@builder.io/sdk-svelte 0.0.1-3 → 0.0.1-30
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 +19 -0
- package/package.json +8 -1
- package/src/blocks/button/button.svelte +25 -47
- package/src/blocks/columns/columns.svelte +115 -102
- package/src/blocks/columns/component-info.js +25 -1
- package/src/blocks/custom-code/custom-code.svelte +59 -61
- package/src/blocks/embed/component-info.js +20 -1
- package/src/blocks/embed/embed.svelte +38 -56
- package/src/blocks/embed/helpers.js +9 -0
- package/src/blocks/form/form.svelte +264 -294
- package/src/blocks/fragment/fragment.svelte +1 -25
- package/src/blocks/image/component-info.js +47 -1
- package/src/blocks/image/image.helpers.js +48 -0
- package/src/blocks/image/image.svelte +126 -116
- package/src/blocks/img/img.svelte +25 -35
- package/src/blocks/input/input.svelte +17 -30
- package/src/blocks/raw-text/raw-text.svelte +4 -25
- package/src/blocks/section/section.svelte +20 -35
- package/src/blocks/select/select.svelte +16 -36
- package/src/blocks/submit-button/submit-button.svelte +4 -29
- package/src/blocks/symbol/component-info.js +1 -0
- package/src/blocks/symbol/symbol.svelte +67 -52
- package/src/blocks/text/text.svelte +1 -24
- package/src/blocks/textarea/textarea.svelte +5 -28
- package/src/blocks/video/video.svelte +60 -41
- package/src/components/render-block/block-styles.svelte +54 -50
- package/src/components/render-block/render-block.helpers.js +23 -0
- package/src/components/render-block/render-block.svelte +199 -159
- package/src/components/render-block/render-component.svelte +20 -0
- package/src/components/render-block/render-repeated-block.svelte +29 -0
- package/src/components/render-block/types.js +0 -0
- package/src/components/render-blocks.svelte +74 -79
- package/src/components/render-content/components/render-styles.svelte +43 -63
- package/src/components/render-content/index.js +4 -0
- package/src/components/render-content/render-content.svelte +266 -207
- package/src/components/render-inlined-styles.svelte +15 -43
- package/src/constants/builder-registered-components.js +48 -0
- package/src/constants/device-sizes.js +3 -21
- package/src/context/builder.context.js +7 -1
- package/src/functions/camel-to-kebab-case.js +4 -0
- package/src/functions/convert-style-object.js +6 -0
- package/src/functions/get-block-component-options.js +6 -1
- package/src/functions/get-block-styles.js +7 -4
- 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/fn.test.js +1 -1
- 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 +10 -8
- package/src/types/components.js +0 -0
- package/src/types/element.js +0 -0
- package/src/blocks/button/index.js +0 -7
- package/src/blocks/columns/index.js +0 -7
- package/src/blocks/custom-code/index.js +0 -7
- package/src/blocks/embed/index.js +0 -7
- package/src/blocks/form/index.js +0 -7
- package/src/blocks/fragment/index.js +0 -7
- package/src/blocks/image/index.js +0 -7
- package/src/blocks/img/index.js +0 -7
- package/src/blocks/input/index.js +0 -7
- package/src/blocks/raw-text/index.js +0 -7
- package/src/blocks/section/index.js +0 -7
- package/src/blocks/select/index.js +0 -7
- package/src/blocks/submit-button/index.js +0 -7
- package/src/blocks/symbol/index.js +0 -7
- package/src/blocks/text/index.js +0 -7
- package/src/blocks/textarea/index.js +0 -7
- package/src/blocks/video/index.js +0 -7
- package/src/components/error-boundary.svelte +0 -26
- package/src/functions/macro-eval.js +0 -5
- package/src/functions/previewing-model-name.js +0 -11
|
@@ -1,333 +1,303 @@
|
|
|
1
1
|
<script>
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
export let
|
|
16
|
-
export let
|
|
17
|
-
export let
|
|
18
|
-
export let
|
|
19
|
-
export let
|
|
20
|
-
export let
|
|
21
|
-
export let
|
|
22
|
-
export let
|
|
23
|
-
export let
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
const sendWithJs = sendWithJs || sendSubmissionsTo === 'email';
|
|
36
|
-
|
|
37
|
-
if (sendSubmissionsTo === 'zapier') {
|
|
38
|
-
event.preventDefault();
|
|
39
|
-
} else if (sendWithJs) {
|
|
40
|
-
if (!(action || sendSubmissionsTo === 'email')) {
|
|
41
|
-
event.preventDefault();
|
|
42
|
-
return;
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
event.preventDefault();
|
|
46
|
-
const el = event.currentTarget;
|
|
47
|
-
const headers = customHeaders || {};
|
|
48
|
-
let body;
|
|
49
|
-
const formData = new FormData(el); // TODO: maybe support null
|
|
2
|
+
import RenderBlock from "../../components/render-block/render-block.svelte";
|
|
3
|
+
import { isEditing } from "../../functions/is-editing.js";
|
|
4
|
+
|
|
5
|
+
export let formRef;
|
|
6
|
+
export let previewState;
|
|
7
|
+
export let sendWithJs;
|
|
8
|
+
export let sendSubmissionsTo;
|
|
9
|
+
export let action;
|
|
10
|
+
export let customHeaders;
|
|
11
|
+
export let contentType;
|
|
12
|
+
export let sendSubmissionsToEmail;
|
|
13
|
+
export let name;
|
|
14
|
+
export let method;
|
|
15
|
+
export let errorMessagePath;
|
|
16
|
+
export let resetFormOnSubmit;
|
|
17
|
+
export let successUrl;
|
|
18
|
+
export let validate;
|
|
19
|
+
export let attributes;
|
|
20
|
+
export let builderBlock;
|
|
21
|
+
export let errorMessage;
|
|
22
|
+
export let sendingMessage;
|
|
23
|
+
export let successMessage;
|
|
24
|
+
|
|
25
|
+
const onSubmit = function onSubmit(event) {
|
|
26
|
+
const sendWithJs = sendWithJs || sendSubmissionsTo === "email";
|
|
27
|
+
|
|
28
|
+
if (sendSubmissionsTo === "zapier") {
|
|
29
|
+
event.preventDefault();
|
|
30
|
+
} else if (sendWithJs) {
|
|
31
|
+
if (!(action || sendSubmissionsTo === "email")) {
|
|
32
|
+
event.preventDefault();
|
|
33
|
+
return;
|
|
34
|
+
}
|
|
50
35
|
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
36
|
+
event.preventDefault();
|
|
37
|
+
const el = event.currentTarget;
|
|
38
|
+
const headers = customHeaders || {};
|
|
39
|
+
let body;
|
|
40
|
+
const formData = new FormData(el); // TODO: maybe support null
|
|
41
|
+
|
|
42
|
+
const formPairs = Array.from(
|
|
43
|
+
event.currentTarget.querySelectorAll("input,select,textarea")
|
|
44
|
+
)
|
|
45
|
+
.filter((el) => !!el.name)
|
|
46
|
+
.map((el) => {
|
|
47
|
+
let value;
|
|
48
|
+
const key = el.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.value;
|
|
75
|
+
}
|
|
54
76
|
|
|
55
|
-
if (el instanceof HTMLInputElement) {
|
|
56
|
-
if (el.type === 'radio') {
|
|
57
|
-
if (el.checked) {
|
|
58
|
-
value = el.name;
|
|
59
77
|
return {
|
|
60
78
|
key,
|
|
61
|
-
value
|
|
79
|
+
value,
|
|
62
80
|
};
|
|
63
|
-
}
|
|
64
|
-
|
|
65
|
-
value = el.checked;
|
|
66
|
-
} else if (el.type === 'number' || el.type === 'range') {
|
|
67
|
-
const num = el.valueAsNumber;
|
|
81
|
+
});
|
|
82
|
+
let contentType = contentType;
|
|
68
83
|
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
}
|
|
72
|
-
} else if (el.type === 'file') {
|
|
73
|
-
// TODO: one vs multiple files
|
|
74
|
-
value = el.files;
|
|
75
|
-
} else {
|
|
76
|
-
value = el.value;
|
|
84
|
+
if (sendSubmissionsTo === "email") {
|
|
85
|
+
contentType = "multipart/form-data";
|
|
77
86
|
}
|
|
78
|
-
} else {
|
|
79
|
-
value = el.value;
|
|
80
|
-
}
|
|
81
|
-
|
|
82
|
-
return {
|
|
83
|
-
key,
|
|
84
|
-
value
|
|
85
|
-
};
|
|
86
|
-
});
|
|
87
|
-
let contentType = contentType;
|
|
88
|
-
|
|
89
|
-
if (sendSubmissionsTo === 'email') {
|
|
90
|
-
contentType = 'multipart/form-data';
|
|
91
|
-
}
|
|
92
|
-
|
|
93
|
-
Array.from(formPairs).forEach(({
|
|
94
|
-
value
|
|
95
|
-
}) => {
|
|
96
|
-
if (value instanceof File || Array.isArray(value) && value[0] instanceof File || value instanceof FileList) {
|
|
97
|
-
contentType = 'multipart/form-data';
|
|
98
|
-
}
|
|
99
|
-
}); // TODO: send as urlEncoded or multipart by default
|
|
100
|
-
// because of ease of use and reliability in browser API
|
|
101
|
-
// for encoding the form?
|
|
102
|
-
|
|
103
|
-
if (contentType !== 'application/json') {
|
|
104
|
-
body = formData;
|
|
105
|
-
} else {
|
|
106
|
-
// Json
|
|
107
|
-
const json = {};
|
|
108
|
-
Array.from(formPairs).forEach(({
|
|
109
|
-
value,
|
|
110
|
-
key
|
|
111
|
-
}) => {
|
|
112
|
-
set(json, key, value);
|
|
113
|
-
});
|
|
114
|
-
body = JSON.stringify(json);
|
|
115
|
-
}
|
|
116
|
-
|
|
117
|
-
if (contentType && contentType !== 'multipart/form-data') {
|
|
118
|
-
if (
|
|
119
|
-
/* Zapier doesn't allow content-type header to be sent from browsers */
|
|
120
|
-
!(sendWithJs && action?.includes('zapier.com'))) {
|
|
121
|
-
headers['content-type'] = contentType;
|
|
122
|
-
}
|
|
123
|
-
}
|
|
124
|
-
|
|
125
|
-
const presubmitEvent = new CustomEvent('presubmit', {
|
|
126
|
-
detail: {
|
|
127
|
-
body
|
|
128
|
-
}
|
|
129
|
-
});
|
|
130
|
-
|
|
131
|
-
if (formRef) {
|
|
132
|
-
formRef.dispatchEvent(presubmitEvent);
|
|
133
|
-
|
|
134
|
-
if (presubmitEvent.defaultPrevented) {
|
|
135
|
-
return;
|
|
136
|
-
}
|
|
137
|
-
}
|
|
138
87
|
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
method: method || 'post'
|
|
147
|
-
}).then(async res => {
|
|
148
|
-
let body;
|
|
149
|
-
const contentType = res.headers.get('content-type');
|
|
150
|
-
|
|
151
|
-
if (contentType && contentType.indexOf('application/json') !== -1) {
|
|
152
|
-
body = await res.json();
|
|
153
|
-
} else {
|
|
154
|
-
body = await res.text();
|
|
155
|
-
}
|
|
156
|
-
|
|
157
|
-
if (!res.ok && errorMessagePath) {
|
|
158
|
-
/* TODO: allow supplying an error formatter function */
|
|
159
|
-
let message = get(body, errorMessagePath);
|
|
160
|
-
|
|
161
|
-
if (message) {
|
|
162
|
-
if (typeof message !== 'string') {
|
|
163
|
-
/* TODO: ideally convert json to yaml so it woul dbe like
|
|
164
|
-
error: - email has been taken */
|
|
165
|
-
message = JSON.stringify(message);
|
|
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";
|
|
166
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?
|
|
167
99
|
|
|
168
|
-
|
|
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);
|
|
169
109
|
}
|
|
170
|
-
}
|
|
171
110
|
|
|
172
|
-
|
|
173
|
-
|
|
111
|
+
if (contentType && contentType !== "multipart/form-data") {
|
|
112
|
+
if (
|
|
113
|
+
/* Zapier doesn't allow content-type header to be sent from browsers */
|
|
114
|
+
!(sendWithJs && action?.includes("zapier.com"))
|
|
115
|
+
) {
|
|
116
|
+
headers["content-type"] = contentType;
|
|
117
|
+
}
|
|
118
|
+
}
|
|
174
119
|
|
|
175
|
-
|
|
176
|
-
const submitSuccessEvent = new CustomEvent('submit:success', {
|
|
120
|
+
const presubmitEvent = new CustomEvent("presubmit", {
|
|
177
121
|
detail: {
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
}
|
|
122
|
+
body,
|
|
123
|
+
},
|
|
181
124
|
});
|
|
182
125
|
|
|
183
126
|
if (formRef) {
|
|
184
|
-
formRef.dispatchEvent(
|
|
127
|
+
formRef.dispatchEvent(presubmitEvent);
|
|
185
128
|
|
|
186
|
-
if (
|
|
129
|
+
if (presubmitEvent.defaultPrevented) {
|
|
187
130
|
return;
|
|
188
131
|
}
|
|
189
|
-
/* TODO: option to turn this on/off? */
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
if (resetFormOnSubmit !== false) {
|
|
193
|
-
formRef.reset();
|
|
194
|
-
}
|
|
195
132
|
}
|
|
196
|
-
/* TODO: client side route event first that can be preventDefaulted */
|
|
197
133
|
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
} else {
|
|
212
|
-
location.href = successUrl;
|
|
134
|
+
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
|
+
sendSubmissionsToEmail || ""
|
|
139
|
+
)}&name=${encodeURIComponent(name || "")}`;
|
|
140
|
+
fetch(
|
|
141
|
+
sendSubmissionsTo === "email" ? formUrl : action,
|
|
142
|
+
/* TODO: throw error if no action URL */
|
|
143
|
+
{
|
|
144
|
+
body,
|
|
145
|
+
headers,
|
|
146
|
+
method: method || "post",
|
|
213
147
|
}
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
formRef.dispatchEvent(submitErrorEvent);
|
|
225
|
-
|
|
226
|
-
if (submitErrorEvent.defaultPrevented) {
|
|
227
|
-
return;
|
|
228
|
-
}
|
|
229
|
-
}
|
|
230
|
-
|
|
231
|
-
responseData = err;
|
|
232
|
-
formState = 'error';
|
|
233
|
-
});
|
|
234
|
-
}
|
|
235
|
-
}
|
|
236
|
-
$: submissionState = () => {
|
|
237
|
-
return isEditing() && previewState || formState;
|
|
238
|
-
};
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
let formState = 'unsubmitted';
|
|
243
|
-
let responseData = null;
|
|
244
|
-
let formErrorMessage = '';
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
</script>
|
|
252
|
-
|
|
253
|
-
<form {...attributes} validate={validate} bind:this={formRef} action={!sendWithJs && action} method={method} name={name} on:submit="{event => onSubmit(event)}" >
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
{#if builderBlock && builderBlock.children }
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
{#each builderBlock?.children as block, index }
|
|
261
|
-
<RenderBlock block={block} ></RenderBlock>
|
|
262
|
-
{/each}
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
{/if}
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
{#if submissionState() === 'error' }
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
<svelte:component dataPath="errorMessage" blocks={errorMessage} this={BuilderBlocks} ></svelte:component>
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
{/if}
|
|
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
|
+
}
|
|
282
158
|
|
|
159
|
+
if (!res.ok && errorMessagePath) {
|
|
160
|
+
/* TODO: allow supplying an error formatter function */
|
|
161
|
+
let message = get(body, errorMessagePath);
|
|
283
162
|
|
|
284
|
-
|
|
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
|
+
}
|
|
285
169
|
|
|
286
|
-
|
|
170
|
+
formErrorMessage = message;
|
|
171
|
+
}
|
|
172
|
+
}
|
|
287
173
|
|
|
288
|
-
|
|
289
|
-
|
|
174
|
+
responseData = body;
|
|
175
|
+
formState = res.ok ? "success" : "error";
|
|
290
176
|
|
|
291
|
-
|
|
177
|
+
if (res.ok) {
|
|
178
|
+
const submitSuccessEvent = new CustomEvent("submit:success", {
|
|
179
|
+
detail: {
|
|
180
|
+
res,
|
|
181
|
+
body,
|
|
182
|
+
},
|
|
183
|
+
});
|
|
292
184
|
|
|
185
|
+
if (formRef) {
|
|
186
|
+
formRef.dispatchEvent(submitSuccessEvent);
|
|
293
187
|
|
|
294
|
-
{
|
|
188
|
+
if (submitSuccessEvent.defaultPrevented) {
|
|
189
|
+
return;
|
|
190
|
+
}
|
|
191
|
+
/* TODO: option to turn this on/off? */
|
|
295
192
|
|
|
193
|
+
if (resetFormOnSubmit !== false) {
|
|
194
|
+
formRef.reset();
|
|
195
|
+
}
|
|
196
|
+
}
|
|
197
|
+
/* TODO: client side route event first that can be preventDefaulted */
|
|
198
|
+
|
|
199
|
+
if (successUrl) {
|
|
200
|
+
if (formRef) {
|
|
201
|
+
const event = new CustomEvent("route", {
|
|
202
|
+
detail: {
|
|
203
|
+
url: successUrl,
|
|
204
|
+
},
|
|
205
|
+
});
|
|
206
|
+
formRef.dispatchEvent(event);
|
|
207
|
+
|
|
208
|
+
if (!event.defaultPrevented) {
|
|
209
|
+
location.href = successUrl;
|
|
210
|
+
}
|
|
211
|
+
} else {
|
|
212
|
+
location.href = successUrl;
|
|
213
|
+
}
|
|
214
|
+
}
|
|
215
|
+
}
|
|
216
|
+
},
|
|
217
|
+
(err) => {
|
|
218
|
+
const submitErrorEvent = new CustomEvent("submit:error", {
|
|
219
|
+
detail: {
|
|
220
|
+
error: err,
|
|
221
|
+
},
|
|
222
|
+
});
|
|
296
223
|
|
|
297
|
-
|
|
224
|
+
if (formRef) {
|
|
225
|
+
formRef.dispatchEvent(submitErrorEvent);
|
|
298
226
|
|
|
299
|
-
|
|
227
|
+
if (submitErrorEvent.defaultPrevented) {
|
|
228
|
+
return;
|
|
229
|
+
}
|
|
230
|
+
}
|
|
300
231
|
|
|
301
|
-
|
|
302
|
-
|
|
232
|
+
responseData = err;
|
|
233
|
+
formState = "error";
|
|
234
|
+
}
|
|
235
|
+
);
|
|
236
|
+
}
|
|
237
|
+
};
|
|
238
|
+
$: submissionState = () => {
|
|
239
|
+
return (isEditing() && previewState) || formState;
|
|
240
|
+
};
|
|
241
|
+
|
|
242
|
+
let formState = "unsubmitted";
|
|
243
|
+
let responseData = null;
|
|
244
|
+
let formErrorMessage = "";
|
|
245
|
+
</script>
|
|
246
|
+
|
|
247
|
+
<form
|
|
248
|
+
{...attributes}
|
|
249
|
+
{validate}
|
|
250
|
+
bind:this={formRef}
|
|
251
|
+
action={!sendWithJs && action}
|
|
252
|
+
{method}
|
|
253
|
+
{name}
|
|
254
|
+
on:submit={(event) => {
|
|
255
|
+
onSubmit(event);
|
|
256
|
+
}}
|
|
257
|
+
>
|
|
258
|
+
{#if builderBlock && builderBlock.children}
|
|
259
|
+
{#each builderBlock?.children as block, undefined}
|
|
260
|
+
<RenderBlock {block} />
|
|
261
|
+
{/each}
|
|
262
|
+
{/if}
|
|
263
|
+
|
|
264
|
+
{#if submissionState() === "error"}
|
|
265
|
+
<svelte:component
|
|
266
|
+
this={BuilderBlocks}
|
|
267
|
+
dataPath="errorMessage"
|
|
268
|
+
blocks={errorMessage}
|
|
269
|
+
/>
|
|
270
|
+
{/if}
|
|
271
|
+
|
|
272
|
+
{#if submissionState() === "sending"}
|
|
273
|
+
<svelte:component
|
|
274
|
+
this={BuilderBlocks}
|
|
275
|
+
dataPath="sendingMessage"
|
|
276
|
+
blocks={sendingMessage}
|
|
277
|
+
/>
|
|
278
|
+
{/if}
|
|
279
|
+
|
|
280
|
+
{#if submissionState() === "error" && responseData}
|
|
281
|
+
<pre class="builder-form-error-text pre">
|
|
303
282
|
|
|
304
283
|
{JSON.stringify(responseData, null, 2)}
|
|
305
284
|
|
|
306
285
|
</pre>
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
{
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
</form>
|
|
327
|
-
|
|
328
|
-
<style>
|
|
329
|
-
.pre {
|
|
330
|
-
padding: 10px;
|
|
331
|
-
color: red;
|
|
332
|
-
text-align: center; }
|
|
333
|
-
</style>
|
|
286
|
+
{/if}
|
|
287
|
+
|
|
288
|
+
{#if submissionState() === "success"}
|
|
289
|
+
<svelte:component
|
|
290
|
+
this={BuilderBlocks}
|
|
291
|
+
dataPath="successMessage"
|
|
292
|
+
blocks={successMessage}
|
|
293
|
+
/>
|
|
294
|
+
{/if}
|
|
295
|
+
</form>
|
|
296
|
+
|
|
297
|
+
<style>
|
|
298
|
+
.pre {
|
|
299
|
+
padding: 10px;
|
|
300
|
+
color: red;
|
|
301
|
+
text-align: center;
|
|
302
|
+
}
|
|
303
|
+
</style>
|
|
@@ -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",
|