@builder.io/sdk-svelte 0.0.3 → 0.0.5
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/--package.json +160 -0
- package/package/blocks/BaseText.svelte +19 -0
- package/package/blocks/BaseText.svelte.d.ts +19 -0
- package/package/blocks/columns/columns.svelte +13 -4
- package/package/blocks/columns/columns.svelte.d.ts +1 -1
- package/package/blocks/custom-code/custom-code.svelte +1 -1
- package/package/blocks/embed/embed.svelte +2 -0
- package/package/blocks/form/form.svelte +7 -5
- package/package/blocks/image/image.svelte +48 -46
- package/package/blocks/image/image.svelte.d.ts +1 -1
- package/package/blocks/img/img.svelte +7 -2
- package/package/blocks/section/section.svelte +7 -2
- package/package/blocks/symbol/symbol.svelte +13 -13
- package/package/blocks/symbol/symbol.svelte.d.ts +3 -3
- package/package/blocks/video/video.svelte +14 -3
- package/package/components/render-block/block-styles.svelte +24 -19
- package/package/components/render-block/block-styles.svelte.d.ts +2 -2
- package/package/components/render-block/render-block.svelte +81 -58
- package/package/components/render-block/render-block.svelte.d.ts +2 -2
- package/package/components/render-block/render-component-with-context.svelte +32 -0
- package/package/components/render-block/render-component-with-context.svelte.d.ts +19 -0
- package/package/components/render-block/render-component.svelte +1 -3
- package/package/components/render-block/render-component.svelte.d.ts +2 -2
- package/package/components/render-block/render-repeated-block.svelte +3 -0
- package/package/components/render-block/types.d.ts +2 -2
- package/package/components/render-block/types.js +1 -2
- package/package/components/render-blocks.svelte +12 -1
- package/package/components/render-blocks.svelte.d.ts +3 -1
- package/package/components/render-content/components/render-styles.svelte +2 -1
- package/package/components/render-content/render-content.svelte +24 -8
- package/package/components/render-content/render-content.svelte.d.ts +2 -2
- package/package/constants/builder-registered-components.js +3 -0
- package/package/context/builder.context.d.ts +1 -0
- package/package/context/builder.context.js +1 -0
- package/package/context/types.d.ts +4 -3
- package/package/context/types.js +1 -3
- package/package/functions/extract-text-styles.d.ts +4 -0
- package/package/functions/extract-text-styles.js +34 -0
- package/package/functions/fast-clone.d.ts +4 -0
- package/package/functions/fast-clone.js +4 -0
- package/package/functions/get-block-actions-handler.d.ts +5 -0
- package/package/functions/get-block-actions-handler.js +9 -0
- package/package/functions/get-block-actions.d.ts +1 -1
- package/package/functions/get-block-actions.js +2 -8
- package/package/functions/get-block-component-options.d.ts +1 -1
- package/package/functions/get-block-component-options.js +0 -1
- package/package/functions/get-block-properties.d.ts +1 -1
- package/package/functions/get-block-properties.js +0 -1
- package/package/functions/get-block-tag.d.ts +1 -1
- package/package/functions/get-block-tag.js +0 -1
- package/package/functions/get-content/ab-testing.d.ts +5 -3
- package/package/functions/get-content/ab-testing.js +75 -37
- package/package/functions/get-content/index.d.ts +1 -1
- package/package/functions/get-content/index.js +4 -5
- package/package/functions/get-content/types.d.ts +7 -2
- package/package/functions/get-processed-block.d.ts +1 -1
- package/package/functions/get-processed-block.js +5 -4
- package/package/functions/get-processed-block.test.js +0 -1
- package/package/functions/get-react-native-block-styles.d.ts +6 -0
- package/package/functions/get-react-native-block-styles.js +16 -0
- package/package/functions/register-component.d.ts +2 -2
- package/package/functions/register-component.js +1 -5
- package/package/functions/register.d.ts +2 -2
- package/package/functions/register.js +0 -2
- package/package/functions/sanitize-react-native-block-styles.d.ts +3 -0
- package/package/functions/sanitize-react-native-block-styles.js +53 -0
- package/package/functions/track.d.ts +1 -1
- package/package/functions/track.js +5 -6
- package/package/functions/transform-block.d.ts +1 -1
- package/package/functions/transform-block.js +0 -1
- package/package/helpers/ab-tests.d.ts +8 -0
- package/package/helpers/ab-tests.js +5 -0
- package/package/helpers/cookie.d.ts +9 -3
- package/package/helpers/cookie.js +8 -3
- package/package/helpers/css.d.ts +5 -1
- package/package/helpers/css.js +14 -1
- package/package/helpers/localStorage.d.ts +3 -4
- package/package/helpers/sessionId.d.ts +3 -4
- package/package/helpers/sessionId.js +5 -3
- package/package/helpers/visitorId.d.ts +3 -5
- package/package/scripts/init-editing.js +42 -38
- package/package/types/builder-content.d.ts +1 -1
- package/package/types/builder-content.js +1 -1
- package/package/types/targets.d.ts +1 -1
- package/package/types/typescript.d.ts +1 -0
- package/package.json +10 -4
- package/src/blocks/BaseText.svelte +27 -0
- package/{package/blocks/button/button.lite.tsx → src/blocks/button/button.svelte} +0 -0
- package/src/blocks/button/component-info.ts +42 -0
- package/{package/blocks/columns/columns.lite.tsx → src/blocks/columns/columns.svelte} +26 -17
- package/src/blocks/columns/component-info.ts +254 -0
- package/src/blocks/custom-code/component-info.ts +31 -0
- package/{package/blocks/custom-code/custom-code.lite.tsx → src/blocks/custom-code/custom-code.svelte} +1 -5
- package/src/blocks/embed/component-info.ts +53 -0
- package/{package/blocks/embed/embed.lite.tsx → src/blocks/embed/embed.svelte} +1 -2
- package/src/blocks/embed/helpers.ts +8 -0
- package/src/blocks/form/component-info.ts +282 -0
- package/{package/blocks/form/form.lite.tsx → src/blocks/form/form.svelte} +12 -31
- package/src/blocks/fragment/component-info.ts +10 -0
- package/{package/blocks/fragment/fragment.lite.tsx → src/blocks/fragment/fragment.svelte} +0 -0
- package/src/blocks/image/component-info.ts +170 -0
- package/src/blocks/image/image.helpers.ts +75 -0
- package/{package/blocks/image/image.lite.tsx → src/blocks/image/image.svelte} +47 -50
- package/src/blocks/img/component-info.ts +21 -0
- package/{package/blocks/img/img.lite.tsx → src/blocks/img/img.svelte} +6 -3
- package/src/blocks/input/component-info.ts +78 -0
- package/{package/blocks/input/input.lite.tsx → src/blocks/input/input.svelte} +0 -0
- package/src/blocks/raw-text/component-info.ts +15 -0
- package/{package/blocks/raw-text/raw-text.lite.tsx → src/blocks/raw-text/raw-text.svelte} +2 -1
- package/src/blocks/section/component-info.ts +50 -0
- package/{package/blocks/section/section.lite.tsx → src/blocks/section/section.svelte} +6 -2
- package/src/blocks/select/component-info.ts +61 -0
- package/{package/blocks/select/select.lite.tsx → src/blocks/select/select.svelte} +0 -0
- package/src/blocks/submit-button/component-info.ts +32 -0
- package/{package/blocks/submit-button/submit-button.lite.tsx → src/blocks/submit-button/submit-button.svelte} +0 -0
- package/src/blocks/symbol/component-info.ts +43 -0
- package/{package/blocks/symbol/symbol.lite.tsx → src/blocks/symbol/symbol.svelte} +23 -15
- package/src/blocks/text/component-info.ts +24 -0
- package/{package/blocks/text/text.lite.tsx → src/blocks/text/text.svelte} +0 -0
- package/src/blocks/textarea/component-info.ts +48 -0
- package/{package/blocks/textarea/textarea.lite.tsx → src/blocks/textarea/textarea.svelte} +0 -0
- package/src/blocks/util.ts +6 -0
- package/src/blocks/video/component-info.ts +109 -0
- package/{package/blocks/video/video.lite.tsx → src/blocks/video/video.svelte} +13 -3
- package/{package/components/render-block/block-styles.lite.tsx → src/components/render-block/block-styles.svelte} +28 -26
- package/src/components/render-block/render-block.helpers.ts +27 -0
- package/{package/components/render-block/render-block.lite.tsx → src/components/render-block/render-block.svelte} +93 -81
- package/src/components/render-block/render-component-with-context.svelte +38 -0
- package/{package/components/render-block/render-component.lite.tsx → src/components/render-block/render-component.svelte} +5 -3
- package/{package/components/render-block/render-repeated-block.lite.tsx → src/components/render-block/render-repeated-block.svelte} +4 -0
- package/src/components/render-block/types.ts +7 -0
- package/{package/components/render-blocks.lite.tsx → src/components/render-blocks.svelte} +15 -2
- package/{package/components/render-content/components/render-styles.lite.tsx → src/components/render-content/components/render-styles.svelte} +2 -8
- package/src/components/render-content/index.ts +1 -0
- package/{package/components/render-content/render-content.lite.tsx → src/components/render-content/render-content.svelte} +34 -36
- package/{package/components/render-inlined-styles.lite.tsx → src/components/render-inlined-styles.svelte} +0 -1
- package/src/constants/builder-registered-components.ts +42 -0
- package/src/constants/device-sizes.ts +28 -0
- package/src/constants/target.ts +2 -0
- package/src/context/builder.context.ts +13 -0
- package/src/context/types.ts +23 -0
- package/src/functions/camel-to-kebab-case.ts +2 -0
- package/src/functions/evaluate.ts +52 -0
- package/src/functions/event-handler-name.ts +6 -0
- package/src/functions/extract-text-styles.ts +39 -0
- package/src/functions/fast-clone.ts +5 -0
- package/src/functions/get-block-actions-handler.ts +19 -0
- package/src/functions/get-block-actions.ts +25 -0
- package/src/functions/get-block-component-options.ts +12 -0
- package/src/functions/get-block-properties.ts +11 -0
- package/src/functions/get-block-tag.ts +7 -0
- package/src/functions/get-builder-search-params/fn.test.ts +19 -0
- package/src/functions/get-builder-search-params/index.ts +48 -0
- package/src/functions/get-content/ab-testing.ts +132 -0
- package/src/functions/get-content/fn.test.ts +35 -0
- package/src/functions/get-content/index.ts +77 -0
- package/src/functions/get-content/types.ts +36 -0
- package/src/functions/get-fetch.ts +14 -0
- package/src/functions/get-global-this.ts +15 -0
- package/src/functions/get-processed-block.test.ts +33 -0
- package/src/functions/get-processed-block.ts +54 -0
- package/src/functions/get-react-native-block-styles.ts +30 -0
- package/src/functions/if-target.ts +20 -0
- package/src/functions/is-browser.ts +3 -0
- package/src/functions/is-editing.ts +7 -0
- package/src/functions/is-iframe.ts +5 -0
- package/src/functions/is-previewing.ts +14 -0
- package/src/functions/mark-mutable.ts +7 -0
- package/src/functions/on-change.test.ts +23 -0
- package/src/functions/on-change.ts +29 -0
- package/src/functions/register-component.ts +67 -0
- package/src/functions/register.ts +46 -0
- package/src/functions/sanitize-react-native-block-styles.ts +65 -0
- package/src/functions/set-editor-settings.ts +16 -0
- package/src/functions/set.test.ts +19 -0
- package/src/functions/set.ts +26 -0
- package/src/functions/track.ts +90 -0
- package/src/functions/transform-block.ts +6 -0
- package/src/helpers/ab-tests.ts +22 -0
- package/src/helpers/cookie.ts +102 -0
- package/src/helpers/css.ts +33 -0
- package/src/helpers/flatten.ts +24 -0
- package/src/helpers/localStorage.ts +38 -0
- package/src/helpers/nullable.ts +4 -0
- package/src/helpers/sessionId.ts +34 -0
- package/src/helpers/time.ts +4 -0
- package/src/helpers/url.test.ts +16 -0
- package/src/helpers/url.ts +12 -0
- package/src/helpers/uuid.ts +17 -0
- package/src/helpers/visitorId.ts +38 -0
- package/src/index-helpers/blocks-exports.ts +10 -0
- package/src/index-helpers/top-of-file.ts +4 -0
- package/src/index.ts +12 -0
- package/src/scripts/init-editing.ts +102 -0
- package/src/types/builder-block.ts +58 -0
- package/src/types/builder-content.ts +39 -0
- package/src/types/can-track.ts +3 -0
- package/src/types/components.ts +188 -0
- package/src/types/deep-partial.ts +7 -0
- package/src/types/element.ts +60 -0
- package/src/types/targets.ts +6 -0
- package/src/types/typescript.ts +7 -0
- package/package/blocks/button/button.lite.d.ts +0 -0
- package/package/blocks/columns/columns.lite.d.ts +0 -0
- package/package/blocks/custom-code/custom-code.lite.d.ts +0 -0
- package/package/blocks/embed/embed.lite.d.ts +0 -0
- package/package/blocks/form/form.lite.d.ts +0 -0
- package/package/blocks/fragment/fragment.lite.d.ts +0 -0
- package/package/blocks/image/image.lite.d.ts +0 -0
- package/package/blocks/img/img.lite.d.ts +0 -0
- package/package/blocks/input/input.lite.d.ts +0 -0
- package/package/blocks/raw-text/raw-text.lite.d.ts +0 -0
- package/package/blocks/section/section.lite.d.ts +0 -0
- package/package/blocks/select/select.lite.d.ts +0 -0
- package/package/blocks/submit-button/submit-button.lite.d.ts +0 -0
- package/package/blocks/symbol/symbol.lite.d.ts +0 -0
- package/package/blocks/text/text.lite.d.ts +0 -0
- package/package/blocks/textarea/textarea.lite.d.ts +0 -0
- package/package/blocks/video/video.lite.d.ts +0 -0
- package/package/components/render-block/block-styles.lite.d.ts +0 -0
- package/package/components/render-block/render-block.lite.d.ts +0 -0
- package/package/components/render-block/render-component.lite.d.ts +0 -0
- package/package/components/render-block/render-repeated-block.lite.d.ts +0 -0
- package/package/components/render-blocks.lite.d.ts +0 -0
- package/package/components/render-content/components/render-styles.lite.d.ts +0 -0
- package/package/components/render-content/render-content.lite.d.ts +0 -0
- package/package/components/render-inlined-styles.lite.d.ts +0 -0
- package/package/functions/convert-style-object.d.ts +0 -1
- package/package/functions/convert-style-object.js +0 -3
- package/package/functions/get-block-styles.d.ts +0 -2
- package/package/functions/get-block-styles.js +0 -21
- package/package/functions/sanitize-styles.d.ts +0 -4
- package/package/functions/sanitize-styles.js +0 -6
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import type { ComponentInfo } from '../../types/components';
|
|
2
|
+
|
|
3
|
+
export const componentInfo: ComponentInfo = {
|
|
4
|
+
name: 'Custom Code',
|
|
5
|
+
static: true,
|
|
6
|
+
builtIn: true,
|
|
7
|
+
requiredPermissions: ['editCode'],
|
|
8
|
+
inputs: [
|
|
9
|
+
{
|
|
10
|
+
name: 'code',
|
|
11
|
+
type: 'html',
|
|
12
|
+
required: true,
|
|
13
|
+
defaultValue: '<p>Hello there, I am custom HTML code!</p>',
|
|
14
|
+
code: true,
|
|
15
|
+
},
|
|
16
|
+
{
|
|
17
|
+
name: 'replaceNodes',
|
|
18
|
+
type: 'boolean',
|
|
19
|
+
helperText: 'Preserve server rendered dom nodes',
|
|
20
|
+
advanced: true,
|
|
21
|
+
},
|
|
22
|
+
{
|
|
23
|
+
name: 'scriptsClientOnly',
|
|
24
|
+
type: 'boolean',
|
|
25
|
+
defaultValue: false,
|
|
26
|
+
helperText:
|
|
27
|
+
'Only print and run scripts on the client. Important when scripts influence DOM that could be replaced when client loads',
|
|
28
|
+
advanced: true,
|
|
29
|
+
},
|
|
30
|
+
],
|
|
31
|
+
};
|
|
@@ -13,17 +13,14 @@
|
|
|
13
13
|
|
|
14
14
|
function findAndRunScripts() {
|
|
15
15
|
// TODO: Move this function to standalone one in '@builder.io/utils'
|
|
16
|
-
if (elem && typeof window !== "undefined") {
|
|
16
|
+
if (elem && elem.getElementsByTagName && typeof window !== "undefined") {
|
|
17
17
|
const scripts = elem.getElementsByTagName("script");
|
|
18
|
-
|
|
19
18
|
for (let i = 0; i < scripts.length; i++) {
|
|
20
19
|
const script = scripts[i];
|
|
21
|
-
|
|
22
20
|
if (script.src) {
|
|
23
21
|
if (scriptsInserted.includes(script.src)) {
|
|
24
22
|
continue;
|
|
25
23
|
}
|
|
26
|
-
|
|
27
24
|
scriptsInserted.push(script.src);
|
|
28
25
|
const newScript = document.createElement("script");
|
|
29
26
|
newScript.async = true;
|
|
@@ -40,7 +37,6 @@
|
|
|
40
37
|
if (scriptsRun.includes(script.innerText)) {
|
|
41
38
|
continue;
|
|
42
39
|
}
|
|
43
|
-
|
|
44
40
|
try {
|
|
45
41
|
scriptsRun.push(script.innerText);
|
|
46
42
|
new Function(script.innerText)();
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
import type { ComponentInfo } from '../../types/components';
|
|
2
|
+
import { markSerializable } from '../util.js';
|
|
3
|
+
|
|
4
|
+
export const componentInfo: ComponentInfo = {
|
|
5
|
+
name: 'Embed',
|
|
6
|
+
static: true,
|
|
7
|
+
builtIn: true,
|
|
8
|
+
inputs: [
|
|
9
|
+
{
|
|
10
|
+
name: 'url',
|
|
11
|
+
type: 'url',
|
|
12
|
+
required: true,
|
|
13
|
+
defaultValue: '',
|
|
14
|
+
helperText: 'e.g. enter a youtube url, google map, etc',
|
|
15
|
+
onChange: markSerializable((options: Map<string, any>) => {
|
|
16
|
+
const url = options.get('url');
|
|
17
|
+
if (url) {
|
|
18
|
+
options.set('content', 'Loading...');
|
|
19
|
+
// TODO: get this out of here!
|
|
20
|
+
const apiKey = 'ae0e60e78201a3f2b0de4b';
|
|
21
|
+
return fetch(
|
|
22
|
+
`https://iframe.ly/api/iframely?url=${url}&api_key=${apiKey}`
|
|
23
|
+
)
|
|
24
|
+
.then((res) => res.json())
|
|
25
|
+
.then((data) => {
|
|
26
|
+
if (options.get('url') === url) {
|
|
27
|
+
if (data.html) {
|
|
28
|
+
options.set('content', data.html);
|
|
29
|
+
} else {
|
|
30
|
+
options.set('content', 'Invalid url, please try another');
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
})
|
|
34
|
+
.catch((_err) => {
|
|
35
|
+
options.set(
|
|
36
|
+
'content',
|
|
37
|
+
'There was an error embedding this URL, please try again or another URL'
|
|
38
|
+
);
|
|
39
|
+
});
|
|
40
|
+
} else {
|
|
41
|
+
options.delete('content');
|
|
42
|
+
}
|
|
43
|
+
}),
|
|
44
|
+
},
|
|
45
|
+
{
|
|
46
|
+
name: 'content',
|
|
47
|
+
type: 'html',
|
|
48
|
+
defaultValue:
|
|
49
|
+
'<div style="padding: 20px; text-align: center">(Choose an embed URL)<div>',
|
|
50
|
+
hideFromUI: true,
|
|
51
|
+
},
|
|
52
|
+
],
|
|
53
|
+
};
|
|
@@ -12,11 +12,10 @@
|
|
|
12
12
|
export let content: EmbedProps["content"];
|
|
13
13
|
|
|
14
14
|
function findAndRunScripts() {
|
|
15
|
+
if (!elem || !elem.getElementsByTagName) return;
|
|
15
16
|
const scripts = elem.getElementsByTagName("script");
|
|
16
|
-
|
|
17
17
|
for (let i = 0; i < scripts.length; i++) {
|
|
18
18
|
const script = scripts[i];
|
|
19
|
-
|
|
20
19
|
if (script.src && !scriptsInserted.includes(script.src)) {
|
|
21
20
|
scriptsInserted.push(script.src);
|
|
22
21
|
const newScript = document.createElement("script");
|
|
@@ -0,0 +1,282 @@
|
|
|
1
|
+
import type { ComponentInfo } from '../../types/components';
|
|
2
|
+
|
|
3
|
+
export const componentInfo: ComponentInfo = {
|
|
4
|
+
name: 'Form:Form',
|
|
5
|
+
builtIn: true,
|
|
6
|
+
// editableTags: ['builder-form-error']
|
|
7
|
+
defaults: {
|
|
8
|
+
responsiveStyles: {
|
|
9
|
+
large: {
|
|
10
|
+
marginTop: '15px',
|
|
11
|
+
paddingBottom: '15px',
|
|
12
|
+
},
|
|
13
|
+
},
|
|
14
|
+
},
|
|
15
|
+
image:
|
|
16
|
+
'https://cdn.builder.io/api/v1/image/assets%2FIsxPKMo2gPRRKeakUztj1D6uqed2%2Fef36d2a846134910b64b88e6d18c5ca5',
|
|
17
|
+
inputs: [
|
|
18
|
+
{
|
|
19
|
+
name: 'sendSubmissionsTo',
|
|
20
|
+
type: 'string',
|
|
21
|
+
// TODO: save to builder data and user can download as csv
|
|
22
|
+
// TODO: easy for mode too or computed add/remove fields form mode
|
|
23
|
+
// so you can edit details and high level mode at same time...
|
|
24
|
+
// Later - more integrations like mailchimp
|
|
25
|
+
// /api/v1/form-submit?to=mailchimp
|
|
26
|
+
enum: [
|
|
27
|
+
{
|
|
28
|
+
label: 'Send to email',
|
|
29
|
+
value: 'email',
|
|
30
|
+
helperText:
|
|
31
|
+
'Send form submissions to the email address of your choosing',
|
|
32
|
+
},
|
|
33
|
+
{
|
|
34
|
+
label: 'Custom',
|
|
35
|
+
value: 'custom',
|
|
36
|
+
helperText:
|
|
37
|
+
'Handle where the form requests go manually with a little code, e.g. to your own custom backend',
|
|
38
|
+
},
|
|
39
|
+
],
|
|
40
|
+
defaultValue: 'email',
|
|
41
|
+
},
|
|
42
|
+
{
|
|
43
|
+
name: 'sendSubmissionsToEmail',
|
|
44
|
+
type: 'string',
|
|
45
|
+
required: true, // TODO: required: () => options.get("sendSubmissionsTo") === "email"
|
|
46
|
+
defaultValue: 'your@email.com',
|
|
47
|
+
showIf: 'options.get("sendSubmissionsTo") === "email"',
|
|
48
|
+
},
|
|
49
|
+
{
|
|
50
|
+
name: 'sendWithJs',
|
|
51
|
+
type: 'boolean',
|
|
52
|
+
helperText: 'Set to false to use basic html form action',
|
|
53
|
+
defaultValue: true,
|
|
54
|
+
showIf: 'options.get("sendSubmissionsTo") === "custom"',
|
|
55
|
+
},
|
|
56
|
+
{
|
|
57
|
+
name: 'name',
|
|
58
|
+
type: 'string',
|
|
59
|
+
defaultValue: 'My form',
|
|
60
|
+
// advanced: true
|
|
61
|
+
},
|
|
62
|
+
{
|
|
63
|
+
name: 'action',
|
|
64
|
+
type: 'string',
|
|
65
|
+
helperText: 'URL to send the form data to',
|
|
66
|
+
showIf: 'options.get("sendSubmissionsTo") === "custom"',
|
|
67
|
+
},
|
|
68
|
+
{
|
|
69
|
+
name: 'contentType',
|
|
70
|
+
type: 'string',
|
|
71
|
+
defaultValue: 'application/json',
|
|
72
|
+
advanced: true,
|
|
73
|
+
// TODO: do automatically if file input
|
|
74
|
+
enum: [
|
|
75
|
+
'application/json',
|
|
76
|
+
'multipart/form-data',
|
|
77
|
+
'application/x-www-form-urlencoded',
|
|
78
|
+
],
|
|
79
|
+
showIf:
|
|
80
|
+
'options.get("sendSubmissionsTo") === "custom" && options.get("sendWithJs") === true',
|
|
81
|
+
},
|
|
82
|
+
{
|
|
83
|
+
name: 'method',
|
|
84
|
+
type: 'string',
|
|
85
|
+
showIf: 'options.get("sendSubmissionsTo") === "custom"',
|
|
86
|
+
defaultValue: 'POST',
|
|
87
|
+
advanced: true,
|
|
88
|
+
},
|
|
89
|
+
{
|
|
90
|
+
name: 'previewState',
|
|
91
|
+
type: 'string',
|
|
92
|
+
// TODO: persist: false flag
|
|
93
|
+
enum: ['unsubmitted', 'sending', 'success', 'error'],
|
|
94
|
+
defaultValue: 'unsubmitted',
|
|
95
|
+
helperText:
|
|
96
|
+
'Choose a state to edit, e.g. choose "success" to show what users see on success and edit the message',
|
|
97
|
+
showIf:
|
|
98
|
+
'options.get("sendSubmissionsTo") !== "zapier" && options.get("sendWithJs") === true',
|
|
99
|
+
},
|
|
100
|
+
{
|
|
101
|
+
name: 'successUrl',
|
|
102
|
+
type: 'url',
|
|
103
|
+
helperText:
|
|
104
|
+
'Optional URL to redirect the user to on form submission success',
|
|
105
|
+
showIf:
|
|
106
|
+
'options.get("sendSubmissionsTo") !== "zapier" && options.get("sendWithJs") === true',
|
|
107
|
+
},
|
|
108
|
+
{
|
|
109
|
+
name: 'resetFormOnSubmit',
|
|
110
|
+
type: 'boolean',
|
|
111
|
+
showIf:
|
|
112
|
+
"options.get('sendSubmissionsTo') === 'custom' && options.get('sendWithJs') === true",
|
|
113
|
+
advanced: true,
|
|
114
|
+
},
|
|
115
|
+
{
|
|
116
|
+
name: 'successMessage',
|
|
117
|
+
type: 'uiBlocks',
|
|
118
|
+
hideFromUI: true,
|
|
119
|
+
defaultValue: [
|
|
120
|
+
{
|
|
121
|
+
'@type': '@builder.io/sdk:Element',
|
|
122
|
+
responsiveStyles: {
|
|
123
|
+
large: {
|
|
124
|
+
marginTop: '10px',
|
|
125
|
+
},
|
|
126
|
+
},
|
|
127
|
+
component: {
|
|
128
|
+
name: 'Text',
|
|
129
|
+
options: {
|
|
130
|
+
text: '<span>Thanks!</span>',
|
|
131
|
+
},
|
|
132
|
+
},
|
|
133
|
+
},
|
|
134
|
+
],
|
|
135
|
+
},
|
|
136
|
+
{
|
|
137
|
+
name: 'validate',
|
|
138
|
+
type: 'boolean',
|
|
139
|
+
defaultValue: true,
|
|
140
|
+
advanced: true,
|
|
141
|
+
},
|
|
142
|
+
{
|
|
143
|
+
name: 'errorMessagePath',
|
|
144
|
+
type: 'text',
|
|
145
|
+
advanced: true,
|
|
146
|
+
helperText:
|
|
147
|
+
'Path to where to get the error message from in a JSON response to display to the user, e.g. "error.message" for a response like { "error": { "message": "this username is taken" }}',
|
|
148
|
+
},
|
|
149
|
+
{
|
|
150
|
+
name: 'errorMessage',
|
|
151
|
+
type: 'uiBlocks',
|
|
152
|
+
hideFromUI: true,
|
|
153
|
+
defaultValue: [
|
|
154
|
+
{
|
|
155
|
+
'@type': '@builder.io/sdk:Element',
|
|
156
|
+
responsiveStyles: {
|
|
157
|
+
large: {
|
|
158
|
+
marginTop: '10px',
|
|
159
|
+
},
|
|
160
|
+
},
|
|
161
|
+
bindings: {
|
|
162
|
+
'component.options.text':
|
|
163
|
+
'state.formErrorMessage || block.component.options.text',
|
|
164
|
+
},
|
|
165
|
+
component: {
|
|
166
|
+
name: 'Text',
|
|
167
|
+
options: {
|
|
168
|
+
text: '<span>Form submission error :( Please check your answers and try again</span>',
|
|
169
|
+
},
|
|
170
|
+
},
|
|
171
|
+
},
|
|
172
|
+
],
|
|
173
|
+
},
|
|
174
|
+
{
|
|
175
|
+
name: 'sendingMessage',
|
|
176
|
+
type: 'uiBlocks',
|
|
177
|
+
hideFromUI: true,
|
|
178
|
+
defaultValue: [
|
|
179
|
+
{
|
|
180
|
+
'@type': '@builder.io/sdk:Element',
|
|
181
|
+
responsiveStyles: {
|
|
182
|
+
large: {
|
|
183
|
+
marginTop: '10px',
|
|
184
|
+
},
|
|
185
|
+
},
|
|
186
|
+
component: {
|
|
187
|
+
name: 'Text',
|
|
188
|
+
options: {
|
|
189
|
+
text: '<span>Sending...</span>',
|
|
190
|
+
},
|
|
191
|
+
},
|
|
192
|
+
},
|
|
193
|
+
],
|
|
194
|
+
},
|
|
195
|
+
{
|
|
196
|
+
name: 'customHeaders',
|
|
197
|
+
type: 'map',
|
|
198
|
+
valueType: {
|
|
199
|
+
type: 'string',
|
|
200
|
+
},
|
|
201
|
+
advanced: true,
|
|
202
|
+
showIf:
|
|
203
|
+
'options.get("sendSubmissionsTo") === "custom" && options.get("sendWithJs") === true',
|
|
204
|
+
},
|
|
205
|
+
],
|
|
206
|
+
noWrap: true,
|
|
207
|
+
canHaveChildren: true,
|
|
208
|
+
defaultChildren: [
|
|
209
|
+
{
|
|
210
|
+
'@type': '@builder.io/sdk:Element',
|
|
211
|
+
responsiveStyles: {
|
|
212
|
+
large: {
|
|
213
|
+
marginTop: '10px',
|
|
214
|
+
},
|
|
215
|
+
},
|
|
216
|
+
component: {
|
|
217
|
+
name: 'Text',
|
|
218
|
+
options: {
|
|
219
|
+
text: '<span>Enter your name</span>',
|
|
220
|
+
},
|
|
221
|
+
},
|
|
222
|
+
},
|
|
223
|
+
{
|
|
224
|
+
'@type': '@builder.io/sdk:Element',
|
|
225
|
+
responsiveStyles: {
|
|
226
|
+
large: {
|
|
227
|
+
marginTop: '10px',
|
|
228
|
+
},
|
|
229
|
+
},
|
|
230
|
+
component: {
|
|
231
|
+
name: 'Form:Input',
|
|
232
|
+
options: {
|
|
233
|
+
name: 'name',
|
|
234
|
+
placeholder: 'Jane Doe',
|
|
235
|
+
},
|
|
236
|
+
},
|
|
237
|
+
},
|
|
238
|
+
{
|
|
239
|
+
'@type': '@builder.io/sdk:Element',
|
|
240
|
+
responsiveStyles: {
|
|
241
|
+
large: {
|
|
242
|
+
marginTop: '10px',
|
|
243
|
+
},
|
|
244
|
+
},
|
|
245
|
+
component: {
|
|
246
|
+
name: 'Text',
|
|
247
|
+
options: {
|
|
248
|
+
text: '<span>Enter your email</span>',
|
|
249
|
+
},
|
|
250
|
+
},
|
|
251
|
+
},
|
|
252
|
+
{
|
|
253
|
+
'@type': '@builder.io/sdk:Element',
|
|
254
|
+
responsiveStyles: {
|
|
255
|
+
large: {
|
|
256
|
+
marginTop: '10px',
|
|
257
|
+
},
|
|
258
|
+
},
|
|
259
|
+
component: {
|
|
260
|
+
name: 'Form:Input',
|
|
261
|
+
options: {
|
|
262
|
+
name: 'email',
|
|
263
|
+
placeholder: 'jane@doe.com',
|
|
264
|
+
},
|
|
265
|
+
},
|
|
266
|
+
},
|
|
267
|
+
{
|
|
268
|
+
'@type': '@builder.io/sdk:Element',
|
|
269
|
+
responsiveStyles: {
|
|
270
|
+
large: {
|
|
271
|
+
marginTop: '10px',
|
|
272
|
+
},
|
|
273
|
+
},
|
|
274
|
+
component: {
|
|
275
|
+
name: 'Form:SubmitButton',
|
|
276
|
+
options: {
|
|
277
|
+
text: 'Submit',
|
|
278
|
+
},
|
|
279
|
+
},
|
|
280
|
+
},
|
|
281
|
+
],
|
|
282
|
+
};
|
|
@@ -8,6 +8,7 @@
|
|
|
8
8
|
* This component was copied over from the old SDKs and has a lot of code pointing to invalid functions/env vars. It needs
|
|
9
9
|
* to be cleaned up before the component can actually be usable.
|
|
10
10
|
*/
|
|
11
|
+
|
|
11
12
|
interface BuilderElement {}
|
|
12
13
|
|
|
13
14
|
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
|
@@ -19,6 +20,7 @@
|
|
|
19
20
|
* This component was copied over from the old SDKs and has a lot of code pointing to invalid functions/env vars. It needs
|
|
20
21
|
* to be cleaned up before the component can actually be usable.
|
|
21
22
|
*/
|
|
23
|
+
|
|
22
24
|
export interface FormProps {
|
|
23
25
|
attributes?: any;
|
|
24
26
|
name?: string;
|
|
@@ -51,6 +53,7 @@
|
|
|
51
53
|
* This component was copied over from the old SDKs and has a lot of code pointing to invalid functions/env vars. It needs
|
|
52
54
|
* to be cleaned up before the component can actually be usable.
|
|
53
55
|
*/
|
|
56
|
+
|
|
54
57
|
export type FormState = "unsubmitted" | "sending" | "success" | "error";
|
|
55
58
|
</script>
|
|
56
59
|
|
|
@@ -84,7 +87,6 @@
|
|
|
84
87
|
|
|
85
88
|
function onSubmit(event) {
|
|
86
89
|
const sendWithJs = sendWithJs || sendSubmissionsTo === "email";
|
|
87
|
-
|
|
88
90
|
if (sendSubmissionsTo === "zapier") {
|
|
89
91
|
event.preventDefault();
|
|
90
92
|
} else if (sendWithJs) {
|
|
@@ -92,13 +94,13 @@
|
|
|
92
94
|
event.preventDefault();
|
|
93
95
|
return;
|
|
94
96
|
}
|
|
95
|
-
|
|
96
97
|
event.preventDefault();
|
|
97
98
|
const el = event.currentTarget;
|
|
98
99
|
const headers = customHeaders || {};
|
|
99
100
|
let body;
|
|
100
|
-
const formData = new FormData(el);
|
|
101
|
+
const formData = new FormData(el);
|
|
101
102
|
|
|
103
|
+
// TODO: maybe support null
|
|
102
104
|
const formPairs = Array.from(
|
|
103
105
|
event.currentTarget.querySelectorAll("input,select,textarea")
|
|
104
106
|
)
|
|
@@ -106,7 +108,6 @@
|
|
|
106
108
|
.map((el) => {
|
|
107
109
|
let value;
|
|
108
110
|
const key = el.name;
|
|
109
|
-
|
|
110
111
|
if (el instanceof HTMLInputElement) {
|
|
111
112
|
if (el.type === "radio") {
|
|
112
113
|
if (el.checked) {
|
|
@@ -120,7 +121,6 @@
|
|
|
120
121
|
value = el.checked;
|
|
121
122
|
} else if (el.type === "number" || el.type === "range") {
|
|
122
123
|
const num = el.valueAsNumber;
|
|
123
|
-
|
|
124
124
|
if (!isNaN(num)) {
|
|
125
125
|
value = num;
|
|
126
126
|
}
|
|
@@ -133,18 +133,15 @@
|
|
|
133
133
|
} else {
|
|
134
134
|
value = el.value;
|
|
135
135
|
}
|
|
136
|
-
|
|
137
136
|
return {
|
|
138
137
|
key,
|
|
139
138
|
value,
|
|
140
139
|
};
|
|
141
140
|
});
|
|
142
141
|
let contentType = contentType;
|
|
143
|
-
|
|
144
142
|
if (sendSubmissionsTo === "email") {
|
|
145
143
|
contentType = "multipart/form-data";
|
|
146
144
|
}
|
|
147
|
-
|
|
148
145
|
Array.from(formPairs).forEach(({ value }) => {
|
|
149
146
|
if (
|
|
150
147
|
value instanceof File ||
|
|
@@ -153,10 +150,11 @@
|
|
|
153
150
|
) {
|
|
154
151
|
contentType = "multipart/form-data";
|
|
155
152
|
}
|
|
156
|
-
});
|
|
153
|
+
});
|
|
154
|
+
|
|
155
|
+
// TODO: send as urlEncoded or multipart by default
|
|
157
156
|
// because of ease of use and reliability in browser API
|
|
158
157
|
// for encoding the form?
|
|
159
|
-
|
|
160
158
|
if (contentType !== "application/json") {
|
|
161
159
|
body = formData;
|
|
162
160
|
} else {
|
|
@@ -167,7 +165,6 @@
|
|
|
167
165
|
});
|
|
168
166
|
body = JSON.stringify(json);
|
|
169
167
|
}
|
|
170
|
-
|
|
171
168
|
if (contentType && contentType !== "multipart/form-data") {
|
|
172
169
|
if (
|
|
173
170
|
/* Zapier doesn't allow content-type header to be sent from browsers */
|
|
@@ -176,21 +173,17 @@
|
|
|
176
173
|
headers["content-type"] = contentType;
|
|
177
174
|
}
|
|
178
175
|
}
|
|
179
|
-
|
|
180
176
|
const presubmitEvent = new CustomEvent("presubmit", {
|
|
181
177
|
detail: {
|
|
182
178
|
body,
|
|
183
179
|
},
|
|
184
180
|
});
|
|
185
|
-
|
|
186
181
|
if (formRef) {
|
|
187
182
|
formRef.dispatchEvent(presubmitEvent);
|
|
188
|
-
|
|
189
183
|
if (presubmitEvent.defaultPrevented) {
|
|
190
184
|
return;
|
|
191
185
|
}
|
|
192
186
|
}
|
|
193
|
-
|
|
194
187
|
formState = "sending";
|
|
195
188
|
const formUrl = `${
|
|
196
189
|
builder.env === "dev" ? "http://localhost:5000" : "https://builder.io"
|
|
@@ -198,8 +191,9 @@
|
|
|
198
191
|
sendSubmissionsToEmail || ""
|
|
199
192
|
)}&name=${encodeURIComponent(name || "")}`;
|
|
200
193
|
fetch(
|
|
201
|
-
sendSubmissionsTo === "email"
|
|
202
|
-
|
|
194
|
+
sendSubmissionsTo === "email"
|
|
195
|
+
? formUrl
|
|
196
|
+
: action /* TODO: throw error if no action URL */,
|
|
203
197
|
{
|
|
204
198
|
body,
|
|
205
199
|
headers,
|
|
@@ -209,31 +203,25 @@
|
|
|
209
203
|
async (res) => {
|
|
210
204
|
let body;
|
|
211
205
|
const contentType = res.headers.get("content-type");
|
|
212
|
-
|
|
213
206
|
if (contentType && contentType.indexOf("application/json") !== -1) {
|
|
214
207
|
body = await res.json();
|
|
215
208
|
} else {
|
|
216
209
|
body = await res.text();
|
|
217
210
|
}
|
|
218
|
-
|
|
219
211
|
if (!res.ok && errorMessagePath) {
|
|
220
212
|
/* TODO: allow supplying an error formatter function */
|
|
221
213
|
let message = get(body, errorMessagePath);
|
|
222
|
-
|
|
223
214
|
if (message) {
|
|
224
215
|
if (typeof message !== "string") {
|
|
225
216
|
/* TODO: ideally convert json to yaml so it woul dbe like
|
|
226
217
|
error: - email has been taken */
|
|
227
218
|
message = JSON.stringify(message);
|
|
228
219
|
}
|
|
229
|
-
|
|
230
220
|
formErrorMessage = message;
|
|
231
221
|
}
|
|
232
222
|
}
|
|
233
|
-
|
|
234
223
|
responseData = body;
|
|
235
224
|
formState = res.ok ? "success" : "error";
|
|
236
|
-
|
|
237
225
|
if (res.ok) {
|
|
238
226
|
const submitSuccessEvent = new CustomEvent("submit:success", {
|
|
239
227
|
detail: {
|
|
@@ -241,21 +229,18 @@
|
|
|
241
229
|
body,
|
|
242
230
|
},
|
|
243
231
|
});
|
|
244
|
-
|
|
245
232
|
if (formRef) {
|
|
246
233
|
formRef.dispatchEvent(submitSuccessEvent);
|
|
247
|
-
|
|
248
234
|
if (submitSuccessEvent.defaultPrevented) {
|
|
249
235
|
return;
|
|
250
236
|
}
|
|
251
237
|
/* TODO: option to turn this on/off? */
|
|
252
|
-
|
|
253
238
|
if (resetFormOnSubmit !== false) {
|
|
254
239
|
formRef.reset();
|
|
255
240
|
}
|
|
256
241
|
}
|
|
257
|
-
/* TODO: client side route event first that can be preventDefaulted */
|
|
258
242
|
|
|
243
|
+
/* TODO: client side route event first that can be preventDefaulted */
|
|
259
244
|
if (successUrl) {
|
|
260
245
|
if (formRef) {
|
|
261
246
|
const event = new CustomEvent("route", {
|
|
@@ -264,7 +249,6 @@
|
|
|
264
249
|
},
|
|
265
250
|
});
|
|
266
251
|
formRef.dispatchEvent(event);
|
|
267
|
-
|
|
268
252
|
if (!event.defaultPrevented) {
|
|
269
253
|
location.href = successUrl;
|
|
270
254
|
}
|
|
@@ -280,15 +264,12 @@
|
|
|
280
264
|
error: err,
|
|
281
265
|
},
|
|
282
266
|
});
|
|
283
|
-
|
|
284
267
|
if (formRef) {
|
|
285
268
|
formRef.dispatchEvent(submitErrorEvent);
|
|
286
|
-
|
|
287
269
|
if (submitErrorEvent.defaultPrevented) {
|
|
288
270
|
return;
|
|
289
271
|
}
|
|
290
272
|
}
|
|
291
|
-
|
|
292
273
|
responseData = err;
|
|
293
274
|
formState = "error";
|
|
294
275
|
}
|
|
File without changes
|