{"_id":"@avenra/liquid-glass","_rev":"3-4a832f18768805cfee273bc3bd5bb880","name":"@avenra/liquid-glass","dist-tags":{"latest":"1.2.0"},"versions":{"1.0.0":{"name":"@avenra/liquid-glass","version":"1.0.0","keywords":["liquid-glass","svg-filter","backdrop-filter","displacement-map","snells-law","refraction","spring-animation","ui-component","typescript","css","animation","glass-effect","web-component"],"author":{"name":"DevSam7t3"},"license":"MIT","_id":"@avenra/liquid-glass@1.0.0","maintainers":[{"name":"devsam7t3","email":"samirashid54222@gmail.com"}],"homepage":"https://docs.avenra.online/docs/liquid-glass/getting-started","bugs":{"url":"https://github.com/DevSam7t3/liquid-glass/issues"},"dist":{"shasum":"95c4534eee90db0e3eb7c5782d1edaa42103df95","tarball":"https://registry.npmjs.org/@avenra/liquid-glass/-/liquid-glass-1.0.0.tgz","fileCount":20,"integrity":"sha512-N+4jeL8LE14z2wWdw6jFBOD7a/9uWKfExi5jHwIc3nNTr6g9cX6mYYqSHnh1B30KsW3WHSozTFAWyLbiPL3Jpg==","signatures":[{"sig":"MEUCIEFiny0+9NyONIQJp2wz4wQGFXh39AGksvnZqYH5d8IrAiEAiVnbjvGLSS0Kx82DrAS8uc2B26qRxYgR3U8uJgZUZqY=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":611456},"main":"dist/liquid-glass.cjs.js","types":"dist/types/index.d.ts","unpkg":"dist/liquid-glass.umd.min.js","module":"dist/liquid-glass.esm.js","browser":"dist/liquid-glass.umd.js","engines":{"node":">=18.0.0"},"exports":{".":{"types":"./dist/types/index.d.ts","import":"./dist/liquid-glass.esm.js","browser":"./dist/liquid-glass.umd.js","require":"./dist/liquid-glass.cjs.js"},"./styles":"./styles/liquid-glass.css"},"gitHead":"57e7b36077699f787e3046024641a9b8a9d63bb2","scripts":{"lint":"eslint .","test":"npm run build && node ./tests/run-tests.cjs","build":"rollup -c","format":"prettier --write .","prepare":"husky","typecheck":"tsc --noEmit","build:watch":"rollup -c -w","prepublishOnly":"npm run typecheck && npm run lint && npm test"},"_npmUser":{"name":"devsam7t3","email":"samirashid54222@gmail.com"},"jsdelivr":"dist/liquid-glass.umd.min.js","repository":{"url":"git+https://github.com/DevSam7t3/liquid-glass.git","type":"git"},"_npmVersion":"10.8.2","description":"Physics-based liquid glass UI effect — Snell's law SVG displacement maps, spring animations, zero runtime dependencies.","directories":{},"lint-staged":{"*.ts":["eslint --fix","prettier --write"],"*.{js,css,md,json}":["prettier --write"]},"sideEffects":["styles/*.css"],"_nodeVersion":"20.20.2","publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"husky":"^9.1.7","tslib":"^2.8.1","eslint":"^10.4.1","rollup":"^2.79.1","prettier":"^3.8.3","@eslint/js":"^10.0.1","typescript":"^5.9.3","lint-staged":"^17.0.7","typescript-eslint":"^8.60.1","rollup-plugin-terser":"^7.0.2","eslint-config-prettier":"^10.1.8","eslint-plugin-prettier":"^5.5.6","@rollup/plugin-commonjs":"^21.0.2","@typescript-eslint/parser":"^8.60.1","rollup-plugin-typescript2":"^0.37.0","@rollup/plugin-node-resolve":"^16.0.3","@typescript-eslint/eslint-plugin":"^8.60.1"},"_npmOperationalInternal":{"tmp":"tmp/liquid-glass_1.0.0_1780639642523_0.9273680916586406","host":"s3://npm-registry-packages-npm-production"}},"1.1.0":{"name":"@avenra/liquid-glass","version":"1.1.0","keywords":["liquid-glass","svg-filter","backdrop-filter","displacement-map","snells-law","refraction","spring-animation","ui-component","typescript","css","animation","glass-effect","web-component"],"author":{"name":"DevSam7t3"},"license":"MIT","_id":"@avenra/liquid-glass@1.1.0","maintainers":[{"name":"devsam7t3","email":"samirashid54222@gmail.com"}],"homepage":"https://docs.avenra.online/docs/liquid-glass/getting-started","bugs":{"url":"https://github.com/DevSam7t3/liquid-glass/issues"},"dist":{"shasum":"7ae8e23502539158cf5e1c462f66bd8f461cb1af","tarball":"https://registry.npmjs.org/@avenra/liquid-glass/-/liquid-glass-1.1.0.tgz","fileCount":20,"integrity":"sha512-vr/WwDyFSGVpoP0JonzDNXpTudKaKXn+sV6pG+R1w4rkC0IoZJtSo1wXj53cqavY/U+qt6eYsJjPqk51hgP1Zg==","signatures":[{"sig":"MEQCIDjHs0dHxfs513bT8Jka0hMWVzdrWyHPfot4heRDFkbzAiBPCWb8wrGgnOeOiwf53E2vomrFAqL18wU5QEYyTxOJbQ==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":611495},"main":"dist/liquid-glass.cjs.js","types":"dist/types/index.d.ts","unpkg":"dist/liquid-glass.umd.min.js","module":"dist/liquid-glass.esm.js","browser":"dist/liquid-glass.umd.js","engines":{"node":">=18.0.0"},"exports":{".":{"types":"./dist/types/index.d.ts","import":"./dist/liquid-glass.esm.js","browser":"./dist/liquid-glass.umd.js","require":"./dist/liquid-glass.cjs.js"},"./styles":"./styles/liquid-glass.css"},"gitHead":"dd2aa9ea691e4c5a9c7521f45007d34fd0aa17a2","scripts":{"lint":"eslint .","test":"npm run build && node ./tests/run-tests.cjs","build":"rollup -c","format":"prettier --write .","prepare":"husky","typecheck":"tsc --noEmit","build:watch":"rollup -c -w","prepublishOnly":"npm run typecheck && npm run lint && npm test"},"_npmUser":{"name":"devsam7t3","email":"samirashid54222@gmail.com"},"jsdelivr":"dist/liquid-glass.umd.min.js","repository":{"url":"git+https://github.com/DevSam7t3/liquid-glass.git","type":"git"},"_npmVersion":"11.6.2","description":"Physics-based liquid glass UI effect — Snell's law SVG displacement maps, spring animations, zero runtime dependencies.","directories":{},"lint-staged":{"*.ts":["eslint --fix","prettier --write"],"*.{js,css,md,json}":["prettier --write"]},"sideEffects":["styles/*.css"],"_nodeVersion":"22.21.1","publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"husky":"^9.1.7","tslib":"^2.8.1","eslint":"^10.4.1","rollup":"^2.79.1","prettier":"^3.8.3","@eslint/js":"^10.0.1","typescript":"^5.9.3","lint-staged":"^17.0.7","typescript-eslint":"^8.60.1","rollup-plugin-terser":"^7.0.2","eslint-config-prettier":"^10.1.8","eslint-plugin-prettier":"^5.5.6","@rollup/plugin-commonjs":"^21.0.2","@typescript-eslint/parser":"^8.60.1","rollup-plugin-typescript2":"^0.37.0","@rollup/plugin-node-resolve":"^16.0.3","@typescript-eslint/eslint-plugin":"^8.60.1"},"_npmOperationalInternal":{"tmp":"tmp/liquid-glass_1.1.0_1780818151178_0.798722884235298","host":"s3://npm-registry-packages-npm-production"}},"1.2.0":{"name":"@avenra/liquid-glass","version":"1.2.0","description":"Physics-based liquid glass UI effect — Snell's law SVG displacement maps, spring animations, zero runtime dependencies.","main":"dist/liquid-glass.cjs.js","module":"dist/liquid-glass.esm.js","browser":"dist/liquid-glass.umd.js","types":"dist/types/index.d.ts","unpkg":"dist/liquid-glass.umd.min.js","jsdelivr":"dist/liquid-glass.umd.min.js","exports":{".":{"import":"./dist/liquid-glass.esm.js","require":"./dist/liquid-glass.cjs.js","browser":"./dist/liquid-glass.umd.js","types":"./dist/types/index.d.ts"},"./styles":"./styles/liquid-glass.css"},"sideEffects":["styles/*.css"],"scripts":{"build":"rollup -c","build:watch":"rollup -c -w","test":"npm run build && node ./tests/run-tests.cjs","typecheck":"tsc --noEmit","lint":"eslint .","format":"prettier --write .","prepublishOnly":"npm run typecheck && npm run lint && npm test","prepare":"husky"},"keywords":["liquid-glass","svg-filter","backdrop-filter","displacement-map","snells-law","refraction","spring-animation","ui-component","typescript","css","animation","glass-effect","web-component"],"author":{"name":"DevSam7t3"},"license":"MIT","repository":{"type":"git","url":"git+https://github.com/DevSam7t3/liquid-glass.git"},"homepage":"https://docs.avenra.online/docs/liquid-glass/getting-started","bugs":{"url":"https://github.com/DevSam7t3/liquid-glass/issues"},"engines":{"node":">=18.0.0"},"publishConfig":{"access":"public"},"lint-staged":{"*.ts":["eslint --fix","prettier --write"],"*.{js,css,md,json}":["prettier --write"]},"devDependencies":{"@eslint/js":"^10.0.1","@rollup/plugin-commonjs":"^21.0.2","@rollup/plugin-node-resolve":"^16.0.3","@typescript-eslint/eslint-plugin":"^8.60.1","@typescript-eslint/parser":"^8.60.1","eslint":"^10.4.1","eslint-config-prettier":"^10.1.8","eslint-plugin-prettier":"^5.5.6","husky":"^9.1.7","lint-staged":"^17.0.7","prettier":"^3.8.3","rollup":"^2.79.1","rollup-plugin-terser":"^7.0.2","rollup-plugin-typescript2":"^0.37.0","tslib":"^2.8.1","typescript":"^5.9.3","typescript-eslint":"^8.60.1"},"_id":"@avenra/liquid-glass@1.2.0","gitHead":"5d6e7a8926d2f0fa8481bb015df18be04d86f43f","_nodeVersion":"20.20.2","_npmVersion":"10.8.2","dist":{"integrity":"sha512-OdFTC0RWYag7ykspUWm1hk/B6MEUHds6+DVzGOpiMB0CuXsMsKj6+gCeJOc6VaLNfIBR3cO87laTBX/v9CiyXA==","shasum":"03f3ff14bebf5458a06603c3351e740d23575ac6","tarball":"https://registry.npmjs.org/@avenra/liquid-glass/-/liquid-glass-1.2.0.tgz","fileCount":20,"unpackedSize":1032089,"signatures":[{"keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U","sig":"MEYCIQDxVzivxgrFgSVgbnJYYoiH4oiIj7agPkIyU/6rXrDYiQIhAJM3Ygd5lIZvRyOlCzsWahikqzy9EWMMVm8qVNUWjCYn"}]},"_npmUser":{"name":"devsam7t3","email":"samirashid54222@gmail.com"},"directories":{},"maintainers":[{"name":"devsam7t3","email":"samirashid54222@gmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages-npm-production","tmp":"tmp/liquid-glass_1.2.0_1781465580682_0.937504273450295"},"_hasShrinkwrap":false}},"time":{"created":"2026-06-05T06:07:22.364Z","modified":"2026-06-14T19:33:00.974Z","1.0.0":"2026-06-05T06:07:22.653Z","1.1.0":"2026-06-07T07:42:31.320Z","1.2.0":"2026-06-14T19:33:00.839Z"},"bugs":{"url":"https://github.com/DevSam7t3/liquid-glass/issues"},"author":{"name":"DevSam7t3"},"license":"MIT","homepage":"https://docs.avenra.online/docs/liquid-glass/getting-started","keywords":["liquid-glass","svg-filter","backdrop-filter","displacement-map","snells-law","refraction","spring-animation","ui-component","typescript","css","animation","glass-effect","web-component"],"repository":{"type":"git","url":"git+https://github.com/DevSam7t3/liquid-glass.git"},"description":"Physics-based liquid glass UI effect — Snell's law SVG displacement maps, spring animations, zero runtime dependencies.","maintainers":[{"name":"devsam7t3","email":"samirashid54222@gmail.com"}],"readme":"# @avenra/liquid-glass\n\n[![CI](https://github.com/DevSam7t3/liquid-glass/actions/workflows/ci.yml/badge.svg)](https://github.com/DevSam7t3/liquid-glass/actions/workflows/ci.yml)\n[![CodeQL](https://github.com/DevSam7t3/liquid-glass/actions/workflows/codeql.yml/badge.svg)](https://github.com/DevSam7t3/liquid-glass/actions/workflows/codeql.yml)\n[![npm version](https://img.shields.io/npm/v/@avenra/liquid-glass.svg)](https://www.npmjs.com/package/@avenra/liquid-glass)\n[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)\n\nPhysics-based liquid glass UI effect for the web. Snell's law refraction baked into an SVG displacement map, specular rim light, spring animations — zero runtime dependencies.\n\n> **Browser note:** The SVG displacement effect requires `backdrop-filter: url()` which is **Chromium-only**. All other browsers receive a CSS `blur + saturate` fallback that still looks like frosted glass.\n\n---\n\n## Install\n\n```bash\nnpm install @avenra/liquid-glass\n```\n\n```html\n<!-- CDN (production) -->\n<script src=\"https://cdn.jsdelivr.net/npm/@avenra/liquid-glass/dist/liquid-glass.umd.min.js\"></script>\n<link\n  rel=\"stylesheet\"\n  href=\"https://cdn.jsdelivr.net/npm/@avenra/liquid-glass/styles/liquid-glass.css\"\n/>\n```\n\n---\n\n## Quick start\n\n### npm / bundler\n\n```ts\nimport { createLiquidButton, createLiquidSwitch, createLiquidSlider } from '@avenra/liquid-glass';\nimport '@avenra/liquid-glass/styles';\n\nconst btn = createLiquidButton('#myBtn', { label: 'Save' });\nbtn.on('click', (e: MouseEvent) => console.log('clicked'));\n\nconst sw = createLiquidSwitch('#toggle', { checked: false });\nsw.on('change', ({ checked }) => console.log('switch:', checked));\n\nconst sl = createLiquidSlider('#slider', { min: 0, max: 100, value: 50 });\nsl.on('input', ({ value }) => updateVolume(value));\nsl.on('change', ({ value }) => savePreference(value)); // fires on release\n```\n\n### CDN / script tag\n\n```html\n<script src=\"https://cdn.jsdelivr.net/npm/@avenra/liquid-glass/dist/liquid-glass.umd.min.js\"></script>\n<link\n  rel=\"stylesheet\"\n  href=\"https://cdn.jsdelivr.net/npm/@avenra/liquid-glass/styles/liquid-glass.css\"\n/>\n<button id=\"btn\"></button>\n<script>\n  const { createLiquidButton } = LiquidGlass;\n  createLiquidButton('#btn', { label: 'Click me' }).on('click', () => alert('hello'));\n</script>\n```\n\n### Zero-JS — data attributes\n\n```html\n<button data-liquid-button data-label=\"Subscribe\"></button>\n<div data-liquid-switch data-checked=\"true\"></div>\n<div data-liquid-slider data-min=\"0\" data-max=\"100\" data-value=\"50\"></div>\n<div data-liquid-glass></div>\n```\n\n```js\nimport { init } from '@avenra/liquid-glass';\nconst handles = init(); // scans document and applies everything\n```\n\n---\n\n## Theming — CSS custom properties\n\nOverride these in your stylesheet to skin every glass element without touching JS:\n\n```css\n:root {\n  --lg-tint: rgba(255, 255, 255, 0.05); /* glass body fill           */\n  --lg-border: rgba(255, 255, 255, 0.2); /* 1px edge border           */\n  --lg-shadow-out: 0 10px 30px rgba(0, 0, 0, 0.3); /* drop shadow               */\n  --lg-shadow-hi: inset 0 2px 5px rgba(255, 255, 255, 0.25); /* top highlight */\n  --lg-shadow-lo: inset 0 -2px 5px rgba(0, 0, 0, 0.15); /* bottom shade  */\n  --lg-accent: #3b82f6; /* slider fill / progress fill gradient start  */\n  --lg-accent-2: #60a5fa; /* gradient end                                */\n}\n```\n\n---\n\n## API Reference\n\n### Common options (all components inherit these)\n\n| Option             | Type                                                    | Default            | Description                                           |\n| ------------------ | ------------------------------------------------------- | ------------------ | ----------------------------------------------------- |\n| `bezelWidth`       | `number`                                                | `20`               | Refractive bezel rim width in px                      |\n| `glassThickness`   | `number`                                                | `80`               | Virtual glass depth (larger = more lateral ray drift) |\n| `refractiveIndex`  | `number`                                                | `1.5`              | Index of refraction n₂ (1.0 = no bend, 2.0 = strong)  |\n| `profile`          | `'convexSquircle' \\| 'convexCircle' \\| 'concave' \\| fn` | `'convexSquircle'` | Bezel surface shape                                   |\n| `blur`             | `number`                                                | `0.5`              | Pre-displacement Gaussian blur stdDeviation           |\n| `saturation`       | `number`                                                | `1.3`              | Post-displacement colour saturation multiplier        |\n| `specularSlope`    | `number`                                                | `0.8`              | Specular highlight intensity 0–1                      |\n| `filterMode`       | `'screen' \\| 'composite'`                               | `'screen'`         | SVG filter blend pipeline                             |\n| `width` / `height` | `number`                                                | auto               | Override element dimensions for map generation        |\n| `radius`           | `number \\| null`                                        | auto               | Corner radius override (null = read from CSS)         |\n\n### Common handle API (every factory returns this)\n\n```ts\nhandle.on(event, fn); // subscribe — returns handle (chainable)\nhandle.off(event, fn); // unsubscribe a specific listener\nhandle.once(event, fn); // subscribe once — auto-removed after first fire\nhandle.destroy(); // clean up all injected DOM and stop animations\n```\n\nAll events include a `destroy` event fired when `destroy()` is called.\n\n---\n\n### `createLiquidGlass(target, options?)`\n\nApply the glass effect to any element.\n\n```ts\nconst glass = createLiquidGlass('#myCard', {\n  bezelWidth: 24,\n  glassThickness: 120,\n  refractiveIndex: 2.0,\n});\n\nglass.on('resize', ({ width, height }) => console.log(width, height));\nglass.refresh(); // rebuild maps (auto-called on resize)\nglass.destroy();\n```\n\n| Event     | Payload                             |\n| --------- | ----------------------------------- |\n| `resize`  | `{ width: number; height: number }` |\n| `destroy` | —                                   |\n\n---\n\n### `createLiquidButton(target, options?)`\n\n```ts\nconst btn = createLiquidButton('#myBtn', { label: 'Save Changes' });\nbtn.on('click', (e: MouseEvent) => handleSave(e));\nbtn.setLabel('Saved ✓');\nbtn.destroy();\n```\n\n| Option  | Type     | Description |\n| ------- | -------- | ----------- |\n| `label` | `string` | Button text |\n\n| Event                       | Payload      |\n| --------------------------- | ------------ |\n| `click`                     | `MouseEvent` |\n| `mouseenter` / `mouseleave` | `MouseEvent` |\n| `mousedown` / `mouseup`     | `MouseEvent` |\n| `destroy`                   | —            |\n\n---\n\n### `createLiquidSwitch(target, options?)`\n\n```ts\nconst sw = createLiquidSwitch('#toggle', { checked: true });\nsw.on('change', ({ checked }) => applyTheme(checked));\nsw.checked = false; // programmatic setter\nsw.toggle();\nsw.destroy();\n```\n\n| Option    | Type      | Default |\n| --------- | --------- | ------- |\n| `checked` | `boolean` | `false` |\n\n| Event     | Payload                                  |\n| --------- | ---------------------------------------- |\n| `change`  | `{ checked: boolean; element: Element }` |\n| `destroy` | —                                        |\n\n---\n\n### `createLiquidSlider(target, options?)`\n\n```ts\nconst sl = createLiquidSlider('#slider', { min: 0, max: 100, value: 50, step: 5 });\nsl.on('input', ({ value }) => updateUI(value)); // while dragging\nsl.on('change', ({ value }) => saveToServer(value)); // on release\nsl.value = 75; // programmatic setter\nsl.destroy();\n```\n\n| Option        | Type     | Default     |\n| ------------- | -------- | ----------- |\n| `min` / `max` | `number` | `0` / `100` |\n| `value`       | `number` | `50`        |\n| `step`        | `number` | `1`         |\n\n| Event     | Payload                               |\n| --------- | ------------------------------------- |\n| `input`   | `{ value: number; element: Element }` |\n| `change`  | `{ value: number; element: Element }` |\n| `destroy` | —                                     |\n\n---\n\n### `createLiquidCursor(container, options?)`\n\nGlass orb that replaces the system cursor inside `container`. The orb grows on hover, shrinks on click.\n\n```ts\nconst cursor = createLiquidCursor('#stage', { size: 90 });\ncursor.destroy(); // restores the default cursor\n```\n\n| Option | Type     | Default |\n| ------ | -------- | ------- |\n| `size` | `number` | `90`    |\n\n---\n\n### `createLiquidInput(target, options?)`\n\nGlass-wrapped `<input>` with micro-vibration on each keystroke and scale spring on focus.\n\n```ts\nconst inp = createLiquidInput('#searchBox', {\n  placeholder: 'Search…',\n  type: 'text',\n});\ninp.on('input', ({ value }) => runSearch(value));\ninp.on('focus', () => showSuggestions());\ninp.value = 'prefilled text'; // getter/setter\ninp.focus();\ninp.destroy();\n```\n\n| Option        | Type     | Default  |\n| ------------- | -------- | -------- |\n| `placeholder` | `string` | `''`     |\n| `value`       | `string` | `''`     |\n| `type`        | `string` | `'text'` |\n\n| Event     | Payload                               |\n| --------- | ------------------------------------- |\n| `focus`   | `FocusEvent`                          |\n| `blur`    | `FocusEvent`                          |\n| `input`   | `{ value: string; element: Element }` |\n| `destroy` | —                                     |\n\n---\n\n### `createLiquidDial(target, options?)`\n\nRotary knob — pointer drag spins it continuously.\n\n```ts\nconst dial = createLiquidDial('#knob', { value: 0 });\ndial.on('change', ({ angle }) => setFilter(angle));\ndial.angle = 90; // programmatic setter (degrees)\ndial.destroy();\n```\n\n| Option  | Type               | Default |\n| ------- | ------------------ | ------- |\n| `value` | `number` (degrees) | `0`     |\n\n| Event     | Payload                               |\n| --------- | ------------------------------------- |\n| `change`  | `{ angle: number; element: Element }` |\n| `destroy` | —                                     |\n\n---\n\n### `createLiquidTooltip(target, options)`\n\nGlass pill that springs above a trigger element on hover/focus.\n\n```ts\n// Assuming #myTooltip is positioned relative to its parent:\nconst tip = createLiquidTooltip('#myTooltip', {\n  trigger: '#triggerBtn',\n  text: 'More details',\n});\ntip.on('show', () => {});\ntip.show(); // programmatic show\ntip.hide(); // programmatic hide\ntip.toggle();\ntip.setText('Updated text');\ntip.destroy();\n```\n\n| Option    | Type                | Required |\n| --------- | ------------------- | -------- |\n| `trigger` | `string \\| Element` | ✓        |\n| `text`    | `string`            | —        |\n\n| Event           | Payload |\n| --------------- | ------- |\n| `show` / `hide` | —       |\n| `destroy`       | —       |\n\n---\n\n### `createLiquidProgress(target, options?)`\n\nFluid progress bar with squish animation on value update.\n\n```ts\nconst bar = createLiquidProgress('#progressBar', { value: 0 });\nbar.on('change', ({ value }) => console.log(value + '%'));\nbar.value = 65; // triggers spring + squish\nbar.destroy();\n```\n\n| Option  | Type           | Default |\n| ------- | -------------- | ------- |\n| `value` | `number` 0–100 | `0`     |\n\n| Event     | Payload                               |\n| --------- | ------------------------------------- |\n| `change`  | `{ value: number; element: Element }` |\n| `destroy` | —                                     |\n\n---\n\n### `init(options?)`\n\nScan the DOM for `data-liquid-*` attributes and apply the matching factory automatically.\n\n```ts\nimport { init } from '@avenra/liquid-glass';\n\nconst handles = init(); // whole document\nconst handles = init({ root: '#myApp' }); // limit to subtree\n```\n\n**Supported data attributes:**\n\n| Attribute            | Options via `data-*`                                              |\n| -------------------- | ----------------------------------------------------------------- |\n| `data-liquid-button` | `data-label`                                                      |\n| `data-liquid-switch` | `data-checked`                                                    |\n| `data-liquid-slider` | `data-min`, `data-max`, `data-value`, `data-step`                 |\n| `data-liquid-glass`  | `data-bezel-width`, `data-refractive-index`, `data-profile`, etc. |\n\nReturns `AnyHandle[]` — one handle per matched element.\n\n---\n\n## TypeScript\n\nAll types are exported from the package root:\n\n```ts\nimport type {\n  LiquidGlassHandle,\n  LiquidGlassOptions,\n  LiquidGlassEventMap,\n  LiquidButtonHandle,\n  LiquidButtonOptions,\n  LiquidButtonEventMap,\n  LiquidSwitchHandle,\n  LiquidSwitchOptions,\n  LiquidSwitchEventMap,\n  LiquidSliderHandle,\n  LiquidSliderOptions,\n  LiquidSliderEventMap,\n  LiquidCursorHandle,\n  LiquidCursorOptions,\n  LiquidInputHandle,\n  LiquidInputOptions,\n  LiquidInputEventMap,\n  LiquidDialHandle,\n  LiquidDialOptions,\n  LiquidDialEventMap,\n  LiquidTooltipHandle,\n  LiquidTooltipOptions,\n  LiquidTooltipEventMap,\n  LiquidProgressHandle,\n  LiquidProgressOptions,\n  LiquidProgressEventMap,\n  AnyHandle,\n} from '@avenra/liquid-glass';\n```\n\n---\n\n## Advanced — low-level API\n\nBuild a fully custom glass component using the raw physics engine:\n\n```ts\nimport {\n  Spring,\n  PROFILES,\n  buildMaps,\n  createFilterSVG,\n  injectImages,\n  setScale,\n  nextFilterId,\n  supportsBackdropFilter,\n} from '@avenra/liquid-glass';\n\nconst { dispUrl, specUrl, maxDisplacement } = buildMaps({\n  width: 200,\n  height: 140,\n  radius: 70,\n  bezelWidth: 30,\n  glassThickness: 150,\n  refractiveIndex: 1.5,\n});\n\nconst filterId = nextFilterId('my-lens');\nconst { svg, refs } = createFilterSVG({ filterId, width: 200, height: 140 });\ninjectImages(refs, dispUrl, specUrl);\nmyElement.appendChild(svg);\n\nif (supportsBackdropFilter()) {\n  innerEl.style.backdropFilter = `url(\"#${filterId}\")`;\n}\n\n// Animation loop — spring the displacement scale\nconst spring = new Spring(maxDisplacement, 300, 20);\nspring.setTarget(maxDisplacement * 1.5);\nrequestAnimationFrame(function loop() {\n  setScale(refs, spring.update(1 / 60));\n  if (!spring.isSettled()) requestAnimationFrame(loop);\n});\n```\n\n---\n\n## Browser compatibility\n\n| Feature                                | Chrome | Edge | Firefox | Safari |\n| -------------------------------------- | ------ | ---- | ------- | ------ |\n| SVG displacement + specular refraction | ✓      | ✓    | —       | —      |\n| CSS blur/saturate fallback             | ✓      | ✓    | ✓       | ✓      |\n\n---\n\n## Build from source\n\n```bash\nnpm install\nnpm run build    # outputs dist/\nnpm test         # build + run physics unit tests\n```\n\n## License\n\nMIT\n\n---\n\n## Support\n\nNeed help? Please see our [Support Guide](SUPPORT.md).\n\n## Contributing\n\nContributions are welcome! Please read our [Contributing Guide](CONTRIBUTING.md) and [Code of Conduct](CODE_OF_CONDUCT.md) before submitting a pull request.\n\n## Security\n\nIf you discover a security vulnerability, please see our [Security Policy](SECURITY.md).\n","readmeFilename":"README.md"}