@tastic/hud 0.8.4 → 0.12.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/README.md +301 -20
- package/dist/index.d.mts +107 -15
- package/dist/index.d.ts +107 -15
- package/dist/index.js +556 -315
- package/dist/index.mjs +483 -262
- package/package.json +16 -8
- package/src/AchievementCatalogSection.tsx +60 -0
- package/src/ActivityStatSection.tsx +29 -0
- package/src/ConfirmDialog.tsx +30 -11
- package/src/ControlSchemePicker.tsx +11 -2
- package/src/InlineColorPicker.tsx +38 -11
- package/src/LabeledDropdown.tsx +5 -17
- package/src/PlayerSetupPanel.tsx +196 -0
- package/src/SectionedDropdown.tsx +18 -7
- package/src/StaggeredWord.tsx +114 -0
- package/src/index.ts +8 -2
- package/src/useAutoAlign.ts +17 -1
- package/src/useQuitConfirmation.ts +61 -0
- package/src/useZoneClampedAlign.ts +135 -0
package/dist/index.mjs
CHANGED
|
@@ -2,6 +2,12 @@ import {
|
|
|
2
2
|
SkiaGate
|
|
3
3
|
} from "./chunk-XEOFR236.mjs";
|
|
4
4
|
|
|
5
|
+
// src/AchievementCatalogSection.tsx
|
|
6
|
+
import { useAutoPaperTheme as useAutoPaperTheme2 } from "@rific/auto-paper";
|
|
7
|
+
import { Fragment } from "react";
|
|
8
|
+
import { StyleSheet as StyleSheet2 } from "react-native";
|
|
9
|
+
import { Text as Text2 } from "react-native-paper";
|
|
10
|
+
|
|
5
11
|
// src/AchievementRow.tsx
|
|
6
12
|
import { useAutoPaperTheme } from "@rific/auto-paper";
|
|
7
13
|
import { StyleSheet, View } from "react-native";
|
|
@@ -70,24 +76,110 @@ var styles = StyleSheet.create({
|
|
|
70
76
|
}
|
|
71
77
|
});
|
|
72
78
|
|
|
79
|
+
// src/fonts.ts
|
|
80
|
+
import { Platform } from "react-native";
|
|
81
|
+
var MONO_FONT = Platform.select({ ios: "Menlo", android: "monospace", default: "monospace" });
|
|
82
|
+
|
|
83
|
+
// src/AchievementCatalogSection.tsx
|
|
84
|
+
import { jsx as jsx2, jsxs as jsxs2 } from "react/jsx-runtime";
|
|
85
|
+
function AchievementCatalogSection({ rows, label = "ALL ACHIEVEMENTS", fg, fgMuted: fgMutedOverride }) {
|
|
86
|
+
const { dark } = useAutoPaperTheme2();
|
|
87
|
+
const fgMuted = fgMutedOverride ?? (dark ? "rgba(255,255,255,0.5)" : "rgba(0,0,0,0.5)");
|
|
88
|
+
return /* @__PURE__ */ jsxs2(Fragment, { children: [
|
|
89
|
+
/* @__PURE__ */ jsx2(Text2, { variant: "labelMedium", style: [styles2.label, { color: fgMuted, fontFamily: MONO_FONT }], children: label }),
|
|
90
|
+
rows.map((row) => /* @__PURE__ */ jsx2(AchievementRow, { icon: row.icon, title: row.title, description: row.description, badgeColor: row.unlockedAt !== void 0 ? row.tierColor : LOCKED_BADGE_COLOR, checkColor: row.tierColor, unlockedLabel: row.unlockedLabel, progress: row.progress, deviceMarker: row.deviceMarker, fg, fgMuted: fgMutedOverride }, row.id))
|
|
91
|
+
] });
|
|
92
|
+
}
|
|
93
|
+
var styles2 = StyleSheet2.create({
|
|
94
|
+
label: {
|
|
95
|
+
letterSpacing: 2,
|
|
96
|
+
marginTop: 8
|
|
97
|
+
}
|
|
98
|
+
});
|
|
99
|
+
|
|
100
|
+
// src/StatRow.tsx
|
|
101
|
+
import { useAutoPaperTheme as useAutoPaperTheme3 } from "@rific/auto-paper";
|
|
102
|
+
import { StyleSheet as StyleSheet3, View as View2 } from "react-native";
|
|
103
|
+
import { Text as Text3 } from "react-native-paper";
|
|
104
|
+
import { jsx as jsx3, jsxs as jsxs3 } from "react/jsx-runtime";
|
|
105
|
+
function StatRow({ label, value, fg: fgOverride, fgMuted: fgMutedOverride }) {
|
|
106
|
+
const { dark } = useAutoPaperTheme3();
|
|
107
|
+
const fg = fgOverride ?? (dark ? "#FFFFFF" : "#000000");
|
|
108
|
+
const fgMuted = fgMutedOverride ?? (dark ? "rgba(255,255,255,0.5)" : "rgba(0,0,0,0.5)");
|
|
109
|
+
return /* @__PURE__ */ jsxs3(View2, { style: styles3.row, children: [
|
|
110
|
+
/* @__PURE__ */ jsx3(Text3, { variant: "bodyMedium", style: { color: fgMuted }, children: label }),
|
|
111
|
+
/* @__PURE__ */ jsx3(Text3, { variant: "bodyMedium", style: [styles3.value, { color: fg }], children: value })
|
|
112
|
+
] });
|
|
113
|
+
}
|
|
114
|
+
var styles3 = StyleSheet3.create({
|
|
115
|
+
row: {
|
|
116
|
+
alignItems: "center",
|
|
117
|
+
flexDirection: "row",
|
|
118
|
+
justifyContent: "space-between"
|
|
119
|
+
},
|
|
120
|
+
value: {
|
|
121
|
+
fontWeight: "bold"
|
|
122
|
+
}
|
|
123
|
+
});
|
|
124
|
+
|
|
125
|
+
// src/StatSection.tsx
|
|
126
|
+
import { useAutoPaperTheme as useAutoPaperTheme4 } from "@rific/auto-paper";
|
|
127
|
+
import { StyleSheet as StyleSheet4, View as View3 } from "react-native";
|
|
128
|
+
import { Text as Text4 } from "react-native-paper";
|
|
129
|
+
import { jsx as jsx4, jsxs as jsxs4 } from "react/jsx-runtime";
|
|
130
|
+
function StatSection({ label, fg: fgOverride, sectionBg: sectionBgOverride, children }) {
|
|
131
|
+
const { dark } = useAutoPaperTheme4();
|
|
132
|
+
const fg = fgOverride ?? (dark ? "#FFFFFF" : "#000000");
|
|
133
|
+
const sectionBg = sectionBgOverride ?? (dark ? "rgba(255,255,255,0.06)" : "rgba(0,0,0,0.04)");
|
|
134
|
+
return /* @__PURE__ */ jsxs4(View3, { style: [styles4.section, { backgroundColor: sectionBg }], children: [
|
|
135
|
+
/* @__PURE__ */ jsx4(Text4, { variant: "labelMedium", style: [styles4.label, { color: fg }], children: label }),
|
|
136
|
+
children
|
|
137
|
+
] });
|
|
138
|
+
}
|
|
139
|
+
var styles4 = StyleSheet4.create({
|
|
140
|
+
// Bold and full-contrast (fg), not the original fontless/fgMuted treatment — that read at the
|
|
141
|
+
// same visual weight as StatRow's own row labels below it (both used the identical muted color;
|
|
142
|
+
// letterSpacing/variant alone didn't separate them enough to read as "this is the group header"
|
|
143
|
+
// at a glance). Matches AchievementRow's own title styling (bold + fg) below it in the same list.
|
|
144
|
+
label: {
|
|
145
|
+
fontWeight: "bold",
|
|
146
|
+
letterSpacing: 2
|
|
147
|
+
},
|
|
148
|
+
section: {
|
|
149
|
+
borderRadius: 12,
|
|
150
|
+
gap: 8,
|
|
151
|
+
padding: 16
|
|
152
|
+
}
|
|
153
|
+
});
|
|
154
|
+
|
|
155
|
+
// src/ActivityStatSection.tsx
|
|
156
|
+
import { jsx as jsx5, jsxs as jsxs5 } from "react/jsx-runtime";
|
|
157
|
+
function ActivityStatSection({ stats }) {
|
|
158
|
+
return /* @__PURE__ */ jsxs5(StatSection, { label: "ACTIVITY", children: [
|
|
159
|
+
/* @__PURE__ */ jsx5(StatRow, { label: "Days Played", value: String(stats.distinctDaysPlayed) }),
|
|
160
|
+
/* @__PURE__ */ jsx5(StatRow, { label: "Day Streak", value: String(stats.currentDayStreak) }),
|
|
161
|
+
/* @__PURE__ */ jsx5(StatRow, { label: "Best Day Streak", value: String(stats.bestDayStreak) })
|
|
162
|
+
] });
|
|
163
|
+
}
|
|
164
|
+
|
|
73
165
|
// src/BaseSettingsDialog.tsx
|
|
74
|
-
import { AutoAppearancePicker, Dialog, useAutoPaperTheme as
|
|
166
|
+
import { AutoAppearancePicker, Dialog, useAutoPaperTheme as useAutoPaperTheme6 } from "@rific/auto-paper";
|
|
75
167
|
import { Button as Button2, SoundContext, TouchableRipple, useHapticSettings, useSoundSettings, useVibration } from "@rific/feedback-press";
|
|
76
168
|
import { useUpdater } from "@rific/updater";
|
|
77
169
|
import { toRotationStyle as toRotationStyle2, useIsTouchPrimaryDevice, useRotation } from "@tastic/core";
|
|
78
170
|
import { useContext, useState as useState2 } from "react";
|
|
79
|
-
import { Platform, ScrollView, StyleSheet as
|
|
80
|
-
import { Icon as Icon3, Text as
|
|
171
|
+
import { Platform as Platform2, ScrollView, StyleSheet as StyleSheet7, View as View5 } from "react-native";
|
|
172
|
+
import { Icon as Icon3, Text as Text6 } from "react-native-paper";
|
|
81
173
|
|
|
82
174
|
// src/ConfirmDialog.tsx
|
|
83
|
-
import { useAutoPaperTheme as
|
|
175
|
+
import { useAutoPaperTheme as useAutoPaperTheme5 } from "@rific/auto-paper";
|
|
84
176
|
import { Button } from "@rific/feedback-press";
|
|
85
177
|
import { toRotationStyle } from "@tastic/core";
|
|
86
|
-
import { StyleSheet as
|
|
87
|
-
import { Icon as Icon2, Portal, Text as
|
|
178
|
+
import { StyleSheet as StyleSheet6, View as View4 } from "react-native";
|
|
179
|
+
import { Icon as Icon2, Portal, Text as Text5 } from "react-native-paper";
|
|
88
180
|
|
|
89
181
|
// src/overlayCard.ts
|
|
90
|
-
import { StyleSheet as
|
|
182
|
+
import { StyleSheet as StyleSheet5 } from "react-native";
|
|
91
183
|
function getOverlayCardColors(dark) {
|
|
92
184
|
return {
|
|
93
185
|
fg: dark ? "#FFFFFF" : "#000000",
|
|
@@ -96,7 +188,7 @@ function getOverlayCardColors(dark) {
|
|
|
96
188
|
cardBorder: dark ? "rgba(255,255,255,0.2)" : "rgba(0,0,0,0.2)"
|
|
97
189
|
};
|
|
98
190
|
}
|
|
99
|
-
var overlayStyles =
|
|
191
|
+
var overlayStyles = StyleSheet5.create({
|
|
100
192
|
card: {
|
|
101
193
|
alignItems: "center",
|
|
102
194
|
borderRadius: 20,
|
|
@@ -118,43 +210,62 @@ var overlayStyles = StyleSheet2.create({
|
|
|
118
210
|
});
|
|
119
211
|
|
|
120
212
|
// src/ConfirmDialog.tsx
|
|
121
|
-
import { jsx as
|
|
213
|
+
import { jsx as jsx6, jsxs as jsxs6 } from "react/jsx-runtime";
|
|
122
214
|
function ConfirmDialog({ visible, title, message, confirmLabel, cancelLabel, onConfirm, onCancel, rotation = 0, icon = "help-circle-outline", destructive = false }) {
|
|
123
|
-
const { dark, colors } =
|
|
215
|
+
const { dark, colors } = useAutoPaperTheme5();
|
|
124
216
|
if (!visible) return null;
|
|
125
217
|
const { fg, cardBg, cardBorder } = getOverlayCardColors(dark);
|
|
126
218
|
const accent = destructive ? colors.danger : colors.primary;
|
|
127
219
|
const onAccent = destructive ? colors.onDanger : colors.onPrimary;
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
/* @__PURE__ */
|
|
131
|
-
/* @__PURE__ */
|
|
132
|
-
/* @__PURE__ */
|
|
133
|
-
|
|
134
|
-
/* @__PURE__ */
|
|
220
|
+
const showCancel = cancelLabel !== void 0 && onCancel !== void 0;
|
|
221
|
+
return /* @__PURE__ */ jsx6(Portal, { children: /* @__PURE__ */ jsx6(View4, { style: [overlayStyles.overlay, styles5.overlay], children: /* @__PURE__ */ jsxs6(View4, { style: [overlayStyles.card, styles5.card, { backgroundColor: cardBg, borderColor: cardBorder }, toRotationStyle(rotation)], children: [
|
|
222
|
+
/* @__PURE__ */ jsx6(Icon2, { source: icon, size: 64, color: accent }),
|
|
223
|
+
/* @__PURE__ */ jsx6(Text5, { variant: "headlineLarge", style: [styles5.title, { color: accent }], children: title }),
|
|
224
|
+
/* @__PURE__ */ jsx6(Text5, { variant: "bodyLarge", style: [styles5.body, { color: fg }], children: message }),
|
|
225
|
+
/* @__PURE__ */ jsxs6(View4, { style: styles5.actions, children: [
|
|
226
|
+
showCancel && /* @__PURE__ */ jsx6(Button, { mode: "outlined", onPress: onCancel, style: styles5.actionButton, children: cancelLabel }),
|
|
227
|
+
/* @__PURE__ */ jsx6(Button, { mode: "contained", onPress: onConfirm, style: showCancel ? styles5.actionButton : styles5.actionButtonSingle, buttonColor: accent, textColor: onAccent, children: confirmLabel })
|
|
135
228
|
] })
|
|
136
229
|
] }) }) });
|
|
137
230
|
}
|
|
138
|
-
var
|
|
139
|
-
//
|
|
140
|
-
//
|
|
141
|
-
//
|
|
142
|
-
//
|
|
231
|
+
var styles5 = StyleSheet6.create({
|
|
232
|
+
// minWidth (not flexBasis) is each button's real floor - whenever both fit side by side, flexGrow
|
|
233
|
+
// still splits any leftover width evenly beyond that floor, same visual result as a plain flex: 1
|
|
234
|
+
// on a roomy screen, but a button can never be squeezed narrower than 128, only wrap to its own
|
|
235
|
+
// row instead (see actions' flexWrap below). This used to be flexBasis: 128, which measured
|
|
236
|
+
// correctly on web but rendered every button roughly SQUARE on iOS - confirmed live (see the
|
|
237
|
+
// "Quit Match?" Cancel/Quit buttons and the single-button "OK" dialogs both coming out ~128pt
|
|
238
|
+
// tall instead of wide). Root cause: react-native-paper's Button renders its Surface as two
|
|
239
|
+
// nested views on iOS only (Surface.tsx's SurfaceIOS, for shadow rendering) - only a curated
|
|
240
|
+
// allowlist of style keys (flex/flexGrow/flexShrink/width/height/position/... - notably NOT
|
|
241
|
+
// flexBasis) reaches the outer view, which is the real flex item inside this row; every other
|
|
242
|
+
// key, flexBasis included, falls through to an inner view whose own unspecified flexDirection
|
|
243
|
+
// defaults to column. flexGrow: 1 landed on the (row-context) outer view and grew width
|
|
244
|
+
// correctly; flexBasis: 128 landed on the (column-context) inner view instead, where a flexBasis
|
|
245
|
+
// sets HEIGHT, not width. minWidth isn't axis-relative like flexBasis, so it constrains width
|
|
246
|
+
// correctly regardless of which of the two views it ends up on. react-native-paper's Button also
|
|
143
247
|
// hardcodes numberOfLines={1} on its label with no override, so a button squeezed under its
|
|
144
248
|
// label's natural width silently ellipsizes ("Cancel" -> "Can...") instead of wrapping - assumed
|
|
145
249
|
// fixable by just giving the row more width, until confirmed live that these two-word labels
|
|
146
250
|
// (Cancel/Reset/New Game) can still lose the truncation fight even with the extra room card's own
|
|
147
|
-
// width fix below provides, on a narrow enough screen.
|
|
148
|
-
// width there's no side-by-side arrangement that fits both buttons at their natural label size,
|
|
149
|
-
// so the layout has to give (stack) rather than the label (truncate).
|
|
251
|
+
// width fix below provides, on a narrow enough screen.
|
|
150
252
|
actionButton: {
|
|
151
|
-
|
|
152
|
-
|
|
253
|
+
flexGrow: 1,
|
|
254
|
+
minWidth: 128
|
|
255
|
+
},
|
|
256
|
+
// A lone confirm button (no cancel - BaseSettingsDialog's info-only "OK" dialogs, e.g. the
|
|
257
|
+
// update-check "no update found" message) has nothing left to share actions' width with, so
|
|
258
|
+
// actionButton's own flexGrow: 1 would stretch it across the entire row instead of reading as a
|
|
259
|
+
// normal button. Same 128 floor, no flexGrow, so it stays at that natural size instead of filling
|
|
260
|
+
// the card - centered by actions' own justifyContent below.
|
|
261
|
+
actionButtonSingle: {
|
|
262
|
+
minWidth: 128
|
|
153
263
|
},
|
|
154
264
|
actions: {
|
|
155
265
|
flexDirection: "row",
|
|
156
266
|
flexWrap: "wrap",
|
|
157
267
|
gap: 12,
|
|
268
|
+
justifyContent: "center",
|
|
158
269
|
width: "100%"
|
|
159
270
|
},
|
|
160
271
|
body: {
|
|
@@ -205,12 +316,12 @@ function useUpdateConfirmBridge() {
|
|
|
205
316
|
}
|
|
206
317
|
|
|
207
318
|
// src/BaseSettingsDialog.tsx
|
|
208
|
-
import { Fragment, jsx as
|
|
319
|
+
import { Fragment as Fragment2, jsx as jsx7, jsxs as jsxs7 } from "react/jsx-runtime";
|
|
209
320
|
function SettingIcon({ source, color, containerColor }) {
|
|
210
|
-
return /* @__PURE__ */
|
|
321
|
+
return /* @__PURE__ */ jsx7(View5, { style: [styles6.iconBadge, { backgroundColor: containerColor }], children: /* @__PURE__ */ jsx7(Icon3, { source, size: 18, color }) });
|
|
211
322
|
}
|
|
212
323
|
function BaseSettingsDialog({ visible, onDismiss, rotation: rotationOverride, version, lockOrientation, onLockOrientationChange, deferBottomEdgeGestures, onDeferBottomEdgeGestures, hideSound = false, hideHaptics = false, hideAppearance = false, hideUpdateCheck = false, onUpdateError, children }) {
|
|
213
|
-
const { colors } =
|
|
324
|
+
const { colors } = useAutoPaperTheme6();
|
|
214
325
|
const ambientRotation = useRotation();
|
|
215
326
|
const rotation = rotationOverride ?? ambientRotation;
|
|
216
327
|
const isTouchPrimary = useIsTouchPrimaryDevice();
|
|
@@ -229,32 +340,32 @@ function BaseSettingsDialog({ visible, onDismiss, rotation: rotationOverride, ve
|
|
|
229
340
|
});
|
|
230
341
|
const updateManifestDate = updateManifest ? new Date(updateManifest.createdAt) : null;
|
|
231
342
|
const showLockOrientation = isTouchPrimary && lockOrientation !== void 0 && onLockOrientationChange !== void 0;
|
|
232
|
-
const showEdgeGuard =
|
|
233
|
-
const showHaptics =
|
|
343
|
+
const showEdgeGuard = Platform2.OS === "ios" && deferBottomEdgeGestures !== void 0 && onDeferBottomEdgeGestures !== void 0;
|
|
344
|
+
const showHaptics = Platform2.OS !== "web" && !hideHaptics;
|
|
234
345
|
const showSound = !hideSound;
|
|
235
346
|
const showAppearance = !hideAppearance;
|
|
236
|
-
const showUpdateCheck =
|
|
237
|
-
return /* @__PURE__ */
|
|
238
|
-
/* @__PURE__ */
|
|
239
|
-
/* @__PURE__ */
|
|
240
|
-
/* @__PURE__ */
|
|
241
|
-
/* @__PURE__ */
|
|
242
|
-
showLockOrientation && /* @__PURE__ */
|
|
243
|
-
/* @__PURE__ */
|
|
244
|
-
/* @__PURE__ */
|
|
245
|
-
/* @__PURE__ */
|
|
246
|
-
/* @__PURE__ */
|
|
347
|
+
const showUpdateCheck = Platform2.OS !== "web" && !hideUpdateCheck;
|
|
348
|
+
return /* @__PURE__ */ jsxs7(Fragment2, { children: [
|
|
349
|
+
/* @__PURE__ */ jsxs7(Dialog, { visible, onDismiss, style: [styles6.dialog, toRotationStyle2(rotation)], children: [
|
|
350
|
+
/* @__PURE__ */ jsx7(Dialog.Title, { children: "Settings" }),
|
|
351
|
+
/* @__PURE__ */ jsx7(Dialog.ScrollArea, { style: styles6.scrollArea, children: /* @__PURE__ */ jsxs7(ScrollView, { contentContainerStyle: styles6.content, showsVerticalScrollIndicator: false, children: [
|
|
352
|
+
/* @__PURE__ */ jsxs7(View5, { style: styles6.toggleGroup, children: [
|
|
353
|
+
showLockOrientation && /* @__PURE__ */ jsx7(TouchableRipple, { onPress: () => onLockOrientationChange(!lockOrientation), style: styles6.toggleButton, accessibilityLabel: `Lock orientation ${lockOrientation ? "on" : "off"}`, children: /* @__PURE__ */ jsxs7(View5, { style: styles6.toggleContent, children: [
|
|
354
|
+
/* @__PURE__ */ jsx7(SettingIcon, { source: lockOrientation ? "lock" : "lock-open-variant-outline", color: lockOrientation ? colors.secondary : colors.onSurfaceVariant, containerColor: lockOrientation ? colors.secondaryContainer : colors.surfaceVariant }),
|
|
355
|
+
/* @__PURE__ */ jsxs7(View5, { style: styles6.flexShrink, children: [
|
|
356
|
+
/* @__PURE__ */ jsx7(Text6, { variant: "bodyLarge", style: { color: colors.onSurface }, children: "Lock Orientation" }),
|
|
357
|
+
/* @__PURE__ */ jsx7(Text6, { variant: "bodySmall", numberOfLines: 1, style: { color: colors.onSurfaceVariant }, children: "Pins the current layout" })
|
|
247
358
|
] })
|
|
248
359
|
] }) }),
|
|
249
|
-
showEdgeGuard && /* @__PURE__ */
|
|
250
|
-
/* @__PURE__ */
|
|
251
|
-
/* @__PURE__ */
|
|
252
|
-
/* @__PURE__ */
|
|
253
|
-
/* @__PURE__ */
|
|
360
|
+
showEdgeGuard && /* @__PURE__ */ jsx7(TouchableRipple, { onPress: () => onDeferBottomEdgeGestures(!deferBottomEdgeGestures), style: styles6.toggleButton, accessibilityLabel: `Edge guard ${deferBottomEdgeGestures ? "on" : "off"}`, children: /* @__PURE__ */ jsxs7(View5, { style: styles6.toggleContent, children: [
|
|
361
|
+
/* @__PURE__ */ jsx7(SettingIcon, { source: deferBottomEdgeGestures ? "shield-check-outline" : "shield-off-outline", color: deferBottomEdgeGestures ? colors.secondary : colors.onSurfaceVariant, containerColor: deferBottomEdgeGestures ? colors.secondaryContainer : colors.surfaceVariant }),
|
|
362
|
+
/* @__PURE__ */ jsxs7(View5, { style: styles6.flexShrink, children: [
|
|
363
|
+
/* @__PURE__ */ jsx7(Text6, { variant: "bodyLarge", style: { color: colors.onSurface }, children: "Edge Guard" }),
|
|
364
|
+
/* @__PURE__ */ jsx7(Text6, { variant: "bodySmall", numberOfLines: 1, style: { color: colors.onSurfaceVariant }, children: "Requires a second swipe" })
|
|
254
365
|
] })
|
|
255
366
|
] }) }),
|
|
256
|
-
(showSound || showHaptics) && /* @__PURE__ */
|
|
257
|
-
showSound && /* @__PURE__ */
|
|
367
|
+
(showSound || showHaptics) && /* @__PURE__ */ jsxs7(View5, { style: styles6.toggleRow, children: [
|
|
368
|
+
showSound && /* @__PURE__ */ jsx7(
|
|
258
369
|
TouchableRipple,
|
|
259
370
|
{
|
|
260
371
|
soundDisabled: true,
|
|
@@ -263,15 +374,15 @@ function BaseSettingsDialog({ visible, onDismiss, rotation: rotationOverride, ve
|
|
|
263
374
|
setSoundSettings({ enabled });
|
|
264
375
|
if (enabled) sound.selection?.();
|
|
265
376
|
},
|
|
266
|
-
style:
|
|
377
|
+
style: styles6.toggleButtonInRow,
|
|
267
378
|
accessibilityLabel: `Sound ${soundSettings.enabled ? "on" : "off"}`,
|
|
268
|
-
children: /* @__PURE__ */
|
|
269
|
-
/* @__PURE__ */
|
|
270
|
-
/* @__PURE__ */
|
|
379
|
+
children: /* @__PURE__ */ jsxs7(View5, { style: styles6.toggleContent, children: [
|
|
380
|
+
/* @__PURE__ */ jsx7(SettingIcon, { source: soundSettings.enabled ? "volume-high" : "volume-off", color: soundSettings.enabled ? colors.tertiary : colors.onSurfaceVariant, containerColor: soundSettings.enabled ? colors.tertiaryContainer : colors.surfaceVariant }),
|
|
381
|
+
/* @__PURE__ */ jsx7(Text6, { variant: "bodyLarge", style: { color: colors.onSurface }, children: "Sound" })
|
|
271
382
|
] })
|
|
272
383
|
}
|
|
273
384
|
),
|
|
274
|
-
showHaptics && /* @__PURE__ */
|
|
385
|
+
showHaptics && /* @__PURE__ */ jsx7(
|
|
275
386
|
TouchableRipple,
|
|
276
387
|
{
|
|
277
388
|
hapticDisabled: true,
|
|
@@ -280,36 +391,36 @@ function BaseSettingsDialog({ visible, onDismiss, rotation: rotationOverride, ve
|
|
|
280
391
|
setHapticSettings({ vibrate });
|
|
281
392
|
if (vibrate) forceHapticFeedback();
|
|
282
393
|
},
|
|
283
|
-
style:
|
|
394
|
+
style: styles6.toggleButtonInRow,
|
|
284
395
|
accessibilityLabel: `Haptics ${hapticSettings.vibrate ? "on" : "off"}`,
|
|
285
|
-
children: /* @__PURE__ */
|
|
286
|
-
/* @__PURE__ */
|
|
287
|
-
/* @__PURE__ */
|
|
396
|
+
children: /* @__PURE__ */ jsxs7(View5, { style: styles6.toggleContent, children: [
|
|
397
|
+
/* @__PURE__ */ jsx7(SettingIcon, { source: hapticSettings.vibrate ? "vibrate" : "vibrate-off", color: hapticSettings.vibrate ? colors.tertiary : colors.onSurfaceVariant, containerColor: hapticSettings.vibrate ? colors.tertiaryContainer : colors.surfaceVariant }),
|
|
398
|
+
/* @__PURE__ */ jsx7(Text6, { variant: "bodyLarge", style: { color: colors.onSurface }, children: "Haptics" })
|
|
288
399
|
] })
|
|
289
400
|
}
|
|
290
401
|
)
|
|
291
402
|
] })
|
|
292
403
|
] }),
|
|
293
|
-
showAppearance && /* @__PURE__ */
|
|
294
|
-
/* @__PURE__ */
|
|
295
|
-
/* @__PURE__ */
|
|
404
|
+
showAppearance && /* @__PURE__ */ jsxs7(View5, { style: styles6.section, children: [
|
|
405
|
+
/* @__PURE__ */ jsx7(Text6, { variant: "labelMedium", style: [styles6.sectionLabel, { color: colors.onSurfaceVariant }], children: "APPEARANCE" }),
|
|
406
|
+
/* @__PURE__ */ jsx7(AutoAppearancePicker, { showLabels: false })
|
|
296
407
|
] }),
|
|
297
408
|
children,
|
|
298
|
-
showUpdateCheck && /* @__PURE__ */
|
|
299
|
-
/* @__PURE__ */
|
|
409
|
+
showUpdateCheck && /* @__PURE__ */ jsxs7(View5, { style: styles6.section, children: [
|
|
410
|
+
/* @__PURE__ */ jsxs7(Text6, { variant: "labelSmall", style: [styles6.sectionLabel, { color: colors.onSurfaceVariant }], children: [
|
|
300
411
|
"VERSION ",
|
|
301
412
|
version,
|
|
302
413
|
updateReady ? " \xB7 UPDATE READY" : ""
|
|
303
414
|
] }),
|
|
304
|
-
/* @__PURE__ */
|
|
415
|
+
/* @__PURE__ */ jsx7(Button2, { mode: "outlined", onPress: check, loading: checking, disabled: checking, children: "Check for Updates" })
|
|
305
416
|
] })
|
|
306
417
|
] }) })
|
|
307
418
|
] }),
|
|
308
|
-
/* @__PURE__ */
|
|
309
|
-
/* @__PURE__ */
|
|
419
|
+
/* @__PURE__ */ jsx7(ConfirmDialog, { visible: !!updateManifest, title: "Update Available", message: updateManifestDate ? `Released ${updateManifestDate.toLocaleDateString()} at ${updateManifestDate.toLocaleTimeString()}` : "", confirmLabel: "Restart", cancelLabel: "Later", icon: "update", rotation, onConfirm: () => respondToUpdateConfirm(true), onCancel: () => respondToUpdateConfirm(false) }),
|
|
420
|
+
/* @__PURE__ */ jsx7(ConfirmDialog, { visible: !!infoMessage, title: infoMessage?.title ?? "", message: infoMessage?.message ?? "", confirmLabel: "OK", icon: "information-outline", rotation, onConfirm: () => setInfoMessage(null) })
|
|
310
421
|
] });
|
|
311
422
|
}
|
|
312
|
-
var
|
|
423
|
+
var styles6 = StyleSheet7.create({
|
|
313
424
|
content: {
|
|
314
425
|
gap: 24,
|
|
315
426
|
paddingVertical: 20
|
|
@@ -377,31 +488,31 @@ var styles3 = StyleSheet4.create({
|
|
|
377
488
|
});
|
|
378
489
|
|
|
379
490
|
// src/BaseStatsScreen.tsx
|
|
380
|
-
import { useAutoPaperTheme as
|
|
491
|
+
import { useAutoPaperTheme as useAutoPaperTheme7 } from "@rific/auto-paper";
|
|
381
492
|
import { Button as Button3, IconButton } from "@rific/feedback-press";
|
|
382
493
|
import { useRotation as useRotation2 } from "@tastic/core";
|
|
383
494
|
import { useState as useState3 } from "react";
|
|
384
|
-
import { ScrollView as ScrollView2, StyleSheet as
|
|
385
|
-
import { Text as
|
|
386
|
-
import { jsx as
|
|
495
|
+
import { ScrollView as ScrollView2, StyleSheet as StyleSheet8, View as View6 } from "react-native";
|
|
496
|
+
import { Text as Text7 } from "react-native-paper";
|
|
497
|
+
import { jsx as jsx8, jsxs as jsxs8 } from "react/jsx-runtime";
|
|
387
498
|
function BaseStatsScreen({ rotation: rotationOverride, title = "Achievements", titleVariant = "headlineSmall", onBack, insets, onReset, resetLabel = "Reset All Stats", resetConfirmTitle = "Reset Everything?", resetConfirmBody = "This permanently erases all stats and achievements. This cannot be undone.", fg: fgOverride, bg: bgOverride, children }) {
|
|
388
|
-
const { dark, colors } =
|
|
499
|
+
const { dark, colors } = useAutoPaperTheme7();
|
|
389
500
|
const ambientRotation = useRotation2();
|
|
390
501
|
const rotation = rotationOverride ?? ambientRotation;
|
|
391
502
|
const [confirmResetVisible, setConfirmResetVisible] = useState3(false);
|
|
392
503
|
const showReset = !!onReset;
|
|
393
504
|
const fg = fgOverride ?? (dark ? "#FFFFFF" : "#000000");
|
|
394
505
|
const bg = bgOverride ?? (dark ? "#000000" : "#FFFFFF");
|
|
395
|
-
return /* @__PURE__ */
|
|
396
|
-
/* @__PURE__ */
|
|
397
|
-
/* @__PURE__ */
|
|
398
|
-
/* @__PURE__ */
|
|
506
|
+
return /* @__PURE__ */ jsxs8(View6, { style: [styles7.container, { backgroundColor: bg }], children: [
|
|
507
|
+
/* @__PURE__ */ jsxs8(View6, { style: [styles7.header, { paddingTop: 8 + insets.top, paddingLeft: 8 + insets.left }], children: [
|
|
508
|
+
/* @__PURE__ */ jsx8(IconButton, { icon: "arrow-left", iconColor: fg, size: 24, onPress: onBack }),
|
|
509
|
+
/* @__PURE__ */ jsx8(Text7, { variant: titleVariant, style: [styles7.title, { color: fg }], children: title })
|
|
399
510
|
] }),
|
|
400
|
-
/* @__PURE__ */
|
|
511
|
+
/* @__PURE__ */ jsxs8(ScrollView2, { style: styles7.scrollView, contentContainerStyle: [styles7.content, { paddingBottom: 32 + insets.bottom }], showsVerticalScrollIndicator: false, children: [
|
|
401
512
|
children,
|
|
402
|
-
showReset && /* @__PURE__ */
|
|
513
|
+
showReset && /* @__PURE__ */ jsx8(Button3, { mode: "contained", onPress: () => setConfirmResetVisible(true), buttonColor: colors.danger, textColor: colors.onDanger, style: styles7.resetButton, children: resetLabel })
|
|
403
514
|
] }),
|
|
404
|
-
/* @__PURE__ */
|
|
515
|
+
/* @__PURE__ */ jsx8(
|
|
405
516
|
ConfirmDialog,
|
|
406
517
|
{
|
|
407
518
|
visible: confirmResetVisible,
|
|
@@ -421,7 +532,7 @@ function BaseStatsScreen({ rotation: rotationOverride, title = "Achievements", t
|
|
|
421
532
|
)
|
|
422
533
|
] });
|
|
423
534
|
}
|
|
424
|
-
var
|
|
535
|
+
var styles7 = StyleSheet8.create({
|
|
425
536
|
container: {
|
|
426
537
|
flex: 1
|
|
427
538
|
},
|
|
@@ -453,18 +564,18 @@ var styles4 = StyleSheet5.create({
|
|
|
453
564
|
|
|
454
565
|
// src/ContentGutter.tsx
|
|
455
566
|
import { computeContentBounds } from "@tastic/core";
|
|
456
|
-
import { StyleSheet as
|
|
457
|
-
import { jsx as
|
|
567
|
+
import { StyleSheet as StyleSheet9, useWindowDimensions, View as View7 } from "react-native";
|
|
568
|
+
import { jsx as jsx9, jsxs as jsxs9 } from "react/jsx-runtime";
|
|
458
569
|
function ContentGutter({ maxContentWidth, leftGutter, rightGutter, style, children }) {
|
|
459
570
|
const { width: windowWidth } = useWindowDimensions();
|
|
460
571
|
const { contentWidth, gutterWidth } = computeContentBounds(windowWidth, maxContentWidth ?? Infinity);
|
|
461
|
-
return /* @__PURE__ */
|
|
462
|
-
/* @__PURE__ */
|
|
463
|
-
/* @__PURE__ */
|
|
464
|
-
/* @__PURE__ */
|
|
572
|
+
return /* @__PURE__ */ jsxs9(View7, { style: [styles8.row, style], children: [
|
|
573
|
+
/* @__PURE__ */ jsx9(View7, { style: [styles8.gutter, { width: gutterWidth }], children: leftGutter }),
|
|
574
|
+
/* @__PURE__ */ jsx9(View7, { style: { width: contentWidth }, children }),
|
|
575
|
+
/* @__PURE__ */ jsx9(View7, { style: [styles8.gutter, { width: gutterWidth }], children: rightGutter })
|
|
465
576
|
] });
|
|
466
577
|
}
|
|
467
|
-
var
|
|
578
|
+
var styles8 = StyleSheet9.create({
|
|
468
579
|
// overflow:'hidden' keeps an oversized leftGutter/rightGutter from bleeding into the content
|
|
469
580
|
// column instead of clipping cleanly at its own real width.
|
|
470
581
|
gutter: {
|
|
@@ -483,38 +594,34 @@ import { Platform as Platform3 } from "react-native";
|
|
|
483
594
|
import { getBlendedColor, getColorRoles } from "@rific/auto-paper";
|
|
484
595
|
import { IconButton as IconButton2, TouchableRipple as TouchableRipple2 } from "@rific/feedback-press";
|
|
485
596
|
import { useRotation as useRotation3 } from "@tastic/core";
|
|
486
|
-
import { ScrollView as ScrollView3, StyleSheet as
|
|
487
|
-
import { Icon as Icon4, Text as
|
|
488
|
-
|
|
489
|
-
// src/fonts.ts
|
|
490
|
-
import { Platform as Platform2 } from "react-native";
|
|
491
|
-
var MONO_FONT = Platform2.select({ ios: "Menlo", android: "monospace", default: "monospace" });
|
|
597
|
+
import { ScrollView as ScrollView3, StyleSheet as StyleSheet11, View as View10 } from "react-native";
|
|
598
|
+
import { Icon as Icon4, Text as Text8 } from "react-native-paper";
|
|
492
599
|
|
|
493
600
|
// src/PopoverBody.tsx
|
|
494
|
-
import { StyleSheet as
|
|
495
|
-
import { Fragment as
|
|
601
|
+
import { StyleSheet as StyleSheet10, View as View8 } from "react-native";
|
|
602
|
+
import { Fragment as Fragment3, jsx as jsx10, jsxs as jsxs10 } from "react/jsx-runtime";
|
|
496
603
|
var CARET_SIZE = 7;
|
|
497
604
|
var CARET_RING_OFFSET = 2;
|
|
498
605
|
var CARET_DIP = 1;
|
|
499
606
|
function PopoverBody({ visible, children, align = "center", verticalAlign = "below", caretColor, caretBorderColor, caretBorderWidth = 1, triggerSize = 0 }) {
|
|
500
607
|
if (!visible) return null;
|
|
501
608
|
const above = verticalAlign === "above";
|
|
502
|
-
const alignStyle = align === "left" ?
|
|
503
|
-
const verticalStyle = above ?
|
|
609
|
+
const alignStyle = align === "left" ? styles9.contentLeft : align === "right" ? styles9.contentRight : styles9.contentCenter;
|
|
610
|
+
const verticalStyle = above ? styles9.contentAbove : styles9.contentBelow;
|
|
504
611
|
const ringSize = CARET_SIZE + caretBorderWidth;
|
|
505
612
|
const caretOffset = (halfFootprint) => align === "right" ? { right: triggerSize / 2 - halfFootprint } : { left: triggerSize / 2 - halfFootprint };
|
|
506
613
|
const caretFill = above ? "borderTopColor" : "borderBottomColor";
|
|
507
614
|
const caretWidthProp = above ? "borderTopWidth" : "borderBottomWidth";
|
|
508
615
|
const caretEdge = (size) => above ? { bottom: -size + CARET_DIP } : { top: -size + CARET_DIP };
|
|
509
|
-
return /* @__PURE__ */
|
|
616
|
+
return /* @__PURE__ */ jsxs10(View8, { style: [styles9.content, alignStyle, verticalStyle], children: [
|
|
510
617
|
children,
|
|
511
|
-
caretColor && /* @__PURE__ */
|
|
512
|
-
/* @__PURE__ */
|
|
513
|
-
/* @__PURE__ */
|
|
618
|
+
caretColor && /* @__PURE__ */ jsxs10(Fragment3, { children: [
|
|
619
|
+
/* @__PURE__ */ jsx10(View8, { style: [styles9.caret, caretOffset(ringSize), caretEdge(ringSize), { [caretFill]: caretBorderColor ?? caretColor, [caretWidthProp]: ringSize, borderLeftWidth: ringSize, borderRightWidth: ringSize }] }),
|
|
620
|
+
/* @__PURE__ */ jsx10(View8, { style: [styles9.caret, caretOffset(CARET_SIZE), caretEdge(CARET_SIZE - CARET_RING_OFFSET), { [caretFill]: caretColor, [caretWidthProp]: CARET_SIZE, borderLeftWidth: CARET_SIZE, borderRightWidth: CARET_SIZE }] })
|
|
514
621
|
] })
|
|
515
622
|
] });
|
|
516
623
|
}
|
|
517
|
-
var
|
|
624
|
+
var styles9 = StyleSheet10.create({
|
|
518
625
|
caret: {
|
|
519
626
|
borderLeftColor: "transparent",
|
|
520
627
|
borderRightColor: "transparent",
|
|
@@ -557,10 +664,10 @@ var styles6 = StyleSheet7.create({
|
|
|
557
664
|
});
|
|
558
665
|
|
|
559
666
|
// src/TriggerGaugeHost.tsx
|
|
560
|
-
import { jsx as
|
|
667
|
+
import { jsx as jsx11 } from "react/jsx-runtime";
|
|
561
668
|
var getTriggerGauge = () => import("./TriggerGauge-2OJOOF6I.mjs").then((mod) => ({ default: mod.TriggerGauge }));
|
|
562
669
|
function TriggerGaugeHost(props) {
|
|
563
|
-
return /* @__PURE__ */
|
|
670
|
+
return /* @__PURE__ */ jsx11(SkiaGate, { getComponent: getTriggerGauge, componentProps: props });
|
|
564
671
|
}
|
|
565
672
|
|
|
566
673
|
// src/useAutoAlign.ts
|
|
@@ -612,7 +719,7 @@ function useAutoAlign(open, contentWidth, contentHeight, rotation = 0) {
|
|
|
612
719
|
}
|
|
613
720
|
|
|
614
721
|
// src/SectionedDropdown.tsx
|
|
615
|
-
import { Fragment as
|
|
722
|
+
import { Fragment as Fragment4, jsx as jsx12, jsxs as jsxs11 } from "react/jsx-runtime";
|
|
616
723
|
var MENU_BORDER_WIDTH = 1;
|
|
617
724
|
var TRIGGER_SIZE = 44;
|
|
618
725
|
var MENU_MIN_WIDTH = 200;
|
|
@@ -623,7 +730,7 @@ var MENU_ITEM_HEIGHT = 40;
|
|
|
623
730
|
var MENU_ITEM_HEIGHT_WITH_DESCRIPTION = 58;
|
|
624
731
|
var MENU_DIVIDER_HEIGHT = 9;
|
|
625
732
|
var MENU_VERTICAL_PADDING = 12;
|
|
626
|
-
function SectionedDropdown({ id, host, icon, accessibilityLabel, sections, accentColor, mutedColor, onAccentColor, dark, align: alignOverride, rotation: rotationOverride, autoDismiss = true, labelFontFamily = MONO_FONT, allClearLabels = { all: "All", clear: "Clear" } }) {
|
|
733
|
+
function SectionedDropdown({ id, host, icon, accessibilityLabel, sections, accentColor, mutedColor, onAccentColor, dark, align: forcedAlign, alignOverride, rotation: rotationOverride, autoDismiss = true, labelFontFamily = MONO_FONT, allClearLabels = { all: "All", clear: "Clear" } }) {
|
|
627
734
|
const ambientRotation = useRotation3();
|
|
628
735
|
const rotation = rotationOverride ?? ambientRotation;
|
|
629
736
|
const menuBg = dark ? "#000000" : "#FFFFFF";
|
|
@@ -637,8 +744,10 @@ function SectionedDropdown({ id, host, icon, accessibilityLabel, sections, accen
|
|
|
637
744
|
const divider = sectionIndex > 0 ? MENU_DIVIDER_HEIGHT : 0;
|
|
638
745
|
return sum + rows + footer + divider;
|
|
639
746
|
}, 0);
|
|
640
|
-
const
|
|
641
|
-
const
|
|
747
|
+
const auto = useAutoAlign(open, MENU_MAX_WIDTH, estimatedHeight, rotation);
|
|
748
|
+
const placement = alignOverride ?? auto;
|
|
749
|
+
const { maxHeight, measured, triggerRef, verticalAlign } = placement;
|
|
750
|
+
const align = forcedAlign ?? placement.align;
|
|
642
751
|
const onlySection = sections.length === 1 ? sections[0] : null;
|
|
643
752
|
const selectedOption = onlySection?.kind === "single" ? onlySection.options.find((o) => o.value === onlySection.value) : void 0;
|
|
644
753
|
const triggerIcon = selectedOption?.icon ?? icon;
|
|
@@ -660,17 +769,17 @@ function SectionedDropdown({ id, host, icon, accessibilityLabel, sections, accen
|
|
|
660
769
|
}
|
|
661
770
|
gaugeOffset += section.options.length;
|
|
662
771
|
}
|
|
663
|
-
const anchorStyle = [
|
|
772
|
+
const anchorStyle = [styles10.anchor, open && styles10.anchorOpen];
|
|
664
773
|
const menuStyle = { backgroundColor: menuBg, borderColor: menuBorderColor, maxHeight };
|
|
665
774
|
const dividerStyle = { backgroundColor: menuBorderColor };
|
|
666
|
-
return /* @__PURE__ */
|
|
667
|
-
/* @__PURE__ */
|
|
668
|
-
/* @__PURE__ */
|
|
669
|
-
/* @__PURE__ */
|
|
775
|
+
return /* @__PURE__ */ jsxs11(View10, { style: anchorStyle, children: [
|
|
776
|
+
/* @__PURE__ */ jsxs11(View10, { ref: triggerRef, collapsable: false, style: styles10.triggerBox, children: [
|
|
777
|
+
/* @__PURE__ */ jsx12(TriggerGaugeHost, { segments: gaugeSegments, litIndices: gaugeLitIndices, size: TRIGGER_SIZE, accentColor, mutedColor }),
|
|
778
|
+
/* @__PURE__ */ jsx12(IconButton2, { icon: triggerIcon, iconColor: triggerIconColor, size: triggerIconSize, accessibilityLabel, onPress: () => host.toggle(id) })
|
|
670
779
|
] }),
|
|
671
|
-
/* @__PURE__ */
|
|
672
|
-
sectionIndex > 0 && /* @__PURE__ */
|
|
673
|
-
section.kind === "single" ? /* @__PURE__ */
|
|
780
|
+
/* @__PURE__ */ jsx12(PopoverBody, { visible: open && measured, align, verticalAlign, caretColor: menuBg, caretBorderColor: menuBorderColor, caretBorderWidth: MENU_BORDER_WIDTH, triggerSize: TRIGGER_SIZE, children: /* @__PURE__ */ jsx12(ScrollView3, { style: [styles10.menu, menuStyle], contentContainerStyle: styles10.menuContent, showsVerticalScrollIndicator: false, children: sections.map((section, sectionIndex) => /* @__PURE__ */ jsxs11(View10, { children: [
|
|
781
|
+
sectionIndex > 0 && /* @__PURE__ */ jsx12(View10, { style: [styles10.divider, dividerStyle] }),
|
|
782
|
+
section.kind === "single" ? /* @__PURE__ */ jsx12(
|
|
674
783
|
SingleSection,
|
|
675
784
|
{
|
|
676
785
|
section,
|
|
@@ -683,7 +792,7 @@ function SectionedDropdown({ id, host, icon, accessibilityLabel, sections, accen
|
|
|
683
792
|
if (autoDismiss) host.close();
|
|
684
793
|
}
|
|
685
794
|
}
|
|
686
|
-
) : /* @__PURE__ */
|
|
795
|
+
) : /* @__PURE__ */ jsx12(MultiSection, { section, accentColor, onAccentColor: resolvedOnAccentColor, mutedColor, labelFontFamily, allClearLabels })
|
|
687
796
|
] }, section.id)) }) })
|
|
688
797
|
] });
|
|
689
798
|
}
|
|
@@ -695,18 +804,18 @@ function SingleSection({
|
|
|
695
804
|
labelFontFamily,
|
|
696
805
|
onSelect
|
|
697
806
|
}) {
|
|
698
|
-
return /* @__PURE__ */
|
|
807
|
+
return /* @__PURE__ */ jsx12(Fragment4, { children: section.options.map((option) => {
|
|
699
808
|
const selected = option.value === section.value;
|
|
700
809
|
const taken = !selected && option.value === section.takenValue;
|
|
701
810
|
const rowColor = selected ? onAccentColor : mutedColor;
|
|
702
|
-
const itemStyle = [
|
|
811
|
+
const itemStyle = [styles10.item, selected && { backgroundColor: accentColor }, taken && styles10.itemTaken];
|
|
703
812
|
const labelStyle = { fontFamily: labelFontFamily, color: rowColor, fontWeight: selected ? "bold" : "normal" };
|
|
704
813
|
const descriptionStyle = { fontFamily: labelFontFamily, color: rowColor };
|
|
705
|
-
return /* @__PURE__ */
|
|
706
|
-
option.icon && /* @__PURE__ */
|
|
707
|
-
/* @__PURE__ */
|
|
708
|
-
/* @__PURE__ */
|
|
709
|
-
option.description && /* @__PURE__ */
|
|
814
|
+
return /* @__PURE__ */ jsx12(TouchableRipple2, { disabled: taken, onPress: () => onSelect(option.value), style: itemStyle, children: /* @__PURE__ */ jsxs11(View10, { style: styles10.itemRow, children: [
|
|
815
|
+
option.icon && /* @__PURE__ */ jsx12(Icon4, { source: option.icon, size: MENU_ITEM_ICON_SIZE, color: rowColor }),
|
|
816
|
+
/* @__PURE__ */ jsxs11(View10, { style: styles10.itemLabelColumn, children: [
|
|
817
|
+
/* @__PURE__ */ jsx12(Text8, { variant: "labelLarge", style: labelStyle, children: option.label }),
|
|
818
|
+
option.description && /* @__PURE__ */ jsx12(Text8, { variant: "labelSmall", style: descriptionStyle, children: option.description })
|
|
710
819
|
] })
|
|
711
820
|
] }) }, option.value);
|
|
712
821
|
}) });
|
|
@@ -720,23 +829,23 @@ function MultiSection({
|
|
|
720
829
|
allClearLabels
|
|
721
830
|
}) {
|
|
722
831
|
const allSelected = section.value.length === section.options.length;
|
|
723
|
-
return /* @__PURE__ */
|
|
832
|
+
return /* @__PURE__ */ jsxs11(Fragment4, { children: [
|
|
724
833
|
section.options.map((option, i) => {
|
|
725
834
|
const selected = section.value.includes(option.value);
|
|
726
835
|
const rowColor = selected ? onAccentColor : mutedColor;
|
|
727
836
|
const prevSelected = selected && i > 0 && section.value.includes(section.options[i - 1].value);
|
|
728
837
|
const nextSelected = selected && i < section.options.length - 1 && section.value.includes(section.options[i + 1].value);
|
|
729
|
-
const itemStyle = [
|
|
838
|
+
const itemStyle = [styles10.item, selected && { backgroundColor: accentColor }, prevSelected && { borderTopLeftRadius: 0, borderTopRightRadius: 0 }, nextSelected && { borderBottomLeftRadius: 0, borderBottomRightRadius: 0 }];
|
|
730
839
|
const labelStyle = { fontFamily: labelFontFamily, color: rowColor, fontWeight: selected ? "bold" : "normal" };
|
|
731
|
-
return /* @__PURE__ */
|
|
732
|
-
option.icon && /* @__PURE__ */
|
|
733
|
-
/* @__PURE__ */
|
|
840
|
+
return /* @__PURE__ */ jsx12(TouchableRipple2, { onPress: () => section.onChange(selected ? section.value.filter((v) => v !== option.value) : [...section.value, option.value]), style: itemStyle, children: /* @__PURE__ */ jsxs11(View10, { style: styles10.itemRow, children: [
|
|
841
|
+
option.icon && /* @__PURE__ */ jsx12(Icon4, { source: option.icon, size: MENU_ITEM_ICON_SIZE, color: rowColor }),
|
|
842
|
+
/* @__PURE__ */ jsx12(Text8, { variant: "labelLarge", style: [styles10.itemLabelFlex, labelStyle], children: option.label })
|
|
734
843
|
] }) }, option.value);
|
|
735
844
|
}),
|
|
736
|
-
section.allClear && /* @__PURE__ */
|
|
845
|
+
section.allClear && /* @__PURE__ */ jsx12(TouchableRipple2, { onPress: () => section.onChange(allSelected ? [] : section.options.map((o) => o.value)), style: styles10.item, children: /* @__PURE__ */ jsx12(Text8, { variant: "labelLarge", style: [styles10.allClearLabel, { fontFamily: labelFontFamily, color: accentColor }], children: allSelected ? allClearLabels.clear : allClearLabels.all }) })
|
|
737
846
|
] });
|
|
738
847
|
}
|
|
739
|
-
var
|
|
848
|
+
var styles10 = StyleSheet11.create({
|
|
740
849
|
allClearLabel: {
|
|
741
850
|
fontWeight: "bold",
|
|
742
851
|
textAlign: "center"
|
|
@@ -753,7 +862,7 @@ var styles7 = StyleSheet8.create({
|
|
|
753
862
|
zIndex: 100
|
|
754
863
|
},
|
|
755
864
|
divider: {
|
|
756
|
-
height:
|
|
865
|
+
height: StyleSheet11.hairlineWidth,
|
|
757
866
|
marginVertical: 4
|
|
758
867
|
},
|
|
759
868
|
item: {
|
|
@@ -806,24 +915,24 @@ var styles7 = StyleSheet8.create({
|
|
|
806
915
|
});
|
|
807
916
|
|
|
808
917
|
// src/ControlSchemePicker.tsx
|
|
809
|
-
import { jsx as
|
|
810
|
-
function ControlSchemePicker({ id, host, value, onChange, options, takenValue, accentColor, mutedColor, onAccentColor, dark, align, labelFontFamily }) {
|
|
918
|
+
import { jsx as jsx13 } from "react/jsx-runtime";
|
|
919
|
+
function ControlSchemePicker({ id, host, value, onChange, options, takenValue, accentColor, mutedColor, onAccentColor, dark, align, alignOverride, rotation, labelFontFamily }) {
|
|
811
920
|
const isTouchPrimary = useIsTouchPrimaryDevice2();
|
|
812
921
|
if (Platform3.OS !== "web" || isTouchPrimary) return null;
|
|
813
|
-
return /* @__PURE__ */
|
|
922
|
+
return /* @__PURE__ */ jsx13(SectionedDropdown, { id, host, icon: "keyboard-outline", accessibilityLabel: "Control scheme", sections: [{ kind: "single", id: "controls", options, value, onChange, takenValue }], accentColor, mutedColor, onAccentColor, dark, align, alignOverride, rotation, labelFontFamily });
|
|
814
923
|
}
|
|
815
924
|
|
|
816
925
|
// src/CornerActionButtons.tsx
|
|
817
926
|
import { IconButton as IconButton3 } from "@rific/feedback-press";
|
|
818
|
-
import { StyleSheet as
|
|
819
|
-
import { Fragment as
|
|
927
|
+
import { StyleSheet as StyleSheet12 } from "react-native";
|
|
928
|
+
import { Fragment as Fragment5, jsx as jsx14, jsxs as jsxs12 } from "react/jsx-runtime";
|
|
820
929
|
function CornerActionButtons({ onBack, onSettings, fg, insets, backIcon = "arrow-left", backLabel = "Back" }) {
|
|
821
|
-
return /* @__PURE__ */
|
|
822
|
-
/* @__PURE__ */
|
|
823
|
-
/* @__PURE__ */
|
|
930
|
+
return /* @__PURE__ */ jsxs12(Fragment5, { children: [
|
|
931
|
+
/* @__PURE__ */ jsx14(IconButton3, { icon: backIcon, iconColor: fg, size: 24, style: [styles11.back, { top: 8 + insets.top, left: 8 + insets.left }], onPress: onBack, accessibilityLabel: backLabel }),
|
|
932
|
+
/* @__PURE__ */ jsx14(IconButton3, { icon: "cog", iconColor: fg, size: 24, style: [styles11.topRight, { top: 8 + insets.top, right: 8 + insets.right }], onPress: onSettings, accessibilityLabel: "Settings" })
|
|
824
933
|
] });
|
|
825
934
|
}
|
|
826
|
-
var
|
|
935
|
+
var styles11 = StyleSheet12.create({
|
|
827
936
|
back: {
|
|
828
937
|
position: "absolute"
|
|
829
938
|
},
|
|
@@ -833,22 +942,22 @@ var styles8 = StyleSheet9.create({
|
|
|
833
942
|
});
|
|
834
943
|
|
|
835
944
|
// src/CornerStatusBadges.tsx
|
|
836
|
-
import { StyleSheet as
|
|
945
|
+
import { StyleSheet as StyleSheet13, View as View11 } from "react-native";
|
|
837
946
|
import { Icon as Icon5 } from "react-native-paper";
|
|
838
|
-
import { Fragment as
|
|
947
|
+
import { Fragment as Fragment6, jsx as jsx15, jsxs as jsxs13 } from "react/jsx-runtime";
|
|
839
948
|
var BADGE_SIZE = 30;
|
|
840
949
|
function StatusBadge({ icon }) {
|
|
841
|
-
return /* @__PURE__ */
|
|
950
|
+
return /* @__PURE__ */ jsx15(View11, { style: styles12.badge, children: icon && /* @__PURE__ */ jsx15(Icon5, { source: icon, size: 16, color: "rgba(255,255,255,0.85)" }) });
|
|
842
951
|
}
|
|
843
952
|
function CornerStatusBadges({ orientationMode, p1OnRight, p1, p2 }) {
|
|
844
953
|
const p1OnRightSide = orientationMode === "sideBySide" && p1OnRight;
|
|
845
954
|
const p2OnLeftSide = orientationMode === "sideBySide" && !p1OnRight;
|
|
846
|
-
return /* @__PURE__ */
|
|
847
|
-
p1 && /* @__PURE__ */
|
|
848
|
-
p2 && /* @__PURE__ */
|
|
955
|
+
return /* @__PURE__ */ jsxs13(Fragment6, { children: [
|
|
956
|
+
p1 && /* @__PURE__ */ jsx15(View11, { pointerEvents: "none", style: p1OnRightSide ? styles12.bottomRight : styles12.bottomLeft, children: /* @__PURE__ */ jsx15(StatusBadge, { icon: p1.icon }) }),
|
|
957
|
+
p2 && /* @__PURE__ */ jsx15(View11, { pointerEvents: "none", style: p2OnLeftSide ? styles12.topLeft : styles12.topRight, children: /* @__PURE__ */ jsx15(StatusBadge, { icon: p2.icon }) })
|
|
849
958
|
] });
|
|
850
959
|
}
|
|
851
|
-
var
|
|
960
|
+
var styles12 = StyleSheet13.create({
|
|
852
961
|
badge: {
|
|
853
962
|
alignItems: "center",
|
|
854
963
|
backgroundColor: "rgba(0,0,0,0.28)",
|
|
@@ -870,9 +979,9 @@ var styles9 = StyleSheet10.create({
|
|
|
870
979
|
import { defaultColors, getContrastColor } from "@rific/auto-paper";
|
|
871
980
|
import { TouchableRipple as TouchableRipple3 } from "@rific/feedback-press";
|
|
872
981
|
import { clamp, useRotation as useRotation4 } from "@tastic/core";
|
|
873
|
-
import { ScrollView as ScrollView4, StyleSheet as
|
|
874
|
-
import { Icon as Icon6, Text as
|
|
875
|
-
import { jsx as
|
|
982
|
+
import { ScrollView as ScrollView4, StyleSheet as StyleSheet14, useWindowDimensions as useWindowDimensions3, View as View12 } from "react-native";
|
|
983
|
+
import { Icon as Icon6, Text as Text9 } from "react-native-paper";
|
|
984
|
+
import { jsx as jsx16, jsxs as jsxs14 } from "react/jsx-runtime";
|
|
876
985
|
var EMOJI_PATTERN = /\p{Extended_Pictographic}/u;
|
|
877
986
|
var DEFAULT_SIZE = 48;
|
|
878
987
|
var SWATCH_SIZE = 28;
|
|
@@ -885,31 +994,37 @@ var SCREEN_MARGIN = 40;
|
|
|
885
994
|
function widthForColumns(columns) {
|
|
886
995
|
return SWATCHES_BORDER_WIDTH * 2 + SWATCHES_PADDING * 2 + SWATCH_SIZE * columns + SWATCHES_GAP * (columns - 1);
|
|
887
996
|
}
|
|
888
|
-
function
|
|
997
|
+
function getInlineColorPickerContentSize(swatchCount, windowWidth, columns) {
|
|
998
|
+
const autoColumns = clamp(Math.floor((windowWidth - 2 * SCREEN_MARGIN + SWATCHES_GAP) / (SWATCH_SIZE + SWATCHES_GAP)), MIN_COLUMNS, MAX_COLUMNS);
|
|
999
|
+
const resolvedColumns = columns ?? autoColumns;
|
|
1000
|
+
const width = widthForColumns(resolvedColumns);
|
|
1001
|
+
const rows = Math.ceil(swatchCount / resolvedColumns);
|
|
1002
|
+
const height = SWATCHES_BORDER_WIDTH * 2 + SWATCHES_PADDING * 2 + SWATCH_SIZE * rows + SWATCHES_GAP * (rows - 1);
|
|
1003
|
+
return { width, height };
|
|
1004
|
+
}
|
|
1005
|
+
function InlineColorPicker({ id, host, value, onChange, previewValue, swatches = defaultColors, takenValue, allowSwapTaken, dark, align: forcedAlign, alignOverride, rotation: rotationOverride, icon = "palette", tag, labelFontFamily = MONO_FONT, autoDismiss = true, columns, size = DEFAULT_SIZE }) {
|
|
889
1006
|
const ambientRotation = useRotation4();
|
|
890
1007
|
const rotation = rotationOverride ?? ambientRotation;
|
|
891
1008
|
const menuBg = dark ? "#000000" : "#FFFFFF";
|
|
892
1009
|
const { width: windowWidth } = useWindowDimensions3();
|
|
893
|
-
const
|
|
894
|
-
const resolvedColumns = columns ?? autoColumns;
|
|
895
|
-
const swatchesWidth = widthForColumns(resolvedColumns);
|
|
896
|
-
const swatchRows = Math.ceil(swatches.length / resolvedColumns);
|
|
897
|
-
const swatchesHeight = SWATCHES_BORDER_WIDTH * 2 + SWATCHES_PADDING * 2 + SWATCH_SIZE * swatchRows + SWATCHES_GAP * (swatchRows - 1);
|
|
1010
|
+
const { width: swatchesWidth, height: swatchesHeight } = getInlineColorPickerContentSize(swatches.length, windowWidth, columns);
|
|
898
1011
|
const open = host.openId === id;
|
|
899
|
-
const
|
|
900
|
-
const
|
|
1012
|
+
const auto = useAutoAlign(open, swatchesWidth, swatchesHeight, rotation);
|
|
1013
|
+
const placement = alignOverride ?? auto;
|
|
1014
|
+
const { maxHeight, measured, triggerRef, verticalAlign } = placement;
|
|
1015
|
+
const align = forcedAlign ?? placement.align;
|
|
901
1016
|
const displayFor = previewValue ?? ((hex) => hex);
|
|
902
1017
|
const displayValue = displayFor(value);
|
|
903
1018
|
const contrastColor = getContrastColor(displayValue);
|
|
904
1019
|
const tagFontSize = size * (tag && EMOJI_PATTERN.test(tag) ? 0.6 : 0.4);
|
|
905
|
-
return /* @__PURE__ */
|
|
906
|
-
/* @__PURE__ */
|
|
907
|
-
/* @__PURE__ */
|
|
1020
|
+
return /* @__PURE__ */ jsxs14(View12, { style: [styles13.anchor, open && styles13.anchorOpen], children: [
|
|
1021
|
+
/* @__PURE__ */ jsx16(TouchableRipple3, { onPress: () => host.toggle(id), borderless: true, style: [styles13.trigger, { backgroundColor: displayValue, borderRadius: size / 2, height: size, width: size }], children: /* @__PURE__ */ jsx16(View12, { ref: triggerRef, collapsable: false, style: styles13.triggerMeasure, children: tag ? /* @__PURE__ */ jsx16(Text9, { style: [styles13.tagLabel, { color: contrastColor, fontFamily: labelFontFamily, fontSize: tagFontSize }], numberOfLines: 1, adjustsFontSizeToFit: true, children: tag }) : /* @__PURE__ */ jsx16(Icon6, { source: icon, size: size * 0.6, color: contrastColor }) }) }),
|
|
1022
|
+
/* @__PURE__ */ jsx16(PopoverBody, { visible: open && measured, align, verticalAlign, caretColor: menuBg, caretBorderColor: displayValue, caretBorderWidth: SWATCHES_BORDER_WIDTH, triggerSize: size, children: /* @__PURE__ */ jsx16(ScrollView4, { style: [styles13.swatches, { backgroundColor: menuBg, borderColor: displayValue, width: swatchesWidth, maxHeight }], contentContainerStyle: styles13.swatchesContent, showsVerticalScrollIndicator: false, children: swatches.map((swatch) => {
|
|
908
1023
|
const selected = swatch.value.toLowerCase() === value.toLowerCase();
|
|
909
1024
|
const taken = !selected && !!takenValue && swatch.value.toLowerCase() === takenValue.toLowerCase();
|
|
910
1025
|
const swappable = taken && allowSwapTaken;
|
|
911
1026
|
const swatchDisplay = displayFor(swatch.value);
|
|
912
|
-
return /* @__PURE__ */
|
|
1027
|
+
return /* @__PURE__ */ jsx16(
|
|
913
1028
|
TouchableRipple3,
|
|
914
1029
|
{
|
|
915
1030
|
disabled: taken && !swappable,
|
|
@@ -918,15 +1033,15 @@ function InlineColorPicker({ id, host, value, onChange, previewValue, swatches =
|
|
|
918
1033
|
if (autoDismiss) host.close();
|
|
919
1034
|
},
|
|
920
1035
|
borderless: true,
|
|
921
|
-
style: [
|
|
922
|
-
children: selected ? /* @__PURE__ */
|
|
1036
|
+
style: [styles13.swatch, { backgroundColor: swatchDisplay }, selected && styles13.swatchSelected, taken && !swappable && styles13.swatchTaken],
|
|
1037
|
+
children: selected ? /* @__PURE__ */ jsx16(Icon6, { source: "check", size: 16, color: getContrastColor(swatchDisplay) }) : swappable ? /* @__PURE__ */ jsx16(Icon6, { source: "swap-horizontal", size: 16, color: getContrastColor(swatchDisplay) }) : taken ? /* @__PURE__ */ jsx16(Icon6, { source: "close", size: 16, color: getContrastColor(swatchDisplay) }) : /* @__PURE__ */ jsx16(View12, {})
|
|
923
1038
|
},
|
|
924
1039
|
swatch.value
|
|
925
1040
|
);
|
|
926
1041
|
}) }) })
|
|
927
1042
|
] });
|
|
928
1043
|
}
|
|
929
|
-
var
|
|
1044
|
+
var styles13 = StyleSheet14.create({
|
|
930
1045
|
anchor: {
|
|
931
1046
|
position: "relative"
|
|
932
1047
|
},
|
|
@@ -1000,9 +1115,9 @@ var styles10 = StyleSheet11.create({
|
|
|
1000
1115
|
// src/LabeledDropdown.tsx
|
|
1001
1116
|
import { getContrastColor as getContrastColor2 } from "@rific/auto-paper";
|
|
1002
1117
|
import { TouchableRipple as TouchableRipple4 } from "@rific/feedback-press";
|
|
1003
|
-
import { ScrollView as ScrollView5, StyleSheet as
|
|
1004
|
-
import { Icon as Icon7, Text as
|
|
1005
|
-
import { jsx as
|
|
1118
|
+
import { ScrollView as ScrollView5, StyleSheet as StyleSheet15, View as View13 } from "react-native";
|
|
1119
|
+
import { Icon as Icon7, Text as Text10 } from "react-native-paper";
|
|
1120
|
+
import { jsx as jsx17, jsxs as jsxs15 } from "react/jsx-runtime";
|
|
1006
1121
|
var TRIGGER_HEIGHT = 28;
|
|
1007
1122
|
var POPOVER_WIDTH = 180;
|
|
1008
1123
|
var ROW_HEIGHT = 36;
|
|
@@ -1025,22 +1140,22 @@ function LabeledDropdown({ id, host, options, value, onChange, color, dark, alig
|
|
|
1025
1140
|
onChange(option.value);
|
|
1026
1141
|
host.close();
|
|
1027
1142
|
};
|
|
1028
|
-
return /* @__PURE__ */
|
|
1029
|
-
/* @__PURE__ */
|
|
1030
|
-
/* @__PURE__ */
|
|
1031
|
-
/* @__PURE__ */
|
|
1143
|
+
return /* @__PURE__ */ jsxs15(View13, { style: [styles14.anchor, open && styles14.anchorOpen], children: [
|
|
1144
|
+
/* @__PURE__ */ jsx17(TouchableRipple4, { onPress: () => host.toggle(id), style: styles14.trigger, children: /* @__PURE__ */ jsxs15(View13, { ref: triggerRef, collapsable: false, style: styles14.triggerInner, children: [
|
|
1145
|
+
/* @__PURE__ */ jsx17(Text10, { style: [styles14.triggerLabel, { color }], numberOfLines: 1, children: (selected?.label ?? "").toUpperCase() }),
|
|
1146
|
+
/* @__PURE__ */ jsx17(Icon7, { source: "menu-down", size: 16, color })
|
|
1032
1147
|
] }) }),
|
|
1033
|
-
/* @__PURE__ */
|
|
1148
|
+
/* @__PURE__ */ jsx17(PopoverBody, { visible: open && measured, align, verticalAlign, caretColor: menuBg, caretBorderColor: color, caretBorderWidth: 2, triggerSize: TRIGGER_HEIGHT, children: /* @__PURE__ */ jsx17(ScrollView5, { style: [styles14.menu, { backgroundColor: menuBg, borderColor: color, width: POPOVER_WIDTH, maxHeight }], contentContainerStyle: styles14.menuContent, showsVerticalScrollIndicator: false, children: options.map((option) => {
|
|
1034
1149
|
const isSelected = option.value === value;
|
|
1035
1150
|
const onColor = getContrastColor2(color);
|
|
1036
|
-
return /* @__PURE__ */
|
|
1037
|
-
option.icon && /* @__PURE__ */
|
|
1038
|
-
/* @__PURE__ */
|
|
1151
|
+
return /* @__PURE__ */ jsx17(TouchableRipple4, { onPress: () => handleSelect(option), style: [styles14.row, isSelected && { backgroundColor: color }], children: /* @__PURE__ */ jsxs15(View13, { style: styles14.rowInner, children: [
|
|
1152
|
+
option.icon && /* @__PURE__ */ jsx17(Icon7, { source: option.icon, size: 18, color: isSelected ? onColor : fg }),
|
|
1153
|
+
/* @__PURE__ */ jsx17(Text10, { style: [styles14.rowLabel, { color: isSelected ? onColor : fg }], numberOfLines: 1, children: option.label })
|
|
1039
1154
|
] }) }, option.value);
|
|
1040
1155
|
}) }) })
|
|
1041
1156
|
] });
|
|
1042
1157
|
}
|
|
1043
|
-
var
|
|
1158
|
+
var styles14 = StyleSheet15.create({
|
|
1044
1159
|
anchor: {
|
|
1045
1160
|
position: "relative"
|
|
1046
1161
|
},
|
|
@@ -1097,26 +1212,23 @@ function loadSkiaWeb() {
|
|
|
1097
1212
|
return Promise.resolve();
|
|
1098
1213
|
}
|
|
1099
1214
|
|
|
1100
|
-
// src/
|
|
1101
|
-
import {
|
|
1102
|
-
import {
|
|
1103
|
-
|
|
1104
|
-
if (!active) return null;
|
|
1105
|
-
return /* @__PURE__ */ jsx14(Pressable, { accessibilityLabel: "Dismiss", accessibilityRole: "button", onPress, style: [StyleSheet13.absoluteFill, style] });
|
|
1106
|
-
}
|
|
1215
|
+
// src/PlayerSetupPanel.tsx
|
|
1216
|
+
import { ProfilePicker } from "@tastic/profile";
|
|
1217
|
+
import { StyleSheet as StyleSheet17, View as View14 } from "react-native";
|
|
1218
|
+
import { Text as Text12 } from "react-native-paper";
|
|
1107
1219
|
|
|
1108
1220
|
// src/ReadyButton.tsx
|
|
1109
1221
|
import { TouchableRipple as TouchableRipple5 } from "@rific/feedback-press";
|
|
1110
|
-
import { StyleSheet as
|
|
1111
|
-
import { Text as
|
|
1112
|
-
import { jsx as
|
|
1222
|
+
import { StyleSheet as StyleSheet16 } from "react-native";
|
|
1223
|
+
import { Text as Text11 } from "react-native-paper";
|
|
1224
|
+
import { jsx as jsx18 } from "react/jsx-runtime";
|
|
1113
1225
|
function ReadyButton({ color, ready, onToggleReady, style, labelFontFamily = MONO_FONT }) {
|
|
1114
|
-
const readyButtonStyle = [
|
|
1226
|
+
const readyButtonStyle = [styles15.readyButton, { borderColor: color }, ready && { backgroundColor: color }, style];
|
|
1115
1227
|
const labelTextStyle = { fontFamily: labelFontFamily, fontWeight: "bold" };
|
|
1116
1228
|
const labelColorStyle = { color: ready ? "#000000" : color };
|
|
1117
|
-
return /* @__PURE__ */
|
|
1229
|
+
return /* @__PURE__ */ jsx18(TouchableRipple5, { onPress: onToggleReady, borderless: true, style: readyButtonStyle, children: /* @__PURE__ */ jsx18(Text11, { variant: "labelLarge", style: [labelTextStyle, labelColorStyle], children: ready ? "READY \u2713" : "READY?" }) });
|
|
1118
1230
|
}
|
|
1119
|
-
var
|
|
1231
|
+
var styles15 = StyleSheet16.create({
|
|
1120
1232
|
readyButton: {
|
|
1121
1233
|
alignItems: "center",
|
|
1122
1234
|
borderRadius: 12,
|
|
@@ -1128,22 +1240,97 @@ var styles12 = StyleSheet14.create({
|
|
|
1128
1240
|
}
|
|
1129
1241
|
});
|
|
1130
1242
|
|
|
1243
|
+
// src/usePopoverHost.ts
|
|
1244
|
+
import { useCallback as useCallback3, useState as useState5 } from "react";
|
|
1245
|
+
function usePopoverHost() {
|
|
1246
|
+
const [openId, setOpenId] = useState5(null);
|
|
1247
|
+
const toggle = useCallback3((id) => {
|
|
1248
|
+
setOpenId((prev) => prev === id ? null : id);
|
|
1249
|
+
}, []);
|
|
1250
|
+
const close = useCallback3(() => setOpenId(null), []);
|
|
1251
|
+
return { openId, toggle, close };
|
|
1252
|
+
}
|
|
1253
|
+
|
|
1254
|
+
// src/PlayerSetupPanel.tsx
|
|
1255
|
+
import { jsx as jsx19, jsxs as jsxs16 } from "react/jsx-runtime";
|
|
1256
|
+
function getColorPopoverId(idPrefix) {
|
|
1257
|
+
return `${idPrefix}-color`;
|
|
1258
|
+
}
|
|
1259
|
+
function getCpuDifficultyPopoverId(idPrefix) {
|
|
1260
|
+
return `${idPrefix}-difficulty`;
|
|
1261
|
+
}
|
|
1262
|
+
function PlayerSetupPanel({ idPrefix, host, label, labelFontFamily, color, onColorChange, swatches, takenColor, allowSwapTaken, colorAlignOverride, colorRotation, isHuman, secondPicker, secondPickerId, ready, onToggleReady, dark, showReadyButton = true, profiles, selectedProfileId, takenProfileId, guestLabel, onProfileSelect, onManageProfiles, cpuDifficulty, cpuDifficultyOptions, onCpuDifficultyChange, cpuDifficultyAlignOverride, humanIcon = "face-man", cpuIcon = "robot" }) {
|
|
1263
|
+
const ownHost = usePopoverHost();
|
|
1264
|
+
const popover = host ?? ownHost;
|
|
1265
|
+
const ownPopoverOpen = popover.openId?.startsWith(`${idPrefix}-`) ?? false;
|
|
1266
|
+
const pickerRowPopoverOpen = popover.openId === getColorPopoverId(idPrefix) || secondPickerId !== void 0 && popover.openId === secondPickerId;
|
|
1267
|
+
const showProfilePicker = isHuman && profiles !== void 0 && !!onProfileSelect;
|
|
1268
|
+
const showCpuDifficulty = !isHuman && cpuDifficulty !== void 0 && cpuDifficultyOptions !== void 0 && !!onCpuDifficultyChange;
|
|
1269
|
+
const selectedProfile = profiles?.find((p) => p.id === selectedProfileId) ?? null;
|
|
1270
|
+
return /* @__PURE__ */ jsxs16(View14, { style: [styles16.panel, ownPopoverOpen && styles16.panelOpen], children: [
|
|
1271
|
+
showProfilePicker ? /* @__PURE__ */ jsx19(ProfilePicker, { idPrefix, host: popover, profiles, selectedId: selectedProfileId ?? null, takenId: takenProfileId, color, dark, guestLabel: guestLabel ?? "GUEST", onSelect: (profile) => onProfileSelect?.(profile), onManage: onManageProfiles }) : showCpuDifficulty ? /* @__PURE__ */ jsx19(LabeledDropdown, { id: getCpuDifficultyPopoverId(idPrefix), host: popover, options: cpuDifficultyOptions, value: cpuDifficulty, onChange: onCpuDifficultyChange, color, dark, alignOverride: cpuDifficultyAlignOverride }) : label && /* @__PURE__ */ jsx19(Text12, { variant: "labelSmall", style: { color, fontFamily: labelFontFamily }, children: label }),
|
|
1272
|
+
/* @__PURE__ */ jsxs16(View14, { style: [styles16.pickerRow, pickerRowPopoverOpen && styles16.pickerRowOpen], children: [
|
|
1273
|
+
/* @__PURE__ */ jsx19(InlineColorPicker, { id: getColorPopoverId(idPrefix), host: popover, value: color, onChange: onColorChange, swatches, takenValue: takenColor, allowSwapTaken, alignOverride: colorAlignOverride, rotation: colorRotation, dark, tag: isHuman ? selectedProfile?.tag : void 0, icon: isHuman ? humanIcon : cpuIcon }),
|
|
1274
|
+
secondPicker
|
|
1275
|
+
] }),
|
|
1276
|
+
isHuman && showReadyButton && onToggleReady && /* @__PURE__ */ jsx19(ReadyButton, { color, ready: ready ?? false, onToggleReady })
|
|
1277
|
+
] });
|
|
1278
|
+
}
|
|
1279
|
+
var styles16 = StyleSheet17.create({
|
|
1280
|
+
panel: {
|
|
1281
|
+
alignItems: "center",
|
|
1282
|
+
gap: 12
|
|
1283
|
+
},
|
|
1284
|
+
// See SectionedDropdown's anchorOpen comment — this panel is typically a sibling of another
|
|
1285
|
+
// panel (and/or a shared-controls row), so a popover escaping this panel's bounds needs the panel
|
|
1286
|
+
// itself elevated, not just the popover content, to paint above a later sibling.
|
|
1287
|
+
panelOpen: {
|
|
1288
|
+
zIndex: 100
|
|
1289
|
+
},
|
|
1290
|
+
// Same gap as `panel`'s own vertical rhythm, reused horizontally — the color picker and (when
|
|
1291
|
+
// present) secondPicker sit side by side within this row instead of stacked in the panel's own
|
|
1292
|
+
// column.
|
|
1293
|
+
pickerRow: {
|
|
1294
|
+
alignItems: "center",
|
|
1295
|
+
flexDirection: "row",
|
|
1296
|
+
gap: 12
|
|
1297
|
+
},
|
|
1298
|
+
// A popover is an absolutely-positioned sibling of its own trigger — so a tall one (the color
|
|
1299
|
+
// swatch grid) can extend down far enough to overlap the ReadyButton below, which paints on top of
|
|
1300
|
+
// it by default DOM order since it's a later sibling within `panel`. `panel`'s own panelOpen
|
|
1301
|
+
// elevation only helps this panel paint above OTHER panels (see its own comment) — it does nothing
|
|
1302
|
+
// for stacking *within* this panel, since React Native Web gives each View its own stacking
|
|
1303
|
+
// context. This is what actually fixes that: elevate pickerRow itself above its own later sibling
|
|
1304
|
+
// whenever one of its own popovers is open.
|
|
1305
|
+
pickerRowOpen: {
|
|
1306
|
+
zIndex: 100
|
|
1307
|
+
}
|
|
1308
|
+
});
|
|
1309
|
+
|
|
1310
|
+
// src/PressAwayOverlay.tsx
|
|
1311
|
+
import { Pressable, StyleSheet as StyleSheet18 } from "react-native";
|
|
1312
|
+
import { jsx as jsx20 } from "react/jsx-runtime";
|
|
1313
|
+
function PressAwayOverlay({ active, onPress, style }) {
|
|
1314
|
+
if (!active) return null;
|
|
1315
|
+
return /* @__PURE__ */ jsx20(Pressable, { accessibilityLabel: "Dismiss", accessibilityRole: "button", onPress, style: [StyleSheet18.absoluteFill, style] });
|
|
1316
|
+
}
|
|
1317
|
+
|
|
1131
1318
|
// src/SharedActionBand.tsx
|
|
1132
1319
|
import { IconButton as IconButton4 } from "@rific/feedback-press";
|
|
1133
|
-
import { StyleSheet as
|
|
1134
|
-
import { jsx as
|
|
1320
|
+
import { StyleSheet as StyleSheet19, View as View15 } from "react-native";
|
|
1321
|
+
import { jsx as jsx21, jsxs as jsxs17 } from "react/jsx-runtime";
|
|
1135
1322
|
function SharedActionBand({ onBack, onSettings, onRandomize, onReset, fg, popoverOpen, children }) {
|
|
1136
|
-
return /* @__PURE__ */
|
|
1137
|
-
/* @__PURE__ */
|
|
1138
|
-
/* @__PURE__ */
|
|
1139
|
-
onRandomize && /* @__PURE__ */
|
|
1140
|
-
onReset && /* @__PURE__ */
|
|
1141
|
-
/* @__PURE__ */
|
|
1323
|
+
return /* @__PURE__ */ jsxs17(View15, { style: [styles17.column, popoverOpen && styles17.columnOpen], children: [
|
|
1324
|
+
/* @__PURE__ */ jsxs17(View15, { style: styles17.actionsRow, children: [
|
|
1325
|
+
/* @__PURE__ */ jsx21(IconButton4, { icon: "arrow-left", iconColor: fg, size: 20, onPress: onBack, accessibilityLabel: "Back" }),
|
|
1326
|
+
onRandomize && /* @__PURE__ */ jsx21(IconButton4, { icon: "dice-multiple", iconColor: fg, size: 18, onPress: onRandomize, accessibilityLabel: "Randomize match settings" }),
|
|
1327
|
+
onReset && /* @__PURE__ */ jsx21(IconButton4, { icon: "restore", iconColor: fg, size: 18, onPress: onReset, accessibilityLabel: "Reset match settings to defaults" }),
|
|
1328
|
+
/* @__PURE__ */ jsx21(IconButton4, { icon: "cog", iconColor: fg, size: 20, onPress: onSettings, accessibilityLabel: "Settings" })
|
|
1142
1329
|
] }),
|
|
1143
1330
|
children
|
|
1144
1331
|
] });
|
|
1145
1332
|
}
|
|
1146
|
-
var
|
|
1333
|
+
var styles17 = StyleSheet19.create({
|
|
1147
1334
|
actionsRow: {
|
|
1148
1335
|
alignItems: "center",
|
|
1149
1336
|
flexDirection: "row",
|
|
@@ -1158,83 +1345,109 @@ var styles13 = StyleSheet15.create({
|
|
|
1158
1345
|
}
|
|
1159
1346
|
});
|
|
1160
1347
|
|
|
1161
|
-
// src/
|
|
1162
|
-
import {
|
|
1163
|
-
import { StyleSheet as
|
|
1164
|
-
import {
|
|
1165
|
-
import { jsx as
|
|
1166
|
-
|
|
1167
|
-
|
|
1168
|
-
|
|
1169
|
-
|
|
1170
|
-
return /* @__PURE__ */ jsxs13(View13, { style: styles14.row, children: [
|
|
1171
|
-
/* @__PURE__ */ jsx17(Text9, { variant: "bodyMedium", style: { color: fgMuted }, children: label }),
|
|
1172
|
-
/* @__PURE__ */ jsx17(Text9, { variant: "bodyMedium", style: [styles14.value, { color: fg }], children: value })
|
|
1173
|
-
] });
|
|
1348
|
+
// src/StaggeredWord.tsx
|
|
1349
|
+
import { useEffect as useEffect2 } from "react";
|
|
1350
|
+
import { StyleSheet as StyleSheet20, View as View16 } from "react-native";
|
|
1351
|
+
import Animated, { Easing, useAnimatedStyle, useSharedValue, withDelay, withTiming } from "react-native-reanimated";
|
|
1352
|
+
import { jsx as jsx22 } from "react/jsx-runtime";
|
|
1353
|
+
var STAGGER_MS = 45;
|
|
1354
|
+
var LETTER_DURATION_MS = 320;
|
|
1355
|
+
function getStaggeredWordDuration(letterCount) {
|
|
1356
|
+
return (letterCount - 1) * STAGGER_MS + LETTER_DURATION_MS;
|
|
1174
1357
|
}
|
|
1175
|
-
|
|
1176
|
-
|
|
1177
|
-
|
|
1178
|
-
|
|
1179
|
-
|
|
1180
|
-
},
|
|
1181
|
-
|
|
1182
|
-
|
|
1183
|
-
|
|
1184
|
-
});
|
|
1185
|
-
|
|
1186
|
-
// src/StatSection.tsx
|
|
1187
|
-
import { useAutoPaperTheme as useAutoPaperTheme6 } from "@rific/auto-paper";
|
|
1188
|
-
import { StyleSheet as StyleSheet17, View as View14 } from "react-native";
|
|
1189
|
-
import { Text as Text10 } from "react-native-paper";
|
|
1190
|
-
import { jsx as jsx18, jsxs as jsxs14 } from "react/jsx-runtime";
|
|
1191
|
-
function StatSection({ label, fg: fgOverride, sectionBg: sectionBgOverride, children }) {
|
|
1192
|
-
const { dark } = useAutoPaperTheme6();
|
|
1193
|
-
const fg = fgOverride ?? (dark ? "#FFFFFF" : "#000000");
|
|
1194
|
-
const sectionBg = sectionBgOverride ?? (dark ? "rgba(255,255,255,0.06)" : "rgba(0,0,0,0.04)");
|
|
1195
|
-
return /* @__PURE__ */ jsxs14(View14, { style: [styles15.section, { backgroundColor: sectionBg }], children: [
|
|
1196
|
-
/* @__PURE__ */ jsx18(Text10, { variant: "labelMedium", style: [styles15.label, { color: fg }], children: label }),
|
|
1197
|
-
children
|
|
1198
|
-
] });
|
|
1358
|
+
function AnimatedLetter({ char, index, color, reducedMotion, fontFamily, fontSize, lineHeight, fontWeight, letterSpacing }) {
|
|
1359
|
+
const progress = useSharedValue(reducedMotion ? 1 : 0);
|
|
1360
|
+
useEffect2(() => {
|
|
1361
|
+
if (reducedMotion) return;
|
|
1362
|
+
progress.value = withDelay(index * STAGGER_MS, withTiming(1, { duration: LETTER_DURATION_MS, easing: Easing.out(Easing.back(1.5)) }));
|
|
1363
|
+
}, [reducedMotion]);
|
|
1364
|
+
const style = useAnimatedStyle(() => ({
|
|
1365
|
+
opacity: progress.value,
|
|
1366
|
+
transform: [{ translateY: (1 - progress.value) * 12 }, { scale: 0.85 + progress.value * 0.15 }]
|
|
1367
|
+
}));
|
|
1368
|
+
return /* @__PURE__ */ jsx22(Animated.Text, { allowFontScaling: false, style: [{ color, fontFamily, fontSize, lineHeight, fontWeight, letterSpacing }, style], children: char });
|
|
1199
1369
|
}
|
|
1200
|
-
|
|
1201
|
-
|
|
1202
|
-
|
|
1203
|
-
|
|
1204
|
-
|
|
1205
|
-
|
|
1206
|
-
fontWeight: "bold",
|
|
1207
|
-
letterSpacing: 2
|
|
1208
|
-
},
|
|
1209
|
-
section: {
|
|
1210
|
-
borderRadius: 12,
|
|
1211
|
-
gap: 8,
|
|
1212
|
-
padding: 16
|
|
1370
|
+
function StaggeredWord({ word, color, fontFamily, fontSize, lineHeight, reducedMotion, startIndex = 0, fontWeight = "bold", letterSpacing, style, onLayout }) {
|
|
1371
|
+
return /* @__PURE__ */ jsx22(View16, { style: [styles18.row, style], onLayout, children: word.split("").map((char, i) => /* @__PURE__ */ jsx22(AnimatedLetter, { char, index: startIndex + i, color, reducedMotion, fontFamily, fontSize, lineHeight, fontWeight, letterSpacing }, i)) });
|
|
1372
|
+
}
|
|
1373
|
+
var styles18 = StyleSheet20.create({
|
|
1374
|
+
row: {
|
|
1375
|
+
flexDirection: "row"
|
|
1213
1376
|
}
|
|
1214
1377
|
});
|
|
1215
1378
|
|
|
1216
1379
|
// src/UpdateDialog.tsx
|
|
1217
1380
|
import { useUpdater as useUpdater2 } from "@rific/updater";
|
|
1218
|
-
import { jsx as
|
|
1381
|
+
import { jsx as jsx23 } from "react/jsx-runtime";
|
|
1219
1382
|
function UpdateDialog({ rotation = 0, autoCheck = true, autoPrompt = true, onError }) {
|
|
1220
1383
|
const { manifest, onConfirm, respond } = useUpdateConfirmBridge();
|
|
1221
1384
|
useUpdater2({ autoCheck, autoPrompt, onConfirm, onError });
|
|
1222
1385
|
const date = manifest ? new Date(manifest.createdAt) : null;
|
|
1223
|
-
return /* @__PURE__ */
|
|
1386
|
+
return /* @__PURE__ */ jsx23(ConfirmDialog, { visible: !!manifest, title: "Update Available", message: date ? `Released ${date.toLocaleDateString()} at ${date.toLocaleTimeString()}` : "", confirmLabel: "Restart", cancelLabel: "Later", icon: "update", rotation, onConfirm: () => respond(true), onCancel: () => respond(false) });
|
|
1224
1387
|
}
|
|
1225
1388
|
|
|
1226
|
-
// src/
|
|
1227
|
-
import { useCallback as
|
|
1228
|
-
function
|
|
1229
|
-
const [
|
|
1230
|
-
const
|
|
1231
|
-
|
|
1389
|
+
// src/useQuitConfirmation.ts
|
|
1390
|
+
import { useCallback as useCallback4, useEffect as useEffect3, useRef as useRef3, useState as useState6 } from "react";
|
|
1391
|
+
function useQuitConfirmation(hasProgress, onConfirmedBack) {
|
|
1392
|
+
const [confirmVisible, setConfirmVisible] = useState6(false);
|
|
1393
|
+
const hasProgressRef = useRef3(hasProgress);
|
|
1394
|
+
useEffect3(() => {
|
|
1395
|
+
hasProgressRef.current = hasProgress;
|
|
1396
|
+
});
|
|
1397
|
+
const onConfirmedBackRef = useRef3(onConfirmedBack);
|
|
1398
|
+
useEffect3(() => {
|
|
1399
|
+
onConfirmedBackRef.current = onConfirmedBack;
|
|
1400
|
+
});
|
|
1401
|
+
const requestBack = useCallback4(() => {
|
|
1402
|
+
if (hasProgressRef.current()) setConfirmVisible(true);
|
|
1403
|
+
else onConfirmedBackRef.current();
|
|
1232
1404
|
}, []);
|
|
1233
|
-
const
|
|
1234
|
-
return {
|
|
1405
|
+
const cancelBack = useCallback4(() => setConfirmVisible(false), []);
|
|
1406
|
+
return { confirmVisible, requestBack, cancelBack };
|
|
1407
|
+
}
|
|
1408
|
+
|
|
1409
|
+
// src/useZoneClampedAlign.ts
|
|
1410
|
+
import { useZoneBounds } from "@tastic/split-screen";
|
|
1411
|
+
import { useEffect as useEffect4, useState as useState7 } from "react";
|
|
1412
|
+
import { useWindowDimensions as useWindowDimensions4 } from "react-native";
|
|
1413
|
+
import { useSafeAreaInsets } from "react-native-safe-area-context";
|
|
1414
|
+
var EDGE_MARGIN2 = 12;
|
|
1415
|
+
function useZoneClampedAlign(open, contentWidth, contentHeight, rotation = 0) {
|
|
1416
|
+
const auto = useAutoAlign(open, contentWidth, contentHeight, rotation);
|
|
1417
|
+
const zone = useZoneBounds();
|
|
1418
|
+
const { height: windowHeight } = useWindowDimensions4();
|
|
1419
|
+
const insets = useSafeAreaInsets();
|
|
1420
|
+
const shouldMeasure = open && auto.measured && zone !== null;
|
|
1421
|
+
const [ownBounds, setOwnBounds] = useState7(null);
|
|
1422
|
+
const [prevShouldMeasure, setPrevShouldMeasure] = useState7(shouldMeasure);
|
|
1423
|
+
if (shouldMeasure !== prevShouldMeasure) {
|
|
1424
|
+
setPrevShouldMeasure(shouldMeasure);
|
|
1425
|
+
setOwnBounds(null);
|
|
1426
|
+
}
|
|
1427
|
+
useEffect4(() => {
|
|
1428
|
+
if (!shouldMeasure) return;
|
|
1429
|
+
auto.triggerRef.current?.measureInWindow((_x, y, _width, height) => {
|
|
1430
|
+
const belowShared = zone.zoneSide === "belowShared";
|
|
1431
|
+
const awayRoom = belowShared ? windowHeight - insets.bottom - (y + height) - EDGE_MARGIN2 : y - insets.top - EDGE_MARGIN2;
|
|
1432
|
+
const towardRoom = belowShared ? y - zone.sharedEdgeY - EDGE_MARGIN2 : zone.sharedEdgeY - (y + height) - EDGE_MARGIN2;
|
|
1433
|
+
const useToward = contentHeight > awayRoom && towardRoom > awayRoom;
|
|
1434
|
+
let awaySide = belowShared ? "below" : "above";
|
|
1435
|
+
let towardSide = belowShared ? "above" : "below";
|
|
1436
|
+
if (zone.rotated) {
|
|
1437
|
+
awaySide = awaySide === "above" ? "below" : "above";
|
|
1438
|
+
towardSide = towardSide === "above" ? "below" : "above";
|
|
1439
|
+
}
|
|
1440
|
+
setOwnBounds({ maxHeight: Math.max(useToward ? towardRoom : awayRoom, 0), verticalAlign: useToward ? towardSide : awaySide });
|
|
1441
|
+
});
|
|
1442
|
+
}, [shouldMeasure, zone, auto.triggerRef, contentHeight, windowHeight, insets.top, insets.bottom]);
|
|
1443
|
+
if (!zone) return auto;
|
|
1444
|
+
if (!ownBounds) return { ...auto, measured: false };
|
|
1445
|
+
return { ...auto, maxHeight: ownBounds.maxHeight, measured: auto.measured, verticalAlign: ownBounds.verticalAlign };
|
|
1235
1446
|
}
|
|
1236
1447
|
export {
|
|
1448
|
+
AchievementCatalogSection,
|
|
1237
1449
|
AchievementRow,
|
|
1450
|
+
ActivityStatSection,
|
|
1238
1451
|
BaseSettingsDialog,
|
|
1239
1452
|
BaseStatsScreen,
|
|
1240
1453
|
ConfirmDialog,
|
|
@@ -1247,20 +1460,28 @@ export {
|
|
|
1247
1460
|
LOCKED_BADGE_COLOR,
|
|
1248
1461
|
LabeledDropdown,
|
|
1249
1462
|
MONO_FONT,
|
|
1463
|
+
PlayerSetupPanel,
|
|
1250
1464
|
PopoverBody,
|
|
1251
1465
|
PressAwayOverlay,
|
|
1252
1466
|
ReadyButton,
|
|
1253
1467
|
SectionedDropdown,
|
|
1254
1468
|
SharedActionBand,
|
|
1255
1469
|
SkiaGate,
|
|
1470
|
+
StaggeredWord,
|
|
1256
1471
|
StatRow,
|
|
1257
1472
|
StatSection,
|
|
1258
1473
|
TriggerGaugeHost,
|
|
1259
1474
|
UpdateDialog,
|
|
1475
|
+
getColorPopoverId,
|
|
1476
|
+
getCpuDifficultyPopoverId,
|
|
1477
|
+
getInlineColorPickerContentSize,
|
|
1260
1478
|
getLabeledDropdownContentHeight,
|
|
1261
1479
|
getOverlayCardColors,
|
|
1480
|
+
getStaggeredWordDuration,
|
|
1262
1481
|
loadSkiaWeb,
|
|
1263
1482
|
overlayStyles,
|
|
1264
1483
|
useAutoAlign,
|
|
1265
|
-
usePopoverHost
|
|
1484
|
+
usePopoverHost,
|
|
1485
|
+
useQuitConfirmation,
|
|
1486
|
+
useZoneClampedAlign
|
|
1266
1487
|
};
|