@buoy-gg/core 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.
Files changed (27) hide show
  1. package/lib/commonjs/floatingMenu/FloatingDevTools.js +20 -5
  2. package/lib/commonjs/floatingMenu/allToolsRegistry.js +193 -0
  3. package/lib/commonjs/floatingMenu/autoExternalSync.js +40 -1
  4. package/lib/commonjs/floatingMenu/dial/DialDevTools.js +56 -6
  5. package/lib/commonjs/floatingMenu/dial/DialIcon.js +41 -0
  6. package/lib/module/floatingMenu/FloatingDevTools.js +21 -6
  7. package/lib/module/floatingMenu/allToolsRegistry.js +190 -0
  8. package/lib/module/floatingMenu/autoExternalSync.js +41 -2
  9. package/lib/module/floatingMenu/dial/DialDevTools.js +58 -8
  10. package/lib/module/floatingMenu/dial/DialIcon.js +42 -1
  11. package/lib/typescript/commonjs/floatingMenu/FloatingDevTools.d.ts.map +1 -1
  12. package/lib/typescript/commonjs/floatingMenu/allToolsRegistry.d.ts +42 -0
  13. package/lib/typescript/commonjs/floatingMenu/allToolsRegistry.d.ts.map +1 -0
  14. package/lib/typescript/commonjs/floatingMenu/autoExternalSync.d.ts +5 -1
  15. package/lib/typescript/commonjs/floatingMenu/autoExternalSync.d.ts.map +1 -1
  16. package/lib/typescript/commonjs/floatingMenu/dial/DialDevTools.d.ts +7 -0
  17. package/lib/typescript/commonjs/floatingMenu/dial/DialDevTools.d.ts.map +1 -1
  18. package/lib/typescript/commonjs/floatingMenu/dial/DialIcon.d.ts.map +1 -1
  19. package/lib/typescript/module/floatingMenu/FloatingDevTools.d.ts.map +1 -1
  20. package/lib/typescript/module/floatingMenu/allToolsRegistry.d.ts +42 -0
  21. package/lib/typescript/module/floatingMenu/allToolsRegistry.d.ts.map +1 -0
  22. package/lib/typescript/module/floatingMenu/autoExternalSync.d.ts +5 -1
  23. package/lib/typescript/module/floatingMenu/autoExternalSync.d.ts.map +1 -1
  24. package/lib/typescript/module/floatingMenu/dial/DialDevTools.d.ts +7 -0
  25. package/lib/typescript/module/floatingMenu/dial/DialDevTools.d.ts.map +1 -1
  26. package/lib/typescript/module/floatingMenu/dial/DialIcon.d.ts.map +1 -1
  27. package/package.json +5 -5
