@builder.io/sdk-solid 0.0.8-14 → 0.0.8-17
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/custom-code/custom-code.jsx +2 -2
- package/src/blocks/embed/component-info.js +20 -1
- package/src/blocks/embed/embed.jsx +30 -33
- package/src/blocks/embed/helpers.js +9 -0
- package/src/blocks/form/form.jsx +2 -2
- package/src/blocks/image/component-info.js +47 -1
- package/src/blocks/image/image.helpers.js +48 -0
- package/src/blocks/image/image.jsx +32 -2
- package/src/blocks/symbol/symbol.jsx +30 -2
- package/src/blocks/video/video.jsx +1 -1
- package/src/components/render-block/block-styles.jsx +2 -1
- package/src/components/render-block/render-block.jsx +77 -10
- package/src/components/render-block/render-repeated-block.jsx +32 -0
- package/src/components/render-content/render-content.jsx +27 -9
- package/src/constants/builder-registered-components.js +4 -1
- package/src/functions/convert-style-object.js +14 -0
- package/src/functions/get-block-styles.js +7 -15
- package/src/functions/get-content/ab-testing.js +38 -0
- package/src/functions/get-content/index.js +5 -50
- package/src/functions/get-content/types.js +0 -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 +5 -0
- package/src/helpers/flatten.js +34 -0
- package/src/functions/fast-clone.js +0 -4
package/package.json
CHANGED
|
@@ -186,7 +186,31 @@ const componentInfo = {
|
|
|
186
186
|
]
|
|
187
187
|
}
|
|
188
188
|
],
|
|
189
|
-
onChange
|
|
189
|
+
onChange(options) {
|
|
190
|
+
function clearWidths() {
|
|
191
|
+
columns.forEach((col) => {
|
|
192
|
+
col.delete("width");
|
|
193
|
+
});
|
|
194
|
+
}
|
|
195
|
+
const columns = options.get("columns");
|
|
196
|
+
if (Array.isArray(columns)) {
|
|
197
|
+
const containsColumnWithWidth = !!columns.find((col) => col.get("width"));
|
|
198
|
+
if (containsColumnWithWidth) {
|
|
199
|
+
const containsColumnWithoutWidth = !!columns.find((col) => !col.get("width"));
|
|
200
|
+
if (containsColumnWithoutWidth) {
|
|
201
|
+
clearWidths();
|
|
202
|
+
} else {
|
|
203
|
+
const sumWidths = columns.reduce((memo, col) => {
|
|
204
|
+
return memo + col.get("width");
|
|
205
|
+
}, 0);
|
|
206
|
+
const widthsDontAddUp = sumWidths !== 100;
|
|
207
|
+
if (widthsDontAddUp) {
|
|
208
|
+
clearWidths();
|
|
209
|
+
}
|
|
210
|
+
}
|
|
211
|
+
}
|
|
212
|
+
}
|
|
213
|
+
}
|
|
190
214
|
},
|
|
191
215
|
{
|
|
192
216
|
name: "space",
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { onMount
|
|
1
|
+
import { onMount } from "solid-js";
|
|
2
2
|
import { createMutable } from "solid-js/store";
|
|
3
3
|
|
|
4
4
|
function CustomCode(props) {
|
|
@@ -41,7 +41,7 @@ function CustomCode(props) {
|
|
|
41
41
|
}
|
|
42
42
|
|
|
43
43
|
});
|
|
44
|
-
|
|
44
|
+
let elem;
|
|
45
45
|
onMount(() => {
|
|
46
46
|
state.findAndRunScripts();
|
|
47
47
|
});
|
|
@@ -9,7 +9,26 @@ const componentInfo = {
|
|
|
9
9
|
required: true,
|
|
10
10
|
defaultValue: "",
|
|
11
11
|
helperText: "e.g. enter a youtube url, google map, etc",
|
|
12
|
-
onChange
|
|
12
|
+
onChange(options) {
|
|
13
|
+
const url = options.get("url");
|
|
14
|
+
if (url) {
|
|
15
|
+
options.set("content", "Loading...");
|
|
16
|
+
const apiKey = "ae0e60e78201a3f2b0de4b";
|
|
17
|
+
return fetch(`https://iframe.ly/api/iframely?url=${url}&api_key=${apiKey}`).then((res) => res.json()).then((data) => {
|
|
18
|
+
if (options.get("url") === url) {
|
|
19
|
+
if (data.html) {
|
|
20
|
+
options.set("content", data.html);
|
|
21
|
+
} else {
|
|
22
|
+
options.set("content", "Invalid url, please try another");
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
}).catch((_err) => {
|
|
26
|
+
options.set("content", "There was an error embedding this URL, please try again or another URL");
|
|
27
|
+
});
|
|
28
|
+
} else {
|
|
29
|
+
options.delete("content");
|
|
30
|
+
}
|
|
31
|
+
}
|
|
13
32
|
},
|
|
14
33
|
{
|
|
15
34
|
name: "content",
|
|
@@ -1,50 +1,47 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { on, createEffect } from "solid-js";
|
|
2
2
|
import { createMutable } from "solid-js/store";
|
|
3
|
+
import { isJsScript } from "./helpers";
|
|
3
4
|
|
|
4
5
|
function Embed(props) {
|
|
5
6
|
const state = createMutable({
|
|
6
7
|
scriptsInserted: [],
|
|
7
8
|
scriptsRun: [],
|
|
9
|
+
ranInitFn: false,
|
|
8
10
|
|
|
9
11
|
findAndRunScripts() {
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
} else if (!script.type || ["text/javascript", "application/javascript", "application/ecmascript"].includes(script.type)) {
|
|
28
|
-
if (state.scriptsRun.includes(script.innerText)) {
|
|
29
|
-
continue;
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
try {
|
|
33
|
-
state.scriptsRun.push(script.innerText);
|
|
34
|
-
new Function(script.innerText)();
|
|
35
|
-
} catch (error) {
|
|
36
|
-
console.warn("`Embed`: Error running script:", error);
|
|
37
|
-
}
|
|
12
|
+
const scripts = elem.getElementsByTagName("script");
|
|
13
|
+
|
|
14
|
+
for (let i = 0; i < scripts.length; i++) {
|
|
15
|
+
const script = scripts[i];
|
|
16
|
+
|
|
17
|
+
if (script.src && !state.scriptsInserted.includes(script.src)) {
|
|
18
|
+
state.scriptsInserted.push(script.src);
|
|
19
|
+
const newScript = document.createElement("script");
|
|
20
|
+
newScript.async = true;
|
|
21
|
+
newScript.src = script.src;
|
|
22
|
+
document.head.appendChild(newScript);
|
|
23
|
+
} else if (isJsScript(script) && !state.scriptsRun.includes(script.innerText)) {
|
|
24
|
+
try {
|
|
25
|
+
state.scriptsRun.push(script.innerText);
|
|
26
|
+
new Function(script.innerText)();
|
|
27
|
+
} catch (error) {
|
|
28
|
+
console.warn("`Embed`: Error running script:", error);
|
|
38
29
|
}
|
|
39
30
|
}
|
|
40
31
|
}
|
|
41
32
|
}
|
|
42
33
|
|
|
43
34
|
});
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
35
|
+
let elem;
|
|
36
|
+
|
|
37
|
+
function onUpdateFn_0() {
|
|
38
|
+
if (elem && !state.ranInitFn) {
|
|
39
|
+
state.ranInitFn = true;
|
|
40
|
+
state.findAndRunScripts();
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
createEffect(on(() => [elem, state.ranInitFn], onUpdateFn_0));
|
|
48
45
|
return <div class="builder-embed" ref={elem} innerHTML={props.content}></div>;
|
|
49
46
|
}
|
|
50
47
|
|
package/src/blocks/form/form.jsx
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { Show, For
|
|
1
|
+
import { Show, For } from "solid-js";
|
|
2
2
|
import { createMutable } from "solid-js/store";
|
|
3
3
|
import { css } from "solid-styled-components";
|
|
4
4
|
import RenderBlock from "../../components/render-block/render-block.jsx";
|
|
@@ -218,7 +218,7 @@ function FormComponent(props) {
|
|
|
218
218
|
}
|
|
219
219
|
|
|
220
220
|
});
|
|
221
|
-
|
|
221
|
+
let formRef;
|
|
222
222
|
return <form {...props.attributes} validate={props.validate} ref={formRef} action={!props.sendWithJs && props.action} method={props.method} name={props.name} onSubmit={event => state.onSubmit(event)}>
|
|
223
223
|
<Show when={props.builderBlock && props.builderBlock.children}>
|
|
224
224
|
<For each={props.builderBlock?.children}>
|
|
@@ -18,7 +18,53 @@ const componentInfo = {
|
|
|
18
18
|
allowedFileTypes: ["jpeg", "jpg", "png", "svg"],
|
|
19
19
|
required: true,
|
|
20
20
|
defaultValue: "https://cdn.builder.io/api/v1/image/assets%2Fpwgjf0RoYWbdnJSbpBAjXNRMe9F2%2Ffb27a7c790324294af8be1c35fe30f4d",
|
|
21
|
-
onChange
|
|
21
|
+
onChange(options) {
|
|
22
|
+
const DEFAULT_ASPECT_RATIO = 0.7041;
|
|
23
|
+
options.delete("srcset");
|
|
24
|
+
options.delete("noWebp");
|
|
25
|
+
function loadImage(url, timeout = 6e4) {
|
|
26
|
+
return new Promise((resolve, reject) => {
|
|
27
|
+
const img = document.createElement("img");
|
|
28
|
+
let loaded = false;
|
|
29
|
+
img.onload = () => {
|
|
30
|
+
loaded = true;
|
|
31
|
+
resolve(img);
|
|
32
|
+
};
|
|
33
|
+
img.addEventListener("error", (event) => {
|
|
34
|
+
console.warn("Image load failed", event.error);
|
|
35
|
+
reject(event.error);
|
|
36
|
+
});
|
|
37
|
+
img.src = url;
|
|
38
|
+
setTimeout(() => {
|
|
39
|
+
if (!loaded) {
|
|
40
|
+
reject(new Error("Image load timed out"));
|
|
41
|
+
}
|
|
42
|
+
}, timeout);
|
|
43
|
+
});
|
|
44
|
+
}
|
|
45
|
+
function round(num) {
|
|
46
|
+
return Math.round(num * 1e3) / 1e3;
|
|
47
|
+
}
|
|
48
|
+
const value = options.get("image");
|
|
49
|
+
const aspectRatio = options.get("aspectRatio");
|
|
50
|
+
fetch(value).then((res) => res.blob()).then((blob) => {
|
|
51
|
+
if (blob.type.includes("svg")) {
|
|
52
|
+
options.set("noWebp", true);
|
|
53
|
+
}
|
|
54
|
+
});
|
|
55
|
+
if (value && (!aspectRatio || aspectRatio === DEFAULT_ASPECT_RATIO)) {
|
|
56
|
+
return loadImage(value).then((img) => {
|
|
57
|
+
const possiblyUpdatedAspectRatio = options.get("aspectRatio");
|
|
58
|
+
if (options.get("image") === value && (!possiblyUpdatedAspectRatio || possiblyUpdatedAspectRatio === DEFAULT_ASPECT_RATIO)) {
|
|
59
|
+
if (img.width && img.height) {
|
|
60
|
+
options.set("aspectRatio", round(img.height / img.width));
|
|
61
|
+
options.set("height", img.height);
|
|
62
|
+
options.set("width", img.width);
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
});
|
|
66
|
+
}
|
|
67
|
+
}
|
|
22
68
|
},
|
|
23
69
|
{
|
|
24
70
|
name: "backgroundSize",
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
function removeProtocol(path) {
|
|
2
|
+
return path.replace(/http(s)?:/, "");
|
|
3
|
+
}
|
|
4
|
+
function updateQueryParam(uri = "", key, value) {
|
|
5
|
+
const re = new RegExp("([?&])" + key + "=.*?(&|$)", "i");
|
|
6
|
+
const separator = uri.indexOf("?") !== -1 ? "&" : "?";
|
|
7
|
+
if (uri.match(re)) {
|
|
8
|
+
return uri.replace(re, "$1" + key + "=" + encodeURIComponent(value) + "$2");
|
|
9
|
+
}
|
|
10
|
+
return uri + separator + key + "=" + encodeURIComponent(value);
|
|
11
|
+
}
|
|
12
|
+
function getShopifyImageUrl(src, size) {
|
|
13
|
+
if (!src || !(src == null ? void 0 : src.match(/cdn\.shopify\.com/)) || !size) {
|
|
14
|
+
return src;
|
|
15
|
+
}
|
|
16
|
+
if (size === "master") {
|
|
17
|
+
return removeProtocol(src);
|
|
18
|
+
}
|
|
19
|
+
const match = src.match(/(_\d+x(\d+)?)?(\.(jpg|jpeg|gif|png|bmp|bitmap|tiff|tif)(\?v=\d+)?)/i);
|
|
20
|
+
if (match) {
|
|
21
|
+
const prefix = src.split(match[0]);
|
|
22
|
+
const suffix = match[3];
|
|
23
|
+
const useSize = size.match("x") ? size : `${size}x`;
|
|
24
|
+
return removeProtocol(`${prefix[0]}_${useSize}${suffix}`);
|
|
25
|
+
}
|
|
26
|
+
return null;
|
|
27
|
+
}
|
|
28
|
+
function getSrcSet(url) {
|
|
29
|
+
if (!url) {
|
|
30
|
+
return url;
|
|
31
|
+
}
|
|
32
|
+
const sizes = [100, 200, 400, 800, 1200, 1600, 2e3];
|
|
33
|
+
if (url.match(/builder\.io/)) {
|
|
34
|
+
let srcUrl = url;
|
|
35
|
+
const widthInSrc = Number(url.split("?width=")[1]);
|
|
36
|
+
if (!isNaN(widthInSrc)) {
|
|
37
|
+
srcUrl = `${srcUrl} ${widthInSrc}w`;
|
|
38
|
+
}
|
|
39
|
+
return sizes.filter((size) => size !== widthInSrc).map((size) => `${updateQueryParam(url, "width", size)} ${size}w`).concat([srcUrl]).join(", ");
|
|
40
|
+
}
|
|
41
|
+
if (url.match(/cdn\.shopify\.com/)) {
|
|
42
|
+
return sizes.map((size) => [getShopifyImageUrl(url, `${size}x${size}`), size]).filter(([sizeUrl]) => !!sizeUrl).map(([sizeUrl, size]) => `${sizeUrl} ${size}w`).concat([url]).join(", ");
|
|
43
|
+
}
|
|
44
|
+
return url;
|
|
45
|
+
}
|
|
46
|
+
export {
|
|
47
|
+
getSrcSet
|
|
48
|
+
};
|
|
@@ -1,11 +1,40 @@
|
|
|
1
1
|
import { Show } from "solid-js";
|
|
2
|
+
import { createMutable } from "solid-js/store";
|
|
2
3
|
import { css } from "solid-styled-components";
|
|
4
|
+
import { getSrcSet } from "./image.helpers";
|
|
3
5
|
|
|
4
6
|
function Image(props) {
|
|
7
|
+
const state = createMutable({
|
|
8
|
+
get srcSetToUse() {
|
|
9
|
+
const imageToUse = props.image || props.src;
|
|
10
|
+
const url = imageToUse;
|
|
11
|
+
|
|
12
|
+
if (!url || // We can auto add srcset for cdn.builder.io and shopify
|
|
13
|
+
// images, otherwise you can supply this prop manually
|
|
14
|
+
!(url.match(/builder\.io/) || url.match(/cdn\.shopify\.com/))) {
|
|
15
|
+
return props.srcset;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
if (props.srcset && props.image?.includes("builder.io/api/v1/image")) {
|
|
19
|
+
if (!props.srcset.includes(props.image.split("?")[0])) {
|
|
20
|
+
console.debug("Removed given srcset");
|
|
21
|
+
return getSrcSet(url);
|
|
22
|
+
}
|
|
23
|
+
} else if (props.image && !props.srcset) {
|
|
24
|
+
return getSrcSet(url);
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
return getSrcSet(url);
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
});
|
|
5
31
|
return <div class={css({
|
|
6
32
|
position: "relative"
|
|
7
33
|
})}>
|
|
8
34
|
<picture>
|
|
35
|
+
<Show when={state.srcSetToUse?.match(/builder\.io/) && !props.noWebp}>
|
|
36
|
+
<source type="image/webp" srcset={state.srcSetToUse?.replace(/\?/g, "?format=webp&")} />
|
|
37
|
+
</Show>
|
|
9
38
|
<img class={"builder-image" + (props.className ? " " + props.className : "") + " " + css({
|
|
10
39
|
opacity: "1",
|
|
11
40
|
transition: "opacity 0.2s ease-in-out",
|
|
@@ -17,8 +46,8 @@ function Image(props) {
|
|
|
17
46
|
})} loading="lazy" alt={props.altText} role={props.altText ? "presentation" : undefined} style={{
|
|
18
47
|
"object-position": props.backgroundSize || "center",
|
|
19
48
|
"object-fit": props.backgroundSize || "cover"
|
|
20
|
-
}} src={props.image} srcset={
|
|
21
|
-
<source srcset={
|
|
49
|
+
}} src={props.image} srcset={state.srcSetToUse} sizes={props.sizes} />
|
|
50
|
+
<source srcset={state.srcSetToUse} />
|
|
22
51
|
</picture>
|
|
23
52
|
<Show when={props.aspectRatio && !(props.fitContent && props.builderBlock?.children?.length)}>
|
|
24
53
|
<div class={"builder-image-sizer " + css({
|
|
@@ -26,6 +55,7 @@ function Image(props) {
|
|
|
26
55
|
pointerEvents: "none",
|
|
27
56
|
fontSize: "0"
|
|
28
57
|
})} style={{
|
|
58
|
+
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
|
29
59
|
"padding-top": props.aspectRatio * 100 + "%"
|
|
30
60
|
}}></div>
|
|
31
61
|
</Show>
|
|
@@ -1,7 +1,8 @@
|
|
|
1
|
-
import { useContext, onMount } from "solid-js";
|
|
1
|
+
import { useContext, onMount, on, createEffect } from "solid-js";
|
|
2
2
|
import { createMutable } from "solid-js/store";
|
|
3
3
|
import RenderContent from "../../components/render-content/render-content.jsx";
|
|
4
4
|
import BuilderContext from "../../context/builder.context";
|
|
5
|
+
import { getContent } from "../../functions/get-content/index.js";
|
|
5
6
|
|
|
6
7
|
function Symbol(props) {
|
|
7
8
|
const state = createMutable({
|
|
@@ -12,10 +13,37 @@ function Symbol(props) {
|
|
|
12
13
|
onMount(() => {
|
|
13
14
|
state.content = props.symbol?.content;
|
|
14
15
|
});
|
|
16
|
+
|
|
17
|
+
function onUpdateFn_0() {
|
|
18
|
+
const symbolToUse = props.symbol;
|
|
19
|
+
/**
|
|
20
|
+
* If:
|
|
21
|
+
* - we have a symbol prop
|
|
22
|
+
* - yet it does not have any content
|
|
23
|
+
* - and we have not already stored content from before
|
|
24
|
+
* - and it has a model name
|
|
25
|
+
*
|
|
26
|
+
* then we want to re-fetch the symbol content.
|
|
27
|
+
*/
|
|
28
|
+
|
|
29
|
+
if (symbolToUse && !symbolToUse.content && !state.content && symbolToUse.model) {
|
|
30
|
+
getContent({
|
|
31
|
+
model: symbolToUse.model,
|
|
32
|
+
apiKey: builderContext.apiKey,
|
|
33
|
+
query: {
|
|
34
|
+
id: symbolToUse.entry
|
|
35
|
+
}
|
|
36
|
+
}).then(response => {
|
|
37
|
+
state.content = response;
|
|
38
|
+
});
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
createEffect(on(() => [props.symbol?.content, props.symbol?.model, props.symbol?.entry, state.content], onUpdateFn_0));
|
|
15
43
|
return <div class={state.className} {...props.attributes} dataSet={{
|
|
16
44
|
class: state.className
|
|
17
45
|
}}>
|
|
18
|
-
<RenderContent apiKey={builderContext.apiKey} context={builderContext.context} data={{ ...props.symbol?.data,
|
|
46
|
+
<RenderContent apiKey={builderContext.apiKey} context={builderContext.context} customComponents={Object.values(builderContext.registeredComponents)} data={{ ...props.symbol?.data,
|
|
19
47
|
...builderContext.state,
|
|
20
48
|
...props.symbol?.content?.data?.state
|
|
21
49
|
}} model={props.symbol?.model} content={state.content}></RenderContent>
|
|
@@ -8,7 +8,7 @@ function Video(props) {
|
|
|
8
8
|
// Hack to get object fit to work as expected and
|
|
9
9
|
// not have the video overflow
|
|
10
10
|
"border-radius": 1
|
|
11
|
-
}}
|
|
11
|
+
}} src={props.video || "no-src"} poster={props.posterImage} autoPlay={props.autoPlay} muted={props.muted} controls={props.controls} loop={props.loop}></video>;
|
|
12
12
|
}
|
|
13
13
|
|
|
14
14
|
export default Video;
|
|
@@ -8,14 +8,21 @@ import { getBlockProperties } from "../../functions/get-block-properties.js";
|
|
|
8
8
|
import { getBlockStyles } from "../../functions/get-block-styles.js";
|
|
9
9
|
import { getBlockTag } from "../../functions/get-block-tag.js";
|
|
10
10
|
import { getProcessedBlock } from "../../functions/get-processed-block.js";
|
|
11
|
+
import { evaluate } from "../../functions/evaluate.js";
|
|
11
12
|
import BlockStyles from "./block-styles.jsx";
|
|
12
13
|
import { isEmptyHtmlElement } from "./render-block.helpers.js";
|
|
13
14
|
import RenderComponent from "./render-component.jsx";
|
|
15
|
+
import RenderRepeatedBlock from "./render-repeated-block.jsx";
|
|
14
16
|
|
|
15
17
|
function RenderBlock(props) {
|
|
16
18
|
const state = createMutable({
|
|
17
19
|
get component() {
|
|
18
|
-
const componentName =
|
|
20
|
+
const componentName = getProcessedBlock({
|
|
21
|
+
block: props.block,
|
|
22
|
+
state: builderContext.state,
|
|
23
|
+
context: builderContext.context,
|
|
24
|
+
evaluateBindings: false
|
|
25
|
+
}).component?.name;
|
|
19
26
|
|
|
20
27
|
if (!componentName) {
|
|
21
28
|
return null;
|
|
@@ -55,10 +62,11 @@ function RenderBlock(props) {
|
|
|
55
62
|
},
|
|
56
63
|
|
|
57
64
|
get useBlock() {
|
|
58
|
-
return getProcessedBlock({
|
|
65
|
+
return state.repeatItemData ? props.block : getProcessedBlock({
|
|
59
66
|
block: props.block,
|
|
60
67
|
state: builderContext.state,
|
|
61
|
-
context: builderContext.context
|
|
68
|
+
context: builderContext.context,
|
|
69
|
+
evaluateBindings: true
|
|
62
70
|
});
|
|
63
71
|
},
|
|
64
72
|
|
|
@@ -90,6 +98,14 @@ function RenderBlock(props) {
|
|
|
90
98
|
};
|
|
91
99
|
},
|
|
92
100
|
|
|
101
|
+
get renderComponentProps() {
|
|
102
|
+
return {
|
|
103
|
+
blockChildren: state.children,
|
|
104
|
+
componentRef: state.componentRef,
|
|
105
|
+
componentOptions: state.componentOptions
|
|
106
|
+
};
|
|
107
|
+
},
|
|
108
|
+
|
|
93
109
|
get children() {
|
|
94
110
|
// TO-DO: When should `canHaveChildren` dictate rendering?
|
|
95
111
|
// This is currently commented out because some Builder components (e.g. Box) do not have `canHaveChildren: true`,
|
|
@@ -98,28 +114,79 @@ function RenderBlock(props) {
|
|
|
98
114
|
return state.useBlock.children ?? [];
|
|
99
115
|
},
|
|
100
116
|
|
|
101
|
-
get
|
|
117
|
+
get childrenWithoutParentComponent() {
|
|
102
118
|
/**
|
|
103
119
|
* When there is no `componentRef`, there might still be children that need to be rendered. In this case,
|
|
104
|
-
* we render them outside of `componentRef
|
|
120
|
+
* we render them outside of `componentRef`.
|
|
121
|
+
* NOTE: We make sure not to render this if `repeatItemData` is non-null, because that means we are rendering an array of
|
|
122
|
+
* blocks, and the children will be repeated within those blocks.
|
|
105
123
|
*/
|
|
106
|
-
|
|
124
|
+
const shouldRenderChildrenOutsideRef = !state.componentRef && !state.repeatItemData;
|
|
125
|
+
return shouldRenderChildrenOutsideRef ? state.children : [];
|
|
126
|
+
},
|
|
127
|
+
|
|
128
|
+
get repeatItemData() {
|
|
129
|
+
/**
|
|
130
|
+
* we don't use `state.useBlock` here because the processing done within its logic includes evaluating the block's bindings,
|
|
131
|
+
* which will not work if there is a repeat.
|
|
132
|
+
*/
|
|
133
|
+
const {
|
|
134
|
+
repeat,
|
|
135
|
+
...blockWithoutRepeat
|
|
136
|
+
} = props.block;
|
|
137
|
+
|
|
138
|
+
if (!repeat?.collection) {
|
|
139
|
+
return undefined;
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
const itemsArray = evaluate({
|
|
143
|
+
code: repeat.collection,
|
|
144
|
+
state: builderContext.state,
|
|
145
|
+
context: builderContext.context
|
|
146
|
+
});
|
|
147
|
+
|
|
148
|
+
if (!Array.isArray(itemsArray)) {
|
|
149
|
+
return undefined;
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
const collectionName = repeat.collection.split(".").pop();
|
|
153
|
+
const itemNameToUse = repeat.itemName || (collectionName ? collectionName + "Item" : "item");
|
|
154
|
+
const repeatArray = itemsArray.map((item, index) => ({
|
|
155
|
+
context: { ...builderContext,
|
|
156
|
+
state: { ...builderContext.state,
|
|
157
|
+
$index: index,
|
|
158
|
+
$item: item,
|
|
159
|
+
[itemNameToUse]: item,
|
|
160
|
+
[`$${itemNameToUse}Index`]: index
|
|
161
|
+
}
|
|
162
|
+
},
|
|
163
|
+
block: blockWithoutRepeat
|
|
164
|
+
}));
|
|
165
|
+
return repeatArray;
|
|
107
166
|
}
|
|
108
167
|
|
|
109
168
|
});
|
|
110
169
|
const builderContext = useContext(BuilderContext);
|
|
111
|
-
return <Show fallback={<RenderComponent
|
|
170
|
+
return <Show fallback={<RenderComponent {...state.renderComponentProps}></RenderComponent>} when={state.shouldWrap}>
|
|
112
171
|
<Show fallback={<Dynamic {...state.attributes} component={state.tagName}></Dynamic>} when={!isEmptyHtmlElement(state.tagName)}>
|
|
113
172
|
<Dynamic {...state.attributes} component={state.tagName}>
|
|
114
|
-
<
|
|
115
|
-
|
|
173
|
+
<Show fallback={<RenderComponent {...state.renderComponentProps}></RenderComponent>} when={state.repeatItemData}>
|
|
174
|
+
<For each={state.repeatItemData}>
|
|
175
|
+
{(data, _index) => {
|
|
176
|
+
const index = _index();
|
|
177
|
+
|
|
178
|
+
return <RenderRepeatedBlock key={index} repeatContext={data.context} block={data.block}></RenderRepeatedBlock>;
|
|
179
|
+
}}
|
|
180
|
+
</For>
|
|
181
|
+
</Show>
|
|
182
|
+
<For each={state.childrenWithoutParentComponent}>
|
|
116
183
|
{(child, _index) => {
|
|
117
184
|
const index = _index();
|
|
118
185
|
|
|
119
186
|
return <RenderBlock key={"render-block-" + child.id} block={child}></RenderBlock>;
|
|
120
187
|
}}
|
|
121
188
|
</For>
|
|
122
|
-
<For each={state.
|
|
189
|
+
<For each={state.childrenWithoutParentComponent}>
|
|
123
190
|
{(child, _index) => {
|
|
124
191
|
const index = _index();
|
|
125
192
|
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import { Dynamic } from "solid-js/web";
|
|
2
|
+
import BuilderContext from "../../context/builder.context";
|
|
3
|
+
import RenderBlock from "./render-block.jsx";
|
|
4
|
+
|
|
5
|
+
function RenderRepeatedBlock(props) {
|
|
6
|
+
return <Dynamic value={{
|
|
7
|
+
get content() {
|
|
8
|
+
return props.repeatContext.content;
|
|
9
|
+
},
|
|
10
|
+
|
|
11
|
+
get state() {
|
|
12
|
+
return props.repeatContext.state;
|
|
13
|
+
},
|
|
14
|
+
|
|
15
|
+
get context() {
|
|
16
|
+
return props.repeatContext.context;
|
|
17
|
+
},
|
|
18
|
+
|
|
19
|
+
get apiKey() {
|
|
20
|
+
return props.repeatContext.apiKey;
|
|
21
|
+
},
|
|
22
|
+
|
|
23
|
+
get registeredComponents() {
|
|
24
|
+
return props.repeatContext.registeredComponents;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
}} component={BuilderContext.Provider}>
|
|
28
|
+
<RenderBlock block={props.block}></RenderBlock>
|
|
29
|
+
</Dynamic>;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
export default RenderRepeatedBlock;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { Show, onMount } from "solid-js";
|
|
1
|
+
import { Show, onMount, on, createEffect } from "solid-js";
|
|
2
2
|
import { Dynamic } from "solid-js/web";
|
|
3
3
|
import { createMutable } from "solid-js/store";
|
|
4
4
|
import { getDefaultRegisteredComponents } from "../../constants/builder-registered-components.js";
|
|
@@ -41,8 +41,8 @@ function RenderContent(props) {
|
|
|
41
41
|
};
|
|
42
42
|
},
|
|
43
43
|
|
|
44
|
-
get
|
|
45
|
-
return {};
|
|
44
|
+
get contextContext() {
|
|
45
|
+
return props.context || {};
|
|
46
46
|
},
|
|
47
47
|
|
|
48
48
|
get allRegisteredComponents() {
|
|
@@ -94,7 +94,7 @@ function RenderContent(props) {
|
|
|
94
94
|
if (jsCode) {
|
|
95
95
|
evaluate({
|
|
96
96
|
code: jsCode,
|
|
97
|
-
context: state.
|
|
97
|
+
context: state.contextContext,
|
|
98
98
|
state: state.contentState
|
|
99
99
|
});
|
|
100
100
|
}
|
|
@@ -107,7 +107,7 @@ function RenderContent(props) {
|
|
|
107
107
|
evalExpression(expression) {
|
|
108
108
|
return expression.replace(/{{([^}]+)}}/g, (_match, group) => evaluate({
|
|
109
109
|
code: group,
|
|
110
|
-
context: state.
|
|
110
|
+
context: state.contextContext,
|
|
111
111
|
state: state.contentState
|
|
112
112
|
}));
|
|
113
113
|
},
|
|
@@ -176,14 +176,14 @@ function RenderContent(props) {
|
|
|
176
176
|
|
|
177
177
|
if (isPreviewing()) {
|
|
178
178
|
if (props.model && previewingModelName() === props.model) {
|
|
179
|
-
const
|
|
180
|
-
const previewApiKey =
|
|
179
|
+
const searchParams = new URL(location.href).searchParams;
|
|
180
|
+
const previewApiKey = searchParams.get("apiKey") || searchParams.get("builder.space");
|
|
181
181
|
|
|
182
182
|
if (previewApiKey) {
|
|
183
183
|
getContent({
|
|
184
184
|
model: props.model,
|
|
185
185
|
apiKey: previewApiKey,
|
|
186
|
-
options: getBuilderSearchParams(convertSearchParamsToQueryObject(
|
|
186
|
+
options: getBuilderSearchParams(convertSearchParamsToQueryObject(searchParams))
|
|
187
187
|
}).then(content => {
|
|
188
188
|
if (content) {
|
|
189
189
|
state.overrideContent = content;
|
|
@@ -198,6 +198,24 @@ function RenderContent(props) {
|
|
|
198
198
|
state.emitStateUpdate();
|
|
199
199
|
}
|
|
200
200
|
});
|
|
201
|
+
|
|
202
|
+
function onUpdateFn_0() {
|
|
203
|
+
state.evaluateJsCode();
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
createEffect(on(() => [state.useContent?.data?.jsCode], onUpdateFn_0));
|
|
207
|
+
|
|
208
|
+
function onUpdateFn_1() {
|
|
209
|
+
state.runHttpRequests();
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
createEffect(on(() => [state.useContent?.data?.httpRequests], onUpdateFn_1));
|
|
213
|
+
|
|
214
|
+
function onUpdateFn_2() {
|
|
215
|
+
state.emitStateUpdate();
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
createEffect(on(() => [state.contentState], onUpdateFn_2));
|
|
201
219
|
return <Dynamic value={{
|
|
202
220
|
get content() {
|
|
203
221
|
return state.useContent;
|
|
@@ -208,7 +226,7 @@ function RenderContent(props) {
|
|
|
208
226
|
},
|
|
209
227
|
|
|
210
228
|
get context() {
|
|
211
|
-
return state.
|
|
229
|
+
return state.contextContext;
|
|
212
230
|
},
|
|
213
231
|
|
|
214
232
|
get apiKey() {
|
|
@@ -30,6 +30,8 @@ import { componentInfo as textComponentInfo } from "../blocks/text/component-inf
|
|
|
30
30
|
import { default as Text } from "../blocks/text/text.jsx";
|
|
31
31
|
import { componentInfo as videoComponentInfo } from "../blocks/video/component-info";
|
|
32
32
|
import { default as Video } from "../blocks/video/video.jsx";
|
|
33
|
+
import { componentInfo as embedComponentInfo } from "../blocks/embed/component-info";
|
|
34
|
+
import { default as embed } from "../blocks/embed/embed.jsx";
|
|
33
35
|
const getDefaultRegisteredComponents = () => [
|
|
34
36
|
__spreadValues({ component: Columns }, columnsComponentInfo),
|
|
35
37
|
__spreadValues({ component: Image }, imageComponentInfo),
|
|
@@ -38,7 +40,8 @@ const getDefaultRegisteredComponents = () => [
|
|
|
38
40
|
__spreadValues({ component: Symbol }, symbolComponentInfo),
|
|
39
41
|
__spreadValues({ component: Button }, buttonComponentInfo),
|
|
40
42
|
__spreadValues({ component: Section }, sectionComponentInfo),
|
|
41
|
-
__spreadValues({ component: Fragment }, fragmentComponentInfo)
|
|
43
|
+
__spreadValues({ component: Fragment }, fragmentComponentInfo),
|
|
44
|
+
__spreadValues({ component: embed }, embedComponentInfo)
|
|
42
45
|
];
|
|
43
46
|
export {
|
|
44
47
|
getDefaultRegisteredComponents
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
const camelCaseToDashCase = (str = "") => str.replace(/[A-Z]/g, (match) => "-" + match.toLowerCase());
|
|
2
|
+
const convertStyleObject = (obj) => {
|
|
3
|
+
if (!obj) {
|
|
4
|
+
return obj;
|
|
5
|
+
}
|
|
6
|
+
const newObj = {};
|
|
7
|
+
for (const key in obj) {
|
|
8
|
+
newObj[camelCaseToDashCase(key)] = obj[key];
|
|
9
|
+
}
|
|
10
|
+
return newObj;
|
|
11
|
+
};
|
|
12
|
+
export {
|
|
13
|
+
convertStyleObject
|
|
14
|
+
};
|
|
@@ -14,27 +14,19 @@ var __spreadValues = (a, b) => {
|
|
|
14
14
|
}
|
|
15
15
|
return a;
|
|
16
16
|
};
|
|
17
|
-
import {
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
if (!obj) {
|
|
21
|
-
return obj;
|
|
22
|
-
}
|
|
23
|
-
const newObj = {};
|
|
24
|
-
for (const key in obj) {
|
|
25
|
-
newObj[camelCaseToDashCase(key)] = obj[key];
|
|
26
|
-
}
|
|
27
|
-
return newObj;
|
|
28
|
-
};
|
|
17
|
+
import { getMaxWidthQueryForSize } from "../constants/device-sizes.js";
|
|
18
|
+
import { convertStyleObject } from "./convert-style-object.js";
|
|
19
|
+
import { sanitizeBlockStyles } from "./sanitize-styles.js";
|
|
29
20
|
function getBlockStyles(block) {
|
|
30
21
|
var _a, _b, _c, _d, _e;
|
|
31
|
-
const styles = __spreadValues({}, convertStyleObject((_a = block.responsiveStyles) == null ? void 0 : _a.large));
|
|
22
|
+
const styles = __spreadValues(__spreadValues({}, convertStyleObject((_a = block.responsiveStyles) == null ? void 0 : _a.large)), block.styles);
|
|
32
23
|
if ((_b = block.responsiveStyles) == null ? void 0 : _b.medium) {
|
|
33
|
-
styles[
|
|
24
|
+
styles[getMaxWidthQueryForSize("medium")] = convertStyleObject((_c = block.responsiveStyles) == null ? void 0 : _c.medium);
|
|
34
25
|
}
|
|
35
26
|
if ((_d = block.responsiveStyles) == null ? void 0 : _d.small) {
|
|
36
|
-
styles[
|
|
27
|
+
styles[getMaxWidthQueryForSize("small")] = convertStyleObject((_e = block.responsiveStyles) == null ? void 0 : _e.small);
|
|
37
28
|
}
|
|
29
|
+
sanitizeBlockStyles(styles);
|
|
38
30
|
return styles;
|
|
39
31
|
}
|
|
40
32
|
export {
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
const handleABTesting = (item, testGroups) => {
|
|
2
|
+
if (item.variations && Object.keys(item.variations).length) {
|
|
3
|
+
const testGroup = item.id ? testGroups[item.id] : void 0;
|
|
4
|
+
const variationValue = testGroup ? item.variations[testGroup] : void 0;
|
|
5
|
+
if (testGroup && variationValue) {
|
|
6
|
+
item.data = variationValue.data;
|
|
7
|
+
item.testVariationId = variationValue.id;
|
|
8
|
+
item.testVariationName = variationValue.name;
|
|
9
|
+
} else {
|
|
10
|
+
let n = 0;
|
|
11
|
+
const random = Math.random();
|
|
12
|
+
let set = false;
|
|
13
|
+
for (const id in item.variations) {
|
|
14
|
+
const variation = item.variations[id];
|
|
15
|
+
const testRatio = variation.testRatio;
|
|
16
|
+
n += testRatio;
|
|
17
|
+
if (random < n) {
|
|
18
|
+
const variationName = variation.name || (variation.id === item.id ? "Default variation" : "");
|
|
19
|
+
set = true;
|
|
20
|
+
Object.assign(item, {
|
|
21
|
+
data: variation.data,
|
|
22
|
+
testVariationId: variation.id,
|
|
23
|
+
testVariationName: variationName
|
|
24
|
+
});
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
if (!set) {
|
|
28
|
+
Object.assign(item, {
|
|
29
|
+
testVariationId: item.id,
|
|
30
|
+
testVariationName: "Default"
|
|
31
|
+
});
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
};
|
|
36
|
+
export {
|
|
37
|
+
handleABTesting
|
|
38
|
+
};
|
|
@@ -37,20 +37,10 @@ var __async = (__this, __arguments, generator) => {
|
|
|
37
37
|
step((generator = generator.apply(__this, __arguments)).next());
|
|
38
38
|
});
|
|
39
39
|
};
|
|
40
|
+
import { flatten } from "../../helpers/flatten.js";
|
|
40
41
|
import { getFetch } from "../get-fetch.js";
|
|
42
|
+
import { handleABTesting } from "./ab-testing.js";
|
|
41
43
|
const fetch$ = getFetch();
|
|
42
|
-
function flatten(object, path = null, separator = ".") {
|
|
43
|
-
return Object.keys(object).reduce((acc, key) => {
|
|
44
|
-
const value = object[key];
|
|
45
|
-
const newPath = [path, key].filter(Boolean).join(separator);
|
|
46
|
-
const isObject = [
|
|
47
|
-
typeof value === "object",
|
|
48
|
-
value !== null,
|
|
49
|
-
!(Array.isArray(value) && value.length === 0)
|
|
50
|
-
].every(Boolean);
|
|
51
|
-
return isObject ? __spreadValues(__spreadValues({}, acc), flatten(value, newPath, separator)) : __spreadProps(__spreadValues({}, acc), { [newPath]: value });
|
|
52
|
-
}, {});
|
|
53
|
-
}
|
|
54
44
|
function getContent(options) {
|
|
55
45
|
return __async(this, null, function* () {
|
|
56
46
|
return (yield getAllContent(__spreadProps(__spreadValues({}, options), { limit: 1 }))).results[0] || null;
|
|
@@ -83,50 +73,15 @@ const generateContentUrl = (options) => {
|
|
|
83
73
|
}
|
|
84
74
|
return url;
|
|
85
75
|
};
|
|
86
|
-
const handleABTesting = (content, testGroups) => {
|
|
87
|
-
for (const item of content.results) {
|
|
88
|
-
if (item.variations && Object.keys(item.variations).length) {
|
|
89
|
-
const testGroup = testGroups[item.id];
|
|
90
|
-
const variationValue = item.variations[testGroup];
|
|
91
|
-
if (testGroup && variationValue) {
|
|
92
|
-
item.data = variationValue.data;
|
|
93
|
-
item.testVariationId = variationValue.id;
|
|
94
|
-
item.testVariationName = variationValue.name;
|
|
95
|
-
} else {
|
|
96
|
-
let n = 0;
|
|
97
|
-
const random = Math.random();
|
|
98
|
-
let set = false;
|
|
99
|
-
for (const id in item.variations) {
|
|
100
|
-
const variation = item.variations[id];
|
|
101
|
-
const testRatio = variation.testRatio;
|
|
102
|
-
n += testRatio;
|
|
103
|
-
if (random < n) {
|
|
104
|
-
const variationName = variation.name || (variation.id === item.id ? "Default variation" : "");
|
|
105
|
-
set = true;
|
|
106
|
-
Object.assign(item, {
|
|
107
|
-
data: variation.data,
|
|
108
|
-
testVariationId: variation.id,
|
|
109
|
-
testVariationName: variationName
|
|
110
|
-
});
|
|
111
|
-
}
|
|
112
|
-
}
|
|
113
|
-
if (!set) {
|
|
114
|
-
Object.assign(item, {
|
|
115
|
-
testVariationId: item.id,
|
|
116
|
-
testVariationName: "Default"
|
|
117
|
-
});
|
|
118
|
-
}
|
|
119
|
-
}
|
|
120
|
-
}
|
|
121
|
-
}
|
|
122
|
-
};
|
|
123
76
|
function getAllContent(options) {
|
|
124
77
|
return __async(this, null, function* () {
|
|
125
78
|
const url = generateContentUrl(options);
|
|
126
79
|
const fetch = yield fetch$;
|
|
127
80
|
const content = yield fetch(url.href).then((res) => res.json());
|
|
128
81
|
if (options.testGroups) {
|
|
129
|
-
|
|
82
|
+
for (const item of content.results) {
|
|
83
|
+
handleABTesting(item, options.testGroups);
|
|
84
|
+
}
|
|
130
85
|
}
|
|
131
86
|
return content;
|
|
132
87
|
});
|
|
File without changes
|
|
@@ -20,9 +20,11 @@ var __spreadProps = (a, b) => __defProps(a, __getOwnPropDescs(b));
|
|
|
20
20
|
import { evaluate } from "./evaluate.js";
|
|
21
21
|
import { set } from "./set.js";
|
|
22
22
|
import { transformBlock } from "./transform-block.js";
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
23
|
+
const evaluateBindings = ({
|
|
24
|
+
block,
|
|
25
|
+
context,
|
|
26
|
+
state
|
|
27
|
+
}) => {
|
|
26
28
|
if (!block.bindings) {
|
|
27
29
|
return block;
|
|
28
30
|
}
|
|
@@ -32,14 +34,19 @@ function getProcessedBlock(options) {
|
|
|
32
34
|
});
|
|
33
35
|
for (const binding in block.bindings) {
|
|
34
36
|
const expression = block.bindings[binding];
|
|
35
|
-
const value = evaluate({
|
|
36
|
-
code: expression,
|
|
37
|
-
state,
|
|
38
|
-
context
|
|
39
|
-
});
|
|
37
|
+
const value = evaluate({ code: expression, state, context });
|
|
40
38
|
set(copied, binding, value);
|
|
41
39
|
}
|
|
42
40
|
return copied;
|
|
41
|
+
};
|
|
42
|
+
function getProcessedBlock(options) {
|
|
43
|
+
const { state, context } = options;
|
|
44
|
+
const block = transformBlock(options.block);
|
|
45
|
+
if (evaluateBindings) {
|
|
46
|
+
return evaluateBindings({ block, state, context });
|
|
47
|
+
} else {
|
|
48
|
+
return block;
|
|
49
|
+
}
|
|
43
50
|
}
|
|
44
51
|
export {
|
|
45
52
|
getProcessedBlock
|
|
@@ -20,7 +20,8 @@ test("Can process bindings", () => {
|
|
|
20
20
|
const processed = getProcessedBlock({
|
|
21
21
|
block,
|
|
22
22
|
context: {},
|
|
23
|
-
state: { test: "hello" }
|
|
23
|
+
state: { test: "hello" },
|
|
24
|
+
evaluateBindings: true
|
|
24
25
|
});
|
|
25
26
|
expect(processed).not.toEqual(block);
|
|
26
27
|
expect((_a = processed.properties) == null ? void 0 : _a.foo).toEqual("baz");
|
|
@@ -29,7 +29,6 @@ var __objRest = (source, exclude) => {
|
|
|
29
29
|
}
|
|
30
30
|
return target;
|
|
31
31
|
};
|
|
32
|
-
import { fastClone } from "./fast-clone.js";
|
|
33
32
|
const components = [];
|
|
34
33
|
function registerComponent(component, info) {
|
|
35
34
|
components.push(__spreadValues({ component }, info));
|
|
@@ -38,31 +37,34 @@ function registerComponent(component, info) {
|
|
|
38
37
|
}
|
|
39
38
|
const createRegisterComponentMessage = (_a) => {
|
|
40
39
|
var _b = _a, {
|
|
41
|
-
component
|
|
40
|
+
component: _
|
|
42
41
|
} = _b, info = __objRest(_b, [
|
|
43
42
|
"component"
|
|
44
43
|
]);
|
|
45
44
|
return {
|
|
46
45
|
type: "builder.registerComponent",
|
|
47
|
-
data: prepareComponentInfoToSend(
|
|
46
|
+
data: prepareComponentInfoToSend(info)
|
|
48
47
|
};
|
|
49
48
|
};
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
49
|
+
const fastClone = (obj) => JSON.parse(JSON.stringify(obj));
|
|
50
|
+
const serializeValue = (value) => typeof value === "function" ? serializeFn(value) : fastClone(value);
|
|
51
|
+
const serializeFn = (fnValue) => {
|
|
52
|
+
const fnStr = fnValue.toString().trim();
|
|
53
|
+
const appendFunction = !fnStr.startsWith("function") && !fnStr.startsWith("(");
|
|
54
|
+
return `return (${appendFunction ? "function " : ""}${fnStr}).apply(this, arguments)`;
|
|
55
|
+
};
|
|
56
|
+
const prepareComponentInfoToSend = (_c) => {
|
|
57
|
+
var _d = _c, {
|
|
58
|
+
inputs
|
|
59
|
+
} = _d, info = __objRest(_d, [
|
|
60
|
+
"inputs"
|
|
61
|
+
]);
|
|
62
|
+
return __spreadProps(__spreadValues({}, fastClone(info)), {
|
|
63
|
+
inputs: inputs == null ? void 0 : inputs.map((input) => Object.entries(input).reduce((acc, [key, value]) => __spreadProps(__spreadValues({}, acc), {
|
|
64
|
+
[key]: serializeValue(value)
|
|
65
|
+
}), {}))
|
|
64
66
|
});
|
|
65
|
-
}
|
|
67
|
+
};
|
|
66
68
|
export {
|
|
67
69
|
components,
|
|
68
70
|
createRegisterComponentMessage,
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
var __defProp = Object.defineProperty;
|
|
2
|
+
var __defProps = Object.defineProperties;
|
|
3
|
+
var __getOwnPropDescs = Object.getOwnPropertyDescriptors;
|
|
4
|
+
var __getOwnPropSymbols = Object.getOwnPropertySymbols;
|
|
5
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
6
|
+
var __propIsEnum = Object.prototype.propertyIsEnumerable;
|
|
7
|
+
var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
|
|
8
|
+
var __spreadValues = (a, b) => {
|
|
9
|
+
for (var prop in b || (b = {}))
|
|
10
|
+
if (__hasOwnProp.call(b, prop))
|
|
11
|
+
__defNormalProp(a, prop, b[prop]);
|
|
12
|
+
if (__getOwnPropSymbols)
|
|
13
|
+
for (var prop of __getOwnPropSymbols(b)) {
|
|
14
|
+
if (__propIsEnum.call(b, prop))
|
|
15
|
+
__defNormalProp(a, prop, b[prop]);
|
|
16
|
+
}
|
|
17
|
+
return a;
|
|
18
|
+
};
|
|
19
|
+
var __spreadProps = (a, b) => __defProps(a, __getOwnPropDescs(b));
|
|
20
|
+
function flatten(object, path = null, separator = ".") {
|
|
21
|
+
return Object.keys(object).reduce((acc, key) => {
|
|
22
|
+
const value = object[key];
|
|
23
|
+
const newPath = [path, key].filter(Boolean).join(separator);
|
|
24
|
+
const isObject = [
|
|
25
|
+
typeof value === "object",
|
|
26
|
+
value !== null,
|
|
27
|
+
!(Array.isArray(value) && value.length === 0)
|
|
28
|
+
].every(Boolean);
|
|
29
|
+
return isObject ? __spreadValues(__spreadValues({}, acc), flatten(value, newPath, separator)) : __spreadProps(__spreadValues({}, acc), { [newPath]: value });
|
|
30
|
+
}, {});
|
|
31
|
+
}
|
|
32
|
+
export {
|
|
33
|
+
flatten
|
|
34
|
+
};
|