@builder.io/sdk-svelte 4.0.8 → 4.0.10

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 (75) hide show
  1. package/lib/browser/blocks/form/form/form.svelte +34 -12
  2. package/lib/browser/blocks/personalization-container/component-info.js +2 -1
  3. package/lib/browser/blocks/personalization-container/helpers/inlined-fns.d.ts +4 -1
  4. package/lib/browser/blocks/personalization-container/helpers/inlined-fns.js +45 -1
  5. package/lib/browser/blocks/personalization-container/helpers.d.ts +24 -4
  6. package/lib/browser/blocks/personalization-container/helpers.js +50 -19
  7. package/lib/browser/blocks/personalization-container/personalization-container.svelte +88 -38
  8. package/lib/browser/blocks/personalization-container/personalization-container.svelte.d.ts +2 -1
  9. package/lib/browser/blocks/personalization-container/personalization-container.types.d.ts +2 -2
  10. package/lib/browser/components/blocks/blocks.svelte +6 -4
  11. package/lib/browser/components/blocks/blocks.svelte.d.ts +5 -2
  12. package/lib/browser/components/blocks/blocks.types.d.ts +1 -1
  13. package/lib/browser/components/content-variants/content-variants.svelte +9 -0
  14. package/lib/browser/constants/builder-registered-components.js +2 -1
  15. package/lib/browser/constants/sdk-version.d.ts +1 -1
  16. package/lib/browser/constants/sdk-version.js +1 -1
  17. package/lib/browser/helpers/no-serialize-wrapper.d.ts +1 -0
  18. package/lib/browser/helpers/no-serialize-wrapper.js +3 -0
  19. package/lib/browser/helpers/user-attributes.d.ts +6 -2
  20. package/lib/browser/helpers/user-attributes.js +19 -4
  21. package/lib/edge/blocks/form/form/form.svelte +34 -12
  22. package/lib/edge/blocks/personalization-container/component-info.js +2 -1
  23. package/lib/edge/blocks/personalization-container/helpers/inlined-fns.d.ts +4 -1
  24. package/lib/edge/blocks/personalization-container/helpers/inlined-fns.js +45 -1
  25. package/lib/edge/blocks/personalization-container/helpers.d.ts +24 -4
  26. package/lib/edge/blocks/personalization-container/helpers.js +50 -19
  27. package/lib/edge/blocks/personalization-container/personalization-container.svelte +88 -38
  28. package/lib/edge/blocks/personalization-container/personalization-container.svelte.d.ts +2 -1
  29. package/lib/edge/blocks/personalization-container/personalization-container.types.d.ts +2 -2
  30. package/lib/edge/components/blocks/blocks.svelte +6 -4
  31. package/lib/edge/components/blocks/blocks.svelte.d.ts +5 -2
  32. package/lib/edge/components/blocks/blocks.types.d.ts +1 -1
  33. package/lib/edge/components/content-variants/content-variants.svelte +9 -0
  34. package/lib/edge/constants/builder-registered-components.js +2 -1
  35. package/lib/edge/constants/sdk-version.d.ts +1 -1
  36. package/lib/edge/constants/sdk-version.js +1 -1
  37. package/lib/edge/helpers/no-serialize-wrapper.d.ts +1 -0
  38. package/lib/edge/helpers/no-serialize-wrapper.js +3 -0
  39. package/lib/edge/helpers/user-attributes.d.ts +6 -2
  40. package/lib/edge/helpers/user-attributes.js +19 -4
  41. package/lib/node/blocks/form/form/form.svelte +34 -12
  42. package/lib/node/blocks/personalization-container/component-info.js +2 -1
  43. package/lib/node/blocks/personalization-container/helpers/inlined-fns.d.ts +4 -1
  44. package/lib/node/blocks/personalization-container/helpers/inlined-fns.js +45 -1
  45. package/lib/node/blocks/personalization-container/helpers.d.ts +24 -4
  46. package/lib/node/blocks/personalization-container/helpers.js +50 -19
  47. package/lib/node/blocks/personalization-container/personalization-container.svelte +88 -38
  48. package/lib/node/blocks/personalization-container/personalization-container.svelte.d.ts +2 -1
  49. package/lib/node/blocks/personalization-container/personalization-container.types.d.ts +2 -2
  50. package/lib/node/components/blocks/blocks.svelte +6 -4
  51. package/lib/node/components/blocks/blocks.svelte.d.ts +5 -2
  52. package/lib/node/components/blocks/blocks.types.d.ts +1 -1
  53. package/lib/node/components/content-variants/content-variants.svelte +9 -0
  54. package/lib/node/constants/builder-registered-components.js +2 -1
  55. package/lib/node/constants/sdk-version.d.ts +1 -1
  56. package/lib/node/constants/sdk-version.js +1 -1
  57. package/lib/node/helpers/no-serialize-wrapper.d.ts +1 -0
  58. package/lib/node/helpers/no-serialize-wrapper.js +3 -0
  59. package/lib/node/helpers/user-attributes.d.ts +6 -2
  60. package/lib/node/helpers/user-attributes.js +19 -4
  61. package/package.json +2 -2
  62. package/src/blocks/form/form/form.svelte +37 -12
  63. package/src/blocks/personalization-container/component-info.ts +2 -1
  64. package/src/blocks/personalization-container/helpers/inlined-fns.ts +42 -2
  65. package/src/blocks/personalization-container/helpers.ts +60 -24
  66. package/src/blocks/personalization-container/personalization-container.svelte +98 -38
  67. package/src/blocks/personalization-container/personalization-container.types.ts +2 -2
  68. package/src/components/blocks/blocks-wrapper.svelte +13 -1
  69. package/src/components/blocks/blocks.svelte +7 -4
  70. package/src/components/blocks/blocks.types.ts +1 -1
  71. package/src/components/content-variants/content-variants.svelte +12 -0
  72. package/src/constants/builder-registered-components.ts +2 -1
  73. package/src/constants/sdk-version.ts +1 -1
  74. package/src/helpers/no-serialize-wrapper.ts +3 -0
  75. package/src/helpers/user-attributes.ts +22 -4
