@tastic/hud 0.13.0 → 0.14.1

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
@@ -215,10 +215,10 @@ function ActivityStatSection({ stats }) {
215
215
  import { AutoAppearancePicker, Dialog, useAutoPaperTheme as useAutoPaperTheme7 } from "@rific/auto-paper";
216
216
  import { Button as Button2, SoundContext, TouchableRipple, useHapticSettings, useSoundSettings, useVibration } from "@rific/feedback-press";
217
217
  import { useUpdater } from "@rific/updater";
218
- import { toRotationStyle as toRotationStyle2, useIsTouchPrimaryDevice, useRotation } from "@tastic/core";
218
+ import { useIsTouchPrimaryDevice, useRotation as useRotation2 } from "@tastic/core";
219
219
  import { useContext, useState as useState2 } from "react";
220
- import { Platform as Platform2, ScrollView, StyleSheet as StyleSheet7, View as View6 } from "react-native";
221
- import { Icon as Icon4, Text as Text7 } 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";
222
222
 
223
223
  // src/ConfirmDialog.tsx
224
224
  import { useAutoPaperTheme as useAutoPaperTheme6 } from "@rific/auto-paper";
@@ -272,6 +272,36 @@ var styles6 = StyleSheet6.create({
272
272
  }
273
273
  });
274
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
+
275
305
  // src/useUpdateConfirmBridge.ts
276
306
  import { useCallback, useRef, useState } from "react";
