@builder.io/sdk-react-native 0.0.1-59 → 0.0.1-61
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 +2 -2
- package/src/components/render-block/block-styles.js +2 -1
- package/src/components/render-block/render-block.js +57 -17
- package/src/components/render-block/render-repeated-block.js +29 -0
- package/src/components/render-content/render-content.js +8 -8
- package/src/functions/convert-style-object.js +7 -0
- package/src/functions/get-block-styles.js +9 -35
- package/src/functions/get-block-tag.js +1 -1
- package/src/functions/get-content/ab-testing.js +39 -0
- package/src/functions/get-content/index.js +5 -50
- package/src/functions/get-content/types.js +1 -0
- package/src/functions/get-processed-block.js +15 -8
- package/src/functions/get-processed-block.test.js +2 -1
- package/src/functions/register-component.js +20 -18
- package/src/functions/sanitize-styles.js +33 -0
- package/src/helpers/flatten.js +35 -0
- package/src/functions/fast-clone.js +0 -5
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-61",
|
|
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,14 +38,21 @@ import { getBlockProperties } from "../../functions/get-block-properties.js";
|
|
|
38
38
|
import { getBlockStyles } from "../../functions/get-block-styles.js";
|
|
39
39
|
import { getBlockTag } from "../../functions/get-block-tag.js";
|
|
40
40
|
import { getProcessedBlock } from "../../functions/get-processed-block.js";
|
|
41
|
+
import { evaluate } from "../../functions/evaluate.js";
|
|
41
42
|
import BlockStyles from "./block-styles.js";
|
|
42
43
|
import { isEmptyHtmlElement } from "./render-block.helpers.js";
|
|
43
44
|
import RenderComponent from "./render-component.js";
|
|
45
|
+
import RenderRepeatedBlock from "./render-repeated-block.js";
|
|
44
46
|
function RenderBlock(props) {
|
|
45
|
-
var _a, _b;
|
|
47
|
+
var _a, _b, _c;
|
|
46
48
|
function component() {
|
|
47
49
|
var _a2;
|
|
48
|
-
const componentName = (_a2 =
|
|
50
|
+
const componentName = (_a2 = getProcessedBlock({
|
|
51
|
+
block: props.block,
|
|
52
|
+
state: builderContext.state,
|
|
53
|
+
context: builderContext.context,
|
|
54
|
+
evaluateBindings: false
|
|
55
|
+
}).component) == null ? void 0 : _a2.name;
|
|
49
56
|
if (!componentName) {
|
|
50
57
|
return null;
|
|
51
58
|
}
|
|
@@ -75,10 +82,11 @@ function RenderBlock(props) {
|
|
|
75
82
|
return getBlockTag(useBlock());
|
|
76
83
|
}
|
|
77
84
|
function useBlock() {
|
|
78
|
-
return getProcessedBlock({
|
|
85
|
+
return repeatItemData() ? props.block : getProcessedBlock({
|
|
79
86
|
block: props.block,
|
|
80
87
|
state: builderContext.state,
|
|
81
|
-
context: builderContext.context
|
|
88
|
+
context: builderContext.context,
|
|
89
|
+
evaluateBindings: true
|
|
82
90
|
});
|
|
83
91
|
}
|
|
84
92
|
function attributes() {
|
|
@@ -99,30 +107,62 @@ function RenderBlock(props) {
|
|
|
99
107
|
attributes: attributes()
|
|
100
108
|
});
|
|
101
109
|
}
|
|
110
|
+
function renderComponentProps() {
|
|
111
|
+
return {
|
|
112
|
+
blockChildren: children(),
|
|
113
|
+
componentRef: componentRef(),
|
|
114
|
+
componentOptions: componentOptions()
|
|
115
|
+
};
|
|
116
|
+
}
|
|
102
117
|
function children() {
|
|
103
118
|
var _a2;
|
|
104
119
|
return (_a2 = useBlock().children) != null ? _a2 : [];
|
|
105
120
|
}
|
|
106
|
-
function
|
|
107
|
-
|
|
121
|
+
function childrenWithoutParentComponent() {
|
|
122
|
+
const shouldRenderChildrenOutsideRef = !componentRef() && !repeatItemData();
|
|
123
|
+
return shouldRenderChildrenOutsideRef ? children() : [];
|
|
124
|
+
}
|
|
125
|
+
function repeatItemData() {
|
|
126
|
+
const _a2 = props.block, { repeat } = _a2, blockWithoutRepeat = __objRest(_a2, ["repeat"]);
|
|
127
|
+
if (!(repeat == null ? void 0 : repeat.collection)) {
|
|
128
|
+
return void 0;
|
|
129
|
+
}
|
|
130
|
+
const itemsArray = evaluate({
|
|
131
|
+
code: repeat.collection,
|
|
132
|
+
state: builderContext.state,
|
|
133
|
+
context: builderContext.context
|
|
134
|
+
});
|
|
135
|
+
if (!Array.isArray(itemsArray)) {
|
|
136
|
+
return void 0;
|
|
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;
|
|
108
152
|
}
|
|
109
153
|
const builderContext = useContext(BuilderContext);
|
|
110
154
|
const TagNameRef = tagName();
|
|
111
|
-
return /* @__PURE__ */ React.createElement(React.Fragment, null, shouldWrap() ? /* @__PURE__ */ React.createElement(React.Fragment, null, !isEmptyHtmlElement(tagName()) ? /* @__PURE__ */ React.createElement(React.Fragment, null, /* @__PURE__ */ React.createElement(TagNameRef, __spreadValues({}, attributes()), /* @__PURE__ */ React.createElement(
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
}), (
|
|
155
|
+
return /* @__PURE__ */ React.createElement(React.Fragment, null, shouldWrap() ? /* @__PURE__ */ React.createElement(React.Fragment, null, !isEmptyHtmlElement(tagName()) ? /* @__PURE__ */ React.createElement(React.Fragment, null, /* @__PURE__ */ React.createElement(TagNameRef, __spreadValues({}, attributes()), repeatItemData() ? /* @__PURE__ */ React.createElement(React.Fragment, null, (_a = repeatItemData()) == null ? void 0 : _a.map((data, index) => /* @__PURE__ */ React.createElement(RenderRepeatedBlock, {
|
|
156
|
+
key: index,
|
|
157
|
+
repeatContext: data.context,
|
|
158
|
+
block: data.block
|
|
159
|
+
}))) : /* @__PURE__ */ React.createElement(RenderComponent, __spreadValues({}, renderComponentProps())), (_b = childrenWithoutParentComponent()) == null ? void 0 : _b.map((child) => /* @__PURE__ */ React.createElement(RenderBlock, {
|
|
116
160
|
key: "render-block-" + child.id,
|
|
117
161
|
block: child
|
|
118
|
-
})), (
|
|
162
|
+
})), (_c = childrenWithoutParentComponent()) == null ? void 0 : _c.map((child) => /* @__PURE__ */ React.createElement(BlockStyles, {
|
|
119
163
|
key: "block-style-" + child.id,
|
|
120
164
|
block: child
|
|
121
|
-
})))) : /* @__PURE__ */ React.createElement(TagNameRef, __spreadValues({}, attributes()))) : /* @__PURE__ */ React.createElement(RenderComponent, {
|
|
122
|
-
blockChildren: children(),
|
|
123
|
-
componentRef: componentRef(),
|
|
124
|
-
componentOptions: componentOptions()
|
|
125
|
-
}));
|
|
165
|
+
})))) : /* @__PURE__ */ React.createElement(TagNameRef, __spreadValues({}, attributes()))) : /* @__PURE__ */ React.createElement(RenderComponent, __spreadValues({}, renderComponentProps())));
|
|
126
166
|
}
|
|
127
167
|
export {
|
|
128
168
|
RenderBlock as default
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import * as React from "react";
|
|
2
|
+
import BuilderContext from "../../context/builder.context";
|
|
3
|
+
import RenderBlock from "./render-block.js";
|
|
4
|
+
function RenderRepeatedBlock(props) {
|
|
5
|
+
return /* @__PURE__ */ React.createElement(BuilderContext.Provider, {
|
|
6
|
+
value: {
|
|
7
|
+
get content() {
|
|
8
|
+
return props.repeatContext.content;
|
|
9
|
+
},
|
|
10
|
+
get state() {
|
|
11
|
+
return props.repeatContext.state;
|
|
12
|
+
},
|
|
13
|
+
get context() {
|
|
14
|
+
return props.repeatContext.context;
|
|
15
|
+
},
|
|
16
|
+
get apiKey() {
|
|
17
|
+
return props.repeatContext.apiKey;
|
|
18
|
+
},
|
|
19
|
+
get registeredComponents() {
|
|
20
|
+
return props.repeatContext.registeredComponents;
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
}, /* @__PURE__ */ React.createElement(RenderBlock, {
|
|
24
|
+
block: props.block
|
|
25
|
+
}));
|
|
26
|
+
}
|
|
27
|
+
export {
|
|
28
|
+
RenderRepeatedBlock as default
|
|
29
|
+
};
|
|
@@ -77,8 +77,8 @@ function RenderContent(props) {
|
|
|
77
77
|
var _a2, _b2;
|
|
78
78
|
return __spreadValues(__spreadValues(__spreadValues({}, (_b2 = (_a2 = props.content) == null ? void 0 : _a2.data) == null ? void 0 : _b2.state), props.data), overrideState);
|
|
79
79
|
}
|
|
80
|
-
function
|
|
81
|
-
return {};
|
|
80
|
+
function contextContext() {
|
|
81
|
+
return props.context || {};
|
|
82
82
|
}
|
|
83
83
|
function allRegisteredComponents() {
|
|
84
84
|
const allComponentsArray = [
|
|
@@ -114,7 +114,7 @@ function RenderContent(props) {
|
|
|
114
114
|
if (jsCode) {
|
|
115
115
|
evaluate({
|
|
116
116
|
code: jsCode,
|
|
117
|
-
context:
|
|
117
|
+
context: contextContext(),
|
|
118
118
|
state: contentState()
|
|
119
119
|
});
|
|
120
120
|
}
|
|
@@ -125,7 +125,7 @@ function RenderContent(props) {
|
|
|
125
125
|
function evalExpression(expression) {
|
|
126
126
|
return expression.replace(/{{([^}]+)}}/g, (_match, group) => evaluate({
|
|
127
127
|
code: group,
|
|
128
|
-
context:
|
|
128
|
+
context: contextContext(),
|
|
129
129
|
state: contentState()
|
|
130
130
|
}));
|
|
131
131
|
}
|
|
@@ -182,13 +182,13 @@ function RenderContent(props) {
|
|
|
182
182
|
}
|
|
183
183
|
if (isPreviewing()) {
|
|
184
184
|
if (props.model && previewingModelName() === props.model) {
|
|
185
|
-
const
|
|
186
|
-
const previewApiKey =
|
|
185
|
+
const searchParams = new URL(location.href).searchParams;
|
|
186
|
+
const previewApiKey = searchParams.get("apiKey") || searchParams.get("builder.space");
|
|
187
187
|
if (previewApiKey) {
|
|
188
188
|
getContent({
|
|
189
189
|
model: props.model,
|
|
190
190
|
apiKey: previewApiKey,
|
|
191
|
-
options: getBuilderSearchParams(convertSearchParamsToQueryObject(
|
|
191
|
+
options: getBuilderSearchParams(convertSearchParamsToQueryObject(searchParams))
|
|
192
192
|
}).then((content) => {
|
|
193
193
|
if (content) {
|
|
194
194
|
setOverrideContent(content);
|
|
@@ -228,7 +228,7 @@ function RenderContent(props) {
|
|
|
228
228
|
return contentState();
|
|
229
229
|
},
|
|
230
230
|
get context() {
|
|
231
|
-
return
|
|
231
|
+
return contextContext();
|
|
232
232
|
},
|
|
233
233
|
get apiKey() {
|
|
234
234
|
return props.apiKey;
|
|
@@ -15,45 +15,19 @@ var __spreadValues = (a, b) => {
|
|
|
15
15
|
}
|
|
16
16
|
return a;
|
|
17
17
|
};
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
function validateReactNativeStyles(styles) {
|
|
22
|
-
for (const key in styles) {
|
|
23
|
-
const propertyValue = styles[key];
|
|
24
|
-
if (key === "display" && !displayValues.has(propertyValue)) {
|
|
25
|
-
if (SHOW_WARNINGS) {
|
|
26
|
-
console.warn(`Style value for key "display" must be "flex" or "none" but had ${propertyValue}`);
|
|
27
|
-
}
|
|
28
|
-
delete styles[key];
|
|
29
|
-
}
|
|
30
|
-
if (typeof propertyValue === "string" && propertyValue.match(/^-?\d/)) {
|
|
31
|
-
const newValue = parseFloat(propertyValue);
|
|
32
|
-
if (!isNaN(newValue)) {
|
|
33
|
-
styles[key] = newValue;
|
|
34
|
-
}
|
|
35
|
-
if (typeof newValue === "number" && newValue < 0) {
|
|
36
|
-
styles[key] = 0;
|
|
37
|
-
}
|
|
38
|
-
}
|
|
39
|
-
if (propertiesThatMustBeNumber.has(key) && typeof styles[key] !== "number") {
|
|
40
|
-
if (SHOW_WARNINGS) {
|
|
41
|
-
console.warn(`Style key ${key} must be a number, but had value \`${styles[key]}\``);
|
|
42
|
-
}
|
|
43
|
-
delete styles[key];
|
|
44
|
-
}
|
|
45
|
-
}
|
|
46
|
-
}
|
|
18
|
+
import { getMaxWidthQueryForSize } from "../constants/device-sizes.js";
|
|
19
|
+
import { convertStyleObject } from "./convert-style-object.js";
|
|
20
|
+
import { sanitizeBlockStyles } from "./sanitize-styles.js";
|
|
47
21
|
function getBlockStyles(block) {
|
|
48
|
-
var _a, _b, _c;
|
|
49
|
-
const styles = __spreadValues(__spreadValues({}, (_a = block.responsiveStyles) == null ? void 0 : _a.large), block.styles);
|
|
22
|
+
var _a, _b, _c, _d, _e;
|
|
23
|
+
const styles = __spreadValues(__spreadValues({}, convertStyleObject((_a = block.responsiveStyles) == null ? void 0 : _a.large)), block.styles);
|
|
50
24
|
if ((_b = block.responsiveStyles) == null ? void 0 : _b.medium) {
|
|
51
|
-
|
|
25
|
+
styles[getMaxWidthQueryForSize("medium")] = convertStyleObject((_c = block.responsiveStyles) == null ? void 0 : _c.medium);
|
|
52
26
|
}
|
|
53
|
-
if ((
|
|
54
|
-
|
|
27
|
+
if ((_d = block.responsiveStyles) == null ? void 0 : _d.small) {
|
|
28
|
+
styles[getMaxWidthQueryForSize("small")] = convertStyleObject((_e = block.responsiveStyles) == null ? void 0 : _e.small);
|
|
55
29
|
}
|
|
56
|
-
|
|
30
|
+
sanitizeBlockStyles(styles);
|
|
57
31
|
return styles;
|
|
58
32
|
}
|
|
59
33
|
export {
|
|
@@ -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,10 @@ 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";
|
|
41
42
|
import { getFetch } from "../get-fetch.js";
|
|
43
|
+
import { handleABTesting } from "./ab-testing.js";
|
|
42
44
|
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
45
|
function getContent(options) {
|
|
56
46
|
return __async(this, null, function* () {
|
|
57
47
|
return (yield getAllContent(__spreadProps(__spreadValues({}, options), { limit: 1 }))).results[0] || null;
|
|
@@ -84,50 +74,15 @@ const generateContentUrl = (options) => {
|
|
|
84
74
|
}
|
|
85
75
|
return url;
|
|
86
76
|
};
|
|
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
77
|
function getAllContent(options) {
|
|
125
78
|
return __async(this, null, function* () {
|
|
126
79
|
const url = generateContentUrl(options);
|
|
127
80
|
const fetch = yield fetch$;
|
|
128
81
|
const content = yield fetch(url.href).then((res) => res.json());
|
|
129
82
|
if (options.testGroups) {
|
|
130
|
-
|
|
83
|
+
for (const item of content.results) {
|
|
84
|
+
handleABTesting(item, options.testGroups);
|
|
85
|
+
}
|
|
131
86
|
}
|
|
132
87
|
return content;
|
|
133
88
|
});
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import * as React from 'react';
|
|
@@ -21,9 +21,11 @@ var __spreadProps = (a, b) => __defProps(a, __getOwnPropDescs(b));
|
|
|
21
21
|
import { evaluate } from "./evaluate.js";
|
|
22
22
|
import { set } from "./set.js";
|
|
23
23
|
import { transformBlock } from "./transform-block.js";
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
24
|
+
const evaluateBindings = ({
|
|
25
|
+
block,
|
|
26
|
+
context,
|
|
27
|
+
state
|
|
28
|
+
}) => {
|
|
27
29
|
if (!block.bindings) {
|
|
28
30
|
return block;
|
|
29
31
|
}
|
|
@@ -33,14 +35,19 @@ function getProcessedBlock(options) {
|
|
|
33
35
|
});
|
|
34
36
|
for (const binding in block.bindings) {
|
|
35
37
|
const expression = block.bindings[binding];
|
|
36
|
-
const value = evaluate({
|
|
37
|
-
code: expression,
|
|
38
|
-
state,
|
|
39
|
-
context
|
|
40
|
-
});
|
|
38
|
+
const value = evaluate({ code: expression, state, context });
|
|
41
39
|
set(copied, binding, value);
|
|
42
40
|
}
|
|
43
41
|
return copied;
|
|
42
|
+
};
|
|
43
|
+
function getProcessedBlock(options) {
|
|
44
|
+
const { state, context } = options;
|
|
45
|
+
const block = transformBlock(options.block);
|
|
46
|
+
if (evaluateBindings) {
|
|
47
|
+
return evaluateBindings({ block, state, context });
|
|
48
|
+
} else {
|
|
49
|
+
return block;
|
|
50
|
+
}
|
|
44
51
|
}
|
|
45
52
|
export {
|
|
46
53
|
getProcessedBlock
|
|
@@ -21,7 +21,8 @@ test("Can process bindings", () => {
|
|
|
21
21
|
const processed = getProcessedBlock({
|
|
22
22
|
block,
|
|
23
23
|
context: {},
|
|
24
|
-
state: { test: "hello" }
|
|
24
|
+
state: { test: "hello" },
|
|
25
|
+
evaluateBindings: true
|
|
25
26
|
});
|
|
26
27
|
expect(processed).not.toEqual(block);
|
|
27
28
|
expect((_a = processed.properties) == null ? void 0 : _a.foo).toEqual("baz");
|
|
@@ -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,33 @@
|
|
|
1
|
+
import * as React from 'react';
|
|
2
|
+
const propertiesThatMustBeNumber = new Set(["lineHeight"]);
|
|
3
|
+
const displayValues = new Set(["flex", "none"]);
|
|
4
|
+
const SHOW_WARNINGS = false;
|
|
5
|
+
const sanitizeBlockStyles = (styles) => {
|
|
6
|
+
for (const key in styles) {
|
|
7
|
+
const propertyValue = styles[key];
|
|
8
|
+
if (key === "display" && !displayValues.has(propertyValue)) {
|
|
9
|
+
if (SHOW_WARNINGS) {
|
|
10
|
+
console.warn(`Style value for key "display" must be "flex" or "none" but had ${propertyValue}`);
|
|
11
|
+
}
|
|
12
|
+
delete styles[key];
|
|
13
|
+
}
|
|
14
|
+
if (typeof propertyValue === "string" && propertyValue.match(/^-?\d/)) {
|
|
15
|
+
const newValue = parseFloat(propertyValue);
|
|
16
|
+
if (!isNaN(newValue)) {
|
|
17
|
+
styles[key] = newValue;
|
|
18
|
+
}
|
|
19
|
+
if (typeof newValue === "number" && newValue < 0) {
|
|
20
|
+
styles[key] = 0;
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
if (propertiesThatMustBeNumber.has(key) && typeof styles[key] !== "number") {
|
|
24
|
+
if (SHOW_WARNINGS) {
|
|
25
|
+
console.warn(`Style key ${key} must be a number, but had value \`${styles[key]}\``);
|
|
26
|
+
}
|
|
27
|
+
delete styles[key];
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
};
|
|
31
|
+
export {
|
|
32
|
+
sanitizeBlockStyles
|
|
33
|
+
};
|
|
@@ -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
|
+
};
|