@tastic/hud 0.13.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
@@ -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();
@@ -322,27 +352,27 @@ function BaseSettingsDialog({ visible, onDismiss, rotation: rotationOverride, ve
322
352
  const showSound = !hideSound;
323
353
  const showAppearance = !hideAppearance;
324
354
  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" })
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" })
335
365
  ] })
336
366
  ] }) }),
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" })
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" })
342
372
  ] })
343
373
  ] }) }),
344
- (showSound || showHaptics) && /* @__PURE__ */ jsxs8(View6, { style: styles7.toggleRow, children: [
345
- showSound && /* @__PURE__ */ jsx8(
374
+ (showSound || showHaptics) && /* @__PURE__ */ jsxs8(View7, { style: styles8.toggleRow, children: [
375
+ showSound && /* @__PURE__ */ jsx9(
346
376
  TouchableRipple,
347
377
  {
348
378
  soundDisabled: true,
@@ -351,15 +381,15 @@ function BaseSettingsDialog({ visible, onDismiss, rotation: rotationOverride, ve
351
381
  setSoundSettings({ enabled });
352
382
  if (enabled) sound.selection?.();
353
383
  },
354
- style: styles7.toggleButtonInRow,
384
+ style: styles8.toggleButtonInRow,
355
385
  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" })
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" })
359
389
  ] })
360
390
  }
361
391
  ),
362
- showHaptics && /* @__PURE__ */ jsx8(
392
+ showHaptics && /* @__PURE__ */ jsx9(
363
393
  TouchableRipple,
364
394
  {
365
395
  hapticDisabled: true,
@@ -368,54 +398,54 @@ function BaseSettingsDialog({ visible, onDismiss, rotation: rotationOverride, ve
368
398
  setHapticSettings({ vibrate });
369
399
  if (vibrate) forceHapticFeedback();
370
400
  },
371
- style: styles7.toggleButtonInRow,
401
+ style: styles8.toggleButtonInRow,
372
402
  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" })
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" })
376
406
  ] })
377
407
  }
378
408
  )
379
409
  ] }),
380
- onShowHowToPlay && /* @__PURE__ */ jsx8(
410
+ onShowHowToPlay && /* @__PURE__ */ jsx9(
381
411
  TouchableRipple,
382
412
  {
383
413
  onPress: () => {
384
414
  onDismiss();
385
415
  onShowHowToPlay();
386
416
  },
387
- style: styles7.toggleButton,
417
+ style: styles8.toggleButton,
388
418
  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" })
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" })
394
424
  ] })
395
425
  ] })
396
426
  }
397
427
  )
398
428
  ] }),
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 })
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 })
402
432
  ] }),
403
433
  children,
404
- showUpdateCheck && /* @__PURE__ */ jsxs8(View6, { style: styles7.section, children: [
405
- /* @__PURE__ */ jsxs8(Text7, { variant: "labelSmall", style: [styles7.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: [
406
436
  "VERSION ",
407
437
  version,
408
438
  updateReady ? " \xB7 UPDATE READY" : ""
409
439
  ] }),
410
- /* @__PURE__ */ jsx8(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" })
411
441
  ] })
412
442
  ] }) })
413
443
  ] }),
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
- ] });
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
+ ] }) });
417
447
  }
418
- var styles7 = StyleSheet7.create({
448
+ var styles8 = StyleSheet8.create({
419
449
  content: {
420
450
  gap: 24,
421
451
  paddingVertical: 20
@@ -485,29 +515,29 @@ var styles7 = StyleSheet7.create({
485
515
  // src/BaseStatsScreen.tsx
486
516
  import { useAutoPaperTheme as useAutoPaperTheme8 } from "@rific/auto-paper";
487
517
  import { Button as Button3, IconButton } from "@rific/feedback-press";
488
- import { useRotation as useRotation2 } from "@tastic/core";
518
+ import { useRotation as useRotation3 } from "@tastic/core";
489
519
  import { useState as useState3 } from "react";
490
- import { ScrollView as ScrollView2, StyleSheet as StyleSheet8, View as View7 } from "react-native";
520
+ import { ScrollView as ScrollView2, StyleSheet as StyleSheet9, View as View8 } from "react-native";
491
521
  import { Text as Text8 } from "react-native-paper";
492
- import { jsx as jsx9, jsxs as jsxs9 } from "react/jsx-runtime";
522
+ import { jsx as jsx10, jsxs as jsxs9 } from "react/jsx-runtime";
493
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 }) {
494
524
  const { dark, colors } = useAutoPaperTheme8();
495
- const ambientRotation = useRotation2();
525
+ const ambientRotation = useRotation3();
496
526
  const rotation = rotationOverride ?? ambientRotation;
497
527
  const [confirmResetVisible, setConfirmResetVisible] = useState3(false);
498
528
  const showReset = !!onReset;
499
529
  const fg = fgOverride ?? (dark ? "#FFFFFF" : "#000000");
500
530
  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 })
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 })
505
535
  ] }),
