@builder.io/sdk-solid 0.1.11 → 0.1.13

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@builder.io/sdk-solid",
3
- "version": "0.1.11",
3
+ "version": "0.1.13",
4
4
  "description": "",
5
5
  "type": "module",
6
6
  "main": "./solid-index.jsx",
@@ -6,56 +6,87 @@ import RenderBlocks from "../../components/render-blocks.jsx";
6
6
  import { getSizesForBreakpoints } from "../../constants/device-sizes";
7
7
  import RenderInlinedStyles from "../../components/render-inlined-styles.jsx";
8
8
  import { TARGET } from "../../constants/target.js";
9
- import { convertStyleMapToCSS } from "../../helpers/css";
10
9
  import BuilderContext from "../../context/builder.context.js";
11
10
 
12
11
  function Columns(props) {
13
- function getGutterSize() {
14
- return typeof props.space === "number" ? props.space || 0 : 20;
15
- }
12
+ const [gutterSize, setGutterSize] = createSignal(
13
+ typeof props.space === "number" ? props.space || 0 : 20
14
+ );
16
15
 
17
- function getColumns() {
18
- return props.columns || [];
19
- }
16
+ const [cols, setCols] = createSignal(props.columns || []);
17
+
18
+ const [stackAt, setStackAt] = createSignal(props.stackColumnsAt || "tablet");
19
+
20
+ const [flexDir, setFlexDir] = createSignal(
21
+ props.stackColumnsAt === "never"
22
+ ? "row"
23
+ : props.reverseColumnsWhenStacked
24
+ ? "column-reverse"
25
+ : "column"
26
+ );
20
27
 
21
28
  function getWidth(index) {
22
- const columns = getColumns();
23
- return columns[index]?.width || 100 / columns.length;
29
+ return cols()[index]?.width || 100 / cols().length;
24
30
  }
25
31
 
26
32
  function getColumnCssWidth(index) {
27
- const columns = getColumns();
28
- const gutterSize = getGutterSize();
29
- const subtractWidth = (gutterSize * (columns.length - 1)) / columns.length;
33
+ const subtractWidth = (gutterSize() * (cols().length - 1)) / cols().length;
30
34
  return `calc(${getWidth(index)}% - ${subtractWidth}px)`;
31
35
  }
32
36
 
33
- function maybeApplyForTablet(prop) {
34
- const _stackColumnsAt = props.stackColumnsAt || "tablet";
35
- return _stackColumnsAt === "tablet" ? prop : "inherit";
37
+ function getTabletStyle({ stackedStyle, desktopStyle }) {
38
+ return stackAt() === "tablet" ? stackedStyle : desktopStyle;
39
+ }
40
+
41
+ function getMobileStyle({ stackedStyle, desktopStyle }) {
42
+ return stackAt() === "never" ? desktopStyle : stackedStyle;
36
43
  }
37
44
 
38
45
  function columnsCssVars() {
39
- const flexDir =
40
- props.stackColumnsAt === "never"
41
- ? "inherit"
42
- : props.reverseColumnsWhenStacked
43
- ? "column-reverse"
44
- : "column";
46
+ if (TARGET === "reactNative") {
47
+ return {
48
+ flexDirection: flexDir(),
49
+ };
50
+ }
45
51
  return {
46
- "--flex-dir": flexDir,
47
- "--flex-dir-tablet": maybeApplyForTablet(flexDir),
52
+ "--flex-dir": flexDir(),
53
+ "--flex-dir-tablet": getTabletStyle({
54
+ stackedStyle: flexDir(),
55
+ desktopStyle: "row",
56
+ }),
48
57
  };
49
58
  }
50
59
 
51
- function columnCssVars() {
52
- const width = "100%";
53
- const marginLeft = "0";
60
+ function columnCssVars(index) {
61
+ const width = getColumnCssWidth(index);
62
+ const gutter = `${index === 0 ? 0 : gutterSize()}px`;
63
+ if (TARGET === "reactNative") {
64
+ return {
65
+ width,
66
+ marginLeft: props.stackColumnsAt === "never" ? gutter : "0",
67
+ };
68
+ }
69
+ const mobileWidth = "100%";
70
+ const mobileMarginLeft = "0";
54
71
  return {
55
- "--column-width": width,
56
- "--column-margin-left": marginLeft,
57
- "--column-width-tablet": maybeApplyForTablet(width),
58
- "--column-margin-left-tablet": maybeApplyForTablet(marginLeft),
72
+ width,
73
+ "margin-left": gutter,
74
+ "--column-width-mobile": getMobileStyle({
75
+ stackedStyle: mobileWidth,
76
+ desktopStyle: width,
77
+ }),
78
+ "--column-margin-left-mobile": getMobileStyle({
79
+ stackedStyle: mobileMarginLeft,
80
+ desktopStyle: gutter,
81
+ }),
82
+ "--column-width-tablet": getTabletStyle({
83
+ stackedStyle: mobileWidth,
84
+ desktopStyle: width,
85
+ }),
86
+ "--column-margin-left-tablet": getTabletStyle({
87
+ stackedStyle: mobileMarginLeft,
88
+ desktopStyle: gutter,
89
+ }),
59
90
  };
60
91
  }
61
92
 
@@ -66,63 +97,34 @@ function Columns(props) {
66
97
  return breakpointSizes[size].max;
67
98
  }
68
99
 
69
- function columnStyleObjects() {
70
- return {
71
- columns: {
72
- small: {
73
- flexDirection: "var(--flex-dir)",
74
- alignItems: "stretch",
75
- },
76
- medium: {
77
- flexDirection: "var(--flex-dir-tablet)",
78
- alignItems: "stretch",
79
- },
80
- },
81
- column: {
82
- small: {
83
- width: "var(--column-width) !important",
84
- marginLeft: "var(--column-margin-left) !important",
85
- },
86
- medium: {
87
- width: "var(--column-width-tablet) !important",
88
- marginLeft: "var(--column-margin-left-tablet) !important",
89
- },
90
- },
91
- };
92
- }
93
-
94
100
  function columnsStyles() {
95
101
  return `
96
102
  @media (max-width: ${getWidthForBreakpointSize("medium")}px) {
97
103
  .${props.builderBlock.id}-breakpoints {
98
- ${convertStyleMapToCSS(columnStyleObjects().columns.medium)}
104
+ flex-direction: var(--flex-dir-tablet);
105
+ align-items: stretch;
99
106
  }
100
107
 
101
108
  .${props.builderBlock.id}-breakpoints > .builder-column {
102
- ${convertStyleMapToCSS(columnStyleObjects().column.medium)}
109
+ width: var(--column-width-tablet) !important;
110
+ margin-left: var(--column-margin-left-tablet) !important;
103
111
  }
104
112
  }
105
113
 
106
114
  @media (max-width: ${getWidthForBreakpointSize("small")}px) {
107
115
  .${props.builderBlock.id}-breakpoints {
108
- ${convertStyleMapToCSS(columnStyleObjects().columns.small)}
116
+ flex-direction: var(--flex-dir);
117
+ align-items: stretch;
109
118
  }
110
119
 
111
120
  .${props.builderBlock.id}-breakpoints > .builder-column {
112
- ${convertStyleMapToCSS(columnStyleObjects().column.small)}
121
+ width: var(--column-width-mobile) !important;
122
+ margin-left: var(--column-margin-left-mobile) !important;
113
123
  }
114
124
  },
115
125
  `;
116
126
  }
117
127
 
118
- function reactNativeColumnsStyles() {
119
- return this.columnStyleObjects.columns.small;
120
- }
121
-
122
- function reactNativeColumnStyles() {
123
- return this.columnStyleObjects.column.small;
124
- }
125
-
126
128
  const builderContext = useContext(BuilderContext);
127
129
 
128
130
  return (
@@ -135,9 +137,9 @@ function Columns(props) {
135
137
  lineHeight: "normal",
136
138
  })
137
139
  }
138
- style={{
139
- ...(TARGET === "reactNative" ? reactNativeColumnsStyles() : {}),
140
- ...columnsCssVars(),
140
+ style={columnsCssVars()}
141
+ dataSet={{
142
+ "builder-block-name": "builder-columns",
141
143
  }}
142
144
  >
143
145
  <Show when={TARGET !== "reactNative"}>
@@ -156,11 +158,9 @@ function Columns(props) {
156
158
  alignItems: "stretch",
157
159
  })
158
160
  }
159
- style={{
160
- width: getColumnCssWidth(index),
161
- "margin-left": `${index === 0 ? 0 : getGutterSize()}px`,
162
- ...(TARGET === "reactNative" ? reactNativeColumnStyles() : {}),
163
- ...columnCssVars(),
161
+ style={columnCssVars(index)}
162
+ dataSet={{
163
+ "builder-block-name": "builder-column",
164
164
  }}
165
165
  key={index}
166
166
  >
@@ -1,4 +1,4 @@
1
- import { useContext, on, createEffect, createSignal } from "solid-js";
1
+ import { useContext, onMount, on, createEffect, createSignal } from "solid-js";
2
2
 
3
3
  import RenderContent from "../../components/render-content/render-content.jsx";
4
4
  import BuilderContext from "../../context/builder.context.js";
@@ -6,10 +6,8 @@ import { getContent } from "../../functions/get-content/index.js";
6
6
  import { TARGET } from "../../constants/target";
7
7
 
8
8
  function Symbol(props) {
9
- const [fetchedContent, setFetchedContent] = createSignal(null);
10
-
11
- function className() {
12
- return [
9
+ const [className, setClassName] = createSignal(
10
+ [
13
11
  ...(TARGET === "vue2" || TARGET === "vue3"
14
12
  ? Object.keys(props.attributes.class)
15
13
  : [props.attributes.class]),
@@ -20,18 +18,12 @@ function Symbol(props) {
20
18
  : undefined,
21
19
  ]
22
20
  .filter(Boolean)
23
- .join(" ");
24
- }
25
-
26
- function contentToUse() {
27
- return props.symbol?.content || fetchedContent();
28
- }
29
-
30
- const builderContext = useContext(BuilderContext);
21
+ .join(" ")
22
+ );
31
23
 
32
- function onUpdateFn_0() {
33
- const symbolToUse = props.symbol;
24
+ const [contentToUse, setContentToUse] = createSignal(props.symbol?.content);
34
25
 
26
+ function fetchContent() {
35
27
  /**
36
28
  * If:
37
29
  * - we have a symbol prop
@@ -42,25 +34,40 @@ function Symbol(props) {
42
34
  * then we want to re-fetch the symbol content.
43
35
  */
44
36
  if (
45
- symbolToUse &&
46
- !symbolToUse.content &&
47
- !fetchedContent() &&
48
- symbolToUse.model &&
37
+ !contentToUse() &&
38
+ props.symbol?.model &&
49
39
  // This is a hack, we should not need to check for this, but it is needed for Svelte.
50
40
  builderContext?.apiKey
51
41
  ) {
52
42
  getContent({
53
- model: symbolToUse.model,
43
+ model: props.symbol.model,
54
44
  apiKey: builderContext.apiKey,
45
+ apiVersion: builderContext.apiVersion,
55
46
  query: {
56
- id: symbolToUse.entry,
47
+ id: props.symbol.entry,
57
48
  },
58
- }).then((response) => {
59
- setFetchedContent(response);
60
- });
49
+ })
50
+ .then((response) => {
51
+ if (response) {
52
+ setContentToUse(response);
53
+ }
54
+ })
55
+ .catch((err) => {
56
+ console.error("[Builder.io]: Could not fetch symbol content: ", err);
57
+ });
61
58
  }
62
59
  }
63
- createEffect(on(() => [props.symbol, fetchedContent()], onUpdateFn_0));
60
+
61
+ const builderContext = useContext(BuilderContext);
62
+
63
+ onMount(() => {
64
+ fetchContent();
65
+ });
66
+
67
+ function onUpdateFn_0() {
68
+ fetchContent();
69
+ }
70
+ createEffect(on(() => [props.symbol], onUpdateFn_0));
64
71
 
65
72
  return (
66
73
  <div
@@ -71,13 +78,14 @@ function Symbol(props) {
71
78
  }}
72
79
  >
73
80
  <RenderContent
81
+ apiVersion={builderContext.apiVersion}
74
82
  apiKey={builderContext.apiKey}
75
83
  context={builderContext.context}
76
84
  customComponents={Object.values(builderContext.registeredComponents)}
77
85
  data={{
78
86
  ...props.symbol?.data,
79
87
  ...builderContext.state,
80
- ...props.symbol?.content?.data?.state,
88
+ ...contentToUse()?.data?.state,
81
89
  }}
82
90
  model={props.symbol?.model}
83
91
  content={contentToUse()}
@@ -304,6 +304,7 @@ function RenderContent(props) {
304
304
  getContent({
305
305
  model: props.model,
306
306
  apiKey: props.apiKey,
307
+ apiVersion: props.apiVersion,
307
308
  }).then((content) => {
308
309
  if (content) {
309
310
  mergeNewContent(content);
@@ -318,21 +319,28 @@ function RenderContent(props) {
318
319
  });
319
320
 
320
321
  function onUpdateFn_0() {
322
+ if (props.content) {
323
+ mergeNewContent(props.content);
324
+ }
325
+ }
326
+ createEffect(on(() => [props.content], onUpdateFn_0));
327
+
328
+ function onUpdateFn_1() {
321
329
  evaluateJsCode();
322
330
  }
323
331
  createEffect(
324
- on(() => [useContent?.data?.jsCode, contentState()], onUpdateFn_0)
332
+ on(() => [useContent?.data?.jsCode, contentState()], onUpdateFn_1)
325
333
  );
326
334
 
327
- function onUpdateFn_1() {
335
+ function onUpdateFn_2() {
328
336
  runHttpRequests();
329
337
  }
330
- createEffect(on(() => [useContent?.data?.httpRequests], onUpdateFn_1));
338
+ createEffect(on(() => [useContent?.data?.httpRequests], onUpdateFn_2));
331
339
 
332
- function onUpdateFn_2() {
340
+ function onUpdateFn_3() {
333
341
  emitStateUpdate();
334
342
  }
335
- createEffect(on(() => [contentState()], onUpdateFn_2));
343
+ createEffect(on(() => [contentState()], onUpdateFn_3));
336
344
 
337
345
  return (
338
346
  <builderContext.Provider
@@ -342,6 +350,7 @@ function RenderContent(props) {
342
350
  setState: setContextState,
343
351
  context: props.context || {},
344
352
  apiKey: props.apiKey,
353
+ apiVersion: props.apiVersion,
345
354
  registeredComponents: allRegisteredComponents(),
346
355
  }}
347
356
  >
@@ -6,6 +6,7 @@ var stdin_default = createContext({
6
6
  setState() {
7
7
  },
8
8
  apiKey: null,
9
+ apiVersion: void 0,
9
10
  registeredComponents: {},
10
11
  inheritedStyles: {}
11
12
  });
@@ -28,12 +28,16 @@ const generateContentUrl = (options) => {
28
28
  model,
29
29
  apiKey,
30
30
  includeRefs = true,
31
- locale
31
+ locale,
32
+ apiVersion = "v2"
32
33
  } = options;
33
34
  if (!apiKey) {
34
35
  throw new Error("Missing API key");
35
36
  }
36
- const url = new URL(`https://cdn.builder.io/api/v2/content/${model}?apiKey=${apiKey}&limit=${limit}&noTraverse=${noTraverse}&includeRefs=${includeRefs}${locale ? `&locale=${locale}` : ""}`);
37
+ if (!["v2", "v3"].includes(apiVersion)) {
38
+ throw new Error(`Invalid apiVersion: expected 'v2' or 'v3', received '${apiVersion}'`);
39
+ }
40
+ const url = new URL(`https://cdn.builder.io/api/${apiVersion}/content/${model}?apiKey=${apiKey}&limit=${limit}&noTraverse=${noTraverse}&includeRefs=${includeRefs}${locale ? `&locale=${locale}` : ""}`);
37
41
  const queryOptions = __spreadValues(__spreadValues({}, getBuilderSearchParamsFromWindow()), normalizeSearchParams(options.options || {}));
38
42
  const flattened = flatten(queryOptions);
39
43
  for (const key in flattened) {
@@ -28,4 +28,46 @@ describe("Generate Content URL", () => {
28
28
  });
29
29
  expect(output).toMatchSnapshot();
30
30
  });
31
+ test("generate content url with apiVersion as v2", () => {
32
+ const output = generateContentUrl({
33
+ apiKey: testKey,
34
+ model: testModel,
35
+ query: { id: testId },
36
+ options,
37
+ apiVersion: "v2"
38
+ });
39
+ expect(output).toMatchSnapshot();
40
+ });
41
+ test("generate content url with apiVersion as v3", () => {
42
+ const output = generateContentUrl({
43
+ apiKey: testKey,
44
+ model: testModel,
45
+ query: { id: testId },
46
+ options,
47
+ apiVersion: "v3"
48
+ });
49
+ expect(output).toMatchSnapshot();
50
+ });
51
+ test("throw error when trying to generate content url with apiVersion as v1", () => {
52
+ expect(() => {
53
+ generateContentUrl({
54
+ apiKey: testKey,
55
+ model: testModel,
56
+ query: { id: testId },
57
+ options,
58
+ apiVersion: "v1"
59
+ });
60
+ }).toThrow(`Invalid apiVersion: expected 'v2' or 'v3', received 'v1'`);
61
+ });
62
+ test("throw error when trying to generate content url with an invalid apiVersion value", () => {
63
+ expect(() => {
64
+ generateContentUrl({
65
+ apiKey: testKey,
66
+ model: testModel,
67
+ query: { id: testId },
68
+ options,
69
+ apiVersion: "INVALID_API_VERSION"
70
+ });
71
+ }).toThrow(`Invalid apiVersion: expected 'v2' or 'v3', received 'INVALID_API_VERSION'`);
72
+ });
31
73
  });
File without changes