@buoy-gg/route-events 1.7.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (79) hide show
  1. package/README.md +654 -0
  2. package/lib/commonjs/RouteObserver.js +54 -0
  3. package/lib/commonjs/RouteParser.js +310 -0
  4. package/lib/commonjs/RouteTracker.js +39 -0
  5. package/lib/commonjs/components/NavigationStack.js +584 -0
  6. package/lib/commonjs/components/RouteEventDetailContent.js +492 -0
  7. package/lib/commonjs/components/RouteEventExpandedContent.js +187 -0
  8. package/lib/commonjs/components/RouteEventItemCompact.js +175 -0
  9. package/lib/commonjs/components/RouteEventsModalWithTabs.js +560 -0
  10. package/lib/commonjs/components/RouteEventsTimeline.js +82 -0
  11. package/lib/commonjs/components/RouteFilterViewV2.js +42 -0
  12. package/lib/commonjs/components/RoutesSitemap.js +948 -0
  13. package/lib/commonjs/expoRouterStore.js +104 -0
  14. package/lib/commonjs/index.js +99 -0
  15. package/lib/commonjs/package.json +1 -0
  16. package/lib/commonjs/preset.js +83 -0
  17. package/lib/commonjs/useNavigationStack.js +241 -0
  18. package/lib/commonjs/useRouteObserver.js +73 -0
  19. package/lib/commonjs/useRouteSitemap.js +234 -0
  20. package/lib/commonjs/utils/safeExpoRouter.js +129 -0
  21. package/lib/commonjs/utils/safeReactNavigation.js +104 -0
  22. package/lib/module/RouteObserver.js +49 -0
  23. package/lib/module/RouteParser.js +305 -0
  24. package/lib/module/RouteTracker.js +35 -0
  25. package/lib/module/components/NavigationStack.js +580 -0
  26. package/lib/module/components/RouteEventDetailContent.js +487 -0
  27. package/lib/module/components/RouteEventExpandedContent.js +183 -0
  28. package/lib/module/components/RouteEventItemCompact.js +171 -0
  29. package/lib/module/components/RouteEventsModalWithTabs.js +557 -0
  30. package/lib/module/components/RouteEventsTimeline.js +78 -0
  31. package/lib/module/components/RouteFilterViewV2.js +38 -0
  32. package/lib/module/components/RoutesSitemap.js +944 -0
  33. package/lib/module/expoRouterStore.js +98 -0
  34. package/lib/module/index.js +23 -0
  35. package/lib/module/preset.js +79 -0
  36. package/lib/module/useNavigationStack.js +238 -0
  37. package/lib/module/useRouteObserver.js +70 -0
  38. package/lib/module/useRouteSitemap.js +229 -0
  39. package/lib/module/utils/safeExpoRouter.js +120 -0
  40. package/lib/module/utils/safeReactNavigation.js +98 -0
  41. package/lib/typescript/RouteObserver.d.ts +37 -0
  42. package/lib/typescript/RouteObserver.d.ts.map +1 -0
  43. package/lib/typescript/RouteParser.d.ts +129 -0
  44. package/lib/typescript/RouteParser.d.ts.map +1 -0
  45. package/lib/typescript/RouteTracker.d.ts +29 -0
  46. package/lib/typescript/RouteTracker.d.ts.map +1 -0
  47. package/lib/typescript/components/NavigationStack.d.ts +11 -0
  48. package/lib/typescript/components/NavigationStack.d.ts.map +1 -0
  49. package/lib/typescript/components/RouteEventDetailContent.d.ts +21 -0
  50. package/lib/typescript/components/RouteEventDetailContent.d.ts.map +1 -0
  51. package/lib/typescript/components/RouteEventExpandedContent.d.ts +16 -0
  52. package/lib/typescript/components/RouteEventExpandedContent.d.ts.map +1 -0
  53. package/lib/typescript/components/RouteEventItemCompact.d.ts +15 -0
  54. package/lib/typescript/components/RouteEventItemCompact.d.ts.map +1 -0
  55. package/lib/typescript/components/RouteEventsModalWithTabs.d.ts +15 -0
  56. package/lib/typescript/components/RouteEventsModalWithTabs.d.ts.map +1 -0
  57. package/lib/typescript/components/RouteEventsTimeline.d.ts +17 -0
  58. package/lib/typescript/components/RouteEventsTimeline.d.ts.map +1 -0
  59. package/lib/typescript/components/RouteFilterViewV2.d.ts +9 -0
  60. package/lib/typescript/components/RouteFilterViewV2.d.ts.map +1 -0
  61. package/lib/typescript/components/RoutesSitemap.d.ts +15 -0
  62. package/lib/typescript/components/RoutesSitemap.d.ts.map +1 -0
  63. package/lib/typescript/expoRouterStore.d.ts +28 -0
  64. package/lib/typescript/expoRouterStore.d.ts.map +1 -0
  65. package/lib/typescript/index.d.ts +18 -0
  66. package/lib/typescript/index.d.ts.map +1 -0
  67. package/lib/typescript/preset.d.ts +76 -0
  68. package/lib/typescript/preset.d.ts.map +1 -0
  69. package/lib/typescript/useNavigationStack.d.ts +48 -0
  70. package/lib/typescript/useNavigationStack.d.ts.map +1 -0
  71. package/lib/typescript/useRouteObserver.d.ts +27 -0
  72. package/lib/typescript/useRouteObserver.d.ts.map +1 -0
  73. package/lib/typescript/useRouteSitemap.d.ts +102 -0
  74. package/lib/typescript/useRouteSitemap.d.ts.map +1 -0
  75. package/lib/typescript/utils/safeExpoRouter.d.ts +13 -0
  76. package/lib/typescript/utils/safeExpoRouter.d.ts.map +1 -0
  77. package/lib/typescript/utils/safeReactNavigation.d.ts +10 -0
  78. package/lib/typescript/utils/safeReactNavigation.d.ts.map +1 -0
  79. package/package.json +72 -0
