@buoy-gg/zustand 7.0.32 → 7.0.34

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (35) hide show
  1. package/lib/commonjs/zustand/components/ZustandDetailViewToggle.js +13 -107
  2. package/lib/commonjs/zustand/components/ZustandEventFilterView.js +24 -288
  3. package/lib/commonjs/zustand/components/ZustandModal.js +83 -141
  4. package/lib/commonjs/zustand/components/ZustandStateChangeItem.js +8 -61
  5. package/lib/commonjs/zustand/components/ZustandStateInfoView.js +2 -46
  6. package/lib/commonjs/zustand/components/ZustandStoreBrowser.js +29 -54
  7. package/lib/commonjs/zustand/hooks/useZustandStateChanges.js +33 -53
  8. package/lib/commonjs/zustand/sync/zustandSyncAdapter.js +24 -78
  9. package/lib/commonjs/zustand/utils/snapshotProvider.js +17 -60
  10. package/lib/commonjs/zustand/utils/zustandStateStore.js +37 -223
  11. package/lib/module/zustand/components/ZustandDetailViewToggle.js +15 -109
  12. package/lib/module/zustand/components/ZustandEventFilterView.js +28 -292
  13. package/lib/module/zustand/components/ZustandModal.js +85 -143
  14. package/lib/module/zustand/components/ZustandStateChangeItem.js +10 -63
  15. package/lib/module/zustand/components/ZustandStateInfoView.js +1 -45
  16. package/lib/module/zustand/components/ZustandStoreBrowser.js +31 -56
  17. package/lib/module/zustand/hooks/useZustandStateChanges.js +34 -54
  18. package/lib/module/zustand/sync/zustandSyncAdapter.js +25 -79
  19. package/lib/module/zustand/utils/snapshotProvider.js +18 -61
  20. package/lib/module/zustand/utils/zustandStateStore.js +37 -223
  21. package/lib/typescript/zustand/components/ZustandDetailViewToggle.d.ts +2 -1
  22. package/lib/typescript/zustand/components/ZustandDetailViewToggle.d.ts.map +1 -1
  23. package/lib/typescript/zustand/components/ZustandEventFilterView.d.ts +6 -0
  24. package/lib/typescript/zustand/components/ZustandEventFilterView.d.ts.map +1 -1
  25. package/lib/typescript/zustand/components/ZustandModal.d.ts.map +1 -1
  26. package/lib/typescript/zustand/components/ZustandStateChangeItem.d.ts.map +1 -1
  27. package/lib/typescript/zustand/components/ZustandStateInfoView.d.ts.map +1 -1
  28. package/lib/typescript/zustand/components/ZustandStoreBrowser.d.ts.map +1 -1
  29. package/lib/typescript/zustand/hooks/useZustandStateChanges.d.ts +2 -1
  30. package/lib/typescript/zustand/hooks/useZustandStateChanges.d.ts.map +1 -1
  31. package/lib/typescript/zustand/sync/zustandSyncAdapter.d.ts +103 -117
  32. package/lib/typescript/zustand/sync/zustandSyncAdapter.d.ts.map +1 -1
  33. package/lib/typescript/zustand/utils/zustandStateStore.d.ts +6 -26
  34. package/lib/typescript/zustand/utils/zustandStateStore.d.ts.map +1 -1
  35. package/package.json +3 -3
@@ -13,8 +13,7 @@
13
13
  * strips functions (recording where they were), and restore re-grafts the
14
14
  * LIVE store's functions onto the snapshot before replacing.
15
15
  */
16
- import { registerStateSnapshotProvider } from "@buoy-gg/shared-ui";
17
- import { boundedDeepEqual, jsonLikelyLargerThan } from "@buoy-gg/shared-ui/dataViewer";
16
+ import { classifyPreviewItem, createRestoreScope, emptyRestoreResult, failedRestore, registerStateSnapshotProvider, unionKeys } from "@buoy-gg/shared-ui";
18
17
  import { zustandStateStore } from "./zustandStateStore";
19
18
  import { isPlainObjectLike, stripFunctions, STRIP_MAX_DEPTH } from "./editableState";
20
19
 
@@ -93,29 +92,13 @@ async function capture() {
93
92
  }
