@builder.io/sdk-react 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/dist/react/blocks/columns/columns.js +68 -73
- package/dist/react/blocks/symbol/symbol.js +40 -35
- package/dist/react/components/render-content/render-content.js +7 -0
- package/dist/react/context/builder.context.js +1 -0
- package/dist/react/functions/get-content/generate-content-url.js +5 -2
- package/dist/react/functions/get-content/generate-content-url.test.js +42 -0
- package/dist/react/types/api-version.js +1 -0
- package/dist/rsc/blocks/columns/columns.js +68 -75
- package/dist/rsc/blocks/symbol/symbol.js +46 -19
- package/dist/rsc/components/render-content/render-content.js +1 -0
- package/dist/rsc/context/builder.context.js +1 -0
- package/dist/rsc/functions/get-content/generate-content-url.js +5 -2
- package/dist/rsc/functions/get-content/generate-content-url.test.js +42 -0
- package/dist/rsc/types/api-version.js +1 -0
- package/package.json +1 -1
- package/packages/react/src/blocks/columns/columns.jsx +81 -79
- package/packages/react/src/blocks/symbol/symbol.jsx +36 -28
- package/packages/react/src/components/render-content/render-content.jsx +7 -0
- package/packages/react/src/context/builder.context.js +1 -0
- package/packages/react/src/functions/get-content/generate-content-url.js +6 -2
- package/packages/react/src/functions/get-content/generate-content-url.test.js +42 -0
- package/packages/react/src/types/api-version.js +0 -0
- package/packages/rsc/src/blocks/columns/columns.jsx +73 -78
- package/packages/rsc/src/blocks/symbol/symbol.jsx +51 -18
- package/packages/rsc/src/components/render-content/render-content.jsx +1 -0
- package/packages/rsc/src/context/builder.context.js +1 -0
- package/packages/rsc/src/functions/get-content/generate-content-url.js +6 -2
- package/packages/rsc/src/functions/get-content/generate-content-url.test.js +42 -0
- package/packages/rsc/src/types/api-version.js +0 -0
|
@@ -6,33 +6,60 @@ import { TARGET } from "../../constants/target";
|
|
|
6
6
|
function Symbol(props) {
|
|
7
7
|
const _context = { ...props["_context"] };
|
|
8
8
|
const state = {
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
9
|
+
className: [
|
|
10
|
+
...(TARGET === "vue2" || TARGET === "vue3"
|
|
11
|
+
? Object.keys(props.attributes.class)
|
|
12
|
+
: [props.attributes.class]),
|
|
13
|
+
"builder-symbol",
|
|
14
|
+
props.symbol?.inline ? "builder-inline-symbol" : undefined,
|
|
15
|
+
props.symbol?.dynamic || props.dynamic
|
|
16
|
+
? "builder-dynamic-symbol"
|
|
17
|
+
: undefined,
|
|
18
|
+
]
|
|
19
|
+
.filter(Boolean)
|
|
20
|
+
.join(" "),
|
|
21
|
+
contentToUse: props.symbol?.content,
|
|
22
|
+
fetchContent() {
|
|
23
|
+
/**
|
|
24
|
+
* If:
|
|
25
|
+
* - we have a symbol prop
|
|
26
|
+
* - yet it does not have any content
|
|
27
|
+
* - and we have not already stored content from before
|
|
28
|
+
* - and it has a model name
|
|
29
|
+
*
|
|
30
|
+
* then we want to re-fetch the symbol content.
|
|
31
|
+
*/
|
|
32
|
+
if (!state.contentToUse &&
|
|
33
|
+
props.symbol?.model &&
|
|
34
|
+
// This is a hack, we should not need to check for this, but it is needed for Svelte.
|
|
35
|
+
builderContext?.apiKey) {
|
|
36
|
+
getContent({
|
|
37
|
+
model: props.symbol.model,
|
|
38
|
+
apiKey: builderContext.apiKey,
|
|
39
|
+
apiVersion: builderContext.apiVersion,
|
|
40
|
+
query: {
|
|
41
|
+
id: props.symbol.entry,
|
|
42
|
+
},
|
|
43
|
+
})
|
|
44
|
+
.then((response) => {
|
|
45
|
+
if (response) {
|
|
46
|
+
state.contentToUse = response;
|
|
47
|
+
}
|
|
48
|
+
})
|
|
49
|
+
.catch((err) => {
|
|
50
|
+
console.error("[Builder.io]: Could not fetch symbol content: ", err);
|
|
51
|
+
});
|
|
52
|
+
}
|
|
26
53
|
},
|
|
27
54
|
};
|
|
28
55
|
const builderContext = _context["BuilderContext"];
|
|
29
56
|
return (React.createElement("div", { ...props.attributes, dataSet: {
|
|
30
57
|
class: state.className,
|
|
31
58
|
}, className: state.className },
|
|
32
|
-
React.createElement(RenderContent, { apiKey: builderContext.apiKey, context: builderContext.context, customComponents: Object.values(builderContext.registeredComponents), data: {
|
|
59
|
+
React.createElement(RenderContent, { apiVersion: builderContext.apiVersion, apiKey: builderContext.apiKey, context: builderContext.context, customComponents: Object.values(builderContext.registeredComponents), data: {
|
|
33
60
|
...props.symbol?.data,
|
|
34
61
|
...builderContext.state,
|
|
35
|
-
...
|
|
62
|
+
...state.contentToUse?.data?.state,
|
|
36
63
|
}, model: props.symbol?.model, content: state.contentToUse, _context: _context })));
|
|
37
64
|
}
|
|
38
65
|
export default Symbol;
|
|
@@ -192,6 +192,7 @@ function RenderContent(props) {
|
|
|
192
192
|
setState: state.setContextState,
|
|
193
193
|
context: props.context || {},
|
|
194
194
|
apiKey: props.apiKey,
|
|
195
|
+
apiVersion: props.apiVersion,
|
|
195
196
|
registeredComponents: state.allRegisteredComponents,
|
|
196
197
|
};
|
|
197
198
|
return (React.createElement(React.Fragment, null, state.useContent ? (React.createElement(React.Fragment, null,
|
|
@@ -17,11 +17,14 @@ var __spreadValues = (a, b) => {
|
|
|
17
17
|
import { flatten } from "../../helpers/flatten.js";
|
|
18
18
|
import { getBuilderSearchParamsFromWindow, normalizeSearchParams } from "../get-builder-search-params/index.js";
|
|
19
19
|
const generateContentUrl = (options) => {
|
|
20
|
-
const { limit = 30, userAttributes, query, noTraverse = false, model, apiKey, includeRefs = true, locale } = options;
|
|
20
|
+
const { limit = 30, userAttributes, query, noTraverse = false, model, apiKey, includeRefs = true, locale, apiVersion = "v2" } = options;
|
|
21
21
|
if (!apiKey) {
|
|
22
22
|
throw new Error("Missing API key");
|
|
23
23
|
}
|
|
24
|
-
|
|
24
|
+
if (!["v2", "v3"].includes(apiVersion)) {
|
|
25
|
+
throw new Error(`Invalid apiVersion: expected 'v2' or 'v3', received '${apiVersion}'`);
|
|
26
|
+
}
|
|
27
|
+
const url = new URL(`https://cdn.builder.io/api/${apiVersion}/content/${model}?apiKey=${apiKey}&limit=${limit}&noTraverse=${noTraverse}&includeRefs=${includeRefs}${locale ? `&locale=${locale}` : ""}`);
|
|
25
28
|
const queryOptions = __spreadValues(__spreadValues({}, getBuilderSearchParamsFromWindow()), normalizeSearchParams(options.options || {}));
|
|
26
29
|
const flattened = flatten(queryOptions);
|
|
27
30
|
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
|
});
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
"use strict";
|
package/package.json
CHANGED
|
@@ -1,59 +1,92 @@
|
|
|
1
1
|
import * as React from "react";
|
|
2
|
-
import { useContext } from "react";
|
|
2
|
+
import { useState, useContext } from "react";
|
|
3
3
|
import RenderBlocks from "../../components/render-blocks";
|
|
4
4
|
import { getSizesForBreakpoints } from "../../constants/device-sizes";
|
|
5
5
|
import RenderInlinedStyles from "../../components/render-inlined-styles";
|
|
6
6
|
import { TARGET } from "../../constants/target.js";
|
|
7
|
-
import { convertStyleMapToCSS } from "../../helpers/css";
|
|
8
7
|
import BuilderContext from "../../context/builder.context.js";
|
|
9
8
|
|
|
10
9
|
function Columns(props) {
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
10
|
+
const [gutterSize, setGutterSize] = useState(() =>
|
|
11
|
+
typeof props.space === "number" ? props.space || 0 : 20
|
|
12
|
+
);
|
|
14
13
|
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
14
|
+
const [cols, setCols] = useState(() => props.columns || []);
|
|
15
|
+
|
|
16
|
+
const [stackAt, setStackAt] = useState(
|
|
17
|
+
() => props.stackColumnsAt || "tablet"
|
|
18
|
+
);
|
|
18
19
|
|
|
19
20
|
function getWidth(index) {
|
|
20
|
-
|
|
21
|
-
return columns[index]?.width || 100 / columns.length;
|
|
21
|
+
return cols[index]?.width || 100 / cols.length;
|
|
22
22
|
}
|
|
23
23
|
|
|
24
24
|
function getColumnCssWidth(index) {
|
|
25
|
-
const
|
|
26
|
-
const gutterSize = getGutterSize();
|
|
27
|
-
const subtractWidth = (gutterSize * (columns.length - 1)) / columns.length;
|
|
25
|
+
const subtractWidth = (gutterSize * (cols.length - 1)) / cols.length;
|
|
28
26
|
return `calc(${getWidth(index)}% - ${subtractWidth}px)`;
|
|
29
27
|
}
|
|
30
28
|
|
|
31
|
-
function
|
|
32
|
-
|
|
33
|
-
return _stackColumnsAt === "tablet" ? prop : "inherit";
|
|
29
|
+
function getTabletStyle({ stackedStyle, desktopStyle }) {
|
|
30
|
+
return stackAt === "tablet" ? stackedStyle : desktopStyle;
|
|
34
31
|
}
|
|
35
32
|
|
|
33
|
+
function getMobileStyle({ stackedStyle, desktopStyle }) {
|
|
34
|
+
return stackAt === "never" ? desktopStyle : stackedStyle;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
const [flexDir, setFlexDir] = useState(() =>
|
|
38
|
+
props.stackColumnsAt === "never"
|
|
39
|
+
? "row"
|
|
40
|
+
: props.reverseColumnsWhenStacked
|
|
41
|
+
? "column-reverse"
|
|
42
|
+
: "column"
|
|
43
|
+
);
|
|
44
|
+
|
|
36
45
|
function columnsCssVars() {
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
: "column";
|
|
46
|
+
if (TARGET === "reactNative") {
|
|
47
|
+
return {
|
|
48
|
+
flexDirection: flexDir,
|
|
49
|
+
};
|
|
50
|
+
}
|
|
43
51
|
return {
|
|
44
52
|
"--flex-dir": flexDir,
|
|
45
|
-
"--flex-dir-tablet":
|
|
53
|
+
"--flex-dir-tablet": getTabletStyle({
|
|
54
|
+
stackedStyle: flexDir,
|
|
55
|
+
desktopStyle: "row",
|
|
56
|
+
}),
|
|
46
57
|
};
|
|
47
58
|
}
|
|
48
59
|
|
|
49
|
-
function columnCssVars() {
|
|
50
|
-
const width =
|
|
51
|
-
const
|
|
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";
|
|
52
71
|
return {
|
|
53
|
-
|
|
54
|
-
"
|
|
55
|
-
"--column-width-
|
|
56
|
-
|
|
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
|
+
}),
|
|
57
90
|
};
|
|
58
91
|
}
|
|
59
92
|
|
|
@@ -64,63 +97,34 @@ function Columns(props) {
|
|
|
64
97
|
return breakpointSizes[size].max;
|
|
65
98
|
}
|
|
66
99
|
|
|
67
|
-
function columnStyleObjects() {
|
|
68
|
-
return {
|
|
69
|
-
columns: {
|
|
70
|
-
small: {
|
|
71
|
-
flexDirection: "var(--flex-dir)",
|
|
72
|
-
alignItems: "stretch",
|
|
73
|
-
},
|
|
74
|
-
medium: {
|
|
75
|
-
flexDirection: "var(--flex-dir-tablet)",
|
|
76
|
-
alignItems: "stretch",
|
|
77
|
-
},
|
|
78
|
-
},
|
|
79
|
-
column: {
|
|
80
|
-
small: {
|
|
81
|
-
width: "var(--column-width) !important",
|
|
82
|
-
marginLeft: "var(--column-margin-left) !important",
|
|
83
|
-
},
|
|
84
|
-
medium: {
|
|
85
|
-
width: "var(--column-width-tablet) !important",
|
|
86
|
-
marginLeft: "var(--column-margin-left-tablet) !important",
|
|
87
|
-
},
|
|
88
|
-
},
|
|
89
|
-
};
|
|
90
|
-
}
|
|
91
|
-
|
|
92
100
|
function columnsStyles() {
|
|
93
101
|
return `
|
|
94
102
|
@media (max-width: ${getWidthForBreakpointSize("medium")}px) {
|
|
95
103
|
.${props.builderBlock.id}-breakpoints {
|
|
96
|
-
|
|
104
|
+
flex-direction: var(--flex-dir-tablet);
|
|
105
|
+
align-items: stretch;
|
|
97
106
|
}
|
|
98
107
|
|
|
99
108
|
.${props.builderBlock.id}-breakpoints > .builder-column {
|
|
100
|
-
|
|
109
|
+
width: var(--column-width-tablet) !important;
|
|
110
|
+
margin-left: var(--column-margin-left-tablet) !important;
|
|
101
111
|
}
|
|
102
112
|
}
|
|
103
113
|
|
|
104
114
|
@media (max-width: ${getWidthForBreakpointSize("small")}px) {
|
|
105
115
|
.${props.builderBlock.id}-breakpoints {
|
|
106
|
-
|
|
116
|
+
flex-direction: var(--flex-dir);
|
|
117
|
+
align-items: stretch;
|
|
107
118
|
}
|
|
108
119
|
|
|
109
120
|
.${props.builderBlock.id}-breakpoints > .builder-column {
|
|
110
|
-
|
|
121
|
+
width: var(--column-width-mobile) !important;
|
|
122
|
+
margin-left: var(--column-margin-left-mobile) !important;
|
|
111
123
|
}
|
|
112
124
|
},
|
|
113
125
|
`;
|
|
114
126
|
}
|
|
115
127
|
|
|
116
|
-
function reactNativeColumnsStyles() {
|
|
117
|
-
return columnStyleObjects.columns.small;
|
|
118
|
-
}
|
|
119
|
-
|
|
120
|
-
function reactNativeColumnStyles() {
|
|
121
|
-
return columnStyleObjects.column.small;
|
|
122
|
-
}
|
|
123
|
-
|
|
124
128
|
const builderContext = useContext(BuilderContext);
|
|
125
129
|
|
|
126
130
|
return (
|
|
@@ -128,11 +132,11 @@ function Columns(props) {
|
|
|
128
132
|
<div
|
|
129
133
|
className={
|
|
130
134
|
`builder-columns ${props.builderBlock.id}-breakpoints` +
|
|
131
|
-
" div-
|
|
135
|
+
" div-568386c4"
|
|
132
136
|
}
|
|
133
|
-
style={
|
|
134
|
-
|
|
135
|
-
|
|
137
|
+
style={columnsCssVars()}
|
|
138
|
+
dataSet={{
|
|
139
|
+
"builder-block-name": "builder-columns",
|
|
136
140
|
}}
|
|
137
141
|
>
|
|
138
142
|
{TARGET !== "reactNative" ? (
|
|
@@ -143,12 +147,10 @@ function Columns(props) {
|
|
|
143
147
|
|
|
144
148
|
{props.columns?.map((column, index) => (
|
|
145
149
|
<div
|
|
146
|
-
className="builder-column div-
|
|
147
|
-
style={
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
...(TARGET === "reactNative" ? reactNativeColumnStyles() : {}),
|
|
151
|
-
...columnCssVars(),
|
|
150
|
+
className="builder-column div-568386c4-2"
|
|
151
|
+
style={columnCssVars(index)}
|
|
152
|
+
dataSet={{
|
|
153
|
+
"builder-block-name": "builder-column",
|
|
152
154
|
}}
|
|
153
155
|
key={index}
|
|
154
156
|
>
|
|
@@ -163,10 +165,10 @@ function Columns(props) {
|
|
|
163
165
|
</div>
|
|
164
166
|
))}
|
|
165
167
|
</div>
|
|
166
|
-
<style>{`.div-
|
|
168
|
+
<style>{`.div-568386c4 {
|
|
167
169
|
display: flex;
|
|
168
170
|
line-height: normal;
|
|
169
|
-
}.div-
|
|
171
|
+
}.div-568386c4-2 {
|
|
170
172
|
display: flex;
|
|
171
173
|
flex-direction: column;
|
|
172
174
|
align-items: stretch;
|
|
@@ -6,8 +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
|
-
|
|
10
|
-
|
|
9
|
+
const [className, setClassName] = useState(() =>
|
|
10
|
+
[
|
|
11
11
|
...(TARGET === "vue2" || TARGET === "vue3"
|
|
12
12
|
? Object.keys(props.attributes.class)
|
|
13
13
|
: [props.attributes.class]),
|
|
@@ -18,20 +18,12 @@ function Symbol(props) {
|
|
|
18
18
|
: undefined,
|
|
19
19
|
]
|
|
20
20
|
.filter(Boolean)
|
|
21
|
-
.join(" ")
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
const [fetchedContent, setFetchedContent] = useState(() => null);
|
|
25
|
-
|
|
26
|
-
function contentToUse() {
|
|
27
|
-
return props.symbol?.content || fetchedContent;
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
const builderContext = useContext(BuilderContext);
|
|
21
|
+
.join(" ")
|
|
22
|
+
);
|
|
31
23
|
|
|
32
|
-
|
|
33
|
-
const symbolToUse = props.symbol;
|
|
24
|
+
const [contentToUse, setContentToUse] = useState(() => props.symbol?.content);
|
|
34
25
|
|
|
26
|
+
function fetchContent() {
|
|
35
27
|
/**
|
|
36
28
|
* If:
|
|
37
29
|
* - we have a symbol prop
|
|
@@ -42,44 +34,60 @@ function Symbol(props) {
|
|
|
42
34
|
* then we want to re-fetch the symbol content.
|
|
43
35
|
*/
|
|
44
36
|
if (
|
|
45
|
-
|
|
46
|
-
|
|
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:
|
|
43
|
+
model: props.symbol.model,
|
|
54
44
|
apiKey: builderContext.apiKey,
|
|
45
|
+
apiVersion: builderContext.apiVersion,
|
|
55
46
|
query: {
|
|
56
|
-
id:
|
|
47
|
+
id: props.symbol.entry,
|
|
57
48
|
},
|
|
58
|
-
})
|
|
59
|
-
|
|
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
|
+
}
|
|
60
|
+
|
|
61
|
+
const builderContext = useContext(BuilderContext);
|
|
62
|
+
|
|
63
|
+
useEffect(() => {
|
|
64
|
+
fetchContent();
|
|
65
|
+
}, []);
|
|
66
|
+
|
|
67
|
+
useEffect(() => {
|
|
68
|
+
fetchContent();
|
|
69
|
+
}, [props.symbol]);
|
|
63
70
|
|
|
64
71
|
return (
|
|
65
72
|
<div
|
|
66
73
|
{...props.attributes}
|
|
67
74
|
dataSet={{
|
|
68
|
-
class: className
|
|
75
|
+
class: className,
|
|
69
76
|
}}
|
|
70
|
-
className={className
|
|
77
|
+
className={className}
|
|
71
78
|
>
|
|
72
79
|
<RenderContent
|
|
80
|
+
apiVersion={builderContext.apiVersion}
|
|
73
81
|
apiKey={builderContext.apiKey}
|
|
74
82
|
context={builderContext.context}
|
|
75
83
|
customComponents={Object.values(builderContext.registeredComponents)}
|
|
76
84
|
data={{
|
|
77
85
|
...props.symbol?.data,
|
|
78
86
|
...builderContext.state,
|
|
79
|
-
...
|
|
87
|
+
...contentToUse?.data?.state,
|
|
80
88
|
}}
|
|
81
89
|
model={props.symbol?.model}
|
|
82
|
-
content={contentToUse
|
|
90
|
+
content={contentToUse}
|
|
83
91
|
/>
|
|
84
92
|
</div>
|
|
85
93
|
);
|
|
@@ -300,6 +300,7 @@ function RenderContent(props) {
|
|
|
300
300
|
getContent({
|
|
301
301
|
model: props.model,
|
|
302
302
|
apiKey: props.apiKey,
|
|
303
|
+
apiVersion: props.apiVersion,
|
|
303
304
|
}).then((content) => {
|
|
304
305
|
if (content) {
|
|
305
306
|
mergeNewContent(content);
|
|
@@ -313,6 +314,11 @@ function RenderContent(props) {
|
|
|
313
314
|
}
|
|
314
315
|
}, []);
|
|
315
316
|
|
|
317
|
+
useEffect(() => {
|
|
318
|
+
if (props.content) {
|
|
319
|
+
mergeNewContent(props.content);
|
|
320
|
+
}
|
|
321
|
+
}, [props.content]);
|
|
316
322
|
useEffect(() => {
|
|
317
323
|
evaluateJsCode();
|
|
318
324
|
}, [useContent?.data?.jsCode, contentState]);
|
|
@@ -343,6 +349,7 @@ function RenderContent(props) {
|
|
|
343
349
|
setState: setContextState,
|
|
344
350
|
context: props.context || {},
|
|
345
351
|
apiKey: props.apiKey,
|
|
352
|
+
apiVersion: props.apiVersion,
|
|
346
353
|
registeredComponents: allRegisteredComponents,
|
|
347
354
|
}}
|
|
348
355
|
>
|
|
@@ -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
|
-
|
|
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
|