sitesmith: pre-create section-inner/bg-section-inner/form-inner linkedNodes
The Invariant 'component type (undefined) does not exist in the resolver'
was Craft.js's toNodeTree choking on the linkedNode that <Element id="X">
auto-creates at render time inside Section / BackgroundSection /
FormContainer. The auto-created node stores its type as the Container
React component class itself, not as {resolvedName:'Container'}, so the
later type.resolvedName lookup returns undefined.
For each shell, treeToState (and apply-ai-response's buildNodeTree) now
synthesizes the linkedNode container up-front with a proper serialized
type, moves the AI's direct children into it, and reparents them. This
matches the canonical shape Craft.js writes when the user manually builds
a site, so Craft.js never has to materialize the linkedNode itself.
This commit is contained in:
@@ -10,6 +10,12 @@ import { SitesmithResponse, SerializedTreeNode } from '../types/sitesmith';
|
||||
* canvas but its render ignores `data.nodes`. */
|
||||
const CANVAS_TYPES = new Set(['Container']);
|
||||
|
||||
const SHELL_INNER: Record<string, string> = {
|
||||
Section: 'section-inner',
|
||||
BackgroundSection: 'bg-section-inner',
|
||||
FormContainer: 'form-inner',
|
||||
};
|
||||
|
||||
/**
|
||||
* Flatten a SerializedTreeNode tree into a Craft.js node map ready for
|
||||
* `actions.deserialize()`.
|
||||
@@ -100,6 +106,35 @@ function buildNodeTree(query: any, tree: SerializedTreeNode): NodeTree {
|
||||
craftNodes[id].data.props.columns = colCount;
|
||||
}
|
||||
}
|
||||
// Section/BackgroundSection/FormContainer wrap their content in a single
|
||||
// <Element id="<key>" is={Container} canvas>. Pre-create the linkedNode
|
||||
// so Craft.js doesn't auto-create one with a malformed type field.
|
||||
const innerKey = SHELL_INNER[node.type.resolvedName];
|
||||
if (innerKey && craftNodes[id].data.nodes.length > 0) {
|
||||
const innerId = `${id}__${innerKey}`;
|
||||
const childIds: string[] = [...craftNodes[id].data.nodes];
|
||||
craftNodes[innerId] = {
|
||||
id: innerId,
|
||||
data: {
|
||||
type: { resolvedName: 'Container' },
|
||||
props: { tag: 'div' },
|
||||
displayName: 'Container',
|
||||
isCanvas: true,
|
||||
parent: id,
|
||||
nodes: childIds,
|
||||
linkedNodes: {},
|
||||
hidden: false,
|
||||
custom: {},
|
||||
},
|
||||
events: { selected: false, hovered: false, dragged: false },
|
||||
rules: { canDrag: () => true, canMoveIn: () => true, canMoveOut: () => true, canDrop: () => true },
|
||||
};
|
||||
for (const cid of childIds) {
|
||||
if (craftNodes[cid]) craftNodes[cid].data.parent = innerId;
|
||||
}
|
||||
craftNodes[id].data.nodes = [];
|
||||
craftNodes[id].data.linkedNodes = { [innerKey]: innerId };
|
||||
}
|
||||
return id;
|
||||
};
|
||||
|
||||
|
||||
Reference in New Issue
Block a user