@buoy-gg/shared-ui 2.1.12 → 2.1.14
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.
- package/lib/commonjs/hooks/safe-area-impl.js +1 -1
- package/lib/commonjs/ui/components/DraggableHeader.js +147 -95
- package/lib/commonjs/ui/components/GripVerticalIcon.js +65 -0
- package/lib/commonjs/ui/components/WindowControls.js +3 -3
- package/lib/commonjs/ui/components/index.js +7 -0
- package/lib/commonjs/utils/persistentStorage.js +14 -2
- package/lib/module/hooks/safe-area-impl.js +1 -1
- package/lib/module/ui/components/DraggableHeader.js +148 -96
- package/lib/module/ui/components/GripVerticalIcon.js +61 -0
- package/lib/module/ui/components/WindowControls.js +5 -4
- package/lib/module/ui/components/index.js +1 -0
- package/lib/module/utils/persistentStorage.js +14 -2
- package/lib/typescript/commonjs/hooks/safe-area-impl.d.ts +1 -1
- package/lib/typescript/commonjs/ui/components/DraggableHeader.d.ts +25 -5
- package/lib/typescript/commonjs/ui/components/DraggableHeader.d.ts.map +1 -1
- package/lib/typescript/commonjs/ui/components/GripVerticalIcon.d.ts +14 -0
- package/lib/typescript/commonjs/ui/components/GripVerticalIcon.d.ts.map +1 -0
- package/lib/typescript/commonjs/ui/components/WindowControls.d.ts.map +1 -1
- package/lib/typescript/commonjs/ui/components/index.d.ts +1 -0
- package/lib/typescript/commonjs/ui/components/index.d.ts.map +1 -1
- package/lib/typescript/commonjs/utils/persistentStorage.d.ts.map +1 -1
- package/lib/typescript/module/hooks/safe-area-impl.d.ts +1 -1
- package/lib/typescript/module/ui/components/DraggableHeader.d.ts +25 -5
- package/lib/typescript/module/ui/components/DraggableHeader.d.ts.map +1 -1
- package/lib/typescript/module/ui/components/GripVerticalIcon.d.ts +14 -0
- package/lib/typescript/module/ui/components/GripVerticalIcon.d.ts.map +1 -0
- package/lib/typescript/module/ui/components/WindowControls.d.ts.map +1 -1
- package/lib/typescript/module/ui/components/index.d.ts +1 -0
- package/lib/typescript/module/ui/components/index.d.ts.map +1 -1
- package/lib/typescript/module/utils/persistentStorage.d.ts.map +1 -1
- package/package.json +4 -4
|
@@ -7,7 +7,7 @@ exports.useNativeSafeAreaInsets = exports.safeAreaType = exports.hasSafeAreaPack
|
|
|
7
7
|
/**
|
|
8
8
|
* Auto-generated safe area implementation
|
|
9
9
|
* Detected: none
|
|
10
|
-
* Generated at: 2026-
|
|
10
|
+
* Generated at: 2026-05-04T02:37:51.788Z
|
|
11
11
|
*
|
|
12
12
|
* DO NOT EDIT - This file is generated by scripts/detect-safe-area.js
|
|
13
13
|
*
|
|
@@ -8,10 +8,18 @@ var _react = require("react");
|
|
|
8
8
|
var _reactNative = require("react-native");
|
|
9
9
|
var _jsxRuntime = require("react/jsx-runtime");
|
|
10
10
|
/**
|
|
11
|
-
* DraggableHeader
|
|
11
|
+
* DraggableHeader — the canonical floating-tools drag handle.
|
|
12
12
|
*
|
|
13
|
-
*
|
|
14
|
-
*
|
|
13
|
+
* Used by FloatingDevTools, JsModal's floating mode, and the perf-monitor
|
|
14
|
+
* bubble. Tracks drag via relative `dx`/`dy` (so parent padding/margins
|
|
15
|
+
* don't affect motion), discriminates tap-vs-drag by total distance, and
|
|
16
|
+
* clamps the final position to the container bounds.
|
|
17
|
+
*
|
|
18
|
+
* IMPORTANT: the PanResponder is created exactly ONCE per mount. All
|
|
19
|
+
* volatile props (callbacks, bounds, sizing) flow through `propsRef` so
|
|
20
|
+
* a parent re-render mid-gesture does NOT re-create the responder. Re-
|
|
21
|
+
* creating it during a drag detaches the active gesture and snaps the
|
|
22
|
+
* element back — that bug burned us once already.
|
|
15
23
|
*/
|
|
16
24
|
const DraggableHeader = exports.DraggableHeader = /*#__PURE__*/(0, _react.memo)(function DraggableHeader({
|
|
17
25
|
children,
|
|
@@ -19,6 +27,8 @@ const DraggableHeader = exports.DraggableHeader = /*#__PURE__*/(0, _react.memo)(
|
|
|
19
27
|
onDragStart,
|
|
20
28
|
onDragEnd,
|
|
21
29
|
onTap,
|
|
30
|
+
onLongPress,
|
|
31
|
+
longPressDelay = 350,
|
|
22
32
|
containerBounds = _reactNative.Dimensions.get("window"),
|
|
23
33
|
elementSize = {
|
|
24
34
|
width: 100,
|
|
@@ -29,113 +39,155 @@ const DraggableHeader = exports.DraggableHeader = /*#__PURE__*/(0, _react.memo)(
|
|
|
29
39
|
y: 0
|
|
30
40
|
},
|
|
31
41
|
style,
|
|
32
|
-
enabled = true
|
|
42
|
+
enabled = true,
|
|
43
|
+
maxOverflowX = 0
|
|
33
44
|
}) {
|
|
34
45
|
const isDraggingRef = (0, _react.useRef)(false);
|
|
35
46
|
const dragDistanceRef = (0, _react.useRef)(0);
|
|
36
|
-
const
|
|
47
|
+
const startPositionRef = (0, _react.useRef)({
|
|
37
48
|
x: 0,
|
|
38
49
|
y: 0
|
|
39
50
|
});
|
|
40
|
-
const
|
|
41
|
-
|
|
42
|
-
onMoveShouldSetPanResponder: (_, g) => enabled && (Math.abs(g.dx) > 1 || Math.abs(g.dy) > 1),
|
|
43
|
-
onPanResponderTerminationRequest: () => false,
|
|
44
|
-
// Resist touch steal
|
|
45
|
-
|
|
46
|
-
onPanResponderGrant: evt => {
|
|
47
|
-
isDraggingRef.current = false; // Start as not dragging
|
|
48
|
-
dragDistanceRef.current = 0;
|
|
49
|
-
// Don't call onDragStart immediately - wait to see if it's actually a drag
|
|
51
|
+
const longPressTimerRef = (0, _react.useRef)(null);
|
|
52
|
+
const longPressFiredRef = (0, _react.useRef)(false);
|
|
50
53
|
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
54
|
+
// Clear any pending long-press timer if the component unmounts mid-press,
|
|
55
|
+
// so the timeout never fires after we're gone.
|
|
56
|
+
(0, _react.useEffect)(() => {
|
|
57
|
+
return () => {
|
|
58
|
+
if (longPressTimerRef.current != null) {
|
|
59
|
+
clearTimeout(longPressTimerRef.current);
|
|
60
|
+
longPressTimerRef.current = null;
|
|
61
|
+
}
|
|
62
|
+
};
|
|
63
|
+
}, []);
|
|
56
64
|
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
65
|
+
// Latest props in a ref. Keeps the PanResponder closure stable across
|
|
66
|
+
// re-renders so an active drag never gets its handlers swapped.
|
|
67
|
+
const propsRef = (0, _react.useRef)({
|
|
68
|
+
onDragStart,
|
|
69
|
+
onDragEnd,
|
|
70
|
+
onTap,
|
|
71
|
+
onLongPress,
|
|
72
|
+
longPressDelay,
|
|
73
|
+
containerBounds,
|
|
74
|
+
elementSize,
|
|
75
|
+
minPosition,
|
|
76
|
+
enabled,
|
|
77
|
+
maxOverflowX
|
|
78
|
+
});
|
|
79
|
+
propsRef.current = {
|
|
80
|
+
onDragStart,
|
|
81
|
+
onDragEnd,
|
|
82
|
+
onTap,
|
|
83
|
+
onLongPress,
|
|
84
|
+
longPressDelay,
|
|
85
|
+
containerBounds,
|
|
86
|
+
elementSize,
|
|
87
|
+
minPosition,
|
|
88
|
+
enabled,
|
|
89
|
+
maxOverflowX
|
|
90
|
+
};
|
|
91
|
+
const panResponder = (0, _react.useMemo)(() => {
|
|
92
|
+
const cancelLongPress = () => {
|
|
93
|
+
if (longPressTimerRef.current != null) {
|
|
94
|
+
clearTimeout(longPressTimerRef.current);
|
|
95
|
+
longPressTimerRef.current = null;
|
|
96
|
+
}
|
|
97
|
+
};
|
|
98
|
+
return _reactNative.PanResponder.create({
|
|
99
|
+
onStartShouldSetPanResponder: () => propsRef.current.enabled,
|
|
100
|
+
onMoveShouldSetPanResponder: (_, g) => propsRef.current.enabled && (Math.abs(g.dx) > 1 || Math.abs(g.dy) > 1),
|
|
101
|
+
onPanResponderTerminationRequest: () => false,
|
|
102
|
+
onPanResponderGrant: () => {
|
|
103
|
+
isDraggingRef.current = false;
|
|
104
|
+
dragDistanceRef.current = 0;
|
|
105
|
+
longPressFiredRef.current = false;
|
|
106
|
+
// Read position synchronously so the first onPanResponderMove
|
|
107
|
+
// has the correct startPosition. stopAnimation's callback can
|
|
108
|
+
// be async on iOS and races the first move event.
|
|
109
|
+
const sx = position.x.__getValue();
|
|
110
|
+
const sy = position.y.__getValue();
|
|
111
|
+
startPositionRef.current = {
|
|
112
|
+
x: sx,
|
|
113
|
+
y: sy
|
|
114
|
+
};
|
|
115
|
+
const {
|
|
116
|
+
onLongPress: lp,
|
|
117
|
+
longPressDelay: lpDelay
|
|
118
|
+
} = propsRef.current;
|
|
119
|
+
if (lp) {
|
|
120
|
+
longPressTimerRef.current = setTimeout(() => {
|
|
121
|
+
longPressTimerRef.current = null;
|
|
122
|
+
if (!isDraggingRef.current && dragDistanceRef.current <= 5) {
|
|
123
|
+
longPressFiredRef.current = true;
|
|
124
|
+
lp();
|
|
125
|
+
}
|
|
126
|
+
}, lpDelay);
|
|
127
|
+
}
|
|
128
|
+
},
|
|
129
|
+
onPanResponderMove: (_evt, gestureState) => {
|
|
130
|
+
const totalDistance = Math.abs(gestureState.dx) + Math.abs(gestureState.dy);
|
|
131
|
+
dragDistanceRef.current = totalDistance;
|
|
132
|
+
if (totalDistance > 5 && !isDraggingRef.current) {
|
|
133
|
+
isDraggingRef.current = true;
|
|
134
|
+
cancelLongPress();
|
|
135
|
+
propsRef.current.onDragStart?.();
|
|
136
|
+
}
|
|
137
|
+
// Use dx/dy relative movement so parent transforms don't affect
|
|
138
|
+
// the drag.
|
|
139
|
+
const x = startPositionRef.current.x + gestureState.dx;
|
|
140
|
+
const y = startPositionRef.current.y + gestureState.dy;
|
|
141
|
+
position.setValue({
|
|
64
142
|
x,
|
|
65
143
|
y
|
|
66
144
|
});
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
145
|
+
},
|
|
146
|
+
onPanResponderRelease: () => {
|
|
147
|
+
cancelLongPress();
|
|
148
|
+
const longPressed = longPressFiredRef.current;
|
|
149
|
+
longPressFiredRef.current = false;
|
|
150
|
+
const wasTap = dragDistanceRef.current <= 5 && !isDraggingRef.current;
|
|
151
|
+
if (wasTap) {
|
|
152
|
+
if (!longPressed) propsRef.current.onTap?.();
|
|
153
|
+
isDraggingRef.current = false;
|
|
154
|
+
return;
|
|
155
|
+
}
|
|
77
156
|
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
y: 0
|
|
92
|
-
});
|
|
93
|
-
position.setValue({
|
|
94
|
-
x,
|
|
95
|
-
y
|
|
96
|
-
});
|
|
97
|
-
},
|
|
98
|
-
onPanResponderRelease: () => {
|
|
99
|
-
// Get current position before any operations
|
|
100
|
-
const currentX = Number(JSON.stringify(position.x));
|
|
101
|
-
const currentY = Number(JSON.stringify(position.y));
|
|
102
|
-
|
|
103
|
-
// Check if it was a tap (minimal movement)
|
|
104
|
-
if (dragDistanceRef.current <= 5 && !isDraggingRef.current) {
|
|
105
|
-
// Reset position to current values without offset for tap
|
|
106
|
-
position.setOffset({
|
|
107
|
-
x: 0,
|
|
108
|
-
y: 0
|
|
109
|
-
});
|
|
157
|
+
// Read the final position synchronously and clamp.
|
|
158
|
+
const cx = position.x.__getValue();
|
|
159
|
+
const cy = position.y.__getValue();
|
|
160
|
+
const {
|
|
161
|
+
containerBounds: bounds,
|
|
162
|
+
elementSize: size,
|
|
163
|
+
minPosition: minPos,
|
|
164
|
+
maxOverflowX: maxOX,
|
|
165
|
+
onDragEnd: dragEnd
|
|
166
|
+
} = propsRef.current;
|
|
167
|
+
const maxX = bounds.width - size.width + maxOX;
|
|
168
|
+
const clampedX = Math.max(minPos.x, Math.min(cx, maxX));
|
|
169
|
+
const clampedY = Math.max(minPos.y, Math.min(cy, bounds.height - size.height));
|
|
110
170
|
position.setValue({
|
|
111
|
-
x:
|
|
112
|
-
y:
|
|
171
|
+
x: clampedX,
|
|
172
|
+
y: clampedY
|
|
173
|
+
});
|
|
174
|
+
dragEnd?.({
|
|
175
|
+
x: clampedX,
|
|
176
|
+
y: clampedY
|
|
113
177
|
});
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
178
|
+
isDraggingRef.current = false;
|
|
179
|
+
},
|
|
180
|
+
onPanResponderTerminate: () => {
|
|
181
|
+
cancelLongPress();
|
|
182
|
+
longPressFiredRef.current = false;
|
|
183
|
+
isDraggingRef.current = false;
|
|
117
184
|
}
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
position.setValue({
|
|
125
|
-
x: clampedX,
|
|
126
|
-
y: clampedY
|
|
127
|
-
});
|
|
128
|
-
onDragEnd?.({
|
|
129
|
-
x: clampedX,
|
|
130
|
-
y: clampedY
|
|
131
|
-
});
|
|
132
|
-
isDraggingRef.current = false;
|
|
133
|
-
},
|
|
134
|
-
onPanResponderTerminate: () => {
|
|
135
|
-
isDraggingRef.current = false;
|
|
136
|
-
// No need to flattenOffset since we're using absolute positioning
|
|
137
|
-
}
|
|
138
|
-
}), [enabled, position, onDragStart, onDragEnd, onTap, containerBounds, elementSize, minPosition]);
|
|
185
|
+
});
|
|
186
|
+
// The responder is stable for the component's lifetime — props are
|
|
187
|
+
// read from a ref. Position is the only Animated.Value reference and
|
|
188
|
+
// is itself stable (created via useRef in the parent hook).
|
|
189
|
+
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
190
|
+
}, [position]);
|
|
139
191
|
return /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.View, {
|
|
140
192
|
style: style,
|
|
141
193
|
...panResponder.panHandlers,
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, "__esModule", {
|
|
4
|
+
value: true
|
|
5
|
+
});
|
|
6
|
+
exports.GripVerticalIcon = GripVerticalIcon;
|
|
7
|
+
var _reactNative = require("react-native");
|
|
8
|
+
var _floatingToolsCore = require("@buoy-gg/floating-tools-core");
|
|
9
|
+
var _gameUIColors = require("../gameUI/constants/gameUIColors.js");
|
|
10
|
+
var _jsxRuntime = require("react/jsx-runtime");
|
|
11
|
+
/**
|
|
12
|
+
* Two columns of three dots — the standard "grabber" affordance used by
|
|
13
|
+
* floating bubbles in this suite (FloatingDevTools, perf-monitor HUD).
|
|
14
|
+
*
|
|
15
|
+
* Sizing comes from `getGripIconLayout` in `@buoy-gg/floating-tools-core`
|
|
16
|
+
* so all bubbles share identical proportions.
|
|
17
|
+
*/
|
|
18
|
+
function GripVerticalIcon({
|
|
19
|
+
size = 24,
|
|
20
|
+
color = _gameUIColors.buoyColors.textSecondary + "CC"
|
|
21
|
+
}) {
|
|
22
|
+
const layout = (0, _floatingToolsCore.getGripIconLayout)(size);
|
|
23
|
+
const containerStyle = {
|
|
24
|
+
width: size,
|
|
25
|
+
height: size,
|
|
26
|
+
flexDirection: "row",
|
|
27
|
+
alignItems: "center",
|
|
28
|
+
justifyContent: "center"
|
|
29
|
+
};
|
|
30
|
+
const columnStyle = {
|
|
31
|
+
flexDirection: "column",
|
|
32
|
+
alignItems: "center",
|
|
33
|
+
justifyContent: "center",
|
|
34
|
+
marginHorizontal: layout.columnGap / 2
|
|
35
|
+
};
|
|
36
|
+
const dotStyle = {
|
|
37
|
+
width: layout.dotSize,
|
|
38
|
+
height: layout.dotSize,
|
|
39
|
+
borderRadius: layout.dotSize / 2,
|
|
40
|
+
backgroundColor: color,
|
|
41
|
+
marginVertical: layout.rowGap / 2
|
|
42
|
+
};
|
|
43
|
+
return /*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNative.View, {
|
|
44
|
+
style: containerStyle,
|
|
45
|
+
children: [/*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNative.View, {
|
|
46
|
+
style: columnStyle,
|
|
47
|
+
children: [/*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.View, {
|
|
48
|
+
style: dotStyle
|
|
49
|
+
}), /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.View, {
|
|
50
|
+
style: dotStyle
|
|
51
|
+
}), /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.View, {
|
|
52
|
+
style: dotStyle
|
|
53
|
+
})]
|
|
54
|
+
}), /*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNative.View, {
|
|
55
|
+
style: columnStyle,
|
|
56
|
+
children: [/*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.View, {
|
|
57
|
+
style: dotStyle
|
|
58
|
+
}), /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.View, {
|
|
59
|
+
style: dotStyle
|
|
60
|
+
}), /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.View, {
|
|
61
|
+
style: dotStyle
|
|
62
|
+
})]
|
|
63
|
+
})]
|
|
64
|
+
});
|
|
65
|
+
}
|
|
@@ -8,11 +8,11 @@ exports.setExpandableWindowControls = setExpandableWindowControls;
|
|
|
8
8
|
var _react = require("react");
|
|
9
9
|
var _reactNative = require("react-native");
|
|
10
10
|
var _index = require("../../icons/index.js");
|
|
11
|
+
var _gameUIColors = require("../gameUI/constants/gameUIColors.js");
|
|
11
12
|
var _jsxRuntime = require("react/jsx-runtime");
|
|
12
13
|
// ============================================================================
|
|
13
14
|
// Global expandable setting — controlled via setExpandableWindowControls()
|
|
14
15
|
// ============================================================================
|
|
15
|
-
|
|
16
16
|
let _expandableEnabled = true; // Default ON
|
|
17
17
|
|
|
18
18
|
/**
|
|
@@ -345,12 +345,12 @@ const styles = _reactNative.StyleSheet.create({
|
|
|
345
345
|
flexDirection: "row",
|
|
346
346
|
alignItems: "center",
|
|
347
347
|
gap: EXPANDED_BUTTON_SPACING,
|
|
348
|
-
backgroundColor:
|
|
348
|
+
backgroundColor: _gameUIColors.buoyColors.card,
|
|
349
349
|
borderRadius: (EXPANDED_BUTTON_SIZE + EXPANDED_PADDING * 2) / 2,
|
|
350
350
|
paddingHorizontal: EXPANDED_PADDING,
|
|
351
351
|
paddingVertical: EXPANDED_PADDING,
|
|
352
352
|
borderWidth: 1,
|
|
353
|
-
borderColor:
|
|
353
|
+
borderColor: _gameUIColors.buoyColors.border,
|
|
354
354
|
shadowColor: "#000",
|
|
355
355
|
shadowOffset: {
|
|
356
356
|
width: 0,
|
|
@@ -177,6 +177,12 @@ Object.defineProperty(exports, "FilterSection", {
|
|
|
177
177
|
return _FilterComponents.FilterSection;
|
|
178
178
|
}
|
|
179
179
|
});
|
|
180
|
+
Object.defineProperty(exports, "GripVerticalIcon", {
|
|
181
|
+
enumerable: true,
|
|
182
|
+
get: function () {
|
|
183
|
+
return _GripVerticalIcon.GripVerticalIcon;
|
|
184
|
+
}
|
|
185
|
+
});
|
|
180
186
|
Object.defineProperty(exports, "HeaderSearchButton", {
|
|
181
187
|
enumerable: true,
|
|
182
188
|
get: function () {
|
|
@@ -356,6 +362,7 @@ var _StatusIndicator = require("./StatusIndicator.js");
|
|
|
356
362
|
var _TimeDisplay = require("./TimeDisplay.js");
|
|
357
363
|
var _DetailView = require("./DetailView.js");
|
|
358
364
|
var _DraggableHeader = require("./DraggableHeader.js");
|
|
365
|
+
var _GripVerticalIcon = require("./GripVerticalIcon.js");
|
|
359
366
|
var _CollapsibleSection = require("./CollapsibleSection.js");
|
|
360
367
|
var _DataInspector = require("./DataInspector.js");
|
|
361
368
|
var _SearchBar = require("./SearchBar.js");
|
|
@@ -51,10 +51,22 @@ function getStorageDir() {
|
|
|
51
51
|
if (!FileSystem?.documentDirectory) return null;
|
|
52
52
|
return `${FileSystem.documentDirectory}${STORAGE_DIR_NAME}/`;
|
|
53
53
|
}
|
|
54
|
+
|
|
55
|
+
// Android's expo-file-system resolves write paths as URIs and decodes %2F back
|
|
56
|
+
// to /, which turns slashed keys into non-existent subdirectories. Escape /
|
|
57
|
+
// before encodeURIComponent so the filename stays flat. JSON-Pointer-style
|
|
58
|
+
// escape is collision-free: ~ -> ~0, then / -> ~1. Decode reverses ~1 -> /
|
|
59
|
+
// before ~0 -> ~ so a key containing the literal "~1" round-trips correctly.
|
|
60
|
+
function encodeKeyForFs(key) {
|
|
61
|
+
return encodeURIComponent(key.replace(/~/g, "~0").replace(/\//g, "~1"));
|
|
62
|
+
}
|
|
63
|
+
function decodeKeyFromFs(encoded) {
|
|
64
|
+
return decodeURIComponent(encoded).replace(/~1/g, "/").replace(/~0/g, "~");
|
|
65
|
+
}
|
|
54
66
|
function getFilePath(key) {
|
|
55
67
|
const dir = getStorageDir();
|
|
56
68
|
if (!dir) return null;
|
|
57
|
-
return `${dir}${
|
|
69
|
+
return `${dir}${encodeKeyForFs(key)}.json`;
|
|
58
70
|
}
|
|
59
71
|
|
|
60
72
|
/**
|
|
@@ -244,7 +256,7 @@ const fileSystemStorage = {
|
|
|
244
256
|
const dirInfo = await fs.getInfoAsync(storageDir);
|
|
245
257
|
if (!dirInfo.exists) return [];
|
|
246
258
|
const files = await fs.readDirectoryAsync(storageDir);
|
|
247
|
-
return files.filter(f => f.endsWith(".json")).map(f =>
|
|
259
|
+
return files.filter(f => f.endsWith(".json")).map(f => decodeKeyFromFs(f.replace(".json", "")));
|
|
248
260
|
} catch {
|
|
249
261
|
return [];
|
|
250
262
|
}
|
|
@@ -1,13 +1,21 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
|
|
3
|
-
import { useRef, useMemo, memo } from "react";
|
|
3
|
+
import { useRef, useMemo, useEffect, memo } from "react";
|
|
4
4
|
import { View, PanResponder, Dimensions } from "react-native";
|
|
5
5
|
import { jsx as _jsx } from "react/jsx-runtime";
|
|
6
6
|
/**
|
|
7
|
-
* DraggableHeader
|
|
7
|
+
* DraggableHeader — the canonical floating-tools drag handle.
|
|
8
8
|
*
|
|
9
|
-
*
|
|
10
|
-
*
|
|
9
|
+
* Used by FloatingDevTools, JsModal's floating mode, and the perf-monitor
|
|
10
|
+
* bubble. Tracks drag via relative `dx`/`dy` (so parent padding/margins
|
|
11
|
+
* don't affect motion), discriminates tap-vs-drag by total distance, and
|
|
12
|
+
* clamps the final position to the container bounds.
|
|
13
|
+
*
|
|
14
|
+
* IMPORTANT: the PanResponder is created exactly ONCE per mount. All
|
|
15
|
+
* volatile props (callbacks, bounds, sizing) flow through `propsRef` so
|
|
16
|
+
* a parent re-render mid-gesture does NOT re-create the responder. Re-
|
|
17
|
+
* creating it during a drag detaches the active gesture and snaps the
|
|
18
|
+
* element back — that bug burned us once already.
|
|
11
19
|
*/
|
|
12
20
|
export const DraggableHeader = /*#__PURE__*/memo(function DraggableHeader({
|
|
13
21
|
children,
|
|
@@ -15,6 +23,8 @@ export const DraggableHeader = /*#__PURE__*/memo(function DraggableHeader({
|
|
|
15
23
|
onDragStart,
|
|
16
24
|
onDragEnd,
|
|
17
25
|
onTap,
|
|
26
|
+
onLongPress,
|
|
27
|
+
longPressDelay = 350,
|
|
18
28
|
containerBounds = Dimensions.get("window"),
|
|
19
29
|
elementSize = {
|
|
20
30
|
width: 100,
|
|
@@ -25,113 +35,155 @@ export const DraggableHeader = /*#__PURE__*/memo(function DraggableHeader({
|
|
|
25
35
|
y: 0
|
|
26
36
|
},
|
|
27
37
|
style,
|
|
28
|
-
enabled = true
|
|
38
|
+
enabled = true,
|
|
39
|
+
maxOverflowX = 0
|
|
29
40
|
}) {
|
|
30
41
|
const isDraggingRef = useRef(false);
|
|
31
42
|
const dragDistanceRef = useRef(0);
|
|
32
|
-
const
|
|
43
|
+
const startPositionRef = useRef({
|
|
33
44
|
x: 0,
|
|
34
45
|
y: 0
|
|
35
46
|
});
|
|
36
|
-
const
|
|
37
|
-
|
|
38
|
-
onMoveShouldSetPanResponder: (_, g) => enabled && (Math.abs(g.dx) > 1 || Math.abs(g.dy) > 1),
|
|
39
|
-
onPanResponderTerminationRequest: () => false,
|
|
40
|
-
// Resist touch steal
|
|
41
|
-
|
|
42
|
-
onPanResponderGrant: evt => {
|
|
43
|
-
isDraggingRef.current = false; // Start as not dragging
|
|
44
|
-
dragDistanceRef.current = 0;
|
|
45
|
-
// Don't call onDragStart immediately - wait to see if it's actually a drag
|
|
47
|
+
const longPressTimerRef = useRef(null);
|
|
48
|
+
const longPressFiredRef = useRef(false);
|
|
46
49
|
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
50
|
+
// Clear any pending long-press timer if the component unmounts mid-press,
|
|
51
|
+
// so the timeout never fires after we're gone.
|
|
52
|
+
useEffect(() => {
|
|
53
|
+
return () => {
|
|
54
|
+
if (longPressTimerRef.current != null) {
|
|
55
|
+
clearTimeout(longPressTimerRef.current);
|
|
56
|
+
longPressTimerRef.current = null;
|
|
57
|
+
}
|
|
58
|
+
};
|
|
59
|
+
}, []);
|
|
52
60
|
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
61
|
+
// Latest props in a ref. Keeps the PanResponder closure stable across
|
|
62
|
+
// re-renders so an active drag never gets its handlers swapped.
|
|
63
|
+
const propsRef = useRef({
|
|
64
|
+
onDragStart,
|
|
65
|
+
onDragEnd,
|
|
66
|
+
onTap,
|
|
67
|
+
onLongPress,
|
|
68
|
+
longPressDelay,
|
|
69
|
+
containerBounds,
|
|
70
|
+
elementSize,
|
|
71
|
+
minPosition,
|
|
72
|
+
enabled,
|
|
73
|
+
maxOverflowX
|
|
74
|
+
});
|
|
75
|
+
propsRef.current = {
|
|
76
|
+
onDragStart,
|
|
77
|
+
onDragEnd,
|
|
78
|
+
onTap,
|
|
79
|
+
onLongPress,
|
|
80
|
+
longPressDelay,
|
|
81
|
+
containerBounds,
|
|
82
|
+
elementSize,
|
|
83
|
+
minPosition,
|
|
84
|
+
enabled,
|
|
85
|
+
maxOverflowX
|
|
86
|
+
};
|
|
87
|
+
const panResponder = useMemo(() => {
|
|
88
|
+
const cancelLongPress = () => {
|
|
89
|
+
if (longPressTimerRef.current != null) {
|
|
90
|
+
clearTimeout(longPressTimerRef.current);
|
|
91
|
+
longPressTimerRef.current = null;
|
|
92
|
+
}
|
|
93
|
+
};
|
|
94
|
+
return PanResponder.create({
|
|
95
|
+
onStartShouldSetPanResponder: () => propsRef.current.enabled,
|
|
96
|
+
onMoveShouldSetPanResponder: (_, g) => propsRef.current.enabled && (Math.abs(g.dx) > 1 || Math.abs(g.dy) > 1),
|
|
97
|
+
onPanResponderTerminationRequest: () => false,
|
|
98
|
+
onPanResponderGrant: () => {
|
|
99
|
+
isDraggingRef.current = false;
|
|
100
|
+
dragDistanceRef.current = 0;
|
|
101
|
+
longPressFiredRef.current = false;
|
|
102
|
+
// Read position synchronously so the first onPanResponderMove
|
|
103
|
+
// has the correct startPosition. stopAnimation's callback can
|
|
104
|
+
// be async on iOS and races the first move event.
|
|
105
|
+
const sx = position.x.__getValue();
|
|
106
|
+
const sy = position.y.__getValue();
|
|
107
|
+
startPositionRef.current = {
|
|
108
|
+
x: sx,
|
|
109
|
+
y: sy
|
|
110
|
+
};
|
|
111
|
+
const {
|
|
112
|
+
onLongPress: lp,
|
|
113
|
+
longPressDelay: lpDelay
|
|
114
|
+
} = propsRef.current;
|
|
115
|
+
if (lp) {
|
|
116
|
+
longPressTimerRef.current = setTimeout(() => {
|
|
117
|
+
longPressTimerRef.current = null;
|
|
118
|
+
if (!isDraggingRef.current && dragDistanceRef.current <= 5) {
|
|
119
|
+
longPressFiredRef.current = true;
|
|
120
|
+
lp();
|
|
121
|
+
}
|
|
122
|
+
}, lpDelay);
|
|
123
|
+
}
|
|
124
|
+
},
|
|
125
|
+
onPanResponderMove: (_evt, gestureState) => {
|
|
126
|
+
const totalDistance = Math.abs(gestureState.dx) + Math.abs(gestureState.dy);
|
|
127
|
+
dragDistanceRef.current = totalDistance;
|
|
128
|
+
if (totalDistance > 5 && !isDraggingRef.current) {
|
|
129
|
+
isDraggingRef.current = true;
|
|
130
|
+
cancelLongPress();
|
|
131
|
+
propsRef.current.onDragStart?.();
|
|
132
|
+
}
|
|
133
|
+
// Use dx/dy relative movement so parent transforms don't affect
|
|
134
|
+
// the drag.
|
|
135
|
+
const x = startPositionRef.current.x + gestureState.dx;
|
|
136
|
+
const y = startPositionRef.current.y + gestureState.dy;
|
|
137
|
+
position.setValue({
|
|
60
138
|
x,
|
|
61
139
|
y
|
|
62
140
|
});
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
141
|
+
},
|
|
142
|
+
onPanResponderRelease: () => {
|
|
143
|
+
cancelLongPress();
|
|
144
|
+
const longPressed = longPressFiredRef.current;
|
|
145
|
+
longPressFiredRef.current = false;
|
|
146
|
+
const wasTap = dragDistanceRef.current <= 5 && !isDraggingRef.current;
|
|
147
|
+
if (wasTap) {
|
|
148
|
+
if (!longPressed) propsRef.current.onTap?.();
|
|
149
|
+
isDraggingRef.current = false;
|
|
150
|
+
return;
|
|
151
|
+
}
|
|
73
152
|
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
y: 0
|
|
88
|
-
});
|
|
89
|
-
position.setValue({
|
|
90
|
-
x,
|
|
91
|
-
y
|
|
92
|
-
});
|
|
93
|
-
},
|
|
94
|
-
onPanResponderRelease: () => {
|
|
95
|
-
// Get current position before any operations
|
|
96
|
-
const currentX = Number(JSON.stringify(position.x));
|
|
97
|
-
const currentY = Number(JSON.stringify(position.y));
|
|
98
|
-
|
|
99
|
-
// Check if it was a tap (minimal movement)
|
|
100
|
-
if (dragDistanceRef.current <= 5 && !isDraggingRef.current) {
|
|
101
|
-
// Reset position to current values without offset for tap
|
|
102
|
-
position.setOffset({
|
|
103
|
-
x: 0,
|
|
104
|
-
y: 0
|
|
105
|
-
});
|
|
153
|
+
// Read the final position synchronously and clamp.
|
|
154
|
+
const cx = position.x.__getValue();
|
|
155
|
+
const cy = position.y.__getValue();
|
|
156
|
+
const {
|
|
157
|
+
containerBounds: bounds,
|
|
158
|
+
elementSize: size,
|
|
159
|
+
minPosition: minPos,
|
|
160
|
+
maxOverflowX: maxOX,
|
|
161
|
+
onDragEnd: dragEnd
|
|
162
|
+
} = propsRef.current;
|
|
163
|
+
const maxX = bounds.width - size.width + maxOX;
|
|
164
|
+
const clampedX = Math.max(minPos.x, Math.min(cx, maxX));
|
|
165
|
+
const clampedY = Math.max(minPos.y, Math.min(cy, bounds.height - size.height));
|
|
106
166
|
position.setValue({
|
|
107
|
-
x:
|
|
108
|
-
y:
|
|
167
|
+
x: clampedX,
|
|
168
|
+
y: clampedY
|
|
169
|
+
});
|
|
170
|
+
dragEnd?.({
|
|
171
|
+
x: clampedX,
|
|
172
|
+
y: clampedY
|
|
109
173
|
});
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
174
|
+
isDraggingRef.current = false;
|
|
175
|
+
},
|
|
176
|
+
onPanResponderTerminate: () => {
|
|
177
|
+
cancelLongPress();
|
|
178
|
+
longPressFiredRef.current = false;
|
|
179
|
+
isDraggingRef.current = false;
|
|
113
180
|
}
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
position.setValue({
|
|
121
|
-
x: clampedX,
|
|
122
|
-
y: clampedY
|
|
123
|
-
});
|
|
124
|
-
onDragEnd?.({
|
|
125
|
-
x: clampedX,
|
|
126
|
-
y: clampedY
|
|
127
|
-
});
|
|
128
|
-
isDraggingRef.current = false;
|
|
129
|
-
},
|
|
130
|
-
onPanResponderTerminate: () => {
|
|
131
|
-
isDraggingRef.current = false;
|
|
132
|
-
// No need to flattenOffset since we're using absolute positioning
|
|
133
|
-
}
|
|
134
|
-
}), [enabled, position, onDragStart, onDragEnd, onTap, containerBounds, elementSize, minPosition]);
|
|
181
|
+
});
|
|
182
|
+
// The responder is stable for the component's lifetime — props are
|
|
183
|
+
// read from a ref. Position is the only Animated.Value reference and
|
|
184
|
+
// is itself stable (created via useRef in the parent hook).
|
|
185
|
+
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
186
|
+
}, [position]);
|
|
135
187
|
return /*#__PURE__*/_jsx(View, {
|
|
136
188
|
style: style,
|
|
137
189
|
...panResponder.panHandlers,
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
import { View } from "react-native";
|
|
4
|
+
import { getGripIconLayout } from "@buoy-gg/floating-tools-core";
|
|
5
|
+
import { buoyColors } from "../gameUI/constants/gameUIColors.js";
|
|
6
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
7
|
+
/**
|
|
8
|
+
* Two columns of three dots — the standard "grabber" affordance used by
|
|
9
|
+
* floating bubbles in this suite (FloatingDevTools, perf-monitor HUD).
|
|
10
|
+
*
|
|
11
|
+
* Sizing comes from `getGripIconLayout` in `@buoy-gg/floating-tools-core`
|
|
12
|
+
* so all bubbles share identical proportions.
|
|
13
|
+
*/
|
|
14
|
+
export function GripVerticalIcon({
|
|
15
|
+
size = 24,
|
|
16
|
+
color = buoyColors.textSecondary + "CC"
|
|
17
|
+
}) {
|
|
18
|
+
const layout = getGripIconLayout(size);
|
|
19
|
+
const containerStyle = {
|
|
20
|
+
width: size,
|
|
21
|
+
height: size,
|
|
22
|
+
flexDirection: "row",
|
|
23
|
+
alignItems: "center",
|
|
24
|
+
justifyContent: "center"
|
|
25
|
+
};
|
|
26
|
+
const columnStyle = {
|
|
27
|
+
flexDirection: "column",
|
|
28
|
+
alignItems: "center",
|
|
29
|
+
justifyContent: "center",
|
|
30
|
+
marginHorizontal: layout.columnGap / 2
|
|
31
|
+
};
|
|
32
|
+
const dotStyle = {
|
|
33
|
+
width: layout.dotSize,
|
|
34
|
+
height: layout.dotSize,
|
|
35
|
+
borderRadius: layout.dotSize / 2,
|
|
36
|
+
backgroundColor: color,
|
|
37
|
+
marginVertical: layout.rowGap / 2
|
|
38
|
+
};
|
|
39
|
+
return /*#__PURE__*/_jsxs(View, {
|
|
40
|
+
style: containerStyle,
|
|
41
|
+
children: [/*#__PURE__*/_jsxs(View, {
|
|
42
|
+
style: columnStyle,
|
|
43
|
+
children: [/*#__PURE__*/_jsx(View, {
|
|
44
|
+
style: dotStyle
|
|
45
|
+
}), /*#__PURE__*/_jsx(View, {
|
|
46
|
+
style: dotStyle
|
|
47
|
+
}), /*#__PURE__*/_jsx(View, {
|
|
48
|
+
style: dotStyle
|
|
49
|
+
})]
|
|
50
|
+
}), /*#__PURE__*/_jsxs(View, {
|
|
51
|
+
style: columnStyle,
|
|
52
|
+
children: [/*#__PURE__*/_jsx(View, {
|
|
53
|
+
style: dotStyle
|
|
54
|
+
}), /*#__PURE__*/_jsx(View, {
|
|
55
|
+
style: dotStyle
|
|
56
|
+
}), /*#__PURE__*/_jsx(View, {
|
|
57
|
+
style: dotStyle
|
|
58
|
+
})]
|
|
59
|
+
})]
|
|
60
|
+
});
|
|
61
|
+
}
|
|
@@ -3,11 +3,12 @@
|
|
|
3
3
|
import { useState, useRef, useCallback, useEffect } from "react";
|
|
4
4
|
import { View, TouchableOpacity, TouchableWithoutFeedback, StyleSheet, Animated, Modal } from "react-native";
|
|
5
5
|
import { X, Minus, DockBottom, FloatWindow } from "../../icons/index.js";
|
|
6
|
-
import {
|
|
6
|
+
import { buoyColors } from "../gameUI/constants/gameUIColors.js";
|
|
7
|
+
|
|
7
8
|
// ============================================================================
|
|
8
9
|
// Global expandable setting — controlled via setExpandableWindowControls()
|
|
9
10
|
// ============================================================================
|
|
10
|
-
|
|
11
|
+
import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
|
|
11
12
|
let _expandableEnabled = true; // Default ON
|
|
12
13
|
|
|
13
14
|
/**
|
|
@@ -340,12 +341,12 @@ const styles = StyleSheet.create({
|
|
|
340
341
|
flexDirection: "row",
|
|
341
342
|
alignItems: "center",
|
|
342
343
|
gap: EXPANDED_BUTTON_SPACING,
|
|
343
|
-
backgroundColor:
|
|
344
|
+
backgroundColor: buoyColors.card,
|
|
344
345
|
borderRadius: (EXPANDED_BUTTON_SIZE + EXPANDED_PADDING * 2) / 2,
|
|
345
346
|
paddingHorizontal: EXPANDED_PADDING,
|
|
346
347
|
paddingVertical: EXPANDED_PADDING,
|
|
347
348
|
borderWidth: 1,
|
|
348
|
-
borderColor:
|
|
349
|
+
borderColor: buoyColors.border,
|
|
349
350
|
shadowColor: "#000",
|
|
350
351
|
shadowOffset: {
|
|
351
352
|
width: 0,
|
|
@@ -23,6 +23,7 @@ export { StatusIndicator } from "./StatusIndicator.js";
|
|
|
23
23
|
export { TimeDisplay } from "./TimeDisplay.js";
|
|
24
24
|
export { DetailView } from "./DetailView.js";
|
|
25
25
|
export { DraggableHeader } from "./DraggableHeader.js";
|
|
26
|
+
export { GripVerticalIcon } from "./GripVerticalIcon.js";
|
|
26
27
|
export { CollapsibleSection } from "./CollapsibleSection.js";
|
|
27
28
|
export { DataInspector } from "./DataInspector.js";
|
|
28
29
|
export { SearchBar } from "./SearchBar.js";
|
|
@@ -45,10 +45,22 @@ function getStorageDir() {
|
|
|
45
45
|
if (!FileSystem?.documentDirectory) return null;
|
|
46
46
|
return `${FileSystem.documentDirectory}${STORAGE_DIR_NAME}/`;
|
|
47
47
|
}
|
|
48
|
+
|
|
49
|
+
// Android's expo-file-system resolves write paths as URIs and decodes %2F back
|
|
50
|
+
// to /, which turns slashed keys into non-existent subdirectories. Escape /
|
|
51
|
+
// before encodeURIComponent so the filename stays flat. JSON-Pointer-style
|
|
52
|
+
// escape is collision-free: ~ -> ~0, then / -> ~1. Decode reverses ~1 -> /
|
|
53
|
+
// before ~0 -> ~ so a key containing the literal "~1" round-trips correctly.
|
|
54
|
+
function encodeKeyForFs(key) {
|
|
55
|
+
return encodeURIComponent(key.replace(/~/g, "~0").replace(/\//g, "~1"));
|
|
56
|
+
}
|
|
57
|
+
function decodeKeyFromFs(encoded) {
|
|
58
|
+
return decodeURIComponent(encoded).replace(/~1/g, "/").replace(/~0/g, "~");
|
|
59
|
+
}
|
|
48
60
|
function getFilePath(key) {
|
|
49
61
|
const dir = getStorageDir();
|
|
50
62
|
if (!dir) return null;
|
|
51
|
-
return `${dir}${
|
|
63
|
+
return `${dir}${encodeKeyForFs(key)}.json`;
|
|
52
64
|
}
|
|
53
65
|
|
|
54
66
|
/**
|
|
@@ -238,7 +250,7 @@ const fileSystemStorage = {
|
|
|
238
250
|
const dirInfo = await fs.getInfoAsync(storageDir);
|
|
239
251
|
if (!dirInfo.exists) return [];
|
|
240
252
|
const files = await fs.readDirectoryAsync(storageDir);
|
|
241
|
-
return files.filter(f => f.endsWith(".json")).map(f =>
|
|
253
|
+
return files.filter(f => f.endsWith(".json")).map(f => decodeKeyFromFs(f.replace(".json", "")));
|
|
242
254
|
} catch {
|
|
243
255
|
return [];
|
|
244
256
|
}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { ReactNode } from "react";
|
|
2
|
-
import { Animated, ViewStyle, StyleProp } from "react-native";
|
|
1
|
+
import { type ReactNode } from "react";
|
|
2
|
+
import { Animated, type ViewStyle, type StyleProp } from "react-native";
|
|
3
3
|
interface DraggableHeaderProps {
|
|
4
4
|
children: ReactNode;
|
|
5
5
|
position: Animated.ValueXY;
|
|
@@ -9,6 +9,12 @@ interface DraggableHeaderProps {
|
|
|
9
9
|
y: number;
|
|
10
10
|
}) => void;
|
|
11
11
|
onTap?: () => void;
|
|
12
|
+
/**
|
|
13
|
+
* Fired when the user holds the surface without moving for
|
|
14
|
+
* `longPressDelay` ms. Cancelled by any drag motion.
|
|
15
|
+
*/
|
|
16
|
+
onLongPress?: () => void;
|
|
17
|
+
longPressDelay?: number;
|
|
12
18
|
containerBounds?: {
|
|
13
19
|
width: number;
|
|
14
20
|
height: number;
|
|
@@ -23,12 +29,26 @@ interface DraggableHeaderProps {
|
|
|
23
29
|
};
|
|
24
30
|
style?: StyleProp<ViewStyle>;
|
|
25
31
|
enabled?: boolean;
|
|
32
|
+
/**
|
|
33
|
+
* Allow the element to drift past the right edge by this many pixels.
|
|
34
|
+
* Used to support drag-past-edge "hide" gestures where the bubble can
|
|
35
|
+
* sit mostly off-screen with only a peek visible.
|
|
36
|
+
*/
|
|
37
|
+
maxOverflowX?: number;
|
|
26
38
|
}
|
|
27
39
|
/**
|
|
28
|
-
* DraggableHeader
|
|
40
|
+
* DraggableHeader — the canonical floating-tools drag handle.
|
|
29
41
|
*
|
|
30
|
-
*
|
|
31
|
-
*
|
|
42
|
+
* Used by FloatingDevTools, JsModal's floating mode, and the perf-monitor
|
|
43
|
+
* bubble. Tracks drag via relative `dx`/`dy` (so parent padding/margins
|
|
44
|
+
* don't affect motion), discriminates tap-vs-drag by total distance, and
|
|
45
|
+
* clamps the final position to the container bounds.
|
|
46
|
+
*
|
|
47
|
+
* IMPORTANT: the PanResponder is created exactly ONCE per mount. All
|
|
48
|
+
* volatile props (callbacks, bounds, sizing) flow through `propsRef` so
|
|
49
|
+
* a parent re-render mid-gesture does NOT re-create the responder. Re-
|
|
50
|
+
* creating it during a drag detaches the active gesture and snaps the
|
|
51
|
+
* element back — that bug burned us once already.
|
|
32
52
|
*/
|
|
33
53
|
export declare const DraggableHeader: import("react").NamedExoticComponent<DraggableHeaderProps>;
|
|
34
54
|
export {};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"DraggableHeader.d.ts","sourceRoot":"","sources":["../../../../../src/ui/components/DraggableHeader.tsx"],"names":[],"mappings":"AAAA,OAAO,
|
|
1
|
+
{"version":3,"file":"DraggableHeader.d.ts","sourceRoot":"","sources":["../../../../../src/ui/components/DraggableHeader.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAoC,KAAK,SAAS,EAAE,MAAM,OAAO,CAAC;AACzE,OAAO,EAGL,QAAQ,EAER,KAAK,SAAS,EACd,KAAK,SAAS,EACf,MAAM,cAAc,CAAC;AAEtB,UAAU,oBAAoB;IAC5B,QAAQ,EAAE,SAAS,CAAC;IACpB,QAAQ,EAAE,QAAQ,CAAC,OAAO,CAAC;IAC3B,WAAW,CAAC,EAAE,MAAM,IAAI,CAAC;IACzB,SAAS,CAAC,EAAE,CAAC,aAAa,EAAE;QAAE,CAAC,EAAE,MAAM,CAAC;QAAC,CAAC,EAAE,MAAM,CAAA;KAAE,KAAK,IAAI,CAAC;IAC9D,KAAK,CAAC,EAAE,MAAM,IAAI,CAAC;IACnB;;;OAGG;IACH,WAAW,CAAC,EAAE,MAAM,IAAI,CAAC;IACzB,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,eAAe,CAAC,EAAE;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAE,CAAC;IACpD,WAAW,CAAC,EAAE;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAE,CAAC;IAChD,WAAW,CAAC,EAAE;QAAE,CAAC,EAAE,MAAM,CAAC;QAAC,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC;IACvC,KAAK,CAAC,EAAE,SAAS,CAAC,SAAS,CAAC,CAAC;IAC7B,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB;;;;OAIG;IACH,YAAY,CAAC,EAAE,MAAM,CAAC;CACvB;AAED;;;;;;;;;;;;;GAaG;AACH,eAAO,MAAM,eAAe,4DA0K1B,CAAC"}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
interface GripVerticalIconProps {
|
|
2
|
+
size?: number;
|
|
3
|
+
color?: string;
|
|
4
|
+
}
|
|
5
|
+
/**
|
|
6
|
+
* Two columns of three dots — the standard "grabber" affordance used by
|
|
7
|
+
* floating bubbles in this suite (FloatingDevTools, perf-monitor HUD).
|
|
8
|
+
*
|
|
9
|
+
* Sizing comes from `getGripIconLayout` in `@buoy-gg/floating-tools-core`
|
|
10
|
+
* so all bubbles share identical proportions.
|
|
11
|
+
*/
|
|
12
|
+
export declare function GripVerticalIcon({ size, color, }: GripVerticalIconProps): import("react").JSX.Element;
|
|
13
|
+
export {};
|
|
14
|
+
//# sourceMappingURL=GripVerticalIcon.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"GripVerticalIcon.d.ts","sourceRoot":"","sources":["../../../../../src/ui/components/GripVerticalIcon.tsx"],"names":[],"mappings":"AAIA,UAAU,qBAAqB;IAC7B,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED;;;;;;GAMG;AACH,wBAAgB,gBAAgB,CAAC,EAC/B,IAAS,EACT,KAAuC,GACxC,EAAE,qBAAqB,+BAwCvB"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"WindowControls.d.ts","sourceRoot":"","sources":["../../../../../src/ui/components/WindowControls.tsx"],"names":[],"mappings":"AAUA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,eAAe,CAAC;
|
|
1
|
+
{"version":3,"file":"WindowControls.d.ts","sourceRoot":"","sources":["../../../../../src/ui/components/WindowControls.tsx"],"names":[],"mappings":"AAUA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,eAAe,CAAC;AAS/C;;;GAGG;AACH,wBAAgB,2BAA2B,CAAC,OAAO,EAAE,OAAO,QAE3D;AAMD,UAAU,mBAAmB;IAC3B,+BAA+B;IAC/B,OAAO,EAAE,MAAM,IAAI,CAAC;IACpB,4EAA4E;IAC5E,UAAU,CAAC,EAAE,MAAM,IAAI,CAAC;IACxB,sFAAsF;IACtF,YAAY,CAAC,EAAE,MAAM,IAAI,CAAC;IAC1B,2EAA2E;IAC3E,IAAI,CAAC,EAAE,SAAS,CAAC;CAClB;AA+BD;;;;GAIG;AACH,wBAAgB,cAAc,CAAC,EAC7B,OAAO,EACP,UAAU,EACV,YAAY,EACZ,IAAI,GACL,EAAE,mBAAmB,+BAoDrB"}
|
|
@@ -23,6 +23,7 @@ export { StatusIndicator } from "./StatusIndicator";
|
|
|
23
23
|
export { TimeDisplay } from "./TimeDisplay";
|
|
24
24
|
export { DetailView } from "./DetailView";
|
|
25
25
|
export { DraggableHeader } from "./DraggableHeader";
|
|
26
|
+
export { GripVerticalIcon } from "./GripVerticalIcon";
|
|
26
27
|
export { CollapsibleSection } from "./CollapsibleSection";
|
|
27
28
|
export { DataInspector } from "./DataInspector";
|
|
28
29
|
export { SearchBar } from "./SearchBar";
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../../src/ui/components/index.ts"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../../src/ui/components/index.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"persistentStorage.d.ts","sourceRoot":"","sources":["../../../../src/utils/persistentStorage.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AA2CH,MAAM,WAAW,eAAe;IAC9B,OAAO,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAAC;IAC7C,OAAO,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IACnD,UAAU,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IACvC,UAAU,IAAI,OAAO,CAAC,MAAM,EAAE,CAAC,CAAC;IAChC,QAAQ,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC,EAAE,CAAC,CAAC;IAC7D,WAAW,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAC3C,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;CACxB;AAGD,KAAK,cAAc,GAAG,YAAY,GAAG,cAAc,GAAG,cAAc,GAAG,QAAQ,CAAC;
|
|
1
|
+
{"version":3,"file":"persistentStorage.d.ts","sourceRoot":"","sources":["../../../../src/utils/persistentStorage.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AA2CH,MAAM,WAAW,eAAe;IAC9B,OAAO,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAAC;IAC7C,OAAO,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IACnD,UAAU,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IACvC,UAAU,IAAI,OAAO,CAAC,MAAM,EAAE,CAAC,CAAC;IAChC,QAAQ,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC,EAAE,CAAC,CAAC;IAC7D,WAAW,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAC3C,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;CACxB;AAGD,KAAK,cAAc,GAAG,YAAY,GAAG,cAAc,GAAG,cAAc,GAAG,QAAQ,CAAC;AAgkBhF;;;;;;;GAOG;AACH,eAAO,MAAM,iBAAiB,EAAE,eAmC/B,CAAC;AAEF;;GAEG;AACH,wBAAsB,wBAAwB,IAAI,OAAO,CAAC,OAAO,CAAC,CAGjE;AAED;;GAEG;AACH,wBAAsB,qBAAqB,IAAI,OAAO,CAAC,cAAc,CAAC,CAGrE;AAED;;GAEG;AACH,wBAAgB,gBAAgB,IAAI,IAAI,CAIvC"}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { ReactNode } from "react";
|
|
2
|
-
import { Animated, ViewStyle, StyleProp } from "react-native";
|
|
1
|
+
import { type ReactNode } from "react";
|
|
2
|
+
import { Animated, type ViewStyle, type StyleProp } from "react-native";
|
|
3
3
|
interface DraggableHeaderProps {
|
|
4
4
|
children: ReactNode;
|
|
5
5
|
position: Animated.ValueXY;
|
|
@@ -9,6 +9,12 @@ interface DraggableHeaderProps {
|
|
|
9
9
|
y: number;
|
|
10
10
|
}) => void;
|
|
11
11
|
onTap?: () => void;
|
|
12
|
+
/**
|
|
13
|
+
* Fired when the user holds the surface without moving for
|
|
14
|
+
* `longPressDelay` ms. Cancelled by any drag motion.
|
|
15
|
+
*/
|
|
16
|
+
onLongPress?: () => void;
|
|
17
|
+
longPressDelay?: number;
|
|
12
18
|
containerBounds?: {
|
|
13
19
|
width: number;
|
|
14
20
|
height: number;
|
|
@@ -23,12 +29,26 @@ interface DraggableHeaderProps {
|
|
|
23
29
|
};
|
|
24
30
|
style?: StyleProp<ViewStyle>;
|
|
25
31
|
enabled?: boolean;
|
|
32
|
+
/**
|
|
33
|
+
* Allow the element to drift past the right edge by this many pixels.
|
|
34
|
+
* Used to support drag-past-edge "hide" gestures where the bubble can
|
|
35
|
+
* sit mostly off-screen with only a peek visible.
|
|
36
|
+
*/
|
|
37
|
+
maxOverflowX?: number;
|
|
26
38
|
}
|
|
27
39
|
/**
|
|
28
|
-
* DraggableHeader
|
|
40
|
+
* DraggableHeader — the canonical floating-tools drag handle.
|
|
29
41
|
*
|
|
30
|
-
*
|
|
31
|
-
*
|
|
42
|
+
* Used by FloatingDevTools, JsModal's floating mode, and the perf-monitor
|
|
43
|
+
* bubble. Tracks drag via relative `dx`/`dy` (so parent padding/margins
|
|
44
|
+
* don't affect motion), discriminates tap-vs-drag by total distance, and
|
|
45
|
+
* clamps the final position to the container bounds.
|
|
46
|
+
*
|
|
47
|
+
* IMPORTANT: the PanResponder is created exactly ONCE per mount. All
|
|
48
|
+
* volatile props (callbacks, bounds, sizing) flow through `propsRef` so
|
|
49
|
+
* a parent re-render mid-gesture does NOT re-create the responder. Re-
|
|
50
|
+
* creating it during a drag detaches the active gesture and snaps the
|
|
51
|
+
* element back — that bug burned us once already.
|
|
32
52
|
*/
|
|
33
53
|
export declare const DraggableHeader: import("react").NamedExoticComponent<DraggableHeaderProps>;
|
|
34
54
|
export {};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"DraggableHeader.d.ts","sourceRoot":"","sources":["../../../../../src/ui/components/DraggableHeader.tsx"],"names":[],"mappings":"AAAA,OAAO,
|
|
1
|
+
{"version":3,"file":"DraggableHeader.d.ts","sourceRoot":"","sources":["../../../../../src/ui/components/DraggableHeader.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAoC,KAAK,SAAS,EAAE,MAAM,OAAO,CAAC;AACzE,OAAO,EAGL,QAAQ,EAER,KAAK,SAAS,EACd,KAAK,SAAS,EACf,MAAM,cAAc,CAAC;AAEtB,UAAU,oBAAoB;IAC5B,QAAQ,EAAE,SAAS,CAAC;IACpB,QAAQ,EAAE,QAAQ,CAAC,OAAO,CAAC;IAC3B,WAAW,CAAC,EAAE,MAAM,IAAI,CAAC;IACzB,SAAS,CAAC,EAAE,CAAC,aAAa,EAAE;QAAE,CAAC,EAAE,MAAM,CAAC;QAAC,CAAC,EAAE,MAAM,CAAA;KAAE,KAAK,IAAI,CAAC;IAC9D,KAAK,CAAC,EAAE,MAAM,IAAI,CAAC;IACnB;;;OAGG;IACH,WAAW,CAAC,EAAE,MAAM,IAAI,CAAC;IACzB,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,eAAe,CAAC,EAAE;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAE,CAAC;IACpD,WAAW,CAAC,EAAE;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAE,CAAC;IAChD,WAAW,CAAC,EAAE;QAAE,CAAC,EAAE,MAAM,CAAC;QAAC,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC;IACvC,KAAK,CAAC,EAAE,SAAS,CAAC,SAAS,CAAC,CAAC;IAC7B,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB;;;;OAIG;IACH,YAAY,CAAC,EAAE,MAAM,CAAC;CACvB;AAED;;;;;;;;;;;;;GAaG;AACH,eAAO,MAAM,eAAe,4DA0K1B,CAAC"}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
interface GripVerticalIconProps {
|
|
2
|
+
size?: number;
|
|
3
|
+
color?: string;
|
|
4
|
+
}
|
|
5
|
+
/**
|
|
6
|
+
* Two columns of three dots — the standard "grabber" affordance used by
|
|
7
|
+
* floating bubbles in this suite (FloatingDevTools, perf-monitor HUD).
|
|
8
|
+
*
|
|
9
|
+
* Sizing comes from `getGripIconLayout` in `@buoy-gg/floating-tools-core`
|
|
10
|
+
* so all bubbles share identical proportions.
|
|
11
|
+
*/
|
|
12
|
+
export declare function GripVerticalIcon({ size, color, }: GripVerticalIconProps): import("react").JSX.Element;
|
|
13
|
+
export {};
|
|
14
|
+
//# sourceMappingURL=GripVerticalIcon.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"GripVerticalIcon.d.ts","sourceRoot":"","sources":["../../../../../src/ui/components/GripVerticalIcon.tsx"],"names":[],"mappings":"AAIA,UAAU,qBAAqB;IAC7B,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED;;;;;;GAMG;AACH,wBAAgB,gBAAgB,CAAC,EAC/B,IAAS,EACT,KAAuC,GACxC,EAAE,qBAAqB,+BAwCvB"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"WindowControls.d.ts","sourceRoot":"","sources":["../../../../../src/ui/components/WindowControls.tsx"],"names":[],"mappings":"AAUA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,eAAe,CAAC;
|
|
1
|
+
{"version":3,"file":"WindowControls.d.ts","sourceRoot":"","sources":["../../../../../src/ui/components/WindowControls.tsx"],"names":[],"mappings":"AAUA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,eAAe,CAAC;AAS/C;;;GAGG;AACH,wBAAgB,2BAA2B,CAAC,OAAO,EAAE,OAAO,QAE3D;AAMD,UAAU,mBAAmB;IAC3B,+BAA+B;IAC/B,OAAO,EAAE,MAAM,IAAI,CAAC;IACpB,4EAA4E;IAC5E,UAAU,CAAC,EAAE,MAAM,IAAI,CAAC;IACxB,sFAAsF;IACtF,YAAY,CAAC,EAAE,MAAM,IAAI,CAAC;IAC1B,2EAA2E;IAC3E,IAAI,CAAC,EAAE,SAAS,CAAC;CAClB;AA+BD;;;;GAIG;AACH,wBAAgB,cAAc,CAAC,EAC7B,OAAO,EACP,UAAU,EACV,YAAY,EACZ,IAAI,GACL,EAAE,mBAAmB,+BAoDrB"}
|
|
@@ -23,6 +23,7 @@ export { StatusIndicator } from "./StatusIndicator";
|
|
|
23
23
|
export { TimeDisplay } from "./TimeDisplay";
|
|
24
24
|
export { DetailView } from "./DetailView";
|
|
25
25
|
export { DraggableHeader } from "./DraggableHeader";
|
|
26
|
+
export { GripVerticalIcon } from "./GripVerticalIcon";
|
|
26
27
|
export { CollapsibleSection } from "./CollapsibleSection";
|
|
27
28
|
export { DataInspector } from "./DataInspector";
|
|
28
29
|
export { SearchBar } from "./SearchBar";
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../../src/ui/components/index.ts"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../../src/ui/components/index.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"persistentStorage.d.ts","sourceRoot":"","sources":["../../../../src/utils/persistentStorage.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AA2CH,MAAM,WAAW,eAAe;IAC9B,OAAO,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAAC;IAC7C,OAAO,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IACnD,UAAU,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IACvC,UAAU,IAAI,OAAO,CAAC,MAAM,EAAE,CAAC,CAAC;IAChC,QAAQ,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC,EAAE,CAAC,CAAC;IAC7D,WAAW,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAC3C,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;CACxB;AAGD,KAAK,cAAc,GAAG,YAAY,GAAG,cAAc,GAAG,cAAc,GAAG,QAAQ,CAAC;
|
|
1
|
+
{"version":3,"file":"persistentStorage.d.ts","sourceRoot":"","sources":["../../../../src/utils/persistentStorage.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AA2CH,MAAM,WAAW,eAAe;IAC9B,OAAO,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAAC;IAC7C,OAAO,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IACnD,UAAU,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IACvC,UAAU,IAAI,OAAO,CAAC,MAAM,EAAE,CAAC,CAAC;IAChC,QAAQ,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC,EAAE,CAAC,CAAC;IAC7D,WAAW,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAC3C,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;CACxB;AAGD,KAAK,cAAc,GAAG,YAAY,GAAG,cAAc,GAAG,cAAc,GAAG,QAAQ,CAAC;AAgkBhF;;;;;;;GAOG;AACH,eAAO,MAAM,iBAAiB,EAAE,eAmC/B,CAAC;AAEF;;GAEG;AACH,wBAAsB,wBAAwB,IAAI,OAAO,CAAC,OAAO,CAAC,CAGjE;AAED;;GAEG;AACH,wBAAsB,qBAAqB,IAAI,OAAO,CAAC,cAAc,CAAC,CAGrE;AAED;;GAEG;AACH,wBAAgB,gBAAgB,IAAI,IAAI,CAIvC"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@buoy-gg/shared-ui",
|
|
3
|
-
"version": "2.1.
|
|
3
|
+
"version": "2.1.14",
|
|
4
4
|
"description": "Shared UI components, hooks, and utilities",
|
|
5
5
|
"main": "lib/commonjs/index.js",
|
|
6
6
|
"module": "lib/module/index.js",
|
|
@@ -115,10 +115,10 @@
|
|
|
115
115
|
],
|
|
116
116
|
"sideEffects": false,
|
|
117
117
|
"dependencies": {
|
|
118
|
-
"@buoy-gg/floating-tools-core": "2.1.
|
|
118
|
+
"@buoy-gg/floating-tools-core": "2.1.14"
|
|
119
119
|
},
|
|
120
120
|
"peerDependencies": {
|
|
121
|
-
"@buoy-gg/license": "2.1.
|
|
121
|
+
"@buoy-gg/license": "2.1.14",
|
|
122
122
|
"@react-native-clipboard/clipboard": "*",
|
|
123
123
|
"expo-clipboard": "*",
|
|
124
124
|
"expo-file-system": "*",
|
|
@@ -146,7 +146,7 @@
|
|
|
146
146
|
"expo-clipboard": "~7.1.5",
|
|
147
147
|
"react-native-safe-area-context": "^5.6.2",
|
|
148
148
|
"typescript": "~5.8.3",
|
|
149
|
-
"@buoy-gg/license": "2.1.
|
|
149
|
+
"@buoy-gg/license": "2.1.14"
|
|
150
150
|
},
|
|
151
151
|
"react-native-builder-bob": {
|
|
152
152
|
"source": "src",
|