@tastic/hud 0.24.0 → 0.25.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
@@ -26,7 +26,10 @@ corner of the screen.
26
26
  and `InlineColorPicker` are built on it.
27
27
  - **`useAutoAlign`**: measures a trigger's actual on-screen position and picks whichever alignment
28
28
  (left/right/center, above/below) keeps a popover from overflowing a screen edge - including a
29
- `maxHeight` for the caller to cap content and scroll when neither direction has enough room.
29
+ `maxHeight` for the caller to cap content and scroll when neither direction has enough room. An
30
+ optional `bounds` View (a scroll view that clips the popover) stands in for the window's edges.
31
+ Its `triggerRef` holds a `ViewInstance` (a View's instance in React Native's legacy and strict
32
+ types alike).
30
33
  - **`SectionedDropdown`**: a popover holding any mix of single-select ("pick one", radio-style) and
31
34
  multi-select ("pick some", checkbox-style, optional all/clear footer) sections, divided by rules.
32
35
  - **`InlineColorPicker`**: swatch-grid color popover, columns auto-clamped to 4 or 5 (the default
@@ -34,7 +37,10 @@ corner of the screen.
34
37
  with an optional "taken" color (shown disabled, or swappable). The trigger itself is a `size`-
35
38
  configurable circle showing either an `icon` or a short `tag` (e.g. a saved player identity's own
36
39
  initial or emoji) - `tag` renders at a larger ratio automatically when it's an emoji, since an
37
- emoji glyph reads visually smaller than a bold letter at the same font size.
40
+ emoji glyph reads visually smaller than a bold letter at the same font size. `renderSwatch`
41
+ draws the trigger and each grid swatch in place of the flat fill (told `'trigger'` or
42
+ `'swatch'`; null keeps a swatch flat), and `bounds` keeps the popover inside a scroll view it
43
+ sits in (see `useAutoAlign`).
38
44
  - **`TriggerGauge`**: decorative ring of tick marks around a trigger, showing which option(s) are
39
45
  active without opening the popover.
40
46
  - **`ReadyButton`**: a per-player or standalone ready toggle.
@@ -255,9 +261,9 @@ export function SettingsDialog({ visible, onDismiss, rotation = 0, settings, set
255
261
  own overlay (a result banner, a game-over card) should too, so every card in the fleet looks the same:
256
262
 
257
263
  ```tsx
258
- import { DialogHeader, OverlayBackdrop, OverlayCard, overlayActionStyles, useCompactDialog, useOverlayCardColors } from '@tastic/hud'
264
+ import { DialogHeader, OverlayBackdrop, OverlayCard, overlayActionStyles, SecondaryButton, useCompactDialog, useOverlayCardColors } from '@tastic/hud'
259
265
 
260
- function GameOverCard({ onRestart }: { onRestart: () => void }) {
266
+ function GameOverCard({ onRestart, onQuit }: { onRestart: () => void; onQuit: () => void }) {
261
267
  const { fgMuted } = useOverlayCardColors()
262
268
  const { compact, onLayout } = useCompactDialog()
263
269
  return (
@@ -265,7 +271,10 @@ function GameOverCard({ onRestart }: { onRestart: () => void }) {
265
271
  <OverlayCard accessibilityViewIsModal>
266
272
  <DialogHeader icon='flag-checkered' title='Game Over' compact={compact} />
267
273
  <Text style={{ color: fgMuted }}>Score 42</Text>
268
- <View style={overlayActionStyles.actions}>...</View>
274
+ <View style={overlayActionStyles.actions}>
275
+ <SecondaryButton onPress={onQuit}>Quit</SecondaryButton>
276
+ <Button mode='contained' onPress={onRestart} style={overlayActionStyles.actionButton}>Play Again</Button>
277
+ </View>
269
278
  </OverlayCard>
270
279
  </OverlayBackdrop>
271
280
  )
@@ -285,6 +294,12 @@ function GameOverCard({ onRestart }: { onRestart: () => void }) {
285
294
  is compact when the space the dialog lays out in is under `COMPACT_DIALOG_HEIGHT` (528pt) along the
286
295
  card's own vertical axis, so a phone held sideways. One-button dialogs end in a single contained
287
296
  primary button (`overlayActionStyles.actionButtonSingle`), the Settings sheet's Done included.
297
+ - **The secondary action is `SecondaryButton`.** Cancel, Skip, Back, a result card's Quit: outlined,
298
+ labeled in the card's text color (`fg`) instead of Paper's default (the theme's primary), and sized
299
+ as one of the action row's buttons. It takes no theme or seat color, so the contained primary beside
300
+ it is the card's only colored button and a seat's card never shows another seat's color. Every prop
301
+ overrides those defaults; a `style` is laid over the row's button style. `ConfirmDialog` and the
302
+ how-to-play card use it.
288
303
  - **Blur is automatic.** The card blurs what's behind it when the player's Blur setting is on and the
289
304
  app hands `expo-blur` to auto-paper's `Provider` (`expoBlur={ExpoBlur}`). Otherwise it paints that
290
305
  raised surface color instead: on Android (`BlurView` needs a blur target there, which a card has
@@ -639,7 +654,7 @@ their props types:
639
654
  - Stats: `BaseStatsScreen`, `StatSection`, `StatRow`, `AchievementRow`, `LOCKED_BADGE_COLOR`,
640
655
  `AchievementCatalogSection`, `ActivityStatSection`, `useWellColors`, `WELL_SHADOW`
641
656
  - Chrome: `CornerActionButtons`, `ContentGutter`, `StaggeredWord`, `getStaggeredWordDuration`
642
- - Overlay cards: `OverlayCard`, `OverlayBackdrop`, `useOverlayCardColors`, `DialogHeader`, `useCompactDialog`, `isCompactDialogHeight`, `COMPACT_DIALOG_HEIGHT`
657
+ - Overlay cards: `OverlayCard`, `OverlayBackdrop`, `useOverlayCardColors`, `SecondaryButton`, `DialogHeader`, `useCompactDialog`, `isCompactDialogHeight`, `COMPACT_DIALOG_HEIGHT`
643
658
  - Popovers (0.23.0+): `PopoverBody`, `PressAwayOverlay`, `usePopoverHost` (and its `PopoverHost` type),
644
659
  `useAutoAlign` (and its `AlignResult`, `PopoverAlign`, `PopoverRotation` and `PopoverVerticalAlign`
645
660
  types), `InlineColorPicker`, `getInlineColorPickerContentSize`
@@ -1,9 +1,10 @@
1
1
  import * as react from 'react';
2
- import { ReactNode, RefObject } from 'react';
2
+ import { ReactNode, RefObject, ComponentRef } from 'react';
3
3
  import { AchievementCatalogRow } from '@tastic/achievements';
4
4
  import { ViewRotation } from '@tastic/core';
5
5
  import { Insets, StyleProp, ViewStyle, View, LayoutChangeEvent, TextStyle } from 'react-native';
6
6
  import { SeedColor } from '@rific/auto-paper';
7
+ import { ButtonProps } from '@rific/feedback-press';
7
8
 
8
9
  interface Props$a {
9
10
  rows: AchievementCatalogRow[];
@@ -145,9 +146,10 @@ interface AlignResult {
145
146
  verticalAlign: PopoverVerticalAlign;
146
147
  maxHeight: number;
147
148
  measured: boolean;
148
- triggerRef: RefObject<View | null>;
149
+ triggerRef: RefObject<ViewInstance | null>;
149
150
  }
150
- declare function useAutoAlign(open: boolean, contentWidth: number, contentHeight: number, rotation?: PopoverRotation): {
151
+ type ViewInstance = ComponentRef<typeof View>;
152
+ declare function useAutoAlign(open: boolean, contentWidth: number, contentHeight: number, rotation?: PopoverRotation, bounds?: RefObject<ViewInstance | null>): {
151
153
  align: PopoverAlign;
152
154
  maxHeight: number;
153
155
  measured: boolean;
@@ -166,6 +168,8 @@ declare function getInlineColorPickerContentSize(swatchCount: number, windowWidt
166
168
  width: number;
167
169
  height: number;
168
170
  };
171
+ type InlineColorPickerSwatchPlace = 'trigger' | 'swatch';
172
+ type InlineColorPickerSwatchRenderer = (color: string, size: number, place: InlineColorPickerSwatchPlace) => ReactNode;
169
173
  interface Props$4 {
170
174
  id: string;
171
175
  host: PopoverHost;
@@ -185,8 +189,10 @@ interface Props$4 {
185
189
  autoDismiss?: boolean;
186
190
  columns?: number;
187
191
  size?: number;
192
+ renderSwatch?: InlineColorPickerSwatchRenderer;
193
+ bounds?: RefObject<ViewInstance | null>;
188
194
  }
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;
195
+ declare function InlineColorPicker({ id, host, value, onChange, previewValue, swatches, takenValue, allowSwapTaken, dark, align: forcedAlign, alignOverride, rotation: rotationOverride, icon, tag, labelFontFamily, autoDismiss, columns, size, renderSwatch, bounds }: Props$4): react.JSX.Element;
190
196
 
191
197
  declare const overlayStyles: {
192
198
  card: {
@@ -298,6 +304,9 @@ interface RotatedFrameProps {
298
304
  * never put a gesture-tracked game board inside it. */
299
305
  declare function RotatedFrame({ children, rotation: rotationOverride, rotatedSafeArea, portalHost, passThrough, maxContentWidth }: RotatedFrameProps): react.JSX.Element;
300
306
 
307
+ type SecondaryButtonProps = ButtonProps;
308
+ declare function SecondaryButton({ style, ...props }: SecondaryButtonProps): react.JSX.Element;
309
+
301
310
  declare function getStaggeredWordDuration(letterCount: number): number;
302
311
  interface StaggeredWordProps {
303
312
  word: string;
@@ -351,4 +360,4 @@ interface WellColors {
351
360
  }
352
361
  declare function useWellColors(): WellColors;
353
362
 
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 };
363
+ export { AchievementCatalogSection, AchievementRow, ActivityStatSection, type AlignResult, BaseSettingsDialog, type BaseSettingsDialogProps, BaseStatsScreen, COMPACT_DIALOG_HEIGHT, ConfirmDialog, type ConfirmDialogProps, ContentGutter, CornerActionButtons, DialogHeader, type DialogHeaderProps, InlineColorPicker, type InlineColorPickerSwatchPlace, type InlineColorPickerSwatchRenderer, 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, SecondaryButton, type SecondaryButtonProps, StaggeredWord, type StaggeredWordProps, StatRow, StatSection, UpdateDialog, type UpdateDialogProps, type ViewInstance, WELL_SHADOW, type WellColors, getInlineColorPickerContentSize, getStaggeredWordDuration, isCompactDialogHeight, overlayActionStyles, overlayStyles, useAutoAlign, useCompactDialog, useOverlayCardColors, usePopoverHost, useWellColors };
@@ -1,9 +1,10 @@
1
1
  import * as react from 'react';
2
- import { ReactNode, RefObject } from 'react';
2
+ import { ReactNode, RefObject, ComponentRef } from 'react';
3
3
  import { AchievementCatalogRow } from '@tastic/achievements';
4
4
  import { ViewRotation } from '@tastic/core';
5
5
  import { Insets, StyleProp, ViewStyle, View, LayoutChangeEvent, TextStyle } from 'react-native';
6
6
  import { SeedColor } from '@rific/auto-paper';
7
+ import { ButtonProps } from '@rific/feedback-press';
7
8
 
8
9
  interface Props$a {
9
10
  rows: AchievementCatalogRow[];
@@ -145,9 +146,10 @@ interface AlignResult {
145
146
  verticalAlign: PopoverVerticalAlign;
146
147
  maxHeight: number;
147
148
  measured: boolean;
148
- triggerRef: RefObject<View | null>;
149
+ triggerRef: RefObject<ViewInstance | null>;
149
150
  }
150
- declare function useAutoAlign(open: boolean, contentWidth: number, contentHeight: number, rotation?: PopoverRotation): {
151
+ type ViewInstance = ComponentRef<typeof View>;
152
+ declare function useAutoAlign(open: boolean, contentWidth: number, contentHeight: number, rotation?: PopoverRotation, bounds?: RefObject<ViewInstance | null>): {
151
153
  align: PopoverAlign;
152
154
  maxHeight: number;
153
155
  measured: boolean;
@@ -166,6 +168,8 @@ declare function getInlineColorPickerContentSize(swatchCount: number, windowWidt
166
168
  width: number;
167
169
  height: number;
168
170
  };
171
+ type InlineColorPickerSwatchPlace = 'trigger' | 'swatch';
172
+ type InlineColorPickerSwatchRenderer = (color: string, size: number, place: InlineColorPickerSwatchPlace) => ReactNode;
169
173
  interface Props$4 {
170
174
  id: string;
171
175
  host: PopoverHost;
@@ -185,8 +189,10 @@ interface Props$4 {
185
189
  autoDismiss?: boolean;
186
190
  columns?: number;
187
191
  size?: number;
192
+ renderSwatch?: InlineColorPickerSwatchRenderer;
193
+ bounds?: RefObject<ViewInstance | null>;
188
194
  }
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;
195
+ declare function InlineColorPicker({ id, host, value, onChange, previewValue, swatches, takenValue, allowSwapTaken, dark, align: forcedAlign, alignOverride, rotation: rotationOverride, icon, tag, labelFontFamily, autoDismiss, columns, size, renderSwatch, bounds }: Props$4): react.JSX.Element;
190
196
 
191
197
  declare const overlayStyles: {
192
198
  card: {
@@ -298,6 +304,9 @@ interface RotatedFrameProps {
298
304
  * never put a gesture-tracked game board inside it. */
299
305
  declare function RotatedFrame({ children, rotation: rotationOverride, rotatedSafeArea, portalHost, passThrough, maxContentWidth }: RotatedFrameProps): react.JSX.Element;
300
306
 
307
+ type SecondaryButtonProps = ButtonProps;
308
+ declare function SecondaryButton({ style, ...props }: SecondaryButtonProps): react.JSX.Element;
309
+
301
310
  declare function getStaggeredWordDuration(letterCount: number): number;
302
311
  interface StaggeredWordProps {
303
312
  word: string;
@@ -351,4 +360,4 @@ interface WellColors {
351
360
  }
352
361
  declare function useWellColors(): WellColors;
353
362
 
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 };
363
+ export { AchievementCatalogSection, AchievementRow, ActivityStatSection, type AlignResult, BaseSettingsDialog, type BaseSettingsDialogProps, BaseStatsScreen, COMPACT_DIALOG_HEIGHT, ConfirmDialog, type ConfirmDialogProps, ContentGutter, CornerActionButtons, DialogHeader, type DialogHeaderProps, InlineColorPicker, type InlineColorPickerSwatchPlace, type InlineColorPickerSwatchRenderer, 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, SecondaryButton, type SecondaryButtonProps, StaggeredWord, type StaggeredWordProps, StatRow, StatSection, UpdateDialog, type UpdateDialogProps, type ViewInstance, WELL_SHADOW, type WellColors, getInlineColorPickerContentSize, getStaggeredWordDuration, isCompactDialogHeight, overlayActionStyles, overlayStyles, useAutoAlign, useCompactDialog, useOverlayCardColors, usePopoverHost, useWellColors };