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