@buoy-gg/core 3.0.1 → 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.
Files changed (51) hide show
  1. package/lib/commonjs/floatingMenu/DevToolsSettingsModal.js +1 -1
  2. package/lib/commonjs/floatingMenu/FloatingDevTools.js +25 -5
  3. package/lib/commonjs/floatingMenu/FloatingMenu.js +3 -7
  4. package/lib/commonjs/floatingMenu/allToolsRegistry.js +193 -0
  5. package/lib/commonjs/floatingMenu/autoExternalSync.js +254 -0
  6. package/lib/commonjs/floatingMenu/defaultConfig.js +1 -1
  7. package/lib/commonjs/floatingMenu/dial/DialDevTools.js +115 -53
  8. package/lib/commonjs/floatingMenu/dial/DialIcon.js +53 -13
  9. package/lib/commonjs/floatingMenu/dial/OnboardingTooltip.js +1 -1
  10. package/lib/module/floatingMenu/DevToolsSettingsModal.js +2 -2
  11. package/lib/module/floatingMenu/FloatingDevTools.js +26 -6
  12. package/lib/module/floatingMenu/FloatingMenu.js +4 -7
  13. package/lib/module/floatingMenu/allToolsRegistry.js +190 -0
  14. package/lib/module/floatingMenu/autoExternalSync.js +248 -0
  15. package/lib/module/floatingMenu/defaultConfig.js +1 -1
  16. package/lib/module/floatingMenu/dial/DialDevTools.js +119 -55
  17. package/lib/module/floatingMenu/dial/DialIcon.js +56 -15
  18. package/lib/module/floatingMenu/dial/OnboardingTooltip.js +2 -1
  19. package/lib/typescript/commonjs/floatingMenu/DevToolsSettingsModal.d.ts.map +1 -1
  20. package/lib/typescript/commonjs/floatingMenu/FloatingDevTools.d.ts +19 -1
  21. package/lib/typescript/commonjs/floatingMenu/FloatingDevTools.d.ts.map +1 -1
  22. package/lib/typescript/commonjs/floatingMenu/FloatingMenu.d.ts.map +1 -1
  23. package/lib/typescript/commonjs/floatingMenu/allToolsRegistry.d.ts +42 -0
  24. package/lib/typescript/commonjs/floatingMenu/allToolsRegistry.d.ts.map +1 -0
  25. package/lib/typescript/commonjs/floatingMenu/autoExternalSync.d.ts +25 -0
  26. package/lib/typescript/commonjs/floatingMenu/autoExternalSync.d.ts.map +1 -0
  27. package/lib/typescript/commonjs/floatingMenu/defaultConfig.d.ts +1 -1
  28. package/lib/typescript/commonjs/floatingMenu/defaultConfig.d.ts.map +1 -1
  29. package/lib/typescript/commonjs/floatingMenu/dial/DialDevTools.d.ts +7 -0
  30. package/lib/typescript/commonjs/floatingMenu/dial/DialDevTools.d.ts.map +1 -1
  31. package/lib/typescript/commonjs/floatingMenu/dial/DialIcon.d.ts.map +1 -1
  32. package/lib/typescript/commonjs/floatingMenu/dial/OnboardingTooltip.d.ts.map +1 -1
  33. package/lib/typescript/commonjs/index.d.ts +1 -0
  34. package/lib/typescript/commonjs/index.d.ts.map +1 -1
  35. package/lib/typescript/module/floatingMenu/DevToolsSettingsModal.d.ts.map +1 -1
  36. package/lib/typescript/module/floatingMenu/FloatingDevTools.d.ts +19 -1
  37. package/lib/typescript/module/floatingMenu/FloatingDevTools.d.ts.map +1 -1
  38. package/lib/typescript/module/floatingMenu/FloatingMenu.d.ts.map +1 -1
  39. package/lib/typescript/module/floatingMenu/allToolsRegistry.d.ts +42 -0
  40. package/lib/typescript/module/floatingMenu/allToolsRegistry.d.ts.map +1 -0
  41. package/lib/typescript/module/floatingMenu/autoExternalSync.d.ts +25 -0
  42. package/lib/typescript/module/floatingMenu/autoExternalSync.d.ts.map +1 -0
  43. package/lib/typescript/module/floatingMenu/defaultConfig.d.ts +1 -1
  44. package/lib/typescript/module/floatingMenu/defaultConfig.d.ts.map +1 -1
  45. package/lib/typescript/module/floatingMenu/dial/DialDevTools.d.ts +7 -0
  46. package/lib/typescript/module/floatingMenu/dial/DialDevTools.d.ts.map +1 -1
  47. package/lib/typescript/module/floatingMenu/dial/DialIcon.d.ts.map +1 -1
  48. package/lib/typescript/module/floatingMenu/dial/OnboardingTooltip.d.ts.map +1 -1
  49. package/lib/typescript/module/index.d.ts +1 -0
  50. package/lib/typescript/module/index.d.ts.map +1 -1
  51. package/package.json +5 -5
@@ -1,29 +1,25 @@
1
1
  "use strict";
2
2
 
3
3
  import { useEffect, useMemo, useRef, useState } from "react";
4
- import { Pressable, StyleSheet, View, Dimensions, Text, Animated, Easing } from "react-native";
4
+ import { Pressable, StyleSheet, View, useWindowDimensions, Text, Animated, Easing } from "react-native";
5
+ import { absoluteFill } from "@buoy-gg/shared-ui";
5
6
  // Icons are provided by installedApps; no direct icon imports here.
6
7
  import { DialIcon } from "./DialIcon.js";
8
+ import { ALL_TOOLS_REGISTRY } from "../allToolsRegistry.js";
7
9
  import { DialPagination } from "./DialPagination.js";
8
10
  import { getRankedToolIds, isDialUsageLoaded, loadDialUsage, recordToolUsage } from "./dialUsageStore.js";
9
11
  import { persistentStorage, useHintsDisabled, devToolsStorageKeys, buoyColors } from "@buoy-gg/shared-ui";
10
12
  import { DevToolsSettingsModal, useDevToolsSettings } from "../DevToolsSettingsModal";
11
- import { useIsPro } from "@buoy-gg/license";
13
+ import { useProAccess } from "@buoy-gg/license";
12
14
  import { useAppHost } from "../AppHost.js";
13
15
  import { OnboardingTooltip } from "./OnboardingTooltip.js";
14
- import { getDialLayout, MAX_DIAL_SLOTS, dialAnimationConfig, dialColors } from "@buoy-gg/floating-tools-core";
15
- import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
16
- const {
17
- width: SCREEN_WIDTH,
18
- height: SCREEN_HEIGHT
19
- } = Dimensions.get("window");
16
+ import { getDialLayout, MAX_DIAL_SLOTS, DIAL_BUTTON_SIZE, DIAL_ICON_SIZE, dialAnimationConfig, dialColors } from "@buoy-gg/floating-tools-core";
20
17
 
21
- // Use shared layout calculation from core
22
- const layout = getDialLayout({
23
- screenWidth: SCREEN_WIDTH
24
- });
25
- const CIRCLE_SIZE = layout.circleSize;
26
- const BUTTON_SIZE = layout.buttonSize;
18
+ // The circle size depends on the live window width, so it's computed inside
19
+ // the component via useWindowDimensions — a module-scope Dimensions.get
20
+ // snapshot goes stale when the window resizes after load (web/desktop).
21
+ import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
22
+ const BUTTON_SIZE = DIAL_BUTTON_SIZE;
27
23
  const ONBOARDING_STORAGE_KEY = "@react_buoy_settings_tooltip_shown";
28
24
  /** A non-interactive placeholder used to fill out the last dial page. */
