@contentful/experiences-visual-editor-react 0.0.1-alpha.6 → 0.0.1-alpha.8
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.js +414 -251
- package/dist/index.js.map +1 -1
- package/dist/renderApp.js +574 -363
- package/dist/renderApp.js.map +1 -1
- package/package.json +4 -4
package/dist/index.js
CHANGED
|
@@ -11,8 +11,8 @@ import { produce } from 'immer';
|
|
|
11
11
|
import { createPortal } from 'react-dom';
|
|
12
12
|
import { v4 } from 'uuid';
|
|
13
13
|
|
|
14
|
-
var css_248z$
|
|
15
|
-
styleInject(css_248z$
|
|
14
|
+
var css_248z$8 = "html,\nbody {\n margin: 0;\n padding: 0;\n}\n\n/*\n * All of these variables are tokens from Forma-36 and should not be adjusted as these\n * are global variables that may affect multiple places.\n * As our customers may use other design libraries, we try to avoid overlapping global\n * variables by always using the prefix `--exp-builder-` inside this SDK.\n */\n\n:root {\n /* Color tokens from Forma 36: https://f36.contentful.com/tokens/color-system */\n --exp-builder-blue100: #e8f5ff;\n --exp-builder-blue200: #ceecff;\n --exp-builder-blue300: #98cbff;\n --exp-builder-blue400: #40a0ff;\n --exp-builder-blue500: #036fe3;\n --exp-builder-blue600: #0059c8;\n --exp-builder-blue700: #0041ab;\n --exp-builder-blue800: #003298;\n --exp-builder-blue900: #002a8e;\n --exp-builder-gray100: #f7f9fa;\n --exp-builder-gray200: #e7ebee;\n --exp-builder-gray300: #cfd9e0;\n --exp-builder-gray400: #aec1cc;\n --exp-builder-gray500: #67728a;\n --exp-builder-gray600: #5a657c;\n --exp-builder-gray700: #414d63;\n --exp-builder-gray800: #1b273a;\n --exp-builder-gray900: #111b2b;\n --exp-builder-purple600: #6c3ecf;\n --exp-builder-red200: #ffe0e0;\n --exp-builder-red800: #7f0010;\n --exp-builder-color-white: #ffffff;\n --exp-builder-glow-primary: 0px 0px 0px 3px #e8f5ff;\n\n /* RGB colors for applying opacity */\n --exp-builder-blue100-rgb: 232, 245, 255;\n --exp-builder-blue300-rgb: 152, 203, 255;\n\n /* Spacing tokens from Forma 36: https://f36.contentful.com/tokens/spacing */\n --exp-builder-spacing-s: 0.75rem;\n --exp-builder-spacing-2xs: 0.25rem;\n\n /* Typography tokens from Forma 36: https://f36.contentful.com/tokens/typography */\n --exp-builder-font-size-l: 1rem;\n --exp-builder-font-size-m: 0.875rem;\n --exp-builder-font-stack-primary: -apple-system, BlinkMacSystemFont, Segoe UI, Helvetica, Arial,\n sans-serif, Apple Color Emoji, Segoe UI Emoji, Segoe UI Symbol;\n --exp-builder-line-height-condensed: 1.25;\n}\n";
|
|
15
|
+
styleInject(css_248z$8);
|
|
16
16
|
|
|
17
17
|
const INCOMING_EVENTS$1 = {
|
|
18
18
|
RequestEditorMode: 'requestEditorMode',
|
|
@@ -70,11 +70,13 @@ const CONTENTFUL_COMPONENTS$1 = {
|
|
|
70
70
|
},
|
|
71
71
|
};
|
|
72
72
|
const EMPTY_CONTAINER_HEIGHT$1 = '80px';
|
|
73
|
+
const DEFAULT_IMAGE_WIDTH = '500px';
|
|
73
74
|
var PostMessageMethods$2;
|
|
74
75
|
(function (PostMessageMethods) {
|
|
75
76
|
PostMessageMethods["REQUEST_ENTITIES"] = "REQUEST_ENTITIES";
|
|
76
77
|
PostMessageMethods["REQUESTED_ENTITIES"] = "REQUESTED_ENTITIES";
|
|
77
78
|
})(PostMessageMethods$2 || (PostMessageMethods$2 = {}));
|
|
79
|
+
const SUPPORTED_IMAGE_FORMATS = ['jpg', 'png', 'webp', 'gif', 'avif'];
|
|
78
80
|
|
|
79
81
|
const structureComponents = new Set([
|
|
80
82
|
CONTENTFUL_COMPONENTS$1.section.id,
|
|
@@ -225,24 +227,18 @@ const transformAlignment = (cfHorizontalAlignment, cfVerticalAlignment, cfFlexDi
|
|
|
225
227
|
? `safe ${cfHorizontalAlignment}`
|
|
226
228
|
: cfHorizontalAlignment,
|
|
227
229
|
};
|
|
228
|
-
const transformBackgroundImage = (cfBackgroundImageUrl,
|
|
229
|
-
const matchBackgroundSize = (
|
|
230
|
-
if ('fill' ===
|
|
230
|
+
const transformBackgroundImage = (cfBackgroundImageUrl, cfBackgroundImageOptions) => {
|
|
231
|
+
const matchBackgroundSize = (scaling) => {
|
|
232
|
+
if ('fill' === scaling)
|
|
231
233
|
return 'cover';
|
|
232
|
-
if ('fit' ===
|
|
234
|
+
if ('fit' === scaling)
|
|
233
235
|
return 'contain';
|
|
234
|
-
return undefined;
|
|
235
236
|
};
|
|
236
|
-
const matchBackgroundPosition = (
|
|
237
|
-
if (!
|
|
238
|
-
return
|
|
239
|
-
}
|
|
240
|
-
if ('string' !== typeof cfBackgroundImageAlignment) {
|
|
241
|
-
return undefined;
|
|
237
|
+
const matchBackgroundPosition = (alignment) => {
|
|
238
|
+
if (!alignment || 'string' !== typeof alignment) {
|
|
239
|
+
return;
|
|
242
240
|
}
|
|
243
|
-
let [horizontalAlignment, verticalAlignment] =
|
|
244
|
-
.trim()
|
|
245
|
-
.split(/\s+/, 2);
|
|
241
|
+
let [horizontalAlignment, verticalAlignment] = alignment.trim().split(/\s+/, 2);
|
|
246
242
|
// Special case for handling single values
|
|
247
243
|
// for backwards compatibility with single values 'right','left', 'center', 'top','bottom'
|
|
248
244
|
if (horizontalAlignment && !verticalAlignment) {
|
|
@@ -278,50 +274,29 @@ const transformBackgroundImage = (cfBackgroundImageUrl, cfBackgroundImageScaling
|
|
|
278
274
|
return `${horizontalAlignment} ${verticalAlignment}`;
|
|
279
275
|
};
|
|
280
276
|
if (!cfBackgroundImageUrl) {
|
|
281
|
-
return
|
|
282
|
-
}
|
|
283
|
-
return {
|
|
284
|
-
backgroundImage: `url(${cfBackgroundImageUrl})`,
|
|
285
|
-
backgroundRepeat: cfBackgroundImageScaling === 'tile' ? 'repeat' : 'no-repeat',
|
|
286
|
-
backgroundPosition: matchBackgroundPosition(cfBackgroundImageAlignment),
|
|
287
|
-
backgroundSize: matchBackgroundSize(cfBackgroundImageScaling),
|
|
288
|
-
};
|
|
289
|
-
};
|
|
290
|
-
const transformContentValue = (value, variableDefinition) => {
|
|
291
|
-
if (variableDefinition.type === 'RichText') {
|
|
292
|
-
return transformRichText(value);
|
|
277
|
+
return;
|
|
293
278
|
}
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
return {
|
|
299
|
-
data: {},
|
|
300
|
-
content: [
|
|
301
|
-
{
|
|
302
|
-
nodeType: BLOCKS.PARAGRAPH,
|
|
303
|
-
data: {},
|
|
304
|
-
content: [
|
|
305
|
-
{
|
|
306
|
-
data: {},
|
|
307
|
-
nodeType: 'text',
|
|
308
|
-
value: value,
|
|
309
|
-
marks: [],
|
|
310
|
-
},
|
|
311
|
-
],
|
|
312
|
-
},
|
|
313
|
-
],
|
|
314
|
-
nodeType: BLOCKS.DOCUMENT,
|
|
315
|
-
};
|
|
279
|
+
let backgroundImage;
|
|
280
|
+
let backgroundImageSet;
|
|
281
|
+
if (typeof cfBackgroundImageUrl === 'string') {
|
|
282
|
+
backgroundImage = `url(${cfBackgroundImageUrl})`;
|
|
316
283
|
}
|
|
317
|
-
|
|
318
|
-
|
|
284
|
+
else {
|
|
285
|
+
const imgSet = cfBackgroundImageUrl.srcSet?.join(',');
|
|
286
|
+
backgroundImage = `url(${cfBackgroundImageUrl.url})`;
|
|
287
|
+
backgroundImageSet = `image-set(${imgSet})`;
|
|
319
288
|
}
|
|
320
|
-
return
|
|
289
|
+
return {
|
|
290
|
+
backgroundImage,
|
|
291
|
+
backgroundImage2: backgroundImageSet,
|
|
292
|
+
backgroundRepeat: cfBackgroundImageOptions?.scaling === 'tile' ? 'repeat' : 'no-repeat',
|
|
293
|
+
backgroundPosition: matchBackgroundPosition(cfBackgroundImageOptions?.alignment),
|
|
294
|
+
backgroundSize: matchBackgroundSize(cfBackgroundImageOptions?.scaling),
|
|
295
|
+
};
|
|
321
296
|
};
|
|
322
297
|
const transformWidthSizing = ({ value, cfMargin, }) => {
|
|
323
298
|
if (!value || !cfMargin)
|
|
324
|
-
return
|
|
299
|
+
return;
|
|
325
300
|
const transformedValue = transformFill(value);
|
|
326
301
|
const marginValues = cfMargin.split(' ');
|
|
327
302
|
const rightMargin = marginValues[1] || '0px';
|
|
@@ -339,7 +314,12 @@ const transformWidthSizing = ({ value, cfMargin, }) => {
|
|
|
339
314
|
return transformedValue;
|
|
340
315
|
};
|
|
341
316
|
|
|
342
|
-
const toCSSAttribute = (key) =>
|
|
317
|
+
const toCSSAttribute = (key) => {
|
|
318
|
+
let val = key.replace(/[A-Z]/g, (m) => '-' + m.toLowerCase());
|
|
319
|
+
// Remove the number from the end of the key to allow for overrides on style properties
|
|
320
|
+
val = val.replace(/\d+$/, '');
|
|
321
|
+
return val;
|
|
322
|
+
};
|
|
343
323
|
const buildStyleTag = ({ styles, nodeId }) => {
|
|
344
324
|
const stylesStr = Object.entries(styles)
|
|
345
325
|
.filter(([, value]) => value !== undefined)
|
|
@@ -349,13 +329,13 @@ const buildStyleTag = ({ styles, nodeId }) => {
|
|
|
349
329
|
const styleRule = `.${className}{ ${stylesStr} }`;
|
|
350
330
|
return [className, styleRule];
|
|
351
331
|
};
|
|
352
|
-
const buildCfStyles = ({ cfHorizontalAlignment, cfVerticalAlignment, cfFlexDirection, cfFlexWrap, cfMargin, cfPadding, cfBackgroundColor, cfWidth, cfHeight, cfMaxWidth, cfBorder, cfGap, cfBackgroundImageUrl,
|
|
332
|
+
const buildCfStyles = ({ cfHorizontalAlignment, cfVerticalAlignment, cfFlexDirection, cfFlexWrap, cfMargin, cfPadding, cfBackgroundColor, cfWidth, cfHeight, cfMaxWidth, cfBorder, cfGap, cfBackgroundImageUrl, cfBackgroundImageOptions, cfFontSize, cfFontWeight, cfImageOptions, cfLineHeight, cfLetterSpacing, cfTextColor, cfTextAlign, cfTextTransform, cfTextBold, cfTextItalic, cfTextUnderline, cfColumnSpan, }) => {
|
|
353
333
|
return {
|
|
354
334
|
margin: cfMargin,
|
|
355
335
|
padding: cfPadding,
|
|
356
336
|
backgroundColor: cfBackgroundColor,
|
|
357
|
-
width: transformWidthSizing({ value: cfWidth, cfMargin }),
|
|
358
|
-
height: transformFill(cfHeight),
|
|
337
|
+
width: transformWidthSizing({ value: cfWidth || cfImageOptions?.width, cfMargin }),
|
|
338
|
+
height: transformFill(cfHeight || cfImageOptions?.height),
|
|
359
339
|
maxWidth: cfMaxWidth,
|
|
360
340
|
...transformGridColumn(cfColumnSpan),
|
|
361
341
|
...transformBorderStyle(cfBorder),
|
|
@@ -363,7 +343,7 @@ const buildCfStyles = ({ cfHorizontalAlignment, cfVerticalAlignment, cfFlexDirec
|
|
|
363
343
|
...transformAlignment(cfHorizontalAlignment, cfVerticalAlignment, cfFlexDirection),
|
|
364
344
|
flexDirection: cfFlexDirection,
|
|
365
345
|
flexWrap: cfFlexWrap,
|
|
366
|
-
...transformBackgroundImage(cfBackgroundImageUrl,
|
|
346
|
+
...transformBackgroundImage(cfBackgroundImageUrl, cfBackgroundImageOptions),
|
|
367
347
|
fontSize: cfFontSize,
|
|
368
348
|
fontWeight: cfTextBold ? 'bold' : cfFontWeight,
|
|
369
349
|
fontStyle: cfTextItalic ? 'italic' : 'normal',
|
|
@@ -374,10 +354,12 @@ const buildCfStyles = ({ cfHorizontalAlignment, cfVerticalAlignment, cfFlexDirec
|
|
|
374
354
|
textTransform: cfTextTransform,
|
|
375
355
|
textDecoration: cfTextUnderline ? 'underline' : 'none',
|
|
376
356
|
boxSizing: 'border-box',
|
|
357
|
+
objectFit: cfImageOptions?.objectFit,
|
|
358
|
+
objectPosition: cfImageOptions?.objectPosition,
|
|
377
359
|
};
|
|
378
360
|
};
|
|
379
361
|
/**
|
|
380
|
-
* Container/section default
|
|
362
|
+
* Container/section default behavior:
|
|
381
363
|
* Default height => height: EMPTY_CONTAINER_HEIGHT (120px)
|
|
382
364
|
* If a container component has children => height: 'fit-content'
|
|
383
365
|
*/
|
|
@@ -391,6 +373,206 @@ const calculateNodeDefaultHeight = ({ blockId, children, value, }) => {
|
|
|
391
373
|
return EMPTY_CONTAINER_HEIGHT$1;
|
|
392
374
|
};
|
|
393
375
|
|
|
376
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
377
|
+
function get(obj, path) {
|
|
378
|
+
if (!path.length) {
|
|
379
|
+
return obj;
|
|
380
|
+
}
|
|
381
|
+
try {
|
|
382
|
+
const [currentPath, ...nextPath] = path;
|
|
383
|
+
return get(obj[currentPath], nextPath);
|
|
384
|
+
}
|
|
385
|
+
catch (err) {
|
|
386
|
+
return undefined;
|
|
387
|
+
}
|
|
388
|
+
}
|
|
389
|
+
|
|
390
|
+
const getBoundValue = (entryOrAsset, path) => {
|
|
391
|
+
const value = get(entryOrAsset, path.split('/').slice(2, -1));
|
|
392
|
+
return value && typeof value == 'object' && value.url
|
|
393
|
+
? value.url
|
|
394
|
+
: value;
|
|
395
|
+
};
|
|
396
|
+
|
|
397
|
+
const transformRichText = (entryOrAsset, path) => {
|
|
398
|
+
const value = getBoundValue(entryOrAsset, path);
|
|
399
|
+
if (typeof value === 'string') {
|
|
400
|
+
return {
|
|
401
|
+
data: {},
|
|
402
|
+
content: [
|
|
403
|
+
{
|
|
404
|
+
nodeType: BLOCKS.PARAGRAPH,
|
|
405
|
+
data: {},
|
|
406
|
+
content: [
|
|
407
|
+
{
|
|
408
|
+
data: {},
|
|
409
|
+
nodeType: 'text',
|
|
410
|
+
value: value,
|
|
411
|
+
marks: [],
|
|
412
|
+
},
|
|
413
|
+
],
|
|
414
|
+
},
|
|
415
|
+
],
|
|
416
|
+
nodeType: BLOCKS.DOCUMENT,
|
|
417
|
+
};
|
|
418
|
+
}
|
|
419
|
+
if (typeof value === 'object' && value.nodeType === BLOCKS.DOCUMENT) {
|
|
420
|
+
return value;
|
|
421
|
+
}
|
|
422
|
+
return undefined;
|
|
423
|
+
};
|
|
424
|
+
|
|
425
|
+
function getOptimizedImageUrl(url, width, quality, format) {
|
|
426
|
+
const params = new URLSearchParams();
|
|
427
|
+
if (width) {
|
|
428
|
+
params.append('w', width.toString());
|
|
429
|
+
}
|
|
430
|
+
if (quality && quality > 0 && quality < 100) {
|
|
431
|
+
params.append('q', quality.toString());
|
|
432
|
+
}
|
|
433
|
+
if (format) {
|
|
434
|
+
params.append('fm', format);
|
|
435
|
+
}
|
|
436
|
+
const queryString = params.toString();
|
|
437
|
+
return `${url}${queryString ? '?' + queryString : ''}`;
|
|
438
|
+
}
|
|
439
|
+
|
|
440
|
+
const MAX_WIDTH_ALLOWED$1 = 2000;
|
|
441
|
+
const getOptimizedBackgroundImageAsset = (file, widthStyle, quality = 100, format) => {
|
|
442
|
+
if (!validateParams(file, quality, format)) ;
|
|
443
|
+
const url = file.url;
|
|
444
|
+
const { width1x, width2x } = getWidths(widthStyle, file);
|
|
445
|
+
const imageUrl1x = getOptimizedImageUrl(url, width1x, quality, format);
|
|
446
|
+
const imageUrl2x = getOptimizedImageUrl(url, width2x, quality, format);
|
|
447
|
+
const srcSet = [`url(${imageUrl1x}) 1x`, `url(${imageUrl2x}) 2x`];
|
|
448
|
+
const returnedUrlImageUrl = getOptimizedImageUrl(url, width2x, quality, format);
|
|
449
|
+
const optimizedBackgroundImageAsset = {
|
|
450
|
+
url: returnedUrlImageUrl,
|
|
451
|
+
srcSet,
|
|
452
|
+
file,
|
|
453
|
+
};
|
|
454
|
+
return optimizedBackgroundImageAsset;
|
|
455
|
+
function validateParams(file, quality, format) {
|
|
456
|
+
if (!file.details.image) {
|
|
457
|
+
throw Error('No image in file asset to transform');
|
|
458
|
+
}
|
|
459
|
+
if (quality < 0 || quality > 100) {
|
|
460
|
+
throw Error('Quality must be between 0 and 100');
|
|
461
|
+
}
|
|
462
|
+
if (format && !SUPPORTED_IMAGE_FORMATS.includes(format)) {
|
|
463
|
+
throw Error(`Format must be one of ${SUPPORTED_IMAGE_FORMATS.join(', ')}`);
|
|
464
|
+
}
|
|
465
|
+
return true;
|
|
466
|
+
}
|
|
467
|
+
};
|
|
468
|
+
function getWidths(widthStyle, file) {
|
|
469
|
+
let width1x = 0;
|
|
470
|
+
let width2x = 0;
|
|
471
|
+
const intrinsicImageWidth = file.details.image.width;
|
|
472
|
+
if (widthStyle.endsWith('px')) {
|
|
473
|
+
width1x = Math.min(Number(widthStyle.replace('px', '')), intrinsicImageWidth);
|
|
474
|
+
}
|
|
475
|
+
else {
|
|
476
|
+
width1x = Math.min(MAX_WIDTH_ALLOWED$1, intrinsicImageWidth);
|
|
477
|
+
}
|
|
478
|
+
width2x = Math.min(width1x * 2, intrinsicImageWidth);
|
|
479
|
+
return { width1x, width2x };
|
|
480
|
+
}
|
|
481
|
+
|
|
482
|
+
const MAX_WIDTH_ALLOWED = 4000;
|
|
483
|
+
const getOptimizedImageAsset = (file, sizes, quality = 100, format) => {
|
|
484
|
+
if (!validateParams(file, quality, format)) ;
|
|
485
|
+
const url = file.url;
|
|
486
|
+
const maxWidth = Math.min(file.details.image.width, MAX_WIDTH_ALLOWED);
|
|
487
|
+
const numOfParts = Math.max(2, Math.ceil(maxWidth / 500));
|
|
488
|
+
const widthParts = Array.from({ length: numOfParts }, (_, index) => Math.ceil((index + 1) * (maxWidth / numOfParts)));
|
|
489
|
+
const srcSet = sizes
|
|
490
|
+
? widthParts.map((width) => `${getOptimizedImageUrl(url, width, quality, format)} ${width}w`)
|
|
491
|
+
: [];
|
|
492
|
+
const intrinsicImageWidth = file.details.image.width;
|
|
493
|
+
if (intrinsicImageWidth > MAX_WIDTH_ALLOWED) {
|
|
494
|
+
srcSet.push(`${getOptimizedImageUrl(url, undefined, quality, format)} ${intrinsicImageWidth}w`);
|
|
495
|
+
}
|
|
496
|
+
const returnedUrl = getOptimizedImageUrl(url, file.details.image.width > 2000 ? 2000 : undefined, quality, format);
|
|
497
|
+
const optimizedImageAsset = {
|
|
498
|
+
url: returnedUrl,
|
|
499
|
+
srcSet,
|
|
500
|
+
sizes,
|
|
501
|
+
file,
|
|
502
|
+
};
|
|
503
|
+
return optimizedImageAsset;
|
|
504
|
+
function validateParams(file, quality, format) {
|
|
505
|
+
if (!file.details.image) {
|
|
506
|
+
throw Error('No image in file asset to transform');
|
|
507
|
+
}
|
|
508
|
+
if (quality < 0 || quality > 100) {
|
|
509
|
+
throw Error('Quality must be between 0 and 100');
|
|
510
|
+
}
|
|
511
|
+
if (format && !SUPPORTED_IMAGE_FORMATS.includes(format)) {
|
|
512
|
+
throw Error(`Format must be one of ${SUPPORTED_IMAGE_FORMATS.join(', ')}`);
|
|
513
|
+
}
|
|
514
|
+
return true;
|
|
515
|
+
}
|
|
516
|
+
};
|
|
517
|
+
|
|
518
|
+
const transformMedia = (asset, variables, resolveDesignValue, variableName, path) => {
|
|
519
|
+
let value;
|
|
520
|
+
//TODO: this will be better served by injectable type transformers instead of if statement
|
|
521
|
+
if (variableName === 'cfImageAsset') {
|
|
522
|
+
const optionsVariableName = 'cfImageOptions';
|
|
523
|
+
const options = resolveDesignValue(variables[optionsVariableName]?.type === 'DesignValue'
|
|
524
|
+
? variables[optionsVariableName].valuesByBreakpoint
|
|
525
|
+
: {}, optionsVariableName);
|
|
526
|
+
if (!options) {
|
|
527
|
+
console.error(`Error transforming image asset: Required variable [${optionsVariableName}] missing from component definition`);
|
|
528
|
+
return;
|
|
529
|
+
}
|
|
530
|
+
try {
|
|
531
|
+
value = getOptimizedImageAsset(asset.fields.file, options.targetSize, Number(options.quality), options.format);
|
|
532
|
+
return value;
|
|
533
|
+
}
|
|
534
|
+
catch (error) {
|
|
535
|
+
console.error('Error transforming image asset', error);
|
|
536
|
+
}
|
|
537
|
+
return;
|
|
538
|
+
}
|
|
539
|
+
if (variableName === 'cfBackgroundImageUrl') {
|
|
540
|
+
const width = resolveDesignValue(variables['cfWidth']?.type === 'DesignValue' ? variables['cfWidth'].valuesByBreakpoint : {}, 'cfWidth');
|
|
541
|
+
const optionsVariableName = 'cfBackgroundImageOptions';
|
|
542
|
+
const options = resolveDesignValue(variables[optionsVariableName]?.type === 'DesignValue'
|
|
543
|
+
? variables[optionsVariableName].valuesByBreakpoint
|
|
544
|
+
: {}, optionsVariableName);
|
|
545
|
+
if (!options) {
|
|
546
|
+
console.error(`Error transforming image asset: Required variable [${optionsVariableName}] missing from component definition`);
|
|
547
|
+
return;
|
|
548
|
+
}
|
|
549
|
+
try {
|
|
550
|
+
value = getOptimizedBackgroundImageAsset(asset.fields.file, width, Number(options.quality), options.format);
|
|
551
|
+
return value;
|
|
552
|
+
}
|
|
553
|
+
catch (error) {
|
|
554
|
+
console.error('Error transforming image asset', error);
|
|
555
|
+
}
|
|
556
|
+
return;
|
|
557
|
+
}
|
|
558
|
+
// return getBoundValue(asset, entityStore, binding, path);
|
|
559
|
+
return getBoundValue(asset, path);
|
|
560
|
+
};
|
|
561
|
+
|
|
562
|
+
const transformBoundContentValue = (variables, entityStore, binding, resolveDesignValue, variableName, variableDefinition, path) => {
|
|
563
|
+
const entityOrAsset = entityStore.getEntryOrAsset(binding, path);
|
|
564
|
+
if (!entityOrAsset)
|
|
565
|
+
return;
|
|
566
|
+
switch (variableDefinition.type) {
|
|
567
|
+
case 'Media':
|
|
568
|
+
return transformMedia(entityOrAsset, variables, resolveDesignValue, variableName, path);
|
|
569
|
+
case 'RichText':
|
|
570
|
+
return transformRichText(entityOrAsset, path);
|
|
571
|
+
default:
|
|
572
|
+
return getBoundValue(entityOrAsset, path);
|
|
573
|
+
}
|
|
574
|
+
};
|
|
575
|
+
|
|
394
576
|
const getDataFromTree = (tree) => {
|
|
395
577
|
let dataSource = {};
|
|
396
578
|
let unboundValues = {};
|
|
@@ -529,42 +711,6 @@ const builtInStyles = {
|
|
|
529
711
|
description: 'The spacing between the elements of the section',
|
|
530
712
|
defaultValue: '0px',
|
|
531
713
|
},
|
|
532
|
-
cfBackgroundImageUrl: {
|
|
533
|
-
displayName: 'Background image',
|
|
534
|
-
type: 'Text',
|
|
535
|
-
defaultValue: '',
|
|
536
|
-
description: 'Background image for section or container',
|
|
537
|
-
},
|
|
538
|
-
cfBackgroundImageScaling: {
|
|
539
|
-
displayName: 'Image scaling',
|
|
540
|
-
type: 'Text',
|
|
541
|
-
group: 'style',
|
|
542
|
-
description: 'Adjust background image to fit, fill or tile the container',
|
|
543
|
-
defaultValue: 'fit',
|
|
544
|
-
validations: {
|
|
545
|
-
in: [
|
|
546
|
-
{
|
|
547
|
-
value: 'fill',
|
|
548
|
-
displayName: 'Fill',
|
|
549
|
-
},
|
|
550
|
-
{
|
|
551
|
-
value: 'fit',
|
|
552
|
-
displayName: 'Fit',
|
|
553
|
-
},
|
|
554
|
-
{
|
|
555
|
-
value: 'tile',
|
|
556
|
-
displayName: 'Tile',
|
|
557
|
-
},
|
|
558
|
-
],
|
|
559
|
-
},
|
|
560
|
-
},
|
|
561
|
-
cfBackgroundImageAlignment: {
|
|
562
|
-
displayName: 'Image alignment',
|
|
563
|
-
type: 'Text',
|
|
564
|
-
group: 'style',
|
|
565
|
-
description: 'Align background image to the edges of the container',
|
|
566
|
-
defaultValue: 'left top',
|
|
567
|
-
},
|
|
568
714
|
cfHyperlink: {
|
|
569
715
|
displayName: 'Hyperlink',
|
|
570
716
|
type: 'Text',
|
|
@@ -612,6 +758,40 @@ const optionalBuiltInStyles = {
|
|
|
612
758
|
description: 'The font weight of the element',
|
|
613
759
|
defaultValue: '400',
|
|
614
760
|
},
|
|
761
|
+
cfImageAsset: {
|
|
762
|
+
displayName: 'Image',
|
|
763
|
+
type: 'Media',
|
|
764
|
+
description: 'Image to display',
|
|
765
|
+
},
|
|
766
|
+
cfImageOptions: {
|
|
767
|
+
displayName: 'Image options',
|
|
768
|
+
type: 'Object',
|
|
769
|
+
group: 'style',
|
|
770
|
+
defaultValue: {
|
|
771
|
+
width: DEFAULT_IMAGE_WIDTH,
|
|
772
|
+
height: '100%',
|
|
773
|
+
objectFit: 'none',
|
|
774
|
+
objectPosition: 'center center',
|
|
775
|
+
quality: '100',
|
|
776
|
+
targetSize: DEFAULT_IMAGE_WIDTH,
|
|
777
|
+
},
|
|
778
|
+
},
|
|
779
|
+
cfBackgroundImageUrl: {
|
|
780
|
+
displayName: 'Background image',
|
|
781
|
+
type: 'Media',
|
|
782
|
+
description: 'Background image for component',
|
|
783
|
+
},
|
|
784
|
+
cfBackgroundImageOptions: {
|
|
785
|
+
displayName: 'Background image options',
|
|
786
|
+
type: 'Object',
|
|
787
|
+
group: 'style',
|
|
788
|
+
defaultValue: {
|
|
789
|
+
scaling: 'fill',
|
|
790
|
+
alignment: 'left top',
|
|
791
|
+
quality: '100',
|
|
792
|
+
targetSize: '2000px',
|
|
793
|
+
},
|
|
794
|
+
},
|
|
615
795
|
cfLineHeight: {
|
|
616
796
|
displayName: 'Line Height',
|
|
617
797
|
type: 'Text',
|
|
@@ -994,29 +1174,9 @@ const sendMessage = (eventType, data) => {
|
|
|
994
1174
|
}, '*');
|
|
995
1175
|
};
|
|
996
1176
|
|
|
997
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
998
|
-
function get(obj, path) {
|
|
999
|
-
if (!path.length) {
|
|
1000
|
-
return obj;
|
|
1001
|
-
}
|
|
1002
|
-
try {
|
|
1003
|
-
const [currentPath, ...nextPath] = path;
|
|
1004
|
-
return get(obj[currentPath], nextPath);
|
|
1005
|
-
}
|
|
1006
|
-
catch (err) {
|
|
1007
|
-
return undefined;
|
|
1008
|
-
}
|
|
1009
|
-
}
|
|
1010
|
-
|
|
1011
|
-
function transformAssetFileToUrl(fieldValue) {
|
|
1012
|
-
return fieldValue && typeof fieldValue == 'object' && fieldValue.url
|
|
1013
|
-
? fieldValue.url
|
|
1014
|
-
: fieldValue;
|
|
1015
|
-
}
|
|
1016
|
-
|
|
1017
1177
|
/**
|
|
1018
1178
|
* Base Store for entities
|
|
1019
|
-
* Can be
|
|
1179
|
+
* Can be extended for the different loading behaviours (editor, production, ..)
|
|
1020
1180
|
*/
|
|
1021
1181
|
class EntityStoreBase {
|
|
1022
1182
|
constructor({ entities, locale }) {
|
|
@@ -1033,68 +1193,26 @@ class EntityStoreBase {
|
|
|
1033
1193
|
updateEntity(entity) {
|
|
1034
1194
|
this.addEntity(entity);
|
|
1035
1195
|
}
|
|
1036
|
-
|
|
1037
|
-
|
|
1038
|
-
|
|
1039
|
-
|
|
1040
|
-
|
|
1041
|
-
|
|
1042
|
-
|
|
1043
|
-
|
|
1044
|
-
|
|
1045
|
-
|
|
1046
|
-
}
|
|
1047
|
-
|
|
1048
|
-
resolvedFieldset.push([entityToResolveFieldsFrom, field, _localeQualifier]);
|
|
1049
|
-
break;
|
|
1050
|
-
}
|
|
1051
|
-
const fieldValue = get(entityToResolveFieldsFrom, ['fields', field]);
|
|
1052
|
-
if (undefined === fieldValue) {
|
|
1053
|
-
return {
|
|
1054
|
-
resolvedFieldset,
|
|
1055
|
-
isFullyResolved: false,
|
|
1056
|
-
reason: `Cannot resolve field Link<${entityToResolveFieldsFrom.sys.type}>(sys.id=${entityToResolveFieldsFrom.sys.id}).fields[${field}] as field value is not defined`,
|
|
1057
|
-
};
|
|
1058
|
-
}
|
|
1059
|
-
else if (isLink(fieldValue)) {
|
|
1060
|
-
const entity = this.getEntityFromLink(fieldValue);
|
|
1061
|
-
if (entity === undefined) {
|
|
1062
|
-
throw new Error(`Logic Error: Broken Precondition [by the time resolution of deep path happens all referents should be in EntityStore]: Cannot resolve field ${field} of a fieldset row [${JSON.stringify(row)}] as linked entity not found in the EntityStore. ${JSON.stringify({
|
|
1063
|
-
link: fieldValue,
|
|
1064
|
-
})}`);
|
|
1065
|
-
}
|
|
1066
|
-
resolvedFieldset.push([entityToResolveFieldsFrom, field, _localeQualifier]);
|
|
1067
|
-
entityToResolveFieldsFrom = entity; // we move up
|
|
1068
|
-
}
|
|
1069
|
-
else {
|
|
1070
|
-
// TODO: Eg. when someone changed the schema and the field is not a link anymore, what should we return then?
|
|
1071
|
-
throw new Error(`LogicError: Invalid value of a field we consider a reference field. Cannot resolve field ${field} of a fieldset as it is not a link, neither undefined.`);
|
|
1072
|
-
}
|
|
1196
|
+
getEntryOrAsset(linkOrEntryOrAsset, path) {
|
|
1197
|
+
if (isDeepPath(path)) {
|
|
1198
|
+
return this.getDeepEntry(linkOrEntryOrAsset, path);
|
|
1199
|
+
}
|
|
1200
|
+
let entity;
|
|
1201
|
+
if (isLink(linkOrEntryOrAsset)) {
|
|
1202
|
+
const resolvedEntity = linkOrEntryOrAsset.sys.linkType === 'Entry'
|
|
1203
|
+
? this.entryMap.get(linkOrEntryOrAsset.sys.id)
|
|
1204
|
+
: this.assetMap.get(linkOrEntryOrAsset.sys.id);
|
|
1205
|
+
if (!resolvedEntity || resolvedEntity.sys.type !== linkOrEntryOrAsset.sys.linkType) {
|
|
1206
|
+
console.warn(`Experience references unresolved entity: ${JSON.stringify(linkOrEntryOrAsset)}`);
|
|
1207
|
+
return;
|
|
1073
1208
|
}
|
|
1074
|
-
|
|
1075
|
-
resolvedFieldset,
|
|
1076
|
-
isFullyResolved: true,
|
|
1077
|
-
};
|
|
1078
|
-
};
|
|
1079
|
-
const headEntity = isLink(headLinkOrEntity)
|
|
1080
|
-
? this.getEntityFromLink(headLinkOrEntity)
|
|
1081
|
-
: headLinkOrEntity;
|
|
1082
|
-
if (undefined === headEntity) {
|
|
1083
|
-
return;
|
|
1209
|
+
entity = resolvedEntity;
|
|
1084
1210
|
}
|
|
1085
|
-
|
|
1086
|
-
|
|
1087
|
-
|
|
1088
|
-
// in case we can't follow till the end, we should signal that there was null-reference in the path
|
|
1089
|
-
const { resolvedFieldset, isFullyResolved, reason } = resolveFieldset(unresolvedFieldset, headEntity);
|
|
1090
|
-
if (!isFullyResolved) {
|
|
1091
|
-
reason &&
|
|
1092
|
-
console.debug(`[experiences-sdk-react::EntityStoreBased::getValueDeep()] Deep path wasn't resolved till leaf node, falling back to undefined, because: ${reason}`);
|
|
1093
|
-
return undefined;
|
|
1211
|
+
else {
|
|
1212
|
+
// We already have the complete entity in preview & delivery (resolved by the CMA client)
|
|
1213
|
+
entity = linkOrEntryOrAsset;
|
|
1094
1214
|
}
|
|
1095
|
-
|
|
1096
|
-
const fieldValue = get(leafEntity, ['fields', field]); // is allowed to be undefined (when non-required field not set; or even when field does NOT exist on the type)
|
|
1097
|
-
return transformAssetFileToUrl(fieldValue);
|
|
1215
|
+
return entity;
|
|
1098
1216
|
}
|
|
1099
1217
|
/**
|
|
1100
1218
|
* @deprecated in the base class this should be simply an abstract method
|
|
@@ -1151,7 +1269,7 @@ class EntityStoreBase {
|
|
|
1151
1269
|
if (missing.length) {
|
|
1152
1270
|
// TODO: move to `debug` utils once it is extracted
|
|
1153
1271
|
console.warn(`Asset "${id}" is not in the store`);
|
|
1154
|
-
return
|
|
1272
|
+
return;
|
|
1155
1273
|
}
|
|
1156
1274
|
return resolved[0];
|
|
1157
1275
|
}
|
|
@@ -1167,7 +1285,7 @@ class EntityStoreBase {
|
|
|
1167
1285
|
if (missing.length) {
|
|
1168
1286
|
// TODO: move to `debug` utils once it is extracted
|
|
1169
1287
|
console.warn(`Entry "${id}" is not in the store`);
|
|
1170
|
-
return
|
|
1288
|
+
return;
|
|
1171
1289
|
}
|
|
1172
1290
|
return resolved[0];
|
|
1173
1291
|
}
|
|
@@ -1178,6 +1296,70 @@ class EntityStoreBase {
|
|
|
1178
1296
|
}
|
|
1179
1297
|
return resolved;
|
|
1180
1298
|
}
|
|
1299
|
+
getDeepEntry(linkOrEntryOrAsset, path) {
|
|
1300
|
+
const resolveFieldset = (unresolvedFieldset, headEntry) => {
|
|
1301
|
+
const resolvedFieldset = [];
|
|
1302
|
+
let entityToResolveFieldsFrom = headEntry;
|
|
1303
|
+
for (let i = 0; i < unresolvedFieldset.length; i++) {
|
|
1304
|
+
const isLeaf = i === unresolvedFieldset.length - 1; // with last row, we are not expecting a link, but a value
|
|
1305
|
+
const row = unresolvedFieldset[i];
|
|
1306
|
+
const [, field, _localeQualifier] = row;
|
|
1307
|
+
if (!entityToResolveFieldsFrom) {
|
|
1308
|
+
throw new Error(`Logic Error: Cannot resolve field ${field} of a fieldset as there is no entity to resolve it from.`);
|
|
1309
|
+
}
|
|
1310
|
+
if (isLeaf) {
|
|
1311
|
+
resolvedFieldset.push([entityToResolveFieldsFrom, field, _localeQualifier]);
|
|
1312
|
+
break;
|
|
1313
|
+
}
|
|
1314
|
+
const fieldValue = get(entityToResolveFieldsFrom, ['fields', field]);
|
|
1315
|
+
if (undefined === fieldValue) {
|
|
1316
|
+
return {
|
|
1317
|
+
resolvedFieldset,
|
|
1318
|
+
isFullyResolved: false,
|
|
1319
|
+
reason: `Cannot resolve field Link<${entityToResolveFieldsFrom.sys.type}>(sys.id=${entityToResolveFieldsFrom.sys.id}).fields[${field}] as field value is not defined`,
|
|
1320
|
+
};
|
|
1321
|
+
}
|
|
1322
|
+
else if (isLink(fieldValue)) {
|
|
1323
|
+
const entity = this.getEntityFromLink(fieldValue);
|
|
1324
|
+
if (entity === undefined) {
|
|
1325
|
+
return {
|
|
1326
|
+
resolvedFieldset,
|
|
1327
|
+
isFullyResolved: false,
|
|
1328
|
+
reason: `Field reference Link (sys.id=${fieldValue.sys.id}) not found in the EntityStore, waiting...`,
|
|
1329
|
+
};
|
|
1330
|
+
}
|
|
1331
|
+
resolvedFieldset.push([entityToResolveFieldsFrom, field, _localeQualifier]);
|
|
1332
|
+
entityToResolveFieldsFrom = entity; // we move up
|
|
1333
|
+
}
|
|
1334
|
+
else {
|
|
1335
|
+
// TODO: Eg. when someone changed the schema and the field is not a link anymore, what should we return then?
|
|
1336
|
+
throw new Error(`LogicError: Invalid value of a field we consider a reference field. Cannot resolve field ${field} of a fieldset as it is not a link, neither undefined.`);
|
|
1337
|
+
}
|
|
1338
|
+
}
|
|
1339
|
+
return {
|
|
1340
|
+
resolvedFieldset,
|
|
1341
|
+
isFullyResolved: true,
|
|
1342
|
+
};
|
|
1343
|
+
};
|
|
1344
|
+
const headEntity = isLink(linkOrEntryOrAsset)
|
|
1345
|
+
? this.getEntityFromLink(linkOrEntryOrAsset)
|
|
1346
|
+
: linkOrEntryOrAsset;
|
|
1347
|
+
if (undefined === headEntity) {
|
|
1348
|
+
return;
|
|
1349
|
+
}
|
|
1350
|
+
const unresolvedFieldset = parseDataSourcePathIntoFieldset(path);
|
|
1351
|
+
// The purpose here is to take this intermediate representation of the deep-path
|
|
1352
|
+
// and to follow the links to the leaf-entity and field
|
|
1353
|
+
// in case we can't follow till the end, we should signal that there was null-reference in the path
|
|
1354
|
+
const { resolvedFieldset, isFullyResolved, reason } = resolveFieldset(unresolvedFieldset, headEntity);
|
|
1355
|
+
if (!isFullyResolved) {
|
|
1356
|
+
reason &&
|
|
1357
|
+
console.debug(`[exp-builder.sdk::EntityStoreBased::getValueDeep()] Deep path wasn't resolved till leaf node, falling back to undefined, because: ${reason}`);
|
|
1358
|
+
return;
|
|
1359
|
+
}
|
|
1360
|
+
const [leafEntity] = resolvedFieldset[resolvedFieldset.length - 1];
|
|
1361
|
+
return leafEntity;
|
|
1362
|
+
}
|
|
1181
1363
|
isAsset(entity) {
|
|
1182
1364
|
return entity.sys.type === 'Asset';
|
|
1183
1365
|
}
|
|
@@ -1356,11 +1538,16 @@ class EditorModeEntityStore extends EditorEntityStore {
|
|
|
1356
1538
|
const { missing: missingAssetIds } = this.getEntitiesFromMap('Asset', uniqueAssetIds);
|
|
1357
1539
|
return { missingEntryIds, missingAssetIds };
|
|
1358
1540
|
}
|
|
1359
|
-
getValue(
|
|
1360
|
-
|
|
1541
|
+
getValue(entityLinkOrEntity, path) {
|
|
1542
|
+
const entity = this.getEntryOrAsset(entityLinkOrEntity, path.join('/'));
|
|
1543
|
+
if (!entity) {
|
|
1361
1544
|
return;
|
|
1362
|
-
|
|
1363
|
-
|
|
1545
|
+
}
|
|
1546
|
+
const fieldValue = get(entity, path);
|
|
1547
|
+
// walk around to render asset files
|
|
1548
|
+
return fieldValue && typeof fieldValue == 'object' && fieldValue.url
|
|
1549
|
+
? fieldValue.url
|
|
1550
|
+
: fieldValue;
|
|
1364
1551
|
}
|
|
1365
1552
|
}
|
|
1366
1553
|
|
|
@@ -1442,9 +1629,9 @@ function gatherDeepReferencesFromTree(startingNode, dataSource) {
|
|
|
1442
1629
|
return deepReferences;
|
|
1443
1630
|
}
|
|
1444
1631
|
|
|
1445
|
-
var css_248z$
|
|
1632
|
+
var css_248z$7 = ".styles-module_DraggableComponent__m5-dA {\n pointer-events: all;\n position: relative;\n transition: outline 0.2s;\n cursor: grab;\n box-sizing: border-box;\n display: flex;\n}\n\n.styles-module_DraggableComponent__m5-dA:before {\n content: '';\n position: absolute;\n top: 0;\n right: 0;\n bottom: 0;\n left: 0;\n outline-offset: -2px;\n outline: 2px solid transparent;\n z-index: 1;\n pointer-events: none;\n}\n\n.styles-module_DraggableClone__X8zTA:before {\n outline: 2px solid var(--exp-builder-blue500);\n}\n\n.styles-module_DraggableClone__X8zTA,\n.styles-module_DraggableClone__X8zTA * {\n pointer-events: none !important;\n}\n\n.styles-module_DraggableComponent__m5-dA:not(.styles-module_userIsDragging__lqbjG) :not(.styles-module_DraggableComponent__m5-dA) {\n pointer-events: none;\n}\n\n.styles-module_isDragging__WHjPU {\n overflow: hidden;\n}\n\n.styles-module_isSelected__BzICQ:before {\n outline: 2px solid transparent !important;\n}\n\n.styles-module_overlay__r4th9 {\n position: absolute;\n display: flex;\n align-items: center;\n min-width: max-content;\n height: 24px;\n z-index: 1;\n font-family: var(--exp-builder-font-stack-primary);\n font-size: 14px;\n font-weight: 500;\n background-color: var(--exp-builder-gray500);\n color: var(--exp-builder-color-white);\n border-radius: 0 0 2px 0;\n padding: 4px 12px 4px 12px;\n transition: opacity 0.2s;\n opacity: 0;\n text-wrap: nowrap;\n}\n\n.styles-module_overlayContainer__eiX-5 {\n opacity: 0;\n}\n\n.styles-module_overlayAssembly__tOzZU {\n background-color: var(--exp-builder-purple600);\n}\n\n.styles-module_userIsDragging__lqbjG > .styles-module_overlay__r4th9,\n.styles-module_userIsDragging__lqbjG > .styles-module_overlayContainer__eiX-5 {\n opacity: 0 !important;\n}\n\n.styles-module_userIsDragging__lqbjG:before {\n outline: 2px solid transparent !important;\n}\n\n.styles-module_DraggableComponent__m5-dA:hover:not(:has(div[data-rfd-draggable-id]:hover)) > .styles-module_overlay__r4th9 {\n opacity: 1;\n}\n\n.styles-module_DraggableComponent__m5-dA:hover:before,\n.styles-module_DraggableComponent__m5-dA:hover div[data-rfd-draggable-id]:before {\n outline: 2px dashed var(--exp-builder-gray500);\n}\n\n.styles-module_DraggableComponent__m5-dA:hover:not(:has(div[data-rfd-draggable-id]:hover)):before {\n outline: 2px solid var(--exp-builder-gray500);\n}\n\n.styles-module_isAssemblyBlock__Y3Avk:hover:before,\n.styles-module_isAssemblyBlock__Y3Avk:hover div[data-rfd-draggable-id]:before,\n.styles-module_DraggableComponent__m5-dA:hover div[data-rfd-draggable-id][data-cf-node-block-type^='assembly']:before {\n outline: 2px dashed var(--exp-builder-purple600);\n}\n\n.styles-module_isAssemblyBlock__Y3Avk:hover:not(:has(div[data-rfd-draggable-id]:hover)):before {\n outline: 2px solid var(--exp-builder-purple600);\n}\n";
|
|
1446
1633
|
var styles$3 = {"DraggableComponent":"styles-module_DraggableComponent__m5-dA","DraggableClone":"styles-module_DraggableClone__X8zTA","userIsDragging":"styles-module_userIsDragging__lqbjG","isDragging":"styles-module_isDragging__WHjPU","isSelected":"styles-module_isSelected__BzICQ","overlay":"styles-module_overlay__r4th9","overlayContainer":"styles-module_overlayContainer__eiX-5","overlayAssembly":"styles-module_overlayAssembly__tOzZU","isAssemblyBlock":"styles-module_isAssemblyBlock__Y3Avk"};
|
|
1447
|
-
styleInject(css_248z$
|
|
1634
|
+
styleInject(css_248z$7);
|
|
1448
1635
|
|
|
1449
1636
|
const SCROLL_STATES = {
|
|
1450
1637
|
Start: 'scrollStart',
|
|
@@ -1547,13 +1734,14 @@ const CF_STYLE_ATTRIBUTES = [
|
|
|
1547
1734
|
'cfWidth',
|
|
1548
1735
|
'cfMaxWidth',
|
|
1549
1736
|
'cfHeight',
|
|
1737
|
+
'cfImageAsset',
|
|
1738
|
+
'cfImageOptions',
|
|
1739
|
+
'cfBackgroundImageUrl',
|
|
1740
|
+
'cfBackgroundImageOptions',
|
|
1550
1741
|
'cfFlexDirection',
|
|
1551
1742
|
'cfFlexWrap',
|
|
1552
1743
|
'cfBorder',
|
|
1553
1744
|
'cfGap',
|
|
1554
|
-
'cfBackgroundImageUrl',
|
|
1555
|
-
'cfBackgroundImageScaling',
|
|
1556
|
-
'cfBackgroundImageAlignment',
|
|
1557
1745
|
'cfFontSize',
|
|
1558
1746
|
'cfFontWeight',
|
|
1559
1747
|
'cfLineHeight',
|
|
@@ -1568,6 +1756,8 @@ const CF_STYLE_ATTRIBUTES = [
|
|
|
1568
1756
|
// we need to keep those in this constant array
|
|
1569
1757
|
// so that omit() in <VisualEditorBlock> and <CompositionBlock>
|
|
1570
1758
|
// can filter them out and not pass as props
|
|
1759
|
+
'cfBackgroundImageScaling',
|
|
1760
|
+
'cfBackgroundImageAlignment',
|
|
1571
1761
|
'cfBackgroundImageAlignmentVertical',
|
|
1572
1762
|
'cfBackgroundImageAlignmentHorizontal',
|
|
1573
1763
|
];
|
|
@@ -1703,7 +1893,7 @@ const NEW_COMPONENT_ID = 'ctfl-new-draggable';
|
|
|
1703
1893
|
const CTFL_ZONE_ID = 'data-ctfl-zone-id';
|
|
1704
1894
|
const CTFL_DRAGGING_ELEMENT = 'data-ctfl-dragging-element';
|
|
1705
1895
|
const HITBOX = {
|
|
1706
|
-
WIDTH:
|
|
1896
|
+
WIDTH: 70,
|
|
1707
1897
|
HEIGHT: 20,
|
|
1708
1898
|
INITIAL_OFFSET: 10,
|
|
1709
1899
|
OFFSET_INCREMENT: 8,
|
|
@@ -2120,10 +2310,12 @@ const useEntityStore = create((set) => ({
|
|
|
2120
2310
|
},
|
|
2121
2311
|
resetEntityStore(locale, entities = []) {
|
|
2122
2312
|
console.debug(`[experiences-sdk-react] Resetting entity store because the locale changed to '${locale}'.`);
|
|
2313
|
+
const newEntityStore = new EditorModeEntityStore({ locale, entities });
|
|
2123
2314
|
set({
|
|
2124
|
-
entityStore:
|
|
2315
|
+
entityStore: newEntityStore,
|
|
2125
2316
|
areEntitiesFetched: false,
|
|
2126
2317
|
});
|
|
2318
|
+
return newEntityStore;
|
|
2127
2319
|
},
|
|
2128
2320
|
}));
|
|
2129
2321
|
|
|
@@ -2159,48 +2351,25 @@ const useComponentProps = ({ node, areEntitiesFetched, resolveDesignValue, rende
|
|
|
2159
2351
|
};
|
|
2160
2352
|
}
|
|
2161
2353
|
else if (variableMapping.type === 'BoundValue') {
|
|
2162
|
-
|
|
2163
|
-
console.debug(`[experiences-sdk-react::useComponentProps] Idle-cycle: as entities are not fetched(areEntitiesFetched=${areEntitiesFetched}), we cannot resolve bound values for ${variableName} so we just resolve them to default values.`);
|
|
2164
|
-
// Just forcing default value (if we're in idle-cycle, entities are missing)
|
|
2165
|
-
return {
|
|
2166
|
-
...acc,
|
|
2167
|
-
[variableName]: transformContentValue(variableDefinition.defaultValue, variableDefinition),
|
|
2168
|
-
};
|
|
2169
|
-
}
|
|
2170
|
-
if (isDeepPath(variableMapping.path)) {
|
|
2171
|
-
const [, uuid] = variableMapping.path.split('/');
|
|
2172
|
-
const link = dataSource[uuid];
|
|
2173
|
-
const boundValue = entityStore?.getValueDeep(link, variableMapping.path);
|
|
2174
|
-
const value = boundValue || variableDefinition.defaultValue;
|
|
2175
|
-
return {
|
|
2176
|
-
...acc,
|
|
2177
|
-
[variableName]: transformContentValue(value, variableDefinition),
|
|
2178
|
-
};
|
|
2179
|
-
}
|
|
2180
|
-
// // take value from the datasource for both bound and unbound value types
|
|
2181
|
-
const [, uuid, ...path] = variableMapping.path.split('/');
|
|
2354
|
+
const [, uuid, path] = variableMapping.path.split('/');
|
|
2182
2355
|
const binding = dataSource[uuid];
|
|
2183
|
-
|
|
2184
|
-
|
|
2185
|
-
: undefined;
|
|
2356
|
+
const variableDefinition = definition.variables[variableName];
|
|
2357
|
+
let boundValue = transformBoundContentValue(node.data.props, entityStore, binding, resolveDesignValue, variableName, variableDefinition, variableMapping.path);
|
|
2186
2358
|
// In some cases, there may be an asset linked in the path, so we need to consider this scenario:
|
|
2187
2359
|
// If no 'boundValue' is found, we also attempt to extract the value associated with the second-to-last item in the path.
|
|
2188
2360
|
// If successful, it means we have identified the linked asset.
|
|
2189
2361
|
if (!boundValue) {
|
|
2190
2362
|
const maybeBoundAsset = areEntitiesFetched
|
|
2191
|
-
? entityStore.getValue(binding, path.slice(0, -2))
|
|
2363
|
+
? entityStore.getValue(binding, path.split('/').slice(0, -2))
|
|
2192
2364
|
: undefined;
|
|
2193
2365
|
if (isLinkToAsset(maybeBoundAsset)) {
|
|
2194
2366
|
boundValue = maybeBoundAsset;
|
|
2195
2367
|
}
|
|
2196
2368
|
}
|
|
2197
|
-
if (typeof boundValue === 'object' && boundValue.sys?.linkType === 'Asset') {
|
|
2198
|
-
boundValue = entityStore?.getValue(boundValue, ['fields', 'file']);
|
|
2199
|
-
}
|
|
2200
2369
|
const value = boundValue || variableDefinition.defaultValue;
|
|
2201
2370
|
return {
|
|
2202
2371
|
...acc,
|
|
2203
|
-
[variableName]:
|
|
2372
|
+
[variableName]: value,
|
|
2204
2373
|
};
|
|
2205
2374
|
}
|
|
2206
2375
|
else {
|
|
@@ -2273,12 +2442,15 @@ const useComponentProps = ({ node, areEntitiesFetched, resolveDesignValue, rende
|
|
|
2273
2442
|
'data-cf-node-block-id': node.data.blockId,
|
|
2274
2443
|
'data-cf-node-block-type': node.type,
|
|
2275
2444
|
};
|
|
2445
|
+
//List explicit style props that will end up being passed to the component
|
|
2446
|
+
const stylesToKeep = ['cfImageAsset'];
|
|
2447
|
+
const stylesToRemove = CF_STYLE_ATTRIBUTES.filter((style) => !stylesToKeep.includes(style));
|
|
2276
2448
|
const componentProps = {
|
|
2277
2449
|
className: componentClass,
|
|
2278
2450
|
editorMode: true,
|
|
2279
2451
|
node,
|
|
2280
2452
|
renderDropzone,
|
|
2281
|
-
...omit(props,
|
|
2453
|
+
...omit(props, stylesToRemove, ['cfHyperlink', 'cfOpenInNewTab']),
|
|
2282
2454
|
...(definition.children ? { children: renderDropzone(node) } : {}),
|
|
2283
2455
|
};
|
|
2284
2456
|
return { componentProps, wrapperProps };
|
|
@@ -2300,13 +2472,16 @@ var PostMessageMethods;
|
|
|
2300
2472
|
PostMessageMethods["REQUESTED_ENTITIES"] = "REQUESTED_ENTITIES";
|
|
2301
2473
|
})(PostMessageMethods || (PostMessageMethods = {}));
|
|
2302
2474
|
|
|
2303
|
-
var css_248z$
|
|
2475
|
+
var css_248z$5 = ".cf-heading {\n white-space: pre-line;\n}\n";
|
|
2476
|
+
styleInject(css_248z$5);
|
|
2477
|
+
|
|
2478
|
+
var css_248z$4 = ".cf-richtext {\n white-space: pre-line;\n}\n";
|
|
2304
2479
|
styleInject(css_248z$4);
|
|
2305
2480
|
|
|
2306
|
-
var css_248z$3 = ".cf-
|
|
2481
|
+
var css_248z$3 = ".cf-text {\n white-space: pre-line;\n}\n";
|
|
2307
2482
|
styleInject(css_248z$3);
|
|
2308
2483
|
|
|
2309
|
-
var css_248z$2$1 = ".cf-
|
|
2484
|
+
var css_248z$2$1 = ".cf-no-image {\n position: relative;\n}\n\n.cf-no-image img {\n background-color: var(--cf-color-gray100);\n outline-offset: -2px;\n outline: 2px solid rgba(var(--cf-color-gray400-rgb), 0.5);\n}\n\n[data-ctfl-draggable-id] .cf-no-image {\n width: 100%;\n height: 100%;\n}\n\n[data-ctfl-draggable-id] .cf-no-image img {\n width: 100%;\n}\n\n.cf-no-image svg {\n position: absolute;\n top: 50%;\n left: 50%;\n transform: translate(-50%, -50%);\n height: var(--cf-text-3xl);\n width: var(--cf-text-3xl);\n max-height: 100%;\n max-width: 100%;\n}\n\n.cf-no-image svg path {\n fill: var(--cf-color-gray400);\n}\n";
|
|
2310
2485
|
styleInject(css_248z$2$1);
|
|
2311
2486
|
|
|
2312
2487
|
var css_248z$1$1 = ".contentful-container {\n position: relative;\n display: flex;\n box-sizing: border-box;\n pointer-events: all;\n}\n\n.contentful-container::-webkit-scrollbar {\n display: none; /* Safari and Chrome */\n}\n\n.cf-single-column-wrapper {\n position: relative;\n}\n\n.cf-container-wrapper {\n position: relative;\n width: 100%;\n}\n\n.cf-container-label {\n position: absolute;\n pointer-events: none;\n top: 0;\n left: 0;\n right: 0;\n bottom: 0;\n display: flex;\n justify-content: center;\n align-items: center;\n overflow-x: clip;\n font-family: var(--exp-builder-font-stack-primary);\n font-size: 12px;\n color: var(--exp-builder-gray400);\n z-index: 10;\n}\n\n/* used by ContentfulSectionAsHyperlink.tsx */\n\n.contentful-container-link,\n.contentful-container-link:active,\n.contentful-container-link:visited,\n.contentful-container-link:hover,\n.contentful-container-link:read-write,\n.contentful-container-link:focus-visible {\n color: inherit;\n text-decoration: unset;\n outline: unset;\n}\n";
|
|
@@ -2334,8 +2509,8 @@ const Flex = forwardRef(({ id, children, onMouseEnter, onMouseUp, onMouseLeave,
|
|
|
2334
2509
|
});
|
|
2335
2510
|
Flex.displayName = 'Flex';
|
|
2336
2511
|
|
|
2337
|
-
var css_248z$
|
|
2338
|
-
styleInject(css_248z$
|
|
2512
|
+
var css_248z$6 = ".Columns {\n display: flex;\n gap: 24px;\n grid-template-columns: repeat(12, 1fr);\n flex-direction: column;\n min-height: 0; /* NEW */\n min-width: 0; /* NEW; needed for Firefox */\n}\n\n@media (min-width: 768px) {\n .Columns {\n display: grid;\n }\n}\n\n.cf-single-column-wrapper {\n position: relative;\n}\n\n.cf-single-column {\n pointer-events: all;\n}\n\n.cf-single-column-label {\n pointer-events: none;\n position: absolute;\n z-index: -1;\n top: 0;\n left: 0;\n right: 0;\n bottom: 0;\n display: flex;\n justify-content: center;\n align-items: center;\n font-family: var(--exp-builder-font-stack-primary);\n font-size: 12px;\n color: var(--exp-builder-gray400);\n z-index: 100;\n}\n";
|
|
2513
|
+
styleInject(css_248z$6);
|
|
2339
2514
|
|
|
2340
2515
|
const ColumnWrapper = forwardRef((props, ref) => {
|
|
2341
2516
|
return (React.createElement("div", { ref: ref, ...props, style: {
|
|
@@ -2558,7 +2733,7 @@ const DraggableChildComponent = (props) => {
|
|
|
2558
2733
|
})));
|
|
2559
2734
|
};
|
|
2560
2735
|
|
|
2561
|
-
var css_248z$2 = ".styles-module_container__te-1H {\n margin-left: auto;\n margin-right: auto;\n position: relative;\n height: 100%;\n width: 100%;\n background-color: transparent;\n transition: background-color 0.2s;\n pointer-events: all !important;\n}\n\n.styles-module_container__te-1H:not(.styles-module_isRoot__5cn-i):before {\n content: '';\n position: absolute;\n top: 0;\n right: 0;\n bottom: 0;\n left: 0;\n outline-offset: -1px;\n outline: 2px solid transparent;\n z-index: 1;\n transition: outline 0.2s;\n pointer-events: none;\n}\n\n.styles-module_isRoot__5cn-i,\n.styles-module_isEmptyCanvas__0XHZR {\n flex: 1;\n}\n\n.styles-module_isEmptyZone__zVpnZ {\n min-height: 80px;\n}\n\n.styles-module_isDragging__Gm8v5:not(.styles-module_isRoot__5cn-i):before {\n outline: 2px dashed var(--exp-builder-gray300);\n}\n\n.styles-module_isDestination__5sCQx:not(.styles-module_isRoot__5cn-i):before {\n transition:\n outline 0.2s,\n background-color 0.2s;\n outline: 2px dashed var(--exp-builder-blue400);\n background-color: rgba(var(--exp-builder-blue100-rgb), 0.5);\n z-index: 2;\n}\n\n.styles-module_hitbox__YQ-1Z {\n position: fixed;\n pointer-events: all !important;\n}\n";
|
|
2736
|
+
var css_248z$2 = ".styles-module_container__te-1H {\n margin-left: auto;\n margin-right: auto;\n position: relative;\n height: 100%;\n width: 100%;\n background-color: transparent;\n transition: background-color 0.2s;\n pointer-events: all !important;\n}\n\n.styles-module_container__te-1H:not(.styles-module_isRoot__5cn-i):before {\n content: '';\n position: absolute;\n top: 0;\n right: 0;\n bottom: 0;\n left: 0;\n outline-offset: -1px;\n outline: 2px solid transparent;\n z-index: 1;\n transition: outline 0.2s;\n pointer-events: none;\n}\n\n.styles-module_isRoot__5cn-i,\n.styles-module_isEmptyCanvas__0XHZR {\n flex: 1;\n}\n\n.styles-module_isEmptyZone__zVpnZ {\n min-height: 80px;\n}\n\n.styles-module_isDragging__Gm8v5:not(.styles-module_isRoot__5cn-i):before {\n outline: 2px dashed var(--exp-builder-gray300);\n}\n\n.styles-module_isDestination__5sCQx:not(.styles-module_isRoot__5cn-i):before {\n transition:\n outline 0.2s,\n background-color 0.2s;\n outline: 2px dashed var(--exp-builder-blue400);\n background-color: rgba(var(--exp-builder-blue100-rgb), 0.5);\n z-index: 2;\n}\n\n.styles-module_hitbox__YQ-1Z {\n position: fixed;\n pointer-events: all !important;\n}\n\n.styles-module_hitbox__YQ-1Z {\n position: fixed;\n pointer-events: all !important;\n}\n";
|
|
2562
2737
|
var styles$2 = {"container":"styles-module_container__te-1H","isRoot":"styles-module_isRoot__5cn-i","isEmptyCanvas":"styles-module_isEmptyCanvas__0XHZR","isEmptyZone":"styles-module_isEmptyZone__zVpnZ","isDragging":"styles-module_isDragging__Gm8v5","isDestination":"styles-module_isDestination__5sCQx","hitbox":"styles-module_hitbox__YQ-1Z"};
|
|
2563
2738
|
styleInject(css_248z$2);
|
|
2564
2739
|
|
|
@@ -3102,11 +3277,11 @@ const EditorBlock = ({ node: rawNode, resolveDesignValue, renderDropzone, draggi
|
|
|
3102
3277
|
if (node.data.blockId === CONTENTFUL_COMPONENTS.singleColumn.id) {
|
|
3103
3278
|
return (React.createElement(React.Fragment, null,
|
|
3104
3279
|
React.createElement(DraggableChildComponent, { elementToRender: elementToRender, id: componentId, index: index, isAssemblyBlock: isAssemblyBlock, isDragDisabled: isSingleColumn, isSelected: selectedNodeId === componentId, userIsDragging: userIsDragging, isContainer: isContainer, blockId: node.data.blockId, coordinates: coordinates, wrapperProps: wrapperProps, onClick: onClick, definition: definition }),
|
|
3105
|
-
isStructureComponent && userIsDragging && (React.createElement(Hitboxes, { parentZoneId: zoneId, zoneId: componentId, enableRootHitboxes: enableRootHitboxes }))));
|
|
3280
|
+
isStructureComponent && !isSingleColumn && userIsDragging && (React.createElement(Hitboxes, { parentZoneId: zoneId, zoneId: componentId, enableRootHitboxes: enableRootHitboxes }))));
|
|
3106
3281
|
}
|
|
3107
3282
|
return (React.createElement(DraggableComponent, { placeholder: placeholder, definition: definition, id: componentId, index: index, isAssemblyBlock: isAssemblyBlock, isDragDisabled: isAssemblyBlock, isSelected: selectedNodeId === componentId, userIsDragging: userIsDragging, isContainer: isContainer, blockId: node.data.blockId, coordinates: coordinates, wrapperProps: wrapperProps, onClick: onClick },
|
|
3108
3283
|
elementToRender(),
|
|
3109
|
-
isStructureComponent && userIsDragging && (React.createElement(Hitboxes, { parentZoneId: zoneId, zoneId: componentId, enableRootHitboxes: enableRootHitboxes }))));
|
|
3284
|
+
isStructureComponent && !isSingleColumn && userIsDragging && (React.createElement(Hitboxes, { parentZoneId: zoneId, zoneId: componentId, enableRootHitboxes: enableRootHitboxes }))));
|
|
3110
3285
|
};
|
|
3111
3286
|
|
|
3112
3287
|
var css_248z$1 = ".EmptyContainer-module_container__XPH5b {\n height: 200px;\n display: flex;\n width: 100%;\n position: absolute;\n align-items: center;\n justify-content: center;\n flex-direction: row;\n transition: all 0.2s;\n color: var(--exp-builder-gray400);\n font-size: var(--exp-builder-font-size-l);\n font-family: var(--exp-builder-font-stack-primary);\n outline: 2px dashed var(--exp-builder-gray400);\n outline-offset: -2px;\n}\n\n.EmptyContainer-module_highlight__lcICy:hover {\n outline: 2px dashed var(--exp-builder-blue500);\n background-color: rgba(var(--exp-builder-blue100-rgb), 0.5);\n cursor: grabbing;\n}\n\n.EmptyContainer-module_icon__82-2O rect {\n fill: var(--exp-builder-gray400);\n}\n\n.EmptyContainer-module_label__4TxRa {\n margin-left: var(--exp-builder-spacing-s);\n}\n";
|
|
@@ -3633,6 +3808,7 @@ function useEditorSubscriber() {
|
|
|
3633
3808
|
const setDataSource = useEditorStore((state) => state.setDataSource);
|
|
3634
3809
|
const setSelectedNodeId = useEditorStore((state) => state.setSelectedNodeId);
|
|
3635
3810
|
const selectedNodeId = useEditorStore((state) => state.selectedNodeId);
|
|
3811
|
+
const resetEntityStore = useEntityStore((state) => state.resetEntityStore);
|
|
3636
3812
|
const setComponentId = useDraggedItemStore((state) => state.setComponentId);
|
|
3637
3813
|
const setDraggingOnCanvas = useDraggedItemStore((state) => state.setDraggingOnCanvas);
|
|
3638
3814
|
const setMousePosition = useDraggedItemStore((state) => state.setMousePosition);
|
|
@@ -3654,7 +3830,7 @@ function useEditorSubscriber() {
|
|
|
3654
3830
|
* Fills up entityStore with entities from newDataSource and from the tree.
|
|
3655
3831
|
* Also manages "entity status" variables (areEntitiesFetched, isFetchingEntities)
|
|
3656
3832
|
*/
|
|
3657
|
-
const fetchMissingEntities = useCallback(async (newDataSource, tree) => {
|
|
3833
|
+
const fetchMissingEntities = useCallback(async (entityStore, newDataSource, tree) => {
|
|
3658
3834
|
// if we realize that there's nothing missing and nothing to fill-fetch before we do any async call,
|
|
3659
3835
|
// then we can simply return and not lock the EntityStore at all.
|
|
3660
3836
|
const startFetching = () => {
|
|
@@ -3725,10 +3901,7 @@ function useEditorSubscriber() {
|
|
|
3725
3901
|
finally {
|
|
3726
3902
|
endFetching();
|
|
3727
3903
|
}
|
|
3728
|
-
}, [
|
|
3729
|
-
/* dataSource, */ entityStore,
|
|
3730
|
-
setEntitiesFetched /* setFetchingEntities, assembliesRegistry */,
|
|
3731
|
-
]);
|
|
3904
|
+
}, [setEntitiesFetched /* setFetchingEntities, assembliesRegistry */]);
|
|
3732
3905
|
useEffect(() => {
|
|
3733
3906
|
const onMessage = async (event) => {
|
|
3734
3907
|
let reason;
|
|
@@ -3758,6 +3931,11 @@ function useEditorSubscriber() {
|
|
|
3758
3931
|
// If the assemblyEntry is not yet fetched, this will be done below by
|
|
3759
3932
|
// the imperative calls to fetchMissingEntities.
|
|
3760
3933
|
}
|
|
3934
|
+
let newEntityStore = entityStore;
|
|
3935
|
+
if (entityStore.locale !== locale) {
|
|
3936
|
+
newEntityStore = resetEntityStore(locale);
|
|
3937
|
+
setLocale(locale);
|
|
3938
|
+
}
|
|
3761
3939
|
// Below are mutually exclusive cases
|
|
3762
3940
|
if (changedNode) {
|
|
3763
3941
|
/**
|
|
@@ -3770,7 +3948,7 @@ function useEditorSubscriber() {
|
|
|
3770
3948
|
if (changedValueType === 'BoundValue') {
|
|
3771
3949
|
const newDataSource = { ...dataSource, ...changedNode.data.dataSource };
|
|
3772
3950
|
setDataSource(newDataSource);
|
|
3773
|
-
await fetchMissingEntities(newDataSource, tree);
|
|
3951
|
+
await fetchMissingEntities(newEntityStore, newDataSource, tree);
|
|
3774
3952
|
}
|
|
3775
3953
|
else if (changedValueType === 'UnboundValue') {
|
|
3776
3954
|
setUnboundValues({
|
|
@@ -3778,19 +3956,15 @@ function useEditorSubscriber() {
|
|
|
3778
3956
|
...changedNode.data.unboundValues,
|
|
3779
3957
|
});
|
|
3780
3958
|
}
|
|
3781
|
-
// Update the tree when all necessary data is fetched and ready for rendering.
|
|
3782
|
-
updateTree(tree);
|
|
3783
|
-
setLocale(locale);
|
|
3784
3959
|
}
|
|
3785
3960
|
else {
|
|
3786
3961
|
const { dataSource, unboundValues } = getDataFromTree(tree);
|
|
3787
3962
|
setDataSource(dataSource);
|
|
3788
3963
|
setUnboundValues(unboundValues);
|
|
3789
|
-
await fetchMissingEntities(dataSource, tree);
|
|
3790
|
-
// Update the tree when all necessary data is fetched and ready for rendering.
|
|
3791
|
-
updateTree(tree);
|
|
3792
|
-
setLocale(locale);
|
|
3964
|
+
await fetchMissingEntities(newEntityStore, dataSource, tree);
|
|
3793
3965
|
}
|
|
3966
|
+
// Update the tree when all necessary data is fetched and ready for rendering.
|
|
3967
|
+
updateTree(tree);
|
|
3794
3968
|
break;
|
|
3795
3969
|
}
|
|
3796
3970
|
case INCOMING_EVENTS.AssembliesRegistered: {
|
|
@@ -3924,6 +4098,7 @@ function useEditorSubscriber() {
|
|
|
3924
4098
|
updateTree,
|
|
3925
4099
|
updateNodesByUpdatedEntity,
|
|
3926
4100
|
setMousePosition,
|
|
4101
|
+
resetEntityStore,
|
|
3927
4102
|
]);
|
|
3928
4103
|
/*
|
|
3929
4104
|
* Handles on scroll business
|
|
@@ -4304,20 +4479,8 @@ const useInitializeEditor = () => {
|
|
|
4304
4479
|
|
|
4305
4480
|
const VisualEditorRoot = () => {
|
|
4306
4481
|
const initialized = useInitializeEditor();
|
|
4307
|
-
const locale = useEditorStore((state) => state.locale);
|
|
4308
4482
|
const setMousePosition = useDraggedItemStore((state) => state.setMousePosition);
|
|
4309
|
-
const entityStore = useEntityStore((state) => state.entityStore);
|
|
4310
4483
|
const setHoveringZone = useZoneStore((state) => state.setHoveringZone);
|
|
4311
|
-
const resetEntityStore = useEntityStore((state) => state.resetEntityStore);
|
|
4312
|
-
useEffect(() => {
|
|
4313
|
-
if (!locale) {
|
|
4314
|
-
return;
|
|
4315
|
-
}
|
|
4316
|
-
if (entityStore.locale === locale) {
|
|
4317
|
-
return;
|
|
4318
|
-
}
|
|
4319
|
-
resetEntityStore(locale);
|
|
4320
|
-
}, [locale, resetEntityStore, entityStore.locale]);
|
|
4321
4484
|
useEffect(() => {
|
|
4322
4485
|
const onMouseMove = (e) => {
|
|
4323
4486
|
setMousePosition(e.clientX, e.clientY);
|