@finsweet/webflow-apps-utils 1.0.4 → 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/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.js +519 -2
- 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/ui/components/button/Button.svelte +1 -1
- package/dist/ui/components/copy-text/CopyText.stories.js +1 -1
- package/dist/ui/components/copy-text/CopyText.svelte +17 -19
- package/dist/ui/components/layout/Layout.svelte +38 -5
- package/dist/ui/components/layout/Layout.svelte.d.ts +24 -1
- package/dist/ui/components/layout/examples/ExampleLayout.svelte +12 -12
- package/dist/ui/components/section/Section.svelte +4 -2
- package/dist/ui/index.css +6 -2
- 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/index.d.ts +1 -0
- package/dist/utils/index.js +1 -0
- package/package.json +1 -1
- package/dist/providers/GlobalProvider.mdx +0 -322
- package/dist/router/Router.mdx +0 -958
- package/dist/stores/docs/Form.mdx +0 -542
|
@@ -0,0 +1,342 @@
|
|
|
1
|
+
import FormDemo from './FormDemo.svelte';
|
|
2
|
+
const meta = {
|
|
3
|
+
title: 'Utils/Form Validation System',
|
|
4
|
+
component: FormDemo,
|
|
5
|
+
parameters: {
|
|
6
|
+
layout: 'centered',
|
|
7
|
+
backgrounds: {
|
|
8
|
+
default: 'dark',
|
|
9
|
+
values: [
|
|
10
|
+
{ name: 'dark', value: '#292929' },
|
|
11
|
+
{ name: 'light', value: '#ffffff' }
|
|
12
|
+
]
|
|
13
|
+
},
|
|
14
|
+
docs: {
|
|
15
|
+
description: {
|
|
16
|
+
component: `
|
|
17
|
+
# Form Validation System
|
|
18
|
+
|
|
19
|
+
A comprehensive form validation system built with Svelte stores and Zod for type-safe form handling in Webflow apps.
|
|
20
|
+
|
|
21
|
+
## Overview
|
|
22
|
+
|
|
23
|
+
The form validation system provides:
|
|
24
|
+
|
|
25
|
+
- Type-safe form state management with Zod validation
|
|
26
|
+
- Unique instance name generation for Webflow components
|
|
27
|
+
- Real-time validation with error handling
|
|
28
|
+
- Form registry for managing multiple forms
|
|
29
|
+
- Class name sanitization for HTML compliance
|
|
30
|
+
|
|
31
|
+
## Core Classes and Functions
|
|
32
|
+
|
|
33
|
+
### FormValidator Class
|
|
34
|
+
|
|
35
|
+
The main class for creating and managing form validation state.
|
|
36
|
+
|
|
37
|
+
\`\`\`typescript
|
|
38
|
+
import { FormValidator } from './';
|
|
39
|
+
|
|
40
|
+
// Define your form data structure
|
|
41
|
+
interface MyFormData {
|
|
42
|
+
name: string;
|
|
43
|
+
instance: string;
|
|
44
|
+
class: string;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
// Create a form validator
|
|
48
|
+
const formValidator = new FormValidator<MyFormData>(
|
|
49
|
+
'my-form-id',
|
|
50
|
+
{
|
|
51
|
+
name: 'My Component',
|
|
52
|
+
instance: 'fs-component',
|
|
53
|
+
class: 'fs-component'
|
|
54
|
+
},
|
|
55
|
+
{
|
|
56
|
+
existingInstances: ['fs-existing-1', 'fs-existing-2']
|
|
57
|
+
}
|
|
58
|
+
);
|
|
59
|
+
\`\`\`
|
|
60
|
+
|
|
61
|
+
#### Constructor Parameters
|
|
62
|
+
|
|
63
|
+
- \`identifier: string\` - Unique identifier for the form (used in global registry)
|
|
64
|
+
- \`initialValues: T\` - Initial form values
|
|
65
|
+
- \`options.existingInstances?: string[]\` - Array of existing instance names for uniqueness validation
|
|
66
|
+
|
|
67
|
+
**Note:** Class validation is enabled by default. Use \`enableClassValidation(false)\` to disable it if your component doesn't require CSS classes.
|
|
68
|
+
|
|
69
|
+
### Static Methods
|
|
70
|
+
|
|
71
|
+
#### generateNames()
|
|
72
|
+
|
|
73
|
+
Generates unique names, instances, and class names based on existing instances:
|
|
74
|
+
|
|
75
|
+
\`\`\`typescript
|
|
76
|
+
const generated = FormValidator.generateNames(
|
|
77
|
+
['fs-slider-1', 'fs-slider-2'], // existing instances
|
|
78
|
+
'slider', // solution name
|
|
79
|
+
'Slider Component' // display name
|
|
80
|
+
);
|
|
81
|
+
|
|
82
|
+
// Returns:
|
|
83
|
+
// {
|
|
84
|
+
// name: 'Slider Component 3',
|
|
85
|
+
// instance: 'fs-slider-3',
|
|
86
|
+
// class: 'fs-slider-3'
|
|
87
|
+
// }
|
|
88
|
+
\`\`\`
|
|
89
|
+
|
|
90
|
+
#### sanitizeClassName()
|
|
91
|
+
|
|
92
|
+
Cleans up class names to ensure HTML compliance:
|
|
93
|
+
|
|
94
|
+
\`\`\`typescript
|
|
95
|
+
const cleaned = FormValidator.sanitizeClassName('my/invalid class-name!');
|
|
96
|
+
// Returns: 'my-invalid-class-name'
|
|
97
|
+
\`\`\`
|
|
98
|
+
|
|
99
|
+
### Instance Methods
|
|
100
|
+
|
|
101
|
+
#### setField()
|
|
102
|
+
|
|
103
|
+
Updates a single form field:
|
|
104
|
+
|
|
105
|
+
\`\`\`typescript
|
|
106
|
+
formValidator.setField('name', 'New Component Name');
|
|
107
|
+
\`\`\`
|
|
108
|
+
|
|
109
|
+
#### setFields()
|
|
110
|
+
|
|
111
|
+
Updates multiple form fields at once:
|
|
112
|
+
|
|
113
|
+
\`\`\`typescript
|
|
114
|
+
formValidator.setFields({
|
|
115
|
+
name: 'New Name',
|
|
116
|
+
instance: 'fs-new-instance'
|
|
117
|
+
});
|
|
118
|
+
\`\`\`
|
|
119
|
+
|
|
120
|
+
#### validateWithInstances()
|
|
121
|
+
|
|
122
|
+
Updates the list of existing instances and re-validates:
|
|
123
|
+
|
|
124
|
+
\`\`\`typescript
|
|
125
|
+
formValidator.validateWithInstances(['fs-new-1', 'fs-new-2']);
|
|
126
|
+
\`\`\`
|
|
127
|
+
|
|
128
|
+
#### ignoreInstanceValidation()
|
|
129
|
+
|
|
130
|
+
Temporarily ignores a specific instance during validation (useful for edit mode):
|
|
131
|
+
|
|
132
|
+
\`\`\`typescript
|
|
133
|
+
formValidator.ignoreInstanceValidation('fs-current-instance', existingInstances);
|
|
134
|
+
\`\`\`
|
|
135
|
+
|
|
136
|
+
#### reset()
|
|
137
|
+
|
|
138
|
+
Resets the form to its initial state:
|
|
139
|
+
|
|
140
|
+
\`\`\`typescript
|
|
141
|
+
formValidator.reset();
|
|
142
|
+
\`\`\`
|
|
143
|
+
|
|
144
|
+
#### enableClassValidation()
|
|
145
|
+
|
|
146
|
+
Enables or disables class name validation dynamically:
|
|
147
|
+
|
|
148
|
+
\`\`\`typescript
|
|
149
|
+
// Disable class validation (useful for certain component types)
|
|
150
|
+
formValidator.enableClassValidation(false);
|
|
151
|
+
|
|
152
|
+
// Re-enable class validation
|
|
153
|
+
formValidator.enableClassValidation(true);
|
|
154
|
+
\`\`\`
|
|
155
|
+
|
|
156
|
+
#### getState()
|
|
157
|
+
|
|
158
|
+
Gets the current form state:
|
|
159
|
+
|
|
160
|
+
\`\`\`typescript
|
|
161
|
+
const state = formValidator.getState();
|
|
162
|
+
console.log(state.isValid, state.errors, state.values);
|
|
163
|
+
\`\`\`
|
|
164
|
+
|
|
165
|
+
#### setSubmitting()
|
|
166
|
+
|
|
167
|
+
Sets the form submission state:
|
|
168
|
+
|
|
169
|
+
\`\`\`typescript
|
|
170
|
+
formValidator.setSubmitting(true);
|
|
171
|
+
// ... perform submission
|
|
172
|
+
formValidator.setSubmitting(false);
|
|
173
|
+
\`\`\`
|
|
174
|
+
|
|
175
|
+
## Form State Structure
|
|
176
|
+
|
|
177
|
+
The form state contains:
|
|
178
|
+
|
|
179
|
+
\`\`\`typescript
|
|
180
|
+
interface FormState<T> {
|
|
181
|
+
values: T; // Current form values
|
|
182
|
+
errors: Record<keyof T, string[]>; // Validation errors by field
|
|
183
|
+
touched: Record<keyof T, boolean>; // Fields that have been interacted with
|
|
184
|
+
isValid: boolean; // Overall form validity
|
|
185
|
+
isDirty: boolean; // Whether form has been modified
|
|
186
|
+
isSubmitting: boolean; // Submission state
|
|
187
|
+
}
|
|
188
|
+
\`\`\`
|
|
189
|
+
|
|
190
|
+
## Global Form Registry
|
|
191
|
+
|
|
192
|
+
The system maintains a global registry of all forms for cross-component access.
|
|
193
|
+
|
|
194
|
+
### getFormById()
|
|
195
|
+
|
|
196
|
+
Retrieve a form instance by its identifier:
|
|
197
|
+
|
|
198
|
+
\`\`\`typescript
|
|
199
|
+
import { getFormById } from './';
|
|
200
|
+
|
|
201
|
+
const form = getFormById('my-form-id');
|
|
202
|
+
if (form) {
|
|
203
|
+
console.log(form.getState());
|
|
204
|
+
}
|
|
205
|
+
\`\`\`
|
|
206
|
+
|
|
207
|
+
### isFormValid()
|
|
208
|
+
|
|
209
|
+
Check if a specific form is valid:
|
|
210
|
+
|
|
211
|
+
\`\`\`typescript
|
|
212
|
+
import { isFormValid } from './';
|
|
213
|
+
|
|
214
|
+
if (isFormValid('my-form-id')) {
|
|
215
|
+
console.log('Form is valid!');
|
|
216
|
+
}
|
|
217
|
+
\`\`\`
|
|
218
|
+
|
|
219
|
+
### getFormErrors()
|
|
220
|
+
|
|
221
|
+
Get error messages for a specific form:
|
|
222
|
+
|
|
223
|
+
\`\`\`typescript
|
|
224
|
+
import { getFormErrors } from './';
|
|
225
|
+
|
|
226
|
+
const errors = getFormErrors('my-form-id');
|
|
227
|
+
console.log(errors);
|
|
228
|
+
\`\`\`
|
|
229
|
+
|
|
230
|
+
### resetForm()
|
|
231
|
+
|
|
232
|
+
Reset a form by its identifier:
|
|
233
|
+
|
|
234
|
+
\`\`\`typescript
|
|
235
|
+
import { resetForm } from './';
|
|
236
|
+
|
|
237
|
+
resetForm('my-form-id');
|
|
238
|
+
\`\`\`
|
|
239
|
+
|
|
240
|
+
## Validation Rules
|
|
241
|
+
|
|
242
|
+
The system includes built-in validation for Webflow component forms:
|
|
243
|
+
|
|
244
|
+
### Name Field
|
|
245
|
+
|
|
246
|
+
- Required (minimum 1 character)
|
|
247
|
+
|
|
248
|
+
### Instance Field
|
|
249
|
+
|
|
250
|
+
- Required (minimum 1 character)
|
|
251
|
+
- Must be unique across existing instances
|
|
252
|
+
- Case-insensitive uniqueness check
|
|
253
|
+
|
|
254
|
+
### Class Field
|
|
255
|
+
|
|
256
|
+
- Required by default (minimum 1 character when validation is enabled)
|
|
257
|
+
- Must contain only letters, numbers, underscores, and hyphens
|
|
258
|
+
- Automatically sanitized with \`sanitizeClassName()\`
|
|
259
|
+
- Can be disabled using \`enableClassValidation(false)\` for components that don't require CSS classes
|
|
260
|
+
|
|
261
|
+
## Dynamic Class Validation
|
|
262
|
+
|
|
263
|
+
The form validator supports enabling or disabling class name validation based on your component's requirements. This is useful for components that don't require CSS classes or when you want to allow more flexible class naming.
|
|
264
|
+
|
|
265
|
+
### When to Disable Class Validation
|
|
266
|
+
|
|
267
|
+
- Components that only use inline styles
|
|
268
|
+
- Third-party integrations that don't require CSS classes
|
|
269
|
+
- Temporary or test components
|
|
270
|
+
- Components where class names are generated programmatically
|
|
271
|
+
|
|
272
|
+
### Usage Examples
|
|
273
|
+
|
|
274
|
+
\`\`\`typescript
|
|
275
|
+
// Create form with class validation enabled (default)
|
|
276
|
+
const formValidator = new FormValidator('component-form', initialValues);
|
|
277
|
+
|
|
278
|
+
// Disable class validation for a component that doesn't need CSS
|
|
279
|
+
formValidator.enableClassValidation(false);
|
|
280
|
+
|
|
281
|
+
// Re-enable class validation if needed later
|
|
282
|
+
formValidator.enableClassValidation(true);
|
|
283
|
+
\`\`\`
|
|
284
|
+
|
|
285
|
+
## Best Practices
|
|
286
|
+
|
|
287
|
+
### 1. Unique Form Identifiers
|
|
288
|
+
|
|
289
|
+
Always use unique identifiers for each form to prevent conflicts:
|
|
290
|
+
|
|
291
|
+
\`\`\`typescript
|
|
292
|
+
const formValidator = new FormValidator(\`\${componentType}-\${componentId}-form\`, initialValues);
|
|
293
|
+
\`\`\`
|
|
294
|
+
|
|
295
|
+
### 2. Handle Existing Instances
|
|
296
|
+
|
|
297
|
+
Always provide existing instances for proper uniqueness validation:
|
|
298
|
+
|
|
299
|
+
\`\`\`typescript
|
|
300
|
+
const formValidator = new FormValidator('form-id', initialValues, {
|
|
301
|
+
existingInstances: getAllExistingInstances()
|
|
302
|
+
});
|
|
303
|
+
\`\`\`
|
|
304
|
+
|
|
305
|
+
### 3. Edit Mode Handling
|
|
306
|
+
|
|
307
|
+
Use \`ignoreInstanceValidation()\` when editing existing components:
|
|
308
|
+
|
|
309
|
+
\`\`\`typescript
|
|
310
|
+
if (isEditMode) {
|
|
311
|
+
formValidator.ignoreInstanceValidation(currentInstance, existingInstances);
|
|
312
|
+
}
|
|
313
|
+
\`\`\`
|
|
314
|
+
|
|
315
|
+
### 4. Cleanup
|
|
316
|
+
|
|
317
|
+
Always clean up form subscriptions to prevent memory leaks:
|
|
318
|
+
|
|
319
|
+
\`\`\`typescript
|
|
320
|
+
onDestroy(() => {
|
|
321
|
+
formSubscription.destroy();
|
|
322
|
+
});
|
|
323
|
+
\`\`\`
|
|
324
|
+
|
|
325
|
+
Click the interactive demo below to see the form validation system in action!
|
|
326
|
+
`
|
|
327
|
+
}
|
|
328
|
+
}
|
|
329
|
+
},
|
|
330
|
+
tags: ['autodocs']
|
|
331
|
+
};
|
|
332
|
+
export default meta;
|
|
333
|
+
export const Interactive = {
|
|
334
|
+
name: 'Interactive Demo',
|
|
335
|
+
parameters: {
|
|
336
|
+
docs: {
|
|
337
|
+
description: {
|
|
338
|
+
story: 'Explore the form validation system with a live interactive demo showing all features including validation, name generation, and error handling.'
|
|
339
|
+
}
|
|
340
|
+
}
|
|
341
|
+
}
|
|
342
|
+
};
|