formstand 0.6.0 → 0.8.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 +236 -0
- package/dist/index.cjs +190 -146
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +90 -59
- package/dist/index.d.ts +90 -59
- package/dist/index.js +191 -148
- package/dist/index.js.map +1 -1
- package/package.json +4 -1
package/dist/index.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { createStore } from 'zustand/vanilla';
|
|
2
2
|
import { z } from 'zod';
|
|
3
|
-
import { useRef, useEffect, createContext, useMemo, useCallback,
|
|
3
|
+
import { useRef, useEffect, createContext, useMemo, useCallback, useState, useId, useContext } from 'react';
|
|
4
4
|
import { jsxs, jsx } from 'react/jsx-runtime';
|
|
5
5
|
import { useStore } from 'zustand/react';
|
|
6
6
|
import { useShallow } from 'zustand/react/shallow';
|
|
@@ -57,7 +57,7 @@ var valuesEqual = (a, b) => {
|
|
|
57
57
|
if (isPlainObject(a) && isPlainObject(b)) {
|
|
58
58
|
const aKeys = Object.keys(a);
|
|
59
59
|
const bKeys = Object.keys(b);
|
|
60
|
-
return aKeys.length === bKeys.length && aKeys.every((k) => valuesEqual(a[k], b[k]));
|
|
60
|
+
return aKeys.length === bKeys.length && aKeys.every((k) => Object.hasOwn(b, k) && valuesEqual(a[k], b[k]));
|
|
61
61
|
}
|
|
62
62
|
return false;
|
|
63
63
|
};
|
|
@@ -92,7 +92,7 @@ var readSegment = (obj, segment) => {
|
|
|
92
92
|
if (Array.isArray(obj)) {
|
|
93
93
|
return typeof segment === "number" ? obj[segment] : void 0;
|
|
94
94
|
}
|
|
95
|
-
return isPlainRecord(obj) ? obj[String(segment)] : void 0;
|
|
95
|
+
return isPlainRecord(obj) && Object.hasOwn(obj, String(segment)) ? obj[String(segment)] : void 0;
|
|
96
96
|
};
|
|
97
97
|
var getAtPath = (obj, path) => parsePath(path).reduce(readSegment, obj);
|
|
98
98
|
var slotAtPath = (obj, path) => {
|
|
@@ -135,6 +135,12 @@ var writeSegments = (obj, segments, value) => {
|
|
|
135
135
|
return writeIntoArray(obj, head, rest, value);
|
|
136
136
|
}
|
|
137
137
|
if (isPlainRecord(obj)) {
|
|
138
|
+
if (!isPlainObject(obj)) {
|
|
139
|
+
console.warn(
|
|
140
|
+
`[formstand] cannot write key "${String(head)}" through a non-plain object (Date/Map/Set/class instance); value left unchanged.`
|
|
141
|
+
);
|
|
142
|
+
return obj;
|
|
143
|
+
}
|
|
138
144
|
const key = String(head);
|
|
139
145
|
return { ...obj, [key]: writeSegments(obj[key], rest, value) };
|
|
140
146
|
}
|
|
@@ -668,7 +674,11 @@ var createForm = (schema, options) => {
|
|
|
668
674
|
});
|
|
669
675
|
}
|
|
670
676
|
const merged = stale ? result.errors : store.getState().errors;
|
|
671
|
-
|
|
677
|
+
try {
|
|
678
|
+
onInvalid?.(merged);
|
|
679
|
+
} catch (error) {
|
|
680
|
+
return { kind: "error", error };
|
|
681
|
+
}
|
|
672
682
|
return { kind: "invalid", errors: merged };
|
|
673
683
|
}
|
|
674
684
|
if (!stale) {
|
|
@@ -928,9 +938,13 @@ var createForm = (schema, options) => {
|
|
|
928
938
|
// In-flight state is owned by live passes, never by snapshots: a
|
|
929
939
|
// snapshotted flag has no pass left to clear it (the pass that set
|
|
930
940
|
// it cleared its ORIGINAL entry when it settled), so restoring one
|
|
931
|
-
// would stick it forever.
|
|
941
|
+
// would stick it forever. isSubmitting follows the same rule — a
|
|
942
|
+
// mid-submit snapshot restored later must not disable submit
|
|
943
|
+
// buttons forever, so it reflects the LIVE submit count instead of
|
|
944
|
+
// the snapshotted flag (a live pass's finally still resets it).
|
|
932
945
|
isValidating: emptyBools,
|
|
933
|
-
isValidatingForm: false
|
|
946
|
+
isValidatingForm: false,
|
|
947
|
+
isSubmitting: inFlight.count > 0
|
|
934
948
|
};
|
|
935
949
|
})
|
|
936
950
|
});
|
|
@@ -958,15 +972,17 @@ var useForm = (schema, options) => {
|
|
|
958
972
|
formRef.current = createForm(schema, options);
|
|
959
973
|
}
|
|
960
974
|
const form = formRef.current;
|
|
975
|
+
const mountInitialsRef = useRef(options.initialValues);
|
|
961
976
|
const warnedRef = useRef(false);
|
|
962
977
|
useEffect(() => {
|
|
963
|
-
|
|
978
|
+
const changedInitials = !Object.is(options.initialValues, mountInitialsRef.current) && !valuesEqual(options.initialValues, mountInitialsRef.current);
|
|
979
|
+
if (!warnedRef.current && (form.schema !== schema || changedInitials)) {
|
|
964
980
|
warnedRef.current = true;
|
|
965
981
|
console.warn(
|
|
966
|
-
"[formstand] useForm received a different schema
|
|
982
|
+
"[formstand] useForm received a different schema or initial values after the first render; schema and options changes are ignored for the life of the component. If the schema is defined inline this is harmless (but consider hoisting it to module scope). For initial values that arrive later (e.g. from a fetch), call form.adoptValues(values) or form.reset(values) instead."
|
|
967
983
|
);
|
|
968
984
|
}
|
|
969
|
-
}, [form, schema]);
|
|
985
|
+
}, [form, schema, options.initialValues]);
|
|
970
986
|
return form;
|
|
971
987
|
};
|
|
972
988
|
var createFormContext = () => {
|
|
@@ -983,38 +999,6 @@ var createFormContext = () => {
|
|
|
983
999
|
};
|
|
984
1000
|
return { Provider, useFormContext };
|
|
985
1001
|
};
|
|
986
|
-
function useFormSelector(form, selector) {
|
|
987
|
-
return useStore(form.store, selector);
|
|
988
|
-
}
|
|
989
|
-
function useFormSelectorShallow(form, selector) {
|
|
990
|
-
return useStore(form.store, useShallow(selector));
|
|
991
|
-
}
|
|
992
|
-
var useFormError = (form) => useStore(
|
|
993
|
-
form.store,
|
|
994
|
-
useShallow((state) => state.errors[""])
|
|
995
|
-
);
|
|
996
|
-
function useIsDirty(form, path) {
|
|
997
|
-
return useStore(
|
|
998
|
-
form.store,
|
|
999
|
-
(state) => path === void 0 || path === "" ? isFieldDirty(state.values, state.initialValues) : isFieldDirty(
|
|
1000
|
-
getAtPath(state.values, path),
|
|
1001
|
-
getAtPath(state.initialValues, path)
|
|
1002
|
-
)
|
|
1003
|
-
);
|
|
1004
|
-
}
|
|
1005
|
-
function useIsValid(form, path) {
|
|
1006
|
-
return useStore(form.store, (state) => {
|
|
1007
|
-
for (const k in state.errors) {
|
|
1008
|
-
const errs = state.errors[k];
|
|
1009
|
-
if (errs !== void 0 && errs.length > 0 && (path === void 0 || path === "" || isPathOrChild(k, path))) {
|
|
1010
|
-
return false;
|
|
1011
|
-
}
|
|
1012
|
-
}
|
|
1013
|
-
return true;
|
|
1014
|
-
});
|
|
1015
|
-
}
|
|
1016
|
-
var useIsSubmitting = (form) => useStore(form.store, (state) => state.isSubmitting);
|
|
1017
|
-
var useSubmitCount = (form) => useStore(form.store, (state) => state.submitCount);
|
|
1018
1002
|
function useField(form, pathArg, options) {
|
|
1019
1003
|
const slice = useStore(
|
|
1020
1004
|
form.store,
|
|
@@ -1144,6 +1128,168 @@ function useField(form, pathArg, options) {
|
|
|
1144
1128
|
[slice, emptyValue, setValue, setTouched, setError, clearError, validate, validateAsync2, onBlur]
|
|
1145
1129
|
);
|
|
1146
1130
|
}
|
|
1131
|
+
var EMPTY_ID_STATE = { items: [], ids: [], counter: 0 };
|
|
1132
|
+
var EMPTY_ITEMS = [];
|
|
1133
|
+
var reconcileIds = (prev, nextItems) => {
|
|
1134
|
+
if (prev.items === nextItems) return prev;
|
|
1135
|
+
if (prev.items.length === nextItems.length && prev.items.every((item, i) => Object.is(item, nextItems[i]))) {
|
|
1136
|
+
return prev;
|
|
1137
|
+
}
|
|
1138
|
+
const buckets = prev.items.reduce((acc, item, i) => {
|
|
1139
|
+
const bucket = acc.get(item);
|
|
1140
|
+
if (bucket === void 0) {
|
|
1141
|
+
acc.set(item, [i]);
|
|
1142
|
+
} else {
|
|
1143
|
+
bucket.push(i);
|
|
1144
|
+
}
|
|
1145
|
+
return acc;
|
|
1146
|
+
}, /* @__PURE__ */ new Map());
|
|
1147
|
+
const matchedIds = nextItems.map((item) => {
|
|
1148
|
+
const prevIndex = buckets.get(item)?.shift();
|
|
1149
|
+
return prevIndex === void 0 ? null : prev.ids[prevIndex] ?? null;
|
|
1150
|
+
});
|
|
1151
|
+
const leftoverAt = new Map(
|
|
1152
|
+
[...buckets.values()].flat().flatMap((i) => {
|
|
1153
|
+
const id = prev.ids[i];
|
|
1154
|
+
return id === void 0 ? [] : [[i, id]];
|
|
1155
|
+
})
|
|
1156
|
+
);
|
|
1157
|
+
const reused = matchedIds.map((id, i) => id ?? leftoverAt.get(i) ?? null);
|
|
1158
|
+
const mintCounts = reused.reduce((acc, id) => {
|
|
1159
|
+
const count = acc[acc.length - 1] ?? 0;
|
|
1160
|
+
return [...acc, id === null ? count + 1 : count];
|
|
1161
|
+
}, []);
|
|
1162
|
+
const minted = mintCounts[mintCounts.length - 1] ?? 0;
|
|
1163
|
+
const ids = reused.map(
|
|
1164
|
+
(id, i) => id ?? `__zfa_${prev.counter + (mintCounts[i] ?? 0)}`
|
|
1165
|
+
);
|
|
1166
|
+
return { items: nextItems, ids, counter: prev.counter + minted };
|
|
1167
|
+
};
|
|
1168
|
+
function useFieldArray(form, pathArg) {
|
|
1169
|
+
const path = useStore(
|
|
1170
|
+
form.store,
|
|
1171
|
+
(state) => typeof pathArg === "function" ? pathArg(state) : pathArg
|
|
1172
|
+
);
|
|
1173
|
+
const slice = useStore(
|
|
1174
|
+
form.store,
|
|
1175
|
+
useShallow((state) => {
|
|
1176
|
+
const value = getAtPath(state.values, path);
|
|
1177
|
+
return {
|
|
1178
|
+
items: Array.isArray(value) ? value : EMPTY_ITEMS,
|
|
1179
|
+
error: state.errors[path]
|
|
1180
|
+
};
|
|
1181
|
+
})
|
|
1182
|
+
);
|
|
1183
|
+
const items = slice.items;
|
|
1184
|
+
const error = slice.error;
|
|
1185
|
+
const [idEntry, setIdEntry] = useState({ form, path, state: EMPTY_ID_STATE });
|
|
1186
|
+
const base = idEntry.form === form && idEntry.path === path ? idEntry.state : { ...EMPTY_ID_STATE, counter: idEntry.state.counter };
|
|
1187
|
+
const nextIdState = reconcileIds(base, items);
|
|
1188
|
+
if (idEntry.form !== form || idEntry.path !== path || idEntry.state !== nextIdState) {
|
|
1189
|
+
setIdEntry({ form, path, state: nextIdState });
|
|
1190
|
+
}
|
|
1191
|
+
const ids = nextIdState.ids;
|
|
1192
|
+
const push = useCallback(
|
|
1193
|
+
(item) => form.arrayPush(path, item),
|
|
1194
|
+
[form, path]
|
|
1195
|
+
);
|
|
1196
|
+
const remove = useCallback(
|
|
1197
|
+
(index) => form.arrayRemove(path, index),
|
|
1198
|
+
[form, path]
|
|
1199
|
+
);
|
|
1200
|
+
const insert = useCallback(
|
|
1201
|
+
(index, item) => form.arrayInsert(path, index, item),
|
|
1202
|
+
[form, path]
|
|
1203
|
+
);
|
|
1204
|
+
const move = useCallback(
|
|
1205
|
+
(from, to) => form.arrayMove(path, from, to),
|
|
1206
|
+
[form, path]
|
|
1207
|
+
);
|
|
1208
|
+
const swap = useCallback(
|
|
1209
|
+
(a, b) => form.arraySwap(path, a, b),
|
|
1210
|
+
[form, path]
|
|
1211
|
+
);
|
|
1212
|
+
const fields = useMemo(
|
|
1213
|
+
() => items.map((value, index) => ({
|
|
1214
|
+
id: ids[index] ?? `__zfa_fallback_${index}`,
|
|
1215
|
+
value
|
|
1216
|
+
})),
|
|
1217
|
+
[items, ids]
|
|
1218
|
+
);
|
|
1219
|
+
return useMemo(
|
|
1220
|
+
() => ({
|
|
1221
|
+
fields,
|
|
1222
|
+
items,
|
|
1223
|
+
length: items.length,
|
|
1224
|
+
error,
|
|
1225
|
+
push,
|
|
1226
|
+
remove,
|
|
1227
|
+
insert,
|
|
1228
|
+
move,
|
|
1229
|
+
swap
|
|
1230
|
+
}),
|
|
1231
|
+
[fields, items, error, push, remove, insert, move, swap]
|
|
1232
|
+
);
|
|
1233
|
+
}
|
|
1234
|
+
var useFormError = (form) => useStore(
|
|
1235
|
+
form.store,
|
|
1236
|
+
useShallow((state) => state.errors[""])
|
|
1237
|
+
);
|
|
1238
|
+
function useIsDirty(form, path) {
|
|
1239
|
+
return useStore(
|
|
1240
|
+
form.store,
|
|
1241
|
+
(state) => path === void 0 || path === "" ? isFieldDirty(state.values, state.initialValues) : isFieldDirty(
|
|
1242
|
+
getAtPath(state.values, path),
|
|
1243
|
+
getAtPath(state.initialValues, path)
|
|
1244
|
+
)
|
|
1245
|
+
);
|
|
1246
|
+
}
|
|
1247
|
+
function useIsValid(form, path) {
|
|
1248
|
+
return useStore(form.store, (state) => {
|
|
1249
|
+
for (const k in state.errors) {
|
|
1250
|
+
const errs = state.errors[k];
|
|
1251
|
+
if (errs !== void 0 && errs.length > 0 && (path === void 0 || path === "" || isPathOrChild(k, path))) {
|
|
1252
|
+
return false;
|
|
1253
|
+
}
|
|
1254
|
+
}
|
|
1255
|
+
return true;
|
|
1256
|
+
});
|
|
1257
|
+
}
|
|
1258
|
+
var useIsSubmitting = (form) => useStore(form.store, (state) => state.isSubmitting);
|
|
1259
|
+
var useSubmitCount = (form) => useStore(form.store, (state) => state.submitCount);
|
|
1260
|
+
function useFormSelector(form, selector) {
|
|
1261
|
+
return useStore(form.store, selector);
|
|
1262
|
+
}
|
|
1263
|
+
function useFormSelectorShallow(form, selector) {
|
|
1264
|
+
return useStore(form.store, useShallow(selector));
|
|
1265
|
+
}
|
|
1266
|
+
|
|
1267
|
+
// src/react/createFormHooks.ts
|
|
1268
|
+
var capitalize = (name) => name.length === 0 ? name : name.charAt(0).toUpperCase() + name.slice(1);
|
|
1269
|
+
var createFormHooks = (form, name) => {
|
|
1270
|
+
const structural = form;
|
|
1271
|
+
const useBoundField = (path, options) => useField(structural, path, options);
|
|
1272
|
+
const useBoundFieldArray = (path) => useFieldArray(structural, path);
|
|
1273
|
+
const useBoundSelector = (selector) => useFormSelector(structural, selector);
|
|
1274
|
+
const useBoundSelectorShallow = (selector) => useFormSelectorShallow(structural, selector);
|
|
1275
|
+
const useBoundError = () => useFormError(structural);
|
|
1276
|
+
const useBoundIsDirty = (path) => useIsDirty(structural, path);
|
|
1277
|
+
const useBoundIsValid = (path) => useIsValid(structural, path);
|
|
1278
|
+
const useBoundIsSubmitting = () => useIsSubmitting(structural);
|
|
1279
|
+
const useBoundSubmitCount = () => useSubmitCount(structural);
|
|
1280
|
+
const prefix = capitalize(name ?? "");
|
|
1281
|
+
return {
|
|
1282
|
+
[`use${prefix}Field`]: useBoundField,
|
|
1283
|
+
[`use${prefix}FieldArray`]: useBoundFieldArray,
|
|
1284
|
+
[`use${prefix}Selector`]: useBoundSelector,
|
|
1285
|
+
[`use${prefix}SelectorShallow`]: useBoundSelectorShallow,
|
|
1286
|
+
[`use${prefix}Error`]: useBoundError,
|
|
1287
|
+
[`use${prefix}IsDirty`]: useBoundIsDirty,
|
|
1288
|
+
[`use${prefix}IsValid`]: useBoundIsValid,
|
|
1289
|
+
[`use${prefix}IsSubmitting`]: useBoundIsSubmitting,
|
|
1290
|
+
[`use${prefix}SubmitCount`]: useBoundSubmitCount
|
|
1291
|
+
};
|
|
1292
|
+
};
|
|
1147
1293
|
|
|
1148
1294
|
// src/react/inputProps.ts
|
|
1149
1295
|
var ariaInvalid = (field) => field.error !== void 0 && field.error.length > 0 ? true : void 0;
|
|
@@ -1334,7 +1480,8 @@ var SelectField = ({
|
|
|
1334
1480
|
const id = useId();
|
|
1335
1481
|
const errorId = `${id}-error`;
|
|
1336
1482
|
const field = useField(form, path);
|
|
1337
|
-
const
|
|
1483
|
+
const clearable = field.emptyValue === null;
|
|
1484
|
+
const showEmptyOption = clearable || field.value === void 0 || field.value === null || placeholder !== void 0;
|
|
1338
1485
|
return /* @__PURE__ */ jsxs("div", { className: "zf-field", children: [
|
|
1339
1486
|
label !== void 0 ? /* @__PURE__ */ jsx("label", { htmlFor: id, className: "zf-label", children: label }) : null,
|
|
1340
1487
|
/* @__PURE__ */ jsxs(
|
|
@@ -1345,7 +1492,7 @@ var SelectField = ({
|
|
|
1345
1492
|
...selectProps(field),
|
|
1346
1493
|
"aria-describedby": hasError(field.error) ? errorId : void 0,
|
|
1347
1494
|
children: [
|
|
1348
|
-
showEmptyOption ? /* @__PURE__ */ jsx("option", { value: "", disabled:
|
|
1495
|
+
showEmptyOption ? /* @__PURE__ */ jsx("option", { value: "", disabled: !clearable, children: placeholder ?? "" }) : null,
|
|
1349
1496
|
options.map((opt, index) => (
|
|
1350
1497
|
// Index-qualified: option lists may legitimately repeat a value
|
|
1351
1498
|
// (e.g. differently-labelled aliases), and bare value keys would
|
|
@@ -1398,111 +1545,7 @@ var focusField = (path, root) => {
|
|
|
1398
1545
|
const controls = focusableControls(root ?? document);
|
|
1399
1546
|
return path === "" ? (root !== void 0 || document.querySelectorAll("form").length <= 1) && focusFirstOf(controls) : focusFirstOf(controls.filter((el) => nameMatchesAny(el, [path])));
|
|
1400
1547
|
};
|
|
1401
|
-
var EMPTY_ID_STATE = { items: [], ids: [], counter: 0 };
|
|
1402
|
-
var EMPTY_ITEMS = [];
|
|
1403
|
-
var reconcileIds = (prev, nextItems) => {
|
|
1404
|
-
if (prev.items === nextItems) return prev;
|
|
1405
|
-
if (prev.items.length === nextItems.length && prev.items.every((item, i) => Object.is(item, nextItems[i]))) {
|
|
1406
|
-
return prev;
|
|
1407
|
-
}
|
|
1408
|
-
const buckets = prev.items.reduce((acc, item, i) => {
|
|
1409
|
-
const bucket = acc.get(item);
|
|
1410
|
-
if (bucket === void 0) {
|
|
1411
|
-
acc.set(item, [i]);
|
|
1412
|
-
} else {
|
|
1413
|
-
bucket.push(i);
|
|
1414
|
-
}
|
|
1415
|
-
return acc;
|
|
1416
|
-
}, /* @__PURE__ */ new Map());
|
|
1417
|
-
const matchedIds = nextItems.map((item) => {
|
|
1418
|
-
const prevIndex = buckets.get(item)?.shift();
|
|
1419
|
-
return prevIndex === void 0 ? null : prev.ids[prevIndex] ?? null;
|
|
1420
|
-
});
|
|
1421
|
-
const leftover = [...buckets.values()].flat().sort((a, b) => a - b).map((i) => prev.ids[i]).filter((id) => id !== void 0);
|
|
1422
|
-
const ordinals = matchedIds.reduce((acc, id) => {
|
|
1423
|
-
const count = acc.length === 0 ? 0 : acc[acc.length - 1] ?? 0;
|
|
1424
|
-
acc.push(id === null ? count + 1 : count);
|
|
1425
|
-
return acc;
|
|
1426
|
-
}, []);
|
|
1427
|
-
const unmatched = ordinals.length === 0 ? 0 : ordinals[ordinals.length - 1] ?? 0;
|
|
1428
|
-
const ids = matchedIds.map((id, i) => {
|
|
1429
|
-
if (id !== null) return id;
|
|
1430
|
-
const ordinal = ordinals[i] ?? 0;
|
|
1431
|
-
return leftover[ordinal - 1] ?? `__zfa_${prev.counter + (ordinal - leftover.length)}`;
|
|
1432
|
-
});
|
|
1433
|
-
return {
|
|
1434
|
-
items: nextItems,
|
|
1435
|
-
ids,
|
|
1436
|
-
counter: prev.counter + Math.max(0, unmatched - leftover.length)
|
|
1437
|
-
};
|
|
1438
|
-
};
|
|
1439
|
-
function useFieldArray(form, pathArg) {
|
|
1440
|
-
const path = useStore(
|
|
1441
|
-
form.store,
|
|
1442
|
-
(state) => typeof pathArg === "function" ? pathArg(state) : pathArg
|
|
1443
|
-
);
|
|
1444
|
-
const slice = useStore(
|
|
1445
|
-
form.store,
|
|
1446
|
-
useShallow((state) => {
|
|
1447
|
-
const value = getAtPath(state.values, path);
|
|
1448
|
-
return {
|
|
1449
|
-
items: Array.isArray(value) ? value : EMPTY_ITEMS,
|
|
1450
|
-
error: state.errors[path]
|
|
1451
|
-
};
|
|
1452
|
-
})
|
|
1453
|
-
);
|
|
1454
|
-
const items = slice.items;
|
|
1455
|
-
const error = slice.error;
|
|
1456
|
-
const [idEntry, setIdEntry] = useState({ form, path, state: EMPTY_ID_STATE });
|
|
1457
|
-
const base = idEntry.form === form && idEntry.path === path ? idEntry.state : { ...EMPTY_ID_STATE, counter: idEntry.state.counter };
|
|
1458
|
-
const nextIdState = reconcileIds(base, items);
|
|
1459
|
-
if (idEntry.form !== form || idEntry.path !== path || idEntry.state !== nextIdState) {
|
|
1460
|
-
setIdEntry({ form, path, state: nextIdState });
|
|
1461
|
-
}
|
|
1462
|
-
const ids = nextIdState.ids;
|
|
1463
|
-
const push = useCallback(
|
|
1464
|
-
(item) => form.arrayPush(path, item),
|
|
1465
|
-
[form, path]
|
|
1466
|
-
);
|
|
1467
|
-
const remove = useCallback(
|
|
1468
|
-
(index) => form.arrayRemove(path, index),
|
|
1469
|
-
[form, path]
|
|
1470
|
-
);
|
|
1471
|
-
const insert = useCallback(
|
|
1472
|
-
(index, item) => form.arrayInsert(path, index, item),
|
|
1473
|
-
[form, path]
|
|
1474
|
-
);
|
|
1475
|
-
const move = useCallback(
|
|
1476
|
-
(from, to) => form.arrayMove(path, from, to),
|
|
1477
|
-
[form, path]
|
|
1478
|
-
);
|
|
1479
|
-
const swap = useCallback(
|
|
1480
|
-
(a, b) => form.arraySwap(path, a, b),
|
|
1481
|
-
[form, path]
|
|
1482
|
-
);
|
|
1483
|
-
const fields = useMemo(
|
|
1484
|
-
() => items.map((value, index) => ({
|
|
1485
|
-
id: ids[index] ?? `__zfa_fallback_${index}`,
|
|
1486
|
-
value
|
|
1487
|
-
})),
|
|
1488
|
-
[items, ids]
|
|
1489
|
-
);
|
|
1490
|
-
return useMemo(
|
|
1491
|
-
() => ({
|
|
1492
|
-
fields,
|
|
1493
|
-
items,
|
|
1494
|
-
length: items.length,
|
|
1495
|
-
error,
|
|
1496
|
-
push,
|
|
1497
|
-
remove,
|
|
1498
|
-
insert,
|
|
1499
|
-
move,
|
|
1500
|
-
swap
|
|
1501
|
-
}),
|
|
1502
|
-
[fields, items, error, push, remove, insert, move, swap]
|
|
1503
|
-
);
|
|
1504
|
-
}
|
|
1505
1548
|
|
|
1506
|
-
export { CheckboxField, NumberField, SelectField, TextField, checkboxProps, createForm, createFormContext, emptyValueForSchema, flattenIssues, focusField, focusFirstError, getAtPath, isAsyncRequiredError, numberInputProps, numberToInputText, parseNumberText, parsePath, selectProps, setAtPath, shouldValidateOn, textInputProps, useField, useFieldArray, useForm, useFormError, useFormSelector, useFormSelectorShallow, useIsDirty, useIsSubmitting, useIsValid, useSubmitCount, validateAsync, validateSync };
|
|
1549
|
+
export { CheckboxField, NumberField, SelectField, TextField, checkboxProps, createForm, createFormContext, createFormHooks, emptyValueForSchema, flattenIssues, focusField, focusFirstError, getAtPath, isAsyncRequiredError, numberInputProps, numberToInputText, parseNumberText, parsePath, selectProps, setAtPath, shouldValidateOn, textInputProps, useField, useFieldArray, useForm, useFormError, useFormSelector, useFormSelectorShallow, useIsDirty, useIsSubmitting, useIsValid, useSubmitCount, validateAsync, validateSync };
|
|
1507
1550
|
//# sourceMappingURL=index.js.map
|
|
1508
1551
|
//# sourceMappingURL=index.js.map
|