@gaddario98/react-core 2.0.8 → 2.1.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.
@@ -1,4 +1,4 @@
1
- 'use strict';var reactState=require('@gaddario98/react-state'),compilerRuntime=require('react/compiler-runtime'),jsxRuntime=require('react/jsx-runtime'),React=require('react'),equal=require('fast-deep-equal'),withSelector_js=require('use-sync-external-store/shim/with-selector.js');function _interopNamespaceDefault(e){var n=Object.create(null);if(e){Object.keys(e).forEach(function(k){if(k!=='default'){var d=Object.getOwnPropertyDescriptor(e,k);Object.defineProperty(n,k,d.get?d:{enumerable:true,get:function(){return e[k]}});}})}n.default=e;return Object.freeze(n)}var React__namespace=/*#__PURE__*/_interopNamespaceDefault(React);const DefaultContainer$1 = ({
1
+ 'use strict';var reactState=require('@gaddario98/react-state'),compilerRuntime=require('react/compiler-runtime'),jsxRuntime=require('react/jsx-runtime'),react=require('react'),jotai=require('jotai'),utils=require('jotai/utils'),equal=require('fast-deep-equal'),reactForm=require('@tanstack/react-form');const DefaultContainer$1 = ({
2
2
  children
3
3
  }) => {
4
4
  return children;
@@ -53,2938 +53,9 @@ function _temp$1(e) {
53
53
  const form = e.currentTarget;
54
54
  const submitButton = form.querySelector("button[type=\"submit\"]");
55
55
  submitButton === null || submitButton === void 0 ? void 0 : submitButton.click();
56
- }const __storeToDerived = /* @__PURE__ */new WeakMap();
57
- const __derivedToStore = /* @__PURE__ */new WeakMap();
58
- const __depsThatHaveWrittenThisTick = {
59
- current: []
60
- };
61
- let __isFlushing = false;
62
- let __batchDepth = 0;
63
- const __pendingUpdates = /* @__PURE__ */new Set();
64
- const __initialBatchValues = /* @__PURE__ */new Map();
65
- function __flush_internals(relatedVals) {
66
- const sorted = Array.from(relatedVals).sort((a, b) => {
67
- if (a instanceof Derived && a.options.deps.includes(b)) return 1;
68
- if (b instanceof Derived && b.options.deps.includes(a)) return -1;
69
- return 0;
70
- });
71
- for (const derived of sorted) {
72
- if (__depsThatHaveWrittenThisTick.current.includes(derived)) {
73
- continue;
74
- }
75
- __depsThatHaveWrittenThisTick.current.push(derived);
76
- derived.recompute();
77
- const stores = __derivedToStore.get(derived);
78
- if (stores) {
79
- for (const store of stores) {
80
- const relatedLinkedDerivedVals = __storeToDerived.get(store);
81
- if (!relatedLinkedDerivedVals) continue;
82
- __flush_internals(relatedLinkedDerivedVals);
83
- }
84
- }
85
- }
86
- }
87
- function __notifyListeners(store) {
88
- const value = {
89
- prevVal: store.prevState,
90
- currentVal: store.state
91
- };
92
- for (const listener of store.listeners) {
93
- listener(value);
94
- }
95
- }
96
- function __notifyDerivedListeners(derived) {
97
- const value = {
98
- prevVal: derived.prevState,
99
- currentVal: derived.state
100
- };
101
- for (const listener of derived.listeners) {
102
- listener(value);
103
- }
104
- }
105
- function __flush(store) {
106
- if (__batchDepth > 0 && !__initialBatchValues.has(store)) {
107
- __initialBatchValues.set(store, store.prevState);
108
- }
109
- __pendingUpdates.add(store);
110
- if (__batchDepth > 0) return;
111
- if (__isFlushing) return;
112
- try {
113
- __isFlushing = true;
114
- while (__pendingUpdates.size > 0) {
115
- const stores = Array.from(__pendingUpdates);
116
- __pendingUpdates.clear();
117
- for (const store2 of stores) {
118
- const prevState = __initialBatchValues.get(store2) ?? store2.prevState;
119
- store2.prevState = prevState;
120
- __notifyListeners(store2);
121
- }
122
- for (const store2 of stores) {
123
- const derivedVals = __storeToDerived.get(store2);
124
- if (!derivedVals) continue;
125
- __depsThatHaveWrittenThisTick.current.push(store2);
126
- __flush_internals(derivedVals);
127
- }
128
- for (const store2 of stores) {
129
- const derivedVals = __storeToDerived.get(store2);
130
- if (!derivedVals) continue;
131
- for (const derived of derivedVals) {
132
- __notifyDerivedListeners(derived);
133
- }
134
- }
135
- }
136
- } finally {
137
- __isFlushing = false;
138
- __depsThatHaveWrittenThisTick.current = [];
139
- __initialBatchValues.clear();
140
- }
141
- }
142
- function batch(fn) {
143
- __batchDepth++;
144
- try {
145
- fn();
146
- } finally {
147
- __batchDepth--;
148
- if (__batchDepth === 0) {
149
- const pendingUpdateToFlush = __pendingUpdates.values().next().value;
150
- if (pendingUpdateToFlush) {
151
- __flush(pendingUpdateToFlush);
152
- }
153
- }
154
- }
155
- }function isUpdaterFunction(updater) {
156
- return typeof updater === "function";
157
- }class Store {
158
- constructor(initialState, options) {
159
- this.listeners = /* @__PURE__ */new Set();
160
- this.subscribe = listener => {
161
- var _a, _b;
162
- this.listeners.add(listener);
163
- const unsub = (_b = (_a = this.options) == null ? void 0 : _a.onSubscribe) == null ? void 0 : _b.call(_a, listener, this);
164
- return () => {
165
- this.listeners.delete(listener);
166
- unsub == null ? void 0 : unsub();
167
- };
168
- };
169
- this.prevState = initialState;
170
- this.state = initialState;
171
- this.options = options;
172
- }
173
- setState(updater) {
174
- var _a, _b, _c;
175
- this.prevState = this.state;
176
- if ((_a = this.options) == null ? void 0 : _a.updateFn) {
177
- this.state = this.options.updateFn(this.prevState)(updater);
178
- } else {
179
- if (isUpdaterFunction(updater)) {
180
- this.state = updater(this.prevState);
181
- } else {
182
- this.state = updater;
183
- }
184
- }
185
- (_c = (_b = this.options) == null ? void 0 : _b.onUpdate) == null ? void 0 : _c.call(_b);
186
- __flush(this);
187
- }
188
- }class Derived {
189
- constructor(options) {
190
- this.listeners = /* @__PURE__ */new Set();
191
- this._subscriptions = [];
192
- this.lastSeenDepValues = [];
193
- this.getDepVals = () => {
194
- const l = this.options.deps.length;
195
- const prevDepVals = new Array(l);
196
- const currDepVals = new Array(l);
197
- for (let i = 0; i < l; i++) {
198
- const dep = this.options.deps[i];
199
- prevDepVals[i] = dep.prevState;
200
- currDepVals[i] = dep.state;
201
- }
202
- this.lastSeenDepValues = currDepVals;
203
- return {
204
- prevDepVals,
205
- currDepVals,
206
- prevVal: this.prevState ?? void 0
207
- };
208
- };
209
- this.recompute = () => {
210
- var _a, _b;
211
- this.prevState = this.state;
212
- const depVals = this.getDepVals();
213
- this.state = this.options.fn(depVals);
214
- (_b = (_a = this.options).onUpdate) == null ? void 0 : _b.call(_a);
215
- };
216
- this.checkIfRecalculationNeededDeeply = () => {
217
- for (const dep of this.options.deps) {
218
- if (dep instanceof Derived) {
219
- dep.checkIfRecalculationNeededDeeply();
220
- }
221
- }
222
- let shouldRecompute = false;
223
- const lastSeenDepValues = this.lastSeenDepValues;
224
- const {
225
- currDepVals
226
- } = this.getDepVals();
227
- for (let i = 0; i < currDepVals.length; i++) {
228
- if (currDepVals[i] !== lastSeenDepValues[i]) {
229
- shouldRecompute = true;
230
- break;
231
- }
232
- }
233
- if (shouldRecompute) {
234
- this.recompute();
235
- }
236
- };
237
- this.mount = () => {
238
- this.registerOnGraph();
239
- this.checkIfRecalculationNeededDeeply();
240
- return () => {
241
- this.unregisterFromGraph();
242
- for (const cleanup of this._subscriptions) {
243
- cleanup();
244
- }
245
- };
246
- };
247
- this.subscribe = listener => {
248
- var _a, _b;
249
- this.listeners.add(listener);
250
- const unsub = (_b = (_a = this.options).onSubscribe) == null ? void 0 : _b.call(_a, listener, this);
251
- return () => {
252
- this.listeners.delete(listener);
253
- unsub == null ? void 0 : unsub();
254
- };
255
- };
256
- this.options = options;
257
- this.state = options.fn({
258
- prevDepVals: void 0,
259
- prevVal: void 0,
260
- currDepVals: this.getDepVals().currDepVals
261
- });
262
- }
263
- registerOnGraph(deps = this.options.deps) {
264
- for (const dep of deps) {
265
- if (dep instanceof Derived) {
266
- dep.registerOnGraph();
267
- this.registerOnGraph(dep.options.deps);
268
- } else if (dep instanceof Store) {
269
- let relatedLinkedDerivedVals = __storeToDerived.get(dep);
270
- if (!relatedLinkedDerivedVals) {
271
- relatedLinkedDerivedVals = /* @__PURE__ */new Set();
272
- __storeToDerived.set(dep, relatedLinkedDerivedVals);
273
- }
274
- relatedLinkedDerivedVals.add(this);
275
- let relatedStores = __derivedToStore.get(this);
276
- if (!relatedStores) {
277
- relatedStores = /* @__PURE__ */new Set();
278
- __derivedToStore.set(this, relatedStores);
279
- }
280
- relatedStores.add(dep);
281
- }
282
- }
283
- }
284
- unregisterFromGraph(deps = this.options.deps) {
285
- for (const dep of deps) {
286
- if (dep instanceof Derived) {
287
- this.unregisterFromGraph(dep.options.deps);
288
- } else if (dep instanceof Store) {
289
- const relatedLinkedDerivedVals = __storeToDerived.get(dep);
290
- if (relatedLinkedDerivedVals) {
291
- relatedLinkedDerivedVals.delete(this);
292
- }
293
- const relatedStores = __derivedToStore.get(this);
294
- if (relatedStores) {
295
- relatedStores.delete(dep);
296
- }
297
- }
298
- }
299
- }
300
- }//#region src/lite-throttler.ts
301
- /**
302
- * A lightweight class that creates a throttled function.
303
- *
304
- * This is an alternative to the Throttler in the core @tanstack/pacer package, but is more
305
- * suitable for libraries and npm packages that need minimal overhead. Unlike the core Throttler,
306
- * this version does not use TanStack Store for state management, has no devtools integration,
307
- * and provides only essential throttling functionality.
308
- *
309
- * Throttling ensures a function is called at most once within a specified time window.
310
- * Unlike debouncing which waits for a pause in calls, throttling guarantees consistent
311
- * execution timing regardless of call frequency.
312
- *
313
- * Supports both leading and trailing edge execution:
314
- * - Leading: Execute immediately on first call (default: true)
315
- * - Trailing: Execute after wait period if called during throttle (default: true)
316
- *
317
- * Features:
318
- * - Zero dependencies - no external libraries required
319
- * - Minimal API surface - only essential methods (maybeExecute, flush, cancel)
320
- * - Simple state management - uses basic private properties instead of reactive stores
321
- * - Callback support for monitoring execution events
322
- * - Lightweight - designed for use in npm packages where bundle size matters
323
- *
324
- * @example
325
- * ```ts
326
- * const throttler = new LiteThrottler((scrollY: number) => {
327
- * updateScrollPosition(scrollY);
328
- * }, {
329
- * wait: 100,
330
- * onExecute: (args, throttler) => {
331
- * console.log('Updated scroll position:', args[0]);
332
- * }
333
- * });
334
- *
335
- * // Will execute at most once per 100ms
336
- * window.addEventListener('scroll', () => {
337
- * throttler.maybeExecute(window.scrollY);
338
- * });
339
- * ```
340
- */
341
- var LiteThrottler = class {
342
- constructor(fn, options) {
343
- this.fn = fn;
344
- this.options = options;
345
- this.lastExecutionTime = 0;
346
- this.isPending = false;
347
- this.maybeExecute = (...args) => {
348
- const timeSinceLastExecution = Date.now() - this.lastExecutionTime;
349
- if (this.options.leading && timeSinceLastExecution >= this.options.wait) this.execute(...args);else {
350
- this.lastArgs = args;
351
- if (!this.timeoutId && this.options.trailing) {
352
- const timeoutDuration = this.options.wait - timeSinceLastExecution;
353
- this.isPending = true;
354
- this.timeoutId = setTimeout(() => {
355
- if (this.lastArgs !== void 0) this.execute(...this.lastArgs);
356
- }, timeoutDuration);
357
- }
358
- }
359
- };
360
- this.execute = (...args) => {
361
- this.fn(...args);
362
- this.options.onExecute?.(args, this);
363
- this.lastExecutionTime = Date.now();
364
- this.clearTimeout();
365
- this.lastArgs = void 0;
366
- this.isPending = false;
367
- };
368
- this.flush = () => {
369
- if (this.isPending && this.lastArgs) this.execute(...this.lastArgs);
370
- };
371
- this.cancel = () => {
372
- this.clearTimeout();
373
- this.lastArgs = void 0;
374
- this.isPending = false;
375
- };
376
- this.clearTimeout = () => {
377
- if (this.timeoutId) {
378
- clearTimeout(this.timeoutId);
379
- this.timeoutId = void 0;
380
- }
381
- };
382
- if (this.options.leading === void 0 && this.options.trailing === void 0) {
383
- this.options.leading = true;
384
- this.options.trailing = true;
385
- }
386
- }
387
- };
388
- /**
389
- * Creates a lightweight throttled function that limits how often the provided function can execute.
390
- *
391
- * This is an alternative to the throttle function in the core @tanstack/pacer package, but is more
392
- * suitable for libraries and npm packages that need minimal overhead. Unlike the core version,
393
- * this function creates a throttler with no external dependencies, devtools integration, or reactive state.
394
- *
395
- * Throttling ensures a function executes at most once within a specified time window,
396
- * regardless of how many times it is called. This is useful for rate-limiting
397
- * expensive operations or UI updates.
398
- *
399
- * @example
400
- * ```ts
401
- * const throttledScroll = liteThrottle(() => {
402
- * updateScrollIndicator();
403
- * }, { wait: 100 });
404
- *
405
- * // Will execute at most once per 100ms
406
- * window.addEventListener('scroll', throttledScroll);
407
- * ```
408
- *
409
- * @example
410
- * ```ts
411
- * // Leading edge execution - fires immediately then throttles
412
- * const throttledResize = liteThrottle(() => {
413
- * recalculateLayout();
414
- * }, { wait: 250, leading: true, trailing: false });
415
- * ```
416
- */
417
- function liteThrottle(fn, options) {
418
- return new LiteThrottler(fn, options).maybeExecute;
419
- }class EventClient {
420
- #enabled = true;
421
- #pluginId;
422
- #eventTarget;
423
- #debug;
424
- #queuedEvents;
425
- #connected;
426
- #connectIntervalId;
427
- #connectEveryMs;
428
- #retryCount = 0;
429
- #maxRetries = 5;
430
- #connecting = false;
431
- #failedToConnect = false;
432
- #internalEventTarget = null;
433
- #onConnected = () => {
434
- this.debugLog("Connected to event bus");
435
- this.#connected = true;
436
- this.#connecting = false;
437
- this.debugLog("Emitting queued events", this.#queuedEvents);
438
- this.#queuedEvents.forEach(event => this.emitEventToBus(event));
439
- this.#queuedEvents = [];
440
- this.stopConnectLoop();
441
- this.#eventTarget().removeEventListener("tanstack-connect-success", this.#onConnected);
442
- };
443
- // fired off right away and then at intervals
444
- #retryConnection = () => {
445
- if (this.#retryCount < this.#maxRetries) {
446
- this.#retryCount++;
447
- this.dispatchCustomEvent("tanstack-connect", {});
448
- return;
449
- }
450
- this.#eventTarget().removeEventListener("tanstack-connect", this.#retryConnection);
451
- this.#failedToConnect = true;
452
- this.debugLog("Max retries reached, giving up on connection");
453
- this.stopConnectLoop();
454
- };
455
- // This is run to register connection handlers on first emit attempt
456
- #connectFunction = () => {
457
- if (this.#connecting) return;
458
- this.#connecting = true;
459
- this.#eventTarget().addEventListener("tanstack-connect-success", this.#onConnected);
460
- this.#retryConnection();
461
- };
462
- constructor({
463
- pluginId,
464
- debug = false,
465
- enabled = true,
466
- reconnectEveryMs = 300
467
- }) {
468
- this.#pluginId = pluginId;
469
- this.#enabled = enabled;
470
- this.#eventTarget = this.getGlobalTarget;
471
- this.#debug = debug;
472
- this.debugLog(" Initializing event subscription for plugin", this.#pluginId);
473
- this.#queuedEvents = [];
474
- this.#connected = false;
475
- this.#failedToConnect = false;
476
- this.#connectIntervalId = null;
477
- this.#connectEveryMs = reconnectEveryMs;
478
- }
479
- startConnectLoop() {
480
- if (this.#connectIntervalId !== null || this.#connected) return;
481
- this.debugLog(`Starting connect loop (every ${this.#connectEveryMs}ms)`);
482
- this.#connectIntervalId = setInterval(this.#retryConnection, this.#connectEveryMs);
483
- }
484
- stopConnectLoop() {
485
- this.#connecting = false;
486
- if (this.#connectIntervalId === null) {
487
- return;
488
- }
489
- clearInterval(this.#connectIntervalId);
490
- this.#connectIntervalId = null;
491
- this.#queuedEvents = [];
492
- this.debugLog("Stopped connect loop");
493
- }
494
- debugLog(...args) {
495
- if (this.#debug) {
496
- console.log(`🌴 [tanstack-devtools:${this.#pluginId}-plugin]`, ...args);
497
- }
498
- }
499
- getGlobalTarget() {
500
- if (typeof globalThis !== "undefined" && globalThis.__TANSTACK_EVENT_TARGET__) {
501
- this.debugLog("Using global event target");
502
- return globalThis.__TANSTACK_EVENT_TARGET__;
503
- }
504
- if (typeof window !== "undefined" && typeof window.addEventListener !== "undefined") {
505
- this.debugLog("Using window as event target");
506
- return window;
507
- }
508
- const eventTarget = typeof EventTarget !== "undefined" ? new EventTarget() : void 0;
509
- if (typeof eventTarget === "undefined" || typeof eventTarget.addEventListener === "undefined") {
510
- this.debugLog("No event mechanism available, running in non-web environment");
511
- return {
512
- addEventListener: () => {},
513
- removeEventListener: () => {},
514
- dispatchEvent: () => false
515
- };
516
- }
517
- this.debugLog("Using new EventTarget as fallback");
518
- return eventTarget;
519
- }
520
- getPluginId() {
521
- return this.#pluginId;
522
- }
523
- dispatchCustomEventShim(eventName, detail) {
524
- try {
525
- const event = new Event(eventName, {
526
- detail
527
- });
528
- this.#eventTarget().dispatchEvent(event);
529
- } catch (e) {
530
- this.debugLog("Failed to dispatch shim event");
531
- }
532
- }
533
- dispatchCustomEvent(eventName, detail) {
534
- try {
535
- this.#eventTarget().dispatchEvent(new CustomEvent(eventName, {
536
- detail
537
- }));
538
- } catch (e) {
539
- this.dispatchCustomEventShim(eventName, detail);
540
- }
541
- }
542
- emitEventToBus(event) {
543
- this.debugLog("Emitting event to client bus", event);
544
- this.dispatchCustomEvent("tanstack-dispatch-event", event);
545
- }
546
- createEventPayload(eventSuffix, payload) {
547
- return {
548
- type: `${this.#pluginId}:${eventSuffix}`,
549
- payload,
550
- pluginId: this.#pluginId
551
- };
552
- }
553
- emit(eventSuffix, payload) {
554
- if (!this.#enabled) {
555
- this.debugLog("Event bus client is disabled, not emitting event", eventSuffix, payload);
556
- return;
557
- }
558
- if (this.#internalEventTarget) {
559
- this.debugLog("Emitting event to internal event target", eventSuffix, payload);
560
- this.#internalEventTarget.dispatchEvent(new CustomEvent(`${this.#pluginId}:${eventSuffix}`, {
561
- detail: this.createEventPayload(eventSuffix, payload)
562
- }));
563
- }
564
- if (this.#failedToConnect) {
565
- this.debugLog("Previously failed to connect, not emitting to bus");
566
- return;
567
- }
568
- if (!this.#connected) {
569
- this.debugLog("Bus not available, will be pushed as soon as connected");
570
- this.#queuedEvents.push(this.createEventPayload(eventSuffix, payload));
571
- if (typeof CustomEvent !== "undefined" && !this.#connecting) {
572
- this.#connectFunction();
573
- this.startConnectLoop();
574
- }
575
- return;
576
- }
577
- return this.emitEventToBus(this.createEventPayload(eventSuffix, payload));
578
- }
579
- on(eventSuffix, cb, options) {
580
- const withEventTarget = options?.withEventTarget ?? false;
581
- const eventName = `${this.#pluginId}:${eventSuffix}`;
582
- if (withEventTarget) {
583
- if (!this.#internalEventTarget) {
584
- this.#internalEventTarget = new EventTarget();
585
- }
586
- this.#internalEventTarget.addEventListener(eventName, e => {
587
- cb(e.detail);
588
- });
589
- }
590
- if (!this.#enabled) {
591
- this.debugLog("Event bus client is disabled, not registering event", eventName);
592
- return () => {};
593
- }
594
- const handler = e => {
595
- this.debugLog("Received event from bus", e.detail);
596
- cb(e.detail);
597
- };
598
- this.#eventTarget().addEventListener(eventName, handler);
599
- this.debugLog("Registered event to bus", eventName);
600
- return () => {
601
- if (withEventTarget) {
602
- this.#internalEventTarget?.removeEventListener(eventName, handler);
603
- }
604
- this.#eventTarget().removeEventListener(eventName, handler);
605
- };
606
- }
607
- onAll(cb) {
608
- if (!this.#enabled) {
609
- this.debugLog("Event bus client is disabled, not registering event");
610
- return () => {};
611
- }
612
- const handler = e => {
613
- const event = e.detail;
614
- cb(event);
615
- };
616
- this.#eventTarget().addEventListener("tanstack-devtools-global", handler);
617
- return () => this.#eventTarget().removeEventListener("tanstack-devtools-global", handler);
618
- }
619
- onAllPluginEvents(cb) {
620
- if (!this.#enabled) {
621
- this.debugLog("Event bus client is disabled, not registering event");
622
- return () => {};
623
- }
624
- const handler = e => {
625
- const event = e.detail;
626
- if (this.#pluginId && event.pluginId !== this.#pluginId) {
627
- return;
628
- }
629
- cb(event);
630
- };
631
- this.#eventTarget().addEventListener("tanstack-devtools-global", handler);
632
- return () => this.#eventTarget().removeEventListener("tanstack-devtools-global", handler);
633
- }
634
- }class FormEventClient extends EventClient {
635
- constructor() {
636
- super({
637
- pluginId: "form-devtools",
638
- reconnectEveryMs: 1e3
639
- });
640
- }
641
- }
642
- const formEventClient = new FormEventClient();function functionalUpdate(updater, input) {
643
- return typeof updater === "function" ? updater(input) : updater;
644
- }
645
- function getBy(obj, path) {
646
- const pathObj = makePathArray(path);
647
- return pathObj.reduce((current, pathPart) => {
648
- if (current === null) return null;
649
- if (typeof current !== "undefined") {
650
- return current[pathPart];
651
- }
652
- return void 0;
653
- }, obj);
654
- }
655
- function setBy(obj, _path, updater) {
656
- const path = makePathArray(_path);
657
- function doSet(parent) {
658
- if (!path.length) {
659
- return functionalUpdate(updater, parent);
660
- }
661
- const key = path.shift();
662
- if (typeof key === "string" || typeof key === "number" && !Array.isArray(parent)) {
663
- if (typeof parent === "object") {
664
- if (parent === null) {
665
- parent = {};
666
- }
667
- return {
668
- ...parent,
669
- [key]: doSet(parent[key])
670
- };
671
- }
672
- return {
673
- [key]: doSet()
674
- };
675
- }
676
- if (Array.isArray(parent) && typeof key === "number") {
677
- const prefix = parent.slice(0, key);
678
- return [...(prefix.length ? prefix : new Array(key)), doSet(parent[key]), ...parent.slice(key + 1)];
679
- }
680
- return [...new Array(key), doSet()];
681
- }
682
- return doSet(obj);
683
- }
684
- function deleteBy(obj, _path) {
685
- const path = makePathArray(_path);
686
- function doDelete(parent) {
687
- if (!parent) return;
688
- if (path.length === 1) {
689
- const finalPath = path[0];
690
- if (Array.isArray(parent) && typeof finalPath === "number") {
691
- return parent.filter((_, i) => i !== finalPath);
692
- }
693
- const {
694
- [finalPath]: remove,
695
- ...rest
696
- } = parent;
697
- return rest;
698
- }
699
- const key = path.shift();
700
- if (typeof key === "string" || typeof key === "number" && !Array.isArray(parent)) {
701
- if (typeof parent === "object") {
702
- return {
703
- ...parent,
704
- [key]: doDelete(parent[key])
705
- };
706
- }
707
- }
708
- if (typeof key === "number") {
709
- if (Array.isArray(parent)) {
710
- if (key >= parent.length) {
711
- return parent;
712
- }
713
- const prefix = parent.slice(0, key);
714
- return [...(prefix.length ? prefix : new Array(key)), doDelete(parent[key]), ...parent.slice(key + 1)];
715
- }
716
- }
717
- throw new Error("It seems we have created an infinite loop in deleteBy. ");
718
- }
719
- return doDelete(obj);
720
- }
721
- const reLineOfOnlyDigits = /^(\d+)$/gm;
722
- const reDigitsBetweenDots = /\.(\d+)(?=\.)/gm;
723
- const reStartWithDigitThenDot = /^(\d+)\./gm;
724
- const reDotWithDigitsToEnd = /\.(\d+$)/gm;
725
- const reMultipleDots = /\.{2,}/gm;
726
- const intPrefix = "__int__";
727
- const intReplace = `${intPrefix}$1`;
728
- function makePathArray(str) {
729
- if (Array.isArray(str)) {
730
- return [...str];
731
- }
732
- if (typeof str !== "string") {
733
- throw new Error("Path must be a string.");
734
- }
735
- return str.replace(/(^\[)|]/gm, "").replace(/\[/g, ".").replace(reLineOfOnlyDigits, intReplace).replace(reDigitsBetweenDots, `.${intReplace}.`).replace(reStartWithDigitThenDot, `${intReplace}.`).replace(reDotWithDigitsToEnd, `.${intReplace}`).replace(reMultipleDots, ".").split(".").map(d => {
736
- if (d.startsWith(intPrefix)) {
737
- const numStr = d.substring(intPrefix.length);
738
- const num = parseInt(numStr, 10);
739
- if (String(num) === numStr) {
740
- return num;
741
- }
742
- return numStr;
743
- }
744
- return d;
745
- });
746
- }
747
- function isNonEmptyArray(obj) {
748
- return !(Array.isArray(obj) && obj.length === 0);
749
- }
750
- function getSyncValidatorArray(cause, options) {
751
- const runValidation = props => {
752
- return props.validators.filter(Boolean).map(validator => {
753
- return {
754
- cause: validator.cause,
755
- validate: validator.fn
756
- };
757
- });
758
- };
759
- return options.validationLogic({
760
- form: options.form,
761
- validators: options.validators,
762
- event: {
763
- type: cause,
764
- async: false
765
- },
766
- runValidation
767
- });
768
- }
769
- function getAsyncValidatorArray(cause, options) {
770
- const {
771
- asyncDebounceMs
772
- } = options;
773
- const {
774
- onBlurAsyncDebounceMs,
775
- onChangeAsyncDebounceMs,
776
- onDynamicAsyncDebounceMs
777
- } = options.validators || {};
778
- const defaultDebounceMs = asyncDebounceMs ?? 0;
779
- const runValidation = props => {
780
- return props.validators.filter(Boolean).map(validator => {
781
- const validatorCause = validator?.cause || cause;
782
- let debounceMs = defaultDebounceMs;
783
- switch (validatorCause) {
784
- case "change":
785
- debounceMs = onChangeAsyncDebounceMs ?? defaultDebounceMs;
786
- break;
787
- case "blur":
788
- debounceMs = onBlurAsyncDebounceMs ?? defaultDebounceMs;
789
- break;
790
- case "dynamic":
791
- debounceMs = onDynamicAsyncDebounceMs ?? defaultDebounceMs;
792
- break;
793
- case "submit":
794
- debounceMs = 0;
795
- break;
796
- }
797
- if (cause === "submit") {
798
- debounceMs = 0;
799
- }
800
- return {
801
- cause: validatorCause,
802
- validate: validator.fn,
803
- debounceMs
804
- };
805
- });
806
- };
807
- return options.validationLogic({
808
- form: options.form,
809
- validators: options.validators,
810
- event: {
811
- type: cause,
812
- async: true
813
- },
814
- runValidation
815
- });
816
- }
817
- const isGlobalFormValidationError = error => {
818
- return !!error && typeof error === "object" && "fields" in error;
819
- };
820
- function evaluate(objA, objB) {
821
- if (Object.is(objA, objB)) {
822
- return true;
823
- }
824
- if (typeof objA !== "object" || objA === null || typeof objB !== "object" || objB === null) {
825
- return false;
826
- }
827
- if (objA instanceof Date && objB instanceof Date) {
828
- return objA.getTime() === objB.getTime();
829
- }
830
- if (objA instanceof Map && objB instanceof Map) {
831
- if (objA.size !== objB.size) return false;
832
- for (const [k, v] of objA) {
833
- if (!objB.has(k) || !Object.is(v, objB.get(k))) return false;
834
- }
835
- return true;
836
- }
837
- if (objA instanceof Set && objB instanceof Set) {
838
- if (objA.size !== objB.size) return false;
839
- for (const v of objA) {
840
- if (!objB.has(v)) return false;
841
- }
842
- return true;
843
- }
844
- const keysA = Object.keys(objA);
845
- const keysB = Object.keys(objB);
846
- if (keysA.length !== keysB.length) {
847
- return false;
848
- }
849
- for (const key of keysA) {
850
- if (!keysB.includes(key) || !evaluate(objA[key], objB[key])) {
851
- return false;
852
- }
853
- }
854
- return true;
855
- }
856
- const determineFormLevelErrorSourceAndValue = ({
857
- newFormValidatorError,
858
- isPreviousErrorFromFormValidator,
859
- previousErrorValue
860
- }) => {
861
- if (newFormValidatorError) {
862
- return {
863
- newErrorValue: newFormValidatorError,
864
- newSource: "form"
865
- };
866
- }
867
- if (isPreviousErrorFromFormValidator) {
868
- return {
869
- newErrorValue: void 0,
870
- newSource: void 0
871
- };
872
- }
873
- if (previousErrorValue) {
874
- return {
875
- newErrorValue: previousErrorValue,
876
- newSource: "field"
877
- };
878
- }
879
- return {
880
- newErrorValue: void 0,
881
- newSource: void 0
882
- };
883
- };
884
- const determineFieldLevelErrorSourceAndValue = ({
885
- formLevelError,
886
- fieldLevelError
887
- }) => {
888
- if (fieldLevelError) {
889
- return {
890
- newErrorValue: fieldLevelError,
891
- newSource: "field"
892
- };
893
- }
894
- if (formLevelError) {
895
- return {
896
- newErrorValue: formLevelError,
897
- newSource: "form"
898
- };
899
- }
900
- return {
901
- newErrorValue: void 0,
902
- newSource: void 0
903
- };
904
- };
905
- function mergeOpts(originalOpts, overrides) {
906
- if (originalOpts === void 0 || originalOpts === null) {
907
- return overrides;
908
- }
909
- return {
910
- ...originalOpts,
911
- ...overrides
912
- };
913
- }
914
- let IDX = 256;
915
- const HEX = [];
916
- let BUFFER;
917
- while (IDX--) {
918
- HEX[IDX] = (IDX + 256).toString(16).substring(1);
919
- }
920
- function uuid() {
921
- let i = 0;
922
- let num;
923
- let out = "";
924
- if (!BUFFER || IDX + 16 > 256) {
925
- BUFFER = new Array(256);
926
- i = 256;
927
- while (i--) {
928
- BUFFER[i] = 256 * Math.random() | 0;
929
- }
930
- i = 0;
931
- IDX = 0;
932
- }
933
- for (; i < 16; i++) {
934
- num = BUFFER[IDX + i];
935
- if (i === 6) out += HEX[num & 15 | 64];else if (i === 8) out += HEX[num & 63 | 128];else out += HEX[num];
936
- if (i & 1 && i > 1 && i < 11) out += "-";
937
- }
938
- IDX++;
939
- return out;
940
- }
941
- const throttleFormState = liteThrottle(form => formEventClient.emit("form-state", {
942
- id: form.formId,
943
- state: form.store.state
944
- }), {
945
- wait: 300
946
- });const defaultValidationLogic = props => {
947
- if (!props.validators) {
948
- return props.runValidation({
949
- validators: [],
950
- form: props.form
951
- });
952
- }
953
- const isAsync = props.event.async;
954
- const onMountValidator = isAsync ? void 0 : {
955
- fn: props.validators.onMount,
956
- cause: "mount"
957
- };
958
- const onChangeValidator = {
959
- fn: isAsync ? props.validators.onChangeAsync : props.validators.onChange,
960
- cause: "change"
961
- };
962
- const onBlurValidator = {
963
- fn: isAsync ? props.validators.onBlurAsync : props.validators.onBlur,
964
- cause: "blur"
965
- };
966
- const onSubmitValidator = {
967
- fn: isAsync ? props.validators.onSubmitAsync : props.validators.onSubmit,
968
- cause: "submit"
969
- };
970
- const onServerValidator = isAsync ? void 0 : {
971
- fn: () => void 0,
972
- cause: "server"
973
- };
974
- switch (props.event.type) {
975
- case "mount":
976
- {
977
- return props.runValidation({
978
- validators: [onMountValidator],
979
- form: props.form
980
- });
981
- }
982
- case "submit":
983
- {
984
- return props.runValidation({
985
- validators: [onChangeValidator, onBlurValidator, onSubmitValidator, onServerValidator],
986
- form: props.form
987
- });
988
- }
989
- case "server":
990
- {
991
- return props.runValidation({
992
- validators: [],
993
- form: props.form
994
- });
995
- }
996
- case "blur":
997
- {
998
- return props.runValidation({
999
- validators: [onBlurValidator, onServerValidator],
1000
- form: props.form
1001
- });
1002
- }
1003
- case "change":
1004
- {
1005
- return props.runValidation({
1006
- validators: [onChangeValidator, onServerValidator],
1007
- form: props.form
1008
- });
1009
- }
1010
- default:
1011
- {
1012
- throw new Error(`Unknown validation event type: ${props.event.type}`);
1013
- }
1014
- }
1015
- };function prefixSchemaToErrors(issues, formValue) {
1016
- const schema = /* @__PURE__ */new Map();
1017
- for (const issue of issues) {
1018
- const issuePath = issue.path ?? [];
1019
- let currentFormValue = formValue;
1020
- let path = "";
1021
- for (let i = 0; i < issuePath.length; i++) {
1022
- const pathSegment = issuePath[i];
1023
- if (pathSegment === void 0) continue;
1024
- const segment = typeof pathSegment === "object" ? pathSegment.key : pathSegment;
1025
- const segmentAsNumber = Number(segment);
1026
- if (Array.isArray(currentFormValue) && !Number.isNaN(segmentAsNumber)) {
1027
- path += `[${segmentAsNumber}]`;
1028
- } else {
1029
- path += (i > 0 ? "." : "") + String(segment);
1030
- }
1031
- if (typeof currentFormValue === "object" && currentFormValue !== null) {
1032
- currentFormValue = currentFormValue[segment];
1033
- } else {
1034
- currentFormValue = void 0;
1035
- }
1036
- }
1037
- schema.set(path, (schema.get(path) ?? []).concat(issue));
1038
- }
1039
- return Object.fromEntries(schema);
1040
- }
1041
- const transformFormIssues = (issues, formValue) => {
1042
- const schemaErrors = prefixSchemaToErrors(issues, formValue);
1043
- return {
1044
- form: schemaErrors,
1045
- fields: schemaErrors
1046
- };
1047
- };
1048
- const standardSchemaValidators = {
1049
- validate({
1050
- value,
1051
- validationSource
1052
- }, schema) {
1053
- const result = schema["~standard"].validate(value);
1054
- if (result instanceof Promise) {
1055
- throw new Error("async function passed to sync validator");
1056
- }
1057
- if (!result.issues) return;
1058
- if (validationSource === "field") return result.issues;
1059
- return transformFormIssues(result.issues, value);
1060
- },
1061
- async validateAsync({
1062
- value,
1063
- validationSource
1064
- }, schema) {
1065
- const result = await schema["~standard"].validate(value);
1066
- if (!result.issues) return;
1067
- if (validationSource === "field") return result.issues;
1068
- return transformFormIssues(result.issues, value);
1069
- }
1070
- };
1071
- const isStandardSchemaValidator = validator => !!validator && "~standard" in validator;const defaultFieldMeta = {
1072
- isValidating: false,
1073
- isTouched: false,
1074
- isBlurred: false,
1075
- isDirty: false,
1076
- isPristine: true,
1077
- isValid: true,
1078
- isDefaultValue: true,
1079
- errors: [],
1080
- errorMap: {},
1081
- errorSourceMap: {}
1082
- };
1083
- function metaHelper(formApi) {
1084
- function handleArrayMove(field, fromIndex, toIndex) {
1085
- const affectedFields = getAffectedFields(field, fromIndex, "move", toIndex);
1086
- const startIndex = Math.min(fromIndex, toIndex);
1087
- const endIndex = Math.max(fromIndex, toIndex);
1088
- for (let i = startIndex; i <= endIndex; i++) {
1089
- affectedFields.push(getFieldPath(field, i));
1090
- }
1091
- const fromFields = Object.keys(formApi.fieldInfo).reduce((fieldMap, fieldKey) => {
1092
- if (fieldKey.startsWith(getFieldPath(field, fromIndex))) {
1093
- fieldMap.set(fieldKey, formApi.getFieldMeta(fieldKey));
1094
- }
1095
- return fieldMap;
1096
- }, /* @__PURE__ */new Map());
1097
- shiftMeta(affectedFields, fromIndex < toIndex ? "up" : "down");
1098
- Object.keys(formApi.fieldInfo).filter(fieldKey => fieldKey.startsWith(getFieldPath(field, toIndex))).forEach(fieldKey => {
1099
- const fromKey = fieldKey.replace(getFieldPath(field, toIndex), getFieldPath(field, fromIndex));
1100
- const fromMeta = fromFields.get(fromKey);
1101
- if (fromMeta) {
1102
- formApi.setFieldMeta(fieldKey, fromMeta);
1103
- }
1104
- });
1105
- }
1106
- function handleArrayRemove(field, index) {
1107
- const affectedFields = getAffectedFields(field, index, "remove");
1108
- shiftMeta(affectedFields, "up");
1109
- }
1110
- function handleArraySwap(field, index, secondIndex) {
1111
- const affectedFields = getAffectedFields(field, index, "swap", secondIndex);
1112
- affectedFields.forEach(fieldKey => {
1113
- if (!fieldKey.toString().startsWith(getFieldPath(field, index))) {
1114
- return;
1115
- }
1116
- const swappedKey = fieldKey.toString().replace(getFieldPath(field, index), getFieldPath(field, secondIndex));
1117
- const [meta1, meta2] = [formApi.getFieldMeta(fieldKey), formApi.getFieldMeta(swappedKey)];
1118
- if (meta1) formApi.setFieldMeta(swappedKey, meta1);
1119
- if (meta2) formApi.setFieldMeta(fieldKey, meta2);
1120
- });
1121
- }
1122
- function handleArrayInsert(field, insertIndex) {
1123
- const affectedFields = getAffectedFields(field, insertIndex, "insert");
1124
- shiftMeta(affectedFields, "down");
1125
- affectedFields.forEach(fieldKey => {
1126
- if (fieldKey.toString().startsWith(getFieldPath(field, insertIndex))) {
1127
- formApi.setFieldMeta(fieldKey, getEmptyFieldMeta());
1128
- }
1129
- });
1130
- }
1131
- function getFieldPath(field, index) {
1132
- return `${field}[${index}]`;
1133
- }
1134
- function getAffectedFields(field, index, mode, secondIndex) {
1135
- const affectedFieldKeys = [getFieldPath(field, index)];
1136
- switch (mode) {
1137
- case "swap":
1138
- affectedFieldKeys.push(getFieldPath(field, secondIndex));
1139
- break;
1140
- case "move":
1141
- {
1142
- const [startIndex, endIndex] = [Math.min(index, secondIndex), Math.max(index, secondIndex)];
1143
- for (let i = startIndex; i <= endIndex; i++) {
1144
- affectedFieldKeys.push(getFieldPath(field, i));
1145
- }
1146
- break;
1147
- }
1148
- default:
1149
- {
1150
- const currentValue = formApi.getFieldValue(field);
1151
- const fieldItems = Array.isArray(currentValue) ? currentValue.length : 0;
1152
- for (let i = index + 1; i < fieldItems; i++) {
1153
- affectedFieldKeys.push(getFieldPath(field, i));
1154
- }
1155
- break;
1156
- }
1157
- }
1158
- return Object.keys(formApi.fieldInfo).filter(fieldKey => affectedFieldKeys.some(key => fieldKey.startsWith(key)));
1159
- }
1160
- function updateIndex(fieldKey, direction) {
1161
- return fieldKey.replace(/\[(\d+)\]/, (_, num) => {
1162
- const currIndex = parseInt(num, 10);
1163
- const newIndex = direction === "up" ? currIndex + 1 : Math.max(0, currIndex - 1);
1164
- return `[${newIndex}]`;
1165
- });
1166
- }
1167
- function shiftMeta(fields, direction) {
1168
- const sortedFields = direction === "up" ? fields : [...fields].reverse();
1169
- sortedFields.forEach(fieldKey => {
1170
- const nextFieldKey = updateIndex(fieldKey.toString(), direction);
1171
- const nextFieldMeta = formApi.getFieldMeta(nextFieldKey);
1172
- if (nextFieldMeta) {
1173
- formApi.setFieldMeta(fieldKey, nextFieldMeta);
1174
- } else {
1175
- formApi.setFieldMeta(fieldKey, getEmptyFieldMeta());
1176
- }
1177
- });
1178
- }
1179
- const getEmptyFieldMeta = () => defaultFieldMeta;
1180
- return {
1181
- handleArrayMove,
1182
- handleArrayRemove,
1183
- handleArraySwap,
1184
- handleArrayInsert
1185
- };
1186
- }function getDefaultFormState(defaultState) {
1187
- return {
1188
- values: defaultState.values ?? {},
1189
- errorMap: defaultState.errorMap ?? {},
1190
- fieldMetaBase: defaultState.fieldMetaBase ?? {},
1191
- isSubmitted: defaultState.isSubmitted ?? false,
1192
- isSubmitting: defaultState.isSubmitting ?? false,
1193
- isValidating: defaultState.isValidating ?? false,
1194
- submissionAttempts: defaultState.submissionAttempts ?? 0,
1195
- isSubmitSuccessful: defaultState.isSubmitSuccessful ?? false,
1196
- validationMetaMap: defaultState.validationMetaMap ?? {
1197
- onChange: void 0,
1198
- onBlur: void 0,
1199
- onSubmit: void 0,
1200
- onMount: void 0,
1201
- onServer: void 0,
1202
- onDynamic: void 0
1203
- }
1204
- };
1205
- }
1206
- class FormApi {
1207
- /**
1208
- * Constructs a new `FormApi` instance with the given form options.
1209
- */
1210
- constructor(opts) {
1211
- this.options = {};
1212
- this.fieldInfo = {};
1213
- this.prevTransformArray = [];
1214
- this.mount = () => {
1215
- const cleanupFieldMetaDerived = this.fieldMetaDerived.mount();
1216
- const cleanupStoreDerived = this.store.mount();
1217
- const cleanupDevtoolBroadcast = this.store.subscribe(() => {
1218
- throttleFormState(this);
1219
- });
1220
- const cleanupFormStateListener = formEventClient.on("request-form-state", e => {
1221
- if (e.payload.id === this._formId) {
1222
- formEventClient.emit("form-api", {
1223
- id: this._formId,
1224
- state: this.store.state,
1225
- options: this.options
1226
- });
1227
- }
1228
- });
1229
- const cleanupFormResetListener = formEventClient.on("request-form-reset", e => {
1230
- if (e.payload.id === this._formId) {
1231
- this.reset();
1232
- }
1233
- });
1234
- const cleanupFormForceSubmitListener = formEventClient.on("request-form-force-submit", e => {
1235
- if (e.payload.id === this._formId) {
1236
- this._devtoolsSubmissionOverride = true;
1237
- this.handleSubmit();
1238
- this._devtoolsSubmissionOverride = false;
1239
- }
1240
- });
1241
- const cleanup = () => {
1242
- cleanupFormForceSubmitListener();
1243
- cleanupFormResetListener();
1244
- cleanupFormStateListener();
1245
- cleanupDevtoolBroadcast();
1246
- cleanupFieldMetaDerived();
1247
- cleanupStoreDerived();
1248
- formEventClient.emit("form-unmounted", {
1249
- id: this._formId
1250
- });
1251
- };
1252
- this.options.listeners?.onMount?.({
1253
- formApi: this
1254
- });
1255
- const {
1256
- onMount
1257
- } = this.options.validators || {};
1258
- formEventClient.emit("form-api", {
1259
- id: this._formId,
1260
- state: this.store.state,
1261
- options: this.options
1262
- });
1263
- if (!onMount) return cleanup;
1264
- this.validateSync("mount");
1265
- return cleanup;
1266
- };
1267
- this.update = options => {
1268
- if (!options) return;
1269
- const oldOptions = this.options;
1270
- this.options = options;
1271
- const shouldUpdateReeval = !!options.transform?.deps?.some((val, i) => val !== this.prevTransformArray[i]);
1272
- const shouldUpdateValues = options.defaultValues && !evaluate(options.defaultValues, oldOptions.defaultValues) && !this.state.isTouched;
1273
- const shouldUpdateState = !evaluate(options.defaultState, oldOptions.defaultState) && !this.state.isTouched;
1274
- if (!shouldUpdateValues && !shouldUpdateState && !shouldUpdateReeval) return;
1275
- batch(() => {
1276
- this.baseStore.setState(() => getDefaultFormState(Object.assign({}, this.state, shouldUpdateState ? options.defaultState : {}, shouldUpdateValues ? {
1277
- values: options.defaultValues
1278
- } : {}, shouldUpdateReeval ? {
1279
- _force_re_eval: !this.state._force_re_eval
1280
- } : {})));
1281
- });
1282
- formEventClient.emit("form-api", {
1283
- id: this._formId,
1284
- state: this.store.state,
1285
- options: this.options
1286
- });
1287
- };
1288
- this.reset = (values, opts2) => {
1289
- const {
1290
- fieldMeta: currentFieldMeta
1291
- } = this.state;
1292
- const fieldMetaBase = this.resetFieldMeta(currentFieldMeta);
1293
- if (values && !opts2?.keepDefaultValues) {
1294
- this.options = {
1295
- ...this.options,
1296
- defaultValues: values
1297
- };
1298
- }
1299
- this.baseStore.setState(() => getDefaultFormState({
1300
- ...this.options.defaultState,
1301
- values: values ?? this.options.defaultValues ?? this.options.defaultState?.values,
1302
- fieldMetaBase
1303
- }));
1304
- };
1305
- this.validateAllFields = async cause => {
1306
- const fieldValidationPromises = [];
1307
- batch(() => {
1308
- void Object.values(this.fieldInfo).forEach(field => {
1309
- if (!field.instance) return;
1310
- const fieldInstance = field.instance;
1311
- fieldValidationPromises.push(
1312
- // Remember, `validate` is either a sync operation or a promise
1313
- Promise.resolve().then(() => fieldInstance.validate(cause, {
1314
- skipFormValidation: true
1315
- })));
1316
- if (!field.instance.state.meta.isTouched) {
1317
- field.instance.setMeta(prev => ({
1318
- ...prev,
1319
- isTouched: true
1320
- }));
1321
- }
1322
- });
1323
- });
1324
- const fieldErrorMapMap = await Promise.all(fieldValidationPromises);
1325
- return fieldErrorMapMap.flat();
1326
- };
1327
- this.validateArrayFieldsStartingFrom = async (field, index, cause) => {
1328
- const currentValue = this.getFieldValue(field);
1329
- const lastIndex = Array.isArray(currentValue) ? Math.max(currentValue.length - 1, 0) : null;
1330
- const fieldKeysToValidate = [`${field}[${index}]`];
1331
- for (let i = index + 1; i <= (lastIndex ?? 0); i++) {
1332
- fieldKeysToValidate.push(`${field}[${i}]`);
1333
- }
1334
- const fieldsToValidate = Object.keys(this.fieldInfo).filter(fieldKey => fieldKeysToValidate.some(key => fieldKey.startsWith(key)));
1335
- const fieldValidationPromises = [];
1336
- batch(() => {
1337
- fieldsToValidate.forEach(nestedField => {
1338
- fieldValidationPromises.push(Promise.resolve().then(() => this.validateField(nestedField, cause)));
1339
- });
1340
- });
1341
- const fieldErrorMapMap = await Promise.all(fieldValidationPromises);
1342
- return fieldErrorMapMap.flat();
1343
- };
1344
- this.validateField = (field, cause) => {
1345
- const fieldInstance = this.fieldInfo[field]?.instance;
1346
- if (!fieldInstance) {
1347
- const {
1348
- hasErrored
1349
- } = this.validateSync(cause);
1350
- if (hasErrored && !this.options.asyncAlways) {
1351
- return this.getFieldMeta(field)?.errors ?? [];
1352
- }
1353
- return this.validateAsync(cause).then(() => {
1354
- return this.getFieldMeta(field)?.errors ?? [];
1355
- });
1356
- }
1357
- if (!fieldInstance.state.meta.isTouched) {
1358
- fieldInstance.setMeta(prev => ({
1359
- ...prev,
1360
- isTouched: true
1361
- }));
1362
- }
1363
- return fieldInstance.validate(cause);
1364
- };
1365
- this.validateSync = cause => {
1366
- const validates = getSyncValidatorArray(cause, {
1367
- ...this.options,
1368
- form: this,
1369
- validationLogic: this.options.validationLogic || defaultValidationLogic
1370
- });
1371
- let hasErrored = false;
1372
- const currentValidationErrorMap = {};
1373
- batch(() => {
1374
- for (const validateObj of validates) {
1375
- if (!validateObj.validate) continue;
1376
- const rawError = this.runValidator({
1377
- validate: validateObj.validate,
1378
- value: {
1379
- value: this.state.values,
1380
- formApi: this,
1381
- validationSource: "form"
1382
- },
1383
- type: "validate"
1384
- });
1385
- const {
1386
- formError,
1387
- fieldErrors
1388
- } = normalizeError$1(rawError);
1389
- const errorMapKey = getErrorMapKey$1(validateObj.cause);
1390
- const allFieldsToProcess = /* @__PURE__ */new Set([...Object.keys(this.state.fieldMeta), ...Object.keys(fieldErrors || {})]);
1391
- for (const field of allFieldsToProcess) {
1392
- if (this.baseStore.state.fieldMetaBase[field] === void 0 && !fieldErrors?.[field]) {
1393
- continue;
1394
- }
1395
- const fieldMeta = this.getFieldMeta(field) ?? defaultFieldMeta;
1396
- const {
1397
- errorMap: currentErrorMap,
1398
- errorSourceMap: currentErrorMapSource
1399
- } = fieldMeta;
1400
- const newFormValidatorError = fieldErrors?.[field];
1401
- const {
1402
- newErrorValue,
1403
- newSource
1404
- } = determineFormLevelErrorSourceAndValue({
1405
- newFormValidatorError,
1406
- isPreviousErrorFromFormValidator:
1407
- // These conditional checks are required, otherwise we get runtime errors.
1408
- // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
1409
- currentErrorMapSource?.[errorMapKey] === "form",
1410
- // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
1411
- previousErrorValue: currentErrorMap?.[errorMapKey]
1412
- });
1413
- if (newSource === "form") {
1414
- currentValidationErrorMap[field] = {
1415
- ...currentValidationErrorMap[field],
1416
- [errorMapKey]: newFormValidatorError
1417
- };
1418
- }
1419
- if (currentErrorMap?.[errorMapKey] !== newErrorValue) {
1420
- this.setFieldMeta(field, (prev = defaultFieldMeta) => ({
1421
- ...prev,
1422
- errorMap: {
1423
- ...prev.errorMap,
1424
- [errorMapKey]: newErrorValue
1425
- },
1426
- errorSourceMap: {
1427
- ...prev.errorSourceMap,
1428
- [errorMapKey]: newSource
1429
- }
1430
- }));
1431
- }
1432
- }
1433
- if (this.state.errorMap?.[errorMapKey] !== formError) {
1434
- this.baseStore.setState(prev => ({
1435
- ...prev,
1436
- errorMap: {
1437
- ...prev.errorMap,
1438
- [errorMapKey]: formError
1439
- }
1440
- }));
1441
- }
1442
- if (formError || fieldErrors) {
1443
- hasErrored = true;
1444
- }
1445
- }
1446
- const submitErrKey = getErrorMapKey$1("submit");
1447
- if (
1448
- // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
1449
- this.state.errorMap?.[submitErrKey] && cause !== "submit" && !hasErrored) {
1450
- this.baseStore.setState(prev => ({
1451
- ...prev,
1452
- errorMap: {
1453
- ...prev.errorMap,
1454
- [submitErrKey]: void 0
1455
- }
1456
- }));
1457
- }
1458
- const serverErrKey = getErrorMapKey$1("server");
1459
- if (
1460
- // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
1461
- this.state.errorMap?.[serverErrKey] && cause !== "server" && !hasErrored) {
1462
- this.baseStore.setState(prev => ({
1463
- ...prev,
1464
- errorMap: {
1465
- ...prev.errorMap,
1466
- [serverErrKey]: void 0
1467
- }
1468
- }));
1469
- }
1470
- });
1471
- return {
1472
- hasErrored,
1473
- fieldsErrorMap: currentValidationErrorMap
1474
- };
1475
- };
1476
- this.validateAsync = async cause => {
1477
- const validates = getAsyncValidatorArray(cause, {
1478
- ...this.options,
1479
- form: this,
1480
- validationLogic: this.options.validationLogic || defaultValidationLogic
1481
- });
1482
- if (!this.state.isFormValidating) {
1483
- this.baseStore.setState(prev => ({
1484
- ...prev,
1485
- isFormValidating: true
1486
- }));
1487
- }
1488
- const promises = [];
1489
- let fieldErrorsFromFormValidators;
1490
- for (const validateObj of validates) {
1491
- if (!validateObj.validate) continue;
1492
- const key = getErrorMapKey$1(validateObj.cause);
1493
- const fieldValidatorMeta = this.state.validationMetaMap[key];
1494
- fieldValidatorMeta?.lastAbortController.abort();
1495
- const controller = new AbortController();
1496
- this.state.validationMetaMap[key] = {
1497
- lastAbortController: controller
1498
- };
1499
- promises.push(new Promise(async resolve => {
1500
- let rawError;
1501
- try {
1502
- rawError = await new Promise((rawResolve, rawReject) => {
1503
- setTimeout(async () => {
1504
- if (controller.signal.aborted) return rawResolve(void 0);
1505
- try {
1506
- rawResolve(await this.runValidator({
1507
- validate: validateObj.validate,
1508
- value: {
1509
- value: this.state.values,
1510
- formApi: this,
1511
- validationSource: "form",
1512
- signal: controller.signal
1513
- },
1514
- type: "validateAsync"
1515
- }));
1516
- } catch (e) {
1517
- rawReject(e);
1518
- }
1519
- }, validateObj.debounceMs);
1520
- });
1521
- } catch (e) {
1522
- rawError = e;
1523
- }
1524
- const {
1525
- formError,
1526
- fieldErrors: fieldErrorsFromNormalizeError
1527
- } = normalizeError$1(rawError);
1528
- if (fieldErrorsFromNormalizeError) {
1529
- fieldErrorsFromFormValidators = fieldErrorsFromFormValidators ? {
1530
- ...fieldErrorsFromFormValidators,
1531
- ...fieldErrorsFromNormalizeError
1532
- } : fieldErrorsFromNormalizeError;
1533
- }
1534
- const errorMapKey = getErrorMapKey$1(validateObj.cause);
1535
- for (const field of Object.keys(this.state.fieldMeta)) {
1536
- if (this.baseStore.state.fieldMetaBase[field] === void 0) {
1537
- continue;
1538
- }
1539
- const fieldMeta = this.getFieldMeta(field);
1540
- if (!fieldMeta) continue;
1541
- const {
1542
- errorMap: currentErrorMap,
1543
- errorSourceMap: currentErrorMapSource
1544
- } = fieldMeta;
1545
- const newFormValidatorError = fieldErrorsFromFormValidators?.[field];
1546
- const {
1547
- newErrorValue,
1548
- newSource
1549
- } = determineFormLevelErrorSourceAndValue({
1550
- newFormValidatorError,
1551
- isPreviousErrorFromFormValidator:
1552
- // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
1553
- currentErrorMapSource?.[errorMapKey] === "form",
1554
- // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
1555
- previousErrorValue: currentErrorMap?.[errorMapKey]
1556
- });
1557
- if (
1558
- // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
1559
- currentErrorMap?.[errorMapKey] !== newErrorValue) {
1560
- this.setFieldMeta(field, prev => ({
1561
- ...prev,
1562
- errorMap: {
1563
- ...prev.errorMap,
1564
- [errorMapKey]: newErrorValue
1565
- },
1566
- errorSourceMap: {
1567
- ...prev.errorSourceMap,
1568
- [errorMapKey]: newSource
1569
- }
1570
- }));
1571
- }
1572
- }
1573
- this.baseStore.setState(prev => ({
1574
- ...prev,
1575
- errorMap: {
1576
- ...prev.errorMap,
1577
- [errorMapKey]: formError
1578
- }
1579
- }));
1580
- resolve(fieldErrorsFromFormValidators ? {
1581
- fieldErrors: fieldErrorsFromFormValidators,
1582
- errorMapKey
1583
- } : void 0);
1584
- }));
1585
- }
1586
- let results = [];
1587
- const fieldsErrorMap = {};
1588
- if (promises.length) {
1589
- results = await Promise.all(promises);
1590
- for (const fieldValidationResult of results) {
1591
- if (fieldValidationResult?.fieldErrors) {
1592
- const {
1593
- errorMapKey
1594
- } = fieldValidationResult;
1595
- for (const [field, fieldError] of Object.entries(fieldValidationResult.fieldErrors)) {
1596
- const oldErrorMap = fieldsErrorMap[field] || {};
1597
- const newErrorMap = {
1598
- ...oldErrorMap,
1599
- [errorMapKey]: fieldError
1600
- };
1601
- fieldsErrorMap[field] = newErrorMap;
1602
- }
1603
- }
1604
- }
1605
- }
1606
- this.baseStore.setState(prev => ({
1607
- ...prev,
1608
- isFormValidating: false
1609
- }));
1610
- return fieldsErrorMap;
1611
- };
1612
- this.validate = cause => {
1613
- const {
1614
- hasErrored,
1615
- fieldsErrorMap
1616
- } = this.validateSync(cause);
1617
- if (hasErrored && !this.options.asyncAlways) {
1618
- return fieldsErrorMap;
1619
- }
1620
- return this.validateAsync(cause);
1621
- };
1622
- this._handleSubmit = async submitMeta => {
1623
- this.baseStore.setState(old => ({
1624
- ...old,
1625
- // Submission attempts mark the form as not submitted
1626
- isSubmitted: false,
1627
- // Count submission attempts
1628
- submissionAttempts: old.submissionAttempts + 1,
1629
- isSubmitSuccessful: false
1630
- // Reset isSubmitSuccessful at the start of submission
1631
- }));
1632
- batch(() => {
1633
- void Object.values(this.fieldInfo).forEach(field => {
1634
- if (!field.instance) return;
1635
- if (!field.instance.state.meta.isTouched) {
1636
- field.instance.setMeta(prev => ({
1637
- ...prev,
1638
- isTouched: true
1639
- }));
1640
- }
1641
- });
1642
- });
1643
- const submitMetaArg = submitMeta ?? this.options.onSubmitMeta;
1644
- if (!this.state.canSubmit && !this._devtoolsSubmissionOverride) {
1645
- this.options.onSubmitInvalid?.({
1646
- value: this.state.values,
1647
- formApi: this,
1648
- meta: submitMetaArg
1649
- });
1650
- return;
1651
- }
1652
- this.baseStore.setState(d => ({
1653
- ...d,
1654
- isSubmitting: true
1655
- }));
1656
- const done = () => {
1657
- this.baseStore.setState(prev => ({
1658
- ...prev,
1659
- isSubmitting: false
1660
- }));
1661
- };
1662
- await this.validateAllFields("submit");
1663
- if (!this.state.isFieldsValid) {
1664
- done();
1665
- this.options.onSubmitInvalid?.({
1666
- value: this.state.values,
1667
- formApi: this,
1668
- meta: submitMetaArg
1669
- });
1670
- formEventClient.emit("form-submission", {
1671
- id: this._formId,
1672
- submissionAttempt: this.state.submissionAttempts,
1673
- successful: false,
1674
- stage: "validateAllFields",
1675
- errors: Object.values(this.state.fieldMeta).map(meta => meta.errors).flat()
1676
- });
1677
- return;
1678
- }
1679
- await this.validate("submit");
1680
- if (!this.state.isValid) {
1681
- done();
1682
- this.options.onSubmitInvalid?.({
1683
- value: this.state.values,
1684
- formApi: this,
1685
- meta: submitMetaArg
1686
- });
1687
- formEventClient.emit("form-submission", {
1688
- id: this._formId,
1689
- submissionAttempt: this.state.submissionAttempts,
1690
- successful: false,
1691
- stage: "validate",
1692
- errors: this.state.errors
1693
- });
1694
- return;
1695
- }
1696
- batch(() => {
1697
- void Object.values(this.fieldInfo).forEach(field => {
1698
- field.instance?.options.listeners?.onSubmit?.({
1699
- value: field.instance.state.value,
1700
- fieldApi: field.instance
1701
- });
1702
- });
1703
- });
1704
- this.options.listeners?.onSubmit?.({
1705
- formApi: this,
1706
- meta: submitMetaArg
1707
- });
1708
- try {
1709
- await this.options.onSubmit?.({
1710
- value: this.state.values,
1711
- formApi: this,
1712
- meta: submitMetaArg
1713
- });
1714
- batch(() => {
1715
- this.baseStore.setState(prev => ({
1716
- ...prev,
1717
- isSubmitted: true,
1718
- isSubmitSuccessful: true
1719
- // Set isSubmitSuccessful to true on successful submission
1720
- }));
1721
- formEventClient.emit("form-submission", {
1722
- id: this._formId,
1723
- submissionAttempt: this.state.submissionAttempts,
1724
- successful: true
1725
- });
1726
- done();
1727
- });
1728
- } catch (err) {
1729
- this.baseStore.setState(prev => ({
1730
- ...prev,
1731
- isSubmitSuccessful: false
1732
- // Ensure isSubmitSuccessful is false if an error occurs
1733
- }));
1734
- formEventClient.emit("form-submission", {
1735
- id: this._formId,
1736
- submissionAttempt: this.state.submissionAttempts,
1737
- successful: false,
1738
- stage: "inflight",
1739
- onError: err
1740
- });
1741
- done();
1742
- throw err;
1743
- }
1744
- };
1745
- this.getFieldValue = field => getBy(this.state.values, field);
1746
- this.getFieldMeta = field => {
1747
- return this.state.fieldMeta[field];
1748
- };
1749
- this.getFieldInfo = field => {
1750
- return this.fieldInfo[field] ||= {
1751
- instance: null,
1752
- validationMetaMap: {
1753
- onChange: void 0,
1754
- onBlur: void 0,
1755
- onSubmit: void 0,
1756
- onMount: void 0,
1757
- onServer: void 0,
1758
- onDynamic: void 0
1759
- }
1760
- };
1761
- };
1762
- this.setFieldMeta = (field, updater) => {
1763
- this.baseStore.setState(prev => {
1764
- return {
1765
- ...prev,
1766
- fieldMetaBase: {
1767
- ...prev.fieldMetaBase,
1768
- [field]: functionalUpdate(updater, prev.fieldMetaBase[field])
1769
- }
1770
- };
1771
- });
1772
- };
1773
- this.resetFieldMeta = fieldMeta => {
1774
- return Object.keys(fieldMeta).reduce((acc, key) => {
1775
- const fieldKey = key;
1776
- acc[fieldKey] = defaultFieldMeta;
1777
- return acc;
1778
- }, {});
1779
- };
1780
- this.setFieldValue = (field, updater, opts2) => {
1781
- const dontUpdateMeta = opts2?.dontUpdateMeta ?? false;
1782
- const dontRunListeners = opts2?.dontRunListeners ?? false;
1783
- const dontValidate = opts2?.dontValidate ?? false;
1784
- batch(() => {
1785
- if (!dontUpdateMeta) {
1786
- this.setFieldMeta(field, prev => ({
1787
- ...prev,
1788
- isTouched: true,
1789
- isDirty: true,
1790
- errorMap: {
1791
- // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
1792
- ...prev?.errorMap,
1793
- onMount: void 0
1794
- }
1795
- }));
1796
- }
1797
- this.baseStore.setState(prev => {
1798
- return {
1799
- ...prev,
1800
- values: setBy(prev.values, field, updater)
1801
- };
1802
- });
1803
- });
1804
- if (!dontRunListeners) {
1805
- this.getFieldInfo(field).instance?.triggerOnChangeListener();
1806
- }
1807
- if (!dontValidate) {
1808
- this.validateField(field, "change");
1809
- }
1810
- };
1811
- this.deleteField = field => {
1812
- const subFieldsToDelete = Object.keys(this.fieldInfo).filter(f => {
1813
- const fieldStr = field.toString();
1814
- return f !== fieldStr && f.startsWith(fieldStr);
1815
- });
1816
- const fieldsToDelete = [...subFieldsToDelete, field];
1817
- this.baseStore.setState(prev => {
1818
- const newState = {
1819
- ...prev
1820
- };
1821
- fieldsToDelete.forEach(f => {
1822
- newState.values = deleteBy(newState.values, f);
1823
- delete this.fieldInfo[f];
1824
- delete newState.fieldMetaBase[f];
1825
- });
1826
- return newState;
1827
- });
1828
- };
1829
- this.pushFieldValue = (field, value, options) => {
1830
- this.setFieldValue(field, prev => [...(Array.isArray(prev) ? prev : []), value], options);
1831
- };
1832
- this.insertFieldValue = async (field, index, value, options) => {
1833
- this.setFieldValue(field, prev => {
1834
- return [...prev.slice(0, index), value, ...prev.slice(index)];
1835
- }, mergeOpts(options, {
1836
- dontValidate: true
1837
- }));
1838
- const dontValidate = options?.dontValidate ?? false;
1839
- if (!dontValidate) {
1840
- await this.validateField(field, "change");
1841
- }
1842
- metaHelper(this).handleArrayInsert(field, index);
1843
- if (!dontValidate) {
1844
- await this.validateArrayFieldsStartingFrom(field, index, "change");
1845
- }
1846
- };
1847
- this.replaceFieldValue = async (field, index, value, options) => {
1848
- this.setFieldValue(field, prev => {
1849
- return prev.map((d, i) => i === index ? value : d);
1850
- }, mergeOpts(options, {
1851
- dontValidate: true
1852
- }));
1853
- const dontValidate = options?.dontValidate ?? false;
1854
- if (!dontValidate) {
1855
- await this.validateField(field, "change");
1856
- await this.validateArrayFieldsStartingFrom(field, index, "change");
1857
- }
1858
- };
1859
- this.removeFieldValue = async (field, index, options) => {
1860
- const fieldValue = this.getFieldValue(field);
1861
- const lastIndex = Array.isArray(fieldValue) ? Math.max(fieldValue.length - 1, 0) : null;
1862
- this.setFieldValue(field, prev => {
1863
- return prev.filter((_d, i) => i !== index);
1864
- }, mergeOpts(options, {
1865
- dontValidate: true
1866
- }));
1867
- metaHelper(this).handleArrayRemove(field, index);
1868
- if (lastIndex !== null) {
1869
- const start = `${field}[${lastIndex}]`;
1870
- this.deleteField(start);
1871
- }
1872
- const dontValidate = options?.dontValidate ?? false;
1873
- if (!dontValidate) {
1874
- await this.validateField(field, "change");
1875
- await this.validateArrayFieldsStartingFrom(field, index, "change");
1876
- }
1877
- };
1878
- this.swapFieldValues = (field, index1, index2, options) => {
1879
- this.setFieldValue(field, prev => {
1880
- const prev1 = prev[index1];
1881
- const prev2 = prev[index2];
1882
- return setBy(setBy(prev, `${index1}`, prev2), `${index2}`, prev1);
1883
- }, mergeOpts(options, {
1884
- dontValidate: true
1885
- }));
1886
- metaHelper(this).handleArraySwap(field, index1, index2);
1887
- const dontValidate = options?.dontValidate ?? false;
1888
- if (!dontValidate) {
1889
- this.validateField(field, "change");
1890
- this.validateField(`${field}[${index1}]`, "change");
1891
- this.validateField(`${field}[${index2}]`, "change");
1892
- }
1893
- };
1894
- this.moveFieldValues = (field, index1, index2, options) => {
1895
- this.setFieldValue(field, prev => {
1896
- const next = [...prev];
1897
- next.splice(index2, 0, next.splice(index1, 1)[0]);
1898
- return next;
1899
- }, mergeOpts(options, {
1900
- dontValidate: true
1901
- }));
1902
- metaHelper(this).handleArrayMove(field, index1, index2);
1903
- const dontValidate = options?.dontValidate ?? false;
1904
- if (!dontValidate) {
1905
- this.validateField(field, "change");
1906
- this.validateField(`${field}[${index1}]`, "change");
1907
- this.validateField(`${field}[${index2}]`, "change");
1908
- }
1909
- };
1910
- this.clearFieldValues = (field, options) => {
1911
- const fieldValue = this.getFieldValue(field);
1912
- const lastIndex = Array.isArray(fieldValue) ? Math.max(fieldValue.length - 1, 0) : null;
1913
- this.setFieldValue(field, [], mergeOpts(options, {
1914
- dontValidate: true
1915
- }));
1916
- if (lastIndex !== null) {
1917
- for (let i = 0; i <= lastIndex; i++) {
1918
- const fieldKey = `${field}[${i}]`;
1919
- this.deleteField(fieldKey);
1920
- }
1921
- }
1922
- const dontValidate = options?.dontValidate ?? false;
1923
- if (!dontValidate) {
1924
- this.validateField(field, "change");
1925
- }
1926
- };
1927
- this.resetField = field => {
1928
- this.baseStore.setState(prev => {
1929
- return {
1930
- ...prev,
1931
- fieldMetaBase: {
1932
- ...prev.fieldMetaBase,
1933
- [field]: defaultFieldMeta
1934
- },
1935
- values: this.options.defaultValues ? setBy(prev.values, field, getBy(this.options.defaultValues, field)) : prev.values
1936
- };
1937
- });
1938
- };
1939
- this.setErrorMap = errorMap => {
1940
- batch(() => {
1941
- Object.entries(errorMap).forEach(([key, value]) => {
1942
- const errorMapKey = key;
1943
- if (isGlobalFormValidationError(value)) {
1944
- const {
1945
- formError,
1946
- fieldErrors
1947
- } = normalizeError$1(value);
1948
- for (const fieldName of Object.keys(this.fieldInfo)) {
1949
- const fieldMeta = this.getFieldMeta(fieldName);
1950
- if (!fieldMeta) continue;
1951
- this.setFieldMeta(fieldName, prev => ({
1952
- ...prev,
1953
- errorMap: {
1954
- ...prev.errorMap,
1955
- [errorMapKey]: fieldErrors?.[fieldName]
1956
- },
1957
- errorSourceMap: {
1958
- ...prev.errorSourceMap,
1959
- [errorMapKey]: "form"
1960
- }
1961
- }));
1962
- }
1963
- this.baseStore.setState(prev => ({
1964
- ...prev,
1965
- errorMap: {
1966
- ...prev.errorMap,
1967
- [errorMapKey]: formError
1968
- }
1969
- }));
1970
- } else {
1971
- this.baseStore.setState(prev => ({
1972
- ...prev,
1973
- errorMap: {
1974
- ...prev.errorMap,
1975
- [errorMapKey]: value
1976
- }
1977
- }));
1978
- }
1979
- });
1980
- });
1981
- };
1982
- this.getAllErrors = () => {
1983
- return {
1984
- form: {
1985
- errors: this.state.errors,
1986
- errorMap: this.state.errorMap
1987
- },
1988
- fields: Object.entries(this.state.fieldMeta).reduce((acc, [fieldName, fieldMeta]) => {
1989
- if (Object.keys(fieldMeta).length && fieldMeta.errors.length) {
1990
- acc[fieldName] = {
1991
- errors: fieldMeta.errors,
1992
- errorMap: fieldMeta.errorMap
1993
- };
1994
- }
1995
- return acc;
1996
- }, {})
1997
- };
1998
- };
1999
- this.parseValuesWithSchema = schema => {
2000
- return standardSchemaValidators.validate({
2001
- value: this.state.values,
2002
- validationSource: "form"
2003
- }, schema);
2004
- };
2005
- this.parseValuesWithSchemaAsync = schema => {
2006
- return standardSchemaValidators.validateAsync({
2007
- value: this.state.values,
2008
- validationSource: "form"
2009
- }, schema);
2010
- };
2011
- this.timeoutIds = {
2012
- validations: {},
2013
- listeners: {},
2014
- formListeners: {}
2015
- };
2016
- this._formId = opts?.formId ?? uuid();
2017
- this._devtoolsSubmissionOverride = false;
2018
- this.baseStore = new Store(getDefaultFormState({
2019
- ...opts?.defaultState,
2020
- values: opts?.defaultValues ?? opts?.defaultState?.values
2021
- }));
2022
- this.fieldMetaDerived = new Derived({
2023
- deps: [this.baseStore],
2024
- fn: ({
2025
- prevDepVals,
2026
- currDepVals,
2027
- prevVal: _prevVal
2028
- }) => {
2029
- const prevVal = _prevVal;
2030
- const prevBaseStore = prevDepVals?.[0];
2031
- const currBaseStore = currDepVals[0];
2032
- let originalMetaCount = 0;
2033
- const fieldMeta = {};
2034
- for (const fieldName of Object.keys(currBaseStore.fieldMetaBase)) {
2035
- const currBaseMeta = currBaseStore.fieldMetaBase[fieldName];
2036
- const prevBaseMeta = prevBaseStore?.fieldMetaBase[fieldName];
2037
- const prevFieldInfo = prevVal?.[fieldName];
2038
- const curFieldVal = getBy(currBaseStore.values, fieldName);
2039
- let fieldErrors = prevFieldInfo?.errors;
2040
- if (!prevBaseMeta || currBaseMeta.errorMap !== prevBaseMeta.errorMap) {
2041
- fieldErrors = Object.values(currBaseMeta.errorMap ?? {}).filter(val => val !== void 0);
2042
- const fieldInstance = this.getFieldInfo(fieldName)?.instance;
2043
- if (!fieldInstance || !fieldInstance.options.disableErrorFlat) {
2044
- fieldErrors = fieldErrors.flat(1);
2045
- }
2046
- }
2047
- const isFieldValid = !isNonEmptyArray(fieldErrors);
2048
- const isFieldPristine = !currBaseMeta.isDirty;
2049
- const isDefaultValue = evaluate(curFieldVal, getBy(this.options.defaultValues, fieldName)) || evaluate(curFieldVal,
2050
- // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
2051
- this.getFieldInfo(fieldName)?.instance?.options.defaultValue);
2052
- if (prevFieldInfo && prevFieldInfo.isPristine === isFieldPristine && prevFieldInfo.isValid === isFieldValid && prevFieldInfo.isDefaultValue === isDefaultValue && prevFieldInfo.errors === fieldErrors && currBaseMeta === prevBaseMeta) {
2053
- fieldMeta[fieldName] = prevFieldInfo;
2054
- originalMetaCount++;
2055
- continue;
2056
- }
2057
- fieldMeta[fieldName] = {
2058
- ...currBaseMeta,
2059
- errors: fieldErrors ?? [],
2060
- isPristine: isFieldPristine,
2061
- isValid: isFieldValid,
2062
- isDefaultValue
2063
- };
2064
- }
2065
- if (!Object.keys(currBaseStore.fieldMetaBase).length) return fieldMeta;
2066
- if (prevVal && originalMetaCount === Object.keys(currBaseStore.fieldMetaBase).length) {
2067
- return prevVal;
2068
- }
2069
- return fieldMeta;
2070
- }
2071
- });
2072
- this.store = new Derived({
2073
- deps: [this.baseStore, this.fieldMetaDerived],
2074
- fn: ({
2075
- prevDepVals,
2076
- currDepVals,
2077
- prevVal: _prevVal
2078
- }) => {
2079
- const prevVal = _prevVal;
2080
- const prevBaseStore = prevDepVals?.[0];
2081
- const currBaseStore = currDepVals[0];
2082
- const currFieldMeta = currDepVals[1];
2083
- const fieldMetaValues = Object.values(currFieldMeta).filter(Boolean);
2084
- const isFieldsValidating = fieldMetaValues.some(field => field.isValidating);
2085
- const isFieldsValid = fieldMetaValues.every(field => field.isValid);
2086
- const isTouched = fieldMetaValues.some(field => field.isTouched);
2087
- const isBlurred = fieldMetaValues.some(field => field.isBlurred);
2088
- const isDefaultValue = fieldMetaValues.every(field => field.isDefaultValue);
2089
- const shouldInvalidateOnMount =
2090
- // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
2091
- isTouched && currBaseStore.errorMap?.onMount;
2092
- const isDirty = fieldMetaValues.some(field => field.isDirty);
2093
- const isPristine = !isDirty;
2094
- const hasOnMountError = Boolean(
2095
- // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
2096
- currBaseStore.errorMap?.onMount ||
2097
- // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
2098
- fieldMetaValues.some(f => f?.errorMap?.onMount));
2099
- const isValidating = !!isFieldsValidating;
2100
- let errors = prevVal?.errors ?? [];
2101
- if (!prevBaseStore || currBaseStore.errorMap !== prevBaseStore.errorMap) {
2102
- errors = Object.values(currBaseStore.errorMap).reduce((prev, curr) => {
2103
- if (curr === void 0) return prev;
2104
- if (curr && isGlobalFormValidationError(curr)) {
2105
- prev.push(curr.form);
2106
- return prev;
2107
- }
2108
- prev.push(curr);
2109
- return prev;
2110
- }, []);
2111
- }
2112
- const isFormValid = errors.length === 0;
2113
- const isValid = isFieldsValid && isFormValid;
2114
- const submitInvalid = this.options.canSubmitWhenInvalid ?? false;
2115
- const canSubmit = currBaseStore.submissionAttempts === 0 && !isTouched && !hasOnMountError || !isValidating && !currBaseStore.isSubmitting && isValid || submitInvalid;
2116
- let errorMap = currBaseStore.errorMap;
2117
- if (shouldInvalidateOnMount) {
2118
- errors = errors.filter(err => err !== currBaseStore.errorMap.onMount);
2119
- errorMap = Object.assign(errorMap, {
2120
- onMount: void 0
2121
- });
2122
- }
2123
- if (prevVal && prevBaseStore && prevVal.errorMap === errorMap && prevVal.fieldMeta === this.fieldMetaDerived.state && prevVal.errors === errors && prevVal.isFieldsValidating === isFieldsValidating && prevVal.isFieldsValid === isFieldsValid && prevVal.isFormValid === isFormValid && prevVal.isValid === isValid && prevVal.canSubmit === canSubmit && prevVal.isTouched === isTouched && prevVal.isBlurred === isBlurred && prevVal.isPristine === isPristine && prevVal.isDefaultValue === isDefaultValue && prevVal.isDirty === isDirty && evaluate(prevBaseStore, currBaseStore)) {
2124
- return prevVal;
2125
- }
2126
- let state = {
2127
- ...currBaseStore,
2128
- errorMap,
2129
- fieldMeta: this.fieldMetaDerived.state,
2130
- errors,
2131
- isFieldsValidating,
2132
- isFieldsValid,
2133
- isFormValid,
2134
- isValid,
2135
- canSubmit,
2136
- isTouched,
2137
- isBlurred,
2138
- isPristine,
2139
- isDefaultValue,
2140
- isDirty
2141
- };
2142
- const transformArray = this.options.transform?.deps ?? [];
2143
- const shouldTransform = transformArray.length !== this.prevTransformArray.length || transformArray.some((val, i) => val !== this.prevTransformArray[i]);
2144
- if (shouldTransform) {
2145
- const newObj = Object.assign({}, this, {
2146
- state
2147
- });
2148
- this.options.transform?.fn(newObj);
2149
- state = newObj.state;
2150
- this.prevTransformArray = transformArray;
2151
- }
2152
- return state;
2153
- }
2154
- });
2155
- this.handleSubmit = this.handleSubmit.bind(this);
2156
- this.update(opts || {});
2157
- }
2158
- get state() {
2159
- return this.store.state;
2160
- }
2161
- get formId() {
2162
- return this._formId;
2163
- }
2164
- /**
2165
- * @private
2166
- */
2167
- runValidator(props) {
2168
- if (isStandardSchemaValidator(props.validate)) {
2169
- return standardSchemaValidators[props.type](props.value, props.validate);
2170
- }
2171
- return props.validate(props.value);
2172
- }
2173
- handleSubmit(submitMeta) {
2174
- return this._handleSubmit(submitMeta);
2175
- }
2176
- }
2177
- function normalizeError$1(rawError) {
2178
- if (rawError) {
2179
- if (isGlobalFormValidationError(rawError)) {
2180
- const formError = normalizeError$1(rawError.form).formError;
2181
- const fieldErrors = rawError.fields;
2182
- return {
2183
- formError,
2184
- fieldErrors
2185
- };
2186
- }
2187
- return {
2188
- formError: rawError
2189
- };
2190
- }
2191
- return {
2192
- formError: void 0
2193
- };
2194
- }
2195
- function getErrorMapKey$1(cause) {
2196
- switch (cause) {
2197
- case "submit":
2198
- return "onSubmit";
2199
- case "blur":
2200
- return "onBlur";
2201
- case "mount":
2202
- return "onMount";
2203
- case "server":
2204
- return "onServer";
2205
- case "dynamic":
2206
- return "onDynamic";
2207
- case "change":
2208
- default:
2209
- return "onChange";
2210
- }
2211
- }class FieldApi {
2212
- /**
2213
- * Initializes a new `FieldApi` instance.
2214
- */
2215
- constructor(opts) {
2216
- this.options = {};
2217
- this.mount = () => {
2218
- const cleanup = this.store.mount();
2219
- if (this.options.defaultValue !== void 0 && !this.getMeta().isTouched) {
2220
- this.form.setFieldValue(this.name, this.options.defaultValue, {
2221
- dontUpdateMeta: true
2222
- });
2223
- }
2224
- const info = this.getInfo();
2225
- info.instance = this;
2226
- this.update(this.options);
2227
- const {
2228
- onMount
2229
- } = this.options.validators || {};
2230
- if (onMount) {
2231
- const error = this.runValidator({
2232
- validate: onMount,
2233
- value: {
2234
- value: this.state.value,
2235
- fieldApi: this,
2236
- validationSource: "field"
2237
- },
2238
- type: "validate"
2239
- });
2240
- if (error) {
2241
- this.setMeta(prev => ({
2242
- ...prev,
2243
- // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
2244
- errorMap: {
2245
- ...prev?.errorMap,
2246
- onMount: error
2247
- },
2248
- errorSourceMap: {
2249
- // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
2250
- ...prev?.errorSourceMap,
2251
- onMount: "field"
2252
- }
2253
- }));
2254
- }
2255
- }
2256
- this.options.listeners?.onMount?.({
2257
- value: this.state.value,
2258
- fieldApi: this
2259
- });
2260
- return cleanup;
2261
- };
2262
- this.update = opts2 => {
2263
- this.options = opts2;
2264
- this.name = opts2.name;
2265
- if (!this.state.meta.isTouched && this.options.defaultValue !== void 0) {
2266
- const formField = this.form.getFieldValue(this.name);
2267
- if (!evaluate(formField, opts2.defaultValue)) {
2268
- this.form.setFieldValue(this.name, opts2.defaultValue, {
2269
- dontUpdateMeta: true,
2270
- dontValidate: true,
2271
- dontRunListeners: true
2272
- });
2273
- }
2274
- }
2275
- if (!this.form.getFieldMeta(this.name)) {
2276
- this.form.setFieldMeta(this.name, this.state.meta);
2277
- }
2278
- };
2279
- this.getValue = () => {
2280
- return this.form.getFieldValue(this.name);
2281
- };
2282
- this.setValue = (updater, options) => {
2283
- this.form.setFieldValue(this.name, updater, mergeOpts(options, {
2284
- dontRunListeners: true,
2285
- dontValidate: true
2286
- }));
2287
- if (!options?.dontRunListeners) {
2288
- this.triggerOnChangeListener();
2289
- }
2290
- if (!options?.dontValidate) {
2291
- this.validate("change");
2292
- }
2293
- };
2294
- this.getMeta = () => this.store.state.meta;
2295
- this.setMeta = updater => this.form.setFieldMeta(this.name, updater);
2296
- this.getInfo = () => this.form.getFieldInfo(this.name);
2297
- this.pushValue = (value, options) => {
2298
- this.form.pushFieldValue(this.name, value, mergeOpts(options, {
2299
- dontRunListeners: true
2300
- }));
2301
- if (!options?.dontRunListeners) {
2302
- this.triggerOnChangeListener();
2303
- }
2304
- };
2305
- this.insertValue = (index, value, options) => {
2306
- this.form.insertFieldValue(this.name, index, value, mergeOpts(options, {
2307
- dontRunListeners: true
2308
- }));
2309
- if (!options?.dontRunListeners) {
2310
- this.triggerOnChangeListener();
2311
- }
2312
- };
2313
- this.replaceValue = (index, value, options) => {
2314
- this.form.replaceFieldValue(this.name, index, value, mergeOpts(options, {
2315
- dontRunListeners: true
2316
- }));
2317
- if (!options?.dontRunListeners) {
2318
- this.triggerOnChangeListener();
2319
- }
2320
- };
2321
- this.removeValue = (index, options) => {
2322
- this.form.removeFieldValue(this.name, index, mergeOpts(options, {
2323
- dontRunListeners: true
2324
- }));
2325
- if (!options?.dontRunListeners) {
2326
- this.triggerOnChangeListener();
2327
- }
2328
- };
2329
- this.swapValues = (aIndex, bIndex, options) => {
2330
- this.form.swapFieldValues(this.name, aIndex, bIndex, mergeOpts(options, {
2331
- dontRunListeners: true
2332
- }));
2333
- if (!options?.dontRunListeners) {
2334
- this.triggerOnChangeListener();
2335
- }
2336
- };
2337
- this.moveValue = (aIndex, bIndex, options) => {
2338
- this.form.moveFieldValues(this.name, aIndex, bIndex, mergeOpts(options, {
2339
- dontRunListeners: true
2340
- }));
2341
- if (!options?.dontRunListeners) {
2342
- this.triggerOnChangeListener();
2343
- }
2344
- };
2345
- this.clearValues = options => {
2346
- this.form.clearFieldValues(this.name, mergeOpts(options, {
2347
- dontRunListeners: true
2348
- }));
2349
- if (!options?.dontRunListeners) {
2350
- this.triggerOnChangeListener();
2351
- }
2352
- };
2353
- this.getLinkedFields = cause => {
2354
- const fields = Object.values(this.form.fieldInfo);
2355
- const linkedFields = [];
2356
- for (const field of fields) {
2357
- if (!field.instance) continue;
2358
- const {
2359
- onChangeListenTo,
2360
- onBlurListenTo
2361
- } = field.instance.options.validators || {};
2362
- if (cause === "change" && onChangeListenTo?.includes(this.name)) {
2363
- linkedFields.push(field.instance);
2364
- }
2365
- if (cause === "blur" && onBlurListenTo?.includes(this.name)) {
2366
- linkedFields.push(field.instance);
2367
- }
2368
- }
2369
- return linkedFields;
2370
- };
2371
- this.validateSync = (cause, errorFromForm) => {
2372
- const validates = getSyncValidatorArray(cause, {
2373
- ...this.options,
2374
- form: this.form,
2375
- validationLogic: this.form.options.validationLogic || defaultValidationLogic
2376
- });
2377
- const linkedFields = this.getLinkedFields(cause);
2378
- const linkedFieldValidates = linkedFields.reduce((acc, field) => {
2379
- const fieldValidates = getSyncValidatorArray(cause, {
2380
- ...field.options,
2381
- form: field.form,
2382
- validationLogic: field.form.options.validationLogic || defaultValidationLogic
2383
- });
2384
- fieldValidates.forEach(validate => {
2385
- validate.field = field;
2386
- });
2387
- return acc.concat(fieldValidates);
2388
- }, []);
2389
- let hasErrored = false;
2390
- batch(() => {
2391
- const validateFieldFn = (field, validateObj) => {
2392
- const errorMapKey = getErrorMapKey(validateObj.cause);
2393
- const fieldLevelError = validateObj.validate ? normalizeError(field.runValidator({
2394
- validate: validateObj.validate,
2395
- value: {
2396
- value: field.store.state.value,
2397
- validationSource: "field",
2398
- fieldApi: field
2399
- },
2400
- type: "validate"
2401
- })) : void 0;
2402
- const formLevelError = errorFromForm[errorMapKey];
2403
- const {
2404
- newErrorValue,
2405
- newSource
2406
- } = determineFieldLevelErrorSourceAndValue({
2407
- formLevelError,
2408
- fieldLevelError
2409
- });
2410
- if (field.state.meta.errorMap?.[errorMapKey] !== newErrorValue) {
2411
- field.setMeta(prev => ({
2412
- ...prev,
2413
- errorMap: {
2414
- ...prev.errorMap,
2415
- [errorMapKey]: newErrorValue
2416
- },
2417
- errorSourceMap: {
2418
- ...prev.errorSourceMap,
2419
- [errorMapKey]: newSource
2420
- }
2421
- }));
2422
- }
2423
- if (newErrorValue) {
2424
- hasErrored = true;
2425
- }
2426
- };
2427
- for (const validateObj of validates) {
2428
- validateFieldFn(this, validateObj);
2429
- }
2430
- for (const fieldValitateObj of linkedFieldValidates) {
2431
- if (!fieldValitateObj.validate) continue;
2432
- validateFieldFn(fieldValitateObj.field, fieldValitateObj);
2433
- }
2434
- });
2435
- const submitErrKey = getErrorMapKey("submit");
2436
- if (
2437
- // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
2438
- this.state.meta.errorMap?.[submitErrKey] && cause !== "submit" && !hasErrored) {
2439
- this.setMeta(prev => ({
2440
- ...prev,
2441
- errorMap: {
2442
- ...prev.errorMap,
2443
- [submitErrKey]: void 0
2444
- },
2445
- errorSourceMap: {
2446
- ...prev.errorSourceMap,
2447
- [submitErrKey]: void 0
2448
- }
2449
- }));
2450
- }
2451
- return {
2452
- hasErrored
2453
- };
2454
- };
2455
- this.validateAsync = async (cause, formValidationResultPromise) => {
2456
- const validates = getAsyncValidatorArray(cause, {
2457
- ...this.options,
2458
- form: this.form,
2459
- validationLogic: this.form.options.validationLogic || defaultValidationLogic
2460
- });
2461
- const asyncFormValidationResults = await formValidationResultPromise;
2462
- const linkedFields = this.getLinkedFields(cause);
2463
- const linkedFieldValidates = linkedFields.reduce((acc, field) => {
2464
- const fieldValidates = getAsyncValidatorArray(cause, {
2465
- ...field.options,
2466
- form: field.form,
2467
- validationLogic: field.form.options.validationLogic || defaultValidationLogic
2468
- });
2469
- fieldValidates.forEach(validate => {
2470
- validate.field = field;
2471
- });
2472
- return acc.concat(fieldValidates);
2473
- }, []);
2474
- const validatesPromises = [];
2475
- const linkedPromises = [];
2476
- const hasAsyncValidators = validates.some(v => v.validate) || linkedFieldValidates.some(v => v.validate);
2477
- if (hasAsyncValidators) {
2478
- if (!this.state.meta.isValidating) {
2479
- this.setMeta(prev => ({
2480
- ...prev,
2481
- isValidating: true
2482
- }));
2483
- }
2484
- for (const linkedField of linkedFields) {
2485
- linkedField.setMeta(prev => ({
2486
- ...prev,
2487
- isValidating: true
2488
- }));
2489
- }
2490
- }
2491
- const validateFieldAsyncFn = (field, validateObj, promises) => {
2492
- const errorMapKey = getErrorMapKey(validateObj.cause);
2493
- const fieldValidatorMeta = field.getInfo().validationMetaMap[errorMapKey];
2494
- fieldValidatorMeta?.lastAbortController.abort();
2495
- const controller = new AbortController();
2496
- this.getInfo().validationMetaMap[errorMapKey] = {
2497
- lastAbortController: controller
2498
- };
2499
- promises.push(new Promise(async resolve => {
2500
- let rawError;
2501
- try {
2502
- rawError = await new Promise((rawResolve, rawReject) => {
2503
- if (this.timeoutIds.validations[validateObj.cause]) {
2504
- clearTimeout(this.timeoutIds.validations[validateObj.cause]);
2505
- }
2506
- this.timeoutIds.validations[validateObj.cause] = setTimeout(async () => {
2507
- if (controller.signal.aborted) return rawResolve(void 0);
2508
- try {
2509
- rawResolve(await this.runValidator({
2510
- validate: validateObj.validate,
2511
- value: {
2512
- value: field.store.state.value,
2513
- fieldApi: field,
2514
- signal: controller.signal,
2515
- validationSource: "field"
2516
- },
2517
- type: "validateAsync"
2518
- }));
2519
- } catch (e) {
2520
- rawReject(e);
2521
- }
2522
- }, validateObj.debounceMs);
2523
- });
2524
- } catch (e) {
2525
- rawError = e;
2526
- }
2527
- if (controller.signal.aborted) return resolve(void 0);
2528
- const fieldLevelError = normalizeError(rawError);
2529
- const formLevelError = asyncFormValidationResults[this.name]?.[errorMapKey];
2530
- const {
2531
- newErrorValue,
2532
- newSource
2533
- } = determineFieldLevelErrorSourceAndValue({
2534
- formLevelError,
2535
- fieldLevelError
2536
- });
2537
- field.setMeta(prev => {
2538
- return {
2539
- ...prev,
2540
- errorMap: {
2541
- // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
2542
- ...prev?.errorMap,
2543
- [errorMapKey]: newErrorValue
2544
- },
2545
- errorSourceMap: {
2546
- ...prev.errorSourceMap,
2547
- [errorMapKey]: newSource
2548
- }
2549
- };
2550
- });
2551
- resolve(newErrorValue);
2552
- }));
2553
- };
2554
- for (const validateObj of validates) {
2555
- if (!validateObj.validate) continue;
2556
- validateFieldAsyncFn(this, validateObj, validatesPromises);
2557
- }
2558
- for (const fieldValitateObj of linkedFieldValidates) {
2559
- if (!fieldValitateObj.validate) continue;
2560
- validateFieldAsyncFn(fieldValitateObj.field, fieldValitateObj, linkedPromises);
2561
- }
2562
- let results = [];
2563
- if (validatesPromises.length || linkedPromises.length) {
2564
- results = await Promise.all(validatesPromises);
2565
- await Promise.all(linkedPromises);
2566
- }
2567
- if (hasAsyncValidators) {
2568
- this.setMeta(prev => ({
2569
- ...prev,
2570
- isValidating: false
2571
- }));
2572
- for (const linkedField of linkedFields) {
2573
- linkedField.setMeta(prev => ({
2574
- ...prev,
2575
- isValidating: false
2576
- }));
2577
- }
2578
- }
2579
- return results.filter(Boolean);
2580
- };
2581
- this.validate = (cause, opts2) => {
2582
- if (!this.state.meta.isTouched) return [];
2583
- const {
2584
- fieldsErrorMap
2585
- } = opts2?.skipFormValidation ? {
2586
- fieldsErrorMap: {}
2587
- } : this.form.validateSync(cause);
2588
- const {
2589
- hasErrored
2590
- } = this.validateSync(cause, fieldsErrorMap[this.name] ?? {});
2591
- if (hasErrored && !this.options.asyncAlways) {
2592
- this.getInfo().validationMetaMap[getErrorMapKey(cause)]?.lastAbortController.abort();
2593
- return this.state.meta.errors;
2594
- }
2595
- const formValidationResultPromise = opts2?.skipFormValidation ? Promise.resolve({}) : this.form.validateAsync(cause);
2596
- return this.validateAsync(cause, formValidationResultPromise);
2597
- };
2598
- this.handleChange = updater => {
2599
- this.setValue(updater);
2600
- };
2601
- this.handleBlur = () => {
2602
- const prevTouched = this.state.meta.isTouched;
2603
- if (!prevTouched) {
2604
- this.setMeta(prev => ({
2605
- ...prev,
2606
- isTouched: true
2607
- }));
2608
- }
2609
- if (!this.state.meta.isBlurred) {
2610
- this.setMeta(prev => ({
2611
- ...prev,
2612
- isBlurred: true
2613
- }));
2614
- }
2615
- this.validate("blur");
2616
- this.triggerOnBlurListener();
2617
- };
2618
- this.setErrorMap = errorMap => {
2619
- this.setMeta(prev => ({
2620
- ...prev,
2621
- errorMap: {
2622
- ...prev.errorMap,
2623
- ...errorMap
2624
- }
2625
- }));
2626
- };
2627
- this.parseValueWithSchema = schema => {
2628
- return standardSchemaValidators.validate({
2629
- value: this.state.value,
2630
- validationSource: "field"
2631
- }, schema);
2632
- };
2633
- this.parseValueWithSchemaAsync = schema => {
2634
- return standardSchemaValidators.validateAsync({
2635
- value: this.state.value,
2636
- validationSource: "field"
2637
- }, schema);
2638
- };
2639
- this.triggerOnChangeListener = () => {
2640
- const formDebounceMs = this.form.options.listeners?.onChangeDebounceMs;
2641
- if (formDebounceMs && formDebounceMs > 0) {
2642
- if (this.timeoutIds.formListeners.change) {
2643
- clearTimeout(this.timeoutIds.formListeners.change);
2644
- }
2645
- this.timeoutIds.formListeners.change = setTimeout(() => {
2646
- this.form.options.listeners?.onChange?.({
2647
- formApi: this.form,
2648
- fieldApi: this
2649
- });
2650
- }, formDebounceMs);
2651
- } else {
2652
- this.form.options.listeners?.onChange?.({
2653
- formApi: this.form,
2654
- fieldApi: this
2655
- });
2656
- }
2657
- const fieldDebounceMs = this.options.listeners?.onChangeDebounceMs;
2658
- if (fieldDebounceMs && fieldDebounceMs > 0) {
2659
- if (this.timeoutIds.listeners.change) {
2660
- clearTimeout(this.timeoutIds.listeners.change);
2661
- }
2662
- this.timeoutIds.listeners.change = setTimeout(() => {
2663
- this.options.listeners?.onChange?.({
2664
- value: this.state.value,
2665
- fieldApi: this
2666
- });
2667
- }, fieldDebounceMs);
2668
- } else {
2669
- this.options.listeners?.onChange?.({
2670
- value: this.state.value,
2671
- fieldApi: this
2672
- });
2673
- }
2674
- };
2675
- this.form = opts.form;
2676
- this.name = opts.name;
2677
- this.options = opts;
2678
- this.timeoutIds = {
2679
- validations: {},
2680
- listeners: {},
2681
- formListeners: {}
2682
- };
2683
- this.store = new Derived({
2684
- deps: [this.form.store],
2685
- fn: ({
2686
- prevVal: _prevVal
2687
- }) => {
2688
- const prevVal = _prevVal;
2689
- const meta = this.form.getFieldMeta(this.name) ?? {
2690
- ...defaultFieldMeta,
2691
- ...opts.defaultMeta
2692
- };
2693
- let value = this.form.getFieldValue(this.name);
2694
- if (!meta.isTouched && value === void 0 && this.options.defaultValue !== void 0 && !evaluate(value, this.options.defaultValue)) {
2695
- value = this.options.defaultValue;
2696
- }
2697
- if (prevVal && prevVal.value === value && prevVal.meta === meta) {
2698
- return prevVal;
2699
- }
2700
- return {
2701
- value,
2702
- meta
2703
- };
2704
- }
2705
- });
2706
- }
2707
- /**
2708
- * The current field state.
2709
- */
2710
- get state() {
2711
- return this.store.state;
2712
- }
2713
- /**
2714
- * @private
2715
- */
2716
- runValidator(props) {
2717
- if (isStandardSchemaValidator(props.validate)) {
2718
- return standardSchemaValidators[props.type](props.value, props.validate);
2719
- }
2720
- return props.validate(props.value);
2721
- }
2722
- triggerOnBlurListener() {
2723
- const formDebounceMs = this.form.options.listeners?.onBlurDebounceMs;
2724
- if (formDebounceMs && formDebounceMs > 0) {
2725
- if (this.timeoutIds.formListeners.blur) {
2726
- clearTimeout(this.timeoutIds.formListeners.blur);
2727
- }
2728
- this.timeoutIds.formListeners.blur = setTimeout(() => {
2729
- this.form.options.listeners?.onBlur?.({
2730
- formApi: this.form,
2731
- fieldApi: this
2732
- });
2733
- }, formDebounceMs);
2734
- } else {
2735
- this.form.options.listeners?.onBlur?.({
2736
- formApi: this.form,
2737
- fieldApi: this
2738
- });
2739
- }
2740
- const fieldDebounceMs = this.options.listeners?.onBlurDebounceMs;
2741
- if (fieldDebounceMs && fieldDebounceMs > 0) {
2742
- if (this.timeoutIds.listeners.blur) {
2743
- clearTimeout(this.timeoutIds.listeners.blur);
2744
- }
2745
- this.timeoutIds.listeners.blur = setTimeout(() => {
2746
- this.options.listeners?.onBlur?.({
2747
- value: this.state.value,
2748
- fieldApi: this
2749
- });
2750
- }, fieldDebounceMs);
2751
- } else {
2752
- this.options.listeners?.onBlur?.({
2753
- value: this.state.value,
2754
- fieldApi: this
2755
- });
2756
- }
2757
- }
2758
- }
2759
- function normalizeError(rawError) {
2760
- if (rawError) {
2761
- return rawError;
2762
- }
2763
- return void 0;
2764
- }
2765
- function getErrorMapKey(cause) {
2766
- switch (cause) {
2767
- case "submit":
2768
- return "onSubmit";
2769
- case "blur":
2770
- return "onBlur";
2771
- case "mount":
2772
- return "onMount";
2773
- case "server":
2774
- return "onServer";
2775
- case "dynamic":
2776
- return "onDynamic";
2777
- case "change":
2778
- default:
2779
- return "onChange";
2780
- }
2781
- }function useStore$1(store, selector = (d) => d, options = {}) {
2782
- const equal = options.equal ?? shallow;
2783
- const slice = withSelector_js.useSyncExternalStoreWithSelector(
2784
- store.subscribe,
2785
- () => store.state,
2786
- () => store.state,
2787
- selector,
2788
- equal
2789
- );
2790
- return slice;
2791
- }
2792
- function shallow(objA, objB) {
2793
- if (Object.is(objA, objB)) {
2794
- return true;
2795
- }
2796
- if (typeof objA !== "object" || objA === null || typeof objB !== "object" || objB === null) {
2797
- return false;
2798
- }
2799
- if (objA instanceof Map && objB instanceof Map) {
2800
- if (objA.size !== objB.size) return false;
2801
- for (const [k, v] of objA) {
2802
- if (!objB.has(k) || !Object.is(v, objB.get(k))) return false;
2803
- }
2804
- return true;
2805
- }
2806
- if (objA instanceof Set && objB instanceof Set) {
2807
- if (objA.size !== objB.size) return false;
2808
- for (const v of objA) {
2809
- if (!objB.has(v)) return false;
2810
- }
2811
- return true;
2812
- }
2813
- if (objA instanceof Date && objB instanceof Date) {
2814
- if (objA.getTime() !== objB.getTime()) return false;
2815
- return true;
2816
- }
2817
- const keysA = getOwnKeys(objA);
2818
- if (keysA.length !== getOwnKeys(objB).length) {
2819
- return false;
2820
- }
2821
- for (let i = 0; i < keysA.length; i++) {
2822
- if (!Object.prototype.hasOwnProperty.call(objB, keysA[i]) || !Object.is(objA[keysA[i]], objB[keysA[i]])) {
2823
- return false;
2824
- }
2825
- }
2826
- return true;
2827
- }
2828
- function getOwnKeys(obj) {
2829
- return Object.keys(obj).concat(
2830
- Object.getOwnPropertySymbols(obj)
2831
- );
2832
- }const useIsomorphicLayoutEffect = typeof window !== "undefined" ? React.useLayoutEffect : React.useEffect;function useField(opts) {
2833
- const [prevOptions, setPrevOptions] = React.useState(() => ({
2834
- form: opts.form,
2835
- name: opts.name
2836
- }));
2837
- const [fieldApi, setFieldApi] = React.useState(() => {
2838
- return new FieldApi({
2839
- ...opts
2840
- });
2841
- });
2842
- if (prevOptions.form !== opts.form || prevOptions.name !== opts.name) {
2843
- setFieldApi(
2844
- new FieldApi({
2845
- ...opts
2846
- })
2847
- );
2848
- setPrevOptions({ form: opts.form, name: opts.name });
2849
- }
2850
- const reactiveStateValue = useStore$1(
2851
- fieldApi.store,
2852
- opts.mode === "array" ? (state) => Object.keys(state.value ?? []).length : (state) => state.value
2853
- );
2854
- const reactiveMetaIsTouched = useStore$1(
2855
- fieldApi.store,
2856
- (state) => state.meta.isTouched
2857
- );
2858
- const reactiveMetaIsBlurred = useStore$1(
2859
- fieldApi.store,
2860
- (state) => state.meta.isBlurred
2861
- );
2862
- const reactiveMetaIsDirty = useStore$1(
2863
- fieldApi.store,
2864
- (state) => state.meta.isDirty
2865
- );
2866
- const reactiveMetaErrorMap = useStore$1(
2867
- fieldApi.store,
2868
- (state) => state.meta.errorMap
2869
- );
2870
- const reactiveMetaErrorSourceMap = useStore$1(
2871
- fieldApi.store,
2872
- (state) => state.meta.errorSourceMap
2873
- );
2874
- const reactiveMetaIsValidating = useStore$1(
2875
- fieldApi.store,
2876
- (state) => state.meta.isValidating
2877
- );
2878
- const extendedFieldApi = React.useMemo(() => {
2879
- const reactiveFieldApi = {
2880
- ...fieldApi,
2881
- get state() {
2882
- return {
2883
- // For array mode, reactiveStateValue is the length (for reactivity tracking),
2884
- // so we need to get the actual value from fieldApi
2885
- value: opts.mode === "array" ? fieldApi.state.value : reactiveStateValue,
2886
- get meta() {
2887
- return {
2888
- ...fieldApi.state.meta,
2889
- isTouched: reactiveMetaIsTouched,
2890
- isBlurred: reactiveMetaIsBlurred,
2891
- isDirty: reactiveMetaIsDirty,
2892
- errorMap: reactiveMetaErrorMap,
2893
- errorSourceMap: reactiveMetaErrorSourceMap,
2894
- isValidating: reactiveMetaIsValidating
2895
- };
2896
- }
2897
- };
2898
- }
2899
- };
2900
- const extendedApi = reactiveFieldApi;
2901
- extendedApi.Field = Field;
2902
- return extendedApi;
2903
- }, [
2904
- fieldApi,
2905
- opts.mode,
2906
- reactiveStateValue,
2907
- reactiveMetaIsTouched,
2908
- reactiveMetaIsBlurred,
2909
- reactiveMetaIsDirty,
2910
- reactiveMetaErrorMap,
2911
- reactiveMetaErrorSourceMap,
2912
- reactiveMetaIsValidating
2913
- ]);
2914
- useIsomorphicLayoutEffect(fieldApi.mount, [fieldApi]);
2915
- useIsomorphicLayoutEffect(() => {
2916
- fieldApi.update(opts);
2917
- });
2918
- return extendedFieldApi;
2919
- }
2920
- const Field = (({
2921
- children,
2922
- ...fieldOptions
2923
- }) => {
2924
- const fieldApi = useField(fieldOptions);
2925
- const jsxToDisplay = React.useMemo(
2926
- () => functionalUpdate(children, fieldApi),
2927
- [children, fieldApi]
2928
- );
2929
- return /* @__PURE__ */ jsxRuntime.jsx(jsxRuntime.Fragment, { children: jsxToDisplay });
2930
- });function useUUID() {
2931
- return React.useState(() => uuid())[0];
2932
- }const useFormId = React__namespace.version.split(".")[0] === "17" ? useUUID : React__namespace.useId;function LocalSubscribe({
2933
- form,
2934
- selector,
2935
- children
2936
- }) {
2937
- const data = useStore$1(form.store, selector);
2938
- return /* @__PURE__ */ jsxRuntime.jsx(jsxRuntime.Fragment, { children: functionalUpdate(children, data) });
2939
- }
2940
- function useForm(opts) {
2941
- const fallbackFormId = useFormId();
2942
- const [prevFormId, setPrevFormId] = React.useState(opts?.formId);
2943
- const [formApi, setFormApi] = React.useState(() => {
2944
- return new FormApi({ ...opts, formId: opts?.formId ?? fallbackFormId });
2945
- });
2946
- if (prevFormId !== opts?.formId) {
2947
- const formId = opts?.formId ?? fallbackFormId;
2948
- setFormApi(new FormApi({ ...opts, formId }));
2949
- setPrevFormId(formId);
2950
- }
2951
- const extendedFormApi = React.useMemo(() => {
2952
- const extendedApi = {
2953
- ...formApi,
2954
- handleSubmit: ((...props) => {
2955
- return formApi._handleSubmit(...props);
2956
- }),
2957
- // We must add all `get`ters from `core`'s `FormApi` here, as otherwise the spread operator won't catch those
2958
- get formId() {
2959
- return formApi._formId;
2960
- },
2961
- get state() {
2962
- return formApi.store.state;
2963
- }
2964
- };
2965
- extendedApi.Field = function APIField(props) {
2966
- return /* @__PURE__ */ jsxRuntime.jsx(Field, { ...props, form: formApi });
2967
- };
2968
- extendedApi.Subscribe = function Subscribe(props) {
2969
- return /* @__PURE__ */ jsxRuntime.jsx(
2970
- LocalSubscribe,
2971
- {
2972
- form: formApi,
2973
- selector: props.selector,
2974
- children: props.children
2975
- }
2976
- );
2977
- };
2978
- return extendedApi;
2979
- }, [formApi]);
2980
- useIsomorphicLayoutEffect(formApi.mount, []);
2981
- useIsomorphicLayoutEffect(() => {
2982
- formApi.update(opts);
2983
- });
2984
- return extendedFormApi;
2985
56
  }/* eslint-disable @typescript-eslint/no-explicit-any */
2986
57
  function useJotaiForm(formOptions) {
2987
- const form = useForm(formOptions);
58
+ const form = reactForm.useForm(formOptions);
2988
59
  return form;
2989
60
  }const FormField = ({
2990
61
  config,
@@ -3002,42 +73,42 @@ function useJotaiForm(formOptions) {
3002
73
  // TanStack Form uses field.state.meta.errors which is an array of ValidationError
3003
74
  const firstError = config.field.state.meta.errors.length > 0 ? config.field.state.meta.errors[0] : undefined;
3004
75
  const errorMessageStr = firstError ? String(firstError) : undefined;
3005
- const errorMessage = React.useMemo(() => {
76
+ const errorMessage = react.useMemo(() => {
3006
77
  if (!errorMessageStr) return undefined;
3007
78
  return errorNs ? translateText === null || translateText === void 0 ? void 0 : translateText(errorMessageStr, {
3008
79
  ns: errorNs || '',
3009
80
  defaultValue: ''
3010
81
  }) : errorMessageStr;
3011
82
  }, [errorMessageStr, errorNs, translateText]);
3012
- const label = React.useMemo(() => {
83
+ const label = react.useMemo(() => {
3013
84
  var _a_0;
3014
85
  return ns ? translateText === null || translateText === void 0 ? void 0 : translateText((_a_0 = config.label) !== null && _a_0 !== void 0 ? _a_0 : '') : config.label;
3015
86
  }, [ns, config.label, translateText]);
3016
- const helperMessage = React.useMemo(() => {
87
+ const helperMessage = react.useMemo(() => {
3017
88
  var _a_1;
3018
89
  return ((_a_1 = config.helper) === null || _a_1 === void 0 ? void 0 : _a_1.text) ? translateText === null || translateText === void 0 ? void 0 : translateText(config.helper.text, config.helper.translationOption) : '';
3019
90
  }, [config.helper, translateText]);
3020
- const ref = React.useRef({
91
+ const ref = react.useRef({
3021
92
  onFieldChange,
3022
93
  handleChange: config.field.handleChange
3023
94
  });
3024
- React.useEffect(() => {
95
+ react.useEffect(() => {
3025
96
  ref.current = {
3026
97
  onFieldChange,
3027
98
  handleChange: config.field.handleChange
3028
99
  };
3029
100
  }, [config.field.handleChange, onFieldChange]);
3030
- const handleChange = React.useCallback(value => {
101
+ const handleChange = react.useCallback(value => {
3031
102
  var _a_2, _b_0;
3032
103
  // TanStack Form handleChange usually expects just the value for input
3033
104
  // but if we are manually calling it we should pass the value.
3034
105
  ref.current.handleChange(value);
3035
106
  (_b_0 = (_a_2 = ref.current).onFieldChange) === null || _b_0 === void 0 ? void 0 : _b_0.call(_a_2, value);
3036
107
  }, []);
3037
- const handleBlur = React.useCallback(() => {
108
+ const handleBlur = react.useCallback(() => {
3038
109
  config.field.handleBlur();
3039
110
  }, [config.field]);
3040
- const baseProps = React.useMemo(() => ({
111
+ const baseProps = react.useMemo(() => ({
3041
112
  value: config.field.state.value,
3042
113
  onChange: handleChange,
3043
114
  onBlur: handleBlur,
@@ -3046,8 +117,8 @@ function useJotaiForm(formOptions) {
3046
117
  label,
3047
118
  helperMessage
3048
119
  }), [config.field.state.value, handleChange, handleBlur, config.field.state.meta.errors.length, errorMessage, label, helperMessage]);
3049
- const ConfigContainer = React.useMemo(() => config.container, [config.container]);
3050
- const FormFieldContainer = React.useMemo(() => formFieldContainer, [formFieldContainer]);
120
+ const ConfigContainer = react.useMemo(() => config.container, [config.container]);
121
+ const FormFieldContainer = react.useMemo(() => formFieldContainer, [formFieldContainer]);
3051
122
  if (ConfigContainer) {
3052
123
  return jsxRuntime.jsx(ConfigContainer, {
3053
124
  children: config.component(baseProps)
@@ -3056,956 +127,7 @@ function useJotaiForm(formOptions) {
3056
127
  return jsxRuntime.jsx(FormFieldContainer, {
3057
128
  children: config.component(baseProps)
3058
129
  });
3059
- };function hasInitialValue(atom) {
3060
- return "init" in atom;
3061
- }
3062
- function isActuallyWritableAtom(atom) {
3063
- return !!atom.write;
3064
- }
3065
- function isAtomStateInitialized(atomState) {
3066
- return "v" in atomState || "e" in atomState;
3067
- }
3068
- function returnAtomValue(atomState) {
3069
- if ("e" in atomState) {
3070
- throw atomState.e;
3071
- }
3072
- if ((undefined ? undefined.MODE : void 0) !== "production" && !("v" in atomState)) {
3073
- throw new Error("[Bug] atom state is not initialized");
3074
- }
3075
- return atomState.v;
3076
- }
3077
- const promiseStateMap = /* @__PURE__ */ new WeakMap();
3078
- function isPendingPromise(value) {
3079
- var _a;
3080
- return isPromiseLike$1(value) && !!((_a = promiseStateMap.get(value)) == null ? void 0 : _a[0]);
3081
- }
3082
- function abortPromise(promise) {
3083
- const promiseState = promiseStateMap.get(promise);
3084
- if (promiseState == null ? void 0 : promiseState[0]) {
3085
- promiseState[0] = false;
3086
- promiseState[1].forEach((fn) => fn());
3087
- }
3088
- }
3089
- function registerAbortHandler(promise, abortHandler) {
3090
- let promiseState = promiseStateMap.get(promise);
3091
- if (!promiseState) {
3092
- promiseState = [true, /* @__PURE__ */ new Set()];
3093
- promiseStateMap.set(promise, promiseState);
3094
- const settle = () => {
3095
- promiseState[0] = false;
3096
- };
3097
- promise.then(settle, settle);
3098
- }
3099
- promiseState[1].add(abortHandler);
3100
- }
3101
- function isPromiseLike$1(p) {
3102
- return typeof (p == null ? void 0 : p.then) === "function";
3103
- }
3104
- function addPendingPromiseToDependency(atom, promise, dependencyAtomState) {
3105
- if (!dependencyAtomState.p.has(atom)) {
3106
- dependencyAtomState.p.add(atom);
3107
- const cleanup = () => dependencyAtomState.p.delete(atom);
3108
- promise.then(cleanup, cleanup);
3109
- }
3110
- }
3111
- function getMountedOrPendingDependents(atom, atomState, mountedMap) {
3112
- var _a;
3113
- const dependents = /* @__PURE__ */ new Set();
3114
- for (const a of ((_a = mountedMap.get(atom)) == null ? void 0 : _a.t) || []) {
3115
- dependents.add(a);
3116
- }
3117
- for (const atomWithPendingPromise of atomState.p) {
3118
- dependents.add(atomWithPendingPromise);
3119
- }
3120
- return dependents;
3121
- }
3122
- const BUILDING_BLOCK_atomRead = (_store, atom, ...params) => atom.read(...params);
3123
- const BUILDING_BLOCK_atomWrite = (_store, atom, ...params) => atom.write(...params);
3124
- const BUILDING_BLOCK_atomOnInit = (store, atom) => {
3125
- var _a;
3126
- return (_a = atom.INTERNAL_onInit) == null ? void 0 : _a.call(atom, store);
3127
- };
3128
- const BUILDING_BLOCK_atomOnMount = (_store, atom, setAtom) => {
3129
- var _a;
3130
- return (_a = atom.onMount) == null ? void 0 : _a.call(atom, setAtom);
3131
- };
3132
- const BUILDING_BLOCK_ensureAtomState = (store, atom) => {
3133
- var _a;
3134
- const buildingBlocks = getInternalBuildingBlocks(store);
3135
- const atomStateMap = buildingBlocks[0];
3136
- const storeHooks = buildingBlocks[6];
3137
- const atomOnInit = buildingBlocks[9];
3138
- if ((undefined ? undefined.MODE : void 0) !== "production" && !atom) {
3139
- throw new Error("Atom is undefined or null");
3140
- }
3141
- let atomState = atomStateMap.get(atom);
3142
- if (!atomState) {
3143
- atomState = { d: /* @__PURE__ */ new Map(), p: /* @__PURE__ */ new Set(), n: 0 };
3144
- atomStateMap.set(atom, atomState);
3145
- (_a = storeHooks.i) == null ? void 0 : _a.call(storeHooks, atom);
3146
- atomOnInit == null ? void 0 : atomOnInit(store, atom);
3147
- }
3148
- return atomState;
3149
- };
3150
- const BUILDING_BLOCK_flushCallbacks = (store) => {
3151
- const buildingBlocks = getInternalBuildingBlocks(store);
3152
- const mountedMap = buildingBlocks[1];
3153
- const changedAtoms = buildingBlocks[3];
3154
- const mountCallbacks = buildingBlocks[4];
3155
- const unmountCallbacks = buildingBlocks[5];
3156
- const storeHooks = buildingBlocks[6];
3157
- const recomputeInvalidatedAtoms = buildingBlocks[13];
3158
- const errors = [];
3159
- const call = (fn) => {
3160
- try {
3161
- fn();
3162
- } catch (e) {
3163
- errors.push(e);
3164
- }
3165
- };
3166
- do {
3167
- if (storeHooks.f) {
3168
- call(storeHooks.f);
3169
- }
3170
- const callbacks = /* @__PURE__ */ new Set();
3171
- const add = callbacks.add.bind(callbacks);
3172
- changedAtoms.forEach((atom) => {
3173
- var _a;
3174
- return (_a = mountedMap.get(atom)) == null ? void 0 : _a.l.forEach(add);
3175
- });
3176
- changedAtoms.clear();
3177
- unmountCallbacks.forEach(add);
3178
- unmountCallbacks.clear();
3179
- mountCallbacks.forEach(add);
3180
- mountCallbacks.clear();
3181
- callbacks.forEach(call);
3182
- if (changedAtoms.size) {
3183
- recomputeInvalidatedAtoms(store);
3184
- }
3185
- } while (changedAtoms.size || unmountCallbacks.size || mountCallbacks.size);
3186
- if (errors.length) {
3187
- throw new AggregateError(errors);
3188
- }
3189
- };
3190
- const BUILDING_BLOCK_recomputeInvalidatedAtoms = (store) => {
3191
- const buildingBlocks = getInternalBuildingBlocks(store);
3192
- const mountedMap = buildingBlocks[1];
3193
- const invalidatedAtoms = buildingBlocks[2];
3194
- const changedAtoms = buildingBlocks[3];
3195
- const ensureAtomState = buildingBlocks[11];
3196
- const readAtomState = buildingBlocks[14];
3197
- const mountDependencies = buildingBlocks[17];
3198
- const topSortedReversed = [];
3199
- const visiting = /* @__PURE__ */ new WeakSet();
3200
- const visited = /* @__PURE__ */ new WeakSet();
3201
- const stack = Array.from(changedAtoms);
3202
- while (stack.length) {
3203
- const a = stack[stack.length - 1];
3204
- const aState = ensureAtomState(store, a);
3205
- if (visited.has(a)) {
3206
- stack.pop();
3207
- continue;
3208
- }
3209
- if (visiting.has(a)) {
3210
- if (invalidatedAtoms.get(a) === aState.n) {
3211
- topSortedReversed.push([a, aState]);
3212
- } else if ((undefined ? undefined.MODE : void 0) !== "production" && invalidatedAtoms.has(a)) {
3213
- throw new Error("[Bug] invalidated atom exists");
3214
- }
3215
- visited.add(a);
3216
- stack.pop();
3217
- continue;
3218
- }
3219
- visiting.add(a);
3220
- for (const d of getMountedOrPendingDependents(a, aState, mountedMap)) {
3221
- if (!visiting.has(d)) {
3222
- stack.push(d);
3223
- }
3224
- }
3225
- }
3226
- for (let i = topSortedReversed.length - 1; i >= 0; --i) {
3227
- const [a, aState] = topSortedReversed[i];
3228
- let hasChangedDeps = false;
3229
- for (const dep of aState.d.keys()) {
3230
- if (dep !== a && changedAtoms.has(dep)) {
3231
- hasChangedDeps = true;
3232
- break;
3233
- }
3234
- }
3235
- if (hasChangedDeps) {
3236
- readAtomState(store, a);
3237
- mountDependencies(store, a);
3238
- }
3239
- invalidatedAtoms.delete(a);
3240
- }
3241
- };
3242
- const storeMutationSet = /* @__PURE__ */ new WeakSet();
3243
- const BUILDING_BLOCK_readAtomState = (store, atom) => {
3244
- var _a, _b;
3245
- const buildingBlocks = getInternalBuildingBlocks(store);
3246
- const mountedMap = buildingBlocks[1];
3247
- const invalidatedAtoms = buildingBlocks[2];
3248
- const changedAtoms = buildingBlocks[3];
3249
- const storeHooks = buildingBlocks[6];
3250
- const atomRead = buildingBlocks[7];
3251
- const ensureAtomState = buildingBlocks[11];
3252
- const flushCallbacks = buildingBlocks[12];
3253
- const recomputeInvalidatedAtoms = buildingBlocks[13];
3254
- const readAtomState = buildingBlocks[14];
3255
- const writeAtomState = buildingBlocks[16];
3256
- const mountDependencies = buildingBlocks[17];
3257
- const setAtomStateValueOrPromise = buildingBlocks[20];
3258
- const atomState = ensureAtomState(store, atom);
3259
- if (isAtomStateInitialized(atomState)) {
3260
- if (mountedMap.has(atom) && invalidatedAtoms.get(atom) !== atomState.n) {
3261
- return atomState;
3262
- }
3263
- let hasChangedDeps = false;
3264
- for (const [a, n] of atomState.d) {
3265
- if (readAtomState(store, a).n !== n) {
3266
- hasChangedDeps = true;
3267
- break;
3268
- }
3269
- }
3270
- if (!hasChangedDeps) {
3271
- return atomState;
3272
- }
3273
- }
3274
- atomState.d.clear();
3275
- let isSync = true;
3276
- function mountDependenciesIfAsync() {
3277
- if (mountedMap.has(atom)) {
3278
- mountDependencies(store, atom);
3279
- recomputeInvalidatedAtoms(store);
3280
- flushCallbacks(store);
3281
- }
3282
- }
3283
- function getter(a) {
3284
- var _a2;
3285
- if (a === atom) {
3286
- const aState2 = ensureAtomState(store, a);
3287
- if (!isAtomStateInitialized(aState2)) {
3288
- if (hasInitialValue(a)) {
3289
- setAtomStateValueOrPromise(store, a, a.init);
3290
- } else {
3291
- throw new Error("no atom init");
3292
- }
3293
- }
3294
- return returnAtomValue(aState2);
3295
- }
3296
- const aState = readAtomState(store, a);
3297
- try {
3298
- return returnAtomValue(aState);
3299
- } finally {
3300
- atomState.d.set(a, aState.n);
3301
- if (isPendingPromise(atomState.v)) {
3302
- addPendingPromiseToDependency(atom, atomState.v, aState);
3303
- }
3304
- if (mountedMap.has(atom)) {
3305
- (_a2 = mountedMap.get(a)) == null ? void 0 : _a2.t.add(atom);
3306
- }
3307
- if (!isSync) {
3308
- mountDependenciesIfAsync();
3309
- }
3310
- }
3311
- }
3312
- let controller;
3313
- let setSelf;
3314
- const options = {
3315
- get signal() {
3316
- if (!controller) {
3317
- controller = new AbortController();
3318
- }
3319
- return controller.signal;
3320
- },
3321
- get setSelf() {
3322
- if ((undefined ? undefined.MODE : void 0) !== "production") {
3323
- console.warn(
3324
- "[DEPRECATED] setSelf is deprecated and will be removed in v3."
3325
- );
3326
- }
3327
- if ((undefined ? undefined.MODE : void 0) !== "production" && !isActuallyWritableAtom(atom)) {
3328
- console.warn("setSelf function cannot be used with read-only atom");
3329
- }
3330
- if (!setSelf && isActuallyWritableAtom(atom)) {
3331
- setSelf = (...args) => {
3332
- if ((undefined ? undefined.MODE : void 0) !== "production" && isSync) {
3333
- console.warn("setSelf function cannot be called in sync");
3334
- }
3335
- if (!isSync) {
3336
- try {
3337
- return writeAtomState(store, atom, ...args);
3338
- } finally {
3339
- recomputeInvalidatedAtoms(store);
3340
- flushCallbacks(store);
3341
- }
3342
- }
3343
- };
3344
- }
3345
- return setSelf;
3346
- }
3347
- };
3348
- const prevEpochNumber = atomState.n;
3349
- try {
3350
- if ((undefined ? undefined.MODE : void 0) !== "production") {
3351
- storeMutationSet.delete(store);
3352
- }
3353
- const valueOrPromise = atomRead(store, atom, getter, options);
3354
- if ((undefined ? undefined.MODE : void 0) !== "production" && storeMutationSet.has(store)) {
3355
- console.warn(
3356
- "Detected store mutation during atom read. This is not supported."
3357
- );
3358
- }
3359
- setAtomStateValueOrPromise(store, atom, valueOrPromise);
3360
- if (isPromiseLike$1(valueOrPromise)) {
3361
- registerAbortHandler(valueOrPromise, () => controller == null ? void 0 : controller.abort());
3362
- valueOrPromise.then(mountDependenciesIfAsync, mountDependenciesIfAsync);
3363
- }
3364
- (_a = storeHooks.r) == null ? void 0 : _a.call(storeHooks, atom);
3365
- return atomState;
3366
- } catch (error) {
3367
- delete atomState.v;
3368
- atomState.e = error;
3369
- ++atomState.n;
3370
- return atomState;
3371
- } finally {
3372
- isSync = false;
3373
- if (prevEpochNumber !== atomState.n && invalidatedAtoms.get(atom) === prevEpochNumber) {
3374
- invalidatedAtoms.set(atom, atomState.n);
3375
- changedAtoms.add(atom);
3376
- (_b = storeHooks.c) == null ? void 0 : _b.call(storeHooks, atom);
3377
- }
3378
- }
3379
- };
3380
- const BUILDING_BLOCK_invalidateDependents = (store, atom) => {
3381
- const buildingBlocks = getInternalBuildingBlocks(store);
3382
- const mountedMap = buildingBlocks[1];
3383
- const invalidatedAtoms = buildingBlocks[2];
3384
- const ensureAtomState = buildingBlocks[11];
3385
- const stack = [atom];
3386
- while (stack.length) {
3387
- const a = stack.pop();
3388
- const aState = ensureAtomState(store, a);
3389
- for (const d of getMountedOrPendingDependents(a, aState, mountedMap)) {
3390
- const dState = ensureAtomState(store, d);
3391
- invalidatedAtoms.set(d, dState.n);
3392
- stack.push(d);
3393
- }
3394
- }
3395
- };
3396
- const BUILDING_BLOCK_writeAtomState = (store, atom, ...args) => {
3397
- const buildingBlocks = getInternalBuildingBlocks(store);
3398
- const changedAtoms = buildingBlocks[3];
3399
- const storeHooks = buildingBlocks[6];
3400
- const atomWrite = buildingBlocks[8];
3401
- const ensureAtomState = buildingBlocks[11];
3402
- const flushCallbacks = buildingBlocks[12];
3403
- const recomputeInvalidatedAtoms = buildingBlocks[13];
3404
- const readAtomState = buildingBlocks[14];
3405
- const invalidateDependents = buildingBlocks[15];
3406
- const writeAtomState = buildingBlocks[16];
3407
- const mountDependencies = buildingBlocks[17];
3408
- const setAtomStateValueOrPromise = buildingBlocks[20];
3409
- let isSync = true;
3410
- const getter = (a) => returnAtomValue(readAtomState(store, a));
3411
- const setter = (a, ...args2) => {
3412
- var _a;
3413
- const aState = ensureAtomState(store, a);
3414
- try {
3415
- if (a === atom) {
3416
- if (!hasInitialValue(a)) {
3417
- throw new Error("atom not writable");
3418
- }
3419
- if ((undefined ? undefined.MODE : void 0) !== "production") {
3420
- storeMutationSet.add(store);
3421
- }
3422
- const prevEpochNumber = aState.n;
3423
- const v = args2[0];
3424
- setAtomStateValueOrPromise(store, a, v);
3425
- mountDependencies(store, a);
3426
- if (prevEpochNumber !== aState.n) {
3427
- changedAtoms.add(a);
3428
- invalidateDependents(store, a);
3429
- (_a = storeHooks.c) == null ? void 0 : _a.call(storeHooks, a);
3430
- }
3431
- return void 0;
3432
- } else {
3433
- return writeAtomState(store, a, ...args2);
3434
- }
3435
- } finally {
3436
- if (!isSync) {
3437
- recomputeInvalidatedAtoms(store);
3438
- flushCallbacks(store);
3439
- }
3440
- }
3441
- };
3442
- try {
3443
- return atomWrite(store, atom, getter, setter, ...args);
3444
- } finally {
3445
- isSync = false;
3446
- }
3447
- };
3448
- const BUILDING_BLOCK_mountDependencies = (store, atom) => {
3449
- var _a;
3450
- const buildingBlocks = getInternalBuildingBlocks(store);
3451
- const mountedMap = buildingBlocks[1];
3452
- const changedAtoms = buildingBlocks[3];
3453
- const storeHooks = buildingBlocks[6];
3454
- const ensureAtomState = buildingBlocks[11];
3455
- const invalidateDependents = buildingBlocks[15];
3456
- const mountAtom = buildingBlocks[18];
3457
- const unmountAtom = buildingBlocks[19];
3458
- const atomState = ensureAtomState(store, atom);
3459
- const mounted = mountedMap.get(atom);
3460
- if (mounted && !isPendingPromise(atomState.v)) {
3461
- for (const [a, n] of atomState.d) {
3462
- if (!mounted.d.has(a)) {
3463
- const aState = ensureAtomState(store, a);
3464
- const aMounted = mountAtom(store, a);
3465
- aMounted.t.add(atom);
3466
- mounted.d.add(a);
3467
- if (n !== aState.n) {
3468
- changedAtoms.add(a);
3469
- invalidateDependents(store, a);
3470
- (_a = storeHooks.c) == null ? void 0 : _a.call(storeHooks, a);
3471
- }
3472
- }
3473
- }
3474
- for (const a of mounted.d) {
3475
- if (!atomState.d.has(a)) {
3476
- mounted.d.delete(a);
3477
- const aMounted = unmountAtom(store, a);
3478
- aMounted == null ? void 0 : aMounted.t.delete(atom);
3479
- }
3480
- }
3481
- }
3482
- };
3483
- const BUILDING_BLOCK_mountAtom = (store, atom) => {
3484
- var _a;
3485
- const buildingBlocks = getInternalBuildingBlocks(store);
3486
- const mountedMap = buildingBlocks[1];
3487
- const mountCallbacks = buildingBlocks[4];
3488
- const storeHooks = buildingBlocks[6];
3489
- const atomOnMount = buildingBlocks[10];
3490
- const ensureAtomState = buildingBlocks[11];
3491
- const flushCallbacks = buildingBlocks[12];
3492
- const recomputeInvalidatedAtoms = buildingBlocks[13];
3493
- const readAtomState = buildingBlocks[14];
3494
- const writeAtomState = buildingBlocks[16];
3495
- const mountAtom = buildingBlocks[18];
3496
- const atomState = ensureAtomState(store, atom);
3497
- let mounted = mountedMap.get(atom);
3498
- if (!mounted) {
3499
- readAtomState(store, atom);
3500
- for (const a of atomState.d.keys()) {
3501
- const aMounted = mountAtom(store, a);
3502
- aMounted.t.add(atom);
3503
- }
3504
- mounted = {
3505
- l: /* @__PURE__ */ new Set(),
3506
- d: new Set(atomState.d.keys()),
3507
- t: /* @__PURE__ */ new Set()
3508
- };
3509
- mountedMap.set(atom, mounted);
3510
- if (isActuallyWritableAtom(atom)) {
3511
- const processOnMount = () => {
3512
- let isSync = true;
3513
- const setAtom = (...args) => {
3514
- try {
3515
- return writeAtomState(store, atom, ...args);
3516
- } finally {
3517
- if (!isSync) {
3518
- recomputeInvalidatedAtoms(store);
3519
- flushCallbacks(store);
3520
- }
3521
- }
3522
- };
3523
- try {
3524
- const onUnmount = atomOnMount(store, atom, setAtom);
3525
- if (onUnmount) {
3526
- mounted.u = () => {
3527
- isSync = true;
3528
- try {
3529
- onUnmount();
3530
- } finally {
3531
- isSync = false;
3532
- }
3533
- };
3534
- }
3535
- } finally {
3536
- isSync = false;
3537
- }
3538
- };
3539
- mountCallbacks.add(processOnMount);
3540
- }
3541
- (_a = storeHooks.m) == null ? void 0 : _a.call(storeHooks, atom);
3542
- }
3543
- return mounted;
3544
- };
3545
- const BUILDING_BLOCK_unmountAtom = (store, atom) => {
3546
- var _a, _b;
3547
- const buildingBlocks = getInternalBuildingBlocks(store);
3548
- const mountedMap = buildingBlocks[1];
3549
- const unmountCallbacks = buildingBlocks[5];
3550
- const storeHooks = buildingBlocks[6];
3551
- const ensureAtomState = buildingBlocks[11];
3552
- const unmountAtom = buildingBlocks[19];
3553
- const atomState = ensureAtomState(store, atom);
3554
- let mounted = mountedMap.get(atom);
3555
- if (!mounted || mounted.l.size) {
3556
- return mounted;
3557
- }
3558
- let isDependent = false;
3559
- for (const a of mounted.t) {
3560
- if ((_a = mountedMap.get(a)) == null ? void 0 : _a.d.has(atom)) {
3561
- isDependent = true;
3562
- break;
3563
- }
3564
- }
3565
- if (!isDependent) {
3566
- if (mounted.u) {
3567
- unmountCallbacks.add(mounted.u);
3568
- }
3569
- mounted = void 0;
3570
- mountedMap.delete(atom);
3571
- for (const a of atomState.d.keys()) {
3572
- const aMounted = unmountAtom(store, a);
3573
- aMounted == null ? void 0 : aMounted.t.delete(atom);
3574
- }
3575
- (_b = storeHooks.u) == null ? void 0 : _b.call(storeHooks, atom);
3576
- return void 0;
3577
- }
3578
- return mounted;
3579
- };
3580
- const BUILDING_BLOCK_setAtomStateValueOrPromise = (store, atom, valueOrPromise) => {
3581
- const ensureAtomState = getInternalBuildingBlocks(store)[11];
3582
- const atomState = ensureAtomState(store, atom);
3583
- const hasPrevValue = "v" in atomState;
3584
- const prevValue = atomState.v;
3585
- if (isPromiseLike$1(valueOrPromise)) {
3586
- for (const a of atomState.d.keys()) {
3587
- addPendingPromiseToDependency(
3588
- atom,
3589
- valueOrPromise,
3590
- ensureAtomState(store, a)
3591
- );
3592
- }
3593
- }
3594
- atomState.v = valueOrPromise;
3595
- delete atomState.e;
3596
- if (!hasPrevValue || !Object.is(prevValue, atomState.v)) {
3597
- ++atomState.n;
3598
- if (isPromiseLike$1(prevValue)) {
3599
- abortPromise(prevValue);
3600
- }
3601
- }
3602
- };
3603
- const BUILDING_BLOCK_storeGet = (store, atom) => {
3604
- const readAtomState = getInternalBuildingBlocks(store)[14];
3605
- return returnAtomValue(readAtomState(store, atom));
3606
- };
3607
- const BUILDING_BLOCK_storeSet = (store, atom, ...args) => {
3608
- const buildingBlocks = getInternalBuildingBlocks(store);
3609
- const flushCallbacks = buildingBlocks[12];
3610
- const recomputeInvalidatedAtoms = buildingBlocks[13];
3611
- const writeAtomState = buildingBlocks[16];
3612
- try {
3613
- return writeAtomState(store, atom, ...args);
3614
- } finally {
3615
- recomputeInvalidatedAtoms(store);
3616
- flushCallbacks(store);
3617
- }
3618
- };
3619
- const BUILDING_BLOCK_storeSub = (store, atom, listener) => {
3620
- const buildingBlocks = getInternalBuildingBlocks(store);
3621
- const flushCallbacks = buildingBlocks[12];
3622
- const mountAtom = buildingBlocks[18];
3623
- const unmountAtom = buildingBlocks[19];
3624
- const mounted = mountAtom(store, atom);
3625
- const listeners = mounted.l;
3626
- listeners.add(listener);
3627
- flushCallbacks(store);
3628
- return () => {
3629
- listeners.delete(listener);
3630
- unmountAtom(store, atom);
3631
- flushCallbacks(store);
3632
- };
3633
- };
3634
- const buildingBlockMap = /* @__PURE__ */ new WeakMap();
3635
- const getInternalBuildingBlocks = (store) => {
3636
- const buildingBlocks = buildingBlockMap.get(store);
3637
- if ((undefined ? undefined.MODE : void 0) !== "production" && !buildingBlocks) {
3638
- throw new Error(
3639
- "Store must be created by buildStore to read its building blocks"
3640
- );
3641
- }
3642
- return buildingBlocks;
3643
- };
3644
- function buildStore(...buildArgs) {
3645
- const store = {
3646
- get(atom) {
3647
- const storeGet = getInternalBuildingBlocks(store)[21];
3648
- return storeGet(store, atom);
3649
- },
3650
- set(atom, ...args) {
3651
- const storeSet = getInternalBuildingBlocks(store)[22];
3652
- return storeSet(store, atom, ...args);
3653
- },
3654
- sub(atom, listener) {
3655
- const storeSub = getInternalBuildingBlocks(store)[23];
3656
- return storeSub(store, atom, listener);
3657
- }
3658
- };
3659
- const buildingBlocks = [
3660
- // store state
3661
- /* @__PURE__ */ new WeakMap(),
3662
- // atomStateMap
3663
- /* @__PURE__ */ new WeakMap(),
3664
- // mountedMap
3665
- /* @__PURE__ */ new WeakMap(),
3666
- // invalidatedAtoms
3667
- /* @__PURE__ */ new Set(),
3668
- // changedAtoms
3669
- /* @__PURE__ */ new Set(),
3670
- // mountCallbacks
3671
- /* @__PURE__ */ new Set(),
3672
- // unmountCallbacks
3673
- {},
3674
- // storeHooks
3675
- // atom interceptors
3676
- BUILDING_BLOCK_atomRead,
3677
- BUILDING_BLOCK_atomWrite,
3678
- BUILDING_BLOCK_atomOnInit,
3679
- BUILDING_BLOCK_atomOnMount,
3680
- // building-block functions
3681
- BUILDING_BLOCK_ensureAtomState,
3682
- BUILDING_BLOCK_flushCallbacks,
3683
- BUILDING_BLOCK_recomputeInvalidatedAtoms,
3684
- BUILDING_BLOCK_readAtomState,
3685
- BUILDING_BLOCK_invalidateDependents,
3686
- BUILDING_BLOCK_writeAtomState,
3687
- BUILDING_BLOCK_mountDependencies,
3688
- BUILDING_BLOCK_mountAtom,
3689
- BUILDING_BLOCK_unmountAtom,
3690
- BUILDING_BLOCK_setAtomStateValueOrPromise,
3691
- BUILDING_BLOCK_storeGet,
3692
- BUILDING_BLOCK_storeSet,
3693
- BUILDING_BLOCK_storeSub,
3694
- void 0
3695
- ].map((fn, i) => buildArgs[i] || fn);
3696
- buildingBlockMap.set(store, Object.freeze(buildingBlocks));
3697
- return store;
3698
- }let keyCount = 0;
3699
- function atom(read, write) {
3700
- const key = `atom${++keyCount}`;
3701
- const config = {
3702
- toString() {
3703
- return (undefined ? undefined.MODE : void 0) !== "production" && this.debugLabel ? key + ":" + this.debugLabel : key;
3704
- }
3705
- };
3706
- if (typeof read === "function") {
3707
- config.read = read;
3708
- } else {
3709
- config.init = read;
3710
- config.read = defaultRead;
3711
- config.write = defaultWrite;
3712
- }
3713
- if (write) {
3714
- config.write = write;
3715
- }
3716
- return config;
3717
- }
3718
- function defaultRead(get) {
3719
- return get(this);
3720
- }
3721
- function defaultWrite(get, set, arg) {
3722
- return set(
3723
- this,
3724
- typeof arg === "function" ? arg(get(this)) : arg
3725
- );
3726
- }
3727
- function createStore() {
3728
- return buildStore();
3729
- }
3730
- let defaultStore;
3731
- function getDefaultStore() {
3732
- if (!defaultStore) {
3733
- defaultStore = createStore();
3734
- if ((undefined ? undefined.MODE : void 0) !== "production") {
3735
- globalThis.__JOTAI_DEFAULT_STORE__ || (globalThis.__JOTAI_DEFAULT_STORE__ = defaultStore);
3736
- if (globalThis.__JOTAI_DEFAULT_STORE__ !== defaultStore) {
3737
- console.warn(
3738
- "Detected multiple Jotai instances. It may cause unexpected behavior with the default store. https://github.com/pmndrs/jotai/discussions/2044"
3739
- );
3740
- }
3741
- }
3742
- }
3743
- return defaultStore;
3744
- }const StoreContext = React.createContext(
3745
- void 0
3746
- );
3747
- function useStore(options) {
3748
- const store = React.useContext(StoreContext);
3749
- return store || getDefaultStore();
3750
- }
3751
-
3752
- const isPromiseLike = (x) => typeof (x == null ? void 0 : x.then) === "function";
3753
- const attachPromiseStatus = (promise) => {
3754
- if (!promise.status) {
3755
- promise.status = "pending";
3756
- promise.then(
3757
- (v) => {
3758
- promise.status = "fulfilled";
3759
- promise.value = v;
3760
- },
3761
- (e) => {
3762
- promise.status = "rejected";
3763
- promise.reason = e;
3764
- }
3765
- );
3766
- }
3767
- };
3768
- const use = React.use || // A shim for older React versions
3769
- ((promise) => {
3770
- if (promise.status === "pending") {
3771
- throw promise;
3772
- } else if (promise.status === "fulfilled") {
3773
- return promise.value;
3774
- } else if (promise.status === "rejected") {
3775
- throw promise.reason;
3776
- } else {
3777
- attachPromiseStatus(promise);
3778
- throw promise;
3779
- }
3780
- });
3781
- const continuablePromiseMap = /* @__PURE__ */ new WeakMap();
3782
- const createContinuablePromise = (promise, getValue) => {
3783
- let continuablePromise = continuablePromiseMap.get(promise);
3784
- if (!continuablePromise) {
3785
- continuablePromise = new Promise((resolve, reject) => {
3786
- let curr = promise;
3787
- const onFulfilled = (me) => (v) => {
3788
- if (curr === me) {
3789
- resolve(v);
3790
- }
3791
- };
3792
- const onRejected = (me) => (e) => {
3793
- if (curr === me) {
3794
- reject(e);
3795
- }
3796
- };
3797
- const onAbort = () => {
3798
- try {
3799
- const nextValue = getValue();
3800
- if (isPromiseLike(nextValue)) {
3801
- continuablePromiseMap.set(nextValue, continuablePromise);
3802
- curr = nextValue;
3803
- nextValue.then(onFulfilled(nextValue), onRejected(nextValue));
3804
- registerAbortHandler(nextValue, onAbort);
3805
- } else {
3806
- resolve(nextValue);
3807
- }
3808
- } catch (e) {
3809
- reject(e);
3810
- }
3811
- };
3812
- promise.then(onFulfilled(promise), onRejected(promise));
3813
- registerAbortHandler(promise, onAbort);
3814
- });
3815
- continuablePromiseMap.set(promise, continuablePromise);
3816
- }
3817
- return continuablePromise;
3818
- };
3819
- function useAtomValue(atom, options) {
3820
- const { delay, unstable_promiseStatus: promiseStatus = !React.use } = {};
3821
- const store = useStore();
3822
- const [[valueFromReducer, storeFromReducer, atomFromReducer], rerender] = React.useReducer(
3823
- (prev) => {
3824
- const nextValue = store.get(atom);
3825
- if (Object.is(prev[0], nextValue) && prev[1] === store && prev[2] === atom) {
3826
- return prev;
3827
- }
3828
- return [nextValue, store, atom];
3829
- },
3830
- void 0,
3831
- () => [store.get(atom), store, atom]
3832
- );
3833
- let value = valueFromReducer;
3834
- if (storeFromReducer !== store || atomFromReducer !== atom) {
3835
- rerender();
3836
- value = store.get(atom);
3837
- }
3838
- React.useEffect(() => {
3839
- const unsub = store.sub(atom, () => {
3840
- if (promiseStatus) {
3841
- try {
3842
- const value2 = store.get(atom);
3843
- if (isPromiseLike(value2)) {
3844
- attachPromiseStatus(
3845
- createContinuablePromise(value2, () => store.get(atom))
3846
- );
3847
- }
3848
- } catch (e) {
3849
- }
3850
- }
3851
- if (typeof delay === "number") {
3852
- setTimeout(rerender, delay);
3853
- return;
3854
- }
3855
- rerender();
3856
- });
3857
- rerender();
3858
- return unsub;
3859
- }, [store, atom, delay, promiseStatus]);
3860
- React.useDebugValue(value);
3861
- if (isPromiseLike(value)) {
3862
- const promise = createContinuablePromise(value, () => store.get(atom));
3863
- if (promiseStatus) {
3864
- attachPromiseStatus(promise);
3865
- }
3866
- return use(promise);
3867
- }
3868
- return value;
3869
- }
3870
-
3871
- function useSetAtom(atom, options) {
3872
- const store = useStore();
3873
- const setAtom = React.useCallback(
3874
- (...args) => {
3875
- if ((undefined ? undefined.MODE : void 0) !== "production" && !("write" in atom)) {
3876
- throw new Error("not writable atom");
3877
- }
3878
- return store.set(atom, ...args);
3879
- },
3880
- [store, atom]
3881
- );
3882
- return setAtom;
3883
- }
3884
-
3885
- function useAtom(atom, options) {
3886
- return [
3887
- useAtomValue(atom),
3888
- // We do wrong type assertion here, which results in throwing an error.
3889
- useSetAtom(atom)
3890
- ];
3891
- }const getCached$2 = (c, m, k) => (m.has(k) ? m : m.set(k, c())).get(k);
3892
- const cache1$3 = /* @__PURE__ */ new WeakMap();
3893
- const memo3 = (create, dep1, dep2, dep3) => {
3894
- const cache2 = getCached$2(() => /* @__PURE__ */ new WeakMap(), cache1$3, dep1);
3895
- const cache3 = getCached$2(() => /* @__PURE__ */ new WeakMap(), cache2, dep2);
3896
- return getCached$2(create, cache3, dep3);
3897
- };
3898
- function selectAtom(anAtom, selector, equalityFn = Object.is) {
3899
- return memo3(
3900
- () => {
3901
- const EMPTY = /* @__PURE__ */ Symbol();
3902
- const selectValue = ([value, prevSlice]) => {
3903
- if (prevSlice === EMPTY) {
3904
- return selector(value);
3905
- }
3906
- const slice = selector(value, prevSlice);
3907
- return equalityFn(prevSlice, slice) ? prevSlice : slice;
3908
- };
3909
- const derivedAtom = atom((get) => {
3910
- const prev = get(derivedAtom);
3911
- const value = get(anAtom);
3912
- return selectValue([value, prev]);
3913
- });
3914
- derivedAtom.init = EMPTY;
3915
- return derivedAtom;
3916
- },
3917
- anAtom,
3918
- selector,
3919
- equalityFn
3920
- );
3921
- }
3922
-
3923
- const isPromiseLike$2 = (x) => typeof (x == null ? void 0 : x.then) === "function";
3924
- function createJSONStorage(getStringStorage = () => {
3925
- try {
3926
- return window.localStorage;
3927
- } catch (e) {
3928
- if ((undefined ? undefined.MODE : void 0) !== "production") {
3929
- if (typeof window !== "undefined") {
3930
- console.warn(e);
3931
- }
3932
- }
3933
- return void 0;
3934
- }
3935
- }, options) {
3936
- var _a;
3937
- let lastStr;
3938
- let lastValue;
3939
- const storage = {
3940
- getItem: (key, initialValue) => {
3941
- var _a2, _b;
3942
- const parse = (str2) => {
3943
- str2 = str2 || "";
3944
- if (lastStr !== str2) {
3945
- try {
3946
- lastValue = JSON.parse(str2, void 0 );
3947
- } catch (e) {
3948
- return initialValue;
3949
- }
3950
- lastStr = str2;
3951
- }
3952
- return lastValue;
3953
- };
3954
- const str = (_b = (_a2 = getStringStorage()) == null ? void 0 : _a2.getItem(key)) != null ? _b : null;
3955
- if (isPromiseLike$2(str)) {
3956
- return str.then(parse);
3957
- }
3958
- return parse(str);
3959
- },
3960
- setItem: (key, newValue) => {
3961
- var _a2;
3962
- return (_a2 = getStringStorage()) == null ? void 0 : _a2.setItem(
3963
- key,
3964
- JSON.stringify(newValue, void 0 )
3965
- );
3966
- },
3967
- removeItem: (key) => {
3968
- var _a2;
3969
- return (_a2 = getStringStorage()) == null ? void 0 : _a2.removeItem(key);
3970
- }
3971
- };
3972
- const createHandleSubscribe = (subscriber2) => (key, callback, initialValue) => subscriber2(key, (v) => {
3973
- let newValue;
3974
- try {
3975
- newValue = JSON.parse(v || "");
3976
- } catch (e) {
3977
- newValue = initialValue;
3978
- }
3979
- callback(newValue);
3980
- });
3981
- let subscriber;
3982
- try {
3983
- subscriber = (_a = getStringStorage()) == null ? void 0 : _a.subscribe;
3984
- } catch (e) {
3985
- }
3986
- if (!subscriber && typeof window !== "undefined" && typeof window.addEventListener === "function" && window.Storage) {
3987
- subscriber = (key, callback) => {
3988
- if (!(getStringStorage() instanceof window.Storage)) {
3989
- return () => {
3990
- };
3991
- }
3992
- const storageEventCallback = (e) => {
3993
- if (e.storageArea === getStringStorage() && e.key === key) {
3994
- callback(e.newValue);
3995
- }
3996
- };
3997
- window.addEventListener("storage", storageEventCallback);
3998
- return () => {
3999
- window.removeEventListener("storage", storageEventCallback);
4000
- };
4001
- };
4002
- }
4003
- if (subscriber) {
4004
- storage.subscribe = createHandleSubscribe(subscriber);
4005
- }
4006
- return storage;
4007
- }
4008
- createJSONStorage();const DEFAULT_FORM_ENTRY = Object.freeze({
130
+ };const DEFAULT_FORM_ENTRY = Object.freeze({
4009
131
  formValues: {},
4010
132
  setValue: () => {}
4011
133
  });
@@ -4013,7 +135,7 @@ createJSONStorage();const DEFAULT_FORM_ENTRY = Object.freeze({
4013
135
  * Global atom storing all form state.
4014
136
  * Key format: "scopeId:formId" or just "formId" for backward compatibility.
4015
137
  */
4016
- const formAtom = atom({});
138
+ const formAtom = jotai.atom({});
4017
139
  /**
4018
140
  * Helper to generate composite keys for forms.
4019
141
  */
@@ -4021,7 +143,7 @@ const getFormCompositeKey = (scopeId, key) => `${scopeId}:${key}`;
4021
143
  /**
4022
144
  * Creates a derived atom for accessing forms of a specific scope.
4023
145
  */
4024
- const createScopeFormsAtom = scopeId => atom(get => {
146
+ const createScopeFormsAtom = scopeId => jotai.atom(get => {
4025
147
  const allForms = get(formAtom);
4026
148
  const prefix = `${scopeId}:`;
4027
149
  const scopeForms = {};
@@ -4047,7 +169,7 @@ const createScopeFormsAtom = scopeId => atom(get => {
4047
169
  }
4048
170
  set(formAtom, newForms);
4049
171
  });
4050
- const createFormSelector = formId => selectAtom(formAtom, forms => {
172
+ const createFormSelector = formId => utils.selectAtom(formAtom, forms => {
4051
173
  const entry = forms[formId];
4052
174
  return entry !== null && entry !== void 0 ? entry : DEFAULT_FORM_ENTRY;
4053
175
  }, (a, b) => a === b || a.formValues === b.formValues && a.setValue === b.setValue);
@@ -4062,14 +184,14 @@ const useFormValue = formId => {
4062
184
  t0 = $[1];
4063
185
  }
4064
186
  const selectorAtom = t0;
4065
- return useAtomValue(selectorAtom);
187
+ return jotai.useAtomValue(selectorAtom);
4066
188
  };
4067
189
  const useFormState = () => {
4068
- return useAtom(formAtom);
190
+ return jotai.useAtom(formAtom);
4069
191
  };
4070
192
  const useSetFormState = formId => {
4071
- const setForms = useSetAtom(formAtom);
4072
- return React.useCallback(val => {
193
+ const setForms = jotai.useSetAtom(formAtom);
194
+ return react.useCallback(val => {
4073
195
  setForms(prev => {
4074
196
  var _a;
4075
197
  const prevEntry = (_a = prev[formId]) !== null && _a !== void 0 ? _a : DEFAULT_FORM_ENTRY;
@@ -4099,19 +221,19 @@ const useFormValues = ({
4099
221
  // Note: This subscription is a bit coarse (entire form entry), but we optimize re-renders locally
4100
222
  // Ideally we would want to subscribe only to specific paths, but Jotai atoms are per-form.
4101
223
  const formEntry = useFormValue(formId);
4102
- const currentValues = React.useMemo(() => formEntry.formValues, [formEntry.formValues]);
4103
- const subscriptions = React.useRef(new Map());
224
+ const currentValues = react.useMemo(() => formEntry.formValues, [formEntry.formValues]);
225
+ const subscriptions = react.useRef(new Map());
4104
226
  // trigger state is used to force re-render when a subscribed value changes
4105
- const [trigger, setTrigger] = React.useState(0);
227
+ const [trigger, setTrigger] = react.useState(0);
4106
228
  // Ref to hold the latest values without causing re-renders itself
4107
- const formRef = React.useRef({
229
+ const formRef = react.useRef({
4108
230
  formValues: formEntry.formValues,
4109
231
  setValue: formEntry.setValue
4110
232
  });
4111
- React.useEffect(() => {
233
+ react.useEffect(() => {
4112
234
  formRef.current.setValue = formEntry.setValue;
4113
235
  }, [formEntry.setValue]);
4114
- React.useEffect(() => {
236
+ react.useEffect(() => {
4115
237
  let shouldTrigger = false;
4116
238
  subscriptions.current.forEach((_, path) => {
4117
239
  const newValue = getValueAtPath(currentValues, path);
@@ -4126,7 +248,7 @@ const useFormValues = ({
4126
248
  setTrigger(c => c + 1);
4127
249
  }
4128
250
  }, [currentValues]);
4129
- const get = React.useCallback((key, defaultValue) => {
251
+ const get = react.useCallback((key, defaultValue) => {
4130
252
  var _a;
4131
253
  const val = (_a = getValueAtPath(formRef.current.formValues, key)) !== null && _a !== void 0 ? _a : defaultValue;
4132
254
  subscriptions.current.set(key, val);
@@ -4134,7 +256,7 @@ const useFormValues = ({
4134
256
  },
4135
257
  // eslint-disable-next-line react-hooks/exhaustive-deps
4136
258
  [trigger]);
4137
- const set = React.useCallback((field, value) => {
259
+ const set = react.useCallback((field, value) => {
4138
260
  formRef.current.setValue(field, value);
4139
261
  }, []);
4140
262
  return {
@@ -4196,7 +318,7 @@ const DynamicFieldItem = ({
4196
318
  } = useFormValues({
4197
319
  formId
4198
320
  });
4199
- const fieldProps = React.useMemo(() => {
321
+ const fieldProps = react.useMemo(() => {
4200
322
  if (typeof item === 'function') {
4201
323
  return item({
4202
324
  get,
@@ -4206,7 +328,7 @@ const DynamicFieldItem = ({
4206
328
  return item;
4207
329
  }
4208
330
  }, [get, set, item]);
4209
- const isHidden = React.useMemo(() => {
331
+ const isHidden = react.useMemo(() => {
4210
332
  if (!fieldProps.hidden) {
4211
333
  return false;
4212
334
  } else if (typeof fieldProps.hidden === 'function') {
@@ -4218,7 +340,7 @@ const DynamicFieldItem = ({
4218
340
  return !!fieldProps.hidden;
4219
341
  }
4220
342
  }, [get, set, fieldProps]);
4221
- const rules = React.useMemo(() => {
343
+ const rules = react.useMemo(() => {
4222
344
  if (!fieldProps.rules) {
4223
345
  return undefined;
4224
346
  } else if (typeof fieldProps.rules === 'function') {
@@ -4230,7 +352,7 @@ const DynamicFieldItem = ({
4230
352
  return fieldProps.rules;
4231
353
  }
4232
354
  }, [get, set, fieldProps]);
4233
- const props = React.useMemo(() => {
355
+ const props = react.useMemo(() => {
4234
356
  var _a;
4235
357
  return Object.assign(Object.assign({}, fieldProps), {
4236
358
  errorNs: (_a = fieldProps.errorNs) !== null && _a !== void 0 ? _a : globalErrorNs
@@ -4256,7 +378,7 @@ const SubmitItem = ({
4256
378
  index,
4257
379
  handlersRef
4258
380
  }) => {
4259
- const handleClick = React.useCallback(async () => {
381
+ const handleClick = react.useCallback(async () => {
4260
382
  const {
4261
383
  formControl,
4262
384
  createSubmitHandler,
@@ -4290,7 +412,7 @@ const SubmitItem = ({
4290
412
  // Call handlers
4291
413
  await createSubmitHandler(item)(values);
4292
414
  }, [item, handlersRef]);
4293
- const Component = React.useMemo(() => item.component, [item]);
415
+ const Component = react.useMemo(() => item.component, [item]);
4294
416
  if (item.hidden || !Component) return jsxRuntime.jsx(jsxRuntime.Fragment, {});
4295
417
  return jsxRuntime.jsx(Component, {
4296
418
  onClick: handleClick,
@@ -4309,15 +431,15 @@ const useFormManager = ({
4309
431
  id = 'form-manager'
4310
432
  }) => {
4311
433
  const formControl = useJotaiForm(formOptions);
4312
- const formState = React.useMemo(() => formControl.state, [formControl.state]);
4313
- const errors = React.useMemo(() => formState.errors, [formState.errors]);
4314
- const values = React.useMemo(() => formState.values, [formState.values]);
434
+ const formState = react.useMemo(() => formControl.state, [formControl.state]);
435
+ const errors = react.useMemo(() => formState.errors, [formState.errors]);
436
+ const values = react.useMemo(() => formState.values, [formState.values]);
4315
437
  const setFormState = useSetFormState(id);
4316
438
  const {
4317
439
  showNotification
4318
440
  } = useFormConfigValue();
4319
- const setValue = React.useCallback((field, updater) => formControl.setFieldValue(field, updater), [formControl]);
4320
- React.useEffect(() => {
441
+ const setValue = react.useCallback((field, updater) => formControl.setFieldValue(field, updater), [formControl]);
442
+ react.useEffect(() => {
4321
443
  setFormState({
4322
444
  setValue,
4323
445
  formValues: formState.values
@@ -4331,12 +453,12 @@ const useFormManager = ({
4331
453
  unsubscribe();
4332
454
  }; /**/
4333
455
  }, [formControl.store, setValue, formState.values, setFormState]);
4334
- const handleNotification = React.useCallback(props => {
456
+ const handleNotification = react.useCallback(props => {
4335
457
  if (props.message) {
4336
458
  showNotification === null || showNotification === void 0 ? void 0 : showNotification(props);
4337
459
  }
4338
460
  }, [showNotification]);
4339
- const filterFormData = React.useCallback((v, submitConfig) => {
461
+ const filterFormData = react.useCallback((v, submitConfig) => {
4340
462
  const keys = submitConfig.values;
4341
463
  if (!keys || keys.length === 0) {
4342
464
  return v;
@@ -4349,14 +471,14 @@ const useFormManager = ({
4349
471
  }
4350
472
  return out;
4351
473
  }, []);
4352
- const processSubmit = React.useCallback(async (d, submitConfig_0) => {
474
+ const processSubmit = react.useCallback(async (d, submitConfig_0) => {
4353
475
  const filteredData = filterFormData(d, submitConfig_0);
4354
476
  if (submitConfig_0.onSuccess) {
4355
477
  return await submitConfig_0.onSuccess(filteredData);
4356
478
  }
4357
479
  throw new Error('No submit handler provided');
4358
480
  }, [filterFormData]);
4359
- const handleError = React.useCallback((error, submitConfig_1) => {
481
+ const handleError = react.useCallback((error, submitConfig_1) => {
4360
482
  if (submitConfig_1.onError) {
4361
483
  submitConfig_1.onError(error);
4362
484
  }
@@ -4365,7 +487,7 @@ const useFormManager = ({
4365
487
  handleNotification(notificationProps);
4366
488
  }
4367
489
  }, [handleNotification, notification]);
4368
- const createSubmitHandler = React.useCallback(submitConfig_2 => async dataSubmit => {
490
+ const createSubmitHandler = react.useCallback(submitConfig_2 => async dataSubmit => {
4369
491
  try {
4370
492
  const res = await processSubmit(trimObject(dataSubmit), submitConfig_2);
4371
493
  const notificationProps_0 = typeof (notification === null || notification === void 0 ? void 0 : notification.success) === 'function' ? notification.success(res) : notification === null || notification === void 0 ? void 0 : notification.success;
@@ -4378,11 +500,11 @@ const useFormManager = ({
4378
500
  throw error_0;
4379
501
  }
4380
502
  }, [processSubmit, notification, handleNotification, handleError]);
4381
- const onInvalidHandle = React.useCallback((err, submitConfig_3) => {
503
+ const onInvalidHandle = react.useCallback((err, submitConfig_3) => {
4382
504
  onInvalid === null || onInvalid === void 0 ? void 0 : onInvalid(err);
4383
505
  handleError(new Error('invalidData'), submitConfig_3);
4384
506
  }, [handleError, onInvalid]);
4385
- const handlersRef = React.useRef({
507
+ const handlersRef = react.useRef({
4386
508
  formControl,
4387
509
  onInvalidHandle,
4388
510
  createSubmitHandler,
@@ -4390,14 +512,14 @@ const useFormManager = ({
4390
512
  trigger: formControl.validateField,
4391
513
  onValuesChange
4392
514
  });
4393
- React.useEffect(() => {
515
+ react.useEffect(() => {
4394
516
  handlersRef.current.onInvalidHandle = onInvalidHandle;
4395
517
  handlersRef.current.createSubmitHandler = createSubmitHandler;
4396
518
  handlersRef.current.setValue = formControl.setFieldValue;
4397
519
  handlersRef.current.trigger = formControl.validateField;
4398
520
  handlersRef.current.onValuesChange = onValuesChange;
4399
521
  }, [onInvalidHandle, createSubmitHandler, formControl, onValuesChange]);
4400
- const fields = React.useMemo(() => data.map((item, index) => {
522
+ const fields = react.useMemo(() => data.map((item, index) => {
4401
523
  var _a, _b;
4402
524
  const staticItem = typeof item === 'function' ? null : item;
4403
525
  return {
@@ -4412,7 +534,7 @@ const useFormManager = ({
4412
534
  renderInHeader: !!(staticItem === null || staticItem === void 0 ? void 0 : staticItem.renderInHeader)
4413
535
  };
4414
536
  }), [data, formControl, globalErrorNs, id]);
4415
- const submits = React.useMemo(() => submit.map((submitConfig_4, index_0) => {
537
+ const submits = react.useMemo(() => submit.map((submitConfig_4, index_0) => {
4416
538
  return {
4417
539
  index: submitConfig_4.index === undefined ? index_0 : submitConfig_4.index,
4418
540
  element: jsxRuntime.jsx(SubmitItem, {
@@ -4425,9 +547,9 @@ const useFormManager = ({
4425
547
  isSubmit: true
4426
548
  };
4427
549
  }), [submit]);
4428
- const elements = React.useMemo(() => fields.concat(submits), [fields, submits]);
4429
- const formContents = React.useMemo(() => [...data, ...submit], [data, submit]);
4430
- React.useEffect(() => {
550
+ const elements = react.useMemo(() => fields.concat(submits), [fields, submits]);
551
+ const formContents = react.useMemo(() => [...data, ...submit], [data, submit]);
552
+ react.useEffect(() => {
4431
553
  var _a_0, _b_0;
4432
554
  (_b_0 = (_a_0 = handlersRef.current).onValuesChange) === null || _b_0 === void 0 ? void 0 : _b_0.call(_a_0, values, handlersRef.current.setValue);
4433
555
  }, [values]);