@buoy-gg/core 7.0.39 → 7.0.41

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 (140) hide show
  1. package/README.md +10 -0
  2. package/bin/buoy.js +25 -31
  3. package/lib/commonjs/browserRegister.js +48 -0
  4. package/lib/commonjs/browserRegister.server.js +10 -0
  5. package/lib/commonjs/floatingMenu/AppHost.web.js +71 -59
  6. package/lib/commonjs/floatingMenu/BrowserToolRuntime.js +150 -0
  7. package/lib/commonjs/floatingMenu/DevToolsSettingsModal.js +10 -1107
  8. package/lib/commonjs/floatingMenu/DevToolsSettingsModal.shared.js +1114 -0
  9. package/lib/commonjs/floatingMenu/DevToolsSettingsModal.web.js +28 -1028
  10. package/lib/commonjs/floatingMenu/FloatingDevTools.js +7 -2
  11. package/lib/commonjs/floatingMenu/FloatingDevTools.web.js +54 -40
  12. package/lib/commonjs/floatingMenu/MinimizedToolsStack.web.js +8 -2
  13. package/lib/commonjs/floatingMenu/autoDiscoverPresets.js +10 -0
  14. package/lib/commonjs/floatingMenu/autoExternalSync.js +9 -0
  15. package/lib/commonjs/floatingMenu/dial/DialDevTools.web.js +86 -12
  16. package/lib/commonjs/floatingMenu/dial/DialIcon.js +4 -2
  17. package/lib/commonjs/floatingMenu/settingsBus.js +6 -17
  18. package/lib/commonjs/floatingMenu/useDesktopSyncStatus.web.js +14 -0
  19. package/lib/commonjs/index.web.js +92 -1
  20. package/lib/commonjs/reactDevtoolsTypes.js +1 -0
  21. package/lib/commonjs/utils/autoDiscoverPresets.web.js +5 -178
  22. package/lib/commonjs/utils/createWebTool.js +20 -0
  23. package/lib/commonjs/utils/createWebTools.js +30 -0
  24. package/lib/commonjs/version.js +1 -1
  25. package/lib/module/browserRegister.js +44 -0
  26. package/lib/module/browserRegister.server.js +6 -0
  27. package/lib/module/floatingMenu/AppHost.web.js +71 -59
  28. package/lib/module/floatingMenu/BrowserToolRuntime.js +146 -0
  29. package/lib/module/floatingMenu/DevToolsSettingsModal.js +1 -1109
  30. package/lib/module/floatingMenu/DevToolsSettingsModal.shared.js +1110 -0
  31. package/lib/module/floatingMenu/DevToolsSettingsModal.web.js +32 -1043
  32. package/lib/module/floatingMenu/FloatingDevTools.js +7 -2
  33. package/lib/module/floatingMenu/FloatingDevTools.web.js +55 -42
  34. package/lib/module/floatingMenu/MinimizedToolsStack.web.js +8 -2
  35. package/lib/module/floatingMenu/autoDiscoverPresets.js +10 -0
  36. package/lib/module/floatingMenu/autoExternalSync.js +9 -0
  37. package/lib/module/floatingMenu/dial/DialDevTools.web.js +87 -14
  38. package/lib/module/floatingMenu/dial/DialIcon.js +4 -2
  39. package/lib/module/floatingMenu/settingsBus.js +1 -17
  40. package/lib/module/floatingMenu/useDesktopSyncStatus.web.js +10 -0
  41. package/lib/module/index.web.js +8 -1
  42. package/lib/module/reactDevtoolsTypes.js +1 -0
  43. package/lib/module/utils/autoDiscoverPresets.web.js +5 -180
  44. package/lib/module/utils/createWebTool.js +17 -0
  45. package/lib/module/utils/createWebTools.js +25 -0
  46. package/lib/module/version.js +1 -1
  47. package/lib/typescript/commonjs/browserRegister.d.ts +5 -0
  48. package/lib/typescript/commonjs/browserRegister.d.ts.map +1 -0
  49. package/lib/typescript/commonjs/browserRegister.server.d.ts +5 -0
  50. package/lib/typescript/commonjs/browserRegister.server.d.ts.map +1 -0
  51. package/lib/typescript/commonjs/floatingMenu/AppHost.web.d.ts +3 -3
  52. package/lib/typescript/commonjs/floatingMenu/AppHost.web.d.ts.map +1 -1
  53. package/lib/typescript/commonjs/floatingMenu/BrowserToolRuntime.d.ts +14 -0
  54. package/lib/typescript/commonjs/floatingMenu/BrowserToolRuntime.d.ts.map +1 -0
  55. package/lib/typescript/commonjs/floatingMenu/DevToolsSettingsModal.d.ts +2 -67
  56. package/lib/typescript/commonjs/floatingMenu/DevToolsSettingsModal.d.ts.map +1 -1
  57. package/lib/typescript/commonjs/floatingMenu/DevToolsSettingsModal.shared.d.ts +71 -0
  58. package/lib/typescript/commonjs/floatingMenu/DevToolsSettingsModal.shared.d.ts.map +1 -0
  59. package/lib/typescript/commonjs/floatingMenu/DevToolsSettingsModal.web.d.ts +3 -16
  60. package/lib/typescript/commonjs/floatingMenu/DevToolsSettingsModal.web.d.ts.map +1 -1
  61. package/lib/typescript/commonjs/floatingMenu/FloatingDevTools.d.ts.map +1 -1
  62. package/lib/typescript/commonjs/floatingMenu/FloatingDevTools.web.d.ts +12 -6
  63. package/lib/typescript/commonjs/floatingMenu/FloatingDevTools.web.d.ts.map +1 -1
  64. package/lib/typescript/commonjs/floatingMenu/MinimizedToolsStack.web.d.ts.map +1 -1
  65. package/lib/typescript/commonjs/floatingMenu/autoDiscoverPresets.d.ts.map +1 -1
  66. package/lib/typescript/commonjs/floatingMenu/autoExternalSync.d.ts.map +1 -1
  67. package/lib/typescript/commonjs/floatingMenu/defaultConfig.d.ts +1 -1
  68. package/lib/typescript/commonjs/floatingMenu/defaultConfig.d.ts.map +1 -1
  69. package/lib/typescript/commonjs/floatingMenu/dial/DialDevTools.web.d.ts.map +1 -1
  70. package/lib/typescript/commonjs/floatingMenu/dial/DialIcon.d.ts.map +1 -1
  71. package/lib/typescript/commonjs/floatingMenu/settingsBus.d.ts +1 -9
  72. package/lib/typescript/commonjs/floatingMenu/settingsBus.d.ts.map +1 -1
  73. package/lib/typescript/commonjs/floatingMenu/useDesktopSyncStatus.web.d.ts +3 -0
  74. package/lib/typescript/commonjs/floatingMenu/useDesktopSyncStatus.web.d.ts.map +1 -0
  75. package/lib/typescript/commonjs/index.web.d.ts +6 -0
  76. package/lib/typescript/commonjs/index.web.d.ts.map +1 -1
  77. package/lib/typescript/commonjs/reactDevtoolsTypes.d.ts +8 -0
  78. package/lib/typescript/commonjs/reactDevtoolsTypes.d.ts.map +1 -0
  79. package/lib/typescript/commonjs/utils/autoDiscoverPresets.web.d.ts +3 -40
  80. package/lib/typescript/commonjs/utils/autoDiscoverPresets.web.d.ts.map +1 -1
  81. package/lib/typescript/commonjs/utils/createWebTool.d.ts +6 -0
  82. package/lib/typescript/commonjs/utils/createWebTool.d.ts.map +1 -0
  83. package/lib/typescript/commonjs/utils/createWebTools.d.ts +4 -0
  84. package/lib/typescript/commonjs/utils/createWebTools.d.ts.map +1 -0
  85. package/lib/typescript/commonjs/version.d.ts +1 -1
  86. package/lib/typescript/module/browserRegister.d.ts +5 -0
  87. package/lib/typescript/module/browserRegister.d.ts.map +1 -0
  88. package/lib/typescript/module/browserRegister.server.d.ts +5 -0
  89. package/lib/typescript/module/browserRegister.server.d.ts.map +1 -0
  90. package/lib/typescript/module/floatingMenu/AppHost.web.d.ts +3 -3
  91. package/lib/typescript/module/floatingMenu/AppHost.web.d.ts.map +1 -1
  92. package/lib/typescript/module/floatingMenu/BrowserToolRuntime.d.ts +14 -0
  93. package/lib/typescript/module/floatingMenu/BrowserToolRuntime.d.ts.map +1 -0
  94. package/lib/typescript/module/floatingMenu/DevToolsSettingsModal.d.ts +2 -67
  95. package/lib/typescript/module/floatingMenu/DevToolsSettingsModal.d.ts.map +1 -1
  96. package/lib/typescript/module/floatingMenu/DevToolsSettingsModal.shared.d.ts +71 -0
  97. package/lib/typescript/module/floatingMenu/DevToolsSettingsModal.shared.d.ts.map +1 -0
  98. package/lib/typescript/module/floatingMenu/DevToolsSettingsModal.web.d.ts +3 -16
  99. package/lib/typescript/module/floatingMenu/DevToolsSettingsModal.web.d.ts.map +1 -1
  100. package/lib/typescript/module/floatingMenu/FloatingDevTools.d.ts.map +1 -1
  101. package/lib/typescript/module/floatingMenu/FloatingDevTools.web.d.ts +12 -6
  102. package/lib/typescript/module/floatingMenu/FloatingDevTools.web.d.ts.map +1 -1
  103. package/lib/typescript/module/floatingMenu/MinimizedToolsStack.web.d.ts.map +1 -1
  104. package/lib/typescript/module/floatingMenu/autoDiscoverPresets.d.ts.map +1 -1
  105. package/lib/typescript/module/floatingMenu/autoExternalSync.d.ts.map +1 -1
  106. package/lib/typescript/module/floatingMenu/defaultConfig.d.ts +1 -1
  107. package/lib/typescript/module/floatingMenu/defaultConfig.d.ts.map +1 -1
  108. package/lib/typescript/module/floatingMenu/dial/DialDevTools.web.d.ts.map +1 -1
  109. package/lib/typescript/module/floatingMenu/dial/DialIcon.d.ts.map +1 -1
  110. package/lib/typescript/module/floatingMenu/settingsBus.d.ts +1 -9
  111. package/lib/typescript/module/floatingMenu/settingsBus.d.ts.map +1 -1
  112. package/lib/typescript/module/floatingMenu/useDesktopSyncStatus.web.d.ts +3 -0
  113. package/lib/typescript/module/floatingMenu/useDesktopSyncStatus.web.d.ts.map +1 -0
  114. package/lib/typescript/module/index.web.d.ts +6 -0
  115. package/lib/typescript/module/index.web.d.ts.map +1 -1
  116. package/lib/typescript/module/reactDevtoolsTypes.d.ts +8 -0
  117. package/lib/typescript/module/reactDevtoolsTypes.d.ts.map +1 -0
  118. package/lib/typescript/module/utils/autoDiscoverPresets.web.d.ts +3 -40
  119. package/lib/typescript/module/utils/autoDiscoverPresets.web.d.ts.map +1 -1
  120. package/lib/typescript/module/utils/createWebTool.d.ts +6 -0
  121. package/lib/typescript/module/utils/createWebTool.d.ts.map +1 -0
  122. package/lib/typescript/module/utils/createWebTools.d.ts +4 -0
  123. package/lib/typescript/module/utils/createWebTools.d.ts.map +1 -0
  124. package/lib/typescript/module/version.d.ts +1 -1
  125. package/lib/web/chunks/chunk-5NZOQR6Q.mjs +2 -0
  126. package/lib/web/chunks/chunk-CGDSLLZF.mjs +2 -0
  127. package/lib/web/chunks/chunk-DCJDUSNR.mjs +2 -0
  128. package/lib/web/chunks/chunk-IDSHFS6G.mjs +2 -0
  129. package/lib/web/chunks/chunk-JOAMJGCS.mjs +2 -0
  130. package/lib/web/chunks/chunk-KYKZ2N52.mjs +2 -0
  131. package/lib/web/chunks/chunk-NGM7JGGS.mjs +2 -0
  132. package/lib/web/chunks/chunk-QZDVCMCT.mjs +2 -0
  133. package/lib/web/chunks/chunk-R7RGRTY5.mjs +2 -0
  134. package/lib/web/chunks/chunk-Z3XWDDIO.mjs +2 -0
  135. package/lib/web/chunks/chunk-ZTGQ6TTY.mjs +2 -0
  136. package/lib/web/index.mjs +11 -0
  137. package/lib/web/register-server.mjs +2 -0
  138. package/lib/web/register.mjs +2 -0
  139. package/lib/web/toolkit.mjs +2 -0
  140. package/package.json +50 -12