506
- /* @__PURE__ */ jsxs9(ScrollView2, { style: styles8.scrollView, contentContainerStyle: [styles8.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: [
507
537
  children,
508
- showReset && /* @__PURE__ */ jsx9(Button3, { mode: "contained", onPress: () => setConfirmResetVisible(true), buttonColor: colors.danger, textColor: colors.onDanger, style: styles8.resetButton, children: resetLabel })
538
+ showReset && /* @__PURE__ */ jsx10(Button3, { mode: "contained", onPress: () => setConfirmResetVisible(true), buttonColor: colors.danger, textColor: colors.onDanger, style: styles9.resetButton, children: resetLabel })
509
539
  ] }),
510
- /* @__PURE__ */ jsx9(
540
+ /* @__PURE__ */ jsx10(
511
541
  ConfirmDialog,
512
542
  {
513
543
  visible: confirmResetVisible,
@@ -527,7 +557,7 @@ function BaseStatsScreen({ rotation: rotationOverride, title = "Achievements", t
527
557
  )
528
558
  ] });
529
559
  }
530
- var styles8 = StyleSheet8.create({
560
+ var styles9 = StyleSheet9.create({
531
561
  container: {
532
562
  flex: 1
533
563
  },
@@ -559,18 +589,18 @@ var styles8 = StyleSheet8.create({
559
589
 
560
590
  // src/ContentGutter.tsx
561
591
  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";
592
+ import { StyleSheet as StyleSheet10, View as View9 } from "react-native";
593
+ import { jsx as jsx11, jsxs as jsxs10 } from "react/jsx-runtime";
564
594
  function ContentGutter({ maxContentWidth, leftGutter, rightGutter, style, children }) {
565
595
  const { width: windowWidth } = useRotatedWindowDimensions();
566
596
  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 })
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 })
571
601
  ] });
572
602
  }
573
- var styles9 = StyleSheet9.create({
603
+ var styles10 = StyleSheet10.create({
574
604
  // overflow:'hidden' keeps an oversized leftGutter/rightGutter from bleeding into the content
575
605
  // column instead of clipping cleanly at its own real width.
576
606
  gutter: {
@@ -588,35 +618,35 @@ import { Platform as Platform3 } from "react-native";
588
618
  // src/SectionedDropdown.tsx
589
619
  import { getBlendedColor, getColorRoles } from "@rific/auto-paper";
590
620
  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";
621
+ import { useRotation as useRotation4 } from "@tastic/core";
622
+ import { ScrollView as ScrollView3, StyleSheet as StyleSheet12, View as View12 } from "react-native";
593
623
  import { Icon as Icon5, Text as Text9 } from "react-native-paper";
594
624
 
595
625
  // 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";
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";
598
628
  var CARET_SIZE = 7;
599
629
  var CARET_RING_OFFSET = 2;
600
630
  var CARET_DIP = 1;
601
631
  function PopoverBody({ visible, children, align = "center", verticalAlign = "below", caretColor, caretBorderColor, caretBorderWidth = 1, triggerSize = 0 }) {
602
632
  if (!visible) return null;
603
633
  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;
634
+ const alignStyle = align === "left" ? styles11.contentLeft : align === "right" ? styles11.contentRight : styles11.contentCenter;
635
+ const verticalStyle = above ? styles11.contentAbove : styles11.contentBelow;
606
636
  const ringSize = CARET_SIZE + caretBorderWidth;
607
637
  const caretOffset = (halfFootprint) => align === "right" ? { right: triggerSize / 2 - halfFootprint } : { left: triggerSize / 2 - halfFootprint };
608
638
  const caretFill = above ? "borderTopColor" : "borderBottomColor";
609
639
  const caretWidthProp = above ? "borderTopWidth" : "borderBottomWidth";
610
640
  const caretEdge = (size) => above ? { bottom: -size + CARET_DIP } : { top: -size + CARET_DIP };
611
- return /* @__PURE__ */ jsxs11(View9, { style: [styles10.content, alignStyle, verticalStyle], children: [
641
+ return /* @__PURE__ */ jsxs11(View10, { style: [styles11.content, alignStyle, verticalStyle], children: [
612
642
  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 }] })
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 }] })
616
646
  ] })
617
647
  ] });
