storion 0.10.1 → 0.11.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/storion.js CHANGED
@@ -1,7 +1,7 @@
1
- import { C as tryDispose, i as isSpec, u as untrack, k as STORION_TYPE, D as unwrapFn, q as shallowEqual, l as resolveEquality } from "./effect-BDQU8Voz.js";
2
- import { d, E, H, I, L, z, P, S, y, x, n, v, e, o, m, p, B, a, h } from "./effect-BDQU8Voz.js";
1
+ import { D as tryDispose, i as isSpec, u as untrack, k as STORION_TYPE, o as batch, F as unwrapFn, v as shallowEqual, m as resolveEquality } from "./effect-1beiYe_c.js";
2
+ import { d, E, H, I, L, B, P, S, z, y, x, e, q, n, p, C, a, h } from "./effect-1beiYe_c.js";
3
3
  import { e as emitter } from "./emitter-j4rC71vY.js";
4
- import { m as m2 } from "./meta-40r-AZfe.js";
4
+ import { m } from "./meta-40r-AZfe.js";
5
5
  function createMetaQuery(entries) {
6
6
  const entryArray = Array.isArray(entries) ? entries : entries ? [entries] : [];
7
7
  const single = (type) => {
@@ -306,114 +306,169 @@ container.defaults = defaultsFn;
306
306
  function isObject(value) {
307
307
  return typeof value === "object" && value !== null;
308
308
  }
309
- function createDisposalTracker() {
310
- let pendingDisposedItems = /* @__PURE__ */ new Set();
311
- let disposalScheduled = false;
309
+ const namedGroups = /* @__PURE__ */ new Map();
310
+ function getNamedGroup(name) {
311
+ let group = namedGroups.get(name);
312
+ if (!group) {
313
+ group = disposalGroup();
314
+ namedGroups.set(name, group);
315
+ }
316
+ return group;
317
+ }
318
+ function isDisposalGroup(value) {
319
+ return typeof value === "object" && value !== null && "scheduleDisposal" in value && "cancelDisposal" in value && "isPending" in value && "flush" in value;
320
+ }
321
+ function normalizeAutoDispose(autoDispose) {
322
+ if (autoDispose === false || autoDispose === void 0) {
323
+ return false;
324
+ }
325
+ if (autoDispose === true) {
326
+ return { enabled: true, gracePeriodMs: 0, group: null };
327
+ }
328
+ if (typeof autoDispose === "number") {
329
+ return { enabled: true, gracePeriodMs: autoDispose, group: null };
330
+ }
331
+ if (typeof autoDispose === "string") {
332
+ return {
333
+ enabled: true,
334
+ gracePeriodMs: 0,
335
+ group: getNamedGroup(autoDispose)
336
+ };
337
+ }
338
+ if (isDisposalGroup(autoDispose)) {
339
+ return { enabled: true, gracePeriodMs: 0, group: autoDispose };
340
+ }
341
+ const opts = autoDispose;
342
+ let group = null;
343
+ if (opts.group) {
344
+ group = typeof opts.group === "string" ? getNamedGroup(opts.group) : opts.group;
345
+ }
312
346
  return {
313
- /**
314
- * Schedule items for async disposal.
315
- * Items will be disposed in a microtask unless cancelled.
316
- * Only objects are tracked - primitives are skipped.
317
- */
318
- scheduleDisposal(items) {
319
- if (items.length === 0) return;
320
- const newPending = new Set(pendingDisposedItems);
321
- let hasNewItems = false;
347
+ enabled: true,
348
+ gracePeriodMs: opts.gracePeriodMs ?? 0,
349
+ group
350
+ };
351
+ }
352
+ function disposalGroup() {
353
+ const pendingItems = /* @__PURE__ */ new Map();
354
+ return {
355
+ scheduleDisposal(items, gracePeriodMs) {
322
356
  for (const item of items) {
323
- if (isObject(item)) {
324
- newPending.add(item);
325
- hasNewItems = true;
326
- }
327
- }
328
- if (!hasNewItems) return;
329
- pendingDisposedItems = newPending;
330
- if (!disposalScheduled) {
331
- disposalScheduled = true;
332
- queueMicrotask(() => {
333
- disposalScheduled = false;
334
- const toDispose = pendingDisposedItems;
335
- pendingDisposedItems = /* @__PURE__ */ new Set();
336
- for (const item of toDispose) {
357
+ if (!isObject(item)) continue;
358
+ if (pendingItems.has(item)) continue;
359
+ if (gracePeriodMs <= 0) {
360
+ pendingItems.set(item, "microtask");
361
+ queueMicrotask(() => {
362
+ if (pendingItems.get(item) === "microtask") {
363
+ pendingItems.delete(item);
364
+ tryDispose(item);
365
+ }
366
+ });
367
+ } else {
368
+ const timeout = setTimeout(() => {
369
+ pendingItems.delete(item);
337
370
  tryDispose(item);
338
- }
339
- });
371
+ }, gracePeriodMs);
372
+ pendingItems.set(item, timeout);
373
+ }
340
374
  }
341
375
  },
342
- /**
343
- * Cancel disposal for items that are being re-added.
344
- * Call this when items are pushed/inserted back into the collection.
345
- * Only objects are checked - primitives are skipped.
346
- */
347
376
  cancelDisposal(items) {
348
- if (items.length === 0 || pendingDisposedItems.size === 0) return;
349
- let hasChanges = false;
350
377
  for (const item of items) {
351
- if (isObject(item) && pendingDisposedItems.has(item)) {
352
- hasChanges = true;
353
- break;
378
+ if (!isObject(item)) continue;
379
+ const pending = pendingItems.get(item);
380
+ if (pending === void 0) continue;
381
+ if (pending !== "microtask") {
382
+ clearTimeout(pending);
354
383
  }
384
+ pendingItems.delete(item);
355
385
  }
356
- if (!hasChanges) return;
357
- const newPending = new Set(pendingDisposedItems);
386
+ },
387
+ isPending(item) {
388
+ return isObject(item) && pendingItems.has(item);
389
+ },
390
+ flush() {
391
+ for (const [item, pending] of pendingItems) {
392
+ if (pending !== "microtask") {
393
+ clearTimeout(pending);
394
+ }
395
+ tryDispose(item);
396
+ }
397
+ pendingItems.clear();
398
+ }
399
+ };
400
+ }
401
+ function createLocalDisposalTracker(gracePeriodMs) {
402
+ const pendingItems = /* @__PURE__ */ new Map();
403
+ return {
404
+ scheduleDisposal(items) {
358
405
  for (const item of items) {
359
- if (isObject(item)) {
360
- newPending.delete(item);
406
+ if (!isObject(item)) continue;
407
+ if (pendingItems.has(item)) continue;
408
+ if (gracePeriodMs <= 0) {
409
+ pendingItems.set(item, "microtask");
410
+ queueMicrotask(() => {
411
+ if (pendingItems.get(item) === "microtask") {
412
+ pendingItems.delete(item);
413
+ tryDispose(item);
414
+ }
415
+ });
416
+ } else {
417
+ const timeout = setTimeout(() => {
418
+ pendingItems.delete(item);
419
+ tryDispose(item);
420
+ }, gracePeriodMs);
421
+ pendingItems.set(item, timeout);
361
422
  }
362
423
  }
363
- pendingDisposedItems = newPending;
364
424
  },
365
- /**
366
- * Check if an item is pending disposal.
367
- */
425
+ cancelDisposal(items) {
426
+ for (const item of items) {
427
+ if (!isObject(item)) continue;
428
+ const pending = pendingItems.get(item);
429
+ if (pending === void 0) continue;
430
+ if (pending !== "microtask") {
431
+ clearTimeout(pending);
432
+ }
433
+ pendingItems.delete(item);
434
+ }
435
+ },
368
436
  isPending(item) {
369
- return isObject(item) && pendingDisposedItems.has(item);
437
+ return isObject(item) && pendingItems.has(item);
370
438
  }
371
439
  };
372
440
  }
373
- function toggle() {
374
- return (prev) => !prev;
375
- }
376
- function increment(amount = 1) {
377
- return (prev) => (prev ?? 0) + amount;
378
- }
379
- function decrement(amount = 1) {
380
- return (prev) => (prev ?? 0) - amount;
381
- }
382
- function multiply(factor) {
383
- return (prev) => (prev ?? 0) * factor;
384
- }
385
- function divide(divisor) {
386
- return (prev) => (prev ?? 0) / divisor;
387
- }
388
- function clamp(min, max) {
389
- return (prev) => Math.min(max, Math.max(min, prev ?? 0));
390
- }
391
- function append(suffix) {
392
- return (prev) => (prev ?? "") + suffix;
393
- }
394
- function prepend(prefix) {
395
- return (prev) => prefix + (prev ?? "");
396
- }
397
- function merge(partial) {
398
- return (prev) => ({ ...prev, ...partial });
399
- }
400
- function reset(defaultValue) {
401
- return () => defaultValue;
402
- }
403
441
  function list(options) {
404
- const autoDispose = (options == null ? void 0 : options.autoDispose) ?? false;
442
+ const autoDisposeResult = normalizeAutoDispose(options == null ? void 0 : options.autoDispose);
443
+ const gracePeriodMs = autoDisposeResult ? autoDisposeResult.gracePeriodMs : 0;
444
+ const group = autoDisposeResult ? autoDisposeResult.group : null;
445
+ const onAdded = options == null ? void 0 : options.onAdded;
446
+ const onRemoved = options == null ? void 0 : options.onRemoved;
405
447
  return (inputFocus) => {
406
448
  const focus = inputFocus;
407
449
  const [getter, setter] = focus;
408
450
  const defaultValue = [];
409
- const tracker = autoDispose ? createDisposalTracker() : null;
451
+ const tracker = autoDisposeResult ? group ?? createLocalDisposalTracker(gracePeriodMs) : null;
410
452
  const getArray = () => getter() ?? defaultValue;
411
453
  const scheduleDisposal = (items) => {
412
- tracker == null ? void 0 : tracker.scheduleDisposal(items);
454
+ if (!tracker) return;
455
+ if ("flush" in tracker) {
456
+ tracker.scheduleDisposal(items, gracePeriodMs);
457
+ } else {
458
+ tracker.scheduleDisposal(items);
459
+ }
413
460
  };
414
461
  const cancelDisposal = (items) => {
415
462
  tracker == null ? void 0 : tracker.cancelDisposal(items);
416
463
  };
464
+ const notifyAdded = (items, startIndex) => {
465
+ if (!onAdded) return;
466
+ items.forEach((item, i) => onAdded(item, startIndex + i));
467
+ };
468
+ const notifyRemoved = (items, indices) => {
469
+ if (!onRemoved) return;
470
+ items.forEach((item, i) => onRemoved(item, indices[i]));
471
+ };
417
472
  return {
418
473
  get() {
419
474
  return getArray();
@@ -435,43 +490,59 @@ function list(options) {
435
490
  return arr[arr.length - 1];
436
491
  },
437
492
  push(...items) {
438
- cancelDisposal(items);
439
- setter((draft) => {
440
- const arr = draft ?? [];
441
- arr.push(...items);
442
- return arr;
493
+ if (items.length === 0) return;
494
+ batch(() => {
495
+ cancelDisposal(items);
496
+ const startIndex = getArray().length;
497
+ setter((draft) => {
498
+ const arr = draft ?? [];
499
+ arr.push(...items);
500
+ return arr;
501
+ });
502
+ notifyAdded(items, startIndex);
443
503
  });
444
504
  },
445
505
  unshift(...items) {
446
- cancelDisposal(items);
447
- setter((draft) => {
448
- const arr = draft ?? [];
449
- arr.unshift(...items);
450
- return arr;
506
+ if (items.length === 0) return;
507
+ batch(() => {
508
+ cancelDisposal(items);
509
+ setter((draft) => {
510
+ const arr = draft ?? [];
511
+ arr.unshift(...items);
512
+ return arr;
513
+ });
514
+ notifyAdded(items, 0);
451
515
  });
452
516
  },
453
517
  pop() {
454
518
  const currentArray = getArray();
455
519
  if (currentArray.length === 0) return void 0;
456
- const removed = currentArray[currentArray.length - 1];
457
- setter((draft) => {
458
- const arr = draft ?? [];
459
- arr.pop();
460
- return arr;
520
+ const index = currentArray.length - 1;
521
+ const removed = currentArray[index];
522
+ batch(() => {
523
+ setter((draft) => {
524
+ const arr = draft ?? [];
525
+ arr.pop();
526
+ return arr;
527
+ });
528
+ scheduleDisposal([removed]);
529
+ notifyRemoved([removed], [index]);
461
530
  });
462
- scheduleDisposal([removed]);
463
531
  return removed;
464
532
  },
465
533
  shift() {
466
534
  const currentArray = getArray();
467
535
  if (currentArray.length === 0) return void 0;
468
536
  const removed = currentArray[0];
469
- setter((draft) => {
470
- const arr = draft ?? [];
471
- arr.shift();
472
- return arr;
537
+ batch(() => {
538
+ setter((draft) => {
539
+ const arr = draft ?? [];
540
+ arr.shift();
541
+ return arr;
542
+ });
543
+ scheduleDisposal([removed]);
544
+ notifyRemoved([removed], [0]);
473
545
  });
474
- scheduleDisposal([removed]);
475
546
  return removed;
476
547
  },
477
548
  remove(...items) {
@@ -486,27 +557,33 @@ function list(options) {
486
557
  }
487
558
  }
488
559
  if (removed.length === 0) return 0;
489
- indicesToRemove.sort((a2, b) => b - a2);
490
- setter((draft) => {
491
- const arr = draft ?? [];
492
- for (const idx of indicesToRemove) {
493
- arr.splice(idx, 1);
494
- }
495
- return arr;
560
+ const sortedIndices = [...indicesToRemove].sort((a2, b) => b - a2);
561
+ batch(() => {
562
+ setter((draft) => {
563
+ const arr = draft ?? [];
564
+ for (const idx of sortedIndices) {
565
+ arr.splice(idx, 1);
566
+ }
567
+ return arr;
568
+ });
569
+ scheduleDisposal(removed);
570
+ notifyRemoved(removed, indicesToRemove);
496
571
  });
497
- scheduleDisposal(removed);
498
572
  return removed.length;
499
573
  },
500
574
  removeAt(index) {
501
575
  const currentArray = getArray();
502
576
  if (index < 0 || index >= currentArray.length) return void 0;
503
577
  const removed = currentArray[index];
504
- setter((draft) => {
505
- const arr = draft ?? [];
506
- arr.splice(index, 1);
507
- return arr;
578
+ batch(() => {
579
+ setter((draft) => {
580
+ const arr = draft ?? [];
581
+ arr.splice(index, 1);
582
+ return arr;
583
+ });
584
+ scheduleDisposal([removed]);
585
+ notifyRemoved([removed], [index]);
508
586
  });
509
- scheduleDisposal([removed]);
510
587
  return removed;
511
588
  },
512
589
  removeWhere(predicate) {
@@ -520,23 +597,30 @@ function list(options) {
520
597
  }
521
598
  }
522
599
  if (removed.length === 0) return 0;
523
- indicesToRemove.sort((a2, b) => b - a2);
524
- setter((draft) => {
525
- const arr = draft ?? [];
526
- for (const idx of indicesToRemove) {
527
- arr.splice(idx, 1);
528
- }
529
- return arr;
600
+ const sortedIndices = [...indicesToRemove].sort((a2, b) => b - a2);
601
+ batch(() => {
602
+ setter((draft) => {
603
+ const arr = draft ?? [];
604
+ for (const idx of sortedIndices) {
605
+ arr.splice(idx, 1);
606
+ }
607
+ return arr;
608
+ });
609
+ scheduleDisposal(removed);
610
+ notifyRemoved(removed, indicesToRemove);
530
611
  });
531
- scheduleDisposal(removed);
532
612
  return removed.length;
533
613
  },
534
614
  insert(index, ...items) {
535
- cancelDisposal(items);
536
- setter((draft) => {
537
- const arr = draft ?? [];
538
- arr.splice(index, 0, ...items);
539
- return arr;
615
+ if (items.length === 0) return;
616
+ batch(() => {
617
+ cancelDisposal(items);
618
+ setter((draft) => {
619
+ const arr = draft ?? [];
620
+ arr.splice(index, 0, ...items);
621
+ return arr;
622
+ });
623
+ notifyAdded(items, index);
540
624
  });
541
625
  },
542
626
  set(index, itemOrReducerOrUpdater) {
@@ -545,39 +629,91 @@ function list(options) {
545
629
  if (isFunction && (index < 0 || index >= currentArray.length)) {
546
630
  return;
547
631
  }
548
- if (!isFunction) {
549
- cancelDisposal([itemOrReducerOrUpdater]);
550
- }
551
632
  const old = index >= 0 && index < currentArray.length ? currentArray[index] : void 0;
552
- setter((draft) => {
553
- const arr = draft ?? [];
554
- if (isFunction) {
555
- const fn = itemOrReducerOrUpdater;
556
- if (index >= 0 && index < arr.length) {
557
- const result = fn(arr[index]);
558
- if (result !== void 0) {
559
- arr[index] = result;
633
+ batch(() => {
634
+ if (!isFunction) {
635
+ cancelDisposal([itemOrReducerOrUpdater]);
636
+ }
637
+ setter((draft) => {
638
+ const arr = draft ?? [];
639
+ if (isFunction) {
640
+ const fn = itemOrReducerOrUpdater;
641
+ if (index >= 0 && index < arr.length) {
642
+ const result = fn(arr[index]);
643
+ if (result !== void 0) {
644
+ arr[index] = result;
645
+ }
560
646
  }
647
+ } else {
648
+ arr[index] = itemOrReducerOrUpdater;
561
649
  }
562
- } else {
563
- arr[index] = itemOrReducerOrUpdater;
650
+ return arr;
651
+ });
652
+ const newValue = getArray()[index];
653
+ if (old !== void 0 && old !== newValue) {
654
+ scheduleDisposal([old]);
655
+ notifyRemoved([old], [index]);
656
+ notifyAdded([newValue], index);
564
657
  }
658
+ });
659
+ },
660
+ tryGet(index, create) {
661
+ const currentArray = getArray();
662
+ if (index >= 0 && index < currentArray.length) {
663
+ return currentArray[index];
664
+ }
665
+ const item = create();
666
+ batch(() => {
667
+ cancelDisposal([item]);
668
+ setter((draft) => {
669
+ const arr = draft ?? [];
670
+ while (arr.length <= index) {
671
+ arr.push(void 0);
672
+ }
673
+ arr[index] = item;
674
+ return arr;
675
+ });
676
+ notifyAdded([item], index);
677
+ });
678
+ return item;
679
+ },
680
+ swap(indexA, indexB) {
681
+ if (indexA === indexB) return;
682
+ const currentArray = getArray();
683
+ if (indexA < 0 || indexA >= currentArray.length || indexB < 0 || indexB >= currentArray.length) {
684
+ return;
685
+ }
686
+ setter((draft) => {
687
+ const arr = draft ?? [];
688
+ const temp = arr[indexA];
689
+ arr[indexA] = arr[indexB];
690
+ arr[indexB] = temp;
565
691
  return arr;
566
692
  });
567
- const newValue = getArray()[index];
568
- if (old !== void 0 && old !== newValue) scheduleDisposal([old]);
569
693
  },
570
694
  clear() {
571
695
  const old = getArray();
572
- setter([]);
573
- scheduleDisposal(old);
696
+ if (old.length === 0) return;
697
+ const indices = old.map((_, i) => i);
698
+ batch(() => {
699
+ setter([]);
700
+ scheduleDisposal(old);
701
+ notifyRemoved(old, indices);
702
+ });
574
703
  },
575
704
  replace(items) {
576
- cancelDisposal(items);
577
705
  const old = getArray();
578
- setter(items);
579
- const toDispose = old.filter((item) => !items.includes(item));
580
- scheduleDisposal(toDispose);
706
+ batch(() => {
707
+ cancelDisposal(items);
708
+ setter(items);
709
+ const toDispose = old.filter((item) => !items.includes(item));
710
+ const removedIndices = toDispose.map((item) => old.indexOf(item));
711
+ scheduleDisposal(toDispose);
712
+ notifyRemoved(toDispose, removedIndices);
713
+ const newItems = items.filter((item) => !old.includes(item));
714
+ const addedIndices = newItems.map((item) => items.indexOf(item));
715
+ newItems.forEach((item, i) => onAdded == null ? void 0 : onAdded(item, addedIndices[i]));
716
+ });
581
717
  },
582
718
  find(predicate) {
583
719
  return getArray().find(predicate);
@@ -601,15 +737,24 @@ function list(options) {
601
737
  };
602
738
  }
603
739
  function map(options) {
604
- const autoDispose = (options == null ? void 0 : options.autoDispose) ?? false;
740
+ const autoDisposeResult = normalizeAutoDispose(options == null ? void 0 : options.autoDispose);
741
+ const gracePeriodMs = autoDisposeResult ? autoDisposeResult.gracePeriodMs : 0;
742
+ const group = autoDisposeResult ? autoDisposeResult.group : null;
743
+ const onAdded = options == null ? void 0 : options.onAdded;
744
+ const onRemoved = options == null ? void 0 : options.onRemoved;
605
745
  const defaultValue = {};
606
746
  return (inputFocus) => {
607
747
  const focus = inputFocus;
608
748
  const [getter, setter] = focus;
609
- const tracker = autoDispose ? createDisposalTracker() : null;
749
+ const tracker = autoDisposeResult ? group ?? createLocalDisposalTracker(gracePeriodMs) : null;
610
750
  const getRecord = () => getter() ?? defaultValue;
611
751
  const scheduleDisposal = (items) => {
612
- tracker == null ? void 0 : tracker.scheduleDisposal(items);
752
+ if (!tracker) return;
753
+ if ("flush" in tracker) {
754
+ tracker.scheduleDisposal(items, gracePeriodMs);
755
+ } else {
756
+ tracker.scheduleDisposal(items);
757
+ }
613
758
  };
614
759
  const cancelDisposal = (items) => {
615
760
  tracker == null ? void 0 : tracker.cancelDisposal(items);
@@ -632,80 +777,136 @@ function map(options) {
632
777
  const isFunction = typeof valueOrReducerOrUpdater === "function";
633
778
  const currentRecord = getRecord();
634
779
  if (isFunction && !(key in currentRecord)) return;
635
- if (!isFunction) {
636
- cancelDisposal([valueOrReducerOrUpdater]);
637
- }
638
780
  const old = currentRecord[key];
639
- setter((draft) => {
640
- const rec = draft ?? {};
641
- if (isFunction) {
642
- const fn = valueOrReducerOrUpdater;
643
- const result = fn(rec[key]);
644
- if (result !== void 0) {
645
- rec[key] = result;
781
+ const hadKey = key in currentRecord;
782
+ batch(() => {
783
+ if (!isFunction) {
784
+ cancelDisposal([valueOrReducerOrUpdater]);
785
+ }
786
+ setter((draft) => {
787
+ const rec = draft ?? {};
788
+ if (isFunction) {
789
+ const fn = valueOrReducerOrUpdater;
790
+ const result = fn(rec[key]);
791
+ if (result !== void 0) {
792
+ rec[key] = result;
793
+ }
794
+ } else {
795
+ rec[key] = valueOrReducerOrUpdater;
646
796
  }
647
- } else {
648
- rec[key] = valueOrReducerOrUpdater;
797
+ return rec;
798
+ });
799
+ const newValue = getRecord()[key];
800
+ if (hadKey && old !== newValue) {
801
+ scheduleDisposal([old]);
802
+ onRemoved == null ? void 0 : onRemoved(old, key);
803
+ }
804
+ if (!hadKey || old !== newValue) {
805
+ onAdded == null ? void 0 : onAdded(newValue, key);
649
806
  }
807
+ });
808
+ },
809
+ tryGet(key, create) {
810
+ const currentRecord = getRecord();
811
+ if (key in currentRecord) {
812
+ return currentRecord[key];
813
+ }
814
+ const value = create();
815
+ batch(() => {
816
+ cancelDisposal([value]);
817
+ setter((draft) => {
818
+ const rec = draft ?? {};
819
+ rec[key] = value;
820
+ return rec;
821
+ });
822
+ onAdded == null ? void 0 : onAdded(value, key);
823
+ });
824
+ return value;
825
+ },
826
+ swap(keyA, keyB) {
827
+ if (keyA === keyB) return;
828
+ const currentRecord = getRecord();
829
+ if (!(keyA in currentRecord) || !(keyB in currentRecord)) return;
830
+ setter((draft) => {
831
+ const rec = draft ?? {};
832
+ const temp = rec[keyA];
833
+ rec[keyA] = rec[keyB];
834
+ rec[keyB] = temp;
650
835
  return rec;
651
836
  });
652
- const newValue = getRecord()[key];
653
- if (old !== void 0 && old !== newValue) scheduleDisposal([old]);
654
837
  },
655
838
  delete(...keys) {
656
839
  const currentRecord = getRecord();
657
840
  const removed = [];
658
- const keysToDelete = [];
659
841
  for (const key of keys) {
660
842
  if (key in currentRecord) {
661
- removed.push(currentRecord[key]);
662
- keysToDelete.push(key);
843
+ removed.push({ value: currentRecord[key], key });
663
844
  }
664
845
  }
665
846
  if (removed.length === 0) return 0;
666
- setter((draft) => {
667
- const rec = draft ?? {};
668
- for (const key of keysToDelete) {
669
- delete rec[key];
670
- }
671
- return rec;
847
+ batch(() => {
848
+ setter((draft) => {
849
+ const rec = draft ?? {};
850
+ for (const { key } of removed) {
851
+ delete rec[key];
852
+ }
853
+ return rec;
854
+ });
855
+ scheduleDisposal(removed.map((r) => r.value));
856
+ removed.forEach(({ value, key }) => onRemoved == null ? void 0 : onRemoved(value, key));
672
857
  });
673
- scheduleDisposal(removed);
674
858
  return removed.length;
675
859
  },
676
860
  deleteWhere(predicate) {
677
861
  const currentRecord = getRecord();
678
862
  const removed = [];
679
- const keysToDelete = [];
680
863
  for (const key of Object.keys(currentRecord)) {
681
864
  if (predicate(currentRecord[key], key)) {
682
- removed.push(currentRecord[key]);
683
- keysToDelete.push(key);
865
+ removed.push({ value: currentRecord[key], key });
684
866
  }
685
867
  }
686
868
  if (removed.length === 0) return 0;
687
- setter((draft) => {
688
- const rec = draft ?? {};
689
- for (const key of keysToDelete) {
690
- delete rec[key];
691
- }
692
- return rec;
869
+ batch(() => {
870
+ setter((draft) => {
871
+ const rec = draft ?? {};
872
+ for (const { key } of removed) {
873
+ delete rec[key];
874
+ }
875
+ return rec;
876
+ });
877
+ scheduleDisposal(removed.map((r) => r.value));
878
+ removed.forEach(({ value, key }) => onRemoved == null ? void 0 : onRemoved(value, key));
693
879
  });
694
- scheduleDisposal(removed);
695
880
  return removed.length;
696
881
  },
697
882
  clear() {
698
- const old = Object.values(getRecord());
699
- setter({});
700
- scheduleDisposal(old);
883
+ const old = getRecord();
884
+ const entries = Object.entries(old);
885
+ if (entries.length === 0) return;
886
+ batch(() => {
887
+ setter({});
888
+ scheduleDisposal(Object.values(old));
889
+ entries.forEach(([key, value]) => onRemoved == null ? void 0 : onRemoved(value, key));
890
+ });
701
891
  },
702
892
  replace(record) {
703
- cancelDisposal(Object.values(record));
704
893
  const old = getRecord();
705
- setter(record);
706
- const newKeys = new Set(Object.keys(record));
707
- const toDispose = Object.entries(old).filter(([key]) => !newKeys.has(key)).map(([, value]) => value);
708
- scheduleDisposal(toDispose);
894
+ batch(() => {
895
+ cancelDisposal(Object.values(record));
896
+ setter(record);
897
+ const newKeys = new Set(Object.keys(record));
898
+ const toDispose = Object.entries(old).filter(
899
+ ([key]) => !newKeys.has(key)
900
+ );
901
+ scheduleDisposal(toDispose.map(([, value]) => value));
902
+ toDispose.forEach(([key, value]) => onRemoved == null ? void 0 : onRemoved(value, key));
903
+ const oldKeys = new Set(Object.keys(old));
904
+ Object.entries(record).forEach(([key, value]) => {
905
+ if (!oldKeys.has(key) || old[key] !== value) {
906
+ onAdded == null ? void 0 : onAdded(value, key);
907
+ }
908
+ });
909
+ });
709
910
  },
710
911
  keys() {
711
912
  return Object.keys(getRecord());
@@ -722,6 +923,36 @@ function map(options) {
722
923
  };
723
924
  };
724
925
  }
926
+ function toggle() {
927
+ return (prev) => !prev;
928
+ }
929
+ function increment(amount = 1) {
930
+ return (prev) => (prev ?? 0) + amount;
931
+ }
932
+ function decrement(amount = 1) {
933
+ return (prev) => (prev ?? 0) - amount;
934
+ }
935
+ function multiply(factor) {
936
+ return (prev) => (prev ?? 0) * factor;
937
+ }
938
+ function divide(divisor) {
939
+ return (prev) => (prev ?? 0) / divisor;
940
+ }
941
+ function clamp(min, max) {
942
+ return (prev) => Math.min(max, Math.max(min, prev ?? 0));
943
+ }
944
+ function append(suffix) {
945
+ return (prev) => (prev ?? "") + suffix;
946
+ }
947
+ function prepend(prefix) {
948
+ return (prev) => prefix + (prev ?? "");
949
+ }
950
+ function merge(partial) {
951
+ return (prev) => ({ ...prev, ...partial });
952
+ }
953
+ function reset(defaultValue) {
954
+ return () => defaultValue;
955
+ }
725
956
  function patternToPredicate(pattern) {
726
957
  if (pattern instanceof RegExp) {
727
958
  return (name) => pattern.test(name);
@@ -880,33 +1111,35 @@ export {
880
1111
  H as HooksContextError,
881
1112
  I as InvalidActionError,
882
1113
  L as LifetimeMismatchError,
883
- z as LocalStoreDependencyError,
1114
+ B as LocalStoreDependencyError,
884
1115
  P as ProviderMissingError,
885
1116
  STORION_TYPE,
886
1117
  S as SetupPhaseError,
887
- y as StoreDisposedError,
888
- x as StorionError,
1118
+ z as StoreDisposedError,
1119
+ y as StorionError,
889
1120
  append,
890
1121
  applyExcept,
891
1122
  applyFor,
892
- n as batch,
1123
+ batch,
893
1124
  clamp,
894
1125
  container,
895
1126
  decrement,
896
- v as deepEqual,
1127
+ x as deepEqual,
1128
+ disposalGroup,
897
1129
  divide,
898
1130
  e as effect,
899
- o as equality,
1131
+ q as equality,
900
1132
  forStores,
1133
+ getNamedGroup,
901
1134
  increment,
902
- m as is,
1135
+ n as is,
903
1136
  list,
904
1137
  map,
905
1138
  merge,
906
- m2 as meta,
1139
+ m as meta,
907
1140
  multiply,
908
1141
  p as pick,
909
- B as pool,
1142
+ C as pool,
910
1143
  prepend,
911
1144
  reset,
912
1145
  createResolver as resolver,