formstand 0.10.0 → 0.12.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/CHANGELOG.md +331 -0
- package/dist/index.cjs +61 -15
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +11 -1
- package/dist/index.d.ts +11 -1
- package/dist/index.js +62 -17
- package/dist/index.js.map +1 -1
- package/package.json +5 -1
package/dist/index.d.cts
CHANGED
|
@@ -282,6 +282,7 @@ type FieldArrayFormApi = Readonly<{
|
|
|
282
282
|
arrayInsert(path: string, index: number, item: unknown): void;
|
|
283
283
|
arrayMove(path: string, from: number, to: number): void;
|
|
284
284
|
arraySwap(path: string, a: number, b: number): void;
|
|
285
|
+
validateField?(path: string): FieldValidationResult;
|
|
285
286
|
}>;
|
|
286
287
|
type FieldArrayEntry<TItem> = Readonly<{
|
|
287
288
|
id: string;
|
|
@@ -398,6 +399,15 @@ type NumberFieldProps<F extends FieldFormApi = FieldFormApi> = Readonly<{
|
|
|
398
399
|
placeholder?: string;
|
|
399
400
|
ref?: FieldRef<HTMLInputElement>;
|
|
400
401
|
}>;
|
|
402
|
+
type NumberInputBinding = Readonly<{
|
|
403
|
+
name: string;
|
|
404
|
+
value: string;
|
|
405
|
+
inputMode: "decimal";
|
|
406
|
+
"aria-invalid": true | undefined;
|
|
407
|
+
onChange: (e: ChangeEvent<HTMLInputElement>) => void;
|
|
408
|
+
onBlur: () => void;
|
|
409
|
+
}>;
|
|
410
|
+
declare const useNumberInput: (field: UseFieldReturn<number | null | undefined>) => NumberInputBinding;
|
|
401
411
|
declare const NumberField: <F extends FieldFormApi>({ form, path, label, placeholder, ref, }: NumberFieldProps<F>) => react.JSX.Element;
|
|
402
412
|
type CheckboxFieldProps<F extends FieldFormApi = FieldFormApi> = Readonly<{
|
|
403
413
|
form: F;
|
|
@@ -488,4 +498,4 @@ declare const dateInputProps: <T extends Date | null | undefined>(field: UseFiel
|
|
|
488
498
|
declare const checkboxProps: <T extends boolean | null | undefined>(field: UseFieldReturn<T>) => CheckboxProps;
|
|
489
499
|
declare const selectProps: <T extends string | null | undefined>(field: UseFieldReturn<T>) => SelectProps;
|
|
490
500
|
|
|
491
|
-
export { type BoolMap, type BoundUseField, type BoundUseFieldArray, type BoundUseFlag, type BoundUseSelector, CheckboxField, type CheckboxFieldProps, type CheckboxProps, type CreateFormOptions, DateField, type DateFieldProps, type DateInputProps, type DefaultPathDepth, type ErrorMap, type FieldArrayEntry, type FieldArrayFormApi, type FieldFormApi, type FieldPath, type FieldPathArg, type FieldRef, type FieldSnapshot, type FieldValidationResult, type FieldValue, type FieldsValidationResult, type Form, type FormContextApi, type FormHooks, type FormProviderProps, type FormState, type FormStateApi, type InvalidSubmitHandler, NumberField, type NumberFieldProps, type NumberInputProps, type ParsedDateText, type ParsedNumberText, type PathDepth, type PathSegment, type PathsOf, type PersistHandle, type PersistOptions, type PersistStorage, type ReadonlyStoreApi, type ResetOptions, SelectField, type SelectFieldOption, type SelectFieldProps, type SelectProps, type SettledFieldValidationResult, type SettledFieldsValidationResult, type SettledValidationResult, type SubmitHandler, type SubmitOptions, type SubmitResult, TextField, type TextFieldProps, type TextInputProps, type UseFieldArrayReturn, type UseFieldOptions, type UseFieldReturn, type ValidationMode, type ValidationResult, type ValidationTrigger, checkboxProps, createForm, createFormContext, createFormHooks, dateInputProps, dateToInputText, emptyValueForSchema, flattenIssues, focusField, focusFirstError, getAtPath, hasFieldError, isAsyncRequiredError, numberInputProps, numberToInputText, parseDateText, parseNumberText, parsePath, persistForm, selectProps, setAtPath, shouldValidateOn, textInputProps, useField, useFieldArray, useForm, useFormError, useFormSelector, useFormSelectorShallow, useIsDirty, useIsSubmitting, useIsValid, useSubmitCount, useVariantField, validateAsync, validateSync };
|
|
501
|
+
export { type BoolMap, type BoundUseField, type BoundUseFieldArray, type BoundUseFlag, type BoundUseSelector, CheckboxField, type CheckboxFieldProps, type CheckboxProps, type CreateFormOptions, DateField, type DateFieldProps, type DateInputProps, type DefaultPathDepth, type ErrorMap, type FieldArrayEntry, type FieldArrayFormApi, type FieldFormApi, type FieldPath, type FieldPathArg, type FieldRef, type FieldSnapshot, type FieldValidationResult, type FieldValue, type FieldsValidationResult, type Form, type FormContextApi, type FormHooks, type FormProviderProps, type FormState, type FormStateApi, type InvalidSubmitHandler, NumberField, type NumberFieldProps, type NumberInputBinding, type NumberInputProps, type ParsedDateText, type ParsedNumberText, type PathDepth, type PathSegment, type PathsOf, type PersistHandle, type PersistOptions, type PersistStorage, type ReadonlyStoreApi, type ResetOptions, SelectField, type SelectFieldOption, type SelectFieldProps, type SelectProps, type SettledFieldValidationResult, type SettledFieldsValidationResult, type SettledValidationResult, type SubmitHandler, type SubmitOptions, type SubmitResult, TextField, type TextFieldProps, type TextInputProps, type UseFieldArrayReturn, type UseFieldOptions, type UseFieldReturn, type ValidationMode, type ValidationResult, type ValidationTrigger, checkboxProps, createForm, createFormContext, createFormHooks, dateInputProps, dateToInputText, emptyValueForSchema, flattenIssues, focusField, focusFirstError, getAtPath, hasFieldError, isAsyncRequiredError, numberInputProps, numberToInputText, parseDateText, parseNumberText, parsePath, persistForm, selectProps, setAtPath, shouldValidateOn, textInputProps, useField, useFieldArray, useForm, useFormError, useFormSelector, useFormSelectorShallow, useIsDirty, useIsSubmitting, useIsValid, useNumberInput, useSubmitCount, useVariantField, validateAsync, validateSync };
|
package/dist/index.d.ts
CHANGED
|
@@ -282,6 +282,7 @@ type FieldArrayFormApi = Readonly<{
|
|
|
282
282
|
arrayInsert(path: string, index: number, item: unknown): void;
|
|
283
283
|
arrayMove(path: string, from: number, to: number): void;
|
|
284
284
|
arraySwap(path: string, a: number, b: number): void;
|
|
285
|
+
validateField?(path: string): FieldValidationResult;
|
|
285
286
|
}>;
|
|
286
287
|
type FieldArrayEntry<TItem> = Readonly<{
|
|
287
288
|
id: string;
|
|
@@ -398,6 +399,15 @@ type NumberFieldProps<F extends FieldFormApi = FieldFormApi> = Readonly<{
|
|
|
398
399
|
placeholder?: string;
|
|
399
400
|
ref?: FieldRef<HTMLInputElement>;
|
|
400
401
|
}>;
|
|
402
|
+
type NumberInputBinding = Readonly<{
|
|
403
|
+
name: string;
|
|
404
|
+
value: string;
|
|
405
|
+
inputMode: "decimal";
|
|
406
|
+
"aria-invalid": true | undefined;
|
|
407
|
+
onChange: (e: ChangeEvent<HTMLInputElement>) => void;
|
|
408
|
+
onBlur: () => void;
|
|
409
|
+
}>;
|
|
410
|
+
declare const useNumberInput: (field: UseFieldReturn<number | null | undefined>) => NumberInputBinding;
|
|
401
411
|
declare const NumberField: <F extends FieldFormApi>({ form, path, label, placeholder, ref, }: NumberFieldProps<F>) => react.JSX.Element;
|
|
402
412
|
type CheckboxFieldProps<F extends FieldFormApi = FieldFormApi> = Readonly<{
|
|
403
413
|
form: F;
|
|
@@ -488,4 +498,4 @@ declare const dateInputProps: <T extends Date | null | undefined>(field: UseFiel
|
|
|
488
498
|
declare const checkboxProps: <T extends boolean | null | undefined>(field: UseFieldReturn<T>) => CheckboxProps;
|
|
489
499
|
declare const selectProps: <T extends string | null | undefined>(field: UseFieldReturn<T>) => SelectProps;
|
|
490
500
|
|
|
491
|
-
export { type BoolMap, type BoundUseField, type BoundUseFieldArray, type BoundUseFlag, type BoundUseSelector, CheckboxField, type CheckboxFieldProps, type CheckboxProps, type CreateFormOptions, DateField, type DateFieldProps, type DateInputProps, type DefaultPathDepth, type ErrorMap, type FieldArrayEntry, type FieldArrayFormApi, type FieldFormApi, type FieldPath, type FieldPathArg, type FieldRef, type FieldSnapshot, type FieldValidationResult, type FieldValue, type FieldsValidationResult, type Form, type FormContextApi, type FormHooks, type FormProviderProps, type FormState, type FormStateApi, type InvalidSubmitHandler, NumberField, type NumberFieldProps, type NumberInputProps, type ParsedDateText, type ParsedNumberText, type PathDepth, type PathSegment, type PathsOf, type PersistHandle, type PersistOptions, type PersistStorage, type ReadonlyStoreApi, type ResetOptions, SelectField, type SelectFieldOption, type SelectFieldProps, type SelectProps, type SettledFieldValidationResult, type SettledFieldsValidationResult, type SettledValidationResult, type SubmitHandler, type SubmitOptions, type SubmitResult, TextField, type TextFieldProps, type TextInputProps, type UseFieldArrayReturn, type UseFieldOptions, type UseFieldReturn, type ValidationMode, type ValidationResult, type ValidationTrigger, checkboxProps, createForm, createFormContext, createFormHooks, dateInputProps, dateToInputText, emptyValueForSchema, flattenIssues, focusField, focusFirstError, getAtPath, hasFieldError, isAsyncRequiredError, numberInputProps, numberToInputText, parseDateText, parseNumberText, parsePath, persistForm, selectProps, setAtPath, shouldValidateOn, textInputProps, useField, useFieldArray, useForm, useFormError, useFormSelector, useFormSelectorShallow, useIsDirty, useIsSubmitting, useIsValid, useSubmitCount, useVariantField, validateAsync, validateSync };
|
|
501
|
+
export { type BoolMap, type BoundUseField, type BoundUseFieldArray, type BoundUseFlag, type BoundUseSelector, CheckboxField, type CheckboxFieldProps, type CheckboxProps, type CreateFormOptions, DateField, type DateFieldProps, type DateInputProps, type DefaultPathDepth, type ErrorMap, type FieldArrayEntry, type FieldArrayFormApi, type FieldFormApi, type FieldPath, type FieldPathArg, type FieldRef, type FieldSnapshot, type FieldValidationResult, type FieldValue, type FieldsValidationResult, type Form, type FormContextApi, type FormHooks, type FormProviderProps, type FormState, type FormStateApi, type InvalidSubmitHandler, NumberField, type NumberFieldProps, type NumberInputBinding, type NumberInputProps, type ParsedDateText, type ParsedNumberText, type PathDepth, type PathSegment, type PathsOf, type PersistHandle, type PersistOptions, type PersistStorage, type ReadonlyStoreApi, type ResetOptions, SelectField, type SelectFieldOption, type SelectFieldProps, type SelectProps, type SettledFieldValidationResult, type SettledFieldsValidationResult, type SettledValidationResult, type SubmitHandler, type SubmitOptions, type SubmitResult, TextField, type TextFieldProps, type TextInputProps, type UseFieldArrayReturn, type UseFieldOptions, type UseFieldReturn, type ValidationMode, type ValidationResult, type ValidationTrigger, checkboxProps, createForm, createFormContext, createFormHooks, dateInputProps, dateToInputText, emptyValueForSchema, flattenIssues, focusField, focusFirstError, getAtPath, hasFieldError, isAsyncRequiredError, numberInputProps, numberToInputText, parseDateText, parseNumberText, parsePath, persistForm, selectProps, setAtPath, shouldValidateOn, textInputProps, useField, useFieldArray, useForm, useFormError, useFormSelector, useFormSelectorShallow, useIsDirty, useIsSubmitting, useIsValid, useNumberInput, useSubmitCount, useVariantField, validateAsync, validateSync };
|
package/dist/index.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { createStore } from 'zustand/vanilla';
|
|
2
2
|
import { devtools } from 'zustand/middleware';
|
|
3
3
|
import { z } from 'zod';
|
|
4
|
-
import { useRef, useEffect, createContext, useMemo, useCallback, useContext, useId
|
|
4
|
+
import { useRef, useEffect, createContext, useMemo, useCallback, useState, useContext, useId } from 'react';
|
|
5
5
|
import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
|
|
6
6
|
import { useStore } from 'zustand/react';
|
|
7
7
|
import { useShallow } from 'zustand/react/shallow';
|
|
@@ -1473,25 +1473,52 @@ function useFieldArray(form, pathArg) {
|
|
|
1473
1473
|
const items = slice.items;
|
|
1474
1474
|
const error = slice.error;
|
|
1475
1475
|
const ids = deriveIds(form.store, path, items).ids;
|
|
1476
|
+
const revalidate = useCallback(() => {
|
|
1477
|
+
const state = form.store.getState();
|
|
1478
|
+
if (shouldValidateOn(
|
|
1479
|
+
"change",
|
|
1480
|
+
state.mode,
|
|
1481
|
+
state.reValidateMode,
|
|
1482
|
+
state.submitCount > 0,
|
|
1483
|
+
state.touched[path] ?? false
|
|
1484
|
+
)) {
|
|
1485
|
+
form.validateField?.(path);
|
|
1486
|
+
}
|
|
1487
|
+
}, [form, path]);
|
|
1476
1488
|
const push = useCallback(
|
|
1477
|
-
(item) =>
|
|
1478
|
-
|
|
1489
|
+
(item) => {
|
|
1490
|
+
form.arrayPush(path, item);
|
|
1491
|
+
revalidate();
|
|
1492
|
+
},
|
|
1493
|
+
[form, path, revalidate]
|
|
1479
1494
|
);
|
|
1480
1495
|
const remove = useCallback(
|
|
1481
|
-
(index) =>
|
|
1482
|
-
|
|
1496
|
+
(index) => {
|
|
1497
|
+
form.arrayRemove(path, index);
|
|
1498
|
+
revalidate();
|
|
1499
|
+
},
|
|
1500
|
+
[form, path, revalidate]
|
|
1483
1501
|
);
|
|
1484
1502
|
const insert = useCallback(
|
|
1485
|
-
(index, item) =>
|
|
1486
|
-
|
|
1503
|
+
(index, item) => {
|
|
1504
|
+
form.arrayInsert(path, index, item);
|
|
1505
|
+
revalidate();
|
|
1506
|
+
},
|
|
1507
|
+
[form, path, revalidate]
|
|
1487
1508
|
);
|
|
1488
1509
|
const move = useCallback(
|
|
1489
|
-
(from, to) =>
|
|
1490
|
-
|
|
1510
|
+
(from, to) => {
|
|
1511
|
+
form.arrayMove(path, from, to);
|
|
1512
|
+
revalidate();
|
|
1513
|
+
},
|
|
1514
|
+
[form, path, revalidate]
|
|
1491
1515
|
);
|
|
1492
1516
|
const swap = useCallback(
|
|
1493
|
-
(a, b) =>
|
|
1494
|
-
|
|
1517
|
+
(a, b) => {
|
|
1518
|
+
form.arraySwap(path, a, b);
|
|
1519
|
+
revalidate();
|
|
1520
|
+
},
|
|
1521
|
+
[form, path, revalidate]
|
|
1495
1522
|
);
|
|
1496
1523
|
const fields = useMemo(
|
|
1497
1524
|
() => items.map((value, index) => ({
|
|
@@ -1932,6 +1959,24 @@ var nameMatchesAny = (el, paths) => {
|
|
|
1932
1959
|
const name = el.getAttribute("name");
|
|
1933
1960
|
return name !== null && paths.some((p) => isPathOrChild(name, p));
|
|
1934
1961
|
};
|
|
1962
|
+
var cssQuoted = (value) => `"${value.replace(/[\\"]/g, (ch) => `\\${ch}`).replace(
|
|
1963
|
+
/[\x00-\x1f\x7f]/g,
|
|
1964
|
+
(ch) => `\\${ch.codePointAt(0).toString(16)} `
|
|
1965
|
+
)}"`;
|
|
1966
|
+
var idMatches = (scope, path) => path === "" ? [] : [...scope.querySelectorAll(`[id=${cssQuoted(path)}]`)];
|
|
1967
|
+
var inDomOrder = (els) => [...els].sort(
|
|
1968
|
+
(a, b) => a === b ? 0 : (a.compareDocumentPosition(b) & Node.DOCUMENT_POSITION_FOLLOWING) !== 0 ? -1 : 1
|
|
1969
|
+
);
|
|
1970
|
+
var pathCandidates = (scope, paths) => {
|
|
1971
|
+
const controls = namedControls(scope);
|
|
1972
|
+
const named = controls.filter((el) => nameMatchesAny(el, paths));
|
|
1973
|
+
const focusableControls = controls.filter(isFocusCandidate);
|
|
1974
|
+
const unnamedPaths = paths.filter(
|
|
1975
|
+
(p) => !focusableControls.some((el) => nameMatchesAny(el, [p]))
|
|
1976
|
+
);
|
|
1977
|
+
const byId = unnamedPaths.flatMap((p) => idMatches(scope, p));
|
|
1978
|
+
return inDomOrder([.../* @__PURE__ */ new Set([...named, ...byId])]);
|
|
1979
|
+
};
|
|
1935
1980
|
var focusFirstError = (errors, root) => {
|
|
1936
1981
|
const scope = root ?? document;
|
|
1937
1982
|
const erroredPaths = Object.keys(errors).filter(
|
|
@@ -1939,18 +1984,18 @@ var focusFirstError = (errors, root) => {
|
|
|
1939
1984
|
);
|
|
1940
1985
|
const hasRootError = (errors[""]?.length ?? 0) > 0;
|
|
1941
1986
|
const controls = namedControls(scope);
|
|
1942
|
-
const fieldMatches =
|
|
1987
|
+
const fieldMatches = pathCandidates(scope, erroredPaths).filter(
|
|
1988
|
+
isFocusCandidate
|
|
1989
|
+
);
|
|
1943
1990
|
const rootFallbackApplies = hasRootError && (root !== void 0 || document.querySelectorAll("form").length <= 1);
|
|
1944
1991
|
const candidates = fieldMatches.length > 0 ? fieldMatches : rootFallbackApplies ? controls.filter(isFocusCandidate) : [];
|
|
1945
1992
|
return focusFirstOf(candidates);
|
|
1946
1993
|
};
|
|
1947
1994
|
var focusField = (path, root) => {
|
|
1948
|
-
const
|
|
1949
|
-
return path === "" ? (root !== void 0 || document.querySelectorAll("form").length <= 1) && focusFirstOf(
|
|
1950
|
-
controls.filter((el) => nameMatchesAny(el, [path])).filter(isFocusCandidate)
|
|
1951
|
-
);
|
|
1995
|
+
const scope = root ?? document;
|
|
1996
|
+
return path === "" ? (root !== void 0 || document.querySelectorAll("form").length <= 1) && focusFirstOf(namedControls(scope).filter(isFocusCandidate)) : focusFirstOf(pathCandidates(scope, [path]).filter(isFocusCandidate));
|
|
1952
1997
|
};
|
|
1953
1998
|
|
|
1954
|
-
export { CheckboxField, DateField, NumberField, SelectField, TextField, checkboxProps, createForm, createFormContext, createFormHooks, dateInputProps, dateToInputText, emptyValueForSchema, flattenIssues, focusField, focusFirstError, getAtPath, hasFieldError, isAsyncRequiredError, numberInputProps, numberToInputText, parseDateText, parseNumberText, parsePath, persistForm, selectProps, setAtPath, shouldValidateOn, textInputProps, useField, useFieldArray, useForm, useFormError, useFormSelector, useFormSelectorShallow, useIsDirty, useIsSubmitting, useIsValid, useSubmitCount, useVariantField, validateAsync, validateSync };
|
|
1999
|
+
export { CheckboxField, DateField, NumberField, SelectField, TextField, checkboxProps, createForm, createFormContext, createFormHooks, dateInputProps, dateToInputText, emptyValueForSchema, flattenIssues, focusField, focusFirstError, getAtPath, hasFieldError, isAsyncRequiredError, numberInputProps, numberToInputText, parseDateText, parseNumberText, parsePath, persistForm, selectProps, setAtPath, shouldValidateOn, textInputProps, useField, useFieldArray, useForm, useFormError, useFormSelector, useFormSelectorShallow, useIsDirty, useIsSubmitting, useIsValid, useNumberInput, useSubmitCount, useVariantField, validateAsync, validateSync };
|
|
1955
2000
|
//# sourceMappingURL=index.js.map
|
|
1956
2001
|
//# sourceMappingURL=index.js.map
|