@motionscript/charts 0.1.0 → 0.1.1-alpha.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +38 -0
- package/README.md +98 -28
- package/dist/bar-chart/bar-chart.d.ts +242 -119
- package/dist/bar-chart/bar-chart.d.ts.map +1 -1
- package/dist/bar-chart/bar-chart.js +231 -260
- package/dist/bar-chart/bar-chart.js.map +1 -1
- package/dist/bar-chart/category-axis.d.ts +16 -38
- package/dist/bar-chart/category-axis.d.ts.map +1 -1
- package/dist/bar-chart/category-axis.js +59 -68
- package/dist/bar-chart/category-axis.js.map +1 -1
- package/dist/bar-chart/chart-bars.d.ts +60 -91
- package/dist/bar-chart/chart-bars.d.ts.map +1 -1
- package/dist/bar-chart/chart-bars.js +88 -125
- package/dist/bar-chart/chart-bars.js.map +1 -1
- package/dist/bar-chart/index.d.ts +5 -13
- package/dist/bar-chart/index.d.ts.map +1 -1
- package/dist/bar-chart/index.js +2 -9
- package/dist/bar-chart/index.js.map +1 -1
- package/dist/bar-chart/shared.d.ts +40 -132
- package/dist/bar-chart/shared.d.ts.map +1 -1
- package/dist/bar-chart/shared.js +70 -158
- package/dist/bar-chart/shared.js.map +1 -1
- package/dist/browser/chunks/chunk-R3Q5EE6E.js +2 -0
- package/dist/browser/chunks/chunk-R3Q5EE6E.js.map +7 -0
- package/dist/browser/index.js +1 -1
- package/dist/browser/index.js.map +4 -4
- package/dist/browser/kit.js +1 -1
- package/dist/browser/manifest.json +1 -1
- package/dist/engine.d.ts +8 -17
- package/dist/engine.d.ts.map +1 -1
- package/dist/engine.js +8 -17
- package/dist/engine.js.map +1 -1
- package/dist/index.d.ts +2 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2 -0
- package/dist/index.js.map +1 -1
- package/dist/kit/cartesian.d.ts +49 -35
- package/dist/kit/cartesian.d.ts.map +1 -1
- package/dist/kit/cartesian.js +80 -42
- package/dist/kit/cartesian.js.map +1 -1
- package/dist/kit/chart-canvas.d.ts +37 -40
- package/dist/kit/chart-canvas.d.ts.map +1 -1
- package/dist/kit/chart-canvas.js +53 -47
- package/dist/kit/chart-canvas.js.map +1 -1
- package/dist/kit/chart-legend.d.ts +16 -59
- package/dist/kit/chart-legend.d.ts.map +1 -1
- package/dist/kit/chart-legend.js +38 -76
- package/dist/kit/chart-legend.js.map +1 -1
- package/dist/kit/entries.d.ts +2 -0
- package/dist/kit/entries.d.ts.map +1 -1
- package/dist/kit/entries.js +2 -0
- package/dist/kit/entries.js.map +1 -1
- package/dist/kit/horizontal-axis.d.ts +77 -0
- package/dist/kit/horizontal-axis.d.ts.map +1 -0
- package/dist/kit/horizontal-axis.js +99 -0
- package/dist/kit/horizontal-axis.js.map +1 -0
- package/dist/kit/motion.d.ts +16 -3
- package/dist/kit/motion.d.ts.map +1 -1
- package/dist/kit/motion.js +15 -1
- package/dist/kit/motion.js.map +1 -1
- package/dist/{pie-chart → kit}/pie-legend.d.ts +14 -29
- package/dist/kit/pie-legend.d.ts.map +1 -0
- package/dist/kit/pie-legend.js +93 -0
- package/dist/kit/pie-legend.js.map +1 -0
- package/dist/kit/polar.d.ts +31 -0
- package/dist/kit/polar.d.ts.map +1 -0
- package/dist/kit/polar.js +33 -0
- package/dist/kit/polar.js.map +1 -0
- package/dist/kit/shared.d.ts +60 -214
- package/dist/kit/shared.d.ts.map +1 -1
- package/dist/kit/shared.js +91 -291
- package/dist/kit/shared.js.map +1 -1
- package/dist/kit/style.d.ts +254 -0
- package/dist/kit/style.d.ts.map +1 -0
- package/dist/kit/style.js +197 -0
- package/dist/kit/style.js.map +1 -0
- package/dist/kit/vertical-axis.d.ts +36 -45
- package/dist/kit/vertical-axis.d.ts.map +1 -1
- package/dist/kit/vertical-axis.js +69 -81
- package/dist/kit/vertical-axis.js.map +1 -1
- package/dist/line-chart/chart-line.d.ts +107 -40
- package/dist/line-chart/chart-line.d.ts.map +1 -1
- package/dist/line-chart/chart-line.js +172 -89
- package/dist/line-chart/chart-line.js.map +1 -1
- package/dist/line-chart/chart-region.d.ts +14 -27
- package/dist/line-chart/chart-region.d.ts.map +1 -1
- package/dist/line-chart/chart-region.js +13 -28
- package/dist/line-chart/chart-region.js.map +1 -1
- package/dist/line-chart/index.d.ts +5 -18
- package/dist/line-chart/index.d.ts.map +1 -1
- package/dist/line-chart/index.js +3 -16
- package/dist/line-chart/index.js.map +1 -1
- package/dist/line-chart/line-chart.d.ts +272 -119
- package/dist/line-chart/line-chart.d.ts.map +1 -1
- package/dist/line-chart/line-chart.js +309 -257
- package/dist/line-chart/line-chart.js.map +1 -1
- package/dist/line-chart/shared.d.ts +73 -130
- package/dist/line-chart/shared.d.ts.map +1 -1
- package/dist/line-chart/shared.js +195 -156
- package/dist/line-chart/shared.js.map +1 -1
- package/dist/line-chart/x-scale.d.ts +16 -55
- package/dist/line-chart/x-scale.d.ts.map +1 -1
- package/dist/line-chart/x-scale.js +44 -111
- package/dist/line-chart/x-scale.js.map +1 -1
- package/dist/nodes.d.ts +3 -13
- package/dist/nodes.d.ts.map +1 -1
- package/dist/nodes.js +9 -13
- package/dist/nodes.js.map +1 -1
- package/dist/pie-chart/index.d.ts +3 -15
- package/dist/pie-chart/index.d.ts.map +1 -1
- package/dist/pie-chart/index.js +1 -11
- package/dist/pie-chart/index.js.map +1 -1
- package/dist/pie-chart/pie-chart.d.ts +147 -85
- package/dist/pie-chart/pie-chart.d.ts.map +1 -1
- package/dist/pie-chart/pie-chart.js +65 -86
- package/dist/pie-chart/pie-chart.js.map +1 -1
- package/dist/pie-chart/pie-ring.d.ts +65 -196
- package/dist/pie-chart/pie-ring.d.ts.map +1 -1
- package/dist/pie-chart/pie-ring.js +154 -292
- package/dist/pie-chart/pie-ring.js.map +1 -1
- package/dist/pie-chart/shared.d.ts +78 -172
- package/dist/pie-chart/shared.d.ts.map +1 -1
- package/dist/pie-chart/shared.js +54 -177
- package/dist/pie-chart/shared.js.map +1 -1
- package/dist/radar-chart/index.d.ts +5 -0
- package/dist/radar-chart/index.d.ts.map +1 -0
- package/dist/radar-chart/index.js +5 -0
- package/dist/radar-chart/index.js.map +1 -0
- package/dist/radar-chart/radar-chart.d.ts +218 -0
- package/dist/radar-chart/radar-chart.d.ts.map +1 -0
- package/dist/radar-chart/radar-chart.js +224 -0
- package/dist/radar-chart/radar-chart.js.map +1 -0
- package/dist/radar-chart/radar-grid.d.ts +43 -0
- package/dist/radar-chart/radar-grid.d.ts.map +1 -0
- package/dist/radar-chart/radar-grid.js +61 -0
- package/dist/radar-chart/radar-grid.js.map +1 -0
- package/dist/radar-chart/radar-series.d.ts +59 -0
- package/dist/radar-chart/radar-series.d.ts.map +1 -0
- package/dist/radar-chart/radar-series.js +71 -0
- package/dist/radar-chart/radar-series.js.map +1 -0
- package/dist/radar-chart/shared.d.ts +73 -0
- package/dist/radar-chart/shared.d.ts.map +1 -0
- package/dist/radar-chart/shared.js +123 -0
- package/dist/radar-chart/shared.js.map +1 -0
- package/dist/radial-chart/index.d.ts +6 -0
- package/dist/radial-chart/index.d.ts.map +1 -0
- package/dist/radial-chart/index.js +4 -0
- package/dist/radial-chart/index.js.map +1 -0
- package/dist/radial-chart/radial-chart.d.ts +216 -0
- package/dist/radial-chart/radial-chart.d.ts.map +1 -0
- package/dist/radial-chart/radial-chart.js +174 -0
- package/dist/radial-chart/radial-chart.js.map +1 -0
- package/dist/radial-chart/radial-rings.d.ts +121 -0
- package/dist/radial-chart/radial-rings.d.ts.map +1 -0
- package/dist/radial-chart/radial-rings.js +273 -0
- package/dist/radial-chart/radial-rings.js.map +1 -0
- package/dist/radial-chart/shared.d.ts +73 -0
- package/dist/radial-chart/shared.d.ts.map +1 -0
- package/dist/radial-chart/shared.js +79 -0
- package/dist/radial-chart/shared.js.map +1 -0
- package/package.json +4 -4
- package/registry.json +21 -6
- package/src/bar-chart/bar-chart.ts +274 -315
- package/src/bar-chart/category-axis.ts +53 -88
- package/src/bar-chart/chart-bars.ts +108 -205
- package/src/bar-chart/index.ts +8 -19
- package/src/bar-chart/shared.ts +81 -309
- package/src/engine.ts +8 -17
- package/src/index.ts +2 -0
- package/src/kit/cartesian.ts +118 -55
- package/src/kit/chart-canvas.ts +50 -80
- package/src/kit/chart-legend.ts +36 -97
- package/src/kit/entries.ts +4 -1
- package/src/kit/horizontal-axis.ts +114 -0
- package/src/kit/motion.ts +18 -2
- package/src/{pie-chart → kit}/pie-legend.ts +25 -65
- package/src/kit/polar.ts +54 -0
- package/src/kit/shared.ts +104 -487
- package/src/kit/style.ts +257 -0
- package/src/kit/vertical-axis.ts +81 -115
- package/src/line-chart/chart-line.ts +185 -91
- package/src/line-chart/chart-region.ts +14 -31
- package/src/line-chart/index.ts +14 -22
- package/src/line-chart/line-chart.ts +377 -315
- package/src/line-chart/shared.ts +229 -304
- package/src/line-chart/x-scale.ts +44 -121
- package/src/nodes.ts +9 -13
- package/src/pie-chart/index.ts +3 -35
- package/src/pie-chart/pie-chart.ts +83 -134
- package/src/pie-chart/pie-ring.ts +162 -368
- package/src/pie-chart/shared.ts +92 -379
- package/src/radar-chart/index.ts +4 -0
- package/src/radar-chart/radar-chart.ts +287 -0
- package/src/radar-chart/radar-grid.ts +78 -0
- package/src/radar-chart/radar-series.ts +88 -0
- package/src/radar-chart/shared.ts +146 -0
- package/src/radial-chart/index.ts +5 -0
- package/src/radial-chart/radial-chart.ts +210 -0
- package/src/radial-chart/radial-rings.ts +328 -0
- package/src/radial-chart/shared.ts +114 -0
- package/dist/browser/chunks/chunk-TJNHLQGV.js +0 -2
- package/dist/browser/chunks/chunk-TJNHLQGV.js.map +0 -7
- package/dist/kit/chart-border.d.ts +0 -27
- package/dist/kit/chart-border.d.ts.map +0 -1
- package/dist/kit/chart-border.js +0 -28
- package/dist/kit/chart-border.js.map +0 -1
- package/dist/line-chart/horizontal-axis.d.ts +0 -79
- package/dist/line-chart/horizontal-axis.d.ts.map +0 -1
- package/dist/line-chart/horizontal-axis.js +0 -129
- package/dist/line-chart/horizontal-axis.js.map +0 -1
- package/dist/pie-chart/pie-legend.d.ts.map +0 -1
- package/dist/pie-chart/pie-legend.js +0 -117
- package/dist/pie-chart/pie-legend.js.map +0 -1
- package/src/kit/chart-border.ts +0 -50
- package/src/line-chart/horizontal-axis.ts +0 -151
|
@@ -1,7 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"version": 3,
|
|
3
|
-
"sources": ["../../../src/kit/shared.ts", "../../../src/kit/cartesian.ts", "../../../src/kit/vertical-axis.ts", "../../../src/kit/entries.ts", "../../../src/kit/motion.ts", "../../../src/kit/chart-border.ts", "../../../src/kit/paints.ts", "../../../src/kit/chart-canvas.ts", "../../../src/kit/chart-legend.ts", "../../../src/engine.ts"],
|
|
4
|
-
"sourcesContent": ["/**\n * The vocabulary every chart node shares: what a *series* is, how an axis is\n * scaled and formatted, and the theme leaves each chart's own theme is assembled\n * from.\n *\n * This module exists because the three chart types are three ways of drawing the\n * same table. A line chart, a bar chart and a pie chart disagree about almost\n * everything visible — polylines against columns against wedges — and agree\n * about almost everything underneath: a series is a column with a caption and a\n * paint, a marker is a number formatted one way, a legend is a swatch beside a\n * label, and a theme is a tree of paints with one mapper and one tween. Writing\n * that three times would mean three answers to \"how does a chart round its axis\"\n * within one app.\n *\n * Kept renderer-agnostic (no `Node` imports) so a host's own inspector\n * mappings can build a partial theme without pulling the components in.\n *\n * **Two conventions run through every resolver and lerp below**, inherited from\n * the shape system's `resolveStroke`/`resolveShadow`:\n *\n * - A **mapper** merges the author's loose, partial input onto a `previous`\n * resolved value and resolves every leaf, so the tween always has resolved\n * data to interpolate. It is idempotent.\n * - A **tween** interpolates two resolved values leaf by leaf. Categorical\n * fields (`fontFamily`, `textAlign`) and fields that are `undefined` on either\n * side **step at the midpoint**, because there is no meaningful in-between and\n * defaulting the missing side to 0 would animate a font weight down to nothing\n * on the way to \"unset\".\n */\n\nimport {\n fillOps,\n lerpNumber,\n shadowOps,\n strokeOps,\n insetsOps,\n textOps,\n type DataRecord,\n type Fill,\n type FillResolved,\n type Insets,\n type InsetsResolved,\n type Shadow,\n type ShadowResolved,\n type Stroke,\n type StrokeResolved,\n type TextStyle,\n} from \"@motionscript/sdk\"\n\n/**\n * One series of a chart: a column of the table, captioned and painted.\n *\n * `field` names the column carrying this series' values. What that becomes is\n * the chart's business — a traced polyline, a column of bars, a wedge — but the\n * three questions asked of it are the same everywhere: which column, what to\n * call it, what to paint it, and whether it is currently drawn.\n *\n * `fill` is an **override**: omit it and the series takes the theme palette's\n * entry for its own index, which is what makes a chart nobody has themed come\n * out in five distinct colours rather than five identical ones.\n */\nexport interface ChartSeries {\n /** Key into each data row for this series' value. */\n field: string\n /** Legend caption for this series. */\n label: string\n /**\n * Paint override for this series' mark and its legend swatch. Omit to take\n * the theme palette's entry for this series' index.\n */\n fill?: Fill\n /** Whether the series shows by default. Defaults to `true`. */\n enabled?: boolean\n}\n\n/** A `[min, max]` numeric range in data units. */\nexport type Range = [min: number, max: number]\n\n/**\n * One axis's *data* domain — what it shows — as opposed to {@link AxisConfig},\n * which is how it's *styled*. Every field is optional: `range`/`ticks` derive\n * from the plotted data when omitted, and `label` defaults to `\"\"`.\n */\nexport interface AxisDomainConfig {\n /** Caption drawn alongside the axis. Pass `\"\"` (the default) to hide it. */\n label?: string\n /** `[min, max]` of the scale. Derived from the data bounds when omitted. */\n range?: Range\n /** Tick values (in data units). Derived (five evenly-spaced) when omitted. */\n ticks?: number[]\n /**\n * How a tick value is written down — a `number-format` pattern such as\n * `#,##0.00` or `$#,##0`.\n *\n * Here rather than in {@link AxisConfig} because it is a statement about the\n * *numbers*, not about the ink they are set in: `$` on a revenue axis says\n * what the column holds, and it has to survive a re-theme. It sits beside\n * `range` and `ticks` for the same reason those do.\n */\n format?: string\n}\n\n/**\n * An axis domain entry's resolve: merges the author's partial input onto\n * `previous`, so a later partial `.set({ yAxis: {...} })` patches\n * `label`/`range`/`ticks` independently. `range`/`ticks` staying `undefined`\n * after the merge is the auto-derive signal the scale getters read.\n */\nexport function resolveAxisDomain(\n domain: AxisDomainConfig | undefined,\n previous?: AxisDomainConfig\n): AxisDomainConfig {\n return {\n label: domain?.label ?? previous?.label ?? \"\",\n range: domain?.range ?? previous?.range,\n ticks: domain?.ticks ?? previous?.ticks,\n format: domain?.format ?? previous?.format,\n }\n}\n\n/**\n * An axis domain entry's lerp: interpolates `range`/`ticks` numerically\n * (pairwise by index for `ticks`), so a `to` command that restates a range\n * rescales the plot smoothly. `label`, and either field when one side is in\n * auto-derive mode, step at the midpoint.\n */\nexport function lerpAxisDomain(\n from: AxisDomainConfig,\n to: AxisDomainConfig,\n t: number\n): AxisDomainConfig {\n return {\n label: t < 0.5 ? from.label : to.label,\n range: lerpOptionalRange(from.range, to.range, t),\n ticks: lerpOptionalTicks(from.ticks, to.ticks, t),\n // Steps at the midpoint with the caption, for the same reason: there is no\n // halfway between `$#,##0` and `0.0%`.\n format: t < 0.5 ? from.format : to.format,\n }\n}\n\nfunction lerpOptionalRange(\n from: Range | undefined,\n to: Range | undefined,\n t: number\n): Range | undefined {\n if (!from || !to) return t < 0.5 ? from : to\n return [lerpNumber(from[0], to[0], t), lerpNumber(from[1], to[1], t)]\n}\n\nfunction lerpOptionalTicks(\n from: number[] | undefined,\n to: number[] | undefined,\n t: number\n): number[] | undefined {\n if (!from || !to) return t < 0.5 ? from : to\n const n = Math.max(from.length, to.length)\n const out: number[] = []\n for (let i = 0; i < n; i++) {\n out.push(lerpNumber(from[i] ?? to[i], to[i] ?? from[i], t))\n }\n return out\n}\n\n/**\n * Where a generic `to()` of an axis domain should land, given the domain as it\n * is *drawn* (`drawn`, with `range` and `ticks` resolved off the data), or\n * `undefined` when the request states neither a `range` nor `ticks` and the\n * plain property tween will do.\n *\n * The stored domain of an auto axis has no `range` and no `ticks`, and\n * {@link lerpAxisDomain} steps an unset side at the midpoint, so tweening the\n * stored value from an auto axis is a cut. The charts therefore tween between\n * resolved domains, as their zoom does; this builds the destination. A `range`\n * given without `ticks` keeps the tick *count* the axis already draws, so each\n * marker slides from its old value to its new one instead of the row popping.\n */\nexport function axisTweenTarget(\n drawn: AxisDomainConfig,\n requested: AxisDomainConfig | undefined\n): AxisDomainConfig | undefined {\n if (requested?.range === undefined && requested?.ticks === undefined) return undefined\n const target = resolveAxisDomain(requested, drawn)\n if (requested.ticks === undefined && requested.range !== undefined) {\n const count = Math.max(2, drawn.ticks?.length ?? 2)\n target.ticks = markerValues(requested.range, count - 1)\n }\n return target\n}\n\n/**\n * An axis domain part-way through a tween that leaves or reaches a `range` or\n * `ticks` left to the data: both ends as stored, and how far along. Only the\n * chart knows what an auto side draws as, so {@link settleAxisDomain} resolves\n * it there. Its own fields are the plain {@link lerpAxisDomain} of its ends, so\n * a mapper merging onto one still reads a domain.\n */\nexport interface AxisDomainBlend extends AxisDomainConfig {\n readonly blend: { readonly from: AxisDomainConfig; readonly to: AxisDomainConfig; readonly t: number }\n}\n\nfunction blendOf(domain: AxisDomainConfig): AxisDomainBlend[\"blend\"] | undefined {\n return (domain as Partial<AxisDomainBlend>).blend\n}\n\n/**\n * A chart's axis entry tween: what `to({ yAxis: { range } })` moves through.\n * Between two explicit domains it is {@link lerpAxisDomain}, and a restated\n * `range` without `ticks` spreads explicit ticks across it, keeping their count.\n * When either end leaves `range` or `ticks` to the data, the value between is an\n * {@link AxisDomainBlend}, which the chart draws as the blend of what each end\n * draws: a rescale from an auto axis is continuous, not a cut at the midpoint.\n */\nexport function lerpAxisEntry(from: AxisDomainConfig, to: AxisDomainConfig, t: number): AxisDomainConfig {\n // The mapper merged the request onto `from`, so a field it left unstated is `from`'s own, by identity.\n const rangeMoved = to.range !== from.range\n const target = rangeMoved && to.range && to.ticks && to.ticks === from.ticks\n ? { ...to, ticks: markerValues(to.range, Math.max(2, to.ticks.length) - 1) }\n : to\n const blended = blendOf(from) !== undefined\n const moved = blended || rangeMoved || target.ticks !== from.ticks\n const auto = blended || from.range === undefined || from.ticks === undefined || target.range === undefined || target.ticks === undefined\n if (!moved || !auto) return lerpAxisDomain(from, target, t)\n if (t === 0) return from\n if (t === 1) return target\n const blend: AxisDomainBlend = { ...lerpAxisDomain(from, target, t), blend: { from, to: target, t } }\n return blend\n}\n\n/**\n * `domain` as the chart draws it: `drawn` resolves a plain domain's auto `range`\n * and `ticks` off the data, and a blend is the lerp of what its two ends draw.\n */\nexport function settleAxisDomain(domain: AxisDomainConfig, drawn: (domain: AxisDomainConfig) => AxisDomainConfig): AxisDomainConfig {\n const blend = blendOf(domain)\n if (!blend) return drawn(domain)\n return lerpAxisDomain(settleAxisDomain(blend.from, drawn), settleAxisDomain(blend.to, drawn), blend.t)\n}\n\n/**\n * The low-level colour tokens the default themes are built from — a dark plot\n * panel with warm-grey axis furniture.\n */\nexport const CHART_PALETTE = {\n /** Fill of the plot panel behind the marks. */\n plotFill: \"#15130e\",\n /** Colour of the plot's thick border. */\n borderColor: \"#4a4036\",\n /** Colour of the faint grid lines spanning the plot. */\n gridColor: \"#2c2820\",\n /** Colour of the numeric axis markers, axis captions, and legend labels. */\n markerColor: \"#8a7f70\",\n /** Colour of a spotlit region's dashed rules and its wash. */\n regionColor: \"#d99a3a\",\n} as const\n\n/** The out-of-the-box series palette, cycled by series index. */\nexport const DEFAULT_SERIES_COLORS = [\n \"#d9603b\",\n \"#8194ad\",\n \"#e0a93b\",\n \"#5e9d6b\",\n \"#9ec85a\",\n] as const\n\n/**\n * Opacity an *un*-spotlighted series fades to — its mark and its legend entry\n * alike, so the two dim together.\n */\nexport const SPOTLIGHT_DIM = 0.2\n\n/** Clamp a number into `[0, 1]` — the range every reveal signal here runs in. */\nexport function clampUnit(value: number): number {\n return value < 0 ? 0 : value > 1 ? 1 : value\n}\n\n// ---- Row readers ---------------------------------------------------------\n\n/**\n * Read a numeric field off a row, defaulting missing, non-numeric and non-finite\n * values to 0.\n *\n * A column left as strings silently plots as 0, which is why the CSV parser's\n * numeric auto-coercion matters — a quoted or unit-suffixed column won't plot\n * until it's coerced.\n */\nexport function num(row: DataRecord, field: string | undefined): number {\n if (field === undefined) return 0\n const v = row[field]\n // A `NaN` or infinite cell is no more a measurement than a missing one: read\n // as 0, it cannot poison the scale and turn every point into `NaN`.\n return typeof v === \"number\" && Number.isFinite(v) ? v : 0\n}\n\n/**\n * Read a field off a row as its caption — the counterpart to {@link num} for\n * the columns a chart *names* things by rather than measures them by (a bar's\n * category, a wedge's slice). A missing cell reads as empty rather than as the\n * string `\"undefined\"`.\n */\nexport function text(row: DataRecord, field: string | undefined): string {\n if (field === undefined || field === \"\") return \"\"\n const v = row[field]\n return v === undefined || v === null ? \"\" : String(v)\n}\n\n/**\n * Every column that holds numbers across `data`, in header order, skipping the\n * names in `exclude` (typically the category column).\n *\n * A column counts as numeric only if every non-empty cell in it is a number, so\n * a stray text cell leaves the column out rather than plotting zeros. This is\n * what lets a chart plot \"every other column\" without the author naming twenty\n * fields.\n */\nexport function numericFields(\n data: DataRecord[],\n exclude: string[] = []\n): string[] {\n if (data.length === 0) return []\n const skip = new Set(exclude)\n const seen = new Set<string>()\n const order: string[] = []\n for (const row of data)\n for (const key of Object.keys(row))\n if (!skip.has(key) && !seen.has(key)) {\n seen.add(key)\n order.push(key)\n }\n\n return order.filter((key) => {\n let sawValue = false\n for (const row of data) {\n const v = row[key]\n if (v === undefined || v === \"\") continue\n if (typeof v !== \"number\") return false\n sawValue = true\n }\n return sawValue\n })\n}\n\n// ---- Theme branches ------------------------------------------------------\n\n/** One axis's (x or y) style vocabulary. */\nexport interface AxisConfig {\n /** Style of each marker along the axis. */\n labelStyle: TextStyle\n /** Style of the axis caption. */\n titleStyle: TextStyle\n /**\n * This axis's direction of the plot's internal grid — weight+fill honoured,\n * dash/cap/join ignored (grid lines are drawn as filled rects).\n */\n lineStyle: Stroke\n /**\n * Gap between the plot and the marker row. Only the side facing the plot is\n * read — `.top` for a horizontal axis, `.right` for a vertical one.\n */\n tickPadding: Insets\n /** Gap between the marker row and the caption, read the same side. */\n titlePadding: Insets\n}\n\n/** A legend's per-series colour swatch — a rounded chip, not the caption. */\nexport interface LegendMarkerConfig {\n width: number\n height: number\n borderRadius: number\n stroke: Stroke\n shadow: Shadow\n}\n\n/** A legend's visual theme. */\nexport interface LegendConfig {\n padding: Insets\n /** Caption style — only the swatch carries the series colour. */\n textStyle: TextStyle\n /** Gap between legend entries. */\n itemGap: number\n markerStyle: LegendMarkerConfig\n}\n\n/** The plot panel a cartesian chart draws its marks over. */\nexport interface PlotAreaConfig {\n stroke: Stroke\n fill: Fill\n shadow: Shadow\n}\n\nconst AXIS_LABEL_STYLE: TextStyle = {\n fontSize: 24,\n fontWeight: 700,\n textAlign: \"center\",\n fill: CHART_PALETTE.markerColor,\n}\nconst AXIS_TITLE_STYLE: TextStyle = {\n fontSize: 30,\n fontWeight: 600,\n textAlign: \"center\",\n fill: CHART_PALETTE.markerColor,\n}\nconst AXIS_LINE_STYLE: Stroke = { weight: 2, fill: CHART_PALETTE.gridColor }\n\n/** The default styling of a horizontal (marker row beneath the plot) axis. */\nexport const DEFAULT_X_AXIS: AxisConfig = {\n labelStyle: AXIS_LABEL_STYLE,\n titleStyle: AXIS_TITLE_STYLE,\n lineStyle: AXIS_LINE_STYLE,\n tickPadding: 20,\n titlePadding: 4,\n}\n\n/** The default styling of a vertical (marker column beside the plot) axis. */\nexport const DEFAULT_Y_AXIS: AxisConfig = {\n labelStyle: { ...AXIS_LABEL_STYLE, fontWeight: 500, textAlign: \"right\" },\n titleStyle: AXIS_TITLE_STYLE,\n lineStyle: AXIS_LINE_STYLE,\n tickPadding: 40,\n titlePadding: 24,\n}\n\n/**\n * The default plot panel: **unpainted**, framed. A chart reads against the\n * stage rather than punching a panel into it, which is the look the family was\n * designed at.\n */\nexport const DEFAULT_PLOT_AREA: PlotAreaConfig = {\n fill: [],\n stroke: { weight: 6, fill: CHART_PALETTE.borderColor },\n shadow: [],\n}\n\n/** The default legend styling, shared by every chart that draws one. */\nexport const DEFAULT_LEGEND: LegendConfig = {\n padding: 0,\n textStyle: {\n fontSize: 30,\n fontWeight: 600,\n textAlign: \"left\",\n fill: CHART_PALETTE.markerColor,\n },\n itemGap: 44,\n markerStyle: {\n width: 60,\n height: 24,\n borderRadius: 6,\n stroke: [],\n shadow: [],\n },\n}\n\n/** The default per-series stroke palette — {@link DEFAULT_SERIES_COLORS}, drawn 4px. */\nexport const DEFAULT_SERIES_STROKES: Stroke[] = DEFAULT_SERIES_COLORS.map(\n (fill) => ({ weight: 4, fill })\n)\n\n/** The default per-series fill palette — the same colours, as solid paint. */\nexport const DEFAULT_SERIES_FILLS: Fill[] = DEFAULT_SERIES_COLORS.map(\n (fill) => fill\n)\n\n// ---- Theme branch resolvers ----------------------------------------------\n// Each chart type assembles its own theme out of these, so \"the axis furniture\"\n// means one thing across the family and each chart still declares only the\n// branches it actually draws.\n\nexport function resolveAxisConfig(\n axis: Partial<AxisConfig> | undefined,\n previous: AxisConfig\n): AxisConfig {\n return {\n labelStyle: textOps.resolveStyle(axis?.labelStyle, previous.labelStyle),\n titleStyle: textOps.resolveStyle(axis?.titleStyle, previous.titleStyle),\n lineStyle: strokeOps.resolve(axis?.lineStyle ?? previous.lineStyle),\n tickPadding: insetsOps.resolve(\n axis?.tickPadding ?? previous.tickPadding,\n previous.tickPadding as InsetsResolved\n ),\n titlePadding: insetsOps.resolve(\n axis?.titlePadding ?? previous.titlePadding,\n previous.titlePadding as InsetsResolved\n ),\n }\n}\n\nexport function lerpAxisConfig(\n from: AxisConfig,\n to: AxisConfig,\n t: number\n): AxisConfig {\n return {\n labelStyle: textOps.lerpStyle(from.labelStyle, to.labelStyle, t),\n titleStyle: textOps.lerpStyle(from.titleStyle, to.titleStyle, t),\n lineStyle: strokeOps.lerp(\n from.lineStyle as StrokeResolved[],\n to.lineStyle as StrokeResolved[],\n t\n ),\n tickPadding: insetsOps.lerp(\n from.tickPadding as InsetsResolved,\n to.tickPadding as InsetsResolved,\n t\n ),\n titlePadding: insetsOps.lerp(\n from.titlePadding as InsetsResolved,\n to.titlePadding as InsetsResolved,\n t\n ),\n }\n}\n\nexport function resolvePlotArea(\n plotArea: Partial<PlotAreaConfig> | undefined,\n previous: PlotAreaConfig\n): PlotAreaConfig {\n return {\n fill: fillOps.resolve(plotArea?.fill ?? previous.fill),\n stroke: strokeOps.resolve(plotArea?.stroke ?? previous.stroke),\n shadow: shadowOps.resolve(plotArea?.shadow ?? previous.shadow),\n }\n}\n\nexport function lerpPlotArea(\n from: PlotAreaConfig,\n to: PlotAreaConfig,\n t: number\n): PlotAreaConfig {\n return {\n fill: fillOps.lerp(\n from.fill as FillResolved[],\n to.fill as FillResolved[],\n t\n ),\n stroke: strokeOps.lerp(\n from.stroke as StrokeResolved[],\n to.stroke as StrokeResolved[],\n t\n ),\n shadow: shadowOps.lerp(\n from.shadow as ShadowResolved[],\n to.shadow as ShadowResolved[],\n t\n ),\n }\n}\n\nfunction resolveLegendMarkerConfig(\n marker: Partial<LegendMarkerConfig> | undefined,\n previous: LegendMarkerConfig\n): LegendMarkerConfig {\n return {\n width: marker?.width ?? previous.width,\n height: marker?.height ?? previous.height,\n borderRadius: marker?.borderRadius ?? previous.borderRadius,\n stroke: strokeOps.resolve(marker?.stroke ?? previous.stroke),\n shadow: shadowOps.resolve(marker?.shadow ?? previous.shadow),\n }\n}\n\nfunction lerpLegendMarkerConfig(\n from: LegendMarkerConfig,\n to: LegendMarkerConfig,\n t: number\n): LegendMarkerConfig {\n return {\n width: lerpNumber(from.width, to.width, t),\n height: lerpNumber(from.height, to.height, t),\n borderRadius: lerpNumber(from.borderRadius, to.borderRadius, t),\n stroke: strokeOps.lerp(\n from.stroke as StrokeResolved[],\n to.stroke as StrokeResolved[],\n t\n ),\n shadow: shadowOps.lerp(\n from.shadow as ShadowResolved[],\n to.shadow as ShadowResolved[],\n t\n ),\n }\n}\n\n/** A legend theme as the author may state it — every branch optional. */\nexport type LegendTheme = Partial<Omit<LegendConfig, \"markerStyle\">> & {\n markerStyle?: Partial<LegendMarkerConfig>\n}\n\nexport function resolveLegendConfig(\n legend: LegendTheme | undefined,\n previous: LegendConfig\n): LegendConfig {\n return {\n padding: insetsOps.resolve(\n legend?.padding ?? previous.padding,\n previous.padding as InsetsResolved\n ),\n textStyle: textOps.resolveStyle(legend?.textStyle, previous.textStyle),\n itemGap: legend?.itemGap ?? previous.itemGap,\n markerStyle: resolveLegendMarkerConfig(\n legend?.markerStyle,\n previous.markerStyle\n ),\n }\n}\n\nexport function lerpLegendConfig(\n from: LegendConfig,\n to: LegendConfig,\n t: number\n): LegendConfig {\n return {\n padding: insetsOps.lerp(\n from.padding as InsetsResolved,\n to.padding as InsetsResolved,\n t\n ),\n textStyle: textOps.lerpStyle(from.textStyle, to.textStyle, t),\n itemGap: lerpNumber(from.itemGap, to.itemGap, t),\n markerStyle: lerpLegendMarkerConfig(from.markerStyle, to.markerStyle, t),\n }\n}\n\n/** A whole-palette override replaces the previous palette outright. */\nexport function resolveSeriesStrokes(\n styles: Stroke[] | undefined,\n previous: Stroke[]\n): Stroke[] {\n return (styles ?? previous).map((s) => strokeOps.resolve(s))\n}\n\n/** Pairwise by index; a palette that grows/shrinks holds the longer side's tail. */\nexport function lerpSeriesStrokes(\n from: Stroke[],\n to: Stroke[],\n t: number\n): Stroke[] {\n const n = Math.max(from.length, to.length)\n const out: Stroke[] = []\n for (let i = 0; i < n; i++) {\n const a = (from[i] ?? to[i]) as StrokeResolved[]\n const b = (to[i] ?? from[i]) as StrokeResolved[]\n out.push(strokeOps.lerp(a, b, t))\n }\n return out\n}\n\n/** The fill-palette twin of {@link resolveSeriesStrokes}, for filled marks. */\nexport function resolveSeriesFills(\n fills: Fill[] | undefined,\n previous: Fill[]\n): Fill[] {\n return (fills ?? previous).map((f) => fillOps.resolve(f))\n}\n\n/** The fill-palette twin of {@link lerpSeriesStrokes}. */\nexport function lerpSeriesFills(from: Fill[], to: Fill[], t: number): Fill[] {\n const n = Math.max(from.length, to.length)\n const out: Fill[] = []\n for (let i = 0; i < n; i++) {\n const a = (from[i] ?? to[i]) as FillResolved[]\n const b = (to[i] ?? from[i]) as FillResolved[]\n out.push(fillOps.lerp(a, b, t))\n }\n return out\n}\n\n// ---- Per-series paint ----------------------------------------------------\n\n/**\n * The effective stroke for series `index`: the palette's entry at\n * `index % palette.length`, with the series' own `fill`, if set, overriding just\n * the last (topmost) layer's colour.\n */\nexport function resolveSeriesStroke(\n palette: Stroke[],\n series: ChartSeries,\n index: number\n): Stroke {\n const entry: Stroke =\n palette.length > 0\n ? palette[index % palette.length]\n : { weight: 4, fill: \"white\" }\n if (series.fill == null) return entry\n const layers = strokeOps.resolve(entry)\n if (layers.length === 0) return { weight: 4, fill: series.fill }\n const next = [...layers]\n next[next.length - 1] = {\n ...next[next.length - 1],\n fill: fillOps.resolve(series.fill),\n }\n return next\n}\n\n/**\n * The effective *colour* for series `index` — the same colour\n * {@link resolveSeriesStroke} draws its line in — for contexts (a legend\n * swatch) that only need the fill.\n */\nexport function resolveSeriesFill(\n palette: Stroke[],\n series: ChartSeries,\n index: number\n): Fill {\n const layers = strokeOps.resolve(resolveSeriesStroke(palette, series, index))\n return layers[layers.length - 1]?.fill ?? \"white\"\n}\n\n/**\n * The effective paint for mark `index` of a **filled** chart (a bar, a wedge):\n * the series' own `fill` when it carries one, else the palette's entry for its\n * index, cycled.\n *\n * The stroke twin above has to reach inside a stroke to swap one layer's colour;\n * a filled mark has no such geometry wrapped around its paint, so an override is\n * simply the whole answer.\n */\nexport function resolvePalettePaint(\n palette: Fill[],\n override: Fill | undefined,\n index: number\n): Fill {\n if (override != null) return override\n if (palette.length === 0) return \"white\"\n return palette[index % palette.length]\n}\n\n// ---- Scales and formatting -----------------------------------------------\n\n\n/**\n * Format a marker value: integers plain, otherwise trimmed to one decimal, or to\n * as many as the axis's tick `step` needs to tell neighbouring ticks apart.\n *\n * One decimal is the floor, so a step of 0.1 or more reads exactly as it always\n * has; a finer step (a unit axis ticked every 0.05) gets two, instead of five\n * ticks captioned `0.1 0.1 0.2 0.2 0.3`. Trailing zeros are dropped either way.\n */\nexport function formatMarker(value: number, step?: number): string {\n if (Number.isInteger(value)) return String(value)\n const decimals = Math.max(1, step === undefined ? 1 : decimalsFor(step))\n return value.toFixed(decimals).replace(/(\\.\\d*?)0+$/, \"$1\").replace(/\\.$/, \"\")\n}\n\n/** Decimal places needed to write `step` exactly, capped at six. */\nfunction decimalsFor(step: number): number {\n if (!(step > 0) || !Number.isFinite(step)) return 1\n for (let d = 0; d <= 6; d++) {\n const scaled = step * 10 ** d\n if (Math.abs(scaled - Math.round(scaled)) < 1e-6 * Math.max(1, scaled)) return d\n }\n // An irrational-looking step (a third): as many places as separate the ticks.\n return Math.min(6, Math.max(1, Math.ceil(-Math.log10(step)) + 1))\n}\n\n/** The gap between neighbouring tick values, or `undefined` for fewer than two distinct ones. */\nexport function markerStep(markers: readonly number[]): number | undefined {\n const sorted = [...markers].filter(Number.isFinite).sort((a, b) => a - b)\n let step: number | undefined\n for (let i = 1; i < sorted.length; i++) {\n const gap = sorted[i] - sorted[i - 1]\n if (gap > 1e-12 && (step === undefined || gap < step)) step = gap\n }\n return step\n}\n\n/** Format a fraction in `[0, 1]` as a percentage: integers plain, else one decimal. */\nexport function formatPercent(fraction: number): string {\n const pct = fraction * 100\n if (Number.isInteger(pct)) return `${pct}%`\n return `${pct.toFixed(1).replace(/\\.0$/, \"\")}%`\n}\n\n/** `markerCount` evenly-spaced tick values across `[min, max]`, ends inclusive. */\nexport function markerValues([min, max]: Range, markerCount: number): number[] {\n const n = Math.max(2, Math.round(markerCount))\n return Array.from({ length: n + 1 }, (_, i) => min + ((max - min) / n) * i)\n}\n\n// Lifted into the engine, because a graph and a diagram want them too — see\n// `@motionscript/sdk/component`. Re-exported so a chart, and anything that\n// copied one, still reaches them where it always did.\nexport { niceStep, enterBudget } from \"@motionscript/sdk/component\"\n", "import { Rect, type ChildView, type Node2D, type Size2D } from \"@motionscript/sdk\"\n\nimport { VerticalAxis } from \"./vertical-axis\"\n\n/**\n * Headroom above the plot, in px.\n *\n * Two jobs, and the second is why it is real padding on the composition rather\n * than a number the point-mapping math imagines: a series peaking at the top of\n * the scale isn't flush to the top edge, **and** the top marker, which is\n * centred on that top grid line, has somewhere to be. Without it the marker's\n * upper half is drawn above the chart's own box.\n */\nexport const TOP_HEADROOM = 24\n\n/** The parts of a cartesian chart's frame, as {@link cartesianFrame} arranges them. */\nexport interface CartesianParts {\n /** The value axis, left of the plot. */\n readonly axis: Node2D\n /** The plot panel: the box the grid and the marks share. */\n readonly plot: Node2D\n /** An invisible twin of the value axis, reserving its gutter under the plot. */\n readonly gutter: Node2D\n /** What sits under the plot, top to bottom: the other axis, then the legend. */\n readonly below: readonly Node2D[]\n}\n\n/**\n * The frame the line and bar charts share: the value axis beside the plot, and\n * under them the gutter beside the rows below the plot, so those rows start at\n * the plot's left edge rather than the chart's.\n */\nexport function cartesianFrame(parts: CartesianParts): Node2D {\n return new Rect({\n flow: \"vertical\",\n width: \"fill\",\n height: \"fill\",\n padding: { top: TOP_HEADROOM },\n children: [\n new Rect({ flow: \"horizontal\", height: \"fill\", width: \"fill\", children: [parts.axis, parts.plot] }),\n new Rect({\n flow: \"horizontal\",\n width: \"fill\",\n children: [parts.gutter, new Rect({ flow: \"vertical\", width: \"fill\", gap: 20, children: [...parts.below] })],\n }),\n ],\n }) as unknown as Node2D\n}\n\n/** A cartesian frame's parts, as a command reaches them through its chart's children. */\nexport interface CartesianViews {\n readonly axis: ChildView\n /** The plot panel's own children: the grid, the marks, the border. */\n readonly plot: readonly ChildView[]\n readonly below: readonly ChildView[]\n}\n\n/**\n * The frame among a chart's children: the last child shaped as\n * {@link cartesianFrame} builds it. The chart builds it after the children it\n * was given, and a document adds its own later still, so it is found by shape.\n */\nexport function cartesianViews(children: readonly ChildView[]): CartesianViews | null {\n for (let i = children.length - 1; i >= 0; i--) {\n const frame = children[i]\n if (!Rect.is(frame)) continue\n const [top, bottom] = frame.children\n const axis = top?.children[0]\n const plot = top?.children[1]\n const below = bottom?.children[1]\n if (!axis || !VerticalAxis.is(axis) || !plot || !below) continue\n return { axis, plot: plot.children, below: below.children }\n }\n return null\n}\n\n/** A part's laid-out size, or nothing before it is built or laid out. */\nexport function laidOutSize(node: Node2D | undefined): Size2D {\n const bounds = node?.layoutBounds\n return { width: bounds?.width ?? 0, height: bounds?.height ?? 0 }\n}\n", "import {\n Rect,\n RotatedBox,\n Text,\n Types,\n component2d,\n insetsOps,\n textOps,\n type NodeOf,\n type Node2D,\n type Node2DProps,\n} from \"@motionscript/sdk\"\n\nimport { asParts, fresh } from \"./entries\"\nimport { armed, arrival, arrivalOf, arrivalsEntry, beats, frameEase, type Arrival } from \"./motion\"\nimport {\n DEFAULT_Y_AXIS,\n enterBudget,\n formatMarker,\n type AxisConfig,\n type Range,\n} from \"./shared\"\n\nexport interface VerticalAxisProps extends Node2DProps {\n /** `[min, max]` of the vertical scale the markers are positioned within. */\n range: Range\n /**\n * Tick values (in data units) to draw up the axis, each placed by its fraction\n * across {@link VerticalAxisProps.range}. Need not be evenly spaced or include\n * the ends.\n */\n markers: number[]\n /**\n * How each marker is captioned, one per entry of `markers` and in its order.\n * Empty (the default), or short, captions a marker with its bare numeric\n * reading; a chart with a number format on this axis writes them through it.\n */\n captions: string[]\n /** Marker/caption text style, grid stroke, and gutters — see {@link AxisConfig}. */\n axis: AxisConfig\n /**\n * Rotated caption drawn in the gutter to the left of the marker column. Empty\n * string (the default) hides it — no caption node is built and no label gutter\n * is reserved.\n */\n label: string\n}\n\n/** How far a marker starts to the right of its slot when it enters, in px. */\nconst SLIDE = 24\n\n/** How a tick value is captioned — see {@link VerticalAxisProps.captions}. */\nexport type MarkerLabel = (value: number) => string\n\n/** What a marker's caption reads: the one listed for its value, else its bare reading. */\nexport function markerCaption(s: { readonly markers: readonly number[]; readonly captions: readonly string[] }, value: number): string {\n const index = s.markers.indexOf(value)\n return (index >= 0 ? s.captions[index] : undefined) ?? formatMarker(value)\n}\n\n/**\n * The numeric vertical axis shared by the cartesian charts: a **column of\n * {@link Text} nodes**, one per marker value, running top-to-bottom (highest\n * value at the top). Pure layout — no `Graphics` — so the markers are real text\n * nodes the scene can measure, restyle, or animate individually.\n *\n * Each marker is positioned so its centre lands exactly on its value's fraction\n * across `range` within the axis's filled height, so unevenly-spaced markers\n * land where their values fall. Both the caption and the position are *bound*,\n * not snapshotted: a chart that rescales its axes (see `LineChart.zoomTo`)\n * tweens `range`/`markers` live. Only the marker **count** is fixed at\n * construction.\n *\n * `enter` staggers them in **bottom-to-top**: each marker starts pushed a\n * little to the right and transparent, then fades and slides left into place.\n * The resting state is the landed one, so a chart that is never told to enter\n * still reads as a finished chart.\n */\nexport const VerticalAxis = component2d({\n key: \"verticalAxis\",\n state: {\n range: fresh<Range>(() => [0, 1]),\n markers: fresh<number[]>(() => []),\n captions: fresh<string[]>(() => []),\n axis: Types.custom<AxisConfig>(DEFAULT_Y_AXIS),\n label: \"\",\n arrivals: arrivalsEntry(),\n },\n // A plain node filled its parent; one made of its markers would hug them.\n defaults: { width: \"fill\", height: \"fill\" },\n children: (state) => {\n // Composed from plain entries (range/markers/label), so it's built once here.\n const tickPad = insetsOps.resolve(state.axis.tickPadding).right\n const titlePad = insetsOps.resolve(state.axis.titlePadding).right\n\n const row: Node2D[] = []\n // The row's parent is the axis: its box is what the markers are placed in.\n const box = () => (row[0]?.parent as Node2D | null | undefined)?.layoutBounds ?? { width: 0, height: 0 }\n /** The live tick values, top → bottom (highest first) — re-read every frame. */\n const sorted = () => [...state.markers].sort((a, b) => b - a)\n /** Tick `i`'s fraction across the live `range`, 0 at the bottom edge. */\n const fracAt = (value: number | undefined) => {\n if (value === undefined) return 0\n const [min, max] = state.range\n return max <= min ? 0 : (value - min) / (max - min)\n }\n\n // One text node per marker, ordered top → bottom. A slot with no value (the\n // live list is shorter than the column built for it) renders as empty text\n // rather than repeating its neighbour.\n const markers = state.markers.map((_, i) => {\n const marker: Node2D = new Text({\n ...textOps.styleProps(state.axis.labelStyle),\n text: () => {\n const value = sorted()[i]\n return value === undefined ? \"\" : markerCaption(state, value)\n },\n y: () => {\n // Node2D space is y-up, so the fraction runs from the bottom.\n const height = box().height\n const centred = (fracAt(sorted()[i]) - 0.5) * height\n // Held inside the axis's top edge — the backstop for a chart whose\n // headroom is smaller than its marker text is tall, which a theme with\n // much larger markers can arrange. Only the top, because what lies\n // below the axis is the chart's own horizontal axis and legend.\n const limit = height / 2 - marker.layoutBounds.height / 2\n return Math.min(centred, limit)\n },\n opacity: () => arrivalOf(state.arrivals, i).opacity,\n x: () => arrivalOf(state.arrivals, i).shift,\n })\n return marker\n })\n\n const children: Node2D[] = []\n if (state.label !== \"\") {\n // Node2D space is y-up and rotation is clockwise, so -90° reads bottom-to-top.\n children.push(\n new RotatedBox({\n angle: -90,\n width: \"hug\",\n height: \"hug\",\n children: new Text({\n ...textOps.styleProps(state.axis.titleStyle),\n text: state.label,\n opacity: () => arrivalOf(state.arrivals, \"label\").opacity,\n x: () => arrivalOf(state.arrivals, \"label\").shift,\n }),\n })\n )\n }\n children.push(new Rect({ height: \"fill\", width: \"hug\", padding: { right: tickPad }, children: markers }))\n row.push(new Rect({ flow: \"horizontal\", gap: titlePad, children }))\n return asParts(row)\n },\n commands: {\n /**\n * Stagger the markers in bottom to top, then slide the caption in from the\n * right after them. Its first frame arms them all: shifted right by `slide`\n * and transparent.\n *\n * The timeline's duration is the **whole** entrance, not one marker's slide:\n * the stagger and the caption are carved out of it rather than added on top.\n * See {@link enterBudget} for why that distinction matters here.\n *\n * `stagger` is seconds between successive markers (derived when omitted);\n * `slide` is the starting rightward offset in px.\n */\n enter: {\n args: {\n stagger: Types.custom<number | undefined>(undefined),\n slide: Types.number(SLIDE),\n },\n run: (timeline, state) => {\n const { stagger, slide } = timeline.args\n const count = state.markers.length\n const captioned = state.label !== \"\"\n const from: Arrival = { opacity: 0, shift: slide }\n const keys = [...state.markers.keys(), ...(captioned ? [\"label\"] : [])]\n const arm = timeline.animate(() => ({ arrivals: armed(keys, from) }))\n if (count === 0) return arm\n const { step, per, caption } = enterBudget(timeline.duration, count, captioned, stagger)\n const ease = frameEase(timeline)\n // Bottom marker leads: the column is top → bottom, so walk it in reverse.\n const markers = state.markers.map((_, i) => ({ at: (count - 1 - i) * step, duration: per, piece: arrival(timeline, i, from, ease) }))\n // Once every marker has landed, the caption slides in from the right.\n const label = captioned ? [{ at: (count - 1) * step + per, duration: caption, piece: arrival(timeline, \"label\", from, ease) }] : []\n return timeline.together([arm, beats(timeline, [...markers, ...label])])\n },\n },\n },\n})\n\nexport type VerticalAxis = NodeOf<typeof VerticalAxis>\n", "import { Types, type Element, type Node2D, type Type } from \"@motionscript/sdk\"\n\n/**\n * An entry made fresh for every node: each node gets its own array or box\n * rather than one shared literal, and a host is told no default for it.\n */\nexport function fresh<T, In = T>(make: () => T, options?: { readonly resolve?: (value: In) => T; readonly kind?: string }): Type<In, T> {\n // A function default is a factory: the component calls it once per node.\n return Types.custom<In, T>(make as unknown as In, options)\n}\n\n/**\n * Nodes a `children` builder made with `new`, as the elements it returns. A\n * part built that way can be read in a binding — its own box, or its parent's,\n * which is the component it was built for — where a call would hand back only\n * the element.\n */\nexport function asParts(nodes: readonly Node2D[]): readonly Element[] {\n return nodes as unknown as readonly Element[]\n}\n", "import { Types, easeOut, type EasingFunction, type Piece, type Timeline } from \"@motionscript/sdk\"\n\nconst identity: EasingFunction = (t) => t\n\n/** Any component's timeline: these helpers only build pieces, which every timeline builds alike. */\ntype AnyTimeline = Timeline<any, any>\n\n/**\n * The ease a part's own frames apply to `t`: none when its command was given\n * one, which already eases every frame the command builds, and otherwise the\n * ease-out every chart command defaults to.\n */\nexport function frameEase(timeline: { readonly easing: EasingFunction | undefined }): EasingFunction {\n return timeline.easing ? identity : easeOut()\n}\n\n/** A piece of a command placed at its own time: from `at` seconds, for `duration` seconds. */\nexport interface Beat {\n readonly at: number\n readonly duration: number\n readonly piece: Piece\n}\n\n/**\n * `beats` at their own offsets over the command, each eased on its own and held\n * at its last frame once it is done. A beat ahead of the playhead writes nothing,\n * so whatever stands before it is written by a piece ahead of these. Beats that\n * run past the command are played faster to end with it.\n */\nexport function beats(timeline: AnyTimeline, parts: readonly Beat[]): Piece {\n const total = timeline.duration\n const natural = parts.reduce((end, part) => Math.max(end, part.at + part.duration), 0)\n const k = natural > total && natural > 0 ? total / natural : 1\n return timeline.together(\n parts.map(({ at, duration, piece }) => {\n const start = at * k\n const length = duration * k\n return timeline.sequence([timeline.wait(start), piece, timeline.wait(Math.max(0, total - start - length))])\n })\n )\n}\n\n/** How far one piece of a staggered entrance has come: its opacity, and how far it still sits off its place. */\nexport interface Arrival {\n readonly opacity: number\n readonly shift: number\n}\n\n/** Each piece's arrival, by key. An unlisted piece has landed. */\nexport type Arrivals = Readonly<Record<string, Arrival>>\n\nexport const LANDED: Arrival = { opacity: 1, shift: 0 }\n\n/**\n * A part's private record of its pieces' arrivals. A write merges into it, so\n * beats placed apart each write their own piece and leave the others as the\n * frame left them.\n */\nexport function arrivalsEntry() {\n return Types.custom<Arrivals>({}, { private: true, resolve: (next: Arrivals, previous?: Arrivals) => ({ ...previous, ...next }) })\n}\n\nexport function arrivalOf(arrivals: Arrivals, key: string | number): Arrival {\n return arrivals[key] ?? LANDED\n}\n\n/** Every piece in `keys` armed at `from`: the first frame of their entrance. */\nexport function armed(keys: readonly (string | number)[], from: Arrival): Arrivals {\n const record: Record<string, Arrival> = {}\n for (const key of keys) record[key] = from\n return record\n}\n\n/**\n * A piece arriving from `from` over its beat: a part armed at `from` tweened to\n * `{ opacity: 1, [axis]: 0 }`, eased by `ease`.\n */\nexport function arrival(timeline: AnyTimeline, key: string | number, from: Arrival, ease: EasingFunction): Piece {\n return timeline.animate((t) => {\n const e = ease(t)\n return {\n arrivals: {\n [key]: {\n opacity: from.opacity + (LANDED.opacity - from.opacity) * e,\n shift: from.shift + (LANDED.shift - from.shift) * e,\n },\n },\n }\n })\n}\n", "import {\n Graphics2D,\n Types,\n component2d,\n strokeOps,\n type NodeOf,\n // Named so this component's emitted type reaches `Node2D` through the sdk, not core.\n type Node2D as _Node2D,\n type Node2DProps,\n type Stroke,\n type StrokeResolved,\n} from \"@motionscript/sdk\"\n\nimport { loadPaints } from \"./paints\"\nimport { DEFAULT_PLOT_AREA } from \"./shared\"\n\nexport interface ChartBorderProps extends Node2DProps {\n /**\n * The plot's thick frame stroke. The stroke resolver's default `align` is\n * `'inside'`, so the whole weight sits within the layout box unless the theme\n * overrides it.\n */\n stroke: Stroke\n}\n\n/**\n * The thick **frame** around a cartesian chart's plot: an empty rect wearing an\n * inside stroke, sized from its box.\n *\n * Split out of {@link ChartCanvas} (the filled + gridded backdrop) so it can be\n * placed *after* the marks in the tree — the box then frames the plot **over**\n * them, so a line or a column running to the edge tucks cleanly under the border\n * rather than sitting on top of it.\n */\nexport const ChartBorder = component2d({\n key: \"chartBorder\",\n state: {\n stroke: Types.custom<Stroke, StrokeResolved[]>(DEFAULT_PLOT_AREA.stroke, { resolve: strokeOps.resolve, lerp: strokeOps.lerp }),\n },\n load: (loader, state) => loadPaints(loader, { strokes: [state.stroke] }),\n render: (ctx, state) => {\n const { width, height } = ctx.size\n if (width <= 0 || height <= 0) return\n // Empty rect (no fill) with the themed stroke, so the frame sits over the\n // marks but the box interior stays clear.\n ctx.draw(new Graphics2D().rect({ x: 0, y: 0, width, height }).stroke(state.stroke))\n },\n})\n\nexport type ChartBorder = NodeOf<typeof ChartBorder>\n", "import type { FillResolved, Loader, ShadowResolved, StrokeResolved } from \"@motionscript/sdk\"\n\n/** Paints a chart part holds in entries of its own, which no paint entry loads for it. */\nexport interface PartPaints {\n readonly fills?: readonly (readonly FillResolved[])[]\n readonly strokes?: readonly (readonly StrokeResolved[])[]\n readonly shadows?: readonly (readonly ShadowResolved[])[]\n}\n\n/** Declare `paints` from a component's `load`. */\nexport function loadPaints(loader: Loader, paints: PartPaints): void {\n for (const fill of paints.fills ?? []) loader.fill(fill)\n for (const strokes of paints.strokes ?? []) for (const stroke of strokes) loader.fill(stroke.fill)\n for (const shadows of paints.shadows ?? []) for (const shadow of shadows) loader.fill(shadow.fill)\n}\n", "import {\n Graphics2D,\n Types,\n component2d,\n fillOps,\n shadowOps,\n strokeOps,\n type Fill,\n type FillResolved,\n type NodeOf,\n // Named so this component's emitted type reaches `Node2D` through the sdk, not core.\n type Node2D as _Node2D,\n type Node2DProps,\n type Shadow,\n type ShadowResolved,\n type Stroke,\n type StrokeResolved,\n} from \"@motionscript/sdk\"\n\nimport { fresh } from \"./entries\"\nimport { loadPaints } from \"./paints\"\nimport {\n DEFAULT_PLOT_AREA,\n DEFAULT_X_AXIS,\n DEFAULT_Y_AXIS,\n type Range,\n} from \"./shared\"\n\nexport interface ChartCanvasProps extends Node2DProps {\n /** Fill of the plot panel behind the marks. */\n fill: Fill\n /** Drop shadow of the panel. Default none. */\n shadow: Shadow\n /** Stroke of the vertical grid lines (one per {@link xMarkers}). */\n xGridStroke: Stroke\n /** Stroke of the horizontal grid lines (one per {@link yMarkers}). */\n yGridStroke: Stroke\n /**\n * Data-unit x positions to draw a vertical grid line at — one per horizontal\n * axis marker, so a line lands under every marker regardless of spacing.\n * Positions at (or past) an {@link xExtent} edge coincide with the border and\n * are skipped. Pass an empty list for a chart whose horizontal axis is\n * categorical and so has no numeric position to rule at.\n */\n xMarkers: number[]\n /** Data-unit y positions to draw a horizontal grid line at. */\n yMarkers: number[]\n /** `[min, max]` of the horizontal scale — maps {@link xMarkers} into the panel. */\n xExtent: Range\n /** `[min, max]` of the vertical scale — maps {@link yMarkers} into the panel. */\n yExtent: Range\n}\n\nconst strokeEntry = (initial: Stroke) =>\n Types.custom<Stroke, StrokeResolved[]>(initial, { resolve: strokeOps.resolve, lerp: strokeOps.lerp })\n\n/**\n * The plot **backdrop** of a cartesian chart: a filled panel with a grid of\n * faint lines spanning both directions across it, sized from its box and centred\n * on its origin.\n *\n * The thick frame is a **separate** {@link ChartBorder} node so it can be drawn\n * *over* the marks while this panel sits under them. Grid lines are placed from\n * the axis marker positions (in data units) mapped into the panel through\n * {@link ChartCanvasProps.xExtent}/`yExtent` — so each line lands under its\n * marker whether or not the markers are evenly spaced.\n */\nexport const ChartCanvas = component2d({\n key: \"chartCanvas\",\n state: {\n fill: Types.custom<Fill, FillResolved[]>(DEFAULT_PLOT_AREA.fill, { resolve: fillOps.resolve, lerp: fillOps.lerp }),\n shadow: Types.custom<Shadow, ShadowResolved[]>(DEFAULT_PLOT_AREA.shadow, { resolve: shadowOps.resolve, lerp: shadowOps.lerp }),\n xGridStroke: strokeEntry(DEFAULT_X_AXIS.lineStyle),\n yGridStroke: strokeEntry(DEFAULT_Y_AXIS.lineStyle),\n xMarkers: fresh<number[]>(() => []),\n yMarkers: fresh<number[]>(() => []),\n xExtent: fresh<Range>(() => [0, 1]),\n yExtent: fresh<Range>(() => [0, 1]),\n },\n // The grid strokes are named past the conventional slots, so they are named here.\n load: (loader, state) =>\n loadPaints(loader, { fills: [state.fill], shadows: [state.shadow], strokes: [state.xGridStroke, state.yGridStroke] }),\n render: (ctx, state) => {\n const { width: W, height: H } = ctx.size\n if (W <= 0 || H <= 0) return\n\n // Plot panel, centred on the origin (node space is y-up, origin centre).\n ctx.draw(new Graphics2D().rect({ x: 0, y: 0, width: W, height: H }).shadow(state.shadow).fill(state.fill))\n\n const [xMin, xMax] = state.xExtent\n const [yMin, yMax] = state.yExtent\n // Fraction of a marker across its extent; guard a zero-width extent.\n const xFrac = (v: number) => (xMax <= xMin ? 0 : (v - xMin) / (xMax - xMin))\n const yFrac = (v: number) => (yMax <= yMin ? 0 : (v - yMin) / (yMax - yMin))\n // Skip markers landing on (or outside) the edges — they'd sit under the border.\n const interior = (f: number) => f > 1e-6 && f < 1 - 1e-6\n\n const xStroke = state.xGridStroke[0]\n if (xStroke) {\n const xGrid = new Graphics2D()\n for (const v of state.xMarkers) {\n const f = xFrac(v)\n if (!interior(f)) continue\n xGrid.rect({ x: -W / 2 + f * W, y: 0, width: xStroke.weight, height: H })\n }\n ctx.draw(xGrid.fill(xStroke.fill))\n }\n\n const yStroke = state.yGridStroke[0]\n if (yStroke) {\n const yGrid = new Graphics2D()\n for (const v of state.yMarkers) {\n const f = yFrac(v)\n if (!interior(f)) continue\n yGrid.rect({ x: 0, y: -H / 2 + f * H, width: W, height: yStroke.weight })\n }\n ctx.draw(yGrid.fill(yStroke.fill))\n }\n },\n})\n\nexport type ChartCanvas = NodeOf<typeof ChartCanvas>\n", "import {\n Flow,\n Paint,\n Rect,\n Shapes,\n Text,\n Types,\n component2d,\n textOps,\n type Fill,\n type NodeOf,\n type RectProps,\n // Named so the row's emitted type reaches the Rect surface it spreads through the sdk, not core.\n type Alignment as _Alignment,\n type CornerRadiusResolved as _CornerRadiusResolved,\n type CornerStyleResolved as _CornerStyleResolved,\n type FillResolved as _FillResolved,\n type FlowMode as _FlowMode,\n type FlowResolved as _FlowResolved,\n type GapSize as _GapSize,\n type Node2D as _Node2D,\n type Node2DProps as _Node2DProps,\n type RectCornerRadius as _RectCornerRadius,\n type RectCornerStyle as _RectCornerStyle,\n type Shadow as _Shadow,\n type ShadowResolved as _ShadowResolved,\n type Stroke as _Stroke,\n type StrokeResolved as _StrokeResolved,\n type Vector2 as _Vector2,\n} from \"@motionscript/sdk\"\n\nimport { fresh } from \"./entries\"\nimport { frameEase } from \"./motion\"\nimport {\n DEFAULT_LEGEND,\n SPOTLIGHT_DIM,\n type ChartSeries,\n type LegendConfig,\n} from \"./shared\"\n\nexport interface ChartLegendProps extends RectProps {\n /**\n * One entry per series: legend `label`, its `enabled` default, and — through\n * {@link ChartLegendProps.swatches} — the colour its chip is painted. A series\n * that starts enabled (the default) is added to the row up front; one that\n * starts `false` is hidden until a later `showSeries`.\n */\n series: ChartSeries[]\n /**\n * The swatch colour for each series, by index — resolved by the chart, whose\n * business it is whether a series' colour comes out of a stroke palette (a\n * line) or a fill palette (a bar). Shorter than the series list means the\n * missing entries fall back to white.\n */\n swatches: Fill[]\n /** Padding, caption style, gaps, and swatch geometry — see {@link LegendConfig}. */\n legend: LegendConfig\n}\n\n/** A row's entries are a `Rect`'s: paint, the flow of its children, its corners. */\nconst row = { ...Paint.state, ...Flow.state, ...Shapes.corners }\n\n/**\n * One legend entry. It hugs its caption and swatch; `shown` scales that width\n * from nothing to the whole of it.\n *\n * The width is taken from the content on every measure, at any reveal, so a frame\n * never depends on whether the entry was once seen fully shown. A collapse needs a\n * number to scale, and `\"hug\"` is not one until something measures it — this is\n * the something.\n */\nconst LegendEntry = component2d({\n key: \"legendEntry\",\n state: { ...row, shown: Types.number(1) },\n commands: { ...Paint.commands },\n measure: (measurer, state, children) => {\n const size = Flow.measure(measurer, state, children, Paint.inset(state))\n return state.shown >= 1 ? size : { ...size, width: state.shown * size.width }\n },\n layout: (box, state, children) => Flow.layout(box, state, children, Paint.inset(state)),\n render: (ctx, state) => Paint.draw(ctx, state, Shapes.rect(ctx.size, state)),\n})\n\n/**\n * How far each entry is shown, written whole (a document, a `set`) or one\n * entry at a time (a command, as `{ [index]: reveal }`), which leaves the others\n * as the frame left them — so two series moving at once each move their own.\n */\nfunction revealOf(value: readonly number[] | Readonly<Record<number, number>>, previous?: number[]): number[] {\n if (Array.isArray(value)) return value as number[]\n const next = [...(previous ?? [])]\n for (const [index, reveal] of Object.entries(value)) next[Number(index)] = reveal\n return next\n}\n\n/**\n * The legend of a chart: a **horizontal-flow row of entries**, one per series, laid out\n * left-to-right with the theme's `itemGap`. Each entry pairs the series label\n * with a rounded colour swatch; only the swatch carries the series colour, the\n * caption reads in the legend's neutral ink.\n *\n * `showSeries`/`hideSeries` flip a series on or off — showing one grows its\n * entry back in at its stable series position, hiding one shrinks it away. So\n * the row only ever shows the currently-enabled series, in series order, and\n * closes the gap when one leaves.\n *\n * This node *is* the row, so the parent places it (centred below the chart) and\n * it hugs its entries.\n */\nexport const ChartLegend = component2d({\n key: \"chartLegend\",\n state: {\n ...row,\n series: fresh<ChartSeries[]>(() => []),\n swatches: fresh<Fill[]>(() => []),\n legend: Types.custom<LegendConfig>(DEFAULT_LEGEND),\n /**\n * How far each entry is shown, `0`–`1`. Drives its width, opacity and gap\n * together, so `0` is an entry that takes no room and `1` is one at its\n * natural size.\n *\n * This replaces adding and removing the entry from the row: a command is\n * asked what it looks like at a time, and \"is this node a child\" is not a\n * value a time can produce. Collapsed-but-present is the same picture reached\n * by a route that *is* a function of `t`.\n */\n reveal: fresh<number[], number[] | Readonly<Record<number, number>>>(() => [], { resolve: revealOf }),\n },\n // This node *is* the row, so the direction is its own answer. It has to be\n // stated — a `Rect` given no flow lays its children out `freeform`, which\n // stacks every entry on the same spot. The gap and padding are the theme's.\n defaults: {\n flow: \"horizontal\",\n width: \"hug\",\n height: \"hug\",\n gap: (state) => state.legend.itemGap,\n padding: (state) => state.legend.padding,\n reveal: (state) => state.series.map((s) => ((s.enabled ?? true) ? 1 : 0)),\n },\n // One entry per series, in series order, every one a child for good: order is\n // fixed rather than depending on which siblings happen to be shown, so an entry\n // always comes back where it belongs.\n children: (state) => {\n const marker = state.legend.markerStyle\n return state.series.map((series, index) =>\n LegendEntry({\n flow: \"horizontal\",\n gap: 12,\n align: \"center\",\n width: \"hug\",\n height: \"hug\",\n // Bound to the reveal, so showing and hiding is a number moving rather\n // than a child arriving and leaving. The width follows it in `measure`,\n // and the flanking gap closes with the entry rather than snapping.\n opacity: () => state.reveal[index] ?? 0,\n gapScale: () => state.reveal[index] ?? 0,\n shown: () => state.reveal[index] ?? 0,\n children: [\n Text({ ...textOps.styleProps(state.legend.textStyle), text: series.label }),\n Rect({\n width: marker.width,\n height: marker.height,\n cornerRadius: marker.borderRadius,\n fill: state.swatches[index] ?? \"white\",\n stroke: marker.stroke,\n shadow: marker.shadow,\n }),\n ],\n })\n )\n },\n commands: {\n ...Paint.commands,\n /**\n * Grow series `index`'s entry back in at its series-order position, the\n * siblings sliding over to make room. A reveal tween rather than an animated\n * `addChildAt`: the entry never left, so the whole thing is a function of `t`.\n */\n showSeries: {\n args: { index: Types.number(0, { min: 0, step: 1 }) },\n // An index that is not a series takes its slot and moves nothing.\n run: (timeline, state) => (timeline.args.index in state.series\n ? timeline.animate(revealFrame(state, timeline.args.index, 1, frameEase(timeline)))\n : timeline.wait(timeline.duration)),\n },\n /** Shrink series `index`'s entry away, the gap closing behind it — the mirror of `showSeries`. */\n hideSeries: {\n args: { index: Types.number(0, { min: 0, step: 1 }) },\n run: (timeline, state) => (timeline.args.index in state.series\n ? timeline.animate(revealFrame(state, timeline.args.index, 0, frameEase(timeline)))\n : timeline.wait(timeline.duration)),\n },\n /**\n * Dim every entry but series `index` to {@link SPOTLIGHT_DIM} and bring that\n * one back to full — the legend half of a chart's `spotlightSeries`. Entries\n * stay in place; only their opacity moves, so the row doesn't reflow. Only\n * the entries shown when it is built are touched: a hidden series' entry is\n * left as `hideSeries` left it.\n */\n spotlightSeries: {\n args: { index: Types.number(0, { min: 0, step: 1 }) },\n run: (timeline, state, children) =>\n timeline.together(\n children.flatMap((entry, i) =>\n (state.reveal[i] ?? 0) > 0 ? [entry.to({ opacity: i === timeline.args.index ? 1 : SPOTLIGHT_DIM })] : []\n )\n ),\n },\n },\n measure: (measurer, state, children) => Flow.measure(measurer, state, children, Paint.inset(state)),\n layout: (box, state, children) => Flow.layout(box, state, children, Paint.inset(state)),\n render: (ctx, state) => Paint.draw(ctx, state, Shapes.rect(ctx.size, state)),\n})\n\n/**\n * One entry's reveal ramping to `target` from where the command finds it — so a\n * hide that follows a show starts where the show left it.\n */\nfunction revealFrame(state: { readonly reveal: readonly number[] }, index: number, target: number, ease: (t: number) => number) {\n const from = state.reveal[index] ?? 0\n return (t: number) => ({ reveal: { [index]: from + (target - from) * ease(t) } })\n}\n\n/** Whether series `index` is showing at all on `legend`. */\nexport function legendShows(legend: { readonly reveal: readonly number[] }, index: number): boolean {\n return (legend.reveal[index] ?? 0) > 0\n}\n\nexport type ChartLegend = NodeOf<typeof ChartLegend>\n", "/**\n * The chart **kit**: everything the three charts share, and the one thing a\n * copied chart does not copy.\n *\n * A copy of the line chart takes `line-chart/*` into your project and rewrites its\n * reach for these to `@motionscript/charts`, so the plot panel, the value\n * axis, the legend and the number formatting stay a real dependency. That is\n * not a size decision — it is the only arrangement that works.\n *\n * A chart identifies its own parts by component identity (`VerticalAxis.is`).\n * Copy `VerticalAxis` alongside your fork and there are now two of it — two\n * components answering one name, and whichever one your chart did not get is\n * a part it never finds, with no error. Keeping the kit external makes that\n * impossible rather than unlikely.\n *\n * It also means a fix to the axis reaches a forked chart without a re-add,\n * which is the half of the bargain you get back for it.\n */\nexport * from \"./kit/shared\"\nexport * from \"./kit/cartesian\"\nexport * from \"./kit/chart-border\"\nexport * from \"./kit/chart-canvas\"\nexport * from \"./kit/chart-legend\"\nexport * from \"./kit/entries\"\nexport * from \"./kit/motion\"\nexport * from \"./kit/paints\"\nexport * from \"./kit/vertical-axis\"\nexport * from \"@motionscript/sdk/component\"\n"],
|
|
5
|
-
"mappings": "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",
|
|
6
|
-
"names": ["fillOps", "lerpNumber", "shadowOps", "strokeOps", "insetsOps", "textOps", "niceStep", "enterBudget", "resolveAxisDomain", "domain", "previous", "lerpAxisDomain", "from", "to", "t", "lerpOptionalRange", "lerpOptionalTicks", "out", "i", "axisTweenTarget", "drawn", "requested", "target", "count", "markerValues", "blendOf", "lerpAxisEntry", "rangeMoved", "blended", "moved", "auto", "settleAxisDomain", "blend", "CHART_PALETTE", "DEFAULT_SERIES_COLORS", "SPOTLIGHT_DIM", "clampUnit", "value", "num", "row", "field", "v", "text", "numericFields", "data", "exclude", "skip", "seen", "order", "key", "sawValue", "AXIS_LABEL_STYLE", "AXIS_TITLE_STYLE", "AXIS_LINE_STYLE", "DEFAULT_X_AXIS", "DEFAULT_Y_AXIS", "DEFAULT_PLOT_AREA", "DEFAULT_LEGEND", "DEFAULT_SERIES_STROKES", "fill", "DEFAULT_SERIES_FILLS", "resolveAxisConfig", "axis", "lerpAxisConfig", "resolvePlotArea", "plotArea", "lerpPlotArea", "resolveLegendMarkerConfig", "marker", "lerpLegendMarkerConfig", "resolveLegendConfig", "legend", "lerpLegendConfig", "resolveSeriesStrokes", "styles", "s", "lerpSeriesStrokes", "a", "b", "resolveSeriesFills", "fills", "f", "lerpSeriesFills", "resolveSeriesStroke", "palette", "series", "index", "entry", "layers", "next", "resolveSeriesFill", "resolvePalettePaint", "override", "formatMarker", "step", "decimals", "decimalsFor", "d", "scaled", "markerStep", "markers", "sorted", "gap", "formatPercent", "fraction", "pct", "min", "max", "markerCount", "_", "Rect", "Rect", "RotatedBox", "Text", "Types", "component2d", "insetsOps", "textOps", "Types", "fresh", "make", "options", "asParts", "nodes", "Types", "easeOut", "identity", "t", "frameEase", "timeline", "beats", "parts", "total", "natural", "end", "part", "k", "at", "duration", "piece", "start", "length", "LANDED", "arrivalsEntry", "next", "previous", "arrivalOf", "arrivals", "key", "armed", "keys", "from", "record", "arrival", "ease", "e", "SLIDE", "markerCaption", "s", "value", "index", "formatMarker", "VerticalAxis", "component2d", "fresh", "Types", "DEFAULT_Y_AXIS", "arrivalsEntry", "state", "tickPad", "insetsOps", "titlePad", "row", "box", "sorted", "a", "b", "fracAt", "min", "max", "markers", "_", "i", "marker", "Text", "textOps", "height", "centred", "limit", "arrivalOf", "children", "RotatedBox", "Rect", "timeline", "stagger", "slide", "count", "captioned", "from", "keys", "arm", "armed", "step", "per", "caption", "enterBudget", "ease", "frameEase", "arrival", "label", "beats", "TOP_HEADROOM", "cartesianFrame", "parts", "Rect", "cartesianViews", "children", "i", "frame", "top", "bottom", "axis", "plot", "below", "VerticalAxis", "laidOutSize", "node", "bounds", "Graphics2D", "Types", "component2d", "strokeOps", "loadPaints", "loader", "paints", "fill", "strokes", "stroke", "shadows", "shadow", "ChartBorder", "component2d", "Types", "DEFAULT_PLOT_AREA", "strokeOps", "loader", "state", "loadPaints", "ctx", "width", "height", "Graphics2D", "Graphics2D", "Types", "component2d", "fillOps", "shadowOps", "strokeOps", "strokeEntry", "initial", "Types", "strokeOps", "ChartCanvas", "component2d", "DEFAULT_PLOT_AREA", "fillOps", "shadowOps", "DEFAULT_X_AXIS", "DEFAULT_Y_AXIS", "fresh", "loader", "state", "loadPaints", "ctx", "W", "H", "Graphics2D", "xMin", "xMax", "yMin", "yMax", "xFrac", "v", "yFrac", "interior", "f", "xStroke", "xGrid", "yStroke", "yGrid", "Flow", "Paint", "Rect", "Shapes", "Text", "Types", "component2d", "textOps", "row", "Paint", "Flow", "Shapes", "LegendEntry", "component2d", "Types", "measurer", "state", "children", "size", "box", "ctx", "revealOf", "value", "previous", "next", "index", "reveal", "ChartLegend", "fresh", "DEFAULT_LEGEND", "s", "marker", "series", "Text", "textOps", "Rect", "timeline", "revealFrame", "frameEase", "entry", "SPOTLIGHT_DIM", "target", "ease", "from", "t", "legendShows", "legend"]
|
|
7
|
-
}
|
|
@@ -1,27 +0,0 @@
|
|
|
1
|
-
import { type NodeOf, type Node2D as _Node2D, type Node2DProps, type Stroke, type StrokeResolved } from "@motionscript/sdk";
|
|
2
|
-
export interface ChartBorderProps extends Node2DProps {
|
|
3
|
-
/**
|
|
4
|
-
* The plot's thick frame stroke. The stroke resolver's default `align` is
|
|
5
|
-
* `'inside'`, so the whole weight sits within the layout box unless the theme
|
|
6
|
-
* overrides it.
|
|
7
|
-
*/
|
|
8
|
-
stroke: Stroke;
|
|
9
|
-
}
|
|
10
|
-
/**
|
|
11
|
-
* The thick **frame** around a cartesian chart's plot: an empty rect wearing an
|
|
12
|
-
* inside stroke, sized from its box.
|
|
13
|
-
*
|
|
14
|
-
* Split out of {@link ChartCanvas} (the filled + gridded backdrop) so it can be
|
|
15
|
-
* placed *after* the marks in the tree — the box then frames the plot **over**
|
|
16
|
-
* them, so a line or a column running to the edge tucks cleanly under the border
|
|
17
|
-
* rather than sitting on top of it.
|
|
18
|
-
*/
|
|
19
|
-
export declare const ChartBorder: import("@motionscript/sdk").Component<"chartBorder", import("@motionscript/sdk").Merge<import("@motionscript/sdk").Box2DState, {
|
|
20
|
-
readonly stroke: import("@motionscript/sdk").Type<Stroke, StrokeResolved[], false>;
|
|
21
|
-
}>, {}, null, _Node2D<Node2DProps>, import("@motionscript/sdk").CallProps<import("@motionscript/sdk").Merge<import("@motionscript/sdk").Box2DState, {
|
|
22
|
-
readonly stroke: import("@motionscript/sdk").Type<Stroke, StrokeResolved[], false>;
|
|
23
|
-
}>, null, import("@motionscript/sdk").BuiltNode<import("@motionscript/sdk").Merge<import("@motionscript/sdk").Box2DState, {
|
|
24
|
-
readonly stroke: import("@motionscript/sdk").Type<Stroke, StrokeResolved[], false>;
|
|
25
|
-
}>, {}, _Node2D<Node2DProps>>>>;
|
|
26
|
-
export type ChartBorder = NodeOf<typeof ChartBorder>;
|
|
27
|
-
//# sourceMappingURL=chart-border.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"chart-border.d.ts","sourceRoot":"","sources":["../../src/kit/chart-border.ts"],"names":[],"mappings":"AAAA,OAAO,EAKL,KAAK,MAAM,EAEX,KAAK,MAAM,IAAI,OAAO,EACtB,KAAK,WAAW,EAChB,KAAK,MAAM,EACX,KAAK,cAAc,EACpB,MAAM,mBAAmB,CAAA;AAK1B,MAAM,WAAW,gBAAiB,SAAQ,WAAW;IACnD;;;;OAIG;IACH,MAAM,EAAE,MAAM,CAAA;CACf;AAED;;;;;;;;GAQG;AACH,eAAO,MAAM,WAAW;;;;;;+BAatB,CAAA;AAEF,MAAM,MAAM,WAAW,GAAG,MAAM,CAAC,OAAO,WAAW,CAAC,CAAA"}
|
package/dist/kit/chart-border.js
DELETED
|
@@ -1,28 +0,0 @@
|
|
|
1
|
-
import { Graphics2D, Types, component2d, strokeOps, } from "@motionscript/sdk";
|
|
2
|
-
import { loadPaints } from "./paints.js";
|
|
3
|
-
import { DEFAULT_PLOT_AREA } from "./shared.js";
|
|
4
|
-
/**
|
|
5
|
-
* The thick **frame** around a cartesian chart's plot: an empty rect wearing an
|
|
6
|
-
* inside stroke, sized from its box.
|
|
7
|
-
*
|
|
8
|
-
* Split out of {@link ChartCanvas} (the filled + gridded backdrop) so it can be
|
|
9
|
-
* placed *after* the marks in the tree — the box then frames the plot **over**
|
|
10
|
-
* them, so a line or a column running to the edge tucks cleanly under the border
|
|
11
|
-
* rather than sitting on top of it.
|
|
12
|
-
*/
|
|
13
|
-
export const ChartBorder = component2d({
|
|
14
|
-
key: "chartBorder",
|
|
15
|
-
state: {
|
|
16
|
-
stroke: Types.custom(DEFAULT_PLOT_AREA.stroke, { resolve: strokeOps.resolve, lerp: strokeOps.lerp }),
|
|
17
|
-
},
|
|
18
|
-
load: (loader, state) => loadPaints(loader, { strokes: [state.stroke] }),
|
|
19
|
-
render: (ctx, state) => {
|
|
20
|
-
const { width, height } = ctx.size;
|
|
21
|
-
if (width <= 0 || height <= 0)
|
|
22
|
-
return;
|
|
23
|
-
// Empty rect (no fill) with the themed stroke, so the frame sits over the
|
|
24
|
-
// marks but the box interior stays clear.
|
|
25
|
-
ctx.draw(new Graphics2D().rect({ x: 0, y: 0, width, height }).stroke(state.stroke));
|
|
26
|
-
},
|
|
27
|
-
});
|
|
28
|
-
//# sourceMappingURL=chart-border.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"chart-border.js","sourceRoot":"","sources":["../../src/kit/chart-border.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,UAAU,EACV,KAAK,EACL,WAAW,EACX,SAAS,GAOV,MAAM,mBAAmB,CAAA;AAE1B,OAAO,EAAE,UAAU,EAAE,MAAM,UAAU,CAAA;AACrC,OAAO,EAAE,iBAAiB,EAAE,MAAM,UAAU,CAAA;AAW5C;;;;;;;;GAQG;AACH,MAAM,CAAC,MAAM,WAAW,GAAG,WAAW,CAAC;IACrC,GAAG,EAAE,aAAa;IAClB,KAAK,EAAE;QACL,MAAM,EAAE,KAAK,CAAC,MAAM,CAA2B,iBAAiB,CAAC,MAAM,EAAE,EAAE,OAAO,EAAE,SAAS,CAAC,OAAO,EAAE,IAAI,EAAE,SAAS,CAAC,IAAI,EAAE,CAAC;KAC/H;IACD,IAAI,EAAE,CAAC,MAAM,EAAE,KAAK,EAAE,EAAE,CAAC,UAAU,CAAC,MAAM,EAAE,EAAE,OAAO,EAAE,CAAC,KAAK,CAAC,MAAM,CAAC,EAAE,CAAC;IACxE,MAAM,EAAE,CAAC,GAAG,EAAE,KAAK,EAAE,EAAE;QACrB,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,GAAG,GAAG,CAAC,IAAI,CAAA;QAClC,IAAI,KAAK,IAAI,CAAC,IAAI,MAAM,IAAI,CAAC;YAAE,OAAM;QACrC,0EAA0E;QAC1E,0CAA0C;QAC1C,GAAG,CAAC,IAAI,CAAC,IAAI,UAAU,EAAE,CAAC,IAAI,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,KAAK,EAAE,MAAM,EAAE,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,CAAA;IACrF,CAAC;CACF,CAAC,CAAA","sourcesContent":["import {\n Graphics2D,\n Types,\n component2d,\n strokeOps,\n type NodeOf,\n // Named so this component's emitted type reaches `Node2D` through the sdk, not core.\n type Node2D as _Node2D,\n type Node2DProps,\n type Stroke,\n type StrokeResolved,\n} from \"@motionscript/sdk\"\n\nimport { loadPaints } from \"./paints\"\nimport { DEFAULT_PLOT_AREA } from \"./shared\"\n\nexport interface ChartBorderProps extends Node2DProps {\n /**\n * The plot's thick frame stroke. The stroke resolver's default `align` is\n * `'inside'`, so the whole weight sits within the layout box unless the theme\n * overrides it.\n */\n stroke: Stroke\n}\n\n/**\n * The thick **frame** around a cartesian chart's plot: an empty rect wearing an\n * inside stroke, sized from its box.\n *\n * Split out of {@link ChartCanvas} (the filled + gridded backdrop) so it can be\n * placed *after* the marks in the tree — the box then frames the plot **over**\n * them, so a line or a column running to the edge tucks cleanly under the border\n * rather than sitting on top of it.\n */\nexport const ChartBorder = component2d({\n key: \"chartBorder\",\n state: {\n stroke: Types.custom<Stroke, StrokeResolved[]>(DEFAULT_PLOT_AREA.stroke, { resolve: strokeOps.resolve, lerp: strokeOps.lerp }),\n },\n load: (loader, state) => loadPaints(loader, { strokes: [state.stroke] }),\n render: (ctx, state) => {\n const { width, height } = ctx.size\n if (width <= 0 || height <= 0) return\n // Empty rect (no fill) with the themed stroke, so the frame sits over the\n // marks but the box interior stays clear.\n ctx.draw(new Graphics2D().rect({ x: 0, y: 0, width, height }).stroke(state.stroke))\n },\n})\n\nexport type ChartBorder = NodeOf<typeof ChartBorder>\n"]}
|
|
@@ -1,79 +0,0 @@
|
|
|
1
|
-
import { type NodeOf, type Node2D } from "@motionscript/sdk";
|
|
2
|
-
import { type Arrival } from "../kit/motion.js";
|
|
3
|
-
import { type AxisConfig, type Range } from "../kit/shared.js";
|
|
4
|
-
/**
|
|
5
|
-
* The horizontal axis of a {@link LineChart}: a **row of {@link Text} nodes**,
|
|
6
|
-
* one per marker value, running left-to-right. Pure layout — the mirror of the
|
|
7
|
-
* kit's `VerticalAxis`, including its bound (not snapshotted) marker text and
|
|
8
|
-
* positions, and its landed resting state.
|
|
9
|
-
*
|
|
10
|
-
* Markers are always placed **by value** across the range, whatever they say:
|
|
11
|
-
* `2026-03` sits three months along, not three slots along. That is what keeps
|
|
12
|
-
* it distinct from a bar chart's bottom axis, which centres a caption on each
|
|
13
|
-
* slot and has no scale at all — the two only look alike. What the values are
|
|
14
|
-
* captioned *as* is the chart's to decide, in `captions`.
|
|
15
|
-
*
|
|
16
|
-
* `enter` staggers the markers in **left-to-right**: each starts lifted a
|
|
17
|
-
* little above its slot and transparent, then fades and slides down into place.
|
|
18
|
-
*/
|
|
19
|
-
export declare const HorizontalAxis: import("@motionscript/sdk").Component<"horizontalAxis", import("@motionscript/sdk").Merge<import("@motionscript/sdk").Box2DState, {
|
|
20
|
-
/** `[min, max]` of the horizontal scale the markers are positioned within. */
|
|
21
|
-
readonly range: import("@motionscript/sdk").Type<Range, Range, false>;
|
|
22
|
-
/** Tick values (in data units) to draw along the axis. */
|
|
23
|
-
readonly markers: import("@motionscript/sdk").Type<number[], number[], false>;
|
|
24
|
-
/**
|
|
25
|
-
* How each marker is captioned, one per entry of `markers` and in its order.
|
|
26
|
-
* Empty (the default), or short, captions a marker with its bare numeric
|
|
27
|
-
* reading; a chart whose x column names months or categories writes those.
|
|
28
|
-
*/
|
|
29
|
-
readonly captions: import("@motionscript/sdk").Type<string[], string[], false>;
|
|
30
|
-
/** Marker/caption text style, grid stroke, and gutters — see {@link AxisConfig}. */
|
|
31
|
-
readonly axis: import("@motionscript/sdk").Type<AxisConfig, AxisConfig, false>;
|
|
32
|
-
/** Caption drawn centred in the gutter beneath the marker row; empty (the default) hides it. */
|
|
33
|
-
readonly label: "";
|
|
34
|
-
readonly arrivals: import("@motionscript/sdk").Type<Readonly<Record<string, Arrival>>, Readonly<Record<string, Arrival>>, false>;
|
|
35
|
-
}>, {
|
|
36
|
-
readonly enter: {
|
|
37
|
-
readonly stagger: import("@motionscript/sdk").Type<number | undefined, number | undefined, false>;
|
|
38
|
-
readonly slide: import("@motionscript/sdk").Type<number, number, false>;
|
|
39
|
-
};
|
|
40
|
-
}, null, Node2D<import("@motionscript/core").Node2DProps>, import("@motionscript/sdk").CallProps<import("@motionscript/sdk").Merge<import("@motionscript/sdk").Box2DState, {
|
|
41
|
-
/** `[min, max]` of the horizontal scale the markers are positioned within. */
|
|
42
|
-
readonly range: import("@motionscript/sdk").Type<Range, Range, false>;
|
|
43
|
-
/** Tick values (in data units) to draw along the axis. */
|
|
44
|
-
readonly markers: import("@motionscript/sdk").Type<number[], number[], false>;
|
|
45
|
-
/**
|
|
46
|
-
* How each marker is captioned, one per entry of `markers` and in its order.
|
|
47
|
-
* Empty (the default), or short, captions a marker with its bare numeric
|
|
48
|
-
* reading; a chart whose x column names months or categories writes those.
|
|
49
|
-
*/
|
|
50
|
-
readonly captions: import("@motionscript/sdk").Type<string[], string[], false>;
|
|
51
|
-
/** Marker/caption text style, grid stroke, and gutters — see {@link AxisConfig}. */
|
|
52
|
-
readonly axis: import("@motionscript/sdk").Type<AxisConfig, AxisConfig, false>;
|
|
53
|
-
/** Caption drawn centred in the gutter beneath the marker row; empty (the default) hides it. */
|
|
54
|
-
readonly label: "";
|
|
55
|
-
readonly arrivals: import("@motionscript/sdk").Type<Readonly<Record<string, Arrival>>, Readonly<Record<string, Arrival>>, false>;
|
|
56
|
-
}>, null, import("@motionscript/sdk").BuiltNode<import("@motionscript/sdk").Merge<import("@motionscript/sdk").Box2DState, {
|
|
57
|
-
/** `[min, max]` of the horizontal scale the markers are positioned within. */
|
|
58
|
-
readonly range: import("@motionscript/sdk").Type<Range, Range, false>;
|
|
59
|
-
/** Tick values (in data units) to draw along the axis. */
|
|
60
|
-
readonly markers: import("@motionscript/sdk").Type<number[], number[], false>;
|
|
61
|
-
/**
|
|
62
|
-
* How each marker is captioned, one per entry of `markers` and in its order.
|
|
63
|
-
* Empty (the default), or short, captions a marker with its bare numeric
|
|
64
|
-
* reading; a chart whose x column names months or categories writes those.
|
|
65
|
-
*/
|
|
66
|
-
readonly captions: import("@motionscript/sdk").Type<string[], string[], false>;
|
|
67
|
-
/** Marker/caption text style, grid stroke, and gutters — see {@link AxisConfig}. */
|
|
68
|
-
readonly axis: import("@motionscript/sdk").Type<AxisConfig, AxisConfig, false>;
|
|
69
|
-
/** Caption drawn centred in the gutter beneath the marker row; empty (the default) hides it. */
|
|
70
|
-
readonly label: "";
|
|
71
|
-
readonly arrivals: import("@motionscript/sdk").Type<Readonly<Record<string, Arrival>>, Readonly<Record<string, Arrival>>, false>;
|
|
72
|
-
}>, {
|
|
73
|
-
readonly enter: {
|
|
74
|
-
readonly stagger: import("@motionscript/sdk").Type<number | undefined, number | undefined, false>;
|
|
75
|
-
readonly slide: import("@motionscript/sdk").Type<number, number, false>;
|
|
76
|
-
};
|
|
77
|
-
}, Node2D<import("@motionscript/core").Node2DProps>>>>;
|
|
78
|
-
export type HorizontalAxis = NodeOf<typeof HorizontalAxis>;
|
|
79
|
-
//# sourceMappingURL=horizontal-axis.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"horizontal-axis.d.ts","sourceRoot":"","sources":["../../src/line-chart/horizontal-axis.ts"],"names":[],"mappings":"AAAA,OAAO,EAOL,KAAK,MAAM,EACX,KAAK,MAAM,EACZ,MAAM,mBAAmB,CAAC;AAG3B,OAAO,EAA8D,KAAK,OAAO,EAAE,MAAM,eAAe,CAAC;AACzG,OAAO,EAGL,KAAK,UAAU,EACf,KAAK,KAAK,EACX,MAAM,eAAe,CAAC;AAMvB;;;;;;;;;;;;;;GAcG;AACH,eAAO,MAAM,cAAc;IAGvB,8EAA8E;;IAE9E,0DAA0D;;IAE1D;;;;OAIG;;IAEH,oFAAoF;;IAEpF,gGAAgG;;;;;;;;;IAZhG,8EAA8E;;IAE9E,0DAA0D;;IAE1D;;;;OAIG;;IAEH,oFAAoF;;IAEpF,gGAAgG;;;;IAZhG,8EAA8E;;IAE9E,0DAA0D;;IAE1D;;;;OAIG;;IAEH,oFAAoF;;IAEpF,gGAAgG;;;;;;;;sDA8FlG,CAAC;AAEH,MAAM,MAAM,cAAc,GAAG,MAAM,CAAC,OAAO,cAAc,CAAC,CAAC"}
|
|
@@ -1,129 +0,0 @@
|
|
|
1
|
-
import { Rect, Text, Types, component2d, insetsOps, textOps, } from "@motionscript/sdk";
|
|
2
|
-
import { asParts, fresh } from "../kit/entries.js";
|
|
3
|
-
import { armed, arrival, arrivalOf, arrivalsEntry, beats, frameEase } from "../kit/motion.js";
|
|
4
|
-
import { DEFAULT_X_AXIS, enterBudget, } from "../kit/shared.js";
|
|
5
|
-
import { markerCaption } from "../kit/vertical-axis.js";
|
|
6
|
-
/** How far a marker starts above its slot when it enters, in px. */
|
|
7
|
-
const SLIDE = 24;
|
|
8
|
-
/**
|
|
9
|
-
* The horizontal axis of a {@link LineChart}: a **row of {@link Text} nodes**,
|
|
10
|
-
* one per marker value, running left-to-right. Pure layout — the mirror of the
|
|
11
|
-
* kit's `VerticalAxis`, including its bound (not snapshotted) marker text and
|
|
12
|
-
* positions, and its landed resting state.
|
|
13
|
-
*
|
|
14
|
-
* Markers are always placed **by value** across the range, whatever they say:
|
|
15
|
-
* `2026-03` sits three months along, not three slots along. That is what keeps
|
|
16
|
-
* it distinct from a bar chart's bottom axis, which centres a caption on each
|
|
17
|
-
* slot and has no scale at all — the two only look alike. What the values are
|
|
18
|
-
* captioned *as* is the chart's to decide, in `captions`.
|
|
19
|
-
*
|
|
20
|
-
* `enter` staggers the markers in **left-to-right**: each starts lifted a
|
|
21
|
-
* little above its slot and transparent, then fades and slides down into place.
|
|
22
|
-
*/
|
|
23
|
-
export const HorizontalAxis = component2d({
|
|
24
|
-
key: "horizontalAxis",
|
|
25
|
-
state: {
|
|
26
|
-
/** `[min, max]` of the horizontal scale the markers are positioned within. */
|
|
27
|
-
range: fresh(() => [0, 1]),
|
|
28
|
-
/** Tick values (in data units) to draw along the axis. */
|
|
29
|
-
markers: fresh(() => []),
|
|
30
|
-
/**
|
|
31
|
-
* How each marker is captioned, one per entry of `markers` and in its order.
|
|
32
|
-
* Empty (the default), or short, captions a marker with its bare numeric
|
|
33
|
-
* reading; a chart whose x column names months or categories writes those.
|
|
34
|
-
*/
|
|
35
|
-
captions: fresh(() => []),
|
|
36
|
-
/** Marker/caption text style, grid stroke, and gutters — see {@link AxisConfig}. */
|
|
37
|
-
axis: Types.custom(DEFAULT_X_AXIS),
|
|
38
|
-
/** Caption drawn centred in the gutter beneath the marker row; empty (the default) hides it. */
|
|
39
|
-
label: "",
|
|
40
|
-
arrivals: arrivalsEntry(),
|
|
41
|
-
},
|
|
42
|
-
// A plain node filled its parent; one made of its markers would hug them.
|
|
43
|
-
defaults: { width: "fill", height: "fill" },
|
|
44
|
-
children: (state) => {
|
|
45
|
-
const tickPad = insetsOps.resolve(state.axis.tickPadding).top;
|
|
46
|
-
const titlePad = insetsOps.resolve(state.axis.titlePadding).top;
|
|
47
|
-
const column = [];
|
|
48
|
-
// The column's parent is the axis: its box is what the markers are placed in.
|
|
49
|
-
const box = () => column[0]?.parent?.layoutBounds ?? { width: 0, height: 0 };
|
|
50
|
-
/** The live tick values, left → right — re-read every frame, not snapshotted. */
|
|
51
|
-
const sorted = () => [...state.markers].sort((a, b) => a - b);
|
|
52
|
-
/** Tick `i`'s fraction across the live `range`, 0 at the left edge. */
|
|
53
|
-
const fracAt = (value) => {
|
|
54
|
-
if (value === undefined)
|
|
55
|
-
return 0;
|
|
56
|
-
const [min, max] = state.range;
|
|
57
|
-
return max <= min ? 0 : (value - min) / (max - min);
|
|
58
|
-
};
|
|
59
|
-
const markers = state.markers.map((_, i) => {
|
|
60
|
-
const marker = new Text({
|
|
61
|
-
...textOps.styleProps(state.axis.labelStyle),
|
|
62
|
-
text: () => {
|
|
63
|
-
const value = sorted()[i];
|
|
64
|
-
return value === undefined ? "" : markerCaption(state, value);
|
|
65
|
-
},
|
|
66
|
-
x: () => {
|
|
67
|
-
const width = box().width;
|
|
68
|
-
const centred = (fracAt(sorted()[i]) - 0.5) * width;
|
|
69
|
-
// Held inside the axis's right edge, which is also the *chart's*: the
|
|
70
|
-
// last marker is centred on the last grid line, so half of `2026-06`
|
|
71
|
-
// — or of `3300` — would be drawn outside the node's box and outside
|
|
72
|
-
// the rectangle the editor draws around it. Only the right edge is
|
|
73
|
-
// held, because the left one has the vertical axis's whole gutter
|
|
74
|
-
// beyond it, and a marker overhanging into that is inside the chart.
|
|
75
|
-
const limit = width / 2 - marker.layoutBounds.width / 2;
|
|
76
|
-
return Math.min(centred, limit);
|
|
77
|
-
},
|
|
78
|
-
opacity: () => arrivalOf(state.arrivals, i).opacity,
|
|
79
|
-
y: () => arrivalOf(state.arrivals, i).shift,
|
|
80
|
-
});
|
|
81
|
-
return marker;
|
|
82
|
-
});
|
|
83
|
-
const children = [
|
|
84
|
-
new Rect({ width: "fill", height: "hug", padding: { top: tickPad }, children: markers }),
|
|
85
|
-
];
|
|
86
|
-
if (state.label !== "") {
|
|
87
|
-
children.push(new Text({
|
|
88
|
-
...textOps.styleProps(state.axis.titleStyle),
|
|
89
|
-
text: state.label,
|
|
90
|
-
opacity: () => arrivalOf(state.arrivals, "label").opacity,
|
|
91
|
-
y: () => arrivalOf(state.arrivals, "label").shift,
|
|
92
|
-
}));
|
|
93
|
-
}
|
|
94
|
-
column.push(new Rect({ flow: "vertical", gap: titlePad, height: "hug", width: "fill", children }));
|
|
95
|
-
return asParts(column);
|
|
96
|
-
},
|
|
97
|
-
commands: {
|
|
98
|
-
/**
|
|
99
|
-
* Stagger the markers in left to right, then slide the caption in after
|
|
100
|
-
* them. Its first frame arms them all: lifted by `slide` and transparent.
|
|
101
|
-
*
|
|
102
|
-
* The timeline's duration is the **whole** entrance — see
|
|
103
|
-
* `VerticalAxis.enter` and {@link enterBudget}.
|
|
104
|
-
*/
|
|
105
|
-
enter: {
|
|
106
|
-
args: {
|
|
107
|
-
stagger: Types.custom(undefined),
|
|
108
|
-
slide: Types.number(SLIDE),
|
|
109
|
-
},
|
|
110
|
-
run: (timeline, state) => {
|
|
111
|
-
const { stagger, slide } = timeline.args;
|
|
112
|
-
const count = state.markers.length;
|
|
113
|
-
const captioned = state.label !== "";
|
|
114
|
-
const from = { opacity: 0, shift: slide };
|
|
115
|
-
const keys = [...state.markers.keys(), ...(captioned ? ["label"] : [])];
|
|
116
|
-
const arm = timeline.animate(() => ({ arrivals: armed(keys, from) }));
|
|
117
|
-
if (count === 0)
|
|
118
|
-
return arm;
|
|
119
|
-
const { step, per, caption } = enterBudget(timeline.duration, count, captioned, stagger);
|
|
120
|
-
const ease = frameEase(timeline);
|
|
121
|
-
// Left marker leads: the row is already left → right.
|
|
122
|
-
const markers = state.markers.map((_, i) => ({ at: i * step, duration: per, piece: arrival(timeline, i, from, ease) }));
|
|
123
|
-
const label = captioned ? [{ at: (count - 1) * step + per, duration: caption, piece: arrival(timeline, "label", from, ease) }] : [];
|
|
124
|
-
return timeline.together([arm, beats(timeline, [...markers, ...label])]);
|
|
125
|
-
},
|
|
126
|
-
},
|
|
127
|
-
},
|
|
128
|
-
});
|
|
129
|
-
//# sourceMappingURL=horizontal-axis.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"horizontal-axis.js","sourceRoot":"","sources":["../../src/line-chart/horizontal-axis.ts"],"names":[],"mappings":"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","sourcesContent":["import {\n Rect,\n Text,\n Types,\n component2d,\n insetsOps,\n textOps,\n type NodeOf,\n type Node2D,\n} from \"@motionscript/sdk\";\n\nimport { asParts, fresh } from \"../kit/entries\";\nimport { armed, arrival, arrivalOf, arrivalsEntry, beats, frameEase, type Arrival } from \"../kit/motion\";\nimport {\n DEFAULT_X_AXIS,\n enterBudget,\n type AxisConfig,\n type Range,\n} from \"../kit/shared\";\nimport { markerCaption } from \"../kit/vertical-axis\";\n\n/** How far a marker starts above its slot when it enters, in px. */\nconst SLIDE = 24;\n\n/**\n * The horizontal axis of a {@link LineChart}: a **row of {@link Text} nodes**,\n * one per marker value, running left-to-right. Pure layout — the mirror of the\n * kit's `VerticalAxis`, including its bound (not snapshotted) marker text and\n * positions, and its landed resting state.\n *\n * Markers are always placed **by value** across the range, whatever they say:\n * `2026-03` sits three months along, not three slots along. That is what keeps\n * it distinct from a bar chart's bottom axis, which centres a caption on each\n * slot and has no scale at all — the two only look alike. What the values are\n * captioned *as* is the chart's to decide, in `captions`.\n *\n * `enter` staggers the markers in **left-to-right**: each starts lifted a\n * little above its slot and transparent, then fades and slides down into place.\n */\nexport const HorizontalAxis = component2d({\n key: \"horizontalAxis\",\n state: {\n /** `[min, max]` of the horizontal scale the markers are positioned within. */\n range: fresh<Range>(() => [0, 1]),\n /** Tick values (in data units) to draw along the axis. */\n markers: fresh<number[]>(() => []),\n /**\n * How each marker is captioned, one per entry of `markers` and in its order.\n * Empty (the default), or short, captions a marker with its bare numeric\n * reading; a chart whose x column names months or categories writes those.\n */\n captions: fresh<string[]>(() => []),\n /** Marker/caption text style, grid stroke, and gutters — see {@link AxisConfig}. */\n axis: Types.custom<AxisConfig>(DEFAULT_X_AXIS),\n /** Caption drawn centred in the gutter beneath the marker row; empty (the default) hides it. */\n label: \"\",\n arrivals: arrivalsEntry(),\n },\n // A plain node filled its parent; one made of its markers would hug them.\n defaults: { width: \"fill\", height: \"fill\" },\n children: (state) => {\n const tickPad = insetsOps.resolve(state.axis.tickPadding).top;\n const titlePad = insetsOps.resolve(state.axis.titlePadding).top;\n\n const column: Node2D[] = [];\n // The column's parent is the axis: its box is what the markers are placed in.\n const box = () => (column[0]?.parent as Node2D | null | undefined)?.layoutBounds ?? { width: 0, height: 0 };\n /** The live tick values, left → right — re-read every frame, not snapshotted. */\n const sorted = () => [...state.markers].sort((a, b) => a - b);\n /** Tick `i`'s fraction across the live `range`, 0 at the left edge. */\n const fracAt = (value: number | undefined) => {\n if (value === undefined) return 0;\n const [min, max] = state.range;\n return max <= min ? 0 : (value - min) / (max - min);\n };\n\n const markers = state.markers.map((_, i) => {\n const marker: Node2D = new Text({\n ...textOps.styleProps(state.axis.labelStyle),\n text: () => {\n const value = sorted()[i];\n return value === undefined ? \"\" : markerCaption(state, value);\n },\n x: () => {\n const width = box().width;\n const centred = (fracAt(sorted()[i]) - 0.5) * width;\n // Held inside the axis's right edge, which is also the *chart's*: the\n // last marker is centred on the last grid line, so half of `2026-06`\n // — or of `3300` — would be drawn outside the node's box and outside\n // the rectangle the editor draws around it. Only the right edge is\n // held, because the left one has the vertical axis's whole gutter\n // beyond it, and a marker overhanging into that is inside the chart.\n const limit = width / 2 - marker.layoutBounds.width / 2;\n return Math.min(centred, limit);\n },\n opacity: () => arrivalOf(state.arrivals, i).opacity,\n y: () => arrivalOf(state.arrivals, i).shift,\n });\n return marker;\n });\n\n const children: Node2D[] = [\n new Rect({ width: \"fill\", height: \"hug\", padding: { top: tickPad }, children: markers }),\n ];\n if (state.label !== \"\") {\n children.push(\n new Text({\n ...textOps.styleProps(state.axis.titleStyle),\n text: state.label,\n opacity: () => arrivalOf(state.arrivals, \"label\").opacity,\n y: () => arrivalOf(state.arrivals, \"label\").shift,\n }),\n );\n }\n\n column.push(new Rect({ flow: \"vertical\", gap: titlePad, height: \"hug\", width: \"fill\", children }));\n return asParts(column);\n },\n commands: {\n /**\n * Stagger the markers in left to right, then slide the caption in after\n * them. Its first frame arms them all: lifted by `slide` and transparent.\n *\n * The timeline's duration is the **whole** entrance — see\n * `VerticalAxis.enter` and {@link enterBudget}.\n */\n enter: {\n args: {\n stagger: Types.custom<number | undefined>(undefined),\n slide: Types.number(SLIDE),\n },\n run: (timeline, state) => {\n const { stagger, slide } = timeline.args;\n const count = state.markers.length;\n const captioned = state.label !== \"\";\n const from: Arrival = { opacity: 0, shift: slide };\n const keys = [...state.markers.keys(), ...(captioned ? [\"label\"] : [])];\n const arm = timeline.animate(() => ({ arrivals: armed(keys, from) }));\n if (count === 0) return arm;\n const { step, per, caption } = enterBudget(timeline.duration, count, captioned, stagger);\n const ease = frameEase(timeline);\n // Left marker leads: the row is already left → right.\n const markers = state.markers.map((_, i) => ({ at: i * step, duration: per, piece: arrival(timeline, i, from, ease) }));\n const label = captioned ? [{ at: (count - 1) * step + per, duration: caption, piece: arrival(timeline, \"label\", from, ease) }] : [];\n return timeline.together([arm, beats(timeline, [...markers, ...label])]);\n },\n },\n },\n});\n\nexport type HorizontalAxis = NodeOf<typeof HorizontalAxis>;\n"]}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"pie-legend.d.ts","sourceRoot":"","sources":["../../src/pie-chart/pie-legend.ts"],"names":[],"mappings":"AAAA,OAAO,EASL,KAAK,MAAM,EACX,KAAK,SAAS,EAEd,KAAK,SAAS,IAAI,UAAU,EAC5B,KAAK,oBAAoB,IAAI,qBAAqB,EAClD,KAAK,mBAAmB,IAAI,oBAAoB,EAChD,KAAK,IAAI,IAAI,KAAK,EAClB,KAAK,YAAY,IAAI,aAAa,EAClC,KAAK,QAAQ,IAAI,SAAS,EAC1B,KAAK,YAAY,IAAI,aAAa,EAClC,KAAK,OAAO,IAAI,QAAQ,EACxB,KAAK,MAAM,IAAI,OAAO,EACtB,KAAK,WAAW,IAAI,YAAY,EAChC,KAAK,gBAAgB,IAAI,iBAAiB,EAC1C,KAAK,eAAe,IAAI,gBAAgB,EACxC,KAAK,MAAM,IAAI,OAAO,EACtB,KAAK,cAAc,IAAI,eAAe,EACtC,KAAK,MAAM,IAAI,OAAO,EACtB,KAAK,cAAc,IAAI,eAAe,EACtC,KAAK,OAAO,IAAI,QAAQ,EACzB,MAAM,mBAAmB,CAAA;AAG1B,OAAO,EAA8D,KAAK,OAAO,EAAE,MAAM,eAAe,CAAA;AACxG,OAAO,EAGL,KAAK,YAAY,EAClB,MAAM,eAAe,CAAA;AACtB,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,UAAU,CAAA;AAExC,MAAM,WAAW,cAAe,SAAQ,SAAS;IAC/C,0CAA0C;IAC1C,MAAM,EAAE,QAAQ,EAAE,CAAA;IAClB,oFAAoF;IACpF,MAAM,EAAE,YAAY,CAAA;IACpB;;;OAGG;IACH,IAAI,EAAE,MAAM,EAAE,CAAA;CACf;AAKD;;;;;;;;;;;;;;;GAeG;AACH,eAAO,MAAM,SAAS;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;2BA+FpB,CAAA;AAEF,MAAM,MAAM,SAAS,GAAG,MAAM,CAAC,OAAO,SAAS,CAAC,CAAA"}
|