@buoy-gg/core 7.0.17 → 7.0.18

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 (55) hide show
  1. package/lib/commonjs/floatingMenu/AppHost.js +5 -3
  2. package/lib/commonjs/floatingMenu/AppHost.web.js +6 -1
  3. package/lib/commonjs/floatingMenu/AppIcon.js +91 -0
  4. package/lib/commonjs/floatingMenu/FloatingDevTools.js +15 -9
  5. package/lib/commonjs/floatingMenu/FloatingMenu.js +12 -6
  6. package/lib/commonjs/floatingMenu/ToolHost.js +13 -3
  7. package/lib/commonjs/floatingMenu/autoExternalSync.js +12 -2
  8. package/lib/commonjs/floatingMenu/dial/DialDevTools.js +13 -6
  9. package/lib/commonjs/toolkit.js +201 -44
  10. package/lib/commonjs/toolkitComponents.js +241 -0
  11. package/lib/module/floatingMenu/AppHost.js +5 -3
  12. package/lib/module/floatingMenu/AppHost.web.js +6 -1
  13. package/lib/module/floatingMenu/AppIcon.js +84 -0
  14. package/lib/module/floatingMenu/FloatingDevTools.js +15 -9
  15. package/lib/module/floatingMenu/FloatingMenu.js +12 -6
  16. package/lib/module/floatingMenu/ToolHost.js +14 -4
  17. package/lib/module/floatingMenu/autoExternalSync.js +12 -2
  18. package/lib/module/floatingMenu/dial/DialDevTools.js +13 -6
  19. package/lib/module/toolkit.js +33 -16
  20. package/lib/module/toolkitComponents.js +230 -0
  21. package/lib/typescript/commonjs/floatingMenu/AppHost.d.ts.map +1 -1
  22. package/lib/typescript/commonjs/floatingMenu/AppHost.web.d.ts.map +1 -1
  23. package/lib/typescript/commonjs/floatingMenu/AppIcon.d.ts +30 -0
  24. package/lib/typescript/commonjs/floatingMenu/AppIcon.d.ts.map +1 -0
  25. package/lib/typescript/commonjs/floatingMenu/FloatingDevTools.d.ts.map +1 -1
  26. package/lib/typescript/commonjs/floatingMenu/FloatingMenu.d.ts.map +1 -1
  27. package/lib/typescript/commonjs/floatingMenu/ToolHost.d.ts +5 -0
  28. package/lib/typescript/commonjs/floatingMenu/ToolHost.d.ts.map +1 -1
  29. package/lib/typescript/commonjs/floatingMenu/autoExternalSync.d.ts +8 -1
  30. package/lib/typescript/commonjs/floatingMenu/autoExternalSync.d.ts.map +1 -1
  31. package/lib/typescript/commonjs/floatingMenu/dial/DialDevTools.d.ts.map +1 -1
  32. package/lib/typescript/commonjs/floatingMenu/types.d.ts +32 -1
  33. package/lib/typescript/commonjs/floatingMenu/types.d.ts.map +1 -1
  34. package/lib/typescript/commonjs/toolkit.d.ts +19 -10
  35. package/lib/typescript/commonjs/toolkit.d.ts.map +1 -1
  36. package/lib/typescript/commonjs/toolkitComponents.d.ts +61 -0
  37. package/lib/typescript/commonjs/toolkitComponents.d.ts.map +1 -0
  38. package/lib/typescript/module/floatingMenu/AppHost.d.ts.map +1 -1
  39. package/lib/typescript/module/floatingMenu/AppHost.web.d.ts.map +1 -1
  40. package/lib/typescript/module/floatingMenu/AppIcon.d.ts +30 -0
  41. package/lib/typescript/module/floatingMenu/AppIcon.d.ts.map +1 -0
  42. package/lib/typescript/module/floatingMenu/FloatingDevTools.d.ts.map +1 -1
  43. package/lib/typescript/module/floatingMenu/FloatingMenu.d.ts.map +1 -1
  44. package/lib/typescript/module/floatingMenu/ToolHost.d.ts +5 -0
  45. package/lib/typescript/module/floatingMenu/ToolHost.d.ts.map +1 -1
  46. package/lib/typescript/module/floatingMenu/autoExternalSync.d.ts +8 -1
  47. package/lib/typescript/module/floatingMenu/autoExternalSync.d.ts.map +1 -1
  48. package/lib/typescript/module/floatingMenu/dial/DialDevTools.d.ts.map +1 -1
  49. package/lib/typescript/module/floatingMenu/types.d.ts +32 -1
  50. package/lib/typescript/module/floatingMenu/types.d.ts.map +1 -1
  51. package/lib/typescript/module/toolkit.d.ts +19 -10
  52. package/lib/typescript/module/toolkit.d.ts.map +1 -1
  53. package/lib/typescript/module/toolkitComponents.d.ts +61 -0
  54. package/lib/typescript/module/toolkitComponents.d.ts.map +1 -0
  55. package/package.json +19 -5