@@ -8,188 +8,15 @@ exports.autoDiscoverWithCustom = autoDiscoverWithCustom;
8
8
  exports.defaultToolPresets = void 0;
9
9
  exports.getEnabledTools = getEnabledTools;
10
10
  exports.getToolsBySlot = getToolsBySlot;
11
- var _floatingToolsCore = require("@buoy-gg/floating-tools-core");
12
- var _jsxRuntime = require("react/jsx-runtime");
13
- /**
14
- * Auto-discovery utility for React DOM Web.
15
- *
16
- * Uses Vite's import.meta.glob to discover installed @buoy-gg/* packages
17
- * at build time. This provides Metro-like auto-discovery behavior for web.
18
- *
19
- * How it works:
20
- * 1. import.meta.glob scans node_modules at build time
21
- * 2. Only packages that are actually installed are included
22
- * 3. Missing packages don't cause errors (like Metro's try-catch)
23
- * 4. Custom tools can override discovered ones by ID
24
- *
25
- * @platform React DOM Web (Vite, CRA, Next.js, Electron)
26
- */
27
-
28
- /**
29
- * Dashed-square glyph for debug-borders (no BIF brand icon exists for it
30
- * yet). Plain SVG so it renders identically everywhere — emoji icons are
31
- * banned here: WKWebView (Capacitor/Tauri) renders them as tofu boxes.
32
- */function DebugBordersGlyph({
33
- size
34
- }) {
35
- return /*#__PURE__*/(0, _jsxRuntime.jsxs)("svg", {
36
- width: size,
37
- height: size,
38
- viewBox: "0 0 24 24",
39
- "aria-hidden": "true",
40
- children: [/*#__PURE__*/(0, _jsxRuntime.jsx)("rect", {
41
- x: "3",
42
- y: "3",
43
- width: "18",
44
- height: "18",
45
- rx: "2",
46
- fill: "none",
47
- stroke: "#10b981",
48
- strokeWidth: "2",
49
- strokeDasharray: "4 3"
50
- }), /*#__PURE__*/(0, _jsxRuntime.jsx)("rect", {
51
- x: "8",
52
- y: "8",
53
- width: "8",
54
- height: "8",
55
- rx: "1",
56
- fill: "#10b98155"
57
- })]
58
- });
59
- }
60
-
61
- // =============================
62
- // Default Tool Presets (Fallback)
63
- // =============================
64
-
65
- /**
66
- * Default tool presets for when packages don't export web presets yet.
67
- * These will be used until each @buoy-gg/* package exports its own preset.
68
- * Icons are the BIF brand icon components (same artwork as native) —
69
- * never emoji strings (tofu in WKWebView).
70
- */
71
- const defaultToolPresets = exports.defaultToolPresets = [{
72
- id: 'env',
73
- name: 'ENV',
74
- description: 'Environment variables debugger',
75
- slot: 'both',
76
- icon: size => /*#__PURE__*/(0, _jsxRuntime.jsx)(_floatingToolsCore.EnvIcon, {
77
- size: size
78
- }),
79
- color: '#4AFF9F'
80
- }, {
81
- id: 'storage',
82
- name: 'STORAGE',
83
- description: 'AsyncStorage browser',
84
- slot: 'both',
85
- icon: size => /*#__PURE__*/(0, _jsxRuntime.jsx)(_floatingToolsCore.StorageIcon, {
86
- size: size
87
- }),
88
- color: '#BA68C8'
89
- }, {
90
- id: 'network',
91
- name: 'NET',
92
- description: 'Network request logger',
93
- slot: 'both',
94
- icon: size => /*#__PURE__*/(0, _jsxRuntime.jsx)(_floatingToolsCore.NetworkIcon, {
95
- size: size
96
- }),
97
- color: '#4AFF9F'
98
- }, {
99
- id: 'query',
100
- name: 'QUERY',
101
- description: 'React Query inspector',
102
- slot: 'both',
103
- icon: size => /*#__PURE__*/(0, _jsxRuntime.jsx)(_floatingToolsCore.QueryIcon, {
104
- size: size
105
- }),
106
- color: '#FF4154'
107
- }, {
108
- id: 'route-events',
109
- name: 'ROUTES',
110
- description: 'Route tracking & navigation inspector',
111
- slot: 'both',
112
- icon: size => /*#__PURE__*/(0, _jsxRuntime.jsx)(_floatingToolsCore.RoutesIcon, {
113
- size: size
114
- }),
115
- color: '#FF9F1C'
116
- }, {
117
- id: 'highlight-updates',
118
- name: 'RENDERS',
119
- description: 'View component render tracking',
120
- slot: 'dial',
121
- icon: size => /*#__PURE__*/(0, _jsxRuntime.jsx)(_floatingToolsCore.RendersIcon, {
122
- size: size
123
- }),
124
- color: '#10b981'
125
- }, {
126
- id: 'debug-borders',
127
- name: 'DEBUG BORDERS',
128
- description: 'Component layout borders',
129
- slot: 'dial',
130
- icon: size => /*#__PURE__*/(0, _jsxRuntime.jsx)(DebugBordersGlyph, {
131
- size: size
132
- }),
133
- color: '#10b981'
134
- }];
135
-
136
- // =============================
137
- // Auto-Discovery Functions
138
- // =============================
11
+ /** Browser tools are registered through FloatingDevTools.apps. */
12
+ const defaultToolPresets = exports.defaultToolPresets = [];
139
13
 
