@tastic/shell 0.3.1 → 0.5.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
@@ -17,12 +17,12 @@ package ecosystem, on [`@tastic/hud`](https://github.com/jayrdeaton/react-native
17
17
  ## What's in here
18
18
 
19
19
  - **`RootLayout`**: the root of the app (gesture root, safe area, fonts, Redux and its persist gate,
20
- the theme, profiles, every game's own provider, the splash gates, the shared orientation reading,
20
+ the theme, profiles, every game's own provider, the splash gates,
21
21
  toasts, How to Play, the OTA update dialog) around expo-router's stack. The stack follows the app's
22
22
  own theme, not the phone's light or dark appearance: the status bar's text, the root window and the
23
23
  navigation theme's background (what shows in a sliding screen's corners during a push or pop).
24
24
  - **Screens** for the routes: `HomeScreen` (the pack's hero, seat 1's button, a row per game, or a
25
- grid of preview tiles on a wide screen), `LoadoutRoute` and `PlayRoute` (`loadout/[game]`,
25
+ grid of preview tiles on a wide screen, split into tabs where the pack has them), `LoadoutRoute` and `PlayRoute` (`loadout/[game]`,
26
26
  `play/[game]`), `ProfilesRoute` and `StatsScreen`.
27
27
  - **The store**: `createPackStore(pack, { keyPrefix, migrate, blacklist, serializableIgnoredPaths,
28
28
  middleware })` builds one persisted store from the shell's keys (theme, haptics, sound, Keep Awake,
@@ -116,8 +116,7 @@ PuckTastic and DuelTastic draw what they always did:
116
116
  | `Provider?` | Mounted once around How to Play and the stack, inside the store, the theme, profiles and every game's `Provider` (one stats context across the pack's games). |
117
117
  | `useScreenOptions?` | A hook returning stack screen options (`StackScreenOptions`), merged after the shell's own (a status bar style of the pack's own, Reduce Motion's crossfade). The shell's already follow the app's theme, and stay dark over a `Backdrop`. |
118
118
  | `useFeedbackSounds?` | A hook returning the two sounds every button plays (`FeedbackSounds`: `selection`, `notification`), in place of the shell's two wavs. |
119
- | `Toaster?` | The pack's own toaster, drawn in a frame turned with the phone (with the safe-area insets turned onto its edges) in place of the shell's. The toast provider is given no Paper, so nothing portals it out of the frame. |
120
- | `portraitWhileKeyboard?` | Every screen reads upright while the software keyboard is up (`@tastic/core`'s `OrientationProvider`), for naming a profile sideways. |
119
+ | `Toaster?` | The pack's own toaster, drawn in a frame over the whole app (inside the safe area) in place of the shell's. The toast provider is given no Paper, so nothing portals it out of the frame. |
121
120
  | `edgeGuard?` | `false` leaves Edge Guard out of Settings (no edge controls, no Edge Guard plugin). |
122
121
  | `seatTheme?` | `(colors, dark) => ({ color, harmony })`: the theme the seats' colors make (a muted seed from seat 1's color), applied whenever they or dark mode change and as a fresh install's theme, in place of a triad of the raw colors. With it, `useSeatColors` reads each seat's color from where it's remembered (`seatColors`) rather than from the theme. |
123
122
  | `previewColor?` | `(hex, dark) => string`: how every profile color is drawn (the seat buttons and their swatches on Home and in the loadouts, a loadout's Ready button and seat controls, each `ProfileChip`), mounted as `@tastic/profile`'s `ProfileColorProvider`. Saved colors stay as picked. |
@@ -129,14 +128,15 @@ PuckTastic and DuelTastic draw what they always did:
129
128
  | `resetStats?` | The stats screen's Reset where the pack resets stats itself (`PackStatsReset`: a `useReset` hook returning `(profileId) => void`, and the `labels` for a player's name, Guest, or `null` for Everyone). It follows the player picker, not the game picker. |
130
129
  | `statsGameTitles?` | `false` leaves each game's name off its sections on All Games, where the sections name it. |
131
130
  | `newProfileColor?` | A new profile's starting color on Profiles. Unset is auto-paper's first swatch. |
