@buoy-gg/jotai 7.0.41 → 7.0.43

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 (54) hide show
  1. package/README.md +11 -80
  2. package/lib/commonjs/index.js +1 -112
  3. package/lib/commonjs/jotai/components/JotaiAtomBrowser.js +1 -199
  4. package/lib/commonjs/jotai/components/JotaiAtomChangeItem.js +1 -95
  5. package/lib/commonjs/jotai/components/JotaiAtomDetailContent.js +1 -715
  6. package/lib/commonjs/jotai/components/JotaiAtomValueDetailContent.js +1 -444
  7. package/lib/commonjs/jotai/components/JotaiEventFilterView.js +1 -43
  8. package/lib/commonjs/jotai/components/JotaiIcon.js +1 -18
  9. package/lib/commonjs/jotai/components/JotaiModal.js +1 -743
  10. package/lib/commonjs/jotai/hooks/useJotaiAtomChanges.js +1 -69
  11. package/lib/commonjs/jotai/sync/jotaiSyncAdapter.js +1 -306
  12. package/lib/commonjs/jotai/types/index.js +1 -1
  13. package/lib/commonjs/jotai/utils/jotaiStateStore.js +1 -321
  14. package/lib/commonjs/jotai/utils/snapshotProvider.js +1 -215
  15. package/lib/commonjs/jotai/utils/testIDs.js +1 -90
  16. package/lib/commonjs/jotai/utils/watchAtoms.js +1 -143
  17. package/lib/commonjs/jotai/utils/writeSemantics.js +1 -47
  18. package/lib/commonjs/preset.js +1 -90
  19. package/lib/module/index.js +1 -85
  20. package/lib/module/jotai/components/JotaiAtomBrowser.js +1 -195
  21. package/lib/module/jotai/components/JotaiAtomChangeItem.js +1 -91
  22. package/lib/module/jotai/components/JotaiAtomDetailContent.js +1 -710
  23. package/lib/module/jotai/components/JotaiAtomValueDetailContent.js +1 -442
  24. package/lib/module/jotai/components/JotaiEventFilterView.js +1 -39
  25. package/lib/module/jotai/components/JotaiIcon.js +1 -11
  26. package/lib/module/jotai/components/JotaiModal.js +1 -738
  27. package/lib/module/jotai/hooks/useJotaiAtomChanges.js +1 -65
  28. package/lib/module/jotai/sync/jotaiSyncAdapter.js +1 -303
  29. package/lib/module/jotai/types/index.js +1 -1
  30. package/lib/module/jotai/utils/jotaiStateStore.js +1 -317
  31. package/lib/module/jotai/utils/snapshotProvider.js +1 -214
  32. package/lib/module/jotai/utils/testIDs.js +1 -82
  33. package/lib/module/jotai/utils/watchAtoms.js +1 -138
  34. package/lib/module/jotai/utils/writeSemantics.js +1 -43
  35. package/lib/module/preset.js +1 -87
  36. package/lib/web/index.mjs +2 -3
  37. package/package.json +4 -7
  38. package/lib/typescript/index.d.ts.map +0 -1
  39. package/lib/typescript/jotai/components/JotaiAtomBrowser.d.ts.map +0 -1
  40. package/lib/typescript/jotai/components/JotaiAtomChangeItem.d.ts.map +0 -1
  41. package/lib/typescript/jotai/components/JotaiAtomDetailContent.d.ts.map +0 -1
  42. package/lib/typescript/jotai/components/JotaiAtomValueDetailContent.d.ts.map +0 -1
  43. package/lib/typescript/jotai/components/JotaiEventFilterView.d.ts.map +0 -1
  44. package/lib/typescript/jotai/components/JotaiIcon.d.ts.map +0 -1
  45. package/lib/typescript/jotai/components/JotaiModal.d.ts.map +0 -1
  46. package/lib/typescript/jotai/hooks/useJotaiAtomChanges.d.ts.map +0 -1
  47. package/lib/typescript/jotai/sync/jotaiSyncAdapter.d.ts.map +0 -1
  48. package/lib/typescript/jotai/types/index.d.ts.map +0 -1
  49. package/lib/typescript/jotai/utils/jotaiStateStore.d.ts.map +0 -1
  50. package/lib/typescript/jotai/utils/snapshotProvider.d.ts.map +0 -1
  51. package/lib/typescript/jotai/utils/testIDs.d.ts.map +0 -1
  52. package/lib/typescript/jotai/utils/watchAtoms.d.ts.map +0 -1
  53. package/lib/typescript/jotai/utils/writeSemantics.d.ts.map +0 -1
  54. package/lib/typescript/preset.d.ts.map +0 -1
