ranui
Version:
A framework-agnostic Web Components UI library built on native custom elements, with TypeScript types, light/dark theming, SSR and PWA support.
106 lines (105 loc) • 4.88 kB
TypeScript
import { RanElement } from '../../utils';
/**
* `r-glass` — a liquid / frosted glass surface.
*
* Frosts and refracts whatever is behind it: `backdrop-filter` blur + saturate
* for the frost, an SVG `feDisplacementMap` (strength = `displace`) for the
* liquid light-bending, plus a specular rim/highlight. All visual knobs are
* exposed as attributes and `--ran-glass-*` tokens; content goes in the default
* slot. Parts: `glass` (the pane), `specular` (the highlight layer).
*
* Backdrop note: this samples the DOM behind the host — the portable technique.
* A full WebGL/WebGPU shader path that rasterizes the *backdrop itself* into a
* texture would look more "liquid" and work identically across browsers, but
* costs the backdrop's interactivity/accessibility (buttons, selectable text,
* live video behind the glass all become a flat pixel buffer) and a much
* heavier bundle — deliberately not pursued here.
*
* `rim` is the middle ground: an opt-in WebGL layer (see `rim.ts`) that adds a
* more physically-lit specular edge + chromatic fringe, computed purely from
* the panel's own shape (never the backdrop), so it costs none of that.
*/
export declare class Glass extends RanElement {
_shadowDom: ShadowRoot;
private _glass;
/** The specular layer the rim renderer mounts into. */
private _specular;
private _turb;
private _disp;
private _uid;
private _events;
private _tabIndexOwnedByComponent;
private _rimRenderer;
static get observedAttributes(): string[];
constructor();
/** Backdrop saturation, as a percentage number (e.g. `180`). */
get saturate(): string;
set saturate(v: string);
/** Liquid refraction strength — the SVG displacement scale. `0` is a flat pane. */
get displace(): string;
set displace(v: string);
/** Turbulence base frequency — smaller = larger, smoother liquid ripples. */
get frequency(): string;
set frequency(v: string);
/** Corner radius, in px. */
get radius(): string;
set radius(v: string);
/** Glass fill tint (any CSS background value). */
get tint(): string;
set tint(v: string);
/** Animated specular sweep across the surface. */
get sheen(): boolean;
set sheen(v: boolean);
/**
* Hover lift + press-scale feedback, for clickable glass. Also makes the host
* a keyboard-operable button: `role="button"`, a tab stop (unless the consumer
* already set one), and Enter/Space dispatch a click — see `_syncInteractive`/
* `_onKeydown`.
*/
get interactive(): boolean;
set interactive(v: boolean);
/**
* Opt-in GPU specular rim + chromatic edge, lit from a fixed top-left light —
* shape-only, never samples the backdrop (see the class doc for why that's the
* point). Renders on WebGL first, always; transparently upgrades to WebGPU in
* the background if available (same pixel output, not a performance change —
* see `rim-webgpu.ts`). Silently falls back to the plain CSS specular gradient
* when neither GPU API is available (old browser, disabled, SSR). See `rim.ts`.
*/
get rim(): boolean;
set rim(v: boolean);
/** Inject the per-instance SVG displacement filter (client only, once). */
private _ensureFilter;
/**
* Lazily create the rim renderer — only while `rim` is set, so a page that
* never uses it never spends one of the browser's limited WebGL/WebGPU
* context slots. `createRimRenderer` owns its own canvas(es) and resize
* tracking (see `rim.ts`) — this just mounts it into the specular layer and
* keeps it alive across disconnect/reconnect, same as the SVG displacement
* filter above; only `_teardownRim` frees it, when `rim` is explicitly
* turned back off.
*/
private _ensureRim;
private _teardownRim;
private _apply;
/** Set a host custom property, appending a unit only when the value is bare-numeric. */
private _setVar;
/**
* `interactive` makes the whole panel a click target (see the `sheen`/hover-lift
* CSS — "for clickable glass"), so it needs the same keyboard activation a real
* `<button>` gets for free: Enter/Space act like a click. Mirrors r-button's and
* r-colorpicker's swatch keydown handler.
*/
private _onKeydown;
/**
* role="button" + a tab stop only while `interactive` — a purely decorative
* glass panel must stay out of the tab order and off the accessibility tree;
* without this a keyboard/screen-reader user had no way to tell (or reach)
* that a glass panel was clickable at all.
*/
private _syncInteractive;
connectedCallback(): void;
disconnectedCallback(): void;
attributeChangedCallback(name: string, oldValue: string | null, newValue: string | null): void;
}
export default Glass;