@buoy-gg/core 1.7.2

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 (132) hide show
  1. package/README.md +43 -0
  2. package/lib/commonjs/floatingMenu/AppHost.js +410 -0
  3. package/lib/commonjs/floatingMenu/AppHostLogic.js +44 -0
  4. package/lib/commonjs/floatingMenu/DefaultConfigContext.js +45 -0
  5. package/lib/commonjs/floatingMenu/DevToolsSettingsModal.js +2274 -0
  6. package/lib/commonjs/floatingMenu/DevToolsVisibilityContext.js +49 -0
  7. package/lib/commonjs/floatingMenu/DraggableHeader.js +114 -0
  8. package/lib/commonjs/floatingMenu/FloatingDevTools.js +254 -0
  9. package/lib/commonjs/floatingMenu/FloatingMenu.js +364 -0
  10. package/lib/commonjs/floatingMenu/MinimizedToolsContext.js +247 -0
  11. package/lib/commonjs/floatingMenu/MinimizedToolsStack.js +206 -0
  12. package/lib/commonjs/floatingMenu/ToggleStateManager.js +36 -0
  13. package/lib/commonjs/floatingMenu/autoDiscoverPresets.js +241 -0
  14. package/lib/commonjs/floatingMenu/defaultConfig.js +160 -0
  15. package/lib/commonjs/floatingMenu/dial/DialDevTools.js +835 -0
  16. package/lib/commonjs/floatingMenu/dial/DialIcon.js +246 -0
  17. package/lib/commonjs/floatingMenu/dial/OnboardingTooltip.js +249 -0
  18. package/lib/commonjs/floatingMenu/dial/onboardingConstants.js +70 -0
  19. package/lib/commonjs/floatingMenu/floatingTools.js +771 -0
  20. package/lib/commonjs/floatingMenu/settingsBus.js +23 -0
  21. package/lib/commonjs/floatingMenu/types.js +5 -0
  22. package/lib/commonjs/index.js +240 -0
  23. package/lib/commonjs/package.json +1 -0
  24. package/lib/module/floatingMenu/AppHost.js +402 -0
  25. package/lib/module/floatingMenu/AppHostLogic.js +39 -0
  26. package/lib/module/floatingMenu/DefaultConfigContext.js +39 -0
  27. package/lib/module/floatingMenu/DevToolsSettingsModal.js +2273 -0
  28. package/lib/module/floatingMenu/DevToolsVisibilityContext.js +44 -0
  29. package/lib/module/floatingMenu/DraggableHeader.js +110 -0
  30. package/lib/module/floatingMenu/FloatingDevTools.js +249 -0
  31. package/lib/module/floatingMenu/FloatingMenu.js +358 -0
  32. package/lib/module/floatingMenu/MinimizedToolsContext.js +239 -0
  33. package/lib/module/floatingMenu/MinimizedToolsStack.js +202 -0
  34. package/lib/module/floatingMenu/ToggleStateManager.js +32 -0
  35. package/lib/module/floatingMenu/autoDiscoverPresets.js +236 -0
  36. package/lib/module/floatingMenu/defaultConfig.js +151 -0
  37. package/lib/module/floatingMenu/dial/DialDevTools.js +829 -0
  38. package/lib/module/floatingMenu/dial/DialIcon.js +241 -0
  39. package/lib/module/floatingMenu/dial/OnboardingTooltip.js +244 -0
  40. package/lib/module/floatingMenu/dial/onboardingConstants.js +64 -0
  41. package/lib/module/floatingMenu/floatingTools.js +767 -0
  42. package/lib/module/floatingMenu/settingsBus.js +19 -0
  43. package/lib/module/floatingMenu/types.js +3 -0
  44. package/lib/module/index.js +29 -0
  45. package/lib/module/package.json +1 -0
  46. package/lib/typescript/commonjs/floatingMenu/AppHost.d.ts +39 -0
  47. package/lib/typescript/commonjs/floatingMenu/AppHost.d.ts.map +1 -0
  48. package/lib/typescript/commonjs/floatingMenu/AppHostLogic.d.ts +37 -0
  49. package/lib/typescript/commonjs/floatingMenu/AppHostLogic.d.ts.map +1 -0
  50. package/lib/typescript/commonjs/floatingMenu/DefaultConfigContext.d.ts +27 -0
  51. package/lib/typescript/commonjs/floatingMenu/DefaultConfigContext.d.ts.map +1 -0
  52. package/lib/typescript/commonjs/floatingMenu/DevToolsSettingsModal.d.ts +57 -0
  53. package/lib/typescript/commonjs/floatingMenu/DevToolsSettingsModal.d.ts.map +1 -0
  54. package/lib/typescript/commonjs/floatingMenu/DevToolsVisibilityContext.d.ts +25 -0
  55. package/lib/typescript/commonjs/floatingMenu/DevToolsVisibilityContext.d.ts.map +1 -0
  56. package/lib/typescript/commonjs/floatingMenu/DraggableHeader.d.ts +30 -0
  57. package/lib/typescript/commonjs/floatingMenu/DraggableHeader.d.ts.map +1 -0
  58. package/lib/typescript/commonjs/floatingMenu/FloatingDevTools.d.ts +226 -0
  59. package/lib/typescript/commonjs/floatingMenu/FloatingDevTools.d.ts.map +1 -0
  60. package/lib/typescript/commonjs/floatingMenu/FloatingMenu.d.ts +39 -0
  61. package/lib/typescript/commonjs/floatingMenu/FloatingMenu.d.ts.map +1 -0
  62. package/lib/typescript/commonjs/floatingMenu/MinimizedToolsContext.d.ts +95 -0
  63. package/lib/typescript/commonjs/floatingMenu/MinimizedToolsContext.d.ts.map +1 -0
  64. package/lib/typescript/commonjs/floatingMenu/MinimizedToolsStack.d.ts +10 -0
  65. package/lib/typescript/commonjs/floatingMenu/MinimizedToolsStack.d.ts.map +1 -0
  66. package/lib/typescript/commonjs/floatingMenu/ToggleStateManager.d.ts +21 -0
  67. package/lib/typescript/commonjs/floatingMenu/ToggleStateManager.d.ts.map +1 -0
  68. package/lib/typescript/commonjs/floatingMenu/autoDiscoverPresets.d.ts +75 -0
  69. package/lib/typescript/commonjs/floatingMenu/autoDiscoverPresets.d.ts.map +1 -0
  70. package/lib/typescript/commonjs/floatingMenu/defaultConfig.d.ts +120 -0
  71. package/lib/typescript/commonjs/floatingMenu/defaultConfig.d.ts.map +1 -0
  72. package/lib/typescript/commonjs/floatingMenu/dial/DialDevTools.d.ts +35 -0
  73. package/lib/typescript/commonjs/floatingMenu/dial/DialDevTools.d.ts.map +1 -0
  74. package/lib/typescript/commonjs/floatingMenu/dial/DialIcon.d.ts +14 -0
  75. package/lib/typescript/commonjs/floatingMenu/dial/DialIcon.d.ts.map +1 -0
  76. package/lib/typescript/commonjs/floatingMenu/dial/OnboardingTooltip.d.ts +12 -0
  77. package/lib/typescript/commonjs/floatingMenu/dial/OnboardingTooltip.d.ts.map +1 -0
  78. package/lib/typescript/commonjs/floatingMenu/dial/onboardingConstants.d.ts +30 -0
  79. package/lib/typescript/commonjs/floatingMenu/dial/onboardingConstants.d.ts.map +1 -0
  80. package/lib/typescript/commonjs/floatingMenu/floatingTools.d.ts +56 -0
  81. package/lib/typescript/commonjs/floatingMenu/floatingTools.d.ts.map +1 -0
  82. package/lib/typescript/commonjs/floatingMenu/settingsBus.d.ts +10 -0
  83. package/lib/typescript/commonjs/floatingMenu/settingsBus.d.ts.map +1 -0
  84. package/lib/typescript/commonjs/floatingMenu/types.d.ts +56 -0
  85. package/lib/typescript/commonjs/floatingMenu/types.d.ts.map +1 -0
  86. package/lib/typescript/commonjs/index.d.ts +18 -0
  87. package/lib/typescript/commonjs/index.d.ts.map +1 -0
  88. package/lib/typescript/commonjs/package.json +1 -0
  89. package/lib/typescript/module/floatingMenu/AppHost.d.ts +39 -0
  90. package/lib/typescript/module/floatingMenu/AppHost.d.ts.map +1 -0
  91. package/lib/typescript/module/floatingMenu/AppHostLogic.d.ts +37 -0
  92. package/lib/typescript/module/floatingMenu/AppHostLogic.d.ts.map +1 -0
  93. package/lib/typescript/module/floatingMenu/DefaultConfigContext.d.ts +27 -0
  94. package/lib/typescript/module/floatingMenu/DefaultConfigContext.d.ts.map +1 -0
  95. package/lib/typescript/module/floatingMenu/DevToolsSettingsModal.d.ts +57 -0
  96. package/lib/typescript/module/floatingMenu/DevToolsSettingsModal.d.ts.map +1 -0
  97. package/lib/typescript/module/floatingMenu/DevToolsVisibilityContext.d.ts +25 -0
  98. package/lib/typescript/module/floatingMenu/DevToolsVisibilityContext.d.ts.map +1 -0
  99. package/lib/typescript/module/floatingMenu/DraggableHeader.d.ts +30 -0
  100. package/lib/typescript/module/floatingMenu/DraggableHeader.d.ts.map +1 -0
  101. package/lib/typescript/module/floatingMenu/FloatingDevTools.d.ts +226 -0
  102. package/lib/typescript/module/floatingMenu/FloatingDevTools.d.ts.map +1 -0
  103. package/lib/typescript/module/floatingMenu/FloatingMenu.d.ts +39 -0
  104. package/lib/typescript/module/floatingMenu/FloatingMenu.d.ts.map +1 -0
  105. package/lib/typescript/module/floatingMenu/MinimizedToolsContext.d.ts +95 -0
  106. package/lib/typescript/module/floatingMenu/MinimizedToolsContext.d.ts.map +1 -0
  107. package/lib/typescript/module/floatingMenu/MinimizedToolsStack.d.ts +10 -0
  108. package/lib/typescript/module/floatingMenu/MinimizedToolsStack.d.ts.map +1 -0
  109. package/lib/typescript/module/floatingMenu/ToggleStateManager.d.ts +21 -0
  110. package/lib/typescript/module/floatingMenu/ToggleStateManager.d.ts.map +1 -0
  111. package/lib/typescript/module/floatingMenu/autoDiscoverPresets.d.ts +75 -0
  112. package/lib/typescript/module/floatingMenu/autoDiscoverPresets.d.ts.map +1 -0
  113. package/lib/typescript/module/floatingMenu/defaultConfig.d.ts +120 -0
  114. package/lib/typescript/module/floatingMenu/defaultConfig.d.ts.map +1 -0
  115. package/lib/typescript/module/floatingMenu/dial/DialDevTools.d.ts +35 -0
  116. package/lib/typescript/module/floatingMenu/dial/DialDevTools.d.ts.map +1 -0
  117. package/lib/typescript/module/floatingMenu/dial/DialIcon.d.ts +14 -0
  118. package/lib/typescript/module/floatingMenu/dial/DialIcon.d.ts.map +1 -0
  119. package/lib/typescript/module/floatingMenu/dial/OnboardingTooltip.d.ts +12 -0
  120. package/lib/typescript/module/floatingMenu/dial/OnboardingTooltip.d.ts.map +1 -0
  121. package/lib/typescript/module/floatingMenu/dial/onboardingConstants.d.ts +30 -0
  122. package/lib/typescript/module/floatingMenu/dial/onboardingConstants.d.ts.map +1 -0
  123. package/lib/typescript/module/floatingMenu/floatingTools.d.ts +56 -0
  124. package/lib/typescript/module/floatingMenu/floatingTools.d.ts.map +1 -0
  125. package/lib/typescript/module/floatingMenu/settingsBus.d.ts +10 -0
  126. package/lib/typescript/module/floatingMenu/settingsBus.d.ts.map +1 -0
  127. package/lib/typescript/module/floatingMenu/types.d.ts +56 -0
  128. package/lib/typescript/module/floatingMenu/types.d.ts.map +1 -0
  129. package/lib/typescript/module/index.d.ts +18 -0
  130. package/lib/typescript/module/index.d.ts.map +1 -0
  131. package/lib/typescript/module/package.json +1 -0
  132. package/package.json +79 -0
