@builder.io/sdk-solid 0.0.16 → 0.0.18
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 +17 -5
- package/solid-index.jsx +5 -0
- package/src/blocks/BaseText.jsx +9 -0
- package/src/blocks/button/button.jsx +9 -6
- package/src/blocks/columns/columns.jsx +54 -52
- package/src/blocks/columns/component-info.js +26 -1
- package/src/blocks/custom-code/custom-code.jsx +35 -38
- package/src/blocks/embed/component-info.js +21 -1
- package/src/blocks/embed/embed.jsx +37 -42
- package/src/blocks/embed/helpers.js +9 -0
- package/src/blocks/form/form.jsx +175 -176
- package/src/blocks/image/component-info.js +48 -1
- package/src/blocks/image/image.helpers.js +48 -0
- package/src/blocks/image/image.jsx +44 -13
- package/src/blocks/img/img.jsx +1 -1
- package/src/blocks/symbol/component-info.js +1 -0
- package/src/blocks/symbol/symbol.jsx +43 -14
- package/src/blocks/text/text.jsx +1 -1
- package/src/blocks/util.js +7 -0
- package/src/blocks/video/video.jsx +21 -2
- package/src/components/render-block/block-styles.jsx +41 -31
- package/src/components/render-block/render-block.helpers.js +23 -0
- package/src/components/render-block/render-block.jsx +205 -90
- package/src/components/render-block/render-component-with-context.jsx +36 -0
- package/src/components/render-block/render-component.jsx +28 -0
- package/src/components/render-block/render-repeated-block.jsx +36 -0
- package/src/components/render-block/types.js +0 -0
- package/src/components/render-blocks.jsx +42 -33
- package/src/components/render-content/components/render-styles.jsx +39 -42
- package/src/components/render-content/index.js +4 -0
- package/src/components/render-content/render-content.jsx +199 -128
- package/src/components/render-inlined-styles.jsx +21 -5
- package/src/constants/builder-registered-components.js +54 -0
- package/src/constants/device-sizes.js +3 -21
- package/src/context/builder.context.js +3 -1
- package/src/context/types.js +0 -0
- package/src/functions/camel-to-kebab-case.js +4 -0
- package/src/functions/convert-style-object.js +14 -0
- package/src/functions/evaluate.js +1 -1
- package/src/functions/extract-text-styles.js +22 -0
- package/src/functions/fast-clone.js +4 -0
- package/src/functions/get-block-actions-handler.js +12 -0
- package/src/functions/get-block-actions.js +2 -7
- package/src/functions/get-block-component-options.js +6 -1
- package/src/functions/get-block-styles.js +27 -19
- package/src/functions/get-builder-search-params/index.js +17 -2
- package/src/functions/get-content/ab-testing.js +99 -0
- package/src/functions/get-content/fn.test.js +1 -1
- package/src/functions/get-content/index.js +20 -62
- package/src/functions/get-content/types.js +0 -0
- package/src/functions/get-fetch.js +2 -2
- package/src/functions/get-processed-block.js +24 -11
- package/src/functions/get-processed-block.test.js +2 -1
- package/src/functions/mark-mutable.js +10 -0
- package/src/functions/register-component.js +45 -26
- package/src/functions/sanitize-styles.js +4 -0
- package/src/functions/track.js +108 -13
- package/src/helpers/ab-tests.js +16 -0
- package/src/helpers/cookie.js +79 -0
- package/src/helpers/css.js +28 -0
- package/src/helpers/flatten.js +34 -0
- package/src/helpers/localStorage.js +34 -0
- package/src/helpers/nullable.js +4 -0
- package/src/helpers/sessionId.js +49 -0
- package/src/helpers/time.js +5 -0
- package/src/helpers/url.js +10 -0
- package/src/helpers/url.test.js +15 -0
- package/src/helpers/uuid.js +13 -0
- package/src/helpers/visitorId.js +33 -0
- package/src/index-helpers/blocks-exports.js +11 -9
- package/src/scripts/init-editing.js +38 -38
- package/src/types/can-track.js +0 -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 -5
- package/src/functions/macro-eval.js +0 -5
- package/src/functions/previewing-model-name.js +0 -11
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import { TARGET } from "../constants/target.js";
|
|
2
2
|
import { isBrowser } from "../functions/is-browser.js";
|
|
3
|
-
import { isEditing } from "../functions/is-editing.js";
|
|
4
3
|
import { register } from "../functions/register.js";
|
|
5
4
|
const registerInsertMenu = () => {
|
|
6
5
|
register("insertMenu", {
|
|
@@ -32,49 +31,50 @@ const setupBrowserForEditing = () => {
|
|
|
32
31
|
}, "*");
|
|
33
32
|
window.addEventListener("message", ({ data }) => {
|
|
34
33
|
var _a2, _b;
|
|
35
|
-
if (data) {
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
}, "*");
|
|
62
|
-
}).catch(console.error);
|
|
63
|
-
} else {
|
|
64
|
-
(_b = window.parent) == null ? void 0 : _b.postMessage({
|
|
34
|
+
if (!(data == null ? void 0 : data.type)) {
|
|
35
|
+
return;
|
|
36
|
+
}
|
|
37
|
+
switch (data.type) {
|
|
38
|
+
case "builder.evaluate": {
|
|
39
|
+
const text = data.data.text;
|
|
40
|
+
const args = data.data.arguments || [];
|
|
41
|
+
const id = data.data.id;
|
|
42
|
+
const fn = new Function(text);
|
|
43
|
+
let result;
|
|
44
|
+
let error = null;
|
|
45
|
+
try {
|
|
46
|
+
result = fn.apply(null, args);
|
|
47
|
+
} catch (err) {
|
|
48
|
+
error = err;
|
|
49
|
+
}
|
|
50
|
+
if (error) {
|
|
51
|
+
(_a2 = window.parent) == null ? void 0 : _a2.postMessage({
|
|
52
|
+
type: "builder.evaluateError",
|
|
53
|
+
data: { id, error: error.message }
|
|
54
|
+
}, "*");
|
|
55
|
+
} else {
|
|
56
|
+
if (result && typeof result.then === "function") {
|
|
57
|
+
result.then((finalResult) => {
|
|
58
|
+
var _a3;
|
|
59
|
+
(_a3 = window.parent) == null ? void 0 : _a3.postMessage({
|
|
65
60
|
type: "builder.evaluateResult",
|
|
66
|
-
data: {
|
|
61
|
+
data: { id, result: finalResult }
|
|
67
62
|
}, "*");
|
|
68
|
-
}
|
|
63
|
+
}).catch(console.error);
|
|
64
|
+
} else {
|
|
65
|
+
(_b = window.parent) == null ? void 0 : _b.postMessage({
|
|
66
|
+
type: "builder.evaluateResult",
|
|
67
|
+
data: { result, id }
|
|
68
|
+
}, "*");
|
|
69
69
|
}
|
|
70
|
-
break;
|
|
71
70
|
}
|
|
71
|
+
break;
|
|
72
72
|
}
|
|
73
73
|
}
|
|
74
74
|
});
|
|
75
75
|
}
|
|
76
76
|
};
|
|
77
|
-
|
|
78
|
-
registerInsertMenu
|
|
79
|
-
setupBrowserForEditing
|
|
80
|
-
}
|
|
77
|
+
export {
|
|
78
|
+
registerInsertMenu,
|
|
79
|
+
setupBrowserForEditing
|
|
80
|
+
};
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
@@ -1,20 +0,0 @@
|
|
|
1
|
-
import { Show } from "solid-js";
|
|
2
|
-
|
|
3
|
-
function Button(props) {
|
|
4
|
-
return (
|
|
5
|
-
<>
|
|
6
|
-
<Show when={props.link}>
|
|
7
|
-
<a
|
|
8
|
-
{...props.attributes}
|
|
9
|
-
role="button"
|
|
10
|
-
href={props.link}
|
|
11
|
-
target={props.openLinkInNewTab ? "_blank" : undefined}
|
|
12
|
-
>
|
|
13
|
-
{props.text}
|
|
14
|
-
</a>
|
|
15
|
-
</Show>
|
|
16
|
-
</>
|
|
17
|
-
);
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
export default Button;
|
|
@@ -1,7 +0,0 @@
|
|
|
1
|
-
import { registerComponent } from "../../functions/register-component.js";
|
|
2
|
-
import component from "./button.js";
|
|
3
|
-
import { componentInfo } from "./component-info.js";
|
|
4
|
-
var stdin_default = registerComponent(component, componentInfo);
|
|
5
|
-
export {
|
|
6
|
-
stdin_default as default
|
|
7
|
-
};
|
|
@@ -1,102 +0,0 @@
|
|
|
1
|
-
import { For } from "solid-js";
|
|
2
|
-
|
|
3
|
-
import { createMutable } from "solid-js/store";
|
|
4
|
-
import { css } from "solid-styled-components";
|
|
5
|
-
|
|
6
|
-
import RenderBlocks from "../../components/render-blocks.js";
|
|
7
|
-
|
|
8
|
-
function Columns(props) {
|
|
9
|
-
const state = createMutable({
|
|
10
|
-
getGutterSize() {
|
|
11
|
-
return typeof props.space === "number" ? props.space || 0 : 20;
|
|
12
|
-
},
|
|
13
|
-
getColumns() {
|
|
14
|
-
return props.columns || [];
|
|
15
|
-
},
|
|
16
|
-
getWidth(index: number) {
|
|
17
|
-
const columns = this.getColumns();
|
|
18
|
-
return columns[index]?.width || 100 / columns.length;
|
|
19
|
-
},
|
|
20
|
-
getColumnCssWidth(index: number) {
|
|
21
|
-
const columns = this.getColumns();
|
|
22
|
-
const gutterSize = this.getGutterSize();
|
|
23
|
-
const subtractWidth =
|
|
24
|
-
(gutterSize * (columns.length - 1)) / columns.length;
|
|
25
|
-
return `calc(${this.getWidth(index)}% - ${subtractWidth}px)`;
|
|
26
|
-
},
|
|
27
|
-
maybeApplyForTablet(prop: string) {
|
|
28
|
-
const _stackColumnsAt = props.stackColumnsAt || "tablet";
|
|
29
|
-
|
|
30
|
-
return _stackColumnsAt === "tablet" ? prop : "inherit";
|
|
31
|
-
},
|
|
32
|
-
get columnsCssVars() {
|
|
33
|
-
const flexDir =
|
|
34
|
-
props.stackColumnsAt === "never"
|
|
35
|
-
? "inherit"
|
|
36
|
-
: props.reverseColumnsWhenStacked
|
|
37
|
-
? "column-reverse"
|
|
38
|
-
: "column";
|
|
39
|
-
return {
|
|
40
|
-
"--flex-dir": flexDir,
|
|
41
|
-
"--flex-dir-tablet": this.maybeApplyForTablet(flexDir),
|
|
42
|
-
};
|
|
43
|
-
},
|
|
44
|
-
get columnCssVars() {
|
|
45
|
-
const width = "100%";
|
|
46
|
-
const marginLeft = "0";
|
|
47
|
-
return {
|
|
48
|
-
"--column-width": width,
|
|
49
|
-
"--column-margin-left": marginLeft,
|
|
50
|
-
"--column-width-tablet": this.maybeApplyForTablet(width),
|
|
51
|
-
"--column-margin-left-tablet": this.maybeApplyForTablet(marginLeft),
|
|
52
|
-
};
|
|
53
|
-
},
|
|
54
|
-
});
|
|
55
|
-
|
|
56
|
-
return (
|
|
57
|
-
<div
|
|
58
|
-
class={css({
|
|
59
|
-
display: "flex",
|
|
60
|
-
alignItems: "stretch",
|
|
61
|
-
lineHeight: "normal",
|
|
62
|
-
"@media (max-width: 999px)": {
|
|
63
|
-
flexDirection: "var(--flex-dir-tablet)",
|
|
64
|
-
},
|
|
65
|
-
"@media (max-width: 639px)": {
|
|
66
|
-
flexDirection: "var(--flex-dir)",
|
|
67
|
-
},
|
|
68
|
-
})}
|
|
69
|
-
style={state.columnsCssVars}
|
|
70
|
-
>
|
|
71
|
-
<For each={props.columns}>
|
|
72
|
-
{(column, _index) => {
|
|
73
|
-
const index = _index();
|
|
74
|
-
return (
|
|
75
|
-
<div
|
|
76
|
-
class={css({
|
|
77
|
-
flexGrow: "1",
|
|
78
|
-
"@media (max-width: 999px)": {
|
|
79
|
-
width: "var(--column-width-tablet) !important",
|
|
80
|
-
marginLeft: "var(--column-margin-left-tablet) !important",
|
|
81
|
-
},
|
|
82
|
-
"@media (max-width: 639px)": {
|
|
83
|
-
width: "var(--column-width) !important",
|
|
84
|
-
marginLeft: "var(--column-margin-left) !important",
|
|
85
|
-
},
|
|
86
|
-
})}
|
|
87
|
-
style={{
|
|
88
|
-
width: state.getColumnCssWidth(index),
|
|
89
|
-
"margin-left": `${index === 0 ? 0 : state.getGutterSize()}px`,
|
|
90
|
-
...state.columnCssVars,
|
|
91
|
-
}}
|
|
92
|
-
>
|
|
93
|
-
<RenderBlocks blocks={column.blocks}></RenderBlocks>
|
|
94
|
-
</div>
|
|
95
|
-
);
|
|
96
|
-
}}
|
|
97
|
-
</For>
|
|
98
|
-
</div>
|
|
99
|
-
);
|
|
100
|
-
}
|
|
101
|
-
|
|
102
|
-
export default Columns;
|
|
@@ -1,7 +0,0 @@
|
|
|
1
|
-
import { registerComponent } from "../../functions/register-component.js";
|
|
2
|
-
import component from "./columns.js";
|
|
3
|
-
import { componentInfo } from "./component-info.js";
|
|
4
|
-
var stdin_default = registerComponent(component, componentInfo);
|
|
5
|
-
export {
|
|
6
|
-
stdin_default as default
|
|
7
|
-
};
|
|
@@ -1,67 +0,0 @@
|
|
|
1
|
-
import { createMutable } from "solid-js/store";
|
|
2
|
-
|
|
3
|
-
function CustomCode(props) {
|
|
4
|
-
const state = createMutable({
|
|
5
|
-
scriptsInserted: [],
|
|
6
|
-
scriptsRun: [],
|
|
7
|
-
findAndRunScripts() {
|
|
8
|
-
// TODO: Move this function to standalone one in '@builder.io/utils'
|
|
9
|
-
if (elem && typeof window !== "undefined") {
|
|
10
|
-
/** @type {HTMLScriptElement[]} */
|
|
11
|
-
const scripts = elem.getElementsByTagName("script");
|
|
12
|
-
|
|
13
|
-
for (let i = 0; i < scripts.length; i++) {
|
|
14
|
-
const script = scripts[i];
|
|
15
|
-
|
|
16
|
-
if (script.src) {
|
|
17
|
-
if (state.scriptsInserted.includes(script.src)) {
|
|
18
|
-
continue;
|
|
19
|
-
}
|
|
20
|
-
|
|
21
|
-
state.scriptsInserted.push(script.src);
|
|
22
|
-
const newScript = document.createElement("script");
|
|
23
|
-
newScript.async = true;
|
|
24
|
-
newScript.src = script.src;
|
|
25
|
-
document.head.appendChild(newScript);
|
|
26
|
-
} else if (
|
|
27
|
-
!script.type ||
|
|
28
|
-
[
|
|
29
|
-
"text/javascript",
|
|
30
|
-
"application/javascript",
|
|
31
|
-
"application/ecmascript",
|
|
32
|
-
].includes(script.type)
|
|
33
|
-
) {
|
|
34
|
-
if (state.scriptsRun.includes(script.innerText)) {
|
|
35
|
-
continue;
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
try {
|
|
39
|
-
state.scriptsRun.push(script.innerText);
|
|
40
|
-
new Function(script.innerText)();
|
|
41
|
-
} catch (error) {
|
|
42
|
-
console.warn("`CustomCode`: Error running script:", error);
|
|
43
|
-
}
|
|
44
|
-
}
|
|
45
|
-
}
|
|
46
|
-
}
|
|
47
|
-
},
|
|
48
|
-
});
|
|
49
|
-
|
|
50
|
-
const elem = useRef();
|
|
51
|
-
|
|
52
|
-
onMount(() => {
|
|
53
|
-
state.findAndRunScripts();
|
|
54
|
-
});
|
|
55
|
-
|
|
56
|
-
return (
|
|
57
|
-
<div
|
|
58
|
-
class={
|
|
59
|
-
"builder-custom-code" + (props.replaceNodes ? " replace-nodes" : "")
|
|
60
|
-
}
|
|
61
|
-
ref={elem}
|
|
62
|
-
innerHTML={props.code}
|
|
63
|
-
></div>
|
|
64
|
-
);
|
|
65
|
-
}
|
|
66
|
-
|
|
67
|
-
export default CustomCode;
|
|
@@ -1,7 +0,0 @@
|
|
|
1
|
-
import { registerComponent } from "../../functions/register-component.js";
|
|
2
|
-
import { componentInfo } from "./component-info.js";
|
|
3
|
-
import component from "./custom-code.js";
|
|
4
|
-
var stdin_default = registerComponent(component, componentInfo);
|
|
5
|
-
export {
|
|
6
|
-
stdin_default as default
|
|
7
|
-
};
|
|
@@ -1,59 +0,0 @@
|
|
|
1
|
-
import { createMutable } from "solid-js/store";
|
|
2
|
-
|
|
3
|
-
function Embed(props) {
|
|
4
|
-
const state = createMutable({
|
|
5
|
-
scriptsInserted: [],
|
|
6
|
-
scriptsRun: [],
|
|
7
|
-
findAndRunScripts() {
|
|
8
|
-
// TODO: Move this function to standalone one in '@builder.io/utils'
|
|
9
|
-
if (elem && typeof window !== "undefined") {
|
|
10
|
-
/** @type {HTMLScriptElement[]} */
|
|
11
|
-
const scripts = elem.getElementsByTagName("script");
|
|
12
|
-
|
|
13
|
-
for (let i = 0; i < scripts.length; i++) {
|
|
14
|
-
const script = scripts[i];
|
|
15
|
-
|
|
16
|
-
if (script.src) {
|
|
17
|
-
if (state.scriptsInserted.includes(script.src)) {
|
|
18
|
-
continue;
|
|
19
|
-
}
|
|
20
|
-
|
|
21
|
-
state.scriptsInserted.push(script.src);
|
|
22
|
-
const newScript = document.createElement("script");
|
|
23
|
-
newScript.async = true;
|
|
24
|
-
newScript.src = script.src;
|
|
25
|
-
document.head.appendChild(newScript);
|
|
26
|
-
} else if (
|
|
27
|
-
!script.type ||
|
|
28
|
-
[
|
|
29
|
-
"text/javascript",
|
|
30
|
-
"application/javascript",
|
|
31
|
-
"application/ecmascript",
|
|
32
|
-
].includes(script.type)
|
|
33
|
-
) {
|
|
34
|
-
if (state.scriptsRun.includes(script.innerText)) {
|
|
35
|
-
continue;
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
try {
|
|
39
|
-
state.scriptsRun.push(script.innerText);
|
|
40
|
-
new Function(script.innerText)();
|
|
41
|
-
} catch (error) {
|
|
42
|
-
console.warn("`Embed`: Error running script:", error);
|
|
43
|
-
}
|
|
44
|
-
}
|
|
45
|
-
}
|
|
46
|
-
}
|
|
47
|
-
},
|
|
48
|
-
});
|
|
49
|
-
|
|
50
|
-
const elem = useRef();
|
|
51
|
-
|
|
52
|
-
onMount(() => {
|
|
53
|
-
state.findAndRunScripts();
|
|
54
|
-
});
|
|
55
|
-
|
|
56
|
-
return <div ref={elem} innerHTML={props.content}></div>;
|
|
57
|
-
}
|
|
58
|
-
|
|
59
|
-
export default Embed;
|
|
@@ -1,7 +0,0 @@
|
|
|
1
|
-
import { registerComponent } from "../../functions/register-component.js";
|
|
2
|
-
import { componentInfo } from "./component-info.js";
|
|
3
|
-
import component from "./embed.js";
|
|
4
|
-
var stdin_default = registerComponent(component, componentInfo);
|
|
5
|
-
export {
|
|
6
|
-
stdin_default as default
|
|
7
|
-
};
|
|
@@ -1,293 +0,0 @@
|
|
|
1
|
-
import { Show, For } from "solid-js";
|
|
2
|
-
|
|
3
|
-
import { createMutable } from "solid-js/store";
|
|
4
|
-
import { css } from "solid-styled-components";
|
|
5
|
-
|
|
6
|
-
import RenderBlock from "../../components/render-block/render-block.js";
|
|
7
|
-
import { isEditing } from "../../functions/is-editing.js";
|
|
8
|
-
|
|
9
|
-
function FormComponent(props) {
|
|
10
|
-
const state = createMutable({
|
|
11
|
-
formState: "unsubmitted",
|
|
12
|
-
responseData: null,
|
|
13
|
-
formErrorMessage: "",
|
|
14
|
-
get submissionState() {
|
|
15
|
-
return (isEditing() && props.previewState) || state.formState;
|
|
16
|
-
},
|
|
17
|
-
onSubmit(
|
|
18
|
-
event: Event & {
|
|
19
|
-
currentTarget: HTMLFormElement;
|
|
20
|
-
}
|
|
21
|
-
) {
|
|
22
|
-
const sendWithJs =
|
|
23
|
-
props.sendWithJs || props.sendSubmissionsTo === "email";
|
|
24
|
-
|
|
25
|
-
if (props.sendSubmissionsTo === "zapier") {
|
|
26
|
-
event.preventDefault();
|
|
27
|
-
} else if (sendWithJs) {
|
|
28
|
-
if (!(props.action || props.sendSubmissionsTo === "email")) {
|
|
29
|
-
event.preventDefault();
|
|
30
|
-
return;
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
event.preventDefault();
|
|
34
|
-
const el = event.currentTarget;
|
|
35
|
-
const headers = props.customHeaders || {};
|
|
36
|
-
let body: any;
|
|
37
|
-
const formData = new FormData(el); // TODO: maybe support null
|
|
38
|
-
|
|
39
|
-
const formPairs: {
|
|
40
|
-
key: string;
|
|
41
|
-
value: File | boolean | number | string | FileList;
|
|
42
|
-
}[] = Array.from(
|
|
43
|
-
event.currentTarget.querySelectorAll("input,select,textarea")
|
|
44
|
-
)
|
|
45
|
-
.filter((el) => !!(el as HTMLInputElement).name)
|
|
46
|
-
.map((el) => {
|
|
47
|
-
let value: any;
|
|
48
|
-
const key = (el as HTMLImageElement).name;
|
|
49
|
-
|
|
50
|
-
if (el instanceof HTMLInputElement) {
|
|
51
|
-
if (el.type === "radio") {
|
|
52
|
-
if (el.checked) {
|
|
53
|
-
value = el.name;
|
|
54
|
-
return {
|
|
55
|
-
key,
|
|
56
|
-
value,
|
|
57
|
-
};
|
|
58
|
-
}
|
|
59
|
-
} else if (el.type === "checkbox") {
|
|
60
|
-
value = el.checked;
|
|
61
|
-
} else if (el.type === "number" || el.type === "range") {
|
|
62
|
-
const num = el.valueAsNumber;
|
|
63
|
-
|
|
64
|
-
if (!isNaN(num)) {
|
|
65
|
-
value = num;
|
|
66
|
-
}
|
|
67
|
-
} else if (el.type === "file") {
|
|
68
|
-
// TODO: one vs multiple files
|
|
69
|
-
value = el.files;
|
|
70
|
-
} else {
|
|
71
|
-
value = el.value;
|
|
72
|
-
}
|
|
73
|
-
} else {
|
|
74
|
-
value = (el as HTMLInputElement).value;
|
|
75
|
-
}
|
|
76
|
-
|
|
77
|
-
return {
|
|
78
|
-
key,
|
|
79
|
-
value,
|
|
80
|
-
};
|
|
81
|
-
});
|
|
82
|
-
let contentType = props.contentType;
|
|
83
|
-
|
|
84
|
-
if (props.sendSubmissionsTo === "email") {
|
|
85
|
-
contentType = "multipart/form-data";
|
|
86
|
-
}
|
|
87
|
-
|
|
88
|
-
Array.from(formPairs).forEach(({ value }) => {
|
|
89
|
-
if (
|
|
90
|
-
value instanceof File ||
|
|
91
|
-
(Array.isArray(value) && value[0] instanceof File) ||
|
|
92
|
-
value instanceof FileList
|
|
93
|
-
) {
|
|
94
|
-
contentType = "multipart/form-data";
|
|
95
|
-
}
|
|
96
|
-
}); // TODO: send as urlEncoded or multipart by default
|
|
97
|
-
// because of ease of use and reliability in browser API
|
|
98
|
-
// for encoding the form?
|
|
99
|
-
|
|
100
|
-
if (contentType !== "application/json") {
|
|
101
|
-
body = formData;
|
|
102
|
-
} else {
|
|
103
|
-
// Json
|
|
104
|
-
const json = {};
|
|
105
|
-
Array.from(formPairs).forEach(({ value, key }) => {
|
|
106
|
-
set(json, key, value);
|
|
107
|
-
});
|
|
108
|
-
body = JSON.stringify(json);
|
|
109
|
-
}
|
|
110
|
-
|
|
111
|
-
if (contentType && contentType !== "multipart/form-data") {
|
|
112
|
-
if (
|
|
113
|
-
/* Zapier doesn't allow content-type header to be sent from browsers */
|
|
114
|
-
!(sendWithJs && props.action?.includes("zapier.com"))
|
|
115
|
-
) {
|
|
116
|
-
headers["content-type"] = contentType;
|
|
117
|
-
}
|
|
118
|
-
}
|
|
119
|
-
|
|
120
|
-
const presubmitEvent = new CustomEvent("presubmit", {
|
|
121
|
-
detail: {
|
|
122
|
-
body,
|
|
123
|
-
},
|
|
124
|
-
});
|
|
125
|
-
|
|
126
|
-
if (formRef) {
|
|
127
|
-
formRef.dispatchEvent(presubmitEvent);
|
|
128
|
-
|
|
129
|
-
if (presubmitEvent.defaultPrevented) {
|
|
130
|
-
return;
|
|
131
|
-
}
|
|
132
|
-
}
|
|
133
|
-
|
|
134
|
-
state.formState = "sending";
|
|
135
|
-
const formUrl = `${
|
|
136
|
-
builder.env === "dev" ? "http://localhost:5000" : "https://builder.io"
|
|
137
|
-
}/api/v1/form-submit?apiKey=${builder.apiKey}&to=${btoa(
|
|
138
|
-
props.sendSubmissionsToEmail || ""
|
|
139
|
-
)}&name=${encodeURIComponent(props.name || "")}`;
|
|
140
|
-
fetch(
|
|
141
|
-
props.sendSubmissionsTo === "email" ? formUrl : props.action!,
|
|
142
|
-
/* TODO: throw error if no action URL */
|
|
143
|
-
{
|
|
144
|
-
body,
|
|
145
|
-
headers,
|
|
146
|
-
method: props.method || "post",
|
|
147
|
-
}
|
|
148
|
-
).then(
|
|
149
|
-
async (res) => {
|
|
150
|
-
let body;
|
|
151
|
-
const contentType = res.headers.get("content-type");
|
|
152
|
-
|
|
153
|
-
if (contentType && contentType.indexOf("application/json") !== -1) {
|
|
154
|
-
body = await res.json();
|
|
155
|
-
} else {
|
|
156
|
-
body = await res.text();
|
|
157
|
-
}
|
|
158
|
-
|
|
159
|
-
if (!res.ok && props.errorMessagePath) {
|
|
160
|
-
/* TODO: allow supplying an error formatter function */
|
|
161
|
-
let message = get(body, props.errorMessagePath);
|
|
162
|
-
|
|
163
|
-
if (message) {
|
|
164
|
-
if (typeof message !== "string") {
|
|
165
|
-
/* TODO: ideally convert json to yaml so it woul dbe like
|
|
166
|
-
error: - email has been taken */
|
|
167
|
-
message = JSON.stringify(message);
|
|
168
|
-
}
|
|
169
|
-
|
|
170
|
-
state.formErrorMessage = message;
|
|
171
|
-
}
|
|
172
|
-
}
|
|
173
|
-
|
|
174
|
-
state.responseData = body;
|
|
175
|
-
state.formState = res.ok ? "success" : "error";
|
|
176
|
-
|
|
177
|
-
if (res.ok) {
|
|
178
|
-
const submitSuccessEvent = new CustomEvent("submit:success", {
|
|
179
|
-
detail: {
|
|
180
|
-
res,
|
|
181
|
-
body,
|
|
182
|
-
},
|
|
183
|
-
});
|
|
184
|
-
|
|
185
|
-
if (formRef) {
|
|
186
|
-
formRef.dispatchEvent(submitSuccessEvent);
|
|
187
|
-
|
|
188
|
-
if (submitSuccessEvent.defaultPrevented) {
|
|
189
|
-
return;
|
|
190
|
-
}
|
|
191
|
-
/* TODO: option to turn this on/off? */
|
|
192
|
-
|
|
193
|
-
if (props.resetFormOnSubmit !== false) {
|
|
194
|
-
formRef.reset();
|
|
195
|
-
}
|
|
196
|
-
}
|
|
197
|
-
/* TODO: client side route event first that can be preventDefaulted */
|
|
198
|
-
|
|
199
|
-
if (props.successUrl) {
|
|
200
|
-
if (formRef) {
|
|
201
|
-
const event = new CustomEvent("route", {
|
|
202
|
-
detail: {
|
|
203
|
-
url: props.successUrl,
|
|
204
|
-
},
|
|
205
|
-
});
|
|
206
|
-
formRef.dispatchEvent(event);
|
|
207
|
-
|
|
208
|
-
if (!event.defaultPrevented) {
|
|
209
|
-
location.href = props.successUrl;
|
|
210
|
-
}
|
|
211
|
-
} else {
|
|
212
|
-
location.href = props.successUrl;
|
|
213
|
-
}
|
|
214
|
-
}
|
|
215
|
-
}
|
|
216
|
-
},
|
|
217
|
-
(err) => {
|
|
218
|
-
const submitErrorEvent = new CustomEvent("submit:error", {
|
|
219
|
-
detail: {
|
|
220
|
-
error: err,
|
|
221
|
-
},
|
|
222
|
-
});
|
|
223
|
-
|
|
224
|
-
if (formRef) {
|
|
225
|
-
formRef.dispatchEvent(submitErrorEvent);
|
|
226
|
-
|
|
227
|
-
if (submitErrorEvent.defaultPrevented) {
|
|
228
|
-
return;
|
|
229
|
-
}
|
|
230
|
-
}
|
|
231
|
-
|
|
232
|
-
state.responseData = err;
|
|
233
|
-
state.formState = "error";
|
|
234
|
-
}
|
|
235
|
-
);
|
|
236
|
-
}
|
|
237
|
-
},
|
|
238
|
-
});
|
|
239
|
-
|
|
240
|
-
const formRef = useRef();
|
|
241
|
-
|
|
242
|
-
return (
|
|
243
|
-
<form
|
|
244
|
-
{...props.attributes}
|
|
245
|
-
validate={props.validate}
|
|
246
|
-
ref={formRef}
|
|
247
|
-
action={!props.sendWithJs && props.action}
|
|
248
|
-
method={props.method}
|
|
249
|
-
name={props.name}
|
|
250
|
-
onSubmit={(event) => state.onSubmit(event)}
|
|
251
|
-
>
|
|
252
|
-
<Show when={props.builderBlock && props.builderBlock.children}>
|
|
253
|
-
<For each={props.builderBlock?.children}>
|
|
254
|
-
{(block, _index) => {
|
|
255
|
-
const index = _index();
|
|
256
|
-
return <RenderBlock block={block}></RenderBlock>;
|
|
257
|
-
}}
|
|
258
|
-
</For>
|
|
259
|
-
</Show>
|
|
260
|
-
<Show when={state.submissionState === "error"}>
|
|
261
|
-
<BuilderBlocks
|
|
262
|
-
dataPath="errorMessage"
|
|
263
|
-
blocks={props.errorMessage}
|
|
264
|
-
></BuilderBlocks>
|
|
265
|
-
</Show>
|
|
266
|
-
<Show when={state.submissionState === "sending"}>
|
|
267
|
-
<BuilderBlocks
|
|
268
|
-
dataPath="sendingMessage"
|
|
269
|
-
blocks={props.sendingMessage}
|
|
270
|
-
></BuilderBlocks>
|
|
271
|
-
</Show>
|
|
272
|
-
<Show when={state.submissionState === "error" && state.responseData}>
|
|
273
|
-
<pre
|
|
274
|
-
class={css({
|
|
275
|
-
padding: "10px",
|
|
276
|
-
color: "red",
|
|
277
|
-
textAlign: "center",
|
|
278
|
-
})}
|
|
279
|
-
>
|
|
280
|
-
{JSON.stringify(state.responseData, null, 2)}
|
|
281
|
-
</pre>
|
|
282
|
-
</Show>
|
|
283
|
-
<Show when={state.submissionState === "success"}>
|
|
284
|
-
<BuilderBlocks
|
|
285
|
-
dataPath="successMessage"
|
|
286
|
-
blocks={props.successMessage}
|
|
287
|
-
></BuilderBlocks>
|
|
288
|
-
</Show>
|
|
289
|
-
</form>
|
|
290
|
-
);
|
|
291
|
-
}
|
|
292
|
-
|
|
293
|
-
export default FormComponent;
|
package/src/blocks/form/index.js
DELETED
|
@@ -1,7 +0,0 @@
|
|
|
1
|
-
import { registerComponent } from "../../functions/register-component.js";
|
|
2
|
-
import { componentInfo } from "./component-info.js";
|
|
3
|
-
import component from "./form.js";
|
|
4
|
-
var stdin_default = registerComponent(component, componentInfo);
|
|
5
|
-
export {
|
|
6
|
-
stdin_default as default
|
|
7
|
-
};
|