@buoy-gg/core 7.0.15 → 7.0.16

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 (99) hide show
  1. package/lib/commonjs/floatingMenu/AppHost.web.js +359 -0
  2. package/lib/commonjs/floatingMenu/AppHostLogic.js +6 -0
  3. package/lib/commonjs/floatingMenu/DevToolsSettingsModal.web.js +787 -418
  4. package/lib/commonjs/floatingMenu/FloatingDevTools.js +1 -1
  5. package/lib/commonjs/floatingMenu/FloatingDevTools.web.js +244 -36
  6. package/lib/commonjs/floatingMenu/FloatingMenu.js +2 -2
  7. package/lib/commonjs/floatingMenu/MinimizedToolsContext.js +2 -3
  8. package/lib/commonjs/floatingMenu/MinimizedToolsStack.web.js +287 -0
  9. package/lib/commonjs/floatingMenu/autoDiscoverPresets.js +16 -0
  10. package/lib/commonjs/floatingMenu/autoExternalSync.js +9 -0
  11. package/lib/commonjs/floatingMenu/dial/DialDevTools.js +7 -4
  12. package/lib/commonjs/floatingMenu/dial/DialDevTools.web.js +373 -231
  13. package/lib/commonjs/floatingMenu/dial/DialIcon.js +25 -3
  14. package/lib/commonjs/floatingMenu/dial/OnboardingTooltip.js +1 -1
  15. package/lib/commonjs/floatingMenu/dial/OnboardingTooltip.web.js +154 -0
  16. package/lib/commonjs/floatingMenu/dial/onboardingConstants.web.js +34 -0
  17. package/lib/commonjs/floatingMenu/floatingTools.js +3 -3
  18. package/lib/commonjs/floatingMenu/floatingTools.web.js +191 -28
  19. package/lib/commonjs/index.js +2 -2
  20. package/lib/commonjs/index.web.js +19 -0
  21. package/lib/commonjs/utils/autoDiscoverPresets.web.js +50 -5
  22. package/lib/module/floatingMenu/AppHost.web.js +351 -0
  23. package/lib/module/floatingMenu/AppHostLogic.js +6 -0
  24. package/lib/module/floatingMenu/DevToolsSettingsModal.web.js +792 -422
  25. package/lib/module/floatingMenu/FloatingDevTools.js +2 -2
  26. package/lib/module/floatingMenu/FloatingDevTools.web.js +247 -38
  27. package/lib/module/floatingMenu/FloatingMenu.js +2 -2
  28. package/lib/module/floatingMenu/MinimizedToolsContext.js +2 -3
  29. package/lib/module/floatingMenu/MinimizedToolsStack.web.js +284 -0
  30. package/lib/module/floatingMenu/autoDiscoverPresets.js +16 -0
  31. package/lib/module/floatingMenu/autoExternalSync.js +9 -0
  32. package/lib/module/floatingMenu/dial/DialDevTools.js +8 -5
  33. package/lib/module/floatingMenu/dial/DialDevTools.web.js +375 -233
  34. package/lib/module/floatingMenu/dial/DialIcon.js +26 -4
  35. package/lib/module/floatingMenu/dial/OnboardingTooltip.js +1 -1
  36. package/lib/module/floatingMenu/dial/OnboardingTooltip.web.js +149 -0
  37. package/lib/module/floatingMenu/dial/onboardingConstants.web.js +27 -0
  38. package/lib/module/floatingMenu/floatingTools.js +3 -3
  39. package/lib/module/floatingMenu/floatingTools.web.js +190 -28
  40. package/lib/module/index.js +2 -2
  41. package/lib/module/index.web.js +5 -0
  42. package/lib/module/utils/autoDiscoverPresets.web.js +53 -7
  43. package/lib/typescript/commonjs/floatingMenu/AppHost.web.d.ts +38 -0
  44. package/lib/typescript/commonjs/floatingMenu/AppHost.web.d.ts.map +1 -0
  45. package/lib/typescript/commonjs/floatingMenu/AppHostLogic.d.ts +21 -1
  46. package/lib/typescript/commonjs/floatingMenu/AppHostLogic.d.ts.map +1 -1
  47. package/lib/typescript/commonjs/floatingMenu/DevToolsSettingsModal.web.d.ts +5 -2
  48. package/lib/typescript/commonjs/floatingMenu/DevToolsSettingsModal.web.d.ts.map +1 -1
  49. package/lib/typescript/commonjs/floatingMenu/FloatingDevTools.web.d.ts +2 -14
  50. package/lib/typescript/commonjs/floatingMenu/FloatingDevTools.web.d.ts.map +1 -1
  51. package/lib/typescript/commonjs/floatingMenu/MinimizedToolsContext.d.ts +2 -20
  52. package/lib/typescript/commonjs/floatingMenu/MinimizedToolsContext.d.ts.map +1 -1
  53. package/lib/typescript/commonjs/floatingMenu/MinimizedToolsStack.web.d.ts +21 -0
  54. package/lib/typescript/commonjs/floatingMenu/MinimizedToolsStack.web.d.ts.map +1 -0
  55. package/lib/typescript/commonjs/floatingMenu/autoDiscoverPresets.d.ts.map +1 -1
  56. package/lib/typescript/commonjs/floatingMenu/autoExternalSync.d.ts.map +1 -1
  57. package/lib/typescript/commonjs/floatingMenu/dial/DialDevTools.d.ts.map +1 -1
  58. package/lib/typescript/commonjs/floatingMenu/dial/DialDevTools.web.d.ts +16 -2
  59. package/lib/typescript/commonjs/floatingMenu/dial/DialDevTools.web.d.ts.map +1 -1
  60. package/lib/typescript/commonjs/floatingMenu/dial/DialIcon.d.ts.map +1 -1
  61. package/lib/typescript/commonjs/floatingMenu/dial/OnboardingTooltip.web.d.ts +9 -0
  62. package/lib/typescript/commonjs/floatingMenu/dial/OnboardingTooltip.web.d.ts.map +1 -0
  63. package/lib/typescript/commonjs/floatingMenu/dial/onboardingConstants.web.d.ts +13 -0
  64. package/lib/typescript/commonjs/floatingMenu/dial/onboardingConstants.web.d.ts.map +1 -0
  65. package/lib/typescript/commonjs/floatingMenu/floatingTools.web.d.ts +29 -2
  66. package/lib/typescript/commonjs/floatingMenu/floatingTools.web.d.ts.map +1 -1
  67. package/lib/typescript/commonjs/index.web.d.ts +1 -0
  68. package/lib/typescript/commonjs/index.web.d.ts.map +1 -1
  69. package/lib/typescript/commonjs/utils/autoDiscoverPresets.web.d.ts +2 -0
  70. package/lib/typescript/commonjs/utils/autoDiscoverPresets.web.d.ts.map +1 -1
  71. package/lib/typescript/module/floatingMenu/AppHost.web.d.ts +38 -0
  72. package/lib/typescript/module/floatingMenu/AppHost.web.d.ts.map +1 -0
  73. package/lib/typescript/module/floatingMenu/AppHostLogic.d.ts +21 -1
  74. package/lib/typescript/module/floatingMenu/AppHostLogic.d.ts.map +1 -1
  75. package/lib/typescript/module/floatingMenu/DevToolsSettingsModal.web.d.ts +5 -2
  76. package/lib/typescript/module/floatingMenu/DevToolsSettingsModal.web.d.ts.map +1 -1
  77. package/lib/typescript/module/floatingMenu/FloatingDevTools.web.d.ts +2 -14
  78. package/lib/typescript/module/floatingMenu/FloatingDevTools.web.d.ts.map +1 -1
  79. package/lib/typescript/module/floatingMenu/MinimizedToolsContext.d.ts +2 -20
  80. package/lib/typescript/module/floatingMenu/MinimizedToolsContext.d.ts.map +1 -1
  81. package/lib/typescript/module/floatingMenu/MinimizedToolsStack.web.d.ts +21 -0
  82. package/lib/typescript/module/floatingMenu/MinimizedToolsStack.web.d.ts.map +1 -0
  83. package/lib/typescript/module/floatingMenu/autoDiscoverPresets.d.ts.map +1 -1
  84. package/lib/typescript/module/floatingMenu/autoExternalSync.d.ts.map +1 -1
  85. package/lib/typescript/module/floatingMenu/dial/DialDevTools.d.ts.map +1 -1
  86. package/lib/typescript/module/floatingMenu/dial/DialDevTools.web.d.ts +16 -2
  87. package/lib/typescript/module/floatingMenu/dial/DialDevTools.web.d.ts.map +1 -1
  88. package/lib/typescript/module/floatingMenu/dial/DialIcon.d.ts.map +1 -1
  89. package/lib/typescript/module/floatingMenu/dial/OnboardingTooltip.web.d.ts +9 -0
  90. package/lib/typescript/module/floatingMenu/dial/OnboardingTooltip.web.d.ts.map +1 -0
  91. package/lib/typescript/module/floatingMenu/dial/onboardingConstants.web.d.ts +13 -0
  92. package/lib/typescript/module/floatingMenu/dial/onboardingConstants.web.d.ts.map +1 -0
  93. package/lib/typescript/module/floatingMenu/floatingTools.web.d.ts +29 -2
  94. package/lib/typescript/module/floatingMenu/floatingTools.web.d.ts.map +1 -1
  95. package/lib/typescript/module/index.web.d.ts +1 -0
  96. package/lib/typescript/module/index.web.d.ts.map +1 -1
  97. package/lib/typescript/module/utils/autoDiscoverPresets.web.d.ts +2 -0
  98. package/lib/typescript/module/utils/autoDiscoverPresets.web.d.ts.map +1 -1
  99. package/package.json +5 -5
