Parameters
Free parameters and the sweeps over them: which names an expression leaves open, the axis a sweep walks, and the session that holds the current value.
@internote/canvas-sdk#Functions
(
children: CompiledNode[],
categorical?: Partial<Record<string, boolean>>,
scope?: FreeParamScope,
): string[]Walks the body flattened, so a letter written inside a cue is found; the caller decides whether a control for it should be SHOWN yet, which is what visibleNodes is for.
(
children: CompiledNode[],
free: string[],
datasets?: Record<string, ChalkDataset>,
): ParameterAxis[]hidden: parameters are left out: a letter the author put behind an expression still holds a value the marks read, and still has no business being a knob. That is why this is not the same walk a surface makes — the surface wants every letter, the footer wants the operable ones.
ParameterAxis for a letter used in an expression but never declared as a parameter: a slider from −5 to 5 in steps of 0.1, starting at 1.(variable: string): ParameterAxis(
nodes: CompiledNode[],
datasets: Record<string, ChalkDataset> | undefined,
): ParameterAxis[]parameter node into a ParameterAxis: its letter, range, step, starting value and format, taking them from a bound data column where it has one.(
node: CompiledNode,
datasets: Record<string, ChalkDataset> | undefined,
): ParameterAxis | null(
axes: ParameterAxis[],
steps: StepController,
params: Record<string, number> | undefined,
sweeps?: Record<string, number>,
): Record<string, number>The reader's two inputs are held apart because they MEAN different things. A plain parameter takes a value — it sits where they put it, and nothing else was ever going to move it. A swept one takes a displacement, which is a claim about the sweep rather than about the number: the letter keeps running, it just runs from where they let go. That is why sweeps alone is handed back on a step change; nobody was driving params, so there is nothing there to hand back.
period: slices against.(axes: ParameterAxis[], periodBinding: unknown): ParameterAxis | nullA mark names the COLUMN, never the parameter: an environment with two parameters over the same years is not a thing anyone has wanted, and making every mark name the same node would be noise. So the match is by column where one can be made, and by there being a single bound parameter where the mark's column and the parameter's are written differently — #pop.year for the marks and #calendar.year for the scrubber is one axis spelled twice, not two axes.
<S extends ParameterSession>(
session: S,
axis: ParameterAxis,
steps: StepController,
value: number,
): Svalue at this clock reading — what dragging the slider stores.(axis: ParameterAxis, steps: StepController, value: number): number(axis: ParameterAxis, steps: StepController, shiftMs?: number): numberThe sweep runs its range end to end over duration: from the moment its anchor fires — the same anchor engine every other cue reads, so a cue.parameter(at: 3 + 1.5s) starts when the rest of step 3's choreography says it does. Past the window it holds the far end, the way a fired keyframe holds the value it moved to.
shiftMs is what the reader's drag left behind: a DISPLACEMENT of the sweep's own elapsed time, never of the scene clock. The clock is shared with every cue in the scene, and moving it to scrub a parameter would fire choreography the reader had not reached and un-fire what they had. A displacement rather than a fixed value because playing must still work afterwards — the sweep carries on at its own rate from wherever they left it, and the cues carry on undisturbed, because both ride the one clock that never moved.
The author's default: is the sweep's own starting displacement, so it begins where the author put it and runs to the far end — and a reader who drags BELOW it still reaches the bottom of the range, because the slider spans the range and the displacement spans the slider.
A discrete parameter lands on its nearest stop, so a mark slicing by it shows a row the data actually holds and never a blend of two.
#Interfaces
Both are vocabulary facts, so both come from the environment. Q1 on an axis ruled in quarters is a quarter, not Q × 1 wanting a slider for Q; and the y in a surface's expression: is the vertical axis it is being evaluated over, not a letter anyone can drag.
An environment that declares neither — a map, say — gets the plain reading, which is the right one for it.
formalReadonly<Record<string, { attribute: string; names: readonly string[] }>>onAxisReadonlySet<string>standingon:, on the axis they do not measure.ReadonlySet<string>columnover: bound one — a mark's period: matches against it.unknowndeclaredbooleandiscretediscrete:) rather than moving through the gaps. The stops are the data's own values, or the step: ladder when one was written.booleaninitialdefault:, else the first stop.numberkindnumberdatemonthweekdayhourweeklabelname: as inline content, when they gave one.unknownmaxnumberminover:, else the author's.numbernodeparameter or cue.parameter node it was read from.CompiledNodestepnumberstopsnumber[]sweepcue.parameter.ParameterSweep | nullvariablestringparamsRecord<string, number>sweepsRecord<string, number>cue.parameter: when it starts, how long it runs, how it eases.atCueAnchordurationMsnumbereasinglinearsmooth