@buoy-gg/jotai 2.1.12 → 2.1.13

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