140
- /**
141
- * Auto-discover installed @buoy-gg/* tool packages.
142
- *
143
- * Uses Vite's import.meta.glob to find packages at build time.
144
- * Only installed packages are included (no errors for missing ones).
145
- *
146
- * Note: Until packages export web presets, this returns default presets.
147
- *
148
- * @returns Array of discovered tool configurations
149
- */
14
+ /** @deprecated Pass explicitly imported presets through FloatingDevTools.apps. */
150
15
  function autoDiscoverWebPresets() {
151
- // TODO: When @buoy-gg/* packages export web presets, use import.meta.glob:
152
- //
153
- // const modules = import.meta.glob(
154
- // '/node_modules/@buoy-gg/*/dist/preset.{js,mjs}',
155
- // { eager: true, import: 'default' }
156
- // );
157
- //
158
- // const presets: WebToolConfig[] = [];
159
- // for (const [path, preset] of Object.entries(modules)) {
160
- // if (preset && typeof preset === 'object' && 'id' in preset) {
161
- // presets.push(preset as WebToolConfig);
162
- // }
163
- // }
164
- // return presets;
165
-
166
- // For now, return default presets
167
- return [...defaultToolPresets];
16
+ return [];
168
17
  }
169
-
170
- /**
171
- * Merge custom tools with auto-discovered ones.
172
- *
173
- * Custom tools take precedence - if a custom tool has the same ID as
174
- * a discovered tool, the custom one is used (same behavior as mobile).
175
- *
176
- * @param customTools - Custom tools to merge (optional)
177
- * @returns Merged array with custom tools taking precedence
178
- */
179
18
  function autoDiscoverWithCustom(customTools = []) {
180
- const discovered = autoDiscoverWebPresets();
181
- if (customTools.length === 0) {
182
- return discovered;
183
- }
184
-
185
- // Create set of custom tool IDs for quick lookup
186
- const customIds = new Set(customTools.map(t => t.id));
187
-
188
- // Filter out discovered tools that have custom overrides
189
- const filteredDiscovered = discovered.filter(t => !customIds.has(t.id));
190
-
191
- // Custom tools first, then remaining discovered
192
- return [...customTools, ...filteredDiscovered];
19
+ return [...new Map(customTools.map(tool => [tool.id, tool])).values()];
193
20
  }
