@buoy-gg/core 1.7.2

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 (132) hide show
  1. package/README.md +43 -0
  2. package/lib/commonjs/floatingMenu/AppHost.js +410 -0
  3. package/lib/commonjs/floatingMenu/AppHostLogic.js +44 -0
  4. package/lib/commonjs/floatingMenu/DefaultConfigContext.js +45 -0
  5. package/lib/commonjs/floatingMenu/DevToolsSettingsModal.js +2274 -0
  6. package/lib/commonjs/floatingMenu/DevToolsVisibilityContext.js +49 -0
  7. package/lib/commonjs/floatingMenu/DraggableHeader.js +114 -0
  8. package/lib/commonjs/floatingMenu/FloatingDevTools.js +254 -0
  9. package/lib/commonjs/floatingMenu/FloatingMenu.js +364 -0
  10. package/lib/commonjs/floatingMenu/MinimizedToolsContext.js +247 -0
  11. package/lib/commonjs/floatingMenu/MinimizedToolsStack.js +206 -0
  12. package/lib/commonjs/floatingMenu/ToggleStateManager.js +36 -0
  13. package/lib/commonjs/floatingMenu/autoDiscoverPresets.js +241 -0
  14. package/lib/commonjs/floatingMenu/defaultConfig.js +160 -0
  15. package/lib/commonjs/floatingMenu/dial/DialDevTools.js +835 -0
  16. package/lib/commonjs/floatingMenu/dial/DialIcon.js +246 -0
  17. package/lib/commonjs/floatingMenu/dial/OnboardingTooltip.js +249 -0
  18. package/lib/commonjs/floatingMenu/dial/onboardingConstants.js +70 -0
  19. package/lib/commonjs/floatingMenu/floatingTools.js +771 -0
  20. package/lib/commonjs/floatingMenu/settingsBus.js +23 -0
  21. package/lib/commonjs/floatingMenu/types.js +5 -0
  22. package/lib/commonjs/index.js +240 -0
  23. package/lib/commonjs/package.json +1 -0
  24. package/lib/module/floatingMenu/AppHost.js +402 -0
  25. package/lib/module/floatingMenu/AppHostLogic.js +39 -0
  26. package/lib/module/floatingMenu/DefaultConfigContext.js +39 -0
  27. package/lib/module/floatingMenu/DevToolsSettingsModal.js +2273 -0
  28. package/lib/module/floatingMenu/DevToolsVisibilityContext.js +44 -0
  29. package/lib/module/floatingMenu/DraggableHeader.js +110 -0
  30. package/lib/module/floatingMenu/FloatingDevTools.js +249 -0
  31. package/lib/module/floatingMenu/FloatingMenu.js +358 -0
  32. package/lib/module/floatingMenu/MinimizedToolsContext.js +239 -0
  33. package/lib/module/floatingMenu/MinimizedToolsStack.js +202 -0
  34. package/lib/module/floatingMenu/ToggleStateManager.js +32 -0
  35. package/lib/module/floatingMenu/autoDiscoverPresets.js +236 -0
  36. package/lib/module/floatingMenu/defaultConfig.js +151 -0
  37. package/lib/module/floatingMenu/dial/DialDevTools.js +829 -0
  38. package/lib/module/floatingMenu/dial/DialIcon.js +241 -0
  39. package/lib/module/floatingMenu/dial/OnboardingTooltip.js +244 -0
  40. package/lib/module/floatingMenu/dial/onboardingConstants.js +64 -0
  41. package/lib/module/floatingMenu/floatingTools.js +767 -0
  42. package/lib/module/floatingMenu/settingsBus.js +19 -0
  43. package/lib/module/floatingMenu/types.js +3 -0
  44. package/lib/module/index.js +29 -0
  45. package/lib/module/package.json +1 -0
  46. package/lib/typescript/commonjs/floatingMenu/AppHost.d.ts +39 -0
  47. package/lib/typescript/commonjs/floatingMenu/AppHost.d.ts.map +1 -0
  48. package/lib/typescript/commonjs/floatingMenu/AppHostLogic.d.ts +37 -0
  49. package/lib/typescript/commonjs/floatingMenu/AppHostLogic.d.ts.map +1 -0
  50. package/lib/typescript/commonjs/floatingMenu/DefaultConfigContext.d.ts +27 -0
  51. package/lib/typescript/commonjs/floatingMenu/DefaultConfigContext.d.ts.map +1 -0
  52. package/lib/typescript/commonjs/floatingMenu/DevToolsSettingsModal.d.ts +57 -0
  53. package/lib/typescript/commonjs/floatingMenu/DevToolsSettingsModal.d.ts.map +1 -0
  54. package/lib/typescript/commonjs/floatingMenu/DevToolsVisibilityContext.d.ts +25 -0
  55. package/lib/typescript/commonjs/floatingMenu/DevToolsVisibilityContext.d.ts.map +1 -0
  56. package/lib/typescript/commonjs/floatingMenu/DraggableHeader.d.ts +30 -0
  57. package/lib/typescript/commonjs/floatingMenu/DraggableHeader.d.ts.map +1 -0
  58. package/lib/typescript/commonjs/floatingMenu/FloatingDevTools.d.ts +226 -0
  59. package/lib/typescript/commonjs/floatingMenu/FloatingDevTools.d.ts.map +1 -0
  60. package/lib/typescript/commonjs/floatingMenu/FloatingMenu.d.ts +39 -0
  61. package/lib/typescript/commonjs/floatingMenu/FloatingMenu.d.ts.map +1 -0
  62. package/lib/typescript/commonjs/floatingMenu/MinimizedToolsContext.d.ts +95 -0
  63. package/lib/typescript/commonjs/floatingMenu/MinimizedToolsContext.d.ts.map +1 -0
  64. package/lib/typescript/commonjs/floatingMenu/MinimizedToolsStack.d.ts +10 -0
  65. package/lib/typescript/commonjs/floatingMenu/MinimizedToolsStack.d.ts.map +1 -0
  66. package/lib/typescript/commonjs/floatingMenu/ToggleStateManager.d.ts +21 -0
  67. package/lib/typescript/commonjs/floatingMenu/ToggleStateManager.d.ts.map +1 -0
  68. package/lib/typescript/commonjs/floatingMenu/autoDiscoverPresets.d.ts +75 -0
  69. package/lib/typescript/commonjs/floatingMenu/autoDiscoverPresets.d.ts.map +1 -0
  70. package/lib/typescript/commonjs/floatingMenu/defaultConfig.d.ts +120 -0
  71. package/lib/typescript/commonjs/floatingMenu/defaultConfig.d.ts.map +1 -0
  72. package/lib/typescript/commonjs/floatingMenu/dial/DialDevTools.d.ts +35 -0
  73. package/lib/typescript/commonjs/floatingMenu/dial/DialDevTools.d.ts.map +1 -0
  74. package/lib/typescript/commonjs/floatingMenu/dial/DialIcon.d.ts +14 -0
  75. package/lib/typescript/commonjs/floatingMenu/dial/DialIcon.d.ts.map +1 -0
  76. package/lib/typescript/commonjs/floatingMenu/dial/OnboardingTooltip.d.ts +12 -0
  77. package/lib/typescript/commonjs/floatingMenu/dial/OnboardingTooltip.d.ts.map +1 -0
  78. package/lib/typescript/commonjs/floatingMenu/dial/onboardingConstants.d.ts +30 -0
  79. package/lib/typescript/commonjs/floatingMenu/dial/onboardingConstants.d.ts.map +1 -0
  80. package/lib/typescript/commonjs/floatingMenu/floatingTools.d.ts +56 -0
  81. package/lib/typescript/commonjs/floatingMenu/floatingTools.d.ts.map +1 -0
  82. package/lib/typescript/commonjs/floatingMenu/settingsBus.d.ts +10 -0
  83. package/lib/typescript/commonjs/floatingMenu/settingsBus.d.ts.map +1 -0
  84. package/lib/typescript/commonjs/floatingMenu/types.d.ts +56 -0
  85. package/lib/typescript/commonjs/floatingMenu/types.d.ts.map +1 -0
  86. package/lib/typescript/commonjs/index.d.ts +18 -0
  87. package/lib/typescript/commonjs/index.d.ts.map +1 -0
  88. package/lib/typescript/commonjs/package.json +1 -0
  89. package/lib/typescript/module/floatingMenu/AppHost.d.ts +39 -0
  90. package/lib/typescript/module/floatingMenu/AppHost.d.ts.map +1 -0
  91. package/lib/typescript/module/floatingMenu/AppHostLogic.d.ts +37 -0
  92. package/lib/typescript/module/floatingMenu/AppHostLogic.d.ts.map +1 -0
  93. package/lib/typescript/module/floatingMenu/DefaultConfigContext.d.ts +27 -0
  94. package/lib/typescript/module/floatingMenu/DefaultConfigContext.d.ts.map +1 -0
  95. package/lib/typescript/module/floatingMenu/DevToolsSettingsModal.d.ts +57 -0
  96. package/lib/typescript/module/floatingMenu/DevToolsSettingsModal.d.ts.map +1 -0
  97. package/lib/typescript/module/floatingMenu/DevToolsVisibilityContext.d.ts +25 -0
  98. package/lib/typescript/module/floatingMenu/DevToolsVisibilityContext.d.ts.map +1 -0
  99. package/lib/typescript/module/floatingMenu/DraggableHeader.d.ts +30 -0
  100. package/lib/typescript/module/floatingMenu/DraggableHeader.d.ts.map +1 -0
  101. package/lib/typescript/module/floatingMenu/FloatingDevTools.d.ts +226 -0
  102. package/lib/typescript/module/floatingMenu/FloatingDevTools.d.ts.map +1 -0
  103. package/lib/typescript/module/floatingMenu/FloatingMenu.d.ts +39 -0
  104. package/lib/typescript/module/floatingMenu/FloatingMenu.d.ts.map +1 -0
  105. package/lib/typescript/module/floatingMenu/MinimizedToolsContext.d.ts +95 -0
  106. package/lib/typescript/module/floatingMenu/MinimizedToolsContext.d.ts.map +1 -0
  107. package/lib/typescript/module/floatingMenu/MinimizedToolsStack.d.ts +10 -0
  108. package/lib/typescript/module/floatingMenu/MinimizedToolsStack.d.ts.map +1 -0
  109. package/lib/typescript/module/floatingMenu/ToggleStateManager.d.ts +21 -0
  110. package/lib/typescript/module/floatingMenu/ToggleStateManager.d.ts.map +1 -0
  111. package/lib/typescript/module/floatingMenu/autoDiscoverPresets.d.ts +75 -0
  112. package/lib/typescript/module/floatingMenu/autoDiscoverPresets.d.ts.map +1 -0
  113. package/lib/typescript/module/floatingMenu/defaultConfig.d.ts +120 -0
  114. package/lib/typescript/module/floatingMenu/defaultConfig.d.ts.map +1 -0
  115. package/lib/typescript/module/floatingMenu/dial/DialDevTools.d.ts +35 -0
  116. package/lib/typescript/module/floatingMenu/dial/DialDevTools.d.ts.map +1 -0
  117. package/lib/typescript/module/floatingMenu/dial/DialIcon.d.ts +14 -0
  118. package/lib/typescript/module/floatingMenu/dial/DialIcon.d.ts.map +1 -0
  119. package/lib/typescript/module/floatingMenu/dial/OnboardingTooltip.d.ts +12 -0
  120. package/lib/typescript/module/floatingMenu/dial/OnboardingTooltip.d.ts.map +1 -0
  121. package/lib/typescript/module/floatingMenu/dial/onboardingConstants.d.ts +30 -0
  122. package/lib/typescript/module/floatingMenu/dial/onboardingConstants.d.ts.map +1 -0
  123. package/lib/typescript/module/floatingMenu/floatingTools.d.ts +56 -0
  124. package/lib/typescript/module/floatingMenu/floatingTools.d.ts.map +1 -0
  125. package/lib/typescript/module/floatingMenu/settingsBus.d.ts +10 -0
  126. package/lib/typescript/module/floatingMenu/settingsBus.d.ts.map +1 -0
  127. package/lib/typescript/module/floatingMenu/types.d.ts +56 -0
  128. package/lib/typescript/module/floatingMenu/types.d.ts.map +1 -0
  129. package/lib/typescript/module/index.d.ts +18 -0
  130. package/lib/typescript/module/index.d.ts.map +1 -0
  131. package/lib/typescript/module/package.json +1 -0
  132. package/package.json +79 -0
