@tastic/hud 0.17.0 → 0.18.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.
@@ -35,9 +35,11 @@ __export(chrome_exports, {
35
35
  ActivityStatSection: () => ActivityStatSection,
36
36
  BaseSettingsDialog: () => BaseSettingsDialog,
37
37
  BaseStatsScreen: () => BaseStatsScreen,
38
+ COMPACT_DIALOG_HEIGHT: () => COMPACT_DIALOG_HEIGHT,
38
39
  ConfirmDialog: () => ConfirmDialog,
39
40
  ContentGutter: () => ContentGutter,
40
41
  CornerActionButtons: () => CornerActionButtons,
42
+ DialogHeader: () => DialogHeader,
41
43
  LOCKED_BADGE_COLOR: () => LOCKED_BADGE_COLOR,
42
44
  MONO_FONT: () => MONO_FONT,
43
45
  OverlayBackdrop: () => OverlayBackdrop,
@@ -47,10 +49,11 @@ __export(chrome_exports, {
47
49
  StatRow: () => StatRow,
48
50
  StatSection: () => StatSection,
49
51
  UpdateDialog: () => UpdateDialog,
50
- getOverlayCardColors: () => getOverlayCardColors,
51
52
  getStaggeredWordDuration: () => getStaggeredWordDuration,
53
+ isCompactDialogHeight: () => isCompactDialogHeight,
52
54
  overlayActionStyles: () => overlayActionStyles,
53
55
  overlayStyles: () => overlayStyles,
56
+ useCompactDialog: () => useCompactDialog,
54
57
  useOverlayCardColors: () => useOverlayCardColors
55
58
  });
56
59
  module.exports = __toCommonJS(chrome_exports);
@@ -216,39 +219,74 @@ function ActivityStatSection({ stats }) {
216
219
  }
217
220
 
218
221
  // src/BaseSettingsDialog.tsx
219
- var import_auto_paper7 = require("@rific/auto-paper");
222
+ var import_auto_paper8 = require("@rific/auto-paper");
220
223
  var import_feedback_press2 = require("@rific/feedback-press");
221
224
  var import_updater = require("@rific/updater");
222
- var import_core3 = require("@tastic/core");
223
- var import_react4 = require("react");
224
- var import_react_native10 = require("react-native");
225
- var import_react_native_paper7 = require("react-native-paper");
225
+ var import_core4 = require("@tastic/core");
226
+ var import_react5 = require("react");
227
+ var import_react_native12 = require("react-native");
228
+ var import_react_native_paper8 = require("react-native-paper");
229
+ var import_react_native_safe_area_context2 = require("react-native-safe-area-context");
226
230
 
227
231
  // src/ConfirmDialog.tsx
228
- var import_auto_paper6 = require("@rific/auto-paper");
232
+ var import_auto_paper7 = require("@rific/auto-paper");
229
233
  var import_feedback_press = require("@rific/feedback-press");
230
- var import_core = require("@tastic/core");
231
- var import_react_native8 = require("react-native");
232
- var import_react_native_paper5 = require("react-native-paper");
234
+ var import_core2 = require("@tastic/core");
235
+ var import_react_native10 = require("react-native");
236
+ var import_react_native_paper6 = require("react-native-paper");
233
237
 
234
- // src/overlayCard.ts
238
+ // src/DialogHeader.tsx
239
+ var import_auto_paper5 = require("@rific/auto-paper");
235
240
  var import_react_native6 = require("react-native");
236
- function getOverlayCardColors(dark) {
237
- return {
238
- fg: dark ? "#FFFFFF" : "#000000",
239
- fgMuted: dark ? "rgba(255,255,255,0.4)" : "rgba(0,0,0,0.4)",
240
- cardBg: dark ? "#111111" : "#F2F2F2",
241
- cardBorder: dark ? "rgba(255,255,255,0.2)" : "rgba(0,0,0,0.2)"
242
- };
241
+ var import_react_native_paper5 = require("react-native-paper");
242
+ var import_jsx_runtime6 = require("react/jsx-runtime");
243
+ var COMPACT_DIALOG_HEIGHT = 528;
244
+ function isCompactDialogHeight(height) {
245
+ return height < COMPACT_DIALOG_HEIGHT;
243
246
  }
244
- var overlayStyles = import_react_native6.StyleSheet.create({
247
+ function DialogHeader({ icon, title, color, compact = false, style }) {
248
+ const { colors } = (0, import_auto_paper5.useAutoPaperTheme)();
249
+ const accent = color ?? colors.primary;
250
+ return /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(import_react_native6.View, { style: [compact ? styles5.compact : styles5.full, style], children: [
251
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(import_react_native_paper5.Icon, { source: icon, size: compact ? COMPACT_ICON_SIZE : ICON_SIZE, color: accent }),
252
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(import_react_native_paper5.Text, { accessibilityRole: "header", variant: compact ? "headlineSmall" : "headlineLarge", style: [styles5.title, compact && styles5.titleCompact, { color: accent }], children: title })
253
+ ] });
254
+ }
255
+ var ICON_SIZE = 64;
256
+ var COMPACT_ICON_SIZE = 32;
257
+ var styles5 = import_react_native6.StyleSheet.create({
258
+ compact: {
259
+ alignItems: "center",
260
+ alignSelf: "stretch",
261
+ flexDirection: "row",
262
+ gap: 12,
263
+ justifyContent: "center"
264
+ },
265
+ full: {
266
+ alignItems: "center",
267
+ alignSelf: "stretch",
268
+ gap: 16
269
+ },
270
+ // textAlign matters once a title wraps: the card centers the Text's block, but each wrapped line
271
+ // still defaults to left-aligned without it.
272
+ title: {
273
+ fontWeight: "bold",
274
+ textAlign: "center"
275
+ },
276
+ titleCompact: {
277
+ flexShrink: 1
278
+ }
279
+ });
280
+
281
+ // src/overlayCard.ts
282
+ var import_react_native7 = require("react-native");
283
+ var overlayStyles = import_react_native7.StyleSheet.create({
245
284
  card: {
246
285
  alignItems: "center",
247
- borderRadius: 20,
248
- borderWidth: 1,
286
+ borderRadius: 28,
249
287
  gap: 16,
250
288
  maxWidth: 360,
251
- padding: 32
289
+ padding: 24
252
290
  },
253
291
  overlay: {
254
292
  alignItems: "center",
@@ -261,7 +299,7 @@ var overlayStyles = import_react_native6.StyleSheet.create({
261
299
  top: 0
262
300
  }
263
301
  });
264
- var overlayActionStyles = import_react_native6.StyleSheet.create({
302
+ var overlayActionStyles = import_react_native7.StyleSheet.create({
265
303
  // minWidth (not flexBasis) is each button's real floor - whenever both fit side by side, flexGrow
266
304
  // still splits any leftover width evenly beyond that floor, same visual result as a plain flex: 1
267
305
  // on a roomy screen, but a button can never be squeezed narrower than 128, only wrap to its own
@@ -304,46 +342,63 @@ var overlayActionStyles = import_react_native6.StyleSheet.create({
304
342
  });
305
343
 
306
344
  // src/OverlaySurface.tsx
307
- var import_auto_paper5 = require("@rific/auto-paper");
308
- var import_react_native7 = require("react-native");
309
- var import_jsx_runtime6 = require("react/jsx-runtime");
345
+ var import_auto_paper6 = require("@rific/auto-paper");
346
+ var import_react_native8 = require("react-native");
347
+ var import_jsx_runtime7 = require("react/jsx-runtime");
310
348
  function useOverlayCardColors() {
311
- const { colors } = (0, import_auto_paper5.useAutoPaperTheme)();
349
+ const { colors } = (0, import_auto_paper6.useAutoPaperTheme)();
312
350
  return { fg: colors.onSurface, fgMuted: colors.onSurfaceVariant, cardBorder: colors.outlineVariant, backdrop: colors.backdrop };
313
351
  }
314
- function OverlayBackdrop({ children, style }) {
352
+ function OverlayBackdrop({ children, style, onLayout }) {
315
353
  const { backdrop } = useOverlayCardColors();
316
- return /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(import_react_native7.View, { style: [overlayStyles.overlay, { backgroundColor: backdrop }, style], children });
354
+ return /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(import_react_native8.View, { onLayout, style: [overlayStyles.overlay, { backgroundColor: backdrop }, style], children });
317
355
  }
318
356
  function OverlayCard({ children, style, ...rest }) {
319
- const { cardBorder } = useOverlayCardColors();
320
- const blur = (0, import_auto_paper5.useBlur)();
321
- return /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(import_auto_paper5.BlurView, { blur, elevation: 3, style: [overlayStyles.card, styles5.card, { borderColor: cardBorder }, style], ...rest, children });
357
+ const { isV3, roundness } = (0, import_auto_paper6.useAutoPaperTheme)();
358
+ const blur = (0, import_auto_paper6.useBlur)();
359
+ return /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(import_auto_paper6.BlurView, { blur, style: [overlayStyles.card, styles6.card, { borderRadius: (isV3 ? 7 : 1) * roundness }, style], ...rest, children });
322
360
  }
323
- var styles5 = import_react_native7.StyleSheet.create({
361
+ var styles6 = import_react_native8.StyleSheet.create({
324
362
  card: { overflow: "hidden" }
325
363
  });
326
364
 
365
+ // src/useCompactDialog.ts
366
+ var import_core = require("@tastic/core");
367
+ var import_react2 = require("react");
368
+ var import_react_native9 = require("react-native");
369
+ function useCompactDialog(rotation = 0) {
370
+ const window = (0, import_react_native9.useWindowDimensions)();
371
+ const framed = (0, import_core.useRotatedWindowDimensions)();
372
+ const [measured, setMeasured] = (0, import_react2.useState)(null);
373
+ const onLayout = (0, import_react2.useCallback)((e) => {
374
+ const { width, height } = e.nativeEvent.layout;
375
+ setMeasured((prev) => prev && prev.width === width && prev.height === height ? prev : { width, height });
376
+ }, []);
377
+ const box = measured ?? (rotation === 0 ? framed : window);
378
+ const turned = rotation === 90 || rotation === -90;
379
+ return { compact: isCompactDialogHeight(turned ? box.width : box.height), onLayout };
380
+ }
381
+
327
382
  // src/ConfirmDialog.tsx
328
- var import_jsx_runtime7 = require("react/jsx-runtime");
383
+ var import_jsx_runtime8 = require("react/jsx-runtime");
329
384
  function ConfirmDialog({ visible, title, message, confirmLabel, cancelLabel, onConfirm, onCancel, rotation = 0, icon = "help-circle-outline", destructive = false }) {
330
- const { colors } = (0, import_auto_paper6.useAutoPaperTheme)();
385
+ const { colors } = (0, import_auto_paper7.useAutoPaperTheme)();
331
386
  const { fg } = useOverlayCardColors();
387
+ const { compact, onLayout } = useCompactDialog(rotation);
332
388
  if (!visible) return null;
333
389
  const accent = destructive ? colors.danger : colors.primary;
334
390
  const onAccent = destructive ? colors.onDanger : colors.onPrimary;
335
391
  const showCancel = cancelLabel !== void 0 && onCancel !== void 0;
336
- return /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(import_react_native_paper5.Portal, { children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(OverlayBackdrop, { style: styles6.overlay, children: /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(OverlayCard, { style: [styles6.card, (0, import_core.toRotationStyle)(rotation)], children: [
337
- /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(import_react_native_paper5.Icon, { source: icon, size: 64, color: accent }),
338
- /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(import_react_native_paper5.Text, { variant: "headlineLarge", style: [styles6.title, { color: accent }], children: title }),
339
- /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(import_react_native_paper5.Text, { variant: "bodyLarge", style: [styles6.body, { color: fg }], children: message }),
340
- /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(import_react_native8.View, { style: overlayActionStyles.actions, children: [
341
- showCancel && /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(import_feedback_press.Button, { mode: "outlined", onPress: onCancel, style: overlayActionStyles.actionButton, children: cancelLabel }),
342
- /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(import_feedback_press.Button, { mode: "contained", onPress: onConfirm, style: showCancel ? overlayActionStyles.actionButton : overlayActionStyles.actionButtonSingle, buttonColor: accent, textColor: onAccent, children: confirmLabel })
392
+ return /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(import_react_native_paper6.Portal, { children: /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(OverlayBackdrop, { style: styles7.overlay, onLayout, children: /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)(OverlayCard, { style: [styles7.card, (0, import_core2.toRotationStyle)(rotation)], children: [
393
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(DialogHeader, { icon, title, color: accent, compact }),
394
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(import_react_native_paper6.Text, { variant: "bodyLarge", style: [styles7.body, { color: fg }], children: message }),
395
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)(import_react_native10.View, { style: overlayActionStyles.actions, children: [
396
+ showCancel && /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(import_feedback_press.Button, { mode: "outlined", onPress: onCancel, style: overlayActionStyles.actionButton, children: cancelLabel }),
397
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(import_feedback_press.Button, { mode: "contained", onPress: onConfirm, style: showCancel ? overlayActionStyles.actionButton : overlayActionStyles.actionButtonSingle, buttonColor: accent, textColor: onAccent, children: confirmLabel })
343
398
  ] })
344
399
  ] }) }) });
345
400
  }
346
- var styles6 = import_react_native8.StyleSheet.create({
401
+ var styles7 = import_react_native10.StyleSheet.create({
347
402
  body: {
348
403
  textAlign: "center"
349
404
  },
@@ -361,35 +416,28 @@ var styles6 = import_react_native8.StyleSheet.create({
361
416
  // screen narrower than maxWidth's own 360.
362
417
  overlay: {
363
418
  paddingHorizontal: 24
364
- },
365
- // textAlign is load-bearing, not decorative, once `title` wraps to more than one line - centered
366
- // within card's own alignItems: 'center' only centers the Text's block as a whole; each wrapped
367
- // line inside that block still defaults to left-aligned without this.
368
- title: {
369
- fontWeight: "bold",
370
- textAlign: "center"
371
419
  }
372
420
  });
373
421
 
374
422
  // src/RotatedFrame.tsx
375
- var import_core2 = require("@tastic/core");
376
- var import_react2 = require("react");
377
- var import_react_native9 = require("react-native");
378
- var import_react_native_paper6 = require("react-native-paper");
423
+ var import_core3 = require("@tastic/core");
424
+ var import_react3 = require("react");
425
+ var import_react_native11 = require("react-native");
426
+ var import_react_native_paper7 = require("react-native-paper");
379
427
  var import_react_native_safe_area_context = require("react-native-safe-area-context");
380
- var import_jsx_runtime8 = require("react/jsx-runtime");
428
+ var import_jsx_runtime9 = require("react/jsx-runtime");
381
429
  function RotatedFrame({ children, rotation: rotationOverride, rotatedSafeArea = false, portalHost = false, passThrough = false, maxContentWidth }) {
382
- const ambientRotation = (0, import_core2.useRotation)();
430
+ const ambientRotation = (0, import_core3.useRotation)();
383
431
  const rotation = rotationOverride ?? ambientRotation;
384
- const window = (0, import_react_native9.useWindowDimensions)();
385
- const { width, height } = (0, import_core2.rotateDimensions)(window.width, window.height, rotation);
432
+ const window = (0, import_react_native11.useWindowDimensions)();
433
+ const { width, height } = (0, import_core3.rotateDimensions)(window.width, window.height, rotation);
386
434
  const rawInsets = (0, import_react_native_safe_area_context.useSafeAreaInsets)();
387
- const insets = (0, import_react2.useMemo)(() => rotatedSafeArea ? (0, import_core2.rotateInsets)(rawInsets, rotation) : rawInsets, [rotatedSafeArea, rawInsets, rotation]);
435
+ const insets = (0, import_react3.useMemo)(() => rotatedSafeArea ? (0, import_core3.rotateInsets)(rawInsets, rotation) : rawInsets, [rotatedSafeArea, rawInsets, rotation]);
388
436
  const cappedWidth = maxContentWidth !== void 0 && width > height ? maxContentWidth : void 0;
389
- const column = /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(import_react_native9.View, { style: [styles7.column, cappedWidth !== void 0 && { maxWidth: cappedWidth }], pointerEvents: passThrough ? "box-none" : void 0, children });
390
- return /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(import_core2.FakeLandscapeView, { rotation, passThrough, style: styles7.root, children: /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(import_react_native_safe_area_context.SafeAreaInsetsContext.Provider, { value: insets, children: portalHost ? /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(import_react_native_paper6.Portal.Host, { children: column }) : column }) });
437
+ const column = /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(import_react_native11.View, { style: [styles8.column, cappedWidth !== void 0 && { maxWidth: cappedWidth }], pointerEvents: passThrough ? "box-none" : void 0, children });
438
+ return /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(import_core3.FakeLandscapeView, { rotation, passThrough, style: styles8.root, children: /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(import_react_native_safe_area_context.SafeAreaInsetsContext.Provider, { value: insets, children: portalHost ? /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(import_react_native_paper7.Portal.Host, { children: column }) : column }) });
391
439
  }
392
- var styles7 = import_react_native9.StyleSheet.create({
440
+ var styles8 = import_react_native11.StyleSheet.create({
393
441
  // A centred column: full width up to `maxWidth`, so a capped frame sits in the middle of a wider window.
394
442
  column: {
395
443
  alignSelf: "center",
@@ -402,18 +450,18 @@ var styles7 = import_react_native9.StyleSheet.create({
402
450
  });
403
451
 
404
452
  // src/useUpdateConfirmBridge.ts
405
- var import_react3 = require("react");
453
+ var import_react4 = require("react");
406
454
  function useUpdateConfirmBridge() {
407
- const [manifest, setManifest] = (0, import_react3.useState)(null);
408
- const resolveRef = (0, import_react3.useRef)(null);
409
- const onConfirm = (0, import_react3.useCallback)(
455
+ const [manifest, setManifest] = (0, import_react4.useState)(null);
456
+ const resolveRef = (0, import_react4.useRef)(null);
457
+ const onConfirm = (0, import_react4.useCallback)(
410
458
  (next) => new Promise((resolve) => {
411
459
  resolveRef.current = resolve;
412
460
  setManifest(next);
413
461
  }),
414
462
  []
415
463
  );
416
- const respond = (0, import_react3.useCallback)((confirmed) => {
464
+ const respond = (0, import_react4.useCallback)((confirmed) => {
417
465
  setManifest(null);
418
466
  resolveRef.current?.(confirmed);
419
467
  resolveRef.current = null;
@@ -422,22 +470,27 @@ function useUpdateConfirmBridge() {
422
470
  }
423
471
 
424
472
  // src/BaseSettingsDialog.tsx
425
- var import_jsx_runtime9 = require("react/jsx-runtime");
473
+ var import_jsx_runtime10 = require("react/jsx-runtime");
426
474
  function SettingIcon({ source, color, containerColor }) {
427
- return /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(import_react_native10.View, { style: [styles8.iconBadge, { backgroundColor: containerColor }], children: /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(import_react_native_paper7.Icon, { source, size: 18, color }) });
475
+ return /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(import_react_native12.View, { style: [styles9.iconBadge, { backgroundColor: containerColor }], children: /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(import_react_native_paper8.Icon, { source, size: 18, color }) });
428
476
  }
429
477
  function BaseSettingsDialog({ visible, onDismiss, rotation: rotationOverride, version, lockOrientation, onLockOrientationChange, deferBottomEdgeGestures, onDeferBottomEdgeGestures, hideSound = false, hideHaptics = false, hideAppearance = false, hideUpdateCheck = false, onUpdateError, onShowHowToPlay, children }) {
430
- const { colors } = (0, import_auto_paper7.useAutoPaperTheme)();
431
- const ambientRotation = (0, import_core3.useRotation)();
478
+ const { colors } = (0, import_auto_paper8.useAutoPaperTheme)();
479
+ const ambientRotation = (0, import_core4.useRotation)();
432
480
  const rotation = rotationOverride ?? ambientRotation;
433
- const isTouchPrimary = (0, import_core3.useIsTouchPrimaryDevice)();
481
+ const window = (0, import_react_native12.useWindowDimensions)();
482
+ const turned = rotation === 90 || rotation === -90;
483
+ const compactHeader = isCompactDialogHeight(turned ? window.width : window.height);
484
+ const insets = (0, import_core4.rotateInsets)((0, import_react_native_safe_area_context2.useSafeAreaInsets)(), rotation);
485
+ const sheetWidth = Math.min(overlayStyles.card.maxWidth, (turned ? window.height : window.width) - 2 * Math.max(insets.left, insets.right, SHEET_GUTTER));
486
+ const isTouchPrimary = (0, import_core4.useIsTouchPrimaryDevice)();
434
487
  const { settings: hapticSettings, set: setHapticSettings } = (0, import_feedback_press2.useHapticSettings)();
435
488
  const { settings: soundSettings, set: setSoundSettings } = (0, import_feedback_press2.useSoundSettings)();
436
- const sound = (0, import_react4.useContext)(import_feedback_press2.SoundContext);
489
+ const sound = (0, import_react5.useContext)(import_feedback_press2.SoundContext);
437
490
  const { forceShort: forceHapticFeedback } = (0, import_feedback_press2.useVibration)();
438
- const { settings: themeSettings, set: setThemeSettings } = (0, import_auto_paper7.useThemeSettings)();
439
- const expoBlur = (0, import_auto_paper7.useBlurModule)();
440
- const [infoMessage, setInfoMessage] = (0, import_react4.useState)(null);
491
+ const { settings: themeSettings, set: setThemeSettings } = (0, import_auto_paper8.useThemeSettings)();
492
+ const expoBlur = (0, import_auto_paper8.useBlurModule)();
493
+ const [infoMessage, setInfoMessage] = (0, import_react5.useState)(null);
441
494
  const { manifest: updateManifest, onConfirm: onUpdateConfirm, respond: respondToUpdateConfirm } = useUpdateConfirmBridge();
442
495
  const { check, checking, updateReady } = (0, import_updater.useUpdater)({
443
496
  autoCheck: false,
@@ -447,117 +500,124 @@ function BaseSettingsDialog({ visible, onDismiss, rotation: rotationOverride, ve
447
500
  onInfo: (title, message) => setInfoMessage({ title, message })
448
501
  });
449
502
  const updateManifestDate = updateManifest ? new Date(updateManifest.createdAt) : null;
450
- const [opened, setOpened] = (0, import_react4.useState)(visible);
503
+ const [opened, setOpened] = (0, import_react5.useState)(visible);
451
504
  if (visible && !opened) setOpened(true);
452
505
  const showLockOrientation = isTouchPrimary && lockOrientation !== void 0 && onLockOrientationChange !== void 0;
453
- const showEdgeGuard = import_react_native10.Platform.OS === "ios" && deferBottomEdgeGestures !== void 0 && onDeferBottomEdgeGestures !== void 0;
454
- const showHaptics = import_react_native10.Platform.OS !== "web" && !hideHaptics;
506
+ const showEdgeGuard = import_react_native12.Platform.OS === "ios" && deferBottomEdgeGestures !== void 0 && onDeferBottomEdgeGestures !== void 0;
507
+ const showHaptics = import_react_native12.Platform.OS !== "web" && !hideHaptics;
455
508
  const showSound = !hideSound;
456
509
  const showAppearance = !hideAppearance;
457
- const showBlur = showAppearance && import_react_native10.Platform.OS !== "android" && expoBlur !== void 0 && expoBlur !== null;
458
- const showUpdateCheck = import_react_native10.Platform.OS !== "web" && !hideUpdateCheck;
510
+ const showBlur = showAppearance && import_react_native12.Platform.OS !== "android" && expoBlur !== void 0 && expoBlur !== null;
511
+ const showUpdateCheck = import_react_native12.Platform.OS !== "web" && !hideUpdateCheck;
459
512
  if (!opened) return null;
460
- return /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(import_react_native_paper7.Portal, { children: /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)(RotatedFrame, { rotation, rotatedSafeArea: true, portalHost: true, passThrough: true, children: [
461
- /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)(import_auto_paper7.Dialog, { visible, onDismiss, style: styles8.dialog, children: [
462
- /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(import_auto_paper7.Dialog.Title, { children: "Settings" }),
463
- /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(import_auto_paper7.Dialog.ScrollArea, { style: styles8.scrollArea, children: /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)(import_react_native10.ScrollView, { contentContainerStyle: styles8.content, showsVerticalScrollIndicator: false, children: [
464
- /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)(import_react_native10.View, { style: styles8.toggleGroup, children: [
465
- showLockOrientation && /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(import_feedback_press2.TouchableRipple, { onPress: () => onLockOrientationChange(!lockOrientation), style: styles8.toggleButton, accessibilityLabel: `Lock orientation ${lockOrientation ? "on" : "off"}`, children: /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)(import_react_native10.View, { style: styles8.toggleContent, children: [
466
- /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(SettingIcon, { source: lockOrientation ? "lock" : "lock-open-variant-outline", color: lockOrientation ? colors.tertiary : colors.onSurfaceVariant, containerColor: lockOrientation ? colors.tertiaryContainer : colors.surfaceVariant }),
467
- /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)(import_react_native10.View, { style: styles8.flexShrink, children: [
468
- /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(import_react_native_paper7.Text, { variant: "bodyLarge", style: { color: colors.onSurface }, children: "Lock Orientation" }),
469
- /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(import_react_native_paper7.Text, { variant: "bodySmall", numberOfLines: 1, style: { color: colors.onSurfaceVariant }, children: "Pins the current layout" })
470
- ] })
471
- ] }) }),
472
- showEdgeGuard && /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(import_feedback_press2.TouchableRipple, { onPress: () => onDeferBottomEdgeGestures(!deferBottomEdgeGestures), style: styles8.toggleButton, accessibilityLabel: `Edge guard ${deferBottomEdgeGestures ? "on" : "off"}`, children: /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)(import_react_native10.View, { style: styles8.toggleContent, children: [
473
- /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(SettingIcon, { source: deferBottomEdgeGestures ? "shield-check-outline" : "shield-off-outline", color: deferBottomEdgeGestures ? colors.tertiary : colors.onSurfaceVariant, containerColor: deferBottomEdgeGestures ? colors.tertiaryContainer : colors.surfaceVariant }),
474
- /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)(import_react_native10.View, { style: styles8.flexShrink, children: [
475
- /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(import_react_native_paper7.Text, { variant: "bodyLarge", style: { color: colors.onSurface }, children: "Edge Guard" }),
476
- /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(import_react_native_paper7.Text, { variant: "bodySmall", numberOfLines: 1, style: { color: colors.onSurfaceVariant }, children: "Requires a second swipe" })
477
- ] })
478
- ] }) }),
479
- (showSound || showHaptics) && /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)(import_react_native10.View, { style: styles8.toggleRow, children: [
480
- showSound && /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
481
- import_feedback_press2.TouchableRipple,
482
- {
483
- soundDisabled: true,
484
- onPress: () => {
485
- const enabled = !soundSettings.enabled;
486
- setSoundSettings({ enabled });
487
- if (enabled) sound.selection?.();
488
- },
489
- style: styles8.toggleButtonInRow,
490
- accessibilityLabel: `Sound ${soundSettings.enabled ? "on" : "off"}`,
491
- children: /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)(import_react_native10.View, { style: styles8.toggleContent, children: [
492
- /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(SettingIcon, { source: soundSettings.enabled ? "volume-high" : "volume-off", color: soundSettings.enabled ? colors.tertiary : colors.onSurfaceVariant, containerColor: soundSettings.enabled ? colors.tertiaryContainer : colors.surfaceVariant }),
493
- /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(import_react_native_paper7.Text, { variant: "bodyLarge", style: { color: colors.onSurface }, children: "Sound" })
494
- ] })
495
- }
496
- ),
497
- showHaptics && /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
513
+ return /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(import_react_native_paper8.Portal, { children: /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)(RotatedFrame, { rotation, rotatedSafeArea: true, portalHost: true, passThrough: true, children: [
514
+ /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)(import_auto_paper8.Dialog, { visible, onDismiss, style: [styles9.dialog, { width: sheetWidth }], children: [
515
+ /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(import_auto_paper8.Dialog.ScrollArea, { style: styles9.scrollArea, children: /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)(import_auto_paper8.FadingScrollView, { contentContainerStyle: styles9.scrollContent, showsVerticalScrollIndicator: false, children: [
516
+ /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(DialogHeader, { icon: "cog", title: "Settings", compact: compactHeader }),
517
+ /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)(import_react_native12.View, { style: styles9.content, children: [
518
+ /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)(import_react_native12.View, { style: styles9.toggleGroup, children: [
519
+ showLockOrientation && /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(import_feedback_press2.TouchableRipple, { onPress: () => onLockOrientationChange(!lockOrientation), style: styles9.toggleButton, accessibilityLabel: `Lock orientation ${lockOrientation ? "on" : "off"}`, children: /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)(import_react_native12.View, { style: styles9.toggleContent, children: [
520
+ /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(SettingIcon, { source: lockOrientation ? "lock" : "lock-open-variant-outline", color: lockOrientation ? colors.tertiary : colors.onSurfaceVariant, containerColor: lockOrientation ? colors.tertiaryContainer : colors.surfaceVariant }),
521
+ /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)(import_react_native12.View, { style: styles9.flexShrink, children: [
522
+ /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(import_react_native_paper8.Text, { variant: "bodyLarge", style: { color: colors.onSurface }, children: "Lock Orientation" }),
523
+ /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(import_react_native_paper8.Text, { variant: "bodySmall", numberOfLines: 1, style: { color: colors.onSurfaceVariant }, children: "Pin current layout" })
524
+ ] })
525
+ ] }) }),
526
+ showEdgeGuard && /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(import_feedback_press2.TouchableRipple, { onPress: () => onDeferBottomEdgeGestures(!deferBottomEdgeGestures), style: styles9.toggleButton, accessibilityLabel: `Edge guard ${deferBottomEdgeGestures ? "on" : "off"}`, children: /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)(import_react_native12.View, { style: styles9.toggleContent, children: [
527
+ /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(SettingIcon, { source: deferBottomEdgeGestures ? "shield-check-outline" : "shield-off-outline", color: deferBottomEdgeGestures ? colors.tertiary : colors.onSurfaceVariant, containerColor: deferBottomEdgeGestures ? colors.tertiaryContainer : colors.surfaceVariant }),
528
+ /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)(import_react_native12.View, { style: styles9.flexShrink, children: [
529
+ /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(import_react_native_paper8.Text, { variant: "bodyLarge", style: { color: colors.onSurface }, children: "Edge Guard" }),
530
+ /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(import_react_native_paper8.Text, { variant: "bodySmall", numberOfLines: 1, style: { color: colors.onSurfaceVariant }, children: "Require second swipe" })
531
+ ] })
532
+ ] }) }),
533
+ (showSound || showHaptics) && /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)(import_react_native12.View, { style: styles9.toggleRow, children: [
534
+ showSound && /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
535
+ import_feedback_press2.TouchableRipple,
536
+ {
537
+ soundDisabled: true,
538
+ onPress: () => {
539
+ const enabled = !soundSettings.enabled;
540
+ setSoundSettings({ enabled });
541
+ if (enabled) sound.selection?.();
542
+ },
543
+ style: styles9.toggleButtonInRow,
544
+ accessibilityLabel: `Sound ${soundSettings.enabled ? "on" : "off"}`,
545
+ children: /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)(import_react_native12.View, { style: styles9.toggleContent, children: [
546
+ /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(SettingIcon, { source: soundSettings.enabled ? "volume-high" : "volume-off", color: soundSettings.enabled ? colors.tertiary : colors.onSurfaceVariant, containerColor: soundSettings.enabled ? colors.tertiaryContainer : colors.surfaceVariant }),
547
+ /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(import_react_native_paper8.Text, { variant: "bodyLarge", style: { color: colors.onSurface }, children: "Sound" })
548
+ ] })
549
+ }
550
+ ),
551
+ showHaptics && /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
552
+ import_feedback_press2.TouchableRipple,
553
+ {
554
+ hapticDisabled: true,
555
+ onPress: () => {
556
+ const vibrate = !hapticSettings.vibrate;
557
+ setHapticSettings({ vibrate });
558
+ if (vibrate) forceHapticFeedback();
559
+ },
560
+ style: styles9.toggleButtonInRow,
561
+ accessibilityLabel: `Haptics ${hapticSettings.vibrate ? "on" : "off"}`,
562
+ children: /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)(import_react_native12.View, { style: styles9.toggleContent, children: [
563
+ /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(SettingIcon, { source: hapticSettings.vibrate ? "vibrate" : "vibrate-off", color: hapticSettings.vibrate ? colors.tertiary : colors.onSurfaceVariant, containerColor: hapticSettings.vibrate ? colors.tertiaryContainer : colors.surfaceVariant }),
564
+ /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(import_react_native_paper8.Text, { variant: "bodyLarge", style: { color: colors.onSurface }, children: "Haptics" })
565
+ ] })
566
+ }
567
+ )
568
+ ] }),
569
+ onShowHowToPlay && /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
498
570
  import_feedback_press2.TouchableRipple,
499
571
  {
500
- hapticDisabled: true,
501
572
  onPress: () => {
502
- const vibrate = !hapticSettings.vibrate;
503
- setHapticSettings({ vibrate });
504
- if (vibrate) forceHapticFeedback();
573
+ onDismiss();
574
+ onShowHowToPlay();
505
575
  },
506
- style: styles8.toggleButtonInRow,
507
- accessibilityLabel: `Haptics ${hapticSettings.vibrate ? "on" : "off"}`,
508
- children: /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)(import_react_native10.View, { style: styles8.toggleContent, children: [
509
- /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(SettingIcon, { source: hapticSettings.vibrate ? "vibrate" : "vibrate-off", color: hapticSettings.vibrate ? colors.tertiary : colors.onSurfaceVariant, containerColor: hapticSettings.vibrate ? colors.tertiaryContainer : colors.surfaceVariant }),
510
- /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(import_react_native_paper7.Text, { variant: "bodyLarge", style: { color: colors.onSurface }, children: "Haptics" })
576
+ style: styles9.toggleButton,
577
+ accessibilityLabel: "How to Play",
578
+ children: /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)(import_react_native12.View, { style: styles9.toggleContent, children: [
579
+ /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(SettingIcon, { source: "help-circle-outline", color: colors.secondary, containerColor: colors.secondaryContainer }),
580
+ /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)(import_react_native12.View, { style: styles9.flexShrink, children: [
581
+ /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(import_react_native_paper8.Text, { variant: "bodyLarge", style: { color: colors.onSurface }, children: "How to Play" }),
582
+ /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(import_react_native_paper8.Text, { variant: "bodySmall", numberOfLines: 1, style: { color: colors.onSurfaceVariant }, children: "Replay quick intro" })
583
+ ] })
511
584
  ] })
512
585
  }
513
586
  )
514
587
  ] }),
515
- onShowHowToPlay && /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
516
- import_feedback_press2.TouchableRipple,
517
- {
518
- onPress: () => {
519
- onDismiss();
520
- onShowHowToPlay();
521
- },
522
- style: styles8.toggleButton,
523
- accessibilityLabel: "How to Play",
524
- children: /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)(import_react_native10.View, { style: styles8.toggleContent, children: [
525
- /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(SettingIcon, { source: "help-circle-outline", color: colors.secondary, containerColor: colors.secondaryContainer }),
526
- /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)(import_react_native10.View, { style: styles8.flexShrink, children: [
527
- /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(import_react_native_paper7.Text, { variant: "bodyLarge", style: { color: colors.onSurface }, children: "How to Play" }),
528
- /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(import_react_native_paper7.Text, { variant: "bodySmall", numberOfLines: 1, style: { color: colors.onSurfaceVariant }, children: "Replay the quick intro" })
529
- ] })
588
+ showAppearance && /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)(import_react_native12.View, { style: styles9.section, children: [
589
+ /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(import_react_native_paper8.Text, { variant: "labelMedium", style: [styles9.sectionLabel, { color: colors.onSurfaceVariant }], children: "APPEARANCE" }),
590
+ /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(import_auto_paper8.AutoAppearancePicker, { showLabels: false }),
591
+ showBlur && /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(import_feedback_press2.TouchableRipple, { onPress: () => setThemeSettings({ blur: !themeSettings.blur }), style: styles9.toggleButton, accessibilityLabel: `Blur ${themeSettings.blur ? "on" : "off"}`, children: /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)(import_react_native12.View, { style: styles9.toggleContent, children: [
592
+ /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(SettingIcon, { source: themeSettings.blur ? "blur" : "blur-off", color: themeSettings.blur ? colors.tertiary : colors.onSurfaceVariant, containerColor: themeSettings.blur ? colors.tertiaryContainer : colors.surfaceVariant }),
593
+ /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)(import_react_native12.View, { style: styles9.flexShrink, children: [
594
+ /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(import_react_native_paper8.Text, { variant: "bodyLarge", style: { color: colors.onSurface }, children: "Blur" }),
595
+ /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(import_react_native_paper8.Text, { variant: "bodySmall", numberOfLines: 1, style: { color: colors.onSurfaceVariant }, children: "Frost behind dialogs" })
530
596
  ] })
531
- }
532
- )
533
- ] }),
534
- showAppearance && /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)(import_react_native10.View, { style: styles8.section, children: [
535
- /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(import_react_native_paper7.Text, { variant: "labelMedium", style: [styles8.sectionLabel, { color: colors.onSurfaceVariant }], children: "APPEARANCE" }),
536
- /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(import_auto_paper7.AutoAppearancePicker, { showLabels: false }),
537
- showBlur && /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(import_feedback_press2.TouchableRipple, { onPress: () => setThemeSettings({ blur: !themeSettings.blur }), style: styles8.toggleButton, accessibilityLabel: `Blur ${themeSettings.blur ? "on" : "off"}`, children: /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)(import_react_native10.View, { style: styles8.toggleContent, children: [
538
- /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(SettingIcon, { source: themeSettings.blur ? "blur" : "blur-off", color: themeSettings.blur ? colors.tertiary : colors.onSurfaceVariant, containerColor: themeSettings.blur ? colors.tertiaryContainer : colors.surfaceVariant }),
539
- /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(import_react_native_paper7.Text, { variant: "bodyLarge", style: { color: colors.onSurface }, children: "Blur" })
540
- ] }) })
541
- ] }),
542
- children,
543
- showUpdateCheck && /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)(import_react_native10.View, { style: styles8.section, children: [
544
- /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)(import_react_native_paper7.Text, { variant: "labelSmall", style: [styles8.sectionLabel, { color: colors.onSurfaceVariant }], children: [
545
- "VERSION ",
546
- version,
547
- updateReady ? " \xB7 UPDATE READY" : ""
597
+ ] }) })
548
598
  ] }),
549
- /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(import_feedback_press2.Button, { mode: "outlined", onPress: check, loading: checking, disabled: checking, children: "Check for Updates" })
599
+ children,
600
+ showUpdateCheck && /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)(import_react_native12.View, { style: styles9.section, children: [
601
+ /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)(import_react_native_paper8.Text, { variant: "labelMedium", style: [styles9.sectionLabel, { color: colors.onSurfaceVariant }], children: [
602
+ "VERSION ",
603
+ version,
604
+ updateReady ? " \xB7 UPDATE READY" : ""
605
+ ] }),
606
+ /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(import_feedback_press2.Button, { mode: "outlined", onPress: check, loading: checking, disabled: checking, children: "Check for Updates" })
607
+ ] })
550
608
  ] })
551
- ] }) })
609
+ ] }) }),
610
+ /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(import_react_native12.View, { style: [overlayActionStyles.actions, styles9.footer], children: /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(import_feedback_press2.Button, { mode: "contained", onPress: onDismiss, style: overlayActionStyles.actionButtonSingle, buttonColor: colors.primary, textColor: colors.onPrimary, children: "Done" }) })
552
611
  ] }),
553
- /* @__PURE__ */ (0, import_jsx_runtime9.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) }),
554
- /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(ConfirmDialog, { visible: !!infoMessage, title: infoMessage?.title ?? "", message: infoMessage?.message ?? "", confirmLabel: "OK", icon: "information-outline", rotation: 0, onConfirm: () => setInfoMessage(null) })
612
+ /* @__PURE__ */ (0, import_jsx_runtime10.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) }),
613
+ /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(ConfirmDialog, { visible: !!infoMessage, title: infoMessage?.title ?? "", message: infoMessage?.message ?? "", confirmLabel: "OK", icon: "information-outline", rotation: 0, onConfirm: () => setInfoMessage(null) })
555
614
  ] }) });
556
615
  }
557
- var styles8 = import_react_native10.StyleSheet.create({
616
+ var SHEET_GUTTER = 24;
617
+ var styles9 = import_react_native12.StyleSheet.create({
618
+ // The rows' sections, 24pt apart.
558
619
  content: {
559
- gap: 24,
560
- paddingVertical: 20
620
+ gap: 24
561
621
  },
562
622
  // Caps the card so it never grows past the screen - without this the dialog just keeps
563
623
  // growing to fit its content and the overflow gets clipped by the screen edge, which is
@@ -569,6 +629,11 @@ var styles8 = import_react_native10.StyleSheet.create({
569
629
  flexShrink: {
570
630
  flexShrink: 1
571
631
  },
632
+ // The overlay cards' 24pt padding, as the sheet's own insets (its scroll area pads 24 sideways).
633
+ footer: {
634
+ paddingBottom: 24,
635
+ paddingHorizontal: 24
636
+ },
572
637
  iconBadge: {
573
638
  alignItems: "center",
574
639
  borderRadius: 10,
@@ -576,9 +641,20 @@ var styles8 = import_react_native10.StyleSheet.create({
576
641
  justifyContent: "center",
577
642
  width: 36
578
643
  },
644
+ // No hairline dividers above and below the scroll area (Paper's MD2-era borders): none of the
645
+ // fleet's other dialogs draws one, so the sheet matches them (Jay, 2026-10-15).
579
646
  scrollArea: {
647
+ borderBottomWidth: 0,
648
+ borderTopWidth: 0,
580
649
  marginBottom: 0
581
650
  },
651
+ // The header and the rows scroll together: the card's 24pt inset above the header, the overlay
652
+ // cards' 16pt gap between it and the rows, and 16pt below the last row before the Done row.
653
+ scrollContent: {
654
+ gap: 16,
655
+ paddingBottom: 16,
656
+ paddingTop: 24
657
+ },
582
658
  section: {
583
659
  gap: 12
584
660
  },
@@ -622,31 +698,31 @@ var styles8 = import_react_native10.StyleSheet.create({
622
698
  });
623
699
 
624
700
  // src/BaseStatsScreen.tsx
625
- var import_auto_paper8 = require("@rific/auto-paper");
701
+ var import_auto_paper9 = require("@rific/auto-paper");
626
702
  var import_feedback_press3 = require("@rific/feedback-press");
627
- var import_core4 = require("@tastic/core");
628
- var import_react5 = require("react");
629
- var import_react_native11 = require("react-native");
630
- var import_react_native_paper8 = require("react-native-paper");
631
- var import_jsx_runtime10 = require("react/jsx-runtime");
703
+ var import_core5 = require("@tastic/core");
704
+ var import_react6 = require("react");
705
+ var import_react_native13 = require("react-native");
706
+ var import_react_native_paper9 = require("react-native-paper");
707
+ var import_jsx_runtime11 = require("react/jsx-runtime");
632
708
  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 }) {
633
- const { dark, colors } = (0, import_auto_paper8.useAutoPaperTheme)();
634
- const ambientRotation = (0, import_core4.useRotation)();
709
+ const { dark, colors } = (0, import_auto_paper9.useAutoPaperTheme)();
710
+ const ambientRotation = (0, import_core5.useRotation)();
635
711
  const rotation = rotationOverride ?? ambientRotation;
636
- const [confirmResetVisible, setConfirmResetVisible] = (0, import_react5.useState)(false);
712
+ const [confirmResetVisible, setConfirmResetVisible] = (0, import_react6.useState)(false);
637
713
  const showReset = !!onReset;
638
714
  const fg = fgOverride ?? (dark ? "#FFFFFF" : "#000000");
639
715
  const bg = bgOverride ?? (dark ? "#000000" : "#FFFFFF");
640
- return /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)(import_react_native11.View, { style: [styles9.container, { backgroundColor: bg }], children: [
641
- /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)(import_react_native11.View, { style: [styles9.header, { paddingTop: 8 + insets.top, paddingLeft: 8 + insets.left }], children: [
642
- /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(import_feedback_press3.IconButton, { icon: "arrow-left", iconColor: fg, size: 24, onPress: onBack }),
643
- /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(import_react_native_paper8.Text, { variant: titleVariant, style: [styles9.title, { color: fg }], children: title })
716
+ return /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)(import_react_native13.View, { style: [styles10.container, { backgroundColor: bg }], children: [
717
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)(import_react_native13.View, { style: [styles10.header, { paddingTop: 8 + insets.top, paddingLeft: 8 + insets.left }], children: [
718
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(import_feedback_press3.IconButton, { icon: "arrow-left", iconColor: fg, size: 24, onPress: onBack }),
719
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(import_react_native_paper9.Text, { variant: titleVariant, style: [styles10.title, { color: fg }], children: title })
644
720
  ] }),
645
- /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)(import_react_native11.ScrollView, { style: styles9.scrollView, contentContainerStyle: [styles9.content, { paddingBottom: 32 + insets.bottom }], showsVerticalScrollIndicator: false, children: [
721
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)(import_react_native13.ScrollView, { style: styles10.scrollView, contentContainerStyle: [styles10.content, { paddingBottom: 32 + insets.bottom }], showsVerticalScrollIndicator: false, children: [
646
722
  children,
647
- showReset && /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(import_feedback_press3.Button, { mode: "contained", onPress: () => setConfirmResetVisible(true), buttonColor: colors.danger, textColor: colors.onDanger, style: styles9.resetButton, children: resetLabel })
723
+ showReset && /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(import_feedback_press3.Button, { mode: "contained", onPress: () => setConfirmResetVisible(true), buttonColor: colors.danger, textColor: colors.onDanger, style: styles10.resetButton, children: resetLabel })
648
724
  ] }),
649
- /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
725
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
650
726
  ConfirmDialog,
651
727
  {
652
728
  visible: confirmResetVisible,
@@ -666,7 +742,7 @@ function BaseStatsScreen({ rotation: rotationOverride, title = "Achievements", t
666
742
  )
667
743
  ] });
668
744
  }
669
- var styles9 = import_react_native11.StyleSheet.create({
745
+ var styles10 = import_react_native13.StyleSheet.create({
670
746
  container: {
671
747
  flex: 1
672
748
  },
@@ -697,19 +773,19 @@ var styles9 = import_react_native11.StyleSheet.create({
697
773
  });
698
774
 
699
775
  // src/ContentGutter.tsx
700
- var import_core5 = require("@tastic/core");
701
- var import_react_native12 = require("react-native");
702
- var import_jsx_runtime11 = require("react/jsx-runtime");
776
+ var import_core6 = require("@tastic/core");
777
+ var import_react_native14 = require("react-native");
778
+ var import_jsx_runtime12 = require("react/jsx-runtime");
703
779
  function ContentGutter({ maxContentWidth, leftGutter, rightGutter, style, children }) {
704
- const { width: windowWidth } = (0, import_core5.useRotatedWindowDimensions)();
705
- const { contentWidth, gutterWidth } = (0, import_core5.computeContentBounds)(windowWidth, maxContentWidth ?? Infinity);
706
- return /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)(import_react_native12.View, { style: [styles10.row, style], children: [
707
- /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(import_react_native12.View, { style: [styles10.gutter, { width: gutterWidth }], children: leftGutter }),
708
- /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(import_react_native12.View, { style: { width: contentWidth }, children }),
709
- /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(import_react_native12.View, { style: [styles10.gutter, { width: gutterWidth }], children: rightGutter })
780
+ const { width: windowWidth } = (0, import_core6.useRotatedWindowDimensions)();
781
+ const { contentWidth, gutterWidth } = (0, import_core6.computeContentBounds)(windowWidth, maxContentWidth ?? Infinity);
782
+ return /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)(import_react_native14.View, { style: [styles11.row, style], children: [
783
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(import_react_native14.View, { style: [styles11.gutter, { width: gutterWidth }], children: leftGutter }),
784
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(import_react_native14.View, { style: { width: contentWidth }, children }),
785
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(import_react_native14.View, { style: [styles11.gutter, { width: gutterWidth }], children: rightGutter })
710
786
  ] });
711
787
  }
712
- var styles10 = import_react_native12.StyleSheet.create({
788
+ var styles11 = import_react_native14.StyleSheet.create({
713
789
  // overflow:'hidden' keeps an oversized leftGutter/rightGutter from bleeding into the content
714
790
  // column instead of clipping cleanly at its own real width.
715
791
  gutter: {
@@ -722,15 +798,15 @@ var styles10 = import_react_native12.StyleSheet.create({
722
798
 
723
799
  // src/CornerActionButtons.tsx
724
800
  var import_feedback_press4 = require("@rific/feedback-press");
725
- var import_react_native13 = require("react-native");
726
- var import_jsx_runtime12 = require("react/jsx-runtime");
801
+ var import_react_native15 = require("react-native");
802
+ var import_jsx_runtime13 = require("react/jsx-runtime");
727
803
  function CornerActionButtons({ onBack, onSettings, fg, insets, backIcon = "arrow-left", backLabel = "Back", hitSlop }) {
728
- return /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)(import_jsx_runtime12.Fragment, { children: [
729
- /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(import_feedback_press4.IconButton, { icon: backIcon, iconColor: fg, size: 24, style: [styles11.back, { top: 8 + insets.top, left: 8 + insets.left }], hitSlop, onPress: onBack, accessibilityLabel: backLabel }),
730
- /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(import_feedback_press4.IconButton, { icon: "cog", iconColor: fg, size: 24, style: [styles11.topRight, { top: 8 + insets.top, right: 8 + insets.right }], hitSlop, onPress: onSettings, accessibilityLabel: "Settings" })
804
+ return /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)(import_jsx_runtime13.Fragment, { children: [
805
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(import_feedback_press4.IconButton, { icon: backIcon, iconColor: fg, size: 24, style: [styles12.back, { top: 8 + insets.top, left: 8 + insets.left }], hitSlop, onPress: onBack, accessibilityLabel: backLabel }),
806
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(import_feedback_press4.IconButton, { icon: "cog", iconColor: fg, size: 24, style: [styles12.topRight, { top: 8 + insets.top, right: 8 + insets.right }], hitSlop, onPress: onSettings, accessibilityLabel: "Settings" })
731
807
  ] });
732
808
  }
733
- var styles11 = import_react_native13.StyleSheet.create({
809
+ var styles12 = import_react_native15.StyleSheet.create({
734
810
  back: {
735
811
  position: "absolute"
736
812
  },
@@ -740,10 +816,10 @@ var styles11 = import_react_native13.StyleSheet.create({
740
816
  });
741
817
 
742
818
  // src/StaggeredWord.tsx
743
- var import_react6 = require("react");
744
- var import_react_native14 = require("react-native");
819
+ var import_react7 = require("react");
820
+ var import_react_native16 = require("react-native");
745
821
  var import_react_native_reanimated = __toESM(require("react-native-reanimated"));
746
- var import_jsx_runtime13 = require("react/jsx-runtime");
822
+ var import_jsx_runtime14 = require("react/jsx-runtime");
747
823
  var STAGGER_MS = 45;
748
824
  var LETTER_DURATION_MS = 320;
749
825
  function getStaggeredWordDuration(letterCount) {
@@ -751,7 +827,7 @@ function getStaggeredWordDuration(letterCount) {
751
827
  }
752
828
  function AnimatedLetter({ char, index, color, reducedMotion, fontFamily, fontSize, lineHeight, fontWeight, letterSpacing }) {
753
829
  const progress = (0, import_react_native_reanimated.useSharedValue)(reducedMotion ? 1 : 0);
754
- (0, import_react6.useEffect)(() => {
830
+ (0, import_react7.useEffect)(() => {
755
831
  if (reducedMotion) return;
756
832
  progress.value = (0, import_react_native_reanimated.withDelay)(index * STAGGER_MS, (0, import_react_native_reanimated.withTiming)(1, { duration: LETTER_DURATION_MS, easing: import_react_native_reanimated.Easing.out(import_react_native_reanimated.Easing.back(1.5)) }));
757
833
  }, [reducedMotion]);
@@ -759,12 +835,12 @@ function AnimatedLetter({ char, index, color, reducedMotion, fontFamily, fontSiz
759
835
  opacity: progress.value,
760
836
  transform: [{ translateY: (1 - progress.value) * 12 }, { scale: 0.85 + progress.value * 0.15 }]
761
837
  }));
762
- return /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(import_react_native_reanimated.default.Text, { allowFontScaling: false, style: [{ color, fontFamily, fontSize, lineHeight, fontWeight, letterSpacing }, style], children: char });
838
+ return /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(import_react_native_reanimated.default.Text, { allowFontScaling: false, style: [{ color, fontFamily, fontSize, lineHeight, fontWeight, letterSpacing }, style], children: char });
763
839
  }
764
840
  function StaggeredWord({ word, color, fontFamily, fontSize, lineHeight, reducedMotion, startIndex = 0, fontWeight = "bold", letterSpacing, style, onLayout }) {
765
- return /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(import_react_native14.View, { style: [styles12.row, style], onLayout, children: word.split("").map((char, i) => /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(AnimatedLetter, { char, index: startIndex + i, color, reducedMotion, fontFamily, fontSize, lineHeight, fontWeight, letterSpacing }, i)) });
841
+ return /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(import_react_native16.View, { style: [styles13.row, style], onLayout, children: word.split("").map((char, i) => /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(AnimatedLetter, { char, index: startIndex + i, color, reducedMotion, fontFamily, fontSize, lineHeight, fontWeight, letterSpacing }, i)) });
766
842
  }
767
- var styles12 = import_react_native14.StyleSheet.create({
843
+ var styles13 = import_react_native16.StyleSheet.create({
768
844
  row: {
769
845
  flexDirection: "row"
770
846
  }
@@ -772,12 +848,12 @@ var styles12 = import_react_native14.StyleSheet.create({
772
848
 
773
849
  // src/UpdateDialog.tsx
774
850
  var import_updater2 = require("@rific/updater");
775
- var import_jsx_runtime14 = require("react/jsx-runtime");
851
+ var import_jsx_runtime15 = require("react/jsx-runtime");
776
852
  function UpdateDialog({ rotation = 0, autoCheck = true, autoPrompt = true, onError }) {
777
853
  const { manifest, onConfirm, respond } = useUpdateConfirmBridge();
778
854
  (0, import_updater2.useUpdater)({ autoCheck, autoPrompt, onConfirm, onError });
779
855
  const date = manifest ? new Date(manifest.createdAt) : null;
780
- return /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(ConfirmDialog, { visible: !!manifest, title: "Update Available", message: date ? `Released ${date.toLocaleDateString()} at ${date.toLocaleTimeString()}` : "", confirmLabel: "Restart", cancelLabel: "Later", icon: "update", rotation, onConfirm: () => respond(true), onCancel: () => respond(false) });
856
+ return /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(ConfirmDialog, { visible: !!manifest, title: "Update Available", message: date ? `Released ${date.toLocaleDateString()} at ${date.toLocaleTimeString()}` : "", confirmLabel: "Restart", cancelLabel: "Later", icon: "update", rotation, onConfirm: () => respond(true), onCancel: () => respond(false) });
781
857
  }
782
858
  // Annotate the CommonJS export names for ESM import in node:
783
859
  0 && (module.exports = {
@@ -786,9 +862,11 @@ function UpdateDialog({ rotation = 0, autoCheck = true, autoPrompt = true, onErr
786
862
  ActivityStatSection,
787
863
  BaseSettingsDialog,
788
864
  BaseStatsScreen,
865
+ COMPACT_DIALOG_HEIGHT,
789
866
  ConfirmDialog,
790
867
  ContentGutter,
791
868
  CornerActionButtons,
869
+ DialogHeader,
792
870
  LOCKED_BADGE_COLOR,
793
871
  MONO_FONT,
794
872
  OverlayBackdrop,
@@ -798,9 +876,10 @@ function UpdateDialog({ rotation = 0, autoCheck = true, autoPrompt = true, onErr
798
876
  StatRow,
799
877
  StatSection,
800
878
  UpdateDialog,
801
- getOverlayCardColors,
802
879
  getStaggeredWordDuration,
880
+ isCompactDialogHeight,
803
881
  overlayActionStyles,
804
882
  overlayStyles,
883
+ useCompactDialog,
805
884
  useOverlayCardColors
806
885
  });