@contentful/experiences-visual-editor-react 1.34.0-dev-20250228T1701-87c41f6.0 → 1.34.1-beta.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -12,8 +12,8 @@ import { v4 } from 'uuid';
12
12
  import { createPortal } from 'react-dom';
13
13
  import classNames from 'classnames';
14
14
 
15
- var css_248z$a = "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";
16
- styleInject(css_248z$a);
15
+ var css_248z$b = "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";
16
+ styleInject(css_248z$b);
17
17
 
18
18
  const INCOMING_EVENTS$1 = {
19
19
  RequestEditorMode: 'requestEditorMode',
@@ -384,45 +384,85 @@ const toCSSAttribute = (key) => {
384
384
  val = val.replace(/\d+$/, '');
385
385
  return val;
386
386
  };
387
- const buildStyleTag = ({ styles, nodeId }) => {
388
- const stylesStr = Object.entries(styles)
387
+ /**
388
+ * Turns a list of CSSProperties into a joined CSS string that can be
389
+ * used for <style> tags. Per default it creates a minimized version.
390
+ * For editor mode, use the `useWhitespaces` flag to create a more readable version.
391
+ *
392
+ * @param cssProperties list of CSS properties
393
+ * @param useWhitespaces adds whitespaces and newlines between each rule
394
+ * @returns a string of CSS rules
395
+ */
396
+ const stringifyCssProperties = (cssProperties, useWhitespaces = false) => {
397
+ const rules = Object.entries(cssProperties)
389
398
  .filter(([, value]) => value !== undefined)
390
- .reduce((acc, [key, value]) => `${acc}
391
- ${toCSSAttribute(key)}: ${value};`, '');
392
- const className = `cfstyles-${nodeId ? nodeId : md5(stylesStr)}`;
393
- const styleRule = `.${className}{ ${stylesStr} }`;
399
+ .map(([key, value]) => useWhitespaces ? `${toCSSAttribute(key)}: ${value};` : `${toCSSAttribute(key)}:${value};`);
400
+ return rules.join(useWhitespaces ? '\n' : '');
401
+ };
402
+ const buildStyleTag = ({ styles, nodeId }) => {
403
+ const generatedStyles = stringifyCssProperties(styles, true);
404
+ const className = `cfstyles-${nodeId ? nodeId : md5(generatedStyles)}`;
405
+ const styleRule = `.${className}{ ${generatedStyles} }`;
394
406
  return [className, styleRule];
395
407
  };
396
- const buildCfStyles = ({ cfHorizontalAlignment, cfVerticalAlignment, cfFlexDirection, cfFlexReverse, cfFlexWrap, cfMargin, cfPadding, cfBackgroundColor, cfWidth, cfHeight, cfMaxWidth, cfBorder, cfBorderRadius, cfGap, cfBackgroundImageUrl, cfBackgroundImageOptions, cfFontSize, cfFontWeight, cfImageOptions, cfLineHeight, cfLetterSpacing, cfTextColor, cfTextAlign, cfTextTransform, cfTextBold, cfTextItalic, cfTextUnderline, cfColumnSpan, cfVisibility, }) => {
397
- return {
408
+ /**
409
+ * Takes plain design values and transforms them into CSS properties. Undefined values will
410
+ * be filtered out.
411
+ *
412
+ * **Example Input**
413
+ * ```
414
+ * values = {
415
+ * cfVisibility: 'visible',
416
+ * cfMargin: '10px',
417
+ * cfFlexReverse: true,
418
+ * cfImageOptions: { objectFit: 'cover' },
419
+ * // ...
420
+ * }
421
+ * ```
422
+ * **Example Output**
423
+ * ```
424
+ * cssProperties = {
425
+ * margin: '10px',
426
+ * flexDirection: 'row-reverse',
427
+ * objectFit: 'cover',
428
+ * // ...
429
+ * }
430
+ * ```
431
+ */
432
+ const buildCfStyles = (values) => {
433
+ const cssProperties = {
398
434
  boxSizing: 'border-box',
399
- ...transformVisibility(cfVisibility),
400
- margin: cfMargin,
401
- padding: cfPadding,
402
- backgroundColor: cfBackgroundColor,
403
- width: transformFill(cfWidth || cfImageOptions?.width),
404
- height: transformFill(cfHeight || cfImageOptions?.height),
405
- maxWidth: cfMaxWidth,
406
- ...transformGridColumn(cfColumnSpan),
407
- ...transformBorderStyle(cfBorder),
408
- borderRadius: cfBorderRadius,
409
- gap: cfGap,
410
- ...transformAlignment(cfHorizontalAlignment, cfVerticalAlignment, cfFlexDirection),
411
- flexDirection: cfFlexReverse && cfFlexDirection ? `${cfFlexDirection}-reverse` : cfFlexDirection,
412
- flexWrap: cfFlexWrap,
413
- ...transformBackgroundImage(cfBackgroundImageUrl, cfBackgroundImageOptions),
414
- fontSize: cfFontSize,
415
- fontWeight: cfTextBold ? 'bold' : cfFontWeight,
416
- fontStyle: cfTextItalic ? 'italic' : undefined,
417
- textDecoration: cfTextUnderline ? 'underline' : undefined,
418
- lineHeight: cfLineHeight,
419
- letterSpacing: cfLetterSpacing,
420
- color: cfTextColor,
421
- textAlign: cfTextAlign,
422
- textTransform: cfTextTransform,
423
- objectFit: cfImageOptions?.objectFit,
424
- objectPosition: cfImageOptions?.objectPosition,
435
+ ...transformVisibility(values.cfVisibility),
436
+ margin: values.cfMargin,
437
+ padding: values.cfPadding,
438
+ backgroundColor: values.cfBackgroundColor,
439
+ width: transformFill(values.cfWidth || values.cfImageOptions?.width),
440
+ height: transformFill(values.cfHeight || values.cfImageOptions?.height),
441
+ maxWidth: values.cfMaxWidth,
442
+ ...transformGridColumn(values.cfColumnSpan),
443
+ ...transformBorderStyle(values.cfBorder),
444
+ borderRadius: values.cfBorderRadius,
445
+ gap: values.cfGap,
446
+ ...transformAlignment(values.cfHorizontalAlignment, values.cfVerticalAlignment, values.cfFlexDirection),
447
+ flexDirection: values.cfFlexReverse && values.cfFlexDirection
448
+ ? `${values.cfFlexDirection}-reverse`
449
+ : values.cfFlexDirection,
450
+ flexWrap: values.cfFlexWrap,
451
+ ...transformBackgroundImage(values.cfBackgroundImageUrl, values.cfBackgroundImageOptions),
452
+ fontSize: values.cfFontSize,
453
+ fontWeight: values.cfTextBold ? 'bold' : values.cfFontWeight,
454
+ fontStyle: values.cfTextItalic ? 'italic' : undefined,
455
+ textDecoration: values.cfTextUnderline ? 'underline' : undefined,
456
+ lineHeight: values.cfLineHeight,
457
+ letterSpacing: values.cfLetterSpacing,
458
+ color: values.cfTextColor,
459
+ textAlign: values.cfTextAlign,
460
+ textTransform: values.cfTextTransform,
461
+ objectFit: values.cfImageOptions?.objectFit,
462
+ objectPosition: values.cfImageOptions?.objectPosition,
425
463
  };
464
+ const cssPropertiesWithoutUndefined = Object.fromEntries(Object.entries(cssProperties).filter(([, value]) => value !== undefined));
465
+ return cssPropertiesWithoutUndefined;
426
466
  };
427
467
  /**
428
468
  * Container/section default behavior:
@@ -947,11 +987,13 @@ const VariableMappingsSchema$1 = z.record(propertyKeySchema$1, VariableMappingSc
947
987
  // https://contentful.atlassian.net/browse/LUMOS-523
948
988
  const PatternPropertyDefinitionSchema$1 = z.object({
949
989
  defaultValue: z
950
- .object({
951
- path: z.string(),
952
- type: z.literal('BoundValue'),
953
- contentType: z.string(),
954
- })
990
+ .record(z.string(), z.object({
991
+ sys: z.object({
992
+ type: z.literal('Link'),
993
+ id: z.string(),
994
+ linkType: z.enum(['Entry']),
995
+ }),
996
+ }))
955
997
  .optional(),
956
998
  contentTypes: z.record(z.string(), z.any()),
957
999
  });
@@ -3009,9 +3051,9 @@ const cloneDeepAsPOJO = (obj) => {
3009
3051
  return JSON.parse(JSON.stringify(obj));
3010
3052
  };
3011
3053
 
3012
- var css_248z$9 = ".render-module_hitbox__l4ysJ {\n position: absolute;\n top: 0;\n left: 0;\n width: 100%;\n height: 10px;\n z-index: 1000000;\n}\n\n.render-module_hitboxLower__tgsA1 {\n position: absolute;\n bottom: -20px;\n left: 0;\n width: 100%;\n height: 20px;\n z-index: 1000000;\n}\n\n.render-module_canvasBottomSpacer__JuxVh {\n position: absolute;\n width: 100%;\n height: 50px;\n}\n\n.render-module_container__-C3d7 {\n position: relative;\n display: flex;\n flex-direction: column;\n}\n\nbody {\n margin: 0;\n}\n\nhtml {\n -ms-overflow-style: none; /* Internet Explorer 10+ */\n scrollbar-width: none; /* Firefox */\n}\n\nhtml::-webkit-scrollbar {\n display: none;\n}\n";
3054
+ var css_248z$a = ".render-module_hitbox__l4ysJ {\n position: absolute;\n top: 0;\n left: 0;\n width: 100%;\n height: 10px;\n z-index: 1000000;\n}\n\n.render-module_hitboxLower__tgsA1 {\n position: absolute;\n bottom: -20px;\n left: 0;\n width: 100%;\n height: 20px;\n z-index: 1000000;\n}\n\n.render-module_canvasBottomSpacer__JuxVh {\n position: absolute;\n width: 100%;\n height: 50px;\n}\n\n.render-module_container__-C3d7 {\n position: relative;\n display: flex;\n flex-direction: column;\n}\n\nbody {\n margin: 0;\n}\n\nhtml {\n -ms-overflow-style: none; /* Internet Explorer 10+ */\n scrollbar-width: none; /* Firefox */\n}\n\nhtml::-webkit-scrollbar {\n display: none;\n}\n";
3013
3055
  var styles$3 = {"hitbox":"render-module_hitbox__l4ysJ","hitboxLower":"render-module_hitboxLower__tgsA1","canvasBottomSpacer":"render-module_canvasBottomSpacer__JuxVh","container":"render-module_container__-C3d7"};
3014
- styleInject(css_248z$9);
3056
+ styleInject(css_248z$a);
3015
3057
 
3016
3058
  // TODO: In order to support integrations without React, we should extract this heavy logic into simple
3017
3059
  // functions that we can reuse in other frameworks.
@@ -3180,6 +3222,9 @@ const useEditorStore = create((set, get) => ({
3180
3222
  },
3181
3223
  }));
3182
3224
 
3225
+ var css_248z$8 = "/* Initially added with PR #253 for each component, this is now a global setting\n * It is recommended on MDN to use this as a default for layouting.\n*/\n* {\n box-sizing: border-box;\n}\n";
3226
+ styleInject(css_248z$8);
3227
+
3183
3228
  /**
3184
3229
  * These modes are ONLY intended to be internally used within the context of
3185
3230
  * editing an experience inside of Contentful Studio. i.e. these modes
@@ -3382,11 +3427,13 @@ const VariableMappingsSchema = z.record(propertyKeySchema, VariableMappingSchema
3382
3427
  // https://contentful.atlassian.net/browse/LUMOS-523
3383
3428
  const PatternPropertyDefinitionSchema = z.object({
3384
3429
  defaultValue: z
3385
- .object({
3386
- path: z.string(),
3387
- type: z.literal('BoundValue'),
3388
- contentType: z.string(),
3389
- })
3430
+ .record(z.string(), z.object({
3431
+ sys: z.object({
3432
+ type: z.literal('Link'),
3433
+ id: z.string(),
3434
+ linkType: z.enum(['Entry']),
3435
+ }),
3436
+ }))
3390
3437
  .optional(),
3391
3438
  contentTypes: z.record(z.string(), z.any()),
3392
3439
  });
@@ -3698,8 +3745,8 @@ Flex.displayName = 'Flex';
3698
3745
  var css_248z$1$1 = ".cf-divider {\n display: contents;\n position: relative;\n width: 100%;\n height: 100%;\n}\n\n.cf-divider hr {\n border: none;\n}\n\n/* For the editor mode add this 10px tolerance to make it easier picking up the divider component.\n * Using the DND zone as precondition makes sure that we don't render this pseudo element in delivery. */\n\n[data-ctfl-zone-id='root'] .cf-divider::before {\n content: \"\";\n position: absolute;\n top: -5px;\n left: -5px;\n bottom: -5px;\n right: -5px;\n pointer-events: all;\n}\n";
3699
3746
  styleInject(css_248z$1$1);
3700
3747
 
3701
- var css_248z$8 = ".cf-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 .cf-columns {\n display: grid;\n }\n}\n\n.cf-single-column-wrapper {\n position: relative;\n display: flex;\n}\n\n.cf-single-column {\n pointer-events: all;\n}\n\n.cf-single-column-wrapper:after {\n content: '';\n display: block;\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: 1;\n}\n\n.cf-single-column-label:after {\n content: 'Column';\n}\n";
3702
- styleInject(css_248z$8);
3748
+ var css_248z$9 = ".cf-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 .cf-columns {\n display: grid;\n }\n}\n\n.cf-single-column-wrapper {\n position: relative;\n display: flex;\n}\n\n.cf-single-column {\n pointer-events: all;\n}\n\n.cf-single-column-wrapper:after {\n content: '';\n display: block;\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: 1;\n}\n\n.cf-single-column-label:after {\n content: 'Column';\n}\n";
3749
+ styleInject(css_248z$9);
3703
3750
 
3704
3751
  const ColumnWrapper = forwardRef((props, ref) => {
3705
3752
  return (React.createElement("div", { ref: ref, ...props, style: {