@buoy-gg/core 7.0.40 → 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 (269) hide show
  1. package/README.md +14 -85
  2. package/bin/buoy.js +20 -347
  3. package/lib/commonjs/Buoy.js +1 -107
  4. package/lib/commonjs/browserRegister.js +1 -0
  5. package/lib/commonjs/browserRegister.server.js +1 -0
  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 -364
  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 -0
  14. package/lib/commonjs/floatingMenu/DefaultConfigContext.js +1 -45
  15. package/lib/commonjs/floatingMenu/DevToolsSettingsModal.js +1 -1119
  16. package/lib/commonjs/floatingMenu/DevToolsSettingsModal.shared.js +1 -0
  17. package/lib/commonjs/floatingMenu/DevToolsSettingsModal.web.js +1 -1048
  18. package/lib/commonjs/floatingMenu/DevToolsVisibilityContext.js +1 -49
  19. package/lib/commonjs/floatingMenu/FloatingDevTools.js +1 -554
  20. package/lib/commonjs/floatingMenu/FloatingDevTools.web.js +1 -401
  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 -371
  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 -461
  29. package/lib/commonjs/floatingMenu/autoExternalSync.js +1 -434
  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 -821
  34. package/lib/commonjs/floatingMenu/dial/DialHyperspace.js +1 -177
  35. package/lib/commonjs/floatingMenu/dial/DialIcon.js +1 -302
  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 -23
  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 -0
  52. package/lib/commonjs/index.js +1 -291
  53. package/lib/commonjs/index.web.js +1 -150
  54. package/lib/commonjs/reactDevtoolsTypes.js +1 -0
  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 -219
  60. package/lib/commonjs/utils/createWebTool.js +1 -0
  61. package/lib/commonjs/utils/createWebTools.js +1 -0
  62. package/lib/commonjs/version.js +1 -18
  63. package/lib/module/Buoy.js +1 -102
  64. package/lib/module/browserRegister.js +1 -0
  65. package/lib/module/browserRegister.server.js +1 -0
  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 -356
  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 -0
  74. package/lib/module/floatingMenu/DefaultConfigContext.js +1 -39
  75. package/lib/module/floatingMenu/DevToolsSettingsModal.js +1 -1115
  76. package/lib/module/floatingMenu/DevToolsSettingsModal.shared.js +1 -0
  77. package/lib/module/floatingMenu/DevToolsSettingsModal.web.js +1 -1055
  78. package/lib/module/floatingMenu/DevToolsVisibilityContext.js +1 -44
  79. package/lib/module/floatingMenu/FloatingDevTools.js +1 -551
  80. package/lib/module/floatingMenu/FloatingDevTools.web.js +1 -399
  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 -368
  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 -457
  89. package/lib/module/floatingMenu/autoExternalSync.js +1 -427
  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 -818
  94. package/lib/module/floatingMenu/dial/DialHyperspace.js +1 -173
  95. package/lib/module/floatingMenu/dial/DialIcon.js +1 -299
  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 -19
  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 -0
  112. package/lib/module/index.js +1 -41
  113. package/lib/module/index.web.js +1 -29
  114. package/lib/module/reactDevtoolsTypes.js +1 -0
  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 -213
  120. package/lib/module/utils/createWebTool.js +1 -0
  121. package/lib/module/utils/createWebTools.js +1 -0
  122. package/lib/module/version.js +1 -14
  123. package/lib/typescript/commonjs/browserRegister.d.ts +13 -0
  124. package/lib/typescript/commonjs/browserRegister.server.d.ts +6 -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/AppHost.web.d.ts +3 -3
  128. package/lib/typescript/commonjs/floatingMenu/BrowserToolRuntime.d.ts +14 -0
  129. package/lib/typescript/commonjs/floatingMenu/DevToolsSettingsModal.d.ts +2 -67
  130. package/lib/typescript/commonjs/floatingMenu/DevToolsSettingsModal.shared.d.ts +71 -0
  131. package/lib/typescript/commonjs/floatingMenu/DevToolsSettingsModal.web.d.ts +3 -16
  132. package/lib/typescript/commonjs/floatingMenu/FloatingDevTools.web.d.ts +12 -6
  133. package/lib/typescript/commonjs/floatingMenu/defaultConfig.d.ts +1 -1
  134. package/lib/typescript/commonjs/floatingMenu/settingsBus.d.ts +1 -9
  135. package/lib/typescript/commonjs/floatingMenu/useDesktopSyncStatus.web.d.ts +3 -0
  136. package/lib/typescript/commonjs/index.web.d.ts +7 -0
  137. package/lib/typescript/commonjs/reactDevtoolsTypes.d.ts +8 -0
  138. package/lib/typescript/commonjs/releaseOptIn.d.ts +4 -0
  139. package/lib/typescript/commonjs/utils/autoDiscoverPresets.web.d.ts +3 -40
  140. package/lib/typescript/commonjs/utils/createWebTool.d.ts +6 -0
  141. package/lib/typescript/commonjs/utils/createWebTools.d.ts +4 -0
  142. package/lib/typescript/commonjs/version.d.ts +1 -1
  143. package/lib/typescript/module/browserRegister.d.ts +13 -0
  144. package/lib/typescript/module/browserRegister.server.d.ts +6 -0
  145. package/lib/typescript/module/earlyHookScript.d.ts +12 -0
  146. package/lib/typescript/module/earlyNetwork.d.ts +52 -0
  147. package/lib/typescript/module/floatingMenu/AppHost.web.d.ts +3 -3
  148. package/lib/typescript/module/floatingMenu/BrowserToolRuntime.d.ts +14 -0
  149. package/lib/typescript/module/floatingMenu/DevToolsSettingsModal.d.ts +2 -67
  150. package/lib/typescript/module/floatingMenu/DevToolsSettingsModal.shared.d.ts +71 -0
  151. package/lib/typescript/module/floatingMenu/DevToolsSettingsModal.web.d.ts +3 -16
  152. package/lib/typescript/module/floatingMenu/FloatingDevTools.web.d.ts +12 -6
  153. package/lib/typescript/module/floatingMenu/defaultConfig.d.ts +1 -1
  154. package/lib/typescript/module/floatingMenu/settingsBus.d.ts +1 -9
  155. package/lib/typescript/module/floatingMenu/useDesktopSyncStatus.web.d.ts +3 -0
  156. package/lib/typescript/module/index.web.d.ts +7 -0
  157. package/lib/typescript/module/reactDevtoolsTypes.d.ts +8 -0
  158. package/lib/typescript/module/releaseOptIn.d.ts +4 -0
  159. package/lib/typescript/module/utils/autoDiscoverPresets.web.d.ts +3 -40
  160. package/lib/typescript/module/utils/createWebTool.d.ts +6 -0
  161. package/lib/typescript/module/utils/createWebTools.d.ts +4 -0
  162. package/lib/typescript/module/version.d.ts +1 -1
  163. package/lib/web/chunks/chunk-5SGL6QL4.mjs +1 -0
  164. package/lib/web/chunks/chunk-FROELTJH.mjs +1 -0
  165. package/lib/web/chunks/chunk-QZDVCMCT.mjs +1 -0
  166. package/lib/web/chunks/chunk-R7RGRTY5.mjs +1 -0
  167. package/lib/web/index.mjs +10 -0
  168. package/lib/web/register-server.mjs +1 -0
  169. package/lib/web/register.mjs +1 -0
  170. package/lib/web/toolkit.mjs +1 -0
  171. package/package.json +50 -12
  172. package/lib/typescript/commonjs/Buoy.d.ts.map +0 -1
  173. package/lib/typescript/commonjs/floatingMenu/AppHost.d.ts.map +0 -1
  174. package/lib/typescript/commonjs/floatingMenu/AppHost.web.d.ts.map +0 -1
  175. package/lib/typescript/commonjs/floatingMenu/AppHostLogic.d.ts.map +0 -1
  176. package/lib/typescript/commonjs/floatingMenu/AppIcon.d.ts.map +0 -1
  177. package/lib/typescript/commonjs/floatingMenu/AppIcon.web.d.ts.map +0 -1
  178. package/lib/typescript/commonjs/floatingMenu/DefaultConfigContext.d.ts.map +0 -1
  179. package/lib/typescript/commonjs/floatingMenu/DevToolsSettingsModal.d.ts.map +0 -1
  180. package/lib/typescript/commonjs/floatingMenu/DevToolsSettingsModal.web.d.ts.map +0 -1
  181. package/lib/typescript/commonjs/floatingMenu/DevToolsVisibilityContext.d.ts.map +0 -1
  182. package/lib/typescript/commonjs/floatingMenu/FloatingDevTools.d.ts.map +0 -1
  183. package/lib/typescript/commonjs/floatingMenu/FloatingDevTools.web.d.ts.map +0 -1
  184. package/lib/typescript/commonjs/floatingMenu/FloatingMenu.d.ts.map +0 -1
  185. package/lib/typescript/commonjs/floatingMenu/MinimizedToolsContext.d.ts.map +0 -1
  186. package/lib/typescript/commonjs/floatingMenu/MinimizedToolsStack.d.ts.map +0 -1
  187. package/lib/typescript/commonjs/floatingMenu/MinimizedToolsStack.web.d.ts.map +0 -1
  188. package/lib/typescript/commonjs/floatingMenu/ToggleStateManager.d.ts.map +0 -1
  189. package/lib/typescript/commonjs/floatingMenu/ToolHost.d.ts.map +0 -1
  190. package/lib/typescript/commonjs/floatingMenu/ToolOpenerBridge.d.ts.map +0 -1
  191. package/lib/typescript/commonjs/floatingMenu/autoDiscoverPresets.d.ts.map +0 -1
  192. package/lib/typescript/commonjs/floatingMenu/autoExternalSync.d.ts.map +0 -1
  193. package/lib/typescript/commonjs/floatingMenu/defaultConfig.d.ts.map +0 -1
  194. package/lib/typescript/commonjs/floatingMenu/deviceIdentity.d.ts.map +0 -1
  195. package/lib/typescript/commonjs/floatingMenu/dial/DialDevTools.d.ts.map +0 -1
  196. package/lib/typescript/commonjs/floatingMenu/dial/DialDevTools.web.d.ts.map +0 -1
  197. package/lib/typescript/commonjs/floatingMenu/dial/DialHyperspace.d.ts.map +0 -1
  198. package/lib/typescript/commonjs/floatingMenu/dial/DialIcon.d.ts.map +0 -1
  199. package/lib/typescript/commonjs/floatingMenu/dial/DialPagination.d.ts.map +0 -1
  200. package/lib/typescript/commonjs/floatingMenu/dial/DialSnow.d.ts.map +0 -1
  201. package/lib/typescript/commonjs/floatingMenu/dial/OnboardingTooltip.d.ts.map +0 -1
  202. package/lib/typescript/commonjs/floatingMenu/dial/OnboardingTooltip.web.d.ts.map +0 -1
  203. package/lib/typescript/commonjs/floatingMenu/dial/dialUsageStore.d.ts.map +0 -1
  204. package/lib/typescript/commonjs/floatingMenu/dial/onboardingConstants.d.ts.map +0 -1
  205. package/lib/typescript/commonjs/floatingMenu/dial/onboardingConstants.web.d.ts.map +0 -1
  206. package/lib/typescript/commonjs/floatingMenu/externalSyncGate.d.ts.map +0 -1
  207. package/lib/typescript/commonjs/floatingMenu/floatingTools.d.ts.map +0 -1
  208. package/lib/typescript/commonjs/floatingMenu/floatingTools.web.d.ts.map +0 -1
  209. package/lib/typescript/commonjs/floatingMenu/optionalRequire.d.ts.map +0 -1
  210. package/lib/typescript/commonjs/floatingMenu/settingsBus.d.ts.map +0 -1
  211. package/lib/typescript/commonjs/floatingMenu/sync/appSyncAdapter.d.ts.map +0 -1
  212. package/lib/typescript/commonjs/floatingMenu/types.d.ts.map +0 -1
  213. package/lib/typescript/commonjs/floatingMenu/useDesktopSyncStatus.d.ts.map +0 -1
  214. package/lib/typescript/commonjs/index.d.ts.map +0 -1
  215. package/lib/typescript/commonjs/index.web.d.ts.map +0 -1
  216. package/lib/typescript/commonjs/telemetry/installPing.d.ts.map +0 -1
  217. package/lib/typescript/commonjs/toolkit.d.ts.map +0 -1
  218. package/lib/typescript/commonjs/toolkitComponents.d.ts.map +0 -1
  219. package/lib/typescript/commonjs/utils/autoDiscoverPresets.web.d.ts.map +0 -1
  220. package/lib/typescript/commonjs/version.d.ts.map +0 -1
  221. package/lib/typescript/module/Buoy.d.ts.map +0 -1
  222. package/lib/typescript/module/floatingMenu/AppHost.d.ts.map +0 -1
  223. package/lib/typescript/module/floatingMenu/AppHost.web.d.ts.map +0 -1
  224. package/lib/typescript/module/floatingMenu/AppHostLogic.d.ts.map +0 -1
  225. package/lib/typescript/module/floatingMenu/AppIcon.d.ts.map +0 -1
  226. package/lib/typescript/module/floatingMenu/AppIcon.web.d.ts.map +0 -1
  227. package/lib/typescript/module/floatingMenu/DefaultConfigContext.d.ts.map +0 -1
  228. package/lib/typescript/module/floatingMenu/DevToolsSettingsModal.d.ts.map +0 -1
  229. package/lib/typescript/module/floatingMenu/DevToolsSettingsModal.web.d.ts.map +0 -1
  230. package/lib/typescript/module/floatingMenu/DevToolsVisibilityContext.d.ts.map +0 -1
  231. package/lib/typescript/module/floatingMenu/FloatingDevTools.d.ts.map +0 -1
  232. package/lib/typescript/module/floatingMenu/FloatingDevTools.web.d.ts.map +0 -1
  233. package/lib/typescript/module/floatingMenu/FloatingMenu.d.ts.map +0 -1
  234. package/lib/typescript/module/floatingMenu/MinimizedToolsContext.d.ts.map +0 -1
  235. package/lib/typescript/module/floatingMenu/MinimizedToolsStack.d.ts.map +0 -1
  236. package/lib/typescript/module/floatingMenu/MinimizedToolsStack.web.d.ts.map +0 -1
  237. package/lib/typescript/module/floatingMenu/ToggleStateManager.d.ts.map +0 -1
  238. package/lib/typescript/module/floatingMenu/ToolHost.d.ts.map +0 -1
  239. package/lib/typescript/module/floatingMenu/ToolOpenerBridge.d.ts.map +0 -1
  240. package/lib/typescript/module/floatingMenu/autoDiscoverPresets.d.ts.map +0 -1
  241. package/lib/typescript/module/floatingMenu/autoExternalSync.d.ts.map +0 -1
  242. package/lib/typescript/module/floatingMenu/defaultConfig.d.ts.map +0 -1
  243. package/lib/typescript/module/floatingMenu/deviceIdentity.d.ts.map +0 -1
  244. package/lib/typescript/module/floatingMenu/dial/DialDevTools.d.ts.map +0 -1
  245. package/lib/typescript/module/floatingMenu/dial/DialDevTools.web.d.ts.map +0 -1
  246. package/lib/typescript/module/floatingMenu/dial/DialHyperspace.d.ts.map +0 -1
  247. package/lib/typescript/module/floatingMenu/dial/DialIcon.d.ts.map +0 -1
  248. package/lib/typescript/module/floatingMenu/dial/DialPagination.d.ts.map +0 -1
  249. package/lib/typescript/module/floatingMenu/dial/DialSnow.d.ts.map +0 -1
  250. package/lib/typescript/module/floatingMenu/dial/OnboardingTooltip.d.ts.map +0 -1
  251. package/lib/typescript/module/floatingMenu/dial/OnboardingTooltip.web.d.ts.map +0 -1
  252. package/lib/typescript/module/floatingMenu/dial/dialUsageStore.d.ts.map +0 -1
  253. package/lib/typescript/module/floatingMenu/dial/onboardingConstants.d.ts.map +0 -1
  254. package/lib/typescript/module/floatingMenu/dial/onboardingConstants.web.d.ts.map +0 -1
  255. package/lib/typescript/module/floatingMenu/externalSyncGate.d.ts.map +0 -1
  256. package/lib/typescript/module/floatingMenu/floatingTools.d.ts.map +0 -1
  257. package/lib/typescript/module/floatingMenu/floatingTools.web.d.ts.map +0 -1
  258. package/lib/typescript/module/floatingMenu/optionalRequire.d.ts.map +0 -1
  259. package/lib/typescript/module/floatingMenu/settingsBus.d.ts.map +0 -1
  260. package/lib/typescript/module/floatingMenu/sync/appSyncAdapter.d.ts.map +0 -1
  261. package/lib/typescript/module/floatingMenu/types.d.ts.map +0 -1
  262. package/lib/typescript/module/floatingMenu/useDesktopSyncStatus.d.ts.map +0 -1
  263. package/lib/typescript/module/index.d.ts.map +0 -1
  264. package/lib/typescript/module/index.web.d.ts.map +0 -1
  265. package/lib/typescript/module/telemetry/installPing.d.ts.map +0 -1
  266. package/lib/typescript/module/toolkit.d.ts.map +0 -1
  267. package/lib/typescript/module/toolkitComponents.d.ts.map +0 -1
  268. package/lib/typescript/module/utils/autoDiscoverPresets.web.d.ts.map +0 -1
  269. package/lib/typescript/module/version.d.ts.map +0 -1
