API reference
import {busk, compile} from '@logfox/busker';
const show = busk(root, routine);busk(root, routine)
Section titled “busk(root, routine)”Puts on a show inside root, an HTMLElement. Returns a Busker. Starts by itself once the root is on screen.
Routine
Section titled “Routine”Every routine has a non-empty steps array. Loop length is compiled from those steps (plus the ring on the last click). In development, busk() validates the routine up front (runtyp) and throws before touching the DOM if the shape is wrong or includes unknown fields (including v1 parallel schedules like toggles or duration). Production builds (NODE_ENV=production) skip the check, so runtyp stays out of your bundle; call assertRoutine yourself if you build routines from untrusted input.
| Field | Type | Default | What it does |
|---|---|---|---|
steps | Step[] | — | Required. The only timeline. |
| Field | Type | Default | What it does |
|---|---|---|---|
start | Point | [0.5, 0.5] | Where the cursor rests before the first beat, as a fraction of the root’s size. |
delay | number | 0 | Ms to wait after the show becomes eligible (visibility + canPlay) before the loop starts. While waiting, the show is not playing — play() / pause() are no-ops and the cursor stays hidden. Restarts if eligibility is lost mid-wait. |
motion | MotionConfig | see below | Glide timing for all { click } and { move } steps. |
clickTargets | string[] | none | Selectors that look clickable and count for the miss hint. |
visibility | number | 1 | How much of the root must be on screen to run, as a fraction. |
canPlay | () => boolean | always true | Extra condition to run, checked with visibility. See Stopping and starting. |
freezeAt | number | 0 | Frame to hold under prefers-reduced-motion. |
exploreHint | boolean | string | ExploreHintConfig | true | A “Click to explore” pill that tails the visitor’s pointer. On by default; pass false to disable, a string for your own label, or a config object. |
One line in a click-driven script — exactly one of:
| Shape | What it does |
|---|---|
{ click: string } | Glide, dwell, press, real click. |
{ wait: number } | Pause the playhead (ms). |
{ move: string | [number, number] } | Glide without pressing. |
{ run: () => void } | Run code once; cursor unchanged. |
[number, number] — a spot as a fraction of the mock root ([0.5, 0.5] is center). Used for routine start and { move: [x, y] } steps. The optional start argument to compile() uses the same tuple shape but in pixels, not fractions.
MotionConfig
Section titled “MotionConfig”| Field | Default | What it does |
|---|---|---|
pxPerSecond | 580 | Constant travel speed (px/s). Glide ms = distance ÷ speed (+ short-hop floor below ~150px). |
minMoveMs | 115 | Minimum glide time before short-hop extras. |
dwellMs | 300 | Hover on target before a { click } presses. |
easing | [0.4, 0, 0.2, 1] | CSS cubic-bezier control points for glide progress. |
Exports: cubicBezierEasing, DEFAULT_EASING, DEFAULT_MOTION.
ExploreHintConfig
Section titled “ExploreHintConfig”| Field | Default | What it does |
|---|---|---|
text | "Click to explore" | Pill label. |
dismissAfterMs | 1800 | Ms after pop-in before auto pop-out (fixed for the visit; pointer motion does not extend it). |
durationMs | — | Alias for dismissAfterMs. |
offsetX | 1.75rem | Gap to the right of the pointer (any CSS length). |
Exports: EXPLORE_HINT_TEXT, EXPLORE_HINT_DISMISS_MS, EXPLORE_HINT_OFFSET_X.
ResolveTarget
Section titled “ResolveTarget”Type exported as ResolveTarget. It is not a function busker gives you — you pass your own into compile() so glide lengths can be computed from distances.
type ResolveTarget = (to: string | Point, from: Point) => Point | null;| Argument | Meaning |
|---|---|
to | The selector or fractional Point from a { click } or { move } step. |
from | Cursor position in px (root coordinates) when this step starts. |
Return the destination in px from the mock root’s top-left. Return null when a selector is not in layout yet (compile assumes ~zero travel; at runtime busk() may remeasure and stretch the glide).
busk() builds a ResolveTarget from the live DOM. In unit tests you stub fixed coordinates — see compile() for tests.
One timed cursor segment from a { click } or { move } step. Output of compile() only — not passed on Routine.
| Field | Type | What it does |
|---|---|---|
to | string | Point | Same target as the step (selector or fraction). See Point. |
from | number | Ms from loop start when the glide begins. |
until | number | Ms when the cursor arrives at to. |
press | number | Optional. On { click } steps only: ms when the demo press runs and the element is .click()ed (after dwell). Absent on { move } glides. Read-only output of compile(). |
ScheduledRun
Section titled “ScheduledRun”One { run } step on the timeline. Output of compile() only — not passed on Routine.
| Field | Type | What it does |
|---|---|---|
at | number | Ms from loop start when run fires once per lap. |
run | () => void | Same function you put in the { run } step. |
compile(steps, resolveTarget, motion?, start?)
Section titled “compile(steps, resolveTarget, motion?, start?)”Runs the same scheduler as busk() without a DOM — for tests and assertions. Walkthrough: compile() for tests.
| Argument | Type | Default | What it does |
|---|---|---|---|
steps | Step[] | — | Same script you would pass on a routine. |
resolveTarget | ResolveTarget | — | Maps each glide target to px (or null). |
motion | MotionConfig | DEFAULT_MOTION | Same glide timing as on a routine. |
start | [number, number] (px) | [0, 0] | Cursor position before the first step. Same tuple shape as Point, but pixels, not fractions. busk() converts routine start fractions to px first. |
Returns:
| Field | Type | What it does |
|---|---|---|
glides | Glide[] | One entry per { click } or { move } step, in order. |
runs | ScheduledRun[] | One entry per { run } step. |
duration | number | Loop length in ms (includes ring time after the last click). |
compileStepStarts(steps, resolveTarget, motion?, start?)
Section titled “compileStepStarts(steps, resolveTarget, motion?, start?)”Same arguments as compile(). Returns number[] — ms from loop start when each step begins, in script order (including { wait } and { run } steps).
Busker
Section titled “Busker”| Member | What it does |
|---|---|
duration | Loop length in ms from compiled steps. |
play() | Start or resume. A no-op once a visitor has taken over. |
pause() | Hold where it is. |
stepAside() | Hand the mock to the visitor: stop for good, hide the cursor. |
destroy() | Stop everything and remove every class, listener, and observer busker added. |