@tastic/shell 0.4.0 → 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.
@@ -34,7 +34,7 @@ const ALL_GAMES = '__all__'
34
34
  const PLAYER_PICKER_ID = 'stats-player'
35
35
  const GAME_PICKER_ID = 'stats-game'
36
36
 
37
- // Widest the column gets in the wide layout (a phone held sideways, a desktop window): a list of stat
37
+ // Widest the column gets in the wide layout (a landscape phone, a desktop window): a list of stat
38
38
  // rows stretched across an 874pt-wide screen reads badly. Upright it's never capped.
39
39
  const STATS_MAX_WIDTH = 640
40
40
 
@@ -45,9 +45,8 @@ const STATS_MAX_WIDTH = 640
45
45
  // can't be told apart. A pack for one player at a time (PackDefinition.guestStats) keeps a guest's
46
46
  // stats under GUEST_PLAYER_ID, offers Guest in the picker and opens on whoever is in seat 1.
47
47
  //
48
- // Turned with the phone in hud's RotatedFrame: its insets remapped onto the frame's edges, the reset
49
- // confirm portaled into a host inside the frame (so it's turned with it, at rotation 0), and the column
50
- // capped in the wide layout.
48
+ // In hud's RotatedFrame, which nothing turns since @tastic/core 0.15: it hands the screen the safe-area
49
+ // insets, hosts the reset confirm's portal inside the frame, and caps the column in the wide layout.
51
50
  export function StatsScreen() {
52
51
  const pickerHost = usePopoverHost()
53
52
  return (
@@ -81,7 +80,7 @@ const noPickerAlign = () => undefined
81
80
  function StatsContent({ pickerHost }: { pickerHost: PopoverHost }) {
82
81
  const pack = usePack()
83
82
  const { dark, colors } = useAutoPaperTheme()
84
- // Already remapped onto the turned frame's edges by RotatedFrame's rotatedSafeArea.
83
+ // Handed over by RotatedFrame's rotatedSafeArea.
85
84
  const insets = useSafeAreaInsets()
86
85
  const { profiles, lastSelected } = useProfiles()
87
86
  const dispatch = useDispatch()
@@ -1,20 +1,19 @@
1
- import { clamp, rotateInsets, useRotatedWindowDimensions, useRotation } from '@tastic/core'
1
+ import { clamp } from '@tastic/core'
2
+ import { useWindowDimensions } from 'react-native'
2
3
  import { type EdgeInsets, useSafeAreaInsets } from 'react-native-safe-area-context'
3
4
 
4
5
  // Home's geometry for a pack whose games have previews (GameDefinition.Preview), ported from
5
6
  // Solitaire's components/homeLayout.ts. Upright, Home is the one scrolling column every pack has: the
6
- // hero, seat 1's button, then a row per game, each row's preview at its start. Held sideways a phone
7
+ // hero, seat 1's button, then a row per game, each row's preview at its start. A landscape phone
7
8
  // is only ~400pt tall, and that column would spend the whole height on the hero before showing a
8
- // single game, so a "wide" layout (any window whose ROTATED footprint is landscape: a phone held
9
- // sideways, an iPad, a desktop browser) splits it into two panes: the hero and seat 1's button on the
9
+ // single game, so a "wide" layout (any window wider than tall: a landscape phone, a landscape iPad, a
10
+ // desktop browser) splits it into two panes: the hero and seat 1's button on the
10
11
  // left, and a scrolling grid of game tiles on the right. The trophy (top-left) and cog (top-right)
11
12
  // corner buttons stay where they are; the right pane stops short of the cog so tiles never scroll
12
13
  // underneath it. A pack without previews keeps the column at every size.
13
14
  //
14
- // Everything here works in the ROTATED frame's own coordinates (Home's FakeLandscapeView): `width`/
15
- // `height` are the rotated footprint and `insets` are the safe-area insets already remapped onto the
16
- // frame's edges (rotateInsets). The rotated top/bottom insets are ~0 under a portrait-locked OS (a
17
- // phone held sideways only has left/right insets), so nothing here leans on them for breathing room.
15
+ // A landscape phone's top and bottom insets are ~0 (only the sides have them), so nothing here leans
16
+ // on them for breathing room.
18
17
 
19
18
  // Every preview's width / height: Solitaire's preview canvas (360 x 200), so its deals fit as drawn.
20
19
  export const PREVIEW_ASPECT = 360 / 200
@@ -52,15 +51,15 @@ const HOME_LEFT_PANE_BOTTOM_PADDING = 16
52
51
  const HOME_HERO_SIDE_ROOM = 16
53
52
 
54
53
  export interface HomeLayout {
55
- // The rotated footprint is landscape: the two-pane layout is in effect (for a pack with previews).
54
+ // The window is landscape: the two-pane layout is in effect (for a pack with previews).
56
55
  isWide: boolean
57
- // The window's footprint AFTER rotation.
56
+ // The window's size.
58
57
  windowWidth: number
59
58
  windowHeight: number
60
- // Safe-area insets remapped onto the rotated frame's own edges (see @tastic/core's rotateInsets).
59
+ // The safe-area insets.
61
60
  insets: EdgeInsets
62
- // Wide layout: padding on the two panes' row. Each side hugs ITS OWN inset (a phone held sideways
63
- // has a large inset only on the island side), the trailing one also reserves the cog's gutter, and
61
+ // Wide layout: padding on the two panes' row. Each side hugs ITS OWN inset (a landscape phone has a
62
+ // large inset only on the island side), the trailing one also reserves the cog's gutter, and
64
63
  // both carry the equal margin left over once the content hits its cap. 0 upright.
65
64
  paddingLeft: number
66
65
  paddingRight: number
@@ -118,12 +117,9 @@ export function computeHomeLayout(windowWidth: number, windowHeight: number, ins
118
117
  }
119
118
  }
120
119
 
121
- // The live layout for the current window and rotation. Reads useRotatedWindowDimensions()/
122
- // rotateInsets() rather than raw useWindowDimensions()/useSafeAreaInsets(), so it describes the
123
- // footprint a rotated Home actually renders into (both are exact identities at 0deg).
120
+ // The live layout for the current window.
124
121
  export function useHomeLayout(): HomeLayout {
125
- const { width, height } = useRotatedWindowDimensions()
126
- const rotation = useRotation()
127
- const insets = rotateInsets(useSafeAreaInsets(), rotation)
122
+ const { width, height } = useWindowDimensions()
123
+ const insets = useSafeAreaInsets()
128
124
  return computeHomeLayout(width, height, insets)
129
125
  }
package/src/types.ts CHANGED
@@ -1,5 +1,4 @@
1
1
  import type { ThemeAppearance, ThemeSettings } from '@rific/auto-paper'
2
- import type { ViewRotation } from '@tastic/core'
3
2
  import type { AlignResult, PopoverHost } from '@tastic/hud/chrome'
4
3
  import type { GuideStep } from '@tastic/hud/guide'
5
4
  import type { MenuOption } from '@tastic/hud/lobby'
@@ -39,10 +38,9 @@ export function humanSeatsFor(mode: RoundMode): Seat[] {
39
38
  }
40
39
 
41
40
  // What the loadout's match-options row is handed (see GameLoadout.options): the popover host it
42
- // shares with seat 1's panel, the screen's rotation, and the colors the row draws with.
41
+ // shares with seat 1's panel, and the colors the row draws with.
43
42
  export interface LoadoutOptionsProps {
44
43
  host: PopoverHost
45
- rotation: ViewRotation
46
44
  accentColor: string
47
45
  mutedColor: string
48
46
  onAccentColor: string
@@ -58,7 +56,6 @@ export interface SeatControlLook {
58
56
  seatColor: string
59
57
  mutedColor: string
60
58
  dark: boolean
61
- rotation: ViewRotation
62
59
  }
63
60
 
64
61
  // One game's part of the shared loadout (shell/screens/LoadoutScreen.tsx), built by the game's
@@ -131,7 +128,7 @@ export interface PackGuide {
131
128
  }
132
129
 
133
130
  // A game's rules sheet (GameDefinition.Rules), opened from its tile's rules button on Home. It renders
134
- // through a Paper Portal into a host Home mounts inside its turned frame, so it's already turned with it.
131
+ // through a Paper Portal into a host Home mounts inside its own frame.
135
132
  export interface GameRulesProps {
136
133
  visible: boolean
137
134
  onDismiss: () => void
@@ -152,11 +149,10 @@ export interface GameDefinition {
152
149
  // Seat 2's choices in this game, in menu order. 'nobody' only where the game has a solo mode.
153
150
  // Left out by a game for one player only: its loadout has no seat 2 button and every round is solo.
154
151
  seatTwo?: readonly SeatTwo[]
155
- // How the 2 Player loadout seats its players, to match where the game puts them: always face
156
- // to face (or only off the web, where a desktop window seats them side by side), and whether an
157
- // upside-down hold swaps who is at the bottom. Only read in 2 Player, so a game without 'person'
158
- // among its seatTwo choices can leave it out.
159
- twoPlayerSeats?: { faceToFaceOnWeb: boolean; followUpsideDown: boolean }
152
+ // The 2 Player loadout seats its players side by side (P1 on the left) in a window wider than tall,
153
+ // to match a game whose board does the same there. Unset, they sit face to face in any window (P1 at
154
+ // the bottom). Only read in 2 Player, so a game without 'person' among its seatTwo choices leaves it out.
155
+ sideBySideWhenWide?: boolean
160
156
  // The store keys this game mounts (settings, achievements, guide), merged into the pack's store.
161
157
  reducers: Record<string, Reducer>
162
158
  // Mounted at the app root for the game's lifetime (its stats and achievements context). Left out by
@@ -172,9 +168,8 @@ export interface GameDefinition {
172
168
  // board: the shell only remembers which game it was (redux/lastActiveGameSlice.ts). A match that
173
169
  // isn't saved (liveplay) shouldn't opt in, or a relaunch would open a fresh one.
174
170
  resumable?: boolean
175
- // The play screen keeps the status bar while the phone is held upright. Unset, the bar is hidden on
176
- // every play screen for the whole round, whatever the angle; set, it's hidden only while the
177
- // content is turned, as on every other screen.
171
+ // The play screen keeps the status bar. Unset, the bar is hidden on every play screen for the whole
172
+ // round; set, it shows as on every other screen.
178
173
  keepStatusBar?: boolean
179
174
  // The game's stats sections and its achievement list for the stats screen, for one profile
180
175
  // (null is Everyone).
@@ -313,13 +308,10 @@ export interface PackDefinition {
313
308
  useScreenOptions?: () => StackScreenOptions
314
309
  // The two sounds every button plays, in place of the shell's own.
315
310
  useFeedbackSounds?: () => FeedbackSounds
316
- // The pack's own toaster, drawn in a frame turned with the phone (with the safe-area insets turned
317
- // onto the frame's edges) in place of the shell's. It renders inline: the toast provider is given no
311
+ // The pack's own toaster, drawn in a frame over the whole app (inside the safe area) in place of the
312
+ // shell's. It renders inline: the toast provider is given no
318
313
  // Paper, so nothing portals it out of the frame.
319
314
  Toaster?: ComponentType
320
- // Every screen reads upright while the software keyboard is up (@tastic/core's OrientationProvider),
321
- // for typing a profile's name with the phone sideways.
322
- portraitWhileKeyboard?: boolean
323
315
  // false leaves Edge Guard out of Settings (a pack with no edge controls and no Edge Guard plugin).
324
316
  edgeGuard?: boolean
325
317
  // The theme seat 1's color makes (a muted seed with a harmony), applied whenever the seats' colors or
@@ -352,9 +344,9 @@ export interface PackDefinition {
352
344
  newProfileColor?: string
353
345
  // Where a picker's menu opens (its alignOverride) on Home (seat 1's button), a loadout's one-human row
354
346
  // (both seat buttons; 2 Player keeps each menu in its own player's half), the stats screen (its two
355
- // pickers) and Profiles (a profile's color swatch). hud's own placement measures a turned button
356
- // against the upright window, so with the phone held sideways it can pick the side with no room and
357
- // run the menu off the screen (Solitaire's useFrameAutoAlign places it in the turned frame instead).
347
+ // pickers) and Profiles (a profile's color swatch). It was added because hud's own placement measured
348
+ // a button in a frame turned by @tastic/core's drawn rotation against the upright window; nothing turns
349
+ // since core 0.15, so a pack may no longer need one.
358
350
  // `open` is whether this picker's menu is open, the size is its content's, and `maxContentWidth` is a
359
351
  // capped column's width the menu stays inside (Profiles' roster). Unset is hud's own placement.
360
352
  usePickerAlign?: PickerAlign