@@ -0,0 +1,492 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.RouteEventDetailContent = RouteEventDetailContent;
7
+ exports.RouteEventDetailFooter = RouteEventDetailFooter;
8
+ var _reactNative = require("react-native");
9
+ var _react = require("react");
10
+ var _sharedUi = require("@buoy-gg/shared-ui");
11
+ var _dataViewer = require("@buoy-gg/shared-ui/dataViewer");
12
+ var _jsxRuntime = require("react/jsx-runtime");
13
+ function RouteEventDetailContent({
14
+ conversation,
15
+ selectedEventIndex = 0,
16
+ onEventIndexChange = () => {},
17
+ disableInternalFooter = false
18
+ }) {
19
+ // Internal view state
20
+ const [internalActiveView, setInternalActiveView] = (0, _react.useState)("current");
21
+
22
+ // Track if preferences have been loaded
23
+ const hasLoadedPreferences = (0, _react.useRef)(false);
24
+
25
+ // Load saved preferences on mount
26
+ (0, _react.useEffect)(() => {
27
+ if (hasLoadedPreferences.current) return;
28
+ const loadPreferences = async () => {
29
+ try {
30
+ // Load detail view preference (current/diff)
31
+ const savedDetailView = await (0, _sharedUi.safeGetItem)(_sharedUi.devToolsStorageKeys.routeEvents.detailView());
32
+ if (savedDetailView === "current" || savedDetailView === "diff") {
33
+ setInternalActiveView(savedDetailView);
34
+ }
35
+ hasLoadedPreferences.current = true;
36
+ } catch (error) {
37
+ // Failed to load view preferences
38
+ }
39
+ };
40
+ loadPreferences();
41
+ }, []);
42
+
43
+ // Save detail view preference when changed
44
+ const handleViewChange = (0, _react.useCallback)(async view => {
45
+ setInternalActiveView(view);
46
+ try {
47
+ await (0, _sharedUi.safeSetItem)(_sharedUi.devToolsStorageKeys.routeEvents.detailView(), view);
48
+ } catch (error) {
49
+ // Failed to save detail view preference
50
+ }
51
+ }, []);
52
+ const renderRouteContent = (event, label) => {
53
+ return /*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNative.View, {
54
+ style: styles.valueContent,
55
+ children: [/*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.View, {
56
+ style: styles.valueHeader,
57
+ children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.Text, {
58
+ style: styles.valueLabel,
59
+ children: label
60
+ })
61
+ }), /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.View, {
62
+ style: styles.valueBox,
63
+ children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_dataViewer.DataViewer, {
64
+ title: "",
65
+ data: {
66
+ pathname: event.pathname,
67
+ segments: event.segments,
68
+ params: event.params,
69
+ timestamp: new Date(event.timestamp).toISOString()
70
+ },
71
+ showTypeFilter: false
72
+ })
73
+ })]
74
+ });
75
+ };
76
+
77
+ // Get all events sorted by time
78
+ const navigationItems = conversation.events.sort((a, b) => a.timestamp - b.timestamp);
79
+ const totalEvents = navigationItems.length;
80
+
81
+ // Precise time HH:MM:SS.mmm
82
+ const formatTimeWithMs = (0, _react.useCallback)(timestamp => {
83
+ const date = new Date(timestamp);
84
+ const h = String(date.getHours()).padStart(2, "0");
85
+ const m = String(date.getMinutes()).padStart(2, "0");
86
+ const s = String(date.getSeconds()).padStart(2, "0");
87
+ const ms = String(date.getMilliseconds()).padStart(3, "0");
88
+ return `${h}:${m}:${s}.${ms}`;
89
+ }, []);
90
+
91
+ // Render current value tab
92
+ const renderCurrentValue = () => {
93
+ const selectedEvent = navigationItems[selectedEventIndex];
94
+ const eventToShow = selectedEvent ?? conversation.lastEvent;
95
+ return /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.View, {
96
+ style: styles.fullPageSection,
97
+ children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.View, {
98
+ style: styles.contentCard,
99
+ children: renderRouteContent(eventToShow, "CURRENT ROUTE STATE")
100
+ })
101
+ });
102
+ };
103
+
104
+ // Render diff tab
105
+ const renderDiff = () => {
106
+ if (navigationItems.length === 0) {
107
+ return /*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNative.View, {
108
+ style: styles.emptyState,
109
+ children: [/*#__PURE__*/(0, _jsxRuntime.jsx)(_sharedUi.AlertCircle, {
110
+ size: 32,
111
+ color: _sharedUi.buoyColors.textMuted
112
+ }), /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.Text, {
113
+ style: styles.emptyText,
114
+ children: "No changes to display"
115
+ })]
116
+ });
117
+ }
118
+ const prevIndex = Math.max(0, selectedEventIndex - 1);
119
+ const currentIndex = selectedEventIndex;
120
+ const previousEvent = navigationItems[prevIndex];
121
+ const currentEvent = navigationItems[currentIndex];
122
+ return /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.ScrollView, {
123
+ style: styles.fullPageSection,
124
+ children: /*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNative.View, {
125
+ style: styles.diffContainer,
126
+ children: [/*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNative.View, {
127
+ style: styles.diffSection,
128
+ children: [/*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.Text, {
129
+ style: styles.diffSectionTitle,
130
+ children: "PREVIOUS"
131
+ }), /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.View, {
132
+ style: styles.contentCard,
133
+ children: renderRouteContent(previousEvent, `Event #${prevIndex + 1}`)
134
+ })]
135
+ }), /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.View, {
136
+ style: styles.diffDivider
137
+ }), /*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNative.View, {
138
+ style: styles.diffSection,
139
+ children: [/*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.Text, {
140
+ style: styles.diffSectionTitle,
141
+ children: "CURRENT"
142
+ }), /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.View, {
143
+ style: styles.contentCard,
144
+ children: renderRouteContent(currentEvent, `Event #${currentIndex + 1}`)
145
+ })]
146
+ })]
147
+ })
148
+ });
149
+ };
150
+ return /*#__PURE__*/(0, _jsxRuntime.jsxs)(_jsxRuntime.Fragment, {
151
+ children: [/*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNative.View, {
152
+ style: [styles.contentOnly, {
153
+ flex: 1,
154
+ paddingBottom: !disableInternalFooter && totalEvents > 1 ? 80 : 0
155
+ }],
156
+ children: [/*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNative.View, {
157
+ style: styles.viewToggleContainer,
158
+ children: [/*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNative.TouchableOpacity, {
159
+ style: [styles.viewToggleCard, internalActiveView === "current" && styles.viewToggleCardActive],
160
+ onPress: () => handleViewChange("current"),
161
+ activeOpacity: 0.8,
162
+ children: [/*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNative.View, {
163
+ style: styles.viewToggleContent,
164
+ children: [/*#__PURE__*/(0, _jsxRuntime.jsx)(_sharedUi.Navigation, {
165
+ size: 16,
166
+ color: internalActiveView === "current" ? _sharedUi.buoyColors.primary : _sharedUi.buoyColors.textSecondary
167
+ }), /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.Text, {
168
+ style: [styles.viewToggleLabel, internalActiveView === "current" && styles.viewToggleLabelActive],
169
+ children: "CURRENT STATE"
170
+ })]
171
+ }), /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.Text, {
172
+ style: [styles.viewToggleDescription, internalActiveView === "current" && {
173
+ color: _sharedUi.buoyColors.text
174
+ }],
175
+ children: "View the current route state"
176
+ })]
177
+ }), /*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNative.TouchableOpacity, {
178
+ style: [styles.viewToggleCard, internalActiveView === "diff" && styles.viewToggleCardActive],
179
+ onPress: () => handleViewChange("diff"),
180
+ activeOpacity: 0.8,
181
+ children: [/*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNative.View, {
182
+ style: styles.viewToggleContent,
183
+ children: [/*#__PURE__*/(0, _jsxRuntime.jsx)(_sharedUi.GitBranch, {
184
+ size: 16,
185
+ color: internalActiveView === "diff" ? _sharedUi.buoyColors.success : _sharedUi.buoyColors.textSecondary
186
+ }), /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.Text, {
187
+ style: [styles.viewToggleLabel, internalActiveView === "diff" && styles.viewToggleLabelActive],
188
+ children: "DIFF VIEW"
189
+ })]
190
+ }), /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.Text, {
191
+ style: [styles.viewToggleDescription, internalActiveView === "diff" && {
192
+ color: _sharedUi.buoyColors.text
193
+ }],
194
+ children: "Compare changes between events"
195
+ })]
196
+ })]
197
+ }), internalActiveView === "current" && renderCurrentValue(), internalActiveView === "diff" && renderDiff()]
198
+ }), totalEvents > 1 && !disableInternalFooter && /*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNative.View, {
199
+ style: styles.stickyFooter,
200
+ children: [/*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNative.TouchableOpacity, {
201
+ onPress: () => onEventIndexChange(Math.max(0, selectedEventIndex - 1)),
202
+ disabled: selectedEventIndex === 0,
203
+ style: [styles.navButton, selectedEventIndex === 0 && styles.navButtonDisabled],
204
+ children: [/*#__PURE__*/(0, _jsxRuntime.jsx)(_sharedUi.ChevronLeft, {
205
+ size: 20,
206
+ color: selectedEventIndex === 0 ? _sharedUi.buoyColors.textMuted : _sharedUi.buoyColors.text
207
+ }), /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.Text, {
208
+ style: [styles.navButtonText, selectedEventIndex === 0 && styles.navButtonTextDisabled],
209
+ children: "Previous"
210
+ })]
211
+ }), /*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNative.View, {
212
+ style: styles.eventCounterContainer,
213
+ children: [/*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNative.Text, {
214
+ style: styles.eventCounter,
215
+ children: ["Event ", selectedEventIndex + 1, " of ", totalEvents]
216
+ }), /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.Text, {
217
+ style: styles.eventTimestamp,
218
+ children: (0, _sharedUi.formatRelativeTime)(new Date(navigationItems[selectedEventIndex]?.timestamp))
219
+ })]
220
+ }), /*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNative.TouchableOpacity, {
221
+ onPress: () => onEventIndexChange(Math.min(totalEvents - 1, selectedEventIndex + 1)),
222
+ disabled: selectedEventIndex === totalEvents - 1,
223
+ style: [styles.navButton, selectedEventIndex === totalEvents - 1 && styles.navButtonDisabled],
224
+ children: [/*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.Text, {
225
+ style: [styles.navButtonText, selectedEventIndex === totalEvents - 1 && styles.navButtonTextDisabled],
226
+ children: "Next"
227
+ }), /*#__PURE__*/(0, _jsxRuntime.jsx)(_sharedUi.ChevronRight, {
228
+ size: 20,
229
+ color: selectedEventIndex === totalEvents - 1 ? _sharedUi.buoyColors.textMuted : _sharedUi.buoyColors.text
230
+ })]
231
+ })]
232
+ })]
233
+ });
234
+ }
235
+
236
+ // External footer component to be rendered by the modal outside the ScrollView
237
+ function RouteEventDetailFooter({
238
+ conversation,
239
+ selectedEventIndex = 0,
240
+ onEventIndexChange = () => {}
241
+ }) {
242
+ const navigationItems = conversation.events.sort((a, b) => a.timestamp - b.timestamp);
243
+ const totalEvents = navigationItems.length;
244
+ if (totalEvents <= 1) return null;
245
+ return /*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNative.View, {
246
+ style: styles.externalFooterBar,
247
+ children: [/*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNative.TouchableOpacity, {
248
+ onPress: () => onEventIndexChange(Math.max(0, selectedEventIndex - 1)),
249
+ disabled: selectedEventIndex === 0,
250
+ style: [styles.navButton, selectedEventIndex === 0 && styles.navButtonDisabled],
251
+ children: [/*#__PURE__*/(0, _jsxRuntime.jsx)(_sharedUi.ChevronLeft, {
252
+ size: 20,
253
+ color: selectedEventIndex === 0 ? _sharedUi.buoyColors.textMuted : _sharedUi.buoyColors.text
254
+ }), /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.Text, {
255
+ style: [styles.navButtonText, selectedEventIndex === 0 && styles.navButtonTextDisabled],
256
+ children: "Previous"
257
+ })]
258
+ }), /*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNative.View, {
259
+ style: styles.eventCounterContainer,
260
+ children: [/*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNative.Text, {
261
+ style: styles.eventCounter,
262
+ children: ["Event ", selectedEventIndex + 1, " of ", totalEvents]
263
+ }), /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.Text, {
264
+ style: styles.eventTimestamp,
265
+ children: (0, _sharedUi.formatRelativeTime)(new Date(navigationItems[selectedEventIndex]?.timestamp))
266
+ })]
267
+ }), /*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNative.TouchableOpacity, {
268
+ onPress: () => onEventIndexChange(Math.min(totalEvents - 1, selectedEventIndex + 1)),
269
+ disabled: selectedEventIndex === totalEvents - 1,
270
+ style: [styles.navButton, selectedEventIndex === totalEvents - 1 && styles.navButtonDisabled],
271
+ children: [/*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.Text, {
272
+ style: [styles.navButtonText, selectedEventIndex === totalEvents - 1 && styles.navButtonTextDisabled],
273
+ children: "Next"
274
+ }), /*#__PURE__*/(0, _jsxRuntime.jsx)(_sharedUi.ChevronRight, {
275
+ size: 20,
276
+ color: selectedEventIndex === totalEvents - 1 ? _sharedUi.buoyColors.textMuted : _sharedUi.buoyColors.text
277
+ })]
278
+ })]
279
+ });
280
+ }
281
+ const styles = _reactNative.StyleSheet.create({
282
+ contentOnly: {
283
+ flex: 1,
284
+ backgroundColor: _sharedUi.buoyColors.base
285
+ },
286
+ stickyFooter: {
287
+ position: "absolute",
288
+ bottom: 0,
289
+ left: 0,
290
+ right: 0,
291
+ flexDirection: "row",
292
+ alignItems: "center",
293
+ justifyContent: "space-between",
294
+ paddingHorizontal: 16,
295
+ paddingVertical: 12,
296
+ backgroundColor: _sharedUi.buoyColors.base,
297
+ borderTopWidth: 1,
298
+ borderTopColor: _sharedUi.buoyColors.border,
299
+ shadowColor: "#000",
300
+ shadowOffset: {
301
+ width: 0,
302
+ height: -2
303
+ },
304
+ shadowOpacity: 0.1,
305
+ shadowRadius: 4,
306
+ elevation: 5
307
+ },
308
+ externalFooterBar: {
309
+ flexDirection: "row",
310
+ alignItems: "center",
311
+ justifyContent: "space-between",
312
+ paddingHorizontal: 16,
313
+ paddingVertical: 12,
314
+ backgroundColor: _sharedUi.buoyColors.base,
315
+ borderTopWidth: 1,
316
+ borderTopColor: _sharedUi.buoyColors.border,
317
+ shadowColor: "#000",
318
+ shadowOffset: {
319
+ width: 0,
320
+ height: -2
321
+ },
322
+ shadowOpacity: 0.1,
323
+ shadowRadius: 4,
324
+ elevation: 5
325
+ },
326
+ fullPageSection: {
327
+ flex: 1,
328
+ paddingHorizontal: 14,
329
+ paddingVertical: 10
330
+ },
331
+ emptyState: {
332
+ flex: 1,
333
+ alignItems: "center",
334
+ justifyContent: "center",
335
+ paddingVertical: 48
336
+ },
337
+ emptyText: {
338
+ marginTop: 12,
339
+ fontSize: 14,
340
+ color: _sharedUi.buoyColors.textSecondary,
341
+ fontFamily: "monospace"
342
+ },
343
+ valueContent: {
344
+ marginTop: 4
345
+ },
346
+ valueHeader: {
347
+ flexDirection: "row",
348
+ alignItems: "center",
349
+ justifyContent: "space-between",
350
+ marginBottom: 4
351
+ },
352
+ valueLabel: {
353
+ fontSize: 10,
354
+ color: _sharedUi.buoyColors.textSecondary,
355
+ fontFamily: "monospace",
356
+ letterSpacing: 0.5,
357
+ fontWeight: "600",
358
+ textTransform: "uppercase"
359
+ },
360
+ valueBox: {
361
+ backgroundColor: _sharedUi.buoyColors.card,
362
+ borderRadius: 6,
363
+ borderWidth: 1,
364
+ borderColor: _sharedUi.buoyColors.border,
365
+ padding: 8
366
+ },
367
+ navButton: {
368
+ flexDirection: "row",
369
+ alignItems: "center",
370
+ gap: 6,
371
+ paddingHorizontal: 12,
372
+ paddingVertical: 8,
373
+ borderRadius: 6,
374
+ backgroundColor: _sharedUi.buoyColors.card,
375
+ minWidth: 100,
376
+ justifyContent: "center"
377
+ },
378
+ navButtonDisabled: {
379
+ opacity: 0.3
380
+ },
381
+ navButtonText: {
382
+ fontSize: 12,
383
+ fontWeight: "600",
384
+ color: _sharedUi.buoyColors.text,
385
+ fontFamily: "monospace",
386
+ textTransform: "uppercase"
387
+ },
388
+ navButtonTextDisabled: {
389
+ color: _sharedUi.buoyColors.textMuted
390
+ },
391
+ eventCounterContainer: {
392
+ alignItems: "center"
393
+ },
394
+ eventCounter: {
395
+ fontSize: 14,
396
+ fontWeight: "700",
397
+ color: _sharedUi.buoyColors.text,
398
+ fontFamily: "monospace",
399
+ textTransform: "uppercase"
400
+ },
401
+ eventTimestamp: {
402
+ fontSize: 11,
403
+ color: _sharedUi.buoyColors.textSecondary,
404
+ fontFamily: "monospace",
405
+ marginTop: 2
406
+ },
407
+ contentCard: {
408
+ backgroundColor: _sharedUi.buoyColors.card,
409
+ borderRadius: 14,
410
+ padding: 14,
411
+ borderWidth: 1,
412
+ borderColor: _sharedUi.buoyColors.border,
413
+ shadowColor: "#000",
414
+ shadowOffset: {
415
+ width: 0,
416
+ height: 2
417
+ },
418
+ shadowOpacity: 0.04,
419
+ shadowRadius: 16,
420
+ elevation: 2
421
+ },
422
+ // View Toggle Cards
423
+ viewToggleContainer: {
424
+ flexDirection: "row",
425
+ gap: 12,
426
+ padding: 14,
427
+ backgroundColor: _sharedUi.buoyColors.base
428
+ },
429
+ viewToggleCard: {
430
+ flex: 1,
431
+ backgroundColor: _sharedUi.buoyColors.card,
432
+ borderRadius: 14,
433
+ borderWidth: 1,
434
+ borderColor: _sharedUi.buoyColors.border,
435
+ padding: 14,
436
+ gap: 8
437
+ },
438
+ viewToggleCardActive: {
439
+ borderWidth: 1.5,
440
+ borderColor: _sharedUi.buoyColors.primary,
441
+ backgroundColor: _sharedUi.buoyColors.primary + "15",
442
+ shadowColor: _sharedUi.buoyColors.primary,
443
+ shadowOffset: {
444
+ width: 0,
445
+ height: 2
446
+ },
447
+ shadowOpacity: 0.1,
448
+ shadowRadius: 8,
449
+ elevation: 3
450
+ },
451
+ viewToggleContent: {
452
+ flexDirection: "row",
453
+ alignItems: "center",
454
+ gap: 8
455
+ },
456
+ viewToggleLabel: {
457
+ fontSize: 12,
458
+ fontWeight: "700",
459
+ letterSpacing: 0.5,
460
+ color: _sharedUi.buoyColors.textSecondary,
461
+ textTransform: "uppercase"
462
+ },
463
+ viewToggleLabelActive: {
464
+ color: _sharedUi.buoyColors.text
465
+ },
466
+ viewToggleDescription: {
467
+ fontSize: 11,
468
+ color: _sharedUi.buoyColors.textMuted,
469
+ lineHeight: 16
470
+ },
471
+ // Diff view styles
472
+ diffContainer: {
473
+ gap: 16
474
+ },
475
+ diffSection: {
476
+ gap: 8
477
+ },
478
+ diffSectionTitle: {
479
+ fontSize: 10,
480
+ fontWeight: "700",
481
+ color: _sharedUi.buoyColors.textSecondary,
482
+ fontFamily: "monospace",
483
+ letterSpacing: 0.5,
484
+ textTransform: "uppercase",
485
+ paddingHorizontal: 4
486
+ },
487
+ diffDivider: {
488
+ height: 1,
489
+ backgroundColor: _sharedUi.buoyColors.border,
490
+ marginVertical: 8
491
+ }
492
+ });
@@ -0,0 +1,187 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.RouteEventExpandedContent = RouteEventExpandedContent;
7
+ var _reactNative = require("react-native");
8
+ var _sharedUi = require("@buoy-gg/shared-ui");
9
+ var _dataViewer = require("@buoy-gg/shared-ui/dataViewer");
10
+ var _jsxRuntime = require("react/jsx-runtime");
11
+ /**
12
+ * RouteEventExpandedContent - Expanded view for route event details
13
+ *
14
+ * Shows 3 organized sections:
15
+ * - Section A: Route Information (Template, From, To)
16
+ * - Section B: Timing Information (Duration, Time)
17
+ * - Section C: Parameters & Metadata (Segments, Parameters, Visit count)
18
+ */
19
+
20
+ // Format duration in milliseconds to human-readable string
21
+ function formatDuration(ms) {
22
+ if (ms < 1000) {
23
+ return `${ms}ms`;
24
+ }
25
+ if (ms < 60000) {
26
+ return `${(ms / 1000).toFixed(1)}s`;
27
+ }
28
+ const minutes = Math.floor(ms / 60000);
29
+ const seconds = (ms % 60000 / 1000).toFixed(0);
30
+ return `${minutes}m ${seconds}s`;
31
+ }
32
+ function RouteEventExpandedContent({
33
+ event,
34
+ visitNumber,
35
+ routeTemplate
36
+ }) {
37
+ const hasParams = event.params && Object.keys(event.params).length > 0;
38
+ return /*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNative.View, {
39
+ style: styles.container,
40
+ children: [/*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNative.View, {
41
+ style: styles.section,
42
+ children: [routeTemplate && /*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNative.View, {
43
+ style: styles.detailRow,
44
+ children: [/*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.Text, {
45
+ style: styles.detailLabel,
46
+ children: "Template:"
47
+ }), /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.Text, {
48
+ style: styles.detailValue,
49
+ children: routeTemplate
50
+ }), /*#__PURE__*/(0, _jsxRuntime.jsx)(_sharedUi.InlineCopyButton, {
51
+ value: routeTemplate,
52
+ buttonStyle: styles.copyButton
53
+ })]
54
+ }), event.previousPathname && /*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNative.View, {
55
+ style: styles.detailRow,
56
+ children: [/*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.Text, {
57
+ style: styles.detailLabel,
58
+ children: "From:"
59
+ }), /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.Text, {
60
+ style: styles.detailValue,
61
+ children: event.previousPathname
62
+ }), /*#__PURE__*/(0, _jsxRuntime.jsx)(_sharedUi.InlineCopyButton, {
63
+ value: event.previousPathname,
64
+ buttonStyle: styles.copyButton
65
+ })]
66
+ }), /*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNative.View, {
67
+ style: styles.detailRow,
68
+ children: [/*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.Text, {
69
+ style: styles.detailLabel,
70
+ children: "To:"
71
+ }), /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.Text, {
72
+ style: styles.detailValue,
73
+ children: event.pathname
74
+ }), /*#__PURE__*/(0, _jsxRuntime.jsx)(_sharedUi.InlineCopyButton, {
75
+ value: event.pathname,
76
+ buttonStyle: styles.copyButton
77
+ })]
78
+ })]
79
+ }), /*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNative.View, {
80
+ style: styles.section,
81
+ children: [event.timeSincePrevious !== undefined && /*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNative.View, {
82
+ style: styles.detailRow,
83
+ children: [/*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.Text, {
84
+ style: styles.detailLabel,
85
+ children: "Duration:"
86
+ }), /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.Text, {
87
+ style: styles.detailValue,
88
+ children: formatDuration(event.timeSincePrevious)
89
+ })]
90
+ }), /*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNative.View, {
91
+ style: styles.detailRow,
92
+ children: [/*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.Text, {
93
+ style: styles.detailLabel,
94
+ children: "Time:"
95
+ }), /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.Text, {
96
+ style: styles.detailValue,
97
+ children: new Date(event.timestamp).toLocaleString()
98
+ })]
99
+ })]
100
+ }), /*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNative.View, {
101
+ style: styles.section,
102
+ children: [event.segments && event.segments.length > 0 && /*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNative.View, {
103
+ style: styles.detailRow,
104
+ children: [/*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.Text, {
105
+ style: styles.detailLabel,
106
+ children: "Segments:"
107
+ }), /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.Text, {
108
+ style: styles.detailValue,
109
+ children: event.segments.join(' → ')
110
+ }), /*#__PURE__*/(0, _jsxRuntime.jsx)(_sharedUi.InlineCopyButton, {
111
+ value: JSON.stringify(event.segments),
112
+ buttonStyle: styles.copyButton
113
+ })]
114
+ }), hasParams && /*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNative.View, {
115
+ style: styles.dataViewerContainer,
116
+ children: [/*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNative.View, {
117
+ style: styles.dataViewerHeader,
118
+ children: [/*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNative.Text, {
119
+ style: styles.dataViewerTitle,
120
+ children: ["Parameters (", Object.keys(event.params).length, ")"]
121
+ }), /*#__PURE__*/(0, _jsxRuntime.jsx)(_sharedUi.InlineCopyButton, {
122
+ value: JSON.stringify(event.params, null, 2),
123
+ buttonStyle: styles.copyButton
124
+ })]
125
+ }), /*#__PURE__*/(0, _jsxRuntime.jsx)(_dataViewer.DataViewer, {
126
+ data: event.params,
127
+ title: "",
128
+ showTypeFilter: false
129
+ })]
130
+ }), visitNumber > 1 && /*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNative.View, {
131
+ style: styles.detailRow,
132
+ children: [/*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.Text, {
133
+ style: styles.detailLabel,
134
+ children: "Visited:"
135
+ }), /*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNative.Text, {
136
+ style: styles.detailValue,
137
+ children: [visitNumber, " time", visitNumber !== 1 ? 's' : '']
138
+ })]
139
+ })]
140
+ })]
141
+ });
142
+ }
143
+ const styles = _reactNative.StyleSheet.create({
144
+ container: {
145
+ gap: 12
146
+ },
147
+ section: {
148
+ gap: 8
149
+ },
150
+ detailRow: {
151
+ flexDirection: "row",
152
+ alignItems: "center",
153
+ gap: 8
154
+ },
155
+ detailLabel: {
156
+ fontSize: 10,
157
+ color: _sharedUi.buoyColors.textSecondary,
158
+ fontFamily: "monospace",
159
+ fontWeight: "600",
160
+ minWidth: 70
161
+ },
162
+ detailValue: {
163
+ fontSize: 11,
164
+ color: _sharedUi.buoyColors.text,
165
+ fontFamily: "monospace",
166
+ flex: 1
167
+ },
168
+ copyButton: {
169
+ padding: 4,
170
+ borderRadius: 4
171
+ },
172
+ dataViewerContainer: {
173
+ marginTop: 4
174
+ },
175
+ dataViewerHeader: {
176
+ flexDirection: "row",
177
+ alignItems: "center",
178
+ justifyContent: "space-between",
179
+ marginBottom: 8
180
+ },
181
+ dataViewerTitle: {
182
+ fontSize: 11,
183
+ color: _sharedUi.buoyColors.textSecondary,
184
+ fontFamily: "monospace",
185
+ fontWeight: "600"
186
+ }
187
+ });