@builder.io/sdk-svelte 4.1.3 → 4.2.3

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 (125) hide show
  1. package/lib/browser/blocks/form/form/form.svelte +8 -6
  2. package/lib/browser/blocks/img/component-info.js +33 -3
  3. package/lib/browser/blocks/img/img.svelte +18 -6
  4. package/lib/browser/blocks/symbol/symbol.svelte +5 -2
  5. package/lib/browser/blocks/symbol/symbol.svelte.d.ts +1 -1
  6. package/lib/browser/blocks/symbol/symbol.types.d.ts +1 -2
  7. package/lib/browser/blocks/tabs/tabs.svelte +5 -4
  8. package/lib/browser/blocks/tabs/tabs.svelte.d.ts +1 -1
  9. package/lib/browser/blocks/text/component-info.js +0 -1
  10. package/lib/browser/components/awaiter.types.d.ts +7 -0
  11. package/lib/browser/components/awaiter.types.js +1 -0
  12. package/lib/browser/components/block/block.svelte +2 -2
  13. package/lib/browser/components/block/components/component-ref/component-ref.svelte +8 -8
  14. package/lib/browser/components/block/components/component-ref/component-ref.svelte.d.ts +2 -2
  15. package/lib/browser/components/block/components/interactive-element.svelte +8 -1
  16. package/lib/browser/components/block/components/live-edit-block-styles.svelte +114 -0
  17. package/lib/browser/components/block/components/live-edit-block-styles.svelte.d.ts +22 -0
  18. package/lib/browser/components/block/components/style-wrapper.svelte +25 -0
  19. package/lib/browser/components/block/components/style-wrapper.svelte.d.ts +23 -0
  20. package/lib/browser/components/content/components/enable-editor.svelte +53 -12
  21. package/lib/browser/components/live-edit.svelte +20 -0
  22. package/lib/browser/components/live-edit.svelte.d.ts +26 -0
  23. package/lib/browser/constants/sdk-version.d.ts +1 -1
  24. package/lib/browser/constants/sdk-version.js +1 -1
  25. package/lib/browser/functions/get-content/generate-content-url.js +3 -8
  26. package/lib/browser/functions/get-content/index.js +8 -0
  27. package/lib/browser/functions/register.d.ts +18 -0
  28. package/lib/browser/functions/register.js +12 -0
  29. package/lib/browser/helpers/find-block.d.ts +18 -0
  30. package/lib/browser/helpers/find-block.js +41 -0
  31. package/lib/browser/helpers/subscribe-to-editor.d.ts +3 -2
  32. package/lib/browser/helpers/subscribe-to-editor.js +4 -2
  33. package/lib/browser/server-index.d.ts +1 -1
  34. package/lib/browser/server-index.js +1 -1
  35. package/lib/edge/blocks/form/form/form.svelte +8 -6
  36. package/lib/edge/blocks/img/component-info.js +33 -3
  37. package/lib/edge/blocks/img/img.svelte +18 -6
  38. package/lib/edge/blocks/symbol/symbol.svelte +5 -2
  39. package/lib/edge/blocks/symbol/symbol.svelte.d.ts +1 -1
  40. package/lib/edge/blocks/symbol/symbol.types.d.ts +1 -2
  41. package/lib/edge/blocks/tabs/tabs.svelte +5 -4
  42. package/lib/edge/blocks/tabs/tabs.svelte.d.ts +1 -1
  43. package/lib/edge/blocks/text/component-info.js +0 -1
  44. package/lib/edge/components/awaiter.types.d.ts +7 -0
  45. package/lib/edge/components/awaiter.types.js +1 -0
  46. package/lib/edge/components/block/block.svelte +2 -2
  47. package/lib/edge/components/block/components/component-ref/component-ref.svelte +8 -8
  48. package/lib/edge/components/block/components/component-ref/component-ref.svelte.d.ts +2 -2
  49. package/lib/edge/components/block/components/interactive-element.svelte +8 -1
  50. package/lib/edge/components/block/components/live-edit-block-styles.svelte +114 -0
  51. package/lib/edge/components/block/components/live-edit-block-styles.svelte.d.ts +22 -0
  52. package/lib/edge/components/block/components/style-wrapper.svelte +25 -0
  53. package/lib/edge/components/block/components/style-wrapper.svelte.d.ts +23 -0
  54. package/lib/edge/components/content/components/enable-editor.svelte +53 -12
  55. package/lib/edge/components/live-edit.svelte +20 -0
  56. package/lib/edge/components/live-edit.svelte.d.ts +26 -0
  57. package/lib/edge/constants/sdk-version.d.ts +1 -1
  58. package/lib/edge/constants/sdk-version.js +1 -1
  59. package/lib/edge/functions/get-content/generate-content-url.js +3 -8
  60. package/lib/edge/functions/get-content/index.js +8 -0
  61. package/lib/edge/functions/register.d.ts +18 -0
  62. package/lib/edge/functions/register.js +12 -0
  63. package/lib/edge/helpers/find-block.d.ts +18 -0
  64. package/lib/edge/helpers/find-block.js +41 -0
  65. package/lib/edge/helpers/subscribe-to-editor.d.ts +3 -2
  66. package/lib/edge/helpers/subscribe-to-editor.js +4 -2
  67. package/lib/edge/server-index.d.ts +1 -1
  68. package/lib/edge/server-index.js +1 -1
  69. package/lib/node/blocks/form/form/form.svelte +8 -6
  70. package/lib/node/blocks/img/component-info.js +33 -3
  71. package/lib/node/blocks/img/img.svelte +18 -6
  72. package/lib/node/blocks/symbol/symbol.svelte +5 -2
  73. package/lib/node/blocks/symbol/symbol.svelte.d.ts +1 -1
  74. package/lib/node/blocks/symbol/symbol.types.d.ts +1 -2
  75. package/lib/node/blocks/tabs/tabs.svelte +5 -4
  76. package/lib/node/blocks/tabs/tabs.svelte.d.ts +1 -1
  77. package/lib/node/blocks/text/component-info.js +0 -1
  78. package/lib/node/components/awaiter.types.d.ts +7 -0
  79. package/lib/node/components/awaiter.types.js +1 -0
  80. package/lib/node/components/block/block.svelte +2 -2
  81. package/lib/node/components/block/components/component-ref/component-ref.svelte +8 -8
  82. package/lib/node/components/block/components/component-ref/component-ref.svelte.d.ts +2 -2
  83. package/lib/node/components/block/components/interactive-element.svelte +8 -1
  84. package/lib/node/components/block/components/live-edit-block-styles.svelte +114 -0
  85. package/lib/node/components/block/components/live-edit-block-styles.svelte.d.ts +22 -0
  86. package/lib/node/components/block/components/style-wrapper.svelte +25 -0
  87. package/lib/node/components/block/components/style-wrapper.svelte.d.ts +23 -0
  88. package/lib/node/components/content/components/enable-editor.svelte +53 -12
  89. package/lib/node/components/live-edit.svelte +20 -0
  90. package/lib/node/components/live-edit.svelte.d.ts +26 -0
  91. package/lib/node/constants/sdk-version.d.ts +1 -1
  92. package/lib/node/constants/sdk-version.js +1 -1
  93. package/lib/node/functions/get-content/generate-content-url.js +3 -8
  94. package/lib/node/functions/get-content/index.js +8 -0
  95. package/lib/node/functions/register.d.ts +18 -0
  96. package/lib/node/functions/register.js +12 -0
  97. package/lib/node/helpers/find-block.d.ts +18 -0
  98. package/lib/node/helpers/find-block.js +41 -0
  99. package/lib/node/helpers/subscribe-to-editor.d.ts +3 -2
  100. package/lib/node/helpers/subscribe-to-editor.js +4 -2
  101. package/lib/node/server-index.d.ts +1 -1
  102. package/lib/node/server-index.js +1 -1
  103. package/package.json +1 -1
  104. package/src/blocks/form/form/form.svelte +11 -6
  105. package/src/blocks/img/component-info.ts +33 -3
  106. package/src/blocks/img/img.svelte +22 -6
  107. package/src/blocks/symbol/symbol.svelte +5 -2
  108. package/src/blocks/symbol/symbol.types.ts +1 -1
  109. package/src/blocks/tabs/tabs.svelte +5 -4
  110. package/src/blocks/text/component-info.ts +0 -1
  111. package/src/components/awaiter.types.ts +7 -0
  112. package/src/components/block/block.svelte +2 -2
  113. package/src/components/block/components/component-ref/component-ref.svelte +8 -10
  114. package/src/components/block/components/interactive-element.svelte +7 -0
  115. package/src/components/block/components/live-edit-block-styles.svelte +146 -0
  116. package/src/components/block/components/style-wrapper.svelte +41 -0
  117. package/src/components/content/components/enable-editor.svelte +113 -40
  118. package/src/components/live-edit.svelte +32 -0
  119. package/src/constants/sdk-version.ts +1 -1
  120. package/src/functions/get-content/generate-content-url.ts +3 -8
  121. package/src/functions/get-content/index.ts +8 -0
  122. package/src/functions/register.ts +29 -0
  123. package/src/helpers/find-block.ts +40 -0
  124. package/src/helpers/subscribe-to-editor.ts +7 -4
  125. package/src/server-index.ts +1 -1