@@ -8,6 +8,7 @@ var _sharedUi = require("@buoy-gg/shared-ui");
8
8
  var _react = _interopRequireWildcard(require("react"));
9
9
  var _reactNative = require("react-native");
10
10
  var _AppHostLogic = require("./AppHostLogic.js");
11
+ var _AppIcon = require("./AppIcon.js");
11
12
  var _MinimizedToolsContext = require("./MinimizedToolsContext.js");
12
13
  var _ToolHost = require("./ToolHost.js");
13
14
  var _DevToolsSettingsModal = require("./DevToolsSettingsModal");
@@ -69,10 +70,11 @@ const AppHostProvider = ({
69
70
  }) => {
70
71
  const appDef = installedAppsRef.current.find(app => app.id === appId);
71
72
  if (appDef) {
72
- const resolvedIcon = typeof appDef.icon === "function" ? appDef.icon({
73
+ const resolvedIcon = (0, _AppIcon.renderAppIcon)(appDef.icon, {
73
74
  slot: "dial",
74
- size: 20
75
- }) : appDef.icon;
75
+ size: 20,
76
+ color: appDef.color
77
+ });
76
78
  open({
77
79
  id: appDef.id,
78
80
  title: appDef.name,
@@ -7,6 +7,7 @@ exports.useAppHost = exports.AppOverlay = exports.AppHostProvider = void 0;
7
7
  var _sharedUi = require("@buoy-gg/shared-ui");
8
8
  var _react = require("react");
9
9
  var _AppHostLogic = require("./AppHostLogic.js");
10
+ var _AppIcon = require("./AppIcon.js");
10
11
  var _floatingToolsWeb = require("./floatingTools.web.js");
11
12
  var _jsxRuntime = require("react/jsx-runtime");
12
13
  /**
@@ -86,7 +87,11 @@ const AppHostProvider = ({
86
87
  }) => {
87
88
  const appDef = installedAppsRef.current.find(app => app.id === appId);
88
89
  if (appDef && appDef.component) {
89
- const resolvedIcon = typeof appDef.icon === "function" ? appDef.icon(20) : appDef.icon;
90
+ const resolvedIcon = (0, _AppIcon.renderAppIcon)(appDef.icon, {
91
+ slot: "dial",
92
+ size: 20,
93
+ color: appDef.color
94
+ });
90
95
  open({
91
96
  id: appDef.id,
92
97
  title: appDef.name,
@@ -0,0 +1,91 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.AppTextIcon = AppTextIcon;
7
+ exports.renderAppIcon = renderAppIcon;
8
+ var _react = _interopRequireDefault(require("react"));
9
+ var _reactNative = require("react-native");
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
+ * Icon resolution for `InstalledApp.icon`.
15
+ *
16
+ * Custom tools may provide an icon three ways:
17
+ * - a component `({ slot, size }) => node` (dynamic, hook-capable)
18
+ * - a pre-built ReactNode
19
+ * - a PLAIN STRING — "AUTH", "KIT", "🗑️" — rendered as an auto-fitting text
20
+ * icon so simple tools never need an icon library.
21
+ *
22
+ * Every menu surface (dial, row, minimize stack, restore path) resolves icons
23
+ * through `renderAppIcon` so all three forms behave identically.
24
+ */
25
+
26
+ /** Visible glyphs, not UTF-16 units — "🗑️" is one glyph, not three. */
27
+ function glyphCount(label) {
28
+ // Strip variation selectors + zero-width joiners before counting.
29
+ const stripped = label.replace(/[\uFE00-\uFE0F\u200D]/g, "");
30
+ return Math.max(Array.from(stripped).length, 1);
31
+ }
32
+ function AppTextIcon({
33
+ label,
34
+ size,
35
+ color = _sharedUi.toolTheme.colors.text
36
+ }) {
37
+ const chars = glyphCount(label);
38
+ // Short labels stay square; longer ones ("AUTH") get a wider box — the
39
+ // dial/row layouts have breathing room and the label reads better than a
40
+ // squashed square would. The computed font size is what fits the box on
41
+ // web; adjustsFontSizeToFit covers native font-metric drift.
42
+ const maxWidth = chars <= 2 ? size : size * 1.6;
43
+ const fontSize = Math.max(7, Math.min(size * (chars === 1 ? 0.7 : 0.62), maxWidth / (0.62 * chars)));
44
+ return /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.View, {
45
+ style: {
46
+ minWidth: size,
47
+ maxWidth,
48
+ height: size,
49
+ alignItems: "center",
50
+ justifyContent: "center"
51
+ },
52
+ children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.Text, {
53
+ numberOfLines: 1,
54
+ adjustsFontSizeToFit: true,
55
+ minimumFontScale: 0.5,
56
+ style: {
57
+ color,
58
+ fontSize,
59
+ fontWeight: "800",
60
+ letterSpacing: 0.5,
61
+ textAlign: "center"
62
+ },
63
+ children: label
64
+ })
65
+ });
66
+ }
67
+
68
+ /**
69
+ * Resolve any `InstalledApp.icon` form to a renderable node. Function icons
70
+ * become elements (createElement — hooks keep working); strings become
71
+ * auto-fitting text icons; nodes pass through.
72
+ */
73
+ function renderAppIcon(icon, ctx) {
74
+ if (icon == null) return icon;
75
+ if (typeof icon === "function") {
76
+ return /*#__PURE__*/_react.default.createElement(icon, {
77
+ slot: ctx.slot,
78
+ size: ctx.size,
79
+ state: ctx.state,
80
+ actions: ctx.actions
81
+ });
82
+ }
83
+ if (typeof icon === "string" || typeof icon === "number") {
84
+ return /*#__PURE__*/(0, _jsxRuntime.jsx)(AppTextIcon, {
85
+ label: String(icon),
86
+ size: ctx.size,
87
+ color: ctx.color
88
+ });
89
+ }
90
+ return icon;
91
+ }
@@ -9,6 +9,7 @@ var _reactNative = require("react-native");
9
9
  var _AppHost = require("./AppHost");
10
10
  var _FloatingMenu = require("./FloatingMenu.js");
11
11
  var _autoDiscoverPresets = require("./autoDiscoverPresets.js");
12
+ var _AppIcon = require("./AppIcon.js");
12
13
  var _DevToolsVisibilityContext = require("./DevToolsVisibilityContext.js");
13
14
  var _optionalRequire = require("./optionalRequire.js");
14
15
  var _sharedUi = require("@buoy-gg/shared-ui");
@@ -230,6 +231,11 @@ const FloatingDevTools = ({
230
231
  // identity (and re-ran discovery) on every parent render.
231
232
  const finalApps = (0, _react.useMemo)(() => userApps ? (0, _autoDiscoverPresets.autoDiscoverPresetsWithCustom)(userApps) : (0, _autoDiscoverPresets.autoDiscoverPresets)(), [userApps]);
232
233
 
234
+ // Custom tools that declared a sync adapter — registered with the broker as
235
+ // `custom:<id>` by AutoExternalSync. Memoized so the sync tools map (keyed
236
+ // by identity) doesn't rebuild every render.
237
+ const syncApps = (0, _react.useMemo)(() => finalApps.filter(app => app.sync), [finalApps]);
238
+
233
239
  // Check if debug-borders is installed and auto-render the overlay
234
240
  const DebugBordersOverlay = (0, _react.useMemo)(() => {
235
241
  try {
@@ -366,13 +372,11 @@ const FloatingDevTools = ({
366
372
  const getToolIcon = (0, _react.useCallback)(id => {
367
373
  const tool = finalApps.find(app => app.id === id);
368
374
  if (!tool) return null;
369
- if (typeof tool.icon === "function") {
370
- return tool.icon({
371
- slot: "dial",
372
- size: 20
373
- });
374
- }
375
- return tool.icon;
375
+ return (0, _AppIcon.renderAppIcon)(tool.icon, {
376
+ slot: "dial",
377
+ size: 20,
378
+ color: tool.color
379
+ });
376
380
  }, [finalApps]);
377
381
 
378
382
  // Gate: Free tier only works in development mode
@@ -394,7 +398,8 @@ const FloatingDevTools = ({
394
398
  options: typeof externalSync === "object" ? externalSync : undefined,
395
399
  requiredEnvVars: requiredEnvVars,
396
400
  isPro: isLicensed,
397
- licenseKey: licenseKey
401
+ licenseKey: licenseKey,
402
+ customApps: syncApps
398
403
  })]
399
404
  });
400
405
  }
@@ -434,7 +439,8 @@ const FloatingDevTools = ({
434
439
  options: typeof externalSync === "object" ? externalSync : undefined,
435
440
  requiredEnvVars: requiredEnvVars,
436
441
  isPro: isLicensed,
437
- licenseKey: licenseKey
442
+ licenseKey: licenseKey,
443
+ customApps: syncApps
438
444
  })]
439
445
  })
440
446
  })
