@builder.io/sdk-svelte 0.0.2 → 0.0.4

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 (144) hide show
  1. package/package/--package.json +159 -0
  2. package/package/blocks/BaseText.svelte +19 -0
  3. package/package/blocks/BaseText.svelte.d.ts +19 -0
  4. package/package/blocks/columns/columns.svelte +13 -4
  5. package/package/blocks/columns/columns.svelte.d.ts +1 -1
  6. package/package/blocks/custom-code/custom-code.svelte +1 -1
  7. package/package/blocks/embed/embed.svelte +2 -0
  8. package/package/blocks/form/form.svelte +7 -5
  9. package/package/blocks/image/image.svelte +48 -46
  10. package/package/blocks/image/image.svelte.d.ts +1 -1
  11. package/package/blocks/img/img.svelte +7 -2
  12. package/package/blocks/section/section.svelte +7 -2
  13. package/package/blocks/symbol/symbol.svelte +13 -13
  14. package/package/blocks/symbol/symbol.svelte.d.ts +3 -3
  15. package/package/blocks/video/video.svelte +14 -3
  16. package/package/components/render-block/block-styles.svelte +24 -19
  17. package/package/components/render-block/block-styles.svelte.d.ts +2 -2
  18. package/package/components/render-block/render-block.svelte +81 -58
  19. package/package/components/render-block/render-block.svelte.d.ts +2 -2
  20. package/package/components/render-block/render-component-with-context.svelte +32 -0
  21. package/package/components/render-block/render-component-with-context.svelte.d.ts +19 -0
  22. package/package/components/render-block/render-component.svelte +1 -3
  23. package/package/components/render-block/render-component.svelte.d.ts +2 -2
  24. package/package/components/render-block/render-repeated-block.svelte +3 -0
  25. package/package/components/render-block/types.d.ts +2 -2
  26. package/package/components/render-block/types.js +1 -2
  27. package/package/components/render-blocks.svelte +12 -1
  28. package/package/components/render-blocks.svelte.d.ts +3 -1
  29. package/package/components/render-content/components/render-styles.svelte +2 -1
  30. package/package/components/render-content/render-content.svelte +24 -8
  31. package/package/components/render-content/render-content.svelte.d.ts +2 -2
  32. package/package/constants/builder-registered-components.js +3 -0
  33. package/package/context/builder.context.d.ts +1 -0
  34. package/package/context/builder.context.js +1 -0
  35. package/package/context/types.d.ts +4 -3
  36. package/package/context/types.js +1 -3
  37. package/package/functions/extract-text-styles.d.ts +4 -0
  38. package/package/functions/extract-text-styles.js +34 -0
  39. package/package/functions/fast-clone.d.ts +4 -0
  40. package/package/functions/fast-clone.js +4 -0
  41. package/package/functions/get-block-actions-handler.d.ts +5 -0
  42. package/package/functions/get-block-actions-handler.js +9 -0
  43. package/package/functions/get-block-actions.d.ts +1 -1
  44. package/package/functions/get-block-actions.js +2 -8
  45. package/package/functions/get-block-component-options.d.ts +1 -1
  46. package/package/functions/get-block-component-options.js +0 -1
  47. package/package/functions/get-block-properties.d.ts +1 -1
  48. package/package/functions/get-block-properties.js +0 -1
  49. package/package/functions/get-block-tag.d.ts +1 -1
  50. package/package/functions/get-block-tag.js +0 -1
  51. package/package/functions/get-builder-search-params/index.d.ts +1 -1
  52. package/package/functions/get-builder-search-params/index.js +6 -2
  53. package/package/functions/get-content/ab-testing.d.ts +5 -3
  54. package/package/functions/get-content/ab-testing.js +75 -37
  55. package/package/functions/get-content/index.d.ts +1 -1
  56. package/package/functions/get-content/index.js +4 -5
  57. package/package/functions/get-content/types.d.ts +7 -2
  58. package/package/functions/get-processed-block.d.ts +1 -1
  59. package/package/functions/get-processed-block.js +5 -4
  60. package/package/functions/get-processed-block.test.js +0 -1
  61. package/package/functions/get-react-native-block-styles.d.ts +6 -0
  62. package/package/functions/get-react-native-block-styles.js +16 -0
  63. package/package/functions/register-component.d.ts +2 -2
  64. package/package/functions/register-component.js +1 -5
  65. package/package/functions/register.d.ts +2 -2
  66. package/package/functions/register.js +0 -2
  67. package/package/functions/sanitize-react-native-block-styles.d.ts +3 -0
  68. package/package/functions/sanitize-react-native-block-styles.js +53 -0
  69. package/package/functions/track.d.ts +1 -1
  70. package/package/functions/track.js +5 -6
  71. package/package/functions/transform-block.d.ts +1 -1
  72. package/package/functions/transform-block.js +0 -1
  73. package/package/helpers/ab-tests.d.ts +8 -0
  74. package/package/helpers/ab-tests.js +5 -0
  75. package/package/helpers/cookie.d.ts +9 -3
  76. package/package/helpers/cookie.js +8 -3
  77. package/package/helpers/css.d.ts +5 -1
  78. package/package/helpers/css.js +14 -1
  79. package/package/helpers/localStorage.d.ts +3 -4
  80. package/package/helpers/sessionId.d.ts +3 -4
  81. package/package/helpers/sessionId.js +5 -3
  82. package/package/helpers/visitorId.d.ts +3 -5
  83. package/package/scripts/init-editing.js +42 -38
  84. package/package/types/builder-content.d.ts +1 -1
  85. package/package/types/builder-content.js +1 -1
  86. package/package/types/targets.d.ts +1 -1
  87. package/package/types/typescript.d.ts +1 -0
  88. package/package.json +8 -3
  89. package/package/blocks/button/button.lite.d.ts +0 -0
  90. package/package/blocks/button/button.lite.tsx +0 -36
  91. package/package/blocks/columns/columns.lite.d.ts +0 -0
  92. package/package/blocks/columns/columns.lite.tsx +0 -139
  93. package/package/blocks/custom-code/custom-code.lite.d.ts +0 -0
  94. package/package/blocks/custom-code/custom-code.lite.tsx +0 -70
  95. package/package/blocks/embed/embed.lite.d.ts +0 -0
  96. package/package/blocks/embed/embed.lite.tsx +0 -52
  97. package/package/blocks/form/form.lite.d.ts +0 -0
  98. package/package/blocks/form/form.lite.tsx +0 -351
  99. package/package/blocks/fragment/fragment.lite.d.ts +0 -0
  100. package/package/blocks/fragment/fragment.lite.tsx +0 -12
  101. package/package/blocks/image/image.lite.d.ts +0 -0
  102. package/package/blocks/image/image.lite.tsx +0 -148
  103. package/package/blocks/img/img.lite.d.ts +0 -0
  104. package/package/blocks/img/img.lite.tsx +0 -48
  105. package/package/blocks/input/input.lite.d.ts +0 -0
  106. package/package/blocks/input/input.lite.tsx +0 -34
  107. package/package/blocks/raw-text/raw-text.lite.d.ts +0 -0
  108. package/package/blocks/raw-text/raw-text.lite.tsx +0 -15
  109. package/package/blocks/section/section.lite.d.ts +0 -0
  110. package/package/blocks/section/section.lite.tsx +0 -30
  111. package/package/blocks/select/select.lite.d.ts +0 -0
  112. package/package/blocks/select/select.lite.tsx +0 -34
  113. package/package/blocks/submit-button/submit-button.lite.d.ts +0 -0
  114. package/package/blocks/submit-button/submit-button.lite.tsx +0 -15
  115. package/package/blocks/symbol/symbol.lite.d.ts +0 -0
  116. package/package/blocks/symbol/symbol.lite.tsx +0 -92
  117. package/package/blocks/text/text.lite.d.ts +0 -0
  118. package/package/blocks/text/text.lite.tsx +0 -11
  119. package/package/blocks/textarea/textarea.lite.d.ts +0 -0
  120. package/package/blocks/textarea/textarea.lite.tsx +0 -19
  121. package/package/blocks/video/video.lite.d.ts +0 -0
  122. package/package/blocks/video/video.lite.tsx +0 -92
  123. package/package/components/render-block/block-styles.lite.d.ts +0 -0
  124. package/package/components/render-block/block-styles.lite.tsx +0 -60
  125. package/package/components/render-block/render-block.lite.d.ts +0 -0
  126. package/package/components/render-block/render-block.lite.tsx +0 -216
  127. package/package/components/render-block/render-component.lite.d.ts +0 -0
  128. package/package/components/render-block/render-component.lite.tsx +0 -33
  129. package/package/components/render-block/render-repeated-block.lite.d.ts +0 -0
  130. package/package/components/render-block/render-repeated-block.lite.tsx +0 -49
  131. package/package/components/render-blocks.lite.d.ts +0 -0
  132. package/package/components/render-blocks.lite.tsx +0 -91
  133. package/package/components/render-content/components/render-styles.lite.d.ts +0 -0
  134. package/package/components/render-content/components/render-styles.lite.tsx +0 -86
  135. package/package/components/render-content/render-content.lite.d.ts +0 -0
  136. package/package/components/render-content/render-content.lite.tsx +0 -356
  137. package/package/components/render-inlined-styles.lite.d.ts +0 -0
  138. package/package/components/render-inlined-styles.lite.tsx +0 -27
  139. package/package/functions/convert-style-object.d.ts +0 -1
  140. package/package/functions/convert-style-object.js +0 -3
  141. package/package/functions/get-block-styles.d.ts +0 -2
  142. package/package/functions/get-block-styles.js +0 -21
  143. package/package/functions/sanitize-styles.d.ts +0 -4
  144. package/package/functions/sanitize-styles.js +0 -6