194
21
 
195
22
  /**
@@ -0,0 +1,20 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.createWebTool = createWebTool;
7
+ var _react = require("react");
8
+ /** Adapt a shared tool preset to the browser menu's icon renderer. */
9
+
10
+ function createWebTool(preset) {
11
+ const icon = preset.icon;
12
+ return {
13
+ ...preset,
14
+ icon: typeof icon === "function" ? size => /*#__PURE__*/(0, _react.createElement)(icon, {
15
+ size,
16
+ slot: preset.slot ?? "both",
17
+ color: preset.color
18
+ }) : () => icon
19
+ };
20
+ }
@@ -0,0 +1,30 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.createWebTools = createWebTools;
7
+ var _sharedUi = _interopRequireWildcard(require("@buoy-gg/shared-ui"));
8
+ var shared = _sharedUi;
9
+ var _createWebTool = require("./createWebTool.js");
10
+ var _DevToolsVisibilityContext = require("../floatingMenu/DevToolsVisibilityContext.js");
11
+ var license = _interopRequireWildcard(require("@buoy-gg/license"));
12
+ var dataViewer = _interopRequireWildcard(require("@buoy-gg/shared-ui/dataViewer"));
13
+ function _interopRequireWildcard(e, t) { if ("function" == typeof WeakMap) var r = new WeakMap(), n = new WeakMap(); return (_interopRequireWildcard = function (e, t) { if (!t && e && e.__esModule) return e; var o, i, f = { __proto__: null, default: e }; if (null === e || "object" != typeof e && "function" != typeof e) return f; if (o = t ? n : r) { if (o.has(e)) return o.get(e); o.set(e, f); } for (const t in e) "default" !== t && {}.hasOwnProperty.call(e, t) && ((i = (o = Object.defineProperty) && Object.getOwnPropertyDescriptor(e, t)) && (i.get || i.set) ? o(f, t, i) : f[t] = e[t]); return f; })(e, t); }
14
+ function createWebTools(modules) {
15
+ (0, _sharedUi.registerToolModules)({
16
+ core: {
17
+ useDevToolsVisibility: _DevToolsVisibilityContext.useDevToolsVisibility
18
+ },
19
+ license,
20
+ 'shared-ui': shared,
21
+ 'shared-ui/dataViewer': dataViewer,
22
+ ...modules
23
+ });
24
+ const seen = new Set();
25
+ return Object.values(modules).flatMap(module => Object.entries(module).flatMap(([name, value]) => {
26
+ if (!name.endsWith('Preset') || !value || typeof value.id !== 'string' || !value.component || seen.has(value.id)) return [];
27
+ seen.add(value.id);
28
+ return [(0, _createWebTool.createWebTool)(value)];
29
+ }));
30
+ }
@@ -15,4 +15,4 @@ exports.SDK_VERSION = void 0;
15
15
  * Drift is prevented by a test that fails when this disagrees with
