Data
Datasets as an environment reads them: a column resolved to numbers, dates, periods or categories, the axis presets over them, and a series entry.
@internote/canvas-sdk#Functions
(value: unknown): IntervalValue | null(
datasets: Record<string, ChalkDataset> | undefined,
value: unknown,
): string[] | null(
datasets: Record<string, ChalkDataset> | undefined,
keysBinding: unknown,
valuesBinding: unknown,
periodBinding: unknown,
): TimeSeries | null(axis: CategoricalAxis, text: string): number | nulltext when they do not.(cells: string[]): ColumnKind(cell: string): { re: number; im: number; } | nullReads D39's written form: 4+2i, 2i+4, -i, 3.5j. A bare real is a complex number with no imaginary part.
(
datasets: Record<string, ChalkDataset> | undefined,
value: unknown,
): ColumnKind | nullperiods.ts) — or null where its cells share no kind.(
datasets: Record<string, ChalkDataset> | undefined,
value: unknown,
): PeriodKind | null(cell: string): number | null(values: number[], ticks?: string[]): CategoricalAxisThe names are the canonical string forms, so everything that reads an axis by name goes on working; values is what the matching and the ticks use. The caller decides the ticks — a graph prints them through its own numeric formatter, which knows about π, decades and dates.
Mar, 09:30 or 2024-W12; the inverse of periodValueOf.(value: number, kind: PeriodKind, step?: number): string(value: unknown): string[]name is one of the AXIS_PRESETS, matched exactly (lower case).(name: string): name is AxisPresetName(axis: { kind?: string; } | null | undefined): axis is CategoricalAxisDateEntry.(value: unknown): value is DateEntry(dataset: ChalkDataset): booleanThe compiler marks one with format: 'geojson', and only .geojson is an admitted extension — the extension IS the format declaration, so the name is checked too and the two can never disagree. .json is deliberately not accepted: a GeoJSON in a .json file should fail when it is attached, naming the extension it needs, rather than at load with a parse error from whatever tried to read it.
(text: string): CsvRowsDeliberately minimal and deliberately not a dependency: RFC 4180 quoting (doubled "" inside a quoted field, delimiters and newlines inside quotes), CRLF, and nothing else. Cells stay strings — a dataset is columns of strings and the receiving attribute's type does the parsing.
(kind: PeriodKind | null): booleanPeriodKind every non-blank cell in a column shares, or null if they do not all match one kind.(cells: string[]): PeriodKind | nullformat: names, or null for auto — which is not a kind but a deferral, and the caller decides it from the data.(raw: unknown): PeriodKind | null(
datasets: Record<string, ChalkDataset> | undefined,
periodBinding: unknown,
): number[](cell: string, kind: PeriodKind): number(name: AxisPresetName): CategoricalAxisfiles.(
datasets: Record<string, ChalkDataset> | undefined,
files: AttachedFiles,
): Record<string, ChalkDataset>Returns the input unchanged when there is nothing to do — no attachments, or the files have not arrived — so the host does not hand environments a new object identity on every render for no reason. A dataset whose file is missing keeps its bare src: the column then resolves to null, exactly as it did before the attachment landed, rather than to an invented empty table that would render as a silently blank chart.
(
datasets: Record<string, ChalkDataset> | undefined,
value: unknown,
axis: CategoricalAxis,
): number[] | null(
datasets: Record<string, ChalkDataset> | undefined,
value: unknown,
): string[] | null[0, 0.46 / s], at the current parameter values.(value: unknown, params: Record<string, number>): IntervalValue | nullfallback.(value: unknown, params: Record<string, number>, fallback?: number): number(
datasets: Record<string, ChalkDataset> | undefined,
value: unknown,
): number[] | nullHH:MM as hours, YYYY-Www as fractional years by the week.(
datasets: Record<string, ChalkDataset> | undefined,
value: unknown,
): number[] | null(series: TimeSeries, at: number): Map<string, number>A key whose own series starts late or ends early holds its nearest reading rather than vanishing: a gap in one country's record should not punch a hole in the map at every other country's expense.
(names: string[]): CategoricalAxis(entry: unknown): string[](entry: unknown): string | nullauto axis.numberlabelRed is R·e·d to the expression parser and a colour to a reader; the refiner keeps both and the axis decides. Written out, an entry is a NUMBER when it is a literal, a date, or an expression whose every letter is a parameter the environment declares, and a NAME otherwise — so a, b beside parameter(var: a) and parameter(var: b) is two numbers, and beside nothing is two categories.
#Constants
Record<AxisPresetName, AxisPreset>format:, in the order the docs should list it.readonly ["auto", "numbers", "dates", "months", "weekdays", "hours", "weeks"]#Interfaces
namesstring[]ticksstring[]kindNumericAxis.'categories'namesstring[]presetmonthsweekdaysstopsnumber[]Everything about the axis's shape is a categorical axis's — the stops stand at 1…n whatever the gaps between the values are, the window is half a step beyond each end, nothing snaps it to a grid step or grows it for the aspect, and a continuous mark is refused on it. What differs is the reading: a cell is matched as a NUMBER (so 800, 800.0 and a column holding either land on the same stop), the stops are sorted ascending rather than kept in the order they were met, and each tick is printed by the numeric formatter instead of writing its own text.
Which is the axis a heatmap of a factorial grid wants: five loads and four speeds, one cell apiece, labelled 2…6 and 800…2000 with nothing invented in between.
Named stops and not values, though the numbers are what the axis holds: a NumericAxis already has a values, and it is the KIND of number written there (numbers, radians, dates). Two fields of one name on the two halves of ResolvedAxis, one a string and one a list, is a mistake waiting for whoever reaches for axis.values without narrowing first.
ticksstring[]columnsstring[]rowsstring[][]date2024-03-15 or 2024-03.stringvaluedateValueOf.numberendstart on a reversed axis.numberstartnumberbyKeyMap<string, Map<number, number>>periodsnumber[]#Types
Record<string, string> | null | undefined<axis> format:.monthsweekdaysnumericdatecomplextextnumeric when every non-blank cell is a number, date when every one is an ISO date (2024-03-15 or 2024-03, nothing locale-dependent), complex when every one is a complex literal that is not a plain number, and text otherwise — which is what a column of names is, and what a categorical axis reads.
format: may say: how the reader reads its values, or auto to decide from the bound data.monthsweekdaysautonumbersdateshoursweeksdate or month, which decides how a scrubber steps through it and labels it.numberdatemonthweekdayhourweek