618
648
  }
619
- var styles10 = StyleSheet10.create({
649
+ var styles11 = StyleSheet11.create({
620
650
  caret: {
621
651
  borderLeftColor: "transparent",
622
652
  borderRightColor: "transparent",
@@ -659,15 +689,15 @@ var styles10 = StyleSheet10.create({
659
689
  });
660
690
 
661
691
  // src/TriggerGaugeHost.tsx
662
- import { jsx as jsx12 } from "react/jsx-runtime";
692
+ import { jsx as jsx13 } from "react/jsx-runtime";
663
693
  var getTriggerGauge = () => import("./TriggerGauge-2OJOOF6I.mjs").then((mod) => ({ default: mod.TriggerGauge }));
664
694
  function TriggerGaugeHost(props) {
665
- return /* @__PURE__ */ jsx12(SkiaGate, { getComponent: getTriggerGauge, componentProps: props });
695
+ return /* @__PURE__ */ jsx13(SkiaGate, { getComponent: getTriggerGauge, componentProps: props });
666
696
  }
667
697
 
668
698
  // src/useAutoAlign.ts
669
699
  import { useCallback as useCallback2, useEffect, useRef as useRef2, useState as useState4 } from "react";
670
- import { useWindowDimensions } from "react-native";
700
+ import { useWindowDimensions as useWindowDimensions2 } from "react-native";
671
701
  var EDGE_MARGIN = 12;
672
702
  function rotateRect(x, y, width, height, rotation, windowWidth, windowHeight) {
673
703
  if (rotation === 0) return { x, y, width, height };
@@ -680,7 +710,7 @@ function rotateRect(x, y, width, height, rotation, windowWidth, windowHeight) {
680
710
  }
681
711
  function useAutoAlign(open, contentWidth, contentHeight, rotation = 0) {
682
712
  const triggerRef = useRef2(null);
683
- const { width: windowWidth, height: windowHeight } = useWindowDimensions();
713
+ const { width: windowWidth, height: windowHeight } = useWindowDimensions2();
684
714
  const [align, setAlign] = useState4("center");
685
715
  const [verticalAlign, setVerticalAlign] = useState4("below");
686
716
  const [maxHeight, setMaxHeight] = useState4(contentHeight);
@@ -714,7 +744,7 @@ function useAutoAlign(open, contentWidth, contentHeight, rotation = 0) {
714
744
  }
715
745
 
716
746
  // src/SectionedDropdown.tsx
717
- import { Fragment as Fragment4, jsx as jsx13, jsxs as jsxs12 } from "react/jsx-runtime";
747
+ import { Fragment as Fragment3, jsx as jsx14, jsxs as jsxs12 } from "react/jsx-runtime";
718
748
  var MENU_BORDER_WIDTH = 1;
719
749
  var TRIGGER_SIZE = 44;
720
750
  var MENU_MIN_WIDTH = 200;
@@ -726,7 +756,7 @@ var MENU_ITEM_HEIGHT_WITH_DESCRIPTION = 58;
726
756
  var MENU_DIVIDER_HEIGHT = 9;
727
757
  var MENU_VERTICAL_PADDING = 12;
728
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" } }) {
729
- const ambientRotation = useRotation3();
759
+ const ambientRotation = useRotation4();
730
760
  const rotation = rotationOverride ?? ambientRotation;
731
761
  const menuBg = dark ? "#000000" : "#FFFFFF";
732
762
  const menuBorderColor = getBlendedColor(mutedColor, menuBg, 0.5);
@@ -764,17 +794,17 @@ function SectionedDropdown({ id, host, icon, accessibilityLabel, sections, accen
764
794
  }
765
795
  gaugeOffset += section.options.length;
766
796
  }
767
- const anchorStyle = [styles11.anchor, open && styles11.anchorOpen];
797
+ const anchorStyle = [styles12.anchor, open && styles12.anchorOpen];
768
798
  const menuStyle = { backgroundColor: menuBg, borderColor: menuBorderColor, maxHeight };
769
799
  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) })
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) })
774
804
  ] }),
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(
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(
778
808
  SingleSection,
779
809
  {
780
810
  section,
@@ -787,7 +817,7 @@ function SectionedDropdown({ id, host, icon, accessibilityLabel, sections, accen
787
817
  if (autoDismiss) host.close();
788
818
  }
789
819
  }
790
- ) : /* @__PURE__ */ jsx13(MultiSection, { section, accentColor, onAccentColor: resolvedOnAccentColor, mutedColor, labelFontFamily, allClearLabels })
820
+ ) : /* @__PURE__ */ jsx14(MultiSection, { section, accentColor, onAccentColor: resolvedOnAccentColor, mutedColor, labelFontFamily, allClearLabels })
791
821
  ] }, section.id)) }) })