@@ -169,7 +169,10 @@ const DialIcon = ({
169
169
  style: styles.pressable,
170
170
  children: [/*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.View, {
171
171
  style: styles.iconWrapper,
172
- children: icon.icon
172
+ children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.View, {
173
+ style: styles.iconClamp,
174
+ children: icon.icon
175
+ })
173
176
  }), /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.Text, {
174
177
  style: styles.label,
175
178
  numberOfLines: 1,
@@ -202,9 +205,12 @@ const DialIcon = ({
202
205
  const IconComp = icon.iconComponent;
203
206
  return /*#__PURE__*/(0, _jsxRuntime.jsx)(IconComp, {
204
207
  slot: "dial",
205
- size: 32
208
+ size: _floatingToolsCore.DIAL_ICON_GLYPH_SIZE
206
209
  });
207
- })() : icon.icon
210
+ })() : /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.View, {
211
+ style: styles.iconClamp,
212
+ children: icon.icon
213
+ })
208
214
  }), /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.Text, {
209
215
  style: styles.label,
210
216
  numberOfLines: 1,
@@ -253,6 +259,22 @@ const styles = _reactNative.StyleSheet.create({
253
259
  alignItems: "center",
254
260
  justifyContent: "center"
255
261
  },
262
+ /**
263
+ * Hard clamp for PRE-RENDERED icon nodes (icon.icon) — the path where the
264
+ * glyph's size is baked in by whoever created the node (unavailable-tool
265
+ * registry entries, consumer custom tools) rather than controlled here. The
266
+ * fixed overflow-hidden box guarantees an oversized node can never blow past
267
+ * its slot and dwarf neighboring icons — worst case it center-crops. The
268
+ * iconComponent path stays unclipped: we render it at DIAL_ICON_GLYPH_SIZE
269
+ * ourselves, and clipping would shave off the icons' glow shadows.
270
+ */
271
+ iconClamp: {
272
+ width: _floatingToolsCore.DIAL_ICON_GLYPH_SIZE,
273
+ height: _floatingToolsCore.DIAL_ICON_GLYPH_SIZE,
274
+ alignItems: "center",
275
+ justifyContent: "center",
276
+ overflow: "hidden"
277
+ },
256
278
  label: {
257
279
  fontSize: _floatingToolsCore.dialStyles.icon.label.fontSize,
258
280
  fontWeight: _floatingToolsCore.dialStyles.icon.label.fontWeight,
@@ -7,7 +7,7 @@ exports.OnboardingTooltip = void 0;
7
7
  var _react = require("react");
8
8
  var _reactNative = require("react-native");
9
9
  var _sharedUi = require("@buoy-gg/shared-ui");
10
- var _onboardingConstants = require("./onboardingConstants.js");
10
+ var _onboardingConstants = require("./onboardingConstants");
11
11
  var _jsxRuntime = require("react/jsx-runtime");
12
12
  const OnboardingTooltip = ({
13
13
  visible,
@@ -0,0 +1,154 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.OnboardingTooltip = OnboardingTooltip;
7
+ var _react = require("react");
8
+ var _floatingToolsReact = require("@buoy-gg/floating-tools-react");
9
+ var _onboardingConstantsWeb = require("./onboardingConstants.web.js");
10
+ var _jsxRuntime = require("react/jsx-runtime");
11
+ /**
12
+ * OnboardingTooltip — Web twin of OnboardingTooltip.tsx.
13
+ * Centered glowing card with a down-pointing arrow, pulse loop, bouncing
14
+ * arrow, and a "Got it!" button. Rendered over a dark backdrop by callers.
15
+ * All values annotated with the native tokens they mirror.
16
+ */
17
+
18
+ let onboardingKeyframesInjected = false;
19
+ function injectOnboardingKeyframes() {
20
+ if (onboardingKeyframesInjected || typeof document === 'undefined') return;
21
+ const style = document.createElement('style');
22
+ style.textContent = `
23
+ @keyframes buoyOnboardPulse {
24
+ 0%, 100% { transform: scale(1); }
25
+ 50% { transform: scale(1.02); }
26
+ }
27
+ @keyframes buoyOnboardArrowBounce {
28
+ 0%, 100% { transform: translateY(0); }
29
+ 50% { transform: translateY(-8px); }
30
+ }
31
+ `;
32
+ document.head.appendChild(style);
33
+ onboardingKeyframesInjected = true;
34
+ }
35
+
36
+ // native dialColors.dialShadow === buoyColors.primary (#20C997 family)
37
+ const PRIMARY = _floatingToolsReact.dialColors.dialShadow;
38
+ function OnboardingTooltip({
39
+ title,
40
+ message,
41
+ onDismiss,
42
+ showArrow = true
43
+ }) {
44
+ const [entered, setEntered] = (0, _react.useState)(false);
45
+ const [buttonPressed, setButtonPressed] = (0, _react.useState)(false);
46
+ (0, _react.useEffect)(() => {
47
+ injectOnboardingKeyframes();
48
+ const raf = requestAnimationFrame(() => setEntered(true));
49
+ return () => cancelAnimationFrame(raf);
50
+ }, []);
51
+ const monoLabel = {
52
+ fontFamily: 'monospace',
53
+ textTransform: 'uppercase'
54
+ };
55
+ return /*#__PURE__*/(0, _jsxRuntime.jsx)("div", {
56
+ style: {
57
+ position: 'fixed',
58
+ left: '50%',
59
+ bottom: (0, _onboardingConstantsWeb.calculateTooltipPosition)(),
60
+ transform: `translateX(-50%) scale(${entered ? 1 : 0.8})`,
61
+ opacity: entered ? 1 : 0,
62
+ // native: fade 300ms + spring scale .8→1
63
+ transition: 'transform 300ms cubic-bezier(0.34, 1.3, 0.64, 1), opacity 300ms ease',
64
+ zIndex: 10002,
65
+ pointerEvents: 'auto'
66
+ },
67
+ children: /*#__PURE__*/(0, _jsxRuntime.jsxs)("div", {
68
+ style: {
69
+ position: 'relative',
70
+ animation: entered ? 'buoyOnboardPulse 3s ease-in-out infinite' : 'none'
71
+ },
72
+ children: [/*#__PURE__*/(0, _jsxRuntime.jsx)("div", {
73
+ style: {
74
+ position: 'absolute',
75
+ inset: -4,
76
+ borderRadius: 18,
77
+ backgroundColor: '#FFFFFF',
78
+ opacity: 0.15
79
+ }
80
+ }), /*#__PURE__*/(0, _jsxRuntime.jsxs)("div", {
81
+ style: {
82
+ position: 'relative',
83
+ maxWidth: 280,
84
+ backgroundColor: _floatingToolsReact.dialColors.dialBackground,
85
+ borderRadius: 16,
86
+ border: `2px solid ${_floatingToolsReact.dialColors.dialBorder}`,
87
+ padding: 20,
88
+ boxShadow: `0 0 20px ${(0, _floatingToolsReact.withAlpha)(PRIMARY, 0.6)}`,
89
+ display: 'flex',
90
+ flexDirection: 'column',
91
+ alignItems: 'center',
92
+ gap: 8
93
+ },
94
+ children: [/*#__PURE__*/(0, _jsxRuntime.jsx)("span", {
95
+ style: {
96
+ ...monoLabel,
97
+ fontSize: 16,
98
+ fontWeight: 900,
99
+ letterSpacing: 1,
100
+ color: PRIMARY,
101
+ textShadow: `0 0 4px ${PRIMARY}`,
102
+ textAlign: 'center'
103
+ },
104
+ children: title
105
+ }), /*#__PURE__*/(0, _jsxRuntime.jsx)("span", {
106
+ style: {
107
+ fontFamily: 'monospace',
108
+ fontSize: 13,
109
+ lineHeight: '20px',
110
+ color: '#FFFFFF',
111
+ textAlign: 'center'
112
+ },
113
+ children: message
114
+ }), /*#__PURE__*/(0, _jsxRuntime.jsx)("button", {
115
+ onClick: onDismiss,
116
+ onMouseDown: () => setButtonPressed(true),
117
+ onMouseUp: () => setButtonPressed(false),
118
+ onMouseLeave: () => setButtonPressed(false),
119
+ style: {
120
+ ...monoLabel,
121
+ marginTop: 8,
122
+ borderRadius: 8,
123
+ border: '2px solid #FFFFFF',
124
+ backgroundColor: 'rgba(255,255,255,0.1)',
125
+ padding: '10px 24px',
126
+ fontSize: 14,
127
+ fontWeight: 900,
128
+ letterSpacing: 1.5,
129
+ color: '#FFFFFF',
130
+ cursor: 'pointer',
131
+ opacity: buttonPressed ? 0.7 : 1,
132
+ transform: buttonPressed ? 'scale(0.96)' : 'scale(1)',
133
+ transition: 'transform 100ms ease, opacity 100ms ease'
134
+ },
135
+ children: "Got it!"
136
+ })]
137
+ }), showArrow && /*#__PURE__*/(0, _jsxRuntime.jsx)("div", {
138
+ style: {
139
+ position: 'absolute',
140
+ left: '50%',
141
+ bottom: _onboardingConstantsWeb.ARROW_BOTTOM_OFFSET,
142
+ marginLeft: -12,
143
+ width: 0,
144
+ height: 0,
145
+ borderLeft: '12px solid transparent',
146
+ borderRight: '12px solid transparent',
147
+ borderTop: `${_onboardingConstantsWeb.ARROW_HEIGHT}px solid ${PRIMARY}`,
148
+ filter: `drop-shadow(0 0 10px ${(0, _floatingToolsReact.withAlpha)(PRIMARY, 0.8)})`,
149
+ animation: entered ? 'buoyOnboardArrowBounce 1.6s ease-in-out infinite' : 'none'
150
+ }
151
+ })]
152
+ })
153
+ });
154
+ }
@@ -0,0 +1,34 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.SPACING_GAP = exports.ARROW_HEIGHT = exports.ARROW_BOTTOM_OFFSET = void 0;
7
+ exports.calculateTargetPosition = calculateTargetPosition;
8
+ exports.calculateTooltipPosition = calculateTooltipPosition;
9
+ exports.getScreenCenterY = getScreenCenterY;
10
+ /**
11
+ * Web twin of onboardingConstants.ts — same math, window.innerHeight instead
12
+ * of RN Dimensions.
13
+ */
14
+ const ARROW_BOTTOM_OFFSET = exports.ARROW_BOTTOM_OFFSET = -40; // Arrow extends below tooltip
15
+ const ARROW_HEIGHT = exports.ARROW_HEIGHT = 20; // borderTopWidth of arrow
16
+ const SPACING_GAP = exports.SPACING_GAP = 10; // Gap between arrow tip and target element
17
+
18
+ function getScreenCenterY() {
19
+ return window.innerHeight / 2;
20
+ }
21
+
22
+ /** Distance from screen bottom for tooltip positioning (centered-ish). */
23
+ function calculateTooltipPosition() {
24
+ const estimatedHalfHeight = 130; // ~half of (tooltip + arrow)
25
+ return getScreenCenterY() - estimatedHalfHeight;
26
+ }
27
+
28
+ /** Distance from screen bottom where the bubble should sit (under the arrow). */
29
+ function calculateTargetPosition() {
30
+ const tooltipBottom = calculateTooltipPosition();
31
+ const arrowTipFromBottom = tooltipBottom + ARROW_BOTTOM_OFFSET;
32
+ const actualArrowTip = arrowTipFromBottom - ARROW_HEIGHT;
33
+ return actualArrowTip - SPACING_GAP;
34
+ }
@@ -9,10 +9,10 @@ exports.UserStatus = UserStatus;
9
9
  var _react = require("react");
10
10
  var _reactNative = require("react-native");
11
11
  var _sharedUi = require("@buoy-gg/shared-ui");
12
- var _onboardingConstants = require("./dial/onboardingConstants.js");
13
- var _MinimizedToolsStack = require("./MinimizedToolsStack.js");
12
+ var _onboardingConstants = require("./dial/onboardingConstants");
13
+ var _MinimizedToolsStack = require("./MinimizedToolsStack");
14
14
  var _MinimizedToolsContext = require("./MinimizedToolsContext.js");
15
- var _AppHost = require("./AppHost.js");
15
+ var _AppHost = require("./AppHost");
16
16
  var _floatingToolsCore = require("@buoy-gg/floating-tools-core");
17
17
  var _jsxRuntime = require("react/jsx-runtime");
18
18
  // Shared utilities from floating-tools-core
@@ -6,14 +6,16 @@ Object.defineProperty(exports, "__esModule", {
6
6
  exports.Divider = Divider;
7
7
  exports.FloatingTools = FloatingTools;
8
8
  exports.UserStatus = UserStatus;
9
+ exports.getBubbleAnchorPosition = getBubbleAnchorPosition;
9
10
  var _react = require("react");
11
+ var _onboardingConstantsWeb = require("./dial/onboardingConstants.web.js");
10
12
  var _floatingToolsReact = require("@buoy-gg/floating-tools-react");
11
13
  var _jsxRuntime = require("react/jsx-runtime");
12
14
  /**
13
15
  * FloatingTools - Web renderer using shared React bindings.
14
16
  *
15
17
  * This file contains ONLY web-specific code (React DOM):
16
- * - Mouse event handling
18
+ * - Pointer event handling (mouse + touch — WKWebView/Capacitor included)
17
19
  * - requestAnimationFrame animation
18
20
  * - Web JSX (div, span)
19
21
  * - localStorage adapter
@@ -33,12 +35,23 @@ const webStorageAdapter = {
33
35
  setItem: (key, value) => localStorage.setItem(key, value)
34
36
  };
35
37
 
38
+ // =============================
39
+ // Native color values not present in floatingToolsColors
40
+ // (core's `secondary` is #E0E0E0 = buoyColors.text; the native bubble uses
41
+ // buoyColors.textSecondary #A0A0A0 for grip dots and "User" label text.
42
+ // Inlined here rather than changed in core because dial.ts also consumes
43
+ // floatingToolsColors.secondary for other surfaces.)
44
+ // =============================
45
+ // native shared-ui gameUIColors.ts: buoyColors.textSecondary = "#A0A0A0"
46
+ const NATIVE_TEXT_SECONDARY = '#A0A0A0';
47
+
36
48
  // =============================
37
49
  // GripVerticalIcon (web JSX)
38
50
  // =============================
39
51
  function GripVerticalIcon({
40
52
  size = 24,
41
- color = (0, _floatingToolsReact.withAlpha)(_floatingToolsReact.floatingToolsColors.secondary, 'CC')
53
+ // native shared-ui GripVerticalIcon.tsx: buoyColors.textSecondary + "CC"
54
+ color = (0, _floatingToolsReact.withAlpha)(NATIVE_TEXT_SECONDARY, 'CC')
42
55
  }) {
43
56
  const layout = (0, _floatingToolsReact.getGripIconLayout)(size);
44
57
  return /*#__PURE__*/(0, _jsxRuntime.jsx)("div", {
@@ -56,7 +69,9 @@ function GripVerticalIcon({
56
69
  flexDirection: 'column',
57
70
  alignItems: 'center',
58
71
  justifyContent: 'center',
59
- marginLeft: col === 0 ? 0 : layout.columnGap
72
+ // native GripVerticalIcon.tsx: marginHorizontal columnGap / 2
73
+ marginLeft: layout.columnGap / 2,
74
+ marginRight: layout.columnGap / 2
60
75
  },
61
76
  children: [0, 1, 2].map(row => /*#__PURE__*/(0, _jsxRuntime.jsx)("div", {
62
77
  style: {
@@ -64,7 +79,9 @@ function GripVerticalIcon({
64
79
  height: layout.dotSize,
65
80
  borderRadius: layout.dotSize / 2,
66
81
  backgroundColor: color,
67
- marginTop: row === 0 ? 0 : layout.rowGap
82
+ // native GripVerticalIcon.tsx: marginVertical rowGap / 2
83
+ marginTop: layout.rowGap / 2,
84
+ marginBottom: layout.rowGap / 2
68
85
  }
69
86
  }, row))
70
87
  }, col))
@@ -88,6 +105,16 @@ function Divider() {
88
105
  // =============================
89
106
  // UserStatus (web JSX)
90
107
  // =============================
108
+ // Mirrors the native gameUIColorsCompat mapping in floatingTools.tsx:
109
+ // success/optional/muted come from the shared palette, but `secondary`
110
+ // (the "User" label text) is buoyColors.textSecondary, not core's secondary.
111
+ const userStatusColors = {
112
+ success: _floatingToolsReact.floatingToolsColors.success,
113
+ optional: _floatingToolsReact.floatingToolsColors.optional,
114
+ muted: _floatingToolsReact.floatingToolsColors.muted,
115
+ // native floatingTools.tsx: gameUIColorsCompat.secondary = buoyColors.textSecondary
116
+ secondary: NATIVE_TEXT_SECONDARY
117
+ };
91
118
  function UserStatus({
92
119
  userRole,
93
120
  onPress
@@ -95,7 +122,7 @@ function UserStatus({
95
122
  const {
96
123
  isDragging
97
124
  } = (0, _floatingToolsReact.useFloatingToolsContext)();
98
- const config = (0, _floatingToolsReact.getUserStatusConfig)(userRole, _floatingToolsReact.floatingToolsColors);
125
+ const config = (0, _floatingToolsReact.getUserStatusConfig)(userRole, userStatusColors);
99
126
  const handleClick = e => {
100
127
  if (!isDragging && onPress) {
101
128
  e.stopPropagation();
@@ -117,7 +144,8 @@ function UserStatus({
117
144
  flexShrink: 0,
118
145
  cursor: onPress && !isDragging ? 'pointer' : 'default',
119
146
  background: 'none',
120
- border: 'none'
147
+ border: 'none',
148
+ margin: 0 // neutralize UA button margin (native View/Touchable has none)
121
149
  },
122
150
  children: [/*#__PURE__*/(0, _jsxRuntime.jsx)("div", {
123
151
  style: {
@@ -132,7 +160,11 @@ function UserStatus({
132
160
  fontSize: 10,
133
161
  fontWeight: 500,
134
162
  color: config.textColor,
135
- letterSpacing: 0.3
163
+ letterSpacing: 0.3,
164
+ // native RN <Text> renders in the platform system font; buttons
165
+ // otherwise use the UA font on web
166
+ fontFamily: '-apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif',
167
+ lineHeight: 'normal'
136
168
  },
137
169
  children: config.label
138
170
  })]
@@ -185,9 +217,20 @@ function useWebAnimation() {
185
217
  // Main FloatingTools Component
186
218
  // =============================
187
219
 
220
+ // Last known bubble position — the AppHost minimize animation targets this so
221
+ // tools shrink toward the stack instead of the old bottom-right dock.
222
+ let lastBubbleAnchor = null;
223
+ function getBubbleAnchorPosition() {
224
+ return lastBubbleAnchor;
225
+ }
188
226
  function FloatingTools({
189
227
  enablePositionPersistence = true,
190
- children
228
+ children,
229
+ pushToSide = false,
230
+ suspendPointerEvents = false,
231
+ centerOnboarding = false,
232
+ minimizedStack,
233
+ hasMinimizedStack = false
191
234
  }) {
192
235
  const bubbleRef = (0, _react.useRef)(null);
193
236
 
@@ -219,6 +262,15 @@ function FloatingTools({
219
262
  }
220
263
  }, [isInitialized, state.position, setAnimatedPosition]);
221
264
 
265
+ // Publish the bubble anchor for the AppHost minimize-target (stack lives
266
+ // fused to the bubble now, not in a fixed dock).
267
+ (0, _react.useEffect)(() => {
268
+ lastBubbleAnchor = {
269
+ x: animatedPosition.x,
270
+ y: animatedPosition.y
271
+ };
272
+ }, [animatedPosition]);
273
+
222
274
  // Handle window resize
223
275
  (0, _react.useEffect)(() => {
224
276
  const handleResize = () => {
@@ -243,17 +295,34 @@ function FloatingTools({
243
295
  }
244
296
  }, [bubbleMeasured, actions]);
245
297
 
246
- // Web-specific: mouse event handling
247
- const [isMouseDown, setIsMouseDown] = (0, _react.useState)(false);
248
- const handleMouseDown = (0, _react.useCallback)(e => {
298
+ // Keep the bubble below notches/status bars (WKWebView with viewport-fit=cover).
299
+ (0, _react.useEffect)(() => {
300
+ const probe = document.createElement('div');
301
+ probe.style.cssText = 'position:fixed;top:env(safe-area-inset-top);left:env(safe-area-inset-left);' + 'visibility:hidden;pointer-events:none';
302
+ document.body.appendChild(probe);
303
+ const rect = probe.getBoundingClientRect();
304
+ document.body.removeChild(probe);
305
+ if (rect.top > 0 || rect.left > 0) {
306
+ actions.setMinPosition({
307
+ x: Math.max(rect.left, 10),
308
+ y: Math.max(rect.top, 10)
309
+ });
310
+ }
311
+ }, [actions]);
312
+
313
+ // Web-specific: pointer event handling (mouse + touch).
314
+ // preventDefault on pointerdown suppresses the compatibility mouse events,
315
+ // and touchAction: 'none' on the bubble stops touch-drags from scrolling.
316
+ const [isPointerDown, setIsPointerDown] = (0, _react.useState)(false);
317
+ const handlePointerDown = (0, _react.useCallback)(e => {
249
318
  e.preventDefault();
250
- setIsMouseDown(true);
319
+ setIsPointerDown(true);
251
320
  actions.handleDragStart({
252
321
  clientX: e.clientX,
253
322
  clientY: e.clientY
254
323
  });
255
324
  }, [actions]);
256
- const handleMouseMove = (0, _react.useCallback)(e => {
325
+ const handlePointerMove = (0, _react.useCallback)(e => {
257
326
  const result = actions.handleDragMove({
258
327
  clientX: e.clientX,
259
328
  clientY: e.clientY
@@ -262,8 +331,8 @@ function FloatingTools({
262
331
  setAnimatedPosition(result.position);
263
332
  }
264
333
  }, [actions, setAnimatedPosition]);
265
- const handleMouseUp = (0, _react.useCallback)(e => {
266
- setIsMouseDown(false);
334
+ const handlePointerUp = (0, _react.useCallback)(e => {
335
+ setIsPointerDown(false);
267
336
  const result = actions.handleDragEnd({
268
337
  clientX: e.clientX,
269
338
  clientY: e.clientY
@@ -280,18 +349,88 @@ function FloatingTools({
280
349
  }
281
350
  }, [actions, animateTo, state.position]);
282
351
  (0, _react.useEffect)(() => {
283
- if (isMouseDown) {
284
- window.addEventListener('mousemove', handleMouseMove);
285
- window.addEventListener('mouseup', handleMouseUp);
352
+ if (isPointerDown) {
353
+ window.addEventListener('pointermove', handlePointerMove);
354
+ window.addEventListener('pointerup', handlePointerUp);
355
+ window.addEventListener('pointercancel', handlePointerUp);
286
356
  return () => {
287
- window.removeEventListener('mousemove', handleMouseMove);
288
- window.removeEventListener('mouseup', handleMouseUp);
357
+ window.removeEventListener('pointermove', handlePointerMove);
358
+ window.removeEventListener('pointerup', handlePointerUp);
359
+ window.removeEventListener('pointercancel', handlePointerUp);
289
360
  };
290
361
  }
291
- }, [isMouseDown, handleMouseMove, handleMouseUp]);
362
+ }, [isPointerDown, handlePointerMove, handlePointerUp]);
363
+
364
+ // Live refs so the pushToSide effect never animates from a stale closure
365
+ // (the from-position jump read as a "pop" when restoring).
366
+ const statePositionRef = (0, _react.useRef)(state.position);
367
+ statePositionRef.current = state.position;
368
+ const isHiddenRef = (0, _react.useRef)(state.isHidden);
369
+ isHiddenRef.current = state.isHidden;
370
+
371
+ // pushToSide: forceHide to the edge while a dial/tool is open; forceShow
372
+ // restores the saved position when it closes (200ms, native parity).
373
+ // Native semantics ported exactly (floatingTools.tsx:537-603):
374
+ // - push only when the bubble isn't already hidden (a user-hidden bubble
375
+ // is left alone, and we don't claim it as OUR push)
376
+ // - restore only when the bubble is STILL hidden from OUR push — if the
377
+ // user tapped/dragged it back out while a tool was open
378
+ // (userWantsVisibleRef), it stays exactly where they put it
379
+ const pushedRef = (0, _react.useRef)(false);
380
+ (0, _react.useEffect)(() => {
381
+ if (!isInitialized) return;
382
+ if (pushToSide && !pushedRef.current) {
383
+ if (isHiddenRef.current) return; // user hid it themselves — not our push
384
+ pushedRef.current = true;
385
+ const {
386
+ targetPosition
387
+ } = actions.forceHide();
388
+ animateTo(statePositionRef.current, targetPosition, () => {});
389
+ } else if (!pushToSide && pushedRef.current) {
390
+ pushedRef.current = false;
391
+ // User already showed it manually while the tool was open — leave it.
392
+ if (!isHiddenRef.current) return;
393
+ const {
394
+ targetPosition
395
+ } = actions.forceShow();
396
+ // The bubble may have grown while hidden (row tools/env badge toggled
397
+ // on) — clamp the restored position so it stays fully on-screen
398
+ // (native handles this via its width-change auto-reposition).
399
+ const width = bubbleRef.current?.getBoundingClientRect().width ?? 100;
400
+ const clamped = {
401
+ x: Math.max(10, Math.min(targetPosition.x, window.innerWidth - width - 10)),
402
+ y: targetPosition.y
403
+ };
404
+ animateTo(statePositionRef.current, clamped, () => {
405
+ actions.commitPosition(clamped);
406
+ });
407
+ }
408
+ // eslint-disable-next-line react-hooks/exhaustive-deps
409
+ }, [pushToSide, isInitialized]);
410
+
411
+ // centerOnboarding: park the bubble under the tooltip arrow while the
412
+ // welcome tooltip is up (native calculateTargetPosition math).
413
+ (0, _react.useEffect)(() => {
414
+ if (!centerOnboarding || !isInitialized) return;
415
+ const bubbleWidth = bubbleRef.current?.getBoundingClientRect().width ?? 100;
416
+ const bubbleHeight = bubbleRef.current?.getBoundingClientRect().height ?? 32;
417
+ const fromBottom = (0, _onboardingConstantsWeb.calculateTargetPosition)();
418
+ const target = {
419
+ x: (window.innerWidth - bubbleWidth) / 2,
420
+ y: window.innerHeight - fromBottom - bubbleHeight
421
+ };
422
+ animateTo(statePositionRef.current, target, () => {});
423
+ // eslint-disable-next-line react-hooks/exhaustive-deps
424
+ }, [centerOnboarding, isInitialized]);
292
425
 
293
426
  // Interleave children with dividers
294
427
  const actionsContent = (0, _react.useMemo)(() => (0, _floatingToolsReact.interleaveWithDividers)(_react.Children.toArray(children), key => /*#__PURE__*/(0, _jsxRuntime.jsx)(Divider, {}, key)), [children]);
428
+
429
+ // Suppress the first paint until the persisted position has loaded so the
430
+ // bubble doesn't flash at 0,0 (native floatingTools.tsx:935-937).
431
+ if (!isInitialized) {
432
+ return null;
433
+ }
295
434
  return /*#__PURE__*/(0, _jsxRuntime.jsxs)("div", {
296
435
  ref: bubbleRef,
297
436
  role: "toolbar",
@@ -305,21 +444,43 @@ function FloatingTools({
305
444
  flexDirection: 'row',
306
445
  alignItems: 'center',
307
446
  backgroundColor: _floatingToolsReact.floatingToolsColors.panel,
308
- borderRadius: 6,
447
+ // native: top-left corner + top border flatten when the minimized
448
+ // stack is fused above (floatingTools.tsx containerStyle)
449
+ borderTopLeftRadius: hasMinimizedStack ? 0 : 6,
450
+ borderTopRightRadius: 6,
451
+ borderBottomLeftRadius: 6,
452
+ borderBottomRightRadius: 6,
309
453
  borderWidth: state.isDragging ? 2 : 1,
454
+ borderTopWidth: state.isDragging ? 2 : hasMinimizedStack ? 0 : 1,
310
455
  borderStyle: 'solid',
311
456
  borderColor: state.isDragging ? _floatingToolsReact.floatingToolsColors.dragActive : (0, _floatingToolsReact.withAlpha)(_floatingToolsReact.floatingToolsColors.muted, '66'),
312
- boxShadow: state.isDragging ? `0 6px 12px ${(0, _floatingToolsReact.withAlpha)(_floatingToolsReact.floatingToolsColors.dragActive, '99')}` : '0 4px 8px rgba(0, 0, 0, 0.3)',
457
+ // native floatingTools.tsx: shadowOffset {0, 6|4}, shadowRadius 12|8,
458
+ // shadowOpacity 0.6|0.3, shadowColor dragActive+"99"|"#000".
459
+ // Dragging color = 0x99 (0.6) alpha x 0.6 shadowOpacity = ~0.36 effective.
460
+ boxShadow: state.isDragging ? `0 6px 12px ${(0, _floatingToolsReact.withAlpha)(_floatingToolsReact.floatingToolsColors.dragActive, 0.36)}` : '0 4px 8px rgba(0, 0, 0, 0.3)',
313
461
  userSelect: 'none',
314
- touchAction: 'none'
462
+ touchAction: 'none',
463
+ pointerEvents: suspendPointerEvents ? 'none' : 'auto'
315
464
  },
316
- children: [/*#__PURE__*/(0, _jsxRuntime.jsx)("div", {
465
+ children: [minimizedStack && /*#__PURE__*/(0, _jsxRuntime.jsx)("div", {
466
+ style: {
467
+ position: 'absolute',
468
+ bottom: '100%',
469
+ left: -1,
470
+ // align with the bubble border edge
471
+ width: _floatingToolsReact.VISIBLE_HANDLE_WIDTH,
472
+ overflow: 'visible',
473
+ zIndex: 1001
474
+ },
475
+ children: minimizedStack
476
+ }), /*#__PURE__*/(0, _jsxRuntime.jsx)("div", {
317
477
  role: "slider",
318
478
  "aria-label": "Drag handle",
319
479
  "aria-valuetext": `Position: ${Math.round(animatedPosition.x)}, ${Math.round(animatedPosition.y)}`,
320
480
  tabIndex: 0,
321
- onMouseDown: handleMouseDown,
481
+ onPointerDown: handlePointerDown,
322
482
  style: {
483
+ touchAction: 'none',
323
484
  paddingLeft: 6,
324
485
  paddingRight: 6,
325
486
  paddingTop: 6,
@@ -329,9 +490,11 @@ function FloatingTools({
329
490
  alignItems: 'center',
330
491
  justifyContent: 'center',
331
492
  width: _floatingToolsReact.VISIBLE_HANDLE_WIDTH,
493
+ boxSizing: 'border-box',
494
+ // RN width includes padding/border
332
495
  borderRight: `1px solid ${(0, _floatingToolsReact.withAlpha)(_floatingToolsReact.floatingToolsColors.muted, '66')}`,
333
- borderTopLeftRadius: 5,
334
- borderBottomLeftRadius: 5,
496
+ // native dragHandleStyle sets NO corner radius (container overflow is
497
+ // visible); the 10%-alpha bg square corner matches native rendering
335
498
  cursor: state.isDragging ? 'grabbing' : 'grab'
336
499
  },
337
500
  children: /*#__PURE__*/(0, _jsxRuntime.jsx)(GripVerticalIcon, {
@@ -255,10 +255,10 @@ Object.keys(_types).forEach(function (key) {
255
255
  });
256
256
  });
257
257
  var _DevToolsSettingsModal = require("./floatingMenu/DevToolsSettingsModal");
258
- var _AppHost = require("./floatingMenu/AppHost.js");
258
+ var _AppHost = require("./floatingMenu/AppHost");
259
259
  var _DevToolsVisibilityContext = require("./floatingMenu/DevToolsVisibilityContext.js");
260
260
  var _ToggleStateManager = require("./floatingMenu/ToggleStateManager.js");
261
261
  var _MinimizedToolsContext = require("./floatingMenu/MinimizedToolsContext.js");
262
- var _MinimizedToolsStack = require("./floatingMenu/MinimizedToolsStack.js");
262
+ var _MinimizedToolsStack = require("./floatingMenu/MinimizedToolsStack");
263
263
  var _license = require("@buoy-gg/license");
264
264
  function _interopRequireWildcard(e, t) { if ("function" == typeof WeakMap) var r = new WeakMap(), n = new WeakMap(); return (_interopRequireWildcard = function (e, t) { if (!t && e && e.__esModule) return e; var o, i, f = { __proto__: null, default: e }; if (null === e || "object" != typeof e && "function" != typeof e) return f; if (o = t ? n : r) { if (o.has(e)) return o.get(e); o.set(e, f); } for (const t in e) "default" !== t && {}.hasOwnProperty.call(e, t) && ((i = (o = Object.defineProperty) && Object.getOwnPropertyDescriptor(e, t)) && (i.get || i.set) ? o(f, t, i) : f[t] = e[t]); return f; })(e, t); }
@@ -3,6 +3,18 @@
3
3
  Object.defineProperty(exports, "__esModule", {
4
4
  value: true
5
5
  });
6
+ Object.defineProperty(exports, "AppHostProvider", {
7
+ enumerable: true,
8
+ get: function () {
9
+ return _AppHostWeb.AppHostProvider;
10
+ }
11
+ });
12
+ Object.defineProperty(exports, "AppOverlay", {
13
+ enumerable: true,
14
+ get: function () {
15
+ return _AppHostWeb.AppOverlay;
16
+ }
17
+ });
6
18
  Object.defineProperty(exports, "DialMenu", {
7
19
  enumerable: true,
8
20
  get: function () {
@@ -111,6 +123,12 @@ Object.defineProperty(exports, "settingsStyles", {
111
123
  return _floatingToolsReact.settingsStyles;
112
124
  }
113
125
  });
126
+ Object.defineProperty(exports, "useAppHost", {
127
+ enumerable: true,
128
+ get: function () {
129
+ return _AppHostWeb.useAppHost;
130
+ }
131
+ });
114
132
  Object.defineProperty(exports, "useFloatingTools", {
115
133
  enumerable: true,
116
134
  get: function () {
@@ -127,5 +145,6 @@ var _FloatingDevToolsWeb = require("./floatingMenu/FloatingDevTools.web.js");
127
145
  var _floatingToolsWeb = require("./floatingMenu/floatingTools.web.js");
128
146
  var _DialDevToolsWeb = require("./floatingMenu/dial/DialDevTools.web.js");
129
147
  var _DevToolsSettingsModalWeb = require("./floatingMenu/DevToolsSettingsModal.web.js");
148
+ var _AppHostWeb = require("./floatingMenu/AppHost.web.js");
130
149
  var _autoDiscoverPresetsWeb = require("./utils/autoDiscoverPresets.web.js");
131
150
  var _floatingToolsReact = require("@buoy-gg/floating-tools-react");