@buoy-gg/route-events 3.0.1 → 3.0.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/lib/commonjs/RouteTracker.js +38 -4
- package/lib/commonjs/components/NavigationStack.js +47 -31
- package/lib/commonjs/components/RoutesSitemap.js +176 -133
- 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 +47 -31
- package/lib/module/components/RoutesSitemap.js +177 -134
- 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 +18 -1
- package/lib/typescript/components/NavigationStack.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 +5 -5
|
@@ -4,9 +4,12 @@ Object.defineProperty(exports, "__esModule", {
|
|
|
4
4
|
value: true
|
|
5
5
|
});
|
|
6
6
|
exports.RouteTracker = RouteTracker;
|
|
7
|
+
var _react = require("react");
|
|
7
8
|
var _sharedUi = require("@buoy-gg/shared-ui");
|
|
8
9
|
var _useRouteObserver = require("./useRouteObserver");
|
|
9
10
|
var _useRouteObserverReactNavigation = require("./useRouteObserverReactNavigation");
|
|
11
|
+
var _useNavigationStack = require("./useNavigationStack");
|
|
12
|
+
var _navigationStackStore = require("./stores/navigationStackStore");
|
|
10
13
|
var _jsxRuntime = require("react/jsx-runtime");
|
|
11
14
|
/**
|
|
12
15
|
* RouteTracker - A component to place inside your navigation tree
|
|
@@ -57,10 +60,41 @@ function ReactNavigationRouteTracker() {
|
|
|
57
60
|
(0, _useRouteObserverReactNavigation.useRouteObserverReactNavigation)();
|
|
58
61
|
return null;
|
|
59
62
|
}
|
|
63
|
+
|
|
64
|
+
/**
|
|
65
|
+
* Mirrors the live navigation stack (and its action functions) into
|
|
66
|
+
* navigationStackStore so the route-events sync adapter can expose the Stack
|
|
67
|
+
* tab to the dashboard. Runs inside the navigation tree where the container ref
|
|
68
|
+
* context is available.
|
|
69
|
+
*/
|
|
70
|
+
function NavigationStackCapture() {
|
|
71
|
+
const {
|
|
72
|
+
stack,
|
|
73
|
+
navigateToIndex,
|
|
74
|
+
popToIndex,
|
|
75
|
+
goBack,
|
|
76
|
+
popToTop
|
|
77
|
+
} = (0, _useNavigationStack.useNavigationStack)();
|
|
78
|
+
(0, _react.useEffect)(() => {
|
|
79
|
+
_navigationStackStore.navigationStackStore.setStack(stack);
|
|
80
|
+
}, [stack]);
|
|
81
|
+
|
|
82
|
+
// Keep the action references fresh (they change as the stack changes) so a
|
|
83
|
+
// remote action always operates on the current navigation state.
|
|
84
|
+
(0, _react.useEffect)(() => {
|
|
85
|
+
_navigationStackStore.navigationStackStore.setActions({
|
|
86
|
+
navigateToIndex,
|
|
87
|
+
popToIndex,
|
|
88
|
+
goBack,
|
|
89
|
+
popToTop
|
|
90
|
+
});
|
|
91
|
+
return () => _navigationStackStore.navigationStackStore.setActions(null);
|
|
92
|
+
});
|
|
93
|
+
return null;
|
|
94
|
+
}
|
|
60
95
|
function RouteTracker() {
|
|
61
96
|
const hasExpo = (0, _sharedUi.isExpoRouterAvailable)();
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
}
|
|
65
|
-
return /*#__PURE__*/(0, _jsxRuntime.jsx)(ReactNavigationRouteTracker, {});
|
|
97
|
+
return /*#__PURE__*/(0, _jsxRuntime.jsxs)(_jsxRuntime.Fragment, {
|
|
98
|
+
children: [hasExpo ? /*#__PURE__*/(0, _jsxRuntime.jsx)(ExpoRouteTracker, {}) : /*#__PURE__*/(0, _jsxRuntime.jsx)(ReactNavigationRouteTracker, {}), /*#__PURE__*/(0, _jsxRuntime.jsx)(NavigationStackCapture, {})]
|
|
99
|
+
});
|
|
66
100
|
}
|
|
@@ -22,24 +22,34 @@ var _jsxRuntime = require("react/jsx-runtime");
|
|
|
22
22
|
// Types
|
|
23
23
|
// ============================================================================
|
|
24
24
|
|
|
25
|
+
/** Stack manipulation a host can be asked to perform on the device. */
|
|
26
|
+
|
|
25
27
|
// ============================================================================
|
|
26
28
|
// Main Component
|
|
27
29
|
// ============================================================================
|
|
28
30
|
|
|
29
31
|
function NavigationStack({
|
|
30
|
-
style
|
|
32
|
+
style,
|
|
33
|
+
injectedStack,
|
|
34
|
+
onAction
|
|
31
35
|
}) {
|
|
32
|
-
const
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
36
|
+
const hookResult = (0, _useNavigationStack.useNavigationStack)();
|
|
37
|
+
const isInjected = injectedStack != null;
|
|
38
|
+
|
|
39
|
+
// Data source: injected (dashboard) or the local navigation container.
|
|
40
|
+
const stack = isInjected ? injectedStack : hookResult.stack;
|
|
41
|
+
const isLoaded = isInjected ? true : hookResult.isLoaded;
|
|
42
|
+
const error = isInjected ? null : hookResult.error;
|
|
43
|
+
const focusedRoute = (0, _react.useMemo)(() => stack.find(item => item.isFocused) ?? null, [stack]);
|
|
44
|
+
const stackDepth = stack.length;
|
|
45
|
+
const isAtRoot = stackDepth <= 1;
|
|
46
|
+
|
|
47
|
+
// Action wrappers: delegate to the host when provided, else act locally.
|
|
48
|
+
const navigateToIndex = index => onAction ? onAction("navigateToIndex", {
|
|
49
|
+
index
|
|
50
|
+
}) : hookResult.navigateToIndex(index);
|
|
51
|
+
const goBack = () => onAction ? onAction("goBack") : hookResult.goBack();
|
|
52
|
+
const popToTop = () => onAction ? onAction("popToTop") : hookResult.popToTop();
|
|
43
53
|
const [expandedIndex, setExpandedIndex] = (0, _react.useState)(null);
|
|
44
54
|
const [showHelp, setShowHelp] = (0, _react.useState)(false);
|
|
45
55
|
const [showUpgradeModal, setShowUpgradeModal] = (0, _react.useState)(false);
|
|
@@ -128,6 +138,26 @@ function NavigationStack({
|
|
|
128
138
|
}
|
|
129
139
|
|
|
130
140
|
// Handlers
|
|
141
|
+
// Confirm a destructive action. On device we use the native Alert; when an
|
|
142
|
+
// action delegate is set (dashboard, react-native-web) Alert button presses
|
|
143
|
+
// don't fire, so fall back to window.confirm.
|
|
144
|
+
const confirmDestructive = (title, message, confirmLabel, onConfirm) => {
|
|
145
|
+
if (onAction) {
|
|
146
|
+
const confirmFn = globalThis.window?.confirm;
|
|
147
|
+
if (!confirmFn || confirmFn(`${title}\n\n${message}`)) {
|
|
148
|
+
onConfirm();
|
|
149
|
+
}
|
|
150
|
+
return;
|
|
151
|
+
}
|
|
152
|
+
_reactNative.Alert.alert(title, message, [{
|
|
153
|
+
text: "Cancel",
|
|
154
|
+
style: "cancel"
|
|
155
|
+
}, {
|
|
156
|
+
text: confirmLabel,
|
|
157
|
+
style: "destructive",
|
|
158
|
+
onPress: onConfirm
|
|
159
|
+
}]);
|
|
160
|
+
};
|
|
131
161
|
const handleGoBack = () => {
|
|
132
162
|
// Gate behind Pro
|
|
133
163
|
if (!isPro) {
|
|
@@ -150,14 +180,7 @@ function NavigationStack({
|
|
|
150
180
|
_reactNative.Alert.alert("Already at Top", "Stack only has one screen");
|
|
151
181
|
return;
|
|
152
182
|
}
|
|
153
|
-
|
|
154
|
-
text: "Cancel",
|
|
155
|
-
style: "cancel"
|
|
156
|
-
}, {
|
|
157
|
-
text: "Pop to Top",
|
|
158
|
-
style: "destructive",
|
|
159
|
-
onPress: popToTop
|
|
160
|
-
}]);
|
|
183
|
+
confirmDestructive("Pop to Top", "This will remove all screens except the root screen.", "Pop to Top", popToTop);
|
|
161
184
|
};
|
|
162
185
|
const toggleExpand = index => {
|
|
163
186
|
setExpandedIndex(expandedIndex === index ? null : index);
|
|
@@ -199,17 +222,10 @@ function NavigationStack({
|
|
|
199
222
|
return;
|
|
200
223
|
}
|
|
201
224
|
const screensToRemove = stackDepth - 1 - selectedRoute.index;
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
text: "Pop",
|
|
207
|
-
style: "destructive",
|
|
208
|
-
onPress: () => {
|
|
209
|
-
// Navigate to the selected route, which effectively pops everything above it
|
|
210
|
-
navigateToIndex(selectedRoute.index);
|
|
211
|
-
}
|
|
212
|
-
}]);
|
|
225
|
+
const targetIndex = selectedRoute.index;
|
|
226
|
+
confirmDestructive("Pop to Route", `Remove ${screensToRemove} screen${screensToRemove !== 1 ? "s" : ""} above ${selectedRoute.pathname}?`, "Pop",
|
|
227
|
+
// Navigate to the selected route, which effectively pops everything above it
|
|
228
|
+
() => navigateToIndex(targetIndex));
|
|
213
229
|
};
|
|
214
230
|
return /*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNative.View, {
|
|
215
231
|
style: [styles.container, style],
|
|
@@ -25,12 +25,30 @@ var _jsxRuntime = require("react/jsx-runtime");
|
|
|
25
25
|
// Types
|
|
26
26
|
// ============================================================================
|
|
27
27
|
|
|
28
|
+
// Synthetic route representing the app's home/index ("/"). Used by the
|
|
29
|
+
// "Home" toolbar shortcut so navigation works the same as tapping any route.
|
|
30
|
+
const HOME_ROUTE = {
|
|
31
|
+
path: "/",
|
|
32
|
+
name: "index",
|
|
33
|
+
type: "index",
|
|
34
|
+
params: [],
|
|
35
|
+
nodeType: "route",
|
|
36
|
+
contextKey: "/",
|
|
37
|
+
isInternal: false,
|
|
38
|
+
children: [],
|
|
39
|
+
depth: 0
|
|
40
|
+
};
|
|
41
|
+
|
|
28
42
|
// ============================================================================
|
|
29
43
|
// Main Component
|
|
30
44
|
// ============================================================================
|
|
31
45
|
|
|
32
46
|
function RoutesSitemap({
|
|
33
|
-
style
|
|
47
|
+
style,
|
|
48
|
+
injectedRoutes,
|
|
49
|
+
injectedSource,
|
|
50
|
+
injectedLastUpdatedAt,
|
|
51
|
+
onNavigateRoute
|
|
34
52
|
}) {
|
|
35
53
|
const [searchQuery, setSearchQuery] = (0, _react.useState)("");
|
|
36
54
|
const [isSearching, setIsSearching] = (0, _react.useState)(false);
|
|
@@ -52,6 +70,7 @@ function RoutesSitemap({
|
|
|
52
70
|
groups,
|
|
53
71
|
stats,
|
|
54
72
|
isLoaded,
|
|
73
|
+
isSupported,
|
|
55
74
|
filteredRoutes,
|
|
56
75
|
routes,
|
|
57
76
|
refresh,
|
|
@@ -59,7 +78,10 @@ function RoutesSitemap({
|
|
|
59
78
|
source
|
|
60
79
|
} = (0, _useRouteSitemap.useRouteSitemap)({
|
|
61
80
|
searchQuery,
|
|
62
|
-
sortBy: "path"
|
|
81
|
+
sortBy: "path",
|
|
82
|
+
injectedRoutes,
|
|
83
|
+
injectedSource,
|
|
84
|
+
injectedLastUpdatedAt
|
|
63
85
|
});
|
|
64
86
|
|
|
65
87
|
// Prepare copy data - memoized so it only rebuilds when dependencies change
|
|
@@ -147,6 +169,13 @@ function RoutesSitemap({
|
|
|
147
169
|
}], "plain-text");
|
|
148
170
|
}, [router]);
|
|
149
171
|
const handleNavigate = (0, _react.useCallback)(route => {
|
|
172
|
+
// When a navigation delegate is supplied (dashboard → device), hand off
|
|
173
|
+
// entirely: the delegate owns Pro gating and param resolution.
|
|
174
|
+
if (onNavigateRoute) {
|
|
175
|
+
onNavigateRoute(route);
|
|
176
|
+
return;
|
|
177
|
+
}
|
|
178
|
+
|
|
150
179
|
// Gate behind Pro
|
|
151
180
|
if (!isPro) {
|
|
152
181
|
setShowUpgradeModal(true);
|
|
@@ -182,7 +211,10 @@ function RoutesSitemap({
|
|
|
182
211
|
} catch (error) {
|
|
183
212
|
_reactNative.Alert.alert("Navigation Error", String(error));
|
|
184
213
|
}
|
|
185
|
-
}, [router, promptForParams, isPro]);
|
|
214
|
+
}, [router, promptForParams, isPro, onNavigateRoute]);
|
|
215
|
+
const handleGoHome = (0, _react.useCallback)(() => {
|
|
216
|
+
handleNavigate(HOME_ROUTE);
|
|
217
|
+
}, [handleNavigate]);
|
|
186
218
|
const handleManualRefresh = (0, _react.useCallback)(() => {
|
|
187
219
|
if (isRefreshing) return;
|
|
188
220
|
setIsRefreshing(true);
|
|
@@ -217,7 +249,7 @@ function RoutesSitemap({
|
|
|
217
249
|
style: styles.loadingContainer,
|
|
218
250
|
children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.Text, {
|
|
219
251
|
style: styles.loadingText,
|
|
220
|
-
children: "Loading routes..."
|
|
252
|
+
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
253
|
})
|
|
222
254
|
})
|
|
223
255
|
});
|
|
@@ -229,6 +261,20 @@ function RoutesSitemap({
|
|
|
229
261
|
children: [/*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNative.View, {
|
|
230
262
|
style: styles.actionsRow,
|
|
231
263
|
children: [/*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNative.View, {
|
|
264
|
+
style: styles.actionWrapper,
|
|
265
|
+
children: [/*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.TouchableOpacity, {
|
|
266
|
+
style: styles.iconButton,
|
|
267
|
+
onPress: handleGoHome,
|
|
268
|
+
accessibilityLabel: "Go to home route",
|
|
269
|
+
children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_sharedUi.Home, {
|
|
270
|
+
size: 16,
|
|
271
|
+
color: _sharedUi.buoyColors.textSecondary
|
|
272
|
+
})
|
|
273
|
+
}), /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.Text, {
|
|
274
|
+
style: styles.actionLabel,
|
|
275
|
+
children: "Home"
|
|
276
|
+
})]
|
|
277
|
+
}), /*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNative.View, {
|
|
232
278
|
style: styles.actionWrapper,
|
|
233
279
|
children: [/*#__PURE__*/(0, _jsxRuntime.jsx)(_sharedUi.ToolbarCopyButton, {
|
|
234
280
|
value: copyAllData,
|
|
@@ -432,82 +478,92 @@ function RouteItemView({
|
|
|
432
478
|
const hasParams = route.params.length > 0;
|
|
433
479
|
const typeColor = getRouteTypeColor(route.type);
|
|
434
480
|
const canNavigate = route.type !== "layout" && route.type !== "group";
|
|
435
|
-
|
|
481
|
+
|
|
482
|
+
// Leaf routes (no children) have nothing to drill into — expanding would only
|
|
483
|
+
// reveal the Copy/Go actions, so show those inline instead of behind a toggle.
|
|
484
|
+
const isExpandable = hasChildren;
|
|
485
|
+
const showDetails = isExpandable ? isExpanded : true;
|
|
486
|
+
return /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.View, {
|
|
436
487
|
style: [styles.routeItem, {
|
|
437
488
|
marginLeft: depth * 12
|
|
438
489
|
}],
|
|
439
|
-
children:
|
|
490
|
+
children: /*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNative.View, {
|
|
440
491
|
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
492
|
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
|
-
|
|
493
|
+
style: styles.routeHeader,
|
|
494
|
+
children: [isExpandable ? /*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNative.TouchableOpacity, {
|
|
495
|
+
style: styles.routeHeaderLeft,
|
|
496
|
+
onPress: () => setIsExpanded(!isExpanded),
|
|
497
|
+
activeOpacity: 0.7,
|
|
498
|
+
children: [/*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.View, {
|
|
499
|
+
style: styles.expandIndicator,
|
|
500
|
+
children: isExpanded ? /*#__PURE__*/(0, _jsxRuntime.jsx)(_sharedUi.ChevronDown, {
|
|
501
|
+
size: 14,
|
|
502
|
+
color: _sharedUi.buoyColors.textSecondary
|
|
503
|
+
}) : /*#__PURE__*/(0, _jsxRuntime.jsx)(_sharedUi.ChevronRight, {
|
|
504
|
+
size: 14,
|
|
505
|
+
color: _sharedUi.buoyColors.textSecondary
|
|
506
|
+
})
|
|
507
|
+
}), /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.Text, {
|
|
508
|
+
style: styles.routePath,
|
|
509
|
+
numberOfLines: 3,
|
|
510
|
+
children: route.path
|
|
511
|
+
})]
|
|
512
|
+
}) :
|
|
513
|
+
/*#__PURE__*/
|
|
514
|
+
// Non-toggling header for leaf routes (keeps the chevron column as a
|
|
515
|
+
// spacer so paths stay aligned with expandable siblings).
|
|
516
|
+
(0, _jsxRuntime.jsxs)(_reactNative.View, {
|
|
517
|
+
style: styles.routeHeaderLeft,
|
|
518
|
+
children: [/*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.View, {
|
|
519
|
+
style: styles.expandIndicator
|
|
520
|
+
}), /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.Text, {
|
|
521
|
+
style: styles.routePath,
|
|
522
|
+
numberOfLines: 3,
|
|
523
|
+
children: route.path
|
|
524
|
+
})]
|
|
525
|
+
}), /*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNative.View, {
|
|
526
|
+
style: styles.routeHeaderActions,
|
|
527
|
+
children: [hasChildren && /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.View, {
|
|
528
|
+
style: styles.childCountBadge,
|
|
504
529
|
children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.Text, {
|
|
505
|
-
style: styles.
|
|
506
|
-
children:
|
|
530
|
+
style: styles.childCountText,
|
|
531
|
+
children: route.children.length
|
|
507
532
|
})
|
|
508
|
-
},
|
|
533
|
+
}), /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.View, {
|
|
534
|
+
style: [styles.typeTag, {
|
|
535
|
+
backgroundColor: `${typeColor}15`,
|
|
536
|
+
borderColor: `${typeColor}40`
|
|
537
|
+
}],
|
|
538
|
+
children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.Text, {
|
|
539
|
+
style: [styles.typeText, {
|
|
540
|
+
color: typeColor
|
|
541
|
+
}],
|
|
542
|
+
children: route.type.toUpperCase()
|
|
543
|
+
})
|
|
544
|
+
}), /*#__PURE__*/(0, _jsxRuntime.jsx)(_sharedUi.InlineCopyButton, {
|
|
545
|
+
value: route.path,
|
|
546
|
+
buttonStyle: styles.iconAction
|
|
547
|
+
}), canNavigate && /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.TouchableOpacity, {
|
|
548
|
+
style: styles.goButton,
|
|
549
|
+
onPress: () => onNavigate(route),
|
|
550
|
+
activeOpacity: 0.7,
|
|
551
|
+
children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.Text, {
|
|
552
|
+
style: styles.goButtonText,
|
|
553
|
+
children: "Go"
|
|
554
|
+
})
|
|
555
|
+
})]
|
|
509
556
|
})]
|
|
510
|
-
}),
|
|
557
|
+
}), showDetails && hasParams && /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.View, {
|
|
558
|
+
style: styles.paramsRow,
|
|
559
|
+
children: route.params.map(param => /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.View, {
|
|
560
|
+
style: styles.paramTag,
|
|
561
|
+
children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.Text, {
|
|
562
|
+
style: styles.paramText,
|
|
563
|
+
children: param
|
|
564
|
+
})
|
|
565
|
+
}, param))
|
|
566
|
+
}), showDetails && hasChildren && /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.View, {
|
|
511
567
|
style: styles.childrenContainer,
|
|
512
568
|
children: route.children.map((child, index) => /*#__PURE__*/(0, _jsxRuntime.jsx)(RouteItemView, {
|
|
513
569
|
route: child,
|
|
@@ -515,7 +571,7 @@ function RouteItemView({
|
|
|
515
571
|
onNavigate: onNavigate
|
|
516
572
|
}, `${child.path}-${index}`))
|
|
517
573
|
})]
|
|
518
|
-
})
|
|
574
|
+
})
|
|
519
575
|
});
|
|
520
576
|
}
|
|
521
577
|
|
|
@@ -569,7 +625,11 @@ const styles = _reactNative.StyleSheet.create({
|
|
|
569
625
|
loadingText: {
|
|
570
626
|
color: _sharedUi.buoyColors.textSecondary,
|
|
571
627
|
fontSize: 14,
|
|
572
|
-
fontFamily: "monospace"
|
|
628
|
+
fontFamily: "monospace",
|
|
629
|
+
textAlign: "center",
|
|
630
|
+
lineHeight: 20,
|
|
631
|
+
paddingHorizontal: 32,
|
|
632
|
+
maxWidth: 420
|
|
573
633
|
},
|
|
574
634
|
header: {
|
|
575
635
|
flexDirection: "column",
|
|
@@ -581,7 +641,7 @@ const styles = _reactNative.StyleSheet.create({
|
|
|
581
641
|
actionsRow: {
|
|
582
642
|
flexDirection: "row",
|
|
583
643
|
alignItems: "center",
|
|
584
|
-
justifyContent: "
|
|
644
|
+
justifyContent: "space-between",
|
|
585
645
|
gap: 12,
|
|
586
646
|
paddingBottom: 4
|
|
587
647
|
},
|
|
@@ -616,6 +676,7 @@ const styles = _reactNative.StyleSheet.create({
|
|
|
616
676
|
letterSpacing: 0.5
|
|
617
677
|
},
|
|
618
678
|
actionWrapper: {
|
|
679
|
+
flex: 1,
|
|
619
680
|
alignItems: "center",
|
|
620
681
|
justifyContent: "center",
|
|
621
682
|
gap: 4,
|
|
@@ -783,15 +844,11 @@ const styles = _reactNative.StyleSheet.create({
|
|
|
783
844
|
marginBottom: 6
|
|
784
845
|
},
|
|
785
846
|
routeCard: {
|
|
786
|
-
flexDirection: "row",
|
|
787
|
-
alignItems: "center",
|
|
788
|
-
justifyContent: "space-between",
|
|
789
|
-
paddingVertical: 10,
|
|
790
|
-
paddingHorizontal: 12,
|
|
791
847
|
backgroundColor: _sharedUi.buoyColors.card,
|
|
792
848
|
borderRadius: 6,
|
|
793
849
|
borderWidth: 1,
|
|
794
850
|
borderColor: _sharedUi.buoyColors.border,
|
|
851
|
+
overflow: "hidden",
|
|
795
852
|
shadowColor: "#000",
|
|
796
853
|
shadowOffset: {
|
|
797
854
|
width: 0,
|
|
@@ -801,8 +858,16 @@ const styles = _reactNative.StyleSheet.create({
|
|
|
801
858
|
shadowRadius: 2,
|
|
802
859
|
elevation: 1
|
|
803
860
|
},
|
|
861
|
+
routeHeader: {
|
|
862
|
+
flexDirection: "row",
|
|
863
|
+
alignItems: "center",
|
|
864
|
+
justifyContent: "space-between",
|
|
865
|
+
paddingVertical: 7,
|
|
866
|
+
paddingHorizontal: 10,
|
|
867
|
+
gap: 8
|
|
868
|
+
},
|
|
804
869
|
expandIndicator: {
|
|
805
|
-
width:
|
|
870
|
+
width: 18,
|
|
806
871
|
alignItems: "center"
|
|
807
872
|
},
|
|
808
873
|
routeHeaderLeft: {
|
|
@@ -851,34 +916,41 @@ const styles = _reactNative.StyleSheet.create({
|
|
|
851
916
|
fontWeight: "600",
|
|
852
917
|
fontFamily: "monospace"
|
|
853
918
|
},
|
|
854
|
-
|
|
855
|
-
|
|
856
|
-
|
|
857
|
-
|
|
858
|
-
|
|
859
|
-
|
|
860
|
-
borderTopColor: _sharedUi.buoyColors.border,
|
|
861
|
-
backgroundColor: _sharedUi.buoyColors.card,
|
|
862
|
-
borderRadius: 6,
|
|
919
|
+
// Compact icon-sized Copy button in the header action cluster.
|
|
920
|
+
iconAction: {
|
|
921
|
+
width: 28,
|
|
922
|
+
height: 24,
|
|
923
|
+
borderRadius: 4,
|
|
924
|
+
backgroundColor: _sharedUi.buoyColors.input,
|
|
863
925
|
borderWidth: 1,
|
|
864
926
|
borderColor: _sharedUi.buoyColors.border,
|
|
865
|
-
|
|
866
|
-
|
|
867
|
-
marginTop: -6
|
|
927
|
+
alignItems: "center",
|
|
928
|
+
justifyContent: "center"
|
|
868
929
|
},
|
|
869
|
-
|
|
870
|
-
|
|
930
|
+
// Small "Go" pill in the header action cluster.
|
|
931
|
+
goButton: {
|
|
932
|
+
height: 24,
|
|
933
|
+
paddingHorizontal: 10,
|
|
934
|
+
borderRadius: 4,
|
|
935
|
+
alignItems: "center",
|
|
936
|
+
justifyContent: "center",
|
|
937
|
+
backgroundColor: _sharedUi.buoyColors.primary + "15",
|
|
938
|
+
borderWidth: 1,
|
|
939
|
+
borderColor: _sharedUi.buoyColors.primary + "40"
|
|
871
940
|
},
|
|
872
|
-
|
|
873
|
-
fontSize:
|
|
874
|
-
color: _sharedUi.buoyColors.
|
|
941
|
+
goButtonText: {
|
|
942
|
+
fontSize: 12,
|
|
943
|
+
color: _sharedUi.buoyColors.primary,
|
|
875
944
|
fontFamily: "monospace",
|
|
876
|
-
|
|
945
|
+
fontWeight: "600"
|
|
877
946
|
},
|
|
878
947
|
paramsRow: {
|
|
879
948
|
flexDirection: "row",
|
|
880
949
|
flexWrap: "wrap",
|
|
881
|
-
gap: 6
|
|
950
|
+
gap: 6,
|
|
951
|
+
paddingHorizontal: 10,
|
|
952
|
+
paddingTop: 2,
|
|
953
|
+
paddingBottom: 8
|
|
882
954
|
},
|
|
883
955
|
paramTag: {
|
|
884
956
|
backgroundColor: "#F59E0B15",
|
|
@@ -894,41 +966,12 @@ const styles = _reactNative.StyleSheet.create({
|
|
|
894
966
|
fontFamily: "monospace",
|
|
895
967
|
fontWeight: "600"
|
|
896
968
|
},
|
|
897
|
-
routeButtons: {
|
|
898
|
-
flexDirection: "row",
|
|
899
|
-
gap: 6,
|
|
900
|
-
marginBottom: 12
|
|
901
|
-
},
|
|
902
|
-
actionButton: {
|
|
903
|
-
flexDirection: "row",
|
|
904
|
-
alignItems: "center",
|
|
905
|
-
gap: 4,
|
|
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: {
|
|
920
|
-
backgroundColor: _sharedUi.buoyColors.primary + "15",
|
|
921
|
-
borderColor: _sharedUi.buoyColors.primary + "40"
|
|
922
|
-
},
|
|
923
|
-
navigateButtonText: {
|
|
924
|
-
fontSize: 12,
|
|
925
|
-
color: _sharedUi.buoyColors.primary,
|
|
926
|
-
fontFamily: "monospace",
|
|
927
|
-
fontWeight: "600"
|
|
928
|
-
},
|
|
929
969
|
childrenContainer: {
|
|
930
970
|
borderLeftWidth: 2,
|
|
931
971
|
borderLeftColor: _sharedUi.buoyColors.border,
|
|
932
|
-
marginLeft: 16
|
|
972
|
+
marginLeft: 16,
|
|
973
|
+
marginRight: 8,
|
|
974
|
+
marginTop: 2,
|
|
975
|
+
marginBottom: 8
|
|
933
976
|
}
|
|
934
977
|
});
|
|
@@ -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");
|