Skip to content

Commit 13a1beb

Browse files
committed
[form] Add createForm function
1 parent 40708a0 commit 13a1beb

File tree

4 files changed

+130
-110
lines changed

4 files changed

+130
-110
lines changed

.changeset/mighty-rockets-push.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
"@sjsf/form": minor
3+
---
4+
5+
Add `createForm` function

packages/form/src/form/form-base.svelte

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
<!--
22
@component
3-
@deprecated use `SimpleForm` component
3+
@deprecated use `SimpleForm` instead
44
-->
55
<script lang="ts" module>
66
import type { HTMLFormAttributes } from "svelte/elements";

packages/form/src/form/form.svelte

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
<!--
22
@component
3-
@deprecated use `SimpleForm` component
3+
@deprecated use `SimpleForm` instead
44
-->
55
<script lang="ts" generics="T, E">
66
import { SvelteMap } from "svelte/reactivity";

packages/form/src/form/use-form.svelte.ts

Lines changed: 123 additions & 108 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ import type { Templates } from "./templates/index.js";
1515
import type { Icons } from "./icons.js";
1616
import type { InputsValidationMode } from "./validation.js";
1717
import type { Errors } from "./errors.js";
18-
import { setFromContext } from "./context/index.js";
18+
import { setFromContext, type FormContext } from "./context/index.js";
1919
import { DefaultFormMerger, type FormMerger } from "./merger.js";
2020
import { fields as defaultFields } from "./fields/index.js";
2121
import { templates as defaultTemplates } from "./templates/index.js";
@@ -94,7 +94,9 @@ export interface FormAPI<T, E> extends FormState<T, E> {
9494

9595
type Value = SchemaValue | undefined;
9696

97-
export function useForm<T, E>(options: UseFormOptions<T, E>): FormAPI<T, E> {
97+
export function createForm<T, E>(
98+
options: UseFormOptions<T, E>
99+
): [FormContext, FormAPI<T, E>] {
98100
const merger = $derived(
99101
options.merger ?? new DefaultFormMerger(options.validator, options.schema)
100102
);
@@ -161,113 +163,126 @@ export function useForm<T, E>(options: UseFormOptions<T, E>): FormAPI<T, E> {
161163
})
162164
);
163165

164-
setFromContext({
165-
get inputsValidationMode() {
166-
return inputsValidationMode;
166+
return [
167+
{
168+
get inputsValidationMode() {
169+
return inputsValidationMode;
170+
},
171+
get isSubmitted() {
172+
return isSubmitted;
173+
},
174+
get errors() {
175+
return errors;
176+
},
177+
get schema() {
178+
return options.schema;
179+
},
180+
get uiSchema() {
181+
return uiSchema;
182+
},
183+
get disabled() {
184+
return disabled;
185+
},
186+
get idPrefix() {
187+
return idPrefix;
188+
},
189+
get idSeparator() {
190+
return idSeparator;
191+
},
192+
get validator() {
193+
return options.validator;
194+
},
195+
get merger() {
196+
return merger;
197+
},
198+
get fields() {
199+
return fields;
200+
},
201+
get templates() {
202+
return templates;
203+
},
204+
get components() {
205+
return options.components;
206+
},
207+
get widgets() {
208+
return options.widgets;
209+
},
210+
get translation() {
211+
return options.translation;
212+
},
213+
get icons() {
214+
return icons;
215+
},
216+
get schedulerYield() {
217+
return schedulerYield;
218+
},
219+
iconOrTranslation: (<L extends Label>(
220+
internals: ComponentInternals,
221+
data: () => [L, ...Labels[L]]
222+
) => {
223+
IconOrTranslation(internals, {
224+
get data() {
225+
return data();
226+
},
227+
});
228+
}) as unknown as Snippet<
229+
[
230+
{
231+
[L in Label]: [L, ...Labels[L]];
232+
}[Label],
233+
]
234+
>,
167235
},
168-
get isSubmitted() {
169-
return isSubmitted;
236+
{
237+
get value() {
238+
return getSnapshot() as T | undefined;
239+
},
240+
set value(v) {
241+
value = merger.mergeFormDataAndSchemaDefaults(
242+
v as Value,
243+
options.schema
244+
);
245+
},
246+
get formValue() {
247+
return value;
248+
},
249+
set formValue(v) {
250+
value = v;
251+
},
252+
get errors() {
253+
return errors;
254+
},
255+
set errors(v) {
256+
errors = v;
257+
},
258+
get isSubmitted() {
259+
return isSubmitted;
260+
},
261+
set isSubmitted(v) {
262+
isSubmitted = v;
263+
},
264+
validate() {
265+
return validateSnapshot(getSnapshot());
266+
},
267+
enhance(node) {
268+
$effect(() => {
269+
node.addEventListener("submit", submitHandler);
270+
node.addEventListener("reset", resetHandler);
271+
return () => {
272+
node.removeEventListener("submit", submitHandler);
273+
node.removeEventListener("reset", resetHandler);
274+
};
275+
});
276+
},
170277
},
171-
get errors() {
172-
return errors;
173-
},
174-
get schema() {
175-
return options.schema;
176-
},
177-
get uiSchema() {
178-
return uiSchema;
179-
},
180-
get disabled() {
181-
return disabled;
182-
},
183-
get idPrefix() {
184-
return idPrefix;
185-
},
186-
get idSeparator() {
187-
return idSeparator;
188-
},
189-
get validator() {
190-
return options.validator;
191-
},
192-
get merger() {
193-
return merger;
194-
},
195-
get fields() {
196-
return fields;
197-
},
198-
get templates() {
199-
return templates;
200-
},
201-
get components() {
202-
return options.components;
203-
},
204-
get widgets() {
205-
return options.widgets;
206-
},
207-
get translation() {
208-
return options.translation;
209-
},
210-
get icons() {
211-
return icons;
212-
},
213-
get schedulerYield() {
214-
return schedulerYield;
215-
},
216-
iconOrTranslation: (<L extends Label>(
217-
internals: ComponentInternals,
218-
data: () => [L, ...Labels[L]]
219-
) => {
220-
IconOrTranslation(internals, {
221-
get data() {
222-
return data();
223-
},
224-
});
225-
}) as unknown as Snippet<
226-
[
227-
{
228-
[L in Label]: [L, ...Labels[L]];
229-
}[Label],
230-
]
231-
>,
232-
});
278+
];
279+
}
233280

234-
return {
235-
get value() {
236-
return getSnapshot() as T | undefined;
237-
},
238-
set value(v) {
239-
value = merger.mergeFormDataAndSchemaDefaults(v as Value, options.schema);
240-
},
241-
get formValue() {
242-
return value;
243-
},
244-
set formValue(v) {
245-
value = v;
246-
},
247-
get errors() {
248-
return errors;
249-
},
250-
set errors(v) {
251-
errors = v;
252-
},
253-
get isSubmitted() {
254-
return isSubmitted;
255-
},
256-
set isSubmitted(v) {
257-
isSubmitted = v;
258-
},
259-
validate() {
260-
return validateSnapshot(getSnapshot());
261-
},
262-
enhance(node) {
263-
$effect(() => {
264-
node.addEventListener("submit", submitHandler);
265-
node.addEventListener("reset", resetHandler);
266-
return () => {
267-
node.removeEventListener("submit", submitHandler);
268-
node.removeEventListener("reset", resetHandler);
269-
};
270-
});
271-
},
272-
};
281+
/**
282+
* Create a FormAPI and set form context
283+
*/
284+
export function useForm<T, E>(options: UseFormOptions<T, E>) {
285+
const [ctx, api] = createForm(options);
286+
setFromContext(ctx);
287+
return api;
273288
}

0 commit comments

Comments
 (0)