@buoy-gg/route-events 3.0.2 → 4.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/lib/commonjs/components/NavigationStack.js +59 -94
- package/lib/commonjs/components/RouteEventsModalWithTabs.js +11 -4
- package/lib/commonjs/components/RoutesSitemap.js +54 -61
- package/lib/module/components/NavigationStack.js +60 -95
- package/lib/module/components/RouteEventsModalWithTabs.js +11 -4
- package/lib/module/components/RoutesSitemap.js +56 -63
- package/lib/typescript/components/NavigationStack.d.ts +7 -1
- package/lib/typescript/components/NavigationStack.d.ts.map +1 -1
- package/lib/typescript/components/RouteEventsModalWithTabs.d.ts.map +1 -1
- package/lib/typescript/components/RoutesSitemap.d.ts.map +1 -1
- package/package.json +6 -6
|
@@ -31,10 +31,14 @@ var _jsxRuntime = require("react/jsx-runtime");
|
|
|
31
31
|
function NavigationStack({
|
|
32
32
|
style,
|
|
33
33
|
injectedStack,
|
|
34
|
-
onAction
|
|
34
|
+
onAction,
|
|
35
|
+
onCopyValueChange
|
|
35
36
|
}) {
|
|
36
37
|
const hookResult = (0, _useNavigationStack.useNavigationStack)();
|
|
37
38
|
const isInjected = injectedStack != null;
|
|
39
|
+
const insets = (0, _sharedUi.useSafeAreaInsets)({
|
|
40
|
+
minBottom: 8
|
|
41
|
+
});
|
|
38
42
|
|
|
39
43
|
// Data source: injected (dashboard) or the local navigation container.
|
|
40
44
|
const stack = isInjected ? injectedStack : hookResult.stack;
|
|
@@ -51,7 +55,6 @@ function NavigationStack({
|
|
|
51
55
|
const goBack = () => onAction ? onAction("goBack") : hookResult.goBack();
|
|
52
56
|
const popToTop = () => onAction ? onAction("popToTop") : hookResult.popToTop();
|
|
53
57
|
const [expandedIndex, setExpandedIndex] = (0, _react.useState)(null);
|
|
54
|
-
const [showHelp, setShowHelp] = (0, _react.useState)(false);
|
|
55
58
|
const [showUpgradeModal, setShowUpgradeModal] = (0, _react.useState)(false);
|
|
56
59
|
|
|
57
60
|
// Check Pro status internally
|
|
@@ -76,6 +79,12 @@ function NavigationStack({
|
|
|
76
79
|
return JSON.stringify(stackData, null, 2);
|
|
77
80
|
}, [stack]);
|
|
78
81
|
|
|
82
|
+
// Report the copy payload up so the host can render the copy button in the
|
|
83
|
+
// shared navbar.
|
|
84
|
+
(0, _react.useEffect)(() => {
|
|
85
|
+
onCopyValueChange?.(stackDataForCopy);
|
|
86
|
+
}, [stackDataForCopy, onCopyValueChange]);
|
|
87
|
+
|
|
79
88
|
// Determine which route actions should operate on
|
|
80
89
|
// If a stack item is expanded, actions target that route
|
|
81
90
|
// Otherwise, actions target the focused (visible) route
|
|
@@ -229,23 +238,10 @@ function NavigationStack({
|
|
|
229
238
|
};
|
|
230
239
|
return /*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNative.View, {
|
|
231
240
|
style: [styles.container, style],
|
|
232
|
-
children: [/*#__PURE__*/(0, _jsxRuntime.
|
|
233
|
-
style: styles.header,
|
|
234
|
-
children: [/*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.TouchableOpacity, {
|
|
235
|
-
style: [styles.iconButton, showHelp && styles.iconButtonActive],
|
|
236
|
-
onPress: () => setShowHelp(!showHelp),
|
|
237
|
-
children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_sharedUi.Info, {
|
|
238
|
-
size: 16,
|
|
239
|
-
color: showHelp ? _sharedUi.buoyColors.primary : _sharedUi.buoyColors.textSecondary
|
|
240
|
-
})
|
|
241
|
-
}), /*#__PURE__*/(0, _jsxRuntime.jsx)(_sharedUi.InlineCopyButton, {
|
|
242
|
-
value: stackDataForCopy,
|
|
243
|
-
buttonStyle: styles.iconButton
|
|
244
|
-
})]
|
|
245
|
-
}), /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.ScrollView, {
|
|
241
|
+
children: [/*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.ScrollView, {
|
|
246
242
|
style: styles.stackScroll,
|
|
247
243
|
contentContainerStyle: [styles.stackContent, {
|
|
248
|
-
paddingBottom:
|
|
244
|
+
paddingBottom: styles.stackContent.padding + insets.bottom
|
|
249
245
|
}],
|
|
250
246
|
children: [...stack].reverse().map((item, reverseIndex) => {
|
|
251
247
|
const actualIndex = stack.length - 1 - reverseIndex;
|
|
@@ -314,59 +310,56 @@ function NavigationStack({
|
|
|
314
310
|
data: item.params,
|
|
315
311
|
showTypeFilter: false
|
|
316
312
|
})
|
|
313
|
+
}), /*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNative.View, {
|
|
314
|
+
style: styles.actionsRow,
|
|
315
|
+
children: [/*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNative.View, {
|
|
316
|
+
style: styles.actionWrapper,
|
|
317
|
+
children: [/*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.TouchableOpacity, {
|
|
318
|
+
style: [styles.actionButton, isAtRoot && styles.actionButtonDisabled],
|
|
319
|
+
onPress: handleGoBack,
|
|
320
|
+
disabled: isAtRoot,
|
|
321
|
+
children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.Text, {
|
|
322
|
+
style: [styles.actionButtonText, isAtRoot && styles.actionButtonTextDisabled],
|
|
323
|
+
children: "Back"
|
|
324
|
+
})
|
|
325
|
+
}), /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.Text, {
|
|
326
|
+
style: styles.helpText,
|
|
327
|
+
children: "Go back one screen"
|
|
328
|
+
})]
|
|
329
|
+
}), /*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNative.View, {
|
|
330
|
+
style: styles.actionWrapper,
|
|
331
|
+
children: [/*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.TouchableOpacity, {
|
|
332
|
+
style: [styles.actionButton, item.isFocused && styles.actionButtonDisabled],
|
|
333
|
+
onPress: handleGo,
|
|
334
|
+
disabled: item.isFocused,
|
|
335
|
+
children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.Text, {
|
|
336
|
+
style: [styles.actionButtonText, item.isFocused && styles.actionButtonTextDisabled],
|
|
337
|
+
children: "Go"
|
|
338
|
+
})
|
|
339
|
+
}), /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.Text, {
|
|
340
|
+
style: styles.helpText,
|
|
341
|
+
children: "Navigate to this route"
|
|
342
|
+
})]
|
|
343
|
+
}), /*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNative.View, {
|
|
344
|
+
style: styles.actionWrapper,
|
|
345
|
+
children: [/*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.TouchableOpacity, {
|
|
346
|
+
style: [styles.actionButton, (item.isFocused || actualIndex === stackDepth - 1) && styles.actionButtonDisabled],
|
|
347
|
+
onPress: handlePopTo,
|
|
348
|
+
disabled: item.isFocused || actualIndex === stackDepth - 1,
|
|
349
|
+
children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.Text, {
|
|
350
|
+
style: [styles.actionButtonText, (item.isFocused || actualIndex === stackDepth - 1) && styles.actionButtonTextDisabled],
|
|
351
|
+
children: "Pop To"
|
|
352
|
+
})
|
|
353
|
+
}), /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.Text, {
|
|
354
|
+
style: styles.helpText,
|
|
355
|
+
children: "Remove screens above this"
|
|
356
|
+
})]
|
|
357
|
+
})]
|
|
317
358
|
})]
|
|
318
359
|
})]
|
|
319
360
|
})
|
|
320
361
|
}, `stack-${actualIndex}-${item.key}`);
|
|
321
362
|
})
|
|
322
|
-
}), /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.View, {
|
|
323
|
-
style: styles.actionsContainer,
|
|
324
|
-
children: /*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNative.View, {
|
|
325
|
-
style: styles.actionsRow,
|
|
326
|
-
children: [/*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNative.View, {
|
|
327
|
-
style: styles.actionWrapper,
|
|
328
|
-
children: [/*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.TouchableOpacity, {
|
|
329
|
-
style: [styles.actionButton, isAtRoot && styles.actionButtonDisabled],
|
|
330
|
-
onPress: handleGoBack,
|
|
331
|
-
disabled: isAtRoot,
|
|
332
|
-
children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.Text, {
|
|
333
|
-
style: [styles.actionButtonText, isAtRoot && styles.actionButtonTextDisabled],
|
|
334
|
-
children: "Back"
|
|
335
|
-
})
|
|
336
|
-
}), showHelp && /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.Text, {
|
|
337
|
-
style: styles.helpText,
|
|
338
|
-
children: "Go back one screen"
|
|
339
|
-
})]
|
|
340
|
-
}), /*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNative.View, {
|
|
341
|
-
style: styles.actionWrapper,
|
|
342
|
-
children: [/*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.TouchableOpacity, {
|
|
343
|
-
style: [styles.actionButton, selectedRoute?.isFocused && styles.actionButtonDisabled],
|
|
344
|
-
onPress: handleGo,
|
|
345
|
-
disabled: selectedRoute?.isFocused,
|
|
346
|
-
children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.Text, {
|
|
347
|
-
style: [styles.actionButtonText, selectedRoute?.isFocused && styles.actionButtonTextDisabled],
|
|
348
|
-
children: "Go"
|
|
349
|
-
})
|
|
350
|
-
}), showHelp && /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.Text, {
|
|
351
|
-
style: styles.helpText,
|
|
352
|
-
children: "Navigate to selected route"
|
|
353
|
-
})]
|
|
354
|
-
}), /*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNative.View, {
|
|
355
|
-
style: styles.actionWrapper,
|
|
356
|
-
children: [/*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.TouchableOpacity, {
|
|
357
|
-
style: [styles.actionButton, (selectedRoute?.isFocused || selectedRoute?.index === stackDepth - 1) && styles.actionButtonDisabled],
|
|
358
|
-
onPress: handlePopTo,
|
|
359
|
-
disabled: selectedRoute?.isFocused || selectedRoute?.index === stackDepth - 1,
|
|
360
|
-
children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.Text, {
|
|
361
|
-
style: [styles.actionButtonText, (selectedRoute?.isFocused || selectedRoute?.index === stackDepth - 1) && styles.actionButtonTextDisabled],
|
|
362
|
-
children: "Pop To"
|
|
363
|
-
})
|
|
364
|
-
}), showHelp && /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.Text, {
|
|
365
|
-
style: styles.helpText,
|
|
366
|
-
children: "Remove screens above selected"
|
|
367
|
-
})]
|
|
368
|
-
})]
|
|
369
|
-
})
|
|
370
363
|
}), /*#__PURE__*/(0, _jsxRuntime.jsx)(_sharedUi.ProUpgradeModal, {
|
|
371
364
|
visible: showUpgradeModal,
|
|
372
365
|
onClose: () => setShowUpgradeModal(false),
|
|
@@ -433,22 +426,6 @@ const styles = _reactNative.StyleSheet.create({
|
|
|
433
426
|
fontFamily: "monospace",
|
|
434
427
|
textAlign: "center"
|
|
435
428
|
},
|
|
436
|
-
header: {
|
|
437
|
-
flexDirection: "row",
|
|
438
|
-
padding: 8,
|
|
439
|
-
gap: 8,
|
|
440
|
-
borderBottomWidth: 1,
|
|
441
|
-
borderBottomColor: _sharedUi.buoyColors.border,
|
|
442
|
-
alignItems: "center",
|
|
443
|
-
justifyContent: "flex-end"
|
|
444
|
-
},
|
|
445
|
-
iconButton: {
|
|
446
|
-
padding: 6,
|
|
447
|
-
borderRadius: 4
|
|
448
|
-
},
|
|
449
|
-
iconButtonActive: {
|
|
450
|
-
backgroundColor: _sharedUi.buoyColors.input
|
|
451
|
-
},
|
|
452
429
|
stackScroll: {
|
|
453
430
|
flex: 1
|
|
454
431
|
},
|
|
@@ -528,22 +505,10 @@ const styles = _reactNative.StyleSheet.create({
|
|
|
528
505
|
marginHorizontal: -12,
|
|
529
506
|
marginBottom: 8
|
|
530
507
|
},
|
|
531
|
-
actionsContainer: {
|
|
532
|
-
position: "absolute",
|
|
533
|
-
left: 0,
|
|
534
|
-
right: 0,
|
|
535
|
-
bottom: 0,
|
|
536
|
-
borderTopWidth: 1,
|
|
537
|
-
borderTopColor: _sharedUi.buoyColors.border,
|
|
538
|
-
backgroundColor: _sharedUi.buoyColors.base,
|
|
539
|
-
paddingHorizontal: 8,
|
|
540
|
-
paddingTop: 8,
|
|
541
|
-
paddingBottom: 8
|
|
542
|
-
},
|
|
543
508
|
actionsRow: {
|
|
544
509
|
flexDirection: "row",
|
|
545
510
|
gap: 6,
|
|
546
|
-
|
|
511
|
+
marginTop: 12
|
|
547
512
|
},
|
|
548
513
|
actionWrapper: {
|
|
549
514
|
flex: 1
|
|
@@ -79,6 +79,9 @@ function RouteEventsModalWithTabs({
|
|
|
79
79
|
const hasExpoRouter = (0, _sharedUi.isExpoRouterAvailable)();
|
|
80
80
|
const [activeTab, setActiveTab] = (0, _react.useState)("events");
|
|
81
81
|
const [showUpgradeModal, setShowUpgradeModal] = (0, _react.useState)(false);
|
|
82
|
+
// Serialized stack reported up by NavigationStack so the copy button can live
|
|
83
|
+
// in the shared navbar.
|
|
84
|
+
const [stackCopyValue, setStackCopyValue] = (0, _react.useState)("");
|
|
82
85
|
|
|
83
86
|
// Check Pro status internally
|
|
84
87
|
const isPro = (0, _license.useIsPro)();
|
|
@@ -377,7 +380,8 @@ function RouteEventsModalWithTabs({
|
|
|
377
380
|
}
|
|
378
381
|
if (activeTab === "stack") {
|
|
379
382
|
return /*#__PURE__*/(0, _jsxRuntime.jsx)(_NavigationStack.NavigationStack, {
|
|
380
|
-
style: styles.contentWrapper
|
|
383
|
+
style: styles.contentWrapper,
|
|
384
|
+
onCopyValueChange: setStackCopyValue
|
|
381
385
|
});
|
|
382
386
|
}
|
|
383
387
|
|
|
@@ -482,8 +486,11 @@ function RouteEventsModalWithTabs({
|
|
|
482
486
|
activeTab: activeTab,
|
|
483
487
|
onTabChange: tab => setActiveTab(tab)
|
|
484
488
|
})
|
|
485
|
-
}), /*#__PURE__*/(0, _jsxRuntime.
|
|
486
|
-
children: activeTab === "
|
|
489
|
+
}), /*#__PURE__*/(0, _jsxRuntime.jsxs)(_sharedUi.ModalHeader.Actions, {
|
|
490
|
+
children: [activeTab === "stack" && /*#__PURE__*/(0, _jsxRuntime.jsx)(_sharedUi.ToolbarCopyButton, {
|
|
491
|
+
value: stackCopyValue,
|
|
492
|
+
buttonStyle: styles.iconButton
|
|
493
|
+
}), activeTab === "events" && /*#__PURE__*/(0, _jsxRuntime.jsxs)(_jsxRuntime.Fragment, {
|
|
487
494
|
children: [/*#__PURE__*/(0, _jsxRuntime.jsx)(_sharedUi.ToolbarCopyButton, {
|
|
488
495
|
value: copyAllEventsData,
|
|
489
496
|
buttonStyle: styles.iconButton
|
|
@@ -506,7 +513,7 @@ function RouteEventsModalWithTabs({
|
|
|
506
513
|
color: _sharedUi.buoyColors.error
|
|
507
514
|
})
|
|
508
515
|
})]
|
|
509
|
-
})
|
|
516
|
+
})]
|
|
510
517
|
})]
|
|
511
518
|
})
|
|
512
519
|
},
|
|
@@ -25,6 +25,11 @@ var _jsxRuntime = require("react/jsx-runtime");
|
|
|
25
25
|
// Types
|
|
26
26
|
// ============================================================================
|
|
27
27
|
|
|
28
|
+
// On desktop (web) the toolbar has far more room, so scale the action buttons
|
|
29
|
+
// up for easier clicking and a less cramped header.
|
|
30
|
+
const IS_DESKTOP = _reactNative.Platform.OS === "web";
|
|
31
|
+
const ACTION_ICON_SIZE = IS_DESKTOP ? 22 : 16;
|
|
32
|
+
|
|
28
33
|
// Synthetic route representing the app's home/index ("/"). Used by the
|
|
29
34
|
// "Home" toolbar shortcut so navigation works the same as tapping any route.
|
|
30
35
|
const HOME_ROUTE = {
|
|
@@ -168,7 +173,7 @@ function RoutesSitemap({
|
|
|
168
173
|
}
|
|
169
174
|
}], "plain-text");
|
|
170
175
|
}, [router]);
|
|
171
|
-
const handleNavigate = (0, _react.useCallback)(route => {
|
|
176
|
+
const handleNavigate = (0, _react.useCallback)((route, options) => {
|
|
172
177
|
// When a navigation delegate is supplied (dashboard → device), hand off
|
|
173
178
|
// entirely: the delegate owns Pro gating and param resolution.
|
|
174
179
|
if (onNavigateRoute) {
|
|
@@ -176,8 +181,8 @@ function RoutesSitemap({
|
|
|
176
181
|
return;
|
|
177
182
|
}
|
|
178
183
|
|
|
179
|
-
// Gate behind Pro
|
|
180
|
-
if (!isPro) {
|
|
184
|
+
// Gate behind Pro (the Home shortcut bypasses this — it's always free)
|
|
185
|
+
if (!isPro && !options?.bypassPro) {
|
|
181
186
|
setShowUpgradeModal(true);
|
|
182
187
|
return;
|
|
183
188
|
}
|
|
@@ -213,7 +218,9 @@ function RoutesSitemap({
|
|
|
213
218
|
}
|
|
214
219
|
}, [router, promptForParams, isPro, onNavigateRoute]);
|
|
215
220
|
const handleGoHome = (0, _react.useCallback)(() => {
|
|
216
|
-
handleNavigate(HOME_ROUTE
|
|
221
|
+
handleNavigate(HOME_ROUTE, {
|
|
222
|
+
bypassPro: true
|
|
223
|
+
});
|
|
217
224
|
}, [handleNavigate]);
|
|
218
225
|
const handleManualRefresh = (0, _react.useCallback)(() => {
|
|
219
226
|
if (isRefreshing) return;
|
|
@@ -261,53 +268,54 @@ function RoutesSitemap({
|
|
|
261
268
|
children: [/*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNative.View, {
|
|
262
269
|
style: styles.actionsRow,
|
|
263
270
|
children: [/*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNative.View, {
|
|
264
|
-
style: styles.actionWrapper,
|
|
271
|
+
style: [styles.actionWrapper, IS_DESKTOP && styles.actionWrapperDesktop],
|
|
265
272
|
children: [/*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.TouchableOpacity, {
|
|
266
|
-
style: styles.iconButton,
|
|
273
|
+
style: [styles.iconButton, IS_DESKTOP && styles.iconButtonDesktop],
|
|
267
274
|
onPress: handleGoHome,
|
|
268
275
|
accessibilityLabel: "Go to home route",
|
|
269
276
|
children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_sharedUi.Home, {
|
|
270
|
-
size:
|
|
277
|
+
size: ACTION_ICON_SIZE,
|
|
271
278
|
color: _sharedUi.buoyColors.textSecondary
|
|
272
279
|
})
|
|
273
280
|
}), /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.Text, {
|
|
274
|
-
style: styles.actionLabel,
|
|
281
|
+
style: [styles.actionLabel, IS_DESKTOP && styles.actionLabelDesktop],
|
|
275
282
|
children: "Home"
|
|
276
283
|
})]
|
|
277
284
|
}), /*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNative.View, {
|
|
278
|
-
style: styles.actionWrapper,
|
|
279
|
-
children: [/*#__PURE__*/(0, _jsxRuntime.jsx)(_sharedUi.
|
|
285
|
+
style: [styles.actionWrapper, IS_DESKTOP && styles.actionWrapperDesktop],
|
|
286
|
+
children: [/*#__PURE__*/(0, _jsxRuntime.jsx)(_sharedUi.CopyButton, {
|
|
280
287
|
value: copyAllData,
|
|
281
|
-
|
|
288
|
+
size: IS_DESKTOP ? ACTION_ICON_SIZE : 14,
|
|
289
|
+
buttonStyle: IS_DESKTOP ? styles.actionButtonHeaderDesktop : styles.actionButtonHeader
|
|
282
290
|
}), /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.Text, {
|
|
283
|
-
style: styles.actionLabel,
|
|
291
|
+
style: [styles.actionLabel, IS_DESKTOP && styles.actionLabelDesktop],
|
|
284
292
|
children: "Copy"
|
|
285
293
|
})]
|
|
286
294
|
}), /*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNative.View, {
|
|
287
|
-
style: styles.actionWrapper,
|
|
295
|
+
style: [styles.actionWrapper, IS_DESKTOP && styles.actionWrapperDesktop],
|
|
288
296
|
children: [/*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.TouchableOpacity, {
|
|
289
|
-
style: [styles.iconButton, isRefreshing && styles.refreshButtonDisabled],
|
|
297
|
+
style: [styles.iconButton, IS_DESKTOP && styles.iconButtonDesktop, isRefreshing && styles.refreshButtonDisabled],
|
|
290
298
|
onPress: handleManualRefresh,
|
|
291
299
|
disabled: isRefreshing,
|
|
292
300
|
children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_sharedUi.RefreshCw, {
|
|
293
|
-
size:
|
|
301
|
+
size: ACTION_ICON_SIZE,
|
|
294
302
|
color: isRefreshing ? _sharedUi.buoyColors.textMuted : _sharedUi.buoyColors.textSecondary
|
|
295
303
|
})
|
|
296
304
|
}), /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.Text, {
|
|
297
|
-
style: styles.actionLabel,
|
|
305
|
+
style: [styles.actionLabel, IS_DESKTOP && styles.actionLabelDesktop],
|
|
298
306
|
children: "Refresh"
|
|
299
307
|
})]
|
|
300
308
|
}), /*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNative.View, {
|
|
301
|
-
style: styles.actionWrapper,
|
|
309
|
+
style: [styles.actionWrapper, IS_DESKTOP && styles.actionWrapperDesktop],
|
|
302
310
|
children: [/*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.TouchableOpacity, {
|
|
303
|
-
style: styles.iconButton,
|
|
311
|
+
style: [styles.iconButton, IS_DESKTOP && styles.iconButtonDesktop],
|
|
304
312
|
onPress: () => setIsSearching(true),
|
|
305
313
|
children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_sharedUi.Search, {
|
|
306
|
-
size:
|
|
314
|
+
size: ACTION_ICON_SIZE,
|
|
307
315
|
color: _sharedUi.buoyColors.textSecondary
|
|
308
316
|
})
|
|
309
317
|
}), /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.Text, {
|
|
310
|
-
style: styles.actionLabel,
|
|
318
|
+
style: [styles.actionLabel, IS_DESKTOP && styles.actionLabelDesktop],
|
|
311
319
|
children: "Search"
|
|
312
320
|
})]
|
|
313
321
|
})]
|
|
@@ -453,18 +461,18 @@ function RouteGroupView({
|
|
|
453
461
|
children: group.routes.length
|
|
454
462
|
})
|
|
455
463
|
})]
|
|
456
|
-
}),
|
|
464
|
+
}), group.description && /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.View, {
|
|
465
|
+
style: styles.groupDescription,
|
|
466
|
+
children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.Text, {
|
|
467
|
+
style: styles.groupDescriptionText,
|
|
468
|
+
children: group.description
|
|
469
|
+
})
|
|
470
|
+
}), isExpanded && /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.View, {
|
|
457
471
|
style: styles.routesList,
|
|
458
|
-
children:
|
|
459
|
-
style: styles.groupDescription,
|
|
460
|
-
children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.Text, {
|
|
461
|
-
style: styles.groupDescriptionText,
|
|
462
|
-
children: group.description
|
|
463
|
-
})
|
|
464
|
-
}), group.routes.map((route, index) => /*#__PURE__*/(0, _jsxRuntime.jsx)(RouteItemView, {
|
|
472
|
+
children: group.routes.map((route, index) => /*#__PURE__*/(0, _jsxRuntime.jsx)(RouteItemView, {
|
|
465
473
|
route: route,
|
|
466
474
|
onNavigate: onNavigate
|
|
467
|
-
}, `${route.path}-${index}`))
|
|
475
|
+
}, `${route.path}-${index}`))
|
|
468
476
|
})]
|
|
469
477
|
});
|
|
470
478
|
}
|
|
@@ -475,7 +483,6 @@ function RouteItemView({
|
|
|
475
483
|
}) {
|
|
476
484
|
const [isExpanded, setIsExpanded] = (0, _react.useState)(false);
|
|
477
485
|
const hasChildren = route.children.length > 0;
|
|
478
|
-
const hasParams = route.params.length > 0;
|
|
479
486
|
const typeColor = getRouteTypeColor(route.type);
|
|
480
487
|
const canNavigate = route.type !== "layout" && route.type !== "group";
|
|
481
488
|
|
|
@@ -554,15 +561,6 @@ function RouteItemView({
|
|
|
554
561
|
})
|
|
555
562
|
})]
|
|
556
563
|
})]
|
|
557
|
-
}), showDetails && hasParams && /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.View, {
|
|
558
|
-
style: styles.paramsRow,
|
|
559
|
-
children: route.params.map(param => /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.View, {
|
|
560
|
-
style: styles.paramTag,
|
|
561
|
-
children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.Text, {
|
|
562
|
-
style: styles.paramText,
|
|
563
|
-
children: param
|
|
564
|
-
})
|
|
565
|
-
}, param))
|
|
566
564
|
}), showDetails && hasChildren && /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.View, {
|
|
567
565
|
style: styles.childrenContainer,
|
|
568
566
|
children: route.children.map((child, index) => /*#__PURE__*/(0, _jsxRuntime.jsx)(RouteItemView, {
|
|
@@ -682,17 +680,31 @@ const styles = _reactNative.StyleSheet.create({
|
|
|
682
680
|
gap: 4,
|
|
683
681
|
minWidth: 48
|
|
684
682
|
},
|
|
683
|
+
actionWrapperDesktop: {
|
|
684
|
+
gap: 8,
|
|
685
|
+
minWidth: 72
|
|
686
|
+
},
|
|
685
687
|
actionButtonHeader: {
|
|
686
688
|
padding: 6,
|
|
687
689
|
borderRadius: 4,
|
|
688
690
|
backgroundColor: _sharedUi.buoyColors.input
|
|
689
691
|
},
|
|
692
|
+
actionButtonHeaderDesktop: {
|
|
693
|
+
padding: 12,
|
|
694
|
+
borderRadius: 8,
|
|
695
|
+
backgroundColor: _sharedUi.buoyColors.input
|
|
696
|
+
},
|
|
690
697
|
iconButton: {
|
|
691
698
|
padding: 6,
|
|
692
699
|
borderRadius: 4,
|
|
693
700
|
alignItems: "center",
|
|
694
701
|
justifyContent: "center"
|
|
695
702
|
},
|
|
703
|
+
iconButtonDesktop: {
|
|
704
|
+
padding: 12,
|
|
705
|
+
borderRadius: 8,
|
|
706
|
+
backgroundColor: _sharedUi.buoyColors.input
|
|
707
|
+
},
|
|
696
708
|
actionLabel: {
|
|
697
709
|
fontSize: 8,
|
|
698
710
|
color: _sharedUi.buoyColors.textMuted,
|
|
@@ -700,6 +712,9 @@ const styles = _reactNative.StyleSheet.create({
|
|
|
700
712
|
textTransform: "uppercase",
|
|
701
713
|
letterSpacing: 0.5
|
|
702
714
|
},
|
|
715
|
+
actionLabelDesktop: {
|
|
716
|
+
fontSize: 12
|
|
717
|
+
},
|
|
703
718
|
refreshButtonDisabled: {
|
|
704
719
|
opacity: 0.5
|
|
705
720
|
},
|
|
@@ -944,28 +959,6 @@ const styles = _reactNative.StyleSheet.create({
|
|
|
944
959
|
fontFamily: "monospace",
|
|
945
960
|
fontWeight: "600"
|
|
946
961
|
},
|
|
947
|
-
paramsRow: {
|
|
948
|
-
flexDirection: "row",
|
|
949
|
-
flexWrap: "wrap",
|
|
950
|
-
gap: 6,
|
|
951
|
-
paddingHorizontal: 10,
|
|
952
|
-
paddingTop: 2,
|
|
953
|
-
paddingBottom: 8
|
|
954
|
-
},
|
|
955
|
-
paramTag: {
|
|
956
|
-
backgroundColor: "#F59E0B15",
|
|
957
|
-
borderColor: "#F59E0B40",
|
|
958
|
-
borderWidth: 1,
|
|
959
|
-
borderRadius: 4,
|
|
960
|
-
paddingHorizontal: 6,
|
|
961
|
-
paddingVertical: 2
|
|
962
|
-
},
|
|
963
|
-
paramText: {
|
|
964
|
-
fontSize: 10,
|
|
965
|
-
color: "#F59E0B",
|
|
966
|
-
fontFamily: "monospace",
|
|
967
|
-
fontWeight: "600"
|
|
968
|
-
},
|
|
969
962
|
childrenContainer: {
|
|
970
963
|
borderLeftWidth: 2,
|
|
971
964
|
borderLeftColor: _sharedUi.buoyColors.border,
|
|
@@ -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,
|
|
12
|
+
import { ChevronDown, ChevronRight, InlineCopyButton, ProUpgradeModal, buoyColors, useSafeAreaInsets } 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";
|
|
@@ -27,10 +27,14 @@ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
|
27
27
|
export function NavigationStack({
|
|
28
28
|
style,
|
|
29
29
|
injectedStack,
|
|
30
|
-
onAction
|
|
30
|
+
onAction,
|
|
31
|
+
onCopyValueChange
|
|
31
32
|
}) {
|
|
32
33
|
const hookResult = useNavigationStack();
|
|
33
34
|
const isInjected = injectedStack != null;
|
|
35
|
+
const insets = useSafeAreaInsets({
|
|
36
|
+
minBottom: 8
|
|
37
|
+
});
|
|
34
38
|
|
|
35
39
|
// Data source: injected (dashboard) or the local navigation container.
|
|
36
40
|
const stack = isInjected ? injectedStack : hookResult.stack;
|
|
@@ -47,7 +51,6 @@ export function NavigationStack({
|
|
|
47
51
|
const goBack = () => onAction ? onAction("goBack") : hookResult.goBack();
|
|
48
52
|
const popToTop = () => onAction ? onAction("popToTop") : hookResult.popToTop();
|
|
49
53
|
const [expandedIndex, setExpandedIndex] = useState(null);
|
|
50
|
-
const [showHelp, setShowHelp] = useState(false);
|
|
51
54
|
const [showUpgradeModal, setShowUpgradeModal] = useState(false);
|
|
52
55
|
|
|
53
56
|
// Check Pro status internally
|
|
@@ -72,6 +75,12 @@ export function NavigationStack({
|
|
|
72
75
|
return JSON.stringify(stackData, null, 2);
|
|
73
76
|
}, [stack]);
|
|
74
77
|
|
|
78
|
+
// Report the copy payload up so the host can render the copy button in the
|
|
79
|
+
// shared navbar.
|
|
80
|
+
useEffect(() => {
|
|
81
|
+
onCopyValueChange?.(stackDataForCopy);
|
|
82
|
+
}, [stackDataForCopy, onCopyValueChange]);
|
|
83
|
+
|
|
75
84
|
// Determine which route actions should operate on
|
|
76
85
|
// If a stack item is expanded, actions target that route
|
|
77
86
|
// Otherwise, actions target the focused (visible) route
|
|
@@ -225,23 +234,10 @@ export function NavigationStack({
|
|
|
225
234
|
};
|
|
226
235
|
return /*#__PURE__*/_jsxs(View, {
|
|
227
236
|
style: [styles.container, style],
|
|
228
|
-
children: [/*#__PURE__*/
|
|
229
|
-
style: styles.header,
|
|
230
|
-
children: [/*#__PURE__*/_jsx(TouchableOpacity, {
|
|
231
|
-
style: [styles.iconButton, showHelp && styles.iconButtonActive],
|
|
232
|
-
onPress: () => setShowHelp(!showHelp),
|
|
233
|
-
children: /*#__PURE__*/_jsx(Info, {
|
|
234
|
-
size: 16,
|
|
235
|
-
color: showHelp ? buoyColors.primary : buoyColors.textSecondary
|
|
236
|
-
})
|
|
237
|
-
}), /*#__PURE__*/_jsx(InlineCopyButton, {
|
|
238
|
-
value: stackDataForCopy,
|
|
239
|
-
buttonStyle: styles.iconButton
|
|
240
|
-
})]
|
|
241
|
-
}), /*#__PURE__*/_jsx(ScrollView, {
|
|
237
|
+
children: [/*#__PURE__*/_jsx(ScrollView, {
|
|
242
238
|
style: styles.stackScroll,
|
|
243
239
|
contentContainerStyle: [styles.stackContent, {
|
|
244
|
-
paddingBottom:
|
|
240
|
+
paddingBottom: styles.stackContent.padding + insets.bottom
|
|
245
241
|
}],
|
|
246
242
|
children: [...stack].reverse().map((item, reverseIndex) => {
|
|
247
243
|
const actualIndex = stack.length - 1 - reverseIndex;
|
|
@@ -310,59 +306,56 @@ export function NavigationStack({
|
|
|
310
306
|
data: item.params,
|
|
311
307
|
showTypeFilter: false
|
|
312
308
|
})
|
|
309
|
+
}), /*#__PURE__*/_jsxs(View, {
|
|
310
|
+
style: styles.actionsRow,
|
|
311
|
+
children: [/*#__PURE__*/_jsxs(View, {
|
|
312
|
+
style: styles.actionWrapper,
|
|
313
|
+
children: [/*#__PURE__*/_jsx(TouchableOpacity, {
|
|
314
|
+
style: [styles.actionButton, isAtRoot && styles.actionButtonDisabled],
|
|
315
|
+
onPress: handleGoBack,
|
|
316
|
+
disabled: isAtRoot,
|
|
317
|
+
children: /*#__PURE__*/_jsx(Text, {
|
|
318
|
+
style: [styles.actionButtonText, isAtRoot && styles.actionButtonTextDisabled],
|
|
319
|
+
children: "Back"
|
|
320
|
+
})
|
|
321
|
+
}), /*#__PURE__*/_jsx(Text, {
|
|
322
|
+
style: styles.helpText,
|
|
323
|
+
children: "Go back one screen"
|
|
324
|
+
})]
|
|
325
|
+
}), /*#__PURE__*/_jsxs(View, {
|
|
326
|
+
style: styles.actionWrapper,
|
|
327
|
+
children: [/*#__PURE__*/_jsx(TouchableOpacity, {
|
|
328
|
+
style: [styles.actionButton, item.isFocused && styles.actionButtonDisabled],
|
|
329
|
+
onPress: handleGo,
|
|
330
|
+
disabled: item.isFocused,
|
|
331
|
+
children: /*#__PURE__*/_jsx(Text, {
|
|
332
|
+
style: [styles.actionButtonText, item.isFocused && styles.actionButtonTextDisabled],
|
|
333
|
+
children: "Go"
|
|
334
|
+
})
|
|
335
|
+
}), /*#__PURE__*/_jsx(Text, {
|
|
336
|
+
style: styles.helpText,
|
|
337
|
+
children: "Navigate to this route"
|
|
338
|
+
})]
|
|
339
|
+
}), /*#__PURE__*/_jsxs(View, {
|
|
340
|
+
style: styles.actionWrapper,
|
|
341
|
+
children: [/*#__PURE__*/_jsx(TouchableOpacity, {
|
|
342
|
+
style: [styles.actionButton, (item.isFocused || actualIndex === stackDepth - 1) && styles.actionButtonDisabled],
|
|
343
|
+
onPress: handlePopTo,
|
|
344
|
+
disabled: item.isFocused || actualIndex === stackDepth - 1,
|
|
345
|
+
children: /*#__PURE__*/_jsx(Text, {
|
|
346
|
+
style: [styles.actionButtonText, (item.isFocused || actualIndex === stackDepth - 1) && styles.actionButtonTextDisabled],
|
|
347
|
+
children: "Pop To"
|
|
348
|
+
})
|
|
349
|
+
}), /*#__PURE__*/_jsx(Text, {
|
|
350
|
+
style: styles.helpText,
|
|
351
|
+
children: "Remove screens above this"
|
|
352
|
+
})]
|
|
353
|
+
})]
|
|
313
354
|
})]
|
|
314
355
|
})]
|
|
315
356
|
})
|
|
316
357
|
}, `stack-${actualIndex}-${item.key}`);
|
|
317
358
|
})
|
|
318
|
-
}), /*#__PURE__*/_jsx(View, {
|
|
319
|
-
style: styles.actionsContainer,
|
|
320
|
-
children: /*#__PURE__*/_jsxs(View, {
|
|
321
|
-
style: styles.actionsRow,
|
|
322
|
-
children: [/*#__PURE__*/_jsxs(View, {
|
|
323
|
-
style: styles.actionWrapper,
|
|
324
|
-
children: [/*#__PURE__*/_jsx(TouchableOpacity, {
|
|
325
|
-
style: [styles.actionButton, isAtRoot && styles.actionButtonDisabled],
|
|
326
|
-
onPress: handleGoBack,
|
|
327
|
-
disabled: isAtRoot,
|
|
328
|
-
children: /*#__PURE__*/_jsx(Text, {
|
|
329
|
-
style: [styles.actionButtonText, isAtRoot && styles.actionButtonTextDisabled],
|
|
330
|
-
children: "Back"
|
|
331
|
-
})
|
|
332
|
-
}), showHelp && /*#__PURE__*/_jsx(Text, {
|
|
333
|
-
style: styles.helpText,
|
|
334
|
-
children: "Go back one screen"
|
|
335
|
-
})]
|
|
336
|
-
}), /*#__PURE__*/_jsxs(View, {
|
|
337
|
-
style: styles.actionWrapper,
|
|
338
|
-
children: [/*#__PURE__*/_jsx(TouchableOpacity, {
|
|
339
|
-
style: [styles.actionButton, selectedRoute?.isFocused && styles.actionButtonDisabled],
|
|
340
|
-
onPress: handleGo,
|
|
341
|
-
disabled: selectedRoute?.isFocused,
|
|
342
|
-
children: /*#__PURE__*/_jsx(Text, {
|
|
343
|
-
style: [styles.actionButtonText, selectedRoute?.isFocused && styles.actionButtonTextDisabled],
|
|
344
|
-
children: "Go"
|
|
345
|
-
})
|
|
346
|
-
}), showHelp && /*#__PURE__*/_jsx(Text, {
|
|
347
|
-
style: styles.helpText,
|
|
348
|
-
children: "Navigate to selected route"
|
|
349
|
-
})]
|
|
350
|
-
}), /*#__PURE__*/_jsxs(View, {
|
|
351
|
-
style: styles.actionWrapper,
|
|
352
|
-
children: [/*#__PURE__*/_jsx(TouchableOpacity, {
|
|
353
|
-
style: [styles.actionButton, (selectedRoute?.isFocused || selectedRoute?.index === stackDepth - 1) && styles.actionButtonDisabled],
|
|
354
|
-
onPress: handlePopTo,
|
|
355
|
-
disabled: selectedRoute?.isFocused || selectedRoute?.index === stackDepth - 1,
|
|
356
|
-
children: /*#__PURE__*/_jsx(Text, {
|
|
357
|
-
style: [styles.actionButtonText, (selectedRoute?.isFocused || selectedRoute?.index === stackDepth - 1) && styles.actionButtonTextDisabled],
|
|
358
|
-
children: "Pop To"
|
|
359
|
-
})
|
|
360
|
-
}), showHelp && /*#__PURE__*/_jsx(Text, {
|
|
361
|
-
style: styles.helpText,
|
|
362
|
-
children: "Remove screens above selected"
|
|
363
|
-
})]
|
|
364
|
-
})]
|
|
365
|
-
})
|
|
366
359
|
}), /*#__PURE__*/_jsx(ProUpgradeModal, {
|
|
367
360
|
visible: showUpgradeModal,
|
|
368
361
|
onClose: () => setShowUpgradeModal(false),
|
|
@@ -429,22 +422,6 @@ const styles = StyleSheet.create({
|
|
|
429
422
|
fontFamily: "monospace",
|
|
430
423
|
textAlign: "center"
|
|
431
424
|
},
|
|
432
|
-
header: {
|
|
433
|
-
flexDirection: "row",
|
|
434
|
-
padding: 8,
|
|
435
|
-
gap: 8,
|
|
436
|
-
borderBottomWidth: 1,
|
|
437
|
-
borderBottomColor: buoyColors.border,
|
|
438
|
-
alignItems: "center",
|
|
439
|
-
justifyContent: "flex-end"
|
|
440
|
-
},
|
|
441
|
-
iconButton: {
|
|
442
|
-
padding: 6,
|
|
443
|
-
borderRadius: 4
|
|
444
|
-
},
|
|
445
|
-
iconButtonActive: {
|
|
446
|
-
backgroundColor: buoyColors.input
|
|
447
|
-
},
|
|
448
425
|
stackScroll: {
|
|
449
426
|
flex: 1
|
|
450
427
|
},
|
|
@@ -524,22 +501,10 @@ const styles = StyleSheet.create({
|
|
|
524
501
|
marginHorizontal: -12,
|
|
525
502
|
marginBottom: 8
|
|
526
503
|
},
|
|
527
|
-
actionsContainer: {
|
|
528
|
-
position: "absolute",
|
|
529
|
-
left: 0,
|
|
530
|
-
right: 0,
|
|
531
|
-
bottom: 0,
|
|
532
|
-
borderTopWidth: 1,
|
|
533
|
-
borderTopColor: buoyColors.border,
|
|
534
|
-
backgroundColor: buoyColors.base,
|
|
535
|
-
paddingHorizontal: 8,
|
|
536
|
-
paddingTop: 8,
|
|
537
|
-
paddingBottom: 8
|
|
538
|
-
},
|
|
539
504
|
actionsRow: {
|
|
540
505
|
flexDirection: "row",
|
|
541
506
|
gap: 6,
|
|
542
|
-
|
|
507
|
+
marginTop: 12
|
|
543
508
|
},
|
|
544
509
|
actionWrapper: {
|
|
545
510
|
flex: 1
|
|
@@ -77,6 +77,9 @@ export function RouteEventsModalWithTabs({
|
|
|
77
77
|
const hasExpoRouter = isExpoRouterAvailable();
|
|
78
78
|
const [activeTab, setActiveTab] = useState("events");
|
|
79
79
|
const [showUpgradeModal, setShowUpgradeModal] = useState(false);
|
|
80
|
+
// Serialized stack reported up by NavigationStack so the copy button can live
|
|
81
|
+
// in the shared navbar.
|
|
82
|
+
const [stackCopyValue, setStackCopyValue] = useState("");
|
|
80
83
|
|
|
81
84
|
// Check Pro status internally
|
|
82
85
|
const isPro = useIsPro();
|
|
@@ -375,7 +378,8 @@ export function RouteEventsModalWithTabs({
|
|
|
375
378
|
}
|
|
376
379
|
if (activeTab === "stack") {
|
|
377
380
|
return /*#__PURE__*/_jsx(NavigationStack, {
|
|
378
|
-
style: styles.contentWrapper
|
|
381
|
+
style: styles.contentWrapper,
|
|
382
|
+
onCopyValueChange: setStackCopyValue
|
|
379
383
|
});
|
|
380
384
|
}
|
|
381
385
|
|
|
@@ -480,8 +484,11 @@ export function RouteEventsModalWithTabs({
|
|
|
480
484
|
activeTab: activeTab,
|
|
481
485
|
onTabChange: tab => setActiveTab(tab)
|
|
482
486
|
})
|
|
483
|
-
}), /*#__PURE__*/
|
|
484
|
-
children: activeTab === "
|
|
487
|
+
}), /*#__PURE__*/_jsxs(ModalHeader.Actions, {
|
|
488
|
+
children: [activeTab === "stack" && /*#__PURE__*/_jsx(ToolbarCopyButton, {
|
|
489
|
+
value: stackCopyValue,
|
|
490
|
+
buttonStyle: styles.iconButton
|
|
491
|
+
}), activeTab === "events" && /*#__PURE__*/_jsxs(_Fragment, {
|
|
485
492
|
children: [/*#__PURE__*/_jsx(ToolbarCopyButton, {
|
|
486
493
|
value: copyAllEventsData,
|
|
487
494
|
buttonStyle: styles.iconButton
|
|
@@ -504,7 +511,7 @@ export function RouteEventsModalWithTabs({
|
|
|
504
511
|
color: buoyColors.error
|
|
505
512
|
})
|
|
506
513
|
})]
|
|
507
|
-
})
|
|
514
|
+
})]
|
|
508
515
|
})]
|
|
509
516
|
})
|
|
510
517
|
},
|
|
@@ -12,9 +12,9 @@
|
|
|
12
12
|
*/
|
|
13
13
|
|
|
14
14
|
import { useState, useCallback, useMemo, useEffect } from "react";
|
|
15
|
-
import { View, Text, TextInput, TouchableOpacity, ScrollView, StyleSheet, Alert } from "react-native";
|
|
15
|
+
import { View, Text, TextInput, TouchableOpacity, ScrollView, StyleSheet, Alert, Platform } from "react-native";
|
|
16
16
|
import { useSafeRouter } from "@buoy-gg/shared-ui";
|
|
17
|
-
import { Search, ChevronDown, ChevronRight, Home, InlineCopyButton,
|
|
17
|
+
import { Search, ChevronDown, ChevronRight, Home, InlineCopyButton, CopyButton, RefreshCw, formatRelativeTime, ProUpgradeModal, buoyColors } from "@buoy-gg/shared-ui";
|
|
18
18
|
import { useIsPro } from "@buoy-gg/license";
|
|
19
19
|
import { useRouteSitemap } from "../useRouteSitemap";
|
|
20
20
|
|
|
@@ -22,6 +22,11 @@ import { useRouteSitemap } from "../useRouteSitemap";
|
|
|
22
22
|
// Types
|
|
23
23
|
// ============================================================================
|
|
24
24
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
25
|
+
// On desktop (web) the toolbar has far more room, so scale the action buttons
|
|
26
|
+
// up for easier clicking and a less cramped header.
|
|
27
|
+
const IS_DESKTOP = Platform.OS === "web";
|
|
28
|
+
const ACTION_ICON_SIZE = IS_DESKTOP ? 22 : 16;
|
|
29
|
+
|
|
25
30
|
// Synthetic route representing the app's home/index ("/"). Used by the
|
|
26
31
|
// "Home" toolbar shortcut so navigation works the same as tapping any route.
|
|
27
32
|
const HOME_ROUTE = {
|
|
@@ -165,7 +170,7 @@ export function RoutesSitemap({
|
|
|
165
170
|
}
|
|
166
171
|
}], "plain-text");
|
|
167
172
|
}, [router]);
|
|
168
|
-
const handleNavigate = useCallback(route => {
|
|
173
|
+
const handleNavigate = useCallback((route, options) => {
|
|
169
174
|
// When a navigation delegate is supplied (dashboard → device), hand off
|
|
170
175
|
// entirely: the delegate owns Pro gating and param resolution.
|
|
171
176
|
if (onNavigateRoute) {
|
|
@@ -173,8 +178,8 @@ export function RoutesSitemap({
|
|
|
173
178
|
return;
|
|
174
179
|
}
|
|
175
180
|
|
|
176
|
-
// Gate behind Pro
|
|
177
|
-
if (!isPro) {
|
|
181
|
+
// Gate behind Pro (the Home shortcut bypasses this — it's always free)
|
|
182
|
+
if (!isPro && !options?.bypassPro) {
|
|
178
183
|
setShowUpgradeModal(true);
|
|
179
184
|
return;
|
|
180
185
|
}
|
|
@@ -210,7 +215,9 @@ export function RoutesSitemap({
|
|
|
210
215
|
}
|
|
211
216
|
}, [router, promptForParams, isPro, onNavigateRoute]);
|
|
212
217
|
const handleGoHome = useCallback(() => {
|
|
213
|
-
handleNavigate(HOME_ROUTE
|
|
218
|
+
handleNavigate(HOME_ROUTE, {
|
|
219
|
+
bypassPro: true
|
|
220
|
+
});
|
|
214
221
|
}, [handleNavigate]);
|
|
215
222
|
const handleManualRefresh = useCallback(() => {
|
|
216
223
|
if (isRefreshing) return;
|
|
@@ -258,53 +265,54 @@ export function RoutesSitemap({
|
|
|
258
265
|
children: [/*#__PURE__*/_jsxs(View, {
|
|
259
266
|
style: styles.actionsRow,
|
|
260
267
|
children: [/*#__PURE__*/_jsxs(View, {
|
|
261
|
-
style: styles.actionWrapper,
|
|
268
|
+
style: [styles.actionWrapper, IS_DESKTOP && styles.actionWrapperDesktop],
|
|
262
269
|
children: [/*#__PURE__*/_jsx(TouchableOpacity, {
|
|
263
|
-
style: styles.iconButton,
|
|
270
|
+
style: [styles.iconButton, IS_DESKTOP && styles.iconButtonDesktop],
|
|
264
271
|
onPress: handleGoHome,
|
|
265
272
|
accessibilityLabel: "Go to home route",
|
|
266
273
|
children: /*#__PURE__*/_jsx(Home, {
|
|
267
|
-
size:
|
|
274
|
+
size: ACTION_ICON_SIZE,
|
|
268
275
|
color: buoyColors.textSecondary
|
|
269
276
|
})
|
|
270
277
|
}), /*#__PURE__*/_jsx(Text, {
|
|
271
|
-
style: styles.actionLabel,
|
|
278
|
+
style: [styles.actionLabel, IS_DESKTOP && styles.actionLabelDesktop],
|
|
272
279
|
children: "Home"
|
|
273
280
|
})]
|
|
274
281
|
}), /*#__PURE__*/_jsxs(View, {
|
|
275
|
-
style: styles.actionWrapper,
|
|
276
|
-
children: [/*#__PURE__*/_jsx(
|
|
282
|
+
style: [styles.actionWrapper, IS_DESKTOP && styles.actionWrapperDesktop],
|
|
283
|
+
children: [/*#__PURE__*/_jsx(CopyButton, {
|
|
277
284
|
value: copyAllData,
|
|
278
|
-
|
|
285
|
+
size: IS_DESKTOP ? ACTION_ICON_SIZE : 14,
|
|
286
|
+
buttonStyle: IS_DESKTOP ? styles.actionButtonHeaderDesktop : styles.actionButtonHeader
|
|
279
287
|
}), /*#__PURE__*/_jsx(Text, {
|
|
280
|
-
style: styles.actionLabel,
|
|
288
|
+
style: [styles.actionLabel, IS_DESKTOP && styles.actionLabelDesktop],
|
|
281
289
|
children: "Copy"
|
|
282
290
|
})]
|
|
283
291
|
}), /*#__PURE__*/_jsxs(View, {
|
|
284
|
-
style: styles.actionWrapper,
|
|
292
|
+
style: [styles.actionWrapper, IS_DESKTOP && styles.actionWrapperDesktop],
|
|
285
293
|
children: [/*#__PURE__*/_jsx(TouchableOpacity, {
|
|
286
|
-
style: [styles.iconButton, isRefreshing && styles.refreshButtonDisabled],
|
|
294
|
+
style: [styles.iconButton, IS_DESKTOP && styles.iconButtonDesktop, isRefreshing && styles.refreshButtonDisabled],
|
|
287
295
|
onPress: handleManualRefresh,
|
|
288
296
|
disabled: isRefreshing,
|
|
289
297
|
children: /*#__PURE__*/_jsx(RefreshCw, {
|
|
290
|
-
size:
|
|
298
|
+
size: ACTION_ICON_SIZE,
|
|
291
299
|
color: isRefreshing ? buoyColors.textMuted : buoyColors.textSecondary
|
|
292
300
|
})
|
|
293
301
|
}), /*#__PURE__*/_jsx(Text, {
|
|
294
|
-
style: styles.actionLabel,
|
|
302
|
+
style: [styles.actionLabel, IS_DESKTOP && styles.actionLabelDesktop],
|
|
295
303
|
children: "Refresh"
|
|
296
304
|
})]
|
|
297
305
|
}), /*#__PURE__*/_jsxs(View, {
|
|
298
|
-
style: styles.actionWrapper,
|
|
306
|
+
style: [styles.actionWrapper, IS_DESKTOP && styles.actionWrapperDesktop],
|
|
299
307
|
children: [/*#__PURE__*/_jsx(TouchableOpacity, {
|
|
300
|
-
style: styles.iconButton,
|
|
308
|
+
style: [styles.iconButton, IS_DESKTOP && styles.iconButtonDesktop],
|
|
301
309
|
onPress: () => setIsSearching(true),
|
|
302
310
|
children: /*#__PURE__*/_jsx(Search, {
|
|
303
|
-
size:
|
|
311
|
+
size: ACTION_ICON_SIZE,
|
|
304
312
|
color: buoyColors.textSecondary
|
|
305
313
|
})
|
|
306
314
|
}), /*#__PURE__*/_jsx(Text, {
|
|
307
|
-
style: styles.actionLabel,
|
|
315
|
+
style: [styles.actionLabel, IS_DESKTOP && styles.actionLabelDesktop],
|
|
308
316
|
children: "Search"
|
|
309
317
|
})]
|
|
310
318
|
})]
|
|
@@ -450,18 +458,18 @@ function RouteGroupView({
|
|
|
450
458
|
children: group.routes.length
|
|
451
459
|
})
|
|
452
460
|
})]
|
|
453
|
-
}),
|
|
461
|
+
}), group.description && /*#__PURE__*/_jsx(View, {
|
|
462
|
+
style: styles.groupDescription,
|
|
463
|
+
children: /*#__PURE__*/_jsx(Text, {
|
|
464
|
+
style: styles.groupDescriptionText,
|
|
465
|
+
children: group.description
|
|
466
|
+
})
|
|
467
|
+
}), isExpanded && /*#__PURE__*/_jsx(View, {
|
|
454
468
|
style: styles.routesList,
|
|
455
|
-
children:
|
|
456
|
-
style: styles.groupDescription,
|
|
457
|
-
children: /*#__PURE__*/_jsx(Text, {
|
|
458
|
-
style: styles.groupDescriptionText,
|
|
459
|
-
children: group.description
|
|
460
|
-
})
|
|
461
|
-
}), group.routes.map((route, index) => /*#__PURE__*/_jsx(RouteItemView, {
|
|
469
|
+
children: group.routes.map((route, index) => /*#__PURE__*/_jsx(RouteItemView, {
|
|
462
470
|
route: route,
|
|
463
471
|
onNavigate: onNavigate
|
|
464
|
-
}, `${route.path}-${index}`))
|
|
472
|
+
}, `${route.path}-${index}`))
|
|
465
473
|
})]
|
|
466
474
|
});
|
|
467
475
|
}
|
|
@@ -472,7 +480,6 @@ function RouteItemView({
|
|
|
472
480
|
}) {
|
|
473
481
|
const [isExpanded, setIsExpanded] = useState(false);
|
|
474
482
|
const hasChildren = route.children.length > 0;
|
|
475
|
-
const hasParams = route.params.length > 0;
|
|
476
483
|
const typeColor = getRouteTypeColor(route.type);
|
|
477
484
|
const canNavigate = route.type !== "layout" && route.type !== "group";
|
|
478
485
|
|
|
@@ -551,15 +558,6 @@ function RouteItemView({
|
|
|
551
558
|
})
|
|
552
559
|
})]
|
|
553
560
|
})]
|
|
554
|
-
}), showDetails && hasParams && /*#__PURE__*/_jsx(View, {
|
|
555
|
-
style: styles.paramsRow,
|
|
556
|
-
children: route.params.map(param => /*#__PURE__*/_jsx(View, {
|
|
557
|
-
style: styles.paramTag,
|
|
558
|
-
children: /*#__PURE__*/_jsx(Text, {
|
|
559
|
-
style: styles.paramText,
|
|
560
|
-
children: param
|
|
561
|
-
})
|
|
562
|
-
}, param))
|
|
563
561
|
}), showDetails && hasChildren && /*#__PURE__*/_jsx(View, {
|
|
564
562
|
style: styles.childrenContainer,
|
|
565
563
|
children: route.children.map((child, index) => /*#__PURE__*/_jsx(RouteItemView, {
|
|
@@ -679,17 +677,31 @@ const styles = StyleSheet.create({
|
|
|
679
677
|
gap: 4,
|
|
680
678
|
minWidth: 48
|
|
681
679
|
},
|
|
680
|
+
actionWrapperDesktop: {
|
|
681
|
+
gap: 8,
|
|
682
|
+
minWidth: 72
|
|
683
|
+
},
|
|
682
684
|
actionButtonHeader: {
|
|
683
685
|
padding: 6,
|
|
684
686
|
borderRadius: 4,
|
|
685
687
|
backgroundColor: buoyColors.input
|
|
686
688
|
},
|
|
689
|
+
actionButtonHeaderDesktop: {
|
|
690
|
+
padding: 12,
|
|
691
|
+
borderRadius: 8,
|
|
692
|
+
backgroundColor: buoyColors.input
|
|
693
|
+
},
|
|
687
694
|
iconButton: {
|
|
688
695
|
padding: 6,
|
|
689
696
|
borderRadius: 4,
|
|
690
697
|
alignItems: "center",
|
|
691
698
|
justifyContent: "center"
|
|
692
699
|
},
|
|
700
|
+
iconButtonDesktop: {
|
|
701
|
+
padding: 12,
|
|
702
|
+
borderRadius: 8,
|
|
703
|
+
backgroundColor: buoyColors.input
|
|
704
|
+
},
|
|
693
705
|
actionLabel: {
|
|
694
706
|
fontSize: 8,
|
|
695
707
|
color: buoyColors.textMuted,
|
|
@@ -697,6 +709,9 @@ const styles = StyleSheet.create({
|
|
|
697
709
|
textTransform: "uppercase",
|
|
698
710
|
letterSpacing: 0.5
|
|
699
711
|
},
|
|
712
|
+
actionLabelDesktop: {
|
|
713
|
+
fontSize: 12
|
|
714
|
+
},
|
|
700
715
|
refreshButtonDisabled: {
|
|
701
716
|
opacity: 0.5
|
|
702
717
|
},
|
|
@@ -941,28 +956,6 @@ const styles = StyleSheet.create({
|
|
|
941
956
|
fontFamily: "monospace",
|
|
942
957
|
fontWeight: "600"
|
|
943
958
|
},
|
|
944
|
-
paramsRow: {
|
|
945
|
-
flexDirection: "row",
|
|
946
|
-
flexWrap: "wrap",
|
|
947
|
-
gap: 6,
|
|
948
|
-
paddingHorizontal: 10,
|
|
949
|
-
paddingTop: 2,
|
|
950
|
-
paddingBottom: 8
|
|
951
|
-
},
|
|
952
|
-
paramTag: {
|
|
953
|
-
backgroundColor: "#F59E0B15",
|
|
954
|
-
borderColor: "#F59E0B40",
|
|
955
|
-
borderWidth: 1,
|
|
956
|
-
borderRadius: 4,
|
|
957
|
-
paddingHorizontal: 6,
|
|
958
|
-
paddingVertical: 2
|
|
959
|
-
},
|
|
960
|
-
paramText: {
|
|
961
|
-
fontSize: 10,
|
|
962
|
-
color: "#F59E0B",
|
|
963
|
-
fontFamily: "monospace",
|
|
964
|
-
fontWeight: "600"
|
|
965
|
-
},
|
|
966
959
|
childrenContainer: {
|
|
967
960
|
borderLeftWidth: 2,
|
|
968
961
|
borderLeftColor: buoyColors.border,
|
|
@@ -23,6 +23,12 @@ export interface NavigationStackProps {
|
|
|
23
23
|
onAction?: (action: NavigationStackActionType, payload?: {
|
|
24
24
|
index?: number;
|
|
25
25
|
}) => void;
|
|
26
|
+
/**
|
|
27
|
+
* Reports the serialized stack (used for the "copy" toolbar action) up to the
|
|
28
|
+
* host so the copy button can live in the shared navbar instead of inside
|
|
29
|
+
* this component. Called whenever the stack changes.
|
|
30
|
+
*/
|
|
31
|
+
onCopyValueChange?: (value: string) => void;
|
|
26
32
|
}
|
|
27
|
-
export declare function NavigationStack({ style, injectedStack, onAction, }: NavigationStackProps): import("react").JSX.Element;
|
|
33
|
+
export declare function NavigationStack({ style, injectedStack, onAction, onCopyValueChange, }: NavigationStackProps): import("react").JSX.Element;
|
|
28
34
|
//# sourceMappingURL=NavigationStack.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"NavigationStack.d.ts","sourceRoot":"","sources":["../../../src/components/NavigationStack.tsx"],"names":[],"mappings":"AAAA;;;;;GAKG;AAsBH,OAAO,EAEL,KAAK,gBAAgB,EACtB,MAAM,uBAAuB,CAAC;AAM/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;
|
|
1
|
+
{"version":3,"file":"NavigationStack.d.ts","sourceRoot":"","sources":["../../../src/components/NavigationStack.tsx"],"names":[],"mappings":"AAAA;;;;;GAKG;AAsBH,OAAO,EAEL,KAAK,gBAAgB,EACtB,MAAM,uBAAuB,CAAC;AAM/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,+BAgbtB"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"RouteEventsModalWithTabs.d.ts","sourceRoot":"","sources":["../../../src/components/RouteEventsModalWithTabs.tsx"],"names":[],"mappings":"AAqDA,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;CACvC;AA8CD,wBAAgB,wBAAwB,CAAC,EACvC,OAAO,EACP,OAAO,EACP,MAAM,EACN,UAAU,EACV,2BAAmC,GACpC,EAAE,6BAA6B,
|
|
1
|
+
{"version":3,"file":"RouteEventsModalWithTabs.d.ts","sourceRoot":"","sources":["../../../src/components/RouteEventsModalWithTabs.tsx"],"names":[],"mappings":"AAqDA,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;CACvC;AA8CD,wBAAgB,wBAAwB,CAAC,EACvC,OAAO,EACP,OAAO,EACP,MAAM,EACN,UAAU,EACV,2BAAmC,GACpC,EAAE,6BAA6B,sCA8iB/B"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"RoutesSitemap.d.ts","sourceRoot":"","sources":["../../../src/components/RoutesSitemap.tsx"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;
|
|
1
|
+
{"version":3,"file":"RoutesSitemap.d.ts","sourceRoot":"","sources":["../../../src/components/RoutesSitemap.tsx"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AA4BH,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,+BA8YpB"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@buoy-gg/route-events",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "4.0.1",
|
|
4
4
|
"description": "route-events package",
|
|
5
5
|
"main": "lib/commonjs/index.js",
|
|
6
6
|
"module": "lib/module/index.js",
|
|
@@ -26,12 +26,12 @@
|
|
|
26
26
|
],
|
|
27
27
|
"sideEffects": false,
|
|
28
28
|
"dependencies": {
|
|
29
|
-
"@buoy-gg/floating-tools-core": "
|
|
30
|
-
"@buoy-gg/shared-ui": "
|
|
29
|
+
"@buoy-gg/floating-tools-core": "4.0.1",
|
|
30
|
+
"@buoy-gg/shared-ui": "4.0.1"
|
|
31
31
|
},
|
|
32
32
|
"peerDependencies": {
|
|
33
|
-
"@buoy-gg/license": "
|
|
34
|
-
"@react-native-async-storage/async-storage": "
|
|
33
|
+
"@buoy-gg/license": "4.0.1",
|
|
34
|
+
"@react-native-async-storage/async-storage": "^2.0.0 || ^3.1.0",
|
|
35
35
|
"@react-navigation/native": "*",
|
|
36
36
|
"expo-router": "*",
|
|
37
37
|
"react": "*",
|
|
@@ -49,7 +49,7 @@
|
|
|
49
49
|
"@types/react-native": "^0.73.0",
|
|
50
50
|
"expo-router": "~5.0.7",
|
|
51
51
|
"typescript": "~5.8.3",
|
|
52
|
-
"@buoy-gg/license": "
|
|
52
|
+
"@buoy-gg/license": "4.0.1"
|
|
53
53
|
},
|
|
54
54
|
"react-native-builder-bob": {
|
|
55
55
|
"source": "src",
|