@pieai/swimmer-ui-kit 1.10.1 → 1.11.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,93 @@
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
+ ### Added
9
+
10
+ - **Morph shape evolution and content cross-blur.** `LiquidGroup.Item` now
11
+ accepts `morph={{ shape, speed, bounce, contentBlur }}`. The adopted centre →
12
+ size → corner timeline makes the liquid change form like jelly, while the
13
+ default `contentBlur: 7` is written to the content wrapper only and clears as
14
+ the motion settles. The brand-kit token default deliberately enables shape;
15
+ pass `shape: false` for a calm opt-out.
16
+ - **Surface-glued Bend.** `effect="bend"` follows an externally moved child,
17
+ bows its long edges and deforms its rounded caps without a lagging body or
18
+ tail. It publishes `--lg-bend-x`, `--lg-bend-y`, `--lg-bend-xn`, and
19
+ `--lg-bend-yn` on the item for content tilt/rotation.
20
+ - **Knob stories and budget evidence.** Storybook now exposes conservative,
21
+ default, and bold points for Morph and Bend, plus contentBlur off/default/bold
22
+ comparisons and a combined filter-area readout.
23
+
24
+ ### Performance
25
+
26
+ - Morph content-blur and Bend deformation slack are part of the existing
27
+ 480,000 CSS-pixel filter-area ceiling. The shared requestAnimationFrame clock
28
+ remains event-driven and sleeps completely after stillness; an over-budget
29
+ group snaps to static filtered rendering with a development warning.
30
+ - **Image Melt and contact dissolve for `LiquidGroup.Item`.** The first two
31
+ `effect="melt"` items now render the donor-shaped measured image pair with
32
+ crisp-face seam masks, two-palette colour mixing, and a visible marbling
33
+ pass. `dissolve` is an image-only contact modifier with liquid displacement
34
+ and release hysteresis; DOM text stays in the crisp content layer, and the
35
+ modifier is ignored with a development warning under `effect="move"`.
36
+ Numeric knobs are token-backed, share the 480,000 px² filter-area and
37
+ process-wide concurrency budgets, degrade visibly with a one-time warning
38
+ when over budget, and sleep their requestAnimationFrame clock at rest.
39
+
40
+ ## 1.11.1
41
+
42
+ ### Fixed
43
+
44
+ - **Waviness now scales to the element it decorates.** `waviness` is an absolute
45
+ pixel amount, and 6px is 11.5% of a 52px segmented control and 42.9% of a 14px
46
+ progress bar — the same token reading as texture in one place and as bites
47
+ taken out of the bar in the other. The effective amplitude is capped at a
48
+ fraction of the shorter side, so the default is safe wherever it lands instead
49
+ of requiring every consumer to remember a rule that fails silently.
50
+
51
+ - **A clean contour after displacement.** The wavy silhouette is made by moving
52
+ the alpha edge between pixels and nothing reconstructed it afterwards. A 0.5px
53
+ blur on the displaced shape gives the rasteriser something to antialias, and
54
+ the filter region grows to fit it — a blur with no room to spread would have
55
+ traded a ragged edge for a clipped one.
56
+
57
+ This addresses the reconstruction, not the noise. Two octaves at a low base
58
+ frequency is blocky, and a displacement inherits the shape of what drives it;
59
+ the rectangular notches visible on a 14px bar are consistent with that, and
60
+ that hypothesis is still open.
61
+
62
+ ## 1.11.0
63
+
64
+ ### Added
65
+
66
+ - **The rest of the donor's liquid vocabulary.** `morph.shape` gives the
67
+ surface a timeline instead of a resize — the mass travels to the new centre,
68
+ size follows, corners sharpen last. `morph.contentBlur` acts on your content
69
+ rather than the silhouette, which is what makes text read as sitting *in* the
70
+ liquid instead of on it. `effect="bend"` deforms the body with velocity while
71
+ staying glued to its content, and publishes `--lg-bend-x/y` plus unitless
72
+ twins so the content can lean with it. `effect="melt"` runs two images into
73
+ each other with real colour averaging and a marbling pass at the seam, and
74
+ `dissolve` is the same physics as an image-only modifier on a morph item.
75
+ All of them ship on: an effect that defaults to off is one nobody sees, and
76
+ 1.10.0 spent a release proving that with `waviness: 0`.
77
+
78
+ Every effect enabled at once measures 307,892 px² of the 480,000 the process
79
+ budget allows, degrades to a static snap rather than throwing when it runs
80
+ out, and the shared clock still stops dead at rest.
81
+
82
+ The donor's general observer is still not taken, and now the reason is
83
+ written down rather than grouped into a list: this kit's loop meters a
84
+ process-wide budget and sleeps completely when nothing moves, and the donor's
85
+ does neither. Effects are recipes; the loop is the kitchen.
86
+
87
+ ### Fixed
88
+
89
+ - **Image dissolve no longer inherits the default content blur.** `contentBlur`
90
+ arriving on by default reached the DOM text that image-only `dissolve` exists
91
+ to keep crisp. Neither adoption was wrong on its own; the combination was.
92
+
6
93
  ## 1.10.1
7
94
 
8
95
  ### Fixed
package/NOTICE CHANGED
@@ -32,12 +32,12 @@ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
32
32
  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
33
33
  SOFTWARE.
34
34
 
