@pieai/swimmer-ui-kit 2.10.0 → 2.12.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/CHANGELOG.md CHANGED
@@ -3,6 +3,51 @@
3
3
  All notable changes to `@pieai/swimmer-ui-kit`.
4
4
  Format: [Keep a Changelog](https://keepachangelog.com); versioning: semver.
5
5
 
6
+ ## Unreleased
7
+
8
+ ## 2.12.0 — 2026-09-29
9
+
10
+ - Add optional `useGameCardOrientation` and the bounded `GameCardTilt` input
11
+ on `GameCollectibleCard`. One explicitly enabled hook serves the active card
12
+ in an album. Mounting does not request permission or subscribe to a sensor.
13
+ Secure context, denial, late permission, page visibility and reduced motion
14
+ have explicit state and cleanup; no sensor samples or consent are stored.
15
+ - Preserve pointer/keyboard flipping and all omitted-prop behavior. A pointer
16
+ on the card wins over device tilt; reduced motion zeros both immediately.
17
+ Drag classification still applies under reduced motion, and a keyboard or
18
+ assistive click is not suppressed by a stale pointer gesture.
19
+ - Add an opt-in Storybook example and isolated browser sensor-contract tests.
20
+ Synthetic sensor/permission cases are not physical-device permission evidence.
21
+
22
+ ## 2.11.0 — 2026-09-28
23
+
24
+ Minor: University's V7 opening screen and card album, and the liquid fix
25
+ NerveKit 0.6 pairs with.
26
+
27
+ - Add `GameSplash`, the opening and scene-change screen: rotating selling
28
+ lines with a highlighted phrase, a progress bar that tracks real readiness,
29
+ and an enter button offered only once ready (the tap that also lets a web
30
+ page start sound). `mode="transition"` shows one line and the bar with no
31
+ button; `useGameSplashDelay` shows it only after a wait outlasts its delay.
32
+ All text comes from the product. First consumer: University's V7 opening.
33
+ - Add `GameCollectibleCard` and `GameCollectibleCardSlot`: a printed card that
34
+ tilts toward the pointer with a glare that follows it and flips on a tap
35
+ (a drag that tilted it is not a tap). Framed by rarity: `common` silver,
36
+ `rare` violet with a gem, `legendary` gold with a crown, a foil kept off the
37
+ words, and an optional `spotlight` light turning behind it for the reveal.
38
+ The slot shows an uncollected card and what unlocks it. Card inks are theme
39
+ tokens (`--game-ui-collect-card-*`) that stay the same on every theme; band
40
+ inks meet 4.5:1. Reduced motion drops tilt, shine and the turning light.
41
+ - Add `playGameCardRevealSound`: a synthesized flip, with bell notes for the
42
+ rarer cards. First consumer: University's V7 card album.
43
+ - Fix the optional liquid styles yielding to the host: `liquid-presence.css`
44
+ now sits in `@layer swimmer-ui` like the main styles, so a product's
45
+ unlayered rules win without special selectors. `LiquidAnchor` reports the
46
+ area it occupies to the family's destination labels, which step around open
47
+ panels instead of needing a host z-index workaround. A `GameButton` with
48
+ `data-game-ui-control="liquid-presence"` lets its liquid body paint the
49
+ button and keeps native interaction. Paired with NerveKit 0.6.
50
+
6
51
  ## 2.10.0 — 2026-09-24
7
52
 
8
53
  Minor: publish the reviewed optional liquid interaction surface required by
package/dist/index.d.ts CHANGED
@@ -1431,6 +1431,14 @@ export declare interface GameCardFanProps {
1431
1431
  label: string;
1432
1432
  }
1433
1433
 
1434
+ export declare type GameCardOrientationStatus = 'unavailable' | 'off' | 'requesting' | 'enabled' | 'denied';
1435
+
1436
+ /** Normalized card tilt; zero is level, -1 and 1 are the bounded extremes. */
1437
+ export declare interface GameCardTilt {
1438
+ readonly x: number;
1439
+ readonly y: number;
1440
+ }
1441
+
1434
1442
  export declare function GameCheckbox({ className, label, ...props }: GameCheckboxProps): ReactNode;
1435
1443
 
1436
1444
  export declare interface GameCheckboxProps extends Pick<InputHTMLAttributes<HTMLInputElement>, 'checked' | 'defaultChecked' | 'disabled' | 'name' | 'onChange' | 'required' | 'value'> {
@@ -1460,6 +1468,70 @@ export declare interface GameCollapsiblePanelProps extends Omit<HTMLAttributes<H
1460
1468
  tone?: 'default' | 'strong';
1461
1469
  }
1462
1470
 
1471
+ /**
1472
+ * A collectible card: tilts toward the pointer with a glare that follows it,
1473
+ * flips on a tap, and is framed by rarity. Built for a card album where
1474
+ * collecting and reviewing are the same act, but it holds nothing about
1475
+ * learning: every word and picture comes from the product.
1476
+ *
1477
+ * Under reduced motion the card does not tilt, shine or spin its light, and a
1478
+ * flip is instant.
1479
+ */
1480
+ export declare function GameCollectibleCard({ rarity, title, caption, setLabel, rarityLabel, art, pips, sticker, back, label, faceDown, defaultFaceDown, onFlip, spotlight, sound, tilt: externalTilt, className, }: GameCollectibleCardProps): ReactNode;
1481
+
1482
+ export declare interface GameCollectibleCardProps {
1483
+ readonly rarity: GameCollectibleCardRarity;
1484
+ /** The card's name, large on the face. */
1485
+ readonly title: string;
1486
+ /** One line under the name. */
1487
+ readonly caption?: string;
1488
+ /** The set it belongs to, on the band at the top. */
1489
+ readonly setLabel?: string;
1490
+ /** The rarity's short word, in the band's chip. */
1491
+ readonly rarityLabel?: string;
1492
+ /** The illustration; the product supplies it. */
1493
+ readonly art?: ReactNode;
1494
+ /** A row of pips under the caption, such as progress toward the next rarity. */
1495
+ readonly pips?: {
1496
+ readonly filled: number;
1497
+ readonly total: number;
1498
+ };
1499
+ /** A sticker on the corner, such as "NEW!". */
1500
+ readonly sticker?: string;
1501
+ /** The back of the card; the kit draws a plain emblem when omitted. */
1502
+ readonly back?: ReactNode;
1503
+ /** The full accessible name, including what a tap does. */
1504
+ readonly label: string;
1505
+ /** Controlled: whether the back is showing. */
1506
+ readonly faceDown?: boolean;
1507
+ /** Uncontrolled start. */
1508
+ readonly defaultFaceDown?: boolean;
1509
+ readonly onFlip?: (faceDown: boolean) => void;
1510
+ /** A soft light turns behind the card: the moment the rarest card is revealed. */
1511
+ readonly spotlight?: boolean;
1512
+ /** Play a synthesized flip sound; browsers allow it only after the page has been tapped. */
1513
+ readonly sound?: boolean;
1514
+ /** Optional normalized tilt from one explicitly enabled sensor owner. A
1515
+ * pointer on this card takes precedence; reduced motion always wins. */
1516
+ readonly tilt?: GameCardTilt | null;
1517
+ readonly className?: string;
1518
+ }
1519
+
1520
+ /**
1521
+ * How rare the card is, which is how it is framed: `common` a plain silver
1522
+ * frame, `rare` a violet frame with a gem set in the top, `legendary` a gold
1523
+ * frame with a crown, a foil that shifts as the card tilts and a soft light
1524
+ * behind it. The product decides what earns each; the kit only draws them.
1525
+ */
1526
+ export declare type GameCollectibleCardRarity = 'common' | 'rare' | 'legendary';
1527
+
1528
+ /** A card not collected yet: its place in the set, and what unlocks it. Not interactive. */
1529
+ export declare function GameCollectibleCardSlot({ label, className, }: {
1530
+ /** What unlocks it, shown on the slot and read as its name. */
1531
+ readonly label: string;
1532
+ readonly className?: string;
1533
+ }): ReactNode;
1534
+
1463
1535
  export declare function GameCompactGameDrawer({ children, className, closeIcon, closeLabel, disabled, label, onOpenChange, open, panelId: providedPanelId, title, triggerIcon, triggerLabel, variant, 'data-testid': testId, }: GameCompactGameDrawerProps): ReactNode;
1464
1536
 
1465
1537
  export declare interface GameCompactGameDrawerProps {
@@ -2067,6 +2139,53 @@ export declare interface GameSliderProps extends Pick<InputHTMLAttributes<HTMLIn
2067
2139
  onChange?: (value: number) => void;
2068
2140
  }
2069
2141
 
2142
+ /**
2143
+ * The opening screen and the scene-change screen, one look for both.
2144
+ *
2145
+ * Its whole job is to make the wait worth watching and honest: the lines say
2146
+ * what the product is for, the bar tracks what is really loading, and entering
2147
+ * is offered only when the thing behind it is complete — nobody is held back
2148
+ * for effect, and nobody walks into a half-drawn scene.
2149
+ */
2150
+ export declare function GameSplash({ title, lines, progress, progressLabel, ready, mode, startLabel, onStart, autoStart, lineSeconds, className, }: GameSplashProps): ReactNode;
2151
+
2152
+ /**
2153
+ * One selling line on the splash. `highlight` is a word or phrase inside
2154
+ * `text` that lights up as the line appears; the product supplies both in the
2155
+ * learner's language, the kit supplies none.
2156
+ */
2157
+ export declare interface GameSplashLine {
2158
+ readonly text: string;
2159
+ readonly highlight?: string;
2160
+ }
2161
+
2162
+ export declare interface GameSplashProps {
2163
+ /** The product's name, shown large. */
2164
+ readonly title: string;
2165
+ /** Two or three lines a visit; they take turns while the product loads. */
2166
+ readonly lines: readonly GameSplashLine[];
2167
+ /** Real readiness, 0 to 1. Never a timer: a bar stuck at 99% is worse than none. */
2168
+ readonly progress: number;
2169
+ /** What the bar says, including the number if the product wants it shown. */
2170
+ readonly progressLabel: string;
2171
+ /** Everything the first screen needs has arrived and drawn once. */
2172
+ readonly ready: boolean;
2173
+ /**
2174
+ * `opening`: the first screen, with a tap to enter once ready (the tap is
2175
+ * also what lets a web page start sound). `transition`: the same look over a
2176
+ * scene change, one line and the bar, no button.
2177
+ */
2178
+ readonly mode?: 'opening' | 'transition';
2179
+ /** The enter button's text, opening mode only. */
2180
+ readonly startLabel?: string;
2181
+ readonly onStart?: () => void;
2182
+ /** Enter by itself when ready, for app shells that need no gesture for sound. */
2183
+ readonly autoStart?: boolean;
2184
+ /** Seconds each line stays before the next. */
2185
+ readonly lineSeconds?: number;
2186
+ readonly className?: string;
2187
+ }
2188
+
2070
2189
  export declare function GameStageTile({ badge, className, icon, kicker, selected, summary, title, tone, type, ...props }: GameStageTileProps): ReactNode;
2071
2190
 
2072
2191
  export declare interface GameStageTileProps extends ButtonHTMLAttributes<HTMLButtonElement> {
@@ -2710,6 +2829,15 @@ export declare interface MorphTuning {
2710
2829
  advanced?: Partial<EvolveOptions>;
2711
2830
  }
2712
2831
 
2832
+ export declare function playGameCardRevealSound(rarity: 'common' | 'rare' | 'legendary', options?: GameInteractionSoundOptions): boolean;
2833
+
2834
+ /**
2835
+ * A card turning over: a short falling sweep, and for a rarer card one or two
2836
+ * bell notes after it. Synthesized, so nothing is downloaded; like every kit
2837
+ * sound, the browser lets it play only once the page has been interacted with.
2838
+ */
2839
+ export declare function playGameCardRevealSoundForContext(audioContext: GameInteractionAudioContext, rarity: 'common' | 'rare' | 'legendary', options?: GameInteractionSoundOptions): boolean;
2840
+
2713
2841
  export declare function playGameInteractionSound(options?: GameInteractionSoundOptions): boolean;
2714
2842
 
2715
2843
  export declare function playGameInteractionSoundForContext(audioContext: GameInteractionAudioContext, options?: GameInteractionSoundOptions): boolean;
@@ -2776,4 +2904,24 @@ declare type Transition = TransitionPreset | SpringConfig | {
2776
2904
 
2777
2905
  declare type TransitionPreset = 'snappy' | 'smooth' | 'bouncy' | 'wobbly';
2778
2906
 
2907
+ /** One optional sensor owner for an album or preview, NOT one per card.
2908
+ * Call enable from a real user action, then pass tilt only to the active card.
2909
+ * No permission, storage, microphone, motion sensor or network request occurs
2910
+ * on mount. Reduced motion cancels consent in flight and requires a new action;
2911
+ * hiding the page pauses samples and recalibrates on return. */
2912
+ export declare function useGameCardOrientation(): {
2913
+ status: GameCardOrientationStatus;
2914
+ tilt: GameCardTilt | null;
2915
+ enable: () => Promise<boolean>;
2916
+ disable: () => void;
2917
+ reducedMotion: boolean;
2918
+ };
2919
+
2920
+ /**
2921
+ * Whether a waiting screen should appear yet: only once `waiting` has stayed
2922
+ * true for `delayMs` without a break. A scene change that finishes inside the
2923
+ * delay never shows the screen at all.
2924
+ */
2925
+ export declare function useGameSplashDelay(waiting: boolean, delayMs?: number): boolean;
2926
+
2779
2927
  export { }