@@ -31,11 +31,11 @@
31
31
  provideLinkComponent,
32
32
  provideRegisteredComponents,
33
33
  } from "./block.helpers";
34
- import BlockStyles from "./components/block-styles.svelte";
35
34
  import BlockWrapper from "./components/block-wrapper.svelte";
36
35
  import type { ComponentProps } from "./components/component-ref/component-ref.helpers";
37
36
  import ComponentRef from "./components/component-ref/component-ref.svelte";
38
37
  import RepeatedBlock from "./components/repeated-block.svelte";
38
+ import StyleWrapper from "./components/style-wrapper.svelte";
39
39
  import type { Writable } from "svelte/store";
40
40
 
41
41
  export let block: BlockProps["block"];
@@ -148,7 +148,7 @@
148
148
  </script>
149
149
 
150
150
  {#if canShowBlock()}
151
- <BlockStyles block={processedBlock()} context={$context} />
151
+ <StyleWrapper block={processedBlock()} context={$context} id={block.id} />
152
152
 
153
153
  {#if !blockComponent?.()?.noWrap}
154
154
  {#if !repeatItem()}
@@ -5,22 +5,18 @@
5
5
  import type { ComponentProps } from "./component-ref.helpers";
6
6
  import { getWrapperProps } from "./component-ref.helpers";
7
7
 
8
- export let componentOptions: ComponentProps["componentOptions"];
9
- export let blockChildren: ComponentProps["blockChildren"];
10
8
  export let isInteractive: ComponentProps["isInteractive"];
11
9
  export let componentRef: ComponentProps["componentRef"];
10
+ export let componentOptions: ComponentProps["componentOptions"];
12
11
  export let builderBlock: ComponentProps["builderBlock"];
13
12
  export let context: ComponentProps["context"];
14
13
  export let linkComponent: ComponentProps["linkComponent"];
15
14
  export let includeBlockProps: ComponentProps["includeBlockProps"];
15
+ export let blockChildren: ComponentProps["blockChildren"];
16
16
  export let registeredComponents: ComponentProps["registeredComponents"];
17
17
 
18
18
  let shouldUpdate = false;
19
19
  let Wrapper = isInteractive ? InteractiveElement : componentRef;
20
-
21
- function onUpdateFn_0(..._args: any[]) {}
22
-
23
- $: onUpdateFn_0(...[componentOptions, blockChildren]);
24
20
  </script>
25
21
 
26
22
  {#if componentRef}
@@ -37,8 +33,10 @@
37
33
  contextValue: $context,
38
34
  })}
39
35
  >
40
- {#each blockChildren as child (child.id)}
41
- <Block block={child} {context} {registeredComponents} {linkComponent} />
42
- {/each}
43
- </svelte:component>
36
+ {#if componentRef}
37
+ {#each blockChildren as child (child.id)}
38
+ <Block block={child} {context} {registeredComponents} {linkComponent} />
39
+ {/each}
40
+ {/if}</svelte:component
41
+ >
44
42
  {/if}
@@ -10,12 +10,15 @@
10
10
  </script>
11
11
 
12
12
  <script lang="ts">
13
+ import { TARGET } from "../../../constants/target";
13
14
  import type { BuilderContextInterface } from "../../../context/types";
14
15
  import { getBlockActions } from "../../../functions/get-block-actions";
15
16
  import { getBlockProperties } from "../../../functions/get-block-properties";
17
+ import { isEditing } from "../../../server-index";
16
18
  import type { BuilderBlock } from "../../../types/builder-block";
17
19
  import type { Dictionary } from "../../../types/typescript";
18
20
  import Awaiter from "../../awaiter.svelte";
21
+ import LiveEdit from "../../live-edit.svelte";
19
22
  import type { Writable } from "svelte/store";
20
23
 
21
24
  export let wrapperProps: InteractiveElementProps["wrapperProps"];
@@ -59,6 +62,10 @@
59
62
  props={wrapperProps}
60
63
  attributes={attributes()}><slot /></Awaiter
61
64
  >
65
+ {:else if TARGET === "rsc" && isEditing()}
66
+ <LiveEdit {Wrapper} id={block.id || ""} attributes={attributes()}
67
+ ><slot /></LiveEdit
68
+ >
62
69
  {:else}
63
70
  <svelte:component
64
71
  this={Wrapper}
@@ -0,0 +1,146 @@
1
+ <script context="module" lang="ts">
2
+ type LiveEditBlockStylesProps = {
3
+ id?: any;
4
+ contextProvider: BuilderContextInterface;
5
+ };
6
+ </script>
7
+
8
+ <script lang="ts">
9
+ import {
10
+ getMaxWidthQueryForSize,
11
+ getSizesForBreakpoints,
12
+ } from "../../../constants/device-sizes";
13
+ import { TARGET } from "../../../constants/target";
14
+ import { camelToKebabCase } from "../../../functions/camel-to-kebab-case";
15
+ import { getProcessedBlock } from "../../../functions/get-processed-block";
16
+ import { createCssClass } from "../../../helpers/css";
17
+ import { findBlockById } from "../../../helpers/find-block";
18
+ import { checkIsDefined } from "../../../helpers/nullable";
19
+ import type {
20
+ BuilderBlock,
21
+ BuilderContextInterface,
22
+ } from "../../../server-index";
23
+ import InlinedStyles from "../../inlined-styles.svelte";
24
+
25
+ export let contextProvider: LiveEditBlockStylesProps["contextProvider"];
26
+ export let id: LiveEditBlockStylesProps["id"] = undefined;
27
+
28
+ $: block = () => {
29
+ return findBlockById(contextProvider.content!, id);
30
+ };
31
+ $: processedBlock = () => {
32
+ const foundBlock = block();
33
+ if (!foundBlock) {
34
+ return null;
35
+ }
36
+ const blockToUse = foundBlock.repeat?.collection
37
+ ? foundBlock
38
+ : getProcessedBlock({
39
+ block: foundBlock,
40
+ localState: contextProvider.localState,
41
+ rootState: contextProvider.rootState,
42
+ rootSetState: contextProvider.rootSetState,
43
+ context: contextProvider.context,
44
+ });
45
+ return blockToUse;
46
+ };
47
+ $: canShowBlock = () => {
48
+ if (checkIsDefined(processedBlock?.()?.hide)) {
49
+ return !processedBlock?.()?.hide;
50
+ }
51
+ if (checkIsDefined(processedBlock?.()?.show)) {
52
+ return processedBlock?.()?.show;
53
+ }
54
+ return true;
55
+ };
56
+ $: css = () => {
57
+ const styles = processedBlock?.()?.responsiveStyles;
58
+ const content = contextProvider.content;
59
+ const sizesWithUpdatedBreakpoints = getSizesForBreakpoints(
60
+ content?.meta?.breakpoints || {}
61
+ );
62
+ const contentHasXSmallBreakpoint = Boolean(
63
+ content?.meta?.breakpoints?.xsmall
64
+ );
65
+ const largeStyles = styles?.large;
66
+ const mediumStyles = styles?.medium;
67
+ const smallStyles = styles?.small;
68
+ const xsmallStyles = styles?.xsmall;
69
+ const className = processedBlock?.()?.id;
70
+ if (!className) {
71
+ return "";
72
+ }
73
+ const largeStylesClass = largeStyles
74
+ ? createCssClass({
75
+ className,
76
+ styles: largeStyles,
77
+ })
78
+ : "";
79
+ const mediumStylesClass = mediumStyles
80
+ ? createCssClass({
81
+ className,
82
+ styles: mediumStyles,
83
+ mediaQuery: getMaxWidthQueryForSize(
84
+ "medium",
85
+ sizesWithUpdatedBreakpoints
86
+ ),
87
+ })
88
+ : "";
89
+ const smallStylesClass = smallStyles
90
+ ? createCssClass({
91
+ className,
92
+ styles: smallStyles,
93
+ mediaQuery: getMaxWidthQueryForSize(
94
+ "small",
95
+ sizesWithUpdatedBreakpoints
96
+ ),
97
+ })
98
+ : "";
99
+ const xsmallStylesClass =
100
+ xsmallStyles && contentHasXSmallBreakpoint
101
+ ? createCssClass({
102
+ className,
103
+ styles: xsmallStyles,
104
+ mediaQuery: getMaxWidthQueryForSize(
105
+ "xsmall",
106
+ sizesWithUpdatedBreakpoints
107
+ ),
108
+ })
109
+ : "";
110
+ const hoverAnimation =
111
+ processedBlock().animations &&
112
+ processedBlock().animations.find((item) => item.trigger === "hover");
113
+ let hoverStylesClass = "";
114
+ if (hoverAnimation) {
115
+ const hoverStyles = hoverAnimation.steps?.[1]?.styles || {};
116
+ hoverStylesClass =
117
+ createCssClass({
118
+ className: `${className}:hover`,
119
+ styles: {
120
+ ...hoverStyles,
121
+ transition: `all ${hoverAnimation.duration}s ${camelToKebabCase(
122
+ hoverAnimation.easing
123
+ )}`,
124
+ transitionDelay: hoverAnimation.delay
125
+ ? `${hoverAnimation.delay}s`
126
+ : "0s",
127
+ },
128
+ }) || "";
129
+ }
130
+ return [
131
+ largeStylesClass,
132
+ mediumStylesClass,
133
+ smallStylesClass,
134
+ xsmallStylesClass,
135
+ hoverStylesClass,
136
+ ].join(" ");
137
+ };
138
+ </script>
139
+
140
+ {#if TARGET === "rsc" && css() && canShowBlock()}
141
+ <InlinedStyles
142
+ id="builderio-block"
143
+ styles={css()}
144
+ nonce={contextProvider.nonce}
145
+ />
146
+ {/if}
@@ -0,0 +1,41 @@
1
+ <script context="module" lang="ts">
2
+ type StyleWrapperProps = {
3
+ block: BuilderBlock;
4
+ context: BuilderContextInterface;
5
+ id?: string;
6
+ };
7
+ </script>
8
+
9
+ <script lang="ts">
10
+ import { getContext, onMount } from "svelte";
11
+
12
+ import { TARGET } from "../../../constants/target";
13
+ import { BuilderContext } from "../../../context/index";
14
+ import {
15
+ isEditing,
16
+ BuilderBlock,
17
+ BuilderContextInterface,
18
+ } from "../../../server-index";
19
+ import BlockStyles from "./block-styles.svelte";
20
+ import LiveEditBlockStyles from "./live-edit-block-styles.svelte";
21
+
22
+ export let block: StyleWrapperProps["block"];
23
+ export let context: StyleWrapperProps["context"];
24
+
25
+ let contextProvider = getContext(BuilderContext.key);
26
+
27
+ let isClientEditing = false;
28
+ let isHydrated = false;
29
+
30
+ onMount(() => {});
31
+ </script>
32
+
33
+ {#if isHydrated}
34
+ {#if TARGET === "rsc" && isClientEditing}
35
+ <LiveEditBlockStyles id={block.id} contextProvider={$contextProvider} />
36
+ {:else}
37
+ <BlockStyles {block} {context} />
38
+ {/if}
39
+ {:else}
40
+ <BlockStyles {block} {context} />
41
+ {/if}
@@ -12,6 +12,27 @@
12
12
  setBuilderContextSignal?: (signal: any) => any;
13
13
  children?: any;
14
14
  };
15
+
16
+ interface BuilderRequest {
17
+ "@type": "@builder.io/core:Request";
18
+ request: {
19
+ url: string;
20
+ query?: {
21
+ [key: string]: string;
22
+ };
23
+ headers?: {
24
+ [key: string]: string;
25
+ };
26
+ method: "GET" | "POST" | "PUT" | "PATCH" | "DELETE";
27
+ body?: any;
28
+ };
29
+ options?: {
30
+ [key: string]: any;
31
+ };
32
+ bindings?: {
33
+ [key: string]: string;
34
+ };
35
+ }
15
36
  </script>
16
37
 
17
38
  <script lang="ts">
@@ -32,7 +53,10 @@
32
53
  import { getDefaultCanTrack } from "../../../helpers/canTrack";
33
54
  import { getCookieSync } from "../../../helpers/cookie";
34
55
  import { postPreviewContent } from "../../../helpers/preview-lru-cache/set";
35
- import { createEditorListener } from "../../../helpers/subscribe-to-editor";
56
+ import {
57
+ createEditorListener,
58
+ EditType,
59
+ } from "../../../helpers/subscribe-to-editor";
36
60
  import { setupBrowserForEditing } from "../../../scripts/init-editing";
37
61
  import type { BuilderContent } from "../../../types/builder-content";
38
62
  import type { ComponentInfo } from "../../../types/components";
@@ -75,7 +99,7 @@
75
99
  return styles;
76
100
  }
77
101
 
78
- function mergeNewRootState(newData: Dictionary<any>) {
102
+ function mergeNewRootState(newData: Dictionary<any>, editType?: EditType) {
79
103
  const combinedState = {
80
104
  ...$builderContextSignal.rootState,
81
105
  ...newData,
@@ -85,8 +109,13 @@
85
109
  } else {
86
110
  $builderContextSignal.rootState = combinedState;
87
111
  }
112
+ if ($builderContextSignal.rootSetState) {
113
+ $builderContextSignal.rootSetState(combinedState);
114
+ } else {
115
+ $builderContextSignal.rootState = combinedState;
116
+ }
88
117
  }
89
- function mergeNewContent(newContent: BuilderContent) {
118
+ function mergeNewContent(newContent: BuilderContent, editType?: EditType) {
90
119
  const newContentValue = {
91
120
  ...$builderContextSignal.content,
92
121
  ...newContent,
@@ -125,11 +154,11 @@
125
154
  animation: (animation) => {
126
155
  triggerAnimation(animation);
127
156
  },
128
- contentUpdate: (newContent) => {
129
- mergeNewContent(newContent);
157
+ contentUpdate: (newContent, editType) => {
158
+ mergeNewContent(newContent, editType);
130
159
  },
131
- stateUpdate: (newState) => {
132
- mergeNewRootState(newState);
160
+ stateUpdate: (newState, editType) => {
161
+ mergeNewRootState(newState, editType);
133
162
  },
134
163
  },
135
164
  })(event);
@@ -155,44 +184,77 @@
155
184
  }
156
185
  function runHttpRequests() {
157
186
  const requests: {
158
- [key: string]: string;
187
+ [key: string]: string | any;
159
188
  } = $builderContextSignal.content?.data?.httpRequests ?? {};
160
- Object.entries(requests).forEach(([key, url]) => {
161
- if (!url) return;
189
+ Object.entries(requests).forEach(
190
+ ([key, httpRequest]: [string, BuilderRequest | string]) => {
191
+ if (!httpRequest) return;
192
+ const isCoreRequest =
193
+ typeof httpRequest === "object" &&
194
+ httpRequest["@type"] === "@builder.io/core:Request";
162
195
 
163
- // request already in progress
164
- if (httpReqsPending[key]) return;
196
+ // request already in progress
197
+ if (httpReqsPending[key]) return;
165
198
 
166
- // request already completed, and not in edit mode
167
- if (httpReqsData[key] && !isEditing()) return;
168
- httpReqsPending[key] = true;
169
- const evaluatedUrl = url.replace(/{{([^}]+)}}/g, (_match, group) =>
170
- String(
171
- evaluate({
172
- code: group,
173
- context: context || {},
174
- localState: undefined,
175
- rootState: $builderContextSignal.rootState,
176
- rootSetState: $builderContextSignal.rootSetState,
199
+ // request already completed, and not in edit mode
200
+ if (httpReqsData[key] && !isEditing()) return;
201
+ const url = isCoreRequest
202
+ ? httpRequest.request.url
203
+ : (httpRequest as string);
204
+ httpReqsPending[key] = true;
205
+ const evaluatedUrl = url.replace(
206
+ /{{([^}]+)}}/g,
207
+ (_match: string, group: string) =>
208
+ String(
209
+ evaluate({
210
+ code: group,
211
+ context: context || {},
212
+ localState: undefined,
213
+ rootState: $builderContextSignal.rootState,
214
+ rootSetState: $builderContextSignal.rootSetState,
215
+ })
216
+ )
217
+ );
218
+ const fetchRequestObj = isCoreRequest
219
+ ? {
220
+ url: evaluatedUrl,
221
+ method: httpRequest.request.method,
222
+ headers: httpRequest.request.headers,
223
+ body: httpRequest.request.body,
224
+ }
225
+ : {
226
+ url: evaluatedUrl,
227
+ method: "GET",
228
+ };
229
+ logFetch(JSON.stringify(fetchRequestObj));
230
+ const fetchOptions = {
231
+ method: fetchRequestObj.method,
232
+ headers: fetchRequestObj.headers,
233
+ body: fetchRequestObj.body,
234
+ };
235
+ if (fetchRequestObj.method === "GET") {
236
+ delete fetchOptions.body;
237
+ }
238
+ fetch(fetchRequestObj.url, fetchOptions)
239
+ .then((response) => response.json())
240
+ .then((json) => {
241
+ mergeNewRootState({
242
+ [key]: json,
243
+ });
244
+ httpReqsData[key] = true;
177
245
  })
178
- )
179
- );
180
- logFetch(evaluatedUrl);
181
- fetch(evaluatedUrl)
182
- .then((response) => response.json())
183
- .then((json) => {
184
- mergeNewRootState({
185
- [key]: json,
246
+ .catch((err) => {
247
+ console.error(
248
+ "error fetching dynamic data",
249
+ JSON.stringify(httpRequest),
250
+ err
251
+ );
252
+ })
253
+ .finally(() => {
254
+ httpReqsPending[key] = false;
186
255
  });
187
- httpReqsData[key] = true;
188
- })
189
- .catch((err) => {
190
- console.error("error fetching dynamic data", url, err);
191
- })
192
- .finally(() => {
193
- httpReqsPending[key] = false;
194
- });
195
- });
256
+ }
257
+ );
196
258
  }
197
259
  function emitStateUpdate() {
198
260
  if (isEditing()) {
@@ -302,6 +364,9 @@
302
364
  let elementRef;
303
365
 
304
366
  let hasExecuted = false;
367
+ let contextValue = $builderContextSignal;
368
+ let prevData = null;
369
+ let prevLocale = "";
305
370
  let ContentWrapper = contentWrapper || "div";
306
371
  let httpReqsData = {};
307
372
  let httpReqsPending = {};
@@ -366,7 +431,11 @@
366
431
 
367
432
  function onUpdateFn_2(..._args: any[]) {
368
433
  if (data) {
434
+ if (prevData === data) {
435
+ return;
436
+ }
369
437
  mergeNewRootState(data);
438
+ prevData = data;
370
439
  }
371
440
  }
372
441
 
@@ -374,9 +443,13 @@
374
443
 
375
444
  function onUpdateFn_3(..._args: any[]) {
376
445
  if (locale) {
446
+ if (prevLocale === locale) {
447
+ return;
448
+ }
377
449
  mergeNewRootState({
378
450
  locale: locale,
379
451
  });
452
+ prevLocale = locale;
380
453
  }
381
454
  }
382
455
 
@@ -0,0 +1,32 @@
1
+ <script context="module" lang="ts">
2
+ type LiveEditProps = {
3
+ children?: any;
4
+ id?: any;
5
+ Wrapper?: any;
6
+ attributes?: any;
7
+ };
8
+ </script>
9
+
10
+ <script lang="ts">
11
+ import { getContext } from "svelte";
12
+
13
+ import { BuilderContext } from "../context/index";
14
+ import { findBlockById } from "../helpers/find-block";
15
+
16
+ export let id: LiveEditProps["id"] = undefined;
17
+ export let attributes: LiveEditProps["attributes"] = undefined;
18
+ export let Wrapper: LiveEditProps["Wrapper"] = undefined;
19
+
20
+ let context = getContext(BuilderContext.key);
21
+
22
+ $: block = () => {
23
+ return findBlockById($context.content!, id);
24
+ };
25
+ $: options = () => {
26
+ return block?.()?.component?.options || {};
27
+ };
28
+ </script>
29
+
30
+ <svelte:component this={Wrapper} {...options()} {attributes}
31
+ ><slot /></svelte:component
32
+ >
@@ -1 +1 @@
1
- export const SDK_VERSION = "4.1.3"
1
+ export const SDK_VERSION = "4.2.3"
@@ -39,15 +39,10 @@ export const generateContentUrl = (options: GetContentOptions): URL => {
39
39
  url.searchParams.set('limit', String(limit));
40
40
  url.searchParams.set('noTraverse', String(noTraverse));
41
41
  url.searchParams.set('includeRefs', String(true));
42
- const finalLocale = locale || userAttributes?.locale;
43
- let finalUserAttributes: Record<string, any> = userAttributes || {};
44
- if (finalLocale) {
45
- url.searchParams.set('locale', finalLocale);
46
- finalUserAttributes = {
47
- locale: finalLocale,
48
- ...finalUserAttributes
49
- };
42
+ if (locale) {
43
+ url.searchParams.set('locale', locale);
50
44
  }
45
+ let finalUserAttributes: Record<string, any> = userAttributes || {};
51
46
  if (enrich) url.searchParams.set('enrich', String(enrich));
52
47
  url.searchParams.set('omit', omit ?? 'meta.componentsUsed');
53
48
  if (fields) {
@@ -15,6 +15,14 @@ const checkContentHasResults = (content: ContentResponse): content is ContentRes
15
15
  * Returns the first content entry that matches the given options.
16
16
  */
17
17
  export async function fetchOneEntry(options: GetContentOptions): Promise<BuilderContent | null> {
18
+ const finalLocale = options.locale || options.userAttributes?.locale;
19
+ if (finalLocale) {
20
+ options.locale = finalLocale;
21
+ options.userAttributes = {
22
+ locale: finalLocale,
23
+ ...options.userAttributes
24
+ };
25
+ }
18
26
  const allContent = await fetchEntries({
19
27
  ...options,
20
28
  limit: 1
@@ -1,7 +1,24 @@
1
1
  import type { BuilderBlock } from '../types/builder-block';
2
2
  import type { DeepPartial } from '../types/deep-partial';
3
+ import type { Input } from '../types/input';
3
4
  import { isBrowser } from './is-browser';
4
5
  import { serializeIncludingFunctions } from './register-component';
6
+ export interface Action {
7
+ name: string;
8
+ inputs?: readonly Input[];
9
+ returnType?: Input;
10
+ action: (options: Record<string, any>) => string;
11
+ /**
12
+ * Is an action for expression (e.g. calculating a binding like a formula
13
+ * to fill a value based on locale) or a function (e.g. something to trigger
14
+ * on an event like add to cart) or either (e.g. a custom code block)
15
+ */
16
+ kind: 'expression' | 'function' | 'any';
17
+ /**
18
+ * Globally unique ID for an action, e.g. "@builder.io:setState"
19
+ */
20
+ id: string;
21
+ }
5
22
  export interface InsertMenuItem {
6
23
  name: string;
7
24
  icon?: string;
@@ -45,4 +62,16 @@ export function register(type: string, info: any) {
45
62
  console.debug('Could not postmessage', err);
46
63
  }
47
64
  }
65
+ }
66
+ export function registerAction(action: Action) {
67
+ if (isBrowser()) {
68
+ const actionClone = JSON.parse(JSON.stringify(action));
69
+ if (action.action) {
70
+ actionClone.action = action.action.toString();
71
+ }
72
+ window.parent?.postMessage({
73
+ type: 'builder.registerAction',
74
+ data: actionClone
75
+ }, '*');
76
+ }
48
77
  }
@@ -0,0 +1,40 @@
1
+ import type { BuilderBlock, BuilderContent } from '../server-index';
2
+
3
+ /**
4
+ * Recursively searches for a block by ID.
5
+ *
6
+ * @param content The Builder content to search through.
7
+ * @param id The ID of the block to search for.
8
+ * @returns The block if found, otherwise null.
9
+ */
10
+ export const findBlockById = (content: BuilderContent, id: string): BuilderBlock | null => {
11
+ return findBlockInTree(content.data?.blocks, id);
12
+ };
13
+
14
+ /**
15
+ * Helper function to recursively search through block tree.
16
+ *
17
+ * @param blocks The blocks to search through.
18
+ * @param id The ID of the block to search for.
19
+ * @returns The block if found, otherwise null.
20
+ * @private This is an internal implementation detail.
21
+ */
22
+ export const findBlockInTree = (blocks: BuilderBlock[] | undefined, id: string): BuilderBlock | null => {
23
+ if (!blocks) return null;
24
+ for (const block of blocks) {
25
+ if (block.id === id) return block;
26
+ if (block.children) {
27
+ const child = findBlockInTree(block.children, id);
28
+ if (child) return child;
29
+ }
30
+ if (block.component?.name === 'Columns' && block.component?.options?.columns) {
31
+ for (const column of block.component.options.columns) {
32
+ if (column.blocks) {
33
+ const child = findBlockInTree(column.blocks, id);
34
+ if (child) return child;
35
+ }
36
+ }
37
+ }
38
+ }
39
+ return null;
40
+ }