@@ -1,821 +1 @@
1
- "use strict";
2
-
3
- Object.defineProperty(exports, "__esModule", {
4
- value: true
5
- });
6
- exports.DialMenu = DialMenu;
7
- var _react = require("react");
8
- var _floatingToolsReact = require("@buoy-gg/floating-tools-react");
9
- var _sharedUi = require("@buoy-gg/shared-ui");
10
- var _OnboardingTooltipWeb = require("./OnboardingTooltip.web.js");
11
- var _jsxRuntime = require("react/jsx-runtime");
12
- /**
13
- * DialDevTools - Web renderer for the radial dial menu.
14
- *
15
- * Uses shared layout calculations, styling, and animation config from @buoy-gg/floating-tools-core.
16
- * Platform-specific: CSS animations, mouse events, web JSX.
17
- *
18
- * Visuals mirror the native DialDevTools.tsx exactly — values that never made
19
- * it into the shared dial.ts are inlined here with provenance comments.
20
- *
21
- * @platform React DOM Web (Vite, CRA, Next.js, Electron)
22
- */
23
-
24
- // native DialDevTools.tsx SETTINGS_TOOLTIP_KEY
25
- const SETTINGS_TOOLTIP_KEY = '@react_buoy_settings_tooltip_shown';
26
-
27
- // Inject CSS keyframes once on module load
28
- let keyframesInjected = false;
29
- function injectKeyframes() {
30
- if (keyframesInjected || typeof document === 'undefined') return;
31
- const style = document.createElement('style');
32
- style.textContent = (0, _floatingToolsReact.getDialCSSKeyframesString)();
33
- document.head.appendChild(style);
34
- keyframesInjected = true;
35
- }
36
-
37
- // Easing functions
38
- const easeOutCubic = t => 1 - Math.pow(1 - t, 3);
39
- const easeInCubic = t => t * t * t;
40
-
41
- // =============================
42
- // Types
43
- // =============================
44
-
45
- // =============================
46
- // Dial Icon Component
47
- // =============================
48
-
49
- function DialIconItem({
50
- icon,
51
- index,
52
- totalIcons,
53
- position,
54
- progress,
55
- onPress
56
- }) {
57
- const [isHovered, setIsHovered] = (0, _react.useState)(false);
58
- const [isPressed, setIsPressed] = (0, _react.useState)(false);
59
- const isEmpty = !icon.icon && icon.id.startsWith('empty-');
60
- const isUnavailable = !isEmpty && icon.unavailable === true;
61
- const interactive = !isEmpty && !isUnavailable;
62
- const {
63
- icons: iconConfig
64
- } = _floatingToolsReact.dialAnimationConfig;
65
-
66
- // Get stagger input range for this icon
67
- const staggerInputRange = (0, _floatingToolsReact.getIconStaggerInputRange)(index, totalIcons);
68
-
69
- // Calculate this icon's individual progress based on the global progress
70
- let iconProgress = 0;
71
- if (progress <= staggerInputRange[1]) {
72
- iconProgress = 0;
73
- } else if (progress <= staggerInputRange[2]) {
74
- iconProgress = (progress - staggerInputRange[1]) / (staggerInputRange[2] - staggerInputRange[1]);
75
- } else {
76
- iconProgress = 1;
77
- }
78
- iconProgress = Math.max(0, Math.min(1, iconProgress));
79
- const iconSize = _floatingToolsReact.DIAL_ICON_SIZE;
80
- const pressedScale = iconConfig.pressIn.scale;
81
- const hoveredScale = 1.1; // web-only hover affordance (no native counterpart)
82
-
83
- const scale = iconProgress * (isPressed ? pressedScale : isHovered ? hoveredScale : 1);
84
-
85
- // Opacity interpolation — native DialIcon.tsx: [0, 0.3, 1] -> [0, 0.3, 1]
86
- let opacity = 0;
87
- if (iconProgress <= 0) {
88
- opacity = 0;
89
- } else if (iconProgress <= 0.3) {
90
- opacity = iconProgress;
91
- } else {
92
- opacity = 0.3 + (iconProgress - 0.3) * (0.7 / 0.7);
93
- }
94
- const x = position.x * iconProgress;
95
- const y = position.y * iconProgress;
96
- return /*#__PURE__*/(0, _jsxRuntime.jsx)("button", {
97
- role: "menuitem",
98
- "aria-label": isEmpty ? 'Empty slot' : icon.name,
99
- "aria-disabled": !interactive,
100
- tabIndex: interactive ? 0 : -1,
101
- onClick: interactive ? onPress : undefined,
102
- onMouseEnter: () => interactive && setIsHovered(true),
103
- onMouseLeave: () => {
104
- setIsHovered(false);
105
- setIsPressed(false);
106
- },
107
- onMouseDown: () => interactive && setIsPressed(true),
108
- onMouseUp: () => setIsPressed(false),
109
- style: {
110
- position: 'absolute',
111
- left: '50%',
112
- top: '50%',
113
- width: iconSize,
114
- height: iconSize,
115
- marginLeft: -iconSize / 2,
116
- marginTop: -iconSize / 2,
117
- display: 'flex',
118
- flexDirection: 'column',
119
- alignItems: 'center',
120
- justifyContent: 'center',
121
- cursor: interactive ? 'pointer' : 'default',
122
- transform: `translate(${x}px, ${y}px) scale(${scale})`,
123
- opacity,
124
- transition: isHovered || isPressed ? 'transform 100ms ease' : 'none',
125
- background: 'none',
126
- border: 'none',
127
- padding: 0
128
- },
129
- children: isEmpty ? /*#__PURE__*/(0, _jsxRuntime.jsx)("div", {
130
- style: {
131
- width: _floatingToolsReact.dialStyles.emptySlot.dotSize,
132
- height: _floatingToolsReact.dialStyles.emptySlot.dotSize,
133
- borderRadius: _floatingToolsReact.dialStyles.emptySlot.dotSize / 2,
134
- backgroundColor: _floatingToolsReact.dialColors.emptyDotBackground,
135
- border: `${_floatingToolsReact.dialStyles.emptySlot.borderWidth}px solid ${_floatingToolsReact.dialColors.emptyDotBorder}`
136
- }
137
- }) : /*#__PURE__*/(0, _jsxRuntime.jsxs)(_jsxRuntime.Fragment, {
138
- children: [/*#__PURE__*/(0, _jsxRuntime.jsx)("div", {
139
- style: {
140
- position: 'absolute',
141
- width: `${_floatingToolsReact.dialStyles.icon.gradientBgSizePercent}%`,
142
- height: `${_floatingToolsReact.dialStyles.icon.gradientBgSizePercent}%`,
143
- borderRadius: _floatingToolsReact.dialStyles.icon.gradientBgBorderRadius,
144
- backgroundColor: 'rgba(0, 0, 0, 0.2)',
145
- opacity: _floatingToolsReact.dialStyles.icon.gradientBgOpacity
146
- }
147
- }), /*#__PURE__*/(0, _jsxRuntime.jsx)("div", {
148
- style: {
149
- position: 'absolute',
150
- width: `${_floatingToolsReact.dialStyles.icon.innerGlowSizePercent}%`,
151
- height: `${_floatingToolsReact.dialStyles.icon.innerGlowSizePercent}%`,
152
- borderRadius: _floatingToolsReact.dialStyles.icon.innerGlowBorderRadius,
153
- backgroundColor: 'rgba(255, 255, 255, 0.02)',
154
- opacity: _floatingToolsReact.dialStyles.icon.innerGlowOpacity
155
- }
156
- }), /*#__PURE__*/(0, _jsxRuntime.jsx)("div", {
157
- style: {
158
- marginBottom: _floatingToolsReact.dialStyles.icon.wrapperMarginBottom,
159
- display: 'flex',
160
- alignItems: 'center',
161
- justifyContent: 'center',
162
- fontSize: 32,
163
- // native DialIcon.tsx: icon rendered at size 32
164
- filter: isHovered ? 'brightness(1.2)' : 'none'
165
- },
166
- children: icon.icon
167
- }), /*#__PURE__*/(0, _jsxRuntime.jsx)("span", {
168
- style: {
169
- fontSize:
170
- // native: adjustsFontSizeToFit minimumFontScale 0.7 — long
171
- // names shrink instead of wrapping/overflowing the slot.
172
- icon.name.length > 8 ? Math.max(_floatingToolsReact.dialStyles.icon.label.fontSize * 0.7, _floatingToolsReact.dialStyles.icon.label.fontSize * 8 / icon.name.length) : _floatingToolsReact.dialStyles.icon.label.fontSize,
173
- fontWeight: _floatingToolsReact.dialStyles.icon.label.fontWeight,
174
- fontFamily: _floatingToolsReact.dialStyles.icon.label.fontFamily,
175
- color: _floatingToolsReact.dialColors.iconLabel,
176
- letterSpacing: _floatingToolsReact.dialStyles.icon.label.letterSpacing,
177
- marginTop: _floatingToolsReact.dialStyles.icon.label.marginTop,
178
- textTransform: 'uppercase',
179
- whiteSpace: 'nowrap'
180
- },
181
- children: icon.name
182
- }), isUnavailable &&
183
- /*#__PURE__*/
184
- // native DialIcon.tsx unavailableCaption: label size - 1, muted
185
- (0, _jsxRuntime.jsx)("span", {
186
- style: {
187
- fontSize: _floatingToolsReact.dialStyles.icon.label.fontSize - 1,
188
- fontWeight: _floatingToolsReact.dialStyles.icon.label.fontWeight,
189
- fontFamily: _floatingToolsReact.dialStyles.icon.label.fontFamily,
190
- letterSpacing: _floatingToolsReact.dialStyles.icon.label.letterSpacing,
191
- color: _floatingToolsReact.floatingToolsColors.muted,
192
- textTransform: 'uppercase',
193
- whiteSpace: 'nowrap'
194
- },
195
- children: "Unavailable"
196
- })]
197
- })
198
- });
199
- }
200
-
201
- // =============================
202
- // Pagination (mirrors native DialPagination.tsx)
203
- // =============================
204
-
205
- /**
206
- * Chevron glyph matching the native pager's ChevronLeft/ChevronRight from
207
- * @buoy-gg/shared-ui (lucide two-line chevron, size 18, strokeWidth 2).
208
- * Inlined as SVG because shared-ui is React Native-only.
209
- */
210
- function PagerChevron({
211
- side,
212
- color
213
- }) {
214
- // native lucide-icons.tsx ChevronLeft: (15,18)->(9,12)->(15,6); ChevronRight mirrored
215
- const lines = side === 'prev' ? [[15, 18, 9, 12], [9, 12, 15, 6]] : [[9, 18, 15, 12], [15, 12, 9, 6]];
216
- return /*#__PURE__*/(0, _jsxRuntime.jsx)("svg", {
217
- width: 18,
218
- height: 18,
219
- viewBox: "0 0 24 24",
220
- "aria-hidden": "true",
221
- focusable: "false",
222
- children: lines.map(([x1, y1, x2, y2], i) => /*#__PURE__*/(0, _jsxRuntime.jsx)("line", {
223
- x1: x1,
224
- y1: y1,
225
- x2: x2,
226
- y2: y2,
227
- stroke: color,
228
- strokeWidth: 2
229
- }, i))
230
- });
231
- }
232
- function PagerButton({
233
- side,
234
- disabled,
235
- onClick
236
- }) {
237
- const [isPressed, setIsPressed] = (0, _react.useState)(false);
238
-
239
- // native DialPagination.tsx: accent = disabled ? emptyDotBorder : dialColors.accent
240
- const accent = disabled ? _floatingToolsReact.dialColors.emptyDotBorder : _floatingToolsReact.dialColors.accent;
241
- return /*#__PURE__*/(0, _jsxRuntime.jsxs)("button", {
242
- type: "button",
243
- "aria-label": `${side === 'prev' ? 'Previous' : 'Next'} dial page`,
244
- disabled: disabled,
245
- onClick: onClick,
246
- onMouseDown: () => !disabled && setIsPressed(true),
247
- onMouseUp: () => setIsPressed(false),
248
- onMouseLeave: () => setIsPressed(false),
249
- style: {
250
- display: 'flex',
251
- alignItems: 'center',
252
- gap: 4,
253
- // native DialPagination.tsx: gap 4
254
- padding: '10px 16px',
255
- // native: paddingVertical 10, paddingHorizontal 16
256
- borderRadius: 10,
257
- border: `1px solid ${_floatingToolsReact.dialColors.dialBorder}`,
258
- backgroundColor: _floatingToolsReact.dialColors.dialBackground,
259
- // native: buttonText night text, buttonTextDisabled iconLabelMuted
260
- color: disabled ? _floatingToolsReact.dialColors.iconLabelMuted : _floatingToolsReact.dialColors.centerText,
261
- fontSize: 12,
262
- fontWeight: 900,
263
- fontFamily: _sharedUi.monoFont,
264
- letterSpacing: 1.5,
265
- textTransform: 'uppercase',
266
- cursor: disabled ? 'default' : 'pointer',
267
- opacity: disabled ? 0.4 : 1,
268
- // native: buttonDisabled opacity 0.4
269
- // native: shadowColor dialShadow, shadowOpacity 0.4, shadowRadius 8
270
- boxShadow: disabled ? 'none' : `0 0 8px ${(0, _floatingToolsReact.withAlpha)(_floatingToolsReact.dialColors.dialShadow, 0.4)}`,
271
- // native: press-in springs to scale 0.92
272
- transform: isPressed ? 'scale(0.92)' : 'scale(1)',
273
- transition: 'transform 100ms ease'
274
- },
275
- children: [side === 'prev' && /*#__PURE__*/(0, _jsxRuntime.jsx)(PagerChevron, {
276
- side: "prev",
277
- color: accent
278
- }), side === 'prev' ? 'PREV' : 'NEXT', side === 'next' && /*#__PURE__*/(0, _jsxRuntime.jsx)(PagerChevron, {
279
- side: "next",
280
- color: accent
281
- })]
282
- });
283
- }
284
-
285
- // =============================
286
- // Main DialMenu Component
287
- // =============================
288
-
289
- function DialMenu({
290
- icons,
291
- onClose,
292
- centerLabel = 'MENU',
293
- onCenterPress,
294
- settingsOpen = false,
295
- hintsDisabled = false
296
- }) {
297
- // Animation values
298
- const [backdropOpacity, setBackdropOpacity] = (0, _react.useState)(0);
299
- const [dialScale, setDialScale] = (0, _react.useState)(0);
300
- const [dialRotation, setDialRotation] = (0, _react.useState)(0);
301
- const [centerButtonScale, setCenterButtonScale] = (0, _react.useState)(0);
302
- const [iconProgress, setIconProgress] = (0, _react.useState)(0);
303
- const [centerPulseScale, setCenterPulseScale] = (0, _react.useState)(1);
304
-
305
- // UI state
306
- const [isHoveringCenter, setIsHoveringCenter] = (0, _react.useState)(false);
307
- const [isExiting, setIsExiting] = (0, _react.useState)(false);
308
- const [entranceComplete, setEntranceComplete] = (0, _react.useState)(false);
309
-
310
- // Refs
311
- const animationRef = (0, _react.useRef)(null);
312
- const isClosingRef = (0, _react.useRef)(false);
313
-
314
- // Config
315
- const {
316
- entrance,
317
- exit,
318
- interaction
319
- } = _floatingToolsReact.dialAnimationConfig;
320
- const cssAnimations = (0, _floatingToolsReact.getDialCSSAnimationStyles)();
321
-
322
- // Layout
323
- const layout = (0, _react.useMemo)(() => (0, _floatingToolsReact.getDialLayout)({
324
- screenWidth: window.innerWidth
325
- }), []);
326
- const gridRotations = (0, _react.useMemo)(() => (0, _floatingToolsReact.getGridLineRotations)(), []);
327
- const positions = (0, _react.useMemo)(() => (0, _floatingToolsReact.getAllIconPositions)(_floatingToolsReact.MAX_DIAL_SLOTS, layout.iconRadius), [layout.iconRadius]);
328
-
329
- // Pagination: tools are split across pages of MAX_DIAL_SLOTS.
330
- const [currentPage, setCurrentPage] = (0, _react.useState)(0);
331
- const pageCount = Math.max(1, Math.ceil(icons.length / _floatingToolsReact.MAX_DIAL_SLOTS));
332
- const safePage = Math.min(currentPage, pageCount - 1);
333
- const paddedIcons = (0, _react.useMemo)(() => {
334
- const start = safePage * _floatingToolsReact.MAX_DIAL_SLOTS;
335
- const result = [...icons.slice(start, start + _floatingToolsReact.MAX_DIAL_SLOTS)];
336
- while (result.length < _floatingToolsReact.MAX_DIAL_SLOTS) {
337
- result.push({
338
- id: `empty-${result.length}`,
339
- name: '',
340
- icon: null,
341
- onPress: () => {}
342
- });
343
- }
344
- return result;
345
- }, [icons, safePage]);
346
-
347
- // Inject keyframes
348
- (0, _react.useEffect)(() => {
349
- injectKeyframes();
350
- }, []);
351
-
352
- // ENTRANCE Animation - runs once on mount
353
- (0, _react.useEffect)(() => {
354
- // Capture config values at mount time
355
- const backdropDuration = entrance.backdrop.duration;
356
- const rotationDuration = entrance.dial.rotation.duration;
357
- const centerButtonDelay = entrance.centerButton.delay;
358
- const iconsDelay = entrance.icons.delay;
359
- const iconsDuration = entrance.icons.duration;
360
- const startTime = performance.now();
361
- const animate = currentTime => {
362
- const elapsed = currentTime - startTime;
363
-
364
- // Backdrop (0-400ms)
365
- setBackdropOpacity(Math.min(1, elapsed / backdropDuration));
366
-
367
- // Dial scale with spring overshoot (~400ms)
368
- const dialProgress = Math.min(1, elapsed / 400);
369
- let springScale = easeOutCubic(dialProgress) * 1.1;
370
- if (dialProgress > 0.7) {
371
- springScale -= (dialProgress - 0.7) * 0.33;
372
- }
373
- if (dialProgress >= 1) springScale = 1;
374
- setDialScale(Math.max(0, Math.min(1.05, springScale)));
375
-
376
- // Dial rotation (0-800ms)
377
- const rotProgress = Math.min(1, elapsed / rotationDuration);
378
- setDialRotation(easeOutCubic(rotProgress) * 360);
379
-
380
- // Center button (300ms delay)
381
- if (elapsed >= centerButtonDelay) {
382
- const centerProgress = Math.min(1, (elapsed - centerButtonDelay) / 300);
383
- let centerSpring = easeOutCubic(centerProgress) * 1.15;
384
- if (centerProgress > 0.6) {
385
- centerSpring -= (centerProgress - 0.6) * 0.375;
386
- }
387
- if (centerProgress >= 1) centerSpring = 1;
388
- setCenterButtonScale(Math.max(0, Math.min(1.05, centerSpring)));
389
- }
390
-
391
- // Icons (500ms delay, 600ms duration)
392
- if (elapsed >= iconsDelay) {
393
- const iconsProgress = Math.min(1, (elapsed - iconsDelay) / iconsDuration);
394
- setIconProgress(easeOutCubic(iconsProgress));
395
- }
396
-
397
- // Continue or finish
398
- const totalTime = iconsDelay + iconsDuration;
399
- if (elapsed < totalTime) {
400
- animationRef.current = requestAnimationFrame(animate);
401
- } else {
402
- // Finalize
403
- setBackdropOpacity(1);
404
- setDialScale(1);
405
- setDialRotation(360);
406
- setCenterButtonScale(1);
407
- setIconProgress(1);
408
- setEntranceComplete(true);
409
- }
410
- };
411
- animationRef.current = requestAnimationFrame(animate);
412
- return () => {
413
- if (animationRef.current) cancelAnimationFrame(animationRef.current);
414
- };
415
- }, []);
416
-
417
- // EXIT Animation
418
- const handleClose = (0, _react.useCallback)(() => {
419
- if (isClosingRef.current) return;
420
- isClosingRef.current = true;
421
- setIsExiting(true);
422
- if (animationRef.current) {
423
- cancelAnimationFrame(animationRef.current);
424
- }
425
- const startTime = performance.now();
426
- const iconsDuration = exit.icons.duration;
427
- const centerDuration = exit.centerButton.duration;
428
- const dialDuration = exit.dialScale.duration;
429
- const step2Duration = Math.max(centerDuration, dialDuration);
430
- const backdropDuration = exit.backdrop.duration;
431
- const animate = currentTime => {
432
- const elapsed = currentTime - startTime;
433
-
434
- // Step 1: Icons collapse (0 - 300ms)
435
- if (elapsed < iconsDuration) {
436
- const progress = easeInCubic(elapsed / iconsDuration);
437
- setIconProgress(1 - progress);
438
- animationRef.current = requestAnimationFrame(animate);
439
- return;
440
- }
441
-
442
- // Step 2: Dial + Center scale down in parallel — native runs the center
443
- // button (200ms) and dial (250ms) with their own durations.
444
- const step2Start = iconsDuration;
445
- if (elapsed < step2Start + step2Duration) {
446
- setIconProgress(0);
447
- const centerProgress = Math.min(1, (elapsed - step2Start) / centerDuration);
448
- const dialProgress = Math.min(1, (elapsed - step2Start) / dialDuration);
449
- setCenterButtonScale(1 - easeInCubic(centerProgress));
450
- setDialScale(1 - easeInCubic(dialProgress));
451
- animationRef.current = requestAnimationFrame(animate);
452
- return;
453
- }
454
-
455
- // Step 3: Backdrop fade (550 - 750ms)
456
- const step3Start = step2Start + step2Duration;
457
- if (elapsed < step3Start + backdropDuration) {
458
- setDialScale(0);
459
- setCenterButtonScale(0);
460
- const progress = (elapsed - step3Start) / backdropDuration;
461
- setBackdropOpacity(1 - progress);
462
- animationRef.current = requestAnimationFrame(animate);
463
- return;
464
- }
465
-
466
- // Done
467
- setBackdropOpacity(0);
468
- onClose();
469
- };
470
- animationRef.current = requestAnimationFrame(animate);
471
- }, [exit, onClose]);
472
-
473
- // Document-level Escape key handler
474
- (0, _react.useEffect)(() => {
475
- const handleKeyDown = e => {
476
- if (e.key === 'Escape') {
477
- handleClose();
478
- }
479
- };
480
- document.addEventListener('keydown', handleKeyDown);
481
- return () => document.removeEventListener('keydown', handleKeyDown);
482
- }, [handleClose]);
483
-
484
- // Settings onboarding tooltip — native DialDevTools.tsx:174-196: shown
485
- // 1200ms after the dial mounts (entrance animations settle first) if never
486
- // dismissed; suppressed while settings is open; dismissed forever when
487
- // settings opens.
488
- const [showSettingsTooltip, setShowSettingsTooltip] = (0, _react.useState)(false);
489
- (0, _react.useEffect)(() => {
490
- if (hintsDisabled) return;
491
- let cancelled = false;
492
- const timer = setTimeout(async () => {
493
- const seen = await _sharedUi.persistentStorage.getItem(SETTINGS_TOOLTIP_KEY);
494
- if (!cancelled && !seen) setShowSettingsTooltip(true);
495
- }, 1200);
496
- return () => {
497
- cancelled = true;
498
- clearTimeout(timer);
499
- };
500
- }, [hintsDisabled]);
501
- const dismissSettingsTooltip = (0, _react.useCallback)(() => {
502
- setShowSettingsTooltip(false);
503
- void _sharedUi.persistentStorage.setItem(SETTINGS_TOOLTIP_KEY, 'true');
504
- }, []);
505
- (0, _react.useEffect)(() => {
506
- if (settingsOpen && showSettingsTooltip) {
507
- dismissSettingsTooltip();
508
- }
509
- }, [settingsOpen, showSettingsTooltip, dismissSettingsTooltip]);
510
-
511
- // Icon press handler
512
- const handleIconPress = (0, _react.useCallback)(icon => {
513
- if (icon.id.startsWith('empty-') || isClosingRef.current) return;
514
-
515
- // Pulse animation
516
- const [pulseIn, pulseOut] = interaction.iconSelect.pulse;
517
- const startTime = performance.now();
518
- const pulseDuration = 150;
519
- const animatePulse = currentTime => {
520
- const elapsed = currentTime - startTime;
521
- if (elapsed < pulseDuration) {
522
- const progress = easeOutCubic(elapsed / pulseDuration);
523
- setCenterPulseScale(1 - (1 - pulseIn.scale) * progress);
524
- requestAnimationFrame(animatePulse);
525
- } else if (elapsed < pulseDuration * 2) {
526
- const progress = easeOutCubic((elapsed - pulseDuration) / pulseDuration);
527
- setCenterPulseScale(pulseIn.scale + (pulseOut.scale - pulseIn.scale) * progress);
528
- requestAnimationFrame(animatePulse);
529
- } else {
530
- setCenterPulseScale(1);
531
- }
532
- };
533
- requestAnimationFrame(animatePulse);
534
-
535
- // Trigger action after delay
536
- setTimeout(() => {
537
- icon.onPress();
538
- handleClose();
539
- }, interaction.iconSelect.actionDelay);
540
- }, [interaction.iconSelect, handleClose]);
541
-
542
- // Page navigation - icons are keyed by slot index, so this only swaps
543
- // their content in place (no remount, no re-animation) for an instant page
544
- // change.
545
- const handlePageChange = (0, _react.useCallback)(next => {
546
- if (isClosingRef.current) return;
547
- const clamped = Math.max(0, Math.min(next, pageCount - 1));
548
- if (clamped !== safePage) setCurrentPage(clamped);
549
- }, [pageCount, safePage]);
550
-
551
- // Computed values
552
- const buttonContainerSize = layout.buttonSize * _floatingToolsReact.dialStyles.centerButton.containerRatio;
553
- const buttonBorderSize = layout.buttonSize * _floatingToolsReact.dialStyles.centerButton.borderRatio;
554
- // Grid spokes stop this far from the centre: the hub's outer disc plus a breath.
555
- const hubClearance = layout.buttonSize * _floatingToolsReact.dialStyles.centerButton.containerRatio / 2 + 6;
556
- const isAnimating = entranceComplete && !isExiting;
557
- return /*#__PURE__*/(0, _jsxRuntime.jsxs)("div", {
558
- role: "dialog",
559
- "aria-label": "Dial Menu",
560
- "aria-modal": "true",
561
- style: {
562
- position: 'fixed',
563
- inset: 0,
564
- zIndex: 10000
565
- },
566
- children: [/*#__PURE__*/(0, _jsxRuntime.jsx)("div", {
567
- role: "button",
568
- "aria-label": "Close dial menu",
569
- tabIndex: 0,
570
- onClick: handleClose,
571
- onKeyDown: e => e.key === 'Escape' && handleClose(),
572
- style: {
573
- position: 'absolute',
574
- inset: 0,
575
- backgroundColor: _floatingToolsReact.dialColors.dialBackdrop,
576
- opacity: backdropOpacity
577
- }
578
- }), /*#__PURE__*/(0, _jsxRuntime.jsxs)("div", {
579
- style: {
580
- position: 'absolute',
581
- left: '50%',
582
- marginLeft: -layout.circleSize / 2,
583
- bottom: 80,
584
- // native DialDevTools.tsx: bottom: 80
585
- width: layout.circleSize,
586
- height: layout.circleSize,
587
- borderRadius: '50%',
588
- backgroundColor: _floatingToolsReact.dialColors.dialBackground,
589
- border: `${_floatingToolsReact.dialStyles.circle.borderWidth}px solid ${_floatingToolsReact.dialColors.dialBorder}`,
590
- // native: shadowColor dialShadow at shadowOpacity 0.5, shadowRadius 20
591
- boxShadow: `0 0 ${_floatingToolsReact.dialStyles.circle.shadowRadius}px ${(0, _floatingToolsReact.withAlpha)(_floatingToolsReact.dialColors.dialShadow, _floatingToolsReact.dialStyles.circle.shadowOpacity)}`,
592
- transform: `scale(${dialScale}) rotate(${dialRotation}deg)`,
593
- opacity: dialScale > 0.01 ? 1 : 0,
594
- overflow: 'hidden'
595
- },
596
- children: [/*#__PURE__*/(0, _jsxRuntime.jsx)("div", {
597
- style: {
598
- position: 'absolute',
599
- inset: 0,
600
- borderRadius: '50%',
601
- backgroundColor: _floatingToolsReact.dialColors.dialGradient1,
602
- opacity: _floatingToolsReact.dialStyles.gradientLayers[0].opacity
603
- }
604
- }), /*#__PURE__*/(0, _jsxRuntime.jsx)("div", {
605
- style: {
606
- position: 'absolute',
607
- inset: 0,
608
- top: '30%',
609
- left: '30%',
610
- borderRadius: '50%',
611
- backgroundColor: _floatingToolsReact.dialColors.dialGradient2,
612
- opacity: _floatingToolsReact.dialStyles.gradientLayers[1].opacity
613
- }
614
- }), /*#__PURE__*/(0, _jsxRuntime.jsx)("div", {
615
- style: {
616
- position: 'absolute',
617
- inset: 0,
618
- top: '50%',
619
- left: '50%',
620
- borderRadius: '50%',
621
- backgroundColor: _floatingToolsReact.dialColors.dialGradient3,
622
- opacity: _floatingToolsReact.dialStyles.gradientLayers[2].opacity
623
- }
624
- }), gridRotations.map(deg => /*#__PURE__*/(0, _jsxRuntime.jsx)("div", {
625
- style: {
626
- position: 'absolute',
627
- top: '50%',
628
- left: 0,
629
- right: 0,
630
- height: _floatingToolsReact.dialStyles.grid.lineHeight,
631
- transform: `rotate(${deg}deg)`,
632
- transformOrigin: 'center'
633
- },
634
- children: ['left', 'right'].map(side => /*#__PURE__*/(0, _jsxRuntime.jsx)("div", {
635
- style: {
636
- position: 'absolute',
637
- top: 0,
638
- [side]: 0,
639
- width: `calc(50% - ${hubClearance}px)`,
640
- height: _floatingToolsReact.dialStyles.grid.lineHeight,
641
- backgroundColor: _floatingToolsReact.dialColors.dialGridLine
642
- }
643
- }, side))
644
- }, deg)), paddedIcons.map((icon, index) => /*#__PURE__*/(0, _jsxRuntime.jsx)(DialIconItem, {
645
- icon: icon,
646
- index: index,
647
- totalIcons: paddedIcons.length,
648
- position: positions[index],
649
- progress: iconProgress,
650
- onPress: () => handleIconPress(icon)
651
- }, index)), /*#__PURE__*/(0, _jsxRuntime.jsxs)("div", {
652
- style: {
653
- position: 'absolute',
654
- left: '50%',
655
- top: '50%',
656
- width: buttonContainerSize,
657
- height: buttonContainerSize,
658
- marginLeft: -buttonContainerSize / 2,
659
- marginTop: -buttonContainerSize / 2,
660
- display: 'flex',
661
- alignItems: 'center',
662
- justifyContent: 'center',
663
- // Glass hub — see the native twin: a barely-there shade on the outer
664
- // disc, a soft puck inside, no rings, so the tool background runs
665
- // through the middle of the dial.
666
- backgroundColor: _floatingToolsReact.dialColors.hubHalo,
667
- borderRadius: layout.buttonSize,
668
- overflow: 'hidden',
669
- transform: `scale(${centerButtonScale * centerPulseScale})`,
670
- opacity: centerButtonScale > 0.01 ? 1 : 0
671
- },
672
- children: [/*#__PURE__*/(0, _jsxRuntime.jsx)("div", {
673
- style: {
674
- position: 'absolute',
675
- inset: 0,
676
- backgroundColor: _floatingToolsReact.dialColors.dialGradient1,
677
- opacity: 0.5,
678
- borderRadius: layout.buttonSize
679
- }
680
- }), /*#__PURE__*/(0, _jsxRuntime.jsx)("div", {
681
- style: {
682
- position: 'absolute',
683
- inset: 0,
684
- top: '20%',
685
- left: '20%',
686
- backgroundColor: _floatingToolsReact.dialColors.dialGradient2,
687
- opacity: 0.3,
688
- borderRadius: layout.buttonSize
689
- }
690
- }), /*#__PURE__*/(0, _jsxRuntime.jsx)("div", {
691
- style: {
692
- position: 'absolute',
693
- inset: 0,
694
- top: '40%',
695
- left: '40%',
696
- backgroundColor: _floatingToolsReact.dialColors.dialGradient3,
697
- opacity: 0.2,
698
- borderRadius: layout.buttonSize
699
- }
700
- }), /*#__PURE__*/(0, _jsxRuntime.jsx)("div", {
701
- style: {
702
- width: buttonBorderSize,
703
- height: buttonBorderSize,
704
- borderRadius: layout.buttonSize * _floatingToolsReact.dialStyles.centerButton.borderRadiusRatio,
705
- backgroundColor: _floatingToolsReact.dialColors.hubFill,
706
- display: 'flex',
707
- alignItems: 'center',
708
- justifyContent: 'center'
709
- },
710
- children: /*#__PURE__*/(0, _jsxRuntime.jsx)("div", {
711
- onClick: onCenterPress,
712
- onMouseEnter: () => setIsHoveringCenter(true),
713
- onMouseLeave: () => setIsHoveringCenter(false),
714
- style: {
715
- width: layout.buttonSize,
716
- height: layout.buttonSize,
717
- borderRadius: layout.buttonSize / 2,
718
- display: 'flex',
719
- flexDirection: 'column',
720
- alignItems: 'center',
721
- justifyContent: 'center',
722
- cursor: onCenterPress ? 'pointer' : 'default',
723
- transform: isHoveringCenter ? `scale(${interaction.centerHover.scale})` : 'scale(1)',
724
- transition: `transform ${interaction.centerHover.duration}ms ease`,
725
- animation: isAnimating && !isHoveringCenter ? cssAnimations.pulse : 'none'
726
- },
727
- children: settingsOpen ?
728
- /*#__PURE__*/
729
- // native DialDevTools.tsx:716-724 — stacked CLOSE / SETTINGS
730
- (0, _jsxRuntime.jsxs)("span", {
731
- style: {
732
- display: 'flex',
733
- flexDirection: 'column',
734
- alignItems: 'center',
735
- fontSize: _floatingToolsReact.dialStyles.centerButton.text.fontSize - 2,
736
- fontWeight: _floatingToolsReact.dialStyles.centerButton.text.fontWeight,
737
- fontFamily: _floatingToolsReact.dialStyles.centerButton.text.fontFamily,
738
- color: _floatingToolsReact.dialColors.centerText,
739
- letterSpacing: _floatingToolsReact.dialStyles.centerButton.text.letterSpacing,
740
- textAlign: 'center',
741
- textShadow: `0 0 4px ${_floatingToolsReact.dialColors.centerTextGlow}`,
742
- textTransform: 'uppercase',
743
- lineHeight: 1.2
744
- },
745
- children: [/*#__PURE__*/(0, _jsxRuntime.jsx)("span", {
746
- style: {
747
- marginBottom: -2
748
- },
749
- children: "CLOSE"
750
- }), /*#__PURE__*/(0, _jsxRuntime.jsx)("span", {
751
- style: {
752
- marginTop: -2
753
- },
754
- children: "SETTINGS"
755
- })]
756
- }) : /*#__PURE__*/(0, _jsxRuntime.jsx)("span", {
757
- style: {
758
- fontSize: _floatingToolsReact.dialStyles.centerButton.text.fontSize,
759
- fontWeight: _floatingToolsReact.dialStyles.centerButton.text.fontWeight,
760
- fontFamily: _floatingToolsReact.dialStyles.centerButton.text.fontFamily,
761
- color: _floatingToolsReact.dialColors.centerText,
762
- // native DialDevTools.tsx centerText
763
- letterSpacing: _floatingToolsReact.dialStyles.centerButton.text.letterSpacing,
764
- textAlign: 'center',
765
- textShadow: `0 0 4px ${_floatingToolsReact.dialColors.centerTextGlow}`,
766
- textTransform: 'uppercase'
767
- },
768
- children: centerLabel
769
- })
770
- })
771
- })]
772
- })]
773
- }), pageCount > 1 && /*#__PURE__*/(0, _jsxRuntime.jsxs)("div", {
774
- style: {
775
- position: 'absolute',
776
- left: '50%',
777
- marginLeft: -layout.circleSize / 2,
778
- top: 'calc(100% - 64px)',
779
- // native: screenHeight - 80 + 16
780
- width: layout.circleSize,
781
- display: 'flex',
782
- alignItems: 'center',
783
- justifyContent: 'space-between',
784
- opacity: Math.min(1, dialScale),
785
- transform: `scale(${Math.min(1, dialScale)})`
786
- },
787
- children: [/*#__PURE__*/(0, _jsxRuntime.jsx)(PagerButton, {
788
- side: "prev",
789
- disabled: safePage <= 0,
790
- onClick: () => handlePageChange(safePage - 1)
791
- }), /*#__PURE__*/(0, _jsxRuntime.jsxs)("span", {
792
- style: {
793
- padding: '6px 12px',
794
- // native indicator: paddingVertical 6, paddingHorizontal 12
795
- fontSize: 13,
796
- fontWeight: 900,
797
- fontFamily: _sharedUi.monoFont,
798
- letterSpacing: 2,
799
- color: _floatingToolsReact.dialColors.centerText,
800
- textShadow: `0 0 6px ${_floatingToolsReact.dialColors.centerTextGlow}`
801
- },
802
- children: [String(safePage + 1).padStart(2, '0'), /*#__PURE__*/(0, _jsxRuntime.jsxs)("span", {
803
- style: {
804
- color: _floatingToolsReact.dialColors.iconLabelMuted,
805
- textShadow: 'none'
806
- },
807
- children: [' / ', String(pageCount).padStart(2, '0')]
808
- })]
809
- }), /*#__PURE__*/(0, _jsxRuntime.jsx)(PagerButton, {
810
- side: "next",
811
- disabled: safePage >= pageCount - 1,
812
- onClick: () => handlePageChange(safePage + 1)
813
- })]
814
- }), showSettingsTooltip && !settingsOpen && /*#__PURE__*/(0, _jsxRuntime.jsx)(_OnboardingTooltipWeb.OnboardingTooltip, {
815
- title: "Welcome to Buoy!",
816
- message: "Tap the center button to configure and add tools to your dial menu.",
817
- onDismiss: dismissSettingsTooltip,
818
- showArrow: false
819
- })]
820
- });
821
- }
1
+ "use strict";Object.defineProperty(exports,"__esModule",{value:true});exports.DialMenu=DialMenu;var _react=require("react");var _floatingToolsReact=require("@buoy-gg/floating-tools-react");var _sharedUi=require("@buoy-gg/shared-ui");var _DialHyperspace=require("./DialHyperspace.js");var _OnboardingTooltipWeb=require("./OnboardingTooltip.web.js");var _jsxRuntime=require("react/jsx-runtime");const DIAL_BACKGROUND_FOCUS={x:.5,y:.5};const SETTINGS_TOOLTIP_KEY="@react_buoy_settings_tooltip_shown";let keyframesInjected=false;function injectKeyframes(){if(keyframesInjected||typeof document==="undefined")return;const o=document.createElement("style");o.textContent=(0,_floatingToolsReact.getDialCSSKeyframesString)();document.head.appendChild(o);keyframesInjected=true}const easeOutCubic=o=>1-Math.pow(1-o,3);const easeInCubic=o=>o*o*o;function DialIconItem({icon:o,index:l,totalIcons:k,position:f,progress:s,onPress:y}){const[w,D]=(0,_react.useState)(false);const[M,v]=(0,_react.useState)(false);const S=!o.icon&&o.id.startsWith("empty-");const $=!S&&o.unavailable===true;const h=!S&&!$;const{icons:F}=_floatingToolsReact.dialAnimationConfig;const m=(0,_floatingToolsReact.getIconStaggerInputRange)(l,k);let c=0;if(s<=m[1]){c=0}else if(s<=m[2]){c=(s-m[1])/(m[2]-m[1])}else{c=1}c=Math.max(0,Math.min(1,c));const b=_floatingToolsReact.DIAL_ICON_SIZE;const q=F.pressIn.scale;const B=1.1;const W=c*(M?q:w?B:1);let T=0;if(c<=0){T=0}else if(c<=.3){T=c}else{T=.3+(c-.3)*(.7/.7)}const H=f.x*c;const U=f.y*c;return(0,_jsxRuntime.jsx)("button",{role:"menuitem","aria-label":S?"Empty slot":o.name,"aria-disabled":!h,tabIndex:h?0:-1,onClick:h?y:void 0,onMouseEnter:()=>h&&D(true),onMouseLeave:()=>{D(false);v(false)},onMouseDown:()=>h&&v(true),onMouseUp:()=>v(false),style:{position:"absolute",left:"50%",top:"50%",width:b,height:b,marginLeft:-b/2,marginTop:-b/2,display:"flex",flexDirection:"column",alignItems:"center",justifyContent:"center",cursor:h?"pointer":"default",transform:`translate(${H}px, ${U}px) scale(${W})`,opacity:T,transition:w||M?"transform 100ms ease":"none",background:"none",border:"none",padding:0},children:S?(0,_jsxRuntime.jsx)("div",{style:{width:_floatingToolsReact.dialStyles.emptySlot.dotSize,height:_floatingToolsReact.dialStyles.emptySlot.dotSize,borderRadius:_floatingToolsReact.dialStyles.emptySlot.dotSize/2,backgroundColor:_floatingToolsReact.dialColors.emptyDotBackground,border:`${_floatingToolsReact.dialStyles.emptySlot.borderWidth}px solid ${_floatingToolsReact.dialColors.emptyDotBorder}`}}):(0,_jsxRuntime.jsxs)(_jsxRuntime.Fragment,{children:[(0,_jsxRuntime.jsx)("div",{style:{position:"absolute",width:`${_floatingToolsReact.dialStyles.icon.gradientBgSizePercent}%`,height:`${_floatingToolsReact.dialStyles.icon.gradientBgSizePercent}%`,borderRadius:_floatingToolsReact.dialStyles.icon.gradientBgBorderRadius,backgroundColor:"rgba(0, 0, 0, 0.2)",opacity:_floatingToolsReact.dialStyles.icon.gradientBgOpacity}}),(0,_jsxRuntime.jsx)("div",{style:{position:"absolute",width:`${_floatingToolsReact.dialStyles.icon.innerGlowSizePercent}%`,height:`${_floatingToolsReact.dialStyles.icon.innerGlowSizePercent}%`,borderRadius:_floatingToolsReact.dialStyles.icon.innerGlowBorderRadius,backgroundColor:"rgba(255, 255, 255, 0.02)",opacity:_floatingToolsReact.dialStyles.icon.innerGlowOpacity}}),(0,_jsxRuntime.jsx)("div",{style:{marginBottom:_floatingToolsReact.dialStyles.icon.wrapperMarginBottom,display:"flex",alignItems:"center",justifyContent:"center",fontSize:32,filter:w?"brightness(1.2)":"none"},children:o.icon}),(0,_jsxRuntime.jsx)("span",{style:{fontSize:o.name.length>8?Math.max(_floatingToolsReact.dialStyles.icon.label.fontSize*.7,_floatingToolsReact.dialStyles.icon.label.fontSize*8/o.name.length):_floatingToolsReact.dialStyles.icon.label.fontSize,fontWeight:_floatingToolsReact.dialStyles.icon.label.fontWeight,fontFamily:_floatingToolsReact.dialStyles.icon.label.fontFamily,color:_floatingToolsReact.dialColors.iconLabel,letterSpacing:_floatingToolsReact.dialStyles.icon.label.letterSpacing,marginTop:_floatingToolsReact.dialStyles.icon.label.marginTop,textTransform:"uppercase",whiteSpace:"nowrap"},children:o.name}),$&&(0,_jsxRuntime.jsx)("span",{style:{fontSize:_floatingToolsReact.dialStyles.icon.label.fontSize-1,fontWeight:_floatingToolsReact.dialStyles.icon.label.fontWeight,fontFamily:_floatingToolsReact.dialStyles.icon.label.fontFamily,letterSpacing:_floatingToolsReact.dialStyles.icon.label.letterSpacing,color:_floatingToolsReact.floatingToolsColors.muted,textTransform:"uppercase",whiteSpace:"nowrap"},children:"Unavailable"})]})})}function PagerChevron({side:o,color:l}){const k=o==="prev"?[[15,18,9,12],[9,12,15,6]]:[[9,18,15,12],[15,12,9,6]];return(0,_jsxRuntime.jsx)("svg",{width:18,height:18,viewBox:"0 0 24 24","aria-hidden":"true",focusable:"false",children:k.map(([f,s,y,w],D)=>(0,_jsxRuntime.jsx)("line",{x1:f,y1:s,x2:y,y2:w,stroke:l,strokeWidth:2},D))})}function PagerButton({side:o,disabled:l,onClick:k}){const[f,s]=(0,_react.useState)(false);const y=l?_floatingToolsReact.dialColors.emptyDotBorder:_floatingToolsReact.dialColors.accent;return(0,_jsxRuntime.jsxs)("button",{type:"button","aria-label":`${o==="prev"?"Previous":"Next"} dial page`,disabled:l,onClick:k,onMouseDown:()=>!l&&s(true),onMouseUp:()=>s(false),onMouseLeave:()=>s(false),style:{display:"flex",alignItems:"center",gap:4,padding:"10px 16px",borderRadius:10,border:`1px solid ${_floatingToolsReact.dialColors.dialBorder}`,backgroundColor:_floatingToolsReact.dialColors.dialBackground,color:l?_floatingToolsReact.dialColors.iconLabelMuted:_floatingToolsReact.dialColors.centerText,fontSize:12,fontWeight:900,fontFamily:_sharedUi.monoFont,letterSpacing:1.5,textTransform:"uppercase",cursor:l?"default":"pointer",opacity:l?.4:1,boxShadow:l?"none":`0 0 8px ${(0,_floatingToolsReact.withAlpha)(_floatingToolsReact.dialColors.dialShadow,.4)}`,transform:f?"scale(0.92)":"scale(1)",transition:"transform 100ms ease"},children:[o==="prev"&&(0,_jsxRuntime.jsx)(PagerChevron,{side:"prev",color:y}),o==="prev"?"PREV":"NEXT",o==="next"&&(0,_jsxRuntime.jsx)(PagerChevron,{side:"next",color:y})]})}function DialMenu({icons:o,onClose:l,centerLabel:k="MENU",onCenterPress:f,settingsOpen:s=false,hintsDisabled:y=false}){const{id:w}=(0,_sharedUi.useToolBackground)();const[D,M]=(0,_react.useState)(0);const[v,S]=(0,_react.useState)(0);const[$,h]=(0,_react.useState)(0);const[F,m]=(0,_react.useState)(0);const[c,b]=(0,_react.useState)(0);const[q,B]=(0,_react.useState)(1);const[W,T]=(0,_react.useState)(false);const[H,U]=(0,_react.useState)(false);const[ne,ie]=(0,_react.useState)(false);const K=(0,_react.useRef)(null);const J=(0,_react.useRef)(null);const g=(0,_react.useRef)(null);const O=(0,_react.useRef)(false);const{entrance:E,exit:L,interaction:P}=_floatingToolsReact.dialAnimationConfig;const ae=(0,_floatingToolsReact.getDialCSSAnimationStyles)();const[N,se]=(0,_react.useState)(()=>({width:window.innerWidth,height:window.innerHeight}));(0,_react.useEffect)(()=>{const t=()=>se({width:window.innerWidth,height:window.innerHeight});window.addEventListener("resize",t);return()=>window.removeEventListener("resize",t)},[]);const i=(0,_react.useMemo)(()=>(0,_floatingToolsReact.getDialLayout)({screenWidth:N.width,maxCircleSize:Math.max(120,Math.min(320,N.height-96))}),[N]);const re=(0,_react.useMemo)(()=>(0,_floatingToolsReact.getGridLineRotations)(),[]);const le=(0,_react.useMemo)(()=>(0,_floatingToolsReact.getAllIconPositions)(_floatingToolsReact.MAX_DIAL_SLOTS,i.iconRadius),[i.iconRadius]);const[ce,de]=(0,_react.useState)(0);const A=Math.max(1,Math.ceil(o.length/_floatingToolsReact.MAX_DIAL_SLOTS));const x=Math.min(ce,A-1);const Q=(0,_react.useMemo)(()=>{const t=x*_floatingToolsReact.MAX_DIAL_SLOTS;const e=[...o.slice(t,t+_floatingToolsReact.MAX_DIAL_SLOTS)];while(e.length<_floatingToolsReact.MAX_DIAL_SLOTS){e.push({id:`empty-${e.length}`,name:"",icon:null,onPress:()=>{}})}return e},[o,x]);(0,_react.useEffect)(()=>{injectKeyframes()},[]);(0,_react.useEffect)(()=>{const t=E.backdrop.duration;const e=E.dial.rotation.duration;const d=E.centerButton.delay;const a=E.icons.delay;const r=E.icons.duration;const u=performance.now();const p=j=>{const n=j-u;M(Math.min(1,n/t));const C=Math.min(1,n/400);let I=easeOutCubic(C)*1.1;if(C>.7){I-=(C-.7)*.33}if(C>=1)I=1;S(Math.max(0,Math.min(1.05,I)));const z=Math.min(1,n/e);h(easeOutCubic(z)*360);if(n>=d){const R=Math.min(1,(n-d)/300);let Z=easeOutCubic(R)*1.15;if(R>.6){Z-=(R-.6)*.375}if(R>=1)Z=1;m(Math.max(0,Math.min(1.05,Z)))}if(n>=a){const R=Math.min(1,(n-a)/r);b(easeOutCubic(R))}const Y=a+r;if(n<Y){g.current=requestAnimationFrame(p)}else{M(1);S(1);h(360);m(1);b(1);ie(true)}};g.current=requestAnimationFrame(p);return()=>{if(g.current)cancelAnimationFrame(g.current)}},[]);const _=(0,_react.useCallback)(()=>{if(O.current)return;O.current=true;U(true);if(g.current){cancelAnimationFrame(g.current)}const t=performance.now();const e=L.icons.duration;const d=L.centerButton.duration;const a=L.dialScale.duration;const r=Math.max(d,a);const u=L.backdrop.duration;const p=j=>{const n=j-t;if(n<e){const z=easeInCubic(n/e);b(1-z);g.current=requestAnimationFrame(p);return}const C=e;if(n<C+r){b(0);const z=Math.min(1,(n-C)/d);const Y=Math.min(1,(n-C)/a);m(1-easeInCubic(z));S(1-easeInCubic(Y));g.current=requestAnimationFrame(p);return}const I=C+r;if(n<I+u){S(0);m(0);const z=(n-I)/u;M(1-z);g.current=requestAnimationFrame(p);return}M(0);l()};g.current=requestAnimationFrame(p)},[L,l]);(0,_react.useEffect)(()=>{const t=document.activeElement;const e=K.current;return()=>{if(t?.isConnected&&(document.activeElement===document.body||e?.contains(document.activeElement))){t.focus()}}},[]);(0,_react.useEffect)(()=>{if(s)return;J.current?.focus();const t=e=>{const d=K.current;if(!d)return;if(e.key==="Escape"){e.preventDefault();_()}else if(e.key==="Tab"){const a=Array.from(d.querySelectorAll('button:not(:disabled):not([aria-disabled="true"]), [tabindex="0"]')).filter(p=>p.getClientRects().length>0);const r=a[0];const u=a[a.length-1];if(!d.contains(document.activeElement)||(e.shiftKey?document.activeElement===r:document.activeElement===u)){e.preventDefault();(e.shiftKey?u:r)?.focus()}}else if(["ArrowRight","ArrowDown","ArrowLeft","ArrowUp","Home","End"].includes(e.key)){const a=Array.from(d.querySelectorAll('[role="menuitem"]:not([aria-disabled="true"])'));const r=a.indexOf(document.activeElement);if(r<0||!a.length)return;e.preventDefault();const u=e.key==="Home"?0:e.key==="End"?a.length-1:(r+(e.key==="ArrowRight"||e.key==="ArrowDown"?1:-1)+a.length)%a.length;a[u].focus()}};document.addEventListener("keydown",t);return()=>document.removeEventListener("keydown",t)},[_,s]);const[X,ee]=(0,_react.useState)(false);(0,_react.useEffect)(()=>{if(y)return;let t=false;const e=setTimeout(async()=>{const d=await _sharedUi.persistentStorage.getItem(SETTINGS_TOOLTIP_KEY);if(!t&&!d)ee(true)},1200);return()=>{t=true;clearTimeout(e)}},[y]);const V=(0,_react.useCallback)(()=>{ee(false);void _sharedUi.persistentStorage.setItem(SETTINGS_TOOLTIP_KEY,"true")},[]);(0,_react.useEffect)(()=>{if(s&&X){V()}},[s,X,V]);const ue=(0,_react.useCallback)(t=>{if(t.id.startsWith("empty-")||O.current)return;const[e,d]=P.iconSelect.pulse;const a=performance.now();const r=150;const u=p=>{const j=p-a;if(j<r){const n=easeOutCubic(j/r);B(1-(1-e.scale)*n);requestAnimationFrame(u)}else if(j<r*2){const n=easeOutCubic((j-r)/r);B(e.scale+(d.scale-e.scale)*n);requestAnimationFrame(u)}else{B(1)}};requestAnimationFrame(u);setTimeout(()=>{t.onPress();_()},P.iconSelect.actionDelay)},[P.iconSelect,_]);const te=(0,_react.useCallback)(t=>{if(O.current)return;const e=Math.max(0,Math.min(t,A-1));if(e!==x)de(e)},[A,x]);const G=i.buttonSize*_floatingToolsReact.dialStyles.centerButton.containerRatio;const oe=i.buttonSize*_floatingToolsReact.dialStyles.centerButton.borderRatio;const pe=i.buttonSize*_floatingToolsReact.dialStyles.centerButton.containerRatio/2+6;const fe=ne&&!H;return(0,_jsxRuntime.jsxs)("div",{ref:K,role:"dialog","aria-label":"Dial Menu","aria-modal":"true",style:{position:"fixed",inset:0,zIndex:1e4},children:[(0,_jsxRuntime.jsx)("button",{type:"button","aria-label":"Close dial menu",tabIndex:0,onClick:_,style:{position:"absolute",inset:0,border:0,padding:0,backgroundColor:_floatingToolsReact.dialColors.dialBackdrop,opacity:D}}),(0,_jsxRuntime.jsxs)("div",{style:{position:"absolute",left:"50%",marginLeft:-i.circleSize/2,bottom:80,width:i.circleSize,height:i.circleSize,borderRadius:"50%",backgroundColor:_floatingToolsReact.dialColors.dialBackground,border:`${_floatingToolsReact.dialStyles.circle.borderWidth}px solid ${_floatingToolsReact.dialColors.dialBorder}`,boxShadow:`0 0 ${_floatingToolsReact.dialStyles.circle.shadowRadius}px ${(0,_floatingToolsReact.withAlpha)(_floatingToolsReact.dialColors.dialShadow,_floatingToolsReact.dialStyles.circle.shadowOpacity)}`,transform:`scale(${v}) rotate(${$}deg)`,opacity:v>.01?1:0,overflow:"hidden"},children:[(0,_jsxRuntime.jsx)("div",{style:{position:"absolute",inset:0,borderRadius:"50%",backgroundColor:_floatingToolsReact.dialColors.dialGradient1,opacity:_floatingToolsReact.dialStyles.gradientLayers[0].opacity}}),(0,_jsxRuntime.jsx)("div",{style:{position:"absolute",inset:0,top:"30%",left:"30%",borderRadius:"50%",backgroundColor:_floatingToolsReact.dialColors.dialGradient2,opacity:_floatingToolsReact.dialStyles.gradientLayers[1].opacity}}),(0,_jsxRuntime.jsx)("div",{style:{position:"absolute",inset:0,top:"50%",left:"50%",borderRadius:"50%",backgroundColor:_floatingToolsReact.dialColors.dialGradient3,opacity:_floatingToolsReact.dialStyles.gradientLayers[2].opacity}}),re.map(t=>(0,_jsxRuntime.jsx)("div",{style:{position:"absolute",top:"50%",left:0,right:0,height:_floatingToolsReact.dialStyles.grid.lineHeight,transform:`rotate(${t}deg)`,transformOrigin:"center"},children:["left","right"].map(e=>(0,_jsxRuntime.jsx)("div",{style:{position:"absolute",top:0,[e]:0,width:`calc(50% - ${pe}px)`,height:_floatingToolsReact.dialStyles.grid.lineHeight,backgroundColor:_floatingToolsReact.dialColors.dialGridLine}},e))},t)),(0,_jsxRuntime.jsx)("div",{"data-testid":"dial-background","data-background":w,style:{position:"absolute",inset:0,pointerEvents:"none"},children:w==="hyperspace"?(0,_jsxRuntime.jsx)(_DialHyperspace.DialHyperspace,{size:i.circleSize}):(0,_jsxRuntime.jsx)(_sharedUi.ToolBackground,{focus:DIAL_BACKGROUND_FOCUS})}),Q.map((t,e)=>(0,_jsxRuntime.jsx)(DialIconItem,{icon:t,index:e,totalIcons:Q.length,position:le[e],progress:c,onPress:()=>ue(t)},e)),(0,_jsxRuntime.jsxs)("div",{style:{position:"absolute",left:"50%",top:"50%",width:G,height:G,marginLeft:-G/2,marginTop:-G/2,display:"flex",alignItems:"center",justifyContent:"center",backgroundColor:_floatingToolsReact.dialColors.hubHalo,borderRadius:i.buttonSize,overflow:"hidden",transform:`scale(${F*q})`,opacity:F>.01?1:0},children:[(0,_jsxRuntime.jsx)("div",{style:{position:"absolute",inset:0,backgroundColor:_floatingToolsReact.dialColors.dialGradient1,opacity:.5,borderRadius:i.buttonSize}}),(0,_jsxRuntime.jsx)("div",{style:{position:"absolute",inset:0,top:"20%",left:"20%",backgroundColor:_floatingToolsReact.dialColors.dialGradient2,opacity:.3,borderRadius:i.buttonSize}}),(0,_jsxRuntime.jsx)("div",{style:{position:"absolute",inset:0,top:"40%",left:"40%",backgroundColor:_floatingToolsReact.dialColors.dialGradient3,opacity:.2,borderRadius:i.buttonSize}}),(0,_jsxRuntime.jsx)("div",{style:{width:oe,height:oe,borderRadius:i.buttonSize*_floatingToolsReact.dialStyles.centerButton.borderRadiusRatio,backgroundColor:_floatingToolsReact.dialColors.hubFill,display:"flex",alignItems:"center",justifyContent:"center"},children:(0,_jsxRuntime.jsx)("button",{ref:J,type:"button","aria-label":s?"Close settings":"Open settings",disabled:!f,onClick:f,onMouseEnter:()=>T(true),onMouseLeave:()=>T(false),style:{border:0,padding:0,background:"transparent",width:i.buttonSize,height:i.buttonSize,borderRadius:i.buttonSize/2,display:"flex",flexDirection:"column",alignItems:"center",justifyContent:"center",cursor:f?"pointer":"default",transform:W?`scale(${P.centerHover.scale})`:"scale(1)",transition:`transform ${P.centerHover.duration}ms ease`,animation:fe&&!W?ae.pulse:"none"},children:s?(0,_jsxRuntime.jsxs)("span",{style:{display:"flex",flexDirection:"column",alignItems:"center",fontSize:_floatingToolsReact.dialStyles.centerButton.text.fontSize-2,fontWeight:_floatingToolsReact.dialStyles.centerButton.text.fontWeight,fontFamily:_floatingToolsReact.dialStyles.centerButton.text.fontFamily,color:_floatingToolsReact.dialColors.centerText,letterSpacing:_floatingToolsReact.dialStyles.centerButton.text.letterSpacing,textAlign:"center",textShadow:`0 0 4px ${_floatingToolsReact.dialColors.centerTextGlow}`,textTransform:"uppercase",lineHeight:1.2},children:[(0,_jsxRuntime.jsx)("span",{style:{marginBottom:-2},children:"CLOSE"}),(0,_jsxRuntime.jsx)("span",{style:{marginTop:-2},children:"SETTINGS"})]}):(0,_jsxRuntime.jsx)("span",{style:{fontSize:_floatingToolsReact.dialStyles.centerButton.text.fontSize,fontWeight:_floatingToolsReact.dialStyles.centerButton.text.fontWeight,fontFamily:_floatingToolsReact.dialStyles.centerButton.text.fontFamily,color:_floatingToolsReact.dialColors.centerText,letterSpacing:_floatingToolsReact.dialStyles.centerButton.text.letterSpacing,textAlign:"center",textShadow:`0 0 4px ${_floatingToolsReact.dialColors.centerTextGlow}`,textTransform:"uppercase"},children:k})})})]})]}),A>1&&(0,_jsxRuntime.jsxs)("div",{style:{position:"absolute",left:"50%",marginLeft:-i.circleSize/2,top:"calc(100% - 64px)",width:i.circleSize,display:"flex",alignItems:"center",justifyContent:"space-between",opacity:Math.min(1,v),transform:`scale(${Math.min(1,v)})`},children:[(0,_jsxRuntime.jsx)(PagerButton,{side:"prev",disabled:x<=0,onClick:()=>te(x-1)}),(0,_jsxRuntime.jsxs)("span",{style:{padding:"6px 12px",fontSize:13,fontWeight:900,fontFamily:_sharedUi.monoFont,letterSpacing:2,color:_floatingToolsReact.dialColors.centerText,textShadow:`0 0 6px ${_floatingToolsReact.dialColors.centerTextGlow}`},children:[String(x+1).padStart(2,"0"),(0,_jsxRuntime.jsxs)("span",{style:{color:_floatingToolsReact.dialColors.iconLabelMuted,textShadow:"none"},children:[" / ",String(A).padStart(2,"0")]})]}),(0,_jsxRuntime.jsx)(PagerButton,{side:"next",disabled:x>=A-1,onClick:()=>te(x+1)})]}),X&&!s&&(0,_jsxRuntime.jsx)(_OnboardingTooltipWeb.OnboardingTooltip,{title:"Welcome to Buoy!",message:"Tap the center button to configure and add tools to your dial menu.",onDismiss:V,showArrow:false})]})}