@functionalcms/svelte-components 5.0.0-beta1 → 5.0.0-beta3

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.
@@ -1,251 +1,251 @@
1
- <script lang="ts">
2
- import {
3
- type Field,
4
- type SelectField,
5
- type CollectionField,
6
- type TextareaField,
7
- type FieldType,
8
- type InputField,
9
- type FilePickerField,
10
- type PhoneInputField,
11
- type TimePickerField,
12
- SubmitResult,
13
- type ButtonConfig
14
- } from './form.js';
15
- import {
16
- Button,
17
- Label,
18
- Fileupload,
19
- Select,
20
- MultiSelect,
21
- Textarea,
22
- Toggle,
23
- Input,
24
- FloatingLabelInput,
25
- Timepicker,
26
- PhoneInput
27
- } from 'flowbite-svelte';
28
- import { fade } from 'svelte/transition';
29
-
30
- interface Props {
31
- action: string;
32
- css?: string;
33
- successMessage?: string;
34
- fields?: Array<Field>;
35
- onMessageSubmitted?: (result: SubmitResult) => void;
36
- buttons: Array<ButtonConfig>;
37
- }
38
-
39
- let {
40
- action,
41
- fields = [],
42
- css = '',
43
- successMessage,
44
- onMessageSubmitted,
45
- buttons = [
46
- {
47
- label: 'Submit',
48
- type: 'submit',
49
- action: undefined
50
- }
51
- ]
52
- }: Props = $props();
53
-
54
- let form: HTMLFormElement;
55
- let showMessage = $state(false);
56
- let isSendingMessage = $state(false);
57
- let loading = $state(false);
58
-
59
- const handleSubmit = async (event: Event) => {
60
- event.preventDefault();
61
- console.log('Submitting form to:', action);
62
- loading = true;
63
- try {
64
- if (!isSendingMessage) {
65
- isSendingMessage = true;
66
- const formData = new FormData(form);
67
- const response = await fetch(action, {
68
- method: 'POST',
69
- body: formData
70
- });
71
- showMessage = response.status === 200;
72
- onMessageSubmitted?.(showMessage ? SubmitResult.Success : SubmitResult.Error);
73
- setTimeout(() => {
74
- showMessage = false;
75
- }, 3000);
76
- }
77
- } catch (error) {
78
- console.error('Error submitting form:', error);
79
- } finally {
80
- isSendingMessage = false;
81
- }
82
- loading = false;
83
- };
84
- </script>
85
-
86
- {#snippet renderInput(field: InputField)}
87
- {#if field.isFloat}
88
- <FloatingLabelInput
89
- id={field.id}
90
- name={field.id}
91
- required={field.required}
92
- readonly={field.readonly}
93
- disabled={field.disabled}
94
- class={field.class}
95
- size={field.size == 'sm' ? 'small' : 'default'}
96
- type={field.type}
97
- variant={field.floatVariant}
98
- placeholder={field.placeholder}
99
- >
100
- {field.label}
101
- </FloatingLabelInput>
102
- {:else}
103
- <Label for={field.id} class={field.labelClass}>{field.label}</Label>
104
- <Input
105
- id={field.id}
106
- name={field.id}
107
- required={field.required}
108
- readonly={field.readonly}
109
- disabled={field.disabled}
110
- class={field.class}
111
- size={field.size}
112
- type={field.type}
113
- placeholder={field.placeholder}
114
- />
115
- {/if}
116
- {/snippet}
117
-
118
- {#snippet renderTextarea(field: TextareaField)}
119
- <Label for={field.id} class={field.labelClass}>{field.label}</Label>
120
- <Textarea
121
- id={field.id}
122
- name={field.id}
123
- required={field.required}
124
- readonly={field.readonly}
125
- disabled={field.disabled}
126
- class={field.class}
127
- label={field.label}
128
- rows={field.rows}
129
- cols={field.cols}
130
- placeholder={field.placeholder}
131
- />
132
- {/snippet}
133
-
134
- {#snippet renderSelect(field: SelectField)}
135
- <Label class={field.labelClass}
136
- >{field.label}
137
- {#if field.type === 'single'}
138
- <Select
139
- id={field.id}
140
- name={field.id}
141
- required={field.required}
142
- readonly={field.readonly}
143
- disabled={field.disabled}
144
- class={field.class}
145
- items={field.options}
146
- bind:value={field.value}
147
- />
148
- {:else}
149
- <MultiSelect class={field.class} items={field.options} bind:value={field.value} />
150
- {/if}
151
- </Label>
152
- {/snippet}
153
-
154
- {#snippet renderCollection(field: CollectionField)}
155
- {#if field.type === 'checkbox'}{:else if field.type === 'radio'}{:else if field.type === 'toggle'}
156
- <Toggle
157
- id={field.id}
158
- name={field.id}
159
- required={field.required}
160
- readonly={field.readonly}
161
- disabled={field.disabled}
162
- class={field.class}
163
- checked={field.checked}
164
- >
165
- {field.label}
166
- </Toggle>
167
- {/if}
168
- {/snippet}
169
-
170
- {#snippet renderFile(field: FilePickerField)}
171
- <Label class={field.labelClass}>{field.label}</Label>
172
- <Fileupload
173
- id={field.id}
174
- name={field.id}
175
- required={field.required}
176
- readonly={field.readonly}
177
- disabled={field.disabled}
178
- class={field.class}
179
- />
180
- {/snippet}
181
-
182
- {#snippet renderPhoneInput(field: PhoneInputField)}
183
- <PhoneInput
184
- id={field.id}
185
- name={field.id}
186
- required={field.required}
187
- readonly={field.readonly}
188
- disabled={field.disabled}
189
- class={field.class}
190
- size={field.size}
191
- placeholder={field.placeholder}
192
- />
193
- {/snippet}
194
-
195
- {#snippet renderTimePicker(field: TimePickerField)}
196
- <Label for={field.id} class={field.labelClass}>{field.label}</Label>
197
- <Timepicker id={field.id} required={field.required} disabled={field.disabled} />
198
- {/snippet}
199
-
200
- {#if showMessage}
201
- <div class="alert alert-success" transition:fade={{ duration: 2000 }}>
202
- {successMessage}
203
- </div>
204
- {:else}
205
- <form method="POST" {action} class={css} bind:this={form}>
206
- <fieldset>
207
- {#each fields as field}
208
- {#if field.typeOfField === 'input'}
209
- {@render renderInput(field)}
210
- {:else if field.typeOfField === 'textarea'}
211
- {@render renderTextarea(field)}
212
- {:else if field.typeOfField === 'select'}
213
- {@render renderSelect(field)}
214
- {:else if field.typeOfField === 'collection'}
215
- {@render renderCollection(field)}
216
- {:else if field.typeOfField === 'file'}
217
- {@render renderFile(field)}
218
- {:else if field.typeOfField === 'phoneInput'}
219
- {@render renderPhoneInput(field)}
220
- {:else if field.typeOfField === 'timepicker'}
221
- {@render renderTimePicker(field)}
222
- {/if}
223
- {/each}
224
-
225
- <div class="buttons">
226
- {#each buttons as button}
227
- {#if button.type === 'submit'}
228
- <Button
229
- type="button"
230
- class={button.class}
231
- color={button.color}
232
- onclick={handleSubmit}
233
- {loading}
234
- >
235
- {button.label}
236
- </Button>
237
- {:else}
238
- <Button
239
- type={button.type}
240
- class={button.class}
241
- color={button.color}
242
- onclick={button.action}
243
- >
244
- {button.label}
245
- </Button>
246
- {/if}
247
- {/each}
248
- </div>
249
- </fieldset>
250
- </form>
251
- {/if}
1
+ <script lang="ts">
2
+ import {
3
+ type Field,
4
+ type SelectField,
5
+ type CollectionField,
6
+ type TextareaField,
7
+ type FieldType,
8
+ type InputField,
9
+ type FilePickerField,
10
+ type PhoneInputField,
11
+ type TimePickerField,
12
+ SubmitResult,
13
+ type ButtonConfig
14
+ } from './form.js';
15
+ import {
16
+ Button,
17
+ Label,
18
+ Fileupload,
19
+ Select,
20
+ MultiSelect,
21
+ Textarea,
22
+ Toggle,
23
+ Input,
24
+ FloatingLabelInput,
25
+ Timepicker,
26
+ PhoneInput
27
+ } from 'flowbite-svelte';
28
+ import { fade } from 'svelte/transition';
29
+
30
+ interface Props {
31
+ action: string;
32
+ css?: string;
33
+ successMessage?: string;
34
+ fields?: Array<Field>;
35
+ onMessageSubmitted?: (result: SubmitResult) => void;
36
+ buttons: Array<ButtonConfig>;
37
+ }
38
+
39
+ let {
40
+ action,
41
+ fields = [],
42
+ css = '',
43
+ successMessage,
44
+ onMessageSubmitted,
45
+ buttons = [
46
+ {
47
+ label: 'Submit',
48
+ type: 'submit',
49
+ action: undefined
50
+ }
51
+ ]
52
+ }: Props = $props();
53
+
54
+ let form: HTMLFormElement;
55
+ let showMessage = $state(false);
56
+ let isSendingMessage = $state(false);
57
+ let loading = $state(false);
58
+
59
+ const handleSubmit = async (event: Event) => {
60
+ event.preventDefault();
61
+ console.log('Submitting form to:', action);
62
+ loading = true;
63
+ try {
64
+ if (!isSendingMessage) {
65
+ isSendingMessage = true;
66
+ const formData = new FormData(form);
67
+ const response = await fetch(action, {
68
+ method: 'POST',
69
+ body: formData
70
+ });
71
+ showMessage = response.status === 200;
72
+ onMessageSubmitted?.(showMessage ? SubmitResult.Success : SubmitResult.Error);
73
+ setTimeout(() => {
74
+ showMessage = false;
75
+ }, 3000);
76
+ }
77
+ } catch (error) {
78
+ console.error('Error submitting form:', error);
79
+ } finally {
80
+ isSendingMessage = false;
81
+ }
82
+ loading = false;
83
+ };
84
+ </script>
85
+
86
+ {#snippet renderInput(field: InputField)}
87
+ {#if field.isFloat}
88
+ <FloatingLabelInput
89
+ id={field.id}
90
+ name={field.id}
91
+ required={field.required}
92
+ readonly={field.readonly}
93
+ disabled={field.disabled}
94
+ class={field.class}
95
+ size={field.size == 'sm' ? 'small' : 'default'}
96
+ type={field.type}
97
+ variant={field.floatVariant}
98
+ placeholder={field.placeholder}
99
+ >
100
+ {field.label}
101
+ </FloatingLabelInput>
102
+ {:else}
103
+ <Label for={field.id} class={field.labelClass}>{field.label}</Label>
104
+ <Input
105
+ id={field.id}
106
+ name={field.id}
107
+ required={field.required}
108
+ readonly={field.readonly}
109
+ disabled={field.disabled}
110
+ class={field.class}
111
+ size={field.size}
112
+ type={field.type}
113
+ placeholder={field.placeholder}
114
+ />
115
+ {/if}
116
+ {/snippet}
117
+
118
+ {#snippet renderTextarea(field: TextareaField)}
119
+ <Label for={field.id} class={field.labelClass}>{field.label}</Label>
120
+ <Textarea
121
+ id={field.id}
122
+ name={field.id}
123
+ required={field.required}
124
+ readonly={field.readonly}
125
+ disabled={field.disabled}
126
+ class={field.class}
127
+ label={field.label}
128
+ rows={field.rows}
129
+ cols={field.cols}
130
+ placeholder={field.placeholder}
131
+ />
132
+ {/snippet}
133
+
134
+ {#snippet renderSelect(field: SelectField)}
135
+ <Label class={field.labelClass}
136
+ >{field.label}
137
+ {#if field.type === 'single'}
138
+ <Select
139
+ id={field.id}
140
+ name={field.id}
141
+ required={field.required}
142
+ readonly={field.readonly}
143
+ disabled={field.disabled}
144
+ class={field.class}
145
+ items={field.options}
146
+ bind:value={field.value}
147
+ />
148
+ {:else}
149
+ <MultiSelect class={field.class} items={field.options} bind:value={field.value} />
150
+ {/if}
151
+ </Label>
152
+ {/snippet}
153
+
154
+ {#snippet renderCollection(field: CollectionField)}
155
+ {#if field.type === 'checkbox'}{:else if field.type === 'radio'}{:else if field.type === 'toggle'}
156
+ <Toggle
157
+ id={field.id}
158
+ name={field.id}
159
+ required={field.required}
160
+ readonly={field.readonly}
161
+ disabled={field.disabled}
162
+ class={field.class}
163
+ checked={field.checked}
164
+ >
165
+ {field.label}
166
+ </Toggle>
167
+ {/if}
168
+ {/snippet}
169
+
170
+ {#snippet renderFile(field: FilePickerField)}
171
+ <Label class={field.labelClass}>{field.label}</Label>
172
+ <Fileupload
173
+ id={field.id}
174
+ name={field.id}
175
+ required={field.required}
176
+ readonly={field.readonly}
177
+ disabled={field.disabled}
178
+ class={field.class}
179
+ />
180
+ {/snippet}
181
+
182
+ {#snippet renderPhoneInput(field: PhoneInputField)}
183
+ <PhoneInput
184
+ id={field.id}
185
+ name={field.id}
186
+ required={field.required}
187
+ readonly={field.readonly}
188
+ disabled={field.disabled}
189
+ class={field.class}
190
+ size={field.size}
191
+ placeholder={field.placeholder}
192
+ />
193
+ {/snippet}
194
+
195
+ {#snippet renderTimePicker(field: TimePickerField)}
196
+ <Label for={field.id} class={field.labelClass}>{field.label}</Label>
197
+ <Timepicker id={field.id} required={field.required} disabled={field.disabled} />
198
+ {/snippet}
199
+
200
+ {#if showMessage}
201
+ <div class="alert alert-success" transition:fade={{ duration: 2000 }}>
202
+ {successMessage}
203
+ </div>
204
+ {:else}
205
+ <form method="POST" {action} class={css} bind:this={form}>
206
+ <fieldset>
207
+ {#each fields as field}
208
+ {#if field.typeOfField === 'input'}
209
+ {@render renderInput(field)}
210
+ {:else if field.typeOfField === 'textarea'}
211
+ {@render renderTextarea(field)}
212
+ {:else if field.typeOfField === 'select'}
213
+ {@render renderSelect(field)}
214
+ {:else if field.typeOfField === 'collection'}
215
+ {@render renderCollection(field)}
216
+ {:else if field.typeOfField === 'file'}
217
+ {@render renderFile(field)}
218
+ {:else if field.typeOfField === 'phoneInput'}
219
+ {@render renderPhoneInput(field)}
220
+ {:else if field.typeOfField === 'timepicker'}
221
+ {@render renderTimePicker(field)}
222
+ {/if}
223
+ {/each}
224
+
225
+ <div class="buttons">
226
+ {#each buttons as button}
227
+ {#if button.type === 'submit'}
228
+ <Button
229
+ type="button"
230
+ class={button.class}
231
+ color={button.color}
232
+ onclick={handleSubmit}
233
+ {loading}
234
+ >
235
+ {button.label}
236
+ </Button>
237
+ {:else}
238
+ <Button
239
+ type={button.type}
240
+ class={button.class}
241
+ color={button.color}
242
+ onclick={button.action}
243
+ >
244
+ {button.label}
245
+ </Button>
246
+ {/if}
247
+ {/each}
248
+ </div>
249
+ </fieldset>
250
+ </form>
251
+ {/if}
@@ -1,30 +1,30 @@
1
- <script lang="ts">
2
- import { browser } from "$app/environment";
3
-
4
- interface Props {
5
- userId: number;
6
- title?: string;
7
- }
8
-
9
- let { userId, title = "store" }: Props = $props();
10
-
11
- if (browser) {
12
- const handle = `ec_tenant_${userId}`;
13
- window.addEventListener('message', (e) => {
14
- !!e.data.frameHeight &&
15
- e.data.pricingUuid === handle &&
16
- (document.getElementById(handle).style.height = e.data.frameHeight);
17
- });
18
- }
19
- </script>
20
-
21
- <iframe
22
- id="ec_tenant_{userId}"
23
- title={title}
24
- width="100%"
25
- src="https://app.easy.tools/ec/{userId}"
26
- allow="accelerometer; autoplay; encrypted-media; gyroscope; picture-in-picture"
27
- allowfullscreen
28
- frameborder="0"
29
- scrolling="no"
30
- ></iframe>
1
+ <script lang="ts">
2
+ import { browser } from "$app/environment";
3
+
4
+ interface Props {
5
+ userId: number;
6
+ title?: string;
7
+ }
8
+
9
+ let { userId, title = "store" }: Props = $props();
10
+
11
+ if (browser) {
12
+ const handle = `ec_tenant_${userId}`;
13
+ window.addEventListener('message', (e) => {
14
+ !!e.data.frameHeight &&
15
+ e.data.pricingUuid === handle &&
16
+ (document.getElementById(handle).style.height = e.data.frameHeight);
17
+ });
18
+ }
19
+ </script>
20
+
21
+ <iframe
22
+ id="ec_tenant_{userId}"
23
+ title={title}
24
+ width="100%"
25
+ src="https://app.easy.tools/ec/{userId}"
26
+ allow="accelerometer; autoplay; encrypted-media; gyroscope; picture-in-picture"
27
+ allowfullscreen
28
+ frameborder="0"
29
+ scrolling="no"
30
+ ></iframe>