132
- | `usePickerAlign?` | `(open, contentWidth, contentHeight, options?) => AlignResult` (`PickerAlign`), a hook: where seat 1's menu on Home, both seat buttons' menus in a loadout's one-human row (2 Player keeps each menu in its own player's half), the stats screen's two pickers and a profile's color swatch open. hud's own placement measures a turned button against the upright window, so with the phone held sideways it can run a menu off the screen (seen on the iOS simulator, 2026-10-29); a pack whose screens turn hands in a frame-aware one (Solitaire's `useFrameAutoAlign`). Profiles passes `{ maxContentWidth: 640 }`, its roster's column. Unset is hud's placement. |
131
+ | `usePickerAlign?` | `(open, contentWidth, contentHeight, options?) => AlignResult` (`PickerAlign`), a hook: where seat 1's menu on Home, both seat buttons' menus in a loadout's one-human row (2 Player keeps each menu in its own player's half), the stats screen's two pickers and a profile's color swatch open. It was added because hud's own placement measured a button in a frame turned by `@tastic/core`'s drawn rotation against the upright window (Solitaire's `useFrameAutoAlign`); nothing turns since core 0.15, so a pack may no longer need one. Profiles passes `{ maxContentWidth: 640 }`, its roster's column. Unset is hud's placement. |
132
+ | `homeTabs?` | Tabs splitting Home's games (`HomeTab`: a `label`, and `includes(game)`, which of the pack's games it shows, in the pack's order): a switch under seat 1's button, or over the grid on a wide screen, on the theme's surface over a `Backdrop`, showing one tab's games at a time. It opens on the first tab and keeps the one picked while Home is covered or the window changes. The other tabs' games stay mounted, hidden, so a switch draws nothing new. A game no tab includes isn't on Home. Unset, or a single tab, shows every game with no switch. Solitaire's: Solitaire (no `seatTwo`) and Two Player. |
133
133
 
134
134
  ### `GameDefinition`
135
135
 
136
136
  Each game is one object: its `id`, `title`, `blurb` and `icon` (a component drawn in the seats'
137
137
  colors, or `imageGameIcon({ light, dark })` for a light and dark pair of pictures), its seat 2
138
- choices (`seatTwo`: `'cpu'`, `'person'`, `'nobody'`) and how 2 Player seats its players
139
- (`twoPlayerSeats`), the store `reducers` it mounts, its root `Provider`, its `useLoadout(mode)`, its
138
+ choices (`seatTwo`: `'cpu'`, `'person'`, `'nobody'`) and whether 2 Player seats its players side by
139
+ side in a wide window (`sideBySideWhenWide`), the store `reducers` it mounts, its root `Provider`, its `useLoadout(mode)`, its
140
140
  `PlayScreen`, its `StatsSections` and `AchievementList`, `resetStats`, and its How to Play `guide`.
141
141
  See `src/types.ts` for every field.
142
142
 
@@ -144,7 +144,7 @@ What a game can leave out or add, each optional, so a two-seat game sets none of
144
144
 
145
145
  | Field | |
146
146
  | --- | --- |
147
- | no `seatTwo` (nor `twoPlayerSeats`) | A game for one player: its loadout has no seat 2 button, every round is solo (`useActiveRound` falls back to `'solo'`), and its How to Play describes a solo round. |
147
+ | no `seatTwo` (nor `sideBySideWhenWide`) | A game for one player: its loadout has no seat 2 button, every round is solo (`useActiveRound` falls back to `'solo'`), and its How to Play describes a solo round. |
148
148
  | no `useLoadout` | Nothing to set up first: Home opens its play screen straight away, after its How to Play the first time, and a link to its loadout plays it. Its rule variants go in its play screen's Settings: `<SettingsDialog>` takes `children`. |
149
149
  | no `cpuDifficulty` (in `GameLoadout`) | A CPU with no levels: seat 2's menu offers one plain CPU. |
150
150
  | `resumable` | A cold launch drops the player back into its play screen if they left the app there rather than backing out of it. The shell remembers only which game (`lastActiveGame`); the game saves and restores its own board. |
@@ -153,8 +153,8 @@ What a game can leave out or add, each optional, so a two-seat game sets none of
153
153
  | no `Provider` | A game whose stats live in the pack's own `Provider`. |
154
154
  | no `AchievementList`, no `resetStats` | A game whose achievements are in the pack's one list, and whose stats the pack resets (`PackDefinition.AchievementList`, `resetStats`). |
155
155
  | no `guide` (`GuidelessGameDefinition`) | A game the pack's own `guide` teaches: its tile opens without cards the first time. A `GameDefinition` keeps `guide` required, so a pack's code that reads its games' cards keeps compiling; `PackDefinition.games` takes either (`PackGameDefinition`). |
156
- | `Rules` | Its tile's rules button opens this sheet (`GameRulesProps`: `visible`, `onDismiss`) in place of its How to Play. It portals into a host inside Home's turned frame, so it's laid out against the frame and turned with it. |
157
- | `keepStatusBar` | Its play screen keeps the status bar while the phone is held upright. Unset, every play screen hides it for the whole round. |
156
+ | `Rules` | Its tile's rules button opens this sheet (`GameRulesProps`: `visible`, `onDismiss`) in place of its How to Play. It portals into a host inside Home's frame, so it's laid out against Home's safe area. |
157
+ | `keepStatusBar` | Its play screen keeps the status bar. Unset, every play screen hides it for the whole round. |
158
158
 
159
159
  A game never imports another game, and the shell never imports a game: games reach the shell only
160
160
  through the pack (`usePack()`).
@@ -175,15 +175,27 @@ through the pack (`usePack()`).
175
175
 
176
176
  Six fixes CardTastic's move brought to every pack's screens: Home's press-away overlay sits in the
177
177
  scroller beside seat 1's button in the upright layout (as the frame's first child it was under the whole
178
- scroller, so a press on a row played the game), seat 1's menu closes on every turn of the phone, both of
178
+ scroller, so a press on a row played the game), seat 1's menu closes on every change of window, both of
179
179
  Home's scrollers fade out at an edge with more past it (auto-paper's `FadingScrollView`), a press
