@tastic/hud 0.1.6 → 0.3.0
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/dist/index.d.mts +91 -23
- package/dist/index.d.ts +91 -23
- package/dist/index.js +463 -105
- package/dist/index.mjs +423 -71
- package/package.json +3 -1
- package/src/BaseSettingsDialog.tsx +371 -0
- package/src/CornerActionButtons.tsx +39 -0
- package/src/LabeledDropdown.tsx +175 -0
- package/src/SharedActionBand.tsx +61 -0
- package/src/index.ts +4 -0
package/dist/index.mjs
CHANGED
|
@@ -1,39 +1,260 @@
|
|
|
1
|
+
// src/BaseSettingsDialog.tsx
|
|
2
|
+
import { AutoAppearancePicker, Dialog, useAutoPaperTheme } from "@rific/auto-paper";
|
|
3
|
+
import { Button, SoundContext, TouchableRipple, useHapticSettings, useSoundSettings, useVibration } from "@rific/feedback-press";
|
|
4
|
+
import { useUpdater } from "@rific/updater";
|
|
5
|
+
import { useIsTouchPrimaryDevice } from "@tastic/core";
|
|
6
|
+
import { useContext, useState } from "react";
|
|
7
|
+
import { Platform, ScrollView, StyleSheet, View } from "react-native";
|
|
8
|
+
import { Icon, Portal, Text } from "react-native-paper";
|
|
9
|
+
import { Fragment, jsx, jsxs } from "react/jsx-runtime";
|
|
10
|
+
function SettingIcon({ source, color, containerColor }) {
|
|
11
|
+
return /* @__PURE__ */ jsx(View, { style: [styles.iconBadge, { backgroundColor: containerColor }], children: /* @__PURE__ */ jsx(Icon, { source, size: 18, color }) });
|
|
12
|
+
}
|
|
13
|
+
function BaseSettingsDialog({ visible, onDismiss, rotation = 0, version, lockOrientation, onLockOrientationChange, deferBottomEdgeGestures, onDeferBottomEdgeGestures, hideSound = false, hideHaptics = false, hideAppearance = false, hideUpdateCheck = false, onUpdateError, children }) {
|
|
14
|
+
const { dark, colors } = useAutoPaperTheme();
|
|
15
|
+
const isTouchPrimary = useIsTouchPrimaryDevice();
|
|
16
|
+
const { settings: hapticSettings, set: setHapticSettings } = useHapticSettings();
|
|
17
|
+
const { settings: soundSettings, set: setSoundSettings } = useSoundSettings();
|
|
18
|
+
const sound = useContext(SoundContext);
|
|
19
|
+
const { forceShort: forceHapticFeedback } = useVibration();
|
|
20
|
+
const [infoMessage, setInfoMessage] = useState(null);
|
|
21
|
+
const { check, checking, updateReady } = useUpdater({
|
|
22
|
+
autoCheck: false,
|
|
23
|
+
autoPrompt: false,
|
|
24
|
+
onError: onUpdateError,
|
|
25
|
+
onInfo: (title, message) => setInfoMessage({ title, message })
|
|
26
|
+
});
|
|
27
|
+
const showLockOrientation = isTouchPrimary && lockOrientation !== void 0 && onLockOrientationChange !== void 0;
|
|
28
|
+
const showEdgeGuard = Platform.OS === "ios" && deferBottomEdgeGestures !== void 0 && onDeferBottomEdgeGestures !== void 0;
|
|
29
|
+
const showHaptics = Platform.OS !== "web" && !hideHaptics;
|
|
30
|
+
const showSound = !hideSound;
|
|
31
|
+
const showAppearance = !hideAppearance;
|
|
32
|
+
const showUpdateCheck = Platform.OS !== "web" && !hideUpdateCheck;
|
|
33
|
+
const fg = dark ? "#FFFFFF" : "#000000";
|
|
34
|
+
const cardBg = dark ? "#111111" : "#F2F2F2";
|
|
35
|
+
const cardBorder = dark ? "rgba(255,255,255,0.2)" : "rgba(0,0,0,0.2)";
|
|
36
|
+
return /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
37
|
+
/* @__PURE__ */ jsxs(Dialog, { visible, onDismiss, style: [styles.dialog, rotation % 360 !== 0 && { transform: [{ rotate: `${rotation}deg` }] }], children: [
|
|
38
|
+
/* @__PURE__ */ jsx(Dialog.Title, { children: "Settings" }),
|
|
39
|
+
/* @__PURE__ */ jsx(Dialog.ScrollArea, { style: styles.scrollArea, children: /* @__PURE__ */ jsxs(ScrollView, { contentContainerStyle: styles.content, showsVerticalScrollIndicator: false, children: [
|
|
40
|
+
/* @__PURE__ */ jsxs(View, { style: styles.toggleGroup, children: [
|
|
41
|
+
showLockOrientation && /* @__PURE__ */ jsx(TouchableRipple, { onPress: () => onLockOrientationChange(!lockOrientation), style: styles.toggleButton, accessibilityLabel: `Lock orientation ${lockOrientation ? "on" : "off"}`, children: /* @__PURE__ */ jsxs(View, { style: styles.toggleContent, children: [
|
|
42
|
+
/* @__PURE__ */ jsx(SettingIcon, { source: lockOrientation ? "lock" : "lock-open-variant-outline", color: lockOrientation ? colors.secondary : colors.onSurfaceVariant, containerColor: lockOrientation ? colors.secondaryContainer : colors.surfaceVariant }),
|
|
43
|
+
/* @__PURE__ */ jsxs(View, { style: styles.flexShrink, children: [
|
|
44
|
+
/* @__PURE__ */ jsx(Text, { variant: "bodyLarge", style: { color: colors.onSurface }, children: "Lock Orientation" }),
|
|
45
|
+
/* @__PURE__ */ jsx(Text, { variant: "bodySmall", numberOfLines: 1, style: { color: colors.onSurfaceVariant }, children: "Pins the current layout" })
|
|
46
|
+
] })
|
|
47
|
+
] }) }),
|
|
48
|
+
showEdgeGuard && /* @__PURE__ */ jsx(TouchableRipple, { onPress: () => onDeferBottomEdgeGestures(!deferBottomEdgeGestures), style: styles.toggleButton, accessibilityLabel: `Edge guard ${deferBottomEdgeGestures ? "on" : "off"}`, children: /* @__PURE__ */ jsxs(View, { style: styles.toggleContent, children: [
|
|
49
|
+
/* @__PURE__ */ jsx(SettingIcon, { source: deferBottomEdgeGestures ? "shield-check-outline" : "shield-off-outline", color: deferBottomEdgeGestures ? colors.secondary : colors.onSurfaceVariant, containerColor: deferBottomEdgeGestures ? colors.secondaryContainer : colors.surfaceVariant }),
|
|
50
|
+
/* @__PURE__ */ jsxs(View, { style: styles.flexShrink, children: [
|
|
51
|
+
/* @__PURE__ */ jsx(Text, { variant: "bodyLarge", style: { color: colors.onSurface }, children: "Edge Guard" }),
|
|
52
|
+
/* @__PURE__ */ jsx(Text, { variant: "bodySmall", numberOfLines: 1, style: { color: colors.onSurfaceVariant }, children: "Requires a second swipe" })
|
|
53
|
+
] })
|
|
54
|
+
] }) }),
|
|
55
|
+
(showSound || showHaptics) && /* @__PURE__ */ jsxs(View, { style: styles.toggleRow, children: [
|
|
56
|
+
showSound && /* @__PURE__ */ jsx(
|
|
57
|
+
TouchableRipple,
|
|
58
|
+
{
|
|
59
|
+
soundDisabled: true,
|
|
60
|
+
onPress: () => {
|
|
61
|
+
const enabled = !soundSettings.enabled;
|
|
62
|
+
setSoundSettings({ enabled });
|
|
63
|
+
if (enabled) sound.selection?.();
|
|
64
|
+
},
|
|
65
|
+
style: styles.toggleButtonInRow,
|
|
66
|
+
accessibilityLabel: `Sound ${soundSettings.enabled ? "on" : "off"}`,
|
|
67
|
+
children: /* @__PURE__ */ jsxs(View, { style: styles.toggleContent, children: [
|
|
68
|
+
/* @__PURE__ */ jsx(SettingIcon, { source: soundSettings.enabled ? "volume-high" : "volume-off", color: soundSettings.enabled ? colors.tertiary : colors.onSurfaceVariant, containerColor: soundSettings.enabled ? colors.tertiaryContainer : colors.surfaceVariant }),
|
|
69
|
+
/* @__PURE__ */ jsx(Text, { variant: "bodyLarge", style: { color: colors.onSurface }, children: "Sound" })
|
|
70
|
+
] })
|
|
71
|
+
}
|
|
72
|
+
),
|
|
73
|
+
showHaptics && /* @__PURE__ */ jsx(
|
|
74
|
+
TouchableRipple,
|
|
75
|
+
{
|
|
76
|
+
hapticDisabled: true,
|
|
77
|
+
onPress: () => {
|
|
78
|
+
const vibrate = !hapticSettings.vibrate;
|
|
79
|
+
setHapticSettings({ vibrate });
|
|
80
|
+
if (vibrate) forceHapticFeedback();
|
|
81
|
+
},
|
|
82
|
+
style: styles.toggleButtonInRow,
|
|
83
|
+
accessibilityLabel: `Haptics ${hapticSettings.vibrate ? "on" : "off"}`,
|
|
84
|
+
children: /* @__PURE__ */ jsxs(View, { style: styles.toggleContent, children: [
|
|
85
|
+
/* @__PURE__ */ jsx(SettingIcon, { source: hapticSettings.vibrate ? "vibrate" : "vibrate-off", color: hapticSettings.vibrate ? colors.tertiary : colors.onSurfaceVariant, containerColor: hapticSettings.vibrate ? colors.tertiaryContainer : colors.surfaceVariant }),
|
|
86
|
+
/* @__PURE__ */ jsx(Text, { variant: "bodyLarge", style: { color: colors.onSurface }, children: "Haptics" })
|
|
87
|
+
] })
|
|
88
|
+
}
|
|
89
|
+
)
|
|
90
|
+
] })
|
|
91
|
+
] }),
|
|
92
|
+
showAppearance && /* @__PURE__ */ jsxs(View, { style: styles.section, children: [
|
|
93
|
+
/* @__PURE__ */ jsx(Text, { variant: "labelMedium", style: [styles.sectionLabel, { color: colors.onSurfaceVariant }], children: "APPEARANCE" }),
|
|
94
|
+
/* @__PURE__ */ jsx(AutoAppearancePicker, { showLabels: false })
|
|
95
|
+
] }),
|
|
96
|
+
children,
|
|
97
|
+
showUpdateCheck && /* @__PURE__ */ jsxs(View, { style: styles.section, children: [
|
|
98
|
+
/* @__PURE__ */ jsxs(Text, { variant: "labelSmall", style: [styles.sectionLabel, { color: colors.onSurfaceVariant }], children: [
|
|
99
|
+
"VERSION ",
|
|
100
|
+
version,
|
|
101
|
+
updateReady ? " \xB7 UPDATE READY" : ""
|
|
102
|
+
] }),
|
|
103
|
+
/* @__PURE__ */ jsx(Button, { mode: "outlined", onPress: check, loading: checking, disabled: checking, children: "Check for Updates" })
|
|
104
|
+
] })
|
|
105
|
+
] }) })
|
|
106
|
+
] }),
|
|
107
|
+
infoMessage && /* @__PURE__ */ jsx(Portal, { children: /* @__PURE__ */ jsx(View, { style: styles.overlay, children: /* @__PURE__ */ jsxs(View, { style: [styles.overlayCard, { backgroundColor: cardBg, borderColor: cardBorder }, rotation % 360 !== 0 && { transform: [{ rotate: `${rotation}deg` }] }], children: [
|
|
108
|
+
/* @__PURE__ */ jsx(Icon, { source: "information-outline", size: 64, color: colors.secondary }),
|
|
109
|
+
/* @__PURE__ */ jsx(Text, { variant: "headlineLarge", style: [styles.overlayTitle, { color: colors.secondary }], children: infoMessage.title }),
|
|
110
|
+
/* @__PURE__ */ jsx(Text, { variant: "bodyLarge", style: [styles.overlayBody, { color: fg }], children: infoMessage.message }),
|
|
111
|
+
/* @__PURE__ */ jsx(Button, { mode: "contained", onPress: () => setInfoMessage(null), style: styles.overlayButton, buttonColor: colors.primary, textColor: colors.onPrimary, children: "OK" })
|
|
112
|
+
] }) }) })
|
|
113
|
+
] });
|
|
114
|
+
}
|
|
115
|
+
var styles = StyleSheet.create({
|
|
116
|
+
content: {
|
|
117
|
+
gap: 24,
|
|
118
|
+
paddingVertical: 20
|
|
119
|
+
},
|
|
120
|
+
// Caps the card so it never grows past the screen — without this the dialog just keeps
|
|
121
|
+
// growing to fit its content and the overflow gets clipped by the screen edge, which is
|
|
122
|
+
// what happened in landscape where there's less height to work with. Dialog.ScrollArea +
|
|
123
|
+
// ScrollView below then take over and let the content scroll within that bound.
|
|
124
|
+
dialog: {
|
|
125
|
+
maxHeight: "90%"
|
|
126
|
+
},
|
|
127
|
+
flexShrink: {
|
|
128
|
+
flexShrink: 1
|
|
129
|
+
},
|
|
130
|
+
iconBadge: {
|
|
131
|
+
alignItems: "center",
|
|
132
|
+
borderRadius: 10,
|
|
133
|
+
height: 36,
|
|
134
|
+
justifyContent: "center",
|
|
135
|
+
width: 36
|
|
136
|
+
},
|
|
137
|
+
overlay: {
|
|
138
|
+
alignItems: "center",
|
|
139
|
+
backgroundColor: "rgba(0,0,0,0.72)",
|
|
140
|
+
bottom: 0,
|
|
141
|
+
justifyContent: "center",
|
|
142
|
+
left: 0,
|
|
143
|
+
position: "absolute",
|
|
144
|
+
right: 0,
|
|
145
|
+
top: 0
|
|
146
|
+
},
|
|
147
|
+
overlayBody: { textAlign: "center" },
|
|
148
|
+
overlayButton: { width: 160 },
|
|
149
|
+
overlayCard: {
|
|
150
|
+
alignItems: "center",
|
|
151
|
+
borderRadius: 20,
|
|
152
|
+
borderWidth: 1,
|
|
153
|
+
gap: 16,
|
|
154
|
+
maxWidth: 360,
|
|
155
|
+
padding: 32
|
|
156
|
+
},
|
|
157
|
+
overlayTitle: { fontWeight: "bold" },
|
|
158
|
+
scrollArea: {
|
|
159
|
+
marginBottom: 0
|
|
160
|
+
},
|
|
161
|
+
section: {
|
|
162
|
+
gap: 12
|
|
163
|
+
},
|
|
164
|
+
sectionLabel: {
|
|
165
|
+
letterSpacing: 2
|
|
166
|
+
},
|
|
167
|
+
// Negative margin cancels the padding so the icon still lines up with APPEARANCE/SOUND &
|
|
168
|
+
// HAPTICS below, while the ripple/hover highlight itself gets room to breathe on both sides
|
|
169
|
+
// instead of a flush edge-to-edge slab. overflow: 'hidden' makes sure that highlight actually
|
|
170
|
+
// clips to borderRadius instead of drawing as a plain rectangle.
|
|
171
|
+
toggleButton: {
|
|
172
|
+
borderRadius: 12,
|
|
173
|
+
marginHorizontal: -12,
|
|
174
|
+
overflow: "hidden",
|
|
175
|
+
paddingHorizontal: 12,
|
|
176
|
+
paddingVertical: 10
|
|
177
|
+
},
|
|
178
|
+
// Same shape as toggleButton but `flex: 1` instead of its own `marginHorizontal: -12` — two of
|
|
179
|
+
// these side by side in toggleRow would otherwise both pull inward and collide in the middle.
|
|
180
|
+
// toggleRow carries that edge-alignment margin once, for the row as a whole, instead.
|
|
181
|
+
toggleButtonInRow: {
|
|
182
|
+
borderRadius: 12,
|
|
183
|
+
flex: 1,
|
|
184
|
+
overflow: "hidden",
|
|
185
|
+
paddingHorizontal: 12,
|
|
186
|
+
paddingVertical: 10
|
|
187
|
+
},
|
|
188
|
+
toggleContent: {
|
|
189
|
+
alignItems: "center",
|
|
190
|
+
flexDirection: "row",
|
|
191
|
+
gap: 12
|
|
192
|
+
},
|
|
193
|
+
toggleGroup: {
|
|
194
|
+
gap: 4
|
|
195
|
+
},
|
|
196
|
+
toggleRow: {
|
|
197
|
+
flexDirection: "row",
|
|
198
|
+
gap: 4,
|
|
199
|
+
marginHorizontal: -12
|
|
200
|
+
}
|
|
201
|
+
});
|
|
202
|
+
|
|
203
|
+
// src/CornerActionButtons.tsx
|
|
204
|
+
import { IconButton } from "@rific/feedback-press";
|
|
205
|
+
import { StyleSheet as StyleSheet2 } from "react-native";
|
|
206
|
+
import { Fragment as Fragment2, jsx as jsx2, jsxs as jsxs2 } from "react/jsx-runtime";
|
|
207
|
+
function CornerActionButtons({ onBack, onSettings, fg, insets }) {
|
|
208
|
+
return /* @__PURE__ */ jsxs2(Fragment2, { children: [
|
|
209
|
+
/* @__PURE__ */ jsx2(IconButton, { icon: "arrow-left", iconColor: fg, size: 24, style: [styles2.back, { top: 8 + insets.top, left: 8 + insets.left }], onPress: onBack, accessibilityLabel: "Back" }),
|
|
210
|
+
/* @__PURE__ */ jsx2(IconButton, { icon: "cog", iconColor: fg, size: 24, style: [styles2.topRight, { top: 8 + insets.top, right: 8 + insets.right }], onPress: onSettings, accessibilityLabel: "Settings" })
|
|
211
|
+
] });
|
|
212
|
+
}
|
|
213
|
+
var styles2 = StyleSheet2.create({
|
|
214
|
+
back: {
|
|
215
|
+
position: "absolute"
|
|
216
|
+
},
|
|
217
|
+
topRight: {
|
|
218
|
+
position: "absolute"
|
|
219
|
+
}
|
|
220
|
+
});
|
|
221
|
+
|
|
1
222
|
// src/fonts.ts
|
|
2
|
-
import { Platform } from "react-native";
|
|
3
|
-
var MONO_FONT =
|
|
223
|
+
import { Platform as Platform2 } from "react-native";
|
|
224
|
+
var MONO_FONT = Platform2.select({ ios: "Menlo", android: "monospace", default: "monospace" });
|
|
4
225
|
|
|
5
226
|
// src/InlineColorPicker.tsx
|
|
6
227
|
import { defaultColors, getContrastColor } from "@rific/auto-paper";
|
|
7
|
-
import { TouchableRipple } from "@rific/feedback-press";
|
|
228
|
+
import { TouchableRipple as TouchableRipple2 } from "@rific/feedback-press";
|
|
8
229
|
import { clamp } from "@tastic/core";
|
|
9
|
-
import { ScrollView, StyleSheet as
|
|
10
|
-
import { Icon, Text } from "react-native-paper";
|
|
230
|
+
import { ScrollView as ScrollView2, StyleSheet as StyleSheet4, useWindowDimensions as useWindowDimensions2, View as View4 } from "react-native";
|
|
231
|
+
import { Icon as Icon2, Text as Text2 } from "react-native-paper";
|
|
11
232
|
|
|
12
233
|
// src/PopoverBody.tsx
|
|
13
|
-
import { StyleSheet, View } from "react-native";
|
|
14
|
-
import { Fragment, jsx, jsxs } from "react/jsx-runtime";
|
|
234
|
+
import { StyleSheet as StyleSheet3, View as View2 } from "react-native";
|
|
235
|
+
import { Fragment as Fragment3, jsx as jsx3, jsxs as jsxs3 } from "react/jsx-runtime";
|
|
15
236
|
var CARET_SIZE = 7;
|
|
16
237
|
var CARET_RING_OFFSET = 2;
|
|
17
238
|
var CARET_DIP = 1;
|
|
18
239
|
function PopoverBody({ visible, children, align = "center", verticalAlign = "below", caretColor, caretBorderColor, caretBorderWidth = 1, triggerSize = 0 }) {
|
|
19
240
|
if (!visible) return null;
|
|
20
241
|
const above = verticalAlign === "above";
|
|
21
|
-
const alignStyle = align === "left" ?
|
|
22
|
-
const verticalStyle = above ?
|
|
242
|
+
const alignStyle = align === "left" ? styles3.contentLeft : align === "right" ? styles3.contentRight : styles3.contentCenter;
|
|
243
|
+
const verticalStyle = above ? styles3.contentAbove : styles3.contentBelow;
|
|
23
244
|
const ringSize = CARET_SIZE + caretBorderWidth;
|
|
24
245
|
const caretOffset = (halfFootprint) => align === "right" ? { right: triggerSize / 2 - halfFootprint } : { left: triggerSize / 2 - halfFootprint };
|
|
25
246
|
const caretFill = above ? "borderTopColor" : "borderBottomColor";
|
|
26
247
|
const caretWidthProp = above ? "borderTopWidth" : "borderBottomWidth";
|
|
27
248
|
const caretEdge = (size) => above ? { bottom: -size + CARET_DIP } : { top: -size + CARET_DIP };
|
|
28
|
-
return /* @__PURE__ */
|
|
249
|
+
return /* @__PURE__ */ jsxs3(View2, { style: [styles3.content, alignStyle, verticalStyle], children: [
|
|
29
250
|
children,
|
|
30
|
-
caretColor && /* @__PURE__ */
|
|
31
|
-
/* @__PURE__ */
|
|
32
|
-
/* @__PURE__ */
|
|
251
|
+
caretColor && /* @__PURE__ */ jsxs3(Fragment3, { children: [
|
|
252
|
+
/* @__PURE__ */ jsx3(View2, { style: [styles3.caret, caretOffset(ringSize), caretEdge(ringSize), { [caretFill]: caretBorderColor ?? caretColor, [caretWidthProp]: ringSize, borderLeftWidth: ringSize, borderRightWidth: ringSize }] }),
|
|
253
|
+
/* @__PURE__ */ jsx3(View2, { style: [styles3.caret, caretOffset(CARET_SIZE), caretEdge(CARET_SIZE - CARET_RING_OFFSET), { [caretFill]: caretColor, [caretWidthProp]: CARET_SIZE, borderLeftWidth: CARET_SIZE, borderRightWidth: CARET_SIZE }] })
|
|
33
254
|
] })
|
|
34
255
|
] });
|
|
35
256
|
}
|
|
36
|
-
var
|
|
257
|
+
var styles3 = StyleSheet3.create({
|
|
37
258
|
caret: {
|
|
38
259
|
borderLeftColor: "transparent",
|
|
39
260
|
borderRightColor: "transparent",
|
|
@@ -76,17 +297,17 @@ var styles = StyleSheet.create({
|
|
|
76
297
|
});
|
|
77
298
|
|
|
78
299
|
// src/useAutoAlign.ts
|
|
79
|
-
import { useCallback, useEffect, useRef, useState } from "react";
|
|
300
|
+
import { useCallback, useEffect, useRef, useState as useState2 } from "react";
|
|
80
301
|
import { useWindowDimensions } from "react-native";
|
|
81
302
|
var EDGE_MARGIN = 12;
|
|
82
303
|
function useAutoAlign(open, contentWidth, contentHeight) {
|
|
83
304
|
const triggerRef = useRef(null);
|
|
84
305
|
const { width: windowWidth, height: windowHeight } = useWindowDimensions();
|
|
85
|
-
const [align, setAlign] =
|
|
86
|
-
const [verticalAlign, setVerticalAlign] =
|
|
87
|
-
const [maxHeight, setMaxHeight] =
|
|
88
|
-
const [measured, setMeasured] =
|
|
89
|
-
const [prevOpen, setPrevOpen] =
|
|
306
|
+
const [align, setAlign] = useState2("center");
|
|
307
|
+
const [verticalAlign, setVerticalAlign] = useState2("below");
|
|
308
|
+
const [maxHeight, setMaxHeight] = useState2(contentHeight);
|
|
309
|
+
const [measured, setMeasured] = useState2(false);
|
|
310
|
+
const [prevOpen, setPrevOpen] = useState2(open);
|
|
90
311
|
if (open !== prevOpen) {
|
|
91
312
|
setPrevOpen(open);
|
|
92
313
|
if (open) setMeasured(false);
|
|
@@ -114,7 +335,7 @@ function useAutoAlign(open, contentWidth, contentHeight) {
|
|
|
114
335
|
}
|
|
115
336
|
|
|
116
337
|
// src/InlineColorPicker.tsx
|
|
117
|
-
import { jsx as
|
|
338
|
+
import { jsx as jsx4, jsxs as jsxs4 } from "react/jsx-runtime";
|
|
118
339
|
var EMOJI_PATTERN = /\p{Extended_Pictographic}/u;
|
|
119
340
|
var DEFAULT_SIZE = 48;
|
|
120
341
|
var SWATCH_SIZE = 28;
|
|
@@ -140,14 +361,14 @@ function InlineColorPicker({ id, host, value, onChange, swatches = defaultColors
|
|
|
140
361
|
const align = alignOverride ?? autoAlign;
|
|
141
362
|
const contrastColor = getContrastColor(value);
|
|
142
363
|
const tagFontSize = size * (tag && EMOJI_PATTERN.test(tag) ? 0.6 : 0.4);
|
|
143
|
-
return /* @__PURE__ */
|
|
144
|
-
/* @__PURE__ */
|
|
145
|
-
/* @__PURE__ */
|
|
364
|
+
return /* @__PURE__ */ jsxs4(View4, { style: [styles4.anchor, open && styles4.anchorOpen], children: [
|
|
365
|
+
/* @__PURE__ */ jsx4(TouchableRipple2, { onPress: () => host.toggle(id), borderless: true, style: [styles4.trigger, { backgroundColor: value, borderRadius: size / 2, height: size, width: size }], children: /* @__PURE__ */ jsx4(View4, { ref: triggerRef, collapsable: false, style: styles4.triggerMeasure, children: tag ? /* @__PURE__ */ jsx4(Text2, { style: [styles4.tagLabel, { color: contrastColor, fontFamily: labelFontFamily, fontSize: tagFontSize }], numberOfLines: 1, adjustsFontSizeToFit: true, children: tag }) : /* @__PURE__ */ jsx4(Icon2, { source: icon, size: size * 0.6, color: contrastColor }) }) }),
|
|
366
|
+
/* @__PURE__ */ jsx4(PopoverBody, { visible: open && measured, align, verticalAlign, caretColor: menuBg, caretBorderColor: value, caretBorderWidth: SWATCHES_BORDER_WIDTH, triggerSize: size, children: /* @__PURE__ */ jsx4(ScrollView2, { style: [styles4.swatches, { backgroundColor: menuBg, borderColor: value, width: swatchesWidth, maxHeight }], contentContainerStyle: styles4.swatchesContent, showsVerticalScrollIndicator: false, children: swatches.map((swatch) => {
|
|
146
367
|
const selected = swatch.value.toLowerCase() === value.toLowerCase();
|
|
147
368
|
const taken = !selected && !!takenValue && swatch.value.toLowerCase() === takenValue.toLowerCase();
|
|
148
369
|
const swappable = taken && allowSwapTaken;
|
|
149
|
-
return /* @__PURE__ */
|
|
150
|
-
|
|
370
|
+
return /* @__PURE__ */ jsx4(
|
|
371
|
+
TouchableRipple2,
|
|
151
372
|
{
|
|
152
373
|
disabled: taken && !swappable,
|
|
153
374
|
onPress: () => {
|
|
@@ -155,15 +376,15 @@ function InlineColorPicker({ id, host, value, onChange, swatches = defaultColors
|
|
|
155
376
|
if (autoDismiss) host.close();
|
|
156
377
|
},
|
|
157
378
|
borderless: true,
|
|
158
|
-
style: [
|
|
159
|
-
children: selected ? /* @__PURE__ */
|
|
379
|
+
style: [styles4.swatch, { backgroundColor: swatch.value }, selected && styles4.swatchSelected, taken && !swappable && styles4.swatchTaken],
|
|
380
|
+
children: selected ? /* @__PURE__ */ jsx4(Icon2, { source: "check", size: 16, color: getContrastColor(swatch.value) }) : swappable ? /* @__PURE__ */ jsx4(Icon2, { source: "swap-horizontal", size: 16, color: getContrastColor(swatch.value) }) : taken ? /* @__PURE__ */ jsx4(Icon2, { source: "close", size: 16, color: getContrastColor(swatch.value) }) : /* @__PURE__ */ jsx4(View4, {})
|
|
160
381
|
},
|
|
161
382
|
swatch.value
|
|
162
383
|
);
|
|
163
384
|
}) }) })
|
|
164
385
|
] });
|
|
165
386
|
}
|
|
166
|
-
var
|
|
387
|
+
var styles4 = StyleSheet4.create({
|
|
167
388
|
anchor: {
|
|
168
389
|
position: "relative"
|
|
169
390
|
},
|
|
@@ -234,31 +455,126 @@ var styles2 = StyleSheet2.create({
|
|
|
234
455
|
}
|
|
235
456
|
});
|
|
236
457
|
|
|
458
|
+
// src/LabeledDropdown.tsx
|
|
459
|
+
import { getContrastColor as getContrastColor2 } from "@rific/auto-paper";
|
|
460
|
+
import { TouchableRipple as TouchableRipple3 } from "@rific/feedback-press";
|
|
461
|
+
import { ScrollView as ScrollView3, StyleSheet as StyleSheet5, View as View5 } from "react-native";
|
|
462
|
+
import { Icon as Icon3, Text as Text3 } from "react-native-paper";
|
|
463
|
+
import { jsx as jsx5, jsxs as jsxs5 } from "react/jsx-runtime";
|
|
464
|
+
var TRIGGER_HEIGHT = 28;
|
|
465
|
+
var POPOVER_WIDTH = 180;
|
|
466
|
+
var ROW_HEIGHT = 36;
|
|
467
|
+
var LIST_PADDING = 8;
|
|
468
|
+
var LABELED_DROPDOWN_POPOVER_WIDTH = POPOVER_WIDTH;
|
|
469
|
+
function getLabeledDropdownContentHeight(optionCount) {
|
|
470
|
+
return LIST_PADDING * 2 + optionCount * ROW_HEIGHT;
|
|
471
|
+
}
|
|
472
|
+
function LabeledDropdown({ id, host, options, value, onChange, color, dark, align: forcedAlign, alignOverride }) {
|
|
473
|
+
const menuBg = dark ? "#000000" : "#FFFFFF";
|
|
474
|
+
const fg = dark ? "#FFFFFF" : "#000000";
|
|
475
|
+
const open = host.openId === id;
|
|
476
|
+
const selected = options.find((o) => o.value === value) ?? null;
|
|
477
|
+
const contentHeight = LIST_PADDING * 2 + options.length * ROW_HEIGHT;
|
|
478
|
+
const auto = useAutoAlign(open, POPOVER_WIDTH, contentHeight);
|
|
479
|
+
const placement = alignOverride ?? auto;
|
|
480
|
+
const { maxHeight, measured, triggerRef, verticalAlign } = placement;
|
|
481
|
+
const align = forcedAlign ?? placement.align;
|
|
482
|
+
const handleSelect = (option) => {
|
|
483
|
+
onChange(option.value);
|
|
484
|
+
host.close();
|
|
485
|
+
};
|
|
486
|
+
return /* @__PURE__ */ jsxs5(View5, { style: [styles5.anchor, open && styles5.anchorOpen], children: [
|
|
487
|
+
/* @__PURE__ */ jsx5(TouchableRipple3, { onPress: () => host.toggle(id), style: styles5.trigger, children: /* @__PURE__ */ jsxs5(View5, { ref: triggerRef, collapsable: false, style: styles5.triggerInner, children: [
|
|
488
|
+
/* @__PURE__ */ jsx5(Text3, { style: [styles5.triggerLabel, { color }], numberOfLines: 1, children: (selected?.label ?? "").toUpperCase() }),
|
|
489
|
+
/* @__PURE__ */ jsx5(Icon3, { source: "menu-down", size: 16, color })
|
|
490
|
+
] }) }),
|
|
491
|
+
/* @__PURE__ */ jsx5(PopoverBody, { visible: open && measured, align, verticalAlign, caretColor: menuBg, caretBorderColor: color, caretBorderWidth: 2, triggerSize: TRIGGER_HEIGHT, children: /* @__PURE__ */ jsx5(ScrollView3, { style: [styles5.menu, { backgroundColor: menuBg, borderColor: color, width: POPOVER_WIDTH, maxHeight }], contentContainerStyle: styles5.menuContent, showsVerticalScrollIndicator: false, children: options.map((option) => {
|
|
492
|
+
const isSelected = option.value === value;
|
|
493
|
+
const onColor = getContrastColor2(color);
|
|
494
|
+
return /* @__PURE__ */ jsx5(TouchableRipple3, { onPress: () => handleSelect(option), style: [styles5.row, isSelected && { backgroundColor: color }], children: /* @__PURE__ */ jsxs5(View5, { style: styles5.rowInner, children: [
|
|
495
|
+
option.icon && /* @__PURE__ */ jsx5(Icon3, { source: option.icon, size: 18, color: isSelected ? onColor : fg }),
|
|
496
|
+
/* @__PURE__ */ jsx5(Text3, { style: [styles5.rowLabel, { color: isSelected ? onColor : fg }], numberOfLines: 1, children: option.label })
|
|
497
|
+
] }) }, option.value);
|
|
498
|
+
}) }) })
|
|
499
|
+
] });
|
|
500
|
+
}
|
|
501
|
+
var styles5 = StyleSheet5.create({
|
|
502
|
+
anchor: {
|
|
503
|
+
position: "relative"
|
|
504
|
+
},
|
|
505
|
+
// React Native Web gives every position:'relative' view its own stacking context, so the
|
|
506
|
+
// elevation has to live on the anchor itself — see PopoverBody's own stacking-context notes.
|
|
507
|
+
anchorOpen: {
|
|
508
|
+
zIndex: 100
|
|
509
|
+
},
|
|
510
|
+
menu: {
|
|
511
|
+
borderRadius: 12,
|
|
512
|
+
borderWidth: 2,
|
|
513
|
+
elevation: 8,
|
|
514
|
+
shadowColor: "#000000",
|
|
515
|
+
shadowOffset: { height: 2, width: 0 },
|
|
516
|
+
shadowOpacity: 0.3,
|
|
517
|
+
shadowRadius: 8
|
|
518
|
+
},
|
|
519
|
+
menuContent: {
|
|
520
|
+
padding: LIST_PADDING
|
|
521
|
+
},
|
|
522
|
+
row: {
|
|
523
|
+
borderRadius: 8,
|
|
524
|
+
height: ROW_HEIGHT
|
|
525
|
+
},
|
|
526
|
+
rowInner: {
|
|
527
|
+
alignItems: "center",
|
|
528
|
+
flexDirection: "row",
|
|
529
|
+
flex: 1,
|
|
530
|
+
gap: 8,
|
|
531
|
+
paddingHorizontal: 12
|
|
532
|
+
},
|
|
533
|
+
rowLabel: {
|
|
534
|
+
flex: 1,
|
|
535
|
+
fontSize: 14
|
|
536
|
+
},
|
|
537
|
+
trigger: {
|
|
538
|
+
alignSelf: "flex-start"
|
|
539
|
+
},
|
|
540
|
+
triggerInner: {
|
|
541
|
+
alignItems: "center",
|
|
542
|
+
flexDirection: "row",
|
|
543
|
+
gap: 2,
|
|
544
|
+
height: TRIGGER_HEIGHT
|
|
545
|
+
},
|
|
546
|
+
triggerLabel: {
|
|
547
|
+
fontSize: 13,
|
|
548
|
+
fontWeight: "700",
|
|
549
|
+
letterSpacing: 1
|
|
550
|
+
}
|
|
551
|
+
});
|
|
552
|
+
|
|
237
553
|
// src/loadSkiaWeb.ts
|
|
238
554
|
function loadSkiaWeb() {
|
|
239
555
|
return Promise.resolve();
|
|
240
556
|
}
|
|
241
557
|
|
|
242
558
|
// src/PressAwayOverlay.tsx
|
|
243
|
-
import { Pressable, StyleSheet as
|
|
244
|
-
import { jsx as
|
|
559
|
+
import { Pressable, StyleSheet as StyleSheet6 } from "react-native";
|
|
560
|
+
import { jsx as jsx6 } from "react/jsx-runtime";
|
|
245
561
|
function PressAwayOverlay({ active, onPress, style }) {
|
|
246
562
|
if (!active) return null;
|
|
247
|
-
return /* @__PURE__ */
|
|
563
|
+
return /* @__PURE__ */ jsx6(Pressable, { accessibilityLabel: "Dismiss", accessibilityRole: "button", onPress, style: [StyleSheet6.absoluteFill, style] });
|
|
248
564
|
}
|
|
249
565
|
|
|
250
566
|
// src/ReadyButton.tsx
|
|
251
|
-
import { TouchableRipple as
|
|
252
|
-
import { StyleSheet as
|
|
253
|
-
import { Text as
|
|
254
|
-
import { jsx as
|
|
567
|
+
import { TouchableRipple as TouchableRipple4 } from "@rific/feedback-press";
|
|
568
|
+
import { StyleSheet as StyleSheet7 } from "react-native";
|
|
569
|
+
import { Text as Text4 } from "react-native-paper";
|
|
570
|
+
import { jsx as jsx7 } from "react/jsx-runtime";
|
|
255
571
|
function ReadyButton({ color, ready, onToggleReady, style, labelFontFamily = MONO_FONT }) {
|
|
256
|
-
const readyButtonStyle = [
|
|
572
|
+
const readyButtonStyle = [styles6.readyButton, { borderColor: color }, ready && { backgroundColor: color }, style];
|
|
257
573
|
const labelTextStyle = { fontFamily: labelFontFamily, fontWeight: "bold" };
|
|
258
574
|
const labelColorStyle = { color: ready ? "#000000" : color };
|
|
259
|
-
return /* @__PURE__ */
|
|
575
|
+
return /* @__PURE__ */ jsx7(TouchableRipple4, { onPress: onToggleReady, borderless: true, style: readyButtonStyle, children: /* @__PURE__ */ jsx7(Text4, { variant: "labelLarge", style: [labelTextStyle, labelColorStyle], children: ready ? "READY \u2713" : "READY?" }) });
|
|
260
576
|
}
|
|
261
|
-
var
|
|
577
|
+
var styles6 = StyleSheet7.create({
|
|
262
578
|
readyButton: {
|
|
263
579
|
alignItems: "center",
|
|
264
580
|
borderRadius: 12,
|
|
@@ -272,20 +588,20 @@ var styles3 = StyleSheet4.create({
|
|
|
272
588
|
|
|
273
589
|
// src/SectionedDropdown.tsx
|
|
274
590
|
import { getBlendedColor, getColorRoles } from "@rific/auto-paper";
|
|
275
|
-
import { IconButton, TouchableRipple as
|
|
276
|
-
import { ScrollView as
|
|
277
|
-
import { Icon as
|
|
591
|
+
import { IconButton as IconButton2, TouchableRipple as TouchableRipple5 } from "@rific/feedback-press";
|
|
592
|
+
import { ScrollView as ScrollView4, StyleSheet as StyleSheet8, View as View6 } from "react-native";
|
|
593
|
+
import { Icon as Icon4, Text as Text5 } from "react-native-paper";
|
|
278
594
|
|
|
279
595
|
// src/TriggerGaugeHost.tsx
|
|
280
596
|
import { lazy, Suspense } from "react";
|
|
281
|
-
import { jsx as
|
|
597
|
+
import { jsx as jsx8 } from "react/jsx-runtime";
|
|
282
598
|
var LazyTriggerGauge = lazy(() => loadSkiaWeb().then(() => import("./TriggerGauge-2OJOOF6I.mjs").then((m) => ({ default: m.TriggerGauge }))));
|
|
283
599
|
function TriggerGaugeHost(props) {
|
|
284
|
-
return /* @__PURE__ */
|
|
600
|
+
return /* @__PURE__ */ jsx8(Suspense, { fallback: null, children: /* @__PURE__ */ jsx8(LazyTriggerGauge, { ...props }) });
|
|
285
601
|
}
|
|
286
602
|
|
|
287
603
|
// src/SectionedDropdown.tsx
|
|
288
|
-
import { Fragment as
|
|
604
|
+
import { Fragment as Fragment4, jsx as jsx9, jsxs as jsxs6 } from "react/jsx-runtime";
|
|
289
605
|
var MENU_BORDER_WIDTH = 1;
|
|
290
606
|
var TRIGGER_SIZE = 44;
|
|
291
607
|
var MENU_MIN_WIDTH = 200;
|
|
@@ -331,17 +647,17 @@ function SectionedDropdown({ id, host, icon, accessibilityLabel, sections, accen
|
|
|
331
647
|
}
|
|
332
648
|
gaugeOffset += section.options.length;
|
|
333
649
|
}
|
|
334
|
-
const anchorStyle = [
|
|
650
|
+
const anchorStyle = [styles7.anchor, open && styles7.anchorOpen];
|
|
335
651
|
const menuStyle = { backgroundColor: menuBg, borderColor: menuBorderColor, maxHeight };
|
|
336
652
|
const dividerStyle = { backgroundColor: menuBorderColor };
|
|
337
|
-
return /* @__PURE__ */
|
|
338
|
-
/* @__PURE__ */
|
|
339
|
-
/* @__PURE__ */
|
|
340
|
-
/* @__PURE__ */
|
|
653
|
+
return /* @__PURE__ */ jsxs6(View6, { style: anchorStyle, children: [
|
|
654
|
+
/* @__PURE__ */ jsxs6(View6, { ref: triggerRef, collapsable: false, style: styles7.triggerBox, children: [
|
|
655
|
+
/* @__PURE__ */ jsx9(TriggerGaugeHost, { segments: gaugeSegments, litIndices: gaugeLitIndices, size: TRIGGER_SIZE, accentColor, mutedColor }),
|
|
656
|
+
/* @__PURE__ */ jsx9(IconButton2, { icon: triggerIcon, iconColor: triggerIconColor, size: triggerIconSize, accessibilityLabel, onPress: () => host.toggle(id) })
|
|
341
657
|
] }),
|
|
342
|
-
/* @__PURE__ */
|
|
343
|
-
sectionIndex > 0 && /* @__PURE__ */
|
|
344
|
-
section.kind === "single" ? /* @__PURE__ */
|
|
658
|
+
/* @__PURE__ */ jsx9(PopoverBody, { visible: open && measured, align, verticalAlign, caretColor: menuBg, caretBorderColor: menuBorderColor, caretBorderWidth: MENU_BORDER_WIDTH, triggerSize: TRIGGER_SIZE, children: /* @__PURE__ */ jsx9(ScrollView4, { style: [styles7.menu, menuStyle], contentContainerStyle: styles7.menuContent, showsVerticalScrollIndicator: false, children: sections.map((section, sectionIndex) => /* @__PURE__ */ jsxs6(View6, { children: [
|
|
659
|
+
sectionIndex > 0 && /* @__PURE__ */ jsx9(View6, { style: [styles7.divider, dividerStyle] }),
|
|
660
|
+
section.kind === "single" ? /* @__PURE__ */ jsx9(
|
|
345
661
|
SingleSection,
|
|
346
662
|
{
|
|
347
663
|
section,
|
|
@@ -354,7 +670,7 @@ function SectionedDropdown({ id, host, icon, accessibilityLabel, sections, accen
|
|
|
354
670
|
if (autoDismiss) host.close();
|
|
355
671
|
}
|
|
356
672
|
}
|
|
357
|
-
) : /* @__PURE__ */
|
|
673
|
+
) : /* @__PURE__ */ jsx9(MultiSection, { section, accentColor, onAccentColor: resolvedOnAccentColor, mutedColor, labelFontFamily, allClearLabels })
|
|
358
674
|
] }, section.id)) }) })
|
|
359
675
|
] });
|
|
360
676
|
}
|
|
@@ -366,17 +682,17 @@ function SingleSection({
|
|
|
366
682
|
labelFontFamily,
|
|
367
683
|
onSelect
|
|
368
684
|
}) {
|
|
369
|
-
return /* @__PURE__ */
|
|
685
|
+
return /* @__PURE__ */ jsx9(Fragment4, { children: section.options.map((option) => {
|
|
370
686
|
const selected = option.value === section.value;
|
|
371
687
|
const rowColor = selected ? onAccentColor : mutedColor;
|
|
372
|
-
const itemStyle = [
|
|
688
|
+
const itemStyle = [styles7.item, selected && { backgroundColor: accentColor }];
|
|
373
689
|
const labelStyle = { fontFamily: labelFontFamily, color: rowColor, fontWeight: selected ? "bold" : "normal" };
|
|
374
690
|
const descriptionStyle = { fontFamily: labelFontFamily, color: rowColor };
|
|
375
|
-
return /* @__PURE__ */
|
|
376
|
-
option.icon && /* @__PURE__ */
|
|
377
|
-
/* @__PURE__ */
|
|
378
|
-
/* @__PURE__ */
|
|
379
|
-
option.description && /* @__PURE__ */
|
|
691
|
+
return /* @__PURE__ */ jsx9(TouchableRipple5, { onPress: () => onSelect(option.value), style: itemStyle, children: /* @__PURE__ */ jsxs6(View6, { style: styles7.itemRow, children: [
|
|
692
|
+
option.icon && /* @__PURE__ */ jsx9(Icon4, { source: option.icon, size: MENU_ITEM_ICON_SIZE, color: rowColor }),
|
|
693
|
+
/* @__PURE__ */ jsxs6(View6, { style: styles7.itemLabelColumn, children: [
|
|
694
|
+
/* @__PURE__ */ jsx9(Text5, { variant: "labelLarge", style: labelStyle, children: option.label }),
|
|
695
|
+
option.description && /* @__PURE__ */ jsx9(Text5, { variant: "labelSmall", style: descriptionStyle, children: option.description })
|
|
380
696
|
] })
|
|
381
697
|
] }) }, option.value);
|
|
382
698
|
}) });
|
|
@@ -390,23 +706,23 @@ function MultiSection({
|
|
|
390
706
|
allClearLabels
|
|
391
707
|
}) {
|
|
392
708
|
const allSelected = section.value.length === section.options.length;
|
|
393
|
-
return /* @__PURE__ */
|
|
709
|
+
return /* @__PURE__ */ jsxs6(Fragment4, { children: [
|
|
394
710
|
section.options.map((option, i) => {
|
|
395
711
|
const selected = section.value.includes(option.value);
|
|
396
712
|
const rowColor = selected ? onAccentColor : mutedColor;
|
|
397
713
|
const prevSelected = selected && i > 0 && section.value.includes(section.options[i - 1].value);
|
|
398
714
|
const nextSelected = selected && i < section.options.length - 1 && section.value.includes(section.options[i + 1].value);
|
|
399
|
-
const itemStyle = [
|
|
715
|
+
const itemStyle = [styles7.item, selected && { backgroundColor: accentColor }, prevSelected && { borderTopLeftRadius: 0, borderTopRightRadius: 0 }, nextSelected && { borderBottomLeftRadius: 0, borderBottomRightRadius: 0 }];
|
|
400
716
|
const labelStyle = { fontFamily: labelFontFamily, color: rowColor, fontWeight: selected ? "bold" : "normal" };
|
|
401
|
-
return /* @__PURE__ */
|
|
402
|
-
option.icon && /* @__PURE__ */
|
|
403
|
-
/* @__PURE__ */
|
|
717
|
+
return /* @__PURE__ */ jsx9(TouchableRipple5, { onPress: () => section.onChange(selected ? section.value.filter((v) => v !== option.value) : [...section.value, option.value]), style: itemStyle, children: /* @__PURE__ */ jsxs6(View6, { style: styles7.itemRow, children: [
|
|
718
|
+
option.icon && /* @__PURE__ */ jsx9(Icon4, { source: option.icon, size: MENU_ITEM_ICON_SIZE, color: rowColor }),
|
|
719
|
+
/* @__PURE__ */ jsx9(Text5, { variant: "labelLarge", style: [styles7.itemLabelFlex, labelStyle], children: option.label })
|
|
404
720
|
] }) }, option.value);
|
|
405
721
|
}),
|
|
406
|
-
section.allClear && /* @__PURE__ */
|
|
722
|
+
section.allClear && /* @__PURE__ */ jsx9(TouchableRipple5, { onPress: () => section.onChange(allSelected ? [] : section.options.map((o) => o.value)), style: styles7.item, children: /* @__PURE__ */ jsx9(Text5, { variant: "labelLarge", style: [styles7.allClearLabel, { fontFamily: labelFontFamily, color: accentColor }], children: allSelected ? allClearLabels.clear : allClearLabels.all }) })
|
|
407
723
|
] });
|
|
408
724
|
}
|
|
409
|
-
var
|
|
725
|
+
var styles7 = StyleSheet8.create({
|
|
410
726
|
allClearLabel: {
|
|
411
727
|
fontWeight: "bold",
|
|
412
728
|
textAlign: "center"
|
|
@@ -423,7 +739,7 @@ var styles4 = StyleSheet5.create({
|
|
|
423
739
|
zIndex: 100
|
|
424
740
|
},
|
|
425
741
|
divider: {
|
|
426
|
-
height:
|
|
742
|
+
height: StyleSheet8.hairlineWidth,
|
|
427
743
|
marginVertical: 4
|
|
428
744
|
},
|
|
429
745
|
item: {
|
|
@@ -470,10 +786,40 @@ var styles4 = StyleSheet5.create({
|
|
|
470
786
|
}
|
|
471
787
|
});
|
|
472
788
|
|
|
789
|
+
// src/SharedActionBand.tsx
|
|
790
|
+
import { IconButton as IconButton3 } from "@rific/feedback-press";
|
|
791
|
+
import { StyleSheet as StyleSheet9, View as View7 } from "react-native";
|
|
792
|
+
import { jsx as jsx10, jsxs as jsxs7 } from "react/jsx-runtime";
|
|
793
|
+
function SharedActionBand({ onBack, onSettings, onRandomize, onReset, fg, popoverOpen, children }) {
|
|
794
|
+
return /* @__PURE__ */ jsxs7(View7, { style: [styles8.column, popoverOpen && styles8.columnOpen], children: [
|
|
795
|
+
/* @__PURE__ */ jsxs7(View7, { style: styles8.actionsRow, children: [
|
|
796
|
+
/* @__PURE__ */ jsx10(IconButton3, { icon: "arrow-left", iconColor: fg, size: 20, onPress: onBack, accessibilityLabel: "Back" }),
|
|
797
|
+
onRandomize && /* @__PURE__ */ jsx10(IconButton3, { icon: "dice-multiple", iconColor: fg, size: 18, onPress: onRandomize, accessibilityLabel: "Randomize match settings" }),
|
|
798
|
+
onReset && /* @__PURE__ */ jsx10(IconButton3, { icon: "restore", iconColor: fg, size: 18, onPress: onReset, accessibilityLabel: "Reset match settings to defaults" }),
|
|
799
|
+
/* @__PURE__ */ jsx10(IconButton3, { icon: "cog", iconColor: fg, size: 20, onPress: onSettings, accessibilityLabel: "Settings" })
|
|
800
|
+
] }),
|
|
801
|
+
children
|
|
802
|
+
] });
|
|
803
|
+
}
|
|
804
|
+
var styles8 = StyleSheet9.create({
|
|
805
|
+
actionsRow: {
|
|
806
|
+
alignItems: "center",
|
|
807
|
+
flexDirection: "row",
|
|
808
|
+
gap: 16
|
|
809
|
+
},
|
|
810
|
+
column: {
|
|
811
|
+
alignItems: "center",
|
|
812
|
+
gap: 8
|
|
813
|
+
},
|
|
814
|
+
columnOpen: {
|
|
815
|
+
zIndex: 100
|
|
816
|
+
}
|
|
817
|
+
});
|
|
818
|
+
|
|
473
819
|
// src/usePopoverHost.ts
|
|
474
|
-
import { useCallback as useCallback2, useState as
|
|
820
|
+
import { useCallback as useCallback2, useState as useState3 } from "react";
|
|
475
821
|
function usePopoverHost() {
|
|
476
|
-
const [openId, setOpenId] =
|
|
822
|
+
const [openId, setOpenId] = useState3(null);
|
|
477
823
|
const toggle = useCallback2((id) => {
|
|
478
824
|
setOpenId((prev) => prev === id ? null : id);
|
|
479
825
|
}, []);
|
|
@@ -481,13 +827,19 @@ function usePopoverHost() {
|
|
|
481
827
|
return { openId, toggle, close };
|
|
482
828
|
}
|
|
483
829
|
export {
|
|
830
|
+
BaseSettingsDialog,
|
|
831
|
+
CornerActionButtons,
|
|
484
832
|
InlineColorPicker,
|
|
833
|
+
LABELED_DROPDOWN_POPOVER_WIDTH,
|
|
834
|
+
LabeledDropdown,
|
|
485
835
|
MONO_FONT,
|
|
486
836
|
PopoverBody,
|
|
487
837
|
PressAwayOverlay,
|
|
488
838
|
ReadyButton,
|
|
489
839
|
SectionedDropdown,
|
|
840
|
+
SharedActionBand,
|
|
490
841
|
TriggerGaugeHost,
|
|
842
|
+
getLabeledDropdownContentHeight,
|
|
491
843
|
loadSkiaWeb,
|
|
492
844
|
useAutoAlign,
|
|
493
845
|
usePopoverHost
|