import { type ReactNode } from "react"; /** One body in a particle field. Positions are unit-box (0..1) so a field is * resolution independent; the surface multiplies by the live viewport. */ export interface Particle { x: number; y: number; /** Radius in px at parallax scale 1. */ r: number; /** Per-body alpha factor, multiplied by the layer's cap. */ a: number; /** Explicit colour. Omit to take the layer's tint. */ color?: string; /** Static rotation in degrees, for sprites whose orientation reads. */ rot?: number; /** Unit direction, for sprites that elongate along their travel axis. */ dx?: number; dy?: number; /** Length in box-units at scale 1, for the streak sprite. */ len?: number; } /** The sprite a particle field draws. Renderers map these onto their own * primitives; every renderer must support all four. */ export type ParticleSprite = "disc" | "halo" | "spark" | "streak"; /** One blob in a gradient field: a soft radial falloff used to build clouds. */ export interface GradientBlob { color: string; /** Unit position inside the layer's own box. */ cx: number; cy: number; /** Radius as a fraction of the box. */ r: number; /** Core stop opacity. */ o: number; /** Gradient fade-out offset. */ end: number; } export interface ParticlesLayer { kind: "particles"; field: Particle[]; sprite: ParticleSprite; /** Parallax rate. 0 pins the layer to the backdrop; 1 travels with the flight; * above 1 rushes past in the foreground. */ depth: number; /** Stagger inside the flight cycle, 0..1, so sibling layers at the same depth * do not arrive together. */ phase: number; tint?: string; alpha: number; bloom: boolean; twinkle: boolean; } export interface GradientLayer { kind: "gradient"; blobs: GradientBlob[]; depth: number; /** Box edge in px. */ size: number; /** Unit anchor in the viewport. */ at: { x: number; y: number; }; drift: boolean; alpha: number; } export interface ShaderLayer { kind: "shader"; /** SkSL source. Only a GPU renderer consumes this; the SVG renderer draws * `fallback` instead, which is why fallback is not optional. */ source: string; uniforms: Record; depth: number; /** What a renderer without shader support draws in this layer's place. */ fallback: ReactNode; alpha: number; } export interface CustomLayer { kind: "custom"; content: ReactNode; depth: number; alpha: number; } export type Layer = ParticlesLayer | GradientLayer | ShaderLayer | CustomLayer; export interface ParticlesProps { field: Particle[]; sprite?: ParticleSprite; depth?: number; phase?: number; tint?: string; alpha?: number; bloom?: boolean; /** Scintillate the field: bodies are dealt into phase buckets that flare at * unrelated moments, and the bright ones grow a diffraction glint at the peak. * The flares are deliberately uncorrelated across the field, because a whole * field brightening at once is a global luminance change the eye adapts through * and barely registers. */ twinkle?: boolean; } export interface GradientProps { blobs: GradientBlob[]; depth?: number; size?: number; at?: { x: number; y: number; }; drift?: boolean; alpha?: number; } export interface ShaderProps { source: string; uniforms?: Record; depth?: number; fallback: ReactNode; alpha?: number; } /** A field of particles at one parallax depth. */ export declare function Particles(_props: ParticlesProps): null; export declare namespace Particles { var layerKind: "particles"; } /** A field of soft radial blobs: the cheap, universally available cloud. */ export declare function Gradient(_props: GradientProps): null; export declare namespace Gradient { var layerKind: "gradient"; } /** A GPU shader layer, with the mandatory fallback for renderers without one. */ export declare function Shader(_props: ShaderProps): null; export declare namespace Shader { var layerKind: "shader"; } export interface CustomProps { children?: ReactNode; depth?: number; alpha?: number; } /** Arbitrary application-supplied art, painted at this position in the layer * stack. This is the seam that keeps the engine general: anything the vocabulary * does not cover, the app draws itself, and it can bind to `backdropClock` to * stay in phase with the rest of the scene. */ export declare function Custom(_props: CustomProps): null; export declare namespace Custom { var layerKind: "custom"; } /** Walk `children` into layer descriptors, in declaration order (which is paint * order: first child is furthest back). Unknown children are ignored rather * than thrown on, so a scene can hold a comment or a conditional null. * * Fragments are traversed. Children.forEach flattens arrays but treats a * Fragment as a single opaque child, and a scene grouped in <>… silently * rendering nothing is a miserable thing to debug. */ export declare function readLayers(children: ReactNode): Layer[]; //# sourceMappingURL=backdrop-layers.d.ts.map