@pieai/swimmer-ui-kit 1.9.0 → 1.10.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,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
+ ## 1.10.1
7
+
8
+ ### Fixed
9
+
10
+ - **`<LiquidGroup>` threw where `window` exists and `matchMedia` does not.**
11
+ The reduced-motion hook guarded on `typeof window === 'undefined'`, which is
12
+ true in node and false in jsdom — and jsdom has no `matchMedia`. Any consumer
13
+ testing in jsdom, and any server render that shims `window`, hit a TypeError
14
+ inside a `useState` initializer. Both the initializer and the subscription now
15
+ ask for the function itself. The kit's own suite runs in node, so the middle
16
+ case had never been exercised; a regression test now pins it.
17
+
18
+ ## 1.10.0
19
+
20
+ ### Added
21
+
22
+ - **`motion="follow"` for selection and progress.** `<LiquidGroup>` now carries
23
+ the donor's Move surface through the token layer and shared animation and
24
+ filter-area budgets. It is used only by `GameSegmentedControl`'s selected
25
+ indicator and `GameProgress`'s leading edge; the shared clock sleeps
26
+ completely at rest.
27
+ - **Optional static waviness on `<LiquidGroup>`.** The new group-level
28
+ `waviness` and `wavinessFreq` knobs adapt the pinned liquid-gooey noise
29
+ displacement so merged silhouettes read as fluid instead of as two rounded
30
+ rectangles. The displaced `shape` feeds both SVG shadow passes and the final
31
+ SVG raster shadow, so the shadow follows the same edge. The token default is
32
+ `0` to preserve existing output; the recommended brand preset is `6px` at
33
+ `0.018`, with `3px`/`0.022` and `10px`/`0.014` available as conservative and
34
+ bold points on the same intensity axis. The noise is fixed-seed and static,
35
+ so it adds no idle animation clock. Its maximum displacement is reserved in
36
+ the filter region and counted by the 480,000 px² budget.
37
+
38
+ ### Fixed
39
+
40
+ - **`<LiquidGroup>` drew nothing under React StrictMode.** The effect cleanup
41
+ marked the memoized engine disposed for good, so StrictMode's second mount
42
+ acquired its budget, reported an active group, and then returned early from
43
+ `wake()`. The merged path's `d` stayed empty, which meant every app rendering
44
+ under StrictMode — that is, every app we ship — got no Morph and no Move at
45
+ all, with nothing in the console to say so. `register()` now revives a
46
+ disposed engine and resets the observer and listener state with it, a
47
+ StrictMode regression test asserts the path is not empty, and the
48
+ budget-exhausted path warns once in development instead of degrading in
49
+ silence. Storybook runs with StrictMode on.
50
+
6
51
  ## 1.9.0
7
52
 
8
53
  ### Added
