@builder.io/sdk-solid 0.2.2 → 0.3.1

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.
package/CHANGELOG.md CHANGED
@@ -1,3 +1,7 @@
1
+ ### 0.2.3
2
+
3
+ - No Changes.
4
+
1
5
  ### 0.2.2
2
6
 
3
7
  - Fix: dynamic bindings for Link URLs.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@builder.io/sdk-solid",
3
- "version": "0.2.2",
3
+ "version": "0.3.1",
4
4
  "description": "",
5
5
  "type": "module",
6
6
  "main": "./solid-index.jsx",
@@ -12,10 +12,7 @@
12
12
  }
13
13
  },
14
14
  "scripts": {
15
- "build": "echo 'no need to build solid SDK'",
16
- "release:patch": "yarn run build && npm version patch && npm publish",
17
- "release:minor": "yarn run build && npm version minor && npm publish",
18
- "release:dev": "yarn run build && npm version prerelease && npm publish --tag dev"
15
+ "build": "echo 'no need to build solid SDK'"
19
16
  },
20
17
  "dependencies": {
21
18
  "solid-styled-components": "^0.27.6"
@@ -65,7 +65,7 @@ function Columns(props) {
65
65
  };
66
66
  }
67
67
  const width = getColumnCssWidth(index);
68
- const gutterPixels = `${gutterSize()}px`;
68
+ const gutterPixels = `${gutter}px`;
69
69
  const mobileWidth = "100%";
70
70
  const mobileMarginLeft = 0;
