@motionscript/charts 0.1.0 → 0.1.1-alpha.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.
Files changed (145) hide show
  1. package/CHANGELOG.md +19 -0
  2. package/dist/bar-chart/bar-chart.d.ts +22 -93
  3. package/dist/bar-chart/bar-chart.d.ts.map +1 -1
  4. package/dist/bar-chart/bar-chart.js +48 -121
  5. package/dist/bar-chart/bar-chart.js.map +1 -1
  6. package/dist/bar-chart/category-axis.d.ts +11 -38
  7. package/dist/bar-chart/category-axis.d.ts.map +1 -1
  8. package/dist/bar-chart/category-axis.js +15 -38
  9. package/dist/bar-chart/category-axis.js.map +1 -1
  10. package/dist/bar-chart/chart-bars.d.ts +43 -74
  11. package/dist/bar-chart/chart-bars.d.ts.map +1 -1
  12. package/dist/bar-chart/chart-bars.js +31 -59
  13. package/dist/bar-chart/chart-bars.js.map +1 -1
  14. package/dist/bar-chart/index.d.ts +2 -10
  15. package/dist/bar-chart/index.d.ts.map +1 -1
  16. package/dist/bar-chart/index.js +0 -7
  17. package/dist/bar-chart/index.js.map +1 -1
  18. package/dist/bar-chart/shared.d.ts +27 -90
  19. package/dist/bar-chart/shared.d.ts.map +1 -1
  20. package/dist/bar-chart/shared.js +15 -54
  21. package/dist/bar-chart/shared.js.map +1 -1
  22. package/dist/browser/chunks/chunk-4SMRCU24.js +2 -0
  23. package/dist/browser/chunks/chunk-4SMRCU24.js.map +7 -0
  24. package/dist/browser/index.js +1 -1
  25. package/dist/browser/index.js.map +3 -3
  26. package/dist/browser/kit.js +1 -1
  27. package/dist/browser/manifest.json +1 -1
  28. package/dist/engine.d.ts +4 -16
  29. package/dist/engine.d.ts.map +1 -1
  30. package/dist/engine.js +4 -16
  31. package/dist/engine.js.map +1 -1
  32. package/dist/kit/cartesian.d.ts +8 -28
  33. package/dist/kit/cartesian.d.ts.map +1 -1
  34. package/dist/kit/cartesian.js +7 -19
  35. package/dist/kit/cartesian.js.map +1 -1
  36. package/dist/kit/chart-border.d.ts +9 -18
  37. package/dist/kit/chart-border.d.ts.map +1 -1
  38. package/dist/kit/chart-border.js +4 -9
  39. package/dist/kit/chart-border.js.map +1 -1
  40. package/dist/kit/chart-canvas.d.ts +25 -36
  41. package/dist/kit/chart-canvas.d.ts.map +1 -1
  42. package/dist/kit/chart-canvas.js +13 -13
  43. package/dist/kit/chart-canvas.js.map +1 -1
  44. package/dist/kit/chart-legend.d.ts +14 -61
  45. package/dist/kit/chart-legend.d.ts.map +1 -1
  46. package/dist/kit/chart-legend.js +17 -65
  47. package/dist/kit/chart-legend.js.map +1 -1
  48. package/dist/kit/entries.d.ts +2 -0
  49. package/dist/kit/entries.d.ts.map +1 -1
  50. package/dist/kit/entries.js +2 -0
  51. package/dist/kit/entries.js.map +1 -1
  52. package/dist/kit/motion.d.ts +11 -3
  53. package/dist/kit/motion.d.ts.map +1 -1
  54. package/dist/kit/motion.js +7 -1
  55. package/dist/kit/motion.js.map +1 -1
  56. package/dist/kit/shared.d.ts +60 -175
  57. package/dist/kit/shared.d.ts.map +1 -1
  58. package/dist/kit/shared.js +40 -157
  59. package/dist/kit/shared.js.map +1 -1
  60. package/dist/kit/vertical-axis.d.ts +16 -45
  61. package/dist/kit/vertical-axis.d.ts.map +1 -1
  62. package/dist/kit/vertical-axis.js +17 -42
  63. package/dist/kit/vertical-axis.js.map +1 -1
  64. package/dist/line-chart/chart-line.d.ts +16 -41
  65. package/dist/line-chart/chart-line.d.ts.map +1 -1
  66. package/dist/line-chart/chart-line.js +14 -43
  67. package/dist/line-chart/chart-line.js.map +1 -1
  68. package/dist/line-chart/chart-region.d.ts +14 -27
  69. package/dist/line-chart/chart-region.d.ts.map +1 -1
  70. package/dist/line-chart/chart-region.js +8 -22
  71. package/dist/line-chart/chart-region.js.map +1 -1
  72. package/dist/line-chart/horizontal-axis.d.ts +16 -43
  73. package/dist/line-chart/horizontal-axis.d.ts.map +1 -1
  74. package/dist/line-chart/horizontal-axis.js +13 -42
  75. package/dist/line-chart/horizontal-axis.js.map +1 -1
  76. package/dist/line-chart/index.d.ts +1 -13
  77. package/dist/line-chart/index.d.ts.map +1 -1
  78. package/dist/line-chart/index.js +0 -12
  79. package/dist/line-chart/index.js.map +1 -1
  80. package/dist/line-chart/line-chart.d.ts +23 -109
  81. package/dist/line-chart/line-chart.d.ts.map +1 -1
  82. package/dist/line-chart/line-chart.js +45 -141
  83. package/dist/line-chart/line-chart.js.map +1 -1
  84. package/dist/line-chart/shared.d.ts +33 -107
  85. package/dist/line-chart/shared.d.ts.map +1 -1
  86. package/dist/line-chart/shared.js +28 -81
  87. package/dist/line-chart/shared.js.map +1 -1
  88. package/dist/line-chart/x-scale.d.ts +14 -55
  89. package/dist/line-chart/x-scale.d.ts.map +1 -1
  90. package/dist/line-chart/x-scale.js +29 -111
  91. package/dist/line-chart/x-scale.js.map +1 -1
  92. package/dist/nodes.d.ts +0 -12
  93. package/dist/nodes.d.ts.map +1 -1
  94. package/dist/nodes.js +0 -12
  95. package/dist/nodes.js.map +1 -1
  96. package/dist/pie-chart/index.d.ts +1 -12
  97. package/dist/pie-chart/index.d.ts.map +1 -1
  98. package/dist/pie-chart/index.js +0 -9
  99. package/dist/pie-chart/index.js.map +1 -1
  100. package/dist/pie-chart/pie-chart.d.ts +37 -71
  101. package/dist/pie-chart/pie-chart.d.ts.map +1 -1
  102. package/dist/pie-chart/pie-chart.js +31 -65
  103. package/dist/pie-chart/pie-chart.js.map +1 -1
  104. package/dist/pie-chart/pie-legend.d.ts +11 -26
  105. package/dist/pie-chart/pie-legend.d.ts.map +1 -1
  106. package/dist/pie-chart/pie-legend.js +14 -39
  107. package/dist/pie-chart/pie-legend.js.map +1 -1
  108. package/dist/pie-chart/pie-ring.d.ts +50 -192
  109. package/dist/pie-chart/pie-ring.d.ts.map +1 -1
  110. package/dist/pie-chart/pie-ring.js +75 -247
  111. package/dist/pie-chart/pie-ring.js.map +1 -1
  112. package/dist/pie-chart/shared.d.ts +45 -131
  113. package/dist/pie-chart/shared.d.ts.map +1 -1
  114. package/dist/pie-chart/shared.js +29 -72
  115. package/dist/pie-chart/shared.js.map +1 -1
  116. package/package.json +4 -4
  117. package/src/bar-chart/bar-chart.ts +51 -165
  118. package/src/bar-chart/category-axis.ts +16 -57
  119. package/src/bar-chart/chart-bars.ts +43 -120
  120. package/src/bar-chart/index.ts +2 -10
  121. package/src/bar-chart/shared.ts +29 -97
  122. package/src/engine.ts +4 -16
  123. package/src/kit/cartesian.ts +11 -26
  124. package/src/kit/chart-border.ts +6 -20
  125. package/src/kit/chart-canvas.ts +15 -40
  126. package/src/kit/chart-legend.ts +17 -86
  127. package/src/kit/entries.ts +4 -1
  128. package/src/kit/motion.ts +11 -2
  129. package/src/kit/shared.ts +58 -219
  130. package/src/kit/vertical-axis.ts +18 -71
  131. package/src/line-chart/chart-line.ts +16 -44
  132. package/src/line-chart/chart-region.ts +10 -23
  133. package/src/line-chart/horizontal-axis.ts +13 -42
  134. package/src/line-chart/index.ts +1 -13
  135. package/src/line-chart/line-chart.ts +50 -184
  136. package/src/line-chart/shared.ts +51 -145
  137. package/src/line-chart/x-scale.ts +31 -121
  138. package/src/nodes.ts +0 -12
  139. package/src/pie-chart/index.ts +1 -12
  140. package/src/pie-chart/pie-chart.ts +34 -102
  141. package/src/pie-chart/pie-legend.ts +14 -55
  142. package/src/pie-chart/pie-ring.ts +80 -307
  143. package/src/pie-chart/shared.ts +50 -139
  144. package/dist/browser/chunks/chunk-TJNHLQGV.js +0 -2
  145. package/dist/browser/chunks/chunk-TJNHLQGV.js.map +0 -7
