@buoy-gg/route-events 3.0.1 → 4.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/lib/commonjs/RouteTracker.js +38 -4
- package/lib/commonjs/components/NavigationStack.js +105 -124
- package/lib/commonjs/components/RouteEventsModalWithTabs.js +11 -4
- package/lib/commonjs/components/RoutesSitemap.js +205 -169
- package/lib/commonjs/expoRouterStore.js +17 -0
- package/lib/commonjs/index.js +7 -0
- package/lib/commonjs/stores/navigationStackStore.js +45 -0
- package/lib/commonjs/sync/routeEventsSyncAdapter.js +148 -0
- package/lib/commonjs/useRouteSitemap.js +28 -7
- package/lib/module/RouteTracker.js +39 -5
- package/lib/module/components/NavigationStack.js +106 -125
- package/lib/module/components/RouteEventsModalWithTabs.js +11 -4
- package/lib/module/components/RoutesSitemap.js +207 -171
- package/lib/module/expoRouterStore.js +16 -0
- package/lib/module/index.js +4 -0
- package/lib/module/stores/navigationStackStore.js +41 -0
- package/lib/module/sync/routeEventsSyncAdapter.js +145 -0
- package/lib/module/useRouteSitemap.js +29 -8
- package/lib/typescript/RouteTracker.d.ts.map +1 -1
- package/lib/typescript/components/NavigationStack.d.ts +24 -1
- package/lib/typescript/components/NavigationStack.d.ts.map +1 -1
- package/lib/typescript/components/RouteEventsModalWithTabs.d.ts.map +1 -1
- package/lib/typescript/components/RoutesSitemap.d.ts +19 -1
- package/lib/typescript/components/RoutesSitemap.d.ts.map +1 -1
- package/lib/typescript/expoRouterStore.d.ts +8 -0
- package/lib/typescript/expoRouterStore.d.ts.map +1 -1
- package/lib/typescript/index.d.ts +3 -1
- package/lib/typescript/index.d.ts.map +1 -1
- package/lib/typescript/stores/navigationStackStore.d.ts +33 -0
- package/lib/typescript/stores/navigationStackStore.d.ts.map +1 -0
- package/lib/typescript/sync/routeEventsSyncAdapter.d.ts +69 -0
- package/lib/typescript/sync/routeEventsSyncAdapter.d.ts.map +1 -0
- package/lib/typescript/useRouteSitemap.d.ts +17 -0
- package/lib/typescript/useRouteSitemap.d.ts.map +1 -1
- package/package.json +6 -6
|
@@ -25,12 +25,35 @@ var _jsxRuntime = require("react/jsx-runtime");
|
|
|
25
25
|
// Types
|
|
26
26
|
// ============================================================================
|
|
27
27
|
|
|
28
|
+
// On desktop (web) the toolbar has far more room, so scale the action buttons
|
|
29
|
+
// up for easier clicking and a less cramped header.
|
|
30
|
+
const IS_DESKTOP = _reactNative.Platform.OS === "web";
|
|
31
|
+
const ACTION_ICON_SIZE = IS_DESKTOP ? 22 : 16;
|
|
32
|
+
|
|
33
|
+
// Synthetic route representing the app's home/index ("/"). Used by the
|
|
34
|
+
// "Home" toolbar shortcut so navigation works the same as tapping any route.
|
|
35
|
+
const HOME_ROUTE = {
|
|
36
|
+
path: "/",
|
|
37
|
+
name: "index",
|
|
38
|
+
type: "index",
|
|
39
|
+
params: [],
|
|
40
|
+
nodeType: "route",
|
|
41
|
+
contextKey: "/",
|
|
42
|
+
isInternal: false,
|
|
43
|
+
children: [],
|
|
44
|
+
depth: 0
|
|
45
|
+
};
|
|
46
|
+
|
|
28
47
|
// ============================================================================
|
|
29
48
|
// Main Component
|
|
30
49
|
// ============================================================================
|
|
31
50
|
|
|
32
51
|
function RoutesSitemap({
|
|
33
|
-
style
|
|
52
|
+
style,
|
|
53
|
+
injectedRoutes,
|
|
54
|
+
injectedSource,
|
|
55
|
+
injectedLastUpdatedAt,
|
|
56
|
+
onNavigateRoute
|
|
34
57
|
}) {
|
|
35
58
|
const [searchQuery, setSearchQuery] = (0, _react.useState)("");
|
|
36
59
|
const [isSearching, setIsSearching] = (0, _react.useState)(false);
|
|
@@ -52,6 +75,7 @@ function RoutesSitemap({
|
|
|
52
75
|
groups,
|
|
53
76
|
stats,
|
|
54
77
|
isLoaded,
|
|
78
|
+
isSupported,
|
|
55
79
|
filteredRoutes,
|
|
56
80
|
routes,
|
|
57
81
|
refresh,
|
|
@@ -59,7 +83,10 @@ function RoutesSitemap({
|
|
|
59
83
|
source
|
|
60
84
|
} = (0, _useRouteSitemap.useRouteSitemap)({
|
|
61
85
|
searchQuery,
|
|
62
|
-
sortBy: "path"
|
|
86
|
+
sortBy: "path",
|
|
87
|
+
injectedRoutes,
|
|
88
|
+
injectedSource,
|
|
89
|
+
injectedLastUpdatedAt
|
|
63
90
|
});
|
|
64
91
|
|
|
65
92
|
// Prepare copy data - memoized so it only rebuilds when dependencies change
|
|
@@ -146,9 +173,16 @@ function RoutesSitemap({
|
|
|
146
173
|
}
|
|
147
174
|
}], "plain-text");
|
|
148
175
|
}, [router]);
|
|
149
|
-
const handleNavigate = (0, _react.useCallback)(route => {
|
|
150
|
-
//
|
|
151
|
-
|
|
176
|
+
const handleNavigate = (0, _react.useCallback)((route, options) => {
|
|
177
|
+
// When a navigation delegate is supplied (dashboard → device), hand off
|
|
178
|
+
// entirely: the delegate owns Pro gating and param resolution.
|
|
179
|
+
if (onNavigateRoute) {
|
|
180
|
+
onNavigateRoute(route);
|
|
181
|
+
return;
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
// Gate behind Pro (the Home shortcut bypasses this — it's always free)
|
|
185
|
+
if (!isPro && !options?.bypassPro) {
|
|
152
186
|
setShowUpgradeModal(true);
|
|
153
187
|
return;
|
|
154
188
|
}
|
|
@@ -182,7 +216,12 @@ function RoutesSitemap({
|
|
|
182
216
|
} catch (error) {
|
|
183
217
|
_reactNative.Alert.alert("Navigation Error", String(error));
|
|
184
218
|
}
|
|
185
|
-
}, [router, promptForParams, isPro]);
|
|
219
|
+
}, [router, promptForParams, isPro, onNavigateRoute]);
|
|
220
|
+
const handleGoHome = (0, _react.useCallback)(() => {
|
|
221
|
+
handleNavigate(HOME_ROUTE, {
|
|
222
|
+
bypassPro: true
|
|
223
|
+
});
|
|
224
|
+
}, [handleNavigate]);
|
|
186
225
|
const handleManualRefresh = (0, _react.useCallback)(() => {
|
|
187
226
|
if (isRefreshing) return;
|
|
188
227
|
setIsRefreshing(true);
|
|
@@ -217,7 +256,7 @@ function RoutesSitemap({
|
|
|
217
256
|
style: styles.loadingContainer,
|
|
218
257
|
children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.Text, {
|
|
219
258
|
style: styles.loadingText,
|
|
220
|
-
children: "Loading routes..."
|
|
259
|
+
children: isSupported ? "Loading routes..." : "Route sitemap isn't available on the dashboard — the route tree lives on the device. Use the Events tab to see navigation here."
|
|
221
260
|
})
|
|
222
261
|
})
|
|
223
262
|
});
|
|
@@ -229,39 +268,54 @@ function RoutesSitemap({
|
|
|
229
268
|
children: [/*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNative.View, {
|
|
230
269
|
style: styles.actionsRow,
|
|
231
270
|
children: [/*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNative.View, {
|
|
232
|
-
style: styles.actionWrapper,
|
|
233
|
-
children: [/*#__PURE__*/(0, _jsxRuntime.jsx)(
|
|
271
|
+
style: [styles.actionWrapper, IS_DESKTOP && styles.actionWrapperDesktop],
|
|
272
|
+
children: [/*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.TouchableOpacity, {
|
|
273
|
+
style: [styles.iconButton, IS_DESKTOP && styles.iconButtonDesktop],
|
|
274
|
+
onPress: handleGoHome,
|
|
275
|
+
accessibilityLabel: "Go to home route",
|
|
276
|
+
children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_sharedUi.Home, {
|
|
277
|
+
size: ACTION_ICON_SIZE,
|
|
278
|
+
color: _sharedUi.buoyColors.textSecondary
|
|
279
|
+
})
|
|
280
|
+
}), /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.Text, {
|
|
281
|
+
style: [styles.actionLabel, IS_DESKTOP && styles.actionLabelDesktop],
|
|
282
|
+
children: "Home"
|
|
283
|
+
})]
|
|
284
|
+
}), /*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNative.View, {
|
|
285
|
+
style: [styles.actionWrapper, IS_DESKTOP && styles.actionWrapperDesktop],
|
|
286
|
+
children: [/*#__PURE__*/(0, _jsxRuntime.jsx)(_sharedUi.CopyButton, {
|
|
234
287
|
value: copyAllData,
|
|
235
|
-
|
|
288
|
+
size: IS_DESKTOP ? ACTION_ICON_SIZE : 14,
|
|
289
|
+
buttonStyle: IS_DESKTOP ? styles.actionButtonHeaderDesktop : styles.actionButtonHeader
|
|
236
290
|
}), /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.Text, {
|
|
237
|
-
style: styles.actionLabel,
|
|
291
|
+
style: [styles.actionLabel, IS_DESKTOP && styles.actionLabelDesktop],
|
|
238
292
|
children: "Copy"
|
|
239
293
|
})]
|
|
240
294
|
}), /*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNative.View, {
|
|
241
|
-
style: styles.actionWrapper,
|
|
295
|
+
style: [styles.actionWrapper, IS_DESKTOP && styles.actionWrapperDesktop],
|
|
242
296
|
children: [/*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.TouchableOpacity, {
|
|
243
|
-
style: [styles.iconButton, isRefreshing && styles.refreshButtonDisabled],
|
|
297
|
+
style: [styles.iconButton, IS_DESKTOP && styles.iconButtonDesktop, isRefreshing && styles.refreshButtonDisabled],
|
|
244
298
|
onPress: handleManualRefresh,
|
|
245
299
|
disabled: isRefreshing,
|
|
246
300
|
children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_sharedUi.RefreshCw, {
|
|
247
|
-
size:
|
|
301
|
+
size: ACTION_ICON_SIZE,
|
|
248
302
|
color: isRefreshing ? _sharedUi.buoyColors.textMuted : _sharedUi.buoyColors.textSecondary
|
|
249
303
|
})
|
|
250
304
|
}), /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.Text, {
|
|
251
|
-
style: styles.actionLabel,
|
|
305
|
+
style: [styles.actionLabel, IS_DESKTOP && styles.actionLabelDesktop],
|
|
252
306
|
children: "Refresh"
|
|
253
307
|
})]
|
|
254
308
|
}), /*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNative.View, {
|
|
255
|
-
style: styles.actionWrapper,
|
|
309
|
+
style: [styles.actionWrapper, IS_DESKTOP && styles.actionWrapperDesktop],
|
|
256
310
|
children: [/*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.TouchableOpacity, {
|
|
257
|
-
style: styles.iconButton,
|
|
311
|
+
style: [styles.iconButton, IS_DESKTOP && styles.iconButtonDesktop],
|
|
258
312
|
onPress: () => setIsSearching(true),
|
|
259
313
|
children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_sharedUi.Search, {
|
|
260
|
-
size:
|
|
314
|
+
size: ACTION_ICON_SIZE,
|
|
261
315
|
color: _sharedUi.buoyColors.textSecondary
|
|
262
316
|
})
|
|
263
317
|
}), /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.Text, {
|
|
264
|
-
style: styles.actionLabel,
|
|
318
|
+
style: [styles.actionLabel, IS_DESKTOP && styles.actionLabelDesktop],
|
|
265
319
|
children: "Search"
|
|
266
320
|
})]
|
|
267
321
|
})]
|
|
@@ -407,18 +461,18 @@ function RouteGroupView({
|
|
|
407
461
|
children: group.routes.length
|
|
408
462
|
})
|
|
409
463
|
})]
|
|
410
|
-
}),
|
|
464
|
+
}), group.description && /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.View, {
|
|
465
|
+
style: styles.groupDescription,
|
|
466
|
+
children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.Text, {
|
|
467
|
+
style: styles.groupDescriptionText,
|
|
468
|
+
children: group.description
|
|
469
|
+
})
|
|
470
|
+
}), isExpanded && /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.View, {
|
|
411
471
|
style: styles.routesList,
|
|
412
|
-
children:
|
|
413
|
-
style: styles.groupDescription,
|
|
414
|
-
children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.Text, {
|
|
415
|
-
style: styles.groupDescriptionText,
|
|
416
|
-
children: group.description
|
|
417
|
-
})
|
|
418
|
-
}), group.routes.map((route, index) => /*#__PURE__*/(0, _jsxRuntime.jsx)(RouteItemView, {
|
|
472
|
+
children: group.routes.map((route, index) => /*#__PURE__*/(0, _jsxRuntime.jsx)(RouteItemView, {
|
|
419
473
|
route: route,
|
|
420
474
|
onNavigate: onNavigate
|
|
421
|
-
}, `${route.path}-${index}`))
|
|
475
|
+
}, `${route.path}-${index}`))
|
|
422
476
|
})]
|
|
423
477
|
});
|
|
424
478
|
}
|
|
@@ -429,85 +483,85 @@ function RouteItemView({
|
|
|
429
483
|
}) {
|
|
430
484
|
const [isExpanded, setIsExpanded] = (0, _react.useState)(false);
|
|
431
485
|
const hasChildren = route.children.length > 0;
|
|
432
|
-
const hasParams = route.params.length > 0;
|
|
433
486
|
const typeColor = getRouteTypeColor(route.type);
|
|
434
487
|
const canNavigate = route.type !== "layout" && route.type !== "group";
|
|
435
|
-
|
|
488
|
+
|
|
489
|
+
// Leaf routes (no children) have nothing to drill into — expanding would only
|
|
490
|
+
// reveal the Copy/Go actions, so show those inline instead of behind a toggle.
|
|
491
|
+
const isExpandable = hasChildren;
|
|
492
|
+
const showDetails = isExpandable ? isExpanded : true;
|
|
493
|
+
return /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.View, {
|
|
436
494
|
style: [styles.routeItem, {
|
|
437
495
|
marginLeft: depth * 12
|
|
438
496
|
}],
|
|
439
|
-
children:
|
|
497
|
+
children: /*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNative.View, {
|
|
440
498
|
style: styles.routeCard,
|
|
441
|
-
children: [/*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNative.TouchableOpacity, {
|
|
442
|
-
style: styles.routeHeaderLeft,
|
|
443
|
-
onPress: () => setIsExpanded(!isExpanded),
|
|
444
|
-
activeOpacity: 0.7,
|
|
445
|
-
children: [/*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.View, {
|
|
446
|
-
style: styles.expandIndicator,
|
|
447
|
-
children: isExpanded ? /*#__PURE__*/(0, _jsxRuntime.jsx)(_sharedUi.ChevronDown, {
|
|
448
|
-
size: 14,
|
|
449
|
-
color: _sharedUi.buoyColors.textSecondary
|
|
450
|
-
}) : /*#__PURE__*/(0, _jsxRuntime.jsx)(_sharedUi.ChevronRight, {
|
|
451
|
-
size: 14,
|
|
452
|
-
color: _sharedUi.buoyColors.textSecondary
|
|
453
|
-
})
|
|
454
|
-
}), /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.Text, {
|
|
455
|
-
style: styles.routePath,
|
|
456
|
-
numberOfLines: 1,
|
|
457
|
-
children: route.path
|
|
458
|
-
})]
|
|
459
|
-
}), /*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNative.View, {
|
|
460
|
-
style: styles.routeHeaderActions,
|
|
461
|
-
children: [hasChildren && /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.View, {
|
|
462
|
-
style: styles.childCountBadge,
|
|
463
|
-
children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.Text, {
|
|
464
|
-
style: styles.childCountText,
|
|
465
|
-
children: route.children.length
|
|
466
|
-
})
|
|
467
|
-
}), /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.View, {
|
|
468
|
-
style: [styles.typeTag, {
|
|
469
|
-
backgroundColor: `${typeColor}15`,
|
|
470
|
-
borderColor: `${typeColor}40`
|
|
471
|
-
}],
|
|
472
|
-
children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.Text, {
|
|
473
|
-
style: [styles.typeText, {
|
|
474
|
-
color: typeColor
|
|
475
|
-
}],
|
|
476
|
-
children: route.type.toUpperCase()
|
|
477
|
-
})
|
|
478
|
-
})]
|
|
479
|
-
})]
|
|
480
|
-
}), isExpanded && /*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNative.View, {
|
|
481
|
-
style: styles.routeDetails,
|
|
482
499
|
children: [/*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNative.View, {
|
|
483
|
-
style: styles.
|
|
484
|
-
children: [/*#__PURE__*/(0, _jsxRuntime.
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
|
|
500
|
+
style: styles.routeHeader,
|
|
501
|
+
children: [isExpandable ? /*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNative.TouchableOpacity, {
|
|
502
|
+
style: styles.routeHeaderLeft,
|
|
503
|
+
onPress: () => setIsExpanded(!isExpanded),
|
|
504
|
+
activeOpacity: 0.7,
|
|
505
|
+
children: [/*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.View, {
|
|
506
|
+
style: styles.expandIndicator,
|
|
507
|
+
children: isExpanded ? /*#__PURE__*/(0, _jsxRuntime.jsx)(_sharedUi.ChevronDown, {
|
|
508
|
+
size: 14,
|
|
509
|
+
color: _sharedUi.buoyColors.textSecondary
|
|
510
|
+
}) : /*#__PURE__*/(0, _jsxRuntime.jsx)(_sharedUi.ChevronRight, {
|
|
511
|
+
size: 14,
|
|
512
|
+
color: _sharedUi.buoyColors.textSecondary
|
|
513
|
+
})
|
|
514
|
+
}), /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.Text, {
|
|
515
|
+
style: styles.routePath,
|
|
516
|
+
numberOfLines: 3,
|
|
517
|
+
children: route.path
|
|
518
|
+
})]
|
|
519
|
+
}) :
|
|
520
|
+
/*#__PURE__*/
|
|
521
|
+
// Non-toggling header for leaf routes (keeps the chevron column as a
|
|
522
|
+
// spacer so paths stay aligned with expandable siblings).
|
|
523
|
+
(0, _jsxRuntime.jsxs)(_reactNative.View, {
|
|
524
|
+
style: styles.routeHeaderLeft,
|
|
525
|
+
children: [/*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.View, {
|
|
526
|
+
style: styles.expandIndicator
|
|
527
|
+
}), /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.Text, {
|
|
528
|
+
style: styles.routePath,
|
|
529
|
+
numberOfLines: 3,
|
|
530
|
+
children: route.path
|
|
531
|
+
})]
|
|
532
|
+
}), /*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNative.View, {
|
|
533
|
+
style: styles.routeHeaderActions,
|
|
534
|
+
children: [hasChildren && /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.View, {
|
|
535
|
+
style: styles.childCountBadge,
|
|
504
536
|
children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.Text, {
|
|
505
|
-
style: styles.
|
|
506
|
-
children:
|
|
537
|
+
style: styles.childCountText,
|
|
538
|
+
children: route.children.length
|
|
507
539
|
})
|
|
508
|
-
},
|
|
540
|
+
}), /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.View, {
|
|
541
|
+
style: [styles.typeTag, {
|
|
542
|
+
backgroundColor: `${typeColor}15`,
|
|
543
|
+
borderColor: `${typeColor}40`
|
|
544
|
+
}],
|
|
545
|
+
children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.Text, {
|
|
546
|
+
style: [styles.typeText, {
|
|
547
|
+
color: typeColor
|
|
548
|
+
}],
|
|
549
|
+
children: route.type.toUpperCase()
|
|
550
|
+
})
|
|
551
|
+
}), /*#__PURE__*/(0, _jsxRuntime.jsx)(_sharedUi.InlineCopyButton, {
|
|
552
|
+
value: route.path,
|
|
553
|
+
buttonStyle: styles.iconAction
|
|
554
|
+
}), canNavigate && /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.TouchableOpacity, {
|
|
555
|
+
style: styles.goButton,
|
|
556
|
+
onPress: () => onNavigate(route),
|
|
557
|
+
activeOpacity: 0.7,
|
|
558
|
+
children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.Text, {
|
|
559
|
+
style: styles.goButtonText,
|
|
560
|
+
children: "Go"
|
|
561
|
+
})
|
|
562
|
+
})]
|
|
509
563
|
})]
|
|
510
|
-
}), hasChildren && /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.View, {
|
|
564
|
+
}), showDetails && hasChildren && /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.View, {
|
|
511
565
|
style: styles.childrenContainer,
|
|
512
566
|
children: route.children.map((child, index) => /*#__PURE__*/(0, _jsxRuntime.jsx)(RouteItemView, {
|
|
513
567
|
route: child,
|
|
@@ -515,7 +569,7 @@ function RouteItemView({
|
|
|
515
569
|
onNavigate: onNavigate
|
|
516
570
|
}, `${child.path}-${index}`))
|
|
517
571
|
})]
|
|
518
|
-
})
|
|
572
|
+
})
|
|
519
573
|
});
|
|
520
574
|
}
|
|
521
575
|
|
|
@@ -569,7 +623,11 @@ const styles = _reactNative.StyleSheet.create({
|
|
|
569
623
|
loadingText: {
|
|
570
624
|
color: _sharedUi.buoyColors.textSecondary,
|
|
571
625
|
fontSize: 14,
|
|
572
|
-
fontFamily: "monospace"
|
|
626
|
+
fontFamily: "monospace",
|
|
627
|
+
textAlign: "center",
|
|
628
|
+
lineHeight: 20,
|
|
629
|
+
paddingHorizontal: 32,
|
|
630
|
+
maxWidth: 420
|
|
573
631
|
},
|
|
574
632
|
header: {
|
|
575
633
|
flexDirection: "column",
|
|
@@ -581,7 +639,7 @@ const styles = _reactNative.StyleSheet.create({
|
|
|
581
639
|
actionsRow: {
|
|
582
640
|
flexDirection: "row",
|
|
583
641
|
alignItems: "center",
|
|
584
|
-
justifyContent: "
|
|
642
|
+
justifyContent: "space-between",
|
|
585
643
|
gap: 12,
|
|
586
644
|
paddingBottom: 4
|
|
587
645
|
},
|
|
@@ -616,22 +674,37 @@ const styles = _reactNative.StyleSheet.create({
|
|
|
616
674
|
letterSpacing: 0.5
|
|
617
675
|
},
|
|
618
676
|
actionWrapper: {
|
|
677
|
+
flex: 1,
|
|
619
678
|
alignItems: "center",
|
|
620
679
|
justifyContent: "center",
|
|
621
680
|
gap: 4,
|
|
622
681
|
minWidth: 48
|
|
623
682
|
},
|
|
683
|
+
actionWrapperDesktop: {
|
|
684
|
+
gap: 8,
|
|
685
|
+
minWidth: 72
|
|
686
|
+
},
|
|
624
687
|
actionButtonHeader: {
|
|
625
688
|
padding: 6,
|
|
626
689
|
borderRadius: 4,
|
|
627
690
|
backgroundColor: _sharedUi.buoyColors.input
|
|
628
691
|
},
|
|
692
|
+
actionButtonHeaderDesktop: {
|
|
693
|
+
padding: 12,
|
|
694
|
+
borderRadius: 8,
|
|
695
|
+
backgroundColor: _sharedUi.buoyColors.input
|
|
696
|
+
},
|
|
629
697
|
iconButton: {
|
|
630
698
|
padding: 6,
|
|
631
699
|
borderRadius: 4,
|
|
632
700
|
alignItems: "center",
|
|
633
701
|
justifyContent: "center"
|
|
634
702
|
},
|
|
703
|
+
iconButtonDesktop: {
|
|
704
|
+
padding: 12,
|
|
705
|
+
borderRadius: 8,
|
|
706
|
+
backgroundColor: _sharedUi.buoyColors.input
|
|
707
|
+
},
|
|
635
708
|
actionLabel: {
|
|
636
709
|
fontSize: 8,
|
|
637
710
|
color: _sharedUi.buoyColors.textMuted,
|
|
@@ -639,6 +712,9 @@ const styles = _reactNative.StyleSheet.create({
|
|
|
639
712
|
textTransform: "uppercase",
|
|
640
713
|
letterSpacing: 0.5
|
|
641
714
|
},
|
|
715
|
+
actionLabelDesktop: {
|
|
716
|
+
fontSize: 12
|
|
717
|
+
},
|
|
642
718
|
refreshButtonDisabled: {
|
|
643
719
|
opacity: 0.5
|
|
644
720
|
},
|
|
@@ -783,15 +859,11 @@ const styles = _reactNative.StyleSheet.create({
|
|
|
783
859
|
marginBottom: 6
|
|
784
860
|
},
|
|
785
861
|
routeCard: {
|
|
786
|
-
flexDirection: "row",
|
|
787
|
-
alignItems: "center",
|
|
788
|
-
justifyContent: "space-between",
|
|
789
|
-
paddingVertical: 10,
|
|
790
|
-
paddingHorizontal: 12,
|
|
791
862
|
backgroundColor: _sharedUi.buoyColors.card,
|
|
792
863
|
borderRadius: 6,
|
|
793
864
|
borderWidth: 1,
|
|
794
865
|
borderColor: _sharedUi.buoyColors.border,
|
|
866
|
+
overflow: "hidden",
|
|
795
867
|
shadowColor: "#000",
|
|
796
868
|
shadowOffset: {
|
|
797
869
|
width: 0,
|
|
@@ -801,8 +873,16 @@ const styles = _reactNative.StyleSheet.create({
|
|
|
801
873
|
shadowRadius: 2,
|
|
802
874
|
elevation: 1
|
|
803
875
|
},
|
|
876
|
+
routeHeader: {
|
|
877
|
+
flexDirection: "row",
|
|
878
|
+
alignItems: "center",
|
|
879
|
+
justifyContent: "space-between",
|
|
880
|
+
paddingVertical: 7,
|
|
881
|
+
paddingHorizontal: 10,
|
|
882
|
+
gap: 8
|
|
883
|
+
},
|
|
804
884
|
expandIndicator: {
|
|
805
|
-
width:
|
|
885
|
+
width: 18,
|
|
806
886
|
alignItems: "center"
|
|
807
887
|
},
|
|
808
888
|
routeHeaderLeft: {
|
|
@@ -851,76 +931,29 @@ const styles = _reactNative.StyleSheet.create({
|
|
|
851
931
|
fontWeight: "600",
|
|
852
932
|
fontFamily: "monospace"
|
|
853
933
|
},
|
|
854
|
-
|
|
855
|
-
|
|
856
|
-
|
|
857
|
-
|
|
858
|
-
|
|
859
|
-
|
|
860
|
-
borderTopColor: _sharedUi.buoyColors.border,
|
|
861
|
-
backgroundColor: _sharedUi.buoyColors.card,
|
|
862
|
-
borderRadius: 6,
|
|
934
|
+
// Compact icon-sized Copy button in the header action cluster.
|
|
935
|
+
iconAction: {
|
|
936
|
+
width: 28,
|
|
937
|
+
height: 24,
|
|
938
|
+
borderRadius: 4,
|
|
939
|
+
backgroundColor: _sharedUi.buoyColors.input,
|
|
863
940
|
borderWidth: 1,
|
|
864
941
|
borderColor: _sharedUi.buoyColors.border,
|
|
865
|
-
|
|
866
|
-
|
|
867
|
-
marginTop: -6
|
|
868
|
-
},
|
|
869
|
-
paramsContainer: {
|
|
870
|
-
gap: 6
|
|
871
|
-
},
|
|
872
|
-
paramsLabel: {
|
|
873
|
-
fontSize: 10,
|
|
874
|
-
color: _sharedUi.buoyColors.textSecondary,
|
|
875
|
-
fontFamily: "monospace",
|
|
876
|
-
marginBottom: 4
|
|
877
|
-
},
|
|
878
|
-
paramsRow: {
|
|
879
|
-
flexDirection: "row",
|
|
880
|
-
flexWrap: "wrap",
|
|
881
|
-
gap: 6
|
|
942
|
+
alignItems: "center",
|
|
943
|
+
justifyContent: "center"
|
|
882
944
|
},
|
|
883
|
-
|
|
884
|
-
|
|
885
|
-
|
|
886
|
-
|
|
945
|
+
// Small "Go" pill in the header action cluster.
|
|
946
|
+
goButton: {
|
|
947
|
+
height: 24,
|
|
948
|
+
paddingHorizontal: 10,
|
|
887
949
|
borderRadius: 4,
|
|
888
|
-
paddingHorizontal: 6,
|
|
889
|
-
paddingVertical: 2
|
|
890
|
-
},
|
|
891
|
-
paramText: {
|
|
892
|
-
fontSize: 10,
|
|
893
|
-
color: "#F59E0B",
|
|
894
|
-
fontFamily: "monospace",
|
|
895
|
-
fontWeight: "600"
|
|
896
|
-
},
|
|
897
|
-
routeButtons: {
|
|
898
|
-
flexDirection: "row",
|
|
899
|
-
gap: 6,
|
|
900
|
-
marginBottom: 12
|
|
901
|
-
},
|
|
902
|
-
actionButton: {
|
|
903
|
-
flexDirection: "row",
|
|
904
950
|
alignItems: "center",
|
|
905
|
-
|
|
906
|
-
backgroundColor: _sharedUi.buoyColors.input,
|
|
907
|
-
borderRadius: 4,
|
|
908
|
-
paddingHorizontal: 12,
|
|
909
|
-
paddingVertical: 6,
|
|
910
|
-
borderWidth: 1,
|
|
911
|
-
borderColor: _sharedUi.buoyColors.border
|
|
912
|
-
},
|
|
913
|
-
actionButtonText: {
|
|
914
|
-
fontSize: 12,
|
|
915
|
-
color: _sharedUi.buoyColors.textSecondary,
|
|
916
|
-
fontFamily: "monospace",
|
|
917
|
-
fontWeight: "600"
|
|
918
|
-
},
|
|
919
|
-
navigateButton: {
|
|
951
|
+
justifyContent: "center",
|
|
920
952
|
backgroundColor: _sharedUi.buoyColors.primary + "15",
|
|
953
|
+
borderWidth: 1,
|
|
921
954
|
borderColor: _sharedUi.buoyColors.primary + "40"
|
|
922
955
|
},
|
|
923
|
-
|
|
956
|
+
goButtonText: {
|
|
924
957
|
fontSize: 12,
|
|
925
958
|
color: _sharedUi.buoyColors.primary,
|
|
926
959
|
fontFamily: "monospace",
|
|
@@ -929,6 +962,9 @@ const styles = _reactNative.StyleSheet.create({
|
|
|
929
962
|
childrenContainer: {
|
|
930
963
|
borderLeftWidth: 2,
|
|
931
964
|
borderLeftColor: _sharedUi.buoyColors.border,
|
|
932
|
-
marginLeft: 16
|
|
965
|
+
marginLeft: 16,
|
|
966
|
+
marginRight: 8,
|
|
967
|
+
marginTop: 2,
|
|
968
|
+
marginBottom: 8
|
|
933
969
|
}
|
|
934
970
|
});
|
|
@@ -5,6 +5,7 @@ Object.defineProperty(exports, "__esModule", {
|
|
|
5
5
|
});
|
|
6
6
|
exports.getExpoRouterStore = getExpoRouterStore;
|
|
7
7
|
exports.getRouteNodeMetadata = getRouteNodeMetadata;
|
|
8
|
+
exports.isExpoRouterStoreSupported = isExpoRouterStoreSupported;
|
|
8
9
|
exports.loadRouteNode = loadRouteNode;
|
|
9
10
|
let cachedStore = null;
|
|
10
11
|
let cachedStoreSource = null;
|
|
@@ -30,10 +31,26 @@ function logOnce(message, error) {
|
|
|
30
31
|
* The storeRef gets populated when Expo Router's useStore() hook runs.
|
|
31
32
|
* So we cache the store reference but its property values update over time.
|
|
32
33
|
*/
|
|
34
|
+
/**
|
|
35
|
+
* Whether the expo-router store can be loaded in this runtime. The store is
|
|
36
|
+
* pulled in via CommonJS `require`, which only exists under Metro/Node. On the
|
|
37
|
+
* web (e.g. the desktop dashboard rendering these RN tools via react-native-web)
|
|
38
|
+
* `require` is undefined, the route tree lives on the device — not here — and
|
|
39
|
+
* there is nothing to load. Callers use this to skip polling/logging.
|
|
40
|
+
*/
|
|
41
|
+
function isExpoRouterStoreSupported() {
|
|
42
|
+
return typeof require !== "undefined";
|
|
43
|
+
}
|
|
33
44
|
function getExpoRouterStore() {
|
|
34
45
|
if (cachedStore) {
|
|
35
46
|
return cachedStore;
|
|
36
47
|
}
|
|
48
|
+
|
|
49
|
+
// No `require` (web): bail quietly rather than throwing ReferenceError and
|
|
50
|
+
// logging a misleading "install expo-router" message on the dashboard.
|
|
51
|
+
if (!isExpoRouterStoreSupported()) {
|
|
52
|
+
return null;
|
|
53
|
+
}
|
|
37
54
|
const loadFromBuild = () => {
|
|
38
55
|
try {
|
|
39
56
|
const module = require("expo-router/build/global-state/router-store");
|
package/lib/commonjs/index.js
CHANGED
|
@@ -63,6 +63,12 @@ Object.defineProperty(exports, "routeEventStore", {
|
|
|
63
63
|
return _routeEventStore.routeEventStore;
|
|
64
64
|
}
|
|
65
65
|
});
|
|
66
|
+
Object.defineProperty(exports, "routeEventsSyncAdapter", {
|
|
67
|
+
enumerable: true,
|
|
68
|
+
get: function () {
|
|
69
|
+
return _routeEventsSyncAdapter.routeEventsSyncAdapter;
|
|
70
|
+
}
|
|
71
|
+
});
|
|
66
72
|
Object.defineProperty(exports, "routeEventsToolPreset", {
|
|
67
73
|
enumerable: true,
|
|
68
74
|
get: function () {
|
|
@@ -129,6 +135,7 @@ var _useRouteObserverReactNavigation = require("./useRouteObserverReactNavigatio
|
|
|
129
135
|
var _useRouteEvents = require("./hooks/useRouteEvents");
|
|
130
136
|
var _useRouteSitemap = require("./useRouteSitemap");
|
|
131
137
|
var _useNavigationStack = require("./useNavigationStack");
|
|
138
|
+
var _routeEventsSyncAdapter = require("./sync/routeEventsSyncAdapter");
|
|
132
139
|
var _RouteParser = require("./RouteParser");
|
|
133
140
|
var _RouteObserver = require("./RouteObserver");
|
|
134
141
|
var _routeEventStore = require("./stores/routeEventStore");
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, "__esModule", {
|
|
4
|
+
value: true
|
|
5
|
+
});
|
|
6
|
+
exports.navigationStackStore = void 0;
|
|
7
|
+
/**
|
|
8
|
+
* Navigation Stack Store
|
|
9
|
+
*
|
|
10
|
+
* Holds the latest serializable navigation stack plus references to the live
|
|
11
|
+
* navigation action functions. The stack is captured inside the navigation tree
|
|
12
|
+
* by <RouteTracker /> (which runs useNavigationStack), and read by the
|
|
13
|
+
* route-events sync adapter so the dashboard can render the Stack tab and drive
|
|
14
|
+
* navigation on the device remotely.
|
|
15
|
+
*
|
|
16
|
+
* The stack itself (StackDisplayItem[]) is JSON-serializable and synced to the
|
|
17
|
+
* dashboard. The action functions are NOT serialized — they stay on the device
|
|
18
|
+
* and are invoked when the dashboard sends a remote action.
|
|
19
|
+
*/
|
|
20
|
+
|
|
21
|
+
class NavigationStackStore {
|
|
22
|
+
stack = [];
|
|
23
|
+
actions = null;
|
|
24
|
+
listeners = new Set();
|
|
25
|
+
getStack() {
|
|
26
|
+
return this.stack;
|
|
27
|
+
}
|
|
28
|
+
setStack(stack) {
|
|
29
|
+
this.stack = stack;
|
|
30
|
+
this.listeners.forEach(listener => listener());
|
|
31
|
+
}
|
|
32
|
+
getActions() {
|
|
33
|
+
return this.actions;
|
|
34
|
+
}
|
|
35
|
+
setActions(actions) {
|
|
36
|
+
this.actions = actions;
|
|
37
|
+
}
|
|
38
|
+
subscribe(listener) {
|
|
39
|
+
this.listeners.add(listener);
|
|
40
|
+
return () => {
|
|
41
|
+
this.listeners.delete(listener);
|
|
42
|
+
};
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
const navigationStackStore = exports.navigationStackStore = new NavigationStackStore();
|