@tastic/hud 0.20.0 → 0.22.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.js CHANGED
@@ -200,10 +200,12 @@ __export(index_exports, {
200
200
  StatSection: () => StatSection,
201
201
  TriggerGaugeHost: () => TriggerGaugeHost,
202
202
  UpdateDialog: () => UpdateDialog,
203
+ WELL_SHADOW: () => WELL_SHADOW,
203
204
  getColorPopoverId: () => getColorPopoverId,
204
205
  getCpuDifficultyPopoverId: () => getCpuDifficultyPopoverId,
205
206
  getInlineColorPickerContentSize: () => getInlineColorPickerContentSize,
206
207
  getLabeledDropdownContentHeight: () => getLabeledDropdownContentHeight,
208
+ getProfilePopoverId: () => getProfilePopoverId,
207
209
  getStaggeredWordDuration: () => getStaggeredWordDuration,
208
210
  isCompactDialogHeight: () => isCompactDialogHeight,
209
211
  loadSkiaWeb: () => loadSkiaWeb,
@@ -214,6 +216,7 @@ __export(index_exports, {
214
216
  useOverlayCardColors: () => useOverlayCardColors,
215
217
  usePopoverHost: () => usePopoverHost,
216
218
  useQuitConfirmation: () => useQuitConfirmation,
219
+ useWellColors: () => useWellColors,
217
220
  useZoneClampedAlign: () => useZoneClampedAlign
218
221
  });
219
222
  module.exports = __toCommonJS(index_exports);
@@ -225,16 +228,25 @@ var import_react_native3 = require("react-native");
225
228
  var import_react_native_paper2 = require("react-native-paper");
226
229
 
227
230
  // src/AchievementRow.tsx
228
- var import_auto_paper = require("@rific/auto-paper");
229
231
  var import_react_native = require("react-native");
230
232
  var import_react_native_paper = require("react-native-paper");
233
+
234
+ // src/wellSurface.ts
235
+ var import_auto_paper = require("@rific/auto-paper");
236
+ var WELL_SHADOW = "0px 1px 2px rgba(0, 0, 0, 0.3), 0px 1px 3px 1px rgba(0, 0, 0, 0.15)";
237
+ function useWellColors() {
238
+ const { colors } = (0, import_auto_paper.useAutoPaperTheme)();
239
+ return { bg: colors.surface, fg: colors.onSurface, fgMuted: colors.onSurfaceVariant };
240
+ }
241
+
242
+ // src/AchievementRow.tsx
231
243
  var import_jsx_runtime = require("react/jsx-runtime");
232
244
  var LOCKED_BADGE_COLOR = "rgba(128,128,128,0.3)";
233
245
  function AchievementRow({ icon, title, description, badgeColor, unlockedLabel, checkColor, progress, deviceMarker, fg: fgOverride, fgMuted: fgMutedOverride, sectionBg: sectionBgOverride }) {
234
- const { dark } = (0, import_auto_paper.useAutoPaperTheme)();
235
- const fg = fgOverride ?? (dark ? "#FFFFFF" : "#000000");
236
- const fgMuted = fgMutedOverride ?? (dark ? "rgba(255,255,255,0.5)" : "rgba(0,0,0,0.5)");
237
- const sectionBg = sectionBgOverride ?? (dark ? "rgba(255,255,255,0.06)" : "rgba(0,0,0,0.04)");
246
+ const well = useWellColors();
247
+ const fg = fgOverride ?? well.fg;
248
+ const fgMuted = fgMutedOverride ?? well.fgMuted;
249
+ const sectionBg = sectionBgOverride ?? well.bg;
238
250
  const unlocked = unlockedLabel !== void 0;
239
251
  return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_react_native.View, { style: [styles.row, { backgroundColor: sectionBg }], children: [
240
252
  /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_react_native.View, { style: [styles.badge, { backgroundColor: badgeColor }], children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_react_native_paper.Icon, { source: icon, size: 20, color: unlocked ? "#000000" : fgMuted }) }),
@@ -277,6 +289,7 @@ var styles = import_react_native.StyleSheet.create({
277
289
  row: {
278
290
  alignItems: "center",
279
291
  borderRadius: 12,
292
+ boxShadow: WELL_SHADOW,
280
293
  flexDirection: "row",
281
294
  gap: 12,
282
295
  padding: 12
@@ -298,13 +311,13 @@ var MONO_FONT = import_react_native2.Platform.select({ ios: "Menlo", android: "m
298
311
 
299
312
  // src/AchievementCatalogSection.tsx
300
313
  var import_jsx_runtime2 = require("react/jsx-runtime");
301
- function AchievementCatalogSection({ rows, label = "ALL ACHIEVEMENTS", fg, fgMuted: fgMutedOverride }) {
314
+ function AchievementCatalogSection({ rows, label = "ALL ACHIEVEMENTS", fg, fgMuted: fgMutedOverride, sectionBg }) {
302
315
  const { dark } = (0, import_auto_paper2.useAutoPaperTheme)();
303
316
  const fgMuted = fgMutedOverride ?? (dark ? "rgba(255,255,255,0.5)" : "rgba(0,0,0,0.5)");
304
317
  const tierAccent = (tierColor) => dark ? tierColor : (0, import_auto_paper2.getBlendedColor)("#000000", tierColor, 0.5);
305
318
  return /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(import_react.Fragment, { children: [
306
319
  /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_react_native_paper2.Text, { variant: "labelMedium", style: [styles2.label, { color: fgMuted, fontFamily: MONO_FONT }], children: label }),
307
- rows.map((row) => /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(AchievementRow, { icon: row.icon, title: row.title, description: row.description, badgeColor: row.unlockedAt !== void 0 ? row.tierColor : LOCKED_BADGE_COLOR, checkColor: tierAccent(row.tierColor), unlockedLabel: row.unlockedLabel, progress: row.progress, deviceMarker: row.deviceMarker, fg, fgMuted: fgMutedOverride }, row.id))
320
+ rows.map((row) => /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(AchievementRow, { icon: row.icon, title: row.title, description: row.description, badgeColor: row.unlockedAt !== void 0 ? row.tierColor : LOCKED_BADGE_COLOR, checkColor: tierAccent(row.tierColor), unlockedLabel: row.unlockedLabel, progress: row.progress, deviceMarker: row.deviceMarker, fg, fgMuted: fgMutedOverride, sectionBg }, row.id))
308
321
  ] });
309
322
  }
310
323
  var styles2 = import_react_native3.StyleSheet.create({
@@ -359,14 +372,13 @@ var styles3 = import_react_native4.StyleSheet.create({
359
372
  });
360
373
 
361
374
  // src/StatRow.tsx
362
- var import_auto_paper4 = require("@rific/auto-paper");
363
375
  var import_react_native5 = require("react-native");
364
376
  var import_react_native_paper4 = require("react-native-paper");
365
377
  var import_jsx_runtime4 = require("react/jsx-runtime");
366
378
  function StatRow({ label, value, fg: fgOverride, fgMuted: fgMutedOverride }) {
367
- const { dark } = (0, import_auto_paper4.useAutoPaperTheme)();
368
- const fg = fgOverride ?? (dark ? "#FFFFFF" : "#000000");
369
- const fgMuted = fgMutedOverride ?? (dark ? "rgba(255,255,255,0.5)" : "rgba(0,0,0,0.5)");
379
+ const well = useWellColors();
380
+ const fg = fgOverride ?? well.fg;
381
+ const fgMuted = fgMutedOverride ?? well.fgMuted;
370
382
  return /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(import_react_native5.View, { style: styles4.row, children: [
371
383
  /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(import_react_native_paper4.Text, { variant: "bodyMedium", style: { color: fgMuted }, children: label }),
372
384
  /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(import_react_native_paper4.Text, { variant: "bodyMedium", style: [styles4.value, { color: fg }], children: value })
@@ -384,14 +396,13 @@ var styles4 = import_react_native5.StyleSheet.create({
384
396
  });
385
397
 
386
398
  // src/StatSection.tsx
387
- var import_auto_paper5 = require("@rific/auto-paper");
388
399
  var import_react_native6 = require("react-native");
389
400
  var import_react_native_paper5 = require("react-native-paper");
390
401
  var import_jsx_runtime5 = require("react/jsx-runtime");
391
402
  function StatSection({ label, fg: fgOverride, sectionBg: sectionBgOverride, children }) {
392
- const { dark } = (0, import_auto_paper5.useAutoPaperTheme)();
393
- const fg = fgOverride ?? (dark ? "#FFFFFF" : "#000000");
394
- const sectionBg = sectionBgOverride ?? (dark ? "rgba(255,255,255,0.06)" : "rgba(0,0,0,0.04)");
403
+ const well = useWellColors();
404
+ const fg = fgOverride ?? well.fg;
405
+ const sectionBg = sectionBgOverride ?? well.bg;
395
406
  return /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(import_react_native6.View, { style: [styles5.section, { backgroundColor: sectionBg }], children: [
396
407
  /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(import_react_native_paper5.Text, { variant: "labelMedium", style: [styles5.label, { color: fg }], children: label }),
397
408
  children
@@ -408,6 +419,7 @@ var styles5 = import_react_native6.StyleSheet.create({
408
419
  },
409
420
  section: {
410
421
  borderRadius: 12,
422
+ boxShadow: WELL_SHADOW,
411
423
  gap: 8,
412
424
  padding: 16
413
425
  }
@@ -415,16 +427,16 @@ var styles5 = import_react_native6.StyleSheet.create({
415
427
 
416
428
  // src/ActivityStatSection.tsx
417
429
  var import_jsx_runtime6 = require("react/jsx-runtime");
418
- function ActivityStatSection({ stats }) {
419
- return /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(StatSection, { label: "ACTIVITY", children: [
420
- /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(StatRow, { label: "Days Played", value: String(stats.distinctDaysPlayed) }),
421
- /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(StatRow, { label: "Day Streak", value: String(stats.currentDayStreak) }),
422
- /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(StatRow, { label: "Best Day Streak", value: String(stats.bestDayStreak) })
430
+ function ActivityStatSection({ stats, fg, fgMuted, sectionBg }) {
431
+ return /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(StatSection, { label: "ACTIVITY", fg, sectionBg, children: [
432
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(StatRow, { label: "Days Played", value: String(stats.distinctDaysPlayed), fg, fgMuted }),
433
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(StatRow, { label: "Day Streak", value: String(stats.currentDayStreak), fg, fgMuted }),
434
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(StatRow, { label: "Best Day Streak", value: String(stats.bestDayStreak), fg, fgMuted })
423
435
  ] });
424
436
  }
425
437
 
426
438
  // src/BaseSettingsDialog.tsx
427
- var import_auto_paper9 = require("@rific/auto-paper");
439
+ var import_auto_paper7 = require("@rific/auto-paper");
428
440
  var import_feedback_press2 = require("@rific/feedback-press");
429
441
  var import_updater = require("@rific/updater");
430
442
  var import_core4 = require("@tastic/core");
@@ -434,7 +446,7 @@ var import_react_native_paper9 = require("react-native-paper");
434
446
  var import_react_native_safe_area_context2 = require("react-native-safe-area-context");
435
447
 
436
448
  // src/ConfirmDialog.tsx
437
- var import_auto_paper8 = require("@rific/auto-paper");
449
+ var import_auto_paper6 = require("@rific/auto-paper");
438
450
  var import_feedback_press = require("@rific/feedback-press");
439
451
  var import_core2 = require("@tastic/core");
440
452
  var import_react3 = require("react");
@@ -442,7 +454,7 @@ var import_react_native11 = require("react-native");
442
454
  var import_react_native_paper7 = require("react-native-paper");
443
455
 
444
456
  // src/DialogHeader.tsx
445
- var import_auto_paper6 = require("@rific/auto-paper");
457
+ var import_auto_paper4 = require("@rific/auto-paper");
446
458
  var import_react_native7 = require("react-native");
447
459
  var import_react_native_paper6 = require("react-native-paper");
448
460
  var import_jsx_runtime7 = require("react/jsx-runtime");
@@ -451,7 +463,7 @@ function isCompactDialogHeight(height) {
451
463
  return height < COMPACT_DIALOG_HEIGHT;
452
464
  }
453
465
  function DialogHeader({ icon, title, color, compact = false, style }) {
454
- const { colors } = (0, import_auto_paper6.useAutoPaperTheme)();
466
+ const { colors } = (0, import_auto_paper4.useAutoPaperTheme)();
455
467
  const accent = color ?? colors.primary;
456
468
  return /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(import_react_native7.View, { style: [compact ? styles6.compact : styles6.full, style], children: [
457
469
  /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(import_react_native_paper6.Icon, { source: icon, size: compact ? COMPACT_ICON_SIZE : ICON_SIZE, color: accent }),
@@ -548,11 +560,11 @@ var overlayActionStyles = import_react_native8.StyleSheet.create({
548
560
  });
549
561
 
550
562
  // src/OverlaySurface.tsx
551
- var import_auto_paper7 = require("@rific/auto-paper");
563
+ var import_auto_paper5 = require("@rific/auto-paper");
552
564
  var import_react_native9 = require("react-native");
553
565
  var import_jsx_runtime8 = require("react/jsx-runtime");
554
566
  function useOverlayCardColors() {
555
- const { colors } = (0, import_auto_paper7.useAutoPaperTheme)();
567
+ const { colors } = (0, import_auto_paper5.useAutoPaperTheme)();
556
568
  return { fg: colors.onSurface, fgMuted: colors.onSurfaceVariant, cardBorder: colors.outlineVariant, backdrop: colors.backdrop };
557
569
  }
558
570
  function OverlayBackdrop({ children, style, onLayout }) {
@@ -560,9 +572,9 @@ function OverlayBackdrop({ children, style, onLayout }) {
560
572
  return /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(import_react_native9.View, { onLayout, style: [overlayStyles.overlay, { backgroundColor: backdrop }, style], children });
561
573
  }
562
574
  function OverlayCard({ children, style, ...rest }) {
563
- const { isV3, roundness } = (0, import_auto_paper7.useAutoPaperTheme)();
564
- const blur = (0, import_auto_paper7.useBlur)();
565
- return /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(import_auto_paper7.BlurView, { blur, style: [overlayStyles.card, styles7.card, { borderRadius: (isV3 ? 7 : 1) * roundness }, style], ...rest, children });
575
+ const { isV3, roundness } = (0, import_auto_paper5.useAutoPaperTheme)();
576
+ const blur = (0, import_auto_paper5.useBlur)();
577
+ return /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(import_auto_paper5.BlurView, { blur, style: [overlayStyles.card, styles7.card, { borderRadius: (isV3 ? 7 : 1) * roundness }, style], ...rest, children });
566
578
  }
567
579
  var styles7 = import_react_native9.StyleSheet.create({
568
580
  card: { overflow: "hidden" }
@@ -588,7 +600,7 @@ function useCompactDialog(rotation = 0) {
588
600
  // src/ConfirmDialog.tsx
589
601
  var import_jsx_runtime9 = require("react/jsx-runtime");
590
602
  function ConfirmDialog({ visible, title, message, confirmLabel, cancelLabel, onConfirm, onCancel, rotation = 0, icon = "help-circle-outline", destructive = false }) {
591
- const { colors } = (0, import_auto_paper8.useAutoPaperTheme)();
603
+ const { colors } = (0, import_auto_paper6.useAutoPaperTheme)();
592
604
  const { fg } = useOverlayCardColors();
593
605
  const { compact, onLayout } = useCompactDialog(rotation);
594
606
  const onCancelRef = (0, import_react3.useRef)(onCancel);
@@ -693,7 +705,7 @@ function SettingIcon({ source, color, containerColor }) {
693
705
  return /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(import_react_native13.View, { style: [styles10.iconBadge, { backgroundColor: containerColor }], children: /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(import_react_native_paper9.Icon, { source, size: 18, color }) });
694
706
  }
695
707
  function BaseSettingsDialog({ visible, onDismiss, rotation: rotationOverride, version, lockOrientation, onLockOrientationChange, deferBottomEdgeGestures, onDeferBottomEdgeGestures, keepAwake, onKeepAwakeChange, hideSound = false, hideHaptics = false, hideAppearance = false, hideUpdateCheck = false, onUpdateError, onShowHowToPlay, children }) {
696
- const { colors } = (0, import_auto_paper9.useAutoPaperTheme)();
708
+ const { colors } = (0, import_auto_paper7.useAutoPaperTheme)();
697
709
  const ambientRotation = (0, import_core4.useRotation)();
698
710
  const rotation = rotationOverride ?? ambientRotation;
699
711
  const window = (0, import_react_native13.useWindowDimensions)();
@@ -706,8 +718,8 @@ function BaseSettingsDialog({ visible, onDismiss, rotation: rotationOverride, ve
706
718
  const { settings: soundSettings, set: setSoundSettings } = (0, import_feedback_press2.useSoundSettings)();
707
719
  const sound = (0, import_react6.useContext)(import_feedback_press2.SoundContext);
708
720
  const { forceShort: forceHapticFeedback } = (0, import_feedback_press2.useVibration)();
709
- const { settings: themeSettings, set: setThemeSettings } = (0, import_auto_paper9.useThemeSettings)();
710
- const expoBlur = (0, import_auto_paper9.useBlurModule)();
721
+ const { settings: themeSettings, set: setThemeSettings } = (0, import_auto_paper7.useThemeSettings)();
722
+ const expoBlur = (0, import_auto_paper7.useBlurModule)();
711
723
  const [infoMessage, setInfoMessage] = (0, import_react6.useState)(null);
712
724
  const { manifest: updateManifest, onConfirm: onUpdateConfirm, respond: respondToUpdateConfirm } = useUpdateConfirmBridge();
713
725
  const { check, checking, updateReady } = (0, import_updater.useUpdater)({
@@ -730,8 +742,8 @@ function BaseSettingsDialog({ visible, onDismiss, rotation: rotationOverride, ve
730
742
  const showUpdateCheck = import_react_native13.Platform.OS !== "web" && !hideUpdateCheck;
731
743
  if (!opened) return null;
732
744
  return /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(import_react_native_paper9.Portal, { children: /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)(RotatedFrame, { rotation, rotatedSafeArea: true, portalHost: true, passThrough: true, children: [
733
- /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)(import_auto_paper9.Dialog, { visible, onDismiss, style: [styles10.dialog, { width: sheetWidth }], children: [
734
- /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(import_auto_paper9.Dialog.ScrollArea, { style: styles10.scrollArea, children: /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)(import_auto_paper9.FadingScrollView, { contentContainerStyle: styles10.scrollContent, showsVerticalScrollIndicator: false, children: [
745
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)(import_auto_paper7.Dialog, { visible, onDismiss, style: [styles10.dialog, { width: sheetWidth }], children: [
746
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(import_auto_paper7.Dialog.ScrollArea, { style: styles10.scrollArea, children: /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)(import_auto_paper7.FadingScrollView, { contentContainerStyle: styles10.scrollContent, showsVerticalScrollIndicator: false, children: [
735
747
  /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(DialogHeader, { icon: "cog", title: "Settings", compact: compactHeader }),
736
748
  /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)(import_react_native13.View, { style: styles10.content, children: [
737
749
  /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)(import_react_native13.View, { style: styles10.toggleGroup, children: [
@@ -813,7 +825,7 @@ function BaseSettingsDialog({ visible, onDismiss, rotation: rotationOverride, ve
813
825
  ] }),
814
826
  showAppearance && /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)(import_react_native13.View, { style: styles10.section, children: [
815
827
  /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(import_react_native_paper9.Text, { variant: "labelMedium", style: [styles10.sectionLabel, { color: colors.onSurfaceVariant }], children: "APPEARANCE" }),
816
- /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(import_auto_paper9.AutoAppearancePicker, { showLabels: false }),
828
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(import_auto_paper7.AutoAppearancePicker, { showLabels: false }),
817
829
  showBlur && /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(import_feedback_press2.TouchableRipple, { onPress: () => setThemeSettings({ blur: !themeSettings.blur }), style: styles10.toggleButton, accessibilityLabel: `Blur ${themeSettings.blur ? "on" : "off"}`, children: /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)(import_react_native13.View, { style: styles10.toggleContent, children: [
818
830
  /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(SettingIcon, { source: themeSettings.blur ? "blur" : "blur-off", color: themeSettings.blur ? colors.tertiary : colors.onSurfaceVariant, containerColor: themeSettings.blur ? colors.tertiaryContainer : colors.surfaceVariant }),
819
831
  /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)(import_react_native13.View, { style: styles10.flexShrink, children: [
@@ -924,7 +936,7 @@ var styles10 = import_react_native13.StyleSheet.create({
924
936
  });
925
937
 
926
938
  // src/BaseStatsScreen.tsx
927
- var import_auto_paper10 = require("@rific/auto-paper");
939
+ var import_auto_paper8 = require("@rific/auto-paper");
928
940
  var import_feedback_press3 = require("@rific/feedback-press");
929
941
  var import_core5 = require("@tastic/core");
930
942
  var import_react7 = require("react");
@@ -932,7 +944,7 @@ var import_react_native14 = require("react-native");
932
944
  var import_react_native_paper10 = require("react-native-paper");
933
945
  var import_jsx_runtime12 = require("react/jsx-runtime");
934
946
  function BaseStatsScreen({ rotation: rotationOverride, title = "Achievements", titleVariant = "headlineSmall", onBack, backLabel = "Back", hitSlop, 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 }) {
935
- const { dark, colors } = (0, import_auto_paper10.useAutoPaperTheme)();
947
+ const { dark, colors } = (0, import_auto_paper8.useAutoPaperTheme)();
936
948
  const ambientRotation = (0, import_core5.useRotation)();
937
949
  const rotation = rotationOverride ?? ambientRotation;
938
950
  const [confirmResetVisible, setConfirmResetVisible] = (0, import_react7.useState)(false);
@@ -944,7 +956,7 @@ function BaseStatsScreen({ rotation: rotationOverride, title = "Achievements", t
944
956
  /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(import_feedback_press3.IconButton, { icon: "arrow-left", iconColor: fg, size: 24, hitSlop, onPress: onBack, accessibilityLabel: backLabel }),
945
957
  /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(import_react_native_paper10.Text, { variant: titleVariant, style: [styles11.title, { color: fg }], children: title })
946
958
  ] }),
947
- /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)(import_react_native14.ScrollView, { style: styles11.scrollView, contentContainerStyle: [styles11.content, { paddingBottom: 32 + insets.bottom }], showsVerticalScrollIndicator: false, children: [
959
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)(import_auto_paper8.FadingScrollView, { style: styles11.scrollView, contentContainerStyle: [styles11.content, { paddingBottom: 32 + insets.bottom }], showsVerticalScrollIndicator: false, children: [
948
960
  children,
949
961
  showReset && /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(import_feedback_press3.Button, { mode: "contained", onPress: () => setConfirmResetVisible(true), buttonColor: colors.danger, textColor: colors.onDanger, style: styles11.resetButton, children: resetLabel })
950
962
  ] }),
@@ -985,7 +997,7 @@ var styles11 = import_react_native14.StyleSheet.create({
985
997
  resetButton: {
986
998
  marginTop: 16
987
999
  },
988
- // Bounds the ScrollView to the space `container`'s flex:1 actually gives it - without this, a
1000
+ // Bounds the scroller (FadingScrollView puts it on its outer box) to the space `container`'s flex:1 actually gives it - without this, a
989
1001
  // ScrollView with only a contentContainerStyle isn't reliably height-constrained on native (it
990
1002
  // can render at its full unclipped content height instead of the screen's), which leaves the
991
1003
  // header's back button touch target unreliable underneath it.
@@ -1027,7 +1039,7 @@ var import_core9 = require("@tastic/core");
1027
1039
  var import_react_native20 = require("react-native");
1028
1040
 
1029
1041
  // src/SectionedDropdown.tsx
1030
- var import_auto_paper11 = require("@rific/auto-paper");
1042
+ var import_auto_paper9 = require("@rific/auto-paper");
1031
1043
  var import_feedback_press4 = require("@rific/feedback-press");
1032
1044
  var import_core8 = require("@tastic/core");
1033
1045
  var import_react_native19 = require("react-native");
@@ -1188,8 +1200,8 @@ function SectionedDropdown({ id, host, icon, accessibilityLabel, sections, accen
1188
1200
  const ambientRotation = (0, import_core8.useRotation)();
1189
1201
  const rotation = rotationOverride ?? ambientRotation;
1190
1202
  const menuBg = dark ? "#000000" : "#FFFFFF";
1191
- const menuBorderColor = (0, import_auto_paper11.getBlendedColor)(mutedColor, menuBg, 0.5);
1192
- const resolvedOnAccentColor = onAccentColor ?? (0, import_auto_paper11.getColorRoles)(accentColor, menuBg).onColor;
1203
+ const menuBorderColor = (0, import_auto_paper9.getBlendedColor)(mutedColor, menuBg, 0.5);
1204
+ const resolvedOnAccentColor = onAccentColor ?? (0, import_auto_paper9.getColorRoles)(accentColor, menuBg).onColor;
1193
1205
  const fg = dark ? "#FFFFFF" : "#000000";
1194
1206
  const open = host.openId === id;
1195
1207
  const estimatedHeight = MENU_VERTICAL_PADDING + sections.reduce((sum, section, sectionIndex) => {
@@ -1430,7 +1442,7 @@ var styles17 = import_react_native22.StyleSheet.create({
1430
1442
  });
1431
1443
 
1432
1444
  // src/InlineColorPicker.tsx
1433
- var import_auto_paper12 = require("@rific/auto-paper");
1445
+ var import_auto_paper10 = require("@rific/auto-paper");
1434
1446
  var import_feedback_press6 = require("@rific/feedback-press");
1435
1447
  var import_core10 = require("@tastic/core");
1436
1448
  var import_react_native23 = require("react-native");
@@ -1456,7 +1468,7 @@ function getInlineColorPickerContentSize(swatchCount, windowWidth, columns) {
1456
1468
  const height = SWATCHES_BORDER_WIDTH * 2 + SWATCHES_PADDING * 2 + SWATCH_SIZE * rows + SWATCHES_GAP * (rows - 1);
1457
1469
  return { width, height };
1458
1470
  }
1459
- function InlineColorPicker({ id, host, value, onChange, previewValue, swatches = import_auto_paper12.defaultColors, takenValue, allowSwapTaken, dark, align: forcedAlign, alignOverride, rotation: rotationOverride, icon = "palette", tag, labelFontFamily = MONO_FONT, autoDismiss = true, columns, size = DEFAULT_SIZE }) {
1471
+ function InlineColorPicker({ id, host, value, onChange, previewValue, swatches = import_auto_paper10.defaultColors, takenValue, allowSwapTaken, dark, align: forcedAlign, alignOverride, rotation: rotationOverride, icon = "palette", tag, labelFontFamily = MONO_FONT, autoDismiss = true, columns, size = DEFAULT_SIZE }) {
1460
1472
  const ambientRotation = (0, import_core10.useRotation)();
1461
1473
  const rotation = rotationOverride ?? ambientRotation;
1462
1474
  const menuBg = dark ? "#000000" : "#FFFFFF";
@@ -1469,7 +1481,7 @@ function InlineColorPicker({ id, host, value, onChange, previewValue, swatches =
1469
1481
  const align = forcedAlign ?? placement.align;
1470
1482
  const displayFor = previewValue ?? ((hex) => hex);
1471
1483
  const displayValue = displayFor(value);
1472
- const contrastColor = (0, import_auto_paper12.getContrastColor)(displayValue);
1484
+ const contrastColor = (0, import_auto_paper10.getContrastColor)(displayValue);
1473
1485
  const tagFontSize = size * (tag && EMOJI_PATTERN.test(tag) ? 0.6 : 0.4);
1474
1486
  return /* @__PURE__ */ (0, import_jsx_runtime22.jsxs)(import_react_native23.View, { style: [styles18.anchor, open && styles18.anchorOpen], children: [
1475
1487
  /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(import_feedback_press6.TouchableRipple, { onPress: () => host.toggle(id), borderless: true, style: [styles18.trigger, { backgroundColor: displayValue, borderRadius: size / 2, height: size, width: size }], children: /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(import_react_native23.View, { ref: triggerRef, collapsable: false, style: styles18.triggerMeasure, children: tag ? /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(import_react_native_paper13.Text, { style: [styles18.tagLabel, { color: contrastColor, fontFamily: labelFontFamily, fontSize: tagFontSize }], numberOfLines: 1, adjustsFontSizeToFit: true, children: tag }) : /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(import_react_native_paper13.Icon, { source: icon, size: size * 0.6, color: contrastColor }) }) }),
@@ -1488,7 +1500,7 @@ function InlineColorPicker({ id, host, value, onChange, previewValue, swatches =
1488
1500
  },
1489
1501
  borderless: true,
1490
1502
  style: [styles18.swatch, { backgroundColor: swatchDisplay }, selected && styles18.swatchSelected, taken && !swappable && styles18.swatchTaken],
1491
- children: selected ? /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(import_react_native_paper13.Icon, { source: "check", size: 16, color: (0, import_auto_paper12.getContrastColor)(swatchDisplay) }) : swappable ? /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(import_react_native_paper13.Icon, { source: "swap-horizontal", size: 16, color: (0, import_auto_paper12.getContrastColor)(swatchDisplay) }) : taken ? /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(import_react_native_paper13.Icon, { source: "close", size: 16, color: (0, import_auto_paper12.getContrastColor)(swatchDisplay) }) : /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(import_react_native23.View, {})
1503
+ children: selected ? /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(import_react_native_paper13.Icon, { source: "check", size: 16, color: (0, import_auto_paper10.getContrastColor)(swatchDisplay) }) : swappable ? /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(import_react_native_paper13.Icon, { source: "swap-horizontal", size: 16, color: (0, import_auto_paper10.getContrastColor)(swatchDisplay) }) : taken ? /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(import_react_native_paper13.Icon, { source: "close", size: 16, color: (0, import_auto_paper10.getContrastColor)(swatchDisplay) }) : /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(import_react_native23.View, {})
1492
1504
  },
1493
1505
  swatch.value
1494
1506
  );
@@ -1567,7 +1579,7 @@ var styles18 = import_react_native23.StyleSheet.create({
1567
1579
  });
1568
1580
 
1569
1581
  // src/LabeledDropdown.tsx
1570
- var import_auto_paper13 = require("@rific/auto-paper");
1582
+ var import_auto_paper11 = require("@rific/auto-paper");
1571
1583
  var import_feedback_press7 = require("@rific/feedback-press");
1572
1584
  var import_react_native24 = require("react-native");
1573
1585
  var import_react_native_paper14 = require("react-native-paper");
@@ -1601,7 +1613,7 @@ function LabeledDropdown({ id, host, options, value, onChange, color, dark, alig
1601
1613
  ] }) }),
1602
1614
  /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(PopoverBody, { visible: open && measured, align, verticalAlign, caretColor: menuBg, caretBorderColor: color, caretBorderWidth: 2, triggerSize: TRIGGER_HEIGHT, children: /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(import_react_native24.ScrollView, { style: [styles19.menu, { backgroundColor: menuBg, borderColor: color, width: POPOVER_WIDTH, maxHeight }], contentContainerStyle: styles19.menuContent, showsVerticalScrollIndicator: false, children: options.map((option) => {
1603
1615
  const isSelected = option.value === value;
1604
- const onColor = (0, import_auto_paper13.getContrastColor)(color);
1616
+ const onColor = (0, import_auto_paper11.getContrastColor)(color);
1605
1617
  return /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(import_feedback_press7.TouchableRipple, { onPress: () => handleSelect(option), style: [styles19.row, isSelected && { backgroundColor: color }], children: /* @__PURE__ */ (0, import_jsx_runtime23.jsxs)(import_react_native24.View, { style: styles19.rowInner, children: [
1606
1618
  option.icon && /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(import_react_native_paper14.Icon, { source: option.icon, size: 18, color: isSelected ? onColor : fg }),
1607
1619
  /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(import_react_native_paper14.Text, { style: [styles19.rowLabel, { color: isSelected ? onColor : fg }], numberOfLines: 1, children: option.label })
@@ -1668,7 +1680,7 @@ function loadSkiaWeb() {
1668
1680
 
1669
1681
  // src/PlayerSetupPanel.tsx
1670
1682
  var import_profile2 = require("@tastic/profile");
1671
- var import_react_native26 = require("react-native");
1683
+ var import_react_native27 = require("react-native");
1672
1684
  var import_react_native_paper16 = require("react-native-paper");
1673
1685
 
1674
1686
  // src/ReadyButton.tsx
@@ -1705,32 +1717,79 @@ function usePopoverHost() {
1705
1717
  return { openId, toggle, close };
1706
1718
  }
1707
1719
 
1720
+ // src/useZoneClampedAlign.ts
1721
+ var import_split_screen = require("@tastic/split-screen");
1722
+ var import_react12 = require("react");
1723
+ var import_react_native26 = require("react-native");
1724
+ var import_react_native_safe_area_context3 = require("react-native-safe-area-context");
1725
+ var EDGE_MARGIN2 = 12;
1726
+ function useZoneClampedAlign(open, contentWidth, contentHeight, rotation = 0) {
1727
+ const auto = useAutoAlign(open, contentWidth, contentHeight, rotation);
1728
+ const zone = (0, import_split_screen.useZoneBounds)();
1729
+ const { height: windowHeight } = (0, import_react_native26.useWindowDimensions)();
1730
+ const insets = (0, import_react_native_safe_area_context3.useSafeAreaInsets)();
1731
+ const shouldMeasure = open && auto.measured && zone !== null;
1732
+ const [ownBounds, setOwnBounds] = (0, import_react12.useState)(null);
1733
+ const [prevShouldMeasure, setPrevShouldMeasure] = (0, import_react12.useState)(shouldMeasure);
1734
+ if (shouldMeasure !== prevShouldMeasure) {
1735
+ setPrevShouldMeasure(shouldMeasure);
1736
+ setOwnBounds(null);
1737
+ }
1738
+ (0, import_react12.useEffect)(() => {
1739
+ if (!shouldMeasure) return;
1740
+ auto.triggerRef.current?.measureInWindow((_x, y, _width, height) => {
1741
+ const belowShared = zone.zoneSide === "belowShared";
1742
+ const awayRoom = belowShared ? windowHeight - insets.bottom - (y + height) - EDGE_MARGIN2 : y - insets.top - EDGE_MARGIN2;
1743
+ const towardRoom = belowShared ? y - zone.sharedEdgeY - EDGE_MARGIN2 : zone.sharedEdgeY - (y + height) - EDGE_MARGIN2;
1744
+ const useToward = contentHeight > awayRoom && towardRoom > awayRoom;
1745
+ let awaySide = belowShared ? "below" : "above";
1746
+ let towardSide = belowShared ? "above" : "below";
1747
+ if (zone.rotated) {
1748
+ awaySide = awaySide === "above" ? "below" : "above";
1749
+ towardSide = towardSide === "above" ? "below" : "above";
1750
+ }
1751
+ setOwnBounds({ maxHeight: Math.max(useToward ? towardRoom : awayRoom, 0), verticalAlign: useToward ? towardSide : awaySide });
1752
+ });
1753
+ }, [shouldMeasure, zone, auto.triggerRef, contentHeight, windowHeight, insets.top, insets.bottom]);
1754
+ if (!zone) return auto;
1755
+ if (!ownBounds) return { ...auto, measured: false };
1756
+ return { ...auto, maxHeight: ownBounds.maxHeight, measured: auto.measured, verticalAlign: ownBounds.verticalAlign };
1757
+ }
1758
+
1708
1759
  // src/PlayerSetupPanel.tsx
1709
1760
  var import_jsx_runtime25 = require("react/jsx-runtime");
1710
1761
  function getColorPopoverId(idPrefix) {
1711
1762
  return `${idPrefix}-color`;
1712
1763
  }
1764
+ function getProfilePopoverId(idPrefix) {
1765
+ return `${idPrefix}-profile`;
1766
+ }
1713
1767
  function getCpuDifficultyPopoverId(idPrefix) {
1714
1768
  return `${idPrefix}-difficulty`;
1715
1769
  }
1716
- function PlayerSetupPanel({ idPrefix, host, label, labelFontFamily, color, onColorChange, swatches, takenColor, allowSwapTaken, colorAlignOverride, colorRotation, isHuman, secondPicker, secondPickerId, ready, onToggleReady, dark, showReadyButton = true, profiles, selectedProfileId, takenProfileId, guestLabel, onProfileSelect, onManageProfiles, cpuDifficulty, cpuDifficultyOptions, onCpuDifficultyChange, cpuDifficultyAlignOverride, humanIcon = "face-man", cpuIcon = "robot" }) {
1770
+ function PlayerSetupPanel({ idPrefix, host, label, labelFontFamily, color, onColorChange, swatches, takenColor, allowSwapTaken, colorCaption, showColor = true, colorAlignOverride, colorRotation, isHuman, secondPicker, secondPickerId, ready, onToggleReady, dark, showReadyButton = true, profiles, selectedProfileId, takenProfileId, guestLabel, onProfileSelect, onManageProfiles, cpuDifficulty, cpuDifficultyOptions, onCpuDifficultyChange, humanIcon = "face-man", cpuIcon = "robot" }) {
1717
1771
  const ownHost = usePopoverHost();
1718
1772
  const popover = host ?? ownHost;
1719
1773
  const ownPopoverOpen = popover.openId?.startsWith(`${idPrefix}-`) ?? false;
1720
1774
  const pickerRowPopoverOpen = popover.openId === getColorPopoverId(idPrefix) || secondPickerId !== void 0 && popover.openId === secondPickerId;
1721
1775
  const showProfilePicker = isHuman && profiles !== void 0 && !!onProfileSelect;
1722
1776
  const showCpuDifficulty = !isHuman && cpuDifficulty !== void 0 && cpuDifficultyOptions !== void 0 && !!onCpuDifficultyChange;
1777
+ const seatButton = showProfilePicker || showCpuDifficulty;
1723
1778
  const selectedProfile = profiles?.find((p) => p.id === selectedProfileId) ?? null;
1724
- return /* @__PURE__ */ (0, import_jsx_runtime25.jsxs)(import_react_native26.View, { style: [styles21.panel, ownPopoverOpen && styles21.panelOpen], children: [
1725
- showProfilePicker ? /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(import_profile2.ProfilePicker, { idPrefix, host: popover, profiles, selectedId: selectedProfileId ?? null, takenId: takenProfileId, color, dark, guestLabel: guestLabel ?? "GUEST", onSelect: (profile) => onProfileSelect?.(profile), onManage: onManageProfiles }) : showCpuDifficulty ? /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(LabeledDropdown, { id: getCpuDifficultyPopoverId(idPrefix), host: popover, options: cpuDifficultyOptions, value: cpuDifficulty, onChange: onCpuDifficultyChange, color, dark, alignOverride: cpuDifficultyAlignOverride }) : label && /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(import_react_native_paper16.Text, { variant: "labelSmall", style: { color, fontFamily: labelFontFamily }, children: label }),
1726
- /* @__PURE__ */ (0, import_jsx_runtime25.jsxs)(import_react_native26.View, { style: [styles21.pickerRow, pickerRowPopoverOpen && styles21.pickerRowOpen], children: [
1727
- /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(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 }),
1779
+ const colorSection = showColor ? { value: color, onChange: onColorChange, swatches, takenValue: takenColor, allowSwapTaken, caption: showProfilePicker && selectedProfile ? colorCaption : void 0 } : void 0;
1780
+ const seatPickerId = showProfilePicker ? getProfilePopoverId(idPrefix) : getCpuDifficultyPopoverId(idPrefix);
1781
+ const seatPickerSize = showProfilePicker ? (0, import_profile2.getProfilePickerContentSize)(profiles.length, !!onManageProfiles, colorSection) : (0, import_profile2.getOptionPickerContentSize)(cpuDifficultyOptions?.length ?? 0, colorSection);
1782
+ const seatPickerAlign = useZoneClampedAlign(seatButton && popover.openId === seatPickerId, seatPickerSize.width, seatPickerSize.height);
1783
+ return /* @__PURE__ */ (0, import_jsx_runtime25.jsxs)(import_react_native27.View, { style: [styles21.panel, ownPopoverOpen && styles21.panelOpen], children: [
1784
+ showProfilePicker ? /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(import_profile2.ProfilePicker, { idPrefix, host: popover, profiles, selectedId: selectedProfileId ?? null, takenId: takenProfileId, color, dark, guestLabel: guestLabel ?? "GUEST", onSelect: (profile) => onProfileSelect?.(profile), onManage: onManageProfiles, colorSection, alignOverride: seatPickerAlign }) : showCpuDifficulty ? /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(import_profile2.OptionPicker, { id: getCpuDifficultyPopoverId(idPrefix), host: popover, options: cpuDifficultyOptions, value: cpuDifficulty, onChange: onCpuDifficultyChange, color, dark, icon: cpuIcon, colorSection, alignOverride: seatPickerAlign }) : label && /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(import_react_native_paper16.Text, { variant: "labelSmall", style: { color, fontFamily: labelFontFamily }, children: label }),
1785
+ (!seatButton || secondPicker) && /* @__PURE__ */ (0, import_jsx_runtime25.jsxs)(import_react_native27.View, { style: [styles21.pickerRow, pickerRowPopoverOpen && styles21.pickerRowOpen], children: [
1786
+ !seatButton && /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(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 }),
1728
1787
  secondPicker
1729
1788
  ] }),
1730
1789
  isHuman && showReadyButton && onToggleReady && /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(ReadyButton, { color, ready: ready ?? false, onToggleReady })
1731
1790
  ] });
1732
1791
  }
1733
- var styles21 = import_react_native26.StyleSheet.create({
1792
+ var styles21 = import_react_native27.StyleSheet.create({
1734
1793
  panel: {
1735
1794
  alignItems: "center",
1736
1795
  gap: 12
@@ -1741,9 +1800,9 @@ var styles21 = import_react_native26.StyleSheet.create({
1741
1800
  panelOpen: {
1742
1801
  zIndex: 100
1743
1802
  },
1744
- // Same gap as `panel`'s own vertical rhythm, reused horizontally - the color picker and (when
1745
- // present) secondPicker sit side by side within this row instead of stacked in the panel's own
1746
- // column.
1803
+ // Same gap as `panel`'s own vertical rhythm, reused horizontally - the fallback color swatch and
1804
+ // (when present) secondPicker sit side by side within this row instead of stacked in the panel's
1805
+ // own column.
1747
1806
  pickerRow: {
1748
1807
  alignItems: "center",
1749
1808
  flexDirection: "row",
@@ -1762,20 +1821,20 @@ var styles21 = import_react_native26.StyleSheet.create({
1762
1821
  });
1763
1822
 
1764
1823
  // src/PressAwayOverlay.tsx
1765
- var import_react_native27 = require("react-native");
1824
+ var import_react_native28 = require("react-native");
1766
1825
  var import_jsx_runtime26 = require("react/jsx-runtime");
1767
1826
  function PressAwayOverlay({ active, onPress, style }) {
1768
1827
  if (!active) return null;
1769
- return /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(import_react_native27.Pressable, { accessibilityLabel: "Dismiss", accessibilityRole: "button", onPress, style: [import_react_native27.StyleSheet.absoluteFill, style] });
1828
+ return /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(import_react_native28.Pressable, { accessibilityLabel: "Dismiss", accessibilityRole: "button", onPress, style: [import_react_native28.StyleSheet.absoluteFill, style] });
1770
1829
  }
1771
1830
 
1772
1831
  // src/SharedActionBand.tsx
1773
1832
  var import_feedback_press9 = require("@rific/feedback-press");
1774
- var import_react_native28 = require("react-native");
1833
+ var import_react_native29 = require("react-native");
1775
1834
  var import_jsx_runtime27 = require("react/jsx-runtime");
1776
1835
  function SharedActionBand({ onBack, onSettings, onRandomize, onReset, fg, popoverOpen, children }) {
1777
- return /* @__PURE__ */ (0, import_jsx_runtime27.jsxs)(import_react_native28.View, { style: [styles22.column, popoverOpen && styles22.columnOpen], children: [
1778
- /* @__PURE__ */ (0, import_jsx_runtime27.jsxs)(import_react_native28.View, { style: styles22.actionsRow, children: [
1836
+ return /* @__PURE__ */ (0, import_jsx_runtime27.jsxs)(import_react_native29.View, { style: [styles22.column, popoverOpen && styles22.columnOpen], children: [
1837
+ /* @__PURE__ */ (0, import_jsx_runtime27.jsxs)(import_react_native29.View, { style: styles22.actionsRow, children: [
1779
1838
  /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(import_feedback_press9.IconButton, { icon: "arrow-left", iconColor: fg, size: 20, onPress: onBack, accessibilityLabel: "Back" }),
1780
1839
  onRandomize && /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(import_feedback_press9.IconButton, { icon: "dice-multiple", iconColor: fg, size: 18, onPress: onRandomize, accessibilityLabel: "Randomize match settings" }),
1781
1840
  onReset && /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(import_feedback_press9.IconButton, { icon: "restore", iconColor: fg, size: 18, onPress: onReset, accessibilityLabel: "Reset match settings to defaults" }),
@@ -1784,7 +1843,7 @@ function SharedActionBand({ onBack, onSettings, onRandomize, onReset, fg, popove
1784
1843
  children
1785
1844
  ] });
1786
1845
  }
1787
- var styles22 = import_react_native28.StyleSheet.create({
1846
+ var styles22 = import_react_native29.StyleSheet.create({
1788
1847
  actionsRow: {
1789
1848
  alignItems: "center",
1790
1849
  flexDirection: "row",
@@ -1800,8 +1859,8 @@ var styles22 = import_react_native28.StyleSheet.create({
1800
1859
  });
1801
1860
 
1802
1861
  // src/StaggeredWord.tsx
1803
- var import_react12 = require("react");
1804
- var import_react_native29 = require("react-native");
1862
+ var import_react13 = require("react");
1863
+ var import_react_native30 = require("react-native");
1805
1864
  var import_react_native_reanimated2 = __toESM(require("react-native-reanimated"));
1806
1865
  var import_jsx_runtime28 = require("react/jsx-runtime");
1807
1866
  var STAGGER_MS = 45;
@@ -1811,7 +1870,7 @@ function getStaggeredWordDuration(letterCount) {
1811
1870
  }
1812
1871
  function AnimatedLetter({ char, index, color, reducedMotion, fontFamily, fontSize, lineHeight, fontWeight, letterSpacing }) {
1813
1872
  const progress = (0, import_react_native_reanimated2.useSharedValue)(reducedMotion ? 1 : 0);
1814
- (0, import_react12.useEffect)(() => {
1873
+ (0, import_react13.useEffect)(() => {
1815
1874
  if (reducedMotion) return;
1816
1875
  progress.value = (0, import_react_native_reanimated2.withDelay)(index * STAGGER_MS, (0, import_react_native_reanimated2.withTiming)(1, { duration: LETTER_DURATION_MS, easing: import_react_native_reanimated2.Easing.out(import_react_native_reanimated2.Easing.back(1.5)) }));
1817
1876
  }, [reducedMotion]);
@@ -1822,9 +1881,9 @@ function AnimatedLetter({ char, index, color, reducedMotion, fontFamily, fontSiz
1822
1881
  return /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(import_react_native_reanimated2.default.Text, { allowFontScaling: false, style: [{ color, fontFamily, fontSize, lineHeight, fontWeight, letterSpacing }, style], children: char });
1823
1882
  }
1824
1883
  function StaggeredWord({ word, color, fontFamily, fontSize, lineHeight, reducedMotion, startIndex = 0, fontWeight = "bold", letterSpacing, style, onLayout }) {
1825
- return /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(import_react_native29.View, { style: [styles23.row, style], onLayout, children: word.split("").map((char, i) => /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(AnimatedLetter, { char, index: startIndex + i, color, reducedMotion, fontFamily, fontSize, lineHeight, fontWeight, letterSpacing }, i)) });
1884
+ return /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(import_react_native30.View, { style: [styles23.row, style], onLayout, children: word.split("").map((char, i) => /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(AnimatedLetter, { char, index: startIndex + i, color, reducedMotion, fontFamily, fontSize, lineHeight, fontWeight, letterSpacing }, i)) });
1826
1885
  }
1827
- var styles23 = import_react_native29.StyleSheet.create({
1886
+ var styles23 = import_react_native30.StyleSheet.create({
1828
1887
  row: {
1829
1888
  flexDirection: "row"
1830
1889
  }
@@ -1841,63 +1900,24 @@ function UpdateDialog({ rotation = 0, autoCheck = true, autoPrompt = true, onErr
1841
1900
  }
1842
1901
 
1843
1902
  // src/useQuitConfirmation.ts
1844
- var import_react13 = require("react");
1903
+ var import_react14 = require("react");
1845
1904
  function useQuitConfirmation(hasProgress, onConfirmedBack) {
1846
- const [confirmVisible, setConfirmVisible] = (0, import_react13.useState)(false);
1847
- const hasProgressRef = (0, import_react13.useRef)(hasProgress);
1848
- (0, import_react13.useEffect)(() => {
1905
+ const [confirmVisible, setConfirmVisible] = (0, import_react14.useState)(false);
1906
+ const hasProgressRef = (0, import_react14.useRef)(hasProgress);
1907
+ (0, import_react14.useEffect)(() => {
1849
1908
  hasProgressRef.current = hasProgress;
1850
1909
  });
1851
- const onConfirmedBackRef = (0, import_react13.useRef)(onConfirmedBack);
1852
- (0, import_react13.useEffect)(() => {
1910
+ const onConfirmedBackRef = (0, import_react14.useRef)(onConfirmedBack);
1911
+ (0, import_react14.useEffect)(() => {
1853
1912
  onConfirmedBackRef.current = onConfirmedBack;
1854
1913
  });
1855
- const requestBack = (0, import_react13.useCallback)(() => {
1914
+ const requestBack = (0, import_react14.useCallback)(() => {
1856
1915
  if (hasProgressRef.current()) setConfirmVisible(true);
1857
1916
  else onConfirmedBackRef.current();
1858
1917
  }, []);
1859
- const cancelBack = (0, import_react13.useCallback)(() => setConfirmVisible(false), []);
1918
+ const cancelBack = (0, import_react14.useCallback)(() => setConfirmVisible(false), []);
1860
1919
  return { confirmVisible, requestBack, cancelBack };
1861
1920
  }
1862
-
1863
- // src/useZoneClampedAlign.ts
1864
- var import_split_screen = require("@tastic/split-screen");
1865
- var import_react14 = require("react");
1866
- var import_react_native30 = require("react-native");
1867
- var import_react_native_safe_area_context3 = require("react-native-safe-area-context");
1868
- var EDGE_MARGIN2 = 12;
1869
- function useZoneClampedAlign(open, contentWidth, contentHeight, rotation = 0) {
1870
- const auto = useAutoAlign(open, contentWidth, contentHeight, rotation);
1871
- const zone = (0, import_split_screen.useZoneBounds)();
1872
- const { height: windowHeight } = (0, import_react_native30.useWindowDimensions)();
1873
- const insets = (0, import_react_native_safe_area_context3.useSafeAreaInsets)();
1874
- const shouldMeasure = open && auto.measured && zone !== null;
1875
- const [ownBounds, setOwnBounds] = (0, import_react14.useState)(null);
1876
- const [prevShouldMeasure, setPrevShouldMeasure] = (0, import_react14.useState)(shouldMeasure);
1877
- if (shouldMeasure !== prevShouldMeasure) {
1878
- setPrevShouldMeasure(shouldMeasure);
1879
- setOwnBounds(null);
1880
- }
1881
- (0, import_react14.useEffect)(() => {
1882
- if (!shouldMeasure) return;
1883
- auto.triggerRef.current?.measureInWindow((_x, y, _width, height) => {
1884
- const belowShared = zone.zoneSide === "belowShared";
1885
- const awayRoom = belowShared ? windowHeight - insets.bottom - (y + height) - EDGE_MARGIN2 : y - insets.top - EDGE_MARGIN2;
1886
- const towardRoom = belowShared ? y - zone.sharedEdgeY - EDGE_MARGIN2 : zone.sharedEdgeY - (y + height) - EDGE_MARGIN2;
1887
- const useToward = contentHeight > awayRoom && towardRoom > awayRoom;
1888
- let awaySide = belowShared ? "below" : "above";
1889
- let towardSide = belowShared ? "above" : "below";
1890
- if (zone.rotated) {
1891
- awaySide = awaySide === "above" ? "below" : "above";
1892
- towardSide = towardSide === "above" ? "below" : "above";
1893
- }
1894
- setOwnBounds({ maxHeight: Math.max(useToward ? towardRoom : awayRoom, 0), verticalAlign: useToward ? towardSide : awaySide });
1895
- });
1896
- }, [shouldMeasure, zone, auto.triggerRef, contentHeight, windowHeight, insets.top, insets.bottom]);
1897
- if (!zone) return auto;
1898
- if (!ownBounds) return { ...auto, measured: false };
1899
- return { ...auto, maxHeight: ownBounds.maxHeight, measured: auto.measured, verticalAlign: ownBounds.verticalAlign };
1900
- }
1901
1921
  // Annotate the CommonJS export names for ESM import in node:
1902
1922
  0 && (module.exports = {
1903
1923
  AchievementCatalogSection,
@@ -1933,10 +1953,12 @@ function useZoneClampedAlign(open, contentWidth, contentHeight, rotation = 0) {
1933
1953
  StatSection,
1934
1954
  TriggerGaugeHost,
1935
1955
  UpdateDialog,
1956
+ WELL_SHADOW,
1936
1957
  getColorPopoverId,
1937
1958
  getCpuDifficultyPopoverId,
1938
1959
  getInlineColorPickerContentSize,
1939
1960
  getLabeledDropdownContentHeight,
1961
+ getProfilePopoverId,
1940
1962
  getStaggeredWordDuration,
1941
1963
  isCompactDialogHeight,
1942
1964
  loadSkiaWeb,
@@ -1947,5 +1969,6 @@ function useZoneClampedAlign(open, contentWidth, contentHeight, rotation = 0) {
1947
1969
  useOverlayCardColors,
1948
1970
  usePopoverHost,
1949
1971
  useQuitConfirmation,
1972
+ useWellColors,
1950
1973
  useZoneClampedAlign
1951
1974
  });