@buoy-gg/route-events 7.0.32 → 7.0.34

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (33) hide show
  1. package/lib/commonjs/RouteTracker.js +2 -0
  2. package/lib/commonjs/components/NavigationStack.js +4 -10
  3. package/lib/commonjs/components/RouteEventsModalWithTabs.js +36 -117
  4. package/lib/commonjs/components/RouteEventsTimeline.js +2 -11
  5. package/lib/commonjs/components/RoutesSitemap.js +8 -8
  6. package/lib/commonjs/hooks/useRouteEvents.js +12 -43
  7. package/lib/commonjs/preset.js +7 -21
  8. package/lib/commonjs/sync/routeEventsSyncAdapter.js +19 -1
  9. package/lib/commonjs/useNavigationStack.js +27 -0
  10. package/lib/module/RouteTracker.js +2 -0
  11. package/lib/module/components/NavigationStack.js +5 -11
  12. package/lib/module/components/RouteEventsModalWithTabs.js +38 -119
  13. package/lib/module/components/RouteEventsTimeline.js +3 -12
  14. package/lib/module/components/RoutesSitemap.js +9 -9
  15. package/lib/module/hooks/useRouteEvents.js +12 -43
  16. package/lib/module/preset.js +6 -19
  17. package/lib/module/sync/routeEventsSyncAdapter.js +19 -1
  18. package/lib/module/useNavigationStack.js +27 -0
  19. package/lib/typescript/RouteTracker.d.ts.map +1 -1
  20. package/lib/typescript/components/NavigationStack.d.ts.map +1 -1
  21. package/lib/typescript/components/RouteEventsModalWithTabs.d.ts.map +1 -1
  22. package/lib/typescript/components/RouteEventsTimeline.d.ts.map +1 -1
  23. package/lib/typescript/components/RoutesSitemap.d.ts.map +1 -1
  24. package/lib/typescript/hooks/useRouteEvents.d.ts.map +1 -1
  25. package/lib/typescript/preset.d.ts +2 -8
  26. package/lib/typescript/preset.d.ts.map +1 -1
  27. package/lib/typescript/stores/navigationStackStore.d.ts +2 -0
  28. package/lib/typescript/stores/navigationStackStore.d.ts.map +1 -1
  29. package/lib/typescript/sync/routeEventsSyncAdapter.d.ts +5 -0
  30. package/lib/typescript/sync/routeEventsSyncAdapter.d.ts.map +1 -1
  31. package/lib/typescript/useNavigationStack.d.ts +7 -0
  32. package/lib/typescript/useNavigationStack.d.ts.map +1 -1
  33. package/package.json +5 -5
@@ -71,6 +71,7 @@ function NavigationStackCapture() {
71
71
  const {
72
72
  stack,
73
73
  navigateToIndex,
74
+ navigateToRoute,
74
75
  popToIndex,
75
76
  goBack,
76
77
  popToTop
@@ -84,6 +85,7 @@ function NavigationStackCapture() {
84
85
  (0, _react.useEffect)(() => {
85
86
  _navigationStackStore.navigationStackStore.setActions({
86
87
  navigateToIndex,
88
+ navigateToRoute,
87
89
  popToIndex,
88
90
  goBack,
89
91
  popToTop
@@ -140,17 +140,11 @@ function NavigationStack({
140
140
  if (stack.length === 0) {
141
141
  return /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.View, {
142
142
  style: [styles.container, style],
143
- children: /*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNative.View, {
144
- style: styles.emptyContainer,
143
+ children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_sharedUi.ToolEmptyState, {
145
144
  testID: "buoy-routes-stack-empty",
146
- children: [/*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.Text, {
147
- style: styles.emptyText,
148
- testID: "buoy-routes-stack-empty-text",
149
- children: "No navigation stack"
150
- }), /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.Text, {
151
- style: styles.emptySubtext,
152
- children: "Navigate to a route to see the stack"
153
- })]
145
+ otto: "walking",
146
+ title: "No navigation stack",
147
+ message: "Navigate to a route to see the stack"
154
148
  })
155
149
  });
156
150
  }
@@ -25,6 +25,23 @@ const CommonActions = (0, _safeReactNavigation.getCommonActions)();
25
25
 
26
26
  // Free tier limit for route events
27
27
 
28
+ /** Persistence recipes: the tab is stored as its bare name, the flag as "true"/"false". */
29
+ const TAB_PERSISTENCE = {
30
+ // Every tab the selector offers, including "stack": the save side has
31
+ // always written it, so leaving it off this list meant the Stack tab
32
+ // was persisted and then silently discarded on the next launch.
33
+ parse: raw => raw === "routes" || raw === "events" || raw === "stack" ? raw : undefined,
34
+ serialize: tab => tab
35
+ };
36
+ const BOOLEAN_PERSISTENCE = {
37
+ parse: raw => raw === "true",
38
+ serialize: value => value.toString()
39
+ };
40
+ const STRING_SET_PERSISTENCE = {
41
+ parse: raw => new Set(JSON.parse(raw)),
42
+ serialize: set => JSON.stringify(Array.from(set))
43
+ };
44
+
28
45
  /**
29
46
  * Find the path from root navigation state to a screen by name.
30
47
  * Returns array of route names from root to the target, or null if not found.
@@ -85,7 +102,7 @@ function RouteEventsModalWithTabs({
85
102
  const router = (0, _sharedUi.useSafeRouter)();
86
103
  const containerRef = (0, _safeReactNavigation.useSafeNavigationContainerRef)();
87
104
  const hasExpoRouter = (0, _sharedUi.isExpoRouterAvailable)();
88
- const [activeTab, setActiveTab] = (0, _react.useState)("events");
105
+ const [activeTab, setActiveTab] = (0, _sharedUi.usePersistedState)(_sharedUi.devToolsStorageKeys.routeEvents.activeTab(), "events", TAB_PERSISTENCE);
89
106
  const [showUpgradeModal, setShowUpgradeModal] = (0, _react.useState)(false);
90
107
  // Serialized stack reported up by NavigationStack so the copy button can live
91
108
  // in the shared navbar.
@@ -107,7 +124,7 @@ function RouteEventsModalWithTabs({
107
124
  // See the RouteTracker component export for easy setup.
108
125
 
109
126
  // Local state to control subscription (true = subscribed, false = unsubscribed)
110
- const [isListeningEnabled, setIsListeningEnabled] = (0, _react.useState)(true);
127
+ const [isListeningEnabled, setIsListeningEnabled] = (0, _sharedUi.usePersistedState)(_sharedUi.devToolsStorageKeys.routeEvents.isMonitoring(), true, BOOLEAN_PERSISTENCE);
111
128
 
112
129
  // Event Listener state - using centralized store via hook
113
130
  // Pass enabled option to control subscription
@@ -127,11 +144,8 @@ function RouteEventsModalWithTabs({
127
144
  const [selectedEvent, setSelectedEvent] = (0, _react.useState)(null);
128
145
  const [selectedVisitNumber, setSelectedVisitNumber] = (0, _react.useState)(1);
129
146
  const [searchQuery, setSearchQuery] = (0, _react.useState)("");
130
- const [ignoredPatterns, setIgnoredPatterns] = (0, _react.useState)(new Set(["/_sitemap", "/api", "/__dev"]));
147
+ const [ignoredPatterns, setIgnoredPatterns] = (0, _sharedUi.usePersistedState)(_sharedUi.devToolsStorageKeys.routeEvents.eventFilters(), new Set(["/_sitemap", "/api", "/__dev"]), STRING_SET_PERSISTENCE);
131
148
  const lastEventRef = (0, _react.useRef)(null);
132
- const hasLoadedFilters = (0, _react.useRef)(false);
133
- const hasLoadedTabState = (0, _react.useRef)(false);
134
- const hasLoadedMonitoringState = (0, _react.useRef)(false);
135
149
  const handleModeChange = (0, _react.useCallback)(_mode => {
136
150
  // Mode changes handled by JsModal
137
151
  }, []);
@@ -183,103 +197,6 @@ function RouteEventsModalWithTabs({
183
197
  }
184
198
  }, [router, containerRef, hasExpoRouter, remote, isPro]);
185
199
 
186
- // Load persisted tab state on mount
187
- (0, _react.useEffect)(() => {
188
- if (!visible || hasLoadedTabState.current) return;
189
- const loadTabState = async () => {
190
- try {
191
- const storedTab = await _sharedUi.persistentStorage.getItem(_sharedUi.devToolsStorageKeys.routeEvents.activeTab());
192
- // Every tab the selector offers, including "stack": the save side has
193
- // always written it, so leaving it off this list meant the Stack tab
194
- // was persisted and then silently discarded on the next launch —
195
- // you came back to Events having chosen otherwise.
196
- if (storedTab === "routes" || storedTab === "events" || storedTab === "stack") {
197
- setActiveTab(storedTab);
198
- }
199
- hasLoadedTabState.current = true;
200
- } catch (error) {
201
- // Failed to load tab state
202
- }
203
- };
204
- loadTabState();
205
- }, [visible]);
206
-
207
- // Load persisted monitoring state on mount
208
- (0, _react.useEffect)(() => {
209
- if (!visible || hasLoadedMonitoringState.current) return;
210
- const loadMonitoringState = async () => {
211
- try {
212
- const storedMonitoring = await _sharedUi.persistentStorage.getItem(_sharedUi.devToolsStorageKeys.routeEvents.isMonitoring());
213
- if (storedMonitoring !== null) {
214
- const shouldMonitor = storedMonitoring === "true";
215
- setIsListeningEnabled(shouldMonitor);
216
- }
217
- hasLoadedMonitoringState.current = true;
218
- } catch (error) {
219
- // Failed to load monitoring state
220
- }
221
- };
222
- loadMonitoringState();
223
- }, [visible]);
224
-
225
- // Save tab state when it changes
226
- (0, _react.useEffect)(() => {
227
- if (!hasLoadedTabState.current) return;
228
- const saveTabState = async () => {
229
- try {
230
- await _sharedUi.persistentStorage.setItem(_sharedUi.devToolsStorageKeys.routeEvents.activeTab(), activeTab);
231
- } catch (error) {
232
- // Failed to save tab state
233
- }
234
- };
235
- saveTabState();
236
- }, [activeTab]);
237
-
238
- // Save monitoring state when it changes
239
- (0, _react.useEffect)(() => {
240
- if (!hasLoadedMonitoringState.current) return;
241
- const saveMonitoringState = async () => {
242
- try {
243
- await _sharedUi.persistentStorage.setItem(_sharedUi.devToolsStorageKeys.routeEvents.isMonitoring(), isListening.toString());
244
- } catch (error) {
245
- // Failed to save monitoring state
246
- }
247
- };
248
- saveMonitoringState();
249
- }, [isListening]);
250
-
251
- // Load persisted filters on mount
252
- (0, _react.useEffect)(() => {
253
- if (!visible || hasLoadedFilters.current) return;
254
- const loadFilters = async () => {
255
- try {
256
- const storedFilters = await _sharedUi.persistentStorage.getItem(_sharedUi.devToolsStorageKeys.routeEvents.eventFilters());
257
- if (storedFilters) {
258
- const filters = JSON.parse(storedFilters);
259
- setIgnoredPatterns(new Set(filters));
260
- }
261
- hasLoadedFilters.current = true;
262
- } catch (error) {
263
- // Failed to load filters
264
- }
265
- };
266
- loadFilters();
267
- }, [visible]);
268
-
269
- // Save filters when they change
270
- (0, _react.useEffect)(() => {
271
- if (!hasLoadedFilters.current) return;
272
- const saveFilters = async () => {
273
- try {
274
- const filters = Array.from(ignoredPatterns);
275
- await _sharedUi.persistentStorage.setItem(_sharedUi.devToolsStorageKeys.routeEvents.eventFilters(), JSON.stringify(filters));
276
- } catch (error) {
277
- // Failed to save filters
278
- }
279
- };
280
- saveFilters();
281
- }, [ignoredPatterns]);
282
-
283
200
  // Event listener is now managed by useRouteEvents hook
284
201
 
285
202
  const handleToggleListening = (0, _react.useCallback)(() => {
@@ -473,21 +390,23 @@ function RouteEventsModalWithTabs({
473
390
  placeholder: "Search pathname or params...",
474
391
  testID: "buoy-routes-search"
475
392
  })
476
- }), /*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNative.View, {
477
- style: styles.emptyState,
393
+ }), /*#__PURE__*/(0, _jsxRuntime.jsx)(_sharedUi.ToolEmptyState, {
478
394
  testID: "buoy-routes-empty",
479
- children: [/*#__PURE__*/(0, _jsxRuntime.jsx)(_sharedUi.Navigation, {
480
- size: 48,
481
- color: _sharedUi.night.color.textTertiary
482
- }), /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.Text, {
483
- style: styles.emptyTitle,
484
- testID: "buoy-routes-empty-title",
485
- children: searchQuery.trim() ? "No matching events" : isListening ? "No route events yet" : "Event listener is paused"
486
- }), /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.Text, {
487
- style: styles.emptySubtitle,
488
- testID: "buoy-routes-empty-subtitle",
489
- children: searchQuery.trim() ? "Try a different search term" : isListening ? "Navigation events will appear here" : "Press play to start monitoring"
490
- })]
395
+ ...(0, _sharedUi.resolveListEmptyState)({
396
+ subject: "route events",
397
+ search: searchQuery,
398
+ total: events.length,
399
+ capturing: isListening,
400
+ waiting: {
401
+ otto: "walking",
402
+ title: "No route events yet",
403
+ message: "Navigation events will appear here"
404
+ },
405
+ paused: {
406
+ title: "Event listener is paused",
407
+ message: "Press play to start monitoring"
408
+ }
409
+ })
491
410
  })]
492
411
  });
493
412
  }
@@ -73,17 +73,8 @@ function RouteEventsTimeline({
73
73
  onPress: handleItemPress,
74
74
  onNavigate: onNavigate
75
75
  }),
76
- showsVerticalScrollIndicator: true
77
- // Clipped cells fail Detox's hittability check even when they are on
78
- // screen, so the e2e bundle keeps every mounted row targetable. The
79
- // env var is inlined at bundle time; guarded so a non-inlining bundler
80
- // keeps production behaviour.
81
- ,
82
- removeClippedSubviews: !(typeof process !== "undefined" && process.env?.EXPO_PUBLIC_E2E),
83
- initialNumToRender: 12,
84
- maxToRenderPerBatch: 8,
85
- windowSize: 5,
86
- updateCellsBatchingPeriod: 50
76
+ showsVerticalScrollIndicator: true,
77
+ ..._sharedUi.EVENT_LIST_PRESET
87
78
  })
88
79
  );
89
80
  }
@@ -408,14 +408,14 @@ function RoutesSitemap({
408
408
  id: "groups"
409
409
  })]