792
822
  ] });
793
823
  }
@@ -799,18 +829,18 @@ function SingleSection({
799
829
  labelFontFamily,
800
830
  onSelect
801
831
  }) {
802
- return /* @__PURE__ */ jsx13(Fragment4, { children: section.options.map((option) => {
832
+ return /* @__PURE__ */ jsx14(Fragment3, { children: section.options.map((option) => {
803
833
  const selected = option.value === section.value;
804
834
  const taken = !selected && option.value === section.takenValue;
805
835
  const rowColor = selected ? onAccentColor : mutedColor;
806
- const itemStyle = [styles11.item, selected && { backgroundColor: accentColor }, taken && styles11.itemTaken];
836
+ const itemStyle = [styles12.item, selected && { backgroundColor: accentColor }, taken && styles12.itemTaken];
807
837
  const labelStyle = { fontFamily: labelFontFamily, color: rowColor, fontWeight: selected ? "bold" : "normal" };
808
838
  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 })
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 })
814
844
  ] })
815
845
  ] }) }, option.value);
816
846
  }) });
@@ -824,23 +854,23 @@ function MultiSection({
824
854
  allClearLabels
825
855
  }) {
826
856
  const allSelected = section.value.length === section.options.length;
827
- return /* @__PURE__ */ jsxs12(Fragment4, { children: [
857
+ return /* @__PURE__ */ jsxs12(Fragment3, { children: [
828
858
  section.options.map((option, i) => {
829
859
  const selected = section.value.includes(option.value);
830
860
  const rowColor = selected ? onAccentColor : mutedColor;
831
861
  const prevSelected = selected && i > 0 && section.value.includes(section.options[i - 1].value);
832
862
  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 }];
863
+ const itemStyle = [styles12.item, selected && { backgroundColor: accentColor }, prevSelected && { borderTopLeftRadius: 0, borderTopRightRadius: 0 }, nextSelected && { borderBottomLeftRadius: 0, borderBottomRightRadius: 0 }];
834
864
  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 })
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 })
838
868
  ] }) }, option.value);
839
869
  }),
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 }) })
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 }) })
841
871
  ] });
842
872
  }
