DOM ENGINEV0.21.3FIZLET

TIMELINE V0.21.3 BETA

@fzlt/core/timeline

Scripted DOM choreography on the kernel clock. Keyframe tracks animate CSS properties (transform, translate, scale, rotate, opacity, clip-path, filter, custom properties: any value whose numbers change and whose words stay) or plain numbers, with easings, delays, staggers, sequencing and overlap, labels, repeats and yoyo. Time moves in the fixed step (no allocation, no DOM); writes happen in render through the ledger, change-only, so Recall restores every property touched. Done or paused, it asks for no frames: the engine settles. With reduced motion, play() lands on the end state in one step (or build a gentler variant on tl.reduced).

@fzlt/core/timeline · GZIP2,137 B2.1 KB of a 2.3 KB budget

Measured on this build: minified and gzipped with everything it imports, the way npm run size checks the budget in CI.

6.3 KB gz
LIVE · LOADINGDOM choreography on the kernel clock: the cartridge seats, the screen opens, the lines stagger in. When it ends, the engine settles. Replay runs it again; with reduced motion it lands on the end at once.

Tap to make the bricks dance into the next shape.7.9 KB gz

STATUS · what the flags meanBETA

Tested and budgeted; not yet carried by a shipped game, or its API is still moving. Shipped now; COMPLETE also asks that its API has had no breaking change since it shipped, which is still to be confirmed.

SINCE
v0.19.0
SHIPPED IN
  • fizlet.com: the home page's reveals and parallax, the origin hero and Before AI: 2015, live
  • the DOM VIRUS site: the cartridge console, the detail-page scenes and the diagrams
MODULES · hosted on this site
import { EASES, timeline } from "https://fizlet.com/dist/timeline.js";
NPM · @fzlt/core
npm install @fzlt/core
import { EASES, timeline } from "@fzlt/core/timeline";
IN SHORT
timeline(e)
  .to(cart, { translate: ["0px -150px", "0px 0px"] }, { dur: 0.7, ease: "back" })
  .label("seated")
  .to(screen, { "clip-path": ["inset(50%)", "inset(0%)"] }, { at: "seated" })
  .to(lines, { opacity: [0, 1] }, { stagger: 0.15 })
  .play(); // e.destroy() gives every property back

API

Every export with its signature, parameters, return type, doc comment and status flag, generated at build time from the published type declarations of v0.21.3 by the TypeScript compiler. For AI agents: the whole API as plain text.

Ease type BETA

An easing: progress 0..1 in, eased progress out (it may overshoot).

export type Ease = (p: number) => number;

EASES const BETA

The named easings: cubic in, out and in-out; back overshoots a little and settles. Also by name: "steps(n)" (n equal jumps: a ticking counter, a typed-out line).

Type
Record<string, Ease>
export declare const EASES: Record<string, Ease>;

Value type BETA

A number, a CSS value ("translate(0px,8px)", "inset(0 50% 0 0)") or keyframes, evenly spaced. Keyframes share one shape: the same words, only the numbers change. A single value starts where the property's last track ended (or is set at once if it has none).

export type Value = number | string | readonly (number | string)[];

TrackOptions interface BETA

Options for one track: where it starts (at), its duration, delay, easing and stagger.

export interface TrackOptions {
    /** Seconds (default 0.4). */
    dur?: number;
    /** Seconds after `at`; negative overlaps the track before (default 0). */
    delay?: number;
    /** A name in EASES, "steps(n)" or a function (default "out"). */
    ease?: string | Ease;
    /** Seconds between one target's start and the next. */
    stagger?: number;
    /** Where it starts: seconds, "<" (with the track before) or a label (default: the end so far). */
    at?: number | string;
}

TimelineOptions interface BETA

Options for timeline(): repeats, yoyo, speed and reduced-motion handling.

export interface TimelineOptions {
    /** Extra plays after the first (default 0; Infinity loops). */
    repeat?: number;
    /** Every other play runs backwards. */
    yoyo?: boolean;
    /** Speed (default 1). */
    rate?: number;
    /** Animate (default: yes, unless the visitor prefers reduced motion; then play() jumps). */
    motion?: boolean;
    /** `a` on this timeline's events (default 0). */
    id?: number;
}

timeline function BETA

A timeline on engine (paused until play()). Events on the ring, a = id: "timeline:start", "timeline:end", and each label's own name (b = its index) as the playhead passes it.

timeline(engine: Engine, o?: TimelineOptions): Timeline
engine
Engine
o?
TimelineOptions optional
Returns
Timeline
Declaration
export declare function timeline(engine: Engine, o?: TimelineOptions): {
    /** Add tracks: each property of `values` on each target (an element, a list of them, or any
     *  object or typed array for plain numbers: `tl.to(arr, { 0: [0, 1] })`). Chainable. */
    to(targets: object | ArrayLike<object>, values: Record<string, Value>, t?: TrackOptions): /*elided*/ any;
    /** Name a moment (default: the end so far) for `at`; its name goes on the ring as it passes. */
    label(name: string, t?: number | string): /*elided*/ any;
    /** Play forward (from the start if it is at the end). */
    play: () => /*elided*/ any;
    /** Play backward (from the end if it is at the start). */
    reverse: () => /*elided*/ any;
    /** Stop where it is. The engine calls this as its System pause hook (off screen, hidden tab,
     *  stop()): then it only suspends, and plays on when the engine resumes unless you paused it. */
    pause(by?: unknown): /*elided*/ any;
    /** Move the playhead to `t` seconds; it keeps playing or stays paused. */
    seek(t: number): /*elided*/ any;
    /** Land on the end in the next step ("timeline:end" fires). */
    finish: () => /*elided*/ any;
    /** Pause and give every property back as it was before the timeline wrote it: styles through
     *  the ledger (a newer host edit wins), plain numbers to their value when the track was added. */
    revert(): /*elided*/ any;
    /** Resolves the next time the timeline ends, or when its engine is destroyed (at once if it was). */
    done: () => Promise<void>;
    /** The playhead in seconds (over every play). */
    readonly time: number;
    /** Every play together, in seconds (Infinity when it loops forever). */
    readonly duration: number;
    readonly playing: boolean;
    /** The visitor prefers reduced motion (or `motion: false`): build the gentler variant on it. */
    readonly reduced: boolean;
    step(e: Engine, dt: number): void;
    render(): void;
};

Timeline type BETA

The timeline timeline() returns: add tracks with to(), then play it.

export type Timeline = ReturnType<typeof timeline>;