import { CanvasHTMLAttributes } from 'react';
import { CSSProperties } from 'react';
import { ForwardRefExoticComponent } from 'react';
import { RefAttributes } from 'react';
/** Face ink for a body colour: dark ink, or light ink on a dark body. */
export declare function autoInk(color: string): string;
/**
* The form of one outline from its coverage raster (N × N, 0–255, over
* design units [-PAD, 100 + PAD]): a pillow height field, its normals as
* matcap cells, and baked occlusion; outside texels near the edge borrow
* their nearest inside texel so upscaling never bleeds transparent black.
*/
export declare function bakeBotAvatarForm(cov: Uint8Array | Uint8ClampedArray, N: number, halfDepth: number): BotAvatarForm;
/** the matcap's side, in cells */
export declare const BOT_AVATAR_MATCAP_SIZE = 64;
export declare const BOT_AVATAR_OVERSCAN = 1.5;
/** The texture covers design units [-PAD, 100 + PAD]. */
export declare const BOT_AVATAR_PAD = 3;
/** the body's centre sits this fraction of the box below the canvas
centre: hops and flips need the room above, not below */
export declare const BOT_AVATAR_RISE = 0.1;
export declare const BOT_AVATAR_SPAN: number;
declare const BotAvatar: ForwardRefExoticComponent>;
export { BotAvatar }
export default BotAvatar;
/** Screen-space vectors into the cap's frame: un-roll, then the transpose
of the rig's rotation; the back cap is the front mirrored in z. */
export declare function botAvatarCapFrame(r: BotAvatarRig): BotAvatarFrame;
export declare interface BotAvatarDrawConfig {
path: Path2D;
face: BotAvatarFace;
faceX: number;
faceY: number;
faceScale: number;
color: string;
ink: string;
shading: BotAvatarShading;
/** intensities and geometry of the lighting; omitted means the stock look */
shadow?: number;
highlight?: number;
depth?: number;
/** degrees clockwise from the top, where the light comes from */
light?: number;
rim?: number;
spread?: number;
/** plastic and fabric: the profile through the depth — 1 (the default) a
cushion, thickest in the middle and rounding off to nothing at the
outline all round; toward 0 a slab with softened edges */
roundness?: number;
/** fabric: the pile's style — length, density, edge fuzz, tufts, curl */
fur?: FurStyle;
/** plastic and fabric: 0–1, how much colour the light keeps past the
palette's full saturation — highlights, sheen and rim stay coloured
rather than paling toward white */
vivid?: number;
/** fabric: where the back light comes from, degrees clockwise from the
top; by default above the toy, toward the side away from the key */
backLight?: number;
/** fabric: how far round to the front the key sits, degrees — 0 grazes
the toy from the side, 90 lights it from the camera (default 32) */
lightFront?: number;
/** fabric: the strength of the highlights along single fibres (default 0) */
shine?: number;
/** fabric: 0–1, how soft the back light is — 0 a small source caught on
single fibres, 1 a large one, an even glow (default 1) */
backSoftness?: number;
/** fabric: the smooth, satin sheen over the body's edge — the key's
sheen and the back light's band as even gradients (default 0) */
sheen?: number;
/** identifies the outline for the material caches (the type name) */
typeKey?: string;
/** no animation loop follows this draw (reduced motion, paused): build
* materials now instead of on idle time */
still?: boolean;
/** with `still`, bake fabric's pile on idle time all the same; the caller
* draws again when it lands (`takeMissed` and `onLanded` in plastic.ts),
* as the component does */
furOnIdle?: boolean;
/** thin parts (antennae) drawn behind the body with `partsDepth` of its
depth; a list draws each piece as its own solid */
parts?: Path2D | Path2D[];
partsDepth?: number;
/** the resolved surface: the whirl is white on dark, black on light */
theme?: 'dark' | 'light';
/** the device pixel ratio the context is scaled by: with it given the
context's transform is taken as that scale and never read back */
dpr?: number;
/** plastic's side slices: filled as vectors, or blitted from sprites of
the outline. `auto` (the default) blits on WebKit, where a
conic-gradient fill costs thirty times a flat one. */
sides?: 'auto' | 'vector' | 'sprite';
/** the whirl's knobs; 1 everywhere is the stock look */
whirl?: {
strength: number;
size: number;
width: number;
length: number;
tilt: number;
};
/** what the bot wears: a hat, glasses, headphones, a bow tie */
wear?: Wear;
}
/**
* What the face is made of. The eyes alone by default; `mouth` adds a
* small mouth that changes with the state.
*/
export declare type BotAvatarFace = 'eyes' | 'mouth';
export declare const botAvatarFaces: BotAvatarFace[];
export declare interface BotAvatarForm {
N: number;
/** bilinear cell in the matcap: index of the top-left cell … */
i00: Uint16Array;
/** … and the weights inside it, 0–255 */
wx: Uint8Array;
wy: Uint8Array;
/** baked occlusion × edge darkening, gamma-compensated, 0–255; 0 = not drawn */
ao: Uint8Array;
/** signed distance to the outline in design units (positive inside) and
the pillow height: kept for the fabric's fibres, which grow down the
slope of the height and out past the edge */
sd: Float32Array;
h: Float32Array;
}
export declare interface BotAvatarFrame {
L: V3;
V: V3;
H: V3;
U: V3;
W: V3;
A: V3;
B: V3;
/** down on screen, in the cap's frame: toward the floor */
D: V3;
/** toward the back light on screen, in the cap's frame */
K: V3;
}
/** Something to wear over the eyes. */
export declare type BotAvatarGlasses = 'none' | 'round' | 'square' | 'shades';
/** Something to wear on the head. */
export declare type BotAvatarHat = 'none' | 'beret' | 'beanie' | 'party' | 'crown';
/** The jump's numbers: an idle flip's and a click's. */
export declare interface BotAvatarJumpConfig {
/** how high, in body units (the body is 100 tall) */
height: number;
/** seconds in the air */
time: number;
/** how much the body stretches in the air, 0–2 */
stretch: number;
/** how much it squashes on the ground, before take-off and on landing, 0–2 */
squash: number;
/** seconds the landing squash takes, contact to recovered */
squashTime: number;
/** the landing squash's shape */
squashEase: BotAvatarSquashEase;
/** seconds the body holds its deepest squash on the ground */
groundTime: number;
/** how the weight settles through that hold */
groundEase: BotAvatarSquashEase;
/** seconds the body takes to rise from its deepest squash back to shape */
riseTime: number;
/** how it rises */
riseEase: BotAvatarSquashEase;
/** seconds a click's jump takes for its landing squash */
clickSquashTime: number;
/** whole turns in the air */
spin: number;
/** degrees of lean into it */
lean: number;
/** seconds between idle jumps, roughly (±40 %); 0 for none */
every: number;
/** when the landing squash begins: seconds before (negative) or after
touch-down; 0 is the moment of contact */
land: number;
}
export declare const botAvatarJumpDefaults: BotAvatarJumpConfig;
export declare interface BotAvatarMaterial {
shadow: number;
highlight: number;
spread: number;
rim: number;
/** 0–1: how much colour the light keeps past the palette's full
saturation (see vivify) */
vivid?: number;
/** fabric: how far round to the front the key sits, radians — 0 grazes
from the side, π/2 lights from the camera */
front?: number;
/** fabric: the strength of the light along single fibres, 1 as it comes */
shine?: number;
/** fabric: 0–1, how soft the back light is — 0 a small source caught on
single fibres, 1 a large one, an even glow reaching further in */
backSoft?: number;
/** fabric: the smooth, satin light over the body's edge — the key's
sheen and the back light's band, as even gradients rather than on
single fibres; 0 by default (matte) */
sheen?: number;
}
/** Body colour by type — the palette on its own. */
export declare const botAvatarPalette: Record;
/** Thin parts (antennae) drawn with a fraction of the body's depth. */
export declare const botAvatarParts: Partial>;
export declare interface BotAvatarPose {
/** radians; yaw > 0 turns the face to the viewer's right, pitch > 0 looks up */
yaw: number;
pitch: number;
roll: number;
/** body-box units (the 100×100 design space) */
x: number;
y: number;
sx: number;
sy: number;
/** 0 shut … 1 open, before blinks */
eyeOpen: number;
/** how far each lid is down right now, 0 … 1 */
blinkL: number;
blinkR: number;
lookX: number;
lookY: number;
/** the breathing cycle, −1 … 1 */
breath: number;
/** working only: how far the eyes have closed into a laugh, 0 … 1 */
laugh: number;
/** the cartoon whirl round a spinning body: strength 0 … 1, and where
its head is, in radians round the ring */
whirl: number;
whirlAngle: number;
/** blend weights: default, working, sleeping — they sum to 1 */
w: [number, number, number];
}
export declare interface BotAvatarPreset {
/** Display name, for labels and the default `aria-label`. */
label: string;
/** The type's own body colour. */
color: string;
/** The face the type ships with. */
face: BotAvatarFace;
/** Where the face sits, in the 100×100 body box. */
faceX: number;
faceY: number;
/** Face scale: shapes with a small middle wear a smaller face. */
faceScale: number;
/** The type's own `brightness` and `saturation`, where the props leave
them out (otherwise 1 and 1.5). */
brightness?: number;
saturation?: number;
}
/**
* The eighteen types: each body has its own colour and says where on it the
* face sits. Every type wears the eyes alone by default.
*/
export declare const botAvatarPresets: Record;
export declare interface BotAvatarProps extends Omit, 'color' | 'ref'> {
/** Body shape. Default `clover`. */
type?: BotAvatarType;
/**
* A custom body outline: SVG path data in the 100×100 body box, centred
* on (50, 50), replacing the type's own (and its antennae). The type
* still sets the face's place, the default colour and the label, so keep
* the outline solid round the face. Default: the type's outline.
*/
path?: string;
/** Face kind. Defaults to the type's own. */
face?: BotAvatarFace;
/** What the bot is doing: `default` (idle), `working` (hopping, spinning) or `sleeping`. */
state?: BotAvatarState;
/** Rendered size in px, or any CSS length. Default `64`. */
size?: number | string;
/** Body colour. Defaults to the type's palette colour. */
color?: string;
/** Face ink. Defaults to dark, or light on a dark body. */
ink?: string;
/**
* Lightness of the body colour: 1 as the palette has it, below 1 darker,
* above 1 lighter (0.5–1.5 is the useful range). Default `1`, or the
* type's own (the star's is `1.1`).
*/
brightness?: number;
/**
* Saturation of the body colour: 1 as the palette has it, below 1
* duller, above 1 more vivid, 0.5–2.5. Past 1.5, where most of the
* palette is already as saturated as a screen shows it, the colour is
* pushed along its own hue toward its most vivid shade (deepening by at
* most 15% where the screen cannot show it brighter), the shade side
* grows richer, and `plastic` and `fabric` keep
* more of it in the light — highlights, sheen, rim and fur tips stay
* coloured rather than paling toward white. Default `1.5`, or the
* type's own (the star's is `1.84`).
*/
saturation?: number;
/** Multiplier on every animation's speed. Default `1`. */
speed?: number;
/** Freeze every animation on its current frame. */
paused?: boolean;
/**
* 0–1. Offsets the blink and glance timing so a row of avatars does not
* blink in unison. Defaults to a value derived from the instance id.
*/
seed?: number;
/** How the body is lit: `fabric` (default), `plastic`, `crisp`, `smooth`
* or `flat`. `true` and `false` mean crisp and flat. */
shading?: BotAvatarShading | boolean;
/** A hat, sitting on the top of the head and turning with it: `beret`,
* `beanie`, `party` or `crown`. Default `none`. */
hat?: BotAvatarHat;
/** Glasses over the eyes: `round`, `square` or `shades`. Default `none`. */
glasses?: BotAvatarGlasses;
/** Headphones over the head, a cup on either side. Default `false`. */
headphones?: boolean;
/** A bow tie under the face. Default `false`. */
bowTie?: boolean;
/** Colour of the hat, the headphones and the bow tie. Default a soft black. */
accessoryColor?: string;
/** Strength of the shadow side, 0–2. Default `0.35` (`1.15` for `fabric`). */
shadow?: number;
/** Strength of the lit side, 0–2. Default `1.3` (`1.45` for `fabric`). */
highlight?: number;
/** Thickness of the body, 0.2–2: what shows when it turns or flips. Default `0.65`. */
depth?: number;
/**
* `plastic` and `fabric`: the body's profile through its depth, 0–1. At
* `1` (default) it is inflated like a cushion or a plush toy — thickest in
* the middle and rounding off to nothing at the outline all round, so a
* turn shows a round side; toward `0` it becomes a slab with soft edges.
*/
roundness?: number;
/** `fabric`: length of the pile, 0.3–2.5. Default `1`. */
furLength?: number;
/** `fabric`: how many fibres, 0.3–2. Default `1.6`. */
furDensity?: number;
/** `fabric`: softness of the silhouette — the haze of fine hairs standing past it, 0–1. Default `0.9`. */
furFuzz?: number;
/** `fabric`: how much the fibres gather into tufts, 0–1. Default `0.4`. */
furClumps?: number;
/** `fabric`: how wavy the fibres are, 0 (straight) – 1. Default `0.7`. */
furCurl?: number;
/**
* `fabric`: how much the pile hangs, 0–1 — combed down from a parting at
* the top, lying over the top edge and hanging off the sides and bottom,
* rather than standing out evenly all round. Default `0.9`.
*/
furGravity?: number;
/** Where the light comes from, in degrees clockwise from the top. Default `300` (`295` for `fabric`): from the upper left, like a studio key light. */
light?: number;
/** Width of the lit rim in `crisp` shading, strength of the Fresnel rim in `plastic`, of the back light in `fabric` — the bright rim it wraps round the top and sides, and the glow of the edge's hairs — 0–2. Default `0.5` (`0.6` for `fabric`). */
rim?: number;
/** `fabric`: where the back light comes from, in degrees clockwise from the top. Default: above the toy, toward the side away from `light`. */
backLight?: number;
/** `fabric`: how far round to the front the key light sits, in degrees — `0` grazes the toy from the side (dramatic), `85` lights it nearly from the camera (flat). Default `32`. */
lightFront?: number;
/** `fabric`: strength of the highlights along single fibres where the key grazes the pile, 0–2. Default `0` (off: a soft, matte pile). */
shine?: number;
/** `fabric`: the smooth, satin sheen over the body's edge — the key's sheen and the back light's band as even gradients, a material shine rather than the fur's own — 0 (matte, only the fibres shine) – 2. Default `0`. */
sheen?: number;
/** `fabric`: how soft the back light is, 0–1 — `0` a small source caught on single fibres as crisp bright hairs, `1` a large one, an even glow reaching further in from the edge and fading out gently. Default `1`. */
backSoftness?: number;
/** Reach of the soft shading in `smooth`, width of the highlight in `plastic`, how far the light wraps round in `fabric`, 0.4–2.5. Default `1.55` (`1.6` for `fabric`). */
spread?: number;
/**
* Holds the body at this orientation, in radians — `yaw` turns it to the
* viewer's right, `pitch` tips it to look up, `roll` tilts it — in the
* state's rest pose, overriding the animation's turns, hops and glances
* (and pointer play) while it is set. For turning an avatar round by
* hand, as a 3D viewer does; usually with `paused`.
*/
pose?: {
yaw?: number;
pitch?: number;
roll?: number;
};
/**
* Pointer play: the eyes and head follow a pointer that comes near, and
* a click makes the avatar hop and turn right round. Default `true`.
*/
interactive?: boolean;
/**
* The surface the avatar sits on, for touches that have to read against
* it. `auto` (default) reads an ancestor `data-theme` attribute or
* `dark` / `light` class, then `prefers-color-scheme`.
*/
theme?: 'auto' | 'dark' | 'light';
/**
* How far the head turns from side to side while idle, 0–2: `1` as the
* library has it, `0` keeps it facing forward. Default `1`.
*/
turn?: number;
/** The whirl round a spin: its strength, 0–2. Off by default (`0`); `1` turns it on. */
whirl?: number;
/** Size of the whirl's ring, 0.6–1.6. Default `1`. */
whirlSize?: number;
/** Thickness of the whirl's trail, 0.4–2. Default `1`. */
whirlWidth?: number;
/** Length of the trail round the ring, 0.4–1.6. Default `1`. */
whirlLength?: number;
/** How flat the ring is seen, 0.5–1.8 (higher is more open). Default `1`. */
whirlTilt?: number;
/** The jump (an idle flip, a click): how high, in body units — the body is 100 tall. Default `26`. */
jumpHeight?: number;
/** Seconds the jump spends in the air. Default `0.68`. */
jumpTime?: number;
/** How much the body stretches in the air, 0–2. Default `1`. */
jumpStretch?: number;
/** How much the body squashes on the ground, before take-off and on landing, 0–2. Default `1.15`. */
jumpSquash?: number;
/** Seconds the landing squash takes, from contact to recovered. Default `0.37`. */
jumpSquashTime?: number;
/**
* How the landing squash plays out: `sharp` (all at once, then eases
* off), `pulse` (a quick press that recovers without a wobble, the
* default), `soft` (eases in and out), `bouncy` (overshoots into a
* stretch and settles).
*/
jumpSquashEase?: BotAvatarSquashEase;
/** Seconds a jump holds its deepest squash on the ground before recovering. Default `0.11`. */
jumpGroundTime?: number;
/**
* How the weight settles through that hold, in the same shapes as
* `jumpSquashEase`: the body presses a little deeper and comes back to
* the held depth, `sharp` at once, `pulse` quickly, `soft` in the
* middle, `bouncy` with a wobble. Default `pulse`.
*/
jumpGroundEase?: BotAvatarSquashEase;
/** Seconds the body takes to rise from its deepest squash back to its own shape. Default `0.33`. */
jumpRiseTime?: number;
/**
* How it rises: `sharp` lets go at once and eases in to rest, `pulse`
* leaves quickly with a long settle, `soft` eases out of the squash and
* into rest, `bouncy` passes rest into a slight stretch and settles
* back. Default `pulse`.
*/
jumpRiseEase?: BotAvatarSquashEase;
/** Seconds a click's jump takes for its landing squash (an idle jump's uses `jumpSquashTime`). Default `0.24`. */
jumpClickSquashTime?: number;
/** Whole turns made in the air, 0–2. Default `1`. */
jumpSpin?: number;
/** Degrees of lean into a jump. Default `6`. */
jumpLean?: number;
/** Seconds between idle jumps, give or take 40 %; 0 for none. Default `8`. */
jumpEvery?: number;
/** When the landing squash begins: seconds before touch-down (negative, bracing for the ground) or after it. Default `0`, the moment of contact. */
jumpLand?: number;
className?: string;
style?: CSSProperties;
}
export declare interface BotAvatarRig {
/** the rig's (floored) cos/sin of yaw and pitch, as used by the slice affines */
cy: number;
sy: number;
cp: number;
sp: number;
/** cos(yaw)·cos(pitch), unfloored: the front cap faces the viewer while positive */
facing: number;
roll: number;
halfDepth: number;
cap: number;
/** unit vector toward the light on screen */
lx: number;
ly: number;
/** unit vector toward the back light on screen (fabric); from the key's
when not given */
bx?: number;
by?: number;
/** the avatar box in device pixels (CSS px × dpr) */
dev: number;
/** the context's transform for body space (a, b, c, d, e, f): the
slices set theirs from it directly rather than through save/restore */
ctm: readonly number[];
/** no animation loop will follow: build the form now rather than on idle time */
still?: boolean;
/** the profile through the depth: 1 a cushion, rounding off to nothing at
the outline all round; toward 0 a slab with softened edges */
round?: number;
}
/**
* How the body is lit. `fabric` (default): a plush faux fur — a baked
* pillow form under a studio light, fine strands combed down the form and
* gathered into lit locks, the silhouette breaking into soft tufts with a
* haze of hairs; the eyes turn into glossy beads. `plastic`: the same form
* as a real glossy material shaded per pixel — a hot spot and a sheen, a
* Fresnel rim, a window reflection, saturated shadows. `crisp`: a lit rim with
* a clean edge round the front, vector-style. `smooth`: no edge, a soft
* shadow and highlight across the whole form. `flat`: the depth alone, no
* lighting.
*/
export declare type BotAvatarShading = 'crisp' | 'smooth' | 'plastic' | 'flat' | 'fabric';
export declare const botAvatarShapes: Record;
export declare class BotAvatarSim {
readonly pose: BotAvatarPose;
state: BotAvatarState;
private rand;
private t;
private wFrom;
private tr;
private trDuration;
private yawW;
private pitchW;
private rollW;
private lookXW;
private lookYW;
private blink;
private blinkAt;
private blinkAgain;
private dart;
private dartAt;
private dartX;
private dartY;
private flip;
private flipPoked;
private jump;
private flipAt;
private flipSide;
private nod;
private nodAt;
private hopPhase;
private hopCount;
/** the hops' gain: the working weight while in the state, then held so
a hop under way finishes whole when the state is left */
private hopGain;
private laughEv;
private laughAt;
private prevYaw;
private jelly;
private jellyV;
/** how far the eyes run ahead of a head turn */
private gazeLead;
/** the idle gaze: where the head is looking, and when it moves on */
private gazeDir;
private gazeAt;
/** how far it turns to the side, 1 as the gaze has it */
private turnK;
/** the breathing cycle's phase, in turns */
private breathPhase;
private ptrX;
private ptrY;
private ptrS;
private ptrTargetX;
private ptrTargetY;
private ptrTargetS;
private baseYaw;
constructor(seed: number, state?: BotAvatarState);
setState(next: BotAvatarState, immediate?: boolean): void;
/** Where the pointer is, relative to the head (−1 … 1 across a head
width), and how strongly to follow it (0 lets go). */
setPointer(x: number, y: number, strength: number): void;
/** A hop and a full turn, right now, whatever the state. */
poke(): void;
/** How far the head turns to the side while idle: 1 as the gaze has
it, 0 keeps it facing forward. */
setTurn(k: number): void;
/** The jump's numbers; any subset. */
setJump(j: Partial): void;
private nextGaze;
/** when the next idle jump is due: `every` seconds, give or take 40 % */
private nextFlip;
/** Advance by `dt` seconds (already scaled by the speed). */
update(dt: number): void;
}
/** How the landing squash of a jump plays out. */
export declare type BotAvatarSquashEase = 'sharp' | 'pulse' | 'soft' | 'bouncy';
/** What the bot is doing. Each state is a pose plus its own motion. */
export declare type BotAvatarState = 'default' | 'working' | 'sleeping';
export declare const botAvatarStates: BotAvatarState[];
/** Texture size for an avatar `devicePx` wide (CSS px × device pixel ratio). */
export declare function botAvatarTier(devicePx: number): number;
/** The eighteen body shapes. */
export declare type BotAvatarType = 'clover' | 'flower' | 'triangle' | 'square' | 'blob' | 'ghost' | 'circle' | 'drop' | 'star' | 'droid' | 'mech' | 'alien' | 'hexagon' | 'cat' | 'cloud' | 'pill' | 'pebble' | 'puddle';
export declare const botAvatarTypes: BotAvatarType[];
/** Fill `out` (M × M × rgb, sRGB 0–255) with the lit sphere for body colour `c` (linear). */
export declare function buildBotAvatarMatcap(out: Float32Array, c: V3, f: BotAvatarFrame, p: BotAvatarMaterial): void;
export declare function drawBotAvatarFrame(ctx: CanvasRenderingContext2D, box: number, pose: BotAvatarPose, cfg: BotAvatarDrawConfig): void;
/** The lights the pile's own fibres are baked for: the back light's
direction on screen (unit, y down) and how far round to the front the
key sits (radians). */
declare interface FurLights {
bx: number;
by: number;
front: number;
}
/** The pile's style: `length` and `density` multiply the base fibres',
`fuzz` (0–1) is how soft the silhouette is, `clumps` (0–1) how much the
fibres gather into tufts, `curl` (0–1) how wavy they are, `gravity`
(0–1) how much they hang down. */
declare interface FurStyle {
length: number;
density: number;
fuzz: number;
clumps: number;
curl: number;
/** 0–1: how much the pile hangs down — combed down from a parting at the
top rather than standing out evenly all round */
gravity: number;
}
declare interface Lift {
/** the baked occlusion with the edge's darkening taken back out */
ao: Uint8Array;
/** the sheen band just inside the outline, a gain */
k: Float32Array;
}
/** Relative luminance (WCAG), 0–1. Unparseable colours count as mid-grey. */
export declare function luminance(color: string): number;
/** Parse #rgb / #rrggbb / rgb() / hsl() into 0–255 channels; null for anything else. */
export declare function parseColor(input: string): [number, number, number] | null;
/** The still pose of a state, for reduced motion and the first paint. */
export declare function restPose(state: BotAvatarState): BotAvatarPose;
/**
* A shade of a colour: `dl` moves the lightness (−1..1), `ds` the
* saturation. Darker shades get a touch more saturation so they stay
* rich instead of going grey, the way a painted surface falls into shadow.
*/
export declare function shade(color: string, dl: number, ds?: number): string;
export declare function shadeBotAvatarTexels(form: BotAvatarForm, mc: Float32Array, px: Uint8ClampedArray, aoMul: Float32Array, lift?: Lift): void;
declare type V3 = [number, number, number];
/** Build a form ahead of time (call from an idle callback at mount). */
export declare function warmBotAvatarPlastic(key: string, path: Path2D, devicePx?: number, depth?: number, fabric?: boolean, style?: FurStyle, light?: number, lights?: FurLights): void;
declare interface Wear {
hat: BotAvatarHat;
glasses: BotAvatarGlasses;
headphones: boolean;
bowTie: boolean;
/** the hat's, the headphones' and the bow tie's colour */
color: string;
/** the body is plush: the bow tie is the same felt rather than satin */
fabric?: boolean;
}
export { }