94
93
  async function restore(data, options) {
95
94
  const snapshot = data;
96
- const excludedSet = new Set(options?.excludeKeys ?? []);
97
- const includedSet = options?.includeKeys ? new Set(options.includeKeys) : null;
98
- const touch = key => !excludedSet.has(key) && (!includedSet || includedSet.has(key));
99
- let excludedHits = 0;
100
- const result = {
101
- ok: true,
102
- applied: 0,
103
- skipped: [],
104
- warnings: []
105
- };
95
+ const scope = createRestoreScope(options);
96
+ const result = emptyRestoreResult();
106
97
  if (!snapshot?.stores) {
107
- return {
108
- ok: false,
109
- applied: 0,
110
- skipped: [],
111
- warnings: ["empty zustand snapshot"]
112
- };
98
+ return failedRestore("empty zustand snapshot");
113
99
  }
114
100
  for (const [name, envelope] of Object.entries(snapshot.stores)) {
115
- if (!touch(name)) {
116
- excludedHits += 1;
117
- continue;
118
- }
101
+ if (!scope.allows(name)) continue;
119
102
  const info = zustandStateStore.getStore(name);
120
103
  if (!info) {
121
104
  result.skipped.push({
@@ -142,12 +125,10 @@ async function restore(data, options) {
142
125
  result.ok = false;
143
126
  }
144
127
  }
145
- if (excludedHits > 0) {
146
- result.warnings.push(`${excludedHits} store(s) excluded by you`);
147
- }
128
+ const excludedWarning = scope.excludedWarning("store(s)");
129
+ if (excludedWarning) result.warnings.push(excludedWarning);
148
130
  return result;
149
131
  }
150
- const ITEM_RENDER_BYTE_LIMIT = 256 * 1024;
151
132
 
152
133
  /**
153
134
  * Per-store restore preview. Both sides are function-stripped through the
@@ -176,8 +157,7 @@ async function previewItems(target, base) {
176
157
  const items = [];
177
158
  const notes = [];
178
159
  let preservedFns = 0;
179
- const names = new Set([...Object.keys(baseStores), ...Object.keys(targetStores)]);
180
- for (const name of names) {
160
+ for (const name of unionKeys(baseStores, targetStores)) {
181
161
  const inTarget = name in targetStores;
182
162
  const inBase = name in baseStores;
183
163
  if (!inTarget) {
@@ -200,39 +180,16 @@ async function previewItems(target, base) {
200
180
  });
201
181
  continue;
202
182
  }
203
- if (!inBase) {
204
- items.push({
205
- key: name,
206
- label: name,
207
- verdict: "added",
208
- newValue: targetStores[name].state
209
- });
210
- continue;
211
- }
212
- const oldState = baseStores[name].state;
213
- const newState = targetStores[name].state;
214
- if (boundedDeepEqual(oldState, newState)) {
215
- items.push({
216
- key: name,
217
- label: name,
218
- verdict: "unchanged"
219
- });
220
- } else if (jsonLikelyLargerThan(oldState, ITEM_RENDER_BYTE_LIMIT) || jsonLikelyLargerThan(newState, ITEM_RENDER_BYTE_LIMIT)) {
221
- items.push({
222
- key: name,
223
- label: name,
224
- verdict: "too-large",
225
- reason: "store too large to render a diff — restore still applies it"
226
- });
227
- } else {
228
- items.push({
229
- key: name,
230
- label: name,
231
- verdict: "changed",
232
- oldValue: oldState,
233
- newValue: newState
234
- });
235
- }
183
+ items.push(classifyPreviewItem({
184
+ key: name,
185
+ label: name,
186
+ oldValue: baseStores[name]?.state,
187
+ newValue: targetStores[name].state,
188
+ inOld: inBase,
189
+ inNew: true
190
+ }, {
191
+ tooLargeReason: "store too large to render a diff — restore still applies it"
192
+ }));
236
193
  }
237
194
  if (preservedFns > 0) {
238
195
  notes.push(`${preservedFns} store action function${preservedFns === 1 ? "" : "s"} preserved on restore (not diffed)`);
@@ -3,9 +3,13 @@
3
3
  /**
4
4
  * Zustand state store - captures and stores Zustand state changes
5
5
  *
6
- * Mirrors the architecture of reduxActionStore.ts from @buoy-gg/redux
6
+ * The generic event-log half (ring buffer, listeners, clear-forwarding for
7
+ * the desktop mirror, pause/suppress flags, hydrate-by-id) is the shared
8
+ * `ChangeLog`; this file owns the zustand-specific half — the store registry,
9
+ * snapshots, mirror rebuild, filters and stats.
7
10
  */
8
11
 
12
+ import { ChangeLog, entityColor, formatValuePreview, shallowDiffSummary } from "@buoy-gg/shared-ui";
9
13
  // ============================================
10
14
  // Store Color Palette
11
15
  // ============================================
@@ -36,168 +40,33 @@ const STORE_COLORS = {
36
40
  * Get consistent color for a store based on its name
37
41
  */
38
42
  function getStoreColor(storeName) {
39
- const lowerName = storeName.toLowerCase();
40
-
41
- // Check for exact match
42
- if (STORE_COLORS[lowerName]) {
43
- return STORE_COLORS[lowerName];
44
- }
45
-
46
- // Check for partial matches
47
- for (const [key, color] of Object.entries(STORE_COLORS)) {
48
- if (lowerName.includes(key)) {
49
- return color;
50
- }
51
- }
52
-
53
- // Generate consistent hex color from name hash
54
- const hash = storeName.split("").reduce((acc, char) => acc + char.charCodeAt(0), 0);
55
- const hue = hash * 137 % 360;
56
- // Convert HSL to hex so "color + alpha_hex" pattern works everywhere
57
- const s = 0.7;
58
- const l = 0.6;
59
- const c = (1 - Math.abs(2 * l - 1)) * s;
60
- const x = c * (1 - Math.abs(hue / 60 % 2 - 1));
61
- const m = l - c / 2;
62
- let r = 0,
63
- g = 0,
64
- b = 0;
65
- if (hue < 60) {
66
- r = c;
67
- g = x;
68
- } else if (hue < 120) {
69
- r = x;
70
- g = c;
71
- } else if (hue < 180) {
72
- g = c;
73
- b = x;
74
- } else if (hue < 240) {
75
- g = x;
76
- b = c;
77
- } else if (hue < 300) {
78
- r = x;
79
- b = c;
80
- } else {
81
- r = c;
82
- b = x;
83
- }
84
- const toHex = v => Math.round((v + m) * 255).toString(16).padStart(2, "0");
85
- return `#${toHex(r)}${toHex(g)}${toHex(b)}`;
43
+ return entityColor(storeName, STORE_COLORS);
86
44
  }
87
45
 
88
- // ============================================
89
- // Helper Functions
90
- // ============================================
91
-
92
46
  /**
93
47
  * Format payload preview for display
94
48
  */
95
49
  function formatPartialPreview(partial, maxLength = 40) {
96
- if (partial === undefined) return "";
97
- if (partial === null) return "null";
98
- try {
99
- if (typeof partial === "function") {
100
- return "(updater fn)";
101
- }
102
- if (typeof partial === "string") {
103
- return partial.length > maxLength ? `"${partial.slice(0, maxLength - 3)}..."` : `"${partial}"`;
104
- }
105
- if (typeof partial === "number" || typeof partial === "boolean") {
106
- return String(partial);
107
- }
108
- if (Array.isArray(partial)) {
109
- if (partial.length === 0) return "[]";
110
- const preview = JSON.stringify(partial);
111
- return preview.length > maxLength ? `[${partial.length} items]` : preview;
112
- }
113
- if (typeof partial === "object") {
114
- const keys = Object.keys(partial);
115
- if (keys.length === 0) return "{}";
116
- const preview = JSON.stringify(partial);
117
- if (preview.length <= maxLength) return preview;
118
- return `{ ${keys.length} keys }`;
119
- }
120
- return String(partial).slice(0, maxLength);
121
- } catch {
122
- return "[complex]";
123
- }
124
- }
125
-
126
- /**
127
- * Calculate state diff summary.
128
- *
129
- * `changedCount` counts the keys in `changedKeys` and nothing else. The two
130
- * used to disagree: a state object that was REPLACED without any top-level
131
- * value moving — which is exactly what zustand's persist middleware does when
132
- * it rehydrates — reported one changed key and named none, so the row said
133
- * "1 key changed" and the detail page it opened drew no CHANGED KEYS card at
134
- * all. `summary` is where a change with no nameable keys is described.
135
- */
136
- function getStateDiffSummary(prevState, nextState) {
137
- if (prevState === nextState) {
138
- return {
139
- summary: "no change",
140
- changedKeys: [],
141
- changedCount: 0
142
- };
143
- }
144
- if (typeof prevState !== "object" || typeof nextState !== "object" || prevState === null || nextState === null) {
145
- return {
146
- summary: "changed",
147
- changedKeys: [],
148
- changedCount: 0
149
- };
150
- }
151
- const prevKeys = Object.keys(prevState);
152
- const nextKeys = Object.keys(nextState);
153
- const added = nextKeys.filter(k => !prevKeys.includes(k));
154
- const removed = prevKeys.filter(k => !nextKeys.includes(k));
155
- const changed = [];
156
- for (const key of prevKeys) {
157
- if (nextKeys.includes(key) && prevState[key] !== nextState[key]) {
158
- changed.push(key);
159
- }
160
- }
161
- const allChangedKeys = [...added, ...removed, ...changed];
162
- const parts = [];
163
- if (added.length > 0) parts.push(`+${added.length}`);
164
- if (removed.length > 0) parts.push(`-${removed.length}`);
165
- if (changed.length > 0) parts.push(`~${changed.length}`);
166
- const totalChanged = allChangedKeys.length;
167
- if (parts.length === 0) {
168
- return {
169
- summary: "nested change",
170
- changedKeys: [],
171
- changedCount: 0
172
- };
173
- }
174
- return {
175
- summary: `${parts.join(" ")} ${totalChanged === 1 ? "key" : "keys"}`,
176
- changedKeys: allChangedKeys,
177
- changedCount: totalChanged
178
- };
50
+ return formatValuePreview(partial, {
51
+ maxLength,
52
+ undefinedLabel: "",
53
+ functionLabel: "(updater fn)"
54
+ });
179
55
  }
180
56
 
181
57
  // ============================================
182
58
  // Zustand State Store
183
59
  // ============================================
184
60
 
185
- class ZustandStateStore {
186
- stateChanges = [];
61
+ class ZustandStateStore extends ChangeLog {
187
62
  stores = new Map();
188
- listeners = new Set();
189
63
  storeListeners = new Set();
190
- clearListeners = new Set();
191
- maxChanges = 200;
192
- idCounter = 0;
193
- isEnabled = true;
194
- captureSuppressed = false;
195
64
  remoteSetStateHandler = null;
196
65
 
197
66
  // ---- State Change Tracking ----
198
67
 
199
68
  addStateChange(params) {
200
- if (!this.isEnabled || this.captureSuppressed) return;
69
+ if (!this.canRecord()) return;
201
70
  const {
202
71
  storeName,
203
72
  partial,
@@ -209,16 +78,20 @@ class ZustandStateStore {
209
78
  isPersisted = false
210
79
  } = params;
211
80
  const hasStateChange = prevState !== nextState;
81
+ // `changedCount` counts the keys in `changedKeys` and nothing else, so the
82
+ // row's "N keys changed" and the detail page's CHANGED KEYS card agree —
83
+ // including the persist-rehydrate case where the object is replaced
84
+ // without any top-level value moving.
212
85
  const {
213
86
  summary,
214
87
  changedKeys,
215
88
  changedCount
216
- } = getStateDiffSummary(prevState, nextState);
89
+ } = shallowDiffSummary(prevState, nextState);
217
90
  const partialPreview = formatPartialPreview(partial);
218
91
  const isSlowUpdate = (duration ?? 0) > 16;
219
92
  const resolvedCategory = category ?? (replace ? "replace" : "setState");
220
93
  const stateChange = {
221
- id: `${Date.now()}-${++this.idCounter}`,
94
+ id: this.nextId(),
222
95
  storeName,
223
96
  timestamp: Date.now(),
224
97
  prevState,
@@ -235,7 +108,7 @@ class ZustandStateStore {
235
108
  isSlowUpdate,
236
109
  isPersisted
237
110
  };
238
- this.stateChanges = [stateChange, ...this.stateChanges].slice(0, this.maxChanges);
111
+ this.push(stateChange);
239
112
 
240
113
  // Update store change count
241
114
  const storeInfo = this.stores.get(storeName);
@@ -245,36 +118,17 @@ class ZustandStateStore {
245
118
  this.notifyListeners();
246
119
  }
247
120
  getStateChanges() {
248
- return [...this.stateChanges];
121
+ return this.getAll();
249
122
  }
250
123
  getStateChangeById(id) {
251
- return this.stateChanges.find(c => c.id === id);
124
+ return this.getById(id);
252
125
  }
253
126
  clearStateChanges() {
254
- this.stateChanges = [];
255
127
  // Reset counts
256
128
  for (const store of this.stores.values()) {
257
129
  store.stateChangeCount = 0;
258
130
  }
259
- this.notifyListeners();
260
- this.clearListeners.forEach(listener => {
261
- try {
262
- listener();
263
- } catch {
264
- // Ignore listener errors
265
- }
266
- });
267
- }
268
-
269
- /**
270
- * Listen for clearStateChanges() calls. Used in remote mirror mode to
271
- * forward a clear performed in the dashboard UI to the synced device.
272
- */
273
- onClear(listener) {
274
- this.clearListeners.add(listener);
275
- return () => {
276
- this.clearListeners.delete(listener);
277
- };
131
+ this.clear();
278
132
  }
279
133
 
280
134
  // ---- Remote Mirror Mode ----
@@ -287,33 +141,19 @@ class ZustandStateStore {
287
141
  * flag so the UI's pause button freezes the reseed.
288
142
  */
289
143
  replaceStateChanges(changes) {
290
- if (!this.isEnabled) return;
291
- this.stateChanges = changes.slice(0, this.maxChanges);
144
+ if (!this.getEnabled()) return;
292
145
  for (const store of this.stores.values()) {
293
146
  store.stateChangeCount = 0;
294
147
  }
295
- for (const change of this.stateChanges) {
148
+ const kept = changes.slice(0, this.max);
149
+ for (const change of kept) {
296
150
  const store = this.stores.get(change.storeName);
297
151
  if (store) store.stateChangeCount++;
298
152
  }
299
- this.notifyListeners();
153
+ this.setItems(kept);
300
154
  this.notifyStoreListeners();
301
155
  }
302
156
 
303
- /**
304
- * Permanently suppress local capture. Use when this store acts as a mirror
305
- * of a remote device's state changes (e.g. the desktop dashboard): data
306
- * arrives via replaceFromSnapshot() and local middleware must never record.
307
- */
308
- disableCapture() {
309
- this.captureSuppressed = true;
310
- }
311
-
312
- /** Whether the store is in remote mirror mode (capture suppressed). */
313
- isCaptureSuppressed() {
314
- return this.captureSuppressed;
315
- }
316
-
317
157
  /**
318
158
  * Serializable snapshot of the tracked stores (registry metadata plus each
319
159
  * store's current state). Used by the sync adapter on the device side —
@@ -358,18 +198,18 @@ class ZustandStateStore {
358
198
  * the enabled flag so the UI's pause button freezes the mirror.
359
199
  */
360
200
  replaceFromSnapshot(changes, storeSnapshots) {
361
- if (!this.isEnabled) return;
201
+ if (!this.getEnabled()) return;
362
202
 
363
203
  // Preserve trees a remote mirror already hydrated — wire-form snapshots
364
204
  // always carry markers, and a later snapshot must not blank the detail pane.
365
205
  const hydrated = new Map();
366
- for (const existing of this.stateChanges) {
206
+ for (const existing of this.items) {
367
207
  const prev = existing.prevState;
368
208
  if (!prev || prev.__buoyStateOnDevice !== true) {
369
209
  hydrated.set(existing.id, existing);
370
210
  }
371
211
  }
372
- this.stateChanges = changes.slice(0, this.maxChanges).map(change => {
212
+ const merged = changes.slice(0, this.max).map(change => {
373
213
  const kept = hydrated.get(change.id);
374
214
  const incoming = change.prevState;
375
215
  return kept && incoming?.__buoyStateOnDevice === true ? {
@@ -413,7 +253,7 @@ class ZustandStateStore {
413
253
  color: snapshot.color
414
254
  }];
415
255
  }));
416
- this.notifyListeners();
256
+ this.setItems(merged);
417
257
  this.notifyStoreListeners();
418
258
  }
419
259
 
@@ -422,13 +262,7 @@ class ZustandStateStore {
422
262
  * device via the adapter's `getChangeDetail`. Remote-mirror (desktop) only.
423
263
  */
424
264
  hydrateChange(id, patch) {
425
- const index = this.stateChanges.findIndex(c => c.id === id);
426
- if (index === -1) return;
427
- this.stateChanges = [...this.stateChanges.slice(0, index), {
428
- ...this.stateChanges[index],
429
- ...patch
430
- }, ...this.stateChanges.slice(index + 1)];
431
- this.notifyListeners();
265
+ this.hydrateById(id, patch);
432
266
  }
433
267
 
434
268
  /**
@@ -481,7 +315,7 @@ class ZustandStateStore {
481
315
  // ---- Filtering ----
482
316
 
483
317
  filterStateChanges(filter) {
484
- let filtered = [...this.stateChanges];
318
+ let filtered = this.getAll();
485
319
  if (filter.searchText) {
486
320
  const search = filter.searchText.toLowerCase();
487
321
  filtered = filtered.filter(c => c.storeName.toLowerCase().includes(search) || c.partialPreview.toLowerCase().includes(search) || c.changedKeys.some(k => k.toLowerCase().includes(search)));
@@ -498,10 +332,10 @@ class ZustandStateStore {
498
332
  // ---- Stats ----
499
333
 
500
334
  getStats() {
501
- const total = this.stateChanges.length;
502
- const withChanges = this.stateChanges.filter(c => c.hasStateChange).length;
335
+ const total = this.items.length;
336
+ const withChanges = this.items.filter(c => c.hasStateChange).length;
503
337
  const storeCount = this.stores.size;
504
- const durations = this.stateChanges.filter(c => c.duration !== undefined).map(c => c.duration);
338
+ const durations = this.items.filter(c => c.duration !== undefined).map(c => c.duration);
505
339
  const avgDuration = durations.length > 0 ? durations.reduce((sum, d) => sum + d, 0) / durations.length : 0;
506
340
  return {
507
341
  totalChanges: total,
@@ -517,38 +351,18 @@ class ZustandStateStore {
517
351
 
518
352
  // ---- Enable / Disable ----
519
353
 
520
- setEnabled(enabled) {
521
- this.isEnabled = enabled;
522
- }
523
- getEnabled() {
524
- return this.isEnabled;
525
- }
526
354
  setMaxChanges(max) {
527
- this.maxChanges = max;
528
- if (this.stateChanges.length > max) {
529
- this.stateChanges = this.stateChanges.slice(0, max);
530
- this.notifyListeners();
531
- }
355
+ this.setMax(max);
532
356
  }
533
357
 
534
358
  // ---- Subscriptions ----
535
359
 
536
- subscribe(listener) {
537
- this.listeners.add(listener);
538
- return () => {
539
- this.listeners.delete(listener);
540
- };
541
- }
542
360
  subscribeToStores(listener) {
543
361
  this.storeListeners.add(listener);
544
362
  return () => {
545
363
  this.storeListeners.delete(listener);
546
364
  };
547
365
  }
548
- notifyListeners() {
549
- const changes = this.getStateChanges();
550
- this.listeners.forEach(listener => listener(changes));
551
- }
552
366
  notifyStoreListeners() {
553
367
  const stores = this.getStores();
554
368
  this.storeListeners.forEach(listener => listener(stores));
@@ -2,7 +2,8 @@
2
2
  * ZustandDetailViewToggle
3
3
  *
4
4
  * Three-card toggle for switching between Change, State, and Diff views.
5
- * Mirrors ReduxDetailViewToggle.tsx
5
+ * The cards themselves are the shared `DetailViewToggle`; this file owns
6
+ * the zustand view list and testID prefix.
6
7
  */
7
8
  import React from "react";
8
9
  export type ZustandDetailViewMode = "change" | "state" | "diff";
@@ -1 +1 @@
1
- {"version":3,"file":"ZustandDetailViewToggle.d.ts","sourceRoot":"","sources":["../../../../src/zustand/components/ZustandDetailViewToggle.tsx"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,KAAe,MAAM,OAAO,CAAC;AAIpC,MAAM,MAAM,qBAAqB,GAAG,QAAQ,GAAG,OAAO,GAAG,MAAM,CAAC;AAWhE,UAAU,4BAA4B;IACpC,UAAU,EAAE,qBAAqB,CAAC;IAClC,YAAY,EAAE,CAAC,IAAI,EAAE,qBAAqB,KAAK,IAAI,CAAC;IACpD,YAAY,CAAC,EAAE,OAAO,CAAC;CACxB;AA0BD,eAAO,MAAM,uBAAuB,0DAqElC,CAAC"}
1
+ {"version":3,"file":"ZustandDetailViewToggle.d.ts","sourceRoot":"","sources":["../../../../src/zustand/components/ZustandDetailViewToggle.tsx"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,KAAe,MAAM,OAAO,CAAC;AASpC,MAAM,MAAM,qBAAqB,GAAG,QAAQ,GAAG,OAAO,GAAG,MAAM,CAAC;AAEhE,UAAU,4BAA4B;IACpC,UAAU,EAAE,qBAAqB,CAAC;IAClC,YAAY,EAAE,CAAC,IAAI,EAAE,qBAAqB,KAAK,IAAI,CAAC;IACpD,YAAY,CAAC,EAAE,OAAO,CAAC;CACxB;AAUD,eAAO,MAAM,uBAAuB,0DAclC,CAAC"}
@@ -1,3 +1,9 @@
1
+ /**
2
+ * ZustandEventFilterView
3
+ *
4
+ * The shared `EntityFilterView` with zustand's nouns: registered stores you
5
+ * can tap to hide, active store-name patterns, and how it works.
6
+ */
1
7
  import type { ZustandStoreInfo } from "../types";
2
8
  interface ZustandEventFilterViewProps {
3
9
  ignoredPatterns: Set<string>;
@@ -1 +1 @@
1
- {"version":3,"file":"ZustandEventFilterView.d.ts","sourceRoot":"","sources":["../../../../src/zustand/components/ZustandEventFilterView.tsx"],"names":[],"mappings":"AAUA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,UAAU,CAAC;AAIjD,UAAU,2BAA2B;IACnC,eAAe,EAAE,GAAG,CAAC,MAAM,CAAC,CAAC;IAC7B,eAAe,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,IAAI,CAAC;IAC3C,YAAY,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,IAAI,CAAC;IACxC,MAAM,EAAE,gBAAgB,EAAE,CAAC;CAC5B;AAuBD,wBAAgB,sBAAsB,CAAC,EACrC,eAAe,EACf,eAAe,EACf,YAAY,EACZ,MAAM,GACP,EAAE,2BAA2B,+BAmM7B"}
1
+ {"version":3,"file":"ZustandEventFilterView.d.ts","sourceRoot":"","sources":["../../../../src/zustand/components/ZustandEventFilterView.tsx"],"names":[],"mappings":"AAAA;;;;;GAKG;AAIH,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,UAAU,CAAC;AAIjD,UAAU,2BAA2B;IACnC,eAAe,EAAE,GAAG,CAAC,MAAM,CAAC,CAAC;IAC7B,eAAe,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,IAAI,CAAC;IAC3C,YAAY,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,IAAI,CAAC;IACxC,MAAM,EAAE,gBAAgB,EAAE,CAAC;CAC5B;AAQD,wBAAgB,sBAAsB,CAAC,EACrC,eAAe,EACf,eAAe,EACf,YAAY,EACZ,MAAM,GACP,EAAE,2BAA2B,+BAwB7B"}
@@ -1 +1 @@
1
- {"version":3,"file":"ZustandModal.d.ts","sourceRoot":"","sources":["../../../../src/zustand/components/ZustandModal.tsx"],"names":[],"mappings":"AAAA;;;;;;GAMG;AA+CH,OAAO,KAAK,EAAE,iBAAiB,EAAsB,MAAM,UAAU,CAAC;AAkCtE,wBAAgB,YAAY,CAAC,EAC3B,OAAO,EACP,OAAO,EACP,MAAM,EACN,UAAU,EACV,2BAAmC,EACnC,MAAc,EACd,aAAqB,EACrB,UAAqB,EACrB,uBAAuB,EACvB,iBAAiB,EACjB,cAAc,EACd,aAAa,GACd,EAAE,iBAAiB,sCAyuBnB;AAED;;;;;GAKG;AACH,wBAAgB,eAAe,CAC7B,KAAK,GAAE,IAAI,CAAC,iBAAiB,EAAE,SAAS,GAAG,SAAS,GAAG,QAAQ,CAAM,+BAGtE"}
1
+ {"version":3,"file":"ZustandModal.d.ts","sourceRoot":"","sources":["../../../../src/zustand/components/ZustandModal.tsx"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAkDH,OAAO,KAAK,EAAE,iBAAiB,EAAsB,MAAM,UAAU,CAAC;AAsCtE,wBAAgB,YAAY,CAAC,EAC3B,OAAO,EACP,OAAO,EACP,MAAM,EACN,UAAU,EACV,2BAAmC,EACnC,MAAc,EACd,aAAqB,EACrB,UAAqB,EACrB,uBAAuB,EACvB,iBAAiB,EACjB,cAAc,EACd,aAAa,GACd,EAAE,iBAAiB,sCA8tBnB;AAED;;;;;GAKG;AACH,wBAAgB,eAAe,CAC7B,KAAK,GAAE,IAAI,CAAC,iBAAiB,EAAE,SAAS,GAAG,SAAS,GAAG,QAAQ,CAAM,+BAGtE"}
@@ -1 +1 @@
1
- {"version":3,"file":"ZustandStateChangeItem.d.ts","sourceRoot":"","sources":["../../../../src/zustand/components/ZustandStateChangeItem.tsx"],"names":[],"mappings":"AAAA;;;;GAIG;AAKH,OAAO,KAAK,EAAE,kBAAkB,EAAuB,MAAM,UAAU,CAAC;AAGxE,UAAU,2BAA2B;IACnC,MAAM,EAAE,kBAAkB,CAAC;IAC3B,OAAO,EAAE,CAAC,MAAM,EAAE,kBAAkB,KAAK,IAAI,CAAC;IAC9C;;;;OAIG;IACH,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AA2FD,eAAO,MAAM,sBAAsB,mEA0DjC,CAAC"}
1
+ {"version":3,"file":"ZustandStateChangeItem.d.ts","sourceRoot":"","sources":["../../../../src/zustand/components/ZustandStateChangeItem.tsx"],"names":[],"mappings":"AAAA;;;;GAIG;AAIH,OAAO,KAAK,EAAE,kBAAkB,EAAuB,MAAM,UAAU,CAAC;AAGxE,UAAU,2BAA2B;IACnC,MAAM,EAAE,kBAAkB,CAAC;IAC3B,OAAO,EAAE,CAAC,MAAM,EAAE,kBAAkB,KAAK,IAAI,CAAC;IAC9C;;;;OAIG;IACH,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AA2FD,eAAO,MAAM,sBAAsB,mEAyBjC,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"ZustandStateInfoView.d.ts","sourceRoot":"","sources":["../../../../src/zustand/components/ZustandStateInfoView.tsx"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,OAAO,KAAiD,MAAM,OAAO,CAAC;AAiBtE,OAAO,KAAK,EAAE,kBAAkB,EAAuB,MAAM,UAAU,CAAC;AAKxE,UAAU,yBAAyB;IACjC,MAAM,EAAE,kBAAkB,CAAC;CAC5B;AAwGD,eAAO,MAAM,oBAAoB,uDAuQ/B,CAAC"}
1
+ {"version":3,"file":"ZustandStateInfoView.d.ts","sourceRoot":"","sources":["../../../../src/zustand/components/ZustandStateInfoView.tsx"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,OAAO,KAAiD,MAAM,OAAO,CAAC;AAkBtE,OAAO,KAAK,EAAE,kBAAkB,EAAuB,MAAM,UAAU,CAAC;AAKxE,UAAU,yBAAyB;IACjC,MAAM,EAAE,kBAAkB,CAAC;CAC5B;AAwED,eAAO,MAAM,oBAAoB,uDAuQ/B,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"ZustandStoreBrowser.d.ts","sourceRoot":"","sources":["../../../../src/zustand/components/ZustandStoreBrowser.tsx"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAWH,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,UAAU,CAAC;AAIjD,UAAU,wBAAwB;IAChC,MAAM,EAAE,gBAAgB,EAAE,CAAC;IAC3B,WAAW,EAAE,MAAM,CAAC;IACpB;;;;;OAKG;IACH,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,8DAA8D;IAC9D,WAAW,EAAE,CAAC,SAAS,EAAE,MAAM,KAAK,IAAI,CAAC;CAC1C;AA4DD,wBAAgB,mBAAmB,CAAC,EAClC,MAAM,EACN,WAAW,EACX,SAAiB,EACjB,WAAW,GACZ,EAAE,wBAAwB,+BA6F1B"}
1
+ {"version":3,"file":"ZustandStoreBrowser.d.ts","sourceRoot":"","sources":["../../../../src/zustand/components/ZustandStoreBrowser.tsx"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAUH,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,UAAU,CAAC;AAIjD,UAAU,wBAAwB;IAChC,MAAM,EAAE,gBAAgB,EAAE,CAAC;IAC3B,WAAW,EAAE,MAAM,CAAC;IACpB;;;;;OAKG;IACH,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,8DAA8D;IAC9D,WAAW,EAAE,CAAC,SAAS,EAAE,MAAM,KAAK,IAAI,CAAC;CAC1C;AA4DD,wBAAgB,mBAAmB,CAAC,EAClC,MAAM,EACN,WAAW,EACX,SAAiB,EACjB,WAAW,GACZ,EAAE,wBAAwB,+BAgG1B"}
@@ -1,7 +1,8 @@
1
1
  /**
2
2
  * Hook for consuming Zustand state changes from the store
3
3
  *
4
- * Mirrors useReduxActions.ts from @buoy-gg/redux
4
+ * The subscribe / filter / pause / clear plumbing is shared `useChangeLog`;
5
+ * this file owns the zustand-specific filter, stats and store registry.
5
6
  */
6
7
  import type { ZustandStateChange, ZustandStoreInfo, ZustandFilter } from "../types";
7
8
  export interface UseZustandStateChangesResult {
@@ -1 +1 @@
1
- {"version":3,"file":"useZustandStateChanges.d.ts","sourceRoot":"","sources":["../../../../src/zustand/hooks/useZustandStateChanges.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAGH,OAAO,KAAK,EACV,kBAAkB,EAClB,gBAAgB,EAChB,aAAa,EACd,MAAM,UAAU,CAAC;AAGlB,MAAM,WAAW,4BAA4B;IAC3C,iCAAiC;IACjC,YAAY,EAAE,kBAAkB,EAAE,CAAC;IACnC,qDAAqD;IACrD,eAAe,EAAE,kBAAkB,EAAE,CAAC;IACtC,8BAA8B;IAC9B,MAAM,EAAE,aAAa,CAAC;IACtB,6BAA6B;IAC7B,SAAS,EAAE,KAAK,CAAC,QAAQ,CAAC,KAAK,CAAC,cAAc,CAAC,aAAa,CAAC,CAAC,CAAC;IAC/D,wCAAwC;IACxC,KAAK,EAAE;QACL,YAAY,EAAE,MAAM,CAAC;QACrB,sBAAsB,EAAE,MAAM,CAAC;QAC/B,yBAAyB,EAAE,MAAM,CAAC;QAClC,UAAU,EAAE,MAAM,CAAC;QACnB,eAAe,EAAE,MAAM,CAAC;KACzB,CAAC;IACF,4BAA4B;IAC5B,MAAM,EAAE,gBAAgB,EAAE,CAAC;IAC3B,uCAAuC;IACvC,YAAY,EAAE,MAAM,IAAI,CAAC;IACzB,iCAAiC;IACjC,SAAS,EAAE,OAAO,CAAC;IACnB,4BAA4B;IAC5B,aAAa,EAAE,MAAM,IAAI,CAAC;IAC1B,6BAA6B;IAC7B,UAAU,EAAE,MAAM,EAAE,CAAC;IACrB,6BAA6B;IAC7B,aAAa,EAAE,CAAC,EAAE,EAAE,MAAM,KAAK,kBAAkB,GAAG,SAAS,CAAC;CAC/D;AAED,wBAAgB,sBAAsB,IAAI,4BAA4B,CAqGrE"}
1
+ {"version":3,"file":"useZustandStateChanges.d.ts","sourceRoot":"","sources":["../../../../src/zustand/hooks/useZustandStateChanges.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAIH,OAAO,KAAK,EACV,kBAAkB,EAClB,gBAAgB,EAChB,aAAa,EACd,MAAM,UAAU,CAAC;AAGlB,MAAM,WAAW,4BAA4B;IAC3C,iCAAiC;IACjC,YAAY,EAAE,kBAAkB,EAAE,CAAC;IACnC,qDAAqD;IACrD,eAAe,EAAE,kBAAkB,EAAE,CAAC;IACtC,8BAA8B;IAC9B,MAAM,EAAE,aAAa,CAAC;IACtB,6BAA6B;IAC7B,SAAS,EAAE,KAAK,CAAC,QAAQ,CAAC,KAAK,CAAC,cAAc,CAAC,aAAa,CAAC,CAAC,CAAC;IAC/D,wCAAwC;IACxC,KAAK,EAAE;QACL,YAAY,EAAE,MAAM,CAAC;QACrB,sBAAsB,EAAE,MAAM,CAAC;QAC/B,yBAAyB,EAAE,MAAM,CAAC;QAClC,UAAU,EAAE,MAAM,CAAC;QACnB,eAAe,EAAE,MAAM,CAAC;KACzB,CAAC;IACF,4BAA4B;IAC5B,MAAM,EAAE,gBAAgB,EAAE,CAAC;IAC3B,uCAAuC;IACvC,YAAY,EAAE,MAAM,IAAI,CAAC;IACzB,iCAAiC;IACjC,SAAS,EAAE,OAAO,CAAC;IACnB,4BAA4B;IAC5B,aAAa,EAAE,MAAM,IAAI,CAAC;IAC1B,6BAA6B;IAC7B,UAAU,EAAE,MAAM,EAAE,CAAC;IACrB,6BAA6B;IAC7B,aAAa,EAAE,CAAC,EAAE,EAAE,MAAM,KAAK,kBAAkB,GAAG,SAAS,CAAC;CAC/D;AAiCD,wBAAgB,sBAAsB,IAAI,4BAA4B,CA0CrE"}