180
180
  anywhere on the stats screen (its header and margins too) closes a picker's menu, the stats screen's
181
- column is capped at 640pt in the wide layout, and Profiles turns with the phone (hud's `RotatedFrame`,
182
- its roster capped at 640pt in the wide layout). Every hud import goes through `@tastic/hud/chrome`,
181
+ column is capped at 640pt in the wide layout, and Profiles' roster is capped at 640pt in the wide
182
+ layout (hud's `RotatedFrame`, which nothing turns any more). Every hud import goes through `@tastic/hud/chrome`,
183
183
  `/guide` or `/lobby`, so an app with no Skia can install the shell; a pack's own imports don't change.
184
184
  The shell's routes are handed to expo-router as plain `Href`s, so an app with typed routes type-checks
185
185
  the shell before its own routes match.
186
186
 
187
+ ### The OS turns (0.5.0)
188
+
189
+ Needs `@tastic/core` 0.15, where the seat mode is the window's shape on every platform. The shell no
190
+ longer reads the accelerometer, draws a turn or offers Lock Orientation. A pack bumping to it:
191
+
192
+ - replaces `twoPlayerSeats` with `sideBySideWhenWide: true` on the games whose 2 Player seats go side by
193
+ side in a wide window (where `faceToFaceOnWeb` was false), and drops it elsewhere;
194
+ - drops `portraitWhileKeyboard`, and any `rotation` it read from the loadout's props or passed to
195
+ `SettingsDialog`;
196
+ - takes `"@tastic/core"` out of `app.json`'s plugins, sets `UIViewControllerBasedStatusBarAppearance: true`
197
+ in `ios.infoPlist` (the stack sets the status bar per screen), and makes a new native build.
198
+
187
199
  ## Peer dependencies
188
200
 
189
201
  None are bundled. The floors are the versions PuckTastic and DuelTastic ran the shell on when it
@@ -197,7 +209,7 @@ became a package (the lower of the two where they differ).
197
209
  | `expo-splash-screen`, `@rific/splash-gate` | >=58.0.10, >=0.2.3 | holding the splash screen until the theme, fonts and profiles are ready |
198
210
  | `expo-constants` | >=58.0.12 | the web tab title |
199
211
  | `expo-blur`, `@react-native-masked-view/masked-view` | >=58.0.4, >=0.3.2 | auto-paper's blur and its scroll fade, Home's fading scrollers |
200
- | `expo-haptics`, `expo-keep-awake`, `expo-sensors` | >=58.0.7, >=58.0.3, >=58.0.4 | the toaster's haptics, Keep Awake, the orientation reading |
212
+ | `expo-haptics`, `expo-keep-awake` | >=58.0.7, >=58.0.3 | the toaster's haptics, Keep Awake |
201
213
  | `react-native-gesture-handler`, `react-native-reanimated`, `react-native-safe-area-context` | >=3.3.0, >=4.7.1, >=5.10.1 | the gesture root, auto-paper's dialogs and the loadout's fades, insets |
202
214
  | `react-native-paper` | >=5.15.3 | text, icons, the toaster and feedback-press |
203
215
  | `@reduxjs/toolkit`, `redux`, `react-redux`, `redux-persist`, `@react-native-async-storage/async-storage` | >=2.13.0, >=5.0.1, >=9.3.0, >=6.0.0, >=2.2.0 | the store and where it's saved |
@@ -205,7 +217,7 @@ became a package (the lower of the two where they differ).
205
217
  | `@rific/core` | >=0.5.0 | settings slices, Keep Awake, `safeBack` |
206
218
  | `@rific/feedback-press` | >=0.13.1 | haptic and sound settings, the UI sounds |
207
219
  | `@rific/toaster` | >=0.10.1 | toasts (DuelTastic runs 0.12, PuckTastic 0.10) |
208
- | `@tastic/core` | >=0.14.0 | orientation, rotation, the status bar and root background |
220
+ | `@tastic/core` | >=0.15.0 | the seat mode from the window's shape, the root background |
209
221
  | `@tastic/hud` | >=0.27.1 | Settings, the stats screen, the loadout's panels (its Skia-free `/lobby` entry, new in 0.26.0; 0.27.1's options for a pack drawn on its own backdrop), How to Play |
