@contentful/experiences-visual-editor-react 1.14.0 → 1.15.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 +70 -20
- package/dist/index.js.map +1 -1
- package/dist/renderApp.js +70 -20
- package/dist/renderApp.js.map +1 -1
- package/package.json +4 -4
package/dist/index.js
CHANGED
|
@@ -83,13 +83,15 @@ var PostMessageMethods$2;
|
|
|
83
83
|
})(PostMessageMethods$2 || (PostMessageMethods$2 = {}));
|
|
84
84
|
const SUPPORTED_IMAGE_FORMATS = ['jpg', 'png', 'webp', 'gif', 'avif'];
|
|
85
85
|
|
|
86
|
-
const
|
|
86
|
+
const structureComponentIds = new Set([
|
|
87
87
|
CONTENTFUL_COMPONENTS$1.section.id,
|
|
88
88
|
CONTENTFUL_COMPONENTS$1.columns.id,
|
|
89
89
|
CONTENTFUL_COMPONENTS$1.container.id,
|
|
90
90
|
CONTENTFUL_COMPONENTS$1.singleColumn.id,
|
|
91
91
|
]);
|
|
92
|
-
const
|
|
92
|
+
const allContentfulComponentIds = new Set(Object.values(CONTENTFUL_COMPONENTS$1).map((component) => component.id));
|
|
93
|
+
const isContentfulStructureComponent = (componentId) => structureComponentIds.has(componentId ?? '');
|
|
94
|
+
const isContentfulComponent = (componentId) => allContentfulComponentIds.has(componentId ?? '');
|
|
93
95
|
const isComponentAllowedOnRoot = (componentId) => isContentfulStructureComponent(componentId) || componentId === CONTENTFUL_COMPONENTS$1.divider.id;
|
|
94
96
|
const isStructureWithRelativeHeight = (componentId, height) => {
|
|
95
97
|
return isContentfulStructureComponent(componentId) && !height?.toString().endsWith('px');
|
|
@@ -197,7 +199,16 @@ const tryParseMessage = (event) => {
|
|
|
197
199
|
return eventData;
|
|
198
200
|
};
|
|
199
201
|
|
|
200
|
-
|
|
202
|
+
const transformVisibility = (value) => {
|
|
203
|
+
if (value === false) {
|
|
204
|
+
return {
|
|
205
|
+
display: 'none',
|
|
206
|
+
};
|
|
207
|
+
}
|
|
208
|
+
// Don't explicitly set anything when visible to not overwrite values like `grid` or `flex`.
|
|
209
|
+
return {};
|
|
210
|
+
};
|
|
211
|
+
// Keep this for backwards compatibility - deleting this would be a breaking change
|
|
201
212
|
// because existing components on a users experience will have the width value as fill
|
|
202
213
|
// rather than 100%
|
|
203
214
|
const transformFill = (value) => (value === 'fill' ? '100%' : value);
|
|
@@ -316,8 +327,9 @@ const buildStyleTag = ({ styles, nodeId }) => {
|
|
|
316
327
|
const styleRule = `.${className}{ ${stylesStr} }`;
|
|
317
328
|
return [className, styleRule];
|
|
318
329
|
};
|
|
319
|
-
const buildCfStyles = ({ cfHorizontalAlignment, cfVerticalAlignment, cfFlexDirection, cfFlexWrap, cfMargin, cfPadding, cfBackgroundColor, cfWidth, cfHeight, cfMaxWidth, cfBorder, cfBorderRadius, cfGap, cfBackgroundImageUrl, cfBackgroundImageOptions, cfFontSize, cfFontWeight, cfImageOptions, cfLineHeight, cfLetterSpacing, cfTextColor, cfTextAlign, cfTextTransform, cfTextBold, cfTextItalic, cfTextUnderline, cfColumnSpan, }) => {
|
|
330
|
+
const buildCfStyles = ({ cfHorizontalAlignment, cfVerticalAlignment, cfFlexDirection, cfFlexWrap, cfMargin, cfPadding, cfBackgroundColor, cfWidth, cfHeight, cfMaxWidth, cfBorder, cfBorderRadius, cfGap, cfBackgroundImageUrl, cfBackgroundImageOptions, cfFontSize, cfFontWeight, cfImageOptions, cfLineHeight, cfLetterSpacing, cfTextColor, cfTextAlign, cfTextTransform, cfTextBold, cfTextItalic, cfTextUnderline, cfColumnSpan, cfVisibility, }) => {
|
|
320
331
|
return {
|
|
332
|
+
...transformVisibility(cfVisibility),
|
|
321
333
|
margin: cfMargin,
|
|
322
334
|
padding: cfPadding,
|
|
323
335
|
backgroundColor: cfBackgroundColor,
|
|
@@ -1423,9 +1435,12 @@ const builtInStylesWithDesignTokens = [
|
|
|
1423
1435
|
'cfTextColor',
|
|
1424
1436
|
'cfMaxWidth',
|
|
1425
1437
|
];
|
|
1426
|
-
const
|
|
1438
|
+
const isValidBreakpointValue = (value) => {
|
|
1439
|
+
return value !== undefined && value !== null && value !== '';
|
|
1440
|
+
};
|
|
1441
|
+
const getValueForBreakpoint = (valuesByBreakpoint, breakpoints, activeBreakpointIndex, variableName, resolveDesignTokens = true) => {
|
|
1427
1442
|
const eventuallyResolveDesignTokens = (value) => {
|
|
1428
|
-
// For some built-in design
|
|
1443
|
+
// For some built-in design properties, we support design tokens
|
|
1429
1444
|
if (builtInStylesWithDesignTokens.includes(variableName)) {
|
|
1430
1445
|
return getDesignTokenRegistration(value, variableName);
|
|
1431
1446
|
}
|
|
@@ -1436,22 +1451,29 @@ const getValueForBreakpoint = (valuesByBreakpoint, breakpoints, activeBreakpoint
|
|
|
1436
1451
|
// Assume that the values are sorted by media query to apply the cascading CSS logic
|
|
1437
1452
|
for (let index = activeBreakpointIndex; index >= 0; index--) {
|
|
1438
1453
|
const breakpointId = breakpoints[index]?.id;
|
|
1439
|
-
if (valuesByBreakpoint[breakpointId]) {
|
|
1454
|
+
if (isValidBreakpointValue(valuesByBreakpoint[breakpointId])) {
|
|
1440
1455
|
// If the value is defined, we use it and stop the breakpoints cascade
|
|
1441
|
-
|
|
1456
|
+
if (resolveDesignTokens) {
|
|
1457
|
+
return eventuallyResolveDesignTokens(valuesByBreakpoint[breakpointId]);
|
|
1458
|
+
}
|
|
1459
|
+
return valuesByBreakpoint[breakpointId];
|
|
1442
1460
|
}
|
|
1443
1461
|
}
|
|
1444
1462
|
// If no breakpoint matched, we search and apply the fallback breakpoint
|
|
1445
1463
|
const fallbackBreakpointIndex = getFallbackBreakpointIndex(breakpoints);
|
|
1446
1464
|
const fallbackBreakpointId = breakpoints[fallbackBreakpointIndex]?.id;
|
|
1447
|
-
if (valuesByBreakpoint[fallbackBreakpointId]) {
|
|
1448
|
-
|
|
1465
|
+
if (isValidBreakpointValue(valuesByBreakpoint[fallbackBreakpointId])) {
|
|
1466
|
+
if (resolveDesignTokens) {
|
|
1467
|
+
return eventuallyResolveDesignTokens(valuesByBreakpoint[fallbackBreakpointId]);
|
|
1468
|
+
}
|
|
1469
|
+
return valuesByBreakpoint[fallbackBreakpointId];
|
|
1449
1470
|
}
|
|
1450
1471
|
}
|
|
1451
1472
|
else {
|
|
1452
1473
|
// Old design properties did not support breakpoints, keep for backward compatibility
|
|
1453
1474
|
return valuesByBreakpoint;
|
|
1454
1475
|
}
|
|
1476
|
+
return undefined;
|
|
1455
1477
|
};
|
|
1456
1478
|
|
|
1457
1479
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
@@ -2250,6 +2272,7 @@ const ASSEMBLY_DEFAULT_CATEGORY = 'Assemblies';
|
|
|
2250
2272
|
const ASSEMBLY_BLOCK_NODE_TYPE = 'assemblyBlock';
|
|
2251
2273
|
const ASSEMBLY_NODE_TYPES = [ASSEMBLY_NODE_TYPE, ASSEMBLY_BLOCK_NODE_TYPE];
|
|
2252
2274
|
const CF_STYLE_ATTRIBUTES = [
|
|
2275
|
+
'cfVisibility',
|
|
2253
2276
|
'cfHorizontalAlignment',
|
|
2254
2277
|
'cfVerticalAlignment',
|
|
2255
2278
|
'cfMargin',
|
|
@@ -3330,9 +3353,9 @@ function useEditorSubscriber() {
|
|
|
3330
3353
|
break;
|
|
3331
3354
|
}
|
|
3332
3355
|
case INCOMING_EVENTS.ComponentDragStarted: {
|
|
3333
|
-
const { id } = eventData.payload;
|
|
3356
|
+
const { id, isAssembly } = eventData.payload;
|
|
3334
3357
|
SimulateDnD$1.setupDrag();
|
|
3335
|
-
setComponentId(id || '');
|
|
3358
|
+
setComponentId(`${id}:${isAssembly}` || '');
|
|
3336
3359
|
setDraggingOnCanvas(true);
|
|
3337
3360
|
sendMessage(OUTGOING_EVENTS.ComponentSelected, {
|
|
3338
3361
|
nodeId: '',
|
|
@@ -3516,26 +3539,37 @@ function useCanvasInteractions() {
|
|
|
3516
3539
|
if (!destination) {
|
|
3517
3540
|
return;
|
|
3518
3541
|
}
|
|
3542
|
+
/**
|
|
3543
|
+
* We only have the draggableId as information about the new component being dropped.
|
|
3544
|
+
* So we need to split it to get the blockId and the isAssembly flag.
|
|
3545
|
+
*/
|
|
3546
|
+
const [blockId, isAssembly] = draggableId.split(':');
|
|
3519
3547
|
const { nodeId: parentId, slotId } = parseZoneId(destination.droppableId);
|
|
3520
3548
|
const droppingOnRoot = parentId === ROOT_ID;
|
|
3521
|
-
const isValidRootComponent =
|
|
3522
|
-
let node = createTreeNode({ blockId:
|
|
3549
|
+
const isValidRootComponent = blockId === CONTENTFUL_COMPONENTS.container.id;
|
|
3550
|
+
let node = createTreeNode({ blockId: blockId, parentId, slotId });
|
|
3523
3551
|
if (droppingOnRoot && !isValidRootComponent) {
|
|
3524
3552
|
const wrappingContainer = createTreeNode({
|
|
3525
3553
|
blockId: CONTENTFUL_COMPONENTS.container.id,
|
|
3526
3554
|
parentId,
|
|
3527
3555
|
});
|
|
3528
3556
|
const childNode = createTreeNode({
|
|
3529
|
-
blockId:
|
|
3557
|
+
blockId: blockId,
|
|
3530
3558
|
parentId: wrappingContainer.data.id,
|
|
3531
3559
|
});
|
|
3532
3560
|
node = wrappingContainer;
|
|
3533
3561
|
node.children = [childNode];
|
|
3534
3562
|
}
|
|
3535
|
-
|
|
3563
|
+
/**
|
|
3564
|
+
* isAssembly comes from a string ID so we need to check if it's 'true' or 'false'
|
|
3565
|
+
* in string format.
|
|
3566
|
+
*/
|
|
3567
|
+
if (isAssembly === 'false') {
|
|
3568
|
+
addChild(destination.index, parentId, node);
|
|
3569
|
+
}
|
|
3536
3570
|
onDrop({
|
|
3537
3571
|
data: tree,
|
|
3538
|
-
componentType:
|
|
3572
|
+
componentType: blockId,
|
|
3539
3573
|
destinationIndex: destination.index,
|
|
3540
3574
|
destinationZoneId: parentId,
|
|
3541
3575
|
slotId,
|
|
@@ -3852,7 +3886,7 @@ const useComponentProps = ({ node, areEntitiesFetched, resolveDesignValue, rende
|
|
|
3852
3886
|
entityStore,
|
|
3853
3887
|
renderDropzone,
|
|
3854
3888
|
]);
|
|
3855
|
-
const cfStyles = buildCfStyles(props);
|
|
3889
|
+
const cfStyles = useMemo(() => buildCfStyles(props), [props]);
|
|
3856
3890
|
const sizeStyles = {
|
|
3857
3891
|
width: cfStyles.width,
|
|
3858
3892
|
maxWidth: cfStyles.maxWidth,
|
|
@@ -4039,9 +4073,25 @@ class ImportedComponentError extends Error {
|
|
|
4039
4073
|
this.name = 'ImportedComponentError';
|
|
4040
4074
|
}
|
|
4041
4075
|
}
|
|
4076
|
+
class ExperienceSDKError extends Error {
|
|
4077
|
+
constructor(message) {
|
|
4078
|
+
super(message);
|
|
4079
|
+
this.name = 'ExperienceSDKError';
|
|
4080
|
+
}
|
|
4081
|
+
}
|
|
4042
4082
|
class ImportedComponentErrorBoundary extends React.Component {
|
|
4043
4083
|
componentDidCatch(error, _errorInfo) {
|
|
4044
|
-
|
|
4084
|
+
if (error.name === 'ImportedComponentError' || error.name === 'ExperienceSDKError') {
|
|
4085
|
+
// This error was already handled by a nested error boundary and should be passed upwards
|
|
4086
|
+
// We have to do this as we wrap every component on every layer with this error boundary and
|
|
4087
|
+
// thus an error deep in the tree bubbles through many layers of error boundaries.
|
|
4088
|
+
throw error;
|
|
4089
|
+
}
|
|
4090
|
+
// Differentiate between custom and SDK-provided components for error tracking
|
|
4091
|
+
const ErrorClass = isContentfulComponent(this.props.componentId)
|
|
4092
|
+
? ExperienceSDKError
|
|
4093
|
+
: ImportedComponentError;
|
|
4094
|
+
const err = new ErrorClass(error.message);
|
|
4045
4095
|
err.stack = error.stack;
|
|
4046
4096
|
throw err;
|
|
4047
4097
|
}
|
|
@@ -4106,7 +4156,7 @@ const useComponent = ({ node: rawNode, resolveDesignValue, renderDropzone, userI
|
|
|
4106
4156
|
const isAssembly = node.type === 'assembly';
|
|
4107
4157
|
const modifiedProps = isStructureComponent || isAssembly ? componentProps : customComponentProps;
|
|
4108
4158
|
const requiresDragWrapper = !isStructureComponent && componentRegistration.options?.wrapComponent === false;
|
|
4109
|
-
const element = React.createElement(ImportedComponentErrorBoundary,
|
|
4159
|
+
const element = React.createElement(ImportedComponentErrorBoundary, { componentId: node.data.blockId }, React.createElement(componentRegistration.component, {
|
|
4110
4160
|
...modifiedProps,
|
|
4111
4161
|
dragProps,
|
|
4112
4162
|
}));
|