843
- var styles11 = StyleSheet11.create({
873
+ var styles12 = StyleSheet12.create({
844
874
  allClearLabel: {
845
875
  fontWeight: "bold",
846
876
  textAlign: "center"
@@ -857,7 +887,7 @@ var styles11 = StyleSheet11.create({
857
887
  zIndex: 100
858
888
  },
859
889
  divider: {
860
- height: StyleSheet11.hairlineWidth,
890
+ height: StyleSheet12.hairlineWidth,
861
891
  marginVertical: 4
862
892
  },
863
893
  item: {
@@ -910,24 +940,24 @@ var styles11 = StyleSheet11.create({
910
940
  });
911
941
 
912
942
  // src/ControlSchemePicker.tsx
913
- import { jsx as jsx14 } from "react/jsx-runtime";
943
+ import { jsx as jsx15 } from "react/jsx-runtime";
914
944
  function ControlSchemePicker({ id, host, value, onChange, options, takenValue, accentColor, mutedColor, onAccentColor, dark, align, alignOverride, rotation, labelFontFamily }) {
915
945
  const isTouchPrimary = useIsTouchPrimaryDevice2();
916
946
  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 });
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 });
918
948
  }
919
949
 
920
950
  // src/CornerActionButtons.tsx
921
951
  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";
952
+ import { StyleSheet as StyleSheet13 } from "react-native";
953
+ import { Fragment as Fragment4, jsx as jsx16, jsxs as jsxs13 } from "react/jsx-runtime";
924
954
  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" })
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" })
928
958
  ] });
929
959
  }
930
- var styles12 = StyleSheet12.create({
960
+ var styles13 = StyleSheet13.create({
931
961
  back: {
932
962
  position: "absolute"
933
963
  },
@@ -937,22 +967,22 @@ var styles12 = StyleSheet12.create({
937
967
  });
938
968
 
939
969
  // src/CornerStatusBadges.tsx
940
- import { StyleSheet as StyleSheet13, View as View12 } from "react-native";
970
+ import { StyleSheet as StyleSheet14, View as View13 } from "react-native";
941
971
  import { Icon as Icon6 } from "react-native-paper";
942
- import { Fragment as Fragment6, jsx as jsx16, jsxs as jsxs14 } from "react/jsx-runtime";
972
+ import { Fragment as Fragment5, jsx as jsx17, jsxs as jsxs14 } from "react/jsx-runtime";
943
973
  var BADGE_SIZE = 30;
944
974
  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)" }) });
975
+ return /* @__PURE__ */ jsx17(View13, { style: styles14.badge, children: icon && /* @__PURE__ */ jsx17(Icon6, { source: icon, size: 16, color: "rgba(255,255,255,0.85)" }) });
946
976
  }
947
977
  function CornerStatusBadges({ orientationMode, p1OnRight, p1, p2 }) {
948
978
  const p1OnRightSide = orientationMode === "sideBySide" && p1OnRight;
949
979
  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 }) })
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 }) })
953
983
  ] });
954
984
  }
955
- var styles13 = StyleSheet13.create({
985
+ var styles14 = StyleSheet14.create({
956
986
  badge: {
957
987
  alignItems: "center",
958
988
  backgroundColor: "rgba(0,0,0,0.28)",
@@ -973,10 +1003,10 @@ var styles13 = StyleSheet13.create({
973
1003
  // src/InlineColorPicker.tsx
974
1004
  import { defaultColors, getContrastColor as getContrastColor2 } from "@rific/auto-paper";
975
1005
  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";
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";
978
1008
  import { Icon as Icon7, Text as Text10 } from "react-native-paper";
979
- import { jsx as jsx17, jsxs as jsxs15 } from "react/jsx-runtime";
1009
+ import { jsx as jsx18, jsxs as jsxs15 } from "react/jsx-runtime";
980
1010
  var EMOJI_PATTERN = /\p{Extended_Pictographic}/u;
981
1011
  var DEFAULT_SIZE = 48;
982
1012
  var SWATCH_SIZE = 28;
@@ -998,10 +1028,10 @@ function getInlineColorPickerContentSize(swatchCount, windowWidth, columns) {
998
1028
  return { width, height };
999
1029
  }
1000
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 }) {
1001
- const ambientRotation = useRotation4();
1031
+ const ambientRotation = useRotation5();
1002
1032
  const rotation = rotationOverride ?? ambientRotation;
1003
1033
  const menuBg = dark ? "#000000" : "#FFFFFF";
1004
- const { width: windowWidth } = useWindowDimensions2();
1034
+ const { width: windowWidth } = useWindowDimensions3();
1005
1035
  const { width: swatchesWidth, height: swatchesHeight } = getInlineColorPickerContentSize(swatches.length, windowWidth, columns);
1006
1036
  const open = host.openId === id;
1007
1037
  const auto = useAutoAlign(open, swatchesWidth, swatchesHeight, rotation);
@@ -1012,14 +1042,14 @@ function InlineColorPicker({ id, host, value, onChange, previewValue, swatches =
1012
1042
  const displayValue = displayFor(value);
1013
1043
  const contrastColor = getContrastColor2(displayValue);
1014
1044
  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) => {
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) => {
1018
1048
  const selected = swatch.value.toLowerCase() === value.toLowerCase();
1019
1049
  const taken = !selected && !!takenValue && swatch.value.toLowerCase() === takenValue.toLowerCase();
1020
1050
  const swappable = taken && allowSwapTaken;
1021
1051
  const swatchDisplay = displayFor(swatch.value);
1022
- return /* @__PURE__ */ jsx17(
1052
+ return /* @__PURE__ */ jsx18(
1023
1053
  TouchableRipple3,
1024
1054
  {
1025
1055
  disabled: taken && !swappable,
@@ -1028,15 +1058,15 @@ function InlineColorPicker({ id, host, value, onChange, previewValue, swatches =
1028
1058
  if (autoDismiss) host.close();
1029
1059
  },
1030
1060
  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, {})
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, {})
1033
1063
  },
1034
1064
  swatch.value
1035
1065
  );
1036
1066
  }) }) })
1037
1067
  ] });
