@buoy-gg/core 7.0.41 → 7.0.43

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 (270) hide show
  1. package/README.md +14 -95
  2. package/bin/buoy.js +19 -340
  3. package/lib/commonjs/Buoy.js +1 -107
  4. package/lib/commonjs/browserRegister.js +1 -48
  5. package/lib/commonjs/browserRegister.server.js +1 -10
  6. package/lib/commonjs/earlyHookScript.js +1 -0
  7. package/lib/commonjs/earlyNetwork.js +1 -0
  8. package/lib/commonjs/floatingMenu/AppHost.js +1 -460
  9. package/lib/commonjs/floatingMenu/AppHost.web.js +1 -376
  10. package/lib/commonjs/floatingMenu/AppHostLogic.js +1 -50
  11. package/lib/commonjs/floatingMenu/AppIcon.js +1 -91
  12. package/lib/commonjs/floatingMenu/AppIcon.web.js +1 -53
  13. package/lib/commonjs/floatingMenu/BrowserToolRuntime.js +1 -150
  14. package/lib/commonjs/floatingMenu/DefaultConfigContext.js +1 -45
  15. package/lib/commonjs/floatingMenu/DevToolsSettingsModal.js +1 -18
  16. package/lib/commonjs/floatingMenu/DevToolsSettingsModal.shared.js +1 -1114
  17. package/lib/commonjs/floatingMenu/DevToolsSettingsModal.web.js +1 -48
  18. package/lib/commonjs/floatingMenu/DevToolsVisibilityContext.js +1 -49
  19. package/lib/commonjs/floatingMenu/FloatingDevTools.js +1 -559
  20. package/lib/commonjs/floatingMenu/FloatingDevTools.web.js +1 -415
  21. package/lib/commonjs/floatingMenu/FloatingMenu.js +1 -371
  22. package/lib/commonjs/floatingMenu/MinimizedToolsContext.js +1 -274
  23. package/lib/commonjs/floatingMenu/MinimizedToolsStack.js +1 -288
  24. package/lib/commonjs/floatingMenu/MinimizedToolsStack.web.js +1 -377
  25. package/lib/commonjs/floatingMenu/ToggleStateManager.js +1 -36
  26. package/lib/commonjs/floatingMenu/ToolHost.js +1 -281
  27. package/lib/commonjs/floatingMenu/ToolOpenerBridge.js +1 -41
  28. package/lib/commonjs/floatingMenu/autoDiscoverPresets.js +1 -471
  29. package/lib/commonjs/floatingMenu/autoExternalSync.js +1 -443
  30. package/lib/commonjs/floatingMenu/defaultConfig.js +1 -167
  31. package/lib/commonjs/floatingMenu/deviceIdentity.js +1 -173
  32. package/lib/commonjs/floatingMenu/dial/DialDevTools.js +1 -904
  33. package/lib/commonjs/floatingMenu/dial/DialDevTools.web.js +1 -895
  34. package/lib/commonjs/floatingMenu/dial/DialHyperspace.js +1 -177
  35. package/lib/commonjs/floatingMenu/dial/DialIcon.js +1 -304
  36. package/lib/commonjs/floatingMenu/dial/DialPagination.js +1 -165
  37. package/lib/commonjs/floatingMenu/dial/DialSnow.js +1 -92
  38. package/lib/commonjs/floatingMenu/dial/OnboardingTooltip.js +1 -246
  39. package/lib/commonjs/floatingMenu/dial/OnboardingTooltip.web.js +2 -147
  40. package/lib/commonjs/floatingMenu/dial/dialUsageStore.js +1 -93
  41. package/lib/commonjs/floatingMenu/dial/onboardingConstants.js +1 -42
  42. package/lib/commonjs/floatingMenu/dial/onboardingConstants.web.js +1 -42
  43. package/lib/commonjs/floatingMenu/externalSyncGate.js +1 -49
  44. package/lib/commonjs/floatingMenu/floatingTools.js +1 -42
  45. package/lib/commonjs/floatingMenu/floatingTools.web.js +1 -30
  46. package/lib/commonjs/floatingMenu/optionalRequire.js +1 -37
  47. package/lib/commonjs/floatingMenu/settingsBus.js +1 -12
  48. package/lib/commonjs/floatingMenu/sync/appSyncAdapter.js +1 -115
  49. package/lib/commonjs/floatingMenu/types.js +1 -5
  50. package/lib/commonjs/floatingMenu/useDesktopSyncStatus.js +1 -28
  51. package/lib/commonjs/floatingMenu/useDesktopSyncStatus.web.js +1 -14
  52. package/lib/commonjs/index.js +1 -291
  53. package/lib/commonjs/index.web.js +1 -241
  54. package/lib/commonjs/reactDevtoolsTypes.js +1 -1
  55. package/lib/commonjs/releaseOptIn.js +1 -0
  56. package/lib/commonjs/telemetry/installPing.js +1 -131
  57. package/lib/commonjs/toolkit.js +1 -584
  58. package/lib/commonjs/toolkitComponents.js +1 -241
  59. package/lib/commonjs/utils/autoDiscoverPresets.web.js +1 -46
  60. package/lib/commonjs/utils/createWebTool.js +1 -20
  61. package/lib/commonjs/utils/createWebTools.js +1 -30
  62. package/lib/commonjs/version.js +1 -18
  63. package/lib/module/Buoy.js +1 -102
  64. package/lib/module/browserRegister.js +1 -44
  65. package/lib/module/browserRegister.server.js +1 -6
  66. package/lib/module/earlyHookScript.js +1 -0
  67. package/lib/module/earlyNetwork.js +1 -0
  68. package/lib/module/floatingMenu/AppHost.js +1 -452
  69. package/lib/module/floatingMenu/AppHost.web.js +1 -368
  70. package/lib/module/floatingMenu/AppHostLogic.js +1 -45
  71. package/lib/module/floatingMenu/AppIcon.js +1 -84
  72. package/lib/module/floatingMenu/AppIcon.web.js +1 -47
  73. package/lib/module/floatingMenu/BrowserToolRuntime.js +1 -146
  74. package/lib/module/floatingMenu/DefaultConfigContext.js +1 -39
  75. package/lib/module/floatingMenu/DevToolsSettingsModal.js +1 -3
  76. package/lib/module/floatingMenu/DevToolsSettingsModal.shared.js +1 -1110
  77. package/lib/module/floatingMenu/DevToolsSettingsModal.web.js +1 -44
  78. package/lib/module/floatingMenu/DevToolsVisibilityContext.js +1 -44
  79. package/lib/module/floatingMenu/FloatingDevTools.js +1 -556
  80. package/lib/module/floatingMenu/FloatingDevTools.web.js +1 -412
  81. package/lib/module/floatingMenu/FloatingMenu.js +1 -366
  82. package/lib/module/floatingMenu/MinimizedToolsContext.js +1 -266
  83. package/lib/module/floatingMenu/MinimizedToolsStack.js +1 -285
  84. package/lib/module/floatingMenu/MinimizedToolsStack.web.js +1 -374
  85. package/lib/module/floatingMenu/ToggleStateManager.js +1 -32
  86. package/lib/module/floatingMenu/ToolHost.js +1 -273
  87. package/lib/module/floatingMenu/ToolOpenerBridge.js +1 -37
  88. package/lib/module/floatingMenu/autoDiscoverPresets.js +1 -467
  89. package/lib/module/floatingMenu/autoExternalSync.js +1 -436
  90. package/lib/module/floatingMenu/defaultConfig.js +1 -158
  91. package/lib/module/floatingMenu/deviceIdentity.js +1 -163
  92. package/lib/module/floatingMenu/dial/DialDevTools.js +1 -900
  93. package/lib/module/floatingMenu/dial/DialDevTools.web.js +1 -891
  94. package/lib/module/floatingMenu/dial/DialHyperspace.js +1 -173
  95. package/lib/module/floatingMenu/dial/DialIcon.js +1 -301
  96. package/lib/module/floatingMenu/dial/DialPagination.js +1 -160
  97. package/lib/module/floatingMenu/dial/DialSnow.js +1 -90
  98. package/lib/module/floatingMenu/dial/OnboardingTooltip.js +1 -240
  99. package/lib/module/floatingMenu/dial/OnboardingTooltip.web.js +2 -142
  100. package/lib/module/floatingMenu/dial/dialUsageStore.js +1 -85
  101. package/lib/module/floatingMenu/dial/onboardingConstants.js +1 -3
  102. package/lib/module/floatingMenu/dial/onboardingConstants.web.js +1 -3
  103. package/lib/module/floatingMenu/externalSyncGate.js +1 -44
  104. package/lib/module/floatingMenu/floatingTools.js +1 -27
  105. package/lib/module/floatingMenu/floatingTools.web.js +1 -3
  106. package/lib/module/floatingMenu/optionalRequire.js +1 -33
  107. package/lib/module/floatingMenu/settingsBus.js +1 -3
  108. package/lib/module/floatingMenu/sync/appSyncAdapter.js +1 -112
  109. package/lib/module/floatingMenu/types.js +1 -3
  110. package/lib/module/floatingMenu/useDesktopSyncStatus.js +1 -25
  111. package/lib/module/floatingMenu/useDesktopSyncStatus.web.js +1 -10
  112. package/lib/module/index.js +1 -41
  113. package/lib/module/index.web.js +1 -36
  114. package/lib/module/reactDevtoolsTypes.js +1 -1
  115. package/lib/module/releaseOptIn.js +1 -0
  116. package/lib/module/telemetry/installPing.js +1 -127
  117. package/lib/module/toolkit.js +1 -62
  118. package/lib/module/toolkitComponents.js +1 -230
  119. package/lib/module/utils/autoDiscoverPresets.web.js +1 -38
  120. package/lib/module/utils/createWebTool.js +1 -17
  121. package/lib/module/utils/createWebTools.js +1 -25
  122. package/lib/module/version.js +1 -14
  123. package/lib/typescript/commonjs/browserRegister.d.ts +9 -1
  124. package/lib/typescript/commonjs/browserRegister.server.d.ts +1 -0
  125. package/lib/typescript/commonjs/earlyHookScript.d.ts +12 -0
  126. package/lib/typescript/commonjs/earlyNetwork.d.ts +52 -0
  127. package/lib/typescript/commonjs/floatingMenu/defaultConfig.d.ts +1 -1
  128. package/lib/typescript/commonjs/index.web.d.ts +1 -0
  129. package/lib/typescript/commonjs/releaseOptIn.d.ts +4 -0
  130. package/lib/typescript/commonjs/version.d.ts +1 -1
  131. package/lib/typescript/module/browserRegister.d.ts +9 -1
  132. package/lib/typescript/module/browserRegister.server.d.ts +1 -0
  133. package/lib/typescript/module/earlyHookScript.d.ts +12 -0
  134. package/lib/typescript/module/earlyNetwork.d.ts +52 -0
  135. package/lib/typescript/module/floatingMenu/defaultConfig.d.ts +1 -1
  136. package/lib/typescript/module/index.web.d.ts +1 -0
  137. package/lib/typescript/module/releaseOptIn.d.ts +4 -0
  138. package/lib/typescript/module/version.d.ts +1 -1
  139. package/lib/web/chunks/chunk-5SGL6QL4.mjs +1 -0
  140. package/lib/web/chunks/chunk-FROELTJH.mjs +1 -0
  141. package/lib/web/chunks/chunk-QZDVCMCT.mjs +1 -2
  142. package/lib/web/chunks/chunk-R7RGRTY5.mjs +1 -2
  143. package/lib/web/index.mjs +2 -3
  144. package/lib/web/register-server.mjs +1 -2
  145. package/lib/web/register.mjs +1 -2
  146. package/lib/web/toolkit.mjs +1 -2
  147. package/package.json +6 -9
  148. package/lib/typescript/commonjs/Buoy.d.ts.map +0 -1
  149. package/lib/typescript/commonjs/browserRegister.d.ts.map +0 -1
  150. package/lib/typescript/commonjs/browserRegister.server.d.ts.map +0 -1
  151. package/lib/typescript/commonjs/floatingMenu/AppHost.d.ts.map +0 -1
  152. package/lib/typescript/commonjs/floatingMenu/AppHost.web.d.ts.map +0 -1
  153. package/lib/typescript/commonjs/floatingMenu/AppHostLogic.d.ts.map +0 -1
  154. package/lib/typescript/commonjs/floatingMenu/AppIcon.d.ts.map +0 -1
  155. package/lib/typescript/commonjs/floatingMenu/AppIcon.web.d.ts.map +0 -1
  156. package/lib/typescript/commonjs/floatingMenu/BrowserToolRuntime.d.ts.map +0 -1
  157. package/lib/typescript/commonjs/floatingMenu/DefaultConfigContext.d.ts.map +0 -1
  158. package/lib/typescript/commonjs/floatingMenu/DevToolsSettingsModal.d.ts.map +0 -1
  159. package/lib/typescript/commonjs/floatingMenu/DevToolsSettingsModal.shared.d.ts.map +0 -1
  160. package/lib/typescript/commonjs/floatingMenu/DevToolsSettingsModal.web.d.ts.map +0 -1
  161. package/lib/typescript/commonjs/floatingMenu/DevToolsVisibilityContext.d.ts.map +0 -1
  162. package/lib/typescript/commonjs/floatingMenu/FloatingDevTools.d.ts.map +0 -1
  163. package/lib/typescript/commonjs/floatingMenu/FloatingDevTools.web.d.ts.map +0 -1
  164. package/lib/typescript/commonjs/floatingMenu/FloatingMenu.d.ts.map +0 -1
  165. package/lib/typescript/commonjs/floatingMenu/MinimizedToolsContext.d.ts.map +0 -1
  166. package/lib/typescript/commonjs/floatingMenu/MinimizedToolsStack.d.ts.map +0 -1
  167. package/lib/typescript/commonjs/floatingMenu/MinimizedToolsStack.web.d.ts.map +0 -1
  168. package/lib/typescript/commonjs/floatingMenu/ToggleStateManager.d.ts.map +0 -1
  169. package/lib/typescript/commonjs/floatingMenu/ToolHost.d.ts.map +0 -1
  170. package/lib/typescript/commonjs/floatingMenu/ToolOpenerBridge.d.ts.map +0 -1
  171. package/lib/typescript/commonjs/floatingMenu/autoDiscoverPresets.d.ts.map +0 -1
  172. package/lib/typescript/commonjs/floatingMenu/autoExternalSync.d.ts.map +0 -1
  173. package/lib/typescript/commonjs/floatingMenu/defaultConfig.d.ts.map +0 -1
  174. package/lib/typescript/commonjs/floatingMenu/deviceIdentity.d.ts.map +0 -1
  175. package/lib/typescript/commonjs/floatingMenu/dial/DialDevTools.d.ts.map +0 -1
  176. package/lib/typescript/commonjs/floatingMenu/dial/DialDevTools.web.d.ts.map +0 -1
  177. package/lib/typescript/commonjs/floatingMenu/dial/DialHyperspace.d.ts.map +0 -1
  178. package/lib/typescript/commonjs/floatingMenu/dial/DialIcon.d.ts.map +0 -1
  179. package/lib/typescript/commonjs/floatingMenu/dial/DialPagination.d.ts.map +0 -1
  180. package/lib/typescript/commonjs/floatingMenu/dial/DialSnow.d.ts.map +0 -1
  181. package/lib/typescript/commonjs/floatingMenu/dial/OnboardingTooltip.d.ts.map +0 -1
  182. package/lib/typescript/commonjs/floatingMenu/dial/OnboardingTooltip.web.d.ts.map +0 -1
  183. package/lib/typescript/commonjs/floatingMenu/dial/dialUsageStore.d.ts.map +0 -1
  184. package/lib/typescript/commonjs/floatingMenu/dial/onboardingConstants.d.ts.map +0 -1
  185. package/lib/typescript/commonjs/floatingMenu/dial/onboardingConstants.web.d.ts.map +0 -1
  186. package/lib/typescript/commonjs/floatingMenu/externalSyncGate.d.ts.map +0 -1
  187. package/lib/typescript/commonjs/floatingMenu/floatingTools.d.ts.map +0 -1
  188. package/lib/typescript/commonjs/floatingMenu/floatingTools.web.d.ts.map +0 -1
  189. package/lib/typescript/commonjs/floatingMenu/optionalRequire.d.ts.map +0 -1
  190. package/lib/typescript/commonjs/floatingMenu/settingsBus.d.ts.map +0 -1
  191. package/lib/typescript/commonjs/floatingMenu/sync/appSyncAdapter.d.ts.map +0 -1
  192. package/lib/typescript/commonjs/floatingMenu/types.d.ts.map +0 -1
  193. package/lib/typescript/commonjs/floatingMenu/useDesktopSyncStatus.d.ts.map +0 -1
  194. package/lib/typescript/commonjs/floatingMenu/useDesktopSyncStatus.web.d.ts.map +0 -1
  195. package/lib/typescript/commonjs/index.d.ts.map +0 -1
  196. package/lib/typescript/commonjs/index.web.d.ts.map +0 -1
  197. package/lib/typescript/commonjs/reactDevtoolsTypes.d.ts.map +0 -1
  198. package/lib/typescript/commonjs/telemetry/installPing.d.ts.map +0 -1
  199. package/lib/typescript/commonjs/toolkit.d.ts.map +0 -1
  200. package/lib/typescript/commonjs/toolkitComponents.d.ts.map +0 -1
  201. package/lib/typescript/commonjs/utils/autoDiscoverPresets.web.d.ts.map +0 -1
  202. package/lib/typescript/commonjs/utils/createWebTool.d.ts.map +0 -1
  203. package/lib/typescript/commonjs/utils/createWebTools.d.ts.map +0 -1
  204. package/lib/typescript/commonjs/version.d.ts.map +0 -1
  205. package/lib/typescript/module/Buoy.d.ts.map +0 -1
  206. package/lib/typescript/module/browserRegister.d.ts.map +0 -1
  207. package/lib/typescript/module/browserRegister.server.d.ts.map +0 -1
  208. package/lib/typescript/module/floatingMenu/AppHost.d.ts.map +0 -1
  209. package/lib/typescript/module/floatingMenu/AppHost.web.d.ts.map +0 -1
  210. package/lib/typescript/module/floatingMenu/AppHostLogic.d.ts.map +0 -1
  211. package/lib/typescript/module/floatingMenu/AppIcon.d.ts.map +0 -1
  212. package/lib/typescript/module/floatingMenu/AppIcon.web.d.ts.map +0 -1
  213. package/lib/typescript/module/floatingMenu/BrowserToolRuntime.d.ts.map +0 -1
  214. package/lib/typescript/module/floatingMenu/DefaultConfigContext.d.ts.map +0 -1
  215. package/lib/typescript/module/floatingMenu/DevToolsSettingsModal.d.ts.map +0 -1
  216. package/lib/typescript/module/floatingMenu/DevToolsSettingsModal.shared.d.ts.map +0 -1
  217. package/lib/typescript/module/floatingMenu/DevToolsSettingsModal.web.d.ts.map +0 -1
  218. package/lib/typescript/module/floatingMenu/DevToolsVisibilityContext.d.ts.map +0 -1
  219. package/lib/typescript/module/floatingMenu/FloatingDevTools.d.ts.map +0 -1
  220. package/lib/typescript/module/floatingMenu/FloatingDevTools.web.d.ts.map +0 -1
  221. package/lib/typescript/module/floatingMenu/FloatingMenu.d.ts.map +0 -1
  222. package/lib/typescript/module/floatingMenu/MinimizedToolsContext.d.ts.map +0 -1
  223. package/lib/typescript/module/floatingMenu/MinimizedToolsStack.d.ts.map +0 -1
  224. package/lib/typescript/module/floatingMenu/MinimizedToolsStack.web.d.ts.map +0 -1
  225. package/lib/typescript/module/floatingMenu/ToggleStateManager.d.ts.map +0 -1
  226. package/lib/typescript/module/floatingMenu/ToolHost.d.ts.map +0 -1
  227. package/lib/typescript/module/floatingMenu/ToolOpenerBridge.d.ts.map +0 -1
  228. package/lib/typescript/module/floatingMenu/autoDiscoverPresets.d.ts.map +0 -1
  229. package/lib/typescript/module/floatingMenu/autoExternalSync.d.ts.map +0 -1
  230. package/lib/typescript/module/floatingMenu/defaultConfig.d.ts.map +0 -1
  231. package/lib/typescript/module/floatingMenu/deviceIdentity.d.ts.map +0 -1
  232. package/lib/typescript/module/floatingMenu/dial/DialDevTools.d.ts.map +0 -1
  233. package/lib/typescript/module/floatingMenu/dial/DialDevTools.web.d.ts.map +0 -1
  234. package/lib/typescript/module/floatingMenu/dial/DialHyperspace.d.ts.map +0 -1
  235. package/lib/typescript/module/floatingMenu/dial/DialIcon.d.ts.map +0 -1
  236. package/lib/typescript/module/floatingMenu/dial/DialPagination.d.ts.map +0 -1
  237. package/lib/typescript/module/floatingMenu/dial/DialSnow.d.ts.map +0 -1
  238. package/lib/typescript/module/floatingMenu/dial/OnboardingTooltip.d.ts.map +0 -1
  239. package/lib/typescript/module/floatingMenu/dial/OnboardingTooltip.web.d.ts.map +0 -1
  240. package/lib/typescript/module/floatingMenu/dial/dialUsageStore.d.ts.map +0 -1
  241. package/lib/typescript/module/floatingMenu/dial/onboardingConstants.d.ts.map +0 -1
  242. package/lib/typescript/module/floatingMenu/dial/onboardingConstants.web.d.ts.map +0 -1
  243. package/lib/typescript/module/floatingMenu/externalSyncGate.d.ts.map +0 -1
  244. package/lib/typescript/module/floatingMenu/floatingTools.d.ts.map +0 -1
  245. package/lib/typescript/module/floatingMenu/floatingTools.web.d.ts.map +0 -1
  246. package/lib/typescript/module/floatingMenu/optionalRequire.d.ts.map +0 -1
  247. package/lib/typescript/module/floatingMenu/settingsBus.d.ts.map +0 -1
  248. package/lib/typescript/module/floatingMenu/sync/appSyncAdapter.d.ts.map +0 -1
  249. package/lib/typescript/module/floatingMenu/types.d.ts.map +0 -1
  250. package/lib/typescript/module/floatingMenu/useDesktopSyncStatus.d.ts.map +0 -1
  251. package/lib/typescript/module/floatingMenu/useDesktopSyncStatus.web.d.ts.map +0 -1
  252. package/lib/typescript/module/index.d.ts.map +0 -1
  253. package/lib/typescript/module/index.web.d.ts.map +0 -1
  254. package/lib/typescript/module/reactDevtoolsTypes.d.ts.map +0 -1
  255. package/lib/typescript/module/telemetry/installPing.d.ts.map +0 -1
  256. package/lib/typescript/module/toolkit.d.ts.map +0 -1
  257. package/lib/typescript/module/toolkitComponents.d.ts.map +0 -1
  258. package/lib/typescript/module/utils/autoDiscoverPresets.web.d.ts.map +0 -1
  259. package/lib/typescript/module/utils/createWebTool.d.ts.map +0 -1
  260. package/lib/typescript/module/utils/createWebTools.d.ts.map +0 -1
  261. package/lib/typescript/module/version.d.ts.map +0 -1
  262. package/lib/web/chunks/chunk-5NZOQR6Q.mjs +0 -2
  263. package/lib/web/chunks/chunk-CGDSLLZF.mjs +0 -2
  264. package/lib/web/chunks/chunk-DCJDUSNR.mjs +0 -2
  265. package/lib/web/chunks/chunk-IDSHFS6G.mjs +0 -2
  266. package/lib/web/chunks/chunk-JOAMJGCS.mjs +0 -2
  267. package/lib/web/chunks/chunk-KYKZ2N52.mjs +0 -2
  268. package/lib/web/chunks/chunk-NGM7JGGS.mjs +0 -2
  269. package/lib/web/chunks/chunk-Z3XWDDIO.mjs +0 -2
  270. package/lib/web/chunks/chunk-ZTGQ6TTY.mjs +0 -2
