@tastic/hud 0.4.0 → 0.6.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
@@ -4,11 +4,11 @@ import { StyleSheet, View } from "react-native";
4
4
  import { Icon, ProgressBar, Text } from "react-native-paper";
5
5
  import { jsx, jsxs } from "react/jsx-runtime";
6
6
  var LOCKED_BADGE_COLOR = "rgba(128,128,128,0.3)";
7
- function AchievementRow({ icon, title, description, badgeColor, unlockedLabel, checkColor, progress, deviceMarker }) {
7
+ function AchievementRow({ icon, title, description, badgeColor, unlockedLabel, checkColor, progress, deviceMarker, fg: fgOverride, fgMuted: fgMutedOverride, sectionBg: sectionBgOverride }) {
8
8
  const { dark } = useAutoPaperTheme();
9
- const fg = dark ? "#FFFFFF" : "#000000";
10
- const fgMuted = dark ? "rgba(255,255,255,0.5)" : "rgba(0,0,0,0.5)";
11
- const sectionBg = dark ? "rgba(255,255,255,0.06)" : "rgba(0,0,0,0.04)";
9
+ const fg = fgOverride ?? (dark ? "#FFFFFF" : "#000000");
10
+ const fgMuted = fgMutedOverride ?? (dark ? "rgba(255,255,255,0.5)" : "rgba(0,0,0,0.5)");
11
+ const sectionBg = sectionBgOverride ?? (dark ? "rgba(255,255,255,0.06)" : "rgba(0,0,0,0.04)");
12
12
  const unlocked = unlockedLabel !== void 0;
13
13
  return /* @__PURE__ */ jsxs(View, { style: [styles.row, { backgroundColor: sectionBg }], children: [
14
14
  /* @__PURE__ */ jsx(View, { style: [styles.badge, { backgroundColor: badgeColor }], children: /* @__PURE__ */ jsx(Icon, { source: icon, size: 20, color: unlocked ? "#000000" : fgMuted }) }),
@@ -232,25 +232,25 @@ var styles2 = StyleSheet2.create({
232
232
  sectionLabel: {
233
233
  letterSpacing: 2
234
234
  },
235
- // Negative margin cancels the padding so the icon still lines up with APPEARANCE/SOUND &
236
- // HAPTICS below, while the ripple/hover highlight itself gets room to breathe on both sides
237
- // instead of a flush edge-to-edge slab. overflow: 'hidden' makes sure that highlight actually
238
- // clips to borderRadius instead of drawing as a plain rectangle.
235
+ // Used to carry marginHorizontal: -12 + paddingHorizontal: 12 (netting to the same inset as
236
+ // APPEARANCE/SOUND & HAPTICS below, while giving the ripple/hover highlight room to breathe
237
+ // into the dialog's own gutter beyond that). Removed: this dialog scrolls (Dialog.ScrollArea +
238
+ // ScrollView above), and on web a ScrollView's own content wrapper clips to its own bounds
239
+ // regardless of a child's negative margin - confirmed live, the icon's own rounded-square badge
240
+ // was getting its left edge sliced off by exactly that overhang. No horizontal inset of its own
241
+ // now - it relies purely on the same dialog padding APPEARANCE/every other row already does,
242
+ // which can never overflow because it's never negative.
239
243
  toggleButton: {
240
244
  borderRadius: 12,
241
- marginHorizontal: -12,
242
245
  overflow: "hidden",
243
- paddingHorizontal: 12,
244
246
  paddingVertical: 10
245
247
  },
246
- // Same shape as toggleButton but `flex: 1` instead of its own `marginHorizontal: -12` two of
247
- // these side by side in toggleRow would otherwise both pull inward and collide in the middle.
248
- // toggleRow carries that edge-alignment margin once, for the row as a whole, instead.
248
+ // Same shape as toggleButton, `flex: 1` instead of its own width - two of these side by side in
249
+ // toggleRow share the row's own edge alignment instead of each carrying their own.
249
250
  toggleButtonInRow: {
250
251
  borderRadius: 12,
251
252
  flex: 1,
252
253
  overflow: "hidden",
253
- paddingHorizontal: 12,
254
254
  paddingVertical: 10
255
255
  },
256
256
  toggleContent: {
@@ -261,10 +261,10 @@ var styles2 = StyleSheet2.create({
261
261
  toggleGroup: {
262
262
  gap: 4
263
263
  },
264
+ // No horizontal margin of its own now either - see toggleButton's identical note.
264
265
  toggleRow: {
265
266
  flexDirection: "row",
266
- gap: 4,
267
- marginHorizontal: -12
267
+ gap: 4
268
268
  }
269
269
  });
270
270
 
@@ -275,26 +275,27 @@ import { useState as useState2 } from "react";
275
275
  import { ScrollView as ScrollView2, StyleSheet as StyleSheet3, View as View3 } from "react-native";
276
276
  import { Icon as Icon3, Portal as Portal2, Text as Text3 } from "react-native-paper";
277
277
  import { jsx as jsx3, jsxs as jsxs3 } from "react/jsx-runtime";
278
- function BaseStatsScreen({ rotation = 0, title = "Achievements", onBack, insets, onReset, resetLabel = "Reset All Stats", resetConfirmTitle = "Reset Everything?", resetConfirmBody = "This permanently erases all stats and achievements. This cannot be undone.", children }) {
278
+ function BaseStatsScreen({ rotation = 0, 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, cardBg: cardBgOverride, accentColor: accentColorOverride, children }) {
279
279
  const { dark, colors } = useAutoPaperTheme3();
280
280
  const [confirmResetVisible, setConfirmResetVisible] = useState2(false);
281
281
  const showReset = !!onReset;
282
- const fg = dark ? "#FFFFFF" : "#000000";
283
- const bg = dark ? "#000000" : "#FFFFFF";
284
- const cardBg = dark ? "#111111" : "#F2F2F2";
282
+ const fg = fgOverride ?? (dark ? "#FFFFFF" : "#000000");
283
+ const bg = bgOverride ?? (dark ? "#000000" : "#FFFFFF");
284
+ const cardBg = cardBgOverride ?? (dark ? "#111111" : "#F2F2F2");
285
285
  const cardBorder = dark ? "rgba(255,255,255,0.2)" : "rgba(0,0,0,0.2)";
286
+ const accentColor = accentColorOverride ?? colors.secondary;
286
287
  return /* @__PURE__ */ jsxs3(View3, { style: [styles3.container, { backgroundColor: bg }], children: [
287
288
  /* @__PURE__ */ jsxs3(View3, { style: [styles3.header, { paddingTop: 8 + insets.top, paddingLeft: 8 + insets.left }], children: [
288
289
  /* @__PURE__ */ jsx3(IconButton, { icon: "arrow-left", iconColor: fg, size: 24, onPress: onBack }),
289
- /* @__PURE__ */ jsx3(Text3, { variant: "displaySmall", style: [styles3.title, { color: fg }], children: title })
290
+ /* @__PURE__ */ jsx3(Text3, { variant: titleVariant, style: [styles3.title, { color: fg }], children: title })
290
291
  ] }),
291
292
  /* @__PURE__ */ jsxs3(ScrollView2, { style: styles3.scrollView, contentContainerStyle: [styles3.content, { paddingBottom: 32 + insets.bottom }], showsVerticalScrollIndicator: false, children: [
292
293
  children,
293
- showReset && /* @__PURE__ */ jsx3(Button2, { mode: "outlined", onPress: () => setConfirmResetVisible(true), textColor: colors.secondary, style: styles3.resetButton, children: resetLabel })
294
+ showReset && /* @__PURE__ */ jsx3(Button2, { mode: "contained", onPress: () => setConfirmResetVisible(true), buttonColor: colors.secondary, textColor: colors.onSecondary, style: styles3.resetButton, children: resetLabel })
294
295
  ] }),
295
296
  confirmResetVisible && /* @__PURE__ */ jsx3(Portal2, { children: /* @__PURE__ */ jsx3(View3, { style: [styles3.overlay, rotation % 360 !== 0 && { transform: [{ rotate: `${rotation}deg` }] }], children: /* @__PURE__ */ jsxs3(View3, { style: [styles3.overlayCard, { backgroundColor: cardBg, borderColor: cardBorder }], children: [
296
- /* @__PURE__ */ jsx3(Icon3, { source: "alert-outline", size: 64, color: colors.secondary }),
297
- /* @__PURE__ */ jsx3(Text3, { variant: "headlineLarge", style: [styles3.overlayTitle, { color: colors.secondary }], children: resetConfirmTitle }),
297
+ /* @__PURE__ */ jsx3(Icon3, { source: "alert-outline", size: 64, color: accentColor }),
298
+ /* @__PURE__ */ jsx3(Text3, { variant: "headlineLarge", style: [styles3.overlayTitle, { color: accentColor }], children: resetConfirmTitle }),
298
299
  /* @__PURE__ */ jsx3(Text3, { variant: "bodyLarge", style: [styles3.overlayBody, { color: fg }], children: resetConfirmBody }),
299
300
  /* @__PURE__ */ jsx3(Button2, { mode: "contained", onPress: () => setConfirmResetVisible(false), style: styles3.overlayButton, children: "Cancel" }),
300
301
  /* @__PURE__ */ jsx3(
@@ -368,17 +369,41 @@ var styles3 = StyleSheet3.create({
368
369
  }
369
370
  });
370
371
 
372
+ // src/ContentGutter.tsx
373
+ import { computeContentBounds } from "@tastic/core";
374
+ import { StyleSheet as StyleSheet4, useWindowDimensions, View as View4 } from "react-native";
375
+ import { jsx as jsx4, jsxs as jsxs4 } from "react/jsx-runtime";
376
+ function ContentGutter({ maxContentWidth, leftGutter, rightGutter, style, children }) {
377
+ const { width: windowWidth } = useWindowDimensions();
378
+ const { contentWidth, gutterWidth } = computeContentBounds(windowWidth, maxContentWidth ?? Infinity);
379
+ return /* @__PURE__ */ jsxs4(View4, { style: [styles4.row, style], children: [
380
+ /* @__PURE__ */ jsx4(View4, { style: [styles4.gutter, { width: gutterWidth }], children: leftGutter }),
381
+ /* @__PURE__ */ jsx4(View4, { style: { width: contentWidth }, children }),
382
+ /* @__PURE__ */ jsx4(View4, { style: [styles4.gutter, { width: gutterWidth }], children: rightGutter })
383
+ ] });
384
+ }
385
+ var styles4 = StyleSheet4.create({
386
+ // overflow:'hidden' keeps an oversized leftGutter/rightGutter from bleeding into the content
387
+ // column instead of clipping cleanly at its own real width.
388
+ gutter: {
389
+ overflow: "hidden"
390
+ },
391
+ row: {
392
+ flexDirection: "row"
393
+ }
394
+ });
395
+
371
396
  // src/CornerActionButtons.tsx
372
397
  import { IconButton as IconButton2 } from "@rific/feedback-press";
373
- import { StyleSheet as StyleSheet4 } from "react-native";
374
- import { Fragment as Fragment2, jsx as jsx4, jsxs as jsxs4 } from "react/jsx-runtime";
398
+ import { StyleSheet as StyleSheet5 } from "react-native";
399
+ import { Fragment as Fragment2, jsx as jsx5, jsxs as jsxs5 } from "react/jsx-runtime";
375
400
  function CornerActionButtons({ onBack, onSettings, fg, insets }) {
376
- return /* @__PURE__ */ jsxs4(Fragment2, { children: [
377
- /* @__PURE__ */ jsx4(IconButton2, { icon: "arrow-left", iconColor: fg, size: 24, style: [styles4.back, { top: 8 + insets.top, left: 8 + insets.left }], onPress: onBack, accessibilityLabel: "Back" }),
378
- /* @__PURE__ */ jsx4(IconButton2, { icon: "cog", iconColor: fg, size: 24, style: [styles4.topRight, { top: 8 + insets.top, right: 8 + insets.right }], onPress: onSettings, accessibilityLabel: "Settings" })
401
+ return /* @__PURE__ */ jsxs5(Fragment2, { children: [
402
+ /* @__PURE__ */ jsx5(IconButton2, { icon: "arrow-left", iconColor: fg, size: 24, style: [styles5.back, { top: 8 + insets.top, left: 8 + insets.left }], onPress: onBack, accessibilityLabel: "Back" }),
403
+ /* @__PURE__ */ jsx5(IconButton2, { icon: "cog", iconColor: fg, size: 24, style: [styles5.topRight, { top: 8 + insets.top, right: 8 + insets.right }], onPress: onSettings, accessibilityLabel: "Settings" })
379
404
  ] });
380
405
  }
381
- var styles4 = StyleSheet4.create({
406
+ var styles5 = StyleSheet5.create({
382
407
  back: {
383
408
  position: "absolute"
384
409
  },
@@ -395,34 +420,34 @@ var MONO_FONT = Platform2.select({ ios: "Menlo", android: "monospace", default:
395
420
  import { defaultColors, getContrastColor } from "@rific/auto-paper";
396
421
  import { TouchableRipple as TouchableRipple2 } from "@rific/feedback-press";
397
422
  import { clamp } from "@tastic/core";
398
- import { ScrollView as ScrollView3, StyleSheet as StyleSheet6, useWindowDimensions as useWindowDimensions2, View as View6 } from "react-native";
423
+ import { ScrollView as ScrollView3, StyleSheet as StyleSheet7, useWindowDimensions as useWindowDimensions3, View as View7 } from "react-native";
399
424
  import { Icon as Icon4, Text as Text4 } from "react-native-paper";
400
425
 
401
426
  // src/PopoverBody.tsx
402
- import { StyleSheet as StyleSheet5, View as View4 } from "react-native";
403
- import { Fragment as Fragment3, jsx as jsx5, jsxs as jsxs5 } from "react/jsx-runtime";
427
+ import { StyleSheet as StyleSheet6, View as View5 } from "react-native";
428
+ import { Fragment as Fragment3, jsx as jsx6, jsxs as jsxs6 } from "react/jsx-runtime";
404
429
  var CARET_SIZE = 7;
405
430
  var CARET_RING_OFFSET = 2;
406
431
  var CARET_DIP = 1;
407
432
  function PopoverBody({ visible, children, align = "center", verticalAlign = "below", caretColor, caretBorderColor, caretBorderWidth = 1, triggerSize = 0 }) {
408
433
  if (!visible) return null;
409
434
  const above = verticalAlign === "above";
410
- const alignStyle = align === "left" ? styles5.contentLeft : align === "right" ? styles5.contentRight : styles5.contentCenter;
411
- const verticalStyle = above ? styles5.contentAbove : styles5.contentBelow;
435
+ const alignStyle = align === "left" ? styles6.contentLeft : align === "right" ? styles6.contentRight : styles6.contentCenter;
436
+ const verticalStyle = above ? styles6.contentAbove : styles6.contentBelow;
412
437
  const ringSize = CARET_SIZE + caretBorderWidth;
413
438
  const caretOffset = (halfFootprint) => align === "right" ? { right: triggerSize / 2 - halfFootprint } : { left: triggerSize / 2 - halfFootprint };
414
439
  const caretFill = above ? "borderTopColor" : "borderBottomColor";
415
440
  const caretWidthProp = above ? "borderTopWidth" : "borderBottomWidth";
416
441
  const caretEdge = (size) => above ? { bottom: -size + CARET_DIP } : { top: -size + CARET_DIP };
417
- return /* @__PURE__ */ jsxs5(View4, { style: [styles5.content, alignStyle, verticalStyle], children: [
442
+ return /* @__PURE__ */ jsxs6(View5, { style: [styles6.content, alignStyle, verticalStyle], children: [
418
443
  children,
419
- caretColor && /* @__PURE__ */ jsxs5(Fragment3, { children: [
420
- /* @__PURE__ */ jsx5(View4, { style: [styles5.caret, caretOffset(ringSize), caretEdge(ringSize), { [caretFill]: caretBorderColor ?? caretColor, [caretWidthProp]: ringSize, borderLeftWidth: ringSize, borderRightWidth: ringSize }] }),
421
- /* @__PURE__ */ jsx5(View4, { style: [styles5.caret, caretOffset(CARET_SIZE), caretEdge(CARET_SIZE - CARET_RING_OFFSET), { [caretFill]: caretColor, [caretWidthProp]: CARET_SIZE, borderLeftWidth: CARET_SIZE, borderRightWidth: CARET_SIZE }] })
444
+ caretColor && /* @__PURE__ */ jsxs6(Fragment3, { children: [
445
+ /* @__PURE__ */ jsx6(View5, { style: [styles6.caret, caretOffset(ringSize), caretEdge(ringSize), { [caretFill]: caretBorderColor ?? caretColor, [caretWidthProp]: ringSize, borderLeftWidth: ringSize, borderRightWidth: ringSize }] }),
446
+ /* @__PURE__ */ jsx6(View5, { style: [styles6.caret, caretOffset(CARET_SIZE), caretEdge(CARET_SIZE - CARET_RING_OFFSET), { [caretFill]: caretColor, [caretWidthProp]: CARET_SIZE, borderLeftWidth: CARET_SIZE, borderRightWidth: CARET_SIZE }] })
422
447
  ] })
423
448
  ] });
424
449
  }
425
- var styles5 = StyleSheet5.create({
450
+ var styles6 = StyleSheet6.create({
426
451
  caret: {
427
452
  borderLeftColor: "transparent",
428
453
  borderRightColor: "transparent",
@@ -466,11 +491,11 @@ var styles5 = StyleSheet5.create({
466
491
 
467
492
  // src/useAutoAlign.ts
468
493
  import { useCallback, useEffect, useRef, useState as useState3 } from "react";
469
- import { useWindowDimensions } from "react-native";
494
+ import { useWindowDimensions as useWindowDimensions2 } from "react-native";
470
495
  var EDGE_MARGIN = 12;
471
496
  function useAutoAlign(open, contentWidth, contentHeight) {
472
497
  const triggerRef = useRef(null);
473
- const { width: windowWidth, height: windowHeight } = useWindowDimensions();
498
+ const { width: windowWidth, height: windowHeight } = useWindowDimensions2();
474
499
  const [align, setAlign] = useState3("center");
475
500
  const [verticalAlign, setVerticalAlign] = useState3("below");
476
501
  const [maxHeight, setMaxHeight] = useState3(contentHeight);
@@ -503,7 +528,7 @@ function useAutoAlign(open, contentWidth, contentHeight) {
503
528
  }
504
529
 
505
530
  // src/InlineColorPicker.tsx
506
- import { jsx as jsx6, jsxs as jsxs6 } from "react/jsx-runtime";
531
+ import { jsx as jsx7, jsxs as jsxs7 } from "react/jsx-runtime";
507
532
  var EMOJI_PATTERN = /\p{Extended_Pictographic}/u;
508
533
  var DEFAULT_SIZE = 48;
509
534
  var SWATCH_SIZE = 28;
@@ -516,9 +541,9 @@ var SCREEN_MARGIN = 40;
516
541
  function widthForColumns(columns) {
517
542
  return SWATCHES_BORDER_WIDTH * 2 + SWATCHES_PADDING * 2 + SWATCH_SIZE * columns + SWATCHES_GAP * (columns - 1);
518
543
  }
519
- function InlineColorPicker({ id, host, value, onChange, swatches = defaultColors, takenValue, allowSwapTaken, dark, align: alignOverride, icon = "palette", tag, labelFontFamily = MONO_FONT, autoDismiss = true, columns, size = DEFAULT_SIZE }) {
544
+ function InlineColorPicker({ id, host, value, onChange, previewValue, swatches = defaultColors, takenValue, allowSwapTaken, dark, align: alignOverride, icon = "palette", tag, labelFontFamily = MONO_FONT, autoDismiss = true, columns, size = DEFAULT_SIZE }) {
520
545
  const menuBg = dark ? "#000000" : "#FFFFFF";
521
- const { width: windowWidth } = useWindowDimensions2();
546
+ const { width: windowWidth } = useWindowDimensions3();
522
547
  const autoColumns = clamp(Math.floor((windowWidth - 2 * SCREEN_MARGIN + SWATCHES_GAP) / (SWATCH_SIZE + SWATCHES_GAP)), MIN_COLUMNS, MAX_COLUMNS);
523
548
  const resolvedColumns = columns ?? autoColumns;
524
549
  const swatchesWidth = widthForColumns(resolvedColumns);
@@ -527,15 +552,18 @@ function InlineColorPicker({ id, host, value, onChange, swatches = defaultColors
527
552
  const open = host.openId === id;
528
553
  const { align: autoAlign, maxHeight, measured, triggerRef, verticalAlign } = useAutoAlign(open, swatchesWidth, swatchesHeight);
529
554
  const align = alignOverride ?? autoAlign;
530
- const contrastColor = getContrastColor(value);
555
+ const displayFor = previewValue ?? ((hex) => hex);
556
+ const displayValue = displayFor(value);
557
+ const contrastColor = getContrastColor(displayValue);
531
558
  const tagFontSize = size * (tag && EMOJI_PATTERN.test(tag) ? 0.6 : 0.4);
532
- return /* @__PURE__ */ jsxs6(View6, { style: [styles6.anchor, open && styles6.anchorOpen], children: [
533
- /* @__PURE__ */ jsx6(TouchableRipple2, { onPress: () => host.toggle(id), borderless: true, style: [styles6.trigger, { backgroundColor: value, borderRadius: size / 2, height: size, width: size }], children: /* @__PURE__ */ jsx6(View6, { ref: triggerRef, collapsable: false, style: styles6.triggerMeasure, children: tag ? /* @__PURE__ */ jsx6(Text4, { style: [styles6.tagLabel, { color: contrastColor, fontFamily: labelFontFamily, fontSize: tagFontSize }], numberOfLines: 1, adjustsFontSizeToFit: true, children: tag }) : /* @__PURE__ */ jsx6(Icon4, { source: icon, size: size * 0.6, color: contrastColor }) }) }),
534
- /* @__PURE__ */ jsx6(PopoverBody, { visible: open && measured, align, verticalAlign, caretColor: menuBg, caretBorderColor: value, caretBorderWidth: SWATCHES_BORDER_WIDTH, triggerSize: size, children: /* @__PURE__ */ jsx6(ScrollView3, { style: [styles6.swatches, { backgroundColor: menuBg, borderColor: value, width: swatchesWidth, maxHeight }], contentContainerStyle: styles6.swatchesContent, showsVerticalScrollIndicator: false, children: swatches.map((swatch) => {
559
+ return /* @__PURE__ */ jsxs7(View7, { style: [styles7.anchor, open && styles7.anchorOpen], children: [
560
+ /* @__PURE__ */ jsx7(TouchableRipple2, { onPress: () => host.toggle(id), borderless: true, style: [styles7.trigger, { backgroundColor: displayValue, borderRadius: size / 2, height: size, width: size }], children: /* @__PURE__ */ jsx7(View7, { ref: triggerRef, collapsable: false, style: styles7.triggerMeasure, children: tag ? /* @__PURE__ */ jsx7(Text4, { style: [styles7.tagLabel, { color: contrastColor, fontFamily: labelFontFamily, fontSize: tagFontSize }], numberOfLines: 1, adjustsFontSizeToFit: true, children: tag }) : /* @__PURE__ */ jsx7(Icon4, { source: icon, size: size * 0.6, color: contrastColor }) }) }),
561
+ /* @__PURE__ */ jsx7(PopoverBody, { visible: open && measured, align, verticalAlign, caretColor: menuBg, caretBorderColor: displayValue, caretBorderWidth: SWATCHES_BORDER_WIDTH, triggerSize: size, children: /* @__PURE__ */ jsx7(ScrollView3, { style: [styles7.swatches, { backgroundColor: menuBg, borderColor: displayValue, width: swatchesWidth, maxHeight }], contentContainerStyle: styles7.swatchesContent, showsVerticalScrollIndicator: false, children: swatches.map((swatch) => {
535
562
  const selected = swatch.value.toLowerCase() === value.toLowerCase();
536
563
  const taken = !selected && !!takenValue && swatch.value.toLowerCase() === takenValue.toLowerCase();
537
564
  const swappable = taken && allowSwapTaken;
538
- return /* @__PURE__ */ jsx6(
565
+ const swatchDisplay = displayFor(swatch.value);
566
+ return /* @__PURE__ */ jsx7(
539
567
  TouchableRipple2,
540
568
  {
541
569
  disabled: taken && !swappable,
@@ -544,15 +572,15 @@ function InlineColorPicker({ id, host, value, onChange, swatches = defaultColors
544
572
  if (autoDismiss) host.close();
545
573
  },
546
574
  borderless: true,
547
- style: [styles6.swatch, { backgroundColor: swatch.value }, selected && styles6.swatchSelected, taken && !swappable && styles6.swatchTaken],
548
- children: selected ? /* @__PURE__ */ jsx6(Icon4, { source: "check", size: 16, color: getContrastColor(swatch.value) }) : swappable ? /* @__PURE__ */ jsx6(Icon4, { source: "swap-horizontal", size: 16, color: getContrastColor(swatch.value) }) : taken ? /* @__PURE__ */ jsx6(Icon4, { source: "close", size: 16, color: getContrastColor(swatch.value) }) : /* @__PURE__ */ jsx6(View6, {})
575
+ style: [styles7.swatch, { backgroundColor: swatchDisplay }, selected && styles7.swatchSelected, taken && !swappable && styles7.swatchTaken],
576
+ children: selected ? /* @__PURE__ */ jsx7(Icon4, { source: "check", size: 16, color: getContrastColor(swatchDisplay) }) : swappable ? /* @__PURE__ */ jsx7(Icon4, { source: "swap-horizontal", size: 16, color: getContrastColor(swatchDisplay) }) : taken ? /* @__PURE__ */ jsx7(Icon4, { source: "close", size: 16, color: getContrastColor(swatchDisplay) }) : /* @__PURE__ */ jsx7(View7, {})
549
577
  },
550
578
  swatch.value
551
579
  );
552
580
  }) }) })
553
581
  ] });
554
582
  }
555
- var styles6 = StyleSheet6.create({
583
+ var styles7 = StyleSheet7.create({
556
584
  anchor: {
557
585
  position: "relative"
558
586
  },
@@ -598,6 +626,10 @@ var styles6 = StyleSheet6.create({
598
626
  gap: SWATCHES_GAP,
599
627
  padding: SWATCHES_PADDING
600
628
  },
629
+ tagLabel: {
630
+ fontWeight: "700",
631
+ letterSpacing: 0.5
632
+ },
601
633
  // borderRadius/height/width come from the `size` prop instead (see render-site override) — no
602
634
  // fixed default here, since this style object is shared by every caller regardless of size.
603
635
  trigger: {
@@ -616,19 +648,15 @@ var styles6 = StyleSheet6.create({
616
648
  justifyContent: "center",
617
649
  paddingHorizontal: 4,
618
650
  width: "100%"
619
- },
620
- tagLabel: {
621
- fontWeight: "700",
622
- letterSpacing: 0.5
623
651
  }
624
652
  });
625
653
 
626
654
  // src/LabeledDropdown.tsx
627
655
  import { getContrastColor as getContrastColor2 } from "@rific/auto-paper";
628
656
  import { TouchableRipple as TouchableRipple3 } from "@rific/feedback-press";
629
- import { ScrollView as ScrollView4, StyleSheet as StyleSheet7, View as View7 } from "react-native";
657
+ import { ScrollView as ScrollView4, StyleSheet as StyleSheet8, View as View8 } from "react-native";
630
658
  import { Icon as Icon5, Text as Text5 } from "react-native-paper";
631
- import { jsx as jsx7, jsxs as jsxs7 } from "react/jsx-runtime";
659
+ import { jsx as jsx8, jsxs as jsxs8 } from "react/jsx-runtime";
632
660
  var TRIGGER_HEIGHT = 28;
633
661
  var POPOVER_WIDTH = 180;
634
662
  var ROW_HEIGHT = 36;
@@ -651,22 +679,22 @@ function LabeledDropdown({ id, host, options, value, onChange, color, dark, alig
651
679
  onChange(option.value);
652
680
  host.close();
653
681
  };
654
- return /* @__PURE__ */ jsxs7(View7, { style: [styles7.anchor, open && styles7.anchorOpen], children: [
655
- /* @__PURE__ */ jsx7(TouchableRipple3, { onPress: () => host.toggle(id), style: styles7.trigger, children: /* @__PURE__ */ jsxs7(View7, { ref: triggerRef, collapsable: false, style: styles7.triggerInner, children: [
656
- /* @__PURE__ */ jsx7(Text5, { style: [styles7.triggerLabel, { color }], numberOfLines: 1, children: (selected?.label ?? "").toUpperCase() }),
657
- /* @__PURE__ */ jsx7(Icon5, { source: "menu-down", size: 16, color })
682
+ return /* @__PURE__ */ jsxs8(View8, { style: [styles8.anchor, open && styles8.anchorOpen], children: [
683
+ /* @__PURE__ */ jsx8(TouchableRipple3, { onPress: () => host.toggle(id), style: styles8.trigger, children: /* @__PURE__ */ jsxs8(View8, { ref: triggerRef, collapsable: false, style: styles8.triggerInner, children: [
684
+ /* @__PURE__ */ jsx8(Text5, { style: [styles8.triggerLabel, { color }], numberOfLines: 1, children: (selected?.label ?? "").toUpperCase() }),
685
+ /* @__PURE__ */ jsx8(Icon5, { source: "menu-down", size: 16, color })
658
686
  ] }) }),
659
- /* @__PURE__ */ jsx7(PopoverBody, { visible: open && measured, align, verticalAlign, caretColor: menuBg, caretBorderColor: color, caretBorderWidth: 2, triggerSize: TRIGGER_HEIGHT, children: /* @__PURE__ */ jsx7(ScrollView4, { style: [styles7.menu, { backgroundColor: menuBg, borderColor: color, width: POPOVER_WIDTH, maxHeight }], contentContainerStyle: styles7.menuContent, showsVerticalScrollIndicator: false, children: options.map((option) => {
687
+ /* @__PURE__ */ jsx8(PopoverBody, { visible: open && measured, align, verticalAlign, caretColor: menuBg, caretBorderColor: color, caretBorderWidth: 2, triggerSize: TRIGGER_HEIGHT, children: /* @__PURE__ */ jsx8(ScrollView4, { style: [styles8.menu, { backgroundColor: menuBg, borderColor: color, width: POPOVER_WIDTH, maxHeight }], contentContainerStyle: styles8.menuContent, showsVerticalScrollIndicator: false, children: options.map((option) => {
660
688
  const isSelected = option.value === value;
661
689
  const onColor = getContrastColor2(color);
662
- return /* @__PURE__ */ jsx7(TouchableRipple3, { onPress: () => handleSelect(option), style: [styles7.row, isSelected && { backgroundColor: color }], children: /* @__PURE__ */ jsxs7(View7, { style: styles7.rowInner, children: [
663
- option.icon && /* @__PURE__ */ jsx7(Icon5, { source: option.icon, size: 18, color: isSelected ? onColor : fg }),
664
- /* @__PURE__ */ jsx7(Text5, { style: [styles7.rowLabel, { color: isSelected ? onColor : fg }], numberOfLines: 1, children: option.label })
690
+ return /* @__PURE__ */ jsx8(TouchableRipple3, { onPress: () => handleSelect(option), style: [styles8.row, isSelected && { backgroundColor: color }], children: /* @__PURE__ */ jsxs8(View8, { style: styles8.rowInner, children: [
691
+ option.icon && /* @__PURE__ */ jsx8(Icon5, { source: option.icon, size: 18, color: isSelected ? onColor : fg }),
692
+ /* @__PURE__ */ jsx8(Text5, { style: [styles8.rowLabel, { color: isSelected ? onColor : fg }], numberOfLines: 1, children: option.label })
665
693
  ] }) }, option.value);
666
694
  }) }) })
667
695
  ] });
668
696
  }
669
- var styles7 = StyleSheet7.create({
697
+ var styles8 = StyleSheet8.create({
670
698
  anchor: {
671
699
  position: "relative"
672
700
  },
@@ -724,25 +752,25 @@ function loadSkiaWeb() {
724
752
  }
725
753
 
726
754
  // src/PressAwayOverlay.tsx
727
- import { Pressable, StyleSheet as StyleSheet8 } from "react-native";
728
- import { jsx as jsx8 } from "react/jsx-runtime";
755
+ import { Pressable, StyleSheet as StyleSheet9 } from "react-native";
756
+ import { jsx as jsx9 } from "react/jsx-runtime";
729
757
  function PressAwayOverlay({ active, onPress, style }) {
730
758
  if (!active) return null;
731
- return /* @__PURE__ */ jsx8(Pressable, { accessibilityLabel: "Dismiss", accessibilityRole: "button", onPress, style: [StyleSheet8.absoluteFill, style] });
759
+ return /* @__PURE__ */ jsx9(Pressable, { accessibilityLabel: "Dismiss", accessibilityRole: "button", onPress, style: [StyleSheet9.absoluteFill, style] });
732
760
  }
733
761
 
734
762
  // src/ReadyButton.tsx
735
763
  import { TouchableRipple as TouchableRipple4 } from "@rific/feedback-press";
736
- import { StyleSheet as StyleSheet9 } from "react-native";
764
+ import { StyleSheet as StyleSheet10 } from "react-native";
737
765
  import { Text as Text6 } from "react-native-paper";
738
- import { jsx as jsx9 } from "react/jsx-runtime";
766
+ import { jsx as jsx10 } from "react/jsx-runtime";
739
767
  function ReadyButton({ color, ready, onToggleReady, style, labelFontFamily = MONO_FONT }) {
740
- const readyButtonStyle = [styles8.readyButton, { borderColor: color }, ready && { backgroundColor: color }, style];
768
+ const readyButtonStyle = [styles9.readyButton, { borderColor: color }, ready && { backgroundColor: color }, style];
741
769
  const labelTextStyle = { fontFamily: labelFontFamily, fontWeight: "bold" };
742
770
  const labelColorStyle = { color: ready ? "#000000" : color };
743
- return /* @__PURE__ */ jsx9(TouchableRipple4, { onPress: onToggleReady, borderless: true, style: readyButtonStyle, children: /* @__PURE__ */ jsx9(Text6, { variant: "labelLarge", style: [labelTextStyle, labelColorStyle], children: ready ? "READY \u2713" : "READY?" }) });
771
+ return /* @__PURE__ */ jsx10(TouchableRipple4, { onPress: onToggleReady, borderless: true, style: readyButtonStyle, children: /* @__PURE__ */ jsx10(Text6, { variant: "labelLarge", style: [labelTextStyle, labelColorStyle], children: ready ? "READY \u2713" : "READY?" }) });
744
772
  }
745
- var styles8 = StyleSheet9.create({
773
+ var styles9 = StyleSheet10.create({
746
774
  readyButton: {
747
775
  alignItems: "center",
748
776
  borderRadius: 12,
@@ -757,19 +785,19 @@ var styles8 = StyleSheet9.create({
757
785
  // src/SectionedDropdown.tsx
758
786
  import { getBlendedColor, getColorRoles } from "@rific/auto-paper";
759
787
  import { IconButton as IconButton3, TouchableRipple as TouchableRipple5 } from "@rific/feedback-press";
760
- import { ScrollView as ScrollView5, StyleSheet as StyleSheet10, View as View8 } from "react-native";
788
+ import { ScrollView as ScrollView5, StyleSheet as StyleSheet11, View as View9 } from "react-native";
761
789
  import { Icon as Icon6, Text as Text7 } from "react-native-paper";
762
790
 
763
791
  // src/TriggerGaugeHost.tsx
764
792
  import { lazy, Suspense } from "react";
765
- import { jsx as jsx10 } from "react/jsx-runtime";
793
+ import { jsx as jsx11 } from "react/jsx-runtime";
766
794
  var LazyTriggerGauge = lazy(() => loadSkiaWeb().then(() => import("./TriggerGauge-2OJOOF6I.mjs").then((m) => ({ default: m.TriggerGauge }))));
767
795
  function TriggerGaugeHost(props) {
768
- return /* @__PURE__ */ jsx10(Suspense, { fallback: null, children: /* @__PURE__ */ jsx10(LazyTriggerGauge, { ...props }) });
796
+ return /* @__PURE__ */ jsx11(Suspense, { fallback: null, children: /* @__PURE__ */ jsx11(LazyTriggerGauge, { ...props }) });
769
797
  }
770
798
 
771
799
  // src/SectionedDropdown.tsx
772
- import { Fragment as Fragment4, jsx as jsx11, jsxs as jsxs8 } from "react/jsx-runtime";
800
+ import { Fragment as Fragment4, jsx as jsx12, jsxs as jsxs9 } from "react/jsx-runtime";
773
801
  var MENU_BORDER_WIDTH = 1;
774
802
  var TRIGGER_SIZE = 44;
775
803
  var MENU_MIN_WIDTH = 200;
@@ -815,17 +843,17 @@ function SectionedDropdown({ id, host, icon, accessibilityLabel, sections, accen
815
843
  }
816
844
  gaugeOffset += section.options.length;
817
845
  }
818
- const anchorStyle = [styles9.anchor, open && styles9.anchorOpen];
846
+ const anchorStyle = [styles10.anchor, open && styles10.anchorOpen];
819
847
  const menuStyle = { backgroundColor: menuBg, borderColor: menuBorderColor, maxHeight };
820
848
  const dividerStyle = { backgroundColor: menuBorderColor };
821
- return /* @__PURE__ */ jsxs8(View8, { style: anchorStyle, children: [
822
- /* @__PURE__ */ jsxs8(View8, { ref: triggerRef, collapsable: false, style: styles9.triggerBox, children: [
823
- /* @__PURE__ */ jsx11(TriggerGaugeHost, { segments: gaugeSegments, litIndices: gaugeLitIndices, size: TRIGGER_SIZE, accentColor, mutedColor }),
824
- /* @__PURE__ */ jsx11(IconButton3, { icon: triggerIcon, iconColor: triggerIconColor, size: triggerIconSize, accessibilityLabel, onPress: () => host.toggle(id) })
849
+ return /* @__PURE__ */ jsxs9(View9, { style: anchorStyle, children: [
850
+ /* @__PURE__ */ jsxs9(View9, { ref: triggerRef, collapsable: false, style: styles10.triggerBox, children: [
851
+ /* @__PURE__ */ jsx12(TriggerGaugeHost, { segments: gaugeSegments, litIndices: gaugeLitIndices, size: TRIGGER_SIZE, accentColor, mutedColor }),
852
+ /* @__PURE__ */ jsx12(IconButton3, { icon: triggerIcon, iconColor: triggerIconColor, size: triggerIconSize, accessibilityLabel, onPress: () => host.toggle(id) })
825
853
  ] }),
826
- /* @__PURE__ */ jsx11(PopoverBody, { visible: open && measured, align, verticalAlign, caretColor: menuBg, caretBorderColor: menuBorderColor, caretBorderWidth: MENU_BORDER_WIDTH, triggerSize: TRIGGER_SIZE, children: /* @__PURE__ */ jsx11(ScrollView5, { style: [styles9.menu, menuStyle], contentContainerStyle: styles9.menuContent, showsVerticalScrollIndicator: false, children: sections.map((section, sectionIndex) => /* @__PURE__ */ jsxs8(View8, { children: [
827
- sectionIndex > 0 && /* @__PURE__ */ jsx11(View8, { style: [styles9.divider, dividerStyle] }),
828
- section.kind === "single" ? /* @__PURE__ */ jsx11(
854
+ /* @__PURE__ */ jsx12(PopoverBody, { visible: open && measured, align, verticalAlign, caretColor: menuBg, caretBorderColor: menuBorderColor, caretBorderWidth: MENU_BORDER_WIDTH, triggerSize: TRIGGER_SIZE, children: /* @__PURE__ */ jsx12(ScrollView5, { style: [styles10.menu, menuStyle], contentContainerStyle: styles10.menuContent, showsVerticalScrollIndicator: false, children: sections.map((section, sectionIndex) => /* @__PURE__ */ jsxs9(View9, { children: [
855
+ sectionIndex > 0 && /* @__PURE__ */ jsx12(View9, { style: [styles10.divider, dividerStyle] }),
856
+ section.kind === "single" ? /* @__PURE__ */ jsx12(
829
857
  SingleSection,
830
858
  {
831
859
  section,
@@ -838,7 +866,7 @@ function SectionedDropdown({ id, host, icon, accessibilityLabel, sections, accen
838
866
  if (autoDismiss) host.close();
839
867
  }
840
868
  }
841
- ) : /* @__PURE__ */ jsx11(MultiSection, { section, accentColor, onAccentColor: resolvedOnAccentColor, mutedColor, labelFontFamily, allClearLabels })
869
+ ) : /* @__PURE__ */ jsx12(MultiSection, { section, accentColor, onAccentColor: resolvedOnAccentColor, mutedColor, labelFontFamily, allClearLabels })
842
870
  ] }, section.id)) }) })
843
871
  ] });
844
872
  }
@@ -850,17 +878,18 @@ function SingleSection({
850
878
  labelFontFamily,
851
879
  onSelect
852
880
  }) {
853
- return /* @__PURE__ */ jsx11(Fragment4, { children: section.options.map((option) => {
881
+ return /* @__PURE__ */ jsx12(Fragment4, { children: section.options.map((option) => {
854
882
  const selected = option.value === section.value;
883
+ const taken = !selected && option.value === section.takenValue;
855
884
  const rowColor = selected ? onAccentColor : mutedColor;
856
- const itemStyle = [styles9.item, selected && { backgroundColor: accentColor }];
885
+ const itemStyle = [styles10.item, selected && { backgroundColor: accentColor }, taken && styles10.itemTaken];
857
886
  const labelStyle = { fontFamily: labelFontFamily, color: rowColor, fontWeight: selected ? "bold" : "normal" };
858
887
  const descriptionStyle = { fontFamily: labelFontFamily, color: rowColor };
859
- return /* @__PURE__ */ jsx11(TouchableRipple5, { onPress: () => onSelect(option.value), style: itemStyle, children: /* @__PURE__ */ jsxs8(View8, { style: styles9.itemRow, children: [
860
- option.icon && /* @__PURE__ */ jsx11(Icon6, { source: option.icon, size: MENU_ITEM_ICON_SIZE, color: rowColor }),
861
- /* @__PURE__ */ jsxs8(View8, { style: styles9.itemLabelColumn, children: [
862
- /* @__PURE__ */ jsx11(Text7, { variant: "labelLarge", style: labelStyle, children: option.label }),
863
- option.description && /* @__PURE__ */ jsx11(Text7, { variant: "labelSmall", style: descriptionStyle, children: option.description })
888
+ return /* @__PURE__ */ jsx12(TouchableRipple5, { disabled: taken, onPress: () => onSelect(option.value), style: itemStyle, children: /* @__PURE__ */ jsxs9(View9, { style: styles10.itemRow, children: [
889
+ option.icon && /* @__PURE__ */ jsx12(Icon6, { source: option.icon, size: MENU_ITEM_ICON_SIZE, color: rowColor }),
890
+ /* @__PURE__ */ jsxs9(View9, { style: styles10.itemLabelColumn, children: [
891
+ /* @__PURE__ */ jsx12(Text7, { variant: "labelLarge", style: labelStyle, children: option.label }),
892
+ option.description && /* @__PURE__ */ jsx12(Text7, { variant: "labelSmall", style: descriptionStyle, children: option.description })
864
893
  ] })
865
894
  ] }) }, option.value);
866
895
  }) });
@@ -874,23 +903,23 @@ function MultiSection({
874
903
  allClearLabels
875
904
  }) {
876
905
  const allSelected = section.value.length === section.options.length;
877
- return /* @__PURE__ */ jsxs8(Fragment4, { children: [
906
+ return /* @__PURE__ */ jsxs9(Fragment4, { children: [
878
907
  section.options.map((option, i) => {
879
908
  const selected = section.value.includes(option.value);
880
909
  const rowColor = selected ? onAccentColor : mutedColor;
881
910
  const prevSelected = selected && i > 0 && section.value.includes(section.options[i - 1].value);
882
911
  const nextSelected = selected && i < section.options.length - 1 && section.value.includes(section.options[i + 1].value);
883
- const itemStyle = [styles9.item, selected && { backgroundColor: accentColor }, prevSelected && { borderTopLeftRadius: 0, borderTopRightRadius: 0 }, nextSelected && { borderBottomLeftRadius: 0, borderBottomRightRadius: 0 }];
912
+ const itemStyle = [styles10.item, selected && { backgroundColor: accentColor }, prevSelected && { borderTopLeftRadius: 0, borderTopRightRadius: 0 }, nextSelected && { borderBottomLeftRadius: 0, borderBottomRightRadius: 0 }];
884
913
  const labelStyle = { fontFamily: labelFontFamily, color: rowColor, fontWeight: selected ? "bold" : "normal" };
885
- return /* @__PURE__ */ jsx11(TouchableRipple5, { onPress: () => section.onChange(selected ? section.value.filter((v) => v !== option.value) : [...section.value, option.value]), style: itemStyle, children: /* @__PURE__ */ jsxs8(View8, { style: styles9.itemRow, children: [
886
- option.icon && /* @__PURE__ */ jsx11(Icon6, { source: option.icon, size: MENU_ITEM_ICON_SIZE, color: rowColor }),
887
- /* @__PURE__ */ jsx11(Text7, { variant: "labelLarge", style: [styles9.itemLabelFlex, labelStyle], children: option.label })
914
+ return /* @__PURE__ */ jsx12(TouchableRipple5, { onPress: () => section.onChange(selected ? section.value.filter((v) => v !== option.value) : [...section.value, option.value]), style: itemStyle, children: /* @__PURE__ */ jsxs9(View9, { style: styles10.itemRow, children: [
915
+ option.icon && /* @__PURE__ */ jsx12(Icon6, { source: option.icon, size: MENU_ITEM_ICON_SIZE, color: rowColor }),
916
+ /* @__PURE__ */ jsx12(Text7, { variant: "labelLarge", style: [styles10.itemLabelFlex, labelStyle], children: option.label })
888
917
  ] }) }, option.value);
889
918
  }),
890
- section.allClear && /* @__PURE__ */ jsx11(TouchableRipple5, { onPress: () => section.onChange(allSelected ? [] : section.options.map((o) => o.value)), style: styles9.item, children: /* @__PURE__ */ jsx11(Text7, { variant: "labelLarge", style: [styles9.allClearLabel, { fontFamily: labelFontFamily, color: accentColor }], children: allSelected ? allClearLabels.clear : allClearLabels.all }) })
919
+ section.allClear && /* @__PURE__ */ jsx12(TouchableRipple5, { onPress: () => section.onChange(allSelected ? [] : section.options.map((o) => o.value)), style: styles10.item, children: /* @__PURE__ */ jsx12(Text7, { variant: "labelLarge", style: [styles10.allClearLabel, { fontFamily: labelFontFamily, color: accentColor }], children: allSelected ? allClearLabels.clear : allClearLabels.all }) })
891
920
  ] });
892
921
  }
893
- var styles9 = StyleSheet10.create({
922
+ var styles10 = StyleSheet11.create({
894
923
  allClearLabel: {
895
924
  fontWeight: "bold",
896
925
  textAlign: "center"
@@ -907,7 +936,7 @@ var styles9 = StyleSheet10.create({
907
936
  zIndex: 100
908
937
  },
909
938
  divider: {
910
- height: StyleSheet10.hairlineWidth,
939
+ height: StyleSheet11.hairlineWidth,
911
940
  marginVertical: 4
912
941
  },
913
942
  item: {
@@ -926,6 +955,11 @@ var styles9 = StyleSheet10.create({
926
955
  flexDirection: "row",
927
956
  gap: 8
928
957
  },
958
+ // Same opacity as ProfilePicker's rowDisabled / InlineColorPicker's swatchTaken — the fleet's
959
+ // established "shown, not removed" treatment for another seat's own current pick.
960
+ itemTaken: {
961
+ opacity: 0.35
962
+ },
929
963
  menu: {
930
964
  borderRadius: 12,
931
965
  borderWidth: MENU_BORDER_WIDTH,
@@ -956,20 +990,20 @@ var styles9 = StyleSheet10.create({
956
990
 
957
991
  // src/SharedActionBand.tsx
958
992
  import { IconButton as IconButton4 } from "@rific/feedback-press";
959
- import { StyleSheet as StyleSheet11, View as View9 } from "react-native";
960
- import { jsx as jsx12, jsxs as jsxs9 } from "react/jsx-runtime";
993
+ import { StyleSheet as StyleSheet12, View as View10 } from "react-native";
994
+ import { jsx as jsx13, jsxs as jsxs10 } from "react/jsx-runtime";
961
995
  function SharedActionBand({ onBack, onSettings, onRandomize, onReset, fg, popoverOpen, children }) {
962
- return /* @__PURE__ */ jsxs9(View9, { style: [styles10.column, popoverOpen && styles10.columnOpen], children: [
963
- /* @__PURE__ */ jsxs9(View9, { style: styles10.actionsRow, children: [
964
- /* @__PURE__ */ jsx12(IconButton4, { icon: "arrow-left", iconColor: fg, size: 20, onPress: onBack, accessibilityLabel: "Back" }),
965
- onRandomize && /* @__PURE__ */ jsx12(IconButton4, { icon: "dice-multiple", iconColor: fg, size: 18, onPress: onRandomize, accessibilityLabel: "Randomize match settings" }),
966
- onReset && /* @__PURE__ */ jsx12(IconButton4, { icon: "restore", iconColor: fg, size: 18, onPress: onReset, accessibilityLabel: "Reset match settings to defaults" }),
967
- /* @__PURE__ */ jsx12(IconButton4, { icon: "cog", iconColor: fg, size: 20, onPress: onSettings, accessibilityLabel: "Settings" })
996
+ return /* @__PURE__ */ jsxs10(View10, { style: [styles11.column, popoverOpen && styles11.columnOpen], children: [
997
+ /* @__PURE__ */ jsxs10(View10, { style: styles11.actionsRow, children: [
998
+ /* @__PURE__ */ jsx13(IconButton4, { icon: "arrow-left", iconColor: fg, size: 20, onPress: onBack, accessibilityLabel: "Back" }),
999
+ onRandomize && /* @__PURE__ */ jsx13(IconButton4, { icon: "dice-multiple", iconColor: fg, size: 18, onPress: onRandomize, accessibilityLabel: "Randomize match settings" }),
1000
+ onReset && /* @__PURE__ */ jsx13(IconButton4, { icon: "restore", iconColor: fg, size: 18, onPress: onReset, accessibilityLabel: "Reset match settings to defaults" }),
1001
+ /* @__PURE__ */ jsx13(IconButton4, { icon: "cog", iconColor: fg, size: 20, onPress: onSettings, accessibilityLabel: "Settings" })
968
1002
  ] }),
969
1003
  children
970
1004
  ] });
971
1005
  }
972
- var styles10 = StyleSheet11.create({
1006
+ var styles11 = StyleSheet12.create({
973
1007
  actionsRow: {
974
1008
  alignItems: "center",
975
1009
  flexDirection: "row",
@@ -986,19 +1020,19 @@ var styles10 = StyleSheet11.create({
986
1020
 
987
1021
  // src/StatRow.tsx
988
1022
  import { useAutoPaperTheme as useAutoPaperTheme4 } from "@rific/auto-paper";
989
- import { StyleSheet as StyleSheet12, View as View10 } from "react-native";
1023
+ import { StyleSheet as StyleSheet13, View as View11 } from "react-native";
990
1024
  import { Text as Text8 } from "react-native-paper";
991
- import { jsx as jsx13, jsxs as jsxs10 } from "react/jsx-runtime";
992
- function StatRow({ label, value }) {
1025
+ import { jsx as jsx14, jsxs as jsxs11 } from "react/jsx-runtime";
1026
+ function StatRow({ label, value, fg: fgOverride, fgMuted: fgMutedOverride }) {
993
1027
  const { dark } = useAutoPaperTheme4();
994
- const fg = dark ? "#FFFFFF" : "#000000";
995
- const fgMuted = dark ? "rgba(255,255,255,0.5)" : "rgba(0,0,0,0.5)";
996
- return /* @__PURE__ */ jsxs10(View10, { style: styles11.row, children: [
997
- /* @__PURE__ */ jsx13(Text8, { variant: "bodyMedium", style: { color: fgMuted }, children: label }),
998
- /* @__PURE__ */ jsx13(Text8, { variant: "bodyMedium", style: [styles11.value, { color: fg }], children: value })
1028
+ const fg = fgOverride ?? (dark ? "#FFFFFF" : "#000000");
1029
+ const fgMuted = fgMutedOverride ?? (dark ? "rgba(255,255,255,0.5)" : "rgba(0,0,0,0.5)");
1030
+ return /* @__PURE__ */ jsxs11(View11, { style: styles12.row, children: [
1031
+ /* @__PURE__ */ jsx14(Text8, { variant: "bodyMedium", style: { color: fgMuted }, children: label }),
1032
+ /* @__PURE__ */ jsx14(Text8, { variant: "bodyMedium", style: [styles12.value, { color: fg }], children: value })
999
1033
  ] });
1000
1034
  }
1001
- var styles11 = StyleSheet12.create({
1035
+ var styles12 = StyleSheet13.create({
1002
1036
  row: {
1003
1037
  alignItems: "center",
1004
1038
  flexDirection: "row",
@@ -1011,20 +1045,25 @@ var styles11 = StyleSheet12.create({
1011
1045
 
1012
1046
  // src/StatSection.tsx
1013
1047
  import { useAutoPaperTheme as useAutoPaperTheme5 } from "@rific/auto-paper";
1014
- import { StyleSheet as StyleSheet13, View as View11 } from "react-native";
1048
+ import { StyleSheet as StyleSheet14, View as View12 } from "react-native";
1015
1049
  import { Text as Text9 } from "react-native-paper";
1016
- import { jsx as jsx14, jsxs as jsxs11 } from "react/jsx-runtime";
1017
- function StatSection({ label, children }) {
1050
+ import { jsx as jsx15, jsxs as jsxs12 } from "react/jsx-runtime";
1051
+ function StatSection({ label, fg: fgOverride, sectionBg: sectionBgOverride, children }) {
1018
1052
  const { dark } = useAutoPaperTheme5();
1019
- const fgMuted = dark ? "rgba(255,255,255,0.5)" : "rgba(0,0,0,0.5)";
1020
- const sectionBg = dark ? "rgba(255,255,255,0.06)" : "rgba(0,0,0,0.04)";
1021
- return /* @__PURE__ */ jsxs11(View11, { style: [styles12.section, { backgroundColor: sectionBg }], children: [
1022
- /* @__PURE__ */ jsx14(Text9, { variant: "labelMedium", style: [styles12.label, { color: fgMuted }], children: label }),
1053
+ const fg = fgOverride ?? (dark ? "#FFFFFF" : "#000000");
1054
+ const sectionBg = sectionBgOverride ?? (dark ? "rgba(255,255,255,0.06)" : "rgba(0,0,0,0.04)");
1055
+ return /* @__PURE__ */ jsxs12(View12, { style: [styles13.section, { backgroundColor: sectionBg }], children: [
1056
+ /* @__PURE__ */ jsx15(Text9, { variant: "labelMedium", style: [styles13.label, { color: fg }], children: label }),
1023
1057
  children
1024
1058
  ] });
1025
1059
  }
1026
- var styles12 = StyleSheet13.create({
1060
+ var styles13 = StyleSheet14.create({
1061
+ // Bold and full-contrast (fg), not the original fontless/fgMuted treatment — that read at the
1062
+ // same visual weight as StatRow's own row labels below it (both used the identical muted color;
1063
+ // letterSpacing/variant alone didn't separate them enough to read as "this is the group header"
1064
+ // at a glance). Matches AchievementRow's own title styling (bold + fg) below it in the same list.
1027
1065
  label: {
1066
+ fontWeight: "bold",
1028
1067
  letterSpacing: 2
1029
1068
  },
1030
1069
  section: {
@@ -1048,6 +1087,7 @@ export {
1048
1087
  AchievementRow,
1049
1088
  BaseSettingsDialog,
1050
1089
  BaseStatsScreen,
1090
+ ContentGutter,
1051
1091
  CornerActionButtons,
1052
1092
  InlineColorPicker,
1053
1093
  LABELED_DROPDOWN_POPOVER_WIDTH,