35
- Liquid-gooey morph filter
36
- -------------------------
37
- The liquid morph primitive in `src/LiquidGroup.tsx` and its supporting filter,
38
- geometry, shadow, and spring modules is an original SwimmerUIKit
39
- implementation informed by the `liquid-gooey` package in the Libraries
40
- repository (https://github.com/Jakubantalik/Libraries/tree/main/packages/liquid-gooey),
35
+ Liquid-gooey Morph/Bend adaptations
36
+ -----------------------------------
37
+ The liquid primitive in `src/LiquidGroup.tsx` and its supporting filter,
38
+ geometry, shadow, spring, evolve, and Move modules includes direct local
39
+ adaptations from the `liquid-gooey` package in the Libraries repository
40
+ (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
43
  The reviewed upstream state is pinned in `donors-individual-lock.json` at commit
@@ -46,22 +46,81 @@ The reviewed upstream state is pinned in `donors-individual-lock.json` at commit
46
46
  checkout is `<portfolio-root>/_donors-individual/for_SwimmerUIKit/` and is not
47
47
  packaged or loaded at runtime.
48
48
 
49
- We took the donor's morph-specific ideas and small implementation patterns:
50
- the SVG silhouette/content split, the Gaussian-blur plus alpha color-matrix
51
- filter, rounded-rectangle geometry, token-compatible shadow passes, and spring
52
- to easing compilation. We also adapted its Move center spring, velocity-axis
49
+ We directly adapted its Morph centre/size/radius spring timeline and motion
50
+ envelope for `morph.shape`, its 7px-default content cross-blur for
51
+ `morph.contentBlur`, and its Bend velocity-bowed path, horizontal cap
52
+ deformation, surface-glued tracking, and `--lg-bend-x` / `--lg-bend-y` /
53
+ `--lg-bend-xn` / `--lg-bend-yn` CSS variable outlet. The local implementations
54
+ are in `src/liquidGooeyEvolve.ts` and `src/liquidGooeyMove.ts`; their file
55
+ headers repeat this source URL, pinned commit, copyright, MIT license, and
56
+ NOTICE pointer. We also adapted the donor's Move center spring, velocity-axis
53
57
  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.
58
+ indicator and progress leading edge. This package directly adapts the donor's
59
+ group-level `waviness` / `wavinessFreq` filter pass: a fixed-seed `feTurbulence`
60
+ field and `feDisplacementMap` move the silhouette before its shadow passes
61
+ consume it, so the shadow follows the same edge.
62
+
63
+ The local implementation also adapts the donor's pairwise image-melt engine in
64
+ `src/liquidGooeyImageMelt.tsx`, including the two-item pairing, measured image
65
+ rects, crisp-face seam masks, two-palette colour mixing, and marbling pass. Its
66
+ contact dissolve masks only `<img>` pixels; text remains in the unfiltered DOM
67
+ content layer. The dissolve math is a scoped adaptation of the donor's contact
68
+ observer behavior, not a transplant of the donor's general observer loop.
69
+
70
+ SwimmerUIKit changes the implementation for this kit by making effect values
71
+ token-driven, keeping texture static with a visible 6px default, and adding
72
+ process-wide animated-group and filter-area budgets that include waviness,
73
+ Morph content-blur, Bend deformation, Melt marbling, and dissolve displacement
74
+ slack. The shared requestAnimationFrame clocks sleep after stillness, and
75
+ over-budget effects degrade visibly with a development warning. The actual
76
+ interactive content remains outside the filtered SVG layer; Morph's blur is
77
+ applied to the content wrapper only, Bend content receives inherited CSS
78
+ variables, and image labels stay crisp above the image layer.
79
+
80
+ The MIT License text for that material:
81
+
82
+ MIT License
83
+
84
+ Copyright (c) 2026 Jakub
85
+
86
+ Permission is hereby granted, free of charge, to any person obtaining a copy
87
+ of this software and associated documentation files (the "Software"), to deal
88
+ in the Software without restriction, including without limitation the rights
89
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
90
+ copies of the Software, and to permit persons to whom the Software is
91
+ furnished to do so, subject to the following conditions:
92
+
93
+ The above copyright notice and this permission notice shall be included in all
94
+ copies or substantial portions of the Software.
95
+
96
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
97
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
98
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
99
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
100
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
101
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
102
+ SOFTWARE.
103
+
104
+ Liquid-gooey image Melt and contact dissolve
105
+ --------------------------------------------
106
+ Portions of the pairwise image-melt and contact-image dissolve implementation
107
+ in `src/liquidGooeyImageMelt.tsx` are adapted from liquid-gooey by Jakub
108
+ Antalik (https://github.com/Jakubantalik/Libraries/tree/main/packages/liquid-gooey),
109
+ Copyright (c) 2026 Jakub, licensed under the MIT License.
110
+
111
+ Source URL: https://github.com/Jakubantalik/Libraries/blob/3862ffa345217443b63696a8c331a0664eea4b04/packages/liquid-gooey/src/imageMelt.tsx
112
+ Pinned donor commit: `3862ffa345217443b63696a8c331a0664eea4b04`
113
+ The scoped contact-dissolve math was reviewed from the same commit's
114
+ `src/observer.ts`. The donor's general observer loop was not imported;
115
+ the kit retains its own budgeted and idle-sleeping runtime. This is a local
116
+ adaptation, not a runtime dependency on the donor checkout.
117
+
118
+ The adapted surface keeps the donor's two-item Melt pairing, measured image
119
+ rects, crisp-face seam masks, two-palette colour mixing and marbling pass. Its
120
+ contact dissolve masks only `<img>` pixels; text remains in the unfiltered DOM
121
+ content layer. SwimmerUIKit adds token-backed knobs, its 480,000 px² filter-area
122
+ and process-wide concurrency budgets, graceful development-visible degradation,
123
+ and a sleeping requestAnimationFrame clock.
65
124
 
66
125
  The MIT License text for that material:
67
126
 
package/dist/index.d.ts CHANGED
@@ -9,6 +9,13 @@ import { TextareaHTMLAttributes } from 'react';
9
9
  /** Opt in to placeholders on purpose, and stop being told about it. */
10
10
  export declare function acknowledgeClayPlaceholders(): void;
11
11
 
12
+ export declare interface BendTuning {
13
+ /** Vertical bow strength, 0..1. */
14
+ vertical?: number;
15
+ /** Horizontal cap deformation, 0..1. */
16
+ horizontal?: number;
17
+ }
18
+
12
19
  export declare const CLAY_ASSET_BASE_PATH: "/assets/game/ui/clay/phase03-clay-kit";
13
20
 
14
21
  export declare const CLAY_ASSET_SIZE_TOKENS: {
@@ -274,6 +281,35 @@ export declare const CLAY_LAYER_TOKENS: {
274
281
  * without putting physics constants in the engine.
275
282
  */
276
283
  declare const CLAY_LIQUID_GOOEY_TOKENS: {
284
+ readonly morphShape: "var(--game-ui-liquid-gooey-morph-shape)";
285
+ readonly morphSpeed: "var(--game-ui-liquid-gooey-morph-speed)";
286
+ readonly morphBounce: "var(--game-ui-liquid-gooey-morph-bounce)";
287
+ readonly evolveMassStiffness: "var(--game-ui-liquid-gooey-evolve-mass-stiffness)";
288
+ readonly evolveMassDamping: "var(--game-ui-liquid-gooey-evolve-mass-damping)";
289
+ readonly evolveSizeStiffness: "var(--game-ui-liquid-gooey-evolve-size-stiffness)";
290
+ readonly evolveSizeDamping: "var(--game-ui-liquid-gooey-evolve-size-damping)";
291
+ readonly evolveRadiusStiffness: "var(--game-ui-liquid-gooey-evolve-radius-stiffness)";
292
+ readonly evolveRadiusDamping: "var(--game-ui-liquid-gooey-evolve-radius-damping)";
293
+ readonly evolveContentBlur: "var(--game-ui-liquid-gooey-evolve-content-blur)";
294
+ readonly evolveRoundness: "var(--game-ui-liquid-gooey-evolve-roundness)";
295
+ readonly evolveCornerDuration: "var(--game-ui-liquid-gooey-evolve-corner-duration)";
296
+ readonly evolveCornerDelay: "var(--game-ui-liquid-gooey-evolve-corner-delay)";
297
+ readonly evolveCornerEase: "var(--game-ui-liquid-gooey-evolve-corner-ease)";
298
+ readonly evolveAnticipation: "var(--game-ui-liquid-gooey-evolve-anticipation)";
299
+ readonly evolveTravel: "var(--game-ui-liquid-gooey-evolve-travel)";
300
+ readonly contentBlurAreaMultiplier: "var(--game-ui-liquid-gooey-content-blur-area-multiplier)";
301
+ readonly bendVertical: "var(--game-ui-liquid-gooey-bend-vertical)";
302
+ readonly bendHorizontal: "var(--game-ui-liquid-gooey-bend-horizontal)";
303
+ readonly bendVelocityVertical: "var(--game-ui-liquid-gooey-bend-velocity-vertical)";
304
+ readonly bendVelocityHorizontal: "var(--game-ui-liquid-gooey-bend-velocity-horizontal)";
305
+ readonly bendSmoothing: "var(--game-ui-liquid-gooey-bend-smoothing)";
306
+ readonly bendActiveThreshold: "var(--game-ui-liquid-gooey-bend-active-threshold)";
307
+ readonly bendVerticalCap: "var(--game-ui-liquid-gooey-bend-vertical-cap)";
308
+ readonly bendHorizontalCap: "var(--game-ui-liquid-gooey-bend-horizontal-cap)";
309
+ readonly bendRadiusMin: "var(--game-ui-liquid-gooey-bend-radius-min)";
310
+ readonly bendRadiusMax: "var(--game-ui-liquid-gooey-bend-radius-max)";
311
+ readonly bendLeadingCapFactor: "var(--game-ui-liquid-gooey-bend-leading-cap-factor)";
312
+ readonly bendTrailingCapFactor: "var(--game-ui-liquid-gooey-bend-trailing-cap-factor)";
277
313
  readonly moveStiffness: "var(--game-ui-liquid-gooey-move-stiffness)";
278
314
  readonly moveDamping: "var(--game-ui-liquid-gooey-move-damping)";
279
315
  readonly moveStretch: "var(--game-ui-liquid-gooey-move-stretch)";
@@ -303,6 +339,31 @@ declare const CLAY_LIQUID_GOOEY_TOKENS: {
303
339
  readonly moveIntegrationRate: "var(--game-ui-liquid-gooey-move-integration-rate)";
304
340
  readonly waviness: "var(--game-ui-liquid-gooey-waviness)";
305
341
  readonly wavinessFreq: "var(--game-ui-liquid-gooey-waviness-freq)";
342
+ readonly meltBlur: "var(--game-ui-liquid-gooey-melt-blur)";
343
+ readonly meltContrast: "var(--game-ui-liquid-gooey-melt-contrast)";
344
+ readonly meltReach: "var(--game-ui-liquid-gooey-melt-reach)";
345
+ readonly meltFade: "var(--game-ui-liquid-gooey-melt-fade)";
346
+ readonly meltWarp: "var(--game-ui-liquid-gooey-melt-warp)";
347
+ readonly meltMix: "var(--game-ui-liquid-gooey-melt-mix)";
348
+ readonly meltMixBlur: "var(--game-ui-liquid-gooey-melt-mix-blur)";
349
+ readonly meltGravity: "var(--game-ui-liquid-gooey-melt-gravity)";
350
+ readonly meltWaviness: "var(--game-ui-liquid-gooey-melt-waviness)";
351
+ readonly dissolveBlur: "var(--game-ui-liquid-gooey-dissolve-blur)";
352
+ readonly dissolveWarp: "var(--game-ui-liquid-gooey-dissolve-warp)";
353
+ readonly dissolvePull: "var(--game-ui-liquid-gooey-dissolve-pull)";
354
+ readonly dissolveRange: "var(--game-ui-liquid-gooey-dissolve-range)";
355
+ readonly dissolveZone: "var(--game-ui-liquid-gooey-dissolve-zone)";
356
+ readonly dissolveMix: "var(--game-ui-liquid-gooey-dissolve-mix)";
357
+ readonly dissolveGravity: "var(--game-ui-liquid-gooey-dissolve-gravity)";
358
+ readonly dissolveTaper: "var(--game-ui-liquid-gooey-dissolve-taper)";
359
+ readonly dissolveWarpFreq: "var(--game-ui-liquid-gooey-dissolve-warp-freq)";
360
+ readonly dissolveFlowSpeed: "var(--game-ui-liquid-gooey-dissolve-flow-speed)";
361
+ readonly dissolveDetail: "var(--game-ui-liquid-gooey-dissolve-detail)";
362
+ readonly dissolveReleaseMs: "var(--game-ui-liquid-gooey-dissolve-release-ms)";
363
+ readonly dissolveFadeMs: "var(--game-ui-liquid-gooey-dissolve-fade-ms)";
364
+ readonly dissolveStrength: "var(--game-ui-liquid-gooey-dissolve-strength)";
365
+ readonly dissolveSink: "var(--game-ui-liquid-gooey-dissolve-sink)";
366
+ readonly dissolveSeamBlur: "var(--game-ui-liquid-gooey-dissolve-seam-blur)";
306
367
  };
307
368
  export { CLAY_LIQUID_GOOEY_TOKENS }
308
369
  export { CLAY_LIQUID_GOOEY_TOKENS as GAME_UI_LIQUID_GOOEY_TOKENS }
@@ -592,6 +653,35 @@ export declare const CLAY_UI_TOKENS: {
592
653
  readonly bloom: "var(--game-ui-liquid-metal-bloom)";
593
654
  };
594
655
  readonly liquidGooey: {
656
+ readonly morphShape: "var(--game-ui-liquid-gooey-morph-shape)";
657
+ readonly morphSpeed: "var(--game-ui-liquid-gooey-morph-speed)";
658
+ readonly morphBounce: "var(--game-ui-liquid-gooey-morph-bounce)";
659
+ readonly evolveMassStiffness: "var(--game-ui-liquid-gooey-evolve-mass-stiffness)";
660
+ readonly evolveMassDamping: "var(--game-ui-liquid-gooey-evolve-mass-damping)";
661
+ readonly evolveSizeStiffness: "var(--game-ui-liquid-gooey-evolve-size-stiffness)";
662
+ readonly evolveSizeDamping: "var(--game-ui-liquid-gooey-evolve-size-damping)";
663
+ readonly evolveRadiusStiffness: "var(--game-ui-liquid-gooey-evolve-radius-stiffness)";
664
+ readonly evolveRadiusDamping: "var(--game-ui-liquid-gooey-evolve-radius-damping)";
665
+ readonly evolveContentBlur: "var(--game-ui-liquid-gooey-evolve-content-blur)";
666
+ readonly evolveRoundness: "var(--game-ui-liquid-gooey-evolve-roundness)";
667
+ readonly evolveCornerDuration: "var(--game-ui-liquid-gooey-evolve-corner-duration)";
668
+ readonly evolveCornerDelay: "var(--game-ui-liquid-gooey-evolve-corner-delay)";
669
+ readonly evolveCornerEase: "var(--game-ui-liquid-gooey-evolve-corner-ease)";
670
+ readonly evolveAnticipation: "var(--game-ui-liquid-gooey-evolve-anticipation)";
671
+ readonly evolveTravel: "var(--game-ui-liquid-gooey-evolve-travel)";
672
+ readonly contentBlurAreaMultiplier: "var(--game-ui-liquid-gooey-content-blur-area-multiplier)";
673
+ readonly bendVertical: "var(--game-ui-liquid-gooey-bend-vertical)";
674
+ readonly bendHorizontal: "var(--game-ui-liquid-gooey-bend-horizontal)";
675
+ readonly bendVelocityVertical: "var(--game-ui-liquid-gooey-bend-velocity-vertical)";
676
+ readonly bendVelocityHorizontal: "var(--game-ui-liquid-gooey-bend-velocity-horizontal)";
677
+ readonly bendSmoothing: "var(--game-ui-liquid-gooey-bend-smoothing)";
678
+ readonly bendActiveThreshold: "var(--game-ui-liquid-gooey-bend-active-threshold)";
679
+ readonly bendVerticalCap: "var(--game-ui-liquid-gooey-bend-vertical-cap)";
680
+ readonly bendHorizontalCap: "var(--game-ui-liquid-gooey-bend-horizontal-cap)";
681
+ readonly bendRadiusMin: "var(--game-ui-liquid-gooey-bend-radius-min)";
682
+ readonly bendRadiusMax: "var(--game-ui-liquid-gooey-bend-radius-max)";
683
+ readonly bendLeadingCapFactor: "var(--game-ui-liquid-gooey-bend-leading-cap-factor)";
684
+ readonly bendTrailingCapFactor: "var(--game-ui-liquid-gooey-bend-trailing-cap-factor)";
595
685
  readonly moveStiffness: "var(--game-ui-liquid-gooey-move-stiffness)";
596
686
  readonly moveDamping: "var(--game-ui-liquid-gooey-move-damping)";
597
687
  readonly moveStretch: "var(--game-ui-liquid-gooey-move-stretch)";
@@ -621,6 +711,31 @@ export declare const CLAY_UI_TOKENS: {
621
711
  readonly moveIntegrationRate: "var(--game-ui-liquid-gooey-move-integration-rate)";
622
712
  readonly waviness: "var(--game-ui-liquid-gooey-waviness)";
623
713
  readonly wavinessFreq: "var(--game-ui-liquid-gooey-waviness-freq)";
714
+ readonly meltBlur: "var(--game-ui-liquid-gooey-melt-blur)";
715
+ readonly meltContrast: "var(--game-ui-liquid-gooey-melt-contrast)";
716
+ readonly meltReach: "var(--game-ui-liquid-gooey-melt-reach)";
717
+ readonly meltFade: "var(--game-ui-liquid-gooey-melt-fade)";
718
+ readonly meltWarp: "var(--game-ui-liquid-gooey-melt-warp)";
719
+ readonly meltMix: "var(--game-ui-liquid-gooey-melt-mix)";
720
+ readonly meltMixBlur: "var(--game-ui-liquid-gooey-melt-mix-blur)";
721
+ readonly meltGravity: "var(--game-ui-liquid-gooey-melt-gravity)";
722
+ readonly meltWaviness: "var(--game-ui-liquid-gooey-melt-waviness)";
723
+ readonly dissolveBlur: "var(--game-ui-liquid-gooey-dissolve-blur)";
724
+ readonly dissolveWarp: "var(--game-ui-liquid-gooey-dissolve-warp)";
725
+ readonly dissolvePull: "var(--game-ui-liquid-gooey-dissolve-pull)";
726
+ readonly dissolveRange: "var(--game-ui-liquid-gooey-dissolve-range)";
727
+ readonly dissolveZone: "var(--game-ui-liquid-gooey-dissolve-zone)";
728
+ readonly dissolveMix: "var(--game-ui-liquid-gooey-dissolve-mix)";
729
+ readonly dissolveGravity: "var(--game-ui-liquid-gooey-dissolve-gravity)";
730
+ readonly dissolveTaper: "var(--game-ui-liquid-gooey-dissolve-taper)";
731
+ readonly dissolveWarpFreq: "var(--game-ui-liquid-gooey-dissolve-warp-freq)";
732
+ readonly dissolveFlowSpeed: "var(--game-ui-liquid-gooey-dissolve-flow-speed)";
733
+ readonly dissolveDetail: "var(--game-ui-liquid-gooey-dissolve-detail)";
734
+ readonly dissolveReleaseMs: "var(--game-ui-liquid-gooey-dissolve-release-ms)";
735
+ readonly dissolveFadeMs: "var(--game-ui-liquid-gooey-dissolve-fade-ms)";
736
+ readonly dissolveStrength: "var(--game-ui-liquid-gooey-dissolve-strength)";
737
+ readonly dissolveSink: "var(--game-ui-liquid-gooey-dissolve-sink)";
738
+ readonly dissolveSeamBlur: "var(--game-ui-liquid-gooey-dissolve-seam-blur)";
624
739
  };
625
740
  };
626
741
 
@@ -685,6 +800,83 @@ export declare const DEFAULT_LIQUID_GOOEY_FILTER_AREA_BUDGET = 480000;
685
800
  */
686
801
  export declare const DEFAULT_LIQUID_METAL_CONTEXT_BUDGET = 2;
687
802
 
803
+ export declare const DISSOLVE_DEFAULTS: ResolvedDissolveOptions;
804
+
805
+ export declare interface DissolveOptions {
806
+ /** Melt blur in px. */
807
+ blur?: number;
808
+ /** Displacement strength of the liquid warp. */
809
+ warp?: number;
810
+ /** Magnetic drift toward the contact, in px. */
811
+ pull?: number;
812
+ /** Distance at which melting starts. */
813
+ range?: number;
814
+ /** Size of the melt zone around the contact, in px. */
815
+ zone?: number;
816
+ /** 0..1 two-liquid erosion strength. */
817
+ mix?: number;
818
+ /** Px the melt is drawn toward the neighbour's centre. */
819
+ gravity?: number;
820
+ /** 0..1 pointiness of the directional flow. */
821
+ taper?: number;
822
+ /** Noise frequency multiplier. */
823
+ warpFreq?: number;
824
+ /** Px/s the noise field may drift while the item is moving. */
825
+ flowSpeed?: number;
826
+ /** Noise style. */
827
+ warpStyle?: 'fractalNoise' | 'turbulence';
828
+ /** Noise octaves. */
829
+ detail?: number;
830
+ /** Whether the dissolve is currently allowed to grow. */
831
+ active?: boolean;
832
+ /** Structural release time in ms. */
833
+ releaseMs?: number;
834
+ /** Opacity fade time in ms. */
835
+ fadeMs?: number;
836
+ /** 0..1 overall dissolve ceiling. */
837
+ strength?: number;
838
+ /** Fraction of the smaller body at which the seam has been swallowed. */
839
+ sink?: number;
840
+ /** Plain blur radius for the guaranteed-smooth seam wash. */
841
+ seamBlur?: number;
842
+ }
843
+
844
+ export declare type DissolveValue = boolean | number | DissolveOptions;
845
+
846
+ /**
847
+ * Morph shape physics adapted from `liquid-gooey` by Jakub Antalik.
848
+ *
849
+ * Source: https://github.com/Jakubantalik/Libraries/tree/main/packages/liquid-gooey
850
+ * Pinned commit: 3862ffa345217443b63696a8c331a0664eea4b04
851
+ * Copyright (c) 2026 Jakub Antalik. Licensed under the MIT License.
852
+ * See NOTICE for the attribution and license text. This local module keeps
853
+ * the donor's centre -> size -> corner timeline and content cross-blur, but
854
+ * routes every tunable value through SwimmerUIKit's token layer.
855
+ */
856
+ declare interface EvolveOptions {
857
+ /** Spring driving the liquid mass's centre. */
858
+ massStiffness?: number;
859
+ massDamping?: number;
860
+ /** Spring driving width and height. */
861
+ sizeStiffness?: number;
862
+ sizeDamping?: number;
863
+ /** Spring driving the corner radius. */
864
+ radiusStiffness?: number;
865
+ radiusDamping?: number;
866
+ /** Maximum content cross-blur during the morph, in px. */
867
+ contentBlur?: number;
868
+ /** 0..1 droplet roundness during a shape transition. */
869
+ roundness?: number;
870
+ /** Corner-forming timeline. */
871
+ cornerDuration?: number;
872
+ cornerDelay?: number;
873
+ cornerEase?: string;
874
+ /** Ramp-in time for the droplet lead, in ms. */
875
+ anticipation?: number;
876
+ /** Maximum droplet lead toward the destination, in px. */
877
+ travel?: number;
878
+ }
879
+
688
880
  export declare function FirstSessionHud({ authenticated, batteryCount, className, dailyStreak, iconSlots, labels, onHistory, onSettings, onWardrobe, playerName, }: FirstSessionHudProps): ReactNode;
689
881
 
690
882
  export declare interface FirstSessionHudIconSlots {
@@ -792,6 +984,35 @@ export declare const GAME_UI_TARGETS: {
792
984
  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"];
793
985
 
794
986
  export declare const GAME_UI_TOKENS: {
987
+ readonly morphShape: "var(--game-ui-liquid-gooey-morph-shape)";
988
+ readonly morphSpeed: "var(--game-ui-liquid-gooey-morph-speed)";
989
+ readonly morphBounce: "var(--game-ui-liquid-gooey-morph-bounce)";
990
+ readonly evolveMassStiffness: "var(--game-ui-liquid-gooey-evolve-mass-stiffness)";
991
+ readonly evolveMassDamping: "var(--game-ui-liquid-gooey-evolve-mass-damping)";
992
+ readonly evolveSizeStiffness: "var(--game-ui-liquid-gooey-evolve-size-stiffness)";
993
+ readonly evolveSizeDamping: "var(--game-ui-liquid-gooey-evolve-size-damping)";
994
+ readonly evolveRadiusStiffness: "var(--game-ui-liquid-gooey-evolve-radius-stiffness)";
995
+ readonly evolveRadiusDamping: "var(--game-ui-liquid-gooey-evolve-radius-damping)";
996
+ readonly evolveContentBlur: "var(--game-ui-liquid-gooey-evolve-content-blur)";
997
+ readonly evolveRoundness: "var(--game-ui-liquid-gooey-evolve-roundness)";
998
+ readonly evolveCornerDuration: "var(--game-ui-liquid-gooey-evolve-corner-duration)";
999
+ readonly evolveCornerDelay: "var(--game-ui-liquid-gooey-evolve-corner-delay)";
1000
+ readonly evolveCornerEase: "var(--game-ui-liquid-gooey-evolve-corner-ease)";
1001
+ readonly evolveAnticipation: "var(--game-ui-liquid-gooey-evolve-anticipation)";
1002
+ readonly evolveTravel: "var(--game-ui-liquid-gooey-evolve-travel)";
1003
+ readonly contentBlurAreaMultiplier: "var(--game-ui-liquid-gooey-content-blur-area-multiplier)";
1004
+ readonly bendVertical: "var(--game-ui-liquid-gooey-bend-vertical)";
1005
+ readonly bendHorizontal: "var(--game-ui-liquid-gooey-bend-horizontal)";
1006
+ readonly bendVelocityVertical: "var(--game-ui-liquid-gooey-bend-velocity-vertical)";
1007
+ readonly bendVelocityHorizontal: "var(--game-ui-liquid-gooey-bend-velocity-horizontal)";
1008
+ readonly bendSmoothing: "var(--game-ui-liquid-gooey-bend-smoothing)";
1009
+ readonly bendActiveThreshold: "var(--game-ui-liquid-gooey-bend-active-threshold)";
1010
+ readonly bendVerticalCap: "var(--game-ui-liquid-gooey-bend-vertical-cap)";
1011
+ readonly bendHorizontalCap: "var(--game-ui-liquid-gooey-bend-horizontal-cap)";
1012
+ readonly bendRadiusMin: "var(--game-ui-liquid-gooey-bend-radius-min)";
1013
+ readonly bendRadiusMax: "var(--game-ui-liquid-gooey-bend-radius-max)";
1014
+ readonly bendLeadingCapFactor: "var(--game-ui-liquid-gooey-bend-leading-cap-factor)";
1015
+ readonly bendTrailingCapFactor: "var(--game-ui-liquid-gooey-bend-trailing-cap-factor)";
795
1016
  readonly moveStiffness: "var(--game-ui-liquid-gooey-move-stiffness)";
796
1017
  readonly moveDamping: "var(--game-ui-liquid-gooey-move-damping)";
797
1018
  readonly moveStretch: "var(--game-ui-liquid-gooey-move-stretch)";
@@ -821,6 +1042,31 @@ export declare const GAME_UI_TOKENS: {
821
1042
  readonly moveIntegrationRate: "var(--game-ui-liquid-gooey-move-integration-rate)";
822
1043
  readonly waviness: "var(--game-ui-liquid-gooey-waviness)";
823
1044
  readonly wavinessFreq: "var(--game-ui-liquid-gooey-waviness-freq)";
1045
+ readonly meltBlur: "var(--game-ui-liquid-gooey-melt-blur)";
1046
+ readonly meltContrast: "var(--game-ui-liquid-gooey-melt-contrast)";
1047
+ readonly meltReach: "var(--game-ui-liquid-gooey-melt-reach)";
1048
+ readonly meltFade: "var(--game-ui-liquid-gooey-melt-fade)";
1049
+ readonly meltWarp: "var(--game-ui-liquid-gooey-melt-warp)";
1050
+ readonly meltMix: "var(--game-ui-liquid-gooey-melt-mix)";
1051
+ readonly meltMixBlur: "var(--game-ui-liquid-gooey-melt-mix-blur)";
1052
+ readonly meltGravity: "var(--game-ui-liquid-gooey-melt-gravity)";
1053
+ readonly meltWaviness: "var(--game-ui-liquid-gooey-melt-waviness)";
1054
+ readonly dissolveBlur: "var(--game-ui-liquid-gooey-dissolve-blur)";
1055
+ readonly dissolveWarp: "var(--game-ui-liquid-gooey-dissolve-warp)";
1056
+ readonly dissolvePull: "var(--game-ui-liquid-gooey-dissolve-pull)";
1057
+ readonly dissolveRange: "var(--game-ui-liquid-gooey-dissolve-range)";
1058
+ readonly dissolveZone: "var(--game-ui-liquid-gooey-dissolve-zone)";
1059
+ readonly dissolveMix: "var(--game-ui-liquid-gooey-dissolve-mix)";
1060
+ readonly dissolveGravity: "var(--game-ui-liquid-gooey-dissolve-gravity)";
1061
+ readonly dissolveTaper: "var(--game-ui-liquid-gooey-dissolve-taper)";
1062
+ readonly dissolveWarpFreq: "var(--game-ui-liquid-gooey-dissolve-warp-freq)";
1063
+ readonly dissolveFlowSpeed: "var(--game-ui-liquid-gooey-dissolve-flow-speed)";
1064
+ readonly dissolveDetail: "var(--game-ui-liquid-gooey-dissolve-detail)";
1065
+ readonly dissolveReleaseMs: "var(--game-ui-liquid-gooey-dissolve-release-ms)";
1066
+ readonly dissolveFadeMs: "var(--game-ui-liquid-gooey-dissolve-fade-ms)";
1067
+ readonly dissolveStrength: "var(--game-ui-liquid-gooey-dissolve-strength)";
1068
+ readonly dissolveSink: "var(--game-ui-liquid-gooey-dissolve-sink)";
1069
+ readonly dissolveSeamBlur: "var(--game-ui-liquid-gooey-dissolve-seam-blur)";
824
1070
  readonly iconSm: "var(--game-ui-asset-icon-sm)";
825
1071
  readonly iconMd: "var(--game-ui-asset-icon-md)";
826
1072
  readonly iconLg: "var(--game-ui-asset-icon-lg)";
@@ -2044,6 +2290,36 @@ export declare function getLiquidMetalContextBudget(): {
2044
2290
  used: number;
2045
2291
  };
2046
2292
 
2293
+ export declare const IMAGE_MELT_DEFAULTS: Required<ImageMeltOptions>;
2294
+
2295
+ export declare interface ImageMeltOptions {
2296
+ /** Goo sigma: how far the bodies reach for each other and how wide colour averaging runs. */
2297
+ blur?: number;
2298
+ /** Alpha-contrast slope of the liquid boundary. */
2299
+ contrast?: number;
2300
+ /** How far each crisp face dissolves back before its neighbour. */
2301
+ reach?: number;
2302
+ /** Softness of the crisp-face dissolve mask. */
2303
+ fade?: number;
2304
+ /** Turbulence displacement of the molten layer, in px. */
2305
+ warp?: number;
2306
+ /** 0..1 two-liquid marbling strength in the touch area. */
2307
+ mix?: number;
2308
+ /** Blur of the marble pass's source colours. */
2309
+ mixBlur?: number;
2310
+ /** How deep the marble zone reaches into each card. */
2311
+ gravity?: number;
2312
+ /** Wavelength control of the warp noise. */
2313
+ waviness?: number;
2314
+ }
2315
+
2316
+ /**
2317
+ * The default fraction is intentionally derived from the rendered surface,
2318
+ * not from the requested waviness token. A fixed pixel displacement is safe
2319
+ * on a large blob but can consume a thin control's whole visual height.
2320
+ */
2321
+ export declare const LIQUID_GOOEY_WAVINESS_MAX_FRACTION = 0.3;
2322
+
2047
2323
  declare interface LiquidGooeyBudgetOptions {
2048
2324
  maxAnimatedGroups?: number;
2049
2325
  maxFilterArea?: number;
@@ -2057,8 +2333,10 @@ declare interface LiquidGooeyBudgetState {
2057
2333
 
2058
2334
  /**
2059
2335
  * 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>.
2336
+ * accessible and separately filtered. Morph content may cross-blur while it
2337
+ * moves; Bend keeps its content surface-glued and exposes its live CSS vars.
2338
+ * Do NOT add border, outline, or box-shadow to children directly; pass the
2339
+ * shared treatment to <LiquidGroup>.
2062
2340
  */
2063
2341
  export declare const LiquidGroup: ForwardRefExoticComponent<LiquidGroupProps & RefAttributes<HTMLDivElement>> & {
2064
2342
  Item: ForwardRefExoticComponent<LiquidItemProps & RefAttributes<HTMLDivElement>>;
@@ -2078,6 +2356,8 @@ export declare const LiquidGroup: ForwardRefExoticComponent<LiquidGroupProps & R
2078
2356
  * | --- | --- |
2079
2357
  * | **merge** (Morph) | two things become one: reward settling, collecting, confirming |
2080
2358
  * | **follow** (Move) | selection, progress, dragging |
2359
+ * | **shape** (Morph shape) | the liquid changes size and corners like jelly |
2360
+ * | **bend** | speed bows the surface while content stays glued to it |
2081
2361
  * | **dissolve** | replacement, transition |
2082
2362
  * | **still** | THE DEFAULT |
2083
2363
  *
@@ -2099,10 +2379,15 @@ export declare interface LiquidGroupProps extends Omit<HTMLAttributes<HTMLDivEle
2099
2379
  shadow?: string;
2100
2380
  /** Optional stroke syntax rebuilt on the merged silhouette. Note: Do NOT add border to children directly! */
2101
2381
  stroke?: string;
2102
- /** Max px the liquid boundary undulates. Defaults to the CSS token (0). */
2382
+ /** Max px the liquid boundary undulates. Defaults to the CSS token (6). */
2103
2383
  waviness?: number;
2104
2384
  /** Noise frequency of the undulation; lower values make longer waves. */
2105
2385
  wavinessFreq?: number;
2386
+ /**
2387
+ * Max fraction of the group's shorter side allowed for waviness. Defaults
2388
+ * to 0.3; pass `false` to explicitly disable the size clamp.
2389
+ */
2390
+ wavinessClamp?: number | false;
2106
2391
  /**
2107
2392
  * `auto` follows the existing component transition clock, `follow` adopts
2108
2393
  * the Move surface for an explicit user-caused selection/progress gesture,
@@ -2130,6 +2415,20 @@ export declare interface LiquidItemProps extends Omit<HTMLAttributes<HTMLDivElem
2130
2415
  delay?: number;
2131
2416
  /** Override the measured content border radius for the silhouette. */
2132
2417
  radius?: number | CornerRadii;
2418
+ /** Select the adopted item surface behavior. Bend follows child geometry. */
2419
+ effect?: 'morph' | 'move' | 'melt' | 'bend';
2420
+ /** Morph shape, tempo, bounce, and content cross-blur tuning. */
2421
+ morph?: MorphTuning;
2422
+ /** Bend strengths for vertical bow and horizontal cap deformation. */
2423
+ bend?: BendTuning;
2424
+ /** Follow a child moved by external code; Bend implies this automatically. */
2425
+ observe?: boolean;
2426
+ /** Numeric knobs for the pairwise image Melt surface, plus an optional source URL. */
2427
+ melt?: ImageMeltOptions & {
2428
+ src?: string;
2429
+ };
2430
+ /** Contact image modifier. Text and other DOM content remain on the crisp layer. */
2431
+ dissolve?: boolean | number | DissolveOptions;
2133
2432
  }
2134
2433
 
2135
2434
  export declare function LiquidMetalButton({ children, className, onClick, sound, type, renderer, ...props }: LiquidMetalButtonProps): ReactNode;
@@ -2149,10 +2448,46 @@ export declare interface LiquidMetalButtonProps extends ButtonHTMLAttributes<HTM
2149
2448
 
2150
2449
  export declare type LiquidMetalRendererMode = 'auto' | 'css' | 'webgl';
2151
2450
 
2451
+ export declare interface MorphTuning {
2452
+ /** Whether shape-change physics is enabled. The kit default is token-on. */
2453
+ shape?: boolean;
2454
+ /** Tempo multiplier. */
2455
+ speed?: number;
2456
+ /** 0..1 overshoot amount. */
2457
+ bounce?: number;
2458
+ /** Maximum content cross-blur, in px. */
2459
+ contentBlur?: number;
2460
+ /** Raw evolve escape hatch. */
2461
+ advanced?: Partial<EvolveOptions>;
2462
+ }
2463
+
2152
2464
  export declare function playGameInteractionSound(options?: GameInteractionSoundOptions): boolean;
2153
2465
 
2154
2466
  export declare function playGameInteractionSoundForContext(audioContext: GameInteractionAudioContext, options?: GameInteractionSoundOptions): boolean;
2155
2467
 
2468
+ declare interface ResolvedDissolveOptions {
2469
+ blur: number;
2470
+ warp: number;
2471
+ pull: number;
2472
+ range: number;
2473
+ zone: number;
2474
+ mix: number;
2475
+ gravity: number;
2476
+ taper: number;
2477
+ warpFreq: number;
2478
+ flowSpeed: number;
2479
+ warpStyle: 'fractalNoise' | 'turbulence';
2480
+ detail: number;
2481
+ active: boolean;
2482
+ releaseMs: number;
2483
+ fadeMs: number;
2484
+ strength: number;
2485
+ sink: number;
2486
+ seamBlur: number;
2487
+ }
2488
+
2489
+ export declare function resolveDissolveOptions(element: HTMLElement | null, input: DissolveValue): ResolvedDissolveOptions;
2490
+
2156
2491
  /**
2157
2492
  * Point the sculpted set at somewhere other than the default path — a CDN, a
2158
2493
  * sub-path deploy, a host whose static root is not `/`. Pass no trailing slash.