@tastic/hud 0.12.0 → 0.14.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.mjs CHANGED
@@ -1,6 +1,11 @@
1
1
  import {
2
2
  SkiaGate
3
3
  } from "./chunk-XEOFR236.mjs";
4
+ import {
5
+ getOverlayCardColors,
6
+ overlayActionStyles,
7
+ overlayStyles
8
+ } from "./chunk-32U2OIRW.mjs";
4
9
 
5
10
  // src/AchievementCatalogSection.tsx
6
11
  import { useAutoPaperTheme as useAutoPaperTheme2 } from "@rific/auto-paper";
@@ -97,21 +102,65 @@ var styles2 = StyleSheet2.create({
97
102
  }
98
103
  });
99
104
 
100
- // src/StatRow.tsx
101
- import { useAutoPaperTheme as useAutoPaperTheme3 } from "@rific/auto-paper";
105
+ // src/AchievementUnlockList.tsx
106
+ import { getContrastColor, useAutoPaperTheme as useAutoPaperTheme3 } from "@rific/auto-paper";
107
+ import { ProfileChip } from "@tastic/profile";
102
108
  import { StyleSheet as StyleSheet3, View as View2 } from "react-native";
103
- import { Text as Text3 } from "react-native-paper";
109
+ import { Icon as Icon2, Text as Text3 } from "react-native-paper";
104
110
  import { jsx as jsx3, jsxs as jsxs3 } from "react/jsx-runtime";
105
- function StatRow({ label, value, fg: fgOverride, fgMuted: fgMutedOverride }) {
111
+ var AVATAR_SIZE = 18;
112
+ function AchievementUnlockList({ unlocks, seats, owners, tierColors, fg: fgOverride, style }) {
106
113
  const { dark } = useAutoPaperTheme3();
107
114
  const fg = fgOverride ?? (dark ? "#FFFFFF" : "#000000");
115
+ const rows = seats.flatMap((seat) => (unlocks[seat] ?? []).map((achievement) => ({ seat, achievement })));
116
+ if (rows.length === 0) return null;
117
+ return /* @__PURE__ */ jsx3(View2, { style: [styles3.list, style], children: rows.map(({ seat, achievement }) => {
118
+ const owner = owners[seat];
119
+ return /* @__PURE__ */ jsxs3(View2, { style: styles3.row, children: [
120
+ owner.profile ? /* @__PURE__ */ jsx3(ProfileChip, { profile: owner.profile, size: AVATAR_SIZE }) : /* @__PURE__ */ jsx3(View2, { style: [styles3.circle, { backgroundColor: owner.color }], children: /* @__PURE__ */ jsx3(Icon2, { source: "account", size: 10, color: getContrastColor(owner.color) }) }),
121
+ /* @__PURE__ */ jsx3(View2, { style: [styles3.circle, { backgroundColor: tierColors[achievement.tier] }], children: /* @__PURE__ */ jsx3(Icon2, { source: achievement.icon, size: 12, color: "#000000" }) }),
122
+ /* @__PURE__ */ jsx3(Text3, { style: [styles3.label, { color: fg }], numberOfLines: 1, children: achievement.title })
123
+ ] }, `${seat}-${achievement.id}`);
124
+ }) });
125
+ }
126
+ var styles3 = StyleSheet3.create({
127
+ circle: {
128
+ alignItems: "center",
129
+ borderRadius: AVATAR_SIZE / 2,
130
+ height: AVATAR_SIZE,
131
+ justifyContent: "center",
132
+ width: AVATAR_SIZE
133
+ },
134
+ label: {
135
+ flexShrink: 1,
136
+ fontSize: 12,
137
+ fontWeight: "700"
138
+ },
139
+ list: {
140
+ gap: 6
141
+ },
142
+ row: {
143
+ alignItems: "center",
144
+ flexDirection: "row",
145
+ gap: 6
146
+ }
147
+ });
148
+
149
+ // src/StatRow.tsx
150
+ import { useAutoPaperTheme as useAutoPaperTheme4 } from "@rific/auto-paper";
151
+ import { StyleSheet as StyleSheet4, View as View3 } from "react-native";
152
+ import { Text as Text4 } from "react-native-paper";
153
+ import { jsx as jsx4, jsxs as jsxs4 } from "react/jsx-runtime";
154
+ function StatRow({ label, value, fg: fgOverride, fgMuted: fgMutedOverride }) {
155
+ const { dark } = useAutoPaperTheme4();
156
+ const fg = fgOverride ?? (dark ? "#FFFFFF" : "#000000");
108
157
  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 })
158
+ return /* @__PURE__ */ jsxs4(View3, { style: styles4.row, children: [
159
+ /* @__PURE__ */ jsx4(Text4, { variant: "bodyMedium", style: { color: fgMuted }, children: label }),
160
+ /* @__PURE__ */ jsx4(Text4, { variant: "bodyMedium", style: [styles4.value, { color: fg }], children: value })
112
161
  ] });
113
162
  }