@@ -21,6 +66,14 @@ Format: [Keep a Changelog](https://keepachangelog.com); versioning: semver.
21
66
  merge — that is the bug this prop exists to remove, and the story documents
22
67
  it as a rule rather than a preference.
23
68
 
69
+ ### Fixed
70
+
71
+ - **The `LiquidGroup` stories now demonstrate the supported composition.** The
72
+ demo buttons reset their browser border and background so they do not paint
73
+ hard-edged content-layer circles over the merged silhouette. The stories now
74
+ show the continuous outline on `LiquidGroup`, with a dedicated
75
+ `stroke` + `shadow` example that makes the group-owned treatment explicit.
76
+
24
77
  ## 1.8.1
25
78
 
26
79
  ### Fixed
package/NOTICE CHANGED
@@ -40,15 +40,28 @@ implementation informed by the `liquid-gooey` package in the Libraries
40
40
  repository (https://github.com/Jakubantalik/Libraries/tree/main/packages/liquid-gooey),
41
41
  Copyright (c) 2026 Jakub Antalik, licensed under the MIT License.
42
42
 
43
+ The reviewed upstream state is pinned in `donors-individual-lock.json` at commit
44
+ `3862ffa345217443b63696a8c331a0664eea4b04`; the package source lives at
45
+ `packages/liquid-gooey/` in that repository. The combined-workspace review
46
+ checkout is `<portfolio-root>/_donors-individual/for_SwimmerUIKit/` and is not
47
+ packaged or loaded at runtime.
48
+
43
49
  We took the donor's morph-specific ideas and small implementation patterns:
44
50
  the SVG silhouette/content split, the Gaussian-blur plus alpha color-matrix
45
51
  filter, rounded-rectangle geometry, token-compatible shadow passes, and spring
46
- to easing compilation. We did not take its move, melt, bend, or dissolve
47
- systems, its general observer, or its image-melt engine. We changed the
48
- implementation for this kit by making fill and shadow values token-driven,
49
- adding a process-wide animated-group and filter-area budget, and putting the
50
- shared requestAnimationFrame clock to sleep after stillness. The actual
51
- interactive content remains outside the filtered SVG layer.
52
+ to easing compilation. We also adapted its Move center spring, velocity-axis
53
+ stretch, and lagging tail/mid-droplet physics for the selected segmented
54
+ indicator and progress leading edge. This package now directly adapts the
55
+ donor's group-level `waviness` / `wavinessFreq` filter pass: a fixed-seed
56
+ `feTurbulence` field and `feDisplacementMap` move the silhouette before its
57
+ shadow passes consume it, so the shadow follows the same edge. We did not take
58
+ the donor's melt, bend, or dissolve systems, its general observer, or its
59
+ image-melt engine. We changed the implementation for this kit by making fill
60
+ and shadow values token-driven, keeping waviness static with a shipped-off
61
+ token default, adding a process-wide animated-group and filter-area budget
62
+ that includes the displacement slack, and putting the shared
63
+ requestAnimationFrame clock to sleep after stillness. The actual interactive
64
+ content remains outside the filtered SVG layer.
52
65
 
53
66
  The MIT License text for that material:
54
67
 
package/dist/index.d.ts CHANGED
@@ -268,6 +268,45 @@ export declare const CLAY_LAYER_TOKENS: {
268
268
  readonly toast: "var(--game-ui-z-toast)";
269
269
  };
270
270
 
271
+ /**
272
+ * Token references for the adopted liquid-gooey Move physics. The values are
273
+ * deliberately numeric custom properties so a host theme can tune the feel
274
+ * without putting physics constants in the engine.
275
+ */
276
+ declare const CLAY_LIQUID_GOOEY_TOKENS: {
277
+ readonly moveStiffness: "var(--game-ui-liquid-gooey-move-stiffness)";
278
+ readonly moveDamping: "var(--game-ui-liquid-gooey-move-damping)";
279
+ readonly moveStretch: "var(--game-ui-liquid-gooey-move-stretch)";
280
+ readonly moveTail: "var(--game-ui-liquid-gooey-move-tail)";
281
+ readonly moveForce: "var(--game-ui-liquid-gooey-move-force)";
282
+ readonly moveTailSpringStiffness: "var(--game-ui-liquid-gooey-move-tail-spring-stiffness)";
283
+ readonly moveTailSpringDamping: "var(--game-ui-liquid-gooey-move-tail-spring-damping)";
284
+ readonly moveStretchSpeed: "var(--game-ui-liquid-gooey-move-stretch-speed)";
285
+ readonly moveStretchSquash: "var(--game-ui-liquid-gooey-move-stretch-squash)";
286
+ readonly moveSpeedThreshold: "var(--game-ui-liquid-gooey-move-speed-threshold)";
287
+ readonly moveTailOnsetSpeed: "var(--game-ui-liquid-gooey-move-tail-onset-speed)";
288
+ readonly moveTailOnsetRange: "var(--game-ui-liquid-gooey-move-tail-onset-range)";
289
+ readonly moveTailRamp: "var(--game-ui-liquid-gooey-move-tail-ramp)";
290
+ readonly moveTailMinRadius: "var(--game-ui-liquid-gooey-move-tail-min-radius)";
291
+ readonly moveTailWobble: "var(--game-ui-liquid-gooey-move-tail-wobble)";
292
+ readonly moveTailPhaseSpeed: "var(--game-ui-liquid-gooey-move-tail-phase-speed)";
293
+ readonly moveTailMidpointA: "var(--game-ui-liquid-gooey-move-tail-midpoint-a)";
294
+ readonly moveTailMidpointB: "var(--game-ui-liquid-gooey-move-tail-midpoint-b)";
295
+ readonly moveTailMidRadiusA: "var(--game-ui-liquid-gooey-move-tail-mid-radius-a)";
296
+ readonly moveTailMidRadiusB: "var(--game-ui-liquid-gooey-move-tail-mid-radius-b)";
297
+ readonly moveTailWobblePhase: "var(--game-ui-liquid-gooey-move-tail-wobble-phase)";
298
+ readonly moveMinPerpendicular: "var(--game-ui-liquid-gooey-move-min-perpendicular)";
299
+ readonly moveLagBase: "var(--game-ui-liquid-gooey-move-lag-base)";
300
+ readonly moveLagForce: "var(--game-ui-liquid-gooey-move-lag-force)";
301
+ readonly moveSettleDistance: "var(--game-ui-liquid-gooey-move-settle-distance)";
302
+ readonly moveSettleSpeed: "var(--game-ui-liquid-gooey-move-settle-speed)";
303
+ readonly moveIntegrationRate: "var(--game-ui-liquid-gooey-move-integration-rate)";
304
+ readonly waviness: "var(--game-ui-liquid-gooey-waviness)";
305
+ readonly wavinessFreq: "var(--game-ui-liquid-gooey-waviness-freq)";
306
+ };
307
+ export { CLAY_LIQUID_GOOEY_TOKENS }
308
+ export { CLAY_LIQUID_GOOEY_TOKENS as GAME_UI_LIQUID_GOOEY_TOKENS }
309
+
271
310
  /**
272
311
  * Effect knobs for `<LiquidMetalButton>`. Face/ink are real colours (both
273
312
  * themes must set them); accent aliases `--game-ui-accent` so a host can
@@ -552,6 +591,37 @@ export declare const CLAY_UI_TOKENS: {
552
591
  readonly rest: "var(--game-ui-liquid-metal-rest)";
553
592
  readonly bloom: "var(--game-ui-liquid-metal-bloom)";
554
593
  };
594
+ readonly liquidGooey: {
595
+ readonly moveStiffness: "var(--game-ui-liquid-gooey-move-stiffness)";
596
+ readonly moveDamping: "var(--game-ui-liquid-gooey-move-damping)";
597
+ readonly moveStretch: "var(--game-ui-liquid-gooey-move-stretch)";
598
+ readonly moveTail: "var(--game-ui-liquid-gooey-move-tail)";
599
+ readonly moveForce: "var(--game-ui-liquid-gooey-move-force)";
600
+ readonly moveTailSpringStiffness: "var(--game-ui-liquid-gooey-move-tail-spring-stiffness)";
601
+ readonly moveTailSpringDamping: "var(--game-ui-liquid-gooey-move-tail-spring-damping)";
602
+ readonly moveStretchSpeed: "var(--game-ui-liquid-gooey-move-stretch-speed)";
603
+ readonly moveStretchSquash: "var(--game-ui-liquid-gooey-move-stretch-squash)";
604
+ readonly moveSpeedThreshold: "var(--game-ui-liquid-gooey-move-speed-threshold)";
605
+ readonly moveTailOnsetSpeed: "var(--game-ui-liquid-gooey-move-tail-onset-speed)";
606
+ readonly moveTailOnsetRange: "var(--game-ui-liquid-gooey-move-tail-onset-range)";
607
+ readonly moveTailRamp: "var(--game-ui-liquid-gooey-move-tail-ramp)";
608
+ readonly moveTailMinRadius: "var(--game-ui-liquid-gooey-move-tail-min-radius)";
609
+ readonly moveTailWobble: "var(--game-ui-liquid-gooey-move-tail-wobble)";
610
+ readonly moveTailPhaseSpeed: "var(--game-ui-liquid-gooey-move-tail-phase-speed)";
611
+ readonly moveTailMidpointA: "var(--game-ui-liquid-gooey-move-tail-midpoint-a)";
612
+ readonly moveTailMidpointB: "var(--game-ui-liquid-gooey-move-tail-midpoint-b)";
613
+ readonly moveTailMidRadiusA: "var(--game-ui-liquid-gooey-move-tail-mid-radius-a)";
614
+ readonly moveTailMidRadiusB: "var(--game-ui-liquid-gooey-move-tail-mid-radius-b)";
615
+ readonly moveTailWobblePhase: "var(--game-ui-liquid-gooey-move-tail-wobble-phase)";
616
+ readonly moveMinPerpendicular: "var(--game-ui-liquid-gooey-move-min-perpendicular)";
617
+ readonly moveLagBase: "var(--game-ui-liquid-gooey-move-lag-base)";
618
+ readonly moveLagForce: "var(--game-ui-liquid-gooey-move-lag-force)";
619
+ readonly moveSettleDistance: "var(--game-ui-liquid-gooey-move-settle-distance)";
620
+ readonly moveSettleSpeed: "var(--game-ui-liquid-gooey-move-settle-speed)";
621
+ readonly moveIntegrationRate: "var(--game-ui-liquid-gooey-move-integration-rate)";
622
+ readonly waviness: "var(--game-ui-liquid-gooey-waviness)";
623
+ readonly wavinessFreq: "var(--game-ui-liquid-gooey-waviness-freq)";
624
+ };
555
625
  };
556
626
 
557
627
  export declare type ClayAssetGroup = keyof typeof CLAY_ASSETS;
@@ -722,6 +792,35 @@ export declare const GAME_UI_TARGETS: {
722
792
  export declare const GAME_UI_THEME_CONTRACT: readonly ["--game-ui-bg", "--game-ui-surface", "--game-ui-surface-raised", "--game-ui-panel", "--game-ui-panel-strong", "--game-ui-panel-deep", "--game-ui-text", "--game-ui-text-muted", "--game-ui-accent", "--game-ui-accent-bright", "--game-ui-secondary", "--game-ui-success", "--game-ui-success-bright", "--game-ui-danger", "--game-ui-danger-bright", "--game-ui-warning", "--game-ui-focus-ring", "--game-ui-border-subtle", "--game-ui-border-strong", "--game-ui-disabled", "--game-ui-ink-deep", "--game-ui-border-ink", "--game-ui-wood", "--game-ui-ink-title", "--game-ui-ink-heading", "--game-ui-liquid-metal-face", "--game-ui-liquid-metal-ink"];
723
793
 
724
794
  export declare const GAME_UI_TOKENS: {
795
+ readonly moveStiffness: "var(--game-ui-liquid-gooey-move-stiffness)";
796
+ readonly moveDamping: "var(--game-ui-liquid-gooey-move-damping)";
797
+ readonly moveStretch: "var(--game-ui-liquid-gooey-move-stretch)";
798
+ readonly moveTail: "var(--game-ui-liquid-gooey-move-tail)";
799
+ readonly moveForce: "var(--game-ui-liquid-gooey-move-force)";
800
+ readonly moveTailSpringStiffness: "var(--game-ui-liquid-gooey-move-tail-spring-stiffness)";
801
+ readonly moveTailSpringDamping: "var(--game-ui-liquid-gooey-move-tail-spring-damping)";
802
+ readonly moveStretchSpeed: "var(--game-ui-liquid-gooey-move-stretch-speed)";
803
+ readonly moveStretchSquash: "var(--game-ui-liquid-gooey-move-stretch-squash)";
804
+ readonly moveSpeedThreshold: "var(--game-ui-liquid-gooey-move-speed-threshold)";
805
+ readonly moveTailOnsetSpeed: "var(--game-ui-liquid-gooey-move-tail-onset-speed)";
806
+ readonly moveTailOnsetRange: "var(--game-ui-liquid-gooey-move-tail-onset-range)";
807
+ readonly moveTailRamp: "var(--game-ui-liquid-gooey-move-tail-ramp)";
808
+ readonly moveTailMinRadius: "var(--game-ui-liquid-gooey-move-tail-min-radius)";
809
+ readonly moveTailWobble: "var(--game-ui-liquid-gooey-move-tail-wobble)";
810
+ readonly moveTailPhaseSpeed: "var(--game-ui-liquid-gooey-move-tail-phase-speed)";
811
+ readonly moveTailMidpointA: "var(--game-ui-liquid-gooey-move-tail-midpoint-a)";
812
+ readonly moveTailMidpointB: "var(--game-ui-liquid-gooey-move-tail-midpoint-b)";
813
+ readonly moveTailMidRadiusA: "var(--game-ui-liquid-gooey-move-tail-mid-radius-a)";
814
+ readonly moveTailMidRadiusB: "var(--game-ui-liquid-gooey-move-tail-mid-radius-b)";
815
+ readonly moveTailWobblePhase: "var(--game-ui-liquid-gooey-move-tail-wobble-phase)";
816
+ readonly moveMinPerpendicular: "var(--game-ui-liquid-gooey-move-min-perpendicular)";
817
+ readonly moveLagBase: "var(--game-ui-liquid-gooey-move-lag-base)";
818
+ readonly moveLagForce: "var(--game-ui-liquid-gooey-move-lag-force)";
819
+ readonly moveSettleDistance: "var(--game-ui-liquid-gooey-move-settle-distance)";
820
+ readonly moveSettleSpeed: "var(--game-ui-liquid-gooey-move-settle-speed)";
821
+ readonly moveIntegrationRate: "var(--game-ui-liquid-gooey-move-integration-rate)";
822
+ readonly waviness: "var(--game-ui-liquid-gooey-waviness)";
823
+ readonly wavinessFreq: "var(--game-ui-liquid-gooey-waviness-freq)";
725
824
  readonly iconSm: "var(--game-ui-asset-icon-sm)";
726
825
  readonly iconMd: "var(--game-ui-asset-icon-md)";
727
826
  readonly iconLg: "var(--game-ui-asset-icon-lg)";
@@ -1956,10 +2055,36 @@ declare interface LiquidGooeyBudgetState {
1956
2055
  activeGroups: number;
1957
2056
  }
1958
2057
 
2058
+ /**
2059
+ * Merges nearby item silhouettes into one shape while leaving their content
2060
+ * accessible and unfiltered. Do NOT add border, outline, or box-shadow to
2061
+ * children directly; pass the shared treatment to <LiquidGroup>.
2062
+ */
1959
2063
  export declare const LiquidGroup: ForwardRefExoticComponent<LiquidGroupProps & RefAttributes<HTMLDivElement>> & {
1960
2064
  Item: ForwardRefExoticComponent<LiquidItemProps & RefAttributes<HTMLDivElement>>;
1961
2065
  };
1962
2066
 
2067
+ /**
2068
+ * A shared liquid silhouette behind crisp item content.
2069
+ *
2070
+ * Put the visual treatment on the group: `fill`, `stroke`, and `shadow` are
2071
+ * rebuilt on the merged silhouette. Do NOT add border, outline, or box-shadow
2072
+ * to children directly; those styles live on the content layer and cannot
2073
+ * merge with the liquid shape.
2074
+ *
2075
+ * Its motion vocabulary is intentionally small and semantic:
2076
+ *
2077
+ * | gesture | meaning |
2078
+ * | --- | --- |
2079
+ * | **merge** (Morph) | two things become one: reward settling, collecting, confirming |
2080
+ * | **follow** (Move) | selection, progress, dragging |
2081
+ * | **dissolve** | replacement, transition |
2082
+ * | **still** | THE DEFAULT |
2083
+ *
2084
+ * Liquid appears only on a state change the user caused. There is no ambient,
2085
+ * idle, or decorative liquid; keep the filter-area budget visible when more
2086
+ * than one group is on a screen.
2087
+ */
1963
2088
  export declare interface LiquidGroupProps extends Omit<HTMLAttributes<HTMLDivElement>, 'children'> {
1964
2089
  children: ReactNode;
1965
2090
  /** Goo blur sigma in px. Larger values bridge larger gaps. */
@@ -1974,13 +2099,26 @@ export declare interface LiquidGroupProps extends Omit<HTMLAttributes<HTMLDivEle
1974
2099
  shadow?: string;
1975
2100
  /** Optional stroke syntax rebuilt on the merged silhouette. Note: Do NOT add border to children directly! */
1976
2101
  stroke?: string;
1977
- /** Deterministic reduced-motion override for previews; auto follows the OS. */
1978
- motion?: 'auto' | 'reduced';
2102
+ /** Max px the liquid boundary undulates. Defaults to the CSS token (0). */
2103
+ waviness?: number;
2104
+ /** Noise frequency of the undulation; lower values make longer waves. */
2105
+ wavinessFreq?: number;
2106
+ /**
2107
+ * `auto` follows the existing component transition clock, `follow` adopts
2108
+ * the Move surface for an explicit user-caused selection/progress gesture,
2109
+ * and `reduced` snaps. Still remains the house default gesture.
2110
+ */
2111
+ motion?: 'auto' | 'follow' | 'reduced';
1979
2112
  }
1980
2113
 
1981
2114
  export declare const LiquidItem: ForwardRefExoticComponent<LiquidItemProps & RefAttributes<HTMLDivElement>>;
1982
2115
 
1983
2116
  export declare interface LiquidItemProps extends Omit<HTMLAttributes<HTMLDivElement>, 'children'> {
2117
+ /**
2118
+ * Crisp content rendered above the merged silhouette. Do NOT add border,
2119
+ * outline, or box-shadow to children directly; put the shared treatment on
2120
+ * the parent <LiquidGroup> instead.
2121
+ */
1984
2122
  children: ReactNode;
1985
2123
  /** Mirrored translation applied to the content wrapper and SVG silhouette. */
1986
2124
  x?: number;