71
71
  return {
@@ -99,30 +99,30 @@ function Columns(props) {
99
99
 
100
100
  function columnsStyles() {
101
101
  return `
102
- @media (max-width: ${getWidthForBreakpointSize("medium")}px) {
103
- .${props.builderBlock.id}-breakpoints {
104
- flex-direction: var(--flex-dir-tablet);
105
- align-items: stretch;
102
+ @media (max-width: ${getWidthForBreakpointSize("medium")}px) {
103
+ .${props.builderBlock.id}-breakpoints {
104
+ flex-direction: var(--flex-dir-tablet);
105
+ align-items: stretch;
106
+ }
107
+
108
+ .${props.builderBlock.id}-breakpoints > .builder-column {
109
+ width: var(--column-width-tablet) !important;
110
+ margin-left: var(--column-margin-left-tablet) !important;
111
+ }
106
112
  }
107
113
 
108
- .${props.builderBlock.id}-breakpoints > .builder-column {
109
- width: var(--column-width-tablet) !important;
110
- margin-left: var(--column-margin-left-tablet) !important;
111
- }
112
- }
113
-
114
- @media (max-width: ${getWidthForBreakpointSize("small")}px) {
115
- .${props.builderBlock.id}-breakpoints {
116
- flex-direction: var(--flex-dir);
117
- align-items: stretch;
118
- }
119
-
120
- .${props.builderBlock.id}-breakpoints > .builder-column {
121
- width: var(--column-width-mobile) !important;
122
- margin-left: var(--column-margin-left-mobile) !important;
123
- }
124
- },
125
- `;
114
+ @media (max-width: ${getWidthForBreakpointSize("small")}px) {
115
+ .${props.builderBlock.id}-breakpoints {
116
+ flex-direction: var(--flex-dir);
117
+ align-items: stretch;
118
+ }
119
+
120
+ .${props.builderBlock.id}-breakpoints > .builder-column {
121
+ width: var(--column-width-mobile) !important;
122
+ margin-left: var(--column-margin-left-mobile) !important;
123
+ }
124
+ },
125
+ `;
126
126
  }
127
127
 
128
128
  const builderContext = useContext(BuilderContext);
@@ -85,7 +85,7 @@ function Symbol(props) {
85
85
  customComponents={Object.values(builderContext.registeredComponents)}
86
86
  data={{
87
87
  ...props.symbol?.data,
88
- ...builderContext.state,
88
+ ...builderContext.localState,
89
89
  ...contentToUse()?.data?.state,
90
90
  }}
91
91
  model={props.symbol?.model}
@@ -14,7 +14,9 @@ function BlockStyles(props) {
14
14
  function useBlock() {
15
15
  return getProcessedBlock({
16
16
  block: props.block,
17
- state: props.context.state,
17
+ localState: props.context.localState,
18
+ rootState: props.context.rootState,
19
+ rootSetState: props.context.rootSetState,
18
20
  context: props.context.context,
19
21
  shouldEvaluateBindings: true,
20
22
  });
@@ -58,7 +58,9 @@ const getComponent = ({
58
58
  var _a;
59
59
  const componentName = (_a = getProcessedBlock({
60
60
  block,
61
- state: context.state,
61
+ localState: context.localState,
62
+ rootState: context.rootState,
63
+ rootSetState: context.rootSetState,
62
64
  context: context.context,
63
65
  shouldEvaluateBindings: false
64
66
  }).component) == null ? void 0 : _a.name;
@@ -85,7 +87,9 @@ const getRepeatItemData = ({
85
87
  }
86
88
  const itemsArray = evaluate({
87
89
  code: repeat.collection,
88
- state: context.state,
90
+ localState: context.localState,
91
+ rootState: context.rootState,
92
+ rootSetState: context.rootSetState,
89
93
  context: context.context
90
94
  });
91
95
  if (!Array.isArray(itemsArray)) {
@@ -95,7 +99,7 @@ const getRepeatItemData = ({
95
99
  const itemNameToUse = repeat.itemName || (collectionName ? collectionName + "Item" : "item");
96
100
  const repeatArray = itemsArray.map((item, index) => ({
97
101
  context: __spreadProps(__spreadValues({}, context), {
98
- state: __spreadProps(__spreadValues({}, context.state), {
102
+ localState: __spreadProps(__spreadValues({}, context.localState), {
99
103
  $index: index,
100
104
  $item: item,
101
105
  [itemNameToUse]: item,
@@ -106,24 +110,8 @@ const getRepeatItemData = ({
106
110
  }));
107
111
  return repeatArray;
108
112
  };
109
- const getProxyState = (context) => {
110
- if (typeof Proxy === "undefined") {
111
- console.error("no Proxy available in this environment, cannot proxy state.");
112
- return context.state;
113
- }
114
- const useState = new Proxy(context.state, {
115
- set: (obj, prop, value) => {
116
- var _a;
117
- obj[prop] = value;
118
- (_a = context.setState) == null ? void 0 : _a.call(context, obj);
119
- return true;
120
- }
121
- });
122
- return useState;
123
- };
124
113
  export {
125
114
  getComponent,
126
- getProxyState,
127
115
  getRepeatItemData,
128
116
  isEmptyHtmlElement
129
117
  };
@@ -8,7 +8,6 @@ import { getProcessedBlock } from "../../functions/get-processed-block.js";
8
8
  import BlockStyles from "./block-styles.jsx";
9
9
  import {
10
10
  getComponent,
11
- getProxyState,
12
11
  getRepeatItemData,
13
12
  isEmptyHtmlElement,
14
13
  } from "./render-block.helpers.js";
@@ -26,25 +25,23 @@ function RenderBlock(props) {
26
25
  })
27
26
  );
28
27
 
29
- const [repeatItemData, setRepeatItemData] = createSignal(
30
- getRepeatItemData({
31
- block: props.block,
32
- context: props.context,
33
- })
34
- );
35
-
36
28
  const [tag, setTag] = createSignal(props.block.tagName || "div");
37
29
 
38
- const [proxyState, setProxyState] = createSignal(
39
- getProxyState(props.context)
40
- );
30
+ function repeatItem() {
31
+ return getRepeatItemData({
32
+ block: props.block,
33
+ context: props.context,
34
+ });
35
+ }
41
36
 
42
37
  function useBlock() {
43
- return repeatItemData()
38
+ return repeatItem()
44
39
  ? props.block
45
40
  : getProcessedBlock({
46
41
  block: props.block,
47
- state: props.context.state,
42
+ localState: props.context.localState,
43
+ rootState: props.context.rootState,
44
+ rootSetState: props.context.rootSetState,
48
45
  context: props.context.context,
49
46
  shouldEvaluateBindings: true,
50
47
  });
@@ -63,7 +60,9 @@ function RenderBlock(props) {
63
60
  function actions() {
64
61
  return getBlockActions({
65
62
  block: useBlock(),
66
- state: TARGET === "qwik" ? props.context.state : proxyState(),
63
+ rootState: props.context.rootState,
64
+ rootSetState: props.context.rootSetState,
65
+ localState: props.context.localState,
67
66
  context: props.context.context,
68
67
  });
69
68
  }
@@ -92,7 +91,7 @@ function RenderBlock(props) {
92
91
  * blocks, and the children will be repeated within those blocks.
93
92
  */
94
93
  const shouldRenderChildrenOutsideRef =
95
- !component()?.component && !repeatItemData();
94
+ !component()?.component && !repeatItem();
96
95
  return shouldRenderChildrenOutsideRef ? useBlock().children ?? [] : [];
97
96
  }
98
97
 
@@ -112,10 +111,11 @@ function RenderBlock(props) {
112
111
  return {
113
112
  apiKey: props.context.apiKey,
114
113
  apiVersion: props.context.apiVersion,
115
- state: props.context.state,
114
+ localState: props.context.localState,
115
+ rootState: props.context.rootState,
116
+ rootSetState: props.context.rootSetState,
116
117
  content: props.context.content,
117
118
  context: props.context.context,
118
- setState: props.context.setState,
119
119
  registeredComponents: props.context.registeredComponents,
120
120
  inheritedStyles: getInheritedTextStyles(),
121
121
  };
@@ -155,8 +155,8 @@ function RenderBlock(props) {
155
155
  <Show when={isEmptyHtmlElement(tag())}>
156
156
  <Dynamic {...attributes()} {...actions()} component={tag()}></Dynamic>
157
157
  </Show>
158
- <Show when={!isEmptyHtmlElement(tag()) && repeatItemData()}>
159
- <For each={repeatItemData()}>
158
+ <Show when={!isEmptyHtmlElement(tag()) && repeatItem()}>
159
+ <For each={repeatItem()}>
160
160
  {(data, _index) => {
161
161
  const index = _index();
162
162
  return (
@@ -169,7 +169,7 @@ function RenderBlock(props) {
169
169
  }}
170
170
  </For>
171
171
  </Show>
172
- <Show when={!isEmptyHtmlElement(tag()) && !repeatItemData()}>
172
+ <Show when={!isEmptyHtmlElement(tag()) && !repeatItem()}>
173
173
  <Dynamic {...attributes()} {...actions()} component={tag()}>
174
174
  <RenderComponent {...renderComponentProps()}></RenderComponent>
175
175
  <For each={childrenWithoutParentComponent()}>
@@ -6,12 +6,14 @@ function RenderRepeatedBlock(props) {
6
6
  <BuilderContext.Provider
7
7
  value={{
8
8
  content: props.repeatContext.content,
9
- state: props.repeatContext.state,
10
- setState: props.repeatContext.setState,
9
+ localState: props.repeatContext.localState,
10
+ rootState: props.repeatContext.rootState,
11
+ rootSetState: props.repeatContext.rootSetState,
11
12
  context: props.repeatContext.context,
12
13
  apiKey: props.repeatContext.apiKey,
13
14
  registeredComponents: props.repeatContext.registeredComponents,
14
15
  inheritedStyles: props.repeatContext.inheritedStyles,
16
+ apiVersion: props.repeatContext.apiVersion,
15
17
  }}
16
18
  >
17
19
  <RenderBlock
@@ -15,16 +15,16 @@ ${getFontCss({
15
15
  })}
16
16
 
17
17
  .builder-text > p:first-of-type, .builder-text > .builder-paragraph:first-of-type {
18
- margin: 0;
18
+ margin: 0;
19
19
  }
20
20
  .builder-text > p, .builder-text > .builder-paragraph {
21
- color: inherit;
22
- line-height: inherit;
23
- letter-spacing: inherit;
24
- font-weight: inherit;
25
- font-size: inherit;
26
- text-align: inherit;
27
- font-family: inherit;
21
+ color: inherit;
22
+ line-height: inherit;
23
+ letter-spacing: inherit;
24
+ font-weight: inherit;
25
+ font-size: inherit;
26
+ text-align: inherit;
27
+ font-family: inherit;
28
28
  }
29
29
  `);
30
30
 
@@ -99,8 +99,8 @@ function RenderContent(props) {
99
99
  });
100
100
  }