@@ -0,0 +1,34 @@
1
+ const TEXT_STYLE_KEYS = [
2
+ 'color',
3
+ 'whiteSpace',
4
+ 'direction',
5
+ 'hyphens',
6
+ 'overflowWrap',
7
+ ];
8
+ /**
9
+ * Check if the key represent a CSS style property that applies to text
10
+ * See MDN docs for refrence of what properties apply to text.
11
+ * https://developer.mozilla.org/en-US/docs/Learn/CSS/Styling_text/Fundamentals#summary
12
+ */
13
+ const isTextStyle = (key) => {
14
+ return (TEXT_STYLE_KEYS.includes(key) ||
15
+ key.startsWith('font') ||
16
+ key.startsWith('text') ||
17
+ key.startsWith('letter') ||
18
+ key.startsWith('line') ||
19
+ key.startsWith('word') ||
20
+ key.startsWith('writing'));
21
+ };
22
+ /**
23
+ * Extract styles that apply to text from a style object.
24
+ */
25
+ export const extractTextStyles = (styles) => {
26
+ const textStyles = {};
27
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
28
+ Object.entries(styles).forEach(([key, value]) => {
29
+ if (isTextStyle(key)) {
30
+ textStyles[key] = value;
31
+ }
32
+ });
33
+ return textStyles;
34
+ };
@@ -0,0 +1,4 @@
1
+ /**
2
+ * We need to serialize values to a string in case there are Proxy values, as is the case with SolidJS etc.
3
+ */
4
+ export declare const fastClone: <T extends object>(obj: T) => T;
@@ -0,0 +1,4 @@
1
+ /**
2
+ * We need to serialize values to a string in case there are Proxy values, as is the case with SolidJS etc.
3
+ */
4
+ export const fastClone = (obj) => JSON.parse(JSON.stringify(obj));
@@ -0,0 +1,5 @@
1
+ import type { BuilderContextInterface } from '../context/types.js';
2
+ import type { BuilderBlock } from '../types/builder-block.js';
3
+ export declare function crateEventHandler(value: string, options: {
4
+ block: BuilderBlock;
5
+ } & Pick<BuilderContextInterface, 'state' | 'context'>): (event: Event) => any;
@@ -0,0 +1,9 @@
1
+ import { evaluate } from './evaluate.js';
2
+ export function crateEventHandler(value, options) {
3
+ return (event) => evaluate({
4
+ code: value,
5
+ context: options.context,
6
+ state: options.state,
7
+ event,
8
+ });
9
+ }
@@ -1,5 +1,5 @@
1
1
  import type { BuilderContextInterface } from '../context/types.js';
