@contentful/experiences-core 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/constants.js +0 -8
- package/dist/constants.js.map +1 -1
- package/dist/deep-binding/DeepReference.d.ts +2 -2
- package/dist/entity/EditorModeEntityStore.d.ts +0 -1
- package/dist/entity/EntityStoreBase.d.ts +8 -3
- package/dist/entity/InMemoryEntitiesPublicApi.d.ts +32 -0
- package/dist/entity/InMemoryEntitiesStore.d.ts +17 -0
- package/dist/index.d.ts +9 -5
- package/dist/index.js +374 -129
- package/dist/index.js.map +1 -1
- package/dist/types.d.ts +4 -10
- package/dist/utils/breakpoints.d.ts +5 -2
- package/dist/utils/isLinkToAsset.d.ts +1 -1
- package/dist/utils/isLinkToEntry.d.ts +5 -0
- package/dist/utils/schema/experienceSchema.d.ts +23 -0
- package/dist/utils/schema/references.d.ts +18 -0
- package/dist/utils/typeguards.d.ts +11 -2
- package/dist/utils/utils.d.ts +1 -6
- package/package.json +3 -3
- package/dist/utils/entityTypeChecks.d.ts +0 -6
package/dist/index.js
CHANGED
|
@@ -2,6 +2,7 @@ import { z, ZodIssueCode } from 'zod';
|
|
|
2
2
|
import { omit, isArray, uniqBy } from 'lodash-es';
|
|
3
3
|
import md5 from 'md5';
|
|
4
4
|
import { BLOCKS } from '@contentful/rich-text-types';
|
|
5
|
+
import { create } from 'zustand';
|
|
5
6
|
|
|
6
7
|
const INCOMING_EVENTS = {
|
|
7
8
|
RequestEditorMode: 'requestEditorMode',
|
|
@@ -114,14 +115,6 @@ const CF_STYLE_ATTRIBUTES = [
|
|
|
114
115
|
'cfTextBold',
|
|
115
116
|
'cfTextItalic',
|
|
116
117
|
'cfTextUnderline',
|
|
117
|
-
// For backwards compatibility
|
|
118
|
-
// we need to keep those in this constant array
|
|
119
|
-
// so that omit() in <VisualEditorBlock> and <CompositionBlock>
|
|
120
|
-
// can filter them out and not pass as props
|
|
121
|
-
'cfBackgroundImageScaling',
|
|
122
|
-
'cfBackgroundImageAlignment',
|
|
123
|
-
'cfBackgroundImageAlignmentVertical',
|
|
124
|
-
'cfBackgroundImageAlignmentHorizontal',
|
|
125
118
|
];
|
|
126
119
|
const EMPTY_CONTAINER_HEIGHT = '80px';
|
|
127
120
|
const DEFAULT_IMAGE_WIDTH = '500px';
|
|
@@ -1463,6 +1456,24 @@ propertyName, resolveDesignTokens = true) => {
|
|
|
1463
1456
|
return valuesByBreakpoint;
|
|
1464
1457
|
}
|
|
1465
1458
|
};
|
|
1459
|
+
/** Overwrites the default value breakpoint by breakpoint. If a breakpoint
|
|
1460
|
+
* is not overwritten, it will fall back to the default. */
|
|
1461
|
+
function mergeDesignValuesByBreakpoint(defaultValue, overwriteValue) {
|
|
1462
|
+
if (!defaultValue || !overwriteValue) {
|
|
1463
|
+
return defaultValue ?? overwriteValue;
|
|
1464
|
+
}
|
|
1465
|
+
const mergedValuesByBreakpoint = { ...defaultValue.valuesByBreakpoint };
|
|
1466
|
+
for (const [breakpointId, value] of Object.entries(overwriteValue.valuesByBreakpoint)) {
|
|
1467
|
+
if (!isValidBreakpointValue(value)) {
|
|
1468
|
+
continue;
|
|
1469
|
+
}
|
|
1470
|
+
mergedValuesByBreakpoint[breakpointId] = value;
|
|
1471
|
+
}
|
|
1472
|
+
return {
|
|
1473
|
+
type: 'DesignValue',
|
|
1474
|
+
valuesByBreakpoint: mergedValuesByBreakpoint,
|
|
1475
|
+
};
|
|
1476
|
+
}
|
|
1466
1477
|
|
|
1467
1478
|
const CF_DEBUG_KEY = 'cf_debug';
|
|
1468
1479
|
/**
|
|
@@ -1592,11 +1603,19 @@ const getElementCoordinates = (element) => {
|
|
|
1592
1603
|
});
|
|
1593
1604
|
};
|
|
1594
1605
|
|
|
1595
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
1596
1606
|
const isLinkToAsset = (variable) => {
|
|
1597
|
-
if (
|
|
1607
|
+
if (variable === null || typeof variable !== 'object')
|
|
1608
|
+
return false;
|
|
1609
|
+
// The `'prop' in` pattern is informing TypeScript of the object shape, no need to cast `as`.
|
|
1610
|
+
if (!('sys' in variable))
|
|
1611
|
+
return false;
|
|
1612
|
+
if (variable.sys === null || typeof variable.sys !== 'object')
|
|
1613
|
+
return false;
|
|
1614
|
+
if (!('linkType' in variable.sys))
|
|
1615
|
+
return false;
|
|
1616
|
+
if (!('id' in variable.sys))
|
|
1598
1617
|
return false;
|
|
1599
|
-
if (
|
|
1618
|
+
if (!('type' in variable.sys))
|
|
1600
1619
|
return false;
|
|
1601
1620
|
return (variable.sys?.linkType === 'Asset' &&
|
|
1602
1621
|
typeof variable.sys?.id === 'string' &&
|
|
@@ -1604,13 +1623,33 @@ const isLinkToAsset = (variable) => {
|
|
|
1604
1623
|
variable.sys?.type === 'Link');
|
|
1605
1624
|
};
|
|
1606
1625
|
|
|
1626
|
+
const isLinkToEntry = (variable) => {
|
|
1627
|
+
if (variable === null || typeof variable !== 'object')
|
|
1628
|
+
return false;
|
|
1629
|
+
// The `'prop' in` pattern is informing TypeScript of the object shape, no need to cast `as`.
|
|
1630
|
+
if (!('sys' in variable))
|
|
1631
|
+
return false;
|
|
1632
|
+
if (variable.sys === null || typeof variable.sys !== 'object')
|
|
1633
|
+
return false;
|
|
1634
|
+
if (!('linkType' in variable.sys))
|
|
1635
|
+
return false;
|
|
1636
|
+
if (!('id' in variable.sys))
|
|
1637
|
+
return false;
|
|
1638
|
+
if (!('type' in variable.sys))
|
|
1639
|
+
return false;
|
|
1640
|
+
return (variable.sys?.linkType === 'Entry' &&
|
|
1641
|
+
typeof variable.sys?.id === 'string' &&
|
|
1642
|
+
!!variable.sys?.id &&
|
|
1643
|
+
variable.sys?.type === 'Link');
|
|
1644
|
+
};
|
|
1645
|
+
|
|
1607
1646
|
const isLink = (maybeLink) => {
|
|
1608
1647
|
if (maybeLink === null)
|
|
1609
1648
|
return false;
|
|
1610
1649
|
if (typeof maybeLink !== 'object')
|
|
1611
1650
|
return false;
|
|
1612
1651
|
const link = maybeLink;
|
|
1613
|
-
return Boolean(link.sys?.id) && link.sys?.type === 'Link';
|
|
1652
|
+
return Boolean(link.sys?.id) && link.sys?.type === 'Link' && Boolean(link.sys?.linkType);
|
|
1614
1653
|
};
|
|
1615
1654
|
|
|
1616
1655
|
/**
|
|
@@ -1837,11 +1876,6 @@ const transformVisibility = (value) => {
|
|
|
1837
1876
|
// Don't explicitly set anything when visible to not overwrite values like `grid` or `flex`.
|
|
1838
1877
|
return {};
|
|
1839
1878
|
};
|
|
1840
|
-
// TODO: Remove in next major version v2 since the change is 17 months old
|
|
1841
|
-
// Keep this for backwards compatibility - deleting this would be a breaking change
|
|
1842
|
-
// because existing components on a users experience will have the width value as fill
|
|
1843
|
-
// rather than 100%
|
|
1844
|
-
const transformFill = (value) => (value === 'fill' ? '100%' : value);
|
|
1845
1879
|
const transformGridColumn = (span) => {
|
|
1846
1880
|
if (!span) {
|
|
1847
1881
|
return {};
|
|
@@ -1886,34 +1920,6 @@ const transformBackgroundImage = (cfBackgroundImageUrl, cfBackgroundImageOptions
|
|
|
1886
1920
|
return;
|
|
1887
1921
|
}
|
|
1888
1922
|
let [horizontalAlignment, verticalAlignment] = alignment.trim().split(/\s+/, 2);
|
|
1889
|
-
// Special case for handling single values
|
|
1890
|
-
// for backwards compatibility with single values 'right','left', 'center', 'top','bottom'
|
|
1891
|
-
if (horizontalAlignment && !verticalAlignment) {
|
|
1892
|
-
const singleValue = horizontalAlignment;
|
|
1893
|
-
switch (singleValue) {
|
|
1894
|
-
case 'left':
|
|
1895
|
-
horizontalAlignment = 'left';
|
|
1896
|
-
verticalAlignment = 'center';
|
|
1897
|
-
break;
|
|
1898
|
-
case 'right':
|
|
1899
|
-
horizontalAlignment = 'right';
|
|
1900
|
-
verticalAlignment = 'center';
|
|
1901
|
-
break;
|
|
1902
|
-
case 'center':
|
|
1903
|
-
horizontalAlignment = 'center';
|
|
1904
|
-
verticalAlignment = 'center';
|
|
1905
|
-
break;
|
|
1906
|
-
case 'top':
|
|
1907
|
-
horizontalAlignment = 'center';
|
|
1908
|
-
verticalAlignment = 'top';
|
|
1909
|
-
break;
|
|
1910
|
-
case 'bottom':
|
|
1911
|
-
horizontalAlignment = 'center';
|
|
1912
|
-
verticalAlignment = 'bottom';
|
|
1913
|
-
break;
|
|
1914
|
-
// just fall down to the normal validation logic for horiz and vert
|
|
1915
|
-
}
|
|
1916
|
-
}
|
|
1917
1923
|
const isHorizontalValid = ['left', 'right', 'center'].includes(horizontalAlignment);
|
|
1918
1924
|
const isVerticalValid = ['top', 'bottom', 'center'].includes(verticalAlignment);
|
|
1919
1925
|
horizontalAlignment = isHorizontalValid ? horizontalAlignment : 'left';
|
|
@@ -1998,8 +2004,8 @@ const buildCfStyles = (values) => {
|
|
|
1998
2004
|
margin: values.cfMargin,
|
|
1999
2005
|
padding: values.cfPadding,
|
|
2000
2006
|
backgroundColor: values.cfBackgroundColor,
|
|
2001
|
-
width:
|
|
2002
|
-
height:
|
|
2007
|
+
width: values.cfWidth || values.cfImageOptions?.width,
|
|
2008
|
+
height: values.cfHeight || values.cfImageOptions?.height,
|
|
2003
2009
|
maxWidth: values.cfMaxWidth,
|
|
2004
2010
|
...transformGridColumn(values.cfColumnSpan),
|
|
2005
2011
|
...transformBorderStyle(values.cfBorder),
|
|
@@ -2222,7 +2228,7 @@ const detachExperienceStyles = (experience) => {
|
|
|
2222
2228
|
* {
|
|
2223
2229
|
* desktop: {
|
|
2224
2230
|
* cfMargin: '1px',
|
|
2225
|
-
* cfWidth: '
|
|
2231
|
+
* cfWidth: '100%',
|
|
2226
2232
|
* cfBackgroundImageUrl: 'https://example.com/image.jpg'
|
|
2227
2233
|
* //...
|
|
2228
2234
|
* }
|
|
@@ -2391,9 +2397,10 @@ const resolveComponentVariablesOverwrites = ({ patternNode, wrapperComponentVari
|
|
|
2391
2397
|
const overwritingValue = wrapperComponentVariablesOverwrites?.[propertyValue.key];
|
|
2392
2398
|
// Property definition from the parent pattern
|
|
2393
2399
|
const propertyDefinition = wrapperComponentSettings?.variableDefinitions?.[propertyValue.key];
|
|
2400
|
+
const defaultValue = propertyDefinition?.defaultValue;
|
|
2394
2401
|
// The overwriting value is either a custom value from the experience or default value from a
|
|
2395
2402
|
// wrapping pattern node that got trickled down to this nesting level.
|
|
2396
|
-
resolvedValues[propertyName] = overwritingValue
|
|
2403
|
+
resolvedValues[propertyName] = mergeDefaultAndOverwriteValues(defaultValue, overwritingValue);
|
|
2397
2404
|
}
|
|
2398
2405
|
else {
|
|
2399
2406
|
// Keep raw values
|
|
@@ -2476,15 +2483,15 @@ const resolveBackgroundImageBinding = ({ variableData, getBoundEntityById, dataS
|
|
|
2476
2483
|
// @ts-expect-error TODO: Types coming from validations erroneously assume that `defaultValue` can be a primitive value (e.g. string or number)
|
|
2477
2484
|
const defaultValueKey = variableDefinition.defaultValue?.key;
|
|
2478
2485
|
const defaultValue = unboundValues[defaultValueKey].value;
|
|
2479
|
-
const
|
|
2480
|
-
//
|
|
2481
|
-
if (!
|
|
2486
|
+
const overwriteValue = componentVariablesOverwrites?.[variableDefinitionKey];
|
|
2487
|
+
// overwriteValue is a ComponentValue we can safely return the default value
|
|
2488
|
+
if (!overwriteValue || overwriteValue.type === 'ComponentValue') {
|
|
2482
2489
|
return defaultValue;
|
|
2483
2490
|
}
|
|
2484
|
-
// at this point
|
|
2491
|
+
// at this point overwriteValue will either be type of 'DesignValue' or 'BoundValue'
|
|
2485
2492
|
// so we recursively run resolution again to resolve it
|
|
2486
2493
|
const resolvedValue = resolveBackgroundImageBinding({
|
|
2487
|
-
variableData:
|
|
2494
|
+
variableData: overwriteValue,
|
|
2488
2495
|
getBoundEntityById,
|
|
2489
2496
|
dataSource,
|
|
2490
2497
|
unboundValues,
|
|
@@ -2637,10 +2644,10 @@ const indexByBreakpoint = ({ variables, breakpointIds, getBoundEntityById, unbou
|
|
|
2637
2644
|
let resolvedVariableData = variableData;
|
|
2638
2645
|
if (variableData.type === 'ComponentValue') {
|
|
2639
2646
|
const variableDefinition = componentSettings?.variableDefinitions[variableData.key];
|
|
2640
|
-
|
|
2641
|
-
|
|
2642
|
-
|
|
2643
|
-
|
|
2647
|
+
const defaultValue = variableDefinition.defaultValue;
|
|
2648
|
+
if (variableDefinition.group === 'style' && defaultValue !== undefined) {
|
|
2649
|
+
const overwriteVariableData = componentVariablesOverwrites?.[variableData.key];
|
|
2650
|
+
resolvedVariableData = mergeDefaultAndOverwriteValues(defaultValue, overwriteVariableData);
|
|
2644
2651
|
}
|
|
2645
2652
|
}
|
|
2646
2653
|
if (resolvedVariableData.type !== 'DesignValue') {
|
|
@@ -2678,6 +2685,12 @@ const flattenDesignTokenRegistry = (designTokenRegistry) => {
|
|
|
2678
2685
|
};
|
|
2679
2686
|
}, {});
|
|
2680
2687
|
};
|
|
2688
|
+
function mergeDefaultAndOverwriteValues(defaultValue, overwriteValue) {
|
|
2689
|
+
if (defaultValue?.type === 'DesignValue' && overwriteValue?.type === 'DesignValue') {
|
|
2690
|
+
return mergeDesignValuesByBreakpoint(defaultValue, overwriteValue);
|
|
2691
|
+
}
|
|
2692
|
+
return overwriteValue ?? defaultValue;
|
|
2693
|
+
}
|
|
2681
2694
|
|
|
2682
2695
|
/**
|
|
2683
2696
|
* Turns a condition like `<768px` or `>1024px` into a media query rule.
|
|
@@ -2773,7 +2786,9 @@ const transformRichText = (entryOrAsset, entityStore, path) => {
|
|
|
2773
2786
|
}
|
|
2774
2787
|
if (typeof value === 'object' && value.nodeType === BLOCKS.DOCUMENT) {
|
|
2775
2788
|
// resolve any links to assets/entries/hyperlinks
|
|
2776
|
-
|
|
2789
|
+
// we need to clone, as we want to keep the original Entity in the EntityStore intact,
|
|
2790
|
+
// and resolveLinks() is mutating the node object.
|
|
2791
|
+
const richTextDocument = structuredClone(value);
|
|
2777
2792
|
resolveLinks(richTextDocument, entityStore);
|
|
2778
2793
|
return richTextDocument;
|
|
2779
2794
|
}
|
|
@@ -2887,17 +2902,37 @@ const transformMedia = (asset, variables, resolveDesignValue, variableName, path
|
|
|
2887
2902
|
return asset.fields.file?.url;
|
|
2888
2903
|
};
|
|
2889
2904
|
|
|
2890
|
-
const
|
|
2905
|
+
const isExperienceEntry = (entry) => {
|
|
2906
|
+
return (entry?.sys?.type === 'Entry' &&
|
|
2907
|
+
!!entry.fields?.title &&
|
|
2908
|
+
!!entry.fields?.slug &&
|
|
2909
|
+
!!entry.fields?.componentTree &&
|
|
2910
|
+
Array.isArray(entry.fields.componentTree.breakpoints) &&
|
|
2911
|
+
Array.isArray(entry.fields.componentTree.children) &&
|
|
2912
|
+
typeof entry.fields.componentTree.schemaVersion === 'string');
|
|
2913
|
+
};
|
|
2914
|
+
const isPatternEntry = (entry) => {
|
|
2915
|
+
return isExperienceEntry(entry) && !!entry.fields?.componentSettings; // signals that this is pattern (not experience) entry
|
|
2916
|
+
};
|
|
2917
|
+
const isEntry = (value) => {
|
|
2891
2918
|
return (null !== value &&
|
|
2892
2919
|
typeof value === 'object' &&
|
|
2893
2920
|
'sys' in value &&
|
|
2894
|
-
value.sys?.type === '
|
|
2921
|
+
value.sys?.type === 'Entry');
|
|
2895
2922
|
};
|
|
2896
|
-
const
|
|
2923
|
+
const isAsset = (value) => {
|
|
2897
2924
|
return (null !== value &&
|
|
2898
2925
|
typeof value === 'object' &&
|
|
2899
2926
|
'sys' in value &&
|
|
2900
|
-
value.sys?.type === '
|
|
2927
|
+
value.sys?.type === 'Asset');
|
|
2928
|
+
};
|
|
2929
|
+
/**
|
|
2930
|
+
* Checks if the values is an array of links.
|
|
2931
|
+
* Note: we use convention where empty arrays are considered valid "arrays of links"
|
|
2932
|
+
* as they don't contradict the type definition.
|
|
2933
|
+
*/
|
|
2934
|
+
const isArrayOfLinks = (value) => {
|
|
2935
|
+
return Array.isArray(value) && value.every((item) => isLink(item));
|
|
2901
2936
|
};
|
|
2902
2937
|
|
|
2903
2938
|
function getResolvedEntryFromLink(entryOrAsset, path, entityStore) {
|
|
@@ -2907,7 +2942,8 @@ function getResolvedEntryFromLink(entryOrAsset, path, entityStore) {
|
|
|
2907
2942
|
else if (!isEntry(entryOrAsset)) {
|
|
2908
2943
|
throw new Error(`Expected an Entry or Asset, but got: ${JSON.stringify(entryOrAsset)}`);
|
|
2909
2944
|
}
|
|
2910
|
-
const
|
|
2945
|
+
const fieldName = path.split('/').slice(2, -1);
|
|
2946
|
+
const value = get(entryOrAsset, fieldName);
|
|
2911
2947
|
let resolvedEntity;
|
|
2912
2948
|
if (isAsset(value) || isEntry(value)) {
|
|
2913
2949
|
// In some cases, reference fields are already resolved
|
|
@@ -2916,74 +2952,67 @@ function getResolvedEntryFromLink(entryOrAsset, path, entityStore) {
|
|
|
2916
2952
|
else if (value?.sys.type === 'Link') {
|
|
2917
2953
|
// Look up the reference in the entity store
|
|
2918
2954
|
resolvedEntity = entityStore.getEntityFromLink(value);
|
|
2919
|
-
if (!resolvedEntity) {
|
|
2920
|
-
return;
|
|
2921
|
-
}
|
|
2922
2955
|
}
|
|
2923
2956
|
else {
|
|
2924
|
-
console.warn(`
|
|
2957
|
+
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 });
|
|
2958
|
+
return;
|
|
2959
|
+
}
|
|
2960
|
+
// no need to make structuredClone(entityStore.getEntityFromLink(value)) because
|
|
2961
|
+
// we provide component with the original Object.frozen object of the entity.
|
|
2962
|
+
// As we don't resolve L3 and don't mutate the entity before returning anymore,
|
|
2963
|
+
// we don't need to make a copy of the entity. And even provide better referential integrity
|
|
2964
|
+
// for the component for the same entity.
|
|
2965
|
+
if (!resolvedEntity) {
|
|
2925
2966
|
return;
|
|
2926
2967
|
}
|
|
2927
|
-
//resolve any embedded links - we currently only support 2 levels deep
|
|
2928
|
-
const fields = resolvedEntity.fields || {};
|
|
2929
|
-
Object.entries(fields).forEach(([fieldKey, field]) => {
|
|
2930
|
-
if (field && field.sys?.type === 'Link') {
|
|
2931
|
-
const entity = entityStore.getEntityFromLink(field);
|
|
2932
|
-
if (entity) {
|
|
2933
|
-
resolvedEntity.fields[fieldKey] = entity;
|
|
2934
|
-
}
|
|
2935
|
-
}
|
|
2936
|
-
else if (field && Array.isArray(field)) {
|
|
2937
|
-
resolvedEntity.fields[fieldKey] = field.map((innerField) => {
|
|
2938
|
-
if (innerField && innerField.sys?.type === 'Link') {
|
|
2939
|
-
const entity = entityStore.getEntityFromLink(innerField);
|
|
2940
|
-
if (entity) {
|
|
2941
|
-
return entity;
|
|
2942
|
-
}
|
|
2943
|
-
}
|
|
2944
|
-
return innerField;
|
|
2945
|
-
});
|
|
2946
|
-
}
|
|
2947
|
-
});
|
|
2948
2968
|
return resolvedEntity;
|
|
2949
2969
|
}
|
|
2950
2970
|
|
|
2971
|
+
const excludeUndefined = (value) => {
|
|
2972
|
+
return value !== undefined;
|
|
2973
|
+
};
|
|
2951
2974
|
function getArrayValue(entryOrAsset, path, entityStore) {
|
|
2975
|
+
// NOTE: Not sure if we need this if-statement,
|
|
2976
|
+
// as it is NOT possible to bind to Array variable an Asset
|
|
2977
|
+
// (as Assets don't have multi-reference fields) unless it's a degenerate case.
|
|
2952
2978
|
if (entryOrAsset.sys.type === 'Asset') {
|
|
2953
2979
|
return entryOrAsset;
|
|
2954
2980
|
}
|
|
2955
|
-
const
|
|
2981
|
+
const fieldName = path.split('/').slice(2, -1);
|
|
2982
|
+
const arrayValue = get(entryOrAsset, fieldName);
|
|
2956
2983
|
if (!isArray(arrayValue)) {
|
|
2957
|
-
console.warn(`Expected
|
|
2984
|
+
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 });
|
|
2958
2985
|
return;
|
|
2959
2986
|
}
|
|
2960
|
-
const result = arrayValue
|
|
2987
|
+
const result = arrayValue
|
|
2988
|
+
.map((value) => {
|
|
2961
2989
|
if (typeof value === 'string') {
|
|
2962
|
-
return value;
|
|
2990
|
+
return value; // handles case where Text array is bound (in [Content Model] tab of the platform, select Text and make it a list)
|
|
2963
2991
|
}
|
|
2964
2992
|
else if (value?.sys?.type === 'Link') {
|
|
2965
2993
|
const resolvedEntity = entityStore.getEntityFromLink(value);
|
|
2966
2994
|
if (!resolvedEntity) {
|
|
2995
|
+
// We return undefined, which means that entity wasn't availble in the Entity Store due to:
|
|
2996
|
+
// - because it's archived entity (and they normally wouldn't be sent to the Entity Store)
|
|
2997
|
+
// - bug where some entity wasn't added to the Entity Store
|
|
2998
|
+
// 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)
|
|
2967
2999
|
return;
|
|
2968
3000
|
}
|
|
2969
|
-
//resolve any embedded links - we currently only support 2 levels deep
|
|
2970
|
-
const fields = resolvedEntity.fields || {};
|
|
2971
|
-
Object.entries(fields).forEach(([fieldKey, field]) => {
|
|
2972
|
-
if (field && field.sys?.type === 'Link') {
|
|
2973
|
-
const entity = entityStore.getEntityFromLink(field);
|
|
2974
|
-
if (entity) {
|
|
2975
|
-
resolvedEntity.fields[fieldKey] = entity;
|
|
2976
|
-
}
|
|
2977
|
-
}
|
|
2978
|
-
});
|
|
2979
3001
|
return resolvedEntity;
|
|
2980
3002
|
}
|
|
2981
3003
|
else {
|
|
2982
3004
|
console.warn(`Expected value to be a string or Link, but got: ${JSON.stringify(value)}`);
|
|
2983
3005
|
return undefined;
|
|
2984
3006
|
}
|
|
2985
|
-
})
|
|
2986
|
-
|
|
3007
|
+
})
|
|
3008
|
+
.filter(excludeUndefined);
|
|
3009
|
+
// eg. imagine you have multi-referene field with 3 links to archived entries,
|
|
3010
|
+
// all of them will be undefined on previous step and will be filtered out
|
|
3011
|
+
// of resultWithoutUndefined. Instead of passing to component an empty array,
|
|
3012
|
+
// we pass undefined. This means that develloper making custom component
|
|
3013
|
+
// does not have to handle empty array case. But only undefiened, which signals:
|
|
3014
|
+
// user didn't bind anything; user bound to reference field which is unset; all references are archived
|
|
3015
|
+
return result.length > 0 ? result : undefined;
|
|
2987
3016
|
}
|
|
2988
3017
|
|
|
2989
3018
|
const transformBoundContentValue = (variables, entityStore, binding, resolveDesignValue, variableName, variableType, path) => {
|
|
@@ -3044,16 +3073,6 @@ function treeMap(node, onNode) {
|
|
|
3044
3073
|
return newNode;
|
|
3045
3074
|
}
|
|
3046
3075
|
|
|
3047
|
-
const isExperienceEntry = (entry) => {
|
|
3048
|
-
return (entry?.sys?.type === 'Entry' &&
|
|
3049
|
-
!!entry.fields?.title &&
|
|
3050
|
-
!!entry.fields?.slug &&
|
|
3051
|
-
!!entry.fields?.componentTree &&
|
|
3052
|
-
Array.isArray(entry.fields.componentTree.breakpoints) &&
|
|
3053
|
-
Array.isArray(entry.fields.componentTree.children) &&
|
|
3054
|
-
typeof entry.fields.componentTree.schemaVersion === 'string');
|
|
3055
|
-
};
|
|
3056
|
-
|
|
3057
3076
|
const getDataFromTree = (tree) => {
|
|
3058
3077
|
let dataSource = {};
|
|
3059
3078
|
let unboundValues = {};
|
|
@@ -3128,8 +3147,6 @@ const checkIsAssemblyNode = ({ componentId, usedComponents, }) => {
|
|
|
3128
3147
|
return false;
|
|
3129
3148
|
return usedComponents.some((usedComponent) => usedComponent.sys.id === componentId);
|
|
3130
3149
|
};
|
|
3131
|
-
/** @deprecated use `checkIsAssemblyNode` instead. Will be removed with SDK v5. */
|
|
3132
|
-
const checkIsAssembly = checkIsAssemblyNode;
|
|
3133
3150
|
/**
|
|
3134
3151
|
* This check assumes that the entry is already ensured to be an experience, i.e. the
|
|
3135
3152
|
* content type of the entry is an experience type with the necessary annotations.
|
|
@@ -3227,6 +3244,124 @@ const validateExperienceBuilderConfig = ({ locale, mode, }) => {
|
|
|
3227
3244
|
}
|
|
3228
3245
|
};
|
|
3229
3246
|
|
|
3247
|
+
const uniqueById = (arr) => {
|
|
3248
|
+
const map = new Map();
|
|
3249
|
+
arr.forEach((item) => map.set(item.sys.id, item));
|
|
3250
|
+
return [...map.values()];
|
|
3251
|
+
};
|
|
3252
|
+
const isObject = (value) => {
|
|
3253
|
+
return typeof value === 'object' && value !== null;
|
|
3254
|
+
};
|
|
3255
|
+
/**
|
|
3256
|
+
* Extracts all references from an entry.
|
|
3257
|
+
* Handles both: reference and multi-reference fields.
|
|
3258
|
+
* Returns unique array of references (even if they repeat within the entry).
|
|
3259
|
+
*/
|
|
3260
|
+
const referencesOf = (entry, fnShouldFollowReferencesOfEntryField) => {
|
|
3261
|
+
const references = [];
|
|
3262
|
+
const handleArray = (fieldValue, _fieldName) => {
|
|
3263
|
+
for (const item of fieldValue) {
|
|
3264
|
+
if (isObject(item) && item.sys?.type === 'Link') {
|
|
3265
|
+
references.push(item);
|
|
3266
|
+
}
|
|
3267
|
+
}
|
|
3268
|
+
};
|
|
3269
|
+
const handleLink = (fieldValue, _fieldName) => {
|
|
3270
|
+
references.push(fieldValue);
|
|
3271
|
+
};
|
|
3272
|
+
for (const [fieldName, fieldValue] of Object.entries(entry.fields)) {
|
|
3273
|
+
if (fnShouldFollowReferencesOfEntryField &&
|
|
3274
|
+
!fnShouldFollowReferencesOfEntryField(fieldName, entry)) {
|
|
3275
|
+
continue;
|
|
3276
|
+
}
|
|
3277
|
+
if (fieldValue === undefined) {
|
|
3278
|
+
continue; // edge case when field is present on object, but is set to undefined explicitly e.g. during test mocking { myField: undefined }
|
|
3279
|
+
}
|
|
3280
|
+
if (Array.isArray(fieldValue)) {
|
|
3281
|
+
handleArray(fieldValue);
|
|
3282
|
+
}
|
|
3283
|
+
else if (fieldValue !== null &&
|
|
3284
|
+
isObject(fieldValue) &&
|
|
3285
|
+
fieldValue.sys?.type === 'Link') {
|
|
3286
|
+
handleLink(fieldValue);
|
|
3287
|
+
}
|
|
3288
|
+
}
|
|
3289
|
+
return uniqueById(references);
|
|
3290
|
+
};
|
|
3291
|
+
// -- REFERENCE EXTRACTION UTILITIES --
|
|
3292
|
+
function extractReferencesFromEntriesAsIds(entries) {
|
|
3293
|
+
const [uniqueEntries, uniqueAssets, uniqueReferences] = extractReferencesFromEntries(entries);
|
|
3294
|
+
const entryIds = uniqueEntries.map((link) => link.sys.id);
|
|
3295
|
+
const assetIds = uniqueAssets.map((link) => link.sys.id);
|
|
3296
|
+
const referenceIds = uniqueReferences.map((link) => link.sys.id);
|
|
3297
|
+
return [entryIds, assetIds, referenceIds];
|
|
3298
|
+
}
|
|
3299
|
+
function extractReferencesFromEntries(entries) {
|
|
3300
|
+
const allReferences = entries.flatMap((entry) => referencesOf(entry));
|
|
3301
|
+
const uniqueReferences = uniqueById(allReferences);
|
|
3302
|
+
const uniqueAssets = uniqueReferences.filter((link) => link.sys.linkType === 'Asset');
|
|
3303
|
+
const uniqueEntries = uniqueReferences.filter((link) => link.sys.linkType === 'Entry');
|
|
3304
|
+
return [uniqueEntries, uniqueAssets, uniqueReferences];
|
|
3305
|
+
}
|
|
3306
|
+
|
|
3307
|
+
const excludeAssets = (entity) => !isAsset(entity);
|
|
3308
|
+
const excludePatternEntries = (entry) => !isPatternEntry(entry);
|
|
3309
|
+
/**
|
|
3310
|
+
* Parses experience and extracts all leaf links that are referenced from the experience.
|
|
3311
|
+
* PRECONDITION: Relies on the fact that entityStore is preloaded with all dataSource
|
|
3312
|
+
* entries using include=2 (meaning that up to L3 entries are already preloaded into EntitStore).
|
|
3313
|
+
*
|
|
3314
|
+
* The function iterates over all entries in the entityStore (assuming they can be L1, L2, L3) and
|
|
3315
|
+
* over all of their references. Any references that are NOT available in the entityStore are considered
|
|
3316
|
+
* "leaf references" aka "leaf links" and are returned.
|
|
3317
|
+
*
|
|
3318
|
+
* The EntityStore happens to contain also entities representing patterns, which we do NOT consider
|
|
3319
|
+
* as entries that point to leaf links. So we don't iterate over patterns only over entries which
|
|
3320
|
+
* can be used for binding.
|
|
3321
|
+
*/
|
|
3322
|
+
const extractLeafLinksReferencedFromExperience = (experience) => {
|
|
3323
|
+
const assetLinks = [];
|
|
3324
|
+
const entryLinks = [];
|
|
3325
|
+
if (!experience.entityStore) {
|
|
3326
|
+
throw new Error('Parameter `experience` should have valid `experience.entityStore` object. Without it, we cannot extract leaf links. Most likely you passed `experience` instance that was not fully fetched. Check your experience fetching logic.');
|
|
3327
|
+
}
|
|
3328
|
+
// We want only leaf links which can be used for binding. We use two filters:
|
|
3329
|
+
// excludeAssets: because assets do not have references, so we don't need to traverse them
|
|
3330
|
+
// excludePatternEntries: because EntityStore happens to also store pattern-entries.
|
|
3331
|
+
// Those point to other patterns, and we don't want to consider them as
|
|
3332
|
+
// parents of leaf links pointing to actual data carrying entries used for binding.
|
|
3333
|
+
const entries = experience.entityStore.entities
|
|
3334
|
+
.filter(excludeAssets)
|
|
3335
|
+
.filter(excludePatternEntries);
|
|
3336
|
+
// We assume that ALL of the entries in the experience
|
|
3337
|
+
for (const entry of entries) {
|
|
3338
|
+
const references = referencesOf(entry);
|
|
3339
|
+
for (const ref of references) {
|
|
3340
|
+
if (isLinkToAsset(ref)) {
|
|
3341
|
+
if (!experience.entityStore.getEntityFromLink(ref)) {
|
|
3342
|
+
assetLinks.push(ref);
|
|
3343
|
+
}
|
|
3344
|
+
}
|
|
3345
|
+
else if (isLinkToEntry(ref)) {
|
|
3346
|
+
if (!experience.entityStore.getEntityFromLink(ref)) {
|
|
3347
|
+
entryLinks.push(ref);
|
|
3348
|
+
}
|
|
3349
|
+
}
|
|
3350
|
+
else {
|
|
3351
|
+
console.warn(`Unexpected reference type found in entry "${entry.sys.id}": ${JSON.stringify(ref)}`);
|
|
3352
|
+
}
|
|
3353
|
+
}
|
|
3354
|
+
}
|
|
3355
|
+
const dedupedAssetLinks = uniqueById(assetLinks);
|
|
3356
|
+
const dedupedEntryLinks = uniqueById(entryLinks);
|
|
3357
|
+
return {
|
|
3358
|
+
assetLinks: dedupedAssetLinks,
|
|
3359
|
+
entryLinks: dedupedEntryLinks,
|
|
3360
|
+
assetIds: dedupedAssetLinks.map((link) => link.sys.id),
|
|
3361
|
+
entryIds: dedupedEntryLinks.map((link) => link.sys.id),
|
|
3362
|
+
};
|
|
3363
|
+
};
|
|
3364
|
+
|
|
3230
3365
|
const sendMessage = (eventType, data) => {
|
|
3231
3366
|
if (typeof window === 'undefined') {
|
|
3232
3367
|
return;
|
|
@@ -3243,6 +3378,17 @@ const sendMessage = (eventType, data) => {
|
|
|
3243
3378
|
}, '*');
|
|
3244
3379
|
};
|
|
3245
3380
|
|
|
3381
|
+
function deepFreeze(obj) {
|
|
3382
|
+
const propNames = Object.getOwnPropertyNames(obj);
|
|
3383
|
+
for (const name of propNames) {
|
|
3384
|
+
const value = obj[name];
|
|
3385
|
+
if (value && typeof value === 'object') {
|
|
3386
|
+
deepFreeze(value);
|
|
3387
|
+
}
|
|
3388
|
+
}
|
|
3389
|
+
return Object.freeze(obj);
|
|
3390
|
+
}
|
|
3391
|
+
|
|
3246
3392
|
/**
|
|
3247
3393
|
* Base Store for entities
|
|
3248
3394
|
* Can be extended for the different loading behaviours (editor, production, ..)
|
|
@@ -3311,6 +3457,22 @@ class EntityStoreBase {
|
|
|
3311
3457
|
}
|
|
3312
3458
|
return resolvedEntity;
|
|
3313
3459
|
}
|
|
3460
|
+
getAssetById(assetId) {
|
|
3461
|
+
const asset = this.assetMap.get(assetId);
|
|
3462
|
+
if (!asset) {
|
|
3463
|
+
console.warn(`Asset with ID "${assetId}" is not found in the store`);
|
|
3464
|
+
return;
|
|
3465
|
+
}
|
|
3466
|
+
return asset;
|
|
3467
|
+
}
|
|
3468
|
+
getEntryById(entryId) {
|
|
3469
|
+
const entry = this.entryMap.get(entryId);
|
|
3470
|
+
if (!entry) {
|
|
3471
|
+
console.warn(`Entry with ID "${entryId}" is not found in the store`);
|
|
3472
|
+
return;
|
|
3473
|
+
}
|
|
3474
|
+
return entry;
|
|
3475
|
+
}
|
|
3314
3476
|
getEntitiesFromMap(type, ids) {
|
|
3315
3477
|
const resolved = [];
|
|
3316
3478
|
const missing = [];
|
|
@@ -3330,10 +3492,12 @@ class EntityStoreBase {
|
|
|
3330
3492
|
}
|
|
3331
3493
|
addEntity(entity) {
|
|
3332
3494
|
if (isAsset(entity)) {
|
|
3333
|
-
|
|
3495
|
+
// cloned and frozen
|
|
3496
|
+
this.assetMap.set(entity.sys.id, deepFreeze(structuredClone(entity)));
|
|
3334
3497
|
}
|
|
3335
3498
|
else if (isEntry(entity)) {
|
|
3336
|
-
|
|
3499
|
+
// cloned and frozen
|
|
3500
|
+
this.entryMap.set(entity.sys.id, deepFreeze(structuredClone(entity)));
|
|
3337
3501
|
}
|
|
3338
3502
|
else {
|
|
3339
3503
|
throw new Error(`Attempted to add an entity to the store that is neither Asset nor Entry: '${JSON.stringify(entity)}'`);
|
|
@@ -3598,7 +3762,6 @@ class EditorModeEntityStore extends EditorEntityStore {
|
|
|
3598
3762
|
};
|
|
3599
3763
|
};
|
|
3600
3764
|
super({ entities, sendMessage, subscribe, locale, timeoutDuration: REQUEST_TIMEOUT });
|
|
3601
|
-
this.locale = locale;
|
|
3602
3765
|
}
|
|
3603
3766
|
/**
|
|
3604
3767
|
* This function collects and returns the list of requested entries and assets. Additionally, it checks
|
|
@@ -3826,6 +3989,89 @@ class EntityStore extends EntityStoreBase {
|
|
|
3826
3989
|
}
|
|
3827
3990
|
}
|
|
3828
3991
|
|
|
3992
|
+
class UninitializedEntityStore extends EntityStoreBase {
|
|
3993
|
+
constructor() {
|
|
3994
|
+
super({ entities: [], locale: 'uninitialized-locale-in-uninitialized-entity-store' });
|
|
3995
|
+
}
|
|
3996
|
+
}
|
|
3997
|
+
|
|
3998
|
+
const inMemoryEntitiesStore = create((set, get) => ({
|
|
3999
|
+
// The UninitializedEntityStore is a placeholder instance and is here to highlight the
|
|
4000
|
+
// // fact that it's not used by anything until during loading lifecycle it'sreplaced by real entity store:
|
|
4001
|
+
// - in Preview+Delivery mode: right after we fetch Expereince and it entities
|
|
4002
|
+
// - in EDITOR (VisualEditor) mode: right after the VisualEditor is async imported and initialize event happens
|
|
4003
|
+
entityStore: new UninitializedEntityStore(),
|
|
4004
|
+
areEntitiesFetched: false,
|
|
4005
|
+
setEntitiesFetched(fetched) {
|
|
4006
|
+
set({ areEntitiesFetched: fetched });
|
|
4007
|
+
},
|
|
4008
|
+
resolveAssetById(assetId) {
|
|
4009
|
+
if (!assetId)
|
|
4010
|
+
return undefined;
|
|
4011
|
+
const { entityStore } = get();
|
|
4012
|
+
return entityStore.getAssetById(assetId);
|
|
4013
|
+
},
|
|
4014
|
+
resolveEntryById(entryId) {
|
|
4015
|
+
if (!entryId)
|
|
4016
|
+
return undefined;
|
|
4017
|
+
const { entityStore } = get();
|
|
4018
|
+
return entityStore.getEntryById(entryId);
|
|
4019
|
+
},
|
|
4020
|
+
resolveEntity(link) {
|
|
4021
|
+
if (!link)
|
|
4022
|
+
return undefined;
|
|
4023
|
+
const { entityStore } = get();
|
|
4024
|
+
return entityStore.getEntityFromLink(link);
|
|
4025
|
+
},
|
|
4026
|
+
resetEntityStore(entityStore) {
|
|
4027
|
+
set({
|
|
4028
|
+
entityStore,
|
|
4029
|
+
areEntitiesFetched: false,
|
|
4030
|
+
});
|
|
4031
|
+
},
|
|
4032
|
+
}));
|
|
4033
|
+
|
|
4034
|
+
function maybeResolveLink(maybeLink) {
|
|
4035
|
+
if (!isLink(maybeLink)) {
|
|
4036
|
+
console.warn('maybeResolveLink function must receive Link shape. Provided argument does not match the Link shape: ', maybeLink);
|
|
4037
|
+
return undefined;
|
|
4038
|
+
}
|
|
4039
|
+
return inMemoryEntitiesStore.getState().resolveEntity(maybeLink);
|
|
4040
|
+
}
|
|
4041
|
+
function maybeResolveByAssetId(assetId) {
|
|
4042
|
+
return inMemoryEntitiesStore.getState().resolveAssetById(assetId);
|
|
4043
|
+
}
|
|
4044
|
+
function maybeResolveByEntryId(entryId) {
|
|
4045
|
+
return inMemoryEntitiesStore.getState().resolveEntryById(entryId);
|
|
4046
|
+
}
|
|
4047
|
+
function hasEntry(entryId) {
|
|
4048
|
+
return Boolean(maybeResolveByEntryId(entryId));
|
|
4049
|
+
}
|
|
4050
|
+
function hasAsset(assetId) {
|
|
4051
|
+
return Boolean(maybeResolveByAssetId(assetId));
|
|
4052
|
+
}
|
|
4053
|
+
function addEntities(entities) {
|
|
4054
|
+
if (!Array.isArray(entities) || entities.length === 0) {
|
|
4055
|
+
return;
|
|
4056
|
+
}
|
|
4057
|
+
const { entityStore } = inMemoryEntitiesStore.getState();
|
|
4058
|
+
const definedEntities = entities.filter(Boolean);
|
|
4059
|
+
for (const entity of definedEntities) {
|
|
4060
|
+
entityStore.updateEntity(entity);
|
|
4061
|
+
}
|
|
4062
|
+
}
|
|
4063
|
+
const inMemoryEntities = {
|
|
4064
|
+
maybeResolveLink,
|
|
4065
|
+
maybeResolveByAssetId,
|
|
4066
|
+
maybeResolveByEntryId,
|
|
4067
|
+
hasEntry,
|
|
4068
|
+
hasAsset,
|
|
4069
|
+
addEntities,
|
|
4070
|
+
};
|
|
4071
|
+
const useInMemoryEntities = () => {
|
|
4072
|
+
return inMemoryEntities;
|
|
4073
|
+
};
|
|
4074
|
+
|
|
3829
4075
|
var VisualEditorMode;
|
|
3830
4076
|
(function (VisualEditorMode) {
|
|
3831
4077
|
VisualEditorMode["LazyLoad"] = "lazyLoad";
|
|
@@ -3833,11 +4079,9 @@ var VisualEditorMode;
|
|
|
3833
4079
|
})(VisualEditorMode || (VisualEditorMode = {}));
|
|
3834
4080
|
|
|
3835
4081
|
function createExperience(options) {
|
|
4082
|
+
let entityStore;
|
|
3836
4083
|
if (typeof options === 'string') {
|
|
3837
|
-
|
|
3838
|
-
return {
|
|
3839
|
-
entityStore,
|
|
3840
|
-
};
|
|
4084
|
+
entityStore = new EntityStore(options);
|
|
3841
4085
|
}
|
|
3842
4086
|
else {
|
|
3843
4087
|
const { experienceEntry, referencedAssets, referencedEntries, locale } = options;
|
|
@@ -3847,15 +4091,16 @@ function createExperience(options) {
|
|
|
3847
4091
|
if (!isExperienceEntry(experienceEntry)) {
|
|
3848
4092
|
throw new Error('Provided entry is not an experience entry');
|
|
3849
4093
|
}
|
|
3850
|
-
|
|
4094
|
+
entityStore = new EntityStore({
|
|
3851
4095
|
experienceEntry,
|
|
3852
4096
|
entities: [...referencedEntries, ...referencedAssets],
|
|
3853
4097
|
locale,
|
|
3854
4098
|
});
|
|
3855
|
-
return {
|
|
3856
|
-
entityStore,
|
|
3857
|
-
};
|
|
3858
4099
|
}
|
|
4100
|
+
inMemoryEntitiesStore.getState().resetEntityStore(entityStore);
|
|
4101
|
+
return {
|
|
4102
|
+
entityStore,
|
|
4103
|
+
};
|
|
3859
4104
|
}
|
|
3860
4105
|
// Following the API shape, we check the `sys.locale` property as we can't rely on the shape of
|
|
3861
4106
|
// fields to determine whether it's localized or not.
|
|
@@ -4449,5 +4694,5 @@ async function fetchById({ client, experienceTypeId, id, localeCode, isEditorMod
|
|
|
4449
4694
|
}
|
|
4450
4695
|
}
|
|
4451
4696
|
|
|
4452
|
-
export { DebugLogger, DeepReference, EditorModeEntityStore, EntityStore, EntityStoreBase, MEDIA_QUERY_REGEXP, VisualEditorMode, addLocale, addMinHeightForEmptyStructures, breakpointsRegistry, buildCfStyles, buildStyleTag, buildTemplate, builtInStyles, calculateNodeDefaultHeight,
|
|
4697
|
+
export { DebugLogger, DeepReference, EditorModeEntityStore, EntityStore, EntityStoreBase, MEDIA_QUERY_REGEXP, VisualEditorMode, addLocale, addMinHeightForEmptyStructures, breakpointsRegistry, buildCfStyles, buildStyleTag, buildTemplate, builtInStyles, calculateNodeDefaultHeight, checkIsAssemblyDefinition, checkIsAssemblyEntry, checkIsAssemblyNode, columnsBuiltInStyles, containerBuiltInStyles, createExperience, debug, defineBreakpoints, defineDesignTokens, designTokensRegistry, detachExperienceStyles, disableDebug, dividerBuiltInStyles, doesMismatchMessageSchema, enableDebug, extractLeafLinksReferencedFromExperience, extractReferencesFromEntries, extractReferencesFromEntriesAsIds, fetchAllAssets, fetchAllEntries, fetchById, fetchBySlug, fetchExperienceEntry, fetchReferencedEntities, findOutermostCoordinates, flattenDesignTokenRegistry, gatherDeepReferencesFromExperienceEntry, gatherDeepReferencesFromTree, generateRandomId, getActiveBreakpointIndex, getBreakpointRegistration, getDataFromTree, getDesignTokenRegistration, getElementCoordinates, getFallbackBreakpointIndex, getInsertionData, getTargetValueInPixels, getTemplateValue, getValueForBreakpoint, inMemoryEntities, inMemoryEntitiesStore, indexByBreakpoint, isArrayOfLinks, isAsset, isCfStyleAttribute, isComponentAllowedOnRoot, isContentfulComponent, isContentfulStructureComponent, isDeepPath, isEntry, isExperienceEntry, isLink, isLinkToAsset, isLinkToEntry, isPatternComponent, isPatternEntry, isStructureWithRelativeHeight, isValidBreakpointValue, lastPathNamedSegmentEq, localizeEntity, maybePopulateDesignTokenValue, mediaQueryMatcher, mergeDesignValuesByBreakpoint, optionalBuiltInStyles, parseCSSValue, parseDataSourcePathIntoFieldset, parseDataSourcePathWithL1DeepBindings, referencesOf, resetBreakpointsRegistry, resetDesignTokenRegistry, resolveBackgroundImageBinding, resolveHyperlinkPattern, runBreakpointsValidation, sanitizeNodeProps, sectionBuiltInStyles, sendMessage, singleColumnBuiltInStyles, stringifyCssProperties, toCSSAttribute, toMediaQuery, transformBoundContentValue, transformVisibility, treeMap, treeVisit, tryParseMessage, uniqueById, useInMemoryEntities, validateExperienceBuilderConfig };
|
|
4453
4698
|
//# sourceMappingURL=index.js.map
|