@builder.io/sdk-svelte 5.2.5 → 5.2.7

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.
Files changed (37) hide show
  1. package/lib/browser/blocks/image/component-info.js +2 -1
  2. package/lib/browser/blocks/image/image.svelte +7 -4
  3. package/lib/browser/blocks/image/image.svelte.d.ts +2 -2
  4. package/lib/browser/blocks/personalization-container/helpers.d.ts +2 -0
  5. package/lib/browser/blocks/personalization-container/helpers.js +30 -3
  6. package/lib/browser/components/content/components/enable-editor.svelte +1 -0
  7. package/lib/browser/components/content-variants/content-variants.svelte +4 -3
  8. package/lib/browser/components/content-variants/content-variants.svelte.d.ts +1 -1
  9. package/lib/browser/constants/sdk-version.d.ts +1 -1
  10. package/lib/browser/constants/sdk-version.js +1 -1
  11. package/lib/edge/blocks/image/component-info.js +2 -1
  12. package/lib/edge/blocks/image/image.svelte +7 -4
  13. package/lib/edge/blocks/image/image.svelte.d.ts +2 -2
  14. package/lib/edge/blocks/personalization-container/helpers.d.ts +2 -0
  15. package/lib/edge/blocks/personalization-container/helpers.js +30 -3
  16. package/lib/edge/components/content/components/enable-editor.svelte +1 -0
  17. package/lib/edge/components/content-variants/content-variants.svelte +4 -3
  18. package/lib/edge/components/content-variants/content-variants.svelte.d.ts +1 -1
  19. package/lib/edge/constants/sdk-version.d.ts +1 -1
  20. package/lib/edge/constants/sdk-version.js +1 -1
  21. package/lib/node/blocks/image/component-info.js +2 -1
  22. package/lib/node/blocks/image/image.svelte +7 -4
  23. package/lib/node/blocks/image/image.svelte.d.ts +2 -2
  24. package/lib/node/blocks/personalization-container/helpers.d.ts +2 -0
  25. package/lib/node/blocks/personalization-container/helpers.js +30 -3
  26. package/lib/node/components/content/components/enable-editor.svelte +1 -0
  27. package/lib/node/components/content-variants/content-variants.svelte +4 -3
  28. package/lib/node/components/content-variants/content-variants.svelte.d.ts +1 -1
  29. package/lib/node/constants/sdk-version.d.ts +1 -1
  30. package/lib/node/constants/sdk-version.js +1 -1
  31. package/package.json +1 -1
  32. package/src/blocks/image/component-info.ts +2 -1
  33. package/src/blocks/image/image.svelte +7 -4
  34. package/src/blocks/personalization-container/helpers.ts +31 -3
  35. package/src/components/content/components/enable-editor.svelte +1 -0
  36. package/src/components/content-variants/content-variants.svelte +6 -3
  37. package/src/constants/sdk-version.ts +1 -1