114
- var styles3 = StyleSheet3.create({
163
+ var styles4 = StyleSheet4.create({
115
164
  row: {
116
165
  alignItems: "center",
117
166
  flexDirection: "row",
@@ -123,20 +172,20 @@ var styles3 = StyleSheet3.create({
123
172
  });
124
173
 
125
174
  // 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";
175
+ import { useAutoPaperTheme as useAutoPaperTheme5 } from "@rific/auto-paper";
176
+ import { StyleSheet as StyleSheet5, View as View4 } from "react-native";
177
+ import { Text as Text5 } from "react-native-paper";
178
+ import { jsx as jsx5, jsxs as jsxs5 } from "react/jsx-runtime";
130
179
  function StatSection({ label, fg: fgOverride, sectionBg: sectionBgOverride, children }) {
131
- const { dark } = useAutoPaperTheme4();
180
+ const { dark } = useAutoPaperTheme5();
132
181
  const fg = fgOverride ?? (dark ? "#FFFFFF" : "#000000");
133
182
  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 }),
183
+ return /* @__PURE__ */ jsxs5(View4, { style: [styles5.section, { backgroundColor: sectionBg }], children: [
184
+ /* @__PURE__ */ jsx5(Text5, { variant: "labelMedium", style: [styles5.label, { color: fg }], children: label }),
136
185
  children
137
186
  ] });
138
187
  }
139
- var styles4 = StyleSheet4.create({
188
+ var styles5 = StyleSheet5.create({
140
189
  // Bold and full-contrast (fg), not the original fontless/fgMuted treatment — that read at the
141
190
  // same visual weight as StatRow's own row labels below it (both used the identical muted color;
142
191
  // letterSpacing/variant alone didn't separate them enough to read as "this is the group header"
@@ -153,121 +202,49 @@ var styles4 = StyleSheet4.create({
153
202
  });
154
203
 
155
204
  // src/ActivityStatSection.tsx
156
- import { jsx as jsx5, jsxs as jsxs5 } from "react/jsx-runtime";
205
+ import { jsx as jsx6, jsxs as jsxs6 } from "react/jsx-runtime";
157
206
  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) })
207
+ return /* @__PURE__ */ jsxs6(StatSection, { label: "ACTIVITY", children: [
208
+ /* @__PURE__ */ jsx6(StatRow, { label: "Days Played", value: String(stats.distinctDaysPlayed) }),
209
+ /* @__PURE__ */ jsx6(StatRow, { label: "Day Streak", value: String(stats.currentDayStreak) }),
210
+ /* @__PURE__ */ jsx6(StatRow, { label: "Best Day Streak", value: String(stats.bestDayStreak) })
162
211
  ] });
163
212
  }
164
213
 
165
214
  // src/BaseSettingsDialog.tsx
166
- import { AutoAppearancePicker, Dialog, useAutoPaperTheme as useAutoPaperTheme6 } from "@rific/auto-paper";
215
+ import { AutoAppearancePicker, Dialog, useAutoPaperTheme as useAutoPaperTheme7 } from "@rific/auto-paper";
167
216
  import { Button as Button2, SoundContext, TouchableRipple, useHapticSettings, useSoundSettings, useVibration } from "@rific/feedback-press";
168
217
  import { useUpdater } from "@rific/updater";
169
- import { toRotationStyle as toRotationStyle2, useIsTouchPrimaryDevice, useRotation } from "@tastic/core";
218
+ import { useIsTouchPrimaryDevice, useRotation as useRotation2 } from "@tastic/core";
170
219
  import { useContext, useState as useState2 } from "react";
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";
220
+ import { Platform as Platform2, ScrollView, StyleSheet as StyleSheet8, View as View7 } from "react-native";
221
+ import { Icon as Icon4, Portal as Portal3, Text as Text7 } from "react-native-paper";
173
222
 
174
223
  // src/ConfirmDialog.tsx
175
- import { useAutoPaperTheme as useAutoPaperTheme5 } from "@rific/auto-paper";
224
+ import { useAutoPaperTheme as useAutoPaperTheme6 } from "@rific/auto-paper";
176
225
  import { Button } from "@rific/feedback-press";
177
226
  import { toRotationStyle } from "@tastic/core";
178
- import { StyleSheet as StyleSheet6, View as View4 } from "react-native";
179
- import { Icon as Icon2, Portal, Text as Text5 } from "react-native-paper";
180
-
181
- // src/overlayCard.ts
182
- import { StyleSheet as StyleSheet5 } from "react-native";
183
- function getOverlayCardColors(dark) {
184
- return {
185
- fg: dark ? "#FFFFFF" : "#000000",
186
- fgMuted: dark ? "rgba(255,255,255,0.4)" : "rgba(0,0,0,0.4)",
187
- cardBg: dark ? "#111111" : "#F2F2F2",
188
- cardBorder: dark ? "rgba(255,255,255,0.2)" : "rgba(0,0,0,0.2)"
189
- };
190
- }
191
- var overlayStyles = StyleSheet5.create({
192
- card: {
193
- alignItems: "center",
194
- borderRadius: 20,
195
- borderWidth: 1,
196
- gap: 16,
197
- maxWidth: 360,
198
- padding: 32
199
- },
200
- overlay: {
201
- alignItems: "center",
202
- backgroundColor: "rgba(0,0,0,0.72)",
203
- bottom: 0,
204
- justifyContent: "center",
205
- left: 0,
206
- position: "absolute",
207
- right: 0,
208
- top: 0
209
- }
210
- });
211
-
212
- // src/ConfirmDialog.tsx
213
- import { jsx as jsx6, jsxs as jsxs6 } from "react/jsx-runtime";
227
+ import { StyleSheet as StyleSheet6, View as View5 } from "react-native";
228
+ import { Icon as Icon3, Portal, Text as Text6 } from "react-native-paper";
229
+ import { jsx as jsx7, jsxs as jsxs7 } from "react/jsx-runtime";
214
230
  function ConfirmDialog({ visible, title, message, confirmLabel, cancelLabel, onConfirm, onCancel, rotation = 0, icon = "help-circle-outline", destructive = false }) {
215
- const { dark, colors } = useAutoPaperTheme5();
231
+ const { dark, colors } = useAutoPaperTheme6();
216
232
  if (!visible) return null;
217
233
  const { fg, cardBg, cardBorder } = getOverlayCardColors(dark);
218
234
  const accent = destructive ? colors.danger : colors.primary;
219
235
  const onAccent = destructive ? colors.onDanger : colors.onPrimary;
220
236
  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 })
237
+ return /* @__PURE__ */ jsx7(Portal, { children: /* @__PURE__ */ jsx7(View5, { style: [overlayStyles.overlay, styles6.overlay], children: /* @__PURE__ */ jsxs7(View5, { style: [overlayStyles.card, styles6.card, { backgroundColor: cardBg, borderColor: cardBorder }, toRotationStyle(rotation)], children: [
238
+ /* @__PURE__ */ jsx7(Icon3, { source: icon, size: 64, color: accent }),
239
+ /* @__PURE__ */ jsx7(Text6, { variant: "headlineLarge", style: [styles6.title, { color: accent }], children: title }),
240
+ /* @__PURE__ */ jsx7(Text6, { variant: "bodyLarge", style: [styles6.body, { color: fg }], children: message }),
241
+ /* @__PURE__ */ jsxs7(View5, { style: overlayActionStyles.actions, children: [
242
+ showCancel && /* @__PURE__ */ jsx7(Button, { mode: "outlined", onPress: onCancel, style: overlayActionStyles.actionButton, children: cancelLabel }),
243
+ /* @__PURE__ */ jsx7(Button, { mode: "contained", onPress: onConfirm, style: showCancel ? overlayActionStyles.actionButton : overlayActionStyles.actionButtonSingle, buttonColor: accent, textColor: onAccent, children: confirmLabel })
228
244
  ] })
229
245
  ] }) }) });
230
246
  }
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
247
- // hardcodes numberOfLines={1} on its label with no override, so a button squeezed under its
248
- // label's natural width silently ellipsizes ("Cancel" -> "Can...") instead of wrapping - assumed
249
- // fixable by just giving the row more width, until confirmed live that these two-word labels
250
- // (Cancel/Reset/New Game) can still lose the truncation fight even with the extra room card's own
251
- // width fix below provides, on a narrow enough screen.
252
- actionButton: {
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
263
- },
264
- actions: {
265
- flexDirection: "row",
266
- flexWrap: "wrap",
267
- gap: 12,
268
- justifyContent: "center",
269
- width: "100%"
270
- },
247
+ var styles6 = StyleSheet6.create({
271
248
  body: {
272
249
  textAlign: "center"
273
250
  },
@@ -295,6 +272,36 @@ var styles5 = StyleSheet6.create({
295
272
  }
296
273
  });
297
274
 
275
+ // src/RotatedFrame.tsx
276
+ import { FakeLandscapeView, rotateDimensions, rotateInsets, useRotation } from "@tastic/core";
277
+ import { useMemo } from "react";
278
+ import { StyleSheet as StyleSheet7, useWindowDimensions, View as View6 } from "react-native";
279
+ import { Portal as Portal2 } from "react-native-paper";
280
+ import { SafeAreaInsetsContext, useSafeAreaInsets } from "react-native-safe-area-context";
281
+ import { jsx as jsx8 } from "react/jsx-runtime";
282
+ function RotatedFrame({ children, rotation: rotationOverride, rotatedSafeArea = false, portalHost = false, passThrough = false, maxContentWidth }) {
283
+ const ambientRotation = useRotation();
284
+ const rotation = rotationOverride ?? ambientRotation;
285
+ const window = useWindowDimensions();
286
+ const { width, height } = rotateDimensions(window.width, window.height, rotation);
287
+ const rawInsets = useSafeAreaInsets();
288
+ const insets = useMemo(() => rotatedSafeArea ? rotateInsets(rawInsets, rotation) : rawInsets, [rotatedSafeArea, rawInsets, rotation]);
289
+ const cappedWidth = maxContentWidth !== void 0 && width > height ? maxContentWidth : void 0;
290
+ const column = /* @__PURE__ */ jsx8(View6, { style: [styles7.column, cappedWidth !== void 0 && { maxWidth: cappedWidth }], pointerEvents: passThrough ? "box-none" : void 0, children });
291
+ return /* @__PURE__ */ jsx8(FakeLandscapeView, { rotation, passThrough, style: styles7.root, children: /* @__PURE__ */ jsx8(SafeAreaInsetsContext.Provider, { value: insets, children: portalHost ? /* @__PURE__ */ jsx8(Portal2.Host, { children: column }) : column }) });
292
+ }
293
+ var styles7 = StyleSheet7.create({
294
+ // A centred column: full width up to `maxWidth`, so a capped frame sits in the middle of a wider window.
295
+ column: {
296
+ alignSelf: "center",
297
+ flex: 1,
298
+ width: "100%"
299
+ },
300
+ root: {
301
+ flex: 1
302
+ }
303
+ });
304
+
298
305
  // src/useUpdateConfirmBridge.ts
299
306
  import { useCallback, useRef, useState } from "react";
300
307
  function useUpdateConfirmBridge() {
@@ -316,13 +323,13 @@ function useUpdateConfirmBridge() {
316
323
  }
317
324
 
318
325
  // src/BaseSettingsDialog.tsx
319
- import { Fragment as Fragment2, jsx as jsx7, jsxs as jsxs7 } from "react/jsx-runtime";
326
+ import { jsx as jsx9, jsxs as jsxs8 } from "react/jsx-runtime";
320
327
  function SettingIcon({ source, color, containerColor }) {
321
- return /* @__PURE__ */ jsx7(View5, { style: [styles6.iconBadge, { backgroundColor: containerColor }], children: /* @__PURE__ */ jsx7(Icon3, { source, size: 18, color }) });
328
+ return /* @__PURE__ */ jsx9(View7, { style: [styles8.iconBadge, { backgroundColor: containerColor }], children: /* @__PURE__ */ jsx9(Icon4, { source, size: 18, color }) });
322
329
  }
323
- function BaseSettingsDialog({ visible, onDismiss, rotation: rotationOverride, version, lockOrientation, onLockOrientationChange, deferBottomEdgeGestures, onDeferBottomEdgeGestures, hideSound = false, hideHaptics = false, hideAppearance = false, hideUpdateCheck = false, onUpdateError, children }) {
324
- const { colors } = useAutoPaperTheme6();
325
- const ambientRotation = useRotation();
330
+ function BaseSettingsDialog({ visible, onDismiss, rotation: rotationOverride, version, lockOrientation, onLockOrientationChange, deferBottomEdgeGestures, onDeferBottomEdgeGestures, hideSound = false, hideHaptics = false, hideAppearance = false, hideUpdateCheck = false, onUpdateError, onShowHowToPlay, children }) {
331
+ const { colors } = useAutoPaperTheme7();
332
+ const ambientRotation = useRotation2();
326
333
  const rotation = rotationOverride ?? ambientRotation;
327
334
  const isTouchPrimary = useIsTouchPrimaryDevice();
328
335
  const { settings: hapticSettings, set: setHapticSettings } = useHapticSettings();
@@ -345,27 +352,27 @@ function BaseSettingsDialog({ visible, onDismiss, rotation: rotationOverride, ve
345
352
  const showSound = !hideSound;
346
353
  const showAppearance = !hideAppearance;
347
354
  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" })
355
+ return /* @__PURE__ */ jsx9(Portal3, { children: /* @__PURE__ */ jsxs8(RotatedFrame, { rotation, rotatedSafeArea: true, portalHost: true, passThrough: true, children: [
356
+ /* @__PURE__ */ jsxs8(Dialog, { visible, onDismiss, style: styles8.dialog, children: [
357
+ /* @__PURE__ */ jsx9(Dialog.Title, { children: "Settings" }),
358
+ /* @__PURE__ */ jsx9(Dialog.ScrollArea, { style: styles8.scrollArea, children: /* @__PURE__ */ jsxs8(ScrollView, { contentContainerStyle: styles8.content, showsVerticalScrollIndicator: false, children: [
359
+ /* @__PURE__ */ jsxs8(View7, { style: styles8.toggleGroup, children: [
360
+ showLockOrientation && /* @__PURE__ */ jsx9(TouchableRipple, { onPress: () => onLockOrientationChange(!lockOrientation), style: styles8.toggleButton, accessibilityLabel: `Lock orientation ${lockOrientation ? "on" : "off"}`, children: /* @__PURE__ */ jsxs8(View7, { style: styles8.toggleContent, children: [
361
+ /* @__PURE__ */ jsx9(SettingIcon, { source: lockOrientation ? "lock" : "lock-open-variant-outline", color: lockOrientation ? colors.secondary : colors.onSurfaceVariant, containerColor: lockOrientation ? colors.secondaryContainer : colors.surfaceVariant }),
362
+ /* @__PURE__ */ jsxs8(View7, { style: styles8.flexShrink, children: [
363
+ /* @__PURE__ */ jsx9(Text7, { variant: "bodyLarge", style: { color: colors.onSurface }, children: "Lock Orientation" }),
364
+ /* @__PURE__ */ jsx9(Text7, { variant: "bodySmall", numberOfLines: 1, style: { color: colors.onSurfaceVariant }, children: "Pins the current layout" })
358
365
  ] })
359
366
  ] }) }),
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" })
367
+ showEdgeGuard && /* @__PURE__ */ jsx9(TouchableRipple, { onPress: () => onDeferBottomEdgeGestures(!deferBottomEdgeGestures), style: styles8.toggleButton, accessibilityLabel: `Edge guard ${deferBottomEdgeGestures ? "on" : "off"}`, children: /* @__PURE__ */ jsxs8(View7, { style: styles8.toggleContent, children: [
368
+ /* @__PURE__ */ jsx9(SettingIcon, { source: deferBottomEdgeGestures ? "shield-check-outline" : "shield-off-outline", color: deferBottomEdgeGestures ? colors.secondary : colors.onSurfaceVariant, containerColor: deferBottomEdgeGestures ? colors.secondaryContainer : colors.surfaceVariant }),
369
+ /* @__PURE__ */ jsxs8(View7, { style: styles8.flexShrink, children: [
370
+ /* @__PURE__ */ jsx9(Text7, { variant: "bodyLarge", style: { color: colors.onSurface }, children: "Edge Guard" }),
371
+ /* @__PURE__ */ jsx9(Text7, { variant: "bodySmall", numberOfLines: 1, style: { color: colors.onSurfaceVariant }, children: "Requires a second swipe" })
365
372
  ] })
366
373
  ] }) }),
367
- (showSound || showHaptics) && /* @__PURE__ */ jsxs7(View5, { style: styles6.toggleRow, children: [
368
- showSound && /* @__PURE__ */ jsx7(
374
+ (showSound || showHaptics) && /* @__PURE__ */ jsxs8(View7, { style: styles8.toggleRow, children: [
375
+ showSound && /* @__PURE__ */ jsx9(
369
376
  TouchableRipple,
370
377
  {
371
378
  soundDisabled: true,
@@ -374,15 +381,15 @@ function BaseSettingsDialog({ visible, onDismiss, rotation: rotationOverride, ve
374
381
  setSoundSettings({ enabled });
375
382
  if (enabled) sound.selection?.();
376
383
  },
377
- style: styles6.toggleButtonInRow,
384
+ style: styles8.toggleButtonInRow,
378
385
  accessibilityLabel: `Sound ${soundSettings.enabled ? "on" : "off"}`,
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" })
386
+ children: /* @__PURE__ */ jsxs8(View7, { style: styles8.toggleContent, children: [
387
+ /* @__PURE__ */ jsx9(SettingIcon, { source: soundSettings.enabled ? "volume-high" : "volume-off", color: soundSettings.enabled ? colors.tertiary : colors.onSurfaceVariant, containerColor: soundSettings.enabled ? colors.tertiaryContainer : colors.surfaceVariant }),
388
+ /* @__PURE__ */ jsx9(Text7, { variant: "bodyLarge", style: { color: colors.onSurface }, children: "Sound" })
382
389
  ] })
383
390
  }
384
391
  ),
385
- showHaptics && /* @__PURE__ */ jsx7(
392
+ showHaptics && /* @__PURE__ */ jsx9(
386
393
  TouchableRipple,
387
394
  {
388
395
  hapticDisabled: true,
@@ -391,36 +398,54 @@ function BaseSettingsDialog({ visible, onDismiss, rotation: rotationOverride, ve
391
398
  setHapticSettings({ vibrate });
392
399
  if (vibrate) forceHapticFeedback();
393
400
  },
394
- style: styles6.toggleButtonInRow,
401
+ style: styles8.toggleButtonInRow,
395
402
  accessibilityLabel: `Haptics ${hapticSettings.vibrate ? "on" : "off"}`,
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" })
403
+ children: /* @__PURE__ */ jsxs8(View7, { style: styles8.toggleContent, children: [
404
+ /* @__PURE__ */ jsx9(SettingIcon, { source: hapticSettings.vibrate ? "vibrate" : "vibrate-off", color: hapticSettings.vibrate ? colors.tertiary : colors.onSurfaceVariant, containerColor: hapticSettings.vibrate ? colors.tertiaryContainer : colors.surfaceVariant }),
405
+ /* @__PURE__ */ jsx9(Text7, { variant: "bodyLarge", style: { color: colors.onSurface }, children: "Haptics" })
399
406
  ] })
400
407
  }
401
408
  )
402
- ] })
409
+ ] }),
410
+ onShowHowToPlay && /* @__PURE__ */ jsx9(
411
+ TouchableRipple,
412
+ {
413
+ onPress: () => {
414
+ onDismiss();
415
+ onShowHowToPlay();
416
+ },
417
+ style: styles8.toggleButton,
418
+ accessibilityLabel: "How to Play",
419
+ children: /* @__PURE__ */ jsxs8(View7, { style: styles8.toggleContent, children: [
420
+ /* @__PURE__ */ jsx9(SettingIcon, { source: "help-circle-outline", color: colors.secondary, containerColor: colors.secondaryContainer }),
421
+ /* @__PURE__ */ jsxs8(View7, { style: styles8.flexShrink, children: [
422
+ /* @__PURE__ */ jsx9(Text7, { variant: "bodyLarge", style: { color: colors.onSurface }, children: "How to Play" }),
423
+ /* @__PURE__ */ jsx9(Text7, { variant: "bodySmall", numberOfLines: 1, style: { color: colors.onSurfaceVariant }, children: "Replay the quick intro" })
424
+ ] })
425
+ ] })
426
+ }
427
+ )
403
428
  ] }),
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 })
429
+ showAppearance && /* @__PURE__ */ jsxs8(View7, { style: styles8.section, children: [
430
+ /* @__PURE__ */ jsx9(Text7, { variant: "labelMedium", style: [styles8.sectionLabel, { color: colors.onSurfaceVariant }], children: "APPEARANCE" }),
431
+ /* @__PURE__ */ jsx9(AutoAppearancePicker, { showLabels: false })
407
432
  ] }),
408
433
  children,
409
- showUpdateCheck && /* @__PURE__ */ jsxs7(View5, { style: styles6.section, children: [
410
- /* @__PURE__ */ jsxs7(Text6, { variant: "labelSmall", style: [styles6.sectionLabel, { color: colors.onSurfaceVariant }], children: [
434
+ showUpdateCheck && /* @__PURE__ */ jsxs8(View7, { style: styles8.section, children: [
435
+ /* @__PURE__ */ jsxs8(Text7, { variant: "labelSmall", style: [styles8.sectionLabel, { color: colors.onSurfaceVariant }], children: [
411
436
  "VERSION ",
412
437
  version,
413
438
  updateReady ? " \xB7 UPDATE READY" : ""
414
439
  ] }),
415
- /* @__PURE__ */ jsx7(Button2, { mode: "outlined", onPress: check, loading: checking, disabled: checking, children: "Check for Updates" })
440
+ /* @__PURE__ */ jsx9(Button2, { mode: "outlined", onPress: check, loading: checking, disabled: checking, children: "Check for Updates" })
416
441
  ] })
417
442
  ] }) })
418
443
  ] }),
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) })
421
- ] });
444
+ /* @__PURE__ */ jsx9(ConfirmDialog, { visible: !!updateManifest, title: "Update Available", message: updateManifestDate ? `Released ${updateManifestDate.toLocaleDateString()} at ${updateManifestDate.toLocaleTimeString()}` : "", confirmLabel: "Restart", cancelLabel: "Later", icon: "update", rotation: 0, onConfirm: () => respondToUpdateConfirm(true), onCancel: () => respondToUpdateConfirm(false) }),
445
+ /* @__PURE__ */ jsx9(ConfirmDialog, { visible: !!infoMessage, title: infoMessage?.title ?? "", message: infoMessage?.message ?? "", confirmLabel: "OK", icon: "information-outline", rotation: 0, onConfirm: () => setInfoMessage(null) })
446
+ ] }) });
422
447
  }
423
- var styles6 = StyleSheet7.create({
448
+ var styles8 = StyleSheet8.create({
424
449
  content: {
425
450
  gap: 24,
426
451
  paddingVertical: 20
@@ -488,31 +513,31 @@ var styles6 = StyleSheet7.create({
488
513
  });
489
514
 
490
515
  // src/BaseStatsScreen.tsx
491
- import { useAutoPaperTheme as useAutoPaperTheme7 } from "@rific/auto-paper";
516
+ import { useAutoPaperTheme as useAutoPaperTheme8 } from "@rific/auto-paper";
492
517
  import { Button as Button3, IconButton } from "@rific/feedback-press";
493
- import { useRotation as useRotation2 } from "@tastic/core";
518
+ import { useRotation as useRotation3 } from "@tastic/core";
494
519
  import { useState as useState3 } from "react";
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";
520
+ import { ScrollView as ScrollView2, StyleSheet as StyleSheet9, View as View8 } from "react-native";
521
+ import { Text as Text8 } from "react-native-paper";
522
+ import { jsx as jsx10, jsxs as jsxs9 } from "react/jsx-runtime";
498
523
  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 }) {
499
- const { dark, colors } = useAutoPaperTheme7();
500
- const ambientRotation = useRotation2();
524
+ const { dark, colors } = useAutoPaperTheme8();
525
+ const ambientRotation = useRotation3();
501
526
  const rotation = rotationOverride ?? ambientRotation;
502
527
  const [confirmResetVisible, setConfirmResetVisible] = useState3(false);
503
528
  const showReset = !!onReset;
504
529
  const fg = fgOverride ?? (dark ? "#FFFFFF" : "#000000");
505
530
  const bg = bgOverride ?? (dark ? "#000000" : "#FFFFFF");
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 })
531
+ return /* @__PURE__ */ jsxs9(View8, { style: [styles9.container, { backgroundColor: bg }], children: [
532
+ /* @__PURE__ */ jsxs9(View8, { style: [styles9.header, { paddingTop: 8 + insets.top, paddingLeft: 8 + insets.left }], children: [
533
+ /* @__PURE__ */ jsx10(IconButton, { icon: "arrow-left", iconColor: fg, size: 24, onPress: onBack }),
534
+ /* @__PURE__ */ jsx10(Text8, { variant: titleVariant, style: [styles9.title, { color: fg }], children: title })
510
535
  ] }),
511
- /* @__PURE__ */ jsxs8(ScrollView2, { style: styles7.scrollView, contentContainerStyle: [styles7.content, { paddingBottom: 32 + insets.bottom }], showsVerticalScrollIndicator: false, children: [
536
+ /* @__PURE__ */ jsxs9(ScrollView2, { style: styles9.scrollView, contentContainerStyle: [styles9.content, { paddingBottom: 32 + insets.bottom }], showsVerticalScrollIndicator: false, children: [
512
537
  children,
513
- showReset && /* @__PURE__ */ jsx8(Button3, { mode: "contained", onPress: () => setConfirmResetVisible(true), buttonColor: colors.danger, textColor: colors.onDanger, style: styles7.resetButton, children: resetLabel })
538
+ showReset && /* @__PURE__ */ jsx10(Button3, { mode: "contained", onPress: () => setConfirmResetVisible(true), buttonColor: colors.danger, textColor: colors.onDanger, style: styles9.resetButton, children: resetLabel })
514
539
  ] }),
515
- /* @__PURE__ */ jsx8(
540
+ /* @__PURE__ */ jsx10(
516
541
  ConfirmDialog,
517
542
  {
518
543
  visible: confirmResetVisible,
@@ -532,7 +557,7 @@ function BaseStatsScreen({ rotation: rotationOverride, title = "Achievements", t
532
557
  )
533
558
  ] });
534
559
  }
535
- var styles7 = StyleSheet8.create({
560
+ var styles9 = StyleSheet9.create({
536
561
  container: {
537
562
  flex: 1
538
563
  },
@@ -563,19 +588,19 @@ var styles7 = StyleSheet8.create({
563
588
  });
564
589
 
565
590
  // src/ContentGutter.tsx
566
- import { computeContentBounds } from "@tastic/core";
567
- import { StyleSheet as StyleSheet9, useWindowDimensions, View as View7 } from "react-native";
568
- import { jsx as jsx9, jsxs as jsxs9 } from "react/jsx-runtime";
591
+ import { computeContentBounds, useRotatedWindowDimensions } from "@tastic/core";
592
+ import { StyleSheet as StyleSheet10, View as View9 } from "react-native";
593
+ import { jsx as jsx11, jsxs as jsxs10 } from "react/jsx-runtime";
569
594
  function ContentGutter({ maxContentWidth, leftGutter, rightGutter, style, children }) {
570
- const { width: windowWidth } = useWindowDimensions();
595
+ const { width: windowWidth } = useRotatedWindowDimensions();
571
596
  const { contentWidth, gutterWidth } = computeContentBounds(windowWidth, maxContentWidth ?? Infinity);
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 })
597
+ return /* @__PURE__ */ jsxs10(View9, { style: [styles10.row, style], children: [
598
+ /* @__PURE__ */ jsx11(View9, { style: [styles10.gutter, { width: gutterWidth }], children: leftGutter }),
599
+ /* @__PURE__ */ jsx11(View9, { style: { width: contentWidth }, children }),
600
+ /* @__PURE__ */ jsx11(View9, { style: [styles10.gutter, { width: gutterWidth }], children: rightGutter })
576
601
  ] });
577
602
  }
578
- var styles8 = StyleSheet9.create({
603
+ var styles10 = StyleSheet10.create({
579
604
  // overflow:'hidden' keeps an oversized leftGutter/rightGutter from bleeding into the content
580
605
  // column instead of clipping cleanly at its own real width.
581
606
  gutter: {
@@ -593,35 +618,35 @@ import { Platform as Platform3 } from "react-native";
593
618
  // src/SectionedDropdown.tsx
594
619
  import { getBlendedColor, getColorRoles } from "@rific/auto-paper";
595
620
  import { IconButton as IconButton2, TouchableRipple as TouchableRipple2 } from "@rific/feedback-press";
596
- import { useRotation as useRotation3 } from "@tastic/core";
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";
621
+ import { useRotation as useRotation4 } from "@tastic/core";
622
+ import { ScrollView as ScrollView3, StyleSheet as StyleSheet12, View as View12 } from "react-native";
623
+ import { Icon as Icon5, Text as Text9 } from "react-native-paper";
599
624
 
600
625
  // src/PopoverBody.tsx
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";
626
+ import { StyleSheet as StyleSheet11, View as View10 } from "react-native";
627
+ import { Fragment as Fragment2, jsx as jsx12, jsxs as jsxs11 } from "react/jsx-runtime";
603
628
  var CARET_SIZE = 7;
604
629
  var CARET_RING_OFFSET = 2;
605
630
  var CARET_DIP = 1;
606
631
  function PopoverBody({ visible, children, align = "center", verticalAlign = "below", caretColor, caretBorderColor, caretBorderWidth = 1, triggerSize = 0 }) {
607
632
  if (!visible) return null;
608
633
  const above = verticalAlign === "above";
609
- const alignStyle = align === "left" ? styles9.contentLeft : align === "right" ? styles9.contentRight : styles9.contentCenter;
610
- const verticalStyle = above ? styles9.contentAbove : styles9.contentBelow;
634
+ const alignStyle = align === "left" ? styles11.contentLeft : align === "right" ? styles11.contentRight : styles11.contentCenter;
635
+ const verticalStyle = above ? styles11.contentAbove : styles11.contentBelow;
611
636
  const ringSize = CARET_SIZE + caretBorderWidth;
612
637
  const caretOffset = (halfFootprint) => align === "right" ? { right: triggerSize / 2 - halfFootprint } : { left: triggerSize / 2 - halfFootprint };
613
638
  const caretFill = above ? "borderTopColor" : "borderBottomColor";
614
639
  const caretWidthProp = above ? "borderTopWidth" : "borderBottomWidth";
615
640
  const caretEdge = (size) => above ? { bottom: -size + CARET_DIP } : { top: -size + CARET_DIP };
616
- return /* @__PURE__ */ jsxs10(View8, { style: [styles9.content, alignStyle, verticalStyle], children: [
641
+ return /* @__PURE__ */ jsxs11(View10, { style: [styles11.content, alignStyle, verticalStyle], children: [
617
642
  children,
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 }] })
643
+ caretColor && /* @__PURE__ */ jsxs11(Fragment2, { children: [
644
+ /* @__PURE__ */ jsx12(View10, { style: [styles11.caret, caretOffset(ringSize), caretEdge(ringSize), { [caretFill]: caretBorderColor ?? caretColor, [caretWidthProp]: ringSize, borderLeftWidth: ringSize, borderRightWidth: ringSize }] }),
645
+ /* @__PURE__ */ jsx12(View10, { style: [styles11.caret, caretOffset(CARET_SIZE), caretEdge(CARET_SIZE - CARET_RING_OFFSET), { [caretFill]: caretColor, [caretWidthProp]: CARET_SIZE, borderLeftWidth: CARET_SIZE, borderRightWidth: CARET_SIZE }] })
621
646
  ] })
622
647
  ] });
623
648
  }
624
- var styles9 = StyleSheet10.create({
649
+ var styles11 = StyleSheet11.create({
625
650
  caret: {
626
651
  borderLeftColor: "transparent",
627
652
  borderRightColor: "transparent",
@@ -664,10 +689,10 @@ var styles9 = StyleSheet10.create({
664
689
  });
665
690
 
666
691
  // src/TriggerGaugeHost.tsx
667
- import { jsx as jsx11 } from "react/jsx-runtime";
692
+ import { jsx as jsx13 } from "react/jsx-runtime";
668
693
  var getTriggerGauge = () => import("./TriggerGauge-2OJOOF6I.mjs").then((mod) => ({ default: mod.TriggerGauge }));
669
694
  function TriggerGaugeHost(props) {
670
- return /* @__PURE__ */ jsx11(SkiaGate, { getComponent: getTriggerGauge, componentProps: props });
695
+ return /* @__PURE__ */ jsx13(SkiaGate, { getComponent: getTriggerGauge, componentProps: props });
671
696
  }
672
697
 
673
698
  // src/useAutoAlign.ts
@@ -719,7 +744,7 @@ function useAutoAlign(open, contentWidth, contentHeight, rotation = 0) {
719
744
  }
720
745
 
721
746
  // src/SectionedDropdown.tsx
722
- import { Fragment as Fragment4, jsx as jsx12, jsxs as jsxs11 } from "react/jsx-runtime";
747
+ import { Fragment as Fragment3, jsx as jsx14, jsxs as jsxs12 } from "react/jsx-runtime";
723
748
  var MENU_BORDER_WIDTH = 1;
724
749
  var TRIGGER_SIZE = 44;
725
750
  var MENU_MIN_WIDTH = 200;
@@ -731,7 +756,7 @@ var MENU_ITEM_HEIGHT_WITH_DESCRIPTION = 58;
731
756
  var MENU_DIVIDER_HEIGHT = 9;
732
757
  var MENU_VERTICAL_PADDING = 12;
733
758
  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" } }) {
734
- const ambientRotation = useRotation3();
759
+ const ambientRotation = useRotation4();
735
760
  const rotation = rotationOverride ?? ambientRotation;
736
761
  const menuBg = dark ? "#000000" : "#FFFFFF";
737
762
  const menuBorderColor = getBlendedColor(mutedColor, menuBg, 0.5);
@@ -769,17 +794,17 @@ function SectionedDropdown({ id, host, icon, accessibilityLabel, sections, accen
769
794
  }
770
795
  gaugeOffset += section.options.length;
771
796
  }
772
- const anchorStyle = [styles10.anchor, open && styles10.anchorOpen];
797
+ const anchorStyle = [styles12.anchor, open && styles12.anchorOpen];
773
798
  const menuStyle = { backgroundColor: menuBg, borderColor: menuBorderColor, maxHeight };
774
799
  const dividerStyle = { backgroundColor: menuBorderColor };
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) })
800
+ return /* @__PURE__ */ jsxs12(View12, { style: anchorStyle, children: [
801
+ /* @__PURE__ */ jsxs12(View12, { ref: triggerRef, collapsable: false, style: styles12.triggerBox, children: [
802
+ /* @__PURE__ */ jsx14(TriggerGaugeHost, { segments: gaugeSegments, litIndices: gaugeLitIndices, size: TRIGGER_SIZE, accentColor, mutedColor }),
803
+ /* @__PURE__ */ jsx14(IconButton2, { icon: triggerIcon, iconColor: triggerIconColor, size: triggerIconSize, accessibilityLabel, onPress: () => host.toggle(id) })
779
804
  ] }),
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(
805
+ /* @__PURE__ */ jsx14(PopoverBody, { visible: open && measured, align, verticalAlign, caretColor: menuBg, caretBorderColor: menuBorderColor, caretBorderWidth: MENU_BORDER_WIDTH, triggerSize: TRIGGER_SIZE, children: /* @__PURE__ */ jsx14(ScrollView3, { style: [styles12.menu, menuStyle], contentContainerStyle: styles12.menuContent, showsVerticalScrollIndicator: false, children: sections.map((section, sectionIndex) => /* @__PURE__ */ jsxs12(View12, { children: [
806
+ sectionIndex > 0 && /* @__PURE__ */ jsx14(View12, { style: [styles12.divider, dividerStyle] }),
807
+ section.kind === "single" ? /* @__PURE__ */ jsx14(
783
808
  SingleSection,
784
809
  {
785
810
  section,
@@ -792,7 +817,7 @@ function SectionedDropdown({ id, host, icon, accessibilityLabel, sections, accen
792
817
  if (autoDismiss) host.close();
793
818
  }
794
819
  }
795
- ) : /* @__PURE__ */ jsx12(MultiSection, { section, accentColor, onAccentColor: resolvedOnAccentColor, mutedColor, labelFontFamily, allClearLabels })
820
+ ) : /* @__PURE__ */ jsx14(MultiSection, { section, accentColor, onAccentColor: resolvedOnAccentColor, mutedColor, labelFontFamily, allClearLabels })
796
821
  ] }, section.id)) }) })
797
822
  ] });
798
823
  }
@@ -804,18 +829,18 @@ function SingleSection({
804
829
  labelFontFamily,
805
830
  onSelect
806
831
  }) {
807
- return /* @__PURE__ */ jsx12(Fragment4, { children: section.options.map((option) => {
832
+ return /* @__PURE__ */ jsx14(Fragment3, { children: section.options.map((option) => {
808
833
  const selected = option.value === section.value;
809
834
  const taken = !selected && option.value === section.takenValue;
810
835
  const rowColor = selected ? onAccentColor : mutedColor;
811
- const itemStyle = [styles10.item, selected && { backgroundColor: accentColor }, taken && styles10.itemTaken];
836
+ const itemStyle = [styles12.item, selected && { backgroundColor: accentColor }, taken && styles12.itemTaken];
812
837
  const labelStyle = { fontFamily: labelFontFamily, color: rowColor, fontWeight: selected ? "bold" : "normal" };
813
838
  const descriptionStyle = { fontFamily: labelFontFamily, color: rowColor };
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 })
839
+ return /* @__PURE__ */ jsx14(TouchableRipple2, { disabled: taken, onPress: () => onSelect(option.value), style: itemStyle, children: /* @__PURE__ */ jsxs12(View12, { style: styles12.itemRow, children: [
840
+ option.icon && /* @__PURE__ */ jsx14(Icon5, { source: option.icon, size: MENU_ITEM_ICON_SIZE, color: rowColor }),
841
+ /* @__PURE__ */ jsxs12(View12, { style: styles12.itemLabelColumn, children: [
842
+ /* @__PURE__ */ jsx14(Text9, { variant: "labelLarge", style: labelStyle, children: option.label }),
843
+ option.description && /* @__PURE__ */ jsx14(Text9, { variant: "labelSmall", style: descriptionStyle, children: option.description })
819
844
  ] })
820
845
  ] }) }, option.value);
821
846
  }) });
@@ -829,23 +854,23 @@ function MultiSection({
829
854
  allClearLabels
830
855
  }) {
831
856
  const allSelected = section.value.length === section.options.length;
832
- return /* @__PURE__ */ jsxs11(Fragment4, { children: [
857
+ return /* @__PURE__ */ jsxs12(Fragment3, { children: [
833
858
  section.options.map((option, i) => {
834
859
  const selected = section.value.includes(option.value);
835
860
  const rowColor = selected ? onAccentColor : mutedColor;
836
861
  const prevSelected = selected && i > 0 && section.value.includes(section.options[i - 1].value);
837
862
  const nextSelected = selected && i < section.options.length - 1 && section.value.includes(section.options[i + 1].value);
838
- const itemStyle = [styles10.item, selected && { backgroundColor: accentColor }, prevSelected && { borderTopLeftRadius: 0, borderTopRightRadius: 0 }, nextSelected && { borderBottomLeftRadius: 0, borderBottomRightRadius: 0 }];
863
+ const itemStyle = [styles12.item, selected && { backgroundColor: accentColor }, prevSelected && { borderTopLeftRadius: 0, borderTopRightRadius: 0 }, nextSelected && { borderBottomLeftRadius: 0, borderBottomRightRadius: 0 }];
839
864
  const labelStyle = { fontFamily: labelFontFamily, color: rowColor, fontWeight: selected ? "bold" : "normal" };
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 })
865
+ return /* @__PURE__ */ jsx14(TouchableRipple2, { onPress: () => section.onChange(selected ? section.value.filter((v) => v !== option.value) : [...section.value, option.value]), style: itemStyle, children: /* @__PURE__ */ jsxs12(View12, { style: styles12.itemRow, children: [
866
+ option.icon && /* @__PURE__ */ jsx14(Icon5, { source: option.icon, size: MENU_ITEM_ICON_SIZE, color: rowColor }),
867
+ /* @__PURE__ */ jsx14(Text9, { variant: "labelLarge", style: [styles12.itemLabelFlex, labelStyle], children: option.label })
843
868
  ] }) }, option.value);
844
869
  }),
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 }) })
870
+ section.allClear && /* @__PURE__ */ jsx14(TouchableRipple2, { onPress: () => section.onChange(allSelected ? [] : section.options.map((o) => o.value)), style: styles12.item, children: /* @__PURE__ */ jsx14(Text9, { variant: "labelLarge", style: [styles12.allClearLabel, { fontFamily: labelFontFamily, color: accentColor }], children: allSelected ? allClearLabels.clear : allClearLabels.all }) })
846
871
  ] });
847
872
  }
848
- var styles10 = StyleSheet11.create({
873
+ var styles12 = StyleSheet12.create({
849
874
  allClearLabel: {
850
875
  fontWeight: "bold",
851
876
  textAlign: "center"
@@ -862,7 +887,7 @@ var styles10 = StyleSheet11.create({
862
887
  zIndex: 100
863
888
  },
864
889
  divider: {
865
- height: StyleSheet11.hairlineWidth,
890
+ height: StyleSheet12.hairlineWidth,
866
891
  marginVertical: 4
867
892
  },
868
893
  item: {
@@ -915,24 +940,24 @@ var styles10 = StyleSheet11.create({
915
940
  });
916
941
 
917
942
  // src/ControlSchemePicker.tsx
918
- import { jsx as jsx13 } from "react/jsx-runtime";
943
+ import { jsx as jsx15 } from "react/jsx-runtime";
919
944
  function ControlSchemePicker({ id, host, value, onChange, options, takenValue, accentColor, mutedColor, onAccentColor, dark, align, alignOverride, rotation, labelFontFamily }) {
920
945
  const isTouchPrimary = useIsTouchPrimaryDevice2();
921
946
  if (Platform3.OS !== "web" || isTouchPrimary) return null;
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 });
947
+ return /* @__PURE__ */ jsx15(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 });
923
948
  }
924
949
 
925
950
  // src/CornerActionButtons.tsx
926
951
  import { IconButton as IconButton3 } from "@rific/feedback-press";
927
- import { StyleSheet as StyleSheet12 } from "react-native";
928
- import { Fragment as Fragment5, jsx as jsx14, jsxs as jsxs12 } from "react/jsx-runtime";
952
+ import { StyleSheet as StyleSheet13 } from "react-native";
953
+ import { Fragment as Fragment4, jsx as jsx16, jsxs as jsxs13 } from "react/jsx-runtime";
929
954
  function CornerActionButtons({ onBack, onSettings, fg, insets, backIcon = "arrow-left", backLabel = "Back" }) {
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" })
955
+ return /* @__PURE__ */ jsxs13(Fragment4, { children: [
956
+ /* @__PURE__ */ jsx16(IconButton3, { icon: backIcon, iconColor: fg, size: 24, style: [styles13.back, { top: 8 + insets.top, left: 8 + insets.left }], onPress: onBack, accessibilityLabel: backLabel }),
957
+ /* @__PURE__ */ jsx16(IconButton3, { icon: "cog", iconColor: fg, size: 24, style: [styles13.topRight, { top: 8 + insets.top, right: 8 + insets.right }], onPress: onSettings, accessibilityLabel: "Settings" })
933
958
  ] });
934
959
  }
935
- var styles11 = StyleSheet12.create({
960
+ var styles13 = StyleSheet13.create({
936
961
  back: {
937
962
  position: "absolute"
938
963
  },
@@ -942,22 +967,22 @@ var styles11 = StyleSheet12.create({
942
967
  });
943
968
 
944
969
  // src/CornerStatusBadges.tsx
945
- import { StyleSheet as StyleSheet13, View as View11 } from "react-native";
946
- import { Icon as Icon5 } from "react-native-paper";
947
- import { Fragment as Fragment6, jsx as jsx15, jsxs as jsxs13 } from "react/jsx-runtime";
970
+ import { StyleSheet as StyleSheet14, View as View13 } from "react-native";
971
+ import { Icon as Icon6 } from "react-native-paper";
972
+ import { Fragment as Fragment5, jsx as jsx17, jsxs as jsxs14 } from "react/jsx-runtime";
948
973
  var BADGE_SIZE = 30;
949
974
  function StatusBadge({ icon }) {
950
- return /* @__PURE__ */ jsx15(View11, { style: styles12.badge, children: icon && /* @__PURE__ */ jsx15(Icon5, { source: icon, size: 16, color: "rgba(255,255,255,0.85)" }) });
975
+ return /* @__PURE__ */ jsx17(View13, { style: styles14.badge, children: icon && /* @__PURE__ */ jsx17(Icon6, { source: icon, size: 16, color: "rgba(255,255,255,0.85)" }) });
951
976
  }
952
977
  function CornerStatusBadges({ orientationMode, p1OnRight, p1, p2 }) {
953
978
  const p1OnRightSide = orientationMode === "sideBySide" && p1OnRight;
954
979
  const p2OnLeftSide = orientationMode === "sideBySide" && !p1OnRight;
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 }) })
980
+ return /* @__PURE__ */ jsxs14(Fragment5, { children: [
981
+ p1 && /* @__PURE__ */ jsx17(View13, { pointerEvents: "none", style: p1OnRightSide ? styles14.bottomRight : styles14.bottomLeft, children: /* @__PURE__ */ jsx17(StatusBadge, { icon: p1.icon }) }),
982
+ p2 && /* @__PURE__ */ jsx17(View13, { pointerEvents: "none", style: p2OnLeftSide ? styles14.topLeft : styles14.topRight, children: /* @__PURE__ */ jsx17(StatusBadge, { icon: p2.icon }) })
958
983
  ] });
959
984
  }
960
- var styles12 = StyleSheet13.create({
985
+ var styles14 = StyleSheet14.create({
961
986
  badge: {
962
987
  alignItems: "center",
963
988
  backgroundColor: "rgba(0,0,0,0.28)",
@@ -976,12 +1001,12 @@ var styles12 = StyleSheet13.create({
976
1001
  });
977
1002
 
978
1003
  // src/InlineColorPicker.tsx
979
- import { defaultColors, getContrastColor } from "@rific/auto-paper";
1004
+ import { defaultColors, getContrastColor as getContrastColor2 } from "@rific/auto-paper";
980
1005
  import { TouchableRipple as TouchableRipple3 } from "@rific/feedback-press";
981
- import { clamp, useRotation as useRotation4 } from "@tastic/core";
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";
1006
+ import { clamp, useRotation as useRotation5 } from "@tastic/core";
1007
+ import { ScrollView as ScrollView4, StyleSheet as StyleSheet15, useWindowDimensions as useWindowDimensions3, View as View14 } from "react-native";
1008
+ import { Icon as Icon7, Text as Text10 } from "react-native-paper";
1009
+ import { jsx as jsx18, jsxs as jsxs15 } from "react/jsx-runtime";
985
1010
  var EMOJI_PATTERN = /\p{Extended_Pictographic}/u;
986
1011
  var DEFAULT_SIZE = 48;
987
1012
  var SWATCH_SIZE = 28;
@@ -1003,7 +1028,7 @@ function getInlineColorPickerContentSize(swatchCount, windowWidth, columns) {
1003
1028
  return { width, height };
1004
1029
  }
1005
1030
  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 }) {
1006
- const ambientRotation = useRotation4();
1031
+ const ambientRotation = useRotation5();
1007
1032
  const rotation = rotationOverride ?? ambientRotation;
1008
1033
  const menuBg = dark ? "#000000" : "#FFFFFF";
1009
1034
  const { width: windowWidth } = useWindowDimensions3();
@@ -1015,16 +1040,16 @@ function InlineColorPicker({ id, host, value, onChange, previewValue, swatches =
1015
1040
  const align = forcedAlign ?? placement.align;
1016
1041
  const displayFor = previewValue ?? ((hex) => hex);
1017
1042
  const displayValue = displayFor(value);
1018
- const contrastColor = getContrastColor(displayValue);
1043
+ const contrastColor = getContrastColor2(displayValue);
1019
1044
  const tagFontSize = size * (tag && EMOJI_PATTERN.test(tag) ? 0.6 : 0.4);
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) => {
1045
+ return /* @__PURE__ */ jsxs15(View14, { style: [styles15.anchor, open && styles15.anchorOpen], children: [
1046
+ /* @__PURE__ */ jsx18(TouchableRipple3, { onPress: () => host.toggle(id), borderless: true, style: [styles15.trigger, { backgroundColor: displayValue, borderRadius: size / 2, height: size, width: size }], children: /* @__PURE__ */ jsx18(View14, { ref: triggerRef, collapsable: false, style: styles15.triggerMeasure, children: tag ? /* @__PURE__ */ jsx18(Text10, { style: [styles15.tagLabel, { color: contrastColor, fontFamily: labelFontFamily, fontSize: tagFontSize }], numberOfLines: 1, adjustsFontSizeToFit: true, children: tag }) : /* @__PURE__ */ jsx18(Icon7, { source: icon, size: size * 0.6, color: contrastColor }) }) }),
1047
+ /* @__PURE__ */ jsx18(PopoverBody, { visible: open && measured, align, verticalAlign, caretColor: menuBg, caretBorderColor: displayValue, caretBorderWidth: SWATCHES_BORDER_WIDTH, triggerSize: size, children: /* @__PURE__ */ jsx18(ScrollView4, { style: [styles15.swatches, { backgroundColor: menuBg, borderColor: displayValue, width: swatchesWidth, maxHeight }], contentContainerStyle: styles15.swatchesContent, showsVerticalScrollIndicator: false, children: swatches.map((swatch) => {
1023
1048
  const selected = swatch.value.toLowerCase() === value.toLowerCase();
1024
1049
  const taken = !selected && !!takenValue && swatch.value.toLowerCase() === takenValue.toLowerCase();
1025
1050
  const swappable = taken && allowSwapTaken;
1026
1051
  const swatchDisplay = displayFor(swatch.value);
1027
- return /* @__PURE__ */ jsx16(
1052
+ return /* @__PURE__ */ jsx18(
1028
1053
  TouchableRipple3,
1029
1054
  {
1030
1055
  disabled: taken && !swappable,
@@ -1033,15 +1058,15 @@ function InlineColorPicker({ id, host, value, onChange, previewValue, swatches =
1033
1058
  if (autoDismiss) host.close();
1034
1059
  },
1035
1060
  borderless: true,
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, {})
1061
+ style: [styles15.swatch, { backgroundColor: swatchDisplay }, selected && styles15.swatchSelected, taken && !swappable && styles15.swatchTaken],
1062
+ children: selected ? /* @__PURE__ */ jsx18(Icon7, { source: "check", size: 16, color: getContrastColor2(swatchDisplay) }) : swappable ? /* @__PURE__ */ jsx18(Icon7, { source: "swap-horizontal", size: 16, color: getContrastColor2(swatchDisplay) }) : taken ? /* @__PURE__ */ jsx18(Icon7, { source: "close", size: 16, color: getContrastColor2(swatchDisplay) }) : /* @__PURE__ */ jsx18(View14, {})
1038
1063
  },
1039
1064
  swatch.value
1040
1065
  );
1041
1066
  }) }) })
1042
1067
  ] });
1043
1068
  }
1044
- var styles13 = StyleSheet14.create({
1069
+ var styles15 = StyleSheet15.create({
1045
1070
  anchor: {
1046
1071
  position: "relative"
1047
1072
  },
@@ -1113,11 +1138,11 @@ var styles13 = StyleSheet14.create({
1113
1138
  });
1114
1139
 
1115
1140
  // src/LabeledDropdown.tsx
1116
- import { getContrastColor as getContrastColor2 } from "@rific/auto-paper";
1141
+ import { getContrastColor as getContrastColor3 } from "@rific/auto-paper";
1117
1142
  import { TouchableRipple as TouchableRipple4 } from "@rific/feedback-press";
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";
1143
+ import { ScrollView as ScrollView5, StyleSheet as StyleSheet16, View as View15 } from "react-native";
1144
+ import { Icon as Icon8, Text as Text11 } from "react-native-paper";
1145
+ import { jsx as jsx19, jsxs as jsxs16 } from "react/jsx-runtime";
1121
1146
  var TRIGGER_HEIGHT = 28;
1122
1147
  var POPOVER_WIDTH = 180;
1123
1148
  var ROW_HEIGHT = 36;
@@ -1140,22 +1165,22 @@ function LabeledDropdown({ id, host, options, value, onChange, color, dark, alig
1140
1165
  onChange(option.value);
1141
1166
  host.close();
1142
1167
  };
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 })
1168
+ return /* @__PURE__ */ jsxs16(View15, { style: [styles16.anchor, open && styles16.anchorOpen], children: [
1169
+ /* @__PURE__ */ jsx19(TouchableRipple4, { onPress: () => host.toggle(id), style: styles16.trigger, children: /* @__PURE__ */ jsxs16(View15, { ref: triggerRef, collapsable: false, style: styles16.triggerInner, children: [
1170
+ /* @__PURE__ */ jsx19(Text11, { style: [styles16.triggerLabel, { color }], numberOfLines: 1, children: (selected?.label ?? "").toUpperCase() }),
1171
+ /* @__PURE__ */ jsx19(Icon8, { source: "menu-down", size: 16, color })
1147
1172
  ] }) }),
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) => {
1173
+ /* @__PURE__ */ jsx19(PopoverBody, { visible: open && measured, align, verticalAlign, caretColor: menuBg, caretBorderColor: color, caretBorderWidth: 2, triggerSize: TRIGGER_HEIGHT, children: /* @__PURE__ */ jsx19(ScrollView5, { style: [styles16.menu, { backgroundColor: menuBg, borderColor: color, width: POPOVER_WIDTH, maxHeight }], contentContainerStyle: styles16.menuContent, showsVerticalScrollIndicator: false, children: options.map((option) => {
1149
1174
  const isSelected = option.value === value;
1150
- const onColor = getContrastColor2(color);
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 })
1175
+ const onColor = getContrastColor3(color);
1176
+ return /* @__PURE__ */ jsx19(TouchableRipple4, { onPress: () => handleSelect(option), style: [styles16.row, isSelected && { backgroundColor: color }], children: /* @__PURE__ */ jsxs16(View15, { style: styles16.rowInner, children: [
1177
+ option.icon && /* @__PURE__ */ jsx19(Icon8, { source: option.icon, size: 18, color: isSelected ? onColor : fg }),
1178
+ /* @__PURE__ */ jsx19(Text11, { style: [styles16.rowLabel, { color: isSelected ? onColor : fg }], numberOfLines: 1, children: option.label })
1154
1179
  ] }) }, option.value);
1155
1180
  }) }) })
1156
1181
  ] });
1157
1182
  }
1158
- var styles14 = StyleSheet15.create({
1183
+ var styles16 = StyleSheet16.create({
1159
1184
  anchor: {
1160
1185
  position: "relative"
1161
1186
  },
@@ -1214,21 +1239,21 @@ function loadSkiaWeb() {
1214
1239
 
1215
1240
  // src/PlayerSetupPanel.tsx
1216
1241
  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";
1242
+ import { StyleSheet as StyleSheet18, View as View16 } from "react-native";
1243
+ import { Text as Text13 } from "react-native-paper";
1219
1244
 
1220
1245
  // src/ReadyButton.tsx
1221
1246
  import { TouchableRipple as TouchableRipple5 } from "@rific/feedback-press";
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";
1247
+ import { StyleSheet as StyleSheet17 } from "react-native";
1248
+ import { Text as Text12 } from "react-native-paper";
1249
+ import { jsx as jsx20 } from "react/jsx-runtime";
1225
1250
  function ReadyButton({ color, ready, onToggleReady, style, labelFontFamily = MONO_FONT }) {
1226
- const readyButtonStyle = [styles15.readyButton, { borderColor: color }, ready && { backgroundColor: color }, style];
1251
+ const readyButtonStyle = [styles17.readyButton, { borderColor: color }, ready && { backgroundColor: color }, style];
1227
1252
  const labelTextStyle = { fontFamily: labelFontFamily, fontWeight: "bold" };
1228
1253
  const labelColorStyle = { color: ready ? "#000000" : color };
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?" }) });
1254
+ return /* @__PURE__ */ jsx20(TouchableRipple5, { onPress: onToggleReady, borderless: true, style: readyButtonStyle, children: /* @__PURE__ */ jsx20(Text12, { variant: "labelLarge", style: [labelTextStyle, labelColorStyle], children: ready ? "READY \u2713" : "READY?" }) });
1230
1255
  }
1231
- var styles15 = StyleSheet16.create({
1256
+ var styles17 = StyleSheet17.create({
1232
1257
  readyButton: {
1233
1258
  alignItems: "center",
1234
1259
  borderRadius: 12,
@@ -1252,7 +1277,7 @@ function usePopoverHost() {
1252
1277
  }
1253
1278
 
1254
1279
  // src/PlayerSetupPanel.tsx
1255
- import { jsx as jsx19, jsxs as jsxs16 } from "react/jsx-runtime";
1280
+ import { jsx as jsx21, jsxs as jsxs17 } from "react/jsx-runtime";
1256
1281
  function getColorPopoverId(idPrefix) {
1257
1282
  return `${idPrefix}-color`;
1258
1283
  }
@@ -1267,16 +1292,16 @@ function PlayerSetupPanel({ idPrefix, host, label, labelFontFamily, color, onCol
1267
1292
  const showProfilePicker = isHuman && profiles !== void 0 && !!onProfileSelect;
1268
1293
  const showCpuDifficulty = !isHuman && cpuDifficulty !== void 0 && cpuDifficultyOptions !== void 0 && !!onCpuDifficultyChange;
1269
1294
  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 }),
1295
+ return /* @__PURE__ */ jsxs17(View16, { style: [styles18.panel, ownPopoverOpen && styles18.panelOpen], children: [
1296
+ showProfilePicker ? /* @__PURE__ */ jsx21(ProfilePicker, { idPrefix, host: popover, profiles, selectedId: selectedProfileId ?? null, takenId: takenProfileId, color, dark, guestLabel: guestLabel ?? "GUEST", onSelect: (profile) => onProfileSelect?.(profile), onManage: onManageProfiles }) : showCpuDifficulty ? /* @__PURE__ */ jsx21(LabeledDropdown, { id: getCpuDifficultyPopoverId(idPrefix), host: popover, options: cpuDifficultyOptions, value: cpuDifficulty, onChange: onCpuDifficultyChange, color, dark, alignOverride: cpuDifficultyAlignOverride }) : label && /* @__PURE__ */ jsx21(Text13, { variant: "labelSmall", style: { color, fontFamily: labelFontFamily }, children: label }),
1297
+ /* @__PURE__ */ jsxs17(View16, { style: [styles18.pickerRow, pickerRowPopoverOpen && styles18.pickerRowOpen], children: [
1298
+ /* @__PURE__ */ jsx21(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
1299
  secondPicker
1275
1300
  ] }),
1276
- isHuman && showReadyButton && onToggleReady && /* @__PURE__ */ jsx19(ReadyButton, { color, ready: ready ?? false, onToggleReady })
1301
+ isHuman && showReadyButton && onToggleReady && /* @__PURE__ */ jsx21(ReadyButton, { color, ready: ready ?? false, onToggleReady })
1277
1302
  ] });
1278
1303
  }
1279
- var styles16 = StyleSheet17.create({
1304
+ var styles18 = StyleSheet18.create({
1280
1305
  panel: {
1281
1306
  alignItems: "center",
1282
1307
  gap: 12
@@ -1308,29 +1333,29 @@ var styles16 = StyleSheet17.create({
1308
1333
  });
1309
1334
 
1310
1335
  // src/PressAwayOverlay.tsx
1311
- import { Pressable, StyleSheet as StyleSheet18 } from "react-native";
1312
- import { jsx as jsx20 } from "react/jsx-runtime";
1336
+ import { Pressable, StyleSheet as StyleSheet19 } from "react-native";
1337
+ import { jsx as jsx22 } from "react/jsx-runtime";
1313
1338
  function PressAwayOverlay({ active, onPress, style }) {
1314
1339
  if (!active) return null;
1315
- return /* @__PURE__ */ jsx20(Pressable, { accessibilityLabel: "Dismiss", accessibilityRole: "button", onPress, style: [StyleSheet18.absoluteFill, style] });
1340
+ return /* @__PURE__ */ jsx22(Pressable, { accessibilityLabel: "Dismiss", accessibilityRole: "button", onPress, style: [StyleSheet19.absoluteFill, style] });
1316
1341
  }
1317
1342
 
1318
1343
  // src/SharedActionBand.tsx
1319
1344
  import { IconButton as IconButton4 } from "@rific/feedback-press";
1320
- import { StyleSheet as StyleSheet19, View as View15 } from "react-native";
1321
- import { jsx as jsx21, jsxs as jsxs17 } from "react/jsx-runtime";
1345
+ import { StyleSheet as StyleSheet20, View as View17 } from "react-native";
1346
+ import { jsx as jsx23, jsxs as jsxs18 } from "react/jsx-runtime";
1322
1347
  function SharedActionBand({ onBack, onSettings, onRandomize, onReset, fg, popoverOpen, children }) {
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" })
1348
+ return /* @__PURE__ */ jsxs18(View17, { style: [styles19.column, popoverOpen && styles19.columnOpen], children: [
1349
+ /* @__PURE__ */ jsxs18(View17, { style: styles19.actionsRow, children: [
1350
+ /* @__PURE__ */ jsx23(IconButton4, { icon: "arrow-left", iconColor: fg, size: 20, onPress: onBack, accessibilityLabel: "Back" }),
1351
+ onRandomize && /* @__PURE__ */ jsx23(IconButton4, { icon: "dice-multiple", iconColor: fg, size: 18, onPress: onRandomize, accessibilityLabel: "Randomize match settings" }),
1352
+ onReset && /* @__PURE__ */ jsx23(IconButton4, { icon: "restore", iconColor: fg, size: 18, onPress: onReset, accessibilityLabel: "Reset match settings to defaults" }),
1353
+ /* @__PURE__ */ jsx23(IconButton4, { icon: "cog", iconColor: fg, size: 20, onPress: onSettings, accessibilityLabel: "Settings" })
1329
1354
  ] }),
1330
1355
  children
1331
1356
  ] });
1332
1357
  }
1333
- var styles17 = StyleSheet19.create({
1358
+ var styles19 = StyleSheet20.create({
1334
1359
  actionsRow: {
1335
1360
  alignItems: "center",
1336
1361
  flexDirection: "row",
@@ -1347,9 +1372,9 @@ var styles17 = StyleSheet19.create({
1347
1372
 
1348
1373
  // src/StaggeredWord.tsx
1349
1374
  import { useEffect as useEffect2 } from "react";
1350
- import { StyleSheet as StyleSheet20, View as View16 } from "react-native";
1375
+ import { StyleSheet as StyleSheet21, View as View18 } from "react-native";
1351
1376
  import Animated, { Easing, useAnimatedStyle, useSharedValue, withDelay, withTiming } from "react-native-reanimated";
1352
- import { jsx as jsx22 } from "react/jsx-runtime";
1377
+ import { jsx as jsx24 } from "react/jsx-runtime";
1353
1378
  var STAGGER_MS = 45;
1354
1379
  var LETTER_DURATION_MS = 320;
1355
1380
  function getStaggeredWordDuration(letterCount) {
@@ -1365,12 +1390,12 @@ function AnimatedLetter({ char, index, color, reducedMotion, fontFamily, fontSiz
1365
1390
  opacity: progress.value,
1366
1391
  transform: [{ translateY: (1 - progress.value) * 12 }, { scale: 0.85 + progress.value * 0.15 }]
1367
1392
  }));
1368
- return /* @__PURE__ */ jsx22(Animated.Text, { allowFontScaling: false, style: [{ color, fontFamily, fontSize, lineHeight, fontWeight, letterSpacing }, style], children: char });
1393
+ return /* @__PURE__ */ jsx24(Animated.Text, { allowFontScaling: false, style: [{ color, fontFamily, fontSize, lineHeight, fontWeight, letterSpacing }, style], children: char });
1369
1394
  }
1370
1395
  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)) });
1396
+ return /* @__PURE__ */ jsx24(View18, { style: [styles20.row, style], onLayout, children: word.split("").map((char, i) => /* @__PURE__ */ jsx24(AnimatedLetter, { char, index: startIndex + i, color, reducedMotion, fontFamily, fontSize, lineHeight, fontWeight, letterSpacing }, i)) });
1372
1397
  }
1373
- var styles18 = StyleSheet20.create({
1398
+ var styles20 = StyleSheet21.create({
1374
1399
  row: {
1375
1400
  flexDirection: "row"
1376
1401
  }
@@ -1378,12 +1403,12 @@ var styles18 = StyleSheet20.create({
1378
1403
 
1379
1404
  // src/UpdateDialog.tsx
1380
1405
  import { useUpdater as useUpdater2 } from "@rific/updater";
1381
- import { jsx as jsx23 } from "react/jsx-runtime";
1406
+ import { jsx as jsx25 } from "react/jsx-runtime";
1382
1407
  function UpdateDialog({ rotation = 0, autoCheck = true, autoPrompt = true, onError }) {
1383
1408
  const { manifest, onConfirm, respond } = useUpdateConfirmBridge();
1384
1409
  useUpdater2({ autoCheck, autoPrompt, onConfirm, onError });
1385
1410
  const date = manifest ? new Date(manifest.createdAt) : null;
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) });
1411
+ return /* @__PURE__ */ jsx25(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) });
1387
1412
  }
1388
1413
 
1389
1414
  // src/useQuitConfirmation.ts
@@ -1410,13 +1435,13 @@ function useQuitConfirmation(hasProgress, onConfirmedBack) {
1410
1435
  import { useZoneBounds } from "@tastic/split-screen";
1411
1436
  import { useEffect as useEffect4, useState as useState7 } from "react";
1412
1437
  import { useWindowDimensions as useWindowDimensions4 } from "react-native";
1413
- import { useSafeAreaInsets } from "react-native-safe-area-context";
1438
+ import { useSafeAreaInsets as useSafeAreaInsets2 } from "react-native-safe-area-context";
1414
1439
  var EDGE_MARGIN2 = 12;
1415
1440
  function useZoneClampedAlign(open, contentWidth, contentHeight, rotation = 0) {
1416
1441
  const auto = useAutoAlign(open, contentWidth, contentHeight, rotation);
1417
1442
  const zone = useZoneBounds();
1418
1443
  const { height: windowHeight } = useWindowDimensions4();
1419
- const insets = useSafeAreaInsets();
1444
+ const insets = useSafeAreaInsets2();
1420
1445
  const shouldMeasure = open && auto.measured && zone !== null;
1421
1446
  const [ownBounds, setOwnBounds] = useState7(null);
1422
1447
  const [prevShouldMeasure, setPrevShouldMeasure] = useState7(shouldMeasure);
@@ -1447,6 +1472,7 @@ function useZoneClampedAlign(open, contentWidth, contentHeight, rotation = 0) {
1447
1472
  export {
1448
1473
  AchievementCatalogSection,
1449
1474
  AchievementRow,
1475
+ AchievementUnlockList,
1450
1476
  ActivityStatSection,
1451
1477
  BaseSettingsDialog,
1452
1478
  BaseStatsScreen,
@@ -1464,6 +1490,7 @@ export {
1464
1490
  PopoverBody,
1465
1491
  PressAwayOverlay,
1466
1492
  ReadyButton,
1493
+ RotatedFrame,
1467
1494
  SectionedDropdown,
1468
1495
  SharedActionBand,
1469
1496
  SkiaGate,
@@ -1479,6 +1506,7 @@ export {
1479
1506
  getOverlayCardColors,
1480
1507
  getStaggeredWordDuration,
1481
1508
  loadSkiaWeb,
1509
+ overlayActionStyles,
1482
1510
  overlayStyles,
1483
1511
  useAutoAlign,
1484
1512
  usePopoverHost,