@contentful/experiences-visual-editor-react 1.28.3 → 1.29.0-beta.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.js +67 -21
- package/dist/index.js.map +1 -1
- package/dist/renderApp.js +67 -21
- package/dist/renderApp.js.map +1 -1
- package/package.json +4 -4
package/dist/index.js
CHANGED
|
@@ -947,6 +947,9 @@ const BaseComponentTreeNodeSchema$1 = z.object({
|
|
|
947
947
|
const ComponentTreeNodeSchema$1 = BaseComponentTreeNodeSchema$1.extend({
|
|
948
948
|
children: z.lazy(() => ComponentTreeNodeSchema$1.array()),
|
|
949
949
|
});
|
|
950
|
+
const BindingSourceTypeEnumSchema$1 = z
|
|
951
|
+
.array(z.enum(['entry', 'asset', 'manual', 'experience']))
|
|
952
|
+
.nonempty();
|
|
950
953
|
const ComponentVariableSchema$1 = z.object({
|
|
951
954
|
displayName: z.string().optional(),
|
|
952
955
|
type: DefinitionPropertyTypeSchema$1,
|
|
@@ -955,6 +958,7 @@ const ComponentVariableSchema$1 = z.object({
|
|
|
955
958
|
defaultValue: PrimitiveValueSchema$1.or(ComponentPropertyValueSchema$1).optional(),
|
|
956
959
|
validations: z
|
|
957
960
|
.object({
|
|
961
|
+
bindingSourceType: BindingSourceTypeEnumSchema$1.optional(),
|
|
958
962
|
required: z.boolean().optional(),
|
|
959
963
|
format: z.literal('URL').optional(),
|
|
960
964
|
in: z
|
|
@@ -2716,12 +2720,11 @@ function compareNodes({ currentNode, updatedNode, originalTree, differences = []
|
|
|
2716
2720
|
const nodeRemoved = currentNodeCount > updatedNodeCount;
|
|
2717
2721
|
const nodeAdded = currentNodeCount < updatedNodeCount;
|
|
2718
2722
|
const parentNodeId = updatedNode.data.id;
|
|
2719
|
-
const isRoot = currentNode.data.id === ROOT_ID;
|
|
2720
2723
|
/**
|
|
2721
2724
|
* The data of the current node has changed, we need to update
|
|
2722
2725
|
* this node to reflect the data change. (design, content, unbound values)
|
|
2723
2726
|
*/
|
|
2724
|
-
if (!
|
|
2727
|
+
if (!isEqual(currentNode.data, updatedNode.data)) {
|
|
2725
2728
|
differences.push({
|
|
2726
2729
|
type: TreeAction.UPDATE_NODE,
|
|
2727
2730
|
nodeId: currentNode.data.id,
|
|
@@ -3321,6 +3324,9 @@ const BaseComponentTreeNodeSchema = z.object({
|
|
|
3321
3324
|
const ComponentTreeNodeSchema = BaseComponentTreeNodeSchema.extend({
|
|
3322
3325
|
children: z.lazy(() => ComponentTreeNodeSchema.array()),
|
|
3323
3326
|
});
|
|
3327
|
+
const BindingSourceTypeEnumSchema = z
|
|
3328
|
+
.array(z.enum(['entry', 'asset', 'manual', 'experience']))
|
|
3329
|
+
.nonempty();
|
|
3324
3330
|
const ComponentVariableSchema = z.object({
|
|
3325
3331
|
displayName: z.string().optional(),
|
|
3326
3332
|
type: DefinitionPropertyTypeSchema,
|
|
@@ -3329,6 +3335,7 @@ const ComponentVariableSchema = z.object({
|
|
|
3329
3335
|
defaultValue: PrimitiveValueSchema.or(ComponentPropertyValueSchema).optional(),
|
|
3330
3336
|
validations: z
|
|
3331
3337
|
.object({
|
|
3338
|
+
bindingSourceType: BindingSourceTypeEnumSchema.optional(),
|
|
3332
3339
|
required: z.boolean().optional(),
|
|
3333
3340
|
format: z.literal('URL').optional(),
|
|
3334
3341
|
in: z
|
|
@@ -4623,7 +4630,29 @@ const MissingComponentPlaceholder = ({ blockId }) => {
|
|
|
4623
4630
|
"'"));
|
|
4624
4631
|
};
|
|
4625
4632
|
|
|
4626
|
-
const
|
|
4633
|
+
const CircularDependencyErrorPlaceholder = forwardRef(({ wrappingPatternIds, ...props }, ref) => {
|
|
4634
|
+
const entityStore = useEntityStore((state) => state.entityStore);
|
|
4635
|
+
return (React.createElement("div", { ...props,
|
|
4636
|
+
// Pass through ref to avoid DND errors being logged
|
|
4637
|
+
ref: ref, "data-cf-node-error": "circular-pattern-dependency", style: {
|
|
4638
|
+
border: '1px solid red',
|
|
4639
|
+
background: 'rgba(255, 0, 0, 0.1)',
|
|
4640
|
+
padding: '1rem 1rem 0 1rem',
|
|
4641
|
+
width: '100%',
|
|
4642
|
+
height: '100%',
|
|
4643
|
+
} },
|
|
4644
|
+
"Circular usage of patterns detected:",
|
|
4645
|
+
React.createElement("ul", null, Array.from(wrappingPatternIds).map((patternId) => {
|
|
4646
|
+
const entryLink = { sys: { type: 'Link', linkType: 'Entry', id: patternId } };
|
|
4647
|
+
const entry = entityStore.getEntityFromLink(entryLink);
|
|
4648
|
+
const entryTitle = entry?.fields?.title;
|
|
4649
|
+
const text = entryTitle ? `${entryTitle} (${patternId})` : patternId;
|
|
4650
|
+
return React.createElement("li", { key: patternId }, text);
|
|
4651
|
+
}))));
|
|
4652
|
+
});
|
|
4653
|
+
CircularDependencyErrorPlaceholder.displayName = 'CircularDependencyErrorPlaceholder';
|
|
4654
|
+
|
|
4655
|
+
const useComponent = ({ node, resolveDesignValue, renderDropzone, userIsDragging, wrappingPatternIds, }) => {
|
|
4627
4656
|
const areEntitiesFetched = useEntityStore((state) => state.areEntitiesFetched);
|
|
4628
4657
|
const tree = useTreeStore((state) => state.tree);
|
|
4629
4658
|
const componentRegistration = useMemo(() => {
|
|
@@ -4659,10 +4688,19 @@ const useComponent = ({ node, resolveDesignValue, renderDropzone, userIsDragging
|
|
|
4659
4688
|
requiresDragWrapper,
|
|
4660
4689
|
});
|
|
4661
4690
|
const elementToRender = (props) => {
|
|
4691
|
+
const { dragProps = {} } = props || {};
|
|
4692
|
+
const { children, innerRef, Tag = 'div', ToolTipAndPlaceholder, style, ...rest } = dragProps;
|
|
4693
|
+
const { 'data-cf-node-block-id': dataCfNodeBlockId, 'data-cf-node-block-type': dataCfNodeBlockType, 'data-cf-node-id': dataCfNodeId, } = componentProps;
|
|
4694
|
+
const refCallback = (refNode) => {
|
|
4695
|
+
if (innerRef && refNode)
|
|
4696
|
+
innerRef(refNode);
|
|
4697
|
+
};
|
|
4662
4698
|
if (!componentRegistration) {
|
|
4663
4699
|
return React.createElement(MissingComponentPlaceholder, { blockId: node.data.blockId });
|
|
4664
4700
|
}
|
|
4665
|
-
|
|
4701
|
+
if (node.data.blockId && wrappingPatternIds.has(node.data.blockId)) {
|
|
4702
|
+
return (React.createElement(CircularDependencyErrorPlaceholder, { ref: refCallback, "data-cf-node-id": dataCfNodeId, "data-cf-node-block-id": dataCfNodeBlockId, "data-cf-node-block-type": dataCfNodeBlockType, wrappingPatternIds: wrappingPatternIds }));
|
|
4703
|
+
}
|
|
4666
4704
|
const element = React.createElement(ImportedComponentErrorBoundary, { componentId: node.data.blockId }, React.createElement(componentRegistration.component, {
|
|
4667
4705
|
...componentProps,
|
|
4668
4706
|
dragProps,
|
|
@@ -4670,12 +4708,7 @@ const useComponent = ({ node, resolveDesignValue, renderDropzone, userIsDragging
|
|
|
4670
4708
|
if (!requiresDragWrapper) {
|
|
4671
4709
|
return element;
|
|
4672
4710
|
}
|
|
4673
|
-
|
|
4674
|
-
const { 'data-cf-node-block-id': dataCfNodeBlockId, 'data-cf-node-block-type': dataCfNodeBlockType, 'data-cf-node-id': dataCfNodeId, } = componentProps;
|
|
4675
|
-
return (React.createElement(Tag, { ...rest, style: { ...style, ...wrapperStyles }, ref: (refNode) => {
|
|
4676
|
-
if (innerRef && refNode)
|
|
4677
|
-
innerRef(refNode);
|
|
4678
|
-
}, "data-cf-node-id": dataCfNodeId, "data-cf-node-block-id": dataCfNodeBlockId, "data-cf-node-block-type": dataCfNodeBlockType },
|
|
4711
|
+
return (React.createElement(Tag, { ...rest, style: { ...style, ...wrapperStyles }, ref: refCallback, "data-cf-node-id": dataCfNodeId, "data-cf-node-block-id": dataCfNodeBlockId, "data-cf-node-block-type": dataCfNodeBlockType },
|
|
4679
4712
|
ToolTipAndPlaceholder,
|
|
4680
4713
|
element));
|
|
4681
4714
|
};
|
|
@@ -5126,7 +5159,7 @@ function getStyle$1(style, snapshot) {
|
|
|
5126
5159
|
transitionDuration: `0.001s`,
|
|
5127
5160
|
};
|
|
5128
5161
|
}
|
|
5129
|
-
const EditorBlock = ({ node: rawNode, resolveDesignValue, renderDropzone, index, zoneId, userIsDragging, placeholder, }) => {
|
|
5162
|
+
const EditorBlock = ({ node: rawNode, resolveDesignValue, renderDropzone, index, zoneId, userIsDragging, placeholder, wrappingPatternIds, }) => {
|
|
5130
5163
|
const { slotId } = parseZoneId(zoneId);
|
|
5131
5164
|
const ref = useRef(null);
|
|
5132
5165
|
const setSelectedNodeId = useEditorStore((state) => state.setSelectedNodeId);
|
|
@@ -5136,6 +5169,7 @@ const EditorBlock = ({ node: rawNode, resolveDesignValue, renderDropzone, index,
|
|
|
5136
5169
|
resolveDesignValue,
|
|
5137
5170
|
renderDropzone,
|
|
5138
5171
|
userIsDragging,
|
|
5172
|
+
wrappingPatternIds,
|
|
5139
5173
|
});
|
|
5140
5174
|
const { isSingleColumn, isWrapped } = useSingleColumn(node, resolveDesignValue);
|
|
5141
5175
|
const setDomRect = useDraggedItemStore((state) => state.setDomRect);
|
|
@@ -5272,13 +5306,14 @@ function getStyle(style = {}, snapshot) {
|
|
|
5272
5306
|
transitionDuration: `0.001s`,
|
|
5273
5307
|
};
|
|
5274
5308
|
}
|
|
5275
|
-
const EditorBlockClone = ({ node: rawNode, resolveDesignValue, snapshot, provided, renderDropzone, }) => {
|
|
5309
|
+
const EditorBlockClone = ({ node: rawNode, resolveDesignValue, snapshot, provided, renderDropzone, wrappingPatternIds, }) => {
|
|
5276
5310
|
const userIsDragging = useDraggedItemStore((state) => state.isDraggingOnCanvas);
|
|
5277
5311
|
const { node, elementToRender } = useComponent({
|
|
5278
5312
|
node: rawNode,
|
|
5279
5313
|
resolveDesignValue,
|
|
5280
5314
|
renderDropzone,
|
|
5281
5315
|
userIsDragging,
|
|
5316
|
+
wrappingPatternIds,
|
|
5282
5317
|
});
|
|
5283
5318
|
const isAssemblyBlock = node.type === ASSEMBLY_BLOCK_NODE_TYPE;
|
|
5284
5319
|
return elementToRender({
|
|
@@ -5311,7 +5346,7 @@ const getHtmlComponentProps = (props) => {
|
|
|
5311
5346
|
return {};
|
|
5312
5347
|
};
|
|
5313
5348
|
|
|
5314
|
-
function DropzoneClone({ node, zoneId, resolveDesignValue, WrapperComponent = 'div', renderDropzone, dragProps, ...rest }) {
|
|
5349
|
+
function DropzoneClone({ node, zoneId, resolveDesignValue, WrapperComponent = 'div', renderDropzone, dragProps, wrappingPatternIds, ...rest }) {
|
|
5315
5350
|
const tree = useTreeStore((state) => state.tree);
|
|
5316
5351
|
const content = node?.children || tree.root?.children || [];
|
|
5317
5352
|
const { slotId } = parseZoneId(zoneId);
|
|
@@ -5332,11 +5367,11 @@ function DropzoneClone({ node, zoneId, resolveDesignValue, WrapperComponent = 'd
|
|
|
5332
5367
|
.filter((node) => node.data.slotId === slotId)
|
|
5333
5368
|
.map((item) => {
|
|
5334
5369
|
const componentId = item.data.id;
|
|
5335
|
-
return (React.createElement(EditorBlockClone, { key: componentId, node: item, resolveDesignValue: resolveDesignValue, renderDropzone: renderDropzone }));
|
|
5370
|
+
return (React.createElement(EditorBlockClone, { key: componentId, node: item, resolveDesignValue: resolveDesignValue, renderDropzone: renderDropzone, wrappingPatternIds: wrappingPatternIds }));
|
|
5336
5371
|
})));
|
|
5337
5372
|
}
|
|
5338
5373
|
|
|
5339
|
-
function Dropzone({ node, zoneId, resolveDesignValue, className, WrapperComponent = 'div', dragProps, ...rest }) {
|
|
5374
|
+
function Dropzone({ node, zoneId, resolveDesignValue, className, WrapperComponent = 'div', dragProps, wrappingPatternIds: parentWrappingPatternIds = new Set(), ...rest }) {
|
|
5340
5375
|
const userIsDragging = useDraggedItemStore((state) => state.isDraggingOnCanvas);
|
|
5341
5376
|
const draggedItem = useDraggedItemStore((state) => state.draggedItem);
|
|
5342
5377
|
const isDraggingNewComponent = useDraggedItemStore((state) => Boolean(state.componentId));
|
|
@@ -5358,13 +5393,24 @@ function Dropzone({ node, zoneId, resolveDesignValue, className, WrapperComponen
|
|
|
5358
5393
|
const isRootAssembly = node?.type === ASSEMBLY_NODE_TYPE;
|
|
5359
5394
|
const htmlDraggableProps = getHtmlDragProps(dragProps);
|
|
5360
5395
|
const htmlProps = getHtmlComponentProps(rest);
|
|
5396
|
+
const wrappingPatternIds = useMemo(() => {
|
|
5397
|
+
// On the top level, the node is not defined. If the root blockId is not the default string,
|
|
5398
|
+
// we assume that it is the entry ID of the experience/ pattern to properly detect circular dependencies
|
|
5399
|
+
if (!node && tree.root.data.blockId && tree.root.data.blockId !== ROOT_ID) {
|
|
5400
|
+
return new Set([tree.root.data.blockId, ...parentWrappingPatternIds]);
|
|
5401
|
+
}
|
|
5402
|
+
if (isRootAssembly && node?.data.blockId) {
|
|
5403
|
+
return new Set([node.data.blockId, ...parentWrappingPatternIds]);
|
|
5404
|
+
}
|
|
5405
|
+
return parentWrappingPatternIds;
|
|
5406
|
+
}, [isRootAssembly, node, parentWrappingPatternIds, tree.root.data.blockId]);
|
|
5361
5407
|
// To avoid a circular dependency, we create the recursive rendering function here and trickle it down
|
|
5362
5408
|
const renderDropzone = useCallback((node, props) => {
|
|
5363
|
-
return (React.createElement(Dropzone, { zoneId: node.data.id, node: node, resolveDesignValue: resolveDesignValue, ...props }));
|
|
5364
|
-
}, [resolveDesignValue]);
|
|
5409
|
+
return (React.createElement(Dropzone, { zoneId: node.data.id, node: node, resolveDesignValue: resolveDesignValue, wrappingPatternIds: wrappingPatternIds, ...props }));
|
|
5410
|
+
}, [wrappingPatternIds, resolveDesignValue]);
|
|
5365
5411
|
const renderClonedDropzone = useCallback((node, props) => {
|
|
5366
|
-
return (React.createElement(DropzoneClone, { zoneId: node.data.id, node: node, resolveDesignValue: resolveDesignValue, renderDropzone: renderClonedDropzone, ...props }));
|
|
5367
|
-
}, [resolveDesignValue]);
|
|
5412
|
+
return (React.createElement(DropzoneClone, { zoneId: node.data.id, node: node, resolveDesignValue: resolveDesignValue, renderDropzone: renderClonedDropzone, wrappingPatternIds: wrappingPatternIds, ...props }));
|
|
5413
|
+
}, [resolveDesignValue, wrappingPatternIds]);
|
|
5368
5414
|
const isDropzoneEnabled = useMemo(() => {
|
|
5369
5415
|
const isColumns = node?.data.blockId === CONTENTFUL_COMPONENTS$1.columns.id;
|
|
5370
5416
|
const isDraggingSingleColumn = draggedNode?.data.blockId === CONTENTFUL_COMPONENTS$1.singleColumn.id;
|
|
@@ -5398,7 +5444,7 @@ function Dropzone({ node, zoneId, resolveDesignValue, className, WrapperComponen
|
|
|
5398
5444
|
if (!resolveDesignValue) {
|
|
5399
5445
|
return null;
|
|
5400
5446
|
}
|
|
5401
|
-
return (React.createElement(Droppable, { droppableId: zoneId, direction: direction, isDropDisabled: !isDropzoneEnabled, renderClone: (provided, snapshot, rubic) => (React.createElement(EditorBlockClone, { node: content[rubic.source.index], resolveDesignValue: resolveDesignValue, provided: provided, snapshot: snapshot, renderDropzone: renderClonedDropzone })) }, (provided, snapshot) => {
|
|
5447
|
+
return (React.createElement(Droppable, { droppableId: zoneId, direction: direction, isDropDisabled: !isDropzoneEnabled, renderClone: (provided, snapshot, rubic) => (React.createElement(EditorBlockClone, { node: content[rubic.source.index], resolveDesignValue: resolveDesignValue, provided: provided, snapshot: snapshot, renderDropzone: renderClonedDropzone, wrappingPatternIds: wrappingPatternIds })) }, (provided, snapshot) => {
|
|
5402
5448
|
return (React.createElement(WrapperComponent, { ...(provided || { droppableProps: {} }).droppableProps, ...htmlDraggableProps, ...htmlProps, ref: (refNode) => {
|
|
5403
5449
|
if (dragProps?.innerRef) {
|
|
5404
5450
|
dragProps.innerRef(refNode);
|
|
@@ -5421,7 +5467,7 @@ function Dropzone({ node, zoneId, resolveDesignValue, className, WrapperComponen
|
|
|
5421
5467
|
elementIndex: i,
|
|
5422
5468
|
dropzoneElementId: zoneId,
|
|
5423
5469
|
direction,
|
|
5424
|
-
}, index: i, zoneId: zoneId, key: item.data.id, userIsDragging: userIsDragging, draggingNewComponent: isDraggingNewComponent, node: item, resolveDesignValue: resolveDesignValue, renderDropzone: renderDropzone })))),
|
|
5470
|
+
}, index: i, zoneId: zoneId, key: item.data.id, userIsDragging: userIsDragging, draggingNewComponent: isDraggingNewComponent, node: item, resolveDesignValue: resolveDesignValue, renderDropzone: renderDropzone, wrappingPatternIds: wrappingPatternIds })))),
|
|
5425
5471
|
provided?.placeholder,
|
|
5426
5472
|
dragProps?.ToolTipAndPlaceholder));
|
|
5427
5473
|
}));
|