@classytic/pos-ui 0.1.0 → 1.2.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.
Files changed (87) hide show
  1. package/LICENSE +75 -0
  2. package/dist/components/CartSidebar.d.ts +56 -0
  3. package/dist/components/CartSidebar.js +10 -9
  4. package/dist/components/PosTopBar.d.ts +19 -0
  5. package/dist/components/PosTopBar.js +4 -4
  6. package/dist/components/PrinterSettingsDialog.d.ts +8 -0
  7. package/dist/components/PrinterSettingsDialog.js +506 -20
  8. package/dist/components/ReceiptDeliveryDialog.d.ts +11 -0
  9. package/dist/components/ReceiptDeliveryDialog.js +98 -0
  10. package/dist/components/ReceiptReprintDialog.d.ts +10 -0
  11. package/dist/components/ReceiptReprintDialog.js +49 -22
  12. package/dist/components/index.d.ts +6 -0
  13. package/dist/components/index.js +7 -0
  14. package/dist/dashboard/components/CustomerLookupDialog.js +108 -90
  15. package/dist/dashboard/components/CustomerQuickAddDialog.js +3 -1
  16. package/dist/dashboard/components/DeliveryPanel.js +134 -0
  17. package/dist/dashboard/components/ProductCard.js +17 -7
  18. package/dist/dashboard/components/ProductsPanel.js +4 -4
  19. package/dist/dashboard/components/SplitPaymentPanel.js +5 -5
  20. package/dist/dashboard/components/VariantSelectorDialog.js +53 -11
  21. package/dist/dashboard/components/cart/AddChargeDialog.js +3 -2
  22. package/dist/dashboard/components/cart/CartItems.js +5 -5
  23. package/dist/dashboard/components/cart/CartSummary.js +6 -6
  24. package/dist/dashboard/components/cart/CustomerSection.js +3 -3
  25. package/dist/dashboard/components/cart/DiscountSection.js +4 -3
  26. package/dist/dashboard/components/cart/PointsRedemptionSection.js +5 -4
  27. package/dist/dashboard/pos.types.d.ts +32 -0
  28. package/dist/hardware/agent-adapter.js +127 -0
  29. package/dist/hardware/agent-pairing.d.ts +18 -0
  30. package/dist/hardware/agent-pairing.js +63 -0
  31. package/dist/hardware/context.d.ts +1 -5
  32. package/dist/hardware/index.d.ts +4 -3
  33. package/dist/hardware/index.js +3 -2
  34. package/dist/hardware/ports.d.ts +21 -4
  35. package/dist/hardware/tauri-adapter.d.ts +0 -1
  36. package/dist/hardware/tauri-adapter.js +19 -5
  37. package/dist/hardware/web-adapter.d.ts +22 -7
  38. package/dist/hardware/web-adapter.js +56 -14
  39. package/dist/hooks/branch-scoped-key.js +64 -0
  40. package/dist/hooks/index.d.ts +6 -0
  41. package/dist/hooks/index.js +7 -0
  42. package/dist/hooks/sale-attempt.js +62 -0
  43. package/dist/hooks/useManagerAuth.js +9 -1
  44. package/dist/hooks/usePosCart.d.ts +55 -0
  45. package/dist/hooks/usePosCart.js +224 -117
  46. package/dist/hooks/usePosCustomer.d.ts +31 -0
  47. package/dist/hooks/usePosCustomer.js +32 -78
  48. package/dist/hooks/usePosDelivery.d.ts +28 -0
  49. package/dist/hooks/usePosDelivery.js +133 -0
  50. package/dist/hooks/usePosMultiOrder.d.ts +22 -0
  51. package/dist/hooks/usePosMultiOrder.js +14 -4
  52. package/dist/hooks/usePosPayment.d.ts +22 -0
  53. package/dist/lib/delivery-payload.js +83 -0
  54. package/dist/lib/money.js +96 -23
  55. package/dist/node_modules/react-hook-form/dist/index.esm.js +468 -332
  56. package/dist/runtime/auth-port.d.ts +1 -5
  57. package/dist/runtime/branch-port.d.ts +1 -5
  58. package/dist/runtime/config.d.ts +43 -6
  59. package/dist/runtime/config.js +18 -1
  60. package/dist/runtime/index.d.ts +2 -2
  61. package/dist/runtime/index.js +2 -2
  62. package/dist/screens/OrderHistoryDrawer.d.ts +8 -0
  63. package/dist/screens/OrderHistoryDrawer.js +15 -15
  64. package/dist/screens/ParkedOrdersDrawer.d.ts +12 -0
  65. package/dist/screens/ParkedOrdersDrawer.js +3 -3
  66. package/dist/screens/PaymentScreen.d.ts +4 -0
  67. package/dist/screens/PaymentScreen.js +194 -33
  68. package/dist/screens/ProductScreen.d.ts +4 -0
  69. package/dist/screens/ProductScreen.js +13 -10
  70. package/dist/screens/ReceiptScreen.d.ts +4 -0
  71. package/dist/screens/ReceiptScreen.js +96 -72
  72. package/dist/screens/ShiftCloseScreen.d.ts +4 -0
  73. package/dist/screens/ShiftCloseScreen.js +18 -15
  74. package/dist/screens/ShiftOpenScreen.d.ts +4 -0
  75. package/dist/screens/ShiftOpenScreen.js +75 -19
  76. package/dist/screens/index.d.ts +8 -0
  77. package/dist/screens/index.js +9 -0
  78. package/dist/shell/index.d.ts +2 -0
  79. package/dist/shell/pos-shell.d.ts +41 -8
  80. package/dist/shell/pos-shell.js +25 -18
  81. package/dist/state/index.d.ts +3 -0
  82. package/dist/state/index.js +4 -0
  83. package/dist/state/pos-context.d.ts +13 -0
  84. package/dist/state/pos-state.d.ts +49 -0
  85. package/dist/state/pos-state.js +6 -7
  86. package/dist/utils/pos-helpers.js +137 -34
  87. package/package.json +27 -7
@@ -2,23 +2,21 @@ import React from "react";
2
2
 
3
3
  //#region node_modules/react-hook-form/dist/index.esm.mjs
4
4
  var isCheckBoxInput = (element) => element.type === "checkbox";
5
+ var isFileInput = (element) => element.type === "file";
5
6
  var isDateObject = (value) => value instanceof Date;
6
7
  var isNullOrUndefined = (value) => value == null;
7
8
  const isObjectType = (value) => typeof value === "object";
8
9
  var isObject = (value) => !isNullOrUndefined(value) && !Array.isArray(value) && isObjectType(value) && !isDateObject(value);
9
- var getEventValue = (event) => isObject(event) && event.target ? isCheckBoxInput(event.target) ? event.target.checked : event.target.value : event;
10
+ var getEventValue = (event) => isObject(event) && event.target ? isCheckBoxInput(event.target) ? event.target.checked : isFileInput(event.target) ? event.target.files : event.target.value : event;
10
11
  var isNameInFieldArray = (names, name) => name.split(".").some((part, index, arr) => !isNaN(Number(part)) && names.has(arr.slice(0, index).join(".")));
11
- var isPlainObject = (tempObject) => {
12
- const prototypeCopy = tempObject.constructor && tempObject.constructor.prototype;
13
- return isObject(prototypeCopy) && prototypeCopy.hasOwnProperty("isPrototypeOf");
14
- };
15
12
  var isWeb = typeof window !== "undefined" && typeof window.HTMLElement !== "undefined" && typeof document !== "undefined";
16
13
  function cloneObject(data) {
14
+ if (data === null || typeof data !== "object") return data;
17
15
  if (data instanceof Date) return new Date(data);
18
16
  const isFileListInstance = typeof FileList !== "undefined" && data instanceof FileList;
19
17
  if (isWeb && (data instanceof Blob || isFileListInstance)) return data;
20
18
  const isArray = Array.isArray(data);
21
- if (!isArray && !(isObject(data) && isPlainObject(data))) return data;
19
+ if (!isArray && data.constructor !== Object) return data;
22
20
  const copy = isArray ? [] : Object.create(Object.getPrototypeOf(data));
23
21
  for (const key in data) if (Object.prototype.hasOwnProperty.call(data, key)) copy[key] = cloneObject(data[key]);
24
22
  return copy;
@@ -103,15 +101,9 @@ var getProxyFormState = (formState, control, localProxyFormState, isRoot = true)
103
101
  return result;
104
102
  };
105
103
  const useIsomorphicLayoutEffect = isWeb ? React.useLayoutEffect : React.useEffect;
106
- var isString = (value) => typeof value === "string";
107
- var generateWatchOutput = (names, _names, formValues, isGlobal, defaultValue) => {
108
- if (isString(names)) {
109
- isGlobal && _names.watch.add(names);
110
- return get(formValues, names, defaultValue);
111
- }
112
- if (Array.isArray(names)) return names.map((fieldName) => (isGlobal && _names.watch.add(fieldName), get(formValues, fieldName)));
113
- isGlobal && (_names.watchAll = true);
114
- return formValues;
104
+ var isPlainObject = (tempObject) => {
105
+ const prototypeCopy = tempObject.constructor && tempObject.constructor.prototype;
106
+ return isObject(prototypeCopy) && prototypeCopy.hasOwnProperty("isPrototypeOf");
115
107
  };
116
108
  var isPrimitive = (value) => isNullOrUndefined(value) || !isObjectType(value);
117
109
  const isEmptyObjectWithCustomPrototype = (object, keys) => keys.length === 0 && !Array.isArray(object) && !isPlainObject(object);
@@ -142,195 +134,32 @@ function deepEqual(object1, object2, visited = /* @__PURE__ */ new WeakMap()) {
142
134
  }
143
135
  return true;
144
136
  }
