@buoy-gg/route-events 7.0.26 → 7.0.28

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 (39) hide show
  1. package/lib/commonjs/RouteParser.js +8 -4
  2. package/lib/commonjs/components/NavigationStack.js +19 -18
  3. package/lib/commonjs/components/ReactNavigationRoutes.js +108 -106
  4. package/lib/commonjs/components/RouteEventDetail.js +9 -6
  5. package/lib/commonjs/components/RouteEventExpandedContent.js +3 -3
  6. package/lib/commonjs/components/RouteEventItemCompact.js +5 -4
  7. package/lib/commonjs/components/RouteEventsModalWithTabs.js +48 -25
  8. package/lib/commonjs/components/RouteEventsTimeline.js +3 -3
  9. package/lib/commonjs/components/RoutesSitemap.js +129 -129
  10. package/lib/commonjs/sync/routeEventsSyncAdapter.js +9 -3
  11. package/lib/commonjs/useNavigationStack.js +4 -5
  12. package/lib/commonjs/useRouteObserverReactNavigation.js +1 -5
  13. package/lib/commonjs/utils/safeReactNavigation.js +62 -6
  14. package/lib/module/RouteParser.js +8 -4
  15. package/lib/module/components/NavigationStack.js +20 -19
  16. package/lib/module/components/ReactNavigationRoutes.js +111 -109
  17. package/lib/module/components/RouteEventDetail.js +10 -7
  18. package/lib/module/components/RouteEventExpandedContent.js +4 -4
  19. package/lib/module/components/RouteEventItemCompact.js +6 -5
  20. package/lib/module/components/RouteEventsModalWithTabs.js +51 -28
  21. package/lib/module/components/RouteEventsTimeline.js +4 -4
  22. package/lib/module/components/RoutesSitemap.js +131 -131
  23. package/lib/module/sync/routeEventsSyncAdapter.js +9 -3
  24. package/lib/module/useNavigationStack.js +6 -7
  25. package/lib/module/useRouteObserverReactNavigation.js +3 -7
  26. package/lib/module/utils/safeReactNavigation.js +62 -6
  27. package/lib/typescript/RouteParser.d.ts.map +1 -1
  28. package/lib/typescript/components/NavigationStack.d.ts.map +1 -1
  29. package/lib/typescript/components/ReactNavigationRoutes.d.ts.map +1 -1
  30. package/lib/typescript/components/RouteEventsModalWithTabs.d.ts +7 -0
  31. package/lib/typescript/components/RouteEventsModalWithTabs.d.ts.map +1 -1
  32. package/lib/typescript/components/RoutesSitemap.d.ts.map +1 -1
  33. package/lib/typescript/sync/routeEventsSyncAdapter.d.ts +1 -0
  34. package/lib/typescript/sync/routeEventsSyncAdapter.d.ts.map +1 -1
  35. package/lib/typescript/useNavigationStack.d.ts.map +1 -1
  36. package/lib/typescript/useRouteObserverReactNavigation.d.ts.map +1 -1
  37. package/lib/typescript/utils/safeReactNavigation.d.ts +6 -5
  38. package/lib/typescript/utils/safeReactNavigation.d.ts.map +1 -1
  39. package/package.json +5 -5
