@builder.io/sdk-react 0.4.0 → 0.4.2

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.
@@ -108,17 +108,17 @@ function Columns(props) {
108
108
  const builderContext = useContext(BuilderContext);
109
109
  return (React.createElement(React.Fragment, null,
110
110
  React.createElement("div", { className: `builder-columns ${props.builderBlock.id}-breakpoints` +
111
- " div-08005e06", style: columnsCssVars() },
111
+ " div-fa2ab8fc", style: columnsCssVars() },
112
112
  TARGET !== "reactNative" ? (React.createElement(React.Fragment, null,
113
113
  React.createElement(RenderInlinedStyles, { styles: columnsStyles() }))) : null,
114
- props.columns?.map((column, index) => (React.createElement("div", { className: "builder-column div-08005e06-2", style: columnCssVars(index), key: index },
114
+ props.columns?.map((column, index) => (React.createElement("div", { className: "builder-column div-fa2ab8fc-2", style: columnCssVars(index), key: index },
115
115
  React.createElement(RenderBlocks, { blocks: column.blocks, path: `component.options.columns.${index}.blocks`, parent: props.builderBlock.id, styleProp: {
116
116
  flexGrow: "1",
117
117
  } }))))),
118
- React.createElement("style", null, `.div-08005e06 {
118
+ React.createElement("style", null, `.div-fa2ab8fc {
119
119
  display: flex;
120
120
  line-height: normal;
121
- }.div-08005e06-2 {
121
+ }.div-fa2ab8fc-2 {
122
122
  display: flex;
123
123
  flex-direction: column;
124
124
  align-items: stretch;
@@ -8,7 +8,7 @@ export const componentInfo = {
8
8
  name: 'image',
9
9
  bubble: true,
10
10
  type: 'file',
11
- allowedFileTypes: ['jpeg', 'jpg', 'png', 'svg'],
11
+ allowedFileTypes: ['jpeg', 'jpg', 'png', 'svg', 'gif', 'webp'],
12
12
  required: true,
13
13
  },
14
14
  ],
@@ -9,7 +9,6 @@ import BlockStyles from "./block-styles";
9
9
  import { getComponent, getRepeatItemData, isEmptyHtmlElement, } from "./render-block.helpers.js";
10
10
  import RenderRepeatedBlock from "./render-repeated-block";
11
11
  import { TARGET } from "../../constants/target.js";
12
- import { extractTextStyles } from "../../functions/extract-text-styles.js";
13
12
  import RenderComponent from "./render-component";
14
13
  import { getReactNativeBlockStyles } from "../../functions/get-react-native-block-styles.js";
15
14
  function RenderBlock(props) {
@@ -79,29 +78,6 @@ function RenderBlock(props) {
79
78
  const shouldRenderChildrenOutsideRef = !component?.component && !repeatItem();
80
79
  return shouldRenderChildrenOutsideRef ? useBlock().children ?? [] : [];
81
80
  }
82
- function childrenContext() {
83
- const getInheritedTextStyles = () => {
84
- if (TARGET !== "reactNative") {
85
- return {};
86
- }
87
- return extractTextStyles(getReactNativeBlockStyles({
88
- block: useBlock(),
89
- context: props.context,
90
- blockStyles: attributes().style,
91
- }));
92
- };
93
- return {
94
- apiKey: props.context.apiKey,
95
- apiVersion: props.context.apiVersion,
96
- localState: props.context.localState,
97
- rootState: props.context.rootState,
98
- rootSetState: props.context.rootSetState,
99
- content: props.context.content,
100
- context: props.context.context,
101
- registeredComponents: props.context.registeredComponents,
102
- inheritedStyles: getInheritedTextStyles(),
103
- };
104
- }
105
81
  function renderComponentProps() {
106
82
  return {
107
83
  blockChildren: useBlock().children ?? [],
@@ -121,9 +97,10 @@ function RenderBlock(props) {
121
97
  },
122
98
  }),
123
99
  },
124
- context: childrenContext(),
100
+ context: childrenContext,
125
101
  };
126
102
  }
103
+ const [childrenContext, setChildrenContext] = useState(() => props.context);
127
104
  return (React.createElement(React.Fragment, null, canShowBlock() ? (React.createElement(React.Fragment, null, !component?.noWrap ? (React.createElement(React.Fragment, null,
128
105
  isEmptyHtmlElement(Tag) ? (React.createElement(React.Fragment, null,
129
106
  React.createElement(Tag, { ...attributes(), ...actions() }))) : null,
@@ -131,8 +108,8 @@ function RenderBlock(props) {
131
108
  !isEmptyHtmlElement(Tag) && !repeatItem() ? (React.createElement(React.Fragment, null,
132
109
  React.createElement(Tag, { ...attributes(), ...actions() },
133
110
  React.createElement(RenderComponent, { ...renderComponentProps() }),
134
- childrenWithoutParentComponent()?.map((child) => (React.createElement(RenderBlock, { key: "render-block-" + child.id, block: child, context: childrenContext() }))),
135
- childrenWithoutParentComponent()?.map((child) => (React.createElement(BlockStyles, { key: "block-style-" + child.id, block: child, context: childrenContext() })))))) : null)) : (React.createElement(React.Fragment, null,
111
+ childrenWithoutParentComponent()?.map((child) => (React.createElement(RenderBlock, { key: "render-block-" + child.id, block: child, context: childrenContext }))),
112
+ childrenWithoutParentComponent()?.map((child) => (React.createElement(BlockStyles, { key: "block-style-" + child.id, block: child, context: childrenContext })))))) : null)) : (React.createElement(React.Fragment, null,
136
113
  React.createElement(RenderComponent, { ...renderComponentProps() }))))) : null));
137
114
  }
138
115
  export default RenderBlock;
@@ -1,5 +1,6 @@
1
1
  'use client';
2
2
  import * as React from "react";
3
+ import { useState } from "react";
3
4
  /**
4
5
  * We can't make this a generic `ProvideContext` function because Vue 2 won't support root slots, e.g.
5
6
  *
@@ -12,17 +13,8 @@ import * as React from "react";
12
13
  import BuilderContext from "../../context/builder.context.js";
13
14
  import RenderBlock from "./render-block";
14
15
  function RenderRepeatedBlock(props) {
15
- return (React.createElement(BuilderContext.Provider, { value: {
16
- content: props.repeatContext.content,
17
- localState: props.repeatContext.localState,
18
- rootState: props.repeatContext.rootState,
19
- rootSetState: props.repeatContext.rootSetState,
20
- context: props.repeatContext.context,
21
- apiKey: props.repeatContext.apiKey,
22
- registeredComponents: props.repeatContext.registeredComponents,
23
- inheritedStyles: props.repeatContext.inheritedStyles,
24
- apiVersion: props.repeatContext.apiVersion,
25
- } },
26
- React.createElement(RenderBlock, { block: props.block, context: props.repeatContext })));
16
+ const [store, setStore] = useState(() => props.repeatContext);
17
+ return (React.createElement(BuilderContext.Provider, { value: store },
18
+ React.createElement(RenderBlock, { block: props.block, context: store })));
27
19
  }
28
20
  export default RenderRepeatedBlock;
@@ -33,10 +33,10 @@ function RenderBlocks(props) {
33
33
  }
34
34
  const builderContext = useContext(BuilderContext);
35
35
  return (React.createElement(React.Fragment, null,
36
- React.createElement("div", { className: className() + " div-251582f2", "builder-path": props.path, "builder-parent-id": props.parent, style: props.styleProp, onClick: (event) => onClick(), onMouseEnter: (event) => onMouseEnter() },
36
+ React.createElement("div", { className: className() + " div-6dd9939e", "builder-path": props.path, "builder-parent-id": props.parent, style: props.styleProp, onClick: (event) => onClick(), onMouseEnter: (event) => onMouseEnter(), onKeyPress: (event) => onClick() },
37
37
  props.blocks ? (React.createElement(React.Fragment, null, props.blocks?.map((block) => (React.createElement(RenderBlock, { key: "render-block-" + block.id, block: block, context: builderContext }))))) : null,
38
38
  props.blocks ? (React.createElement(React.Fragment, null, props.blocks?.map((block) => (React.createElement(BlockStyles, { key: "block-style-" + block.id, block: block, context: builderContext }))))) : null),
39
- React.createElement("style", null, `.div-251582f2 {
39
+ React.createElement("style", null, `.div-6dd9939e {
40
40
  display: flex;
41
41
  flex-direction: column;
42
42
  align-items: stretch;
@@ -25,60 +25,45 @@ function RenderContent(props) {
25
25
  const elementRef = useRef(null);
26
26
  const [forceReRenderCount, setForceReRenderCount] = useState(() => 0);
27
27
  const [overrideContent, setOverrideContent] = useState(() => null);
28
- const [useContent, setUseContent] = useState(() => getContentInitialValue({
29
- content: props.content,
30
- data: props.data,
31
- }));
32
28
  function mergeNewContent(newContent) {
33
- setUseContent({
34
- ...useContent,
35
- ...newContent,
36
- data: {
37
- ...useContent?.data,
38
- ...newContent?.data,
39
- },
40
- meta: {
41
- ...useContent?.meta,
42
- ...newContent?.meta,
43
- breakpoints: newContent?.meta?.breakpoints || useContent?.meta?.breakpoints,
29
+ setBuilderContextSignal((PREVIOUS_VALUE) => ({
30
+ ...PREVIOUS_VALUE,
31
+ content: {
32
+ ...builderContextSignal.content,
33
+ ...newContent,
34
+ data: {
35
+ ...builderContextSignal.content?.data,
36
+ ...newContent?.data,
37
+ },
38
+ meta: {
39
+ ...builderContextSignal.content?.meta,
40
+ ...newContent?.meta,
41
+ breakpoints: newContent?.meta?.breakpoints ||
42
+ builderContextSignal.content?.meta?.breakpoints,
43
+ },
44
44
  },
45
- });
45
+ }));
46
46
  }
47
47
  function setBreakpoints(breakpoints) {
48
- setUseContent({
49
- ...useContent,
50
- meta: {
51
- ...useContent?.meta,
52
- breakpoints,
48
+ setBuilderContextSignal((PREVIOUS_VALUE) => ({
49
+ ...PREVIOUS_VALUE,
50
+ content: {
51
+ ...builderContextSignal.content,
52
+ meta: {
53
+ ...builderContextSignal.content?.meta,
54
+ breakpoints,
55
+ },
53
56
  },
54
- });
57
+ }));
55
58
  }
56
59
  const [update, setUpdate] = useState(() => 0);
57
60
  const [canTrackToUse, setCanTrackToUse] = useState(() => checkIsDefined(props.canTrack) ? props.canTrack : true);
58
- const [contentState, setContentState] = useState(() => getContextStateInitialValue({
59
- content: props.content,
60
- data: props.data,
61
- locale: props.locale,
62
- }));
63
61
  function contentSetState(newRootState) {
64
- setContentState(newRootState);
62
+ setBuilderContextSignal((PREVIOUS_VALUE) => ({
63
+ ...PREVIOUS_VALUE,
64
+ rootState: newRootState,
65
+ }));
65
66
  }
66
- const [allRegisteredComponents, setAllRegisteredComponents] = useState(() => [
67
- ...getDefaultRegisteredComponents(),
68
- // While this `components` object is deprecated, we must maintain support for it.
69
- // Since users are able to override our default components, we need to make sure that we do not break such
70
- // existing usage.
71
- // This is why we spread `components` after the default Builder.io components, but before the `props.customComponents`,
72
- // which is the new standard way of providing custom components, and must therefore take precedence.
73
- ...components,
74
- ...(props.customComponents || []),
75
- ].reduce((acc, { component, ...curr }) => ({
76
- ...acc,
77
- [curr.name]: {
78
- component: TARGET === "vue3" ? wrapComponentRef(component) : component,
79
- ...curr,
80
- },
81
- }), {}));
82
67
  function processMessage(event) {
83
68
  const { data } = event;
84
69
  if (data) {
@@ -86,7 +71,7 @@ function RenderContent(props) {
86
71
  case "builder.configureSdk": {
87
72
  const messageContent = data.data;
88
73
  const { breakpoints, contentId } = messageContent;
89
- if (!contentId || contentId !== useContent?.id) {
74
+ if (!contentId || contentId !== builderContextSignal.content?.id) {
90
75
  return;
91
76
  }
92
77
  if (breakpoints) {
@@ -117,13 +102,13 @@ function RenderContent(props) {
117
102
  }
118
103
  function evaluateJsCode() {
119
104
  // run any dynamic JS code attached to content
120
- const jsCode = useContent?.data?.jsCode;
105
+ const jsCode = builderContextSignal.content?.data?.jsCode;
121
106
  if (jsCode) {
122
107
  evaluate({
123
108
  code: jsCode,
124
109
  context: props.context || {},
125
110
  localState: undefined,
126
- rootState: contentState,
111
+ rootState: builderContextSignal.rootState,
127
112
  rootSetState: contentSetState,
128
113
  });
129
114
  }
@@ -131,9 +116,9 @@ function RenderContent(props) {
131
116
  const [httpReqsData, setHttpReqsData] = useState(() => ({}));
132
117
  const [clicked, setClicked] = useState(() => false);
133
118
  function onClick(event) {
134
- if (useContent) {
135
- const variationId = useContent?.testVariationId;
136
- const contentId = useContent?.id;
119
+ if (builderContextSignal.content) {
120
+ const variationId = builderContextSignal.content?.testVariationId;
121
+ const contentId = builderContextSignal.content?.id;
137
122
  _track({
138
123
  type: "click",
139
124
  canTrack: canTrackToUse,
@@ -153,7 +138,7 @@ function RenderContent(props) {
153
138
  code: group,
154
139
  context: props.context || {},
155
140
  localState: undefined,
156
- rootState: contentState,
141
+ rootState: builderContextSignal.rootState,
157
142
  rootSetState: contentSetState,
158
143
  }));
159
144
  }
@@ -162,7 +147,7 @@ function RenderContent(props) {
162
147
  .then((response) => response.json())
163
148
  .then((json) => {
164
149
  const newState = {
165
- ...contentState,
150
+ ...builderContextSignal.rootState,
166
151
  [key]: json,
167
152
  };
168
153
  contentSetState(newState);
@@ -172,7 +157,7 @@ function RenderContent(props) {
172
157
  });
173
158
  }
174
159
  function runHttpRequests() {
175
- const requests = useContent?.data?.httpRequests ?? {};
160
+ const requests = builderContextSignal.content?.data?.httpRequests ?? {};
176
161
  Object.entries(requests).forEach(([key, url]) => {
177
162
  if (url && (!httpReqsData[key] || isEditing())) {
178
163
  const evaluatedUrl = evalExpression(url);
@@ -187,7 +172,7 @@ function RenderContent(props) {
187
172
  if (isEditing()) {
188
173
  window.dispatchEvent(new CustomEvent("builder:component:stateChange", {
189
174
  detail: {
190
- state: contentState,
175
+ state: builderContextSignal.rootState,
191
176
  ref: {
192
177
  name: props.model,
193
178
  },
@@ -200,6 +185,39 @@ function RenderContent(props) {
200
185
  contentId: props.content?.id,
201
186
  parentContentId: props.parentContentId,
202
187
  }));
188
+ const [builderContextSignal, setBuilderContextSignal] = useState(() => ({
189
+ content: getContentInitialValue({
190
+ content: props.content,
191
+ data: props.data,
192
+ }),
193
+ localState: undefined,
194
+ rootState: getContextStateInitialValue({
195
+ content: props.content,
196
+ data: props.data,
197
+ locale: props.locale,
198
+ }),
199
+ rootSetState: contentSetState,
200
+ context: props.context || {},
201
+ apiKey: props.apiKey,
202
+ apiVersion: props.apiVersion,
203
+ registeredComponents: [
204
+ ...getDefaultRegisteredComponents(),
205
+ // While this `components` object is deprecated, we must maintain support for it.
206
+ // Since users are able to override our default components, we need to make sure that we do not break such
207
+ // existing usage.
208
+ // This is why we spread `components` after the default Builder.io components, but before the `props.customComponents`,
209
+ // which is the new standard way of providing custom components, and must therefore take precedence.
210
+ ...components,
211
+ ...(props.customComponents || []),
212
+ ].reduce((acc, { component, ...curr }) => ({
213
+ ...acc,
214
+ [curr.name]: {
215
+ component: TARGET === "vue3" ? wrapComponentRef(component) : component,
216
+ ...curr,
217
+ },
218
+ }), {}),
219
+ inheritedStyles: {},
220
+ }));
203
221
  useEffect(() => {
204
222
  if (!props.apiKey) {
205
223
  logger.error("No API key provided to `RenderContent` component. This can cause issues. Please provide an API key using the `apiKey` prop.");
@@ -225,16 +243,16 @@ function RenderContent(props) {
225
243
  }
226
244
  : {}),
227
245
  });
228
- Object.values(allRegisteredComponents).forEach((registeredComponent) => {
246
+ Object.values(builderContextSignal.registeredComponents).forEach((registeredComponent) => {
229
247
  const message = createRegisterComponentMessage(registeredComponent);
230
248
  window.parent?.postMessage(message, "*");
231
249
  });
232
250
  window.addEventListener("message", processMessage);
233
251
  window.addEventListener("builder:component:stateChangeListenerActivated", emitStateUpdate);
234
252
  }
235
- if (useContent) {
236
- const variationId = useContent?.testVariationId;
237
- const contentId = useContent?.id;
253
+ if (builderContextSignal.content) {
254
+ const variationId = builderContextSignal.content?.testVariationId;
255
+ const contentId = builderContextSignal.content?.id;
238
256
  _track({
239
257
  type: "impression",
240
258
  canTrack: canTrackToUse,
@@ -282,13 +300,16 @@ function RenderContent(props) {
282
300
  }, [props.content]);
283
301
  useEffect(() => {
284
302
  evaluateJsCode();
285
- }, [useContent?.data?.jsCode, contentState]);
303
+ }, [
304
+ builderContextSignal.content?.data?.jsCode,
305
+ builderContextSignal.rootState,
306
+ ]);
286
307
  useEffect(() => {
287
308
  runHttpRequests();
288
- }, [useContent?.data?.httpRequests]);
309
+ }, [builderContextSignal.content?.data?.httpRequests]);
289
310
  useEffect(() => {
290
311
  emitStateUpdate();
291
- }, [contentState]);
312
+ }, [builderContextSignal.rootState]);
292
313
  useEffect(() => {
293
314
  return () => {
294
315
  if (isBrowser()) {
@@ -297,18 +318,8 @@ function RenderContent(props) {
297
318
  }
298
319
  };
299
320
  }, []);
300
- return (React.createElement(builderContext.Provider, { value: {
301
- content: useContent,
302
- localState: undefined,
303
- rootState: contentState,
304
- rootSetState: TARGET === "qwik" ? undefined : contentSetState,
305
- context: props.context || {},
306
- apiKey: props.apiKey,
307
- apiVersion: props.apiVersion,
308
- registeredComponents: allRegisteredComponents,
309
- inheritedStyles: {},
310
- } }, useContent ? (React.createElement(React.Fragment, null,
311
- React.createElement("div", { ref: elementRef, onClick: (event) => onClick(event), "builder-content-id": useContent?.id, "builder-model": props.model, ...(TARGET === "reactNative"
321
+ return (React.createElement(builderContext.Provider, { value: builderContextSignal }, builderContextSignal.content ? (React.createElement(React.Fragment, null,
322
+ React.createElement("div", { ref: elementRef, onClick: (event) => onClick(event), "builder-content-id": builderContextSignal.content?.id, "builder-model": props.model, ...(TARGET === "reactNative"
312
323
  ? {
313
324
  dataSet: {
314
325
  // currently, we can't set the actual ID here. // we don't need it right now, we just need to identify content divs for testing.
@@ -324,7 +335,7 @@ function RenderContent(props) {
324
335
  props.isSsrAbTest ? (React.createElement(React.Fragment, null,
325
336
  React.createElement("script", { dangerouslySetInnerHTML: { __html: scriptStr } }))) : null,
326
337
  TARGET !== "reactNative" ? (React.createElement(React.Fragment, null,
327
- React.createElement(RenderContentStyles, { contentId: useContent?.id, cssCode: useContent?.data?.cssCode, customFonts: useContent?.data?.customFonts }))) : null,
328
- React.createElement(RenderBlocks, { blocks: useContent?.data?.blocks, key: forceReRenderCount })))) : null));
338
+ React.createElement(RenderContentStyles, { contentId: builderContextSignal.content?.id, cssCode: builderContextSignal.content?.data?.cssCode, customFonts: builderContextSignal.content?.data?.customFonts }))) : null,
339
+ React.createElement(RenderBlocks, { blocks: builderContextSignal.content?.data?.blocks, key: forceReRenderCount })))) : null));
329
340
  }
330
341
  export default RenderContent;
@@ -1 +1 @@
1
- export declare const SDK_VERSION = "0.4.0";
1
+ export declare const SDK_VERSION = "0.4.2";
@@ -1 +1 @@
1
- export const SDK_VERSION = "0.4.0";
1
+ export const SDK_VERSION = "0.4.2";
@@ -1,5 +1,11 @@
1
1
  type QueryObject = Record<string, string | string[]>;
2
2
  export declare const convertSearchParamsToQueryObject: (searchParams: URLSearchParams) => QueryObject;
3
+ /**
4
+ * Receives a `URLSearchParams` object or a regular query object, and returns the subset of query params that are
5
+ * relevant to the Builder SDK.
6
+ *
7
+ * @returns
8
+ */
3
9
  export declare const getBuilderSearchParams: (_options: QueryObject | URLSearchParams | undefined) => QueryObject;
4
10
  export declare const getBuilderSearchParamsFromWindow: () => QueryObject;
5
11
  export declare const normalizeSearchParams: (searchParams: QueryObject | URLSearchParams) => QueryObject;
@@ -8,6 +8,12 @@ export const convertSearchParamsToQueryObject = (searchParams) => {
8
8
  });
