@contentful/experiences-visual-editor-react 3.3.0-dev-20250820T1056-fd92026.0 → 3.3.1-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 +72 -21
- package/dist/index.js.map +1 -1
- package/dist/renderApp.js +101 -24
- package/dist/renderApp.js.map +1 -1
- package/package.json +4 -4
package/dist/index.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import styleInject from 'style-inject';
|
|
2
2
|
import React, { useState, useEffect, useCallback, forwardRef, useMemo, useLayoutEffect, useRef } from 'react';
|
|
3
3
|
import { z } from 'zod';
|
|
4
|
-
import { omit, isArray, isEqual, get as get$2, debounce } from 'lodash-es';
|
|
4
|
+
import { cloneDeep, omit, isArray, isEqual, get as get$2, debounce } from 'lodash-es';
|
|
5
5
|
import md5 from 'md5';
|
|
6
6
|
import { BLOCKS } from '@contentful/rich-text-types';
|
|
7
7
|
import { create, useStore } from 'zustand';
|
|
@@ -1011,6 +1011,18 @@ var CodeNames$1;
|
|
|
1011
1011
|
CodeNames["Custom"] = "custom";
|
|
1012
1012
|
})(CodeNames$1 || (CodeNames$1 = {}));
|
|
1013
1013
|
|
|
1014
|
+
const sdkOptionsRegistry = {};
|
|
1015
|
+
/**
|
|
1016
|
+
* Used inside defineComponents to forward registry arguments to this registry
|
|
1017
|
+
* of SDK options.
|
|
1018
|
+
*/
|
|
1019
|
+
const defineSdkOptions = (options) => {
|
|
1020
|
+
Object.assign(sdkOptionsRegistry, options);
|
|
1021
|
+
};
|
|
1022
|
+
const getSdkOptions = () => {
|
|
1023
|
+
return { ...sdkOptionsRegistry };
|
|
1024
|
+
};
|
|
1025
|
+
|
|
1014
1026
|
const MEDIA_QUERY_REGEXP = /(<|>)(\d{1,})(px|cm|mm|in|pt|pc)$/;
|
|
1015
1027
|
const toCSSMediaQuery = ({ query }) => {
|
|
1016
1028
|
if (query === '*')
|
|
@@ -1595,6 +1607,20 @@ const transformBackgroundImage = (cfBackgroundImageUrl, cfBackgroundImageOptions
|
|
|
1595
1607
|
backgroundSize: matchBackgroundSize(cfBackgroundImageOptions?.scaling),
|
|
1596
1608
|
};
|
|
1597
1609
|
};
|
|
1610
|
+
const transformTextAlign = (value) => {
|
|
1611
|
+
if (!value)
|
|
1612
|
+
return undefined;
|
|
1613
|
+
const sdkOptions = getSdkOptions();
|
|
1614
|
+
// New behavior: translate left/right to start/end
|
|
1615
|
+
// Customer can opt-out by activating this global option toggle
|
|
1616
|
+
if (!sdkOptions.__disableTextAlignmentTransform) {
|
|
1617
|
+
if (value === 'left')
|
|
1618
|
+
return 'start';
|
|
1619
|
+
if (value === 'right')
|
|
1620
|
+
return 'end';
|
|
1621
|
+
}
|
|
1622
|
+
return value;
|
|
1623
|
+
};
|
|
1598
1624
|
|
|
1599
1625
|
const toCSSAttribute = (key) => {
|
|
1600
1626
|
let val = key.replace(/[A-Z]/g, (m) => '-' + m.toLowerCase());
|
|
@@ -1672,7 +1698,7 @@ const buildCfStyles = (values) => {
|
|
|
1672
1698
|
lineHeight: values.cfLineHeight,
|
|
1673
1699
|
letterSpacing: values.cfLetterSpacing,
|
|
1674
1700
|
color: values.cfTextColor,
|
|
1675
|
-
textAlign: values.cfTextAlign,
|
|
1701
|
+
textAlign: transformTextAlign(values.cfTextAlign),
|
|
1676
1702
|
textTransform: values.cfTextTransform,
|
|
1677
1703
|
objectFit: values.cfImageOptions?.objectFit,
|
|
1678
1704
|
objectPosition: values.cfImageOptions?.objectPosition,
|
|
@@ -1805,7 +1831,7 @@ const transformRichText = (entryOrAsset, entityStore, path) => {
|
|
|
1805
1831
|
// resolve any links to assets/entries/hyperlinks
|
|
1806
1832
|
// we need to clone, as we want to keep the original Entity in the EntityStore intact,
|
|
1807
1833
|
// and resolveLinks() is mutating the node object.
|
|
1808
|
-
const richTextDocument =
|
|
1834
|
+
const richTextDocument = cloneDeep(value);
|
|
1809
1835
|
resolveLinks(richTextDocument, entityStore);
|
|
1810
1836
|
return richTextDocument;
|
|
1811
1837
|
}
|
|
@@ -2151,6 +2177,27 @@ const tryParseMessage = (event) => {
|
|
|
2151
2177
|
return eventData;
|
|
2152
2178
|
};
|
|
2153
2179
|
|
|
2180
|
+
const splitDirectAndSlotChildren = (allChildNodes, componentDefinition) => {
|
|
2181
|
+
// Bridge difference between editor and delivery mode
|
|
2182
|
+
const getSlotId = (child) => {
|
|
2183
|
+
if ('data' in child)
|
|
2184
|
+
return child.data.slotId;
|
|
2185
|
+
return child.slotId;
|
|
2186
|
+
};
|
|
2187
|
+
const slotNodesMap = {};
|
|
2188
|
+
for (const slotId in componentDefinition.slots) {
|
|
2189
|
+
// We only allow one component per slot (container). This is just safer to not render components twice or not at all
|
|
2190
|
+
const nodes = allChildNodes.filter((child) => getSlotId(child) === slotId);
|
|
2191
|
+
slotNodesMap[slotId] = nodes.length ? nodes : null;
|
|
2192
|
+
}
|
|
2193
|
+
const directChildNodes = allChildNodes.filter((child) => getSlotId(child) === undefined);
|
|
2194
|
+
if (!componentDefinition.children || !directChildNodes.length) {
|
|
2195
|
+
// If there are no children allowed in the component or no children added, render as undefined
|
|
2196
|
+
return { slotNodesMap, directChildNodes: undefined };
|
|
2197
|
+
}
|
|
2198
|
+
return { slotNodesMap, directChildNodes };
|
|
2199
|
+
};
|
|
2200
|
+
|
|
2154
2201
|
const sendMessage = (eventType, data) => {
|
|
2155
2202
|
if (typeof window === 'undefined') {
|
|
2156
2203
|
return;
|
|
@@ -2282,11 +2329,11 @@ let EntityStoreBase$1 = class EntityStoreBase {
|
|
|
2282
2329
|
addEntity(entity) {
|
|
2283
2330
|
if (isAsset$1(entity)) {
|
|
2284
2331
|
// cloned and frozen
|
|
2285
|
-
this.assetMap.set(entity.sys.id, deepFreeze$1(
|
|
2332
|
+
this.assetMap.set(entity.sys.id, deepFreeze$1(cloneDeep(entity)));
|
|
2286
2333
|
}
|
|
2287
2334
|
else if (isEntry$1(entity)) {
|
|
2288
2335
|
// cloned and frozen
|
|
2289
|
-
this.entryMap.set(entity.sys.id, deepFreeze$1(
|
|
2336
|
+
this.entryMap.set(entity.sys.id, deepFreeze$1(cloneDeep(entity)));
|
|
2290
2337
|
}
|
|
2291
2338
|
else {
|
|
2292
2339
|
throw new Error(`Attempted to add an entity to the store that is neither Asset nor Entry: '${JSON.stringify(entity)}'`);
|
|
@@ -3219,12 +3266,14 @@ const useEditorStore = create((set, get) => ({
|
|
|
3219
3266
|
}
|
|
3220
3267
|
set({ locale });
|
|
3221
3268
|
},
|
|
3222
|
-
initializeEditor({ componentRegistry: initialRegistry, designTokens, initialLocale }) {
|
|
3269
|
+
initializeEditor({ componentRegistry: initialRegistry, designTokens, sdkOptions, initialLocale, }) {
|
|
3223
3270
|
initialRegistry.forEach((registration) => {
|
|
3224
3271
|
componentRegistry.set(registration.definition.id, registration);
|
|
3225
3272
|
});
|
|
3226
3273
|
// Re-register the design tokens with the Visual Editor's instance of the experiences-core package
|
|
3227
3274
|
defineDesignTokens(designTokens);
|
|
3275
|
+
// Same copy over from one instance to the other is necessary for the sdk options
|
|
3276
|
+
defineSdkOptions(sdkOptions);
|
|
3228
3277
|
set({ locale: initialLocale });
|
|
3229
3278
|
},
|
|
3230
3279
|
}));
|
|
@@ -4093,11 +4142,11 @@ class EntityStoreBase {
|
|
|
4093
4142
|
addEntity(entity) {
|
|
4094
4143
|
if (isAsset(entity)) {
|
|
4095
4144
|
// cloned and frozen
|
|
4096
|
-
this.assetMap.set(entity.sys.id, deepFreeze(
|
|
4145
|
+
this.assetMap.set(entity.sys.id, deepFreeze(cloneDeep(entity)));
|
|
4097
4146
|
}
|
|
4098
4147
|
else if (isEntry(entity)) {
|
|
4099
4148
|
// cloned and frozen
|
|
4100
|
-
this.entryMap.set(entity.sys.id, deepFreeze(
|
|
4149
|
+
this.entryMap.set(entity.sys.id, deepFreeze(cloneDeep(entity)));
|
|
4101
4150
|
}
|
|
4102
4151
|
else {
|
|
4103
4152
|
throw new Error(`Attempted to add an entity to the store that is neither Asset nor Entry: '${JSON.stringify(entity)}'`);
|
|
@@ -4905,18 +4954,19 @@ function EditorBlock({ node, resolveDesignValue, wrappingPatternIds: parentWrapp
|
|
|
4905
4954
|
if (isRootAssemblyNode && node.data.blockId && parentWrappingPatternIds.has(node.data.blockId)) {
|
|
4906
4955
|
return React.createElement(CircularDependencyErrorPlaceholder, { wrappingPatternIds: wrappingPatternIds });
|
|
4907
4956
|
}
|
|
4908
|
-
const
|
|
4909
|
-
|
|
4910
|
-
|
|
4911
|
-
|
|
4912
|
-
|
|
4913
|
-
|
|
4914
|
-
|
|
4915
|
-
|
|
4916
|
-
|
|
4917
|
-
|
|
4918
|
-
|
|
4919
|
-
|
|
4957
|
+
const { slotNodesMap, directChildNodes } = splitDirectAndSlotChildren(node.children, componentRegistration.definition);
|
|
4958
|
+
const renderChildNode = (childNode) => (React.createElement(EditorBlock, { key: childNode.data.id, node: childNode, resolveDesignValue: resolveDesignValue, wrappingPatternIds: wrappingPatternIds, entityStore: entityStore, areEntitiesFetched: areEntitiesFetched }));
|
|
4959
|
+
const renderedSlotNodesMap = Object.entries(slotNodesMap).reduce((acc, [slotId, nodes]) => {
|
|
4960
|
+
if (nodes?.length) {
|
|
4961
|
+
acc[slotId] = React.createElement(React.Fragment, null, nodes.map((slotChildNode) => renderChildNode(slotChildNode)));
|
|
4962
|
+
}
|
|
4963
|
+
else {
|
|
4964
|
+
acc[slotId] = React.createElement("div", { className: styles$1.emptySlot });
|
|
4965
|
+
}
|
|
4966
|
+
return acc;
|
|
4967
|
+
}, {});
|
|
4968
|
+
const renderedChildren = directChildNodes?.map((childNode) => renderChildNode(childNode));
|
|
4969
|
+
return (React.createElement(RegistrationComponent, { node: node, resolveDesignValue: resolveDesignValue, componentRegistration: componentRegistration, slotNodes: renderedSlotNodesMap, entityStore: entityStore, areEntitiesFetched: areEntitiesFetched }, renderedChildren));
|
|
4920
4970
|
}
|
|
4921
4971
|
const RegistrationComponent = ({ node, resolveDesignValue, componentRegistration, slotNodes, children, entityStore, areEntitiesFetched, }) => {
|
|
4922
4972
|
const { componentProps } = useComponentProps({
|
|
@@ -5149,11 +5199,12 @@ const useInitializeEditor = (inMemoryEntitiesStore) => {
|
|
|
5149
5199
|
const onVisualEditorInitialize = (event) => {
|
|
5150
5200
|
if (!event.detail)
|
|
5151
5201
|
return;
|
|
5152
|
-
const { componentRegistry, designTokens, locale: initialLocale, entities } = event.detail;
|
|
5202
|
+
const { componentRegistry, designTokens, sdkOptions, locale: initialLocale, entities, } = event.detail;
|
|
5153
5203
|
initializeEditor({
|
|
5154
5204
|
initialLocale,
|
|
5155
5205
|
componentRegistry,
|
|
5156
5206
|
designTokens,
|
|
5207
|
+
sdkOptions,
|
|
5157
5208
|
});
|
|
5158
5209
|
// if entities is set to [], then everything will still work as EntityStore will
|
|
5159
5210
|
// request entities on demand via ▲REQUEST_ENTITY
|