@motionscript/charts 0.1.1-alpha.0 → 0.1.1-alpha.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (207) hide show
  1. package/CHANGELOG.md +19 -0
  2. package/README.md +98 -28
  3. package/dist/bar-chart/bar-chart.d.ts +233 -39
  4. package/dist/bar-chart/bar-chart.d.ts.map +1 -1
  5. package/dist/bar-chart/bar-chart.js +215 -171
  6. package/dist/bar-chart/bar-chart.js.map +1 -1
  7. package/dist/bar-chart/category-axis.d.ts +12 -7
  8. package/dist/bar-chart/category-axis.d.ts.map +1 -1
  9. package/dist/bar-chart/category-axis.js +56 -42
  10. package/dist/bar-chart/category-axis.js.map +1 -1
  11. package/dist/bar-chart/chart-bars.d.ts +52 -52
  12. package/dist/bar-chart/chart-bars.d.ts.map +1 -1
  13. package/dist/bar-chart/chart-bars.js +80 -89
  14. package/dist/bar-chart/chart-bars.js.map +1 -1
  15. package/dist/bar-chart/index.d.ts +4 -4
  16. package/dist/bar-chart/index.d.ts.map +1 -1
  17. package/dist/bar-chart/index.js +2 -2
  18. package/dist/bar-chart/index.js.map +1 -1
  19. package/dist/bar-chart/shared.d.ts +36 -65
  20. package/dist/bar-chart/shared.d.ts.map +1 -1
  21. package/dist/bar-chart/shared.js +68 -117
  22. package/dist/bar-chart/shared.js.map +1 -1
  23. package/dist/browser/chunks/chunk-R3Q5EE6E.js +2 -0
  24. package/dist/browser/chunks/chunk-R3Q5EE6E.js.map +7 -0
  25. package/dist/browser/index.js +1 -1
  26. package/dist/browser/index.js.map +4 -4
  27. package/dist/browser/kit.js +1 -1
  28. package/dist/browser/manifest.json +1 -1
  29. package/dist/engine.d.ts +5 -2
  30. package/dist/engine.d.ts.map +1 -1
  31. package/dist/engine.js +5 -2
  32. package/dist/engine.js.map +1 -1
  33. package/dist/index.d.ts +2 -0
  34. package/dist/index.d.ts.map +1 -1
  35. package/dist/index.js +2 -0
  36. package/dist/index.js.map +1 -1
  37. package/dist/kit/cartesian.d.ts +49 -15
  38. package/dist/kit/cartesian.d.ts.map +1 -1
  39. package/dist/kit/cartesian.js +79 -29
  40. package/dist/kit/cartesian.js.map +1 -1
  41. package/dist/kit/chart-canvas.d.ts +32 -24
  42. package/dist/kit/chart-canvas.d.ts.map +1 -1
  43. package/dist/kit/chart-canvas.js +52 -46
  44. package/dist/kit/chart-canvas.js.map +1 -1
  45. package/dist/kit/chart-legend.d.ts +8 -4
  46. package/dist/kit/chart-legend.d.ts.map +1 -1
  47. package/dist/kit/chart-legend.js +30 -20
  48. package/dist/kit/chart-legend.js.map +1 -1
  49. package/dist/{line-chart → kit}/horizontal-axis.d.ts +31 -6
  50. package/dist/kit/horizontal-axis.d.ts.map +1 -0
  51. package/dist/{line-chart → kit}/horizontal-axis.js +23 -24
  52. package/dist/kit/horizontal-axis.js.map +1 -0
  53. package/dist/kit/motion.d.ts +5 -0
  54. package/dist/kit/motion.d.ts.map +1 -1
  55. package/dist/kit/motion.js +8 -0
  56. package/dist/kit/motion.js.map +1 -1
  57. package/dist/{pie-chart → kit}/pie-legend.d.ts +3 -3
  58. package/dist/kit/pie-legend.d.ts.map +1 -0
  59. package/dist/{pie-chart → kit}/pie-legend.js +11 -10
  60. package/dist/kit/pie-legend.js.map +1 -0
  61. package/dist/kit/polar.d.ts +31 -0
  62. package/dist/kit/polar.d.ts.map +1 -0
  63. package/dist/kit/polar.js +33 -0
  64. package/dist/kit/polar.js.map +1 -0
  65. package/dist/kit/shared.d.ts +11 -50
  66. package/dist/kit/shared.d.ts.map +1 -1
  67. package/dist/kit/shared.js +58 -141
  68. package/dist/kit/shared.js.map +1 -1
  69. package/dist/kit/style.d.ts +254 -0
  70. package/dist/kit/style.d.ts.map +1 -0
  71. package/dist/kit/style.js +197 -0
  72. package/dist/kit/style.js.map +1 -0
  73. package/dist/kit/vertical-axis.d.ts +22 -2
  74. package/dist/kit/vertical-axis.d.ts.map +1 -1
  75. package/dist/kit/vertical-axis.js +56 -43
  76. package/dist/kit/vertical-axis.js.map +1 -1
  77. package/dist/line-chart/chart-line.d.ts +95 -3
  78. package/dist/line-chart/chart-line.d.ts.map +1 -1
  79. package/dist/line-chart/chart-line.js +165 -53
  80. package/dist/line-chart/chart-line.js.map +1 -1
  81. package/dist/line-chart/chart-region.d.ts +1 -1
  82. package/dist/line-chart/chart-region.d.ts.map +1 -1
  83. package/dist/line-chart/chart-region.js +7 -8
  84. package/dist/line-chart/chart-region.js.map +1 -1
  85. package/dist/line-chart/index.d.ts +5 -6
  86. package/dist/line-chart/index.d.ts.map +1 -1
  87. package/dist/line-chart/index.js +3 -4
  88. package/dist/line-chart/index.js.map +1 -1
  89. package/dist/line-chart/line-chart.d.ts +257 -18
  90. package/dist/line-chart/line-chart.d.ts.map +1 -1
  91. package/dist/line-chart/line-chart.js +282 -134
  92. package/dist/line-chart/line-chart.js.map +1 -1
  93. package/dist/line-chart/shared.d.ts +51 -34
  94. package/dist/line-chart/shared.d.ts.map +1 -1
  95. package/dist/line-chart/shared.js +175 -83
  96. package/dist/line-chart/shared.js.map +1 -1
  97. package/dist/line-chart/x-scale.d.ts +2 -0
  98. package/dist/line-chart/x-scale.d.ts.map +1 -1
  99. package/dist/line-chart/x-scale.js +15 -0
  100. package/dist/line-chart/x-scale.js.map +1 -1
  101. package/dist/nodes.d.ts +3 -1
  102. package/dist/nodes.d.ts.map +1 -1
  103. package/dist/nodes.js +9 -1
  104. package/dist/nodes.js.map +1 -1
  105. package/dist/pie-chart/index.d.ts +2 -3
  106. package/dist/pie-chart/index.d.ts.map +1 -1
  107. package/dist/pie-chart/index.js +1 -2
  108. package/dist/pie-chart/index.js.map +1 -1
  109. package/dist/pie-chart/pie-chart.d.ts +114 -18
  110. package/dist/pie-chart/pie-chart.d.ts.map +1 -1
  111. package/dist/pie-chart/pie-chart.js +37 -24
  112. package/dist/pie-chart/pie-chart.js.map +1 -1
  113. package/dist/pie-chart/pie-ring.d.ts +16 -5
  114. package/dist/pie-chart/pie-ring.d.ts.map +1 -1
  115. package/dist/pie-chart/pie-ring.js +89 -55
  116. package/dist/pie-chart/pie-ring.js.map +1 -1
  117. package/dist/pie-chart/shared.d.ts +53 -61
  118. package/dist/pie-chart/shared.d.ts.map +1 -1
  119. package/dist/pie-chart/shared.js +41 -121
  120. package/dist/pie-chart/shared.js.map +1 -1
  121. package/dist/radar-chart/index.d.ts +5 -0
  122. package/dist/radar-chart/index.d.ts.map +1 -0
  123. package/dist/radar-chart/index.js +5 -0
  124. package/dist/radar-chart/index.js.map +1 -0
  125. package/dist/radar-chart/radar-chart.d.ts +218 -0
  126. package/dist/radar-chart/radar-chart.d.ts.map +1 -0
  127. package/dist/radar-chart/radar-chart.js +224 -0
  128. package/dist/radar-chart/radar-chart.js.map +1 -0
  129. package/dist/radar-chart/radar-grid.d.ts +43 -0
  130. package/dist/radar-chart/radar-grid.d.ts.map +1 -0
  131. package/dist/radar-chart/radar-grid.js +61 -0
  132. package/dist/radar-chart/radar-grid.js.map +1 -0
  133. package/dist/radar-chart/radar-series.d.ts +59 -0
  134. package/dist/radar-chart/radar-series.d.ts.map +1 -0
  135. package/dist/radar-chart/radar-series.js +71 -0
  136. package/dist/radar-chart/radar-series.js.map +1 -0
  137. package/dist/radar-chart/shared.d.ts +73 -0
  138. package/dist/radar-chart/shared.d.ts.map +1 -0
  139. package/dist/radar-chart/shared.js +123 -0
  140. package/dist/radar-chart/shared.js.map +1 -0
  141. package/dist/radial-chart/index.d.ts +6 -0
  142. package/dist/radial-chart/index.d.ts.map +1 -0
  143. package/dist/radial-chart/index.js +4 -0
  144. package/dist/radial-chart/index.js.map +1 -0
  145. package/dist/radial-chart/radial-chart.d.ts +216 -0
  146. package/dist/radial-chart/radial-chart.d.ts.map +1 -0
  147. package/dist/radial-chart/radial-chart.js +174 -0
  148. package/dist/radial-chart/radial-chart.js.map +1 -0
  149. package/dist/radial-chart/radial-rings.d.ts +121 -0
  150. package/dist/radial-chart/radial-rings.d.ts.map +1 -0
  151. package/dist/radial-chart/radial-rings.js +273 -0
  152. package/dist/radial-chart/radial-rings.js.map +1 -0
  153. package/dist/radial-chart/shared.d.ts +73 -0
  154. package/dist/radial-chart/shared.d.ts.map +1 -0
  155. package/dist/radial-chart/shared.js +79 -0
  156. package/dist/radial-chart/shared.js.map +1 -0
  157. package/package.json +4 -4
  158. package/registry.json +21 -6
  159. package/src/bar-chart/bar-chart.ts +252 -179
  160. package/src/bar-chart/category-axis.ts +46 -40
  161. package/src/bar-chart/chart-bars.ts +97 -117
  162. package/src/bar-chart/index.ts +7 -10
  163. package/src/bar-chart/shared.ts +78 -238
  164. package/src/engine.ts +5 -2
  165. package/src/index.ts +2 -0
  166. package/src/kit/cartesian.ts +118 -40
  167. package/src/kit/chart-canvas.ts +49 -54
  168. package/src/kit/chart-legend.ts +28 -20
  169. package/src/kit/horizontal-axis.ts +114 -0
  170. package/src/kit/motion.ts +7 -0
  171. package/src/{pie-chart → kit}/pie-legend.ts +12 -11
  172. package/src/kit/polar.ts +54 -0
  173. package/src/kit/shared.ts +55 -277
  174. package/src/kit/style.ts +257 -0
  175. package/src/kit/vertical-axis.ts +67 -48
  176. package/src/line-chart/chart-line.ts +176 -54
  177. package/src/line-chart/chart-region.ts +6 -10
  178. package/src/line-chart/index.ts +14 -10
  179. package/src/line-chart/line-chart.ts +347 -151
  180. package/src/line-chart/shared.ts +193 -174
  181. package/src/line-chart/x-scale.ts +13 -0
  182. package/src/nodes.ts +9 -1
  183. package/src/pie-chart/index.ts +2 -23
  184. package/src/pie-chart/pie-chart.ts +52 -35
  185. package/src/pie-chart/pie-ring.ts +92 -71
  186. package/src/pie-chart/shared.ts +68 -266
  187. package/src/radar-chart/index.ts +4 -0
  188. package/src/radar-chart/radar-chart.ts +287 -0
  189. package/src/radar-chart/radar-grid.ts +78 -0
  190. package/src/radar-chart/radar-series.ts +88 -0
  191. package/src/radar-chart/shared.ts +146 -0
  192. package/src/radial-chart/index.ts +5 -0
  193. package/src/radial-chart/radial-chart.ts +210 -0
  194. package/src/radial-chart/radial-rings.ts +328 -0
  195. package/src/radial-chart/shared.ts +114 -0
  196. package/dist/browser/chunks/chunk-4SMRCU24.js +0 -2
  197. package/dist/browser/chunks/chunk-4SMRCU24.js.map +0 -7
  198. package/dist/kit/chart-border.d.ts +0 -18
  199. package/dist/kit/chart-border.d.ts.map +0 -1
  200. package/dist/kit/chart-border.js +0 -23
  201. package/dist/kit/chart-border.js.map +0 -1
  202. package/dist/line-chart/horizontal-axis.d.ts.map +0 -1
  203. package/dist/line-chart/horizontal-axis.js.map +0 -1
  204. package/dist/pie-chart/pie-legend.d.ts.map +0 -1
  205. package/dist/pie-chart/pie-legend.js.map +0 -1
  206. package/src/kit/chart-border.ts +0 -36
  207. package/src/line-chart/horizontal-axis.ts +0 -122
