@mmstack/primitives 21.8.0 → 21.8.2

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@mmstack/primitives",
3
- "version": "21.8.0",
3
+ "version": "21.8.2",
4
4
  "keywords": [
5
5
  "angular",
6
6
  "signals",
@@ -3094,10 +3094,14 @@ declare const STORE_SHARED_GLOBALS: unique symbol;
3094
3094
  type ProxyCache = WeakMap<object, Map<PropertyKey, WeakRef<Signal<any>>>>;
3095
3095
  /**
3096
3096
  * @internal
3097
- * Prunes a cache entry once its proxy is reclaimed by the GC.
3097
+ * Prunes a cache entry once its proxy is reclaimed by the GC. The held value must reference
3098
+ * `target` only weakly: held values are retained by the registry until its cleanup callbacks
3099
+ * run (host tasks — they never run inside a synchronous burst), so a strong `target` here
3100
+ * keeps every dropped subtree's backing-signal ancestry alive across GCs. If `target` is
3101
+ * already dead its whole cache entry died with it (WeakMap), and there is nothing to prune.
3098
3102
  */
3099
3103
  type ProxyCleanupRegistry = FinalizationRegistry<{
3100
- target: object;
3104
+ targetRef: WeakRef<object>;
3101
3105
  prop: PropertyKey;
3102
3106
  }>;
3103
3107
  /**
@@ -3767,6 +3771,12 @@ type StoreHistory = {
3767
3771
  undo(): void;
3768
3772
  /** Re-apply the most recently undone change. */
3769
3773
  redo(): void;
3774
+ /**
3775
+ * Close the current coalescing run: the next tracked change starts a NEW undo entry even if
3776
+ * it lands inside the `coalesce` window. Call it on the boundaries your UX considers an
3777
+ * action — a field blur, a selection change, a drag drop. A no-op without `coalesce`.
3778
+ */
3779
+ checkpoint(): void;
3770
3780
  /** Forget all tracked history (e.g. after a save boundary). */
3771
3781
  clear(): void;
3772
3782
  destroy(): void;
@@ -3778,11 +3788,29 @@ type StoreHistoryOptions = CreateOpLogOptions & {
3778
3788
  * The change stream to track. Defaults to self-diffing `source` (every change to the store
3779
3789
  * becomes undoable). For collaborative-safe undo, pass a sync client's LOCAL envelope stream
3780
3790
  * (e.g. an `opSync`'s `subscribe`, which fires only for this peer's own writes) — remote
3781
- * peers' changes then never land on your undo stack.
3791
+ * peers' changes then never land on your undo stack. When the stream exposes `flush` (an
3792
+ * `opSync` does), undo/redo drain it synchronously so their own emissions never echo back
3793
+ * onto the stack as fresh entries.
3782
3794
  */
3783
3795
  readonly track?: {
3784
3796
  subscribe(cb: (batch: OpBatch) => void): () => void;
3797
+ flush?(): void;
3798
+ };
3799
+ /**
3800
+ * Merge rapid consecutive edits into ONE undo entry, so a typing run undoes as a unit
3801
+ * instead of per keystroke. A tracked change arriving within `ms` of the previous one AND
3802
+ * touching the same paths with the same op kinds extends the previous entry (set
3803
+ * `samePath: false` to merge on time alone); anything else — a different field, a kind
3804
+ * change, a pause longer than `ms`, a `checkpoint()`, an undo/redo — starts a new entry.
3805
+ * The window is measured between consecutive changes, so an unbroken run keeps merging.
3806
+ * Undoing a merged entry is exactly equivalent to undoing its changes one by one.
3807
+ */
3808
+ readonly coalesce?: {
3809
+ readonly ms: number;
3810
+ readonly samePath?: boolean;
3785
3811
  };
3812
+ /** Clock for the coalescing window (injectable for tests; default `Date.now`). */
3813
+ readonly now?: () => number;
3786
3814
  };
3787
3815
  /**
3788
3816
  * Undo/redo for a copy-on-write store, built on the op-log: each tracked change is stored as
@@ -3792,7 +3820,8 @@ type StoreHistoryOptions = CreateOpLogOptions & {
3792
3820
  *
3793
3821
  * Composes with sync for collaborative undo: pass `track: syncClient` so only YOUR writes are
3794
3822
  * undoable, while `undo()` emits a normal op that propagates to peers (it writes through the
3795
- * store, which the sync client picks up).
3823
+ * store, which the sync client picks up). Coalescing groups only this stack's entries — what
3824
+ * goes over the wire is untouched.
3796
3825
  */
3797
3826
  declare function storeHistory<T extends object>(source: WritableSignal<T>, opt?: StoreHistoryOptions): StoreHistory;
3798
3827