{"_id":"liquid-gooey","_rev":"4-ad65388af3925604c0efbb6ebe76139d","name":"liquid-gooey","dist-tags":{"latest":"0.2.2"},"versions":{"0.1.0":{"name":"liquid-gooey","version":"0.1.0","keywords":["react","gooey","metaball","liquid","svg-filter","animation","spring"],"author":{"name":"Jakub Antalik"},"license":"MIT","_id":"liquid-gooey@0.1.0","maintainers":[{"name":"jakubkubo","email":"jakubja@gmail.com"}],"homepage":"https://gooey.jakubantalik.com","bugs":{"url":"https://github.com/Jakubantalik/Libraries/issues"},"dist":{"shasum":"264fe1f80a2652cd9264035d01c3726f231dd599","tarball":"https://registry.npmjs.org/liquid-gooey/-/liquid-gooey-0.1.0.tgz","fileCount":9,"integrity":"sha512-iFG1/RaI9Qntvpv6tzxOQGesTJSmctd3gb1pNYH9Tn8elnolknDI2WeYpr5IenClNe/6hWonS/zPvOCJm+9uaQ==","signatures":[{"sig":"MEUCIQCD39XyQed8bPQma+u6qoX/xlN3nLHDimJ3w6JnOsWeOQIgIVbm8eRjjvkwvG7hAG1pedH3DFoFRU/tMJLjsOu9TFk=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":511225},"main":"./dist/index.cjs","type":"module","types":"./dist/index.d.ts","module":"./dist/index.js","exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.js","require":"./dist/index.cjs"}},"gitHead":"23689a13fa05cbd12993a271cc2b58a507bbdbe5","scripts":{"build":"tsup src/index.ts --format esm,cjs --dts --sourcemap --clean","typecheck":"tsc --noEmit","prepublishOnly":"npm run build"},"_npmUser":{"name":"jakubkubo","email":"jakubja@gmail.com"},"repository":{"url":"git+https://github.com/Jakubantalik/Libraries.git","type":"git","directory":"packages/liquid-gooey"},"_npmVersion":"10.8.2","description":"Liquid UI effects for React: Morph (gooey merge, jelly shape change, contact dissolve) and Move (liquid-rubber trails). SVG-filter silhouette layer + crisp content layer, real shadows on the merged liquid. Cross-browser, Safari included.","directories":{},"sideEffects":false,"_nodeVersion":"20.20.2","_hasShrinkwrap":false,"devDependencies":{"tsup":"^8.1.0","typescript":"^5.5.3","@types/react":"^18.3.3","@types/react-dom":"^18.3.0"},"peerDependencies":{"react":">=18","react-dom":">=18"},"_npmOperationalInternal":{"tmp":"tmp/liquid-gooey_0.1.0_1786453579350_0.8045100649572288","host":"s3://npm-registry-packages-npm-production"}},"0.2.0":{"name":"liquid-gooey","version":"0.2.0","keywords":["react","gooey","metaball","liquid","svg-filter","animation","spring"],"author":{"name":"Jakub Antalik"},"license":"MIT","_id":"liquid-gooey@0.2.0","maintainers":[{"name":"jakubkubo","email":"jakubja@gmail.com"}],"homepage":"https://gooey.jakubantalik.com","bugs":{"url":"https://github.com/Jakubantalik/Libraries/issues"},"dist":{"shasum":"36439d40acaa76b6b1f218362035866f18cc42ed","tarball":"https://registry.npmjs.org/liquid-gooey/-/liquid-gooey-0.2.0.tgz","fileCount":9,"integrity":"sha512-FXjMKk8Sa4xAI7ggAb70pbFJHf0Lcrm/R2RnOPvfXdNncXPdd/Uuh0yhmO8PgLifmwtvckGU766DWFLIH2hHGw==","signatures":[{"sig":"MEUCIQCOLsPCfH9oIH5lop+6JJvVROlWzZlJqCqWwzZujWU9CgIgBuiYhgVXZelMn5jRi+tvOGz3zdEepCAesQsls6mwO78=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":741523},"main":"./dist/index.cjs","type":"module","types":"./dist/index.d.ts","module":"./dist/index.js","exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.js","require":"./dist/index.cjs"}},"gitHead":"1cc11871d3b55279caa96a9665e1f84443e50c93","scripts":{"build":"tsup src/index.ts --format esm,cjs --dts --sourcemap --clean","typecheck":"tsc --noEmit","prepublishOnly":"npm run build"},"_npmUser":{"name":"jakubkubo","email":"jakubja@gmail.com"},"repository":{"url":"git+https://github.com/Jakubantalik/Libraries.git","type":"git","directory":"packages/liquid-gooey"},"_npmVersion":"10.8.2","description":"Liquid UI effects for React: Morph (gooey merge, jelly shape change, contact dissolve), Move (liquid-rubber trails), Melt (two images running molten into each other) and Bend (bodies that bow with velocity). SVG-filter silhouette layer + crisp content lay","directories":{},"sideEffects":false,"_nodeVersion":"20.20.2","_hasShrinkwrap":false,"devDependencies":{"tsup":"^8.1.0","typescript":"^5.5.3","@types/react":"^18.3.3","@types/react-dom":"^18.3.0"},"peerDependencies":{"react":">=18","react-dom":">=18"},"_npmOperationalInternal":{"tmp":"tmp/liquid-gooey_0.2.0_1787844302707_0.72087618987778","host":"s3://npm-registry-packages-npm-production"}},"0.2.1":{"name":"liquid-gooey","version":"0.2.1","keywords":["react","gooey","metaball","liquid","svg-filter","animation","spring"],"author":{"name":"Jakub Antalik"},"license":"MIT","_id":"liquid-gooey@0.2.1","maintainers":[{"name":"jakubkubo","email":"jakubja@gmail.com"}],"homepage":"https://gooey.jakubantalik.com","bugs":{"url":"https://github.com/Jakubantalik/Libraries/issues"},"dist":{"shasum":"201c64f0d49963797532a2a65f2d8e0022d5753f","tarball":"https://registry.npmjs.org/liquid-gooey/-/liquid-gooey-0.2.1.tgz","fileCount":9,"integrity":"sha512-BRb0Rscie4JCHFmk4bkWxM+p03c34sidLgNE8XFJGRGEyWM/Wf0FYztJH3CfMWwOVajd4dVurAFe+BTSj8Eeeg==","signatures":[{"sig":"MEUCIBYSTCXkrF9tqC98wY9BYv9NVRrhS4rD8YDI4LFxoHHBAiEAuamY3Y8xrLMkpMx2Bb45UmgJgTSAxtuw6+bs0NzylJI=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"},{"sig":"MEQCIDwfk/UdXhkr5dE8cFI0hn//dDTZfBswriLvE7D3+t3dAiAolml0gNFJcb2OwTYt4bYpIb7y8/t5X7K2Yy2lvl0tzw==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":741873},"main":"./dist/index.cjs","type":"module","types":"./dist/index.d.ts","module":"./dist/index.js","exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.js","require":"./dist/index.cjs"}},"gitHead":"37835a94a54de606ebe6e3a5a1f8d30ddf4303b0","scripts":{"build":"tsup src/index.ts --format esm,cjs --dts --sourcemap --clean","typecheck":"tsc --noEmit","prepublishOnly":"npm run build"},"_npmUser":{"name":"jakubkubo","email":"jakubja@gmail.com"},"repository":{"url":"git+https://github.com/Jakubantalik/Libraries.git","type":"git","directory":"packages/liquid-gooey"},"_npmVersion":"10.8.2","description":"Liquid UI effects for React: Morph (gooey merge, jelly shape change, contact dissolve), Move (liquid-rubber trails), Melt (two images running molten into each other) and Bend (bodies that bow with velocity). SVG-filter silhouette layer + crisp content lay","directories":{},"sideEffects":false,"_nodeVersion":"20.20.2","_hasShrinkwrap":false,"devDependencies":{"tsup":"^8.1.0","typescript":"^5.5.3","@types/react":"^18.3.3","@types/react-dom":"^18.3.0"},"peerDependencies":{"react":">=18","react-dom":">=18"},"_npmOperationalInternal":{"tmp":"tmp/liquid-gooey_0.2.1_1787851598703_0.9942108421291893","host":"s3://npm-registry-packages-npm-production"}},"0.2.2":{"_id":"liquid-gooey@0.2.2","bugs":{"url":"https://github.com/Jakubantalik/Libraries.dev/issues"},"dist":{"shasum":"ccf5347db03a85ed203073968d5ecf265d7d1f5d","tarball":"https://registry.npmjs.org/liquid-gooey/-/liquid-gooey-0.2.2.tgz","fileCount":9,"integrity":"sha512-UnnNSYdZoNHXowmHKo2pOF6suI1+pLMKf7qBMj1wT6wG3u0gqXP7qiLVMpCjJM2ETkr/GqF8n4fcuIgWb1fHQQ==","signatures":[{"sig":"MEQCIDsvkjbP5BtCRmpPvGIu63x0zaIH9Wb2De1YhORiEhKvAiBoHMGXFXJk32K+c6CDo2O4CId8NkynhlZMzdm92iWV+Q==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"},{"keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U","sig":"MEUCIQCvvR0NYmwP9EueXRig32OlRxeC0+U0EBl6tjHr0oys8wIgSYGUuP/SOw6hdbDGQ6V71TDi2TjNEuyf8kAJkcMIgMU="}],"unpackedSize":745911},"main":"./dist/index.cjs","name":"liquid-gooey","type":"module","types":"./dist/index.d.ts","author":{"name":"Jakub Antalik"},"module":"./dist/index.js","exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.js","require":"./dist/index.cjs"}},"gitHead":"b7c588f1cfe3497d1d8a2fd8a6950351f0330285","license":"MIT","scripts":{"build":"tsup src/index.ts --format esm,cjs --dts --sourcemap --clean","typecheck":"tsc --noEmit","prepublishOnly":"npm run build"},"version":"0.2.2","_npmUser":{"name":"jakubkubo","email":"jakubja@gmail.com"},"homepage":"https://libraries.dev/gooey","keywords":["react","gooey","metaball","liquid","svg-filter","animation","spring"],"repository":{"url":"git+https://github.com/Jakubantalik/Libraries.dev.git","type":"git","directory":"packages/liquid-gooey"},"_npmVersion":"10.8.2","description":"Liquid UI effects for React: Morph (gooey merge, jelly shape change, contact dissolve), Move (liquid-rubber trails), Melt (two images running molten into each other) and Bend (bodies that bow with velocity). SVG-filter silhouette layer + crisp content lay","directories":{},"maintainers":[{"name":"jakubkubo","email":"jakubja@gmail.com"}],"sideEffects":false,"_nodeVersion":"20.20.2","_hasShrinkwrap":false,"devDependencies":{"tsup":"^8.1.0","typescript":"^5.5.3","@types/react":"^18.3.3","@types/react-dom":"^18.3.0"},"peerDependencies":{"react":">=18","react-dom":">=18"},"_npmOperationalInternal":{"host":"s3://npm-registry-packages-npm-production","tmp":"tmp/liquid-gooey_0.2.2_1790064642386_0.5626526102120668"}}},"time":{"created":"2026-08-11T13:06:18.949Z","modified":"2026-09-22T08:10:42.662Z","0.1.0":"2026-08-11T13:06:19.522Z","0.2.0":"2026-08-27T15:25:02.855Z","0.2.1":"2026-08-27T17:26:38.810Z","0.2.2":"2026-09-22T08:10:42.490Z"},"bugs":{"url":"https://github.com/Jakubantalik/Libraries.dev/issues"},"author":{"name":"Jakub Antalik"},"license":"MIT","homepage":"https://libraries.dev/gooey","keywords":["react","gooey","metaball","liquid","svg-filter","animation","spring"],"repository":{"url":"git+https://github.com/Jakubantalik/Libraries.dev.git","type":"git","directory":"packages/liquid-gooey"},"description":"Liquid UI effects for React: Morph (gooey merge, jelly shape change, contact dissolve), Move (liquid-rubber trails), Melt (two images running molten into each other) and Bend (bodies that bow with velocity). SVG-filter silhouette layer + crisp content lay","maintainers":[{"name":"jakubkubo","email":"jakubja@gmail.com"}],"readme":"# liquid-gooey\n\nLiquid effects for React UI. Two effects and one modifier cover the whole family:\n\n- **Morph** — touching pieces merge gooily and change shape like jelly. Menus, avatar groups, morphing panels.\n- **Move** — the surface trails a moving element as liquid rubber with a droplet tail. Sliders, tab indicators, dragged things.\n\nPlus **`dissolve`**, an orthogonal modifier: your imagery melts into whatever it touches. It isn't a third effect — the effects describe how the *surface moves*, dissolve describes what your *content* does where two surfaces meet.\n\nCross-browser (Safari included), crisp text/icons/images at all times, real shadows on the merged liquid, zero idle cost.\n\n## Why\n\nThe usual gooey effect runs blur + alpha-contrast over your actual UI. That one decision costs you everything else: text goes soft, images smear, shadows become impossible (the contrast step eats them), and Safari renders it wrong. So the effect stays confined to decorative colored circles.\n\nliquid-gooey splits it in two — a silhouette layer carries the goo and the shadow, your real DOM rides crisp on top. Same liquid, none of the tax.\n\n- **Real shadows.** Parsed from `box-shadow` syntax and rebuilt on the *merged* silhouette, so one consistent shadow hugs the liquid through every merge, split and bridge — no handoff, nothing to flash.\n- **Crisp everything.** Text, icons and photos stay pixel-sharp because they are never filtered.\n- **Images that actually melt.** Opt-in dissolve warps imagery at the contact point with SVG displacement — two materials mixing, not a blur.\n- **Safari included.** Filters run on SVG content, never CSS `url()` on HTML — that's the specific thing WebKit gets wrong.\n- **It's real UI, not decoration.** The content layer is live DOM: focus rings, hit targets, ARIA and handlers all intact.\n- **Zero idle cost.** Component-driven springs compile to GPU-composited CSS `linear()` easings; the measurement loop sleeps completely when nothing moves.\n- **Two effects, not fifty knobs.** Morph and Move take 3–4 normalized knobs each, plus a `dissolve` modifier — with the full physics underneath when you want it.\n\n```bash\nnpm install liquid-gooey\n```\n\n```tsx\nimport { Liquid } from 'liquid-gooey'\n\n<Liquid blur={6} contrast={18} fill=\"#fff\" shadow=\"0 2px 6px rgba(0,0,0,.08)\">\n  {/* MORPH (default): give items x/y and the library animates element and\n      liquid in perfect sync — a plus-menu that splits like droplets */}\n  <Liquid.Item x={open ? -54 : 0} y={open ? -34 : 0} transition=\"bouncy\">\n    <button className=\"round-btn\">…</button>\n  </Liquid.Item>\n  <Liquid.Item x={0} y={open ? -64 : 0} transition=\"bouncy\" delay={40}>\n    <button className=\"round-btn\">…</button>\n  </Liquid.Item>\n</Liquid>\n```\n\nRun the playground: `npm install && npm run dev` — add `?pro` to the URL for the full raw-physics control panels.\n\n## The four effects\n\n### Morph (default)\n\nMerging is automatic: blobs share the group's goo filter, so touching pieces bridge and merge. One optional power:\n\n```tsx\n// Shape change: the liquid mass flows toward the new centre first, then size\n// and corner radius adapt — content cross-blurs inside the moving liquid.\n<Liquid.Item morph={{ shape: true }}>\n  <div className={open ? 'panel-open' : 'panel-closed'}>…</div>\n</Liquid.Item>\n```\n\n| Knob | Default | Meaning |\n| --- | --- | --- |\n| `shape` | `false` | Liquid shape-change physics (springs + droplet travel + corner timeline). |\n| `speed` | `1` | Tempo multiplier for the shape physics (2 = twice as fast, same character). |\n| `bounce` | `0.5` | `0..1` — how much the physics overshoot and wobble. `0` = calm, critically damped. |\n| `contentBlur` | `7` | Max px **your content** cross-blurs by while the liquid is in motion, sharpening as it settles. `0` disables. |\n\nMorph acts on both halves of the effect: the *surface* (merge, springs, corner timeline) and your *content* (`contentBlur` while moving).\n\n### Dissolve (a modifier, not an effect)\n\n```tsx\n<Liquid.Item dissolve />                      // the tuned look\n<Liquid.Item dissolve={0.5} />                // scaled intensity\n<Liquid.Item dissolve={{ mix: 0.7, active: dragging }} />   // full DissolveOptions\n```\n\nThe item's imagery melts into a touching neighbour at the contact point — a liquid warp with two-liquid mixing, not a blur. Strength ramps with proximity, tracking where the goo bridge actually forms, so it needs no gating of its own; wire `active` to your drag state if you want it to clear on release. Text is never melted, only imagery.\n\nToday it applies to morph items. Under `effect=\"move\"` it is ignored with a dev warning: the melt is drawn from the element's measured rect while move's liquid deliberately lags on a spring, so the two would visibly disagree.\n\n### Move\n\n```tsx\n<Liquid.Item effect=\"move\" move={{ springiness: 0.5, trail: 0.575 }}>\n  <div className=\"thumb\" style={{ transform: `translateX(${x}px)` }} />\n</Liquid.Item>\n```\n\nYou move the element however you like (CSS, pointer events, Framer Motion) — the liquid trails it.\n\n| Knob | Default | Meaning |\n| --- | --- | --- |\n| `springiness` | `0.5` | `0..1` — how tightly the liquid chases. 0 = heavy syrup, 1 = near-instant. |\n| `wobble` | `0.5` | `0..1` — overshoot on arrival. |\n| `stretch` | `0.36` | `0..1` — velocity stretch of the drop. |\n| `trail` | `0.575` | `0..1` — trailing droplet size. 0 disables the tail. |\n\nAll defaults reproduce the library's tuned look exactly — knobs at rest change nothing.\n\n### Melt\n\nTwo images running molten into each other: the goo averages their colours where\nthey touch, each crisp face dissolves back at the seam, and a marbling pass folds\nthe two palettes into streaks inside the contact area.\n\n```tsx\n<Liquid>\n  <Liquid.Item effect=\"melt\">\n    <div className=\"card\"><img src={a} /></div>\n  </Liquid.Item>\n  <Liquid.Item effect=\"melt\">\n    <div className=\"card\"><img src={b} /></div>\n  </Liquid.Item>\n</Liquid>\n```\n\nMove the elements however you like — the melt follows their rendered rects. The\nsource is read from the first `<img>` inside the item, or passed as\n`melt={{ src }}`. Your element stays interactive (drag handlers, focus) but is\npainted by the melt layer, so style its size and radius as usual.\n\nPairwise by design: the first two melt items in a group form the pair, because\nthe seam maths is two-body.\n\n| Knob | Default | Meaning |\n| --- | --- | --- |\n| `blur` | `7` | Goo sigma — how far the bodies reach, and how wide the colour averaging runs. |\n| `contrast` | `40` | Sharpness of the liquid boundary. |\n| `reach` | `0.8` | How far each crisp face dissolves back before the neighbour. |\n| `fade` | `17` | Softness of that dissolve. |\n| `warp` | `0` | Turbulence displacement of the molten layer (px). |\n| `mix` | `1` | `0..1` — marbling strength in the touch area. |\n| `mixBlur` | `8` | Blur of the marble pass's source colours: low keeps image detail, high folds pre-averaged soup. |\n| `gravity` | `1.9` | How deep the marble zone reaches into each card. |\n| `waviness` | `12` | Wavelength of the warp noise: low = long lazy rolls, high = fine ripples. |\n\n### Bend\n\nThe body deforms with velocity, like a soft bar pulled through liquid: dragging\nvertically arcs the long edges (the middle leads, the ends lag), dragging\nsideways reshapes the rounded caps (the leading one blunts, the trailing one\nstretches). The surface stays glued to its content — there is no lag and no\ntail, so text and icons never slide off their own card.\n\n```tsx\n<Liquid.Item effect=\"bend\" bend={{ vertical: 0.6, horizontal: 0.35 }}>\n  <div className=\"card\" style={{ transform: `translate(${x}px, ${y}px)` }}>…</div>\n</Liquid.Item>\n```\n\n| Knob | Default | Meaning |\n| --- | --- | --- |\n| `vertical` | `0.6` | `0..1` — bow strength of the long edges. |\n| `horizontal` | `0.35` | `0..1` — cap deformation. |\n\nThe live bend is published on the item as CSS variables — `--lg-bend-x` /\n`--lg-bend-y` (px) and `--lg-bend-xn` / `--lg-bend-yn` (unitless, for `deg`\nmaths) — so the content can lean, rotate or shear along with the silhouette:\n\n```css\n.card > * {\n  transform: translateY(calc(var(--lg-bend-y, 0px) * 2))\n             rotate(calc(var(--lg-bend-yn, 0) * 1deg));\n}\n```\n\n## `<Liquid>` (the group)\n\nRenders a `position: relative` div; the liquid silhouette svg sits behind all children.\n\n| Prop | Default | Description |\n| --- | --- | --- |\n| `blur` | `6` | Goo blur sigma (px). Larger = pieces bridge from farther away. **Bridging is a ratio of blur to gap** — roughly, neighbours merge once `blur` ≳ the gap between them. Items 8px apart barely bridge at `blur={5}` and merge cleanly at `blur={12}`. If pieces that should merge look separate, raise `blur` (or close the gap) before suspecting anything else. |\n| `contrast` | `18` | Alpha-contrast slope. Larger = sharper liquid edge. |\n| `fill` | `'#fff'` | Liquid surface color. Any CSS color; `var(--surface)` works (theming). |\n| `shadow` | — | `box-shadow` syntax, multi-layer supported. Rendered on the **merged** silhouette, so one consistent shadow hugs the liquid through every merge and split. `inset` layers paint INSIDE the liquid edge — inner rings and top highlights follow the merged goo too. |\n| `filterPadding` | `24` | Extra filter-region slack (px) if blobs travel outside the group's box. |\n| `waviness` | `0` | Max px the liquid boundary undulates — the silhouette and its shadows run through a gentle noise displacement, so edges read as fluid rather than geometric. |\n| `wavinessFreq` | `0.018` | Noise frequency of that undulation; lower = longer, lazier waves. |\n\nPlus all standard `div` props. **Size the group to contain the full travel of its items** (like a menu reserving its open footprint).\n\n## `<Liquid.Item>`\n\n| Prop | Description |\n| --- | --- |\n| `effect` | `'morph'` (default), `'move'`, `'melt'` or `'bend'`. |\n| `morph` / `move` / `melt` / `bend` | The knobs above, plus `advanced` (below). |\n| `dissolve` | `true`, `0..1`, or raw `DissolveOptions` — melts imagery where surfaces meet. Orthogonal to `effect`. |\n| `x` `y` `scale` `transition` `delay` | Component-driven position: the library animates element + liquid in one commit — pixel-perfect sync. `transition` is `'snappy' \\| 'smooth' \\| 'bouncy'`, `{ stiffness, damping, mass }` or `{ duration, ease }`. |\n| `observe` | Plain-merge items animated by *your* code: the liquid follows the child's rendered rect. Implied by `morph.shape`, `dissolve` and `effect=\"move\"`. |\n| `radius` | Override the measured border-radius (`number` or `[tl, tr, br, bl]`). |\n\nBorder-radius is measured from computed style; percentage radii, circles and pills just work.\n\n## Advanced (the pro escape hatch)\n\nEvery raw engine value stays reachable — the slim knobs map onto them, and `advanced` merges over the mapping:\n\n```tsx\n<Liquid.Item\n  morph={{\n    shape: true,\n    advanced: {\n      evolve: { massStiffness: 320, cornerDuration: 820, roundness: 1 /* EvolveOptions */ },\n      blobInset: 2,   // shrink the blob so an opaque photo covers its own liquid\n      bridgeGrow: 8,  // liquid coat that swells out and necks into a neighbour\n    },\n  }}\n  // dissolve takes its raw options directly — no `advanced` detour\n  dissolve={{ warp: 26, mix: 0.7, gravity: 60, active: dragging /* DissolveOptions */ }}\n/>\n\n<Liquid.Item effect=\"move\" move={{ advanced: { stiffness: 380, damping: 18 /* MoveOptions */ } }} />\n```\n\nExported for typing and defaults: `EvolveOptions` / `EVOLVE_DEFAULTS`, `MoveOptions` / `MOVE_DEFAULTS`, `DissolveOptions`, `Transition`, `presets`. Highlights:\n\n- **EvolveOptions** — `massStiffness/Damping`, `sizeStiffness/Damping`, `radiusStiffness/Damping`, `contentBlur` (cross-blur px), `roundness` (0–1 droplet strength), `anticipation`/`travel` (ms the droplet lead ramps in / px it reaches), corner timeline `cornerDuration`/`cornerDelay`/`cornerEase`.\n- **DissolveOptions** — `blur`, `warp`, `zone`, `range`, `mix` (two-liquid erosion), `gravity`/`taper` (pointy directional flow), `warpFreq`, `flowSpeed` (churn), `warpStyle`, `detail`, `active`/`releaseMs` (wire `active` to your drag; release completes in exactly `releaseMs`).\n- **MoveOptions** — `stiffness`, `damping`, `stretch`, `tail`.\n\n## How it works (and why it's fast)\n\nYou cannot run a goo filter over real UI pixels — it destroys text and images, and WebKit's CSS `url()` filters on HTML are broken anyway. So the library uses two layers with one source of truth:\n\n- **Silhouette layer (below):** an SVG holding one plain blob per item, mirroring each item's geometry. The goo filter and the shadow chain run here. Filters on *SVG content* render identically in Chrome, Firefox and Safari.\n- **Content layer (above):** your real, interactive, unfiltered elements — crisp at all times. Give them transparent backgrounds; the liquid below is their surface.\n\nPerformance:\n\n- Component-driven motion compiles springs to CSS `linear()` easings (cached) — GPU-composited transitions, no per-frame JS.\n- Observed items share one per-group rAF loop that **sleeps entirely** (zero idle cost) after ~0.5s of stillness and wakes instantly via MutationObserver / transition events / ResizeObserver / pointer events.\n- The dissolve overlay renders only near contact and sleeps with the engine.\n\nCaveats: the dissolve warps a snapshot of each image's `src` (rebuilt on resize), and writes `mask-image` onto `<img>` elements during contact — don't combine with your own masks there. `morph.shape` writes `filter: blur()` onto the element mid-morph — don't combine with your own `filter` there. Rotation isn't mirrored (v1).\n\n## Notes\n\n- **Accessibility**: the content layer is real DOM — focus rings, hit targets and ARIA are never filtered.\n- **Reduced motion**: component-driven transitions collapse to instant snaps under `prefers-reduced-motion`.\n- **Theming**: pass `fill=\"var(--surface)\"` and let CSS variables switch light/dark.\n- **Item backgrounds** should be transparent — the blob is the surface. An opaque child (a full-bleed image in a circle) covers its own blob, which is exactly right for image chips.\n\n## Publishing\n\n```bash\nnpm run typecheck && npm run build\nnpm publish        # from a logged-in npm account\n```\n\n`dist/` ships ESM + CJS + types; `sideEffects: false`; React ≥18 peer dependency.\n\n## Credits\n\nFilter architecture distilled from the PRO7 \"Gooey plus menu\" prototype; API philosophy inspired by [Sileo](https://sileo.aaryan.design/).\n\nMIT\n","readmeFilename":"README.md"}