formstand 0.16.0 → 0.18.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 +173 -0
- package/dist/{createForm-jlzK2lCG.d.cts → createForm-B73p1TgL.d.cts} +17 -6
- package/dist/{createForm-jlzK2lCG.d.ts → createForm-B73p1TgL.d.ts} +17 -6
- package/dist/devtools/index.d.cts +1 -1
- package/dist/devtools/index.d.ts +1 -1
- package/dist/index.cjs +142 -48
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +45 -23
- package/dist/index.d.ts +45 -23
- package/dist/index.js +141 -50
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -276,6 +276,7 @@ var emptyValueForSchema = (schema) => {
|
|
|
276
276
|
};
|
|
277
277
|
return walk(schema, false);
|
|
278
278
|
};
|
|
279
|
+
var isClearableSchema = (schema) => schema instanceof zod.z.ZodOptional || schema instanceof zod.z.ZodNullable || schema instanceof zod.z.ZodDefault || schema instanceof zod.z.ZodPrefault;
|
|
279
280
|
var unwrapForWalk = (s) => {
|
|
280
281
|
if (s instanceof zod.z.ZodOptional || s instanceof zod.z.ZodNullable) {
|
|
281
282
|
return s.unwrap();
|
|
@@ -297,7 +298,7 @@ var schemaHasPath = (schema, path) => {
|
|
|
297
298
|
if (head === void 0) return true;
|
|
298
299
|
if (s instanceof zod.z.ZodObject) {
|
|
299
300
|
const shape = s.shape;
|
|
300
|
-
const child = shape[String(head)];
|
|
301
|
+
const child = Object.hasOwn(shape, String(head)) ? shape[String(head)] : void 0;
|
|
301
302
|
if (child !== void 0) return walk(child, rest, budget - 1);
|
|
302
303
|
const catchall = s.def.catchall;
|
|
303
304
|
return catchall !== void 0 && !(catchall instanceof zod.z.ZodNever);
|
|
@@ -317,7 +318,7 @@ var fieldSchemaAtPath = (schema, path) => parsePath(path).reduce((current, segme
|
|
|
317
318
|
if (current === null || hasChecks(current)) return null;
|
|
318
319
|
if (current instanceof zod.z.ZodObject && typeof segment === "string") {
|
|
319
320
|
const shape = current.shape;
|
|
320
|
-
return shape[segment] ?? null;
|
|
321
|
+
return Object.hasOwn(shape, segment) ? shape[segment] ?? null : null;
|
|
321
322
|
}
|
|
322
323
|
if (current instanceof zod.z.ZodArray && typeof segment === "number") {
|
|
323
324
|
return current.element;
|
|
@@ -722,7 +723,7 @@ var createForm = (schema, options) => {
|
|
|
722
723
|
};
|
|
723
724
|
const applyArrayOp = (path, nextArray, mapper, indexInBounds) => {
|
|
724
725
|
const current = getAtPath(store.getState().values, path);
|
|
725
|
-
if (current !== void 0 && !Array.isArray(current)) {
|
|
726
|
+
if (current !== void 0 && current !== null && !Array.isArray(current)) {
|
|
726
727
|
console.warn(
|
|
727
728
|
`[formstand] array op on "${path}" but the value at that path is not an array (got ${typeof current}). Operation skipped.`
|
|
728
729
|
);
|
|
@@ -831,6 +832,7 @@ var createForm = (schema, options) => {
|
|
|
831
832
|
try {
|
|
832
833
|
await onValid(result.data);
|
|
833
834
|
} catch (error) {
|
|
835
|
+
submitOptions?.onError?.(error);
|
|
834
836
|
return { kind: "error", error };
|
|
835
837
|
}
|
|
836
838
|
return { kind: "valid", data: result.data };
|
|
@@ -938,6 +940,17 @@ var createForm = (schema, options) => {
|
|
|
938
940
|
...state,
|
|
939
941
|
...errorChannels(state, { serverErrors: errors })
|
|
940
942
|
})),
|
|
943
|
+
addErrors: (errors) => store.setState((state) => ({
|
|
944
|
+
...state,
|
|
945
|
+
...errorChannels(state, {
|
|
946
|
+
serverErrors: Object.entries(errors).reduce(
|
|
947
|
+
// Computed keys throughout, so a server field named
|
|
948
|
+
// "__proto__" lands as an own property like everywhere else.
|
|
949
|
+
(acc, [key, list]) => list === void 0 || list.length === 0 ? omitKey(acc, key) : { ...acc, [key]: list },
|
|
950
|
+
state.serverErrors
|
|
951
|
+
)
|
|
952
|
+
})
|
|
953
|
+
})),
|
|
941
954
|
clearErrors: (path) => store.setState((state) => {
|
|
942
955
|
const scrub = (map) => path === void 0 ? emptyErrors : omitScope(map, [path]);
|
|
943
956
|
return {
|
|
@@ -1077,7 +1090,14 @@ var createForm = (schema, options) => {
|
|
|
1077
1090
|
),
|
|
1078
1091
|
handleSubmit: (onValid, onInvalid, opts) => async (event) => {
|
|
1079
1092
|
event?.preventDefault();
|
|
1080
|
-
|
|
1093
|
+
const result = await submit(onValid, onInvalid, opts);
|
|
1094
|
+
if (result.kind === "error" && opts?.onError === void 0 && process.env.NODE_ENV !== "production") {
|
|
1095
|
+
console.warn(
|
|
1096
|
+
"[formstand] submit handler threw and nothing observed it \u2014 the form shows no feedback. Pass { onError } to handleSubmit (or setError inside your handler):",
|
|
1097
|
+
result.error
|
|
1098
|
+
);
|
|
1099
|
+
}
|
|
1100
|
+
return result;
|
|
1081
1101
|
},
|
|
1082
1102
|
diff: () => {
|
|
1083
1103
|
const state = store.getState();
|
|
@@ -1178,13 +1198,16 @@ var persistForm = (form, options) => {
|
|
|
1178
1198
|
return void 0;
|
|
1179
1199
|
}
|
|
1180
1200
|
};
|
|
1181
|
-
const
|
|
1201
|
+
const load = () => {
|
|
1182
1202
|
try {
|
|
1183
1203
|
const raw = storage === null ? null : storage.getItem(options.key);
|
|
1184
1204
|
if (raw === null) return false;
|
|
1185
1205
|
const parsed = JSON.parse(raw);
|
|
1186
1206
|
const versioned = options.version !== void 0 && typeof parsed === "object" && parsed !== null && "__v" in parsed;
|
|
1187
1207
|
if (options.version !== void 0 && !versioned) return false;
|
|
1208
|
+
if (options.version === void 0 && typeof parsed === "object" && parsed !== null && Object.hasOwn(parsed, "__v") && Object.hasOwn(parsed, "values")) {
|
|
1209
|
+
return false;
|
|
1210
|
+
}
|
|
1188
1211
|
const wrapper = parsed;
|
|
1189
1212
|
if (versioned && wrapper.__v !== options.version) return false;
|
|
1190
1213
|
if (versioned && wrapper.values === void 0) return false;
|
|
@@ -1220,7 +1243,7 @@ var persistForm = (form, options) => {
|
|
|
1220
1243
|
}
|
|
1221
1244
|
};
|
|
1222
1245
|
if (apply !== "manual") {
|
|
1223
|
-
|
|
1246
|
+
load();
|
|
1224
1247
|
}
|
|
1225
1248
|
const unsubscribe = form.watchValues((values) => {
|
|
1226
1249
|
cancelPending();
|
|
@@ -1234,7 +1257,7 @@ var persistForm = (form, options) => {
|
|
|
1234
1257
|
}
|
|
1235
1258
|
});
|
|
1236
1259
|
return Object.freeze({
|
|
1237
|
-
|
|
1260
|
+
load,
|
|
1238
1261
|
clear: () => {
|
|
1239
1262
|
cancelPending();
|
|
1240
1263
|
try {
|
|
@@ -1248,6 +1271,33 @@ var persistForm = (form, options) => {
|
|
|
1248
1271
|
}
|
|
1249
1272
|
});
|
|
1250
1273
|
};
|
|
1274
|
+
var usePersistForm = (form, options) => {
|
|
1275
|
+
const inner = react.useRef(null);
|
|
1276
|
+
const latestOptions = react.useRef(options);
|
|
1277
|
+
react.useEffect(() => {
|
|
1278
|
+
latestOptions.current = options;
|
|
1279
|
+
});
|
|
1280
|
+
const key = options.key;
|
|
1281
|
+
react.useEffect(() => {
|
|
1282
|
+
const handle = persistForm(form, latestOptions.current);
|
|
1283
|
+
inner.current = handle;
|
|
1284
|
+
return () => {
|
|
1285
|
+
inner.current = null;
|
|
1286
|
+
handle.dispose();
|
|
1287
|
+
};
|
|
1288
|
+
}, [form, key]);
|
|
1289
|
+
return react.useMemo(
|
|
1290
|
+
() => ({
|
|
1291
|
+
load: () => inner.current?.load() ?? false,
|
|
1292
|
+
clear: () => inner.current?.clear(),
|
|
1293
|
+
// dispose stops THIS component's watching early; the effect cleanup
|
|
1294
|
+
// still runs its own dispose harmlessly (persistForm's dispose is
|
|
1295
|
+
// idempotent by construction — it only cancels and unsubscribes).
|
|
1296
|
+
dispose: () => inner.current?.dispose()
|
|
1297
|
+
}),
|
|
1298
|
+
[]
|
|
1299
|
+
);
|
|
1300
|
+
};
|
|
1251
1301
|
var useForm = (schema, options) => {
|
|
1252
1302
|
const formRef = react.useRef(null);
|
|
1253
1303
|
if (formRef.current === null) {
|
|
@@ -1302,12 +1352,17 @@ function useField(form, pathArg, options) {
|
|
|
1302
1352
|
const path = slice.path;
|
|
1303
1353
|
const formSchema = form.schema;
|
|
1304
1354
|
const initialValue = slice.initialValue;
|
|
1305
|
-
const emptyValue = react.useMemo(() => {
|
|
1355
|
+
const { emptyValue, clearable } = react.useMemo(() => {
|
|
1306
1356
|
if (formSchema !== void 0) {
|
|
1307
1357
|
const sub = fieldSchemaAtPath(formSchema, path);
|
|
1308
|
-
if (sub !== null)
|
|
1358
|
+
if (sub !== null) {
|
|
1359
|
+
return {
|
|
1360
|
+
emptyValue: emptyValueForSchema(sub),
|
|
1361
|
+
clearable: isClearableSchema(sub)
|
|
1362
|
+
};
|
|
1363
|
+
}
|
|
1309
1364
|
}
|
|
1310
|
-
return initialValue === null ? null : void 0;
|
|
1365
|
+
return initialValue === null ? { emptyValue: null, clearable: true } : { emptyValue: void 0, clearable: false };
|
|
1311
1366
|
}, [formSchema, path, initialValue]);
|
|
1312
1367
|
const debounceMs = options?.debounceMs;
|
|
1313
1368
|
const debounceTimerRef = react.useRef(null);
|
|
@@ -1324,9 +1379,13 @@ function useField(form, pathArg, options) {
|
|
|
1324
1379
|
if (debounceTimerRef.current !== null) {
|
|
1325
1380
|
clearTimeout(debounceTimerRef.current);
|
|
1326
1381
|
}
|
|
1382
|
+
const scheduled = getAtPath(form.store.getState().values, path);
|
|
1327
1383
|
debounceTimerRef.current = setTimeout(() => {
|
|
1328
|
-
void form.validateFieldAsync(path);
|
|
1329
1384
|
debounceTimerRef.current = null;
|
|
1385
|
+
const state = form.store.getState();
|
|
1386
|
+
if (state.values === state.initialValues) return;
|
|
1387
|
+
if (!Object.is(getAtPath(state.values, path), scheduled)) return;
|
|
1388
|
+
void form.validateFieldAsync(path);
|
|
1330
1389
|
}, debounceMs);
|
|
1331
1390
|
return;
|
|
1332
1391
|
}
|
|
@@ -1389,6 +1448,7 @@ function useField(form, pathArg, options) {
|
|
|
1389
1448
|
value: slice.value,
|
|
1390
1449
|
initialValue: slice.initialValue,
|
|
1391
1450
|
emptyValue,
|
|
1451
|
+
clearable,
|
|
1392
1452
|
error: slice.error,
|
|
1393
1453
|
// `?.[0]` covers both the undefined channel and an empty array.
|
|
1394
1454
|
firstError: slice.error?.[0],
|
|
@@ -1403,7 +1463,7 @@ function useField(form, pathArg, options) {
|
|
|
1403
1463
|
validateAsync: validateAsync2,
|
|
1404
1464
|
onBlur
|
|
1405
1465
|
}),
|
|
1406
|
-
[slice, emptyValue, setValue, setTouched, setError, clearError, validate, validateAsync2, onBlur]
|
|
1466
|
+
[slice, emptyValue, clearable, setValue, setTouched, setError, clearError, validate, validateAsync2, onBlur]
|
|
1407
1467
|
);
|
|
1408
1468
|
}
|
|
1409
1469
|
|
|
@@ -1587,25 +1647,64 @@ function useFieldArray(form, pathArg) {
|
|
|
1587
1647
|
})),
|
|
1588
1648
|
[items, ids]
|
|
1589
1649
|
);
|
|
1650
|
+
const setError = react.useCallback(
|
|
1651
|
+
// Same string-shorthand normalization as useField.setError, so custom
|
|
1652
|
+
// implementations typed for readonly string[] never receive a bare
|
|
1653
|
+
// string.
|
|
1654
|
+
(errors) => form.setError?.(path, typeof errors === "string" ? [errors] : errors),
|
|
1655
|
+
[form, path]
|
|
1656
|
+
);
|
|
1657
|
+
const clearError = react.useCallback(() => form.clearErrors?.(path), [form, path]);
|
|
1590
1658
|
return react.useMemo(
|
|
1591
1659
|
() => ({
|
|
1660
|
+
path,
|
|
1592
1661
|
fields,
|
|
1593
1662
|
items,
|
|
1594
1663
|
length: items.length,
|
|
1595
1664
|
error,
|
|
1665
|
+
firstError: error?.[0],
|
|
1666
|
+
setError,
|
|
1667
|
+
clearError,
|
|
1596
1668
|
push,
|
|
1597
1669
|
remove,
|
|
1598
1670
|
insert,
|
|
1599
1671
|
move,
|
|
1600
1672
|
swap
|
|
1601
1673
|
}),
|
|
1602
|
-
[fields, items, error, push, remove, insert, move, swap]
|
|
1674
|
+
[path, fields, items, error, setError, clearError, push, remove, insert, move, swap]
|
|
1603
1675
|
);
|
|
1604
1676
|
}
|
|
1605
1677
|
var useFormError = (form) => react$1.useStore(
|
|
1606
1678
|
form.store,
|
|
1607
1679
|
shallow.useShallow((state) => state.errors[""])
|
|
1608
1680
|
);
|
|
1681
|
+
function useFormValues(form) {
|
|
1682
|
+
return react$1.useStore(form.store, (state) => state.values);
|
|
1683
|
+
}
|
|
1684
|
+
|
|
1685
|
+
// src/react/useFields.ts
|
|
1686
|
+
function useFields(form, paths) {
|
|
1687
|
+
const fields = paths.map(
|
|
1688
|
+
(path) => (
|
|
1689
|
+
// eslint-disable-next-line react-hooks/rules-of-hooks -- a fixed hook count by the stable-arity contract above; each element must be a REAL UseFieldReturn so it spreads into the prop builders
|
|
1690
|
+
useField(form, path)
|
|
1691
|
+
)
|
|
1692
|
+
);
|
|
1693
|
+
const merged = [...new Set(fields.flatMap((field) => field.error ?? []))];
|
|
1694
|
+
return {
|
|
1695
|
+
fields,
|
|
1696
|
+
error: merged.length > 0 ? merged : void 0,
|
|
1697
|
+
firstError: merged[0],
|
|
1698
|
+
touched: fields.some((field) => field.touched),
|
|
1699
|
+
dirty: fields.some((field) => field.dirty),
|
|
1700
|
+
isValidating: fields.some((field) => field.isValidating),
|
|
1701
|
+
onBlur: () => {
|
|
1702
|
+
fields.forEach((field) => {
|
|
1703
|
+
field.onBlur();
|
|
1704
|
+
});
|
|
1705
|
+
}
|
|
1706
|
+
};
|
|
1707
|
+
}
|
|
1609
1708
|
function useIsDirty(form, path) {
|
|
1610
1709
|
return react$1.useStore(
|
|
1611
1710
|
form.store,
|
|
@@ -1626,6 +1725,19 @@ function useIsValid(form, path) {
|
|
|
1626
1725
|
return true;
|
|
1627
1726
|
});
|
|
1628
1727
|
}
|
|
1728
|
+
function useIsValidating(form, path) {
|
|
1729
|
+
return react$1.useStore(form.store, (state) => {
|
|
1730
|
+
if (path === void 0 || path === "") {
|
|
1731
|
+
if (state.isValidatingForm) return true;
|
|
1732
|
+
}
|
|
1733
|
+
for (const k in state.isValidating) {
|
|
1734
|
+
if (state.isValidating[k] === true && (path === void 0 || path === "" || isPathOrChild(k, path))) {
|
|
1735
|
+
return true;
|
|
1736
|
+
}
|
|
1737
|
+
}
|
|
1738
|
+
return false;
|
|
1739
|
+
});
|
|
1740
|
+
}
|
|
1629
1741
|
var useIsSubmitting = (form) => react$1.useStore(form.store, (state) => state.isSubmitting);
|
|
1630
1742
|
var useSubmitCount = (form) => react$1.useStore(form.store, (state) => state.submitCount);
|
|
1631
1743
|
function useFormSelector(form, selector) {
|
|
@@ -1651,7 +1763,13 @@ var createFormHooks = (form, name) => {
|
|
|
1651
1763
|
const useBoundError = () => useFormError(structural);
|
|
1652
1764
|
const useBoundIsDirty = (path) => useIsDirty(structural, path);
|
|
1653
1765
|
const useBoundIsValid = (path) => useIsValid(structural, path);
|
|
1766
|
+
const useBoundIsValidating = (path) => useIsValidating(structural, path);
|
|
1654
1767
|
const useBoundIsSubmitting = () => useIsSubmitting(structural);
|
|
1768
|
+
const useBoundValues = () => useFormValues(structural);
|
|
1769
|
+
const useBoundFields = (paths) => useFields(
|
|
1770
|
+
structural,
|
|
1771
|
+
paths
|
|
1772
|
+
);
|
|
1655
1773
|
const useBoundSubmitCount = () => useSubmitCount(structural);
|
|
1656
1774
|
const prefix = capitalize(name ?? "");
|
|
1657
1775
|
return {
|
|
@@ -1663,37 +1781,13 @@ var createFormHooks = (form, name) => {
|
|
|
1663
1781
|
[`use${prefix}Error`]: useBoundError,
|
|
1664
1782
|
[`use${prefix}IsDirty`]: useBoundIsDirty,
|
|
1665
1783
|
[`use${prefix}IsValid`]: useBoundIsValid,
|
|
1784
|
+
[`use${prefix}IsValidating`]: useBoundIsValidating,
|
|
1666
1785
|
[`use${prefix}IsSubmitting`]: useBoundIsSubmitting,
|
|
1667
|
-
[`use${prefix}SubmitCount`]: useBoundSubmitCount
|
|
1786
|
+
[`use${prefix}SubmitCount`]: useBoundSubmitCount,
|
|
1787
|
+
[`use${prefix}Values`]: useBoundValues,
|
|
1788
|
+
[`use${prefix}Fields`]: useBoundFields
|
|
1668
1789
|
};
|
|
1669
1790
|
};
|
|
1670
|
-
function useFormValues(form) {
|
|
1671
|
-
return react$1.useStore(form.store, (state) => state.values);
|
|
1672
|
-
}
|
|
1673
|
-
|
|
1674
|
-
// src/react/useFields.ts
|
|
1675
|
-
function useFields(form, paths) {
|
|
1676
|
-
const fields = paths.map(
|
|
1677
|
-
(path) => (
|
|
1678
|
-
// eslint-disable-next-line react-hooks/rules-of-hooks -- a fixed hook count by the stable-arity contract above; each element must be a REAL UseFieldReturn so it spreads into the prop builders
|
|
1679
|
-
useField(form, path)
|
|
1680
|
-
)
|
|
1681
|
-
);
|
|
1682
|
-
const merged = [...new Set(fields.flatMap((field) => field.error ?? []))];
|
|
1683
|
-
return {
|
|
1684
|
-
fields,
|
|
1685
|
-
error: merged.length > 0 ? merged : void 0,
|
|
1686
|
-
firstError: merged[0],
|
|
1687
|
-
touched: fields.some((field) => field.touched),
|
|
1688
|
-
dirty: fields.some((field) => field.dirty),
|
|
1689
|
-
isValidating: fields.some((field) => field.isValidating),
|
|
1690
|
-
onBlur: () => {
|
|
1691
|
-
fields.forEach((field) => {
|
|
1692
|
-
field.onBlur();
|
|
1693
|
-
});
|
|
1694
|
-
}
|
|
1695
|
-
};
|
|
1696
|
-
}
|
|
1697
1791
|
|
|
1698
1792
|
// src/react/inputProps.ts
|
|
1699
1793
|
var hasFieldError = (error) => error !== void 0 && error.length > 0;
|
|
@@ -1710,9 +1804,7 @@ var textInputProps = (field) => ({
|
|
|
1710
1804
|
"aria-invalid": ariaInvalid(field),
|
|
1711
1805
|
onChange: (e) => {
|
|
1712
1806
|
const text = e.target.value;
|
|
1713
|
-
field.setValue(
|
|
1714
|
-
text === "" && field.emptyValue === null ? null : text
|
|
1715
|
-
);
|
|
1807
|
+
field.setValue(text === "" && field.clearable ? field.emptyValue : text);
|
|
1716
1808
|
},
|
|
1717
1809
|
onBlur: field.onBlur
|
|
1718
1810
|
});
|
|
@@ -1723,6 +1815,7 @@ var numberInputProps = (field) => ({
|
|
|
1723
1815
|
"aria-invalid": ariaInvalid(field),
|
|
1724
1816
|
onChange: (e) => {
|
|
1725
1817
|
const parsed = parseNumberText(e.target.value);
|
|
1818
|
+
if (parsed.kind === "invalid") return;
|
|
1726
1819
|
field.setValue(
|
|
1727
1820
|
parsed.kind === "number" ? parsed.value : field.emptyValue
|
|
1728
1821
|
);
|
|
@@ -1785,9 +1878,7 @@ var selectProps = (field) => ({
|
|
|
1785
1878
|
"aria-invalid": ariaInvalid(field),
|
|
1786
1879
|
onChange: (e) => {
|
|
1787
1880
|
const v = e.target.value;
|
|
1788
|
-
field.setValue(
|
|
1789
|
-
v === "" && field.emptyValue === null ? null : v
|
|
1790
|
-
);
|
|
1881
|
+
field.setValue(v === "" && field.clearable ? field.emptyValue : v);
|
|
1791
1882
|
},
|
|
1792
1883
|
onBlur: field.onBlur
|
|
1793
1884
|
});
|
|
@@ -1994,7 +2085,7 @@ var SelectField = ({
|
|
|
1994
2085
|
const field = useField(form, path);
|
|
1995
2086
|
const a11y = useFieldA11y(field.error);
|
|
1996
2087
|
const select = selectProps(field);
|
|
1997
|
-
const clearable = field.
|
|
2088
|
+
const clearable = field.clearable;
|
|
1998
2089
|
const hasExplicitEmptyOption = options.some((opt) => opt.value === "");
|
|
1999
2090
|
const showEmptyOption = !hasExplicitEmptyOption && (clearable || select.value === "" || placeholder !== void 0);
|
|
2000
2091
|
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
@@ -2101,6 +2192,7 @@ exports.focusFirstError = focusFirstError;
|
|
|
2101
2192
|
exports.getAtPath = getAtPath;
|
|
2102
2193
|
exports.hasFieldError = hasFieldError;
|
|
2103
2194
|
exports.isAsyncRequiredError = isAsyncRequiredError;
|
|
2195
|
+
exports.isClearableSchema = isClearableSchema;
|
|
2104
2196
|
exports.numberInputProps = numberInputProps;
|
|
2105
2197
|
exports.numberToInputText = numberToInputText;
|
|
2106
2198
|
exports.parseDateText = parseDateText;
|
|
@@ -2122,7 +2214,9 @@ exports.useFormValues = useFormValues;
|
|
|
2122
2214
|
exports.useIsDirty = useIsDirty;
|
|
2123
2215
|
exports.useIsSubmitting = useIsSubmitting;
|
|
2124
2216
|
exports.useIsValid = useIsValid;
|
|
2217
|
+
exports.useIsValidating = useIsValidating;
|
|
2125
2218
|
exports.useNumberInput = useNumberInput;
|
|
2219
|
+
exports.usePersistForm = usePersistForm;
|
|
2126
2220
|
exports.useSubmitCount = useSubmitCount;
|
|
2127
2221
|
exports.useVariantField = useVariantField;
|
|
2128
2222
|
exports.validateAsync = validateAsync;
|