@tastic/hud 0.21.0 → 0.23.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -209,12 +209,16 @@ its own `useGameSettings()` hook internally instead of taking it as props. Snake
209
209
  the fleet with real Redux Toolkit state - reads `lockOrientation`/`deferBottomEdgeGestures` via
210
210
  `useSelector` and writes them back via `dispatch(gameActions.setLockOrientation(...))` directly
211
211
  inside the adapter, with nothing threaded through props at all. `BaseSettingsDialog` doesn't care
212
- which of these an app uses: sound, haptics, appearance, and update-checking are identical across
213
- every app and live entirely inside this package now, so `lockOrientation`/`onLockOrientationChange`,
214
- `deferBottomEdgeGestures`/`onDeferBottomEdgeGestures` and `keepAwake`/`onKeepAwakeChange` are the only
215
- settings an adapter actually needs to source itself, however it does that. Each pair is optional: omit
216
- one and its row doesn't show. The Keep Awake row only toggles the value; the app keeps the screen awake
217
- itself while it's on (for example with `expo-keep-awake` on its match screen).
212
+ which of these an app uses: sound, haptics, appearance, update-checking and Keep Awake are identical
213
+ across every app and read their own shared settings, so `lockOrientation`/`onLockOrientationChange`
214
+ and `deferBottomEdgeGestures`/`onDeferBottomEdgeGestures` are the only settings an adapter actually
215
+ needs to source itself, however it does that. Each pair is optional: omit one and its row doesn't show.
216
+
217
+ The Keep Awake row reads `@rific/core`'s Keep Awake setting (`useKeepAwakeSettings()`), the same way
218
+ the Sound row reads `@rific/feedback-press`. It shows on touch-first devices (where Lock Orientation
219
+ shows) in any app whose `KeepAwakeProvider` was given `expo-keep-awake` (`useExpoKeepAwake()` returns
220
+ it), and is hidden otherwise. The app opts in once at its root and calls `useKeepAwake('game')` on the
221
+ screen that should stay awake; see `@rific/core`'s README for the bridge.
218
222
 
