@buoy-gg/shared-ui 2.1.10 → 2.1.12
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/dataViewer/DataViewer.js +1 -3
- package/lib/commonjs/dataViewer/VirtualizedDataExplorer.js +3 -4
- package/lib/commonjs/hooks/safe-area-impl.js +1 -1
- package/lib/commonjs/icons/ImageOverlayIcon.js +142 -0
- package/lib/commonjs/icons/index.js +8 -0
- package/lib/commonjs/ui/components/EventHistoryViewer/EventHistoryViewer.js +2 -1
- package/lib/commonjs/ui/components/WindowControls.js +307 -46
- package/lib/commonjs/ui/components/index.js +6 -0
- package/lib/commonjs/utils/time/TickContext.js +43 -0
- package/lib/commonjs/utils/time/index.js +21 -1
- package/lib/commonjs/utils/time/useRelativeTime.js +36 -0
- package/lib/module/dataViewer/DataViewer.js +1 -3
- package/lib/module/dataViewer/VirtualizedDataExplorer.js +3 -4
- package/lib/module/hooks/safe-area-impl.js +1 -1
- package/lib/module/icons/ImageOverlayIcon.js +137 -0
- package/lib/module/icons/index.js +1 -0
- package/lib/module/ui/components/EventHistoryViewer/EventHistoryViewer.js +3 -2
- package/lib/module/ui/components/WindowControls.js +308 -48
- package/lib/module/ui/components/index.js +1 -1
- package/lib/module/utils/time/TickContext.js +38 -0
- package/lib/module/utils/time/index.js +3 -1
- package/lib/module/utils/time/useRelativeTime.js +33 -0
- package/lib/typescript/commonjs/dataViewer/VirtualizedDataExplorer.d.ts.map +1 -1
- package/lib/typescript/commonjs/hooks/safe-area-impl.d.ts +1 -1
- package/lib/typescript/commonjs/icons/ImageOverlayIcon.d.ts +14 -0
- package/lib/typescript/commonjs/icons/ImageOverlayIcon.d.ts.map +1 -0
- package/lib/typescript/commonjs/icons/index.d.ts +1 -0
- package/lib/typescript/commonjs/icons/index.d.ts.map +1 -1
- package/lib/typescript/commonjs/ui/components/WindowControls.d.ts +8 -3
- package/lib/typescript/commonjs/ui/components/WindowControls.d.ts.map +1 -1
- package/lib/typescript/commonjs/ui/components/index.d.ts +1 -1
- package/lib/typescript/commonjs/ui/components/index.d.ts.map +1 -1
- package/lib/typescript/commonjs/utils/time/TickContext.d.ts +21 -0
- package/lib/typescript/commonjs/utils/time/TickContext.d.ts.map +1 -0
- package/lib/typescript/commonjs/utils/time/index.d.ts +2 -0
- package/lib/typescript/commonjs/utils/time/index.d.ts.map +1 -1
- package/lib/typescript/commonjs/utils/time/useRelativeTime.d.ts +11 -0
- package/lib/typescript/commonjs/utils/time/useRelativeTime.d.ts.map +1 -0
- package/lib/typescript/module/dataViewer/VirtualizedDataExplorer.d.ts.map +1 -1
- package/lib/typescript/module/hooks/safe-area-impl.d.ts +1 -1
- package/lib/typescript/module/icons/ImageOverlayIcon.d.ts +14 -0
- package/lib/typescript/module/icons/ImageOverlayIcon.d.ts.map +1 -0
- package/lib/typescript/module/icons/index.d.ts +1 -0
- package/lib/typescript/module/icons/index.d.ts.map +1 -1
- package/lib/typescript/module/ui/components/WindowControls.d.ts +8 -3
- package/lib/typescript/module/ui/components/WindowControls.d.ts.map +1 -1
- package/lib/typescript/module/ui/components/index.d.ts +1 -1
- package/lib/typescript/module/ui/components/index.d.ts.map +1 -1
- package/lib/typescript/module/utils/time/TickContext.d.ts +21 -0
- package/lib/typescript/module/utils/time/TickContext.d.ts.map +1 -0
- package/lib/typescript/module/utils/time/index.d.ts +2 -0
- package/lib/typescript/module/utils/time/index.d.ts.map +1 -1
- package/lib/typescript/module/utils/time/useRelativeTime.d.ts +11 -0
- package/lib/typescript/module/utils/time/useRelativeTime.d.ts.map +1 -0
- package/package.json +4 -4
|
@@ -131,9 +131,7 @@ const DataViewer = ({
|
|
|
131
131
|
};
|
|
132
132
|
exports.DataViewer = DataViewer;
|
|
133
133
|
const styles = _reactNative.StyleSheet.create({
|
|
134
|
-
container: {
|
|
135
|
-
flex: 1
|
|
136
|
-
},
|
|
134
|
+
container: {},
|
|
137
135
|
header: {
|
|
138
136
|
flexDirection: "row",
|
|
139
137
|
justifyContent: "space-between",
|
|
@@ -60,7 +60,6 @@ const STABLE_STYLES = _reactNative.StyleSheet.create({
|
|
|
60
60
|
borderRadius: 8,
|
|
61
61
|
borderWidth: 1,
|
|
62
62
|
borderColor: _index.gameUIColors.primary + "14" // border-white/[0.08]
|
|
63
|
-
// Remove flex: 1 and minHeight to allow natural sizing
|
|
64
63
|
},
|
|
65
64
|
header: {
|
|
66
65
|
flexDirection: "column",
|
|
@@ -888,7 +887,7 @@ const VirtualizedDataExplorer = ({
|
|
|
888
887
|
|
|
889
888
|
// Simple keyExtractor without useCallback [[memory:4875251]]
|
|
890
889
|
const keyExtractor = item => item.id;
|
|
891
|
-
const hasData = data && (typeof data === "
|
|
890
|
+
const hasData = data !== null && data !== undefined && (typeof data === "string" ? data.length > 0 : typeof data === "number" || typeof data === "boolean" ? true : Array.isArray(data) ? data.length > 0 : typeof data === "object" ? Object.keys(data).length > 0 : false);
|
|
892
891
|
|
|
893
892
|
// Raw mode: render data directly without header/container
|
|
894
893
|
if (rawMode) {
|
|
@@ -908,7 +907,7 @@ const VirtualizedDataExplorer = ({
|
|
|
908
907
|
}
|
|
909
908
|
return /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.View, {
|
|
910
909
|
style: {
|
|
911
|
-
|
|
910
|
+
minHeight: isProcessing ? 40 : flatData.length * ITEM_HEIGHT
|
|
912
911
|
},
|
|
913
912
|
children: isProcessing ? /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.View, {
|
|
914
913
|
style: {
|
|
@@ -1023,7 +1022,7 @@ const VirtualizedDataExplorer = ({
|
|
|
1023
1022
|
})
|
|
1024
1023
|
}) : /*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNative.View, {
|
|
1025
1024
|
style: {
|
|
1026
|
-
height:
|
|
1025
|
+
height: flatData.length * ITEM_HEIGHT,
|
|
1027
1026
|
position: "relative"
|
|
1028
1027
|
},
|
|
1029
1028
|
children: [/*#__PURE__*/(0, _jsxRuntime.jsx)(_IndentGuidesOverlay.IndentGuidesOverlay, {
|
|
@@ -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-04-21T17:25:18.600Z
|
|
11
11
|
*
|
|
12
12
|
* DO NOT EDIT - This file is generated by scripts/detect-safe-area.js
|
|
13
13
|
*
|
|
@@ -0,0 +1,142 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, "__esModule", {
|
|
4
|
+
value: true
|
|
5
|
+
});
|
|
6
|
+
exports.ImageOverlayIcon = void 0;
|
|
7
|
+
var _reactNative = require("react-native");
|
|
8
|
+
var _jsxRuntime = require("react/jsx-runtime");
|
|
9
|
+
/**
|
|
10
|
+
* ImageOverlayIcon - Icon for the Image Overlay dev tool
|
|
11
|
+
* Shows layered image frames with a mountain/sun motif,
|
|
12
|
+
* representing design mockup overlay functionality.
|
|
13
|
+
*/
|
|
14
|
+
const ImageOverlayIcon = ({
|
|
15
|
+
size = 24,
|
|
16
|
+
color = "#A855F7",
|
|
17
|
+
glowColor
|
|
18
|
+
}) => {
|
|
19
|
+
const scale = size / 24;
|
|
20
|
+
const activeColor = color;
|
|
21
|
+
const activeGlow = glowColor || color;
|
|
22
|
+
return /*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNative.View, {
|
|
23
|
+
style: {
|
|
24
|
+
width: size,
|
|
25
|
+
height: size,
|
|
26
|
+
position: "relative",
|
|
27
|
+
alignItems: "center",
|
|
28
|
+
justifyContent: "center"
|
|
29
|
+
},
|
|
30
|
+
children: [/*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.View, {
|
|
31
|
+
style: {
|
|
32
|
+
position: "absolute",
|
|
33
|
+
width: 14 * scale,
|
|
34
|
+
height: 14 * scale,
|
|
35
|
+
borderRadius: 2 * scale,
|
|
36
|
+
borderWidth: 1.5 * scale,
|
|
37
|
+
borderColor: activeGlow,
|
|
38
|
+
backgroundColor: "transparent",
|
|
39
|
+
left: 2 * scale,
|
|
40
|
+
top: 2 * scale,
|
|
41
|
+
opacity: 0.25
|
|
42
|
+
}
|
|
43
|
+
}), /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.View, {
|
|
44
|
+
style: {
|
|
45
|
+
position: "absolute",
|
|
46
|
+
width: 15 * scale,
|
|
47
|
+
height: 15 * scale,
|
|
48
|
+
borderRadius: 2.5 * scale,
|
|
49
|
+
backgroundColor: activeGlow,
|
|
50
|
+
left: 7 * scale,
|
|
51
|
+
top: 7 * scale,
|
|
52
|
+
opacity: 0.12
|
|
53
|
+
}
|
|
54
|
+
}), /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.View, {
|
|
55
|
+
style: {
|
|
56
|
+
position: "absolute",
|
|
57
|
+
width: 14 * scale,
|
|
58
|
+
height: 14 * scale,
|
|
59
|
+
borderRadius: 2 * scale,
|
|
60
|
+
borderWidth: 1.5 * scale,
|
|
61
|
+
borderColor: activeColor,
|
|
62
|
+
backgroundColor: "transparent",
|
|
63
|
+
left: 8 * scale,
|
|
64
|
+
top: 8 * scale,
|
|
65
|
+
opacity: 0.9
|
|
66
|
+
}
|
|
67
|
+
}), /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.View, {
|
|
68
|
+
style: {
|
|
69
|
+
position: "absolute",
|
|
70
|
+
width: 3 * scale,
|
|
71
|
+
height: 3 * scale,
|
|
72
|
+
borderRadius: 1.5 * scale,
|
|
73
|
+
backgroundColor: activeColor,
|
|
74
|
+
left: 11 * scale,
|
|
75
|
+
top: 11 * scale,
|
|
76
|
+
opacity: 0.8
|
|
77
|
+
}
|
|
78
|
+
}), /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.View, {
|
|
79
|
+
style: {
|
|
80
|
+
position: "absolute",
|
|
81
|
+
width: 6 * scale,
|
|
82
|
+
height: 1.5 * scale,
|
|
83
|
+
backgroundColor: activeColor,
|
|
84
|
+
left: 9 * scale,
|
|
85
|
+
top: 18.5 * scale,
|
|
86
|
+
opacity: 0.7,
|
|
87
|
+
transform: [{
|
|
88
|
+
rotate: "-35deg"
|
|
89
|
+
}],
|
|
90
|
+
transformOrigin: "right center",
|
|
91
|
+
borderRadius: 0.5 * scale
|
|
92
|
+
}
|
|
93
|
+
}), /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.View, {
|
|
94
|
+
style: {
|
|
95
|
+
position: "absolute",
|
|
96
|
+
width: 6 * scale,
|
|
97
|
+
height: 1.5 * scale,
|
|
98
|
+
backgroundColor: activeColor,
|
|
99
|
+
left: 14.5 * scale,
|
|
100
|
+
top: 18.5 * scale,
|
|
101
|
+
opacity: 0.7,
|
|
102
|
+
transform: [{
|
|
103
|
+
rotate: "35deg"
|
|
104
|
+
}],
|
|
105
|
+
transformOrigin: "left center",
|
|
106
|
+
borderRadius: 0.5 * scale
|
|
107
|
+
}
|
|
108
|
+
}), [{
|
|
109
|
+
x: 2,
|
|
110
|
+
y: 2
|
|
111
|
+
}, {
|
|
112
|
+
x: 16,
|
|
113
|
+
y: 2
|
|
114
|
+
}, {
|
|
115
|
+
x: 2,
|
|
116
|
+
y: 16
|
|
117
|
+
}].map((pos, i) => /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.View, {
|
|
118
|
+
style: {
|
|
119
|
+
position: "absolute",
|
|
120
|
+
width: 2 * scale,
|
|
121
|
+
height: 2 * scale,
|
|
122
|
+
borderRadius: 1 * scale,
|
|
123
|
+
backgroundColor: activeGlow,
|
|
124
|
+
left: (pos.x - 1) * scale,
|
|
125
|
+
top: (pos.y - 1) * scale,
|
|
126
|
+
opacity: 0.5
|
|
127
|
+
}
|
|
128
|
+
}, `dot-${i}`)), /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.View, {
|
|
129
|
+
style: {
|
|
130
|
+
position: "absolute",
|
|
131
|
+
width: 8 * scale,
|
|
132
|
+
height: 1.5 * scale,
|
|
133
|
+
borderRadius: 0.75 * scale,
|
|
134
|
+
backgroundColor: "#fff",
|
|
135
|
+
left: 11 * scale,
|
|
136
|
+
top: 8.5 * scale,
|
|
137
|
+
opacity: 0.15
|
|
138
|
+
}
|
|
139
|
+
})]
|
|
140
|
+
});
|
|
141
|
+
};
|
|
142
|
+
exports.ImageOverlayIcon = ImageOverlayIcon;
|
|
@@ -22,6 +22,7 @@ var _exportNames = {
|
|
|
22
22
|
HighlightUpdatesIcon: true,
|
|
23
23
|
RenderCountIcon: true,
|
|
24
24
|
BenchmarkIcon: true,
|
|
25
|
+
ImageOverlayIcon: true,
|
|
25
26
|
IconBackground: true
|
|
26
27
|
};
|
|
27
28
|
Object.defineProperty(exports, "BenchmarkIcon", {
|
|
@@ -60,6 +61,12 @@ Object.defineProperty(exports, "IconBackground", {
|
|
|
60
61
|
return _IconBackground.IconBackground;
|
|
61
62
|
}
|
|
62
63
|
});
|
|
64
|
+
Object.defineProperty(exports, "ImageOverlayIcon", {
|
|
65
|
+
enumerable: true,
|
|
66
|
+
get: function () {
|
|
67
|
+
return _ImageOverlayIcon.ImageOverlayIcon;
|
|
68
|
+
}
|
|
69
|
+
});
|
|
63
70
|
Object.defineProperty(exports, "LaptopIcon", {
|
|
64
71
|
enumerable: true,
|
|
65
72
|
get: function () {
|
|
@@ -160,6 +167,7 @@ var _RouteMapIcon = require("./RouteMapIcon.js");
|
|
|
160
167
|
var _StackPulseIcon = require("./StackPulseIcon.js");
|
|
161
168
|
var _RenderCountIcon = require("./RenderCountIcon.js");
|
|
162
169
|
var _BenchmarkIcon = require("./BenchmarkIcon.js");
|
|
170
|
+
var _ImageOverlayIcon = require("./ImageOverlayIcon.js");
|
|
163
171
|
var _IconBackground = require("./IconBackground.js");
|
|
164
172
|
var _lucideIcons = require("./lucide-icons.js");
|
|
165
173
|
Object.keys(_lucideIcons).forEach(function (key) {
|
|
@@ -82,8 +82,9 @@ const EventHistoryViewer = exports.EventHistoryViewer = /*#__PURE__*/(0, _react.
|
|
|
82
82
|
diffDescription: diffViewDescription,
|
|
83
83
|
diffIcon: diffViewIcon,
|
|
84
84
|
diffDisabled: diffDisabled
|
|
85
|
-
}), activeView === "current" && /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.
|
|
85
|
+
}), activeView === "current" && /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.ScrollView, {
|
|
86
86
|
style: styles.contentSection,
|
|
87
|
+
showsVerticalScrollIndicator: true,
|
|
87
88
|
children: renderCurrentView()
|
|
88
89
|
}), activeView === "diff" && /*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNative.View, {
|
|
89
90
|
style: styles.contentSection,
|
|
@@ -4,9 +4,25 @@ Object.defineProperty(exports, "__esModule", {
|
|
|
4
4
|
value: true
|
|
5
5
|
});
|
|
6
6
|
exports.WindowControls = WindowControls;
|
|
7
|
+
exports.setExpandableWindowControls = setExpandableWindowControls;
|
|
8
|
+
var _react = require("react");
|
|
7
9
|
var _reactNative = require("react-native");
|
|
8
10
|
var _index = require("../../icons/index.js");
|
|
9
11
|
var _jsxRuntime = require("react/jsx-runtime");
|
|
12
|
+
// ============================================================================
|
|
13
|
+
// Global expandable setting — controlled via setExpandableWindowControls()
|
|
14
|
+
// ============================================================================
|
|
15
|
+
|
|
16
|
+
let _expandableEnabled = true; // Default ON
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* Set whether window controls use the expandable iPad-style behavior.
|
|
20
|
+
* Called by the floating-tools settings system when the setting changes.
|
|
21
|
+
*/
|
|
22
|
+
function setExpandableWindowControls(enabled) {
|
|
23
|
+
_expandableEnabled = enabled;
|
|
24
|
+
}
|
|
25
|
+
|
|
10
26
|
// ============================================================================
|
|
11
27
|
// Types
|
|
12
28
|
// ============================================================================
|
|
@@ -24,19 +40,28 @@ const COLORS = {
|
|
|
24
40
|
toggleMode: "#28C840" // Green - expand/fullscreen button
|
|
25
41
|
};
|
|
26
42
|
|
|
27
|
-
//
|
|
28
|
-
const BUTTON_SIZE = 12;
|
|
29
|
-
const BUTTON_SPACING = 8;
|
|
30
|
-
const ICON_SIZE = 8;
|
|
43
|
+
// Collapsed state (original small dots)
|
|
44
|
+
const BUTTON_SIZE = 12;
|
|
45
|
+
const BUTTON_SPACING = 8;
|
|
46
|
+
const ICON_SIZE = 8;
|
|
47
|
+
|
|
48
|
+
// Expanded state (large easy-to-tap buttons)
|
|
49
|
+
const EXPANDED_BUTTON_SIZE = 36;
|
|
50
|
+
const EXPANDED_BUTTON_SPACING = 12;
|
|
51
|
+
const EXPANDED_ICON_SIZE = 16;
|
|
52
|
+
const EXPANDED_PADDING = 8;
|
|
53
|
+
|
|
54
|
+
// Auto-dismiss timeout
|
|
55
|
+
const AUTO_DISMISS_MS = 3000;
|
|
31
56
|
|
|
32
57
|
// ============================================================================
|
|
33
58
|
// Component
|
|
34
59
|
// ============================================================================
|
|
35
60
|
|
|
36
61
|
/**
|
|
37
|
-
*
|
|
38
|
-
*
|
|
39
|
-
*
|
|
62
|
+
* iPad-style expandable window controls.
|
|
63
|
+
* Default: small macOS-style colored dots. On tap, expands to reveal
|
|
64
|
+
* large, easy-to-press buttons. Auto-dismisses after timeout or tap outside.
|
|
40
65
|
*/
|
|
41
66
|
function WindowControls({
|
|
42
67
|
onClose,
|
|
@@ -45,44 +70,236 @@ function WindowControls({
|
|
|
45
70
|
mode
|
|
46
71
|
}) {
|
|
47
72
|
// Show action-based icon: what will happen when clicked
|
|
48
|
-
// - If floating, show DockBottom (clicking will dock to bottom)
|
|
49
|
-
// - If bottomSheet, show FloatWindow (clicking will make it float)
|
|
50
73
|
const ToggleModeIcon = mode === "floating" ? _index.DockBottom : _index.FloatWindow;
|
|
51
74
|
const toggleModeLabel = mode === "floating" ? "Dock to bottom sheet" : "Make floating window";
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
style:
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
75
|
+
|
|
76
|
+
// When expandable is disabled, render original directly-tappable buttons
|
|
77
|
+
if (!_expandableEnabled) {
|
|
78
|
+
return /*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNative.View, {
|
|
79
|
+
style: styles.container,
|
|
80
|
+
children: [onMinimize && /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.TouchableOpacity, {
|
|
81
|
+
onPress: onMinimize,
|
|
82
|
+
style: [styles.dot, styles.minimizeDot],
|
|
83
|
+
activeOpacity: 0.8,
|
|
84
|
+
accessibilityLabel: "Minimize modal",
|
|
85
|
+
accessibilityRole: "button",
|
|
86
|
+
children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_index.Minus, {
|
|
87
|
+
size: ICON_SIZE,
|
|
88
|
+
color: "#7A5A00",
|
|
89
|
+
strokeWidth: 1.5
|
|
90
|
+
})
|
|
91
|
+
}), onToggleMode && /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.TouchableOpacity, {
|
|
92
|
+
onPress: onToggleMode,
|
|
93
|
+
style: [styles.dot, styles.expandDot],
|
|
94
|
+
activeOpacity: 0.8,
|
|
95
|
+
accessibilityLabel: toggleModeLabel,
|
|
96
|
+
accessibilityRole: "button",
|
|
97
|
+
children: /*#__PURE__*/(0, _jsxRuntime.jsx)(ToggleModeIcon, {
|
|
98
|
+
size: ICON_SIZE,
|
|
99
|
+
color: "#004A1A",
|
|
100
|
+
strokeWidth: 1.5
|
|
101
|
+
})
|
|
102
|
+
}), /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.TouchableOpacity, {
|
|
103
|
+
onPress: onClose,
|
|
104
|
+
style: [styles.dot, styles.closeDot],
|
|
105
|
+
activeOpacity: 0.8,
|
|
106
|
+
accessibilityLabel: "Close modal",
|
|
107
|
+
accessibilityRole: "button",
|
|
108
|
+
children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_index.X, {
|
|
109
|
+
size: ICON_SIZE,
|
|
110
|
+
color: "#4A0000",
|
|
111
|
+
strokeWidth: 1.5
|
|
112
|
+
})
|
|
113
|
+
})]
|
|
114
|
+
});
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
// On real devices, use iPad-style expandable controls
|
|
118
|
+
return /*#__PURE__*/(0, _jsxRuntime.jsx)(ExpandableWindowControls, {
|
|
119
|
+
onClose: onClose,
|
|
120
|
+
onMinimize: onMinimize,
|
|
121
|
+
onToggleMode: onToggleMode,
|
|
122
|
+
mode: mode
|
|
123
|
+
});
|
|
124
|
+
}
|
|
125
|
+
function ExpandableWindowControls({
|
|
126
|
+
onClose,
|
|
127
|
+
onMinimize,
|
|
128
|
+
onToggleMode,
|
|
129
|
+
mode
|
|
130
|
+
}) {
|
|
131
|
+
const [expanded, setExpanded] = (0, _react.useState)(false);
|
|
132
|
+
const [triggerLayout, setTriggerLayout] = (0, _react.useState)(null);
|
|
133
|
+
const expandAnim = (0, _react.useRef)(new _reactNative.Animated.Value(0)).current;
|
|
134
|
+
const dismissTimeout = (0, _react.useRef)(null);
|
|
135
|
+
const triggerRef = (0, _react.useRef)(null);
|
|
136
|
+
const ToggleModeIcon = mode === "floating" ? _index.DockBottom : _index.FloatWindow;
|
|
137
|
+
const toggleModeLabel = mode === "floating" ? "Dock to bottom sheet" : "Make floating window";
|
|
138
|
+
const clearDismissTimer = (0, _react.useCallback)(() => {
|
|
139
|
+
if (dismissTimeout.current) {
|
|
140
|
+
clearTimeout(dismissTimeout.current);
|
|
141
|
+
dismissTimeout.current = null;
|
|
142
|
+
}
|
|
143
|
+
}, []);
|
|
144
|
+
const collapse = (0, _react.useCallback)(() => {
|
|
145
|
+
clearDismissTimer();
|
|
146
|
+
_reactNative.Animated.spring(expandAnim, {
|
|
147
|
+
toValue: 0,
|
|
148
|
+
tension: 200,
|
|
149
|
+
friction: 20,
|
|
150
|
+
useNativeDriver: true
|
|
151
|
+
}).start(() => {
|
|
152
|
+
setExpanded(false);
|
|
153
|
+
});
|
|
154
|
+
}, [expandAnim, clearDismissTimer]);
|
|
155
|
+
const expand = (0, _react.useCallback)(() => {
|
|
156
|
+
// Measure trigger position on screen before expanding
|
|
157
|
+
triggerRef.current?.measureInWindow((x, y, width, height) => {
|
|
158
|
+
setTriggerLayout({
|
|
159
|
+
x,
|
|
160
|
+
y,
|
|
161
|
+
width,
|
|
162
|
+
height
|
|
163
|
+
});
|
|
164
|
+
setExpanded(true);
|
|
165
|
+
_reactNative.Animated.spring(expandAnim, {
|
|
166
|
+
toValue: 1,
|
|
167
|
+
tension: 180,
|
|
168
|
+
friction: 18,
|
|
169
|
+
useNativeDriver: true
|
|
170
|
+
}).start();
|
|
171
|
+
|
|
172
|
+
// Auto-dismiss
|
|
173
|
+
clearDismissTimer();
|
|
174
|
+
dismissTimeout.current = setTimeout(collapse, AUTO_DISMISS_MS);
|
|
175
|
+
});
|
|
176
|
+
}, [expandAnim, collapse, clearDismissTimer]);
|
|
177
|
+
(0, _react.useEffect)(() => {
|
|
178
|
+
return clearDismissTimer;
|
|
179
|
+
}, [clearDismissTimer]);
|
|
180
|
+
const handleAction = (0, _react.useCallback)(action => {
|
|
181
|
+
collapse();
|
|
182
|
+
action();
|
|
183
|
+
}, [collapse]);
|
|
184
|
+
|
|
185
|
+
// Animation interpolations
|
|
186
|
+
const scale = expandAnim.interpolate({
|
|
187
|
+
inputRange: [0, 1],
|
|
188
|
+
outputRange: [0.3, 1]
|
|
189
|
+
});
|
|
190
|
+
const opacity = expandAnim.interpolate({
|
|
191
|
+
inputRange: [0, 0.5, 1],
|
|
192
|
+
outputRange: [0, 0.8, 1]
|
|
193
|
+
});
|
|
194
|
+
|
|
195
|
+
// Count visible buttons for layout calculation
|
|
196
|
+
const buttonCount = 1 + (onMinimize ? 1 : 0) + (onToggleMode ? 1 : 0);
|
|
197
|
+
const expandedWidth = buttonCount * EXPANDED_BUTTON_SIZE + (buttonCount - 1) * EXPANDED_BUTTON_SPACING + EXPANDED_PADDING * 2;
|
|
198
|
+
const expandedHeight = EXPANDED_BUTTON_SIZE + EXPANDED_PADDING * 2;
|
|
199
|
+
return /*#__PURE__*/(0, _jsxRuntime.jsxs)(_jsxRuntime.Fragment, {
|
|
200
|
+
children: [/*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.TouchableOpacity, {
|
|
201
|
+
ref: triggerRef,
|
|
202
|
+
onPress: expand,
|
|
203
|
+
activeOpacity: 0.7,
|
|
204
|
+
accessibilityLabel: "Open window controls",
|
|
70
205
|
accessibilityRole: "button",
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
206
|
+
style: styles.trigger,
|
|
207
|
+
hitSlop: {
|
|
208
|
+
top: 8,
|
|
209
|
+
bottom: 8,
|
|
210
|
+
left: 8,
|
|
211
|
+
right: 8
|
|
212
|
+
},
|
|
213
|
+
children: /*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNative.View, {
|
|
214
|
+
style: styles.container,
|
|
215
|
+
children: [onMinimize && /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.View, {
|
|
216
|
+
style: [styles.dot, styles.minimizeDot],
|
|
217
|
+
children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_index.Minus, {
|
|
218
|
+
size: ICON_SIZE,
|
|
219
|
+
color: "#7A5A00",
|
|
220
|
+
strokeWidth: 1.5
|
|
221
|
+
})
|
|
222
|
+
}), onToggleMode && /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.View, {
|
|
223
|
+
style: [styles.dot, styles.expandDot],
|
|
224
|
+
children: /*#__PURE__*/(0, _jsxRuntime.jsx)(ToggleModeIcon, {
|
|
225
|
+
size: ICON_SIZE,
|
|
226
|
+
color: "#004A1A",
|
|
227
|
+
strokeWidth: 1.5
|
|
228
|
+
})
|
|
229
|
+
}), /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.View, {
|
|
230
|
+
style: [styles.dot, styles.closeDot],
|
|
231
|
+
children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_index.X, {
|
|
232
|
+
size: ICON_SIZE,
|
|
233
|
+
color: "#4A0000",
|
|
234
|
+
strokeWidth: 1.5
|
|
235
|
+
})
|
|
236
|
+
})]
|
|
75
237
|
})
|
|
76
|
-
}), /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
238
|
+
}), expanded && /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.Modal, {
|
|
239
|
+
transparent: true,
|
|
240
|
+
visible: true,
|
|
241
|
+
statusBarTranslucent: true,
|
|
242
|
+
children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.TouchableWithoutFeedback, {
|
|
243
|
+
onPress: collapse,
|
|
244
|
+
children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.View, {
|
|
245
|
+
style: styles.overlay,
|
|
246
|
+
children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.Animated.View, {
|
|
247
|
+
style: [styles.expandedPanel, {
|
|
248
|
+
transform: [{
|
|
249
|
+
scale
|
|
250
|
+
}],
|
|
251
|
+
opacity,
|
|
252
|
+
// Position the expanded panel anchored to trigger's top-right
|
|
253
|
+
top: triggerLayout ? triggerLayout.y - EXPANDED_PADDING : 0,
|
|
254
|
+
right: triggerLayout ? Math.max(4,
|
|
255
|
+
// screen width minus trigger's right edge
|
|
256
|
+
// We don't need Dimensions here since we use measureInWindow
|
|
257
|
+
// which gives absolute coords. right = screenWidth - (x + width)
|
|
258
|
+
0) : 0,
|
|
259
|
+
// Position using left instead, anchored to trigger's right edge
|
|
260
|
+
left: triggerLayout ? triggerLayout.x + triggerLayout.width - expandedWidth : undefined
|
|
261
|
+
}],
|
|
262
|
+
children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.TouchableWithoutFeedback, {
|
|
263
|
+
children: /*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNative.View, {
|
|
264
|
+
style: styles.expandedContainer,
|
|
265
|
+
children: [onMinimize && /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.TouchableOpacity, {
|
|
266
|
+
onPress: () => handleAction(onMinimize),
|
|
267
|
+
style: [styles.expandedButton, styles.minimizeButtonExpanded],
|
|
268
|
+
activeOpacity: 0.7,
|
|
269
|
+
accessibilityLabel: "Minimize modal",
|
|
270
|
+
accessibilityRole: "button",
|
|
271
|
+
children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_index.Minus, {
|
|
272
|
+
size: EXPANDED_ICON_SIZE,
|
|
273
|
+
color: "#7A5A00",
|
|
274
|
+
strokeWidth: 2
|
|
275
|
+
})
|
|
276
|
+
}), onToggleMode && /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.TouchableOpacity, {
|
|
277
|
+
onPress: () => handleAction(onToggleMode),
|
|
278
|
+
style: [styles.expandedButton, styles.expandButtonExpanded],
|
|
279
|
+
activeOpacity: 0.7,
|
|
280
|
+
accessibilityLabel: toggleModeLabel,
|
|
281
|
+
accessibilityRole: "button",
|
|
282
|
+
children: /*#__PURE__*/(0, _jsxRuntime.jsx)(ToggleModeIcon, {
|
|
283
|
+
size: EXPANDED_ICON_SIZE,
|
|
284
|
+
color: "#004A1A",
|
|
285
|
+
strokeWidth: 2
|
|
286
|
+
})
|
|
287
|
+
}), /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.TouchableOpacity, {
|
|
288
|
+
onPress: () => handleAction(onClose),
|
|
289
|
+
style: [styles.expandedButton, styles.closeButtonExpanded],
|
|
290
|
+
activeOpacity: 0.7,
|
|
291
|
+
accessibilityLabel: "Close modal",
|
|
292
|
+
accessibilityRole: "button",
|
|
293
|
+
children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_index.X, {
|
|
294
|
+
size: EXPANDED_ICON_SIZE,
|
|
295
|
+
color: "#4A0000",
|
|
296
|
+
strokeWidth: 2
|
|
297
|
+
})
|
|
298
|
+
})]
|
|
299
|
+
})
|
|
300
|
+
})
|
|
301
|
+
})
|
|
302
|
+
})
|
|
86
303
|
})
|
|
87
304
|
})]
|
|
88
305
|
});
|
|
@@ -93,26 +310,70 @@ function WindowControls({
|
|
|
93
310
|
// ============================================================================
|
|
94
311
|
|
|
95
312
|
const styles = _reactNative.StyleSheet.create({
|
|
313
|
+
trigger: {
|
|
314
|
+
padding: 2
|
|
315
|
+
},
|
|
96
316
|
container: {
|
|
97
317
|
flexDirection: "row",
|
|
98
318
|
alignItems: "center",
|
|
99
319
|
gap: BUTTON_SPACING
|
|
100
320
|
},
|
|
101
|
-
|
|
321
|
+
dot: {
|
|
102
322
|
width: BUTTON_SIZE,
|
|
103
323
|
height: BUTTON_SIZE,
|
|
104
324
|
borderRadius: BUTTON_SIZE / 2,
|
|
105
|
-
// Perfectly circular
|
|
106
325
|
alignItems: "center",
|
|
107
326
|
justifyContent: "center"
|
|
108
327
|
},
|
|
109
|
-
|
|
328
|
+
closeDot: {
|
|
329
|
+
backgroundColor: COLORS.close
|
|
330
|
+
},
|
|
331
|
+
minimizeDot: {
|
|
332
|
+
backgroundColor: COLORS.minimize
|
|
333
|
+
},
|
|
334
|
+
expandDot: {
|
|
335
|
+
backgroundColor: COLORS.toggleMode
|
|
336
|
+
},
|
|
337
|
+
overlay: {
|
|
338
|
+
flex: 1
|
|
339
|
+
},
|
|
340
|
+
expandedPanel: {
|
|
341
|
+
position: "absolute",
|
|
342
|
+
zIndex: 9999
|
|
343
|
+
},
|
|
344
|
+
expandedContainer: {
|
|
345
|
+
flexDirection: "row",
|
|
346
|
+
alignItems: "center",
|
|
347
|
+
gap: EXPANDED_BUTTON_SPACING,
|
|
348
|
+
backgroundColor: "rgba(16, 22, 35, 0.95)",
|
|
349
|
+
borderRadius: (EXPANDED_BUTTON_SIZE + EXPANDED_PADDING * 2) / 2,
|
|
350
|
+
paddingHorizontal: EXPANDED_PADDING,
|
|
351
|
+
paddingVertical: EXPANDED_PADDING,
|
|
352
|
+
borderWidth: 1,
|
|
353
|
+
borderColor: "rgba(0, 184, 230, 0.3)",
|
|
354
|
+
shadowColor: "#000",
|
|
355
|
+
shadowOffset: {
|
|
356
|
+
width: 0,
|
|
357
|
+
height: 4
|
|
358
|
+
},
|
|
359
|
+
shadowOpacity: 0.4,
|
|
360
|
+
shadowRadius: 12,
|
|
361
|
+
elevation: 30
|
|
362
|
+
},
|
|
363
|
+
expandedButton: {
|
|
364
|
+
width: EXPANDED_BUTTON_SIZE,
|
|
365
|
+
height: EXPANDED_BUTTON_SIZE,
|
|
366
|
+
borderRadius: EXPANDED_BUTTON_SIZE / 2,
|
|
367
|
+
alignItems: "center",
|
|
368
|
+
justifyContent: "center"
|
|
369
|
+
},
|
|
370
|
+
closeButtonExpanded: {
|
|
110
371
|
backgroundColor: COLORS.close
|
|
111
372
|
},
|
|
112
|
-
|
|
373
|
+
minimizeButtonExpanded: {
|
|
113
374
|
backgroundColor: COLORS.minimize
|
|
114
375
|
},
|
|
115
|
-
|
|
376
|
+
expandButtonExpanded: {
|
|
116
377
|
backgroundColor: COLORS.toggleMode
|
|
117
378
|
}
|
|
118
379
|
});
|
|
@@ -327,6 +327,12 @@ Object.defineProperty(exports, "WindowControls", {
|
|
|
327
327
|
return _WindowControls.WindowControls;
|
|
328
328
|
}
|
|
329
329
|
});
|
|
330
|
+
Object.defineProperty(exports, "setExpandableWindowControls", {
|
|
331
|
+
enumerable: true,
|
|
332
|
+
get: function () {
|
|
333
|
+
return _WindowControls.setExpandableWindowControls;
|
|
334
|
+
}
|
|
335
|
+
});
|
|
330
336
|
var _BackButton = require("./BackButton.js");
|
|
331
337
|
var _ValueTypeBadge = require("./ValueTypeBadge.js");
|
|
332
338
|
var _StorageTypeBadge = require("./StorageTypeBadge.js");
|