formstand 0.20.0 → 0.21.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/dist/index.js CHANGED
@@ -1,5 +1,5 @@
1
- import { getAtPath, slotAtPath, setAtPath, isPlainObject, hasOwnSlot, valuesEqual, useFormSelectorShallow, isFieldDirty, useFormSelector, parsePath } from './chunk-N7WPXYCU.js';
2
- export { getAtPath, parsePath, setAtPath, useFormSelector, useFormSelectorShallow } from './chunk-N7WPXYCU.js';
1
+ import { getAtPath, slotAtPath, setAtPath, isPlainObject, hasOwnSlot, valuesEqual, useFormSelectorShallow, isFieldDirty, useFormSelector, parsePath } from './chunk-OB23TUKY.js';
2
+ export { getAtPath, parsePath, setAtPath, useFormSelector, useFormSelectorShallow } from './chunk-OB23TUKY.js';
3
3
  import { shouldValidateOn } from './chunk-MQ6262S3.js';
4
4
  export { shouldValidateOn } from './chunk-MQ6262S3.js';
5
5
  import { createStore } from 'zustand/vanilla';
@@ -830,27 +830,25 @@ var createForm = (schema, options) => {
830
830
  };
831
831
  }),
832
832
  updateState: (updater) => {
833
- const valuesBefore = store.getState().values;
834
- store.setState((state) => {
835
- const patch = updater(state);
836
- if (Object.keys(patch).length === 0) return state;
837
- if (patch.errors !== void 0 && patch.errors !== state.errors) {
838
- console.warn(
839
- "[formstand] `errors` is derived from schemaErrors/serverErrors \u2014 patch those channels instead; the direct `errors` patch is ignored."
840
- );
841
- }
842
- const next = { ...state, ...patch };
843
- return {
844
- ...next,
845
- ...errorChannels(state, {
846
- schemaErrors: next.schemaErrors,
847
- serverErrors: next.serverErrors
848
- })
849
- };
850
- });
851
- if (store.getState().values !== valuesBefore) {
833
+ const state = store.getState();
834
+ const patch = updater(state);
835
+ if (Object.keys(patch).length === 0) return;
836
+ if (patch.errors !== void 0 && patch.errors !== state.errors) {
837
+ console.warn(
838
+ "[formstand] `errors` is derived from schemaErrors/serverErrors \u2014 patch those channels instead; the direct `errors` patch is ignored."
839
+ );
840
+ }
841
+ const next = { ...state, ...patch };
842
+ if (next.values !== state.values) {
852
843
  clearArrayOpsUnder(store, "");
853
844
  }
845
+ store.setState(() => ({
846
+ ...next,
847
+ ...errorChannels(state, {
848
+ schemaErrors: next.schemaErrors,
849
+ serverErrors: next.serverErrors
850
+ })
851
+ }));
854
852
  },
855
853
  adoptValues: (values) => {
856
854
  sequences.clear();
@@ -1010,6 +1008,35 @@ var createForm = (schema, options) => {
1010
1008
  });
1011
1009
  };
1012
1010
 
1011
+ // src/core/debounce.ts
1012
+ var createDebouncer = (ms) => {
1013
+ const timer = {
1014
+ current: null
1015
+ };
1016
+ const cancel = () => {
1017
+ if (timer.current !== null) {
1018
+ clearTimeout(timer.current);
1019
+ timer.current = null;
1020
+ }
1021
+ };
1022
+ const schedule = (run) => {
1023
+ cancel();
1024
+ if (ms === 0) {
1025
+ run();
1026
+ return;
1027
+ }
1028
+ timer.current = setTimeout(() => {
1029
+ timer.current = null;
1030
+ run();
1031
+ }, ms);
1032
+ };
1033
+ return Object.freeze({
1034
+ schedule,
1035
+ cancel,
1036
+ pending: () => timer.current !== null
1037
+ });
1038
+ };
1039
+
1013
1040
  // src/core/persist.ts
1014
1041
  var kindOf = (value) => value === null ? "null" : Array.isArray(value) ? "array" : typeof value;
1015
1042
  var conflictsWith = (draft, reference) => {
@@ -1084,28 +1111,13 @@ var persistForm = (form, options) => {
1084
1111
  } catch {
1085
1112
  }
1086
1113
  };
1087
- const timerRef = {
1088
- current: null
1089
- };
1090
- const cancelPending = () => {
1091
- if (timerRef.current !== null) {
1092
- clearTimeout(timerRef.current);
1093
- timerRef.current = null;
1094
- }
1095
- };
1114
+ const writes = createDebouncer(debounceMs);
1115
+ const cancelPending = () => writes.cancel();
1096
1116
  if (apply !== "manual") {
1097
1117
  load();
1098
1118
  }
1099
1119
  const unsubscribe = form.watchValues((values) => {
1100
- cancelPending();
1101
- if (debounceMs === 0) {
1102
- writeDraft(values);
1103
- } else {
1104
- timerRef.current = setTimeout(() => {
1105
- timerRef.current = null;
1106
- writeDraft(values);
1107
- }, debounceMs);
1108
- }
1120
+ writes.schedule(() => writeDraft(values));
1109
1121
  });
1110
1122
  return Object.freeze({
1111
1123
  load,
@@ -1488,28 +1500,24 @@ function useField(form, pathArg, options) {
1488
1500
  return initialValue === null ? { emptyValue: null, clearable: true } : { emptyValue: void 0, clearable: false };
1489
1501
  }, [formSchema, path, initialValue]);
1490
1502
  const debounceMs = options?.debounceMs;
1491
- const debounceTimerRef = useRef(null);
1503
+ const debouncerRef = useRef(null);
1492
1504
  useEffect(() => {
1493
1505
  return () => {
1494
- if (debounceTimerRef.current !== null) {
1495
- clearTimeout(debounceTimerRef.current);
1496
- debounceTimerRef.current = null;
1497
- }
1506
+ debouncerRef.current?.cancel();
1507
+ debouncerRef.current = null;
1498
1508
  };
1499
1509
  }, [form, path, debounceMs]);
1500
1510
  const triggerValidate = useCallback(() => {
1501
1511
  if (debounceMs !== void 0 && debounceMs > 0) {
1502
- if (debounceTimerRef.current !== null) {
1503
- clearTimeout(debounceTimerRef.current);
1504
- }
1512
+ const debouncer = debouncerRef.current ?? createDebouncer(debounceMs);
1513
+ debouncerRef.current = debouncer;
1505
1514
  const scheduled = getAtPath(form.store.getState().values, path);
1506
- debounceTimerRef.current = setTimeout(() => {
1507
- debounceTimerRef.current = null;
1515
+ debouncer.schedule(() => {
1508
1516
  const state = form.store.getState();
1509
1517
  if (state.values === state.initialValues) return;
1510
1518
  if (!Object.is(getAtPath(state.values, path), scheduled)) return;
1511
1519
  void form.validateFieldAsync(path);
1512
- }, debounceMs);
1520
+ });
1513
1521
  return;
1514
1522
  }
1515
1523
  form.validateField(path);