410
410
  })]
411
- }), displayGroups.length === 0 ? /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.View, {
412
- style: styles.emptyState,
413
- testID: "buoy-routes-sitemap-empty",
414
- children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.Text, {
415
- style: styles.emptyText,
416
- testID: "buoy-routes-sitemap-empty-text",
417
- children: "No routes found"
418
- })
411
+ }), displayGroups.length === 0 ? /*#__PURE__*/(0, _jsxRuntime.jsx)(_sharedUi.ToolEmptyState, {
412
+ testID: "buoy-routes-sitemap-empty"
413
+ // map = "route inspector; where am I in the navigator" — the one
414
+ // OTTO_USES sentence written for this screen.
415
+ ,
416
+ otto: "map",
417
+ title: "No routes found",
418
+ message: "Nothing in the router matches. Clear the search to see the whole tree."
419
419
  }) : displayGroups.map(group => /*#__PURE__*/(0, _jsxRuntime.jsx)(RouteGroupView, {
420
420
  group: group,
421
421
  isExpanded: searchQuery.length > 0 || expandedGroups.has(group.title),
@@ -4,7 +4,7 @@ Object.defineProperty(exports, "__esModule", {
4
4
  value: true
5
5
  });
6
6
  exports.useRouteEvents = useRouteEvents;
7
- var _react = require("react");
7
+ var _sharedUi = require("@buoy-gg/shared-ui");
8
8
  var _routeEventStore = require("../stores/routeEventStore");
9
9
  /**
10
10
  * useRouteEvents Hook
@@ -39,50 +39,19 @@ function useRouteEvents(options = {}) {
39
39
  maxEvents = 500,
40
40
  enabled = true
41
41
  } = options;
42
- const [events, setEvents] = (0, _react.useState)([]);
43
- // Track listening state locally so it updates reactively with the subscription
44
- const [isListening, setIsListening] = (0, _react.useState)(enabled);
45
-
46
- // Subscribe to store - this automatically starts/stops listening
47
- // based on subscriber count (Subscribable pattern from TanStack Query)
48
- // Only subscribe when enabled is true
49
- (0, _react.useEffect)(() => {
50
- if (!enabled) {
51
- setIsListening(false);
52
- return;
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;
59
- const unsubscribe = _routeEventStore.routeEventStore.subscribeToEvents(allEvents => {
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
- });
69
- });
70
-
71
- // Mark as listening after successful subscription
72
- setIsListening(true);
73
- return () => {
74
- unsubscribe();
75
- if (rafId != null) cancelAnimationFrame(rafId);
76
- // Note: Don't set isListening=false here because we might be
77
- // re-subscribing due to dependency change, not actually stopping
78
- };
79
- }, [maxEvents, enabled]);
80
- const clearEvents = (0, _react.useCallback)(() => {
81
- _routeEventStore.routeEventStore.clearEvents();
82
- }, []);
42
+ // Subscribing auto-starts the route observer (Subscribable pattern), and
43
+ // the shared hook frame-coalesces navigation bursts into one commit.
44
+ const {
45
+ events,
46
+ clearEvents,
47
+ isActive
48
+ } = (0, _sharedUi.useEventStoreEvents)(_routeEventStore.routeEventStore, {
49
+ maxEvents,
50
+ enabled
51
+ });
83
52
  return {
84
53
  events,
85
54
  clearEvents,
86
- isListening
55
+ isListening: isActive
87
56
  };
88
57
  }
@@ -3,10 +3,10 @@
3
3
  Object.defineProperty(exports, "__esModule", {
4
4
  value: true
5
5
  });
6
- exports.createRouteEventsTool = createRouteEventsTool;
7
- exports.routeEventsToolPreset = void 0;
6
+ exports.routeEventsToolPreset = exports.createRouteEventsTool = void 0;
8
7
  var _floatingToolsCore = require("@buoy-gg/floating-tools-core");
9
8
  var _RouteEventsModalWithTabs = require("./components/RouteEventsModalWithTabs");
9
+ var _sharedUi = require("@buoy-gg/shared-ui");
10
10
  var _jsxRuntime = require("react/jsx-runtime");
11
11
  /**
12
12
  * Pre-configured route events tool for FloatingDevTools
@@ -33,7 +33,7 @@ var _jsxRuntime = require("react/jsx-runtime");
33
33
  * - Navigation stack visualization
34
34
  * - Automatic route tracking (no setup needed)
35
35
  */
36
- const routeEventsToolPreset = exports.routeEventsToolPreset = {
36
+ const routeEventsToolPreset = exports.routeEventsToolPreset = (0, _sharedUi.defineToolPreset)({
37
37
  id: "route-events",
38
38
  name: "ROUTES",
39
39
  description: "Route tracking & navigation inspector",
@@ -47,7 +47,7 @@ const routeEventsToolPreset = exports.routeEventsToolPreset = {
47
47
  props: {
48
48
  enableSharedModalDimensions: false
49
49
  }
50
- };
50
+ });
51
51
 
52
52
  /**
53
53
  * Create a custom route events tool configuration.
@@ -64,20 +64,6 @@ const routeEventsToolPreset = exports.routeEventsToolPreset = {
64
64
  * });
65
65
  * ```
66
66
  */
67
- function createRouteEventsTool(options) {
68
- return {
69
- id: options?.id || "route-events",
70
- name: options?.name || "ROUTES",
71
- description: options?.description || "Route tracking & navigation inspector",
72
- slot: "both",
73
- icon: ({
74
- size
75
- }) => /*#__PURE__*/(0, _jsxRuntime.jsx)(_floatingToolsCore.RoutesIcon, {
76
- size: size
77
- }),
78
- component: _RouteEventsModalWithTabs.RouteEventsModalWithTabs,
79
- props: {
80
- enableSharedModalDimensions: options?.enableSharedModalDimensions !== undefined ? options.enableSharedModalDimensions : false
81
- }
82
- };
83
- }
67
+ const createRouteEventsTool = exports.createRouteEventsTool = (0, _sharedUi.createToolFactory)(routeEventsToolPreset, options => ({
68
+ enableSharedModalDimensions: options.enableSharedModalDimensions ?? false
69
+ }));
@@ -173,7 +173,25 @@ const routeEventsSyncAdapter = exports.routeEventsSyncAdapter = {
173
173
  }
174
174
  const router = (0, _sharedUi.getSafeRouter)();
175
175
  if (!router) {
176
- throw new Error("expo-router is not available on this device");
176
+ // Bare React Navigation: no paths, but the tracker captured the
177
+ // container ref, so navigate by SCREEN NAME — "/Settings" and
178
+ // "Settings" both resolve, and nested navigators are walked via the
179
+ // root state. This is half the market; "throw off expo-router" made
180
+ // navigate a dead verb for every RN CLI app.
181
+ const actions = _navigationStackStore.navigationStackStore.getActions();
182
+ const name = path.replace(/^\//, "");
183
+ if (!actions?.navigateToRoute || !name) {
184
+ throw new Error("expo-router is not available here and no navigation container was captured — is <RouteTracker /> mounted inside your NavigationContainer?");
185
+ }
186
+ const ok = actions.navigateToRoute(name, p?.params);
187
+ if (!ok) {
188
+ throw new Error(`Could not navigate to "${name}" — no navigation container is live.`);
189
+ }
190
+ return {
191
+ navigated: path,
192
+ replaced: false,
193
+ via: "react-navigation"
194
+ };
177
195
  }
178
196
  // Push by default so navigate-then-back flows keep working. Callers that
179
197
  // mean "leave this screen" (sitemap Go, agents resetting to home) pass
@@ -282,6 +282,32 @@ function useNavigationStack() {
282
282
  console.error("Failed to navigate:", err);
283
283
  }
284
284
  }, [stack, containerRef]);
285
+ const navigateToRoute = (0, _react.useCallback)((name, params) => {
286
+ if (!containerRef) return false;
287
+ try {
288
+ // Deep path first, so screens inside nested navigators resolve even
289
+ // when their navigator isn't mounted yet.
290
+ const rootState = containerRef.getRootState?.();
291
+ if (!params && rootState) {
292
+ const path = findScreenPath(rootState, name);
293
+ if (path) {
294
+ const action = buildNestedNavigateAction(path);
295
+ if (action) {
296
+ containerRef.dispatch(action);
297
+ return true;
298
+ }
299
+ }
300
+ }
301
+ containerRef.dispatch(CommonActions.navigate({
302
+ name,
303
+ params
304
+ }));
305
+ return true;
306
+ } catch (err) {
307
+ console.error("Failed to navigate:", err);
308
+ return false;
309
+ }
310
+ }, [containerRef]);
285
311
  const popToIndex = (0, _react.useCallback)(index => {
286
312
  if (index >= stack.length || index < 0) return;
287
313
  const currentIndex = stack.length - 1;
@@ -336,6 +362,7 @@ function useNavigationStack() {
336
362
  error,
337
363
  refresh,
338
364
  navigateToIndex,
365
+ navigateToRoute,
339
366
  popToIndex,
340
367
  goBack,
341
368
  popToTop
@@ -67,6 +67,7 @@ function NavigationStackCapture() {
67
67
  const {
68
68
  stack,
69
69
  navigateToIndex,
70
+ navigateToRoute,
70
71
  popToIndex,
71
72
  goBack,
72
73
  popToTop
@@ -80,6 +81,7 @@ function NavigationStackCapture() {
80
81
  useEffect(() => {
81
82
  navigationStackStore.setActions({
82
83
  navigateToIndex,
84
+ navigateToRoute,
83
85
  popToIndex,
84
86
  goBack,
85
87
  popToTop
@@ -9,7 +9,7 @@
9
9
 
10
10
  import { useState, useMemo, useEffect } from "react";
11
11
  import { View, Text, ScrollView, TouchableOpacity, StyleSheet, Alert } from "react-native";
12
- import { ChevronDown, ChevronRight, InlineCopyButton, ProUpgradeModal, buoyColors, night, useSafeAreaInsets } from "@buoy-gg/shared-ui";
12
+ import { ChevronDown, ChevronRight, InlineCopyButton, ProUpgradeModal, buoyColors, night, useSafeAreaInsets, ToolEmptyState } from "@buoy-gg/shared-ui";
13
13
  import { useIsPro } from "@buoy-gg/license";
14
14
  import { DataViewer } from "@buoy-gg/shared-ui/dataViewer";
15
15
  import { useNavigationStack } from "../useNavigationStack";
@@ -136,17 +136,11 @@ export function NavigationStack({
136
136
  if (stack.length === 0) {
137
137
  return /*#__PURE__*/_jsx(View, {
138
138
  style: [styles.container, style],
139
- children: /*#__PURE__*/_jsxs(View, {
140
- style: styles.emptyContainer,
139
+ children: /*#__PURE__*/_jsx(ToolEmptyState, {
141
140
  testID: "buoy-routes-stack-empty",
142
- children: [/*#__PURE__*/_jsx(Text, {
143
- style: styles.emptyText,
144
- testID: "buoy-routes-stack-empty-text",
145
- children: "No navigation stack"
146
- }), /*#__PURE__*/_jsx(Text, {
147
- style: styles.emptySubtext,
148
- children: "Navigate to a route to see the stack"
149
- })]
141
+ otto: "walking",
142
+ title: "No navigation stack",
143
+ message: "Navigate to a route to see the stack"
150
144
  })
151
145
  });
152
146
  }
@@ -8,8 +8,8 @@ import { getCommonActions, useSafeNavigationContainerRef } from "../utils/safeRe
8
8
  // (useSafeNavigationContainerRef then yields undefined, so the dispatch
9
9
  // paths below never execute).
10
10
  const CommonActions = getCommonActions();
11
- import { useSafeRouter, isExpoRouterAvailable, windowDragProps } from "@buoy-gg/shared-ui";
12
- import { JsModal, ModalHeader, TabSelector, formatRelativeTime, devToolsStorageKeys, Navigation, Trash2, Filter, SearchBar, persistentStorage, ToolbarCopyButton, Lock, ProUpgradeModal, PowerToggleButton, buoyColors, night, TickProvider, useLimit } from "@buoy-gg/shared-ui";
11
+ import { useSafeRouter, isExpoRouterAvailable, windowDragProps, ToolEmptyState, resolveListEmptyState, usePersistedState } from "@buoy-gg/shared-ui";
12
+ import { JsModal, ModalHeader, TabSelector, formatRelativeTime, devToolsStorageKeys, Trash2, Filter, SearchBar, ToolbarCopyButton, Lock, ProUpgradeModal, PowerToggleButton, buoyColors, night, TickProvider, useLimit } from "@buoy-gg/shared-ui";
13
13
  import { useIsPro } from "@buoy-gg/license";
14
14
 
15
15
  // Free tier limit for route events
@@ -22,6 +22,23 @@ import { ReactNavigationRoutes } from "./ReactNavigationRoutes";
22
22
  import { NavigationStack } from "./NavigationStack";
23
23
  import { RouteEventsTimeline } from "./RouteEventsTimeline";
24
24
  import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
25
+ /** Persistence recipes: the tab is stored as its bare name, the flag as "true"/"false". */
26
+ const TAB_PERSISTENCE = {
27
+ // Every tab the selector offers, including "stack": the save side has
28
+ // always written it, so leaving it off this list meant the Stack tab
29
+ // was persisted and then silently discarded on the next launch.
30
+ parse: raw => raw === "routes" || raw === "events" || raw === "stack" ? raw : undefined,
31
+ serialize: tab => tab
32
+ };
33
+ const BOOLEAN_PERSISTENCE = {
34
+ parse: raw => raw === "true",
35
+ serialize: value => value.toString()
36
+ };
37
+ const STRING_SET_PERSISTENCE = {
38
+ parse: raw => new Set(JSON.parse(raw)),
39
+ serialize: set => JSON.stringify(Array.from(set))
40
+ };
41
+
25
42
  /**
26
43
  * Find the path from root navigation state to a screen by name.
27
44
  * Returns array of route names from root to the target, or null if not found.
@@ -82,7 +99,7 @@ export function RouteEventsModalWithTabs({
82
99
  const router = useSafeRouter();
83
100
  const containerRef = useSafeNavigationContainerRef();
84
101
  const hasExpoRouter = isExpoRouterAvailable();
85
- const [activeTab, setActiveTab] = useState("events");
102
+ const [activeTab, setActiveTab] = usePersistedState(devToolsStorageKeys.routeEvents.activeTab(), "events", TAB_PERSISTENCE);
86
103
  const [showUpgradeModal, setShowUpgradeModal] = useState(false);
87
104
  // Serialized stack reported up by NavigationStack so the copy button can live
88
105
  // in the shared navbar.
@@ -104,7 +121,7 @@ export function RouteEventsModalWithTabs({
104
121
  // See the RouteTracker component export for easy setup.
105
122
 
106
123
  // Local state to control subscription (true = subscribed, false = unsubscribed)
107
- const [isListeningEnabled, setIsListeningEnabled] = useState(true);
124
+ const [isListeningEnabled, setIsListeningEnabled] = usePersistedState(devToolsStorageKeys.routeEvents.isMonitoring(), true, BOOLEAN_PERSISTENCE);
108
125
 
109
126
  // Event Listener state - using centralized store via hook
110
127
  // Pass enabled option to control subscription
@@ -124,11 +141,8 @@ export function RouteEventsModalWithTabs({
124
141
  const [selectedEvent, setSelectedEvent] = useState(null);
125
142
  const [selectedVisitNumber, setSelectedVisitNumber] = useState(1);
126
143
  const [searchQuery, setSearchQuery] = useState("");
127
- const [ignoredPatterns, setIgnoredPatterns] = useState(new Set(["/_sitemap", "/api", "/__dev"]));
144
+ const [ignoredPatterns, setIgnoredPatterns] = usePersistedState(devToolsStorageKeys.routeEvents.eventFilters(), new Set(["/_sitemap", "/api", "/__dev"]), STRING_SET_PERSISTENCE);
128
145
  const lastEventRef = useRef(null);
129
- const hasLoadedFilters = useRef(false);
130
- const hasLoadedTabState = useRef(false);
131
- const hasLoadedMonitoringState = useRef(false);
132
146
  const handleModeChange = useCallback(_mode => {
133
147
  // Mode changes handled by JsModal
134
148
  }, []);
@@ -180,103 +194,6 @@ export function RouteEventsModalWithTabs({
180
194
  }
181
195
  }, [router, containerRef, hasExpoRouter, remote, isPro]);
182
196
 
183
- // Load persisted tab state on mount
184
- useEffect(() => {
185
- if (!visible || hasLoadedTabState.current) return;
186
- const loadTabState = async () => {
187
- try {
188
- const storedTab = await persistentStorage.getItem(devToolsStorageKeys.routeEvents.activeTab());
189
- // Every tab the selector offers, including "stack": the save side has
190
- // always written it, so leaving it off this list meant the Stack tab
191
- // was persisted and then silently discarded on the next launch —
192
- // you came back to Events having chosen otherwise.
193
- if (storedTab === "routes" || storedTab === "events" || storedTab === "stack") {
194
- setActiveTab(storedTab);
195
- }
196
- hasLoadedTabState.current = true;
197
- } catch (error) {
198
- // Failed to load tab state
199
- }
200
- };
201
- loadTabState();
202
- }, [visible]);
203
-
204
- // Load persisted monitoring state on mount
205
- useEffect(() => {
206
- if (!visible || hasLoadedMonitoringState.current) return;
207
- const loadMonitoringState = async () => {
208
- try {
209
- const storedMonitoring = await persistentStorage.getItem(devToolsStorageKeys.routeEvents.isMonitoring());
210
- if (storedMonitoring !== null) {
211
- const shouldMonitor = storedMonitoring === "true";
212
- setIsListeningEnabled(shouldMonitor);
213
- }
214
- hasLoadedMonitoringState.current = true;
215
- } catch (error) {
216
- // Failed to load monitoring state
217
- }
218
- };
219
- loadMonitoringState();
220
- }, [visible]);
221
-
222
- // Save tab state when it changes
223
- useEffect(() => {
224
- if (!hasLoadedTabState.current) return;
225
- const saveTabState = async () => {
226
- try {
227
- await persistentStorage.setItem(devToolsStorageKeys.routeEvents.activeTab(), activeTab);
228
- } catch (error) {
229
- // Failed to save tab state
230
- }
231
- };
232
- saveTabState();
233
- }, [activeTab]);
234
-
235
- // Save monitoring state when it changes
236
- useEffect(() => {
237
- if (!hasLoadedMonitoringState.current) return;
238
- const saveMonitoringState = async () => {
239
- try {
240
- await persistentStorage.setItem(devToolsStorageKeys.routeEvents.isMonitoring(), isListening.toString());
241
- } catch (error) {
242
- // Failed to save monitoring state
243
- }
244
- };
245
- saveMonitoringState();
246
- }, [isListening]);
247
-
248
- // Load persisted filters on mount
249
- useEffect(() => {
250
- if (!visible || hasLoadedFilters.current) return;
251
- const loadFilters = async () => {
252
- try {
253
- const storedFilters = await persistentStorage.getItem(devToolsStorageKeys.routeEvents.eventFilters());
254
- if (storedFilters) {
255
- const filters = JSON.parse(storedFilters);
256
- setIgnoredPatterns(new Set(filters));
257
- }
258
- hasLoadedFilters.current = true;
259
- } catch (error) {
260
- // Failed to load filters
261
- }
262
- };
263
- loadFilters();
264
- }, [visible]);
265
-
266
- // Save filters when they change
267
- useEffect(() => {
268
- if (!hasLoadedFilters.current) return;
269
- const saveFilters = async () => {
270
- try {
271
- const filters = Array.from(ignoredPatterns);
272
- await persistentStorage.setItem(devToolsStorageKeys.routeEvents.eventFilters(), JSON.stringify(filters));
273
- } catch (error) {
274
- // Failed to save filters
275
- }
276
- };
277
- saveFilters();
278
- }, [ignoredPatterns]);
279
-
280
197
  // Event listener is now managed by useRouteEvents hook
281
198
 
282
199
  const handleToggleListening = useCallback(() => {
@@ -470,21 +387,23 @@ export function RouteEventsModalWithTabs({
470
387
  placeholder: "Search pathname or params...",
471
388
  testID: "buoy-routes-search"
472
389
  })
473
- }), /*#__PURE__*/_jsxs(View, {
474
- style: styles.emptyState,
390
+ }), /*#__PURE__*/_jsx(ToolEmptyState, {
475
391
  testID: "buoy-routes-empty",
476
- children: [/*#__PURE__*/_jsx(Navigation, {
477
- size: 48,
478
- color: night.color.textTertiary
479
- }), /*#__PURE__*/_jsx(Text, {
480
- style: styles.emptyTitle,
481
- testID: "buoy-routes-empty-title",
482
- children: searchQuery.trim() ? "No matching events" : isListening ? "No route events yet" : "Event listener is paused"
483
- }), /*#__PURE__*/_jsx(Text, {
484
- style: styles.emptySubtitle,
485
- testID: "buoy-routes-empty-subtitle",
486
- children: searchQuery.trim() ? "Try a different search term" : isListening ? "Navigation events will appear here" : "Press play to start monitoring"
487
- })]
392
+ ...resolveListEmptyState({
393
+ subject: "route events",
394
+ search: searchQuery,
395
+ total: events.length,
396
+ capturing: isListening,
397
+ waiting: {
398
+ otto: "walking",
399
+ title: "No route events yet",
400
+ message: "Navigation events will appear here"
401
+ },
402
+ paused: {
403
+ title: "Event listener is paused",
404
+ message: "Press play to start monitoring"
405
+ }
406
+ })
488
407
  })]
489
408
  });
490
409
  }
@@ -12,7 +12,7 @@
12
12
 
13
13
  import { useCallback } from "react";
14
14
  import { View, Text, FlatList, StyleSheet } from "react-native";
15
- import { Navigation, night } from "@buoy-gg/shared-ui";
15
+ import { Navigation, night, EVENT_LIST_PRESET } from "@buoy-gg/shared-ui";
16
16
  import { RouteEventItemCompact } from "./RouteEventItemCompact";
17
17
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
18
18
  export function RouteEventsTimeline({
@@ -69,17 +69,8 @@ export function RouteEventsTimeline({
69
69
  onPress: handleItemPress,
70
70
  onNavigate: onNavigate
71
71
  }),
72
- showsVerticalScrollIndicator: true
73
- // Clipped cells fail Detox's hittability check even when they are on
74
- // screen, so the e2e bundle keeps every mounted row targetable. The
75
- // env var is inlined at bundle time; guarded so a non-inlining bundler
76
- // keeps production behaviour.
77
- ,
78
- removeClippedSubviews: !(typeof process !== "undefined" && process.env?.EXPO_PUBLIC_E2E),
79
- initialNumToRender: 12,
80
- maxToRenderPerBatch: 8,
81
- windowSize: 5,
82
- updateCellsBatchingPeriod: 50
72
+ showsVerticalScrollIndicator: true,
73
+ ...EVENT_LIST_PRESET
83
74
  })
84
75
  );
85
76
  }
@@ -12,7 +12,7 @@
12
12
  */
13
13
 
14
14
  import { useState, useCallback, useMemo, useEffect } from "react";
15
- import { night } from "@buoy-gg/shared-ui";
15
+ import { night, ToolEmptyState } from "@buoy-gg/shared-ui";
16
16
  import { View, Text, TextInput, TouchableOpacity, ScrollView, StyleSheet, Alert, Platform } from "react-native";
17
17
  import { useSafeRouter } from "@buoy-gg/shared-ui";
18
18
  import { Search, ChevronDown, ChevronRight, Home, InlineCopyButton, CopyButton, RefreshCw, formatRelativeTime, ProUpgradeModal } from "@buoy-gg/shared-ui";
@@ -406,14 +406,14 @@ export function RoutesSitemap({
406
406
  id: "groups"
407
407
  })]
408
408
  })]
409
- }), displayGroups.length === 0 ? /*#__PURE__*/_jsx(View, {
410
- style: styles.emptyState,
411
- testID: "buoy-routes-sitemap-empty",
412
- children: /*#__PURE__*/_jsx(Text, {
413
- style: styles.emptyText,
414
- testID: "buoy-routes-sitemap-empty-text",
415
- children: "No routes found"
416
- })
409
+ }), displayGroups.length === 0 ? /*#__PURE__*/_jsx(ToolEmptyState, {
410
+ testID: "buoy-routes-sitemap-empty"
411
+ // map = "route inspector; where am I in the navigator" — the one
412
+ // OTTO_USES sentence written for this screen.
413
+ ,
414
+ otto: "map",
415
+ title: "No routes found",
416
+ message: "Nothing in the router matches. Clear the search to see the whole tree."
417
417
  }) : displayGroups.map(group => /*#__PURE__*/_jsx(RouteGroupView, {
418
418
  group: group,
419
419
  isExpanded: searchQuery.length > 0 || expandedGroups.has(group.title),
@@ -26,7 +26,7 @@
26
26
  * ```
27
27
  */
28
28
 
29
- import { useState, useEffect, useCallback } from "react";
29
+ import { useEventStoreEvents } from "@buoy-gg/shared-ui";
30
30
  import { routeEventStore } from "../stores/routeEventStore";
31
31
 
32
32
  // Re-export RouteChangeEvent for convenience
@@ -36,50 +36,19 @@ export function useRouteEvents(options = {}) {
36
36
  maxEvents = 500,
37
37
  enabled = true
38
38
  } = options;
39
- const [events, setEvents] = useState([]);
40
- // Track listening state locally so it updates reactively with the subscription
41
- const [isListening, setIsListening] = useState(enabled);
42
-
43
- // Subscribe to store - this automatically starts/stops listening
44
- // based on subscriber count (Subscribable pattern from TanStack Query)
45
- // Only subscribe when enabled is true
46
- useEffect(() => {
47
- if (!enabled) {
48
- setIsListening(false);
49
- return;
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;
56
- const unsubscribe = routeEventStore.subscribeToEvents(allEvents => {
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
- });
66
- });
67
-
68
- // Mark as listening after successful subscription
69
- setIsListening(true);
70
- return () => {
71
- unsubscribe();
72
- if (rafId != null) cancelAnimationFrame(rafId);
73
- // Note: Don't set isListening=false here because we might be
74
- // re-subscribing due to dependency change, not actually stopping
75
- };
76
- }, [maxEvents, enabled]);
77
- const clearEvents = useCallback(() => {
78
- routeEventStore.clearEvents();
79
- }, []);
39
+ // Subscribing auto-starts the route observer (Subscribable pattern), and
40
+ // the shared hook frame-coalesces navigation bursts into one commit.
41
+ const {
42
+ events,
43
+ clearEvents,
44
+ isActive
45
+ } = useEventStoreEvents(routeEventStore, {
46
+ maxEvents,
47
+ enabled
48
+ });
80
49
  return {
81
50
  events,
82
51
  clearEvents,
83
- isListening
52
+ isListening: isActive
84
53
  };
85
54
  }
@@ -19,6 +19,7 @@
19
19
 
20
20
  import { RoutesIcon } from "@buoy-gg/floating-tools-core";
21
21
  import { RouteEventsModalWithTabs } from "./components/RouteEventsModalWithTabs";
22
+ import { createToolFactory, defineToolPreset } from "@buoy-gg/shared-ui";
22
23
 
23
24
  /**
24
25
  * Pre-configured route events tool for FloatingDevTools.
@@ -29,7 +30,7 @@ import { RouteEventsModalWithTabs } from "./components/RouteEventsModalWithTabs"
29
30
  * - Automatic route tracking (no setup needed)
30
31
  */
31
32
  import { jsx as _jsx } from "react/jsx-runtime";
32
- export const routeEventsToolPreset = {
33
+ export const routeEventsToolPreset = defineToolPreset({
33
34
  id: "route-events",
34
35
  name: "ROUTES",
35
36
  description: "Route tracking & navigation inspector",
@@ -43,7 +44,7 @@ export const routeEventsToolPreset = {
43
44
  props: {
44
45
  enableSharedModalDimensions: false
45
46
  }
46
- };
47
+ });
47
48
 
48
49
  /**
49
50
  * Create a custom route events tool configuration.
@@ -60,20 +61,6 @@ export const routeEventsToolPreset = {
60
61
  * });
61
62
  * ```
62
63
  */
63
- export function createRouteEventsTool(options) {
64
- return {
65
- id: options?.id || "route-events",
66
- name: options?.name || "ROUTES",
67
- description: options?.description || "Route tracking & navigation inspector",
68
- slot: "both",
69
- icon: ({
70
- size
71
- }) => /*#__PURE__*/_jsx(RoutesIcon, {
72
- size: size
73
- }),
74
- component: RouteEventsModalWithTabs,
75
- props: {
76
- enableSharedModalDimensions: options?.enableSharedModalDimensions !== undefined ? options.enableSharedModalDimensions : false
77
- }
78
- };
79
- }
64
+ export const createRouteEventsTool = createToolFactory(routeEventsToolPreset, options => ({
65
+ enableSharedModalDimensions: options.enableSharedModalDimensions ?? false
66
+ }));
@@ -171,7 +171,25 @@ export const routeEventsSyncAdapter = {
171
171
  }
172
172
  const router = getSafeRouter();
173
173
  if (!router) {
174
- throw new Error("expo-router is not available on this device");
174
+ // Bare React Navigation: no paths, but the tracker captured the
175
+ // container ref, so navigate by SCREEN NAME — "/Settings" and
176
+ // "Settings" both resolve, and nested navigators are walked via the
177
+ // root state. This is half the market; "throw off expo-router" made
178
+ // navigate a dead verb for every RN CLI app.
179
+ const actions = navigationStackStore.getActions();
180
+ const name = path.replace(/^\//, "");
181
+ if (!actions?.navigateToRoute || !name) {
182
+ throw new Error("expo-router is not available here and no navigation container was captured — is <RouteTracker /> mounted inside your NavigationContainer?");
183
+ }
184
+ const ok = actions.navigateToRoute(name, p?.params);
185
+ if (!ok) {
186
+ throw new Error(`Could not navigate to "${name}" — no navigation container is live.`);
187
+ }
188
+ return {
189
+ navigated: path,
190
+ replaced: false,
191
+ via: "react-navigation"
192
+ };
175
193
  }
176
194
  // Push by default so navigate-then-back flows keep working. Callers that
177
195
  // mean "leave this screen" (sitemap Go, agents resetting to home) pass
@@ -279,6 +279,32 @@ export function useNavigationStack() {
279
279
  console.error("Failed to navigate:", err);
280
280
  }
281
281
  }, [stack, containerRef]);
282
+ const navigateToRoute = useCallback((name, params) => {
283
+ if (!containerRef) return false;
284
+ try {
285
+ // Deep path first, so screens inside nested navigators resolve even
286
+ // when their navigator isn't mounted yet.
287
+ const rootState = containerRef.getRootState?.();
288
+ if (!params && rootState) {
289
+ const path = findScreenPath(rootState, name);
290
+ if (path) {
291
+ const action = buildNestedNavigateAction(path);
292
+ if (action) {
293
+ containerRef.dispatch(action);
294
+ return true;
295
+ }
296
+ }
297
+ }
298
+ containerRef.dispatch(CommonActions.navigate({
299
+ name,
300
+ params
301
+ }));
302
+ return true;
303
+ } catch (err) {
304
+ console.error("Failed to navigate:", err);
305
+ return false;
306
+ }
307
+ }, [containerRef]);
282
308
  const popToIndex = useCallback(index => {
283
309
  if (index >= stack.length || index < 0) return;
284
310
  const currentIndex = stack.length - 1;
@@ -333,6 +359,7 @@ export function useNavigationStack() {
333
359
  error,
334
360
  refresh,
335
361
  navigateToIndex,
362
+ navigateToRoute,
336
363
  popToIndex,
337
364
  goBack,
338
365
  popToTop
@@ -1 +1 @@
1
- {"version":3,"file":"RouteTracker.d.ts","sourceRoot":"","sources":["../../src/RouteTracker.tsx"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAuCG;AAgDH,wBAAgB,YAAY,gCAQ3B"}
1
+ {"version":3,"file":"RouteTracker.d.ts","sourceRoot":"","sources":["../../src/RouteTracker.tsx"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAuCG;AAiDH,wBAAgB,YAAY,gCAQ3B"}
@@ -1 +1 @@
1
- {"version":3,"file":"NavigationStack.d.ts","sourceRoot":"","sources":["../../../src/components/NavigationStack.tsx"],"names":[],"mappings":"AAAA;;;;;GAKG;AAuBH,OAAO,EAEL,KAAK,gBAAgB,EACtB,MAAM,uBAAuB,CAAC;AAO/B,uEAAuE;AACvE,MAAM,MAAM,yBAAyB,GACjC,iBAAiB,GACjB,YAAY,GACZ,QAAQ,GACR,UAAU,CAAC;AAEf,MAAM,WAAW,oBAAoB;IACnC,KAAK,CAAC,EAAE,GAAG,CAAC;IAEZ;;;;OAIG;IACH,aAAa,CAAC,EAAE,gBAAgB,EAAE,CAAC;IAEnC;;;;OAIG;IACH,QAAQ,CAAC,EAAE,CACT,MAAM,EAAE,yBAAyB,EACjC,OAAO,CAAC,EAAE;QAAE,KAAK,CAAC,EAAE,MAAM,CAAA;KAAE,KACzB,IAAI,CAAC;IAEV;;;;OAIG;IACH,iBAAiB,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;CAC7C;AAMD,wBAAgB,eAAe,CAAC,EAC9B,KAAK,EACL,aAAa,EACb,QAAQ,EACR,iBAAiB,GAClB,EAAE,oBAAoB,+BA6dtB"}
1
+ {"version":3,"file":"NavigationStack.d.ts","sourceRoot":"","sources":["../../../src/components/NavigationStack.tsx"],"names":[],"mappings":"AAAA;;;;;GAKG;AAwBH,OAAO,EAEL,KAAK,gBAAgB,EACtB,MAAM,uBAAuB,CAAC;AAO/B,uEAAuE;AACvE,MAAM,MAAM,yBAAyB,GACjC,iBAAiB,GACjB,YAAY,GACZ,QAAQ,GACR,UAAU,CAAC;AAEf,MAAM,WAAW,oBAAoB;IACnC,KAAK,CAAC,EAAE,GAAG,CAAC;IAEZ;;;;OAIG;IACH,aAAa,CAAC,EAAE,gBAAgB,EAAE,CAAC;IAEnC;;;;OAIG;IACH,QAAQ,CAAC,EAAE,CACT,MAAM,EAAE,yBAAyB,EACjC,OAAO,CAAC,EAAE;QAAE,KAAK,CAAC,EAAE,MAAM,CAAA;KAAE,KACzB,IAAI,CAAC;IAEV;;;;OAIG;IACH,iBAAiB,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;CAC7C;AAMD,wBAAgB,eAAe,CAAC,EAC9B,KAAK,EACL,aAAa,EACb,QAAQ,EACR,iBAAiB,GAClB,EAAE,oBAAoB,+BA2dtB"}
@@ -1 +1 @@
1
- {"version":3,"file":"RouteEventsModalWithTabs.d.ts","sourceRoot":"","sources":["../../../src/components/RouteEventsModalWithTabs.tsx"],"names":[],"mappings":"AAuDA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAC;AAGhD,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,uBAAuB,CAAC;AAC9D,OAAO,KAAK,EAAE,yBAAyB,EAAE,MAAM,mBAAmB,CAAC;AAGnE,MAAM,WAAW,6BAA6B;IAC5C,OAAO,EAAE,OAAO,CAAC;IACjB,OAAO,EAAE,MAAM,IAAI,CAAC;IACpB,MAAM,CAAC,EAAE,MAAM,IAAI,CAAC;IACpB,UAAU,CAAC,EAAE,CAAC,UAAU,EAAE,GAAG,KAAK,IAAI,CAAC;IACvC,2BAA2B,CAAC,EAAE,OAAO,CAAC;IACtC;;;;;OAKG;IACH,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB;;;;;OAKG;IACH,MAAM,CAAC,EAAE;QACP,OAAO,CAAC,EAAE;YACR,MAAM,CAAC,EAAE,SAAS,EAAE,CAAC;YACrB,MAAM,CAAC,EAAE,OAAO,GAAG,KAAK,GAAG,IAAI,CAAC;YAChC,aAAa,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;SAC/B,CAAC;QACF,KAAK,CAAC,EAAE,gBAAgB,EAAE,CAAC;QAC3B;;;;WAIG;QACH,eAAe,CAAC,EAAE,CAAC,KAAK,EAAE,SAAS,KAAK,IAAI,CAAC;QAC7C;;;;;WAKG;QACH,cAAc,CAAC,EAAE,CAAC,QAAQ,EAAE,MAAM,KAAK,IAAI,CAAC;QAC5C,2EAA2E;QAC3E,aAAa,CAAC,EAAE,CACd,MAAM,EAAE,yBAAyB,EACjC,OAAO,CAAC,EAAE;YAAE,KAAK,CAAC,EAAE,MAAM,CAAA;SAAE,KACzB,IAAI,CAAC;KACX,CAAC;CACH;AA8CD,wBAAgB,wBAAwB,CAAC,EACvC,OAAO,EACP,OAAO,EACP,MAAM,EACN,UAAU,EACV,2BAAmC,EACnC,MAAc,EACd,MAAM,GACP,EAAE,6BAA6B,sCAguB/B;AAED;;;;;GAKG;AACH,wBAAgB,cAAc,CAC5B,KAAK,GAAE,IAAI,CAAC,6BAA6B,EAAE,SAAS,GAAG,SAAS,GAAG,QAAQ,CAAM,+BAKlF"}
1
+ {"version":3,"file":"RouteEventsModalWithTabs.d.ts","sourceRoot":"","sources":["../../../src/components/RouteEventsModalWithTabs.tsx"],"names":[],"mappings":"AAyDA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAC;AAGhD,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,uBAAuB,CAAC;AAC9D,OAAO,KAAK,EAAE,yBAAyB,EAAE,MAAM,mBAAmB,CAAC;AAGnE,MAAM,WAAW,6BAA6B;IAC5C,OAAO,EAAE,OAAO,CAAC;IACjB,OAAO,EAAE,MAAM,IAAI,CAAC;IACpB,MAAM,CAAC,EAAE,MAAM,IAAI,CAAC;IACpB,UAAU,CAAC,EAAE,CAAC,UAAU,EAAE,GAAG,KAAK,IAAI,CAAC;IACvC,2BAA2B,CAAC,EAAE,OAAO,CAAC;IACtC;;;;;OAKG;IACH,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB;;;;;OAKG;IACH,MAAM,CAAC,EAAE;QACP,OAAO,CAAC,EAAE;YACR,MAAM,CAAC,EAAE,SAAS,EAAE,CAAC;YACrB,MAAM,CAAC,EAAE,OAAO,GAAG,KAAK,GAAG,IAAI,CAAC;YAChC,aAAa,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;SAC/B,CAAC;QACF,KAAK,CAAC,EAAE,gBAAgB,EAAE,CAAC;QAC3B;;;;WAIG;QACH,eAAe,CAAC,EAAE,CAAC,KAAK,EAAE,SAAS,KAAK,IAAI,CAAC;QAC7C;;;;;WAKG;QACH,cAAc,CAAC,EAAE,CAAC,QAAQ,EAAE,MAAM,KAAK,IAAI,CAAC;QAC5C,2EAA2E;QAC3E,aAAa,CAAC,EAAE,CACd,MAAM,EAAE,yBAAyB,EACjC,OAAO,CAAC,EAAE;YAAE,KAAK,CAAC,EAAE,MAAM,CAAA;SAAE,KACzB,IAAI,CAAC;KACX,CAAC;CACH;AAgED,wBAAgB,wBAAwB,CAAC,EACvC,OAAO,EACP,OAAO,EACP,MAAM,EACN,UAAU,EACV,2BAAmC,EACnC,MAAc,EACd,MAAM,GACP,EAAE,6BAA6B,sCAqmB/B;AAED;;;;;GAKG;AACH,wBAAgB,cAAc,CAC5B,KAAK,GAAE,IAAI,CAAC,6BAA6B,EAAE,SAAS,GAAG,SAAS,GAAG,QAAQ,CAAM,+BAKlF"}
@@ -1 +1 @@
1
- {"version":3,"file":"RouteEventsTimeline.d.ts","sourceRoot":"","sources":["../../../src/components/RouteEventsTimeline.tsx"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAaH,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,kBAAkB,CAAC;AAGzD,UAAU,wBAAwB;IAChC,MAAM,EAAE,gBAAgB,EAAE,CAAC;IAC3B;wEACoE;IACpE,WAAW,EAAE,GAAG,CAAC,gBAAgB,EAAE,MAAM,CAAC,CAAC;IAC3C,UAAU,CAAC,EAAE,CAAC,QAAQ,EAAE,MAAM,KAAK,IAAI,CAAC;IACxC,aAAa,EAAE,CAAC,KAAK,EAAE,gBAAgB,EAAE,WAAW,EAAE,MAAM,KAAK,IAAI,CAAC;CACvE;AAED,wBAAgB,mBAAmB,CAAC,EAClC,MAAM,EACN,WAAW,EACX,UAAU,EACV,aAAa,GACd,EAAE,wBAAwB,+BA8D1B"}
1
+ {"version":3,"file":"RouteEventsTimeline.d.ts","sourceRoot":"","sources":["../../../src/components/RouteEventsTimeline.tsx"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAcH,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,kBAAkB,CAAC;AAGzD,UAAU,wBAAwB;IAChC,MAAM,EAAE,gBAAgB,EAAE,CAAC;IAC3B;wEACoE;IACpE,WAAW,EAAE,GAAG,CAAC,gBAAgB,EAAE,MAAM,CAAC,CAAC;IAC3C,UAAU,CAAC,EAAE,CAAC,QAAQ,EAAE,MAAM,KAAK,IAAI,CAAC;IACxC,aAAa,EAAE,CAAC,KAAK,EAAE,gBAAgB,EAAE,WAAW,EAAE,MAAM,KAAK,IAAI,CAAC;CACvE;AAED,wBAAgB,mBAAmB,CAAC,EAClC,MAAM,EACN,WAAW,EACX,UAAU,EACV,aAAa,GACd,EAAE,wBAAwB,+BAoD1B"}
@@ -1 +1 @@
1
- {"version":3,"file":"RoutesSitemap.d.ts","sourceRoot":"","sources":["../../../src/components/RoutesSitemap.tsx"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AA6BH,OAAO,KAAK,EAAE,SAAS,EAAc,MAAM,gBAAgB,CAAC;AAM5D,MAAM,WAAW,kBAAkB;IACjC,KAAK,CAAC,EAAE,GAAG,CAAC;IAEZ;;;;OAIG;IACH,cAAc,CAAC,EAAE,SAAS,EAAE,CAAC;IAE7B,oDAAoD;IACpD,cAAc,CAAC,EAAE,OAAO,GAAG,KAAK,GAAG,IAAI,CAAC;IAExC,8DAA8D;IAC9D,qBAAqB,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAEtC;;;;;OAKG;IACH,eAAe,CAAC,EAAE,CAAC,KAAK,EAAE,SAAS,KAAK,IAAI,CAAC;CAC9C;AAsCD,wBAAgB,aAAa,CAAC,EAC5B,KAAK,EACL,cAAc,EACd,cAAc,EACd,qBAAqB,EACrB,eAAe,GAChB,EAAE,kBAAkB,+BA8apB"}
1
+ {"version":3,"file":"RoutesSitemap.d.ts","sourceRoot":"","sources":["../../../src/components/RoutesSitemap.tsx"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAgCH,OAAO,KAAK,EAAE,SAAS,EAAc,MAAM,gBAAgB,CAAC;AAM5D,MAAM,WAAW,kBAAkB;IACjC,KAAK,CAAC,EAAE,GAAG,CAAC;IAEZ;;;;OAIG;IACH,cAAc,CAAC,EAAE,SAAS,EAAE,CAAC;IAE7B,oDAAoD;IACpD,cAAc,CAAC,EAAE,OAAO,GAAG,KAAK,GAAG,IAAI,CAAC;IAExC,8DAA8D;IAC9D,qBAAqB,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAEtC;;;;;OAKG;IACH,eAAe,CAAC,EAAE,CAAC,KAAK,EAAE,SAAS,KAAK,IAAI,CAAC;CAC9C;AAsCD,wBAAgB,aAAa,CAAC,EAC5B,KAAK,EACL,cAAc,EACd,cAAc,EACd,qBAAqB,EACrB,eAAe,GAChB,EAAE,kBAAkB,+BAibpB"}
@@ -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,CAoDtB"}
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,CAStB"}
@@ -51,16 +51,10 @@ export declare const routeEventsToolPreset: {
51
51
  * });
52
52
  * ```
53
53
  */
54
- export declare function createRouteEventsTool(options?: {
55
- /** Tool name (default: "ROUTES") */
56
- name?: string;
57
- /** Tool description */
58
- description?: string;
59
- /** Custom tool ID (default: "route-events") */
60
- id?: string;
54
+ export declare const createRouteEventsTool: (options?: ({
61
55
  /** Enable shared modal dimensions */
62
56
  enableSharedModalDimensions?: boolean;
63
- }): {
57
+ } & import("@buoy-gg/shared-ui").ToolPresetOverrides) | undefined) => {
64
58
  id: string;
65
59
  name: string;
66
60
  description: string;
@@ -1 +1 @@
1
- {"version":3,"file":"preset.d.ts","sourceRoot":"","sources":["../../src/preset.tsx"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAGH,OAAO,EAAE,wBAAwB,EAAE,MAAM,uCAAuC,CAAC;AAEjF;;;;;;;GAOG;AACH,eAAO,MAAM,qBAAqB;;;;;qBAKf;QAAE,IAAI,EAAE,MAAM,CAAA;KAAE;;;;;CAKlC,CAAC;AAEF;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,qBAAqB,CAAC,OAAO,CAAC,EAAE;IAC9C,oCAAoC;IACpC,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,uBAAuB;IACvB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,+CAA+C;IAC/C,EAAE,CAAC,EAAE,MAAM,CAAC;IACZ,qCAAqC;IACrC,2BAA2B,CAAC,EAAE,OAAO,CAAC;CACvC;;;;;qBAOoB;QAAE,IAAI,EAAE,MAAM,CAAA;KAAE;;;;;EASpC"}
1
+ {"version":3,"file":"preset.d.ts","sourceRoot":"","sources":["../../src/preset.tsx"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAGH,OAAO,EAAE,wBAAwB,EAAE,MAAM,uCAAuC,CAAC;AAGjF;;;;;;;GAOG;AACH,eAAO,MAAM,qBAAqB;;;;;qBAKf;QAAE,IAAI,EAAE,MAAM,CAAA;KAAE;;;;;CAKjC,CAAC;AAEH;;;;;;;;;;;;;;GAcG;AACH,eAAO,MAAM,qBAAqB;IAG9B,qCAAqC;kCACP,OAAO;;;;;;qBA1BtB;QAAE,IAAI,EAAE,MAAM,CAAA;KAAE;;;;;CA8BlC,CAAC"}
@@ -14,6 +14,8 @@
14
14
  import type { StackDisplayItem } from "../useNavigationStack";
15
15
  export interface NavigationStackActions {
16
16
  navigateToIndex: (index: number) => void;
17
+ /** Name-based navigation for bare React Navigation. Optional: older trackers don't capture it. */
18
+ navigateToRoute?: (name: string, params?: object) => boolean;
17
19
  popToIndex: (index: number) => void;
18
20
  goBack: () => void;
19
21
  popToTop: () => void;
@@ -1 +1 @@
1
- {"version":3,"file":"navigationStackStore.d.ts","sourceRoot":"","sources":["../../../src/stores/navigationStackStore.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAEH,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,uBAAuB,CAAC;AAE9D,MAAM,WAAW,sBAAsB;IACrC,eAAe,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;IACzC,UAAU,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;IACpC,MAAM,EAAE,MAAM,IAAI,CAAC;IACnB,QAAQ,EAAE,MAAM,IAAI,CAAC;CACtB;AAED,cAAM,oBAAoB;IACxB,OAAO,CAAC,KAAK,CAA0B;IACvC,OAAO,CAAC,OAAO,CAAuC;IACtD,OAAO,CAAC,SAAS,CAAyB;IAE1C,QAAQ,IAAI,gBAAgB,EAAE;IAI9B,QAAQ,CAAC,KAAK,EAAE,gBAAgB,EAAE,GAAG,IAAI;IAKzC,UAAU,IAAI,sBAAsB,GAAG,IAAI;IAI3C,UAAU,CAAC,OAAO,EAAE,sBAAsB,GAAG,IAAI,GAAG,IAAI;IAIxD,SAAS,CAAC,QAAQ,EAAE,MAAM,IAAI,GAAG,MAAM,IAAI;CAM5C;AAED,eAAO,MAAM,oBAAoB,sBAA6B,CAAC"}
1
+ {"version":3,"file":"navigationStackStore.d.ts","sourceRoot":"","sources":["../../../src/stores/navigationStackStore.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAEH,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,uBAAuB,CAAC;AAE9D,MAAM,WAAW,sBAAsB;IACrC,eAAe,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;IACzC,kGAAkG;IAClG,eAAe,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,MAAM,KAAK,OAAO,CAAC;IAC7D,UAAU,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;IACpC,MAAM,EAAE,MAAM,IAAI,CAAC;IACnB,QAAQ,EAAE,MAAM,IAAI,CAAC;CACtB;AAED,cAAM,oBAAoB;IACxB,OAAO,CAAC,KAAK,CAA0B;IACvC,OAAO,CAAC,OAAO,CAAuC;IACtD,OAAO,CAAC,SAAS,CAAyB;IAE1C,QAAQ,IAAI,gBAAgB,EAAE;IAI9B,QAAQ,CAAC,KAAK,EAAE,gBAAgB,EAAE,GAAG,IAAI;IAKzC,UAAU,IAAI,sBAAsB,GAAG,IAAI;IAI3C,UAAU,CAAC,OAAO,EAAE,sBAAsB,GAAG,IAAI,GAAG,IAAI;IAIxD,SAAS,CAAC,QAAQ,EAAE,MAAM,IAAI,GAAG,MAAM,IAAI;CAM5C;AAED,eAAO,MAAM,oBAAoB,sBAA6B,CAAC"}
@@ -84,6 +84,11 @@ export declare const routeEventsSyncAdapter: {
84
84
  navigate: (params?: unknown) => {
85
85
  navigated: string;
86
86
  replaced: boolean;
87
+ via: string;
88
+ } | {
89
+ navigated: string;
90
+ replaced: boolean;
91
+ via?: undefined;
87
92
  };
88
93
  stackNavigateToIndex: (params?: unknown) => {
89
94
  navigatedToIndex: number;
@@ -1 +1 @@
1
- {"version":3,"file":"routeEventsSyncAdapter.d.ts","sourceRoot":"","sources":["../../../src/sync/routeEventsSyncAdapter.ts"],"names":[],"mappings":"AAGA,OAAO,EAAe,KAAK,SAAS,EAAE,MAAM,gBAAgB,CAAC;AAE7D,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,kBAAkB,CAAC;AACzD,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,uBAAuB,CAAC;AAG9D;;;;;GAKG;AACH,eAAO,MAAM,2BAA2B,QAAY,CAAC;AA4BrD;;;;;GAKG;AACH,MAAM,WAAW,oBAAoB;IACnC,6EAA6E;IAC7E,MAAM,EAAE,SAAS,EAAE,CAAC;IACpB,mEAAmE;IACnE,MAAM,EAAE,OAAO,GAAG,KAAK,GAAG,IAAI,CAAC;IAC/B,6EAA6E;IAC7E,aAAa,EAAE,MAAM,GAAG,IAAI,CAAC;CAC9B;AAED;;;GAGG;AACH,MAAM,WAAW,sBAAsB;IACrC,MAAM,EAAE,gBAAgB,EAAE,CAAC;IAC3B,OAAO,EAAE,oBAAoB,CAAC;IAC9B,8EAA8E;IAC9E,KAAK,EAAE,gBAAgB,EAAE,CAAC;CAC3B;AAWD;;;;;;;;;;;;;GAaG;AACH,eAAO,MAAM,sBAAsB;;uBAEhB,sBAAsB;0BAKjB,MAAM,IAAI;;;QAkC9B;;;;;;;;WAQG;;;;;;;;;;;;;;;;;QAgCH;;;WAGG;4BACiB,OAAO;;;;wCAsBK,OAAO;;;mCAUZ,OAAO;;;;;;;;;;CAuBrC,CAAC"}
1
+ {"version":3,"file":"routeEventsSyncAdapter.d.ts","sourceRoot":"","sources":["../../../src/sync/routeEventsSyncAdapter.ts"],"names":[],"mappings":"AAGA,OAAO,EAAe,KAAK,SAAS,EAAE,MAAM,gBAAgB,CAAC;AAE7D,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,kBAAkB,CAAC;AACzD,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,uBAAuB,CAAC;AAG9D;;;;;GAKG;AACH,eAAO,MAAM,2BAA2B,QAAY,CAAC;AA4BrD;;;;;GAKG;AACH,MAAM,WAAW,oBAAoB;IACnC,6EAA6E;IAC7E,MAAM,EAAE,SAAS,EAAE,CAAC;IACpB,mEAAmE;IACnE,MAAM,EAAE,OAAO,GAAG,KAAK,GAAG,IAAI,CAAC;IAC/B,6EAA6E;IAC7E,aAAa,EAAE,MAAM,GAAG,IAAI,CAAC;CAC9B;AAED;;;GAGG;AACH,MAAM,WAAW,sBAAsB;IACrC,MAAM,EAAE,gBAAgB,EAAE,CAAC;IAC3B,OAAO,EAAE,oBAAoB,CAAC;IAC9B,8EAA8E;IAC9E,KAAK,EAAE,gBAAgB,EAAE,CAAC;CAC3B;AAWD;;;;;;;;;;;;;GAaG;AACH,eAAO,MAAM,sBAAsB;;uBAEhB,sBAAsB;0BAKjB,MAAM,IAAI;;;QAkC9B;;;;;;;;WAQG;;;;;;;;;;;;;;;;;QAgCH;;;WAGG;4BACiB,OAAO;;;;;;;;;wCAsCK,OAAO;;;mCAUZ,OAAO;;;;;;;;;;CAuBrC,CAAC"}
@@ -27,6 +27,13 @@ export interface UseNavigationStackResult {
27
27
  error: Error | null;
28
28
  refresh: () => void;
29
29
  navigateToIndex: (index: number) => void;
30
+ /**
31
+ * Navigate to a screen by NAME on bare React Navigation — the fallback
32
+ * that makes the `navigate` sync action work off expo-router. Resolves
33
+ * nested navigators via the root state when it can; returns false when no
34
+ * container ref was captured.
35
+ */
36
+ navigateToRoute: (name: string, params?: object) => boolean;
30
37
  popToIndex: (index: number) => void;
31
38
  goBack: () => void;
32
39
  popToTop: () => void;
@@ -1 +1 @@
1
- {"version":3,"file":"useNavigationStack.d.ts","sourceRoot":"","sources":["../../src/useNavigationStack.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AA4BH,MAAM,WAAW,gBAAgB;IAC/B,GAAG,EAAE,MAAM,CAAC;IACZ,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,MAAM,CAAC;IACjB,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;IAC5B,SAAS,EAAE,OAAO,CAAC;IACnB,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,OAAO,CAAC;CACjB;AAED,MAAM,WAAW,wBAAwB;IAEvC,KAAK,EAAE,gBAAgB,EAAE,CAAC;IAC1B,YAAY,EAAE,gBAAgB,GAAG,IAAI,CAAC;IACtC,UAAU,EAAE,MAAM,CAAC;IACnB,QAAQ,EAAE,OAAO,CAAC;IAGlB,QAAQ,EAAE,OAAO,CAAC;IAClB,KAAK,EAAE,KAAK,GAAG,IAAI,CAAC;IAGpB,OAAO,EAAE,MAAM,IAAI,CAAC;IACpB,eAAe,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;IACzC,UAAU,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;IACpC,MAAM,EAAE,MAAM,IAAI,CAAC;IACnB,QAAQ,EAAE,MAAM,IAAI,CAAC;CACtB;AAuKD;;;;;;;;;;;;;;;;;;GAkBG;AACH,wBAAgB,kBAAkB,IAAI,wBAAwB,CAqK7D"}
1
+ {"version":3,"file":"useNavigationStack.d.ts","sourceRoot":"","sources":["../../src/useNavigationStack.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AA4BH,MAAM,WAAW,gBAAgB;IAC/B,GAAG,EAAE,MAAM,CAAC;IACZ,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,MAAM,CAAC;IACjB,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;IAC5B,SAAS,EAAE,OAAO,CAAC;IACnB,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,OAAO,CAAC;CACjB;AAED,MAAM,WAAW,wBAAwB;IAEvC,KAAK,EAAE,gBAAgB,EAAE,CAAC;IAC1B,YAAY,EAAE,gBAAgB,GAAG,IAAI,CAAC;IACtC,UAAU,EAAE,MAAM,CAAC;IACnB,QAAQ,EAAE,OAAO,CAAC;IAGlB,QAAQ,EAAE,OAAO,CAAC;IAClB,KAAK,EAAE,KAAK,GAAG,IAAI,CAAC;IAGpB,OAAO,EAAE,MAAM,IAAI,CAAC;IACpB,eAAe,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;IACzC;;;;;OAKG;IACH,eAAe,EAAE,CAAC,IAAI,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,MAAM,KAAK,OAAO,CAAC;IAC5D,UAAU,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;IACpC,MAAM,EAAE,MAAM,IAAI,CAAC;IACnB,QAAQ,EAAE,MAAM,IAAI,CAAC;CACtB;AAuKD;;;;;;;;;;;;;;;;;;GAkBG;AACH,wBAAgB,kBAAkB,IAAI,wBAAwB,CAiM7D"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@buoy-gg/route-events",
3
- "version": "7.0.32",
3
+ "version": "7.0.34",
4
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",
@@ -26,11 +26,11 @@
26
26
  ],
27
27
  "sideEffects": false,
28
28
  "dependencies": {
29
- "@buoy-gg/shared-ui": "^7.0.32",
30
- "@buoy-gg/floating-tools-core": "^7.0.32"
29
+ "@buoy-gg/shared-ui": "^7.0.34",
30
+ "@buoy-gg/floating-tools-core": "^7.0.34"
31
31
  },
32
32
  "peerDependencies": {
33
- "@buoy-gg/license": "7.0.32",
33
+ "@buoy-gg/license": "7.0.34",
34
34
  "@react-native-async-storage/async-storage": "^2.0.0 || ^3.1.0",
35
35
  "@react-navigation/native": "*",
36
36
  "expo-router": "*",
@@ -52,7 +52,7 @@
52
52
  "@types/react-native": "^0.73.0",
53
53
  "expo-router": "~5.0.7",
54
54
  "typescript": "~5.8.3",
55
- "@buoy-gg/license": "^7.0.32"
55
+ "@buoy-gg/license": "^7.0.34"
56
56
  },
57
57
  "react-native-builder-bob": {
58
58
  "source": "src",