2
- import { BuilderBlock } from '../types/builder-block.js';
2
+ import type { BuilderBlock } from '../types/builder-block.js';
3
3
  declare type Actions = {
4
4
  [index: string]: (event: Event) => any;
5
5
  };
@@ -1,6 +1,5 @@
1
- import '../types/builder-block.js';
2
- import { evaluate } from './evaluate.js';
3
1
  import { getEventHandlerName } from './event-handler-name.js';
2
+ import { crateEventHandler } from './get-block-actions-handler.js';
4
3
  export function getBlockActions(options) {
5
4
  const obj = {};
6
5
  const optionActions = options.block.actions ?? {};
@@ -10,12 +9,7 @@ export function getBlockActions(options) {
10
9
  continue;
11
10
  }
12
11
  const value = optionActions[key];
13
- obj[getEventHandlerName(key)] = (event) => evaluate({
14
- code: value,
15
- context: options.context,
16
- state: options.state,
17
- event,
18
- });
12
+ obj[getEventHandlerName(key)] = crateEventHandler(value, options);
19
13
  }
20
14
  return obj;
21
15
  }
@@ -1,2 +1,2 @@
1
- import { BuilderBlock } from '../types/builder-block.js';
1
+ import type { BuilderBlock } from '../types/builder-block.js';
2
2
  export declare function getBlockComponentOptions(block: BuilderBlock): any;