219
223
  Every adapter also passes `version={release.otaVersion}` (so the dialog's own update-check button
220
224
  knows what it's currently running) and `onUpdateError`, wired to a real `useToast()` call. Wire this
@@ -239,8 +243,6 @@ export function SettingsDialog({ visible, onDismiss, rotation = 0, settings, set
239
243
  onLockOrientationChange={(value) => setSettings({ lockOrientation: value })}
240
244
  deferBottomEdgeGestures={settings.deferBottomEdgeGestures}
241
245
  onDeferBottomEdgeGestures={(value) => setSettings({ deferBottomEdgeGestures: value })}
242
- keepAwake={settings.keepAwake}
243
- onKeepAwakeChange={(value) => setSettings({ keepAwake: value })}
244
246
  onUpdateError={(message) => error('Update check failed', message)}
245
247
  />
246
248
  )
@@ -483,6 +485,7 @@ interface AchievementCatalogSectionProps {
483
485
  label?: string // default 'ALL ACHIEVEMENTS'
484
486
  fg?: string
485
487
  fgMuted?: string
488
+ sectionBg?: string // passed to every row
486
489
  }
487
490
  ```
488
491
 
@@ -495,9 +498,17 @@ stats object with these three fields satisfies it:
495
498
  ```ts
496
499
  interface ActivityStatSectionProps {
497
500
  stats: { distinctDaysPlayed: number; currentDayStreak: number; bestDayStreak: number }
501
+ fg?: string
502
+ fgMuted?: string
503
+ sectionBg?: string
498
504
  }
499
505
  ```
500
506
 
507
+ **Wells.** Every `StatSection` and `AchievementRow` is a well: the theme's `surface` (the same surface as the dialogs)
508
+ on MD3's level-1 shadow, with `onSurface`/`onSurfaceVariant` text. `useWellColors()` returns those colors and
509
+ `WELL_SHADOW` the shadow, for an app's own cards (a menu tile) to match. Each component's `fg`/`fgMuted`/`sectionBg`
510
+ props still override them.
511
+
501
512
  Composing both with `@tastic/achievements`' own row computation:
502
513
 
503
514
  ```tsx
@@ -619,17 +630,26 @@ const { open } = useGuide()
619
630
 
620
631
  ## Fleet chrome without the heavy peers (`@tastic/hud/chrome`)
621
632
 
622
- The shared dialogs, stats screen pieces, corner buttons and style tokens, from a standalone entry that never
623
- touches the main barrel. It's for an app that has `@tastic/core` and `@rific/updater` but none of Skia,
624
- `@tastic/profile` or `@tastic/split-screen` (Hangman). It exports, with their props types:
633
+ The shared dialogs, stats screen pieces, corner buttons, popover primitives, color picker and style tokens,
634
+ from a standalone entry that never touches the main barrel. It's for an app that has `@tastic/core` and
635
+ `@rific/updater` but none of Skia, `@tastic/profile` or `@tastic/split-screen` (Hangman). It exports, with
636
+ their props types:
625
637
 
626
638
  - Dialogs: `BaseSettingsDialog`, `ConfirmDialog`, `UpdateDialog`, `RotatedFrame`
627
639
  - Stats: `BaseStatsScreen`, `StatSection`, `StatRow`, `AchievementRow`, `LOCKED_BADGE_COLOR`,
628
- `AchievementCatalogSection`, `ActivityStatSection`
640
+ `AchievementCatalogSection`, `ActivityStatSection`, `useWellColors`, `WELL_SHADOW`
629
641
  - Chrome: `CornerActionButtons`, `ContentGutter`, `StaggeredWord`, `getStaggeredWordDuration`
630
642
  - Overlay cards: `OverlayCard`, `OverlayBackdrop`, `useOverlayCardColors`, `DialogHeader`, `useCompactDialog`, `isCompactDialogHeight`, `COMPACT_DIALOG_HEIGHT`
643
+ - Popovers (0.23.0+): `PopoverBody`, `PressAwayOverlay`, `usePopoverHost` (and its `PopoverHost` type),
644
+ `useAutoAlign` (and its `AlignResult`, `PopoverAlign`, `PopoverRotation` and `PopoverVerticalAlign`
645
+ types), `InlineColorPicker`, `getInlineColorPickerContentSize`
631
646
  - Style tokens: `overlayStyles`, `overlayActionStyles`, `MONO_FONT`
632
647
 
648
+ The popovers are here for `@tastic/profile`: from 0.16 its `ProfilePicker`, `ProfilesScreen` and the rest
649
+ import them (and `ConfirmDialog`) from this entry instead of the main barrel, so a Skia-free app can use
650
+ them. That's why `@tastic/profile` 0.16 needs hud 0.23.0 or later. `useZoneClampedAlign` (it needs `@tastic/split-screen`), `SectionedDropdown` (its trigger gauge
651
+ loads Skia) and `PlayerSetupPanel` (it renders `@tastic/profile`'s pickers) stay main-entry only.
652
+
633
653
  Each is the same component the main entry exports and is documented above. Only the import path changes:
634
654
 
635
655
  ```tsx
@@ -637,8 +657,8 @@ import { BaseSettingsDialog, ConfirmDialog, CornerActionButtons } from '@tastic/
637
657
  ```
638
658
 
639
659
  It pulls in only `react`, `react-native`, `react-native-paper`, `react-native-reanimated`,
640
- `react-native-safe-area-context`, `@rific/auto-paper`, `@rific/feedback-press`, `@rific/updater` and
641
- `@tastic/core`. `AchievementCatalogSection` uses `@tastic/achievements` for types only, so nothing loads it at
660
+ `react-native-safe-area-context`, `@rific/auto-paper`, `@rific/core`, `@rific/feedback-press`,
661
+ `@rific/updater` and `@tastic/core`. `AchievementCatalogSection` uses `@tastic/achievements` for types only, so nothing loads it at
642
662
  runtime, but an app whose TypeScript resolves the `react-native` export condition (the fleet's tsconfig does)
643
663
  type-checks hud's source and needs it installed. `AchievementUnlockList` isn't here because it renders
644
664
  `@tastic/profile`'s `ProfileChip`. A test (`src/__tests__/chromeImports.test.ts`) walks the import graph from
@@ -684,8 +704,9 @@ resolve module".
684
704
  | `react-native-reanimated` | >=3.0.0 | main entry (`StaggeredWord`), `./guide`, `./chrome` (`StaggeredWord`) |
685
705
  | `@rific/auto-paper` | >=0.12.2 | main entry (`BaseSettingsDialog` needs the nested `Portal.Host` first shipped in 0.12.2; `OverlayCard` uses `BlurView` and `useBlur`, and `BaseSettingsDialog`'s Blur row uses `useBlurModule` and `useThemeSettings`, all in 0.12.2), `./guide`, `./chrome` |
686
706
  | `@rific/feedback-press` | >=0.10.2 | main entry (`useSoundSettings` first shipped in 0.10.2), `./guide`, `./chrome` |
707
+ | `@rific/core` | >=0.4.0 | main entry and `./chrome`: `BaseSettingsDialog`'s Keep Awake row (`useKeepAwakeSettings`, `useExpoKeepAwake`, first shipped in 0.4.0) |
687
708
  | `react-native-safe-area-context` | >=5.0.0 | main entry (`useZoneClampedAlign`), `./chrome` (`RotatedFrame`, `BaseSettingsDialog`) |
688
- | `@tastic/core` | >=0.12.0, optional | main entry: `useRotation()` and most dialogs; `RotatedFrame` and `BaseSettingsDialog` need `FakeLandscapeView`'s `rotation`/`passThrough`, first shipped in 0.12.0; `./chrome` (the same dialogs) |
709
+ | `@tastic/core` | >=0.12.0, optional | main entry: `useRotation()` and most dialogs; `RotatedFrame` and `BaseSettingsDialog` need `FakeLandscapeView`'s `rotation`/`passThrough`, first shipped in 0.12.0; `./chrome` (the same dialogs, and `InlineColorPicker`) |
689
710
  | `@rific/updater` | >=0.4.0, optional | main entry and `./chrome`: `BaseSettingsDialog`, `UpdateDialog` |
690
711
  | `@tastic/profile` | >=0.4.0, optional | main entry: `PlayerSetupPanel`, `AchievementUnlockList` (`ProfileChip`) |
691
712
  | `@tastic/split-screen` | >=0.5.0, optional | main entry: `useZoneClampedAlign` |
@@ -1,19 +1,21 @@
1
1
  import * as react from 'react';
2
- import { ReactNode } from 'react';
2
+ import { ReactNode, RefObject } from 'react';
3
3
  import { AchievementCatalogRow } from '@tastic/achievements';
4
4
  import { ViewRotation } from '@tastic/core';
5
- import { Insets, StyleProp, ViewStyle, LayoutChangeEvent, TextStyle } from 'react-native';
5
+ import { Insets, StyleProp, ViewStyle, View, LayoutChangeEvent, TextStyle } from 'react-native';
6
+ import { SeedColor } from '@rific/auto-paper';
6
7
 
7
- interface Props$7 {
8
+ interface Props$a {
8
9
  rows: AchievementCatalogRow[];
9
10
  label?: string;
10
11
  fg?: string;
11
12
  fgMuted?: string;
13
+ sectionBg?: string;
12
14
  }
13
- declare function AchievementCatalogSection({ rows, label, fg, fgMuted: fgMutedOverride }: Props$7): react.JSX.Element;
15
+ declare function AchievementCatalogSection({ rows, label, fg, fgMuted: fgMutedOverride, sectionBg }: Props$a): react.JSX.Element;
14
16
 
15
17
  declare const LOCKED_BADGE_COLOR = "rgba(128,128,128,0.3)";
16
- interface Props$6 {
18
+ interface Props$9 {
17
19
  icon: string;
18
20
  title: string;
19
21
  description: string;
@@ -26,17 +28,20 @@ interface Props$6 {
26
28
  fgMuted?: string;
27
29
  sectionBg?: string;
28
30
  }
29
- declare function AchievementRow({ icon, title, description, badgeColor, unlockedLabel, checkColor, progress, deviceMarker, fg: fgOverride, fgMuted: fgMutedOverride, sectionBg: sectionBgOverride }: Props$6): react.JSX.Element;
31
+ declare function AchievementRow({ icon, title, description, badgeColor, unlockedLabel, checkColor, progress, deviceMarker, fg: fgOverride, fgMuted: fgMutedOverride, sectionBg: sectionBgOverride }: Props$9): react.JSX.Element;
30
32
 
31
33
  interface ActivityStats {
32
34
  distinctDaysPlayed: number;
33
35
  currentDayStreak: number;
34
36
  bestDayStreak: number;
35
37
  }
36
- interface Props$5 {
38
+ interface Props$8 {
37
39
  stats: ActivityStats;
40
+ fg?: string;
41
+ fgMuted?: string;
42
+ sectionBg?: string;
38
43
  }
39
- declare function ActivityStatSection({ stats }: Props$5): react.JSX.Element;
44
+ declare function ActivityStatSection({ stats, fg, fgMuted, sectionBg }: Props$8): react.JSX.Element;
40
45
 
41
46
  interface BaseSettingsDialogProps {
42
47
  visible: boolean;
@@ -47,8 +52,6 @@ interface BaseSettingsDialogProps {
47
52
  onLockOrientationChange?: (value: boolean) => void;
48
53
  deferBottomEdgeGestures?: boolean;
49
54
  onDeferBottomEdgeGestures?: (value: boolean) => void;
50
- keepAwake?: boolean;
51
- onKeepAwakeChange?: (value: boolean) => void;
52
55
  hideSound?: boolean;
53
56
  hideHaptics?: boolean;
54
57
  hideAppearance?: boolean;
@@ -57,10 +60,10 @@ interface BaseSettingsDialogProps {
57
60
  onShowHowToPlay?: () => void;
58
61
  children?: ReactNode;
59
62
  }
60
- declare function BaseSettingsDialog({ visible, onDismiss, rotation: rotationOverride, version, lockOrientation, onLockOrientationChange, deferBottomEdgeGestures, onDeferBottomEdgeGestures, keepAwake, onKeepAwakeChange, hideSound, hideHaptics, hideAppearance, hideUpdateCheck, onUpdateError, onShowHowToPlay, children }: BaseSettingsDialogProps): react.JSX.Element | null;
63
+ declare function BaseSettingsDialog({ visible, onDismiss, rotation: rotationOverride, version, lockOrientation, onLockOrientationChange, deferBottomEdgeGestures, onDeferBottomEdgeGestures, hideSound, hideHaptics, hideAppearance, hideUpdateCheck, onUpdateError, onShowHowToPlay, children }: BaseSettingsDialogProps): react.JSX.Element | null;
61
64
 
62
65
  type MD3TextVariant = 'displayLarge' | 'displayMedium' | 'displaySmall' | 'headlineLarge' | 'headlineMedium' | 'headlineSmall' | 'titleLarge' | 'titleMedium' | 'titleSmall' | 'labelLarge' | 'labelMedium' | 'labelSmall' | 'bodyLarge' | 'bodyMedium' | 'bodySmall';
63
- interface Props$4 {
66
+ interface Props$7 {
64
67
  rotation?: ViewRotation;
65
68
  title?: string;
66
69
  titleVariant?: MD3TextVariant;
@@ -81,7 +84,7 @@ interface Props$4 {
81
84
  bg?: string;
82
85
  children: ReactNode;
83
86
  }
84
- declare function BaseStatsScreen({ rotation: rotationOverride, title, titleVariant, onBack, backLabel, hitSlop, insets, onReset, resetLabel, resetConfirmTitle, resetConfirmBody, fg: fgOverride, bg: bgOverride, children }: Props$4): react.JSX.Element;
87
+ declare function BaseStatsScreen({ rotation: rotationOverride, title, titleVariant, onBack, backLabel, hitSlop, insets, onReset, resetLabel, resetConfirmTitle, resetConfirmBody, fg: fgOverride, bg: bgOverride, children }: Props$7): react.JSX.Element;
85
88
 
86
89
  interface ConfirmDialogProps {
87
90
  visible: boolean;
@@ -97,16 +100,16 @@ interface ConfirmDialogProps {
97
100
  }
98
101
  declare function ConfirmDialog({ visible, title, message, confirmLabel, cancelLabel, onConfirm, onCancel, rotation, icon, destructive }: ConfirmDialogProps): react.JSX.Element | null;
99
102
 
100
- interface Props$3 {
103
+ interface Props$6 {
101
104
  maxContentWidth?: number;
102
105
  leftGutter?: ReactNode;
103
106
  rightGutter?: ReactNode;
104
107
  style?: StyleProp<ViewStyle>;
105
108
  children: ReactNode;
106
109
  }
107
- declare function ContentGutter({ maxContentWidth, leftGutter, rightGutter, style, children }: Props$3): react.JSX.Element;
110
+ declare function ContentGutter({ maxContentWidth, leftGutter, rightGutter, style, children }: Props$6): react.JSX.Element;
108
111
 
109
- interface Props$2 {
112
+ interface Props$5 {
110
113
  onBack: () => void;
111
114
  onSettings: () => void;
112
115
  fg: string;
@@ -119,7 +122,7 @@ interface Props$2 {
119
122
  backLabel?: string;
120
123
  hitSlop?: number | Insets;
121
124
  }
122
- declare function CornerActionButtons({ onBack, onSettings, fg, insets, backIcon, backLabel, hitSlop }: Props$2): react.JSX.Element;
125
+ declare function CornerActionButtons({ onBack, onSettings, fg, insets, backIcon, backLabel, hitSlop }: Props$5): react.JSX.Element;
123
126
 
124
127
  declare const COMPACT_DIALOG_HEIGHT = 528;
125
128
  declare function isCompactDialogHeight(height: number): boolean;
@@ -134,6 +137,57 @@ declare function DialogHeader({ icon, title, color, compact, style }: DialogHead
134
137
 
135
138
  declare const MONO_FONT: string;
136
139
 
140
+ type PopoverAlign = 'left' | 'right' | 'center';
141
+ type PopoverVerticalAlign = 'below' | 'above';
142
+ type PopoverRotation = ViewRotation;
143
+ interface AlignResult {
144
+ align: PopoverAlign;
145
+ verticalAlign: PopoverVerticalAlign;
146
+ maxHeight: number;
147
+ measured: boolean;
148
+ triggerRef: RefObject<View | null>;
149
+ }
150
+ declare function useAutoAlign(open: boolean, contentWidth: number, contentHeight: number, rotation?: PopoverRotation): {
151
+ align: PopoverAlign;
152
+ maxHeight: number;
153
+ measured: boolean;
154
+ triggerRef: RefObject<View | null>;
155
+ verticalAlign: PopoverVerticalAlign;
156
+ };
157
+
158
+ interface PopoverHost {
159
+ openId: string | null;
160
+ toggle: (id: string) => void;
161
+ close: () => void;
162
+ }
163
+ declare function usePopoverHost(): PopoverHost;
164
+
165
+ declare function getInlineColorPickerContentSize(swatchCount: number, windowWidth: number, columns?: number): {
166
+ width: number;
167
+ height: number;
168
+ };
169
+ interface Props$4 {
170
+ id: string;
171
+ host: PopoverHost;
172
+ value: string;
173
+ onChange: (hex: string) => void;
174
+ previewValue?: (hex: string) => string;
175
+ swatches?: SeedColor[];
176
+ takenValue?: string;
177
+ allowSwapTaken?: boolean;
178
+ dark: boolean;
179
+ align?: 'left' | 'right' | 'center';
180
+ alignOverride?: AlignResult;
181
+ rotation?: PopoverRotation;
182
+ icon?: string;
183
+ tag?: string;
184
+ labelFontFamily?: string;
185
+ autoDismiss?: boolean;
186
+ columns?: number;
187
+ size?: number;
188
+ }
189
+ declare function InlineColorPicker({ id, host, value, onChange, previewValue, swatches, takenValue, allowSwapTaken, dark, align: forcedAlign, alignOverride, rotation: rotationOverride, icon, tag, labelFontFamily, autoDismiss, columns, size }: Props$4): react.JSX.Element;
190
+
137
191
  declare const overlayStyles: {
138
192
  card: {
139
193
  alignItems: "center";
@@ -191,6 +245,25 @@ interface OverlayCardProps {
191
245
  }
192
246
  declare function OverlayCard({ children, style, ...rest }: OverlayCardProps): react.JSX.Element;
193
247
 
248
+ interface Props$3 {
249
+ visible: boolean;
250
+ children: ReactNode;
251
+ align?: 'left' | 'right' | 'center';
252
+ verticalAlign?: 'below' | 'above';
253
+ caretColor?: string;
254
+ caretBorderColor?: string;
255
+ caretBorderWidth?: number;
256
+ triggerSize?: number;
257
+ }
258
+ declare function PopoverBody({ visible, children, align, verticalAlign, caretColor, caretBorderColor, caretBorderWidth, triggerSize }: Props$3): react.JSX.Element | null;
259
+
260
+ interface Props$2 {
261
+ active: boolean;
262
+ onPress: () => void;
263
+ style?: StyleProp<ViewStyle>;
264
+ }
265
+ declare function PressAwayOverlay({ active, onPress, style }: Props$2): react.JSX.Element | null;
266
+
194
267
  interface RotatedFrameProps {
195
268
  children: ReactNode;
196
269
  /** The angle to turn the frame by. Defaults to the live physical hold (@tastic/core's useRotation); pass it
@@ -270,4 +343,12 @@ declare function useCompactDialog(rotation?: ViewRotation): {
270
343
  onLayout: (e: LayoutChangeEvent) => void;
271
344
  };
272
345
 
273
- export { AchievementCatalogSection, AchievementRow, ActivityStatSection, BaseSettingsDialog, type BaseSettingsDialogProps, BaseStatsScreen, COMPACT_DIALOG_HEIGHT, ConfirmDialog, type ConfirmDialogProps, ContentGutter, CornerActionButtons, DialogHeader, type DialogHeaderProps, LOCKED_BADGE_COLOR, MONO_FONT, OverlayBackdrop, type OverlayBackdropProps, OverlayCard, type OverlayCardProps, type OverlayCardThemeColors, RotatedFrame, type RotatedFrameProps, StaggeredWord, type StaggeredWordProps, StatRow, StatSection, UpdateDialog, type UpdateDialogProps, getStaggeredWordDuration, isCompactDialogHeight, overlayActionStyles, overlayStyles, useCompactDialog, useOverlayCardColors };
346
+ declare const WELL_SHADOW = "0px 1px 2px rgba(0, 0, 0, 0.3), 0px 1px 3px 1px rgba(0, 0, 0, 0.15)";
347
+ interface WellColors {
348
+ bg: string;
349
+ fg: string;
350
+ fgMuted: string;
351
+ }
352
+ declare function useWellColors(): WellColors;
353
+
354
+ export { AchievementCatalogSection, AchievementRow, ActivityStatSection, type AlignResult, BaseSettingsDialog, type BaseSettingsDialogProps, BaseStatsScreen, COMPACT_DIALOG_HEIGHT, ConfirmDialog, type ConfirmDialogProps, ContentGutter, CornerActionButtons, DialogHeader, type DialogHeaderProps, InlineColorPicker, LOCKED_BADGE_COLOR, MONO_FONT, OverlayBackdrop, type OverlayBackdropProps, OverlayCard, type OverlayCardProps, type OverlayCardThemeColors, type PopoverAlign, PopoverBody, type PopoverHost, type PopoverRotation, type PopoverVerticalAlign, PressAwayOverlay, RotatedFrame, type RotatedFrameProps, StaggeredWord, type StaggeredWordProps, StatRow, StatSection, UpdateDialog, type UpdateDialogProps, WELL_SHADOW, type WellColors, getInlineColorPickerContentSize, getStaggeredWordDuration, isCompactDialogHeight, overlayActionStyles, overlayStyles, useAutoAlign, useCompactDialog, useOverlayCardColors, usePopoverHost, useWellColors };
@@ -1,19 +1,21 @@
1
1
  import * as react from 'react';
2
- import { ReactNode } from 'react';
2
+ import { ReactNode, RefObject } from 'react';
3
3
  import { AchievementCatalogRow } from '@tastic/achievements';
4
4
  import { ViewRotation } from '@tastic/core';
5
- import { Insets, StyleProp, ViewStyle, LayoutChangeEvent, TextStyle } from 'react-native';
5
+ import { Insets, StyleProp, ViewStyle, View, LayoutChangeEvent, TextStyle } from 'react-native';
6
+ import { SeedColor } from '@rific/auto-paper';
6
7
 
7
- interface Props$7 {
8
+ interface Props$a {
8
9
  rows: AchievementCatalogRow[];
9
10
  label?: string;
10
11
  fg?: string;
11
12
  fgMuted?: string;
13
+ sectionBg?: string;
12
14
  }
13
- declare function AchievementCatalogSection({ rows, label, fg, fgMuted: fgMutedOverride }: Props$7): react.JSX.Element;
15
+ declare function AchievementCatalogSection({ rows, label, fg, fgMuted: fgMutedOverride, sectionBg }: Props$a): react.JSX.Element;
14
16
 
15
17
  declare const LOCKED_BADGE_COLOR = "rgba(128,128,128,0.3)";
16
- interface Props$6 {
18
+ interface Props$9 {
17
19
  icon: string;
18
20
  title: string;
19
21
  description: string;
@@ -26,17 +28,20 @@ interface Props$6 {
26
28
  fgMuted?: string;
27
29
  sectionBg?: string;
28
30
  }
29
- declare function AchievementRow({ icon, title, description, badgeColor, unlockedLabel, checkColor, progress, deviceMarker, fg: fgOverride, fgMuted: fgMutedOverride, sectionBg: sectionBgOverride }: Props$6): react.JSX.Element;
31
+ declare function AchievementRow({ icon, title, description, badgeColor, unlockedLabel, checkColor, progress, deviceMarker, fg: fgOverride, fgMuted: fgMutedOverride, sectionBg: sectionBgOverride }: Props$9): react.JSX.Element;
30
32
 
31
33
  interface ActivityStats {
32
34
  distinctDaysPlayed: number;
33
35
  currentDayStreak: number;
34
36
  bestDayStreak: number;
35
37
  }
36
- interface Props$5 {
38
+ interface Props$8 {
37
39
  stats: ActivityStats;
40
+ fg?: string;
41
+ fgMuted?: string;
42
+ sectionBg?: string;
38
43
  }
39
- declare function ActivityStatSection({ stats }: Props$5): react.JSX.Element;
44
+ declare function ActivityStatSection({ stats, fg, fgMuted, sectionBg }: Props$8): react.JSX.Element;
40
45
 
41
46
  interface BaseSettingsDialogProps {
42
47
  visible: boolean;
@@ -47,8 +52,6 @@ interface BaseSettingsDialogProps {
47
52
  onLockOrientationChange?: (value: boolean) => void;
48
53
  deferBottomEdgeGestures?: boolean;
49
54
  onDeferBottomEdgeGestures?: (value: boolean) => void;
50
- keepAwake?: boolean;
51
- onKeepAwakeChange?: (value: boolean) => void;
52
55
  hideSound?: boolean;
53
56
  hideHaptics?: boolean;
54
57
  hideAppearance?: boolean;
@@ -57,10 +60,10 @@ interface BaseSettingsDialogProps {
57
60
  onShowHowToPlay?: () => void;
58
61
  children?: ReactNode;
59
62
  }
60
- declare function BaseSettingsDialog({ visible, onDismiss, rotation: rotationOverride, version, lockOrientation, onLockOrientationChange, deferBottomEdgeGestures, onDeferBottomEdgeGestures, keepAwake, onKeepAwakeChange, hideSound, hideHaptics, hideAppearance, hideUpdateCheck, onUpdateError, onShowHowToPlay, children }: BaseSettingsDialogProps): react.JSX.Element | null;
63
+ declare function BaseSettingsDialog({ visible, onDismiss, rotation: rotationOverride, version, lockOrientation, onLockOrientationChange, deferBottomEdgeGestures, onDeferBottomEdgeGestures, hideSound, hideHaptics, hideAppearance, hideUpdateCheck, onUpdateError, onShowHowToPlay, children }: BaseSettingsDialogProps): react.JSX.Element | null;
61
64
 
62
65
  type MD3TextVariant = 'displayLarge' | 'displayMedium' | 'displaySmall' | 'headlineLarge' | 'headlineMedium' | 'headlineSmall' | 'titleLarge' | 'titleMedium' | 'titleSmall' | 'labelLarge' | 'labelMedium' | 'labelSmall' | 'bodyLarge' | 'bodyMedium' | 'bodySmall';
63
- interface Props$4 {
66
+ interface Props$7 {
64
67
  rotation?: ViewRotation;
65
68
  title?: string;
66
69
  titleVariant?: MD3TextVariant;
@@ -81,7 +84,7 @@ interface Props$4 {
81
84
  bg?: string;
82
85
  children: ReactNode;
83
86
  }
84
- declare function BaseStatsScreen({ rotation: rotationOverride, title, titleVariant, onBack, backLabel, hitSlop, insets, onReset, resetLabel, resetConfirmTitle, resetConfirmBody, fg: fgOverride, bg: bgOverride, children }: Props$4): react.JSX.Element;
87
+ declare function BaseStatsScreen({ rotation: rotationOverride, title, titleVariant, onBack, backLabel, hitSlop, insets, onReset, resetLabel, resetConfirmTitle, resetConfirmBody, fg: fgOverride, bg: bgOverride, children }: Props$7): react.JSX.Element;
85
88
 
86
89
  interface ConfirmDialogProps {
87
90
  visible: boolean;
@@ -97,16 +100,16 @@ interface ConfirmDialogProps {
97
100
  }
98
101
  declare function ConfirmDialog({ visible, title, message, confirmLabel, cancelLabel, onConfirm, onCancel, rotation, icon, destructive }: ConfirmDialogProps): react.JSX.Element | null;
99
102
 
100
- interface Props$3 {
103
+ interface Props$6 {
101
104
  maxContentWidth?: number;
102
105
  leftGutter?: ReactNode;
103
106
  rightGutter?: ReactNode;
104
107
  style?: StyleProp<ViewStyle>;
105
108
  children: ReactNode;
106
109
  }
107
- declare function ContentGutter({ maxContentWidth, leftGutter, rightGutter, style, children }: Props$3): react.JSX.Element;
110
+ declare function ContentGutter({ maxContentWidth, leftGutter, rightGutter, style, children }: Props$6): react.JSX.Element;
108
111
 
109
- interface Props$2 {
112
+ interface Props$5 {
110
113
  onBack: () => void;
111
114
  onSettings: () => void;
112
115
  fg: string;
@@ -119,7 +122,7 @@ interface Props$2 {
119
122
  backLabel?: string;
120
123
  hitSlop?: number | Insets;
121
124
  }
122
- declare function CornerActionButtons({ onBack, onSettings, fg, insets, backIcon, backLabel, hitSlop }: Props$2): react.JSX.Element;
125
+ declare function CornerActionButtons({ onBack, onSettings, fg, insets, backIcon, backLabel, hitSlop }: Props$5): react.JSX.Element;
123
126
 
124
127
  declare const COMPACT_DIALOG_HEIGHT = 528;
125
128
  declare function isCompactDialogHeight(height: number): boolean;
@@ -134,6 +137,57 @@ declare function DialogHeader({ icon, title, color, compact, style }: DialogHead
134
137
 
135
138
  declare const MONO_FONT: string;
136
139
 
140
+ type PopoverAlign = 'left' | 'right' | 'center';
141
+ type PopoverVerticalAlign = 'below' | 'above';
142
+ type PopoverRotation = ViewRotation;
143
+ interface AlignResult {
144
+ align: PopoverAlign;
145
+ verticalAlign: PopoverVerticalAlign;
146
+ maxHeight: number;
147
+ measured: boolean;
148
+ triggerRef: RefObject<View | null>;
149
+ }
150
+ declare function useAutoAlign(open: boolean, contentWidth: number, contentHeight: number, rotation?: PopoverRotation): {
151
+ align: PopoverAlign;
152
+ maxHeight: number;
153
+ measured: boolean;
154
+ triggerRef: RefObject<View | null>;
155
+ verticalAlign: PopoverVerticalAlign;
156
+ };
157
+
158
+ interface PopoverHost {
159
+ openId: string | null;
160
+ toggle: (id: string) => void;
161
+ close: () => void;
162
+ }
163
+ declare function usePopoverHost(): PopoverHost;
164
+
165
+ declare function getInlineColorPickerContentSize(swatchCount: number, windowWidth: number, columns?: number): {
166
+ width: number;
167
+ height: number;
168
+ };
169
+ interface Props$4 {
170
+ id: string;
171
+ host: PopoverHost;
172
+ value: string;
173
+ onChange: (hex: string) => void;
174
+ previewValue?: (hex: string) => string;
175
+ swatches?: SeedColor[];
176
+ takenValue?: string;
177
+ allowSwapTaken?: boolean;
178
+ dark: boolean;
179
+ align?: 'left' | 'right' | 'center';
180
+ alignOverride?: AlignResult;
181
+ rotation?: PopoverRotation;
182
+ icon?: string;
183
+ tag?: string;
184
+ labelFontFamily?: string;
185
+ autoDismiss?: boolean;
186
+ columns?: number;
187
+ size?: number;
188
+ }
189
+ declare function InlineColorPicker({ id, host, value, onChange, previewValue, swatches, takenValue, allowSwapTaken, dark, align: forcedAlign, alignOverride, rotation: rotationOverride, icon, tag, labelFontFamily, autoDismiss, columns, size }: Props$4): react.JSX.Element;
190
+
137
191
  declare const overlayStyles: {
138
192
  card: {
139
193
  alignItems: "center";
@@ -191,6 +245,25 @@ interface OverlayCardProps {
191
245
  }
192
246
  declare function OverlayCard({ children, style, ...rest }: OverlayCardProps): react.JSX.Element;
193
247
 
248
+ interface Props$3 {
249
+ visible: boolean;
250
+ children: ReactNode;
251
+ align?: 'left' | 'right' | 'center';
252
+ verticalAlign?: 'below' | 'above';
253
+ caretColor?: string;
254
+ caretBorderColor?: string;
255
+ caretBorderWidth?: number;
256
+ triggerSize?: number;
257
+ }
258
+ declare function PopoverBody({ visible, children, align, verticalAlign, caretColor, caretBorderColor, caretBorderWidth, triggerSize }: Props$3): react.JSX.Element | null;
259
+
260
+ interface Props$2 {
261
+ active: boolean;
262
+ onPress: () => void;
263
+ style?: StyleProp<ViewStyle>;
264
+ }
265
+ declare function PressAwayOverlay({ active, onPress, style }: Props$2): react.JSX.Element | null;
266
+
194
267
  interface RotatedFrameProps {
195
268
  children: ReactNode;
196
269
  /** The angle to turn the frame by. Defaults to the live physical hold (@tastic/core's useRotation); pass it
@@ -270,4 +343,12 @@ declare function useCompactDialog(rotation?: ViewRotation): {
270
343
  onLayout: (e: LayoutChangeEvent) => void;
271
344
  };
272
345
 
273
- export { AchievementCatalogSection, AchievementRow, ActivityStatSection, BaseSettingsDialog, type BaseSettingsDialogProps, BaseStatsScreen, COMPACT_DIALOG_HEIGHT, ConfirmDialog, type ConfirmDialogProps, ContentGutter, CornerActionButtons, DialogHeader, type DialogHeaderProps, LOCKED_BADGE_COLOR, MONO_FONT, OverlayBackdrop, type OverlayBackdropProps, OverlayCard, type OverlayCardProps, type OverlayCardThemeColors, RotatedFrame, type RotatedFrameProps, StaggeredWord, type StaggeredWordProps, StatRow, StatSection, UpdateDialog, type UpdateDialogProps, getStaggeredWordDuration, isCompactDialogHeight, overlayActionStyles, overlayStyles, useCompactDialog, useOverlayCardColors };
346
+ declare const WELL_SHADOW = "0px 1px 2px rgba(0, 0, 0, 0.3), 0px 1px 3px 1px rgba(0, 0, 0, 0.15)";
347
+ interface WellColors {
348
+ bg: string;
349
+ fg: string;
350
+ fgMuted: string;
351
+ }
352
+ declare function useWellColors(): WellColors;
353
+
354
+ export { AchievementCatalogSection, AchievementRow, ActivityStatSection, type AlignResult, BaseSettingsDialog, type BaseSettingsDialogProps, BaseStatsScreen, COMPACT_DIALOG_HEIGHT, ConfirmDialog, type ConfirmDialogProps, ContentGutter, CornerActionButtons, DialogHeader, type DialogHeaderProps, InlineColorPicker, LOCKED_BADGE_COLOR, MONO_FONT, OverlayBackdrop, type OverlayBackdropProps, OverlayCard, type OverlayCardProps, type OverlayCardThemeColors, type PopoverAlign, PopoverBody, type PopoverHost, type PopoverRotation, type PopoverVerticalAlign, PressAwayOverlay, RotatedFrame, type RotatedFrameProps, StaggeredWord, type StaggeredWordProps, StatRow, StatSection, UpdateDialog, type UpdateDialogProps, WELL_SHADOW, type WellColors, getInlineColorPickerContentSize, getStaggeredWordDuration, isCompactDialogHeight, overlayActionStyles, overlayStyles, useAutoAlign, useCompactDialog, useOverlayCardColors, usePopoverHost, useWellColors };