@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.
- package/dist/components/Icon.svelte +16 -16
- package/dist/components/content/Markdown.svelte +10 -10
- package/dist/components/form/AntiBot.svelte +12 -12
- package/dist/components/form/Dropzone.svelte +180 -180
- package/dist/components/form/SmartForm.svelte +251 -251
- package/dist/components/integrations/EasyTools.svelte +30 -30
- package/dist/components/layouts/DefaultLayout.svelte +110 -110
- package/dist/components/layouts/FlexBox.svelte +73 -73
- package/dist/components/layouts/MenuLayout.svelte +60 -60
- package/dist/components/layouts/Meta.svelte +28 -28
- package/dist/components/layouts/StyleBox.svelte +17 -17
- package/dist/components/layouts/Tracker.svelte +18 -18
- package/dist/components/layouts/Well.svelte +20 -20
- package/dist/components/presentation/ImageCompare.svelte +180 -180
- package/dist/components/presentation/Logo.svelte +37 -37
- package/package.json +75 -75
|
@@ -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>
|