1038
1068
  }
1039
- var styles14 = StyleSheet14.create({
1069
+ var styles15 = StyleSheet15.create({
1040
1070
  anchor: {
1041
1071
  position: "relative"
1042
1072
  },
@@ -1110,9 +1140,9 @@ var styles14 = StyleSheet14.create({
1110
1140
  // src/LabeledDropdown.tsx
1111
1141
  import { getContrastColor as getContrastColor3 } from "@rific/auto-paper";
1112
1142
  import { TouchableRipple as TouchableRipple4 } from "@rific/feedback-press";
1113
- import { ScrollView as ScrollView5, StyleSheet as StyleSheet15, View as View14 } from "react-native";
1143
+ import { ScrollView as ScrollView5, StyleSheet as StyleSheet16, View as View15 } from "react-native";
1114
1144
  import { Icon as Icon8, Text as Text11 } from "react-native-paper";
1115
- import { jsx as jsx18, jsxs as jsxs16 } from "react/jsx-runtime";
1145
+ import { jsx as jsx19, jsxs as jsxs16 } from "react/jsx-runtime";
1116
1146
  var TRIGGER_HEIGHT = 28;
1117
1147
  var POPOVER_WIDTH = 180;
1118
1148
  var ROW_HEIGHT = 36;
@@ -1135,22 +1165,22 @@ function LabeledDropdown({ id, host, options, value, onChange, color, dark, alig
1135
1165
  onChange(option.value);
1136
1166
  host.close();
1137
1167
  };
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 })
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 })
1142
1172
  ] }) }),
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) => {
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) => {
1144
1174
  const isSelected = option.value === value;
1145
1175
  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 })
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 })
1149
1179
  ] }) }, option.value);
1150
1180
  }) }) })
1151
1181
  ] });
1152
1182
  }
