@tastic/hud 0.8.1 → 0.8.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.mjs CHANGED
@@ -74,10 +74,43 @@ var styles = StyleSheet.create({
74
74
  import { AutoAppearancePicker, Dialog, useAutoPaperTheme as useAutoPaperTheme2 } from "@rific/auto-paper";
75
75
  import { Button, SoundContext, TouchableRipple, useHapticSettings, useSoundSettings, useVibration } from "@rific/feedback-press";
76
76
  import { useUpdater } from "@rific/updater";
77
- import { useIsTouchPrimaryDevice, useRotation } from "@tastic/core";
77
+ import { toRotationStyle, useIsTouchPrimaryDevice, useRotation } from "@tastic/core";
78
78
  import { useContext, useState } from "react";
79
- import { Platform, ScrollView, StyleSheet as StyleSheet2, View as View2 } from "react-native";
79
+ import { Platform, ScrollView, StyleSheet as StyleSheet3, View as View2 } from "react-native";
80
80
  import { Icon as Icon2, Portal, Text as Text2 } from "react-native-paper";
81
+
82
+ // src/overlayCard.ts
83
+ import { StyleSheet as StyleSheet2 } from "react-native";
84
+ function getOverlayCardColors(dark) {
85
+ return {
86
+ fg: dark ? "#FFFFFF" : "#000000",
87
+ fgMuted: dark ? "rgba(255,255,255,0.4)" : "rgba(0,0,0,0.4)",
88
+ cardBg: dark ? "#111111" : "#F2F2F2",
89
+ cardBorder: dark ? "rgba(255,255,255,0.2)" : "rgba(0,0,0,0.2)"
90
+ };
91
+ }
92
+ var overlayStyles = StyleSheet2.create({
93
+ card: {
94
+ alignItems: "center",
95
+ borderRadius: 20,
96
+ borderWidth: 1,
97
+ gap: 16,
98
+ maxWidth: 360,
99
+ padding: 32
100
+ },
101
+ overlay: {
102
+ alignItems: "center",
103
+ backgroundColor: "rgba(0,0,0,0.72)",
104
+ bottom: 0,
105
+ justifyContent: "center",
106
+ left: 0,
107
+ position: "absolute",
108
+ right: 0,
109
+ top: 0
110
+ }
111
+ });
112
+
113
+ // src/BaseSettingsDialog.tsx
81
114
  import { Fragment, jsx as jsx2, jsxs as jsxs2 } from "react/jsx-runtime";
82
115
  function SettingIcon({ source, color, containerColor }) {
83
116
  return /* @__PURE__ */ jsx2(View2, { style: [styles2.iconBadge, { backgroundColor: containerColor }], children: /* @__PURE__ */ jsx2(Icon2, { source, size: 18, color }) });
@@ -104,11 +137,9 @@ function BaseSettingsDialog({ visible, onDismiss, rotation: rotationOverride, ve
104
137
  const showSound = !hideSound;
105
138
  const showAppearance = !hideAppearance;
106
139
  const showUpdateCheck = Platform.OS !== "web" && !hideUpdateCheck;
107
- const fg = dark ? "#FFFFFF" : "#000000";
108
- const cardBg = dark ? "#111111" : "#F2F2F2";
109
- const cardBorder = dark ? "rgba(255,255,255,0.2)" : "rgba(0,0,0,0.2)";
140
+ const { fg, cardBg, cardBorder } = getOverlayCardColors(dark);
110
141
  return /* @__PURE__ */ jsxs2(Fragment, { children: [
111
- /* @__PURE__ */ jsxs2(Dialog, { visible, onDismiss, style: [styles2.dialog, rotation % 360 !== 0 && { transform: [{ rotate: `${rotation}deg` }] }], children: [
142
+ /* @__PURE__ */ jsxs2(Dialog, { visible, onDismiss, style: [styles2.dialog, toRotationStyle(rotation)], children: [
112
143
  /* @__PURE__ */ jsx2(Dialog.Title, { children: "Settings" }),
113
144
  /* @__PURE__ */ jsx2(Dialog.ScrollArea, { style: styles2.scrollArea, children: /* @__PURE__ */ jsxs2(ScrollView, { contentContainerStyle: styles2.content, showsVerticalScrollIndicator: false, children: [
114
145
  /* @__PURE__ */ jsxs2(View2, { style: styles2.toggleGroup, children: [
@@ -178,7 +209,7 @@ function BaseSettingsDialog({ visible, onDismiss, rotation: rotationOverride, ve
178
209
  ] })
179
210
  ] }) })
180
211
  ] }),
181
- infoMessage && /* @__PURE__ */ jsx2(Portal, { children: /* @__PURE__ */ jsx2(View2, { style: styles2.overlay, children: /* @__PURE__ */ jsxs2(View2, { style: [styles2.overlayCard, { backgroundColor: cardBg, borderColor: cardBorder }, rotation % 360 !== 0 && { transform: [{ rotate: `${rotation}deg` }] }], children: [
212
+ infoMessage && /* @__PURE__ */ jsx2(Portal, { children: /* @__PURE__ */ jsx2(View2, { style: overlayStyles.overlay, children: /* @__PURE__ */ jsxs2(View2, { style: [overlayStyles.card, { backgroundColor: cardBg, borderColor: cardBorder }, toRotationStyle(rotation)], children: [
182
213
  /* @__PURE__ */ jsx2(Icon2, { source: "information-outline", size: 64, color: colors.secondary }),
183
214
  /* @__PURE__ */ jsx2(Text2, { variant: "headlineLarge", style: [styles2.overlayTitle, { color: colors.secondary }], children: infoMessage.title }),
184
215
  /* @__PURE__ */ jsx2(Text2, { variant: "bodyLarge", style: [styles2.overlayBody, { color: fg }], children: infoMessage.message }),
@@ -186,7 +217,7 @@ function BaseSettingsDialog({ visible, onDismiss, rotation: rotationOverride, ve
186
217
  ] }) }) })
187
218
  ] });
188
219
  }
189
- var styles2 = StyleSheet2.create({
220
+ var styles2 = StyleSheet3.create({
190
221
  content: {
191
222
  gap: 24,
192
223
  paddingVertical: 20
@@ -208,26 +239,8 @@ var styles2 = StyleSheet2.create({
208
239
  justifyContent: "center",
209
240
  width: 36
210
241
  },
211
- overlay: {
212
- alignItems: "center",
213
- backgroundColor: "rgba(0,0,0,0.72)",
214
- bottom: 0,
215
- justifyContent: "center",
216
- left: 0,
217
- position: "absolute",
218
- right: 0,
219
- top: 0
220
- },
221
242
  overlayBody: { textAlign: "center" },
222
243
  overlayButton: { width: 160 },
223
- overlayCard: {
224
- alignItems: "center",
225
- borderRadius: 20,
226
- borderWidth: 1,
227
- gap: 16,
228
- maxWidth: 360,
229
- padding: 32
230
- },
231
244
  overlayTitle: { fontWeight: "bold" },
232
245
  scrollArea: {
233
246
  marginBottom: 0
@@ -275,56 +288,125 @@ var styles2 = StyleSheet2.create({
275
288
  });
276
289
 
277
290
  // src/BaseStatsScreen.tsx
278
- import { useAutoPaperTheme as useAutoPaperTheme3 } from "@rific/auto-paper";
279
- import { Button as Button2, IconButton } from "@rific/feedback-press";
291
+ import { useAutoPaperTheme as useAutoPaperTheme4 } from "@rific/auto-paper";
292
+ import { Button as Button3, IconButton } from "@rific/feedback-press";
280
293
  import { useRotation as useRotation2 } from "@tastic/core";
281
294
  import { useState as useState2 } from "react";
282
- import { ScrollView as ScrollView2, StyleSheet as StyleSheet3, View as View3 } from "react-native";
295
+ import { ScrollView as ScrollView2, StyleSheet as StyleSheet5, View as View4 } from "react-native";
296
+ import { Text as Text4 } from "react-native-paper";
297
+
298
+ // src/ConfirmDialog.tsx
299
+ import { useAutoPaperTheme as useAutoPaperTheme3 } from "@rific/auto-paper";
300
+ import { Button as Button2 } from "@rific/feedback-press";
301
+ import { toRotationStyle as toRotationStyle2 } from "@tastic/core";
302
+ import { StyleSheet as StyleSheet4, View as View3 } from "react-native";
283
303
  import { Icon as Icon3, Portal as Portal2, Text as Text3 } from "react-native-paper";
284
304
  import { jsx as jsx3, jsxs as jsxs3 } from "react/jsx-runtime";
285
- 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, cardBg: cardBgOverride, accentColor: accentColorOverride, children }) {
305
+ function ConfirmDialog({ visible, title, message, confirmLabel, cancelLabel, onConfirm, onCancel, rotation = 0, icon = "help-circle-outline", destructive = false }) {
286
306
  const { dark, colors } = useAutoPaperTheme3();
307
+ if (!visible) return null;
308
+ const { fg, cardBg, cardBorder } = getOverlayCardColors(dark);
309
+ const accent = destructive ? colors.danger : colors.primary;
310
+ const onAccent = destructive ? colors.onDanger : colors.onPrimary;
311
+ return /* @__PURE__ */ jsx3(Portal2, { children: /* @__PURE__ */ jsx3(View3, { style: [overlayStyles.overlay, styles3.overlay], children: /* @__PURE__ */ jsxs3(View3, { style: [overlayStyles.card, styles3.card, { backgroundColor: cardBg, borderColor: cardBorder }, toRotationStyle2(rotation)], children: [
312
+ /* @__PURE__ */ jsx3(Icon3, { source: icon, size: 64, color: accent }),
313
+ /* @__PURE__ */ jsx3(Text3, { variant: "headlineLarge", style: [styles3.title, { color: accent }], children: title }),
314
+ /* @__PURE__ */ jsx3(Text3, { variant: "bodyLarge", style: [styles3.body, { color: fg }], children: message }),
315
+ /* @__PURE__ */ jsxs3(View3, { style: styles3.actions, children: [
316
+ /* @__PURE__ */ jsx3(Button2, { mode: "outlined", onPress: onCancel, style: styles3.actionButton, children: cancelLabel }),
317
+ /* @__PURE__ */ jsx3(Button2, { mode: "contained", onPress: onConfirm, style: styles3.actionButton, buttonColor: accent, textColor: onAccent, children: confirmLabel })
318
+ ] })
319
+ ] }) }) });
320
+ }
321
+ var styles3 = StyleSheet4.create({
322
+ // flexBasis (not flex: 1's own 0%) is each button's real floor: whenever both fit side by side,
323
+ // flexGrow still splits any leftover width evenly beyond that floor, same visual result as the
324
+ // old flex: 1 on a roomy screen - but a button can never be squeezed narrower than 128, only
325
+ // wrap to its own row instead (see actions' flexWrap below). react-native-paper's Button
326
+ // hardcodes numberOfLines={1} on its label with no override, so a button squeezed under its
327
+ // label's natural width silently ellipsizes ("Cancel" -> "Can...") instead of wrapping - assumed
328
+ // fixable by just giving the row more width, until confirmed live that these two-word labels
329
+ // (Cancel/Reset/New Game) can still lose the truncation fight even with the extra room card's own
330
+ // width fix below provides, on a narrow enough screen. flexBasis is the real fix: past a certain
331
+ // width there's no side-by-side arrangement that fits both buttons at their natural label size,
332
+ // so the layout has to give (stack) rather than the label (truncate).
333
+ actionButton: {
334
+ flexBasis: 128,
335
+ flexGrow: 1
336
+ },
337
+ actions: {
338
+ flexDirection: "row",
339
+ flexWrap: "wrap",
340
+ gap: 12,
341
+ width: "100%"
342
+ },
343
+ body: {
344
+ textAlign: "center"
345
+ },
346
+ // Additive on top of overlayCard's own shared `card` shape (borderRadius/borderWidth/gap/maxWidth/
347
+ // padding) — claims its full allowance instead of just maxWidth alone, which only caps how wide the
348
+ // card is allowed to get - without an explicit width, a flex-centered child sizes to its own content
349
+ // instead of stretching, so the card (and therefore actions below) can end up narrower than the
350
+ // screen actually has room for, needlessly forcing the action row to wrap sooner than it has to.
351
+ card: {
352
+ width: "100%"
353
+ },
354
+ // Additive on top of overlayCard's own shared `overlay` backdrop — gives the card room to breathe
355
+ // from the screen edges now that it reliably stretches to fill its full width allowance (see
356
+ // card's own width comment) - without this, width: '100%' would run the card edge-to-edge on a
357
+ // screen narrower than maxWidth's own 360.
358
+ overlay: {
359
+ paddingHorizontal: 24
360
+ },
361
+ // textAlign is load-bearing, not decorative, once `title` wraps to more than one line - centered
362
+ // within card's own alignItems: 'center' only centers the Text's block as a whole; each wrapped
363
+ // line inside that block still defaults to left-aligned without this.
364
+ title: {
365
+ fontWeight: "bold",
366
+ textAlign: "center"
367
+ }
368
+ });
369
+
370
+ // src/BaseStatsScreen.tsx
371
+ import { jsx as jsx4, jsxs as jsxs4 } from "react/jsx-runtime";
372
+ 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 }) {
373
+ const { dark, colors } = useAutoPaperTheme4();
287
374
  const ambientRotation = useRotation2();
288
375
  const rotation = rotationOverride ?? ambientRotation;
289
376
  const [confirmResetVisible, setConfirmResetVisible] = useState2(false);
290
377
  const showReset = !!onReset;
291
378
  const fg = fgOverride ?? (dark ? "#FFFFFF" : "#000000");
292
379
  const bg = bgOverride ?? (dark ? "#000000" : "#FFFFFF");
293
- const cardBg = cardBgOverride ?? (dark ? "#111111" : "#F2F2F2");
294
- const cardBorder = dark ? "rgba(255,255,255,0.2)" : "rgba(0,0,0,0.2)";
295
- const accentColor = accentColorOverride ?? colors.secondary;
296
- return /* @__PURE__ */ jsxs3(View3, { style: [styles3.container, { backgroundColor: bg }], children: [
297
- /* @__PURE__ */ jsxs3(View3, { style: [styles3.header, { paddingTop: 8 + insets.top, paddingLeft: 8 + insets.left }], children: [
298
- /* @__PURE__ */ jsx3(IconButton, { icon: "arrow-left", iconColor: fg, size: 24, onPress: onBack }),
299
- /* @__PURE__ */ jsx3(Text3, { variant: titleVariant, style: [styles3.title, { color: fg }], children: title })
380
+ return /* @__PURE__ */ jsxs4(View4, { style: [styles4.container, { backgroundColor: bg }], children: [
381
+ /* @__PURE__ */ jsxs4(View4, { style: [styles4.header, { paddingTop: 8 + insets.top, paddingLeft: 8 + insets.left }], children: [
382
+ /* @__PURE__ */ jsx4(IconButton, { icon: "arrow-left", iconColor: fg, size: 24, onPress: onBack }),
383
+ /* @__PURE__ */ jsx4(Text4, { variant: titleVariant, style: [styles4.title, { color: fg }], children: title })
300
384
  ] }),
301
- /* @__PURE__ */ jsxs3(ScrollView2, { style: styles3.scrollView, contentContainerStyle: [styles3.content, { paddingBottom: 32 + insets.bottom }], showsVerticalScrollIndicator: false, children: [
385
+ /* @__PURE__ */ jsxs4(ScrollView2, { style: styles4.scrollView, contentContainerStyle: [styles4.content, { paddingBottom: 32 + insets.bottom }], showsVerticalScrollIndicator: false, children: [
302
386
  children,
303
- showReset && /* @__PURE__ */ jsx3(Button2, { mode: "contained", onPress: () => setConfirmResetVisible(true), buttonColor: colors.secondary, textColor: colors.onSecondary, style: styles3.resetButton, children: resetLabel })
387
+ showReset && /* @__PURE__ */ jsx4(Button3, { mode: "contained", onPress: () => setConfirmResetVisible(true), buttonColor: colors.danger, textColor: colors.onDanger, style: styles4.resetButton, children: resetLabel })
304
388
  ] }),
305
- confirmResetVisible && /* @__PURE__ */ jsx3(Portal2, { children: /* @__PURE__ */ jsx3(View3, { style: [styles3.overlay, rotation % 360 !== 0 && { transform: [{ rotate: `${rotation}deg` }] }], children: /* @__PURE__ */ jsxs3(View3, { style: [styles3.overlayCard, { backgroundColor: cardBg, borderColor: cardBorder }], children: [
306
- /* @__PURE__ */ jsx3(Icon3, { source: "alert-outline", size: 64, color: accentColor }),
307
- /* @__PURE__ */ jsx3(Text3, { variant: "headlineLarge", style: [styles3.overlayTitle, { color: accentColor }], children: resetConfirmTitle }),
308
- /* @__PURE__ */ jsx3(Text3, { variant: "bodyLarge", style: [styles3.overlayBody, { color: fg }], children: resetConfirmBody }),
309
- /* @__PURE__ */ jsx3(Button2, { mode: "contained", onPress: () => setConfirmResetVisible(false), style: styles3.overlayButton, children: "Cancel" }),
310
- /* @__PURE__ */ jsx3(
311
- Button2,
312
- {
313
- mode: "contained",
314
- onPress: () => {
315
- onReset?.();
316
- setConfirmResetVisible(false);
317
- },
318
- style: styles3.overlayButton,
319
- buttonColor: colors.secondary,
320
- textColor: colors.onSecondary,
321
- children: "Reset"
389
+ /* @__PURE__ */ jsx4(
390
+ ConfirmDialog,
391
+ {
392
+ visible: confirmResetVisible,
393
+ title: resetConfirmTitle,
394
+ message: resetConfirmBody,
395
+ confirmLabel: "Reset",
396
+ cancelLabel: "Cancel",
397
+ icon: "alert-outline",
398
+ destructive: true,
399
+ rotation,
400
+ onCancel: () => setConfirmResetVisible(false),
401
+ onConfirm: () => {
402
+ onReset?.();
403
+ setConfirmResetVisible(false);
322
404
  }
323
- )
324
- ] }) }) })
405
+ }
406
+ )
325
407
  ] });
326
408
  }
327
- var styles3 = StyleSheet3.create({
409
+ var styles4 = StyleSheet5.create({
328
410
  container: {
329
411
  flex: 1
330
412
  },
@@ -338,30 +420,6 @@ var styles3 = StyleSheet3.create({
338
420
  gap: 4,
339
421
  paddingBottom: 8
340
422
  },
341
- // Same overlay shape BaseSettingsDialog's own info overlay uses (backdrop + centered card),
342
- // rotated in place the same way rather than via Portal-root transform for the same reason — see
343
- // that component's own identical styles for the full rationale.
344
- overlay: {
345
- alignItems: "center",
346
- backgroundColor: "rgba(0,0,0,0.72)",
347
- bottom: 0,
348
- justifyContent: "center",
349
- left: 0,
350
- position: "absolute",
351
- right: 0,
352
- top: 0
353
- },
354
- overlayBody: { textAlign: "center" },
355
- overlayButton: { width: 160 },
356
- overlayCard: {
357
- alignItems: "center",
358
- borderRadius: 20,
359
- borderWidth: 1,
360
- gap: 16,
361
- maxWidth: 360,
362
- padding: 32
363
- },
364
- overlayTitle: { fontWeight: "bold", marginBottom: -8 },
365
423
  resetButton: {
366
424
  marginTop: 16
367
425
  },
@@ -378,68 +436,9 @@ var styles3 = StyleSheet3.create({
378
436
  }
379
437
  });
380
438
 
381
- // src/ConfirmDialog.tsx
382
- import { useAutoPaperTheme as useAutoPaperTheme4 } from "@rific/auto-paper";
383
- import { Button as Button3 } from "@rific/feedback-press";
384
- import { StyleSheet as StyleSheet4, View as View4 } from "react-native";
385
- import { Icon as Icon4, Portal as Portal3, Text as Text4 } from "react-native-paper";
386
- import { jsx as jsx4, jsxs as jsxs4 } from "react/jsx-runtime";
387
- function ConfirmDialog({ visible, title, message, confirmLabel, cancelLabel, onConfirm, onCancel, rotation = 0, icon = "help-circle-outline", destructive = false }) {
388
- const { dark, colors } = useAutoPaperTheme4();
389
- if (!visible) return null;
390
- const fg = dark ? "#FFFFFF" : "#000000";
391
- const cardBg = dark ? "#111111" : "#F2F2F2";
392
- const cardBorder = dark ? "rgba(255,255,255,0.2)" : "rgba(0,0,0,0.2)";
393
- const accent = destructive ? colors.danger : colors.primary;
394
- const onAccent = destructive ? colors.onDanger : colors.onPrimary;
395
- return /* @__PURE__ */ jsx4(Portal3, { children: /* @__PURE__ */ jsx4(View4, { style: styles4.overlay, children: /* @__PURE__ */ jsxs4(View4, { style: [styles4.card, { backgroundColor: cardBg, borderColor: cardBorder }, rotation % 360 !== 0 && { transform: [{ rotate: `${rotation}deg` }] }], children: [
396
- /* @__PURE__ */ jsx4(Icon4, { source: icon, size: 64, color: accent }),
397
- /* @__PURE__ */ jsx4(Text4, { variant: "headlineLarge", style: [styles4.title, { color: accent }], children: title }),
398
- /* @__PURE__ */ jsx4(Text4, { variant: "bodyLarge", style: [styles4.body, { color: fg }], children: message }),
399
- /* @__PURE__ */ jsxs4(View4, { style: styles4.actions, children: [
400
- /* @__PURE__ */ jsx4(Button3, { mode: "outlined", onPress: onCancel, style: styles4.actionButton, children: cancelLabel }),
401
- /* @__PURE__ */ jsx4(Button3, { mode: "contained", onPress: onConfirm, style: styles4.actionButton, buttonColor: accent, textColor: onAccent, children: confirmLabel })
402
- ] })
403
- ] }) }) });
404
- }
405
- var styles4 = StyleSheet4.create({
406
- actionButton: {
407
- flex: 1
408
- },
409
- actions: {
410
- flexDirection: "row",
411
- gap: 12,
412
- width: "100%"
413
- },
414
- body: {
415
- textAlign: "center"
416
- },
417
- card: {
418
- alignItems: "center",
419
- borderRadius: 20,
420
- borderWidth: 1,
421
- gap: 16,
422
- maxWidth: 360,
423
- padding: 32
424
- },
425
- overlay: {
426
- alignItems: "center",
427
- backgroundColor: "rgba(0,0,0,0.72)",
428
- bottom: 0,
429
- justifyContent: "center",
430
- left: 0,
431
- position: "absolute",
432
- right: 0,
433
- top: 0
434
- },
435
- title: {
436
- fontWeight: "bold"
437
- }
438
- });
439
-
440
439
  // src/ContentGutter.tsx
441
440
  import { computeContentBounds } from "@tastic/core";
442
- import { StyleSheet as StyleSheet5, useWindowDimensions, View as View5 } from "react-native";
441
+ import { StyleSheet as StyleSheet6, useWindowDimensions, View as View5 } from "react-native";
443
442
  import { jsx as jsx5, jsxs as jsxs5 } from "react/jsx-runtime";
444
443
  function ContentGutter({ maxContentWidth, leftGutter, rightGutter, style, children }) {
445
444
  const { width: windowWidth } = useWindowDimensions();
@@ -450,7 +449,7 @@ function ContentGutter({ maxContentWidth, leftGutter, rightGutter, style, childr
450
449
  /* @__PURE__ */ jsx5(View5, { style: [styles5.gutter, { width: gutterWidth }], children: rightGutter })
451
450
  ] });
452
451
  }
453
- var styles5 = StyleSheet5.create({
452
+ var styles5 = StyleSheet6.create({
454
453
  // overflow:'hidden' keeps an oversized leftGutter/rightGutter from bleeding into the content
455
454
  // column instead of clipping cleanly at its own real width.
456
455
  gutter: {
@@ -469,15 +468,15 @@ import { Platform as Platform3 } from "react-native";
469
468
  import { getBlendedColor, getColorRoles } from "@rific/auto-paper";
470
469
  import { IconButton as IconButton2, TouchableRipple as TouchableRipple2 } from "@rific/feedback-press";
471
470
  import { useRotation as useRotation3 } from "@tastic/core";
472
- import { ScrollView as ScrollView3, StyleSheet as StyleSheet7, View as View8 } from "react-native";
473
- import { Icon as Icon5, Text as Text5 } from "react-native-paper";
471
+ import { ScrollView as ScrollView3, StyleSheet as StyleSheet8, View as View8 } from "react-native";
472
+ import { Icon as Icon4, Text as Text5 } from "react-native-paper";
474
473
 
475
474
  // src/fonts.ts
476
475
  import { Platform as Platform2 } from "react-native";
477
476
  var MONO_FONT = Platform2.select({ ios: "Menlo", android: "monospace", default: "monospace" });
478
477
 
479
478
  // src/PopoverBody.tsx
480
- import { StyleSheet as StyleSheet6, View as View6 } from "react-native";
479
+ import { StyleSheet as StyleSheet7, View as View6 } from "react-native";
481
480
  import { Fragment as Fragment2, jsx as jsx6, jsxs as jsxs6 } from "react/jsx-runtime";
482
481
  var CARET_SIZE = 7;
483
482
  var CARET_RING_OFFSET = 2;
@@ -500,7 +499,7 @@ function PopoverBody({ visible, children, align = "center", verticalAlign = "bel
500
499
  ] })
501
500
  ] });
502
501
  }
503
- var styles6 = StyleSheet6.create({
502
+ var styles6 = StyleSheet7.create({
504
503
  caret: {
505
504
  borderLeftColor: "transparent",
506
505
  borderRightColor: "transparent",
@@ -689,7 +688,7 @@ function SingleSection({
689
688
  const labelStyle = { fontFamily: labelFontFamily, color: rowColor, fontWeight: selected ? "bold" : "normal" };
690
689
  const descriptionStyle = { fontFamily: labelFontFamily, color: rowColor };
691
690
  return /* @__PURE__ */ jsx8(TouchableRipple2, { disabled: taken, onPress: () => onSelect(option.value), style: itemStyle, children: /* @__PURE__ */ jsxs7(View8, { style: styles7.itemRow, children: [
692
- option.icon && /* @__PURE__ */ jsx8(Icon5, { source: option.icon, size: MENU_ITEM_ICON_SIZE, color: rowColor }),
691
+ option.icon && /* @__PURE__ */ jsx8(Icon4, { source: option.icon, size: MENU_ITEM_ICON_SIZE, color: rowColor }),
693
692
  /* @__PURE__ */ jsxs7(View8, { style: styles7.itemLabelColumn, children: [
694
693
  /* @__PURE__ */ jsx8(Text5, { variant: "labelLarge", style: labelStyle, children: option.label }),
695
694
  option.description && /* @__PURE__ */ jsx8(Text5, { variant: "labelSmall", style: descriptionStyle, children: option.description })
@@ -715,14 +714,14 @@ function MultiSection({
715
714
  const itemStyle = [styles7.item, selected && { backgroundColor: accentColor }, prevSelected && { borderTopLeftRadius: 0, borderTopRightRadius: 0 }, nextSelected && { borderBottomLeftRadius: 0, borderBottomRightRadius: 0 }];
716
715
  const labelStyle = { fontFamily: labelFontFamily, color: rowColor, fontWeight: selected ? "bold" : "normal" };
717
716
  return /* @__PURE__ */ jsx8(TouchableRipple2, { onPress: () => section.onChange(selected ? section.value.filter((v) => v !== option.value) : [...section.value, option.value]), style: itemStyle, children: /* @__PURE__ */ jsxs7(View8, { style: styles7.itemRow, children: [
718
- option.icon && /* @__PURE__ */ jsx8(Icon5, { source: option.icon, size: MENU_ITEM_ICON_SIZE, color: rowColor }),
717
+ option.icon && /* @__PURE__ */ jsx8(Icon4, { source: option.icon, size: MENU_ITEM_ICON_SIZE, color: rowColor }),
719
718
  /* @__PURE__ */ jsx8(Text5, { variant: "labelLarge", style: [styles7.itemLabelFlex, labelStyle], children: option.label })
720
719
  ] }) }, option.value);
721
720
  }),
722
721
  section.allClear && /* @__PURE__ */ jsx8(TouchableRipple2, { onPress: () => section.onChange(allSelected ? [] : section.options.map((o) => o.value)), style: styles7.item, children: /* @__PURE__ */ jsx8(Text5, { variant: "labelLarge", style: [styles7.allClearLabel, { fontFamily: labelFontFamily, color: accentColor }], children: allSelected ? allClearLabels.clear : allClearLabels.all }) })
723
722
  ] });
724
723
  }
725
- var styles7 = StyleSheet7.create({
724
+ var styles7 = StyleSheet8.create({
726
725
  allClearLabel: {
727
726
  fontWeight: "bold",
728
727
  textAlign: "center"
@@ -739,7 +738,7 @@ var styles7 = StyleSheet7.create({
739
738
  zIndex: 100
740
739
  },
741
740
  divider: {
742
- height: StyleSheet7.hairlineWidth,
741
+ height: StyleSheet8.hairlineWidth,
743
742
  marginVertical: 4
744
743
  },
745
744
  item: {
@@ -801,7 +800,7 @@ function ControlSchemePicker({ id, host, value, onChange, options, takenValue, a
801
800
 
802
801
  // src/CornerActionButtons.tsx
803
802
  import { IconButton as IconButton3 } from "@rific/feedback-press";
804
- import { StyleSheet as StyleSheet8 } from "react-native";
803
+ import { StyleSheet as StyleSheet9 } from "react-native";
805
804
  import { Fragment as Fragment4, jsx as jsx10, jsxs as jsxs8 } from "react/jsx-runtime";
806
805
  function CornerActionButtons({ onBack, onSettings, fg, insets, backIcon = "arrow-left", backLabel = "Back" }) {
807
806
  return /* @__PURE__ */ jsxs8(Fragment4, { children: [
@@ -809,7 +808,7 @@ function CornerActionButtons({ onBack, onSettings, fg, insets, backIcon = "arrow
809
808
  /* @__PURE__ */ jsx10(IconButton3, { icon: "cog", iconColor: fg, size: 24, style: [styles8.topRight, { top: 8 + insets.top, right: 8 + insets.right }], onPress: onSettings, accessibilityLabel: "Settings" })
810
809
  ] });
811
810
  }
812
- var styles8 = StyleSheet8.create({
811
+ var styles8 = StyleSheet9.create({
813
812
  back: {
814
813
  position: "absolute"
815
814
  },
@@ -819,12 +818,12 @@ var styles8 = StyleSheet8.create({
819
818
  });
820
819
 
821
820
  // src/CornerStatusBadges.tsx
822
- import { StyleSheet as StyleSheet9, View as View9 } from "react-native";
823
- import { Icon as Icon6 } from "react-native-paper";
821
+ import { StyleSheet as StyleSheet10, View as View9 } from "react-native";
822
+ import { Icon as Icon5 } from "react-native-paper";
824
823
  import { Fragment as Fragment5, jsx as jsx11, jsxs as jsxs9 } from "react/jsx-runtime";
825
824
  var BADGE_SIZE = 30;
826
825
  function StatusBadge({ icon }) {
827
- return /* @__PURE__ */ jsx11(View9, { style: styles9.badge, children: icon && /* @__PURE__ */ jsx11(Icon6, { source: icon, size: 16, color: "rgba(255,255,255,0.85)" }) });
826
+ return /* @__PURE__ */ jsx11(View9, { style: styles9.badge, children: icon && /* @__PURE__ */ jsx11(Icon5, { source: icon, size: 16, color: "rgba(255,255,255,0.85)" }) });
828
827
  }
829
828
  function CornerStatusBadges({ orientationMode, p1OnRight, p1, p2 }) {
830
829
  const p1OnRightSide = orientationMode === "sideBySide" && p1OnRight;
@@ -834,7 +833,7 @@ function CornerStatusBadges({ orientationMode, p1OnRight, p1, p2 }) {
834
833
  p2 && /* @__PURE__ */ jsx11(View9, { pointerEvents: "none", style: p2OnLeftSide ? styles9.topLeft : styles9.topRight, children: /* @__PURE__ */ jsx11(StatusBadge, { icon: p2.icon }) })
835
834
  ] });
836
835
  }
837
- var styles9 = StyleSheet9.create({
836
+ var styles9 = StyleSheet10.create({
838
837
  badge: {
839
838
  alignItems: "center",
840
839
  backgroundColor: "rgba(0,0,0,0.28)",
@@ -856,8 +855,8 @@ var styles9 = StyleSheet9.create({
856
855
  import { defaultColors, getContrastColor } from "@rific/auto-paper";
857
856
  import { TouchableRipple as TouchableRipple3 } from "@rific/feedback-press";
858
857
  import { clamp, useRotation as useRotation4 } from "@tastic/core";
859
- import { ScrollView as ScrollView4, StyleSheet as StyleSheet10, useWindowDimensions as useWindowDimensions3, View as View10 } from "react-native";
860
- import { Icon as Icon7, Text as Text6 } from "react-native-paper";
858
+ import { ScrollView as ScrollView4, StyleSheet as StyleSheet11, useWindowDimensions as useWindowDimensions3, View as View10 } from "react-native";
859
+ import { Icon as Icon6, Text as Text6 } from "react-native-paper";
861
860
  import { jsx as jsx12, jsxs as jsxs10 } from "react/jsx-runtime";
862
861
  var EMOJI_PATTERN = /\p{Extended_Pictographic}/u;
863
862
  var DEFAULT_SIZE = 48;
@@ -889,7 +888,7 @@ function InlineColorPicker({ id, host, value, onChange, previewValue, swatches =
889
888
  const contrastColor = getContrastColor(displayValue);
890
889
  const tagFontSize = size * (tag && EMOJI_PATTERN.test(tag) ? 0.6 : 0.4);
891
890
  return /* @__PURE__ */ jsxs10(View10, { style: [styles10.anchor, open && styles10.anchorOpen], children: [
892
- /* @__PURE__ */ jsx12(TouchableRipple3, { onPress: () => host.toggle(id), borderless: true, style: [styles10.trigger, { backgroundColor: displayValue, borderRadius: size / 2, height: size, width: size }], children: /* @__PURE__ */ jsx12(View10, { ref: triggerRef, collapsable: false, style: styles10.triggerMeasure, children: tag ? /* @__PURE__ */ jsx12(Text6, { style: [styles10.tagLabel, { color: contrastColor, fontFamily: labelFontFamily, fontSize: tagFontSize }], numberOfLines: 1, adjustsFontSizeToFit: true, children: tag }) : /* @__PURE__ */ jsx12(Icon7, { source: icon, size: size * 0.6, color: contrastColor }) }) }),
891
+ /* @__PURE__ */ jsx12(TouchableRipple3, { onPress: () => host.toggle(id), borderless: true, style: [styles10.trigger, { backgroundColor: displayValue, borderRadius: size / 2, height: size, width: size }], children: /* @__PURE__ */ jsx12(View10, { ref: triggerRef, collapsable: false, style: styles10.triggerMeasure, children: tag ? /* @__PURE__ */ jsx12(Text6, { style: [styles10.tagLabel, { color: contrastColor, fontFamily: labelFontFamily, fontSize: tagFontSize }], numberOfLines: 1, adjustsFontSizeToFit: true, children: tag }) : /* @__PURE__ */ jsx12(Icon6, { source: icon, size: size * 0.6, color: contrastColor }) }) }),
893
892
  /* @__PURE__ */ jsx12(PopoverBody, { visible: open && measured, align, verticalAlign, caretColor: menuBg, caretBorderColor: displayValue, caretBorderWidth: SWATCHES_BORDER_WIDTH, triggerSize: size, children: /* @__PURE__ */ jsx12(ScrollView4, { style: [styles10.swatches, { backgroundColor: menuBg, borderColor: displayValue, width: swatchesWidth, maxHeight }], contentContainerStyle: styles10.swatchesContent, showsVerticalScrollIndicator: false, children: swatches.map((swatch) => {
894
893
  const selected = swatch.value.toLowerCase() === value.toLowerCase();
895
894
  const taken = !selected && !!takenValue && swatch.value.toLowerCase() === takenValue.toLowerCase();
@@ -905,14 +904,14 @@ function InlineColorPicker({ id, host, value, onChange, previewValue, swatches =
905
904
  },
906
905
  borderless: true,
907
906
  style: [styles10.swatch, { backgroundColor: swatchDisplay }, selected && styles10.swatchSelected, taken && !swappable && styles10.swatchTaken],
908
- children: selected ? /* @__PURE__ */ jsx12(Icon7, { source: "check", size: 16, color: getContrastColor(swatchDisplay) }) : swappable ? /* @__PURE__ */ jsx12(Icon7, { source: "swap-horizontal", size: 16, color: getContrastColor(swatchDisplay) }) : taken ? /* @__PURE__ */ jsx12(Icon7, { source: "close", size: 16, color: getContrastColor(swatchDisplay) }) : /* @__PURE__ */ jsx12(View10, {})
907
+ children: selected ? /* @__PURE__ */ jsx12(Icon6, { source: "check", size: 16, color: getContrastColor(swatchDisplay) }) : swappable ? /* @__PURE__ */ jsx12(Icon6, { source: "swap-horizontal", size: 16, color: getContrastColor(swatchDisplay) }) : taken ? /* @__PURE__ */ jsx12(Icon6, { source: "close", size: 16, color: getContrastColor(swatchDisplay) }) : /* @__PURE__ */ jsx12(View10, {})
909
908
  },
910
909
  swatch.value
911
910
  );
912
911
  }) }) })
913
912
  ] });
914
913
  }
915
- var styles10 = StyleSheet10.create({
914
+ var styles10 = StyleSheet11.create({
916
915
  anchor: {
917
916
  position: "relative"
918
917
  },
@@ -986,8 +985,8 @@ var styles10 = StyleSheet10.create({
986
985
  // src/LabeledDropdown.tsx
987
986
  import { getContrastColor as getContrastColor2 } from "@rific/auto-paper";
988
987
  import { TouchableRipple as TouchableRipple4 } from "@rific/feedback-press";
989
- import { ScrollView as ScrollView5, StyleSheet as StyleSheet11, View as View11 } from "react-native";
990
- import { Icon as Icon8, Text as Text7 } from "react-native-paper";
988
+ import { ScrollView as ScrollView5, StyleSheet as StyleSheet12, View as View11 } from "react-native";
989
+ import { Icon as Icon7, Text as Text7 } from "react-native-paper";
991
990
  import { jsx as jsx13, jsxs as jsxs11 } from "react/jsx-runtime";
992
991
  var TRIGGER_HEIGHT = 28;
993
992
  var POPOVER_WIDTH = 180;
@@ -1014,19 +1013,19 @@ function LabeledDropdown({ id, host, options, value, onChange, color, dark, alig
1014
1013
  return /* @__PURE__ */ jsxs11(View11, { style: [styles11.anchor, open && styles11.anchorOpen], children: [
1015
1014
  /* @__PURE__ */ jsx13(TouchableRipple4, { onPress: () => host.toggle(id), style: styles11.trigger, children: /* @__PURE__ */ jsxs11(View11, { ref: triggerRef, collapsable: false, style: styles11.triggerInner, children: [
1016
1015
  /* @__PURE__ */ jsx13(Text7, { style: [styles11.triggerLabel, { color }], numberOfLines: 1, children: (selected?.label ?? "").toUpperCase() }),
1017
- /* @__PURE__ */ jsx13(Icon8, { source: "menu-down", size: 16, color })
1016
+ /* @__PURE__ */ jsx13(Icon7, { source: "menu-down", size: 16, color })
1018
1017
  ] }) }),
1019
1018
  /* @__PURE__ */ jsx13(PopoverBody, { visible: open && measured, align, verticalAlign, caretColor: menuBg, caretBorderColor: color, caretBorderWidth: 2, triggerSize: TRIGGER_HEIGHT, children: /* @__PURE__ */ jsx13(ScrollView5, { style: [styles11.menu, { backgroundColor: menuBg, borderColor: color, width: POPOVER_WIDTH, maxHeight }], contentContainerStyle: styles11.menuContent, showsVerticalScrollIndicator: false, children: options.map((option) => {
1020
1019
  const isSelected = option.value === value;
1021
1020
  const onColor = getContrastColor2(color);
1022
1021
  return /* @__PURE__ */ jsx13(TouchableRipple4, { onPress: () => handleSelect(option), style: [styles11.row, isSelected && { backgroundColor: color }], children: /* @__PURE__ */ jsxs11(View11, { style: styles11.rowInner, children: [
1023
- option.icon && /* @__PURE__ */ jsx13(Icon8, { source: option.icon, size: 18, color: isSelected ? onColor : fg }),
1022
+ option.icon && /* @__PURE__ */ jsx13(Icon7, { source: option.icon, size: 18, color: isSelected ? onColor : fg }),
1024
1023
  /* @__PURE__ */ jsx13(Text7, { style: [styles11.rowLabel, { color: isSelected ? onColor : fg }], numberOfLines: 1, children: option.label })
1025
1024
  ] }) }, option.value);
1026
1025
  }) }) })
1027
1026
  ] });
1028
1027
  }
1029
- var styles11 = StyleSheet11.create({
1028
+ var styles11 = StyleSheet12.create({
1030
1029
  anchor: {
1031
1030
  position: "relative"
1032
1031
  },
@@ -1084,16 +1083,16 @@ function loadSkiaWeb() {
1084
1083
  }
1085
1084
 
1086
1085
  // src/PressAwayOverlay.tsx
1087
- import { Pressable, StyleSheet as StyleSheet12 } from "react-native";
1086
+ import { Pressable, StyleSheet as StyleSheet13 } from "react-native";
1088
1087
  import { jsx as jsx14 } from "react/jsx-runtime";
1089
1088
  function PressAwayOverlay({ active, onPress, style }) {
1090
1089
  if (!active) return null;
1091
- return /* @__PURE__ */ jsx14(Pressable, { accessibilityLabel: "Dismiss", accessibilityRole: "button", onPress, style: [StyleSheet12.absoluteFill, style] });
1090
+ return /* @__PURE__ */ jsx14(Pressable, { accessibilityLabel: "Dismiss", accessibilityRole: "button", onPress, style: [StyleSheet13.absoluteFill, style] });
1092
1091
  }
1093
1092
 
1094
1093
  // src/ReadyButton.tsx
1095
1094
  import { TouchableRipple as TouchableRipple5 } from "@rific/feedback-press";
1096
- import { StyleSheet as StyleSheet13 } from "react-native";
1095
+ import { StyleSheet as StyleSheet14 } from "react-native";
1097
1096
  import { Text as Text8 } from "react-native-paper";
1098
1097
  import { jsx as jsx15 } from "react/jsx-runtime";
1099
1098
  function ReadyButton({ color, ready, onToggleReady, style, labelFontFamily = MONO_FONT }) {
@@ -1102,7 +1101,7 @@ function ReadyButton({ color, ready, onToggleReady, style, labelFontFamily = MON
1102
1101
  const labelColorStyle = { color: ready ? "#000000" : color };
1103
1102
  return /* @__PURE__ */ jsx15(TouchableRipple5, { onPress: onToggleReady, borderless: true, style: readyButtonStyle, children: /* @__PURE__ */ jsx15(Text8, { variant: "labelLarge", style: [labelTextStyle, labelColorStyle], children: ready ? "READY \u2713" : "READY?" }) });
1104
1103
  }
1105
- var styles12 = StyleSheet13.create({
1104
+ var styles12 = StyleSheet14.create({
1106
1105
  readyButton: {
1107
1106
  alignItems: "center",
1108
1107
  borderRadius: 12,
@@ -1116,7 +1115,7 @@ var styles12 = StyleSheet13.create({
1116
1115
 
1117
1116
  // src/SharedActionBand.tsx
1118
1117
  import { IconButton as IconButton4 } from "@rific/feedback-press";
1119
- import { StyleSheet as StyleSheet14, View as View12 } from "react-native";
1118
+ import { StyleSheet as StyleSheet15, View as View12 } from "react-native";
1120
1119
  import { jsx as jsx16, jsxs as jsxs12 } from "react/jsx-runtime";
1121
1120
  function SharedActionBand({ onBack, onSettings, onRandomize, onReset, fg, popoverOpen, children }) {
1122
1121
  return /* @__PURE__ */ jsxs12(View12, { style: [styles13.column, popoverOpen && styles13.columnOpen], children: [
@@ -1129,7 +1128,7 @@ function SharedActionBand({ onBack, onSettings, onRandomize, onReset, fg, popove
1129
1128
  children
1130
1129
  ] });
1131
1130
  }
1132
- var styles13 = StyleSheet14.create({
1131
+ var styles13 = StyleSheet15.create({
1133
1132
  actionsRow: {
1134
1133
  alignItems: "center",
1135
1134
  flexDirection: "row",
@@ -1146,7 +1145,7 @@ var styles13 = StyleSheet14.create({
1146
1145
 
1147
1146
  // src/StatRow.tsx
1148
1147
  import { useAutoPaperTheme as useAutoPaperTheme5 } from "@rific/auto-paper";
1149
- import { StyleSheet as StyleSheet15, View as View13 } from "react-native";
1148
+ import { StyleSheet as StyleSheet16, View as View13 } from "react-native";
1150
1149
  import { Text as Text9 } from "react-native-paper";
1151
1150
  import { jsx as jsx17, jsxs as jsxs13 } from "react/jsx-runtime";
1152
1151
  function StatRow({ label, value, fg: fgOverride, fgMuted: fgMutedOverride }) {
@@ -1158,7 +1157,7 @@ function StatRow({ label, value, fg: fgOverride, fgMuted: fgMutedOverride }) {
1158
1157
  /* @__PURE__ */ jsx17(Text9, { variant: "bodyMedium", style: [styles14.value, { color: fg }], children: value })
1159
1158
  ] });
1160
1159
  }
1161
- var styles14 = StyleSheet15.create({
1160
+ var styles14 = StyleSheet16.create({
1162
1161
  row: {
1163
1162
  alignItems: "center",
1164
1163
  flexDirection: "row",
@@ -1171,7 +1170,7 @@ var styles14 = StyleSheet15.create({
1171
1170
 
1172
1171
  // src/StatSection.tsx
1173
1172
  import { useAutoPaperTheme as useAutoPaperTheme6 } from "@rific/auto-paper";
1174
- import { StyleSheet as StyleSheet16, View as View14 } from "react-native";
1173
+ import { StyleSheet as StyleSheet17, View as View14 } from "react-native";
1175
1174
  import { Text as Text10 } from "react-native-paper";
1176
1175
  import { jsx as jsx18, jsxs as jsxs14 } from "react/jsx-runtime";
1177
1176
  function StatSection({ label, fg: fgOverride, sectionBg: sectionBgOverride, children }) {
@@ -1183,7 +1182,7 @@ function StatSection({ label, fg: fgOverride, sectionBg: sectionBgOverride, chil
1183
1182
  children
1184
1183
  ] });
1185
1184
  }
1186
- var styles15 = StyleSheet16.create({
1185
+ var styles15 = StyleSheet17.create({
1187
1186
  // Bold and full-contrast (fg), not the original fontless/fgMuted treatment — that read at the
1188
1187
  // same visual weight as StatRow's own row labels below it (both used the identical muted color;
1189
1188
  // letterSpacing/variant alone didn't separate them enough to read as "this is the group header"
@@ -1233,7 +1232,9 @@ export {
1233
1232
  StatSection,
1234
1233
  TriggerGaugeHost,
1235
1234
  getLabeledDropdownContentHeight,
1235
+ getOverlayCardColors,
1236
1236
  loadSkiaWeb,
1237
+ overlayStyles,
1237
1238
  useAutoAlign,
1238
1239
  usePopoverHost
1239
1240
  };