16
16
  * package.json, so a version bump that forgets this file cannot ship.
17
17
  */
18
- const SDK_VERSION = exports.SDK_VERSION = "7.0.39";
18
+ const SDK_VERSION = exports.SDK_VERSION = "7.0.41";
@@ -0,0 +1,44 @@
1
+ "use strict";
2
+
3
+ import * as ReactDevtools from 'react-devtools-core';
4
+
5
+ /** Call before importing React DOM so render and element inspectors can see app roots. */
6
+ export function registerBrowserDevTools(options = {}) {
7
+ if (typeof window === 'undefined' || typeof document === 'undefined') return false;
8
+ const dev = typeof __DEV__ !== 'undefined' ? __DEV__ : process.env.NODE_ENV !== 'production';
9
+ if (!dev && !options.enableInRelease) return false;
10
+ const target = window;
11
+ const previous = target.__REACT_DEVTOOLS_GLOBAL_HOOK__;
12
+ // Fast Refresh installs a minimal hook before the application's entry runs.
13
+ // Preserve its callbacks and renderer IDs when installing the full backend.
14
+ const refreshHook = previous && previous.supportsFiber && !previous.getFiberRoots && !previous.sub && Object.getOwnPropertyDescriptor(target, '__REACT_DEVTOOLS_GLOBAL_HOOK__')?.configurable;
15
+ if (refreshHook) delete target.__REACT_DEVTOOLS_GLOBAL_HOOK__;
16
+ if (!target.__REACT_DEVTOOLS_GLOBAL_HOOK__) {
17
+ const initialize = ReactDevtools.initialize ?? ReactDevtools.default?.initialize;
18
+ initialize({
19
+ appendComponentStack: false,
20
+ breakOnConsoleErrors: false,
21
+ showInlineWarningsAndErrors: false,
22
+ hideConsoleLogsInStrictMode: false
23
+ });
24
+ if (refreshHook) {
25
+ const hook = target.__REACT_DEVTOOLS_GLOBAL_HOOK__;
26
+ const inject = hook.inject;
27
+ const ids = new Map();
28
+ hook.inject = renderer => {
29
+ const id = inject(renderer);
30
+ ids.set(id, previous.inject(renderer));
31
+ return id;
32
+ };
33
+ for (const name of ['onScheduleFiberRoot', 'onCommitFiberRoot', 'onCommitFiberUnmount']) {
34
+ const current = hook[name];
35
+ hook[name] = (id, ...args) => {
36
+ previous[name]?.(ids.get(id) ?? id, ...args);
37
+ return current?.(id, ...args);
38
+ };
39
+ }
40
+ }
41
+ }
42
+ return Boolean(target.__REACT_DEVTOOLS_GLOBAL_HOOK__);
43
+ }
44
+ registerBrowserDevTools();
@@ -0,0 +1,6 @@
1
+ "use strict";
2
+
3
+ /** The server entry does not load the browser's React DevTools backend. */
4
+ export function registerBrowserDevTools(_options = {}) {
5
+ return false;
6
+ }
@@ -1,36 +1,20 @@
1
1
  "use strict";
