@formisch/svelte 0.1.0
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/LICENSE.md +9 -0
- package/README.md +81 -0
- package/dist/components/Field/Field.svelte +31 -0
- package/dist/components/Field/Field.svelte.d.ts +36 -0
- package/dist/components/Field/index.d.ts +1 -0
- package/dist/components/Field/index.js +1 -0
- package/dist/components/FieldArray/FieldArray.svelte +36 -0
- package/dist/components/FieldArray/FieldArray.svelte.d.ts +36 -0
- package/dist/components/FieldArray/index.d.ts +1 -0
- package/dist/components/FieldArray/index.js +1 -0
- package/dist/components/Form/Form.svelte +28 -0
- package/dist/components/Form/Form.svelte.d.ts +33 -0
- package/dist/components/Form/index.d.ts +1 -0
- package/dist/components/Form/index.js +1 -0
- package/dist/components/index.d.ts +3 -0
- package/dist/components/index.js +3 -0
- package/dist/core/index.svelte.d.ts +256 -0
- package/dist/core/index.svelte.js +445 -0
- package/dist/index.d.ts +5 -0
- package/dist/index.js +4 -0
- package/dist/methods/index.svelte.d.ts +127 -0
- package/dist/methods/index.svelte.js +211 -0
- package/dist/runes/createForm/createForm.svelte.d.ts +3 -0
- package/dist/runes/createForm/createForm.svelte.js +38 -0
- package/dist/runes/createForm/index.d.ts +1 -0
- package/dist/runes/createForm/index.js +1 -0
- package/dist/runes/index.d.ts +3 -0
- package/dist/runes/index.js +3 -0
- package/dist/runes/useField/index.d.ts +1 -0
- package/dist/runes/useField/index.js +1 -0
- package/dist/runes/useField/useField.svelte.d.ts +7 -0
- package/dist/runes/useField/useField.svelte.js +58 -0
- package/dist/runes/useFieldArray/index.d.ts +1 -0
- package/dist/runes/useFieldArray/index.js +1 -0
- package/dist/runes/useFieldArray/useFieldArray.svelte.d.ts +7 -0
- package/dist/runes/useFieldArray/useFieldArray.svelte.js +29 -0
- package/dist/types/field.d.ts +38 -0
- package/dist/types/field.js +1 -0
- package/dist/types/form.d.ts +10 -0
- package/dist/types/form.js +1 -0
- package/dist/types/index.d.ts +3 -0
- package/dist/types/index.js +3 -0
- package/dist/types/utils.d.ts +4 -0
- package/dist/types/utils.js +1 -0
- package/dist/utils/index.d.ts +1 -0
- package/dist/utils/index.js +1 -0
- package/dist/utils/unwrap/index.d.ts +1 -0
- package/dist/utils/unwrap/index.js +1 -0
- package/dist/utils/unwrap/unwrap.d.ts +2 -0
- package/dist/utils/unwrap/unwrap.js +6 -0
- package/package.json +75 -0
|
@@ -0,0 +1,211 @@
|
|
|
1
|
+
import { INTERNAL, batch, copyItemState, createId, getFieldInput, getFieldStore, initializeFieldStore, resetItemState, setFieldInput, setInitialFieldInput, swapItemState, untrack, validateFormInput, validateIfRequired, walkFieldStore } from "../core/index.svelte";
|
|
2
|
+
|
|
3
|
+
//#region src/focus/focus.ts
|
|
4
|
+
function focus(config) {
|
|
5
|
+
getFieldStore(config.form[INTERNAL], config.path).elements[0]?.focus();
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
//#endregion
|
|
9
|
+
//#region src/getAllErrors/getAllErrors.ts
|
|
10
|
+
function getAllErrors(form) {
|
|
11
|
+
let allErrors = null;
|
|
12
|
+
walkFieldStore(form[INTERNAL], (internalFieldStore) => {
|
|
13
|
+
const errors = internalFieldStore.errors.value;
|
|
14
|
+
if (errors) if (allErrors) allErrors.push(...errors);
|
|
15
|
+
else allErrors = [...errors];
|
|
16
|
+
});
|
|
17
|
+
return allErrors;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
//#endregion
|
|
21
|
+
//#region src/getErrors/getErrors.ts
|
|
22
|
+
function getErrors(form, config) {
|
|
23
|
+
return (config?.path ? getFieldStore(form[INTERNAL], config.path) : form[INTERNAL]).errors.value;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
//#endregion
|
|
27
|
+
//#region src/getInput/getInput.ts
|
|
28
|
+
function getInput(form, config) {
|
|
29
|
+
return getFieldInput(config?.path ? getFieldStore(form[INTERNAL], config.path) : form[INTERNAL]);
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
//#endregion
|
|
33
|
+
//#region src/handleSubmit/handleSubmit.ts
|
|
34
|
+
function handleSubmit(form, handler) {
|
|
35
|
+
return async (event) => {
|
|
36
|
+
event.preventDefault();
|
|
37
|
+
const internalFormStore = form[INTERNAL];
|
|
38
|
+
internalFormStore.isSubmitted.value = true;
|
|
39
|
+
internalFormStore.isSubmitting.value = true;
|
|
40
|
+
try {
|
|
41
|
+
const result = await validateFormInput(internalFormStore, { shouldFocus: true });
|
|
42
|
+
if (result.success) await handler(result.output, event);
|
|
43
|
+
} catch (error) {
|
|
44
|
+
internalFormStore.errors.value = [error instanceof Error ? error.message : "An unknown error has occurred."];
|
|
45
|
+
} finally {
|
|
46
|
+
internalFormStore.isSubmitting.value = false;
|
|
47
|
+
}
|
|
48
|
+
};
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
//#endregion
|
|
52
|
+
//#region src/insert/insert.ts
|
|
53
|
+
function insert(form, config) {
|
|
54
|
+
const internalFormStore = form[INTERNAL];
|
|
55
|
+
const internalArrayStore = getFieldStore(internalFormStore, config.path);
|
|
56
|
+
const items = untrack(() => internalArrayStore.items.value);
|
|
57
|
+
const insertIndex = config.at === void 0 ? items.length : config.at;
|
|
58
|
+
if (insertIndex >= 0 && insertIndex <= items.length) batch(() => {
|
|
59
|
+
const newItems = [...items];
|
|
60
|
+
newItems.splice(insertIndex, 0, createId());
|
|
61
|
+
internalArrayStore.items.value = newItems;
|
|
62
|
+
for (let index = items.length; index > insertIndex; index--) copyItemState(internalArrayStore.children[index - 1], internalArrayStore.children[index]);
|
|
63
|
+
if (!internalArrayStore.children[insertIndex]) {
|
|
64
|
+
const path = JSON.parse(internalArrayStore.name);
|
|
65
|
+
internalArrayStore.children[insertIndex] = {};
|
|
66
|
+
path.push(insertIndex);
|
|
67
|
+
initializeFieldStore(internalArrayStore.children[insertIndex], internalArrayStore.schema.item, config.initialInput, path);
|
|
68
|
+
} else resetItemState(internalArrayStore.children[insertIndex], config.initialInput);
|
|
69
|
+
internalArrayStore.isTouched.value = true;
|
|
70
|
+
internalArrayStore.isDirty.value = true;
|
|
71
|
+
validateIfRequired(internalFormStore, internalArrayStore, "input");
|
|
72
|
+
});
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
//#endregion
|
|
76
|
+
//#region src/move/move.ts
|
|
77
|
+
function move(form, config) {
|
|
78
|
+
const internalFormStore = form[INTERNAL];
|
|
79
|
+
const internalArrayStore = getFieldStore(internalFormStore, config.path);
|
|
80
|
+
const items = untrack(() => internalArrayStore.items.value);
|
|
81
|
+
if (config.from >= 0 && config.from <= items.length - 1 && config.to >= 0 && config.to <= items.length - 1 && config.from !== config.to) batch(() => {
|
|
82
|
+
const newItems = [...items];
|
|
83
|
+
newItems.splice(config.to, 0, newItems.splice(config.from, 1)[0]);
|
|
84
|
+
internalArrayStore.items.value = newItems;
|
|
85
|
+
const tempInternalFieldStore = {};
|
|
86
|
+
initializeFieldStore(tempInternalFieldStore, internalArrayStore.schema.item, void 0, []);
|
|
87
|
+
copyItemState(internalArrayStore.children[config.from < config.to ? config.from : config.to], tempInternalFieldStore);
|
|
88
|
+
if (config.from < config.to) for (let index = config.from; index < config.to; index++) copyItemState(internalArrayStore.children[index + 1], internalArrayStore.children[index]);
|
|
89
|
+
else for (let index = config.from; index > config.to; index--) copyItemState(internalArrayStore.children[index - 1], internalArrayStore.children[index]);
|
|
90
|
+
copyItemState(tempInternalFieldStore, internalArrayStore.children[config.from < config.to ? config.to : config.from]);
|
|
91
|
+
internalArrayStore.isTouched.value = true;
|
|
92
|
+
internalArrayStore.isDirty.value = internalArrayStore.startItems.value.join() !== newItems.join();
|
|
93
|
+
validateIfRequired(internalFormStore, internalArrayStore, "input");
|
|
94
|
+
});
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
//#endregion
|
|
98
|
+
//#region src/remove/remove.ts
|
|
99
|
+
function remove(form, config) {
|
|
100
|
+
const internalFormStore = form[INTERNAL];
|
|
101
|
+
const internalArrayStore = getFieldStore(internalFormStore, config.path);
|
|
102
|
+
const items = untrack(() => internalArrayStore.items.value);
|
|
103
|
+
if (config.at >= 0 && config.at <= items.length - 1) batch(() => {
|
|
104
|
+
const newItems = [...items];
|
|
105
|
+
newItems.splice(config.at, 1);
|
|
106
|
+
internalArrayStore.items.value = newItems;
|
|
107
|
+
for (let index = config.at; index < items.length - 1; index++) copyItemState(internalArrayStore.children[index + 1], internalArrayStore.children[index]);
|
|
108
|
+
internalArrayStore.isTouched.value = true;
|
|
109
|
+
internalArrayStore.isDirty.value = internalArrayStore.startItems.value.join() !== newItems.join();
|
|
110
|
+
validateIfRequired(internalFormStore, internalArrayStore, "input");
|
|
111
|
+
});
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
//#endregion
|
|
115
|
+
//#region src/replace/replace.ts
|
|
116
|
+
function replace(form, config) {
|
|
117
|
+
const internalFormStore = form[INTERNAL];
|
|
118
|
+
const internalArrayStore = getFieldStore(internalFormStore, config.path);
|
|
119
|
+
const items = untrack(() => internalArrayStore.items.value);
|
|
120
|
+
if (config.at >= 0 && config.at <= items.length - 1) batch(() => {
|
|
121
|
+
const newItems = [...items];
|
|
122
|
+
newItems[config.at] = createId();
|
|
123
|
+
internalArrayStore.items.value = newItems;
|
|
124
|
+
resetItemState(internalArrayStore.children[config.at], config.initialInput);
|
|
125
|
+
internalArrayStore.isTouched.value = true;
|
|
126
|
+
internalArrayStore.isDirty.value = true;
|
|
127
|
+
validateIfRequired(internalFormStore, internalArrayStore, "input");
|
|
128
|
+
});
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
//#endregion
|
|
132
|
+
//#region src/reset/reset.ts
|
|
133
|
+
function reset(form, config) {
|
|
134
|
+
batch(() => {
|
|
135
|
+
untrack(() => {
|
|
136
|
+
const internalFormStore = form[INTERNAL];
|
|
137
|
+
const internalFieldStore = config?.path ? getFieldStore(internalFormStore, config.path) : internalFormStore;
|
|
138
|
+
if (config?.initialInput) setInitialFieldInput(internalFieldStore, config.initialInput);
|
|
139
|
+
walkFieldStore(internalFieldStore, (internalFieldStore$1) => {
|
|
140
|
+
if (!config?.keepErrors) internalFieldStore$1.errors.value = null;
|
|
141
|
+
if (internalFieldStore$1.kind === "array") {
|
|
142
|
+
internalFieldStore$1.startItems.value = internalFieldStore$1.initialItems.value;
|
|
143
|
+
if (!config?.keepInput || internalFieldStore$1.startItems.value.length === internalFieldStore$1.items.value.length) internalFieldStore$1.items.value = internalFieldStore$1.initialItems.value;
|
|
144
|
+
if (!config?.keepTouched) internalFieldStore$1.isTouched.value = false;
|
|
145
|
+
internalFieldStore$1.isDirty.value = internalFieldStore$1.startItems.value !== internalFieldStore$1.items.value;
|
|
146
|
+
} else if (internalFieldStore$1.kind === "value") {
|
|
147
|
+
internalFieldStore$1.startInput.value = internalFieldStore$1.initialInput.value;
|
|
148
|
+
if (!config?.keepInput) internalFieldStore$1.input.value = internalFieldStore$1.initialInput.value;
|
|
149
|
+
if (!config?.keepTouched) internalFieldStore$1.isTouched.value = false;
|
|
150
|
+
internalFieldStore$1.isDirty.value = internalFieldStore$1.startInput.value !== internalFieldStore$1.input.value;
|
|
151
|
+
for (const element of internalFieldStore$1.elements) if (element.type === "file") element.value = "";
|
|
152
|
+
}
|
|
153
|
+
});
|
|
154
|
+
if (!config?.path) {
|
|
155
|
+
if (!config?.keepSubmitted) internalFormStore.isSubmitted.value = false;
|
|
156
|
+
if (internalFormStore.validate === "initial") validateFormInput(internalFormStore);
|
|
157
|
+
}
|
|
158
|
+
});
|
|
159
|
+
});
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
//#endregion
|
|
163
|
+
//#region src/setErrors/setErrors.ts
|
|
164
|
+
function setErrors(form, config) {
|
|
165
|
+
(config.path ? getFieldStore(form[INTERNAL], config.path) : form[INTERNAL]).errors.value = config.errors;
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
//#endregion
|
|
169
|
+
//#region src/setInput/setInput.ts
|
|
170
|
+
function setInput(form, config) {
|
|
171
|
+
batch(() => {
|
|
172
|
+
const internalFormStore = form[INTERNAL];
|
|
173
|
+
const internalFieldStore = config.path ? getFieldStore(internalFormStore, config.path) : internalFormStore;
|
|
174
|
+
setFieldInput(internalFieldStore, config.input);
|
|
175
|
+
validateIfRequired(internalFormStore, internalFieldStore, "input");
|
|
176
|
+
});
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
//#endregion
|
|
180
|
+
//#region src/submit/submit.ts
|
|
181
|
+
function submit(form) {
|
|
182
|
+
form[INTERNAL].element?.requestSubmit();
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
//#endregion
|
|
186
|
+
//#region src/swap/swap.ts
|
|
187
|
+
function swap(form, config) {
|
|
188
|
+
const internalFormStore = form[INTERNAL];
|
|
189
|
+
const internalArrayStore = getFieldStore(internalFormStore, config.path);
|
|
190
|
+
const items = untrack(() => internalArrayStore.items.value);
|
|
191
|
+
if (config.at >= 0 && config.at <= items.length - 1 && config.and >= 0 && config.and <= items.length - 1 && config.at !== config.and) batch(() => {
|
|
192
|
+
const newItems = [...items];
|
|
193
|
+
const tempItemId = newItems[config.at];
|
|
194
|
+
newItems[config.at] = newItems[config.and];
|
|
195
|
+
newItems[config.and] = tempItemId;
|
|
196
|
+
internalArrayStore.items.value = newItems;
|
|
197
|
+
swapItemState(internalArrayStore.children[config.at], internalArrayStore.children[config.and]);
|
|
198
|
+
internalArrayStore.isTouched.value = true;
|
|
199
|
+
internalArrayStore.isDirty.value = internalArrayStore.startItems.value.join() !== newItems.join();
|
|
200
|
+
validateIfRequired(internalFormStore, internalArrayStore, "input");
|
|
201
|
+
});
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
//#endregion
|
|
205
|
+
//#region src/validate/validate.ts
|
|
206
|
+
function validate(form, config) {
|
|
207
|
+
return validateFormInput(form[INTERNAL], config);
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
//#endregion
|
|
211
|
+
export { focus, getAllErrors, getErrors, getInput, handleSubmit, insert, move, remove, replace, reset, setErrors, setInput, submit, swap, validate };
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import { createFormStore, getFieldBool, INTERNAL, validateFormInput, } from '../../core/index.svelte';
|
|
2
|
+
import { onMount } from 'svelte';
|
|
3
|
+
import * as v from 'valibot';
|
|
4
|
+
export function createForm(config) {
|
|
5
|
+
const internalFormStore = createFormStore(config, (input) => v.safeParseAsync(config.schema, input));
|
|
6
|
+
onMount(() => {
|
|
7
|
+
if (config.validate === 'initial') {
|
|
8
|
+
validateFormInput(internalFormStore);
|
|
9
|
+
}
|
|
10
|
+
});
|
|
11
|
+
const isTouched = $derived(getFieldBool(internalFormStore, 'isTouched'));
|
|
12
|
+
const isDirty = $derived(getFieldBool(internalFormStore, 'isDirty'));
|
|
13
|
+
const isValid = $derived(!getFieldBool(internalFormStore, 'errors'));
|
|
14
|
+
return {
|
|
15
|
+
[INTERNAL]: internalFormStore,
|
|
16
|
+
get isSubmitting() {
|
|
17
|
+
return internalFormStore.isSubmitting.value;
|
|
18
|
+
},
|
|
19
|
+
get isSubmitted() {
|
|
20
|
+
return internalFormStore.isSubmitted.value;
|
|
21
|
+
},
|
|
22
|
+
get isValidating() {
|
|
23
|
+
return internalFormStore.isValidating.value;
|
|
24
|
+
},
|
|
25
|
+
get isTouched() {
|
|
26
|
+
return isTouched;
|
|
27
|
+
},
|
|
28
|
+
get isDirty() {
|
|
29
|
+
return isDirty;
|
|
30
|
+
},
|
|
31
|
+
get isValid() {
|
|
32
|
+
return isValid;
|
|
33
|
+
},
|
|
34
|
+
get errors() {
|
|
35
|
+
return internalFormStore.errors.value;
|
|
36
|
+
},
|
|
37
|
+
};
|
|
38
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from './createForm.svelte.ts';
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from './createForm.svelte';
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from './useField.svelte.ts';
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from './useField.svelte';
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import { type RequiredPath, type Schema, type ValidPath } from '../../core/index.svelte';
|
|
2
|
+
import type * as v from 'valibot';
|
|
3
|
+
import type { FieldStore, FormStore, MaybeGetter } from '../../types/index.ts';
|
|
4
|
+
export interface UseFieldConfig<TSchema extends Schema = Schema, TFieldPath extends RequiredPath = RequiredPath> {
|
|
5
|
+
readonly path: ValidPath<v.InferInput<TSchema>, TFieldPath>;
|
|
6
|
+
}
|
|
7
|
+
export declare function useField<TSchema extends Schema, TFieldPath extends RequiredPath>(form: MaybeGetter<FormStore<TSchema>>, config: MaybeGetter<UseFieldConfig<TSchema, TFieldPath>>): FieldStore<TSchema, TFieldPath>;
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
import { getElementInput, getFieldBool, getFieldInput, getFieldStore, INTERNAL, setFieldBool, setFieldInput, validateIfRequired, } from '../../core/index.svelte';
|
|
2
|
+
import { createAttachmentKey } from 'svelte/attachments';
|
|
3
|
+
import { unwrap } from '../../utils/index';
|
|
4
|
+
export function useField(form, config) {
|
|
5
|
+
const path = $derived(unwrap(config).path);
|
|
6
|
+
const internalFormStore = $derived(unwrap(form)[INTERNAL]);
|
|
7
|
+
const internalFieldStore = $derived(getFieldStore(internalFormStore, path));
|
|
8
|
+
const input = $derived(getFieldInput(internalFieldStore));
|
|
9
|
+
const isTouched = $derived(getFieldBool(internalFieldStore, 'isTouched'));
|
|
10
|
+
const isDirty = $derived(getFieldBool(internalFieldStore, 'isDirty'));
|
|
11
|
+
const isValid = $derived(!getFieldBool(internalFieldStore, 'errors'));
|
|
12
|
+
return {
|
|
13
|
+
get path() {
|
|
14
|
+
return path;
|
|
15
|
+
},
|
|
16
|
+
get input() {
|
|
17
|
+
return input;
|
|
18
|
+
},
|
|
19
|
+
get errors() {
|
|
20
|
+
return internalFieldStore.errors.value;
|
|
21
|
+
},
|
|
22
|
+
get isTouched() {
|
|
23
|
+
return isTouched;
|
|
24
|
+
},
|
|
25
|
+
get isDirty() {
|
|
26
|
+
return isDirty;
|
|
27
|
+
},
|
|
28
|
+
get isValid() {
|
|
29
|
+
return isValid;
|
|
30
|
+
},
|
|
31
|
+
props: {
|
|
32
|
+
get name() {
|
|
33
|
+
return internalFieldStore.name;
|
|
34
|
+
},
|
|
35
|
+
autofocus: !!internalFieldStore.errors.value,
|
|
36
|
+
[createAttachmentKey()](element) {
|
|
37
|
+
internalFieldStore.elements.push(element);
|
|
38
|
+
return () => {
|
|
39
|
+
internalFieldStore.elements = internalFieldStore.elements.filter((el) => el !== element);
|
|
40
|
+
};
|
|
41
|
+
},
|
|
42
|
+
onfocus() {
|
|
43
|
+
setFieldBool(internalFieldStore, 'isTouched', true);
|
|
44
|
+
validateIfRequired(internalFormStore, internalFieldStore, 'touch');
|
|
45
|
+
},
|
|
46
|
+
oninput(event) {
|
|
47
|
+
setFieldInput(internalFieldStore, getElementInput(event.currentTarget, internalFieldStore));
|
|
48
|
+
validateIfRequired(internalFormStore, internalFieldStore, 'input');
|
|
49
|
+
},
|
|
50
|
+
onchange() {
|
|
51
|
+
validateIfRequired(internalFormStore, internalFieldStore, 'change');
|
|
52
|
+
},
|
|
53
|
+
onblur() {
|
|
54
|
+
validateIfRequired(internalFormStore, internalFieldStore, 'blur');
|
|
55
|
+
},
|
|
56
|
+
},
|
|
57
|
+
};
|
|
58
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from './useFieldArray.svelte.ts';
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from './useFieldArray.svelte';
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import { type RequiredPath, type Schema, type ValidArrayPath } from '../../core/index.svelte';
|
|
2
|
+
import type * as v from 'valibot';
|
|
3
|
+
import type { FieldArrayStore, FormStore, MaybeGetter } from '../../types/index.ts';
|
|
4
|
+
export interface UseFieldArrayConfig<TSchema extends Schema = Schema, TFieldArrayPath extends RequiredPath = RequiredPath> {
|
|
5
|
+
readonly path: ValidArrayPath<v.InferInput<TSchema>, TFieldArrayPath>;
|
|
6
|
+
}
|
|
7
|
+
export declare function useFieldArray<TSchema extends Schema, TFieldArrayPath extends RequiredPath>(form: MaybeGetter<FormStore<TSchema>>, config: MaybeGetter<UseFieldArrayConfig<TSchema, TFieldArrayPath>>): FieldArrayStore<TSchema, TFieldArrayPath>;
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import { getFieldBool, getFieldStore, INTERNAL, } from '../../core/index.svelte';
|
|
2
|
+
import { unwrap } from '../../utils/index';
|
|
3
|
+
export function useFieldArray(form, config) {
|
|
4
|
+
const path = $derived(unwrap(config).path);
|
|
5
|
+
const internalFieldStore = $derived(getFieldStore(unwrap(form)[INTERNAL], path));
|
|
6
|
+
const isTouched = $derived(getFieldBool(internalFieldStore, 'isTouched'));
|
|
7
|
+
const isDirty = $derived(getFieldBool(internalFieldStore, 'isDirty'));
|
|
8
|
+
const isValid = $derived(!getFieldBool(internalFieldStore, 'errors'));
|
|
9
|
+
return {
|
|
10
|
+
get path() {
|
|
11
|
+
return path;
|
|
12
|
+
},
|
|
13
|
+
get items() {
|
|
14
|
+
return internalFieldStore.items.value;
|
|
15
|
+
},
|
|
16
|
+
get errors() {
|
|
17
|
+
return internalFieldStore.errors.value;
|
|
18
|
+
},
|
|
19
|
+
get isTouched() {
|
|
20
|
+
return isTouched;
|
|
21
|
+
},
|
|
22
|
+
get isDirty() {
|
|
23
|
+
return isDirty;
|
|
24
|
+
},
|
|
25
|
+
get isValid() {
|
|
26
|
+
return isValid;
|
|
27
|
+
},
|
|
28
|
+
};
|
|
29
|
+
}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import type { FieldElement, PartialValues, PathValue, RequiredPath, Schema, ValidArrayPath, ValidPath } from '../core/index.svelte';
|
|
2
|
+
import type { FocusEventHandler, FormEventHandler } from 'svelte/elements';
|
|
3
|
+
import type * as v from 'valibot';
|
|
4
|
+
/**
|
|
5
|
+
* Value type of the field element props.
|
|
6
|
+
*/
|
|
7
|
+
export interface FieldElementProps {
|
|
8
|
+
readonly name: string;
|
|
9
|
+
readonly autofocus: boolean;
|
|
10
|
+
readonly [ref: symbol]: (element: FieldElement) => () => void;
|
|
11
|
+
readonly onfocus: FocusEventHandler<FieldElement>;
|
|
12
|
+
readonly oninput: FormEventHandler<FieldElement>;
|
|
13
|
+
readonly onchange: FormEventHandler<FieldElement>;
|
|
14
|
+
readonly onblur: FocusEventHandler<FieldElement>;
|
|
15
|
+
}
|
|
16
|
+
/**
|
|
17
|
+
* Value type of the field store.
|
|
18
|
+
*/
|
|
19
|
+
export interface FieldStore<TSchema extends Schema = Schema, TFieldPath extends RequiredPath = RequiredPath> {
|
|
20
|
+
readonly path: ValidPath<v.InferInput<TSchema>, TFieldPath>;
|
|
21
|
+
readonly input: PartialValues<PathValue<v.InferInput<TSchema>, TFieldPath>>;
|
|
22
|
+
readonly errors: [string, ...string[]] | null;
|
|
23
|
+
readonly isTouched: boolean;
|
|
24
|
+
readonly isDirty: boolean;
|
|
25
|
+
readonly isValid: boolean;
|
|
26
|
+
readonly props: FieldElementProps;
|
|
27
|
+
}
|
|
28
|
+
/**
|
|
29
|
+
* Value type of the field array store.
|
|
30
|
+
*/
|
|
31
|
+
export interface FieldArrayStore<TSchema extends Schema = Schema, TFieldArrayPath extends RequiredPath = RequiredPath> {
|
|
32
|
+
readonly path: ValidArrayPath<v.InferInput<TSchema>, TFieldArrayPath>;
|
|
33
|
+
readonly items: string[];
|
|
34
|
+
readonly errors: [string, ...string[]] | null;
|
|
35
|
+
readonly isTouched: boolean;
|
|
36
|
+
readonly isDirty: boolean;
|
|
37
|
+
readonly isValid: boolean;
|
|
38
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import type { BaseFormStore, Schema } from '../core/index.svelte';
|
|
2
|
+
export interface FormStore<TSchema extends Schema = Schema> extends BaseFormStore<TSchema> {
|
|
3
|
+
readonly isSubmitting: boolean;
|
|
4
|
+
readonly isSubmitted: boolean;
|
|
5
|
+
readonly isValidating: boolean;
|
|
6
|
+
readonly isTouched: boolean;
|
|
7
|
+
readonly isDirty: boolean;
|
|
8
|
+
readonly isValid: boolean;
|
|
9
|
+
readonly errors: [string, ...string[]] | null;
|
|
10
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from './unwrap/index.ts';
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from './unwrap/index';
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from './unwrap.ts';
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from './unwrap';
|
package/package.json
ADDED
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@formisch/svelte",
|
|
3
|
+
"description": "The modular and type-safe form library for Svelte",
|
|
4
|
+
"version": "0.1.0",
|
|
5
|
+
"license": "MIT",
|
|
6
|
+
"author": "Fabian Hiller",
|
|
7
|
+
"homepage": "https://formisch.dev",
|
|
8
|
+
"repository": {
|
|
9
|
+
"type": "git",
|
|
10
|
+
"url": "https://github.com/fabian-hiller/formisch"
|
|
11
|
+
},
|
|
12
|
+
"keywords": [
|
|
13
|
+
"vue",
|
|
14
|
+
"form",
|
|
15
|
+
"typescript",
|
|
16
|
+
"schema",
|
|
17
|
+
"validation"
|
|
18
|
+
],
|
|
19
|
+
"type": "module",
|
|
20
|
+
"main": "./dist/index.js",
|
|
21
|
+
"types": "./dist/types/index.d.ts",
|
|
22
|
+
"svelte": "./dist/index.js",
|
|
23
|
+
"exports": {
|
|
24
|
+
".": {
|
|
25
|
+
"types": "./dist/index.d.ts",
|
|
26
|
+
"svelte": "./dist/index.js"
|
|
27
|
+
}
|
|
28
|
+
},
|
|
29
|
+
"sideEffects": false,
|
|
30
|
+
"files": [
|
|
31
|
+
"dist",
|
|
32
|
+
"!dist/**/*.test.*",
|
|
33
|
+
"!dist/**/*.spec.*"
|
|
34
|
+
],
|
|
35
|
+
"publishConfig": {
|
|
36
|
+
"access": "public"
|
|
37
|
+
},
|
|
38
|
+
"devDependencies": {
|
|
39
|
+
"@eslint/compat": "^1.3.2",
|
|
40
|
+
"@eslint/js": "^9.35.0",
|
|
41
|
+
"@sveltejs/adapter-auto": "^6.1.0",
|
|
42
|
+
"@sveltejs/kit": "^2.37.1",
|
|
43
|
+
"@sveltejs/package": "^2.5.0",
|
|
44
|
+
"@sveltejs/vite-plugin-svelte": "^6.2.0",
|
|
45
|
+
"eslint": "^9.35.0",
|
|
46
|
+
"eslint-plugin-svelte": "^3.12.2",
|
|
47
|
+
"globals": "^16.4.0",
|
|
48
|
+
"publint": "^0.3.12",
|
|
49
|
+
"svelte": "^5.38.8",
|
|
50
|
+
"svelte-check": "^4.3.1",
|
|
51
|
+
"typescript": "^5.9.2",
|
|
52
|
+
"typescript-eslint": "^8.43.0",
|
|
53
|
+
"vite": "^7.1.5",
|
|
54
|
+
"@formisch/core": "0.2.0",
|
|
55
|
+
"@formisch/methods": "0.2.0"
|
|
56
|
+
},
|
|
57
|
+
"peerDependencies": {
|
|
58
|
+
"svelte": "^5.29.0",
|
|
59
|
+
"typescript": ">=5",
|
|
60
|
+
"valibot": "^1.0.0"
|
|
61
|
+
},
|
|
62
|
+
"peerDependenciesMeta": {
|
|
63
|
+
"typescript": {
|
|
64
|
+
"optional": true
|
|
65
|
+
}
|
|
66
|
+
},
|
|
67
|
+
"scripts": {
|
|
68
|
+
"build": "svelte-package --input src && node ./scripts/rewrite-imports.js",
|
|
69
|
+
"check": "svelte-kit sync && svelte-check --tsconfig ./tsconfig.json",
|
|
70
|
+
"lint": "eslint \"src/**/*.ts*\" && tsc --noEmit",
|
|
71
|
+
"lint.fix": "eslint \"src/**/*.ts*\" --fix",
|
|
72
|
+
"format": "prettier --write ./src",
|
|
73
|
+
"format.check": "prettier --check ./src"
|
|
74
|
+
}
|
|
75
|
+
}
|