import * as react from 'react'; import { HTMLAttributes, ReactNode } from 'react'; /** Options accepted by the engine and the `` component. */ interface LiquidGlassOptions { /** Lens width in px. */ width: number; /** Lens height in px. */ height: number; /** Corner radius in px, or `"auto"` for a fully rounded pill/circle. */ radius: number | "auto"; /** * Refraction strength as a fraction of the container size (0–0.25 is a * sensible range). Cheap to change: does not regenerate the map. */ strength: number; /** Chromatic aberration along the lens edge, 0–1. */ chromaticAberration: number; /** Gaussian blur of the refracted content in px. */ blur: number; /** Width of the refracting edge band in px. Larger = thicker glass rim. */ depth: number; /** * Lens profile, 0–1. At 0 displacement ramps linearly from the center; * at 1 the lens is a full spherical dome. */ curvature: number; /** * How much displacement near an edge stays perpendicular to it, 0–1. * 1 splays the refraction outwards at the corners, 0 keeps it radial. */ splay: number; /** Inner specular glow strength, 0–1. */ glow: number; /** Fraction of the lens the glow spreads across, 0–1. */ glowSpread: number; /** Falloff exponent of the glow. */ glowExponent: number; /** Bright rim along the lens edge, 0–1. */ edgeHighlight: number; /** Width of the edge highlight band in px. */ edgeWidth: number; /** Falloff exponent of the edge highlight. */ edgeExponent: number; /** Master intensity of the baked specular pass (glow + edge), 0–2. */ specular: number; /** Direction of the specular light in degrees. */ specularAngle: number; /** Resolution of the generated displacement map (power of two). */ quality: number; } declare const DEFAULT_OPTIONS: LiquidGlassOptions; /** Parameters of the raw displacement-map computation, all in lens space. */ interface DisplacementMapParams { /** Output bitmap size (square, even). */ size: number; halfWidth: number; halfHeight: number; radius: number; depth: number; /** Dome depth in px; 0 for a linear profile. */ domeDepth: number; splay: number; glow: number; glowSpread: number; glowExponent: number; edgeHighlight: number; edgeWidth: number; edgeExponent: number; specularAngle: number; } /** DOM elements the engine drives. */ interface LiquidGlassHost { /** Element the lens lives in; overlays are positioned relative to it. */ container: HTMLElement; /** * Wrapper around the refracted content; receives `style.filter`. The SVG * filter's coordinate space belongs to this element, so all lens math is * measured against it. */ filtered: HTMLElement; /** Empty element the engine renders the `` filter into. */ defsHost: HTMLElement; /** Optional element positioned over the lens (shadow / rim chrome). */ shadow?: HTMLElement | null; } /** * Imperative core of liquid-glass-web-react. Owns the SVG filter, the displacement map * and all per-frame attribute updates. Framework-agnostic by design; the * React component is a thin wrapper around this class. * * Two update paths, mirroring how the effect stays cheap to animate: * - `setPosition` / fast options only move the filter's lens subregion and * never touch the map. * - Shape/surface options regenerate the map, throttled to one per frame. */ declare class LiquidGlassEngine { private host; private options; private filterEl; private feImageEl; private lensRegionEls; private dispEls; private blurEl; private specularEl; private x; private y; private mapUrl; private mapCanvas; private readonly id; private version; private regenQueued; private rafId; private resizeObserver; private destroyed; private warnedFootprint; /** Called whenever a new displacement map has been generated. */ onMap: ((url: string) => void) | null; constructor(host: LiquidGlassHost, options?: Partial); /** Lens center as fractions (0–1) of the glass surface (filtered box). */ setPosition(x: number, y: number): void; getPosition(): { x: number; y: number; }; /** Latest generated displacement map as a PNG data URL. */ getMapUrl(): string; /** Merge new options; regenerates the map only when the shape changed. */ setOptions(partial: Partial): void; getOptions(): LiquidGlassOptions; /** Re-measure and re-apply everything (e.g. after layout changes). */ refresh(): void; destroy(): void; private get halfWidth(); private get halfHeight(); private get cornerRadius(); /** * Builds the filter primitive chain: * * neutral flood ─ feImage(map at lens) ─▶ map * source ─ feGaussianBlur(optional) ─▶ blurred * 3 × feDisplacementMap at offset scales, one per RGB channel, * recombined additively ─▶ chromatic refraction * map blue channel ─▶ specular highlight, composited over * lens punched out of source, refraction composited back in * * Everything tagged `data-lens` is restricted to the lens subregion, so * content outside the lens is the browser's original render and the * filter's cost scales with the lens, not the container. */ private buildFilter; private scheduleRegenerate; private regenerate; /** * Fast path: repositions the lens subregion, updates scales/blur, bumps * the filter ID. Safari caches filter output by ID and keeps serving stale * results otherwise, so every update assigns a fresh one. */ private update; } interface LiquidGlassProps extends Partial, Omit, "children"> { /** Content the lens refracts. Stays live: selectable, clickable, scrollable. */ children: ReactNode; /** Lens center as a fraction of the container width, 0–1. Default 0.5. */ x?: number; /** Lens center as a fraction of the container height, 0–1. Default 0.5. */ y?: number; /** Let the user drag the lens around. */ draggable?: boolean; /** * Drop shadow / rim around the lens. `true` for the default, a string for * a custom `box-shadow`, `false` for none. Default `true`. */ shadow?: boolean | string; /** Fires while the lens moves (dragging or `x`/`y` changes). */ onMove?: (x: number, y: number) => void; /** Fires with a PNG data URL whenever the displacement map regenerates. */ onMapGenerated?: (url: string) => void; } interface LiquidGlassHandle { /** Root container element. */ element: HTMLDivElement | null; /** Imperative engine, for advanced control (animation loops etc.). */ engine: LiquidGlassEngine | null; /** Move the lens without re-rendering React (cheap, per-frame safe). */ setPosition: (x: number, y: number) => void; } /** * A liquid glass lens over live DOM content. * * ```tsx * * * * ``` */ declare const LiquidGlass: react.ForwardRefExoticComponent>; /** * Computes the displacement map as raw RGBA pixels. * * Red encodes horizontal displacement and green vertical (128 = neutral). * Blue carries the baked specular mask (glow + edge highlight). Outside the * rounded-rect lens every pixel is neutral, so the filter leaves those * pixels untouched. * * The map has four-fold symmetry: only the top-left quadrant is computed and * each pixel is written into all four quadrants, negating X displacement * across the vertical axis and Y across the horizontal one. The specular * projection |x·cosθ ± y·sinθ| yields two values per quadrant pair, which is * what the sum/diff split below handles. * * Pure function (no DOM), so it is unit-testable and worker-friendly. */ declare function computeDisplacementMap(p: DisplacementMapParams): Uint8ClampedArray; /** * Renders the displacement map to a PNG data URL via a (reusable) canvas. */ declare function renderDisplacementMap(p: DisplacementMapParams, canvas?: HTMLCanvasElement): string; export { DEFAULT_OPTIONS, type DisplacementMapParams, LiquidGlass, LiquidGlassEngine, type LiquidGlassHandle, type LiquidGlassHost, type LiquidGlassOptions, type LiquidGlassProps, computeDisplacementMap, renderDisplacementMap };