@tastic/hud 0.19.0 → 0.21.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
@@ -38,22 +38,22 @@ __export(TriggerGauge_exports, {
38
38
  function TriggerGauge({ segments, litIndices, size, accentColor, mutedColor, dashWidth, startDeg = DEFAULT_START_DEG, endDeg = startDeg }) {
39
39
  const totalDurationMs = MOUNT_DURATION_MS + Math.max(0, segments - 1) * MOUNT_STAGGER_MS;
40
40
  const mountProgress = (0, import_react_native_reanimated.useSharedValue)(0);
41
- (0, import_react8.useLayoutEffect)(() => {
41
+ (0, import_react9.useLayoutEffect)(() => {
42
42
  mountProgress.value = (0, import_react_native_reanimated.withTiming)(1, { duration: totalDurationMs, easing: import_react_native_reanimated.Easing.out(import_react_native_reanimated.Easing.cubic) });
43
43
  }, []);
44
44
  const rawSweepDeg = ((endDeg - startDeg) % 360 + 360) % 360;
45
45
  const totalSweepDeg = rawSweepDeg === 0 ? 360 : rawSweepDeg;
46
46
  const step = segments > 0 ? totalSweepDeg / segments : 0;
47
- const centerDeg = (0, import_react8.useCallback)((i) => startDeg + (i + 0.5) * step, [startDeg, step]);
47
+ const centerDeg = (0, import_react9.useCallback)((i) => startDeg + (i + 0.5) * step, [startDeg, step]);
48
48
  const singleSelect = litIndices.length === 1;
49
49
  const angleDeg = (0, import_react_native_reanimated.useSharedValue)(centerDeg(litIndices[0] ?? 0));
50
50
  const litIndicesKey = [...litIndices].sort((a, b) => a - b).join(",");
51
- const [transitionFrom, setTransitionFrom] = (0, import_react8.useState)(litIndices);
51
+ const [transitionFrom, setTransitionFrom] = (0, import_react9.useState)(litIndices);
52
52
  const transitionFromKey = [...transitionFrom].sort((a, b) => a - b).join(",");
53
- const lastKeyRef = (0, import_react8.useRef)(litIndicesKey);
54
- const lastIndicesRef = (0, import_react8.useRef)(litIndices);
53
+ const lastKeyRef = (0, import_react9.useRef)(litIndicesKey);
54
+ const lastIndicesRef = (0, import_react9.useRef)(litIndices);
55
55
  const selectionProgress = (0, import_react_native_reanimated.useSharedValue)(1);
56
- (0, import_react8.useLayoutEffect)(() => {
56
+ (0, import_react9.useLayoutEffect)(() => {
57
57
  if (litIndicesKey !== lastKeyRef.current) {
58
58
  if (singleSelect && lastIndicesRef.current.length === 1) {
59
59
  angleDeg.value = (0, import_react_native_reanimated.withTiming)(centerDeg(litIndices[0]), { duration: SELECTION_TRANSITION_DURATION_MS, easing: import_react_native_reanimated.Easing.out(import_react_native_reanimated.Easing.cubic) });
@@ -135,13 +135,13 @@ function TriggerGauge({ segments, litIndices, size, accentColor, mutedColor, das
135
135
  /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(import_react_native_skia.Path, { path: litPath, style: "stroke", strokeWidth: LIT_THICKNESS, strokeCap: "round", color: accentColor, opacity: 1 })
136
136
  ] }) });
137
137
  }
138
- var import_react_native_skia, import_core7, import_react8, import_react_native17, import_react_native_reanimated, import_jsx_runtime16, UNLIT_THICKNESS, LIT_THICKNESS, DASH_GAP_PX, ARC_GAP, DEFAULT_START_DEG, MIN_DASH_ANGLE_DEG, MOUNT_DURATION_MS, MOUNT_STAGGER_MS, SELECTION_TRANSITION_DURATION_MS, styles14;
138
+ var import_react_native_skia, import_core7, import_react9, import_react_native17, import_react_native_reanimated, import_jsx_runtime16, UNLIT_THICKNESS, LIT_THICKNESS, DASH_GAP_PX, ARC_GAP, DEFAULT_START_DEG, MIN_DASH_ANGLE_DEG, MOUNT_DURATION_MS, MOUNT_STAGGER_MS, SELECTION_TRANSITION_DURATION_MS, styles14;
139
139
  var init_TriggerGauge = __esm({
140
140
  "src/TriggerGauge.tsx"() {
141
141
  "use strict";
142
142
  import_react_native_skia = require("@shopify/react-native-skia");
143
143
  import_core7 = require("@tastic/core");
144
- import_react8 = require("react");
144
+ import_react9 = require("react");
145
145
  import_react_native17 = require("react-native");
146
146
  import_react_native_reanimated = require("react-native-reanimated");
147
147
  import_jsx_runtime16 = require("react/jsx-runtime");
@@ -204,6 +204,7 @@ __export(index_exports, {
204
204
  getCpuDifficultyPopoverId: () => getCpuDifficultyPopoverId,
205
205
  getInlineColorPickerContentSize: () => getInlineColorPickerContentSize,
206
206
  getLabeledDropdownContentHeight: () => getLabeledDropdownContentHeight,
207
+ getProfilePopoverId: () => getProfilePopoverId,
207
208
  getStaggeredWordDuration: () => getStaggeredWordDuration,
208
209
  isCompactDialogHeight: () => isCompactDialogHeight,
209
210
  loadSkiaWeb: () => loadSkiaWeb,
@@ -301,9 +302,10 @@ var import_jsx_runtime2 = require("react/jsx-runtime");
301
302
  function AchievementCatalogSection({ rows, label = "ALL ACHIEVEMENTS", fg, fgMuted: fgMutedOverride }) {
302
303
  const { dark } = (0, import_auto_paper2.useAutoPaperTheme)();
303
304
  const fgMuted = fgMutedOverride ?? (dark ? "rgba(255,255,255,0.5)" : "rgba(0,0,0,0.5)");
305
+ const tierAccent = (tierColor) => dark ? tierColor : (0, import_auto_paper2.getBlendedColor)("#000000", tierColor, 0.5);
304
306
  return /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(import_react.Fragment, { children: [
305
307
  /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_react_native_paper2.Text, { variant: "labelMedium", style: [styles2.label, { color: fgMuted, fontFamily: MONO_FONT }], children: label }),
306
- 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: row.tierColor, unlockedLabel: row.unlockedLabel, progress: row.progress, deviceMarker: row.deviceMarker, fg, fgMuted: fgMutedOverride }, row.id))
308
+ 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))
307
309
  ] });
308
310
  }
309
311
  var styles2 = import_react_native3.StyleSheet.create({
@@ -427,7 +429,7 @@ var import_auto_paper9 = require("@rific/auto-paper");
427
429
  var import_feedback_press2 = require("@rific/feedback-press");
428
430
  var import_updater = require("@rific/updater");
429
431
  var import_core4 = require("@tastic/core");
430
- var import_react5 = require("react");
432
+ var import_react6 = require("react");
431
433
  var import_react_native13 = require("react-native");
432
434
  var import_react_native_paper9 = require("react-native-paper");
433
435
  var import_react_native_safe_area_context2 = require("react-native-safe-area-context");
@@ -436,6 +438,7 @@ var import_react_native_safe_area_context2 = require("react-native-safe-area-con
436
438
  var import_auto_paper8 = require("@rific/auto-paper");
437
439
  var import_feedback_press = require("@rific/feedback-press");
438
440
  var import_core2 = require("@tastic/core");
441
+ var import_react3 = require("react");
439
442
  var import_react_native11 = require("react-native");
440
443
  var import_react_native_paper7 = require("react-native-paper");
441
444
 
@@ -589,6 +592,18 @@ function ConfirmDialog({ visible, title, message, confirmLabel, cancelLabel, onC
589
592
  const { colors } = (0, import_auto_paper8.useAutoPaperTheme)();
590
593
  const { fg } = useOverlayCardColors();
591
594
  const { compact, onLayout } = useCompactDialog(rotation);
595
+ const onCancelRef = (0, import_react3.useRef)(onCancel);
596
+ (0, import_react3.useEffect)(() => {
597
+ onCancelRef.current = onCancel;
598
+ });
599
+ (0, import_react3.useEffect)(() => {
600
+ if (!visible) return;
601
+ const subscription = import_react_native11.BackHandler.addEventListener("hardwareBackPress", () => {
602
+ onCancelRef.current?.();
603
+ return true;
604
+ });
605
+ return () => subscription.remove();
606
+ }, [visible]);
592
607
  if (!visible) return null;
593
608
  const accent = destructive ? colors.danger : colors.primary;
594
609
  const onAccent = destructive ? colors.onDanger : colors.onPrimary;
@@ -625,7 +640,7 @@ var styles8 = import_react_native11.StyleSheet.create({
625
640
 
626
641
  // src/RotatedFrame.tsx
627
642
  var import_core3 = require("@tastic/core");
628
- var import_react3 = require("react");
643
+ var import_react4 = require("react");
629
644
  var import_react_native12 = require("react-native");
630
645
  var import_react_native_paper8 = require("react-native-paper");
631
646
  var import_react_native_safe_area_context = require("react-native-safe-area-context");
@@ -636,7 +651,7 @@ function RotatedFrame({ children, rotation: rotationOverride, rotatedSafeArea =
636
651
  const window = (0, import_react_native12.useWindowDimensions)();
637
652
  const { width, height } = (0, import_core3.rotateDimensions)(window.width, window.height, rotation);
638
653
  const rawInsets = (0, import_react_native_safe_area_context.useSafeAreaInsets)();
639
- const insets = (0, import_react3.useMemo)(() => rotatedSafeArea ? (0, import_core3.rotateInsets)(rawInsets, rotation) : rawInsets, [rotatedSafeArea, rawInsets, rotation]);
654
+ const insets = (0, import_react4.useMemo)(() => rotatedSafeArea ? (0, import_core3.rotateInsets)(rawInsets, rotation) : rawInsets, [rotatedSafeArea, rawInsets, rotation]);
640
655
  const cappedWidth = maxContentWidth !== void 0 && width > height ? maxContentWidth : void 0;
641
656
  const column = /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(import_react_native12.View, { style: [styles9.column, cappedWidth !== void 0 && { maxWidth: cappedWidth }], pointerEvents: passThrough ? "box-none" : void 0, children });
642
657
  return /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(import_core3.FakeLandscapeView, { rotation, passThrough, style: styles9.root, children: /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(import_react_native_safe_area_context.SafeAreaInsetsContext.Provider, { value: insets, children: portalHost ? /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(import_react_native_paper8.Portal.Host, { children: column }) : column }) });
@@ -654,18 +669,18 @@ var styles9 = import_react_native12.StyleSheet.create({
654
669
  });
655
670
 
656
671
  // src/useUpdateConfirmBridge.ts
657
- var import_react4 = require("react");
672
+ var import_react5 = require("react");
658
673
  function useUpdateConfirmBridge() {
659
- const [manifest, setManifest] = (0, import_react4.useState)(null);
660
- const resolveRef = (0, import_react4.useRef)(null);
661
- const onConfirm = (0, import_react4.useCallback)(
674
+ const [manifest, setManifest] = (0, import_react5.useState)(null);
675
+ const resolveRef = (0, import_react5.useRef)(null);
676
+ const onConfirm = (0, import_react5.useCallback)(
662
677
  (next) => new Promise((resolve) => {
663
678
  resolveRef.current = resolve;
664
679
  setManifest(next);
665
680
  }),
666
681
  []
667
682
  );
668
- const respond = (0, import_react4.useCallback)((confirmed) => {
683
+ const respond = (0, import_react5.useCallback)((confirmed) => {
669
684
  setManifest(null);
670
685
  resolveRef.current?.(confirmed);
671
686
  resolveRef.current = null;
@@ -690,11 +705,11 @@ function BaseSettingsDialog({ visible, onDismiss, rotation: rotationOverride, ve
690
705
  const isTouchPrimary = (0, import_core4.useIsTouchPrimaryDevice)();
691
706
  const { settings: hapticSettings, set: setHapticSettings } = (0, import_feedback_press2.useHapticSettings)();
692
707
  const { settings: soundSettings, set: setSoundSettings } = (0, import_feedback_press2.useSoundSettings)();
693
- const sound = (0, import_react5.useContext)(import_feedback_press2.SoundContext);
708
+ const sound = (0, import_react6.useContext)(import_feedback_press2.SoundContext);
694
709
  const { forceShort: forceHapticFeedback } = (0, import_feedback_press2.useVibration)();
695
710
  const { settings: themeSettings, set: setThemeSettings } = (0, import_auto_paper9.useThemeSettings)();
696
711
  const expoBlur = (0, import_auto_paper9.useBlurModule)();
697
- const [infoMessage, setInfoMessage] = (0, import_react5.useState)(null);
712
+ const [infoMessage, setInfoMessage] = (0, import_react6.useState)(null);
698
713
  const { manifest: updateManifest, onConfirm: onUpdateConfirm, respond: respondToUpdateConfirm } = useUpdateConfirmBridge();
699
714
  const { check, checking, updateReady } = (0, import_updater.useUpdater)({
700
715
  autoCheck: false,
@@ -704,7 +719,7 @@ function BaseSettingsDialog({ visible, onDismiss, rotation: rotationOverride, ve
704
719
  onInfo: (title, message) => setInfoMessage({ title, message })
705
720
  });
706
721
  const updateManifestDate = updateManifest ? new Date(updateManifest.createdAt) : null;
707
- const [opened, setOpened] = (0, import_react5.useState)(visible);
722
+ const [opened, setOpened] = (0, import_react6.useState)(visible);
708
723
  if (visible && !opened) setOpened(true);
709
724
  const showLockOrientation = isTouchPrimary && lockOrientation !== void 0 && onLockOrientationChange !== void 0;
710
725
  const showEdgeGuard = import_react_native13.Platform.OS === "ios" && deferBottomEdgeGestures !== void 0 && onDeferBottomEdgeGestures !== void 0;
@@ -822,7 +837,7 @@ function BaseSettingsDialog({ visible, onDismiss, rotation: rotationOverride, ve
822
837
  /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(import_react_native13.View, { style: [overlayActionStyles.actions, styles10.footer], children: /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(import_feedback_press2.Button, { mode: "contained", onPress: onDismiss, style: overlayActionStyles.actionButtonSingle, buttonColor: colors.primary, textColor: colors.onPrimary, children: "Done" }) })
823
838
  ] }),
824
839
  /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(ConfirmDialog, { visible: !!updateManifest, title: "Update Available", message: updateManifestDate ? `Released ${updateManifestDate.toLocaleDateString()} at ${updateManifestDate.toLocaleTimeString()}` : "", confirmLabel: "Restart", cancelLabel: "Later", icon: "update", rotation: 0, onConfirm: () => respondToUpdateConfirm(true), onCancel: () => respondToUpdateConfirm(false) }),
825
- /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(ConfirmDialog, { visible: !!infoMessage, title: infoMessage?.title ?? "", message: infoMessage?.message ?? "", confirmLabel: "OK", icon: "information-outline", rotation: 0, onConfirm: () => setInfoMessage(null) })
840
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(ConfirmDialog, { visible: !!infoMessage, title: infoMessage?.title ?? "", message: infoMessage?.message ?? "", confirmLabel: "OK", icon: "information-outline", rotation: 0, onConfirm: () => setInfoMessage(null), onCancel: () => setInfoMessage(null) })
826
841
  ] }) });
827
842
  }
828
843
  var SHEET_GUTTER = 24;
@@ -913,24 +928,24 @@ var styles10 = import_react_native13.StyleSheet.create({
913
928
  var import_auto_paper10 = require("@rific/auto-paper");
914
929
  var import_feedback_press3 = require("@rific/feedback-press");
915
930
  var import_core5 = require("@tastic/core");
916
- var import_react6 = require("react");
931
+ var import_react7 = require("react");
917
932
  var import_react_native14 = require("react-native");
918
933
  var import_react_native_paper10 = require("react-native-paper");
919
934
  var import_jsx_runtime12 = require("react/jsx-runtime");
920
- function BaseStatsScreen({ rotation: rotationOverride, title = "Achievements", titleVariant = "headlineSmall", onBack, insets, onReset, resetLabel = "Reset All Stats", resetConfirmTitle = "Reset Everything?", resetConfirmBody = "This permanently erases all stats and achievements. This cannot be undone.", fg: fgOverride, bg: bgOverride, children }) {
935
+ 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 }) {
921
936
  const { dark, colors } = (0, import_auto_paper10.useAutoPaperTheme)();
922
937
  const ambientRotation = (0, import_core5.useRotation)();
923
938
  const rotation = rotationOverride ?? ambientRotation;
924
- const [confirmResetVisible, setConfirmResetVisible] = (0, import_react6.useState)(false);
939
+ const [confirmResetVisible, setConfirmResetVisible] = (0, import_react7.useState)(false);
925
940
  const showReset = !!onReset;
926
941
  const fg = fgOverride ?? (dark ? "#FFFFFF" : "#000000");
927
942
  const bg = bgOverride ?? (dark ? "#000000" : "#FFFFFF");
928
943
  return /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)(import_react_native14.View, { style: [styles11.container, { backgroundColor: bg }], children: [
929
944
  /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)(import_react_native14.View, { style: [styles11.header, { paddingTop: 8 + insets.top, paddingLeft: 8 + insets.left }], children: [
930
- /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(import_feedback_press3.IconButton, { icon: "arrow-left", iconColor: fg, size: 24, onPress: onBack }),
945
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(import_feedback_press3.IconButton, { icon: "arrow-left", iconColor: fg, size: 24, hitSlop, onPress: onBack, accessibilityLabel: backLabel }),
931
946
  /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(import_react_native_paper10.Text, { variant: titleVariant, style: [styles11.title, { color: fg }], children: title })
932
947
  ] }),
933
- /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)(import_react_native14.ScrollView, { style: styles11.scrollView, contentContainerStyle: [styles11.content, { paddingBottom: 32 + insets.bottom }], showsVerticalScrollIndicator: false, children: [
948
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)(import_auto_paper10.FadingScrollView, { style: styles11.scrollView, contentContainerStyle: [styles11.content, { paddingBottom: 32 + insets.bottom }], showsVerticalScrollIndicator: false, children: [
934
949
  children,
935
950
  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 })
936
951
  ] }),
@@ -971,7 +986,7 @@ var styles11 = import_react_native14.StyleSheet.create({
971
986
  resetButton: {
972
987
  marginTop: 16
973
988
  },
974
- // Bounds the ScrollView to the space `container`'s flex:1 actually gives it - without this, a
989
+ // Bounds the scroller (FadingScrollView puts it on its outer box) to the space `container`'s flex:1 actually gives it - without this, a
975
990
  // ScrollView with only a contentContainerStyle isn't reliably height-constrained on native (it
976
991
  // can render at its full unclipped content height instead of the screen's), which leaves the
977
992
  // header's back button touch target unreliable underneath it.
@@ -1086,11 +1101,11 @@ var styles13 = import_react_native16.StyleSheet.create({
1086
1101
  });
1087
1102
 
1088
1103
  // src/SkiaGate.tsx
1089
- var import_react7 = require("react");
1104
+ var import_react8 = require("react");
1090
1105
  var import_jsx_runtime15 = require("react/jsx-runtime");
1091
1106
  function SkiaGate({ getComponent, componentProps, fallback = null }) {
1092
- const [Component, setComponent] = (0, import_react7.useState)(null);
1093
- (0, import_react7.useEffect)(() => {
1107
+ const [Component, setComponent] = (0, import_react8.useState)(null);
1108
+ (0, import_react8.useEffect)(() => {
1094
1109
  let cancelled = false;
1095
1110
  getComponent().then((mod) => {
1096
1111
  if (!cancelled) setComponent(() => mod.default);
@@ -1111,7 +1126,7 @@ function TriggerGaugeHost(props) {
1111
1126
  }
1112
1127
 
1113
1128
  // src/useAutoAlign.ts
1114
- var import_react9 = require("react");
1129
+ var import_react10 = require("react");
1115
1130
  var import_react_native18 = require("react-native");
1116
1131
  var EDGE_MARGIN = 12;
1117
1132
  function rotateRect(x, y, width, height, rotation, windowWidth, windowHeight) {
@@ -1124,18 +1139,18 @@ function rotateRect(x, y, width, height, rotation, windowWidth, windowHeight) {
1124
1139
  return { x: cx + newDx - newWidth / 2, y: cy + newDy - newHeight / 2, width: newWidth, height: newHeight };
1125
1140
  }
1126
1141
  function useAutoAlign(open, contentWidth, contentHeight, rotation = 0) {
1127
- const triggerRef = (0, import_react9.useRef)(null);
1142
+ const triggerRef = (0, import_react10.useRef)(null);
1128
1143
  const { width: windowWidth, height: windowHeight } = (0, import_react_native18.useWindowDimensions)();
1129
- const [align, setAlign] = (0, import_react9.useState)("center");
1130
- const [verticalAlign, setVerticalAlign] = (0, import_react9.useState)("below");
1131
- const [maxHeight, setMaxHeight] = (0, import_react9.useState)(contentHeight);
1132
- const [measured, setMeasured] = (0, import_react9.useState)(false);
1133
- const [prevOpen, setPrevOpen] = (0, import_react9.useState)(open);
1144
+ const [align, setAlign] = (0, import_react10.useState)("center");
1145
+ const [verticalAlign, setVerticalAlign] = (0, import_react10.useState)("below");
1146
+ const [maxHeight, setMaxHeight] = (0, import_react10.useState)(contentHeight);
1147
+ const [measured, setMeasured] = (0, import_react10.useState)(false);
1148
+ const [prevOpen, setPrevOpen] = (0, import_react10.useState)(open);
1134
1149
  if (open !== prevOpen) {
1135
1150
  setPrevOpen(open);
1136
1151
  if (open) setMeasured(false);
1137
1152
  }
1138
- const measure = (0, import_react9.useCallback)(() => {
1153
+ const measure = (0, import_react10.useCallback)(() => {
1139
1154
  triggerRef.current?.measureInWindow((rawX, rawY, rawWidth, rawHeight) => {
1140
1155
  const { x, y, width: triggerWidth, height: triggerHeight } = rotateRect(rawX, rawY, rawWidth, rawHeight, rotation, windowWidth, windowHeight);
1141
1156
  const centerX = x + triggerWidth / 2;
@@ -1152,7 +1167,7 @@ function useAutoAlign(open, contentWidth, contentHeight, rotation = 0) {
1152
1167
  setMeasured(true);
1153
1168
  });
1154
1169
  }, [contentWidth, contentHeight, windowWidth, windowHeight, rotation]);
1155
- (0, import_react9.useEffect)(() => {
1170
+ (0, import_react10.useEffect)(() => {
1156
1171
  if (open) measure();
1157
1172
  }, [open, measure]);
1158
1173
  return { align, maxHeight, measured, triggerRef, verticalAlign };
@@ -1654,7 +1669,7 @@ function loadSkiaWeb() {
1654
1669
 
1655
1670
  // src/PlayerSetupPanel.tsx
1656
1671
  var import_profile2 = require("@tastic/profile");
1657
- var import_react_native26 = require("react-native");
1672
+ var import_react_native27 = require("react-native");
1658
1673
  var import_react_native_paper16 = require("react-native-paper");
1659
1674
 
1660
1675
  // src/ReadyButton.tsx
@@ -1681,42 +1696,89 @@ var styles20 = import_react_native25.StyleSheet.create({
1681
1696
  });
1682
1697
 
1683
1698
  // src/usePopoverHost.ts
1684
- var import_react10 = require("react");
1699
+ var import_react11 = require("react");
1685
1700
  function usePopoverHost() {
1686
- const [openId, setOpenId] = (0, import_react10.useState)(null);
1687
- const toggle = (0, import_react10.useCallback)((id) => {
1701
+ const [openId, setOpenId] = (0, import_react11.useState)(null);
1702
+ const toggle = (0, import_react11.useCallback)((id) => {
1688
1703
  setOpenId((prev) => prev === id ? null : id);
1689
1704
  }, []);
1690
- const close = (0, import_react10.useCallback)(() => setOpenId(null), []);
1705
+ const close = (0, import_react11.useCallback)(() => setOpenId(null), []);
1691
1706
  return { openId, toggle, close };
1692
1707
  }
1693
1708
 
1709
+ // src/useZoneClampedAlign.ts
1710
+ var import_split_screen = require("@tastic/split-screen");
1711
+ var import_react12 = require("react");
1712
+ var import_react_native26 = require("react-native");
1713
+ var import_react_native_safe_area_context3 = require("react-native-safe-area-context");
1714
+ var EDGE_MARGIN2 = 12;
1715
+ function useZoneClampedAlign(open, contentWidth, contentHeight, rotation = 0) {
1716
+ const auto = useAutoAlign(open, contentWidth, contentHeight, rotation);
1717
+ const zone = (0, import_split_screen.useZoneBounds)();
1718
+ const { height: windowHeight } = (0, import_react_native26.useWindowDimensions)();
1719
+ const insets = (0, import_react_native_safe_area_context3.useSafeAreaInsets)();
1720
+ const shouldMeasure = open && auto.measured && zone !== null;
1721
+ const [ownBounds, setOwnBounds] = (0, import_react12.useState)(null);
1722
+ const [prevShouldMeasure, setPrevShouldMeasure] = (0, import_react12.useState)(shouldMeasure);
1723
+ if (shouldMeasure !== prevShouldMeasure) {
1724
+ setPrevShouldMeasure(shouldMeasure);
1725
+ setOwnBounds(null);
1726
+ }
1727
+ (0, import_react12.useEffect)(() => {
1728
+ if (!shouldMeasure) return;
1729
+ auto.triggerRef.current?.measureInWindow((_x, y, _width, height) => {
1730
+ const belowShared = zone.zoneSide === "belowShared";
1731
+ const awayRoom = belowShared ? windowHeight - insets.bottom - (y + height) - EDGE_MARGIN2 : y - insets.top - EDGE_MARGIN2;
1732
+ const towardRoom = belowShared ? y - zone.sharedEdgeY - EDGE_MARGIN2 : zone.sharedEdgeY - (y + height) - EDGE_MARGIN2;
1733
+ const useToward = contentHeight > awayRoom && towardRoom > awayRoom;
1734
+ let awaySide = belowShared ? "below" : "above";
1735
+ let towardSide = belowShared ? "above" : "below";
1736
+ if (zone.rotated) {
1737
+ awaySide = awaySide === "above" ? "below" : "above";
1738
+ towardSide = towardSide === "above" ? "below" : "above";
1739
+ }
1740
+ setOwnBounds({ maxHeight: Math.max(useToward ? towardRoom : awayRoom, 0), verticalAlign: useToward ? towardSide : awaySide });
1741
+ });
1742
+ }, [shouldMeasure, zone, auto.triggerRef, contentHeight, windowHeight, insets.top, insets.bottom]);
1743
+ if (!zone) return auto;
1744
+ if (!ownBounds) return { ...auto, measured: false };
1745
+ return { ...auto, maxHeight: ownBounds.maxHeight, measured: auto.measured, verticalAlign: ownBounds.verticalAlign };
1746
+ }
1747
+
1694
1748
  // src/PlayerSetupPanel.tsx
1695
1749
  var import_jsx_runtime25 = require("react/jsx-runtime");
1696
1750
  function getColorPopoverId(idPrefix) {
1697
1751
  return `${idPrefix}-color`;
1698
1752
  }
1753
+ function getProfilePopoverId(idPrefix) {
1754
+ return `${idPrefix}-profile`;
1755
+ }
1699
1756
  function getCpuDifficultyPopoverId(idPrefix) {
1700
1757
  return `${idPrefix}-difficulty`;
1701
1758
  }
1702
- 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" }) {
1759
+ 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" }) {
1703
1760
  const ownHost = usePopoverHost();
1704
1761
  const popover = host ?? ownHost;
1705
1762
  const ownPopoverOpen = popover.openId?.startsWith(`${idPrefix}-`) ?? false;
1706
1763
  const pickerRowPopoverOpen = popover.openId === getColorPopoverId(idPrefix) || secondPickerId !== void 0 && popover.openId === secondPickerId;
1707
1764
  const showProfilePicker = isHuman && profiles !== void 0 && !!onProfileSelect;
1708
1765
  const showCpuDifficulty = !isHuman && cpuDifficulty !== void 0 && cpuDifficultyOptions !== void 0 && !!onCpuDifficultyChange;
1766
+ const seatButton = showProfilePicker || showCpuDifficulty;
1709
1767
  const selectedProfile = profiles?.find((p) => p.id === selectedProfileId) ?? null;
1710
- return /* @__PURE__ */ (0, import_jsx_runtime25.jsxs)(import_react_native26.View, { style: [styles21.panel, ownPopoverOpen && styles21.panelOpen], children: [
1711
- 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 }),
1712
- /* @__PURE__ */ (0, import_jsx_runtime25.jsxs)(import_react_native26.View, { style: [styles21.pickerRow, pickerRowPopoverOpen && styles21.pickerRowOpen], children: [
1713
- /* @__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 }),
1768
+ const colorSection = showColor ? { value: color, onChange: onColorChange, swatches, takenValue: takenColor, allowSwapTaken, caption: showProfilePicker && selectedProfile ? colorCaption : void 0 } : void 0;
1769
+ const seatPickerId = showProfilePicker ? getProfilePopoverId(idPrefix) : getCpuDifficultyPopoverId(idPrefix);
1770
+ const seatPickerSize = showProfilePicker ? (0, import_profile2.getProfilePickerContentSize)(profiles.length, !!onManageProfiles, colorSection) : (0, import_profile2.getOptionPickerContentSize)(cpuDifficultyOptions?.length ?? 0, colorSection);
1771
+ const seatPickerAlign = useZoneClampedAlign(seatButton && popover.openId === seatPickerId, seatPickerSize.width, seatPickerSize.height);
1772
+ return /* @__PURE__ */ (0, import_jsx_runtime25.jsxs)(import_react_native27.View, { style: [styles21.panel, ownPopoverOpen && styles21.panelOpen], children: [
1773
+ 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 }),
1774
+ (!seatButton || secondPicker) && /* @__PURE__ */ (0, import_jsx_runtime25.jsxs)(import_react_native27.View, { style: [styles21.pickerRow, pickerRowPopoverOpen && styles21.pickerRowOpen], children: [
1775
+ !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 }),
1714
1776
  secondPicker
1715
1777
  ] }),
1716
1778
  isHuman && showReadyButton && onToggleReady && /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(ReadyButton, { color, ready: ready ?? false, onToggleReady })
1717
1779
  ] });
1718
1780
  }
1719
- var styles21 = import_react_native26.StyleSheet.create({
1781
+ var styles21 = import_react_native27.StyleSheet.create({
1720
1782
  panel: {
1721
1783
  alignItems: "center",
1722
1784
  gap: 12
@@ -1727,9 +1789,9 @@ var styles21 = import_react_native26.StyleSheet.create({
1727
1789
  panelOpen: {
1728
1790
  zIndex: 100
1729
1791
  },
1730
- // Same gap as `panel`'s own vertical rhythm, reused horizontally - the color picker and (when
1731
- // present) secondPicker sit side by side within this row instead of stacked in the panel's own
1732
- // column.
1792
+ // Same gap as `panel`'s own vertical rhythm, reused horizontally - the fallback color swatch and
1793
+ // (when present) secondPicker sit side by side within this row instead of stacked in the panel's
1794
+ // own column.
1733
1795
  pickerRow: {
1734
1796
  alignItems: "center",
1735
1797
  flexDirection: "row",
@@ -1748,20 +1810,20 @@ var styles21 = import_react_native26.StyleSheet.create({
1748
1810
  });
1749
1811
 
1750
1812
  // src/PressAwayOverlay.tsx
1751
- var import_react_native27 = require("react-native");
1813
+ var import_react_native28 = require("react-native");
1752
1814
  var import_jsx_runtime26 = require("react/jsx-runtime");
1753
1815
  function PressAwayOverlay({ active, onPress, style }) {
1754
1816
  if (!active) return null;
1755
- return /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(import_react_native27.Pressable, { accessibilityLabel: "Dismiss", accessibilityRole: "button", onPress, style: [import_react_native27.StyleSheet.absoluteFill, style] });
1817
+ return /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(import_react_native28.Pressable, { accessibilityLabel: "Dismiss", accessibilityRole: "button", onPress, style: [import_react_native28.StyleSheet.absoluteFill, style] });
1756
1818
  }
1757
1819
 
1758
1820
  // src/SharedActionBand.tsx
1759
1821
  var import_feedback_press9 = require("@rific/feedback-press");
1760
- var import_react_native28 = require("react-native");
1822
+ var import_react_native29 = require("react-native");
1761
1823
  var import_jsx_runtime27 = require("react/jsx-runtime");
1762
1824
  function SharedActionBand({ onBack, onSettings, onRandomize, onReset, fg, popoverOpen, children }) {
1763
- return /* @__PURE__ */ (0, import_jsx_runtime27.jsxs)(import_react_native28.View, { style: [styles22.column, popoverOpen && styles22.columnOpen], children: [
1764
- /* @__PURE__ */ (0, import_jsx_runtime27.jsxs)(import_react_native28.View, { style: styles22.actionsRow, children: [
1825
+ return /* @__PURE__ */ (0, import_jsx_runtime27.jsxs)(import_react_native29.View, { style: [styles22.column, popoverOpen && styles22.columnOpen], children: [
1826
+ /* @__PURE__ */ (0, import_jsx_runtime27.jsxs)(import_react_native29.View, { style: styles22.actionsRow, children: [
1765
1827
  /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(import_feedback_press9.IconButton, { icon: "arrow-left", iconColor: fg, size: 20, onPress: onBack, accessibilityLabel: "Back" }),
1766
1828
  onRandomize && /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(import_feedback_press9.IconButton, { icon: "dice-multiple", iconColor: fg, size: 18, onPress: onRandomize, accessibilityLabel: "Randomize match settings" }),
1767
1829
  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" }),
@@ -1770,7 +1832,7 @@ function SharedActionBand({ onBack, onSettings, onRandomize, onReset, fg, popove
1770
1832
  children
1771
1833
  ] });
1772
1834
  }
1773
- var styles22 = import_react_native28.StyleSheet.create({
1835
+ var styles22 = import_react_native29.StyleSheet.create({
1774
1836
  actionsRow: {
1775
1837
  alignItems: "center",
1776
1838
  flexDirection: "row",
@@ -1786,8 +1848,8 @@ var styles22 = import_react_native28.StyleSheet.create({
1786
1848
  });
1787
1849
 
1788
1850
  // src/StaggeredWord.tsx
1789
- var import_react11 = require("react");
1790
- var import_react_native29 = require("react-native");
1851
+ var import_react13 = require("react");
1852
+ var import_react_native30 = require("react-native");
1791
1853
  var import_react_native_reanimated2 = __toESM(require("react-native-reanimated"));
1792
1854
  var import_jsx_runtime28 = require("react/jsx-runtime");
1793
1855
  var STAGGER_MS = 45;
@@ -1797,7 +1859,7 @@ function getStaggeredWordDuration(letterCount) {
1797
1859
  }
1798
1860
  function AnimatedLetter({ char, index, color, reducedMotion, fontFamily, fontSize, lineHeight, fontWeight, letterSpacing }) {
1799
1861
  const progress = (0, import_react_native_reanimated2.useSharedValue)(reducedMotion ? 1 : 0);
1800
- (0, import_react11.useEffect)(() => {
1862
+ (0, import_react13.useEffect)(() => {
1801
1863
  if (reducedMotion) return;
1802
1864
  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)) }));
1803
1865
  }, [reducedMotion]);
@@ -1808,9 +1870,9 @@ function AnimatedLetter({ char, index, color, reducedMotion, fontFamily, fontSiz
1808
1870
  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 });
1809
1871
  }
1810
1872
  function StaggeredWord({ word, color, fontFamily, fontSize, lineHeight, reducedMotion, startIndex = 0, fontWeight = "bold", letterSpacing, style, onLayout }) {
1811
- 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)) });
1873
+ 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)) });
1812
1874
  }
1813
- var styles23 = import_react_native29.StyleSheet.create({
1875
+ var styles23 = import_react_native30.StyleSheet.create({
1814
1876
  row: {
1815
1877
  flexDirection: "row"
1816
1878
  }
@@ -1827,63 +1889,24 @@ function UpdateDialog({ rotation = 0, autoCheck = true, autoPrompt = true, onErr
1827
1889
  }
1828
1890
 
1829
1891
  // src/useQuitConfirmation.ts
1830
- var import_react12 = require("react");
1892
+ var import_react14 = require("react");
1831
1893
  function useQuitConfirmation(hasProgress, onConfirmedBack) {
1832
- const [confirmVisible, setConfirmVisible] = (0, import_react12.useState)(false);
1833
- const hasProgressRef = (0, import_react12.useRef)(hasProgress);
1834
- (0, import_react12.useEffect)(() => {
1894
+ const [confirmVisible, setConfirmVisible] = (0, import_react14.useState)(false);
1895
+ const hasProgressRef = (0, import_react14.useRef)(hasProgress);
1896
+ (0, import_react14.useEffect)(() => {
1835
1897
  hasProgressRef.current = hasProgress;
1836
1898
  });
1837
- const onConfirmedBackRef = (0, import_react12.useRef)(onConfirmedBack);
1838
- (0, import_react12.useEffect)(() => {
1899
+ const onConfirmedBackRef = (0, import_react14.useRef)(onConfirmedBack);
1900
+ (0, import_react14.useEffect)(() => {
1839
1901
  onConfirmedBackRef.current = onConfirmedBack;
1840
1902
  });
1841
- const requestBack = (0, import_react12.useCallback)(() => {
1903
+ const requestBack = (0, import_react14.useCallback)(() => {
1842
1904
  if (hasProgressRef.current()) setConfirmVisible(true);
1843
1905
  else onConfirmedBackRef.current();
1844
1906
  }, []);
1845
- const cancelBack = (0, import_react12.useCallback)(() => setConfirmVisible(false), []);
1907
+ const cancelBack = (0, import_react14.useCallback)(() => setConfirmVisible(false), []);
1846
1908
  return { confirmVisible, requestBack, cancelBack };
1847
1909
  }
1848
-
1849
- // src/useZoneClampedAlign.ts
1850
- var import_split_screen = require("@tastic/split-screen");
1851
- var import_react13 = require("react");
1852
- var import_react_native30 = require("react-native");
1853
- var import_react_native_safe_area_context3 = require("react-native-safe-area-context");
1854
- var EDGE_MARGIN2 = 12;
1855
- function useZoneClampedAlign(open, contentWidth, contentHeight, rotation = 0) {
1856
- const auto = useAutoAlign(open, contentWidth, contentHeight, rotation);
1857
- const zone = (0, import_split_screen.useZoneBounds)();
1858
- const { height: windowHeight } = (0, import_react_native30.useWindowDimensions)();
1859
- const insets = (0, import_react_native_safe_area_context3.useSafeAreaInsets)();
1860
- const shouldMeasure = open && auto.measured && zone !== null;
1861
- const [ownBounds, setOwnBounds] = (0, import_react13.useState)(null);
1862
- const [prevShouldMeasure, setPrevShouldMeasure] = (0, import_react13.useState)(shouldMeasure);
1863
- if (shouldMeasure !== prevShouldMeasure) {
1864
- setPrevShouldMeasure(shouldMeasure);
1865
- setOwnBounds(null);
1866
- }
1867
- (0, import_react13.useEffect)(() => {
1868
- if (!shouldMeasure) return;
1869
- auto.triggerRef.current?.measureInWindow((_x, y, _width, height) => {
1870
- const belowShared = zone.zoneSide === "belowShared";
1871
- const awayRoom = belowShared ? windowHeight - insets.bottom - (y + height) - EDGE_MARGIN2 : y - insets.top - EDGE_MARGIN2;
1872
- const towardRoom = belowShared ? y - zone.sharedEdgeY - EDGE_MARGIN2 : zone.sharedEdgeY - (y + height) - EDGE_MARGIN2;
1873
- const useToward = contentHeight > awayRoom && towardRoom > awayRoom;
1874
- let awaySide = belowShared ? "below" : "above";
1875
- let towardSide = belowShared ? "above" : "below";
1876
- if (zone.rotated) {
1877
- awaySide = awaySide === "above" ? "below" : "above";
1878
- towardSide = towardSide === "above" ? "below" : "above";
1879
- }
1880
- setOwnBounds({ maxHeight: Math.max(useToward ? towardRoom : awayRoom, 0), verticalAlign: useToward ? towardSide : awaySide });
1881
- });
1882
- }, [shouldMeasure, zone, auto.triggerRef, contentHeight, windowHeight, insets.top, insets.bottom]);
1883
- if (!zone) return auto;
1884
- if (!ownBounds) return { ...auto, measured: false };
1885
- return { ...auto, maxHeight: ownBounds.maxHeight, measured: auto.measured, verticalAlign: ownBounds.verticalAlign };
1886
- }
1887
1910
  // Annotate the CommonJS export names for ESM import in node:
1888
1911
  0 && (module.exports = {
1889
1912
  AchievementCatalogSection,
@@ -1923,6 +1946,7 @@ function useZoneClampedAlign(open, contentWidth, contentHeight, rotation = 0) {
1923
1946
  getCpuDifficultyPopoverId,
1924
1947
  getInlineColorPickerContentSize,
1925
1948
  getLabeledDropdownContentHeight,
1949
+ getProfilePopoverId,
1926
1950
  getStaggeredWordDuration,
1927
1951
  isCompactDialogHeight,
1928
1952
  loadSkiaWeb,