@@ -1,1114 +1 @@
1
- "use strict";
2
-
3
- Object.defineProperty(exports, "__esModule", {
4
- value: true
5
- });
6
- exports.useDevToolsSettings = exports.DevToolsSettingsModal = void 0;
7
- var _react = require("react");
8
- var _reactNative = require("react-native");
9
- var _settingsBus = require("./settingsBus.js");
10
- var _useDesktopSyncStatus = require("./useDesktopSyncStatus");
11
- var _sharedUi = require("@buoy-gg/shared-ui");
12
- var _floatingToolsCore = require("@buoy-gg/floating-tools-core");
13
- var _DefaultConfigContext = require("./DefaultConfigContext.js");
14
- var _AppIcon = require("./AppIcon");
15
- var _jsxRuntime = require("react/jsx-runtime");
16
- const STORAGE_KEY = "@react_buoy_dev_tools_settings";
17
- const MAX_DIAL_SLOTS = 6;
18
- const enforceDialLimit = dialTools => {
19
- let remaining = MAX_DIAL_SLOTS;
20
- const limited = {};
21
- for (const [id, enabled] of Object.entries(dialTools)) {
22
- if (enabled && remaining > 0) {
23
- limited[id] = true;
24
- remaining -= 1;
25
- } else {
26
- limited[id] = false;
27
- }
28
- }
29
- return limited;
30
- };
31
- const sanitizeFloating = (floating, allowedKeys) => {
32
- const {
33
- userStatus,
34
- environment,
35
- ...rest
36
- } = floating;
37
- const filteredEntries = allowedKeys ? Object.entries(rest).filter(([key]) => allowedKeys.includes(key)) : Object.entries(rest);
38
- return {
39
- ...Object.fromEntries(filteredEntries),
40
- environment: environment ?? false
41
- };
42
- };
43
- const mergeWithDefaults = (defaults, stored, options) => {
44
- if (!stored) return defaults;
45
- const combinedDial = {
46
- ...defaults.dialTools,
47
- ...(stored.dialTools ?? {})
48
- };
49
- const dialEntries = options?.allowedDialKeys ? Object.entries(combinedDial).filter(([key]) => options.allowedDialKeys?.includes(key)) : Object.entries(combinedDial);
50
- const mergedDial = enforceDialLimit(Object.fromEntries(dialEntries));
51
- return {
52
- dialTools: mergedDial,
53
- floatingTools: sanitizeFloating({
54
- ...defaults.floatingTools,
55
- ...(stored.floatingTools ?? {})
56
- }, options?.allowedFloatingKeys),
57
- globalSettings: {
58
- enableSharedModalDimensions: false,
59
- // Default to false
60
- expandableWindowControls: true,
61
- // Default to true
62
- ...(stored.globalSettings ?? {})
63
- }
64
- };
65
- };
66
-
67
- /**
68
- * Global settings that apply to all dev tools.
69
- * These settings override individual tool configurations.
70
- */
71
-
72
- /**
73
- * Serialized preferences that power the floating dev tools UI. Values persist across sessions
74
- * via AsyncStorage so teams can tailor which tools appear in the dial or floating row.
75
- */
76
-
77
- /**
78
- * The subset of InstalledApp the settings modal needs per tool. `icon`/`color`
79
- * let rows fall back to the tool's own glyph when getToolIcon() has no
80
- * night-tuned override for it.
81
- */
82
-
83
- /**
84
- * Generate default settings based on available apps and optional team default configuration.
85
- *
86
- * @param availableApps - List of available apps from auto-discovery
87
- * @param defaultFloatingTools - Optional array of tool IDs to enable by default in floating bubble
88
- * @param defaultDialTools - Optional array of tool IDs to enable by default in dial menu
89
- * If not provided, all dial-compatible tools are enabled by default (up to 6)
90
- */
91
- const generateDefaultSettings = (availableApps = [], defaultFloatingTools, defaultDialTools) => {
92
- const dialDefaults = {};
93
- const floatingDefaults = {};
94
-
95
- // Create sets for quick lookup of default-enabled tools
96
- // Cast to Set<string> to allow comparison with any tool ID (including custom tools)
97
- const enabledFloatingSet = new Set(defaultFloatingTools ?? []);
98
- const enabledDialSet = new Set(defaultDialTools ?? []);
99
-
100
- // If no defaultDialTools specified, auto-enable all dial-compatible tools
101
- const autoEnableDialTools = !defaultDialTools || defaultDialTools.length === 0;
102
- for (const app of availableApps) {
103
- const {
104
- id,
105
- slot = "both"
106
- } = app;
107
- if (slot === "dial" || slot === "both") {
108
- // Auto-enable if no defaults specified, otherwise check the set
109
- dialDefaults[id] = autoEnableDialTools ? true : enabledDialSet.has(id);
110
- }
111
- if (slot === "row" || slot === "both") {
112
- // Enable if in defaultFloatingTools, otherwise false
113
- floatingDefaults[id] = enabledFloatingSet.has(id);
114
- }
115
- }
116
- return {
117
- dialTools: enforceDialLimit(dialDefaults),
118
- floatingTools: {
119
- ...floatingDefaults,
120
- // Special: environment badge - check if 'environment' is in the floating defaults
121
- environment: enabledFloatingSet.has('environment')
122
- },
123
- globalSettings: {
124
- enableSharedModalDimensions: false,
125
- // Default to false - each modal has its own persistence
126
- expandableWindowControls: true // Default to true - expandable on touch devices
127
- }
128
- };
129
- };
130
-
131
- /**
132
- * Configurable modal surface that lets engineers pick which dev tools appear in the dial and
133
- * floating row. Persists preferences and enforces slot limits for a consistent UX.
134
- *
135
- * Styled in the "night" language (Everlights port — see shared-ui's
136
- * ui/night): section labels outside near-black cards, hairline-separated
137
- * rows, real switches, and a transparent header the star field runs through.
138
- */
139
- const DevToolsSettingsModal = ({
140
- visible,
141
- onClose,
142
- onSettingsChange,
143
- initialSettings,
144
- availableApps = [],
145
- storage = _sharedUi.persistentStorage,
146
- zIndex
147
- }) => {
148
- // Get team default configuration from context
149
- const {
150
- defaultFloatingTools,
151
- defaultDialTools
152
- } = (0, _DefaultConfigContext.useDefaultConfig)();
153
- const defaultSettings = (0, _react.useMemo)(() => generateDefaultSettings(availableApps, defaultFloatingTools, defaultDialTools), [availableApps, defaultFloatingTools, defaultDialTools]);
154
- const allowedDialKeys = (0, _react.useMemo)(() => Object.keys(defaultSettings.dialTools), [defaultSettings]);
155
- const allowedFloatingKeys = (0, _react.useMemo)(() => Object.keys(defaultSettings.floatingTools).filter(key => key !== "environment"), [defaultSettings]);
156
- const [settings, setSettings] = (0, _react.useState)(initialSettings || cachedSettings || defaultSettings);
157
- const [activeTab, setActiveTab] = (0, _react.useState)(cachedActiveTab ?? "floating");
158
- const [activeTabLoaded, setActiveTabLoaded] = (0, _react.useState)(cachedActiveTab !== null);
159
- const [expandedSettings, setExpandedSettings] = (0, _react.useState)(new Set());
160
- const [showLicenseModal, setShowLicenseModal] = (0, _react.useState)(false);
161
- /**
162
- * Tool icons are the expensive half of this modal: ~20 of them, each a
163
- * data-driven glyph that mounts one view per shape. Rendering them in the
164
- * first pass pushed the modal's first paint out to ~240ms, so the tap felt
165
- * dead. Holding them back a single frame lets the chrome and the tool rows
166
- * paint at ~100ms and the glyphs land during the entrance fade.
167
- *
168
- * There is no layout shift: `styles.toolIconSlot` is a fixed box, so it
169
- * reads as the icon's placeholder until filled.
170
- */
171
- const [iconsReady, setIconsReady] = (0, _react.useState)(false);
172
- (0, _react.useEffect)(() => {
173
- const frame = requestAnimationFrame(() => setIconsReady(true));
174
- return () => cancelAnimationFrame(frame);
175
- }, []);
176
-
177
- // null when external-sync isn't installed (or predates the status store);
178
- // "idle" until AutoExternalSync initializes — the row hides in both cases.
179
- const desktopSyncStatus = (0, _useDesktopSyncStatus.useDesktopSyncStatus)();
180
-
181
- // Load persisted active tab on mount
182
- (0, _react.useEffect)(() => {
183
- const loadActiveTab = async () => {
184
- try {
185
- const savedTab = await _sharedUi.persistentStorage.getItem(_sharedUi.devToolsStorageKeys.settings.activeTab());
186
- if (savedTab && ["floating", "settings", "pro"].includes(savedTab)) {
187
- const tab = savedTab;
188
- cachedActiveTab = tab;
189
- setActiveTab(prev => prev === tab ? prev : tab);
190
- }
191
- } catch (error) {
192
- // Failed to load active tab - use default
193
- } finally {
194
- setActiveTabLoaded(true);
195
- }
196
- };
197
- loadActiveTab();
198
- }, []);
199
-
200
- // Persist active tab when it changes
201
- (0, _react.useEffect)(() => {
202
- // Only persist after initial state is loaded to avoid overwriting with default
203
- if (!activeTabLoaded) return;
204
- _sharedUi.persistentStorage.setItem(_sharedUi.devToolsStorageKeys.settings.activeTab(), activeTab).catch(error => {
205
- // Failed to save active tab - continue without persistence
206
- console.warn("Failed to save settings active tab:", error);
207
- });
208
- }, [activeTab, activeTabLoaded]);
209
-
210
- // License hooks
211
- const useLicenseHook = (0, _sharedUi.getUseLicense)();
212
- const license = useLicenseHook?.();
213
- const isPro = license?.isPro ?? false;
214
- // A key is set but validation is failing. Without this the tab renders a bare
215
- // "Free" badge, which reads as "your key was rejected" when what actually
216
- // happened is that we never reached the license server. `errorKind` decides
217
- // which story to tell: only a transport failure gets the VPN/proxy advice — a
218
- // real verdict (suspended, expired) with that advice would send the user off
219
- // to fight their network over a key that was genuinely rejected.
220
- const licenseError = !isPro && license?.licenseKey ? license.error : null;
221
- const licenseErrorIsTransport = license?.errorKind === "transport";
222
- const [storageBackend, setStorageBackend] = (0, _react.useState)(cachedStorageBackend);
223
- const [isClearing, setIsClearing] = (0, _react.useState)(false);
224
- const [clearSuccess, setClearSuccess] = (0, _react.useState)(false);
225
- const [isStorageExpanded, setIsStorageExpanded] = (0, _react.useState)(false);
226
- const [savedKeys, setSavedKeys] = (0, _react.useState)([]);
227
- const [savedKeysLoading, setSavedKeysLoading] = (0, _react.useState)(false);
228
- const insets = (0, _sharedUi.useSafeAreaInsets)();
229
- const screenHeight = _reactNative.Dimensions.get("window").height;
230
- const screenWidth = _reactNative.Dimensions.get("window").width;
231
- const modalHeight = Math.floor(screenHeight * 0.33); // 1/3 of screen height
232
- const modalWidth = Math.min(screenWidth - 32, 400); // Modal width with padding
233
-
234
- const loadSettings = (0, _react.useCallback)(async () => {
235
- try {
236
- const savedSettings = await storage.getItem(STORAGE_KEY);
237
- if (savedSettings) {
238
- const parsed = JSON.parse(savedSettings);
239
- const merged = mergeWithDefaults(defaultSettings, parsed, {
240
- allowedDialKeys,
241
- allowedFloatingKeys
242
- });
243
- cachedSettings = merged;
244
- setSettings(prev => sameSettings(prev, merged) ? prev : merged);
245
- return;
246
- }
247
- cachedSettings = defaultSettings;
248
- setSettings(prev => sameSettings(prev, defaultSettings) ? prev : defaultSettings);
249
- } catch (error) {
250
- console.error("Failed to load dev tools settings:", error);
251
- setSettings(defaultSettings);
252
- }
253
- }, [defaultSettings, allowedDialKeys, allowedFloatingKeys, storage]);
254
- (0, _react.useEffect)(() => {
255
- loadSettings();
256
- }, [loadSettings]);
257
-
258
- // Load storage backend type
259
- (0, _react.useEffect)(() => {
260
- (0, _sharedUi.getStorageBackendType)().then(backend => {
261
- cachedStorageBackend = backend;
262
- setStorageBackend(prev => prev === backend ? prev : backend);
263
- });
264
- }, []);
265
-
266
- // Load saved keys when storage card is expanded
267
- (0, _react.useEffect)(() => {
268
- if (isStorageExpanded) {
269
- setSavedKeysLoading(true);
270
- _sharedUi.persistentStorage.getAllKeys().then(keys => {
271
- setSavedKeys(keys.sort());
272
- }).catch(() => {
273
- setSavedKeys([]);
274
- }).finally(() => {
275
- setSavedKeysLoading(false);
276
- });
277
- }
278
- }, [isStorageExpanded]);
279
- const saveSettings = async newSettings => {
280
- try {
281
- const limitedSettings = {
282
- ...newSettings,
283
- dialTools: enforceDialLimit(newSettings.dialTools)
284
- };
285
- await storage.setItem(STORAGE_KEY, JSON.stringify(limitedSettings));
286
- cachedSettings = limitedSettings;
287
- setSettings(limitedSettings);
288
- onSettingsChange?.(limitedSettings);
289
- // Notify listeners (e.g., floating bubble) to refresh immediately
290
- _settingsBus.settingsBus.emit(limitedSettings);
291
- } catch (error) {
292
- console.error("Failed to save dev tools settings:", error);
293
- }
294
- };
295
- const toggleFloatingTool = tool => {
296
- const newSettings = {
297
- ...settings,
298
- floatingTools: {
299
- ...settings.floatingTools,
300
- [tool]: !settings.floatingTools[tool]
301
- }
302
- };
303
- saveSettings(newSettings);
304
- };
305
- const toggleGlobalSetting = setting => {
306
- const newSettings = {
307
- ...settings,
308
- globalSettings: {
309
- ...settings.globalSettings,
310
- [setting]: !settings.globalSettings?.[setting]
311
- }
312
- };
313
- saveSettings(newSettings);
314
- };
315
- const handleClearStorage = async () => {
316
- setIsClearing(true);
317
- setClearSuccess(false);
318
- try {
319
- await _sharedUi.persistentStorage.clear();
320
- setClearSuccess(true);
321
- // Reset settings to defaults after clearing
322
- setSettings(defaultSettings);
323
- if (storage !== _sharedUi.persistentStorage) await storage.setItem(STORAGE_KEY, JSON.stringify(defaultSettings));
324
- onSettingsChange?.(defaultSettings);
325
- _settingsBus.settingsBus.emit(defaultSettings);
326
- // Reset success state after 2 seconds
327
- setTimeout(() => setClearSuccess(false), 2000);
328
- } catch (error) {
329
- console.error("Failed to clear storage:", error);
330
- } finally {
331
- setIsClearing(false);
332
- }
333
- };
334
-
335
- // Modal is fixed to bottom sheet mode
336
- const handleModeChange = (0, _react.useCallback)(_mode => {
337
- // Mode changes handled by JsModal
338
- }, []);
339
- const getToolDescription = tool => {
340
- // Get description from availableApps
341
- const app = availableApps.find(a => a.id === tool);
342
- if (app?.description) {
343
- return app.description;
344
- }
345
- if (tool === "environment") {
346
- return "Environment badge.";
347
- }
348
- return "";
349
- };
350
- const getToolLabel = tool => {
351
- if (tool === "environment") {
352
- return "Env Badge";
353
- }
354
- const app = availableApps.find(a => a.id === tool);
355
- return app?.name ?? tool.toUpperCase().replace(/_/g, " ");
356
- };
357
- const getToolIcon = tool => {
358
- if (!iconsReady) return null;
359
- switch (tool) {
360
- case "query":
361
- return /*#__PURE__*/(0, _jsxRuntime.jsx)(_floatingToolsCore.QueryIcon, {
362
- size: 18
363
- });
364
- case "env":
365
- return /*#__PURE__*/(0, _jsxRuntime.jsx)(_floatingToolsCore.EnvIcon, {
366
- size: 18
367
- });
368
- case "sentry":
369
- return /*#__PURE__*/(0, _jsxRuntime.jsx)(_sharedUi.SentryIcon, {
370
- size: 18,
371
- color: "#9945FF"
372
- });
373
- case "storage":
374
- return /*#__PURE__*/(0, _jsxRuntime.jsx)(_floatingToolsCore.StorageIcon, {
375
- size: 18,
376
- bgColor: _sharedUi.night.color.surface
377
- });
378
- case "wifi":
379
- case "query-wifi-toggle":
380
- // Support both IDs for wifi toggle
381
- return /*#__PURE__*/(0, _jsxRuntime.jsx)(_sharedUi.WifiCircuitIcon, {
382
- size: 18,
383
- colorPreset: "green",
384
- strength: 4,
385
- noBackground: true
386
- });
387
- case "route-events":
388
- return /*#__PURE__*/(0, _jsxRuntime.jsx)(_floatingToolsCore.RoutesIcon, {
389
- size: 18,
390
- bgColor: _sharedUi.night.color.surface
391
- });
392
- case "network":
393
- return /*#__PURE__*/(0, _jsxRuntime.jsx)(_floatingToolsCore.NetworkIcon, {
394
- size: 18
395
- });
396
- case "environment":
397
- return /*#__PURE__*/(0, _jsxRuntime.jsx)(_floatingToolsCore.EnvIcon, {
398
- size: 18
399
- });
400
- case "debug-borders":
401
- return /*#__PURE__*/(0, _jsxRuntime.jsx)(_sharedUi.Layers, {
402
- size: 18,
403
- color: _sharedUi.night.color.accent
404
- });
405
- case "highlight-updates":
406
- return /*#__PURE__*/(0, _jsxRuntime.jsx)(_sharedUi.RenderCountIcon, {
407
- size: 18,
408
- color: _sharedUi.night.color.accent
409
- });
410
- case "highlight-updates-modal":
411
- return /*#__PURE__*/(0, _jsxRuntime.jsx)(_floatingToolsCore.HighlighterIcon, {
412
- size: 18
413
- });
414
- case "redux":
415
- return /*#__PURE__*/(0, _jsxRuntime.jsx)(_floatingToolsCore.ReduxIcon, {
416
- size: 18
417
- });
418
- case "image-overlay":
419
- return /*#__PURE__*/(0, _jsxRuntime.jsx)(_sharedUi.ImageOverlayIcon, {
420
- size: 18
421
- });
422
- case "events":
423
- return /*#__PURE__*/(0, _jsxRuntime.jsx)(_floatingToolsCore.EventsIcon, {
424
- size: 18
425
- });
426
- case "zustand":
427
- try {
428
- // @ts-ignore - Optional package
429
- const {
430
- ZustandIcon
431
- } = require("@buoy-gg/zustand");
432
- return /*#__PURE__*/(0, _jsxRuntime.jsx)(ZustandIcon, {
433
- size: 18
434
- });
435
- } catch {
436
- return /*#__PURE__*/(0, _jsxRuntime.jsx)(_sharedUi.Info, {
437
- size: 18,
438
- color: _sharedUi.night.color.textSecondary
439
- });
440
- }
441
- case "jotai":
442
- try {
443
- // @ts-ignore - Optional package
444
- const {
445
- JotaiIcon
446
- } = require("@buoy-gg/jotai");
447
- return /*#__PURE__*/(0, _jsxRuntime.jsx)(JotaiIcon, {
448
- size: 18
449
- });
450
- } catch {
451
- return /*#__PURE__*/(0, _jsxRuntime.jsx)(_sharedUi.Info, {
452
- size: 18,
453
- color: _sharedUi.night.color.textSecondary
454
- });
455
- }
456
- default:
457
- {
458
- // Tools without a night-tuned override (console, images, time
459
- // machine, perf monitor, custom toolkit tools, …) render their own
460
- // app icon — the same artwork the dial shows.
461
- const app = availableApps.find(a => a.id === tool);
462
- if (app?.icon != null) {
463
- return (0, _AppIcon.renderAppIcon)(app.icon, {
464
- slot: "row",
465
- size: 18,
466
- color: app.color
467
- });
468
- }
469
- return /*#__PURE__*/(0, _jsxRuntime.jsx)(_sharedUi.Info, {
470
- size: 18,
471
- color: _sharedUi.night.color.textSecondary
472
- });
473
- }
474
- }
475
- };
476
-
477
- /**
478
- * One tool row: glyph, name + one-line description, switch. Lives inside a
479
- * NightCard's hairline-separated rows.
480
- */
481
- const renderToolRow = (keyName, value, disabled, onToggle) => {
482
- const description = getToolDescription(keyName);
483
- return /*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNative.TouchableOpacity, {
484
- activeOpacity: disabled ? 1 : 0.7,
485
- onPress: () => !disabled && onToggle(),
486
- accessibilityLabel: getToolLabel(keyName),
487
- accessibilityRole: "button",
488
- style: [styles.toolRow, disabled && styles.rowDisabled],
489
- children: [/*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.View, {
490
- style: styles.toolIconSlot,
491
- children: getToolIcon(keyName)
492
- }), /*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNative.View, {
493
- style: styles.rowInfo,
494
- children: [/*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNative.Text, {
495
- style: styles.rowLabel,
496
- children: [getToolLabel(keyName), disabled ? " · max 6" : ""]
497
- }), description ? /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.Text, {
498
- style: styles.rowCaption,
499
- numberOfLines: 1,
500
- children: description
501
- }) : null]
502
- }), /*#__PURE__*/(0, _jsxRuntime.jsx)(_sharedUi.NightSwitch, {
503
- value: value,
504
- disabled: disabled,
505
- onValueChange: () => onToggle()
506
- })]
507
- }, keyName);
508
- };
509
-
510
- // Toggle expanded state for a setting card
511
- const toggleSettingExpanded = settingKey => {
512
- setExpandedSettings(prev => {
513
- const newSet = new Set(prev);
514
- if (newSet.has(settingKey)) {
515
- newSet.delete(settingKey);
516
- } else {
517
- newSet.add(settingKey);
518
- }
519
- return newSet;
520
- });
521
- };
522
-
523
- /**
524
- * One global-setting row: name + one-line hint, switch, and a tap-to-expand
525
- * body holding the full description and recommendation.
526
- */
527
- const renderGlobalSettingRow = (settingKey, label, shortDescription, fullDescription, recommendation) => {
528
- const value = settings.globalSettings?.[settingKey] ?? false;
529
- const isExpanded = expandedSettings.has(settingKey);
530
- return /*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNative.View, {
531
- children: [/*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNative.TouchableOpacity, {
532
- activeOpacity: 0.7,
533
- onPress: () => toggleSettingExpanded(settingKey),
534
- accessibilityLabel: label,
535
- style: styles.settingRow,
536
- children: [/*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNative.View, {
537
- style: styles.rowInfo,
538
- children: [/*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.Text, {
539
- style: styles.rowLabel,
540
- children: label
541
- }), /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.Text, {
542
- style: styles.rowCaption,
543
- numberOfLines: isExpanded ? 0 : 1,
544
- children: shortDescription
545
- })]
546
- }), /*#__PURE__*/(0, _jsxRuntime.jsx)(_sharedUi.NightSwitch, {
547
- value: value,
548
- onValueChange: () => toggleGlobalSetting(settingKey)
549
- })]
550
- }), isExpanded && /*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNative.View, {
551
- style: styles.settingRowBody,
552
- children: [/*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.Text, {
553
- style: styles.settingRowBodyText,
554
- children: fullDescription
555
- }), /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.Text, {
556
- style: styles.settingRowBodyHint,
557
- children: recommendation
558
- })]
559
- })]
560
- }, settingKey);
561
- };
562
-
563
- /** Section = uppercase label, card, optional footnote(s) under it. */
564
- const renderSection = (label, card, footnotes) => /*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNative.View, {
565
- children: [/*#__PURE__*/(0, _jsxRuntime.jsx)(_sharedUi.NightSectionLabel, {
566
- children: label
567
- }), card, footnotes]
568
- });
569
- const storageBadge = storageBackend === "filesystem" ? /*#__PURE__*/(0, _jsxRuntime.jsx)(_sharedUi.NightBadge, {
570
- label: "File System",
571
- tone: "accent"
572
- }) : storageBackend === "asyncstorage" ? /*#__PURE__*/(0, _jsxRuntime.jsx)(_sharedUi.NightBadge, {
573
- label: "Async Storage",
574
- tone: "warning"
575
- }) : storageBackend === "localstorage" ? /*#__PURE__*/(0, _jsxRuntime.jsx)(_sharedUi.NightBadge, {
576
- label: "Local Storage",
577
- tone: "accent"
578
- }) : storageBackend === "memory" ? /*#__PURE__*/(0, _jsxRuntime.jsx)(_sharedUi.NightBadge, {
579
- label: "Memory",
580
- tone: "danger"
581
- }) : /*#__PURE__*/(0, _jsxRuntime.jsx)(_sharedUi.NightBadge, {
582
- label: "Loading\u2026",
583
- tone: "neutral"
584
- });
585
- const renderContent = () => /*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNative.View, {
586
- style: styles.container,
587
- children: [/*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNative.ScrollView, {
588
- style: styles.scrollContent,
589
- showsVerticalScrollIndicator: false,
590
- contentContainerStyle: styles.scrollContainer,
591
- children: [activeTab === "floating" && /*#__PURE__*/(0, _jsxRuntime.jsx)(_jsxRuntime.Fragment, {
592
- children: renderSection("Floating Tools", /*#__PURE__*/(0, _jsxRuntime.jsx)(_sharedUi.NightCard, {
593
- glass: true,
594
- children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_sharedUi.NightRows, {
595
- children: Object.entries(settings.floatingTools).map(([key, value]) => renderToolRow(key, value, false, () => toggleFloatingTool(key)))
596
- })
597
- }), /*#__PURE__*/(0, _jsxRuntime.jsx)(_sharedUi.NightFootnote, {
598
- children: "Tools switched on here appear in the floating bubble row."
599
- }))
600
- }), activeTab === "settings" && /*#__PURE__*/(0, _jsxRuntime.jsxs)(_jsxRuntime.Fragment, {
601
- children: [renderSection("Background", /*#__PURE__*/(0, _jsxRuntime.jsx)(_sharedUi.NightCard, {
602
- glass: true,
603
- padded: true,
604
- children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_sharedUi.BackgroundSwitcher, {
605
- embedded: true
606
- })
607
- })), renderSection("Storage", /*#__PURE__*/(0, _jsxRuntime.jsxs)(_sharedUi.NightCard, {
608
- glass: true,
609
- children: [/*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNative.TouchableOpacity, {
610
- activeOpacity: 0.7,
611
- onPress: () => setIsStorageExpanded(!isStorageExpanded),
612
- accessibilityLabel: "Storage Type",
613
- style: styles.settingRow,
614
- children: [/*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.View, {
615
- style: styles.rowInfo,
616
- children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.Text, {
617
- style: styles.rowLabel,
618
- children: "Storage Type"
619
- })
620
- }), storageBadge, isStorageExpanded ? /*#__PURE__*/(0, _jsxRuntime.jsx)(_sharedUi.ChevronDown, {
621
- size: 16,
622
- color: _sharedUi.night.color.textTertiary
623
- }) : /*#__PURE__*/(0, _jsxRuntime.jsx)(_sharedUi.ChevronRightIcon, {
624
- size: 16,
625
- color: _sharedUi.night.color.textTertiary
626
- })]
627
- }), isStorageExpanded && /*#__PURE__*/(0, _jsxRuntime.jsxs)(_jsxRuntime.Fragment, {
628
- children: [/*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNative.View, {
629
- style: styles.settingRowBody,
630
- children: [/*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.Text, {
631
- style: styles.settingRowBodyText,
632
- children: storageBackend === "filesystem" ? "Settings persist independently and survive AsyncStorage.clear() calls during logout." : storageBackend === "asyncstorage" ? "Settings may be lost if AsyncStorage is cleared during logout." : storageBackend === "localstorage" ? "Settings are saved in this browser. Clearing site data removes them." : storageBackend === "memory" ? "Settings are stored in memory only and will be lost on app restart." : "Checking storage backend…"
633
- }), storageBackend === "asyncstorage" && /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.Text, {
634
- style: [styles.settingRowBodyText, styles.bodyWarning],
635
- children: "Install expo-file-system to persist settings through logout flows."
636
- }), storageBackend === "memory" && /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.Text, {
637
- style: [styles.settingRowBodyText, styles.bodyDanger],
638
- children: "No persistent storage available \u2014 install expo-file-system (best) or @react-native-async-storage/async-storage."
639
- })]
640
- }), /*#__PURE__*/(0, _jsxRuntime.jsx)(_sharedUi.NightSeparator, {}), /*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNative.View, {
641
- style: styles.storageExpanded,
642
- children: [/*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNative.View, {
643
- style: styles.storageExpandedHeader,
644
- children: [/*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.Text, {
645
- style: styles.storageExpandedTitle,
646
- children: "SAVED SETTINGS"
647
- }), /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.Text, {
648
- style: styles.storageExpandedCount,
649
- children: savedKeysLoading ? "…" : `${savedKeys.length} keys`
650
- })]
651
- }), savedKeysLoading ? /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.Text, {
652
- style: styles.storageKeyEmpty,
653
- children: "Loading\u2026"
654
- }) : savedKeys.length === 0 ? /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.Text, {
655
- style: styles.storageKeyEmpty,
656
- children: "No settings saved yet"
657
- }) : /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.ScrollView, {
658
- style: styles.storageKeysList,
659
- nestedScrollEnabled: true,
660
- showsVerticalScrollIndicator: true,
661
- children: savedKeys.map(key => /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.View, {
662
- style: styles.storageKeyItem,
663
- children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.Text, {
664
- style: styles.storageKeyText,
665
- numberOfLines: 1,
666
- children: key.replace("@react_buoy_", "")
667
- })
668
- }, key))
669
- })]
670
- }), /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.View, {
671
- style: styles.cardButtonWrap,
672
- children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_sharedUi.NightButton, {
673
- label: clearSuccess ? "Cleared" : isClearing ? "Clearing…" : "Clear All Settings",
674
- variant: clearSuccess ? "secondary" : "destructive",
675
- size: "md",
676
- disabled: isClearing,
677
- onPress: handleClearStorage,
678
- icon: clearSuccess ? /*#__PURE__*/(0, _jsxRuntime.jsx)(_sharedUi.CheckCircle2, {
679
- size: 15,
680
- color: _sharedUi.night.color.accent
681
- }) : /*#__PURE__*/(0, _jsxRuntime.jsx)(_sharedUi.Trash2, {
682
- size: 15,
683
- color: isClearing ? _sharedUi.night.color.textTertiary : _sharedUi.night.color.danger
684
- })
685
- })
686
- })]
687
- })]
688
- })), desktopSyncStatus && desktopSyncStatus.state !== "idle" && renderSection("Desktop Sync", /*#__PURE__*/(0, _jsxRuntime.jsxs)(_sharedUi.NightCard, {
689
- glass: true,
690
- children: [/*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNative.TouchableOpacity, {
691
- activeOpacity: 0.7,
692
- onPress: () => toggleSettingExpanded("desktopSync"),
693
- accessibilityLabel: "Buoy Desktop",
694
- style: styles.settingRow,
695
- children: [/*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.View, {
696
- style: styles.rowInfo,
697
- children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.Text, {
698
- style: styles.rowLabel,
699
- children: "Buoy Desktop"
700
- })
701
- }), desktopSyncStatus.state === "connected" ? /*#__PURE__*/(0, _jsxRuntime.jsx)(_sharedUi.NightBadge, {
702
- label: "Connected",
703
- tone: "accent"
704
- }) : desktopSyncStatus.state === "connecting" ? /*#__PURE__*/(0, _jsxRuntime.jsx)(_sharedUi.NightBadge, {
705
- label: "Connecting\u2026",
706
- tone: "neutral"
707
- }) : /*#__PURE__*/(0, _jsxRuntime.jsx)(_sharedUi.NightBadge, {
708
- label: "Retrying",
709
- tone: "warning"
710
- }), expandedSettings.has("desktopSync") ? /*#__PURE__*/(0, _jsxRuntime.jsx)(_sharedUi.ChevronDown, {
711
- size: 16,
712
- color: _sharedUi.night.color.textTertiary
713
- }) : /*#__PURE__*/(0, _jsxRuntime.jsx)(_sharedUi.ChevronRightIcon, {
714
- size: 16,
715
- color: _sharedUi.night.color.textTertiary
716
- })]
717
- }), expandedSettings.has("desktopSync") && /*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNative.View, {
718
- style: styles.settingRowBody,
719
- children: [/*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNative.Text, {
720
- style: styles.settingRowBodyText,
721
- children: [desktopSyncStatus.state === "connected" ? "Streaming tool data to Buoy Desktop at " : "Trying to reach Buoy Desktop at ", /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.Text, {
722
- style: styles.footnoteMono,
723
- children: desktopSyncStatus.targetURL ?? "(unknown URL)"
724
- }), desktopSyncStatus.state !== "connected" && " — is the desktop app running? Override with the externalSync socketURL option if it runs elsewhere."]
725
- }), desktopSyncStatus.state === "retrying" && desktopSyncStatus.lastError && /*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNative.Text, {
726
- style: [styles.settingRowBodyText, styles.bodyWarning],
727
- children: ["Last error: ", desktopSyncStatus.lastError]
728
- })]
729
- })]
730
- })), renderSection("Modal Behavior", /*#__PURE__*/(0, _jsxRuntime.jsx)(_sharedUi.NightCard, {
731
- glass: true,
732
- children: /*#__PURE__*/(0, _jsxRuntime.jsxs)(_sharedUi.NightRows, {
733
- children: [renderGlobalSettingRow("enableSharedModalDimensions", "Shared Modal Size", "Sync dimensions across all tools", "When enabled, all tool modals will share the same size and position. Resizing one modal will affect all others. When disabled, each tool remembers its own size and position independently.", "Keep OFF for the best experience. This allows you to customize each tool's modal size separately."), _reactNative.Platform.OS !== "web" ? renderGlobalSettingRow("expandableWindowControls", "Expand Controls", "iPad-style expandable window buttons", "When enabled, the window control buttons (minimize, toggle mode, close) start as small dots and expand into larger, easy-to-tap buttons when pressed. When disabled, buttons are directly tappable at their small size.", "Keep ON for touch devices where the small buttons are hard to press. Turn OFF if you prefer direct single-tap access.") : null]
734
- })
735
- }))]
736
- }), activeTab === "pro" && /*#__PURE__*/(0, _jsxRuntime.jsxs)(_jsxRuntime.Fragment, {
737
- children: [renderSection("License", /*#__PURE__*/(0, _jsxRuntime.jsx)(_sharedUi.NightCard, {
738
- glass: true,
739
- children: /*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNative.View, {
740
- style: styles.settingRow,
741
- children: [/*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.View, {
742
- style: styles.rowInfo,
743
- children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.Text, {
744
- style: styles.rowLabel,
745
- children: "License Status"
746
- })
747
- }), /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.View, {
748
- testID: "buoy-settings-license-status",
749
- accessibilityLabel: isPro ? "License: Active" : "License: Free",
750
- children: isPro ? /*#__PURE__*/(0, _jsxRuntime.jsx)(_sharedUi.NightBadge, {
751
- label: "Active",
752
- tone: "accent"
753
- }) : /*#__PURE__*/(0, _jsxRuntime.jsx)(_sharedUi.NightBadge, {
754
- label: "Free",
755
- tone: "neutral"
756
- })
757
- })]
758
- })
759
- }), /*#__PURE__*/(0, _jsxRuntime.jsx)(_sharedUi.NightFootnote, {
760
- children: isPro ? "You have full access to all Buoy DevTools features." : licenseError ? licenseErrorIsTransport ? `Couldn't reach the license server (${licenseError}). A VPN or corporate proxy can block buoy.gg — turn it off and reload. Your key hasn't been rejected.` : `License check failed: ${licenseError}.` : "Upgrade to Pro to unlock all features and support development."
761
- })), !isPro && /*#__PURE__*/(0, _jsxRuntime.jsxs)(_jsxRuntime.Fragment, {
762
- children: [renderSection("Pro Features", /*#__PURE__*/(0, _jsxRuntime.jsx)(_sharedUi.NightCard, {
763
- glass: true,
764
- children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_sharedUi.NightRows, {
765
- children: ["Advanced Settings", "Priority Support"].map(feature => /*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNative.View, {
766
- style: styles.featureRow,
767
- children: [/*#__PURE__*/(0, _jsxRuntime.jsx)(_sharedUi.CheckCircle2, {
768
- size: 16,
769
- color: _sharedUi.night.color.accent
770
- }), /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.Text, {
771
- style: styles.rowLabel,
772
- children: feature
773
- })]
774
- }, feature))
775
- })
776
- })), /*#__PURE__*/(0, _jsxRuntime.jsx)(_sharedUi.NightButton, {
777
- label: "Upgrade to Pro",
778
- variant: "primary",
779
- size: "lg",
780
- onPress: () => setShowLicenseModal(true)
781
- })]
782
- })]
783
- })]
784
- }), /*#__PURE__*/(0, _jsxRuntime.jsx)(_sharedUi.LicenseEntryModal, {
785
- visible: showLicenseModal,
786
- onClose: () => setShowLicenseModal(false),
787
- onSuccess: () => setShowLicenseModal(false)
788
- })]
789
- });
790
- return /*#__PURE__*/(0, _jsxRuntime.jsx)(_sharedUi.JsModal, {
791
- visible: visible,
792
- onClose: onClose,
793
- zIndex: zIndex,
794
- variant: "night",
795
- header: {
796
- showToggleButton: false,
797
- customContent: /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.View, {
798
- style: styles.headerRow,
799
- children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_sharedUi.NightSegmented, {
800
- glass: true,
801
- tabs: [{
802
- key: "floating",
803
- label: "Floating"
804
- }, {
805
- key: "settings",
806
- label: "Settings"
807
- }, {
808
- key: "pro",
809
- label: "Pro"
810
- }],
811
- activeKey: activeTab,
812
- onChange: tab => setActiveTab(tab)
813
- })
814
- })
815
- },
816
- initialMode: "bottomSheet",
817
- onModeChange: handleModeChange,
818
- persistenceKey: _sharedUi.devToolsStorageKeys.settings.root(),
819
- enablePersistence: true,
820
- maxHeight: screenHeight - insets.top,
821
- initialHeight: modalHeight,
822
- initialFloatingPosition: {
823
- x: (screenWidth - modalWidth) / 2,
824
- y: insets.top + 20
825
- },
826
- enableGlitchEffects: true,
827
- children: renderContent()
828
- });
829
- };
830
-
831
- // Basic default settings for the hook (when apps are not available and no defaults configured)
832
- exports.DevToolsSettingsModal = DevToolsSettingsModal;
833
- const basicDefaultSettings = {
834
- dialTools: {},
835
- floatingTools: {
836
- environment: false
837
- },
838
- globalSettings: {
839
- enableSharedModalDimensions: false
840
- }
841
- };
842
-
843
- /**
844
- * Creates default settings from the team configuration arrays.
845
- * Used by the hook when no stored settings exist.
846
- *
847
- * Note: This function doesn't have access to availableApps, so it can only
848
- * enable tools that are explicitly listed in the config arrays.
849
- * For auto-enabling all dial tools, the generateDefaultSettings function
850
- * (which has access to availableApps) handles that case.
851
- */
852
- const createDefaultsFromConfig = (defaultFloatingTools, defaultDialTools) => {
853
- const floatingSet = new Set(defaultFloatingTools ?? []);
854
- const dialSet = new Set(defaultDialTools ?? []);
855
-
856
- // Build dial tools record from defaults
857
- // Note: If no defaults specified, dialTools will be empty here
858
- // but generateDefaultSettings will auto-enable all tools when it has access to availableApps
859
- const dialTools = {};
860
- for (const id of dialSet) {
861
- dialTools[id] = true;
862
- }
863
-
864
- // Build floating tools record from defaults
865
- const floatingTools = {
866
- environment: floatingSet.has('environment')
867
- };
868
- for (const id of floatingSet) {
869
- if (id !== 'environment') {
870
- floatingTools[id] = true;
871
- }
872
- }
873
- return {
874
- dialTools: enforceDialLimit(dialTools),
875
- floatingTools,
876
- globalSettings: {
877
- enableSharedModalDimensions: false
878
- }
879
- };
880
- };
881
-
882
- /**
883
- * Convenience hook for accessing persisted dev tools settings. Subscribes to the internal
884
- * event bus so all surfaces stay in sync when the modal saves new preferences.
885
- *
886
- * When no saved settings exist, the hook uses the default configuration from
887
- * the DefaultConfigProvider (if available) to determine initial tool states.
888
- */
889
- /**
890
- * Session cache for the values the settings modal loads asynchronously on mount.
891
- *
892
- * Without it every open renders three times: once with defaults, then again as
893
- * each of the persisted reads (settings, active tab, storage backend) resolves —
894
- * and each of those re-renders rebuilds the whole tool list. The values cannot
895
- * change behind our back (writes go through this module, and settingsBus
896
- * broadcasts them), so after the first open we can render the real values
897
- * immediately and only re-render if a read actually came back different.
898
- */
899
- let cachedSettings = null;
900
- let cachedActiveTab = null;
901
- let cachedStorageBackend = null;
902
-
903
- /** Cheap structural equality — these objects are small and JSON-safe. */
904
- const sameSettings = (a, b) => JSON.stringify(a) === JSON.stringify(b);
905
-
906
- // Every surface that changes settings broadcasts on the bus, so listening here
907
- // keeps the cache authoritative rather than merely last-seen — otherwise a
908
- // change made while the modal was unmounted would show stale for one frame.
909
- // Registered for the app's lifetime on purpose; there is nothing to unsubscribe.
910
- _settingsBus.settingsBus.addListener(payload => {
911
- if (payload) cachedSettings = payload;
912
- });
913
- const useDevToolsSettings = () => {
914
- // Get team default configuration from context
915
- const {
916
- defaultFloatingTools,
917
- defaultDialTools
918
- } = (0, _DefaultConfigContext.useDefaultConfig)();
919
-
920
- // Compute the effective defaults based on team configuration
921
- const effectiveDefaults = (0, _react.useMemo)(() => {
922
- if (!defaultFloatingTools && !defaultDialTools) {
923
- return basicDefaultSettings;
924
- }
925
- return createDefaultsFromConfig(defaultFloatingTools, defaultDialTools);
926
- }, [defaultFloatingTools, defaultDialTools]);
927
- const [settings, setSettings] = (0, _react.useState)(effectiveDefaults);
928
- const loadSettings = (0, _react.useCallback)(async () => {
929
- try {
930
- const savedSettings = await _sharedUi.persistentStorage.getItem(STORAGE_KEY);
931
- if (savedSettings) {
932
- const parsed = JSON.parse(savedSettings);
933
- const merged = mergeWithDefaults(effectiveDefaults, parsed);
934
- setSettings(merged);
935
- return;
936
- }
937
- // No saved settings - use the effective defaults (including team config)
938
- setSettings(effectiveDefaults);
939
- } catch (error) {
940
- console.error("Failed to load dev tools settings:", error);
941
- setSettings(effectiveDefaults);
942
- }
943
- }, [effectiveDefaults]);
944
- (0, _react.useEffect)(() => {
945
- loadSettings();
946
- // Subscribe to settings changes
947
- const unsub = _settingsBus.settingsBus.addListener(payload => {
948
- try {
949
- if (payload) {
950
- setSettings(payload);
951
- }
952
- } catch (err) {
953
- // Listener errors are intentionally swallowed to avoid breaking subscribers
954
- }
955
- });
956
- return () => {
957
- unsub();
958
- };
959
- }, [loadSettings]);
960
-
961
- // Refresh settings when component using this hook becomes visible
962
- const refreshSettings = (0, _react.useCallback)(() => {
963
- loadSettings();
964
- }, [loadSettings]);
965
- return {
966
- settings,
967
- refreshSettings
968
- };
969
- };
970
- exports.useDevToolsSettings = useDevToolsSettings;
971
- const styles = _reactNative.StyleSheet.create({
972
- container: {
973
- flex: 1,
974
- // Transparent so JsModal's night star field shows through everything.
975
- backgroundColor: "transparent"
976
- },
977
- // Header — the segmented control. The window controls are cleared
978
- // vertically by JsModal's drag-indicator strip, so this runs full width.
979
- headerRow: {
980
- flexDirection: "row",
981
- alignItems: "center",
982
- paddingLeft: _sharedUi.night.gutter,
983
- paddingRight: _sharedUi.night.gutter,
984
- paddingBottom: 8
985
- },
986
- // Scroll content — labeled groups on a 24pt rhythm (Everlights create screen)
987
- scrollContent: {
988
- flex: 1
989
- },
990
- scrollContainer: {
991
- paddingHorizontal: _sharedUi.night.gutter,
992
- paddingTop: 8,
993
- paddingBottom: 24,
994
- gap: _sharedUi.night.groupGap
995
- },
996
- // Rows
997
- toolRow: {
998
- flexDirection: "row",
999
- alignItems: "center",
1000
- gap: 12,
1001
- paddingHorizontal: _sharedUi.night.rowPadH,
1002
- paddingVertical: 12
1003
- },
1004
- settingRow: {
1005
- flexDirection: "row",
1006
- alignItems: "center",
1007
- gap: 10,
1008
- paddingHorizontal: _sharedUi.night.rowPadH,
1009
- paddingVertical: _sharedUi.night.rowPadV,
1010
- minHeight: 52
1011
- },
1012
- featureRow: {
1013
- flexDirection: "row",
1014
- alignItems: "center",
1015
- gap: 10,
1016
- paddingHorizontal: _sharedUi.night.rowPadH,
1017
- paddingVertical: 12
1018
- },
1019
- rowDisabled: {
1020
- opacity: 0.4
1021
- },
1022
- toolIconSlot: {
1023
- width: 24,
1024
- alignItems: "center"
1025
- },
1026
- rowInfo: {
1027
- flex: 1,
1028
- gap: 2
1029
- },
1030
- rowLabel: {
1031
- color: _sharedUi.night.color.text,
1032
- fontSize: _sharedUi.night.font.row,
1033
- fontWeight: "500"
1034
- },
1035
- rowCaption: {
1036
- color: _sharedUi.night.color.textTertiary,
1037
- fontSize: _sharedUi.night.font.label
1038
- },
1039
- // Expanded body under a global-setting row
1040
- settingRowBody: {
1041
- paddingHorizontal: _sharedUi.night.rowPadH,
1042
- paddingBottom: _sharedUi.night.rowPadV,
1043
- gap: 6
1044
- },
1045
- settingRowBodyText: {
1046
- color: _sharedUi.night.color.textSecondary,
1047
- fontSize: _sharedUi.night.font.caption,
1048
- lineHeight: _sharedUi.night.font.caption * 1.45
1049
- },
1050
- settingRowBodyHint: {
1051
- color: _sharedUi.night.color.textTertiary,
1052
- fontSize: _sharedUi.night.font.caption,
1053
- lineHeight: _sharedUi.night.font.caption * 1.45
1054
- },
1055
- bodyWarning: {
1056
- color: _sharedUi.night.color.warning
1057
- },
1058
- bodyDanger: {
1059
- color: _sharedUi.night.color.danger
1060
- },
1061
- // Buttons that live inside a card
1062
- cardButtonWrap: {
1063
- paddingHorizontal: _sharedUi.night.cardPad,
1064
- paddingTop: 10,
1065
- paddingBottom: _sharedUi.night.cardPad
1066
- },
1067
- // Storage expanded key list
1068
- storageExpanded: {
1069
- paddingHorizontal: _sharedUi.night.rowPadH,
1070
- paddingVertical: 12,
1071
- gap: 8
1072
- },
1073
- storageExpandedHeader: {
1074
- flexDirection: "row",
1075
- alignItems: "center"
1076
- },
1077
- storageExpandedTitle: {
1078
- flex: 1,
1079
- color: _sharedUi.night.color.textSecondary,
1080
- fontSize: _sharedUi.night.font.micro,
1081
- fontWeight: "600",
1082
- letterSpacing: 0.5
1083
- },
1084
- storageExpandedCount: {
1085
- color: _sharedUi.night.color.textTertiary,
1086
- fontSize: _sharedUi.night.font.micro
1087
- },
1088
- storageKeysList: {
1089
- maxHeight: 150
1090
- },
1091
- storageKeyItem: {
1092
- backgroundColor: _sharedUi.night.color.glassElevated,
1093
- borderRadius: _sharedUi.night.radius.segment,
1094
- paddingHorizontal: 10,
1095
- paddingVertical: 7,
1096
- marginBottom: 4
1097
- },
1098
- storageKeyText: {
1099
- color: _sharedUi.night.color.textSecondary,
1100
- fontSize: _sharedUi.night.font.micro,
1101
- fontFamily: _sharedUi.monoFont
1102
- },
1103
- storageKeyEmpty: {
1104
- color: _sharedUi.night.color.textTertiary,
1105
- fontSize: _sharedUi.night.font.caption,
1106
- fontStyle: "italic"
1107
- },
1108
- // Footnote inline code
1109
- footnoteMono: {
1110
- fontFamily: _sharedUi.monoFont,
1111
- fontSize: _sharedUi.night.font.label,
1112
- color: _sharedUi.night.color.textSecondary
1113
- }
1114
- });
1
+ "use strict";Object.defineProperty(exports,"__esModule",{value:true});exports.useDevToolsSettings=exports.DevToolsSettingsModal=void 0;var _react=require("react");var _reactNative=require("react-native");var _settingsBus=require("./settingsBus.js");var _useDesktopSyncStatus=require("./useDesktopSyncStatus");var _sharedUi=require("@buoy-gg/shared-ui");var _floatingToolsCore=require("@buoy-gg/floating-tools-core");var _DefaultConfigContext=require("./DefaultConfigContext.js");var _AppIcon=require("./AppIcon");var _jsxRuntime=require("react/jsx-runtime");const STORAGE_KEY="@react_buoy_dev_tools_settings";const MAX_DIAL_SLOTS=6;const enforceDialLimit=r=>{let a=MAX_DIAL_SLOTS;const n={};for(const[c,s]of Object.entries(r)){if(s&&a>0){n[c]=true;a-=1}else{n[c]=false}}return n};const sanitizeFloating=(r,a)=>{const{userStatus:n,environment:c,...s}=r;const l=a?Object.entries(s).filter(([d])=>a.includes(d)):Object.entries(s);return{...Object.fromEntries(l),environment:c??false}};const mergeWithDefaults=(r,a,n)=>{if(!a)return r;const c={...r.dialTools,...a.dialTools??{}};const s=n?.allowedDialKeys?Object.entries(c).filter(([d])=>n.allowedDialKeys?.includes(d)):Object.entries(c);const l=enforceDialLimit(Object.fromEntries(s));return{dialTools:l,floatingTools:sanitizeFloating({...r.floatingTools,...a.floatingTools??{}},n?.allowedFloatingKeys),globalSettings:{enableSharedModalDimensions:false,expandableWindowControls:true,...a.globalSettings??{}}}};const generateDefaultSettings=(r=[],a,n)=>{const c={};const s={};const l=new Set(a??[]);const d=new Set(n??[]);const g=!n||n.length===0;for(const x of r){const{id:i,slot:S="both"}=x;if(S==="dial"||S==="both"){c[i]=g?true:d.has(i)}if(S==="row"||S==="both"){s[i]=l.has(i)}}return{dialTools:enforceDialLimit(c),floatingTools:{...s,environment:l.has("environment")},globalSettings:{enableSharedModalDimensions:false,expandableWindowControls:true}}};const DevToolsSettingsModal=({visible:r,onClose:a,onSettingsChange:n,initialSettings:c,availableApps:s=[],storage:l=_sharedUi.persistentStorage,zIndex:d})=>{const{defaultFloatingTools:g,defaultDialTools:x}=(0,_DefaultConfigContext.useDefaultConfig)();const i=(0,_react.useMemo)(()=>generateDefaultSettings(s,g,x),[s,g,x]);const S=(0,_react.useMemo)(()=>Object.keys(i.dialTools),[i]);const R=(0,_react.useMemo)(()=>Object.keys(i.floatingTools).filter(e=>e!=="environment"),[i]);const[f,b]=(0,_react.useState)(c||cachedSettings||i);const[w,F]=(0,_react.useState)(cachedActiveTab??"floating");const[N,G]=(0,_react.useState)(cachedActiveTab!==null);const[C,Y]=(0,_react.useState)(new Set);const[$,I]=(0,_react.useState)(false);const[Q,X]=(0,_react.useState)(false);(0,_react.useEffect)(()=>{const e=requestAnimationFrame(()=>X(true));return()=>cancelAnimationFrame(e)},[]);const h=(0,_useDesktopSyncStatus.useDesktopSyncStatus)();(0,_react.useEffect)(()=>{const e=async()=>{try{const t=await _sharedUi.persistentStorage.getItem(_sharedUi.devToolsStorageKeys.settings.activeTab());if(t&&["floating","settings","pro"].includes(t)){const o=t;cachedActiveTab=o;F(y=>y===o?y:o)}}catch(t){}finally{G(true)}};e()},[]);(0,_react.useEffect)(()=>{if(!N)return;_sharedUi.persistentStorage.setItem(_sharedUi.devToolsStorageKeys.settings.activeTab(),w).catch(e=>{console.warn("Failed to save settings active tab:",e)})},[w,N]);const Z=(0,_sharedUi.getUseLicense)();const T=Z?.();const m=T?.isPro??false;const z=!m&&T?.licenseKey?T.error:null;const ee=T?.errorKind==="transport";const[u,te]=(0,_react.useState)(cachedStorageBackend);const[D,k]=(0,_react.useState)(false);const[B,L]=(0,_react.useState)(false);const[j,oe]=(0,_react.useState)(false);const[E,O]=(0,_react.useState)([]);const[V,P]=(0,_react.useState)(false);const M=(0,_sharedUi.useSafeAreaInsets)();const H=_reactNative.Dimensions.get("window").height;const K=_reactNative.Dimensions.get("window").width;const ne=Math.floor(H*.33);const se=Math.min(K-32,400);const _=(0,_react.useCallback)(async()=>{try{const e=await l.getItem(STORAGE_KEY);if(e){const t=JSON.parse(e);const o=mergeWithDefaults(i,t,{allowedDialKeys:S,allowedFloatingKeys:R});cachedSettings=o;b(y=>sameSettings(y,o)?y:o);return}cachedSettings=i;b(t=>sameSettings(t,i)?t:i)}catch(e){console.error("Failed to load dev tools settings:",e);b(i)}},[i,S,R,l]);(0,_react.useEffect)(()=>{_()},[_]);(0,_react.useEffect)(()=>{(0,_sharedUi.getStorageBackendType)().then(e=>{cachedStorageBackend=e;te(t=>t===e?t:e)})},[]);(0,_react.useEffect)(()=>{if(j){P(true);_sharedUi.persistentStorage.getAllKeys().then(e=>{O(e.sort())}).catch(()=>{O([])}).finally(()=>{P(false)})}},[j]);const A=async e=>{try{const t={...e,dialTools:enforceDialLimit(e.dialTools)};await l.setItem(STORAGE_KEY,JSON.stringify(t));cachedSettings=t;b(t);n?.(t);_settingsBus.settingsBus.emit(t)}catch(t){console.error("Failed to save dev tools settings:",t)}};const ie=e=>{const t={...f,floatingTools:{...f.floatingTools,[e]:!f.floatingTools[e]}};A(t)};const re=e=>{const t={...f,globalSettings:{...f.globalSettings,[e]:!f.globalSettings?.[e]}};A(t)};const ae=async()=>{k(true);L(false);try{await _sharedUi.persistentStorage.clear();L(true);b(i);if(l!==_sharedUi.persistentStorage)await l.setItem(STORAGE_KEY,JSON.stringify(i));n?.(i);_settingsBus.settingsBus.emit(i);setTimeout(()=>L(false),2e3)}catch(e){console.error("Failed to clear storage:",e)}finally{k(false)}};const le=(0,_react.useCallback)(e=>{},[]);const ce=e=>{const t=s.find(o=>o.id===e);if(t?.description){return t.description}if(e==="environment"){return"Environment badge."}return""};const W=e=>{if(e==="environment"){return"Env Badge"}const t=s.find(o=>o.id===e);return t?.name??e.toUpperCase().replace(/_/g," ")};const de=e=>{if(!Q)return null;switch(e){case"query":return(0,_jsxRuntime.jsx)(_floatingToolsCore.QueryIcon,{size:18});case"env":return(0,_jsxRuntime.jsx)(_floatingToolsCore.EnvIcon,{size:18});case"sentry":return(0,_jsxRuntime.jsx)(_sharedUi.SentryIcon,{size:18,color:"#9945FF"});case"storage":return(0,_jsxRuntime.jsx)(_floatingToolsCore.StorageIcon,{size:18,bgColor:_sharedUi.night.color.surface});case"wifi":case"query-wifi-toggle":return(0,_jsxRuntime.jsx)(_sharedUi.WifiCircuitIcon,{size:18,colorPreset:"green",strength:4,noBackground:true});case"route-events":return(0,_jsxRuntime.jsx)(_floatingToolsCore.RoutesIcon,{size:18,bgColor:_sharedUi.night.color.surface});case"network":return(0,_jsxRuntime.jsx)(_floatingToolsCore.NetworkIcon,{size:18});case"environment":return(0,_jsxRuntime.jsx)(_floatingToolsCore.EnvIcon,{size:18});case"debug-borders":return(0,_jsxRuntime.jsx)(_sharedUi.Layers,{size:18,color:_sharedUi.night.color.accent});case"highlight-updates":return(0,_jsxRuntime.jsx)(_sharedUi.RenderCountIcon,{size:18,color:_sharedUi.night.color.accent});case"highlight-updates-modal":return(0,_jsxRuntime.jsx)(_floatingToolsCore.HighlighterIcon,{size:18});case"redux":return(0,_jsxRuntime.jsx)(_floatingToolsCore.ReduxIcon,{size:18});case"image-overlay":return(0,_jsxRuntime.jsx)(_sharedUi.ImageOverlayIcon,{size:18});case"events":return(0,_jsxRuntime.jsx)(_floatingToolsCore.EventsIcon,{size:18});case"zustand":try{const{ZustandIcon:t}=require("@buoy-gg/zustand");return(0,_jsxRuntime.jsx)(t,{size:18})}catch{return(0,_jsxRuntime.jsx)(_sharedUi.Info,{size:18,color:_sharedUi.night.color.textSecondary})}case"jotai":try{const{JotaiIcon:t}=require("@buoy-gg/jotai");return(0,_jsxRuntime.jsx)(t,{size:18})}catch{return(0,_jsxRuntime.jsx)(_sharedUi.Info,{size:18,color:_sharedUi.night.color.textSecondary})}default:{const t=s.find(o=>o.id===e);if(t?.icon!=null){return(0,_AppIcon.renderAppIcon)(t.icon,{slot:"row",size:18,color:t.color})}return(0,_jsxRuntime.jsx)(_sharedUi.Info,{size:18,color:_sharedUi.night.color.textSecondary})}}};const ge=(e,t,o,y)=>{const v=ce(e);return(0,_jsxRuntime.jsxs)(_reactNative.TouchableOpacity,{activeOpacity:o?1:.7,onPress:()=>!o&&y(),accessibilityLabel:W(e),accessibilityRole:"button",style:[styles.toolRow,o&&styles.rowDisabled],children:[(0,_jsxRuntime.jsx)(_reactNative.View,{style:styles.toolIconSlot,children:de(e)}),(0,_jsxRuntime.jsxs)(_reactNative.View,{style:styles.rowInfo,children:[(0,_jsxRuntime.jsxs)(_reactNative.Text,{style:styles.rowLabel,children:[W(e),o?" \xB7 max 6":""]}),v?(0,_jsxRuntime.jsx)(_reactNative.Text,{style:styles.rowCaption,numberOfLines:1,children:v}):null]}),(0,_jsxRuntime.jsx)(_sharedUi.NightSwitch,{value:t,disabled:o,onValueChange:()=>y()})]},e)};const q=e=>{Y(t=>{const o=new Set(t);if(o.has(e)){o.delete(e)}else{o.add(e)}return o})};const J=(e,t,o,y,v)=>{const ye=f.globalSettings?.[e]??false;const U=C.has(e);return(0,_jsxRuntime.jsxs)(_reactNative.View,{children:[(0,_jsxRuntime.jsxs)(_reactNative.TouchableOpacity,{activeOpacity:.7,onPress:()=>q(e),accessibilityLabel:t,style:styles.settingRow,children:[(0,_jsxRuntime.jsxs)(_reactNative.View,{style:styles.rowInfo,children:[(0,_jsxRuntime.jsx)(_reactNative.Text,{style:styles.rowLabel,children:t}),(0,_jsxRuntime.jsx)(_reactNative.Text,{style:styles.rowCaption,numberOfLines:U?0:1,children:o})]}),(0,_jsxRuntime.jsx)(_sharedUi.NightSwitch,{value:ye,onValueChange:()=>re(e)})]}),U&&(0,_jsxRuntime.jsxs)(_reactNative.View,{style:styles.settingRowBody,children:[(0,_jsxRuntime.jsx)(_reactNative.Text,{style:styles.settingRowBodyText,children:y}),(0,_jsxRuntime.jsx)(_reactNative.Text,{style:styles.settingRowBodyHint,children:v})]})]},e)};const p=(e,t,o)=>(0,_jsxRuntime.jsxs)(_reactNative.View,{children:[(0,_jsxRuntime.jsx)(_sharedUi.NightSectionLabel,{children:e}),t,o]});const he=u==="filesystem"?(0,_jsxRuntime.jsx)(_sharedUi.NightBadge,{label:"File System",tone:"accent"}):u==="asyncstorage"?(0,_jsxRuntime.jsx)(_sharedUi.NightBadge,{label:"Async Storage",tone:"warning"}):u==="localstorage"?(0,_jsxRuntime.jsx)(_sharedUi.NightBadge,{label:"Local Storage",tone:"accent"}):u==="memory"?(0,_jsxRuntime.jsx)(_sharedUi.NightBadge,{label:"Memory",tone:"danger"}):(0,_jsxRuntime.jsx)(_sharedUi.NightBadge,{label:"Loading\u2026",tone:"neutral"});const ue=()=>(0,_jsxRuntime.jsxs)(_reactNative.View,{style:styles.container,children:[(0,_jsxRuntime.jsxs)(_reactNative.ScrollView,{style:styles.scrollContent,showsVerticalScrollIndicator:false,contentContainerStyle:styles.scrollContainer,children:[w==="floating"&&(0,_jsxRuntime.jsx)(_jsxRuntime.Fragment,{children:p("Floating Tools",(0,_jsxRuntime.jsx)(_sharedUi.NightCard,{glass:true,children:(0,_jsxRuntime.jsx)(_sharedUi.NightRows,{children:Object.entries(f.floatingTools).map(([e,t])=>ge(e,t,false,()=>ie(e)))})}),(0,_jsxRuntime.jsx)(_sharedUi.NightFootnote,{children:"Tools switched on here appear in the floating bubble row."}))}),w==="settings"&&(0,_jsxRuntime.jsxs)(_jsxRuntime.Fragment,{children:[p("Background",(0,_jsxRuntime.jsx)(_sharedUi.NightCard,{glass:true,padded:true,children:(0,_jsxRuntime.jsx)(_sharedUi.BackgroundSwitcher,{embedded:true})})),p("Storage",(0,_jsxRuntime.jsxs)(_sharedUi.NightCard,{glass:true,children:[(0,_jsxRuntime.jsxs)(_reactNative.TouchableOpacity,{activeOpacity:.7,onPress:()=>oe(!j),accessibilityLabel:"Storage Type",style:styles.settingRow,children:[(0,_jsxRuntime.jsx)(_reactNative.View,{style:styles.rowInfo,children:(0,_jsxRuntime.jsx)(_reactNative.Text,{style:styles.rowLabel,children:"Storage Type"})}),he,j?(0,_jsxRuntime.jsx)(_sharedUi.ChevronDown,{size:16,color:_sharedUi.night.color.textTertiary}):(0,_jsxRuntime.jsx)(_sharedUi.ChevronRightIcon,{size:16,color:_sharedUi.night.color.textTertiary})]}),j&&(0,_jsxRuntime.jsxs)(_jsxRuntime.Fragment,{children:[(0,_jsxRuntime.jsxs)(_reactNative.View,{style:styles.settingRowBody,children:[(0,_jsxRuntime.jsx)(_reactNative.Text,{style:styles.settingRowBodyText,children:u==="filesystem"?"Settings persist independently and survive AsyncStorage.clear() calls during logout.":u==="asyncstorage"?"Settings may be lost if AsyncStorage is cleared during logout.":u==="localstorage"?"Settings are saved in this browser. Clearing site data removes them.":u==="memory"?"Settings are stored in memory only and will be lost on app restart.":"Checking storage backend\u2026"}),u==="asyncstorage"&&(0,_jsxRuntime.jsx)(_reactNative.Text,{style:[styles.settingRowBodyText,styles.bodyWarning],children:"Install expo-file-system to persist settings through logout flows."}),u==="memory"&&(0,_jsxRuntime.jsx)(_reactNative.Text,{style:[styles.settingRowBodyText,styles.bodyDanger],children:"No persistent storage available \u2014 install expo-file-system (best) or @react-native-async-storage/async-storage."})]}),(0,_jsxRuntime.jsx)(_sharedUi.NightSeparator,{}),(0,_jsxRuntime.jsxs)(_reactNative.View,{style:styles.storageExpanded,children:[(0,_jsxRuntime.jsxs)(_reactNative.View,{style:styles.storageExpandedHeader,children:[(0,_jsxRuntime.jsx)(_reactNative.Text,{style:styles.storageExpandedTitle,children:"SAVED SETTINGS"}),(0,_jsxRuntime.jsx)(_reactNative.Text,{style:styles.storageExpandedCount,children:V?"\u2026":`${E.length} keys`})]}),V?(0,_jsxRuntime.jsx)(_reactNative.Text,{style:styles.storageKeyEmpty,children:"Loading\u2026"}):E.length===0?(0,_jsxRuntime.jsx)(_reactNative.Text,{style:styles.storageKeyEmpty,children:"No settings saved yet"}):(0,_jsxRuntime.jsx)(_reactNative.ScrollView,{style:styles.storageKeysList,nestedScrollEnabled:true,showsVerticalScrollIndicator:true,children:E.map(e=>(0,_jsxRuntime.jsx)(_reactNative.View,{style:styles.storageKeyItem,children:(0,_jsxRuntime.jsx)(_reactNative.Text,{style:styles.storageKeyText,numberOfLines:1,children:e.replace("@react_buoy_","")})},e))})]}),(0,_jsxRuntime.jsx)(_reactNative.View,{style:styles.cardButtonWrap,children:(0,_jsxRuntime.jsx)(_sharedUi.NightButton,{label:B?"Cleared":D?"Clearing\u2026":"Clear All Settings",variant:B?"secondary":"destructive",size:"md",disabled:D,onPress:ae,icon:B?(0,_jsxRuntime.jsx)(_sharedUi.CheckCircle2,{size:15,color:_sharedUi.night.color.accent}):(0,_jsxRuntime.jsx)(_sharedUi.Trash2,{size:15,color:D?_sharedUi.night.color.textTertiary:_sharedUi.night.color.danger})})})]})]})),h&&h.state!=="idle"&&p("Desktop Sync",(0,_jsxRuntime.jsxs)(_sharedUi.NightCard,{glass:true,children:[(0,_jsxRuntime.jsxs)(_reactNative.TouchableOpacity,{activeOpacity:.7,onPress:()=>q("desktopSync"),accessibilityLabel:"Buoy Desktop",style:styles.settingRow,children:[(0,_jsxRuntime.jsx)(_reactNative.View,{style:styles.rowInfo,children:(0,_jsxRuntime.jsx)(_reactNative.Text,{style:styles.rowLabel,children:"Buoy Desktop"})}),h.state==="connected"?(0,_jsxRuntime.jsx)(_sharedUi.NightBadge,{label:"Connected",tone:"accent"}):h.state==="connecting"?(0,_jsxRuntime.jsx)(_sharedUi.NightBadge,{label:"Connecting\u2026",tone:"neutral"}):(0,_jsxRuntime.jsx)(_sharedUi.NightBadge,{label:"Retrying",tone:"warning"}),C.has("desktopSync")?(0,_jsxRuntime.jsx)(_sharedUi.ChevronDown,{size:16,color:_sharedUi.night.color.textTertiary}):(0,_jsxRuntime.jsx)(_sharedUi.ChevronRightIcon,{size:16,color:_sharedUi.night.color.textTertiary})]}),C.has("desktopSync")&&(0,_jsxRuntime.jsxs)(_reactNative.View,{style:styles.settingRowBody,children:[(0,_jsxRuntime.jsxs)(_reactNative.Text,{style:styles.settingRowBodyText,children:[h.state==="connected"?"Streaming tool data to Buoy Desktop at ":"Trying to reach Buoy Desktop at ",(0,_jsxRuntime.jsx)(_reactNative.Text,{style:styles.footnoteMono,children:h.targetURL??"(unknown URL)"}),h.state!=="connected"&&" \u2014 is the desktop app running? Override with the externalSync socketURL option if it runs elsewhere."]}),h.state==="retrying"&&h.lastError&&(0,_jsxRuntime.jsxs)(_reactNative.Text,{style:[styles.settingRowBodyText,styles.bodyWarning],children:["Last error: ",h.lastError]})]})]})),p("Modal Behavior",(0,_jsxRuntime.jsx)(_sharedUi.NightCard,{glass:true,children:(0,_jsxRuntime.jsxs)(_sharedUi.NightRows,{children:[J("enableSharedModalDimensions","Shared Modal Size","Sync dimensions across all tools","When enabled, all tool modals will share the same size and position. Resizing one modal will affect all others. When disabled, each tool remembers its own size and position independently.","Keep OFF for the best experience. This allows you to customize each tool's modal size separately."),_reactNative.Platform.OS!=="web"?J("expandableWindowControls","Expand Controls","iPad-style expandable window buttons","When enabled, the window control buttons (minimize, toggle mode, close) start as small dots and expand into larger, easy-to-tap buttons when pressed. When disabled, buttons are directly tappable at their small size.","Keep ON for touch devices where the small buttons are hard to press. Turn OFF if you prefer direct single-tap access."):null]})}))]}),w==="pro"&&(0,_jsxRuntime.jsxs)(_jsxRuntime.Fragment,{children:[p("License",(0,_jsxRuntime.jsx)(_sharedUi.NightCard,{glass:true,children:(0,_jsxRuntime.jsxs)(_reactNative.View,{style:styles.settingRow,children:[(0,_jsxRuntime.jsx)(_reactNative.View,{style:styles.rowInfo,children:(0,_jsxRuntime.jsx)(_reactNative.Text,{style:styles.rowLabel,children:"License Status"})}),(0,_jsxRuntime.jsx)(_reactNative.View,{testID:"buoy-settings-license-status",accessibilityLabel:m?"License: Active":"License: Free",children:m?(0,_jsxRuntime.jsx)(_sharedUi.NightBadge,{label:"Active",tone:"accent"}):(0,_jsxRuntime.jsx)(_sharedUi.NightBadge,{label:"Free",tone:"neutral"})})]})}),(0,_jsxRuntime.jsx)(_sharedUi.NightFootnote,{children:m?"You have full access to all Buoy DevTools features.":z?ee?`Couldn't reach the license server (${z}). A VPN or corporate proxy can block buoy.gg \u2014 turn it off and reload. Your key hasn't been rejected.`:`License check failed: ${z}.`:"Upgrade to Pro to unlock all features and support development."})),!m&&(0,_jsxRuntime.jsxs)(_jsxRuntime.Fragment,{children:[p("Pro Features",(0,_jsxRuntime.jsx)(_sharedUi.NightCard,{glass:true,children:(0,_jsxRuntime.jsx)(_sharedUi.NightRows,{children:["Advanced Settings","Priority Support"].map(e=>(0,_jsxRuntime.jsxs)(_reactNative.View,{style:styles.featureRow,children:[(0,_jsxRuntime.jsx)(_sharedUi.CheckCircle2,{size:16,color:_sharedUi.night.color.accent}),(0,_jsxRuntime.jsx)(_reactNative.Text,{style:styles.rowLabel,children:e})]},e))})})),(0,_jsxRuntime.jsx)(_sharedUi.NightButton,{label:"Upgrade to Pro",variant:"primary",size:"lg",onPress:()=>I(true)})]})]})]}),(0,_jsxRuntime.jsx)(_sharedUi.LicenseEntryModal,{visible:$,onClose:()=>I(false),onSuccess:()=>I(false)})]});return(0,_jsxRuntime.jsx)(_sharedUi.JsModal,{visible:r,onClose:a,zIndex:d,variant:"night",header:{showToggleButton:false,customContent:(0,_jsxRuntime.jsx)(_reactNative.View,{style:styles.headerRow,children:(0,_jsxRuntime.jsx)(_sharedUi.NightSegmented,{glass:true,tabs:[{key:"floating",label:"Floating"},{key:"settings",label:"Settings"},{key:"pro",label:"Pro"}],activeKey:w,onChange:e=>F(e)})})},initialMode:"bottomSheet",onModeChange:le,persistenceKey:_sharedUi.devToolsStorageKeys.settings.root(),enablePersistence:true,maxHeight:H-M.top,initialHeight:ne,initialFloatingPosition:{x:(K-se)/2,y:M.top+20},enableGlitchEffects:true,children:ue()})};exports.DevToolsSettingsModal=DevToolsSettingsModal;const basicDefaultSettings={dialTools:{},floatingTools:{environment:false},globalSettings:{enableSharedModalDimensions:false}};const createDefaultsFromConfig=(r,a)=>{const n=new Set(r??[]);const c=new Set(a??[]);const s={};for(const d of c){s[d]=true}const l={environment:n.has("environment")};for(const d of n){if(d!=="environment"){l[d]=true}}return{dialTools:enforceDialLimit(s),floatingTools:l,globalSettings:{enableSharedModalDimensions:false}}};let cachedSettings=null;let cachedActiveTab=null;let cachedStorageBackend=null;const sameSettings=(r,a)=>JSON.stringify(r)===JSON.stringify(a);_settingsBus.settingsBus.addListener(r=>{if(r)cachedSettings=r});const useDevToolsSettings=()=>{const{defaultFloatingTools:r,defaultDialTools:a}=(0,_DefaultConfigContext.useDefaultConfig)();const n=(0,_react.useMemo)(()=>{if(!r&&!a){return basicDefaultSettings}return createDefaultsFromConfig(r,a)},[r,a]);const[c,s]=(0,_react.useState)(n);const l=(0,_react.useCallback)(async()=>{try{const g=await _sharedUi.persistentStorage.getItem(STORAGE_KEY);if(g){const x=JSON.parse(g);const i=mergeWithDefaults(n,x);s(i);return}s(n)}catch(g){console.error("Failed to load dev tools settings:",g);s(n)}},[n]);(0,_react.useEffect)(()=>{l();const g=_settingsBus.settingsBus.addListener(x=>{try{if(x){s(x)}}catch(i){}});return()=>{g()}},[l]);const d=(0,_react.useCallback)(()=>{l()},[l]);return{settings:c,refreshSettings:d}};exports.useDevToolsSettings=useDevToolsSettings;const styles=_reactNative.StyleSheet.create({container:{flex:1,backgroundColor:"transparent"},headerRow:{flexDirection:"row",alignItems:"center",paddingLeft:_sharedUi.night.gutter,paddingRight:_sharedUi.night.gutter,paddingBottom:8},scrollContent:{flex:1},scrollContainer:{paddingHorizontal:_sharedUi.night.gutter,paddingTop:8,paddingBottom:24,gap:_sharedUi.night.groupGap},toolRow:{flexDirection:"row",alignItems:"center",gap:12,paddingHorizontal:_sharedUi.night.rowPadH,paddingVertical:12},settingRow:{flexDirection:"row",alignItems:"center",gap:10,paddingHorizontal:_sharedUi.night.rowPadH,paddingVertical:_sharedUi.night.rowPadV,minHeight:52},featureRow:{flexDirection:"row",alignItems:"center",gap:10,paddingHorizontal:_sharedUi.night.rowPadH,paddingVertical:12},rowDisabled:{opacity:.4},toolIconSlot:{width:24,alignItems:"center"},rowInfo:{flex:1,gap:2},rowLabel:{color:_sharedUi.night.color.text,fontSize:_sharedUi.night.font.row,fontWeight:"500"},rowCaption:{color:_sharedUi.night.color.textTertiary,fontSize:_sharedUi.night.font.label},settingRowBody:{paddingHorizontal:_sharedUi.night.rowPadH,paddingBottom:_sharedUi.night.rowPadV,gap:6},settingRowBodyText:{color:_sharedUi.night.color.textSecondary,fontSize:_sharedUi.night.font.caption,lineHeight:_sharedUi.night.font.caption*1.45},settingRowBodyHint:{color:_sharedUi.night.color.textTertiary,fontSize:_sharedUi.night.font.caption,lineHeight:_sharedUi.night.font.caption*1.45},bodyWarning:{color:_sharedUi.night.color.warning},bodyDanger:{color:_sharedUi.night.color.danger},cardButtonWrap:{paddingHorizontal:_sharedUi.night.cardPad,paddingTop:10,paddingBottom:_sharedUi.night.cardPad},storageExpanded:{paddingHorizontal:_sharedUi.night.rowPadH,paddingVertical:12,gap:8},storageExpandedHeader:{flexDirection:"row",alignItems:"center"},storageExpandedTitle:{flex:1,color:_sharedUi.night.color.textSecondary,fontSize:_sharedUi.night.font.micro,fontWeight:"600",letterSpacing:.5},storageExpandedCount:{color:_sharedUi.night.color.textTertiary,fontSize:_sharedUi.night.font.micro},storageKeysList:{maxHeight:150},storageKeyItem:{backgroundColor:_sharedUi.night.color.glassElevated,borderRadius:_sharedUi.night.radius.segment,paddingHorizontal:10,paddingVertical:7,marginBottom:4},storageKeyText:{color:_sharedUi.night.color.textSecondary,fontSize:_sharedUi.night.font.micro,fontFamily:_sharedUi.monoFont},storageKeyEmpty:{color:_sharedUi.night.color.textTertiary,fontSize:_sharedUi.night.font.caption,fontStyle:"italic"},footnoteMono:{fontFamily:_sharedUi.monoFont,fontSize:_sharedUi.night.font.label,color:_sharedUi.night.color.textSecondary}});