277
307
  function useUpdateConfirmBridge() {
@@ -293,13 +323,13 @@ function useUpdateConfirmBridge() {
293
323
  }
294
324
 
295
325
  // src/BaseSettingsDialog.tsx
296
- import { Fragment as Fragment2, jsx as jsx8, jsxs as jsxs8 } from "react/jsx-runtime";
326
+ import { jsx as jsx9, jsxs as jsxs8 } from "react/jsx-runtime";
297
327
  function SettingIcon({ source, color, containerColor }) {
298
- return /* @__PURE__ */ jsx8(View6, { style: [styles7.iconBadge, { backgroundColor: containerColor }], children: /* @__PURE__ */ jsx8(Icon4, { source, size: 18, color }) });
328
+ return /* @__PURE__ */ jsx9(View7, { style: [styles8.iconBadge, { backgroundColor: containerColor }], children: /* @__PURE__ */ jsx9(Icon4, { source, size: 18, color }) });
299
329
  }
300
330
  function BaseSettingsDialog({ visible, onDismiss, rotation: rotationOverride, version, lockOrientation, onLockOrientationChange, deferBottomEdgeGestures, onDeferBottomEdgeGestures, hideSound = false, hideHaptics = false, hideAppearance = false, hideUpdateCheck = false, onUpdateError, onShowHowToPlay, children }) {
301
331
  const { colors } = useAutoPaperTheme7();
302
- const ambientRotation = useRotation();
332
+ const ambientRotation = useRotation2();
303
333
  const rotation = rotationOverride ?? ambientRotation;
304
334
  const isTouchPrimary = useIsTouchPrimaryDevice();
305
335
  const { settings: hapticSettings, set: setHapticSettings } = useHapticSettings();
@@ -316,33 +346,36 @@ function BaseSettingsDialog({ visible, onDismiss, rotation: rotationOverride, ve
316
346
  onInfo: (title, message) => setInfoMessage({ title, message })
317
347
  });
318
348
  const updateManifestDate = updateManifest ? new Date(updateManifest.createdAt) : null;
349
+ const [opened, setOpened] = useState2(visible);
350
+ if (visible && !opened) setOpened(true);
319
351
  const showLockOrientation = isTouchPrimary && lockOrientation !== void 0 && onLockOrientationChange !== void 0;
320
352
  const showEdgeGuard = Platform2.OS === "ios" && deferBottomEdgeGestures !== void 0 && onDeferBottomEdgeGestures !== void 0;
321
353
  const showHaptics = Platform2.OS !== "web" && !hideHaptics;
322
354
  const showSound = !hideSound;
323
355
  const showAppearance = !hideAppearance;
324
356
  const showUpdateCheck = Platform2.OS !== "web" && !hideUpdateCheck;
325
- return /* @__PURE__ */ jsxs8(Fragment2, { children: [
326
- /* @__PURE__ */ jsxs8(Dialog, { visible, onDismiss, style: [styles7.dialog, toRotationStyle2(rotation)], children: [
327
- /* @__PURE__ */ jsx8(Dialog.Title, { children: "Settings" }),
328
- /* @__PURE__ */ jsx8(Dialog.ScrollArea, { style: styles7.scrollArea, children: /* @__PURE__ */ jsxs8(ScrollView, { contentContainerStyle: styles7.content, showsVerticalScrollIndicator: false, children: [
329
- /* @__PURE__ */ jsxs8(View6, { style: styles7.toggleGroup, children: [
330
- showLockOrientation && /* @__PURE__ */ jsx8(TouchableRipple, { onPress: () => onLockOrientationChange(!lockOrientation), style: styles7.toggleButton, accessibilityLabel: `Lock orientation ${lockOrientation ? "on" : "off"}`, children: /* @__PURE__ */ jsxs8(View6, { style: styles7.toggleContent, children: [
331
- /* @__PURE__ */ jsx8(SettingIcon, { source: lockOrientation ? "lock" : "lock-open-variant-outline", color: lockOrientation ? colors.secondary : colors.onSurfaceVariant, containerColor: lockOrientation ? colors.secondaryContainer : colors.surfaceVariant }),
332
- /* @__PURE__ */ jsxs8(View6, { style: styles7.flexShrink, children: [
333
- /* @__PURE__ */ jsx8(Text7, { variant: "bodyLarge", style: { color: colors.onSurface }, children: "Lock Orientation" }),
334
- /* @__PURE__ */ jsx8(Text7, { variant: "bodySmall", numberOfLines: 1, style: { color: colors.onSurfaceVariant }, children: "Pins the current layout" })
357
+ if (!opened) return null;
358
+ return /* @__PURE__ */ jsx9(Portal3, { children: /* @__PURE__ */ jsxs8(RotatedFrame, { rotation, rotatedSafeArea: true, portalHost: true, passThrough: true, children: [
359
+ /* @__PURE__ */ jsxs8(Dialog, { visible, onDismiss, style: styles8.dialog, children: [
360
+ /* @__PURE__ */ jsx9(Dialog.Title, { children: "Settings" }),
361
+ /* @__PURE__ */ jsx9(Dialog.ScrollArea, { style: styles8.scrollArea, children: /* @__PURE__ */ jsxs8(ScrollView, { contentContainerStyle: styles8.content, showsVerticalScrollIndicator: false, children: [
362
+ /* @__PURE__ */ jsxs8(View7, { style: styles8.toggleGroup, children: [
363
+ showLockOrientation && /* @__PURE__ */ jsx9(TouchableRipple, { onPress: () => onLockOrientationChange(!lockOrientation), style: styles8.toggleButton, accessibilityLabel: `Lock orientation ${lockOrientation ? "on" : "off"}`, children: /* @__PURE__ */ jsxs8(View7, { style: styles8.toggleContent, children: [
364
+ /* @__PURE__ */ jsx9(SettingIcon, { source: lockOrientation ? "lock" : "lock-open-variant-outline", color: lockOrientation ? colors.secondary : colors.onSurfaceVariant, containerColor: lockOrientation ? colors.secondaryContainer : colors.surfaceVariant }),
365
+ /* @__PURE__ */ jsxs8(View7, { style: styles8.flexShrink, children: [
366
+ /* @__PURE__ */ jsx9(Text7, { variant: "bodyLarge", style: { color: colors.onSurface }, children: "Lock Orientation" }),
367
+ /* @__PURE__ */ jsx9(Text7, { variant: "bodySmall", numberOfLines: 1, style: { color: colors.onSurfaceVariant }, children: "Pins the current layout" })
335
368
  ] })
336
369
  ] }) }),
337
- showEdgeGuard && /* @__PURE__ */ jsx8(TouchableRipple, { onPress: () => onDeferBottomEdgeGestures(!deferBottomEdgeGestures), style: styles7.toggleButton, accessibilityLabel: `Edge guard ${deferBottomEdgeGestures ? "on" : "off"}`, children: /* @__PURE__ */ jsxs8(View6, { style: styles7.toggleContent, children: [
338
- /* @__PURE__ */ jsx8(SettingIcon, { source: deferBottomEdgeGestures ? "shield-check-outline" : "shield-off-outline", color: deferBottomEdgeGestures ? colors.secondary : colors.onSurfaceVariant, containerColor: deferBottomEdgeGestures ? colors.secondaryContainer : colors.surfaceVariant }),
339
- /* @__PURE__ */ jsxs8(View6, { style: styles7.flexShrink, children: [
340
- /* @__PURE__ */ jsx8(Text7, { variant: "bodyLarge", style: { color: colors.onSurface }, children: "Edge Guard" }),
341
- /* @__PURE__ */ jsx8(Text7, { variant: "bodySmall", numberOfLines: 1, style: { color: colors.onSurfaceVariant }, children: "Requires a second swipe" })
370
+ showEdgeGuard && /* @__PURE__ */ jsx9(TouchableRipple, { onPress: () => onDeferBottomEdgeGestures(!deferBottomEdgeGestures), style: styles8.toggleButton, accessibilityLabel: `Edge guard ${deferBottomEdgeGestures ? "on" : "off"}`, children: /* @__PURE__ */ jsxs8(View7, { style: styles8.toggleContent, children: [
371
+ /* @__PURE__ */ jsx9(SettingIcon, { source: deferBottomEdgeGestures ? "shield-check-outline" : "shield-off-outline", color: deferBottomEdgeGestures ? colors.secondary : colors.onSurfaceVariant, containerColor: deferBottomEdgeGestures ? colors.secondaryContainer : colors.surfaceVariant }),
372
+ /* @__PURE__ */ jsxs8(View7, { style: styles8.flexShrink, children: [
373
+ /* @__PURE__ */ jsx9(Text7, { variant: "bodyLarge", style: { color: colors.onSurface }, children: "Edge Guard" }),
374
+ /* @__PURE__ */ jsx9(Text7, { variant: "bodySmall", numberOfLines: 1, style: { color: colors.onSurfaceVariant }, children: "Requires a second swipe" })
342
375
  ] })
343
376
  ] }) }),
344
- (showSound || showHaptics) && /* @__PURE__ */ jsxs8(View6, { style: styles7.toggleRow, children: [
345
- showSound && /* @__PURE__ */ jsx8(
377
+ (showSound || showHaptics) && /* @__PURE__ */ jsxs8(View7, { style: styles8.toggleRow, children: [
378
+ showSound && /* @__PURE__ */ jsx9(
346
379
  TouchableRipple,
347
380
  {
348
381
  soundDisabled: true,
@@ -351,15 +384,15 @@ function BaseSettingsDialog({ visible, onDismiss, rotation: rotationOverride, ve
351
384
  setSoundSettings({ enabled });
352
385
  if (enabled) sound.selection?.();
353
386
  },
354
- style: styles7.toggleButtonInRow,
387
+ style: styles8.toggleButtonInRow,
355
388
  accessibilityLabel: `Sound ${soundSettings.enabled ? "on" : "off"}`,
356
- children: /* @__PURE__ */ jsxs8(View6, { style: styles7.toggleContent, children: [
357
- /* @__PURE__ */ jsx8(SettingIcon, { source: soundSettings.enabled ? "volume-high" : "volume-off", color: soundSettings.enabled ? colors.tertiary : colors.onSurfaceVariant, containerColor: soundSettings.enabled ? colors.tertiaryContainer : colors.surfaceVariant }),
358
- /* @__PURE__ */ jsx8(Text7, { variant: "bodyLarge", style: { color: colors.onSurface }, children: "Sound" })
389
+ children: /* @__PURE__ */ jsxs8(View7, { style: styles8.toggleContent, children: [
390
+ /* @__PURE__ */ jsx9(SettingIcon, { source: soundSettings.enabled ? "volume-high" : "volume-off", color: soundSettings.enabled ? colors.tertiary : colors.onSurfaceVariant, containerColor: soundSettings.enabled ? colors.tertiaryContainer : colors.surfaceVariant }),
391
+ /* @__PURE__ */ jsx9(Text7, { variant: "bodyLarge", style: { color: colors.onSurface }, children: "Sound" })
359
392
  ] })
360
393
  }
361
394
  ),
362
- showHaptics && /* @__PURE__ */ jsx8(
395
+ showHaptics && /* @__PURE__ */ jsx9(
363
396
  TouchableRipple,
364
397
  {
365
398
  hapticDisabled: true,
@@ -368,54 +401,54 @@ function BaseSettingsDialog({ visible, onDismiss, rotation: rotationOverride, ve
368
401
  setHapticSettings({ vibrate });
369
402
  if (vibrate) forceHapticFeedback();
370
403
  },
371
- style: styles7.toggleButtonInRow,
404
+ style: styles8.toggleButtonInRow,
372
405
  accessibilityLabel: `Haptics ${hapticSettings.vibrate ? "on" : "off"}`,
373
- children: /* @__PURE__ */ jsxs8(View6, { style: styles7.toggleContent, children: [
374
- /* @__PURE__ */ jsx8(SettingIcon, { source: hapticSettings.vibrate ? "vibrate" : "vibrate-off", color: hapticSettings.vibrate ? colors.tertiary : colors.onSurfaceVariant, containerColor: hapticSettings.vibrate ? colors.tertiaryContainer : colors.surfaceVariant }),
375
- /* @__PURE__ */ jsx8(Text7, { variant: "bodyLarge", style: { color: colors.onSurface }, children: "Haptics" })
406
+ children: /* @__PURE__ */ jsxs8(View7, { style: styles8.toggleContent, children: [
407
+ /* @__PURE__ */ jsx9(SettingIcon, { source: hapticSettings.vibrate ? "vibrate" : "vibrate-off", color: hapticSettings.vibrate ? colors.tertiary : colors.onSurfaceVariant, containerColor: hapticSettings.vibrate ? colors.tertiaryContainer : colors.surfaceVariant }),
408
+ /* @__PURE__ */ jsx9(Text7, { variant: "bodyLarge", style: { color: colors.onSurface }, children: "Haptics" })
376
409
  ] })
377
410
  }
378
411
  )
379
412
  ] }),
380
- onShowHowToPlay && /* @__PURE__ */ jsx8(
413
+ onShowHowToPlay && /* @__PURE__ */ jsx9(
381
414
  TouchableRipple,
382
415
  {
383
416
  onPress: () => {
384
417
  onDismiss();
385
418
  onShowHowToPlay();
386
419
  },
387
- style: styles7.toggleButton,
420
+ style: styles8.toggleButton,
388
421
  accessibilityLabel: "How to Play",
389
- children: /* @__PURE__ */ jsxs8(View6, { style: styles7.toggleContent, children: [
390
- /* @__PURE__ */ jsx8(SettingIcon, { source: "help-circle-outline", color: colors.secondary, containerColor: colors.secondaryContainer }),
391
- /* @__PURE__ */ jsxs8(View6, { style: styles7.flexShrink, children: [
392
- /* @__PURE__ */ jsx8(Text7, { variant: "bodyLarge", style: { color: colors.onSurface }, children: "How to Play" }),
393
- /* @__PURE__ */ jsx8(Text7, { variant: "bodySmall", numberOfLines: 1, style: { color: colors.onSurfaceVariant }, children: "Replay the quick intro" })
422
+ children: /* @__PURE__ */ jsxs8(View7, { style: styles8.toggleContent, children: [
423
+ /* @__PURE__ */ jsx9(SettingIcon, { source: "help-circle-outline", color: colors.secondary, containerColor: colors.secondaryContainer }),
424
+ /* @__PURE__ */ jsxs8(View7, { style: styles8.flexShrink, children: [
425
+ /* @__PURE__ */ jsx9(Text7, { variant: "bodyLarge", style: { color: colors.onSurface }, children: "How to Play" }),
426
+ /* @__PURE__ */ jsx9(Text7, { variant: "bodySmall", numberOfLines: 1, style: { color: colors.onSurfaceVariant }, children: "Replay the quick intro" })
394
427
  ] })
395
428
  ] })
396
429
  }
397
430
  )
398
431
  ] }),
399
- showAppearance && /* @__PURE__ */ jsxs8(View6, { style: styles7.section, children: [
400
- /* @__PURE__ */ jsx8(Text7, { variant: "labelMedium", style: [styles7.sectionLabel, { color: colors.onSurfaceVariant }], children: "APPEARANCE" }),
401
- /* @__PURE__ */ jsx8(AutoAppearancePicker, { showLabels: false })
432
+ showAppearance && /* @__PURE__ */ jsxs8(View7, { style: styles8.section, children: [
433
+ /* @__PURE__ */ jsx9(Text7, { variant: "labelMedium", style: [styles8.sectionLabel, { color: colors.onSurfaceVariant }], children: "APPEARANCE" }),
434
+ /* @__PURE__ */ jsx9(AutoAppearancePicker, { showLabels: false })
402
435
  ] }),
403
436
  children,
404
- showUpdateCheck && /* @__PURE__ */ jsxs8(View6, { style: styles7.section, children: [
405
- /* @__PURE__ */ jsxs8(Text7, { variant: "labelSmall", style: [styles7.sectionLabel, { color: colors.onSurfaceVariant }], children: [
437
+ showUpdateCheck && /* @__PURE__ */ jsxs8(View7, { style: styles8.section, children: [
438
+ /* @__PURE__ */ jsxs8(Text7, { variant: "labelSmall", style: [styles8.sectionLabel, { color: colors.onSurfaceVariant }], children: [
406
439
  "VERSION ",
407
440
  version,
408
441
  updateReady ? " \xB7 UPDATE READY" : ""
409
442
  ] }),
410
- /* @__PURE__ */ jsx8(Button2, { mode: "outlined", onPress: check, loading: checking, disabled: checking, children: "Check for Updates" })
443
+ /* @__PURE__ */ jsx9(Button2, { mode: "outlined", onPress: check, loading: checking, disabled: checking, children: "Check for Updates" })
411
444
  ] })
412
445
  ] }) })
413
446
  ] }),
414
- /* @__PURE__ */ jsx8(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) }),
415
- /* @__PURE__ */ jsx8(ConfirmDialog, { visible: !!infoMessage, title: infoMessage?.title ?? "", message: infoMessage?.message ?? "", confirmLabel: "OK", icon: "information-outline", rotation, onConfirm: () => setInfoMessage(null) })
416
- ] });
447
+ /* @__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) }),
448
+ /* @__PURE__ */ jsx9(ConfirmDialog, { visible: !!infoMessage, title: infoMessage?.title ?? "", message: infoMessage?.message ?? "", confirmLabel: "OK", icon: "information-outline", rotation: 0, onConfirm: () => setInfoMessage(null) })
449
+ ] }) });
417
450
  }
418
- var styles7 = StyleSheet7.create({
451
+ var styles8 = StyleSheet8.create({
419
452
  content: {
420
453
  gap: 24,
421
454
  paddingVertical: 20
@@ -485,29 +518,29 @@ var styles7 = StyleSheet7.create({
485
518
  // src/BaseStatsScreen.tsx
486
519
  import { useAutoPaperTheme as useAutoPaperTheme8 } from "@rific/auto-paper";
487
520
  import { Button as Button3, IconButton } from "@rific/feedback-press";
488
- import { useRotation as useRotation2 } from "@tastic/core";
521
+ import { useRotation as useRotation3 } from "@tastic/core";
489
522
  import { useState as useState3 } from "react";
490
- import { ScrollView as ScrollView2, StyleSheet as StyleSheet8, View as View7 } from "react-native";
523
+ import { ScrollView as ScrollView2, StyleSheet as StyleSheet9, View as View8 } from "react-native";
491
524
  import { Text as Text8 } from "react-native-paper";
492
- import { jsx as jsx9, jsxs as jsxs9 } from "react/jsx-runtime";
525
+ import { jsx as jsx10, jsxs as jsxs9 } from "react/jsx-runtime";
493
526
  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 }) {
494
527
  const { dark, colors } = useAutoPaperTheme8();
495
- const ambientRotation = useRotation2();
528
+ const ambientRotation = useRotation3();
496
529
  const rotation = rotationOverride ?? ambientRotation;
497
530
  const [confirmResetVisible, setConfirmResetVisible] = useState3(false);
498
531
  const showReset = !!onReset;
499
532
  const fg = fgOverride ?? (dark ? "#FFFFFF" : "#000000");
500
533
  const bg = bgOverride ?? (dark ? "#000000" : "#FFFFFF");
501
- return /* @__PURE__ */ jsxs9(View7, { style: [styles8.container, { backgroundColor: bg }], children: [
502
- /* @__PURE__ */ jsxs9(View7, { style: [styles8.header, { paddingTop: 8 + insets.top, paddingLeft: 8 + insets.left }], children: [
503
- /* @__PURE__ */ jsx9(IconButton, { icon: "arrow-left", iconColor: fg, size: 24, onPress: onBack }),
504
- /* @__PURE__ */ jsx9(Text8, { variant: titleVariant, style: [styles8.title, { color: fg }], children: title })
534
+ return /* @__PURE__ */ jsxs9(View8, { style: [styles9.container, { backgroundColor: bg }], children: [
535
+ /* @__PURE__ */ jsxs9(View8, { style: [styles9.header, { paddingTop: 8 + insets.top, paddingLeft: 8 + insets.left }], children: [
536
+ /* @__PURE__ */ jsx10(IconButton, { icon: "arrow-left", iconColor: fg, size: 24, onPress: onBack }),
537
+ /* @__PURE__ */ jsx10(Text8, { variant: titleVariant, style: [styles9.title, { color: fg }], children: title })
505
538
  ] }),
506
- /* @__PURE__ */ jsxs9(ScrollView2, { style: styles8.scrollView, contentContainerStyle: [styles8.content, { paddingBottom: 32 + insets.bottom }], showsVerticalScrollIndicator: false, children: [
539
+ /* @__PURE__ */ jsxs9(ScrollView2, { style: styles9.scrollView, contentContainerStyle: [styles9.content, { paddingBottom: 32 + insets.bottom }], showsVerticalScrollIndicator: false, children: [
507
540
  children,
508
- showReset && /* @__PURE__ */ jsx9(Button3, { mode: "contained", onPress: () => setConfirmResetVisible(true), buttonColor: colors.danger, textColor: colors.onDanger, style: styles8.resetButton, children: resetLabel })
541
+ showReset && /* @__PURE__ */ jsx10(Button3, { mode: "contained", onPress: () => setConfirmResetVisible(true), buttonColor: colors.danger, textColor: colors.onDanger, style: styles9.resetButton, children: resetLabel })
509
542
  ] }),
510
- /* @__PURE__ */ jsx9(
543
+ /* @__PURE__ */ jsx10(
511
544
  ConfirmDialog,
512
545
  {
513
546
  visible: confirmResetVisible,
@@ -527,7 +560,7 @@ function BaseStatsScreen({ rotation: rotationOverride, title = "Achievements", t
527
560
  )
528
561
  ] });
529
562
  }
530
- var styles8 = StyleSheet8.create({
563
+ var styles9 = StyleSheet9.create({
531
564
  container: {
532
565
  flex: 1
533
566
  },
@@ -559,18 +592,18 @@ var styles8 = StyleSheet8.create({
559
592
 
560
593
  // src/ContentGutter.tsx
561
594
  import { computeContentBounds, useRotatedWindowDimensions } from "@tastic/core";
562
- import { StyleSheet as StyleSheet9, View as View8 } from "react-native";
563
- import { jsx as jsx10, jsxs as jsxs10 } from "react/jsx-runtime";
595
+ import { StyleSheet as StyleSheet10, View as View9 } from "react-native";
596
+ import { jsx as jsx11, jsxs as jsxs10 } from "react/jsx-runtime";
564
597
  function ContentGutter({ maxContentWidth, leftGutter, rightGutter, style, children }) {
565
598
  const { width: windowWidth } = useRotatedWindowDimensions();
566
599
  const { contentWidth, gutterWidth } = computeContentBounds(windowWidth, maxContentWidth ?? Infinity);
567
- return /* @__PURE__ */ jsxs10(View8, { style: [styles9.row, style], children: [
568
- /* @__PURE__ */ jsx10(View8, { style: [styles9.gutter, { width: gutterWidth }], children: leftGutter }),
569
- /* @__PURE__ */ jsx10(View8, { style: { width: contentWidth }, children }),
570
- /* @__PURE__ */ jsx10(View8, { style: [styles9.gutter, { width: gutterWidth }], children: rightGutter })
600
+ return /* @__PURE__ */ jsxs10(View9, { style: [styles10.row, style], children: [
601
+ /* @__PURE__ */ jsx11(View9, { style: [styles10.gutter, { width: gutterWidth }], children: leftGutter }),
602
+ /* @__PURE__ */ jsx11(View9, { style: { width: contentWidth }, children }),
603
+ /* @__PURE__ */ jsx11(View9, { style: [styles10.gutter, { width: gutterWidth }], children: rightGutter })
571
604
  ] });
572
605
  }
573
- var styles9 = StyleSheet9.create({
606
+ var styles10 = StyleSheet10.create({
574
607
  // overflow:'hidden' keeps an oversized leftGutter/rightGutter from bleeding into the content
575
608
  // column instead of clipping cleanly at its own real width.
576
609
  gutter: {
@@ -588,35 +621,35 @@ import { Platform as Platform3 } from "react-native";
588
621
  // src/SectionedDropdown.tsx
589
622
  import { getBlendedColor, getColorRoles } from "@rific/auto-paper";
590
623
  import { IconButton as IconButton2, TouchableRipple as TouchableRipple2 } from "@rific/feedback-press";
591
- import { useRotation as useRotation3 } from "@tastic/core";
592
- import { ScrollView as ScrollView3, StyleSheet as StyleSheet11, View as View11 } from "react-native";
624
+ import { useRotation as useRotation4 } from "@tastic/core";
625
+ import { ScrollView as ScrollView3, StyleSheet as StyleSheet12, View as View12 } from "react-native";
593
626
  import { Icon as Icon5, Text as Text9 } from "react-native-paper";
594
627
 
595
628
  // src/PopoverBody.tsx
596
- import { StyleSheet as StyleSheet10, View as View9 } from "react-native";
597
- import { Fragment as Fragment3, jsx as jsx11, jsxs as jsxs11 } from "react/jsx-runtime";
629
+ import { StyleSheet as StyleSheet11, View as View10 } from "react-native";
630
+ import { Fragment as Fragment2, jsx as jsx12, jsxs as jsxs11 } from "react/jsx-runtime";
598
631
  var CARET_SIZE = 7;
599
632
  var CARET_RING_OFFSET = 2;
600
633
  var CARET_DIP = 1;
601
634
  function PopoverBody({ visible, children, align = "center", verticalAlign = "below", caretColor, caretBorderColor, caretBorderWidth = 1, triggerSize = 0 }) {
602
635
  if (!visible) return null;
603
636
  const above = verticalAlign === "above";
604
- const alignStyle = align === "left" ? styles10.contentLeft : align === "right" ? styles10.contentRight : styles10.contentCenter;
605
- const verticalStyle = above ? styles10.contentAbove : styles10.contentBelow;
637
+ const alignStyle = align === "left" ? styles11.contentLeft : align === "right" ? styles11.contentRight : styles11.contentCenter;
638
+ const verticalStyle = above ? styles11.contentAbove : styles11.contentBelow;
606
639
  const ringSize = CARET_SIZE + caretBorderWidth;
607
640
  const caretOffset = (halfFootprint) => align === "right" ? { right: triggerSize / 2 - halfFootprint } : { left: triggerSize / 2 - halfFootprint };
608
641
  const caretFill = above ? "borderTopColor" : "borderBottomColor";
609
642
  const caretWidthProp = above ? "borderTopWidth" : "borderBottomWidth";
610
643
  const caretEdge = (size) => above ? { bottom: -size + CARET_DIP } : { top: -size + CARET_DIP };
611
- return /* @__PURE__ */ jsxs11(View9, { style: [styles10.content, alignStyle, verticalStyle], children: [
644
+ return /* @__PURE__ */ jsxs11(View10, { style: [styles11.content, alignStyle, verticalStyle], children: [
612
645
  children,
613
- caretColor && /* @__PURE__ */ jsxs11(Fragment3, { children: [
614
- /* @__PURE__ */ jsx11(View9, { style: [styles10.caret, caretOffset(ringSize), caretEdge(ringSize), { [caretFill]: caretBorderColor ?? caretColor, [caretWidthProp]: ringSize, borderLeftWidth: ringSize, borderRightWidth: ringSize }] }),
615
- /* @__PURE__ */ jsx11(View9, { style: [styles10.caret, caretOffset(CARET_SIZE), caretEdge(CARET_SIZE - CARET_RING_OFFSET), { [caretFill]: caretColor, [caretWidthProp]: CARET_SIZE, borderLeftWidth: CARET_SIZE, borderRightWidth: CARET_SIZE }] })
646
+ caretColor && /* @__PURE__ */ jsxs11(Fragment2, { children: [
647
+ /* @__PURE__ */ jsx12(View10, { style: [styles11.caret, caretOffset(ringSize), caretEdge(ringSize), { [caretFill]: caretBorderColor ?? caretColor, [caretWidthProp]: ringSize, borderLeftWidth: ringSize, borderRightWidth: ringSize }] }),
648
+ /* @__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 }] })
616
649
  ] })
617
650
  ] });
618
651
  }
619
- var styles10 = StyleSheet10.create({
652
+ var styles11 = StyleSheet11.create({
620
653
  caret: {
621
654
  borderLeftColor: "transparent",
622
655
  borderRightColor: "transparent",
@@ -659,15 +692,15 @@ var styles10 = StyleSheet10.create({
659
692
  });
660
693
 
661
694
  // src/TriggerGaugeHost.tsx
662
- import { jsx as jsx12 } from "react/jsx-runtime";
695
+ import { jsx as jsx13 } from "react/jsx-runtime";
663
696
  var getTriggerGauge = () => import("./TriggerGauge-2OJOOF6I.mjs").then((mod) => ({ default: mod.TriggerGauge }));
664
697
  function TriggerGaugeHost(props) {
665
- return /* @__PURE__ */ jsx12(SkiaGate, { getComponent: getTriggerGauge, componentProps: props });
698
+ return /* @__PURE__ */ jsx13(SkiaGate, { getComponent: getTriggerGauge, componentProps: props });
666
699
  }
667
700
 
668
701
  // src/useAutoAlign.ts
669
702
  import { useCallback as useCallback2, useEffect, useRef as useRef2, useState as useState4 } from "react";
670
- import { useWindowDimensions } from "react-native";
703
+ import { useWindowDimensions as useWindowDimensions2 } from "react-native";
671
704
  var EDGE_MARGIN = 12;
672
705
  function rotateRect(x, y, width, height, rotation, windowWidth, windowHeight) {
673
706
  if (rotation === 0) return { x, y, width, height };
@@ -680,7 +713,7 @@ function rotateRect(x, y, width, height, rotation, windowWidth, windowHeight) {
680
713
  }
681
714
  function useAutoAlign(open, contentWidth, contentHeight, rotation = 0) {
682
715
  const triggerRef = useRef2(null);
683
- const { width: windowWidth, height: windowHeight } = useWindowDimensions();
716
+ const { width: windowWidth, height: windowHeight } = useWindowDimensions2();
684
717
  const [align, setAlign] = useState4("center");
685
718
  const [verticalAlign, setVerticalAlign] = useState4("below");
686
719
  const [maxHeight, setMaxHeight] = useState4(contentHeight);
@@ -714,7 +747,7 @@ function useAutoAlign(open, contentWidth, contentHeight, rotation = 0) {
714
747
  }
715
748
 
716
749
  // src/SectionedDropdown.tsx
717
- import { Fragment as Fragment4, jsx as jsx13, jsxs as jsxs12 } from "react/jsx-runtime";
750
+ import { Fragment as Fragment3, jsx as jsx14, jsxs as jsxs12 } from "react/jsx-runtime";
718
751
  var MENU_BORDER_WIDTH = 1;
719
752
  var TRIGGER_SIZE = 44;
720
753
  var MENU_MIN_WIDTH = 200;
@@ -726,7 +759,7 @@ var MENU_ITEM_HEIGHT_WITH_DESCRIPTION = 58;
726
759
  var MENU_DIVIDER_HEIGHT = 9;
727
760
  var MENU_VERTICAL_PADDING = 12;
728
761
  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" } }) {
729
- const ambientRotation = useRotation3();
762
+ const ambientRotation = useRotation4();
730
763
  const rotation = rotationOverride ?? ambientRotation;
731
764
  const menuBg = dark ? "#000000" : "#FFFFFF";
732
765
  const menuBorderColor = getBlendedColor(mutedColor, menuBg, 0.5);
@@ -764,17 +797,17 @@ function SectionedDropdown({ id, host, icon, accessibilityLabel, sections, accen
764
797
  }
765
798
  gaugeOffset += section.options.length;
766
799
  }
767
- const anchorStyle = [styles11.anchor, open && styles11.anchorOpen];
800
+ const anchorStyle = [styles12.anchor, open && styles12.anchorOpen];
768
801
  const menuStyle = { backgroundColor: menuBg, borderColor: menuBorderColor, maxHeight };
769
802
  const dividerStyle = { backgroundColor: menuBorderColor };
770
- return /* @__PURE__ */ jsxs12(View11, { style: anchorStyle, children: [
771
- /* @__PURE__ */ jsxs12(View11, { ref: triggerRef, collapsable: false, style: styles11.triggerBox, children: [
772
- /* @__PURE__ */ jsx13(TriggerGaugeHost, { segments: gaugeSegments, litIndices: gaugeLitIndices, size: TRIGGER_SIZE, accentColor, mutedColor }),
773
- /* @__PURE__ */ jsx13(IconButton2, { icon: triggerIcon, iconColor: triggerIconColor, size: triggerIconSize, accessibilityLabel, onPress: () => host.toggle(id) })
803
+ return /* @__PURE__ */ jsxs12(View12, { style: anchorStyle, children: [
804
+ /* @__PURE__ */ jsxs12(View12, { ref: triggerRef, collapsable: false, style: styles12.triggerBox, children: [
805
+ /* @__PURE__ */ jsx14(TriggerGaugeHost, { segments: gaugeSegments, litIndices: gaugeLitIndices, size: TRIGGER_SIZE, accentColor, mutedColor }),
806
+ /* @__PURE__ */ jsx14(IconButton2, { icon: triggerIcon, iconColor: triggerIconColor, size: triggerIconSize, accessibilityLabel, onPress: () => host.toggle(id) })
774
807
  ] }),
775
- /* @__PURE__ */ jsx13(PopoverBody, { visible: open && measured, align, verticalAlign, caretColor: menuBg, caretBorderColor: menuBorderColor, caretBorderWidth: MENU_BORDER_WIDTH, triggerSize: TRIGGER_SIZE, children: /* @__PURE__ */ jsx13(ScrollView3, { style: [styles11.menu, menuStyle], contentContainerStyle: styles11.menuContent, showsVerticalScrollIndicator: false, children: sections.map((section, sectionIndex) => /* @__PURE__ */ jsxs12(View11, { children: [
776
- sectionIndex > 0 && /* @__PURE__ */ jsx13(View11, { style: [styles11.divider, dividerStyle] }),
777
- section.kind === "single" ? /* @__PURE__ */ jsx13(
808
+ /* @__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: [
809
+ sectionIndex > 0 && /* @__PURE__ */ jsx14(View12, { style: [styles12.divider, dividerStyle] }),
810
+ section.kind === "single" ? /* @__PURE__ */ jsx14(
778
811
  SingleSection,
779
812
  {
780
813
  section,
@@ -787,7 +820,7 @@ function SectionedDropdown({ id, host, icon, accessibilityLabel, sections, accen
787
820
  if (autoDismiss) host.close();
788
821
  }
789
822
  }
790
- ) : /* @__PURE__ */ jsx13(MultiSection, { section, accentColor, onAccentColor: resolvedOnAccentColor, mutedColor, labelFontFamily, allClearLabels })
823
+ ) : /* @__PURE__ */ jsx14(MultiSection, { section, accentColor, onAccentColor: resolvedOnAccentColor, mutedColor, labelFontFamily, allClearLabels })
791
824
  ] }, section.id)) }) })
792
825
  ] });
793
826
  }
@@ -799,18 +832,18 @@ function SingleSection({
799
832
  labelFontFamily,
800
833
  onSelect
801
834
  }) {
802
- return /* @__PURE__ */ jsx13(Fragment4, { children: section.options.map((option) => {
835
+ return /* @__PURE__ */ jsx14(Fragment3, { children: section.options.map((option) => {
803
836
  const selected = option.value === section.value;
804
837
  const taken = !selected && option.value === section.takenValue;
805
838
  const rowColor = selected ? onAccentColor : mutedColor;
806
- const itemStyle = [styles11.item, selected && { backgroundColor: accentColor }, taken && styles11.itemTaken];
839
+ const itemStyle = [styles12.item, selected && { backgroundColor: accentColor }, taken && styles12.itemTaken];
807
840
  const labelStyle = { fontFamily: labelFontFamily, color: rowColor, fontWeight: selected ? "bold" : "normal" };
808
841
  const descriptionStyle = { fontFamily: labelFontFamily, color: rowColor };
809
- return /* @__PURE__ */ jsx13(TouchableRipple2, { disabled: taken, onPress: () => onSelect(option.value), style: itemStyle, children: /* @__PURE__ */ jsxs12(View11, { style: styles11.itemRow, children: [
810
- option.icon && /* @__PURE__ */ jsx13(Icon5, { source: option.icon, size: MENU_ITEM_ICON_SIZE, color: rowColor }),
811
- /* @__PURE__ */ jsxs12(View11, { style: styles11.itemLabelColumn, children: [
812
- /* @__PURE__ */ jsx13(Text9, { variant: "labelLarge", style: labelStyle, children: option.label }),
813
- option.description && /* @__PURE__ */ jsx13(Text9, { variant: "labelSmall", style: descriptionStyle, children: option.description })
842
+ return /* @__PURE__ */ jsx14(TouchableRipple2, { disabled: taken, onPress: () => onSelect(option.value), style: itemStyle, children: /* @__PURE__ */ jsxs12(View12, { style: styles12.itemRow, children: [
843
+ option.icon && /* @__PURE__ */ jsx14(Icon5, { source: option.icon, size: MENU_ITEM_ICON_SIZE, color: rowColor }),
844
+ /* @__PURE__ */ jsxs12(View12, { style: styles12.itemLabelColumn, children: [
845
+ /* @__PURE__ */ jsx14(Text9, { variant: "labelLarge", style: labelStyle, children: option.label }),
846
+ option.description && /* @__PURE__ */ jsx14(Text9, { variant: "labelSmall", style: descriptionStyle, children: option.description })
814
847
  ] })
815
848
  ] }) }, option.value);
816
849
  }) });
@@ -824,23 +857,23 @@ function MultiSection({
824
857
  allClearLabels
825
858
  }) {
826
859
  const allSelected = section.value.length === section.options.length;
827
- return /* @__PURE__ */ jsxs12(Fragment4, { children: [
860
+ return /* @__PURE__ */ jsxs12(Fragment3, { children: [
828
861
  section.options.map((option, i) => {
829
862
  const selected = section.value.includes(option.value);
830
863
  const rowColor = selected ? onAccentColor : mutedColor;
831
864
  const prevSelected = selected && i > 0 && section.value.includes(section.options[i - 1].value);
832
865
  const nextSelected = selected && i < section.options.length - 1 && section.value.includes(section.options[i + 1].value);
833
- const itemStyle = [styles11.item, selected && { backgroundColor: accentColor }, prevSelected && { borderTopLeftRadius: 0, borderTopRightRadius: 0 }, nextSelected && { borderBottomLeftRadius: 0, borderBottomRightRadius: 0 }];
866
+ const itemStyle = [styles12.item, selected && { backgroundColor: accentColor }, prevSelected && { borderTopLeftRadius: 0, borderTopRightRadius: 0 }, nextSelected && { borderBottomLeftRadius: 0, borderBottomRightRadius: 0 }];
834
867
  const labelStyle = { fontFamily: labelFontFamily, color: rowColor, fontWeight: selected ? "bold" : "normal" };
835
- return /* @__PURE__ */ jsx13(TouchableRipple2, { onPress: () => section.onChange(selected ? section.value.filter((v) => v !== option.value) : [...section.value, option.value]), style: itemStyle, children: /* @__PURE__ */ jsxs12(View11, { style: styles11.itemRow, children: [
836
- option.icon && /* @__PURE__ */ jsx13(Icon5, { source: option.icon, size: MENU_ITEM_ICON_SIZE, color: rowColor }),
837
- /* @__PURE__ */ jsx13(Text9, { variant: "labelLarge", style: [styles11.itemLabelFlex, labelStyle], children: option.label })
868
+ 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: [
869
+ option.icon && /* @__PURE__ */ jsx14(Icon5, { source: option.icon, size: MENU_ITEM_ICON_SIZE, color: rowColor }),
870
+ /* @__PURE__ */ jsx14(Text9, { variant: "labelLarge", style: [styles12.itemLabelFlex, labelStyle], children: option.label })
838
871
  ] }) }, option.value);
839
872
  }),
840
- section.allClear && /* @__PURE__ */ jsx13(TouchableRipple2, { onPress: () => section.onChange(allSelected ? [] : section.options.map((o) => o.value)), style: styles11.item, children: /* @__PURE__ */ jsx13(Text9, { variant: "labelLarge", style: [styles11.allClearLabel, { fontFamily: labelFontFamily, color: accentColor }], children: allSelected ? allClearLabels.clear : allClearLabels.all }) })
873
+ 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 }) })
841
874
  ] });
842
875
  }
843
- var styles11 = StyleSheet11.create({
876
+ var styles12 = StyleSheet12.create({
844
877
  allClearLabel: {
845
878
  fontWeight: "bold",
846
879
  textAlign: "center"
@@ -857,7 +890,7 @@ var styles11 = StyleSheet11.create({
857
890
  zIndex: 100
858
891
  },
859
892
  divider: {
860
- height: StyleSheet11.hairlineWidth,
893
+ height: StyleSheet12.hairlineWidth,
861
894
  marginVertical: 4
862
895
  },
863
896
  item: {
@@ -910,24 +943,24 @@ var styles11 = StyleSheet11.create({
910
943
  });
911
944
 
912
945
  // src/ControlSchemePicker.tsx
913
- import { jsx as jsx14 } from "react/jsx-runtime";
946
+ import { jsx as jsx15 } from "react/jsx-runtime";
914
947
  function ControlSchemePicker({ id, host, value, onChange, options, takenValue, accentColor, mutedColor, onAccentColor, dark, align, alignOverride, rotation, labelFontFamily }) {
915
948
  const isTouchPrimary = useIsTouchPrimaryDevice2();
916
949
  if (Platform3.OS !== "web" || isTouchPrimary) return null;
917
- return /* @__PURE__ */ jsx14(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 });
950
+ 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 });
918
951
  }
919
952
 
920
953
  // src/CornerActionButtons.tsx
921
954
  import { IconButton as IconButton3 } from "@rific/feedback-press";
922
- import { StyleSheet as StyleSheet12 } from "react-native";
923
- import { Fragment as Fragment5, jsx as jsx15, jsxs as jsxs13 } from "react/jsx-runtime";
955
+ import { StyleSheet as StyleSheet13 } from "react-native";
956
+ import { Fragment as Fragment4, jsx as jsx16, jsxs as jsxs13 } from "react/jsx-runtime";
924
957
  function CornerActionButtons({ onBack, onSettings, fg, insets, backIcon = "arrow-left", backLabel = "Back" }) {
925
- return /* @__PURE__ */ jsxs13(Fragment5, { children: [
926
- /* @__PURE__ */ jsx15(IconButton3, { icon: backIcon, iconColor: fg, size: 24, style: [styles12.back, { top: 8 + insets.top, left: 8 + insets.left }], onPress: onBack, accessibilityLabel: backLabel }),
927
- /* @__PURE__ */ jsx15(IconButton3, { icon: "cog", iconColor: fg, size: 24, style: [styles12.topRight, { top: 8 + insets.top, right: 8 + insets.right }], onPress: onSettings, accessibilityLabel: "Settings" })
958
+ return /* @__PURE__ */ jsxs13(Fragment4, { children: [
959
+ /* @__PURE__ */ jsx16(IconButton3, { icon: backIcon, iconColor: fg, size: 24, style: [styles13.back, { top: 8 + insets.top, left: 8 + insets.left }], onPress: onBack, accessibilityLabel: backLabel }),
960
+ /* @__PURE__ */ jsx16(IconButton3, { icon: "cog", iconColor: fg, size: 24, style: [styles13.topRight, { top: 8 + insets.top, right: 8 + insets.right }], onPress: onSettings, accessibilityLabel: "Settings" })
928
961
  ] });
929
962
  }
930
- var styles12 = StyleSheet12.create({
963
+ var styles13 = StyleSheet13.create({
931
964
  back: {
932
965
  position: "absolute"
933
966
  },
@@ -937,22 +970,22 @@ var styles12 = StyleSheet12.create({
937
970
  });
938
971
 
939
972
  // src/CornerStatusBadges.tsx
940
- import { StyleSheet as StyleSheet13, View as View12 } from "react-native";
973
+ import { StyleSheet as StyleSheet14, View as View13 } from "react-native";
941
974
  import { Icon as Icon6 } from "react-native-paper";
942
- import { Fragment as Fragment6, jsx as jsx16, jsxs as jsxs14 } from "react/jsx-runtime";
975
+ import { Fragment as Fragment5, jsx as jsx17, jsxs as jsxs14 } from "react/jsx-runtime";
943
976
  var BADGE_SIZE = 30;
944
977
  function StatusBadge({ icon }) {
945
- return /* @__PURE__ */ jsx16(View12, { style: styles13.badge, children: icon && /* @__PURE__ */ jsx16(Icon6, { source: icon, size: 16, color: "rgba(255,255,255,0.85)" }) });
978
+ return /* @__PURE__ */ jsx17(View13, { style: styles14.badge, children: icon && /* @__PURE__ */ jsx17(Icon6, { source: icon, size: 16, color: "rgba(255,255,255,0.85)" }) });
946
979
  }
947
980
  function CornerStatusBadges({ orientationMode, p1OnRight, p1, p2 }) {
948
981
  const p1OnRightSide = orientationMode === "sideBySide" && p1OnRight;
949
982
  const p2OnLeftSide = orientationMode === "sideBySide" && !p1OnRight;
950
- return /* @__PURE__ */ jsxs14(Fragment6, { children: [
951
- p1 && /* @__PURE__ */ jsx16(View12, { pointerEvents: "none", style: p1OnRightSide ? styles13.bottomRight : styles13.bottomLeft, children: /* @__PURE__ */ jsx16(StatusBadge, { icon: p1.icon }) }),
952
- p2 && /* @__PURE__ */ jsx16(View12, { pointerEvents: "none", style: p2OnLeftSide ? styles13.topLeft : styles13.topRight, children: /* @__PURE__ */ jsx16(StatusBadge, { icon: p2.icon }) })
983
+ return /* @__PURE__ */ jsxs14(Fragment5, { children: [
984
+ p1 && /* @__PURE__ */ jsx17(View13, { pointerEvents: "none", style: p1OnRightSide ? styles14.bottomRight : styles14.bottomLeft, children: /* @__PURE__ */ jsx17(StatusBadge, { icon: p1.icon }) }),
985
+ p2 && /* @__PURE__ */ jsx17(View13, { pointerEvents: "none", style: p2OnLeftSide ? styles14.topLeft : styles14.topRight, children: /* @__PURE__ */ jsx17(StatusBadge, { icon: p2.icon }) })
953
986
  ] });
954
987
  }
955
- var styles13 = StyleSheet13.create({
988
+ var styles14 = StyleSheet14.create({
956
989
  badge: {
957
990
  alignItems: "center",
958
991
  backgroundColor: "rgba(0,0,0,0.28)",
@@ -973,10 +1006,10 @@ var styles13 = StyleSheet13.create({
973
1006
  // src/InlineColorPicker.tsx
974
1007
  import { defaultColors, getContrastColor as getContrastColor2 } from "@rific/auto-paper";
975
1008
  import { TouchableRipple as TouchableRipple3 } from "@rific/feedback-press";
976
- import { clamp, useRotation as useRotation4 } from "@tastic/core";
977
- import { ScrollView as ScrollView4, StyleSheet as StyleSheet14, useWindowDimensions as useWindowDimensions2, View as View13 } from "react-native";
1009
+ import { clamp, useRotation as useRotation5 } from "@tastic/core";
1010
+ import { ScrollView as ScrollView4, StyleSheet as StyleSheet15, useWindowDimensions as useWindowDimensions3, View as View14 } from "react-native";
978
1011
  import { Icon as Icon7, Text as Text10 } from "react-native-paper";
979
- import { jsx as jsx17, jsxs as jsxs15 } from "react/jsx-runtime";
1012
+ import { jsx as jsx18, jsxs as jsxs15 } from "react/jsx-runtime";
980
1013
  var EMOJI_PATTERN = /\p{Extended_Pictographic}/u;
981
1014
  var DEFAULT_SIZE = 48;
982
1015
  var SWATCH_SIZE = 28;
@@ -998,10 +1031,10 @@ function getInlineColorPickerContentSize(swatchCount, windowWidth, columns) {
998
1031
  return { width, height };
999
1032
  }
1000
1033
  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 }) {
1001
- const ambientRotation = useRotation4();
1034
+ const ambientRotation = useRotation5();
1002
1035
  const rotation = rotationOverride ?? ambientRotation;
1003
1036
  const menuBg = dark ? "#000000" : "#FFFFFF";
1004
- const { width: windowWidth } = useWindowDimensions2();
1037
+ const { width: windowWidth } = useWindowDimensions3();
1005
1038
  const { width: swatchesWidth, height: swatchesHeight } = getInlineColorPickerContentSize(swatches.length, windowWidth, columns);
1006
1039
  const open = host.openId === id;
1007
1040
  const auto = useAutoAlign(open, swatchesWidth, swatchesHeight, rotation);
@@ -1012,14 +1045,14 @@ function InlineColorPicker({ id, host, value, onChange, previewValue, swatches =
1012
1045
  const displayValue = displayFor(value);
1013
1046
  const contrastColor = getContrastColor2(displayValue);
1014
1047
  const tagFontSize = size * (tag && EMOJI_PATTERN.test(tag) ? 0.6 : 0.4);
1015
- return /* @__PURE__ */ jsxs15(View13, { style: [styles14.anchor, open && styles14.anchorOpen], children: [
1016
- /* @__PURE__ */ jsx17(TouchableRipple3, { onPress: () => host.toggle(id), borderless: true, style: [styles14.trigger, { backgroundColor: displayValue, borderRadius: size / 2, height: size, width: size }], children: /* @__PURE__ */ jsx17(View13, { ref: triggerRef, collapsable: false, style: styles14.triggerMeasure, children: tag ? /* @__PURE__ */ jsx17(Text10, { style: [styles14.tagLabel, { color: contrastColor, fontFamily: labelFontFamily, fontSize: tagFontSize }], numberOfLines: 1, adjustsFontSizeToFit: true, children: tag }) : /* @__PURE__ */ jsx17(Icon7, { source: icon, size: size * 0.6, color: contrastColor }) }) }),
1017
- /* @__PURE__ */ jsx17(PopoverBody, { visible: open && measured, align, verticalAlign, caretColor: menuBg, caretBorderColor: displayValue, caretBorderWidth: SWATCHES_BORDER_WIDTH, triggerSize: size, children: /* @__PURE__ */ jsx17(ScrollView4, { style: [styles14.swatches, { backgroundColor: menuBg, borderColor: displayValue, width: swatchesWidth, maxHeight }], contentContainerStyle: styles14.swatchesContent, showsVerticalScrollIndicator: false, children: swatches.map((swatch) => {
1048
+ return /* @__PURE__ */ jsxs15(View14, { style: [styles15.anchor, open && styles15.anchorOpen], children: [
1049
+ /* @__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 }) }) }),
1050
+ /* @__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) => {
1018
1051
  const selected = swatch.value.toLowerCase() === value.toLowerCase();
1019
1052
  const taken = !selected && !!takenValue && swatch.value.toLowerCase() === takenValue.toLowerCase();
1020
1053
  const swappable = taken && allowSwapTaken;
1021
1054
  const swatchDisplay = displayFor(swatch.value);
1022
- return /* @__PURE__ */ jsx17(
1055
+ return /* @__PURE__ */ jsx18(
1023
1056
  TouchableRipple3,
1024
1057
  {
1025
1058
  disabled: taken && !swappable,
@@ -1028,15 +1061,15 @@ function InlineColorPicker({ id, host, value, onChange, previewValue, swatches =
1028
1061
  if (autoDismiss) host.close();
1029
1062
  },
1030
1063
  borderless: true,
1031
- style: [styles14.swatch, { backgroundColor: swatchDisplay }, selected && styles14.swatchSelected, taken && !swappable && styles14.swatchTaken],
1032
- children: selected ? /* @__PURE__ */ jsx17(Icon7, { source: "check", size: 16, color: getContrastColor2(swatchDisplay) }) : swappable ? /* @__PURE__ */ jsx17(Icon7, { source: "swap-horizontal", size: 16, color: getContrastColor2(swatchDisplay) }) : taken ? /* @__PURE__ */ jsx17(Icon7, { source: "close", size: 16, color: getContrastColor2(swatchDisplay) }) : /* @__PURE__ */ jsx17(View13, {})
1064
+ style: [styles15.swatch, { backgroundColor: swatchDisplay }, selected && styles15.swatchSelected, taken && !swappable && styles15.swatchTaken],
1065
+ 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, {})
1033
1066
  },
1034
1067
  swatch.value
1035
1068
  );
1036
1069
  }) }) })
1037
1070
  ] });
1038
1071
  }
1039
- var styles14 = StyleSheet14.create({
1072
+ var styles15 = StyleSheet15.create({
1040
1073
  anchor: {
1041
1074
  position: "relative"
1042
1075
  },
@@ -1110,9 +1143,9 @@ var styles14 = StyleSheet14.create({
1110
1143
  // src/LabeledDropdown.tsx
1111
1144
  import { getContrastColor as getContrastColor3 } from "@rific/auto-paper";
1112
1145
  import { TouchableRipple as TouchableRipple4 } from "@rific/feedback-press";
1113
- import { ScrollView as ScrollView5, StyleSheet as StyleSheet15, View as View14 } from "react-native";
1146
+ import { ScrollView as ScrollView5, StyleSheet as StyleSheet16, View as View15 } from "react-native";
1114
1147
  import { Icon as Icon8, Text as Text11 } from "react-native-paper";
1115
- import { jsx as jsx18, jsxs as jsxs16 } from "react/jsx-runtime";
1148
+ import { jsx as jsx19, jsxs as jsxs16 } from "react/jsx-runtime";
1116
1149
  var TRIGGER_HEIGHT = 28;
1117
1150
  var POPOVER_WIDTH = 180;
1118
1151
  var ROW_HEIGHT = 36;
@@ -1135,22 +1168,22 @@ function LabeledDropdown({ id, host, options, value, onChange, color, dark, alig
1135
1168
  onChange(option.value);
1136
1169
  host.close();
1137
1170
  };
1138
- return /* @__PURE__ */ jsxs16(View14, { style: [styles15.anchor, open && styles15.anchorOpen], children: [
1139
- /* @__PURE__ */ jsx18(TouchableRipple4, { onPress: () => host.toggle(id), style: styles15.trigger, children: /* @__PURE__ */ jsxs16(View14, { ref: triggerRef, collapsable: false, style: styles15.triggerInner, children: [
1140
- /* @__PURE__ */ jsx18(Text11, { style: [styles15.triggerLabel, { color }], numberOfLines: 1, children: (selected?.label ?? "").toUpperCase() }),
1141
- /* @__PURE__ */ jsx18(Icon8, { source: "menu-down", size: 16, color })
1171
+ return /* @__PURE__ */ jsxs16(View15, { style: [styles16.anchor, open && styles16.anchorOpen], children: [
1172
+ /* @__PURE__ */ jsx19(TouchableRipple4, { onPress: () => host.toggle(id), style: styles16.trigger, children: /* @__PURE__ */ jsxs16(View15, { ref: triggerRef, collapsable: false, style: styles16.triggerInner, children: [
1173
+ /* @__PURE__ */ jsx19(Text11, { style: [styles16.triggerLabel, { color }], numberOfLines: 1, children: (selected?.label ?? "").toUpperCase() }),
1174
+ /* @__PURE__ */ jsx19(Icon8, { source: "menu-down", size: 16, color })
1142
1175
  ] }) }),
1143
- /* @__PURE__ */ jsx18(PopoverBody, { visible: open && measured, align, verticalAlign, caretColor: menuBg, caretBorderColor: color, caretBorderWidth: 2, triggerSize: TRIGGER_HEIGHT, children: /* @__PURE__ */ jsx18(ScrollView5, { style: [styles15.menu, { backgroundColor: menuBg, borderColor: color, width: POPOVER_WIDTH, maxHeight }], contentContainerStyle: styles15.menuContent, showsVerticalScrollIndicator: false, children: options.map((option) => {
1176
+ /* @__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) => {
1144
1177
  const isSelected = option.value === value;
1145
1178
  const onColor = getContrastColor3(color);
1146
- return /* @__PURE__ */ jsx18(TouchableRipple4, { onPress: () => handleSelect(option), style: [styles15.row, isSelected && { backgroundColor: color }], children: /* @__PURE__ */ jsxs16(View14, { style: styles15.rowInner, children: [
1147
- option.icon && /* @__PURE__ */ jsx18(Icon8, { source: option.icon, size: 18, color: isSelected ? onColor : fg }),
1148
- /* @__PURE__ */ jsx18(Text11, { style: [styles15.rowLabel, { color: isSelected ? onColor : fg }], numberOfLines: 1, children: option.label })
1179
+ return /* @__PURE__ */ jsx19(TouchableRipple4, { onPress: () => handleSelect(option), style: [styles16.row, isSelected && { backgroundColor: color }], children: /* @__PURE__ */ jsxs16(View15, { style: styles16.rowInner, children: [
1180
+ option.icon && /* @__PURE__ */ jsx19(Icon8, { source: option.icon, size: 18, color: isSelected ? onColor : fg }),
1181
+ /* @__PURE__ */ jsx19(Text11, { style: [styles16.rowLabel, { color: isSelected ? onColor : fg }], numberOfLines: 1, children: option.label })
1149
1182
  ] }) }, option.value);
1150
1183
  }) }) })
1151
1184
  ] });
1152
1185
  }
1153
- var styles15 = StyleSheet15.create({
1186
+ var styles16 = StyleSheet16.create({
1154
1187
  anchor: {
1155
1188
  position: "relative"
1156
1189
  },
@@ -1209,21 +1242,21 @@ function loadSkiaWeb() {
1209
1242
 
1210
1243
  // src/PlayerSetupPanel.tsx
1211
1244
  import { ProfilePicker } from "@tastic/profile";
1212
- import { StyleSheet as StyleSheet17, View as View15 } from "react-native";
1245
+ import { StyleSheet as StyleSheet18, View as View16 } from "react-native";
1213
1246
  import { Text as Text13 } from "react-native-paper";
1214
1247
 
1215
1248
  // src/ReadyButton.tsx
1216
1249
  import { TouchableRipple as TouchableRipple5 } from "@rific/feedback-press";
1217
- import { StyleSheet as StyleSheet16 } from "react-native";
1250
+ import { StyleSheet as StyleSheet17 } from "react-native";
1218
1251
  import { Text as Text12 } from "react-native-paper";
1219
- import { jsx as jsx19 } from "react/jsx-runtime";
1252
+ import { jsx as jsx20 } from "react/jsx-runtime";
1220
1253
  function ReadyButton({ color, ready, onToggleReady, style, labelFontFamily = MONO_FONT }) {
1221
- const readyButtonStyle = [styles16.readyButton, { borderColor: color }, ready && { backgroundColor: color }, style];
1254
+ const readyButtonStyle = [styles17.readyButton, { borderColor: color }, ready && { backgroundColor: color }, style];
1222
1255
  const labelTextStyle = { fontFamily: labelFontFamily, fontWeight: "bold" };
1223
1256
  const labelColorStyle = { color: ready ? "#000000" : color };
1224
- return /* @__PURE__ */ jsx19(TouchableRipple5, { onPress: onToggleReady, borderless: true, style: readyButtonStyle, children: /* @__PURE__ */ jsx19(Text12, { variant: "labelLarge", style: [labelTextStyle, labelColorStyle], children: ready ? "READY \u2713" : "READY?" }) });
1257
+ return /* @__PURE__ */ jsx20(TouchableRipple5, { onPress: onToggleReady, borderless: true, style: readyButtonStyle, children: /* @__PURE__ */ jsx20(Text12, { variant: "labelLarge", style: [labelTextStyle, labelColorStyle], children: ready ? "READY \u2713" : "READY?" }) });
1225
1258
  }
1226
- var styles16 = StyleSheet16.create({
1259
+ var styles17 = StyleSheet17.create({
1227
1260
  readyButton: {
1228
1261
  alignItems: "center",
1229
1262
  borderRadius: 12,
@@ -1247,7 +1280,7 @@ function usePopoverHost() {
1247
1280
  }
1248
1281
 
1249
1282
  // src/PlayerSetupPanel.tsx
1250
- import { jsx as jsx20, jsxs as jsxs17 } from "react/jsx-runtime";
1283
+ import { jsx as jsx21, jsxs as jsxs17 } from "react/jsx-runtime";
1251
1284
  function getColorPopoverId(idPrefix) {
1252
1285
  return `${idPrefix}-color`;
1253
1286
  }
@@ -1262,16 +1295,16 @@ function PlayerSetupPanel({ idPrefix, host, label, labelFontFamily, color, onCol
1262
1295
  const showProfilePicker = isHuman && profiles !== void 0 && !!onProfileSelect;
1263
1296
  const showCpuDifficulty = !isHuman && cpuDifficulty !== void 0 && cpuDifficultyOptions !== void 0 && !!onCpuDifficultyChange;
1264
1297
  const selectedProfile = profiles?.find((p) => p.id === selectedProfileId) ?? null;
1265
- return /* @__PURE__ */ jsxs17(View15, { style: [styles17.panel, ownPopoverOpen && styles17.panelOpen], children: [
1266
- showProfilePicker ? /* @__PURE__ */ jsx20(ProfilePicker, { idPrefix, host: popover, profiles, selectedId: selectedProfileId ?? null, takenId: takenProfileId, color, dark, guestLabel: guestLabel ?? "GUEST", onSelect: (profile) => onProfileSelect?.(profile), onManage: onManageProfiles }) : showCpuDifficulty ? /* @__PURE__ */ jsx20(LabeledDropdown, { id: getCpuDifficultyPopoverId(idPrefix), host: popover, options: cpuDifficultyOptions, value: cpuDifficulty, onChange: onCpuDifficultyChange, color, dark, alignOverride: cpuDifficultyAlignOverride }) : label && /* @__PURE__ */ jsx20(Text13, { variant: "labelSmall", style: { color, fontFamily: labelFontFamily }, children: label }),
1267
- /* @__PURE__ */ jsxs17(View15, { style: [styles17.pickerRow, pickerRowPopoverOpen && styles17.pickerRowOpen], children: [
1268
- /* @__PURE__ */ jsx20(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 }),
1298
+ return /* @__PURE__ */ jsxs17(View16, { style: [styles18.panel, ownPopoverOpen && styles18.panelOpen], children: [
1299
+ 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 }),
1300
+ /* @__PURE__ */ jsxs17(View16, { style: [styles18.pickerRow, pickerRowPopoverOpen && styles18.pickerRowOpen], children: [
1301
+ /* @__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 }),
1269
1302
  secondPicker
1270
1303
  ] }),
1271
- isHuman && showReadyButton && onToggleReady && /* @__PURE__ */ jsx20(ReadyButton, { color, ready: ready ?? false, onToggleReady })
1304
+ isHuman && showReadyButton && onToggleReady && /* @__PURE__ */ jsx21(ReadyButton, { color, ready: ready ?? false, onToggleReady })
1272
1305
  ] });
1273
1306
  }
1274
- var styles17 = StyleSheet17.create({
1307
+ var styles18 = StyleSheet18.create({
1275
1308
  panel: {
1276
1309
  alignItems: "center",
1277
1310
  gap: 12
@@ -1303,29 +1336,29 @@ var styles17 = StyleSheet17.create({
1303
1336
  });
1304
1337
 
1305
1338
  // src/PressAwayOverlay.tsx
1306
- import { Pressable, StyleSheet as StyleSheet18 } from "react-native";
1307
- import { jsx as jsx21 } from "react/jsx-runtime";
1339
+ import { Pressable, StyleSheet as StyleSheet19 } from "react-native";
1340
+ import { jsx as jsx22 } from "react/jsx-runtime";
1308
1341
  function PressAwayOverlay({ active, onPress, style }) {
1309
1342
  if (!active) return null;
1310
- return /* @__PURE__ */ jsx21(Pressable, { accessibilityLabel: "Dismiss", accessibilityRole: "button", onPress, style: [StyleSheet18.absoluteFill, style] });
1343
+ return /* @__PURE__ */ jsx22(Pressable, { accessibilityLabel: "Dismiss", accessibilityRole: "button", onPress, style: [StyleSheet19.absoluteFill, style] });
1311
1344
  }
1312
1345
 
1313
1346
  // src/SharedActionBand.tsx
1314
1347
  import { IconButton as IconButton4 } from "@rific/feedback-press";
1315
- import { StyleSheet as StyleSheet19, View as View16 } from "react-native";
1316
- import { jsx as jsx22, jsxs as jsxs18 } from "react/jsx-runtime";
1348
+ import { StyleSheet as StyleSheet20, View as View17 } from "react-native";
1349
+ import { jsx as jsx23, jsxs as jsxs18 } from "react/jsx-runtime";
1317
1350
  function SharedActionBand({ onBack, onSettings, onRandomize, onReset, fg, popoverOpen, children }) {
1318
- return /* @__PURE__ */ jsxs18(View16, { style: [styles18.column, popoverOpen && styles18.columnOpen], children: [
1319
- /* @__PURE__ */ jsxs18(View16, { style: styles18.actionsRow, children: [
1320
- /* @__PURE__ */ jsx22(IconButton4, { icon: "arrow-left", iconColor: fg, size: 20, onPress: onBack, accessibilityLabel: "Back" }),
1321
- onRandomize && /* @__PURE__ */ jsx22(IconButton4, { icon: "dice-multiple", iconColor: fg, size: 18, onPress: onRandomize, accessibilityLabel: "Randomize match settings" }),
1322
- onReset && /* @__PURE__ */ jsx22(IconButton4, { icon: "restore", iconColor: fg, size: 18, onPress: onReset, accessibilityLabel: "Reset match settings to defaults" }),
1323
- /* @__PURE__ */ jsx22(IconButton4, { icon: "cog", iconColor: fg, size: 20, onPress: onSettings, accessibilityLabel: "Settings" })
1351
+ return /* @__PURE__ */ jsxs18(View17, { style: [styles19.column, popoverOpen && styles19.columnOpen], children: [
1352
+ /* @__PURE__ */ jsxs18(View17, { style: styles19.actionsRow, children: [
1353
+ /* @__PURE__ */ jsx23(IconButton4, { icon: "arrow-left", iconColor: fg, size: 20, onPress: onBack, accessibilityLabel: "Back" }),
1354
+ onRandomize && /* @__PURE__ */ jsx23(IconButton4, { icon: "dice-multiple", iconColor: fg, size: 18, onPress: onRandomize, accessibilityLabel: "Randomize match settings" }),
1355
+ onReset && /* @__PURE__ */ jsx23(IconButton4, { icon: "restore", iconColor: fg, size: 18, onPress: onReset, accessibilityLabel: "Reset match settings to defaults" }),
1356
+ /* @__PURE__ */ jsx23(IconButton4, { icon: "cog", iconColor: fg, size: 20, onPress: onSettings, accessibilityLabel: "Settings" })
1324
1357
  ] }),
1325
1358
  children
1326
1359
  ] });
1327
1360
  }
1328
- var styles18 = StyleSheet19.create({
1361
+ var styles19 = StyleSheet20.create({
1329
1362
  actionsRow: {
1330
1363
  alignItems: "center",
1331
1364
  flexDirection: "row",
@@ -1342,9 +1375,9 @@ var styles18 = StyleSheet19.create({
1342
1375
 
1343
1376
  // src/StaggeredWord.tsx
1344
1377
  import { useEffect as useEffect2 } from "react";
1345
- import { StyleSheet as StyleSheet20, View as View17 } from "react-native";
1378
+ import { StyleSheet as StyleSheet21, View as View18 } from "react-native";
1346
1379
  import Animated, { Easing, useAnimatedStyle, useSharedValue, withDelay, withTiming } from "react-native-reanimated";
1347
- import { jsx as jsx23 } from "react/jsx-runtime";
1380
+ import { jsx as jsx24 } from "react/jsx-runtime";
1348
1381
  var STAGGER_MS = 45;
1349
1382
  var LETTER_DURATION_MS = 320;
1350
1383
  function getStaggeredWordDuration(letterCount) {
@@ -1360,12 +1393,12 @@ function AnimatedLetter({ char, index, color, reducedMotion, fontFamily, fontSiz
1360
1393
  opacity: progress.value,
1361
1394
  transform: [{ translateY: (1 - progress.value) * 12 }, { scale: 0.85 + progress.value * 0.15 }]
1362
1395
  }));
1363
- return /* @__PURE__ */ jsx23(Animated.Text, { allowFontScaling: false, style: [{ color, fontFamily, fontSize, lineHeight, fontWeight, letterSpacing }, style], children: char });
1396
+ return /* @__PURE__ */ jsx24(Animated.Text, { allowFontScaling: false, style: [{ color, fontFamily, fontSize, lineHeight, fontWeight, letterSpacing }, style], children: char });
1364
1397
  }
1365
1398
  function StaggeredWord({ word, color, fontFamily, fontSize, lineHeight, reducedMotion, startIndex = 0, fontWeight = "bold", letterSpacing, style, onLayout }) {
1366
- return /* @__PURE__ */ jsx23(View17, { style: [styles19.row, style], onLayout, children: word.split("").map((char, i) => /* @__PURE__ */ jsx23(AnimatedLetter, { char, index: startIndex + i, color, reducedMotion, fontFamily, fontSize, lineHeight, fontWeight, letterSpacing }, i)) });
1399
+ 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)) });
1367
1400
  }
1368
- var styles19 = StyleSheet20.create({
1401
+ var styles20 = StyleSheet21.create({
1369
1402
  row: {
1370
1403
  flexDirection: "row"
1371
1404
  }
@@ -1373,12 +1406,12 @@ var styles19 = StyleSheet20.create({
1373
1406
 
1374
1407
  // src/UpdateDialog.tsx
1375
1408
  import { useUpdater as useUpdater2 } from "@rific/updater";
1376
- import { jsx as jsx24 } from "react/jsx-runtime";
1409
+ import { jsx as jsx25 } from "react/jsx-runtime";
1377
1410
  function UpdateDialog({ rotation = 0, autoCheck = true, autoPrompt = true, onError }) {
1378
1411
  const { manifest, onConfirm, respond } = useUpdateConfirmBridge();
1379
1412
  useUpdater2({ autoCheck, autoPrompt, onConfirm, onError });
1380
1413
  const date = manifest ? new Date(manifest.createdAt) : null;
1381
- return /* @__PURE__ */ jsx24(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) });
1414
+ 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) });
1382
1415
  }
1383
1416
 
1384
1417
  // src/useQuitConfirmation.ts
@@ -1404,14 +1437,14 @@ function useQuitConfirmation(hasProgress, onConfirmedBack) {
1404
1437
  // src/useZoneClampedAlign.ts
1405
1438
  import { useZoneBounds } from "@tastic/split-screen";
1406
1439
  import { useEffect as useEffect4, useState as useState7 } from "react";
1407
- import { useWindowDimensions as useWindowDimensions3 } from "react-native";
1408
- import { useSafeAreaInsets } from "react-native-safe-area-context";
1440
+ import { useWindowDimensions as useWindowDimensions4 } from "react-native";
1441
+ import { useSafeAreaInsets as useSafeAreaInsets2 } from "react-native-safe-area-context";
1409
1442
  var EDGE_MARGIN2 = 12;
1410
1443
  function useZoneClampedAlign(open, contentWidth, contentHeight, rotation = 0) {
1411
1444
  const auto = useAutoAlign(open, contentWidth, contentHeight, rotation);
1412
1445
  const zone = useZoneBounds();
1413
- const { height: windowHeight } = useWindowDimensions3();
1414
- const insets = useSafeAreaInsets();
1446
+ const { height: windowHeight } = useWindowDimensions4();
1447
+ const insets = useSafeAreaInsets2();
1415
1448
  const shouldMeasure = open && auto.measured && zone !== null;
1416
1449
  const [ownBounds, setOwnBounds] = useState7(null);
1417
1450
  const [prevShouldMeasure, setPrevShouldMeasure] = useState7(shouldMeasure);
@@ -1460,6 +1493,7 @@ export {
1460
1493
  PopoverBody,
1461
1494
  PressAwayOverlay,
1462
1495
  ReadyButton,
1496
+ RotatedFrame,
1463
1497
  SectionedDropdown,
1464
1498
  SharedActionBand,
1465
1499
  SkiaGate,