package/README.md ADDED
@@ -0,0 +1,43 @@
1
+ # @buoy/core
2
+
3
+ [![npm](https://img.shields.io/npm/v/@buoy%2Fcore)](https://www.npmjs.com/package/@buoy/core)
4
+
5
+
6
+ Floating dev tools launcher and host provider for React Native apps.
7
+
8
+ ## Install
9
+ ```bash
10
+ pnpm add @buoy/core @buoy/shared-ui
11
+ ```
12
+
13
+ ## Quick Start
14
+ ```tsx
15
+ import { AppHostProvider, FloatingMenu } from '@buoy/core';
16
+ import type { InstalledApp } from '@buoy/core';
17
+ import { EnvVarsModal } from '@buoy/env';
18
+
19
+ const APPS: InstalledApp[] = [
20
+ {
21
+ id: 'env',
22
+ name: 'Environment',
23
+ icon: '🛰️',
24
+ component: EnvVarsModal,
25
+ singleton: true,
26
+ },
27
+ ];
28
+
29
+ export function DevToolsHost() {
30
+ return (
31
+ <AppHostProvider>
32
+ <FloatingMenu apps={APPS} />
33
+ </AppHostProvider>
34
+ );
35
+ }
36
+ ```
37
+
38
+ ## Key Exports
39
+ - `AppHostProvider` – Context provider that manages installed dev tools.
40
+ - `FloatingMenu` – Cyberpunk-inspired floating entrypoint for tools.
41
+ - `AppOverlay` & `useAppHost()` – Programmatic APIs for opening tools.
42
+
43
+ The menu hosts any `InstalledApp` descriptor. Combine it with other `@buoy/*` packages for a full suite of debug panels.
@@ -0,0 +1,410 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.useAppHost = exports.AppOverlay = exports.AppHostProvider = void 0;
7
+ var _sharedUi = require("@buoy-gg/shared-ui");
8
+ var _react = _interopRequireWildcard(require("react"));
9
+ var _reactNative = require("react-native");
10
+ var _AppHostLogic = require("./AppHostLogic.js");
11
+ var _MinimizedToolsContext = require("./MinimizedToolsContext.js");
12
+ var _DevToolsSettingsModal = require("./DevToolsSettingsModal.js");
13
+ var _jsxRuntime = require("react/jsx-runtime");
14
+ 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); }
15
+ const AppHostContext = /*#__PURE__*/(0, _react.createContext)(null);
16
+ const STORAGE_KEY_OPEN_APPS = "@react_buoy_open_apps";
17
+ const PERSISTENCE_DELAY = 500;
18
+
19
+ // Type for persisted app state
20
+
21
+ /**
22
+ * Provides the floating dev tools application host. Tracks open tool instances, restores
23
+ * persisted state, and exposes imperative helpers used by `FloatingMenu` and friends.
24
+ */
25
+ const AppHostProvider = ({
26
+ children
27
+ }) => {
28
+ const [openApps, setOpenApps] = (0, _react.useState)([]);
29
+ const [isRestored, setIsRestored] = (0, _react.useState)(false);
30
+ const persistenceTimeoutRef = (0, _react.useRef)(null);
31
+ const installedAppsRef = (0, _react.useRef)([]);
32
+ const pendingRestoreRef = (0, _react.useRef)(null);
33
+ const {
34
+ restore: removeFromMinimizedStack
35
+ } = (0, _MinimizedToolsContext.useMinimizedTools)();
36
+ const open = (0, _react.useCallback)(def => {
37
+ let resolvedId = "";
38
+ setOpenApps(current => {
39
+ const {
40
+ apps,
41
+ instanceId,
42
+ wasMinimized
43
+ } = (0, _AppHostLogic.resolveOpenAppsState)(current, def, () => `${def.id}-${Date.now()}-${Math.random().toString(36).slice(2)}`);
44
+ resolvedId = instanceId;
45
+
46
+ // If the app was minimized, remove it from the minimized stack
47
+ // This needs to be done outside of setOpenApps to avoid nested state updates
48
+ if (wasMinimized) {
49
+ // Schedule the removal for after this state update completes
50
+ setTimeout(() => removeFromMinimizedStack(instanceId), 0);
51
+ }
52
+ return apps;
53
+ });
54
+ return resolvedId;
55
+ }, [removeFromMinimizedStack]);
56
+ const tryRestorePending = (0, _react.useCallback)(() => {
57
+ if (isRestored) return;
58
+ if (!installedAppsRef.current.length) return;
59
+ const pendingApps = pendingRestoreRef.current;
60
+ if (!pendingApps || pendingApps.length === 0) {
61
+ setIsRestored(true);
62
+ return;
63
+ }
64
+ pendingRestoreRef.current = null;
65
+ pendingApps.forEach(({
66
+ id: appId,
67
+ minimized
68
+ }) => {
69
+ const appDef = installedAppsRef.current.find(app => app.id === appId);
70
+ if (appDef) {
71
+ const resolvedIcon = typeof appDef.icon === "function" ? appDef.icon({
72
+ slot: "dial",
73
+ size: 20
74
+ }) : appDef.icon;
75
+ open({
76
+ id: appDef.id,
77
+ title: appDef.name,
78
+ component: appDef.component,
79
+ props: appDef.props,
80
+ launchMode: appDef.launchMode || "self-modal",
81
+ singleton: appDef.singleton,
82
+ icon: resolvedIcon,
83
+ color: appDef.color,
84
+ minimized: minimized // Preserve minimized state
85
+ });
86
+ }
87
+ });
88
+ setIsRestored(true);
89
+ }, [isRestored, open]);
90
+
91
+ // Restore open apps on mount
92
+ (0, _react.useEffect)(() => {
93
+ const restoreOpenApps = async () => {
94
+ try {
95
+ const saved = await (0, _sharedUi.safeGetItem)(STORAGE_KEY_OPEN_APPS);
96
+ if (saved) {
97
+ const parsed = JSON.parse(saved);
98
+ // Handle both old format (string[]) and new format (PersistedAppState[])
99
+ let savedApps;
100
+ if (Array.isArray(parsed) && parsed.length > 0) {
101
+ if (typeof parsed[0] === "string") {
102
+ // Old format: convert string[] to PersistedAppState[]
103
+ savedApps = parsed.map(id => ({
104
+ id,
105
+ minimized: false
106
+ }));
107
+ } else {
108
+ // New format: already PersistedAppState[]
109
+ savedApps = parsed;
110
+ }
111
+ if (savedApps.length) {
112
+ pendingRestoreRef.current = savedApps;
113
+ tryRestorePending();
114
+ return;
115
+ }
116
+ }
117
+ }
118
+ } catch (error) {
119
+ // Failed to restore open apps - continue with fresh state
120
+ }
121
+ setIsRestored(true);
122
+ };
123
+ restoreOpenApps();
124
+ }, [tryRestorePending]);
125
+
126
+ // Save open apps with debounce
127
+ (0, _react.useEffect)(() => {
128
+ if (!isRestored) return;
129
+
130
+ // Clear existing timeout
131
+ if (persistenceTimeoutRef.current) {
132
+ clearTimeout(persistenceTimeoutRef.current);
133
+ }
134
+
135
+ // Set new timeout to save
136
+ persistenceTimeoutRef.current = setTimeout(() => {
137
+ const appStates = openApps.map(app => ({
138
+ id: app.id,
139
+ minimized: app.minimized ?? false
140
+ }));
141
+ (0, _sharedUi.safeSetItem)(STORAGE_KEY_OPEN_APPS, JSON.stringify(appStates));
142
+ }, PERSISTENCE_DELAY);
143
+ return () => {
144
+ if (persistenceTimeoutRef.current) {
145
+ clearTimeout(persistenceTimeoutRef.current);
146
+ }
147
+ };
148
+ }, [openApps, isRestored]);
149
+
150
+ // Store reference to installed apps for restoration
151
+ const registerApps = (0, _react.useCallback)(apps => {
152
+ installedAppsRef.current = apps;
153
+ tryRestorePending();
154
+ }, [tryRestorePending]);
155
+ const close = (0, _react.useCallback)(instanceId => {
156
+ setOpenApps(s => {
157
+ if (!s.length) return s;
158
+ if (!instanceId) return s.slice(0, -1);
159
+ return s.filter(a => a.instanceId !== instanceId);
160
+ });
161
+ }, []);
162
+ const closeAll = (0, _react.useCallback)(() => setOpenApps([]), []);
163
+ const minimize = (0, _react.useCallback)(instanceId => {
164
+ setOpenApps(s => s.map(app => app.instanceId === instanceId ? {
165
+ ...app,
166
+ minimized: true
167
+ } : app));
168
+ }, []);
169
+ const restore = (0, _react.useCallback)((instanceId, restoreState) => {
170
+ setOpenApps(s => s.map(app => app.instanceId === instanceId ? {
171
+ ...app,
172
+ minimized: false,
173
+ restoreState
174
+ } : app));
175
+ }, []);
176
+ const isMinimized = (0, _react.useCallback)(instanceId => {
177
+ const app = openApps.find(a => a.instanceId === instanceId);
178
+ return app?.minimized ?? false;
179
+ }, [openApps]);
180
+ _react.default.useEffect(() => {
181
+ if (openApps.length === 0) return;
182
+ const handler = () => {
183
+ close();
184
+ return true;
185
+ };
186
+ const sub = _reactNative.BackHandler.addEventListener("hardwareBackPress", handler);
187
+ return () => sub.remove();
188
+ }, [openApps.length, close]);
189
+ const value = (0, _react.useMemo)(() => ({
190
+ openApps,
191
+ // Only count non-toggle-only and non-minimized tools as "open"
192
+ isAnyOpen: openApps.filter(app => app.launchMode !== "toggle-only" && !app.minimized).length > 0,
193
+ open,
194
+ close,
195
+ closeAll,
196
+ registerApps,
197
+ minimize,
198
+ restore,
199
+ isMinimized
200
+ }), [openApps, open, close, closeAll, registerApps, minimize, restore, isMinimized]);
201
+ return /*#__PURE__*/(0, _jsxRuntime.jsx)(AppHostContext.Provider, {
202
+ value: value,
203
+ children: children
204
+ });
205
+ };
206
+
207
+ /**
208
+ * Accessor hook for the dev tools app host. Components can open/close tools or inspect
209
+ * the active stack. Falls back to a no-op implementation when rendered outside the provider.
210
+ */
211
+ exports.AppHostProvider = AppHostProvider;
212
+ const useAppHost = () => {
213
+ const ctx = (0, _react.useContext)(AppHostContext);
214
+ // Return a default value if not in provider (for backwards compatibility)
215
+ if (!ctx) {
216
+ return {
217
+ openApps: [],
218
+ isAnyOpen: false,
219
+ open: () => "",
220
+ close: () => {},
221
+ closeAll: () => {},
222
+ minimize: () => {},
223
+ restore: (_instanceId, _restoreState) => {},
224
+ isMinimized: () => false
225
+ };
226
+ }
227
+ return ctx;
228
+ };
229
+
230
+ /**
231
+ * Renders a single app instance. Keeps component mounted even when minimized
232
+ * by passing visible={false} instead of unmounting.
233
+ *
234
+ * Supports multiple simultaneous modals - each gets its own z-index based on
235
+ * position in the open apps stack (later opened = higher z-index).
236
+ */
237
+ exports.useAppHost = useAppHost;
238
+ const AppRenderer = ({
239
+ app,
240
+ zIndex,
241
+ onClose,
242
+ onMinimize,
243
+ minimizeTargetPosition,
244
+ globalEnableSharedModalDimensions
245
+ }) => {
246
+ const Comp = app.component;
247
+ // All non-minimized apps are visible - supports multiple simultaneous modals
248
+ const isVisible = !app.minimized;
249
+
250
+ // Merge props with global settings override
251
+ // Priority: Global settings (if defined) > Tool prop > Default (false)
252
+ const mergedProps = {
253
+ ...(app.props ?? {}),
254
+ // Only override if globalEnableSharedModalDimensions is explicitly true
255
+ // (when the user turns it on in settings)
256
+ ...(globalEnableSharedModalDimensions === true ? {
257
+ enableSharedModalDimensions: true
258
+ } : {})
259
+ };
260
+ if (app.launchMode === "self-modal") {
261
+ return /*#__PURE__*/(0, _jsxRuntime.jsx)(Comp, {
262
+ ...mergedProps,
263
+ visible: isVisible,
264
+ onClose: onClose,
265
+ onRequestClose: onClose,
266
+ onMinimize: onMinimize,
267
+ minimizeTargetPosition: minimizeTargetPosition,
268
+ initialModalState: app.restoreState,
269
+ instanceId: app.instanceId,
270
+ zIndex: zIndex
271
+ });
272
+ }
273
+ if (app.launchMode === "inline") {
274
+ if (!isVisible) return null;
275
+ return /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.View, {
276
+ pointerEvents: "box-none",
277
+ style: [_reactNative.StyleSheet.absoluteFill, {
278
+ zIndex
279
+ }],
280
+ children: /*#__PURE__*/(0, _jsxRuntime.jsx)(Comp, {
281
+ ...mergedProps,
282
+ onClose: onClose,
283
+ onMinimize: onMinimize,
284
+ minimizeTargetPosition: minimizeTargetPosition,
285
+ initialModalState: app.restoreState,
286
+ instanceId: app.instanceId
287
+ })
288
+ });
289
+ }
290
+
291
+ // host-modal mode
292
+ return /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.Modal, {
293
+ visible: isVisible,
294
+ transparent: true,
295
+ animationType: "slide",
296
+ onRequestClose: onClose,
297
+ children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.View, {
298
+ style: styles.backdrop,
299
+ children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.View, {
300
+ style: styles.card,
301
+ children: /*#__PURE__*/(0, _jsxRuntime.jsx)(Comp, {
302
+ ...mergedProps,
303
+ onClose: onClose,
304
+ onMinimize: onMinimize,
305
+ minimizeTargetPosition: minimizeTargetPosition,
306
+ initialModalState: app.restoreState,
307
+ instanceId: app.instanceId
308
+ })
309
+ })
310
+ })
311
+ });
312
+ };
313
+
314
+ /**
315
+ * Renders all dev tool surfaces. Keeps minimized apps mounted but hidden
316
+ * so their state and listeners are preserved (similar to React Navigation screens).
317
+ *
318
+ * Supports multiple simultaneous modals - each modal gets a z-index based on
319
+ * its position in the stack (later opened modals appear on top).
320
+ */
321
+ const AppOverlay = () => {
322
+ const {
323
+ openApps,
324
+ close,
325
+ minimize
326
+ } = useAppHost();
327
+ const {
328
+ minimize: addToMinimizedStack,
329
+ getNextIconPosition,
330
+ minimizedTools
331
+ } = (0, _MinimizedToolsContext.useMinimizedTools)();
332
+ const {
333
+ settings
334
+ } = (0, _DevToolsSettingsModal.useDevToolsSettings)();
335
+
336
+ // Sync restored minimized apps to MinimizedToolsContext
337
+ // This handles apps that were restored from persistence with minimized=true
338
+ _react.default.useEffect(() => {
339
+ openApps.forEach(app => {
340
+ if (app.minimized && app.launchMode !== "toggle-only") {
341
+ // Check if this app is already in the minimized stack
342
+ const isInStack = minimizedTools.some(t => t.instanceId === app.instanceId);
343
+ if (!isInStack) {
344
+ // Add to minimized stack (restored from persistence)
345
+ addToMinimizedStack({
346
+ instanceId: app.instanceId,
347
+ id: app.id,
348
+ title: app.title || app.id,
349
+ icon: app.icon,
350
+ color: app.color
351
+ });
352
+ }
353
+ }
354
+ });
355
+ }, [openApps, minimizedTools, addToMinimizedStack]);
356
+
357
+ // Filter to renderable apps (exclude toggle-only)
358
+ const renderableApps = openApps.filter(app => app.launchMode !== "toggle-only");
359
+ if (renderableApps.length === 0) return null;
360
+
361
+ // Base z-index for modals - each subsequent modal gets +1
362
+ const BASE_ZINDEX = 9000;
363
+ return /*#__PURE__*/(0, _jsxRuntime.jsx)(_jsxRuntime.Fragment, {
364
+ children: renderableApps.map((app, index) => {
365
+ // z-index based on position - later in array = higher z-index (on top)
366
+ const zIndex = BASE_ZINDEX + index;
367
+ const minimizeTargetPosition = getNextIconPosition();
368
+ const handleMinimize = modalState => {
369
+ // IMPORTANT: Order matters here!
370
+ // 1. First mark the app as minimized in AppHost - this updates isAnyOpen
371
+ // so that pushToSide becomes false before the icon component mounts
372
+ minimize(app.instanceId);
373
+ // 2. Then add to the minimized stack - this triggers the icon to mount
374
+ // By now isAnyOpen is false, so the icon mounts with pushToSide=false
375
+ addToMinimizedStack({
376
+ instanceId: app.instanceId,
377
+ id: app.id,
378
+ title: app.title || app.id,
379
+ icon: app.icon,
380
+ color: app.color,
381
+ modalState: modalState
382
+ });
383
+ };
384
+ return /*#__PURE__*/(0, _jsxRuntime.jsx)(AppRenderer, {
385
+ app: app,
386
+ zIndex: zIndex,
387
+ onClose: () => close(app.instanceId),
388
+ onMinimize: handleMinimize,
389
+ minimizeTargetPosition: minimizeTargetPosition,
390
+ globalEnableSharedModalDimensions: settings.globalSettings?.enableSharedModalDimensions
391
+ }, app.instanceId);
392
+ })
393
+ });
394
+ };
395
+ exports.AppOverlay = AppOverlay;
396
+ const styles = _reactNative.StyleSheet.create({
397
+ backdrop: {
398
+ flex: 1,
399
+ backgroundColor: "rgba(0,0,0,0.28)",
400
+ alignItems: "center",
401
+ justifyContent: "center"
402
+ },
403
+ card: {
404
+ maxHeight: "90%",
405
+ width: "94%",
406
+ borderRadius: 12,
407
+ backgroundColor: "white",
408
+ overflow: "hidden"
409
+ }
410
+ });
@@ -0,0 +1,44 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.resolveOpenAppsState = void 0;
7
+ /**
8
+ * Computes the new list of open tool instances when a user launches a dev app. Singleton
9
+ * tools reuse their existing instance while non-singletons create a new entry using the
10
+ * provided `generateId` helper.
11
+ *
12
+ * @param current - Current stack of open app instances.
13
+ * @param def - Descriptor of the tool to launch (without runtime instance id).
14
+ * @param generateId - Callback used to generate a unique instance identifier.
15
+ * @returns Updated instance list alongside the resolved instance id.
16
+ */
17
+ const resolveOpenAppsState = (current, def, generateId) => {
18
+ if (def.singleton) {
19
+ const existing = current.find(app => app.id === def.id);
20
+ if (existing) {
21
+ const wasMinimized = existing.minimized ?? false;
22
+ return {
23
+ instanceId: existing.instanceId,
24
+ wasMinimized,
25
+ apps: [...current.filter(app => app.instanceId !== existing.instanceId),
26
+ // Un-minimize the existing app when re-opening it
27
+ {
28
+ ...existing,
29
+ minimized: false
30
+ }]
31
+ };
32
+ }
33
+ }
34
+ const instanceId = generateId();
35
+ return {
36
+ instanceId,
37
+ wasMinimized: false,
38
+ apps: [...current, {
39
+ ...def,
40
+ instanceId
41
+ }]
42
+ };
43
+ };
44
+ exports.resolveOpenAppsState = resolveOpenAppsState;
@@ -0,0 +1,45 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.DefaultConfigProvider = DefaultConfigProvider;
7
+ exports.useDefaultConfig = useDefaultConfig;
8
+ var _react = _interopRequireWildcard(require("react"));
9
+ var _jsxRuntime = require("react/jsx-runtime");
10
+ 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); }
11
+ /**
12
+ * Context value for default configuration settings.
13
+ */
14
+
15
+ const DefaultConfigContext = /*#__PURE__*/(0, _react.createContext)({});
16
+
17
+ /**
18
+ * Provider for default configuration that can be consumed by the settings system.
19
+ * This allows teams to set default tool configurations without prop drilling.
20
+ *
21
+ * @internal Used by FloatingDevTools to provide defaults to the settings hook.
22
+ */
23
+ function DefaultConfigProvider({
24
+ children,
25
+ defaultFloatingTools,
26
+ defaultDialTools
27
+ }) {
28
+ const value = _react.default.useMemo(() => ({
29
+ defaultFloatingTools,
30
+ defaultDialTools
31
+ }), [defaultFloatingTools, defaultDialTools]);
32
+ return /*#__PURE__*/(0, _jsxRuntime.jsx)(DefaultConfigContext.Provider, {
33
+ value: value,
34
+ children: children
35
+ });
36
+ }
37
+
38
+ /**
39
+ * Hook to access the default configuration from context.
40
+ *
41
+ * @internal Used by useDevToolsSettings to apply defaults.
42
+ */
43
+ function useDefaultConfig() {
44
+ return (0, _react.useContext)(DefaultConfigContext);
45
+ }