1153
- var styles15 = StyleSheet15.create({
1183
+ var styles16 = StyleSheet16.create({
1154
1184
  anchor: {
1155
1185
  position: "relative"
1156
1186
  },
@@ -1209,21 +1239,21 @@ function loadSkiaWeb() {
1209
1239
 
1210
1240
  // src/PlayerSetupPanel.tsx
1211
1241
  import { ProfilePicker } from "@tastic/profile";
1212
- import { StyleSheet as StyleSheet17, View as View15 } from "react-native";
1242
+ import { StyleSheet as StyleSheet18, View as View16 } from "react-native";
1213
1243
  import { Text as Text13 } from "react-native-paper";
1214
1244
 
1215
1245
  // src/ReadyButton.tsx
1216
1246
  import { TouchableRipple as TouchableRipple5 } from "@rific/feedback-press";
1217
- import { StyleSheet as StyleSheet16 } from "react-native";
1247
+ import { StyleSheet as StyleSheet17 } from "react-native";
1218
1248
  import { Text as Text12 } from "react-native-paper";
1219
- import { jsx as jsx19 } from "react/jsx-runtime";
1249
+ import { jsx as jsx20 } from "react/jsx-runtime";
1220
1250
  function ReadyButton({ color, ready, onToggleReady, style, labelFontFamily = MONO_FONT }) {
1221
- const readyButtonStyle = [styles16.readyButton, { borderColor: color }, ready && { backgroundColor: color }, style];
1251
+ const readyButtonStyle = [styles17.readyButton, { borderColor: color }, ready && { backgroundColor: color }, style];
1222
1252
  const labelTextStyle = { fontFamily: labelFontFamily, fontWeight: "bold" };
1223
1253
  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?" }) });
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?" }) });
1225
1255
  }
1226
- var styles16 = StyleSheet16.create({
1256
+ var styles17 = StyleSheet17.create({
1227
1257
  readyButton: {
1228
1258
  alignItems: "center",
1229
1259
  borderRadius: 12,
@@ -1247,7 +1277,7 @@ function usePopoverHost() {
1247
1277
  }
1248
1278
 
1249
1279
  // src/PlayerSetupPanel.tsx
1250
- import { jsx as jsx20, jsxs as jsxs17 } from "react/jsx-runtime";
1280
+ import { jsx as jsx21, jsxs as jsxs17 } from "react/jsx-runtime";
1251
1281
  function getColorPopoverId(idPrefix) {
1252
1282
  return `${idPrefix}-color`;
1253
1283
  }
@@ -1262,16 +1292,16 @@ function PlayerSetupPanel({ idPrefix, host, label, labelFontFamily, color, onCol
1262
1292
  const showProfilePicker = isHuman && profiles !== void 0 && !!onProfileSelect;
1263
1293
  const showCpuDifficulty = !isHuman && cpuDifficulty !== void 0 && cpuDifficultyOptions !== void 0 && !!onCpuDifficultyChange;
1264
1294
  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 }),
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 }),
1269
1299
  secondPicker
1270
1300
  ] }),
1271
- isHuman && showReadyButton && onToggleReady && /* @__PURE__ */ jsx20(ReadyButton, { color, ready: ready ?? false, onToggleReady })
1301
+ isHuman && showReadyButton && onToggleReady && /* @__PURE__ */ jsx21(ReadyButton, { color, ready: ready ?? false, onToggleReady })
1272
1302
  ] });
1273
1303
  }
1274
- var styles17 = StyleSheet17.create({
1304
+ var styles18 = StyleSheet18.create({
1275
1305
  panel: {
1276
1306
  alignItems: "center",
1277
1307
  gap: 12
@@ -1303,29 +1333,29 @@ var styles17 = StyleSheet17.create({
1303
1333
  });
1304
1334
 
1305
1335
  // src/PressAwayOverlay.tsx
1306
- import { Pressable, StyleSheet as StyleSheet18 } from "react-native";
1307
- import { jsx as jsx21 } from "react/jsx-runtime";
1336
+ import { Pressable, StyleSheet as StyleSheet19 } from "react-native";
1337
+ import { jsx as jsx22 } from "react/jsx-runtime";
1308
1338
  function PressAwayOverlay({ active, onPress, style }) {
1309
1339
  if (!active) return null;
1310
- return /* @__PURE__ */ jsx21(Pressable, { accessibilityLabel: "Dismiss", accessibilityRole: "button", onPress, style: [StyleSheet18.absoluteFill, style] });
1340
+ return /* @__PURE__ */ jsx22(Pressable, { accessibilityLabel: "Dismiss", accessibilityRole: "button", onPress, style: [StyleSheet19.absoluteFill, style] });
1311
1341
  }
1312
1342
 
1313
1343
  // src/SharedActionBand.tsx
1314
1344
  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";
1345
+ import { StyleSheet as StyleSheet20, View as View17 } from "react-native";
1346
+ import { jsx as jsx23, jsxs as jsxs18 } from "react/jsx-runtime";
1317
1347
  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" })
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" })
1324
1354
  ] }),
1325
1355
  children
1326
1356
  ] });
1327
1357
  }