145
- const HookFormContext = React.createContext(null);
146
- HookFormContext.displayName = "HookFormContext";
147
- var appendErrors = (name, validateAllFieldCriteria, errors, type, message) => validateAllFieldCriteria ? {
148
- ...errors[name],
149
- types: {
150
- ...errors[name] && errors[name].types ? errors[name].types : {},
151
- [type]: message || true
152
- }
153
- } : {};
154
- var compact = (value) => Array.isArray(value) ? value.filter(Boolean) : [];
155
- var convertToArrayPayload = (value) => Array.isArray(value) ? value : [value];
156
- var createSubject = () => {
157
- let _observers = [];
158
- const next = (value) => {
159
- for (const observer of _observers) observer.next && observer.next(value);
160
- };
161
- const subscribe = (observer) => {
162
- _observers.push(observer);
163
- return { unsubscribe: () => {
164
- _observers = _observers.filter((o) => o !== observer);
165
- } };
166
- };
167
- const unsubscribe = () => {
168
- _observers = [];
169
- };
137
+ function useResyncOnReconnect() {
138
+ const _connected = React.useRef(false);
139
+ const _prevValue = React.useRef(void 0);
170
140
  return {
171
- get observers() {
172
- return _observers;
173
- },
174
- next,
175
- subscribe,
176
- unsubscribe
141
+ resyncIfNeeded: React.useCallback((enabled, getCurrentValue, setValue) => {
142
+ if (enabled && _connected.current) {
143
+ const currentValue = getCurrentValue();
144
+ if (!deepEqual(_prevValue.current, currentValue)) setValue(currentValue);
145
+ }
146
+ _connected.current = true;
147
+ }, []),
148
+ snapshot: React.useCallback((enabled, getCurrentValue) => {
149
+ if (enabled) _prevValue.current = cloneObject(getCurrentValue());
150
+ }, [])
177
151
  };
178
- };
179
- function extractFormValues(fieldsState, formValues) {
180
- const values = {};
181
- for (const key in fieldsState) if (fieldsState.hasOwnProperty(key)) {
182
- const fieldState = fieldsState[key];
183
- const fieldValue = formValues[key];
184
- if (fieldState && isObject(fieldState) && fieldValue) {
185
- const nestedFieldsState = extractFormValues(fieldState, fieldValue);
186
- if (isObject(nestedFieldsState)) values[key] = nestedFieldsState;
187
- } else if (fieldsState[key]) values[key] = fieldValue;
188
- }
189
- return values;
190
- }
191
- var isEmptyObject = (value) => isObject(value) && !Object.keys(value).length;
192
- var isFileInput = (element) => element.type === "file";
193
- var isHTMLElement = (value) => {
194
- if (!isWeb) return false;
195
- const owner = value ? value.ownerDocument : 0;
196
- return value instanceof (owner && owner.defaultView ? owner.defaultView.HTMLElement : HTMLElement);
197
- };
198
- var isMultipleSelect = (element) => element.type === `select-multiple`;
199
- var isRadioInput = (element) => element.type === "radio";
200
- var isRadioOrCheckbox = (ref) => isRadioInput(ref) || isCheckBoxInput(ref);
201
- var live = (ref) => isHTMLElement(ref) && ref.isConnected;
202
- function baseGet(object, updatePath) {
203
- const length = updatePath.slice(0, -1).length;
204
- let index = 0;
205
- while (index < length) {
206
- if (isNullOrUndefined(object)) {
207
- object = void 0;
208
- break;
209
- }
210
- object = object[updatePath[index]];
211
- index++;
212
- }
213
- return object;
214
- }
215
- function isEmptyArray(obj) {
216
- for (const key in obj) if (obj.hasOwnProperty(key) && !isUndefined(obj[key])) return false;
217
- return true;
218
152
  }
219
- function unset(object, path) {
220
- if (isString(path) && Object.prototype.hasOwnProperty.call(object, path)) {
221
- delete object[path];
222
- return object;
223
- }
224
- const paths = Array.isArray(path) ? path : isKey(path) ? [path] : stringToPath(path);
225
- const childObject = paths.length === 1 ? object : baseGet(object, paths);
226
- const index = paths.length - 1;
227
- const key = paths[index];
228
- if (childObject) delete childObject[key];
229
- if (index !== 0 && (isObject(childObject) && isEmptyObject(childObject) || Array.isArray(childObject) && isEmptyArray(childObject))) unset(object, paths.slice(0, -1));
230
- return object;
231
- }
232
- var objectHasFunction = (data) => {
233
- for (const key in data) if (isFunction(data[key])) return true;
234
- return false;
235
- };
236
- function isTraversable(value) {
237
- return Array.isArray(value) || isObject(value) && !objectHasFunction(value);
238
- }
239
- function markFieldsDirty(data, fields = {}) {
240
- for (const key in data) {
241
- const value = data[key];
242
- if (isTraversable(value)) {
243
- fields[key] = Array.isArray(value) ? [] : {};
244
- markFieldsDirty(value, fields[key]);
245
- } else if (!isUndefined(value)) fields[key] = true;
246
- }
247
- return fields;
248
- }
249
- function pruneDirtyFields(value) {
250
- if (value === false) return;
251
- if (value === true) return true;
252
- if (Array.isArray(value)) {
253
- const result = value.map((value) => pruneDirtyFields(value));
254
- return result.some((value) => value !== void 0) ? result : void 0;
255
- }
256
- if (isObject(value)) {
257
- const result = {};
258
- for (const key in value) {
259
- const pruned = pruneDirtyFields(value[key]);
260
- if (!isUndefined(pruned)) result[key] = pruned;
261
- }
262
- return Object.keys(result).length ? result : void 0;
263
- }
264
- }
265
- function getDirtyFields(data, formValues, dirtyFieldsFromValues) {
266
- if (!dirtyFieldsFromValues) dirtyFieldsFromValues = markFieldsDirty(formValues);
267
- for (const key in data) {
268
- const value = data[key];
269
- if (isTraversable(value)) if (isUndefined(formValues) || isPrimitive(dirtyFieldsFromValues[key])) dirtyFieldsFromValues[key] = markFieldsDirty(value, Array.isArray(value) ? [] : {});
270
- else getDirtyFields(value, isNullOrUndefined(formValues) ? {} : formValues[key], dirtyFieldsFromValues[key]);
271
- else {
272
- const formValue = formValues[key];
273
- dirtyFieldsFromValues[key] = !deepEqual(value, formValue);
274
- }
275
- }
276
- return pruneDirtyFields(dirtyFieldsFromValues) || {};
277
- }
278
- const defaultResult = {
279
- value: false,
280
- isValid: false
281
- };
282
- const validResult = {
283
- value: true,
284
- isValid: true
285
- };
286
- var getCheckboxValue = (options) => {
287
- if (Array.isArray(options)) {
288
- if (options.length > 1) {
289
- const values = options.filter((option) => option && option.checked && !option.disabled).map((option) => option.value);
290
- return {
291
- value: values,
292
- isValid: !!values.length
293
- };
294
- }
295
- return options[0].checked && !options[0].disabled ? options[0].attributes && !isUndefined(options[0].attributes.value) ? isUndefined(options[0].value) || options[0].value === "" ? validResult : {
296
- value: options[0].value,
297
- isValid: true
298
- } : validResult : defaultResult;
299
- }
300
- return defaultResult;
301
- };
302
- var getFieldValueAs = (value, { valueAsNumber, valueAsDate, setValueAs }) => isUndefined(value) ? value : valueAsNumber ? value === "" ? NaN : value ? +value : value : valueAsDate && isString(value) ? new Date(value) : setValueAs ? setValueAs(value) : value;
303
- const defaultReturn = {
304
- isValid: false,
305
- value: null
306
- };
307
- var getRadioValue = (options) => Array.isArray(options) ? options.reduce((previous, option) => option && option.checked && !option.disabled ? {
308
- isValid: true,
309
- value: option.value
310
- } : previous, defaultReturn) : defaultReturn;
311
- function getFieldValue(_f) {
312
- const ref = _f.ref;
313
- if (isFileInput(ref)) return ref.files;
314
- if (isRadioInput(ref)) return getRadioValue(_f.refs).value;
315
- if (isMultipleSelect(ref)) return [...ref.selectedOptions].map(({ value }) => value);
316
- if (isCheckBoxInput(ref)) return getCheckboxValue(_f.refs).value;
317
- return getFieldValueAs(isUndefined(ref.value) ? _f.ref.value : ref.value, _f);
318
- }
319
- var getResolverOptions = (fieldsNames, _fields, criteriaMode, shouldUseNativeValidation) => {
320
- const fields = {};
321
- for (const name of fieldsNames) {
322
- const field = get(_fields, name);
323
- field && set(fields, name, field._f);
153
+ var isString = (value) => typeof value === "string";
154
+ var generateWatchOutput = (names, _names, formValues, isGlobal, defaultValue) => {
155
+ if (isString(names)) {
156
+ isGlobal && _names.watch.add(names);
157
+ return get(formValues, names, defaultValue);
324
158
  }
325
- return {
326
- criteriaMode,
327
- names: [...fieldsNames],
328
- fields,
329
- shouldUseNativeValidation
330
- };
159
+ if (Array.isArray(names)) return names.map((fieldName) => (isGlobal && _names.watch.add(fieldName), get(formValues, fieldName)));
160
+ isGlobal && (_names.watchAll = true);
161
+ return formValues;
331
162
  };
332
- var isRegex = (value) => value instanceof RegExp;
333
- var getRuleValue = (rule) => isUndefined(rule) ? rule : isRegex(rule) ? rule.source : isObject(rule) ? isRegex(rule.value) ? rule.value.source : rule.value : rule;
334
163
  var getValidationModes = (mode) => ({
335
164
  isOnSubmit: !mode || mode === VALIDATION_MODE.onSubmit,
336
165
  isOnBlur: mode === VALIDATION_MODE.onBlur,
@@ -338,16 +167,6 @@ var getValidationModes = (mode) => ({
338
167
  isOnAll: mode === VALIDATION_MODE.all,
339
168
  isOnTouch: mode === VALIDATION_MODE.onTouched
340
169
  });
341
- const ASYNC_FUNCTION = "AsyncFunction";
342
- var hasPromiseValidation = (fieldReference) => {
343
- if (!fieldReference || !fieldReference.validate) return false;
344
- if (isFunction(fieldReference.validate)) return fieldReference.validate.constructor.name === ASYNC_FUNCTION;
345
- if (isObject(fieldReference.validate)) {
346
- for (const key in fieldReference.validate) if (fieldReference.validate[key].constructor.name === ASYNC_FUNCTION) return true;
347
- }
348
- return false;
349
- };
350
- var hasValidation = (options) => options.mount && (options.required || options.min || options.max || options.maxLength || options.minLength || options.pattern || options.validate);
351
170
  var isWatched = (name, _names, isBlurEvent) => {
352
171
  if (isBlurEvent) return false;
353
172
  if (_names.watchAll || _names.watch.has(name)) return true;
@@ -356,58 +175,20 @@ var isWatched = (name, _names, isBlurEvent) => {
356
175
  };
357
176
  const iterateFieldsByAction = (fields, action, fieldsNames, abortEarly) => {
358
177
  for (const key of fieldsNames || Object.keys(fields)) {
359
- const field = get(fields, key);
178
+ if (key === "_f") continue;
179
+ const field = fieldsNames ? get(fields, key) : fields[key];
360
180
  if (field) {
361
- const { _f, ...currentField } = field;
181
+ const { _f } = field;
362
182
  if (_f) {
363
183
  if (_f.refs && _f.refs[0] && action(_f.refs[0], key) && !abortEarly) return true;
364
184
  else if (_f.ref && action(_f.ref, _f.name) && !abortEarly) return true;
365
- else if (iterateFieldsByAction(currentField, action)) break;
366
- } else if (isObject(currentField)) {
367
- if (iterateFieldsByAction(currentField, action)) break;
185
+ else if (iterateFieldsByAction(field, action)) break;
186
+ } else if (isObject(field) || Array.isArray(field)) {
187
+ if (iterateFieldsByAction(field, action)) break;
368
188
  }
369
189
  }
370
190
  }
371
191
  };
372
- function schemaErrorLookup(errors, _fields, name) {
373
- const error = get(errors, name);
374
- if (error || isKey(name)) return {
375
- error,
376
- name
377
- };
378
- const names = name.split(".");
379
- while (names.length) {
380
- const fieldName = names.join(".");
381
- const field = get(_fields, fieldName);
382
- const foundError = get(errors, fieldName);
383
- if (field && !Array.isArray(field) && name !== fieldName) return { name };
384
- if (foundError && foundError.type) return {
385
- name: fieldName,
386
- error: foundError
387
- };
388
- if (foundError && foundError.root && foundError.root.type) return {
389
- name: `${fieldName}.root`,
390
- error: foundError.root
391
- };
392
- names.pop();
393
- }
394
- return { name };
395
- }
396
- var shouldRenderFormState = (formStateData, _proxyFormState, updateFormState, isRoot) => {
397
- updateFormState(formStateData);
398
- const { name, ...formState } = formStateData;
399
- const keys = Object.keys(formState);
400
- return !keys.length || isRoot && keys.length >= Object.keys(_proxyFormState).length || keys.find((key) => _proxyFormState[key] === (!isRoot || VALIDATION_MODE.all));
401
- };
402
- var shouldSubscribeByName = (name, signalName, exact) => !name || !signalName || name === signalName || convertToArrayPayload(name).some((currentName) => currentName && (exact ? currentName === signalName : currentName.startsWith(signalName) || signalName.startsWith(currentName)));
403
- var skipValidation = (isBlurEvent, isTouched, isSubmitted, reValidateMode, mode) => {
404
- if (mode.isOnAll) return false;
405
- else if (!isSubmitted && mode.isOnTouch) return !(isTouched || isBlurEvent);
406
- else if (isSubmitted ? reValidateMode.isOnBlur : mode.isOnBlur) return !isBlurEvent;
407
- else if (isSubmitted ? reValidateMode.isOnChange : mode.isOnChange) return isBlurEvent;
408
- return true;
409
- };
410
- var unsetEmptyArray = (ref, name) => !compact(get(ref, name)).length && unset(ref, name);
411
192
  var updateFieldArrayRootError = (errors, error, name) => {
412
193
  const existingErrors = get(errors, name);
413
194
  const fieldArrayErrors = Array.isArray(existingErrors) ? existingErrors : [];
@@ -415,6 +196,54 @@ var updateFieldArrayRootError = (errors, error, name) => {
415
196
  set(errors, name, fieldArrayErrors);
416
197
  return errors;
417
198
  };
199
+ var isEmptyObject = (value) => isObject(value) && !Object.keys(value).length;
200
+ var isHTMLElement = (value) => {
201
+ if (!isWeb) return false;
202
+ const owner = value ? value.ownerDocument : 0;
203
+ return value instanceof (owner && owner.defaultView ? owner.defaultView.HTMLElement : HTMLElement);
204
+ };
205
+ var isRadioInput = (element) => element.type === "radio";
206
+ var isRegex = (value) => value instanceof RegExp;
207
+ var appendErrors = (name, validateAllFieldCriteria, errors, type, message) => validateAllFieldCriteria ? {
208
+ ...errors[name],
209
+ types: {
210
+ ...errors[name] && errors[name].types ? errors[name].types : {},
211
+ [type]: message || true
212
+ }
213
+ } : {};
214
+ const defaultResult = {
215
+ value: false,
216
+ isValid: false
217
+ };
218
+ const validResult = {
219
+ value: true,
220
+ isValid: true
221
+ };
222
+ var getCheckboxValue = (options) => {
223
+ if (!Array.isArray(options)) return defaultResult;
224
+ if (options.length > 1) {
225
+ const values = options.filter((option) => option && option.checked && !option.disabled).map((option) => option.value);
226
+ return {
227
+ value: values,
228
+ isValid: !!values.length
229
+ };
230
+ }
231
+ const option = options[0];
232
+ if (!option || !option.checked || option.disabled) return defaultResult;
233
+ if (!option.attributes || !("value" in option.attributes)) return validResult;
234
+ return isUndefined(option.value) || option.value === "" ? validResult : {
235
+ value: option.value,
236
+ isValid: true
237
+ };
238
+ };
239
+ const defaultReturn = {
240
+ isValid: false,
241
+ value: null
242
+ };
243
+ var getRadioValue = (options) => Array.isArray(options) ? options.reduce((previous, option) => option && option.checked && !option.disabled ? {
244
+ isValid: true,
245
+ value: option.value
246
+ } : previous, defaultReturn) : defaultReturn;
418
247
  function getValidateError(result, ref, type = "validate") {
419
248
  if (isString(result) || Array.isArray(result) && result.every(isString) || isBoolean(result) && !result) return {
420
249
  type,
@@ -477,7 +306,7 @@ var validateField = async (field, disabledFieldNames, formValues, validateAllFie
477
306
  let exceedMin;
478
307
  const maxOutput = getValueAndMessage(max);
479
308
  const minOutput = getValueAndMessage(min);
480
- if (!isNullOrUndefined(inputValue) && !isNaN(inputValue)) {
309
+ if (!isNullOrUndefined(inputValue) && !isDateObject(inputValue) && !isNaN(inputValue)) {
481
310
  const valueNumber = ref.valueAsNumber || (inputValue ? +inputValue : inputValue);
482
311
  if (!isNullOrUndefined(maxOutput.value)) exceedMax = valueNumber > maxOutput.value;
483
312
  if (!isNullOrUndefined(minOutput.value)) exceedMin = valueNumber < minOutput.value;
@@ -561,15 +390,239 @@ var validateField = async (field, disabledFieldNames, formValues, validateAllFie
561
390
  }
562
391
  }
563
392
  }
564
- setCustomValidity(true);
393
+ const fieldError = error[name];
394
+ setCustomValidity(fieldError ? fieldError.message : true);
565
395
  return error;
566
396
  };
397
+ var convertToArrayPayload = (value) => Array.isArray(value) ? value : [value];
398
+ var compact = (value) => Array.isArray(value) ? value.filter(Boolean) : [];
399
+ function baseGet(object, updatePath) {
400
+ const length = updatePath.length - 1;
401
+ let index = 0;
402
+ while (index < length) {
403
+ if (isNullOrUndefined(object)) {
404
+ object = void 0;
405
+ break;
406
+ }
407
+ object = object[updatePath[index]];
408
+ index++;
409
+ }
410
+ return object;
411
+ }
412
+ function isEmptyArray(obj) {
413
+ for (const key in obj) if (obj.hasOwnProperty(key) && !isUndefined(obj[key])) return false;
414
+ return true;
415
+ }
416
+ function unset(object, path) {
417
+ if (isString(path) && Object.prototype.hasOwnProperty.call(object, path)) {
418
+ delete object[path];
419
+ return object;
420
+ }
421
+ const paths = Array.isArray(path) ? path : isKey(path) ? [path] : stringToPath(path);
422
+ if (paths.some((segment) => PROTOTYPE_KEYWORDS.includes(String(segment)))) return object;
423
+ const childObject = paths.length === 1 ? object : baseGet(object, paths);
424
+ const index = paths.length - 1;
425
+ const key = paths[index];
426
+ if (childObject) delete childObject[key];
427
+ if (index !== 0 && (isObject(childObject) && isEmptyObject(childObject) || Array.isArray(childObject) && isEmptyArray(childObject))) unset(object, paths.slice(0, -1));
428
+ return object;
429
+ }
430
+ const HookFormContext = React.createContext(null);
431
+ HookFormContext.displayName = "HookFormContext";
432
+ var createSubject = () => {
433
+ let _observers = [];
434
+ const next = (value) => {
435
+ for (const observer of _observers) observer.next && observer.next(value);
436
+ };
437
+ const subscribe = (observer) => {
438
+ _observers.push(observer);
439
+ return { unsubscribe: () => {
440
+ _observers = _observers.filter((o) => o !== observer);
441
+ } };
442
+ };
443
+ const unsubscribe = () => {
444
+ _observers = [];
445
+ };
446
+ return {
447
+ get observers() {
448
+ return _observers;
449
+ },
450
+ next,
451
+ subscribe,
452
+ unsubscribe
453
+ };
454
+ };
455
+ function extractFormValues(fieldsState, formValues) {
456
+ const values = {};
457
+ for (const key in fieldsState) if (fieldsState.hasOwnProperty(key)) {
458
+ const fieldState = fieldsState[key];
459
+ const fieldValue = formValues[key];
460
+ if (fieldState && isObject(fieldState) && fieldValue) {
461
+ const nestedFieldsState = extractFormValues(fieldState, fieldValue);
462
+ if (isObject(nestedFieldsState)) values[key] = nestedFieldsState;
463
+ } else if (fieldsState[key]) values[key] = fieldValue;
464
+ }
465
+ return values;
466
+ }
467
+ const hasOwn = (value, key) => value !== null && isObjectType(value) && Object.prototype.hasOwnProperty.call(value, key);
468
+ var has = (object, path) => {
469
+ if (!path) return false;
470
+ let result = object;
471
+ for (const key of isKey(path) ? [path] : stringToPath(path)) {
472
+ if (!hasOwn(result, key)) return hasOwn(object, path);
473
+ result = result[key];
474
+ }
475
+ return true;
476
+ };
477
+ var isMultipleSelect = (element) => element.type === `select-multiple`;
478
+ var isRadioOrCheckbox = (ref) => isRadioInput(ref) || isCheckBoxInput(ref);
479
+ var live = (ref) => isHTMLElement(ref) && ref.isConnected;
480
+ function isDirtyContainer(value) {
481
+ return Array.isArray(value) || isObject(value);
482
+ }
483
+ function collectDirtyFieldNames(dirtyTree, cachedDirtyFields, prefix = "", names = []) {
484
+ for (const key in dirtyTree) {
485
+ const path = prefix ? `${prefix}.${key}` : key;
486
+ const value = dirtyTree[key];
487
+ if (isDirtyContainer(value) && isDirtyContainer(get(cachedDirtyFields, path))) collectDirtyFieldNames(value, cachedDirtyFields, path, names);
488
+ else names.push(path);
489
+ }
490
+ return names;
491
+ }
492
+ var objectHasFunction = (data) => {
493
+ for (const key in data) if (isFunction(data[key])) return true;
494
+ return false;
495
+ };
496
+ function isTraversable(value) {
497
+ return Array.isArray(value) || isObject(value) && !objectHasFunction(value);
498
+ }
499
+ function isRegisteredLeaf(fieldRef) {
500
+ return !!(fieldRef && "_f" in fieldRef);
501
+ }
502
+ function isEmptyDirtyContainer(value) {
503
+ return Array.isArray(value) ? !value.some((item) => !isUndefined(item)) : !Object.keys(value).length;
504
+ }
505
+ function clearDirtyField(container, key) {
506
+ if (Array.isArray(container)) container[key] = void 0;
507
+ else delete container[key];
508
+ }
509
+ function markFieldsDirty(data, fields = {}, fieldRefs) {
510
+ for (const key in data) {
511
+ const value = data[key];
512
+ const fieldRef = fieldRefs && fieldRefs[key];
513
+ if (isTraversable(value) && (!Array.isArray(value) || !isRegisteredLeaf(fieldRef))) {
514
+ fields[key] = Array.isArray(value) ? [] : {};
515
+ markFieldsDirty(value, fields[key], fieldRef);
516
+ if (isEmptyDirtyContainer(fields[key])) clearDirtyField(fields, key);
517
+ } else if (!isUndefined(value)) fields[key] = true;
518
+ }
519
+ return fields;
520
+ }
521
+ function getDirtyFields(data, formValues, dirtyFieldsFromValues, fieldRefs) {
522
+ if (!dirtyFieldsFromValues) dirtyFieldsFromValues = markFieldsDirty(formValues, {}, fieldRefs);
523
+ for (const key in data) {
524
+ const value = data[key];
525
+ const fieldRef = fieldRefs && fieldRefs[key];
526
+ if (isTraversable(value) && (!Array.isArray(value) || !isRegisteredLeaf(fieldRef))) {
527
+ if (isUndefined(formValues) || isPrimitive(dirtyFieldsFromValues[key])) dirtyFieldsFromValues[key] = markFieldsDirty(value, Array.isArray(value) ? [] : {}, fieldRef);
528
+ else getDirtyFields(value, isNullOrUndefined(formValues) ? {} : formValues[key], dirtyFieldsFromValues[key], fieldRef);
529
+ if (isEmptyDirtyContainer(dirtyFieldsFromValues[key])) clearDirtyField(dirtyFieldsFromValues, key);
530
+ } else if (deepEqual(value, formValues[key])) clearDirtyField(dirtyFieldsFromValues, key);
531
+ else dirtyFieldsFromValues[key] = true;
532
+ }
533
+ return dirtyFieldsFromValues;
534
+ }
535
+ var getFieldArrayItemNames = (names, name) => {
536
+ const segments = name.split(".");
537
+ const matches = [];
538
+ let prefix = segments[0];
539
+ for (let i = 1; i < segments.length; prefix += "." + segments[i++]) if (!isNaN(+segments[i]) && names.has(prefix)) matches.push(`${prefix}.${segments[i]}`);
540
+ return matches;
541
+ };
542
+ var getFieldValueAs = (value, { valueAsNumber, valueAsDate, setValueAs }) => isUndefined(value) ? value : valueAsNumber ? value === "" ? NaN : value ? +value : value : valueAsDate && isString(value) ? new Date(value) : setValueAs ? setValueAs(value) : value;
543
+ function getFieldValue(_f) {
544
+ const ref = _f.ref;
545
+ if (isFileInput(ref)) return ref.files;
546
+ if (isRadioInput(ref)) return getRadioValue(_f.refs).value;
547
+ if (isMultipleSelect(ref)) return [...ref.selectedOptions].map(({ value }) => value);
548
+ if (isCheckBoxInput(ref)) return getCheckboxValue(_f.refs).value;
549
+ return getFieldValueAs(ref.value, _f);
550
+ }
551
+ var getResolverOptions = (fieldsNames, _fields, criteriaMode, shouldUseNativeValidation) => {
552
+ const fields = {};
553
+ for (const name of fieldsNames) {
554
+ const field = get(_fields, name);
555
+ field && set(fields, name, field._f);
556
+ }
557
+ return {
558
+ criteriaMode,
559
+ names: [...fieldsNames],
560
+ fields,
561
+ shouldUseNativeValidation
562
+ };
563
+ };
564
+ var getRuleValue = (rule) => isUndefined(rule) ? rule : isRegex(rule) ? rule.source : isObject(rule) ? isRegex(rule.value) ? rule.value.source : rule.value : rule;
565
+ const ASYNC_FUNCTION = "AsyncFunction";
566
+ var hasPromiseValidation = (fieldReference) => {
567
+ if (!fieldReference || !fieldReference.validate) return false;
568
+ if (isFunction(fieldReference.validate)) return fieldReference.validate.constructor.name === ASYNC_FUNCTION;
569
+ if (isObject(fieldReference.validate)) {
570
+ for (const key in fieldReference.validate) if (fieldReference.validate[key].constructor.name === ASYNC_FUNCTION) return true;
571
+ }
572
+ return false;
573
+ };
574
+ var hasValidation = (options) => options.mount && (options.required || !isUndefined(options.required) && options.required !== false || !isUndefined(options.min) || !isUndefined(options.max) || !isUndefined(options.maxLength) || !isUndefined(options.minLength) || options.pattern || options.validate);
575
+ function schemaErrorLookup(errors, _fields, name) {
576
+ const error = get(errors, name);
577
+ if (error || isKey(name)) return {
578
+ error,
579
+ name
580
+ };
581
+ const names = name.split(".");
582
+ while (names.length) {
583
+ const fieldName = names.join(".");
584
+ const field = get(_fields, fieldName);
585
+ const foundError = get(errors, fieldName);
586
+ if (field && !Array.isArray(field) && name !== fieldName) return { name };
587
+ if (foundError && foundError.type) return {
588
+ name: fieldName,
589
+ error: foundError
590
+ };
591
+ if (foundError && foundError.root && foundError.root.type) return {
592
+ name: `${fieldName}.root`,
593
+ error: foundError.root
594
+ };
595
+ names.pop();
596
+ }
597
+ return { name };
598
+ }
599
+ var shouldRenderFormState = (formStateData, _proxyFormState, updateFormState, isRoot) => {
600
+ updateFormState(formStateData);
601
+ const keys = Object.keys(formStateData).filter((key) => key !== "name");
602
+ return !keys.length || isRoot && keys.length >= Object.keys(_proxyFormState).length || keys.find((key) => _proxyFormState[key] === (!isRoot || VALIDATION_MODE.all));
603
+ };
604
+ var shouldSubscribeByName = (name, signalName, exact) => !name || !signalName || name === signalName || convertToArrayPayload(name).some((currentName) => currentName && (exact ? currentName === signalName || currentName.startsWith(signalName + ".") : currentName.startsWith(signalName) || signalName.startsWith(currentName)));
605
+ var skipValidation = (isBlurEvent, isTouched, isSubmitted, reValidateMode, mode) => {
606
+ if (mode.isOnAll) return false;
607
+ else if (!isSubmitted && mode.isOnTouch) return !(isTouched || isBlurEvent);
608
+ else if (isSubmitted ? reValidateMode.isOnBlur : mode.isOnBlur) return !isBlurEvent;
609
+ else if (isSubmitted ? reValidateMode.isOnChange : mode.isOnChange) return isBlurEvent;
610
+ return true;
611
+ };
612
+ var unsetEmptyArray = (ref, name) => {
613
+ const array = get(ref, name);
614
+ !compact(array).length && !(array !== null && array !== void 0 && array.root) && unset(ref, name);
615
+ };
567
616
  const defaultOptions = {
568
617
  mode: VALIDATION_MODE.onSubmit,
569
618
  reValidateMode: VALIDATION_MODE.onChange,
570
619
  shouldFocusError: true
571
620
  };
572
621
  const FORM_ERROR_TYPE = "form";
622
+ const updateDirtyFields = (dirtyFields, nextDirtyFields) => {
623
+ for (const key in dirtyFields) if (!(key in nextDirtyFields)) delete dirtyFields[key];
624
+ Object.assign(dirtyFields, nextDirtyFields);
625
+ };
573
626
  const DEFAULT_FORM_STATE = {
574
627
  submitCount: 0,
575
628
  isDirty: false,
@@ -599,6 +652,7 @@ function createFormControl(props = {}) {
599
652
  let _formValues = _options.shouldUnregister ? {} : cloneObject(_defaultValues);
600
653
  let _state = {
601
654
  action: false,
655
+ actionArrayLengths: /* @__PURE__ */ new Map(),
602
656
  mount: false,
603
657
  watch: false,
604
658
  keepIsValid: false
@@ -611,8 +665,8 @@ function createFormControl(props = {}) {
611
665
  watch: /* @__PURE__ */ new Set(),
612
666
  registerName: /* @__PURE__ */ new Set()
613
667
  };
614
- let delayErrorCallback;
615
- let timer = 0;
668
+ const delayErrorCallbacks = {};
669
+ const timers = {};
616
670
  let _valuesSubscriberCount = 0;
617
671
  let _validationModeBeforeSubmit = getValidationModes(_options.mode);
618
672
  let _validationModeAfterSubmit = getValidationModes(_options.reValidateMode);
@@ -631,29 +685,31 @@ function createFormControl(props = {}) {
631
685
  array: createSubject(),
632
686
  state: createSubject()
633
687
  };
688
+ let _setValidCallId = 0;
634
689
  const shouldDisplayAllAssociatedErrors = _options.criteriaMode === VALIDATION_MODE.all;
635
- const debounce = (callback) => (wait) => {
636
- clearTimeout(timer);
637
- timer = setTimeout(callback, wait);
690
+ const debounce = (name, callback) => (wait) => {
691
+ clearTimeout(timers[name]);
692
+ timers[name] = setTimeout(callback, wait);
638
693
  };
639
694
  const _setValid = async (shouldUpdateValid) => {
640
695
  if (_state.keepIsValid) return;
641
696
  if (!_options.disabled && (_proxyFormState.isValid || _proxySubscribeFormState.isValid || shouldUpdateValid)) {
697
+ const callId = ++_setValidCallId;
642
698
  let isValid;
643
699
  if (_options.resolver) {
644
700
  isValid = isEmptyObject((await _runSchema()).errors);
645
- _updateIsValidating();
701
+ callId === _setValidCallId && _updateIsValidating();
646
702
  } else isValid = await executeBuiltInValidation({
647
703
  fields: _fields,
648
704
  onlyCheckValid: true,
649
705
  eventType: EVENTS.VALID
650
706
  });
651
- if (isValid !== _formState.isValid) _subjects.state.next({ isValid });
707
+ if (callId === _setValidCallId && isValid !== _formState.isValid) _subjects.state.next({ isValid });
652
708
  }
653
709
  };
654
710
  const _updateIsValidating = (names, isValidating) => {
655
711
  if (!_options.disabled && (_proxyFormState.isValidating || _proxyFormState.validatingFields || _proxySubscribeFormState.isValidating || _proxySubscribeFormState.validatingFields)) {
656
- (names || Array.from(_names.mount)).forEach((name) => {
712
+ (names || _names.mount).forEach((name) => {
657
713
  if (name) isValidating ? set(_formState.validatingFields, name, isValidating) : unset(_formState.validatingFields, name);
658
714
  });
659
715
  _subjects.state.next({
@@ -663,22 +719,28 @@ function createFormControl(props = {}) {
663
719
  }
664
720
  };
665
721
  const _updateDirtyFields = () => {
666
- _formState.dirtyFields = getDirtyFields(_defaultValues, _formValues);
722
+ _formState.dirtyFields = getDirtyFields(_defaultValues, _formValues, void 0, _fields);
667
723
  };
668
724
  const _setFieldArray = (name, values = [], method, args, shouldSetValues = true, shouldUpdateFieldsAndState = true) => {
669
725
  if (args && method && !_options.disabled) {
670
726
  _state.action = true;
671
- if (shouldUpdateFieldsAndState && Array.isArray(get(_fields, name))) {
672
- const fieldValues = method(get(_fields, name), args.argA, args.argB);
727
+ const fields = get(_fields, name);
728
+ if (!_state.actionArrayLengths.has(name)) _state.actionArrayLengths.set(name, Array.isArray(fields) ? fields.length : 0);
729
+ if (shouldUpdateFieldsAndState && Array.isArray(fields)) {
730
+ const fieldValues = method(fields, args.argA, args.argB);
673
731
  shouldSetValues && set(_fields, name, fieldValues);
674
732
  }
675
- if (shouldUpdateFieldsAndState && Array.isArray(get(_formState.errors, name))) {
676
- const errors = method(get(_formState.errors, name), args.argA, args.argB);
733
+ const fieldArrayErrors = get(_formState.errors, name);
734
+ if (shouldUpdateFieldsAndState && Array.isArray(fieldArrayErrors)) {
735
+ const rootError = fieldArrayErrors.root;
736
+ const errors = method(fieldArrayErrors, args.argA, args.argB) || fieldArrayErrors;
737
+ if (rootError) errors.root = rootError;
677
738
  shouldSetValues && set(_formState.errors, name, errors);
678
739
  unsetEmptyArray(_formState.errors, name);
679
740
  }
680
- if ((_proxyFormState.touchedFields || _proxySubscribeFormState.touchedFields) && shouldUpdateFieldsAndState && Array.isArray(get(_formState.touchedFields, name))) {
681
- const touchedFields = method(get(_formState.touchedFields, name), args.argA, args.argB);
741
+ const touchedFieldsArray = get(_formState.touchedFields, name);
742
+ if ((_proxyFormState.touchedFields || _proxySubscribeFormState.touchedFields) && shouldUpdateFieldsAndState && Array.isArray(touchedFieldsArray)) {
743
+ const touchedFields = method(touchedFieldsArray, args.argA, args.argB);
682
744
  shouldSetValues && set(_formState.touchedFields, name, touchedFields);
683
745
  }
684
746
  if (_proxyFormState.dirtyFields || _proxySubscribeFormState.dirtyFields) _updateDirtyFields();
@@ -715,10 +777,30 @@ function createFormControl(props = {}) {
715
777
  }
716
778
  return false;
717
779
  };
780
+ const isStaleArrayIndex = (name) => {
781
+ if (!_state.actionArrayLengths.size) return false;
782
+ const segments = isKey(name) ? [name] : stringToPath(name);
783
+ let node = _formValues;
784
+ let path = "";
785
+ let ownerDepth = -1;
786
+ let ownerPreActionLength = 0;
787
+ for (let i = 0; i < segments.length; i++) {
788
+ if (isNullOrUndefined(node)) return false;
789
+ const key = segments[i];
790
+ path = path ? `${path}.${key}` : key;
791
+ if (Array.isArray(node) && +key >= node.length) return ownerDepth === -1 ? false : i === ownerDepth ? +key < ownerPreActionLength : true;
792
+ if (_state.actionArrayLengths.has(path)) {
793
+ ownerDepth = i + 1;
794
+ ownerPreActionLength = _state.actionArrayLengths.get(path);
795
+ }
796
+ node = node[key];
797
+ }
798
+ return false;
799
+ };
718
800
  const updateValidAndValue = (name, shouldSkipSetValueAs, value, ref) => {
719
801
  const field = get(_fields, name);
720
802
  if (field) {
721
- if (hasExplicitNullIntermediate(name)) return;
803
+ if (hasExplicitNullIntermediate(name) || isStaleArrayIndex(name)) return;
722
804
  const wasUnsetInFormValues = isUndefined(get(_formValues, name));
723
805
  const defaultValue = get(_formValues, name, isUndefined(value) ? get(_defaultValues, name) : value);
724
806
  isUndefined(defaultValue) || ref && ref.defaultChecked || shouldSkipSetValueAs ? set(_formValues, name, shouldSkipSetValueAs ? defaultValue : getFieldValue(field._f)) : setFieldValue(name, defaultValue);
@@ -738,7 +820,7 @@ function createFormControl(props = {}) {
738
820
  let shouldUpdateField = false;
739
821
  let isPreviousDirty = false;
740
822
  const output = { name };
741
- if (!_options.disabled) {
823
+ if (!_options.disabled || shouldDirty === true) {
742
824
  if (!isBlurEvent || shouldDirty) {
743
825
  const isCurrentFieldPristine = deepEqual(get(_defaultValues, name), fieldValue);
744
826
  if (_proxyFormState.isDirty || _proxySubscribeFormState.isDirty) {
@@ -747,7 +829,7 @@ function createFormControl(props = {}) {
747
829
  shouldUpdateField = isPreviousDirty !== output.isDirty;
748
830
  }
749
831
  isPreviousDirty = !!get(_formState.dirtyFields, name);
750
- if (isCurrentFieldPristine !== _formState.isDirty) _formState.dirtyFields = getDirtyFields(_defaultValues, _formValues);
832
+ if (isCurrentFieldPristine !== _formState.isDirty) updateDirtyFields(_formState.dirtyFields, getDirtyFields(_defaultValues, _formValues, void 0, _fields));
751
833
  else isCurrentFieldPristine ? unset(_formState.dirtyFields, name) : set(_formState.dirtyFields, name, true);
752
834
  output.dirtyFields = _formState.dirtyFields;
753
835
  shouldUpdateField = shouldUpdateField || (_proxyFormState.dirtyFields || _proxySubscribeFormState.dirtyFields) && isPreviousDirty !== !isCurrentFieldPristine;
@@ -768,11 +850,11 @@ function createFormControl(props = {}) {
768
850
  const previousFieldError = get(_formState.errors, name);
769
851
  const shouldUpdateValid = (_proxyFormState.isValid || _proxySubscribeFormState.isValid) && isBoolean(isValid) && _formState.isValid !== isValid;
770
852
  if (_options.delayError && error) {
771
- delayErrorCallback = debounce(() => updateErrors(name, error));
772
- delayErrorCallback(_options.delayError);
853
+ delayErrorCallbacks[name] = debounce(name, () => updateErrors(name, error));
854
+ delayErrorCallbacks[name](_options.delayError);
773
855
  } else {
774
- clearTimeout(timer);
775
- delayErrorCallback = null;
856
+ clearTimeout(timers[name]);
857
+ delete delayErrorCallbacks[name];
776
858
  error ? set(_formState.errors, name, error) : unset(_formState.errors, name);
777
859
  _formState.errors = { ..._formState.errors };
778
860
  }
@@ -783,10 +865,6 @@ function createFormControl(props = {}) {
783
865
  errors: _formState.errors,
784
866
  name
785
867
  };
786
- _formState = {
787
- ..._formState,
788
- ...updatedFormState
789
- };
790
868
  _subjects.state.next(updatedFormState);
791
869
  }
792
870
  };
@@ -880,10 +958,10 @@ function createFormControl(props = {}) {
880
958
  }
881
959
  _names.unMount = /* @__PURE__ */ new Set();
882
960
  };
883
- const _getDirty = (name, data) => !_options.disabled && (name && data && set(_formValues, name, data), !deepEqual(_state.mount ? _formValues : _defaultValues, _defaultValues));
884
- const _getWatch = (names, defaultValue, isGlobal) => generateWatchOutput(names, _names, { ..._state.mount ? _formValues : isUndefined(defaultValue) ? _defaultValues : isString(names) ? { [names]: defaultValue } : defaultValue }, isGlobal, defaultValue);
961
+ const _getDirty = (name, data) => (name && data && set(_formValues, name, data), !deepEqual(_state.mount ? _formValues : _defaultValues, _defaultValues));
962
+ const _getWatch = (names, defaultValue, isGlobal) => generateWatchOutput(names, _names, { ..._state.mount ? _formValues : isUndefined(defaultValue) || isString(names) ? _defaultValues : defaultValue }, isGlobal, defaultValue);
885
963
  const _getFieldArray = (name) => compact(get(_state.mount ? _formValues : _defaultValues, name, _options.shouldUnregister ? get(_defaultValues, name, []) : []));
886
- const setFieldValue = (name, value, options = {}, skipClone = false, skipRender = false) => {
964
+ const setFieldValue = (name, value, options = {}, skipClone = false, skipRender = false, skipValueRender = false) => {
887
965
  const field = get(_fields, name);
888
966
  let fieldValue = value;
889
967
  if (field) {
@@ -892,15 +970,18 @@ function createFormControl(props = {}) {
892
970
  !fieldReference.disabled && set(_formValues, name, getFieldValueAs(value, fieldReference));
893
971
  fieldValue = isHTMLElement(fieldReference.ref) && isNullOrUndefined(value) ? "" : value;
894
972
  if (isMultipleSelect(fieldReference.ref)) [...fieldReference.ref.options].forEach((optionRef) => optionRef.selected = fieldValue.includes(optionRef.value));
895
- else if (fieldReference.refs) if (isCheckBoxInput(fieldReference.ref)) fieldReference.refs.forEach((checkboxRef) => {
896
- if (!checkboxRef.defaultChecked || !checkboxRef.disabled) if (Array.isArray(fieldValue)) checkboxRef.checked = !!fieldValue.find((data) => data === checkboxRef.value);
897
- else checkboxRef.checked = fieldValue === checkboxRef.value || !!fieldValue;
898
- });
899
- else fieldReference.refs.forEach((radioRef) => radioRef.checked = radioRef.value === fieldValue);
900
- else if (isFileInput(fieldReference.ref)) fieldReference.ref.value = "";
973
+ else if (fieldReference.refs) {
974
+ if (isCheckBoxInput(fieldReference.ref)) fieldReference.refs.forEach((checkboxRef) => {
975
+ if (!checkboxRef.defaultChecked || !checkboxRef.disabled) {
976
+ if (Array.isArray(fieldValue)) checkboxRef.checked = !!fieldValue.find((data) => data === checkboxRef.value);
977
+ else checkboxRef.checked = fieldValue === checkboxRef.value || !!fieldValue;
978
+ }
979
+ });
980
+ else fieldReference.refs.forEach((radioRef) => radioRef.checked = radioRef.value === fieldValue);
981
+ } else if (isFileInput(fieldReference.ref)) fieldReference.ref.value = "";
901
982
  else {
902
983
  fieldReference.ref.value = fieldValue;
903
- if (!fieldReference.ref.type && !skipRender) _subjects.state.next({
984
+ if (!fieldReference.ref.type && !skipRender && !skipValueRender) _subjects.state.next({
904
985
  name,
905
986
  values: skipClone ? _formValues : cloneObject(_formValues)
906
987
  });
@@ -908,15 +989,19 @@ function createFormControl(props = {}) {
908
989
  }
909
990
  }
910
991
  (options.shouldDirty || options.shouldTouch) && updateTouchAndDirty(name, fieldValue, options.shouldTouch, options.shouldDirty, !skipRender);
911
- options.shouldValidate && trigger(name);
992
+ options.shouldValidate && trigger(name, { delayError: options.delayError });
912
993
  };
913
- const setFieldValues = (name, value, options, skipClone = false, skipRender = false) => {
994
+ const setFieldValues = (name, value, options, skipClone = false, skipRender = false, skipValueRender = false) => {
995
+ if (_names.array.has(name)) _subjects.array.next({
996
+ name,
997
+ values: skipClone ? _formValues : cloneObject(_formValues)
998
+ });
914
999
  for (const fieldKey in value) {
915
1000
  if (!value.hasOwnProperty(fieldKey)) return;
916
1001
  const fieldValue = value[fieldKey];
917
1002
  const fieldName = name + "." + fieldKey;
918
1003
  const field = get(_fields, fieldName);
919
- (_names.array.has(name) || isObject(fieldValue) || field && !field._f) && !isDateObject(fieldValue) ? setFieldValues(fieldName, fieldValue, options, skipClone, skipRender) : setFieldValue(fieldName, fieldValue, options, skipClone, skipRender);
1004
+ (_names.array.has(name) || isObject(fieldValue) || field && !field._f) && !isDateObject(fieldValue) ? setFieldValues(fieldName, fieldValue, options, skipClone, skipRender, skipValueRender) : setFieldValue(fieldName, fieldValue, options, skipClone, skipRender, skipValueRender);
920
1005
  }
921
1006
  };
922
1007
  const _setValue = (name, value, options, skipClone, skipStateEmit = false) => {
@@ -940,8 +1025,9 @@ function createFormControl(props = {}) {
940
1025
  }
941
1026
  } else {
942
1027
  const isEmpty = Array.isArray(cloneValue) && !cloneValue.length || isEmptyObject(cloneValue);
943
- if (!field || field._f || isNullOrUndefined(cloneValue) || isEmpty) setFieldValue(name, cloneValue, options, skipClone, skipStateEmit);
944
- else setFieldValues(name, cloneValue, options, skipClone, skipStateEmit);
1028
+ const skipValueRender = !isValueUnchanged && !skipStateEmit;
1029
+ if (!field || field._f || isNullOrUndefined(cloneValue) || isEmpty) setFieldValue(name, cloneValue, options, skipClone, skipStateEmit, skipValueRender);
1030
+ else setFieldValues(name, cloneValue, options, skipClone, skipStateEmit, skipValueRender);
945
1031
  }
946
1032
  if (!isValueUnchanged && !skipStateEmit) {
947
1033
  const watched = isWatched(name, _names);
@@ -951,6 +1037,10 @@ function createFormControl(props = {}) {
951
1037
  name: _state.mount || watched ? name : void 0,
952
1038
  values
953
1039
  });
1040
+ if (!isFieldArray) for (const itemName of getFieldArrayItemNames(_names.array, name)) _subjects.state.next({
1041
+ name: itemName,
1042
+ values
1043
+ });
954
1044
  }
955
1045
  };
956
1046
  const setValue = (name, value, options = {}) => _setValue(name, value, options, false);
@@ -961,7 +1051,7 @@ function createFormControl(props = {}) {
961
1051
  ..._formValues,
962
1052
  ...updatedFormValues
963
1053
  };
964
- for (const fieldName of _names.mount) _setValue(fieldName, get(updatedFormValues, fieldName), options, true, true);
1054
+ for (const fieldName of _names.mount) if (has(updatedFormValues, fieldName)) _setValue(fieldName, get(updatedFormValues, fieldName), options, true, true);
965
1055
  _subjects.state.next({
966
1056
  ..._formState,
967
1057
  name: void 0,
@@ -992,7 +1082,8 @@ function createFormControl(props = {}) {
992
1082
  if (isBlurEvent) {
993
1083
  if (!target || !target.readOnly) {
994
1084
  field._f.onBlur && field._f.onBlur(event);
995
- delayErrorCallback && delayErrorCallback(0);
1085
+ const pendingDelayError = delayErrorCallbacks[name];
1086
+ pendingDelayError && pendingDelayError(0);
996
1087
  }
997
1088
  } else if (field._f.onChange) field._f.onChange(event);
998
1089
  const fieldState = updateTouchAndDirty(name, fieldValue, isBlurEvent);
@@ -1080,6 +1171,17 @@ function createFormControl(props = {}) {
1080
1171
  name,
1081
1172
  eventType: EVENTS.TRIGGER
1082
1173
  });
1174
+ if (options.delayError && _options.delayError && isString(name)) {
1175
+ const error = get(_formState.errors, name);
1176
+ if (error) {
1177
+ unset(_formState.errors, name);
1178
+ delayErrorCallbacks[name] = debounce(name, () => updateErrors(name, error));
1179
+ delayErrorCallbacks[name](_options.delayError);
1180
+ } else {
1181
+ clearTimeout(timers[name]);
1182
+ delete delayErrorCallbacks[name];
1183
+ }
1184
+ }
1083
1185
  _subjects.state.next({
1084
1186
  ...!isString(name) || (_proxyFormState.isValid || _proxySubscribeFormState.isValid) && isValid !== _formState.isValid ? {} : { name },
1085
1187
  ..._options.resolver || !name ? { isValid } : {},
@@ -1093,13 +1195,18 @@ function createFormControl(props = {}) {
1093
1195
  if (config) values = extractFormValues(config.dirtyFields ? _formState.dirtyFields : _formState.touchedFields, values);
1094
1196
  return isUndefined(fieldNames) ? values : isString(fieldNames) ? get(values, fieldNames) : fieldNames.map((name) => get(values, name));
1095
1197
  };
1096
- const getFieldState = (name, formState) => ({
1097
- invalid: !!get((formState || _formState).errors, name),
1098
- isDirty: !!get((formState || _formState).dirtyFields, name),
1099
- error: get((formState || _formState).errors, name),
1100
- isValidating: !!get(_formState.validatingFields, name),
1101
- isTouched: !!get((formState || _formState).touchedFields, name)
1102
- });
1198
+ const getErrors = (fieldNames) => isUndefined(fieldNames) ? { ..._formState.errors } : isString(fieldNames) ? get(_formState.errors, fieldNames) : fieldNames.map((name) => get(_formState.errors, name));
1199
+ const getFieldState = (name, formState) => {
1200
+ const targetFormState = formState || _formState;
1201
+ const error = get(targetFormState.errors, name);
1202
+ return {
1203
+ invalid: !!error,
1204
+ isDirty: !!get(targetFormState.dirtyFields, name),
1205
+ error,
1206
+ isValidating: !!get(_formState.validatingFields, name),
1207
+ isTouched: !!get(targetFormState.touchedFields, name)
1208
+ };
1209
+ };
1103
1210
  const clearErrors = (name) => {
1104
1211
  const names = name ? convertToArrayPayload(name) : void 0;
1105
1212
  names === null || names === void 0 || names.forEach((inputName) => unset(_formState.errors, inputName));
@@ -1109,7 +1216,10 @@ function createFormControl(props = {}) {
1109
1216
  errors: _formState.errors
1110
1217
  });
1111
1218
  });
1112
- else _subjects.state.next({ errors: {} });
1219
+ else {
1220
+ _formState.errors = {};
1221
+ _subjects.state.next({ errors: _formState.errors });
1222
+ }
1113
1223
  };
1114
1224
  const setError = (name, error, options) => {
1115
1225
  const ref = (get(_fields, name, { _f: {} })._f || {}).ref;
@@ -1192,10 +1302,10 @@ function createFormControl(props = {}) {
1192
1302
  !options.keepIsValidating && unset(_formState.validatingFields, fieldName);
1193
1303
  !_options.shouldUnregister && !options.keepDefaultValue && unset(_defaultValues, fieldName);
1194
1304
  }
1195
- _subjects.state.next({ values: cloneObject(_formValues) });
1305
+ _valuesSubscriberCount && _subjects.state.next({ values: cloneObject(_formValues) });
1196
1306
  _subjects.state.next({
1197
1307
  ..._formState,
1198
- ...!options.keepDirty ? {} : { isDirty: _getDirty() }
1308
+ ...options.keepDirty ? {} : { isDirty: _getDirty() }
1199
1309
  });
1200
1310
  !options.keepIsValid && _setValid();
1201
1311
  };
@@ -1248,20 +1358,22 @@ function createFormControl(props = {}) {
1248
1358
  const radioOrCheckbox = isRadioOrCheckbox(fieldRef);
1249
1359
  const refs = field._f.refs || [];
1250
1360
  if (radioOrCheckbox ? refs.find((option) => option === fieldRef) : fieldRef === field._f.ref) return;
1251
- set(_fields, name, { _f: {
1252
- ...field._f,
1253
- ...radioOrCheckbox ? {
1254
- refs: [
1255
- ...refs.filter(live),
1256
- fieldRef,
1257
- ...Array.isArray(get(_defaultValues, name)) ? [{}] : []
1258
- ],
1259
- ref: {
1260
- type: fieldRef.type,
1261
- name
1262
- }
1263
- } : { ref: fieldRef }
1264
- } });
1361
+ const newField = { ...field._f };
1362
+ if (radioOrCheckbox) {
1363
+ newField.refs = [
1364
+ ...refs.filter(live),
1365
+ fieldRef,
1366
+ ...Array.isArray(get(_defaultValues, name)) ? [{}] : []
1367
+ ];
1368
+ newField.ref = {
1369
+ type: fieldRef.type,
1370
+ name
1371
+ };
1372
+ } else {
1373
+ newField.ref = fieldRef;
1374
+ delete newField.refs;
1375
+ }
1376
+ set(_fields, name, { _f: newField });
1265
1377
  updateValidAndValue(name, false, void 0, fieldRef);
1266
1378
  } else {
1267
1379
  field = get(_fields, name, {});
@@ -1287,6 +1399,7 @@ function createFormControl(props = {}) {
1287
1399
  }
1288
1400
  };
1289
1401
  const handleSubmit = (onValid, onInvalid) => async (e) => {
1402
+ let result = void 0;
1290
1403
  let onValidError = void 0;
1291
1404
  if (e) {
1292
1405
  e.preventDefault && e.preventDefault();
@@ -1308,7 +1421,7 @@ function createFormControl(props = {}) {
1308
1421
  if (isEmptyObject(_formState.errors)) {
1309
1422
  _subjects.state.next({ errors: {} });
1310
1423
  try {
1311
- await onValid(fieldValues, e);
1424
+ result = await onValid(fieldValues, e);
1312
1425
  } catch (error) {
1313
1426
  onValidError = error;
1314
1427
  }
@@ -1325,6 +1438,7 @@ function createFormControl(props = {}) {
1325
1438
  errors: _formState.errors
1326
1439
  });
1327
1440
  if (onValidError) throw onValidError;
1441
+ return result;
1328
1442
  };
1329
1443
  const resetField = (name, options = {}) => {
1330
1444
  if (get(_fields, name)) {
@@ -1350,11 +1464,12 @@ function createFormControl(props = {}) {
1350
1464
  const cloneUpdatedValues = cloneObject(updatedValues);
1351
1465
  const isEmptyResetValues = isEmptyObject(formValues);
1352
1466
  const values = cloneUpdatedValues;
1467
+ const fieldRefs = _fields;
1353
1468
  if (!keepStateOptions.keepDefaultValues) _defaultValues = updatedValues;
1354
1469
  if (!keepStateOptions.keepValues) {
1355
1470
  if (keepStateOptions.keepDirtyValues) {
1356
- const fieldsToCheck = /* @__PURE__ */ new Set([..._names.mount, ...Object.keys(getDirtyFields(_defaultValues, _formValues))]);
1357
- for (const fieldName of Array.from(fieldsToCheck)) {
1471
+ const fieldsToCheck = /* @__PURE__ */ new Set([..._names.mount, ...collectDirtyFieldNames(getDirtyFields(_defaultValues, _formValues, void 0, fieldRefs), _formState.dirtyFields)]);
1472
+ for (const fieldName of fieldsToCheck) {
1358
1473
  const isDirty = get(_formState.dirtyFields, fieldName);
1359
1474
  const existingValue = get(_formValues, fieldName);
1360
1475
  const newValue = get(values, fieldName);
@@ -1383,7 +1498,11 @@ function createFormControl(props = {}) {
1383
1498
  if (keepStateOptions.keepFieldsRef) for (const fieldName of _names.mount) set(_formValues, fieldName, get(values, fieldName));
1384
1499
  } else _formValues = cloneObject(values);
1385
1500
  _subjects.array.next({ values: { ...values } });
1386
- _subjects.state.next({ values: { ...values } });
1501
+ _subjects.state.next({
1502
+ name: void 0,
1503
+ type: void 0,
1504
+ values: { ...values }
1505
+ });
1387
1506
  }
1388
1507
  _names = {
1389
1508
  mount: keepStateOptions.keepDirtyValues ? _names.mount : /* @__PURE__ */ new Set(),
@@ -1399,12 +1518,13 @@ function createFormControl(props = {}) {
1399
1518
  _state.watch = !!_options.shouldUnregister;
1400
1519
  _state.keepIsValid = !!keepStateOptions.keepIsValid;
1401
1520
  _state.action = false;
1521
+ _state.actionArrayLengths.clear();
1402
1522
  if (!keepStateOptions.keepErrors) _formState.errors = {};
1403
1523
  _subjects.state.next({
1404
1524
  submitCount: keepStateOptions.keepSubmitCount ? _formState.submitCount : 0,
1405
1525
  isDirty: isEmptyResetValues ? false : keepStateOptions.keepDirty ? _formState.isDirty : keepStateOptions.keepValues ? _getDirty() : !!(keepStateOptions.keepDefaultValues && !deepEqual(formValues, _defaultValues)),
1406
1526
  isSubmitted: keepStateOptions.keepIsSubmitted ? _formState.isSubmitted : false,
1407
- dirtyFields: isEmptyResetValues ? {} : keepStateOptions.keepDirtyValues ? keepStateOptions.keepDefaultValues && _formValues ? getDirtyFields(_defaultValues, _formValues) : _formState.dirtyFields : keepStateOptions.keepDefaultValues && formValues ? getDirtyFields(_defaultValues, formValues) : keepStateOptions.keepDirty ? _formState.dirtyFields : {},
1527
+ dirtyFields: isEmptyResetValues ? {} : keepStateOptions.keepDirtyValues ? keepStateOptions.keepDefaultValues && _formValues ? getDirtyFields(_defaultValues, _formValues, void 0, fieldRefs) : _formState.dirtyFields : keepStateOptions.keepDefaultValues && formValues ? getDirtyFields(_defaultValues, formValues, void 0, fieldRefs) : keepStateOptions.keepDirty ? _formState.dirtyFields : {},
1408
1528
  touchedFields: keepStateOptions.keepTouched ? _formState.touchedFields : {},
1409
1529
  errors: keepStateOptions.keepErrors ? _formState.errors : {},
1410
1530
  isSubmitSuccessful: keepStateOptions.keepIsSubmitSuccessful ? _formState.isSubmitSuccessful : false,
@@ -1428,11 +1548,13 @@ function createFormControl(props = {}) {
1428
1548
  }
1429
1549
  };
1430
1550
  const _setFormState = (updatedFormState) => {
1551
+ const { name, type, values, ...formState } = updatedFormState;
1431
1552
  _formState = {
1432
1553
  ..._formState,
1433
- ...updatedFormState
1554
+ ...formState
1434
1555
  };
1435
1556
  };
1557
+ _subjects.state.subscribe({ next: _setFormState });
1436
1558
  const _resetDefaultValues = () => isFunction(_options.defaultValues) && _options.defaultValues().then((values) => {
1437
1559
  reset(values, _options.resetOptions);
1438
1560
  _subjects.state.next({ isLoading: false });
@@ -1440,7 +1562,7 @@ function createFormControl(props = {}) {
1440
1562
  const resetDefaultValues = (values, options = {}) => {
1441
1563
  _defaultValues = cloneObject(values);
1442
1564
  if (!options.keepDirty) {
1443
- const newDirtyFields = getDirtyFields(_defaultValues, _formValues);
1565
+ const newDirtyFields = getDirtyFields(_defaultValues, _formValues, void 0, _fields);
1444
1566
  _formState.dirtyFields = newDirtyFields;
1445
1567
  _formState.isDirty = !isEmptyObject(newDirtyFields);
1446
1568
  }
@@ -1518,6 +1640,7 @@ function createFormControl(props = {}) {
1518
1640
  setValue,
1519
1641
  setValues,
1520
1642
  getValues,
1643
+ getErrors,
1521
1644
  reset,
1522
1645
  resetField,
1523
1646
  resetDefaultValues,
@@ -1590,8 +1713,14 @@ function useForm(props = {}) {
1590
1713
  }
1591
1714
  const control = _formControl.current.control;
1592
1715
  control._options = props;
1716
+ const { resyncIfNeeded, snapshot } = useResyncOnReconnect();
1593
1717
  useIsomorphicLayoutEffect(() => {
1594
- const sub = control._subscribe({
1718
+ const getCurrentFormState = () => ({
1719
+ ...control._formState,
1720
+ defaultValues: control._defaultValues
1721
+ });
1722
+ resyncIfNeeded(true, getCurrentFormState, updateFormState);
1723
+ const unsubscribe = control._subscribe({
1595
1724
  formState: control._proxyFormState,
1596
1725
  callback: () => updateFormState({
1597
1726
  ...control._formState,
@@ -1604,8 +1733,15 @@ function useForm(props = {}) {
1604
1733
  isReady: true
1605
1734
  }));
1606
1735
  control._formState.isReady = true;
1607
- return sub;
1608
- }, [control]);
1736
+ return () => {
1737
+ unsubscribe();
1738
+ snapshot(true, getCurrentFormState);
1739
+ };
1740
+ }, [
1741
+ control,
1742
+ resyncIfNeeded,
1743
+ snapshot
1744
+ ]);
1609
1745
  React.useEffect(() => control._disableForm(props.disabled), [control, props.disabled]);
1610
1746
  React.useEffect(() => {
1611
1747
  if (props.mode) control._options.mode = props.mode;