@buoy-gg/route-events 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 (102) hide show
  1. package/README.md +11 -64
  2. package/lib/commonjs/RouteObserver.js +1 -54
  3. package/lib/commonjs/RouteParser.js +1 -314
  4. package/lib/commonjs/RouteTracker.js +1 -112
  5. package/lib/commonjs/RouteTracker.web.js +1 -12
  6. package/lib/commonjs/browserRouteRegistry.js +1 -30
  7. package/lib/commonjs/browserRoutes.js +1 -96
  8. package/lib/commonjs/components/NavigationStack.js +2 -572
  9. package/lib/commonjs/components/ReactNavigationRoutes.js +1 -836
  10. package/lib/commonjs/components/ReactNavigationRoutes.web.js +1 -12
  11. package/lib/commonjs/components/RouteEventDetail.js +1 -97
  12. package/lib/commonjs/components/RouteEventExpandedContent.js +1 -204
  13. package/lib/commonjs/components/RouteEventItemCompact.js +1 -191
  14. package/lib/commonjs/components/RouteEventsModalWithTabs.js +1 -734
  15. package/lib/commonjs/components/RouteEventsTimeline.js +1 -107
  16. package/lib/commonjs/components/RouteFilterViewV2.js +1 -42
  17. package/lib/commonjs/components/RoutesSitemap.js +2 -1035
  18. package/lib/commonjs/expoRouterStore.js +1 -121
  19. package/lib/commonjs/expoRouterStore.web.js +1 -44
  20. package/lib/commonjs/hooks/useRouteEvents.js +1 -57
  21. package/lib/commonjs/index.js +1 -168
  22. package/lib/commonjs/preset.js +1 -69
  23. package/lib/commonjs/stores/navigationStackStore.js +1 -45
  24. package/lib/commonjs/stores/routeEventStore.js +1 -136
  25. package/lib/commonjs/sync/routeEventsSyncAdapter.js +1 -275
  26. package/lib/commonjs/useNavigationStack.js +1 -408
  27. package/lib/commonjs/useNavigationStack.web.js +1 -32
  28. package/lib/commonjs/useRouteObserver.js +1 -73
  29. package/lib/commonjs/useRouteObserverReactNavigation.js +1 -109
  30. package/lib/commonjs/useRouteSitemap.js +1 -255
  31. package/lib/commonjs/utils/routeTemplate.js +1 -79
  32. package/lib/commonjs/utils/safeReactNavigation.js +1 -194
  33. package/lib/commonjs/utils/safeReactNavigation.web.js +1 -36
  34. package/lib/commonjs/utils/testIDs.js +1 -63
  35. package/lib/module/RouteObserver.js +1 -49
  36. package/lib/module/RouteParser.js +1 -309
  37. package/lib/module/RouteTracker.js +1 -109
  38. package/lib/module/RouteTracker.web.js +1 -8
  39. package/lib/module/browserRouteRegistry.js +1 -24
  40. package/lib/module/browserRoutes.js +1 -92
  41. package/lib/module/components/NavigationStack.js +2 -568
  42. package/lib/module/components/ReactNavigationRoutes.js +1 -832
  43. package/lib/module/components/ReactNavigationRoutes.web.js +1 -3
  44. package/lib/module/components/RouteEventDetail.js +1 -93
  45. package/lib/module/components/RouteEventExpandedContent.js +1 -200
  46. package/lib/module/components/RouteEventItemCompact.js +1 -187
  47. package/lib/module/components/RouteEventsModalWithTabs.js +1 -731
  48. package/lib/module/components/RouteEventsTimeline.js +1 -103
  49. package/lib/module/components/RouteFilterViewV2.js +1 -38
  50. package/lib/module/components/RoutesSitemap.js +2 -1033
  51. package/lib/module/expoRouterStore.js +1 -114
  52. package/lib/module/expoRouterStore.web.js +1 -37
  53. package/lib/module/hooks/useRouteEvents.js +1 -54
  54. package/lib/module/index.js +1 -70
  55. package/lib/module/preset.js +1 -66
  56. package/lib/module/stores/navigationStackStore.js +1 -41
  57. package/lib/module/stores/routeEventStore.js +1 -128
  58. package/lib/module/sync/routeEventsSyncAdapter.js +1 -273
  59. package/lib/module/useNavigationStack.js +1 -404
  60. package/lib/module/useNavigationStack.web.js +1 -28
  61. package/lib/module/useRouteObserver.js +1 -70
  62. package/lib/module/useRouteObserverReactNavigation.js +1 -106
  63. package/lib/module/useRouteSitemap.js +1 -250
  64. package/lib/module/utils/routeTemplate.js +1 -73
  65. package/lib/module/utils/safeReactNavigation.js +1 -185
  66. package/lib/module/utils/safeReactNavigation.web.js +1 -27
  67. package/lib/module/utils/testIDs.js +1 -55
  68. package/lib/web/index.mjs +4 -5
  69. package/package.json +6 -11
  70. package/lib/typescript/RouteObserver.d.ts.map +0 -1
  71. package/lib/typescript/RouteParser.d.ts.map +0 -1
  72. package/lib/typescript/RouteTracker.d.ts.map +0 -1
  73. package/lib/typescript/RouteTracker.web.d.ts.map +0 -1
  74. package/lib/typescript/browserRouteRegistry.d.ts.map +0 -1
  75. package/lib/typescript/browserRoutes.d.ts.map +0 -1
  76. package/lib/typescript/components/NavigationStack.d.ts.map +0 -1
  77. package/lib/typescript/components/ReactNavigationRoutes.d.ts.map +0 -1
  78. package/lib/typescript/components/ReactNavigationRoutes.web.d.ts.map +0 -1
  79. package/lib/typescript/components/RouteEventDetail.d.ts.map +0 -1
  80. package/lib/typescript/components/RouteEventExpandedContent.d.ts.map +0 -1
  81. package/lib/typescript/components/RouteEventItemCompact.d.ts.map +0 -1
  82. package/lib/typescript/components/RouteEventsModalWithTabs.d.ts.map +0 -1
  83. package/lib/typescript/components/RouteEventsTimeline.d.ts.map +0 -1
  84. package/lib/typescript/components/RouteFilterViewV2.d.ts.map +0 -1
  85. package/lib/typescript/components/RoutesSitemap.d.ts.map +0 -1
  86. package/lib/typescript/expoRouterStore.d.ts.map +0 -1
  87. package/lib/typescript/expoRouterStore.web.d.ts.map +0 -1
  88. package/lib/typescript/hooks/useRouteEvents.d.ts.map +0 -1
  89. package/lib/typescript/index.d.ts.map +0 -1
  90. package/lib/typescript/preset.d.ts.map +0 -1
  91. package/lib/typescript/stores/navigationStackStore.d.ts.map +0 -1
  92. package/lib/typescript/stores/routeEventStore.d.ts.map +0 -1
  93. package/lib/typescript/sync/routeEventsSyncAdapter.d.ts.map +0 -1
  94. package/lib/typescript/useNavigationStack.d.ts.map +0 -1
  95. package/lib/typescript/useNavigationStack.web.d.ts.map +0 -1
  96. package/lib/typescript/useRouteObserver.d.ts.map +0 -1
  97. package/lib/typescript/useRouteObserverReactNavigation.d.ts.map +0 -1
  98. package/lib/typescript/useRouteSitemap.d.ts.map +0 -1
  99. package/lib/typescript/utils/routeTemplate.d.ts.map +0 -1
  100. package/lib/typescript/utils/safeReactNavigation.d.ts.map +0 -1
  101. package/lib/typescript/utils/safeReactNavigation.web.d.ts.map +0 -1
  102. package/lib/typescript/utils/testIDs.d.ts.map +0 -1
