@pieai/swimmer-ui-kit 2.11.0 → 2.13.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
@@ -5,6 +5,38 @@ Format: [Keep a Changelog](https://keepachangelog.com); versioning: semver.
5
5
 
6
6
  ## Unreleased
7
7
 
8
+ ### 2.13.0 candidate — WO-UI-1
9
+
10
+ - Add opt-in `surface="plaque"` to `GameButton`, `GameIconButton` and
11
+ `GameAvatar`, with opaque light/night copper token pairs derived from
12
+ Directing's reviewed D1-03 cabinet material. Default controls stay unchanged.
13
+ - Add controlled `GameOtpInput`: numeric slots, paste/autofill, keyboard and
14
+ backspace, localized descriptions and input-method composition handling.
15
+ Only changed user input completes a code; verification stays in the host.
16
+ - Add vertical `GameTabs` with Up/Down navigation and an accessible name.
17
+ - Add `GameListRow` with thumbnail, text, current indicator and independent
18
+ selection/actions; no nested buttons.
19
+ - Add browser regressions, six stories and contrast guards. Redirect fresh
20
+ modal-test screenshots to `.devspace-visual/`, preserving retained scratch
21
+ evidence and all existing assertions.
22
+ - Compatibility: additive only; no new dependency or React peer change.
23
+ This candidate is not published: Owner's private-publication instruction
24
+ needs clarification before using this repository's public npm workflow.
25
+
26
+ ## 2.12.0 — 2026-09-29
27
+
28
+ - Add optional `useGameCardOrientation` and the bounded `GameCardTilt` input
29
+ on `GameCollectibleCard`. One explicitly enabled hook serves the active card
30
+ in an album. Mounting does not request permission or subscribe to a sensor.
31
+ Secure context, denial, late permission, page visibility and reduced motion
32
+ have explicit state and cleanup; no sensor samples or consent are stored.
33
+ - Preserve pointer/keyboard flipping and all omitted-prop behavior. A pointer
34
+ on the card wins over device tilt; reduced motion zeros both immediately.
35
+ Drag classification still applies under reduced motion, and a keyboard or
36
+ assistive click is not suppressed by a stale pointer gesture.
37
+ - Add an opt-in Storybook example and isolated browser sensor-contract tests.
38
+ Synthetic sensor/permission cases are not physical-device permission evidence.
39
+
8
40
  ## 2.11.0 — 2026-09-28
9
41
 
10
42
  Minor: University's V7 opening screen and card album, and the liquid fix
package/README.md CHANGED
@@ -2,8 +2,9 @@
2
2
 
3
3
  Self-contained clay game UI kit for PieAI web, game, and wrapped
4
4
  (mobile/desktop WebView) surfaces. React 19 + TypeScript strict.
5
- **Zero runtime dependencies, 100% standard CSS** — consumers need no
6
- Tailwind, no PostCSS, no CSS processor of any kind.
5
+ **100% standard CSS** — consumers need no Tailwind, no PostCSS, no CSS
6
+ processor of any kind. The optional `GameHelpTip` uses the existing Floating UI
7
+ dependency; ordinary controls remain native.
7
8
 
8
9
  Source is publicly readable. Use is governed by the
9
10
  [PieAI Limited Use License](./LICENSE), not an open-source license. The visual
@@ -56,6 +57,13 @@ import '@pieai/swimmer-ui-kit/tailwind.css';
56
57
 
57
58
  ## What's inside
58
59
 
60
+ - **Account primitives (2.13.0 local candidate, not published)**:
61
+ opt-in copper `surface="plaque"`, `GameOtpInput`, vertical `GameTabs`,
62
+ and `GameListRow` with independent actions. See the
63
+ [account-controls contract](docs/reference/design-system-guide.md#账号界面原件)
64
+ and Storybook `Clay / Account / AccountControls`. Account requests and
65
+ business state stay in the host.
66
+
59
67
  - **Ready-to-use components** across: core controls (`GameButton`,
60
68
  `LiquidMetalButton`, `GameTabs`,
61
69
  `GameSlider`, `GameToggle`, `GameForms` inputs…), panels and windows
package/dist/index.d.ts CHANGED
@@ -1259,9 +1259,11 @@ export declare type GameAssetSource = 'starter' | 'generated' | 'imported';
1259
1259
 
1260
1260
  export declare type GameAssetStatus = 'ready' | 'generating' | 'missing' | 'placed' | 'selected' | 'error';
1261
1261
 
1262
- export declare function GameAvatar({ className, name, size, src, status, }: GameAvatarProps): ReactNode;
1262
+ export declare function GameAvatar({ className, name, size, src, status, surface, }: GameAvatarProps): ReactNode;
1263
1263
 
1264
1264
  export declare interface GameAvatarProps {
1265
+ /** Optional copper frame; omitted keeps the existing avatar surface. */
1266
+ surface?: 'flat' | 'plaque';
1265
1267
  /** Display name — used as image alt text and for the initials fallback. */
1266
1268
  name: string;
1267
1269
  /** Optional image URL; when missing, initials are shown instead. */
@@ -1397,7 +1399,7 @@ export declare interface GameButtonProps extends ButtonHTMLAttributes<HTMLButton
1397
1399
  variant?: GameButtonVariant;
1398
1400
  }
1399
1401
 
1400
- export declare type GameButtonSurface = 'flat' | 'liquid';
1402
+ export declare type GameButtonSurface = 'flat' | 'liquid' | 'plaque';
1401
1403
 
1402
1404
  export declare type GameButtonVariant = 'primary' | 'secondary' | 'ghost' | 'danger' | 'success';
1403
1405
 
@@ -1431,6 +1433,14 @@ export declare interface GameCardFanProps {
1431
1433
  label: string;
1432
1434
  }
1433
1435
 
1436
+ export declare type GameCardOrientationStatus = 'unavailable' | 'off' | 'requesting' | 'enabled' | 'denied';
1437
+
1438
+ /** Normalized card tilt; zero is level, -1 and 1 are the bounded extremes. */
1439
+ export declare interface GameCardTilt {
1440
+ readonly x: number;
1441
+ readonly y: number;
1442
+ }
1443
+
1434
1444
  export declare function GameCheckbox({ className, label, ...props }: GameCheckboxProps): ReactNode;
1435
1445
 
1436
1446
  export declare interface GameCheckboxProps extends Pick<InputHTMLAttributes<HTMLInputElement>, 'checked' | 'defaultChecked' | 'disabled' | 'name' | 'onChange' | 'required' | 'value'> {
@@ -1469,7 +1479,7 @@ export declare interface GameCollapsiblePanelProps extends Omit<HTMLAttributes<H
1469
1479
  * Under reduced motion the card does not tilt, shine or spin its light, and a
1470
1480
  * flip is instant.
1471
1481
  */
1472
- export declare function GameCollectibleCard({ rarity, title, caption, setLabel, rarityLabel, art, pips, sticker, back, label, faceDown, defaultFaceDown, onFlip, spotlight, sound, className, }: GameCollectibleCardProps): ReactNode;
1482
+ export declare function GameCollectibleCard({ rarity, title, caption, setLabel, rarityLabel, art, pips, sticker, back, label, faceDown, defaultFaceDown, onFlip, spotlight, sound, tilt: externalTilt, className, }: GameCollectibleCardProps): ReactNode;
1473
1483
 
1474
1484
  export declare interface GameCollectibleCardProps {
1475
1485
  readonly rarity: GameCollectibleCardRarity;
@@ -1503,6 +1513,9 @@ export declare interface GameCollectibleCardProps {
1503
1513
  readonly spotlight?: boolean;
1504
1514
  /** Play a synthesized flip sound; browsers allow it only after the page has been tapped. */
1505
1515
  readonly sound?: boolean;
1516
+ /** Optional normalized tilt from one explicitly enabled sensor owner. A
1517
+ * pointer on this card takes precedence; reduced motion always wins. */
1518
+ readonly tilt?: GameCardTilt | null;
1506
1519
  readonly className?: string;
1507
1520
  }
1508
1521
 
@@ -1881,6 +1894,22 @@ export declare interface GameLanguageMenuProps {
1881
1894
  onSelect?: (id: string) => void;
1882
1895
  }
1883
1896
 
1897
+ /** A quiet list surface, with sibling controls rather than buttons inside a button. */
1898
+ export declare function GameListRow({ title, description, thumbnail, current, selected, disabled, onSelect, selectLabel, actions, className, ...props }: GameListRowProps): ReactNode;
1899
+
1900
+ export declare interface GameListRowProps extends Omit<HTMLAttributes<HTMLDivElement>, 'title' | 'onSelect' | 'children'> {
1901
+ title: string;
1902
+ description?: ReactNode;
1903
+ thumbnail?: ReactNode;
1904
+ current?: boolean;
1905
+ selected?: boolean;
1906
+ disabled?: boolean;
1907
+ onSelect?: () => void;
1908
+ /** Optional name for the row's selection control, independent of its actions. */
1909
+ selectLabel?: string;
1910
+ actions?: ReactNode;
1911
+ }
1912
+
1884
1913
  export declare function GameLoadingState({ label, tone }: GameLoadingStateProps): ReactNode;
1885
1914
 
1886
1915
  export declare interface GameLoadingStateProps {
@@ -1967,6 +1996,24 @@ export declare interface GameOrientationGateProps {
1967
1996
  title: string;
1968
1997
  }
1969
1998
 
1999
+ /** Numeric entry only. Sending, expiry, validation and retries belong to the host. */
2000
+ export declare function GameOtpInput({ length, value, onChange, onComplete, invalid, disabled, readOnly, getSlotLabel, getSlotDescription, className, 'aria-describedby': describedBy, ...props }: GameOtpInputProps): ReactNode;
2001
+
2002
+ export declare interface GameOtpInputProps extends Omit<HTMLAttributes<HTMLDivElement>, 'onChange' | 'onInput' | 'children'> {
2003
+ /** Number of numeric slots; defaults to six. */
2004
+ length?: number;
2005
+ value: string;
2006
+ onChange: (value: string) => void;
2007
+ /** Only user input completes a code; mounting or changing props never submits. */
2008
+ onComplete?: (value: string) => void;
2009
+ invalid?: boolean;
2010
+ disabled?: boolean;
2011
+ readOnly?: boolean;
2012
+ /** Zero-based slot index, followed by the configured length. */
2013
+ getSlotLabel?: (index: number, length: number) => string;
2014
+ getSlotDescription?: (index: number, length: number) => string;
2015
+ }
2016
+
1970
2017
  export declare function GamePanel({ children, className, title, tone, ...props }: GamePanelProps): ReactNode;
1971
2018
 
1972
2019
  export declare interface GamePanelProps extends HTMLAttributes<HTMLElement> {
@@ -1998,7 +2045,7 @@ export declare function GameProgress({ className, label, max, showValue, tone, v
1998
2045
 
1999
2046
  export declare interface GameProgressProps {
2000
2047
  /** Defaults to the existing liquid leading edge. Flat adds no SVG filter. */
2001
- surface?: GameButtonSurface;
2048
+ surface?: Exclude<GameButtonSurface, 'plaque'>;
2002
2049
  liquidFinish?: LiquidFinish;
2003
2050
  /** Current value, between 0 and `max`. */
2004
2051
  value: number;
@@ -2073,7 +2120,7 @@ export declare interface GameSegmentedControlProps {
2073
2120
  onSelect?: (id: string) => void;
2074
2121
  options: readonly GameSegmentedOption[];
2075
2122
  /** Existing default is liquid. Flat provides a quiet, filter-free option. */
2076
- surface?: GameButtonSurface;
2123
+ surface?: Exclude<GameButtonSurface, 'plaque'>;
2077
2124
  liquidFinish?: LiquidFinish;
2078
2125
  disabled?: boolean;
2079
2126
  }
@@ -2093,7 +2140,7 @@ export declare const GameSelect: ForwardRefExoticComponent<GameSelectProps & Ref
2093
2140
 
2094
2141
  export declare interface GameSelectProps extends SelectHTMLAttributes<HTMLSelectElement> {
2095
2142
  invalid?: boolean;
2096
- surface?: GameButtonSurface;
2143
+ surface?: Exclude<GameButtonSurface, 'plaque'>;
2097
2144
  liquidFinish?: LiquidFinish;
2098
2145
  }
2099
2146
 
@@ -2202,9 +2249,12 @@ export declare interface GameTabItem {
2202
2249
  panelId?: string;
2203
2250
  }
2204
2251
 
2205
- export declare function GameTabs({ activeId, id, onSelect, tabs }: GameTabsProps): ReactNode;
2252
+ export declare function GameTabs({ activeId, id, onSelect, tabs, orientation, 'aria-label': label, 'aria-labelledby': labelledBy, }: GameTabsProps): ReactNode;
2206
2253
 
2207
2254
  export declare interface GameTabsProps {
2255
+ orientation?: 'horizontal' | 'vertical';
2256
+ 'aria-label'?: string;
2257
+ 'aria-labelledby'?: string;
2208
2258
  activeId: string;
2209
2259
  /**
2210
2260
  * Base id for this tabs instance (defaults to a generated one). Each tab
@@ -2355,7 +2405,7 @@ export declare function GameToggle({ checked, disabled, label, onClick, surface,
2355
2405
  export declare interface GameToggleProps extends Pick<ButtonHTMLAttributes<HTMLButtonElement>, 'disabled' | 'onClick'> {
2356
2406
  checked: boolean;
2357
2407
  label: string;
2358
- surface?: GameButtonSurface;
2408
+ surface?: Exclude<GameButtonSurface, 'plaque'>;
2359
2409
  liquidFinish?: LiquidFinish;
2360
2410
  }
2361
2411
 
@@ -2893,6 +2943,19 @@ declare type Transition = TransitionPreset | SpringConfig | {
2893
2943
 
2894
2944
  declare type TransitionPreset = 'snappy' | 'smooth' | 'bouncy' | 'wobbly';
2895
2945
 
2946
+ /** One optional sensor owner for an album or preview, NOT one per card.
2947
+ * Call enable from a real user action, then pass tilt only to the active card.
2948
+ * No permission, storage, microphone, motion sensor or network request occurs
2949
+ * on mount. Reduced motion cancels consent in flight and requires a new action;
2950
+ * hiding the page pauses samples and recalibrates on return. */
2951
+ export declare function useGameCardOrientation(): {
2952
+ status: GameCardOrientationStatus;
2953
+ tilt: GameCardTilt | null;
2954
+ enable: () => Promise<boolean>;
2955
+ disable: () => void;
2956
+ reducedMotion: boolean;
2957
+ };
2958
+
2896
2959
  /**
2897
2960
  * Whether a waiting screen should appear yet: only once `waiting` has stayed
2898
2961
  * true for `delayMs` without a break. A scene change that finishes inside the