@builder.io/sdk-react-native 0.0.1-60 → 0.0.1-63
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 +1 -1
- package/src/blocks/columns/component-info.js +25 -1
- package/src/blocks/embed/component-info.js +20 -1
- package/src/blocks/embed/embed.js +22 -29
- package/src/blocks/embed/helpers.js +10 -0
- package/src/blocks/image/component-info.js +47 -1
- package/src/blocks/image/image.helpers.js +49 -0
- package/src/blocks/symbol/symbol.js +3 -2
- package/src/components/render-block/render-block.js +17 -19
- package/src/components/render-block/types.js +1 -0
- package/src/components/render-content/render-content.js +13 -15
- package/src/functions/get-block-tag.js +1 -1
- package/src/functions/get-builder-search-params/index.js +12 -1
- package/src/functions/get-content/ab-testing.js +39 -0
- package/src/functions/get-content/index.js +16 -58
- package/src/functions/get-content/types.js +1 -0
- package/src/functions/register-component.js +20 -18
- package/src/helpers/flatten.js +35 -0
- package/src/functions/fast-clone.js +0 -5
- package/src/functions/previewing-model-name.js +0 -12
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@builder.io/sdk-react-native",
|
|
3
3
|
"description": "Builder.io SDK for React Native",
|
|
4
|
-
"version": "0.0.1-
|
|
4
|
+
"version": "0.0.1-63",
|
|
5
5
|
"main": "src/index.js",
|
|
6
6
|
"scripts": {
|
|
7
7
|
"release:dev": "npm version prerelease --no-git-tag-version && npm publish --tag dev --access public"
|
|
@@ -187,7 +187,31 @@ const componentInfo = {
|
|
|
187
187
|
]
|
|
188
188
|
}
|
|
189
189
|
],
|
|
190
|
-
onChange
|
|
190
|
+
onChange(options) {
|
|
191
|
+
function clearWidths() {
|
|
192
|
+
columns.forEach((col) => {
|
|
193
|
+
col.delete("width");
|
|
194
|
+
});
|
|
195
|
+
}
|
|
196
|
+
const columns = options.get("columns");
|
|
197
|
+
if (Array.isArray(columns)) {
|
|
198
|
+
const containsColumnWithWidth = !!columns.find((col) => col.get("width"));
|
|
199
|
+
if (containsColumnWithWidth) {
|
|
200
|
+
const containsColumnWithoutWidth = !!columns.find((col) => !col.get("width"));
|
|
201
|
+
if (containsColumnWithoutWidth) {
|
|
202
|
+
clearWidths();
|
|
203
|
+
} else {
|
|
204
|
+
const sumWidths = columns.reduce((memo, col) => {
|
|
205
|
+
return memo + col.get("width");
|
|
206
|
+
}, 0);
|
|
207
|
+
const widthsDontAddUp = sumWidths !== 100;
|
|
208
|
+
if (widthsDontAddUp) {
|
|
209
|
+
clearWidths();
|
|
210
|
+
}
|
|
211
|
+
}
|
|
212
|
+
}
|
|
213
|
+
}
|
|
214
|
+
}
|
|
191
215
|
},
|
|
192
216
|
{
|
|
193
217
|
name: "space",
|
|
@@ -10,7 +10,26 @@ const componentInfo = {
|
|
|
10
10
|
required: true,
|
|
11
11
|
defaultValue: "",
|
|
12
12
|
helperText: "e.g. enter a youtube url, google map, etc",
|
|
13
|
-
onChange
|
|
13
|
+
onChange(options) {
|
|
14
|
+
const url = options.get("url");
|
|
15
|
+
if (url) {
|
|
16
|
+
options.set("content", "Loading...");
|
|
17
|
+
const apiKey = "ae0e60e78201a3f2b0de4b";
|
|
18
|
+
return fetch(`https://iframe.ly/api/iframely?url=${url}&api_key=${apiKey}`).then((res) => res.json()).then((data) => {
|
|
19
|
+
if (options.get("url") === url) {
|
|
20
|
+
if (data.html) {
|
|
21
|
+
options.set("content", data.html);
|
|
22
|
+
} else {
|
|
23
|
+
options.set("content", "Invalid url, please try another");
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
}).catch((_err) => {
|
|
27
|
+
options.set("content", "There was an error embedding this URL, please try again or another URL");
|
|
28
|
+
});
|
|
29
|
+
} else {
|
|
30
|
+
options.delete("content");
|
|
31
|
+
}
|
|
32
|
+
}
|
|
14
33
|
},
|
|
15
34
|
{
|
|
16
35
|
name: "content",
|
|
@@ -1,45 +1,38 @@
|
|
|
1
1
|
import * as React from "react";
|
|
2
2
|
import { View } from "react-native";
|
|
3
3
|
import { useState, useRef, useEffect } from "react";
|
|
4
|
+
import { isJsScript } from "./helpers";
|
|
4
5
|
function Embed(props) {
|
|
5
6
|
const elem = useRef(null);
|
|
6
7
|
const [scriptsInserted, setScriptsInserted] = useState(() => []);
|
|
7
8
|
const [scriptsRun, setScriptsRun] = useState(() => []);
|
|
9
|
+
const [ranInitFn, setRanInitFn] = useState(() => false);
|
|
8
10
|
function findAndRunScripts() {
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
}
|
|
23
|
-
"
|
|
24
|
-
"application/javascript",
|
|
25
|
-
"application/ecmascript"
|
|
26
|
-
].includes(script.type)) {
|
|
27
|
-
if (scriptsRun.includes(script.innerText)) {
|
|
28
|
-
continue;
|
|
29
|
-
}
|
|
30
|
-
try {
|
|
31
|
-
scriptsRun.push(script.innerText);
|
|
32
|
-
new Function(script.innerText)();
|
|
33
|
-
} catch (error) {
|
|
34
|
-
console.warn("`Embed`: Error running script:", error);
|
|
35
|
-
}
|
|
11
|
+
const scripts = elem.current.getElementsByTagName("script");
|
|
12
|
+
for (let i = 0; i < scripts.length; i++) {
|
|
13
|
+
const script = scripts[i];
|
|
14
|
+
if (script.src && !scriptsInserted.includes(script.src)) {
|
|
15
|
+
scriptsInserted.push(script.src);
|
|
16
|
+
const newScript = document.createElement("script");
|
|
17
|
+
newScript.async = true;
|
|
18
|
+
newScript.src = script.src;
|
|
19
|
+
document.head.appendChild(newScript);
|
|
20
|
+
} else if (isJsScript(script) && !scriptsRun.includes(script.innerText)) {
|
|
21
|
+
try {
|
|
22
|
+
scriptsRun.push(script.innerText);
|
|
23
|
+
new Function(script.innerText)();
|
|
24
|
+
} catch (error) {
|
|
25
|
+
console.warn("`Embed`: Error running script:", error);
|
|
36
26
|
}
|
|
37
27
|
}
|
|
38
28
|
}
|
|
39
29
|
}
|
|
40
30
|
useEffect(() => {
|
|
41
|
-
|
|
42
|
-
|
|
31
|
+
if (elem.current && !ranInitFn) {
|
|
32
|
+
setRanInitFn(true);
|
|
33
|
+
findAndRunScripts();
|
|
34
|
+
}
|
|
35
|
+
}, [elem, ranInitFn]);
|
|
43
36
|
return /* @__PURE__ */ React.createElement(View, {
|
|
44
37
|
ref: elem,
|
|
45
38
|
dangerouslySetInnerHTML: { __html: props.content }
|
|
@@ -19,7 +19,53 @@ const componentInfo = {
|
|
|
19
19
|
allowedFileTypes: ["jpeg", "jpg", "png", "svg"],
|
|
20
20
|
required: true,
|
|
21
21
|
defaultValue: "https://cdn.builder.io/api/v1/image/assets%2Fpwgjf0RoYWbdnJSbpBAjXNRMe9F2%2Ffb27a7c790324294af8be1c35fe30f4d",
|
|
22
|
-
onChange
|
|
22
|
+
onChange(options) {
|
|
23
|
+
const DEFAULT_ASPECT_RATIO = 0.7041;
|
|
24
|
+
options.delete("srcset");
|
|
25
|
+
options.delete("noWebp");
|
|
26
|
+
function loadImage(url, timeout = 6e4) {
|
|
27
|
+
return new Promise((resolve, reject) => {
|
|
28
|
+
const img = document.createElement("img");
|
|
29
|
+
let loaded = false;
|
|
30
|
+
img.onload = () => {
|
|
31
|
+
loaded = true;
|
|
32
|
+
resolve(img);
|
|
33
|
+
};
|
|
34
|
+
img.addEventListener("error", (event) => {
|
|
35
|
+
console.warn("Image load failed", event.error);
|
|
36
|
+
reject(event.error);
|
|
37
|
+
});
|
|
38
|
+
img.src = url;
|
|
39
|
+
setTimeout(() => {
|
|
40
|
+
if (!loaded) {
|
|
41
|
+
reject(new Error("Image load timed out"));
|
|
42
|
+
}
|
|
43
|
+
}, timeout);
|
|
44
|
+
});
|
|
45
|
+
}
|
|
46
|
+
function round(num) {
|
|
47
|
+
return Math.round(num * 1e3) / 1e3;
|
|
48
|
+
}
|
|
49
|
+
const value = options.get("image");
|
|
50
|
+
const aspectRatio = options.get("aspectRatio");
|
|
51
|
+
fetch(value).then((res) => res.blob()).then((blob) => {
|
|
52
|
+
if (blob.type.includes("svg")) {
|
|
53
|
+
options.set("noWebp", true);
|
|
54
|
+
}
|
|
55
|
+
});
|
|
56
|
+
if (value && (!aspectRatio || aspectRatio === DEFAULT_ASPECT_RATIO)) {
|
|
57
|
+
return loadImage(value).then((img) => {
|
|
58
|
+
const possiblyUpdatedAspectRatio = options.get("aspectRatio");
|
|
59
|
+
if (options.get("image") === value && (!possiblyUpdatedAspectRatio || possiblyUpdatedAspectRatio === DEFAULT_ASPECT_RATIO)) {
|
|
60
|
+
if (img.width && img.height) {
|
|
61
|
+
options.set("aspectRatio", round(img.height / img.width));
|
|
62
|
+
options.set("height", img.height);
|
|
63
|
+
options.set("width", img.width);
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
});
|
|
67
|
+
}
|
|
68
|
+
}
|
|
23
69
|
},
|
|
24
70
|
{
|
|
25
71
|
name: "backgroundSize",
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
import * as React from 'react';
|
|
2
|
+
function removeProtocol(path) {
|
|
3
|
+
return path.replace(/http(s)?:/, "");
|
|
4
|
+
}
|
|
5
|
+
function updateQueryParam(uri = "", key, value) {
|
|
6
|
+
const re = new RegExp("([?&])" + key + "=.*?(&|$)", "i");
|
|
7
|
+
const separator = uri.indexOf("?") !== -1 ? "&" : "?";
|
|
8
|
+
if (uri.match(re)) {
|
|
9
|
+
return uri.replace(re, "$1" + key + "=" + encodeURIComponent(value) + "$2");
|
|
10
|
+
}
|
|
11
|
+
return uri + separator + key + "=" + encodeURIComponent(value);
|
|
12
|
+
}
|
|
13
|
+
function getShopifyImageUrl(src, size) {
|
|
14
|
+
if (!src || !(src == null ? void 0 : src.match(/cdn\.shopify\.com/)) || !size) {
|
|
15
|
+
return src;
|
|
16
|
+
}
|
|
17
|
+
if (size === "master") {
|
|
18
|
+
return removeProtocol(src);
|
|
19
|
+
}
|
|
20
|
+
const match = src.match(/(_\d+x(\d+)?)?(\.(jpg|jpeg|gif|png|bmp|bitmap|tiff|tif)(\?v=\d+)?)/i);
|
|
21
|
+
if (match) {
|
|
22
|
+
const prefix = src.split(match[0]);
|
|
23
|
+
const suffix = match[3];
|
|
24
|
+
const useSize = size.match("x") ? size : `${size}x`;
|
|
25
|
+
return removeProtocol(`${prefix[0]}_${useSize}${suffix}`);
|
|
26
|
+
}
|
|
27
|
+
return null;
|
|
28
|
+
}
|
|
29
|
+
function getSrcSet(url) {
|
|
30
|
+
if (!url) {
|
|
31
|
+
return url;
|
|
32
|
+
}
|
|
33
|
+
const sizes = [100, 200, 400, 800, 1200, 1600, 2e3];
|
|
34
|
+
if (url.match(/builder\.io/)) {
|
|
35
|
+
let srcUrl = url;
|
|
36
|
+
const widthInSrc = Number(url.split("?width=")[1]);
|
|
37
|
+
if (!isNaN(widthInSrc)) {
|
|
38
|
+
srcUrl = `${srcUrl} ${widthInSrc}w`;
|
|
39
|
+
}
|
|
40
|
+
return sizes.filter((size) => size !== widthInSrc).map((size) => `${updateQueryParam(url, "width", size)} ${size}w`).concat([srcUrl]).join(", ");
|
|
41
|
+
}
|
|
42
|
+
if (url.match(/cdn\.shopify\.com/)) {
|
|
43
|
+
return sizes.map((size) => [getShopifyImageUrl(url, `${size}x${size}`), size]).filter(([sizeUrl]) => !!sizeUrl).map(([sizeUrl, size]) => `${sizeUrl} ${size}w`).concat([url]).join(", ");
|
|
44
|
+
}
|
|
45
|
+
return url;
|
|
46
|
+
}
|
|
47
|
+
export {
|
|
48
|
+
getSrcSet
|
|
49
|
+
};
|
|
@@ -38,8 +38,8 @@ function Symbol(props) {
|
|
|
38
38
|
getContent({
|
|
39
39
|
model: symbolToUse.model,
|
|
40
40
|
apiKey: builderContext.apiKey,
|
|
41
|
-
|
|
42
|
-
|
|
41
|
+
query: {
|
|
42
|
+
id: symbolToUse.entry
|
|
43
43
|
}
|
|
44
44
|
}).then((response) => {
|
|
45
45
|
setContent(response);
|
|
@@ -58,6 +58,7 @@ function Symbol(props) {
|
|
|
58
58
|
}), /* @__PURE__ */ React.createElement(RenderContent, {
|
|
59
59
|
apiKey: builderContext.apiKey,
|
|
60
60
|
context: builderContext.context,
|
|
61
|
+
customComponents: Object.values(builderContext.registeredComponents),
|
|
61
62
|
data: __spreadValues(__spreadValues(__spreadValues({}, (_d = props.symbol) == null ? void 0 : _d.data), builderContext.state), (_g = (_f = (_e = props.symbol) == null ? void 0 : _e.content) == null ? void 0 : _f.data) == null ? void 0 : _g.state),
|
|
62
63
|
model: (_h = props.symbol) == null ? void 0 : _h.model,
|
|
63
64
|
content
|
|
@@ -127,30 +127,28 @@ function RenderBlock(props) {
|
|
|
127
127
|
if (!(repeat == null ? void 0 : repeat.collection)) {
|
|
128
128
|
return void 0;
|
|
129
129
|
}
|
|
130
|
-
const { collection, itemName } = repeat;
|
|
131
130
|
const itemsArray = evaluate({
|
|
132
|
-
code: collection,
|
|
131
|
+
code: repeat.collection,
|
|
133
132
|
state: builderContext.state,
|
|
134
133
|
context: builderContext.context
|
|
135
134
|
});
|
|
136
|
-
if (Array.isArray(itemsArray)) {
|
|
137
|
-
const collectionName = collection.split(".").pop();
|
|
138
|
-
const itemNameToUse = itemName || (collectionName ? collectionName + "Item" : "item");
|
|
139
|
-
const repeatArray = itemsArray.map((item, index) => ({
|
|
140
|
-
context: __spreadProps(__spreadValues({}, builderContext), {
|
|
141
|
-
state: __spreadProps(__spreadValues({}, builderContext.state), {
|
|
142
|
-
$index: index,
|
|
143
|
-
$item: item,
|
|
144
|
-
[itemNameToUse]: item,
|
|
145
|
-
[`$${itemNameToUse}Index`]: index
|
|
146
|
-
})
|
|
147
|
-
}),
|
|
148
|
-
block: blockWithoutRepeat
|
|
149
|
-
}));
|
|
150
|
-
return repeatArray;
|
|
151
|
-
} else {
|
|
135
|
+
if (!Array.isArray(itemsArray)) {
|
|
152
136
|
return void 0;
|
|
153
137
|
}
|
|
138
|
+
const collectionName = repeat.collection.split(".").pop();
|
|
139
|
+
const itemNameToUse = repeat.itemName || (collectionName ? collectionName + "Item" : "item");
|
|
140
|
+
const repeatArray = itemsArray.map((item, index) => ({
|
|
141
|
+
context: __spreadProps(__spreadValues({}, builderContext), {
|
|
142
|
+
state: __spreadProps(__spreadValues({}, builderContext.state), {
|
|
143
|
+
$index: index,
|
|
144
|
+
$item: item,
|
|
145
|
+
[itemNameToUse]: item,
|
|
146
|
+
[`$${itemNameToUse}Index`]: index
|
|
147
|
+
})
|
|
148
|
+
}),
|
|
149
|
+
block: blockWithoutRepeat
|
|
150
|
+
}));
|
|
151
|
+
return repeatArray;
|
|
154
152
|
}
|
|
155
153
|
const builderContext = useContext(BuilderContext);
|
|
156
154
|
const TagNameRef = tagName();
|
|
@@ -158,7 +156,7 @@ function RenderBlock(props) {
|
|
|
158
156
|
key: index,
|
|
159
157
|
repeatContext: data.context,
|
|
160
158
|
block: data.block
|
|
161
|
-
}))) : /* @__PURE__ */ React.createElement(RenderComponent, __spreadValues({}, renderComponentProps())), (_b = childrenWithoutParentComponent()) == null ? void 0 : _b.map((child) => /* @__PURE__ */ React.createElement(RenderBlock, {
|
|
159
|
+
}))) : null, !repeatItemData() ? /* @__PURE__ */ React.createElement(React.Fragment, null, /* @__PURE__ */ React.createElement(RenderComponent, __spreadValues({}, renderComponentProps()))) : null, (_b = childrenWithoutParentComponent()) == null ? void 0 : _b.map((child) => /* @__PURE__ */ React.createElement(RenderBlock, {
|
|
162
160
|
key: "render-block-" + child.id,
|
|
163
161
|
block: child
|
|
164
162
|
})), (_c = childrenWithoutParentComponent()) == null ? void 0 : _c.map((child) => /* @__PURE__ */ React.createElement(BlockStyles, {
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import * as React from 'react';
|
|
@@ -44,16 +44,11 @@ import { getDefaultRegisteredComponents } from "../../constants/builder-register
|
|
|
44
44
|
import { TARGET } from "../../constants/target.js";
|
|
45
45
|
import BuilderContext from "../../context/builder.context";
|
|
46
46
|
import { evaluate } from "../../functions/evaluate.js";
|
|
47
|
-
import {
|
|
48
|
-
convertSearchParamsToQueryObject,
|
|
49
|
-
getBuilderSearchParams
|
|
50
|
-
} from "../../functions/get-builder-search-params/index.js";
|
|
51
47
|
import { getContent } from "../../functions/get-content/index.js";
|
|
52
48
|
import { getFetch } from "../../functions/get-fetch.js";
|
|
53
49
|
import { isBrowser } from "../../functions/is-browser.js";
|
|
54
50
|
import { isEditing } from "../../functions/is-editing.js";
|
|
55
51
|
import { isPreviewing } from "../../functions/is-previewing.js";
|
|
56
|
-
import { previewingModelName } from "../../functions/previewing-model-name.js";
|
|
57
52
|
import {
|
|
58
53
|
components,
|
|
59
54
|
createRegisterComponentMessage
|
|
@@ -62,7 +57,7 @@ import { track } from "../../functions/track.js";
|
|
|
62
57
|
import RenderBlocks from "../render-blocks.js";
|
|
63
58
|
import RenderContentStyles from "./components/render-styles.js";
|
|
64
59
|
function RenderContent(props) {
|
|
65
|
-
var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k
|
|
60
|
+
var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k;
|
|
66
61
|
function useContent() {
|
|
67
62
|
var _a2;
|
|
68
63
|
const mergedContent = __spreadProps(__spreadValues(__spreadValues({}, props.content), overrideContent), {
|
|
@@ -164,6 +159,10 @@ function RenderContent(props) {
|
|
|
164
159
|
}));
|
|
165
160
|
}
|
|
166
161
|
}
|
|
162
|
+
function shouldRenderContentStyles() {
|
|
163
|
+
var _a2, _b2, _c2, _d2, _e2;
|
|
164
|
+
return Boolean((((_b2 = (_a2 = useContent == null ? void 0 : useContent()) == null ? void 0 : _a2.data) == null ? void 0 : _b2.cssCode) || ((_e2 = (_d2 = (_c2 = useContent == null ? void 0 : useContent()) == null ? void 0 : _c2.data) == null ? void 0 : _d2.customFonts) == null ? void 0 : _e2.length)) && TARGET !== "reactNative");
|
|
165
|
+
}
|
|
167
166
|
useEffect(() => {
|
|
168
167
|
if (isBrowser()) {
|
|
169
168
|
if (isEditing()) {
|
|
@@ -181,14 +180,13 @@ function RenderContent(props) {
|
|
|
181
180
|
});
|
|
182
181
|
}
|
|
183
182
|
if (isPreviewing()) {
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
const previewApiKey =
|
|
183
|
+
const searchParams = new URL(location.href).searchParams;
|
|
184
|
+
if (props.model && searchParams.get("builder.preview") === props.model) {
|
|
185
|
+
const previewApiKey = searchParams.get("apiKey") || searchParams.get("builder.space");
|
|
187
186
|
if (previewApiKey) {
|
|
188
187
|
getContent({
|
|
189
188
|
model: props.model,
|
|
190
|
-
apiKey: previewApiKey
|
|
191
|
-
options: getBuilderSearchParams(convertSearchParamsToQueryObject(currentUrl.searchParams))
|
|
189
|
+
apiKey: previewApiKey
|
|
192
190
|
}).then((content) => {
|
|
193
191
|
if (content) {
|
|
194
192
|
setOverrideContent(content);
|
|
@@ -242,11 +240,11 @@ function RenderContent(props) {
|
|
|
242
240
|
contentId: useContent().id
|
|
243
241
|
}),
|
|
244
242
|
"data-builder-content-id": (_e = useContent == null ? void 0 : useContent()) == null ? void 0 : _e.id
|
|
245
|
-
}, (
|
|
246
|
-
cssCode: useContent().data.cssCode,
|
|
247
|
-
customFonts: useContent().data.customFonts
|
|
243
|
+
}, shouldRenderContentStyles() ? /* @__PURE__ */ React.createElement(RenderContentStyles, {
|
|
244
|
+
cssCode: (_g = (_f = useContent == null ? void 0 : useContent()) == null ? void 0 : _f.data) == null ? void 0 : _g.cssCode,
|
|
245
|
+
customFonts: (_i = (_h = useContent == null ? void 0 : useContent()) == null ? void 0 : _h.data) == null ? void 0 : _i.customFonts
|
|
248
246
|
}) : null, /* @__PURE__ */ React.createElement(RenderBlocks, {
|
|
249
|
-
blocks: (
|
|
247
|
+
blocks: (_k = (_j = useContent == null ? void 0 : useContent()) == null ? void 0 : _j.data) == null ? void 0 : _k.blocks
|
|
250
248
|
}))) : null);
|
|
251
249
|
}
|
|
252
250
|
export {
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import * as React from 'react';
|
|
2
|
+
import { isBrowser } from "../is-browser";
|
|
2
3
|
const BUILDER_SEARCHPARAMS_PREFIX = "builder.";
|
|
3
4
|
const convertSearchParamsToQueryObject = (searchParams) => {
|
|
4
5
|
const options = {};
|
|
@@ -17,7 +18,17 @@ const getBuilderSearchParams = (options) => {
|
|
|
17
18
|
});
|
|
18
19
|
return newOptions;
|
|
19
20
|
};
|
|
21
|
+
const getBuilderSearchParamsFromWindow = () => {
|
|
22
|
+
if (!isBrowser()) {
|
|
23
|
+
return {};
|
|
24
|
+
}
|
|
25
|
+
const searchParams = new URLSearchParams(window.location.search);
|
|
26
|
+
return getBuilderSearchParams(convertSearchParamsToQueryObject(searchParams));
|
|
27
|
+
};
|
|
28
|
+
const normalizeSearchParams = (searchParams) => searchParams instanceof URLSearchParams ? convertSearchParamsToQueryObject(searchParams) : searchParams;
|
|
20
29
|
export {
|
|
21
30
|
convertSearchParamsToQueryObject,
|
|
22
|
-
getBuilderSearchParams
|
|
31
|
+
getBuilderSearchParams,
|
|
32
|
+
getBuilderSearchParamsFromWindow,
|
|
33
|
+
normalizeSearchParams
|
|
23
34
|
};
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import * as React from 'react';
|
|
2
|
+
const handleABTesting = (item, testGroups) => {
|
|
3
|
+
if (item.variations && Object.keys(item.variations).length) {
|
|
4
|
+
const testGroup = item.id ? testGroups[item.id] : void 0;
|
|
5
|
+
const variationValue = testGroup ? item.variations[testGroup] : void 0;
|
|
6
|
+
if (testGroup && variationValue) {
|
|
7
|
+
item.data = variationValue.data;
|
|
8
|
+
item.testVariationId = variationValue.id;
|
|
9
|
+
item.testVariationName = variationValue.name;
|
|
10
|
+
} else {
|
|
11
|
+
let n = 0;
|
|
12
|
+
const random = Math.random();
|
|
13
|
+
let set = false;
|
|
14
|
+
for (const id in item.variations) {
|
|
15
|
+
const variation = item.variations[id];
|
|
16
|
+
const testRatio = variation.testRatio;
|
|
17
|
+
n += testRatio;
|
|
18
|
+
if (random < n) {
|
|
19
|
+
const variationName = variation.name || (variation.id === item.id ? "Default variation" : "");
|
|
20
|
+
set = true;
|
|
21
|
+
Object.assign(item, {
|
|
22
|
+
data: variation.data,
|
|
23
|
+
testVariationId: variation.id,
|
|
24
|
+
testVariationName: variationName
|
|
25
|
+
});
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
if (!set) {
|
|
29
|
+
Object.assign(item, {
|
|
30
|
+
testVariationId: item.id,
|
|
31
|
+
testVariationName: "Default"
|
|
32
|
+
});
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
};
|
|
37
|
+
export {
|
|
38
|
+
handleABTesting
|
|
39
|
+
};
|
|
@@ -38,20 +38,14 @@ var __async = (__this, __arguments, generator) => {
|
|
|
38
38
|
step((generator = generator.apply(__this, __arguments)).next());
|
|
39
39
|
});
|
|
40
40
|
};
|
|
41
|
+
import { flatten } from "../../helpers/flatten.js";
|
|
42
|
+
import {
|
|
43
|
+
getBuilderSearchParamsFromWindow,
|
|
44
|
+
normalizeSearchParams
|
|
45
|
+
} from "../get-builder-search-params/index.js";
|
|
41
46
|
import { getFetch } from "../get-fetch.js";
|
|
47
|
+
import { handleABTesting } from "./ab-testing.js";
|
|
42
48
|
const fetch$ = getFetch();
|
|
43
|
-
function flatten(object, path = null, separator = ".") {
|
|
44
|
-
return Object.keys(object).reduce((acc, key) => {
|
|
45
|
-
const value = object[key];
|
|
46
|
-
const newPath = [path, key].filter(Boolean).join(separator);
|
|
47
|
-
const isObject = [
|
|
48
|
-
typeof value === "object",
|
|
49
|
-
value !== null,
|
|
50
|
-
!(Array.isArray(value) && value.length === 0)
|
|
51
|
-
].every(Boolean);
|
|
52
|
-
return isObject ? __spreadValues(__spreadValues({}, acc), flatten(value, newPath, separator)) : __spreadProps(__spreadValues({}, acc), { [newPath]: value });
|
|
53
|
-
}, {});
|
|
54
|
-
}
|
|
55
49
|
function getContent(options) {
|
|
56
50
|
return __async(this, null, function* () {
|
|
57
51
|
return (yield getAllContent(__spreadProps(__spreadValues({}, options), { limit: 1 }))).results[0] || null;
|
|
@@ -67,67 +61,31 @@ const generateContentUrl = (options) => {
|
|
|
67
61
|
apiKey
|
|
68
62
|
} = options;
|
|
69
63
|
const url = new URL(`https://cdn.builder.io/api/v2/content/${model}?apiKey=${apiKey}&limit=${limit}&noTraverse=${noTraverse}`);
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
}
|
|
64
|
+
const queryOptions = __spreadValues(__spreadValues({}, getBuilderSearchParamsFromWindow()), normalizeSearchParams(options.options || {}));
|
|
65
|
+
const flattened = flatten(queryOptions);
|
|
66
|
+
for (const key in flattened) {
|
|
67
|
+
url.searchParams.set(key, String(flattened[key]));
|
|
75
68
|
}
|
|
76
69
|
if (userAttributes) {
|
|
77
70
|
url.searchParams.set("userAttributes", JSON.stringify(userAttributes));
|
|
78
71
|
}
|
|
79
72
|
if (query) {
|
|
80
|
-
const
|
|
81
|
-
for (const key in
|
|
82
|
-
url.searchParams.set(key, JSON.stringify(
|
|
73
|
+
const flattened2 = flatten({ query });
|
|
74
|
+
for (const key in flattened2) {
|
|
75
|
+
url.searchParams.set(key, JSON.stringify(flattened2[key]));
|
|
83
76
|
}
|
|
84
77
|
}
|
|
85
78
|
return url;
|
|
86
79
|
};
|
|
87
|
-
const handleABTesting = (content, testGroups) => {
|
|
88
|
-
for (const item of content.results) {
|
|
89
|
-
if (item.variations && Object.keys(item.variations).length) {
|
|
90
|
-
const testGroup = testGroups[item.id];
|
|
91
|
-
const variationValue = item.variations[testGroup];
|
|
92
|
-
if (testGroup && variationValue) {
|
|
93
|
-
item.data = variationValue.data;
|
|
94
|
-
item.testVariationId = variationValue.id;
|
|
95
|
-
item.testVariationName = variationValue.name;
|
|
96
|
-
} else {
|
|
97
|
-
let n = 0;
|
|
98
|
-
const random = Math.random();
|
|
99
|
-
let set = false;
|
|
100
|
-
for (const id in item.variations) {
|
|
101
|
-
const variation = item.variations[id];
|
|
102
|
-
const testRatio = variation.testRatio;
|
|
103
|
-
n += testRatio;
|
|
104
|
-
if (random < n) {
|
|
105
|
-
const variationName = variation.name || (variation.id === item.id ? "Default variation" : "");
|
|
106
|
-
set = true;
|
|
107
|
-
Object.assign(item, {
|
|
108
|
-
data: variation.data,
|
|
109
|
-
testVariationId: variation.id,
|
|
110
|
-
testVariationName: variationName
|
|
111
|
-
});
|
|
112
|
-
}
|
|
113
|
-
}
|
|
114
|
-
if (!set) {
|
|
115
|
-
Object.assign(item, {
|
|
116
|
-
testVariationId: item.id,
|
|
117
|
-
testVariationName: "Default"
|
|
118
|
-
});
|
|
119
|
-
}
|
|
120
|
-
}
|
|
121
|
-
}
|
|
122
|
-
}
|
|
123
|
-
};
|
|
124
80
|
function getAllContent(options) {
|
|
125
81
|
return __async(this, null, function* () {
|
|
126
82
|
const url = generateContentUrl(options);
|
|
127
83
|
const fetch = yield fetch$;
|
|
128
84
|
const content = yield fetch(url.href).then((res) => res.json());
|
|
129
85
|
if (options.testGroups) {
|
|
130
|
-
|
|
86
|
+
for (const item of content.results) {
|
|
87
|
+
handleABTesting(item, options.testGroups);
|
|
88
|
+
}
|
|
131
89
|
}
|
|
132
90
|
return content;
|
|
133
91
|
});
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import * as React from 'react';
|
|
@@ -30,7 +30,6 @@ var __objRest = (source, exclude) => {
|
|
|
30
30
|
}
|
|
31
31
|
return target;
|
|
32
32
|
};
|
|
33
|
-
import { fastClone } from "./fast-clone.js";
|
|
34
33
|
const components = [];
|
|
35
34
|
function registerComponent(component, info) {
|
|
36
35
|
components.push(__spreadValues({ component }, info));
|
|
@@ -39,31 +38,34 @@ function registerComponent(component, info) {
|
|
|
39
38
|
}
|
|
40
39
|
const createRegisterComponentMessage = (_a) => {
|
|
41
40
|
var _b = _a, {
|
|
42
|
-
component
|
|
41
|
+
component: _
|
|
43
42
|
} = _b, info = __objRest(_b, [
|
|
44
43
|
"component"
|
|
45
44
|
]);
|
|
46
45
|
return {
|
|
47
46
|
type: "builder.registerComponent",
|
|
48
|
-
data: prepareComponentInfoToSend(
|
|
47
|
+
data: prepareComponentInfoToSend(info)
|
|
49
48
|
};
|
|
50
49
|
};
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
50
|
+
const fastClone = (obj) => JSON.parse(JSON.stringify(obj));
|
|
51
|
+
const serializeValue = (value) => typeof value === "function" ? serializeFn(value) : fastClone(value);
|
|
52
|
+
const serializeFn = (fnValue) => {
|
|
53
|
+
const fnStr = fnValue.toString().trim();
|
|
54
|
+
const appendFunction = !fnStr.startsWith("function") && !fnStr.startsWith("(");
|
|
55
|
+
return `return (${appendFunction ? "function " : ""}${fnStr}).apply(this, arguments)`;
|
|
56
|
+
};
|
|
57
|
+
const prepareComponentInfoToSend = (_c) => {
|
|
58
|
+
var _d = _c, {
|
|
59
|
+
inputs
|
|
60
|
+
} = _d, info = __objRest(_d, [
|
|
61
|
+
"inputs"
|
|
62
|
+
]);
|
|
63
|
+
return __spreadProps(__spreadValues({}, fastClone(info)), {
|
|
64
|
+
inputs: inputs == null ? void 0 : inputs.map((input) => Object.entries(input).reduce((acc, [key, value]) => __spreadProps(__spreadValues({}, acc), {
|
|
65
|
+
[key]: serializeValue(value)
|
|
66
|
+
}), {}))
|
|
65
67
|
});
|
|
66
|
-
}
|
|
68
|
+
};
|
|
67
69
|
export {
|
|
68
70
|
components,
|
|
69
71
|
createRegisterComponentMessage,
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import * as React from 'react';
|
|
2
|
+
var __defProp = Object.defineProperty;
|
|
3
|
+
var __defProps = Object.defineProperties;
|
|
4
|
+
var __getOwnPropDescs = Object.getOwnPropertyDescriptors;
|
|
5
|
+
var __getOwnPropSymbols = Object.getOwnPropertySymbols;
|
|
6
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
7
|
+
var __propIsEnum = Object.prototype.propertyIsEnumerable;
|
|
8
|
+
var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
|
|
9
|
+
var __spreadValues = (a, b) => {
|
|
10
|
+
for (var prop in b || (b = {}))
|
|
11
|
+
if (__hasOwnProp.call(b, prop))
|
|
12
|
+
__defNormalProp(a, prop, b[prop]);
|
|
13
|
+
if (__getOwnPropSymbols)
|
|
14
|
+
for (var prop of __getOwnPropSymbols(b)) {
|
|
15
|
+
if (__propIsEnum.call(b, prop))
|
|
16
|
+
__defNormalProp(a, prop, b[prop]);
|
|
17
|
+
}
|
|
18
|
+
return a;
|
|
19
|
+
};
|
|
20
|
+
var __spreadProps = (a, b) => __defProps(a, __getOwnPropDescs(b));
|
|
21
|
+
function flatten(object, path = null, separator = ".") {
|
|
22
|
+
return Object.keys(object).reduce((acc, key) => {
|
|
23
|
+
const value = object[key];
|
|
24
|
+
const newPath = [path, key].filter(Boolean).join(separator);
|
|
25
|
+
const isObject = [
|
|
26
|
+
typeof value === "object",
|
|
27
|
+
value !== null,
|
|
28
|
+
!(Array.isArray(value) && value.length === 0)
|
|
29
|
+
].every(Boolean);
|
|
30
|
+
return isObject ? __spreadValues(__spreadValues({}, acc), flatten(value, newPath, separator)) : __spreadProps(__spreadValues({}, acc), { [newPath]: value });
|
|
31
|
+
}, {});
|
|
32
|
+
}
|
|
33
|
+
export {
|
|
34
|
+
flatten
|
|
35
|
+
};
|
|
@@ -1,12 +0,0 @@
|
|
|
1
|
-
import * as React from 'react';
|
|
2
|
-
import { isPreviewing } from "./is-previewing.js";
|
|
3
|
-
function previewingModelName() {
|
|
4
|
-
if (!isPreviewing()) {
|
|
5
|
-
return null;
|
|
6
|
-
}
|
|
7
|
-
const url = new URL(location.href);
|
|
8
|
-
return url.searchParams.get("builder.preview");
|
|
9
|
-
}
|
|
10
|
-
export {
|
|
11
|
-
previewingModelName
|
|
12
|
-
};
|