@builder.io/sdk-solid 0.0.8-2 → 0.0.8-22
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/README.md +5 -1
- package/package.json +11 -7
- package/src/blocks/button/button.jsx +6 -1
- package/src/blocks/columns/columns.jsx +7 -7
- 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 +31 -34
- package/src/blocks/embed/helpers.js +9 -0
- package/src/blocks/form/form.jsx +3 -3
- package/src/blocks/image/component-info.js +47 -1
- package/src/blocks/image/image.helpers.js +48 -0
- package/src/blocks/image/image.jsx +43 -7
- package/src/blocks/symbol/component-info.js +1 -0
- package/src/blocks/symbol/symbol.jsx +32 -3
- package/src/blocks/text/text.jsx +1 -1
- package/src/blocks/video/video.jsx +25 -2
- package/src/components/render-block/block-styles.jsx +31 -23
- package/src/components/render-block/render-block.helpers.js +23 -0
- package/src/components/render-block/render-block.jsx +123 -36
- package/src/components/render-block/render-component.jsx +27 -0
- package/src/components/render-block/render-repeated-block.jsx +32 -0
- package/src/components/render-block/types.js +0 -0
- package/src/components/render-blocks.jsx +12 -2
- package/src/components/render-content/components/render-styles.jsx +1 -1
- package/src/components/render-content/index.js +4 -0
- package/src/components/render-content/render-content.jsx +79 -28
- package/src/components/render-inlined-styles.jsx +2 -1
- package/src/constants/builder-registered-components.js +48 -0
- package/src/constants/device-sizes.js +3 -21
- package/src/context/builder.context.js +2 -1
- package/src/functions/camel-to-kebab-case.js +4 -0
- package/src/functions/convert-style-object.js +14 -0
- package/src/functions/get-block-component-options.js +6 -1
- package/src/functions/get-block-styles.js +7 -15
- package/src/functions/get-builder-search-params/index.js +12 -1
- package/src/functions/get-content/ab-testing.js +38 -0
- package/src/functions/get-content/index.js +16 -58
- 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 +45 -26
- package/src/functions/sanitize-styles.js +5 -0
- package/src/helpers/css.js +12 -0
- package/src/helpers/flatten.js +34 -0
- package/src/index-helpers/blocks-exports.js +11 -9
- package/src/solid-index.jsx +5 -0
- package/src/types/components.js +0 -0
- package/src/types/element.js +0 -0
- package/src/blocks/button/button.lite.tsx +0 -20
- package/src/blocks/button/index.js +0 -7
- package/src/blocks/columns/columns.lite.tsx +0 -102
- package/src/blocks/columns/index.js +0 -7
- package/src/blocks/custom-code/custom-code.lite.tsx +0 -67
- package/src/blocks/custom-code/index.js +0 -7
- package/src/blocks/embed/embed.lite.tsx +0 -59
- package/src/blocks/embed/index.js +0 -7
- package/src/blocks/form/form.lite.tsx +0 -293
- package/src/blocks/form/index.js +0 -7
- package/src/blocks/fragment/fragment.lite.tsx +0 -5
- package/src/blocks/fragment/index.js +0 -7
- package/src/blocks/image/image.lite.tsx +0 -83
- package/src/blocks/image/index.js +0 -7
- package/src/blocks/img/img.lite.tsx +0 -18
- package/src/blocks/img/index.js +0 -7
- package/src/blocks/input/index.js +0 -7
- package/src/blocks/input/input.lite.tsx +0 -20
- package/src/blocks/raw-text/index.js +0 -7
- package/src/blocks/raw-text/raw-text.lite.tsx +0 -10
- package/src/blocks/section/index.js +0 -7
- package/src/blocks/section/section.lite.tsx +0 -18
- package/src/blocks/select/index.js +0 -7
- package/src/blocks/select/select.lite.tsx +0 -28
- package/src/blocks/submit-button/index.js +0 -7
- package/src/blocks/submit-button/submit-button.lite.tsx +0 -9
- package/src/blocks/symbol/index.js +0 -7
- package/src/blocks/symbol/symbol.lite.tsx +0 -39
- package/src/blocks/text/index.js +0 -7
- package/src/blocks/text/text.lite.tsx +0 -5
- package/src/blocks/textarea/index.js +0 -7
- package/src/blocks/textarea/textarea.lite.tsx +0 -13
- package/src/blocks/video/index.js +0 -7
- package/src/blocks/video/video.lite.tsx +0 -26
- package/src/components/error-boundary.jsx +0 -5
- package/src/components/error-boundary.lite.tsx +0 -5
- package/src/components/render-block/block-styles.lite.tsx +0 -38
- package/src/components/render-block/render-block.lite.tsx +0 -119
- package/src/components/render-blocks.lite.tsx +0 -75
- package/src/components/render-content/components/render-styles.lite.tsx +0 -76
- package/src/components/render-content/render-content.lite.tsx +0 -232
- package/src/components/render-inlined-styles.lite.tsx +0 -26
- package/src/functions/macro-eval.js +0 -5
- package/src/functions/previewing-model-name.js +0 -11
package/README.md
CHANGED
package/package.json
CHANGED
|
@@ -1,23 +1,27 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@builder.io/sdk-solid",
|
|
3
|
-
"version": "0.0.8-
|
|
4
|
-
"type": "module",
|
|
3
|
+
"version": "0.0.8-22",
|
|
5
4
|
"description": "",
|
|
6
|
-
"
|
|
7
|
-
"main": "src/index.
|
|
5
|
+
"type": "module",
|
|
6
|
+
"main": "./src/solid-index.jsx",
|
|
7
|
+
"module": "./src/solid-index.jsx",
|
|
8
8
|
"exports": {
|
|
9
|
-
".": "./src/index.
|
|
9
|
+
".": "./src/solid-index.jsx"
|
|
10
10
|
},
|
|
11
11
|
"scripts": {
|
|
12
12
|
"release:dev": "npm version prerelease --no-git-tag-version && npm publish --tag dev --access public"
|
|
13
13
|
},
|
|
14
14
|
"dependencies": {
|
|
15
|
+
"node-fetch": "^2.6.7",
|
|
15
16
|
"solid-styled-components": "^0.27.6"
|
|
16
17
|
},
|
|
17
18
|
"peerDependencies": {
|
|
18
|
-
"solid-js": "^1.3
|
|
19
|
+
"solid-js": "^1.4.3"
|
|
19
20
|
},
|
|
20
21
|
"devDependencies": {
|
|
21
|
-
"solid
|
|
22
|
+
"babel-preset-solid": "^1.3.17",
|
|
23
|
+
"solid-js": "^1.4.3",
|
|
24
|
+
"vite": "^2.9.8",
|
|
25
|
+
"vite-plugin-solid": "^2.2.6"
|
|
22
26
|
}
|
|
23
27
|
}
|
|
@@ -1,8 +1,13 @@
|
|
|
1
1
|
import { Show } from "solid-js";
|
|
2
|
+
import { css } from "solid-styled-components";
|
|
2
3
|
|
|
3
4
|
function Button(props) {
|
|
4
5
|
return <>
|
|
5
|
-
<Show
|
|
6
|
+
<Show fallback={<button class={css({
|
|
7
|
+
all: "unset"
|
|
8
|
+
})} {...props.attributes}>
|
|
9
|
+
{props.text}
|
|
10
|
+
</button>} when={props.link}>
|
|
6
11
|
<a {...props.attributes} role="button" href={props.link} target={props.openLinkInNewTab ? "_blank" : undefined}>
|
|
7
12
|
{props.text}
|
|
8
13
|
</a>
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { For } from "solid-js";
|
|
2
2
|
import { createMutable } from "solid-js/store";
|
|
3
3
|
import { css } from "solid-styled-components";
|
|
4
|
-
import RenderBlocks from "../../components/render-blocks";
|
|
4
|
+
import RenderBlocks from "../../components/render-blocks.jsx";
|
|
5
5
|
|
|
6
6
|
function Columns(props) {
|
|
7
7
|
const state = createMutable({
|
|
@@ -51,11 +51,11 @@ function Columns(props) {
|
|
|
51
51
|
}
|
|
52
52
|
|
|
53
53
|
});
|
|
54
|
-
return <div class={css({
|
|
54
|
+
return <div class={"builder-columns " + css({
|
|
55
55
|
display: "flex",
|
|
56
56
|
alignItems: "stretch",
|
|
57
57
|
lineHeight: "normal",
|
|
58
|
-
"@media (max-width:
|
|
58
|
+
"@media (max-width: 991px)": {
|
|
59
59
|
flexDirection: "var(--flex-dir-tablet)"
|
|
60
60
|
},
|
|
61
61
|
"@media (max-width: 639px)": {
|
|
@@ -66,9 +66,9 @@ function Columns(props) {
|
|
|
66
66
|
{(column, _index) => {
|
|
67
67
|
const index = _index();
|
|
68
68
|
|
|
69
|
-
return <div class={css({
|
|
69
|
+
return <div class={"builder-column " + css({
|
|
70
70
|
flexGrow: "1",
|
|
71
|
-
"@media (max-width:
|
|
71
|
+
"@media (max-width: 991px)": {
|
|
72
72
|
width: "var(--column-width-tablet) !important",
|
|
73
73
|
marginLeft: "var(--column-margin-left-tablet) !important"
|
|
74
74
|
},
|
|
@@ -80,8 +80,8 @@ function Columns(props) {
|
|
|
80
80
|
width: state.getColumnCssWidth(index),
|
|
81
81
|
"margin-left": `${index === 0 ? 0 : state.getGutterSize()}px`,
|
|
82
82
|
...state.columnCssVars
|
|
83
|
-
}}>
|
|
84
|
-
<RenderBlocks blocks={column.blocks}></RenderBlocks>
|
|
83
|
+
}} key={index}>
|
|
84
|
+
<RenderBlocks blocks={column.blocks} path={`component.options.columns.${index}.blocks`} parent={props.builderBlock.id}></RenderBlocks>
|
|
85
85
|
</div>;
|
|
86
86
|
}}
|
|
87
87
|
</For>
|
|
@@ -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,3 +1,4 @@
|
|
|
1
|
+
import { onMount } from "solid-js";
|
|
1
2
|
import { createMutable } from "solid-js/store";
|
|
2
3
|
|
|
3
4
|
function CustomCode(props) {
|
|
@@ -8,7 +9,6 @@ function CustomCode(props) {
|
|
|
8
9
|
findAndRunScripts() {
|
|
9
10
|
// TODO: Move this function to standalone one in '@builder.io/utils'
|
|
10
11
|
if (elem && typeof window !== "undefined") {
|
|
11
|
-
/** @type {HTMLScriptElement[]} */
|
|
12
12
|
const scripts = elem.getElementsByTagName("script");
|
|
13
13
|
|
|
14
14
|
for (let i = 0; i < scripts.length; i++) {
|
|
@@ -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,51 +1,48 @@
|
|
|
1
|
+
import { on, createEffect } from "solid-js";
|
|
1
2
|
import { createMutable } from "solid-js/store";
|
|
3
|
+
import { isJsScript } from "./helpers";
|
|
2
4
|
|
|
3
5
|
function Embed(props) {
|
|
4
6
|
const state = createMutable({
|
|
5
7
|
scriptsInserted: [],
|
|
6
8
|
scriptsRun: [],
|
|
9
|
+
ranInitFn: false,
|
|
7
10
|
|
|
8
11
|
findAndRunScripts() {
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
const
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
state.
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
document.head.appendChild(newScript);
|
|
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
|
-
|
|
48
|
-
|
|
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));
|
|
45
|
+
return <div class="builder-embed" ref={elem} innerHTML={props.content}></div>;
|
|
49
46
|
}
|
|
50
47
|
|
|
51
48
|
export default Embed;
|
package/src/blocks/form/form.jsx
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { Show, For } from "solid-js";
|
|
2
2
|
import { createMutable } from "solid-js/store";
|
|
3
3
|
import { css } from "solid-styled-components";
|
|
4
|
-
import RenderBlock from "../../components/render-block/render-block";
|
|
4
|
+
import RenderBlock from "../../components/render-block/render-block.jsx";
|
|
5
5
|
import { isEditing } from "../../functions/is-editing.js";
|
|
6
6
|
|
|
7
7
|
function FormComponent(props) {
|
|
@@ -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}>
|
|
@@ -236,7 +236,7 @@ function FormComponent(props) {
|
|
|
236
236
|
<BuilderBlocks dataPath="sendingMessage" blocks={props.sendingMessage}></BuilderBlocks>
|
|
237
237
|
</Show>
|
|
238
238
|
<Show when={state.submissionState === "error" && state.responseData}>
|
|
239
|
-
<pre class={css({
|
|
239
|
+
<pre class={"builder-form-error-text " + css({
|
|
240
240
|
padding: "10px",
|
|
241
241
|
color: "red",
|
|
242
242
|
textAlign: "center"
|
|
@@ -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,48 @@
|
|
|
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
|
+
get webpSrcSet() {
|
|
31
|
+
if (state.srcSetToUse?.match(/builder\.io/) && !props.noWebp) {
|
|
32
|
+
return state.srcSetToUse.replace(/\?/g, "?format=webp&");
|
|
33
|
+
} else {
|
|
34
|
+
return "";
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
});
|
|
5
39
|
return <div class={css({
|
|
6
40
|
position: "relative"
|
|
7
41
|
})}>
|
|
8
42
|
<picture>
|
|
43
|
+
<Show when={state.webpSrcSet}>
|
|
44
|
+
<source type="image/webp" srcset={state.webpSrcSet} />
|
|
45
|
+
</Show>
|
|
9
46
|
<img class={"builder-image" + (props.className ? " " + props.className : "") + " " + css({
|
|
10
47
|
opacity: "1",
|
|
11
48
|
transition: "opacity 0.2s ease-in-out",
|
|
@@ -14,22 +51,21 @@ function Image(props) {
|
|
|
14
51
|
width: "100%",
|
|
15
52
|
top: "0px",
|
|
16
53
|
left: "0px"
|
|
17
|
-
})} loading="lazy" alt={props.altText}
|
|
54
|
+
})} loading="lazy" alt={props.altText} role={props.altText ? "presentation" : undefined} style={{
|
|
18
55
|
"object-position": props.backgroundSize || "center",
|
|
19
56
|
"object-fit": props.backgroundSize || "cover"
|
|
20
|
-
}} src={props.image} srcset={
|
|
21
|
-
<source
|
|
57
|
+
}} src={props.image} srcset={state.srcSetToUse} sizes={props.sizes} />
|
|
58
|
+
<source srcset={state.srcSetToUse} />
|
|
22
59
|
</picture>
|
|
23
60
|
<Show when={props.aspectRatio && !(props.fitContent && props.builderBlock?.children?.length)}>
|
|
24
|
-
<div class={css({
|
|
61
|
+
<div class={"builder-image-sizer " + css({
|
|
25
62
|
width: "100%",
|
|
26
63
|
pointerEvents: "none",
|
|
27
64
|
fontSize: "0"
|
|
28
65
|
})} style={{
|
|
66
|
+
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
|
29
67
|
"padding-top": props.aspectRatio * 100 + "%"
|
|
30
|
-
}}>
|
|
31
|
-
{" "}
|
|
32
|
-
</div>
|
|
68
|
+
}}></div>
|
|
33
69
|
</Show>
|
|
34
70
|
<Show when={props.builderBlock?.children?.length && props.fitContent}>
|
|
35
71
|
{props.children}
|
|
@@ -1,6 +1,8 @@
|
|
|
1
|
+
import { useContext, onMount, on, createEffect } from "solid-js";
|
|
1
2
|
import { createMutable } from "solid-js/store";
|
|
2
|
-
import RenderContent from "../../components/render-content/render-content";
|
|
3
|
+
import RenderContent from "../../components/render-content/render-content.jsx";
|
|
3
4
|
import BuilderContext from "../../context/builder.context";
|
|
5
|
+
import { getContent } from "../../functions/get-content/index.js";
|
|
4
6
|
|
|
5
7
|
function Symbol(props) {
|
|
6
8
|
const state = createMutable({
|
|
@@ -11,12 +13,39 @@ function Symbol(props) {
|
|
|
11
13
|
onMount(() => {
|
|
12
14
|
state.content = props.symbol?.content;
|
|
13
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));
|
|
14
43
|
return <div class={state.className} {...props.attributes} dataSet={{
|
|
15
44
|
class: state.className
|
|
16
45
|
}}>
|
|
17
|
-
<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,
|
|
18
47
|
...builderContext.state,
|
|
19
|
-
...props.symbol?.
|
|
48
|
+
...props.symbol?.content?.data?.state
|
|
20
49
|
}} model={props.symbol?.model} content={state.content}></RenderContent>
|
|
21
50
|
</div>;
|
|
22
51
|
}
|
package/src/blocks/text/text.jsx
CHANGED
|
@@ -1,5 +1,28 @@
|
|
|
1
|
+
import { createMutable } from "solid-js/store";
|
|
2
|
+
|
|
1
3
|
function Video(props) {
|
|
2
|
-
|
|
4
|
+
const state = createMutable({
|
|
5
|
+
get videoProps() {
|
|
6
|
+
return { ...(props.autoPlay === true ? {
|
|
7
|
+
autoPlay: true
|
|
8
|
+
} : {}),
|
|
9
|
+
...(props.muted === true ? {
|
|
10
|
+
muted: true
|
|
11
|
+
} : {}),
|
|
12
|
+
...(props.controls === true ? {
|
|
13
|
+
controls: true
|
|
14
|
+
} : {}),
|
|
15
|
+
...(props.loop === true ? {
|
|
16
|
+
loop: true
|
|
17
|
+
} : {}),
|
|
18
|
+
...(props.playsInline === true ? {
|
|
19
|
+
playsInline: true
|
|
20
|
+
} : {})
|
|
21
|
+
};
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
});
|
|
25
|
+
return <video {...state.videoProps} style={{
|
|
3
26
|
width: "100%",
|
|
4
27
|
height: "100%",
|
|
5
28
|
...props.attributes?.style,
|
|
@@ -8,7 +31,7 @@ function Video(props) {
|
|
|
8
31
|
// Hack to get object fit to work as expected and
|
|
9
32
|
// not have the video overflow
|
|
10
33
|
"border-radius": 1
|
|
11
|
-
}}
|
|
34
|
+
}} src={props.video || "no-src"} poster={props.posterImage}></video>;
|
|
12
35
|
}
|
|
13
36
|
|
|
14
37
|
export default Video;
|