/** * The idle layer, evaluated rather than declared. See `docs/motion-spec.md`. * * `motion.css` is the original and stays the original: on the web the browser * runs these loops off a stylesheet and nothing in TypeScript is involved. This * file is the same seven animations written as arithmetic, for React Native, * which has no stylesheet, no custom properties and no `@keyframes`. * * ## The whole idle layer is a pure function of time * * That is the property everything here rests on, and it is worth stating * because it is not obvious from the CSS. Every loop is `infinite`, none of * them has a start event, none reacts to anything, and the only inputs are the * seeded timings, the amplitude, and two pose channels. So there is no state to * keep, nothing to start or stop, and no drift to correct: given a clock, * `idleAt` says what the blobatar looks like, and two blobatars that agree * about the clock agree about everything. * * It is also what makes this testable without a device. `scripts/probe-idle.ts` * runs the real stylesheet in headless Chrome, freezes it at sampled times, and * compares the matrices the browser computed against what this returns. That is * the only honest oracle for a port of a stylesheet, and it is the same * instrument `probe-compose.ts` already uses for the pose. * * ## What amplitude means here * * On the web `--mo-amp` ramps 0 to 1 on hover, and is pinned to 1 by * `animate="always"`. There is no hover on a touch screen, and `motion.css` * already says so itself: under `@media not ((hover: hover) and (pointer: * fine))` every loop is paused and amplitude forced to 0 unless the blobatar is * `mo-always`. So the only mode this platform has is the always one, and * amplitude is a plain 0-to-1 the caller ramps rather than a hover state. * * ## What is not here * * The hover lift, which is `.mo-root:hover`'s `translateY(-1.5px) scale(1.04)`, * because it is a pointer response and there is no pointer. `--mo-rate`, the * slow-motion debugging dial, because it is a stylesheet class for a person * looking at a page. Both are the web's, and neither has a meaning to port. */ import { type IdleSeeds } from "./animate"; import { type Posable, type Pose } from "./morph"; import { type TraitOverrides } from "./traits"; export type { IdleSeeds }; /** * This blobatar's idle timings, from its name. * * The sibling of the `--mo-*` custom properties `_parts` emits, for a renderer * with no stylesheet to read them. Same traits, same draws, same crowd: a * blobatar breathes on the same offset on both platforms, which is the only * thing that makes the two the same creature in motion rather than two * creatures that look alike. * * It reads `traits` directly rather than going through the renderer's * `resolve`, and the two option names below are the whole of what `resolve` * does before the palette work this has no use for. Reaching through the * renderer would put a copy of it in `dist/idle.js`, since core's entries are * standalone bundles. */ export declare function idleSeeds(name: string, opts?: { normalize?: boolean; traits?: TraitOverrides; }): IdleSeeds; /** * One frame of the idle layer, as the numbers each nesting level needs. * * The shape mirrors `motion.css`'s element structure rather than its list of * `@keyframes`, because that is what a renderer has to build: root, breathe, * bob, the eye pair, each eye, each eye's own path. A field here is one level * there, and `idleTransforms` is the mapping. */ export interface IdleFrame { /** `mo-shake`, the tremor, in viewBox units. Rides `shake`, not amplitude. */ shake: [number, number]; /** `mo-breathe`, a non-uniform scale about the viewBox centre. */ breathe: [number, number]; /** `mo-bob`, vertical, in viewBox units. Negative is up. */ bob: number; /** `mo-saccade`, the eye pair's glance, in viewBox units. */ saccade: [number, number]; /** * `mo-rock`'s phase, +1 to -1, which is the seesaw `thinking` rides. * * A phase and not a position: it is read by the pose composition, where * `rock` decides how much of `edy2` it is allowed to move. At +1 the pair * sits exactly where `bakePose` puts it, which is why the static render of * `thinking` is frame zero of this loop rather than an approximation of it. */ rockp: number; /** `mo-blink`, a scaleY on each eye's own path, in its own leaned frame. */ blink: number; /** * `mo-wrap`, the saccade's foreshortening, as coefficients rather than as a * finished scale. * * The horizontal term and the rotation both depend on which eye they are * being applied to, exactly as the pose's differentials do, so they are * returned unresolved and the composition multiplies in the per-eye sign. * `sx` is `1 + mx + side * (which eye this is)`. */ wrap: { mx: number; side: number; sy: number; rot: number; }; } /** * What the blobatar looks like at time `t`, in milliseconds since whenever the * caller started counting. * * The origin does not matter and deliberately so. Every loop here is infinite * and phase-offset per seed, so there is no moment that is the beginning of * anything, and a blobatar mounted late is not out of step with one mounted * early. That is the same property the stylesheet has, where a blobatar * appearing mid-scroll joins loops that were already running. * * `amp` is the amplitude, 0 to 1, and it scales the ambient layers only. * `shake` and `rock` are pose channels rather than ambient ones, so they ride * the pose's own amount: a `mad` blobatar trembles because `mad` says so, not * because it is being animated. See the header on what amplitude means here. */ export declare function idleAt(s: IdleSeeds, t: number, amp: number, shake?: number): IdleFrame; /** * One frame of the whole animated blobatar, as a transform per nesting level. * * The mapping from `motion.css`'s elements to this object is one to one, and * deliberately so: a renderer builds six levels of group and puts one of these * on each, which is the same tree the stylesheet decorates. Nothing here is a * simplification of that tree, because every level of it earns its place by * having a different origin or a different clock, and collapsing two of them is * how the eye-scale bug in `motion.css`'s own history happened. * * The order inside each string is the order CSS resolves the individual * transform properties: `translate`, then `rotate`, then `scale`, then * `transform`. That is stated in `motion.css` beside `.mo-eye` and it is the * rule the whole composition turns on. Following the comment there is correct; * re-deriving it is how the two stop agreeing. */ export declare function idleTransforms(l: L, p: Pose, f: IdleFrame): { root: string; breathe: string; bob: string; eyes: string; eye: string[]; glance: string[]; }; //# sourceMappingURL=idle.d.ts.map