@@ -1,12 +1 @@
1
- "use strict";
2
-
3
- Object.defineProperty(exports, "__esModule", {
4
- value: true
5
- });
6
- Object.defineProperty(exports, "ReactNavigationRoutes", {
7
- enumerable: true,
8
- get: function () {
9
- return _RoutesSitemap.RoutesSitemap;
10
- }
11
- });
12
- var _RoutesSitemap = require("./RoutesSitemap");
1
+ "use strict";Object.defineProperty(exports,"__esModule",{value:true});Object.defineProperty(exports,"ReactNavigationRoutes",{enumerable:true,get:function(){return _RoutesSitemap.RoutesSitemap}});var _RoutesSitemap=require("./RoutesSitemap");
@@ -1,97 +1 @@
1
- "use strict";
2
-
3
- Object.defineProperty(exports, "__esModule", {
4
- value: true
5
- });
6
- exports.RouteEventDetail = RouteEventDetail;
7
- var _reactNative = require("react-native");
8
- var _sharedUi = require("@buoy-gg/shared-ui");
9
- var _RouteEventExpandedContent = require("./RouteEventExpandedContent");
10
- var _routeTemplate = require("../utils/routeTemplate");
11
- var _jsxRuntime = require("react/jsx-runtime");
12
- /**
13
- * RouteEventDetail - Full-screen detail view for a single route event.
14
- *
15
- * Mirrors how the Events tool shows a detail page for every other event
16
- * source: the readable route sections (reusing RouteEventExpandedContent)
17
- * plus a prominent "Go to route" action. The back header and toolbar copy
18
- * button are owned by the surrounding modal.
19
- */
20
-
21
- function RouteEventDetail({
22
- event,
23
- visitNumber = 1,
24
- onNavigate
25
- }) {
26
- const routeTemplate = (0, _routeTemplate.getRouteTemplate)(event.pathname, event.segments);
27
- return /*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNative.View, {
28
- style: styles.container,
29
- children: [/*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.ScrollView, {
30
- testID: "buoy-routes-detail-scroll",
31
- style: styles.scroll,
32
- contentContainerStyle: styles.scrollContent,
33
- showsVerticalScrollIndicator: true,
34
- children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_RouteEventExpandedContent.RouteEventExpandedContent, {
35
- event: event,
36
- visitNumber: visitNumber,
37
- routeTemplate: routeTemplate
38
- })
39
- }), onNavigate && /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.View, {
40
- style: styles.footer,
41
- children: /*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNative.TouchableOpacity, {
42
- style: styles.goButton,
43
- onPress: () => onNavigate((0, _routeTemplate.routeHref)(event.pathname, event.params)),
44
- activeOpacity: 0.8,
45
- testID: "buoy-routes-detail-go",
46
- accessibilityRole: "button",
47
- accessibilityLabel: `Go to route ${event.pathname}`,
48
- children: [/*#__PURE__*/(0, _jsxRuntime.jsx)(_sharedUi.Navigation, {
49
- size: 16,
50
- color: _sharedUi.night.color.onAccent
51
- }), /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.Text, {
52
- style: styles.goButtonText,
53
- children: "Go to route"
54
- })]
55
- })
56
- })]
57
- });
58
- }
59
- const styles = _reactNative.StyleSheet.create({
60
- container: {
61
- flex: 1,
62
- // Transparent so the night sheet's star field shows through.
63
- backgroundColor: "transparent"
64
- },
65
- scroll: {
66
- flex: 1
67
- },
68
- scrollContent: {
69
- padding: 14
70
- },
71
- footer: {
72
- paddingHorizontal: 16,
73
- paddingVertical: 12,
74
- // Transparent so the night sheet's star field shows through.
75
- backgroundColor: "transparent",
76
- borderTopWidth: 1,
77
- borderTopColor: _sharedUi.night.color.border
78
- },
79
- goButton: {
80
- flexDirection: "row",
81
- alignItems: "center",
82
- justifyContent: "center",
83
- gap: 8,
84
- backgroundColor: _sharedUi.night.color.accent,
85
- paddingVertical: 12,
86
- borderRadius: 8
87
- },
88
- goButtonText: {
89
- fontSize: 13,
90
- fontWeight: "600",
91
- // Ink on a filled accent surface — the night accent takes dark ink.
92
- color: _sharedUi.night.color.onAccent,
93
- fontFamily: _sharedUi.monoFont,
94
- textTransform: "uppercase",
95
- letterSpacing: 0.5
96
- }
97
- });
1
+ "use strict";Object.defineProperty(exports,"__esModule",{value:true});exports.RouteEventDetail=RouteEventDetail;var _reactNative=require("react-native");var _sharedUi=require("@buoy-gg/shared-ui");var _RouteEventExpandedContent=require("./RouteEventExpandedContent");var _routeTemplate=require("../utils/routeTemplate");var _jsxRuntime=require("react/jsx-runtime");function RouteEventDetail({event:e,visitNumber:o=1,onNavigate:t}){const r=(0,_routeTemplate.getRouteTemplate)(e.pathname,e.segments);return(0,_jsxRuntime.jsxs)(_reactNative.View,{style:styles.container,children:[(0,_jsxRuntime.jsx)(_reactNative.ScrollView,{testID:"buoy-routes-detail-scroll",style:styles.scroll,contentContainerStyle:styles.scrollContent,showsVerticalScrollIndicator:true,children:(0,_jsxRuntime.jsx)(_RouteEventExpandedContent.RouteEventExpandedContent,{event:e,visitNumber:o,routeTemplate:r})}),t&&(0,_jsxRuntime.jsx)(_reactNative.View,{style:styles.footer,children:(0,_jsxRuntime.jsxs)(_reactNative.TouchableOpacity,{style:styles.goButton,onPress:()=>t((0,_routeTemplate.routeHref)(e.pathname,e.params)),activeOpacity:.8,testID:"buoy-routes-detail-go",accessibilityRole:"button",accessibilityLabel:`Go to route ${e.pathname}`,children:[(0,_jsxRuntime.jsx)(_sharedUi.Navigation,{size:16,color:_sharedUi.night.color.onAccent}),(0,_jsxRuntime.jsx)(_reactNative.Text,{style:styles.goButtonText,children:"Go to route"})]})})]})}const styles=_reactNative.StyleSheet.create({container:{flex:1,backgroundColor:"transparent"},scroll:{flex:1},scrollContent:{padding:14},footer:{paddingHorizontal:16,paddingVertical:12,backgroundColor:"transparent",borderTopWidth:1,borderTopColor:_sharedUi.night.color.border},goButton:{flexDirection:"row",alignItems:"center",justifyContent:"center",gap:8,backgroundColor:_sharedUi.night.color.accent,paddingVertical:12,borderRadius:8},goButtonText:{fontSize:13,fontWeight:"600",color:_sharedUi.night.color.onAccent,fontFamily:_sharedUi.monoFont,textTransform:"uppercase",letterSpacing:.5}});
@@ -1,204 +1 @@
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
- testID: "buoy-routes-detail-template",
45
- children: [/*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.Text, {
46
- style: styles.detailLabel,
47
- children: "Template:"
48
- }), /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.Text, {
49
- style: styles.detailValue,
50
- testID: "buoy-routes-detail-template-value",
51
- children: routeTemplate
52
- }), /*#__PURE__*/(0, _jsxRuntime.jsx)(_sharedUi.InlineCopyButton, {
53
- value: routeTemplate,
54
- buttonStyle: styles.copyButton
55
- })]
56
- }), event.previousPathname && /*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNative.View, {
57
- style: styles.detailRow,
58
- testID: "buoy-routes-detail-from",
59
- children: [/*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.Text, {
60
- style: styles.detailLabel,
61
- children: "From:"
62
- }), /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.Text, {
63
- style: styles.detailValue,
64
- testID: "buoy-routes-detail-from-value",
65
- children: event.previousPathname
66
- }), /*#__PURE__*/(0, _jsxRuntime.jsx)(_sharedUi.InlineCopyButton, {
67
- value: event.previousPathname,
68
- buttonStyle: styles.copyButton
69
- })]
70
- }), /*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNative.View, {
71
- style: styles.detailRow,
72
- testID: "buoy-routes-detail-to",
73
- children: [/*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.Text, {
74
- style: styles.detailLabel,
75
- children: "To:"
76
- }), /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.Text, {
77
- style: styles.detailValue,
78
- testID: "buoy-routes-detail-to-value",
79
- children: event.pathname
80
- }), /*#__PURE__*/(0, _jsxRuntime.jsx)(_sharedUi.InlineCopyButton, {
81
- value: event.pathname,
82
- buttonStyle: styles.copyButton
83
- })]
84
- })]
85
- }), /*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNative.View, {
86
- style: styles.section,
87
- children: [event.timeSincePrevious !== undefined && /*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNative.View, {
88
- style: styles.detailRow,
89
- testID: "buoy-routes-detail-duration",
90
- children: [/*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.Text, {
91
- style: styles.detailLabel,
92
- children: "Duration:"
93
- }), /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.Text, {
94
- style: styles.detailValue,
95
- testID: "buoy-routes-detail-duration-value",
96
- children: formatDuration(event.timeSincePrevious)
97
- })]
98
- }), /*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNative.View, {
99
- style: styles.detailRow,
100
- testID: "buoy-routes-detail-time",
101
- children: [/*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.Text, {
102
- style: styles.detailLabel,
103
- children: "Time:"
104
- }), /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.Text, {
105
- style: styles.detailValue,
106
- testID: "buoy-routes-detail-time-value",
107
- children: new Date(event.timestamp).toLocaleString()
108
- })]
109
- })]
110
- }), /*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNative.View, {
111
- style: styles.section,
112
- children: [event.segments && event.segments.length > 0 && /*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNative.View, {
113
- style: styles.detailRow,
114
- testID: "buoy-routes-detail-segments",
115
- children: [/*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.Text, {
116
- style: styles.detailLabel,
117
- children: "Segments:"
118
- }), /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.Text, {
119
- style: styles.detailValue,
120
- testID: "buoy-routes-detail-segments-value",
121
- children: event.segments.join(' → ')
122
- }), /*#__PURE__*/(0, _jsxRuntime.jsx)(_sharedUi.InlineCopyButton, {
123
- value: JSON.stringify(event.segments),
124
- buttonStyle: styles.copyButton
125
- })]
126
- }), hasParams && /*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNative.View, {
127
- style: styles.dataViewerContainer,
128
- children: [/*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNative.View, {
129
- style: styles.dataViewerHeader,
130
- children: [/*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNative.Text, {
131
- style: styles.dataViewerTitle,
132
- testID: "buoy-routes-detail-params-title",
133
- children: ["Parameters (", Object.keys(event.params).length, ")"]
134
- }), /*#__PURE__*/(0, _jsxRuntime.jsx)(_sharedUi.InlineCopyButton, {
135
- value: JSON.stringify(event.params, null, 2),
136
- buttonStyle: styles.copyButton
137
- })]
138
- }), /*#__PURE__*/(0, _jsxRuntime.jsx)(_dataViewer.DataViewer, {
139
- data: event.params,
140
- title: "",
141
- showTypeFilter: true,
142
- rawMode: true,
143
- initialExpanded: true
144
- })]
145
- }), visitNumber > 1 && /*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNative.View, {
146
- style: styles.detailRow,
147
- testID: "buoy-routes-detail-visited",
148
- children: [/*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.Text, {
149
- style: styles.detailLabel,
150
- children: "Visited:"
151
- }), /*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNative.Text, {
152
- style: styles.detailValue,
153
- testID: "buoy-routes-detail-visited-value",
154
- children: [visitNumber, " time", visitNumber !== 1 ? 's' : '']
155
- })]
156
- })]
157
- })]
158
- });
159
- }
160
- const styles = _reactNative.StyleSheet.create({
161
- container: {
162
- gap: 12
163
- },
164
- section: {
165
- gap: 8
166
- },
167
- detailRow: {
168
- flexDirection: "row",
169
- alignItems: "center",
170
- gap: 8
171
- },
172
- detailLabel: {
173
- fontSize: 10,
174
- color: _sharedUi.night.color.textSecondary,
175
- fontFamily: _sharedUi.monoFont,
176
- fontWeight: "600",
177
- minWidth: 70
178
- },
179
- detailValue: {
180
- fontSize: 11,
181
- color: _sharedUi.night.color.text,
182
- fontFamily: _sharedUi.monoFont,
183
- flex: 1
184
- },
185
- copyButton: {
186
- padding: 4,
187
- borderRadius: 4
188
- },
189
- dataViewerContainer: {
190
- marginTop: 4
191
- },
192
- dataViewerHeader: {
193
- flexDirection: "row",
194
- alignItems: "center",
195
- justifyContent: "space-between",
196
- marginBottom: 8
197
- },
198
- dataViewerTitle: {
199
- fontSize: 11,
200
- color: _sharedUi.night.color.textSecondary,
201
- fontFamily: _sharedUi.monoFont,
202
- fontWeight: "600"
203
- }
204
- });
1
+ "use strict";Object.defineProperty(exports,"__esModule",{value:true});exports.RouteEventExpandedContent=RouteEventExpandedContent;var _reactNative=require("react-native");var _sharedUi=require("@buoy-gg/shared-ui");var _dataViewer=require("@buoy-gg/shared-ui/dataViewer");var _jsxRuntime=require("react/jsx-runtime");function formatDuration(e){if(e<1e3){return`${e}ms`}if(e<6e4){return`${(e/1e3).toFixed(1)}s`}const t=Math.floor(e/6e4);const i=(e%6e4/1e3).toFixed(0);return`${t}m ${i}s`}function RouteEventExpandedContent({event:e,visitNumber:t,routeTemplate:i}){const s=e.params&&Object.keys(e.params).length>0;return(0,_jsxRuntime.jsxs)(_reactNative.View,{style:styles.container,children:[(0,_jsxRuntime.jsxs)(_reactNative.View,{style:styles.section,children:[i&&(0,_jsxRuntime.jsxs)(_reactNative.View,{style:styles.detailRow,testID:"buoy-routes-detail-template",children:[(0,_jsxRuntime.jsx)(_reactNative.Text,{style:styles.detailLabel,children:"Template:"}),(0,_jsxRuntime.jsx)(_reactNative.Text,{style:styles.detailValue,testID:"buoy-routes-detail-template-value",children:i}),(0,_jsxRuntime.jsx)(_sharedUi.InlineCopyButton,{value:i,buttonStyle:styles.copyButton})]}),e.previousPathname&&(0,_jsxRuntime.jsxs)(_reactNative.View,{style:styles.detailRow,testID:"buoy-routes-detail-from",children:[(0,_jsxRuntime.jsx)(_reactNative.Text,{style:styles.detailLabel,children:"From:"}),(0,_jsxRuntime.jsx)(_reactNative.Text,{style:styles.detailValue,testID:"buoy-routes-detail-from-value",children:e.previousPathname}),(0,_jsxRuntime.jsx)(_sharedUi.InlineCopyButton,{value:e.previousPathname,buttonStyle:styles.copyButton})]}),(0,_jsxRuntime.jsxs)(_reactNative.View,{style:styles.detailRow,testID:"buoy-routes-detail-to",children:[(0,_jsxRuntime.jsx)(_reactNative.Text,{style:styles.detailLabel,children:"To:"}),(0,_jsxRuntime.jsx)(_reactNative.Text,{style:styles.detailValue,testID:"buoy-routes-detail-to-value",children:e.pathname}),(0,_jsxRuntime.jsx)(_sharedUi.InlineCopyButton,{value:e.pathname,buttonStyle:styles.copyButton})]})]}),(0,_jsxRuntime.jsxs)(_reactNative.View,{style:styles.section,children:[e.timeSincePrevious!==void 0&&(0,_jsxRuntime.jsxs)(_reactNative.View,{style:styles.detailRow,testID:"buoy-routes-detail-duration",children:[(0,_jsxRuntime.jsx)(_reactNative.Text,{style:styles.detailLabel,children:"Duration:"}),(0,_jsxRuntime.jsx)(_reactNative.Text,{style:styles.detailValue,testID:"buoy-routes-detail-duration-value",children:formatDuration(e.timeSincePrevious)})]}),(0,_jsxRuntime.jsxs)(_reactNative.View,{style:styles.detailRow,testID:"buoy-routes-detail-time",children:[(0,_jsxRuntime.jsx)(_reactNative.Text,{style:styles.detailLabel,children:"Time:"}),(0,_jsxRuntime.jsx)(_reactNative.Text,{style:styles.detailValue,testID:"buoy-routes-detail-time-value",children:new Date(e.timestamp).toLocaleString()})]})]}),(0,_jsxRuntime.jsxs)(_reactNative.View,{style:styles.section,children:[e.segments&&e.segments.length>0&&(0,_jsxRuntime.jsxs)(_reactNative.View,{style:styles.detailRow,testID:"buoy-routes-detail-segments",children:[(0,_jsxRuntime.jsx)(_reactNative.Text,{style:styles.detailLabel,children:"Segments:"}),(0,_jsxRuntime.jsx)(_reactNative.Text,{style:styles.detailValue,testID:"buoy-routes-detail-segments-value",children:e.segments.join(" \u2192 ")}),(0,_jsxRuntime.jsx)(_sharedUi.InlineCopyButton,{value:JSON.stringify(e.segments),buttonStyle:styles.copyButton})]}),s&&(0,_jsxRuntime.jsxs)(_reactNative.View,{style:styles.dataViewerContainer,children:[(0,_jsxRuntime.jsxs)(_reactNative.View,{style:styles.dataViewerHeader,children:[(0,_jsxRuntime.jsxs)(_reactNative.Text,{style:styles.dataViewerTitle,testID:"buoy-routes-detail-params-title",children:["Parameters (",Object.keys(e.params).length,")"]}),(0,_jsxRuntime.jsx)(_sharedUi.InlineCopyButton,{value:JSON.stringify(e.params,null,2),buttonStyle:styles.copyButton})]}),(0,_jsxRuntime.jsx)(_dataViewer.DataViewer,{data:e.params,title:"",showTypeFilter:true,rawMode:true,initialExpanded:true})]}),t>1&&(0,_jsxRuntime.jsxs)(_reactNative.View,{style:styles.detailRow,testID:"buoy-routes-detail-visited",children:[(0,_jsxRuntime.jsx)(_reactNative.Text,{style:styles.detailLabel,children:"Visited:"}),(0,_jsxRuntime.jsxs)(_reactNative.Text,{style:styles.detailValue,testID:"buoy-routes-detail-visited-value",children:[t," time",t!==1?"s":""]})]})]})]})}const styles=_reactNative.StyleSheet.create({container:{gap:12},section:{gap:8},detailRow:{flexDirection:"row",alignItems:"center",gap:8},detailLabel:{fontSize:10,color:_sharedUi.night.color.textSecondary,fontFamily:_sharedUi.monoFont,fontWeight:"600",minWidth:70},detailValue:{fontSize:11,color:_sharedUi.night.color.text,fontFamily:_sharedUi.monoFont,flex:1},copyButton:{padding:4,borderRadius:4},dataViewerContainer:{marginTop:4},dataViewerHeader:{flexDirection:"row",alignItems:"center",justifyContent:"space-between",marginBottom:8},dataViewerTitle:{fontSize:11,color:_sharedUi.night.color.textSecondary,fontFamily:_sharedUi.monoFont,fontWeight:"600"}});
@@ -1,191 +1 @@
1
- "use strict";
2
-
3
- Object.defineProperty(exports, "__esModule", {
4
- value: true
5
- });
6
- exports.RouteEventItemCompact = void 0;
7
- var _react = require("react");
8
- var _reactNative = require("react-native");
9
- var _sharedUi = require("@buoy-gg/shared-ui");
10
- var _RouteEventExpandedContent = require("./RouteEventExpandedContent");
11
- var _routeTemplate = require("../utils/routeTemplate");
12
- var _testIDs = require("../utils/testIDs");
13
- var _jsxRuntime = require("react/jsx-runtime");
14
- /**
15
- * RouteEventItemCompact - Compact list item for route events
16
- *
17
- * Uses CompactRow pattern matching network/storage/redux components
18
- */
19
-
20
- // Route type for color coding
21
-
22
- // Get route type for color coding
23
- function getRouteType(event) {
24
- if (event.pathname === "/") {
25
- return "home";
26
- }
27
- if ((0, _routeTemplate.getRouteTemplate)(event.pathname, event.segments)) {
28
- return "dynamic";
29
- }
30
- if (event.params && Object.keys(event.params).length > 0) {
31
- return "with-params";
32
- }
33
- return "default";
34
- }
35
-
36
- // Get color for route type
37
- function getRouteTypeColor(routeType) {
38
- switch (routeType) {
39
- case "home":
40
- return _sharedUi.buoyColors.success;
41
- case "dynamic":
42
- return _sharedUi.night.color.accent;
43
- case "with-params":
44
- return _sharedUi.buoyColors.warning;
45
- default:
46
- return _sharedUi.night.color.textSecondary;
47
- // More visible than border color
48
- }
49
- }
50
-
51
- // Get status label (route type name)
52
- function getStatusLabel(routeType) {
53
- switch (routeType) {
54
- case "home":
55
- return "Home";
56
- case "dynamic":
57
- return "Dynamic";
58
- case "with-params":
59
- return "Params";
60
- default:
61
- return "Static";
62
- }
63
- }
64
-
65
- // Format duration in human-readable format
66
- function formatDuration(ms) {
67
- if (ms < 1000) return `${Math.round(ms)}ms`;
68
- if (ms < 60000) return `${(ms / 1000).toFixed(1)}s`;
69
- const minutes = Math.floor(ms / 60000);
70
- const seconds = Math.floor(ms % 60000 / 1000);
71
- return seconds > 0 ? `${minutes}m ${seconds}s` : `${minutes}m`;
72
- }
73
-
74
- // Get status sublabel (time on previous route + depth info)
75
- function getStatusSublabel(event) {
76
- const parts = [];
77
-
78
- // Show time spent on previous route if available
79
- if (event.timeSincePrevious !== undefined && event.timeSincePrevious > 0) {
80
- parts.push(formatDuration(event.timeSincePrevious));
81
- }
82
-
83
- // Show segment depth (e.g., "depth 2" for /users/profile)
84
- const depth = event.segments?.length || 0;
85
- if (depth > 0) {
86
- parts.push(`depth ${depth}`);
87
- }
88
- return parts.join(" · ") || "root";
89
- }
90
-
91
- // Get badge text - only show when there's additional info beyond the status label
92
- function getBadgeText(event) {
93
- const hasParams = event.params && Object.keys(event.params).length > 0;
94
- if (hasParams) {
95
- const paramCount = Object.keys(event.params).length;
96
- return `${paramCount} PARAM${paramCount !== 1 ? "S" : ""}`;
97
- }
98
-
99
- // Don't show badge text - route type is already shown in status label
100
- return undefined;
101
- }
102
-
103
- // Memo justified by profiling (tool-bench 2026-07-06): 400 row renders
104
- // during a 5s dwell at 500 events (timeline re-renders cascaded into all
105
- // mounted rows via an inline onPress closure).
106
- const RouteEventItemCompact = exports.RouteEventItemCompact = /*#__PURE__*/(0, _react.memo)(function RouteEventItemCompact({
107
- event,
108
- visitNumber,
109
- isExpanded,
110
- onPress,
111
- onNavigate,
112
- index
113
- }) {
114
- const routeType = (0, _react.useMemo)(() => getRouteType(event), [event]);
115
- const routeTemplate = (0, _react.useMemo)(() => (0, _routeTemplate.getRouteTemplate)(event.pathname, event.segments), [event.pathname, event.segments]);
116
- const statusColor = (0, _react.useMemo)(() => getRouteTypeColor(routeType), [routeType]);
117
- const statusLabel = (0, _react.useMemo)(() => getStatusLabel(routeType), [routeType]);
118
- const statusSublabel = (0, _react.useMemo)(() => getStatusSublabel(event), [event]);
119
- const badgeText = (0, _react.useMemo)(() => getBadgeText(event), [event]);
120
- const testID = (0, _react.useMemo)(() => (0, _testIDs.eventRowTestID)(event.pathname, visitNumber), [event.pathname, visitNumber]);
121
- // Spelled out for assistive tech: the row's whole verdict is a coloured dot
122
- // and two short words that Fabric merges into the row's container, so
123
- // VoiceOver would otherwise announce a control it cannot describe.
124
- const accessibilityLabel = (0, _react.useMemo)(() => `${event.pathname}, ${statusLabel}, ${statusSublabel}`, [event.pathname, statusLabel, statusSublabel]);
125
- const expandedContent = (0, _react.useMemo)(() => {
126
- if (!isExpanded) return undefined;
127
- return /*#__PURE__*/(0, _jsxRuntime.jsx)(_RouteEventExpandedContent.RouteEventExpandedContent, {
128
- event: event,
129
- visitNumber: visitNumber,
130
- routeTemplate: routeTemplate
131
- });
132
- }, [isExpanded, event, visitNumber, routeTemplate]);
133
-
134
- // The Go button lives beside the row, not inside its touchable (see
135
- // CompactRow.trailingAction), so a press never opens the row as well.
136
- const goButton = (0, _react.useMemo)(() => {
137
- if (!onNavigate) return undefined;
138
- return /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.TouchableOpacity, {
139
- style: styles.goButton,
140
- onPress: () => onNavigate((0, _routeTemplate.routeHref)(event.pathname, event.params)),
141
- testID: `${testID}-go`,
142
- accessibilityRole: "button",
143
- accessibilityLabel: `Go to ${event.pathname}`,
144
- children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.Text, {
145
- style: styles.goButtonText,
146
- children: "Go"
147
- })
148
- });
149
- }, [onNavigate, event.pathname, testID]);
150
- return /*#__PURE__*/(0, _jsxRuntime.jsx)(_sharedUi.CompactRow, {
151
- statusDotColor: statusColor,
152
- statusLabel: statusLabel,
153
- statusSublabel: statusSublabel,
154
- primaryText: event.pathname,
155
- badgeText: badgeText,
156
- badgeColor: statusColor,
157
- trailingAction: goButton,
158
- bottomRightText: /*#__PURE__*/(0, _jsxRuntime.jsx)(_sharedUi.RelativeTime, {
159
- timestamp: event.timestamp
160
- }),
161
- showChevron: true,
162
- expandedContent: expandedContent,
163
- isExpanded: isExpanded,
164
- expandedGlowColor: statusColor,
165
- onPress: () => onPress(index),
166
- testID: testID,
167
- statusTestID: `${testID}-status`,
168
- statusSublabelTestID: `${testID}-sublabel`,
169
- accessibilityLabel: accessibilityLabel
170
- });
171
- });
172
- const styles = _reactNative.StyleSheet.create({
173
- badgeText: {
174
- fontSize: 11,
175
- fontWeight: "600",
176
- fontFamily: _sharedUi.monoFont
177
- },
178
- goButton: {
179
- backgroundColor: _sharedUi.night.color.accent,
180
- paddingHorizontal: 8,
181
- paddingVertical: 4,
182
- borderRadius: 4
183
- },
184
- goButtonText: {
185
- fontSize: 10,
186
- fontWeight: "600",
187
- // Ink on a filled accent surface — the night accent takes dark ink.
188
- color: _sharedUi.night.color.onAccent,
189
- fontFamily: _sharedUi.monoFont
190
- }
191
- });
1
+ "use strict";Object.defineProperty(exports,"__esModule",{value:true});exports.RouteEventItemCompact=void 0;var _react=require("react");var _reactNative=require("react-native");var _sharedUi=require("@buoy-gg/shared-ui");var _RouteEventExpandedContent=require("./RouteEventExpandedContent");var _routeTemplate=require("../utils/routeTemplate");var _testIDs=require("../utils/testIDs");var _jsxRuntime=require("react/jsx-runtime");function getRouteType(e){if(e.pathname==="/"){return"home"}if((0,_routeTemplate.getRouteTemplate)(e.pathname,e.segments)){return"dynamic"}if(e.params&&Object.keys(e.params).length>0){return"with-params"}return"default"}function getRouteTypeColor(e){switch(e){case"home":return _sharedUi.buoyColors.success;case"dynamic":return _sharedUi.night.color.accent;case"with-params":return _sharedUi.buoyColors.warning;default:return _sharedUi.night.color.textSecondary}}function getStatusLabel(e){switch(e){case"home":return"Home";case"dynamic":return"Dynamic";case"with-params":return"Params";default:return"Static"}}function formatDuration(e){if(e<1e3)return`${Math.round(e)}ms`;if(e<6e4)return`${(e/1e3).toFixed(1)}s`;const t=Math.floor(e/6e4);const o=Math.floor(e%6e4/1e3);return o>0?`${t}m ${o}s`:`${t}m`}function getStatusSublabel(e){const t=[];if(e.timeSincePrevious!==void 0&&e.timeSincePrevious>0){t.push(formatDuration(e.timeSincePrevious))}const o=e.segments?.length||0;if(o>0){t.push(`depth ${o}`)}return t.join(" \xB7 ")||"root"}function getBadgeText(e){const t=e.params&&Object.keys(e.params).length>0;if(t){const o=Object.keys(e.params).length;return`${o} PARAM${o!==1?"S":""}`}return void 0}const RouteEventItemCompact=exports.RouteEventItemCompact=(0,_react.memo)(function e({event:t,visitNumber:o,isExpanded:s,onPress:l,onNavigate:n,index:p}){const r=(0,_react.useMemo)(()=>getRouteType(t),[t]);const m=(0,_react.useMemo)(()=>(0,_routeTemplate.getRouteTemplate)(t.pathname,t.segments),[t.pathname,t.segments]);const u=(0,_react.useMemo)(()=>getRouteTypeColor(r),[r]);const i=(0,_react.useMemo)(()=>getStatusLabel(r),[r]);const c=(0,_react.useMemo)(()=>getStatusSublabel(t),[t]);const d=(0,_react.useMemo)(()=>getBadgeText(t),[t]);const a=(0,_react.useMemo)(()=>(0,_testIDs.eventRowTestID)(t.pathname,o),[t.pathname,o]);const h=(0,_react.useMemo)(()=>`${t.pathname}, ${i}, ${c}`,[t.pathname,i,c]);const g=(0,_react.useMemo)(()=>{if(!s)return void 0;return(0,_jsxRuntime.jsx)(_RouteEventExpandedContent.RouteEventExpandedContent,{event:t,visitNumber:o,routeTemplate:m})},[s,t,o,m]);const f=(0,_react.useMemo)(()=>{if(!n)return void 0;return(0,_jsxRuntime.jsx)(_reactNative.TouchableOpacity,{style:styles.goButton,onPress:()=>n((0,_routeTemplate.routeHref)(t.pathname,t.params)),testID:`${a}-go`,accessibilityRole:"button",accessibilityLabel:`Go to ${t.pathname}`,children:(0,_jsxRuntime.jsx)(_reactNative.Text,{style:styles.goButtonText,children:"Go"})})},[n,t.pathname,a]);return(0,_jsxRuntime.jsx)(_sharedUi.CompactRow,{statusDotColor:u,statusLabel:i,statusSublabel:c,primaryText:t.pathname,badgeText:d,badgeColor:u,trailingAction:f,bottomRightText:(0,_jsxRuntime.jsx)(_sharedUi.RelativeTime,{timestamp:t.timestamp}),showChevron:true,expandedContent:g,isExpanded:s,expandedGlowColor:u,onPress:()=>l(p),testID:a,statusTestID:`${a}-status`,statusSublabelTestID:`${a}-sublabel`,accessibilityLabel:h})});const styles=_reactNative.StyleSheet.create({badgeText:{fontSize:11,fontWeight:"600",fontFamily:_sharedUi.monoFont},goButton:{backgroundColor:_sharedUi.night.color.accent,paddingHorizontal:8,paddingVertical:4,borderRadius:4},goButtonText:{fontSize:10,fontWeight:"600",color:_sharedUi.night.color.onAccent,fontFamily:_sharedUi.monoFont}});