@@ -118,8 +118,14 @@ const FloatingDevTools = ({
118
118
  ...props
119
119
  }) => {
120
120
  const resolvedEnvironment = environment ?? (0, _sharedUi.normalizeEnvironment)(process.env.NODE_ENV ?? "dev");
121
- // Check Pro status for production gating
122
- const isPro = (0, _license.useIsPro)();
121
+ // Production gating + the device→dashboard license handshake must use a REAL
122
+ // license only NOT the free Weekend Pass. Otherwise shipping Buoy would
123
+ // expose the devtools to end users every weekend, and the dashboard would try
124
+ // to adopt a non-existent key. (Feature unlocks inside the tools still honor
125
+ // the Weekend Pass via their own useIsPro().)
126
+ const {
127
+ isLicensed
128
+ } = (0, _license.useProAccess)();
123
129
 
124
130
  // Get full license state for requireLicense gating
125
131
  const {
@@ -128,10 +134,17 @@ const FloatingDevTools = ({
128
134
  } = (0, _license.useLicense)();
129
135
  const [showLicenseModal, setShowLicenseModal] = (0, _react.useState)(false);
130
136
 
131
- // Initialize license manager on mount, and set/clear license key when prop changes
137
+ // Initialize license manager on mount, and set/clear license key when prop changes.
138
+ // The `licenseKey` prop is the source of truth WHEN PROVIDED:
139
+ // - non-empty → validate + activate that key
140
+ // - "" (blank) → EXPLICITLY clear the cached license (key was removed)
141
+ // - undefined → don't touch it (the app may set a key via Buoy.init())
132
142
  (0, _react.useEffect)(() => {
133
143
  if (licenseKeyProp && licenseKeyProp.trim() !== "") {
134
144
  _license.LicenseManager.initialize().then(() => _license.LicenseManager.setLicenseKey(licenseKeyProp)).catch(() => {});
145
+ } else if (licenseKeyProp === "") {
146
+ // Explicit removal: wipe the 30-day cache so Pro actually turns off.
147
+ _license.LicenseManager.initialize().then(() => _license.LicenseManager.clearLicense()).catch(() => {});
135
148
  } else {
136
149
  _license.LicenseManager.initialize();
137
150
  }
@@ -308,7 +321,7 @@ const FloatingDevTools = ({
308
321
  // Gate: Free tier only works in development mode
309
322
  // Pro users can use DevTools everywhere (dev + production)
310
323
  const isDevelopment = typeof __DEV__ !== "undefined" && __DEV__;
311
- if (!isDevelopment && !isPro) {
324
+ if (!isDevelopment && !isLicensed) {
312
325
  // Free user in production - don't render DevTools
313
326
  return null;
314
327
  }
@@ -346,7 +359,9 @@ const FloatingDevTools = ({
346
359
  })
347
360
  }), children, DebugBordersOverlay && /*#__PURE__*/(0, _jsxRuntime.jsx)(DebugBordersOverlay, {}), HighlightUpdatesOverlay && /*#__PURE__*/(0, _jsxRuntime.jsx)(HighlightUpdatesOverlay, {}), ImageOverlayOverlay && /*#__PURE__*/(0, _jsxRuntime.jsx)(ImageOverlayOverlay, {}), PerfMonitorOverlay && /*#__PURE__*/(0, _jsxRuntime.jsx)(PerfMonitorOverlay, {}), ImpersonateOverlay && /*#__PURE__*/(0, _jsxRuntime.jsx)(ImpersonateOverlay, {}), RouteTracker && /*#__PURE__*/(0, _jsxRuntime.jsx)(RouteTracker, {}), isDevelopment && externalSync !== false && (0, _autoExternalSync.isExternalSyncAvailable)() && /*#__PURE__*/(0, _jsxRuntime.jsx)(_autoExternalSync.AutoExternalSync, {
348
361
  options: typeof externalSync === "object" ? externalSync : undefined,
349
- requiredEnvVars: requiredEnvVars
362
+ requiredEnvVars: requiredEnvVars,
363
+ isPro: isLicensed,
364
+ licenseKey: licenseKey
350
365
  })]
351
366
  })
352
367
  })
@@ -0,0 +1,193 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.ALL_TOOLS_REGISTRY = void 0;
7
+ var _react = _interopRequireDefault(require("react"));
8
+ var _reactNative = require("react-native");
9
+ var _floatingToolsCore = require("@buoy-gg/floating-tools-core");
10
+ var _sharedUi = require("@buoy-gg/shared-ui");
11
+ var _jsxRuntime = require("react/jsx-runtime");
12
+ function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
13
+ /**
14
+ * Canonical registry of ALL dial-eligible tools React Buoy offers on mobile.
15
+ *
16
+ * This is the single source of truth used to compute which tools are
17
+ * "unavailable" (offered but not installed in the current app). It lives
18
+ * inside the floating-menu package so nothing outside needs to be imported.
19
+ *
20
+ * Rules for this file:
21
+ * - Only import from REQUIRED dependencies (@buoy-gg/floating-tools-core,
22
+ * @buoy-gg/shared-ui, react-native) so the icons are always resolvable,
23
+ * even when the optional tool packages are not installed.
24
+ * - Only include tools whose preset slot is NOT "row" (row-only tools never
25
+ * appear in the dial and have no "unavailable" state to show).
26
+ * - Keep the order intentional: this order is the fallback when no usage
27
+ * data exists for new/unavailable tools.
28
+ */
29
+
30
+ // ─── Color constants for tools whose icons live in optional packages ─────────
31
+ // Copied verbatim from the source icon components so the vendored copies below
32
+ // render identically to the real tool icons.
33
+
34
+ /** Zustand brand color — copied from @buoy-gg/zustand ZustandIcon.tsx */const ZUSTAND_ICON_COLOR = "#463B3F";
35
+ /** Jotai brand color — copied from @buoy-gg/jotai JotaiIcon.tsx */
36
+ const JOTAI_ICON_COLOR = "#6C47FF";
37
+ /** Image overlay purple — matches the preset */
38
+ const IMAGE_OVERLAY_ICON_COLOR = "#A855F7";
39
+
40
+ // ─── Vendored copies of optional-package icons ───────────────────────────────
41
+ // Zustand and Jotai ship their real icons inside their own packages (which may
42
+ // not be installed), so we cannot import them from a required dependency.
43
+ //
44
+ // The REAL icons in @buoy-gg/zustand and @buoy-gg/jotai are themselves a single
45
+ // centered letter glyph (verified — there are no SVG logos in those packages).
46
+ // These are faithful copies of those source components, so unavailable items
47
+ // render the ACTUAL tool icon (just dimmed by DialIcon), not a placeholder.
48
+
49
+ /** Faithful copy of @buoy-gg/zustand `ZustandIcon` */
50
+ const ZustandIcon = ({
51
+ size,
52
+ color
53
+ }) => /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.View, {
54
+ style: {
55
+ width: size,
56
+ height: size,
57
+ justifyContent: "center",
58
+ alignItems: "center"
59
+ },
60
+ children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.Text, {
61
+ style: {
62
+ fontSize: size * 0.75,
63
+ color: color || ZUSTAND_ICON_COLOR,
64
+ fontWeight: "700"
65
+ },
66
+ children: "Z"
67
+ })
68
+ });
69
+
70
+ /** Faithful copy of @buoy-gg/jotai `JotaiIcon` */
71
+ const JotaiIcon = ({
72
+ size,
73
+ color
74
+ }) => /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.View, {
75
+ style: {
76
+ width: size,
77
+ height: size,
78
+ justifyContent: "center",
79
+ alignItems: "center"
80
+ },
81
+ children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.Text, {
82
+ style: {
83
+ fontSize: size * 0.75,
84
+ color: color || JOTAI_ICON_COLOR,
85
+ fontWeight: "700"
86
+ },
87
+ children: "J"
88
+ })
89
+ });
90
+
91
+ // ─── Registry entry type ──────────────────────────────────────────────────────
92
+
93
+ // ─── Canonical catalog ────────────────────────────────────────────────────────
94
+
95
+ /**
96
+ * Full list of every dial-eligible tool React Buoy offers on mobile.
97
+ *
98
+ * Available (installed) tools are shown normally in the dial.
99
+ * Unavailable (not installed) tools are appended at the end of the dial and look
100
+ * like a normal item (real icon + real name) with a small muted "Unavailable"
101
+ * caption added; they are non-interactive.
102
+ *
103
+ * To add a new tool to Buoy:
104
+ * 1. Add its preset to autoDiscoverPresets.ts
105
+ * 2. Add an entry here so it appears in the "unavailable" section for apps
106
+ * that haven't installed it yet.
107
+ */
108
+ const ALL_TOOLS_REGISTRY = exports.ALL_TOOLS_REGISTRY = [{
109
+ id: "env",
110
+ name: "ENV",
111
+ color: _floatingToolsCore.ENV_ICON_COLOR,
112
+ renderIcon: size => /*#__PURE__*/(0, _jsxRuntime.jsx)(_floatingToolsCore.EnvIcon, {
113
+ size: size
114
+ })
115
+ }, {
116
+ id: "network",
117
+ name: "NETWORK",
118
+ color: _floatingToolsCore.NETWORK_ICON_COLOR,
119
+ renderIcon: size => /*#__PURE__*/(0, _jsxRuntime.jsx)(_floatingToolsCore.NetworkIcon, {
120
+ size: size
121
+ })
122
+ }, {
123
+ id: "storage",
124
+ name: "STORAGE",
125
+ color: _floatingToolsCore.STORAGE_ICON_COLOR,
126
+ renderIcon: size => /*#__PURE__*/(0, _jsxRuntime.jsx)(_floatingToolsCore.StorageIcon, {
127
+ size: size
128
+ })
129
+ }, {
130
+ id: "query",
131
+ name: "QUERY",
132
+ color: _floatingToolsCore.QUERY_ICON_COLOR,
133
+ renderIcon: size => /*#__PURE__*/(0, _jsxRuntime.jsx)(_floatingToolsCore.QueryIcon, {
134
+ size: size
135
+ })
136
+ }, {
137
+ id: "route-events",
138
+ name: "ROUTES",
139
+ color: _floatingToolsCore.ROUTES_ICON_COLOR,
140
+ renderIcon: size => /*#__PURE__*/(0, _jsxRuntime.jsx)(_floatingToolsCore.RoutesIcon, {
141
+ size: size
142
+ })
143
+ }, {
144
+ id: "highlight-updates-modal",
145
+ name: "HIGHLIGHT",
146
+ color: _floatingToolsCore.HIGHLIGHTER_ICON_COLOR,
147
+ renderIcon: size => /*#__PURE__*/(0, _jsxRuntime.jsx)(_floatingToolsCore.HighlighterIcon, {
148
+ size: size
149
+ })
150
+ }, {
151
+ id: "redux",
152
+ name: "REDUX",
153
+ color: _floatingToolsCore.REDUX_ICON_COLOR,
154
+ renderIcon: size => /*#__PURE__*/(0, _jsxRuntime.jsx)(_floatingToolsCore.ReduxIcon, {
155
+ size: size
156
+ })
157
+ }, {
158
+ id: "zustand",
159
+ name: "ZUSTAND",
160
+ color: ZUSTAND_ICON_COLOR,
161
+ renderIcon: size => /*#__PURE__*/(0, _jsxRuntime.jsx)(ZustandIcon, {
162
+ size: size
163
+ })
164
+ }, {
165
+ id: "events",
166
+ name: "EVENTS",
167
+ color: _floatingToolsCore.EVENTS_ICON_COLOR,
168
+ renderIcon: size => /*#__PURE__*/(0, _jsxRuntime.jsx)(_floatingToolsCore.EventsIcon, {
169
+ size: size
170
+ })
171
+ }, {
172
+ id: "jotai",
173
+ name: "JOTAI",
174
+ color: JOTAI_ICON_COLOR,
175
+ renderIcon: size => /*#__PURE__*/(0, _jsxRuntime.jsx)(JotaiIcon, {
176
+ size: size
177
+ })
178
+ }, {
179
+ id: "image-overlay",
180
+ name: "IMG",
181
+ color: IMAGE_OVERLAY_ICON_COLOR,
182
+ renderIcon: size => /*#__PURE__*/(0, _jsxRuntime.jsx)(_sharedUi.ImageOverlayIcon, {
183
+ size: size,
184
+ color: IMAGE_OVERLAY_ICON_COLOR
185
+ })
186
+ }, {
187
+ id: "perf-monitor-modal",
188
+ name: "BENCH",
189
+ color: _floatingToolsCore.BENCHMARK_ICON_COLOR,
190
+ renderIcon: size => /*#__PURE__*/(0, _jsxRuntime.jsx)(_floatingToolsCore.BenchmarkIcon, {
191
+ size: size
192
+ })
193
+ }];
@@ -40,6 +40,7 @@ let reduxModule = null;
40
40
  let zustandModule = null;