@@ -1,25 +1,10 @@
1
- /**
2
- * Types and pure helpers specific to the {@link BarChart} family: how a row's
3
- * values become the spans its columns cover, how the value axis is scaled around
4
- * them, and the theme the bars add to the shared chart vocabulary.
5
- *
6
- * Everything a line or a pie chart would want too — what a series is, the axis
7
- * domain model, the theme leaf resolvers, the legend and plot-panel branches —
8
- * lives in `../kit/shared.ts` and is imported here.
9
- *
10
- * Kept renderer-agnostic (no `Node` imports) so a host's inspector mapping
11
- * can build a partial {@link BarChartTheme} without
12
- * pulling the components in.
13
- */
14
1
  import { fillOps, lerpNumber, shadowOps, strokeOps, textOps, } from "@motionscript/sdk";
15
- import { CHART_PALETTE, DEFAULT_LEGEND, DEFAULT_PLOT_AREA, DEFAULT_SERIES_FILLS, DEFAULT_X_AXIS, DEFAULT_Y_AXIS, SPOTLIGHT_DIM, lerpAxisConfig, lerpLegendConfig, lerpPlotArea, lerpSeriesFills, niceStep, num, resolveAxisConfig, resolveLegendConfig, resolvePlotArea, resolveSeriesFills, text, } from "../kit/shared.js";
2
+ import { niceStep } from "@motionscript/sdk/component";
3
+ import { CHART_PALETTE, DEFAULT_LEGEND, DEFAULT_PLOT_AREA, DEFAULT_SERIES_FILLS, DEFAULT_X_AXIS, DEFAULT_Y_AXIS, SPOTLIGHT_DIM, lerpAxisConfig, lerpLegendConfig, lerpPlotArea, lerpSeriesFills, num, resolveAxisConfig, resolveLegendConfig, resolvePlotArea, resolveSeriesFills, text, } from "../kit/shared.js";
16
4
  /**
17
- * The spans one row's bars cover, one per series, in series order.
18
- *
19
- * Stacking is a running sum in the order the series are listed, which is also
20
- * the order they're drawn: series 0 sits on the baseline and each later one
21
- * rides on what's below it. A zero-valued series still yields a (degenerate)
22
- * span so the returned list stays index-aligned with the series list.
5
+ * One row's spans, in series order. Stacking is a running sum in listed order,
6
+ * so series 0 sits on the baseline. A zero value still yields a degenerate span,
7
+ * keeping the list index-aligned with the series.
23
8
  */
24
9
  export function barSpans(row, series, stacked) {
25
10
  let running = 0;
@@ -33,13 +18,9 @@ export function barSpans(row, series, stacked) {
33
18
  });
34
19
  }
35
20
  /**
36
- * The index of the series whose segment ends a row's stack — the one that gets
37
- * the rounded cap, so a stack reads as one capped column rather than a pile of
38
- * separate boxes. `-1` when every value in the row is zero.
39
- *
40
- * Read off the *last non-zero* series rather than the last one listed, so a
41
- * series that happens to be 0 in this row doesn't take the cap and leave the
42
- * segment below it square.
21
+ * The series ending a row's stack, which gets the rounded cap; `-1` when the row
22
+ * is all zero. It is the last non-zero series, so a zero one does not take the
23
+ * cap and leave the segment below square.
43
24
  */
44
25
  export function stackCapIndex(row, series) {
45
26
  let last = -1;
@@ -49,17 +30,13 @@ export function stackCapIndex(row, series) {
49
30
  }
50
31
  return last;
51
32
  }
52
- /** The captions beneath the baseline: one per row, read off the category column. */
53
33
  export function barCategories(data, field) {
54
34
  return data.map((row) => text(row, field));
55
35
  }
56
36
  /**
57
- * The `[min, max]` of everything the chart draws, **zero always included**.
58
- *
59
- * Zero is in the range whatever the data says, because a bar chart's baseline is
60
- * zero: a scale starting at 40 draws a column three times its neighbour for a
61
- * 10% difference, which is the classic way to lie with one. A chart that really
62
- * does want a cropped axis says so with an explicit range.
37
+ * The `[min, max]` of everything drawn, zero always included: a scale starting
38
+ * at 40 draws a column three times its neighbour for a 10% difference. A cropped
39
+ * axis takes an explicit range.
63
40
  */
64
41
  export function barValueExtent(data, series, stacked) {
65
42
  let lo = 0;
@@ -72,14 +49,7 @@ export function barValueExtent(data, series, stacked) {
72
49
  }
73
50
  return lo < hi ? [lo, hi] : [0, 1];
74
51
  }