29
25
  const createEmptySlot = slotIndex => ({
@@ -53,7 +49,37 @@ export const DialDevTools = ({
53
49
  const {
54
50
  open
55
51
  } = useAppHost();
56
- const isPro = useIsPro();
52
+ const {
53
+ isPro,
54
+ isWeekendFree
55
+ } = useProAccess();
56
+
57
+ // Live window size — keeps the dial centered and sized correctly when the
58
+ // window resizes (Electron/web) or the device rotates.
59
+ const {
60
+ width: screenWidth,
61
+ height: screenHeight
62
+ } = useWindowDimensions();
63
+ const circleSize = getDialLayout({
64
+ screenWidth
65
+ }).circleSize;
66
+ const sizeStyles = useMemo(() => ({
67
+ parent: {
68
+ width: circleSize,
69
+ height: circleSize
70
+ },
71
+ circle: {
72
+ width: circleSize,
73
+ height: circleSize,
74
+ borderRadius: circleSize / 2
75
+ },
76
+ rounded: {
77
+ borderRadius: circleSize / 2
78
+ },
79
+ gridLine: {
80
+ width: circleSize
81
+ }
82
+ }), [circleSize]);
57
83
 
58
84
  // Load persisted settings modal state on mount
59
85
  useEffect(() => {
@@ -186,6 +212,35 @@ export const DialDevTools = ({
186
212
  return map;
187
213
  }, [dialApps, actions, open, onClose]);
188
214
 
215
+ // Tools from the global registry that are NOT installed in this app.
216
+ // These are appended after all available tools so paging "next" eventually
217
+ // reveals them. They are display-only (real icon + real name + "Unavailable").
218
+ const unavailableTools = useMemo(() => {
219
+ const installedIds = new Set(dialApps.map(a => a.id));
220
+ return ALL_TOOLS_REGISTRY.filter(t => !installedIds.has(t.id));
221
+ }, [dialApps]);
222
+
223
+ // Build stable IconType entries for each unavailable tool.
224
+ const unavailableIconsById = useMemo(() => {
225
+ const map = new Map();
226
+ for (const tool of unavailableTools) {
227
+ map.set(tool.id, {
228
+ id: tool.id,
229
+ name: tool.name,
230
+ // Pre-render the icon at the standard dial slot size so it looks correct.
231
+ icon: tool.renderIcon(DIAL_ICON_SIZE),
232
+ iconComponent: undefined,
233
+ color: tool.color,
234
+ unavailable: true,
235
+ // Tapping an unavailable tool is intentionally a no-op: the dial stays
236
+ // open and no modal launches, signalling the tool is not installed.
237
+ // Future: add a brief Toast with an install link here.
238
+ onPress: () => {}
239
+ });
240
+ }
241
+ return map;
242
+ }, [unavailableTools]);
243
+
189
244
  // Snapshot the usage-ranked order when the dial opens. It stays stable while
190
245
  // open so icons don't jump positions mid-interaction.
191
246
  const [rankedIds, setRankedIds] = useState(() => getRankedToolIds(dialApps.map(a => a.id)));
@@ -204,7 +259,9 @@ export const DialDevTools = ({
204
259
  cancelled = true;
205
260
  };
206
261
  }, [dialApps]);
207
- const pageCount = Math.max(1, Math.ceil(rankedIds.length / MAX_DIAL_SLOTS));
262
+
263
+ // Page count spans available tools (usage-ranked) + unavailable tools (appended).
264
+ const pageCount = Math.max(1, Math.ceil((rankedIds.length + unavailableTools.length) / MAX_DIAL_SLOTS));
208
265
  const [currentPage, setCurrentPage] = useState(0);
209
266
  const safePage = Math.min(currentPage, pageCount - 1);
210
267
 
@@ -212,13 +269,18 @@ export const DialDevTools = ({
212
269
  // snapshotted on open, so each icon's page and slot are fixed for the
213
270
  // session — which lets us mount all icons once and paginate purely by
214
271
  // toggling visibility (no remounts on page change).
272
+ //
273
+ // Order: usage-ranked available tools first, unavailable tools appended at
274
+ // the very end. This guarantees unavailable items always appear on the last
275
+ // pages and never displace available tools.
215
276
  const allDialIcons = useMemo(() => {
216
- return rankedIds.map(id => iconsById.get(id)).filter(icon => Boolean(icon)).map((icon, i) => ({
277
+ const allIds = [...rankedIds, ...unavailableTools.map(t => t.id)];
278
+ return allIds.map(id => iconsById.get(id) ?? unavailableIconsById.get(id)).filter(icon => Boolean(icon)).map((icon, i) => ({
217
279
  icon,
218
280
  page: Math.floor(i / MAX_DIAL_SLOTS),
219
281
  slot: i % MAX_DIAL_SLOTS
220
282
  }));
221
- }, [rankedIds, iconsById]);
283
+ }, [rankedIds, iconsById, unavailableTools, unavailableIconsById]);
222
284
 
223
285
  // Empty slot indices for the current page (only the last page can be
224
286
  // partial). These are cheap placeholder dots.
@@ -420,6 +482,10 @@ export const DialDevTools = ({
420
482
  });
421
483
  };
422
484
  const handleIconPress = icon => {
485
+ // Unavailable tools are display-only. Return early so the dial stays open
486
+ // and no modal or animation is triggered. The dimmed appearance already
487
+ // communicates that the tool is not installed.
488
+ if (icon.unavailable) return;
423
489
  setSelectedIcon(1);
424
490
  const interaction = dialAnimationConfig?.interaction ?? {
425
491
  iconSelect: {
@@ -480,13 +546,13 @@ export const DialDevTools = ({
480
546
  children: [/*#__PURE__*/_jsx(Animated.View, {
481
547
  style: [styles.backdrop, backdropAnimatedStyle],
482
548
  children: /*#__PURE__*/_jsx(Pressable, {
483
- style: StyleSheet.absoluteFillObject,
549
+ style: absoluteFill,
484
550
  onPress: handleClose
485
551
  })
486
552
  }), /*#__PURE__*/_jsxs(Animated.View, {
487
- style: [styles.parent, {
553
+ style: [styles.parent, sizeStyles.parent, {
488
554
  position: "absolute",
489
- left: (SCREEN_WIDTH - CIRCLE_SIZE) / 2,
555
+ left: (screenWidth - circleSize) / 2,
490
556
  bottom: 80,
491
557
  transform: [{
492
558
  scale: dialScale
@@ -498,21 +564,21 @@ export const DialDevTools = ({
498
564
  }]
499
565
  }],
500
566
  children: [/*#__PURE__*/_jsxs(Animated.View, {
501
- style: styles.circle,
567
+ style: [styles.circle, sizeStyles.circle],
502
568
  children: [/*#__PURE__*/_jsxs(View, {
503
- style: styles.gradientBackground,
569
+ style: [styles.gradientBackground, sizeStyles.rounded],
504
570
  children: [/*#__PURE__*/_jsx(View, {
505
- style: styles.gradientLayer1
571
+ style: [styles.gradientLayer1, sizeStyles.rounded]
506
572
  }), /*#__PURE__*/_jsx(View, {
507
- style: styles.gradientLayer2
573
+ style: [styles.gradientLayer2, sizeStyles.rounded]
508
574
  }), /*#__PURE__*/_jsx(View, {
509
- style: styles.gradientLayer3
575
+ style: [styles.gradientLayer3, sizeStyles.rounded]
510
576
  }), /*#__PURE__*/_jsx(View, {
511
577
  style: styles.gridPattern,
512
578
  children: Array.from({
513
579
  length: 6
514
580
  }).map((_, i) => /*#__PURE__*/_jsx(View, {
515
- style: [styles.gridLine, {
581
+ style: [styles.gridLine, sizeStyles.gridLine, {
516
582
  transform: [{
517
583
  rotate: `${i * 60}deg`
518
584
  }]
@@ -587,8 +653,8 @@ export const DialDevTools = ({
587
653
  style: styles.centerText,
588
654
  children: "BUOY"
589
655
  }), isPro && /*#__PURE__*/_jsx(Text, {
590
- style: styles.proText,
591
- children: "PRO"
656
+ style: [styles.proText, isWeekendFree && styles.weekendText],
657
+ children: isWeekendFree ? "WEEKEND" : "PRO"
592
658
  })]
593
659
  })
594
660
  })
@@ -603,11 +669,11 @@ export const DialDevTools = ({
603
669
  onNext: () => handlePageChange(safePage + 1),
604
670
  animatedStyle: {
605
671
  position: "absolute",
606
- left: (SCREEN_WIDTH - CIRCLE_SIZE) / 2,
607
- // Circle's bottom edge sits at bottom: 80 -> SCREEN_HEIGHT - 80
672
+ left: (screenWidth - circleSize) / 2,
673
+ // Circle's bottom edge sits at bottom: 80 -> screenHeight - 80
608
674
  // from the top. Place the pager 16px below that edge.
609
- top: SCREEN_HEIGHT - 80 + 16,
610
- width: CIRCLE_SIZE,
675
+ top: screenHeight - 80 + 16,
676
+ width: circleSize,
611
677
  opacity: dialScale,
612
678
  transform: [{
613
679
  scale: dialScale
@@ -628,23 +694,20 @@ export const DialDevTools = ({
628
694
  };
629
695
  const styles = StyleSheet.create({
630
696
  container: {
631
- ...StyleSheet.absoluteFillObject,
697
+ ...absoluteFill,
632
698
  zIndex: 9999
633
699
  },
634
700
  backdrop: {
635
- ...StyleSheet.absoluteFillObject,
701
+ ...absoluteFill,
636
702
  backgroundColor: dialColors.dialBackdrop
637
703
  },
704
+ // width/height/borderRadius for the circle pieces come from sizeStyles —
705
+ // they track the live window width.
638
706
  parent: {
639
- width: CIRCLE_SIZE,
640
- height: CIRCLE_SIZE,
641
707
  alignItems: "center",
642
708
  justifyContent: "center"
643
709
  },
644
710
  circle: {
645
- width: CIRCLE_SIZE,
646
- height: CIRCLE_SIZE,
647
- borderRadius: CIRCLE_SIZE / 2,
648
711
  position: "absolute",
649
712
  backgroundColor: "transparent",
650
713
  borderWidth: 1,
@@ -661,41 +724,36 @@ const styles = StyleSheet.create({
661
724
  gradientBackground: {
662
725
  width: "100%",
663
726
  height: "100%",
664
- borderRadius: CIRCLE_SIZE / 2,
665
727
  position: "relative",
666
728
  backgroundColor: dialColors.dialBackground,
667
729
  overflow: "hidden"
668
730
  },
669
731
  gradientLayer1: {
670
- ...StyleSheet.absoluteFillObject,
732
+ ...absoluteFill,
671
733
  backgroundColor: dialColors.dialGradient1,
672
- opacity: 0.6,
673
- borderRadius: CIRCLE_SIZE / 2
734
+ opacity: 0.6
674
735
  },
675
736
  gradientLayer2: {
676
- ...StyleSheet.absoluteFillObject,
737
+ ...absoluteFill,
677
738
  backgroundColor: dialColors.dialGradient2,
678
739
  opacity: 0.4,
679
740
  top: "30%",
680
- left: "30%",
681
- borderRadius: CIRCLE_SIZE / 2
741
+ left: "30%"
682
742
  },
683
743
  gradientLayer3: {
684
- ...StyleSheet.absoluteFillObject,
744
+ ...absoluteFill,
685
745
  backgroundColor: dialColors.dialGradient3,
686
746
  opacity: 0.3,
687
747
  top: "50%",
688
- left: "50%",
689
- borderRadius: CIRCLE_SIZE / 2
748
+ left: "50%"
690
749
  },
691
750
  gridPattern: {
692
- ...StyleSheet.absoluteFillObject,
751
+ ...absoluteFill,
693
752
  alignItems: "center",
694
753
  justifyContent: "center"
695
754
  },
696
755
  gridLine: {
697
756
  position: "absolute",
698
- width: CIRCLE_SIZE,
699
757
  height: 1,
700
758
  backgroundColor: dialColors.dialGridLine
701
759
  },
@@ -721,13 +779,13 @@ const styles = StyleSheet.create({
721
779
  overflow: "hidden"
722
780
  },
723
781
  buttonGradientLayer1: {
724
- ...StyleSheet.absoluteFillObject,
782
+ ...absoluteFill,
725
783
  backgroundColor: dialColors.dialGradient1,
726
784
  opacity: 0.5,
727
785
  borderRadius: BUTTON_SIZE
728
786
  },
729
787
  buttonGradientLayer2: {
730
- ...StyleSheet.absoluteFillObject,
788
+ ...absoluteFill,
731
789
  backgroundColor: dialColors.dialGradient2,
732
790
  opacity: 0.3,
733
791
  top: "20%",
@@ -735,7 +793,7 @@ const styles = StyleSheet.create({
735
793
  borderRadius: BUTTON_SIZE
736
794
  },
737
795
  buttonGradientLayer3: {
738
- ...StyleSheet.absoluteFillObject,
796
+ ...absoluteFill,
739
797
  backgroundColor: dialColors.dialGradient3,
740
798
  opacity: 0.2,
741
799
  top: "40%",
@@ -801,5 +859,11 @@ const styles = StyleSheet.create({
801
859
  height: 0
802
860
  },
803
861
  textShadowRadius: 4
862
+ },
863
+ // Weekend Pass variant — violet, tighter spacing so "WEEKEND" fits the dial.
864
+ weekendText: {
865
+ color: "#BF5AF2",
866
+ letterSpacing: 1,
867
+ textShadowColor: "#BF5AF2"
804
868
  }
805
869
  });
@@ -1,19 +1,13 @@
1
1
  "use strict";
2
2
 
3
3
  import { useMemo, useRef } from "react";
4
- import { StyleSheet, Pressable, View, Text, Dimensions, Animated } from "react-native";
5
- import { getDialLayout, getIconPosition, getIconStaggerInputRange, DIAL_START_ANGLE, dialColors, dialStyles, dialAnimationConfig } from "@buoy-gg/floating-tools-core";
6
- import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
7
- const {
8
- width: SCREEN_WIDTH
9
- } = Dimensions.get("window");
4
+ import { StyleSheet, Pressable, View, Text, useWindowDimensions, Animated } from "react-native";
5
+ import { getDialLayout, getIconPosition, getIconStaggerInputRange, DIAL_START_ANGLE, DIAL_ICON_SIZE, dialColors, dialStyles, dialAnimationConfig, floatingToolsColors } from "@buoy-gg/floating-tools-core";
10
6
 
11
- // Use shared layout calculation
12
- const layout = getDialLayout({
13
- screenWidth: SCREEN_WIDTH
14
- });
15
- const VIEW_SIZE = layout.iconSize;
16
- const CIRCLE_RADIUS = layout.circleRadius;
7
+ // The circle radius depends on the live window width and is computed inside
8
+ // the component (must match DialDevTools' circle, which does the same).
9
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
10
+ const VIEW_SIZE = DIAL_ICON_SIZE;
17
11
  export const DialIcon = ({
18
12
  index,
19
13
  icon,
@@ -24,6 +18,12 @@ export const DialIcon = ({
24
18
  }) => {
25
19
  // Animation values - using interpolation for better performance
26
20
  const scale = useRef(new Animated.Value(1)).current;
21
+ const {
22
+ width: screenWidth
23
+ } = useWindowDimensions();
24
+ const layout = useMemo(() => getDialLayout({
25
+ screenWidth
26
+ }), [screenWidth]);
27
27
 
28
28
  // Hover animation on press in/out - using shared config
29
29
  // Fallback values in case dialAnimationConfig hasn't loaded yet
@@ -119,14 +119,14 @@ export const DialIcon = ({
119
119
  itemOpacity,
120
120
  progressScale: staggeredProgress
121
121
  };
122
- }, [index, totalIcons, iconsProgress]);
122
+ }, [index, totalIcons, iconsProgress, layout]);
123
123
 
124
124
  // Main animated style for position and appearance
125
125
  const animatedStyle = {
126
126
  position: "absolute",
127
- left: CIRCLE_RADIUS - VIEW_SIZE / 2,
127
+ left: layout.circleRadius - VIEW_SIZE / 2,
128
128
  // Center position
129
- top: CIRCLE_RADIUS - VIEW_SIZE / 2,
129
+ top: layout.circleRadius - VIEW_SIZE / 2,
130
130
  // Center position
131
131
  opacity: motion.itemOpacity,
132
132
  transform: [{
@@ -154,6 +154,32 @@ export const DialIcon = ({
154
154
  children: /*#__PURE__*/_jsx(View, {
155
155
  style: styles.emptyDot
156
156
  })
157
+ }) : icon.unavailable ?
158
+ /*#__PURE__*/
159
+ // ── Unavailable tool ──────────────────────────────────────────────────
160
+ // Renders the real icon + real name at NORMAL styling (visually identical
161
+ // to an installed tool). The ONLY signal that it's unavailable is the small
162
+ // muted "Unavailable" caption under the name. It's non-interactive: no
163
+ // Pressable, and the dial stays open when tapped because
164
+ // DialDevTools.handleIconPress returns early for unavailable icons.
165
+ _jsxs(View, {
166
+ style: styles.pressable,
167
+ children: [/*#__PURE__*/_jsx(View, {
168
+ style: styles.iconWrapper,
169
+ children: icon.icon
170
+ }), /*#__PURE__*/_jsx(Text, {
171
+ style: styles.label,
172
+ numberOfLines: 1,
173
+ adjustsFontSizeToFit: true,
174
+ minimumFontScale: 0.7,
175
+ children: icon.name.toUpperCase()
176
+ }), /*#__PURE__*/_jsx(Text, {
177
+ style: styles.unavailableCaption,
178
+ numberOfLines: 1,
179
+ adjustsFontSizeToFit: true,
180
+ minimumFontScale: 0.6,
181
+ children: "Unavailable"
182
+ })]
157
183
  }) : /*#__PURE__*/_jsxs(Pressable, {
158
184
  onPress: () => onPress(icon),
159
185
  onPressIn: handlePressIn,
@@ -244,5 +270,20 @@ const styles = StyleSheet.create({
244
270
  backgroundColor: dialColors.emptyDotBackground,
245
271
  borderWidth: dialStyles.emptySlot.borderWidth,
246
272
  borderColor: dialColors.emptyDotBorder
273
+ },
274
+ // ── Unavailable tool styles ────────────────────────────────────────────────
275
+ /**
276
+ * Small muted caption shown under the (normal-styled) tool name — the only
277
+ * signal that the tool is not installed. Kept compact (smaller than the label)
278
+ * so the extra line doesn't disturb the arc layout. Uses the shared muted
279
+ * theme token rather than a hardcoded color.
280
+ */
281
+ unavailableCaption: {
282
+ fontSize: dialStyles.icon.label.fontSize - 1,
283
+ fontWeight: dialStyles.icon.label.fontWeight,
284
+ letterSpacing: dialStyles.icon.label.letterSpacing,
285
+ fontFamily: dialStyles.icon.label.fontFamily,
286
+ color: floatingToolsColors.muted,
287
+ textTransform: "uppercase"
247
288
  }
248
289
  });
@@ -2,6 +2,7 @@
2
2
 
3
3
  import { useEffect, useRef } from "react";
4
4
  import { Animated, Pressable, StyleSheet, Text, View, Easing } from "react-native";
5
+ import { absoluteFill } from "@buoy-gg/shared-ui";
5
6
  import { dialColors, buoyColors } from "@buoy-gg/shared-ui";
6
7
  import { calculateTooltipPosition, ARROW_BOTTOM_OFFSET, ARROW_HEIGHT } from "./onboardingConstants.js";
7
8
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
@@ -128,7 +129,7 @@ export const OnboardingTooltip = ({
128
129
  };
129
130
  const styles = StyleSheet.create({
130
131
  container: {
131
- ...StyleSheet.absoluteFillObject,
132
+ ...absoluteFill,
132
133
  alignItems: "center",
133
134
  justifyContent: "center",
134
135
  pointerEvents: "box-none"
@@ -1 +1 @@
1
- {"version":3,"file":"DevToolsSettingsModal.d.ts","sourceRoot":"","sources":["../../../../src/floatingMenu/DevToolsSettingsModal.tsx"],"names":[],"mappings":"AAAA,OAAO,EAA6C,EAAE,EAAE,MAAM,OAAO,CAAC;AAqJtE;;;GAGG;AACH,MAAM,WAAW,sBAAsB;IACrC;;;;OAIG;IACH,2BAA2B,CAAC,EAAE,OAAO,CAAC;IACtC;;;OAGG;IACH,wBAAwB,CAAC,EAAE,OAAO,CAAC;CACpC;AAED;;;GAGG;AACH,MAAM,WAAW,gBAAgB;IAC/B,4EAA4E;IAC5E,SAAS,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACnC,uFAAuF;IACvF,aAAa,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG;QACvC,WAAW,EAAE,OAAO,CAAC;KACtB,CAAC;IACF,kDAAkD;IAClD,cAAc,CAAC,EAAE,sBAAsB,CAAC;CACzC;AAED,UAAU,0BAA0B;IAClC,OAAO,EAAE,OAAO,CAAC;IACjB,OAAO,EAAE,MAAM,IAAI,CAAC;IACpB,gBAAgB,CAAC,EAAE,CAAC,QAAQ,EAAE,gBAAgB,KAAK,IAAI,CAAC;IACxD,eAAe,CAAC,EAAE,gBAAgB,CAAC;IACnC,aAAa,CAAC,EAAE;QACd,EAAE,EAAE,MAAM,CAAC;QACX,IAAI,EAAE,MAAM,CAAC;QACb,WAAW,CAAC,EAAE,MAAM,CAAC;QACrB,IAAI,CAAC,EAAE,MAAM,GAAG,KAAK,GAAG,MAAM,CAAC;KAChC,EAAE,CAAC;CACL;AA2DD;;;GAGG;AACH,eAAO,MAAM,qBAAqB,EAAE,EAAE,CAAC,0BAA0B,CA28BhE,CAAC;AAwDF;;;;;;GAMG;AACH,eAAO,MAAM,mBAAmB;;;CAuD/B,CAAC"}
1
+ {"version":3,"file":"DevToolsSettingsModal.d.ts","sourceRoot":"","sources":["../../../../src/floatingMenu/DevToolsSettingsModal.tsx"],"names":[],"mappings":"AAAA,OAAO,EAA6C,EAAE,EAAE,MAAM,OAAO,CAAC;AAsJtE;;;GAGG;AACH,MAAM,WAAW,sBAAsB;IACrC;;;;OAIG;IACH,2BAA2B,CAAC,EAAE,OAAO,CAAC;IACtC;;;OAGG;IACH,wBAAwB,CAAC,EAAE,OAAO,CAAC;CACpC;AAED;;;GAGG;AACH,MAAM,WAAW,gBAAgB;IAC/B,4EAA4E;IAC5E,SAAS,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACnC,uFAAuF;IACvF,aAAa,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG;QACvC,WAAW,EAAE,OAAO,CAAC;KACtB,CAAC;IACF,kDAAkD;IAClD,cAAc,CAAC,EAAE,sBAAsB,CAAC;CACzC;AAED,UAAU,0BAA0B;IAClC,OAAO,EAAE,OAAO,CAAC;IACjB,OAAO,EAAE,MAAM,IAAI,CAAC;IACpB,gBAAgB,CAAC,EAAE,CAAC,QAAQ,EAAE,gBAAgB,KAAK,IAAI,CAAC;IACxD,eAAe,CAAC,EAAE,gBAAgB,CAAC;IACnC,aAAa,CAAC,EAAE;QACd,EAAE,EAAE,MAAM,CAAC;QACX,IAAI,EAAE,MAAM,CAAC;QACb,WAAW,CAAC,EAAE,MAAM,CAAC;QACrB,IAAI,CAAC,EAAE,MAAM,GAAG,KAAK,GAAG,MAAM,CAAC;KAChC,EAAE,CAAC;CACL;AA2DD;;;GAGG;AACH,eAAO,MAAM,qBAAqB,EAAE,EAAE,CAAC,0BAA0B,CA+8BhE,CAAC;AAwDF;;;;;;GAMG;AACH,eAAO,MAAM,mBAAmB;;;CAuD/B,CAAC"}
@@ -2,6 +2,7 @@ import React from "react";
2
2
  import { type FloatingMenuProps } from "./FloatingMenu";
3
3
  import type { InstalledApp } from "./types";
4
4
  import { type DefaultFloatingConfig, type DefaultDialConfig } from "./defaultConfig";
5
+ import { type ExternalSyncOptions } from "./autoExternalSync";
5
6
  /**
6
7
  * Environment variable configuration
7
8
  *
@@ -229,6 +230,23 @@ export interface FloatingDevToolsProps extends Omit<FloatingMenuProps, "apps"> {
229
230
  * ```
230
231
  */
231
232
  zustandStores?: Record<string, any>;
233
+ /**
234
+ * Zero-config sync to the Buoy Desktop dashboard.
235
+ *
236
+ * Enabled by default in dev builds whenever @buoy-gg/external-sync is
237
+ * installed: connects to the desktop broker (localhost:42831 — a silent
238
+ * no-op when the desktop app isn't running) and registers a sync adapter
239
+ * for every installed tool automatically. Nothing else to render.
240
+ *
241
+ * Pass `false` to disable, or options to customize the device identity /
242
+ * broker URL:
243
+ *
244
+ * @example
245
+ * ```tsx
246
+ * <FloatingDevTools externalSync={{ deviceName: "My App (ios)" }} />
247
+ * ```
248
+ */
249
+ externalSync?: boolean | ExternalSyncOptions;
232
250
  }
233
251
  /**
234
252
  * Unified floating development tools component with automatic preset discovery.
@@ -284,5 +302,5 @@ export interface FloatingDevToolsProps extends Omit<FloatingMenuProps, "apps"> {
284
302
  *
285
303
  * @param props - FloatingDevTools props
286
304
  */
287
- export declare const FloatingDevTools: ({ apps, requiredEnvVars, requiredStorageKeys, children, disableHints, defaultFloatingTools, defaultDialTools, requireLicense, licenseKey: licenseKeyProp, zustandStores, environment, ...props }: FloatingDevToolsProps) => React.JSX.Element | null;
305
+ export declare const FloatingDevTools: ({ apps, requiredEnvVars, requiredStorageKeys, children, disableHints, defaultFloatingTools, defaultDialTools, requireLicense, licenseKey: licenseKeyProp, zustandStores, environment, externalSync, ...props }: FloatingDevToolsProps) => React.JSX.Element | null;
288
306
  //# sourceMappingURL=FloatingDevTools.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"FloatingDevTools.d.ts","sourceRoot":"","sources":["../../../../src/floatingMenu/FloatingDevTools.tsx"],"names":[],"mappings":"AAAA,OAAO,KAA+D,MAAM,OAAO,CAAC;AAGpF,OAAO,EAAgB,KAAK,iBAAiB,EAAE,MAAM,gBAAgB,CAAC;AAMtE,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AAI5C,OAAO,EACL,KAAK,qBAAqB,EAC1B,KAAK,iBAAiB,EAEvB,MAAM,iBAAiB,CAAC;AAIzB;;;;;;;;;;;;;;;;GAgBG;AACH,MAAM,MAAM,YAAY,GACpB,MAAM,GACN;IACE,GAAG,EAAE,MAAM,CAAC;IACZ,aAAa,EAAE,MAAM,CAAC;IACtB,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB,GACD;IACE,GAAG,EAAE,MAAM,CAAC;IACZ,YAAY,EACR,QAAQ,GACR,QAAQ,GACR,SAAS,GACT,QAAQ,GACR,OAAO,GACP,KAAK,CAAC;IACV,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB,CAAC;AAEN;;GAEG;AACH,MAAM,WAAW,gBAAgB;IAC/B,GAAG,EAAE,MAAM,CAAC;IACZ,YAAY,CAAC,EAAE,QAAQ,GAAG,QAAQ,GAAG,SAAS,GAAG,QAAQ,CAAC;IAC1D,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,WAAW,EAAE,OAAO,GAAG,QAAQ,GAAG,MAAM,CAAC;CAC1C;AAED;;;;;;GAMG;AACH,MAAM,WAAW,qBAAsB,SAAQ,IAAI,CAAC,iBAAiB,EAAE,MAAM,CAAC;IAC5E;;;;;;;;;;;;;;;;;;;;;;OAsBG;IACH,IAAI,CAAC,EAAE,YAAY,EAAE,CAAC;IAEtB;;;;;;;;;;;;;;OAcG;IACH,eAAe,CAAC,EAAE,YAAY,EAAE,CAAC;IAEjC;;;;;;;;;;;;OAYG;IACH,mBAAmB,CAAC,EAAE,gBAAgB,EAAE,CAAC;IAEzC;;;;;;;;;;OAUG;IACH,QAAQ,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;IAE3B;;;;;;;;;OASG;IACH,YAAY,CAAC,EAAE,OAAO,CAAC;IAEvB;;;;;;;;;;;;;OAaG;IACH,oBAAoB,CAAC,EAAE,qBAAqB,CAAC;IAE7C;;;;;;;;;;;;;;OAcG;IACH,gBAAgB,CAAC,EAAE,iBAAiB,CAAC;IAErC;;;;;;;;;;;;;;;;OAgBG;IACH,qBAAqB,CAAC,EAAE,OAAO,oBAAoB,EAAE,WAAW,EAAE,CAAC;IAEnE;;;;;;;;;;;;;OAaG;IACH,mBAAmB,CAAC,EAAE,CAAC,WAAW,EAAE,OAAO,oBAAoB,EAAE,WAAW,KAAK,IAAI,CAAC;IAEtF;;;;;;;;;;OAUG;IACH,cAAc,CAAC,EAAE,OAAO,CAAC;IAEzB;;;;;;;;OAQG;IACH,UAAU,CAAC,EAAE,MAAM,CAAC;IAEpB;;;;;;;;;;;;;;;;;;OAkBG;IACH,aAAa,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;CACrC;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAqDG;AACH,eAAO,MAAM,gBAAgB,GAAI,kMAa9B,qBAAqB,6BAwOvB,CAAC"}
1
+ {"version":3,"file":"FloatingDevTools.d.ts","sourceRoot":"","sources":["../../../../src/floatingMenu/FloatingDevTools.tsx"],"names":[],"mappings":"AAAA,OAAO,KAA+D,MAAM,OAAO,CAAC;AAGpF,OAAO,EAAgB,KAAK,iBAAiB,EAAE,MAAM,gBAAgB,CAAC;AAMtE,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AAI5C,OAAO,EACL,KAAK,qBAAqB,EAC1B,KAAK,iBAAiB,EAEvB,MAAM,iBAAiB,CAAC;AAGzB,OAAO,EAGL,KAAK,mBAAmB,EACzB,MAAM,oBAAoB,CAAC;AAE5B;;;;;;;;;;;;;;;;GAgBG;AACH,MAAM,MAAM,YAAY,GACpB,MAAM,GACN;IACE,GAAG,EAAE,MAAM,CAAC;IACZ,aAAa,EAAE,MAAM,CAAC;IACtB,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB,GACD;IACE,GAAG,EAAE,MAAM,CAAC;IACZ,YAAY,EACR,QAAQ,GACR,QAAQ,GACR,SAAS,GACT,QAAQ,GACR,OAAO,GACP,KAAK,CAAC;IACV,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB,CAAC;AAEN;;GAEG;AACH,MAAM,WAAW,gBAAgB;IAC/B,GAAG,EAAE,MAAM,CAAC;IACZ,YAAY,CAAC,EAAE,QAAQ,GAAG,QAAQ,GAAG,SAAS,GAAG,QAAQ,CAAC;IAC1D,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,WAAW,EAAE,OAAO,GAAG,QAAQ,GAAG,MAAM,CAAC;CAC1C;AAED;;;;;;GAMG;AACH,MAAM,WAAW,qBAAsB,SAAQ,IAAI,CAAC,iBAAiB,EAAE,MAAM,CAAC;IAC5E;;;;;;;;;;;;;;;;;;;;;;OAsBG;IACH,IAAI,CAAC,EAAE,YAAY,EAAE,CAAC;IAEtB;;;;;;;;;;;;;;OAcG;IACH,eAAe,CAAC,EAAE,YAAY,EAAE,CAAC;IAEjC;;;;;;;;;;;;OAYG;IACH,mBAAmB,CAAC,EAAE,gBAAgB,EAAE,CAAC;IAEzC;;;;;;;;;;OAUG;IACH,QAAQ,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;IAE3B;;;;;;;;;OASG;IACH,YAAY,CAAC,EAAE,OAAO,CAAC;IAEvB;;;;;;;;;;;;;OAaG;IACH,oBAAoB,CAAC,EAAE,qBAAqB,CAAC;IAE7C;;;;;;;;;;;;;;OAcG;IACH,gBAAgB,CAAC,EAAE,iBAAiB,CAAC;IAErC;;;;;;;;;;;;;;;;OAgBG;IACH,qBAAqB,CAAC,EAAE,OAAO,oBAAoB,EAAE,WAAW,EAAE,CAAC;IAEnE;;;;;;;;;;;;;OAaG;IACH,mBAAmB,CAAC,EAAE,CAAC,WAAW,EAAE,OAAO,oBAAoB,EAAE,WAAW,KAAK,IAAI,CAAC;IAEtF;;;;;;;;;;OAUG;IACH,cAAc,CAAC,EAAE,OAAO,CAAC;IAEzB;;;;;;;;OAQG;IACH,UAAU,CAAC,EAAE,MAAM,CAAC;IAEpB;;;;;;;;;;;;;;;;;;OAkBG;IACH,aAAa,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;IAEpC;;;;;;;;;;;;;;;OAeG;IACH,YAAY,CAAC,EAAE,OAAO,GAAG,mBAAmB,CAAC;CAC9C;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAqDG;AACH,eAAO,MAAM,gBAAgB,GAAI,gNAc9B,qBAAqB,6BAoQvB,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"FloatingMenu.d.ts","sourceRoot":"","sources":["../../../../src/floatingMenu/FloatingMenu.tsx"],"names":[],"mappings":"AAAA,OAAc,EAAE,EAAE,EAAqD,MAAM,OAAO,CAAC;AASrF,OAAO,EAAiB,QAAQ,EAAc,MAAM,iBAAiB,CAAC;AACtE,OAAO,KAAK,EACV,YAAY,EACZ,mBAAmB,EACnB,iBAAiB,EAClB,MAAM,SAAS,CAAC;AACjB,OAAO,KAAK,EAAE,qBAAqB,EAAE,iBAAiB,EAAE,MAAM,iBAAiB,CAAC;AAEhF,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAC;AActD;;;GAGG;AACH,MAAM,WAAW,iBAAiB;IAChC,+DAA+D;IAC/D,IAAI,EAAE,YAAY,EAAE,CAAC;IACrB,6EAA6E;IAC7E,KAAK,CAAC,EAAE,iBAAiB,CAAC;IAC1B,sFAAsF;IACtF,OAAO,CAAC,EAAE,mBAAmB,CAAC;IAC9B,iFAAiF;IACjF,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,uFAAuF;IACvF,WAAW,CAAC,EAAE,WAAW,CAAC;IAC1B,yEAAyE;IACzE,QAAQ,CAAC,EAAE,QAAQ,CAAC;IACpB,kFAAkF;IAClF,oBAAoB,CAAC,EAAE,qBAAqB,CAAC;IAC7C,oFAAoF;IACpF,gBAAgB,CAAC,EAAE,iBAAiB,CAAC;IACrC;;;OAGG;IACH,qBAAqB,CAAC,EAAE,WAAW,EAAE,CAAC;IACtC;;;OAGG;IACH,mBAAmB,CAAC,EAAE,CAAC,WAAW,EAAE,WAAW,KAAK,IAAI,CAAC;CAC1D;AAYD,eAAO,MAAM,YAAY,EAAE,EAAE,CAAC,iBAAiB,CAwU9C,CAAC"}
1
+ {"version":3,"file":"FloatingMenu.d.ts","sourceRoot":"","sources":["../../../../src/floatingMenu/FloatingMenu.tsx"],"names":[],"mappings":"AAAA,OAAc,EAAE,EAAE,EAAqD,MAAM,OAAO,CAAC;AASrF,OAAO,EAAiB,QAAQ,EAAc,MAAM,iBAAiB,CAAC;AACtE,OAAO,KAAK,EACV,YAAY,EACZ,mBAAmB,EACnB,iBAAiB,EAClB,MAAM,SAAS,CAAC;AACjB,OAAO,KAAK,EAAE,qBAAqB,EAAE,iBAAiB,EAAE,MAAM,iBAAiB,CAAC;AAEhF,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAC;AActD;;;GAGG;AACH,MAAM,WAAW,iBAAiB;IAChC,+DAA+D;IAC/D,IAAI,EAAE,YAAY,EAAE,CAAC;IACrB,6EAA6E;IAC7E,KAAK,CAAC,EAAE,iBAAiB,CAAC;IAC1B,sFAAsF;IACtF,OAAO,CAAC,EAAE,mBAAmB,CAAC;IAC9B,iFAAiF;IACjF,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,uFAAuF;IACvF,WAAW,CAAC,EAAE,WAAW,CAAC;IAC1B,yEAAyE;IACzE,QAAQ,CAAC,EAAE,QAAQ,CAAC;IACpB,kFAAkF;IAClF,oBAAoB,CAAC,EAAE,qBAAqB,CAAC;IAC7C,oFAAoF;IACpF,gBAAgB,CAAC,EAAE,iBAAiB,CAAC;IACrC;;;OAGG;IACH,qBAAqB,CAAC,EAAE,WAAW,EAAE,CAAC;IACtC;;;OAGG;IACH,mBAAmB,CAAC,EAAE,CAAC,WAAW,EAAE,WAAW,KAAK,IAAI,CAAC;CAC1D;AAWD,eAAO,MAAM,YAAY,EAAE,EAAE,CAAC,iBAAiB,CAwU9C,CAAC"}
@@ -0,0 +1,42 @@
1
+ /**
2
+ * Canonical registry of ALL dial-eligible tools React Buoy offers on mobile.
3
+ *
4
+ * This is the single source of truth used to compute which tools are
5
+ * "unavailable" (offered but not installed in the current app). It lives
6
+ * inside the floating-menu package so nothing outside needs to be imported.
7
+ *
8
+ * Rules for this file:
9
+ * - Only import from REQUIRED dependencies (@buoy-gg/floating-tools-core,
10
+ * @buoy-gg/shared-ui, react-native) so the icons are always resolvable,
11
+ * even when the optional tool packages are not installed.
12
+ * - Only include tools whose preset slot is NOT "row" (row-only tools never
13
+ * appear in the dial and have no "unavailable" state to show).
14
+ * - Keep the order intentional: this order is the fallback when no usage
15
+ * data exists for new/unavailable tools.
16
+ */
17
+ import React from "react";
18
+ export interface AllToolsEntry {
19
+ /** Unique tool ID — must match the preset id from the tool's package */
20
+ id: string;
21
+ /** Display name (shown in the dial + unavailable label) */
22
+ name: string;
23
+ /** Accent color */
24
+ color: string;
25
+ /** Icon render function — receives the requested pixel size */
26
+ renderIcon: (size: number) => React.ReactNode;
27
+ }
28
+ /**
29
+ * Full list of every dial-eligible tool React Buoy offers on mobile.
30
+ *
31
+ * Available (installed) tools are shown normally in the dial.
32
+ * Unavailable (not installed) tools are appended at the end of the dial and look
33
+ * like a normal item (real icon + real name) with a small muted "Unavailable"
34
+ * caption added; they are non-interactive.
35
+ *
36
+ * To add a new tool to Buoy:
37
+ * 1. Add its preset to autoDiscoverPresets.ts
38
+ * 2. Add an entry here so it appears in the "unavailable" section for apps
39
+ * that haven't installed it yet.
40
+ */
41
+ export declare const ALL_TOOLS_REGISTRY: AllToolsEntry[];
42
+ //# sourceMappingURL=allToolsRegistry.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"allToolsRegistry.d.ts","sourceRoot":"","sources":["../../../../src/floatingMenu/allToolsRegistry.tsx"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAEH,OAAO,KAAK,MAAM,OAAO,CAAC;AAgE1B,MAAM,WAAW,aAAa;IAC5B,wEAAwE;IACxE,EAAE,EAAE,MAAM,CAAC;IACX,2DAA2D;IAC3D,IAAI,EAAE,MAAM,CAAC;IACb,mBAAmB;IACnB,KAAK,EAAE,MAAM,CAAC;IACd,+DAA+D;IAC/D,UAAU,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,KAAK,CAAC,SAAS,CAAC;CAC/C;AAID;;;;;;;;;;;;GAYG;AACH,eAAO,MAAM,kBAAkB,EAAE,aAAa,EAyE7C,CAAC"}
@@ -0,0 +1,25 @@
1
+ import type { EnvVarConfig } from "./FloatingDevTools";
2
+ /** Whether zero-config sync can run (the external-sync package is installed). */
3
+ export declare function isExternalSyncAvailable(): boolean;
4
+ export interface ExternalSyncOptions {
5
+ /** Broker URL. @default "http://localhost:42831" (the Buoy Desktop app) */
6
+ socketURL?: string;
7
+ /** Shown in the desktop device list. @default "<app name> (<platform>)" */
8
+ deviceName?: string;
9
+ /** Stable device identity across restarts. @default "<app-slug>-<platform>" */
10
+ deviceId?: string;
11
+ /** @default false */
12
+ enableLogs?: boolean;
13
+ }
14
+ interface AutoExternalSyncProps {
15
+ options?: ExternalSyncOptions;
16
+ /** FloatingDevTools' requiredEnvVars — reused for the env tool's adapter. */
17
+ requiredEnvVars?: EnvVarConfig[];
18
+ /** Pro status, forwarded into the handshake so the dashboard can adopt it. */
19
+ isPro?: boolean;
20
+ /** Pro license key, forwarded into the handshake alongside `isPro`. */
21
+ licenseKey?: string | null;
22
+ }
23
+ export declare function AutoExternalSync({ options, requiredEnvVars, isPro, licenseKey, }: AutoExternalSyncProps): null;
24
+ export {};
25
+ //# sourceMappingURL=autoExternalSync.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"autoExternalSync.d.ts","sourceRoot":"","sources":["../../../../src/floatingMenu/autoExternalSync.tsx"],"names":[],"mappings":"AAgBA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AA8GvD,iFAAiF;AACjF,wBAAgB,uBAAuB,IAAI,OAAO,CAEjD;AAED,MAAM,WAAW,mBAAmB;IAClC,2EAA2E;IAC3E,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,2EAA2E;IAC3E,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,+EAA+E;IAC/E,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,qBAAqB;IACrB,UAAU,CAAC,EAAE,OAAO,CAAC;CACtB;AAuBD,UAAU,qBAAqB;IAC7B,OAAO,CAAC,EAAE,mBAAmB,CAAC;IAC9B,6EAA6E;IAC7E,eAAe,CAAC,EAAE,YAAY,EAAE,CAAC;IACjC,8EAA8E;IAC9E,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,uEAAuE;IACvE,UAAU,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;CAC5B;AAED,wBAAgB,gBAAgB,CAAC,EAC/B,OAAO,EACP,eAAe,EACf,KAAK,EACL,UAAU,GACX,EAAE,qBAAqB,QAqGvB"}
@@ -19,7 +19,7 @@
19
19
  * All known tool IDs that can appear in the floating menu or dial menu.
20
20
  * This is a union type of all auto-discovered tool IDs.
21
21
  */
22
- export type BuiltInToolId = 'env' | 'network' | 'storage' | 'query' | 'query-wifi-toggle' | 'route-events' | 'debug-borders' | 'highlight-updates' | 'highlight-updates-modal';
22
+ export type BuiltInToolId = 'env' | 'network' | 'storage' | 'query' | 'query-wifi-toggle' | 'route-events' | 'debug-borders' | 'highlight-updates' | 'highlight-updates-modal' | 'redux' | 'zustand' | 'jotai' | 'events' | 'image-overlay' | 'perf-monitor' | 'perf-monitor-modal';
23
23
  /**
24
24
  * Special floating-only tool IDs that only appear in the floating bubble row.
25
25
  */
@@ -1 +1 @@
1
- {"version":3,"file":"defaultConfig.d.ts","sourceRoot":"","sources":["../../../../src/floatingMenu/defaultConfig.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AAEH;;;GAGG;AACH,MAAM,MAAM,aAAa,GACrB,KAAK,GACL,SAAS,GACT,SAAS,GACT,OAAO,GACP,mBAAmB,GACnB,cAAc,GACd,eAAe,GACf,mBAAmB,GACnB,yBAAyB,CAAC;AAE9B;;GAEG;AACH,MAAM,MAAM,kBAAkB,GAAG,aAAa,CAAC;AAE/C;;;GAGG;AACH,MAAM,MAAM,cAAc,GAAG,aAAa,GAAG,kBAAkB,CAAC;AAEhE;;;GAGG;AACH,MAAM,MAAM,UAAU,GAAG,aAAa,CAAC;AAEvC;;GAEG;AACH,eAAO,MAAM,cAAc,IAAI,CAAC;AAEhC;;;;;;;;GAQG;AACH,MAAM,MAAM,qBAAqB,GAAG,cAAc,EAAE,CAAC;AAErD;;;;;;;;GAQG;AACH,MAAM,MAAM,iBAAiB,GAAG,UAAU,EAAE,CAAC;AAE7C;;;;;;;;;;;;;;;;;GAiBG;AACH,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,iBAAiB,GAAG,iBAAiB,CAW9E;AAED;;;;;;;;;;;;;;;;;;GAkBG;AACH,wBAAgB,mBAAmB,CACjC,CAAC,SAAS,cAAc,EAAE,EAC1B,CAAC,SAAS,UAAU,EAAE,EACtB,MAAM,EAAE;IACR,QAAQ,CAAC,EAAE,CAAC,CAAC;IACb,IAAI,CAAC,EAAE,CAAC,CAAC;CACV,GAAG;IACF,QAAQ,EAAE,CAAC,GAAG,SAAS,CAAC;IACxB,IAAI,EAAE,CAAC,GAAG,SAAS,CAAC;CACrB,CAUA;AAED;;GAEG;AACH,wBAAgB,gBAAgB,CAAC,EAAE,EAAE,MAAM,GAAG,EAAE,IAAI,cAAc,CAcjE;AAED;;GAEG;AACH,wBAAgB,YAAY,CAAC,EAAE,EAAE,MAAM,GAAG,EAAE,IAAI,UAAU,CAazD;AAED;;;;;GAKG;AACH,wBAAgB,eAAe,CAAC,CAAC,SAAS,MAAM,EAC9C,GAAG,EAAE,CAAC,EAAE,EACR,cAAc,EAAE,CAAC,EAAE,GAClB,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CASzB"}
1
+ {"version":3,"file":"defaultConfig.d.ts","sourceRoot":"","sources":["../../../../src/floatingMenu/defaultConfig.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AAEH;;;GAGG;AACH,MAAM,MAAM,aAAa,GACrB,KAAK,GACL,SAAS,GACT,SAAS,GACT,OAAO,GACP,mBAAmB,GACnB,cAAc,GACd,eAAe,GACf,mBAAmB,GACnB,yBAAyB,GACzB,OAAO,GACP,SAAS,GACT,OAAO,GACP,QAAQ,GACR,eAAe,GACf,cAAc,GACd,oBAAoB,CAAC;AAEzB;;GAEG;AACH,MAAM,MAAM,kBAAkB,GAAG,aAAa,CAAC;AAE/C;;;GAGG;AACH,MAAM,MAAM,cAAc,GAAG,aAAa,GAAG,kBAAkB,CAAC;AAEhE;;;GAGG;AACH,MAAM,MAAM,UAAU,GAAG,aAAa,CAAC;AAEvC;;GAEG;AACH,eAAO,MAAM,cAAc,IAAI,CAAC;AAEhC;;;;;;;;GAQG;AACH,MAAM,MAAM,qBAAqB,GAAG,cAAc,EAAE,CAAC;AAErD;;;;;;;;GAQG;AACH,MAAM,MAAM,iBAAiB,GAAG,UAAU,EAAE,CAAC;AAE7C;;;;;;;;;;;;;;;;;GAiBG;AACH,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,iBAAiB,GAAG,iBAAiB,CAW9E;AAED;;;;;;;;;;;;;;;;;;GAkBG;AACH,wBAAgB,mBAAmB,CACjC,CAAC,SAAS,cAAc,EAAE,EAC1B,CAAC,SAAS,UAAU,EAAE,EACtB,MAAM,EAAE;IACR,QAAQ,CAAC,EAAE,CAAC,CAAC;IACb,IAAI,CAAC,EAAE,CAAC,CAAC;CACV,GAAG;IACF,QAAQ,EAAE,CAAC,GAAG,SAAS,CAAC;IACxB,IAAI,EAAE,CAAC,GAAG,SAAS,CAAC;CACrB,CAUA;AAED;;GAEG;AACH,wBAAgB,gBAAgB,CAAC,EAAE,EAAE,MAAM,GAAG,EAAE,IAAI,cAAc,CAcjE;AAED;;GAEG;AACH,wBAAgB,YAAY,CAAC,EAAE,EAAE,MAAM,GAAG,EAAE,IAAI,UAAU,CAazD;AAED;;;;;GAKG;AACH,wBAAgB,eAAe,CAAC,CAAC,SAAS,MAAM,EAC9C,GAAG,EAAE,CAAC,EAAE,EACR,cAAc,EAAE,CAAC,EAAE,GAClB,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CASzB"}
@@ -19,6 +19,13 @@ export type IconType = {
19
19
  }) => ReactNode;
20
20
  color: string;
21
21
  onPress: () => void;
22
+ /**
23
+ * True for tools that React Buoy offers but the current app has not installed.
24
+ * Unavailable items render like a normal item (real icon + real name at full
25
+ * styling) plus a small muted "Unavailable" caption, and are non-interactive
26
+ * (tapping does nothing and keeps the dial open).
27
+ */
28
+ unavailable?: boolean;
22
29
  };
23
30
  interface DialDevToolsProps {
24
31
  onClose?: () => void;
@@ -1 +1 @@
1
- {"version":3,"file":"DialDevTools.d.ts","sourceRoot":"","sources":["../../../../../src/floatingMenu/dial/DialDevTools.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAwC,SAAS,EAAE,EAAE,EAAE,MAAM,OAAO,CAAC;AA8B5E,OAAO,KAAK,EACV,YAAY,EACZ,mBAAmB,EACnB,iBAAiB,EAClB,MAAM,UAAU,CAAC;AAqBlB,MAAM,MAAM,QAAQ,GAAG;IACrB,EAAE,CAAC,EAAE,MAAM,CAAC;IACZ,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,SAAS,CAAC;IAChB;;;;;;OAMG;IACH,aAAa,CAAC,EAAE,CAAC,GAAG,EAAE;QAAE,IAAI,CAAC,EAAE,MAAM,CAAC;QAAC,IAAI,CAAC,EAAE,MAAM,CAAC;QAAC,KAAK,CAAC,EAAE,iBAAiB,CAAC;QAAC,OAAO,CAAC,EAAE,mBAAmB,CAAA;KAAE,KAAK,SAAS,CAAC;IAC/H,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,MAAM,IAAI,CAAC;CACrB,CAAC;AAWF,UAAU,iBAAiB;IACzB,OAAO,CAAC,EAAE,MAAM,IAAI,CAAC;IACrB,eAAe,CAAC,EAAE,MAAM,IAAI,CAAC;IAC7B,gBAAgB,CAAC,EAAE,OAAO,CAAC;IAC3B,IAAI,EAAE,YAAY,EAAE,CAAC;IACrB,KAAK,CAAC,EAAE,iBAAiB,CAAC;IAC1B,OAAO,CAAC,EAAE,mBAAmB,CAAC;CAC/B;AAED,eAAO,MAAM,YAAY,EAAE,EAAE,CAAC,iBAAiB,CAwmB9C,CAAC"}
1
+ {"version":3,"file":"DialDevTools.d.ts","sourceRoot":"","sources":["../../../../../src/floatingMenu/dial/DialDevTools.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAwC,SAAS,EAAE,EAAE,EAAE,MAAM,OAAO,CAAC;AAgC5E,OAAO,KAAK,EACV,YAAY,EACZ,mBAAmB,EACnB,iBAAiB,EAClB,MAAM,UAAU,CAAC;AAqBlB,MAAM,MAAM,QAAQ,GAAG;IACrB,EAAE,CAAC,EAAE,MAAM,CAAC;IACZ,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,SAAS,CAAC;IAChB;;;;;;OAMG;IACH,aAAa,CAAC,EAAE,CAAC,GAAG,EAAE;QAAE,IAAI,CAAC,EAAE,MAAM,CAAC;QAAC,IAAI,CAAC,EAAE,MAAM,CAAC;QAAC,KAAK,CAAC,EAAE,iBAAiB,CAAC;QAAC,OAAO,CAAC,EAAE,mBAAmB,CAAA;KAAE,KAAK,SAAS,CAAC;IAC/H,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,MAAM,IAAI,CAAC;IACpB;;;;;OAKG;IACH,WAAW,CAAC,EAAE,OAAO,CAAC;CACvB,CAAC;AAWF,UAAU,iBAAiB;IACzB,OAAO,CAAC,EAAE,MAAM,IAAI,CAAC;IACrB,eAAe,CAAC,EAAE,MAAM,IAAI,CAAC;IAC7B,gBAAgB,CAAC,EAAE,OAAO,CAAC;IAC3B,IAAI,EAAE,YAAY,EAAE,CAAC;IACrB,KAAK,CAAC,EAAE,iBAAiB,CAAC;IAC1B,OAAO,CAAC,EAAE,mBAAmB,CAAC;CAC/B;AAED,eAAO,MAAM,YAAY,EAAE,EAAE,CAAC,iBAAiB,CAmrB9C,CAAC"}