@@ -0,0 +1,241 @@
1
+ "use strict";
2
+
3
+ import { useRef } from "react";
4
+ import { StyleSheet, Pressable, View, Text, Dimensions, Animated } from "react-native";
5
+ import { getDialLayout, getIconPosition, getIconStaggerInputRange, DIAL_START_ANGLE, dialColors, dialStyles, dialAnimationConfig } from "@buoy-gg/floating-tools-core";
6
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
7
+ const {
8
+ width: SCREEN_WIDTH
9
+ } = Dimensions.get("window");
10
+
11
+ // Use shared layout calculation
12
+ const layout = getDialLayout({
13
+ screenWidth: SCREEN_WIDTH
14
+ });
15
+ const VIEW_SIZE = layout.iconSize;
16
+ const CIRCLE_SIZE = layout.circleSize;
17
+ const CIRCLE_RADIUS = layout.circleRadius;
18
+ export const DialIcon = ({
19
+ index,
20
+ icon,
21
+ iconsProgress,
22
+ onPress,
23
+ selectedIcon,
24
+ totalIcons
25
+ }) => {
26
+ // Use shared position calculation from core
27
+ const iconPosition = getIconPosition(index, totalIcons, layout.iconRadius, DIAL_START_ANGLE);
28
+ const {
29
+ x: finalX,
30
+ y: finalY,
31
+ angle
32
+ } = iconPosition;
33
+ const radius = layout.iconRadius;
34
+
35
+ // Animation values - using interpolation for better performance
36
+ const scale = useRef(new Animated.Value(1)).current;
37
+
38
+ // Hover animation on press in/out - using shared config
39
+ // Fallback values in case dialAnimationConfig hasn't loaded yet
40
+ const iconAnimConfig = dialAnimationConfig?.icons ?? {
41
+ pressIn: {
42
+ scale: 0.95,
43
+ damping: 15,
44
+ stiffness: 400
45
+ },
46
+ pressOut: {
47
+ scale: 1,
48
+ damping: 15,
49
+ stiffness: 400
50
+ }
51
+ };
52
+ const {
53
+ pressIn,
54
+ pressOut
55
+ } = iconAnimConfig;
56
+ const handlePressIn = () => {
57
+ Animated.spring(scale, {
58
+ toValue: pressIn.scale,
59
+ damping: pressIn.damping,
60
+ stiffness: pressIn.stiffness,
61
+ useNativeDriver: true
62
+ }).start();
63
+ };
64
+ const handlePressOut = () => {
65
+ Animated.spring(scale, {
66
+ toValue: pressOut.scale,
67
+ damping: pressOut.damping,
68
+ stiffness: pressOut.stiffness,
69
+ useNativeDriver: true
70
+ }).start();
71
+ };
72
+
73
+ // Use shared stagger calculation from core
74
+ const staggerInputRange = getIconStaggerInputRange(index, totalIcons);
75
+
76
+ // Use interpolation for smooth animation that works both directions
77
+ const staggeredProgress = iconsProgress.interpolate({
78
+ inputRange: staggerInputRange,
79
+ outputRange: [0, 0, 1, 1],
80
+ extrapolate: "clamp"
81
+ });
82
+
83
+ // Spiral animation with interpolation
84
+ const spiralRotation = staggeredProgress.interpolate({
85
+ inputRange: [0, 1],
86
+ outputRange: [Math.PI * 2, 0] // Spiral from 2π to 0
87
+ });
88
+
89
+ // Distance from center
90
+ const distance = staggeredProgress.interpolate({
91
+ inputRange: [0, 1],
92
+ outputRange: [0, radius]
93
+ });
94
+
95
+ // Calculate X and Y positions using Animated operations
96
+ const translateX = Animated.add(Animated.multiply(distance, spiralRotation.interpolate({
97
+ inputRange: [0, Math.PI * 2],
98
+ outputRange: [Math.cos(angle), Math.cos(angle + Math.PI * 2)]
99
+ })), staggeredProgress.interpolate({
100
+ inputRange: [0, 1],
101
+ outputRange: [0, finalX - radius * Math.cos(angle + Math.PI * 2)]
102
+ }));
103
+ const translateY = Animated.add(Animated.multiply(distance, spiralRotation.interpolate({
104
+ inputRange: [0, Math.PI * 2],
105
+ outputRange: [Math.sin(angle), Math.sin(angle + Math.PI * 2)]
106
+ })), staggeredProgress.interpolate({
107
+ inputRange: [0, 1],
108
+ outputRange: [0, finalY - radius * Math.sin(angle + Math.PI * 2)]
109
+ }));
110
+
111
+ // Opacity animation
112
+ const itemOpacity = staggeredProgress.interpolate({
113
+ inputRange: [0, 0.3, 1],
114
+ outputRange: [0, 0.3, 1]
115
+ });
116
+
117
+ // Scale based on progress
118
+ const progressScale = staggeredProgress;
119
+
120
+ // Main animated style for position and appearance
121
+ const animatedStyle = {
122
+ position: "absolute",
123
+ left: CIRCLE_RADIUS - VIEW_SIZE / 2,
124
+ // Center position
125
+ top: CIRCLE_RADIUS - VIEW_SIZE / 2,
126
+ // Center position
127
+ opacity: itemOpacity,
128
+ transform: [{
129
+ translateX
130
+ },
131
+ // Apply translation from center
132
+ {
133
+ translateY
134
+ },
135
+ // Apply translation from center
136
+ {
137
+ scale: Animated.multiply(scale, progressScale)
138
+ }]
139
+ };
140
+
141
+ // Check if this is an empty spot (no icon and no iconComponent)
142
+ const isEmpty = icon.icon === null && !icon.iconComponent;
143
+ return /*#__PURE__*/_jsx(Animated.View, {
144
+ style: [styles.view, animatedStyle],
145
+ children: isEmpty ?
146
+ /*#__PURE__*/
147
+ // Empty spot - just show a subtle circle
148
+ _jsx(View, {
149
+ style: styles.emptySpot,
150
+ children: /*#__PURE__*/_jsx(View, {
151
+ style: styles.emptyDot
152
+ })
153
+ }) : /*#__PURE__*/_jsxs(Pressable, {
154
+ onPress: () => onPress(index),
155
+ onPressIn: handlePressIn,
156
+ onPressOut: handlePressOut,
157
+ style: styles.pressable,
158
+ children: [/*#__PURE__*/_jsx(View, {
159
+ style: [styles.iconGradientBg, {
160
+ backgroundColor: "rgba(0, 0, 0, 0.2)"
161
+ }]
162
+ }), /*#__PURE__*/_jsx(View, {
163
+ style: [styles.iconInnerGlow, {
164
+ backgroundColor: "rgba(255, 255, 255, 0.02)"
165
+ }]
166
+ }), /*#__PURE__*/_jsx(View, {
167
+ style: styles.iconWrapper,
168
+ children: icon.iconComponent ? (() => {
169
+ const IconComp = icon.iconComponent;
170
+ return /*#__PURE__*/_jsx(IconComp, {
171
+ slot: "dial",
172
+ size: 32
173
+ });
174
+ })() : icon.icon
175
+ }), /*#__PURE__*/_jsx(Text, {
176
+ style: styles.label,
177
+ numberOfLines: 1,
178
+ adjustsFontSizeToFit: true,
179
+ minimumFontScale: 0.7,
180
+ children: icon.name.toUpperCase()
181
+ })]
182
+ })
183
+ });
184
+ };
185
+ const styles = StyleSheet.create({
186
+ view: {
187
+ width: VIEW_SIZE,
188
+ height: VIEW_SIZE,
189
+ justifyContent: "center",
190
+ alignItems: "center"
191
+ },
192
+ pressable: {
193
+ width: "100%",
194
+ height: "100%",
195
+ justifyContent: "center",
196
+ alignItems: "center",
197
+ padding: 4,
198
+ backgroundColor: "transparent"
199
+ },
200
+ iconGradientBg: {
201
+ position: "absolute",
202
+ width: "85%",
203
+ height: "85%",
204
+ borderRadius: 12,
205
+ opacity: 0.3
206
+ },
207
+ iconInnerGlow: {
208
+ position: "absolute",
209
+ width: "70%",
210
+ height: "70%",
211
+ borderRadius: 10,
212
+ opacity: 0.5
213
+ },
214
+ iconWrapper: {
215
+ marginBottom: 4,
216
+ alignItems: "center",
217
+ justifyContent: "center"
218
+ },
219
+ label: {
220
+ fontSize: dialStyles.icon.label.fontSize,
221
+ fontWeight: dialStyles.icon.label.fontWeight,
222
+ letterSpacing: dialStyles.icon.label.letterSpacing,
223
+ fontFamily: dialStyles.icon.label.fontFamily,
224
+ marginTop: dialStyles.icon.label.marginTop,
225
+ color: dialColors.iconLabel
226
+ },
227
+ emptySpot: {
228
+ width: "100%",
229
+ height: "100%",
230
+ justifyContent: "center",
231
+ alignItems: "center"
232
+ },
233
+ emptyDot: {
234
+ width: dialStyles.emptySlot.dotSize,
235
+ height: dialStyles.emptySlot.dotSize,
236
+ borderRadius: dialStyles.emptySlot.dotSize / 2,
237
+ backgroundColor: dialColors.emptyDotBackground,
238
+ borderWidth: dialStyles.emptySlot.borderWidth,
239
+ borderColor: dialColors.emptyDotBorder
240
+ }
241
+ });
@@ -0,0 +1,244 @@
1
+ "use strict";
2
+
3
+ import { useEffect, useRef } from "react";
4
+ import { Animated, Pressable, StyleSheet, Text, View, Easing } from "react-native";
5
+ import { dialColors, buoyColors } from "@buoy-gg/shared-ui";
6
+ import { calculateTooltipPosition, ARROW_BOTTOM_OFFSET, ARROW_HEIGHT } from "./onboardingConstants.js";
7
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
8
+ export const OnboardingTooltip = ({
9
+ visible,
10
+ onDismiss,
11
+ title = "Welcome to Buoy Tools!",
12
+ message = "Tap the center button to configure and add developer tools to your dial menu."
13
+ }) => {
14
+ const fadeAnim = useRef(new Animated.Value(0)).current;
15
+ const scaleAnim = useRef(new Animated.Value(0.8)).current;
16
+ const pulseAnim = useRef(new Animated.Value(1)).current;
17
+ const arrowBounceAnim = useRef(new Animated.Value(0)).current;
18
+ useEffect(() => {
19
+ if (visible) {
20
+ // Entrance animation
21
+ Animated.parallel([Animated.timing(fadeAnim, {
22
+ toValue: 1,
23
+ duration: 300,
24
+ easing: Easing.out(Easing.ease),
25
+ useNativeDriver: true
26
+ }), Animated.spring(scaleAnim, {
27
+ toValue: 1,
28
+ damping: 12,
29
+ stiffness: 150,
30
+ useNativeDriver: true
31
+ })]).start();
32
+
33
+ // Continuous pulse animation for the tooltip
34
+ Animated.loop(Animated.sequence([Animated.timing(pulseAnim, {
35
+ toValue: 1.02,
36
+ duration: 1500,
37
+ easing: Easing.inOut(Easing.ease),
38
+ useNativeDriver: true
39
+ }), Animated.timing(pulseAnim, {
40
+ toValue: 1,
41
+ duration: 1500,
42
+ easing: Easing.inOut(Easing.ease),
43
+ useNativeDriver: true
44
+ })])).start();
45
+
46
+ // Bouncing arrow animation
47
+ Animated.loop(Animated.sequence([Animated.timing(arrowBounceAnim, {
48
+ toValue: -8,
49
+ duration: 800,
50
+ easing: Easing.inOut(Easing.ease),
51
+ useNativeDriver: true
52
+ }), Animated.timing(arrowBounceAnim, {
53
+ toValue: 0,
54
+ duration: 800,
55
+ easing: Easing.inOut(Easing.ease),
56
+ useNativeDriver: true
57
+ })])).start();
58
+ } else {
59
+ // Exit animation
60
+ Animated.parallel([Animated.timing(fadeAnim, {
61
+ toValue: 0,
62
+ duration: 200,
63
+ easing: Easing.in(Easing.ease),
64
+ useNativeDriver: true
65
+ }), Animated.timing(scaleAnim, {
66
+ toValue: 0.8,
67
+ duration: 200,
68
+ easing: Easing.in(Easing.ease),
69
+ useNativeDriver: true
70
+ })]).start();
71
+ }
72
+ }, [visible]);
73
+ if (!visible) {
74
+ return null;
75
+ }
76
+ return /*#__PURE__*/_jsx(Animated.View, {
77
+ style: [styles.container, {
78
+ opacity: fadeAnim,
79
+ transform: [{
80
+ scale: scaleAnim
81
+ }]
82
+ }],
83
+ pointerEvents: "box-none",
84
+ children: /*#__PURE__*/_jsx(Animated.View, {
85
+ style: [styles.tooltipContainer, {
86
+ transform: [{
87
+ scale: pulseAnim
88
+ }]
89
+ }],
90
+ children: /*#__PURE__*/_jsxs(View, {
91
+ style: styles.tooltip,
92
+ children: [/*#__PURE__*/_jsx(View, {
93
+ style: styles.glowEffect
94
+ }), /*#__PURE__*/_jsxs(View, {
95
+ style: styles.content,
96
+ children: [/*#__PURE__*/_jsx(Text, {
97
+ style: styles.title,
98
+ children: title
99
+ }), /*#__PURE__*/_jsx(Text, {
100
+ style: styles.message,
101
+ children: message
102
+ }), /*#__PURE__*/_jsx(Pressable, {
103
+ onPress: onDismiss,
104
+ style: ({
105
+ pressed
106
+ }) => [styles.button, pressed && styles.buttonPressed],
107
+ children: /*#__PURE__*/_jsx(View, {
108
+ style: styles.buttonGradient,
109
+ children: /*#__PURE__*/_jsx(Text, {
110
+ style: styles.buttonText,
111
+ children: "Got it!"
112
+ })
113
+ })
114
+ })]
115
+ }), /*#__PURE__*/_jsx(Animated.View, {
116
+ style: [styles.arrowContainer, {
117
+ transform: [{
118
+ translateY: arrowBounceAnim
119
+ }]
120
+ }],
121
+ children: /*#__PURE__*/_jsx(View, {
122
+ style: styles.arrow
123
+ })
124
+ })]
125
+ })
126
+ })
127
+ });
128
+ };
129
+ const styles = StyleSheet.create({
130
+ container: {
131
+ ...StyleSheet.absoluteFillObject,
132
+ alignItems: "center",
133
+ justifyContent: "center",
134
+ pointerEvents: "box-none"
135
+ },
136
+ tooltipContainer: {
137
+ position: "absolute",
138
+ bottom: calculateTooltipPosition(),
139
+ alignItems: "center",
140
+ maxWidth: 280
141
+ },
142
+ tooltip: {
143
+ backgroundColor: dialColors.dialBackground,
144
+ borderRadius: 16,
145
+ borderWidth: 2,
146
+ borderColor: dialColors.dialBorder,
147
+ padding: 20,
148
+ shadowColor: buoyColors.primary,
149
+ shadowOffset: {
150
+ width: 0,
151
+ height: 0
152
+ },
153
+ shadowOpacity: 0.6,
154
+ shadowRadius: 20,
155
+ elevation: 10
156
+ },
157
+ glowEffect: {
158
+ position: "absolute",
159
+ top: -4,
160
+ left: -4,
161
+ right: -4,
162
+ bottom: -4,
163
+ borderRadius: 18,
164
+ backgroundColor: "#FFFFFF",
165
+ opacity: 0.15
166
+ },
167
+ content: {
168
+ alignItems: "center",
169
+ gap: 12
170
+ },
171
+ title: {
172
+ color: buoyColors.primary,
173
+ fontSize: 16,
174
+ fontWeight: "900",
175
+ fontFamily: "monospace",
176
+ letterSpacing: 1,
177
+ textAlign: "center",
178
+ textTransform: "uppercase",
179
+ textShadowColor: buoyColors.primary,
180
+ textShadowOffset: {
181
+ width: 0,
182
+ height: 0
183
+ },
184
+ textShadowRadius: 4
185
+ },
186
+ message: {
187
+ color: "#FFFFFF",
188
+ fontSize: 13,
189
+ lineHeight: 20,
190
+ textAlign: "center",
191
+ fontFamily: "monospace"
192
+ },
193
+ button: {
194
+ marginTop: 8,
195
+ borderRadius: 8,
196
+ overflow: "hidden",
197
+ borderWidth: 2,
198
+ borderColor: "#FFFFFF"
199
+ },
200
+ buttonPressed: {
201
+ opacity: 0.7,
202
+ transform: [{
203
+ scale: 0.96
204
+ }]
205
+ },
206
+ buttonGradient: {
207
+ backgroundColor: "rgba(255, 255, 255, 0.1)",
208
+ paddingHorizontal: 24,
209
+ paddingVertical: 10,
210
+ alignItems: "center"
211
+ },
212
+ buttonText: {
213
+ color: "#FFFFFF",
214
+ fontSize: 14,
215
+ fontWeight: "900",
216
+ fontFamily: "monospace",
217
+ letterSpacing: 1.5,
218
+ textTransform: "uppercase"
219
+ },
220
+ arrowContainer: {
221
+ position: "absolute",
222
+ bottom: ARROW_BOTTOM_OFFSET,
223
+ left: 0,
224
+ right: 0,
225
+ alignItems: "center"
226
+ },
227
+ arrow: {
228
+ width: 0,
229
+ height: 0,
230
+ borderLeftWidth: 12,
231
+ borderRightWidth: 12,
232
+ borderTopWidth: ARROW_HEIGHT,
233
+ borderLeftColor: "transparent",
234
+ borderRightColor: "transparent",
235
+ borderTopColor: buoyColors.primary,
236
+ shadowColor: buoyColors.primary,
237
+ shadowOffset: {
238
+ width: 0,
239
+ height: 0
240
+ },
241
+ shadowOpacity: 0.8,
242
+ shadowRadius: 10
243
+ }
244
+ });
@@ -0,0 +1,64 @@
1
+ "use strict";
2
+
3
+ import { Dimensions } from "react-native";
4
+
5
+ /**
6
+ * Shared constants for onboarding tooltip positioning
7
+ * These ensure the floating menu aligns perfectly under the tooltip arrow
8
+ * All positions are calculated dynamically based on screen size
9
+ */
10
+
11
+ // Arrow dimensions (relative positioning)
12
+ export const ARROW_BOTTOM_OFFSET = -40; // Arrow extends below tooltip
13
+ export const ARROW_HEIGHT = 20; // borderTopWidth of arrow
14
+ export const SPACING_GAP = 10; // Gap between arrow tip and target element
15
+
16
+ /**
17
+ * Calculate the center Y position of the screen
18
+ * This is used to vertically center the onboarding UI
19
+ *
20
+ * @returns Y coordinate at the center of the screen
21
+ */
22
+ export function getScreenCenterY() {
23
+ const {
24
+ height: screenHeight
25
+ } = Dimensions.get("window");
26
+ return screenHeight / 2;
27
+ }
28
+
29
+ /**
30
+ * Calculate the tooltip position to center it vertically on screen
31
+ * Uses flexbox-style centering - tooltip will center itself with its actual size
32
+ *
33
+ * @returns Distance from screen bottom for tooltip positioning
34
+ */
35
+ export function calculateTooltipPosition() {
36
+ // Position from center - tooltip will be centered with transform or flex
37
+ // We return a value that's slightly above center to account for the arrow below
38
+ const centerY = getScreenCenterY();
39
+
40
+ // Approximate offset to center the tooltip+arrow combo
41
+ // This is a reasonable estimate that works for most tooltip sizes
42
+ const estimatedHalfHeight = 130; // ~half of (tooltip + arrow)
43
+
44
+ return centerY - estimatedHalfHeight;
45
+ }
46
+
47
+ /**
48
+ * Calculate the position where a target element should be placed
49
+ * to align directly under the tooltip arrow
50
+ *
51
+ * @returns Distance from screen bottom where element should be positioned
52
+ */
53
+ export function calculateTargetPosition() {
54
+ const tooltipBottom = calculateTooltipPosition();
55
+
56
+ // Arrow tip position = tooltip bottom + arrow offset (arrow extends below, so negative)
57
+ const arrowTipFromBottom = tooltipBottom + ARROW_BOTTOM_OFFSET;
58
+
59
+ // Subtract arrow height to get to the actual tip
60
+ const actualArrowTip = arrowTipFromBottom - ARROW_HEIGHT;
61
+
62
+ // Subtract spacing gap to position element below arrow
63
+ return actualArrowTip - SPACING_GAP;
64
+ }