@@ -57,7 +57,7 @@ function RoutesSitemap({
57
57
  }) {
58
58
  const [searchQuery, setSearchQuery] = (0, _react.useState)("");
59
59
  const [isSearching, setIsSearching] = (0, _react.useState)(false);
60
- const [expandedGroups, setExpandedGroups] = (0, _react.useState)(new Set(["Root Routes", "Dynamic Routes"]));
60
+ const [expandedGroups, setExpandedGroups] = (0, _react.useState)(new Set(["Static Routes", "Dynamic Routes"]));
61
61
  const [isRefreshing, setIsRefreshing] = (0, _react.useState)(false);
62
62
  const [showUpgradeModal, setShowUpgradeModal] = (0, _react.useState)(false);
63
63
 
@@ -263,96 +263,15 @@ function RoutesSitemap({
263
263
  }
264
264
  return /*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNative.View, {
265
265
  style: [styles.container, style],
266
- children: [!isSearching ? /*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNative.View, {
267
- style: styles.header,
268
- children: [/*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNative.View, {
269
- style: styles.actionsRow,
270
- children: [/*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNative.View, {
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, {
287
- value: copyAllData,
288
- size: IS_DESKTOP ? ACTION_ICON_SIZE : 14,
289
- buttonStyle: IS_DESKTOP ? styles.actionButtonHeaderDesktop : styles.actionButtonHeader
290
- }), /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.Text, {
291
- style: [styles.actionLabel, IS_DESKTOP && styles.actionLabelDesktop],
292
- children: "Copy"
293
- })]
294
- }), /*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNative.View, {
295
- style: [styles.actionWrapper, IS_DESKTOP && styles.actionWrapperDesktop],
296
- children: [/*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.TouchableOpacity, {
297
- style: [styles.iconButton, IS_DESKTOP && styles.iconButtonDesktop, isRefreshing && styles.refreshButtonDisabled],
298
- onPress: handleManualRefresh,
299
- disabled: isRefreshing,
300
- children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_sharedUi.RefreshCw, {
301
- size: ACTION_ICON_SIZE,
302
- color: isRefreshing ? _sharedUi.buoyColors.textMuted : _sharedUi.buoyColors.textSecondary
303
- })
304
- }), /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.Text, {
305
- style: [styles.actionLabel, IS_DESKTOP && styles.actionLabelDesktop],
306
- children: "Refresh"
307
- })]
308
- }), /*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNative.View, {
309
- style: [styles.actionWrapper, IS_DESKTOP && styles.actionWrapperDesktop],
310
- children: [/*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.TouchableOpacity, {
311
- style: [styles.iconButton, IS_DESKTOP && styles.iconButtonDesktop],
312
- onPress: () => setIsSearching(true),
313
- children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_sharedUi.Search, {
314
- size: ACTION_ICON_SIZE,
315
- color: _sharedUi.buoyColors.textSecondary
316
- })
317
- }), /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.Text, {
318
- style: [styles.actionLabel, IS_DESKTOP && styles.actionLabelDesktop],
319
- children: "Search"
320
- })]
321
- })]
322
- }), /*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNative.View, {
323
- style: styles.statsGrid,
324
- children: [/*#__PURE__*/(0, _jsxRuntime.jsx)(StatItem, {
325
- value: stats.total,
326
- label: "Total"
327
- }), /*#__PURE__*/(0, _jsxRuntime.jsx)(StatItem, {
328
- value: stats.static,
329
- label: "Static"
330
- }), /*#__PURE__*/(0, _jsxRuntime.jsx)(StatItem, {
331
- value: stats.dynamic,
332
- label: "Dynamic"
333
- }), /*#__PURE__*/(0, _jsxRuntime.jsx)(StatItem, {
334
- value: stats.catchAll,
335
- label: "Catch-All"
336
- }), /*#__PURE__*/(0, _jsxRuntime.jsx)(StatItem, {
337
- value: stats.layouts,
338
- label: "Layouts"
339
- }), /*#__PURE__*/(0, _jsxRuntime.jsx)(StatItem, {
340
- value: stats.groups,
341
- label: "Groups"
342
- })]
343
- })]
344
- }) :
345
- /*#__PURE__*/
346
- /* Search mode - full width search bar */
347
- (0, _jsxRuntime.jsxs)(_reactNative.View, {
266
+ children: [isSearching && /*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNative.View, {
348
267
  style: styles.searchContainer,
349
268
  children: [/*#__PURE__*/(0, _jsxRuntime.jsx)(_sharedUi.Search, {
350
269
  size: 16,
351
- color: _sharedUi.buoyColors.textMuted
270
+ color: _sharedUi.night.color.textTertiary
352
271
  }), /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.TextInput, {
353
272
  style: styles.searchInput,
354
273
  placeholder: "Search routes...",
355
- placeholderTextColor: _sharedUi.buoyColors.textMuted,
274
+ placeholderTextColor: _sharedUi.night.color.placeholder,
356
275
  value: searchQuery,
357
276
  onChangeText: setSearchQuery,
358
277
  autoCapitalize: "none",
@@ -379,7 +298,85 @@ function RoutesSitemap({
379
298
  }), /*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNative.ScrollView, {
380
299
  style: styles.scrollView,
381
300
  contentContainerStyle: styles.scrollContent,
382
- children: [displayGroups.length === 0 ? /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.View, {
301
+ children: [!isSearching && /*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNative.View, {
302
+ style: styles.header,
303
+ children: [/*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNative.View, {
304
+ style: styles.actionsRow,
305
+ children: [/*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNative.View, {
306
+ style: [styles.actionWrapper, IS_DESKTOP && styles.actionWrapperDesktop],
307
+ children: [/*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.TouchableOpacity, {
308
+ style: [styles.iconButton, IS_DESKTOP && styles.iconButtonDesktop],
309
+ onPress: handleGoHome,
310
+ accessibilityLabel: "Go to home route",
311
+ children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_sharedUi.Home, {
312
+ size: ACTION_ICON_SIZE,
313
+ color: _sharedUi.night.color.textSecondary
314
+ })
315
+ }), /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.Text, {
316
+ style: [styles.actionLabel, IS_DESKTOP && styles.actionLabelDesktop],
317
+ children: "Home"
318
+ })]
319
+ }), /*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNative.View, {
320
+ style: [styles.actionWrapper, IS_DESKTOP && styles.actionWrapperDesktop],
321
+ children: [/*#__PURE__*/(0, _jsxRuntime.jsx)(_sharedUi.CopyButton, {
322
+ value: copyAllData,
323
+ size: IS_DESKTOP ? ACTION_ICON_SIZE : 14,
324
+ buttonStyle: IS_DESKTOP ? styles.actionButtonHeaderDesktop : styles.actionButtonHeader
325
+ }), /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.Text, {
326
+ style: [styles.actionLabel, IS_DESKTOP && styles.actionLabelDesktop],
327
+ children: "Copy"
328
+ })]
329
+ }), /*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNative.View, {
330
+ style: [styles.actionWrapper, IS_DESKTOP && styles.actionWrapperDesktop],
331
+ children: [/*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.TouchableOpacity, {
332
+ style: [styles.iconButton, IS_DESKTOP && styles.iconButtonDesktop, isRefreshing && styles.refreshButtonDisabled],
333
+ onPress: handleManualRefresh,
334
+ disabled: isRefreshing,
335
+ children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_sharedUi.RefreshCw, {
336
+ size: ACTION_ICON_SIZE,
337
+ color: isRefreshing ? _sharedUi.night.color.textTertiary : _sharedUi.night.color.textSecondary
338
+ })
339
+ }), /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.Text, {
340
+ style: [styles.actionLabel, IS_DESKTOP && styles.actionLabelDesktop],
341
+ children: "Refresh"
342
+ })]
343
+ }), /*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNative.View, {
344
+ style: [styles.actionWrapper, IS_DESKTOP && styles.actionWrapperDesktop],
345
+ children: [/*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.TouchableOpacity, {
346
+ style: [styles.iconButton, IS_DESKTOP && styles.iconButtonDesktop],
347
+ onPress: () => setIsSearching(true),
348
+ children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_sharedUi.Search, {
349
+ size: ACTION_ICON_SIZE,
350
+ color: _sharedUi.night.color.textSecondary
351
+ })
352
+ }), /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.Text, {
353
+ style: [styles.actionLabel, IS_DESKTOP && styles.actionLabelDesktop],
354
+ children: "Search"
355
+ })]
356
+ })]
357
+ }), /*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNative.View, {
358
+ style: styles.statsGrid,
359
+ children: [/*#__PURE__*/(0, _jsxRuntime.jsx)(StatItem, {
360
+ value: stats.total,
361
+ label: "Total"
362
+ }), /*#__PURE__*/(0, _jsxRuntime.jsx)(StatItem, {
363
+ value: stats.static,
364
+ label: "Static"
365
+ }), /*#__PURE__*/(0, _jsxRuntime.jsx)(StatItem, {
366
+ value: stats.dynamic,
367
+ label: "Dynamic"
368
+ }), /*#__PURE__*/(0, _jsxRuntime.jsx)(StatItem, {
369
+ value: stats.catchAll,
370
+ label: "Catch-All"
371
+ }), /*#__PURE__*/(0, _jsxRuntime.jsx)(StatItem, {
372
+ value: stats.layouts,
373
+ label: "Layouts"
374
+ }), /*#__PURE__*/(0, _jsxRuntime.jsx)(StatItem, {
375
+ value: stats.groups,
376
+ label: "Groups"
377
+ })]
378
+ })]
379
+ }), displayGroups.length === 0 ? /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.View, {
383
380
  style: styles.emptyState,
384
381
  children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.Text, {
385
382
  style: styles.emptyText,
@@ -446,10 +443,10 @@ function RouteGroupView({
446
443
  style: styles.groupHeaderLeft,
447
444
  children: [isExpanded ? /*#__PURE__*/(0, _jsxRuntime.jsx)(_sharedUi.ChevronDown, {
448
445
  size: 14,
449
- color: _sharedUi.buoyColors.textSecondary
446
+ color: _sharedUi.night.color.textSecondary
450
447
  }) : /*#__PURE__*/(0, _jsxRuntime.jsx)(_sharedUi.ChevronRight, {
451
448
  size: 14,
452
- color: _sharedUi.buoyColors.textSecondary
449
+ color: _sharedUi.night.color.textSecondary
453
450
  }), /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.Text, {
454
451
  style: styles.groupTitle,
455
452
  children: group.title
@@ -506,10 +503,10 @@ function RouteItemView({
506
503
  style: styles.expandIndicator,
507
504
  children: isExpanded ? /*#__PURE__*/(0, _jsxRuntime.jsx)(_sharedUi.ChevronDown, {
508
505
  size: 14,
509
- color: _sharedUi.buoyColors.textSecondary
506
+ color: _sharedUi.night.color.textSecondary
510
507
  }) : /*#__PURE__*/(0, _jsxRuntime.jsx)(_sharedUi.ChevronRight, {
511
508
  size: 14,
512
- color: _sharedUi.buoyColors.textSecondary
509
+ color: _sharedUi.night.color.textSecondary
513
510
  })
514
511
  }), /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.Text, {
515
512
  style: styles.routePath,
@@ -613,7 +610,8 @@ function getRouteTypeColor(type) {
613
610
  const styles = _reactNative.StyleSheet.create({
614
611
  container: {
615
612
  flex: 1,
616
- backgroundColor: _sharedUi.buoyColors.base
613
+ // Transparent so JsModal's ToolBackground shows through (the modal paints opaque base beneath it).
614
+ backgroundColor: "transparent"
617
615
  },
618
616
  loadingContainer: {
619
617
  flex: 1,
@@ -621,7 +619,7 @@ const styles = _reactNative.StyleSheet.create({
621
619
  alignItems: "center"
622
620
  },
623
621
  loadingText: {
624
- color: _sharedUi.buoyColors.textSecondary,
622
+ color: _sharedUi.night.color.textSecondary,
625
623
  fontSize: 14,
626
624
  fontFamily: "monospace",
627
625
  textAlign: "center",
@@ -633,8 +631,9 @@ const styles = _reactNative.StyleSheet.create({
633
631
  flexDirection: "column",
634
632
  padding: 8,
635
633
  borderBottomWidth: 1,
636
- borderBottomColor: _sharedUi.buoyColors.border,
637
- gap: 12
634
+ borderBottomColor: _sharedUi.night.color.border,
635
+ gap: 12,
636
+ marginBottom: 8
638
637
  },
639
638
  actionsRow: {
640
639
  flexDirection: "row",
@@ -653,7 +652,7 @@ const styles = _reactNative.StyleSheet.create({
653
652
  flexShrink: 1,
654
653
  flexBasis: "30%",
655
654
  minWidth: 90,
656
- backgroundColor: _sharedUi.buoyColors.card,
655
+ backgroundColor: _sharedUi.night.color.surface,
657
656
  borderRadius: 8,
658
657
  paddingVertical: 10,
659
658
  paddingHorizontal: 12,
@@ -662,12 +661,12 @@ const styles = _reactNative.StyleSheet.create({
662
661
  statValue: {
663
662
  fontSize: 18,
664
663
  fontWeight: "800",
665
- color: _sharedUi.buoyColors.text,
664
+ color: _sharedUi.night.color.text,
666
665
  fontFamily: "monospace"
667
666
  },
668
667
  statLabel: {
669
668
  fontSize: 10,
670
- color: _sharedUi.buoyColors.textMuted,
669
+ color: _sharedUi.night.color.textTertiary,
671
670
  marginTop: 4,
672
671
  fontFamily: "monospace",
673
672
  textTransform: "uppercase",
@@ -687,12 +686,12 @@ const styles = _reactNative.StyleSheet.create({
687
686
  actionButtonHeader: {
688
687
  padding: 6,
689
688
  borderRadius: 4,
690
- backgroundColor: _sharedUi.buoyColors.input
689
+ backgroundColor: _sharedUi.night.color.surfaceElevated
691
690
  },
692
691
  actionButtonHeaderDesktop: {
693
692
  padding: 12,
694
693
  borderRadius: 8,
695
- backgroundColor: _sharedUi.buoyColors.input
694
+ backgroundColor: _sharedUi.night.color.surfaceElevated
696
695
  },
697
696
  iconButton: {
698
697
  padding: 6,
@@ -703,11 +702,11 @@ const styles = _reactNative.StyleSheet.create({
703
702
  iconButtonDesktop: {
704
703
  padding: 12,
705
704
  borderRadius: 8,
706
- backgroundColor: _sharedUi.buoyColors.input
705
+ backgroundColor: _sharedUi.night.color.surfaceElevated
707
706
  },
708
707
  actionLabel: {
709
708
  fontSize: 8,
710
- color: _sharedUi.buoyColors.textMuted,
709
+ color: _sharedUi.night.color.textTertiary,
711
710
  fontFamily: "monospace",
712
711
  textTransform: "uppercase",
713
712
  letterSpacing: 0.5
@@ -727,11 +726,11 @@ const styles = _reactNative.StyleSheet.create({
727
726
  paddingVertical: 16,
728
727
  marginTop: 16,
729
728
  borderTopWidth: 1,
730
- borderTopColor: _sharedUi.buoyColors.border
729
+ borderTopColor: _sharedUi.night.color.border
731
730
  },
732
731
  metaText: {
733
732
  fontSize: 12,
734
- color: _sharedUi.buoyColors.textSecondary,
733
+ color: _sharedUi.night.color.textSecondary,
735
734
  fontFamily: "monospace"
736
735
  },
737
736
  sourceBadge: {
@@ -739,12 +738,12 @@ const styles = _reactNative.StyleSheet.create({
739
738
  paddingVertical: 2,
740
739
  borderRadius: 999,
741
740
  borderWidth: 1,
742
- borderColor: _sharedUi.buoyColors.border,
743
- backgroundColor: _sharedUi.buoyColors.card
741
+ borderColor: _sharedUi.night.color.border,
742
+ backgroundColor: _sharedUi.night.color.surface
744
743
  },
745
744
  sourceText: {
746
745
  fontSize: 11,
747
- color: _sharedUi.buoyColors.textSecondary,
746
+ color: _sharedUi.night.color.textSecondary,
748
747
  textTransform: "capitalize",
749
748
  fontFamily: "monospace"
750
749
  },
@@ -754,11 +753,11 @@ const styles = _reactNative.StyleSheet.create({
754
753
  padding: 8,
755
754
  gap: 8,
756
755
  borderBottomWidth: 1,
757
- borderBottomColor: _sharedUi.buoyColors.border
756
+ borderBottomColor: _sharedUi.night.color.border
758
757
  },
759
758
  searchInput: {
760
759
  flex: 1,
761
- color: _sharedUi.buoyColors.text,
760
+ color: _sharedUi.night.color.text,
762
761
  fontSize: 14,
763
762
  fontFamily: "monospace"
764
763
  },
@@ -766,7 +765,7 @@ const styles = _reactNative.StyleSheet.create({
766
765
  padding: 4
767
766
  },
768
767
  clearButtonText: {
769
- color: _sharedUi.buoyColors.textMuted,
768
+ color: _sharedUi.night.color.textTertiary,
770
769
  fontSize: 18
771
770
  },
772
771
  closeSearchButton: {
@@ -774,7 +773,7 @@ const styles = _reactNative.StyleSheet.create({
774
773
  paddingVertical: 4
775
774
  },
776
775
  closeSearchText: {
777
- color: _sharedUi.buoyColors.primary,
776
+ color: _sharedUi.night.color.accent,
778
777
  fontSize: 14,
779
778
  fontWeight: "600",
780
779
  fontFamily: "monospace"
@@ -783,14 +782,14 @@ const styles = _reactNative.StyleSheet.create({
783
782
  flex: 1
784
783
  },
785
784
  scrollContent: {
786
- paddingVertical: 8
785
+ paddingBottom: 8
787
786
  },
788
787
  emptyState: {
789
788
  padding: 32,
790
789
  alignItems: "center"
791
790
  },
792
791
  emptyText: {
793
- color: _sharedUi.buoyColors.textSecondary,
792
+ color: _sharedUi.night.color.textSecondary,
794
793
  fontSize: 14,
795
794
  fontFamily: "monospace"
796
795
  },
@@ -803,9 +802,9 @@ const styles = _reactNative.StyleSheet.create({
803
802
  justifyContent: "space-between",
804
803
  padding: 12,
805
804
  paddingHorizontal: 16,
806
- backgroundColor: _sharedUi.buoyColors.card,
805
+ backgroundColor: _sharedUi.night.color.surface,
807
806
  borderLeftWidth: 3,
808
- borderLeftColor: _sharedUi.buoyColors.textSecondary
807
+ borderLeftColor: _sharedUi.night.color.fillTertiary
809
808
  },
810
809
  groupHeaderLeft: {
811
810
  flexDirection: "row",
@@ -816,7 +815,7 @@ const styles = _reactNative.StyleSheet.create({
816
815
  groupTitle: {
817
816
  fontSize: 12,
818
817
  fontWeight: "700",
819
- color: _sharedUi.buoyColors.text,
818
+ color: _sharedUi.night.color.text,
820
819
  fontFamily: "monospace",
821
820
  textTransform: "uppercase",
822
821
  letterSpacing: 0.8
@@ -839,19 +838,20 @@ const styles = _reactNative.StyleSheet.create({
839
838
  fontFamily: "monospace"
840
839
  },
841
840
  routesList: {
842
- backgroundColor: _sharedUi.buoyColors.base
841
+ // Transparent so the night sheet's star field shows through.
842
+ backgroundColor: "transparent"
843
843
  },
844
844
  groupDescription: {
845
845
  paddingHorizontal: 16,
846
846
  paddingVertical: 8,
847
847
  marginBottom: 8,
848
- backgroundColor: _sharedUi.buoyColors.input,
848
+ backgroundColor: _sharedUi.night.color.surfaceElevated,
849
849
  borderLeftWidth: 3,
850
- borderLeftColor: _sharedUi.buoyColors.textSecondary
850
+ borderLeftColor: _sharedUi.night.color.fillTertiary
851
851
  },
852
852
  groupDescriptionText: {
853
853
  fontSize: 11,
854
- color: _sharedUi.buoyColors.textSecondary,
854
+ color: _sharedUi.night.color.textSecondary,
855
855
  fontFamily: "monospace",
856
856
  lineHeight: 16
857
857
  },
@@ -859,10 +859,10 @@ const styles = _reactNative.StyleSheet.create({
859
859
  marginBottom: 6
860
860
  },
861
861
  routeCard: {
862
- backgroundColor: _sharedUi.buoyColors.card,
862
+ backgroundColor: _sharedUi.night.color.surface,
863
863
  borderRadius: 6,
864
864
  borderWidth: 1,
865
- borderColor: _sharedUi.buoyColors.border,
865
+ borderColor: _sharedUi.night.color.border,
866
866
  overflow: "hidden",
867
867
  shadowColor: "#000",
868
868
  shadowOffset: {
@@ -894,7 +894,7 @@ const styles = _reactNative.StyleSheet.create({
894
894
  routePath: {
895
895
  fontSize: 13,
896
896
  fontWeight: "600",
897
- color: _sharedUi.buoyColors.text,
897
+ color: _sharedUi.night.color.text,
898
898
  fontFamily: "monospace",
899
899
  flex: 1
900
900
  },
@@ -917,7 +917,7 @@ const styles = _reactNative.StyleSheet.create({
917
917
  childCountText: {
918
918
  fontSize: 11,
919
919
  fontWeight: "600",
920
- color: _sharedUi.macOSColors.text.icon,
920
+ color: _sharedUi.night.color.textSecondary,
921
921
  fontFamily: "monospace"
922
922
  },
923
923
  typeTag: {
@@ -936,9 +936,9 @@ const styles = _reactNative.StyleSheet.create({
936
936
  width: 28,
937
937
  height: 24,
938
938
  borderRadius: 4,
939
- backgroundColor: _sharedUi.buoyColors.input,
939
+ backgroundColor: _sharedUi.night.color.surfaceElevated,
940
940
  borderWidth: 1,
941
- borderColor: _sharedUi.buoyColors.border,
941
+ borderColor: _sharedUi.night.color.border,
942
942
  alignItems: "center",
943
943
  justifyContent: "center"
944
944
  },
@@ -949,19 +949,19 @@ const styles = _reactNative.StyleSheet.create({
949
949
  borderRadius: 4,
950
950
  alignItems: "center",
951
951
  justifyContent: "center",
952
- backgroundColor: _sharedUi.buoyColors.primary + "15",
952
+ backgroundColor: _sharedUi.night.color.accentSoft,
953
953
  borderWidth: 1,
954
- borderColor: _sharedUi.buoyColors.primary + "40"
954
+ borderColor: _sharedUi.night.color.accentBorder
955
955
  },
956
956
  goButtonText: {
957
957
  fontSize: 12,
958
- color: _sharedUi.buoyColors.primary,
958
+ color: _sharedUi.night.color.accent,
959
959
  fontFamily: "monospace",
960
960
  fontWeight: "600"
961
961
  },
962
962
  childrenContainer: {
963
963
  borderLeftWidth: 2,
964
- borderLeftColor: _sharedUi.buoyColors.border,
964
+ borderLeftColor: _sharedUi.night.color.border,
965
965
  marginLeft: 16,
966
966
  marginRight: 8,
967
967
  marginTop: 2,
@@ -123,7 +123,8 @@ const routeEventsSyncAdapter = exports.routeEventsSyncAdapter = {
123
123
  * dynamic params into a concrete path before invoking this.
124
124
  */
125
125
  navigate: params => {
126
- const path = params?.path;
126
+ const p = params;
127
+ const path = p?.path;
127
128
  if (!path) {
128
129
  throw new Error("navigate requires a 'path' param");
129
130
  }
@@ -131,9 +132,14 @@ const routeEventsSyncAdapter = exports.routeEventsSyncAdapter = {
131
132
  if (!router) {
132
133
  throw new Error("expo-router is not available on this device");
133
134
  }
134
- router.navigate(path);
135
+ // Push by default so navigate-then-back flows keep working. Callers that
136
+ // mean "leave this screen" (sitemap Go, agents resetting to home) pass
137
+ // replace: true — otherwise "Go to home" stacks another `/` on top.
138
+ const go = p?.replace === true && typeof router.replace === "function" ? router.replace : router.navigate;
139
+ go(path);
135
140
  return {
136
- navigated: path
141
+ navigated: path,
142
+ replaced: p?.replace === true
137
143
  };
138
144
  },
139
145
  // ── Stack actions: delegate to the live navigation actions captured by
@@ -19,12 +19,11 @@ var _sharedUi = require("@buoy-gg/shared-ui");
19
19
  * - RN CLI: uses NavigationContainerRefContext (works as sibling of navigators)
20
20
  */
21
21
 
22
- // Resolved once at module load; null when @react-navigation/native is absent
23
- // (the fallback context then yields an undefined containerRef, so the
24
- // dispatch paths below never execute).
22
+ // Resolved once at module load; null when React Navigation is absent
23
+ // (useSafeNavigationContainerRef then yields undefined, so the dispatch
24
+ // paths below never execute).
25
25
  const CommonActions = (0, _safeReactNavigation.getCommonActions)();
26
26
  const StackActions = (0, _safeReactNavigation.getStackActions)();
27
- const NavigationContainerRefContext = (0, _safeReactNavigation.getNavigationContainerRefContext)();
28
27
 
29
28
  // ============================================================================
30
29
  // Type Definitions
@@ -202,7 +201,7 @@ function buildStack(navigationState, isExpo) {
202
201
  */
203
202
  function useNavigationStack() {
204
203
  const isExpo = (0, _sharedUi.isExpoRouterAvailable)();
205
- const containerRef = (0, _react.useContext)(NavigationContainerRefContext);
204
+ const containerRef = (0, _safeReactNavigation.useSafeNavigationContainerRef)();
206
205
  const [navigationState, setNavigationState] = (0, _react.useState)(() => containerRef?.getRootState?.() ?? null);
207
206
  const [isLoaded, setIsLoaded] = (0, _react.useState)(false);
208
207
  const [error, setError] = (0, _react.useState)(null);
@@ -18,10 +18,6 @@ var _RouteObserver = require("./RouteObserver");
18
18
  * a NavigationContainer — does NOT need to be inside a navigator.
19
19
  */
20
20
 
21
- // Resolved once at module load; falls back to an always-undefined context
22
- // when @react-navigation/native is absent, so the effect below no-ops.
23
- const NavigationContainerRefContext = (0, _safeReactNavigation.getNavigationContainerRefContext)();
24
-
25
21
  /**
26
22
  * Walk a React Navigation state tree to find the deepest focused route.
27
23
  * Returns the route object and the array of route names from root to leaf.
@@ -85,7 +81,7 @@ function emitRouteEvent(state, previousPathnameRef, previousTimestampRef, callba
85
81
  * Works anywhere inside a NavigationContainer (does not need to be inside a navigator).
86
82
  */
87
83
  function useRouteObserverReactNavigation(callback) {
88
- const containerRef = (0, _react.useContext)(NavigationContainerRefContext);
84
+ const containerRef = (0, _safeReactNavigation.useSafeNavigationContainerRef)();
89
85
  const callbackRef = (0, _react.useRef)(callback);
90
86
  const previousPathnameRef = (0, _react.useRef)(undefined);
91
87
  const previousTimestampRef = (0, _react.useRef)(undefined);
@@ -4,10 +4,10 @@ Object.defineProperty(exports, "__esModule", {
4
4
  value: true
5
5
  });
6
6
  exports.getCommonActions = getCommonActions;
7
- exports.getNavigationContainerRefContext = getNavigationContainerRefContext;
8
7
  exports.getStackActions = getStackActions;
9
8
  exports.isReactNavigationAvailable = isReactNavigationAvailable;
10
9
  exports.useSafeNavigation = useSafeNavigation;
10
+ exports.useSafeNavigationContainerRef = useSafeNavigationContainerRef;
11
11
  exports.useSafeNavigationState = useSafeNavigationState;
12
12
  var _react = require("react");
13
13
  /**
@@ -20,6 +20,31 @@ var _react = require("react");
20
20
  let reactNavigation = null;
21
21
  let isAvailable = false;
22
22
  let checkedAvailability = false;
23
+
24
+ // Expo Router (SDK 54+) VENDORS React Navigation: its NavigationContainer
25
+ // provides the vendored NavigationContainerRefContext from
26
+ // expo-router/build/react-navigation, NOT the one exported by the
27
+ // @react-navigation/native package (which may not even be installed, or is a
28
+ // second module instance whose context nobody provides). Reading only the npm
29
+ // context in such apps yields undefined forever — the Stack tab then hangs on
30
+ // "Loading navigation stack...". So we load both copies and consult both
31
+ // contexts.
32
+ let vendoredReactNavigation = null;
33
+ let checkedVendored = false;
34
+ function getVendoredReactNavigation() {
35
+ if (checkedVendored) return vendoredReactNavigation;
36
+ checkedVendored = true;
37
+ try {
38
+ // Compat entry re-exporting the vendored native/core/routers modules.
39
+ // Older expo-router versions (and RN CLI apps) don't have it — the
40
+ // require throws and we stay on @react-navigation/native.
41
+ const vendored = require("expo-router/react-navigation");
42
+ vendoredReactNavigation = vendored?.NavigationContainerRefContext ? vendored : null;
43
+ } catch {
44
+ vendoredReactNavigation = null;
45
+ }
46
+ return vendoredReactNavigation;
47
+ }
23
48
  function checkReactNavigationAvailability() {
24
49
  if (checkedAvailability) return isAvailable;
25
50
  try {
@@ -29,6 +54,17 @@ function checkReactNavigationAvailability() {
29
54
  isAvailable = false;
30
55
  reactNavigation = null;
31
56
  }
57
+
58
+ // Expo Router apps don't necessarily install @react-navigation/native at
59
+ // all — the vendored copy then supplies CommonActions/StackActions/hooks
60
+ // (actions are plain serializable objects, so either copy's work).
61
+ if (!isAvailable) {
62
+ const vendored = getVendoredReactNavigation();
63
+ if (vendored) {
64
+ reactNavigation = vendored;
65
+ isAvailable = true;
66
+ }
67
+ }
32
68
  checkedAvailability = true;
33
69
  return isAvailable;
34
70
  }
@@ -120,13 +156,33 @@ function getStackActions() {
120
156
  return checkReactNavigationAvailability() ? reactNavigation.StackActions : null;
121
157
  }
122
158
 
159
+ // Both contexts are resolved ONCE and cached so hook identity/order stays
160
+ // stable for the app lifetime (module presence is constant).
161
+ let npmContainerRefContext = null;
162
+ let vendoredContainerRefContext = null;
163
+ function getContainerRefContexts() {
164
+ if (npmContainerRefContext == null) {
165
+ npmContainerRefContext = checkReactNavigationAvailability() && reactNavigation.NavigationContainerRefContext ? reactNavigation.NavigationContainerRefContext : FallbackNavigationContainerRefContext;
166
+ }
167
+ if (vendoredContainerRefContext == null) {
168
+ const vendored = getVendoredReactNavigation();
169
+ vendoredContainerRefContext = vendored?.NavigationContainerRefContext ?? FallbackNavigationContainerRefContext;
170
+ }
171
+ return [npmContainerRefContext, vendoredContainerRefContext];
172
+ }
173
+
123
174
  /**
124
- * NavigationContainerRefContext, read via @react-navigation/native's
125
- * re-export (never from @react-navigation/core directly — core is not a
126
- * declared dependency). Falls back to an always-undefined context.
175
+ * The navigation container ref for THIS app, whichever module instance
176
+ * provides it: @react-navigation/native's NavigationContainerRefContext
177
+ * (RN CLI, older expo-router) or Expo Router's vendored copy (SDK 54+).
178
+ * Returns undefined when rendered outside any NavigationContainer or when
179
+ * React Navigation is absent entirely.
127
180
  */
128
- function getNavigationContainerRefContext() {
129
- return checkReactNavigationAvailability() && reactNavigation.NavigationContainerRefContext ? reactNavigation.NavigationContainerRefContext : FallbackNavigationContainerRefContext;
181
+ function useSafeNavigationContainerRef() {
182
+ const [npmCtx, vendoredCtx] = getContainerRefContexts();
183
+ const npmRef = (0, _react.useContext)(npmCtx);
184
+ const vendoredRef = (0, _react.useContext)(vendoredCtx);
185
+ return npmRef ?? vendoredRef;
130
186
  }
131
187
 
132
188
  // ============================================================================