@@ -1,7 +0,0 @@
1
- {
2
- "version": 3,
3
- "sources": ["../../../src/kit/shared.ts", "../../../src/kit/cartesian.ts", "../../../src/kit/vertical-axis.ts", "../../../src/kit/entries.ts", "../../../src/kit/motion.ts", "../../../src/kit/chart-border.ts", "../../../src/kit/paints.ts", "../../../src/kit/chart-canvas.ts", "../../../src/kit/chart-legend.ts", "../../../src/engine.ts"],
4
- "sourcesContent": ["/**\n * What every chart shares: series, axis scaling and formatting, and the theme\n * leaves each chart's theme is assembled from. No `Node` imports, so a host's\n * inspector mappings can build a partial theme without the components.\n *\n * A mapper merges partial input onto a `previous` resolved value (idempotent). A\n * tween interpolates two resolved values leaf by leaf, but categorical fields\n * (`fontFamily`, `textAlign`) and any field `undefined` on either side step at\n * the midpoint: defaulting the missing side to 0 would animate a font weight\n * down to nothing on the way to \"unset\".\n */\n\nimport {\n fillOps,\n lerpNumber,\n shadowOps,\n strokeOps,\n insetsOps,\n textOps,\n type DataRecord,\n type Fill,\n type FillResolved,\n type Insets,\n type InsetsResolved,\n type Shadow,\n type ShadowResolved,\n type Stroke,\n type StrokeResolved,\n type TextStyle,\n} from \"@motionscript/sdk\"\n\n/** One series of a chart: a column of the table, captioned and painted. */\nexport interface ChartSeries {\n /** Key into each data row for this series' value. */\n field: string\n label: string\n /** Overrides the theme palette's entry for this series' index, for its mark and legend swatch. */\n fill?: Fill\n /** Defaults to `true`. */\n enabled?: boolean\n}\n\n/** A `[min, max]` numeric range in data units. */\nexport type Range = [min: number, max: number]\n\n/** One axis's *data* domain, as opposed to {@link AxisConfig}, which is how it is styled. */\nexport interface AxisDomainConfig {\n /** Caption drawn alongside the axis; `\"\"` hides it. */\n label?: string\n /** Derived from the data bounds when omitted. */\n range?: Range\n /** Derived (five evenly spaced) when omitted. */\n ticks?: number[]\n /**\n * A `number-format` pattern such as `#,##0.00` or `$#,##0`. It lives here, not\n * in {@link AxisConfig}, because it says what the column holds and has to\n * survive a re-theme.\n */\n format?: string\n}\n\n/** An {@link AxisDomainConfig} with `range` and `ticks` worked out. */\nexport type ResolvedAxisDomain = AxisDomainConfig & { readonly range: Range; readonly ticks: number[] }\n\n/**\n * Merges partial input onto `previous`, so a later `.set({ yAxis: {...} })`\n * patches `label`/`range`/`ticks` independently. An unset `range`/`ticks` is the\n * auto-derive signal.\n */\nexport function resolveAxisDomain(\n domain: AxisDomainConfig | undefined,\n previous?: AxisDomainConfig\n): AxisDomainConfig {\n return {\n label: domain?.label ?? previous?.label ?? \"\",\n range: domain?.range ?? previous?.range,\n ticks: domain?.ticks ?? previous?.ticks,\n format: domain?.format ?? previous?.format,\n }\n}\n\n/**\n * Interpolates `range` and `ticks` numerically (ticks pairwise by index).\n * `label`, `format`, and either field when one side is auto, step at the\n * midpoint: there is no halfway between `$#,##0` and `0.0%`.\n */\nexport function lerpAxisDomain(\n from: AxisDomainConfig,\n to: AxisDomainConfig,\n t: number\n): AxisDomainConfig {\n return {\n label: t < 0.5 ? from.label : to.label,\n range: lerpOptionalRange(from.range, to.range, t),\n ticks: lerpOptionalTicks(from.ticks, to.ticks, t),\n format: t < 0.5 ? from.format : to.format,\n }\n}\n\nfunction lerpOptionalRange(\n from: Range | undefined,\n to: Range | undefined,\n t: number\n): Range | undefined {\n if (!from || !to) return t < 0.5 ? from : to\n return [lerpNumber(from[0], to[0], t), lerpNumber(from[1], to[1], t)]\n}\n\nfunction lerpOptionalTicks(\n from: number[] | undefined,\n to: number[] | undefined,\n t: number\n): number[] | undefined {\n if (!from || !to) return t < 0.5 ? from : to\n const n = Math.max(from.length, to.length)\n const out: number[] = []\n for (let i = 0; i < n; i++) {\n out.push(lerpNumber(from[i] ?? to[i], to[i] ?? from[i], t))\n }\n return out\n}\n\n/**\n * An axis domain part-way through a tween that leaves or reaches a `range` or\n * `ticks` left to the data: both ends as stored, and how far along. Only the\n * chart knows what an auto side draws as, so {@link settleAxisDomain} resolves\n * it there. Its own fields are the plain {@link lerpAxisDomain} of its ends, so\n * a mapper merging onto one still reads a domain.\n */\nexport interface AxisDomainBlend extends AxisDomainConfig {\n readonly blend: { readonly from: AxisDomainConfig; readonly to: AxisDomainConfig; readonly t: number }\n}\n\nfunction blendOf(domain: AxisDomainConfig): AxisDomainBlend[\"blend\"] | undefined {\n return (domain as Partial<AxisDomainBlend>).blend\n}\n\n/**\n * The axis entry tween behind `to({ yAxis: { range } })`. Between explicit\n * domains it is {@link lerpAxisDomain}, and a restated `range` without `ticks`\n * spreads ticks across it, keeping their count. When either end leaves `range`\n * or `ticks` to the data, the value between is an {@link AxisDomainBlend}, so a\n * rescale from an auto axis is continuous rather than a cut at the midpoint.\n */\nexport function lerpAxisEntry(from: AxisDomainConfig, to: AxisDomainConfig, t: number): AxisDomainConfig {\n // The mapper merged the request onto `from`, so a field it left unstated is `from`'s own, by identity.\n const rangeMoved = to.range !== from.range\n const target = rangeMoved && to.range && to.ticks && to.ticks === from.ticks\n ? { ...to, ticks: markerValues(to.range, Math.max(2, to.ticks.length) - 1) }\n : to\n const blended = blendOf(from) !== undefined\n const moved = blended || rangeMoved || target.ticks !== from.ticks\n const auto = blended || from.range === undefined || from.ticks === undefined || target.range === undefined || target.ticks === undefined\n if (!moved || !auto) return lerpAxisDomain(from, target, t)\n if (t === 0) return from\n if (t === 1) return target\n const blend: AxisDomainBlend = { ...lerpAxisDomain(from, target, t), blend: { from, to: target, t } }\n return blend\n}\n\n/** `domain` as drawn: `drawn` resolves a plain domain's auto `range` and `ticks`; a blend is the lerp of what its ends draw. */\nexport function settleAxisDomain(domain: AxisDomainConfig, drawn: (domain: AxisDomainConfig) => AxisDomainConfig): AxisDomainConfig {\n const blend = blendOf(domain)\n if (!blend) return drawn(domain)\n return lerpAxisDomain(settleAxisDomain(blend.from, drawn), settleAxisDomain(blend.to, drawn), blend.t)\n}\n\n/** The colour tokens the default themes are built from: a dark plot panel with warm-grey axis furniture. */\nexport const CHART_PALETTE = {\n plotFill: \"#15130e\",\n borderColor: \"#4a4036\",\n gridColor: \"#2c2820\",\n /** Axis markers, axis captions and legend labels. */\n markerColor: \"#8a7f70\",\n /** A spotlit region's dashed rules and wash. */\n regionColor: \"#d99a3a\",\n} as const\n\n/** The out-of-the-box series palette, cycled by series index. */\nexport const DEFAULT_SERIES_COLORS = [\n \"#d9603b\",\n \"#8194ad\",\n \"#e0a93b\",\n \"#5e9d6b\",\n \"#9ec85a\",\n] as const\n\n/** Opacity an un-spotlighted series fades to, mark and legend entry alike. */\nexport const SPOTLIGHT_DIM = 0.2\n\n/**\n * Reads a numeric field off a row. A string column plots as 0, so a quoted or\n * unit-suffixed column needs the CSV parser's numeric coercion first.\n */\nexport function num(row: DataRecord, field: string | undefined): number {\n if (field === undefined) return 0\n const v = row[field]\n // A `NaN` or infinite cell is no more a measurement than a missing one: read\n // as 0, it cannot poison the scale and turn every point into `NaN`.\n return typeof v === \"number\" && Number.isFinite(v) ? v : 0\n}\n\n/** The counterpart to {@link num} for the columns a chart names things by; a missing cell reads as empty, not `\"undefined\"`. */\nexport function text(row: DataRecord, field: string | undefined): string {\n if (field === undefined || field === \"\") return \"\"\n const v = row[field]\n return v === undefined || v === null ? \"\" : String(v)\n}\n\n/**\n * Every numeric column of `data` in header order, skipping `exclude`. A column\n * is numeric only if every non-empty cell is a number, so a stray text cell\n * drops the column rather than plotting zeros.\n */\nexport function numericFields(\n data: DataRecord[],\n exclude: string[] = []\n): string[] {\n if (data.length === 0) return []\n const skip = new Set(exclude)\n const seen = new Set<string>()\n const order: string[] = []\n for (const row of data)\n for (const key of Object.keys(row))\n if (!skip.has(key) && !seen.has(key)) {\n seen.add(key)\n order.push(key)\n }\n\n return order.filter((key) => {\n let sawValue = false\n for (const row of data) {\n const v = row[key]\n if (v === undefined || v === \"\") continue\n if (typeof v !== \"number\") return false\n sawValue = true\n }\n return sawValue\n })\n}\n\n/** One axis's (x or y) style vocabulary. */\nexport interface AxisConfig {\n /** Style of each marker along the axis. */\n labelStyle: TextStyle\n titleStyle: TextStyle\n /** This axis's grid lines: weight and fill honoured, dash/cap/join ignored (they are filled rects). */\n lineStyle: Stroke\n /** Gap between the plot and the marker row; only the side facing the plot is read (`.top` horizontal, `.right` vertical). */\n tickPadding: Insets\n /** Gap between the marker row and the caption, read the same side. */\n titlePadding: Insets\n}\n\n/** A legend's per-series colour swatch. */\nexport interface LegendMarkerConfig {\n width: number\n height: number\n borderRadius: number\n stroke: Stroke\n shadow: Shadow\n}\n\nexport interface LegendConfig {\n padding: Insets\n /** Only the swatch carries the series colour. */\n textStyle: TextStyle\n itemGap: number\n markerStyle: LegendMarkerConfig\n}\n\n/** The plot panel a cartesian chart draws its marks over. */\nexport interface PlotAreaConfig {\n stroke: Stroke\n fill: Fill\n shadow: Shadow\n}\n\nconst AXIS_LABEL_STYLE: TextStyle = {\n fontSize: 24,\n fontWeight: 700,\n textAlign: \"center\",\n fill: CHART_PALETTE.markerColor,\n}\nconst AXIS_TITLE_STYLE: TextStyle = {\n fontSize: 30,\n fontWeight: 600,\n textAlign: \"center\",\n fill: CHART_PALETTE.markerColor,\n}\nconst AXIS_LINE_STYLE: Stroke = { weight: 2, fill: CHART_PALETTE.gridColor }\n\nexport const DEFAULT_X_AXIS: AxisConfig = {\n labelStyle: AXIS_LABEL_STYLE,\n titleStyle: AXIS_TITLE_STYLE,\n lineStyle: AXIS_LINE_STYLE,\n tickPadding: 20,\n titlePadding: 4,\n}\n\nexport const DEFAULT_Y_AXIS: AxisConfig = {\n labelStyle: { ...AXIS_LABEL_STYLE, fontWeight: 500, textAlign: \"right\" },\n titleStyle: AXIS_TITLE_STYLE,\n lineStyle: AXIS_LINE_STYLE,\n tickPadding: 40,\n titlePadding: 24,\n}\n\n/** Unpainted but framed: a chart reads against the stage rather than punching a panel into it. */\nexport const DEFAULT_PLOT_AREA: PlotAreaConfig = {\n fill: [],\n stroke: { weight: 6, fill: CHART_PALETTE.borderColor },\n shadow: [],\n}\n\nexport const DEFAULT_LEGEND: LegendConfig = {\n padding: 0,\n textStyle: {\n fontSize: 30,\n fontWeight: 600,\n textAlign: \"left\",\n fill: CHART_PALETTE.markerColor,\n },\n itemGap: 44,\n markerStyle: {\n width: 60,\n height: 24,\n borderRadius: 6,\n stroke: [],\n shadow: [],\n },\n}\n\n/** {@link DEFAULT_SERIES_COLORS} as 4px strokes. */\nexport const DEFAULT_SERIES_STROKES: Stroke[] = DEFAULT_SERIES_COLORS.map(\n (fill) => ({ weight: 4, fill })\n)\n\n/** {@link DEFAULT_SERIES_COLORS} as solid fills. */\nexport const DEFAULT_SERIES_FILLS: Fill[] = DEFAULT_SERIES_COLORS.map(\n (fill) => fill\n)\n\nexport function resolveAxisConfig(\n axis: Partial<AxisConfig> | undefined,\n previous: AxisConfig\n): AxisConfig {\n return {\n labelStyle: textOps.resolveStyle(axis?.labelStyle, previous.labelStyle),\n titleStyle: textOps.resolveStyle(axis?.titleStyle, previous.titleStyle),\n lineStyle: strokeOps.resolve(axis?.lineStyle ?? previous.lineStyle),\n tickPadding: insetsOps.resolve(\n axis?.tickPadding ?? previous.tickPadding,\n previous.tickPadding as InsetsResolved\n ),\n titlePadding: insetsOps.resolve(\n axis?.titlePadding ?? previous.titlePadding,\n previous.titlePadding as InsetsResolved\n ),\n }\n}\n\nexport function lerpAxisConfig(\n from: AxisConfig,\n to: AxisConfig,\n t: number\n): AxisConfig {\n return {\n labelStyle: textOps.lerpStyle(from.labelStyle, to.labelStyle, t),\n titleStyle: textOps.lerpStyle(from.titleStyle, to.titleStyle, t),\n lineStyle: strokeOps.lerp(\n from.lineStyle as StrokeResolved[],\n to.lineStyle as StrokeResolved[],\n t\n ),\n tickPadding: insetsOps.lerp(\n from.tickPadding as InsetsResolved,\n to.tickPadding as InsetsResolved,\n t\n ),\n titlePadding: insetsOps.lerp(\n from.titlePadding as InsetsResolved,\n to.titlePadding as InsetsResolved,\n t\n ),\n }\n}\n\nexport function resolvePlotArea(\n plotArea: Partial<PlotAreaConfig> | undefined,\n previous: PlotAreaConfig\n): PlotAreaConfig {\n return {\n fill: fillOps.resolve(plotArea?.fill ?? previous.fill),\n stroke: strokeOps.resolve(plotArea?.stroke ?? previous.stroke),\n shadow: shadowOps.resolve(plotArea?.shadow ?? previous.shadow),\n }\n}\n\nexport function lerpPlotArea(\n from: PlotAreaConfig,\n to: PlotAreaConfig,\n t: number\n): PlotAreaConfig {\n return {\n fill: fillOps.lerp(\n from.fill as FillResolved[],\n to.fill as FillResolved[],\n t\n ),\n stroke: strokeOps.lerp(\n from.stroke as StrokeResolved[],\n to.stroke as StrokeResolved[],\n t\n ),\n shadow: shadowOps.lerp(\n from.shadow as ShadowResolved[],\n to.shadow as ShadowResolved[],\n t\n ),\n }\n}\n\nfunction resolveLegendMarkerConfig(\n marker: Partial<LegendMarkerConfig> | undefined,\n previous: LegendMarkerConfig\n): LegendMarkerConfig {\n return {\n width: marker?.width ?? previous.width,\n height: marker?.height ?? previous.height,\n borderRadius: marker?.borderRadius ?? previous.borderRadius,\n stroke: strokeOps.resolve(marker?.stroke ?? previous.stroke),\n shadow: shadowOps.resolve(marker?.shadow ?? previous.shadow),\n }\n}\n\nfunction lerpLegendMarkerConfig(\n from: LegendMarkerConfig,\n to: LegendMarkerConfig,\n t: number\n): LegendMarkerConfig {\n return {\n width: lerpNumber(from.width, to.width, t),\n height: lerpNumber(from.height, to.height, t),\n borderRadius: lerpNumber(from.borderRadius, to.borderRadius, t),\n stroke: strokeOps.lerp(\n from.stroke as StrokeResolved[],\n to.stroke as StrokeResolved[],\n t\n ),\n shadow: shadowOps.lerp(\n from.shadow as ShadowResolved[],\n to.shadow as ShadowResolved[],\n t\n ),\n }\n}\n\n/** A legend theme as the author may state it: every branch optional. */\nexport type LegendTheme = Partial<Omit<LegendConfig, \"markerStyle\">> & {\n markerStyle?: Partial<LegendMarkerConfig>\n}\n\nexport function resolveLegendConfig(\n legend: LegendTheme | undefined,\n previous: LegendConfig\n): LegendConfig {\n return {\n padding: insetsOps.resolve(\n legend?.padding ?? previous.padding,\n previous.padding as InsetsResolved\n ),\n textStyle: textOps.resolveStyle(legend?.textStyle, previous.textStyle),\n itemGap: legend?.itemGap ?? previous.itemGap,\n markerStyle: resolveLegendMarkerConfig(\n legend?.markerStyle,\n previous.markerStyle\n ),\n }\n}\n\nexport function lerpLegendConfig(\n from: LegendConfig,\n to: LegendConfig,\n t: number\n): LegendConfig {\n return {\n padding: insetsOps.lerp(\n from.padding as InsetsResolved,\n to.padding as InsetsResolved,\n t\n ),\n textStyle: textOps.lerpStyle(from.textStyle, to.textStyle, t),\n itemGap: lerpNumber(from.itemGap, to.itemGap, t),\n markerStyle: lerpLegendMarkerConfig(from.markerStyle, to.markerStyle, t),\n }\n}\n\n/** A palette override replaces the previous palette outright. */\nexport function resolveSeriesStrokes(\n styles: Stroke[] | undefined,\n previous: Stroke[]\n): Stroke[] {\n return (styles ?? previous).map((s) => strokeOps.resolve(s))\n}\n\n/** Pairwise by index; a palette that grows/shrinks holds the longer side's tail. */\nexport function lerpSeriesStrokes(\n from: Stroke[],\n to: Stroke[],\n t: number\n): Stroke[] {\n const n = Math.max(from.length, to.length)\n const out: Stroke[] = []\n for (let i = 0; i < n; i++) {\n const a = (from[i] ?? to[i]) as StrokeResolved[]\n const b = (to[i] ?? from[i]) as StrokeResolved[]\n out.push(strokeOps.lerp(a, b, t))\n }\n return out\n}\n\n/** The fill-palette twin of {@link resolveSeriesStrokes}, for filled marks. */\nexport function resolveSeriesFills(\n fills: Fill[] | undefined,\n previous: Fill[]\n): Fill[] {\n return (fills ?? previous).map((f) => fillOps.resolve(f))\n}\n\n/** The fill-palette twin of {@link lerpSeriesStrokes}. */\nexport function lerpSeriesFills(from: Fill[], to: Fill[], t: number): Fill[] {\n const n = Math.max(from.length, to.length)\n const out: Fill[] = []\n for (let i = 0; i < n; i++) {\n const a = (from[i] ?? to[i]) as FillResolved[]\n const b = (to[i] ?? from[i]) as FillResolved[]\n out.push(fillOps.lerp(a, b, t))\n }\n return out\n}\n\n/**\n * The stroke for series `index`: the palette's entry at `index % palette.length`,\n * with the series' own `fill`, if set, replacing just the topmost layer's colour.\n */\nexport function resolveSeriesStroke(\n palette: Stroke[],\n series: ChartSeries,\n index: number\n): Stroke {\n const entry: Stroke =\n palette.length > 0\n ? palette[index % palette.length]\n : { weight: 4, fill: \"white\" }\n if (series.fill == null) return entry\n const layers = strokeOps.resolve(entry)\n if (layers.length === 0) return { weight: 4, fill: series.fill }\n const next = [...layers]\n next[next.length - 1] = {\n ...next[next.length - 1],\n fill: fillOps.resolve(series.fill),\n }\n return next\n}\n\n/** The colour {@link resolveSeriesStroke} draws series `index` in, for a legend swatch. */\nexport function resolveSeriesFill(\n palette: Stroke[],\n series: ChartSeries,\n index: number\n): Fill {\n const layers = strokeOps.resolve(resolveSeriesStroke(palette, series, index))\n return layers[layers.length - 1]?.fill ?? \"white\"\n}\n\n/**\n * Format a marker value: integers plain, otherwise one decimal, or as many as\n * the tick `step` needs to tell neighbours apart (a unit axis ticked every 0.05\n * gets two, not `0.1 0.1 0.2 0.2 0.3`). Trailing zeros are dropped.\n */\nexport function formatMarker(value: number, step?: number): string {\n if (Number.isInteger(value)) return String(value)\n const decimals = Math.max(1, step === undefined ? 1 : decimalsFor(step))\n return value.toFixed(decimals).replace(/(\\.\\d*?)0+$/, \"$1\").replace(/\\.$/, \"\")\n}\n\n/** Decimal places needed to write `step` exactly, capped at six. */\nfunction decimalsFor(step: number): number {\n if (!(step > 0) || !Number.isFinite(step)) return 1\n for (let d = 0; d <= 6; d++) {\n const scaled = step * 10 ** d\n if (Math.abs(scaled - Math.round(scaled)) < 1e-6 * Math.max(1, scaled)) return d\n }\n // An irrational-looking step (a third): as many places as separate the ticks.\n return Math.min(6, Math.max(1, Math.ceil(-Math.log10(step)) + 1))\n}\n\n/** The gap between neighbouring tick values, or `undefined` for fewer than two distinct ones. */\nexport function markerStep(markers: readonly number[]): number | undefined {\n const sorted = [...markers].filter(Number.isFinite).sort((a, b) => a - b)\n let step: number | undefined\n for (let i = 1; i < sorted.length; i++) {\n const gap = sorted[i] - sorted[i - 1]\n if (gap > 1e-12 && (step === undefined || gap < step)) step = gap\n }\n return step\n}\n\n/** Format a fraction in `[0, 1]` as a percentage: integers plain, else one decimal. */\nexport function formatPercent(fraction: number): string {\n const pct = fraction * 100\n if (Number.isInteger(pct)) return `${pct}%`\n return `${pct.toFixed(1).replace(/\\.0$/, \"\")}%`\n}\n\n/** `markerCount` evenly-spaced tick values across `[min, max]`, ends inclusive. */\nexport function markerValues([min, max]: Range, markerCount: number): number[] {\n const n = Math.max(2, Math.round(markerCount))\n return Array.from({ length: n + 1 }, (_, i) => min + ((max - min) / n) * i)\n}\n", "import { Rect, type ChildView, type Node2D, type Size2D } from \"@motionscript/sdk\"\n\nimport { VerticalAxis } from \"./vertical-axis\"\n\n/**\n * Headroom above the plot, in px. Real padding on the composition, so the top\n * marker, centred on the top grid line, does not draw its upper half above the\n * chart's own box.\n */\nconst TOP_HEADROOM = 24\n\ninterface CartesianParts {\n readonly axis: Node2D\n /** The box the grid and the marks share. */\n readonly plot: Node2D\n /** An invisible twin of the value axis, reserving its gutter under the plot. */\n readonly gutter: Node2D\n /** What sits under the plot, top to bottom: the other axis, then the legend. */\n readonly below: readonly Node2D[]\n}\n\n/** The frame the line and bar charts share: the value axis beside the plot, and under them the gutter, so the rows below start at the plot's left edge. */\nexport function cartesianFrame(parts: CartesianParts): Node2D {\n return new Rect({\n flow: \"vertical\",\n width: \"fill\",\n height: \"fill\",\n padding: { top: TOP_HEADROOM },\n children: [\n new Rect({ flow: \"horizontal\", height: \"fill\", width: \"fill\", children: [parts.axis, parts.plot] }),\n new Rect({\n flow: \"horizontal\",\n width: \"fill\",\n children: [parts.gutter, new Rect({ flow: \"vertical\", width: \"fill\", gap: 20, children: [...parts.below] })],\n }),\n ],\n }) as unknown as Node2D\n}\n\ninterface CartesianViews {\n readonly axis: ChildView\n /** The plot panel's own children: grid, marks, border. */\n readonly plot: readonly ChildView[]\n readonly below: readonly ChildView[]\n}\n\n/** The last child shaped as {@link cartesianFrame} builds it: the chart builds it after the children it was given and a document adds its own later, so it is found by shape. */\nexport function cartesianViews(children: readonly ChildView[]): CartesianViews | null {\n for (let i = children.length - 1; i >= 0; i--) {\n const frame = children[i]\n if (!Rect.is(frame)) continue\n const [top, bottom] = frame.children\n const axis = top?.children[0]\n const plot = top?.children[1]\n const below = bottom?.children[1]\n if (!axis || !VerticalAxis.is(axis) || !plot || !below) continue\n return { axis, plot: plot.children, below: below.children }\n }\n return null\n}\n\n/** A part's laid-out size; zero before it is built or laid out. */\nexport function laidOutSize(node: Node2D | undefined): Size2D {\n const bounds = node?.layoutBounds\n return { width: bounds?.width ?? 0, height: bounds?.height ?? 0 }\n}\n", "import {\n Rect,\n RotatedBox,\n Text,\n Types,\n component2d,\n insetsOps,\n textOps,\n type NodeOf,\n // Named so this component's emitted type reaches `Node2D` and its props through the sdk, not core.\n type Node2D,\n type Node2DProps as _Node2DProps,\n} from \"@motionscript/sdk\"\nimport { enterBudget } from \"@motionscript/sdk/component\"\n\nimport { asParts, fresh } from \"./entries\"\nimport { armed, arrival, arrivalOf, arrivalsEntry, beats, frameEase, type Arrival } from \"./motion\"\nimport {\n DEFAULT_Y_AXIS,\n formatMarker,\n type AxisConfig,\n type Range,\n} from \"./shared\"\n\nconst SLIDE = 24\n\n/** What a marker's caption reads: the one listed for its value, else its bare reading. */\nexport function markerCaption(s: { readonly markers: readonly number[]; readonly captions: readonly string[] }, value: number): string {\n const index = s.markers.indexOf(value)\n return (index >= 0 ? s.captions[index] : undefined) ?? formatMarker(value)\n}\n\n/**\n * The numeric vertical axis the cartesian charts share: a column of {@link Text}\n * markers, highest at the top, each centred on its value's fraction across\n * `range`. Caption and position are bound, so a rescale tweens live; only the\n * marker count is fixed at construction. The resting state is landed.\n */\nexport const VerticalAxis = component2d({\n key: \"verticalAxis\",\n state: {\n range: fresh<Range>(() => [0, 1]),\n /** Tick values in data units, each placed by its fraction across `range`; need not be even or include the ends. */\n markers: fresh<number[]>(() => []),\n /** One caption per marker in its order; a missing one reads as the bare numeric value. */\n captions: fresh<string[]>(() => []),\n axis: Types.custom<AxisConfig>(DEFAULT_Y_AXIS),\n /** Rotated caption in the gutter left of the markers; empty builds no caption node and reserves no gutter. */\n label: \"\",\n arrivals: arrivalsEntry(),\n },\n // A node made of markers would otherwise hug them.\n defaults: { width: \"fill\", height: \"fill\" },\n children: (state) => {\n const tickPad = insetsOps.resolve(state.axis.tickPadding).right\n const titlePad = insetsOps.resolve(state.axis.titlePadding).right\n\n const row: Node2D[] = []\n // The row's parent is the axis, whose box the markers are placed in.\n const box = () => (row[0]?.parent as Node2D | null | undefined)?.layoutBounds ?? { width: 0, height: 0 }\n const sorted = () => [...state.markers].sort((a, b) => b - a)\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 // A slot with no value (the live list is shorter than the column built) renders empty, not its neighbour.\n const markers = state.markers.map((_, i) => {\n const marker: Node2D = new Text({\n ...textOps.styleProps(state.axis.labelStyle),\n text: () => {\n const value = sorted()[i]\n return value === undefined ? \"\" : markerCaption(state, value)\n },\n y: () => {\n // Node2D space is y-up, so the fraction runs from the bottom.\n const height = box().height\n const centred = (fracAt(sorted()[i]) - 0.5) * height\n // Held inside the top edge for a theme whose markers are taller than the headroom; only the top, since the chart's own axis and legend lie below.\n const limit = height / 2 - marker.layoutBounds.height / 2\n return Math.min(centred, limit)\n },\n opacity: () => arrivalOf(state.arrivals, i).opacity,\n x: () => arrivalOf(state.arrivals, i).shift,\n })\n return marker\n })\n\n const children: Node2D[] = []\n if (state.label !== \"\") {\n // Node2D space is y-up and rotation is clockwise, so -90° reads bottom-to-top.\n children.push(\n new RotatedBox({\n angle: -90,\n width: \"hug\",\n height: \"hug\",\n children: new Text({\n ...textOps.styleProps(state.axis.titleStyle),\n text: state.label,\n opacity: () => arrivalOf(state.arrivals, \"label\").opacity,\n x: () => arrivalOf(state.arrivals, \"label\").shift,\n }),\n })\n )\n }\n children.push(new Rect({ height: \"fill\", width: \"hug\", padding: { right: tickPad }, children: markers }))\n row.push(new Rect({ flow: \"horizontal\", gap: titlePad, children }))\n return asParts(row)\n },\n commands: {\n /**\n * Stagger markers in bottom to top, then the caption. The duration is the\n * whole entrance ({@link enterBudget}). `stagger` is seconds between markers\n * (derived when omitted); `slide` is the starting rightward offset in px.\n */\n enter: {\n args: {\n stagger: Types.custom<number | undefined>(undefined),\n slide: Types.number(SLIDE),\n },\n run: (timeline, state) => {\n const { stagger, slide } = timeline.args\n const count = state.markers.length\n const captioned = state.label !== \"\"\n const from: Arrival = { opacity: 0, shift: slide }\n const keys = [...state.markers.keys(), ...(captioned ? [\"label\"] : [])]\n const arm = timeline.animate(() => ({ arrivals: armed(keys, from) }))\n if (count === 0) return arm\n const { step, per, caption } = enterBudget(timeline.duration, count, captioned, stagger)\n const ease = frameEase(timeline)\n // The bottom marker leads, so walk the top-to-bottom column in reverse.\n const markers = state.markers.map((_, i) => ({ at: (count - 1 - 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 VerticalAxis = NodeOf<typeof VerticalAxis>\n", "import { Types, type Element, type EntryOptions, type Node2D, type Type } from \"@motionscript/sdk\"\n\n/**\n * An entry made fresh for every node: each node gets its own array or box\n * rather than one shared literal, and a host is told no default for it.\n */\nexport function fresh<T, In = T>(make: () => T, options?: { readonly resolve?: (value: In) => T; readonly kind?: string }): Type<In, T> {\n // A function default is a factory: the component calls it once per node.\n return Types.custom<In, T>(make as unknown as In, options)\n}\n\n/**\n * Nodes a `children` builder made with `new`, as the elements it returns. A\n * part built that way can be read in a binding — its own box, or its parent's,\n * which is the component it was built for — where a call would hand back only\n * the element.\n */\nexport function asParts(nodes: readonly Node2D[]): readonly Element[] {\n return nodes as unknown as readonly Element[]\n}\n\n/** The argument every per-series command takes: an index into `series`, offered by name. */\nexport const SERIES_ARG = Types.custom<number, number, EntryOptions & { readonly min: number; readonly step: number }>(0, { kind: \"series\", min: 0, step: 1 })\n", "import { Types, easeOut, type EasingFunction, type Piece, type Timeline } from \"@motionscript/sdk\"\n\nconst identity: EasingFunction = (t) => t\n\n/** Any component's timeline: these helpers only build pieces, which every timeline builds alike. */\nexport type AnyTimeline = Timeline<any, any>\n\n/** How far a legend starts below its slot when `enter` brings it in, in px. */\nexport const LEGEND_SLIDE = 20\n\n/** Marker count when an axis states no ticks. */\nexport const DEFAULT_MARKERS = 5\n\n/** How a cartesian `enter` splits its duration: axes arriving, marks drawing, legend coming up. Sums to 1. */\nexport const ENTER_SHARE = { axes: 0.35, marks: 0.5, legend: 0.15 } as const\n\n/**\n * The ease a part's own frames apply to `t`: none when its command was given\n * one, which already eases every frame the command builds, and otherwise the\n * ease-out every chart command defaults to.\n */\nexport function frameEase(timeline: { readonly easing: EasingFunction | undefined }): EasingFunction {\n return timeline.easing ? identity : easeOut()\n}\n\n/** A piece of a command placed at its own time: from `at` seconds, for `duration` seconds. */\nexport interface Beat {\n readonly at: number\n readonly duration: number\n readonly piece: Piece\n}\n\n/**\n * `beats` at their own offsets over the command, each eased on its own and held\n * at its last frame once it is done. A beat ahead of the playhead writes nothing,\n * so whatever stands before it is written by a piece ahead of these. Beats that\n * run past the command are played faster to end with it.\n */\nexport function beats(timeline: AnyTimeline, parts: readonly Beat[]): Piece {\n const total = timeline.duration\n const natural = parts.reduce((end, part) => Math.max(end, part.at + part.duration), 0)\n const k = natural > total && natural > 0 ? total / natural : 1\n return timeline.together(\n parts.map(({ at, duration, piece }) => {\n const start = at * k\n const length = duration * k\n return timeline.sequence([timeline.wait(start), piece, timeline.wait(Math.max(0, total - start - length))])\n })\n )\n}\n\n/** How far one piece of a staggered entrance has come: its opacity, and how far it still sits off its place. */\nexport interface Arrival {\n readonly opacity: number\n readonly shift: number\n}\n\n/** Each piece's arrival, by key. An unlisted piece has landed. */\nexport type Arrivals = Readonly<Record<string, Arrival>>\n\nconst LANDED: Arrival = { opacity: 1, shift: 0 }\n\n/**\n * A part's private record of its pieces' arrivals. A write merges into it, so\n * beats placed apart each write their own piece and leave the others as the\n * frame left them.\n */\nexport function arrivalsEntry() {\n return Types.custom<Arrivals>({}, { private: true, resolve: (next: Arrivals, previous?: Arrivals) => ({ ...previous, ...next }) })\n}\n\nexport function arrivalOf(arrivals: Arrivals, key: string | number): Arrival {\n return arrivals[key] ?? LANDED\n}\n\n/** Every piece in `keys` armed at `from`: the first frame of their entrance. */\nexport function armed(keys: readonly (string | number)[], from: Arrival): Arrivals {\n const record: Record<string, Arrival> = {}\n for (const key of keys) record[key] = from\n return record\n}\n\n/**\n * A piece arriving from `from` over its beat: a part armed at `from` tweened to\n * `{ opacity: 1, [axis]: 0 }`, eased by `ease`.\n */\nexport function arrival(timeline: AnyTimeline, key: string | number, from: Arrival, ease: EasingFunction): Piece {\n return timeline.animate((t) => {\n const e = ease(t)\n return {\n arrivals: {\n [key]: {\n opacity: from.opacity + (LANDED.opacity - from.opacity) * e,\n shift: from.shift + (LANDED.shift - from.shift) * e,\n },\n },\n }\n })\n}\n", "import {\n Graphics2D,\n Types,\n component2d,\n strokeOps,\n type NodeOf,\n // Named so this component's emitted type reaches `Node2D` and its props through the sdk, not core.\n type Node2D as _Node2D,\n type Node2DProps as _Node2DProps,\n type Stroke,\n type StrokeResolved,\n} from \"@motionscript/sdk\"\n\nimport { loadPaints } from \"./paints\"\nimport { DEFAULT_PLOT_AREA } from \"./shared\"\n\n/**\n * The frame around a cartesian plot: an empty rect with an inside stroke. Split\n * from {@link ChartCanvas} so it is placed after the marks and frames the plot\n * over them, tucking a line or column running to the edge under the border.\n */\nexport const ChartBorder = component2d({\n key: \"chartBorder\",\n state: {\n /** The stroke resolver's default `align` is `'inside'`, so the whole weight sits within the box unless the theme overrides it. */\n stroke: Types.custom<Stroke, StrokeResolved[]>(DEFAULT_PLOT_AREA.stroke, { resolve: strokeOps.resolve, lerp: strokeOps.lerp }),\n },\n load: (loader, state) => loadPaints(loader, { strokes: [state.stroke] }),\n render: (ctx, state) => {\n const { width, height } = ctx.size\n if (width <= 0 || height <= 0) return\n ctx.draw(new Graphics2D().rect({ x: 0, y: 0, width, height }).stroke(state.stroke))\n },\n})\n\nexport type ChartBorder = NodeOf<typeof ChartBorder>\n", "import type { FillResolved, Loader, ShadowResolved, StrokeResolved } from \"@motionscript/sdk\"\n\n/** Paints a chart part holds in entries of its own, which no paint entry loads for it. */\nexport interface PartPaints {\n readonly fills?: readonly (readonly FillResolved[])[]\n readonly strokes?: readonly (readonly StrokeResolved[])[]\n readonly shadows?: readonly (readonly ShadowResolved[])[]\n}\n\n/** Declare `paints` from a component's `load`. */\nexport function loadPaints(loader: Loader, paints: PartPaints): void {\n for (const fill of paints.fills ?? []) loader.fill(fill)\n for (const strokes of paints.strokes ?? []) for (const stroke of strokes) loader.fill(stroke.fill)\n for (const shadows of paints.shadows ?? []) for (const shadow of shadows) loader.fill(shadow.fill)\n}\n", "import {\n Graphics2D,\n Types,\n component2d,\n fillOps,\n shadowOps,\n strokeOps,\n type Fill,\n type FillResolved,\n type NodeOf,\n // Named so this component's emitted type reaches `Node2D` and its props through the sdk, not core.\n type Node2D as _Node2D,\n type Node2DProps as _Node2DProps,\n type Shadow,\n type ShadowResolved,\n type Stroke,\n type StrokeResolved,\n} from \"@motionscript/sdk\"\n\nimport { fresh } from \"./entries\"\nimport { loadPaints } from \"./paints\"\nimport {\n DEFAULT_PLOT_AREA,\n DEFAULT_X_AXIS,\n DEFAULT_Y_AXIS,\n type Range,\n} from \"./shared\"\n\nconst strokeEntry = (initial: Stroke) =>\n Types.custom<Stroke, StrokeResolved[]>(initial, { resolve: strokeOps.resolve, lerp: strokeOps.lerp })\n\n/**\n * The plot backdrop: a filled panel and a grid, sized from its box. The frame is\n * a separate {@link ChartBorder} drawn over the marks. Grid lines are placed from\n * the axis markers' data-unit positions mapped through the extents, so each lands\n * under its marker however the markers are spaced.\n */\nexport const ChartCanvas = component2d({\n key: \"chartCanvas\",\n state: {\n fill: Types.custom<Fill, FillResolved[]>(DEFAULT_PLOT_AREA.fill, { resolve: fillOps.resolve, lerp: fillOps.lerp }),\n shadow: Types.custom<Shadow, ShadowResolved[]>(DEFAULT_PLOT_AREA.shadow, { resolve: shadowOps.resolve, lerp: shadowOps.lerp }),\n xGridStroke: strokeEntry(DEFAULT_X_AXIS.lineStyle),\n yGridStroke: strokeEntry(DEFAULT_Y_AXIS.lineStyle),\n /**\n * Data-unit positions of the vertical grid lines, one per horizontal marker.\n * Positions at or past an extent edge coincide with the border and are\n * skipped. Empty for a categorical axis, which has no numeric position to rule at.\n */\n xMarkers: fresh<number[]>(() => []),\n yMarkers: fresh<number[]>(() => []),\n /** `[min, max]` of each scale, mapping the markers into the panel. */\n xExtent: fresh<Range>(() => [0, 1]),\n yExtent: fresh<Range>(() => [0, 1]),\n },\n // The grid strokes sit past the conventional slots, so they are named here.\n load: (loader, state) =>\n loadPaints(loader, { fills: [state.fill], shadows: [state.shadow], strokes: [state.xGridStroke, state.yGridStroke] }),\n render: (ctx, state) => {\n const { width: W, height: H } = ctx.size\n if (W <= 0 || H <= 0) return\n\n ctx.draw(new Graphics2D().rect({ x: 0, y: 0, width: W, height: H }).shadow(state.shadow).fill(state.fill))\n\n const [xMin, xMax] = state.xExtent\n const [yMin, yMax] = state.yExtent\n // A zero-width extent maps to 0.\n const xFrac = (v: number) => (xMax <= xMin ? 0 : (v - xMin) / (xMax - xMin))\n const yFrac = (v: number) => (yMax <= yMin ? 0 : (v - yMin) / (yMax - yMin))\n // Markers on or past the edges would sit under the border.\n const interior = (f: number) => f > 1e-6 && f < 1 - 1e-6\n\n const xStroke = state.xGridStroke[0]\n if (xStroke) {\n const xGrid = new Graphics2D()\n for (const v of state.xMarkers) {\n const f = xFrac(v)\n if (!interior(f)) continue\n xGrid.rect({ x: -W / 2 + f * W, y: 0, width: xStroke.weight, height: H })\n }\n ctx.draw(xGrid.fill(xStroke.fill))\n }\n\n const yStroke = state.yGridStroke[0]\n if (yStroke) {\n const yGrid = new Graphics2D()\n for (const v of state.yMarkers) {\n const f = yFrac(v)\n if (!interior(f)) continue\n yGrid.rect({ x: 0, y: -H / 2 + f * H, width: W, height: yStroke.weight })\n }\n ctx.draw(yGrid.fill(yStroke.fill))\n }\n },\n})\n\nexport type ChartCanvas = NodeOf<typeof ChartCanvas>\n", "import {\n Flow,\n Paint,\n Rect,\n Shapes,\n Text,\n Types,\n component2d,\n textOps,\n type Fill,\n type NodeOf,\n // Named so the row's emitted type reaches the Rect surface it spreads through the sdk, not core.\n type Alignment as _Alignment,\n type CornerRadiusResolved as _CornerRadiusResolved,\n type CornerStyleResolved as _CornerStyleResolved,\n type FillResolved as _FillResolved,\n type FlowMode as _FlowMode,\n type FlowResolved as _FlowResolved,\n type GapSize as _GapSize,\n type Node2D as _Node2D,\n type Node2DProps as _Node2DProps,\n type RectCornerRadius as _RectCornerRadius,\n type RectCornerStyle as _RectCornerStyle,\n type Shadow as _Shadow,\n type ShadowResolved as _ShadowResolved,\n type Stroke as _Stroke,\n type StrokeResolved as _StrokeResolved,\n type Vector2 as _Vector2,\n} from \"@motionscript/sdk\"\n\nimport { fresh } from \"./entries\"\nimport { frameEase } from \"./motion\"\nimport {\n DEFAULT_LEGEND,\n SPOTLIGHT_DIM,\n type ChartSeries,\n type LegendConfig,\n} from \"./shared\"\n\nconst row = { ...Paint.state, ...Flow.state, ...Shapes.corners }\n\n/**\n * One legend entry, hugging its caption and swatch; `shown` scales that width\n * from nothing. The width is measured from the content at any reveal, so a frame\n * never depends on the entry once having been fully shown (`\"hug\"` is not a\n * number to scale until something measures it).\n */\nconst LegendEntry = component2d({\n key: \"legendEntry\",\n state: { ...row, shown: Types.number(1) },\n commands: { ...Paint.commands },\n measure: (measurer, state, children) => {\n const size = Flow.measure(measurer, state, children, Paint.inset(state))\n return state.shown >= 1 ? size : { ...size, width: state.shown * size.width }\n },\n layout: (box, state, children) => Flow.layout(box, state, children, Paint.inset(state)),\n render: (ctx, state) => Paint.draw(ctx, state, Shapes.rect(ctx.size, state)),\n})\n\n/** Written whole, or one entry at a time as `{ [index]: reveal }`, which leaves the others as the frame left them so two series can move at once. */\nfunction revealOf(value: readonly number[] | Readonly<Record<number, number>>, previous?: number[]): number[] {\n if (Array.isArray(value)) return value as number[]\n const next = [...(previous ?? [])]\n for (const [index, reveal] of Object.entries(value)) next[Number(index)] = reveal\n return next\n}\n\n/** A chart's legend: a horizontal row with one entry per series, each a caption and a colour swatch. This node is the row, so the parent places it. */\nexport const ChartLegend = component2d({\n key: \"chartLegend\",\n state: {\n ...row,\n series: fresh<ChartSeries[]>(() => []),\n /** Swatch colour by series index, resolved by the chart; a missing entry is white. */\n swatches: fresh<Fill[]>(() => []),\n legend: Types.custom<LegendConfig>(DEFAULT_LEGEND),\n /**\n * How far each entry is shown, `0`-`1`, driving its width, opacity and gap\n * together. Entries are never added or removed: \"is this node a child\" is not\n * a function of time, while collapsed-but-present is.\n */\n reveal: fresh<number[], number[] | Readonly<Record<number, number>>>(() => [], { resolve: revealOf }),\n },\n // The flow must be stated: a `Rect` with none lays children out `freeform`, stacking every entry on one spot.\n defaults: {\n flow: \"horizontal\",\n width: \"hug\",\n height: \"hug\",\n gap: (state) => state.legend.itemGap,\n padding: (state) => state.legend.padding,\n reveal: (state) => state.series.map((s) => ((s.enabled ?? true) ? 1 : 0)),\n },\n // Every entry stays a child, so one always comes back where it belongs.\n children: (state) => {\n const marker = state.legend.markerStyle\n return state.series.map((series, index) =>\n LegendEntry({\n flow: \"horizontal\",\n gap: 12,\n align: \"center\",\n width: \"hug\",\n height: \"hug\",\n // The width follows the reveal in `measure`, and the flanking gap closes with the entry.\n opacity: () => state.reveal[index] ?? 0,\n gapScale: () => state.reveal[index] ?? 0,\n shown: () => state.reveal[index] ?? 0,\n children: [\n Text({ ...textOps.styleProps(state.legend.textStyle), text: series.label }),\n Rect({\n width: marker.width,\n height: marker.height,\n cornerRadius: marker.borderRadius,\n fill: state.swatches[index] ?? \"white\",\n stroke: marker.stroke,\n shadow: marker.shadow,\n }),\n ],\n })\n )\n },\n commands: {\n ...Paint.commands,\n /** Grow series `index`'s entry back in at its position, the siblings sliding over. */\n showSeries: {\n args: { index: Types.number(0, { min: 0, step: 1 }) },\n // An index that is not a series takes its slot and moves nothing.\n run: (timeline, state) => (timeline.args.index in state.series\n ? timeline.animate(revealFrame(state, timeline.args.index, 1, frameEase(timeline)))\n : timeline.wait(timeline.duration)),\n },\n /** The mirror of `showSeries`. */\n hideSeries: {\n args: { index: Types.number(0, { min: 0, step: 1 }) },\n run: (timeline, state) => (timeline.args.index in state.series\n ? timeline.animate(revealFrame(state, timeline.args.index, 0, frameEase(timeline)))\n : timeline.wait(timeline.duration)),\n },\n /** Dim every entry but `index` to {@link SPOTLIGHT_DIM}, in place. A hidden series' entry is left as `hideSeries` left it. */\n spotlightSeries: {\n args: { index: Types.number(0, { min: 0, step: 1 }) },\n run: (timeline, state, children) =>\n timeline.together(\n children.flatMap((entry, i) =>\n (state.reveal[i] ?? 0) > 0 ? [entry.to({ opacity: i === timeline.args.index ? 1 : SPOTLIGHT_DIM })] : []\n )\n ),\n },\n },\n measure: (measurer, state, children) => Flow.measure(measurer, state, children, Paint.inset(state)),\n layout: (box, state, children) => Flow.layout(box, state, children, Paint.inset(state)),\n render: (ctx, state) => Paint.draw(ctx, state, Shapes.rect(ctx.size, state)),\n})\n\n/** One entry's reveal ramping to `target` from where the command finds it, so a hide after a show starts where the show left it. */\nfunction revealFrame(state: { readonly reveal: readonly number[] }, index: number, target: number, ease: (t: number) => number) {\n const from = state.reveal[index] ?? 0\n return (t: number) => ({ reveal: { [index]: from + (target - from) * ease(t) } })\n}\n\nexport type ChartLegend = NodeOf<typeof ChartLegend>\n", "/**\n * The chart kit: what the three charts share, and what a copied chart does not\n * copy. A chart finds its parts by component identity (`VerticalAxis.is`), so a\n * second copy of `VerticalAxis` would be a second component that the chart never\n * finds, with no error. Copies import the kit from `@motionscript/charts`.\n */\nexport * from \"./kit/shared\"\nexport * from \"./kit/cartesian\"\nexport * from \"./kit/chart-border\"\nexport * from \"./kit/chart-canvas\"\nexport * from \"./kit/chart-legend\"\nexport * from \"./kit/entries\"\nexport * from \"./kit/motion\"\nexport * from \"./kit/paints\"\nexport * from \"./kit/vertical-axis\"\nexport * from \"@motionscript/sdk/component\"\n"],
5
- "mappings": "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",
6
- "names": ["fillOps", "lerpNumber", "shadowOps", "strokeOps", "insetsOps", "textOps", "resolveAxisDomain", "domain", "previous", "lerpAxisDomain", "from", "to", "t", "lerpOptionalRange", "lerpOptionalTicks", "out", "i", "blendOf", "lerpAxisEntry", "rangeMoved", "target", "markerValues", "blended", "moved", "auto", "settleAxisDomain", "drawn", "blend", "CHART_PALETTE", "DEFAULT_SERIES_COLORS", "SPOTLIGHT_DIM", "num", "row", "field", "v", "text", "numericFields", "data", "exclude", "skip", "seen", "order", "key", "sawValue", "AXIS_LABEL_STYLE", "AXIS_TITLE_STYLE", "AXIS_LINE_STYLE", "DEFAULT_X_AXIS", "DEFAULT_Y_AXIS", "DEFAULT_PLOT_AREA", "DEFAULT_LEGEND", "DEFAULT_SERIES_STROKES", "fill", "DEFAULT_SERIES_FILLS", "resolveAxisConfig", "axis", "lerpAxisConfig", "resolvePlotArea", "plotArea", "lerpPlotArea", "resolveLegendMarkerConfig", "marker", "lerpLegendMarkerConfig", "resolveLegendConfig", "legend", "lerpLegendConfig", "resolveSeriesStrokes", "styles", "s", "lerpSeriesStrokes", "a", "b", "resolveSeriesFills", "fills", "f", "lerpSeriesFills", "resolveSeriesStroke", "palette", "series", "index", "entry", "layers", "next", "resolveSeriesFill", "formatMarker", "value", "step", "decimals", "decimalsFor", "d", "scaled", "markerStep", "markers", "sorted", "gap", "formatPercent", "fraction", "pct", "min", "max", "markerCount", "_", "Rect", "Rect", "RotatedBox", "Text", "Types", "component2d", "insetsOps", "textOps", "enterBudget", "Types", "fresh", "make", "options", "asParts", "nodes", "SERIES_ARG", "Types", "easeOut", "identity", "t", "LEGEND_SLIDE", "DEFAULT_MARKERS", "ENTER_SHARE", "frameEase", "timeline", "beats", "parts", "total", "natural", "end", "part", "k", "at", "duration", "piece", "start", "length", "LANDED", "arrivalsEntry", "next", "previous", "arrivalOf", "arrivals", "key", "armed", "keys", "from", "record", "arrival", "ease", "e", "SLIDE", "markerCaption", "s", "value", "index", "formatMarker", "VerticalAxis", "component2d", "fresh", "Types", "DEFAULT_Y_AXIS", "arrivalsEntry", "state", "tickPad", "insetsOps", "titlePad", "row", "box", "sorted", "a", "b", "fracAt", "min", "max", "markers", "_", "i", "marker", "Text", "textOps", "height", "centred", "limit", "arrivalOf", "children", "RotatedBox", "Rect", "timeline", "stagger", "slide", "count", "captioned", "from", "keys", "arm", "armed", "step", "per", "caption", "enterBudget", "ease", "frameEase", "arrival", "label", "beats", "TOP_HEADROOM", "cartesianFrame", "parts", "Rect", "cartesianViews", "children", "i", "frame", "top", "bottom", "axis", "plot", "below", "VerticalAxis", "laidOutSize", "node", "bounds", "Graphics2D", "Types", "component2d", "strokeOps", "loadPaints", "loader", "paints", "fill", "strokes", "stroke", "shadows", "shadow", "ChartBorder", "component2d", "Types", "DEFAULT_PLOT_AREA", "strokeOps", "loader", "state", "loadPaints", "ctx", "width", "height", "Graphics2D", "Graphics2D", "Types", "component2d", "fillOps", "shadowOps", "strokeOps", "strokeEntry", "initial", "Types", "strokeOps", "ChartCanvas", "component2d", "DEFAULT_PLOT_AREA", "fillOps", "shadowOps", "DEFAULT_X_AXIS", "DEFAULT_Y_AXIS", "fresh", "loader", "state", "loadPaints", "ctx", "W", "H", "Graphics2D", "xMin", "xMax", "yMin", "yMax", "xFrac", "v", "yFrac", "interior", "f", "xStroke", "xGrid", "yStroke", "yGrid", "Flow", "Paint", "Rect", "Shapes", "Text", "Types", "component2d", "textOps", "row", "Paint", "Flow", "Shapes", "LegendEntry", "component2d", "Types", "measurer", "state", "children", "size", "box", "ctx", "revealOf", "value", "previous", "next", "index", "reveal", "ChartLegend", "fresh", "DEFAULT_LEGEND", "s", "marker", "series", "Text", "textOps", "Rect", "timeline", "revealFrame", "frameEase", "entry", "SPOTLIGHT_DIM", "target", "ease", "from", "t"]
7
- }
@@ -1,18 +0,0 @@
1
- import { type NodeOf, type Node2D as _Node2D, type Node2DProps as _Node2DProps, type Stroke, type StrokeResolved } from "@motionscript/sdk";
2
- /**
3
- * The frame around a cartesian plot: an empty rect with an inside stroke. Split
4
- * from {@link ChartCanvas} so it is placed after the marks and frames the plot
5
- * over them, tucking a line or column running to the edge under the border.
6
- */
7
- export declare const ChartBorder: import("@motionscript/sdk").Component<"chartBorder", import("@motionscript/sdk").Merge<import("@motionscript/sdk").Box2DState, {
8
- /** The stroke resolver's default `align` is `'inside'`, so the whole weight sits within the box unless the theme overrides it. */
9
- readonly stroke: import("@motionscript/sdk").Type<Stroke, StrokeResolved[], false>;
10
- }>, {}, null, _Node2D<_Node2DProps>, import("@motionscript/sdk").CallProps<import("@motionscript/sdk").Merge<import("@motionscript/sdk").Box2DState, {
11
- /** The stroke resolver's default `align` is `'inside'`, so the whole weight sits within the box unless the theme overrides it. */
12
- readonly stroke: import("@motionscript/sdk").Type<Stroke, StrokeResolved[], false>;
13
- }>, null, import("@motionscript/sdk").BuiltNode<import("@motionscript/sdk").Merge<import("@motionscript/sdk").Box2DState, {
14
- /** The stroke resolver's default `align` is `'inside'`, so the whole weight sits within the box unless the theme overrides it. */
15
- readonly stroke: import("@motionscript/sdk").Type<Stroke, StrokeResolved[], false>;
16
- }>, {}, _Node2D<_Node2DProps>>>>;
17
- export type ChartBorder = NodeOf<typeof ChartBorder>;
18
- //# sourceMappingURL=chart-border.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"chart-border.d.ts","sourceRoot":"","sources":["../../src/kit/chart-border.ts"],"names":[],"mappings":"AAAA,OAAO,EAKL,KAAK,MAAM,EAEX,KAAK,MAAM,IAAI,OAAO,EACtB,KAAK,WAAW,IAAI,YAAY,EAChC,KAAK,MAAM,EACX,KAAK,cAAc,EACpB,MAAM,mBAAmB,CAAA;AAK1B;;;;GAIG;AACH,eAAO,MAAM,WAAW;IAGpB,kIAAkI;;;IAAlI,kIAAkI;;;IAAlI,kIAAkI;;gCASpI,CAAA;AAEF,MAAM,MAAM,WAAW,GAAG,MAAM,CAAC,OAAO,WAAW,CAAC,CAAA"}
@@ -1,23 +0,0 @@
1
- import { Graphics2D, Types, component2d, strokeOps, } from "@motionscript/sdk";
2
- import { loadPaints } from "./paints.js";
3
- import { DEFAULT_PLOT_AREA } from "./shared.js";
4
- /**
5
- * The frame around a cartesian plot: an empty rect with an inside stroke. Split
6
- * from {@link ChartCanvas} so it is placed after the marks and frames the plot
7
- * over them, tucking a line or column running to the edge under the border.
8
- */
9
- export const ChartBorder = component2d({
10
- key: "chartBorder",
11
- state: {
12
- /** The stroke resolver's default `align` is `'inside'`, so the whole weight sits within the box unless the theme overrides it. */
13
- stroke: Types.custom(DEFAULT_PLOT_AREA.stroke, { resolve: strokeOps.resolve, lerp: strokeOps.lerp }),
14
- },
15
- load: (loader, state) => loadPaints(loader, { strokes: [state.stroke] }),
16
- render: (ctx, state) => {
17
- const { width, height } = ctx.size;
18
- if (width <= 0 || height <= 0)
19
- return;
20
- ctx.draw(new Graphics2D().rect({ x: 0, y: 0, width, height }).stroke(state.stroke));
21
- },
22
- });
23
- //# sourceMappingURL=chart-border.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"chart-border.js","sourceRoot":"","sources":["../../src/kit/chart-border.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,UAAU,EACV,KAAK,EACL,WAAW,EACX,SAAS,GAOV,MAAM,mBAAmB,CAAA;AAE1B,OAAO,EAAE,UAAU,EAAE,MAAM,UAAU,CAAA;AACrC,OAAO,EAAE,iBAAiB,EAAE,MAAM,UAAU,CAAA;AAE5C;;;;GAIG;AACH,MAAM,CAAC,MAAM,WAAW,GAAG,WAAW,CAAC;IACrC,GAAG,EAAE,aAAa;IAClB,KAAK,EAAE;QACL,kIAAkI;QAClI,MAAM,EAAE,KAAK,CAAC,MAAM,CAA2B,iBAAiB,CAAC,MAAM,EAAE,EAAE,OAAO,EAAE,SAAS,CAAC,OAAO,EAAE,IAAI,EAAE,SAAS,CAAC,IAAI,EAAE,CAAC;KAC/H;IACD,IAAI,EAAE,CAAC,MAAM,EAAE,KAAK,EAAE,EAAE,CAAC,UAAU,CAAC,MAAM,EAAE,EAAE,OAAO,EAAE,CAAC,KAAK,CAAC,MAAM,CAAC,EAAE,CAAC;IACxE,MAAM,EAAE,CAAC,GAAG,EAAE,KAAK,EAAE,EAAE;QACrB,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,GAAG,GAAG,CAAC,IAAI,CAAA;QAClC,IAAI,KAAK,IAAI,CAAC,IAAI,MAAM,IAAI,CAAC;YAAE,OAAM;QACrC,GAAG,CAAC,IAAI,CAAC,IAAI,UAAU,EAAE,CAAC,IAAI,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,KAAK,EAAE,MAAM,EAAE,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,CAAA;IACrF,CAAC;CACF,CAAC,CAAA","sourcesContent":["import {\n Graphics2D,\n Types,\n component2d,\n strokeOps,\n type NodeOf,\n // Named so this component's emitted type reaches `Node2D` and its props through the sdk, not core.\n type Node2D as _Node2D,\n type Node2DProps as _Node2DProps,\n type Stroke,\n type StrokeResolved,\n} from \"@motionscript/sdk\"\n\nimport { loadPaints } from \"./paints\"\nimport { DEFAULT_PLOT_AREA } from \"./shared\"\n\n/**\n * The frame around a cartesian plot: an empty rect with an inside stroke. Split\n * from {@link ChartCanvas} so it is placed after the marks and frames the plot\n * over them, tucking a line or column running to the edge under the border.\n */\nexport const ChartBorder = component2d({\n key: \"chartBorder\",\n state: {\n /** The stroke resolver's default `align` is `'inside'`, so the whole weight sits within the box unless the theme overrides it. */\n stroke: Types.custom<Stroke, StrokeResolved[]>(DEFAULT_PLOT_AREA.stroke, { resolve: strokeOps.resolve, lerp: strokeOps.lerp }),\n },\n load: (loader, state) => loadPaints(loader, { strokes: [state.stroke] }),\n render: (ctx, state) => {\n const { width, height } = ctx.size\n if (width <= 0 || height <= 0) return\n ctx.draw(new Graphics2D().rect({ x: 0, y: 0, width, height }).stroke(state.stroke))\n },\n})\n\nexport type ChartBorder = NodeOf<typeof ChartBorder>\n"]}
@@ -1 +0,0 @@
1
- {"version":3,"file":"horizontal-axis.d.ts","sourceRoot":"","sources":["../../src/line-chart/horizontal-axis.ts"],"names":[],"mappings":"AAAA,OAAO,EAOL,KAAK,MAAM,EACX,KAAK,MAAM,EACX,KAAK,WAAW,IAAI,YAAY,EACjC,MAAM,mBAAmB,CAAC;AAI3B,OAAO,EAA8D,KAAK,OAAO,EAAE,MAAM,eAAe,CAAC;AACzG,OAAO,EAEL,KAAK,UAAU,EACf,KAAK,KAAK,EACX,MAAM,eAAe,CAAC;AAKvB;;;;;GAKG;AACH,eAAO,MAAM,cAAc;;IAIvB,iCAAiC;;IAEjC,0FAA0F;;;IAG1F,2DAA2D;;;;;;;;;;IAL3D,iCAAiC;;IAEjC,0FAA0F;;;IAG1F,2DAA2D;;;;;IAL3D,iCAAiC;;IAEjC,0FAA0F;;;IAG1F,2DAA2D;;;;;;;;0BAgF7D,CAAC;AAEH,MAAM,MAAM,cAAc,GAAG,MAAM,CAAC,OAAO,cAAc,CAAC,CAAC"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"horizontal-axis.js","sourceRoot":"","sources":["../../src/line-chart/horizontal-axis.ts"],"names":[],"mappings":"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","sourcesContent":["import {\n Rect,\n Text,\n Types,\n component2d,\n insetsOps,\n textOps,\n type NodeOf,\n type Node2D,\n type Node2DProps as _Node2DProps,\n} from \"@motionscript/sdk\";\nimport { enterBudget } from \"@motionscript/sdk/component\";\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 type AxisConfig,\n type Range,\n} from \"../kit/shared\";\nimport { markerCaption } from \"../kit/vertical-axis\";\n\nconst SLIDE = 24;\n\n/**\n * The horizontal axis of a {@link LineChart}: a row of {@link Text} markers, the\n * mirror of `VerticalAxis` (bound text and positions, landed resting state).\n * Markers are placed by value across the range, whatever they say: `2026-03`\n * sits three months along, not three slots along, unlike a bar chart's axis.\n */\nexport const HorizontalAxis = component2d({\n key: \"horizontalAxis\",\n state: {\n range: fresh<Range>(() => [0, 1]),\n /** Tick values in data units. */\n markers: fresh<number[]>(() => []),\n /** One caption per marker in its order; a missing one reads as the bare numeric value. */\n captions: fresh<string[]>(() => []),\n axis: Types.custom<AxisConfig>(DEFAULT_X_AXIS),\n /** Caption centred beneath the markers; empty hides it. */\n label: \"\",\n arrivals: arrivalsEntry(),\n },\n // A node made of markers would otherwise 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, whose box the markers are placed in.\n const box = () => (column[0]?.parent as Node2D | null | undefined)?.layoutBounds ?? { width: 0, height: 0 };\n const sorted = () => [...state.markers].sort((a, b) => a - b);\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 right edge, the chart's own: the last marker is centred on the last grid line, so half of it would fall outside the box. The left edge has the vertical axis's gutter beyond it.\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 /** Stagger markers in left to right, then the caption. The duration is the whole entrance ({@link enterBudget}). */\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 const markers = state.markers.map((_, i) => ({ at: i * step, duration: per, piece: arrival(timeline, i, from, ease) }));\n const label = captioned ? [{ at: (count - 1) * step + per, duration: caption, piece: arrival(timeline, \"label\", from, ease) }] : [];\n return timeline.together([arm, beats(timeline, [...markers, ...label])]);\n },\n },\n },\n});\n\nexport type HorizontalAxis = NodeOf<typeof HorizontalAxis>;\n"]}
@@ -1 +0,0 @@
1
- {"version":3,"file":"pie-legend.d.ts","sourceRoot":"","sources":["../../src/pie-chart/pie-legend.ts"],"names":[],"mappings":"AAAA,OAAO,EAUL,KAAK,MAAM,EAEX,KAAK,SAAS,IAAI,UAAU,EAC5B,KAAK,oBAAoB,IAAI,qBAAqB,EAClD,KAAK,mBAAmB,IAAI,oBAAoB,EAChD,KAAK,IAAI,IAAI,KAAK,EAClB,KAAK,YAAY,IAAI,aAAa,EAClC,KAAK,QAAQ,IAAI,SAAS,EAC1B,KAAK,YAAY,IAAI,aAAa,EAClC,KAAK,OAAO,IAAI,QAAQ,EACxB,KAAK,MAAM,IAAI,OAAO,EACtB,KAAK,WAAW,IAAI,YAAY,EAChC,KAAK,gBAAgB,IAAI,iBAAiB,EAC1C,KAAK,eAAe,IAAI,gBAAgB,EACxC,KAAK,MAAM,IAAI,OAAO,EACtB,KAAK,cAAc,IAAI,eAAe,EACtC,KAAK,MAAM,IAAI,OAAO,EACtB,KAAK,cAAc,IAAI,eAAe,EACtC,KAAK,OAAO,IAAI,QAAQ,EACzB,MAAM,mBAAmB,CAAA;AAG1B,OAAO,EAA8D,KAAK,OAAO,EAAE,MAAM,eAAe,CAAA;AACxG,OAAO,EAAkB,KAAK,YAAY,EAAE,MAAM,eAAe,CAAA;AACjE,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,UAAU,CAAA;AAIxC;;;;;GAKG;AACH,eAAO,MAAM,SAAS;IAMlB,0CAA0C;;;IAG1C,iIAAiI;;;;;;;;;;;;;;;;;;;;;;;;;;;;;IAHjI,0CAA0C;;;IAG1C,iIAAiI;;;;;;;;;;;;;;;;;;IAHjI,0CAA0C;;;IAG1C,iIAAiI;;;;;;;;;;;;;;;;;;;;;;;;;;;;2BAwEnI,CAAA;AAEF,MAAM,MAAM,SAAS,GAAG,MAAM,CAAC,OAAO,SAAS,CAAC,CAAA"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"pie-legend.js","sourceRoot":"","sources":["../../src/pie-chart/pie-legend.ts"],"names":[],"mappings":"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","sourcesContent":["import {\n Flow,\n Paint,\n Rect,\n Shapes,\n Text,\n Types,\n clamp,\n component2d,\n textOps,\n type NodeOf,\n // Named so the column's emitted type reaches the Rect surface it spreads through the sdk, not core.\n type Alignment as _Alignment,\n type CornerRadiusResolved as _CornerRadiusResolved,\n type CornerStyleResolved as _CornerStyleResolved,\n type Fill as _Fill,\n type FillResolved as _FillResolved,\n type FlowMode as _FlowMode,\n type FlowResolved as _FlowResolved,\n type GapSize as _GapSize,\n type Node2D as _Node2D,\n type Node2DProps as _Node2DProps,\n type RectCornerRadius as _RectCornerRadius,\n type RectCornerStyle as _RectCornerStyle,\n type Shadow as _Shadow,\n type ShadowResolved as _ShadowResolved,\n type Stroke as _Stroke,\n type StrokeResolved as _StrokeResolved,\n type Vector2 as _Vector2,\n} from \"@motionscript/sdk\"\n\nimport { fresh } from \"../kit/entries\"\nimport { armed, arrival, arrivalOf, arrivalsEntry, beats, frameEase, type Arrival } from \"../kit/motion\"\nimport { DEFAULT_LEGEND, type LegendConfig } from \"../kit/shared\"\nimport type { PieSlice } from \"./shared\"\n\nconst SLIDE = 16\n\n/**\n * The legend of a {@link PieChart}: a column (it sits beside the ring, in the\n * vertical strip it leaves) of caption-and-swatch entries, one per slice. No\n * show/hide: removing a row would re-cut every other wedge's share. Selection\n * arrives through `dims`.\n */\nexport const PieLegend = component2d({\n key: \"pieLegend\",\n state: {\n ...Paint.state,\n ...Flow.state,\n ...Shapes.corners,\n /** One entry per slice, in ring order. */\n slices: fresh<PieSlice[]>(() => []),\n legend: Types.custom<LegendConfig>(DEFAULT_LEGEND),\n /** Per-slice opacity multiplier, the signal that dims the ring, so an entry fades in step with its wedge. Missing reads as 1. */\n dims: fresh<number[]>(() => []),\n arrivals: arrivalsEntry(),\n },\n // The flow must be stated: a `Rect` with none lays children out `freeform`, every caption on top of the last.\n defaults: {\n flow: \"vertical\",\n align: \"centerLeft\",\n width: \"hug\",\n height: \"hug\",\n gap: (state) => state.legend.itemGap / 3,\n padding: (state) => state.legend.padding,\n },\n // The selection dim rides a wrapper, so the entrance animates the entry's own opacity without the two fighting over one value.\n children: (state) => {\n const marker = state.legend.markerStyle\n return state.slices.map((_, index) =>\n Rect({\n width: \"hug\",\n height: \"hug\",\n flow: \"freeform\",\n opacity: () => clamp(state.dims[index] ?? 1, 0, 1),\n children: [\n Rect({\n flow: \"horizontal\",\n gap: 12,\n align: \"center\",\n width: \"hug\",\n height: \"hug\",\n opacity: () => arrivalOf(state.arrivals, index).opacity,\n x: () => arrivalOf(state.arrivals, index).shift,\n children: [\n Rect({\n width: marker.height,\n height: marker.height,\n cornerRadius: marker.borderRadius,\n fill: () => state.slices[index]?.fill ?? \"white\",\n stroke: marker.stroke,\n shadow: marker.shadow,\n }),\n Text({\n ...textOps.styleProps(state.legend.textStyle),\n text: () => state.slices[index]?.category ?? \"\",\n }),\n ],\n }),\n ],\n })\n )\n },\n commands: {\n ...Paint.commands,\n /** Every entry shifted right and transparent: what a chart shows ahead of this legend's beat, since `enter` arms only on its first frame. */\n arm: (timeline, state) =>\n timeline.animate(() => ({ arrivals: armed([...state.slices.keys()], { opacity: 0, shift: SLIDE }) })),\n /** Slide and fade entries in from the right, top to bottom. The duration is the whole entrance, the stagger carved out of it. */\n enter: (timeline, state) => {\n const count = state.slices.length\n if (count === 0) return timeline.wait(timeline.duration)\n const from: Arrival = { opacity: 0, shift: SLIDE }\n const arm = timeline.animate(() => ({ arrivals: armed([...state.slices.keys()], from) }))\n // Each gap is a fifth of an entry's move, the axes' rhythm, solved from the budget.\n const per = timeline.duration / (1 + Math.max(0, count - 1) / 5)\n const step = per / 5\n const ease = frameEase(timeline)\n const entries = state.slices.map((_, i) => ({ at: i * step, duration: per, piece: arrival(timeline, i, from, ease) }))\n return timeline.together([arm, beats(timeline, entries)])\n },\n },\n measure: (measurer, state, children) => Flow.measure(measurer, state, children, Paint.inset(state)),\n layout: (box, state, children) => Flow.layout(box, state, children, Paint.inset(state)),\n render: (ctx, state) => Paint.draw(ctx, state, Shapes.rect(ctx.size, state)),\n})\n\nexport type PieLegend = NodeOf<typeof PieLegend>\n"]}
@@ -1,36 +0,0 @@
1
- import {
2
- Graphics2D,
3
- Types,
4
- component2d,
5
- strokeOps,
6
- type NodeOf,
7
- // Named so this component's emitted type reaches `Node2D` and its props through the sdk, not core.
8
- type Node2D as _Node2D,
9
- type Node2DProps as _Node2DProps,
10
- type Stroke,
11
- type StrokeResolved,
12
- } from "@motionscript/sdk"
13
-
14
- import { loadPaints } from "./paints"
15
- import { DEFAULT_PLOT_AREA } from "./shared"
16
-
17
- /**
18
- * The frame around a cartesian plot: an empty rect with an inside stroke. Split
19
- * from {@link ChartCanvas} so it is placed after the marks and frames the plot
20
- * over them, tucking a line or column running to the edge under the border.
21
- */
22
- export const ChartBorder = component2d({
23
- key: "chartBorder",
24
- state: {
25
- /** The stroke resolver's default `align` is `'inside'`, so the whole weight sits within the box unless the theme overrides it. */
26
- stroke: Types.custom<Stroke, StrokeResolved[]>(DEFAULT_PLOT_AREA.stroke, { resolve: strokeOps.resolve, lerp: strokeOps.lerp }),
27
- },
28
- load: (loader, state) => loadPaints(loader, { strokes: [state.stroke] }),
29
- render: (ctx, state) => {
30
- const { width, height } = ctx.size
31
- if (width <= 0 || height <= 0) return
32
- ctx.draw(new Graphics2D().rect({ x: 0, y: 0, width, height }).stroke(state.stroke))
33
- },
34
- })
35
-
36
- export type ChartBorder = NodeOf<typeof ChartBorder>
@@ -1,122 +0,0 @@
1
- import {
2
- Rect,
3
- Text,
4
- Types,
5
- component2d,
6
- insetsOps,
7
- textOps,
8
- type NodeOf,
9
- type Node2D,
10
- type Node2DProps as _Node2DProps,
11
- } from "@motionscript/sdk";
12
- import { enterBudget } from "@motionscript/sdk/component";
13
-
14
- import { asParts, fresh } from "../kit/entries";
15
- import { armed, arrival, arrivalOf, arrivalsEntry, beats, frameEase, type Arrival } from "../kit/motion";
16
- import {
17
- DEFAULT_X_AXIS,
18
- type AxisConfig,
19
- type Range,
20
- } from "../kit/shared";
21
- import { markerCaption } from "../kit/vertical-axis";
22
-
23
- const SLIDE = 24;
24
-
25
- /**
26
- * The horizontal axis of a {@link LineChart}: a row of {@link Text} markers, the
27
- * mirror of `VerticalAxis` (bound text and positions, landed resting state).
28
- * Markers are placed by value across the range, whatever they say: `2026-03`
29
- * sits three months along, not three slots along, unlike a bar chart's axis.
30
- */
31
- export const HorizontalAxis = component2d({
32
- key: "horizontalAxis",
33
- state: {
34
- range: fresh<Range>(() => [0, 1]),
35
- /** Tick values in data units. */
36
- markers: fresh<number[]>(() => []),
37
- /** One caption per marker in its order; a missing one reads as the bare numeric value. */
38
- captions: fresh<string[]>(() => []),
39
- axis: Types.custom<AxisConfig>(DEFAULT_X_AXIS),
40
- /** Caption centred beneath the markers; empty hides it. */
41
- label: "",
42
- arrivals: arrivalsEntry(),
43
- },
44
- // A node made of markers would otherwise hug them.
45
- defaults: { width: "fill", height: "fill" },
46
- children: (state) => {
47
- const tickPad = insetsOps.resolve(state.axis.tickPadding).top;
48
- const titlePad = insetsOps.resolve(state.axis.titlePadding).top;
49
-
50
- const column: Node2D[] = [];
51
- // The column's parent is the axis, whose box the markers are placed in.
52
- const box = () => (column[0]?.parent as Node2D | null | undefined)?.layoutBounds ?? { width: 0, height: 0 };
53
- const sorted = () => [...state.markers].sort((a, b) => a - b);
54
- const fracAt = (value: number | undefined) => {
55
- if (value === undefined) return 0;
56
- const [min, max] = state.range;
57
- return max <= min ? 0 : (value - min) / (max - min);
58
- };
59
-
60
- const markers = state.markers.map((_, i) => {
61
- const marker: Node2D = new Text({
62
- ...textOps.styleProps(state.axis.labelStyle),
63
- text: () => {
64
- const value = sorted()[i];
65
- return value === undefined ? "" : markerCaption(state, value);
66
- },
67
- x: () => {
68
- const width = box().width;
69
- const centred = (fracAt(sorted()[i]) - 0.5) * width;
70
- // Held inside the right edge, the chart's own: the last marker is centred on the last grid line, so half of it would fall outside the box. The left edge has the vertical axis's gutter beyond it.
71
- const limit = width / 2 - marker.layoutBounds.width / 2;
72
- return Math.min(centred, limit);
73
- },
74
- opacity: () => arrivalOf(state.arrivals, i).opacity,
75
- y: () => arrivalOf(state.arrivals, i).shift,
76
- });
77
- return marker;
78
- });
79
-
80
- const children: Node2D[] = [
81
- new Rect({ width: "fill", height: "hug", padding: { top: tickPad }, children: markers }),
82
- ];
83
- if (state.label !== "") {
84
- children.push(
85
- new Text({
86
- ...textOps.styleProps(state.axis.titleStyle),
87
- text: state.label,
88
- opacity: () => arrivalOf(state.arrivals, "label").opacity,
89
- y: () => arrivalOf(state.arrivals, "label").shift,
90
- }),
91
- );
92
- }
93
-
94
- column.push(new Rect({ flow: "vertical", gap: titlePad, height: "hug", width: "fill", children }));
95
- return asParts(column);
96
- },
97
- commands: {
98
- /** Stagger markers in left to right, then the caption. The duration is the whole entrance ({@link enterBudget}). */
99
- enter: {
100
- args: {
101
- stagger: Types.custom<number | undefined>(undefined),
102
- slide: Types.number(SLIDE),
103
- },
104
- run: (timeline, state) => {
105
- const { stagger, slide } = timeline.args;
106
- const count = state.markers.length;
107
- const captioned = state.label !== "";
108
- const from: Arrival = { opacity: 0, shift: slide };
109
- const keys = [...state.markers.keys(), ...(captioned ? ["label"] : [])];
110
- const arm = timeline.animate(() => ({ arrivals: armed(keys, from) }));
111
- if (count === 0) return arm;
112
- const { step, per, caption } = enterBudget(timeline.duration, count, captioned, stagger);
113
- const ease = frameEase(timeline);
114
- const markers = state.markers.map((_, i) => ({ at: i * step, duration: per, piece: arrival(timeline, i, from, ease) }));
115
- const label = captioned ? [{ at: (count - 1) * step + per, duration: caption, piece: arrival(timeline, "label", from, ease) }] : [];
116
- return timeline.together([arm, beats(timeline, [...markers, ...label])]);
117
- },
118
- },
119
- },
120
- });
121
-
122
- export type HorizontalAxis = NodeOf<typeof HorizontalAxis>;