@tastic/hud 0.22.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
  )
@@ -628,17 +630,26 @@ const { open } = useGuide()
628
630
 
629
631
  ## Fleet chrome without the heavy peers (`@tastic/hud/chrome`)
630
632
 
631
- The shared dialogs, stats screen pieces, corner buttons and style tokens, from a standalone entry that never
632
- touches the main barrel. It's for an app that has `@tastic/core` and `@rific/updater` but none of Skia,
633
- `@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:
634
637
 
635
638
  - Dialogs: `BaseSettingsDialog`, `ConfirmDialog`, `UpdateDialog`, `RotatedFrame`
636
639
  - Stats: `BaseStatsScreen`, `StatSection`, `StatRow`, `AchievementRow`, `LOCKED_BADGE_COLOR`,
637
640
  `AchievementCatalogSection`, `ActivityStatSection`, `useWellColors`, `WELL_SHADOW`
638
641
  - Chrome: `CornerActionButtons`, `ContentGutter`, `StaggeredWord`, `getStaggeredWordDuration`
639
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`
640
646
  - Style tokens: `overlayStyles`, `overlayActionStyles`, `MONO_FONT`
641
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
+
642
653
  Each is the same component the main entry exports and is documented above. Only the import path changes:
643
654
 
644
655
  ```tsx
@@ -646,8 +657,8 @@ import { BaseSettingsDialog, ConfirmDialog, CornerActionButtons } from '@tastic/
646
657
  ```
647
658
 
648
659
  It pulls in only `react`, `react-native`, `react-native-paper`, `react-native-reanimated`,
649
- `react-native-safe-area-context`, `@rific/auto-paper`, `@rific/feedback-press`, `@rific/updater` and
650
- `@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
651
662
  runtime, but an app whose TypeScript resolves the `react-native` export condition (the fleet's tsconfig does)
652
663
  type-checks hud's source and needs it installed. `AchievementUnlockList` isn't here because it renders
653
664
  `@tastic/profile`'s `ProfileChip`. A test (`src/__tests__/chromeImports.test.ts`) walks the import graph from
@@ -693,8 +704,9 @@ resolve module".
693
704
  | `react-native-reanimated` | >=3.0.0 | main entry (`StaggeredWord`), `./guide`, `./chrome` (`StaggeredWord`) |
694
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` |
695
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) |
696
708
  | `react-native-safe-area-context` | >=5.0.0 | main entry (`useZoneClampedAlign`), `./chrome` (`RotatedFrame`, `BaseSettingsDialog`) |
697
- | `@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`) |
698
710
  | `@rific/updater` | >=0.4.0, optional | main entry and `./chrome`: `BaseSettingsDialog`, `UpdateDialog` |
699
711
  | `@tastic/profile` | >=0.4.0, optional | main entry: `PlayerSetupPanel`, `AchievementUnlockList` (`ProfileChip`) |
700
712
  | `@tastic/split-screen` | >=0.5.0, optional | main entry: `useZoneClampedAlign` |
@@ -1,20 +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;
12
13
  sectionBg?: string;
13
14
  }
14
- declare function AchievementCatalogSection({ rows, label, fg, fgMuted: fgMutedOverride, sectionBg }: Props$7): react.JSX.Element;
15
+ declare function AchievementCatalogSection({ rows, label, fg, fgMuted: fgMutedOverride, sectionBg }: Props$a): react.JSX.Element;
15
16
 
16
17
  declare const LOCKED_BADGE_COLOR = "rgba(128,128,128,0.3)";
