@motionscript/charts 0.1.0-alpha.8 → 0.1.0
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 +6 -0
- package/LICENSE +201 -201
- package/NOTICE +49 -49
- package/README.md +99 -99
- package/dist/bar-chart/bar-chart.js.map +1 -1
- package/dist/bar-chart/category-axis.js.map +1 -1
- package/dist/bar-chart/chart-bars.js.map +1 -1
- package/dist/bar-chart/index.js.map +1 -1
- package/dist/bar-chart/shared.js.map +1 -1
- package/dist/browser/chunks/{chunk-XROBIRQK.js → chunk-TJNHLQGV.js} +1 -1
- package/dist/browser/chunks/chunk-TJNHLQGV.js.map +7 -0
- package/dist/browser/index.js +1 -1
- package/dist/browser/index.js.map +1 -1
- package/dist/browser/kit.js +1 -1
- package/dist/browser/manifest.json +1 -1
- package/dist/engine.d.ts +1 -1
- package/dist/engine.js +1 -1
- package/dist/engine.js.map +1 -1
- package/dist/index.js.map +1 -1
- package/dist/kit/cartesian.js.map +1 -1
- package/dist/kit/chart-border.js.map +1 -1
- package/dist/kit/chart-canvas.js.map +1 -1
- package/dist/kit/chart-legend.js.map +1 -1
- package/dist/kit/entries.js.map +1 -1
- package/dist/kit/motion.js.map +1 -1
- package/dist/kit/paints.js.map +1 -1
- package/dist/kit/shared.js.map +1 -1
- package/dist/kit/vertical-axis.js.map +1 -1
- package/dist/line-chart/chart-line.js.map +1 -1
- package/dist/line-chart/chart-region.js.map +1 -1
- package/dist/line-chart/horizontal-axis.js.map +1 -1
- package/dist/line-chart/index.d.ts +1 -1
- package/dist/line-chart/index.js +1 -1
- package/dist/line-chart/index.js.map +1 -1
- package/dist/line-chart/line-chart.js.map +1 -1
- package/dist/line-chart/shared.js.map +1 -1
- package/dist/line-chart/x-scale.js.map +1 -1
- package/dist/nodes.js.map +1 -1
- package/dist/pie-chart/index.js.map +1 -1
- package/dist/pie-chart/pie-chart.js.map +1 -1
- package/dist/pie-chart/pie-legend.js.map +1 -1
- package/dist/pie-chart/pie-ring.js.map +1 -1
- package/dist/pie-chart/shared.js.map +1 -1
- package/package.json +4 -4
- package/registry.json +23 -23
- package/src/bar-chart/bar-chart.ts +542 -542
- package/src/bar-chart/category-axis.ts +162 -162
- package/src/bar-chart/chart-bars.ts +287 -287
- package/src/bar-chart/index.ts +31 -31
- package/src/bar-chart/shared.ts +354 -354
- package/src/engine.ts +28 -28
- package/src/index.ts +5 -5
- package/src/kit/cartesian.ts +81 -81
- package/src/kit/chart-border.ts +50 -50
- package/src/kit/chart-canvas.ts +122 -122
- package/src/kit/chart-legend.ts +229 -229
- package/src/kit/entries.ts +20 -20
- package/src/kit/motion.ts +90 -90
- package/src/kit/paints.ts +15 -15
- package/src/kit/shared.ts +782 -782
- package/src/kit/vertical-axis.ts +194 -194
- package/src/line-chart/chart-line.ts +156 -156
- package/src/line-chart/chart-region.ts +90 -90
- package/src/line-chart/horizontal-axis.ts +151 -151
- package/src/line-chart/index.ts +39 -39
- package/src/line-chart/line-chart.ts +598 -598
- package/src/line-chart/shared.ts +473 -473
- package/src/line-chart/x-scale.ts +382 -382
- package/src/nodes.ts +18 -18
- package/src/pie-chart/index.ts +37 -37
- package/src/pie-chart/pie-chart.ts +296 -296
- package/src/pie-chart/pie-legend.ts +169 -169
- package/src/pie-chart/pie-ring.ts +848 -848
- package/src/pie-chart/shared.ts +496 -496
- package/dist/browser/chunks/chunk-XROBIRQK.js.map +0 -7
- package/src/node_modules/.vite/vitest/da39a3ee5e6b4b0d3255bfef95601890afd80709/results.json +0 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"chart-line.js","sourceRoot":"","sources":["../../src/line-chart/chart-line.ts"],"names":[],"mappings":"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","sourcesContent":["import {\r\n Graphics2D,\r\n Types,\r\n component2d,\r\n strokeOps,\r\n type NodeOf,\r\n // Named so this component's emitted type reaches `Node2D` through the sdk, not core.\r\n type Node2D as _Node2D,\r\n type Stroke,\r\n type StrokeResolved,\r\n type Vector2,\r\n} from \"@motionscript/sdk\"\r\n\r\nimport { fresh } from \"../kit/entries\"\r\nimport { frameEase } from \"../kit/motion\"\r\nimport { loadPaints } from \"../kit/paints\"\r\nimport { SPOTLIGHT_DIM } from \"../kit/shared\"\r\nimport {\r\n EMPTY_REGION_BOX,\r\n clipPolylineToBox,\r\n hasRegion,\r\n type RegionBox,\r\n} from \"./shared\"\r\n\r\n/**\r\n * The prefix of `pts` revealed at fraction `p ∈ [0, 1]`, measuring the reveal\r\n * by *cumulative arc length* so the line traces at a steady pace regardless of\r\n * uneven point spacing. Returns the whole-point prefix plus one interpolated\r\n * point partway along the active segment.\r\n */\r\nfunction tracePoints(pts: Vector2[], p: number): Vector2[] {\r\n if (p >= 1 || pts.length < 2) return pts\r\n if (p <= 0) return []\r\n\r\n const segLen: number[] = []\r\n let total = 0\r\n for (let i = 1; i < pts.length; i++) {\r\n const d = Math.hypot(pts[i].x - pts[i - 1].x, pts[i].y - pts[i - 1].y)\r\n segLen.push(d)\r\n total += d\r\n }\r\n if (total === 0) return pts\r\n\r\n let target = total * p\r\n const out: Vector2[] = [pts[0]]\r\n for (let i = 0; i < segLen.length; i++) {\r\n if (target >= segLen[i]) {\r\n out.push(pts[i + 1])\r\n target -= segLen[i]\r\n } else {\r\n const t = segLen[i] === 0 ? 0 : target / segLen[i]\r\n out.push({\r\n x: pts[i].x + (pts[i + 1].x - pts[i].x) * t,\r\n y: pts[i].y + (pts[i + 1].y - pts[i].y) * t,\r\n })\r\n break\r\n }\r\n }\r\n return out\r\n}\r\n\r\n/**\r\n * A single series line of a {@link LineChart}: one rounded polyline traced\r\n * through pre-mapped pixel `points`, drawn as one {@link Graphics2D} command list.\r\n * Sized and positioned by the parent, which shares the plot's coordinate frame.\r\n *\r\n * Two signals drive it: `progress` traces the line in\r\n * (animated by `enter`) and `enabled` shows or hides it wholesale.\r\n */\r\nexport const ChartLine = component2d({\r\n key: \"chartLine\",\r\n state: {\r\n /** The series polyline, already mapped into this node's local pixel space (origin at centre, y-up) by the parent {@link LineChart}. Ordered along x. */\r\n points: fresh<Vector2[]>(() => []),\r\n /** Line colour + weight (+ optional dash/cap/join) — the per-series stroke. */\r\n stroke: Types.custom<Stroke, StrokeResolved[]>([], { resolve: strokeOps.resolve, lerp: strokeOps.lerp }),\r\n /**\r\n * Reveal of the line in `[0, 1]`: 0 hides it, 1 traces it fully from its left\r\n * end to its right. Defaults to 1, so the paused editor canvas paints the line;\r\n * `enter` drives it from 0 regardless of where it rests.\r\n */\r\n progress: 1,\r\n /** Whether this line is drawn at all: the switch the chart flips alongside its legend's per-series toggle. */\r\n enabled: true,\r\n /** A slice of the plot to spotlight, in this node's own pixel space: outside it the line drops to `dimOpacity`. */\r\n spotlight: fresh<RegionBox>(() => EMPTY_REGION_BOX),\r\n /** Opacity the out-of-region stretches fade to. */\r\n dimOpacity: SPOTLIGHT_DIM,\r\n },\r\n load: (loader, state) => loadPaints(loader, { strokes: [state.stroke] }),\r\n commands: {\r\n /**\r\n * Trace the line from `from` to `to` over the command — by default in from\r\n * its left end to its right. `showSeries` and `hideSeries` are the same\r\n * motion in opposite directions, so both are this with their ends stated.\r\n *\r\n * `enabled` rides along in the same value rather than being set before or\r\n * after the command: a line is drawable for every `t` the trace covers and\r\n * undrawn outside it, which is what makes arriving at a time backwards show\r\n * what arriving forwards does.\r\n */\r\n enter: {\r\n args: { from: Types.number(0, { min: 0, max: 1 }), to: Types.number(1, { min: 0, max: 1 }) },\r\n run: (timeline) => {\r\n const { from, to } = timeline.args\r\n const ease = frameEase(timeline)\r\n return timeline.animate((t) => {\r\n const progress = from + (to - from) * ease(t)\r\n // Hidden only once it has fully retraced, so the last frame of a hide is\r\n // the empty plot rather than a line that vanished a frame early.\r\n return { progress, enabled: progress > 0 }\r\n })\r\n },\r\n },\r\n },\r\n render: (ctx, state) => {\r\n if (!state.enabled) return\r\n const pts = state.points\r\n if (pts.length < 2) return\r\n\r\n const p = Math.max(0, Math.min(1, state.progress))\r\n if (p <= 0) return\r\n\r\n const drawn = tracePoints(pts, p)\r\n if (drawn.length < 2) return\r\n const stroke = state.stroke\r\n const radius = (stroke[0]?.weight ?? 0) * 2 // round the joins\r\n\r\n const box = state.spotlight\r\n if (!hasRegion(box)) {\r\n ctx.draw(new Graphics2D().line({ points: drawn, radius }).stroke(stroke))\r\n return\r\n }\r\n\r\n // Spotlit: the whole line goes down to `dimOpacity`, then the stretches\r\n // inside the region are re-drawn over it at full strength. Two passes rather\r\n // than one dim + one bright *complementary* pair, so the bright run has\r\n // continuous geometry through the region and its joins round the way an\r\n // unspotlit line's do — and so the boundary lands exactly on the region edge.\r\n ctx.draw(\r\n new Graphics2D()\r\n .line({ points: drawn, radius })\r\n .stroke(stroke)\r\n .opacity(Math.max(0, Math.min(1, state.dimOpacity)))\r\n )\r\n\r\n // One `draw` per run: shapes chained before a `stroke()` are combined into a\r\n // single surface, and stroking a union of disjoint open paths doesn't paint\r\n // — so a line that leaves the region and comes back would lose both halves.\r\n for (const run of clipPolylineToBox(drawn, box)) {\r\n ctx.draw(new Graphics2D().line({ points: run, radius }).stroke(stroke))\r\n }\r\n },\r\n})\r\n\r\nexport type ChartLine = NodeOf<typeof ChartLine>\r\n"]}
|
|
1
|
+
{"version":3,"file":"chart-line.js","sourceRoot":"","sources":["../../src/line-chart/chart-line.ts"],"names":[],"mappings":"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","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 Stroke,\n type StrokeResolved,\n type Vector2,\n} from \"@motionscript/sdk\"\n\nimport { fresh } from \"../kit/entries\"\nimport { frameEase } from \"../kit/motion\"\nimport { loadPaints } from \"../kit/paints\"\nimport { SPOTLIGHT_DIM } from \"../kit/shared\"\nimport {\n EMPTY_REGION_BOX,\n clipPolylineToBox,\n hasRegion,\n type RegionBox,\n} from \"./shared\"\n\n/**\n * The prefix of `pts` revealed at fraction `p ∈ [0, 1]`, measuring the reveal\n * by *cumulative arc length* so the line traces at a steady pace regardless of\n * uneven point spacing. Returns the whole-point prefix plus one interpolated\n * point partway along the active segment.\n */\nfunction tracePoints(pts: Vector2[], p: number): Vector2[] {\n if (p >= 1 || pts.length < 2) return pts\n if (p <= 0) return []\n\n const segLen: number[] = []\n let total = 0\n for (let i = 1; i < pts.length; i++) {\n const d = Math.hypot(pts[i].x - pts[i - 1].x, pts[i].y - pts[i - 1].y)\n segLen.push(d)\n total += d\n }\n if (total === 0) return pts\n\n let target = total * p\n const out: Vector2[] = [pts[0]]\n for (let i = 0; i < segLen.length; i++) {\n if (target >= segLen[i]) {\n out.push(pts[i + 1])\n target -= segLen[i]\n } else {\n const t = segLen[i] === 0 ? 0 : target / segLen[i]\n out.push({\n x: pts[i].x + (pts[i + 1].x - pts[i].x) * t,\n y: pts[i].y + (pts[i + 1].y - pts[i].y) * t,\n })\n break\n }\n }\n return out\n}\n\n/**\n * A single series line of a {@link LineChart}: one rounded polyline traced\n * through pre-mapped pixel `points`, drawn as one {@link Graphics2D} command list.\n * Sized and positioned by the parent, which shares the plot's coordinate frame.\n *\n * Two signals drive it: `progress` traces the line in\n * (animated by `enter`) and `enabled` shows or hides it wholesale.\n */\nexport const ChartLine = component2d({\n key: \"chartLine\",\n state: {\n /** The series polyline, already mapped into this node's local pixel space (origin at centre, y-up) by the parent {@link LineChart}. Ordered along x. */\n points: fresh<Vector2[]>(() => []),\n /** Line colour + weight (+ optional dash/cap/join) — the per-series stroke. */\n stroke: Types.custom<Stroke, StrokeResolved[]>([], { resolve: strokeOps.resolve, lerp: strokeOps.lerp }),\n /**\n * Reveal of the line in `[0, 1]`: 0 hides it, 1 traces it fully from its left\n * end to its right. Defaults to 1, so the paused editor canvas paints the line;\n * `enter` drives it from 0 regardless of where it rests.\n */\n progress: 1,\n /** Whether this line is drawn at all: the switch the chart flips alongside its legend's per-series toggle. */\n enabled: true,\n /** A slice of the plot to spotlight, in this node's own pixel space: outside it the line drops to `dimOpacity`. */\n spotlight: fresh<RegionBox>(() => EMPTY_REGION_BOX),\n /** Opacity the out-of-region stretches fade to. */\n dimOpacity: SPOTLIGHT_DIM,\n },\n load: (loader, state) => loadPaints(loader, { strokes: [state.stroke] }),\n commands: {\n /**\n * Trace the line from `from` to `to` over the command — by default in from\n * its left end to its right. `showSeries` and `hideSeries` are the same\n * motion in opposite directions, so both are this with their ends stated.\n *\n * `enabled` rides along in the same value rather than being set before or\n * after the command: a line is drawable for every `t` the trace covers and\n * undrawn outside it, which is what makes arriving at a time backwards show\n * what arriving forwards does.\n */\n enter: {\n args: { from: Types.number(0, { min: 0, max: 1 }), to: Types.number(1, { min: 0, max: 1 }) },\n run: (timeline) => {\n const { from, to } = timeline.args\n const ease = frameEase(timeline)\n return timeline.animate((t) => {\n const progress = from + (to - from) * ease(t)\n // Hidden only once it has fully retraced, so the last frame of a hide is\n // the empty plot rather than a line that vanished a frame early.\n return { progress, enabled: progress > 0 }\n })\n },\n },\n },\n render: (ctx, state) => {\n if (!state.enabled) return\n const pts = state.points\n if (pts.length < 2) return\n\n const p = Math.max(0, Math.min(1, state.progress))\n if (p <= 0) return\n\n const drawn = tracePoints(pts, p)\n if (drawn.length < 2) return\n const stroke = state.stroke\n const radius = (stroke[0]?.weight ?? 0) * 2 // round the joins\n\n const box = state.spotlight\n if (!hasRegion(box)) {\n ctx.draw(new Graphics2D().line({ points: drawn, radius }).stroke(stroke))\n return\n }\n\n // Spotlit: the whole line goes down to `dimOpacity`, then the stretches\n // inside the region are re-drawn over it at full strength. Two passes rather\n // than one dim + one bright *complementary* pair, so the bright run has\n // continuous geometry through the region and its joins round the way an\n // unspotlit line's do — and so the boundary lands exactly on the region edge.\n ctx.draw(\n new Graphics2D()\n .line({ points: drawn, radius })\n .stroke(stroke)\n .opacity(Math.max(0, Math.min(1, state.dimOpacity)))\n )\n\n // One `draw` per run: shapes chained before a `stroke()` are combined into a\n // single surface, and stroking a union of disjoint open paths doesn't paint\n // — so a line that leaves the region and comes back would lose both halves.\n for (const run of clipPolylineToBox(drawn, box)) {\n ctx.draw(new Graphics2D().line({ points: run, radius }).stroke(stroke))\n }\n },\n})\n\nexport type ChartLine = NodeOf<typeof ChartLine>\n"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"chart-region.js","sourceRoot":"","sources":["../../src/line-chart/chart-region.ts"],"names":[],"mappings":"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","sourcesContent":["import {\
|
|
1
|
+
{"version":3,"file":"chart-region.js","sourceRoot":"","sources":["../../src/line-chart/chart-region.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,UAAU,EACV,KAAK,EACL,WAAW,EACX,OAAO,EACP,SAAS,GAQV,MAAM,mBAAmB,CAAA;AAE1B,OAAO,EAAE,KAAK,EAAE,MAAM,gBAAgB,CAAA;AACtC,OAAO,EAAE,UAAU,EAAE,MAAM,eAAe,CAAA;AAC1C,OAAO,EACL,mBAAmB,EACnB,gBAAgB,EAChB,SAAS,GAEV,MAAM,UAAU,CAAA;AAEjB;;;;;;;;;;;;;GAaG;AACH,MAAM,CAAC,MAAM,WAAW,GAAG,WAAW,CAAC;IACrC,GAAG,EAAE,aAAa;IAClB,KAAK,EAAE;QACL,2KAA2K;QAC3K,GAAG,EAAE,KAAK,CAAY,GAAG,EAAE,CAAC,gBAAgB,CAAC;QAC7C,0DAA0D;QAC1D,MAAM,EAAE,KAAK,CAAC,MAAM,CAA2B,mBAAmB,CAAC,MAAM,CAAC,MAAM,EAAE,EAAE,OAAO,EAAE,SAAS,CAAC,OAAO,EAAE,IAAI,EAAE,SAAS,CAAC,IAAI,EAAE,CAAC;QACvI,oDAAoD;QACpD,IAAI,EAAE,KAAK,CAAC,MAAM,CAAuB,mBAAmB,CAAC,MAAM,CAAC,IAAI,EAAE,EAAE,OAAO,EAAE,OAAO,CAAC,OAAO,EAAE,IAAI,EAAE,OAAO,CAAC,IAAI,EAAE,CAAC;QAC3H,uIAAuI;QACvI,MAAM,EAAE,CAAC;KACV;IACD,IAAI,EAAE,CAAC,MAAM,EAAE,KAAK,EAAE,EAAE,CAAC,UAAU,CAAC,MAAM,EAAE,EAAE,KAAK,EAAE,CAAC,KAAK,CAAC,IAAI,CAAC,EAAE,OAAO,EAAE,CAAC,KAAK,CAAC,MAAM,CAAC,EAAE,CAAC;IAC7F,MAAM,EAAE,CAAC,GAAG,EAAE,KAAK,EAAE,EAAE;QACrB,MAAM,GAAG,GAAG,KAAK,CAAC,GAAG,CAAA;QACrB,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC;YAAE,OAAM;QAE3B,MAAM,CAAC,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,KAAK,CAAC,MAAM,CAAC,CAAC,CAAA;QAChD,IAAI,CAAC,IAAI,CAAC;YAAE,OAAM;QAElB,MAAM,KAAK,GAAG,GAAG,CAAC,KAAK,GAAG,GAAG,CAAC,IAAI,CAAA;QAClC,MAAM,MAAM,GAAG,GAAG,CAAC,GAAG,GAAG,GAAG,CAAC,MAAM,CAAA;QACnC,MAAM,EAAE,GAAG,CAAC,GAAG,CAAC,IAAI,GAAG,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,CAAA;QACrC,MAAM,EAAE,GAAG,CAAC,GAAG,CAAC,MAAM,GAAG,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,CAAA;QAErC,oDAAoD;QACpD,IAAI,KAAK,CAAC,IAAI,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YAC1B,GAAG,CAAC,IAAI,CAAC,IAAI,UAAU,EAAE,CAAC,IAAI,CAAC,EAAE,CAAC,EAAE,EAAE,EAAE,CAAC,EAAE,EAAE,EAAE,KAAK,EAAE,MAAM,EAAE,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,CAAA;QAC9F,CAAC;QAED,yEAAyE;QACzE,qEAAqE;QACrE,IAAI,KAAK,CAAC,MAAM,CAAC,MAAM,KAAK,CAAC;YAAE,OAAM;QAErC,sEAAsE;QACtE,wEAAwE;QACxE,yDAAyD;QACzD,MAAM,IAAI,GAAG,CAAC,MAAkC,EAAE,EAAE,CAClD,GAAG,CAAC,IAAI,CAAC,IAAI,UAAU,EAAE,CAAC,IAAI,CAAC,EAAE,MAAM,EAAE,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,CAAA;QAE7E,IAAI,GAAG,CAAC,QAAQ,EAAE,CAAC;YACjB,MAAM,IAAI,GAAG,CAAC,MAAM,GAAG,CAAC,CAAC,GAAG,CAAC,CAAA;YAC7B,KAAK,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,IAAI,EAAE,GAAG,CAAC,KAAK,CAAC;gBAAE,IAAI,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,EAAE,GAAG,IAAI,EAAE,EAAE,EAAE,CAAC,EAAE,CAAC,EAAE,EAAE,GAAG,IAAI,EAAE,CAAC,CAAC,CAAA;QACzF,CAAC;QACD,IAAI,GAAG,CAAC,QAAQ,EAAE,CAAC;YACjB,MAAM,IAAI,GAAG,CAAC,KAAK,GAAG,CAAC,CAAC,GAAG,CAAC,CAAA;YAC5B,KAAK,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,MAAM,EAAE,GAAG,CAAC,GAAG,CAAC;gBAAE,IAAI,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,GAAG,IAAI,EAAE,CAAC,EAAE,EAAE,EAAE,CAAC,EAAE,EAAE,GAAG,IAAI,EAAE,CAAC,EAAE,CAAC,CAAC,CAAA;QACzF,CAAC;IACH,CAAC;CACF,CAAC,CAAA","sourcesContent":["import {\n Graphics2D,\n Types,\n component2d,\n fillOps,\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 Stroke,\n type StrokeResolved,\n} from \"@motionscript/sdk\"\n\nimport { fresh } from \"../kit/entries\"\nimport { loadPaints } from \"../kit/paints\"\nimport {\n DEFAULT_CHART_THEME,\n EMPTY_REGION_BOX,\n hasRegion,\n type RegionBox,\n} from \"./shared\"\n\n/**\n * The **region call-out** of a {@link LineChart}: a washed rectangle over the\n * plot with a dashed rule down each edge the author actually bounded. Sized and\n * positioned entirely from the pre-mapped `box` rather\n * than its own box — the region already carries the plot geometry.\n *\n * It draws only the *marking*; fading the series outside the region is\n * {@link ChartLine}'s job (it clips its own polyline against the same box), so\n * the two can't disagree about where the boundary is.\n *\n * Only bounded edges get a rule: a region given just an `x` range spans the full\n * plot height, so its top and bottom edges are the plot's own border, not a data\n * bound — drawing dashes there would assert a limit the author didn't set.\n */\nexport const ChartRegion = component2d({\n key: \"chartRegion\",\n state: {\n /** The highlighted slice, already resolved into this node's local pixel space (origin at centre, y-up) by the parent {@link LineChart}. A degenerate box draws nothing. */\n box: fresh<RegionBox>(() => EMPTY_REGION_BOX),\n /** Dashed rule marking each *bounded* edge of the box. */\n stroke: Types.custom<Stroke, StrokeResolved[]>(DEFAULT_CHART_THEME.region.stroke, { resolve: strokeOps.resolve, lerp: strokeOps.lerp }),\n /** Wash filling the box, under the series lines. */\n fill: Types.custom<Fill, FillResolved[]>(DEFAULT_CHART_THEME.region.fill, { resolve: fillOps.resolve, lerp: fillOps.lerp }),\n /** Reveal of the annotation in `[0, 1]`, driven by the chart's own `regionReveal` so the rules and the series' dimming move as one. */\n reveal: 0,\n },\n load: (loader, state) => loadPaints(loader, { fills: [state.fill], strokes: [state.stroke] }),\n render: (ctx, state) => {\n const box = state.box\n if (!hasRegion(box)) return\n\n const r = Math.max(0, Math.min(1, state.reveal))\n if (r <= 0) return\n\n const width = box.right - box.left\n const height = box.top - box.bottom\n const cx = (box.left + box.right) / 2\n const cy = (box.bottom + box.top) / 2\n\n // Wash first, so the rules sit over their own tint.\n if (state.fill.length > 0) {\n ctx.draw(new Graphics2D().rect({ x: cx, y: cy, width, height }).fill(state.fill).opacity(r))\n }\n\n // One rule per bounded edge, growing from the region's centre outward as\n // `reveal` climbs — the same \"trace it in\" beat as the series lines.\n if (state.stroke.length === 0) return\n\n // One `draw` per rule rather than four line ops under a single paint:\n // shapes chained before a `stroke()` are combined into one surface, and\n // stroking a union of disjoint open paths doesn't paint.\n const rule = (points: { x: number; y: number }[]) =>\n ctx.draw(new Graphics2D().line({ points }).stroke(state.stroke).opacity(r))\n\n if (box.xBounded) {\n const half = (height / 2) * r\n for (const x of [box.left, box.right]) rule([{ x, y: cy - half }, { x, y: cy + half }])\n }\n if (box.yBounded) {\n const half = (width / 2) * r\n for (const y of [box.bottom, box.top]) rule([{ x: cx - half, y }, { x: cx + half, y }])\n }\n },\n})\n\nexport type ChartRegion = NodeOf<typeof ChartRegion>\n"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"horizontal-axis.js","sourceRoot":"","sources":["../../src/line-chart/horizontal-axis.ts"],"names":[],"mappings":"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","sourcesContent":["import {\r\n Rect,\r\n Text,\r\n Types,\r\n component2d,\r\n insetsOps,\r\n textOps,\r\n type NodeOf,\r\n type Node2D,\r\n} from \"@motionscript/sdk\";\r\n\r\nimport { asParts, fresh } from \"../kit/entries\";\r\nimport { armed, arrival, arrivalOf, arrivalsEntry, beats, frameEase, type Arrival } from \"../kit/motion\";\r\nimport {\r\n DEFAULT_X_AXIS,\r\n enterBudget,\r\n type AxisConfig,\r\n type Range,\r\n} from \"../kit/shared\";\r\nimport { markerCaption } from \"../kit/vertical-axis\";\r\n\r\n/** How far a marker starts above its slot when it enters, in px. */\r\nconst SLIDE = 24;\r\n\r\n/**\r\n * The horizontal axis of a {@link LineChart}: a **row of {@link Text} nodes**,\r\n * one per marker value, running left-to-right. Pure layout — the mirror of the\r\n * kit's `VerticalAxis`, including its bound (not snapshotted) marker text and\r\n * positions, and its landed resting state.\r\n *\r\n * Markers are always placed **by value** across the range, whatever they say:\r\n * `2026-03` sits three months along, not three slots along. That is what keeps\r\n * it distinct from a bar chart's bottom axis, which centres a caption on each\r\n * slot and has no scale at all — the two only look alike. What the values are\r\n * captioned *as* is the chart's to decide, in `captions`.\r\n *\r\n * `enter` staggers the markers in **left-to-right**: each starts lifted a\r\n * little above its slot and transparent, then fades and slides down into place.\r\n */\r\nexport const HorizontalAxis = component2d({\r\n key: \"horizontalAxis\",\r\n state: {\r\n /** `[min, max]` of the horizontal scale the markers are positioned within. */\r\n range: fresh<Range>(() => [0, 1]),\r\n /** Tick values (in data units) to draw along the axis. */\r\n markers: fresh<number[]>(() => []),\r\n /**\r\n * How each marker is captioned, one per entry of `markers` and in its order.\r\n * Empty (the default), or short, captions a marker with its bare numeric\r\n * reading; a chart whose x column names months or categories writes those.\r\n */\r\n captions: fresh<string[]>(() => []),\r\n /** Marker/caption text style, grid stroke, and gutters — see {@link AxisConfig}. */\r\n axis: Types.custom<AxisConfig>(DEFAULT_X_AXIS),\r\n /** Caption drawn centred in the gutter beneath the marker row; empty (the default) hides it. */\r\n label: \"\",\r\n arrivals: arrivalsEntry(),\r\n },\r\n // A plain node filled its parent; one made of its markers would hug them.\r\n defaults: { width: \"fill\", height: \"fill\" },\r\n children: (state) => {\r\n const tickPad = insetsOps.resolve(state.axis.tickPadding).top;\r\n const titlePad = insetsOps.resolve(state.axis.titlePadding).top;\r\n\r\n const column: Node2D[] = [];\r\n // The column's parent is the axis: its box is what the markers are placed in.\r\n const box = () => (column[0]?.parent as Node2D | null | undefined)?.layoutBounds ?? { width: 0, height: 0 };\r\n /** The live tick values, left → right — re-read every frame, not snapshotted. */\r\n const sorted = () => [...state.markers].sort((a, b) => a - b);\r\n /** Tick `i`'s fraction across the live `range`, 0 at the left edge. */\r\n const fracAt = (value: number | undefined) => {\r\n if (value === undefined) return 0;\r\n const [min, max] = state.range;\r\n return max <= min ? 0 : (value - min) / (max - min);\r\n };\r\n\r\n const markers = state.markers.map((_, i) => {\r\n const marker: Node2D = new Text({\r\n ...textOps.styleProps(state.axis.labelStyle),\r\n text: () => {\r\n const value = sorted()[i];\r\n return value === undefined ? \"\" : markerCaption(state, value);\r\n },\r\n x: () => {\r\n const width = box().width;\r\n const centred = (fracAt(sorted()[i]) - 0.5) * width;\r\n // Held inside the axis's right edge, which is also the *chart's*: the\r\n // last marker is centred on the last grid line, so half of `2026-06`\r\n // — or of `3300` — would be drawn outside the node's box and outside\r\n // the rectangle the editor draws around it. Only the right edge is\r\n // held, because the left one has the vertical axis's whole gutter\r\n // beyond it, and a marker overhanging into that is inside the chart.\r\n const limit = width / 2 - marker.layoutBounds.width / 2;\r\n return Math.min(centred, limit);\r\n },\r\n opacity: () => arrivalOf(state.arrivals, i).opacity,\r\n y: () => arrivalOf(state.arrivals, i).shift,\r\n });\r\n return marker;\r\n });\r\n\r\n const children: Node2D[] = [\r\n new Rect({ width: \"fill\", height: \"hug\", padding: { top: tickPad }, children: markers }),\r\n ];\r\n if (state.label !== \"\") {\r\n children.push(\r\n new Text({\r\n ...textOps.styleProps(state.axis.titleStyle),\r\n text: state.label,\r\n opacity: () => arrivalOf(state.arrivals, \"label\").opacity,\r\n y: () => arrivalOf(state.arrivals, \"label\").shift,\r\n }),\r\n );\r\n }\r\n\r\n column.push(new Rect({ flow: \"vertical\", gap: titlePad, height: \"hug\", width: \"fill\", children }));\r\n return asParts(column);\r\n },\r\n commands: {\r\n /**\r\n * Stagger the markers in left to right, then slide the caption in after\r\n * them. Its first frame arms them all: lifted by `slide` and transparent.\r\n *\r\n * The timeline's duration is the **whole** entrance — see\r\n * `VerticalAxis.enter` and {@link enterBudget}.\r\n */\r\n enter: {\r\n args: {\r\n stagger: Types.custom<number | undefined>(undefined),\r\n slide: Types.number(SLIDE),\r\n },\r\n run: (timeline, state) => {\r\n const { stagger, slide } = timeline.args;\r\n const count = state.markers.length;\r\n const captioned = state.label !== \"\";\r\n const from: Arrival = { opacity: 0, shift: slide };\r\n const keys = [...state.markers.keys(), ...(captioned ? [\"label\"] : [])];\r\n const arm = timeline.animate(() => ({ arrivals: armed(keys, from) }));\r\n if (count === 0) return arm;\r\n const { step, per, caption } = enterBudget(timeline.duration, count, captioned, stagger);\r\n const ease = frameEase(timeline);\r\n // Left marker leads: the row is already left → right.\r\n const markers = state.markers.map((_, i) => ({ at: i * step, duration: per, piece: arrival(timeline, i, from, ease) }));\r\n const label = captioned ? [{ at: (count - 1) * step + per, duration: caption, piece: arrival(timeline, \"label\", from, ease) }] : [];\r\n return timeline.together([arm, beats(timeline, [...markers, ...label])]);\r\n },\r\n },\r\n },\r\n});\r\n\r\nexport type HorizontalAxis = NodeOf<typeof HorizontalAxis>;\r\n"]}
|
|
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"]}
|
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
* (the plot panel, the value axis, the legend); each part is exported too, so
|
|
7
7
|
* another node type can reuse one on its own.
|
|
8
8
|
*
|
|
9
|
-
* These files are what
|
|
9
|
+
* These files are what a copy of the line chart takes (`registry.json`). Everything they reach for
|
|
10
10
|
* that is *not* here comes from the kit and stays a dependency — see
|
|
11
11
|
* `../engine.ts` for why that line is where it is.
|
|
12
12
|
*/
|
package/dist/line-chart/index.js
CHANGED
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
* (the plot panel, the value axis, the legend); each part is exported too, so
|
|
7
7
|
* another node type can reuse one on its own.
|
|
8
8
|
*
|
|
9
|
-
* These files are what
|
|
9
|
+
* These files are what a copy of the line chart takes (`registry.json`). Everything they reach for
|
|
10
10
|
* that is *not* here comes from the kit and stays a dependency — see
|
|
11
11
|
* `../engine.ts` for why that line is where it is.
|
|
12
12
|
*/
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/line-chart/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AACH,OAAO,EAAE,SAAS,EAAE,gBAAgB,EAAE,MAAM,cAAc,CAAA;AAE1D,OAAO,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAA;AAC5C,OAAO,EAAE,SAAS,EAAE,MAAM,cAAc,CAAA;AACxC,OAAO,EAAE,cAAc,EAAE,MAAM,mBAAmB,CAAA;AAClD,OAAO,EACL,mBAAmB,EACnB,gBAAgB,EAChB,iBAAiB,EACjB,SAAS,EACT,cAAc,EACd,iBAAiB,EACjB,gBAAgB,EAChB,aAAa,EACb,YAAY,EACZ,OAAO,GACR,MAAM,UAAU,CAAA;AASjB,OAAO,EAAE,aAAa,EAAE,YAAY,EAAE,aAAa,EAAE,MAAM,WAAW,CAAA","sourcesContent":["/**\
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/line-chart/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AACH,OAAO,EAAE,SAAS,EAAE,gBAAgB,EAAE,MAAM,cAAc,CAAA;AAE1D,OAAO,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAA;AAC5C,OAAO,EAAE,SAAS,EAAE,MAAM,cAAc,CAAA;AACxC,OAAO,EAAE,cAAc,EAAE,MAAM,mBAAmB,CAAA;AAClD,OAAO,EACL,mBAAmB,EACnB,gBAAgB,EAChB,iBAAiB,EACjB,SAAS,EACT,cAAc,EACd,iBAAiB,EACjB,gBAAgB,EAChB,aAAa,EACb,YAAY,EACZ,OAAO,GACR,MAAM,UAAU,CAAA;AASjB,OAAO,EAAE,aAAa,EAAE,YAAY,EAAE,aAAa,EAAE,MAAM,WAAW,CAAA","sourcesContent":["/**\n * The line chart: a cartesian plot with a traced polyline, spotlit regions and\n * a staggered entrance.\n *\n * {@link LineChart} composes the parts below plus the shared ones in the kit\n * (the plot panel, the value axis, the legend); each part is exported too, so\n * another node type can reuse one on its own.\n *\n * These files are what a copy of the line chart takes (`registry.json`). Everything they reach for\n * that is *not* here comes from the kit and stays a dependency — see\n * `../engine.ts` for why that line is where it is.\n */\nexport { LineChart, lineChartDomains } from \"./line-chart\"\nexport type { LineChartDomains, LineChartProps, LineChartValues } from \"./line-chart\"\nexport { ChartRegion } from \"./chart-region\"\nexport { ChartLine } from \"./chart-line\"\nexport { HorizontalAxis } from \"./horizontal-axis\"\nexport {\n DEFAULT_CHART_THEME,\n EMPTY_REGION_BOX,\n clipPolylineToBox,\n hasRegion,\n lerpChartTheme,\n resolveChartTheme,\n resolveRegionBox,\n resolveYScale,\n seriesPoints,\n yExtent,\n} from \"./shared\"\nexport type {\n ChartConfig,\n ChartTheme,\n LineSeries,\n PlotRegion,\n RegionBox,\n RegionConfig,\n} from \"./shared\"\nexport { formatInstant, parseInstant, resolveXScale } from \"./x-scale\"\nexport type { XScale, XScaleKind } from \"./x-scale\"\n"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"line-chart.js","sourceRoot":"","sources":["../../src/line-chart/line-chart.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,IAAI,EACJ,KAAK,EACL,WAAW,EACX,OAAO,GAWR,MAAM,mBAAmB,CAAA;AAC1B,OAAO,EAAE,YAAY,EAAE,MAAM,6BAA6B,CAAA;AAE1D,OAAO,EAAE,cAAc,EAAE,cAAc,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAA;AAC9E,OAAO,EAAE,WAAW,EAAE,MAAM,qBAAqB,CAAA;AACjD,OAAO,EAAE,WAAW,EAAE,MAAM,qBAAqB,CAAA;AACjD,OAAO,EAAE,WAAW,EAAE,MAAM,qBAAqB,CAAA;AACjD,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,MAAM,gBAAgB,CAAA;AAC/C,OAAO,EAAE,KAAK,EAAa,MAAM,eAAe,CAAA;AAChD,OAAO,EAAE,YAAY,EAAE,MAAM,sBAAsB,CAAA;AACnD,OAAO,EACL,aAAa,EACb,YAAY,EACZ,cAAc,EACd,aAAa,EACb,UAAU,EACV,YAAY,EACZ,iBAAiB,EACjB,iBAAiB,EACjB,mBAAmB,EACnB,gBAAgB,GAGjB,MAAM,eAAe,CAAA;AACtB,OAAO,EAAE,SAAS,EAAE,MAAM,cAAc,CAAA;AACxC,OAAO,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAA;AAC5C,OAAO,EAAE,cAAc,EAAE,MAAM,mBAAmB,CAAA;AAClD,OAAO,EACL,mBAAmB,EACnB,cAAc,EACd,iBAAiB,EACjB,gBAAgB,EAChB,aAAa,EACb,YAAY,GAMb,MAAM,UAAU,CAAA;AACjB,OAAO,EAAE,aAAa,EAAe,MAAM,WAAW,CAAA;AAgDtD;;;GAGG;AACH,MAAM,UAAU,GAAG,KAAK,CAAC,MAAM,CAAiF,CAAC,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,GAAG,EAAE,CAAC,EAAE,IAAI,EAAE,CAAC,EAAE,CAAC,CAAA;AAEvJ,8HAA8H;AAC9H,MAAM,UAAU,GAAG,KAAK,CAAC,MAAM,CAAyB,SAAS,EAAE;IACjE,IAAI,EAAE,QAAQ;IACd,UAAU,EAAE;QACV,CAAC,EAAE,EAAE,IAAI,EAAE,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,UAAU,EAAE,CAAC,EAAE,UAAU,EAAE,GAAG,EAAE;QACnE,CAAC,EAAE,EAAE,IAAI,EAAE,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,UAAU,EAAE,CAAC,EAAE,UAAU,EAAE,GAAG,EAAE;KACrE;CACF,CAAC,CAAA;AAEF,sEAAsE;AACtE,MAAM,YAAY,GAAG,EAAE,CAAA;AAEvB,iEAAiE;AACjE,MAAM,eAAe,GAAG,CAAC,CAAA;AAEzB;;;;GAIG;AACH,MAAM,UAAU,GAAG,IAAI,CAAA;AACvB,MAAM,WAAW,GAAG,GAAG,CAAA;AACvB,MAAM,YAAY,GAAG,IAAI,CAAA;AAUzB;;;GAGG;AACH,SAAS,QAAQ,CAAC,CAAkB,EAAE,MAAM,GAAG,CAAC,CAAC,KAAK,CAAC,MAAM;IAC3D,OAAO,aAAa,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;AAChD,CAAC;AAED;;;;GAIG;AACH,SAAS,MAAM,CAAC,CAAkB,EAAE,MAAwB;IAC1D,MAAM,MAAM,GAAG,QAAQ,CAAC,CAAC,EAAE,MAAM,CAAC,MAAM,CAAC,CAAA;IACzC,MAAM,KAAK,GAAG,MAAM,CAAC,KAAK,IAAI,MAAM,CAAC,MAAM,CAAA;IAC3C,OAAO,EAAE,GAAG,MAAM,EAAE,KAAK,EAAE,KAAK,EAAE,MAAM,CAAC,KAAK,IAAI,MAAM,CAAC,KAAK,CAAC,KAAK,EAAE,eAAe,GAAG,CAAC,CAAC,EAAE,CAAA;AAC9F,CAAC;AAED;;;;GAIG;AACH,SAAS,MAAM,CAAC,CAAkB,EAAE,MAAwB;IAC1D,MAAM,SAAS,GAAG,CAAC,MAAM,CAAC,KAAK,EAAE,MAAM,IAAI,eAAe,CAAC,GAAG,CAAC,CAAA;IAC/D,MAAM,KAAK,GAAG,aAAa,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC,MAAM,EAAE,MAAM,CAAC,KAAK,EAAE,SAAS,CAAC,CAAA;IACtE,OAAO,EAAE,GAAG,MAAM,EAAE,KAAK,EAAE,KAAK,EAAE,MAAM,CAAC,KAAK,IAAI,YAAY,CAAC,KAAK,EAAE,eAAe,GAAG,CAAC,CAAC,EAAE,CAAA;AAC9F,CAAC;AAED,2FAA2F;AAC3F,MAAM,YAAY,GAAG,IAAI,OAAO,EAG7B,CAAA;AAEH,+FAA+F;AAC/F,MAAM,UAAU,gBAAgB,CAAC,CAAkB;IACjD,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,KAAK,EAAE,MAAM,EAAE,GAAG,CAAC,CAAA;IAChD,MAAM,IAAI,GAAG,YAAY,CAAC,GAAG,CAAC,IAAI,CAAC,CAAA;IACnC,IAAI,IAAI,IAAI,IAAI,CAAC,MAAM,KAAK,MAAM,IAAI,IAAI,CAAC,KAAK,KAAK,KAAK,IAAI,IAAI,CAAC,KAAK,KAAK,KAAK,IAAI,IAAI,CAAC,MAAM,KAAK,MAAM,EAAE,CAAC;QAC7G,OAAO,IAAI,CAAC,OAAO,CAAA;IACrB,CAAC;IACD,MAAM,OAAO,GAAG;QACd,CAAC,EAAE,gBAAgB,CAAC,KAAK,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,MAAM,CAAC,CAAC,EAAE,CAAC,CAAC,CAA0B;QACxE,CAAC,EAAE,gBAAgB,CAAC,KAAK,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,MAAM,CAAC,CAAC,EAAE,CAAC,CAAC,CAA0B;KACzE,CAAA;IACD,YAAY,CAAC,GAAG,CAAC,IAAI,EAAE,EAAE,MAAM,EAAE,KAAK,EAAE,KAAK,EAAE,MAAM,EAAE,OAAO,EAAE,CAAC,CAAA;IACjE,OAAO,OAAO,CAAA;AAChB,CAAC;AAED;;;GAGG;AACH,SAAS,YAAY,CAAC,CAAkB,EAAE,OAAyB,EAAE,KAAa,EAAE,IAAY;IAC9F,MAAM,MAAM,GAAG,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAA;IAC9B,IAAI,CAAC,MAAM;QAAE,OAAO,EAAE,CAAA;IACtB,MAAM,MAAM,GAAG,YAAY,CAAC,CAAC,CAAC,IAAI,EAAE,QAAQ,CAAC,CAAC,CAAC,EAAE,MAAM,CAAC,CAAA;IACxD,IAAI,MAAM,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,EAAE,CAAA;IAClC,MAAM,EAAE,KAAK,EAAE,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,GAAG,IAAI,CAAA;IACpC,MAAM,CAAC,IAAI,EAAE,IAAI,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC,KAAK,CAAA;IACpC,MAAM,CAAC,IAAI,EAAE,IAAI,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC,KAAK,CAAA;IACpC,MAAM,KAAK,GAAG,CAAC,CAAS,EAAE,EAAE,CAAC,CAAC,IAAI,IAAI,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,IAAI,CAAC,GAAG,CAAC,IAAI,GAAG,IAAI,CAAC,GAAG,GAAG,CAAC,GAAG,CAAC,CAAC,CAAA;IACxF,MAAM,KAAK,GAAG,CAAC,CAAS,EAAE,EAAE,CAAC,CAAC,IAAI,IAAI,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,IAAI,CAAC,GAAG,CAAC,IAAI,GAAG,IAAI,CAAC,GAAG,GAAG,CAAC,GAAG,CAAC,CAAC,CAAA;IACxF,8CAA8C;IAC9C,OAAO,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,EAAE,CAAC,EAAE,KAAK,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,KAAK,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAA;AAC/D,CAAC;AAED,+GAA+G;AAC/G,SAAS,SAAS,CAAC,CAA2D,EAAE,OAAyB,EAAE,IAAY;IACrH,MAAM,EAAE,KAAK,EAAE,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,GAAG,IAAI,CAAA;IACpC,OAAO,gBAAgB,CAAC,CAAC,CAAC,MAAM,EAAE,EAAE,IAAI,EAAE,CAAC,CAAC,GAAG,CAAC,EAAE,KAAK,EAAE,CAAC,GAAG,CAAC,EAAE,MAAM,EAAE,CAAC,CAAC,GAAG,CAAC,EAAE,GAAG,EAAE,CAAC,GAAG,CAAC,EAAE,EAAE,OAAO,CAAC,CAAC,CAAC,KAAK,EAAE,OAAO,CAAC,CAAC,CAAC,KAAK,CAAC,CAAA;AACjI,CAAC;AAED;;;;GAIG;AACH,SAAS,UAAU,CAAC,CAAyC;IAC3D,MAAM,MAAM,GAAG,CAAC,CAAC,MAAM,CAAA;IACvB,OAAO,MAAM,IAAI,IAAI,IAAI,CAAC,MAAM,CAAC,CAAC,KAAK,SAAS,IAAI,MAAM,CAAC,CAAC,KAAK,SAAS,CAAC,CAAA;AAC7E,CAAC;AAED,gHAAgH;AAChH,SAAS,SAAS,CAAC,MAAqC;IACtD,OAAO,MAAM,IAAI,IAAI,IAAI,OAAO,MAAM,KAAK,QAAQ,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAA;AACnE,CAAC;AAED,uEAAuE;AACvE,SAAS,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,CAAQ;IACzB,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAA;AACjC,CAAC;AAED;;;GAGG;AACH,SAAS,OAAO,CAAC,KAAY,EAAE,KAAwB;IACrD,MAAM,EAAE,GAAG,IAAI,CAAC,KAAK,CAAC,CAAA;IACtB,OAAO,EAAE,KAAK,EAAE,EAAE,EAAE,KAAK,EAAE,YAAY,CAAC,EAAE,EAAE,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,KAAK,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,EAAE,CAAA;AAC9E,CAAC;AAED,gEAAgE;AAChE,SAAS,MAAM,CAAC,IAAsB,EAAE,EAAgD,EAAE,CAAS;IACjG,OAAO;QACL,GAAG,CAAC,EAAE,CAAC,CAAC,IAAI,EAAE,KAAK,EAAE,cAAc,CAAC,IAAI,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC;QACvD,GAAG,CAAC,EAAE,CAAC,CAAC,IAAI,EAAE,KAAK,EAAE,cAAc,CAAC,IAAI,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC;KACxD,CAAA;AACH,CAAC;AAID,2EAA2E;AAC3E,SAAS,OAAO,CAAC,QAA8B;IAC7C,MAAM,KAAK,GAAG,cAAc,CAAC,QAAQ,CAAC,CAAA;IACtC,IAAI,CAAC,KAAK;QAAE,OAAO,IAAI,CAAA;IACvB,MAAM,KAAK,GAAG,KAAK,CAAC,KAAK,CAAC,IAAI,CAAC,cAAc,CAAC,EAAE,CAAC,CAAA;IACjD,IAAI,CAAC,YAAY,CAAC,EAAE,CAAC,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,KAAK;QAAE,OAAO,IAAI,CAAA;IACvD,OAAO;QACL,KAAK,EAAE,KAAK,CAAC,IAAI;QACjB,KAAK;QACL,KAAK,EAAE,KAAK,CAAC,IAAI,CAAC,MAAM,CAAC,SAAS,CAAC,EAAE,CAAC;QACtC,MAAM,EAAE,KAAK,CAAC,KAAK,CAAC,IAAI,CAAC,WAAW,CAAC,EAAE,CAAC,IAAI,IAAI;KACjD,CAAA;AACH,CAAC;AAED,iGAAiG;AACjG,SAAS,QAAQ,CAAC,QAAqB,EAAE,KAAgB;IACvD,MAAM,IAAI,GAAG,KAAK,CAAC,YAAY,CAAA;IAC/B,MAAM,MAAM,GAAG,KAAK,CAAC,MAAM,CAAA;IAC3B,yEAAyE;IACzE,IAAI,IAAI,KAAK,CAAC;QAAE,OAAO,QAAQ,CAAC,OAAO,CAAC,GAAG,EAAE,CAAC,CAAC,EAAE,MAAM,EAAE,IAAI,EAAE,YAAY,EAAE,CAAC,EAAE,CAAC,EAAE,EAAE,KAAK,EAAE,KAAK,EAAE,CAAC,CAAA;IACpG,0FAA0F;IAC1F,OAAO,QAAQ,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,EAAE,MAAM,EAAE,IAAI,EAAE,YAAY,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,MAAM,EAAE,YAAY,EAAE,IAAI,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC,EAAE,CAAC,CAAC,CAAA;AACzH,CAAC;AAED,8FAA8F;AAC9F,SAAS,QAAQ,CAAC,QAAqB,EAAE,QAA8B,EAAE,KAAa,EAAE,IAAa;IACnG,MAAM,KAAK,GAAG,OAAO,CAAC,QAAQ,CAAC,CAAA;IAC/B,MAAM,IAAI,GAAG,KAAK,EAAE,KAAK,CAAC,KAAK,CAAC,CAAA;IAChC,IAAI,CAAC,KAAK,IAAI,CAAC,IAAI;QAAE,OAAO,QAAQ,CAAC,IAAI,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAA;IAC5D,OAAO,QAAQ,CAAC,QAAQ,CAAC;QACvB,IAAI,CAAC,GAAG,CAAC,OAAO,EAAE,IAAI,CAAC,CAAC,CAAC,EAAE,IAAI,EAAE,CAAC,EAAE,EAAE,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,IAAI,EAAE,CAAC,EAAE,EAAE,EAAE,CAAC,EAAE,CAAC;QACjE,GAAG,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,MAAM,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,YAAY,EAAE,EAAE,KAAK,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;KAC3F,CAAC,CAAA;AACJ,CAAC;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AACH,MAAM,CAAC,MAAM,SAAS,GAAG,WAAW,CAAC;IACnC,GAAG,EAAE,WAAW;IAChB,KAAK,EAAE;QACL,IAAI,EAAE,KAAK,CAAe,GAAG,EAAE,CAAC,EAAE,EAAE,EAAE,IAAI,EAAE,SAAS,EAAE,CAAC;QACxD,MAAM,EAAE,EAAE;QACV,MAAM,EAAE,KAAK,CAAe,GAAG,EAAE,CAAC,EAAE,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,CAAC;QACzD,KAAK,EAAE,KAAK,CAAC,MAAM,CAAmB,EAAE,EAAE,EAAE,OAAO,EAAE,iBAAiB,EAAE,IAAI,EAAE,aAAa,EAAE,CAAC;QAC9F,KAAK,EAAE,KAAK,CAAC,MAAM,CAAmB,EAAE,EAAE,EAAE,OAAO,EAAE,iBAAiB,EAAE,IAAI,EAAE,aAAa,EAAE,CAAC;QAC9F,KAAK,EAAE,KAAK,CAAC,MAAM,CAA0B,mBAAmB,EAAE,EAAE,OAAO,EAAE,iBAAiB,EAAE,IAAI,EAAE,cAAc,EAAE,CAAC;QACvH;;;WAGG;QACH,MAAM,EAAE,KAAK,CAAC,MAAM,CAAoB,IAAI,CAAC;QAC7C;;;;WAIG;QACH,YAAY,EAAE,CAAC;QACf,oFAAoF;QACpF,UAAU,EAAE,KAAK,CAAC,OAAO,CAAC,IAAI,EAAE,EAAE,UAAU,EAAE,KAAK,EAAE,CAAC;QACtD;;;;WAIG;QACH,IAAI,EAAE,KAAK,CAAC,MAAM,CAA0B,IAAI,EAAE,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC;KACrE;IACD,yDAAyD;IACzD,QAAQ,EAAE,EAAE,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE;IAC3C,eAAe,EAAE,EAAE;IACnB,QAAQ,EAAE,CAAC,KAAK,EAAE,EAAE;QAClB,MAAM,KAAK,GAAG,GAAG,EAAE,CAAC,KAAK,CAAC,KAAK,CAAA;QAC/B,MAAM,OAAO,GAAG,GAAG,EAAE,CAAC,gBAAgB,CAAC,KAAK,CAAC,CAAA;QAC7C,IAAI,IAAwB,CAAA;QAC5B,MAAM,QAAQ,GAAG,GAAG,EAAE,CAAC,WAAW,CAAC,IAAI,CAAC,CAAA;QACxC,MAAM,OAAO,GAAG,KAAK,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,OAAO,IAAI,IAAI,CAAC,CAAA;QAE1D,6EAA6E;QAC7E,2EAA2E;QAC3E,MAAM,KAAK,GAAG,IAAI,YAAY,CAAC;YAC7B,KAAK,EAAE,GAAG,EAAE,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC,KAAK;YAC9B,OAAO,EAAE,GAAG,EAAE,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC,KAAK;YAChC,qEAAqE;YACrE,QAAQ,EAAE,GAAG,EAAE;gBACb,MAAM,OAAO,GAAG,OAAO,EAAE,CAAC,CAAC,CAAC,KAAK,CAAA;gBACjC,MAAM,MAAM,GAAG,KAAK,CAAC,KAAK,CAAC,MAAM,CAAA;gBACjC,OAAO,OAAO,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC,MAAM,KAAK,SAAS,CAAC,CAAC,CAAC,YAAY,CAAC,KAAK,EAAE,UAAU,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC,YAAY,CAAC,KAAK,EAAE,MAAM,CAAC,CAAC,CAAC,CAAA;YAChI,CAAC;YACD,IAAI,EAAE,GAAG,EAAE,CAAC,KAAK,EAAE,CAAC,KAAK;YACzB,KAAK,EAAE,KAAK,CAAC,KAAK,CAAC,KAAK,IAAI,EAAE;YAC9B,KAAK,EAAE,KAAK;YACZ,MAAM,EAAE,MAAM;SACf,CAAC,CAAA;QAEF,MAAM,KAAK,GAAG,IAAI,cAAc,CAAC;YAC/B,KAAK,EAAE,GAAG,EAAE,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC,KAAK;YAC9B,OAAO,EAAE,GAAG,EAAE,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC,KAAK;YAChC,0EAA0E;YAC1E,gDAAgD;YAChD,QAAQ,EAAE,GAAG,EAAE;gBACb,MAAM,MAAM,GAAG,QAAQ,CAAC,KAAK,CAAC,CAAA;gBAC9B,OAAO,OAAO,EAAE,CAAC,CAAC,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,MAAM,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,CAAA;YAC9D,CAAC;YACD,IAAI,EAAE,GAAG,EAAE,CAAC,KAAK,EAAE,CAAC,KAAK;YACzB,KAAK,EAAE,KAAK,CAAC,KAAK,CAAC,KAAK,IAAI,EAAE;YAC9B,KAAK,EAAE,MAAM;YACb,MAAM,EAAE,KAAK;SACd,CAAC,CAAA;QAEF,MAAM,KAAK,GAAG,KAAK,CAAC,MAAM,CAAC,GAAG,CAC5B,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CACP,IAAI,SAAS,CAAC;YACZ,MAAM,EAAE,GAAG,EAAE,CAAC,YAAY,CAAC,KAAK,EAAE,OAAO,EAAE,EAAE,CAAC,EAAE,QAAQ,EAAE,CAAC;YAC3D,MAAM,EAAE,GAAG,EAAE,CAAC,mBAAmB,CAAC,KAAK,EAAE,CAAC,YAAY,EAAE,CAAC,EAAE,CAAC,CAAC;YAC7D,OAAO,EAAE,OAAO,CAAC,CAAC,CAAC;YACnB,sEAAsE;YACtE,uDAAuD;YACvD,SAAS,EAAE,GAAG,EAAE,CAAC,SAAS,CAAC,KAAK,EAAE,OAAO,EAAE,EAAE,QAAQ,EAAE,CAAC;YACxD,sEAAsE;YACtE,UAAU,EAAE,GAAG,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,GAAG,KAAK,EAAE,CAAC,MAAM,CAAC,UAAU,CAAC,GAAG,KAAK,CAAC,YAAY;SAC3E,CAAsB,CAC1B,CAAA;QAED,MAAM,KAAK,GAAa,CAAC,KAA0B,CAAC,CAAA;QACpD,IAAI,KAAK,CAAC,UAAU,KAAK,KAAK,EAAE,CAAC;YAC/B,KAAK,CAAC,IAAI,CACR,IAAI,WAAW,CAAC;gBACd,MAAM,EAAE,KAAK,CAAC,MAAM;gBACpB,0EAA0E;gBAC1E,oDAAoD;gBACpD,QAAQ,EAAE,GAAG,EAAE,CAAC,KAAK,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,iBAAiB,CAAC,KAAK,EAAE,CAAC,YAAY,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC;gBACzF,MAAM,EAAE,GAAG,EAAE,CAAC,KAAK,EAAE,CAAC,MAAM;gBAC5B,oEAAoE;gBACpE,sEAAsE;gBACtE,GAAG,EAAE,KAAK,CAAC,KAAK,CAAC,MAAM,CAAC,OAAO;gBAC/B,OAAO,EAAE,KAAK,CAAC,KAAK,CAAC,MAAM,CAAC,OAAO;aACpC,CAAsB,CACxB,CAAA;QACH,CAAC;QAED,IAAI,GAAG,IAAI,IAAI,CAAC;YACd,IAAI,EAAE,IAAI;YACV,QAAQ,EAAE;gBACR,IAAI,WAAW,CAAC;oBACd,IAAI,EAAE,GAAG,EAAE,CAAC,KAAK,EAAE,CAAC,QAAQ,CAAC,IAAI;oBACjC,MAAM,EAAE,GAAG,EAAE,CAAC,KAAK,EAAE,CAAC,QAAQ,CAAC,MAAM;oBACrC,WAAW,EAAE,GAAG,EAAE,CAAC,KAAK,EAAE,CAAC,KAAK,CAAC,SAAS;oBAC1C,WAAW,EAAE,GAAG,EAAE,CAAC,KAAK,EAAE,CAAC,KAAK,CAAC,SAAS;oBAC1C,mEAAmE;oBACnE,QAAQ,EAAE,GAAG,EAAE,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC,KAAK;oBACjC,QAAQ,EAAE,GAAG,EAAE,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC,KAAK;oBACjC,OAAO,EAAE,GAAG,EAAE,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC,KAAK;oBAChC,OAAO,EAAE,GAAG,EAAE,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC,KAAK;iBACjC,CAAC;gBACF,yEAAyE;gBACzE,gDAAgD;gBAChD,IAAI,WAAW,CAAC;oBACd,GAAG,EAAE,GAAG,EAAE,CAAC,SAAS,CAAC,KAAK,EAAE,OAAO,EAAE,EAAE,QAAQ,EAAE,CAAC;oBAClD,MAAM,EAAE,GAAG,EAAE,CAAC,KAAK,EAAE,CAAC,MAAM,CAAC,MAAM;oBACnC,IAAI,EAAE,GAAG,EAAE,CAAC,KAAK,EAAE,CAAC,MAAM,CAAC,IAAI;oBAC/B,MAAM,EAAE,GAAG,EAAE,CAAC,KAAK,CAAC,YAAY;iBACjC,CAAC;gBACF,GAAG,KAAK;gBACR,IAAI,WAAW,CAAC,EAAE,MAAM,EAAE,GAAG,EAAE,CAAC,KAAK,EAAE,CAAC,QAAQ,CAAC,MAAM,EAAE,CAAC;aAC3D;SACF,CAAsB,CAAA;QAEvB,MAAM,MAAM,GAAG,IAAI,YAAY,CAAC;YAC9B,OAAO,EAAE,CAAC;YACV,KAAK,EAAE,GAAG,EAAE,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC,KAAK;YAC9B,OAAO,EAAE,GAAG,EAAE,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC,KAAK;YAChC,IAAI,EAAE,GAAG,EAAE,CAAC,KAAK,EAAE,CAAC,KAAK;YACzB,KAAK,EAAE,KAAK,CAAC,KAAK,CAAC,KAAK,IAAI,EAAE;YAC9B,KAAK,EAAE,KAAK;YACZ,MAAM,EAAE,CAAC;SACV,CAAsB,CAAA;QAEvB,OAAO,OAAO,CAAC,CAAC,cAAc,CAAC,EAAE,IAAI,EAAE,KAA0B,EAAE,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,CAAC,CAAC,CAAC,CAAA;IAC7F,CAAC;IACD,QAAQ,EAAE;QACR;;;;;;;;WAQG;QACH,KAAK,EAAE;YACL,IAAI,EAAE,EAAE;YACR,+EAA+E;YAC/E,QAAQ,EAAE,IAAI;YACd,MAAM,EAAE,OAAO,EAAE;YACjB,GAAG,EAAE,CAAC,QAAQ,EAAE,KAAK,EAAE,QAAQ,EAAE,EAAE;gBACjC,MAAM,KAAK,GAAG,OAAO,CAAC,QAAQ,CAAC,CAAA;gBAC/B,IAAI,CAAC,KAAK;oBAAE,OAAO,QAAQ,CAAC,IAAI,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAA;gBACnD,MAAM,QAAQ,GAAG,QAAQ,CAAC,QAAQ,CAAA;gBAClC,MAAM,SAAS,GAAG,UAAU,CAAC,KAAK,CAAC,IAAI,KAAK,CAAC,YAAY,KAAK,CAAC,CAAA;gBAC/D,MAAM,IAAI,GAAG,SAAS,CAAC,CAAC,CAAC,QAAQ,GAAG,IAAI,CAAC,CAAC,CAAC,QAAQ,CAAA;gBACnD,MAAM,IAAI,GAAG,IAAI,GAAG,UAAU,CAAA;gBAC9B,MAAM,MAAM,GAAG,IAAI,GAAG,WAAW,CAAA;gBACjC,MAAM,EAAE,MAAM,EAAE,GAAG,KAAK,CAAA;gBACxB,MAAM,GAAG,GAAG,CAAC,KAAoB,EAAQ,EAAE,CAAC,CAAC,EAAE,EAAE,EAAE,CAAC,EAAE,QAAQ,EAAE,CAAC,EAAE,KAAK,EAAE,CAAC,CAAA;gBAC3E,wEAAwE;gBACxE,4EAA4E;gBAC5E,OAAO,KAAK,CAAC,QAAQ,EAAE;oBACrB,GAAG,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,QAAQ,CAAC,OAAO,CAAC,GAAG,EAAE,CAAC,CAAC,EAAE,YAAY,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;oBAC1E,GAAG,KAAK,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC,EAAE,QAAQ,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC;oBAC3D,GAAG,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,MAAM,CAAC,EAAE,CAAC,EAAE,OAAO,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,YAAY,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;oBACrE,EAAE,EAAE,EAAE,CAAC,EAAE,QAAQ,EAAE,IAAI,EAAE,KAAK,EAAE,KAAK,CAAC,KAAK,CAAC,GAAG,CAAC,OAAO,EAAE,EAAE,KAAK,EAAE,EAAE,EAAE,CAAC,EAAE;oBACzE,EAAE,EAAE,EAAE,CAAC,EAAE,QAAQ,EAAE,IAAI,EAAE,KAAK,EAAE,KAAK,CAAC,KAAK,CAAC,GAAG,CAAC,OAAO,EAAE,EAAE,KAAK,EAAE,EAAE,EAAE,CAAC,EAAE;oBACzE,GAAG,KAAK,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC,EAAE,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,MAAM,EAAE,KAAK,EAAE,IAAI,CAAC,GAAG,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC;oBACxF,GAAG,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,EAAE,EAAE,EAAE,IAAI,GAAG,MAAM,EAAE,QAAQ,EAAE,IAAI,GAAG,YAAY,EAAE,KAAK,EAAE,MAAM,CAAC,EAAE,CAAC,EAAE,OAAO,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;oBACjH,GAAG,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,EAAE,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,QAAQ,GAAG,IAAI,EAAE,KAAK,EAAE,QAAQ,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,EAAE,YAAY,EAAE,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;iBACvH,CAAC,CAAA;YACJ,CAAC;SACF;QACD;;;;;;WAMG;QACH,eAAe,EAAE;YACf,IAAI,EAAE,EAAE,MAAM,EAAE,UAAU,EAAE;YAC5B,MAAM,EAAE,OAAO,EAAE;YACjB,GAAG,EAAE,CAAC,QAAQ,EAAE,KAAK,EAAE,EAAE;gBACvB,MAAM,MAAM,GAAG,SAAS,CAAC,QAAQ,CAAC,IAAI,CAAC,MAAM,CAAC,CAAA;gBAC9C,MAAM,IAAI,GAAG,KAAK,CAAC,YAAY,CAAA;gBAC/B,MAAM,QAAQ,GAAG,KAAK,CAAC,MAAM,CAAA;gBAC7B,6EAA6E;gBAC7E,IAAI,MAAM,CAAC,CAAC,KAAK,SAAS,IAAI,MAAM,CAAC,CAAC,KAAK,SAAS;oBAAE,OAAO,QAAQ,CAAC,QAAQ,EAAE,KAAK,CAAC,CAAA;gBACtF,4EAA4E;gBAC5E,IAAI,IAAI,IAAI,CAAC,IAAI,CAAC,UAAU,CAAC,KAAK,CAAC;oBAAE,OAAO,QAAQ,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,EAAE,MAAM,EAAE,YAAY,EAAE,IAAI,GAAG,CAAC,CAAC,GAAG,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC,CAAA;gBACtH,OAAO,QAAQ,CAAC,OAAO,CACrB,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,GAAG,GAAG;oBACb,CAAC,CAAC,EAAE,MAAM,EAAE,QAAQ,EAAE,YAAY,EAAE,IAAI,GAAG,CAAC,CAAC,GAAG,QAAQ,CAAC,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE;oBACvE,CAAC,CAAC,EAAE,MAAM,EAAE,YAAY,EAAE,QAAQ,CAAC,IAAI,CAAC,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,EAAE,CAAC,EACvD,EAAE,KAAK,EAAE,KAAK,EAAE,CACjB,CAAA;YACH,CAAC;SACF;QACD,6FAA6F;QAC7F,WAAW,EAAE;YACX,IAAI,EAAE,EAAE;YACR,MAAM,EAAE,OAAO,EAAE;YACjB,GAAG,EAAE,CAAC,QAAQ,EAAE,KAAK,EAAE,EAAE,CAAC,QAAQ,CAAC,QAAQ,EAAE,KAAK,CAAC;SACpD;QACD;;;;;WAKG;QACH,MAAM,EAAE;YACN,IAAI,EAAE,EAAE,MAAM,EAAE,UAAU,EAAE;YAC5B,MAAM,EAAE,OAAO,EAAE;YACjB,GAAG,EAAE,CAAC,QAAQ,EAAE,KAAK,EAAE,EAAE;gBACvB,MAAM,MAAM,GAAG,SAAS,CAAC,QAAQ,CAAC,IAAI,CAAC,MAAM,CAAC,CAAA;gBAC9C,IAAI,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;oBAAE,OAAO,QAAQ,CAAC,IAAI,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAA;gBACnE,MAAM,IAAI,GAAG,gBAAgB,CAAC,KAAK,CAAC,CAAA;gBACpC,MAAM,IAAI,GAAG,KAAK,CAAC,IAAI,IAAI,IAAI,CAAA;gBAC/B,MAAM,EAAE,GAAG;oBACT,GAAG,CAAC,MAAM,CAAC,CAAC,IAAI,EAAE,CAAC,EAAE,EAAE,GAAG,IAAI,CAAC,CAAC,EAAE,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC,EAAE,IAAI,CAAC,CAAC,CAAC,KAAK,CAAC,EAAE,EAAE,CAAC;oBACzE,GAAG,CAAC,MAAM,CAAC,CAAC,IAAI,EAAE,CAAC,EAAE,EAAE,GAAG,IAAI,CAAC,CAAC,EAAE,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC,EAAE,IAAI,CAAC,CAAC,CAAC,KAAK,CAAC,EAAE,EAAE,CAAC;iBAC1E,CAAA;gBACD,OAAO,QAAQ,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,EAAE,IAAI,EAAE,GAAG,MAAM,CAAC,IAAI,EAAE,EAAE,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC,CAAA;YACpE,CAAC;SACF;QACD,+GAA+G;QAC/G,SAAS,EAAE;YACT,IAAI,EAAE,EAAE;YACR,MAAM,EAAE,OAAO,EAAE;YACjB,GAAG,EAAE,CAAC,QAAQ,EAAE,KAAK,EAAE,EAAE;gBACvB,MAAM,IAAI,GAAG,KAAK,CAAC,IAAI,CAAA;gBACvB,IAAI,CAAC,IAAI;oBAAE,OAAO,QAAQ,CAAC,IAAI,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAA;gBAClD,MAAM,IAAI,GAAG,gBAAgB,CAAC,KAAK,CAAC,CAAA;gBACpC,OAAO,QAAQ,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,EAAE,IAAI,EAAE,IAAI,EAAE,GAAG,MAAM,CAAC,IAAI,EAAE,IAAI,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC,CAAA;YAC5E,CAAC;SACF;QACD;;;WAGG;QACH,UAAU,EAAE;YACV,IAAI,EAAE,EAAE,WAAW,EAAE,UAAU,EAAE;YACjC,MAAM,EAAE,OAAO,EAAE;YACjB,GAAG,EAAE,CAAC,QAAQ,EAAE,MAAM,EAAE,QAAQ,EAAE,EAAE,CAAC,QAAQ,CAAC,QAAQ,EAAE,QAAQ,EAAE,QAAQ,CAAC,IAAI,CAAC,WAAW,EAAE,IAAI,CAAC;SACnG;QACD,2FAA2F;QAC3F,UAAU,EAAE;YACV,IAAI,EAAE,EAAE,WAAW,EAAE,UAAU,EAAE;YACjC,MAAM,EAAE,OAAO,EAAE;YACjB,GAAG,EAAE,CAAC,QAAQ,EAAE,MAAM,EAAE,QAAQ,EAAE,EAAE,CAAC,QAAQ,CAAC,QAAQ,EAAE,QAAQ,EAAE,QAAQ,CAAC,IAAI,CAAC,WAAW,EAAE,KAAK,CAAC;SACpG;QACD;;;;WAIG;QACH,eAAe,EAAE;YACf,IAAI,EAAE,EAAE,WAAW,EAAE,UAAU,EAAE;YACjC,MAAM,EAAE,OAAO,EAAE;YACjB,GAAG,EAAE,CAAC,QAAQ,EAAE,MAAM,EAAE,QAAQ,EAAE,EAAE;gBAClC,MAAM,KAAK,GAAG,OAAO,CAAC,QAAQ,CAAC,CAAA;gBAC/B,IAAI,CAAC,KAAK;oBAAE,OAAO,QAAQ,CAAC,IAAI,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAA;gBACnD,MAAM,KAAK,GAAG,QAAQ,CAAC,IAAI,CAAC,WAAW,CAAA;gBACvC,OAAO,QAAQ,CAAC,QAAQ,CAAC;oBACvB,GAAG,KAAK,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,CAAC,EAAE,EAAE,CAAC,IAAI,CAAC,EAAE,CAAC,EAAE,OAAO,EAAE,CAAC,KAAK,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,aAAa,EAAE,CAAC,CAAC;oBACtF,GAAG,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,MAAM,CAAC,GAAG,CAAC,iBAAiB,EAAE,EAAE,KAAK,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;iBAC1E,CAAC,CAAA;YACJ,CAAC;SACF;KACF;CACF,CAAC,CAAA","sourcesContent":["import {\r\n Rect,\r\n Types,\r\n component2d,\r\n easeOut,\r\n type ChildView,\r\n type DataRecord,\r\n type EntryOptions,\r\n type NodeOf,\r\n // Named so this component's emitted type reaches `Node2D` through the sdk, not core.\r\n type Node2D,\r\n type Node2DProps,\r\n type Size2D,\r\n type Timeline,\r\n type Vector2,\r\n} from \"@motionscript/sdk\"\r\nimport { formatNumber } from \"@motionscript/sdk/component\"\r\n\r\nimport { cartesianFrame, cartesianViews, laidOutSize } from \"../kit/cartesian\"\r\nimport { ChartBorder } from \"../kit/chart-border\"\r\nimport { ChartCanvas } from \"../kit/chart-canvas\"\r\nimport { ChartLegend } from \"../kit/chart-legend\"\r\nimport { asParts, fresh } from \"../kit/entries\"\r\nimport { beats, type Beat } from \"../kit/motion\"\r\nimport { VerticalAxis } from \"../kit/vertical-axis\"\r\nimport {\r\n SPOTLIGHT_DIM,\r\n formatMarker,\r\n lerpAxisDomain,\r\n lerpAxisEntry,\r\n markerStep,\r\n markerValues,\r\n resolveAxisDomain,\r\n resolveSeriesFill,\r\n resolveSeriesStroke,\r\n settleAxisDomain,\r\n type AxisDomainConfig,\r\n type Range,\r\n} from \"../kit/shared\"\r\nimport { ChartLine } from \"./chart-line\"\r\nimport { ChartRegion } from \"./chart-region\"\r\nimport { HorizontalAxis } from \"./horizontal-axis\"\r\nimport {\r\n DEFAULT_CHART_THEME,\r\n lerpChartTheme,\r\n resolveChartTheme,\r\n resolveRegionBox,\r\n resolveYScale,\r\n seriesPoints,\r\n type ChartConfig,\r\n type ChartTheme,\r\n type LineSeries,\r\n type PlotRegion,\r\n type RegionBox,\r\n} from \"./shared\"\r\nimport { resolveXScale, type XScale } from \"./x-scale\"\r\n\r\nexport interface LineChartProps extends Node2DProps {\r\n /** One row per sample — a plain record of field name to value. */\r\n data: DataRecord[]\r\n /**\r\n * Key into each row for its x value, shared by every series. Named `xField`\r\n * rather than `x` because every node already has an `x` — its position.\r\n */\r\n xField: string\r\n /** One polyline per entry: which field it plots, its legend `label`, its `fill`. */\r\n series: LineSeries[]\r\n /** X-axis data domain: caption, scale range, and tick placement. */\r\n xAxis?: AxisDomainConfig\r\n /** Y-axis data domain: caption, scale range, and tick placement. */\r\n yAxis?: AxisDomainConfig\r\n /**\r\n * A slice of the plot to spotlight, in **data units**. Dashed rules mark the\r\n * bounded edges and every series fades outside the box — see\r\n * `spotlightRegion`, which animates the same thing. `null` (the default) is no\r\n * region.\r\n */\r\n region?: PlotRegion | null\r\n /**\r\n * The chart's visual theme — series palette, axis text/grid/gutters, plot\r\n * panel paint, and legend styling. Every branch is optional and deep-merged\r\n * onto {@link DEFAULT_CHART_THEME}, so pass only what you want to override.\r\n */\r\n theme?: ChartTheme\r\n /** Whether the legend row below the plot is drawn at all. */\r\n showLegend?: boolean\r\n}\r\n\r\n/** Both axes' domains with their ranges and ticks resolved. */\r\nexport interface LineChartDomains {\r\n readonly x: AxisDomainConfig & { readonly range: Range; readonly ticks: number[] }\r\n readonly y: AxisDomainConfig & { readonly range: Range; readonly ticks: number[] }\r\n}\r\n\r\n/** What a line chart plots, as its entries hold it. */\r\nexport interface LineChartValues {\r\n readonly data: DataRecord[]\r\n readonly xField: string\r\n readonly series: LineSeries[]\r\n readonly xAxis: AxisDomainConfig\r\n readonly yAxis: AxisDomainConfig\r\n}\r\n\r\n/**\r\n * The argument every per-series command takes: an index into `series`. Its own\r\n * kind rather than `number` so a host can offer the series by name.\r\n */\r\nconst SERIES_ARG = Types.custom<number, number, EntryOptions & { readonly min: number; readonly step: number }>(0, { kind: \"series\", min: 0, step: 1 })\r\n\r\n/** One argument, two controls: the commands take a `PlotRegion`, so the x and y spans a host draws are declared inside it. */\r\nconst REGION_ARG = Types.custom<PlotRegion | undefined>(undefined, {\r\n kind: \"region\",\r\n properties: {\r\n x: { kind: \"range\", default: true, defaultMin: 0, defaultMax: 100 },\r\n y: { kind: \"range\", default: false, defaultMin: 0, defaultMax: 100 },\r\n },\r\n})\r\n\r\n/** How far the legend starts below its slot when it enters, in px. */\r\nconst LEGEND_SLIDE = 20\r\n\r\n/** Fallback marker count when neither axis's ticks are given. */\r\nconst DEFAULT_MARKERS = 5\r\n\r\n/**\r\n * How `enter` divides its duration between its three beats: the axes arriving,\r\n * the lines tracing, and the legend coming up. Shares of the whole, so they must\r\n * sum to 1 — the entrance takes exactly the time it was given.\r\n */\r\nconst AXES_SHARE = 0.35\r\nconst LINES_SHARE = 0.5\r\nconst LEGEND_SHARE = 0.15\r\n\r\n/** What the chart's own commands read: its entries, and the private `home` a zoom remembers. */\r\ninterface LineState extends LineChartValues {\r\n readonly theme: ChartConfig\r\n readonly region: PlotRegion | null\r\n readonly regionReveal: number\r\n readonly home: LineChartDomains | null\r\n}\r\n\r\n/**\r\n * What the x column *is* — a number, an instant, or a place in the file — and\r\n * with it how each row is positioned, ticked and captioned. See `x-scale.ts`.\r\n */\r\nfunction columnOf(s: LineChartValues, format = s.xAxis.format): XScale {\r\n return resolveXScale(s.data, s.xField, format)\r\n}\r\n\r\n/**\r\n * The horizontal axis with its range and ticks resolved: the explicit ones, else\r\n * the column's extent and five ticks across it, asked of the column because only\r\n * a numeric one has round numbers between its samples.\r\n */\r\nfunction drawnX(s: LineChartValues, domain: AxisDomainConfig): AxisDomainConfig {\r\n const column = columnOf(s, domain.format)\r\n const range = domain.range ?? column.extent\r\n return { ...domain, range, ticks: domain.ticks ?? column.ticks(range, DEFAULT_MARKERS - 1) }\r\n}\r\n\r\n/**\r\n * The vertical axis with its range and ticks resolved. Auto-ranging steps into\r\n * one fewer segment than the intended marker count, so the tidy bounds frame the\r\n * ticks the axis draws.\r\n */\r\nfunction drawnY(s: LineChartValues, domain: AxisDomainConfig): AxisDomainConfig {\r\n const divisions = (domain.ticks?.length ?? DEFAULT_MARKERS) - 1\r\n const range = resolveYScale(s.data, s.series, domain.range, divisions)\r\n return { ...domain, range, ticks: domain.ticks ?? markerValues(range, DEFAULT_MARKERS - 1) }\r\n}\r\n\r\n/** The last domains worked out from each data array, and what else they were read from. */\r\nconst domainsDrawn = new WeakMap<\r\n DataRecord[],\r\n Pick<LineChartValues, \"xField\" | \"xAxis\" | \"yAxis\" | \"series\"> & { readonly domains: LineChartDomains }\r\n>()\r\n\r\n/** Both axes as a line chart draws them now, an auto range or tick row read back as itself. */\r\nexport function lineChartDomains(s: LineChartValues): LineChartDomains {\r\n const { data, xField, xAxis, yAxis, series } = s\r\n const kept = domainsDrawn.get(data)\r\n if (kept && kept.xField === xField && kept.xAxis === xAxis && kept.yAxis === yAxis && kept.series === series) {\r\n return kept.domains\r\n }\r\n const domains = {\r\n x: settleAxisDomain(xAxis, (d) => drawnX(s, d)) as LineChartDomains[\"x\"],\r\n y: settleAxisDomain(yAxis, (d) => drawnY(s, d)) as LineChartDomains[\"y\"],\r\n }\r\n domainsDrawn.set(data, { xField, xAxis, yAxis, series, domains })\r\n return domains\r\n}\r\n\r\n/**\r\n * Map one series' data points into the plot's **centred** pixel space (origin at\r\n * the plot centre, y-up): x runs `[-w/2, +w/2]`, y runs `[-h/2, +h/2]`.\r\n */\r\nfunction seriesPixels(s: LineChartValues, domains: LineChartDomains, index: number, plot: Size2D): Vector2[] {\r\n const series = s.series[index]\r\n if (!series) return []\r\n const points = seriesPoints(s.data, columnOf(s), series)\r\n if (points.length === 0) return []\r\n const { width: w, height: h } = plot\r\n const [xMin, xMax] = domains.x.range\r\n const [yMin, yMax] = domains.y.range\r\n const xToPx = (x: number) => (xMax <= xMin ? 0 : ((x - xMin) / (xMax - xMin) - 0.5) * w)\r\n const yToPx = (y: number) => (yMax <= yMin ? 0 : ((y - yMin) / (yMax - yMin) - 0.5) * h)\r\n // `seriesPoints` already sorted them along x.\r\n return points.map(([x, y]) => ({ x: xToPx(x), y: yToPx(y) }))\r\n}\r\n\r\n/** `region` mapped into the plot's centred pixel space, against the live scales, so it travels with a zoom. */\r\nfunction regionBox(s: LineChartValues & { readonly region: PlotRegion | null }, domains: LineChartDomains, plot: Size2D): RegionBox {\r\n const { width: w, height: h } = plot\r\n return resolveRegionBox(s.region, { left: -w / 2, right: w / 2, bottom: -h / 2, top: h / 2 }, domains.x.range, domains.y.range)\r\n}\r\n\r\n/**\r\n * Whether a call-out is authored at all. Not whether it resolves to pixels: a\r\n * command is built before the first layout, and a region on a chart not yet\r\n * measured is a real one. A region bounding neither axis is none, as `null` is.\r\n */\r\nfunction hasCallout(s: { readonly region: PlotRegion | null }): boolean {\r\n const region = s.region\r\n return region != null && (region.x !== undefined || region.y !== undefined)\r\n}\r\n\r\n/** The `region` a document handed a command, or `{}`: a command is added before its arguments are filled in. */\r\nfunction regionArg(region: PlotRegion | null | undefined): PlotRegion {\r\n return region != null && typeof region === \"object\" ? region : {}\r\n}\r\n\r\n/** A range read as a span, whichever way round the author wrote it. */\r\nfunction span([a, b]: Range): Range {\r\n return a <= b ? [a, b] : [b, a]\r\n}\r\n\r\n/**\r\n * Rescale an axis to `range`, keeping the tick *count* it already has, so each\r\n * marker slides from its old value to its new one instead of the row popping.\r\n */\r\nfunction rescale(range: Range, ticks: readonly number[]): AxisDomainConfig {\r\n const to = span(range)\r\n return { range: to, ticks: markerValues(to, Math.max(2, ticks.length) - 1) }\r\n}\r\n\r\n/** The axis writes of a move from `from` toward `to` at `t`. */\r\nfunction axesAt(from: LineChartDomains, to: Partial<Record<\"x\" | \"y\", AxisDomainConfig>>, t: number) {\r\n return {\r\n ...(to.x && { xAxis: lerpAxisDomain(from.x, to.x, t) }),\r\n ...(to.y && { yAxis: lerpAxisDomain(from.y, to.y, t) }),\r\n }\r\n}\r\n\r\ntype AnyTimeline = Timeline<any, any>\r\n\r\n/** The parts a line chart's commands drive, found through its children. */\r\nfunction partsOf(children: readonly ChildView[]) {\r\n const frame = cartesianViews(children)\r\n if (!frame) return null\r\n const hAxis = frame.below.find(HorizontalAxis.is)\r\n if (!VerticalAxis.is(frame.axis) || !hAxis) return null\r\n return {\r\n vAxis: frame.axis,\r\n hAxis,\r\n lines: frame.plot.filter(ChartLine.is),\r\n legend: frame.below.find(ChartLegend.is) ?? null,\r\n }\r\n}\r\n\r\n/** Drop the call-out: the rules retract, the wash fades, and every series comes back to full. */\r\nfunction clearing(timeline: AnyTimeline, state: LineState) {\r\n const from = state.regionReveal\r\n const region = state.region\r\n // Nothing to retract, but the call still takes its slot on the timeline.\r\n if (from === 0) return timeline.animate(() => ({ region: null, regionReveal: 0 }), { eased: false })\r\n // `region` is held until the retraction lands, or there would be nothing left to retract.\r\n return timeline.animate((t) => (t >= 1 ? { region: null, regionReveal: 0 } : { region, regionReveal: from * (1 - t) }))\r\n}\r\n\r\n/** Trace series `index`'s line in (`show`) or back out, in lockstep with its legend entry. */\r\nfunction toggling(timeline: AnyTimeline, children: readonly ChildView[], index: number, show: boolean) {\r\n const parts = partsOf(children)\r\n const line = parts?.lines[index]\r\n if (!parts || !line) return timeline.wait(timeline.duration)\r\n return timeline.together([\r\n line.run(\"enter\", show ? { from: 0, to: 1 } : { from: 1, to: 0 }),\r\n ...(parts.legend ? [parts.legend.run(show ? \"showSeries\" : \"hideSeries\", { index })] : []),\r\n ])\r\n}\r\n\r\n/**\r\n * A multi-series line chart, composed from five independent parts rather than\r\n * one monolithic draw:\r\n *\r\n * - {@link ChartCanvas} — the plot panel with a two-way grid, under everything.\r\n * - {@link VerticalAxis} / {@link HorizontalAxis} — columns/rows of real text\r\n * markers that stagger in, each carrying its own axis caption.\r\n * - {@link ChartRegion} — the optional call-out marking a spotlit slice of the\r\n * plot: dashed rules on its bounded edges, and every series faded outside it.\r\n * - {@link ChartLine} (one per series) — the traced polylines over the canvas.\r\n * - {@link ChartLegend} — a row of entries below the chart, one per series.\r\n *\r\n * Every part reads the chart's entries through bindings, and the lines, the\r\n * region and the grid all map against the plot panel's own laid-out box, so\r\n * points land exactly on their markers and the chart re-flows if its box\r\n * changes.\r\n *\r\n * **Resting state is the finished chart**: an editor paints a node's Initial\r\n * state on a paused canvas. `enter` arms every part on its first frame.\r\n *\r\n * Past the entrance, `showSeries`/`hideSeries`/`spotlightSeries` pick out a\r\n * *series*, `spotlightRegion` marks a *slice of the plot* without changing the\r\n * scale, and `zoomTo` rescales the axes so a slice fills the plot. A spotlit\r\n * region resolves against the live scales, so it travels with a zoom. A `to` of\r\n * an axis `range` or `ticks` tweens from the domain as drawn (see\r\n * {@link lerpAxisEntry}), so an auto axis rescales continuously.\r\n */\r\nexport const LineChart = component2d({\r\n key: \"lineChart\",\r\n state: {\r\n data: fresh<DataRecord[]>(() => [], { kind: \"dataset\" }),\r\n xField: \"\",\r\n series: fresh<LineSeries[]>(() => [], { kind: \"series\" }),\r\n xAxis: Types.custom<AxisDomainConfig>({}, { resolve: resolveAxisDomain, lerp: lerpAxisEntry }),\r\n yAxis: Types.custom<AxisDomainConfig>({}, { resolve: resolveAxisDomain, lerp: lerpAxisEntry }),\r\n theme: Types.custom<ChartTheme, ChartConfig>(DEFAULT_CHART_THEME, { resolve: resolveChartTheme, lerp: lerpChartTheme }),\r\n /**\r\n * The spotlit slice of the plot in data units, or `null` for none. The box\r\n * snaps; the animation is {@link regionReveal} drawing the rules on.\r\n */\r\n region: Types.custom<PlotRegion | null>(null),\r\n /**\r\n * How far the `region` call-out is drawn in, `[0, 1]`: the rules grow out and\r\n * the wash fades up as it climbs, while every line's out-of-region stretch\r\n * fades to the theme's `region.dimOpacity`.\r\n */\r\n regionReveal: 0,\r\n /** Read as the chart is built: the legend is a part the chart builds or doesn't. */\r\n showLegend: Types.boolean(true, { animatable: false }),\r\n /**\r\n * The domain `zoomTo` first left, so `resetZoom` restores the chart as it\r\n * stood, auto-derived ticks included. Cleared by `resetZoom`, so the next zoom\r\n * remembers wherever the chart rests then.\r\n */\r\n home: Types.custom<LineChartDomains | null>(null, { private: true }),\r\n },\r\n // Its parts fill it; a node made of them would hug them.\r\n defaults: { width: \"fill\", height: \"fill\" },\r\n allowedChildren: [],\r\n children: (state) => {\r\n const theme = () => state.theme\r\n const domains = () => lineChartDomains(state)\r\n let plot: Node2D | undefined\r\n const plotSize = () => laidOutSize(plot)\r\n const enabled = state.series.map((s) => s.enabled ?? true)\r\n\r\n // Bound, not snapshotted, so a rescale re-labels and re-places the row as it\r\n // tweens. The marker *count* is read once, which is why `zoomTo` keeps it.\r\n const vAxis = new VerticalAxis({\r\n range: () => domains().y.range,\r\n markers: () => domains().y.ticks,\r\n // The y axis is always numbers, so its format is simply the pattern.\r\n captions: () => {\r\n const markers = domains().y.ticks\r\n const format = state.yAxis.format\r\n return markers.map((value) => (format === undefined ? formatMarker(value, markerStep(markers)) : formatNumber(value, format)))\r\n },\r\n axis: () => theme().yAxis,\r\n label: state.yAxis.label ?? \"\",\r\n width: \"hug\",\r\n height: \"fill\",\r\n })\r\n\r\n const hAxis = new HorizontalAxis({\r\n range: () => domains().x.range,\r\n markers: () => domains().x.ticks,\r\n // A tick on a month or category column is captioned with the cell it came\r\n // out of — `Jan`, not the instant it parsed to.\r\n captions: () => {\r\n const column = columnOf(state)\r\n return domains().x.ticks.map((value) => column.label(value))\r\n },\r\n axis: () => theme().xAxis,\r\n label: state.xAxis.label ?? \"\",\r\n width: \"fill\",\r\n height: \"hug\",\r\n })\r\n\r\n const lines = state.series.map(\r\n (s, i) =>\r\n new ChartLine({\r\n points: () => seriesPixels(state, domains(), i, plotSize()),\r\n stroke: () => resolveSeriesStroke(theme().seriesStyles, s, i),\r\n enabled: enabled[i],\r\n // Each line clips itself against the box the rules are drawn from, so\r\n // the dim/bright boundary can't drift from the dashes.\r\n spotlight: () => regionBox(state, domains(), plotSize()),\r\n // Ramped by the reveal that draws the rules: one signal, both halves.\r\n dimOpacity: () => 1 - (1 - theme().region.dimOpacity) * state.regionReveal,\r\n }) as unknown as Node2D\r\n )\r\n\r\n const below: Node2D[] = [hAxis as unknown as Node2D]\r\n if (state.showLegend !== false) {\r\n below.push(\r\n new ChartLegend({\r\n series: state.series,\r\n // The legend paints a swatch, not a line, so it is handed the colour each\r\n // stroke resolves to rather than the stroke itself.\r\n swatches: () => state.series.map((s, i) => resolveSeriesFill(theme().seriesStyles, s, i)),\r\n legend: () => theme().legend,\r\n // The row's spacing is the theme's as the chart was built, like the\r\n // entries' type and chips: a theme tween re-paints the swatches only.\r\n gap: state.theme.legend.itemGap,\r\n padding: state.theme.legend.padding,\r\n }) as unknown as Node2D\r\n )\r\n }\r\n\r\n plot = new Rect({\r\n clip: true,\r\n children: [\r\n new ChartCanvas({\r\n fill: () => theme().plotArea.fill,\r\n shadow: () => theme().plotArea.shadow,\r\n xGridStroke: () => theme().xAxis.lineStyle,\r\n yGridStroke: () => theme().yAxis.lineStyle,\r\n // A grid line under every axis marker; the canvas skips the edges.\r\n xMarkers: () => domains().x.ticks,\r\n yMarkers: () => domains().y.ticks,\r\n xExtent: () => domains().x.range,\r\n yExtent: () => domains().y.range,\r\n }),\r\n // Over the grid, under the lines, so a spotlit stretch of a series isn't\r\n // tinted by the highlight meant to pick it out.\r\n new ChartRegion({\r\n box: () => regionBox(state, domains(), plotSize()),\r\n stroke: () => theme().region.stroke,\r\n fill: () => theme().region.fill,\r\n reveal: () => state.regionReveal,\r\n }),\r\n ...lines,\r\n new ChartBorder({ stroke: () => theme().plotArea.stroke }),\r\n ],\r\n }) as unknown as Node2D\r\n\r\n const gutter = new VerticalAxis({\r\n opacity: 0,\r\n range: () => domains().y.range,\r\n markers: () => domains().y.ticks,\r\n axis: () => theme().yAxis,\r\n label: state.yAxis.label ?? \"\",\r\n width: \"hug\",\r\n height: 0,\r\n }) as unknown as Node2D\r\n\r\n return asParts([cartesianFrame({ axis: vAxis as unknown as Node2D, plot, gutter, below })])\r\n },\r\n commands: {\r\n /**\r\n * Animate the whole chart in: the two axes stagger their markers in, the\r\n * series lines trace left to right, and the legend fades up last. Its first\r\n * frame arms every part: markers shifted and transparent, lines untraced,\r\n * the legend dropped and transparent.\r\n *\r\n * `duration` is the **whole** entrance; the beats are shares of it. A chart\r\n * authored with a `region` lands its call-out last, in the final quarter.\r\n */\r\n enter: {\r\n args: {},\r\n // Held from the chart's arrival, so it never shows finished ahead of its draw.\r\n entrance: true,\r\n easing: easeOut(),\r\n run: (timeline, state, children) => {\r\n const parts = partsOf(children)\r\n if (!parts) return timeline.wait(timeline.duration)\r\n const duration = timeline.duration\r\n const revealing = hasCallout(state) && state.regionReveal === 0\r\n const body = revealing ? duration * 0.75 : duration\r\n const axes = body * AXES_SHARE\r\n const traced = body * LINES_SHARE\r\n const { legend } = parts\r\n const at0 = (piece: Beat[\"piece\"]): Beat => ({ at: 0, duration: 0, piece })\r\n // The first frame arms what every later beat moves: a beat ahead of the\r\n // playhead writes nothing. A beat with nothing to do still takes its share.\r\n return beats(timeline, [\r\n ...(revealing ? [at0(timeline.animate(() => ({ regionReveal: 0 })))] : []),\r\n ...parts.lines.map((line) => at0(line.to({ progress: 0 }))),\r\n ...(legend ? [at0(legend.to({ opacity: 0, y: -LEGEND_SLIDE }))] : []),\r\n { at: 0, duration: axes, piece: parts.vAxis.run(\"enter\", { slide: 24 }) },\r\n { at: 0, duration: axes, piece: parts.hAxis.run(\"enter\", { slide: 24 }) },\r\n ...parts.lines.map((line) => ({ at: axes, duration: traced, piece: line.run(\"enter\") })),\r\n ...(legend ? [{ at: axes + traced, duration: body * LEGEND_SHARE, piece: legend.to({ opacity: 1, y: 0 }) }] : []),\r\n ...(revealing ? [{ at: body, duration: duration * 0.25, piece: timeline.animate((t) => ({ regionReveal: t })) }] : []),\r\n ])\r\n },\r\n },\r\n /**\r\n * Spotlight a rectangular slice of the plot given in **data units**: dashed\r\n * rules draw onto each bounded edge while every series fades outside the box.\r\n * Either axis alone is a band; both are a box. Called while another region is\r\n * up, the old call-out retracts over the first half and the new one draws in\r\n * over the second, each half eased on its own.\r\n */\r\n spotlightRegion: {\r\n args: { region: REGION_ARG },\r\n easing: easeOut(),\r\n run: (timeline, state) => {\r\n const region = regionArg(timeline.args.region)\r\n const from = state.regionReveal\r\n const previous = state.region\r\n // A region bounding neither axis is no call-out: spotlighting it is a clear.\r\n if (region.x === undefined && region.y === undefined) return clearing(timeline, state)\r\n // Nothing up yet: the region is set from the first frame and just draws on.\r\n if (from <= 0 || !hasCallout(state)) return timeline.animate((t) => ({ region, regionReveal: from + (1 - from) * t }))\r\n return timeline.animate(\r\n (t) => (t < 0.5\r\n ? { region: previous, regionReveal: from * (1 - timeline.ease(t * 2)) }\r\n : { region, regionReveal: timeline.ease(t * 2 - 1) }),\r\n { eased: false }\r\n )\r\n },\r\n },\r\n /** Drop the region call-out. A no-op when nothing is spotlit, which still takes its slot. */\r\n clearRegion: {\r\n args: {},\r\n easing: easeOut(),\r\n run: (timeline, state) => clearing(timeline, state),\r\n },\r\n /**\r\n * Zoom the plot to a slice of itself, given in **data units**: the named axes\r\n * rescale so that slice fills the plot, the grid, both marker rows and every\r\n * series following. An omitted axis is left as it is. The first zoom\r\n * remembers the domain it left, for `resetZoom`.\r\n */\r\n zoomTo: {\r\n args: { region: REGION_ARG },\r\n easing: easeOut(),\r\n run: (timeline, state) => {\r\n const region = regionArg(timeline.args.region)\r\n if (!region.x && !region.y) return timeline.wait(timeline.duration)\r\n const from = lineChartDomains(state)\r\n const home = state.home ?? from\r\n const to = {\r\n ...(region.x && { x: { ...from.x, ...rescale(region.x, from.x.ticks) } }),\r\n ...(region.y && { y: { ...from.y, ...rescale(region.y, from.y.ticks) } }),\r\n }\r\n return timeline.animate((t) => ({ home, ...axesAt(from, to, t) }))\r\n },\r\n },\r\n /** Pull back out to the domain the first zoom left — the mirror of `zoomTo`, and a hold if it never zoomed. */\r\n resetZoom: {\r\n args: {},\r\n easing: easeOut(),\r\n run: (timeline, state) => {\r\n const home = state.home\r\n if (!home) return timeline.wait(timeline.duration)\r\n const from = lineChartDomains(state)\r\n return timeline.animate((t) => ({ home: null, ...axesAt(from, home, t) }))\r\n },\r\n },\r\n /**\r\n * Show series `index`: **trace** its line in left to right, in lockstep with\r\n * its legend entry growing in.\r\n */\r\n showSeries: {\r\n args: { seriesIndex: SERIES_ARG },\r\n easing: easeOut(),\r\n run: (timeline, _state, children) => toggling(timeline, children, timeline.args.seriesIndex, true),\r\n },\r\n /** Hide series `index`: **retrace** its line back out as its legend entry shrinks away. */\r\n hideSeries: {\r\n args: { seriesIndex: SERIES_ARG },\r\n easing: easeOut(),\r\n run: (timeline, _state, children) => toggling(timeline, children, timeline.args.seriesIndex, false),\r\n },\r\n /**\r\n * Fade every other series — each line **and its legend entry** — to focus on\r\n * `index`, which comes back to full. The legend dims in place, so the row\r\n * doesn't reflow.\r\n */\r\n spotlightSeries: {\r\n args: { seriesIndex: SERIES_ARG },\r\n easing: easeOut(),\r\n run: (timeline, _state, children) => {\r\n const parts = partsOf(children)\r\n if (!parts) return timeline.wait(timeline.duration)\r\n const index = timeline.args.seriesIndex\r\n return timeline.together([\r\n ...parts.lines.map((line, i) => line.to({ opacity: i === index ? 1 : SPOTLIGHT_DIM })),\r\n ...(parts.legend ? [parts.legend.run(\"spotlightSeries\", { index })] : []),\r\n ])\r\n },\r\n },\r\n },\r\n})\r\n\r\nexport type LineChart = NodeOf<typeof LineChart>\r\n"]}
|
|
1
|
+
{"version":3,"file":"line-chart.js","sourceRoot":"","sources":["../../src/line-chart/line-chart.ts"],"names":[],"mappings":"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","sourcesContent":["import {\n Rect,\n Types,\n component2d,\n easeOut,\n type ChildView,\n type DataRecord,\n type EntryOptions,\n type NodeOf,\n // Named so this component's emitted type reaches `Node2D` through the sdk, not core.\n type Node2D,\n type Node2DProps,\n type Size2D,\n type Timeline,\n type Vector2,\n} from \"@motionscript/sdk\"\nimport { formatNumber } from \"@motionscript/sdk/component\"\n\nimport { cartesianFrame, cartesianViews, laidOutSize } from \"../kit/cartesian\"\nimport { ChartBorder } from \"../kit/chart-border\"\nimport { ChartCanvas } from \"../kit/chart-canvas\"\nimport { ChartLegend } from \"../kit/chart-legend\"\nimport { asParts, fresh } from \"../kit/entries\"\nimport { beats, type Beat } from \"../kit/motion\"\nimport { VerticalAxis } from \"../kit/vertical-axis\"\nimport {\n SPOTLIGHT_DIM,\n formatMarker,\n lerpAxisDomain,\n lerpAxisEntry,\n markerStep,\n markerValues,\n resolveAxisDomain,\n resolveSeriesFill,\n resolveSeriesStroke,\n settleAxisDomain,\n type AxisDomainConfig,\n type Range,\n} from \"../kit/shared\"\nimport { ChartLine } from \"./chart-line\"\nimport { ChartRegion } from \"./chart-region\"\nimport { HorizontalAxis } from \"./horizontal-axis\"\nimport {\n DEFAULT_CHART_THEME,\n lerpChartTheme,\n resolveChartTheme,\n resolveRegionBox,\n resolveYScale,\n seriesPoints,\n type ChartConfig,\n type ChartTheme,\n type LineSeries,\n type PlotRegion,\n type RegionBox,\n} from \"./shared\"\nimport { resolveXScale, type XScale } from \"./x-scale\"\n\nexport interface LineChartProps extends Node2DProps {\n /** One row per sample — a plain record of field name to value. */\n data: DataRecord[]\n /**\n * Key into each row for its x value, shared by every series. Named `xField`\n * rather than `x` because every node already has an `x` — its position.\n */\n xField: string\n /** One polyline per entry: which field it plots, its legend `label`, its `fill`. */\n series: LineSeries[]\n /** X-axis data domain: caption, scale range, and tick placement. */\n xAxis?: AxisDomainConfig\n /** Y-axis data domain: caption, scale range, and tick placement. */\n yAxis?: AxisDomainConfig\n /**\n * A slice of the plot to spotlight, in **data units**. Dashed rules mark the\n * bounded edges and every series fades outside the box — see\n * `spotlightRegion`, which animates the same thing. `null` (the default) is no\n * region.\n */\n region?: PlotRegion | null\n /**\n * The chart's visual theme — series palette, axis text/grid/gutters, plot\n * panel paint, and legend styling. Every branch is optional and deep-merged\n * onto {@link DEFAULT_CHART_THEME}, so pass only what you want to override.\n */\n theme?: ChartTheme\n /** Whether the legend row below the plot is drawn at all. */\n showLegend?: boolean\n}\n\n/** Both axes' domains with their ranges and ticks resolved. */\nexport interface LineChartDomains {\n readonly x: AxisDomainConfig & { readonly range: Range; readonly ticks: number[] }\n readonly y: AxisDomainConfig & { readonly range: Range; readonly ticks: number[] }\n}\n\n/** What a line chart plots, as its entries hold it. */\nexport interface LineChartValues {\n readonly data: DataRecord[]\n readonly xField: string\n readonly series: LineSeries[]\n readonly xAxis: AxisDomainConfig\n readonly yAxis: AxisDomainConfig\n}\n\n/**\n * The argument every per-series command takes: an index into `series`. Its own\n * kind rather than `number` so a host can offer the series by name.\n */\nconst SERIES_ARG = Types.custom<number, number, EntryOptions & { readonly min: number; readonly step: number }>(0, { kind: \"series\", min: 0, step: 1 })\n\n/** One argument, two controls: the commands take a `PlotRegion`, so the x and y spans a host draws are declared inside it. */\nconst REGION_ARG = Types.custom<PlotRegion | undefined>(undefined, {\n kind: \"region\",\n properties: {\n x: { kind: \"range\", default: true, defaultMin: 0, defaultMax: 100 },\n y: { kind: \"range\", default: false, defaultMin: 0, defaultMax: 100 },\n },\n})\n\n/** How far the legend starts below its slot when it enters, in px. */\nconst LEGEND_SLIDE = 20\n\n/** Fallback marker count when neither axis's ticks are given. */\nconst DEFAULT_MARKERS = 5\n\n/**\n * How `enter` divides its duration between its three beats: the axes arriving,\n * the lines tracing, and the legend coming up. Shares of the whole, so they must\n * sum to 1 — the entrance takes exactly the time it was given.\n */\nconst AXES_SHARE = 0.35\nconst LINES_SHARE = 0.5\nconst LEGEND_SHARE = 0.15\n\n/** What the chart's own commands read: its entries, and the private `home` a zoom remembers. */\ninterface LineState extends LineChartValues {\n readonly theme: ChartConfig\n readonly region: PlotRegion | null\n readonly regionReveal: number\n readonly home: LineChartDomains | null\n}\n\n/**\n * What the x column *is* — a number, an instant, or a place in the file — and\n * with it how each row is positioned, ticked and captioned. See `x-scale.ts`.\n */\nfunction columnOf(s: LineChartValues, format = s.xAxis.format): XScale {\n return resolveXScale(s.data, s.xField, format)\n}\n\n/**\n * The horizontal axis with its range and ticks resolved: the explicit ones, else\n * the column's extent and five ticks across it, asked of the column because only\n * a numeric one has round numbers between its samples.\n */\nfunction drawnX(s: LineChartValues, domain: AxisDomainConfig): AxisDomainConfig {\n const column = columnOf(s, domain.format)\n const range = domain.range ?? column.extent\n return { ...domain, range, ticks: domain.ticks ?? column.ticks(range, DEFAULT_MARKERS - 1) }\n}\n\n/**\n * The vertical axis with its range and ticks resolved. Auto-ranging steps into\n * one fewer segment than the intended marker count, so the tidy bounds frame the\n * ticks the axis draws.\n */\nfunction drawnY(s: LineChartValues, domain: AxisDomainConfig): AxisDomainConfig {\n const divisions = (domain.ticks?.length ?? DEFAULT_MARKERS) - 1\n const range = resolveYScale(s.data, s.series, domain.range, divisions)\n return { ...domain, range, ticks: domain.ticks ?? markerValues(range, DEFAULT_MARKERS - 1) }\n}\n\n/** The last domains worked out from each data array, and what else they were read from. */\nconst domainsDrawn = new WeakMap<\n DataRecord[],\n Pick<LineChartValues, \"xField\" | \"xAxis\" | \"yAxis\" | \"series\"> & { readonly domains: LineChartDomains }\n>()\n\n/** Both axes as a line chart draws them now, an auto range or tick row read back as itself. */\nexport function lineChartDomains(s: LineChartValues): LineChartDomains {\n const { data, xField, xAxis, yAxis, series } = s\n const kept = domainsDrawn.get(data)\n if (kept && kept.xField === xField && kept.xAxis === xAxis && kept.yAxis === yAxis && kept.series === series) {\n return kept.domains\n }\n const domains = {\n x: settleAxisDomain(xAxis, (d) => drawnX(s, d)) as LineChartDomains[\"x\"],\n y: settleAxisDomain(yAxis, (d) => drawnY(s, d)) as LineChartDomains[\"y\"],\n }\n domainsDrawn.set(data, { xField, xAxis, yAxis, series, domains })\n return domains\n}\n\n/**\n * Map one series' data points into the plot's **centred** pixel space (origin at\n * the plot centre, y-up): x runs `[-w/2, +w/2]`, y runs `[-h/2, +h/2]`.\n */\nfunction seriesPixels(s: LineChartValues, domains: LineChartDomains, index: number, plot: Size2D): Vector2[] {\n const series = s.series[index]\n if (!series) return []\n const points = seriesPoints(s.data, columnOf(s), series)\n if (points.length === 0) return []\n const { width: w, height: h } = plot\n const [xMin, xMax] = domains.x.range\n const [yMin, yMax] = domains.y.range\n const xToPx = (x: number) => (xMax <= xMin ? 0 : ((x - xMin) / (xMax - xMin) - 0.5) * w)\n const yToPx = (y: number) => (yMax <= yMin ? 0 : ((y - yMin) / (yMax - yMin) - 0.5) * h)\n // `seriesPoints` already sorted them along x.\n return points.map(([x, y]) => ({ x: xToPx(x), y: yToPx(y) }))\n}\n\n/** `region` mapped into the plot's centred pixel space, against the live scales, so it travels with a zoom. */\nfunction regionBox(s: LineChartValues & { readonly region: PlotRegion | null }, domains: LineChartDomains, plot: Size2D): RegionBox {\n const { width: w, height: h } = plot\n return resolveRegionBox(s.region, { left: -w / 2, right: w / 2, bottom: -h / 2, top: h / 2 }, domains.x.range, domains.y.range)\n}\n\n/**\n * Whether a call-out is authored at all. Not whether it resolves to pixels: a\n * command is built before the first layout, and a region on a chart not yet\n * measured is a real one. A region bounding neither axis is none, as `null` is.\n */\nfunction hasCallout(s: { readonly region: PlotRegion | null }): boolean {\n const region = s.region\n return region != null && (region.x !== undefined || region.y !== undefined)\n}\n\n/** The `region` a document handed a command, or `{}`: a command is added before its arguments are filled in. */\nfunction regionArg(region: PlotRegion | null | undefined): PlotRegion {\n return region != null && typeof region === \"object\" ? region : {}\n}\n\n/** A range read as a span, whichever way round the author wrote it. */\nfunction span([a, b]: Range): Range {\n return a <= b ? [a, b] : [b, a]\n}\n\n/**\n * Rescale an axis to `range`, keeping the tick *count* it already has, so each\n * marker slides from its old value to its new one instead of the row popping.\n */\nfunction rescale(range: Range, ticks: readonly number[]): AxisDomainConfig {\n const to = span(range)\n return { range: to, ticks: markerValues(to, Math.max(2, ticks.length) - 1) }\n}\n\n/** The axis writes of a move from `from` toward `to` at `t`. */\nfunction axesAt(from: LineChartDomains, to: Partial<Record<\"x\" | \"y\", AxisDomainConfig>>, t: number) {\n return {\n ...(to.x && { xAxis: lerpAxisDomain(from.x, to.x, t) }),\n ...(to.y && { yAxis: lerpAxisDomain(from.y, to.y, t) }),\n }\n}\n\ntype AnyTimeline = Timeline<any, any>\n\n/** The parts a line chart's commands drive, found through its children. */\nfunction partsOf(children: readonly ChildView[]) {\n const frame = cartesianViews(children)\n if (!frame) return null\n const hAxis = frame.below.find(HorizontalAxis.is)\n if (!VerticalAxis.is(frame.axis) || !hAxis) return null\n return {\n vAxis: frame.axis,\n hAxis,\n lines: frame.plot.filter(ChartLine.is),\n legend: frame.below.find(ChartLegend.is) ?? null,\n }\n}\n\n/** Drop the call-out: the rules retract, the wash fades, and every series comes back to full. */\nfunction clearing(timeline: AnyTimeline, state: LineState) {\n const from = state.regionReveal\n const region = state.region\n // Nothing to retract, but the call still takes its slot on the timeline.\n if (from === 0) return timeline.animate(() => ({ region: null, regionReveal: 0 }), { eased: false })\n // `region` is held until the retraction lands, or there would be nothing left to retract.\n return timeline.animate((t) => (t >= 1 ? { region: null, regionReveal: 0 } : { region, regionReveal: from * (1 - t) }))\n}\n\n/** Trace series `index`'s line in (`show`) or back out, in lockstep with its legend entry. */\nfunction toggling(timeline: AnyTimeline, children: readonly ChildView[], index: number, show: boolean) {\n const parts = partsOf(children)\n const line = parts?.lines[index]\n if (!parts || !line) return timeline.wait(timeline.duration)\n return timeline.together([\n line.run(\"enter\", show ? { from: 0, to: 1 } : { from: 1, to: 0 }),\n ...(parts.legend ? [parts.legend.run(show ? \"showSeries\" : \"hideSeries\", { index })] : []),\n ])\n}\n\n/**\n * A multi-series line chart, composed from five independent parts rather than\n * one monolithic draw:\n *\n * - {@link ChartCanvas} — the plot panel with a two-way grid, under everything.\n * - {@link VerticalAxis} / {@link HorizontalAxis} — columns/rows of real text\n * markers that stagger in, each carrying its own axis caption.\n * - {@link ChartRegion} — the optional call-out marking a spotlit slice of the\n * plot: dashed rules on its bounded edges, and every series faded outside it.\n * - {@link ChartLine} (one per series) — the traced polylines over the canvas.\n * - {@link ChartLegend} — a row of entries below the chart, one per series.\n *\n * Every part reads the chart's entries through bindings, and the lines, the\n * region and the grid all map against the plot panel's own laid-out box, so\n * points land exactly on their markers and the chart re-flows if its box\n * changes.\n *\n * **Resting state is the finished chart**: an editor paints a node's Initial\n * state on a paused canvas. `enter` arms every part on its first frame.\n *\n * Past the entrance, `showSeries`/`hideSeries`/`spotlightSeries` pick out a\n * *series*, `spotlightRegion` marks a *slice of the plot* without changing the\n * scale, and `zoomTo` rescales the axes so a slice fills the plot. A spotlit\n * region resolves against the live scales, so it travels with a zoom. A `to` of\n * an axis `range` or `ticks` tweens from the domain as drawn (see\n * {@link lerpAxisEntry}), so an auto axis rescales continuously.\n */\nexport const LineChart = component2d({\n key: \"lineChart\",\n state: {\n data: fresh<DataRecord[]>(() => [], { kind: \"dataset\" }),\n xField: \"\",\n series: fresh<LineSeries[]>(() => [], { kind: \"series\" }),\n xAxis: Types.custom<AxisDomainConfig>({}, { resolve: resolveAxisDomain, lerp: lerpAxisEntry }),\n yAxis: Types.custom<AxisDomainConfig>({}, { resolve: resolveAxisDomain, lerp: lerpAxisEntry }),\n theme: Types.custom<ChartTheme, ChartConfig>(DEFAULT_CHART_THEME, { resolve: resolveChartTheme, lerp: lerpChartTheme }),\n /**\n * The spotlit slice of the plot in data units, or `null` for none. The box\n * snaps; the animation is {@link regionReveal} drawing the rules on.\n */\n region: Types.custom<PlotRegion | null>(null),\n /**\n * How far the `region` call-out is drawn in, `[0, 1]`: the rules grow out and\n * the wash fades up as it climbs, while every line's out-of-region stretch\n * fades to the theme's `region.dimOpacity`.\n */\n regionReveal: 0,\n /** Read as the chart is built: the legend is a part the chart builds or doesn't. */\n showLegend: Types.boolean(true, { animatable: false }),\n /**\n * The domain `zoomTo` first left, so `resetZoom` restores the chart as it\n * stood, auto-derived ticks included. Cleared by `resetZoom`, so the next zoom\n * remembers wherever the chart rests then.\n */\n home: Types.custom<LineChartDomains | null>(null, { private: true }),\n },\n // Its parts fill it; a node made of them would hug them.\n defaults: { width: \"fill\", height: \"fill\" },\n allowedChildren: [],\n children: (state) => {\n const theme = () => state.theme\n const domains = () => lineChartDomains(state)\n let plot: Node2D | undefined\n const plotSize = () => laidOutSize(plot)\n const enabled = state.series.map((s) => s.enabled ?? true)\n\n // Bound, not snapshotted, so a rescale re-labels and re-places the row as it\n // tweens. The marker *count* is read once, which is why `zoomTo` keeps it.\n const vAxis = new VerticalAxis({\n range: () => domains().y.range,\n markers: () => domains().y.ticks,\n // The y axis is always numbers, so its format is simply the pattern.\n captions: () => {\n const markers = domains().y.ticks\n const format = state.yAxis.format\n return markers.map((value) => (format === undefined ? formatMarker(value, markerStep(markers)) : formatNumber(value, format)))\n },\n axis: () => theme().yAxis,\n label: state.yAxis.label ?? \"\",\n width: \"hug\",\n height: \"fill\",\n })\n\n const hAxis = new HorizontalAxis({\n range: () => domains().x.range,\n markers: () => domains().x.ticks,\n // A tick on a month or category column is captioned with the cell it came\n // out of — `Jan`, not the instant it parsed to.\n captions: () => {\n const column = columnOf(state)\n return domains().x.ticks.map((value) => column.label(value))\n },\n axis: () => theme().xAxis,\n label: state.xAxis.label ?? \"\",\n width: \"fill\",\n height: \"hug\",\n })\n\n const lines = state.series.map(\n (s, i) =>\n new ChartLine({\n points: () => seriesPixels(state, domains(), i, plotSize()),\n stroke: () => resolveSeriesStroke(theme().seriesStyles, s, i),\n enabled: enabled[i],\n // Each line clips itself against the box the rules are drawn from, so\n // the dim/bright boundary can't drift from the dashes.\n spotlight: () => regionBox(state, domains(), plotSize()),\n // Ramped by the reveal that draws the rules: one signal, both halves.\n dimOpacity: () => 1 - (1 - theme().region.dimOpacity) * state.regionReveal,\n }) as unknown as Node2D\n )\n\n const below: Node2D[] = [hAxis as unknown as Node2D]\n if (state.showLegend !== false) {\n below.push(\n new ChartLegend({\n series: state.series,\n // The legend paints a swatch, not a line, so it is handed the colour each\n // stroke resolves to rather than the stroke itself.\n swatches: () => state.series.map((s, i) => resolveSeriesFill(theme().seriesStyles, s, i)),\n legend: () => theme().legend,\n // The row's spacing is the theme's as the chart was built, like the\n // entries' type and chips: a theme tween re-paints the swatches only.\n gap: state.theme.legend.itemGap,\n padding: state.theme.legend.padding,\n }) as unknown as Node2D\n )\n }\n\n plot = new Rect({\n clip: true,\n children: [\n new ChartCanvas({\n fill: () => theme().plotArea.fill,\n shadow: () => theme().plotArea.shadow,\n xGridStroke: () => theme().xAxis.lineStyle,\n yGridStroke: () => theme().yAxis.lineStyle,\n // A grid line under every axis marker; the canvas skips the edges.\n xMarkers: () => domains().x.ticks,\n yMarkers: () => domains().y.ticks,\n xExtent: () => domains().x.range,\n yExtent: () => domains().y.range,\n }),\n // Over the grid, under the lines, so a spotlit stretch of a series isn't\n // tinted by the highlight meant to pick it out.\n new ChartRegion({\n box: () => regionBox(state, domains(), plotSize()),\n stroke: () => theme().region.stroke,\n fill: () => theme().region.fill,\n reveal: () => state.regionReveal,\n }),\n ...lines,\n new ChartBorder({ stroke: () => theme().plotArea.stroke }),\n ],\n }) as unknown as Node2D\n\n const gutter = new VerticalAxis({\n opacity: 0,\n range: () => domains().y.range,\n markers: () => domains().y.ticks,\n axis: () => theme().yAxis,\n label: state.yAxis.label ?? \"\",\n width: \"hug\",\n height: 0,\n }) as unknown as Node2D\n\n return asParts([cartesianFrame({ axis: vAxis as unknown as Node2D, plot, gutter, below })])\n },\n commands: {\n /**\n * Animate the whole chart in: the two axes stagger their markers in, the\n * series lines trace left to right, and the legend fades up last. Its first\n * frame arms every part: markers shifted and transparent, lines untraced,\n * the legend dropped and transparent.\n *\n * `duration` is the **whole** entrance; the beats are shares of it. A chart\n * authored with a `region` lands its call-out last, in the final quarter.\n */\n enter: {\n args: {},\n // Held from the chart's arrival, so it never shows finished ahead of its draw.\n entrance: true,\n easing: easeOut(),\n run: (timeline, state, children) => {\n const parts = partsOf(children)\n if (!parts) return timeline.wait(timeline.duration)\n const duration = timeline.duration\n const revealing = hasCallout(state) && state.regionReveal === 0\n const body = revealing ? duration * 0.75 : duration\n const axes = body * AXES_SHARE\n const traced = body * LINES_SHARE\n const { legend } = parts\n const at0 = (piece: Beat[\"piece\"]): Beat => ({ at: 0, duration: 0, piece })\n // The first frame arms what every later beat moves: a beat ahead of the\n // playhead writes nothing. A beat with nothing to do still takes its share.\n return beats(timeline, [\n ...(revealing ? [at0(timeline.animate(() => ({ regionReveal: 0 })))] : []),\n ...parts.lines.map((line) => at0(line.to({ progress: 0 }))),\n ...(legend ? [at0(legend.to({ opacity: 0, y: -LEGEND_SLIDE }))] : []),\n { at: 0, duration: axes, piece: parts.vAxis.run(\"enter\", { slide: 24 }) },\n { at: 0, duration: axes, piece: parts.hAxis.run(\"enter\", { slide: 24 }) },\n ...parts.lines.map((line) => ({ at: axes, duration: traced, piece: line.run(\"enter\") })),\n ...(legend ? [{ at: axes + traced, duration: body * LEGEND_SHARE, piece: legend.to({ opacity: 1, y: 0 }) }] : []),\n ...(revealing ? [{ at: body, duration: duration * 0.25, piece: timeline.animate((t) => ({ regionReveal: t })) }] : []),\n ])\n },\n },\n /**\n * Spotlight a rectangular slice of the plot given in **data units**: dashed\n * rules draw onto each bounded edge while every series fades outside the box.\n * Either axis alone is a band; both are a box. Called while another region is\n * up, the old call-out retracts over the first half and the new one draws in\n * over the second, each half eased on its own.\n */\n spotlightRegion: {\n args: { region: REGION_ARG },\n easing: easeOut(),\n run: (timeline, state) => {\n const region = regionArg(timeline.args.region)\n const from = state.regionReveal\n const previous = state.region\n // A region bounding neither axis is no call-out: spotlighting it is a clear.\n if (region.x === undefined && region.y === undefined) return clearing(timeline, state)\n // Nothing up yet: the region is set from the first frame and just draws on.\n if (from <= 0 || !hasCallout(state)) return timeline.animate((t) => ({ region, regionReveal: from + (1 - from) * t }))\n return timeline.animate(\n (t) => (t < 0.5\n ? { region: previous, regionReveal: from * (1 - timeline.ease(t * 2)) }\n : { region, regionReveal: timeline.ease(t * 2 - 1) }),\n { eased: false }\n )\n },\n },\n /** Drop the region call-out. A no-op when nothing is spotlit, which still takes its slot. */\n clearRegion: {\n args: {},\n easing: easeOut(),\n run: (timeline, state) => clearing(timeline, state),\n },\n /**\n * Zoom the plot to a slice of itself, given in **data units**: the named axes\n * rescale so that slice fills the plot, the grid, both marker rows and every\n * series following. An omitted axis is left as it is. The first zoom\n * remembers the domain it left, for `resetZoom`.\n */\n zoomTo: {\n args: { region: REGION_ARG },\n easing: easeOut(),\n run: (timeline, state) => {\n const region = regionArg(timeline.args.region)\n if (!region.x && !region.y) return timeline.wait(timeline.duration)\n const from = lineChartDomains(state)\n const home = state.home ?? from\n const to = {\n ...(region.x && { x: { ...from.x, ...rescale(region.x, from.x.ticks) } }),\n ...(region.y && { y: { ...from.y, ...rescale(region.y, from.y.ticks) } }),\n }\n return timeline.animate((t) => ({ home, ...axesAt(from, to, t) }))\n },\n },\n /** Pull back out to the domain the first zoom left — the mirror of `zoomTo`, and a hold if it never zoomed. */\n resetZoom: {\n args: {},\n easing: easeOut(),\n run: (timeline, state) => {\n const home = state.home\n if (!home) return timeline.wait(timeline.duration)\n const from = lineChartDomains(state)\n return timeline.animate((t) => ({ home: null, ...axesAt(from, home, t) }))\n },\n },\n /**\n * Show series `index`: **trace** its line in left to right, in lockstep with\n * its legend entry growing in.\n */\n showSeries: {\n args: { seriesIndex: SERIES_ARG },\n easing: easeOut(),\n run: (timeline, _state, children) => toggling(timeline, children, timeline.args.seriesIndex, true),\n },\n /** Hide series `index`: **retrace** its line back out as its legend entry shrinks away. */\n hideSeries: {\n args: { seriesIndex: SERIES_ARG },\n easing: easeOut(),\n run: (timeline, _state, children) => toggling(timeline, children, timeline.args.seriesIndex, false),\n },\n /**\n * Fade every other series — each line **and its legend entry** — to focus on\n * `index`, which comes back to full. The legend dims in place, so the row\n * doesn't reflow.\n */\n spotlightSeries: {\n args: { seriesIndex: SERIES_ARG },\n easing: easeOut(),\n run: (timeline, _state, children) => {\n const parts = partsOf(children)\n if (!parts) return timeline.wait(timeline.duration)\n const index = timeline.args.seriesIndex\n return timeline.together([\n ...parts.lines.map((line, i) => line.to({ opacity: i === index ? 1 : SPOTLIGHT_DIM })),\n ...(parts.legend ? [parts.legend.run(\"spotlightSeries\", { index })] : []),\n ])\n },\n },\n },\n})\n\nexport type LineChart = NodeOf<typeof LineChart>\n"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"shared.js","sourceRoot":"","sources":["../../src/line-chart/shared.ts"],"names":[],"mappings":"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","sourcesContent":["/**\r\n * Types and pure helpers specific to the {@link LineChart} family: the traced\r\n * polylines, the spotlit region they dim outside of, and the theme those two\r\n * add to the shared chart vocabulary.\r\n *\r\n * Everything a bar or a pie chart would want too — what a series is, how an axis\r\n * is scaled and formatted, the theme leaf resolvers, the legend and plot-panel\r\n * branches — lives in `../kit/shared.ts` and is imported here. What's\r\n * left below is what only a line chart has: points sorted along an x column,\r\n * a region clipped out of a polyline, and the `region` branch of the theme.\r\n *\r\n * Kept renderer-agnostic (no `Node` imports) so every part shares one\r\n * scale/format/palette/theme vocabulary, and so a host's own inspector\r\n * mapping can build a partial {@link ChartTheme} without\r\n * pulling the components in.\r\n */\r\n\r\nimport {\r\n Fills,\r\n fillOps,\r\n lerpNumber,\r\n strokeOps,\r\n type DataRecord,\r\n type Fill,\r\n type FillResolved,\r\n type Stroke,\r\n type StrokeResolved,\r\n} from \"@motionscript/sdk\"\r\n\r\nimport {\r\n CHART_PALETTE,\r\n DEFAULT_LEGEND,\r\n DEFAULT_PLOT_AREA,\r\n DEFAULT_SERIES_STROKES,\r\n DEFAULT_X_AXIS,\r\n DEFAULT_Y_AXIS,\r\n SPOTLIGHT_DIM,\r\n lerpAxisConfig,\r\n lerpLegendConfig,\r\n lerpPlotArea,\r\n lerpSeriesStrokes,\r\n niceStep,\r\n num,\r\n resolveAxisConfig,\r\n resolveLegendConfig,\r\n resolvePlotArea,\r\n resolveSeriesStrokes,\r\n type AxisConfig,\r\n type ChartSeries,\r\n type LegendConfig,\r\n type LegendTheme,\r\n type PlotAreaConfig,\r\n type Range,\r\n} from \"../kit/shared\"\r\nimport type { XScale } from \"./x-scale\"\r\n\r\n/**\r\n * One series in a {@link LineChart}: a polyline traced through the values in one\r\n * column of the chart's `data`, drawn in `fill` (or the theme's `seriesStyles`\r\n * palette when omitted) and captioned by `label` in the legend.\r\n *\r\n * The family-wide {@link ChartSeries} under a name that says what it draws here;\r\n * the chart's own `xField` prop names the column carrying the shared x values,\r\n * so every series is read off the same rows — one row per sample, one column per\r\n * series.\r\n */\r\nexport type LineSeries = ChartSeries\r\n\r\n// ---- Plot regions -------------------------------------------------------\r\n\r\n/**\r\n * A rectangular slice of the plot, in **data units** — the author-facing input\r\n * to {@link LineChart.spotlightRegion} / {@link LineChart.zoomTo}.\r\n *\r\n * Either axis may be omitted, and that's the point: `{ x: [60, 100] }` is a\r\n * vertical band spanning the full height, `{ y: [8, 10] }` a horizontal band\r\n * spanning the full width, and both together a box. A reversed range is read\r\n * the same as the forward one — a region is a span, not a direction.\r\n */\r\nexport interface PlotRegion {\r\n /** Horizontal span in x-axis data units. Omit to span the full plot width. */\r\n x?: Range\r\n /** Vertical span in y-axis data units. Omit to span the full plot height. */\r\n y?: Range\r\n}\r\n\r\n/**\r\n * A {@link PlotRegion} resolved into the plot's **centred pixel space** (origin\r\n * at the plot centre, y-up) — the same local frame the series points live in,\r\n * so a line can be clipped against it directly.\r\n *\r\n * `xBounded`/`yBounded` carry which axes the author actually constrained: an\r\n * unbounded axis has its edges pinned to the plot's own and draws no rule.\r\n */\r\nexport interface RegionBox {\r\n left: number\r\n right: number\r\n bottom: number\r\n top: number\r\n /** The author gave an x range — the left/right edges are real data bounds. */\r\n xBounded: boolean\r\n /** The author gave a y range — the bottom/top edges are real data bounds. */\r\n yBounded: boolean\r\n}\r\n\r\n/** The empty box, used as the \"no region\" resting value. */\r\nexport const EMPTY_REGION_BOX: RegionBox = {\r\n left: 0,\r\n right: 0,\r\n bottom: 0,\r\n top: 0,\r\n xBounded: false,\r\n yBounded: false,\r\n}\r\n\r\n/** Is `box` a real, non-degenerate region — i.e. is there anything to spotlight? */\r\nexport function hasRegion(box: RegionBox): boolean {\r\n return box.right > box.left && box.top > box.bottom\r\n}\r\n\r\n/**\r\n * Resolve a {@link PlotRegion} against the plot's pixel box and the chart's\r\n * scales. `plot` is the plot rectangle in centred pixel space, and\r\n * `xScale`/`yScale` the data ranges those edges span.\r\n *\r\n * An omitted axis takes the plot's own edges, so the region spans it. A given\r\n * axis is clamped to the plot, so a range running off the scale still produces\r\n * a box inside the panel.\r\n */\r\nexport function resolveRegionBox(\r\n region: PlotRegion | null | undefined,\r\n plot: { left: number; right: number; bottom: number; top: number },\r\n xScale: Range,\r\n yScale: Range\r\n): RegionBox {\r\n if (!region || (region.x === undefined && region.y === undefined)) {\r\n return EMPTY_REGION_BOX\r\n }\r\n\r\n const span = (\r\n range: Range | undefined,\r\n [min, max]: Range,\r\n lo: number,\r\n hi: number\r\n ): [number, number, boolean] => {\r\n if (range === undefined || max <= min) return [lo, hi, false]\r\n const a = Math.min(range[0], range[1])\r\n const b = Math.max(range[0], range[1])\r\n const toPx = (v: number) => lo + ((v - min) / (max - min)) * (hi - lo)\r\n return [\r\n Math.max(lo, Math.min(hi, toPx(a))),\r\n Math.max(lo, Math.min(hi, toPx(b))),\r\n true,\r\n ]\r\n }\r\n\r\n const [left, right, xBounded] = span(region.x, xScale, plot.left, plot.right)\r\n const [bottom, top, yBounded] = span(region.y, yScale, plot.bottom, plot.top)\r\n return { left, right, bottom, top, xBounded, yBounded }\r\n}\r\n\r\n/** A bare `{x, y}` — declared locally so this module stays free of node imports. */\r\ninterface Vector2Like {\r\n x: number\r\n y: number\r\n}\r\n\r\n/**\r\n * The parts of `points` that fall **inside** `box`, as a list of contiguous\r\n * sub-polylines — the geometry behind the region spotlight: a series is drawn\r\n * dimmed in full, then these runs are re-drawn over it at full strength.\r\n *\r\n * Segments are clipped against the box rather than filtered by endpoint, so a\r\n * line entering the region mid-segment is cut exactly on the boundary.\r\n */\r\nexport function clipPolylineToBox(\r\n points: Vector2Like[],\r\n box: RegionBox\r\n): Vector2Like[][] {\r\n if (points.length < 2 || !hasRegion(box)) return []\r\n\r\n const runs: Vector2Like[][] = []\r\n let run: Vector2Like[] = []\r\n\r\n for (let i = 1; i < points.length; i++) {\r\n const seg = clipSegment(points[i - 1], points[i], box)\r\n if (!seg) {\r\n // Segment misses the box entirely — close whatever run was open.\r\n if (run.length >= 2) runs.push(run)\r\n run = []\r\n continue\r\n }\r\n const [a, b] = seg\r\n // Continue the open run when this clipped segment starts where the last one\r\n // ended; otherwise the line left the box and came back, which is a new run.\r\n if (run.length > 0 && samePoint(run[run.length - 1], a)) run.push(b)\r\n else {\r\n if (run.length >= 2) runs.push(run)\r\n run = [a, b]\r\n }\r\n }\r\n if (run.length >= 2) runs.push(run)\r\n return runs\r\n}\r\n\r\n/** Points within half a pixel are the same point, for run-joining purposes. */\r\nfunction samePoint(a: Vector2Like, b: Vector2Like): boolean {\r\n return Math.abs(a.x - b.x) < 0.5 && Math.abs(a.y - b.y) < 0.5\r\n}\r\n\r\n/**\r\n * Liang–Barsky clip of one segment against the axis-aligned `box`. Returns the\r\n * surviving `[start, end]`, or `null` when the segment lies wholly outside.\r\n */\r\nfunction clipSegment(\r\n a: Vector2Like,\r\n b: Vector2Like,\r\n box: RegionBox\r\n): [Vector2Like, Vector2Like] | null {\r\n const dx = b.x - a.x\r\n const dy = b.y - a.y\r\n let t0 = 0\r\n let t1 = 1\r\n\r\n // Each edge as (p, q): the segment survives where p·t <= q.\r\n const edges: [number, number][] = [\r\n [-dx, a.x - box.left],\r\n [dx, box.right - a.x],\r\n [-dy, a.y - box.bottom],\r\n [dy, box.top - a.y],\r\n ]\r\n for (const [p, q] of edges) {\r\n if (p === 0) {\r\n // Parallel to this edge: outside it means the whole segment is out.\r\n if (q < 0) return null\r\n continue\r\n }\r\n const r = q / p\r\n if (p < 0) {\r\n if (r > t1) return null\r\n if (r > t0) t0 = r\r\n } else {\r\n if (r < t0) return null\r\n if (r < t1) t1 = r\r\n }\r\n }\r\n return [\r\n { x: a.x + t0 * dx, y: a.y + t0 * dy },\r\n { x: a.x + t1 * dx, y: a.y + t1 * dy },\r\n ]\r\n}\r\n\r\n// ---- Theme ---------------------------------------------------------------\r\n\r\n/**\r\n * How a spotlit {@link PlotRegion} is drawn — the dashed rules on its bounded\r\n * edges, the wash filling it, and how far the series fade outside it.\r\n */\r\nexport interface RegionConfig {\r\n /** The dashed rule marking each bounded edge. */\r\n stroke: Stroke\r\n /** Wash filling the region, drawn under the series lines. */\r\n fill: Fill\r\n /** Opacity the stretch of every series *outside* the region fades to. */\r\n dimOpacity: number\r\n}\r\n\r\n/** A {@link LineChart}'s full, resolved visual theme. */\r\nexport interface ChartConfig {\r\n /**\r\n * Default per-series line stroke, cycled by series index (`i % length`). A\r\n * series' own `fill`, when set, overrides just the colour.\r\n */\r\n seriesStyles: Stroke[]\r\n xAxis: AxisConfig\r\n yAxis: AxisConfig\r\n /** The plot panel: border, fill, and drop shadow. */\r\n plotArea: PlotAreaConfig\r\n legend: LegendConfig\r\n /** The spotlit-region annotation — see {@link RegionConfig}. */\r\n region: RegionConfig\r\n}\r\n\r\n/**\r\n * Author-facing partial theme, passed as {@link LineChart}'s `theme` prop —\r\n * every branch optional and deep-merged onto {@link DEFAULT_CHART_THEME}.\r\n */\r\nexport type ChartTheme = {\r\n seriesStyles?: Stroke[]\r\n xAxis?: Partial<AxisConfig>\r\n yAxis?: Partial<AxisConfig>\r\n plotArea?: Partial<PlotAreaConfig>\r\n legend?: LegendTheme\r\n region?: Partial<RegionConfig>\r\n}\r\n\r\n/**\r\n * The legend of a line chart: the shared one, with a small rounded-square\r\n * swatch in place of the wide chip. A bar's or a wedge's swatch stands in for\r\n * an area of paint and is drawn like one; a line's stands in for a colour, and\r\n * a square reads as the sample it is.\r\n */\r\nconst LINE_CHART_LEGEND: LegendConfig = {\r\n ...DEFAULT_LEGEND,\r\n markerStyle: {\r\n ...DEFAULT_LEGEND.markerStyle,\r\n width: 20,\r\n height: 20,\r\n borderRadius: 6,\r\n },\r\n}\r\n\r\n/** The chart's out-of-the-box look. */\r\nexport const DEFAULT_CHART_THEME: ChartConfig = {\r\n seriesStyles: DEFAULT_SERIES_STROKES,\r\n xAxis: DEFAULT_X_AXIS,\r\n yAxis: DEFAULT_Y_AXIS,\r\n plotArea: DEFAULT_PLOT_AREA,\r\n legend: LINE_CHART_LEGEND,\r\n region: {\r\n // Brighter than the grid and dashed, so the boundary reads as a call-out\r\n // rather than another axis line; `butt` caps keep the dash lengths exact.\r\n stroke: {\r\n weight: 3,\r\n fill: CHART_PALETTE.regionColor,\r\n dash: [14, 12],\r\n cap: \"butt\",\r\n },\r\n // A wash barely above the panel — enough to tint the band, not enough to\r\n // mute the series drawn over it.\r\n fill: Fills.color(CHART_PALETTE.regionColor, { opacity: 0.08 }),\r\n dimOpacity: SPOTLIGHT_DIM,\r\n },\r\n}\r\n\r\nfunction resolveRegionConfig(\r\n region: Partial<RegionConfig> | undefined,\r\n previous: RegionConfig\r\n): RegionConfig {\r\n return {\r\n stroke: strokeOps.resolve(region?.stroke ?? previous.stroke),\r\n fill: fillOps.resolve(region?.fill ?? previous.fill),\r\n dimOpacity: region?.dimOpacity ?? previous.dimOpacity,\r\n }\r\n}\r\n\r\nfunction lerpRegionConfig(\r\n from: RegionConfig,\r\n to: RegionConfig,\r\n t: number\r\n): RegionConfig {\r\n return {\r\n stroke: strokeOps.lerp(\r\n from.stroke as StrokeResolved[],\r\n to.stroke as StrokeResolved[],\r\n t\r\n ),\r\n fill: fillOps.lerp(\r\n from.fill as FillResolved[],\r\n to.fill as FillResolved[],\r\n t\r\n ),\r\n dimOpacity: lerpNumber(from.dimOpacity, to.dimOpacity, t),\r\n }\r\n}\r\n\r\n/**\r\n * {@link LineChart}'s `theme` entry's resolve: merges the author's partial\r\n * {@link ChartTheme} onto `previous` (falling back to\r\n * {@link DEFAULT_CHART_THEME} on first resolution), fully resolving every leaf.\r\n */\r\nexport function resolveChartTheme(\r\n theme: ChartTheme | undefined,\r\n previous?: ChartConfig\r\n): ChartConfig {\r\n const base = previous ?? DEFAULT_CHART_THEME\r\n return {\r\n seriesStyles: resolveSeriesStrokes(theme?.seriesStyles, base.seriesStyles),\r\n xAxis: resolveAxisConfig(theme?.xAxis, base.xAxis),\r\n yAxis: resolveAxisConfig(theme?.yAxis, base.yAxis),\r\n plotArea: resolvePlotArea(theme?.plotArea, base.plotArea),\r\n legend: resolveLegendConfig(theme?.legend, base.legend),\r\n region: resolveRegionConfig(theme?.region, base.region),\r\n }\r\n}\r\n\r\n/** {@link LineChart}'s `theme` entry's lerp — leaf by leaf. */\r\nexport function lerpChartTheme(\r\n from: ChartConfig,\r\n to: ChartConfig,\r\n t: number\r\n): ChartConfig {\r\n return {\r\n seriesStyles: lerpSeriesStrokes(from.seriesStyles, to.seriesStyles, t),\r\n xAxis: lerpAxisConfig(from.xAxis, to.xAxis, t),\r\n yAxis: lerpAxisConfig(from.yAxis, to.yAxis, t),\r\n plotArea: lerpPlotArea(from.plotArea, to.plotArea, t),\r\n legend: lerpLegendConfig(from.legend, to.legend, t),\r\n region: lerpRegionConfig(from.region, to.region, t),\r\n }\r\n}\r\n\r\n// ---- Scales --------------------------------------------------------------\r\n\r\n/**\r\n * Resolve one series' `[x, y]` points out of the chart's rows: each row's\r\n * position on the {@link XScale} paired with its own `field` column, sorted\r\n * along x so the polyline traces left-to-right whatever order the rows arrived\r\n * in.\r\n *\r\n * A row missing its y column contributes a 0 rather than a gap — these charts\r\n * draw continuous lines, so dropping the point would silently bridge the hole.\r\n *\r\n * Takes the resolved scale rather than the column *name*, because what a row's x\r\n * is depends on what kind of column it came out of: a number, an instant, or a\r\n * place in the file. See `x-scale.ts`.\r\n */\r\nexport function seriesPoints(\r\n data: DataRecord[],\r\n x: XScale,\r\n series: LineSeries\r\n): [x: number, y: number][] {\r\n return data\r\n .map((row, i): [number, number] => [x.at(i), num(row, series.field)])\r\n .sort((a, b) => a[0] - b[0])\r\n}\r\n\r\n/** Min/max across every series' column, the fallback when unset. */\r\nexport function yExtent(data: DataRecord[], series: LineSeries[]): Range {\r\n let lo = Infinity\r\n let hi = -Infinity\r\n for (const row of data)\r\n for (const s of series) {\r\n const v = num(row, s.field)\r\n if (v < lo) lo = v\r\n if (v > hi) hi = v\r\n }\r\n return lo <= hi ? [lo, hi] : [0, 1]\r\n}\r\n\r\n/**\r\n * Effective vertical scale: the explicit `range`, else the data's y extent\r\n * nudged out to tidy step bounds so markers read as round numbers.\r\n *\r\n * `divisions` is how many segments the auto-range is stepped into (one fewer\r\n * than a marker count) — it only shapes the tidy step when `range` is omitted.\r\n */\r\nexport function resolveYScale(\r\n data: DataRecord[],\r\n series: LineSeries[],\r\n range: Range | undefined,\r\n divisions: number\r\n): Range {\r\n if (range) return range\r\n const [lo, hi] = yExtent(data, series)\r\n const segments = Math.max(1, Math.round(divisions))\r\n if (hi === lo) return constantScale(lo, segments)\r\n const step = niceStep((hi - lo) / segments)\r\n return [Math.floor(lo / step) * step, Math.ceil(hi / step) * step]\r\n}\r\n\r\n/**\r\n * The scale for data that never moves. A zero-width scale puts every tick on the\r\n * same value and the line on the plot's floor, so it is widened to a few steps\r\n * either side of the value (the step sized to its magnitude, so `5` gets\r\n * `[3, 7]` and `5000` gets `[3000, 7000]`), or to `[0, 1]` for all zeros, as for\r\n * no data at all.\r\n */\r\nfunction constantScale(value: number, segments: number): Range {\r\n if (value === 0) return [0, 1]\r\n const step = niceStep(Math.abs(value) / segments)\r\n return [value - step, value + step]\r\n}\r\n"]}
|
|
1
|
+
{"version":3,"file":"shared.js","sourceRoot":"","sources":["../../src/line-chart/shared.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Types and pure helpers specific to the {@link LineChart} family: the traced\n * polylines, the spotlit region they dim outside of, and the theme those two\n * add to the shared chart vocabulary.\n *\n * Everything a bar or a pie chart would want too — what a series is, how an axis\n * is scaled and formatted, the theme leaf resolvers, the legend and plot-panel\n * branches — lives in `../kit/shared.ts` and is imported here. What's\n * left below is what only a line chart has: points sorted along an x column,\n * a region clipped out of a polyline, and the `region` branch of the theme.\n *\n * Kept renderer-agnostic (no `Node` imports) so every part shares one\n * scale/format/palette/theme vocabulary, and so a host's own inspector\n * mapping can build a partial {@link ChartTheme} without\n * pulling the components in.\n */\n\nimport {\n Fills,\n fillOps,\n lerpNumber,\n strokeOps,\n type DataRecord,\n type Fill,\n type FillResolved,\n type Stroke,\n type StrokeResolved,\n} from \"@motionscript/sdk\"\n\nimport {\n CHART_PALETTE,\n DEFAULT_LEGEND,\n DEFAULT_PLOT_AREA,\n DEFAULT_SERIES_STROKES,\n DEFAULT_X_AXIS,\n DEFAULT_Y_AXIS,\n SPOTLIGHT_DIM,\n lerpAxisConfig,\n lerpLegendConfig,\n lerpPlotArea,\n lerpSeriesStrokes,\n niceStep,\n num,\n resolveAxisConfig,\n resolveLegendConfig,\n resolvePlotArea,\n resolveSeriesStrokes,\n type AxisConfig,\n type ChartSeries,\n type LegendConfig,\n type LegendTheme,\n type PlotAreaConfig,\n type Range,\n} from \"../kit/shared\"\nimport type { XScale } from \"./x-scale\"\n\n/**\n * One series in a {@link LineChart}: a polyline traced through the values in one\n * column of the chart's `data`, drawn in `fill` (or the theme's `seriesStyles`\n * palette when omitted) and captioned by `label` in the legend.\n *\n * The family-wide {@link ChartSeries} under a name that says what it draws here;\n * the chart's own `xField` prop names the column carrying the shared x values,\n * so every series is read off the same rows — one row per sample, one column per\n * series.\n */\nexport type LineSeries = ChartSeries\n\n// ---- Plot regions -------------------------------------------------------\n\n/**\n * A rectangular slice of the plot, in **data units** — the author-facing input\n * to {@link LineChart.spotlightRegion} / {@link LineChart.zoomTo}.\n *\n * Either axis may be omitted, and that's the point: `{ x: [60, 100] }` is a\n * vertical band spanning the full height, `{ y: [8, 10] }` a horizontal band\n * spanning the full width, and both together a box. A reversed range is read\n * the same as the forward one — a region is a span, not a direction.\n */\nexport interface PlotRegion {\n /** Horizontal span in x-axis data units. Omit to span the full plot width. */\n x?: Range\n /** Vertical span in y-axis data units. Omit to span the full plot height. */\n y?: Range\n}\n\n/**\n * A {@link PlotRegion} resolved into the plot's **centred pixel space** (origin\n * at the plot centre, y-up) — the same local frame the series points live in,\n * so a line can be clipped against it directly.\n *\n * `xBounded`/`yBounded` carry which axes the author actually constrained: an\n * unbounded axis has its edges pinned to the plot's own and draws no rule.\n */\nexport interface RegionBox {\n left: number\n right: number\n bottom: number\n top: number\n /** The author gave an x range — the left/right edges are real data bounds. */\n xBounded: boolean\n /** The author gave a y range — the bottom/top edges are real data bounds. */\n yBounded: boolean\n}\n\n/** The empty box, used as the \"no region\" resting value. */\nexport const EMPTY_REGION_BOX: RegionBox = {\n left: 0,\n right: 0,\n bottom: 0,\n top: 0,\n xBounded: false,\n yBounded: false,\n}\n\n/** Is `box` a real, non-degenerate region — i.e. is there anything to spotlight? */\nexport function hasRegion(box: RegionBox): boolean {\n return box.right > box.left && box.top > box.bottom\n}\n\n/**\n * Resolve a {@link PlotRegion} against the plot's pixel box and the chart's\n * scales. `plot` is the plot rectangle in centred pixel space, and\n * `xScale`/`yScale` the data ranges those edges span.\n *\n * An omitted axis takes the plot's own edges, so the region spans it. A given\n * axis is clamped to the plot, so a range running off the scale still produces\n * a box inside the panel.\n */\nexport function resolveRegionBox(\n region: PlotRegion | null | undefined,\n plot: { left: number; right: number; bottom: number; top: number },\n xScale: Range,\n yScale: Range\n): RegionBox {\n if (!region || (region.x === undefined && region.y === undefined)) {\n return EMPTY_REGION_BOX\n }\n\n const span = (\n range: Range | undefined,\n [min, max]: Range,\n lo: number,\n hi: number\n ): [number, number, boolean] => {\n if (range === undefined || max <= min) return [lo, hi, false]\n const a = Math.min(range[0], range[1])\n const b = Math.max(range[0], range[1])\n const toPx = (v: number) => lo + ((v - min) / (max - min)) * (hi - lo)\n return [\n Math.max(lo, Math.min(hi, toPx(a))),\n Math.max(lo, Math.min(hi, toPx(b))),\n true,\n ]\n }\n\n const [left, right, xBounded] = span(region.x, xScale, plot.left, plot.right)\n const [bottom, top, yBounded] = span(region.y, yScale, plot.bottom, plot.top)\n return { left, right, bottom, top, xBounded, yBounded }\n}\n\n/** A bare `{x, y}` — declared locally so this module stays free of node imports. */\ninterface Vector2Like {\n x: number\n y: number\n}\n\n/**\n * The parts of `points` that fall **inside** `box`, as a list of contiguous\n * sub-polylines — the geometry behind the region spotlight: a series is drawn\n * dimmed in full, then these runs are re-drawn over it at full strength.\n *\n * Segments are clipped against the box rather than filtered by endpoint, so a\n * line entering the region mid-segment is cut exactly on the boundary.\n */\nexport function clipPolylineToBox(\n points: Vector2Like[],\n box: RegionBox\n): Vector2Like[][] {\n if (points.length < 2 || !hasRegion(box)) return []\n\n const runs: Vector2Like[][] = []\n let run: Vector2Like[] = []\n\n for (let i = 1; i < points.length; i++) {\n const seg = clipSegment(points[i - 1], points[i], box)\n if (!seg) {\n // Segment misses the box entirely — close whatever run was open.\n if (run.length >= 2) runs.push(run)\n run = []\n continue\n }\n const [a, b] = seg\n // Continue the open run when this clipped segment starts where the last one\n // ended; otherwise the line left the box and came back, which is a new run.\n if (run.length > 0 && samePoint(run[run.length - 1], a)) run.push(b)\n else {\n if (run.length >= 2) runs.push(run)\n run = [a, b]\n }\n }\n if (run.length >= 2) runs.push(run)\n return runs\n}\n\n/** Points within half a pixel are the same point, for run-joining purposes. */\nfunction samePoint(a: Vector2Like, b: Vector2Like): boolean {\n return Math.abs(a.x - b.x) < 0.5 && Math.abs(a.y - b.y) < 0.5\n}\n\n/**\n * Liang–Barsky clip of one segment against the axis-aligned `box`. Returns the\n * surviving `[start, end]`, or `null` when the segment lies wholly outside.\n */\nfunction clipSegment(\n a: Vector2Like,\n b: Vector2Like,\n box: RegionBox\n): [Vector2Like, Vector2Like] | null {\n const dx = b.x - a.x\n const dy = b.y - a.y\n let t0 = 0\n let t1 = 1\n\n // Each edge as (p, q): the segment survives where p·t <= q.\n const edges: [number, number][] = [\n [-dx, a.x - box.left],\n [dx, box.right - a.x],\n [-dy, a.y - box.bottom],\n [dy, box.top - a.y],\n ]\n for (const [p, q] of edges) {\n if (p === 0) {\n // Parallel to this edge: outside it means the whole segment is out.\n if (q < 0) return null\n continue\n }\n const r = q / p\n if (p < 0) {\n if (r > t1) return null\n if (r > t0) t0 = r\n } else {\n if (r < t0) return null\n if (r < t1) t1 = r\n }\n }\n return [\n { x: a.x + t0 * dx, y: a.y + t0 * dy },\n { x: a.x + t1 * dx, y: a.y + t1 * dy },\n ]\n}\n\n// ---- Theme ---------------------------------------------------------------\n\n/**\n * How a spotlit {@link PlotRegion} is drawn — the dashed rules on its bounded\n * edges, the wash filling it, and how far the series fade outside it.\n */\nexport interface RegionConfig {\n /** The dashed rule marking each bounded edge. */\n stroke: Stroke\n /** Wash filling the region, drawn under the series lines. */\n fill: Fill\n /** Opacity the stretch of every series *outside* the region fades to. */\n dimOpacity: number\n}\n\n/** A {@link LineChart}'s full, resolved visual theme. */\nexport interface ChartConfig {\n /**\n * Default per-series line stroke, cycled by series index (`i % length`). A\n * series' own `fill`, when set, overrides just the colour.\n */\n seriesStyles: Stroke[]\n xAxis: AxisConfig\n yAxis: AxisConfig\n /** The plot panel: border, fill, and drop shadow. */\n plotArea: PlotAreaConfig\n legend: LegendConfig\n /** The spotlit-region annotation — see {@link RegionConfig}. */\n region: RegionConfig\n}\n\n/**\n * Author-facing partial theme, passed as {@link LineChart}'s `theme` prop —\n * every branch optional and deep-merged onto {@link DEFAULT_CHART_THEME}.\n */\nexport type ChartTheme = {\n seriesStyles?: Stroke[]\n xAxis?: Partial<AxisConfig>\n yAxis?: Partial<AxisConfig>\n plotArea?: Partial<PlotAreaConfig>\n legend?: LegendTheme\n region?: Partial<RegionConfig>\n}\n\n/**\n * The legend of a line chart: the shared one, with a small rounded-square\n * swatch in place of the wide chip. A bar's or a wedge's swatch stands in for\n * an area of paint and is drawn like one; a line's stands in for a colour, and\n * a square reads as the sample it is.\n */\nconst LINE_CHART_LEGEND: LegendConfig = {\n ...DEFAULT_LEGEND,\n markerStyle: {\n ...DEFAULT_LEGEND.markerStyle,\n width: 20,\n height: 20,\n borderRadius: 6,\n },\n}\n\n/** The chart's out-of-the-box look. */\nexport const DEFAULT_CHART_THEME: ChartConfig = {\n seriesStyles: DEFAULT_SERIES_STROKES,\n xAxis: DEFAULT_X_AXIS,\n yAxis: DEFAULT_Y_AXIS,\n plotArea: DEFAULT_PLOT_AREA,\n legend: LINE_CHART_LEGEND,\n region: {\n // Brighter than the grid and dashed, so the boundary reads as a call-out\n // rather than another axis line; `butt` caps keep the dash lengths exact.\n stroke: {\n weight: 3,\n fill: CHART_PALETTE.regionColor,\n dash: [14, 12],\n cap: \"butt\",\n },\n // A wash barely above the panel — enough to tint the band, not enough to\n // mute the series drawn over it.\n fill: Fills.color(CHART_PALETTE.regionColor, { opacity: 0.08 }),\n dimOpacity: SPOTLIGHT_DIM,\n },\n}\n\nfunction resolveRegionConfig(\n region: Partial<RegionConfig> | undefined,\n previous: RegionConfig\n): RegionConfig {\n return {\n stroke: strokeOps.resolve(region?.stroke ?? previous.stroke),\n fill: fillOps.resolve(region?.fill ?? previous.fill),\n dimOpacity: region?.dimOpacity ?? previous.dimOpacity,\n }\n}\n\nfunction lerpRegionConfig(\n from: RegionConfig,\n to: RegionConfig,\n t: number\n): RegionConfig {\n return {\n stroke: strokeOps.lerp(\n from.stroke as StrokeResolved[],\n to.stroke as StrokeResolved[],\n t\n ),\n fill: fillOps.lerp(\n from.fill as FillResolved[],\n to.fill as FillResolved[],\n t\n ),\n dimOpacity: lerpNumber(from.dimOpacity, to.dimOpacity, t),\n }\n}\n\n/**\n * {@link LineChart}'s `theme` entry's resolve: merges the author's partial\n * {@link ChartTheme} onto `previous` (falling back to\n * {@link DEFAULT_CHART_THEME} on first resolution), fully resolving every leaf.\n */\nexport function resolveChartTheme(\n theme: ChartTheme | undefined,\n previous?: ChartConfig\n): ChartConfig {\n const base = previous ?? DEFAULT_CHART_THEME\n return {\n seriesStyles: resolveSeriesStrokes(theme?.seriesStyles, base.seriesStyles),\n xAxis: resolveAxisConfig(theme?.xAxis, base.xAxis),\n yAxis: resolveAxisConfig(theme?.yAxis, base.yAxis),\n plotArea: resolvePlotArea(theme?.plotArea, base.plotArea),\n legend: resolveLegendConfig(theme?.legend, base.legend),\n region: resolveRegionConfig(theme?.region, base.region),\n }\n}\n\n/** {@link LineChart}'s `theme` entry's lerp — leaf by leaf. */\nexport function lerpChartTheme(\n from: ChartConfig,\n to: ChartConfig,\n t: number\n): ChartConfig {\n return {\n seriesStyles: lerpSeriesStrokes(from.seriesStyles, to.seriesStyles, t),\n xAxis: lerpAxisConfig(from.xAxis, to.xAxis, t),\n yAxis: lerpAxisConfig(from.yAxis, to.yAxis, t),\n plotArea: lerpPlotArea(from.plotArea, to.plotArea, t),\n legend: lerpLegendConfig(from.legend, to.legend, t),\n region: lerpRegionConfig(from.region, to.region, t),\n }\n}\n\n// ---- Scales --------------------------------------------------------------\n\n/**\n * Resolve one series' `[x, y]` points out of the chart's rows: each row's\n * position on the {@link XScale} paired with its own `field` column, sorted\n * along x so the polyline traces left-to-right whatever order the rows arrived\n * in.\n *\n * A row missing its y column contributes a 0 rather than a gap — these charts\n * draw continuous lines, so dropping the point would silently bridge the hole.\n *\n * Takes the resolved scale rather than the column *name*, because what a row's x\n * is depends on what kind of column it came out of: a number, an instant, or a\n * place in the file. See `x-scale.ts`.\n */\nexport function seriesPoints(\n data: DataRecord[],\n x: XScale,\n series: LineSeries\n): [x: number, y: number][] {\n return data\n .map((row, i): [number, number] => [x.at(i), num(row, series.field)])\n .sort((a, b) => a[0] - b[0])\n}\n\n/** Min/max across every series' column, the fallback when unset. */\nexport function yExtent(data: DataRecord[], series: LineSeries[]): Range {\n let lo = Infinity\n let hi = -Infinity\n for (const row of data)\n for (const s of series) {\n const v = num(row, s.field)\n if (v < lo) lo = v\n if (v > hi) hi = v\n }\n return lo <= hi ? [lo, hi] : [0, 1]\n}\n\n/**\n * Effective vertical scale: the explicit `range`, else the data's y extent\n * nudged out to tidy step bounds so markers read as round numbers.\n *\n * `divisions` is how many segments the auto-range is stepped into (one fewer\n * than a marker count) — it only shapes the tidy step when `range` is omitted.\n */\nexport function resolveYScale(\n data: DataRecord[],\n series: LineSeries[],\n range: Range | undefined,\n divisions: number\n): Range {\n if (range) return range\n const [lo, hi] = yExtent(data, series)\n const segments = Math.max(1, Math.round(divisions))\n if (hi === lo) return constantScale(lo, segments)\n const step = niceStep((hi - lo) / segments)\n return [Math.floor(lo / step) * step, Math.ceil(hi / step) * step]\n}\n\n/**\n * The scale for data that never moves. A zero-width scale puts every tick on the\n * same value and the line on the plot's floor, so it is widened to a few steps\n * either side of the value (the step sized to its magnitude, so `5` gets\n * `[3, 7]` and `5000` gets `[3000, 7000]`), or to `[0, 1]` for all zeros, as for\n * no data at all.\n */\nfunction constantScale(value: number, segments: number): Range {\n if (value === 0) return [0, 1]\n const step = niceStep(Math.abs(value) / segments)\n return [value - step, value + step]\n}\n"]}
|