@@ -2,8 +2,13 @@ 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 { FILTER_WITH_CUSTOM_TARGETING_SCRIPT, PERSONALIZATION_SCRIPT } from './helpers/inlined-fns';
5
+ import type { Target } from '../../types/targets';
6
+ import { FILTER_WITH_CUSTOM_TARGETING_SCRIPT, PERSONALIZATION_SCRIPT, UPDATE_VISIBILITY_STYLES_SCRIPT } from './helpers/inlined-fns';
6
7
  import type { PersonalizationContainerProps } from './personalization-container.types';
8
+ export const DEFAULT_INDEX = 'default';
9
+ const FILTER_WITH_CUSTOM_TARGETING_SCRIPT_FN_NAME = 'filterWithCustomTargeting';
10
+ const BUILDER_IO_PERSONALIZATION_SCRIPT_FN_NAME = 'builderIoPersonalization';
11
+ const UPDATE_VARIANT_VISIBILITY_SCRIPT_FN_NAME = 'updateVisibilityStylesScript';
7
12
  export type UserAttributes = {
8
13
  date?: string | Date;
9
14
  urlPath?: string;
@@ -16,12 +21,33 @@ export type Query = {
16
21
  operator: QueryOperator;
17
22
  value: QueryValue;
18
23
  };
24
+ type BlocksToRenderReturnType = {
25
+ blocks: BuilderBlock[];
26
+ path: string;
27
+ index: number | typeof DEFAULT_INDEX;
28
+ };
29
+
30
+ /**
31
+ * SDKs that support Variant Containers
32
+ */
33
+ export const SDKS_SUPPORTING_PERSONALIZATION = (['react', 'vue', 'svelte', 'qwik'] as Target[]);
34
+
35
+ /**
36
+ * After hydration, we reset the tree
37
+ * These SDKs handle Personalization Container in a special way:
38
+ * - first, the inlined script will help us add `display: none`, `aria-hidden: true` and `hidden: true` to the non-winning variants
39
+ * - then, on mount / when the component is hydrated - we reset the tree with only the winning variant and deleting the entire tree
40
+ *
41
+ * This helps us to avoid flicker and show the correct / winning variant initially and then once we've hydrated we show the winning variant
42
+ * and keep a track of the cookies to update to the correct variant dynamically when the cookie updates.
43
+ */
44
+ export const SDKS_REQUIRING_RESET_APPROACH = (['vue', 'svelte', 'qwik'] as Target[]);
19
45
  export function checkShouldRenderVariants(variants: PersonalizationContainerProps['variants'], canTrack: boolean) {
20
46
  const hasVariants = variants && variants.length > 0;
21
47
  if (TARGET === 'reactNative') return false;
22
48
  if (!hasVariants) return false;
23
49
  if (!canTrack) return false;
24
- if (TARGET === 'vue' || TARGET === 'svelte') return true;
50
+ if (SDKS_REQUIRING_RESET_APPROACH.includes(TARGET)) return true;
25
51
  if (isBrowser()) return false;
26
52
  return true;
27
53
  }
@@ -37,22 +63,23 @@ export function getBlocksToRender({
37
63
  isHydrated: boolean;
38
64
  filteredVariants: PersonalizationContainerProps['variants'];
39
65
  fallbackBlocks?: BuilderBlock[];
40
- }): {
41
- blocks: BuilderBlock[];
42
- path: string | undefined;
43
- } {
44
- const fallback = {
66
+ }): BlocksToRenderReturnType {
67
+ const fallback: BlocksToRenderReturnType = {
45
68
  blocks: fallbackBlocks ?? [],
46
- path: 'this.children'
69
+ path: 'this.children',
70
+ index: DEFAULT_INDEX
47
71
  };
48
72
  if (isHydrated && isEditing()) {
49
73
  // If editing a specific variant
50
74
  if (typeof previewingIndex === 'number' && previewingIndex < (variants?.length ?? 0)) {
51
- const variant = variants![previewingIndex];
52
- return {
53
- blocks: variant.blocks,
54
- path: `component.options.variants.${previewingIndex}.blocks`
55
- };
75
+ const variant = variants?.[previewingIndex];
76
+ if (variant) {
77
+ return {
78
+ blocks: variant.blocks,
79
+ path: `variants.${previewingIndex}.blocks`,
80
+ index: previewingIndex
81
+ };
82
+ }
56
83
  }
57
84
  // Otherwise we're editing the default variant
58
85
  return fallback;
@@ -61,24 +88,33 @@ export function getBlocksToRender({
61
88
  // If we're on the browser, check if there's a winning variant
62
89
  if (isBrowser()) {
63
90
  const winningVariant = filteredVariants?.[0];
64
- if (winningVariant) {
65
- return {
66
- blocks: winningVariant.blocks,
67
- path: `component.options.variants.${variants?.indexOf(winningVariant)}.blocks`
68
- };
91
+ if (winningVariant && variants) {
92
+ const variantIndex = variants.indexOf(winningVariant);
93
+ if (variantIndex !== -1) {
94
+ return {
95
+ blocks: winningVariant.blocks,
96
+ path: `variants.${variantIndex}.blocks`,
97
+ index: variantIndex
98
+ };
99
+ }
69
100
  }
70
101
  }
71
102
 
72
103
  // If no winning variant or we are on the server, return the default variant
73
104
  return fallback;
74
105
  }
75
- export const getPersonalizationScript = (variants: PersonalizationContainerProps['variants'], blockId: string, locale?: string) => {
106
+ export const getInitPersonalizationVariantsFnsScriptString = () => {
76
107
  return `
77
- (function() {
78
- ${FILTER_WITH_CUSTOM_TARGETING_SCRIPT}
79
- ${PERSONALIZATION_SCRIPT}
80
- getPersonalizedVariant(${JSON.stringify(variants)}, "${blockId}"${locale ? `, "${locale}"` : ''})
81
- })();
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}
82
111
  `;
83
112
  };
113
+ const isHydrationTarget = TARGET === 'react';
114
+ export const getPersonalizationScript = (variants: PersonalizationContainerProps['variants'], blockId: string, locale?: string) => {
115
+ return `window.${BUILDER_IO_PERSONALIZATION_SCRIPT_FN_NAME}(${JSON.stringify(variants)}, "${blockId}", ${isHydrationTarget}${locale ? `, "${locale}"` : ''})`;
116
+ };
117
+ export const getUpdateVisibilityStylesScript = (variants: PersonalizationContainerProps['variants'], blockId: string, locale?: string) => {
118
+ return `window.${UPDATE_VARIANT_VISIBILITY_SCRIPT_FN_NAME}(${JSON.stringify(variants)}, "${blockId}", ${isHydrationTarget}${locale ? `, "${locale}"` : ''})`;
119
+ };
84
120
  export { filterWithCustomTargeting } from './helpers/inlined-fns'
@@ -4,26 +4,43 @@
4
4
  import Blocks from "../../components/blocks/blocks.svelte";
5
5
  import InlinedScript from "../../components/inlined-script.svelte";
6
6
  import InlinedStyles from "../../components/inlined-styles.svelte";
7
+ import { TARGET } from "../../constants/target";
8
+ import { getClassPropName } from "../../functions/get-class-prop-name";
7
9
  import { isEditing } from "../../functions/is-editing";
8
10
  import { isPreviewing } from "../../functions/is-previewing";
9
11
  import { getDefaultCanTrack } from "../../helpers/canTrack";
10
12
  import { userAttributesService } from "../../helpers/user-attributes";
13
+ import { filterAttrs } from "../helpers";
11
14
  import {
12
15
  checkShouldRenderVariants,
16
+ DEFAULT_INDEX,
13
17
  filterWithCustomTargeting,
14
18
  getBlocksToRender,
15
19
  getPersonalizationScript,
20
+ getUpdateVisibilityStylesScript,
21
+ SDKS_REQUIRING_RESET_APPROACH,
16
22
  } from "./helpers";
17
23
  import type { PersonalizationContainerProps } from "./personalization-container.types";
24
+ import { setAttrs } from "../helpers";
18
25
 
19
26
  export let builderContext: PersonalizationContainerProps["builderContext"];
20
27
  export let variants: PersonalizationContainerProps["variants"] = undefined;
21
28
  export let builderBlock: PersonalizationContainerProps["builderBlock"];
22
- export let previewingIndex: PersonalizationContainerProps["previewingIndex"] =
23
- undefined;
24
29
  export let attributes: PersonalizationContainerProps["attributes"] =
25
30
  undefined;
31
+ export let previewingIndex: PersonalizationContainerProps["previewingIndex"] =
32
+ undefined;
33
+ export let builderComponents: PersonalizationContainerProps["builderComponents"];
26
34
 
35
+ $: attrs = () => {
36
+ return {
37
+ ...filterAttrs(attributes, "on:", false),
38
+ ...filterAttrs(attributes, "on:", true),
39
+ [getClassPropName()]: `builder-personalization-container ${
40
+ attributes[getClassPropName()] || ""
41
+ }`,
42
+ };
43
+ };
27
44
  $: filteredVariants = () => {
28
45
  return (variants || []).filter((variant) => {
29
46
  return filterWithCustomTargeting(
@@ -45,7 +62,7 @@
45
62
  return getBlocksToRender({
46
63
  variants: variants,
47
64
  fallbackBlocks: builderBlock?.children,
48
- isHydrated: isHydrated,
65
+ isHydrated: shouldResetVariants,
49
66
  filteredVariants: filteredVariants(),
50
67
  previewingIndex: previewingIndex,
51
68
  });
@@ -54,7 +71,7 @@
54
71
  return (variants || [])
55
72
  .map(
56
73
  (_, index) =>
57
- `[data-variant-id="${builderBlock?.id}-${index}"] { display: none; } `
74
+ `div[data-variant-id="${builderBlock?.id}-${index}"] { display: none !important; } `
58
75
  )
59
76
  .join("");
60
77
  };
@@ -67,18 +84,26 @@
67
84
  builderBlock?.id || "none",
68
85
  $builderContext?.rootState?.locale as string | undefined
69
86
  );
87
+ let updateVisibilityStylesScript = getUpdateVisibilityStylesScript(
88
+ variants,
89
+ builderBlock?.id || "none",
90
+ $builderContext?.rootState?.locale as string | undefined
91
+ );
70
92
  let unsubscribers = [];
71
93
  let shouldRenderVariants = checkShouldRenderVariants(
72
94
  variants,
73
95
  getDefaultCanTrack($builderContext?.canTrack)
74
96
  );
75
- let isHydrated = false;
97
+ let shouldResetVariants = false;
76
98
 
77
99
  onMount(() => {
78
- isHydrated = true;
100
+ shouldResetVariants = true;
79
101
  const unsub = userAttributesService.subscribeOnUserAttributesChange(
80
102
  (attrs) => {
81
103
  userAttributes = attrs;
104
+ },
105
+ {
106
+ fireImmediately: TARGET === "qwik",
82
107
  }
83
108
  );
84
109
  if (!(isEditing() || isPreviewing())) {
@@ -87,7 +112,7 @@
87
112
  rootRef.dispatchEvent(
88
113
  new CustomEvent("builder.variantLoaded", {
89
114
  detail: {
90
- variant: variant || "default",
115
+ variant: variant || DEFAULT_INDEX,
91
116
  content: $builderContext?.content,
92
117
  },
93
118
  bubbles: true,
@@ -99,7 +124,7 @@
99
124
  rootRef.dispatchEvent(
100
125
  new CustomEvent("builder.variantDisplayed", {
101
126
  detail: {
102
- variant: variant || "default",
127
+ variant: variant || DEFAULT_INDEX,
103
128
  content: $builderContext?.content,
104
129
  },
105
130
  bubbles: true,
@@ -119,37 +144,72 @@
119
144
  });
120
145
  </script>
121
146
 
122
- <div
123
- bind:this={rootRef}
124
- {...attributes}
125
- class={`builder-personalization-container ${attributes?.className || ""}`}
126
- >
127
- {#if shouldRenderVariants}
128
- {#each variants as variant, index (index)}
129
- <svelte:element
130
- this={"template"}
131
- data-variant-id={`${builderBlock?.id}-${index}`}
132
- ><Blocks
147
+ <div bind:this={rootRef} {...attrs()}>
148
+ {#if shouldResetVariants && SDKS_REQUIRING_RESET_APPROACH.includes(TARGET)}
149
+ <Blocks
150
+ blocks={blocksToRender().blocks}
151
+ parent={builderBlock?.id}
152
+ path={blocksToRender().path}
153
+ context={builderContext}
154
+ registeredComponents={builderComponents}
155
+ BlocksWrapperProps={{
156
+ ...$builderContext?.BlocksWrapperProps,
157
+ "data-variant-id": `${builderBlock?.id}-${blocksToRender().index}`,
158
+ }}
159
+ />
160
+ {/if}
161
+ {#if (!shouldResetVariants && SDKS_REQUIRING_RESET_APPROACH.includes(TARGET)) || !SDKS_REQUIRING_RESET_APPROACH.includes(TARGET)}
162
+ {#if shouldRenderVariants}
163
+ <InlinedStyles
164
+ nonce={$builderContext?.nonce || ""}
165
+ styles={hideVariantsStyleString()}
166
+ id={`variants-styles-${builderBlock?.id}`}
167
+ />
168
+ <InlinedScript
169
+ nonce={$builderContext?.nonce || ""}
170
+ scriptStr={updateVisibilityStylesScript}
171
+ id={`variants-visibility-script-${builderBlock?.id}`}
172
+ />
173
+
174
+ {#each variants as variant, index (`${builderBlock?.id}-${index}`)}
175
+ <Blocks
176
+ BlocksWrapperProps={{
177
+ ...$builderContext?.BlocksWrapperProps,
178
+ "aria-hidden": true,
179
+ hidden: true,
180
+ "data-variant-id": `${builderBlock?.id}-${index}`,
181
+ }}
133
182
  blocks={variant.blocks}
134
183
  parent={builderBlock?.id}
135
184
  path={`component.options.variants.${index}.blocks`}
136
- /></svelte:element
137
- >
138
- {/each}
139
-
140
- <InlinedStyles
141
- nonce={$builderContext?.nonce || ""}
142
- styles={hideVariantsStyleString()}
143
- id={`variants-styles-${builderBlock?.id}`}
144
- />
145
- <InlinedScript
146
- nonce={$builderContext?.nonce || ""}
147
- {scriptStr}
148
- id={`variants-script-${builderBlock?.id}`}
149
- />
150
- {/if}<Blocks
151
- blocks={blocksToRender().blocks}
152
- parent={builderBlock?.id}
153
- path={blocksToRender().path}
154
- />
185
+ context={builderContext}
186
+ registeredComponents={builderComponents}
187
+ ><InlinedScript
188
+ nonce={$builderContext?.nonce || ""}
189
+ {scriptStr}
190
+ id={`variants-script-${builderBlock?.id}-${index}`}
191
+ /></Blocks
192
+ >
193
+ {/each}
194
+ {/if}
195
+ <Blocks
196
+ blocks={blocksToRender().blocks}
197
+ parent={builderBlock?.id}
198
+ path={blocksToRender().path}
199
+ context={builderContext}
200
+ registeredComponents={builderComponents}
201
+ BlocksWrapperProps={{
202
+ ...$builderContext?.BlocksWrapperProps,
203
+ "data-variant-id": `${builderBlock?.id}-${blocksToRender().index}`,
204
+ }}
205
+ >
206
+ {#if shouldRenderVariants}
207
+ <InlinedScript
208
+ nonce={$builderContext?.nonce || ""}
209
+ {scriptStr}
210
+ id={`variants-script-${builderBlock?.id}-${DEFAULT_INDEX}`}
211
+ />
212
+ {/if}</Blocks
213
+ >
214
+ {/if}
155
215
  </div>
@@ -1,5 +1,5 @@
1
1
  import type { BuilderBlock } from '../../types/builder-block';
2
- import type { BuilderDataProps } from '../../types/builder-props';
2
+ import type { BuilderComponentsProp, BuilderDataProps } from '../../types/builder-props';
3
3
  import type { Query } from './helpers';
4
4
  export type PersonalizationContainerProps = {
5
5
  children?: any;
@@ -11,4 +11,4 @@ export type PersonalizationContainerProps = {
11
11
  startDate?: string;
12
12
  endDate?: string;
13
13
  }>;
14
- } & BuilderDataProps
14
+ } & BuilderDataProps & BuilderComponentsProp
@@ -9,7 +9,19 @@
9
9
  */
10
10
  BlocksWrapper: any;
11
11
  /**
12
- * Additonal props to pass to `blocksWrapper`. Defaults to `{}`.
12
+ * Props to be applied to the wrapping element of blocks. Can be set in two ways:
13
+ * 1. Globally via `<Content blocksWrapperProps={{...}}/>` - applies to all blocks wrappers in the Content
14
+ * 2. Locally via `<Blocks BlocksWrapperProps={{...}}/>` - applies only to this specific blocks instance and overrides global props
15
+ *
16
+ * For merging both global and local props, spread the context props before adding your own:
17
+ * ```
18
+ * <Blocks
19
+ * BlocksWrapperProps={{
20
+ * ...builderContext.BlocksWrapperProps,
21
+ * 'data-test-id': 'my-test-id'
22
+ * }}
23
+ * />
24
+ * ```
13
25
  */
14
26
  BlocksWrapperProps: any;
15
27
  children?: any;
@@ -11,8 +11,10 @@
11
11
  export let parent: BlocksProps["parent"];
12
12
  export let path: BlocksProps["path"];
13
13
  export let styleProp: BlocksProps["styleProp"];
14
- export let className: BlocksProps["className"] = undefined;
14
+ export let BlocksWrapperProps: BlocksProps["BlocksWrapperProps"];
15
15
  export let context: BlocksProps["context"] = undefined;
16
+ export let className: BlocksProps["className"] = undefined;
17
+
16
18
  export let linkComponent: BlocksProps["linkComponent"] = undefined;
17
19
  export let registeredComponents: BlocksProps["registeredComponents"] =
18
20
  undefined;
@@ -26,11 +28,12 @@
26
28
  {parent}
27
29
  {path}
28
30
  {styleProp}
31
+ BlocksWrapperProps={BlocksWrapperProps ||
32
+ $context?.BlocksWrapperProps ||
33
+ $builderContext?.BlocksWrapperProps}
29
34
  classNameProp={className}
30
35
  BlocksWrapper={$context?.BlocksWrapper || $builderContext?.BlocksWrapper}
31
- BlocksWrapperProps={$context?.BlocksWrapperProps ||
32
- $builderContext?.BlocksWrapperProps}
33
- >
36
+ ><slot />
34
37
  {#if blocks}
35
38
  {#each blocks as block (block.id)}
36
39
  <Block
@@ -1,7 +1,7 @@
1
1
  import type { Writable } from "svelte/store";
2
2
  import type { BuilderContextInterface, RegisteredComponents } from '../../context/types';
3
3
  import type { BlocksWrapperProps } from './blocks-wrapper.svelte';
4
- export type BlocksProps = Partial<Omit<BlocksWrapperProps, 'BlocksWrapper' | 'BlocksWrapperProps' | 'classNameProp'>> & {
4
+ export type BlocksProps = Partial<Omit<BlocksWrapperProps, 'BlocksWrapper' | 'classNameProp'>> & {
5
5
  context?: Writable<BuilderContextInterface>;
6
6
  registeredComponents?: RegisteredComponents;
7
7
  linkComponent?: any;
@@ -10,6 +10,10 @@
10
10
  <script lang="ts">
11
11
  import { onMount } from "svelte";
12
12
 
13
+ import {
14
+ SDKS_SUPPORTING_PERSONALIZATION,
15
+ getInitPersonalizationVariantsFnsScriptString,
16
+ } from "../../blocks/personalization-container/helpers";
13
17
  import { TARGET } from "../../constants/target";
14
18
  import { handleABTestingSync } from "../../helpers/ab-tests";
15
19
  import { getDefaultCanTrack } from "../../helpers/canTrack";
@@ -94,6 +98,14 @@
94
98
  scriptStr={getInitVariantsFnsScriptString()}
95
99
  nonce={nonce || ""}
96
100
  />
101
+
102
+ {#if SDKS_SUPPORTING_PERSONALIZATION.includes(TARGET)}
103
+ <InlinedScript
104
+ id="builderio-init-personalization-variants-fns"
105
+ nonce={nonce || ""}
106
+ scriptStr={getInitPersonalizationVariantsFnsScriptString()}
107
+ />
108
+ {/if}
97
109
  {/if}
98
110
 
99
111
  {#if shouldRenderVariants}
@@ -9,6 +9,7 @@ import { default as Fragment } from '../blocks/fragment/index';
9
9
  import { componentInfo as imageComponentInfo } from '../blocks/image/component-info';
10
10
  import { default as Image } from '../blocks/image/index';
11
11
  import { componentInfo as personalizationContainerComponentInfo } from '../blocks/personalization-container/component-info';
12
+ import { SDKS_SUPPORTING_PERSONALIZATION } from '../blocks/personalization-container/helpers';
12
13
  import { default as PersonalizationContainer } from '../blocks/personalization-container/index';
13
14
  import { componentInfo as sectionComponentInfo } from '../blocks/section/component-info';
14
15
  import { default as Section } from '../blocks/section/index';
@@ -52,7 +53,7 @@ export const getDefaultRegisteredComponents: () => RegisteredComponent[] = () =>
52
53
  }, {
53
54
  component: Text,
54
55
  ...textComponentInfo
55
- }, ...(TARGET === 'react' ? [{
56
+ }, ...(SDKS_SUPPORTING_PERSONALIZATION.includes(TARGET) ? [{
56
57
  component: PersonalizationContainer,
57
58
  ...personalizationContainerComponentInfo
58
59
  }] : []), ...(TARGET === 'rsc' ? [] : [{
@@ -1 +1 @@
1
- export const SDK_VERSION = "4.0.8"
1
+ export const SDK_VERSION = "4.0.10"
@@ -0,0 +1,3 @@
1
+ export function noSerializeWrapper(fn: () => void) {
2
+ return fn;
3
+ }
@@ -1,5 +1,7 @@
1
+ import { TARGET } from '../constants/target';
1
2
  import { isBrowser } from '../functions/is-browser';
2
3
  import { getCookieSync, setCookie } from './cookie';
4
+ import { noSerializeWrapper } from './no-serialize-wrapper';
3
5
  export interface UserAttributes {
4
6
  [key: string]: any;
5
7
  }
@@ -32,18 +34,34 @@ export function createUserAttributesService() {
32
34
  canTrack
33
35
  }) || '{}');
34
36
  },
35
- subscribeOnUserAttributesChange(callback: (attrs: UserAttributes) => void) {
37
+ subscribeOnUserAttributesChange(callback: (attrs: UserAttributes) => void, {
38
+ fireImmediately
39
+ }: {
40
+ fireImmediately?: boolean;
41
+ } = {}) {
36
42
  subscribers.add(callback);
37
- return () => {
43
+ if (fireImmediately) {
44
+ callback(this.getUserAttributes());
45
+ }
46
+ return noSerializeWrapper(function () {
38
47
  subscribers.delete(callback);
39
- };
48
+ });
40
49
  },
41
50
  setCanTrack(value: boolean) {
42
51
  canTrack = value;
43
52
  }
44
53
  };
45
54
  }
46
- export const userAttributesService = createUserAttributesService();
55
+ let _userAttributesService: ReturnType<typeof createUserAttributesService>;
56
+ if (isBrowser() && TARGET === 'qwik') {
57
+ if (!(window as any).__BUILDER_USER_ATTRIBUTES_SERVICE__) {
58
+ (window as any).__BUILDER_USER_ATTRIBUTES_SERVICE__ = createUserAttributesService();
59
+ }
60
+ _userAttributesService = (window as any).__BUILDER_USER_ATTRIBUTES_SERVICE__;
61
+ } else {
62
+ _userAttributesService = createUserAttributesService();
63
+ }
64
+ export const userAttributesService = _userAttributesService;
47
65
  export const setClientUserAttributes = (attributes: UserAttributes) => {
48
66
  userAttributesService.setUserAttributes(attributes);
49
67
  }