@@ -8,6 +8,7 @@ var _react = _interopRequireWildcard(require("react"));
8
8
  var _reactNative = require("react-native");
9
9
  var _sharedUi = require("@buoy-gg/shared-ui");
10
10
  var _floatingTools = require("./floatingTools");
11
+ var _AppIcon = require("./AppIcon.js");
11
12
  var _DialDevTools = require("./dial/DialDevTools");
12
13
  var _DevToolsSettingsModal = require("./DevToolsSettingsModal");
13
14
  var _AppHost = require("./AppHost");
@@ -172,12 +173,13 @@ const FloatingMenu = ({
172
173
 
173
174
  // Only open modal if not a toggle-only tool
174
175
  if (app.launchMode !== "toggle-only") {
175
- // Resolve the icon for minimize stack display
176
- // IMPORTANT: Use React.createElement for function components to preserve hooks
177
- const resolvedIcon = typeof app.icon === "function" ? /*#__PURE__*/_react.default.createElement(app.icon, {
176
+ // Resolve the icon for minimize stack display (createElement keeps
177
+ // function-icon hooks working; strings become text icons).
178
+ const resolvedIcon = (0, _AppIcon.renderAppIcon)(app.icon, {
178
179
  slot: "dial",
179
- size: 20
180
- }) : app.icon;
180
+ size: 20,
181
+ color: app.color
182
+ });
181
183
  open({
182
184
  id: app.id,
183
185
  title: app.name,
@@ -285,7 +287,11 @@ const FloatingMenu = ({
285
287
  actions: mergedActions
286
288
  });
287
289
  }
288
- return app.icon;
290
+ return (0, _AppIcon.renderAppIcon)(app.icon, {
291
+ slot: "row",
292
+ size: 16,
293
+ color: app.color
294
+ });
289
295
  })()
290
296
  }, `row-${app.id}`))]