101
101
 
102
- function setContextState(newState) {
103
- setContentState(newState);
102
+ function contentSetState(newRootState) {
103
+ setContentState(newRootState);
104
104
  }
105
105
 
106
106
  function processMessage(event) {
@@ -149,7 +149,9 @@ function RenderContent(props) {
149
149
  evaluate({
150
150
  code: jsCode,
151
151
  context: props.context || {},
152
- state: contentState(),
152
+ localState: undefined,
153
+ rootState: contentState(),
154
+ rootSetState: contentSetState,
153
155
  });
154
156
  }
155
157
  }
@@ -178,7 +180,9 @@ function RenderContent(props) {
178
180
  evaluate({
179
181
  code: group,
180
182
  context: props.context || {},
181
- state: contentState(),
183
+ localState: undefined,
184
+ rootState: contentState(),
185
+ rootSetState: contentSetState,
182
186
  })
183
187
  );
184
188
  }
@@ -191,7 +195,7 @@ function RenderContent(props) {
191
195
  ...contentState(),
192
196
  [key]: json,
193
197
  };
194
- setContextState(newState);
198
+ contentSetState(newState);
195
199
  })
196
200
  .catch((err) => {
197
201
  console.error("error fetching dynamic data", url, err);
@@ -349,12 +353,14 @@ function RenderContent(props) {
349
353
  <builderContext.Provider
350
354
  value={{
351
355
  content: useContent,
352
- state: contentState(),
353
- setState: setContextState,
356
+ localState: undefined,
357
+ rootState: contentState(),
358
+ rootSetState: TARGET === "qwik" ? undefined : contentSetState,
354
359
  context: props.context || {},
355
360
  apiKey: props.apiKey,
356
361
  apiVersion: props.apiVersion,
357
362
  registeredComponents: allRegisteredComponents(),
363
+ inheritedStyles: {},
358
364
  }}
359
365
  >
360
366
  <Show when={useContent}>
@@ -5,7 +5,7 @@ import { TARGET } from "../constants/target.js";
5
5
 
6
6
  function RenderInlinedStyles(props) {
7
7
  function tag() {
8
- // NOTE: we have to obfusctate the name of the tag due to a limitation in the svelte-preprocessor plugin.
8
+ // NOTE: we have to obfuscate the name of the tag due to a limitation in the svelte-preprocessor plugin.
9
9
  // https://github.com/sveltejs/vite-plugin-svelte/issues/315#issuecomment-1109000027
10
10
  return "sty" + "le";
11
11
  }
@@ -0,0 +1 @@
1
+ export const SDK_VERSION = "0.3.1"
@@ -2,9 +2,10 @@ import { createContext } from "solid-js";
2
2
  var stdin_default = createContext({
3
3
  content: null,
4
4
  context: {},
5
- state: {},
6
- setState() {
5
+ localState: void 0,
6
+ rootSetState() {
7
7
  },
8
+ rootState: {},
8
9
  apiKey: null,
9
10
  apiVersion: void 0,
10
11
  registeredComponents: {},
@@ -3,7 +3,9 @@ import { isEditing } from "./is-editing.js";
3
3
  function evaluate({
4
4
  code,
5
5
  context,
6
- state,
6
+ localState,
7
+ rootState,
8
+ rootSetState,
7
9
  event,
8
10
  isExpression = true
9
11
  }) {
@@ -19,11 +21,33 @@ function evaluate({
19
21
  const useReturn = isExpression && !(code.includes(";") || code.includes(" return ") || code.trim().startsWith("return "));
20
22
  const useCode = useReturn ? `return (${code});` : code;
21
23
  try {
22
- return new Function("builder", "Builder", "state", "context", "event", useCode)(builder, builder, state, context, event);
24
+ return new Function("builder", "Builder", "state", "context", "event", useCode)(builder, builder, flattenState(rootState, localState, rootSetState), context, event);
23
25
  } catch (e) {
24
26
  console.warn("Builder custom code error: \n While Evaluating: \n ", useCode, "\n", e);
25
27
  }
26
28
  }
29
+ function flattenState(rootState, localState, rootSetState) {
30
+ if (rootState === localState) {
31
+ throw new Error("rootState === localState");
32
+ }
33
+ return new Proxy(rootState, {
34
+ get: (_, prop) => {
35
+ if (localState && prop in localState) {
36
+ return localState[prop];
37
+ }
38
+ return rootState[prop];
39
+ },
40
+ set: (_, prop, value) => {
41
+ if (localState && prop in localState) {
42
+ throw new Error("Writing to local state is not allowed as it is read-only.");
43
+ }
44
+ rootState[prop] = value;
45
+ rootSetState == null ? void 0 : rootSetState(rootState);
46
+ return true;
47
+ }
48
+ });
49
+ }
27
50
  export {
28
- evaluate
51
+ evaluate,
52
+ flattenState
29
53
  };
@@ -0,0 +1,17 @@
1
+ import { flattenState } from "./evaluate";
2
+ describe("flatten state", () => {
3
+ it("should behave normally when no PROTO_STATE", () => {
4
+ const localState = {};
5
+ const rootState = { foo: "bar" };
6
+ const flattened = flattenState(rootState, localState, void 0);
7
+ expect(flattened.foo).toEqual("bar");
8
+ flattened.foo = "baz";
9
+ expect(rootState.foo).toEqual("baz");
10
+ });
11
+ it("should shadow write ", () => {
12
+ const rootState = { foo: "foo" };
13
+ const localState = { foo: "baz" };
14
+ const flattened = flattenState(rootState, localState, void 0);
15
+ expect(() => flattened.foo = "bar").toThrow("Writing to local state is not allowed as it is read-only.");
16
+ });
17
+ });
@@ -2,7 +2,9 @@ import { evaluate } from "./evaluate.js";
2
2
  const createEventHandler = (value, options) => (event) => evaluate({
3
3
  code: value,
4
4
  context: options.context,
5
- state: options.state,
5
+ localState: options.localState,
6
+ rootState: options.rootState,
7
+ rootSetState: options.rootSetState,
6
8
  event,
7
9
  isExpression: false
8
10
  });
@@ -57,7 +57,7 @@ function getAllContent(options) {
57
57
  const res = yield fetch(url.href);
58
58
  const content = yield res.json();
59
59
  if ("status" in content && !("results" in content)) {
60
- logger.error("Error fetching data. ", content, options);
60
+ logger.error("Error fetching data. ", { url, content, options });
61
61
  return content;
62
62
  }
63
63
  const canTrack = options.canTrack !== false;
@@ -24,7 +24,9 @@ import { transformBlock } from "./transform-block.js";
24
24
  const evaluateBindings = ({
25
25
  block,
26
26
  context,
27
- state
27
+ localState,
28
+ rootState,
29
+ rootSetState
28
30
  }) => {
29
31
  if (!block.bindings) {
30
32
  return block;
@@ -36,7 +38,13 @@ const evaluateBindings = ({
36
38
  });
37
39
  for (const binding in block.bindings) {
38
40
  const expression = block.bindings[binding];
39
- const value = evaluate({ code: expression, state, context });
41
+ const value = evaluate({
42
+ code: expression,
43
+ localState,
44
+ rootState,
45
+ rootSetState,
46
+ context
47
+ });
40
48
  set(copied, binding, value);
41
49
  }
42
50
  return copied;
@@ -45,11 +53,19 @@ function getProcessedBlock({
45
53
  block,
46
54
  context,
47
55
  shouldEvaluateBindings,
48
- state
56
+ localState,
57
+ rootState,
58
+ rootSetState
49
59
  }) {
50
60
  const transformedBlock = transformBlock(block);
51
61
  if (shouldEvaluateBindings) {
52
- return evaluateBindings({ block: transformedBlock, state, context });
62
+ return evaluateBindings({
63
+ block: transformedBlock,
64
+ localState,
65
+ rootState,
66
+ rootSetState,
67
+ context
68
+ });
53
69
  } else {
54
70
  return transformedBlock;
55
71
  }
@@ -20,7 +20,9 @@ test("Can process bindings", () => {
20
20
  const processed = getProcessedBlock({
21
21
  block,
22
22
  context: {},
23
- state: { test: "hello" },
23
+ rootState: { test: "hello" },
24
+ rootSetState: void 0,
25
+ localState: void 0,
24
26
  shouldEvaluateBindings: true
25
27
  });
26
28
  expect(processed).not.toEqual(block);
@@ -1,3 +1,4 @@
1
+ import { SDK_VERSION } from "../constants/sdk-version.js";
1
2
  import { TARGET } from "../constants/target.js";
2
3
  import { isBrowser } from "../functions/is-browser.js";
3
4
  import { register } from "../functions/register.js";
@@ -31,6 +32,7 @@ const setupBrowserForEditing = (options = {}) => {
31
32
  type: "builder.sdkInfo",
32
33
  data: {
33
34
  target: TARGET,
35
+ version: SDK_VERSION,
34
36
  supportsPatchUpdates: false,
35
37
  supportsAddBlockScoping: true,
36
38
  supportsCustomBreakpoints: true