9
9
  return options;
10
10
  };
11
+ /**
12
+ * Receives a `URLSearchParams` object or a regular query object, and returns the subset of query params that are
13
+ * relevant to the Builder SDK.
14
+ *
15
+ * @returns
16
+ */
11
17
  export const getBuilderSearchParams = (_options) => {
12
18
  if (!_options) {
13
19
  return {};
@@ -8,6 +8,7 @@ export type { InsertMenuConfig, InsertMenuItem } from './functions/register.js';
8
8
  export { setEditorSettings } from './functions/set-editor-settings.js';
9
9
  export type { Settings } from './functions/set-editor-settings.js';
10
10
  export { getAllContent, getContent, processContentResult, } from './functions/get-content/index.js';
11
+ export { getBuilderSearchParams } from './functions/get-builder-search-params/index.js';
11
12
  export { track } from './functions/track/index.js';
12
13
  export type { RegisteredComponent } from './context/types';
13
14
  export type { ComponentInfo } from './types/components';
package/dist/sdk/index.js CHANGED
@@ -6,4 +6,5 @@ export { createRegisterComponentMessage } from './functions/register-component.j
6
6
  export { register } from './functions/register.js';
7
7
  export { setEditorSettings } from './functions/set-editor-settings.js';
8
8
  export { getAllContent, getContent, processContentResult, } from './functions/get-content/index.js';
9
+ export { getBuilderSearchParams } from './functions/get-builder-search-params/index.js';
9
10
  export { track } from './functions/track/index.js';
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@builder.io/sdk-react",
3
3
  "description": "Builder.io SDK for React",
4
- "version": "0.4.0",
4
+ "version": "0.4.2",
5
5
  "type": "module",
6
6
  "files": [
7
7
  "dist"