210
222
  | `@tastic/profile` | >=0.16.2 | profiles, the seat buttons, seat colors |
211
223
  | `@tastic/achievements` | >=0.6.0 | `createGameStats`, `forgetProfileAchievements` |
package/dist/index.d.mts CHANGED
@@ -2,7 +2,6 @@ import * as react from 'react';
2
2
  import { ComponentType, ReactNode, ComponentProps } from 'react';
3
3
  import * as _rific_auto_paper from '@rific/auto-paper';
4
4
  import { ThemeAppearance, ThemeSettings } from '@rific/auto-paper';
5
- import { ViewRotation } from '@tastic/core';
6
5
  import { PopoverHost, AlignResult } from '@tastic/hud/chrome';
7
6
  import { GuideStep } from '@tastic/hud/guide';
8
7
  import { MenuOption } from '@tastic/hud/lobby';
@@ -85,8 +84,6 @@ declare const opponentActions: {
85
84
  };
86
85
 
87
86
  interface AppSettings {
88
- lockOrientation: boolean;
89
- lockedRotation?: ViewRotation;
90
87
  deferBottomEdgeGestures: boolean;
91
88
  }
92
89
  declare const DEFAULT_APP_SETTINGS: AppSettings;
@@ -140,7 +137,6 @@ declare function seatTwoFor(saved: SeatTwo, choices: readonly SeatTwo[] | undefi
140
137
  declare function humanSeatsFor(mode: RoundMode): Seat[];
141
138
  interface LoadoutOptionsProps {
142
139
  host: PopoverHost;
143
- rotation: ViewRotation;
144
140
  accentColor: string;
145
141
  mutedColor: string;
146
142
  onAccentColor: string;
@@ -153,7 +149,6 @@ interface SeatControlLook {
153
149
  seatColor: string;
154
150
  mutedColor: string;
155
151
  dark: boolean;
156
- rotation: ViewRotation;
157
152
  }
158
153
  interface GameLoadout {
159
154
  roundSettings: object;
@@ -211,10 +206,7 @@ interface GameDefinition {
211
206
  icon?: ComponentType<GameIconProps>;
212
207
  Preview?: ComponentType<GamePreviewProps>;
213
208
  seatTwo?: readonly SeatTwo[];
214
- twoPlayerSeats?: {
215
- faceToFaceOnWeb: boolean;
216
- followUpsideDown: boolean;
217
- };
209
+ sideBySideWhenWide?: boolean;
218
210
  reducers: Record<string, Reducer>;
219
211
  Provider?: ComponentType<{
220
212
  children: ReactNode;
@@ -252,6 +244,10 @@ interface PackStatsSectionsProps {
252
244
  profileId: string | null;
253
245
  gameId: string | null;
254
246
  }
247
+ interface HomeTab {
248
+ label: string;
249
+ includes: (game: PackGameDefinition) => boolean;
250
+ }
255
251
  type StackScreenOptions = Exclude<NonNullable<ComponentProps<typeof Stack>['screenOptions']>, (...args: never[]) => unknown>;
256
252
  interface FeedbackSounds {
257
253
  selection: () => void;
@@ -275,6 +271,7 @@ interface PackDefinition {
275
271
  wordmark: readonly [string, string];
276
272
  colorCaption: string;
277
273
  games: readonly PackGameDefinition[];
274
+ homeTabs?: readonly HomeTab[];
278
275
  seatColors: Record<Seat, string>;
279
276
  appearance?: ThemeAppearance;
280
277
  HeroTitle: ComponentType<HeroTitleProps>;
@@ -292,7 +289,6 @@ interface PackDefinition {
292
289
  useScreenOptions?: () => StackScreenOptions;
293
290
  useFeedbackSounds?: () => FeedbackSounds;
294
291
  Toaster?: ComponentType;
295
- portraitWhileKeyboard?: boolean;
296
292
  edgeGuard?: boolean;
297
293
  seatTheme?: (colors: Record<Seat, string>, dark: boolean) => Pick<ThemeSettings, 'color' | 'harmony'>;
298
294
  previewColor?: (hex: string, dark: boolean) => string;
@@ -344,7 +340,6 @@ declare function createPackStore(pack: PackStoreSource, { keyPrefix, migrate, bl
344
340
  liveplay: LiveplaySliceState;
345
341
  } & redux_persist_es_persistReducer.PersistPartial, {
346
342
  type: string;
347
- payload?: unknown;
348
343
  } | {
349
344
  type: string;
350
345
  payload?: unknown;
@@ -354,6 +349,7 @@ declare function createPackStore(pack: PackStoreSource, { keyPrefix, migrate, bl
354
349
  type: string;
355
350
  } | {
356
351
  type: string;
352
+ payload?: unknown;
357
353
  }, _reduxjs_toolkit.Tuple<[redux.StoreEnhancer<{
358
354
  dispatch: redux_thunk.ThunkDispatch<{
359
355
  theme: _rific_auto_paper.ThemeState;
@@ -406,11 +402,10 @@ declare function imageGameIcon(images: {
406
402
  interface SettingsDialogProps {
407
403
  visible: boolean;
408
404
  onDismiss: () => void;
409
- rotation?: ViewRotation;
410
405
  onShowHowToPlay?: () => void;
411
406
  children?: ReactNode;
412
407
  }
413
- declare function SettingsDialog({ visible, onDismiss, rotation, onShowHowToPlay, children }: SettingsDialogProps): react.JSX.Element;
408
+ declare function SettingsDialog({ visible, onDismiss, onShowHowToPlay, children }: SettingsDialogProps): react.JSX.Element;
414
409
 
415
410
  declare function useActiveRound<S extends object>(game: string, defaults: S): {
416
411
  mode: RoundMode;
@@ -556,4 +551,5 @@ declare function createPlayerSettings<S extends WithControls<C>, C>({ id, defaul
556
551
  };
557
552
  };
558
553
 
559
- export { type ActiveRound, type AppSettings, DEFAULT_APP_SETTINGS, DEFAULT_OPPONENT, type FeedbackSounds, GUEST_PLAYER_ID, type GameDefinition, type GameGuide, type GameGuideState, type GameIconProps, type GameLoadout, type GamePreviewProps, type GameRulesProps, type GuidelessGameDefinition, type HeroTitleProps, HomeScreen, type LiveplaySliceState, type LoadoutOptionsProps, LoadoutRoute, type OpponentState, PREVIEW_ASPECT, type PackDefinition, type PackGameDefinition, type PackGuide, PackProvider, type PackStatsReset, type PackStatsSectionsProps, type PackStatsTab, type PackStore, type PackStoreConfig, type PackStoreSource, type PickerAlign, PlayRoute, type PlayerControlsState, type PlayerSettingsState, type ProfileSelectionState, ProfilesProvider, ProfilesRoute, type RecordResult, RootLayout, type RoundMode, type Seat, type SeatColorsState, type SeatControlLook, type SeatTwo, SettingsDialog, type SettingsDialogProps, type ShellState, type StackScreenOptions, StatsScreen, appSettingsActions, reducer$1 as appSettingsReducer, createGameGuideSlice, createGameStats, createPackStore, createPlayerSettings, createSeatColorsReducer, createShellReducers, defaultProfileSelectionState, defaultSeatColorsState, forgetProfileAchievements, humanSeatsFor, imageGameIcon, liveplayActions, reducer$3 as liveplayReducer, onProfileRemoved, opponentActions, reducer$2 as opponentReducer, profileSelectionActions, reducer as profileSelectionReducer, roundModeFor, seatColorsActions, seatPlayerKey, seatTwoFor, useActiveRound, useAppSettings, useGameGuide, useOpponent, usePack, usePackGame, useProfiles, useSeatColors };
554
+ export { DEFAULT_APP_SETTINGS, DEFAULT_OPPONENT, GUEST_PLAYER_ID, HomeScreen, LoadoutRoute, PREVIEW_ASPECT, PackProvider, PlayRoute, ProfilesProvider, ProfilesRoute, RootLayout, SettingsDialog, StatsScreen, appSettingsActions, reducer$1 as appSettingsReducer, createGameGuideSlice, createGameStats, createPackStore, createPlayerSettings, createSeatColorsReducer, createShellReducers, defaultProfileSelectionState, defaultSeatColorsState, forgetProfileAchievements, humanSeatsFor, imageGameIcon, liveplayActions, reducer$3 as liveplayReducer, onProfileRemoved, opponentActions, reducer$2 as opponentReducer, profileSelectionActions, reducer as profileSelectionReducer, roundModeFor, seatColorsActions, seatPlayerKey, seatTwoFor, useActiveRound, useAppSettings, useGameGuide, useOpponent, usePack, usePackGame, useProfiles, useSeatColors };
555
+ export type { ActiveRound, AppSettings, FeedbackSounds, GameDefinition, GameGuide, GameGuideState, GameIconProps, GameLoadout, GamePreviewProps, GameRulesProps, GuidelessGameDefinition, HeroTitleProps, HomeTab, LiveplaySliceState, LoadoutOptionsProps, OpponentState, PackDefinition, PackGameDefinition, PackGuide, PackStatsReset, PackStatsSectionsProps, PackStatsTab, PackStore, PackStoreConfig, PackStoreSource, PickerAlign, PlayerControlsState, PlayerSettingsState, ProfileSelectionState, RecordResult, RoundMode, Seat, SeatColorsState, SeatControlLook, SeatTwo, SettingsDialogProps, ShellState, StackScreenOptions };
package/dist/index.d.ts CHANGED
@@ -2,7 +2,6 @@ import * as react from 'react';
2
2
  import { ComponentType, ReactNode, ComponentProps } from 'react';
3
3
  import * as _rific_auto_paper from '@rific/auto-paper';
4
4
  import { ThemeAppearance, ThemeSettings } from '@rific/auto-paper';
5
- import { ViewRotation } from '@tastic/core';
6
5
  import { PopoverHost, AlignResult } from '@tastic/hud/chrome';
7
6
  import { GuideStep } from '@tastic/hud/guide';
8
7
  import { MenuOption } from '@tastic/hud/lobby';
@@ -85,8 +84,6 @@ declare const opponentActions: {
85
84
  };
86
85
 
87
86
  interface AppSettings {
88
- lockOrientation: boolean;
89
- lockedRotation?: ViewRotation;
90
87
  deferBottomEdgeGestures: boolean;
91
88
  }
92
89
  declare const DEFAULT_APP_SETTINGS: AppSettings;
@@ -140,7 +137,6 @@ declare function seatTwoFor(saved: SeatTwo, choices: readonly SeatTwo[] | undefi
140
137
  declare function humanSeatsFor(mode: RoundMode): Seat[];
141
138
  interface LoadoutOptionsProps {
142
139
  host: PopoverHost;
143
- rotation: ViewRotation;
144
140
  accentColor: string;
145
141
  mutedColor: string;
146
142
  onAccentColor: string;
@@ -153,7 +149,6 @@ interface SeatControlLook {
153
149
  seatColor: string;
154
150
  mutedColor: string;
155
151
  dark: boolean;
156
- rotation: ViewRotation;
157
152
  }
158
153
  interface GameLoadout {
159
154
  roundSettings: object;
@@ -211,10 +206,7 @@ interface GameDefinition {
211
206
  icon?: ComponentType<GameIconProps>;
212
207
  Preview?: ComponentType<GamePreviewProps>;
213
208
  seatTwo?: readonly SeatTwo[];
214
- twoPlayerSeats?: {
215
- faceToFaceOnWeb: boolean;
216
- followUpsideDown: boolean;
217
- };
209
+ sideBySideWhenWide?: boolean;
218
210
  reducers: Record<string, Reducer>;
219
211
  Provider?: ComponentType<{
220
212
  children: ReactNode;
@@ -252,6 +244,10 @@ interface PackStatsSectionsProps {
252
244
  profileId: string | null;
253
245
  gameId: string | null;
254
246
  }
247
+ interface HomeTab {
248
+ label: string;
249
+ includes: (game: PackGameDefinition) => boolean;
250
+ }
255
251
  type StackScreenOptions = Exclude<NonNullable<ComponentProps<typeof Stack>['screenOptions']>, (...args: never[]) => unknown>;
256
252
  interface FeedbackSounds {
257
253
  selection: () => void;
@@ -275,6 +271,7 @@ interface PackDefinition {
275
271
  wordmark: readonly [string, string];
276
272
  colorCaption: string;
277
273
  games: readonly PackGameDefinition[];
274
+ homeTabs?: readonly HomeTab[];
278
275
  seatColors: Record<Seat, string>;
279
276
  appearance?: ThemeAppearance;
280
277
  HeroTitle: ComponentType<HeroTitleProps>;
@@ -292,7 +289,6 @@ interface PackDefinition {
292
289
  useScreenOptions?: () => StackScreenOptions;
293
290
  useFeedbackSounds?: () => FeedbackSounds;
294
291
  Toaster?: ComponentType;
295
- portraitWhileKeyboard?: boolean;
296
292
  edgeGuard?: boolean;
297
293
  seatTheme?: (colors: Record<Seat, string>, dark: boolean) => Pick<ThemeSettings, 'color' | 'harmony'>;
298
294
  previewColor?: (hex: string, dark: boolean) => string;
@@ -344,7 +340,6 @@ declare function createPackStore(pack: PackStoreSource, { keyPrefix, migrate, bl
344
340
  liveplay: LiveplaySliceState;
345
341
  } & redux_persist_es_persistReducer.PersistPartial, {
346
342
  type: string;
347
- payload?: unknown;
348
343
  } | {
349
344
  type: string;
350
345
  payload?: unknown;
@@ -354,6 +349,7 @@ declare function createPackStore(pack: PackStoreSource, { keyPrefix, migrate, bl
354
349
  type: string;
355
350
  } | {
356
351
  type: string;
352
+ payload?: unknown;
357
353
  }, _reduxjs_toolkit.Tuple<[redux.StoreEnhancer<{
358
354
  dispatch: redux_thunk.ThunkDispatch<{
359
355
  theme: _rific_auto_paper.ThemeState;
@@ -406,11 +402,10 @@ declare function imageGameIcon(images: {
406
402
  interface SettingsDialogProps {
407
403
  visible: boolean;
408
404
  onDismiss: () => void;
409
- rotation?: ViewRotation;
410
405
  onShowHowToPlay?: () => void;
411
406
  children?: ReactNode;
412
407
  }
413
- declare function SettingsDialog({ visible, onDismiss, rotation, onShowHowToPlay, children }: SettingsDialogProps): react.JSX.Element;
408
+ declare function SettingsDialog({ visible, onDismiss, onShowHowToPlay, children }: SettingsDialogProps): react.JSX.Element;
414
409
 
415
410
  declare function useActiveRound<S extends object>(game: string, defaults: S): {
416
411
  mode: RoundMode;
@@ -556,4 +551,5 @@ declare function createPlayerSettings<S extends WithControls<C>, C>({ id, defaul
556
551
  };
557
552
  };
558
553
 
559
- export { type ActiveRound, type AppSettings, DEFAULT_APP_SETTINGS, DEFAULT_OPPONENT, type FeedbackSounds, GUEST_PLAYER_ID, type GameDefinition, type GameGuide, type GameGuideState, type GameIconProps, type GameLoadout, type GamePreviewProps, type GameRulesProps, type GuidelessGameDefinition, type HeroTitleProps, HomeScreen, type LiveplaySliceState, type LoadoutOptionsProps, LoadoutRoute, type OpponentState, PREVIEW_ASPECT, type PackDefinition, type PackGameDefinition, type PackGuide, PackProvider, type PackStatsReset, type PackStatsSectionsProps, type PackStatsTab, type PackStore, type PackStoreConfig, type PackStoreSource, type PickerAlign, PlayRoute, type PlayerControlsState, type PlayerSettingsState, type ProfileSelectionState, ProfilesProvider, ProfilesRoute, type RecordResult, RootLayout, type RoundMode, type Seat, type SeatColorsState, type SeatControlLook, type SeatTwo, SettingsDialog, type SettingsDialogProps, type ShellState, type StackScreenOptions, StatsScreen, appSettingsActions, reducer$1 as appSettingsReducer, createGameGuideSlice, createGameStats, createPackStore, createPlayerSettings, createSeatColorsReducer, createShellReducers, defaultProfileSelectionState, defaultSeatColorsState, forgetProfileAchievements, humanSeatsFor, imageGameIcon, liveplayActions, reducer$3 as liveplayReducer, onProfileRemoved, opponentActions, reducer$2 as opponentReducer, profileSelectionActions, reducer as profileSelectionReducer, roundModeFor, seatColorsActions, seatPlayerKey, seatTwoFor, useActiveRound, useAppSettings, useGameGuide, useOpponent, usePack, usePackGame, useProfiles, useSeatColors };
554
+ export { DEFAULT_APP_SETTINGS, DEFAULT_OPPONENT, GUEST_PLAYER_ID, HomeScreen, LoadoutRoute, PREVIEW_ASPECT, PackProvider, PlayRoute, ProfilesProvider, ProfilesRoute, RootLayout, SettingsDialog, StatsScreen, appSettingsActions, reducer$1 as appSettingsReducer, createGameGuideSlice, createGameStats, createPackStore, createPlayerSettings, createSeatColorsReducer, createShellReducers, defaultProfileSelectionState, defaultSeatColorsState, forgetProfileAchievements, humanSeatsFor, imageGameIcon, liveplayActions, reducer$3 as liveplayReducer, onProfileRemoved, opponentActions, reducer$2 as opponentReducer, profileSelectionActions, reducer as profileSelectionReducer, roundModeFor, seatColorsActions, seatPlayerKey, seatTwoFor, useActiveRound, useAppSettings, useGameGuide, useOpponent, usePack, usePackGame, useProfiles, useSeatColors };
555
+ export type { ActiveRound, AppSettings, FeedbackSounds, GameDefinition, GameGuide, GameGuideState, GameIconProps, GameLoadout, GamePreviewProps, GameRulesProps, GuidelessGameDefinition, HeroTitleProps, HomeTab, LiveplaySliceState, LoadoutOptionsProps, OpponentState, PackDefinition, PackGameDefinition, PackGuide, PackStatsReset, PackStatsSectionsProps, PackStatsTab, PackStore, PackStoreConfig, PackStoreSource, PickerAlign, PlayerControlsState, PlayerSettingsState, ProfileSelectionState, RecordResult, RoundMode, Seat, SeatColorsState, SeatControlLook, SeatTwo, SettingsDialogProps, ShellState, StackScreenOptions };