@buoy-gg/core 7.0.40 → 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 -1111
  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 -1113
  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
@@ -1,1055 +1,44 @@
1
1
  "use strict";
2
2
 
3
- /**
4
- * DevToolsSettingsModal - Web renderer for the dev tools settings modal.
5
- *
6
- * Uses shared configuration and logic from @buoy-gg/floating-tools-react.
7
- * Platform-specific: CSS, mouse events, web JSX.
8
- *
9
- * VISUAL PARITY: styled 1:1 against the native reference
10
- * (devtools-floating-menu/src/floatingMenu/DevToolsSettingsModal.tsx, which
11
- * renders in the "night" language — shared-ui's ui/night Everlights port —
12
- * inside JsModal variant="night"). shared-ui is RN-only, so the night tokens
13
- * and primitive styles are inlined below with provenance comments.
14
- *
15
- * @platform React DOM Web (Vite, CRA, Next.js, Electron)
16
- */
17
-
18
- import { useState, useCallback, useEffect } from 'react';
19
- import {
20
- // Hook
21
- useSettings,
22
- // Tab configuration
23
- settingsTabs,
24
- // Tool metadata
25
- getToolLabel, getToolDescription,
26
- // Global settings config
27
- globalSettingsConfig
28
- // Types
29
- } from '@buoy-gg/floating-tools-react';
30
- import { QueryIcon, SentryIcon, EnvIcon, StorageIcon, NetworkIcon, RoutesIcon, HighlighterIcon, ReduxIcon, EventsIcon, WifiIcon, ImageOverlayIcon, ZustandIcon, JotaiIcon } from '@buoy-gg/floating-tools-core';
31
- // JsModal.web + storage keys via the consumer's shared-ui web shim — the
32
- // settings sheet is a real JsModal on web now, same as native. The
33
- // BackgroundSwitcher is the same RN component native mounts: it renders under
34
- // the consumer's RNW lane exactly like the ToolBackground JsModal.web draws.
35
- import { JsModal, devToolsStorageKeys, BackgroundSwitcher, monoFont } from '@buoy-gg/shared-ui';
36
-
37
- /** env(safe-area-inset-top) via a one-shot probe (native: useSafeAreaInsets). */
38
- import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
39
- function readTopSafeAreaInset() {
40
- if (typeof document === 'undefined') return 0;
41
- const probe = document.createElement('div');
42
- probe.style.cssText = 'position:fixed;top:env(safe-area-inset-top);visibility:hidden;pointer-events:none';
43
- document.body.appendChild(probe);
44
- const top = probe.getBoundingClientRect().top;
45
- document.body.removeChild(probe);
46
- return Math.max(0, top);
47
- }
48
-
49
- // =============================
50
- // Night tokens (provenance)
51
- // =============================
52
-
53
- /**
54
- * `night` from @buoy-gg/shared-ui (ui/night/nightTheme.ts) — the Everlights
55
- * palette the native settings modal is styled with. shared-ui cannot be
56
- * imported on web, so the values are inlined verbatim.
57
- */
58
- const night = {
59
- bg: '#050505',
60
- surface: '#0C0C0C',
61
- surfaceElevated: '#161618',
62
- border: '#1A1A1C',
63
- separator: 'rgba(255, 255, 255, 0.08)',
64
- glass: 'rgba(5, 5, 5, 0.50)',
65
- glassElevated: 'rgba(255, 255, 255, 0.06)',
66
- glassBorder: 'rgba(255, 255, 255, 0.07)',
67
- fillTertiary: 'rgba(255, 255, 255, 0.12)',
68
- buttonSurface: 'rgba(8, 10, 14, 0.85)',
69
- button: '#1C1C1C',
70
- buttonPressed: '#2C2C2E',
71
- text: '#ECEDEE',
72
- textSecondary: '#9BA1A6',
73
- textTertiary: '#636366',
74
- placeholder: 'rgba(255, 255, 255, 0.30)',
75
- accent: '#20C997',
76
- accentSoft: 'rgba(32, 201, 151, 0.12)',
77
- accentFill: 'rgba(32, 201, 151, 0.18)',
78
- accentBorderStrong: 'rgba(32, 201, 151, 0.35)',
79
- onAccent: '#000000',
80
- danger: '#FF3B30',
81
- dangerSoft: 'rgba(255, 59, 48, 0.10)',
82
- warning: '#FF8329',
83
- warningSoft: 'rgba(255, 131, 41, 0.12)',
84
- fillSecondary: 'rgba(255, 255, 255, 0.08)',
85
- knob: '#D4D8DC'
86
- };
87
-
88
- // =============================
89
- // Types
90
- // =============================
91
-
92
- // =============================
93
- // Web Storage Adapter
94
- // =============================
95
-
96
- const webStorageAdapter = {
97
- getItem: key => localStorage.getItem(key),
98
- setItem: (key, value) => localStorage.setItem(key, value)
99
- };
100
-
101
- // =============================
102
- // Icon Components (Web SVGs)
103
- // =============================
104
-
105
- /** Fallback for shared-ui Layers icon (native debug-borders row icon). */
106
- const Layers = ({
107
- size = 24,
108
- color = 'currentColor'
109
- }) => /*#__PURE__*/_jsxs("svg", {
110
- width: size,
111
- height: size,
112
- viewBox: "0 0 24 24",
113
- fill: "none",
114
- stroke: color,
115
- strokeWidth: "2",
116
- strokeLinecap: "round",
117
- strokeLinejoin: "round",
118
- children: [/*#__PURE__*/_jsx("path", {
119
- d: "M12.83 2.18a2 2 0 0 0-1.66 0L2.6 6.08a1 1 0 0 0 0 1.83l8.58 3.91a2 2 0 0 0 1.66 0l8.58-3.9a1 1 0 0 0 0-1.83Z"
120
- }), /*#__PURE__*/_jsx("path", {
121
- d: "m22 17.65-9.17 4.16a2 2 0 0 1-1.66 0L2 17.65"
122
- }), /*#__PURE__*/_jsx("path", {
123
- d: "m22 12.65-9.17 4.16a2 2 0 0 1-1.66 0L2 12.65"
124
- })]
125
- });
126
-
127
- /** Fallback for shared-ui RenderCountIcon (native highlight-updates row icon). */
128
- const Sparkles = ({
129
- size = 24,
130
- color = 'currentColor'
131
- }) => /*#__PURE__*/_jsxs("svg", {
132
- width: size,
133
- height: size,
134
- viewBox: "0 0 24 24",
135
- fill: "none",
136
- stroke: color,
137
- strokeWidth: "2",
138
- strokeLinecap: "round",
139
- strokeLinejoin: "round",
140
- children: [/*#__PURE__*/_jsx("path", {
141
- d: "M9.937 15.5A2 2 0 0 0 8.5 14.063l-6.135-1.582a.5.5 0 0 1 0-.962L8.5 9.936A2 2 0 0 0 9.937 8.5l1.582-6.135a.5.5 0 0 1 .963 0L14.063 8.5A2 2 0 0 0 15.5 9.937l6.135 1.581a.5.5 0 0 1 0 .964L15.5 14.063a2 2 0 0 0-1.437 1.437l-1.582 6.135a.5.5 0 0 1-.963 0z"
142
- }), /*#__PURE__*/_jsx("path", {
143
- d: "M20 3v4"
144
- }), /*#__PURE__*/_jsx("path", {
145
- d: "M22 5h-4"
146
- }), /*#__PURE__*/_jsx("path", {
147
- d: "M4 17v2"
148
- }), /*#__PURE__*/_jsx("path", {
149
- d: "M5 18H3"
150
- })]
151
- });
152
-
153
- /** shared-ui Info icon (native default tool icon). */
154
- const Info = ({
155
- size = 24,
156
- color = 'currentColor'
157
- }) => /*#__PURE__*/_jsxs("svg", {
158
- width: size,
159
- height: size,
160
- viewBox: "0 0 24 24",
161
- fill: "none",
162
- stroke: color,
163
- strokeWidth: "2",
164
- strokeLinecap: "round",
165
- strokeLinejoin: "round",
166
- children: [/*#__PURE__*/_jsx("circle", {
167
- cx: "12",
168
- cy: "12",
169
- r: "10"
170
- }), /*#__PURE__*/_jsx("path", {
171
- d: "M12 16v-4"
172
- }), /*#__PURE__*/_jsx("path", {
173
- d: "M12 8h.01"
174
- })]
175
- });
176
-
177
- /** shared-ui CheckCircle2 icon (clear-success feedback). */
178
- const CheckCircle2 = ({
179
- size = 24,
180
- color = 'currentColor'
181
- }) => /*#__PURE__*/_jsxs("svg", {
182
- width: size,
183
- height: size,
184
- viewBox: "0 0 24 24",
185
- fill: "none",
186
- stroke: color,
187
- strokeWidth: "2",
188
- strokeLinecap: "round",
189
- strokeLinejoin: "round",
190
- children: [/*#__PURE__*/_jsx("circle", {
191
- cx: "12",
192
- cy: "12",
193
- r: "10"
194
- }), /*#__PURE__*/_jsx("path", {
195
- d: "m9 12 2 2 4-4"
196
- })]
197
- });
198
-
199
- /** shared-ui Trash2 icon (native Clear All Settings button icon). */
200
- const Trash2 = ({
201
- size = 24,
202
- color = 'currentColor'
203
- }) => /*#__PURE__*/_jsxs("svg", {
204
- width: size,
205
- height: size,
206
- viewBox: "0 0 24 24",
207
- fill: "none",
208
- stroke: color,
209
- strokeWidth: "2",
210
- strokeLinecap: "round",
211
- strokeLinejoin: "round",
212
- children: [/*#__PURE__*/_jsx("path", {
213
- d: "M3 6h18"
214
- }), /*#__PURE__*/_jsx("path", {
215
- d: "M19 6v14a2 2 0 0 1-2 2H7a2 2 0 0 1-2-2V6"
216
- }), /*#__PURE__*/_jsx("path", {
217
- d: "M8 6V4a2 2 0 0 1 2-2h4a2 2 0 0 1 2 2v2"
218
- }), /*#__PURE__*/_jsx("line", {
219
- x1: "10",
220
- x2: "10",
221
- y1: "11",
222
- y2: "17"
223
- }), /*#__PURE__*/_jsx("line", {
224
- x1: "14",
225
- x2: "14",
226
- y1: "11",
227
- y2: "17"
228
- })]
229
- });
230
- function ChevronRightIcon({
231
- size = 16,
232
- color = 'currentColor'
233
- }) {
234
- return /*#__PURE__*/_jsx("svg", {
235
- width: size,
236
- height: size,
237
- viewBox: "0 0 24 24",
238
- fill: "none",
239
- stroke: color,
240
- strokeWidth: "2",
241
- strokeLinecap: "round",
242
- strokeLinejoin: "round",
243
- children: /*#__PURE__*/_jsx("path", {
244
- d: "M9 18l6-6-6-6"
245
- })
246
- });
247
- }
248
- function ChevronDownIcon({
249
- size = 16,
250
- color = 'currentColor'
251
- }) {
252
- return /*#__PURE__*/_jsx("svg", {
253
- width: size,
254
- height: size,
255
- viewBox: "0 0 24 24",
256
- fill: "none",
257
- stroke: color,
258
- strokeWidth: "2",
259
- strokeLinecap: "round",
260
- strokeLinejoin: "round",
261
- children: /*#__PURE__*/_jsx("path", {
262
- d: "m6 9 6 6 6-6"
263
- })
264
- });
265
- }
266
-
267
- /**
268
- * Tool icon mapping — mirrors the native getToolIcon() switch in
269
- * DevToolsSettingsModal.tsx (size 18 in the night rows). Real tool icons come
270
- * from floating-tools-core (web-compatible); shared-ui-only icons use the
271
- * closest web SVG fallback.
272
- */
273
- function ToolIcon({
274
- toolId,
275
- tool
276
- }) {
277
- const size = 18; // native: getToolIcon renders all icons at size 18
278
- switch (toolId) {
279
- case 'query':
280
- return /*#__PURE__*/_jsx(QueryIcon, {
281
- size: size
282
- });
283
- case 'env':
284
- case 'environment':
285
- return /*#__PURE__*/_jsx(EnvIcon, {
286
- size: size
287
- });
288
- case 'sentry':
289
- return /*#__PURE__*/_jsx(SentryIcon, {
290
- size: size,
291
- color: "#9945FF"
292
- });
293
- case 'storage':
294
- // native passes bgColor=night surface for the BIF knock-out parts
295
- return /*#__PURE__*/_jsx(StorageIcon, {
296
- size: size,
297
- bgColor: night.surface
298
- });
299
- case 'wifi':
300
- case 'query-wifi-toggle':
301
- // native: WifiCircuitIcon colorPreset="green" (shared-ui only)
302
- return /*#__PURE__*/_jsx(WifiIcon, {
303
- size: size
304
- });
305
- case 'route-events':
306
- case 'routes':
307
- // web alias for the same tool
308
- return /*#__PURE__*/_jsx(RoutesIcon, {
309
- size: size,
310
- bgColor: night.surface
311
- });
312
- case 'network':
313
- return /*#__PURE__*/_jsx(NetworkIcon, {
314
- size: size
315
- });
316
- case 'debug-borders':
317
- // native: Layers size 18 color night accent
318
- return /*#__PURE__*/_jsx(Layers, {
319
- size: size,
320
- color: night.accent
321
- });
322
- case 'highlight-updates':
323
- // native: RenderCountIcon size 18 color night accent
324
- return /*#__PURE__*/_jsx(Sparkles, {
325
- size: size,
326
- color: night.accent
327
- });
328
- case 'highlight-updates-modal':
329
- return /*#__PURE__*/_jsx(HighlighterIcon, {
330
- size: size
331
- });
332
- case 'redux':
333
- return /*#__PURE__*/_jsx(ReduxIcon, {
334
- size: size
335
- });
336
- case 'image-overlay':
337
- return /*#__PURE__*/_jsx(ImageOverlayIcon, {
338
- size: size
339
- });
340
- case 'events':
341
- return /*#__PURE__*/_jsx(EventsIcon, {
342
- size: size
343
- });
344
- case 'zustand':
345
- return /*#__PURE__*/_jsx(ZustandIcon, {
346
- size: size
347
- });
348
- case 'jotai':
349
- return /*#__PURE__*/_jsx(JotaiIcon, {
350
- size: size
351
- });
352
- default:
353
- {
354
- // Tools without a hardcoded glyph (console, images, time machine,
355
- // perf monitor, custom toolkit tools, …) render their own icon —
356
- // mirrors the native getToolIcon() renderAppIcon fallback.
357
- if (typeof tool?.icon === 'function') {
358
- return /*#__PURE__*/_jsx(_Fragment, {
359
- children: tool.icon(size)
360
- });
361
- }
362
- if (typeof tool?.icon === 'string') {
363
- // Web twin of native AppTextIcon: short labels/emoji auto-fit the slot.
364
- return /*#__PURE__*/_jsx("span", {
365
- style: {
366
- maxWidth: size * 1.6,
367
- overflow: 'hidden',
368
- whiteSpace: 'nowrap',
369
- fontSize: tool.icon.length <= 2 ? size * 0.7 : 10,
370
- fontWeight: 800,
371
- letterSpacing: 0.5,
372
- textAlign: 'center',
373
- color: tool.color ?? night.textSecondary
374
- },
375
- children: tool.icon
376
- });
377
- }
378
- // native: Info size 18 color night textSecondary
379
- return /*#__PURE__*/_jsx(Info, {
380
- size: size,
381
- color: night.textSecondary
382
- });
383
- }
384
- }
385
- }
386
-
387
- // =============================
388
- // Night primitives (DOM twins of shared-ui ui/night/primitives.tsx)
389
- // =============================
390
-
391
- /** native NightSectionLabel: 12/600/ls0.8 uppercase, mb 8, ml 4 */
392
- function SectionLabel({
393
- children
394
- }) {
395
- return /*#__PURE__*/_jsx("div", {
396
- style: {
397
- color: night.textSecondary,
398
- fontSize: 12,
399
- fontWeight: 600,
400
- letterSpacing: 0.8,
401
- textTransform: 'uppercase',
402
- marginBottom: 8,
403
- marginLeft: 4
404
- },
405
- children: children
406
- });
407
- }
408
-
409
- /** native NightFootnote: 13/500 textTertiary, mt 8, ml 4 */
410
- function Footnote({
411
- children,
412
- tone = 'tertiary'
413
- }) {
414
- return /*#__PURE__*/_jsx("div", {
415
- style: {
416
- color: tone === 'warning' ? night.warning : tone === 'danger' ? night.danger : night.textTertiary,
417
- fontSize: 13,
418
- fontWeight: 500,
419
- lineHeight: '18px',
420
- marginTop: 8,
421
- marginLeft: 4
422
- },
423
- children: children
424
- });
425
- }
426
-
427
- /** native NightCard glass: 50% black, radius 14, 1px white-alpha hairline, clipped */
428
- const cardStyle = {
429
- backgroundColor: night.glass,
430
- borderRadius: 14,
431
- border: `1px solid ${night.glassBorder}`,
432
- overflow: 'hidden'
433
- };
434
-
435
- /** native NightSeparator: hairline inset 16 */
436
- function Separator({
437
- inset = 16
438
- }) {
439
- return /*#__PURE__*/_jsx("div", {
440
- style: {
441
- height: 1,
442
- transform: 'scaleY(0.5)',
443
- // hairline
444
- marginLeft: inset,
445
- backgroundColor: night.separator
446
- }
447
- });
448
- }
449
-
450
- /** native NightSwitch: 56×32 track, 22px thumb, 24px travel, 200ms */
451
- function NightSwitch({
452
- value,
453
- onChange,
454
- disabled
455
- }) {
456
- return /*#__PURE__*/_jsx("button", {
457
- role: "switch",
458
- "aria-checked": value,
459
- disabled: disabled,
460
- onClick: e => {
461
- e.stopPropagation();
462
- if (!disabled) onChange();
463
- },
464
- style: {
465
- width: 56,
466
- height: 32,
467
- borderRadius: 16,
468
- border: `1px solid ${value ? night.accentBorderStrong : night.fillTertiary}`,
469
- backgroundColor: value ? night.accentFill : night.surfaceElevated,
470
- padding: 0,
471
- position: 'relative',
472
- cursor: disabled ? 'not-allowed' : 'pointer',
473
- opacity: disabled ? 0.4 : 1,
474
- flexShrink: 0,
475
- boxSizing: 'border-box',
476
- transition: 'background-color 200ms ease, border-color 200ms ease'
477
- },
478
- children: /*#__PURE__*/_jsx("span", {
479
- style: {
480
- position: 'absolute',
481
- top: 4,
482
- left: 4,
483
- width: 22,
484
- height: 22,
485
- borderRadius: 11,
486
- backgroundColor: value ? night.accent : night.knob,
487
- transform: value ? 'translateX(24px)' : 'translateX(0)',
488
- transition: 'transform 200ms ease, background-color 200ms ease'
489
- }
490
- })
491
- });
492
- }
493
-
494
- /** native NightBadge: uppercase 11/600 cap on a soft tint */
495
- function Badge({
496
- label,
497
- tone = 'neutral'
498
- }) {
499
- const bg = tone === 'accent' ? night.accentSoft : tone === 'warning' ? night.warningSoft : tone === 'danger' ? night.dangerSoft : night.fillSecondary;
500
- const color = tone === 'accent' ? night.accent : tone === 'warning' ? night.warning : tone === 'danger' ? night.danger : night.textSecondary;
501
- return /*#__PURE__*/_jsx("span", {
502
- style: {
503
- padding: '4px 8px',
504
- borderRadius: 6,
505
- backgroundColor: bg,
506
- color,
507
- fontSize: 11,
508
- fontWeight: 600,
509
- letterSpacing: 0.5,
510
- textTransform: 'uppercase',
511
- flexShrink: 0
512
- },
513
- children: label
514
- });
515
- }
516
-
517
- /** native NightButton size md: 34pt, radius 17, plate or accent fill */
518
- function NightButton({
519
- label,
520
- onClick,
521
- variant = 'secondary',
522
- icon,
523
- disabled
524
- }) {
525
- const color = variant === 'primary' ? night.onAccent : variant === 'destructive' ? night.danger : night.accent;
526
- return /*#__PURE__*/_jsxs("button", {
527
- onClick: onClick,
528
- disabled: disabled,
529
- style: {
530
- width: '100%',
531
- height: 34,
532
- borderRadius: 17,
533
- border: 'none',
534
- display: 'flex',
535
- alignItems: 'center',
536
- justifyContent: 'center',
537
- gap: 8,
538
- backgroundColor: variant === 'primary' ? night.accent : night.button,
539
- color,
540
- fontSize: 15,
541
- fontWeight: 600,
542
- fontFamily: 'inherit',
543
- cursor: disabled ? 'not-allowed' : 'pointer',
544
- opacity: disabled ? 0.4 : 1,
545
- transition: 'background-color 150ms ease, opacity 150ms ease'
546
- },
547
- children: [icon, label]
548
- });
549
- }
550
-
551
- // =============================
552
- // Row styles (native styles.settingRow / toolRow / rowLabel / rowCaption)
553
- // =============================
554
-
555
- const settingRowStyle = {
556
- display: 'flex',
557
- flexDirection: 'row',
558
- alignItems: 'center',
559
- gap: 10,
560
- padding: '14px 16px',
561
- minHeight: 52,
562
- boxSizing: 'border-box',
563
- cursor: 'pointer'
564
- };
565
- const rowLabelStyle = {
566
- color: night.text,
567
- fontSize: 15,
568
- fontWeight: 500
569
- };
570
- const rowCaptionStyle = {
571
- color: night.textTertiary,
572
- fontSize: 12,
573
- overflow: 'hidden',
574
- textOverflow: 'ellipsis',
575
- whiteSpace: 'nowrap'
576
- };
577
-
578
- // =============================
579
- // Tool Row (native renderToolRow)
580
- // =============================
581
-
582
- function ToolRow({
583
- toolId,
584
- enabled,
585
- disabled,
586
- availableTools,
587
- onToggle
588
- }) {
589
- const label = getToolLabel(toolId, availableTools);
590
- const description = getToolDescription(toolId, availableTools);
591
- return /*#__PURE__*/_jsxs("div", {
592
- onClick: disabled ? undefined : onToggle,
593
- style: {
594
- // native styles.toolRow: gap 12, px 16, py 12
595
- display: 'flex',
596
- flexDirection: 'row',
597
- alignItems: 'center',
598
- gap: 12,
599
- padding: '12px 16px',
600
- cursor: disabled ? 'not-allowed' : 'pointer',
601
- opacity: disabled ? 0.4 : 1
602
- },
603
- children: [/*#__PURE__*/_jsx("div", {
604
- style: {
605
- width: 24,
606
- display: 'flex',
607
- alignItems: 'center',
608
- justifyContent: 'center',
609
- flexShrink: 0
610
- },
611
- children: /*#__PURE__*/_jsx(ToolIcon, {
612
- toolId: toolId,
613
- tool: availableTools?.find(t => t.id === toolId)
614
- })
615
- }), /*#__PURE__*/_jsxs("div", {
616
- style: {
617
- flex: 1,
618
- minWidth: 0,
619
- display: 'flex',
620
- flexDirection: 'column',
621
- gap: 2
622
- },
623
- children: [/*#__PURE__*/_jsxs("div", {
624
- style: rowLabelStyle,
625
- children: [label, disabled && ' · max 6']
626
- }), description ? /*#__PURE__*/_jsx("div", {
627
- style: rowCaptionStyle,
628
- children: description
629
- }) : null]
630
- }), /*#__PURE__*/_jsx(NightSwitch, {
631
- value: enabled,
632
- disabled: disabled,
633
- onChange: onToggle
634
- })]
635
- });
636
- }
637
-
638
- // =============================
639
- // Global Setting Row (native renderGlobalSettingRow)
640
- // =============================
641
-
642
- function GlobalSettingRow({
643
- label,
644
- shortDescription,
645
- fullDescription,
646
- recommendation,
647
- value,
648
- onToggle
649
- }) {
650
- const [isExpanded, setIsExpanded] = useState(false);
651
- return /*#__PURE__*/_jsxs("div", {
652
- children: [/*#__PURE__*/_jsxs("div", {
653
- onClick: () => setIsExpanded(v => !v),
654
- style: settingRowStyle,
655
- children: [/*#__PURE__*/_jsxs("div", {
656
- style: {
657
- flex: 1,
658
- minWidth: 0,
659
- display: 'flex',
660
- flexDirection: 'column',
661
- gap: 2
662
- },
663
- children: [/*#__PURE__*/_jsx("div", {
664
- style: rowLabelStyle,
665
- children: label
666
- }), /*#__PURE__*/_jsx("div", {
667
- style: isExpanded ? {
668
- ...rowCaptionStyle,
669
- whiteSpace: 'normal'
670
- } : rowCaptionStyle,
671
- children: shortDescription
672
- })]
673
- }), /*#__PURE__*/_jsx(NightSwitch, {
674
- value: value,
675
- onChange: onToggle
676
- })]
677
- }), isExpanded && /*#__PURE__*/_jsxs("div", {
678
- style: {
679
- // native settingRowBody: px 16, pb 14, gap 6
680
- padding: '0 16px 14px',
681
- display: 'flex',
682
- flexDirection: 'column',
683
- gap: 6
684
- },
685
- children: [/*#__PURE__*/_jsx("div", {
686
- style: {
687
- color: night.textSecondary,
688
- fontSize: 13,
689
- lineHeight: '19px'
690
- },
691
- children: fullDescription
692
- }), /*#__PURE__*/_jsx("div", {
693
- style: {
694
- color: night.textTertiary,
695
- fontSize: 13,
696
- lineHeight: '19px'
697
- },
698
- children: recommendation
699
- })]
700
- })]
701
- });
702
- }
703
-
704
- // =============================
705
- // Main Component
706
- // =============================
707
-
3
+ import { useCallback, useMemo } from "react";
4
+ import { persistentStorage } from "@buoy-gg/shared-ui";
5
+ import { DevToolsSettingsModal } from "./DevToolsSettingsModal.shared.js";
6
+ import { DefaultConfigProvider } from "./DefaultConfigContext.js";
7
+ import { jsx as _jsx } from "react/jsx-runtime";
8
+ const EMPTY_TOOLS = [];
9
+
10
+ /** Adapts the browser host to the shared settings and account panel. */
708
11
  export function SettingsModal({
709
12
  visible,
710
13
  onClose,
711
- availableTools = [],
14
+ availableTools = EMPTY_TOOLS,
712
15
  defaultFloatingTools,
713
16
  defaultDialTools,
714
- storage = webStorageAdapter,
17
+ storage = persistentStorage,
715
18
  onSettingsChange
716
19
  }) {
717
- const [activeTab, setActiveTab] = useState('floating');
718
- const [isStorageExpanded, setIsStorageExpanded] = useState(false);
719
- const [savedKeys, setSavedKeys] = useState([]);
720
- const [clearSuccess, setClearSuccess] = useState(false);
721
-
722
- // Use the shared settings hook
723
- const {
724
- settings,
725
- isLoading,
726
- actions
727
- } = useSettings({
728
- availableTools,
729
- defaultFloatingTools,
730
- defaultDialTools,
731
- storage,
732
- onSettingsChange
733
- });
734
-
735
- // JsModal owns the close animation now — this is just the Escape path.
736
- const handleClose = useCallback(() => {
737
- onClose();
738
- }, [onClose]);
739
-
740
- // Escape key handler
741
- useEffect(() => {
742
- if (!visible) return;
743
- const handleKeyDown = e => {
744
- if (e.key === 'Escape') {
745
- handleClose();
746
- }
747
- };
748
- document.addEventListener('keydown', handleKeyDown);
749
- return () => document.removeEventListener('keydown', handleKeyDown);
750
- }, [visible, handleClose]);
751
-
752
- // Saved-settings key list for the storage card (mirrors the native
753
- // persistentStorage.getAllKeys() list; on web, Buoy keys in localStorage).
754
- useEffect(() => {
755
- if (!visible || !isStorageExpanded) return;
756
- try {
757
- const keys = Object.keys(localStorage).filter(key => key.startsWith('@react_buoy')).sort();
758
- setSavedKeys(keys);
759
- } catch {
760
- setSavedKeys([]);
761
- }
762
- }, [visible, isStorageExpanded, clearSuccess, settings]);
763
- const handleClearAll = useCallback(() => {
764
- // Same behavior as before (reset via the shared hook); the 2s "Cleared"
765
- // flash mirrors the native clear button feedback.
766
- actions.resetToDefaults();
767
- setClearSuccess(true);
768
- setTimeout(() => setClearSuccess(false), 2000);
769
- }, [actions]);
770
- if (!visible) return null;
771
-
772
- // Filter tabs - exclude 'pro' for now on web
773
- const displayTabs = settingsTabs.filter(tab => tab.key !== 'pro');
774
-
775
- // Segmented control rendered inside the JsModal header — native passes a
776
- // NightSegmented glass as header.customContent the same way. Track = glass
777
- // at radius 10 / padding 3; active thumb = glassElevated at radius 8 with
778
- // the accent underline glow (the Everlights All/Day tabs).
779
- const tabHeader = /*#__PURE__*/_jsx("div", {
780
- style: {
781
- display: 'flex',
782
- alignItems: 'center',
783
- paddingLeft: 16,
784
- paddingRight: 16,
785
- // window controls are cleared vertically, not sideways
786
- paddingBottom: 8
787
- },
788
- children: /*#__PURE__*/_jsx("div", {
789
- style: {
790
- flex: 1,
791
- display: 'flex',
792
- backgroundColor: night.glass,
793
- borderRadius: 10,
794
- border: `1px solid ${night.glassBorder}`,
795
- padding: 3,
796
- boxSizing: 'border-box'
797
- },
798
- children: displayTabs.map(tab => {
799
- const isActive = activeTab === tab.key;
800
- // native settingsTabs labels are uppercase ids; night shows title case
801
- const label = tab.label.charAt(0).toUpperCase() + tab.label.slice(1).toLowerCase();
802
- return /*#__PURE__*/_jsxs("button", {
803
- onClick: () => setActiveTab(tab.key),
804
- role: "tab",
805
- "aria-selected": isActive,
806
- style: {
807
- flex: 1,
808
- position: 'relative',
809
- padding: '8px 0',
810
- borderRadius: 8,
811
- border: 'none',
812
- backgroundColor: isActive ? night.glassElevated : 'transparent',
813
- color: isActive ? night.text : night.textSecondary,
814
- fontSize: 13,
815
- fontWeight: isActive ? 600 : 500,
816
- fontFamily: 'inherit',
817
- cursor: 'pointer',
818
- transition: 'all 150ms ease',
819
- display: 'flex',
820
- alignItems: 'center',
821
- justifyContent: 'center'
822
- },
823
- children: [label, isActive && /*#__PURE__*/_jsx("span", {
824
- style: {
825
- position: 'absolute',
826
- bottom: 2,
827
- left: '50%',
828
- transform: 'translateX(-50%)',
829
- width: 24,
830
- height: 2.5,
831
- borderRadius: 1.25,
832
- backgroundColor: night.accent,
833
- boxShadow: `0 0 6px ${night.accent}99`
834
- }
835
- })]
836
- }, tab.key);
837
- })
838
- })
839
- });
840
-
841
- // native: initialHeight = screenHeight / 3, floating starts centered at
842
- // width min(screenWidth - 32, 400), y = insets.top + 20.
843
- const modalWidth = Math.min(window.innerWidth - 32, 400);
844
- const topInset = readTopSafeAreaInset();
845
- return /*#__PURE__*/_jsx(JsModal, {
846
- visible: visible,
847
- onClose: handleClose,
848
- variant: "night",
849
- header: {
850
- showToggleButton: false,
851
- customContent: tabHeader
852
- },
853
- initialMode: "bottomSheet",
854
- persistenceKey: devToolsStorageKeys.settings.root(),
855
- enablePersistence: true,
856
- initialHeight: Math.floor(window.innerHeight * 0.33),
857
- initialFloatingPosition: {
858
- x: (window.innerWidth - modalWidth) / 2,
859
- y: topInset + 20 // native: insets.top + 20
860
- },
861
- zIndex: 10001 // above the dial (10000) — settings opens over it
862
- ,
863
- disableScrollWrapper: true,
864
- children: /*#__PURE__*/_jsx("div", {
865
- style: {
866
- flex: 1,
867
- minHeight: 0,
868
- overflow: 'auto',
869
- backgroundColor: 'transparent',
870
- padding: '8px 16px 24px',
871
- display: 'flex',
872
- flexDirection: 'column',
873
- gap: 24
874
- },
875
- children: isLoading ? /*#__PURE__*/_jsx("div", {
876
- style: {
877
- display: 'flex',
878
- alignItems: 'center',
879
- justifyContent: 'center',
880
- padding: 40,
881
- color: night.textTertiary,
882
- fontSize: 13
883
- },
884
- children: "Loading settings\u2026"
885
- }) : /*#__PURE__*/_jsxs(_Fragment, {
886
- children: [activeTab === 'floating' && /*#__PURE__*/_jsxs("div", {
887
- children: [/*#__PURE__*/_jsx(SectionLabel, {
888
- children: "Floating Tools"
889
- }), /*#__PURE__*/_jsx("div", {
890
- style: cardStyle,
891
- children: Object.entries(settings.floatingTools).map(([id, enabled], index) => /*#__PURE__*/_jsxs("div", {
892
- children: [index > 0 && /*#__PURE__*/_jsx(Separator, {}), /*#__PURE__*/_jsx(ToolRow, {
893
- toolId: id,
894
- enabled: enabled,
895
- availableTools: availableTools,
896
- onToggle: () => id === 'environment' ? actions.toggleEnvironment() : actions.toggleFloatingTool(id)
897
- })]
898
- }, id))
899
- }), /*#__PURE__*/_jsx(Footnote, {
900
- children: "Tools switched on here appear in the floating bubble row."
901
- })]
902
- }), activeTab === 'settings' && /*#__PURE__*/_jsxs(_Fragment, {
903
- children: [/*#__PURE__*/_jsxs("div", {
904
- children: [/*#__PURE__*/_jsx(SectionLabel, {
905
- children: "Background"
906
- }), /*#__PURE__*/_jsx("div", {
907
- style: {
908
- ...cardStyle,
909
- padding: 14
910
- },
911
- children: /*#__PURE__*/_jsx(BackgroundSwitcher, {
912
- embedded: true
913
- })
914
- })]
915
- }), /*#__PURE__*/_jsxs("div", {
916
- children: [/*#__PURE__*/_jsx(SectionLabel, {
917
- children: "Storage"
918
- }), /*#__PURE__*/_jsxs("div", {
919
- style: cardStyle,
920
- children: [/*#__PURE__*/_jsxs("div", {
921
- onClick: () => setIsStorageExpanded(v => !v),
922
- style: settingRowStyle,
923
- children: [/*#__PURE__*/_jsx("div", {
924
- style: {
925
- flex: 1,
926
- minWidth: 0
927
- },
928
- children: /*#__PURE__*/_jsx("div", {
929
- style: rowLabelStyle,
930
- children: "Storage Type"
931
- })
932
- }), /*#__PURE__*/_jsx(Badge, {
933
- label: "Local Storage",
934
- tone: "accent"
935
- }), isStorageExpanded ? /*#__PURE__*/_jsx(ChevronDownIcon, {
936
- size: 16,
937
- color: night.textTertiary
938
- }) : /*#__PURE__*/_jsx(ChevronRightIcon, {
939
- size: 16,
940
- color: night.textTertiary
941
- })]
942
- }), isStorageExpanded && /*#__PURE__*/_jsxs(_Fragment, {
943
- children: [/*#__PURE__*/_jsx("div", {
944
- style: {
945
- padding: '0 16px 14px'
946
- },
947
- children: /*#__PURE__*/_jsx("div", {
948
- style: {
949
- color: night.textSecondary,
950
- fontSize: 13,
951
- lineHeight: '19px'
952
- },
953
- children: "Settings persist in the browser's localStorage and survive page reloads."
954
- })
955
- }), /*#__PURE__*/_jsx(Separator, {}), /*#__PURE__*/_jsxs("div", {
956
- style: {
957
- padding: '12px 16px',
958
- display: 'flex',
959
- flexDirection: 'column',
960
- gap: 8
961
- },
962
- children: [/*#__PURE__*/_jsxs("div", {
963
- style: {
964
- display: 'flex',
965
- alignItems: 'center'
966
- },
967
- children: [/*#__PURE__*/_jsx("span", {
968
- style: {
969
- flex: 1,
970
- color: night.textSecondary,
971
- fontSize: 11,
972
- fontWeight: 600,
973
- letterSpacing: 0.5
974
- },
975
- children: "SAVED SETTINGS"
976
- }), /*#__PURE__*/_jsxs("span", {
977
- style: {
978
- color: night.textTertiary,
979
- fontSize: 11
980
- },
981
- children: [savedKeys.length, " keys"]
982
- })]
983
- }), savedKeys.length === 0 ? /*#__PURE__*/_jsx("div", {
984
- style: {
985
- color: night.textTertiary,
986
- fontSize: 13,
987
- fontStyle: 'italic'
988
- },
989
- children: "No settings saved yet"
990
- }) : /*#__PURE__*/_jsx("div", {
991
- style: {
992
- maxHeight: 150,
993
- overflow: 'auto'
994
- },
995
- children: savedKeys.map(key => /*#__PURE__*/_jsx("div", {
996
- style: {
997
- backgroundColor: night.glassElevated,
998
- borderRadius: 8,
999
- padding: '7px 10px',
1000
- marginBottom: 4
1001
- },
1002
- children: /*#__PURE__*/_jsx("div", {
1003
- style: {
1004
- color: night.textSecondary,
1005
- fontSize: 11,
1006
- fontFamily: monoFont,
1007
- overflow: 'hidden',
1008
- textOverflow: 'ellipsis',
1009
- whiteSpace: 'nowrap'
1010
- },
1011
- children: key.replace('@react_buoy_', '')
1012
- })
1013
- }, key))
1014
- })]
1015
- }), /*#__PURE__*/_jsx("div", {
1016
- style: {
1017
- padding: '10px 14px 14px'
1018
- },
1019
- children: /*#__PURE__*/_jsx(NightButton, {
1020
- label: clearSuccess ? 'Cleared' : 'Clear All Settings',
1021
- variant: clearSuccess ? 'secondary' : 'destructive',
1022
- onClick: handleClearAll,
1023
- icon: clearSuccess ? /*#__PURE__*/_jsx(CheckCircle2, {
1024
- size: 15,
1025
- color: night.accent
1026
- }) : /*#__PURE__*/_jsx(Trash2, {
1027
- size: 15,
1028
- color: night.danger
1029
- })
1030
- })
1031
- })]
1032
- })]
1033
- })]
1034
- }), /*#__PURE__*/_jsxs("div", {
1035
- children: [/*#__PURE__*/_jsx(SectionLabel, {
1036
- children: "Modal Behavior"
1037
- }), /*#__PURE__*/_jsx("div", {
1038
- style: cardStyle,
1039
- children: globalSettingsConfig.map((config, index) => /*#__PURE__*/_jsxs("div", {
1040
- children: [index > 0 && /*#__PURE__*/_jsx(Separator, {}), /*#__PURE__*/_jsx(GlobalSettingRow, {
1041
- label: config.label,
1042
- shortDescription: config.shortDescription,
1043
- fullDescription: config.fullDescription,
1044
- recommendation: config.recommendation,
1045
- value: settings.globalSettings?.[config.key] ?? false,
1046
- onToggle: () => actions.toggleGlobalSetting(config.key)
1047
- })]
1048
- }, config.key))
1049
- })]
1050
- })]
1051
- })]
1052
- })
20
+ const adapter = useMemo(() => ({
21
+ getItem: async key => storage.getItem(key),
22
+ setItem: async (key, value) => storage.setItem(key, value)
23
+ }), [storage]);
24
+ const availableApps = useMemo(() => availableTools.map(tool => ({
25
+ ...tool,
26
+ name: tool.name ?? tool.id,
27
+ icon: typeof tool.icon === "function" ? context => tool.icon(context.size) : tool.icon
28
+ })), [availableTools]);
29
+ const handleChange = useCallback(settings => {
30
+ onSettingsChange?.(settings);
31
+ }, [onSettingsChange]);
32
+ return /*#__PURE__*/_jsx(DefaultConfigProvider, {
33
+ defaultFloatingTools: defaultFloatingTools,
34
+ defaultDialTools: defaultDialTools,
35
+ children: /*#__PURE__*/_jsx(DevToolsSettingsModal, {
36
+ visible: visible,
37
+ onClose: onClose,
38
+ zIndex: 11000,
39
+ availableApps: availableApps,
40
+ storage: adapter,
41
+ onSettingsChange: handleChange
1053
42
  })
1054
43
  });
1055
44
  }