@finsweet/webflow-apps-utils 1.0.8 → 1.0.9
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/types/customCode.d.ts +1 -1
- package/dist/ui/components/Loader.svelte +0 -2
- package/dist/ui/components/button/Button.stories.svelte +0 -8
- package/dist/ui/components/button/Button.svelte +68 -76
- package/dist/ui/components/button/index.d.ts +1 -1
- package/dist/ui/components/button/index.js +1 -0
- package/dist/ui/components/controlled-buttons/ControlledButtons.svelte +17 -7
- package/dist/ui/components/copy-text/CopyText.svelte +48 -39
- package/dist/ui/components/divider/Divider.stories.svelte +0 -4
- package/dist/ui/components/input/index.d.ts +1 -1
- package/dist/ui/components/input/index.js +1 -0
- package/dist/ui/components/layout/Layout.svelte +0 -5
- package/dist/ui/components/layout/examples/ExampleLayout.svelte +1 -8
- package/dist/ui/components/modal/Example.svelte +0 -7
- package/dist/ui/components/modal/Modal.stories.svelte +0 -2
- package/dist/ui/components/modal/Modal.svelte +1 -1
- package/dist/ui/components/notification/Notification.stories.svelte +0 -8
- package/dist/ui/components/section/Section.stories.svelte +0 -1
- package/dist/ui/components/text/README.md +0 -2
- package/dist/ui/components/text/Text.stories.svelte +0 -6
- package/dist/ui/components/text/Text.svelte +0 -19
- package/dist/ui/components/tooltip/Tooltip.svelte +9 -4
- package/dist/ui/icons/FinsweetLogoOutlineIcon.svelte +17 -0
- package/dist/ui/icons/FinsweetLogoOutlineIcon.svelte.d.ts +26 -0
- package/dist/ui/icons/TriangleDownIconToggle.svelte +0 -1
- package/dist/ui/icons/index.d.ts +2 -1
- package/dist/ui/icons/index.js +2 -1
- package/dist/ui/index.css +1 -1
- package/dist/ui/providers/GlobalProviderDemo.svelte +0 -2
- package/dist/ui/router/Router.stories.js +7 -7
- package/dist/ui/router/examples/RouterExample.svelte +0 -9
- package/dist/ui/router/examples/pages/AboutPage.svelte +0 -4
- package/dist/ui/router/providers/Link.svelte +0 -2
- package/dist/ui/router/providers/Route.svelte +0 -3
- package/dist/ui/stores/form.d.ts +136 -3
- package/dist/ui/stores/form.js +310 -2
- package/package.json +1 -1
package/dist/ui/stores/form.d.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { derived } from 'svelte/store';
|
|
2
|
+
import { z } from 'zod';
|
|
2
3
|
interface FormState<T> {
|
|
3
4
|
values: T;
|
|
4
5
|
errors: Record<keyof T, string[]>;
|
|
@@ -7,6 +8,108 @@ interface FormState<T> {
|
|
|
7
8
|
isDirty: boolean;
|
|
8
9
|
isSubmitting: boolean;
|
|
9
10
|
}
|
|
11
|
+
/**
|
|
12
|
+
* Generic Form Manager for any Zod schema with cross-component field support
|
|
13
|
+
*/
|
|
14
|
+
export declare class FormManager<T extends Record<string, unknown>> {
|
|
15
|
+
private schema;
|
|
16
|
+
private _store;
|
|
17
|
+
private initialValues;
|
|
18
|
+
private identifier;
|
|
19
|
+
private fieldRegistrations;
|
|
20
|
+
readonly values: ReturnType<typeof derived<typeof this._store, T>>;
|
|
21
|
+
readonly errors: ReturnType<typeof derived<typeof this._store, Record<keyof T, string[]>>>;
|
|
22
|
+
readonly touched: ReturnType<typeof derived<typeof this._store, Record<keyof T, boolean>>>;
|
|
23
|
+
readonly isValid: ReturnType<typeof derived<typeof this._store, boolean>>;
|
|
24
|
+
readonly isDirty: ReturnType<typeof derived<typeof this._store, boolean>>;
|
|
25
|
+
readonly isSubmitting: ReturnType<typeof derived<typeof this._store, boolean>>;
|
|
26
|
+
constructor(identifier: string, schema: z.ZodType<T>, initialValues: T);
|
|
27
|
+
/**
|
|
28
|
+
* Register a field with the form for cross-component management
|
|
29
|
+
*/
|
|
30
|
+
registerField<K extends keyof T>(fieldName: K, options?: {
|
|
31
|
+
validate?: (value: T[K]) => string | null;
|
|
32
|
+
transform?: (value: unknown) => T[K];
|
|
33
|
+
}): {
|
|
34
|
+
value: import("svelte/store").Readable<T[K]>;
|
|
35
|
+
error: import("svelte/store").Readable<Record<keyof T, string[]>[K]>;
|
|
36
|
+
touched: import("svelte/store").Readable<false | Record<keyof T, boolean>[K]>;
|
|
37
|
+
setValue: (value: T[K]) => void;
|
|
38
|
+
setTouched: () => void;
|
|
39
|
+
validate: () => string[];
|
|
40
|
+
};
|
|
41
|
+
/**
|
|
42
|
+
* Set the value of a specific field
|
|
43
|
+
*/
|
|
44
|
+
setField<K extends keyof T>(field: K, value: T[K]): void;
|
|
45
|
+
/**
|
|
46
|
+
* Set multiple field values at once
|
|
47
|
+
*/
|
|
48
|
+
setFields(values: Partial<T>): void;
|
|
49
|
+
/**
|
|
50
|
+
* Set a field as touched without changing its value
|
|
51
|
+
*/
|
|
52
|
+
setTouched<K extends keyof T>(field: K): void;
|
|
53
|
+
/**
|
|
54
|
+
* Validate a specific field
|
|
55
|
+
*/
|
|
56
|
+
validateField<K extends keyof T>(field: K): string[];
|
|
57
|
+
/**
|
|
58
|
+
* Reset the form to initial values
|
|
59
|
+
*/
|
|
60
|
+
reset(): void;
|
|
61
|
+
/**
|
|
62
|
+
* Set the form as submitting
|
|
63
|
+
*/
|
|
64
|
+
setSubmitting(isSubmitting: boolean): void;
|
|
65
|
+
/**
|
|
66
|
+
* Update the schema (useful for dynamic forms)
|
|
67
|
+
*/
|
|
68
|
+
updateSchema(newSchema: z.ZodType<T>): void;
|
|
69
|
+
/**
|
|
70
|
+
* Validate the entire form
|
|
71
|
+
*/
|
|
72
|
+
private validate;
|
|
73
|
+
/**
|
|
74
|
+
* Get the current state of the form
|
|
75
|
+
*/
|
|
76
|
+
getState(): FormState<T>;
|
|
77
|
+
/**
|
|
78
|
+
* Destroy the form and clean up resources
|
|
79
|
+
*/
|
|
80
|
+
destroy(): void;
|
|
81
|
+
}
|
|
82
|
+
/**
|
|
83
|
+
* Creates a generic form with Zod validation
|
|
84
|
+
*/
|
|
85
|
+
export declare function createGenericForm<T extends Record<string, unknown>>(identifier: string, schema: z.ZodType<T>, initialValues: T): {
|
|
86
|
+
values: import("svelte/store").Readable<T>;
|
|
87
|
+
errors: import("svelte/store").Readable<Record<keyof T, string[]>>;
|
|
88
|
+
touched: import("svelte/store").Readable<Record<keyof T, boolean>>;
|
|
89
|
+
isValid: import("svelte/store").Readable<boolean>;
|
|
90
|
+
isDirty: import("svelte/store").Readable<boolean>;
|
|
91
|
+
isSubmitting: import("svelte/store").Readable<boolean>;
|
|
92
|
+
setField: <K extends keyof T>(field: K, value: T[K]) => void;
|
|
93
|
+
setFields: (values: Partial<T>) => void;
|
|
94
|
+
setTouched: <K extends keyof T>(field: K) => void;
|
|
95
|
+
reset: () => void;
|
|
96
|
+
setSubmitting: (isSubmitting: boolean) => void;
|
|
97
|
+
updateSchema: (newSchema: z.ZodType<T, z.ZodTypeDef, T>) => void;
|
|
98
|
+
registerField: <K extends keyof T>(fieldName: K, options?: {
|
|
99
|
+
validate?: ((value: T[K]) => string | null) | undefined;
|
|
100
|
+
transform?: ((value: unknown) => T[K]) | undefined;
|
|
101
|
+
} | undefined) => {
|
|
102
|
+
value: import("svelte/store").Readable<T[K]>;
|
|
103
|
+
error: import("svelte/store").Readable<Record<keyof T, string[]>[K]>;
|
|
104
|
+
touched: import("svelte/store").Readable<false | Record<keyof T, boolean>[K]>;
|
|
105
|
+
setValue: (value: T[K]) => void;
|
|
106
|
+
setTouched: () => void;
|
|
107
|
+
validate: () => string[];
|
|
108
|
+
};
|
|
109
|
+
validateField: <K extends keyof T>(field: K) => string[];
|
|
110
|
+
getState: () => FormState<T>;
|
|
111
|
+
destroy: () => void;
|
|
112
|
+
};
|
|
10
113
|
/**
|
|
11
114
|
* Creates a form validation utility with Svelte 5 reactive stores
|
|
12
115
|
* @param identifier - Unique identifier for the form
|
|
@@ -85,7 +188,7 @@ export declare class FormValidator<T extends {
|
|
|
85
188
|
*/
|
|
86
189
|
setSubmitting(isSubmitting: boolean): void;
|
|
87
190
|
/**
|
|
88
|
-
* Get the current state of the form
|
|
191
|
+
* Get the current state of the form
|
|
89
192
|
*/
|
|
90
193
|
getState(): FormState<T>;
|
|
91
194
|
}
|
|
@@ -118,7 +221,11 @@ export declare function createForm<T extends {
|
|
|
118
221
|
/**
|
|
119
222
|
* Get a form by its identifier
|
|
120
223
|
*/
|
|
121
|
-
export declare function getFormById(identifier: string): FormValidator<
|
|
224
|
+
export declare function getFormById(identifier: string): FormValidator<{
|
|
225
|
+
name: string;
|
|
226
|
+
instance: string;
|
|
227
|
+
class: string;
|
|
228
|
+
}> | FormManager<Record<string, unknown>> | undefined;
|
|
122
229
|
/**
|
|
123
230
|
* Check if a form with a specific identifier is valid
|
|
124
231
|
*/
|
|
@@ -136,9 +243,35 @@ export declare function createFormSubscription(identifier: string): import("svel
|
|
|
136
243
|
errors: {};
|
|
137
244
|
values: {};
|
|
138
245
|
}> | {
|
|
139
|
-
subscribe: (this: void, run: import("svelte/store").Subscriber<FormState<
|
|
246
|
+
subscribe: (this: void, run: import("svelte/store").Subscriber<FormState<{
|
|
247
|
+
name: string;
|
|
248
|
+
instance: string;
|
|
249
|
+
class: string;
|
|
250
|
+
}> | FormState<Record<string, unknown>>>, invalidate?: () => void) => import("svelte/store").Unsubscriber;
|
|
140
251
|
destroy: () => void;
|
|
141
252
|
};
|
|
253
|
+
/**
|
|
254
|
+
* Helper to get field state for a specific form and field
|
|
255
|
+
*/
|
|
256
|
+
export declare function getFieldState<T extends Record<string, unknown>>(formId: string, fieldName: keyof T): {
|
|
257
|
+
value: undefined;
|
|
258
|
+
error: never[];
|
|
259
|
+
touched: boolean;
|
|
260
|
+
isValid: boolean;
|
|
261
|
+
} | {
|
|
262
|
+
value: T[keyof T];
|
|
263
|
+
error: Record<keyof T, string[]>[keyof T];
|
|
264
|
+
touched: boolean | Record<keyof T, boolean>[keyof T];
|
|
265
|
+
isValid: boolean;
|
|
266
|
+
};
|
|
267
|
+
/**
|
|
268
|
+
* Helper to update a field value for a specific form
|
|
269
|
+
*/
|
|
270
|
+
export declare function updateFieldValue<T extends Record<string, unknown>>(formId: string, fieldName: keyof T, value: T[typeof fieldName]): void;
|
|
271
|
+
/**
|
|
272
|
+
* Helper to get all registered field names for a form
|
|
273
|
+
*/
|
|
274
|
+
export declare function getFormFieldNames(formId: string): string[];
|
|
142
275
|
/**
|
|
143
276
|
* Store to track if the form is adding or updating to the Canvas
|
|
144
277
|
*/
|
package/dist/ui/stores/form.js
CHANGED
|
@@ -3,8 +3,280 @@ import { z } from 'zod';
|
|
|
3
3
|
// Registry to track all form states by identifier
|
|
4
4
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
5
5
|
const formsRegistry = writable({});
|
|
6
|
+
// Registry to track field registrations per form
|
|
7
|
+
const fieldRegistrations = writable({});
|
|
6
8
|
// Validates class name according to HTML class name rules
|
|
7
9
|
const classNameRegex = /^[a-zA-Z0-9_-]+$/;
|
|
10
|
+
/**
|
|
11
|
+
* Generic Form Manager for any Zod schema with cross-component field support
|
|
12
|
+
*/
|
|
13
|
+
export class FormManager {
|
|
14
|
+
schema;
|
|
15
|
+
_store;
|
|
16
|
+
initialValues;
|
|
17
|
+
identifier;
|
|
18
|
+
fieldRegistrations = new Map();
|
|
19
|
+
// Public reactive stores that components can directly use
|
|
20
|
+
values;
|
|
21
|
+
errors;
|
|
22
|
+
touched;
|
|
23
|
+
isValid;
|
|
24
|
+
isDirty;
|
|
25
|
+
isSubmitting;
|
|
26
|
+
constructor(identifier, schema, initialValues) {
|
|
27
|
+
this.identifier = identifier;
|
|
28
|
+
this.schema = schema;
|
|
29
|
+
this.initialValues = initialValues;
|
|
30
|
+
// Create the internal form state store
|
|
31
|
+
this._store = writable({
|
|
32
|
+
values: initialValues,
|
|
33
|
+
errors: {},
|
|
34
|
+
touched: {},
|
|
35
|
+
isValid: false,
|
|
36
|
+
isDirty: false,
|
|
37
|
+
isSubmitting: false
|
|
38
|
+
});
|
|
39
|
+
// Create derived stores
|
|
40
|
+
this.values = derived(this._store, ($store) => $store.values);
|
|
41
|
+
this.errors = derived(this._store, ($store) => $store.errors);
|
|
42
|
+
this.touched = derived(this._store, ($store) => $store.touched);
|
|
43
|
+
this.isValid = derived(this._store, ($store) => $store.isValid);
|
|
44
|
+
this.isDirty = derived(this._store, ($store) => $store.isDirty);
|
|
45
|
+
this.isSubmitting = derived(this._store, ($store) => $store.isSubmitting);
|
|
46
|
+
// Register this form with the global registry
|
|
47
|
+
formsRegistry.update((registry) => {
|
|
48
|
+
registry[identifier] = this;
|
|
49
|
+
return registry;
|
|
50
|
+
});
|
|
51
|
+
// Initialize field registrations for this form
|
|
52
|
+
fieldRegistrations.update((registrations) => {
|
|
53
|
+
registrations[identifier] = {};
|
|
54
|
+
return registrations;
|
|
55
|
+
});
|
|
56
|
+
// Initial validation
|
|
57
|
+
this.validate();
|
|
58
|
+
}
|
|
59
|
+
/**
|
|
60
|
+
* Register a field with the form for cross-component management
|
|
61
|
+
*/
|
|
62
|
+
registerField(fieldName, options) {
|
|
63
|
+
const registration = {
|
|
64
|
+
name: fieldName,
|
|
65
|
+
validate: options?.validate,
|
|
66
|
+
transform: options?.transform
|
|
67
|
+
};
|
|
68
|
+
this.fieldRegistrations.set(fieldName, registration);
|
|
69
|
+
// Update global field registrations
|
|
70
|
+
fieldRegistrations.update((registrations) => {
|
|
71
|
+
registrations[this.identifier][fieldName] =
|
|
72
|
+
registration;
|
|
73
|
+
return registrations;
|
|
74
|
+
});
|
|
75
|
+
return {
|
|
76
|
+
// Return field-specific reactive stores
|
|
77
|
+
value: derived(this.values, ($values) => $values[fieldName]),
|
|
78
|
+
error: derived(this.errors, ($errors) => $errors[fieldName] || []),
|
|
79
|
+
touched: derived(this.touched, ($touched) => $touched[fieldName] || false),
|
|
80
|
+
// Field-specific methods
|
|
81
|
+
setValue: (value) => this.setField(fieldName, value),
|
|
82
|
+
setTouched: () => this.setTouched(fieldName),
|
|
83
|
+
validate: () => this.validateField(fieldName)
|
|
84
|
+
};
|
|
85
|
+
}
|
|
86
|
+
/**
|
|
87
|
+
* Set the value of a specific field
|
|
88
|
+
*/
|
|
89
|
+
setField(field, value) {
|
|
90
|
+
this._store.update((state) => {
|
|
91
|
+
const newState = {
|
|
92
|
+
...state,
|
|
93
|
+
values: {
|
|
94
|
+
...state.values,
|
|
95
|
+
[field]: value
|
|
96
|
+
},
|
|
97
|
+
touched: {
|
|
98
|
+
...state.touched,
|
|
99
|
+
[field]: true
|
|
100
|
+
},
|
|
101
|
+
isDirty: true
|
|
102
|
+
};
|
|
103
|
+
return newState;
|
|
104
|
+
});
|
|
105
|
+
this.validate();
|
|
106
|
+
}
|
|
107
|
+
/**
|
|
108
|
+
* Set multiple field values at once
|
|
109
|
+
*/
|
|
110
|
+
setFields(values) {
|
|
111
|
+
this._store.update((state) => {
|
|
112
|
+
const newTouched = { ...state.touched };
|
|
113
|
+
// Mark all updated fields as touched
|
|
114
|
+
Object.keys(values).forEach((key) => {
|
|
115
|
+
newTouched[key] = true;
|
|
116
|
+
});
|
|
117
|
+
return {
|
|
118
|
+
...state,
|
|
119
|
+
values: {
|
|
120
|
+
...state.values,
|
|
121
|
+
...values
|
|
122
|
+
},
|
|
123
|
+
touched: newTouched,
|
|
124
|
+
isDirty: true
|
|
125
|
+
};
|
|
126
|
+
});
|
|
127
|
+
this.validate();
|
|
128
|
+
}
|
|
129
|
+
/**
|
|
130
|
+
* Set a field as touched without changing its value
|
|
131
|
+
*/
|
|
132
|
+
setTouched(field) {
|
|
133
|
+
this._store.update((state) => ({
|
|
134
|
+
...state,
|
|
135
|
+
touched: {
|
|
136
|
+
...state.touched,
|
|
137
|
+
[field]: true
|
|
138
|
+
}
|
|
139
|
+
}));
|
|
140
|
+
}
|
|
141
|
+
/**
|
|
142
|
+
* Validate a specific field
|
|
143
|
+
*/
|
|
144
|
+
validateField(field) {
|
|
145
|
+
const currentState = get(this._store);
|
|
146
|
+
const fieldValue = currentState.values[field];
|
|
147
|
+
const errors = [];
|
|
148
|
+
// Check custom field validation
|
|
149
|
+
const registration = this.fieldRegistrations.get(field);
|
|
150
|
+
if (registration?.validate) {
|
|
151
|
+
const customError = registration.validate(fieldValue);
|
|
152
|
+
if (customError) {
|
|
153
|
+
errors.push(customError);
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
// Run Zod validation on the entire form to get field-specific errors
|
|
157
|
+
const result = this.schema.safeParse(currentState.values);
|
|
158
|
+
if (!result.success) {
|
|
159
|
+
const zodErrors = result.error.format();
|
|
160
|
+
const fieldErrors = zodErrors[field]?._errors || [];
|
|
161
|
+
errors.push(...fieldErrors);
|
|
162
|
+
}
|
|
163
|
+
return errors;
|
|
164
|
+
}
|
|
165
|
+
/**
|
|
166
|
+
* Reset the form to initial values
|
|
167
|
+
*/
|
|
168
|
+
reset() {
|
|
169
|
+
this._store.set({
|
|
170
|
+
values: { ...this.initialValues },
|
|
171
|
+
errors: {},
|
|
172
|
+
touched: {},
|
|
173
|
+
isValid: false,
|
|
174
|
+
isDirty: false,
|
|
175
|
+
isSubmitting: false
|
|
176
|
+
});
|
|
177
|
+
this.validate();
|
|
178
|
+
}
|
|
179
|
+
/**
|
|
180
|
+
* Set the form as submitting
|
|
181
|
+
*/
|
|
182
|
+
setSubmitting(isSubmitting) {
|
|
183
|
+
this._store.update((state) => ({
|
|
184
|
+
...state,
|
|
185
|
+
isSubmitting
|
|
186
|
+
}));
|
|
187
|
+
}
|
|
188
|
+
/**
|
|
189
|
+
* Update the schema (useful for dynamic forms)
|
|
190
|
+
*/
|
|
191
|
+
updateSchema(newSchema) {
|
|
192
|
+
this.schema = newSchema;
|
|
193
|
+
this.validate();
|
|
194
|
+
}
|
|
195
|
+
/**
|
|
196
|
+
* Validate the entire form
|
|
197
|
+
*/
|
|
198
|
+
validate() {
|
|
199
|
+
this._store.update((state) => {
|
|
200
|
+
const result = this.schema.safeParse(state.values);
|
|
201
|
+
const errors = {};
|
|
202
|
+
let isValid = true;
|
|
203
|
+
if (!result.success) {
|
|
204
|
+
isValid = false;
|
|
205
|
+
// Convert Zod errors to our error format
|
|
206
|
+
Object.keys(state.values).forEach((key) => {
|
|
207
|
+
const fieldKey = key;
|
|
208
|
+
const fieldErrors = result.error.format()[fieldKey]
|
|
209
|
+
?._errors || [];
|
|
210
|
+
// Add custom field validation errors
|
|
211
|
+
const registration = this.fieldRegistrations.get(key);
|
|
212
|
+
if (registration?.validate) {
|
|
213
|
+
const customError = registration.validate(state.values[fieldKey]);
|
|
214
|
+
if (customError) {
|
|
215
|
+
fieldErrors.push(customError);
|
|
216
|
+
}
|
|
217
|
+
}
|
|
218
|
+
if (fieldErrors.length > 0) {
|
|
219
|
+
errors[fieldKey] = fieldErrors;
|
|
220
|
+
}
|
|
221
|
+
});
|
|
222
|
+
}
|
|
223
|
+
return {
|
|
224
|
+
...state,
|
|
225
|
+
errors,
|
|
226
|
+
isValid
|
|
227
|
+
};
|
|
228
|
+
});
|
|
229
|
+
}
|
|
230
|
+
/**
|
|
231
|
+
* Get the current state of the form
|
|
232
|
+
*/
|
|
233
|
+
getState() {
|
|
234
|
+
return get(this._store);
|
|
235
|
+
}
|
|
236
|
+
/**
|
|
237
|
+
* Destroy the form and clean up resources
|
|
238
|
+
*/
|
|
239
|
+
destroy() {
|
|
240
|
+
// Remove from registries
|
|
241
|
+
formsRegistry.update((registry) => {
|
|
242
|
+
delete registry[this.identifier];
|
|
243
|
+
return registry;
|
|
244
|
+
});
|
|
245
|
+
fieldRegistrations.update((registrations) => {
|
|
246
|
+
delete registrations[this.identifier];
|
|
247
|
+
return registrations;
|
|
248
|
+
});
|
|
249
|
+
// Clear field registrations
|
|
250
|
+
this.fieldRegistrations.clear();
|
|
251
|
+
}
|
|
252
|
+
}
|
|
253
|
+
/**
|
|
254
|
+
* Creates a generic form with Zod validation
|
|
255
|
+
*/
|
|
256
|
+
export function createGenericForm(identifier, schema, initialValues) {
|
|
257
|
+
const form = new FormManager(identifier, schema, initialValues);
|
|
258
|
+
return {
|
|
259
|
+
// Reactive stores that components can directly subscribe to
|
|
260
|
+
values: form.values,
|
|
261
|
+
errors: form.errors,
|
|
262
|
+
touched: form.touched,
|
|
263
|
+
isValid: form.isValid,
|
|
264
|
+
isDirty: form.isDirty,
|
|
265
|
+
isSubmitting: form.isSubmitting,
|
|
266
|
+
// Helper methods
|
|
267
|
+
setField: form.setField.bind(form),
|
|
268
|
+
setFields: form.setFields.bind(form),
|
|
269
|
+
setTouched: form.setTouched.bind(form),
|
|
270
|
+
reset: form.reset.bind(form),
|
|
271
|
+
setSubmitting: form.setSubmitting.bind(form),
|
|
272
|
+
updateSchema: form.updateSchema.bind(form),
|
|
273
|
+
registerField: form.registerField.bind(form),
|
|
274
|
+
validateField: form.validateField.bind(form),
|
|
275
|
+
// For advanced use cases
|
|
276
|
+
getState: form.getState.bind(form),
|
|
277
|
+
destroy: form.destroy.bind(form)
|
|
278
|
+
};
|
|
279
|
+
}
|
|
8
280
|
/**
|
|
9
281
|
* Creates a form validation utility with Svelte 5 reactive stores
|
|
10
282
|
* @param identifier - Unique identifier for the form
|
|
@@ -265,7 +537,7 @@ export class FormValidator {
|
|
|
265
537
|
}));
|
|
266
538
|
}
|
|
267
539
|
/**
|
|
268
|
-
* Get the current state of the form
|
|
540
|
+
* Get the current state of the form
|
|
269
541
|
*/
|
|
270
542
|
getState() {
|
|
271
543
|
return get(this._store);
|
|
@@ -302,7 +574,6 @@ export function createForm(identifier, initialValues, options) {
|
|
|
302
574
|
/**
|
|
303
575
|
* Get a form by its identifier
|
|
304
576
|
*/
|
|
305
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
306
577
|
export function getFormById(identifier) {
|
|
307
578
|
const registry = get(formsRegistry);
|
|
308
579
|
return registry[identifier];
|
|
@@ -354,6 +625,43 @@ export function createFormSubscription(identifier) {
|
|
|
354
625
|
destroy: () => clearInterval(intervalId)
|
|
355
626
|
};
|
|
356
627
|
}
|
|
628
|
+
/**
|
|
629
|
+
* Helper to get field state for a specific form and field
|
|
630
|
+
*/
|
|
631
|
+
export function getFieldState(formId, fieldName) {
|
|
632
|
+
const form = getFormById(formId);
|
|
633
|
+
if (!form) {
|
|
634
|
+
return {
|
|
635
|
+
value: undefined,
|
|
636
|
+
error: [],
|
|
637
|
+
touched: false,
|
|
638
|
+
isValid: true
|
|
639
|
+
};
|
|
640
|
+
}
|
|
641
|
+
const state = form.getState();
|
|
642
|
+
return {
|
|
643
|
+
value: state.values[fieldName],
|
|
644
|
+
error: state.errors[fieldName] || [],
|
|
645
|
+
touched: state.touched[fieldName] || false,
|
|
646
|
+
isValid: !state.errors[fieldName] || state.errors[fieldName].length === 0
|
|
647
|
+
};
|
|
648
|
+
}
|
|
649
|
+
/**
|
|
650
|
+
* Helper to update a field value for a specific form
|
|
651
|
+
*/
|
|
652
|
+
export function updateFieldValue(formId, fieldName, value) {
|
|
653
|
+
const form = getFormById(formId);
|
|
654
|
+
if (form && 'setField' in form) {
|
|
655
|
+
form.setField(fieldName, value);
|
|
656
|
+
}
|
|
657
|
+
}
|
|
658
|
+
/**
|
|
659
|
+
* Helper to get all registered field names for a form
|
|
660
|
+
*/
|
|
661
|
+
export function getFormFieldNames(formId) {
|
|
662
|
+
const registrations = get(fieldRegistrations);
|
|
663
|
+
return Object.keys(registrations[formId] || {});
|
|
664
|
+
}
|
|
357
665
|
/**
|
|
358
666
|
* Store to track if the form is adding or updating to the Canvas
|
|
359
667
|
*/
|