1328
- var styles18 = StyleSheet19.create({
1358
+ var styles19 = StyleSheet20.create({
1329
1359
  actionsRow: {
1330
1360
  alignItems: "center",
1331
1361
  flexDirection: "row",
@@ -1342,9 +1372,9 @@ var styles18 = StyleSheet19.create({
1342
1372
 
1343
1373
  // src/StaggeredWord.tsx
1344
1374
  import { useEffect as useEffect2 } from "react";
1345
- import { StyleSheet as StyleSheet20, View as View17 } from "react-native";
1375
+ import { StyleSheet as StyleSheet21, View as View18 } from "react-native";
1346
1376
  import Animated, { Easing, useAnimatedStyle, useSharedValue, withDelay, withTiming } from "react-native-reanimated";
1347
- import { jsx as jsx23 } from "react/jsx-runtime";
1377
+ import { jsx as jsx24 } from "react/jsx-runtime";
1348
1378
  var STAGGER_MS = 45;
1349
1379
  var LETTER_DURATION_MS = 320;
1350
1380
  function getStaggeredWordDuration(letterCount) {
@@ -1360,12 +1390,12 @@ function AnimatedLetter({ char, index, color, reducedMotion, fontFamily, fontSiz
1360
1390
  opacity: progress.value,
1361
1391
  transform: [{ translateY: (1 - progress.value) * 12 }, { scale: 0.85 + progress.value * 0.15 }]
1362
1392
  }));
1363
- return /* @__PURE__ */ jsx23(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 });
1364
1394
  }
1365
1395
  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)) });
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)) });
1367
1397
  }
1368
- var styles19 = StyleSheet20.create({
1398
+ var styles20 = StyleSheet21.create({
1369
1399
  row: {
1370
1400
  flexDirection: "row"
1371
1401
  }
@@ -1373,12 +1403,12 @@ var styles19 = StyleSheet20.create({
1373
1403
 
1374
1404
  // src/UpdateDialog.tsx
1375
1405
  import { useUpdater as useUpdater2 } from "@rific/updater";
1376
- import { jsx as jsx24 } from "react/jsx-runtime";
1406
+ import { jsx as jsx25 } from "react/jsx-runtime";
1377
1407
  function UpdateDialog({ rotation = 0, autoCheck = true, autoPrompt = true, onError }) {
1378
1408
  const { manifest, onConfirm, respond } = useUpdateConfirmBridge();
1379
1409
  useUpdater2({ autoCheck, autoPrompt, onConfirm, onError });
1380
1410
  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) });
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) });
1382
1412
  }
1383
1413
 
1384
1414
  // src/useQuitConfirmation.ts
@@ -1404,14 +1434,14 @@ function useQuitConfirmation(hasProgress, onConfirmedBack) {
1404
1434
  // src/useZoneClampedAlign.ts
1405
1435
  import { useZoneBounds } from "@tastic/split-screen";
1406
1436
  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";
1437
+ import { useWindowDimensions as useWindowDimensions4 } from "react-native";
1438
+ import { useSafeAreaInsets as useSafeAreaInsets2 } from "react-native-safe-area-context";
1409
1439
  var EDGE_MARGIN2 = 12;
1410
1440
  function useZoneClampedAlign(open, contentWidth, contentHeight, rotation = 0) {
1411
1441
  const auto = useAutoAlign(open, contentWidth, contentHeight, rotation);
1412
1442
  const zone = useZoneBounds();
1413
- const { height: windowHeight } = useWindowDimensions3();
1414
- const insets = useSafeAreaInsets();
1443
+ const { height: windowHeight } = useWindowDimensions4();
1444
+ const insets = useSafeAreaInsets2();
1415
1445
  const shouldMeasure = open && auto.measured && zone !== null;
1416
1446
  const [ownBounds, setOwnBounds] = useState7(null);
1417
1447
  const [prevShouldMeasure, setPrevShouldMeasure] = useState7(shouldMeasure);
@@ -1460,6 +1490,7 @@ export {
1460
1490
  PopoverBody,
1461
1491
  PressAwayOverlay,
1462
1492
  ReadyButton,
1493
+ RotatedFrame,
1463
1494
  SectionedDropdown,
1464
1495
  SharedActionBand,
1465
1496
  SkiaGate,