@contentful/experiences-visual-editor-react 1.42.3 → 2.0.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.d.ts +3 -2
- package/dist/index.js +736 -189
- package/dist/index.js.map +1 -1
- package/dist/renderApp.js +3593 -3046
- package/dist/renderApp.js.map +1 -1
- package/package.json +4 -4
package/dist/index.js
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
import styleInject from 'style-inject';
|
|
2
2
|
import React, { useEffect, useRef, useState, useCallback, forwardRef, useLayoutEffect, useMemo } from 'react';
|
|
3
3
|
import { z } from 'zod';
|
|
4
|
-
import { omit, isArray, isEqual, get as get$
|
|
4
|
+
import { omit, isArray, isEqual, get as get$2 } from 'lodash-es';
|
|
5
5
|
import md5 from 'md5';
|
|
6
6
|
import { BLOCKS } from '@contentful/rich-text-types';
|
|
7
|
-
import { create } from 'zustand';
|
|
7
|
+
import { create, useStore } from 'zustand';
|
|
8
8
|
import { Droppable, Draggable, DragDropContext } from '@hello-pangea/dnd';
|
|
9
9
|
import { produce } from 'immer';
|
|
10
10
|
import '@contentful/rich-text-react-renderer';
|
|
@@ -126,14 +126,6 @@ const CF_STYLE_ATTRIBUTES = [
|
|
|
126
126
|
'cfTextBold',
|
|
127
127
|
'cfTextItalic',
|
|
128
128
|
'cfTextUnderline',
|
|
129
|
-
// For backwards compatibility
|
|
130
|
-
// we need to keep those in this constant array
|
|
131
|
-
// so that omit() in <VisualEditorBlock> and <CompositionBlock>
|
|
132
|
-
// can filter them out and not pass as props
|
|
133
|
-
'cfBackgroundImageScaling',
|
|
134
|
-
'cfBackgroundImageAlignment',
|
|
135
|
-
'cfBackgroundImageAlignmentVertical',
|
|
136
|
-
'cfBackgroundImageAlignmentHorizontal',
|
|
137
129
|
];
|
|
138
130
|
const EMPTY_CONTAINER_HEIGHT$1 = '80px';
|
|
139
131
|
const DEFAULT_IMAGE_WIDTH = '500px';
|
|
@@ -1105,6 +1097,24 @@ propertyName, resolveDesignTokens = true) => {
|
|
|
1105
1097
|
return valuesByBreakpoint;
|
|
1106
1098
|
}
|
|
1107
1099
|
};
|
|
1100
|
+
/** Overwrites the default value breakpoint by breakpoint. If a breakpoint
|
|
1101
|
+
* is not overwritten, it will fall back to the default. */
|
|
1102
|
+
function mergeDesignValuesByBreakpoint(defaultValue, overwriteValue) {
|
|
1103
|
+
if (!defaultValue || !overwriteValue) {
|
|
1104
|
+
return defaultValue ?? overwriteValue;
|
|
1105
|
+
}
|
|
1106
|
+
const mergedValuesByBreakpoint = { ...defaultValue.valuesByBreakpoint };
|
|
1107
|
+
for (const [breakpointId, value] of Object.entries(overwriteValue.valuesByBreakpoint)) {
|
|
1108
|
+
if (!isValidBreakpointValue(value)) {
|
|
1109
|
+
continue;
|
|
1110
|
+
}
|
|
1111
|
+
mergedValuesByBreakpoint[breakpointId] = value;
|
|
1112
|
+
}
|
|
1113
|
+
return {
|
|
1114
|
+
type: 'DesignValue',
|
|
1115
|
+
valuesByBreakpoint: mergedValuesByBreakpoint,
|
|
1116
|
+
};
|
|
1117
|
+
}
|
|
1108
1118
|
|
|
1109
1119
|
const CF_DEBUG_KEY$1 = 'cf_debug';
|
|
1110
1120
|
/**
|
|
@@ -1226,11 +1236,19 @@ const getElementCoordinates = (element) => {
|
|
|
1226
1236
|
});
|
|
1227
1237
|
};
|
|
1228
1238
|
|
|
1229
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
1230
1239
|
const isLinkToAsset = (variable) => {
|
|
1231
|
-
if (
|
|
1240
|
+
if (variable === null || typeof variable !== 'object')
|
|
1241
|
+
return false;
|
|
1242
|
+
// The `'prop' in` pattern is informing TypeScript of the object shape, no need to cast `as`.
|
|
1243
|
+
if (!('sys' in variable))
|
|
1232
1244
|
return false;
|
|
1233
|
-
if (typeof variable !== 'object')
|
|
1245
|
+
if (variable.sys === null || typeof variable.sys !== 'object')
|
|
1246
|
+
return false;
|
|
1247
|
+
if (!('linkType' in variable.sys))
|
|
1248
|
+
return false;
|
|
1249
|
+
if (!('id' in variable.sys))
|
|
1250
|
+
return false;
|
|
1251
|
+
if (!('type' in variable.sys))
|
|
1234
1252
|
return false;
|
|
1235
1253
|
return (variable.sys?.linkType === 'Asset' &&
|
|
1236
1254
|
typeof variable.sys?.id === 'string' &&
|
|
@@ -1238,20 +1256,20 @@ const isLinkToAsset = (variable) => {
|
|
|
1238
1256
|
variable.sys?.type === 'Link');
|
|
1239
1257
|
};
|
|
1240
1258
|
|
|
1241
|
-
const isLink = (maybeLink) => {
|
|
1259
|
+
const isLink$1 = (maybeLink) => {
|
|
1242
1260
|
if (maybeLink === null)
|
|
1243
1261
|
return false;
|
|
1244
1262
|
if (typeof maybeLink !== 'object')
|
|
1245
1263
|
return false;
|
|
1246
1264
|
const link = maybeLink;
|
|
1247
|
-
return Boolean(link.sys?.id) && link.sys?.type === 'Link';
|
|
1265
|
+
return Boolean(link.sys?.id) && link.sys?.type === 'Link' && Boolean(link.sys?.linkType);
|
|
1248
1266
|
};
|
|
1249
1267
|
|
|
1250
1268
|
/**
|
|
1251
1269
|
* This module encapsulates format of the path to a deep reference.
|
|
1252
1270
|
*/
|
|
1253
|
-
const parseDataSourcePathIntoFieldset = (path) => {
|
|
1254
|
-
const parsedPath = parseDeepPath(path);
|
|
1271
|
+
const parseDataSourcePathIntoFieldset$1 = (path) => {
|
|
1272
|
+
const parsedPath = parseDeepPath$1(path);
|
|
1255
1273
|
if (null === parsedPath) {
|
|
1256
1274
|
throw new Error(`Cannot parse path '${path}' as deep path`);
|
|
1257
1275
|
}
|
|
@@ -1264,7 +1282,7 @@ const parseDataSourcePathIntoFieldset = (path) => {
|
|
|
1264
1282
|
* @returns
|
|
1265
1283
|
*/
|
|
1266
1284
|
const parseDataSourcePathWithL1DeepBindings = (path) => {
|
|
1267
|
-
const parsedPath = parseDeepPath(path);
|
|
1285
|
+
const parsedPath = parseDeepPath$1(path);
|
|
1268
1286
|
if (null === parsedPath) {
|
|
1269
1287
|
throw new Error(`Cannot parse path '${path}' as deep path`);
|
|
1270
1288
|
}
|
|
@@ -1281,14 +1299,14 @@ const parseDataSourcePathWithL1DeepBindings = (path) => {
|
|
|
1281
1299
|
* - /6J8eA60yXwdm5eyUh9fX6/fields/mainStory/~locale
|
|
1282
1300
|
* @returns
|
|
1283
1301
|
*/
|
|
1284
|
-
const isDeepPath = (deepPathCandidate) => {
|
|
1285
|
-
const deepPathParsed = parseDeepPath(deepPathCandidate);
|
|
1302
|
+
const isDeepPath$1 = (deepPathCandidate) => {
|
|
1303
|
+
const deepPathParsed = parseDeepPath$1(deepPathCandidate);
|
|
1286
1304
|
if (!deepPathParsed) {
|
|
1287
1305
|
return false;
|
|
1288
1306
|
}
|
|
1289
1307
|
return deepPathParsed.fields.length > 1;
|
|
1290
1308
|
};
|
|
1291
|
-
const parseDeepPath = (deepPathCandidate) => {
|
|
1309
|
+
const parseDeepPath$1 = (deepPathCandidate) => {
|
|
1292
1310
|
// ALGORITHM:
|
|
1293
1311
|
// We start with deep path in form:
|
|
1294
1312
|
// /uuid123/fields/mainStory/~locale/fields/cover/~locale/fields/title/~locale
|
|
@@ -1314,7 +1332,7 @@ const parseDeepPath = (deepPathCandidate) => {
|
|
|
1314
1332
|
return /^fields\/[^/^~]+\/~locale$/.test(fieldChunk.join('/'));
|
|
1315
1333
|
};
|
|
1316
1334
|
const deepPathSegments = deepPathCandidate.split('/');
|
|
1317
|
-
const chunks = chunkSegments(deepPathSegments, { startNextChunkOnElementEqualTo: 'fields' });
|
|
1335
|
+
const chunks = chunkSegments$1(deepPathSegments, { startNextChunkOnElementEqualTo: 'fields' });
|
|
1318
1336
|
if (chunks.length <= 1) {
|
|
1319
1337
|
return null; // malformed path, even regular paths have at least 2 chunks
|
|
1320
1338
|
}
|
|
@@ -1334,7 +1352,7 @@ const parseDeepPath = (deepPathCandidate) => {
|
|
|
1334
1352
|
fields: fieldChunks.map((fieldChunk) => fieldChunk[1]), // pick only fieldName eg. from ['fields','mainStory', '~locale'] we pick `mainStory`
|
|
1335
1353
|
};
|
|
1336
1354
|
};
|
|
1337
|
-
const chunkSegments = (segments, { startNextChunkOnElementEqualTo }) => {
|
|
1355
|
+
const chunkSegments$1 = (segments, { startNextChunkOnElementEqualTo }) => {
|
|
1338
1356
|
const chunks = [];
|
|
1339
1357
|
let currentChunk = [];
|
|
1340
1358
|
const isSegmentBeginningOfChunk = (segment) => segment === startNextChunkOnElementEqualTo;
|
|
@@ -1435,11 +1453,6 @@ const transformVisibility = (value) => {
|
|
|
1435
1453
|
// Don't explicitly set anything when visible to not overwrite values like `grid` or `flex`.
|
|
1436
1454
|
return {};
|
|
1437
1455
|
};
|
|
1438
|
-
// TODO: Remove in next major version v2 since the change is 17 months old
|
|
1439
|
-
// Keep this for backwards compatibility - deleting this would be a breaking change
|
|
1440
|
-
// because existing components on a users experience will have the width value as fill
|
|
1441
|
-
// rather than 100%
|
|
1442
|
-
const transformFill = (value) => (value === 'fill' ? '100%' : value);
|
|
1443
1456
|
const transformGridColumn = (span) => {
|
|
1444
1457
|
if (!span) {
|
|
1445
1458
|
return {};
|
|
@@ -1484,34 +1497,6 @@ const transformBackgroundImage = (cfBackgroundImageUrl, cfBackgroundImageOptions
|
|
|
1484
1497
|
return;
|
|
1485
1498
|
}
|
|
1486
1499
|
let [horizontalAlignment, verticalAlignment] = alignment.trim().split(/\s+/, 2);
|
|
1487
|
-
// Special case for handling single values
|
|
1488
|
-
// for backwards compatibility with single values 'right','left', 'center', 'top','bottom'
|
|
1489
|
-
if (horizontalAlignment && !verticalAlignment) {
|
|
1490
|
-
const singleValue = horizontalAlignment;
|
|
1491
|
-
switch (singleValue) {
|
|
1492
|
-
case 'left':
|
|
1493
|
-
horizontalAlignment = 'left';
|
|
1494
|
-
verticalAlignment = 'center';
|
|
1495
|
-
break;
|
|
1496
|
-
case 'right':
|
|
1497
|
-
horizontalAlignment = 'right';
|
|
1498
|
-
verticalAlignment = 'center';
|
|
1499
|
-
break;
|
|
1500
|
-
case 'center':
|
|
1501
|
-
horizontalAlignment = 'center';
|
|
1502
|
-
verticalAlignment = 'center';
|
|
1503
|
-
break;
|
|
1504
|
-
case 'top':
|
|
1505
|
-
horizontalAlignment = 'center';
|
|
1506
|
-
verticalAlignment = 'top';
|
|
1507
|
-
break;
|
|
1508
|
-
case 'bottom':
|
|
1509
|
-
horizontalAlignment = 'center';
|
|
1510
|
-
verticalAlignment = 'bottom';
|
|
1511
|
-
break;
|
|
1512
|
-
// just fall down to the normal validation logic for horiz and vert
|
|
1513
|
-
}
|
|
1514
|
-
}
|
|
1515
1500
|
const isHorizontalValid = ['left', 'right', 'center'].includes(horizontalAlignment);
|
|
1516
1501
|
const isVerticalValid = ['top', 'bottom', 'center'].includes(verticalAlignment);
|
|
1517
1502
|
horizontalAlignment = isHorizontalValid ? horizontalAlignment : 'left';
|
|
@@ -1596,8 +1581,8 @@ const buildCfStyles = (values) => {
|
|
|
1596
1581
|
margin: values.cfMargin,
|
|
1597
1582
|
padding: values.cfPadding,
|
|
1598
1583
|
backgroundColor: values.cfBackgroundColor,
|
|
1599
|
-
width:
|
|
1600
|
-
height:
|
|
1584
|
+
width: values.cfWidth || values.cfImageOptions?.width,
|
|
1585
|
+
height: values.cfHeight || values.cfImageOptions?.height,
|
|
1601
1586
|
maxWidth: values.cfMaxWidth,
|
|
1602
1587
|
...transformGridColumn(values.cfColumnSpan),
|
|
1603
1588
|
...transformBorderStyle(values.cfBorder),
|
|
@@ -1703,13 +1688,13 @@ const getOptimizedBackgroundImageAsset = (file, widthStyle, quality = '100%', fo
|
|
|
1703
1688
|
};
|
|
1704
1689
|
|
|
1705
1690
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
1706
|
-
function get(obj, path) {
|
|
1691
|
+
function get$1(obj, path) {
|
|
1707
1692
|
if (!path.length) {
|
|
1708
1693
|
return obj;
|
|
1709
1694
|
}
|
|
1710
1695
|
try {
|
|
1711
1696
|
const [currentPath, ...nextPath] = path;
|
|
1712
|
-
return get(obj[currentPath], nextPath);
|
|
1697
|
+
return get$1(obj[currentPath], nextPath);
|
|
1713
1698
|
}
|
|
1714
1699
|
catch (err) {
|
|
1715
1700
|
return undefined;
|
|
@@ -1717,7 +1702,7 @@ function get(obj, path) {
|
|
|
1717
1702
|
}
|
|
1718
1703
|
|
|
1719
1704
|
const getBoundValue = (entryOrAsset, path) => {
|
|
1720
|
-
const value = get(entryOrAsset, path.split('/').slice(2, -1));
|
|
1705
|
+
const value = get$1(entryOrAsset, path.split('/').slice(2, -1));
|
|
1721
1706
|
return value && typeof value == 'object' && value.url
|
|
1722
1707
|
? value.url
|
|
1723
1708
|
: value;
|
|
@@ -1747,7 +1732,9 @@ const transformRichText = (entryOrAsset, entityStore, path) => {
|
|
|
1747
1732
|
}
|
|
1748
1733
|
if (typeof value === 'object' && value.nodeType === BLOCKS.DOCUMENT) {
|
|
1749
1734
|
// resolve any links to assets/entries/hyperlinks
|
|
1750
|
-
|
|
1735
|
+
// we need to clone, as we want to keep the original Entity in the EntityStore intact,
|
|
1736
|
+
// and resolveLinks() is mutating the node object.
|
|
1737
|
+
const richTextDocument = structuredClone(value);
|
|
1751
1738
|
resolveLinks(richTextDocument, entityStore);
|
|
1752
1739
|
return richTextDocument;
|
|
1753
1740
|
}
|
|
@@ -1802,7 +1789,7 @@ const transformMedia = (asset, variables, resolveDesignValue, variableName, path
|
|
|
1802
1789
|
let value;
|
|
1803
1790
|
// If it is not a deep path and not pointing to the file of the asset,
|
|
1804
1791
|
// it is just pointing to a normal field and therefore we just resolve the value as normal field
|
|
1805
|
-
if (!isDeepPath(path) && !lastPathNamedSegmentEq(path, 'file')) {
|
|
1792
|
+
if (!isDeepPath$1(path) && !lastPathNamedSegmentEq(path, 'file')) {
|
|
1806
1793
|
return getBoundValue(asset, path);
|
|
1807
1794
|
}
|
|
1808
1795
|
//TODO: this will be better served by injectable type transformers instead of if statement
|
|
@@ -1860,104 +1847,97 @@ const transformMedia = (asset, variables, resolveDesignValue, variableName, path
|
|
|
1860
1847
|
}
|
|
1861
1848
|
return asset.fields.file?.url;
|
|
1862
1849
|
};
|
|
1863
|
-
|
|
1864
|
-
const isAsset = (value) => {
|
|
1850
|
+
const isEntry$1 = (value) => {
|
|
1865
1851
|
return (null !== value &&
|
|
1866
1852
|
typeof value === 'object' &&
|
|
1867
1853
|
'sys' in value &&
|
|
1868
|
-
value.sys?.type === '
|
|
1854
|
+
value.sys?.type === 'Entry');
|
|
1869
1855
|
};
|
|
1870
|
-
const
|
|
1856
|
+
const isAsset$1 = (value) => {
|
|
1871
1857
|
return (null !== value &&
|
|
1872
1858
|
typeof value === 'object' &&
|
|
1873
1859
|
'sys' in value &&
|
|
1874
|
-
value.sys?.type === '
|
|
1860
|
+
value.sys?.type === 'Asset');
|
|
1875
1861
|
};
|
|
1876
1862
|
|
|
1877
1863
|
function getResolvedEntryFromLink(entryOrAsset, path, entityStore) {
|
|
1878
|
-
if (isAsset(entryOrAsset)) {
|
|
1864
|
+
if (isAsset$1(entryOrAsset)) {
|
|
1879
1865
|
return entryOrAsset;
|
|
1880
1866
|
}
|
|
1881
|
-
else if (!isEntry(entryOrAsset)) {
|
|
1867
|
+
else if (!isEntry$1(entryOrAsset)) {
|
|
1882
1868
|
throw new Error(`Expected an Entry or Asset, but got: ${JSON.stringify(entryOrAsset)}`);
|
|
1883
1869
|
}
|
|
1884
|
-
const
|
|
1870
|
+
const fieldName = path.split('/').slice(2, -1);
|
|
1871
|
+
const value = get$1(entryOrAsset, fieldName);
|
|
1885
1872
|
let resolvedEntity;
|
|
1886
|
-
if (isAsset(value) || isEntry(value)) {
|
|
1873
|
+
if (isAsset$1(value) || isEntry$1(value)) {
|
|
1887
1874
|
// In some cases, reference fields are already resolved
|
|
1888
1875
|
resolvedEntity = value;
|
|
1889
1876
|
}
|
|
1890
1877
|
else if (value?.sys.type === 'Link') {
|
|
1891
1878
|
// Look up the reference in the entity store
|
|
1892
1879
|
resolvedEntity = entityStore.getEntityFromLink(value);
|
|
1893
|
-
if (!resolvedEntity) {
|
|
1894
|
-
return;
|
|
1895
|
-
}
|
|
1896
1880
|
}
|
|
1897
1881
|
else {
|
|
1898
|
-
console.warn(`
|
|
1882
|
+
console.warn(`When attempting to follow link in field '${fieldName}' of entity, the value is expected to be a link, but got: ${JSON.stringify(value)}`, { entity: entryOrAsset });
|
|
1883
|
+
return;
|
|
1884
|
+
}
|
|
1885
|
+
// no need to make structuredClone(entityStore.getEntityFromLink(value)) because
|
|
1886
|
+
// we provide component with the original Object.frozen object of the entity.
|
|
1887
|
+
// As we don't resolve L3 and don't mutate the entity before returning anymore,
|
|
1888
|
+
// we don't need to make a copy of the entity. And even provide better referential integrity
|
|
1889
|
+
// for the component for the same entity.
|
|
1890
|
+
if (!resolvedEntity) {
|
|
1899
1891
|
return;
|
|
1900
1892
|
}
|
|
1901
|
-
//resolve any embedded links - we currently only support 2 levels deep
|
|
1902
|
-
const fields = resolvedEntity.fields || {};
|
|
1903
|
-
Object.entries(fields).forEach(([fieldKey, field]) => {
|
|
1904
|
-
if (field && field.sys?.type === 'Link') {
|
|
1905
|
-
const entity = entityStore.getEntityFromLink(field);
|
|
1906
|
-
if (entity) {
|
|
1907
|
-
resolvedEntity.fields[fieldKey] = entity;
|
|
1908
|
-
}
|
|
1909
|
-
}
|
|
1910
|
-
else if (field && Array.isArray(field)) {
|
|
1911
|
-
resolvedEntity.fields[fieldKey] = field.map((innerField) => {
|
|
1912
|
-
if (innerField && innerField.sys?.type === 'Link') {
|
|
1913
|
-
const entity = entityStore.getEntityFromLink(innerField);
|
|
1914
|
-
if (entity) {
|
|
1915
|
-
return entity;
|
|
1916
|
-
}
|
|
1917
|
-
}
|
|
1918
|
-
return innerField;
|
|
1919
|
-
});
|
|
1920
|
-
}
|
|
1921
|
-
});
|
|
1922
1893
|
return resolvedEntity;
|
|
1923
1894
|
}
|
|
1924
1895
|
|
|
1896
|
+
const excludeUndefined = (value) => {
|
|
1897
|
+
return value !== undefined;
|
|
1898
|
+
};
|
|
1925
1899
|
function getArrayValue(entryOrAsset, path, entityStore) {
|
|
1900
|
+
// NOTE: Not sure if we need this if-statement,
|
|
1901
|
+
// as it is NOT possible to bind to Array variable an Asset
|
|
1902
|
+
// (as Assets don't have multi-reference fields) unless it's a degenerate case.
|
|
1926
1903
|
if (entryOrAsset.sys.type === 'Asset') {
|
|
1927
1904
|
return entryOrAsset;
|
|
1928
1905
|
}
|
|
1929
|
-
const
|
|
1906
|
+
const fieldName = path.split('/').slice(2, -1);
|
|
1907
|
+
const arrayValue = get$1(entryOrAsset, fieldName);
|
|
1930
1908
|
if (!isArray(arrayValue)) {
|
|
1931
|
-
console.warn(`Expected
|
|
1909
|
+
console.warn(`A field '${fieldName}' of an entity was bound to an Array variable. Expected value of that field to be an array, but got: ${JSON.stringify(arrayValue)}`, { entity: entryOrAsset });
|
|
1932
1910
|
return;
|
|
1933
1911
|
}
|
|
1934
|
-
const result = arrayValue
|
|
1912
|
+
const result = arrayValue
|
|
1913
|
+
.map((value) => {
|
|
1935
1914
|
if (typeof value === 'string') {
|
|
1936
|
-
return value;
|
|
1915
|
+
return value; // handles case where Text array is bound (in [Content Model] tab of the platform, select Text and make it a list)
|
|
1937
1916
|
}
|
|
1938
1917
|
else if (value?.sys?.type === 'Link') {
|
|
1939
1918
|
const resolvedEntity = entityStore.getEntityFromLink(value);
|
|
1940
1919
|
if (!resolvedEntity) {
|
|
1920
|
+
// We return undefined, which means that entity wasn't availble in the Entity Store due to:
|
|
1921
|
+
// - because it's archived entity (and they normally wouldn't be sent to the Entity Store)
|
|
1922
|
+
// - bug where some entity wasn't added to the Entity Store
|
|
1923
|
+
// BTW, deleted entities shouldn't even be possible here as they require CT deletion first and that shouldn't allow us to load them at all)
|
|
1941
1924
|
return;
|
|
1942
1925
|
}
|
|
1943
|
-
//resolve any embedded links - we currently only support 2 levels deep
|
|
1944
|
-
const fields = resolvedEntity.fields || {};
|
|
1945
|
-
Object.entries(fields).forEach(([fieldKey, field]) => {
|
|
1946
|
-
if (field && field.sys?.type === 'Link') {
|
|
1947
|
-
const entity = entityStore.getEntityFromLink(field);
|
|
1948
|
-
if (entity) {
|
|
1949
|
-
resolvedEntity.fields[fieldKey] = entity;
|
|
1950
|
-
}
|
|
1951
|
-
}
|
|
1952
|
-
});
|
|
1953
1926
|
return resolvedEntity;
|
|
1954
1927
|
}
|
|
1955
1928
|
else {
|
|
1956
1929
|
console.warn(`Expected value to be a string or Link, but got: ${JSON.stringify(value)}`);
|
|
1957
1930
|
return undefined;
|
|
1958
1931
|
}
|
|
1959
|
-
})
|
|
1960
|
-
|
|
1932
|
+
})
|
|
1933
|
+
.filter(excludeUndefined);
|
|
1934
|
+
// eg. imagine you have multi-referene field with 3 links to archived entries,
|
|
1935
|
+
// all of them will be undefined on previous step and will be filtered out
|
|
1936
|
+
// of resultWithoutUndefined. Instead of passing to component an empty array,
|
|
1937
|
+
// we pass undefined. This means that develloper making custom component
|
|
1938
|
+
// does not have to handle empty array case. But only undefiened, which signals:
|
|
1939
|
+
// user didn't bind anything; user bound to reference field which is unset; all references are archived
|
|
1940
|
+
return result.length > 0 ? result : undefined;
|
|
1961
1941
|
}
|
|
1962
1942
|
|
|
1963
1943
|
const transformBoundContentValue = (variables, entityStore, binding, resolveDesignValue, variableName, variableType, path) => {
|
|
@@ -2116,11 +2096,22 @@ const sendMessage = (eventType, data) => {
|
|
|
2116
2096
|
}, '*');
|
|
2117
2097
|
};
|
|
2118
2098
|
|
|
2099
|
+
function deepFreeze$1(obj) {
|
|
2100
|
+
const propNames = Object.getOwnPropertyNames(obj);
|
|
2101
|
+
for (const name of propNames) {
|
|
2102
|
+
const value = obj[name];
|
|
2103
|
+
if (value && typeof value === 'object') {
|
|
2104
|
+
deepFreeze$1(value);
|
|
2105
|
+
}
|
|
2106
|
+
}
|
|
2107
|
+
return Object.freeze(obj);
|
|
2108
|
+
}
|
|
2109
|
+
|
|
2119
2110
|
/**
|
|
2120
2111
|
* Base Store for entities
|
|
2121
2112
|
* Can be extended for the different loading behaviours (editor, production, ..)
|
|
2122
2113
|
*/
|
|
2123
|
-
class EntityStoreBase {
|
|
2114
|
+
let EntityStoreBase$1 = class EntityStoreBase {
|
|
2124
2115
|
constructor({ entities, locale }) {
|
|
2125
2116
|
/* serialized */ this.entryMap = new Map();
|
|
2126
2117
|
/* serialized */ this.assetMap = new Map();
|
|
@@ -2136,11 +2127,11 @@ class EntityStoreBase {
|
|
|
2136
2127
|
this.addEntity(entity);
|
|
2137
2128
|
}
|
|
2138
2129
|
getEntryOrAsset(linkOrEntryOrAsset, path) {
|
|
2139
|
-
if (isDeepPath(path)) {
|
|
2130
|
+
if (isDeepPath$1(path)) {
|
|
2140
2131
|
return this.getDeepEntry(linkOrEntryOrAsset, path);
|
|
2141
2132
|
}
|
|
2142
2133
|
let entity;
|
|
2143
|
-
if (isLink(linkOrEntryOrAsset)) {
|
|
2134
|
+
if (isLink$1(linkOrEntryOrAsset)) {
|
|
2144
2135
|
const resolvedEntity = linkOrEntryOrAsset.sys.linkType === 'Entry'
|
|
2145
2136
|
? this.entryMap.get(linkOrEntryOrAsset.sys.id)
|
|
2146
2137
|
: this.assetMap.get(linkOrEntryOrAsset.sys.id);
|
|
@@ -2150,7 +2141,7 @@ class EntityStoreBase {
|
|
|
2150
2141
|
}
|
|
2151
2142
|
entity = resolvedEntity;
|
|
2152
2143
|
}
|
|
2153
|
-
else if (isAsset(linkOrEntryOrAsset) || isEntry(linkOrEntryOrAsset)) {
|
|
2144
|
+
else if (isAsset$1(linkOrEntryOrAsset) || isEntry$1(linkOrEntryOrAsset)) {
|
|
2154
2145
|
// We already have the complete entity in preview & delivery (resolved by the CMA client)
|
|
2155
2146
|
entity = linkOrEntryOrAsset;
|
|
2156
2147
|
}
|
|
@@ -2172,7 +2163,7 @@ class EntityStoreBase {
|
|
|
2172
2163
|
console.warn(`Unresolved entity reference: ${entityLink.sys.linkType} with ID ${entityLink.sys.id}`);
|
|
2173
2164
|
return;
|
|
2174
2165
|
}
|
|
2175
|
-
return get(entity, path);
|
|
2166
|
+
return get$1(entity, path);
|
|
2176
2167
|
}
|
|
2177
2168
|
getEntityFromLink(link) {
|
|
2178
2169
|
const resolvedEntity = link.sys.linkType === 'Entry'
|
|
@@ -2184,6 +2175,22 @@ class EntityStoreBase {
|
|
|
2184
2175
|
}
|
|
2185
2176
|
return resolvedEntity;
|
|
2186
2177
|
}
|
|
2178
|
+
getAssetById(assetId) {
|
|
2179
|
+
const asset = this.assetMap.get(assetId);
|
|
2180
|
+
if (!asset) {
|
|
2181
|
+
console.warn(`Asset with ID "${assetId}" is not found in the store`);
|
|
2182
|
+
return;
|
|
2183
|
+
}
|
|
2184
|
+
return asset;
|
|
2185
|
+
}
|
|
2186
|
+
getEntryById(entryId) {
|
|
2187
|
+
const entry = this.entryMap.get(entryId);
|
|
2188
|
+
if (!entry) {
|
|
2189
|
+
console.warn(`Entry with ID "${entryId}" is not found in the store`);
|
|
2190
|
+
return;
|
|
2191
|
+
}
|
|
2192
|
+
return entry;
|
|
2193
|
+
}
|
|
2187
2194
|
getEntitiesFromMap(type, ids) {
|
|
2188
2195
|
const resolved = [];
|
|
2189
2196
|
const missing = [];
|
|
@@ -2202,11 +2209,13 @@ class EntityStoreBase {
|
|
|
2202
2209
|
};
|
|
2203
2210
|
}
|
|
2204
2211
|
addEntity(entity) {
|
|
2205
|
-
if (isAsset(entity)) {
|
|
2206
|
-
|
|
2212
|
+
if (isAsset$1(entity)) {
|
|
2213
|
+
// cloned and frozen
|
|
2214
|
+
this.assetMap.set(entity.sys.id, deepFreeze$1(structuredClone(entity)));
|
|
2207
2215
|
}
|
|
2208
|
-
else if (isEntry(entity)) {
|
|
2209
|
-
|
|
2216
|
+
else if (isEntry$1(entity)) {
|
|
2217
|
+
// cloned and frozen
|
|
2218
|
+
this.entryMap.set(entity.sys.id, deepFreeze$1(structuredClone(entity)));
|
|
2210
2219
|
}
|
|
2211
2220
|
else {
|
|
2212
2221
|
throw new Error(`Attempted to add an entity to the store that is neither Asset nor Entry: '${JSON.stringify(entity)}'`);
|
|
@@ -2259,7 +2268,7 @@ class EntityStoreBase {
|
|
|
2259
2268
|
resolvedFieldset.push([entityToResolveFieldsFrom, field, _localeQualifier]);
|
|
2260
2269
|
break;
|
|
2261
2270
|
}
|
|
2262
|
-
const fieldValue = get(entityToResolveFieldsFrom, ['fields', field]);
|
|
2271
|
+
const fieldValue = get$1(entityToResolveFieldsFrom, ['fields', field]);
|
|
2263
2272
|
if (undefined === fieldValue) {
|
|
2264
2273
|
return {
|
|
2265
2274
|
resolvedFieldset,
|
|
@@ -2267,7 +2276,7 @@ class EntityStoreBase {
|
|
|
2267
2276
|
reason: `Cannot resolve field Link<${entityToResolveFieldsFrom.sys.type}>(sys.id=${entityToResolveFieldsFrom.sys.id}).fields[${field}] as field value is not defined`,
|
|
2268
2277
|
};
|
|
2269
2278
|
}
|
|
2270
|
-
else if (isLink(fieldValue)) {
|
|
2279
|
+
else if (isLink$1(fieldValue)) {
|
|
2271
2280
|
const entity = this.getEntityFromLink(fieldValue);
|
|
2272
2281
|
if (entity === undefined) {
|
|
2273
2282
|
return {
|
|
@@ -2279,7 +2288,7 @@ class EntityStoreBase {
|
|
|
2279
2288
|
resolvedFieldset.push([entityToResolveFieldsFrom, field, _localeQualifier]);
|
|
2280
2289
|
entityToResolveFieldsFrom = entity; // we move up
|
|
2281
2290
|
}
|
|
2282
|
-
else if (isAsset(fieldValue) || isEntry(fieldValue)) {
|
|
2291
|
+
else if (isAsset$1(fieldValue) || isEntry$1(fieldValue)) {
|
|
2283
2292
|
resolvedFieldset.push([entityToResolveFieldsFrom, field, _localeQualifier]);
|
|
2284
2293
|
entityToResolveFieldsFrom = fieldValue; // we move up
|
|
2285
2294
|
}
|
|
@@ -2296,13 +2305,13 @@ class EntityStoreBase {
|
|
|
2296
2305
|
isFullyResolved: true,
|
|
2297
2306
|
};
|
|
2298
2307
|
};
|
|
2299
|
-
const headEntity = isLink(linkOrEntryOrAsset)
|
|
2308
|
+
const headEntity = isLink$1(linkOrEntryOrAsset)
|
|
2300
2309
|
? this.getEntityFromLink(linkOrEntryOrAsset)
|
|
2301
2310
|
: linkOrEntryOrAsset;
|
|
2302
2311
|
if (undefined === headEntity) {
|
|
2303
2312
|
return;
|
|
2304
2313
|
}
|
|
2305
|
-
const unresolvedFieldset = parseDataSourcePathIntoFieldset(path);
|
|
2314
|
+
const unresolvedFieldset = parseDataSourcePathIntoFieldset$1(path);
|
|
2306
2315
|
// The purpose here is to take this intermediate representation of the deep-path
|
|
2307
2316
|
// and to follow the links to the leaf-entity and field
|
|
2308
2317
|
// in case we can't follow till the end, we should signal that there was null-reference in the path
|
|
@@ -2328,13 +2337,13 @@ class EntityStoreBase {
|
|
|
2328
2337
|
locale: this.locale,
|
|
2329
2338
|
};
|
|
2330
2339
|
}
|
|
2331
|
-
}
|
|
2340
|
+
};
|
|
2332
2341
|
|
|
2333
2342
|
/**
|
|
2334
2343
|
* EntityStore which resolves entries and assets from the editor
|
|
2335
2344
|
* over the sendMessage and subscribe functions.
|
|
2336
2345
|
*/
|
|
2337
|
-
class EditorEntityStore extends EntityStoreBase {
|
|
2346
|
+
class EditorEntityStore extends EntityStoreBase$1 {
|
|
2338
2347
|
constructor({ entities, locale, sendMessage, subscribe, timeoutDuration = 3000, }) {
|
|
2339
2348
|
super({ entities, locale });
|
|
2340
2349
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
@@ -2471,7 +2480,6 @@ class EditorModeEntityStore extends EditorEntityStore {
|
|
|
2471
2480
|
};
|
|
2472
2481
|
};
|
|
2473
2482
|
super({ entities, sendMessage, subscribe, locale, timeoutDuration: REQUEST_TIMEOUT });
|
|
2474
|
-
this.locale = locale;
|
|
2475
2483
|
}
|
|
2476
2484
|
/**
|
|
2477
2485
|
* This function collects and returns the list of requested entries and assets. Additionally, it checks
|
|
@@ -2501,11 +2509,91 @@ class EditorModeEntityStore extends EditorEntityStore {
|
|
|
2501
2509
|
if (!entity) {
|
|
2502
2510
|
return;
|
|
2503
2511
|
}
|
|
2504
|
-
const fieldValue = get(entity, path);
|
|
2512
|
+
const fieldValue = get$1(entity, path);
|
|
2505
2513
|
return transformAssetFileToUrl(fieldValue);
|
|
2506
2514
|
}
|
|
2507
2515
|
}
|
|
2508
2516
|
|
|
2517
|
+
let UninitializedEntityStore$1 = class UninitializedEntityStore extends EntityStoreBase$1 {
|
|
2518
|
+
constructor() {
|
|
2519
|
+
super({ entities: [], locale: 'uninitialized-locale-in-uninitialized-entity-store' });
|
|
2520
|
+
}
|
|
2521
|
+
};
|
|
2522
|
+
|
|
2523
|
+
const inMemoryEntitiesStore = create((set, get) => ({
|
|
2524
|
+
// The UninitializedEntityStore is a placeholder instance and is here to highlight the
|
|
2525
|
+
// // fact that it's not used by anything until during loading lifecycle it'sreplaced by real entity store:
|
|
2526
|
+
// - in Preview+Delivery mode: right after we fetch Expereince and it entities
|
|
2527
|
+
// - in EDITOR (VisualEditor) mode: right after the VisualEditor is async imported and initialize event happens
|
|
2528
|
+
entityStore: new UninitializedEntityStore$1(),
|
|
2529
|
+
areEntitiesFetched: false,
|
|
2530
|
+
setEntitiesFetched(fetched) {
|
|
2531
|
+
set({ areEntitiesFetched: fetched });
|
|
2532
|
+
},
|
|
2533
|
+
resolveAssetById(assetId) {
|
|
2534
|
+
if (!assetId)
|
|
2535
|
+
return undefined;
|
|
2536
|
+
const { entityStore } = get();
|
|
2537
|
+
return entityStore.getAssetById(assetId);
|
|
2538
|
+
},
|
|
2539
|
+
resolveEntryById(entryId) {
|
|
2540
|
+
if (!entryId)
|
|
2541
|
+
return undefined;
|
|
2542
|
+
const { entityStore } = get();
|
|
2543
|
+
return entityStore.getEntryById(entryId);
|
|
2544
|
+
},
|
|
2545
|
+
resolveEntity(link) {
|
|
2546
|
+
if (!link)
|
|
2547
|
+
return undefined;
|
|
2548
|
+
const { entityStore } = get();
|
|
2549
|
+
return entityStore.getEntityFromLink(link);
|
|
2550
|
+
},
|
|
2551
|
+
resetEntityStore(entityStore) {
|
|
2552
|
+
set({
|
|
2553
|
+
entityStore,
|
|
2554
|
+
areEntitiesFetched: false,
|
|
2555
|
+
});
|
|
2556
|
+
},
|
|
2557
|
+
}));
|
|
2558
|
+
|
|
2559
|
+
function maybeResolveLink(maybeLink) {
|
|
2560
|
+
if (!isLink$1(maybeLink)) {
|
|
2561
|
+
console.warn('maybeResolveLink function must receive Link shape. Provided argument does not match the Link shape: ', maybeLink);
|
|
2562
|
+
return undefined;
|
|
2563
|
+
}
|
|
2564
|
+
return inMemoryEntitiesStore.getState().resolveEntity(maybeLink);
|
|
2565
|
+
}
|
|
2566
|
+
function maybeResolveByAssetId(assetId) {
|
|
2567
|
+
return inMemoryEntitiesStore.getState().resolveAssetById(assetId);
|
|
2568
|
+
}
|
|
2569
|
+
function maybeResolveByEntryId(entryId) {
|
|
2570
|
+
return inMemoryEntitiesStore.getState().resolveEntryById(entryId);
|
|
2571
|
+
}
|
|
2572
|
+
function hasEntry(entryId) {
|
|
2573
|
+
return Boolean(maybeResolveByEntryId(entryId));
|
|
2574
|
+
}
|
|
2575
|
+
function hasAsset(assetId) {
|
|
2576
|
+
return Boolean(maybeResolveByAssetId(assetId));
|
|
2577
|
+
}
|
|
2578
|
+
function addEntities(entities) {
|
|
2579
|
+
if (!Array.isArray(entities) || entities.length === 0) {
|
|
2580
|
+
return;
|
|
2581
|
+
}
|
|
2582
|
+
const { entityStore } = inMemoryEntitiesStore.getState();
|
|
2583
|
+
const definedEntities = entities.filter(Boolean);
|
|
2584
|
+
for (const entity of definedEntities) {
|
|
2585
|
+
entityStore.updateEntity(entity);
|
|
2586
|
+
}
|
|
2587
|
+
}
|
|
2588
|
+
const inMemoryEntities = {
|
|
2589
|
+
maybeResolveLink,
|
|
2590
|
+
maybeResolveByAssetId,
|
|
2591
|
+
maybeResolveByEntryId,
|
|
2592
|
+
hasEntry,
|
|
2593
|
+
hasAsset,
|
|
2594
|
+
addEntities,
|
|
2595
|
+
};
|
|
2596
|
+
|
|
2509
2597
|
var VisualEditorMode$1;
|
|
2510
2598
|
(function (VisualEditorMode) {
|
|
2511
2599
|
VisualEditorMode["LazyLoad"] = "lazyLoad";
|
|
@@ -2535,7 +2623,7 @@ class DeepReference {
|
|
|
2535
2623
|
// field references nothing (or even field doesn't exist)
|
|
2536
2624
|
return undefined;
|
|
2537
2625
|
}
|
|
2538
|
-
if (!isLink(maybeReferentLink)) {
|
|
2626
|
+
if (!isLink$1(maybeReferentLink)) {
|
|
2539
2627
|
// Scenario of "impostor referent", where one of the deepPath's segments is not a Link but some other type
|
|
2540
2628
|
// Under normal circumstance we expect field to be a Link, but it could be an "impostor"
|
|
2541
2629
|
// eg. `Text` or `Number` or anything like that; could be due to CT changes or manual path creation via CMA
|
|
@@ -2555,7 +2643,7 @@ function gatherDeepReferencesFromTree(startingNode, dataSource) {
|
|
|
2555
2643
|
for (const [, variableMapping] of Object.entries(node.data.props)) {
|
|
2556
2644
|
if (variableMapping.type !== 'BoundValue')
|
|
2557
2645
|
continue;
|
|
2558
|
-
if (!isDeepPath(variableMapping.path))
|
|
2646
|
+
if (!isDeepPath$1(variableMapping.path))
|
|
2559
2647
|
continue;
|
|
2560
2648
|
deepReferences.push(DeepReference.from({
|
|
2561
2649
|
path: variableMapping.path,
|
|
@@ -3164,6 +3252,26 @@ const useTreeStore = create((set, get) => ({
|
|
|
3164
3252
|
reparentChildNode(sourceIndex, destinationIndex, sourceParentId, destinationParentId, state.tree.root);
|
|
3165
3253
|
}));
|
|
3166
3254
|
},
|
|
3255
|
+
// breadth first search
|
|
3256
|
+
findNodeById(nodeId) {
|
|
3257
|
+
if (!nodeId) {
|
|
3258
|
+
return null;
|
|
3259
|
+
}
|
|
3260
|
+
const rootNode = get().tree.root;
|
|
3261
|
+
const visitedNodeIds = [];
|
|
3262
|
+
const queue = [];
|
|
3263
|
+
let currentNode = rootNode;
|
|
3264
|
+
queue.push(currentNode);
|
|
3265
|
+
while (queue.length) {
|
|
3266
|
+
currentNode = queue.shift();
|
|
3267
|
+
visitedNodeIds.push(currentNode.data.id);
|
|
3268
|
+
if (currentNode.data.id === nodeId) {
|
|
3269
|
+
return currentNode;
|
|
3270
|
+
}
|
|
3271
|
+
queue.push(...currentNode.children);
|
|
3272
|
+
}
|
|
3273
|
+
return null;
|
|
3274
|
+
},
|
|
3167
3275
|
}));
|
|
3168
3276
|
const hasBreakpointDiffs = (currentTree, newTree) => {
|
|
3169
3277
|
const currentBreakpoints = currentTree?.root?.data?.breakpoints ?? [];
|
|
@@ -3944,6 +4052,419 @@ class DebugLogger {
|
|
|
3944
4052
|
DebugLogger.instance = null;
|
|
3945
4053
|
DebugLogger.getInstance();
|
|
3946
4054
|
|
|
4055
|
+
const isLink = (maybeLink) => {
|
|
4056
|
+
if (maybeLink === null)
|
|
4057
|
+
return false;
|
|
4058
|
+
if (typeof maybeLink !== 'object')
|
|
4059
|
+
return false;
|
|
4060
|
+
const link = maybeLink;
|
|
4061
|
+
return Boolean(link.sys?.id) && link.sys?.type === 'Link' && Boolean(link.sys?.linkType);
|
|
4062
|
+
};
|
|
4063
|
+
|
|
4064
|
+
/**
|
|
4065
|
+
* This module encapsulates format of the path to a deep reference.
|
|
4066
|
+
*/
|
|
4067
|
+
const parseDataSourcePathIntoFieldset = (path) => {
|
|
4068
|
+
const parsedPath = parseDeepPath(path);
|
|
4069
|
+
if (null === parsedPath) {
|
|
4070
|
+
throw new Error(`Cannot parse path '${path}' as deep path`);
|
|
4071
|
+
}
|
|
4072
|
+
return parsedPath.fields.map((field) => [null, field, '~locale']);
|
|
4073
|
+
};
|
|
4074
|
+
/**
|
|
4075
|
+
* Detects if paths is valid deep-path, like:
|
|
4076
|
+
* - /gV6yKXp61hfYrR7rEyKxY/fields/mainStory/~locale/fields/cover/~locale/fields/title/~locale
|
|
4077
|
+
* or regular, like:
|
|
4078
|
+
* - /6J8eA60yXwdm5eyUh9fX6/fields/mainStory/~locale
|
|
4079
|
+
* @returns
|
|
4080
|
+
*/
|
|
4081
|
+
const isDeepPath = (deepPathCandidate) => {
|
|
4082
|
+
const deepPathParsed = parseDeepPath(deepPathCandidate);
|
|
4083
|
+
if (!deepPathParsed) {
|
|
4084
|
+
return false;
|
|
4085
|
+
}
|
|
4086
|
+
return deepPathParsed.fields.length > 1;
|
|
4087
|
+
};
|
|
4088
|
+
const parseDeepPath = (deepPathCandidate) => {
|
|
4089
|
+
// ALGORITHM:
|
|
4090
|
+
// We start with deep path in form:
|
|
4091
|
+
// /uuid123/fields/mainStory/~locale/fields/cover/~locale/fields/title/~locale
|
|
4092
|
+
// First turn string into array of segments
|
|
4093
|
+
// ['', 'uuid123', 'fields', 'mainStory', '~locale', 'fields', 'cover', '~locale', 'fields', 'title', '~locale']
|
|
4094
|
+
// Then group segments into intermediate represenatation - chunks, where each non-initial chunk starts with 'fields'
|
|
4095
|
+
// [
|
|
4096
|
+
// [ "", "uuid123" ],
|
|
4097
|
+
// [ "fields", "mainStory", "~locale" ],
|
|
4098
|
+
// [ "fields", "cover", "~locale" ],
|
|
4099
|
+
// [ "fields", "title", "~locale" ]
|
|
4100
|
+
// ]
|
|
4101
|
+
// Then check "initial" chunk for corretness
|
|
4102
|
+
// Then check all "field-leading" chunks for correctness
|
|
4103
|
+
const isValidInitialChunk = (initialChunk) => {
|
|
4104
|
+
// must have start with '' and have at least 2 segments, second non-empty
|
|
4105
|
+
// eg. /-_432uuid123123
|
|
4106
|
+
return /^\/([^/^~]+)$/.test(initialChunk.join('/'));
|
|
4107
|
+
};
|
|
4108
|
+
const isValidFieldChunk = (fieldChunk) => {
|
|
4109
|
+
// must start with 'fields' and have at least 3 segments, second non-empty and last segment must be '~locale'
|
|
4110
|
+
// eg. fields/-32234mainStory/~locale
|
|
4111
|
+
return /^fields\/[^/^~]+\/~locale$/.test(fieldChunk.join('/'));
|
|
4112
|
+
};
|
|
4113
|
+
const deepPathSegments = deepPathCandidate.split('/');
|
|
4114
|
+
const chunks = chunkSegments(deepPathSegments, { startNextChunkOnElementEqualTo: 'fields' });
|
|
4115
|
+
if (chunks.length <= 1) {
|
|
4116
|
+
return null; // malformed path, even regular paths have at least 2 chunks
|
|
4117
|
+
}
|
|
4118
|
+
else if (chunks.length === 2) {
|
|
4119
|
+
return null; // deep paths have at least 3 chunks
|
|
4120
|
+
}
|
|
4121
|
+
// With 3+ chunks we can now check for deep path correctness
|
|
4122
|
+
const [initialChunk, ...fieldChunks] = chunks;
|
|
4123
|
+
if (!isValidInitialChunk(initialChunk)) {
|
|
4124
|
+
return null;
|
|
4125
|
+
}
|
|
4126
|
+
if (!fieldChunks.every(isValidFieldChunk)) {
|
|
4127
|
+
return null;
|
|
4128
|
+
}
|
|
4129
|
+
return {
|
|
4130
|
+
key: initialChunk[1], // pick uuid from initial chunk ['','uuid123'],
|
|
4131
|
+
fields: fieldChunks.map((fieldChunk) => fieldChunk[1]), // pick only fieldName eg. from ['fields','mainStory', '~locale'] we pick `mainStory`
|
|
4132
|
+
};
|
|
4133
|
+
};
|
|
4134
|
+
const chunkSegments = (segments, { startNextChunkOnElementEqualTo }) => {
|
|
4135
|
+
const chunks = [];
|
|
4136
|
+
let currentChunk = [];
|
|
4137
|
+
const isSegmentBeginningOfChunk = (segment) => segment === startNextChunkOnElementEqualTo;
|
|
4138
|
+
const excludeEmptyChunks = (chunk) => chunk.length > 0;
|
|
4139
|
+
for (let i = 0; i < segments.length; i++) {
|
|
4140
|
+
const isInitialElement = i === 0;
|
|
4141
|
+
const segment = segments[i];
|
|
4142
|
+
if (isInitialElement) {
|
|
4143
|
+
currentChunk = [segment];
|
|
4144
|
+
}
|
|
4145
|
+
else if (isSegmentBeginningOfChunk(segment)) {
|
|
4146
|
+
chunks.push(currentChunk);
|
|
4147
|
+
currentChunk = [segment];
|
|
4148
|
+
}
|
|
4149
|
+
else {
|
|
4150
|
+
currentChunk.push(segment);
|
|
4151
|
+
}
|
|
4152
|
+
}
|
|
4153
|
+
chunks.push(currentChunk);
|
|
4154
|
+
return chunks.filter(excludeEmptyChunks);
|
|
4155
|
+
};
|
|
4156
|
+
|
|
4157
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
4158
|
+
function get(obj, path) {
|
|
4159
|
+
if (!path.length) {
|
|
4160
|
+
return obj;
|
|
4161
|
+
}
|
|
4162
|
+
try {
|
|
4163
|
+
const [currentPath, ...nextPath] = path;
|
|
4164
|
+
return get(obj[currentPath], nextPath);
|
|
4165
|
+
}
|
|
4166
|
+
catch (err) {
|
|
4167
|
+
return undefined;
|
|
4168
|
+
}
|
|
4169
|
+
}
|
|
4170
|
+
const isEntry = (value) => {
|
|
4171
|
+
return (null !== value &&
|
|
4172
|
+
typeof value === 'object' &&
|
|
4173
|
+
'sys' in value &&
|
|
4174
|
+
value.sys?.type === 'Entry');
|
|
4175
|
+
};
|
|
4176
|
+
const isAsset = (value) => {
|
|
4177
|
+
return (null !== value &&
|
|
4178
|
+
typeof value === 'object' &&
|
|
4179
|
+
'sys' in value &&
|
|
4180
|
+
value.sys?.type === 'Asset');
|
|
4181
|
+
};
|
|
4182
|
+
|
|
4183
|
+
function deepFreeze(obj) {
|
|
4184
|
+
const propNames = Object.getOwnPropertyNames(obj);
|
|
4185
|
+
for (const name of propNames) {
|
|
4186
|
+
const value = obj[name];
|
|
4187
|
+
if (value && typeof value === 'object') {
|
|
4188
|
+
deepFreeze(value);
|
|
4189
|
+
}
|
|
4190
|
+
}
|
|
4191
|
+
return Object.freeze(obj);
|
|
4192
|
+
}
|
|
4193
|
+
|
|
4194
|
+
/**
|
|
4195
|
+
* Base Store for entities
|
|
4196
|
+
* Can be extended for the different loading behaviours (editor, production, ..)
|
|
4197
|
+
*/
|
|
4198
|
+
class EntityStoreBase {
|
|
4199
|
+
constructor({ entities, locale }) {
|
|
4200
|
+
/* serialized */ this.entryMap = new Map();
|
|
4201
|
+
/* serialized */ this.assetMap = new Map();
|
|
4202
|
+
this.locale = locale;
|
|
4203
|
+
for (const entity of entities) {
|
|
4204
|
+
this.addEntity(entity);
|
|
4205
|
+
}
|
|
4206
|
+
}
|
|
4207
|
+
get entities() {
|
|
4208
|
+
return [...this.entryMap.values(), ...this.assetMap.values()];
|
|
4209
|
+
}
|
|
4210
|
+
updateEntity(entity) {
|
|
4211
|
+
this.addEntity(entity);
|
|
4212
|
+
}
|
|
4213
|
+
getEntryOrAsset(linkOrEntryOrAsset, path) {
|
|
4214
|
+
if (isDeepPath(path)) {
|
|
4215
|
+
return this.getDeepEntry(linkOrEntryOrAsset, path);
|
|
4216
|
+
}
|
|
4217
|
+
let entity;
|
|
4218
|
+
if (isLink(linkOrEntryOrAsset)) {
|
|
4219
|
+
const resolvedEntity = linkOrEntryOrAsset.sys.linkType === 'Entry'
|
|
4220
|
+
? this.entryMap.get(linkOrEntryOrAsset.sys.id)
|
|
4221
|
+
: this.assetMap.get(linkOrEntryOrAsset.sys.id);
|
|
4222
|
+
if (!resolvedEntity || resolvedEntity.sys.type !== linkOrEntryOrAsset.sys.linkType) {
|
|
4223
|
+
console.warn(`Experience references unresolved entity: ${JSON.stringify(linkOrEntryOrAsset)}`);
|
|
4224
|
+
return;
|
|
4225
|
+
}
|
|
4226
|
+
entity = resolvedEntity;
|
|
4227
|
+
}
|
|
4228
|
+
else if (isAsset(linkOrEntryOrAsset) || isEntry(linkOrEntryOrAsset)) {
|
|
4229
|
+
// We already have the complete entity in preview & delivery (resolved by the CMA client)
|
|
4230
|
+
entity = linkOrEntryOrAsset;
|
|
4231
|
+
}
|
|
4232
|
+
else {
|
|
4233
|
+
throw new Error(`Unexpected object when resolving entity: ${JSON.stringify(linkOrEntryOrAsset)}`);
|
|
4234
|
+
}
|
|
4235
|
+
return entity;
|
|
4236
|
+
}
|
|
4237
|
+
/**
|
|
4238
|
+
* @deprecated in the base class this should be simply an abstract method
|
|
4239
|
+
* @param entityLink
|
|
4240
|
+
* @param path
|
|
4241
|
+
* @returns
|
|
4242
|
+
*/
|
|
4243
|
+
getValue(entityLink, path) {
|
|
4244
|
+
const entity = this.getEntity(entityLink.sys.linkType, entityLink.sys.id);
|
|
4245
|
+
if (!entity) {
|
|
4246
|
+
// TODO: move to `debug` utils once it is extracted
|
|
4247
|
+
console.warn(`Unresolved entity reference: ${entityLink.sys.linkType} with ID ${entityLink.sys.id}`);
|
|
4248
|
+
return;
|
|
4249
|
+
}
|
|
4250
|
+
return get(entity, path);
|
|
4251
|
+
}
|
|
4252
|
+
getEntityFromLink(link) {
|
|
4253
|
+
const resolvedEntity = link.sys.linkType === 'Entry'
|
|
4254
|
+
? this.entryMap.get(link.sys.id)
|
|
4255
|
+
: this.assetMap.get(link.sys.id);
|
|
4256
|
+
if (!resolvedEntity || resolvedEntity.sys.type !== link.sys.linkType) {
|
|
4257
|
+
console.warn(`Experience references unresolved entity: ${JSON.stringify(link)}`);
|
|
4258
|
+
return;
|
|
4259
|
+
}
|
|
4260
|
+
return resolvedEntity;
|
|
4261
|
+
}
|
|
4262
|
+
getAssetById(assetId) {
|
|
4263
|
+
const asset = this.assetMap.get(assetId);
|
|
4264
|
+
if (!asset) {
|
|
4265
|
+
console.warn(`Asset with ID "${assetId}" is not found in the store`);
|
|
4266
|
+
return;
|
|
4267
|
+
}
|
|
4268
|
+
return asset;
|
|
4269
|
+
}
|
|
4270
|
+
getEntryById(entryId) {
|
|
4271
|
+
const entry = this.entryMap.get(entryId);
|
|
4272
|
+
if (!entry) {
|
|
4273
|
+
console.warn(`Entry with ID "${entryId}" is not found in the store`);
|
|
4274
|
+
return;
|
|
4275
|
+
}
|
|
4276
|
+
return entry;
|
|
4277
|
+
}
|
|
4278
|
+
getEntitiesFromMap(type, ids) {
|
|
4279
|
+
const resolved = [];
|
|
4280
|
+
const missing = [];
|
|
4281
|
+
for (const id of ids) {
|
|
4282
|
+
const entity = this.getEntity(type, id);
|
|
4283
|
+
if (entity) {
|
|
4284
|
+
resolved.push(entity);
|
|
4285
|
+
}
|
|
4286
|
+
else {
|
|
4287
|
+
missing.push(id);
|
|
4288
|
+
}
|
|
4289
|
+
}
|
|
4290
|
+
return {
|
|
4291
|
+
resolved,
|
|
4292
|
+
missing,
|
|
4293
|
+
};
|
|
4294
|
+
}
|
|
4295
|
+
addEntity(entity) {
|
|
4296
|
+
if (isAsset(entity)) {
|
|
4297
|
+
// cloned and frozen
|
|
4298
|
+
this.assetMap.set(entity.sys.id, deepFreeze(structuredClone(entity)));
|
|
4299
|
+
}
|
|
4300
|
+
else if (isEntry(entity)) {
|
|
4301
|
+
// cloned and frozen
|
|
4302
|
+
this.entryMap.set(entity.sys.id, deepFreeze(structuredClone(entity)));
|
|
4303
|
+
}
|
|
4304
|
+
else {
|
|
4305
|
+
throw new Error(`Attempted to add an entity to the store that is neither Asset nor Entry: '${JSON.stringify(entity)}'`);
|
|
4306
|
+
}
|
|
4307
|
+
}
|
|
4308
|
+
async fetchAsset(id) {
|
|
4309
|
+
const { resolved, missing } = this.getEntitiesFromMap('Asset', [id]);
|
|
4310
|
+
if (missing.length) {
|
|
4311
|
+
// TODO: move to `debug` utils once it is extracted
|
|
4312
|
+
console.warn(`Asset "${id}" is not in the store`);
|
|
4313
|
+
return;
|
|
4314
|
+
}
|
|
4315
|
+
return resolved[0];
|
|
4316
|
+
}
|
|
4317
|
+
async fetchAssets(ids) {
|
|
4318
|
+
const { resolved, missing } = this.getEntitiesFromMap('Asset', ids);
|
|
4319
|
+
if (missing.length) {
|
|
4320
|
+
throw new Error(`Missing assets in the store (${missing.join(',')})`);
|
|
4321
|
+
}
|
|
4322
|
+
return resolved;
|
|
4323
|
+
}
|
|
4324
|
+
async fetchEntry(id) {
|
|
4325
|
+
const { resolved, missing } = this.getEntitiesFromMap('Entry', [id]);
|
|
4326
|
+
if (missing.length) {
|
|
4327
|
+
// TODO: move to `debug` utils once it is extracted
|
|
4328
|
+
console.warn(`Entry "${id}" is not in the store`);
|
|
4329
|
+
return;
|
|
4330
|
+
}
|
|
4331
|
+
return resolved[0];
|
|
4332
|
+
}
|
|
4333
|
+
async fetchEntries(ids) {
|
|
4334
|
+
const { resolved, missing } = this.getEntitiesFromMap('Entry', ids);
|
|
4335
|
+
if (missing.length) {
|
|
4336
|
+
throw new Error(`Missing assets in the store (${missing.join(',')})`);
|
|
4337
|
+
}
|
|
4338
|
+
return resolved;
|
|
4339
|
+
}
|
|
4340
|
+
getDeepEntry(linkOrEntryOrAsset, path) {
|
|
4341
|
+
const resolveFieldset = (unresolvedFieldset, headEntry) => {
|
|
4342
|
+
const resolvedFieldset = [];
|
|
4343
|
+
let entityToResolveFieldsFrom = headEntry;
|
|
4344
|
+
for (let i = 0; i < unresolvedFieldset.length; i++) {
|
|
4345
|
+
const isLeaf = i === unresolvedFieldset.length - 1; // with last row, we are not expecting a link, but a value
|
|
4346
|
+
const row = unresolvedFieldset[i];
|
|
4347
|
+
const [, field, _localeQualifier] = row;
|
|
4348
|
+
if (!entityToResolveFieldsFrom) {
|
|
4349
|
+
throw new Error(`Logic Error: Cannot resolve field ${field} of a fieldset as there is no entity to resolve it from.`);
|
|
4350
|
+
}
|
|
4351
|
+
if (isLeaf) {
|
|
4352
|
+
resolvedFieldset.push([entityToResolveFieldsFrom, field, _localeQualifier]);
|
|
4353
|
+
break;
|
|
4354
|
+
}
|
|
4355
|
+
const fieldValue = get(entityToResolveFieldsFrom, ['fields', field]);
|
|
4356
|
+
if (undefined === fieldValue) {
|
|
4357
|
+
return {
|
|
4358
|
+
resolvedFieldset,
|
|
4359
|
+
isFullyResolved: false,
|
|
4360
|
+
reason: `Cannot resolve field Link<${entityToResolveFieldsFrom.sys.type}>(sys.id=${entityToResolveFieldsFrom.sys.id}).fields[${field}] as field value is not defined`,
|
|
4361
|
+
};
|
|
4362
|
+
}
|
|
4363
|
+
else if (isLink(fieldValue)) {
|
|
4364
|
+
const entity = this.getEntityFromLink(fieldValue);
|
|
4365
|
+
if (entity === undefined) {
|
|
4366
|
+
return {
|
|
4367
|
+
resolvedFieldset,
|
|
4368
|
+
isFullyResolved: false,
|
|
4369
|
+
reason: `Field reference Link (sys.id=${fieldValue.sys.id}) not found in the EntityStore, waiting...`,
|
|
4370
|
+
};
|
|
4371
|
+
}
|
|
4372
|
+
resolvedFieldset.push([entityToResolveFieldsFrom, field, _localeQualifier]);
|
|
4373
|
+
entityToResolveFieldsFrom = entity; // we move up
|
|
4374
|
+
}
|
|
4375
|
+
else if (isAsset(fieldValue) || isEntry(fieldValue)) {
|
|
4376
|
+
resolvedFieldset.push([entityToResolveFieldsFrom, field, _localeQualifier]);
|
|
4377
|
+
entityToResolveFieldsFrom = fieldValue; // we move up
|
|
4378
|
+
}
|
|
4379
|
+
else {
|
|
4380
|
+
return {
|
|
4381
|
+
resolvedFieldset,
|
|
4382
|
+
isFullyResolved: false,
|
|
4383
|
+
reason: `Deep path points to an invalid field value of type '${typeof fieldValue}' (value=${fieldValue})`,
|
|
4384
|
+
};
|
|
4385
|
+
}
|
|
4386
|
+
}
|
|
4387
|
+
return {
|
|
4388
|
+
resolvedFieldset,
|
|
4389
|
+
isFullyResolved: true,
|
|
4390
|
+
};
|
|
4391
|
+
};
|
|
4392
|
+
const headEntity = isLink(linkOrEntryOrAsset)
|
|
4393
|
+
? this.getEntityFromLink(linkOrEntryOrAsset)
|
|
4394
|
+
: linkOrEntryOrAsset;
|
|
4395
|
+
if (undefined === headEntity) {
|
|
4396
|
+
return;
|
|
4397
|
+
}
|
|
4398
|
+
const unresolvedFieldset = parseDataSourcePathIntoFieldset(path);
|
|
4399
|
+
// The purpose here is to take this intermediate representation of the deep-path
|
|
4400
|
+
// and to follow the links to the leaf-entity and field
|
|
4401
|
+
// in case we can't follow till the end, we should signal that there was null-reference in the path
|
|
4402
|
+
const { resolvedFieldset, isFullyResolved, reason } = resolveFieldset(unresolvedFieldset, headEntity);
|
|
4403
|
+
if (!isFullyResolved) {
|
|
4404
|
+
reason &&
|
|
4405
|
+
console.debug(`[exp-builder.sdk::EntityStoreBased::getValueDeep()] Deep path wasn't resolved till leaf node, falling back to undefined, because: ${reason}`);
|
|
4406
|
+
return;
|
|
4407
|
+
}
|
|
4408
|
+
const [leafEntity] = resolvedFieldset[resolvedFieldset.length - 1];
|
|
4409
|
+
return leafEntity;
|
|
4410
|
+
}
|
|
4411
|
+
getEntity(type, id) {
|
|
4412
|
+
if (type === 'Asset') {
|
|
4413
|
+
return this.assetMap.get(id);
|
|
4414
|
+
}
|
|
4415
|
+
return this.entryMap.get(id);
|
|
4416
|
+
}
|
|
4417
|
+
toJSON() {
|
|
4418
|
+
return {
|
|
4419
|
+
entryMap: Object.fromEntries(this.entryMap),
|
|
4420
|
+
assetMap: Object.fromEntries(this.assetMap),
|
|
4421
|
+
locale: this.locale,
|
|
4422
|
+
};
|
|
4423
|
+
}
|
|
4424
|
+
}
|
|
4425
|
+
|
|
4426
|
+
class UninitializedEntityStore extends EntityStoreBase {
|
|
4427
|
+
constructor() {
|
|
4428
|
+
super({ entities: [], locale: 'uninitialized-locale-in-uninitialized-entity-store' });
|
|
4429
|
+
}
|
|
4430
|
+
}
|
|
4431
|
+
|
|
4432
|
+
create((set, get) => ({
|
|
4433
|
+
// The UninitializedEntityStore is a placeholder instance and is here to highlight the
|
|
4434
|
+
// // fact that it's not used by anything until during loading lifecycle it'sreplaced by real entity store:
|
|
4435
|
+
// - in Preview+Delivery mode: right after we fetch Expereince and it entities
|
|
4436
|
+
// - in EDITOR (VisualEditor) mode: right after the VisualEditor is async imported and initialize event happens
|
|
4437
|
+
entityStore: new UninitializedEntityStore(),
|
|
4438
|
+
areEntitiesFetched: false,
|
|
4439
|
+
setEntitiesFetched(fetched) {
|
|
4440
|
+
set({ areEntitiesFetched: fetched });
|
|
4441
|
+
},
|
|
4442
|
+
resolveAssetById(assetId) {
|
|
4443
|
+
if (!assetId)
|
|
4444
|
+
return undefined;
|
|
4445
|
+
const { entityStore } = get();
|
|
4446
|
+
return entityStore.getAssetById(assetId);
|
|
4447
|
+
},
|
|
4448
|
+
resolveEntryById(entryId) {
|
|
4449
|
+
if (!entryId)
|
|
4450
|
+
return undefined;
|
|
4451
|
+
const { entityStore } = get();
|
|
4452
|
+
return entityStore.getEntryById(entryId);
|
|
4453
|
+
},
|
|
4454
|
+
resolveEntity(link) {
|
|
4455
|
+
if (!link)
|
|
4456
|
+
return undefined;
|
|
4457
|
+
const { entityStore } = get();
|
|
4458
|
+
return entityStore.getEntityFromLink(link);
|
|
4459
|
+
},
|
|
4460
|
+
resetEntityStore(entityStore) {
|
|
4461
|
+
set({
|
|
4462
|
+
entityStore,
|
|
4463
|
+
areEntitiesFetched: false,
|
|
4464
|
+
});
|
|
4465
|
+
},
|
|
4466
|
+
}));
|
|
4467
|
+
|
|
3947
4468
|
var VisualEditorMode;
|
|
3948
4469
|
(function (VisualEditorMode) {
|
|
3949
4470
|
VisualEditorMode["LazyLoad"] = "lazyLoad";
|
|
@@ -4008,23 +4529,6 @@ const Assembly = (props) => {
|
|
|
4008
4529
|
return React.createElement("div", { "data-test-id": "assembly", ...props, style: assemblyStyle });
|
|
4009
4530
|
};
|
|
4010
4531
|
|
|
4011
|
-
const useEntityStore = create((set) => ({
|
|
4012
|
-
entityStore: new EditorModeEntityStore({ locale: 'en-US', entities: [] }),
|
|
4013
|
-
areEntitiesFetched: false,
|
|
4014
|
-
setEntitiesFetched(fetched) {
|
|
4015
|
-
set({ areEntitiesFetched: fetched });
|
|
4016
|
-
},
|
|
4017
|
-
resetEntityStore(locale, entities = []) {
|
|
4018
|
-
console.debug(`[experiences-sdk-react] Resetting entity store because the locale changed to '${locale}'.`);
|
|
4019
|
-
const newEntityStore = new EditorModeEntityStore({ locale, entities });
|
|
4020
|
-
set({
|
|
4021
|
-
entityStore: newEntityStore,
|
|
4022
|
-
areEntitiesFetched: false,
|
|
4023
|
-
});
|
|
4024
|
-
return newEntityStore;
|
|
4025
|
-
},
|
|
4026
|
-
}));
|
|
4027
|
-
|
|
4028
4532
|
class DragState {
|
|
4029
4533
|
constructor() {
|
|
4030
4534
|
this.isDragStartedOnParent = false;
|
|
@@ -4094,10 +4598,11 @@ class SimulateDnD extends DragState {
|
|
|
4094
4598
|
}
|
|
4095
4599
|
var SimulateDnD$1 = new SimulateDnD();
|
|
4096
4600
|
|
|
4097
|
-
function useEditorSubscriber() {
|
|
4098
|
-
const entityStore =
|
|
4099
|
-
const areEntitiesFetched =
|
|
4100
|
-
const setEntitiesFetched =
|
|
4601
|
+
function useEditorSubscriber(entityCache) {
|
|
4602
|
+
const entityStore = entityCache((state) => state.entityStore);
|
|
4603
|
+
const areEntitiesFetched = entityCache((state) => state.areEntitiesFetched);
|
|
4604
|
+
const setEntitiesFetched = entityCache((state) => state.setEntitiesFetched);
|
|
4605
|
+
const resetEntityStore = entityCache((state) => state.resetEntityStore);
|
|
4101
4606
|
const { updateTree, updateNodesByUpdatedEntity } = useTreeStore((state) => ({
|
|
4102
4607
|
updateTree: state.updateTree,
|
|
4103
4608
|
updateNodesByUpdatedEntity: state.updateNodesByUpdatedEntity,
|
|
@@ -4109,7 +4614,6 @@ function useEditorSubscriber() {
|
|
|
4109
4614
|
const setDataSource = useEditorStore((state) => state.setDataSource);
|
|
4110
4615
|
const setSelectedNodeId = useEditorStore((state) => state.setSelectedNodeId);
|
|
4111
4616
|
const selectedNodeId = useEditorStore((state) => state.selectedNodeId);
|
|
4112
|
-
const resetEntityStore = useEntityStore((state) => state.resetEntityStore);
|
|
4113
4617
|
const setComponentId = useDraggedItemStore((state) => state.setComponentId);
|
|
4114
4618
|
const setHoveredComponentId = useDraggedItemStore((state) => state.setHoveredComponentId);
|
|
4115
4619
|
const setDraggingOnCanvas = useDraggedItemStore((state) => state.setDraggingOnCanvas);
|
|
@@ -4160,7 +4664,7 @@ function useEditorSubscriber() {
|
|
|
4160
4664
|
const isMissingL2Entities = (deepReferences) => {
|
|
4161
4665
|
const referentLinks = deepReferences
|
|
4162
4666
|
.map((deepReference) => deepReference.extractReferent(entityStore))
|
|
4163
|
-
.filter(isLink);
|
|
4667
|
+
.filter(isLink$1);
|
|
4164
4668
|
const { missingAssetIds, missingEntryIds } = entityStore.getMissingEntityIds(referentLinks);
|
|
4165
4669
|
return Boolean(missingAssetIds.length) || Boolean(missingEntryIds.length);
|
|
4166
4670
|
};
|
|
@@ -4177,7 +4681,7 @@ function useEditorSubscriber() {
|
|
|
4177
4681
|
const fillupL2 = async ({ deepReferences }) => {
|
|
4178
4682
|
const referentLinks = deepReferences
|
|
4179
4683
|
.map((deepReference) => deepReference.extractReferent(entityStore))
|
|
4180
|
-
.filter(isLink);
|
|
4684
|
+
.filter(isLink$1);
|
|
4181
4685
|
const { missingAssetIds, missingEntryIds } = entityStore.getMissingEntityIds(referentLinks);
|
|
4182
4686
|
await entityStore.fetchEntities({ missingAssetIds, missingEntryIds });
|
|
4183
4687
|
};
|
|
@@ -4230,8 +4734,9 @@ function useEditorSubscriber() {
|
|
|
4230
4734
|
}
|
|
4231
4735
|
let newEntityStore = entityStore;
|
|
4232
4736
|
if (entityStore.locale !== locale) {
|
|
4233
|
-
newEntityStore =
|
|
4737
|
+
newEntityStore = new EditorModeEntityStore({ locale, entities: [] });
|
|
4234
4738
|
setLocale(locale);
|
|
4739
|
+
resetEntityStore(newEntityStore);
|
|
4235
4740
|
}
|
|
4236
4741
|
// Below are mutually exclusive cases
|
|
4237
4742
|
if (changedNode) {
|
|
@@ -4761,17 +5266,49 @@ const addStylesTag = (className, styleRules) => {
|
|
|
4761
5266
|
|
|
4762
5267
|
const getUnboundValues = ({ key, fallback, unboundValues, }) => {
|
|
4763
5268
|
const lodashPath = `${key}.value`;
|
|
4764
|
-
return get$
|
|
5269
|
+
return get$2(unboundValues, lodashPath, fallback);
|
|
5270
|
+
};
|
|
5271
|
+
|
|
5272
|
+
/**
|
|
5273
|
+
* When node is a pattern block, we need to look up for default values of the pattern variables
|
|
5274
|
+
* and merge them with the updated node props.
|
|
5275
|
+
* While loop is making sure that we look up for the updated default values in the parent pattern
|
|
5276
|
+
* component settings as well.
|
|
5277
|
+
*/
|
|
5278
|
+
const maybeMergePatternDefaultDesignValues = ({ variableName, variableMapping, node, findNodeById, }) => {
|
|
5279
|
+
if (node.type === ASSEMBLY_BLOCK_NODE_TYPE) {
|
|
5280
|
+
const patternId = node.data.pattern?.id;
|
|
5281
|
+
const exposedPropertyName = node['exposedPropertyNameToKeyMap'][variableName];
|
|
5282
|
+
if (!exposedPropertyName || !patternId) {
|
|
5283
|
+
return variableMapping.valuesByBreakpoint;
|
|
5284
|
+
}
|
|
5285
|
+
const exposedVariableDefinition = componentRegistry.get(patternId)?.definition.variables[exposedPropertyName];
|
|
5286
|
+
let exposedDefaultValue = exposedVariableDefinition?.defaultValue;
|
|
5287
|
+
let parentPatternNode = findNodeById(node.data.pattern?.nodeId);
|
|
5288
|
+
while (parentPatternNode) {
|
|
5289
|
+
const parentPatternId = parentPatternNode.data.pattern?.id;
|
|
5290
|
+
const nextKey = parentPatternNode['exposedPropertyNameToKeyMap'][exposedPropertyName];
|
|
5291
|
+
if (!parentPatternId || !nextKey) {
|
|
5292
|
+
break;
|
|
5293
|
+
}
|
|
5294
|
+
const parentPatternVariableDefinition = componentRegistry.get(parentPatternId)?.definition.variables[nextKey];
|
|
5295
|
+
exposedDefaultValue = mergeDesignValuesByBreakpoint(parentPatternVariableDefinition?.defaultValue, exposedDefaultValue);
|
|
5296
|
+
parentPatternNode = findNodeById(parentPatternNode.data.pattern?.nodeId);
|
|
5297
|
+
}
|
|
5298
|
+
const mergedDesignValue = mergeDesignValuesByBreakpoint(exposedDefaultValue, variableMapping);
|
|
5299
|
+
return mergedDesignValue?.valuesByBreakpoint;
|
|
5300
|
+
}
|
|
5301
|
+
return variableMapping.valuesByBreakpoint;
|
|
4765
5302
|
};
|
|
4766
5303
|
|
|
4767
|
-
const useComponentProps = ({ node, areEntitiesFetched, resolveDesignValue, renderDropzone, definition, options, userIsDragging, requiresDragWrapper, }) => {
|
|
5304
|
+
const useComponentProps = ({ node, entityStore, areEntitiesFetched, resolveDesignValue, renderDropzone, definition, options, userIsDragging, requiresDragWrapper, }) => {
|
|
4768
5305
|
const unboundValues = useEditorStore((state) => state.unboundValues);
|
|
4769
5306
|
const hyperlinkPattern = useEditorStore((state) => state.hyperLinkPattern);
|
|
4770
5307
|
const locale = useEditorStore((state) => state.locale);
|
|
4771
5308
|
const dataSource = useEditorStore((state) => state.dataSource);
|
|
4772
|
-
const entityStore = useEntityStore((state) => state.entityStore);
|
|
4773
5309
|
const draggingId = useDraggedItemStore((state) => state.onBeforeCaptureId);
|
|
4774
5310
|
const nodeRect = useDraggedItemStore((state) => state.domRect);
|
|
5311
|
+
const findNodeById = useTreeStore((state) => state.findNodeById);
|
|
4775
5312
|
const isEmptyZone = !node.children.length;
|
|
4776
5313
|
const props = useMemo(() => {
|
|
4777
5314
|
const propsBase = {
|
|
@@ -4795,7 +5332,13 @@ const useComponentProps = ({ node, areEntitiesFetched, resolveDesignValue, rende
|
|
|
4795
5332
|
};
|
|
4796
5333
|
}
|
|
4797
5334
|
if (variableMapping.type === 'DesignValue') {
|
|
4798
|
-
const
|
|
5335
|
+
const value = maybeMergePatternDefaultDesignValues({
|
|
5336
|
+
variableName,
|
|
5337
|
+
variableMapping,
|
|
5338
|
+
node,
|
|
5339
|
+
findNodeById,
|
|
5340
|
+
});
|
|
5341
|
+
const valuesByBreakpoint = resolveDesignValue(value, variableName);
|
|
4799
5342
|
const designValue = variableName === 'cfHeight'
|
|
4800
5343
|
? calculateNodeDefaultHeight({
|
|
4801
5344
|
blockId: node.data.blockId,
|
|
@@ -4886,6 +5429,7 @@ const useComponentProps = ({ node, areEntitiesFetched, resolveDesignValue, rende
|
|
|
4886
5429
|
unboundValues,
|
|
4887
5430
|
entityStore,
|
|
4888
5431
|
renderDropzone,
|
|
5432
|
+
findNodeById,
|
|
4889
5433
|
]);
|
|
4890
5434
|
const cfStyles = useMemo(() => ({
|
|
4891
5435
|
...buildCfStyles(props),
|
|
@@ -5058,7 +5602,6 @@ const MissingComponentPlaceholder = ({ blockId }) => {
|
|
|
5058
5602
|
};
|
|
5059
5603
|
|
|
5060
5604
|
const CircularDependencyErrorPlaceholder = forwardRef(({ wrappingPatternIds, ...props }, ref) => {
|
|
5061
|
-
const entityStore = useEntityStore((state) => state.entityStore);
|
|
5062
5605
|
return (React.createElement("div", { ...props,
|
|
5063
5606
|
// Pass through ref to avoid DND errors being logged
|
|
5064
5607
|
ref: ref, "data-cf-node-error": "circular-pattern-dependency", style: {
|
|
@@ -5071,7 +5614,7 @@ const CircularDependencyErrorPlaceholder = forwardRef(({ wrappingPatternIds, ...
|
|
|
5071
5614
|
"Circular usage of patterns detected:",
|
|
5072
5615
|
React.createElement("ul", null, Array.from(wrappingPatternIds).map((patternId) => {
|
|
5073
5616
|
const entryLink = { sys: { type: 'Link', linkType: 'Entry', id: patternId } };
|
|
5074
|
-
const entry =
|
|
5617
|
+
const entry = inMemoryEntities.maybeResolveLink(entryLink);
|
|
5075
5618
|
const entryTitle = entry?.fields?.title;
|
|
5076
5619
|
const text = entryTitle ? `${entryTitle} (${patternId})` : patternId;
|
|
5077
5620
|
return React.createElement("li", { key: patternId }, text);
|
|
@@ -5079,8 +5622,7 @@ const CircularDependencyErrorPlaceholder = forwardRef(({ wrappingPatternIds, ...
|
|
|
5079
5622
|
});
|
|
5080
5623
|
CircularDependencyErrorPlaceholder.displayName = 'CircularDependencyErrorPlaceholder';
|
|
5081
5624
|
|
|
5082
|
-
const useComponent = ({ node, resolveDesignValue, renderDropzone, userIsDragging, wrappingPatternIds, }) => {
|
|
5083
|
-
const areEntitiesFetched = useEntityStore((state) => state.areEntitiesFetched);
|
|
5625
|
+
const useComponent = ({ node, entityStore, areEntitiesFetched, resolveDesignValue, renderDropzone, userIsDragging, wrappingPatternIds, }) => {
|
|
5084
5626
|
const tree = useTreeStore((state) => state.tree);
|
|
5085
5627
|
const componentRegistration = useMemo(() => {
|
|
5086
5628
|
let registration = componentRegistry.get(node.data.blockId);
|
|
@@ -5106,6 +5648,7 @@ const useComponent = ({ node, resolveDesignValue, renderDropzone, userIsDragging
|
|
|
5106
5648
|
const requiresDragWrapper = !isPatternNode && !isStructureComponent && !componentRegistration?.options?.wrapComponent;
|
|
5107
5649
|
const { componentProps, wrapperStyles } = useComponentProps({
|
|
5108
5650
|
node,
|
|
5651
|
+
entityStore,
|
|
5109
5652
|
areEntitiesFetched,
|
|
5110
5653
|
resolveDesignValue,
|
|
5111
5654
|
renderDropzone,
|
|
@@ -5580,13 +6123,15 @@ function getStyle$1(style, snapshot) {
|
|
|
5580
6123
|
transitionDuration: `0.001s`,
|
|
5581
6124
|
};
|
|
5582
6125
|
}
|
|
5583
|
-
const EditorBlock = ({ node: rawNode, resolveDesignValue, renderDropzone, index, zoneId, userIsDragging, placeholder, wrappingPatternIds, }) => {
|
|
6126
|
+
const EditorBlock = ({ node: rawNode, entityStore, areEntitiesFetched, resolveDesignValue, renderDropzone, index, zoneId, userIsDragging, placeholder, wrappingPatternIds, }) => {
|
|
5584
6127
|
const { slotId } = parseZoneId(zoneId);
|
|
5585
6128
|
const ref = useRef(null);
|
|
5586
6129
|
const setSelectedNodeId = useEditorStore((state) => state.setSelectedNodeId);
|
|
5587
6130
|
const selectedNodeId = useEditorStore((state) => state.selectedNodeId);
|
|
5588
6131
|
const { node, componentId, elementToRender, definition, isPatternNode, isPatternComponent, isNestedPattern, } = useComponent({
|
|
5589
6132
|
node: rawNode,
|
|
6133
|
+
entityStore,
|
|
6134
|
+
areEntitiesFetched,
|
|
5590
6135
|
resolveDesignValue,
|
|
5591
6136
|
renderDropzone,
|
|
5592
6137
|
userIsDragging,
|
|
@@ -5727,10 +6272,12 @@ function getStyle(style = {}, snapshot) {
|
|
|
5727
6272
|
transitionDuration: `0.001s`,
|
|
5728
6273
|
};
|
|
5729
6274
|
}
|
|
5730
|
-
const EditorBlockClone = ({ node: rawNode, resolveDesignValue, snapshot, provided, renderDropzone, wrappingPatternIds, }) => {
|
|
6275
|
+
const EditorBlockClone = ({ node: rawNode, entityStore, areEntitiesFetched, resolveDesignValue, snapshot, provided, renderDropzone, wrappingPatternIds, }) => {
|
|
5731
6276
|
const userIsDragging = useDraggedItemStore((state) => state.isDraggingOnCanvas);
|
|
5732
6277
|
const { node, elementToRender } = useComponent({
|
|
5733
6278
|
node: rawNode,
|
|
6279
|
+
entityStore,
|
|
6280
|
+
areEntitiesFetched,
|
|
5734
6281
|
resolveDesignValue,
|
|
5735
6282
|
renderDropzone,
|
|
5736
6283
|
userIsDragging,
|
|
@@ -5767,7 +6314,7 @@ const getHtmlComponentProps = (props) => {
|
|
|
5767
6314
|
return {};
|
|
5768
6315
|
};
|
|
5769
6316
|
|
|
5770
|
-
function DropzoneClone({ node, zoneId, resolveDesignValue, WrapperComponent = 'div', renderDropzone, dragProps, wrappingPatternIds, ...rest }) {
|
|
6317
|
+
function DropzoneClone({ node, entityStore, zoneId, resolveDesignValue, WrapperComponent = 'div', renderDropzone, dragProps, wrappingPatternIds, areEntitiesFetched, ...rest }) {
|
|
5771
6318
|
const tree = useTreeStore((state) => state.tree);
|
|
5772
6319
|
const content = node?.children || tree.root?.children || [];
|
|
5773
6320
|
const { slotId } = parseZoneId(zoneId);
|
|
@@ -5788,11 +6335,11 @@ function DropzoneClone({ node, zoneId, resolveDesignValue, WrapperComponent = 'd
|
|
|
5788
6335
|
.filter((node) => node.data.slotId === slotId)
|
|
5789
6336
|
.map((item) => {
|
|
5790
6337
|
const componentId = item.data.id;
|
|
5791
|
-
return (React.createElement(EditorBlockClone, { key: componentId, node: item, resolveDesignValue: resolveDesignValue, renderDropzone: renderDropzone, wrappingPatternIds: wrappingPatternIds }));
|
|
6338
|
+
return (React.createElement(EditorBlockClone, { entityStore: entityStore, areEntitiesFetched: areEntitiesFetched, key: componentId, node: item, resolveDesignValue: resolveDesignValue, renderDropzone: renderDropzone, wrappingPatternIds: wrappingPatternIds }));
|
|
5792
6339
|
})));
|
|
5793
6340
|
}
|
|
5794
6341
|
|
|
5795
|
-
function Dropzone({ node, zoneId, resolveDesignValue, className, WrapperComponent = 'div', dragProps, wrappingPatternIds: parentWrappingPatternIds = new Set(), ...rest }) {
|
|
6342
|
+
function Dropzone({ node, zoneId, resolveDesignValue, className, WrapperComponent = 'div', dragProps, entityStore, areEntitiesFetched, wrappingPatternIds: parentWrappingPatternIds = new Set(), ...rest }) {
|
|
5796
6343
|
const userIsDragging = useDraggedItemStore((state) => state.isDraggingOnCanvas);
|
|
5797
6344
|
const draggedItem = useDraggedItemStore((state) => state.draggedItem);
|
|
5798
6345
|
const isDraggingNewComponent = useDraggedItemStore((state) => Boolean(state.componentId));
|
|
@@ -5827,11 +6374,11 @@ function Dropzone({ node, zoneId, resolveDesignValue, className, WrapperComponen
|
|
|
5827
6374
|
}, [isRootAssembly, node, parentWrappingPatternIds, tree.root.data.blockId]);
|
|
5828
6375
|
// To avoid a circular dependency, we create the recursive rendering function here and trickle it down
|
|
5829
6376
|
const renderDropzone = useCallback((node, props) => {
|
|
5830
|
-
return (React.createElement(Dropzone, { zoneId: node.data.id, node: node, resolveDesignValue: resolveDesignValue, wrappingPatternIds: wrappingPatternIds, ...props }));
|
|
5831
|
-
}, [wrappingPatternIds, resolveDesignValue]);
|
|
6377
|
+
return (React.createElement(Dropzone, { zoneId: node.data.id, entityStore: entityStore, node: node, resolveDesignValue: resolveDesignValue, wrappingPatternIds: wrappingPatternIds, areEntitiesFetched: areEntitiesFetched, ...props }));
|
|
6378
|
+
}, [wrappingPatternIds, resolveDesignValue, entityStore, areEntitiesFetched]);
|
|
5832
6379
|
const renderClonedDropzone = useCallback((node, props) => {
|
|
5833
|
-
return (React.createElement(DropzoneClone, { zoneId: node.data.id, node: node, resolveDesignValue: resolveDesignValue, renderDropzone: renderClonedDropzone, wrappingPatternIds: wrappingPatternIds, ...props }));
|
|
5834
|
-
}, [resolveDesignValue, wrappingPatternIds]);
|
|
6380
|
+
return (React.createElement(DropzoneClone, { entityStore: entityStore, areEntitiesFetched: areEntitiesFetched, zoneId: node.data.id, node: node, resolveDesignValue: resolveDesignValue, renderDropzone: renderClonedDropzone, wrappingPatternIds: wrappingPatternIds, ...props }));
|
|
6381
|
+
}, [resolveDesignValue, wrappingPatternIds, entityStore, areEntitiesFetched]);
|
|
5835
6382
|
const isDropzoneEnabled = useMemo(() => {
|
|
5836
6383
|
const isColumns = node?.data.blockId === CONTENTFUL_COMPONENTS$1.columns.id;
|
|
5837
6384
|
const isDraggingSingleColumn = draggedNode?.data.blockId === CONTENTFUL_COMPONENTS$1.singleColumn.id;
|
|
@@ -5873,7 +6420,7 @@ function Dropzone({ node, zoneId, resolveDesignValue, className, WrapperComponen
|
|
|
5873
6420
|
? node.children.length === 1 &&
|
|
5874
6421
|
resolveDesignValue(node?.children[0]?.data.props.cfWidth?.valuesByBreakpoint ?? {}, 'cfWidth') === '100%'
|
|
5875
6422
|
: false;
|
|
5876
|
-
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) => {
|
|
6423
|
+
return (React.createElement(Droppable, { droppableId: zoneId, direction: direction, isDropDisabled: !isDropzoneEnabled, renderClone: (provided, snapshot, rubic) => (React.createElement(EditorBlockClone, { entityStore: entityStore, areEntitiesFetched: areEntitiesFetched, node: content[rubic.source.index], resolveDesignValue: resolveDesignValue, provided: provided, snapshot: snapshot, renderDropzone: renderClonedDropzone, wrappingPatternIds: wrappingPatternIds })) }, (provided, snapshot) => {
|
|
5877
6424
|
return (React.createElement(WrapperComponent, { ...(provided || { droppableProps: {} }).droppableProps, ...htmlDraggableProps, ...htmlProps, ref: (refNode) => {
|
|
5878
6425
|
if (dragProps?.innerRef) {
|
|
5879
6426
|
dragProps.innerRef(refNode);
|
|
@@ -5891,7 +6438,7 @@ function Dropzone({ node, zoneId, resolveDesignValue, className, WrapperComponen
|
|
|
5891
6438
|
}) },
|
|
5892
6439
|
isEmptyCanvas ? (React.createElement(EmptyContainer, { isDragging: isRootZone && userIsDragging })) : (content
|
|
5893
6440
|
.filter((node) => node.data.slotId === slotId)
|
|
5894
|
-
.map((item, i) => (React.createElement(EditorBlock, { placeholder: {
|
|
6441
|
+
.map((item, i) => (React.createElement(EditorBlock, { entityStore: entityStore, areEntitiesFetched: areEntitiesFetched, placeholder: {
|
|
5895
6442
|
isDraggingOver: snapshot?.isDraggingOver,
|
|
5896
6443
|
totalIndexes: content.length,
|
|
5897
6444
|
elementIndex: i,
|
|
@@ -5903,8 +6450,8 @@ function Dropzone({ node, zoneId, resolveDesignValue, className, WrapperComponen
|
|
|
5903
6450
|
}));
|
|
5904
6451
|
}
|
|
5905
6452
|
|
|
5906
|
-
const RootRenderer = ({ onChange }) => {
|
|
5907
|
-
useEditorSubscriber();
|
|
6453
|
+
const RootRenderer = ({ onChange, inMemoryEntitiesStore, }) => {
|
|
6454
|
+
useEditorSubscriber(inMemoryEntitiesStore);
|
|
5908
6455
|
const dragItem = useDraggedItemStore((state) => state.componentId);
|
|
5909
6456
|
const userIsDragging = useDraggedItemStore((state) => state.isDraggingOnCanvas);
|
|
5910
6457
|
const setHoveredComponentId = useDraggedItemStore((state) => state.setHoveredComponentId);
|
|
@@ -5984,28 +6531,28 @@ const RootRenderer = ({ onChange }) => {
|
|
|
5984
6531
|
handleResizeCanvas();
|
|
5985
6532
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
5986
6533
|
}, [containerRef.current]);
|
|
6534
|
+
const entityStore = inMemoryEntitiesStore((state) => state.entityStore);
|
|
6535
|
+
const areEntitiesFetched = inMemoryEntitiesStore((state) => state.areEntitiesFetched);
|
|
5987
6536
|
return (React.createElement(DNDProvider, null,
|
|
5988
6537
|
dragItem && React.createElement(DraggableContainer, { id: dragItem }),
|
|
5989
6538
|
React.createElement("div", { "data-ctfl-root": true, className: styles$3.container, ref: containerRef, style: containerStyles },
|
|
5990
6539
|
userIsDragging && React.createElement("div", { "data-ctfl-zone-id": ROOT_ID, className: styles$3.hitbox }),
|
|
5991
|
-
React.createElement(Dropzone, { zoneId: ROOT_ID, resolveDesignValue: resolveDesignValue }),
|
|
6540
|
+
React.createElement(Dropzone, { zoneId: ROOT_ID, resolveDesignValue: resolveDesignValue, entityStore: entityStore, areEntitiesFetched: areEntitiesFetched }),
|
|
5992
6541
|
userIsDragging && (React.createElement(React.Fragment, null,
|
|
5993
6542
|
React.createElement("div", { "data-ctfl-zone-id": ROOT_ID, className: styles$3.hitboxLower }),
|
|
5994
6543
|
React.createElement("div", { "data-ctfl-zone-id": ROOT_ID, className: styles$3.canvasBottomSpacer })))),
|
|
5995
6544
|
React.createElement("div", { "data-ctfl-hitboxes": true })));
|
|
5996
6545
|
};
|
|
5997
6546
|
|
|
5998
|
-
const useInitializeEditor = () => {
|
|
6547
|
+
const useInitializeEditor = (inMemoryEntitiesStore) => {
|
|
5999
6548
|
const initializeEditor = useEditorStore((state) => state.initializeEditor);
|
|
6000
6549
|
const [initialized, setInitialized] = useState(false);
|
|
6001
|
-
const resetEntityStore =
|
|
6550
|
+
const resetEntityStore = useStore(inMemoryEntitiesStore, (state) => state.resetEntityStore);
|
|
6002
6551
|
useEffect(() => {
|
|
6003
6552
|
const onVisualEditorInitialize = (event) => {
|
|
6004
6553
|
if (!event.detail)
|
|
6005
6554
|
return;
|
|
6006
|
-
const { componentRegistry, designTokens, locale: initialLocale,
|
|
6007
|
-
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
6008
|
-
entities, } = event.detail;
|
|
6555
|
+
const { componentRegistry, designTokens, locale: initialLocale, entities } = event.detail;
|
|
6009
6556
|
initializeEditor({
|
|
6010
6557
|
initialLocale,
|
|
6011
6558
|
componentRegistry,
|
|
@@ -6013,7 +6560,7 @@ const useInitializeEditor = () => {
|
|
|
6013
6560
|
});
|
|
6014
6561
|
// if entities is set to [], then everything will still work as EntityStore will
|
|
6015
6562
|
// request entities on demand via ▲REQUEST_ENTITY
|
|
6016
|
-
resetEntityStore(initialLocale, entities);
|
|
6563
|
+
resetEntityStore(new EditorModeEntityStore({ locale: initialLocale, entities }));
|
|
6017
6564
|
setInitialized(true);
|
|
6018
6565
|
};
|
|
6019
6566
|
// Listen for VisualEditorComponents internal event
|
|
@@ -6033,8 +6580,8 @@ const useInitializeEditor = () => {
|
|
|
6033
6580
|
return initialized;
|
|
6034
6581
|
};
|
|
6035
6582
|
|
|
6036
|
-
const VisualEditorRoot = ({ experience }) => {
|
|
6037
|
-
const initialized = useInitializeEditor();
|
|
6583
|
+
const VisualEditorRoot = ({ experience, inMemoryEntitiesStore: inMemoryEntitiesStore$1 = inMemoryEntitiesStore, }) => {
|
|
6584
|
+
const initialized = useInitializeEditor(inMemoryEntitiesStore$1);
|
|
6038
6585
|
const setHyperLinkPattern = useEditorStore((state) => state.setHyperLinkPattern);
|
|
6039
6586
|
const setMousePosition = useDraggedItemStore((state) => state.setMousePosition);
|
|
6040
6587
|
const setHoveringZone = useZoneStore((state) => state.setHoveringZone);
|
|
@@ -6070,7 +6617,7 @@ const VisualEditorRoot = ({ experience }) => {
|
|
|
6070
6617
|
}, [setHoveringZone, setMousePosition]);
|
|
6071
6618
|
if (!initialized)
|
|
6072
6619
|
return null;
|
|
6073
|
-
return React.createElement(RootRenderer,
|
|
6620
|
+
return React.createElement(RootRenderer, { inMemoryEntitiesStore: inMemoryEntitiesStore$1 });
|
|
6074
6621
|
};
|
|
6075
6622
|
|
|
6076
6623
|
export { VisualEditorRoot as default };
|