291
297
  })
@@ -168,6 +168,13 @@ function ToolModalShell({
168
168
  const subtitle = headerOverride?.subtitle ?? config.subtitle;
169
169
  const onBack = headerOverride?.onBack;
170
170
  const actions = headerOverride?.actions ?? config.headerActions;
171
+ const searchable = headerOverride?.searchable ?? config.searchable;
172
+
173
+ // A screen that hides search while it's open would strand the input with
174
+ // no way to dismiss it — close it on entry instead.
175
+ (0, _react.useEffect)(() => {
176
+ if (!searchable && isSearchActive) clearSearch();
177
+ }, [searchable, isSearchActive, clearSearch]);
171
178
 
172
179
  // Tool-scoped persistence via the custom namespace unless the user has the
173
180
  // shared-dimensions global setting on (all tools share one window size).
@@ -184,7 +191,8 @@ function ToolModalShell({
184
191
  title: title,
185
192
  subtitle: subtitle
186
193
  }), /*#__PURE__*/(0, _jsxRuntime.jsxs)(_sharedUi.ModalHeader.Actions, {
187
- children: [!isSearchActive && actions, config.searchable && !isSearchActive && /*#__PURE__*/(0, _jsxRuntime.jsx)(_sharedUi.HeaderSearchButton, {
194
+ children: [!isSearchActive && actions, searchable && !isSearchActive && /*#__PURE__*/(0, _jsxRuntime.jsx)(_sharedUi.HeaderSearchButton, {
195
+ testID: `tool-search-${app.id}`,
188
196
  onPress: () => setIsSearchActive(true)
189
197
  })]
190
198
  })]
@@ -212,8 +220,10 @@ function ToolModalShell({
212
220
  styles: {},
213
221
  children: /*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNative.View, {
214
222
  style: styles.bodyRoot,
215
- children: [/*#__PURE__*/(0, _jsxRuntime.jsx)(Body, {
216
- ...bodyProps
223
+ children: [/*#__PURE__*/(0, _jsxRuntime.jsx)(_sharedUi.TickProvider, {
224
+ children: /*#__PURE__*/(0, _jsxRuntime.jsx)(Body, {
225
+ ...bodyProps
226
+ })
217
227
  }), toast && /*#__PURE__*/(0, _jsxRuntime.jsx)(ToastView, {
218
228
  message: toast.message,
219
229
  type: toast.type,
@@ -180,7 +180,8 @@ function AutoExternalSync({
180
180
  options,
181
181
  requiredEnvVars,
182
182
  isPro,
183
- licenseKey
183
+ licenseKey,
184
+ customApps
184
185
  }) {
185
186
  const {
186
187
  useExternalSyncSocket,
@@ -293,8 +294,17 @@ function AutoExternalSync({
293
294
  if (assetsModule?.assetsSyncAdapter) {
294
295
  map.assets = assetsModule.assetsSyncAdapter;
295
296
  }
297
+
298
+ // Third-party custom tools that declared InstalledApp.sync. Namespaced so
299
+ // a custom tool named "network" can't shadow the first-party adapter on
300
+ // the broker, in MCP call_action, or in desktop watch state.
301
+ for (const app of customApps ?? []) {
302
+ if (app?.sync) {
303
+ map[`custom:${app.id}`] = app.sync;
304
+ }
305
+ }
296
306
  return map;
297
- }, [queryAdapter, requiredEnvVars]);
307
+ }, [queryAdapter, requiredEnvVars, customApps]);
298
308
  useExternalSync({
299
309
  tools,
300
310
  socket,
@@ -13,6 +13,7 @@ var _DialPagination = require("./DialPagination.js");
13
13
  var _dialUsageStore = require("./dialUsageStore.js");
14
14
  var _DevToolsSettingsModal = require("../DevToolsSettingsModal");
15
15
  var _license = require("@buoy-gg/license");
16
+ var _AppIcon = require("../AppIcon.js");
16
17
  var _AppHost = require("../AppHost");
17
18
  var _OnboardingTooltip = require("./OnboardingTooltip");
18
19
  var _floatingToolsCore = require("@buoy-gg/floating-tools-core");
@@ -175,9 +176,14 @@ const DialDevTools = ({
175
176
  map.set(app.id, {
176
177
  id: app.id,
177
178
  name: app.name,
178
- // Pass both the pre-rendered icon (for non-function icons) and the
179
- // component (for dynamic rendering).
180
- icon: typeof app.icon === "function" ? null : app.icon,
179
+ // Pass both the pre-rendered icon (for non-function icons; strings
180
+ // resolve to auto-fitting text icons) and the component (for dynamic
181
+ // rendering).
182
+ icon: typeof app.icon === "function" ? null : (0, _AppIcon.renderAppIcon)(app.icon, {
183
+ slot: "dial",
184
+ size: 20,
185
+ color: app.color
186
+ }),
181
187
  // Cast to the expected type - the signature is compatible at runtime.
182
188
  iconComponent: typeof app.icon === "function" ? app.icon : undefined,
183
189
  color: app.color ?? _sharedUi.buoyColors.primary,
@@ -191,10 +197,11 @@ const DialDevTools = ({
191
197
 
192
198
  // Only open modal if not a toggle-only tool.
193
199
  if (app.launchMode !== "toggle-only") {
194
- const resolvedIcon = typeof app.icon === "function" ? app.icon({
200
+ const resolvedIcon = (0, _AppIcon.renderAppIcon)(app.icon, {
195
201
  slot: "dial",
196
- size: 20
197
- }) : app.icon;
202
+ size: 20,
203
+ color: app.color
204
+ });
198
205
  open({
199
206
  id: app.id,
200
207
  title: app.name,