@@ -102,7 +102,8 @@ export const componentInfo = {
102
102
  }, {
103
103
  name: 'sizes',
104
104
  type: 'string',
105
- hideFromUI: true
105
+ advanced: true,
106
+ helperText: 'The sizes attribute for responsive images, e.g. "(max-width: 600px) 100vw, 50vw"'
106
107
  }, {
107
108
  name: 'srcset',
108
109
  type: 'string',
@@ -4,14 +4,14 @@ export let image;
4
4
  export let src = undefined;
5
5
  export let srcset = undefined;
6
6
  export let noWebp = undefined;
7
- export let aspectRatio = undefined;
7
+ export let sizes = undefined;
8
8
  export let highPriority = undefined;
9
+ export let aspectRatio = undefined;
9
10
  export let altText = undefined;
10
11
  export let title = undefined;
11
12
  export let backgroundPosition = undefined;
12
13
  export let backgroundSize = undefined;
13
14
  export let className = undefined;
14
- export let sizes = undefined;
15
15
  export let builderBlock = undefined;
16
16
  export let fitContent = undefined;
17
17
  function stringifyStyles(stylesObj) {
@@ -56,6 +56,9 @@ $: webpSrcSet = () => {
56
56
  return "";
57
57
  }
58
58
  };
59
+ $: sizesToUse = () => {
60
+ return sizes || (highPriority ? undefined : "auto");
61
+ };
59
62
  $: aspectRatioCss = () => {
60
63
  const aspectRatioStyles = {
61
64
  position: "absolute",
@@ -72,7 +75,7 @@ onMount(() => { });
72
75
 
73
76
  <picture>
74
77
  {#if webpSrcSet()}
75
- <source type="image/webp" srcset={webpSrcSet()} />
78
+ <source type="image/webp" srcset={webpSrcSet()} sizes={sizesToUse()} />
76
79
  {/if}<img
77
80
  style={stringifyStyles({
78
81
  objectPosition: backgroundPosition || "center",
@@ -87,7 +90,7 @@ onMount(() => { });
87
90
  class={"builder-image" + (className ? " " + className : "") + " img"}
88
91
  src={image}
89
92
  srcset={srcSetToUse()}
90
- {sizes}
93
+ sizes={sizesToUse()}
91
94
  /></picture
92
95
  >
93
96
 
@@ -6,14 +6,14 @@ declare const __propDef: {
6
6
  src?: ImageProps["src"];
7
7
  srcset?: ImageProps["srcset"];
8
8
  noWebp?: ImageProps["noWebp"];
9
- aspectRatio?: ImageProps["aspectRatio"];
9
+ sizes?: ImageProps["sizes"];
10
10
  highPriority?: ImageProps["highPriority"];
11
+ aspectRatio?: ImageProps["aspectRatio"];
11
12
  altText?: ImageProps["altText"];
12
13
  title?: ImageProps["title"];
13
14
  backgroundPosition?: ImageProps["backgroundPosition"];
14
15
  backgroundSize?: ImageProps["backgroundSize"];
15
16
  className?: ImageProps["className"];
16
- sizes?: ImageProps["sizes"];
17
17
  builderBlock?: ImageProps["builderBlock"];
18
18
  fitContent?: ImageProps["fitContent"];
19
19
  };
@@ -1,4 +1,5 @@
1
1
  import type { BuilderBlock } from '../../types/builder-block';
2
+ import type { BuilderContent } from '../../types/builder-content';
2
3
  import type { Target } from '../../types/targets';
3
4
  import type { PersonalizationContainerProps } from './personalization-container.types';
4
5
  export declare const DEFAULT_INDEX = "default";
@@ -41,6 +42,7 @@ export declare function getBlocksToRender({ variants, previewingIndex, isHydrate
41
42
  filteredVariants: PersonalizationContainerProps['variants'];
42
43
  fallbackBlocks?: BuilderBlock[];
43
44
  }): BlocksToRenderReturnType;
45
+ export declare const hasPersonalizationContainer: (content: BuilderContent | null | undefined) => boolean;
44
46
  export declare const getInitPersonalizationVariantsFnsScriptString: () => string;
45
47
  export declare const getPersonalizationScript: (variants: PersonalizationContainerProps['variants'], blockId: string, locale?: string) => string;
46
48
  export declare const getUpdateVisibilityStylesScript: (variants: PersonalizationContainerProps['variants'], blockId: string, locale?: string) => string;
@@ -6,6 +6,7 @@ export const DEFAULT_INDEX = 'default';
6
6
  const FILTER_WITH_CUSTOM_TARGETING_SCRIPT_FN_NAME = 'filterWithCustomTargeting';
7
7
  const BUILDER_IO_PERSONALIZATION_SCRIPT_FN_NAME = 'builderIoPersonalization';
8
8
  const UPDATE_VARIANT_VISIBILITY_SCRIPT_FN_NAME = 'updateVisibilityStylesScript';
9
+ const PERSONALIZATION_CONTAINER_COMPONENT_NAME = 'PersonalizationContainer';
9
10
  /**
10
11
  * SDKs that support Variant Containers
11
12
  */
@@ -72,11 +73,37 @@ export function getBlocksToRender({ variants, previewingIndex, isHydrated, filte
72
73
  // If no winning variant or we are on the server, return the default variant
73
74
  return fallback;
74
75
  }
76
+ /**
77
+ * Walks the whole content rather than a known set of paths. A/B variation blocks live on
78
+ * `variations[*].data.blocks`, a sibling of `data.blocks`, and containers can sit inside columns,
79
+ * tabs, slots or inlined symbols. A missed container leaves the inlined fns undefined at parse
80
+ * time, so every variant renders at once.
81
+ */
82
+ const containsPersonalizationContainer = (value) => {
83
+ if (Array.isArray(value)) {
84
+ return value.some(containsPersonalizationContainer);
85
+ }
86
+ if (!value || typeof value !== 'object')
87
+ return false;
88
+ if (value.component?.name === PERSONALIZATION_CONTAINER_COMPONENT_NAME) {
89
+ return true;
90
+ }
91
+ return Object.values(value).some(containsPersonalizationContainer);
92
+ };
93
+ export const hasPersonalizationContainer = (content) => containsPersonalizationContainer(content);
75
94
  export const getInitPersonalizationVariantsFnsScriptString = () => {
76
95
  return `
77
- window.${FILTER_WITH_CUSTOM_TARGETING_SCRIPT_FN_NAME} = ${FILTER_WITH_CUSTOM_TARGETING_SCRIPT}
78
- window.${BUILDER_IO_PERSONALIZATION_SCRIPT_FN_NAME} = ${PERSONALIZATION_SCRIPT}
79
- window.${UPDATE_VARIANT_VISIBILITY_SCRIPT_FN_NAME} = ${UPDATE_VISIBILITY_STYLES_SCRIPT}
96
+ (function() {
97
+ if (!window.${FILTER_WITH_CUSTOM_TARGETING_SCRIPT_FN_NAME}) {
98
+ window.${FILTER_WITH_CUSTOM_TARGETING_SCRIPT_FN_NAME} = ${FILTER_WITH_CUSTOM_TARGETING_SCRIPT};
99
+ }
100
+ if (!window.${BUILDER_IO_PERSONALIZATION_SCRIPT_FN_NAME}) {
101
+ window.${BUILDER_IO_PERSONALIZATION_SCRIPT_FN_NAME} = ${PERSONALIZATION_SCRIPT};
102
+ }
103
+ if (!window.${UPDATE_VARIANT_VISIBILITY_SCRIPT_FN_NAME}) {
104
+ window.${UPDATE_VARIANT_VISIBILITY_SCRIPT_FN_NAME} = ${UPDATE_VISIBILITY_STYLES_SCRIPT};
105
+ }
106
+ })();
80
107
  `;
81
108
  };
82
109
  const isHydrationTarget = TARGET === 'react';
@@ -281,6 +281,7 @@ let hasExecuted = false;
281
281
  let contextValue = $builderContextSignal;
282
282
  let prevData = null;
283
283
  let prevLocale = "";
284
+ let prevContent = null;
284
285
  let ContentWrapper = contentWrapper || "div";
285
286
  let httpReqsData = {};
286
287
  let httpReqsPending = {};
@@ -1,7 +1,7 @@
1
1
  <script context="module"></script>
2
2
 
3
3
  <script>import { onMount } from "svelte";
4
- import { SDKS_SUPPORTING_PERSONALIZATION, getInitPersonalizationVariantsFnsScriptString, } from "../../blocks/personalization-container/helpers";
4
+ import { SDKS_SUPPORTING_PERSONALIZATION, getInitPersonalizationVariantsFnsScriptString, hasPersonalizationContainer, } from "../../blocks/personalization-container/helpers";
5
5
  import { TARGET } from "../../constants/target";
6
6
  import { handleABTestingSync } from "../../helpers/ab-tests";
7
7
  import { getDefaultCanTrack } from "../../helpers/canTrack";
@@ -11,9 +11,9 @@ import InlinedStyles from "../inlined-styles.svelte";
11
11
  import { checkShouldRenderVariants, getInitVariantsFnsScriptString, getUpdateCookieAndStylesScript, getVariants, } from "./helpers";
12
12
  export let canTrack = undefined;
13
13
  export let content;
14
- export let isNestedRender = undefined;
15
14
  export let nonce = undefined;
16
15
  export let apiHost = undefined;
16
+ export let isNestedRender = undefined;
17
17
  export let model;
18
18
  export let data = undefined;
19
19
  export let context = undefined;
@@ -54,6 +54,7 @@ let shouldRenderVariants = checkShouldRenderVariants({
54
54
  canTrack: getDefaultCanTrack(canTrack),
55
55
  content: content,
56
56
  });
57
+ let shouldEmitPersonalizationFns = TARGET !== "reactNative" && hasPersonalizationContainer(content);
57
58
  onMount(() => {
58
59
  /**
59
60
  * For Solid/Svelte: we unmount the non-winning variants post-hydration.
@@ -62,7 +63,7 @@ onMount(() => {
62
63
  });
63
64
  </script>
64
65
 
65
- {#if !isNestedRender && TARGET !== "reactNative"}
66
+ {#if shouldEmitPersonalizationFns}
66
67
  {#if SDKS_SUPPORTING_PERSONALIZATION.includes(TARGET)}
67
68
  <InlinedScript
68
69
  id="builderio-init-personalization-variants-fns"
@@ -10,9 +10,9 @@ declare const __propDef: {
10
10
  props: {
11
11
  canTrack?: VariantsProviderProps["canTrack"];
12
12
  content: VariantsProviderProps["content"];
13
- isNestedRender?: VariantsProviderProps["isNestedRender"];
14
13
  nonce?: VariantsProviderProps["nonce"];
15
14
  apiHost?: VariantsProviderProps["apiHost"];
15
+ isNestedRender?: VariantsProviderProps["isNestedRender"];
16
16
  model: VariantsProviderProps["model"];
17
17
  data?: VariantsProviderProps["data"];
18
18
  context?: VariantsProviderProps["context"];
@@ -1 +1 @@
1
- export declare const SDK_VERSION = "5.2.5";
1
+ export declare const SDK_VERSION = "5.2.7";
@@ -1 +1 @@
1
- export const SDK_VERSION = "5.2.5";
1
+ export const SDK_VERSION = "5.2.7";
@@ -102,7 +102,8 @@ export const componentInfo = {
102
102
  }, {
103
103
  name: 'sizes',
104
104
  type: 'string',
105
- hideFromUI: true
105
+ advanced: true,
106
+ helperText: 'The sizes attribute for responsive images, e.g. "(max-width: 600px) 100vw, 50vw"'
106
107
  }, {
107
108
  name: 'srcset',
108
109
  type: 'string',
@@ -4,14 +4,14 @@ export let image;
4
4
  export let src = undefined;
5
5
  export let srcset = undefined;
6
6
  export let noWebp = undefined;
7
- export let aspectRatio = undefined;
7
+ export let sizes = undefined;
8
8
  export let highPriority = undefined;
9
+ export let aspectRatio = undefined;
9
10
  export let altText = undefined;
10
11
  export let title = undefined;
11
12
  export let backgroundPosition = undefined;
12
13
  export let backgroundSize = undefined;
13
14
  export let className = undefined;
14
- export let sizes = undefined;
15
15
  export let builderBlock = undefined;
16
16
  export let fitContent = undefined;
17
17
  function stringifyStyles(stylesObj) {
@@ -56,6 +56,9 @@ $: webpSrcSet = () => {
56
56
  return "";
57
57
  }
58
58
  };
59
+ $: sizesToUse = () => {
60
+ return sizes || (highPriority ? undefined : "auto");
61
+ };
59
62
  $: aspectRatioCss = () => {
60
63
  const aspectRatioStyles = {
61
64
  position: "absolute",
@@ -72,7 +75,7 @@ onMount(() => { });
72
75
 
73
76
  <picture>
74
77
  {#if webpSrcSet()}
75
- <source type="image/webp" srcset={webpSrcSet()} />
78
+ <source type="image/webp" srcset={webpSrcSet()} sizes={sizesToUse()} />
76
79
  {/if}<img
77
80
  style={stringifyStyles({
78
81
  objectPosition: backgroundPosition || "center",
@@ -87,7 +90,7 @@ onMount(() => { });
87
90
  class={"builder-image" + (className ? " " + className : "") + " img"}
88
91
  src={image}
89
92
  srcset={srcSetToUse()}
90
- {sizes}
93
+ sizes={sizesToUse()}
91
94
  /></picture
92
95
  >
93
96
 
@@ -6,14 +6,14 @@ declare const __propDef: {
6
6
  src?: ImageProps["src"];
7
7
  srcset?: ImageProps["srcset"];
8
8
  noWebp?: ImageProps["noWebp"];
9
- aspectRatio?: ImageProps["aspectRatio"];
9
+ sizes?: ImageProps["sizes"];
10
10
  highPriority?: ImageProps["highPriority"];
11
+ aspectRatio?: ImageProps["aspectRatio"];
11
12
  altText?: ImageProps["altText"];
12
13
  title?: ImageProps["title"];
13
14
  backgroundPosition?: ImageProps["backgroundPosition"];
14
15
  backgroundSize?: ImageProps["backgroundSize"];
15
16
  className?: ImageProps["className"];
16
- sizes?: ImageProps["sizes"];
17
17
  builderBlock?: ImageProps["builderBlock"];
18
18
  fitContent?: ImageProps["fitContent"];
19
19
  };
@@ -1,4 +1,5 @@
1
1
  import type { BuilderBlock } from '../../types/builder-block';
2
+ import type { BuilderContent } from '../../types/builder-content';
2
3
  import type { Target } from '../../types/targets';
3
4
  import type { PersonalizationContainerProps } from './personalization-container.types';
4
5
  export declare const DEFAULT_INDEX = "default";
@@ -41,6 +42,7 @@ export declare function getBlocksToRender({ variants, previewingIndex, isHydrate
41
42
  filteredVariants: PersonalizationContainerProps['variants'];
42
43
  fallbackBlocks?: BuilderBlock[];
43
44
  }): BlocksToRenderReturnType;
45
+ export declare const hasPersonalizationContainer: (content: BuilderContent | null | undefined) => boolean;
44
46
  export declare const getInitPersonalizationVariantsFnsScriptString: () => string;
45
47
  export declare const getPersonalizationScript: (variants: PersonalizationContainerProps['variants'], blockId: string, locale?: string) => string;
46
48
  export declare const getUpdateVisibilityStylesScript: (variants: PersonalizationContainerProps['variants'], blockId: string, locale?: string) => string;
@@ -6,6 +6,7 @@ export const DEFAULT_INDEX = 'default';
6
6
  const FILTER_WITH_CUSTOM_TARGETING_SCRIPT_FN_NAME = 'filterWithCustomTargeting';
7
7
  const BUILDER_IO_PERSONALIZATION_SCRIPT_FN_NAME = 'builderIoPersonalization';
8
8
  const UPDATE_VARIANT_VISIBILITY_SCRIPT_FN_NAME = 'updateVisibilityStylesScript';
9
+ const PERSONALIZATION_CONTAINER_COMPONENT_NAME = 'PersonalizationContainer';
9
10
  /**
10
11
  * SDKs that support Variant Containers
11
12
  */
@@ -72,11 +73,37 @@ export function getBlocksToRender({ variants, previewingIndex, isHydrated, filte
72
73
  // If no winning variant or we are on the server, return the default variant
73
74
  return fallback;
74
75
  }
76
+ /**
77
+ * Walks the whole content rather than a known set of paths. A/B variation blocks live on
78
+ * `variations[*].data.blocks`, a sibling of `data.blocks`, and containers can sit inside columns,
79
+ * tabs, slots or inlined symbols. A missed container leaves the inlined fns undefined at parse
80
+ * time, so every variant renders at once.
81
+ */
82
+ const containsPersonalizationContainer = (value) => {
83
+ if (Array.isArray(value)) {
84
+ return value.some(containsPersonalizationContainer);
85
+ }
86
+ if (!value || typeof value !== 'object')
87
+ return false;
88
+ if (value.component?.name === PERSONALIZATION_CONTAINER_COMPONENT_NAME) {
89
+ return true;
90
+ }
91
+ return Object.values(value).some(containsPersonalizationContainer);
92
+ };
93
+ export const hasPersonalizationContainer = (content) => containsPersonalizationContainer(content);
75
94
  export const getInitPersonalizationVariantsFnsScriptString = () => {
76
95
  return `
77
- window.${FILTER_WITH_CUSTOM_TARGETING_SCRIPT_FN_NAME} = ${FILTER_WITH_CUSTOM_TARGETING_SCRIPT}
78
- window.${BUILDER_IO_PERSONALIZATION_SCRIPT_FN_NAME} = ${PERSONALIZATION_SCRIPT}
79
- window.${UPDATE_VARIANT_VISIBILITY_SCRIPT_FN_NAME} = ${UPDATE_VISIBILITY_STYLES_SCRIPT}
96
+ (function() {
97
+ if (!window.${FILTER_WITH_CUSTOM_TARGETING_SCRIPT_FN_NAME}) {
98
+ window.${FILTER_WITH_CUSTOM_TARGETING_SCRIPT_FN_NAME} = ${FILTER_WITH_CUSTOM_TARGETING_SCRIPT};
99
+ }
100
+ if (!window.${BUILDER_IO_PERSONALIZATION_SCRIPT_FN_NAME}) {
101
+ window.${BUILDER_IO_PERSONALIZATION_SCRIPT_FN_NAME} = ${PERSONALIZATION_SCRIPT};
102
+ }
103
+ if (!window.${UPDATE_VARIANT_VISIBILITY_SCRIPT_FN_NAME}) {
104
+ window.${UPDATE_VARIANT_VISIBILITY_SCRIPT_FN_NAME} = ${UPDATE_VISIBILITY_STYLES_SCRIPT};
105
+ }
106
+ })();
80
107
  `;
81
108
  };
82
109
  const isHydrationTarget = TARGET === 'react';
@@ -281,6 +281,7 @@ let hasExecuted = false;
281
281
  let contextValue = $builderContextSignal;
282
282
  let prevData = null;
283
283
  let prevLocale = "";
284
+ let prevContent = null;
284
285
  let ContentWrapper = contentWrapper || "div";
285
286
  let httpReqsData = {};
286
287
  let httpReqsPending = {};
@@ -1,7 +1,7 @@
1
1
  <script context="module"></script>
2
2
 
3
3
  <script>import { onMount } from "svelte";
4
- import { SDKS_SUPPORTING_PERSONALIZATION, getInitPersonalizationVariantsFnsScriptString, } from "../../blocks/personalization-container/helpers";
4
+ import { SDKS_SUPPORTING_PERSONALIZATION, getInitPersonalizationVariantsFnsScriptString, hasPersonalizationContainer, } from "../../blocks/personalization-container/helpers";
5
5
  import { TARGET } from "../../constants/target";
6
6
  import { handleABTestingSync } from "../../helpers/ab-tests";
7
7
  import { getDefaultCanTrack } from "../../helpers/canTrack";
@@ -11,9 +11,9 @@ import InlinedStyles from "../inlined-styles.svelte";
11
11
  import { checkShouldRenderVariants, getInitVariantsFnsScriptString, getUpdateCookieAndStylesScript, getVariants, } from "./helpers";
12
12
  export let canTrack = undefined;
13
13
  export let content;
14
- export let isNestedRender = undefined;
15
14
  export let nonce = undefined;
16
15
  export let apiHost = undefined;
16
+ export let isNestedRender = undefined;
17
17
  export let model;
18
18
  export let data = undefined;
19
19
  export let context = undefined;
@@ -54,6 +54,7 @@ let shouldRenderVariants = checkShouldRenderVariants({
54
54
  canTrack: getDefaultCanTrack(canTrack),
55
55
  content: content,
56
56
  });
57
+ let shouldEmitPersonalizationFns = TARGET !== "reactNative" && hasPersonalizationContainer(content);
57
58
  onMount(() => {
58
59
  /**
59
60
  * For Solid/Svelte: we unmount the non-winning variants post-hydration.
@@ -62,7 +63,7 @@ onMount(() => {
62
63
  });
63
64
  </script>
64
65
 
65
- {#if !isNestedRender && TARGET !== "reactNative"}
66
+ {#if shouldEmitPersonalizationFns}
66
67
  {#if SDKS_SUPPORTING_PERSONALIZATION.includes(TARGET)}
67
68
  <InlinedScript
68
69
  id="builderio-init-personalization-variants-fns"
@@ -10,9 +10,9 @@ declare const __propDef: {
10
10
  props: {
11
11
  canTrack?: VariantsProviderProps["canTrack"];
12
12
  content: VariantsProviderProps["content"];
13
- isNestedRender?: VariantsProviderProps["isNestedRender"];
14
13
  nonce?: VariantsProviderProps["nonce"];
15
14
  apiHost?: VariantsProviderProps["apiHost"];
15
+ isNestedRender?: VariantsProviderProps["isNestedRender"];
16
16
  model: VariantsProviderProps["model"];
17
17
  data?: VariantsProviderProps["data"];
18
18
  context?: VariantsProviderProps["context"];
@@ -1 +1 @@
1
- export declare const SDK_VERSION = "5.2.5";
1
+ export declare const SDK_VERSION = "5.2.7";
@@ -1 +1 @@
1
- export const SDK_VERSION = "5.2.5";
1
+ export const SDK_VERSION = "5.2.7";
@@ -102,7 +102,8 @@ export const componentInfo = {
102
102
  }, {
103
103
  name: 'sizes',
104
104
  type: 'string',
105
- hideFromUI: true
105
+ advanced: true,
106
+ helperText: 'The sizes attribute for responsive images, e.g. "(max-width: 600px) 100vw, 50vw"'
106
107
  }, {
107
108
  name: 'srcset',
108
109
  type: 'string',
@@ -4,14 +4,14 @@ export let image;
4
4
  export let src = undefined;
5
5
  export let srcset = undefined;
6
6
  export let noWebp = undefined;
7
- export let aspectRatio = undefined;
7
+ export let sizes = undefined;
8
8
  export let highPriority = undefined;
9
+ export let aspectRatio = undefined;
9
10
  export let altText = undefined;
10
11
  export let title = undefined;
11
12
  export let backgroundPosition = undefined;
12
13
  export let backgroundSize = undefined;
13
14
  export let className = undefined;
14
- export let sizes = undefined;
15
15
  export let builderBlock = undefined;
16
16
  export let fitContent = undefined;
17
17
  function stringifyStyles(stylesObj) {
@@ -56,6 +56,9 @@ $: webpSrcSet = () => {
56
56
  return "";
57
57
  }
58
58
  };
59
+ $: sizesToUse = () => {
60
+ return sizes || (highPriority ? undefined : "auto");
61
+ };
59
62
  $: aspectRatioCss = () => {
60
63
  const aspectRatioStyles = {
61
64
  position: "absolute",
@@ -72,7 +75,7 @@ onMount(() => { });
72
75
 
73
76
  <picture>
74
77
  {#if webpSrcSet()}
75
- <source type="image/webp" srcset={webpSrcSet()} />
78
+ <source type="image/webp" srcset={webpSrcSet()} sizes={sizesToUse()} />
76
79
  {/if}<img
77
80
  style={stringifyStyles({
78
81
  objectPosition: backgroundPosition || "center",
@@ -87,7 +90,7 @@ onMount(() => { });
87
90
  class={"builder-image" + (className ? " " + className : "") + " img"}
88
91
  src={image}
89
92
  srcset={srcSetToUse()}
90
- {sizes}
93
+ sizes={sizesToUse()}
91
94
  /></picture
92
95
  >
93
96
 
@@ -6,14 +6,14 @@ declare const __propDef: {
6
6
  src?: ImageProps["src"];
7
7
  srcset?: ImageProps["srcset"];
8
8
  noWebp?: ImageProps["noWebp"];
9
- aspectRatio?: ImageProps["aspectRatio"];
9
+ sizes?: ImageProps["sizes"];
10
10
  highPriority?: ImageProps["highPriority"];
11
+ aspectRatio?: ImageProps["aspectRatio"];
11
12
  altText?: ImageProps["altText"];
12
13
  title?: ImageProps["title"];
13
14
  backgroundPosition?: ImageProps["backgroundPosition"];
14
15
  backgroundSize?: ImageProps["backgroundSize"];
15
16
  className?: ImageProps["className"];
16
- sizes?: ImageProps["sizes"];
17
17
  builderBlock?: ImageProps["builderBlock"];
18
18
  fitContent?: ImageProps["fitContent"];
19
19
  };
@@ -1,4 +1,5 @@
1
1
  import type { BuilderBlock } from '../../types/builder-block';
2
+ import type { BuilderContent } from '../../types/builder-content';
2
3
  import type { Target } from '../../types/targets';
3
4
  import type { PersonalizationContainerProps } from './personalization-container.types';
4
5
  export declare const DEFAULT_INDEX = "default";
@@ -41,6 +42,7 @@ export declare function getBlocksToRender({ variants, previewingIndex, isHydrate
41
42
  filteredVariants: PersonalizationContainerProps['variants'];
42
43
  fallbackBlocks?: BuilderBlock[];
43
44
  }): BlocksToRenderReturnType;
45
+ export declare const hasPersonalizationContainer: (content: BuilderContent | null | undefined) => boolean;
44
46
  export declare const getInitPersonalizationVariantsFnsScriptString: () => string;
45
47
  export declare const getPersonalizationScript: (variants: PersonalizationContainerProps['variants'], blockId: string, locale?: string) => string;
46
48
  export declare const getUpdateVisibilityStylesScript: (variants: PersonalizationContainerProps['variants'], blockId: string, locale?: string) => string;
@@ -6,6 +6,7 @@ export const DEFAULT_INDEX = 'default';
6
6
  const FILTER_WITH_CUSTOM_TARGETING_SCRIPT_FN_NAME = 'filterWithCustomTargeting';
7
7
  const BUILDER_IO_PERSONALIZATION_SCRIPT_FN_NAME = 'builderIoPersonalization';
8
8
  const UPDATE_VARIANT_VISIBILITY_SCRIPT_FN_NAME = 'updateVisibilityStylesScript';
9
+ const PERSONALIZATION_CONTAINER_COMPONENT_NAME = 'PersonalizationContainer';
9
10
  /**
10
11
  * SDKs that support Variant Containers
11
12
  */
@@ -72,11 +73,37 @@ export function getBlocksToRender({ variants, previewingIndex, isHydrated, filte
72
73
  // If no winning variant or we are on the server, return the default variant
73
74
  return fallback;
74
75
  }
76
+ /**
77
+ * Walks the whole content rather than a known set of paths. A/B variation blocks live on
78
+ * `variations[*].data.blocks`, a sibling of `data.blocks`, and containers can sit inside columns,
79
+ * tabs, slots or inlined symbols. A missed container leaves the inlined fns undefined at parse
80
+ * time, so every variant renders at once.
81
+ */
82
+ const containsPersonalizationContainer = (value) => {
83
+ if (Array.isArray(value)) {
84
+ return value.some(containsPersonalizationContainer);
85
+ }
86
+ if (!value || typeof value !== 'object')
87
+ return false;
88
+ if (value.component?.name === PERSONALIZATION_CONTAINER_COMPONENT_NAME) {
89
+ return true;
90
+ }
91
+ return Object.values(value).some(containsPersonalizationContainer);
92
+ };
93
+ export const hasPersonalizationContainer = (content) => containsPersonalizationContainer(content);
75
94
  export const getInitPersonalizationVariantsFnsScriptString = () => {
76
95
  return `
77
- window.${FILTER_WITH_CUSTOM_TARGETING_SCRIPT_FN_NAME} = ${FILTER_WITH_CUSTOM_TARGETING_SCRIPT}
78
- window.${BUILDER_IO_PERSONALIZATION_SCRIPT_FN_NAME} = ${PERSONALIZATION_SCRIPT}
79
- window.${UPDATE_VARIANT_VISIBILITY_SCRIPT_FN_NAME} = ${UPDATE_VISIBILITY_STYLES_SCRIPT}
96
+ (function() {
97
+ if (!window.${FILTER_WITH_CUSTOM_TARGETING_SCRIPT_FN_NAME}) {
98
+ window.${FILTER_WITH_CUSTOM_TARGETING_SCRIPT_FN_NAME} = ${FILTER_WITH_CUSTOM_TARGETING_SCRIPT};
99
+ }
100
+ if (!window.${BUILDER_IO_PERSONALIZATION_SCRIPT_FN_NAME}) {
101
+ window.${BUILDER_IO_PERSONALIZATION_SCRIPT_FN_NAME} = ${PERSONALIZATION_SCRIPT};
102
+ }
103
+ if (!window.${UPDATE_VARIANT_VISIBILITY_SCRIPT_FN_NAME}) {
104
+ window.${UPDATE_VARIANT_VISIBILITY_SCRIPT_FN_NAME} = ${UPDATE_VISIBILITY_STYLES_SCRIPT};
105
+ }
106
+ })();
80
107
  `;
81
108
  };
82
109
  const isHydrationTarget = TARGET === 'react';
@@ -281,6 +281,7 @@ let hasExecuted = false;
281
281
  let contextValue = $builderContextSignal;
282
282
  let prevData = null;
283
283
  let prevLocale = "";
284
+ let prevContent = null;
284
285
  let ContentWrapper = contentWrapper || "div";
285
286
  let httpReqsData = {};
286
287
  let httpReqsPending = {};
@@ -1,7 +1,7 @@
1
1
  <script context="module"></script>
2
2
 
3
3
  <script>import { onMount } from "svelte";
4
- import { SDKS_SUPPORTING_PERSONALIZATION, getInitPersonalizationVariantsFnsScriptString, } from "../../blocks/personalization-container/helpers";
4
+ import { SDKS_SUPPORTING_PERSONALIZATION, getInitPersonalizationVariantsFnsScriptString, hasPersonalizationContainer, } from "../../blocks/personalization-container/helpers";
5
5
  import { TARGET } from "../../constants/target";
6
6
  import { handleABTestingSync } from "../../helpers/ab-tests";
7
7
  import { getDefaultCanTrack } from "../../helpers/canTrack";
@@ -11,9 +11,9 @@ import InlinedStyles from "../inlined-styles.svelte";
11
11
  import { checkShouldRenderVariants, getInitVariantsFnsScriptString, getUpdateCookieAndStylesScript, getVariants, } from "./helpers";
12
12
  export let canTrack = undefined;
13
13
  export let content;
14
- export let isNestedRender = undefined;
15
14
  export let nonce = undefined;
16
15
  export let apiHost = undefined;
16
+ export let isNestedRender = undefined;
17
17
  export let model;
18
18
  export let data = undefined;
19
19
  export let context = undefined;
@@ -54,6 +54,7 @@ let shouldRenderVariants = checkShouldRenderVariants({
54
54
  canTrack: getDefaultCanTrack(canTrack),
55
55
  content: content,
56
56
  });
57
+ let shouldEmitPersonalizationFns = TARGET !== "reactNative" && hasPersonalizationContainer(content);
57
58
  onMount(() => {
58
59
  /**
59
60
  * For Solid/Svelte: we unmount the non-winning variants post-hydration.
@@ -62,7 +63,7 @@ onMount(() => {
62
63
  });
63
64
  </script>
64
65
 
65
- {#if !isNestedRender && TARGET !== "reactNative"}
66
+ {#if shouldEmitPersonalizationFns}
66
67
  {#if SDKS_SUPPORTING_PERSONALIZATION.includes(TARGET)}
67
68
  <InlinedScript
68
69
  id="builderio-init-personalization-variants-fns"
@@ -10,9 +10,9 @@ declare const __propDef: {
10
10
  props: {
11
11
  canTrack?: VariantsProviderProps["canTrack"];
12
12
  content: VariantsProviderProps["content"];
13
- isNestedRender?: VariantsProviderProps["isNestedRender"];
14
13
  nonce?: VariantsProviderProps["nonce"];
15
14
  apiHost?: VariantsProviderProps["apiHost"];
15
+ isNestedRender?: VariantsProviderProps["isNestedRender"];
16
16
  model: VariantsProviderProps["model"];
17
17
  data?: VariantsProviderProps["data"];
18
18
  context?: VariantsProviderProps["context"];
@@ -1 +1 @@
1
- export declare const SDK_VERSION = "5.2.5";
1
+ export declare const SDK_VERSION = "5.2.7";
@@ -1 +1 @@
1
- export const SDK_VERSION = "5.2.5";
1
+ export const SDK_VERSION = "5.2.7";
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@builder.io/sdk-svelte",
3
3
  "description": "Builder.io SDK for Svelte",
4
- "version": "5.2.5",
4
+ "version": "5.2.7",
5
5
  "type": "module",
6
6
  "files": [
7
7
  "lib",
@@ -104,7 +104,8 @@ export const componentInfo: ComponentInfo = {
104
104
  }, {
105
105
  name: 'sizes',
106
106
  type: 'string',
107
- hideFromUI: true
107
+ advanced: true,
108
+ helperText: 'The sizes attribute for responsive images, e.g. "(max-width: 600px) 100vw, 50vw"'
108
109
  }, {
109
110
  name: 'srcset',
110
111
  type: 'string',
@@ -8,14 +8,14 @@
8
8
  export let src: ImageProps["src"] = undefined;
9
9
  export let srcset: ImageProps["srcset"] = undefined;
10
10
  export let noWebp: ImageProps["noWebp"] = undefined;
11
- export let aspectRatio: ImageProps["aspectRatio"] = undefined;
11
+ export let sizes: ImageProps["sizes"] = undefined;
12
12
  export let highPriority: ImageProps["highPriority"] = undefined;
13
+ export let aspectRatio: ImageProps["aspectRatio"] = undefined;
13
14
  export let altText: ImageProps["altText"] = undefined;
14
15
  export let title: ImageProps["title"] = undefined;
15
16
  export let backgroundPosition: ImageProps["backgroundPosition"] = undefined;
16
17
  export let backgroundSize: ImageProps["backgroundSize"] = undefined;
17
18
  export let className: ImageProps["className"] = undefined;
18
- export let sizes: ImageProps["sizes"] = undefined;
19
19
  export let builderBlock: ImageProps["builderBlock"] = undefined;
20
20
  export let fitContent: ImageProps["fitContent"] = undefined;
21
21
 
@@ -64,6 +64,9 @@
64
64
  return "";
65
65
  }
66
66
  };
67
+ $: sizesToUse = () => {
68
+ return sizes || (highPriority ? undefined : "auto");
69
+ };
67
70
  $: aspectRatioCss = () => {
68
71
  const aspectRatioStyles = {
69
72
  position: "absolute",
@@ -81,7 +84,7 @@
81
84
 
82
85
  <picture>
83
86
  {#if webpSrcSet()}
84
- <source type="image/webp" srcset={webpSrcSet()} />
87
+ <source type="image/webp" srcset={webpSrcSet()} sizes={sizesToUse()} />
85
88
  {/if}<img
86
89
  style={stringifyStyles({
87
90
  objectPosition: backgroundPosition || "center",
@@ -96,7 +99,7 @@
96
99
  class={"builder-image" + (className ? " " + className : "") + " img"}
97
100
  src={image}
98
101
  srcset={srcSetToUse()}
99
- {sizes}
102
+ sizes={sizesToUse()}
100
103
  /></picture
101
104
  >
102
105
 
@@ -2,6 +2,7 @@ import { TARGET } from '../../constants/target';
2
2
  import { isBrowser } from '../../functions/is-browser';
3
3
  import { isEditing } from '../../functions/is-editing';
4
4
  import type { BuilderBlock } from '../../types/builder-block';
5
+ import type { BuilderContent } from '../../types/builder-content';
5
6
  import type { Target } from '../../types/targets';
6
7
  import { FILTER_WITH_CUSTOM_TARGETING_SCRIPT, PERSONALIZATION_SCRIPT, UPDATE_VISIBILITY_STYLES_SCRIPT } from './helpers/inlined-fns';
7
8
  import type { PersonalizationContainerProps } from './personalization-container.types';
@@ -9,6 +10,7 @@ export const DEFAULT_INDEX = 'default';
9
10
  const FILTER_WITH_CUSTOM_TARGETING_SCRIPT_FN_NAME = 'filterWithCustomTargeting';
10
11
  const BUILDER_IO_PERSONALIZATION_SCRIPT_FN_NAME = 'builderIoPersonalization';
11
12
  const UPDATE_VARIANT_VISIBILITY_SCRIPT_FN_NAME = 'updateVisibilityStylesScript';
13
+ const PERSONALIZATION_CONTAINER_COMPONENT_NAME = 'PersonalizationContainer';
12
14
  export type UserAttributes = {
13
15
  date?: string | Date;
14
16
  urlPath?: string;
@@ -103,11 +105,37 @@ export function getBlocksToRender({
103
105
  // If no winning variant or we are on the server, return the default variant
104
106
  return fallback;
105
107
  }
108
+
109
+ /**
110
+ * Walks the whole content rather than a known set of paths. A/B variation blocks live on
111
+ * `variations[*].data.blocks`, a sibling of `data.blocks`, and containers can sit inside columns,
112
+ * tabs, slots or inlined symbols. A missed container leaves the inlined fns undefined at parse
113
+ * time, so every variant renders at once.
114
+ */
115
+ const containsPersonalizationContainer = (value: unknown): boolean => {
116
+ if (Array.isArray(value)) {
117
+ return value.some(containsPersonalizationContainer);
118
+ }
119
+ if (!value || typeof value !== 'object') return false;
120
+ if ((value as BuilderBlock).component?.name === PERSONALIZATION_CONTAINER_COMPONENT_NAME) {
121
+ return true;
122
+ }
123
+ return Object.values(value).some(containsPersonalizationContainer);
124
+ };
125
+ export const hasPersonalizationContainer = (content: BuilderContent | null | undefined) => containsPersonalizationContainer(content);
106
126
  export const getInitPersonalizationVariantsFnsScriptString = () => {
107
127
  return `
108
- window.${FILTER_WITH_CUSTOM_TARGETING_SCRIPT_FN_NAME} = ${FILTER_WITH_CUSTOM_TARGETING_SCRIPT}
109
- window.${BUILDER_IO_PERSONALIZATION_SCRIPT_FN_NAME} = ${PERSONALIZATION_SCRIPT}
110
- window.${UPDATE_VARIANT_VISIBILITY_SCRIPT_FN_NAME} = ${UPDATE_VISIBILITY_STYLES_SCRIPT}
128
+ (function() {
129
+ if (!window.${FILTER_WITH_CUSTOM_TARGETING_SCRIPT_FN_NAME}) {
130
+ window.${FILTER_WITH_CUSTOM_TARGETING_SCRIPT_FN_NAME} = ${FILTER_WITH_CUSTOM_TARGETING_SCRIPT};
131
+ }
132
+ if (!window.${BUILDER_IO_PERSONALIZATION_SCRIPT_FN_NAME}) {
133
+ window.${BUILDER_IO_PERSONALIZATION_SCRIPT_FN_NAME} = ${PERSONALIZATION_SCRIPT};
134
+ }
135
+ if (!window.${UPDATE_VARIANT_VISIBILITY_SCRIPT_FN_NAME}) {
136
+ window.${UPDATE_VARIANT_VISIBILITY_SCRIPT_FN_NAME} = ${UPDATE_VISIBILITY_STYLES_SCRIPT};
137
+ }
138
+ })();
111
139
  `;
112
140
  };
113
141
  const isHydrationTarget = TARGET === 'react';
@@ -367,6 +367,7 @@
367
367
  let contextValue = $builderContextSignal;
368
368
  let prevData = null;
369
369
  let prevLocale = "";
370
+ let prevContent = null;
370
371
  let ContentWrapper = contentWrapper || "div";
371
372
  let httpReqsData = {};
372
373
  let httpReqsPending = {};
@@ -13,6 +13,7 @@
13
13
  import {
14
14
  SDKS_SUPPORTING_PERSONALIZATION,
15
15
  getInitPersonalizationVariantsFnsScriptString,
16
+ hasPersonalizationContainer,
16
17
  } from "../../blocks/personalization-container/helpers";
17
18
  import { TARGET } from "../../constants/target";
18
19
  import { handleABTestingSync } from "../../helpers/ab-tests";
@@ -30,10 +31,10 @@
30
31
 
31
32
  export let canTrack: VariantsProviderProps["canTrack"] = undefined;
32
33
  export let content: VariantsProviderProps["content"];
33
- export let isNestedRender: VariantsProviderProps["isNestedRender"] =
34
- undefined;
35
34
  export let nonce: VariantsProviderProps["nonce"] = undefined;
36
35
  export let apiHost: VariantsProviderProps["apiHost"] = undefined;
36
+ export let isNestedRender: VariantsProviderProps["isNestedRender"] =
37
+ undefined;
37
38
  export let model: VariantsProviderProps["model"];
38
39
  export let data: VariantsProviderProps["data"] = undefined;
39
40
  export let context: VariantsProviderProps["context"] = undefined;
@@ -83,6 +84,8 @@
83
84
  canTrack: getDefaultCanTrack(canTrack),
84
85
  content: content,
85
86
  });
87
+ let shouldEmitPersonalizationFns =
88
+ TARGET !== "reactNative" && hasPersonalizationContainer(content);
86
89
 
87
90
  onMount(() => {
88
91
  /**
@@ -92,7 +95,7 @@
92
95
  });
93
96
  </script>
94
97
 
95
- {#if !isNestedRender && TARGET !== "reactNative"}
98
+ {#if shouldEmitPersonalizationFns}
96
99
  {#if SDKS_SUPPORTING_PERSONALIZATION.includes(TARGET)}
97
100
  <InlinedScript
98
101
  id="builderio-init-personalization-variants-fns"
@@ -1 +1 @@
1
- export const SDK_VERSION = "5.2.5"
1
+ export const SDK_VERSION = "5.2.7"