@buoy-gg/route-events 6.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/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)
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@buoy-gg/route-events",
|
|
3
|
-
"version": "6.0.
|
|
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/
|
|
30
|
-
"@buoy-gg/
|
|
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": "6.0.
|
|
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": "6.0.
|
|
52
|
+
"@buoy-gg/license": "6.0.1"
|
|
53
53
|
},
|
|
54
54
|
"react-native-builder-bob": {
|
|
55
55
|
"source": "src",
|