41
41
  let jotaiModule = null;
42
42
  let eventsModule = null;
43
+ let consoleModule = null;
43
44
  let envModule = null;
44
45
  let highlightUpdatesModule = null;
45
46
  let debugBordersModule = null;
@@ -91,6 +92,11 @@ try {
91
92
  } catch {
92
93
  // not installed
93
94
  }
95
+ try {
96
+ consoleModule = require("@buoy-gg/console");
97
+ } catch {
98
+ // not installed
99
+ }
94
100
  try {
95
101
  envModule = require("@buoy-gg/env");
96
102
  } catch {
@@ -140,7 +146,9 @@ function defaultIdentity() {
140
146
  }
141
147
  function AutoExternalSync({
142
148
  options,
143
- requiredEnvVars
149
+ requiredEnvVars,
150
+ isPro,
151
+ licenseKey
144
152
  }) {
145
153
  const {
146
154
  useExternalSyncSocket,
@@ -162,6 +170,34 @@ function AutoExternalSync({
162
170
  platform: _reactNative.Platform.OS,
163
171
  enableLogs: options?.enableLogs
164
172
  });
173
+
174
+ // The license validates asynchronously (Keygen call on mount), usually AFTER
175
+ // the socket handshake is already sent — so the one-shot handshake query
176
+ // can't carry Pro status reliably. Emit it as an event whenever it resolves
177
+ // or changes, and on every (re)connect. The broker stores it on the device
178
+ // record and rebroadcasts, so the desktop dashboard can auto-adopt the key.
179
+ const licenseRef = (0, _react.useRef)({
180
+ isPro,
181
+ licenseKey
182
+ });
183
+ licenseRef.current = {
184
+ isPro,
185
+ licenseKey
186
+ };
187
+ (0, _react.useEffect)(() => {
188
+ if (!socket) return;
189
+ const emitLicense = () => {
190
+ socket.emit("device-license", {
191
+ isPro: licenseRef.current.isPro ? "1" : "0",
192
+ licenseKey: licenseRef.current.licenseKey ?? ""
193
+ });
194
+ };
195
+ if (socket.connected) emitLicense();
196
+ socket.on("connect", emitLicense);
197
+ return () => {
198
+ socket.off("connect", emitLicense);
199
+ };
200
+ }, [socket, isPro, licenseKey]);
165
201
  const tools = (0, _react.useMemo)(() => {
166
202
  const map = {};
167
203
  if (storageModule?.storageSyncAdapter) {
@@ -188,6 +224,9 @@ function AutoExternalSync({
188
224
  if (eventsModule?.eventsSyncAdapter) {
189
225
  map.events = eventsModule.eventsSyncAdapter;
190
226
  }
227
+ if (consoleModule?.consoleSyncAdapter) {
228
+ map.console = consoleModule.consoleSyncAdapter;
229
+ }
191
230
  if (envModule?.createEnvSyncAdapter) {
192
231
  map.env = envModule.createEnvSyncAdapter(requiredEnvVars ?? []);
193
232
  }
@@ -8,6 +8,7 @@ var _react = require("react");
8
8
  var _reactNative = require("react-native");
9
9
  var _sharedUi = require("@buoy-gg/shared-ui");
10
10
  var _DialIcon = require("./DialIcon.js");
11
+ var _allToolsRegistry = require("../allToolsRegistry.js");
11
12
  var _DialPagination = require("./DialPagination.js");
12
13
  var _dialUsageStore = require("./dialUsageStore.js");
13
14
  var _DevToolsSettingsModal = require("../DevToolsSettingsModal");
@@ -51,7 +52,10 @@ const DialDevTools = ({
51
52
  const {
52
53
  open
53
54
  } = (0, _AppHost.useAppHost)();
54
- const isPro = (0, _license.useIsPro)();
55
+ const {
56
+ isPro,
57
+ isWeekendFree
58
+ } = (0, _license.useProAccess)();
55
59
 
56
60
  // Live window size — keeps the dial centered and sized correctly when the
57
61
  // window resizes (Electron/web) or the device rotates.
@@ -211,6 +215,35 @@ const DialDevTools = ({
211
215
  return map;
212
216
  }, [dialApps, actions, open, onClose]);
213
217
 
218
+ // Tools from the global registry that are NOT installed in this app.
219
+ // These are appended after all available tools so paging "next" eventually
220
+ // reveals them. They are display-only (real icon + real name + "Unavailable").
221
+ const unavailableTools = (0, _react.useMemo)(() => {
222
+ const installedIds = new Set(dialApps.map(a => a.id));
223
+ return _allToolsRegistry.ALL_TOOLS_REGISTRY.filter(t => !installedIds.has(t.id));
224
+ }, [dialApps]);
225
+
226
+ // Build stable IconType entries for each unavailable tool.
227
+ const unavailableIconsById = (0, _react.useMemo)(() => {
228
+ const map = new Map();
229
+ for (const tool of unavailableTools) {
230
+ map.set(tool.id, {
231
+ id: tool.id,
232
+ name: tool.name,
233
+ // Pre-render the icon at the standard dial slot size so it looks correct.
234
+ icon: tool.renderIcon(_floatingToolsCore.DIAL_ICON_SIZE),
235
+ iconComponent: undefined,
236
+ color: tool.color,
237
+ unavailable: true,
238
+ // Tapping an unavailable tool is intentionally a no-op: the dial stays
239
+ // open and no modal launches, signalling the tool is not installed.
240
+ // Future: add a brief Toast with an install link here.
241
+ onPress: () => {}
242
+ });
243
+ }
244
+ return map;
245
+ }, [unavailableTools]);
246
+
214
247
  // Snapshot the usage-ranked order when the dial opens. It stays stable while
215
248
  // open so icons don't jump positions mid-interaction.
216
249
  const [rankedIds, setRankedIds] = (0, _react.useState)(() => (0, _dialUsageStore.getRankedToolIds)(dialApps.map(a => a.id)));
@@ -229,7 +262,9 @@ const DialDevTools = ({
229
262
  cancelled = true;
230
263
  };
231
264
  }, [dialApps]);
232
- const pageCount = Math.max(1, Math.ceil(rankedIds.length / _floatingToolsCore.MAX_DIAL_SLOTS));
265
+
266
+ // Page count spans available tools (usage-ranked) + unavailable tools (appended).
267
+ const pageCount = Math.max(1, Math.ceil((rankedIds.length + unavailableTools.length) / _floatingToolsCore.MAX_DIAL_SLOTS));
233
268
  const [currentPage, setCurrentPage] = (0, _react.useState)(0);
234
269
  const safePage = Math.min(currentPage, pageCount - 1);
235
270
 
@@ -237,13 +272,18 @@ const DialDevTools = ({
237
272
  // snapshotted on open, so each icon's page and slot are fixed for the
238
273
  // session — which lets us mount all icons once and paginate purely by
239
274
  // toggling visibility (no remounts on page change).
275
+ //
276
+ // Order: usage-ranked available tools first, unavailable tools appended at
277
+ // the very end. This guarantees unavailable items always appear on the last
278
+ // pages and never displace available tools.
240
279
  const allDialIcons = (0, _react.useMemo)(() => {
241
- return rankedIds.map(id => iconsById.get(id)).filter(icon => Boolean(icon)).map((icon, i) => ({
280
+ const allIds = [...rankedIds, ...unavailableTools.map(t => t.id)];
281
+ return allIds.map(id => iconsById.get(id) ?? unavailableIconsById.get(id)).filter(icon => Boolean(icon)).map((icon, i) => ({
242
282
  icon,
243
283
  page: Math.floor(i / _floatingToolsCore.MAX_DIAL_SLOTS),
244
284
  slot: i % _floatingToolsCore.MAX_DIAL_SLOTS
245
285
  }));
246
- }, [rankedIds, iconsById]);
286
+ }, [rankedIds, iconsById, unavailableTools, unavailableIconsById]);
247
287
 
248
288
  // Empty slot indices for the current page (only the last page can be
249
289
  // partial). These are cheap placeholder dots.
@@ -445,6 +485,10 @@ const DialDevTools = ({
445
485
  });
446
486
  };
447
487
  const handleIconPress = icon => {
488
+ // Unavailable tools are display-only. Return early so the dial stays open
489
+ // and no modal or animation is triggered. The dimmed appearance already
490
+ // communicates that the tool is not installed.
491
+ if (icon.unavailable) return;
448
492
  setSelectedIcon(1);
449
493
  const interaction = _floatingToolsCore.dialAnimationConfig?.interaction ?? {
450
494
  iconSelect: {
@@ -612,8 +656,8 @@ const DialDevTools = ({
612
656
  style: styles.centerText,
613
657
  children: "BUOY"
614
658
  }), isPro && /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.Text, {
615
- style: styles.proText,
616
- children: "PRO"
659
+ style: [styles.proText, isWeekendFree && styles.weekendText],
660
+ children: isWeekendFree ? "WEEKEND" : "PRO"
617
661
  })]
618
662
  })
619
663
  })
@@ -819,5 +863,11 @@ const styles = _reactNative.StyleSheet.create({
819
863
  height: 0
820
864
  },
821
865
  textShadowRadius: 4
866
+ },
867
+ // Weekend Pass variant — violet, tighter spacing so "WEEKEND" fits the dial.
868
+ weekendText: {
869
+ color: "#BF5AF2",
870
+ letterSpacing: 1,
871
+ textShadowColor: "#BF5AF2"
822
872
  }
823
873
  });
@@ -157,6 +157,32 @@ const DialIcon = ({
157
157
  children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.View, {
158
158
  style: styles.emptyDot
159
159
  })
160
+ }) : icon.unavailable ?
161
+ /*#__PURE__*/
162
+ // ── Unavailable tool ──────────────────────────────────────────────────
163
+ // Renders the real icon + real name at NORMAL styling (visually identical
164
+ // to an installed tool). The ONLY signal that it's unavailable is the small
165
+ // muted "Unavailable" caption under the name. It's non-interactive: no
166
+ // Pressable, and the dial stays open when tapped because
167
+ // DialDevTools.handleIconPress returns early for unavailable icons.
168
+ (0, _jsxRuntime.jsxs)(_reactNative.View, {
169
+ style: styles.pressable,
170
+ children: [/*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.View, {
171
+ style: styles.iconWrapper,
172
+ children: icon.icon
173
+ }), /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.Text, {
174
+ style: styles.label,
175
+ numberOfLines: 1,
176
+ adjustsFontSizeToFit: true,
177
+ minimumFontScale: 0.7,
178
+ children: icon.name.toUpperCase()
179
+ }), /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.Text, {
180
+ style: styles.unavailableCaption,
181
+ numberOfLines: 1,
182
+ adjustsFontSizeToFit: true,
183
+ minimumFontScale: 0.6,
184
+ children: "Unavailable"
185
+ })]
160
186
  }) : /*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNative.Pressable, {
161
187
  onPress: () => onPress(icon),
162
188
  onPressIn: handlePressIn,
@@ -248,5 +274,20 @@ const styles = _reactNative.StyleSheet.create({
248
274
  backgroundColor: _floatingToolsCore.dialColors.emptyDotBackground,
249
275
  borderWidth: _floatingToolsCore.dialStyles.emptySlot.borderWidth,
250
276
  borderColor: _floatingToolsCore.dialColors.emptyDotBorder
277
+ },
278
+ // ── Unavailable tool styles ────────────────────────────────────────────────
279
+ /**
280
+ * Small muted caption shown under the (normal-styled) tool name — the only
281
+ * signal that the tool is not installed. Kept compact (smaller than the label)
282
+ * so the extra line doesn't disturb the arc layout. Uses the shared muted
283
+ * theme token rather than a hardcoded color.
284
+ */
285
+ unavailableCaption: {
286
+ fontSize: _floatingToolsCore.dialStyles.icon.label.fontSize - 1,
287
+ fontWeight: _floatingToolsCore.dialStyles.icon.label.fontWeight,
288
+ letterSpacing: _floatingToolsCore.dialStyles.icon.label.letterSpacing,
289
+ fontFamily: _floatingToolsCore.dialStyles.icon.label.fontFamily,
290
+ color: _floatingToolsCore.floatingToolsColors.muted,
291
+ textTransform: "uppercase"
251
292
  }
252
293
  });
@@ -11,7 +11,7 @@ import { HintsProvider, LicenseEntryModal, normalizeEnvironment } from "@buoy-gg
11
11
  import { MinimizedToolsProvider } from "./MinimizedToolsContext.js";
12
12
  import { validateDialConfig } from "./defaultConfig.js";
13
13
  import { DefaultConfigProvider } from "./DefaultConfigContext.js";
14
- import { LicenseManager, useIsPro, useLicense } from "@buoy-gg/license";
14
+ import { LicenseManager, useProAccess, useLicense } from "@buoy-gg/license";
15
15
  import { AutoExternalSync, isExternalSyncAvailable } from "./autoExternalSync.js";
16
16
 
17
17
  /**
@@ -114,8 +114,14 @@ export const FloatingDevTools = ({
114
114
  ...props
115
115
  }) => {
116
116
  const resolvedEnvironment = environment ?? normalizeEnvironment(process.env.NODE_ENV ?? "dev");
117
- // Check Pro status for production gating
118
- const isPro = useIsPro();
117
+ // Production gating + the device→dashboard license handshake must use a REAL
118
+ // license only — NOT the free Weekend Pass. Otherwise shipping Buoy would
119
+ // expose the devtools to end users every weekend, and the dashboard would try
120
+ // to adopt a non-existent key. (Feature unlocks inside the tools still honor
121
+ // the Weekend Pass via their own useIsPro().)
122
+ const {
123
+ isLicensed
124
+ } = useProAccess();
119
125
 
120
126
  // Get full license state for requireLicense gating
121
127
  const {
@@ -124,10 +130,17 @@ export const FloatingDevTools = ({
124
130
  } = useLicense();
125
131
  const [showLicenseModal, setShowLicenseModal] = useState(false);
126
132
 
127
- // Initialize license manager on mount, and set/clear license key when prop changes
133
+ // Initialize license manager on mount, and set/clear license key when prop changes.
134
+ // The `licenseKey` prop is the source of truth WHEN PROVIDED:
135
+ // - non-empty → validate + activate that key
136
+ // - "" (blank) → EXPLICITLY clear the cached license (key was removed)
137
+ // - undefined → don't touch it (the app may set a key via Buoy.init())
128
138
  useEffect(() => {
129
139
  if (licenseKeyProp && licenseKeyProp.trim() !== "") {
130
140
  LicenseManager.initialize().then(() => LicenseManager.setLicenseKey(licenseKeyProp)).catch(() => {});
141
+ } else if (licenseKeyProp === "") {
142
+ // Explicit removal: wipe the 30-day cache so Pro actually turns off.
143
+ LicenseManager.initialize().then(() => LicenseManager.clearLicense()).catch(() => {});
131
144
  } else {
132
145
  LicenseManager.initialize();
133
146
  }
@@ -304,7 +317,7 @@ export const FloatingDevTools = ({
304
317
  // Gate: Free tier only works in development mode
305
318
  // Pro users can use DevTools everywhere (dev + production)
306
319
  const isDevelopment = typeof __DEV__ !== "undefined" && __DEV__;
307
- if (!isDevelopment && !isPro) {
320
+ if (!isDevelopment && !isLicensed) {
308
321
  // Free user in production - don't render DevTools
309
322
  return null;
310
323
  }
@@ -342,7 +355,9 @@ export const FloatingDevTools = ({
342
355
  })
343
356
  }), children, DebugBordersOverlay && /*#__PURE__*/_jsx(DebugBordersOverlay, {}), HighlightUpdatesOverlay && /*#__PURE__*/_jsx(HighlightUpdatesOverlay, {}), ImageOverlayOverlay && /*#__PURE__*/_jsx(ImageOverlayOverlay, {}), PerfMonitorOverlay && /*#__PURE__*/_jsx(PerfMonitorOverlay, {}), ImpersonateOverlay && /*#__PURE__*/_jsx(ImpersonateOverlay, {}), RouteTracker && /*#__PURE__*/_jsx(RouteTracker, {}), isDevelopment && externalSync !== false && isExternalSyncAvailable() && /*#__PURE__*/_jsx(AutoExternalSync, {
344
357
  options: typeof externalSync === "object" ? externalSync : undefined,
345
- requiredEnvVars: requiredEnvVars
358
+ requiredEnvVars: requiredEnvVars,
359
+ isPro: isLicensed,
360
+ licenseKey: licenseKey
346
361
  })]
347
362
  })
348
363
  })
@@ -0,0 +1,190 @@
1
+ "use strict";
2
+
3
+ /**
4
+ * Canonical registry of ALL dial-eligible tools React Buoy offers on mobile.
5
+ *
6
+ * This is the single source of truth used to compute which tools are
7
+ * "unavailable" (offered but not installed in the current app). It lives
8
+ * inside the floating-menu package so nothing outside needs to be imported.
9
+ *
10
+ * Rules for this file:
11
+ * - Only import from REQUIRED dependencies (@buoy-gg/floating-tools-core,
12
+ * @buoy-gg/shared-ui, react-native) so the icons are always resolvable,
13
+ * even when the optional tool packages are not installed.
14
+ * - Only include tools whose preset slot is NOT "row" (row-only tools never
15
+ * appear in the dial and have no "unavailable" state to show).
16
+ * - Keep the order intentional: this order is the fallback when no usage
17
+ * data exists for new/unavailable tools.
18
+ */
19
+
20
+ import React from "react";
21
+ import { View, Text } from "react-native";
22
+ import { EnvIcon, ENV_ICON_COLOR, NetworkIcon, NETWORK_ICON_COLOR, StorageIcon, STORAGE_ICON_COLOR, QueryIcon, QUERY_ICON_COLOR, RoutesIcon, ROUTES_ICON_COLOR, HighlighterIcon, HIGHLIGHTER_ICON_COLOR, ReduxIcon, REDUX_ICON_COLOR, EventsIcon, EVENTS_ICON_COLOR, BenchmarkIcon, BENCHMARK_ICON_COLOR } from "@buoy-gg/floating-tools-core";
23
+ import { ImageOverlayIcon } from "@buoy-gg/shared-ui";
24
+
25
+ // ─── Color constants for tools whose icons live in optional packages ─────────
26
+ // Copied verbatim from the source icon components so the vendored copies below
27
+ // render identically to the real tool icons.
28
+
29
+ /** Zustand brand color — copied from @buoy-gg/zustand ZustandIcon.tsx */
30
+ import { jsx as _jsx } from "react/jsx-runtime";
31
+ const ZUSTAND_ICON_COLOR = "#463B3F";
32
+ /** Jotai brand color — copied from @buoy-gg/jotai JotaiIcon.tsx */
33
+ const JOTAI_ICON_COLOR = "#6C47FF";
34
+ /** Image overlay purple — matches the preset */
35
+ const IMAGE_OVERLAY_ICON_COLOR = "#A855F7";
36
+
37
+ // ─── Vendored copies of optional-package icons ───────────────────────────────
38
+ // Zustand and Jotai ship their real icons inside their own packages (which may
39
+ // not be installed), so we cannot import them from a required dependency.
40
+ //
41
+ // The REAL icons in @buoy-gg/zustand and @buoy-gg/jotai are themselves a single
42
+ // centered letter glyph (verified — there are no SVG logos in those packages).
43
+ // These are faithful copies of those source components, so unavailable items
44
+ // render the ACTUAL tool icon (just dimmed by DialIcon), not a placeholder.
45
+
46
+ /** Faithful copy of @buoy-gg/zustand `ZustandIcon` */
47
+ const ZustandIcon = ({
48
+ size,
49
+ color
50
+ }) => /*#__PURE__*/_jsx(View, {
51
+ style: {
52
+ width: size,
53
+ height: size,
54
+ justifyContent: "center",
55
+ alignItems: "center"
56
+ },
57
+ children: /*#__PURE__*/_jsx(Text, {
58
+ style: {
59
+ fontSize: size * 0.75,
60
+ color: color || ZUSTAND_ICON_COLOR,
61
+ fontWeight: "700"
62
+ },
63
+ children: "Z"
64
+ })
65
+ });
66
+
67
+ /** Faithful copy of @buoy-gg/jotai `JotaiIcon` */
68
+ const JotaiIcon = ({
69
+ size,
70
+ color
71
+ }) => /*#__PURE__*/_jsx(View, {
72
+ style: {
73
+ width: size,
74
+ height: size,
75
+ justifyContent: "center",
76
+ alignItems: "center"
77
+ },
78
+ children: /*#__PURE__*/_jsx(Text, {
79
+ style: {
80
+ fontSize: size * 0.75,
81
+ color: color || JOTAI_ICON_COLOR,
82
+ fontWeight: "700"
83
+ },
84
+ children: "J"
85
+ })
86
+ });
87
+
88
+ // ─── Registry entry type ──────────────────────────────────────────────────────
89
+
90
+ // ─── Canonical catalog ────────────────────────────────────────────────────────
91
+
92
+ /**
93
+ * Full list of every dial-eligible tool React Buoy offers on mobile.
94
+ *
95
+ * Available (installed) tools are shown normally in the dial.
96
+ * Unavailable (not installed) tools are appended at the end of the dial and look
97
+ * like a normal item (real icon + real name) with a small muted "Unavailable"
98
+ * caption added; they are non-interactive.
99
+ *
100
+ * To add a new tool to Buoy:
101
+ * 1. Add its preset to autoDiscoverPresets.ts
102
+ * 2. Add an entry here so it appears in the "unavailable" section for apps
103
+ * that haven't installed it yet.
104
+ */
105
+ export const ALL_TOOLS_REGISTRY = [{
106
+ id: "env",
107
+ name: "ENV",
108
+ color: ENV_ICON_COLOR,
109
+ renderIcon: size => /*#__PURE__*/_jsx(EnvIcon, {
110
+ size: size
111
+ })
112
+ }, {
113
+ id: "network",
114
+ name: "NETWORK",
115
+ color: NETWORK_ICON_COLOR,
116
+ renderIcon: size => /*#__PURE__*/_jsx(NetworkIcon, {
117
+ size: size
118
+ })
119
+ }, {
120
+ id: "storage",
121
+ name: "STORAGE",
122
+ color: STORAGE_ICON_COLOR,
123
+ renderIcon: size => /*#__PURE__*/_jsx(StorageIcon, {
124
+ size: size
125
+ })
126
+ }, {
127
+ id: "query",
128
+ name: "QUERY",
129
+ color: QUERY_ICON_COLOR,
130
+ renderIcon: size => /*#__PURE__*/_jsx(QueryIcon, {
131
+ size: size
132
+ })
133
+ }, {
134
+ id: "route-events",
135
+ name: "ROUTES",
136
+ color: ROUTES_ICON_COLOR,
137
+ renderIcon: size => /*#__PURE__*/_jsx(RoutesIcon, {
138
+ size: size
139
+ })
140
+ }, {
141
+ id: "highlight-updates-modal",
142
+ name: "HIGHLIGHT",
143
+ color: HIGHLIGHTER_ICON_COLOR,
144
+ renderIcon: size => /*#__PURE__*/_jsx(HighlighterIcon, {
145
+ size: size
146
+ })
147
+ }, {
148
+ id: "redux",
149
+ name: "REDUX",
150
+ color: REDUX_ICON_COLOR,
151
+ renderIcon: size => /*#__PURE__*/_jsx(ReduxIcon, {
152
+ size: size
153
+ })
154
+ }, {
155
+ id: "zustand",
156
+ name: "ZUSTAND",
157
+ color: ZUSTAND_ICON_COLOR,
158
+ renderIcon: size => /*#__PURE__*/_jsx(ZustandIcon, {
159
+ size: size
160
+ })
161
+ }, {
162
+ id: "events",
163
+ name: "EVENTS",
164
+ color: EVENTS_ICON_COLOR,
165
+ renderIcon: size => /*#__PURE__*/_jsx(EventsIcon, {
166
+ size: size
167
+ })
168
+ }, {
169
+ id: "jotai",
170
+ name: "JOTAI",
171
+ color: JOTAI_ICON_COLOR,
172
+ renderIcon: size => /*#__PURE__*/_jsx(JotaiIcon, {
173
+ size: size
174
+ })
175
+ }, {
176
+ id: "image-overlay",
177
+ name: "IMG",
178
+ color: IMAGE_OVERLAY_ICON_COLOR,
179
+ renderIcon: size => /*#__PURE__*/_jsx(ImageOverlayIcon, {
180
+ size: size,
181
+ color: IMAGE_OVERLAY_ICON_COLOR
182
+ })
183
+ }, {
184
+ id: "perf-monitor-modal",
185
+ name: "BENCH",
186
+ color: BENCHMARK_ICON_COLOR,
187
+ renderIcon: size => /*#__PURE__*/_jsx(BenchmarkIcon, {
188
+ size: size
189
+ })
190
+ }];
@@ -13,7 +13,7 @@
13
13
  * Identity defaults come from expo-constants when available (app name →
14
14
  * "MyApp (ios)" / "myapp-ios"), overridable via the `externalSync` prop.
15
15
  */
16
- import { useMemo } from "react";
16
+ import { useEffect, useMemo, useRef } from "react";
17
17
  import { Platform } from "react-native";
18
18
  /* eslint-disable @typescript-eslint/no-var-requires */
19
19
 
@@ -34,6 +34,7 @@ let reduxModule = null;
34
34
  let zustandModule = null;
35
35
  let jotaiModule = null;
36
36
  let eventsModule = null;
37
+ let consoleModule = null;
37
38
  let envModule = null;
38
39
  let highlightUpdatesModule = null;
39
40
  let debugBordersModule = null;
@@ -85,6 +86,11 @@ try {
85
86
  } catch {
86
87
  // not installed
87
88
  }
89
+ try {
90
+ consoleModule = require("@buoy-gg/console");
91
+ } catch {
92
+ // not installed
93
+ }
88
94
  try {
89
95
  envModule = require("@buoy-gg/env");
90
96
  } catch {
@@ -134,7 +140,9 @@ function defaultIdentity() {
134
140
  }
135
141
  export function AutoExternalSync({
136
142
  options,
137
- requiredEnvVars
143
+ requiredEnvVars,
144
+ isPro,
145
+ licenseKey
138
146
  }) {
139
147
  const {
140
148
  useExternalSyncSocket,
@@ -156,6 +164,34 @@ export function AutoExternalSync({
156
164
  platform: Platform.OS,
157
165
  enableLogs: options?.enableLogs
158
166
  });
167
+
168
+ // The license validates asynchronously (Keygen call on mount), usually AFTER
169
+ // the socket handshake is already sent — so the one-shot handshake query
170
+ // can't carry Pro status reliably. Emit it as an event whenever it resolves
171
+ // or changes, and on every (re)connect. The broker stores it on the device
172
+ // record and rebroadcasts, so the desktop dashboard can auto-adopt the key.
173
+ const licenseRef = useRef({
174
+ isPro,
175
+ licenseKey
176
+ });
177
+ licenseRef.current = {
178
+ isPro,
179
+ licenseKey
180
+ };
181
+ useEffect(() => {
182
+ if (!socket) return;
183
+ const emitLicense = () => {
184
+ socket.emit("device-license", {
185
+ isPro: licenseRef.current.isPro ? "1" : "0",
186
+ licenseKey: licenseRef.current.licenseKey ?? ""
187
+ });
188
+ };
189
+ if (socket.connected) emitLicense();
190
+ socket.on("connect", emitLicense);
191
+ return () => {
192
+ socket.off("connect", emitLicense);
193
+ };
194
+ }, [socket, isPro, licenseKey]);
159
195
  const tools = useMemo(() => {
160
196
  const map = {};
161
197
  if (storageModule?.storageSyncAdapter) {
@@ -182,6 +218,9 @@ export function AutoExternalSync({
182
218
  if (eventsModule?.eventsSyncAdapter) {
183
219
  map.events = eventsModule.eventsSyncAdapter;
184
220
  }
221
+ if (consoleModule?.consoleSyncAdapter) {
222
+ map.console = consoleModule.consoleSyncAdapter;
223
+ }
185
224
  if (envModule?.createEnvSyncAdapter) {
186
225
  map.env = envModule.createEnvSyncAdapter(requiredEnvVars ?? []);
187
226
  }
@@ -5,14 +5,15 @@ import { Pressable, StyleSheet, View, useWindowDimensions, Text, Animated, Easin
5
5
  import { absoluteFill } from "@buoy-gg/shared-ui";
6
6
  // Icons are provided by installedApps; no direct icon imports here.
7
7
  import { DialIcon } from "./DialIcon.js";
8
+ import { ALL_TOOLS_REGISTRY } from "../allToolsRegistry.js";
8
9
  import { DialPagination } from "./DialPagination.js";
9
10
  import { getRankedToolIds, isDialUsageLoaded, loadDialUsage, recordToolUsage } from "./dialUsageStore.js";
10
11
  import { persistentStorage, useHintsDisabled, devToolsStorageKeys, buoyColors } from "@buoy-gg/shared-ui";
11
12
  import { DevToolsSettingsModal, useDevToolsSettings } from "../DevToolsSettingsModal";
12
- import { useIsPro } from "@buoy-gg/license";
13
+ import { useProAccess } from "@buoy-gg/license";
13
14
  import { useAppHost } from "../AppHost.js";
14
15
  import { OnboardingTooltip } from "./OnboardingTooltip.js";
15
- import { getDialLayout, MAX_DIAL_SLOTS, DIAL_BUTTON_SIZE, dialAnimationConfig, dialColors } from "@buoy-gg/floating-tools-core";
16
+ import { getDialLayout, MAX_DIAL_SLOTS, DIAL_BUTTON_SIZE, DIAL_ICON_SIZE, dialAnimationConfig, dialColors } from "@buoy-gg/floating-tools-core";
16
17
 
17
18
  // The circle size depends on the live window width, so it's computed inside
18
19
  // the component via useWindowDimensions — a module-scope Dimensions.get
@@ -48,7 +49,10 @@ export const DialDevTools = ({
48
49
  const {
49
50
  open
50
51
  } = useAppHost();
51
- const isPro = useIsPro();
52
+ const {
53
+ isPro,
54
+ isWeekendFree
55
+ } = useProAccess();
52
56
 
53
57
  // Live window size — keeps the dial centered and sized correctly when the
54
58
  // window resizes (Electron/web) or the device rotates.
@@ -208,6 +212,35 @@ export const DialDevTools = ({
208
212
  return map;
209
213
  }, [dialApps, actions, open, onClose]);
210
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
+
211
244
  // Snapshot the usage-ranked order when the dial opens. It stays stable while
212
245
  // open so icons don't jump positions mid-interaction.
213
246
  const [rankedIds, setRankedIds] = useState(() => getRankedToolIds(dialApps.map(a => a.id)));
@@ -226,7 +259,9 @@ export const DialDevTools = ({
226
259
  cancelled = true;
227
260
  };
228
261
  }, [dialApps]);
229
- 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));
230
265
  const [currentPage, setCurrentPage] = useState(0);
231
266
  const safePage = Math.min(currentPage, pageCount - 1);
232
267
 
@@ -234,13 +269,18 @@ export const DialDevTools = ({
234
269
  // snapshotted on open, so each icon's page and slot are fixed for the
235
270
  // session — which lets us mount all icons once and paginate purely by
236
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.
237
276
  const allDialIcons = useMemo(() => {
238
- 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) => ({
239
279
  icon,
240
280
  page: Math.floor(i / MAX_DIAL_SLOTS),
241
281
  slot: i % MAX_DIAL_SLOTS
242
282
  }));
243
- }, [rankedIds, iconsById]);
283
+ }, [rankedIds, iconsById, unavailableTools, unavailableIconsById]);
244
284
 
245
285
  // Empty slot indices for the current page (only the last page can be
246
286
  // partial). These are cheap placeholder dots.
@@ -442,6 +482,10 @@ export const DialDevTools = ({
442
482
  });
443
483
  };
444
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;
445
489
  setSelectedIcon(1);
446
490
  const interaction = dialAnimationConfig?.interaction ?? {
447
491
  iconSelect: {
@@ -609,8 +653,8 @@ export const DialDevTools = ({
609
653
  style: styles.centerText,
610
654
  children: "BUOY"
611
655
  }), isPro && /*#__PURE__*/_jsx(Text, {
612
- style: styles.proText,
613
- children: "PRO"
656
+ style: [styles.proText, isWeekendFree && styles.weekendText],
657
+ children: isWeekendFree ? "WEEKEND" : "PRO"
614
658
  })]
615
659
  })
616
660
  })
@@ -815,5 +859,11 @@ const styles = StyleSheet.create({
815
859
  height: 0
816
860
  },
817
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"
818
868
  }
819
869
  });
@@ -2,7 +2,7 @@
2
2
 
3
3
  import { useMemo, useRef } from "react";
4
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 } from "@buoy-gg/floating-tools-core";
5
+ import { getDialLayout, getIconPosition, getIconStaggerInputRange, DIAL_START_ANGLE, DIAL_ICON_SIZE, dialColors, dialStyles, dialAnimationConfig, floatingToolsColors } from "@buoy-gg/floating-tools-core";
6
6
 