2
2
 
3
3
  /**
4
- * AppHost.web.tsx — DOM port of AppHost.tsx (React Native).
5
- *
6
- * Same state machine (shared `AppHostLogic.ts`), same `@react_buoy_open_apps`
7
- * persistence key + JSON shape (`{id, minimized}[]`, 500ms debounce), same
8
- * launch modes and z-order model (base 9000 + stack index).
9
- *
10
- * Intentional deviations from the native file (all logged):
11
- * - No `MinimizedToolsContext`/`MinimizedToolsStack` second store: the
12
- * minimized dock derives directly from `openApps` (`minimized === true`),
13
- * the same simplification the Flutter port made deliberately
14
- * (packages-flutter/buoy_core — see FLUTTER_TOOLS_PORT/MASTER_PLAN.md).
15
- * `@react_buoy_minimized_tools` is therefore not written on web.
16
- * - `BackHandler` (Android hardware back) → `Escape` keydown closes the
17
- * top-most open tool.
18
- * - No `setExpandableWindowControls` / global settings bridge — the web
19
- * settings modal has no global-settings tab yet.
20
- * - `minimizeTargetPosition` is computed from the dock layout below instead
21
- * of `MinimizedToolsContext.getNextIconPosition()`.
22
- *
23
- * @platform React DOM Web
4
+ * Browser tool host using the shared open-app state machine and persistence.
5
+ * Minimized tools derive from openApps. Escape closes the top visible tool;
6
+ * the minimized stack remains attached to the floating menu.
24
7
  */
25
8
  import { persistentStorage } from "@buoy-gg/shared-ui";
26
9
  import { createContext, useCallback, useContext, useEffect, useMemo, useRef, useState } from "react";
27
10
  import { resolveOpenAppsState } from "./AppHostLogic.js";
28
11
  import { renderAppIcon } from "./AppIcon";
12
+ import { ToolModalShell } from "./ToolHost.js";
13
+ import { useDevToolsSettings } from "./DevToolsSettingsModal.shared.js";
29
14
  import { getBubbleAnchorPosition } from "./floatingTools.web.js";
30
15
  import { jsx as _jsx, Fragment as _Fragment } from "react/jsx-runtime";
31
16
  const AppHostContext = /*#__PURE__*/createContext(null);
32
17
  const STORAGE_KEY_OPEN_APPS = "@react_buoy_open_apps";
33
- const PERSISTENCE_DELAY = 500;
34
18
 
35
19
  // Minimized dock geometry — mirrors MinimizedToolsContext.tsx constants.
36
20
  const ICON_SIZE = 44;