17
- interface Props$6 {
18
+ interface Props$9 {
18
19
  icon: string;
19
20
  title: string;
20
21
  description: string;
@@ -27,20 +28,20 @@ interface Props$6 {
27
28
  fgMuted?: string;
28
29
  sectionBg?: string;
29
30
  }
30
- 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;
31
32
 
32
33
  interface ActivityStats {
33
34
  distinctDaysPlayed: number;
34
35
  currentDayStreak: number;
35
36
  bestDayStreak: number;
36
37
  }
37
- interface Props$5 {
38
+ interface Props$8 {
38
39
  stats: ActivityStats;
39
40
  fg?: string;
40
41
  fgMuted?: string;
41
42
  sectionBg?: string;
42
43
  }
43
- declare function ActivityStatSection({ stats, fg, fgMuted, sectionBg }: Props$5): react.JSX.Element;
44
+ declare function ActivityStatSection({ stats, fg, fgMuted, sectionBg }: Props$8): react.JSX.Element;
44
45
 
45
46
  interface BaseSettingsDialogProps {
46
47
  visible: boolean;
@@ -51,8 +52,6 @@ interface BaseSettingsDialogProps {
51
52
  onLockOrientationChange?: (value: boolean) => void;
52
53
  deferBottomEdgeGestures?: boolean;
53
54
  onDeferBottomEdgeGestures?: (value: boolean) => void;
54
- keepAwake?: boolean;
55
- onKeepAwakeChange?: (value: boolean) => void;
56
55
  hideSound?: boolean;
57
56
  hideHaptics?: boolean;
58
57
  hideAppearance?: boolean;
@@ -61,10 +60,10 @@ interface BaseSettingsDialogProps {
61
60
  onShowHowToPlay?: () => void;
62
61
  children?: ReactNode;
63
62
  }
64
- 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;
65
64
 
66
65
  type MD3TextVariant = 'displayLarge' | 'displayMedium' | 'displaySmall' | 'headlineLarge' | 'headlineMedium' | 'headlineSmall' | 'titleLarge' | 'titleMedium' | 'titleSmall' | 'labelLarge' | 'labelMedium' | 'labelSmall' | 'bodyLarge' | 'bodyMedium' | 'bodySmall';
67
- interface Props$4 {
66
+ interface Props$7 {
68
67
  rotation?: ViewRotation;
69
68
  title?: string;
70
69
  titleVariant?: MD3TextVariant;
@@ -85,7 +84,7 @@ interface Props$4 {
85
84
  bg?: string;
86
85
  children: ReactNode;
87
86
  }
88
- 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;
89
88
 
90
89
  interface ConfirmDialogProps {
91
90
  visible: boolean;
@@ -101,16 +100,16 @@ interface ConfirmDialogProps {
101
100
  }
102
101
  declare function ConfirmDialog({ visible, title, message, confirmLabel, cancelLabel, onConfirm, onCancel, rotation, icon, destructive }: ConfirmDialogProps): react.JSX.Element | null;
103
102
 
104
- interface Props$3 {
103
+ interface Props$6 {
105
104
  maxContentWidth?: number;
106
105
  leftGutter?: ReactNode;
107
106
  rightGutter?: ReactNode;
108
107
  style?: StyleProp<ViewStyle>;
109
108
  children: ReactNode;
110
109
  }
111
- 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;
112
111
 
113
- interface Props$2 {
112
+ interface Props$5 {
114
113
  onBack: () => void;
115
114
  onSettings: () => void;
116
115
  fg: string;
@@ -123,7 +122,7 @@ interface Props$2 {
123
122
  backLabel?: string;
124
123
  hitSlop?: number | Insets;
125
124
  }
126
- 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;
127
126
 
128
127
  declare const COMPACT_DIALOG_HEIGHT = 528;
129
128
  declare function isCompactDialogHeight(height: number): boolean;
@@ -138,6 +137,57 @@ declare function DialogHeader({ icon, title, color, compact, style }: DialogHead
138
137
 
139
138
  declare const MONO_FONT: string;
140
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
+
141
191
  declare const overlayStyles: {
142
192
  card: {
143
193
  alignItems: "center";
@@ -195,6 +245,25 @@ interface OverlayCardProps {
195
245
  }
196
246
  declare function OverlayCard({ children, style, ...rest }: OverlayCardProps): react.JSX.Element;
197
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
+
198
267
  interface RotatedFrameProps {
199
268
  children: ReactNode;
200
269
  /** The angle to turn the frame by. Defaults to the live physical hold (@tastic/core's useRotation); pass it
@@ -282,4 +351,4 @@ interface WellColors {
282
351
  }
283
352
  declare function useWellColors(): WellColors;
284
353
 
285
- 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, WELL_SHADOW, type WellColors, getStaggeredWordDuration, isCompactDialogHeight, overlayActionStyles, overlayStyles, useCompactDialog, useOverlayCardColors, useWellColors };
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,20 +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;
12
13
  sectionBg?: string;
13
14
  }
14
- declare function AchievementCatalogSection({ rows, label, fg, fgMuted: fgMutedOverride, sectionBg }: Props$7): react.JSX.Element;
15
+ declare function AchievementCatalogSection({ rows, label, fg, fgMuted: fgMutedOverride, sectionBg }: Props$a): react.JSX.Element;
15
16
 
16
17
  declare const LOCKED_BADGE_COLOR = "rgba(128,128,128,0.3)";
17
- interface Props$6 {
18
+ interface Props$9 {
18
19
  icon: string;
19
20
  title: string;
20
21
  description: string;
@@ -27,20 +28,20 @@ interface Props$6 {
27
28
  fgMuted?: string;
28
29
  sectionBg?: string;
29
30
  }
30
- 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;
31
32
 
32
33
  interface ActivityStats {
33
34
  distinctDaysPlayed: number;
34
35
  currentDayStreak: number;
35
36
  bestDayStreak: number;
36
37
  }
37
- interface Props$5 {
38
+ interface Props$8 {
38
39
  stats: ActivityStats;
39
40
  fg?: string;
40
41
  fgMuted?: string;
41
42
  sectionBg?: string;
42
43
  }
43
- declare function ActivityStatSection({ stats, fg, fgMuted, sectionBg }: Props$5): react.JSX.Element;
44
+ declare function ActivityStatSection({ stats, fg, fgMuted, sectionBg }: Props$8): react.JSX.Element;
44
45
 
45
46
  interface BaseSettingsDialogProps {
46
47
  visible: boolean;
@@ -51,8 +52,6 @@ interface BaseSettingsDialogProps {
51
52
  onLockOrientationChange?: (value: boolean) => void;
52
53
  deferBottomEdgeGestures?: boolean;
53
54
  onDeferBottomEdgeGestures?: (value: boolean) => void;
54
- keepAwake?: boolean;
55
- onKeepAwakeChange?: (value: boolean) => void;
56
55
  hideSound?: boolean;
57
56
  hideHaptics?: boolean;
58
57
  hideAppearance?: boolean;
@@ -61,10 +60,10 @@ interface BaseSettingsDialogProps {
61
60
  onShowHowToPlay?: () => void;
62
61
  children?: ReactNode;
63
62
  }
64
- 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;
65
64
 
66
65
  type MD3TextVariant = 'displayLarge' | 'displayMedium' | 'displaySmall' | 'headlineLarge' | 'headlineMedium' | 'headlineSmall' | 'titleLarge' | 'titleMedium' | 'titleSmall' | 'labelLarge' | 'labelMedium' | 'labelSmall' | 'bodyLarge' | 'bodyMedium' | 'bodySmall';
67
- interface Props$4 {
66
+ interface Props$7 {
68
67
  rotation?: ViewRotation;
69
68
  title?: string;
70
69
  titleVariant?: MD3TextVariant;
@@ -85,7 +84,7 @@ interface Props$4 {
85
84
  bg?: string;
86
85
  children: ReactNode;
87
86
  }
88
- 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;
89
88
 
90
89
  interface ConfirmDialogProps {
91
90
  visible: boolean;
@@ -101,16 +100,16 @@ interface ConfirmDialogProps {
101
100
  }
102
101
  declare function ConfirmDialog({ visible, title, message, confirmLabel, cancelLabel, onConfirm, onCancel, rotation, icon, destructive }: ConfirmDialogProps): react.JSX.Element | null;
103
102
 
104
- interface Props$3 {
103
+ interface Props$6 {
105
104
  maxContentWidth?: number;
106
105
  leftGutter?: ReactNode;
107
106
  rightGutter?: ReactNode;
108
107
  style?: StyleProp<ViewStyle>;
109
108
  children: ReactNode;
110
109
  }
111
- 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;
112
111
 
113
- interface Props$2 {
112
+ interface Props$5 {
114
113
  onBack: () => void;
115
114
  onSettings: () => void;
116
115
  fg: string;
@@ -123,7 +122,7 @@ interface Props$2 {
123
122
  backLabel?: string;
124
123
  hitSlop?: number | Insets;
125
124
  }
126
- 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;
127
126
 
128
127
  declare const COMPACT_DIALOG_HEIGHT = 528;
129
128
  declare function isCompactDialogHeight(height: number): boolean;
@@ -138,6 +137,57 @@ declare function DialogHeader({ icon, title, color, compact, style }: DialogHead
138
137
 
139
138
  declare const MONO_FONT: string;
140
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
+
141
191
  declare const overlayStyles: {
142
192
  card: {
143
193
  alignItems: "center";
@@ -195,6 +245,25 @@ interface OverlayCardProps {
195
245
  }
196
246
  declare function OverlayCard({ children, style, ...rest }: OverlayCardProps): react.JSX.Element;
197
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
+
198
267
  interface RotatedFrameProps {
199
268
  children: ReactNode;
200
269
  /** The angle to turn the frame by. Defaults to the live physical hold (@tastic/core's useRotation); pass it
@@ -282,4 +351,4 @@ interface WellColors {
282
351
  }
283
352
  declare function useWellColors(): WellColors;
284
353
 
285
- 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, WELL_SHADOW, type WellColors, getStaggeredWordDuration, isCompactDialogHeight, overlayActionStyles, overlayStyles, useCompactDialog, useOverlayCardColors, useWellColors };
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 };