@buoy-gg/core 7.0.41 → 7.0.42

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 +5 -5
  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,366 +1 @@
1
- "use strict";
2
-
3
- import React, { useEffect, useMemo, useRef, useState } from "react";
4
- import { TouchableOpacity, StyleSheet, View } from "react-native";
5
- import { absoluteFill } from "@buoy-gg/shared-ui";
6
- import { FloatingTools, UserStatus } from "./floatingTools";
7
- import { renderAppIcon } from "./AppIcon";
8
- import { DialDevTools } from "./dial/DialDevTools";
9
- import { EnvironmentIndicator, persistentStorage, useHintsDisabled, devToolsStorageKeys, buoyColors } from "@buoy-gg/shared-ui";
10
- import { useDevToolsSettings } from "./DevToolsSettingsModal";
11
- import { useAppHost } from "./AppHost";
12
- import { useDevToolsVisibility } from "./DevToolsVisibilityContext.js";
13
- import { toggleStateManager } from "./ToggleStateManager.js";
14
- import { OnboardingTooltip } from "./dial/OnboardingTooltip";
15
-
16
- /**
17
- * Props for the floating developer tools launcher. Controls which apps are shown and
18
- * how the menu integrates with the current host environment.
19
- */
20
- import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
21
- /**
22
- * FloatingMenu renders the persistent developer tools entry point. It handles visibility,
23
- * integrates with the AppHost, and presents available tools as floating shortcuts and a dial.
24
- */
25
- const FLOATING_MENU_ONBOARDING_KEY = "@react_buoy_floating_menu_tooltip_shown";
26
- const ONBOARDING_STEP_KEY = "@react_buoy_onboarding_step";
27
- export const FloatingMenu = ({
28
- apps,
29
- state,
30
- actions,
31
- hidden,
32
- environment,
33
- userRole = "admin",
34
- availableEnvironments,
35
- onEnvironmentSwitch
36
- }) => {
37
- const [internalHidden, setInternalHidden] = useState(false);
38
- const [showDial, setShowDial] = useState(false);
39
- const [dialStateLoaded, setDialStateLoaded] = useState(false);
40
- const [onboardingStep, setOnboardingStep] = useState(null);
41
- const [, forceUpdate] = useState(0); // Used to force re-render when toggle states change
42
- const onboardingDismissedRef = useRef(false); // Track if onboarding was dismissed
43
- const hintsDisabled = useHintsDisabled();
44
-
45
- // Load persisted dial state on mount
46
- useEffect(() => {
47
- const loadDialState = async () => {
48
- try {
49
- const savedDialOpen = await persistentStorage.getItem(devToolsStorageKeys.dial.isOpen());
50
- if (savedDialOpen === "true") {
51
- setShowDial(true);
52
- }
53
- } catch (error) {
54
- // Failed to load dial state - use default (closed)
55
- } finally {
56
- setDialStateLoaded(true);
57
- }
58
- };
59
- loadDialState();
60
- }, []);
61
-
62
- // Persist dial state when it changes
63
- useEffect(() => {
64
- // Only persist after initial state is loaded to avoid overwriting with default
65
- if (!dialStateLoaded) return;
66
- persistentStorage.setItem(devToolsStorageKeys.dial.isOpen(), showDial ? "true" : "false").catch(error => {
67
- // Failed to save dial state - continue without persistence
68
- console.warn("Failed to save dial state:", error);
69
- });
70
- }, [showDial, dialStateLoaded]);
71
-
72
- // Determine if environment selector should be shown
73
- const showEnvironmentSelector = Boolean(availableEnvironments?.length && onEnvironmentSwitch);
74
- const {
75
- isAnyOpen,
76
- open,
77
- registerApps
78
- } = useAppHost();
79
- const wasAppOpenRef = useRef(isAnyOpen);
80
- const {
81
- setDialOpen,
82
- setToolOpen
83
- } = useDevToolsVisibility();
84
-
85
- // Check onboarding status on first load
86
- useEffect(() => {
87
- // Skip onboarding if hints are disabled
88
- if (hintsDisabled) {
89
- return;
90
- }
91
- const checkOnboarding = async () => {
92
- try {
93
- const hasSeenOnboarding = await persistentStorage.getItem(FLOATING_MENU_ONBOARDING_KEY);
94
- if (!hasSeenOnboarding) {
95
- // Small delay to let the UI settle before showing tooltip
96
- setTimeout(() => {
97
- setOnboardingStep("positioning");
98
- }, 1000);
99
- }
100
- } catch (error) {
101
- // If there's an error reading storage, don't show onboarding
102
- }
103
- };
104
- checkOnboarding();
105
- }, [hintsDisabled]);
106
-
107
- // Subscribe to toggle state changes to update icon colors
108
- useEffect(() => {
109
- const unsubscribe = toggleStateManager.subscribe(() => {
110
- forceUpdate(prev => prev + 1);
111
- });
112
- return unsubscribe;
113
- }, []);
114
-
115
- // Sync dial state with visibility context
116
- useEffect(() => {
117
- setDialOpen(showDial);
118
- }, [showDial, setDialOpen]);
119
-
120
- // Sync tool open state with visibility context
121
- useEffect(() => {
122
- setToolOpen(isAnyOpen);
123
- }, [isAnyOpen, setToolOpen]);
124
-
125
- // When an app is open or dial is shown, push the menu to the side instead of hiding completely
126
- const shouldPushToSide = useMemo(() => Boolean(showDial || isAnyOpen), [showDial, isAnyOpen]);
127
-
128
- // Use external hidden prop or internal hidden state for complete hiding
129
- const isCompletelyHidden = useMemo(() => Boolean(hidden ?? internalHidden), [hidden, internalHidden]);
130
- const {
131
- settings: devToolsSettings
132
- } = useDevToolsSettings();
133
-
134
- // Register apps with AppHost for persistence
135
- useEffect(() => {
136
- if (registerApps) {
137
- registerApps(apps);
138
- }
139
- }, [apps, registerApps]);
140
- const mergedActions = useMemo(() => {
141
- return {
142
- ...(actions ?? {}),
143
- closeMenu: () => setShowDial(false),
144
- hideFloatingRow: () => setInternalHidden(true),
145
- showFloatingRow: () => setInternalHidden(false),
146
- notifyToggleChange: () => forceUpdate(prev => prev + 1)
147
- };
148
- }, [actions]);
149
- useEffect(() => {
150
- if (wasAppOpenRef.current && !isAnyOpen) {
151
- setInternalHidden(false);
152
- setShowDial(false);
153
- }
154
- wasAppOpenRef.current = isAnyOpen;
155
- }, [isAnyOpen]);
156
-
157
- // Filter function for floating tools based on settings
158
- const isFloatingEnabled = id => {
159
- if (!devToolsSettings) return false;
160
- // Floating tools require explicit opt-in (unlike dial tools which auto-enable)
161
- return devToolsSettings.floatingTools[id] ?? false;
162
- };
163
-
164
- // Dial is the default/only layout
165
-
166
- const handlePress = app => {
167
- // Call the app's onPress callback if provided, passing actions for toggle tools
168
- app?.onPress?.(mergedActions);
169
-
170
- // Only open modal if not a toggle-only tool
171
- if (app.launchMode !== "toggle-only") {
172
- // Resolve the icon for minimize stack display (createElement keeps
173
- // function-icon hooks working; strings become text icons).
174
- const resolvedIcon = renderAppIcon(app.icon, {
175
- slot: "dial",
176
- size: 20,
177
- color: app.color
178
- });
179
- open({
180
- id: app.id,
181
- title: app.name,
182
- component: app.component,
183
- props: app.props,
184
- launchMode: app.launchMode ?? "self-modal",
185
- singleton: app.singleton ?? true,
186
- icon: resolvedIcon,
187
- color: app.color,
188
- modal: app.modal
189
- });
190
- }
191
- };
192
- const handleOnboardingDismiss = () => {
193
- // Mark as dismissed immediately in ref (synchronous, no re-render needed)
194
- onboardingDismissedRef.current = true;
195
-
196
- // Update state to hide tooltip
197
- setOnboardingStep(null);
198
-
199
- // Save to storage asynchronously in the background
200
- persistentStorage.setItem(FLOATING_MENU_ONBOARDING_KEY, "true").catch(error => {
201
- // Silently fail - user already saw onboarding, just won't persist
202
- console.warn("Failed to save onboarding state:", error);
203
- });
204
- };
205
- const handleDialOpen = () => {
206
- // If user opens dial during onboarding, mark onboarding as complete
207
- if (isOnboarding) {
208
- handleOnboardingDismiss();
209
- }
210
- setShowDial(true);
211
- };
212
-
213
- // Determine if we're in onboarding mode (only when explicitly set to positioning AND not dismissed AND hints not disabled)
214
- const isOnboarding = onboardingStep === "positioning" && !onboardingDismissedRef.current && !hintsDisabled;
215
-
216
- // During onboarding, disable position persistence and use centered position
217
- const shouldEnablePositionPersistence = !isOnboarding;
218
- return /*#__PURE__*/_jsxs(_Fragment, {
219
- children: [isOnboarding && !showDial && !isAnyOpen && /*#__PURE__*/_jsxs(View, {
220
- style: styles.onboardingContainer,
221
- children: [/*#__PURE__*/_jsx(View, {
222
- style: styles.onboardingBackdrop
223
- }), /*#__PURE__*/_jsx(OnboardingTooltip, {
224
- visible: true,
225
- onDismiss: handleOnboardingDismiss,
226
- title: "Welcome to Buoy!",
227
- message: "Grab and position this menu wherever you want, then tap the icon to open your tools."
228
- })]
229
- }), /*#__PURE__*/_jsx(View, {
230
- nativeID: "floating-devtools-root"
231
- // While the dial overlay is open, the floating menu underneath must be
232
- // inert — otherwise the draggable bubble's gesture handling intercepts
233
- // touches on dial controls that overlap it (e.g. the pager buttons).
234
- ,
235
- pointerEvents: isCompletelyHidden || showDial ? "none" : "box-none",
236
- style: {
237
- position: "absolute",
238
- top: 0,
239
- left: 0,
240
- right: 0,
241
- bottom: 0,
242
- zIndex: isOnboarding ? 10001 : 9999,
243
- // Higher z-index during onboarding to show above backdrop
244
- opacity: isCompletelyHidden ? 0 : 1
245
- },
246
- children: /*#__PURE__*/_jsxs(FloatingTools, {
247
- enablePositionPersistence: shouldEnablePositionPersistence,
248
- pushToSide: shouldPushToSide,
249
- centerOnboarding: isOnboarding,
250
- environment: environment,
251
- availableEnvironments: availableEnvironments,
252
- onEnvironmentSwitch: onEnvironmentSwitch,
253
- showEnvironmentSelector: showEnvironmentSelector && devToolsSettings?.floatingTools?.environment,
254
- children: [environment && devToolsSettings?.floatingTools?.environment !== false && !showEnvironmentSelector ? /*#__PURE__*/_jsx(EnvironmentIndicator, {
255
- environment: environment
256
- }) : null, userRole ? /*#__PURE__*/_jsx(UserStatus, {
257
- userRole: userRole,
258
- onPress: handleDialOpen
259
- }) :
260
- /*#__PURE__*/
261
- // Fallback: small launcher icon to ensure settings are always accessible
262
- _jsx(TouchableOpacity, {
263
- accessibilityLabel: "Open Dev Tools Menu",
264
- onPress: handleDialOpen,
265
- style: styles.fab,
266
- children: /*#__PURE__*/_jsx(View, {
267
- style: styles.menuButton,
268
- children: /*#__PURE__*/_jsx(MenuLauncherIcon, {
269
- size: 14
270
- })
271
- })
272
- }), apps.filter(a => (a.slot ?? "both") !== "dial" && isFloatingEnabled(a.id)).map(app => /*#__PURE__*/_jsx(TouchableOpacity, {
273
- accessibilityLabel: app.name,
274
- onPress: () => handlePress(app),
275
- style: styles.fab,
276
- children: (() => {
277
- if (typeof app.icon === "function") {
278
- const IconComponent = app.icon;
279
- return /*#__PURE__*/_jsx(IconComponent, {
280
- slot: "row",
281
- size: 16,
282
- state: state,
283
- actions: mergedActions
284
- });
285
- }
286
- return renderAppIcon(app.icon, {
287
- slot: "row",
288
- size: 16,
289
- color: app.color
290
- });
291
- })()
292
- }, `row-${app.id}`))]
293
- })
294
- }), showDial && !isCompletelyHidden && /*#__PURE__*/_jsx(DialDevTools, {
295
- apps: apps,
296
- state: state,
297
- actions: mergedActions,
298
- onClose: () => {
299
- setShowDial(false);
300
- }
301
- })]
302
- });
303
- };
304
- const styles = StyleSheet.create({
305
- fab: {
306
- paddingHorizontal: 6,
307
- paddingVertical: 4,
308
- borderRadius: 6,
309
- marginRight: 4,
310
- alignItems: "center",
311
- justifyContent: "center",
312
- minWidth: 0,
313
- minHeight: 0,
314
- backgroundColor: "transparent"
315
- },
316
- menuButton: {
317
- paddingHorizontal: 4,
318
- paddingVertical: 2,
319
- minWidth: 16,
320
- alignItems: "center",
321
- justifyContent: "center"
322
- },
323
- menuDots: {
324
- color: "#8CA2C8",
325
- fontSize: 14,
326
- fontWeight: "900"
327
- },
328
- onboardingContainer: {
329
- ...absoluteFill,
330
- zIndex: 10000
331
- },
332
- onboardingBackdrop: {
333
- ...absoluteFill,
334
- backgroundColor: "rgba(0, 0, 0, 0.85)"
335
- }
336
- });
337
- /** Minimal 3x3 dot icon used when the user status badge is unavailable. */
338
- const MenuLauncherIcon = ({
339
- size = 14,
340
- color = buoyColors.primary
341
- }) => {
342
- const dotSize = Math.max(2, Math.floor(size / 4));
343
- const gap = Math.max(1, Math.floor(size / 16));
344
- const items = Array.from({
345
- length: 9
346
- });
347
- return /*#__PURE__*/_jsx(View, {
348
- style: {
349
- width: size,
350
- height: size,
351
- flexDirection: "row",
352
- flexWrap: "wrap",
353
- alignContent: "center",
354
- justifyContent: "center"
355
- },
356
- children: items.map((_, i) => /*#__PURE__*/_jsx(View, {
357
- style: {
358
- width: dotSize,
359
- height: dotSize,
360
- margin: gap,
361
- borderRadius: 2,
362
- backgroundColor: color
363
- }
364
- }, i))
365
- });
366
- };
1
+ "use strict";import fo,{useEffect as r,useMemo as I,useRef as k,useState as m}from"react";import{TouchableOpacity as L,StyleSheet as X,View as l}from"react-native";import{absoluteFill as N}from"@buoy-gg/shared-ui";import{FloatingTools as Z,UserStatus as oo}from"./floatingTools";import{renderAppIcon as W}from"./AppIcon";import{DialDevTools as eo}from"./dial/DialDevTools";import{EnvironmentIndicator as to,persistentStorage as p,useHintsDisabled as no,devToolsStorageKeys as G,buoyColors as so}from"@buoy-gg/shared-ui";import{useDevToolsSettings as io}from"./DevToolsSettingsModal";import{useAppHost as ro}from"./AppHost";import{useDevToolsVisibility as lo}from"./DevToolsVisibilityContext.js";import{toggleStateManager as ao}from"./ToggleStateManager.js";import{OnboardingTooltip as co}from"./dial/OnboardingTooltip";import{jsx as e,jsxs as _,Fragment as uo}from"react/jsx-runtime";const V="@react_buoy_floating_menu_tooltip_shown";const Co="@react_buoy_onboarding_step";export const FloatingMenu=({apps:n,state:f,actions:a,hidden:h,environment:c,userRole:w="admin",availableEnvironments:b,onEnvironmentSwitch:C})=>{const[M,S]=m(false);const[s,d]=m(false);const[x,K]=m(false);const[U,A]=m(null);const[,E]=m(0);const F=k(false);const D=no();r(()=>{const o=async()=>{try{const t=await p.getItem(G.dial.isOpen());if(t==="true"){d(true)}}catch(t){}finally{K(true)}};o()},[]);r(()=>{if(!x)return;p.setItem(G.dial.isOpen(),s?"true":"false").catch(o=>{console.warn("Failed to save dial state:",o)})},[s,x]);const P=Boolean(b?.length&&C);const{isAnyOpen:i,open:Y,registerApps:O}=ro();const R=k(i);const{setDialOpen:B,setToolOpen:H}=lo();r(()=>{if(D){return}const o=async()=>{try{const t=await p.getItem(V);if(!t){setTimeout(()=>{A("positioning")},1e3)}}catch(t){}};o()},[D]);r(()=>{const o=ao.subscribe(()=>{E(t=>t+1)});return o},[]);r(()=>{B(s)},[s,B]);r(()=>{H(i)},[i,H]);const $=I(()=>Boolean(s||i),[s,i]);const v=I(()=>Boolean(h??M),[h,M]);const{settings:y}=io();r(()=>{if(O){O(n)}},[n,O]);const T=I(()=>{return{...a??{},closeMenu:()=>d(false),hideFloatingRow:()=>S(true),showFloatingRow:()=>S(false),notifyToggleChange:()=>E(o=>o+1)}},[a]);r(()=>{if(R.current&&!i){S(false);d(false)}R.current=i},[i]);const q=o=>{if(!y)return false;return y.floatingTools[o]??false};const J=o=>{o?.onPress?.(T);if(o.launchMode!=="toggle-only"){const t=W(o.icon,{slot:"dial",size:20,color:o.color});Y({id:o.id,title:o.name,component:o.component,props:o.props,launchMode:o.launchMode??"self-modal",singleton:o.singleton??true,icon:t,color:o.color,modal:o.modal})}};const j=()=>{F.current=true;A(null);p.setItem(V,"true").catch(o=>{console.warn("Failed to save onboarding state:",o)})};const z=()=>{if(u){j()}d(true)};const u=U==="positioning"&&!F.current&&!D;const Q=!u;return _(uo,{children:[u&&!s&&!i&&_(l,{style:g.onboardingContainer,children:[e(l,{style:g.onboardingBackdrop}),e(co,{visible:true,onDismiss:j,title:"Welcome to Buoy!",message:"Grab and position this menu wherever you want, then tap the icon to open your tools."})]}),e(l,{nativeID:"floating-devtools-root",pointerEvents:v||s?"none":"box-none",style:{position:"absolute",top:0,left:0,right:0,bottom:0,zIndex:u?10001:9999,opacity:v?0:1},children:_(Z,{enablePositionPersistence:Q,pushToSide:$,centerOnboarding:u,environment:c,availableEnvironments:b,onEnvironmentSwitch:C,showEnvironmentSelector:P&&y?.floatingTools?.environment,children:[c&&y?.floatingTools?.environment!==false&&!P?e(to,{environment:c}):null,w?e(oo,{userRole:w,onPress:z}):e(L,{accessibilityLabel:"Open Dev Tools Menu",onPress:z,style:g.fab,children:e(l,{style:g.menuButton,children:e(mo,{size:14})})}),n.filter(o=>(o.slot??"both")!=="dial"&&q(o.id)).map(o=>e(L,{accessibilityLabel:o.name,onPress:()=>J(o),style:g.fab,children:(()=>{if(typeof o.icon==="function"){const t=o.icon;return e(t,{slot:"row",size:16,state:f,actions:T})}return W(o.icon,{slot:"row",size:16,color:o.color})})()},`row-${o.id}`))]})}),s&&!v&&e(eo,{apps:n,state:f,actions:T,onClose:()=>{d(false)}})]})};const g=X.create({fab:{paddingHorizontal:6,paddingVertical:4,borderRadius:6,marginRight:4,alignItems:"center",justifyContent:"center",minWidth:0,minHeight:0,backgroundColor:"transparent"},menuButton:{paddingHorizontal:4,paddingVertical:2,minWidth:16,alignItems:"center",justifyContent:"center"},menuDots:{color:"#8CA2C8",fontSize:14,fontWeight:"900"},onboardingContainer:{...N,zIndex:1e4},onboardingBackdrop:{...N,backgroundColor:"rgba(0, 0, 0, 0.85)"}});const mo=({size:n=14,color:f=so.primary})=>{const a=Math.max(2,Math.floor(n/4));const h=Math.max(1,Math.floor(n/16));const c=Array.from({length:9});return e(l,{style:{width:n,height:n,flexDirection:"row",flexWrap:"wrap",alignContent:"center",justifyContent:"center"},children:c.map((w,b)=>e(l,{style:{width:a,height:a,margin:h,borderRadius:2,backgroundColor:f}},b))})};
@@ -1,266 +1 @@
1
- "use strict";
2
-
3
- import React, { createContext, useContext, useState, useCallback, useEffect, useRef, useMemo } from "react";
4
- import { Dimensions } from "react-native";
5
- import { persistentStorage, getSafeAreaInsets } from "@buoy-gg/shared-ui";
6
-
7
- // ============================================================================
8
- // Types
9
- // ============================================================================
10
-
11
- // Type moved to the platform-free AppHostLogic.ts (so the web host can use
12
- // it without importing this react-native file); re-exported for back-compat.
13
-
14
- /**
15
- * Represents a minimized tool that can be restored
16
- */
17
-
18
- /**
19
- * Position for a minimized tool icon in the stack
20
- */
21
- import { jsx as _jsx } from "react/jsx-runtime";
22
- // ============================================================================
23
- // Constants
24
- // ============================================================================
25
-
26
- const ICON_SIZE = 44;
27
- const ICON_GAP = 12;
28
- const BOTTOM_OFFSET = 100; // Distance from safe area bottom
29
- const RIGHT_OFFSET = 16; // Distance from right edge
30
-
31
- /**
32
- * Calculate the position of a minimized tool icon in the stack
33
- * Icons stack upward from bottom-right corner
34
- */
35
- export function getIconPosition(index) {
36
- const {
37
- width: screenWidth,
38
- height: screenHeight
39
- } = Dimensions.get("window");
40
- const safeArea = getSafeAreaInsets();
41
-
42
- // X position: right edge minus icon size and offset
43
- const x = screenWidth - ICON_SIZE - RIGHT_OFFSET;
44
-
45
- // Y position: bottom up, starting at safe area bottom + offset
46
- const baseY = screenHeight - safeArea.bottom - BOTTOM_OFFSET - ICON_SIZE;
47
- const y = baseY - index * (ICON_SIZE + ICON_GAP);
48
- return {
49
- x,
50
- y
51
- };
52
- }
53
-
54
- /**
55
- * Get the icon size constant
56
- */
57
- export function getIconSize() {
58
- return ICON_SIZE;
59
- }
60
-
61
- /**
62
- * Context value for minimized tools management
63
- */
64
-
65
- // ============================================================================
66
- // Storage
67
- // ============================================================================
68
-
69
- const STORAGE_KEY = "@react_buoy_minimized_tools";
70
- const PERSISTENCE_DELAY = 500;
71
-
72
- /**
73
- * Serializable version of MinimizedTool for storage
74
- * (icon is not serializable, so we only store the id to reconstruct)
75
- */
76
-
77
- // ============================================================================
78
- // Context
79
- // ============================================================================
80
-
81
- const MinimizedToolsContext = /*#__PURE__*/createContext(null);
82
-
83
- // ============================================================================
84
- // Provider
85
- // ============================================================================
86
-
87
- /**
88
- * Provider component for minimized tools management.
89
- * Handles state, persistence, and provides context to children.
90
- */
91
- export function MinimizedToolsProvider({
92
- children,
93
- getToolIcon
94
- }) {
95
- const [minimizedTools, setMinimizedTools] = useState([]);
96
- /**
97
- * A mirror of the list that can be read SYNCHRONOUSLY.
98
- *
99
- * `restore()` has to return the tool it removed, in the same tick, because
100
- * its caller uses that return value to un-minimize the tool in AppHost. It
101
- * cannot get that from `minimizedTools` (the callback is memoized with no
102
- * deps, so it would close over a stale list) and it cannot get it from
103
- * inside a state updater either — see the note on `restore`.
104
- */
105
- const minimizedToolsRef = useRef([]);
106
- const [isRestored, setIsRestored] = useState(false);
107
- const persistenceTimeoutRef = useRef(null);
108
- const getToolIconRef = useRef(getToolIcon);
109
-
110
- // Keep ref updated
111
- useEffect(() => {
112
- getToolIconRef.current = getToolIcon;
113
- }, [getToolIcon]);
114
-
115
- // Restore minimized tools from storage on mount
116
- useEffect(() => {
117
- const restoreMinimizedTools = async () => {
118
- try {
119
- const saved = await persistentStorage.getItem(STORAGE_KEY);
120
- if (saved) {
121
- const serialized = JSON.parse(saved);
122
- // Reconstruct tools with icons
123
- const restored = serialized.map(tool => ({
124
- ...tool,
125
- icon: getToolIconRef.current?.(tool.id) ?? null
126
- }));
127
- setMinimizedTools(restored);
128
- }
129
- } catch (error) {
130
- // Failed to restore minimized tools - continue with empty state
131
- }
132
- setIsRestored(true);
133
- };
134
- restoreMinimizedTools();
135
- }, []);
136
-
137
- // One assignment, every render, so the ref never lags the state it mirrors.
138
- minimizedToolsRef.current = minimizedTools;
139
-
140
- // Persist minimized tools to storage with debounce
141
- useEffect(() => {
142
- if (!isRestored) return;
143
- if (persistenceTimeoutRef.current) {
144
- clearTimeout(persistenceTimeoutRef.current);
145
- }
146
- persistenceTimeoutRef.current = setTimeout(() => {
147
- // Serialize tools (exclude icon which is not serializable)
148
- const serialized = minimizedTools.map(({
149
- icon,
150
- ...rest
151
- }) => rest);
152
- persistentStorage.setItem(STORAGE_KEY, JSON.stringify(serialized));
153
- }, PERSISTENCE_DELAY);
154
- return () => {
155
- if (persistenceTimeoutRef.current) {
156
- clearTimeout(persistenceTimeoutRef.current);
157
- }
158
- };
159
- }, [minimizedTools, isRestored]);
160
- const minimize = useCallback(tool => {
161
- setMinimizedTools(current => {
162
- // Check if already minimized (by id for singleton behavior)
163
- const existing = current.find(t => t.id === tool.id);
164
- if (existing) {
165
- // Update existing minimized tool
166
- return current.map(t => t.id === tool.id ? {
167
- ...tool,
168
- minimizedAt: Date.now()
169
- } : t);
170
- }
171
- // Add new minimized tool
172
- return [...current, {
173
- ...tool,
174
- minimizedAt: Date.now()
175
- }];
176
- });
177
- }, []);
178
-
179
- /**
180
- * Take a tool out of the minimized list and hand it back to the caller.
181
- *
182
- * THE RETURN VALUE IS LOAD-BEARING. `MinimizedToolsStack` only calls
183
- * `onRestore` — which is what actually un-minimizes the tool in AppHost —
184
- * when this returns non-null. This used to assign the tool inside the
185
- * `setMinimizedTools` updater and read it back on the next line, which
186
- * assumes React runs updaters synchronously at the call site. Under React
187
- * 18's automatic batching it does not: the updater runs in the render
188
- * phase, so the caller always saw `null`, `onRestore` never fired, and
189
- * AppHost kept the tool flagged `minimized: true`. The tool then sat in the
190
- * rail with no way back — tapping it did nothing, and neither did opening
191
- * it again from the dial, because AppHost already had it open. It survived
192
- * reloads, because both stores are persisted.
193
- *
194
- * Reading the ref instead keeps the lookup synchronous and leaves the
195
- * updater doing only what an updater should: deriving the next state.
196
- */
197
- const restore = useCallback(instanceId => {
198
- const restoredTool = minimizedToolsRef.current.find(t => t.instanceId === instanceId) ?? null;
199
- if (!restoredTool) return null;
200
- setMinimizedTools(current => current.filter(t => t.instanceId !== instanceId));
201
- return restoredTool;
202
- }, []);
203
- const isMinimized = useCallback(id => {
204
- return minimizedTools.some(t => t.id === id);
205
- }, [minimizedTools]);
206
- const getMinimizedTool = useCallback(instanceId => {
207
- return minimizedTools.find(t => t.instanceId === instanceId);
208
- }, [minimizedTools]);
209
- const clearAll = useCallback(() => {
210
- setMinimizedTools([]);
211
- }, []);
212
- const getNextIconPosition = useCallback(() => {
213
- // Next icon will be at the current count index
214
- return getIconPosition(minimizedTools.length);
215
- }, [minimizedTools.length]);
216
- const getToolIconPosition = useCallback(instanceId => {
217
- const index = minimizedTools.findIndex(t => t.instanceId === instanceId);
218
- if (index === -1) return null;
219
- return getIconPosition(index);
220
- }, [minimizedTools]);
221
- const value = useMemo(() => ({
222
- minimizedTools,
223
- minimize,
224
- restore,
225
- isMinimized,
226
- getMinimizedTool,
227
- clearAll,
228
- count: minimizedTools.length,
229
- getNextIconPosition,
230
- getToolIconPosition
231
- }), [minimizedTools, minimize, restore, isMinimized, getMinimizedTool, clearAll, getNextIconPosition, getToolIconPosition]);
232
- return /*#__PURE__*/_jsx(MinimizedToolsContext.Provider, {
233
- value: value,
234
- children: children
235
- });
236
- }
237
-
238
- // ============================================================================
239
- // Hook
240
- // ============================================================================
241
-
242
- /**
243
- * Hook to access minimized tools context.
244
- * Must be used within a MinimizedToolsProvider.
245
- */
246
- export function useMinimizedTools() {
247
- const context = useContext(MinimizedToolsContext);
248
- if (!context) {
249
- // Return a no-op implementation when outside provider
250
- return {
251
- minimizedTools: [],
252
- minimize: () => {},
253
- restore: () => null,
254
- isMinimized: () => false,
255
- getMinimizedTool: () => undefined,
256
- clearAll: () => {},
257
- count: 0,
258
- getNextIconPosition: () => ({
259
- x: 0,
260
- y: 0
261
- }),
262
- getToolIconPosition: () => null
263
- };
264
- }
265
- return context;
266
- }
1
+ "use strict";import J,{createContext as N,useContext as w,useState as _,useCallback as s,useEffect as T,useRef as z,useMemo as y}from"react";import{Dimensions as v}from"react-native";import{persistentStorage as A,getSafeAreaInsets as b}from"@buoy-gg/shared-ui";import{jsx as D}from"react/jsx-runtime";const a=44;const F=12;const G=100;const Y=16;export function getIconPosition(r){const{width:u,height:n}=v.get("window");const c=b();const m=u-a-Y;const d=n-c.bottom-G-a;const f=d-r*(a+F);return{x:m,y:f}}export function getIconSize(){return a}const O="@react_buoy_minimized_tools";const j=500;const P=N(null);export function MinimizedToolsProvider({children:r,getToolIcon:u}){const[n,c]=_([]);const m=z([]);const[d,f]=_(false);const l=z(null);const g=z(u);T(()=>{g.current=u},[u]);T(()=>{const t=async()=>{try{const e=await A.getItem(O);if(e){const i=JSON.parse(e);const o=i.map(R=>({...R,icon:g.current?.(R.id)??null}));c(o)}}catch(e){}f(true)};t()},[]);m.current=n;T(()=>{if(!d)return;if(l.current){clearTimeout(l.current)}l.current=setTimeout(()=>{const t=n.map(({icon:e,...i})=>i);A.setItem(O,JSON.stringify(t))},j);return()=>{if(l.current){clearTimeout(l.current)}}},[n,d]);const I=s(t=>{c(e=>{const i=e.find(o=>o.id===t.id);if(i){return e.map(o=>o.id===t.id?{...t,minimizedAt:Date.now()}:o)}return[...e,{...t,minimizedAt:Date.now()}]})},[]);const x=s(t=>{const e=m.current.find(i=>i.instanceId===t)??null;if(!e)return null;c(i=>i.filter(o=>o.instanceId!==t));return e},[]);const p=s(t=>{return n.some(e=>e.id===t)},[n]);const S=s(t=>{return n.find(e=>e.instanceId===t)},[n]);const M=s(()=>{c([])},[]);const h=s(()=>{return getIconPosition(n.length)},[n.length]);const E=s(t=>{const e=n.findIndex(i=>i.instanceId===t);if(e===-1)return null;return getIconPosition(e)},[n]);const C=y(()=>({minimizedTools:n,minimize:I,restore:x,isMinimized:p,getMinimizedTool:S,clearAll:M,count:n.length,getNextIconPosition:h,getToolIconPosition:E}),[n,I,x,p,S,M,h,E]);return D(P.Provider,{value:C,children:r})}export function useMinimizedTools(){const r=w(P);if(!r){return{minimizedTools:[],minimize:()=>{},restore:()=>null,isMinimized:()=>false,getMinimizedTool:()=>void 0,clearAll:()=>{},count:0,getNextIconPosition:()=>({x:0,y:0}),getToolIconPosition:()=>null}}return r}