@buoy-gg/zustand 7.0.40 → 7.0.42
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/README.md +11 -72
- package/lib/commonjs/index.js +1 -105
- package/lib/commonjs/preset.js +1 -102
- package/lib/commonjs/zustand/components/ZustandActionButton.js +1 -118
- package/lib/commonjs/zustand/components/ZustandDetailViewToggle.js +1 -48
- package/lib/commonjs/zustand/components/ZustandEventFilterView.js +1 -43
- package/lib/commonjs/zustand/components/ZustandIcon.js +1 -18
- package/lib/commonjs/zustand/components/ZustandModal.js +1 -772
- package/lib/commonjs/zustand/components/ZustandStateChangeItem.js +1 -117
- package/lib/commonjs/zustand/components/ZustandStateDetailContent.js +1 -372
- package/lib/commonjs/zustand/components/ZustandStateInfoView.js +1 -488
- package/lib/commonjs/zustand/components/ZustandStoreBrowser.js +1 -204
- package/lib/commonjs/zustand/components/ZustandStoreDetailContent.js +1 -471
- package/lib/commonjs/zustand/hooks/useZustandStateChanges.js +1 -74
- package/lib/commonjs/zustand/sync/zustandSyncAdapter.js +1 -382
- package/lib/commonjs/zustand/types/index.js +1 -1
- package/lib/commonjs/zustand/utils/buoyZustandMiddleware.js +1 -284
- package/lib/commonjs/zustand/utils/editableState.js +1 -146
- package/lib/commonjs/zustand/utils/snapshotProvider.js +1 -209
- package/lib/commonjs/zustand/utils/testIDs.js +1 -82
- package/lib/commonjs/zustand/utils/zustandStateStore.js +1 -379
- package/lib/module/index.js +1 -90
- package/lib/module/preset.js +1 -98
- package/lib/module/zustand/components/ZustandActionButton.js +1 -114
- package/lib/module/zustand/components/ZustandDetailViewToggle.js +1 -43
- package/lib/module/zustand/components/ZustandEventFilterView.js +1 -39
- package/lib/module/zustand/components/ZustandIcon.js +1 -11
- package/lib/module/zustand/components/ZustandModal.js +1 -767
- package/lib/module/zustand/components/ZustandStateChangeItem.js +1 -113
- package/lib/module/zustand/components/ZustandStateDetailContent.js +1 -368
- package/lib/module/zustand/components/ZustandStateInfoView.js +1 -483
- package/lib/module/zustand/components/ZustandStoreBrowser.js +1 -200
- package/lib/module/zustand/components/ZustandStoreDetailContent.js +1 -469
- package/lib/module/zustand/hooks/useZustandStateChanges.js +1 -70
- package/lib/module/zustand/sync/zustandSyncAdapter.js +1 -380
- package/lib/module/zustand/types/index.js +1 -1
- package/lib/module/zustand/utils/buoyZustandMiddleware.js +1 -278
- package/lib/module/zustand/utils/editableState.js +1 -138
- package/lib/module/zustand/utils/snapshotProvider.js +1 -209
- package/lib/module/zustand/utils/testIDs.js +1 -74
- package/lib/module/zustand/utils/zustandStateStore.js +1 -375
- package/lib/web/index.mjs +2 -0
- package/package.json +35 -12
- package/lib/commonjs/zustand/components/ZustandStoreEditorScreen.js +0 -393
- package/lib/module/zustand/components/ZustandStoreEditorScreen.js +0 -389
- package/lib/typescript/index.d.ts.map +0 -1
- package/lib/typescript/preset.d.ts.map +0 -1
- package/lib/typescript/zustand/components/ZustandActionButton.d.ts.map +0 -1
- package/lib/typescript/zustand/components/ZustandDetailViewToggle.d.ts.map +0 -1
- package/lib/typescript/zustand/components/ZustandEventFilterView.d.ts.map +0 -1
- package/lib/typescript/zustand/components/ZustandIcon.d.ts.map +0 -1
- package/lib/typescript/zustand/components/ZustandModal.d.ts.map +0 -1
- package/lib/typescript/zustand/components/ZustandStateChangeItem.d.ts.map +0 -1
- package/lib/typescript/zustand/components/ZustandStateDetailContent.d.ts.map +0 -1
- package/lib/typescript/zustand/components/ZustandStateInfoView.d.ts.map +0 -1
- package/lib/typescript/zustand/components/ZustandStoreBrowser.d.ts.map +0 -1
- package/lib/typescript/zustand/components/ZustandStoreDetailContent.d.ts.map +0 -1
- package/lib/typescript/zustand/components/ZustandStoreEditorScreen.d.ts +0 -42
- package/lib/typescript/zustand/components/ZustandStoreEditorScreen.d.ts.map +0 -1
- package/lib/typescript/zustand/hooks/useZustandStateChanges.d.ts.map +0 -1
- package/lib/typescript/zustand/sync/zustandSyncAdapter.d.ts.map +0 -1
- package/lib/typescript/zustand/types/index.d.ts.map +0 -1
- package/lib/typescript/zustand/utils/buoyZustandMiddleware.d.ts.map +0 -1
- package/lib/typescript/zustand/utils/editableState.d.ts.map +0 -1
- package/lib/typescript/zustand/utils/snapshotProvider.d.ts.map +0 -1
- package/lib/typescript/zustand/utils/testIDs.d.ts.map +0 -1
- package/lib/typescript/zustand/utils/zustandStateStore.d.ts.map +0 -1
|
@@ -1,74 +1 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
|
|
3
|
-
/**
|
|
4
|
-
* Zustand tool test handles.
|
|
5
|
-
*
|
|
6
|
-
* Every tappable and every value the e2e suite reads back is addressed
|
|
7
|
-
* `buoy-zustand-<thing>`. Two rules in here need explaining.
|
|
8
|
-
*
|
|
9
|
-
* **A change row's handle carries an ORDINAL, and it counts per STORE.** The
|
|
10
|
-
* Events tool can address a row by what it is about, because an event is a
|
|
11
|
-
* thing that happened to a named subject — one key, one URL, one atom. A
|
|
12
|
-
* zustand state change is not: a store that a screen writes to fifty times
|
|
13
|
-
* produces fifty separate, equally real rows. Addressing them by store name
|
|
14
|
-
* alone would give fifty views one handle, and Detox fails a *matcher* that
|
|
15
|
-
* hits more than one element — so a suite would break on `toExist()`, before
|
|
16
|
-
* any assertion, with an error that says nothing about duplicate changes.
|
|
17
|
-
*
|
|
18
|
-
* So the handle is `buoy-zustand-row-<slug(storeName)>-<n>`, where n counts
|
|
19
|
-
* back from the newest row of that store (1 = newest). Deliberately relative:
|
|
20
|
-
* a state change has no identity a host could know in advance — `id` is a
|
|
21
|
-
* timestamp plus a per-process counter whose value depends on how many
|
|
22
|
-
* changes the app happened to make before the test looked. What a test CAN
|
|
23
|
-
* know is "the set I just fired is the newest change to that store". Read and
|
|
24
|
-
* tap in one beat: a row's ordinal moves the instant another change lands.
|
|
25
|
-
*
|
|
26
|
-
* **A store row's handle does NOT.** A store is registered once under a name
|
|
27
|
-
* that is unique by construction (`zustandStateStore.registerStore` returns
|
|
28
|
-
* early on a name it already holds), so `buoy-zustand-store-<slug(name)>` is
|
|
29
|
-
* as stable as the store itself — and unlike a change, it is a thing the host
|
|
30
|
-
* knows the name of before the app has booted.
|
|
31
|
-
*
|
|
32
|
-
* The suite mirrors these rules in CommonJS (`example-dev-build/utils/
|
|
33
|
-
* zustandBench.js`) and asserts the two agree — Detox runs in Node on the host
|
|
34
|
-
* and cannot import TypeScript.
|
|
35
|
-
*/
|
|
36
|
-
|
|
37
|
-
/** Prefix every handle in this tool shares. */
|
|
38
|
-
export const ZUSTAND_TEST_ID = "buoy-zustand";
|
|
39
|
-
|
|
40
|
-
/** `zbenchWatch` → `zbenchwatch`. Shared with every Buoy tool. */
|
|
41
|
-
export function slugForTestID(value) {
|
|
42
|
-
return String(value ?? "").toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-+|-+$/g, "") || "unknown";
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
/**
|
|
46
|
-
* Handle for one change row: `buoy-zustand-row-zbenchwatch-1`.
|
|
47
|
-
*
|
|
48
|
-
* `ordinal` is 1-based and counts back from the newest row of this store.
|
|
49
|
-
*/
|
|
50
|
-
export function changeRowTestID(storeName, ordinal) {
|
|
51
|
-
return `${ZUSTAND_TEST_ID}-row-${slugForTestID(storeName)}-${ordinal}`;
|
|
52
|
-
}
|
|
53
|
-
|
|
54
|
-
/** Handle for one store row in the browser: `buoy-zustand-store-zbenchwatch`. */
|
|
55
|
-
export function storeRowTestID(storeName) {
|
|
56
|
-
return `${ZUSTAND_TEST_ID}-store-${slugForTestID(storeName)}`;
|
|
57
|
-
}
|
|
58
|
-
|
|
59
|
-
/**
|
|
60
|
-
* Row handle per change id for one rendered list, newest-first.
|
|
61
|
-
*
|
|
62
|
-
* Built once for the whole list rather than per row, because an ordinal is a
|
|
63
|
-
* fact about the list and a row cannot compute its own.
|
|
64
|
-
*/
|
|
65
|
-
export function buildChangeRowTestIDs(changes) {
|
|
66
|
-
const seen = new Map();
|
|
67
|
-
const handles = new Map();
|
|
68
|
-
for (const change of changes) {
|
|
69
|
-
const ordinal = (seen.get(change.storeName) ?? 0) + 1;
|
|
70
|
-
seen.set(change.storeName, ordinal);
|
|
71
|
-
handles.set(change.id, changeRowTestID(change.storeName, ordinal));
|
|
72
|
-
}
|
|
73
|
-
return handles;
|
|
74
|
-
}
|
|
1
|
+
"use strict";export const ZUSTAND_TEST_ID="buoy-zustand";export function slugForTestID(e){return String(e??"").toLowerCase().replace(/[^a-z0-9]+/g,"-").replace(/^-+|-+$/g,"")||"unknown"}export function changeRowTestID(e,t){return`${ZUSTAND_TEST_ID}-row-${slugForTestID(e)}-${t}`}export function storeRowTestID(e){return`${ZUSTAND_TEST_ID}-store-${slugForTestID(e)}`}export function buildChangeRowTestIDs(e){const t=new Map;const n=new Map;for(const o of e){const r=(t.get(o.storeName)??0)+1;t.set(o.storeName,r);n.set(o.id,changeRowTestID(o.storeName,r))}return n}
|
|
@@ -1,375 +1 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
|
|
3
|
-
/**
|
|
4
|
-
* Zustand state store - captures and stores Zustand state changes
|
|
5
|
-
*
|
|
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.
|
|
10
|
-
*/
|
|
11
|
-
|
|
12
|
-
import { ChangeLog, entityColor, formatValuePreview, shallowDiffSummary } from "@buoy-gg/shared-ui";
|
|
13
|
-
// ============================================
|
|
14
|
-
// Store Color Palette
|
|
15
|
-
// ============================================
|
|
16
|
-
|
|
17
|
-
const STORE_COLORS = {
|
|
18
|
-
counter: "#10B981",
|
|
19
|
-
// emerald
|
|
20
|
-
auth: "#8B5CF6",
|
|
21
|
-
// purple
|
|
22
|
-
user: "#3B82F6",
|
|
23
|
-
// blue
|
|
24
|
-
cart: "#EC4899",
|
|
25
|
-
// pink
|
|
26
|
-
app: "#6366F1",
|
|
27
|
-
// indigo
|
|
28
|
-
ui: "#F59E0B",
|
|
29
|
-
// amber
|
|
30
|
-
settings: "#14B8A6",
|
|
31
|
-
// teal
|
|
32
|
-
theme: "#06B6D4",
|
|
33
|
-
// cyan
|
|
34
|
-
navigation: "#F97316",
|
|
35
|
-
// orange
|
|
36
|
-
form: "#EF4444" // red
|
|
37
|
-
};
|
|
38
|
-
|
|
39
|
-
/**
|
|
40
|
-
* Get consistent color for a store based on its name
|
|
41
|
-
*/
|
|
42
|
-
function getStoreColor(storeName) {
|
|
43
|
-
return entityColor(storeName, STORE_COLORS);
|
|
44
|
-
}
|
|
45
|
-
|
|
46
|
-
/**
|
|
47
|
-
* Format payload preview for display
|
|
48
|
-
*/
|
|
49
|
-
function formatPartialPreview(partial, maxLength = 40) {
|
|
50
|
-
return formatValuePreview(partial, {
|
|
51
|
-
maxLength,
|
|
52
|
-
undefinedLabel: "",
|
|
53
|
-
functionLabel: "(updater fn)"
|
|
54
|
-
});
|
|
55
|
-
}
|
|
56
|
-
|
|
57
|
-
// ============================================
|
|
58
|
-
// Zustand State Store
|
|
59
|
-
// ============================================
|
|
60
|
-
|
|
61
|
-
class ZustandStateStore extends ChangeLog {
|
|
62
|
-
stores = new Map();
|
|
63
|
-
storeListeners = new Set();
|
|
64
|
-
remoteSetStateHandler = null;
|
|
65
|
-
|
|
66
|
-
// ---- State Change Tracking ----
|
|
67
|
-
|
|
68
|
-
addStateChange(params) {
|
|
69
|
-
if (!this.canRecord()) return;
|
|
70
|
-
const {
|
|
71
|
-
storeName,
|
|
72
|
-
partial,
|
|
73
|
-
replace,
|
|
74
|
-
prevState,
|
|
75
|
-
nextState,
|
|
76
|
-
duration,
|
|
77
|
-
category,
|
|
78
|
-
isPersisted = false
|
|
79
|
-
} = params;
|
|
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.
|
|
85
|
-
const {
|
|
86
|
-
summary,
|
|
87
|
-
changedKeys,
|
|
88
|
-
changedCount
|
|
89
|
-
} = shallowDiffSummary(prevState, nextState);
|
|
90
|
-
const partialPreview = formatPartialPreview(partial);
|
|
91
|
-
const isSlowUpdate = (duration ?? 0) > 16;
|
|
92
|
-
const resolvedCategory = category ?? (replace ? "replace" : "setState");
|
|
93
|
-
const stateChange = {
|
|
94
|
-
id: this.nextId(),
|
|
95
|
-
storeName,
|
|
96
|
-
timestamp: Date.now(),
|
|
97
|
-
prevState,
|
|
98
|
-
nextState,
|
|
99
|
-
partial,
|
|
100
|
-
duration,
|
|
101
|
-
hasStateChange,
|
|
102
|
-
replace,
|
|
103
|
-
category: resolvedCategory,
|
|
104
|
-
changedKeys,
|
|
105
|
-
changedKeysCount: changedCount,
|
|
106
|
-
diffSummary: summary,
|
|
107
|
-
partialPreview,
|
|
108
|
-
isSlowUpdate,
|
|
109
|
-
isPersisted
|
|
110
|
-
};
|
|
111
|
-
this.push(stateChange);
|
|
112
|
-
|
|
113
|
-
// Update store change count
|
|
114
|
-
const storeInfo = this.stores.get(storeName);
|
|
115
|
-
if (storeInfo) {
|
|
116
|
-
storeInfo.stateChangeCount++;
|
|
117
|
-
}
|
|
118
|
-
this.notifyListeners();
|
|
119
|
-
}
|
|
120
|
-
getStateChanges() {
|
|
121
|
-
return this.getAll();
|
|
122
|
-
}
|
|
123
|
-
getStateChangeById(id) {
|
|
124
|
-
return this.getById(id);
|
|
125
|
-
}
|
|
126
|
-
clearStateChanges() {
|
|
127
|
-
// Reset counts
|
|
128
|
-
for (const store of this.stores.values()) {
|
|
129
|
-
store.stateChangeCount = 0;
|
|
130
|
-
}
|
|
131
|
-
this.clear();
|
|
132
|
-
// The browser keeps its store list in React state and only re-reads it
|
|
133
|
-
// on a store notification — `clear()` above only tells the change-log
|
|
134
|
-
// listeners, so without this the cards kept their old counts after Clear.
|
|
135
|
-
this.notifyStoreListeners();
|
|
136
|
-
}
|
|
137
|
-
|
|
138
|
-
// ---- Remote Mirror Mode ----
|
|
139
|
-
|
|
140
|
-
/**
|
|
141
|
-
* Replace the change log without touching the store registry. Used when a
|
|
142
|
-
* host keeps real registered stores (JUMP / RESET stay wired) but needs to
|
|
143
|
-
* reseed the event list — the docs live tour, or any mirror that already
|
|
144
|
-
* called `registerStore`. Does not fire `onClear`. Respects the enabled
|
|
145
|
-
* flag so the UI's pause button freezes the reseed.
|
|
146
|
-
*/
|
|
147
|
-
replaceStateChanges(changes) {
|
|
148
|
-
if (!this.getEnabled()) return;
|
|
149
|
-
for (const store of this.stores.values()) {
|
|
150
|
-
store.stateChangeCount = 0;
|
|
151
|
-
}
|
|
152
|
-
const kept = changes.slice(0, this.max);
|
|
153
|
-
for (const change of kept) {
|
|
154
|
-
const store = this.stores.get(change.storeName);
|
|
155
|
-
if (store) store.stateChangeCount++;
|
|
156
|
-
}
|
|
157
|
-
this.setItems(kept);
|
|
158
|
-
this.notifyStoreListeners();
|
|
159
|
-
}
|
|
160
|
-
|
|
161
|
-
/**
|
|
162
|
-
* Serializable snapshot of the tracked stores (registry metadata plus each
|
|
163
|
-
* store's current state). Used by the sync adapter on the device side —
|
|
164
|
-
* the live `api` handles can't go over the wire.
|
|
165
|
-
*/
|
|
166
|
-
getStoreSnapshots() {
|
|
167
|
-
return Array.from(this.stores.values()).map(store => {
|
|
168
|
-
let currentState;
|
|
169
|
-
try {
|
|
170
|
-
currentState = store.api.getState();
|
|
171
|
-
} catch {
|
|
172
|
-
currentState = undefined;
|
|
173
|
-
}
|
|
174
|
-
return {
|
|
175
|
-
name: store.name,
|
|
176
|
-
stateChangeCount: store.stateChangeCount,
|
|
177
|
-
isPersisted: store.isPersisted,
|
|
178
|
-
persistName: store.persistName,
|
|
179
|
-
// Persisted is not the same as re-readable: a store registered before
|
|
180
|
-
// its persist middleware attached has a name but no handle. The
|
|
181
|
-
// Storage tool needs the difference to decide between offering "apply"
|
|
182
|
-
// and telling the user to restart.
|
|
183
|
-
canRehydrate: typeof store.rehydrate === "function",
|
|
184
|
-
color: store.color,
|
|
185
|
-
currentState
|
|
186
|
-
};
|
|
187
|
-
});
|
|
188
|
-
}
|
|
189
|
-
|
|
190
|
-
/**
|
|
191
|
-
* Handler invoked when the UI calls setState on a mirrored store (e.g.
|
|
192
|
-
* time-travel from the dashboard). Forward it to the synced device.
|
|
193
|
-
*/
|
|
194
|
-
setRemoteSetStateHandler(handler) {
|
|
195
|
-
this.remoteSetStateHandler = handler;
|
|
196
|
-
}
|
|
197
|
-
|
|
198
|
-
/**
|
|
199
|
-
* Replace the entire mirror contents from a synced device snapshot. The
|
|
200
|
-
* rebuilt registry entries get stub `api` handles: getState() serves the
|
|
201
|
-
* snapshotted state, setState() forwards to the remote handler. Respects
|
|
202
|
-
* the enabled flag so the UI's pause button freezes the mirror.
|
|
203
|
-
*/
|
|
204
|
-
replaceFromSnapshot(changes, storeSnapshots) {
|
|
205
|
-
if (!this.getEnabled()) return;
|
|
206
|
-
|
|
207
|
-
// Preserve trees a remote mirror already hydrated — wire-form snapshots
|
|
208
|
-
// always carry markers, and a later snapshot must not blank the detail pane.
|
|
209
|
-
const hydrated = new Map();
|
|
210
|
-
for (const existing of this.items) {
|
|
211
|
-
const prev = existing.prevState;
|
|
212
|
-
if (!prev || prev.__buoyStateOnDevice !== true) {
|
|
213
|
-
hydrated.set(existing.id, existing);
|
|
214
|
-
}
|
|
215
|
-
}
|
|
216
|
-
const merged = changes.slice(0, this.max).map(change => {
|
|
217
|
-
const kept = hydrated.get(change.id);
|
|
218
|
-
const incoming = change.prevState;
|
|
219
|
-
return kept && incoming?.__buoyStateOnDevice === true ? {
|
|
220
|
-
...change,
|
|
221
|
-
prevState: kept.prevState,
|
|
222
|
-
nextState: kept.nextState,
|
|
223
|
-
partial: kept.partial
|
|
224
|
-
} : change;
|
|
225
|
-
});
|
|
226
|
-
|
|
227
|
-
// Preserve currentState a remote mirror already hydrated — oversized
|
|
228
|
-
// stores arrive as STATE_ON_DEVICE markers on every snapshot.
|
|
229
|
-
const hydratedStores = new Map();
|
|
230
|
-
for (const [name, store] of this.stores) {
|
|
231
|
-
try {
|
|
232
|
-
const state = store.api.getState();
|
|
233
|
-
const marker = state;
|
|
234
|
-
if (!marker || marker.__buoyStateOnDevice !== true) {
|
|
235
|
-
hydratedStores.set(name, state);
|
|
236
|
-
}
|
|
237
|
-
} catch {
|
|
238
|
-
// ignore
|
|
239
|
-
}
|
|
240
|
-
}
|
|
241
|
-
this.stores = new Map(storeSnapshots.map(snapshot => {
|
|
242
|
-
const incoming = snapshot.currentState;
|
|
243
|
-
const kept = hydratedStores.get(snapshot.name);
|
|
244
|
-
const currentState = kept !== undefined && incoming?.__buoyStateOnDevice === true ? kept : snapshot.currentState;
|
|
245
|
-
return [snapshot.name, {
|
|
246
|
-
name: snapshot.name,
|
|
247
|
-
api: {
|
|
248
|
-
getState: () => currentState,
|
|
249
|
-
setState: (partial, replace) => {
|
|
250
|
-
this.remoteSetStateHandler?.(snapshot.name, partial, replace);
|
|
251
|
-
},
|
|
252
|
-
subscribe: () => () => {}
|
|
253
|
-
},
|
|
254
|
-
stateChangeCount: snapshot.stateChangeCount,
|
|
255
|
-
isPersisted: snapshot.isPersisted,
|
|
256
|
-
persistName: snapshot.persistName,
|
|
257
|
-
color: snapshot.color
|
|
258
|
-
}];
|
|
259
|
-
}));
|
|
260
|
-
this.setItems(merged);
|
|
261
|
-
this.notifyStoreListeners();
|
|
262
|
-
}
|
|
263
|
-
|
|
264
|
-
/**
|
|
265
|
-
* Hydrate one mirrored change with real trees fetched on demand from the
|
|
266
|
-
* device via the adapter's `getChangeDetail`. Remote-mirror (desktop) only.
|
|
267
|
-
*/
|
|
268
|
-
hydrateChange(id, patch) {
|
|
269
|
-
this.hydrateById(id, patch);
|
|
270
|
-
}
|
|
271
|
-
|
|
272
|
-
/**
|
|
273
|
-
* Hydrate one mirrored store's currentState fetched on demand from the
|
|
274
|
-
* device via the adapter's `getStoreState`. Remote-mirror (desktop) only.
|
|
275
|
-
*/
|
|
276
|
-
hydrateStoreState(storeName, currentState) {
|
|
277
|
-
const store = this.stores.get(storeName);
|
|
278
|
-
if (!store) return;
|
|
279
|
-
this.stores.set(storeName, {
|
|
280
|
-
...store,
|
|
281
|
-
api: {
|
|
282
|
-
...store.api,
|
|
283
|
-
getState: () => currentState
|
|
284
|
-
}
|
|
285
|
-
});
|
|
286
|
-
this.notifyStoreListeners();
|
|
287
|
-
}
|
|
288
|
-
|
|
289
|
-
// ---- Store Registry ----
|
|
290
|
-
|
|
291
|
-
registerStore(name, api, options) {
|
|
292
|
-
if (this.stores.has(name)) return;
|
|
293
|
-
const storeInfo = {
|
|
294
|
-
name,
|
|
295
|
-
api,
|
|
296
|
-
stateChangeCount: 0,
|
|
297
|
-
isPersisted: options?.isPersisted ?? false,
|
|
298
|
-
persistName: options?.persistName,
|
|
299
|
-
rehydrate: options?.rehydrate,
|
|
300
|
-
color: getStoreColor(name)
|
|
301
|
-
};
|
|
302
|
-
this.stores.set(name, storeInfo);
|
|
303
|
-
this.notifyStoreListeners();
|
|
304
|
-
}
|
|
305
|
-
unregisterStore(name) {
|
|
306
|
-
this.stores.delete(name);
|
|
307
|
-
this.notifyStoreListeners();
|
|
308
|
-
}
|
|
309
|
-
getStores() {
|
|
310
|
-
return Array.from(this.stores.values());
|
|
311
|
-
}
|
|
312
|
-
getStore(name) {
|
|
313
|
-
return this.stores.get(name);
|
|
314
|
-
}
|
|
315
|
-
getStoreColor(name) {
|
|
316
|
-
return this.stores.get(name)?.color ?? getStoreColor(name);
|
|
317
|
-
}
|
|
318
|
-
|
|
319
|
-
// ---- Filtering ----
|
|
320
|
-
|
|
321
|
-
filterStateChanges(filter) {
|
|
322
|
-
let filtered = this.getAll();
|
|
323
|
-
if (filter.searchText) {
|
|
324
|
-
const search = filter.searchText.toLowerCase();
|
|
325
|
-
filtered = filtered.filter(c => c.storeName.toLowerCase().includes(search) || c.partialPreview.toLowerCase().includes(search) || c.changedKeys.some(k => k.toLowerCase().includes(search)));
|
|
326
|
-
}
|
|
327
|
-
if (filter.storeNames && filter.storeNames.length > 0) {
|
|
328
|
-
filtered = filtered.filter(c => filter.storeNames.includes(c.storeName));
|
|
329
|
-
}
|
|
330
|
-
if (filter.onlyWithChanges) {
|
|
331
|
-
filtered = filtered.filter(c => c.hasStateChange);
|
|
332
|
-
}
|
|
333
|
-
return filtered;
|
|
334
|
-
}
|
|
335
|
-
|
|
336
|
-
// ---- Stats ----
|
|
337
|
-
|
|
338
|
-
getStats() {
|
|
339
|
-
const total = this.items.length;
|
|
340
|
-
const withChanges = this.items.filter(c => c.hasStateChange).length;
|
|
341
|
-
const storeCount = this.stores.size;
|
|
342
|
-
const durations = this.items.filter(c => c.duration !== undefined).map(c => c.duration);
|
|
343
|
-
const avgDuration = durations.length > 0 ? durations.reduce((sum, d) => sum + d, 0) / durations.length : 0;
|
|
344
|
-
return {
|
|
345
|
-
totalChanges: total,
|
|
346
|
-
changesWithStateChange: withChanges,
|
|
347
|
-
changesWithoutStateChange: total - withChanges,
|
|
348
|
-
storeCount,
|
|
349
|
-
averageDuration: Math.round(avgDuration * 100) / 100
|
|
350
|
-
};
|
|
351
|
-
}
|
|
352
|
-
getUniqueStoreNames() {
|
|
353
|
-
return Array.from(this.stores.keys()).sort();
|
|
354
|
-
}
|
|
355
|
-
|
|
356
|
-
// ---- Enable / Disable ----
|
|
357
|
-
|
|
358
|
-
setMaxChanges(max) {
|
|
359
|
-
this.setMax(max);
|
|
360
|
-
}
|
|
361
|
-
|
|
362
|
-
// ---- Subscriptions ----
|
|
363
|
-
|
|
364
|
-
subscribeToStores(listener) {
|
|
365
|
-
this.storeListeners.add(listener);
|
|
366
|
-
return () => {
|
|
367
|
-
this.storeListeners.delete(listener);
|
|
368
|
-
};
|
|
369
|
-
}
|
|
370
|
-
notifyStoreListeners() {
|
|
371
|
-
const stores = this.getStores();
|
|
372
|
-
this.storeListeners.forEach(listener => listener(stores));
|
|
373
|
-
}
|
|
374
|
-
}
|
|
375
|
-
export const zustandStateStore = new ZustandStateStore();
|
|
1
|
+
"use strict";import{ChangeLog as v,entityColor as L,formatValuePreview as w,shallowDiffSummary as x}from"@buoy-gg/shared-ui";const N={counter:"#10B981",auth:"#8B5CF6",user:"#3B82F6",cart:"#EC4899",app:"#6366F1",ui:"#F59E0B",settings:"#14B8A6",theme:"#06B6D4",navigation:"#F97316",form:"#EF4444"};function d(c){return L(c,N)}function b(c,t=40){return w(c,{maxLength:t,undefinedLabel:"",functionLabel:"(updater fn)"})}class P extends v{stores=new Map;storeListeners=new Set;remoteSetStateHandler=null;addStateChange(t){if(!this.canRecord())return;const{storeName:s,partial:r,replace:a,prevState:o,nextState:e,duration:n,category:i,isPersisted:h=false}=t;const u=o!==e;const{summary:g,changedKeys:l,changedCount:f}=x(o,e);const m=b(r);const C=(n??0)>16;const y=i??(a?"replace":"setState");const p={id:this.nextId(),storeName:s,timestamp:Date.now(),prevState:o,nextState:e,partial:r,duration:n,hasStateChange:u,replace:a,category:y,changedKeys:l,changedKeysCount:f,diffSummary:g,partialPreview:m,isSlowUpdate:C,isPersisted:h};this.push(p);const S=this.stores.get(s);if(S){S.stateChangeCount++}this.notifyListeners()}getStateChanges(){return this.getAll()}getStateChangeById(t){return this.getById(t)}clearStateChanges(){for(const t of this.stores.values()){t.stateChangeCount=0}this.clear();this.notifyStoreListeners()}replaceStateChanges(t){if(!this.getEnabled())return;for(const r of this.stores.values()){r.stateChangeCount=0}const s=t.slice(0,this.max);for(const r of s){const a=this.stores.get(r.storeName);if(a)a.stateChangeCount++}this.setItems(s);this.notifyStoreListeners()}getStoreSnapshots(){return Array.from(this.stores.values()).map(t=>{let s;try{s=t.api.getState()}catch{s=void 0}return{name:t.name,stateChangeCount:t.stateChangeCount,isPersisted:t.isPersisted,persistName:t.persistName,canRehydrate:typeof t.rehydrate==="function",color:t.color,currentState:s}})}setRemoteSetStateHandler(t){this.remoteSetStateHandler=t}replaceFromSnapshot(t,s){if(!this.getEnabled())return;const r=new Map;for(const e of this.items){const n=e.prevState;if(!n||n.__buoyStateOnDevice!==true){r.set(e.id,e)}}const a=t.slice(0,this.max).map(e=>{const n=r.get(e.id);const i=e.prevState;return n&&i?.__buoyStateOnDevice===true?{...e,prevState:n.prevState,nextState:n.nextState,partial:n.partial}:e});const o=new Map;for(const[e,n]of this.stores){try{const i=n.api.getState();const h=i;if(!h||h.__buoyStateOnDevice!==true){o.set(e,i)}}catch{}}this.stores=new Map(s.map(e=>{const n=e.currentState;const i=o.get(e.name);const h=i!==void 0&&n?.__buoyStateOnDevice===true?i:e.currentState;return[e.name,{name:e.name,api:{getState:()=>h,setState:(u,g)=>{this.remoteSetStateHandler?.(e.name,u,g)},subscribe:()=>()=>{}},stateChangeCount:e.stateChangeCount,isPersisted:e.isPersisted,persistName:e.persistName,color:e.color}]}));this.setItems(a);this.notifyStoreListeners()}hydrateChange(t,s){this.hydrateById(t,s)}hydrateStoreState(t,s){const r=this.stores.get(t);if(!r)return;this.stores.set(t,{...r,api:{...r.api,getState:()=>s}});this.notifyStoreListeners()}registerStore(t,s,r){if(this.stores.has(t))return;const a={name:t,api:s,stateChangeCount:0,isPersisted:r?.isPersisted??false,persistName:r?.persistName,rehydrate:r?.rehydrate,color:d(t)};this.stores.set(t,a);this.notifyStoreListeners()}unregisterStore(t){this.stores.delete(t);this.notifyStoreListeners()}getStores(){return Array.from(this.stores.values())}getStore(t){return this.stores.get(t)}getStoreColor(t){return this.stores.get(t)?.color??d(t)}filterStateChanges(t){let s=this.getAll();if(t.searchText){const r=t.searchText.toLowerCase();s=s.filter(a=>a.storeName.toLowerCase().includes(r)||a.partialPreview.toLowerCase().includes(r)||a.changedKeys.some(o=>o.toLowerCase().includes(r)))}if(t.storeNames&&t.storeNames.length>0){s=s.filter(r=>t.storeNames.includes(r.storeName))}if(t.onlyWithChanges){s=s.filter(r=>r.hasStateChange)}return s}getStats(){const t=this.items.length;const s=this.items.filter(e=>e.hasStateChange).length;const r=this.stores.size;const a=this.items.filter(e=>e.duration!==void 0).map(e=>e.duration);const o=a.length>0?a.reduce((e,n)=>e+n,0)/a.length:0;return{totalChanges:t,changesWithStateChange:s,changesWithoutStateChange:t-s,storeCount:r,averageDuration:Math.round(o*100)/100}}getUniqueStoreNames(){return Array.from(this.stores.keys()).sort()}setMaxChanges(t){this.setMax(t)}subscribeToStores(t){this.storeListeners.add(t);return()=>{this.storeListeners.delete(t)}}notifyStoreListeners(){const t=this.getStores();this.storeListeners.forEach(s=>s(t))}}export const zustandStateStore=new P;
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
"use client";var wt=Object.defineProperty;var Ar=Object.getOwnPropertyDescriptor;var Rr=Object.getOwnPropertyNames;var Lr=Object.prototype.hasOwnProperty;var zr=(e,t)=>{for(var r in t)wt(e,r,{get:t[r],enumerable:true})},vt=(e,t,r,a)=>{if(t&&typeof t=="object"||typeof t=="function")for(let n of Rr(t))!Lr.call(e,n)&&n!==r&&wt(e,n,{get:()=>t[n],enumerable:!(a=Ar(t,n))||a.enumerable});return e},Vr=(e,t,r)=>(vt(e,t,"default"),r&&vt(r,t,"default"));typeof window<"u"&&typeof globalThis.global>"u"&&(globalThis.global=globalThis);import{classifyPreviewItem as Hr,createRestoreScope as jr,emptyRestoreResult as Or,failedRestore as Wr,registerStateSnapshotProvider as Fr,unionKeys as Mr}from"@buoy-gg/shared-ui/web";import{ChangeLog as Kr,entityColor as Ur,formatValuePreview as Zr,shallowDiffSummary as _r}from"@buoy-gg/shared-ui/web";var Gr={counter:"#10B981",auth:"#8B5CF6",user:"#3B82F6",cart:"#EC4899",app:"#6366F1",ui:"#F59E0B",settings:"#14B8A6",theme:"#06B6D4",navigation:"#F97316",form:"#EF4444"};function Tt(e){return Ur(e,Gr)}function Jr(e,t=40){return Zr(e,{maxLength:t,undefinedLabel:"",functionLabel:"(updater fn)"})}var Yr=class extends Kr{constructor(){super(...arguments);this.stores=new Map;this.storeListeners=new Set;this.remoteSetStateHandler=null}addStateChange(e){if(!this.canRecord())return;let{storeName:t,partial:r,replace:a,prevState:n,nextState:o,duration:i,category:c,isPersisted:s=false}=e,p=n!==o,{summary:m,changedKeys:y,changedCount:b}=_r(n,o),h=Jr(r),f=(i??0)>16,P=c??(a?"replace":"setState"),D={id:this.nextId(),storeName:t,timestamp:Date.now(),prevState:n,nextState:o,partial:r,duration:i,hasStateChange:p,replace:a,category:P,changedKeys:y,changedKeysCount:b,diffSummary:m,partialPreview:h,isSlowUpdate:f,isPersisted:s};this.push(D);let j=this.stores.get(t);j&&j.stateChangeCount++,this.notifyListeners()}getStateChanges(){return this.getAll()}getStateChangeById(e){return this.getById(e)}clearStateChanges(){for(let e of this.stores.values())e.stateChangeCount=0;this.clear(),this.notifyStoreListeners()}replaceStateChanges(e){if(!this.getEnabled())return;for(let r of this.stores.values())r.stateChangeCount=0;let t=e.slice(0,this.max);for(let r of t){let a=this.stores.get(r.storeName);a&&a.stateChangeCount++}this.setItems(t),this.notifyStoreListeners()}getStoreSnapshots(){return Array.from(this.stores.values()).map(e=>{let t;try{t=e.api.getState()}catch{t=void 0}return{name:e.name,stateChangeCount:e.stateChangeCount,isPersisted:e.isPersisted,persistName:e.persistName,canRehydrate:typeof e.rehydrate=="function",color:e.color,currentState:t}})}setRemoteSetStateHandler(e){this.remoteSetStateHandler=e}replaceFromSnapshot(e,t){if(!this.getEnabled())return;let r=new Map;for(let o of this.items){let i=o.prevState;(!i||i.__buoyStateOnDevice!==true)&&r.set(o.id,o)}let a=e.slice(0,this.max).map(o=>{let i=r.get(o.id),c=o.prevState;return i&&c?.__buoyStateOnDevice===true?{...o,prevState:i.prevState,nextState:i.nextState,partial:i.partial}:o}),n=new Map;for(let[o,i]of this.stores)try{let c=i.api.getState(),s=c;(!s||s.__buoyStateOnDevice!==true)&&n.set(o,c)}catch{}this.stores=new Map(t.map(o=>{let i=o.currentState,c=n.get(o.name),s=c!==void 0&&i?.__buoyStateOnDevice===true?c:o.currentState;return[o.name,{name:o.name,api:{getState:()=>s,setState:(p,m)=>{this.remoteSetStateHandler?.(o.name,p,m)},subscribe:()=>()=>{}},stateChangeCount:o.stateChangeCount,isPersisted:o.isPersisted,persistName:o.persistName,color:o.color}]})),this.setItems(a),this.notifyStoreListeners()}hydrateChange(e,t){this.hydrateById(e,t)}hydrateStoreState(e,t){let r=this.stores.get(e);r&&(this.stores.set(e,{...r,api:{...r.api,getState:()=>t}}),this.notifyStoreListeners())}registerStore(e,t,r){if(this.stores.has(e))return;let a={name:e,api:t,stateChangeCount:0,isPersisted:r?.isPersisted??false,persistName:r?.persistName,rehydrate:r?.rehydrate,color:Tt(e)};this.stores.set(e,a),this.notifyStoreListeners()}unregisterStore(e){this.stores.delete(e),this.notifyStoreListeners()}getStores(){return Array.from(this.stores.values())}getStore(e){return this.stores.get(e)}getStoreColor(e){return this.stores.get(e)?.color??Tt(e)}filterStateChanges(e){let t=this.getAll();if(e.searchText){let r=e.searchText.toLowerCase();t=t.filter(a=>a.storeName.toLowerCase().includes(r)||a.partialPreview.toLowerCase().includes(r)||a.changedKeys.some(n=>n.toLowerCase().includes(r)))}return e.storeNames&&e.storeNames.length>0&&(t=t.filter(r=>e.storeNames.includes(r.storeName))),e.onlyWithChanges&&(t=t.filter(r=>r.hasStateChange)),t}getStats(){let e=this.items.length,t=this.items.filter(o=>o.hasStateChange).length,r=this.stores.size,a=this.items.filter(o=>o.duration!==void 0).map(o=>o.duration),n=a.length>0?a.reduce((o,i)=>o+i,0)/a.length:0;return{totalChanges:e,changesWithStateChange:t,changesWithoutStateChange:e-t,storeCount:r,averageDuration:Math.round(n*100)/100}}getUniqueStoreNames(){return Array.from(this.stores.keys()).sort()}setMaxChanges(e){this.setMax(e)}subscribeToStores(e){return this.storeListeners.add(e),()=>{this.storeListeners.delete(e)}}notifyStoreListeners(){let e=this.getStores();this.storeListeners.forEach(t=>t(e))}},S=new Yr;function _(e){if(typeof e!="object"||e===null||Array.isArray(e))return false;let t=Object.getPrototypeOf(e);return t===Object.prototype||t===null}function ve(e,t,r,a,n){if(typeof e=="function"){r.push(t);return}if(typeof e!="object"||e===null||n>=8)return e;if(a.has(e))return;if(a.add(e),Array.isArray(e))return e.map((i,c)=>typeof i=="function"?(r.push(`${t}[${c}]`),null):ve(i,`${t}[${c}]`,r,a,n+1));if(!_(e))return e;let o={};for(let[i,c]of Object.entries(e)){if(typeof c=="function"){r.push(t?`${t}.${i}`:i);continue}o[i]=ve(c,t?`${t}.${i}`:i,r,a,n+1)}return o}function It(e){if(_(e)&&e.__buoyStateOnDevice===true)return{data:null,fnPaths:[],blockedReason:"Store state hasn't synced from the device yet."};if(!_(e))return{data:null,fnPaths:[],blockedReason:"Only stores whose state is a plain object can be edited \u2014 a merge write has nothing to address in "+(Array.isArray(e)?"an array":`a ${typeof e}`)+"."};let t=[],r=ve(e,"",t,new WeakSet,0),a=t.filter(n=>n.includes(".")||n.includes("["));return a.length>0?{data:null,fnPaths:t,blockedReason:`State keeps a function inside "${a[0]}" \u2014 a merge write of that key would drop it, so this store can't be edited here.`}:{data:r,fnPaths:t,blockedReason:null}}function qr(e,t){if(!_(t))throw new Error("The store's state must stay an object.");let r=Object.keys(e).filter(n=>!(n in t));if(r.length>0)throw new Error(`Can't remove top-level ${r.length===1?"key":"keys"} ${r.map(n=>`"${n}"`).join(", ")} \u2014 zustand merge writes can't delete. Edit the value instead.`);let a={};for(let n of Object.keys(t))(!(n in e)||JSON.stringify(t[n])!==JSON.stringify(e[n]))&&(a[n]=t[n]);return a}var kt=8;function Dt(e,t,r,a){if(!(!_(t)||!_(e))&&!(a>=kt||r.has(t))){r.add(t);for(let[n,o]of Object.entries(t))if(typeof o=="function")e[n]=o;else if(_(o)){if(!_(e[n])){if(!Bt(o,new WeakSet,a+1))continue;e[n]={}}Dt(e[n],o,r,a+1)}}}function Bt(e,t,r){if(r>=kt||t.has(e))return false;t.add(e);for(let a of Object.values(e))if(typeof a=="function"||_(a)&&Bt(a,t,r+1))return true;return false}function Qr(){return S.getStores().length===0?{canCapture:false,canRestore:false,detail:"No Zustand stores registered \u2014 pass `zustandStores` to FloatingDevTools or add the buoyDevTools middleware"}:{canCapture:true,canRestore:true}}async function Xr(){let e=[],t={};for(let r of S.getStores()){let a=[],n;try{n=ve(r.api.getState(),"",a,new WeakSet,0)}catch(o){e.push(`store "${r.name}": capture failed (${String(o)})`);continue}t[r.name]={state:n,fnPaths:a}}return{data:{stores:t},warnings:e}}async function ea(e,t){let r=e,a=jr(t),n=Or();if(!r?.stores)return Wr("empty zustand snapshot");for(let[i,c]of Object.entries(r.stores)){if(!a.allows(i))continue;let s=S.getStore(i);if(!s){n.skipped.push({id:i,reason:"store not registered (renamed, or created after snapshot?)"});continue}try{let p=c.state;Dt(p,s.api.getState(),new WeakSet,0),s.api.setState(p,true),s.api.getState()===p?n.applied+=1:(n.warnings.push(`store "${i}": setState did not take effect`),n.ok=false)}catch(p){n.skipped.push({id:i,reason:String(p)}),n.ok=false}}let o=a.excludedWarning("store(s)");return o&&n.warnings.push(o),n}async function ta(e,t){let r=e?.stores??{},a=t===void 0,n={};if(a)for(let s of S.getStores()){let p=[];try{n[s.name]={state:ve(s.api.getState(),"",p,new WeakSet,0),fnPaths:p}}catch{}}else Object.assign(n,t?.stores??{});let o=[],i=[],c=0;for(let s of Mr(n,r)){let p=s in r,m=s in n;if(!p){a?i.push(`store "${s}" not in snapshot \u2014 untouched`):o.push({key:s,label:s,verdict:"removed",oldValue:n[s].state});continue}if(c+=r[s].fnPaths?.length??0,a&&!S.getStore(s)){o.push({key:s,label:s,verdict:"wont-apply",reason:"store not registered (renamed, or created after snapshot?)"});continue}o.push(Hr({key:s,label:s,oldValue:n[s]?.state,newValue:r[s].state,inOld:m,inNew:true},{tooLargeReason:"store too large to render a diff \u2014 restore still applies it"}))}return c>0&&i.push(`${c} store action function${c===1?"":"s"} preserved on restore (not diffed)`),{items:o,notes:i}}Fr({id:"zustand",label:"Zustand",status:Qr,capture:Xr,restore:ea,previewItems:ta});import{useState as Q,useMemo as te,useRef as $e,useCallback as E,useEffect as $t}from"react";var Pt={};zr(Pt,{AccessibilityInfo:()=>na,ActivityIndicator:()=>Xa,Alert:()=>ro,Animated:()=>ia,AppRegistry:()=>la,AppState:()=>ca,Appearance:()=>sa,BackHandler:()=>da,Button:()=>eo,CheckBox:()=>ka,Clipboard:()=>ua,DeviceEventEmitter:()=>Wa,Dimensions:()=>ha,Easing:()=>ga,FlatList:()=>Ze,I18nManager:()=>pa,Image:()=>Da,ImageBackground:()=>Ba,InteractionManager:()=>ma,Keyboard:()=>fa,KeyboardAvoidingView:()=>$a,LayoutAnimation:()=>ya,Linking:()=>ba,LogBox:()=>Oa,Modal:()=>qa,NativeEventEmitter:()=>Sa,NativeModules:()=>oa,PanResponder:()=>Ca,Picker:()=>Pa,PixelRatio:()=>xa,Platform:()=>wa,Pressable:()=>Ya,ProgressBar:()=>Na,RefreshControl:()=>Ea,SafeAreaView:()=>Aa,ScrollView:()=>Te,SectionList:()=>Ra,Share:()=>va,StatusBar:()=>La,StyleSheet:()=>le,Switch:()=>Qa,Text:()=>x,TextInput:()=>_a,Touchable:()=>za,TouchableHighlight:()=>Ga,TouchableNativeFeedback:()=>Va,TouchableOpacity:()=>re,TouchableWithoutFeedback:()=>Ja,UIManager:()=>Ta,Vibration:()=>Ia,View:()=>d,VirtualizedList:()=>Ha,YellowBox:()=>ja,findNodeHandle:()=>to,unstable_createElement:()=>aa,useColorScheme:()=>Fa,useLocaleContext:()=>Ma,useWindowDimensions:()=>Ka});Vr(Pt,ra);import*as ra from"react-native-web";import{unstable_createElement as aa,NativeModules as oa,AccessibilityInfo as na,Animated as ia,Appearance as sa,AppRegistry as la,AppState as ca,BackHandler as da,Clipboard as ua,Dimensions as ha,Easing as ga,I18nManager as pa,Keyboard as fa,InteractionManager as ma,LayoutAnimation as ya,Linking as ba,NativeEventEmitter as Sa,PanResponder as Ca,PixelRatio as xa,Platform as wa,Share as va,StyleSheet as le,UIManager as Ta,Vibration as Ia,CheckBox as ka,FlatList as Ze,Image as Da,ImageBackground as Ba,KeyboardAvoidingView as $a,Picker as Pa,ProgressBar as Na,RefreshControl as Ea,SafeAreaView as Aa,SectionList as Ra,StatusBar as La,Touchable as za,TouchableNativeFeedback as Va,VirtualizedList as Ha,YellowBox as ja,LogBox as Oa,DeviceEventEmitter as Wa,useColorScheme as Fa,useLocaleContext as Ma,useWindowDimensions as Ka}from"react-native-web";import*as M from"react-native-web";import{createElement as Ua,forwardRef as Za}from"react";function K(e){let t=Za((a,n)=>{let{accessibilityState:o,accessibilityValue:i,...c}=a;for(let s of["busy","checked","disabled","expanded","selected"])o?.[s]!==void 0&&c[`aria-${s}`]===void 0&&(c[`aria-${s}`]=o[s]);for(let[s,p]of Object.entries({min:"valuemin",max:"valuemax",now:"valuenow",text:"valuetext"}))i?.[s]!==void 0&&c[`aria-${p}`]===void 0&&(c[`aria-${p}`]=i[s]);return Ua(e,{...c,ref:n})}),r=e.State;return r&&Object.assign(t,{State:r}),t.displayName=e.displayName??e.name??"NativeWebView",t}var d=K(M.View),x=K(M.Text),_a=K(M.TextInput),re=K(M.TouchableOpacity),Ga=K(M.TouchableHighlight),Ja=K(M.TouchableWithoutFeedback),Ya=K(M.Pressable),Te=K(M.ScrollView),qa=K(M.Modal),Qa=K(M.Switch),Xa=K(M.ActivityIndicator),eo=K(M.Button),to=M.findNodeHandle,ro={alert(e,t,r,a){if(typeof document>"u")return;let n=document.createElement("dialog");n.dataset.buoyRoot="",n.setAttribute("aria-label",e),n.style.cssText="position:fixed;inset:0;margin:auto;width:min(440px,90vw);padding:24px;border:1px solid #475569;border-radius:14px;background:#17212e;color:#f1f5f9;font:14px system-ui;box-shadow:0 20px 80px #0008;z-index:2147483647";let o=document.createElement("h2");if(o.textContent=e,o.style.cssText="font-size:18px;margin:0 0 12px",n.appendChild(o),t){let p=document.createElement("p");p.textContent=t,p.style.cssText="line-height:1.5;white-space:pre-wrap;margin:0 0 20px",n.appendChild(p)}let i=document.createElement("div");i.style.cssText="display:flex;justify-content:flex-end;flex-wrap:wrap;gap:8px";let c=r?.length?r:[{text:"OK"}],s=()=>{n.close?.(),n.remove()};for(let p of c){let m=document.createElement("button");m.type="button",m.textContent=p.text??"OK",m.style.cssText=`padding:9px 14px;border:1px solid #64748b;border-radius:7px;color:white;background:${p.style==="destructive"?"#a52b38":"#283a4d"};cursor:pointer;font:inherit`,m.onclick=()=>{s(),p.onPress?.()},i.appendChild(m)}n.addEventListener("cancel",p=>{p.preventDefault(),a?.cancelable!==false&&(s(),a?.onDismiss?.())}),n.appendChild(i),document.body.appendChild(n),n.showModal?n.showModal():n.setAttribute("open","")}};import{JsModal as ao,ModalHeader as A,TabSelector as oo,macOSColors as no,night as V,ToolEmptyState as _e,resolveListEmptyState as Nt,Search as io,Filter as so,Power as lo,Lock as co,devToolsStorageKeys as uo,ProUpgradeModal as ho,PowerToggleButton as go,ToolbarCopyButton as Ge,ToolbarClearButton as po,truncatePayload as he,TickProvider as Et,useLimit as fo,windowDragProps as mo,EVENT_LIST_PRESET as At}from"@buoy-gg/shared-ui/web";import{useIsPro as yo}from"@buoy-gg/license/web";import{useCallback as bo,useMemo as Rt}from"react";import{useChangeLog as So,useSubscribedValue as Co}from"@buoy-gg/shared-ui/web";function xo(e,t){let r=e;if(t.searchText){let a=t.searchText.toLowerCase();r=r.filter(n=>n.storeName.toLowerCase().includes(a)||n.partialPreview.toLowerCase().includes(a)||n.changedKeys.some(o=>o.toLowerCase().includes(a)))}return t.storeNames&&t.storeNames.length>0&&(r=r.filter(a=>t.storeNames.includes(a.storeName))),t.onlyWithChanges&&(r=r.filter(a=>a.hasStateChange)),r}var wo=()=>S.getStores(),vo=e=>S.subscribeToStores(e);function Lt(){let e=So(S,{filterItems:xo}),t=Co(wo,vo),r=Rt(()=>{let o=e.items.length,i=e.items.filter(c=>c.hasStateChange).length;return{totalChanges:o,changesWithStateChange:i,changesWithoutStateChange:o-i,storeCount:t.length,averageDuration:0}},[e.items,t]),a=Rt(()=>S.getUniqueStoreNames(),[t]),n=bo(o=>S.getStateChangeById(o),[]);return{stateChanges:e.items,filteredChanges:e.filteredItems,filter:e.filter,setFilter:e.setFilter,stats:r,stores:t,clearChanges:S.clearStateChanges.bind(S),isEnabled:e.isEnabled,toggleCapture:e.toggleCapture,storeNames:a,getChangeById:n}}import{memo as To}from"react";import{ChangeRow as Io,buoyColors as zt,night as ko}from"@buoy-gg/shared-ui/web";import{jsx as Do}from"react/jsx-runtime";function Bo(e,t){switch(e){case"replace":return"Replace";case"persist":return"Hydrate";case"initial":return"Initial";default:return t.charAt(0).toUpperCase()+t.slice(1)}}function $o(e,t){switch(e){case"replace":return zt.warning;case"persist":return zt.info;case"initial":return ko.color.textTertiary;default:return S.getStoreColor(t)}}function Po(e){let t=[];return e.duration!==void 0&&e.duration>=.1&&t.push(`${e.duration.toFixed(1)}ms`),e.hasStateChange?e.changedKeysCount>0?t.push(`${e.changedKeysCount} key${e.changedKeysCount>1?"s":""} changed`):t.push(e.diffSummary||"state changed"):t.push("no state change"),t.join(" \xB7 ")}function No(e){return e.category==="replace"?"REPLACE":e.category==="persist"?"HYDRATE":e.category==="initial"?"INIT":"SET"}function Eo(e){return e.changedKeys.length>0&&e.changedKeys.length<=3?e.changedKeys.join(", "):e.changedKeys.length>3?`${e.changedKeys.slice(0,2).join(", ")} +${e.changedKeys.length-2}`:e.partialPreview||"setState()"}var Vt=To(function({change:e,onPress:t,testID:r}){let a=$o(e.category,e.storeName),n=Bo(e.category,e.storeName),o=Po(e),i=Eo(e),c=No(e);return Do(Io,{statusColor:a,statusLabel:n,sublabel:o,primaryText:i,timestamp:e.timestamp,badgeText:c,changed:e.hasStateChange,slow:e.isSlowUpdate,onPress:()=>t(e),testID:r})});import{useState as Ht,useCallback as Pe,useMemo as jt}from"react";import{night as ae,EventStepperFooter as Ot,formatRelativeTime as Ne,parseValue as Ee,monoFont as Ie}from"@buoy-gg/shared-ui/web";import{DataViewer as Ao,SplitDiffViewer as Ro,TreeDiffViewer as Lo,diffThemes as zo}from"@buoy-gg/shared-ui/web/dataViewer";import{memo as Vo}from"react";import{DetailViewToggle as Ho,FileText as jo,Database as Oo,GitBranch as Wo}from"@buoy-gg/shared-ui/web";import{jsx as Fo}from"react/jsx-runtime";var Mo=[{key:"change",label:"CHANGE",description:"View change details",icon:jo},{key:"state",label:"STATE",description:"View current state",icon:Oo},{key:"diff",label:"DIFF",description:"Compare changes",icon:Wo}],Ko=["diff"],Uo=Vo(function({activeView:e,onViewChange:t,diffDisabled:r=false}){return Fo(Ho,{views:Mo,activeView:e,onViewChange:t,disabledKeys:r?Ko:void 0,testIDPrefix:"buoy-zustand"})});import{memo as Zo,useCallback as Je,useState as _o,useEffect as Go}from"react";import{buoyColors as H,night as I,Clock as Jo,AlertTriangle as Yo,Zap as Wt,Info as qo,Box as Ft,Database as Qo,parseValue as Xo,ProUpgradeModal as en,copyToClipboard as tn,InfoRow as Mt,monoFont as ge}from"@buoy-gg/shared-ui/web";import{useIsPro as rn}from"@buoy-gg/license/web";import{DataViewer as an}from"@buoy-gg/shared-ui/web/dataViewer";import{night as $,monoFont as on}from"@buoy-gg/shared-ui/web";import{jsx as Kt,jsxs as nn}from"react/jsx-runtime";var sn={copy:{color:$.color.accent,backgroundColor:$.color.accentSoft,borderColor:$.color.accentBorder,textColor:$.color.accent},reset:{color:$.color.warning,backgroundColor:$.color.warningSoft,borderColor:$.color.warning+"40",textColor:$.color.warning},clear:{color:$.color.danger,backgroundColor:$.color.dangerSoft,borderColor:$.color.danger+"40",textColor:$.color.danger},jump:{color:$.color.warning,backgroundColor:$.color.warningSoft,borderColor:$.color.warning+"40",textColor:$.color.warning}};function Ye({onPress:e,text:t,type:r,disabled:a=false,testID:n}){let o=sn[r];return nn(re,{disabled:a,onPress:e,style:[qe.button,{backgroundColor:a?$.color.textTertiary+"1A":o.backgroundColor,borderColor:a?$.color.textTertiary+"33":o.borderColor,opacity:a?.5:1}],activeOpacity:.7,testID:n,accessibilityRole:"button",accessibilityLabel:t,accessibilityState:{disabled:a},children:[Kt(d,{style:[qe.dot,{backgroundColor:a?$.color.textTertiary:o.color}]}),Kt(x,{style:[qe.text,{color:a?$.color.textTertiary:o.textColor}],children:t})]})}var qe=le.create({button:{flexDirection:"row",alignItems:"center",justifyContent:"center",borderRadius:6,borderWidth:1,paddingHorizontal:12,paddingVertical:6,height:25,minWidth:80,shadowOffset:{width:0,height:1},shadowOpacity:.2,shadowRadius:2,elevation:2},dot:{width:5,height:5,borderRadius:3,marginRight:6,shadowColor:$.color.text,shadowOffset:{width:0,height:0},shadowOpacity:.6,shadowRadius:2},text:{fontSize:10,fontWeight:"600",letterSpacing:.5,textTransform:"uppercase",fontFamily:on,height:12}});var u="buoy-zustand";function Qe(e){return String(e??"").toLowerCase().replace(/[^a-z0-9]+/g,"-").replace(/^-+|-+$/g,"")||"unknown"}function ln(e,t){return`${u}-row-${Qe(e)}-${t}`}function Ut(e){return`${u}-store-${Qe(e)}`}function cn(e){let t=new Map,r=new Map;for(let a of e){let n=(t.get(a.storeName)??0)+1;t.set(a.storeName,n),r.set(a.id,ln(a.storeName,n))}return r}import{jsx as w,jsxs as W}from"react/jsx-runtime";function dn(e){switch(e){case"replace":return{label:"REPLACE",color:H.warning,bgColor:H.warning+"26"};case"persist":return{label:"PERSIST",color:H.info,bgColor:H.info+"26"};case"initial":return{label:"INITIAL",color:I.color.textTertiary,bgColor:I.color.textTertiary+"26"};default:return{label:"SET STATE",color:H.success,bgColor:H.success+"26"}}}function un(e){return e===void 0?"N/A":e<1?"<1ms":`${e.toFixed(1)}ms`}function Ae({icon:e,title:t,badge:r,testID:a}){return W(d,{style:C.sectionHeader,testID:a,children:[W(d,{style:C.sectionHeaderLeft,children:[w(e,{size:14,color:I.color.accent}),w(x,{style:C.sectionTitle,children:t})]}),r]})}function hn(e){let t=new Date(e),r=t.getHours().toString().padStart(2,"0"),a=t.getMinutes().toString().padStart(2,"0"),n=t.getSeconds().toString().padStart(2,"0"),o=t.getMilliseconds().toString().padStart(3,"0");return`${r}:${a}:${n}.${o}`}var gn=Zo(function({change:e}){let t=rn(),[r,a]=_o(false);Go(()=>{r&&t&&a(false)},[r,t]);let n=dn(e.category),o=e.partial!==void 0&&e.partial!=="(updater fn)",i=e.changedKeys.length>0,c=S.getStoreColor(e.storeName),s=Je(async()=>{if(!t){a(true);return}await tn(e.nextState)},[e.nextState,t]),p=Je(()=>{let y=S.getStore(e.storeName);if(y?.api.getInitialState){let b=y.api.getInitialState();y.api.setState(b,true)}},[e.storeName]),m=Je(()=>{let y=S.getStore(e.storeName);y&&y.api.setState(e.nextState,true)},[e.storeName,e.nextState]);return W(Te,{style:C.container,contentContainerStyle:C.contentContainer,showsVerticalScrollIndicator:false,testID:`${u}-detail-scroll`,children:[W(d,{style:C.card,testID:`${u}-info-card`,children:[w(Ae,{icon:qo,title:"CHANGE INFO"}),W(d,{style:C.cardContent,children:[w(Mt,{label:"Store",value:e.storeName,mono:true,valueColor:c,testID:`${u}-info-store`}),w(Mt,{label:"Time",value:hn(e.timestamp),mono:true,testID:`${u}-info-time`}),W(d,{style:C.badgeRow,children:[w(d,{style:[C.categoryBadge,{backgroundColor:n.bgColor}],children:w(x,{style:[C.categoryText,{color:n.color}],testID:`${u}-info-category`,children:n.label})}),W(d,{style:[C.durationBadge,e.isSlowUpdate&&C.durationBadgeSlow],children:[w(Jo,{size:10,color:e.isSlowUpdate?H.error:I.color.textSecondary}),w(x,{style:[C.durationText,e.isSlowUpdate&&C.durationTextSlow],testID:`${u}-info-duration`,children:un(e.duration)}),e.isSlowUpdate&&w(Yo,{size:10,color:H.error})]}),e.hasStateChange?W(d,{style:C.changesBadge,children:[w(Wt,{size:10,color:H.success}),w(x,{style:C.changesText,testID:`${u}-info-changes`,children:e.diffSummary||"changed"})]}):w(d,{style:C.noChangesBadge,children:w(x,{style:C.noChangesText,testID:`${u}-info-no-changes`,children:"no change"})}),e.isPersisted&&W(d,{style:C.persistBadge,children:[w(Qo,{size:10,color:H.info}),w(x,{style:C.persistText,testID:`${u}-info-persisted`,children:"PERSISTED"})]})]})]})]}),i&&W(d,{style:C.card,testID:`${u}-keys-card`,children:[w(Ae,{icon:Wt,title:"CHANGED KEYS",badge:w(d,{style:C.countBadge,children:w(x,{style:C.countText,testID:`${u}-keys-count`,children:e.changedKeys.length})})}),w(d,{style:C.cardContent,children:w(d,{style:C.keysContainer,children:e.changedKeys.map(y=>w(d,{style:C.keyBadge,children:w(x,{style:C.keyText,testID:`${u}-key-${y}`,children:y})},y))})})]}),o&&W(d,{style:C.card,testID:`${u}-partial-card`,children:[w(Ae,{icon:Ft,title:"PARTIAL (setState argument)",badge:w(d,{style:C.typeBadge,children:w(x,{style:C.typeText,testID:`${u}-partial-type`,children:Array.isArray(e.partial)?"ARRAY":typeof e.partial=="object"?"OBJECT":(typeof e.partial).toUpperCase()})})}),w(d,{style:C.dataViewerContainer,children:w(an,{title:"",data:Xo(e.partial),showTypeFilter:true,rawMode:true,initialExpanded:true})})]}),e.partial==="(updater fn)"&&W(d,{style:C.card,testID:`${u}-updater-card`,children:[w(Ae,{icon:Ft,title:"SET STATE CALL"}),W(d,{style:C.cardContent,children:[w(x,{style:C.updaterText,children:"Called with an updater function: set((state) => ...)"}),w(x,{style:C.updaterSubtext,children:"The partial value is computed at runtime from the previous state. See the DIFF tab to view the resulting changes."})]})]}),W(d,{style:C.actionsGrid,children:[w(Ye,{type:"jump",text:"JUMP",onPress:m,testID:`${u}-jump`}),w(Ye,{type:"reset",text:"RESET STORE",onPress:p,testID:`${u}-reset`}),w(Ye,{type:"copy",text:"COPY STATE",onPress:s,testID:`${u}-copy-state`})]}),w(en,{visible:r,onClose:()=>a(false),featureName:"Copy"})]})}),C=le.create({container:{flex:1},contentContainer:{padding:8,paddingBottom:100,gap:16},card:{backgroundColor:I.color.surface,borderRadius:6,borderWidth:1,borderColor:I.color.accentBorderStrong,overflow:"hidden",shadowColor:I.color.accent,shadowOffset:{width:0,height:0},shadowOpacity:.1,shadowRadius:6},sectionHeader:{flexDirection:"row",alignItems:"center",justifyContent:"space-between",paddingHorizontal:12,paddingVertical:10,borderBottomWidth:1,borderBottomColor:I.color.accentBorder,backgroundColor:I.color.accentSoft},sectionHeaderLeft:{flexDirection:"row",alignItems:"center",gap:6},sectionTitle:{fontSize:12,fontWeight:"600",letterSpacing:.5,color:I.color.accent,fontFamily:ge},cardContent:{padding:14,gap:10},badgeRow:{flexDirection:"row",flexWrap:"wrap",gap:8,marginTop:6},categoryBadge:{paddingHorizontal:8,paddingVertical:3,borderRadius:4},categoryText:{fontSize:9,fontWeight:"700",letterSpacing:.3},durationBadge:{flexDirection:"row",alignItems:"center",gap:4,paddingHorizontal:8,paddingVertical:3,borderRadius:4,backgroundColor:I.color.surfaceElevated},durationBadgeSlow:{backgroundColor:H.error+"26"},durationText:{fontSize:9,fontWeight:"600",color:I.color.textSecondary,fontFamily:ge},durationTextSlow:{color:H.error},changesBadge:{flexDirection:"row",alignItems:"center",gap:4,paddingHorizontal:8,paddingVertical:3,borderRadius:4,backgroundColor:H.success+"26"},changesText:{fontSize:9,fontWeight:"600",color:H.success},noChangesBadge:{paddingHorizontal:8,paddingVertical:3,borderRadius:4,backgroundColor:I.color.surfaceElevated},noChangesText:{fontSize:9,fontWeight:"600",color:I.color.textTertiary},persistBadge:{flexDirection:"row",alignItems:"center",gap:4,paddingHorizontal:8,paddingVertical:3,borderRadius:4,backgroundColor:H.info+"26"},persistText:{fontSize:9,fontWeight:"700",color:H.info,letterSpacing:.3},keysContainer:{flexDirection:"row",flexWrap:"wrap",gap:6},keyBadge:{paddingHorizontal:8,paddingVertical:4,borderRadius:4,backgroundColor:I.color.accentSoft,borderWidth:1,borderColor:I.color.accentBorder},keyText:{fontSize:11,fontWeight:"600",color:I.color.accent,fontFamily:ge},countBadge:{paddingHorizontal:8,paddingVertical:3,borderRadius:4,backgroundColor:I.color.accentFill},countText:{fontSize:9,fontWeight:"700",color:I.color.accent,fontFamily:ge},typeBadge:{paddingHorizontal:6,paddingVertical:2,borderRadius:3,backgroundColor:I.color.surfaceElevated},typeText:{fontSize:8,fontWeight:"600",color:I.color.textTertiary,fontFamily:ge},dataViewerContainer:{backgroundColor:I.color.bg,minHeight:60},updaterText:{fontSize:12,color:I.color.text,fontFamily:ge},updaterSubtext:{fontSize:11,color:I.color.textTertiary,lineHeight:16,marginTop:4},actionsGrid:{flexDirection:"row",flexWrap:"wrap",gap:12,justifyContent:"flex-start"}});import{DiffModeTabs as pn,CompareBar as fn}from"@buoy-gg/shared-ui/web";import{jsx as B,jsxs as pe}from"react/jsx-runtime";function Xe(e){return S.getStoreColor(e.storeName)}function Zt(e){switch(e.category){case"replace":return"REPLACE";case"persist":return"HYDRATE";case"initial":return"INIT";default:return"SET"}}function mn(e){return e===null?"null":e===void 0?"undefined":Array.isArray(e)?"array":typeof e}function _t(e){return new Date(e).toLocaleTimeString("en-US",{hour12:false,hour:"2-digit",minute:"2-digit",second:"2-digit"})}var yn=[{key:"tree",label:"TREE VIEW"},{key:"split",label:"SPLIT VIEW"}];function Gt({change:e,changes:t,selectedIndex:r,onIndexChange:a,disableInternalFooter:n=false,initialView:o="change"}){let[i,c]=Ht(o),[s,p]=Ht("tree"),m=t.length,y=Xe(e),b=Zt(e),h=mn(Ee(e.nextState)),f=m-r,P=f-1,D=r<m-1?r+1:null,j=D!==null?t[D]:null,O=jt(()=>({index:D??0,label:P>0?`#${P}`:"Initial",timestamp:j?_t(j.timestamp):"",relativeTime:j?Ne(new Date(j.timestamp)):"state",badge:j?B(d,{style:[N.changeBadgeSmall,{backgroundColor:`${Xe(j)}20`}],children:B(x,{style:[N.changeTextSmall,{color:Xe(j)}],children:Zt(j)})}):void 0}),[D,j,P]),me=jt(()=>({index:r,label:`#${f}`,timestamp:_t(e.timestamp),relativeTime:Ne(new Date(e.timestamp)),badge:B(d,{style:[N.changeBadgeSmall,{backgroundColor:`${y}20`}],children:B(x,{style:[N.changeTextSmall,{color:y}],children:b})})}),[r,e.timestamp,y,b,f]),oe=Pe(()=>{let ne=Ee(e.nextState);return pe(d,{style:N.contentCard,testID:`${u}-state-card`,children:[pe(d,{style:N.valueHeader,children:[B(x,{style:N.valueLabel,children:"STATE AFTER CHANGE"}),pe(d,{style:N.valueHeaderBadges,children:[B(d,{style:[N.changeBadge,{backgroundColor:`${y}20`}],children:B(x,{style:[N.changeText,{color:y}],children:b})}),B(d,{style:N.typeBadge,children:B(x,{style:N.typeText,testID:`${u}-state-type`,children:h.toUpperCase()})})]})]}),B(d,{style:N.dataViewerContainer,children:B(Ao,{title:"",data:ne,showTypeFilter:true,rawMode:true,initialExpanded:true})})]})},[e.nextState,y,b,h]),ye=Pe(()=>{let ne=Ee(e.prevState),de=Ee(e.nextState);return s==="split"?B(Te,{style:{flex:1},showsVerticalScrollIndicator:true,children:B(Ro,{oldValue:ne,newValue:de,theme:zo.devToolsDefault,options:{hideLineNumbers:false,disableWordDiff:false,showDiffOnly:false,compareMethod:"words",contextLines:3},showThemeName:false})}):B(Lo,{oldValue:ne,newValue:de})},[e.prevState,e.nextState,s]),be=Pe(()=>{a(Math.min(m-1,r+1))},[r,m,a]),Se=Pe(()=>{a(Math.max(0,r-1))},[r,a]),J=e.prevState===void 0,Ce=!n&&m>1;return pe(d,{style:N.container,children:[B(Uo,{activeView:i,onViewChange:c,diffDisabled:J}),pe(d,{style:[N.contentArea,Ce&&N.contentAreaFooterPad],children:[i==="change"&&B(gn,{change:e}),i==="state"&&B(d,{style:N.stateContainer,children:oe()}),i==="diff"&&pe(d,{style:N.diffContainer,testID:`${u}-diff`,children:[B(pn,{tabs:yn,activeTab:s,onTabChange:p,testIDPrefix:`${u}-diff-tab`}),B(fn,{leftEvent:O,rightEvent:me}),B(d,{style:N.diffContent,testID:`${u}-diff-content`,children:ye()})]})]}),Ce&&B(Ot,{currentIndex:f-1,totalItems:m,onPrevious:be,onNext:Se,itemLabel:"Change",subtitle:Ne(new Date(e.timestamp)),absolute:true})]})}function Jt({change:e,changes:t,selectedIndex:r,onIndexChange:a}){let n=t.length;if(n<=1)return null;let o=n-r;return B(Ot,{currentIndex:o-1,totalItems:n,onPrevious:()=>a(Math.min(n-1,r+1)),onNext:()=>a(Math.max(0,r-1)),itemLabel:"Change",subtitle:Ne(new Date(e.timestamp))})}var N=le.create({container:{flex:1,backgroundColor:"transparent"},contentArea:{flex:1},contentAreaFooterPad:{paddingBottom:96},stateContainer:{flex:1,padding:14},contentCard:{backgroundColor:ae.color.surface,borderRadius:14,padding:14,borderWidth:1,borderColor:ae.color.border},valueHeader:{flexDirection:"row",alignItems:"center",justifyContent:"space-between",marginBottom:8},valueLabel:{fontSize:10,color:ae.color.textSecondary,fontFamily:Ie,letterSpacing:.5,fontWeight:"600"},valueHeaderBadges:{flexDirection:"row",alignItems:"center",gap:6},changeBadge:{paddingHorizontal:8,paddingVertical:2,borderRadius:4},changeText:{fontSize:9,fontWeight:"700",fontFamily:Ie,letterSpacing:.3},typeBadge:{paddingHorizontal:8,paddingVertical:2,borderRadius:4,backgroundColor:ae.color.surfaceElevated},typeText:{fontSize:9,fontWeight:"600",color:ae.color.textTertiary,fontFamily:Ie},valueBox:{backgroundColor:ae.color.bg,borderRadius:6,borderWidth:1,borderColor:ae.color.border,padding:8},valueText:{fontSize:12,color:ae.color.text,fontFamily:Ie,lineHeight:18},diffContainer:{flex:1},diffContent:{flex:1,paddingHorizontal:14},changeBadgeSmall:{paddingHorizontal:6,paddingVertical:1,borderRadius:3},changeTextSmall:{fontSize:8,fontWeight:"700",fontFamily:Ie},dataViewerContainer:{marginTop:-12,marginHorizontal:-12,marginBottom:-12}});import{useMemo as bn}from"react";import{CompactRow as Sn,night as et,ToolEmptyState as tt,resolveListEmptyState as Cn,monoFont as Yt}from"@buoy-gg/shared-ui/web";import{jsx as G,jsxs as rt}from"react/jsx-runtime";function xn(e){try{let t=e.api.getState();if(t&&typeof t=="object"&&t.__buoyStateOnDevice===true)return"on device";if(t&&typeof t=="object"){let r=Object.keys(t).filter(a=>typeof t[a]!="function");return r.length===0?"no data keys":r.length<=3?r.join(", "):`${r.slice(0,2).join(", ")} +${r.length-2}`}return""}catch{return""}}function wn(){return G(tt,{testID:`${u}-stores-loading`,otto:"loading",title:"Loading stores\u2026",message:"Waiting for the device to send its registered stores."})}function vn(){return G(tt,{testID:`${u}-stores-empty`,otto:"scanning",title:"No stores registered",message:`Use watchStores() to register your Zustand stores.
|
|
2
|
+
They will appear here with their current state.`})}function Tn({stores:e,searchQuery:t,isLoading:r=false,onOpenStore:a}){let n=bn(()=>{if(!t)return e;let o=t.toLowerCase();return e.filter(i=>i.name.toLowerCase().includes(o)||i.persistName&&i.persistName.toLowerCase().includes(o))},[e,t]);return n.length===0&&!t?r?G(wn,{}):G(vn,{}):n.length===0&&t?G(tt,{testID:`${u}-stores-no-match`,...Cn({subject:"stores",verb:"registered",search:t,total:e.length,waiting:{otto:"scanning",title:"No stores registered",message:"Use watchStores() to register your Zustand stores."}})}):rt(Te,{style:X.container,contentContainerStyle:X.scrollContent,showsVerticalScrollIndicator:true,testID:`${u}-stores-scroll`,children:[rt(d,{style:X.sectionHeader,children:[G(x,{style:X.sectionTitle,children:"STORES"}),G(d,{style:X.sectionCountBadge,children:G(x,{style:X.sectionCountText,testID:`${u}-stores-count`,children:n.length})})]}),n.map(o=>{let i=xn(o),c=S.getStoreColor(o.name),s=Ut(o.name);return rt(d,{style:X.storeRowWrapper,children:[G(Sn,{statusDotColor:c,statusLabel:o.isPersisted?"persisted":"in-memory",primaryText:o.name,secondaryText:i||void 0,showChevron:true,onPress:()=>a(o.name),testID:s,statusTestID:`${s}-backing`,primaryTestID:`${s}-name`,secondaryTestID:`${s}-keys`}),o.stateChangeCount>0&&G(d,{style:[X.absCountBadge,{backgroundColor:c+"22",borderColor:c+"55"}],pointerEvents:"none",children:G(x,{style:[X.absCountText,{color:c}],testID:`${s}-count`,children:String(o.stateChangeCount)})})]},o.name)})]})}var X=le.create({container:{flex:1},storeRowWrapper:{position:"relative"},absCountBadge:{position:"absolute",top:4,right:10,paddingHorizontal:5,paddingVertical:1,borderRadius:4,borderWidth:1,zIndex:1},absCountText:{fontSize:9,fontWeight:"700",fontFamily:Yt},scrollContent:{paddingTop:8,paddingBottom:20},sectionHeader:{flexDirection:"row",alignItems:"center",paddingHorizontal:16,paddingVertical:8,gap:8},sectionTitle:{fontSize:11,fontWeight:"700",letterSpacing:.5,color:et.color.textTertiary},sectionCountBadge:{backgroundColor:et.color.accentFill,paddingHorizontal:8,paddingVertical:2,borderRadius:4},sectionCountText:{fontSize:10,fontWeight:"700",color:et.color.accent,fontFamily:Yt}});import{useCallback as In,useEffect as kn,useMemo as at,useState as Re}from"react";import{buoyColors as ot,Database as Dn,ExpandedInfoRow as Le,FileJson as Bn,night as R,PillBadge as nt,parseValue as qt,monoFont as ze}from"@buoy-gg/shared-ui/web";import{DataViewer as $n,LiveExplorer as Pn,ValueEditModal as Nn,updateNestedDataByPath as En,deleteNestedDataByPath as An}from"@buoy-gg/shared-ui/web/dataViewer";import{Fragment as Qt,jsx as v,jsxs as U}from"react/jsx-runtime";var Rn=300,ce=`${u}-detail`;function Ln(e){let t=r=>r.toLowerCase().replace(/[^a-z0-9]+/g,"-").replace(/^-+|-+$/g,"");return e.length===0?`${ce}-explorer-root`:`${ce}-explorer-${e.map(t).filter(Boolean).join("-")}`}function zn({store:e,onViewHistory:t}){let r=Ut(e.name),[a,n]=Re(0);kn(()=>e.api.subscribe(()=>n(b=>b+1)),[e.api]);let o=e.api.getState(),i=at(()=>It(o),[o,a]),[c,s]=Re(false),p=at(()=>{if(i.data!==null)return{update:(b,h)=>{let f=e.api.getState();if(!_(f)||b.length===0)return;let P=b[0],D=b.length===1?h:En(f[P],b.slice(1),h);e.api.setState({[P]:D},false)},remove:b=>{let h=e.api.getState();if(!_(h)||b.length<=1)return;let f=b[0],P=An(h[f],b.slice(1));e.api.setState({[f]:P},false)},canRemove:b=>b.length>1}},[e.api,i.data===null]),m=In(b=>{let h=It(e.api.getState());if(h.data===null)return;let f=qr(h.data,b);Object.keys(f).length>0&&e.api.setState(f,false),s(false)},[e.api]),y=at(()=>{if(o&&typeof o=="object"){let b={};for(let[h,f]of Object.entries(o))typeof f!="function"&&(b[h]=f);return qt(b)}return qt(o)},[o,a]);return U(d,{style:T.root,children:[U(Te,{testID:`${ce}-scroll`,style:T.scroll,contentContainerStyle:T.scrollContent,keyboardShouldPersistTaps:"handled",children:[v(d,{style:T.section,children:U(d,{style:T.editorContainer,children:[U(d,{style:T.sectionHeaderRow,children:[v(x,{testID:`${ce}-editor-header`,style:T.sectionHeaderText,children:"State Editor"}),i.data!==null?U(re,{onPress:()=>s(true),testID:`${ce}-raw`,accessibilityRole:"button",accessibilityLabel:"Edit raw JSON",style:T.rawButton,hitSlop:{top:6,bottom:6,left:6,right:6},children:[v(Bn,{size:13,color:R.color.accent}),v(x,{style:T.rawButtonText,children:"Raw"})]}):null]}),v(d,{style:T.sectionBody,children:i.data!==null?U(Qt,{children:[v(Pn,{editable:true,label:"State",value:i.data,defaultExpanded:["State"],writer:p,dataVersion:a,testIDForPath:Ln,debounceMs:Rn}),v(x,{style:T.editorHint,children:"Edits write into the live store as you make them \u2014 merged, so the store's actions and untouched keys survive."})]}):v(x,{style:T.blockedText,testID:`${ce}-edit-blocked`,children:i.blockedReason})})]})}),v(d,{style:T.section,children:U(d,{style:T.infoContainer,children:[v(x,{style:T.sectionHeaderTextPlain,children:"Store Details"}),U(d,{style:T.infoBody,children:[v(Le,{label:"Type",children:v(nt,{color:e.color,testID:`${r}-type`,children:"ZUSTAND"})}),U(Le,{label:"Backing",children:[v(nt,{color:ot.info,icon:e.isPersisted?v(Dn,{size:9,color:ot.info}):void 0,testID:`${r}-persist`,children:e.isPersisted?e.persistName||"persisted":"in-memory"}),e.isPersisted?v(Vn,{store:e,rowID:r}):null]}),e.stateChangeCount>0&&U(Le,{label:"Changes",children:[v(nt,{color:ot.warning,testID:`${r}-changes`,children:String(e.stateChangeCount)}),v(re,{onPress:()=>t(e.name),style:T.inlineLinkButton,hitSlop:{top:6,bottom:6,left:6,right:6},testID:`${r}-history`,accessibilityRole:"button",accessibilityLabel:`View ${e.name} history`,children:v(x,{style:[T.inlineLinkText,{color:e.color}],children:"view history \u2192"})})]}),i.fnPaths.length>0&&v(Le,{label:"Actions",children:v(x,{style:T.actionsText,testID:`${ce}-actions`,numberOfLines:2,children:i.fnPaths.join(" \xB7 ")})})]})]})}),v(d,{style:T.section,children:U(d,{style:T.infoContainer,children:[v(x,{style:T.sectionHeaderTextPlain,children:"State Explorer"}),v(d,{style:T.viewerBody,testID:`${r}-state`,children:y&&typeof y=="object"?v($n,{title:"",data:y,showTypeFilter:true,rawMode:true,initialExpanded:false}):v(x,{style:T.blockedText,children:"Empty state"})})]})})]}),c&&i.data!==null?v(Nn,{path:[],value:i.data,onSave:b=>{try{m(b)}catch{}},onCancel:()=>s(false),saveLabel:"Apply",testIDPrefix:`${u}-value`}):null]})}function Vn({store:e,rowID:t}){let[r,a]=Re(false),[n,o]=Re(null);return e.rehydrate?U(Qt,{children:[v(re,{onPress:()=>{a(true),o(null),(async()=>{try{await e.rehydrate?.()}catch(i){o(i instanceof Error?i.message:String(i))}finally{a(false)}})()},disabled:r,style:T.inlineLinkButton,hitSlop:{top:6,bottom:6,left:6,right:6},testID:`${t}-reread`,accessibilityRole:"button",accessibilityLabel:`Re-read ${e.name} from storage`,children:v(x,{style:[T.inlineLinkText,{color:e.color}],children:r?"re-reading\u2026":"re-read saved value \u2192"})}),n?v(x,{style:[T.inlineLinkText,{color:R.color.danger}],children:n}):null]}):null}var T=le.create({root:{flex:1,minHeight:0},scroll:{flex:1},scrollContent:{paddingHorizontal:8,paddingTop:8,paddingBottom:24},section:{marginBottom:16},editorContainer:{minWidth:200,backgroundColor:R.color.surface,borderRadius:6,borderWidth:1,borderColor:R.color.accent+"4D",overflow:"hidden",shadowColor:R.color.accent,shadowOffset:{width:0,height:0},shadowOpacity:.1,shadowRadius:6},sectionHeaderRow:{flexDirection:"row",alignItems:"center",justifyContent:"space-between",backgroundColor:R.color.accent+"1A",paddingHorizontal:12,paddingVertical:8,borderBottomWidth:1,borderBottomColor:R.color.accent+"33"},sectionHeaderText:{fontWeight:"600",fontSize:12,color:R.color.accent,letterSpacing:.5,textTransform:"uppercase",fontFamily:ze},rawButton:{flexDirection:"row",alignItems:"center",gap:4},rawButtonText:{color:R.color.accent,fontSize:11,fontWeight:"700"},sectionBody:{padding:8},editorHint:{color:R.color.textTertiary,fontSize:10,paddingTop:8,paddingHorizontal:4,lineHeight:14},blockedText:{color:R.color.textSecondary,fontSize:12,padding:12,lineHeight:18},infoContainer:{minWidth:200,backgroundColor:R.color.surface,borderRadius:6,borderWidth:1,borderColor:R.color.border,overflow:"hidden"},sectionHeaderTextPlain:{backgroundColor:R.color.surfaceElevated,paddingHorizontal:12,paddingVertical:8,fontWeight:"600",fontSize:12,color:R.color.textSecondary,borderBottomWidth:1,borderBottomColor:R.color.border,letterSpacing:.5,textTransform:"uppercase",fontFamily:ze},infoBody:{padding:12,gap:10},viewerBody:{backgroundColor:R.color.bg,minHeight:60},inlineLinkButton:{marginLeft:4},inlineLinkText:{fontSize:10,fontWeight:"600",fontFamily:ze},actionsText:{flex:1,color:R.color.textSecondary,fontSize:10,fontFamily:ze,lineHeight:15}});import{useMemo as Hn}from"react";import{EntityFilterView as jn}from"@buoy-gg/shared-ui/web";import{jsx as On}from"react/jsx-runtime";var Wn=["\u2022 auth \u2192 hides authStore from stores & events","\u2022 temp \u2192 hides tempStore, tempUserStore","\u2022 cart \u2192 hides cartStore from both tabs"];function Fn({ignoredPatterns:e,onTogglePattern:t,onAddPattern:r,stores:a}){let n=Hn(()=>a.map(o=>({name:o.name,color:S.getStoreColor(o.name)})),[a]);return On(jn,{entities:n,ignoredPatterns:e,onTogglePattern:t,onAddPattern:r,entityNoun:"STORES",entitySingular:"store",entityKey:"store",testIDPrefix:u,slug:Qe,howItWorks:"Patterns hide matching stores from both the Stores tab and the Events tab. Tap a store above to quickly add it as a filter.",examples:Wn})}import{Fragment as Xt,jsx as g,jsxs as F}from"react/jsx-runtime";function Mn({isEnabled:e,searchText:t,totalChanges:r}){let a=Nt({subject:"changes",search:t,total:r,capturing:e,waiting:{otto:"waiting",title:"No state changes",message:"State changes will appear here as stores update."},paused:{title:"No state changes",message:"Enable capture to start recording state changes"}});return g(_e,{...a,testID:`${u}-empty`})}function Ve({visible:e,onClose:t,onBack:r,onMinimize:a,enableSharedModalDimensions:n=false,inline:o=false,storesLoading:i=false,initialTab:c="stores",initialSelectedChangeId:s,initialDetailView:p,onChangeSelect:m,onStoreExpand:y}){let b=yo(),h=fo("zustand.changes"),[f,P]=Q(false),[D,j]=Q(c),[O,me]=Q(null),[oe,ye]=Q(null),[be,Se]=Q(false),[J,Ce]=Q(new Set),{stateChanges:ne,filteredChanges:de,filter:mi,setFilter:xe,stats:ir,stores:we,clearChanges:sr,isEnabled:ke,toggleCapture:lr}=Lt(),Y=te(()=>J.size===0?de:de.filter(l=>!Array.from(J).some(k=>l.storeName.toLowerCase().includes(k.toLowerCase()))),[de,J]),ue=te(()=>J.size===0?we:we.filter(l=>!Array.from(J).some(k=>l.name.toLowerCase().includes(k.toLowerCase()))),[we,J]),cr=te(()=>O?ne.filter(l=>l.storeName===O).length:0,[ne,O]),De=te(()=>O?Y.filter(l=>l.storeName===O):Y,[Y,O]),Fe=te(()=>De.slice(0,h),[De,h]),Me=te(()=>Math.max(0,De.length-h),[De.length,h]),dr=Me>0,z=Fe,[Ke,ie]=Q(null),se=te(()=>{if(Ke===null)return null;let l=z.findIndex(k=>k.id===Ke);return l>=0?l:null},[Ke,z]),Z=se!==null?z[se]:null,lt=$e(null);$t(()=>{if(!m)return;let l=Z?.id??null;l===null||l===lt.current||(lt.current=l,m(Z))},[Z,m]);let ct=$e(null);$t(()=>{!s||ct.current===s||!z.some(l=>l.id===s)||(ct.current=s,ie(s))},[s,z]);let[ee,Ue]=Q(""),[ur,Be]=Q(false),yi=$e(null),hr=$e(null),gr=E(l=>{},[]),pr=l=>{Ue(l),D==="events"&&xe(k=>({...k,searchText:l}))},fr=E(()=>{Ue(""),xe(l=>({...l,searchText:""})),Be(false)},[xe]),dt=E(l=>{ie(l.id)},[]),mr=E(()=>{P(true)},[]),yr=E(()=>{ie(null)},[]),ut=E(l=>{let k=z[l];k&&ie(k.id)},[z]),br=E(l=>{me(l),ie(null)},[]),Sr=E(()=>{me(null),ie(null)},[]),Cr=E(l=>{ye(l),y?.(l)},[y]),xr=E(()=>{ye(null)},[]),wr=E(()=>ue.reduce((l,k)=>{try{let q=k.api.getState();if(q&&typeof q=="object"){let Ct={};for(let[Er,xt]of Object.entries(q))typeof xt!="function"&&(Ct[Er]=he(xt));l[k.name]=Ct}else l[k.name]=he(q)}catch{l[k.name]=null}return l},{}),[ue]),vr=E(()=>Y.map(l=>({id:l.id,storeName:l.storeName,timestamp:l.timestamp,prevState:he(l.prevState),nextState:he(l.nextState),hasStateChange:l.hasStateChange,changedKeys:l.changedKeys})),[Y]),Tr=E(()=>z.map(l=>({id:l.id,storeName:l.storeName,timestamp:l.timestamp,prevState:he(l.prevState),nextState:he(l.nextState),hasStateChange:l.hasStateChange,changedKeys:l.changedKeys})),[z]),Ir=E(l=>{Ce(k=>{let q=new Set(k);return q.has(l)?q.delete(l):q.add(l),q})},[]),kr=E(l=>{Ce(k=>new Set([...k,l]))},[]),Dr=E(l=>{j(l),me(null),ye(null),ie(null),Se(false),ee&&(Ue(""),xe(k=>({...k,searchText:""}))),Be(false)},[ee,xe]),ht=E(l=>l.id,[]),gt=te(()=>cn(z),[z]),pt=E(({item:l})=>g(Vt,{change:l,onPress:dt,testID:gt.get(l.id)}),[dt,gt]),ft=J.size>0,mt=()=>be?F(A,{children:[g(A.Navigation,{onBack:()=>Se(false)}),g(A.Content,{title:"Filters",centered:true,testID:`${u}-filters-title`})]}):Z?F(A,{children:[g(A.Navigation,{onBack:yr}),g(A.Content,{title:`${Z.storeName}/setState`,centered:true,testID:`${u}-detail-title`})]}):O?F(A,{children:[g(A.Navigation,{onBack:Sr}),g(A.Content,{title:`${O} History`,centered:true,testID:`${u}-history-title`}),g(A.Actions,{children:g(Ge,{value:Tr,disabled:z.length===0,buttonStyle:L.headerActionButton,testID:`${u}-copy`})})]}):oe?F(A,{children:[g(A.Navigation,{onBack:xr}),g(A.Content,{title:oe,centered:true,testID:`${u}-store-detail-title`})]}):F(A,{children:[r&&g(A.Navigation,{onBack:r}),g(A.Content,{title:"",children:ur?g(A.Search,{value:ee,onChangeText:pr,onCancel:fr,placeholder:D==="stores"?"Search stores...":"Search events...",accessibilityLabel:"Search Zustand stores and events",iconSize:14,testID:`${u}-search-field`,containerTestID:`${u}-search`,clearTestID:`${u}-search-clear`,onBlur:()=>{ee.length===0&&Be(false)}}):g(oo,{tabs:[{key:"stores",label:`Stores${ue.length>0?` (${ue.length})`:""}`},{key:"events",label:`Events${Y.length>0?` (${Y.length})`:""}`}],activeTab:D,onTabChange:Dr,testIDPrefix:`${u}-tab`})}),F(A.Actions,{children:[g(re,{onPress:()=>Be(true),style:L.headerActionButton,testID:`${u}-search-open`,accessibilityRole:"button",accessibilityLabel:"Search",children:g(io,{size:14,color:V.color.textSecondary})}),g(re,{onPress:()=>Se(true),style:[L.headerActionButton,ft&&L.headerActionButtonActive],testID:`${u}-filters-open`,accessibilityRole:"button",accessibilityLabel:"Filters",children:g(so,{size:14,color:ft?V.color.accent:V.color.textSecondary})}),D==="stores"&&g(Ge,{value:wr,disabled:ue.length===0,buttonStyle:L.headerActionButton,testID:`${u}-copy`}),D==="events"&&F(Xt,{children:[g(Ge,{value:vr,disabled:Y.length===0,buttonStyle:L.headerActionButton,testID:`${u}-copy`}),g(go,{isEnabled:ke,onToggle:lr,accessibilityLabel:"Toggle Zustand state capture",testID:`${u}-power`}),g(po,{onPress:sr,disabled:Y.length===0,buttonStyle:L.headerActionButton,testID:`${u}-clear`})]})]})]}),Br=()=>{if(be)return g(Fn,{ignoredPatterns:J,onTogglePattern:Ir,onAddPattern:kr,stores:we});if(Z&&se!==null)return g(Gt,{change:Z,changes:z,selectedIndex:se,onIndexChange:ut,disableInternalFooter:true,initialView:p});if(O)return z.length>0?g(Ze,{testID:`${u}-history-list`,data:z,renderItem:pt,keyExtractor:ht,contentContainerStyle:L.listContent,showsVerticalScrollIndicator:true,...At}):g(_e,{testID:`${u}-history-empty`,...Nt({subject:"changes",search:ee,total:ee.trim()?cr:0,capturing:ke,waiting:{otto:"waiting",title:"No history yet",message:`State changes for ${O} will appear here.`},paused:{title:"No history yet",message:`Capture is off, so nothing is being recorded for ${O}.`}})});if(oe){let l=we.find(k=>k.name===oe)??null;return l?g(zn,{store:l,onViewHistory:br}):g(_e,{testID:`${u}-store-detail-gone`,otto:"ghost",title:"Store no longer registered",message:`${oe} is not in the registry any more.`})}return D==="stores"?g(Tn,{stores:ue,searchQuery:ee,isLoading:i,onOpenStore:Cr}):F(Xt,{children:[!ke&&F(d,{style:L.disabledBanner,testID:`${u}-banner-disabled`,children:[g(lo,{size:14,color:V.color.warning}),g(x,{style:L.disabledText,children:"State capture is disabled"})]}),dr&&F(re,{style:L.lockedBanner,onPress:mr,activeOpacity:.8,testID:`${u}-locked`,accessibilityRole:"button",children:[g(co,{size:14,color:V.color.accent}),F(x,{style:L.lockedText,testID:`${u}-locked-text`,children:[Me," older"," ",Me===1?"change":"changes"," locked"]}),g(d,{style:L.upgradeBadge,children:g(x,{style:L.upgradeBadgeText,children:"UPGRADE"})})]}),Fe.length>0?g(Ze,{ref:hr,testID:`${u}-list`,data:Fe,renderItem:pt,keyExtractor:ht,contentContainerStyle:L.listContent,showsVerticalScrollIndicator:true,...At}):g(Mn,{isEnabled:ke,searchText:ee,totalChanges:ir.totalChanges})]})},$r=n?uo.modal.root():"buoy-zustand-modal";if(!e)return null;let yt=Z&&se!==null?g(Jt,{change:Z,changes:z,selectedIndex:se,onIndexChange:ut}):null,Pr=Z&&z.length>1?68:0,Nr=!be&&!(Z&&se!==null)&&(O!=null||D==="events"||D==="stores"),bt=g(d,{style:L.container,children:Br()}),St=g(ho,{visible:f,onClose:()=>P(false),featureName:"Full State History"});return o?F(Et,{children:[F(d,{style:L.inlineRoot,children:[g(d,{style:L.inlineHeader,...mo,children:mt()}),bt,yt]}),St]}):F(Et,{children:[g(ao,{visible:e,onClose:t,onMinimize:a,persistenceKey:$r,header:{showToggleButton:true,customContent:mt()},onModeChange:gr,enablePersistence:true,initialMode:"bottomSheet",enableGlitchEffects:true,disableScrollWrapper:Nr,styles:{},footer:yt,footerHeight:Pr,children:bt}),St]})}function Kn(e={}){return g(Ve,{...e,inline:true,visible:true,onClose:()=>{}})}var L=le.create({inlineRoot:{flex:1,minHeight:0,backgroundColor:"transparent"},inlineHeader:{paddingHorizontal:12,paddingVertical:8,borderBottomWidth:1,borderBottomColor:no.border.default,backgroundColor:"transparent"},container:{flex:1,backgroundColor:"transparent"},headerActionButton:{width:32,height:32,borderRadius:8,backgroundColor:V.color.buttonSurface,borderWidth:1,borderColor:V.color.border,alignItems:"center",justifyContent:"center"},headerActionButtonDisabled:{opacity:.55},headerActionButtonActive:{backgroundColor:V.color.accentSoft,borderColor:V.color.accentBorderStrong},disabledBanner:{flexDirection:"row",alignItems:"center",gap:8,padding:10,marginHorizontal:12,marginTop:8,backgroundColor:V.color.warningSoft,borderRadius:8,borderWidth:1,borderColor:V.color.warning+"20"},disabledText:{color:V.color.warning,fontSize:11,flex:1},listContent:{paddingTop:8,paddingBottom:20},lockedBanner:{flexDirection:"row",alignItems:"center",gap:8,padding:10,marginHorizontal:12,marginTop:8,backgroundColor:V.color.accentSoft,borderRadius:8,borderWidth:1,borderColor:V.color.accentBorder},lockedText:{color:V.color.accent,fontSize:11,fontWeight:"500",flex:1},upgradeBadge:{backgroundColor:V.color.accent,paddingHorizontal:8,paddingVertical:3,borderRadius:4},upgradeBadgeText:{color:V.color.onAccent,fontSize:9,fontWeight:"700",letterSpacing:.5}});import{ZustandIcon as it,ZUSTAND_ICON_COLOR as Un}from"@buoy-gg/shared-ui/web";import{jsx as er}from"react/jsx-runtime";var Zn={id:"zustand",name:"ZUSTAND",description:"Zustand store & state inspector",slot:"both",icon:({size:e})=>er(it,{size:e}),component:Ve,props:{enableSharedModalDimensions:false}};function _n(e){return{id:e?.id||"zustand",name:e?.name||"ZUSTAND",description:e?.description||"Zustand store & state inspector",slot:"both",icon:({size:t})=>er(it,{size:t,color:e?.iconColor}),component:Ve,props:{enableSharedModalDimensions:e?.enableSharedModalDimensions!==void 0?e.enableSharedModalDimensions:false}}}var fe=Symbol.for("@@buoy-zustand/watched");function tr(e){let t=e.persist;return t&&typeof t.getOptions=="function"?{isPersisted:true,persistName:t.getOptions()?.name,persistApi:t}:{isPersisted:false}}function Gn(e){let t=[];for(let[r,a]of Object.entries(e)){let n=a;if(n[fe])continue;n[fe]=true;let{isPersisted:o,persistName:i,persistApi:c}=tr(a);S.registerStore(r,{getState:a.getState,getInitialState:a.getInitialState,setState:a.setState,subscribe:a.subscribe},{isPersisted:o,persistName:i,rehydrate:typeof c?.rehydrate=="function"?()=>c.rehydrate():void 0});let s=false,p=a.subscribe((m,y)=>{try{let b;if(!s&&o){let h=false;try{h=c?.hasHydrated?.()===false}catch{}h&&(s=true,b="persist")}S.addStateChange({storeName:r,partial:void 0,replace:false,prevState:y,nextState:m,duration:void 0,category:b,isPersisted:o})}catch{}});t.push(()=>{p(),delete a[fe],S.unregisterStore(r)})}return()=>{t.forEach(r=>r())}}var Jn=0;function Yn(e,t){return(r,a,n)=>{let o=t?.name??`store-${++Jn}`,i=t?.enabled!==false,c=r,s=(m,y)=>{if(!i)return c(m,y);let b=performance.now(),h=a();c(m,y);let f=a(),P=performance.now()-b,D=typeof m=="function"?"(updater fn)":m;S.addStateChange({storeName:o,partial:D,replace:y??false,prevState:h,nextState:f,duration:P,isPersisted:S.getStore(o)?.isPersisted??false})},p=e(s,a,n);return setTimeout(()=>{if(n[fe])return;n[fe]=true;let{isPersisted:m,persistName:y}=tr(n);S.registerStore(o,{getState:a,getInitialState:n.getInitialState,setState:s,subscribe:n.subscribe},{isPersisted:m,persistName:y})},0),p}}function qn(e){return e[fe]===true}import{expandKeyedArrays as Qn,patchFromPath as Xn,readPath as ei,refusalText as ti,shapeSummary as He,suggestedPatch as st,typedEditViolations as ri,unshapedLists as ai}from"@buoy-gg/shared-ui/web";import{WIRE_DETAIL_LIMIT_BYTES as rr,createSyncAdapter as oi,detailByIdAction as ni,isJsonSerializable as ii,isOverWireBudget as si,memoByIdentity as li,onDeviceMarker as ar,readParams as je,toWire as or,truncatedNote as ci}from"@buoy-gg/shared-ui/web";var Oe=e=>typeof e=="object"&&e!==null&&!Array.isArray(e)&&Object.getPrototypeOf(e)===Object.prototype;function nr(e,t){if(!Oe(e)||!Oe(t))return t;let r={...e};for(let[a,n]of Object.entries(t))r[a]=a in e?nr(e[a],n):n;return r}var We=ar("State","State trees stay on the device \u2014 fetched on demand via getChangeDetail / getStoreState."),di=ar("Payload","Partial stays on the device \u2014 fetched on demand via getChangeDetail.");function ui(e,t){let r=e;for(let a of t.split(".")){if(!r||typeof r!="object"||Array.isArray(r)||!(a in r))return false;r=r[a]}return Array.isArray(r)?r.length>0:!!r&&typeof r=="object"}function hi(e){return e&&typeof e=="object"&&!Array.isArray(e)?Object.keys(e):void 0}var gi=li(e=>({...e,prevState:We,nextState:We,partial:or(e.partial,di)})),pi=e=>or(e,We),fi=oi({version:2,getSnapshot:()=>({changes:S.getStateChanges().map(gi),stores:S.getStoreSnapshots().map(e=>({...e,currentState:pi(e.currentState)}))}),subscribe:[e=>S.subscribe(e),e=>S.subscribeToStores(e)],actions:{clearEvents:()=>{S.clearStateChanges()},getChangeDetail:ni(e=>S.getStateChangeById(e),(e,t)=>({prevState:t(e.prevState),nextState:t(e.nextState),partial:t(e.partial)})),getStoreState:e=>{let{storeName:t,path:r}=je(e);if(!t)return{found:false,reason:"missing storeName"};let a=S.getStore(t);if(!a)return{found:false,reason:"unknown storeName"};let n;try{n=a.api.getState()}catch{n=void 0}if(r){let i=ei(n,r);return i.ok?{found:true,storeName:t,path:r,shape:He(i.value),currentState:i.value}:{found:false,reason:i.error}}let o=He(n);return si(n,rr)?{found:true,storeName:t,...o?{shape:o}:{},currentState:ii(n)?ci(rr):We}:{found:true,storeName:t,...o?{shape:o}:{},currentState:n}},listStores:e=>{let{includeValues:t=false,limit:r}=je(e),a=S.getStoreSnapshots(),n=(typeof r=="number"&&r>0?a.slice(0,r):a).map(o=>({name:o.name,changes:o.stateChangeCount,isPersisted:o.isPersisted,persistName:o.persistName,canRehydrate:o.canRehydrate,...t?{currentState:o.currentState}:{keys:hi(o.currentState)},...He(o.currentState)?{shape:He(o.currentState)}:{}}));return{stores:n,total:a.length,returned:n.length,includedValues:t}},setState:e=>{let{storeName:t,state:r,replace:a,force:n,path:o,value:i}=je(e),c=r,s=[],p=[];if(!t)return{ok:false,error:"Missing storeName."};let m=S.getStore(t);if(!m)return{ok:false,error:`No store named "${t}".`};if(r===void 0&&o===void 0)return{ok:false,error:"Refused: no change was described. Send `state` with the fields to merge, or `path` and `value` to set one value."};let y=false;if(o!==void 0){if(i===void 0)return{ok:false,error:`Refused: sent \`path\` without \`value\`. Say what to set "${o}" to; if you mean to clear it, send value:null and the field must already be nullable.`};let h;try{h=m.api.getState()}catch{h=void 0}let f=Xn(h,o,i);if(!f.ok)return{ok:false,error:`Refused: ${f.error}`};c=f.patch,y=true}if(!n&&(a===false||y)){let h;try{h=m.api.getState()}catch{h=void 0}if(h!==void 0){let f=Qn(h,c);if(f.error)return{ok:false,error:`Refused: ${f.error}`};c=f.patch,s=f.notes}if(h!==void 0&&(p=ai(h).filter(f=>ui(c,f))),h!==void 0){let f=ri(h,c,{noun:"store"});if(f.length>0)return{ok:false,error:ti(f,"store",st(c,f)),...st(c,f)?{suggestedState:st(c,f)}:{},violations:f}}}let b=y||a===false;if(b){let h;try{h=m.api.getState()}catch{h=void 0}if(Oe(h)&&Oe(c)){let f={};for(let[P,D]of Object.entries(c))f[P]=P in h?nr(h[P],D):D;c=f}}return m.api.setState(c,b?false:a??true),{ok:true,...o!==void 0?{path:o}:{},...s.length?{keyed:s}:{},...p.length?{unchecked:p.map(h=>`\`${h}\` was empty, so nothing in the app knows what its items look like and the shape of what you added was NOT checked. If the app renders a field you left out, it will render undefined \u2014 read the store back and compare against how the screen uses it.`)}:{}}},rehydrate:async e=>{let{storeName:t}=je(e);if(!t)return{ok:false,error:"Missing storeName."};let r=S.getStore(t);return r?r.isPersisted?r.rehydrate?(await r.rehydrate(),{ok:true,storeName:t,persistName:r.persistName}):{ok:false,error:`"${t}" is persisted but Buoy has no rehydrate handle for it. It was probably registered before the app's persist middleware attached.`}:{ok:false,error:`"${t}" is not a persisted store \u2014 it has no saved copy to re-read.`}:{ok:false,error:`No store named "${t}".`}}}});export{Un as ZUSTAND_ICON_COLOR,it as ZustandIcon,Ve as ZustandModal,Vt as ZustandStateChangeItem,Gt as ZustandStateDetailContent,Jt as ZustandStateDetailFooter,Kn as ZustandToolView,Yn as buoyDevTools,_n as createZustandTool,qn as isStoreInstrumented,Lt as useZustandStateChanges,Gn as watchStores,S as zustandStateStore,fi as zustandSyncAdapter,Zn as zustandToolPreset};
|