@@ -1,715 +1 @@
1
- "use strict";
2
-
3
- Object.defineProperty(exports, "__esModule", {
4
- value: true
5
- });
6
- exports.JotaiAtomDetailContent = JotaiAtomDetailContent;
7
- exports.JotaiAtomDetailFooter = JotaiAtomDetailFooter;
8
- var _react = _interopRequireWildcard(require("react"));
9
- var _reactNative = require("react-native");
10
- var _sharedUi = require("@buoy-gg/shared-ui");
11
- var _dataViewer = require("@buoy-gg/shared-ui/dataViewer");
12
- var _license = require("@buoy-gg/license");
13
- var _jotaiStateStore = require("../utils/jotaiStateStore");
14
- var _testIDs = require("../utils/testIDs");
15
- var _jsxRuntime = require("react/jsx-runtime");
16
- function _interopRequireWildcard(e, t) { if ("function" == typeof WeakMap) var r = new WeakMap(), n = new WeakMap(); return (_interopRequireWildcard = function (e, t) { if (!t && e && e.__esModule) return e; var o, i, f = { __proto__: null, default: e }; if (null === e || "object" != typeof e && "function" != typeof e) return f; if (o = t ? n : r) { if (o.has(e)) return o.get(e); o.set(e, f); } for (const t in e) "default" !== t && {}.hasOwnProperty.call(e, t) && ((i = (o = Object.defineProperty) && Object.getOwnPropertyDescriptor(e, t)) && (i.get || i.set) ? o(f, t, i) : f[t] = e[t]); return f; })(e, t); }
17
- /**
18
- * JotaiAtomDetailContent
19
- *
20
- * Detail view for a Jotai atom change with 3 view modes:
21
- * - CHANGE: Atom label, timestamp, category, changed keys
22
- * - VALUE: Full atom value after change
23
- * - DIFF: Compare prev vs next value
24
- *
25
- * Mirrors ZustandStateDetailContent.tsx from @buoy-gg/zustand
26
- */
27
-
28
- // ---- View Toggle ----
29
- const VIEW_CONFIGS = [{
30
- key: "change",
31
- label: "CHANGE",
32
- icon: _sharedUi.FileText
33
- }, {
34
- key: "value",
35
- label: "VALUE",
36
- icon: _sharedUi.Database
37
- }, {
38
- key: "diff",
39
- label: "DIFF",
40
- icon: _sharedUi.GitBranch
41
- }];
42
- const DIFF_DISABLED = ["diff"];
43
-
44
- // ---- Helpers ----
45
-
46
- function getCategoryInfo(category) {
47
- switch (category) {
48
- case "initial":
49
- return {
50
- label: "INITIAL",
51
- color: _sharedUi.night.color.textTertiary,
52
- bgColor: _sharedUi.night.color.textTertiary + "26"
53
- };
54
- default:
55
- return {
56
- label: "WRITE",
57
- color: _sharedUi.buoyColors.success,
58
- bgColor: _sharedUi.buoyColors.success + "26"
59
- };
60
- }
61
- }
62
- function formatTime(timestamp) {
63
- const date = new Date(timestamp);
64
- const h = date.getHours().toString().padStart(2, "0");
65
- const m = date.getMinutes().toString().padStart(2, "0");
66
- const s = date.getSeconds().toString().padStart(2, "0");
67
- const ms = date.getMilliseconds().toString().padStart(3, "0");
68
- return `${h}:${m}:${s}.${ms}`;
69
- }
70
- function formatTimestamp(timestamp) {
71
- return new Date(timestamp).toLocaleTimeString("en-US", {
72
- hour12: false,
73
- hour: "2-digit",
74
- minute: "2-digit",
75
- second: "2-digit"
76
- });
77
- }
78
- function getValueType(value) {
79
- if (value === null) return "null";
80
- if (value === undefined) return "undefined";
81
- if (Array.isArray(value)) return "array";
82
- return typeof value;
83
- }
84
- function getChangeLabel(category) {
85
- return category === "initial" ? "INIT" : "WRITE";
86
- }
87
- const DIFF_MODE_TABS = [{
88
- key: "tree",
89
- label: "TREE VIEW"
90
- }, {
91
- key: "split",
92
- label: "SPLIT VIEW"
93
- }];
94
-
95
- // ---- Change Info View (CHANGE tab) ----
96
-
97
- const JotaiAtomInfoView = /*#__PURE__*/(0, _react.memo)(function JotaiAtomInfoView({
98
- change
99
- }) {
100
- const isPro = (0, _license.useIsPro)();
101
- const [showProModal, setShowProModal] = (0, _react.useState)(false);
102
- const categoryInfo = getCategoryInfo(change.category);
103
- const atomColor = _jotaiStateStore.jotaiStateStore.getAtomColor(change.atomLabel);
104
- const handleCopyValue = (0, _react.useCallback)(async () => {
105
- if (!isPro) {
106
- setShowProModal(true);
107
- return;
108
- }
109
- await (0, _sharedUi.copyToClipboard)(change.nextValue);
110
- }, [change.nextValue, isPro]);
111
- return /*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNative.ScrollView, {
112
- style: infoStyles.container,
113
- contentContainerStyle: infoStyles.content,
114
- showsVerticalScrollIndicator: false,
115
- testID: `${_testIDs.JOTAI_TEST_ID}-detail-scroll`,
116
- children: [/*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNative.View, {
117
- style: infoStyles.card,
118
- testID: `${_testIDs.JOTAI_TEST_ID}-info-card`,
119
- children: [/*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.View, {
120
- style: infoStyles.sectionHeader,
121
- children: /*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNative.View, {
122
- style: infoStyles.sectionHeaderLeft,
123
- children: [/*#__PURE__*/(0, _jsxRuntime.jsx)(_sharedUi.Info, {
124
- size: 14,
125
- color: _sharedUi.night.color.accent
126
- }), /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.Text, {
127
- style: infoStyles.sectionTitle,
128
- children: "CHANGE INFO"
129
- })]
130
- })
131
- }), /*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNative.View, {
132
- style: infoStyles.cardContent,
133
- children: [/*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNative.View, {
134
- style: infoStyles.infoRow,
135
- children: [/*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.Text, {
136
- style: infoStyles.infoLabel,
137
- children: "Atom"
138
- }), /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.Text, {
139
- style: [infoStyles.infoValue, infoStyles.infoValueMono, {
140
- color: atomColor
141
- }],
142
- numberOfLines: 1,
143
- ellipsizeMode: "middle",
144
- testID: `${_testIDs.JOTAI_TEST_ID}-info-atom`,
145
- children: change.atomLabel
146
- })]
147
- }), /*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNative.View, {
148
- style: infoStyles.infoRow,
149
- children: [/*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.Text, {
150
- style: infoStyles.infoLabel,
151
- children: "Time"
152
- }), /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.Text, {
153
- style: [infoStyles.infoValue, infoStyles.infoValueMono],
154
- testID: `${_testIDs.JOTAI_TEST_ID}-info-time`,
155
- children: formatTime(change.timestamp)
156
- })]
157
- }), /*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNative.View, {
158
- style: infoStyles.badgeRow,
159
- children: [/*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.View, {
160
- style: [infoStyles.categoryBadge, {
161
- backgroundColor: categoryInfo.bgColor
162
- }],
163
- children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.Text, {
164
- style: [infoStyles.categoryText, {
165
- color: categoryInfo.color
166
- }],
167
- testID: `${_testIDs.JOTAI_TEST_ID}-info-category`,
168
- children: categoryInfo.label
169
- })
170
- }), change.hasValueChange ? /*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNative.View, {
171
- style: infoStyles.changesBadge,
172
- children: [/*#__PURE__*/(0, _jsxRuntime.jsx)(_sharedUi.Zap, {
173
- size: 10,
174
- color: _sharedUi.buoyColors.success
175
- }), /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.Text, {
176
- style: infoStyles.changesText,
177
- testID: `${_testIDs.JOTAI_TEST_ID}-info-changes`,
178
- children: change.diffSummary || "changed"
179
- })]
180
- }) : /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.View, {
181
- style: infoStyles.noChangesBadge,
182
- children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.Text, {
183
- style: infoStyles.noChangesText,
184
- testID: `${_testIDs.JOTAI_TEST_ID}-info-no-changes`,
185
- children: "no change"
186
- })
187
- })]
188
- })]
189
- })]
190
- }), change.changedKeys.length > 0 && /*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNative.View, {
191
- style: infoStyles.card,
192
- testID: `${_testIDs.JOTAI_TEST_ID}-keys-card`,
193
- children: [/*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNative.View, {
194
- style: infoStyles.sectionHeader,
195
- children: [/*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNative.View, {
196
- style: infoStyles.sectionHeaderLeft,
197
- children: [/*#__PURE__*/(0, _jsxRuntime.jsx)(_sharedUi.Zap, {
198
- size: 14,
199
- color: _sharedUi.night.color.accent
200
- }), /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.Text, {
201
- style: infoStyles.sectionTitle,
202
- children: "CHANGED KEYS"
203
- })]
204
- }), /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.View, {
205
- style: infoStyles.countBadge,
206
- children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.Text, {
207
- style: infoStyles.countText,
208
- testID: `${_testIDs.JOTAI_TEST_ID}-keys-count`,
209
- children: change.changedKeys.length
210
- })
211
- })]
212
- }), /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.View, {
213
- style: infoStyles.cardContent,
214
- children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.View, {
215
- style: infoStyles.keysContainer,
216
- children: change.changedKeys.map(key => /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.View, {
217
- style: infoStyles.keyBadge,
218
- children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.Text, {
219
- style: infoStyles.keyText,
220
- testID: `${_testIDs.JOTAI_TEST_ID}-key-${(0, _testIDs.slugForTestID)(key)}`,
221
- children: key
222
- })
223
- }, key))
224
- })
225
- })]
226
- }), /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.View, {
227
- style: infoStyles.actionsRow,
228
- children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.View, {
229
- style: [infoStyles.actionButton, infoStyles.actionButtonCopy],
230
- onTouchEnd: handleCopyValue,
231
- testID: `${_testIDs.JOTAI_TEST_ID}-copy-value`,
232
- accessibilityRole: "button",
233
- accessibilityLabel: "Copy value",
234
- children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.Text, {
235
- style: [infoStyles.actionButtonText, {
236
- color: _sharedUi.night.color.accent
237
- }],
238
- children: "COPY VALUE"
239
- })
240
- })
241
- }), /*#__PURE__*/(0, _jsxRuntime.jsx)(_sharedUi.ProUpgradeModal, {
242
- visible: showProModal,
243
- onClose: () => setShowProModal(false),
244
- featureName: "Copy"
245
- })]
246
- });
247
- });
248
-
249
- // ---- Main Detail Content ----
250
-
251
- function JotaiAtomDetailContent({
252
- change,
253
- changes,
254
- selectedIndex,
255
- onIndexChange,
256
- disableInternalFooter = false,
257
- initialView = "change"
258
- }) {
259
- // View state (initialView seeds it once; taps own it afterwards)
260
- const [activeView, setActiveView] = (0, _react.useState)(initialView);
261
- const [diffMode, setDiffMode] = (0, _react.useState)("tree");
262
- const totalChanges = changes.length;
263
- const atomColor = _jotaiStateStore.jotaiStateStore.getAtomColor(change.atomLabel);
264
- const changeLabel = getChangeLabel(change.category);
265
- const valueType = getValueType((0, _sharedUi.parseValue)(change.nextValue));
266
- const chronologicalNumber = totalChanges - selectedIndex;
267
- const prevChangeIndex = selectedIndex < totalChanges - 1 ? selectedIndex + 1 : null;
268
- const prevChange = prevChangeIndex !== null ? changes[prevChangeIndex] : null;
269
- const prevChronologicalNumber = chronologicalNumber - 1;
270
- const leftEvent = (0, _react.useMemo)(() => ({
271
- index: prevChangeIndex ?? 0,
272
- label: prevChronologicalNumber > 0 ? `#${prevChronologicalNumber}` : "Initial",
273
- timestamp: prevChange ? formatTimestamp(prevChange.timestamp) : "",
274
- relativeTime: prevChange ? (0, _sharedUi.formatRelativeTime)(new Date(prevChange.timestamp)) : "value",
275
- badge: prevChange ? /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.View, {
276
- style: [styles.changeBadgeSmall, {
277
- backgroundColor: `${_jotaiStateStore.jotaiStateStore.getAtomColor(prevChange.atomLabel)}20`
278
- }],
279
- children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.Text, {
280
- style: [styles.changeTextSmall, {
281
- color: _jotaiStateStore.jotaiStateStore.getAtomColor(prevChange.atomLabel)
282
- }],
283
- children: getChangeLabel(prevChange.category)
284
- })
285
- }) : undefined
286
- }), [prevChangeIndex, prevChange, prevChronologicalNumber]);
287
- const rightEvent = (0, _react.useMemo)(() => ({
288
- index: selectedIndex,
289
- label: `#${chronologicalNumber}`,
290
- timestamp: formatTimestamp(change.timestamp),
291
- relativeTime: (0, _sharedUi.formatRelativeTime)(new Date(change.timestamp)),
292
- badge: /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.View, {
293
- style: [styles.changeBadgeSmall, {
294
- backgroundColor: `${atomColor}20`
295
- }],
296
- children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.Text, {
297
- style: [styles.changeTextSmall, {
298
- color: atomColor
299
- }],
300
- children: changeLabel
301
- })
302
- })
303
- }), [selectedIndex, change.timestamp, atomColor, changeLabel, chronologicalNumber]);
304
- const renderValueView = (0, _react.useCallback)(() => {
305
- const parsed = (0, _sharedUi.parseValue)(change.nextValue);
306
- return /*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNative.View, {
307
- style: styles.contentCard,
308
- testID: `${_testIDs.JOTAI_TEST_ID}-value-card`,
309
- children: [/*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNative.View, {
310
- style: styles.valueHeader,
311
- children: [/*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.Text, {
312
- style: styles.valueLabel,
313
- children: "VALUE AFTER CHANGE"
314
- }), /*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNative.View, {
315
- style: styles.valueHeaderBadges,
316
- children: [/*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.View, {
317
- style: [styles.changeBadge, {
318
- backgroundColor: `${atomColor}20`
319
- }],
320
- children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.Text, {
321
- style: [styles.changeText, {
322
- color: atomColor
323
- }],
324
- children: changeLabel
325
- })
326
- }), /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.View, {
327
- style: styles.typeBadge,
328
- children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.Text, {
329
- style: styles.typeText,
330
- testID: `${_testIDs.JOTAI_TEST_ID}-value-type`,
331
- children: valueType.toUpperCase()
332
- })
333
- })]
334
- })]
335
- }), /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.View, {
336
- style: infoStyles.dataViewerContainer,
337
- children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_dataViewer.DataViewer, {
338
- title: "",
339
- data: parsed,
340
- showTypeFilter: true,
341
- rawMode: true,
342
- initialExpanded: true
343
- })
344
- })]
345
- });
346
- }, [change.nextValue, atomColor, changeLabel, valueType]);
347
- const renderDiffContent = (0, _react.useCallback)(() => {
348
- const prevVal = (0, _sharedUi.parseValue)(change.prevValue);
349
- const nextVal = (0, _sharedUi.parseValue)(change.nextValue);
350
- if (diffMode === "split") {
351
- return /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.ScrollView, {
352
- style: {
353
- flex: 1
354
- },
355
- showsVerticalScrollIndicator: true,
356
- children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_dataViewer.SplitDiffViewer, {
357
- oldValue: prevVal,
358
- newValue: nextVal,
359
- theme: _dataViewer.diffThemes.devToolsDefault,
360
- options: {
361
- hideLineNumbers: false,
362
- disableWordDiff: false,
363
- showDiffOnly: false,
364
- compareMethod: "words",
365
- contextLines: 3
366
- },
367
- showThemeName: false
368
- })
369
- });
370
- }
371
- return /*#__PURE__*/(0, _jsxRuntime.jsx)(_dataViewer.TreeDiffViewer, {
372
- oldValue: prevVal,
373
- newValue: nextVal
374
- });
375
- }, [change.prevValue, change.nextValue, diffMode]);
376
- const handleFooterPrevious = (0, _react.useCallback)(() => {
377
- onIndexChange(Math.min(totalChanges - 1, selectedIndex + 1));
378
- }, [selectedIndex, totalChanges, onIndexChange]);
379
- const handleFooterNext = (0, _react.useCallback)(() => {
380
- onIndexChange(Math.max(0, selectedIndex - 1));
381
- }, [selectedIndex, onIndexChange]);
382
-
383
- // The diff compares THIS change's prevValue/nextValue — no siblings needed.
384
- // Gating on `changes.length` greyed DIFF out for every jotai event opened
385
- // from the Events timeline (a one-element array). Only a change with no
386
- // captured previous value has nothing to compare.
387
- const diffDisabled = change.prevValue === undefined;
388
- const showInternalFooter = !disableInternalFooter && totalChanges > 1;
389
- return /*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNative.View, {
390
- style: styles.container,
391
- children: [/*#__PURE__*/(0, _jsxRuntime.jsx)(_sharedUi.DetailViewToggle, {
392
- views: VIEW_CONFIGS,
393
- activeView: activeView,
394
- onViewChange: setActiveView,
395
- disabledKeys: diffDisabled ? DIFF_DISABLED : undefined,
396
- testIDPrefix: _testIDs.JOTAI_TEST_ID
397
- }), /*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNative.View, {
398
- style: [styles.contentArea, showInternalFooter && styles.contentAreaFooterPad],
399
- children: [activeView === "change" && /*#__PURE__*/(0, _jsxRuntime.jsx)(JotaiAtomInfoView, {
400
- change: change
401
- }), activeView === "value" && /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.View, {
402
- style: styles.stateContainer,
403
- children: renderValueView()
404
- }), activeView === "diff" && /*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNative.View, {
405
- style: styles.diffContainer,
406
- testID: `${_testIDs.JOTAI_TEST_ID}-diff`,
407
- children: [/*#__PURE__*/(0, _jsxRuntime.jsx)(_sharedUi.DiffModeTabs, {
408
- tabs: DIFF_MODE_TABS,
409
- activeTab: diffMode,
410
- onTabChange: setDiffMode,
411
- testIDPrefix: `${_testIDs.JOTAI_TEST_ID}-diff-tab`
412
- }), /*#__PURE__*/(0, _jsxRuntime.jsx)(_sharedUi.CompareBar, {
413
- leftEvent: leftEvent,
414
- rightEvent: rightEvent
415
- }), /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.View, {
416
- style: styles.diffContent,
417
- testID: `${_testIDs.JOTAI_TEST_ID}-diff-content`,
418
- children: renderDiffContent()
419
- })]
420
- })]
421
- }), showInternalFooter && /*#__PURE__*/(0, _jsxRuntime.jsx)(_sharedUi.EventStepperFooter, {
422
- currentIndex: chronologicalNumber - 1,
423
- totalItems: totalChanges,
424
- onPrevious: handleFooterPrevious,
425
- onNext: handleFooterNext,
426
- itemLabel: "Change",
427
- subtitle: (0, _sharedUi.formatRelativeTime)(new Date(change.timestamp)),
428
- absolute: true
429
- })]
430
- });
431
- }
432
- function JotaiAtomDetailFooter({
433
- change,
434
- changes,
435
- selectedIndex,
436
- onIndexChange
437
- }) {
438
- const totalChanges = changes.length;
439
- if (totalChanges <= 1) return null;
440
- const chronologicalNumber = totalChanges - selectedIndex;
441
- return /*#__PURE__*/(0, _jsxRuntime.jsx)(_sharedUi.EventStepperFooter, {
442
- currentIndex: chronologicalNumber - 1,
443
- totalItems: totalChanges,
444
- onPrevious: () => onIndexChange(Math.min(totalChanges - 1, selectedIndex + 1)),
445
- onNext: () => onIndexChange(Math.max(0, selectedIndex - 1)),
446
- itemLabel: "Change",
447
- subtitle: (0, _sharedUi.formatRelativeTime)(new Date(change.timestamp))
448
- });
449
- }
450
- const styles = _reactNative.StyleSheet.create({
451
- container: {
452
- flex: 1,
453
- // Transparent so the night sheet's star field shows through.
454
- backgroundColor: "transparent"
455
- },
456
- contentArea: {
457
- flex: 1
458
- },
459
- // Clearance for the absolute EventStepperFooter — only when it renders,
460
- // otherwise hosts like the Events tool get a dead band at the sheet bottom.
461
- contentAreaFooterPad: {
462
- paddingBottom: 96
463
- },
464
- stateContainer: {
465
- flex: 1,
466
- padding: 14
467
- },
468
- contentCard: {
469
- backgroundColor: _sharedUi.night.color.surface,
470
- borderRadius: 14,
471
- padding: 14,
472
- borderWidth: 1,
473
- borderColor: _sharedUi.night.color.border
474
- },
475
- valueHeader: {
476
- flexDirection: "row",
477
- alignItems: "center",
478
- justifyContent: "space-between",
479
- marginBottom: 8
480
- },
481
- valueLabel: {
482
- fontSize: 10,
483
- color: _sharedUi.night.color.textSecondary,
484
- fontFamily: _sharedUi.monoFont,
485
- letterSpacing: 0.5,
486
- fontWeight: "600"
487
- },
488
- valueHeaderBadges: {
489
- flexDirection: "row",
490
- alignItems: "center",
491
- gap: 6
492
- },
493
- changeBadge: {
494
- paddingHorizontal: 8,
495
- paddingVertical: 2,
496
- borderRadius: 4
497
- },
498
- changeText: {
499
- fontSize: 9,
500
- fontWeight: "700",
501
- fontFamily: _sharedUi.monoFont,
502
- letterSpacing: 0.3
503
- },
504
- typeBadge: {
505
- paddingHorizontal: 8,
506
- paddingVertical: 2,
507
- borderRadius: 4,
508
- backgroundColor: _sharedUi.night.color.surfaceElevated
509
- },
510
- typeText: {
511
- fontSize: 9,
512
- fontWeight: "600",
513
- color: _sharedUi.night.color.textTertiary,
514
- fontFamily: _sharedUi.monoFont
515
- },
516
- valueBox: {
517
- // Inset code box — darker than the card, the night track color.
518
- backgroundColor: _sharedUi.night.color.bg,
519
- borderRadius: 6,
520
- borderWidth: 1,
521
- borderColor: _sharedUi.night.color.border,
522
- padding: 8
523
- },
524
- valueText: {
525
- fontSize: 12,
526
- color: _sharedUi.night.color.text,
527
- fontFamily: _sharedUi.monoFont,
528
- lineHeight: 18
529
- },
530
- diffContainer: {
531
- flex: 1
532
- },
533
- diffContent: {
534
- flex: 1,
535
- paddingHorizontal: 14
536
- },
537
- changeBadgeSmall: {
538
- paddingHorizontal: 6,
539
- paddingVertical: 1,
540
- borderRadius: 3
541
- },
542
- changeTextSmall: {
543
- fontSize: 8,
544
- fontWeight: "700",
545
- fontFamily: _sharedUi.monoFont
546
- }
547
- });
548
- const infoStyles = _reactNative.StyleSheet.create({
549
- container: {
550
- flex: 1
551
- },
552
- content: {
553
- padding: 8,
554
- paddingBottom: 100,
555
- gap: 16
556
- },
557
- card: {
558
- backgroundColor: _sharedUi.night.color.surface,
559
- borderRadius: 6,
560
- borderWidth: 1,
561
- borderColor: _sharedUi.night.color.accentBorderStrong,
562
- overflow: "hidden",
563
- shadowColor: _sharedUi.night.color.accent,
564
- shadowOffset: {
565
- width: 0,
566
- height: 0
567
- },
568
- shadowOpacity: 0.1,
569
- shadowRadius: 6
570
- },
571
- sectionHeader: {
572
- flexDirection: "row",
573
- alignItems: "center",
574
- justifyContent: "space-between",
575
- paddingHorizontal: 12,
576
- paddingVertical: 10,
577
- borderBottomWidth: 1,
578
- borderBottomColor: _sharedUi.night.color.accentBorder,
579
- backgroundColor: _sharedUi.night.color.accentSoft
580
- },
581
- sectionHeaderLeft: {
582
- flexDirection: "row",
583
- alignItems: "center",
584
- gap: 6
585
- },
586
- sectionTitle: {
587
- fontSize: 12,
588
- fontWeight: "600",
589
- letterSpacing: 0.5,
590
- color: _sharedUi.night.color.accent,
591
- fontFamily: _sharedUi.monoFont
592
- },
593
- cardContent: {
594
- padding: 14,
595
- gap: 10
596
- },
597
- infoRow: {
598
- flexDirection: "row",
599
- alignItems: "center",
600
- justifyContent: "space-between"
601
- },
602
- infoLabel: {
603
- fontSize: 11,
604
- color: _sharedUi.night.color.textTertiary,
605
- fontWeight: "500"
606
- },
607
- infoValue: {
608
- fontSize: 11,
609
- color: _sharedUi.night.color.text,
610
- fontWeight: "500",
611
- flex: 1,
612
- textAlign: "right",
613
- marginLeft: 12
614
- },
615
- infoValueMono: {
616
- fontFamily: _sharedUi.monoFont
617
- },
618
- badgeRow: {
619
- flexDirection: "row",
620
- flexWrap: "wrap",
621
- gap: 8,
622
- marginTop: 6
623
- },
624
- categoryBadge: {
625
- paddingHorizontal: 8,
626
- paddingVertical: 3,
627
- borderRadius: 4
628
- },
629
- categoryText: {
630
- fontSize: 9,
631
- fontWeight: "700",
632
- letterSpacing: 0.3
633
- },
634
- changesBadge: {
635
- flexDirection: "row",
636
- alignItems: "center",
637
- gap: 4,
638
- paddingHorizontal: 8,
639
- paddingVertical: 3,
640
- borderRadius: 4,
641
- backgroundColor: _sharedUi.buoyColors.success + "26"
642
- },
643
- changesText: {
644
- fontSize: 9,
645
- fontWeight: "600",
646
- color: _sharedUi.buoyColors.success
647
- },
648
- noChangesBadge: {
649
- paddingHorizontal: 8,
650
- paddingVertical: 3,
651
- borderRadius: 4,
652
- backgroundColor: _sharedUi.night.color.surfaceElevated
653
- },
654
- noChangesText: {
655
- fontSize: 9,
656
- fontWeight: "600",
657
- color: _sharedUi.night.color.textTertiary
658
- },
659
- keysContainer: {
660
- flexDirection: "row",
661
- flexWrap: "wrap",
662
- gap: 6
663
- },
664
- keyBadge: {
665
- paddingHorizontal: 8,
666
- paddingVertical: 4,
667
- borderRadius: 4,
668
- backgroundColor: _sharedUi.night.color.accentSoft,
669
- borderWidth: 1,
670
- borderColor: _sharedUi.night.color.accentBorder
671
- },
672
- keyText: {
673
- fontSize: 11,
674
- fontWeight: "600",
675
- color: _sharedUi.night.color.accent,
676
- fontFamily: _sharedUi.monoFont
677
- },
678
- countBadge: {
679
- paddingHorizontal: 8,
680
- paddingVertical: 3,
681
- borderRadius: 4,
682
- backgroundColor: _sharedUi.night.color.accentFill
683
- },
684
- countText: {
685
- fontSize: 9,
686
- fontWeight: "700",
687
- color: _sharedUi.night.color.accent,
688
- fontFamily: _sharedUi.monoFont
689
- },
690
- actionsRow: {
691
- flexDirection: "row",
692
- gap: 12
693
- },
694
- actionButton: {
695
- paddingHorizontal: 14,
696
- paddingVertical: 8,
697
- borderRadius: 8,
698
- borderWidth: 1
699
- },
700
- actionButtonCopy: {
701
- borderColor: _sharedUi.night.color.accentBorder,
702
- backgroundColor: _sharedUi.night.color.accentSoft
703
- },
704
- actionButtonText: {
705
- fontSize: 10,
706
- fontWeight: "700",
707
- fontFamily: _sharedUi.monoFont,
708
- letterSpacing: 0.3
709
- },
710
- dataViewerContainer: {
711
- marginTop: -12,
712
- marginHorizontal: -12,
713
- marginBottom: -12
714
- }
715
- });
1
+ "use strict";Object.defineProperty(exports,"__esModule",{value:true});exports.JotaiAtomDetailContent=JotaiAtomDetailContent;exports.JotaiAtomDetailFooter=JotaiAtomDetailFooter;var _react=_interopRequireWildcard(require("react"));var _reactNative=require("react-native");var _sharedUi=require("@buoy-gg/shared-ui");var _dataViewer=require("@buoy-gg/shared-ui/dataViewer");var _license=require("@buoy-gg/license");var _jotaiStateStore=require("../utils/jotaiStateStore");var _testIDs=require("../utils/testIDs");var _jsxRuntime=require("react/jsx-runtime");function _interopRequireWildcard(e,o){if("function"==typeof WeakMap)var n=new WeakMap,r=new WeakMap;return(_interopRequireWildcard=function(t,l){if(!l&&t&&t.__esModule)return t;var i,c,a={__proto__:null,default:t};if(null===t||"object"!=typeof t&&"function"!=typeof t)return a;if(i=l?r:n){if(i.has(t))return i.get(t);i.set(t,a)}for(const d in t)"default"!==d&&{}.hasOwnProperty.call(t,d)&&((c=(i=Object.defineProperty)&&Object.getOwnPropertyDescriptor(t,d))&&(c.get||c.set)?i(a,d,c):a[d]=t[d]);return a})(e,o)}const VIEW_CONFIGS=[{key:"change",label:"CHANGE",icon:_sharedUi.FileText},{key:"value",label:"VALUE",icon:_sharedUi.Database},{key:"diff",label:"DIFF",icon:_sharedUi.GitBranch}];const DIFF_DISABLED=["diff"];function getCategoryInfo(e){switch(e){case"initial":return{label:"INITIAL",color:_sharedUi.night.color.textTertiary,bgColor:_sharedUi.night.color.textTertiary+"26"};default:return{label:"WRITE",color:_sharedUi.buoyColors.success,bgColor:_sharedUi.buoyColors.success+"26"}}}function formatTime(e){const o=new Date(e);const n=o.getHours().toString().padStart(2,"0");const r=o.getMinutes().toString().padStart(2,"0");const t=o.getSeconds().toString().padStart(2,"0");const l=o.getMilliseconds().toString().padStart(3,"0");return`${n}:${r}:${t}.${l}`}function formatTimestamp(e){return new Date(e).toLocaleTimeString("en-US",{hour12:false,hour:"2-digit",minute:"2-digit",second:"2-digit"})}function getValueType(e){if(e===null)return"null";if(e===void 0)return"undefined";if(Array.isArray(e))return"array";return typeof e}function getChangeLabel(e){return e==="initial"?"INIT":"WRITE"}const DIFF_MODE_TABS=[{key:"tree",label:"TREE VIEW"},{key:"split",label:"SPLIT VIEW"}];const JotaiAtomInfoView=(0,_react.memo)(function e({change:o}){const n=(0,_license.useIsPro)();const[r,t]=(0,_react.useState)(false);const l=getCategoryInfo(o.category);const i=_jotaiStateStore.jotaiStateStore.getAtomColor(o.atomLabel);const c=(0,_react.useCallback)(async()=>{if(!n){t(true);return}await(0,_sharedUi.copyToClipboard)(o.nextValue)},[o.nextValue,n]);return(0,_jsxRuntime.jsxs)(_reactNative.ScrollView,{style:infoStyles.container,contentContainerStyle:infoStyles.content,showsVerticalScrollIndicator:false,testID:`${_testIDs.JOTAI_TEST_ID}-detail-scroll`,children:[(0,_jsxRuntime.jsxs)(_reactNative.View,{style:infoStyles.card,testID:`${_testIDs.JOTAI_TEST_ID}-info-card`,children:[(0,_jsxRuntime.jsx)(_reactNative.View,{style:infoStyles.sectionHeader,children:(0,_jsxRuntime.jsxs)(_reactNative.View,{style:infoStyles.sectionHeaderLeft,children:[(0,_jsxRuntime.jsx)(_sharedUi.Info,{size:14,color:_sharedUi.night.color.accent}),(0,_jsxRuntime.jsx)(_reactNative.Text,{style:infoStyles.sectionTitle,children:"CHANGE INFO"})]})}),(0,_jsxRuntime.jsxs)(_reactNative.View,{style:infoStyles.cardContent,children:[(0,_jsxRuntime.jsxs)(_reactNative.View,{style:infoStyles.infoRow,children:[(0,_jsxRuntime.jsx)(_reactNative.Text,{style:infoStyles.infoLabel,children:"Atom"}),(0,_jsxRuntime.jsx)(_reactNative.Text,{style:[infoStyles.infoValue,infoStyles.infoValueMono,{color:i}],numberOfLines:1,ellipsizeMode:"middle",testID:`${_testIDs.JOTAI_TEST_ID}-info-atom`,children:o.atomLabel})]}),(0,_jsxRuntime.jsxs)(_reactNative.View,{style:infoStyles.infoRow,children:[(0,_jsxRuntime.jsx)(_reactNative.Text,{style:infoStyles.infoLabel,children:"Time"}),(0,_jsxRuntime.jsx)(_reactNative.Text,{style:[infoStyles.infoValue,infoStyles.infoValueMono],testID:`${_testIDs.JOTAI_TEST_ID}-info-time`,children:formatTime(o.timestamp)})]}),(0,_jsxRuntime.jsxs)(_reactNative.View,{style:infoStyles.badgeRow,children:[(0,_jsxRuntime.jsx)(_reactNative.View,{style:[infoStyles.categoryBadge,{backgroundColor:l.bgColor}],children:(0,_jsxRuntime.jsx)(_reactNative.Text,{style:[infoStyles.categoryText,{color:l.color}],testID:`${_testIDs.JOTAI_TEST_ID}-info-category`,children:l.label})}),o.hasValueChange?(0,_jsxRuntime.jsxs)(_reactNative.View,{style:infoStyles.changesBadge,children:[(0,_jsxRuntime.jsx)(_sharedUi.Zap,{size:10,color:_sharedUi.buoyColors.success}),(0,_jsxRuntime.jsx)(_reactNative.Text,{style:infoStyles.changesText,testID:`${_testIDs.JOTAI_TEST_ID}-info-changes`,children:o.diffSummary||"changed"})]}):(0,_jsxRuntime.jsx)(_reactNative.View,{style:infoStyles.noChangesBadge,children:(0,_jsxRuntime.jsx)(_reactNative.Text,{style:infoStyles.noChangesText,testID:`${_testIDs.JOTAI_TEST_ID}-info-no-changes`,children:"no change"})})]})]})]}),o.changedKeys.length>0&&(0,_jsxRuntime.jsxs)(_reactNative.View,{style:infoStyles.card,testID:`${_testIDs.JOTAI_TEST_ID}-keys-card`,children:[(0,_jsxRuntime.jsxs)(_reactNative.View,{style:infoStyles.sectionHeader,children:[(0,_jsxRuntime.jsxs)(_reactNative.View,{style:infoStyles.sectionHeaderLeft,children:[(0,_jsxRuntime.jsx)(_sharedUi.Zap,{size:14,color:_sharedUi.night.color.accent}),(0,_jsxRuntime.jsx)(_reactNative.Text,{style:infoStyles.sectionTitle,children:"CHANGED KEYS"})]}),(0,_jsxRuntime.jsx)(_reactNative.View,{style:infoStyles.countBadge,children:(0,_jsxRuntime.jsx)(_reactNative.Text,{style:infoStyles.countText,testID:`${_testIDs.JOTAI_TEST_ID}-keys-count`,children:o.changedKeys.length})})]}),(0,_jsxRuntime.jsx)(_reactNative.View,{style:infoStyles.cardContent,children:(0,_jsxRuntime.jsx)(_reactNative.View,{style:infoStyles.keysContainer,children:o.changedKeys.map(a=>(0,_jsxRuntime.jsx)(_reactNative.View,{style:infoStyles.keyBadge,children:(0,_jsxRuntime.jsx)(_reactNative.Text,{style:infoStyles.keyText,testID:`${_testIDs.JOTAI_TEST_ID}-key-${(0,_testIDs.slugForTestID)(a)}`,children:a})},a))})})]}),(0,_jsxRuntime.jsx)(_reactNative.View,{style:infoStyles.actionsRow,children:(0,_jsxRuntime.jsx)(_reactNative.View,{style:[infoStyles.actionButton,infoStyles.actionButtonCopy],onTouchEnd:c,testID:`${_testIDs.JOTAI_TEST_ID}-copy-value`,accessibilityRole:"button",accessibilityLabel:"Copy value",children:(0,_jsxRuntime.jsx)(_reactNative.Text,{style:[infoStyles.actionButtonText,{color:_sharedUi.night.color.accent}],children:"COPY VALUE"})})}),(0,_jsxRuntime.jsx)(_sharedUi.ProUpgradeModal,{visible:r,onClose:()=>t(false),featureName:"Copy"})]})});function JotaiAtomDetailContent({change:e,changes:o,selectedIndex:n,onIndexChange:r,disableInternalFooter:t=false,initialView:l="change"}){const[i,c]=(0,_react.useState)(l);const[a,d]=(0,_react.useState)("tree");const u=o.length;const g=_jotaiStateStore.jotaiStateStore.getAtomColor(e.atomLabel);const f=getChangeLabel(e.category);const T=getValueType((0,_sharedUi.parseValue)(e.nextValue));const h=u-n;const x=n<u-1?n+1:null;const s=x!==null?o[x]:null;const m=h-1;const w=(0,_react.useMemo)(()=>({index:x??0,label:m>0?`#${m}`:"Initial",timestamp:s?formatTimestamp(s.timestamp):"",relativeTime:s?(0,_sharedUi.formatRelativeTime)(new Date(s.timestamp)):"value",badge:s?(0,_jsxRuntime.jsx)(_reactNative.View,{style:[styles.changeBadgeSmall,{backgroundColor:`${_jotaiStateStore.jotaiStateStore.getAtomColor(s.atomLabel)}20`}],children:(0,_jsxRuntime.jsx)(_reactNative.Text,{style:[styles.changeTextSmall,{color:_jotaiStateStore.jotaiStateStore.getAtomColor(s.atomLabel)}],children:getChangeLabel(s.category)})}):void 0}),[x,s,m]);const V=(0,_react.useMemo)(()=>({index:n,label:`#${h}`,timestamp:formatTimestamp(e.timestamp),relativeTime:(0,_sharedUi.formatRelativeTime)(new Date(e.timestamp)),badge:(0,_jsxRuntime.jsx)(_reactNative.View,{style:[styles.changeBadgeSmall,{backgroundColor:`${g}20`}],children:(0,_jsxRuntime.jsx)(_reactNative.Text,{style:[styles.changeTextSmall,{color:g}],children:f})})}),[n,e.timestamp,g,f,h]);const S=(0,_react.useCallback)(()=>{const y=(0,_sharedUi.parseValue)(e.nextValue);return(0,_jsxRuntime.jsxs)(_reactNative.View,{style:styles.contentCard,testID:`${_testIDs.JOTAI_TEST_ID}-value-card`,children:[(0,_jsxRuntime.jsxs)(_reactNative.View,{style:styles.valueHeader,children:[(0,_jsxRuntime.jsx)(_reactNative.Text,{style:styles.valueLabel,children:"VALUE AFTER CHANGE"}),(0,_jsxRuntime.jsxs)(_reactNative.View,{style:styles.valueHeaderBadges,children:[(0,_jsxRuntime.jsx)(_reactNative.View,{style:[styles.changeBadge,{backgroundColor:`${g}20`}],children:(0,_jsxRuntime.jsx)(_reactNative.Text,{style:[styles.changeText,{color:g}],children:f})}),(0,_jsxRuntime.jsx)(_reactNative.View,{style:styles.typeBadge,children:(0,_jsxRuntime.jsx)(_reactNative.Text,{style:styles.typeText,testID:`${_testIDs.JOTAI_TEST_ID}-value-type`,children:T.toUpperCase()})})]})]}),(0,_jsxRuntime.jsx)(_reactNative.View,{style:infoStyles.dataViewerContainer,children:(0,_jsxRuntime.jsx)(_dataViewer.DataViewer,{title:"",data:y,showTypeFilter:true,rawMode:true,initialExpanded:true})})]})},[e.nextValue,g,f,T]);const C=(0,_react.useCallback)(()=>{const y=(0,_sharedUi.parseValue)(e.prevValue);const b=(0,_sharedUi.parseValue)(e.nextValue);if(a==="split"){return(0,_jsxRuntime.jsx)(_reactNative.ScrollView,{style:{flex:1},showsVerticalScrollIndicator:true,children:(0,_jsxRuntime.jsx)(_dataViewer.SplitDiffViewer,{oldValue:y,newValue:b,theme:_dataViewer.diffThemes.devToolsDefault,options:{hideLineNumbers:false,disableWordDiff:false,showDiffOnly:false,compareMethod:"words",contextLines:3},showThemeName:false})})}return(0,_jsxRuntime.jsx)(_dataViewer.TreeDiffViewer,{oldValue:y,newValue:b})},[e.prevValue,e.nextValue,a]);const j=(0,_react.useCallback)(()=>{r(Math.min(u-1,n+1))},[n,u,r]);const I=(0,_react.useCallback)(()=>{r(Math.max(0,n-1))},[n,r]);const D=e.prevValue===void 0;const p=!t&&u>1;return(0,_jsxRuntime.jsxs)(_reactNative.View,{style:styles.container,children:[(0,_jsxRuntime.jsx)(_sharedUi.DetailViewToggle,{views:VIEW_CONFIGS,activeView:i,onViewChange:c,disabledKeys:D?DIFF_DISABLED:void 0,testIDPrefix:_testIDs.JOTAI_TEST_ID}),(0,_jsxRuntime.jsxs)(_reactNative.View,{style:[styles.contentArea,p&&styles.contentAreaFooterPad],children:[i==="change"&&(0,_jsxRuntime.jsx)(JotaiAtomInfoView,{change:e}),i==="value"&&(0,_jsxRuntime.jsx)(_reactNative.View,{style:styles.stateContainer,children:S()}),i==="diff"&&(0,_jsxRuntime.jsxs)(_reactNative.View,{style:styles.diffContainer,testID:`${_testIDs.JOTAI_TEST_ID}-diff`,children:[(0,_jsxRuntime.jsx)(_sharedUi.DiffModeTabs,{tabs:DIFF_MODE_TABS,activeTab:a,onTabChange:d,testIDPrefix:`${_testIDs.JOTAI_TEST_ID}-diff-tab`}),(0,_jsxRuntime.jsx)(_sharedUi.CompareBar,{leftEvent:w,rightEvent:V}),(0,_jsxRuntime.jsx)(_reactNative.View,{style:styles.diffContent,testID:`${_testIDs.JOTAI_TEST_ID}-diff-content`,children:C()})]})]}),p&&(0,_jsxRuntime.jsx)(_sharedUi.EventStepperFooter,{currentIndex:h-1,totalItems:u,onPrevious:j,onNext:I,itemLabel:"Change",subtitle:(0,_sharedUi.formatRelativeTime)(new Date(e.timestamp)),absolute:true})]})}function JotaiAtomDetailFooter({change:e,changes:o,selectedIndex:n,onIndexChange:r}){const t=o.length;if(t<=1)return null;const l=t-n;return(0,_jsxRuntime.jsx)(_sharedUi.EventStepperFooter,{currentIndex:l-1,totalItems:t,onPrevious:()=>r(Math.min(t-1,n+1)),onNext:()=>r(Math.max(0,n-1)),itemLabel:"Change",subtitle:(0,_sharedUi.formatRelativeTime)(new Date(e.timestamp))})}const styles=_reactNative.StyleSheet.create({container:{flex:1,backgroundColor:"transparent"},contentArea:{flex:1},contentAreaFooterPad:{paddingBottom:96},stateContainer:{flex:1,padding:14},contentCard:{backgroundColor:_sharedUi.night.color.surface,borderRadius:14,padding:14,borderWidth:1,borderColor:_sharedUi.night.color.border},valueHeader:{flexDirection:"row",alignItems:"center",justifyContent:"space-between",marginBottom:8},valueLabel:{fontSize:10,color:_sharedUi.night.color.textSecondary,fontFamily:_sharedUi.monoFont,letterSpacing:.5,fontWeight:"600"},valueHeaderBadges:{flexDirection:"row",alignItems:"center",gap:6},changeBadge:{paddingHorizontal:8,paddingVertical:2,borderRadius:4},changeText:{fontSize:9,fontWeight:"700",fontFamily:_sharedUi.monoFont,letterSpacing:.3},typeBadge:{paddingHorizontal:8,paddingVertical:2,borderRadius:4,backgroundColor:_sharedUi.night.color.surfaceElevated},typeText:{fontSize:9,fontWeight:"600",color:_sharedUi.night.color.textTertiary,fontFamily:_sharedUi.monoFont},valueBox:{backgroundColor:_sharedUi.night.color.bg,borderRadius:6,borderWidth:1,borderColor:_sharedUi.night.color.border,padding:8},valueText:{fontSize:12,color:_sharedUi.night.color.text,fontFamily:_sharedUi.monoFont,lineHeight:18},diffContainer:{flex:1},diffContent:{flex:1,paddingHorizontal:14},changeBadgeSmall:{paddingHorizontal:6,paddingVertical:1,borderRadius:3},changeTextSmall:{fontSize:8,fontWeight:"700",fontFamily:_sharedUi.monoFont}});const infoStyles=_reactNative.StyleSheet.create({container:{flex:1},content:{padding:8,paddingBottom:100,gap:16},card:{backgroundColor:_sharedUi.night.color.surface,borderRadius:6,borderWidth:1,borderColor:_sharedUi.night.color.accentBorderStrong,overflow:"hidden",shadowColor:_sharedUi.night.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:_sharedUi.night.color.accentBorder,backgroundColor:_sharedUi.night.color.accentSoft},sectionHeaderLeft:{flexDirection:"row",alignItems:"center",gap:6},sectionTitle:{fontSize:12,fontWeight:"600",letterSpacing:.5,color:_sharedUi.night.color.accent,fontFamily:_sharedUi.monoFont},cardContent:{padding:14,gap:10},infoRow:{flexDirection:"row",alignItems:"center",justifyContent:"space-between"},infoLabel:{fontSize:11,color:_sharedUi.night.color.textTertiary,fontWeight:"500"},infoValue:{fontSize:11,color:_sharedUi.night.color.text,fontWeight:"500",flex:1,textAlign:"right",marginLeft:12},infoValueMono:{fontFamily:_sharedUi.monoFont},badgeRow:{flexDirection:"row",flexWrap:"wrap",gap:8,marginTop:6},categoryBadge:{paddingHorizontal:8,paddingVertical:3,borderRadius:4},categoryText:{fontSize:9,fontWeight:"700",letterSpacing:.3},changesBadge:{flexDirection:"row",alignItems:"center",gap:4,paddingHorizontal:8,paddingVertical:3,borderRadius:4,backgroundColor:_sharedUi.buoyColors.success+"26"},changesText:{fontSize:9,fontWeight:"600",color:_sharedUi.buoyColors.success},noChangesBadge:{paddingHorizontal:8,paddingVertical:3,borderRadius:4,backgroundColor:_sharedUi.night.color.surfaceElevated},noChangesText:{fontSize:9,fontWeight:"600",color:_sharedUi.night.color.textTertiary},keysContainer:{flexDirection:"row",flexWrap:"wrap",gap:6},keyBadge:{paddingHorizontal:8,paddingVertical:4,borderRadius:4,backgroundColor:_sharedUi.night.color.accentSoft,borderWidth:1,borderColor:_sharedUi.night.color.accentBorder},keyText:{fontSize:11,fontWeight:"600",color:_sharedUi.night.color.accent,fontFamily:_sharedUi.monoFont},countBadge:{paddingHorizontal:8,paddingVertical:3,borderRadius:4,backgroundColor:_sharedUi.night.color.accentFill},countText:{fontSize:9,fontWeight:"700",color:_sharedUi.night.color.accent,fontFamily:_sharedUi.monoFont},actionsRow:{flexDirection:"row",gap:12},actionButton:{paddingHorizontal:14,paddingVertical:8,borderRadius:8,borderWidth:1},actionButtonCopy:{borderColor:_sharedUi.night.color.accentBorder,backgroundColor:_sharedUi.night.color.accentSoft},actionButtonText:{fontSize:10,fontWeight:"700",fontFamily:_sharedUi.monoFont,letterSpacing:.3},dataViewerContainer:{marginTop:-12,marginHorizontal:-12,marginBottom:-12}});