@finsweet/webflow-apps-utils 1.0.3 → 1.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/dist/index.d.ts +1 -1
- package/dist/index.js +1 -1
- package/dist/providers/GlobalProvider.stories.d.ts +5 -0
- package/dist/providers/GlobalProvider.stories.js +419 -0
- package/dist/providers/GlobalProviderDemo.svelte +266 -0
- package/dist/providers/GlobalProviderDemo.svelte.d.ts +3 -0
- package/dist/providers/configuratorUtils.d.ts +11 -14
- package/dist/providers/configuratorUtils.js +68 -115
- package/dist/providers/index.d.ts +1 -1
- package/dist/providers/index.js +1 -1
- package/dist/router/Router.stories.d.ts +6 -0
- package/dist/router/Router.stories.js +564 -0
- package/dist/router/examples/RouterExample.svelte +271 -0
- package/dist/router/examples/RouterExample.svelte.d.ts +18 -0
- package/dist/router/examples/index.d.ts +4 -0
- package/dist/router/examples/index.js +4 -0
- package/dist/router/examples/pages/AboutPage.svelte +568 -0
- package/dist/router/examples/pages/AboutPage.svelte.d.ts +13 -0
- package/dist/router/examples/pages/HomePage.svelte +200 -0
- package/dist/router/examples/pages/HomePage.svelte.d.ts +14 -0
- package/dist/router/examples/pages/NotFoundPage.svelte +307 -0
- package/dist/router/examples/pages/NotFoundPage.svelte.d.ts +17 -0
- package/dist/router/hooks.svelte.d.ts +2 -2
- package/dist/router/index.d.ts +3 -0
- package/dist/router/index.js +3 -0
- package/dist/router/{Link.svelte → providers/Link.svelte} +1 -1
- package/dist/router/{Route.svelte → providers/Route.svelte} +1 -1
- package/dist/router/{Route.svelte.d.ts → providers/Route.svelte.d.ts} +1 -1
- package/dist/router/{Router.svelte → providers/RouterProvider.svelte} +22 -5
- package/dist/router/{Router.svelte.d.ts → providers/RouterProvider.svelte.d.ts} +8 -4
- package/dist/router/providers/index.d.ts +3 -0
- package/dist/router/providers/index.js +3 -0
- package/dist/router/{index.svelte.d.ts → router.svelte.d.ts} +1 -3
- package/dist/router/{index.svelte.js → router.svelte.js} +1 -4
- package/dist/stores/forms/Form.stories.d.ts +5 -0
- package/dist/stores/forms/Form.stories.js +342 -0
- package/dist/stores/forms/FormDemo.svelte +545 -0
- package/dist/stores/forms/FormDemo.svelte.d.ts +18 -0
- package/dist/stores/forms.d.ts +41 -4
- package/dist/stores/forms.js +86 -32
- package/dist/types/customCode.d.ts +1 -1
- package/dist/types/window.d.ts +1 -0
- package/dist/ui/components/button/Button.svelte +1 -1
- package/dist/ui/components/copy-text/CopyText.stories.d.ts +70 -0
- package/dist/ui/components/copy-text/CopyText.stories.js +241 -0
- package/dist/ui/components/copy-text/CopyText.svelte +247 -0
- package/dist/ui/components/copy-text/CopyText.svelte.d.ts +4 -0
- package/dist/ui/components/copy-text/index.d.ts +2 -0
- package/dist/ui/components/copy-text/index.js +1 -0
- package/dist/ui/components/copy-text/types.d.ts +52 -0
- package/dist/ui/components/copy-text/types.js +1 -0
- package/dist/ui/components/index.d.ts +1 -0
- package/dist/ui/components/index.js +1 -0
- package/dist/ui/components/input/Input.stories.d.ts +9 -0
- package/dist/ui/components/input/Input.stories.js +78 -0
- package/dist/ui/components/input/Input.svelte +39 -3
- package/dist/ui/components/input/types.d.ts +6 -0
- package/dist/ui/components/layout/Layout.svelte +45 -64
- package/dist/ui/components/layout/Layout.svelte.d.ts +26 -3
- package/dist/ui/components/layout/examples/ExampleLayout.svelte +32 -27
- package/dist/ui/components/layout/index.d.ts +1 -1
- package/dist/ui/components/layout/test-helpers/TestLayoutWithFooter.svelte +20 -0
- package/dist/ui/components/layout/test-helpers/TestLayoutWithFooter.svelte.d.ts +7 -0
- package/dist/ui/components/layout/types.d.ts +1 -10
- package/dist/ui/components/notification/Notification.stories.svelte +12 -1
- package/dist/ui/components/notification/Notification.svelte +10 -5
- package/dist/ui/components/notification/Notification.svelte.d.ts +1 -1
- package/dist/ui/components/notification/types.d.ts +1 -1
- package/dist/ui/components/section/Section.svelte +8 -4
- package/dist/ui/components/section/types.d.ts +8 -0
- package/dist/ui/components/text/Text.stories.svelte +67 -1
- package/dist/ui/components/text/Text.svelte +209 -8
- package/dist/ui/components/text/types.d.ts +4 -0
- package/dist/ui/index.css +6 -2
- package/dist/utils/animations/factory.d.ts +7 -0
- package/dist/utils/animations/factory.js +101 -0
- package/dist/utils/animations/index.d.ts +7 -0
- package/dist/utils/animations/index.js +62 -0
- package/dist/utils/animations/types.d.ts +39 -0
- package/dist/utils/animations/types.js +1 -0
- package/dist/utils/custom-code/configs.d.ts +22 -0
- package/dist/utils/custom-code/configs.js +40 -0
- package/dist/utils/custom-code/index.d.ts +1 -0
- package/dist/utils/custom-code/index.js +1 -0
- package/dist/utils/diff-mapper/DiffMapper.stories.d.ts +5 -0
- package/dist/utils/diff-mapper/DiffMapper.stories.js +185 -0
- package/dist/utils/diff-mapper/DiffMapperDemo.svelte +351 -0
- package/dist/utils/diff-mapper/DiffMapperDemo.svelte.d.ts +18 -0
- package/dist/utils/diff-mapper/deepDiffMapper.d.ts +31 -0
- package/dist/utils/diff-mapper/deepDiffMapper.js +264 -0
- package/dist/utils/diff-mapper/index.d.ts +1 -0
- package/dist/utils/diff-mapper/index.js +1 -0
- package/dist/utils/helpers/capitalizeFirstLetter.d.ts +4 -0
- package/dist/utils/helpers/capitalizeFirstLetter.js +9 -0
- package/dist/utils/helpers/getTimeNow.d.ts +4 -0
- package/dist/utils/helpers/getTimeNow.js +8 -0
- package/dist/utils/helpers/index.d.ts +4 -0
- package/dist/utils/helpers/index.js +4 -0
- package/dist/utils/helpers/minifyCode.d.ts +10 -0
- package/dist/utils/helpers/minifyCode.js +73 -0
- package/dist/utils/helpers/objectsToModuleExports.d.ts +1 -1
- package/dist/utils/helpers/objectsToModuleExports.js +1 -0
- package/dist/utils/helpers/toHumanReadableList.d.ts +4 -0
- package/dist/utils/helpers/toHumanReadableList.js +11 -0
- package/dist/utils/index.d.ts +2 -0
- package/dist/utils/index.js +2 -0
- package/dist/utils/webflow-canvas/getAllChildren.d.ts +16 -0
- package/dist/utils/webflow-canvas/getAllChildren.js +65 -0
- package/dist/utils/webflow-canvas/getElementClassList.d.ts +9 -0
- package/dist/utils/webflow-canvas/getElementClassList.js +19 -0
- package/dist/utils/webflow-canvas/index.d.ts +2 -0
- package/dist/utils/webflow-canvas/index.js +2 -0
- package/package.json +6 -1
- package/dist/providers/GlobalProvider.mdx +0 -322
- package/dist/router/README.md +0 -397
- /package/dist/router/{Link.svelte.d.ts → providers/Link.svelte.d.ts} +0 -0
|
@@ -0,0 +1,545 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
import { FormValidator } from '../forms';
|
|
3
|
+
|
|
4
|
+
interface DemoFormData {
|
|
5
|
+
name: string;
|
|
6
|
+
instance: string;
|
|
7
|
+
class: string;
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
// Demo state
|
|
11
|
+
let existingInstances = ['fs-slider-1', 'fs-slider-2', 'fs-tabs-1'];
|
|
12
|
+
let isEditMode = false;
|
|
13
|
+
let currentInstance = 'fs-slider-1';
|
|
14
|
+
let classValidationEnabled = true;
|
|
15
|
+
let refreshTrigger = 0;
|
|
16
|
+
|
|
17
|
+
// Create form validator
|
|
18
|
+
const formValidator = new FormValidator<DemoFormData>(
|
|
19
|
+
'demo-form',
|
|
20
|
+
{
|
|
21
|
+
name: 'New Component',
|
|
22
|
+
instance: 'fs-component',
|
|
23
|
+
class: 'fs-component'
|
|
24
|
+
},
|
|
25
|
+
{ existingInstances }
|
|
26
|
+
);
|
|
27
|
+
|
|
28
|
+
// Subscribe to form state using derived stores
|
|
29
|
+
const formValues = formValidator.values;
|
|
30
|
+
const formErrors = formValidator.errors;
|
|
31
|
+
const formTouched = formValidator.touched;
|
|
32
|
+
const formIsValid = formValidator.isValid;
|
|
33
|
+
const formIsDirty = formValidator.isDirty;
|
|
34
|
+
const formIsSubmitting = formValidator.isSubmitting;
|
|
35
|
+
|
|
36
|
+
function forceRefresh() {
|
|
37
|
+
refreshTrigger++;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
function generateNewNames() {
|
|
41
|
+
const generated = FormValidator.generateNames(existingInstances, 'demo', 'Demo Component');
|
|
42
|
+
formValidator.setFields(generated);
|
|
43
|
+
forceRefresh();
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
function toggleEditMode() {
|
|
47
|
+
isEditMode = !isEditMode;
|
|
48
|
+
if (isEditMode) {
|
|
49
|
+
formValidator.ignoreInstanceValidation(currentInstance, existingInstances);
|
|
50
|
+
formValidator.setFields({
|
|
51
|
+
name: currentInstance,
|
|
52
|
+
instance: currentInstance,
|
|
53
|
+
class: currentInstance
|
|
54
|
+
});
|
|
55
|
+
} else {
|
|
56
|
+
formValidator.validateWithInstances(existingInstances);
|
|
57
|
+
}
|
|
58
|
+
forceRefresh();
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
function toggleClassValidation() {
|
|
62
|
+
classValidationEnabled = !classValidationEnabled;
|
|
63
|
+
formValidator.enableClassValidation(classValidationEnabled);
|
|
64
|
+
forceRefresh();
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
function addExistingInstance() {
|
|
68
|
+
const newInstance = `fs-new-${Date.now()}`;
|
|
69
|
+
existingInstances = [...existingInstances, newInstance];
|
|
70
|
+
formValidator.validateWithInstances(existingInstances);
|
|
71
|
+
forceRefresh();
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
function resetForm() {
|
|
75
|
+
formValidator.reset();
|
|
76
|
+
isEditMode = false;
|
|
77
|
+
forceRefresh();
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
function submitForm(event: SubmitEvent) {
|
|
81
|
+
event.preventDefault();
|
|
82
|
+
if (!$formIsValid) return;
|
|
83
|
+
|
|
84
|
+
formValidator.setSubmitting(true);
|
|
85
|
+
|
|
86
|
+
// Simulate submission
|
|
87
|
+
setTimeout(() => {
|
|
88
|
+
formValidator.setSubmitting(false);
|
|
89
|
+
console.log('Form submitted:', $formValues);
|
|
90
|
+
forceRefresh();
|
|
91
|
+
}, 1000);
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
function handleClassInput(e: Event) {
|
|
95
|
+
const target = e.target as HTMLInputElement;
|
|
96
|
+
const sanitized = FormValidator.sanitizeClassName(target.value);
|
|
97
|
+
formValidator.setField('class', sanitized);
|
|
98
|
+
forceRefresh();
|
|
99
|
+
}
|
|
100
|
+
</script>
|
|
101
|
+
|
|
102
|
+
{#key refreshTrigger}
|
|
103
|
+
<div class="demo-container">
|
|
104
|
+
<h3>Form Validation System Demo</h3>
|
|
105
|
+
|
|
106
|
+
<div class="demo-controls">
|
|
107
|
+
<div class="control-section">
|
|
108
|
+
<h4>Demo Controls</h4>
|
|
109
|
+
<div class="button-group">
|
|
110
|
+
<button onclick={generateNewNames} class="btn btn--secondary"> Generate Names </button>
|
|
111
|
+
<button onclick={toggleEditMode} class="btn btn--secondary">
|
|
112
|
+
{isEditMode ? 'Exit Edit Mode' : 'Enter Edit Mode'}
|
|
113
|
+
</button>
|
|
114
|
+
<button onclick={toggleClassValidation} class="btn btn--secondary">
|
|
115
|
+
{classValidationEnabled ? 'Disable' : 'Enable'} Class Validation
|
|
116
|
+
</button>
|
|
117
|
+
<button onclick={addExistingInstance} class="btn btn--secondary">
|
|
118
|
+
Add Existing Instance
|
|
119
|
+
</button>
|
|
120
|
+
<button onclick={resetForm} class="btn btn--secondary"> Reset Form </button>
|
|
121
|
+
</div>
|
|
122
|
+
</div>
|
|
123
|
+
|
|
124
|
+
<div class="status-section">
|
|
125
|
+
<h4>Form Status</h4>
|
|
126
|
+
<div class="status-grid">
|
|
127
|
+
<div class="status-item">
|
|
128
|
+
<span>Valid:</span>
|
|
129
|
+
<strong class="status-{$formIsValid}">{$formIsValid ? 'YES' : 'NO'}</strong>
|
|
130
|
+
</div>
|
|
131
|
+
<div class="status-item">
|
|
132
|
+
<span>Dirty:</span>
|
|
133
|
+
<strong class="status-{$formIsDirty}">{$formIsDirty ? 'YES' : 'NO'}</strong>
|
|
134
|
+
</div>
|
|
135
|
+
<div class="status-item">
|
|
136
|
+
<span>Submitting:</span>
|
|
137
|
+
<strong class="status-{$formIsSubmitting}">{$formIsSubmitting ? 'YES' : 'NO'}</strong>
|
|
138
|
+
</div>
|
|
139
|
+
<div class="status-item">
|
|
140
|
+
<span>Edit Mode:</span>
|
|
141
|
+
<strong class="status-{isEditMode}">{isEditMode ? 'ON' : 'OFF'}</strong>
|
|
142
|
+
</div>
|
|
143
|
+
<div class="status-item">
|
|
144
|
+
<span>Class Validation:</span>
|
|
145
|
+
<strong class="status-{classValidationEnabled}"
|
|
146
|
+
>{classValidationEnabled ? 'ON' : 'OFF'}</strong
|
|
147
|
+
>
|
|
148
|
+
</div>
|
|
149
|
+
</div>
|
|
150
|
+
</div>
|
|
151
|
+
</div>
|
|
152
|
+
|
|
153
|
+
<form class="demo-form" onsubmit={submitForm}>
|
|
154
|
+
<div class="form-section">
|
|
155
|
+
<h4>Component Form</h4>
|
|
156
|
+
|
|
157
|
+
<div class="field">
|
|
158
|
+
<label for="name">Component Name</label>
|
|
159
|
+
<input
|
|
160
|
+
id="name"
|
|
161
|
+
type="text"
|
|
162
|
+
value={$formValues.name}
|
|
163
|
+
oninput={(e) => {
|
|
164
|
+
const target = e.target as HTMLInputElement;
|
|
165
|
+
formValidator.setField('name', target.value);
|
|
166
|
+
forceRefresh();
|
|
167
|
+
}}
|
|
168
|
+
class:error={($formErrors.name?.length || 0) > 0}
|
|
169
|
+
placeholder="Enter component name"
|
|
170
|
+
/>
|
|
171
|
+
{#if $formErrors.name?.length > 0}
|
|
172
|
+
<span class="error">{$formErrors.name[0]}</span>
|
|
173
|
+
{/if}
|
|
174
|
+
</div>
|
|
175
|
+
|
|
176
|
+
<div class="field">
|
|
177
|
+
<label for="instance">Instance Name</label>
|
|
178
|
+
<input
|
|
179
|
+
id="instance"
|
|
180
|
+
type="text"
|
|
181
|
+
value={$formValues.instance}
|
|
182
|
+
oninput={(e) => {
|
|
183
|
+
const target = e.target as HTMLInputElement;
|
|
184
|
+
formValidator.setField('instance', target.value);
|
|
185
|
+
forceRefresh();
|
|
186
|
+
}}
|
|
187
|
+
class:error={($formErrors.instance?.length || 0) > 0}
|
|
188
|
+
placeholder="Enter instance name (must be unique)"
|
|
189
|
+
/>
|
|
190
|
+
{#if $formErrors.instance?.length > 0}
|
|
191
|
+
<span class="error">{$formErrors.instance[0]}</span>
|
|
192
|
+
{/if}
|
|
193
|
+
</div>
|
|
194
|
+
|
|
195
|
+
<div class="field">
|
|
196
|
+
<label for="class">CSS Class Name</label>
|
|
197
|
+
<input
|
|
198
|
+
id="class"
|
|
199
|
+
type="text"
|
|
200
|
+
value={$formValues.class}
|
|
201
|
+
oninput={handleClassInput}
|
|
202
|
+
class:error={($formErrors.class?.length || 0) > 0}
|
|
203
|
+
placeholder="Enter CSS class name"
|
|
204
|
+
disabled={!classValidationEnabled}
|
|
205
|
+
/>
|
|
206
|
+
{#if $formErrors.class?.length > 0}
|
|
207
|
+
<span class="error">{$formErrors.class[0]}</span>
|
|
208
|
+
{/if}
|
|
209
|
+
{#if !classValidationEnabled}
|
|
210
|
+
<span class="helper">Class validation is disabled</span>
|
|
211
|
+
{/if}
|
|
212
|
+
</div>
|
|
213
|
+
|
|
214
|
+
<button
|
|
215
|
+
type="submit"
|
|
216
|
+
disabled={!$formIsValid || $formIsSubmitting}
|
|
217
|
+
class="btn btn--primary"
|
|
218
|
+
>
|
|
219
|
+
{#if $formIsSubmitting}
|
|
220
|
+
Submitting...
|
|
221
|
+
{:else if isEditMode}
|
|
222
|
+
Update Component
|
|
223
|
+
{:else}
|
|
224
|
+
Create Component
|
|
225
|
+
{/if}
|
|
226
|
+
</button>
|
|
227
|
+
</div>
|
|
228
|
+
</form>
|
|
229
|
+
|
|
230
|
+
<div class="debug-section">
|
|
231
|
+
<h4>Debug Information</h4>
|
|
232
|
+
|
|
233
|
+
<div class="debug-grid">
|
|
234
|
+
<div class="debug-item">
|
|
235
|
+
<h5>Existing Instances</h5>
|
|
236
|
+
<code>{JSON.stringify(existingInstances, null, 2)}</code>
|
|
237
|
+
</div>
|
|
238
|
+
|
|
239
|
+
<div class="debug-item">
|
|
240
|
+
<h5>Form Values</h5>
|
|
241
|
+
<code>{JSON.stringify($formValues, null, 2)}</code>
|
|
242
|
+
</div>
|
|
243
|
+
|
|
244
|
+
<div class="debug-item">
|
|
245
|
+
<h5>Form Errors</h5>
|
|
246
|
+
<code>{JSON.stringify($formErrors, null, 2)}</code>
|
|
247
|
+
</div>
|
|
248
|
+
|
|
249
|
+
<div class="debug-item">
|
|
250
|
+
<h5>Touched Fields</h5>
|
|
251
|
+
<code>{JSON.stringify($formTouched, null, 2)}</code>
|
|
252
|
+
</div>
|
|
253
|
+
</div>
|
|
254
|
+
</div>
|
|
255
|
+
|
|
256
|
+
<div class="examples-section">
|
|
257
|
+
<h4>Static Method Examples</h4>
|
|
258
|
+
|
|
259
|
+
<div class="example">
|
|
260
|
+
<h5>FormValidator.generateNames()</h5>
|
|
261
|
+
<button
|
|
262
|
+
onclick={() => {
|
|
263
|
+
const result = FormValidator.generateNames(existingInstances, 'test', 'Test Component');
|
|
264
|
+
console.log('Generated names:', result);
|
|
265
|
+
}}
|
|
266
|
+
class="btn btn--secondary"
|
|
267
|
+
>
|
|
268
|
+
Generate Test Names (check console)
|
|
269
|
+
</button>
|
|
270
|
+
</div>
|
|
271
|
+
|
|
272
|
+
<div class="example">
|
|
273
|
+
<h5>FormValidator.sanitizeClassName()</h5>
|
|
274
|
+
<div class="sanitize-demo">
|
|
275
|
+
<input
|
|
276
|
+
type="text"
|
|
277
|
+
placeholder="Enter invalid class name"
|
|
278
|
+
oninput={(e) => {
|
|
279
|
+
const target = e.target as HTMLInputElement;
|
|
280
|
+
const sanitized = FormValidator.sanitizeClassName(target.value);
|
|
281
|
+
const output = target.nextElementSibling as HTMLElement;
|
|
282
|
+
if (output) output.textContent = sanitized;
|
|
283
|
+
}}
|
|
284
|
+
/>
|
|
285
|
+
<span class="sanitized-output">Sanitized output will appear here</span>
|
|
286
|
+
</div>
|
|
287
|
+
</div>
|
|
288
|
+
</div>
|
|
289
|
+
</div>
|
|
290
|
+
{/key}
|
|
291
|
+
|
|
292
|
+
<style>
|
|
293
|
+
.demo-container {
|
|
294
|
+
padding: 1.5rem;
|
|
295
|
+
max-width: 800px;
|
|
296
|
+
margin: 0 auto;
|
|
297
|
+
background: var(--background1);
|
|
298
|
+
color: var(--text1);
|
|
299
|
+
font-family: var(--font-stack);
|
|
300
|
+
}
|
|
301
|
+
|
|
302
|
+
.demo-controls {
|
|
303
|
+
display: grid;
|
|
304
|
+
grid-template-columns: 1fr 1fr;
|
|
305
|
+
gap: 1.5rem;
|
|
306
|
+
margin-bottom: 2rem;
|
|
307
|
+
}
|
|
308
|
+
|
|
309
|
+
.control-section,
|
|
310
|
+
.status-section {
|
|
311
|
+
padding: 1rem;
|
|
312
|
+
border: 1px solid var(--border2);
|
|
313
|
+
border-radius: var(--border-radius);
|
|
314
|
+
background: var(--background2);
|
|
315
|
+
}
|
|
316
|
+
|
|
317
|
+
.control-section h4,
|
|
318
|
+
.status-section h4,
|
|
319
|
+
.form-section h4,
|
|
320
|
+
.debug-section h4,
|
|
321
|
+
.examples-section h4 {
|
|
322
|
+
margin: 0 0 1rem 0;
|
|
323
|
+
color: var(--text1);
|
|
324
|
+
font-size: var(--font-size-large);
|
|
325
|
+
font-weight: var(--font-weight-medium);
|
|
326
|
+
}
|
|
327
|
+
|
|
328
|
+
.button-group {
|
|
329
|
+
display: flex;
|
|
330
|
+
flex-wrap: wrap;
|
|
331
|
+
gap: 0.5rem;
|
|
332
|
+
}
|
|
333
|
+
|
|
334
|
+
.status-grid {
|
|
335
|
+
display: grid;
|
|
336
|
+
grid-template-columns: 1fr 1fr;
|
|
337
|
+
gap: 0.5rem;
|
|
338
|
+
}
|
|
339
|
+
|
|
340
|
+
.status-item {
|
|
341
|
+
display: flex;
|
|
342
|
+
justify-content: space-between;
|
|
343
|
+
padding: 0.25rem 0;
|
|
344
|
+
font-size: var(--font-size-small);
|
|
345
|
+
}
|
|
346
|
+
|
|
347
|
+
.demo-form {
|
|
348
|
+
margin-bottom: 2rem;
|
|
349
|
+
}
|
|
350
|
+
|
|
351
|
+
.form-section {
|
|
352
|
+
padding: 1rem;
|
|
353
|
+
border: 1px solid var(--border2);
|
|
354
|
+
border-radius: var(--border-radius);
|
|
355
|
+
background: var(--background2);
|
|
356
|
+
}
|
|
357
|
+
|
|
358
|
+
.field {
|
|
359
|
+
margin-bottom: 1rem;
|
|
360
|
+
}
|
|
361
|
+
|
|
362
|
+
label {
|
|
363
|
+
display: block;
|
|
364
|
+
margin-bottom: 0.25rem;
|
|
365
|
+
font-size: var(--font-size-small);
|
|
366
|
+
font-weight: var(--font-weight-medium);
|
|
367
|
+
color: var(--text1);
|
|
368
|
+
}
|
|
369
|
+
|
|
370
|
+
input {
|
|
371
|
+
width: 100%;
|
|
372
|
+
padding: var(--padding-small);
|
|
373
|
+
border: 1px solid var(--border2);
|
|
374
|
+
border-radius: var(--border-radius);
|
|
375
|
+
background: var(--background1);
|
|
376
|
+
color: var(--text1);
|
|
377
|
+
font-size: var(--font-size-small);
|
|
378
|
+
font-family: var(--font-stack);
|
|
379
|
+
}
|
|
380
|
+
|
|
381
|
+
input:focus {
|
|
382
|
+
outline: none;
|
|
383
|
+
border-color: var(--actionPrimaryBackground);
|
|
384
|
+
}
|
|
385
|
+
|
|
386
|
+
input.error {
|
|
387
|
+
border-color: var(--redText);
|
|
388
|
+
}
|
|
389
|
+
|
|
390
|
+
input:disabled {
|
|
391
|
+
opacity: 0.6;
|
|
392
|
+
cursor: not-allowed;
|
|
393
|
+
}
|
|
394
|
+
|
|
395
|
+
.error {
|
|
396
|
+
color: var(--redText);
|
|
397
|
+
font-size: var(--font-size-tiny);
|
|
398
|
+
margin-top: 0.25rem;
|
|
399
|
+
display: block;
|
|
400
|
+
}
|
|
401
|
+
|
|
402
|
+
.helper {
|
|
403
|
+
color: var(--text3);
|
|
404
|
+
font-size: var(--font-size-tiny);
|
|
405
|
+
margin-top: 0.25rem;
|
|
406
|
+
display: block;
|
|
407
|
+
}
|
|
408
|
+
|
|
409
|
+
.btn {
|
|
410
|
+
padding: var(--padding-small) var(--padding-regular);
|
|
411
|
+
border: none;
|
|
412
|
+
border-radius: var(--border-radius);
|
|
413
|
+
cursor: pointer;
|
|
414
|
+
font-size: var(--font-size-small);
|
|
415
|
+
font-weight: var(--font-weight-normal);
|
|
416
|
+
font-family: var(--font-stack);
|
|
417
|
+
transition: all 0.2s ease;
|
|
418
|
+
}
|
|
419
|
+
|
|
420
|
+
.btn--primary {
|
|
421
|
+
background: var(--actionPrimaryBackground);
|
|
422
|
+
color: var(--actionPrimaryText);
|
|
423
|
+
box-shadow: var(--boxShadows-action-colored);
|
|
424
|
+
}
|
|
425
|
+
|
|
426
|
+
.btn--primary:hover:not(:disabled) {
|
|
427
|
+
background: var(--actionPrimaryBackgroundHover);
|
|
428
|
+
color: var(--actionPrimaryTextHover);
|
|
429
|
+
}
|
|
430
|
+
|
|
431
|
+
.btn--secondary {
|
|
432
|
+
background: var(--actionSecondaryBackground);
|
|
433
|
+
color: var(--actionSecondaryText);
|
|
434
|
+
box-shadow: var(--boxShadows-action-secondary);
|
|
435
|
+
}
|
|
436
|
+
|
|
437
|
+
.btn--secondary:hover:not(:disabled) {
|
|
438
|
+
background: var(--actionSecondaryBackgroundHover);
|
|
439
|
+
color: var(--actionSecondaryTextHover);
|
|
440
|
+
}
|
|
441
|
+
|
|
442
|
+
.btn:disabled {
|
|
443
|
+
opacity: 0.6;
|
|
444
|
+
cursor: not-allowed;
|
|
445
|
+
}
|
|
446
|
+
|
|
447
|
+
.status-true {
|
|
448
|
+
color: var(--greenText);
|
|
449
|
+
font-weight: var(--font-weight-medium);
|
|
450
|
+
}
|
|
451
|
+
|
|
452
|
+
.status-false {
|
|
453
|
+
color: var(--redText);
|
|
454
|
+
font-weight: var(--font-weight-medium);
|
|
455
|
+
}
|
|
456
|
+
|
|
457
|
+
.debug-section {
|
|
458
|
+
margin-bottom: 2rem;
|
|
459
|
+
padding: 1rem;
|
|
460
|
+
border: 1px solid var(--border2);
|
|
461
|
+
border-radius: var(--border-radius);
|
|
462
|
+
background: var(--background2);
|
|
463
|
+
}
|
|
464
|
+
|
|
465
|
+
.debug-grid {
|
|
466
|
+
display: grid;
|
|
467
|
+
grid-template-columns: 1fr 1fr;
|
|
468
|
+
gap: 1rem;
|
|
469
|
+
}
|
|
470
|
+
|
|
471
|
+
.debug-item h5 {
|
|
472
|
+
margin: 0 0 0.5rem 0;
|
|
473
|
+
font-size: var(--font-size-small);
|
|
474
|
+
font-weight: var(--font-weight-medium);
|
|
475
|
+
color: var(--text2);
|
|
476
|
+
}
|
|
477
|
+
|
|
478
|
+
.examples-section {
|
|
479
|
+
padding: 1rem;
|
|
480
|
+
border: 1px solid var(--border2);
|
|
481
|
+
border-radius: var(--border-radius);
|
|
482
|
+
background: var(--background2);
|
|
483
|
+
}
|
|
484
|
+
|
|
485
|
+
.example {
|
|
486
|
+
margin-bottom: 1rem;
|
|
487
|
+
}
|
|
488
|
+
|
|
489
|
+
.example h5 {
|
|
490
|
+
margin: 0 0 0.5rem 0;
|
|
491
|
+
font-size: var(--font-size-small);
|
|
492
|
+
font-weight: var(--font-weight-medium);
|
|
493
|
+
color: var(--text2);
|
|
494
|
+
}
|
|
495
|
+
|
|
496
|
+
.sanitize-demo {
|
|
497
|
+
display: flex;
|
|
498
|
+
gap: 0.5rem;
|
|
499
|
+
align-items: center;
|
|
500
|
+
}
|
|
501
|
+
|
|
502
|
+
.sanitize-demo input {
|
|
503
|
+
flex: 1;
|
|
504
|
+
}
|
|
505
|
+
|
|
506
|
+
.sanitized-output {
|
|
507
|
+
flex: 1;
|
|
508
|
+
padding: var(--padding-small);
|
|
509
|
+
background: var(--background3);
|
|
510
|
+
border: 1px solid var(--border2);
|
|
511
|
+
border-radius: var(--border-radius);
|
|
512
|
+
font-family: monospace;
|
|
513
|
+
font-size: var(--font-size-tiny);
|
|
514
|
+
color: var(--text3);
|
|
515
|
+
}
|
|
516
|
+
|
|
517
|
+
code {
|
|
518
|
+
background: var(--background3);
|
|
519
|
+
border: 1px solid var(--border2);
|
|
520
|
+
padding: var(--padding-tiny);
|
|
521
|
+
border-radius: var(--border-radius);
|
|
522
|
+
font-family: monospace;
|
|
523
|
+
font-size: var(--font-size-tiny);
|
|
524
|
+
color: var(--text2);
|
|
525
|
+
display: block;
|
|
526
|
+
white-space: pre-wrap;
|
|
527
|
+
max-height: 150px;
|
|
528
|
+
overflow-y: auto;
|
|
529
|
+
}
|
|
530
|
+
|
|
531
|
+
@media (max-width: 768px) {
|
|
532
|
+
.demo-controls {
|
|
533
|
+
grid-template-columns: 1fr;
|
|
534
|
+
}
|
|
535
|
+
|
|
536
|
+
.debug-grid {
|
|
537
|
+
grid-template-columns: 1fr;
|
|
538
|
+
}
|
|
539
|
+
|
|
540
|
+
.sanitize-demo {
|
|
541
|
+
flex-direction: column;
|
|
542
|
+
align-items: stretch;
|
|
543
|
+
}
|
|
544
|
+
}
|
|
545
|
+
</style>
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
interface $$__sveltets_2_IsomorphicComponent<Props extends Record<string, any> = any, Events extends Record<string, any> = any, Slots extends Record<string, any> = any, Exports = {}, Bindings = string> {
|
|
2
|
+
new (options: import('svelte').ComponentConstructorOptions<Props>): import('svelte').SvelteComponent<Props, Events, Slots> & {
|
|
3
|
+
$$bindings?: Bindings;
|
|
4
|
+
} & Exports;
|
|
5
|
+
(internal: unknown, props: {
|
|
6
|
+
$$events?: Events;
|
|
7
|
+
$$slots?: Slots;
|
|
8
|
+
}): Exports & {
|
|
9
|
+
$set?: any;
|
|
10
|
+
$on?: any;
|
|
11
|
+
};
|
|
12
|
+
z_$$bindings?: Bindings;
|
|
13
|
+
}
|
|
14
|
+
declare const FormDemo: $$__sveltets_2_IsomorphicComponent<Record<string, never>, {
|
|
15
|
+
[evt: string]: CustomEvent<any>;
|
|
16
|
+
}, {}, {}, string>;
|
|
17
|
+
type FormDemo = InstanceType<typeof FormDemo>;
|
|
18
|
+
export default FormDemo;
|
package/dist/stores/forms.d.ts
CHANGED
|
@@ -8,7 +8,7 @@ interface FormState<T> {
|
|
|
8
8
|
isSubmitting: boolean;
|
|
9
9
|
}
|
|
10
10
|
/**
|
|
11
|
-
* Creates a form validation utility with
|
|
11
|
+
* Creates a form validation utility with Svelte 5 reactive stores
|
|
12
12
|
* @param identifier - Unique identifier for the form
|
|
13
13
|
* @param options - Configuration options
|
|
14
14
|
*/
|
|
@@ -18,12 +18,18 @@ export declare class FormValidator<T extends {
|
|
|
18
18
|
class: string;
|
|
19
19
|
}> {
|
|
20
20
|
private schema;
|
|
21
|
-
private
|
|
22
|
-
form: ReturnType<typeof derived<typeof this.store, FormState<T>>>;
|
|
21
|
+
private _store;
|
|
23
22
|
private instancesSet;
|
|
24
23
|
private initialValues;
|
|
25
24
|
private identifier;
|
|
26
25
|
private currentInstanceToIgnore;
|
|
26
|
+
private classValidationEnabled;
|
|
27
|
+
readonly values: ReturnType<typeof derived<typeof this._store, T>>;
|
|
28
|
+
readonly errors: ReturnType<typeof derived<typeof this._store, Record<keyof T, string[]>>>;
|
|
29
|
+
readonly touched: ReturnType<typeof derived<typeof this._store, Record<keyof T, boolean>>>;
|
|
30
|
+
readonly isValid: ReturnType<typeof derived<typeof this._store, boolean>>;
|
|
31
|
+
readonly isDirty: ReturnType<typeof derived<typeof this._store, boolean>>;
|
|
32
|
+
readonly isSubmitting: ReturnType<typeof derived<typeof this._store, boolean>>;
|
|
27
33
|
/**
|
|
28
34
|
* Generates unique name, instance, and class based on solution name and existing instances
|
|
29
35
|
* @param existingInstances - Array of existing instance names
|
|
@@ -65,6 +71,11 @@ export declare class FormValidator<T extends {
|
|
|
65
71
|
* Reset the form to initial values
|
|
66
72
|
*/
|
|
67
73
|
reset(): void;
|
|
74
|
+
/**
|
|
75
|
+
* Enable or disable class name validation
|
|
76
|
+
* @param enabled - Whether to enable class validation
|
|
77
|
+
*/
|
|
78
|
+
enableClassValidation(enabled: boolean): void;
|
|
68
79
|
/**
|
|
69
80
|
* Validate the form values
|
|
70
81
|
*/
|
|
@@ -74,10 +85,36 @@ export declare class FormValidator<T extends {
|
|
|
74
85
|
*/
|
|
75
86
|
setSubmitting(isSubmitting: boolean): void;
|
|
76
87
|
/**
|
|
77
|
-
* Get the current state of the form
|
|
88
|
+
* Get the current state of the form (for legacy compatibility)
|
|
78
89
|
*/
|
|
79
90
|
getState(): FormState<T>;
|
|
80
91
|
}
|
|
92
|
+
/**
|
|
93
|
+
* Setup form hook
|
|
94
|
+
*/
|
|
95
|
+
export declare function createForm<T extends {
|
|
96
|
+
name: string;
|
|
97
|
+
instance: string;
|
|
98
|
+
class: string;
|
|
99
|
+
}>(identifier: string, initialValues: T, options?: {
|
|
100
|
+
existingInstances?: string[];
|
|
101
|
+
enableClassValidation?: boolean;
|
|
102
|
+
}): {
|
|
103
|
+
values: import("svelte/store").Readable<T>;
|
|
104
|
+
errors: import("svelte/store").Readable<Record<keyof T, string[]>>;
|
|
105
|
+
touched: import("svelte/store").Readable<Record<keyof T, boolean>>;
|
|
106
|
+
isValid: import("svelte/store").Readable<boolean>;
|
|
107
|
+
isDirty: import("svelte/store").Readable<boolean>;
|
|
108
|
+
isSubmitting: import("svelte/store").Readable<boolean>;
|
|
109
|
+
setField: <K extends keyof T>(field: K, value: T[K]) => void;
|
|
110
|
+
setFields: (values: Partial<T>) => void;
|
|
111
|
+
reset: () => void;
|
|
112
|
+
enableClassValidation: (enabled: boolean) => void;
|
|
113
|
+
ignoreInstanceValidation: (instanceValue: string, existingInstances: string[]) => void;
|
|
114
|
+
setSubmitting: (isSubmitting: boolean) => void;
|
|
115
|
+
validate: () => void;
|
|
116
|
+
getState: () => FormState<T>;
|
|
117
|
+
};
|
|
81
118
|
/**
|
|
82
119
|
* Get a form by its identifier
|
|
83
120
|
*/
|