75
- /**
76
- * Effective value scale: the explicit `range`, else the data's extent nudged out
77
- * to tidy step bounds so the markers read as round numbers.
78
- *
79
- * `divisions` is how many segments the auto-range is stepped into (one fewer
80
- * than the marker count), so the ticks the axis draws land on the bounds this
81
- * picks.
82
- */
52
+ /** The explicit `range`, else the data's extent nudged to tidy bounds; `divisions` (one fewer than the marker count) makes the drawn ticks land on them. */
83
53
  export function resolveBarScale(data, series, stacked, range, divisions) {
84
54
  if (range)
85
55
  return range;
@@ -88,7 +58,6 @@ export function resolveBarScale(data, series, stacked, range, divisions) {
88
58
  const step = niceStep((hi - lo) / segments || 1);
89
59
  return [Math.floor(lo / step) * step, Math.ceil(hi / step) * step];
90
60
  }
91
- /** The bar chart's out-of-the-box look. */
92
61
  export const DEFAULT_BAR_CHART_THEME = {
93
62
  seriesFills: DEFAULT_SERIES_FILLS,
94
63
  bar: {
@@ -98,9 +67,7 @@ export const DEFAULT_BAR_CHART_THEME = {
98
67
  stroke: [],
99
68
  shadow: [],
100
69
  },
101
- // A category axis names its slots, so its captions are set like a caption
102
- // rather than like a numeric marker: same size, less weight than the line
103
- // chart's ticks, and centred on the slot.
70
+ // Captions rather than numeric markers: less weight than the line chart's ticks.
104
71
  xAxis: {
105
72
  ...DEFAULT_X_AXIS,
106
73
  labelStyle: { ...DEFAULT_X_AXIS.labelStyle, fontWeight: 600 },
@@ -135,12 +102,7 @@ function lerpBarStyle(from, to, t) {
135
102
  shadow: shadowOps.lerp(from.shadow, to.shadow, t),
136
103
  };
137
104
  }
138
- /**
139
- * {@link BarChart}'s `theme` entry's resolve: merges the author's partial
140
- * {@link BarChartTheme} onto `previous` (falling back to
141
- * {@link DEFAULT_BAR_CHART_THEME} on first resolution), fully resolving every
142
- * leaf so the tween below always has resolved data to interpolate.
143
- */
105
+ /** The `theme` entry's resolve: merges a partial {@link BarChartTheme} onto `previous` (first resolution: the default). */
144
106
  export function resolveBarChartTheme(theme, previous) {
145
107
  const base = previous ?? DEFAULT_BAR_CHART_THEME;
146
108
  return {
@@ -156,7 +118,6 @@ export function resolveBarChartTheme(theme, previous) {
156
118
  },
157
119
  };
158
120
  }
159
- /** {@link BarChart}'s `theme` entry's lerp — leaf by leaf. */
160
121
  export function lerpBarChartTheme(from, to, t) {
161
122
  return {
162
123
  seriesFills: lerpSeriesFills(from.seriesFills, to.seriesFills, t),
@@ -171,7 +132,7 @@ export function lerpBarChartTheme(from, to, t) {
171
132
  },
172
133
  };
173
134
  }
174
- /** The paint series `index` is drawn in: its own override, else the palette's entry. */
135
+ /** Series `index`'s own `fill`, else the palette's entry. */
175
136
  export function resolveBarFill(palette, series, index) {
176
137
  if (series.fill != null)
177
138
  return fillOps.resolve(series.fill);
@@ -1 +1 @@
1
- {"version":3,"file":"shared.js","sourceRoot":"","sources":["../../src/bar-chart/shared.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAEH,OAAO,EACL,OAAO,EACP,UAAU,EACV,SAAS,EACT,SAAS,EACT,OAAO,GAQR,MAAM,mBAAmB,CAAA;AAE1B,OAAO,EACL,aAAa,EACb,cAAc,EACd,iBAAiB,EACjB,oBAAoB,EACpB,cAAc,EACd,cAAc,EACd,aAAa,EACb,cAAc,EACd,gBAAgB,EAChB,YAAY,EACZ,eAAe,EACf,QAAQ,EACR,GAAG,EACH,iBAAiB,EACjB,mBAAmB,EACnB,eAAe,EACf,kBAAkB,EAClB,IAAI,GAOL,MAAM,eAAe,CAAA;AA8BtB;;;;;;;GAOG;AACH,MAAM,UAAU,QAAQ,CACtB,GAAe,EACf,MAAmB,EACnB,OAAgB;IAEhB,IAAI,OAAO,GAAG,CAAC,CAAA;IACf,OAAO,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE;QACtB,MAAM,KAAK,GAAG,GAAG,CAAC,GAAG,EAAE,CAAC,CAAC,KAAK,CAAC,CAAA;QAC/B,IAAI,CAAC,OAAO;YAAE,OAAO,EAAE,IAAI,EAAE,CAAC,EAAE,EAAE,EAAE,KAAK,EAAE,KAAK,EAAE,CAAA;QAClD,MAAM,IAAI,GAAG,OAAO,CAAA;QACpB,OAAO,IAAI,KAAK,CAAA;QAChB,OAAO,EAAE,IAAI,EAAE,EAAE,EAAE,OAAO,EAAE,KAAK,EAAE,CAAA;IACrC,CAAC,CAAC,CAAA;AACJ,CAAC;AAED;;;;;;;;GAQG;AACH,MAAM,UAAU,aAAa,CAAC,GAAe,EAAE,MAAmB;IAChE,IAAI,IAAI,GAAG,CAAC,CAAC,CAAA;IACb,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;QACvC,IAAI,GAAG,CAAC,GAAG,EAAE,MAAM,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,KAAK,CAAC;YAAE,IAAI,GAAG,CAAC,CAAA;IAC/C,CAAC;IACD,OAAO,IAAI,CAAA;AACb,CAAC;AAED,oFAAoF;AACpF,MAAM,UAAU,aAAa,CAAC,IAAkB,EAAE,KAAa;IAC7D,OAAO,IAAI,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,IAAI,CAAC,GAAG,EAAE,KAAK,CAAC,CAAC,CAAA;AAC5C,CAAC;AAED;;;;;;;GAOG;AACH,MAAM,UAAU,cAAc,CAC5B,IAAkB,EAClB,MAAmB,EACnB,OAAgB;IAEhB,IAAI,EAAE,GAAG,CAAC,CAAA;IACV,IAAI,EAAE,GAAG,CAAC,CAAA;IACV,KAAK,MAAM,GAAG,IAAI,IAAI,EAAE,CAAC;QACvB,KAAK,MAAM,IAAI,IAAI,QAAQ,CAAC,GAAG,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,CAAC;YAClD,EAAE,GAAG,IAAI,CAAC,GAAG,CAAC,EAAE,EAAE,IAAI,CAAC,IAAI,EAAE,IAAI,CAAC,EAAE,CAAC,CAAA;YACrC,EAAE,GAAG,IAAI,CAAC,GAAG,CAAC,EAAE,EAAE,IAAI,CAAC,IAAI,EAAE,IAAI,CAAC,EAAE,CAAC,CAAA;QACvC,CAAC;IACH,CAAC;IACD,OAAO,EAAE,GAAG,EAAE,CAAC,CAAC,CAAC,CAAC,EAAE,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAA;AACpC,CAAC;AAED;;;;;;;GAOG;AACH,MAAM,UAAU,eAAe,CAC7B,IAAkB,EAClB,MAAmB,EACnB,OAAgB,EAChB,KAAwB,EACxB,SAAiB;IAEjB,IAAI,KAAK;QAAE,OAAO,KAAK,CAAA;IACvB,MAAM,CAAC,EAAE,EAAE,EAAE,CAAC,GAAG,cAAc,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,CAAC,CAAA;IACtD,MAAM,QAAQ,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,KAAK,CAAC,SAAS,CAAC,CAAC,CAAA;IACnD,MAAM,IAAI,GAAG,QAAQ,CAAC,CAAC,EAAE,GAAG,EAAE,CAAC,GAAG,QAAQ,IAAI,CAAC,CAAC,CAAA;IAChD,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,EAAE,GAAG,IAAI,CAAC,GAAG,IAAI,EAAE,IAAI,CAAC,IAAI,CAAC,EAAE,GAAG,IAAI,CAAC,GAAG,IAAI,CAAC,CAAA;AACpE,CAAC;AAyDD,2CAA2C;AAC3C,MAAM,CAAC,MAAM,uBAAuB,GAAmB;IACrD,WAAW,EAAE,oBAAoB;IACjC,GAAG,EAAE;QACH,YAAY,EAAE,CAAC;QACf,QAAQ,EAAE,IAAI;QACd,QAAQ,EAAE,CAAC;QACX,MAAM,EAAE,EAAE;QACV,MAAM,EAAE,EAAE;KACX;IACD,0EAA0E;IAC1E,0EAA0E;IAC1E,0CAA0C;IAC1C,KAAK,EAAE;QACL,GAAG,cAAc;QACjB,UAAU,EAAE,EAAE,GAAG,cAAc,CAAC,UAAU,EAAE,UAAU,EAAE,GAAG,EAAE;QAC7D,WAAW,EAAE,EAAE;KAChB;IACD,KAAK,EAAE,cAAc;IACrB,QAAQ,EAAE,iBAAiB;IAC3B,MAAM,EAAE,cAAc;IACtB,UAAU,EAAE;QACV,QAAQ,EAAE,EAAE;QACZ,UAAU,EAAE,GAAG;QACf,SAAS,EAAE,QAAQ;QACnB,IAAI,EAAE,aAAa,CAAC,WAAW;KAChC;IACD,SAAS,EAAE,EAAE,UAAU,EAAE,aAAa,EAAE;CACzC,CAAA;AAED,SAAS,eAAe,CACtB,GAAwC,EACxC,QAAwB;IAExB,OAAO;QACL,YAAY,EAAE,GAAG,EAAE,YAAY,IAAI,QAAQ,CAAC,YAAY;QACxD,QAAQ,EAAE,GAAG,EAAE,QAAQ,IAAI,QAAQ,CAAC,QAAQ;QAC5C,QAAQ,EAAE,GAAG,EAAE,QAAQ,IAAI,QAAQ,CAAC,QAAQ;QAC5C,MAAM,EAAE,SAAS,CAAC,OAAO,CAAC,GAAG,EAAE,MAAM,IAAI,QAAQ,CAAC,MAAM,CAAC;QACzD,MAAM,EAAE,SAAS,CAAC,OAAO,CAAC,GAAG,EAAE,MAAM,IAAI,QAAQ,CAAC,MAAM,CAAC;KAC1D,CAAA;AACH,CAAC;AAED,SAAS,YAAY,CACnB,IAAoB,EACpB,EAAkB,EAClB,CAAS;IAET,OAAO;QACL,YAAY,EAAE,UAAU,CAAC,IAAI,CAAC,YAAY,EAAE,EAAE,CAAC,YAAY,EAAE,CAAC,CAAC;QAC/D,QAAQ,EAAE,UAAU,CAAC,IAAI,CAAC,QAAQ,EAAE,EAAE,CAAC,QAAQ,EAAE,CAAC,CAAC;QACnD,QAAQ,EAAE,UAAU,CAAC,IAAI,CAAC,QAAQ,EAAE,EAAE,CAAC,QAAQ,EAAE,CAAC,CAAC;QACnD,MAAM,EAAE,SAAS,CAAC,IAAI,CACpB,IAAI,CAAC,MAA0B,EAC/B,EAAE,CAAC,MAA0B,EAC7B,CAAC,CACF;QACD,MAAM,EAAE,SAAS,CAAC,IAAI,CACpB,IAAI,CAAC,MAA0B,EAC/B,EAAE,CAAC,MAA0B,EAC7B,CAAC,CACF;KACF,CAAA;AACH,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,oBAAoB,CAClC,KAAgC,EAChC,QAAyB;IAEzB,MAAM,IAAI,GAAG,QAAQ,IAAI,uBAAuB,CAAA;IAChD,OAAO;QACL,WAAW,EAAE,kBAAkB,CAAC,KAAK,EAAE,WAAW,EAAE,IAAI,CAAC,WAAW,CAAC;QACrE,GAAG,EAAE,eAAe,CAAC,KAAK,EAAE,GAAG,EAAE,IAAI,CAAC,GAAG,CAAC;QAC1C,KAAK,EAAE,iBAAiB,CAAC,KAAK,EAAE,KAAK,EAAE,IAAI,CAAC,KAAK,CAAC;QAClD,KAAK,EAAE,iBAAiB,CAAC,KAAK,EAAE,KAAK,EAAE,IAAI,CAAC,KAAK,CAAC;QAClD,QAAQ,EAAE,eAAe,CAAC,KAAK,EAAE,QAAQ,EAAE,IAAI,CAAC,QAAQ,CAAC;QACzD,MAAM,EAAE,mBAAmB,CAAC,KAAK,EAAE,MAAM,EAAE,IAAI,CAAC,MAAM,CAAC;QACvD,UAAU,EAAE,OAAO,CAAC,YAAY,CAAC,KAAK,EAAE,UAAU,EAAE,IAAI,CAAC,UAAU,CAAC;QACpE,SAAS,EAAE;YACT,UAAU,EAAE,KAAK,EAAE,SAAS,EAAE,UAAU,IAAI,IAAI,CAAC,SAAS,CAAC,UAAU;SACtE;KACF,CAAA;AACH,CAAC;AAED,8DAA8D;AAC9D,MAAM,UAAU,iBAAiB,CAC/B,IAAoB,EACpB,EAAkB,EAClB,CAAS;IAET,OAAO;QACL,WAAW,EAAE,eAAe,CAAC,IAAI,CAAC,WAAW,EAAE,EAAE,CAAC,WAAW,EAAE,CAAC,CAAC;QACjE,GAAG,EAAE,YAAY,CAAC,IAAI,CAAC,GAAG,EAAE,EAAE,CAAC,GAAG,EAAE,CAAC,CAAC;QACtC,KAAK,EAAE,cAAc,CAAC,IAAI,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,EAAE,CAAC,CAAC;QAC9C,KAAK,EAAE,cAAc,CAAC,IAAI,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,EAAE,CAAC,CAAC;QAC9C,QAAQ,EAAE,YAAY,CAAC,IAAI,CAAC,QAAQ,EAAE,EAAE,CAAC,QAAQ,EAAE,CAAC,CAAC;QACrD,MAAM,EAAE,gBAAgB,CAAC,IAAI,CAAC,MAAM,EAAE,EAAE,CAAC,MAAM,EAAE,CAAC,CAAC;QACnD,UAAU,EAAE,OAAO,CAAC,SAAS,CAAC,IAAI,CAAC,UAAU,EAAE,EAAE,CAAC,UAAU,EAAE,CAAC,CAAC;QAChE,SAAS,EAAE;YACT,UAAU,EAAE,UAAU,CACpB,IAAI,CAAC,SAAS,CAAC,UAAU,EACzB,EAAE,CAAC,SAAS,CAAC,UAAU,EACvB,CAAC,CACF;SACF;KACF,CAAA;AACH,CAAC;AAED,wFAAwF;AACxF,MAAM,UAAU,cAAc,CAC5B,OAAe,EACf,MAAiB,EACjB,KAAa;IAEb,IAAI,MAAM,CAAC,IAAI,IAAI,IAAI;QAAE,OAAO,OAAO,CAAC,OAAO,CAAC,MAAM,CAAC,IAAI,CAAC,CAAA;IAC5D,IAAI,OAAO,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,OAAO,CAAA;IACxC,OAAO,OAAO,CAAC,KAAK,GAAG,OAAO,CAAC,MAAM,CAAC,CAAA;AACxC,CAAC","sourcesContent":["/**\n * Types and pure helpers specific to the {@link BarChart} family: how a row's\n * values become the spans its columns cover, how the value axis is scaled around\n * them, and the theme the bars add to the shared chart vocabulary.\n *\n * Everything a line or a pie chart would want too — what a series is, the axis\n * domain model, the theme leaf resolvers, the legend and plot-panel branches —\n * lives in `../kit/shared.ts` and is imported here.\n *\n * Kept renderer-agnostic (no `Node` imports) so a host's inspector mapping\n * can build a partial {@link BarChartTheme} without\n * pulling the components in.\n */\n\nimport {\n fillOps,\n lerpNumber,\n shadowOps,\n strokeOps,\n textOps,\n type DataRecord,\n type Fill,\n type Shadow,\n type ShadowResolved,\n type Stroke,\n type StrokeResolved,\n type TextStyle,\n} from \"@motionscript/sdk\"\n\nimport {\n CHART_PALETTE,\n DEFAULT_LEGEND,\n DEFAULT_PLOT_AREA,\n DEFAULT_SERIES_FILLS,\n DEFAULT_X_AXIS,\n DEFAULT_Y_AXIS,\n SPOTLIGHT_DIM,\n lerpAxisConfig,\n lerpLegendConfig,\n lerpPlotArea,\n lerpSeriesFills,\n niceStep,\n num,\n resolveAxisConfig,\n resolveLegendConfig,\n resolvePlotArea,\n resolveSeriesFills,\n text,\n type AxisConfig,\n type ChartSeries,\n type LegendConfig,\n type LegendTheme,\n type PlotAreaConfig,\n type Range,\n} from \"../kit/shared\"\n\n/**\n * One series in a {@link BarChart}: a column of the table drawn as one bar per\n * row — side by side with its siblings within each category's slot, or stacked\n * on top of them.\n *\n * The family-wide {@link ChartSeries} under a name that says what it draws here.\n */\nexport type BarSeries = ChartSeries\n\n/**\n * One drawn bar's span in **data units**: the value its base sits at and the\n * value its far end reaches.\n *\n * A span rather than a height because that is the one shape both modes fit. A\n * grouped bar runs from zero to its value; a stacked segment runs from the\n * running total below it to that total plus its own value. Negative values fall\n * out of the same arithmetic — the span simply runs the other way — so a chart\n * with a loss in it needs no special case, only a baseline that isn't the floor.\n */\nexport interface BarSpan {\n /** Value the bar's base sits at — 0 when grouped, the running total when stacked. */\n from: number\n /** Value its far end reaches. */\n to: number\n /** The value this bar plots — `to - from`, kept for the figure printed on it. */\n value: number\n}\n\n/**\n * The spans one row's bars cover, one per series, in series order.\n *\n * Stacking is a running sum in the order the series are listed, which is also\n * the order they're drawn: series 0 sits on the baseline and each later one\n * rides on what's below it. A zero-valued series still yields a (degenerate)\n * span so the returned list stays index-aligned with the series list.\n */\nexport function barSpans(\n row: DataRecord,\n series: BarSeries[],\n stacked: boolean\n): BarSpan[] {\n let running = 0\n return series.map((s) => {\n const value = num(row, s.field)\n if (!stacked) return { from: 0, to: value, value }\n const from = running\n running += value\n return { from, to: running, value }\n })\n}\n\n/**\n * The index of the series whose segment ends a row's stack — the one that gets\n * the rounded cap, so a stack reads as one capped column rather than a pile of\n * separate boxes. `-1` when every value in the row is zero.\n *\n * Read off the *last non-zero* series rather than the last one listed, so a\n * series that happens to be 0 in this row doesn't take the cap and leave the\n * segment below it square.\n */\nexport function stackCapIndex(row: DataRecord, series: BarSeries[]): number {\n let last = -1\n for (let i = 0; i < series.length; i++) {\n if (num(row, series[i].field) !== 0) last = i\n }\n return last\n}\n\n/** The captions beneath the baseline: one per row, read off the category column. */\nexport function barCategories(data: DataRecord[], field: string): string[] {\n return data.map((row) => text(row, field))\n}\n\n/**\n * The `[min, max]` of everything the chart draws, **zero always included**.\n *\n * Zero is in the range whatever the data says, because a bar chart's baseline is\n * zero: a scale starting at 40 draws a column three times its neighbour for a\n * 10% difference, which is the classic way to lie with one. A chart that really\n * does want a cropped axis says so with an explicit range.\n */\nexport function barValueExtent(\n data: DataRecord[],\n series: BarSeries[],\n stacked: boolean\n): Range {\n let lo = 0\n let hi = 0\n for (const row of data) {\n for (const span of barSpans(row, series, stacked)) {\n lo = Math.min(lo, span.from, span.to)\n hi = Math.max(hi, span.from, span.to)\n }\n }\n return lo < hi ? [lo, hi] : [0, 1]\n}\n\n/**\n * Effective value scale: the explicit `range`, else the data's extent nudged out\n * to tidy step bounds so the markers read as round numbers.\n *\n * `divisions` is how many segments the auto-range is stepped into (one fewer\n * than the marker count), so the ticks the axis draws land on the bounds this\n * picks.\n */\nexport function resolveBarScale(\n data: DataRecord[],\n series: BarSeries[],\n stacked: boolean,\n range: Range | undefined,\n divisions: number\n): Range {\n if (range) return range\n const [lo, hi] = barValueExtent(data, series, stacked)\n const segments = Math.max(1, Math.round(divisions))\n const step = niceStep((hi - lo) / segments || 1)\n return [Math.floor(lo / step) * step, Math.ceil(hi / step) * step]\n}\n\n// ---- Theme ---------------------------------------------------------------\n\n/** How the columns themselves are drawn and how the slot is divided up. */\nexport interface BarStyleConfig {\n /**\n * Radius of a column's far-end corners, in px. Only the outer end rounds — an\n * interior stacked segment stays square, so the stack reads as one column.\n */\n cornerRadius: number\n /**\n * Fraction of its category's slot the bars fill, `[0, 1]`. The remainder is\n * the channel between one category and the next, which is what makes a bar\n * chart read as groups rather than as a solid block.\n */\n slotFill: number\n /** Gap between the grouped bars *within* one slot, in px. Ignored when stacked. */\n groupGap: number\n /** Optional outline on every column. */\n stroke: Stroke\n /** Optional drop shadow on every column. */\n shadow: Shadow\n}\n\n/** A {@link BarChart}'s full, resolved visual theme. */\nexport interface BarChartConfig {\n /**\n * Default per-series bar paint, cycled by series index (`i % length`). A\n * series' own `fill`, when set, replaces its entry outright.\n */\n seriesFills: Fill[]\n bar: BarStyleConfig\n /** The category axis beneath the baseline. */\n xAxis: AxisConfig\n /** The numeric value axis up the left. */\n yAxis: AxisConfig\n plotArea: PlotAreaConfig\n legend: LegendConfig\n /** The figure printed on each column, when the chart prints them. */\n valueStyle: TextStyle\n /** How far everything *outside* a spotlit series or category fades. */\n spotlight: { dimOpacity: number }\n}\n\n/** Author-facing partial theme — every branch optional and deep-merged. */\nexport type BarChartTheme = {\n seriesFills?: Fill[]\n bar?: Partial<BarStyleConfig>\n xAxis?: Partial<AxisConfig>\n yAxis?: Partial<AxisConfig>\n plotArea?: Partial<PlotAreaConfig>\n legend?: LegendTheme\n valueStyle?: TextStyle\n spotlight?: Partial<BarChartConfig[\"spotlight\"]>\n}\n\n/** The bar chart's out-of-the-box look. */\nexport const DEFAULT_BAR_CHART_THEME: BarChartConfig = {\n seriesFills: DEFAULT_SERIES_FILLS,\n bar: {\n cornerRadius: 6,\n slotFill: 0.72,\n groupGap: 6,\n stroke: [],\n shadow: [],\n },\n // A category axis names its slots, so its captions are set like a caption\n // rather than like a numeric marker: same size, less weight than the line\n // chart's ticks, and centred on the slot.\n xAxis: {\n ...DEFAULT_X_AXIS,\n labelStyle: { ...DEFAULT_X_AXIS.labelStyle, fontWeight: 600 },\n tickPadding: 16,\n },\n yAxis: DEFAULT_Y_AXIS,\n plotArea: DEFAULT_PLOT_AREA,\n legend: DEFAULT_LEGEND,\n valueStyle: {\n fontSize: 24,\n fontWeight: 700,\n textAlign: \"center\",\n fill: CHART_PALETTE.markerColor,\n },\n spotlight: { dimOpacity: SPOTLIGHT_DIM },\n}\n\nfunction resolveBarStyle(\n bar: Partial<BarStyleConfig> | undefined,\n previous: BarStyleConfig\n): BarStyleConfig {\n return {\n cornerRadius: bar?.cornerRadius ?? previous.cornerRadius,\n slotFill: bar?.slotFill ?? previous.slotFill,\n groupGap: bar?.groupGap ?? previous.groupGap,\n stroke: strokeOps.resolve(bar?.stroke ?? previous.stroke),\n shadow: shadowOps.resolve(bar?.shadow ?? previous.shadow),\n }\n}\n\nfunction lerpBarStyle(\n from: BarStyleConfig,\n to: BarStyleConfig,\n t: number\n): BarStyleConfig {\n return {\n cornerRadius: lerpNumber(from.cornerRadius, to.cornerRadius, t),\n slotFill: lerpNumber(from.slotFill, to.slotFill, t),\n groupGap: lerpNumber(from.groupGap, to.groupGap, 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/**\n * {@link BarChart}'s `theme` entry's resolve: merges the author's partial\n * {@link BarChartTheme} onto `previous` (falling back to\n * {@link DEFAULT_BAR_CHART_THEME} on first resolution), fully resolving every\n * leaf so the tween below always has resolved data to interpolate.\n */\nexport function resolveBarChartTheme(\n theme: BarChartTheme | undefined,\n previous?: BarChartConfig\n): BarChartConfig {\n const base = previous ?? DEFAULT_BAR_CHART_THEME\n return {\n seriesFills: resolveSeriesFills(theme?.seriesFills, base.seriesFills),\n bar: resolveBarStyle(theme?.bar, base.bar),\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 valueStyle: textOps.resolveStyle(theme?.valueStyle, base.valueStyle),\n spotlight: {\n dimOpacity: theme?.spotlight?.dimOpacity ?? base.spotlight.dimOpacity,\n },\n }\n}\n\n/** {@link BarChart}'s `theme` entry's lerp — leaf by leaf. */\nexport function lerpBarChartTheme(\n from: BarChartConfig,\n to: BarChartConfig,\n t: number\n): BarChartConfig {\n return {\n seriesFills: lerpSeriesFills(from.seriesFills, to.seriesFills, t),\n bar: lerpBarStyle(from.bar, to.bar, 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 valueStyle: textOps.lerpStyle(from.valueStyle, to.valueStyle, t),\n spotlight: {\n dimOpacity: lerpNumber(\n from.spotlight.dimOpacity,\n to.spotlight.dimOpacity,\n t\n ),\n },\n }\n}\n\n/** The paint series `index` is drawn in: its own override, else the palette's entry. */\nexport function resolveBarFill(\n palette: Fill[],\n series: BarSeries,\n index: number\n): Fill {\n if (series.fill != null) return fillOps.resolve(series.fill)\n if (palette.length === 0) return \"white\"\n return palette[index % palette.length]\n}\n"]}
1
+ {"version":3,"file":"shared.js","sourceRoot":"","sources":["../../src/bar-chart/shared.ts"],"names":[],"mappings":"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","sourcesContent":["import {\n fillOps,\n lerpNumber,\n shadowOps,\n strokeOps,\n textOps,\n type DataRecord,\n type Fill,\n type Shadow,\n type ShadowResolved,\n type Stroke,\n type StrokeResolved,\n type TextStyle,\n} from \"@motionscript/sdk\"\nimport { niceStep } from \"@motionscript/sdk/component\"\n\nimport {\n CHART_PALETTE,\n DEFAULT_LEGEND,\n DEFAULT_PLOT_AREA,\n DEFAULT_SERIES_FILLS,\n DEFAULT_X_AXIS,\n DEFAULT_Y_AXIS,\n SPOTLIGHT_DIM,\n lerpAxisConfig,\n lerpLegendConfig,\n lerpPlotArea,\n lerpSeriesFills,\n num,\n resolveAxisConfig,\n resolveLegendConfig,\n resolvePlotArea,\n resolveSeriesFills,\n text,\n type AxisConfig,\n type ChartSeries,\n type LegendConfig,\n type LegendTheme,\n type PlotAreaConfig,\n type Range,\n} from \"../kit/shared\"\n\n/** One bar per row, beside its siblings in the category slot or stacked on them: {@link ChartSeries} under the name for what it draws here. */\nexport type BarSeries = ChartSeries\n\n/**\n * One bar's span in data units. A span rather than a height because both modes\n * fit it, and a negative value just runs the other way with no special case.\n */\nexport interface BarSpan {\n /** Where the base sits: 0 when grouped, the running total below when stacked. */\n from: number\n to: number\n /** `to - from`, kept for the figure printed on the bar. */\n value: number\n}\n\n/**\n * One row's spans, in series order. Stacking is a running sum in listed order,\n * so series 0 sits on the baseline. A zero value still yields a degenerate span,\n * keeping the list index-aligned with the series.\n */\nexport function barSpans(\n row: DataRecord,\n series: BarSeries[],\n stacked: boolean\n): BarSpan[] {\n let running = 0\n return series.map((s) => {\n const value = num(row, s.field)\n if (!stacked) return { from: 0, to: value, value }\n const from = running\n running += value\n return { from, to: running, value }\n })\n}\n\n/**\n * The series ending a row's stack, which gets the rounded cap; `-1` when the row\n * is all zero. It is the last non-zero series, so a zero one does not take the\n * cap and leave the segment below square.\n */\nexport function stackCapIndex(row: DataRecord, series: BarSeries[]): number {\n let last = -1\n for (let i = 0; i < series.length; i++) {\n if (num(row, series[i].field) !== 0) last = i\n }\n return last\n}\n\nexport function barCategories(data: DataRecord[], field: string): string[] {\n return data.map((row) => text(row, field))\n}\n\n/**\n * The `[min, max]` of everything drawn, zero always included: a scale starting\n * at 40 draws a column three times its neighbour for a 10% difference. A cropped\n * axis takes an explicit range.\n */\nexport function barValueExtent(\n data: DataRecord[],\n series: BarSeries[],\n stacked: boolean\n): Range {\n let lo = 0\n let hi = 0\n for (const row of data) {\n for (const span of barSpans(row, series, stacked)) {\n lo = Math.min(lo, span.from, span.to)\n hi = Math.max(hi, span.from, span.to)\n }\n }\n return lo < hi ? [lo, hi] : [0, 1]\n}\n\n/** The explicit `range`, else the data's extent nudged to tidy bounds; `divisions` (one fewer than the marker count) makes the drawn ticks land on them. */\nexport function resolveBarScale(\n data: DataRecord[],\n series: BarSeries[],\n stacked: boolean,\n range: Range | undefined,\n divisions: number\n): Range {\n if (range) return range\n const [lo, hi] = barValueExtent(data, series, stacked)\n const segments = Math.max(1, Math.round(divisions))\n const step = niceStep((hi - lo) / segments || 1)\n return [Math.floor(lo / step) * step, Math.ceil(hi / step) * step]\n}\n\n/** How the columns are drawn and the slot divided. */\nexport interface BarStyleConfig {\n /** Radius in px of a column's far-end corners; an interior stacked segment stays square. */\n cornerRadius: number\n /** Fraction of the category slot the bars fill, `[0, 1]`; the rest separates groups. */\n slotFill: number\n /** Gap in px between grouped bars within a slot; ignored when stacked. */\n groupGap: number\n stroke: Stroke\n shadow: Shadow\n}\n\n/** A {@link BarChart}'s full, resolved visual theme. */\nexport interface BarChartConfig {\n /** Cycled by series index; a series' own `fill` replaces its entry outright. */\n seriesFills: Fill[]\n bar: BarStyleConfig\n /** The category axis. */\n xAxis: AxisConfig\n /** The value axis. */\n yAxis: AxisConfig\n plotArea: PlotAreaConfig\n legend: LegendConfig\n /** The figure printed on each column. */\n valueStyle: TextStyle\n /** How far everything outside a spotlit series or category fades. */\n spotlight: { dimOpacity: number }\n}\n\n/** The author's partial theme, deep-merged onto {@link DEFAULT_BAR_CHART_THEME}. */\nexport type BarChartTheme = {\n seriesFills?: Fill[]\n bar?: Partial<BarStyleConfig>\n xAxis?: Partial<AxisConfig>\n yAxis?: Partial<AxisConfig>\n plotArea?: Partial<PlotAreaConfig>\n legend?: LegendTheme\n valueStyle?: TextStyle\n spotlight?: Partial<BarChartConfig[\"spotlight\"]>\n}\n\nexport const DEFAULT_BAR_CHART_THEME: BarChartConfig = {\n seriesFills: DEFAULT_SERIES_FILLS,\n bar: {\n cornerRadius: 6,\n slotFill: 0.72,\n groupGap: 6,\n stroke: [],\n shadow: [],\n },\n // Captions rather than numeric markers: less weight than the line chart's ticks.\n xAxis: {\n ...DEFAULT_X_AXIS,\n labelStyle: { ...DEFAULT_X_AXIS.labelStyle, fontWeight: 600 },\n tickPadding: 16,\n },\n yAxis: DEFAULT_Y_AXIS,\n plotArea: DEFAULT_PLOT_AREA,\n legend: DEFAULT_LEGEND,\n valueStyle: {\n fontSize: 24,\n fontWeight: 700,\n textAlign: \"center\",\n fill: CHART_PALETTE.markerColor,\n },\n spotlight: { dimOpacity: SPOTLIGHT_DIM },\n}\n\nfunction resolveBarStyle(\n bar: Partial<BarStyleConfig> | undefined,\n previous: BarStyleConfig\n): BarStyleConfig {\n return {\n cornerRadius: bar?.cornerRadius ?? previous.cornerRadius,\n slotFill: bar?.slotFill ?? previous.slotFill,\n groupGap: bar?.groupGap ?? previous.groupGap,\n stroke: strokeOps.resolve(bar?.stroke ?? previous.stroke),\n shadow: shadowOps.resolve(bar?.shadow ?? previous.shadow),\n }\n}\n\nfunction lerpBarStyle(\n from: BarStyleConfig,\n to: BarStyleConfig,\n t: number\n): BarStyleConfig {\n return {\n cornerRadius: lerpNumber(from.cornerRadius, to.cornerRadius, t),\n slotFill: lerpNumber(from.slotFill, to.slotFill, t),\n groupGap: lerpNumber(from.groupGap, to.groupGap, 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/** The `theme` entry's resolve: merges a partial {@link BarChartTheme} onto `previous` (first resolution: the default). */\nexport function resolveBarChartTheme(\n theme: BarChartTheme | undefined,\n previous?: BarChartConfig\n): BarChartConfig {\n const base = previous ?? DEFAULT_BAR_CHART_THEME\n return {\n seriesFills: resolveSeriesFills(theme?.seriesFills, base.seriesFills),\n bar: resolveBarStyle(theme?.bar, base.bar),\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 valueStyle: textOps.resolveStyle(theme?.valueStyle, base.valueStyle),\n spotlight: {\n dimOpacity: theme?.spotlight?.dimOpacity ?? base.spotlight.dimOpacity,\n },\n }\n}\n\nexport function lerpBarChartTheme(\n from: BarChartConfig,\n to: BarChartConfig,\n t: number\n): BarChartConfig {\n return {\n seriesFills: lerpSeriesFills(from.seriesFills, to.seriesFills, t),\n bar: lerpBarStyle(from.bar, to.bar, 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 valueStyle: textOps.lerpStyle(from.valueStyle, to.valueStyle, t),\n spotlight: {\n dimOpacity: lerpNumber(\n from.spotlight.dimOpacity,\n to.spotlight.dimOpacity,\n t\n ),\n },\n }\n}\n\n/** Series `index`'s own `fill`, else the palette's entry. */\nexport function resolveBarFill(\n palette: Fill[],\n series: BarSeries,\n index: number\n): Fill {\n if (series.fill != null) return fillOps.resolve(series.fill)\n if (palette.length === 0) return \"white\"\n return palette[index % palette.length]\n}\n"]}
@@ -0,0 +1,2 @@
1
+ import{fillOps as b,lerpNumber as y,shadowOps as M,strokeOps as g,insetsOps as w,textOps as S}from"@motionscript/sdk";function Xe(e,t){return{label:e?.label??t?.label??"",range:e?.range??t?.range,ticks:e?.ticks??t?.ticks,format:e?.format??t?.format}}function R(e,t,r){return{label:r<.5?e.label:t.label,range:pe(e.range,t.range,r),ticks:ge(e.ticks,t.ticks,r),format:r<.5?e.format:t.format}}function pe(e,t,r){return!e||!t?r<.5?e:t:[y(e[0],t[0],r),y(e[1],t[1],r)]}function ge(e,t,r){if(!e||!t)return r<.5?e:t;let n=Math.max(e.length,t.length),i=[];for(let o=0;o<n;o++)i.push(y(e[o]??t[o],t[o]??e[o],r));return i}function B(e){return e.blend}function Be(e,t,r){let n=t.range!==e.range,i=n&&t.range&&t.ticks&&t.ticks===e.ticks?{...t,ticks:we(t.range,Math.max(2,t.ticks.length)-1)}:t,o=B(e)!==void 0,l=o||n||i.ticks!==e.ticks,s=o||e.range===void 0||e.ticks===void 0||i.range===void 0||i.ticks===void 0;return!l||!s?R(e,i,r):r===0?e:r===1?i:{...R(e,i,r),blend:{from:e,to:i,t:r}}}function X(e,t){let r=B(e);return r?R(X(r.from,t),X(r.to,t),r.t):t(e)}var E={plotFill:"#15130e",borderColor:"#4a4036",gridColor:"#2c2820",markerColor:"#8a7f70",regionColor:"#d99a3a"},H=["#d9603b","#8194ad","#e0a93b","#5e9d6b","#9ec85a"],Y=.2;function He(e,t){if(t===void 0)return 0;let r=e[t];return typeof r=="number"&&Number.isFinite(r)?r:0}function Ye(e,t){if(t===void 0||t==="")return"";let r=e[t];return r==null?"":String(r)}function $e(e,t=[]){if(e.length===0)return[];let r=new Set(t),n=new Set,i=[];for(let o of e)for(let l of Object.keys(o))!r.has(l)&&!n.has(l)&&(n.add(l),i.push(l));return i.filter(o=>{let l=!1;for(let s of e){let a=s[o];if(!(a===void 0||a==="")){if(typeof a!="number")return!1;l=!0}}return l})}var $={fontSize:24,fontWeight:700,textAlign:"center",fill:E.markerColor},V={fontSize:30,fontWeight:600,textAlign:"center",fill:E.markerColor},W={weight:2,fill:E.gridColor},j={labelStyle:$,titleStyle:V,lineStyle:W,tickPadding:20,titlePadding:4},O={labelStyle:{...$,fontWeight:500,textAlign:"right"},titleStyle:V,lineStyle:W,tickPadding:40,titlePadding:24},A={fill:[],stroke:{weight:6,fill:E.borderColor},shadow:[]},K={padding:0,textStyle:{fontSize:30,fontWeight:600,textAlign:"left",fill:E.markerColor},itemGap:44,markerStyle:{width:60,height:24,borderRadius:6,stroke:[],shadow:[]}},Ve=H.map(e=>({weight:4,fill:e})),We=H.map(e=>e);function je(e,t){return{labelStyle:S.resolveStyle(e?.labelStyle,t.labelStyle),titleStyle:S.resolveStyle(e?.titleStyle,t.titleStyle),lineStyle:g.resolve(e?.lineStyle??t.lineStyle),tickPadding:w.resolve(e?.tickPadding??t.tickPadding,t.tickPadding),titlePadding:w.resolve(e?.titlePadding??t.titlePadding,t.titlePadding)}}function Ke(e,t,r){return{labelStyle:S.lerpStyle(e.labelStyle,t.labelStyle,r),titleStyle:S.lerpStyle(e.titleStyle,t.titleStyle,r),lineStyle:g.lerp(e.lineStyle,t.lineStyle,r),tickPadding:w.lerp(e.tickPadding,t.tickPadding,r),titlePadding:w.lerp(e.titlePadding,t.titlePadding,r)}}function qe(e,t){return{fill:b.resolve(e?.fill??t.fill),stroke:g.resolve(e?.stroke??t.stroke),shadow:M.resolve(e?.shadow??t.shadow)}}function Je(e,t,r){return{fill:b.lerp(e.fill,t.fill,r),stroke:g.lerp(e.stroke,t.stroke,r),shadow:M.lerp(e.shadow,t.shadow,r)}}function xe(e,t){return{width:e?.width??t.width,height:e?.height??t.height,borderRadius:e?.borderRadius??t.borderRadius,stroke:g.resolve(e?.stroke??t.stroke),shadow:M.resolve(e?.shadow??t.shadow)}}function me(e,t,r){return{width:y(e.width,t.width,r),height:y(e.height,t.height,r),borderRadius:y(e.borderRadius,t.borderRadius,r),stroke:g.lerp(e.stroke,t.stroke,r),shadow:M.lerp(e.shadow,t.shadow,r)}}function Qe(e,t){return{padding:w.resolve(e?.padding??t.padding,t.padding),textStyle:S.resolveStyle(e?.textStyle,t.textStyle),itemGap:e?.itemGap??t.itemGap,markerStyle:xe(e?.markerStyle,t.markerStyle)}}function Ze(e,t,r){return{padding:w.lerp(e.padding,t.padding,r),textStyle:S.lerpStyle(e.textStyle,t.textStyle,r),itemGap:y(e.itemGap,t.itemGap,r),markerStyle:me(e.markerStyle,t.markerStyle,r)}}function et(e,t){return(e??t).map(r=>g.resolve(r))}function tt(e,t,r){let n=Math.max(e.length,t.length),i=[];for(let o=0;o<n;o++){let l=e[o]??t[o],s=t[o]??e[o];i.push(g.lerp(l,s,r))}return i}function rt(e,t){return(e??t).map(r=>b.resolve(r))}function nt(e,t,r){let n=Math.max(e.length,t.length),i=[];for(let o=0;o<n;o++){let l=e[o]??t[o],s=t[o]??e[o];i.push(b.lerp(l,s,r))}return i}function ye(e,t,r){let n=e.length>0?e[r%e.length]:{weight:4,fill:"white"};if(t.fill==null)return n;let i=g.resolve(n);if(i.length===0)return{weight:4,fill:t.fill};let o=[...i];return o[o.length-1]={...o[o.length-1],fill:b.resolve(t.fill)},o}function ot(e,t,r){let n=g.resolve(ye(e,t,r));return n[n.length-1]?.fill??"white"}function q(e,t){if(Number.isInteger(e))return String(e);let r=Math.max(1,t===void 0?1:ke(t));return e.toFixed(r).replace(/(\.\d*?)0+$/,"$1").replace(/\.$/,"")}function ke(e){if(!(e>0)||!Number.isFinite(e))return 1;for(let t=0;t<=6;t++){let r=e*10**t;if(Math.abs(r-Math.round(r))<1e-6*Math.max(1,r))return t}return Math.min(6,Math.max(1,Math.ceil(-Math.log10(e))+1))}function it(e){let t=[...e].filter(Number.isFinite).sort((n,i)=>n-i),r;for(let n=1;n<t.length;n++){let i=t[n]-t[n-1];i>1e-12&&(r===void 0||i<r)&&(r=i)}return r}function lt(e){let t=e*100;return Number.isInteger(t)?`${t}%`:`${t.toFixed(1).replace(/\.0$/,"")}%`}function we([e,t],r){let n=Math.max(2,Math.round(r));return Array.from({length:n+1},(i,o)=>e+(t-e)/n*o)}import{Rect as P}from"@motionscript/sdk";import{Rect as te,RotatedBox as ve,Text as re,Types as C,component2d as Le,insetsOps as ne,textOps as oe}from"@motionscript/sdk";import{enterBudget as Pe}from"@motionscript/sdk/component";import{Types as J}from"@motionscript/sdk";function h(e,t){return J.custom(e,t)}function Se(e){return e}var ct=J.custom(0,{kind:"series",min:0,step:1});import{Types as be,easeOut as Ee}from"@motionscript/sdk";var Ae=e=>e,ft=20,ut=5,pt={axes:.35,marks:.5,legend:.15};function v(e){return e.easing?Ae:Ee()}function Q(e,t){let r=e.duration,n=t.reduce((o,l)=>Math.max(o,l.at+l.duration),0),i=n>r&&n>0?r/n:1;return e.together(t.map(({at:o,duration:l,piece:s})=>{let a=o*i,f=l*i;return e.sequence([e.wait(a),s,e.wait(Math.max(0,r-a-f))])}))}var D={opacity:1,shift:0};function Z(){return be.custom({},{private:!0,resolve:(e,t)=>({...t,...e})})}function L(e,t){return e[t]??D}function ee(e,t){let r={};for(let n of e)r[n]=t;return r}function G(e,t,r,n){return e.animate(i=>{let o=n(i);return{arrivals:{[t]:{opacity:r.opacity+(D.opacity-r.opacity)*o,shift:r.shift+(D.shift-r.shift)*o}}}})}var Te=24;function _e(e,t){let r=e.markers.indexOf(t);return(r>=0?e.captions[r]:void 0)??q(t)}var ie=Le({key:"verticalAxis",state:{range:h(()=>[0,1]),markers:h(()=>[]),captions:h(()=>[]),axis:C.custom(O),label:"",arrivals:Z()},defaults:{width:"fill",height:"fill"},children:e=>{let t=ne.resolve(e.axis.tickPadding).right,r=ne.resolve(e.axis.titlePadding).right,n=[],i=()=>n[0]?.parent?.layoutBounds??{width:0,height:0},o=()=>[...e.markers].sort((f,c)=>c-f),l=f=>{if(f===void 0)return 0;let[c,p]=e.range;return p<=c?0:(f-c)/(p-c)},s=e.markers.map((f,c)=>{let p=new re({...oe.styleProps(e.axis.labelStyle),text:()=>{let u=o()[c];return u===void 0?"":_e(e,u)},y:()=>{let u=i().height,d=(l(o()[c])-.5)*u,m=u/2-p.layoutBounds.height/2;return Math.min(d,m)},opacity:()=>L(e.arrivals,c).opacity,x:()=>L(e.arrivals,c).shift});return p}),a=[];return e.label!==""&&a.push(new ve({angle:-90,width:"hug",height:"hug",children:new re({...oe.styleProps(e.axis.titleStyle),text:e.label,opacity:()=>L(e.arrivals,"label").opacity,x:()=>L(e.arrivals,"label").shift})})),a.push(new te({height:"fill",width:"hug",padding:{right:t},children:s})),n.push(new te({flow:"horizontal",gap:r,children:a})),n},commands:{enter:{args:{stagger:C.custom(void 0),slide:C.number(Te)},run:(e,t)=>{let{stagger:r,slide:n}=e.args,i=t.markers.length,o=t.label!=="",l={opacity:0,shift:n},s=[...t.markers.keys(),...o?["label"]:[]],a=e.animate(()=>({arrivals:ee(s,l)}));if(i===0)return a;let{step:f,per:c,caption:p}=Pe(e.duration,i,o,r),u=v(e),d=t.markers.map((k,N)=>({at:(i-1-N)*f,duration:c,piece:G(e,N,l,u)})),m=o?[{at:(i-1)*f+c,duration:p,piece:G(e,"label",l,u)}]:[];return e.together([a,Q(e,[...d,...m])])}}}});var Me=24;function At(e){return new P({flow:"vertical",width:"fill",height:"fill",padding:{top:Me},children:[new P({flow:"horizontal",height:"fill",width:"fill",children:[e.axis,e.plot]}),new P({flow:"horizontal",width:"fill",children:[e.gutter,new P({flow:"vertical",width:"fill",gap:20,children:[...e.below]})]})]})}function vt(e){for(let t=e.length-1;t>=0;t--){let r=e[t];if(!P.is(r))continue;let[n,i]=r.children,o=n?.children[0],l=n?.children[1],s=i?.children[1];if(!(!o||!ie.is(o)||!l||!s))return{axis:o,plot:l.children,below:s.children}}return null}function Lt(e){let t=e?.layoutBounds;return{width:t?.width??0,height:t?.height??0}}import{Graphics2D as Oe,Types as Fe,component2d as Re,strokeOps as le}from"@motionscript/sdk";function F(e,t){for(let r of t.fills??[])e.fill(r);for(let r of t.strokes??[])for(let n of r)e.fill(n.fill);for(let r of t.shadows??[])for(let n of r)e.fill(n.fill)}var Ft=Re({key:"chartBorder",state:{stroke:Fe.custom(A.stroke,{resolve:le.resolve,lerp:le.lerp})},load:(e,t)=>F(e,{strokes:[t.stroke]}),render:(e,t)=>{let{width:r,height:n}=e.size;r<=0||n<=0||e.draw(new Oe().rect({x:0,y:0,width:r,height:n}).stroke(t.stroke))}});import{Graphics2D as I,Types as z,component2d as De,fillOps as se,shadowOps as ae,strokeOps as ce}from"@motionscript/sdk";var de=e=>z.custom(e,{resolve:ce.resolve,lerp:ce.lerp}),zt=De({key:"chartCanvas",state:{fill:z.custom(A.fill,{resolve:se.resolve,lerp:se.lerp}),shadow:z.custom(A.shadow,{resolve:ae.resolve,lerp:ae.lerp}),xGridStroke:de(j.lineStyle),yGridStroke:de(O.lineStyle),xMarkers:h(()=>[]),yMarkers:h(()=>[]),xExtent:h(()=>[0,1]),yExtent:h(()=>[0,1])},load:(e,t)=>F(e,{fills:[t.fill],shadows:[t.shadow],strokes:[t.xGridStroke,t.yGridStroke]}),render:(e,t)=>{let{width:r,height:n}=e.size;if(r<=0||n<=0)return;e.draw(new I().rect({x:0,y:0,width:r,height:n}).shadow(t.shadow).fill(t.fill));let[i,o]=t.xExtent,[l,s]=t.yExtent,a=d=>o<=i?0:(d-i)/(o-i),f=d=>s<=l?0:(d-l)/(s-l),c=d=>d>1e-6&&d<1-1e-6,p=t.xGridStroke[0];if(p){let d=new I;for(let m of t.xMarkers){let k=a(m);c(k)&&d.rect({x:-r/2+k*r,y:0,width:p.weight,height:n})}e.draw(d.fill(p.fill))}let u=t.yGridStroke[0];if(u){let d=new I;for(let m of t.yMarkers){let k=f(m);c(k)&&d.rect({x:0,y:-n/2+k*n,width:r,height:u.weight})}e.draw(d.fill(u.fill))}}});import{Flow as _,Paint as x,Rect as Ge,Shapes as U,Text as Ce,Types as T,component2d as fe,textOps as Ie}from"@motionscript/sdk";var ue={...x.state,..._.state,...U.corners},ze=fe({key:"legendEntry",state:{...ue,shown:T.number(1)},commands:{...x.commands},measure:(e,t,r)=>{let n=_.measure(e,t,r,x.inset(t));return t.shown>=1?n:{...n,width:t.shown*n.width}},layout:(e,t,r)=>_.layout(e,t,r,x.inset(t)),render:(e,t)=>x.draw(e,t,U.rect(e.size,t))});function Ue(e,t){if(Array.isArray(e))return e;let r=[...t??[]];for(let[n,i]of Object.entries(e))r[Number(n)]=i;return r}var Yt=fe({key:"chartLegend",state:{...ue,series:h(()=>[]),swatches:h(()=>[]),legend:T.custom(K),reveal:h(()=>[],{resolve:Ue})},defaults:{flow:"horizontal",width:"hug",height:"hug",gap:e=>e.legend.itemGap,padding:e=>e.legend.padding,reveal:e=>e.series.map(t=>t.enabled??!0?1:0)},children:e=>{let t=e.legend.markerStyle;return e.series.map((r,n)=>ze({flow:"horizontal",gap:12,align:"center",width:"hug",height:"hug",opacity:()=>e.reveal[n]??0,gapScale:()=>e.reveal[n]??0,shown:()=>e.reveal[n]??0,children:[Ce({...Ie.styleProps(e.legend.textStyle),text:r.label}),Ge({width:t.width,height:t.height,cornerRadius:t.borderRadius,fill:e.swatches[n]??"white",stroke:t.stroke,shadow:t.shadow})]}))},commands:{...x.commands,showSeries:{args:{index:T.number(0,{min:0,step:1})},run:(e,t)=>e.args.index in t.series?e.animate(he(t,e.args.index,1,v(e))):e.wait(e.duration)},hideSeries:{args:{index:T.number(0,{min:0,step:1})},run:(e,t)=>e.args.index in t.series?e.animate(he(t,e.args.index,0,v(e))):e.wait(e.duration)},spotlightSeries:{args:{index:T.number(0,{min:0,step:1})},run:(e,t,r)=>e.together(r.flatMap((n,i)=>(t.reveal[i]??0)>0?[n.to({opacity:i===e.args.index?1:Y})]:[]))}},measure:(e,t,r)=>_.measure(e,t,r,x.inset(t)),layout:(e,t,r)=>_.layout(e,t,r,x.inset(t)),render:(e,t)=>x.draw(e,t,U.rect(e.size,t))});function he(e,t,r,n){let i=e.reveal[t]??0;return o=>({reveal:{[t]:i+(r-i)*n(o)}})}export*from"@motionscript/sdk/component";export{h as a,Se as b,ct as c,ft as d,ut as e,pt as f,v as g,Q as h,Z as i,L as j,ee as k,G as l,Xe as m,R as n,Be as o,X as p,E as q,H as r,Y as s,He as t,Ye as u,$e as v,j as w,O as x,A as y,K as z,Ve as A,We as B,je as C,Ke as D,qe as E,Je as F,Qe as G,Ze as H,et as I,tt as J,rt as K,nt as L,ye as M,ot as N,q as O,it as P,lt as Q,we as R,_e as S,ie as T,At as U,vt as V,Lt as W,F as X,Ft as Y,zt as Z,Yt as _};
2
+ //# sourceMappingURL=chunk-4SMRCU24.js.map
@@ -0,0 +1,7 @@
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
+ }