@@ -1,4 +1,3 @@
1
- import '../types/builder-block.js';
2
1
  export function getBlockComponentOptions(block) {
3
2
  return {
4
3
  ...block.component?.options,
@@ -1,4 +1,4 @@
1
- import { BuilderBlock } from '../types/builder-block.js';
1
+ import type { BuilderBlock } from '../types/builder-block.js';
2
2
  export declare function getBlockProperties(block: BuilderBlock): {
3
3
  'builder-id': string | undefined;
4
4
  class: string;
@@ -1,4 +1,3 @@
1
- import '../types/builder-block.js';
2
1
  export function getBlockProperties(block) {
3
2
  return {
4
3
  ...block.properties,
@@ -1,3 +1,3 @@
1
- import { BuilderBlock } from '../types/builder-block.js';
1
+ import type { BuilderBlock } from '../types/builder-block.js';
2
2
  export declare type TagName = string;
3
3
  export declare function getBlockTag(block: BuilderBlock): TagName;
@@ -1,4 +1,3 @@
1
- import '../types/builder-block.js';
2
1
  export function getBlockTag(block) {
3
2
  return block.tagName || 'div';
4
3
  }
@@ -1,6 +1,6 @@
1
1
  declare type QueryObject = Record<string, string>;
2
2
  export declare const convertSearchParamsToQueryObject: (searchParams: URLSearchParams) => QueryObject;
3
- export declare const getBuilderSearchParams: (options: QueryObject) => QueryObject;
3
+ export declare const getBuilderSearchParams: (_options: QueryObject | URLSearchParams | undefined) => QueryObject;
4
4
  export declare const getBuilderSearchParamsFromWindow: () => QueryObject;
5
5
  export declare const normalizeSearchParams: (searchParams: QueryObject | URLSearchParams) => QueryObject;
6
6
  export {};
@@ -7,7 +7,11 @@ export const convertSearchParamsToQueryObject = (searchParams) => {
7
7
  });
8
8
  return options;
9
9
  };
10
- export const getBuilderSearchParams = (options) => {
10
+ export const getBuilderSearchParams = (_options) => {
11
+ if (!_options) {
12
+ return {};
13
+ }
14
+ const options = normalizeSearchParams(_options);
11
15
  const newOptions = {};
12
16
  Object.keys(options).forEach((key) => {
13
17
  if (key.startsWith(BUILDER_SEARCHPARAMS_PREFIX)) {
@@ -22,7 +26,7 @@ export const getBuilderSearchParamsFromWindow = () => {
22
26
  return {};
23
27
  }
24
28
  const searchParams = new URLSearchParams(window.location.search);
25
- return getBuilderSearchParams(convertSearchParamsToQueryObject(searchParams));
29
+ return getBuilderSearchParams(searchParams);
26
30
  };
27
31
  export const normalizeSearchParams = (searchParams) => searchParams instanceof URLSearchParams
28
32
  ? convertSearchParamsToQueryObject(searchParams)
@@ -1,3 +1,5 @@
1
- import { GetContentOptions } from './types.js';
2
- import { BuilderContent } from '../../types/builder-content.js';
3
- export declare const handleABTesting: (item: BuilderContent, testGroups: NonNullable<GetContentOptions['testGroups']>) => void;
1
+ import type { BuilderContent } from '../../types/builder-content.js';
2
+ import type { CanTrack } from '../../types/can-track.js';
3
+ export declare const handleABTesting: ({ item, canTrack, }: {
4
+ item: BuilderContent;
5
+ } & CanTrack) => Promise<void>;
@@ -1,40 +1,78 @@
1
- import './types.js';
2
- import '../../types/builder-content.js';
3
- export const handleABTesting = (item, testGroups) => {
4
- if (item.variations && Object.keys(item.variations).length) {
5
- const testGroup = item.id ? testGroups[item.id] : undefined;
6
- const variationValue = testGroup ? item.variations[testGroup] : undefined;
7
- if (testGroup && variationValue) {
8
- item.data = variationValue.data;
9
- item.testVariationId = variationValue.id;
10
- item.testVariationName = variationValue.name;
11
- }
12
- else {
13
- // TODO: a/b test iteration logic
14
- let n = 0;
15
- const random = Math.random();
16
- let set = false;
17
- for (const id in item.variations) {
18
- const variation = item.variations[id];
19
- const testRatio = variation.testRatio;
20
- n += testRatio;
21
- if (random < n) {
22
- const variationName = variation.name ||
23
- (variation.id === item.id ? 'Default variation' : '');
24
- set = true;
25
- Object.assign(item, {
26
- data: variation.data,
27
- testVariationId: variation.id,
28
- testVariationName: variationName,
29
- });
30
- }
31
- }
32
- if (!set) {
33
- Object.assign(item, {
34
- testVariationId: item.id,
35
- testVariationName: 'Default',
36
- });
37
- }
1
+ import { getContentVariationCookie, setContentVariationCookie, } from '../../helpers/ab-tests.js';
2
+ import { checkIsDefined } from '../../helpers/nullable.js';
3
+ const checkIsBuilderContentWithVariations = (item) => checkIsDefined(item.id) &&
4
+ checkIsDefined(item.variations) &&
5
+ Object.keys(item.variations).length > 0;
6
+ /**
7
+ * Randomly assign a variation to this user and store it in cookies/storage
8
+ */
9
+ const getRandomVariationId = ({ id, variations, }) => {
10
+ let n = 0;
11
+ const random = Math.random();
12
+ // loop over variations test ratios, incrementing a counter,
13
+ // until we find the variation that this user should be assigned to
14
+ for (const id in variations) {
15
+ const testRatio = variations[id]?.testRatio;
16
+ n += testRatio;
17
+ if (random < n) {
18
+ return id;
38
19
  }
39
20
  }
21
+ // `item.variations` does not include the default variation
22
+ // if we arrive here, then it means that the random number fits in the default variation bucket
23
+ return id;
24
+ };
25
+ const getTestFields = ({ item, testGroupId, }) => {
26
+ const variationValue = item.variations[testGroupId];
27
+ if (testGroupId === item.id ||
28
+ // handle edge-case where `testGroupId` points to non-existing variation
29
+ !variationValue) {
30
+ return {
31
+ testVariationId: item.id,
32
+ testVariationName: 'Default',
33
+ };
34
+ }
35
+ else {
36
+ return {
37
+ data: variationValue.data,
38
+ testVariationId: variationValue.id,
39
+ testVariationName: variationValue.name || (variationValue.id === item.id ? 'Default' : ''),
40
+ };
41
+ }
42
+ };
43
+ const getContentVariation = async ({ item, canTrack, }) => {
44
+ // try to find test variation in cookies/storage
45
+ const testGroupId = await getContentVariationCookie({
46
+ canTrack,
47
+ contentId: item.id,
48
+ });
49
+ const testFields = testGroupId
50
+ ? getTestFields({ item, testGroupId })
51
+ : undefined;
52
+ if (testFields) {
53
+ return testFields;
54
+ }
55
+ else {
56
+ // if variation not found in storage, assign a random variation to this user
57
+ const randomVariationId = getRandomVariationId({
58
+ variations: item.variations,
59
+ id: item.id,
60
+ });
61
+ // store variation in cookies/storage
62
+ setContentVariationCookie({
63
+ contentId: item.id,
64
+ value: randomVariationId,
65
+ canTrack,
66
+ }).catch((err) => {
67
+ console.error('could not store A/B test variation: ', err);
68
+ });
69
+ return getTestFields({ item, testGroupId: randomVariationId });
70
+ }
71
+ };
72
+ export const handleABTesting = async ({ item, canTrack, }) => {
73
+ if (!checkIsBuilderContentWithVariations(item)) {
74
+ return;
75
+ }
76
+ const variationValue = await getContentVariation({ item, canTrack });
77
+ Object.assign(item, variationValue);
40
78
  };
@@ -1,4 +1,4 @@
1
- import { BuilderContent } from '../../types/builder-content.js';
1
+ import type { BuilderContent } from '../../types/builder-content.js';
2
2
  export declare type GetContentOptions = import('./types.js').GetContentOptions;
3
3
  export declare function getContent(options: GetContentOptions): Promise<BuilderContent | null>;
4
4
  export declare const generateContentUrl: (options: GetContentOptions) => URL;
@@ -1,9 +1,7 @@
1
1
  import { flatten } from '../../helpers/flatten.js';
2
- import '../../types/builder-content.js';
3
2
  import { getBuilderSearchParamsFromWindow, normalizeSearchParams, } from '../get-builder-search-params/index.js';
4
3
  import { getFetch } from '../get-fetch.js';
5
4
  import { handleABTesting } from './ab-testing.js';
6
- const fetch$ = getFetch();
7
5
  export async function getContent(options) {
8
6
  return (await getAllContent({ ...options, limit: 1 })).results[0] || null;
9
7
  }
@@ -31,11 +29,12 @@ export const generateContentUrl = (options) => {
31
29
  };
32
30
  export async function getAllContent(options) {
33
31
  const url = generateContentUrl(options);
34
- const fetch = await fetch$;
32
+ const fetch = await getFetch();
35
33
  const content = await fetch(url.href).then((res) => res.json());
36
- if (options.testGroups) {
34
+ const canTrack = options.canTrack !== false;
35
+ if (canTrack) {
37
36
  for (const item of content.results) {
38
- handleABTesting(item, options.testGroups);
37
+ await handleABTesting({ item, canTrack });
39
38
  }
40
39
  }
41
40
  return content;
@@ -3,8 +3,6 @@ export interface GetContentOptions {
3
3
  model: string;
4
4
  /** Your public API key */
5
5
  apiKey: string;
6
- /** A/B test groups the current visitor is in. Key is the content ID, value is the variation ID */
7
- testGroups?: Record<string, string> | null;
8
6
  /** Number of items to fetch. Default is 1 */
9
7
  limit?: number;
10
8
  /** User attributes to target on, such as { urlPath: '/foo', device: 'mobile', ...etc } */
@@ -23,4 +21,11 @@ export interface GetContentOptions {
23
21
  * If set to `false`, it will render the entire content tree eagerly.
24
22
  */
25
23
  noTraverse?: boolean;
24
+ /**
25
+ * If set to `false`, it will not use cookies to target content. Therefore, A/B Testing will be disabled and
26
+ * only the default variation will be returned to every user.
27
+ *
28
+ * Defaults to `true`.
29
+ */
30
+ canTrack?: boolean;
26
31
  }
@@ -1,5 +1,5 @@
1
1
  import type { BuilderContextInterface } from '../context/types.js';
2
- import { BuilderBlock } from '../types/builder-block.js';
2
+ import type { BuilderBlock } from '../types/builder-block.js';
3
3
  export declare function getProcessedBlock({ block, context, shouldEvaluateBindings, state, }: {
4
4
  block: BuilderBlock;
5
5
  /**
@@ -1,15 +1,16 @@
1
- import '../types/builder-block.js';
2
1
  import { evaluate } from './evaluate.js';
2
+ import { fastClone } from './fast-clone.js';
3
3
  import { set } from './set.js';
4
4
  import { transformBlock } from './transform-block.js';
5
5
  const evaluateBindings = ({ block, context, state, }) => {
6
6
  if (!block.bindings) {
7
7
  return block;
8
8
  }
9
+ const copy = fastClone(block);
9
10
  const copied = {
10
- ...block,
11
- properties: { ...block.properties },
12
- actions: { ...block.actions },
11
+ ...copy,
12
+ properties: { ...copy.properties },
13
+ actions: { ...copy.actions },
13
14
  };
14
15
  for (const binding in block.bindings) {
15
16
  const expression = block.bindings[binding];
@@ -1,4 +1,3 @@
1
- import '../types/builder-block.js';
2
1
  import { getProcessedBlock } from './get-processed-block.js';
3
2
  test('Can process bindings', () => {
4
3
  const block = {
@@ -0,0 +1,6 @@
1
+ import type { BuilderContextInterface } from '../context/types.js';
2
+ import type { BuilderBlock } from '../types/builder-block.js';
3
+ export declare function getReactNativeBlockStyles({ block, context, }: {
4
+ block: BuilderBlock;
5
+ context: BuilderContextInterface;
6
+ }): CSSStyleDeclaration | Record<string, string | undefined>;
@@ -0,0 +1,16 @@
1
+ import { sanitizeReactNativeBlockStyles } from './sanitize-react-native-block-styles.js';
2
+ export function getReactNativeBlockStyles({ block, context, }) {
3
+ const responsiveStyles = block.responsiveStyles;
4
+ if (!responsiveStyles) {
5
+ return {};
6
+ }
7
+ const styles = {
8
+ // recursively apply inherited styles so that they can be passed down to children `Text` blocks
9
+ ...context.inheritedStyles,
10
+ ...(responsiveStyles.large || {}),
11
+ ...(responsiveStyles.medium || {}),
12
+ ...(responsiveStyles.small || {}),
13
+ };
14
+ const newStyles = sanitizeReactNativeBlockStyles(styles);
15
+ return newStyles;
16
+ }
@@ -1,4 +1,4 @@
1
- import { RegisteredComponent } from '../context/types.js';
1
+ import type { RegisteredComponent } from '../context/types.js';
2
2
  import type { ComponentInfo } from '../types/components.js';
3
3
  /**
4
4
  * @deprecated. Use the `customComponents` prop in RenderContent instead to provide your custom components to the builder SDK.
@@ -8,7 +8,7 @@ export declare const components: RegisteredComponent[];
8
8
  * @deprecated. Use the `customComponents` prop in RenderContent instead to provide your custom components to the builder SDK.
9
9
  */
10
10
  export declare function registerComponent(component: any, info: ComponentInfo): void;
11
- export declare const createRegisterComponentMessage: ({ component, ...info }: RegisteredComponent) => {
11
+ export declare const createRegisterComponentMessage: ({ component: _, ...info }: RegisteredComponent) => {
12
12
  type: string;
13
13
  data: ComponentInfo;
14
14
  };
@@ -1,4 +1,4 @@
1
- import '../context/types.js';
1
+ import { fastClone } from './fast-clone.js';
2
2
  /**
3
3
  * @deprecated. Use the `customComponents` prop in RenderContent instead to provide your custom components to the builder SDK.
4
4
  */
@@ -15,10 +15,6 @@ export const createRegisterComponentMessage = ({ component: _, ...info }) => ({
15
15
  type: 'builder.registerComponent',
16
16
  data: prepareComponentInfoToSend(info),
17
17
  });
18
- /**
19
- * We need to serialize values to a string in case there are Proxy values, as is the case with SolidJS etc.
20
- */
21
- const fastClone = (obj) => JSON.parse(JSON.stringify(obj));
22
18
  const serializeValue = (value) => typeof value === 'function' ? serializeFn(value) : fastClone(value);
23
19
  /**
24
20
  * Input attributes that are functions must be converted to strings before being serialized to JSON.
@@ -1,5 +1,5 @@
1
- import { BuilderBlock } from '../types/builder-block.js';
2
- import { DeepPartial } from '../types/deep-partial.js';
1
+ import type { BuilderBlock } from '../types/builder-block.js';
2
+ import type { DeepPartial } from '../types/deep-partial.js';
3
3
  export interface InsertMenuItem {
4
4
  name: string;
5
5
  icon?: string;
@@ -1,5 +1,3 @@
1
- import '../types/builder-block.js';
2
- import '../types/deep-partial.js';
3
1
  import { isBrowser } from './is-browser.js';
4
2
  const registry = {};
5
3
  export function register(type, info) {
@@ -0,0 +1,3 @@
1
+ declare type Styles = Record<string, string | number>;
2
+ export declare const sanitizeReactNativeBlockStyles: (styles: Styles) => Styles;
3
+ export {};
@@ -0,0 +1,53 @@
1
+ const propertiesThatMustBeNumber = new Set(['lineHeight']);
2
+ const displayValues = new Set(['flex', 'none']);
3
+ const SHOW_WARNINGS = false;
4
+ const normalizeNumber = (value) => {
5
+ if (Number.isNaN(value)) {
6
+ return undefined;
7
+ }
8
+ else if (value < 0) {
9
+ // TODO: why are negative values not allowed?
10
+ return 0;
11
+ }
12
+ else {
13
+ return value;
14
+ }
15
+ };
16
+ export const sanitizeReactNativeBlockStyles = (styles) => {
17
+ return Object.keys(styles).reduce((acc, key) => {
18
+ const propertyValue = styles[key];
19
+ if (key === 'display' && !displayValues.has(propertyValue)) {
20
+ if (SHOW_WARNINGS) {
21
+ console.warn(`Style value for key "display" must be "flex" or "none" but had ${propertyValue}`);
22
+ }
23
+ return acc;
24
+ }
25
+ if (propertiesThatMustBeNumber.has(key) &&
26
+ typeof propertyValue !== 'number') {
27
+ if (SHOW_WARNINGS) {
28
+ console.warn(`Style key ${key} must be a number, but had value \`${styles[key]}\``);
29
+ }
30
+ return acc;
31
+ }
32
+ if (typeof propertyValue === 'string') {
33
+ // `px` units need to be stripped and replaced with numbers
34
+ // https://regexr.com/6ualn
35
+ const isPixelUnit = propertyValue.match(/^-?(\d*)(\.?)(\d*)*px$/);
36
+ if (isPixelUnit) {
37
+ const newValue = parseFloat(propertyValue);
38
+ const normalizedValue = normalizeNumber(newValue);
39
+ if (normalizedValue) {
40
+ return { ...acc, [key]: normalizedValue };
41
+ }
42
+ else {
43
+ return acc;
44
+ }
45
+ }
46
+ else if (propertyValue === '0') {
47
+ // 0 edge case needs to be handled
48
+ return { ...acc, [key]: 0 };
49
+ }
50
+ }
51
+ return { ...acc, [key]: propertyValue };
52
+ }, {});
53
+ };
@@ -1,4 +1,4 @@
1
- import { CanTrack } from '../types/can-track.js';
1
+ import type { CanTrack } from '../types/can-track.js';
2
2
  interface Event {
3
3
  type: 'click' | 'impression';
4
4
  data: {
@@ -1,25 +1,24 @@
1
1
  import { TARGET } from '../constants/target.js';
2
2
  import { getSessionId } from '../helpers/sessionId.js';
3
3
  import { getVisitorId } from '../helpers/visitorId.js';
4
- import '../types/can-track.js';
5
4
  import { isBrowser } from './is-browser.js';
6
5
  import { isEditing } from './is-editing.js';
7
- const getTrackingEventData = ({ canTrack }) => {
6
+ const getTrackingEventData = async ({ canTrack, }) => {
8
7
  if (!canTrack) {
9
8
  return { visitorId: undefined, sessionId: undefined };
10
9
  }
11
- const sessionId = getSessionId({ canTrack });
10
+ const sessionId = await getSessionId({ canTrack });
12
11
  const visitorId = getVisitorId({ canTrack });
13
12
  return {
14
13
  sessionId,
15
14
  visitorId,
16
15
  };
17
16
  };
18
- const createEvent = ({ type: eventType, canTrack, orgId, contentId, ...properties }) => ({
17
+ const createEvent = async ({ type: eventType, canTrack, orgId, contentId, ...properties }) => ({
19
18
  type: eventType,
20
19
  data: {
21
20
  ...properties,
22
- ...getTrackingEventData({ canTrack }),
21
+ ...(await getTrackingEventData({ canTrack })),
23
22
  ownerId: orgId,
24
23
  contentId,
25
24
  },
@@ -37,7 +36,7 @@ export async function track(eventProps) {
37
36
  return fetch(`https://builder.io/api/v1/track`, {
38
37
  method: 'POST',
39
38
  body: JSON.stringify({
40
- events: [createEvent(eventProps)],
39
+ events: [await createEvent(eventProps)],
41
40
  }),
42
41
  headers: {
43
42
  'content-type': 'application/json',
@@ -1,2 +1,2 @@
1
- import { BuilderBlock } from '../types/builder-block.js';
1
+ import type { BuilderBlock } from '../types/builder-block.js';
2
2
  export declare function transformBlock(block: BuilderBlock): BuilderBlock;
@@ -1,4 +1,3 @@
1
- import '../types/builder-block.js';
2
1
  // Noope way for targets to make modifications to the block object if/as needed
3
2
  export function transformBlock(block) {
4
3
  return block;
@@ -0,0 +1,8 @@
1
+ import type { CanTrack } from '../types/can-track.js';
2
+ export declare const getContentVariationCookie: ({ contentId, canTrack, }: {
3
+ contentId: string;
4
+ } & CanTrack) => Promise<string | undefined>;
5
+ export declare const setContentVariationCookie: ({ contentId, canTrack, value, }: {
6
+ contentId: string;
7
+ value: string;
8
+ } & CanTrack) => Promise<undefined>;
@@ -0,0 +1,5 @@
1
+ import { getCookie, setCookie } from './cookie.js';
2
+ const BUILDER_STORE_PREFIX = 'builderio.variations';
3
+ const getContentTestKey = (id) => `${BUILDER_STORE_PREFIX}.${id}`;
4
+ export const getContentVariationCookie = ({ contentId, canTrack, }) => getCookie({ name: getContentTestKey(contentId), canTrack });
5
+ export const setContentVariationCookie = ({ contentId, canTrack, value, }) => setCookie({ name: getContentTestKey(contentId), value, canTrack });
@@ -1,9 +1,15 @@
1
- import { CanTrack } from '../types/can-track.js';
1
+ import type { CanTrack } from '../types/can-track.js';
2
+ /**
3
+ * NOTE: This function is `async` because its react-native override is async. Do not remove the `async` keyword!
4
+ */
2
5
  export declare const getCookie: ({ name, canTrack, }: {
3
6
  name: string;
4
- } & CanTrack) => string | undefined;
7
+ } & CanTrack) => Promise<string | undefined>;
8
+ /**
9
+ * NOTE: This function is `async` because its react-native override is async. Do not remove the `async` keyword!
10
+ */
5
11
  export declare const setCookie: ({ name, value, expires, canTrack, }: {
6
12
  name: string;
7
13
  value: string;
8
14
  expires?: Date | undefined;
9
- } & CanTrack) => undefined;
15
+ } & CanTrack) => Promise<undefined>;
@@ -1,7 +1,9 @@
1
1
  import { isBrowser } from '../functions/is-browser.js';
2
- import '../types/can-track.js';
3
2
  import { getTopLevelDomain } from './url.js';
4
- export const getCookie = ({ name, canTrack, }) => {
3
+ /**
4
+ * NOTE: This function is `async` because its react-native override is async. Do not remove the `async` keyword!
5
+ */
6
+ export const getCookie = async ({ name, canTrack, }) => {
5
7
  try {
6
8
  if (!canTrack) {
7
9
  return undefined;
@@ -41,7 +43,10 @@ const createCookieString = ({ name, value, expires, }) => {
41
43
  const cookie = stringifyCookie(cookieValue);
42
44
  return cookie;
43
45
  };
44
- export const setCookie = ({ name, value, expires, canTrack, }) => {
46
+ /**
47
+ * NOTE: This function is `async` because its react-native override is async. Do not remove the `async` keyword!
48
+ */
49
+ export const setCookie = async ({ name, value, expires, canTrack, }) => {
45
50
  try {
46
51
  if (!canTrack) {
47
52
  return undefined;