@@ -52,9 +36,11 @@ export const AppHostProvider = ({
52
36
  }) => {
53
37
  const [openApps, setOpenApps] = useState([]);
54
38
  const [isRestored, setIsRestored] = useState(false);
55
- const persistenceTimeoutRef = useRef(null);
56
39
  const installedAppsRef = useRef([]);
57
40
  const pendingRestoreRef = useRef(null);
41
+ const restoredRef = useRef(false);
42
+ const storageReadRef = useRef(false);
43
+ const registeredRef = useRef(false);
58
44
  const open = useCallback(def => {
59
45
  let resolvedId = "";
60
46
  setOpenApps(current => {
@@ -68,8 +54,8 @@ export const AppHostProvider = ({
68
54
  return resolvedId;
69
55
  }, []);
70
56
  const tryRestorePending = useCallback(() => {
71
- if (isRestored) return;
72
- if (!installedAppsRef.current.length) return;
57
+ if (restoredRef.current || !storageReadRef.current || !registeredRef.current) return;
58
+ restoredRef.current = true;
73
59
  const pendingApps = pendingRestoreRef.current;
74
60
  if (!pendingApps || pendingApps.length === 0) {
75
61
  setIsRestored(true);
@@ -92,8 +78,9 @@ export const AppHostProvider = ({
92
78
  title: appDef.name,
93
79
  component: appDef.component,
94
80
  props: appDef.props,
81
+ modal: appDef.modal,
95
82
  launchMode: appDef.launchMode || "self-modal",
96
- singleton: appDef.singleton,
83
+ singleton: appDef.singleton ?? true,
97
84
  icon: resolvedIcon,
98
85
  color: appDef.color,
99
86
  minimized
@@ -101,14 +88,16 @@ export const AppHostProvider = ({
101
88
  }
102
89
  });
103
90
  setIsRestored(true);
104
- }, [isRestored, open]);
91
+ }, [open]);
105
92
 
106
93
  // Restore open apps on mount. Handles both the legacy `string[]` shape and
107
94
  // the current `{id, minimized}[]` shape — same tolerance as native.
108
95
  useEffect(() => {
96
+ let cancelled = false;
109
97
  const restoreOpenApps = async () => {
110
98
  try {
111
99
  const saved = await persistentStorage.getItem(STORAGE_KEY_OPEN_APPS);
100
+ if (cancelled) return;
112
101
  if (saved) {
113
102
  const parsed = JSON.parse(saved);
114
103
  let savedApps;
@@ -119,46 +108,40 @@ export const AppHostProvider = ({
119
108
  minimized: false
120
109
  }));
121
110
  } else {
122
- savedApps = parsed;
111
+ savedApps = parsed.filter(item => typeof item === "object" && item !== null && typeof item.id === "string");
123
112
  }
124
113
  if (savedApps.length) {
125
114
  pendingRestoreRef.current = savedApps;
126
- tryRestorePending();
127
- return;
128
115
  }
129
116
  }
130
117
  }
131
118
  } catch {
132
119
  // Failed to restore open apps - continue with fresh state
133
120
  }
134
- setIsRestored(true);
121
+ if (cancelled) return;
122
+ storageReadRef.current = true;
123
+ tryRestorePending();
124
+ };
125
+ void restoreOpenApps();
126
+ return () => {
127
+ cancelled = true;
135
128
  };
136
- restoreOpenApps();
137
129
  }, [tryRestorePending]);
138
130
 
139
- // Save open apps with debounce
131
+ // Save discrete open/minimize/close changes before a reload can lose them.
140
132
  useEffect(() => {
141
133
  if (!isRestored) return;
142
- if (persistenceTimeoutRef.current) {
143
- clearTimeout(persistenceTimeoutRef.current);
144
- }
145
- persistenceTimeoutRef.current = setTimeout(() => {
146
- const appStates = openApps.map(app => ({
147
- id: app.id,
148
- minimized: app.minimized ?? false
149
- }));
150
- persistentStorage.setItem(STORAGE_KEY_OPEN_APPS, JSON.stringify(appStates));
151
- }, PERSISTENCE_DELAY);
152
- return () => {
153
- if (persistenceTimeoutRef.current) {
154
- clearTimeout(persistenceTimeoutRef.current);
155
- }
156
- };
134
+ const appStates = openApps.map(app => ({
135
+ id: app.id,
136
+ minimized: app.minimized ?? false
137
+ }));
138
+ void persistentStorage.setItem(STORAGE_KEY_OPEN_APPS, JSON.stringify(appStates));
157
139
  }, [openApps, isRestored]);
158
140
 
159
141
  // Store reference to installed apps for restoration
160
142
  const registerApps = useCallback(apps => {
161
143
  installedAppsRef.current = apps;
144
+ registeredRef.current = true;
162
145
  tryRestorePending();
163
146
  }, [tryRestorePending]);
164
147
  const close = useCallback(instanceId => {
@@ -169,16 +152,18 @@ export const AppHostProvider = ({
169
152
  });
170
153
  }, []);
171
154
  const closeAll = useCallback(() => setOpenApps([]), []);
172
- const minimize = useCallback(instanceId => {
155
+ const minimize = useCallback((instanceId, restoreState) => {
173
156
  setOpenApps(s => s.map(app => app.instanceId === instanceId ? {
174
157
  ...app,
175
- minimized: true
158
+ minimized: true,
159
+ restoreState
176
160
  } : app));
177
161
  }, []);
178
- const restore = useCallback(instanceId => {
162
+ const restore = useCallback((instanceId, restoreState) => {
179
163
  setOpenApps(s => s.map(app => app.instanceId === instanceId ? {
180
164
  ...app,
181
- minimized: false
165
+ minimized: false,
166
+ restoreState: restoreState ?? app.restoreState
182
167
  } : app));
183
168
  }, []);
184
169
  const isMinimized = useCallback(instanceId => {
@@ -193,11 +178,13 @@ export const AppHostProvider = ({
193
178
  if (!hasVisibleApps) return;
194
179
  const handler = event => {
195
180
  if (event.key !== "Escape") return;
196
- close();
181
+ if (event.defaultPrevented) return;
182
+ const top = [...openApps].reverse().find(app => app.launchMode !== "toggle-only" && !app.minimized);
183
+ if (top) close(top.instanceId);
197
184
  };
198
185
  window.addEventListener("keydown", handler);
199
186
  return () => window.removeEventListener("keydown", handler);
200
- }, [hasVisibleApps, close]);
187
+ }, [hasVisibleApps, close, openApps]);
201
188
  const value = useMemo(() => ({
202
189
  openApps,
203
190
  isAnyOpen: hasVisibleApps,
@@ -267,20 +254,41 @@ const AppRenderer = ({
267
254
  zIndex,
268
255
  onClose,
269
256
  onMinimize,
270
- minimizeTargetPosition
257
+ minimizeTargetPosition,
258
+ enableSharedModalDimensions
271
259
  }) => {
272
260
  const Comp = app.component;
273
261
  const isVisible = !app.minimized;
262
+ const bodyProps = {
263
+ ...(app.props ?? {}),
264
+ ...(enableSharedModalDimensions ? {
265
+ enableSharedModalDimensions: true
266
+ } : {})
267
+ };
268
+ if (app.modal && (!app.launchMode || app.launchMode === "self-modal")) {
269
+ return /*#__PURE__*/_jsx(ToolModalShell, {
270
+ app: app,
271
+ config: app.modal,
272
+ visible: isVisible,
273
+ zIndex: zIndex,
274
+ onClose: onClose,
275
+ onMinimize: onMinimize,
276
+ initialModalState: app.restoreState,
277
+ enableSharedModalDimensions: enableSharedModalDimensions,
278
+ bodyProps: bodyProps
279
+ });
280
+ }
274
281
  if (app.launchMode === "self-modal") {
275
282
  return /*#__PURE__*/_jsx(Comp, {
276
- ...(app.props ?? {}),
283
+ ...bodyProps,
277
284
  visible: isVisible,
278
285
  onClose: onClose,
279
286
  onRequestClose: onClose,
280
287
  onMinimize: onMinimize,
281
288
  minimizeTargetPosition: minimizeTargetPosition,
282
289
  instanceId: app.instanceId,
283
- zIndex: zIndex
290
+ zIndex: zIndex,
291
+ initialModalState: app.restoreState
284
292
  });
285
293
  }
286
294
  if (app.launchMode === "inline") {
@@ -296,7 +304,7 @@ const AppRenderer = ({
296
304
  pointerEvents: "none"
297
305
  },
298
306
  children: /*#__PURE__*/_jsx(Comp, {
299
- ...(app.props ?? {}),
307
+ ...bodyProps,
300
308
  onClose: onClose,
301
309
  onMinimize: onMinimize,
302
310
  minimizeTargetPosition: minimizeTargetPosition,
@@ -315,7 +323,7 @@ const AppRenderer = ({
315
323
  children: /*#__PURE__*/_jsx("div", {
316
324
  style: cardStyle,
317
325
  children: /*#__PURE__*/_jsx(Comp, {
318
- ...(app.props ?? {}),
326
+ ...bodyProps,
319
327
  onClose: onClose,
320
328
  onMinimize: onMinimize,
321
329
  minimizeTargetPosition: minimizeTargetPosition,
@@ -337,6 +345,9 @@ export const AppOverlay = () => {
337
345
  close,
338
346
  minimize
339
347
  } = useAppHost();
348
+ const {
349
+ settings
350
+ } = useDevToolsSettings();
340
351
  const renderableApps = openApps.filter(app => app.launchMode !== "toggle-only");
341
352
  if (renderableApps.length === 0) return null;
342
353
  const minimizedCount = renderableApps.filter(app => app.minimized).length;
@@ -349,7 +360,8 @@ export const AppOverlay = () => {
349
360
  app: app,
350
361
  zIndex: BASE_ZINDEX + index,
351
362
  onClose: () => close(app.instanceId),
352
- onMinimize: () => minimize(app.instanceId),
363
+ onMinimize: state => minimize(app.instanceId, state),
364
+ enableSharedModalDimensions: settings.globalSettings?.enableSharedModalDimensions === true,
353
365
  minimizeTargetPosition: minimizeTarget
354
366
  }, app.instanceId))
355
367
  });