Skip to content

API reference

typescript
import {busk, compile} from '@logfox/busker';
const show = busk(root, routine);

Puts on a show inside root, an HTMLElement. Returns a Busker. Starts by itself once the root is on screen.

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.

FieldTypeDefaultWhat it does
stepsStep[]—Required. The only timeline.
FieldTypeDefaultWhat it does
startPoint[0.5, 0.5]Where the cursor rests before the first beat, as a fraction of the root’s size.
delaynumber0Ms 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.
motionMotionConfigsee belowGlide timing for all { click } and { move } steps.
clickTargetsstring[]noneSelectors that look clickable and count for the miss hint.
visibilitynumber1How much of the root must be on screen to run, as a fraction.
canPlay() => booleanalways trueExtra condition to run, checked with visibility. See Stopping and starting.
freezeAtnumber0Frame to hold under prefers-reduced-motion.
exploreHintboolean | string | ExploreHintConfigtrueA “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:

ShapeWhat 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.

FieldDefaultWhat it does
pxPerSecond580Constant travel speed (px/s). Glide ms = distance ÷ speed (+ short-hop floor below ~150px).
minMoveMs115Minimum glide time before short-hop extras.
dwellMs300Hover 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.

FieldDefaultWhat it does
text"Click to explore"Pill label.
dismissAfterMs1800Ms after pop-in before auto pop-out (fixed for the visit; pointer motion does not extend it).
durationMs—Alias for dismissAfterMs.
offsetX1.75remGap to the right of the pointer (any CSS length).

Exports: EXPLORE_HINT_TEXT, EXPLORE_HINT_DISMISS_MS, EXPLORE_HINT_OFFSET_X.

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.

typescript
type ResolveTarget = (to: string | Point, from: Point) => Point | null;
ArgumentMeaning
toThe selector or fractional Point from a { click } or { move } step.
fromCursor 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.

FieldTypeWhat it does
tostring | PointSame target as the step (selector or fraction). See Point.
fromnumberMs from loop start when the glide begins.
untilnumberMs when the cursor arrives at to.
pressnumberOptional. 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().

One { run } step on the timeline. Output of compile() only — not passed on Routine.

FieldTypeWhat it does
atnumberMs from loop start when run fires once per lap.
run() => voidSame 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.

ArgumentTypeDefaultWhat it does
stepsStep[]—Same script you would pass on a routine.
resolveTargetResolveTarget—Maps each glide target to px (or null).
motionMotionConfigDEFAULT_MOTIONSame 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:

FieldTypeWhat it does
glidesGlide[]One entry per { click } or { move } step, in order.
runsScheduledRun[]One entry per { run } step.
durationnumberLoop 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).

MemberWhat it does
durationLoop 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.

← compile() helper · Styling