@buoy-gg/route-events 5.0.0 → 6.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +31 -627
- package/lib/commonjs/components/RouteEventItemCompact.js +13 -7
- package/lib/commonjs/components/RouteEventsTimeline.js +34 -10
- package/lib/commonjs/hooks/useRouteEvents.js +15 -6
- package/lib/module/components/RouteEventItemCompact.js +14 -8
- package/lib/module/components/RouteEventsTimeline.js +35 -11
- package/lib/module/hooks/useRouteEvents.js +15 -6
- package/lib/typescript/components/RouteEventItemCompact.d.ts +5 -2
- package/lib/typescript/components/RouteEventItemCompact.d.ts.map +1 -1
- package/lib/typescript/components/RouteEventsTimeline.d.ts.map +1 -1
- package/lib/typescript/hooks/useRouteEvents.d.ts.map +1 -1
- package/package.json +6 -6
package/README.md
CHANGED
|
@@ -1,654 +1,58 @@
|
|
|
1
|
-
# @buoy/route-events
|
|
1
|
+
# @buoy-gg/route-events
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
[](https://www.npmjs.com/package/@buoy-gg/route-events) [](https://www.npmjs.com/package/@buoy-gg/route-events)
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
**See every route in your app, watch navigation happen in real time, and jump to any screen from a full sitemap.**
|
|
6
6
|
|
|
7
|
-
-
|
|
8
|
-
- **Route Sitemap**: Browse all available routes in your app with search and navigation
|
|
9
|
-
- **Navigation Stack Viewer**: Inspect the current navigation stack in real-time
|
|
10
|
-
- **Event Timeline**: View a chronological timeline of all route changes
|
|
11
|
-
- **Filtering & Search**: Filter events by pathname patterns and search through routes
|
|
12
|
-
- **Persistent State**: Remembers your monitoring preferences and filters
|
|
13
|
-
- **Full Modal UI**: Beautiful, production-ready modal interface for all features
|
|
7
|
+
Part of [Buoy](https://github.com/Buoy-gg/buoy) — devtools that live inside your React Native app. Install it and it auto-appears in the floating menu from [`@buoy-gg/core`](https://www.npmjs.com/package/@buoy-gg/core).
|
|
14
8
|
|
|
15
|
-
|
|
9
|
+

|
|
16
10
|
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
For external projects:
|
|
11
|
+
## Install
|
|
20
12
|
|
|
21
13
|
```bash
|
|
22
|
-
npm install @buoy/route-events
|
|
23
|
-
# or
|
|
24
|
-
pnpm add @buoy/route-events
|
|
25
|
-
# or
|
|
26
|
-
yarn add @buoy/route-events
|
|
27
|
-
```
|
|
28
|
-
|
|
29
|
-
## Quick Start
|
|
30
|
-
|
|
31
|
-
### Simplest Setup - Just 1 Line!
|
|
32
|
-
|
|
33
|
-
**Import the preset and add it to your tools array. Done!**
|
|
34
|
-
|
|
35
|
-
```typescript
|
|
36
|
-
import { routeEventsToolPreset } from '@buoy/route-events';
|
|
37
|
-
import { FloatingDevTools } from '@buoy/core';
|
|
38
|
-
|
|
39
|
-
const installedApps = [
|
|
40
|
-
routeEventsToolPreset, // That's it! One line.
|
|
41
|
-
// ...your other tools
|
|
42
|
-
];
|
|
43
|
-
|
|
44
|
-
function App() {
|
|
45
|
-
return (
|
|
46
|
-
<FloatingDevTools
|
|
47
|
-
apps={installedApps}
|
|
48
|
-
environment="local"
|
|
49
|
-
userRole="admin"
|
|
50
|
-
/>
|
|
51
|
-
);
|
|
52
|
-
}
|
|
14
|
+
npm install @buoy-gg/core @buoy-gg/route-events
|
|
53
15
|
```
|
|
54
16
|
|
|
55
|
-
|
|
56
|
-
- ✅ Starts tracking routes when opened
|
|
57
|
-
- ✅ Uses the built-in route observer singleton
|
|
58
|
-
- ✅ Provides all three tabs (Routes, Events, Stack)
|
|
59
|
-
- ✅ No configuration, no props, no hooks to call
|
|
60
|
-
|
|
61
|
-
## Requirements
|
|
17
|
+
## Quick start
|
|
62
18
|
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
- `@react-native-async-storage/async-storage` (state persistence)
|
|
68
|
-
- `react` / `react-native`
|
|
69
|
-
|
|
70
|
-
These packages are declared as `peerDependencies`, so your app decides the exact versions. When a dependency is missing or not initialized, the devtool logs a clear `[RouteEvents] ...` console message (in dev builds) and gracefully disables the affected feature instead of crashing. See `packages/route-events/docs/ROUTES_SITEMAP_ACCESS_GUIDE.md` for the full data-flow and troubleshooting guide.
|
|
71
|
-
|
|
72
|
-
### Alternative: Manual Setup
|
|
73
|
-
|
|
74
|
-
If you're not using FloatingDevTools or want more control:
|
|
75
|
-
|
|
76
|
-
```typescript
|
|
77
|
-
import { RouteEventsModalWithTabs } from '@buoy/route-events';
|
|
78
|
-
|
|
79
|
-
function App() {
|
|
80
|
-
const [showRoutes, setShowRoutes] = useState(false);
|
|
19
|
+
```tsx
|
|
20
|
+
// app/_layout.tsx (Expo Router)
|
|
21
|
+
import { Slot } from "expo-router";
|
|
22
|
+
import { FloatingDevTools } from "@buoy-gg/core";
|
|
81
23
|
|
|
24
|
+
export default function RootLayout() {
|
|
82
25
|
return (
|
|
83
26
|
<>
|
|
84
|
-
<
|
|
85
|
-
|
|
86
|
-
</Button>
|
|
87
|
-
|
|
88
|
-
<RouteEventsModalWithTabs
|
|
89
|
-
visible={showRoutes}
|
|
90
|
-
onClose={() => setShowRoutes(false)}
|
|
91
|
-
/>
|
|
27
|
+
<Slot />
|
|
28
|
+
<FloatingDevTools />
|
|
92
29
|
</>
|
|
93
30
|
);
|
|
94
31
|
}
|
|
95
32
|
```
|
|
96
33
|
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
### Core Components
|
|
100
|
-
|
|
101
|
-
#### `RouteEventsModalWithTabs`
|
|
102
|
-
|
|
103
|
-
The main modal interface with three tabs: Routes, Events, and Stack.
|
|
104
|
-
|
|
105
|
-
**Props:**
|
|
106
|
-
|
|
107
|
-
```typescript
|
|
108
|
-
interface RouteEventsModalWithTabsProps {
|
|
109
|
-
/** Whether the modal is visible */
|
|
110
|
-
visible: boolean;
|
|
111
|
-
/** Callback when modal is closed */
|
|
112
|
-
onClose: () => void;
|
|
113
|
-
/** Optional back button handler */
|
|
114
|
-
onBack?: () => void;
|
|
115
|
-
/** Whether to use shared modal dimensions */
|
|
116
|
-
enableSharedModalDimensions?: boolean;
|
|
117
|
-
/**
|
|
118
|
-
* Optional route observer instance.
|
|
119
|
-
* If not provided, uses the default singleton (recommended).
|
|
120
|
-
* Route tracking starts automatically when the modal is opened.
|
|
121
|
-
*/
|
|
122
|
-
routeObserver?: RouteObserver;
|
|
123
|
-
}
|
|
124
|
-
```
|
|
125
|
-
|
|
126
|
-
**Example:**
|
|
127
|
-
|
|
128
|
-
```typescript
|
|
129
|
-
<RouteEventsModalWithTabs
|
|
130
|
-
visible={isVisible}
|
|
131
|
-
onClose={handleClose}
|
|
132
|
-
/>
|
|
133
|
-
```
|
|
134
|
-
|
|
135
|
-
**Advanced Example (with custom observer):**
|
|
136
|
-
|
|
137
|
-
Only needed if you want to use a custom route observer instance:
|
|
138
|
-
|
|
139
|
-
```typescript
|
|
140
|
-
import { RouteEventsModalWithTabs, routeObserver } from '@buoy/route-events';
|
|
141
|
-
|
|
142
|
-
<RouteEventsModalWithTabs
|
|
143
|
-
visible={isVisible}
|
|
144
|
-
onClose={handleClose}
|
|
145
|
-
routeObserver={routeObserver} // Optional - uses default if not provided
|
|
146
|
-
/>
|
|
147
|
-
```
|
|
148
|
-
|
|
149
|
-
#### `RoutesSitemap`
|
|
150
|
-
|
|
151
|
-
Standalone component for browsing all routes in your application.
|
|
152
|
-
|
|
153
|
-
**Props:**
|
|
154
|
-
|
|
155
|
-
```typescript
|
|
156
|
-
interface RoutesSitemapProps {
|
|
157
|
-
style?: StyleProp<ViewStyle>;
|
|
158
|
-
}
|
|
159
|
-
```
|
|
160
|
-
|
|
161
|
-
**Example:**
|
|
162
|
-
|
|
163
|
-
```typescript
|
|
164
|
-
import { RoutesSitemap } from '@buoy/route-events';
|
|
165
|
-
|
|
166
|
-
function RoutesScreen() {
|
|
167
|
-
return <RoutesSitemap />;
|
|
168
|
-
}
|
|
169
|
-
```
|
|
170
|
-
|
|
171
|
-
#### `NavigationStack`
|
|
172
|
-
|
|
173
|
-
Standalone component for visualizing the current navigation stack.
|
|
174
|
-
|
|
175
|
-
**Props:**
|
|
176
|
-
|
|
177
|
-
```typescript
|
|
178
|
-
interface NavigationStackProps {
|
|
179
|
-
style?: StyleProp<ViewStyle>;
|
|
180
|
-
}
|
|
181
|
-
```
|
|
182
|
-
|
|
183
|
-
**Example:**
|
|
184
|
-
|
|
185
|
-
```typescript
|
|
186
|
-
import { NavigationStack } from '@buoy/route-events';
|
|
187
|
-
|
|
188
|
-
function DebugScreen() {
|
|
189
|
-
return <NavigationStack />;
|
|
190
|
-
}
|
|
191
|
-
```
|
|
192
|
-
|
|
193
|
-
### Hooks
|
|
194
|
-
|
|
195
|
-
#### `useRouteObserver`
|
|
196
|
-
|
|
197
|
-
Hook to track route changes and emit events to the global observer.
|
|
198
|
-
|
|
199
|
-
**Note:** You typically don't need to use this hook directly - the `RouteEventsModalWithTabs` component starts tracking automatically. This hook is only needed for advanced use cases like custom analytics.
|
|
200
|
-
|
|
201
|
-
**Signature:**
|
|
202
|
-
|
|
203
|
-
```typescript
|
|
204
|
-
function useRouteObserver(
|
|
205
|
-
callback?: (event: RouteChangeEvent) => void
|
|
206
|
-
): void
|
|
207
|
-
```
|
|
208
|
-
|
|
209
|
-
**Examples:**
|
|
210
|
-
|
|
211
|
-
```typescript
|
|
212
|
-
// Only needed for custom analytics - modal handles tracking automatically!
|
|
213
|
-
import { useRouteObserver } from '@buoy/route-events';
|
|
214
|
-
|
|
215
|
-
export default function RootLayout() {
|
|
216
|
-
useRouteObserver((event) => {
|
|
217
|
-
analytics.trackPageView(event.pathname);
|
|
218
|
-
});
|
|
219
|
-
|
|
220
|
-
return <Stack />;
|
|
221
|
-
}
|
|
222
|
-
```
|
|
223
|
-
|
|
224
|
-
#### `useRouteSitemap`
|
|
225
|
-
|
|
226
|
-
Access route information from your app's file-based routing structure.
|
|
227
|
-
|
|
228
|
-
**Signature:**
|
|
229
|
-
|
|
230
|
-
```typescript
|
|
231
|
-
function useRouteSitemap(
|
|
232
|
-
options?: UseRouteSitemapOptions
|
|
233
|
-
): UseRouteSitemapResult
|
|
234
|
-
```
|
|
235
|
-
|
|
236
|
-
**Options:**
|
|
237
|
-
|
|
238
|
-
```typescript
|
|
239
|
-
interface UseRouteSitemapOptions {
|
|
240
|
-
/** Whether to include layout routes */
|
|
241
|
-
includeLayouts?: boolean;
|
|
242
|
-
/** Whether to include route groups */
|
|
243
|
-
includeGroups?: boolean;
|
|
244
|
-
}
|
|
245
|
-
```
|
|
246
|
-
|
|
247
|
-
**Result:**
|
|
248
|
-
|
|
249
|
-
```typescript
|
|
250
|
-
interface UseRouteSitemapResult {
|
|
251
|
-
/** All routes in the application */
|
|
252
|
-
routes: RouteInfo[];
|
|
253
|
-
/** Routes grouped by directory */
|
|
254
|
-
groups: RouteGroup[];
|
|
255
|
-
/** Statistics about the routes */
|
|
256
|
-
stats: RouteStats;
|
|
257
|
-
/** Get a specific route by path */
|
|
258
|
-
getRoute: (path: string) => RouteInfo | undefined;
|
|
259
|
-
/** Get all parent routes of a path */
|
|
260
|
-
getParents: (path: string) => RouteInfo[];
|
|
261
|
-
}
|
|
262
|
-
```
|
|
263
|
-
|
|
264
|
-
**Example:**
|
|
265
|
-
|
|
266
|
-
```typescript
|
|
267
|
-
import { useRouteSitemap } from '@buoy/route-events';
|
|
268
|
-
|
|
269
|
-
function RouteDebugger() {
|
|
270
|
-
const { routes, stats, getRoute } = useRouteSitemap();
|
|
271
|
-
|
|
272
|
-
console.log(`Total routes: ${stats.total}`);
|
|
273
|
-
console.log(`Dynamic routes: ${stats.byType.dynamic}`);
|
|
274
|
-
|
|
275
|
-
const homeRoute = getRoute('/');
|
|
276
|
-
// { path: '/', type: 'index', ... }
|
|
277
|
-
|
|
278
|
-
return (
|
|
279
|
-
<View>
|
|
280
|
-
{routes.map(route => (
|
|
281
|
-
<Text key={route.path}>{route.path}</Text>
|
|
282
|
-
))}
|
|
283
|
-
</View>
|
|
284
|
-
);
|
|
285
|
-
}
|
|
286
|
-
```
|
|
287
|
-
|
|
288
|
-
#### `useNavigationStack`
|
|
289
|
-
|
|
290
|
-
Access and control the current navigation stack.
|
|
34
|
+
That's it. `FloatingDevTools` detects the package, mounts the route tracker for you, and the ROUTES tool shows up in the menu. It auto-detects whether you're on Expo Router or React Navigation and adapts.
|
|
291
35
|
|
|
292
|
-
|
|
36
|
+
## What you get
|
|
293
37
|
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
38
|
+
- **Full sitemap** — browse every route in your app, searchable, with route types (static, dynamic, layout) labeled
|
|
39
|
+
- **Jump to any screen** — tap a route in the sitemap and navigate straight to it, params and all
|
|
40
|
+
- **Live navigation stack** — watch the stack push, pop, and replace as you move through the app
|
|
41
|
+
- **Navigation event timeline** — every navigation logged with path, params, timestamp, and time since the previous one
|
|
42
|
+
- **Filtering & search** — filter events by pathname pattern, search across routes
|
|
43
|
+
- **Zero setup** — no `<RouteTracker />` to place, no config; the core menu wires it automatically
|
|
44
|
+
- **Hooks for custom UIs** — `useRouteEvents`, `useRouteSitemap`, and `useNavigationStack` if you want the data without the modal
|
|
297
45
|
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
```typescript
|
|
301
|
-
interface UseNavigationStackResult {
|
|
302
|
-
/** The current navigation stack */
|
|
303
|
-
stack: StackDisplayItem[];
|
|
304
|
-
/** Whether the data is loading */
|
|
305
|
-
loading: boolean;
|
|
306
|
-
/** Navigate to a specific stack index */
|
|
307
|
-
navigateToIndex: (index: number) => void;
|
|
308
|
-
/** Pop back to a specific index */
|
|
309
|
-
popToIndex: (index: number) => void;
|
|
310
|
-
/** Go back one screen */
|
|
311
|
-
goBack: () => void;
|
|
312
|
-
/** Go to the root of the stack */
|
|
313
|
-
popToTop: () => void;
|
|
314
|
-
}
|
|
315
|
-
```
|
|
316
|
-
|
|
317
|
-
**Example:**
|
|
318
|
-
|
|
319
|
-
```typescript
|
|
320
|
-
import { useNavigationStack } from '@buoy/route-events';
|
|
321
|
-
|
|
322
|
-
function NavigationDebugger() {
|
|
323
|
-
const { stack, goBack, popToTop } = useNavigationStack();
|
|
324
|
-
|
|
325
|
-
return (
|
|
326
|
-
<View>
|
|
327
|
-
<Text>Stack Depth: {stack.length}</Text>
|
|
328
|
-
<Button onPress={goBack}>Go Back</Button>
|
|
329
|
-
<Button onPress={popToTop}>Go to Root</Button>
|
|
330
|
-
|
|
331
|
-
{stack.map((item, index) => (
|
|
332
|
-
<Text key={item.key}>
|
|
333
|
-
{index}: {item.displayPath}
|
|
334
|
-
</Text>
|
|
335
|
-
))}
|
|
336
|
-
</View>
|
|
337
|
-
);
|
|
338
|
-
}
|
|
339
|
-
```
|
|
340
|
-
|
|
341
|
-
### Utilities
|
|
342
|
-
|
|
343
|
-
#### `RouteObserver`
|
|
344
|
-
|
|
345
|
-
Singleton instance for observing route changes.
|
|
346
|
-
|
|
347
|
-
**Methods:**
|
|
348
|
-
|
|
349
|
-
```typescript
|
|
350
|
-
class RouteObserver {
|
|
351
|
-
/** Emit a route change event */
|
|
352
|
-
emit(event: RouteChangeEvent): void;
|
|
353
|
-
|
|
354
|
-
/** Add a listener for route changes */
|
|
355
|
-
addListener(callback: (event: RouteChangeEvent) => void): () => void;
|
|
356
|
-
|
|
357
|
-
/** Remove a listener */
|
|
358
|
-
removeListener(callback: (event: RouteChangeEvent) => void): void;
|
|
359
|
-
}
|
|
360
|
-
```
|
|
361
|
-
|
|
362
|
-
**Example:**
|
|
363
|
-
|
|
364
|
-
```typescript
|
|
365
|
-
import { routeObserver } from '@buoy/route-events';
|
|
366
|
-
|
|
367
|
-
// Add listener
|
|
368
|
-
const unsubscribe = routeObserver.addListener((event) => {
|
|
369
|
-
console.log('Route changed:', event.pathname);
|
|
370
|
-
});
|
|
371
|
-
|
|
372
|
-
// Later, remove listener
|
|
373
|
-
unsubscribe();
|
|
374
|
-
```
|
|
375
|
-
|
|
376
|
-
#### `RouteParser`
|
|
377
|
-
|
|
378
|
-
Utility for parsing Expo Router's route structure.
|
|
379
|
-
|
|
380
|
-
**Methods:**
|
|
381
|
-
|
|
382
|
-
```typescript
|
|
383
|
-
class RouteParser {
|
|
384
|
-
/** Get all routes from the router */
|
|
385
|
-
static getRoutes(options?: {
|
|
386
|
-
includeLayouts?: boolean;
|
|
387
|
-
includeGroups?: boolean;
|
|
388
|
-
}): RouteInfo[];
|
|
389
|
-
|
|
390
|
-
/** Group routes by directory */
|
|
391
|
-
static groupRoutes(routes: RouteInfo[]): RouteGroup[];
|
|
392
|
-
|
|
393
|
-
/** Get statistics about routes */
|
|
394
|
-
static getStats(routes: RouteInfo[]): RouteStats;
|
|
395
|
-
}
|
|
396
|
-
```
|
|
397
|
-
|
|
398
|
-
### Types
|
|
399
|
-
|
|
400
|
-
#### `RouteChangeEvent`
|
|
401
|
-
|
|
402
|
-
```typescript
|
|
403
|
-
interface RouteChangeEvent {
|
|
404
|
-
/** Current pathname */
|
|
405
|
-
pathname: string;
|
|
406
|
-
/** Route parameters */
|
|
407
|
-
params: Record<string, string | string[]>;
|
|
408
|
-
/** Route segments */
|
|
409
|
-
segments: string[];
|
|
410
|
-
/** Timestamp of the change */
|
|
411
|
-
timestamp: number;
|
|
412
|
-
/** Previous pathname (if available) */
|
|
413
|
-
previousPathname?: string;
|
|
414
|
-
/** Time since previous navigation in ms */
|
|
415
|
-
timeSincePrevious?: number;
|
|
416
|
-
}
|
|
417
|
-
```
|
|
418
|
-
|
|
419
|
-
#### `RouteInfo`
|
|
420
|
-
|
|
421
|
-
```typescript
|
|
422
|
-
interface RouteInfo {
|
|
423
|
-
/** Full path of the route */
|
|
424
|
-
path: string;
|
|
425
|
-
/** Route type */
|
|
426
|
-
type: RouteType;
|
|
427
|
-
/** Route name/file */
|
|
428
|
-
name: string;
|
|
429
|
-
/** Dynamic parameters */
|
|
430
|
-
params: string[];
|
|
431
|
-
/** Whether it's a layout */
|
|
432
|
-
isLayout: boolean;
|
|
433
|
-
/** Whether it's a route group */
|
|
434
|
-
isGroup: boolean;
|
|
435
|
-
/** Parent path */
|
|
436
|
-
parent?: string;
|
|
437
|
-
}
|
|
438
|
-
```
|
|
439
|
-
|
|
440
|
-
#### `RouteType`
|
|
441
|
-
|
|
442
|
-
```typescript
|
|
443
|
-
type RouteType =
|
|
444
|
-
| 'index' // index routes (/)
|
|
445
|
-
| 'static' // static routes (/about)
|
|
446
|
-
| 'dynamic' // dynamic routes (/user/[id])
|
|
447
|
-
| 'catch-all' // catch-all routes (/docs/[...path])
|
|
448
|
-
| 'layout' // layout routes (_layout.tsx)
|
|
449
|
-
| 'group'; // route groups ((tabs))
|
|
450
|
-
```
|
|
451
|
-
|
|
452
|
-
## Use Cases
|
|
453
|
-
|
|
454
|
-
### Analytics Integration
|
|
455
|
-
|
|
456
|
-
```typescript
|
|
457
|
-
import { useRouteObserver } from '@buoy/route-events';
|
|
458
|
-
|
|
459
|
-
export default function RootLayout() {
|
|
460
|
-
useRouteObserver((event) => {
|
|
461
|
-
// Track page views
|
|
462
|
-
analytics.trackPageView({
|
|
463
|
-
path: event.pathname,
|
|
464
|
-
params: event.params,
|
|
465
|
-
previousPath: event.previousPathname,
|
|
466
|
-
timeSpent: event.timeSincePrevious,
|
|
467
|
-
});
|
|
468
|
-
});
|
|
469
|
-
|
|
470
|
-
return <Stack />;
|
|
471
|
-
}
|
|
472
|
-
```
|
|
473
|
-
|
|
474
|
-
### Performance Monitoring
|
|
475
|
-
|
|
476
|
-
```typescript
|
|
477
|
-
import { useRouteObserver } from '@buoy/route-events';
|
|
478
|
-
|
|
479
|
-
export default function RootLayout() {
|
|
480
|
-
useRouteObserver((event) => {
|
|
481
|
-
if (event.timeSincePrevious && event.timeSincePrevious > 1000) {
|
|
482
|
-
// Log slow navigations
|
|
483
|
-
console.warn('Slow navigation:', {
|
|
484
|
-
from: event.previousPathname,
|
|
485
|
-
to: event.pathname,
|
|
486
|
-
duration: event.timeSincePrevious,
|
|
487
|
-
});
|
|
488
|
-
}
|
|
489
|
-
});
|
|
490
|
-
|
|
491
|
-
return <Stack />;
|
|
492
|
-
}
|
|
493
|
-
```
|
|
494
|
-
|
|
495
|
-
### Development Tools
|
|
496
|
-
|
|
497
|
-
```typescript
|
|
498
|
-
import { RouteEventsModalWithTabs, routeObserver } from '@buoy/route-events';
|
|
499
|
-
|
|
500
|
-
function DevTools() {
|
|
501
|
-
const [visible, setVisible] = useState(false);
|
|
502
|
-
|
|
503
|
-
// Only show in development
|
|
504
|
-
if (__DEV__) {
|
|
505
|
-
return (
|
|
506
|
-
<>
|
|
507
|
-
<TouchableOpacity
|
|
508
|
-
style={styles.devButton}
|
|
509
|
-
onPress={() => setVisible(true)}
|
|
510
|
-
>
|
|
511
|
-
<Text>🧭 Routes</Text>
|
|
512
|
-
</TouchableOpacity>
|
|
513
|
-
|
|
514
|
-
<RouteEventsModalWithTabs
|
|
515
|
-
visible={visible}
|
|
516
|
-
onClose={() => setVisible(false)}
|
|
517
|
-
routeObserver={routeObserver}
|
|
518
|
-
/>
|
|
519
|
-
</>
|
|
520
|
-
);
|
|
521
|
-
}
|
|
522
|
-
|
|
523
|
-
return null;
|
|
524
|
-
}
|
|
525
|
-
```
|
|
526
|
-
|
|
527
|
-
### Route Documentation
|
|
528
|
-
|
|
529
|
-
```typescript
|
|
530
|
-
import { useRouteSitemap } from '@buoy/route-events';
|
|
531
|
-
|
|
532
|
-
function RouteDocumentation() {
|
|
533
|
-
const { routes, groups, stats } = useRouteSitemap({
|
|
534
|
-
includeLayouts: false,
|
|
535
|
-
includeGroups: false,
|
|
536
|
-
});
|
|
537
|
-
|
|
538
|
-
return (
|
|
539
|
-
<ScrollView>
|
|
540
|
-
<Text>Total Routes: {stats.total}</Text>
|
|
541
|
-
|
|
542
|
-
{groups.map(group => (
|
|
543
|
-
<View key={group.name}>
|
|
544
|
-
<Text>{group.name} ({group.routes.length})</Text>
|
|
545
|
-
{group.routes.map(route => (
|
|
546
|
-
<Text key={route.path}>
|
|
547
|
-
{route.path} - {route.type}
|
|
548
|
-
</Text>
|
|
549
|
-
))}
|
|
550
|
-
</View>
|
|
551
|
-
))}
|
|
552
|
-
</ScrollView>
|
|
553
|
-
);
|
|
554
|
-
}
|
|
555
|
-
```
|
|
556
|
-
|
|
557
|
-
## Features in Detail
|
|
558
|
-
|
|
559
|
-
### Routes Tab
|
|
560
|
-
|
|
561
|
-
- Browse all routes in your application
|
|
562
|
-
- Search routes by path or name
|
|
563
|
-
- View route types (static, dynamic, catch-all)
|
|
564
|
-
- Navigate to any route directly
|
|
565
|
-
- Handles dynamic route parameters with prompts
|
|
566
|
-
- Group and layout route identification
|
|
567
|
-
|
|
568
|
-
### Events Tab
|
|
569
|
-
|
|
570
|
-
- Real-time route change monitoring
|
|
571
|
-
- Toggle monitoring on/off
|
|
572
|
-
- Event timeline with timestamps
|
|
573
|
-
- Filter events by pathname patterns
|
|
574
|
-
- Search through event history
|
|
575
|
-
- View detailed event information
|
|
576
|
-
- Compare route changes (diff view)
|
|
577
|
-
- Clear event history
|
|
578
|
-
- Persistent filter preferences
|
|
579
|
-
|
|
580
|
-
### Stack Tab
|
|
581
|
-
|
|
582
|
-
- Real-time navigation stack visualization
|
|
583
|
-
- Stack depth indicator
|
|
584
|
-
- Navigate to any stack level
|
|
585
|
-
- Pop to specific stack index
|
|
586
|
-
- Quick navigation controls
|
|
587
|
-
- Route parameter display
|
|
588
|
-
|
|
589
|
-
## Dependencies
|
|
590
|
-
|
|
591
|
-
- `@buoy/shared-ui` - Common UI components and utilities
|
|
592
|
-
- `expo-router` - Expo Router integration (peer dependency)
|
|
593
|
-
- `@react-navigation/native` - React Navigation integration (peer dependency)
|
|
594
|
-
- `@react-native-async-storage/async-storage` - For persistent preferences (peer dependency)
|
|
595
|
-
- React and React Native (peer dependencies)
|
|
596
|
-
|
|
597
|
-
## Development
|
|
598
|
-
|
|
599
|
-
### Building
|
|
600
|
-
|
|
601
|
-
```bash
|
|
602
|
-
pnpm build
|
|
603
|
-
```
|
|
604
|
-
|
|
605
|
-
### Type Checking
|
|
606
|
-
|
|
607
|
-
```bash
|
|
608
|
-
pnpm typecheck
|
|
609
|
-
```
|
|
610
|
-
|
|
611
|
-
### Clean Build
|
|
612
|
-
|
|
613
|
-
```bash
|
|
614
|
-
pnpm clean
|
|
615
|
-
```
|
|
616
|
-
|
|
617
|
-
## Package Structure
|
|
618
|
-
|
|
619
|
-
```
|
|
620
|
-
route-events/
|
|
621
|
-
├── src/
|
|
622
|
-
│ ├── components/ # UI components
|
|
623
|
-
│ │ ├── RouteEventsModalWithTabs.tsx
|
|
624
|
-
│ │ ├── RoutesSitemap.tsx
|
|
625
|
-
│ │ ├── NavigationStack.tsx
|
|
626
|
-
│ │ ├── RouteEventsTimeline.tsx
|
|
627
|
-
│ │ ├── RouteEventItemCompact.tsx
|
|
628
|
-
│ │ ├── RouteEventDetailContent.tsx
|
|
629
|
-
│ │ ├── RouteEventExpandedContent.tsx
|
|
630
|
-
│ │ └── RouteFilterViewV2.tsx
|
|
631
|
-
│ ├── RouteObserver.ts # Event system
|
|
632
|
-
│ ├── RouteParser.ts # Route parsing utilities
|
|
633
|
-
│ ├── useRouteObserver.ts # Route tracking hook
|
|
634
|
-
│ ├── useRouteSitemap.ts # Sitemap access hook
|
|
635
|
-
│ ├── useNavigationStack.ts # Stack access hook
|
|
636
|
-
│ └── index.tsx # Main exports
|
|
637
|
-
├── lib/ # Built output (git ignored)
|
|
638
|
-
├── package.json
|
|
639
|
-
├── tsconfig.json
|
|
640
|
-
├── tsconfig.build.json
|
|
641
|
-
└── README.md
|
|
642
|
-
```
|
|
46
|
+
## Desktop & AI
|
|
643
47
|
|
|
644
|
-
|
|
48
|
+
The same live session streams to [Buoy Desktop](https://github.com/Buoy-gg/Buoy-Desktop) (free, macOS/Windows/Linux) and to Claude Code or Cursor via the [Buoy MCP server](https://buoy.gg/buoy/latest/docs/mcp).
|
|
645
49
|
|
|
646
|
-
|
|
50
|
+
## Free vs Pro
|
|
647
51
|
|
|
648
|
-
|
|
52
|
+
Every tool is free. [Pro](https://buoy.gg/pricing) unlocks production builds, the MCP server, and unlimited capture. Every weekend, Pro features unlock free for everyone.
|
|
649
53
|
|
|
650
|
-
|
|
54
|
+
---
|
|
651
55
|
|
|
652
|
-
|
|
56
|
+
📚 [Full docs](https://buoy.gg/buoy/latest/docs/tools/routes) · [All Buoy tools](https://github.com/Buoy-gg/buoy)
|
|
653
57
|
|
|
654
|
-
|
|
58
|
+
Proprietary software. © Buoy LLC. [Terms](https://buoy.gg/terms)
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
Object.defineProperty(exports, "__esModule", {
|
|
4
4
|
value: true
|
|
5
5
|
});
|
|
6
|
-
exports.RouteEventItemCompact =
|
|
6
|
+
exports.RouteEventItemCompact = void 0;
|
|
7
7
|
var _react = require("react");
|
|
8
8
|
var _reactNative = require("react-native");
|
|
9
9
|
var _sharedUi = require("@buoy-gg/shared-ui");
|
|
@@ -114,12 +114,17 @@ function getBadgeText(event) {
|
|
|
114
114
|
// Don't show badge text - route type is already shown in status label
|
|
115
115
|
return undefined;
|
|
116
116
|
}
|
|
117
|
-
|
|
117
|
+
|
|
118
|
+
// Memo justified by profiling (tool-bench 2026-07-06): 400 row renders
|
|
119
|
+
// during a 5s dwell at 500 events (timeline re-renders cascaded into all
|
|
120
|
+
// mounted rows via an inline onPress closure).
|
|
121
|
+
const RouteEventItemCompact = exports.RouteEventItemCompact = /*#__PURE__*/(0, _react.memo)(function RouteEventItemCompact({
|
|
118
122
|
event,
|
|
119
123
|
visitNumber,
|
|
120
124
|
isExpanded,
|
|
121
125
|
onPress,
|
|
122
|
-
onNavigate
|
|
126
|
+
onNavigate,
|
|
127
|
+
index
|
|
123
128
|
}) {
|
|
124
129
|
const routeType = (0, _react.useMemo)(() => getRouteType(event), [event]);
|
|
125
130
|
const routeTemplate = (0, _react.useMemo)(() => getRouteTemplate(event.pathname, event.segments), [event.pathname, event.segments]);
|
|
@@ -127,7 +132,6 @@ function RouteEventItemCompact({
|
|
|
127
132
|
const statusLabel = (0, _react.useMemo)(() => getStatusLabel(routeType), [routeType]);
|
|
128
133
|
const statusSublabel = (0, _react.useMemo)(() => getStatusSublabel(event), [event]);
|
|
129
134
|
const badgeText = (0, _react.useMemo)(() => getBadgeText(event), [event]);
|
|
130
|
-
const timeLabel = (0, _sharedUi.useRelativeTime)(event.timestamp);
|
|
131
135
|
const expandedContent = (0, _react.useMemo)(() => {
|
|
132
136
|
if (!isExpanded) return undefined;
|
|
133
137
|
return /*#__PURE__*/(0, _jsxRuntime.jsx)(_RouteEventExpandedContent.RouteEventExpandedContent, {
|
|
@@ -170,14 +174,16 @@ function RouteEventItemCompact({
|
|
|
170
174
|
badgeText: onNavigate ? undefined : badgeText,
|
|
171
175
|
badgeColor: statusColor,
|
|
172
176
|
customBadge: customBadge,
|
|
173
|
-
bottomRightText:
|
|
177
|
+
bottomRightText: /*#__PURE__*/(0, _jsxRuntime.jsx)(_sharedUi.RelativeTime, {
|
|
178
|
+
timestamp: event.timestamp
|
|
179
|
+
}),
|
|
174
180
|
showChevron: true,
|
|
175
181
|
expandedContent: expandedContent,
|
|
176
182
|
isExpanded: isExpanded,
|
|
177
183
|
expandedGlowColor: statusColor,
|
|
178
|
-
onPress: onPress
|
|
184
|
+
onPress: () => onPress(index)
|
|
179
185
|
});
|
|
180
|
-
}
|
|
186
|
+
});
|
|
181
187
|
const styles = _reactNative.StyleSheet.create({
|
|
182
188
|
badgeContainer: {
|
|
183
189
|
flexDirection: "row",
|
|
@@ -42,16 +42,40 @@ function RouteEventsTimeline({
|
|
|
42
42
|
})]
|
|
43
43
|
});
|
|
44
44
|
}
|
|
45
|
-
return
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
45
|
+
return (
|
|
46
|
+
/*#__PURE__*/
|
|
47
|
+
// Virtualized — the previous ScrollView + map mounted ALL events (at
|
|
48
|
+
// the 500-event cap that measured 32.8 JS FPS during an idle dwell,
|
|
49
|
+
// tool-bench 2026-07-06). extraData re-renders visible rows when the
|
|
50
|
+
// expanded row changes.
|
|
51
|
+
(0, _jsxRuntime.jsx)(_reactNative.FlatList, {
|
|
52
|
+
contentContainerStyle: styles.listContent,
|
|
53
|
+
data: events
|
|
54
|
+
// STABLE content keys — index-based keys remount every row when a new
|
|
55
|
+
// event prepends (measured 4 JS FPS during automation, which emits
|
|
56
|
+
// route events on every bounce; tool-bench 2026-07-06).
|
|
57
|
+
,
|
|
58
|
+
keyExtractor: event => `${event.timestamp}-${event.pathname}`,
|
|
59
|
+
extraData: expandedIndex,
|
|
60
|
+
renderItem: ({
|
|
61
|
+
item: event,
|
|
62
|
+
index
|
|
63
|
+
}) => /*#__PURE__*/(0, _jsxRuntime.jsx)(_RouteEventItemCompact.RouteEventItemCompact, {
|
|
64
|
+
event: event,
|
|
65
|
+
visitNumber: visitCounts.get(index) || 1,
|
|
66
|
+
isExpanded: expandedIndex === index,
|
|
67
|
+
index: index,
|
|
68
|
+
onPress: handleItemPress,
|
|
69
|
+
onNavigate: onNavigate
|
|
70
|
+
}),
|
|
71
|
+
showsVerticalScrollIndicator: true,
|
|
72
|
+
removeClippedSubviews: true,
|
|
73
|
+
initialNumToRender: 12,
|
|
74
|
+
maxToRenderPerBatch: 8,
|
|
75
|
+
windowSize: 5,
|
|
76
|
+
updateCellsBatchingPeriod: 50
|
|
77
|
+
})
|
|
78
|
+
);
|
|
55
79
|
}
|
|
56
80
|
const styles = _reactNative.StyleSheet.create({
|
|
57
81
|
listContent: {
|
|
@@ -51,19 +51,28 @@ function useRouteEvents(options = {}) {
|
|
|
51
51
|
setIsListening(false);
|
|
52
52
|
return;
|
|
53
53
|
}
|
|
54
|
+
|
|
55
|
+
// Frame-coalesced (see network's useNetworkEventList): navigation
|
|
56
|
+
// bursts land as one commit per frame instead of one per emission.
|
|
57
|
+
let rafId = null;
|
|
58
|
+
let pending = null;
|
|
54
59
|
const unsubscribe = _routeEventStore.routeEventStore.subscribeToEvents(allEvents => {
|
|
55
|
-
|
|
56
|
-
if (
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
60
|
+
pending = allEvents;
|
|
61
|
+
if (rafId != null) return;
|
|
62
|
+
rafId = requestAnimationFrame(() => {
|
|
63
|
+
rafId = null;
|
|
64
|
+
if (!pending) return;
|
|
65
|
+
const latest = pending;
|
|
66
|
+
pending = null;
|
|
67
|
+
setEvents(latest.length > maxEvents ? latest.slice(0, maxEvents) : latest);
|
|
68
|
+
});
|
|
61
69
|
});
|
|
62
70
|
|
|
63
71
|
// Mark as listening after successful subscription
|
|
64
72
|
setIsListening(true);
|
|
65
73
|
return () => {
|
|
66
74
|
unsubscribe();
|
|
75
|
+
if (rafId != null) cancelAnimationFrame(rafId);
|
|
67
76
|
// Note: Don't set isListening=false here because we might be
|
|
68
77
|
// re-subscribing due to dependency change, not actually stopping
|
|
69
78
|
};
|
|
@@ -6,9 +6,9 @@
|
|
|
6
6
|
* Uses CompactRow pattern matching network/storage/redux components
|
|
7
7
|
*/
|
|
8
8
|
|
|
9
|
-
import { useMemo } from "react";
|
|
9
|
+
import { memo, useMemo } from "react";
|
|
10
10
|
import { View, Text, TouchableOpacity, StyleSheet } from "react-native";
|
|
11
|
-
import { CompactRow,
|
|
11
|
+
import { CompactRow, RelativeTime, buoyColors } from "@buoy-gg/shared-ui";
|
|
12
12
|
import { RouteEventExpandedContent } from "./RouteEventExpandedContent";
|
|
13
13
|
|
|
14
14
|
// Route type for color coding
|
|
@@ -110,12 +110,17 @@ function getBadgeText(event) {
|
|
|
110
110
|
// Don't show badge text - route type is already shown in status label
|
|
111
111
|
return undefined;
|
|
112
112
|
}
|
|
113
|
-
|
|
113
|
+
|
|
114
|
+
// Memo justified by profiling (tool-bench 2026-07-06): 400 row renders
|
|
115
|
+
// during a 5s dwell at 500 events (timeline re-renders cascaded into all
|
|
116
|
+
// mounted rows via an inline onPress closure).
|
|
117
|
+
export const RouteEventItemCompact = /*#__PURE__*/memo(function RouteEventItemCompact({
|
|
114
118
|
event,
|
|
115
119
|
visitNumber,
|
|
116
120
|
isExpanded,
|
|
117
121
|
onPress,
|
|
118
|
-
onNavigate
|
|
122
|
+
onNavigate,
|
|
123
|
+
index
|
|
119
124
|
}) {
|
|
120
125
|
const routeType = useMemo(() => getRouteType(event), [event]);
|
|
121
126
|
const routeTemplate = useMemo(() => getRouteTemplate(event.pathname, event.segments), [event.pathname, event.segments]);
|
|
@@ -123,7 +128,6 @@ export function RouteEventItemCompact({
|
|
|
123
128
|
const statusLabel = useMemo(() => getStatusLabel(routeType), [routeType]);
|
|
124
129
|
const statusSublabel = useMemo(() => getStatusSublabel(event), [event]);
|
|
125
130
|
const badgeText = useMemo(() => getBadgeText(event), [event]);
|
|
126
|
-
const timeLabel = useRelativeTime(event.timestamp);
|
|
127
131
|
const expandedContent = useMemo(() => {
|
|
128
132
|
if (!isExpanded) return undefined;
|
|
129
133
|
return /*#__PURE__*/_jsx(RouteEventExpandedContent, {
|
|
@@ -166,14 +170,16 @@ export function RouteEventItemCompact({
|
|
|
166
170
|
badgeText: onNavigate ? undefined : badgeText,
|
|
167
171
|
badgeColor: statusColor,
|
|
168
172
|
customBadge: customBadge,
|
|
169
|
-
bottomRightText:
|
|
173
|
+
bottomRightText: /*#__PURE__*/_jsx(RelativeTime, {
|
|
174
|
+
timestamp: event.timestamp
|
|
175
|
+
}),
|
|
170
176
|
showChevron: true,
|
|
171
177
|
expandedContent: expandedContent,
|
|
172
178
|
isExpanded: isExpanded,
|
|
173
179
|
expandedGlowColor: statusColor,
|
|
174
|
-
onPress: onPress
|
|
180
|
+
onPress: () => onPress(index)
|
|
175
181
|
});
|
|
176
|
-
}
|
|
182
|
+
});
|
|
177
183
|
const styles = StyleSheet.create({
|
|
178
184
|
badgeContainer: {
|
|
179
185
|
flexDirection: "row",
|
|
@@ -10,7 +10,7 @@
|
|
|
10
10
|
*/
|
|
11
11
|
|
|
12
12
|
import { useCallback, useState } from "react";
|
|
13
|
-
import { View, Text,
|
|
13
|
+
import { View, Text, FlatList, StyleSheet } from "react-native";
|
|
14
14
|
import { Navigation, buoyColors } from "@buoy-gg/shared-ui";
|
|
15
15
|
import { RouteEventItemCompact } from "./RouteEventItemCompact";
|
|
16
16
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
@@ -38,16 +38,40 @@ export function RouteEventsTimeline({
|
|
|
38
38
|
})]
|
|
39
39
|
});
|
|
40
40
|
}
|
|
41
|
-
return
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
41
|
+
return (
|
|
42
|
+
/*#__PURE__*/
|
|
43
|
+
// Virtualized — the previous ScrollView + map mounted ALL events (at
|
|
44
|
+
// the 500-event cap that measured 32.8 JS FPS during an idle dwell,
|
|
45
|
+
// tool-bench 2026-07-06). extraData re-renders visible rows when the
|
|
46
|
+
// expanded row changes.
|
|
47
|
+
_jsx(FlatList, {
|
|
48
|
+
contentContainerStyle: styles.listContent,
|
|
49
|
+
data: events
|
|
50
|
+
// STABLE content keys — index-based keys remount every row when a new
|
|
51
|
+
// event prepends (measured 4 JS FPS during automation, which emits
|
|
52
|
+
// route events on every bounce; tool-bench 2026-07-06).
|
|
53
|
+
,
|
|
54
|
+
keyExtractor: event => `${event.timestamp}-${event.pathname}`,
|
|
55
|
+
extraData: expandedIndex,
|
|
56
|
+
renderItem: ({
|
|
57
|
+
item: event,
|
|
58
|
+
index
|
|
59
|
+
}) => /*#__PURE__*/_jsx(RouteEventItemCompact, {
|
|
60
|
+
event: event,
|
|
61
|
+
visitNumber: visitCounts.get(index) || 1,
|
|
62
|
+
isExpanded: expandedIndex === index,
|
|
63
|
+
index: index,
|
|
64
|
+
onPress: handleItemPress,
|
|
65
|
+
onNavigate: onNavigate
|
|
66
|
+
}),
|
|
67
|
+
showsVerticalScrollIndicator: true,
|
|
68
|
+
removeClippedSubviews: true,
|
|
69
|
+
initialNumToRender: 12,
|
|
70
|
+
maxToRenderPerBatch: 8,
|
|
71
|
+
windowSize: 5,
|
|
72
|
+
updateCellsBatchingPeriod: 50
|
|
73
|
+
})
|
|
74
|
+
);
|
|
51
75
|
}
|
|
52
76
|
const styles = StyleSheet.create({
|
|
53
77
|
listContent: {
|
|
@@ -48,19 +48,28 @@ export function useRouteEvents(options = {}) {
|
|
|
48
48
|
setIsListening(false);
|
|
49
49
|
return;
|
|
50
50
|
}
|
|
51
|
+
|
|
52
|
+
// Frame-coalesced (see network's useNetworkEventList): navigation
|
|
53
|
+
// bursts land as one commit per frame instead of one per emission.
|
|
54
|
+
let rafId = null;
|
|
55
|
+
let pending = null;
|
|
51
56
|
const unsubscribe = routeEventStore.subscribeToEvents(allEvents => {
|
|
52
|
-
|
|
53
|
-
if (
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
57
|
+
pending = allEvents;
|
|
58
|
+
if (rafId != null) return;
|
|
59
|
+
rafId = requestAnimationFrame(() => {
|
|
60
|
+
rafId = null;
|
|
61
|
+
if (!pending) return;
|
|
62
|
+
const latest = pending;
|
|
63
|
+
pending = null;
|
|
64
|
+
setEvents(latest.length > maxEvents ? latest.slice(0, maxEvents) : latest);
|
|
65
|
+
});
|
|
58
66
|
});
|
|
59
67
|
|
|
60
68
|
// Mark as listening after successful subscription
|
|
61
69
|
setIsListening(true);
|
|
62
70
|
return () => {
|
|
63
71
|
unsubscribe();
|
|
72
|
+
if (rafId != null) cancelAnimationFrame(rafId);
|
|
64
73
|
// Note: Don't set isListening=false here because we might be
|
|
65
74
|
// re-subscribing due to dependency change, not actually stopping
|
|
66
75
|
};
|
|
@@ -8,8 +8,11 @@ export interface RouteEventItemCompactProps {
|
|
|
8
8
|
event: RouteChangeEvent;
|
|
9
9
|
visitNumber: number;
|
|
10
10
|
isExpanded: boolean;
|
|
11
|
-
onPress
|
|
11
|
+
/** Row's list index — passed back through onPress so the handler can
|
|
12
|
+
* stay a single stable callback (memo-compatible). */
|
|
13
|
+
index: number;
|
|
14
|
+
onPress: (index: number) => void;
|
|
12
15
|
onNavigate?: (pathname: string) => void;
|
|
13
16
|
}
|
|
14
|
-
export declare
|
|
17
|
+
export declare const RouteEventItemCompact: import("react").NamedExoticComponent<RouteEventItemCompactProps>;
|
|
15
18
|
//# sourceMappingURL=RouteEventItemCompact.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"RouteEventItemCompact.d.ts","sourceRoot":"","sources":["../../../src/components/RouteEventItemCompact.tsx"],"names":[],"mappings":"AAAA;;;;GAIG;AAKH,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,kBAAkB,CAAC;AAGzD,MAAM,WAAW,0BAA0B;IACzC,KAAK,EAAE,gBAAgB,CAAC;IACxB,WAAW,EAAE,MAAM,CAAC;IACpB,UAAU,EAAE,OAAO,CAAC;IACpB,
|
|
1
|
+
{"version":3,"file":"RouteEventItemCompact.d.ts","sourceRoot":"","sources":["../../../src/components/RouteEventItemCompact.tsx"],"names":[],"mappings":"AAAA;;;;GAIG;AAKH,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,kBAAkB,CAAC;AAGzD,MAAM,WAAW,0BAA0B;IACzC,KAAK,EAAE,gBAAgB,CAAC;IACxB,WAAW,EAAE,MAAM,CAAC;IACpB,UAAU,EAAE,OAAO,CAAC;IACpB;0DACsD;IACtD,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;IACjC,UAAU,CAAC,EAAE,CAAC,QAAQ,EAAE,MAAM,KAAK,IAAI,CAAC;CACzC;AAgHD,eAAO,MAAM,qBAAqB,kEAmEhC,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"RouteEventsTimeline.d.ts","sourceRoot":"","sources":["../../../src/components/RouteEventsTimeline.tsx"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAaH,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,kBAAkB,CAAC;AAGzD,UAAU,wBAAwB;IAChC,MAAM,EAAE,gBAAgB,EAAE,CAAC;IAC3B,WAAW,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACjC,UAAU,CAAC,EAAE,CAAC,QAAQ,EAAE,MAAM,KAAK,IAAI,CAAC;CACzC;AAED,wBAAgB,mBAAmB,CAAC,EAClC,MAAM,EACN,WAAW,EACX,UAAU,GACX,EAAE,wBAAwB,+
|
|
1
|
+
{"version":3,"file":"RouteEventsTimeline.d.ts","sourceRoot":"","sources":["../../../src/components/RouteEventsTimeline.tsx"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAaH,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,kBAAkB,CAAC;AAGzD,UAAU,wBAAwB;IAChC,MAAM,EAAE,gBAAgB,EAAE,CAAC;IAC3B,WAAW,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACjC,UAAU,CAAC,EAAE,CAAC,QAAQ,EAAE,MAAM,KAAK,IAAI,CAAC;CACzC;AAED,wBAAgB,mBAAmB,CAAC,EAClC,MAAM,EACN,WAAW,EACX,UAAU,GACX,EAAE,wBAAwB,+BAoD1B"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useRouteEvents.d.ts","sourceRoot":"","sources":["../../../src/hooks/useRouteEvents.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AAGH,OAAO,EAEL,KAAK,gBAAgB,EACtB,MAAM,2BAA2B,CAAC;AAGnC,YAAY,EAAE,gBAAgB,EAAE,MAAM,2BAA2B,CAAC;AAElE,MAAM,WAAW,qBAAqB;IACpC,gDAAgD;IAChD,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,mFAAmF;IACnF,OAAO,CAAC,EAAE,OAAO,CAAC;CACnB;AAED,MAAM,WAAW,oBAAoB;IACnC,sCAAsC;IACtC,MAAM,EAAE,gBAAgB,EAAE,CAAC;IAC3B,uBAAuB;IACvB,WAAW,EAAE,MAAM,IAAI,CAAC;IACxB,6DAA6D;IAC7D,WAAW,EAAE,OAAO,CAAC;CACtB;AAED,wBAAgB,cAAc,CAC5B,OAAO,GAAE,qBAA0B,GAClC,oBAAoB,
|
|
1
|
+
{"version":3,"file":"useRouteEvents.d.ts","sourceRoot":"","sources":["../../../src/hooks/useRouteEvents.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AAGH,OAAO,EAEL,KAAK,gBAAgB,EACtB,MAAM,2BAA2B,CAAC;AAGnC,YAAY,EAAE,gBAAgB,EAAE,MAAM,2BAA2B,CAAC;AAElE,MAAM,WAAW,qBAAqB;IACpC,gDAAgD;IAChD,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,mFAAmF;IACnF,OAAO,CAAC,EAAE,OAAO,CAAC;CACnB;AAED,MAAM,WAAW,oBAAoB;IACnC,sCAAsC;IACtC,MAAM,EAAE,gBAAgB,EAAE,CAAC;IAC3B,uBAAuB;IACvB,WAAW,EAAE,MAAM,IAAI,CAAC;IACxB,6DAA6D;IAC7D,WAAW,EAAE,OAAO,CAAC;CACtB;AAED,wBAAgB,cAAc,CAC5B,OAAO,GAAE,qBAA0B,GAClC,oBAAoB,CAoDtB"}
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@buoy-gg/route-events",
|
|
3
|
-
"version": "
|
|
4
|
-
"description": "
|
|
3
|
+
"version": "6.0.1",
|
|
4
|
+
"description": "Navigation devtool for React Native — live stack, full sitemap, jump to any screen. Expo Router & React Navigation. Part of Buoy devtools.",
|
|
5
5
|
"main": "lib/commonjs/index.js",
|
|
6
6
|
"module": "lib/module/index.js",
|
|
7
7
|
"types": "lib/typescript/index.d.ts",
|
|
@@ -26,11 +26,11 @@
|
|
|
26
26
|
],
|
|
27
27
|
"sideEffects": false,
|
|
28
28
|
"dependencies": {
|
|
29
|
-
"@buoy-gg/floating-tools-core": "
|
|
30
|
-
"@buoy-gg/shared-ui": "
|
|
29
|
+
"@buoy-gg/floating-tools-core": "6.0.1",
|
|
30
|
+
"@buoy-gg/shared-ui": "6.0.1"
|
|
31
31
|
},
|
|
32
32
|
"peerDependencies": {
|
|
33
|
-
"@buoy-gg/license": "
|
|
33
|
+
"@buoy-gg/license": "6.0.1",
|
|
34
34
|
"@react-native-async-storage/async-storage": "^2.0.0 || ^3.1.0",
|
|
35
35
|
"@react-navigation/native": "*",
|
|
36
36
|
"expo-router": "*",
|
|
@@ -49,7 +49,7 @@
|
|
|
49
49
|
"@types/react-native": "^0.73.0",
|
|
50
50
|
"expo-router": "~5.0.7",
|
|
51
51
|
"typescript": "~5.8.3",
|
|
52
|
-
"@buoy-gg/license": "
|
|
52
|
+
"@buoy-gg/license": "6.0.1"
|
|
53
53
|
},
|
|
54
54
|
"react-native-builder-bob": {
|
|
55
55
|
"source": "src",
|