@pieai/swimmer-ui-kit 2.5.0 → 2.6.1

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,84 @@
3
3
  All notable changes to `@pieai/swimmer-ui-kit`.
4
4
  Format: [Keep a Changelog](https://keepachangelog.com); versioning: semver.
5
5
 
6
+ ## 2.6.1 — 2026-09-12
7
+
8
+ Patch: production CSS behavior, not a new material or API.
9
+
10
+ - Preserve the liquid button/icon's independent `scale` and `translate` resets
11
+ through CSS minification. The compiler folded literal identity values into
12
+ `transform: none`, but transform does not reset the independent properties:
13
+ development looked correct while the published native hit target shrank on
14
+ press. Explicit CSS `initial` resets survive the build and a consumer rebuild.
15
+ - Fix static-button press specificity so the normal 3px lip travel does not win
16
+ over the static opt-out. Ordinary buttons keep their intentional press motion.
17
+ - Add real-browser tests against actually minified CSS to `pnpm verify`, with
18
+ an ordinary-button positive control. Source-only and screenshot-at-rest checks
19
+ did not establish this built interaction contract.
20
+
21
+ Consumers should use **2.6.1** rather than 2.6.0. No import/prop migration is
22
+ needed from 2.6.0; existing release versions are not overwritten. The two finishes,
23
+ six liquid control categories and native-select state preservation remain unchanged.
24
+
25
+ ## 2.6.0 — 2026-09-12
26
+
27
+ Minor: new optional material selection and native controls. Existing root
28
+ exports and export-map paths remain; omitted options retain prior defaults.
29
+
30
+ ### Added
31
+
32
+ - `LiquidFinish` and optional `liquidFinish="matte" | "glossy"` across
33
+ LiquidGroup/LiquidSurface, GameButton, GameIconButton, GameToggle,
34
+ GameSegmentedControl, GameProgress and GameSelect. Both finishes reuse the
35
+ existing renderer; matte removes the specular pass, not motion or shadows.
36
+ Explicit LiquidGroup `gloss` remains the advanced override.
37
+ - Liquid icon buttons and switch thumbs; GameSelect uses a real native select
38
+ with optional liquid closed-field decoration, form/reset/ref/optgroup support,
39
+ invalid semantics and ordinary disabled/multiple/list modes. The popup remains
40
+ platform-native; this is not a searchable combobox or custom liquid listbox.
41
+ - Optional flat, filter-free progress and segmented surfaces. Slider forwards
42
+ native step, disabled, name and id.
43
+ - A beginner catalog at the site root: 12 shared recipe groups, 6 liquid control
44
+ categories, matte/glossy comparison, theme/state selection, actual interaction,
45
+ complete copyable/typechecked React examples and shareable configuration URLs.
46
+ Storybook uses the same recipes. The old reference remains at `/?view=reference`
47
+ and old `#game-ui-preview-*` links still open it.
48
+
49
+ ### Fixed and intentionally changed
50
+
51
+ - Press decoration ignores secondary pointer buttons and key repeat, clears on
52
+ lost capture/cancellation/blur, resets through disabled, and honors `static`.
53
+ Native content and hit targets never inherit the squash transform.
54
+ - The liquid button's native element no longer picks up the ordinary button's
55
+ independent CSS `scale` on press or hover lift; only the silhouette moves.
56
+ - Pointer feedback survives macOS WebKit's native pointerdown-then-blur ordering;
57
+ a true window deactivation still cancels the gesture. No focus is forced onto
58
+ the native control to hide this platform difference.
59
+ - Progress ARIA values now agree with the clamped visible value, including invalid
60
+ maxima and non-finite input. Forced-colors decoration falls back to system UI.
61
+ - `GameInput` and `GameTextArea` now expose `invalid` through `aria-invalid`,
62
+ like the new select; an explicit ARIA value still wins.
63
+ - Select decoration is a sibling of the persistent native field. Disabling,
64
+ changing material or switching single/list presentation must not remount the
65
+ select and lose an uncontrolled choice or replace its forwarded DOM ref.
66
+ Catalog material/state adjustments likewise preserve the current example's
67
+ entered values instead of silently resetting the recipe.
68
+ - Disabled icon buttons, switches and segmented options now have a quiet,
69
+ non-hovering treatment. Disabled segmented controls retain the selected option
70
+ on a flat surface instead of reserving animated liquid groups.
71
+ Inherited native fieldset disabling also hides button/icon/switch/select decoration.
72
+ - The liquid form page selects experiments instead of mounting every form, size,
73
+ tone and state simultaneously. At most two liquid groups are mounted; the shared
74
+ budget was not increased and the twelve forms were not removed or retuned.
75
+
76
+ ### Consumer action
77
+
78
+ Pin the new version and run your own product gates. New materials/controls are
79
+ opt-in; University was not modified. Do not remove its destination/route transition
80
+ when adopting kit buttons. See the upgrade playbook for adoption and rollback.
81
+ No new runtime dependency, ambient clock, donor observer, image optimization or
82
+ commercial donor preset is introduced by this release.
83
+
6
84
  ## 2.5.0 — 2026-09-12
7
85
 
8
86
  ### Find the right component before reading the whole API
package/README.md CHANGED
@@ -17,14 +17,18 @@ assets may not be extracted, modified, or redistributed as a standalone pack.
17
17
  [Usage and upgrade playbook](docs/reference/usage-and-upgrade-playbook.md)
18
18
  - Exhaustive reference (not the starting point):
19
19
  [Generated public API inventory](docs/reference/public-api-inventory.md)
20
- - Live catalog: `pnpm dev` (preview page) and `pnpm storybook`
20
+ - [Interactive catalog](https://swimmer-ui-kit.pieaistudio.com/): real controls,
21
+ matte/glossy comparison, theme/state selectors and copyable React examples.
22
+ - [Full reference](https://swimmer-ui-kit.pieaistudio.com/?view=reference) and
23
+ [liquid form laboratory](https://swimmer-ui-kit.pieaistudio.com/liquid.html).
24
+ Local: `pnpm dev` and `pnpm storybook`.
21
25
 
22
26
  ## Install
23
27
 
24
28
  ```json
25
29
  {
26
30
  "dependencies": {
27
- "@pieai/swimmer-ui-kit": "2.5.0"
31
+ "@pieai/swimmer-ui-kit": "2.6.1"
28
32
  }
29
33
  }
30
34
  ```
package/dist/index.d.ts CHANGED
@@ -5,6 +5,7 @@ import { HTMLAttributes } from 'react';
5
5
  import { InputHTMLAttributes } from 'react';
6
6
  import { ReactNode } from 'react';
7
7
  import { RefAttributes } from 'react';
8
+ import { SelectHTMLAttributes } from 'react';
8
9
  import { TextareaHTMLAttributes } from 'react';
9
10
 
10
11
  /** Opt in to placeholders on purpose, and stop being told about it. */
@@ -1376,12 +1377,14 @@ export declare interface GameBuildLibraryProps {
1376
1377
  'data-testid'?: string | undefined;
1377
1378
  }
1378
1379
 
1379
- export declare function GameButton({ children, className, fullWidth, onClick, sound, static: isStatic, surface, type, variant, ...props }: GameButtonProps): ReactNode;
1380
+ export declare function GameButton({ children, className, fullWidth, liquidFinish, onClick, sound, static: isStatic, surface, type, variant, ...props }: GameButtonProps): ReactNode;
1380
1381
 
1381
1382
  export declare interface GameButtonProps extends ButtonHTMLAttributes<HTMLButtonElement> {
1382
1383
  children: ReactNode;
1383
1384
  /** Fill the available row, including the liquid silhouette and hit target. */
1384
1385
  fullWidth?: boolean;
1386
+ /** Named liquid material. Only used with surface="liquid"; omitted keeps the current look. */
1387
+ liquidFinish?: LiquidFinish;
1385
1388
  sound?: GameInteractionSoundOptions | false;
1386
1389
  /** Disable the scale-on-press feedback where the motion would distract. */
1387
1390
  static?: boolean;
@@ -1727,11 +1730,13 @@ export declare interface GameHudProps {
1727
1730
  label: string;
1728
1731
  }
1729
1732
 
1730
- export declare function GameIconButton({ children, className, label, type, ...props }: GameIconButtonProps): ReactNode;
1733
+ export declare function GameIconButton({ children, className, label, surface, liquidFinish, type, ...props }: GameIconButtonProps): ReactNode;
1731
1734
 
1732
1735
  export declare interface GameIconButtonProps extends ButtonHTMLAttributes<HTMLButtonElement> {
1733
1736
  children: ReactNode;
1734
1737
  label: string;
1738
+ surface?: GameButtonSurface;
1739
+ liquidFinish?: LiquidFinish;
1735
1740
  }
1736
1741
 
1737
1742
  export declare const GameInput: ForwardRefExoticComponent<GameInputProps & RefAttributes<HTMLInputElement>>;
@@ -1912,9 +1917,12 @@ export declare interface GamePlacementToolbarProps {
1912
1917
  title: string;
1913
1918
  }
1914
1919
 
1915
- export declare function GameProgress({ className, label, max, showValue, tone, value, valueLabel, }: GameProgressProps): ReactNode;
1920
+ export declare function GameProgress({ className, label, max, showValue, tone, value, valueLabel, surface, liquidFinish, }: GameProgressProps): ReactNode;
1916
1921
 
1917
1922
  export declare interface GameProgressProps {
1923
+ /** Defaults to the existing liquid leading edge. Flat adds no SVG filter. */
1924
+ surface?: GameButtonSurface;
1925
+ liquidFinish?: LiquidFinish;
1918
1926
  /** Current value, between 0 and `max`. */
1919
1927
  value: number;
1920
1928
  max?: number;
@@ -1980,13 +1988,17 @@ export declare const GameSceneHudLayout: typeof GameShell;
1980
1988
 
1981
1989
  export declare type GameSceneHudLayoutProps = GameShellProps;
1982
1990
 
1983
- export declare function GameSegmentedControl({ activeId, label, onSelect, options, }: GameSegmentedControlProps): ReactNode;
1991
+ export declare function GameSegmentedControl({ activeId, label, onSelect, options, surface, liquidFinish, disabled, }: GameSegmentedControlProps): ReactNode;
1984
1992
 
1985
1993
  export declare interface GameSegmentedControlProps {
1986
1994
  activeId: string;
1987
1995
  label: string;
1988
1996
  onSelect?: (id: string) => void;
1989
1997
  options: readonly GameSegmentedOption[];
1998
+ /** Existing default is liquid. Flat provides a quiet, filter-free option. */
1999
+ surface?: GameButtonSurface;
2000
+ liquidFinish?: LiquidFinish;
2001
+ disabled?: boolean;
1990
2002
  }
1991
2003
 
1992
2004
  declare interface GameSegmentedOption {
@@ -1994,6 +2006,20 @@ declare interface GameSegmentedOption {
1994
2006
  label: string;
1995
2007
  }
1996
2008
 
2009
+ /**
2010
+ * Native select, not a custom listbox state machine. Options/optgroups, form
2011
+ * submission, reset, keyboard and the mobile picker remain browser-owned.
2012
+ * Liquid paints only the closed single-select field. Disabled/multiple/list
2013
+ * modes use the ordinary surface; we do not pretend to animate an OS popup.
2014
+ */
2015
+ export declare const GameSelect: ForwardRefExoticComponent<GameSelectProps & RefAttributes<HTMLSelectElement>>;
2016
+
2017
+ export declare interface GameSelectProps extends SelectHTMLAttributes<HTMLSelectElement> {
2018
+ invalid?: boolean;
2019
+ surface?: GameButtonSurface;
2020
+ liquidFinish?: LiquidFinish;
2021
+ }
2022
+
1997
2023
  export declare function GameShell({ assetLibrary, bottomBar, children, className, density, hud, layout, movementPad, overlay, sidePanel, title, }: GameShellProps): ReactNode;
1998
2024
 
1999
2025
  export declare interface GameShellProps {
@@ -2018,9 +2044,9 @@ export declare interface GameShellProps {
2018
2044
  title: string;
2019
2045
  }
2020
2046
 
2021
- export declare function GameSlider({ label, max, min, onChange, value }: GameSliderProps): ReactNode;
2047
+ export declare function GameSlider({ label, max, min, step, disabled, name, id, onChange, value, }: GameSliderProps): ReactNode;
2022
2048
 
2023
- export declare interface GameSliderProps extends Pick<InputHTMLAttributes<HTMLInputElement>, 'max' | 'min' | 'value'> {
2049
+ export declare interface GameSliderProps extends Pick<InputHTMLAttributes<HTMLInputElement>, 'max' | 'min' | 'value' | 'step' | 'disabled' | 'name' | 'id'> {
2024
2050
  label: string;
2025
2051
  onChange?: (value: number) => void;
2026
2052
  }
@@ -2200,11 +2226,13 @@ export declare interface GameToastProps {
2200
2226
  tone?: 'info' | 'success' | 'danger';
2201
2227
  }
2202
2228
 
2203
- export declare function GameToggle({ checked, disabled, label, onClick }: GameToggleProps): ReactNode;
2229
+ export declare function GameToggle({ checked, disabled, label, onClick, surface, liquidFinish, }: GameToggleProps): ReactNode;
2204
2230
 
2205
2231
  export declare interface GameToggleProps extends Pick<ButtonHTMLAttributes<HTMLButtonElement>, 'disabled' | 'onClick'> {
2206
2232
  checked: boolean;
2207
2233
  label: string;
2234
+ surface?: GameButtonSurface;
2235
+ liquidFinish?: LiquidFinish;
2208
2236
  }
2209
2237
 
2210
2238
  export declare function GameTooltip({ children, label }: GameTooltipProps): ReactNode;
@@ -2354,6 +2382,9 @@ export declare const LIQUID_FORMS: Readonly<Record<LiquidForm, LiquidFormSpec>>;
2354
2382
  */
2355
2383
  export declare const LIQUID_GOOEY_WAVINESS_MAX_FRACTION = 0.3;
2356
2384
 
2385
+ /** Material is independent of a widget's meaning and a form's motion. */
2386
+ export declare type LiquidFinish = 'matte' | 'glossy';
2387
+
2357
2388
  /**
2358
2389
  * The named looks.
2359
2390
  *
@@ -2532,6 +2563,8 @@ export declare interface LiquidGroupProps extends Omit<HTMLAttributes<HTMLDivEle
2532
2563
  * curved surface so it reads as a material rather than as a silhouette.
2533
2564
  */
2534
2565
  gloss?: number;
2566
+ /** Optional named finish. An explicit raw gloss wins; omitted preserves the old rendering. */
2567
+ liquidFinish?: LiquidFinish;
2535
2568
  /** Surface fill. Defaults to the kit's theme surface token. */
2536
2569
  fill?: string;
2537
2570
  /** Extra filter-region slack in px for the silhouette's painted edges. */
@@ -2624,10 +2657,12 @@ export declare interface LiquidMetalButtonProps extends ButtonHTMLAttributes<HTM
2624
2657
 
2625
2658
  export declare type LiquidMetalRendererMode = 'auto' | 'css' | 'webgl';
2626
2659
 
2627
- export declare function LiquidSurface({ children, form, active, fill, stroke, shadow: shadowOverride, radius, className, style, }: LiquidSurfaceProps): ReactNode;
2660
+ export declare function LiquidSurface({ children, liquidFinish, form, active, fill, stroke, shadow: shadowOverride, radius, className, style, }: LiquidSurfaceProps): ReactNode;
2628
2661
 
2629
2662
  export declare interface LiquidSurfaceProps {
2630
2663
  children: ReactNode;
2664
+ /** Omitted keeps the form's existing lighting; matte and glossy share the same motion. */
2665
+ liquidFinish?: LiquidFinish;
2631
2666
  /** Which named look. Defaults to the press form, the one a control wants. */
2632
2667
  form?: LiquidForm;
2633
2668
  /**