7
7
  // The circle radius depends on the live window width and is computed inside
8
8
  // the component (must match DialDevTools' circle, which does the same).
@@ -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
  });
@@ -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;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,6BAqPvB,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"}
@@ -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"}
@@ -15,7 +15,11 @@ interface AutoExternalSyncProps {
15
15
  options?: ExternalSyncOptions;
16
16
  /** FloatingDevTools' requiredEnvVars — reused for the env tool's adapter. */
17
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;
18
22
  }
19
- export declare function AutoExternalSync({ options, requiredEnvVars, }: AutoExternalSyncProps): null;
23
+ export declare function AutoExternalSync({ options, requiredEnvVars, isPro, licenseKey, }: AutoExternalSyncProps): null;
20
24
  export {};
21
25
  //# sourceMappingURL=autoExternalSync.d.ts.map
@@ -1 +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;AAwGvD,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;CAClC;AAED,wBAAgB,gBAAgB,CAAC,EAC/B,OAAO,EACP,eAAe,GAChB,EAAE,qBAAqB,QA4EvB"}
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,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;AA+B5E,OAAO,KAAK,EACV,YAAY,EACZ,mBAAmB,EACnB,iBAAiB,EAClB,MAAM,UAAU,CAAC;AAoBlB,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,CA4nB9C,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"}
@@ -1 +1 @@
1
- {"version":3,"file":"DialIcon.d.ts","sourceRoot":"","sources":["../../../../../src/floatingMenu/dial/DialIcon.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAmB,EAAE,EAAE,MAAM,OAAO,CAAC;AAC5C,OAAO,EAML,QAAQ,EACT,MAAM,cAAc,CAAC;AACtB,OAAO,EAAE,QAAQ,EAAE,MAAM,gBAAgB,CAAC;AAgB1C,KAAK,KAAK,GAAG;IACX,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,QAAQ,CAAC;IACf,aAAa,EAAE,QAAQ,CAAC,KAAK,CAAC;IAC9B,OAAO,EAAE,CAAC,IAAI,EAAE,QAAQ,KAAK,IAAI,CAAC;IAClC,UAAU,EAAE,MAAM,CAAC;IACnB;;;;OAIG;IACH,MAAM,EAAE,OAAO,CAAC;CACjB,CAAC;AAEF,eAAO,MAAM,QAAQ,EAAE,EAAE,CAAC,KAAK,CAuM9B,CAAC"}
1
+ {"version":3,"file":"DialIcon.d.ts","sourceRoot":"","sources":["../../../../../src/floatingMenu/dial/DialIcon.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAmB,EAAE,EAAE,MAAM,OAAO,CAAC;AAC5C,OAAO,EAML,QAAQ,EACT,MAAM,cAAc,CAAC;AACtB,OAAO,EAAE,QAAQ,EAAE,MAAM,gBAAgB,CAAC;AAiB1C,KAAK,KAAK,GAAG;IACX,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,QAAQ,CAAC;IACf,aAAa,EAAE,QAAQ,CAAC,KAAK,CAAC;IAC9B,OAAO,EAAE,CAAC,IAAI,EAAE,QAAQ,KAAK,IAAI,CAAC;IAClC,UAAU,EAAE,MAAM,CAAC;IACnB;;;;OAIG;IACH,MAAM,EAAE,OAAO,CAAC;CACjB,CAAC;AAEF,eAAO,MAAM,QAAQ,EAAE,EAAE,CAAC,KAAK,CAwO9B,CAAC"}
@@ -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;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,6BAqPvB,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"}
@@ -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"}
@@ -15,7 +15,11 @@ interface AutoExternalSyncProps {
15
15
  options?: ExternalSyncOptions;
16
16
  /** FloatingDevTools' requiredEnvVars — reused for the env tool's adapter. */
17
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;
18
22
  }
19
- export declare function AutoExternalSync({ options, requiredEnvVars, }: AutoExternalSyncProps): null;
23
+ export declare function AutoExternalSync({ options, requiredEnvVars, isPro, licenseKey, }: AutoExternalSyncProps): null;
20
24
  export {};
21
25
  //# sourceMappingURL=autoExternalSync.d.ts.map
@@ -1 +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;AAwGvD,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;CAClC;AAED,wBAAgB,gBAAgB,CAAC,EAC/B,OAAO,EACP,eAAe,GAChB,EAAE,qBAAqB,QA4EvB"}
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,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;AA+B5E,OAAO,KAAK,EACV,YAAY,EACZ,mBAAmB,EACnB,iBAAiB,EAClB,MAAM,UAAU,CAAC;AAoBlB,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,CA4nB9C,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"}
@@ -1 +1 @@
1
- {"version":3,"file":"DialIcon.d.ts","sourceRoot":"","sources":["../../../../../src/floatingMenu/dial/DialIcon.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAmB,EAAE,EAAE,MAAM,OAAO,CAAC;AAC5C,OAAO,EAML,QAAQ,EACT,MAAM,cAAc,CAAC;AACtB,OAAO,EAAE,QAAQ,EAAE,MAAM,gBAAgB,CAAC;AAgB1C,KAAK,KAAK,GAAG;IACX,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,QAAQ,CAAC;IACf,aAAa,EAAE,QAAQ,CAAC,KAAK,CAAC;IAC9B,OAAO,EAAE,CAAC,IAAI,EAAE,QAAQ,KAAK,IAAI,CAAC;IAClC,UAAU,EAAE,MAAM,CAAC;IACnB;;;;OAIG;IACH,MAAM,EAAE,OAAO,CAAC;CACjB,CAAC;AAEF,eAAO,MAAM,QAAQ,EAAE,EAAE,CAAC,KAAK,CAuM9B,CAAC"}
1
+ {"version":3,"file":"DialIcon.d.ts","sourceRoot":"","sources":["../../../../../src/floatingMenu/dial/DialIcon.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAmB,EAAE,EAAE,MAAM,OAAO,CAAC;AAC5C,OAAO,EAML,QAAQ,EACT,MAAM,cAAc,CAAC;AACtB,OAAO,EAAE,QAAQ,EAAE,MAAM,gBAAgB,CAAC;AAiB1C,KAAK,KAAK,GAAG;IACX,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,QAAQ,CAAC;IACf,aAAa,EAAE,QAAQ,CAAC,KAAK,CAAC;IAC9B,OAAO,EAAE,CAAC,IAAI,EAAE,QAAQ,KAAK,IAAI,CAAC;IAClC,UAAU,EAAE,MAAM,CAAC;IACnB;;;;OAIG;IACH,MAAM,EAAE,OAAO,CAAC;CACjB,CAAC;AAEF,eAAO,MAAM,QAAQ,EAAE,EAAE,CAAC,KAAK,CAwO9B,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@buoy-gg/core",
3
- "version": "3.0.2",
3
+ "version": "4.0.1",
4
4
  "description": "Floating dev tools launcher and AppHost",
5
5
  "main": "lib/commonjs/index.js",
6
6
  "module": "lib/module/index.js",
@@ -22,10 +22,10 @@
22
22
  ],
23
23
  "sideEffects": false,
24
24
  "dependencies": {
25
- "@buoy-gg/shared-ui": "3.0.2",
26
- "@buoy-gg/floating-tools-react": "3.0.2",
27
- "@buoy-gg/license": "3.0.2",
28
- "@buoy-gg/floating-tools-core": "3.0.2"
25
+ "@buoy-gg/shared-ui": "4.0.1",
26
+ "@buoy-gg/floating-tools-core": "4.0.1",
27
+ "@buoy-gg/license": "4.0.1",
28
+ "@buoy-gg/floating-tools-react": "4.0.1"
29
29
  },
30
30
  "peerDependencies": {
31
31
  "react": "*",