@motionscript/charts 0.1.1-alpha.2 → 0.1.1-alpha.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +8 -0
- package/README.md +7 -9
- package/dist/bar-chart/bar-chart.d.ts +48 -48
- package/dist/bar-chart/bar-chart.js +2 -2
- package/dist/bar-chart/bar-chart.js.map +1 -1
- package/dist/bar-chart/shared.d.ts +2 -1
- package/dist/bar-chart/shared.d.ts.map +1 -1
- package/dist/bar-chart/shared.js +2 -0
- package/dist/bar-chart/shared.js.map +1 -1
- package/dist/browser/chunks/chunk-FJHNBNPQ.js +2 -0
- package/dist/browser/chunks/chunk-FJHNBNPQ.js.map +7 -0
- package/dist/browser/index.js +1 -1
- package/dist/browser/index.js.map +3 -3
- package/dist/browser/kit.js +1 -1
- package/dist/browser/manifest.json +1 -1
- package/dist/kit/style.d.ts +25 -20
- package/dist/kit/style.d.ts.map +1 -1
- package/dist/kit/style.js +20 -18
- package/dist/kit/style.js.map +1 -1
- package/dist/line-chart/line-chart.d.ts +48 -48
- package/dist/line-chart/line-chart.js +2 -2
- package/dist/line-chart/line-chart.js.map +1 -1
- package/dist/line-chart/shared.d.ts +2 -1
- package/dist/line-chart/shared.d.ts.map +1 -1
- package/dist/line-chart/shared.js +2 -0
- package/dist/line-chart/shared.js.map +1 -1
- package/dist/pie-chart/pie-chart.d.ts +18 -24
- package/dist/pie-chart/pie-chart.d.ts.map +1 -1
- package/dist/pie-chart/shared.d.ts +7 -9
- package/dist/pie-chart/shared.d.ts.map +1 -1
- package/dist/pie-chart/shared.js +7 -10
- package/dist/pie-chart/shared.js.map +1 -1
- package/dist/radar-chart/index.d.ts +1 -1
- package/dist/radar-chart/index.d.ts.map +1 -1
- package/dist/radar-chart/index.js +1 -1
- package/dist/radar-chart/index.js.map +1 -1
- package/dist/radar-chart/radar-chart.d.ts +6 -12
- package/dist/radar-chart/radar-chart.d.ts.map +1 -1
- package/dist/radar-chart/radar-chart.js +1 -2
- package/dist/radar-chart/radar-chart.js.map +1 -1
- package/dist/radar-chart/shared.d.ts +2 -5
- package/dist/radar-chart/shared.d.ts.map +1 -1
- package/dist/radar-chart/shared.js +3 -6
- package/dist/radar-chart/shared.js.map +1 -1
- package/dist/radial-chart/radial-chart.d.ts +12 -18
- package/dist/radial-chart/radial-chart.d.ts.map +1 -1
- package/dist/radial-chart/shared.d.ts +5 -7
- package/dist/radial-chart/shared.d.ts.map +1 -1
- package/dist/radial-chart/shared.js +5 -8
- package/dist/radial-chart/shared.js.map +1 -1
- package/package.json +4 -4
- package/src/bar-chart/bar-chart.ts +2 -2
- package/src/bar-chart/shared.ts +3 -0
- package/src/kit/style.ts +21 -19
- package/src/line-chart/line-chart.ts +2 -2
- package/src/line-chart/shared.ts +3 -1
- package/src/pie-chart/shared.ts +6 -10
- package/src/radar-chart/index.ts +1 -1
- package/src/radar-chart/radar-chart.ts +0 -2
- package/src/radar-chart/shared.ts +3 -7
- package/src/radial-chart/shared.ts +4 -8
- package/dist/browser/chunks/chunk-7XCRX6GE.js +0 -2
- package/dist/browser/chunks/chunk-7XCRX6GE.js.map +0 -7
package/src/kit/style.ts
CHANGED
|
@@ -3,8 +3,9 @@
|
|
|
3
3
|
* below, so a look saved off one chart lays onto any other (a field the other
|
|
4
4
|
* chart does not draw is dropped). A chart spreads the shared groups and adds a
|
|
5
5
|
* `marks` group of its own. Every run of text a chart draws is its own
|
|
6
|
-
* `Types.typography` field,
|
|
7
|
-
*
|
|
6
|
+
* `Types.typography` field, set the way a text node is, in the group of the
|
|
7
|
+
* part it labels: axis text with its axis, values with the labels, the
|
|
8
|
+
* legend's captions with the legend.
|
|
8
9
|
*/
|
|
9
10
|
|
|
10
11
|
import {
|
|
@@ -49,23 +50,9 @@ export const GRID_BACKGROUND = {
|
|
|
49
50
|
gridBackground: Types.fill([]),
|
|
50
51
|
}
|
|
51
52
|
|
|
52
|
-
/** The
|
|
53
|
-
export const
|
|
54
|
-
legendText: Types.typography({ fontSize: 28, fontWeight: 500, fill: CHART_FOREGROUND }),
|
|
55
|
-
}
|
|
56
|
-
|
|
57
|
-
export const CARTESIAN_TEXT = {
|
|
58
|
-
/** The markers under the plot: categories on a column chart, values on a horizontal bar chart. */
|
|
59
|
-
xLabelText: Types.typography({ fontSize: 28, fontWeight: 500, fill: CHART_MUTED }),
|
|
60
|
-
/** The caption under the plot. */
|
|
61
|
-
xTitleText: Types.typography({ fontSize: 31, fontWeight: 600, fill: CHART_MUTED }),
|
|
62
|
-
/** The markers beside the plot. */
|
|
63
|
-
yLabelText: Types.typography({ fontSize: 28, fontWeight: 500, fill: CHART_MUTED }),
|
|
64
|
-
/** The caption beside the plot, turned on its side. */
|
|
65
|
-
yTitleText: Types.typography({ fontSize: 31, fontWeight: 600, fill: CHART_MUTED }),
|
|
66
|
-
/** The figures printed by the marks. */
|
|
53
|
+
/** The figures printed by the marks, for a chart's `labels` group. */
|
|
54
|
+
export const VALUE_TEXT = {
|
|
67
55
|
valueText: Types.typography({ fontSize: 24, fontWeight: 600, fill: CHART_FOREGROUND }),
|
|
68
|
-
...LEGEND_TEXT,
|
|
69
56
|
}
|
|
70
57
|
|
|
71
58
|
export const CARTESIAN_GRID = {
|
|
@@ -73,12 +60,23 @@ export const CARTESIAN_GRID = {
|
|
|
73
60
|
horizontalGrid: Types.stroke({ weight: 2, fill: "white/15" }),
|
|
74
61
|
/** The lines under the category markers; empty draws none. */
|
|
75
62
|
verticalGrid: Types.stroke([]),
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
export const CARTESIAN_AXES = {
|
|
76
66
|
/** The baseline and the value-axis rule; empty draws none. */
|
|
77
67
|
axisStroke: Types.stroke([]),
|
|
78
68
|
/** Read as the chart is built: whether the category (x) axis row is drawn. */
|
|
79
69
|
showXAxis: Types.boolean(true, { animatable: false }),
|
|
70
|
+
/** The markers under the plot: categories on a column chart, values on a horizontal bar chart. */
|
|
71
|
+
xLabelText: Types.typography({ fontSize: 28, fontWeight: 500, fill: CHART_MUTED }),
|
|
72
|
+
/** The caption under the plot. */
|
|
73
|
+
xTitleText: Types.typography({ fontSize: 31, fontWeight: 600, fill: CHART_MUTED }),
|
|
80
74
|
/** Read as the chart is built: whether the value (y) axis column is drawn. */
|
|
81
75
|
showYAxis: Types.boolean(true, { animatable: false }),
|
|
76
|
+
/** The markers beside the plot. */
|
|
77
|
+
yLabelText: Types.typography({ fontSize: 28, fontWeight: 500, fill: CHART_MUTED }),
|
|
78
|
+
/** The caption beside the plot, turned on its side. */
|
|
79
|
+
yTitleText: Types.typography({ fontSize: 31, fontWeight: 600, fill: CHART_MUTED }),
|
|
82
80
|
}
|
|
83
81
|
|
|
84
82
|
export type LegendPosition = "bottom" | "top" | "right" | "none"
|
|
@@ -88,6 +86,8 @@ export const CHART_LEGEND = {
|
|
|
88
86
|
/** Read as the chart is built: where the legend sits, or `none`. */
|
|
89
87
|
legend: Types.oneOf(["bottom", "top", "right", "none"] as const, { animatable: false }),
|
|
90
88
|
swatch: Types.oneOf(["square", "circle", "line"] as const),
|
|
89
|
+
/** The legend's captions. */
|
|
90
|
+
legendText: Types.typography({ fontSize: 28, fontWeight: 500, fill: CHART_FOREGROUND }),
|
|
91
91
|
}
|
|
92
92
|
|
|
93
93
|
/** The fields every chart's style resolves, whichever groups it spreads. */
|
|
@@ -118,7 +118,9 @@ export interface CartesianStyle extends ChartStyleBase {
|
|
|
118
118
|
const _PRESET_FIELDS = {
|
|
119
119
|
...CHART_SERIES,
|
|
120
120
|
...GRID_BACKGROUND,
|
|
121
|
-
...
|
|
121
|
+
...CARTESIAN_AXES,
|
|
122
|
+
...VALUE_TEXT,
|
|
123
|
+
legendText: CHART_LEGEND.legendText,
|
|
122
124
|
labelText: Types.typography(),
|
|
123
125
|
centerText: Types.typography(),
|
|
124
126
|
spokeText: Types.typography(),
|
|
@@ -47,7 +47,7 @@ import {
|
|
|
47
47
|
} from "../kit/shared"
|
|
48
48
|
import {
|
|
49
49
|
CARTESIAN_GRID,
|
|
50
|
-
|
|
50
|
+
CARTESIAN_AXES,
|
|
51
51
|
CHART_LEGEND,
|
|
52
52
|
CHART_SERIES,
|
|
53
53
|
CHART_STYLE_FAMILY,
|
|
@@ -79,7 +79,7 @@ import { resolveXScale, type XScale } from "./x-scale"
|
|
|
79
79
|
|
|
80
80
|
const LINE_STYLE = Types.style(
|
|
81
81
|
CHART_STYLE_FAMILY,
|
|
82
|
-
{ series: CHART_SERIES, background: GRID_BACKGROUND,
|
|
82
|
+
{ series: CHART_SERIES, background: GRID_BACKGROUND, grid: CARTESIAN_GRID, axes: CARTESIAN_AXES, marks: LINE_MARKS, labels: LINE_LABELS, legend: CHART_LEGEND },
|
|
83
83
|
{ presets: CHART_STYLE_PRESETS }
|
|
84
84
|
)
|
|
85
85
|
|
package/src/line-chart/shared.ts
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
|
-
import { Types, type DataRecord, type Vector2 } from "@motionscript/sdk"
|
|
1
|
+
import { Types, type DataRecord, type Vector2, type TextStyle as _TextStyle } from "@motionscript/sdk"
|
|
2
2
|
|
|
3
3
|
import { niceRange, num, type ChartSeries, type Range } from "../kit/shared"
|
|
4
|
+
import { VALUE_TEXT } from "../kit/style"
|
|
4
5
|
import type { XScale } from "./x-scale"
|
|
5
6
|
|
|
6
7
|
/** One polyline of a {@link LineChart}: {@link ChartSeries} under the name for what it draws here. */
|
|
@@ -395,4 +396,5 @@ export const LINE_MARKS = {
|
|
|
395
396
|
export const LINE_LABELS = {
|
|
396
397
|
/** Read as the chart is built: each point's value printed above or below it, or none. */
|
|
397
398
|
values: Types.oneOf(["none", "above", "below"] as const, { animatable: false }),
|
|
399
|
+
...VALUE_TEXT,
|
|
398
400
|
}
|
package/src/pie-chart/shared.ts
CHANGED
|
@@ -6,7 +6,6 @@ import {
|
|
|
6
6
|
CHART_LEGEND,
|
|
7
7
|
CHART_MUTED,
|
|
8
8
|
CHART_SERIES,
|
|
9
|
-
LEGEND_TEXT,
|
|
10
9
|
legendConfigOf,
|
|
11
10
|
placedText,
|
|
12
11
|
sizeOf,
|
|
@@ -165,15 +164,6 @@ export interface PieStyle extends ChartStyleBase {
|
|
|
165
164
|
export const PIE_STYLE_GROUPS = {
|
|
166
165
|
series: CHART_SERIES,
|
|
167
166
|
background: CHART_BACKGROUND,
|
|
168
|
-
text: {
|
|
169
|
-
/** Each slice's name. */
|
|
170
|
-
labelText: Types.typography({ fontSize: 28, fontWeight: 500, fill: CHART_MUTED }),
|
|
171
|
-
/** Each slice's share or value, beside its name; inside a wedge both are set larger, inked for contrast. */
|
|
172
|
-
valueText: Types.typography({ fontSize: 28, fontWeight: 700, fill: CHART_FOREGROUND }),
|
|
173
|
-
/** The summary in the hole; its caption is set smaller, in the slice names' ink. */
|
|
174
|
-
centerText: Types.typography({ fontSize: 50, fontWeight: 800, fill: CHART_FOREGROUND }),
|
|
175
|
-
...LEGEND_TEXT,
|
|
176
|
-
},
|
|
177
167
|
marks: {
|
|
178
168
|
/** Hole radius as a fraction of the outer radius: 0 is a pie, about 0.6 a donut. */
|
|
179
169
|
innerRadius: Types.number(0, { min: 0, max: 0.9, step: 0.05 }),
|
|
@@ -185,6 +175,12 @@ export const PIE_STYLE_GROUPS = {
|
|
|
185
175
|
labels: {
|
|
186
176
|
/** Read as the chart is built: inside the wedge, outside on a leader, or none. */
|
|
187
177
|
labelPlacement: Types.oneOf(["inside", "outside", "none"] as const, { animatable: false }),
|
|
178
|
+
/** Each slice's name. */
|
|
179
|
+
labelText: Types.typography({ fontSize: 28, fontWeight: 500, fill: CHART_MUTED }),
|
|
180
|
+
/** Each slice's share or value, beside its name; inside a wedge both are set larger, inked for contrast. */
|
|
181
|
+
valueText: Types.typography({ fontSize: 28, fontWeight: 700, fill: CHART_FOREGROUND }),
|
|
182
|
+
/** The summary in the hole; its caption is set smaller, in the slice names' ink. */
|
|
183
|
+
centerText: Types.typography({ fontSize: 50, fontWeight: 800, fill: CHART_FOREGROUND }),
|
|
188
184
|
},
|
|
189
185
|
legend: CHART_LEGEND,
|
|
190
186
|
}
|
package/src/radar-chart/index.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
1
|
export { RadarChart, radarFractions, radarScale, type RadarValues } from "./radar-chart"
|
|
2
2
|
export { RadarGrid } from "./radar-grid"
|
|
3
3
|
export { RadarSeries, seriesVertices } from "./radar-series"
|
|
4
|
-
export { RADAR_GRID, RADAR_MARKS,
|
|
4
|
+
export { RADAR_GRID, RADAR_MARKS, fitRadius, niceCeil, spokeDirection } from "./shared"
|
|
@@ -40,7 +40,6 @@ import { RadarGrid } from "./radar-grid"
|
|
|
40
40
|
import { RadarSeries } from "./radar-series"
|
|
41
41
|
import {
|
|
42
42
|
RADAR_GRID,
|
|
43
|
-
RADAR_TEXT,
|
|
44
43
|
RADAR_MARKS,
|
|
45
44
|
categoriesOf,
|
|
46
45
|
fitRadius,
|
|
@@ -130,7 +129,6 @@ export const RadarChart = component2d({
|
|
|
130
129
|
{
|
|
131
130
|
series: CHART_SERIES,
|
|
132
131
|
background: GRID_BACKGROUND,
|
|
133
|
-
text: RADAR_TEXT,
|
|
134
132
|
grid: RADAR_GRID,
|
|
135
133
|
marks: RADAR_MARKS,
|
|
136
134
|
legend: CHART_LEGEND,
|
|
@@ -1,13 +1,7 @@
|
|
|
1
1
|
import { Types, type TextStyle, type DataRecord, type Size2D, type StrokeResolved, type Stroke as _Stroke, type Vector2 } from "@motionscript/sdk"
|
|
2
2
|
|
|
3
3
|
import { num, text, type ChartSeries } from "../kit/shared"
|
|
4
|
-
import { CHART_MUTED
|
|
5
|
-
|
|
6
|
-
/** The radar chart's text: the category names around the rim, and the legend. */
|
|
7
|
-
export const RADAR_TEXT = {
|
|
8
|
-
spokeText: Types.typography({ fontSize: 28, fontWeight: 500, fill: CHART_MUTED }),
|
|
9
|
-
...LEGEND_TEXT,
|
|
10
|
-
}
|
|
4
|
+
import { CHART_MUTED } from "../kit/style"
|
|
11
5
|
|
|
12
6
|
export type GridShape = "polygon" | "circle"
|
|
13
7
|
|
|
@@ -23,6 +17,8 @@ export const RADAR_GRID = {
|
|
|
23
17
|
spokeStroke: Types.stroke({ weight: 2, fill: "white/15" }),
|
|
24
18
|
/** Read as the chart is built: whether the category names stand around the rim. */
|
|
25
19
|
spokeLabels: Types.boolean(true, { animatable: false }),
|
|
20
|
+
/** The category names around the rim. */
|
|
21
|
+
spokeText: Types.typography({ fontSize: 28, fontWeight: 500, fill: CHART_MUTED }),
|
|
26
22
|
}
|
|
27
23
|
|
|
28
24
|
export const RADAR_MARKS = {
|
|
@@ -6,7 +6,6 @@ import {
|
|
|
6
6
|
CHART_LEGEND,
|
|
7
7
|
CHART_MUTED,
|
|
8
8
|
CHART_SERIES,
|
|
9
|
-
LEGEND_TEXT,
|
|
10
9
|
legendConfigOf,
|
|
11
10
|
paletteFill,
|
|
12
11
|
placedText,
|
|
@@ -70,13 +69,6 @@ export interface RadialStyle extends ChartStyleBase {
|
|
|
70
69
|
export const RADIAL_STYLE_GROUPS = {
|
|
71
70
|
series: CHART_SERIES,
|
|
72
71
|
background: CHART_BACKGROUND,
|
|
73
|
-
text: {
|
|
74
|
-
/** The category at each ring's start, and the caption under the centre. */
|
|
75
|
-
labelText: Types.typography({ fontSize: 28, fontWeight: 500, fill: CHART_MUTED }),
|
|
76
|
-
/** The summary in the middle. */
|
|
77
|
-
centerText: Types.typography({ fontSize: 50, fontWeight: 800, fill: CHART_FOREGROUND }),
|
|
78
|
-
...LEGEND_TEXT,
|
|
79
|
-
},
|
|
80
72
|
marks: {
|
|
81
73
|
/** Where the innermost ring starts, as a fraction of the outer radius. */
|
|
82
74
|
innerRadius: Types.number(0.3, { min: 0, max: 0.9, step: 0.05 }),
|
|
@@ -94,6 +86,10 @@ export const RADIAL_STYLE_GROUPS = {
|
|
|
94
86
|
labels: {
|
|
95
87
|
/** The category written at each ring's start, set in the label text. */
|
|
96
88
|
ringLabels: Types.boolean(false),
|
|
89
|
+
/** The category at each ring's start, and the caption under the centre. */
|
|
90
|
+
labelText: Types.typography({ fontSize: 28, fontWeight: 500, fill: CHART_MUTED }),
|
|
91
|
+
/** The summary in the middle. */
|
|
92
|
+
centerText: Types.typography({ fontSize: 50, fontWeight: 800, fill: CHART_FOREGROUND }),
|
|
97
93
|
},
|
|
98
94
|
legend: CHART_LEGEND,
|
|
99
95
|
}
|
|
@@ -1,2 +0,0 @@
|
|
|
1
|
-
import{lerpNumber as X}from"@motionscript/sdk";import{niceStep as $}from"@motionscript/sdk/component";function St(e,t){return{label:e?.label??t?.label??"",range:e?.range??t?.range,ticks:e?.ticks??t?.ticks,format:e?.format??t?.format}}function Y(e,t,r){return{label:r<.5?e.label:t.label,range:Ce(e.range,t.range,r),ticks:Ie(e.ticks,t.ticks,r),format:r<.5?e.format:t.format}}function Ce(e,t,r){return!e||!t?r<.5?e:t:[X(e[0],t[0],r),X(e[1],t[1],r)]}function Ie(e,t,r){if(!e||!t)return r<.5?e:t;let n=Math.max(e.length,t.length),o=[];for(let i=0;i<n;i++)o.push(X(e[i]??t[i],t[i]??e[i],r));return o}function ie(e){return e.blend}function At(e,t,r){let n=t.range!==e.range,o=n&&t.range&&t.ticks&&t.ticks===e.ticks?{...t,ticks:j(t.range,Math.max(2,t.ticks.length)-1)}:t,i=ie(e)!==void 0,a=i||n||o.ticks!==e.ticks,l=i||e.range===void 0||e.ticks===void 0||o.range===void 0||o.ticks===void 0;return!a||!l?Y(e,o,r):r===0?e:r===1?o:{...Y(e,o,r),blend:{from:e,to:o,t:r}}}function oe(e,t){let r=ie(e);return r?Y(oe(r.from,t),oe(r.to,t),r.t):t(e)}var B={plotFill:"#15130e",borderColor:"#4a4036",gridColor:"#2c2820",markerColor:"#8a7f70",regionColor:"#d99a3a"},ae=.2;function Et(e,t){if(t===void 0)return 0;let r=e[t];return typeof r=="number"&&Number.isFinite(r)?r:0}function vt(e,t){if(t===void 0||t==="")return"";let r=e[t];return r==null?"":String(r)}function Mt(e,t=[]){if(e.length===0)return[];let r=new Set(t),n=new Set,o=[];for(let i of e)for(let a of Object.keys(i))!r.has(a)&&!n.has(a)&&(n.add(a),o.push(a));return o.filter(i=>{let a=!1;for(let l of e){let c=l[i];if(!(c===void 0||c==="")){if(typeof c!="number")return!1;a=!0}}return a})}var le={fontSize:24,fontWeight:700,textAlign:"center",fill:B.markerColor},se={fontSize:30,fontWeight:600,textAlign:"center",fill:B.markerColor},ce={weight:2,fill:B.gridColor},fe={labelStyle:le,titleStyle:se,lineStyle:ce,tickPadding:20,titlePadding:4},de={labelStyle:{...le,fontWeight:500,textAlign:"right"},titleStyle:se,lineStyle:ce,tickPadding:40,titlePadding:24},N={padding:0,textStyle:{fontSize:30,fontWeight:600,textAlign:"left",fill:B.markerColor},itemGap:44,markerStyle:{width:60,height:24,borderRadius:6,stroke:[],shadow:[]}};function ue(e,t){if(Number.isInteger(e))return String(e);let r=Math.max(1,t===void 0?1:Be(t));return e.toFixed(r).replace(/(\.\d*?)0+$/,"$1").replace(/\.$/,"")}function Be(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 Lt(e){let t=[...e].filter(Number.isFinite).sort((n,o)=>n-o),r;for(let n=1;n<t.length;n++){let o=t[n]-t[n-1];o>1e-12&&(r===void 0||o<r)&&(r=o)}return r}function _t(e){let t=e*100;return Number.isInteger(t)?`${t}%`:`${t.toFixed(1).replace(/\.0$/,"")}%`}function j([e,t],r){let n=Math.max(2,Math.round(r));return Array.from({length:n+1},(o,i)=>e+(t-e)/n*i)}function Rt([e,t],r){let n=Math.max(1,Math.round(r));if(t===e)return Ne(e,n);let o=$((t-e)/n);return[Math.floor(e/o)*o,Math.ceil(t/o)*o]}function Ne(e,t){if(e===0)return[0,1];let r=$(Math.abs(e)/t);return[e-r,e+r]}function zt([e,t],r){let n=t-e,o=Math.max(1,Math.round(r));if(!(n>0))return j([e,t],o);let i=f=>Math.abs(f-Math.round(f))<1e-6,a=$(n/o),l;for(let f of We(a)){let s=n/f;!i(s)||!i(e/f)||s<2||s>8||(l===void 0||Math.abs(s-o)<Math.abs(n/l-o))&&(l=f)}if(l===void 0)return j([e,t],o);let c=Math.round(e/l);return Array.from({length:Math.round(n/l)+1},(f,s)=>Number(((c+s)*l).toPrecision(12)))}function We(e){let t=10**Math.floor(Math.log10(e)),r=[];for(let o of[t/10,t,t*10])for(let i of[1,2,5])r.push(i*o);let n=r.findIndex(o=>Math.abs(o-e)<e*1e-9);return r.slice(Math.max(0,n-2),n+3)}import{Types as d,textOps as he}from"@motionscript/sdk";var Ot="chart",ge=["#4f8cff","#2fbf8f","#f5a524","#e5547a","#9b6cf0"],V="#f4f4f5",O="#a1a1aa",He={seriesFills:d.palette(ge)},Ue={background:d.fill([])},Xe={...Ue,gridBackground:d.fill([])},Ye={legendText:d.typography({fontSize:28,fontWeight:500,fill:V})},je={xLabelText:d.typography({fontSize:28,fontWeight:500,fill:O}),xTitleText:d.typography({fontSize:31,fontWeight:600,fill:O}),yLabelText:d.typography({fontSize:28,fontWeight:500,fill:O}),yTitleText:d.typography({fontSize:31,fontWeight:600,fill:O}),valueText:d.typography({fontSize:24,fontWeight:600,fill:V}),...Ye},$e={horizontalGrid:d.stroke({weight:2,fill:"white/15"}),verticalGrid:d.stroke([]),axisStroke:d.stroke([]),showXAxis:d.boolean(!0,{animatable:!1}),showYAxis:d.boolean(!0,{animatable:!1})},Dt={legend:d.oneOf(["bottom","top","right","none"],{animatable:!1}),swatch:d.oneOf(["square","circle","line"])},Pt={...He,...Xe,...je,labelText:d.typography(),centerText:d.typography(),spokeText:d.typography(),horizontalGrid:$e.horizontalGrid,gridStroke:d.stroke([]),spokeStroke:d.stroke([]),track:d.fill([])};function T(e,t){let r=n=>({fill:n});return{xLabelText:r(t),xTitleText:r(t),yLabelText:r(t),yTitleText:r(t),valueText:r(e),legendText:r(e),labelText:r(t),centerText:r(e),spokeText:r(t)}}function S(e){return{horizontalGrid:{weight:2,fill:e},gridStroke:{weight:2,fill:e},spokeStroke:{weight:2,fill:e},track:e}}var Ct={midnight:{seriesFills:[...ge],...T(V,O),...S("white/15"),track:"white/10",background:[],gridBackground:[]},paper:{seriesFills:["#2563eb","#059669","#d97706","#db2777","#7c3aed"],...T("#1c1917","#57534e"),...S("#1c1917/12"),background:"#fafaf9",gridBackground:[]},ember:{seriesFills:["#d9603b","#8194ad","#e0a93b","#5e9d6b","#9ec85a"],...T("#e9e1d4","#8a7f70"),...S("#2c2820"),background:"#15130e",gridBackground:[]},neon:{seriesFills:["#22d3ee","#a3e635","#f472b6","#facc15","#818cf8"],...T("#ffffff","#94a3b8"),...S("white/10"),background:[],gridBackground:[]},ocean:{seriesFills:["#0ea5e9","#14b8a6","#6366f1","#38bdf8","#2dd4bf"],...T("#e0f2fe","#7dd3fc"),...S("#7dd3fc/20"),background:"#082f49",gridBackground:[]},sunset:{seriesFills:["#f97316","#ef4444","#ec4899","#f59e0b","#a855f7"],...T("#fff7ed","#fdba74"),...S("#fdba74/20"),background:[],gridBackground:[]},pastel:{seriesFills:["#a5b4fc","#f9a8d4","#86efac","#fde68a","#7dd3fc"],...T("#f8fafc","#cbd5e1"),...S("white/12"),background:[],gridBackground:[]},mono:{seriesFills:["#fafafa","#a3a3a3","#737373","#d4d4d4","#525252"],...T("#fafafa","#a3a3a3"),...S("white/12"),background:[],gridBackground:[]}};function Ve(e,t,r){if(r!=null)return r;let n=e.seriesFills;return n.length>0?n[t%n.length]:"white"}function It(e,t,r){return Ve(e,r,t.fill)}function R(e,t=28){let r=e?.fontSize;return typeof r=="number"&&Number.isFinite(r)?r:t}function W(e,t="center",r){return he.styleProps({...he.mergeStyle(e,r),textAlign:t})}function Ke(e,t){return W(t==="x"?e.xLabelText:e.yLabelText,t==="x"?"center":"right")}function Bt(e,t="center"){return W(e.valueText,t)}function Nt(e,t){let r=Math.round(R(t==="x"?e.xLabelText:e.yLabelText)*.6);return{labelStyle:Ke(e,t),titleStyle:W(t==="x"?e.xTitleText:e.yTitleText),lineStyle:t==="x"?e.verticalGrid:e.horizontalGrid,tickPadding:t==="x"?{top:r}:{right:r},titlePadding:t==="x"?{top:Math.round(r/2)}:{right:r}}}function Wt(e){let t=R(e.legendText),r=Math.max(8,Math.round(t*.6)),n=e.swatch==="line"?{width:Math.round(r*2),height:Math.max(3,Math.round(r/4)),borderRadius:r}:e.swatch==="circle"?{width:r,height:r,borderRadius:r/2}:{width:r,height:r,borderRadius:Math.round(r/4)};return{padding:0,textStyle:W(e.legendText,"left"),itemGap:Math.round(t*1.4),markerStyle:{...n,stroke:[],shadow:[]}}}function Ht(e){return t=>{if(typeof t!="object"||t===null||Array.isArray(t))return t;let r=t,n=["palette","foreground","muted","fontFamily","fontSize","fontWeight","barRadius"],o=e==="cartesian"||e==="radar";if(!n.some(v=>v in r)&&!(o&&"background"in r&&!("gridBackground"in r)))return t;let{palette:i,foreground:a,muted:l,fontFamily:c,fontSize:f,fontWeight:s,barRadius:p,...g}=r,x={...g};typeof p=="number"&&x.barCornerRadius===void 0&&(x.barCornerRadius={topLeft:p,topRight:p,bottomRight:0,bottomLeft:0}),i!==void 0&&x.seriesFills===void 0&&(x.seriesFills=i),o&&"background"in r&&!("gridBackground"in r)&&(x.gridBackground=r.background,delete x.background);let L=typeof f=="number"?f:void 0,C=typeof s=="number"?s:void 0,h=(v,I=1,Pe=0)=>{let _={};return typeof c=="string"&&c!==""&&(_.fontFamily=c),L!==void 0&&(_.fontSize=Math.round(L*I)),C!==void 0&&(_.fontWeight=Math.min(900,C+Pe)),v!==void 0&&(_.fill=v),Object.keys(_).length>0?_:void 0},y={legendText:h(a)};e==="cartesian"?(y.xLabelText=h(l),y.yLabelText=h(l),y.xTitleText=h(l,1.1,100),y.yTitleText=h(l,1.1,100),y.valueText=h(a,.85,100)):e==="pie"?(y.labelText=h(l),y.valueText=h(a,1,200),y.centerText=h(a,1.8,300)):e==="radar"?y.spokeText=h(l):(y.labelText=h(l),y.centerText=h(a,1.8,300));for(let[v,I]of Object.entries(y))I&&x[v]===void 0&&(x[v]=I);return x}}import{Rect as A,RotatedBox as qe,Text as pe,textOps as Je}from"@motionscript/sdk";function jt(e){return Math.round(R(e.legendText)*.9)}function $t(e){return Math.ceil(R(e.yLabelText)*.7)}function Vt(e){return Math.ceil(R(e.xLabelText)*1.1)}function Kt(e){let r=[new A({flow:"horizontal",width:"fill",height:"fill",children:[...e.left?[e.left]:[],e.plot]})];e.bottom&&r.push(new A({flow:"horizontal",width:"fill",height:"hug",children:[...e.ghost?[e.ghost]:[],e.bottom]}));let n=new A({flow:"vertical",width:"fill",height:"fill",children:r}),o=e.legend&&e.legendAt!=="none"?e.legend:void 0,i=new A({flow:"horizontal",width:"fill",height:"fill",align:"center",gap:e.gap,children:[n,...o&&e.legendAt==="right"?[o]:[]]}),a=l=>new A({flow:"horizontal",width:"fill",height:"hug",align:"center",children:[l]});return new A({flow:"vertical",width:"fill",height:"fill",gap:e.gap,padding:e.padding,...e.background?{fill:e.background}:{},children:[...o&&e.legendAt==="top"?[a(o)]:[],i,...o&&e.legendAt==="bottom"?[a(o)]:[]]})}function qt(e){let t=[],r=n=>{for(let o of n)t.push(o),r(o.children)};return r(e),t}function Jt(e){let t=e?.layoutBounds;return{width:t?.width??0,height:t?.height??0}}function b(e){let t=Object.keys(Je.styleProps(e())),r={};for(let n of t)r[n]=()=>e()[n];return r}function Qt(e){let t=Array.from({length:e.count},(n,o)=>new pe({...b(e.text),text:()=>e.captions()[o]??""})),r=[];return e.title!==""&&r.push(new qe({angle:-90,width:"hug",height:"hug",children:new pe({...b(e.titleText),text:e.title})})),r.push(new A({flow:"vertical",width:"hug",height:"hug",padding:()=>({right:e.tickPad()}),children:t})),new A({opacity:0,flow:"horizontal",gap:e.titlePad,width:"hug",height:0,children:r})}function Zt(e,t){return(Array.isArray(e)?e:[e]).map(n=>typeof n=="object"&&n!==null?{...n,opacity:(n.opacity??1)*t}:n)}import{Graphics2D as Se,Types as H,component2d as Qe,fillOps as be,strokeOps as ke}from"@motionscript/sdk";import{Types as xe}from"@motionscript/sdk";function u(e,t){return xe.custom(e,t)}function me(e){return e}var rr=xe.custom(0,{kind:"series",min:0,step:1});function ye(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 K=()=>H.custom([],{resolve:ke.resolve,lerp:ke.lerp});function we(e,[t,r],n){return(r<=t?0:(e-t)/(r-t)-.5)*n}function Te(e,t,r,n,o=1){e.draw(new Se().line({points:[t,r]}).stroke(n).opacity(o))}var sr=Qe({key:"chartCanvas",state:{fill:H.custom([],{resolve:be.resolve,lerp:be.lerp}),xGridStroke:K(),yGridStroke:K(),xMarkers:u(()=>[]),yMarkers:u(()=>[]),xExtent:u(()=>[0,1]),yExtent:u(()=>[0,1]),axisStroke:K(),xAxisAt:H.custom(null),yAxisAt:H.custom(null)},load:(e,t)=>ye(e,{fills:[t.fill],strokes:[t.xGridStroke,t.yGridStroke,t.axisStroke]}),render:(e,t)=>{let{width:r,height:n}=e.size;if(r<=0||n<=0)return;t.fill.length>0&&e.draw(new Se().rect({x:0,y:0,width:r,height:n}).fill(t.fill));let o=(c,f,s)=>Math.max(-f/2+s/2,Math.min(f/2-s/2,c)),i=(c,f)=>{let s=f[0]?.weight??0;if(!(s<=0))for(let p of c){let g=o(we(p,t.xExtent,r),r,s);Te(e,{x:g,y:-n/2},{x:g,y:n/2},f)}},a=(c,f)=>{let s=f[0]?.weight??0;if(!(s<=0))for(let p of c){let g=o(we(p,t.yExtent,n),n,s);Te(e,{x:-r/2,y:g},{x:r/2,y:g},f)}},l=([c,f])=>s=>s>=Math.min(c,f)-1e-9&&s<=Math.max(c,f)+1e-9;i(t.xMarkers.filter(l(t.xExtent)),t.xGridStroke),a(t.yMarkers.filter(l(t.yExtent)),t.yGridStroke),t.xAxisAt!==null&&a([t.xAxisAt],t.axisStroke),t.yAxisAt!==null&&i([t.yAxisAt],t.axisStroke)}});import{Rect as Me,Text as Le,Types as U,component2d as lt}from"@motionscript/sdk";import{enterBudget as st}from"@motionscript/sdk/component";import{Types as Ze,easeOut as et}from"@motionscript/sdk";var tt=e=>e,q=20;function dr(e){return e==="top"?{y:q}:e==="right"?{x:q}:{y:-q}}var ur=5,hr={axes:.35,marks:.5,legend:.15};function k(e){return e.easing?tt:et()}function z(e,t){let r=e.duration,n=t.reduce((i,a)=>Math.max(i,a.at+a.duration),0),o=n>r&&n>0?r/n:1;return e.together(t.map(({at:i,duration:a,piece:l})=>{let c=i*o,f=a*o;return e.sequence([e.wait(c),l,e.wait(Math.max(0,r-c-f))])}))}var J={opacity:1,shift:0};function F(){return Ze.custom({},{private:!0,resolve:(e,t)=>({...t,...e})})}function m(e,t){return e[t]??J}function M(e,t){let r={};for(let n of e)r[n]=t;return r}function E(e,t,r,n){return e.animate(o=>{let i=n(o);return{arrivals:{[t]:{opacity:r.opacity+(J.opacity-r.opacity)*i,shift:r.shift+(J.shift-r.shift)*i}}}})}import{Rect as Ae,RotatedBox as rt,Text as Ee,Types as Q,component2d as nt,insetsOps as ve}from"@motionscript/sdk";import{enterBudget as ot}from"@motionscript/sdk/component";var it=24;function Z(e,t){let r=e.markers.indexOf(t);return(r>=0?e.captions[r]:void 0)??ue(t)}function ee(e,t){return{tick:ve.resolve(e.tickPadding)[t],title:ve.resolve(e.titlePadding)[t]}}function at(e){let t=()=>ee(e.axis(),"right"),r=Array.from({length:e.count},(o,i)=>{let a=()=>l.parent?.layoutBounds??{width:0,height:0},l=new Ee({...b(()=>e.axis().labelStyle),text:()=>e.text(i),x:()=>(a().width-t().tick)/2-l.layoutBounds.width/2+m(e.arrivals(),i).shift,y:()=>e.place(i,a().height),opacity:()=>m(e.arrivals(),i).opacity*(e.opacity?.(i)??1)});return l}),n=[];return e.label!==""&&n.push(new rt({angle:-90,width:"hug",height:"hug",children:new Ee({...b(()=>e.axis().titleStyle),text:e.label,opacity:()=>m(e.arrivals(),"label").opacity,x:()=>m(e.arrivals(),"label").shift})})),n.push(new Ae({height:"fill",width:"hug",padding:()=>({right:t().tick}),children:r})),new Ae({flow:"horizontal",gap:()=>t().title,height:"fill",children:n})}var wr=nt({key:"verticalAxis",state:{range:u(()=>[0,1]),markers:u(()=>[]),captions:u(()=>[]),axis:Q.custom(de),label:"",arrivals:F()},defaults:{width:"fill",height:"fill"},children:e=>{let t=()=>[...e.markers].sort((n,o)=>o-n),r=n=>{if(n===void 0)return 0;let[o,i]=e.range;return i<=o?0:(n-o)/(i-o)};return[at({count:e.markers.length,axis:()=>e.axis,text:n=>{let o=t()[n];return o===void 0?"":Z(e,o)},place:(n,o)=>(r(t()[n])-.5)*o,arrivals:()=>e.arrivals,label:e.label})]},commands:{enter:{args:{stagger:Q.custom(void 0),slide:Q.number(it)},run:(e,t)=>{let{stagger:r,slide:n}=e.args,o=t.markers.length,i=t.label!=="",a={opacity:0,shift:n},l=[...t.markers.keys(),...i?["label"]:[]],c=e.animate(()=>({arrivals:M(l,a)}));if(o===0)return c;let{step:f,per:s,caption:p}=ot(e.duration,o,i,r),g=k(e),x=t.markers.map((C,h)=>({at:(o-1-h)*f,duration:s,piece:E(e,h,a,g)})),L=i?[{at:(o-1)*f+s,duration:p,piece:E(e,"label",a,g)}]:[];return e.together([c,z(e,[...x,...L])])}}}});var ct=24,Rr=lt({key:"horizontalAxis",state:{range:u(()=>[0,1]),markers:u(()=>[]),captions:u(()=>[]),axis:U.custom(fe),label:"",overhang:U.custom({left:0,right:0}),arrivals:F()},defaults:{width:"fill",height:"fill"},children:e=>{let t=()=>ee(e.axis,"top"),r=()=>[...e.markers].sort((a,l)=>a-l),n=a=>{if(a===void 0)return 0;let[l,c]=e.range;return c<=l?0:(a-l)/(c-l)},o=e.markers.map((a,l)=>{let c=()=>f.parent?.layoutBounds.width??0,f=new Le({...b(()=>e.axis.labelStyle),text:()=>{let s=r()[l];return s===void 0?"":Z(e,s)},x:()=>{let s=c(),p=f.layoutBounds.width/2,g=(n(r()[l])-.5)*s;return Math.max(-s/2-e.overhang.left+p,Math.min(s/2+e.overhang.right-p,g))},opacity:()=>m(e.arrivals,l).opacity,y:()=>m(e.arrivals,l).shift});return f}),i=[new Me({width:"fill",height:"hug",padding:()=>({top:t().tick}),children:o})];return e.label!==""&&i.push(new Le({...b(()=>e.axis.titleStyle),text:e.label,opacity:()=>m(e.arrivals,"label").opacity,y:()=>m(e.arrivals,"label").shift})),[new Me({flow:"vertical",gap:()=>t().title,height:"hug",width:"fill",children:i})]},commands:{enter:{args:{stagger:U.custom(void 0),slide:U.number(ct)},run:(e,t)=>{let{stagger:r,slide:n}=e.args,o=t.markers.length,i=t.label!=="",a={opacity:0,shift:n},l=[...t.markers.keys(),...i?["label"]:[]],c=e.animate(()=>({arrivals:M(l,a)}));if(o===0)return c;let{step:f,per:s,caption:p}=st(e.duration,o,i,r),g=k(e),x=t.markers.map((C,h)=>({at:h*f,duration:s,piece:E(e,h,a,g)})),L=i?[{at:(o-1)*f+s,duration:p,piece:E(e,"label",a,g)}]:[];return e.together([c,z(e,[...x,...L])])}}}});import{Flow as D,Paint as w,Rect as ft,Shapes as te,Text as dt,Types as G,component2d as Re}from"@motionscript/sdk";var ze={...w.state,...D.state,...te.corners},ut=Re({key:"legendEntry",state:{...ze,shown:G.number(1),along:G.oneOf(["horizontal","vertical"])},commands:{...w.commands},measure:(e,t,r)=>{let n=D.measure(e,t,r,w.inset(t));return t.shown>=1?n:t.along==="vertical"?{...n,height:t.shown*n.height}:{...n,width:t.shown*n.width}},layout:(e,t,r)=>D.layout(e,t,r,w.inset(t)),render:(e,t)=>w.draw(e,t,te.rect(e.size,t))});function ht(e,t){if(Array.isArray(e))return e;let r=[...t??[]];for(let[n,o]of Object.entries(e))r[Number(n)]=o;return r}var Cr=Re({key:"chartLegend",state:{...ze,series:u(()=>[]),swatches:u(()=>[]),legend:G.custom(N),reveal:u(()=>[],{resolve:ht})},defaults:{flow:"horizontal",width:"hug",height:"hug",gap:e=>e.flow==="vertical"?Math.round(e.legend.itemGap*.4):e.legend.itemGap,padding:e=>e.legend.padding,align:e=>e.flow==="vertical"?"centerLeft":"center",reveal:e=>e.series.map(t=>t.enabled??!0?1:0)},children:e=>{let t=()=>e.legend.markerStyle,r=e.flow==="vertical"?"vertical":"horizontal";return e.series.map((n,o)=>ut({flow:"horizontal",gap:()=>Math.round((e.legend.textStyle.fontSize??24)*.45),align:"center",width:"hug",height:"hug",along:r,opacity:()=>e.reveal[o]??0,gapScale:()=>e.reveal[o]??0,shown:()=>e.reveal[o]??0,children:[ft({width:()=>t().width,height:()=>t().height,cornerRadius:()=>t().borderRadius,fill:()=>e.swatches[o]??"white",stroke:()=>t().stroke,shadow:()=>t().shadow}),dt({...b(()=>e.legend.textStyle),text:n.label||n.field})]}))},commands:{...w.commands,showSeries:{args:{index:G.number(0,{min:0,step:1})},run:(e,t)=>e.args.index in t.series?e.animate(_e(t,e.args.index,1,k(e))):e.wait(e.duration)},hideSeries:{args:{index:G.number(0,{min:0,step:1})},run:(e,t)=>e.args.index in t.series?e.animate(_e(t,e.args.index,0,k(e))):e.wait(e.duration)},spotlightSeries:{args:{index:G.number(0,{min:0,step:1})},run:(e,t,r)=>e.together(r.flatMap((n,o)=>(t.reveal[o]??0)>0?[n.to({opacity:o===e.args.index?1:ae})]:[]))}},measure:(e,t,r)=>D.measure(e,t,r,w.inset(t)),layout:(e,t,r)=>D.layout(e,t,r,w.inset(t)),render:(e,t)=>w.draw(e,t,te.rect(e.size,t))});function _e(e,t,r,n){let o=e.reveal[t]??0;return i=>({reveal:{[t]:o+(r-o)*n(i)}})}import{Flow as re,Paint as P,Rect as ne,Shapes as Fe,Text as gt,Types as pt,clamp as xt,component2d as mt,textOps as yt}from"@motionscript/sdk";var Ge=16,Ur=mt({key:"pieLegend",state:{...P.state,...re.state,...Fe.corners,slices:u(()=>[]),legend:pt.custom(N),dims:u(()=>[]),arrivals:F()},defaults:{flow:"vertical",align:"centerLeft",width:"hug",height:"hug",gap:e=>e.legend.itemGap/3,padding:e=>e.legend.padding},children:e=>{let t=()=>e.legend.markerStyle;return e.slices.map((r,n)=>ne({width:"hug",height:"hug",flow:"freeform",opacity:()=>xt(e.dims[n]??1,0,1),children:[ne({flow:"horizontal",gap:()=>Math.round(e.legend.textStyle.fontSize===void 0?12:Number(e.legend.textStyle.fontSize)*.4),align:"center",width:"hug",height:"hug",opacity:()=>m(e.arrivals,n).opacity,x:()=>m(e.arrivals,n).shift,children:[ne({width:()=>t().width,height:()=>t().height,cornerRadius:()=>t().borderRadius,fill:()=>e.slices[n]?.fill??"white"}),gt({...yt.styleProps(e.legend.textStyle),fill:()=>e.legend.textStyle.fill??"white",fontSize:()=>e.legend.textStyle.fontSize??28,fontWeight:()=>e.legend.textStyle.fontWeight??500,text:()=>e.slices[n]?.category??""})]})]}))},commands:{...P.commands,arm:(e,t)=>e.animate(()=>({arrivals:M([...t.slices.keys()],{opacity:0,shift:Ge})})),enter:(e,t)=>{let r=t.slices.length;if(r===0)return e.wait(e.duration);let n={opacity:0,shift:Ge},o=e.animate(()=>({arrivals:M([...t.slices.keys()],n)})),i=e.duration/(1+Math.max(0,r-1)/5),a=i/5,l=k(e),c=t.slices.map((f,s)=>({at:s*a,duration:i,piece:E(e,s,n,l)}));return e.together([o,z(e,c)])}},measure:(e,t,r)=>re.measure(e,t,r,P.inset(t)),layout:(e,t,r)=>re.layout(e,t,r,P.inset(t)),render:(e,t)=>P.draw(e,t,Fe.rect(e.size,t))});import{clamp as bt,fillOps as Oe}from"@motionscript/sdk";var jr=Math.PI/180;function $r(e,t,r){return e<=0?1:1-(1-bt(t,0,1))*e*(1-r)}function Vr(e,t){return{x:e*Math.sin(t),y:e*Math.cos(t)}}var Kr=.15,De=new WeakMap;function kt(e){if(typeof e!="object"||e===null)return Oe.resolve(e);let t=De.get(e);return t===void 0&&De.set(e,t=Oe.resolve(e)),t}function qr(e){return e.map(t=>kt(t.fill))}export*from"@motionscript/sdk/component";export{Ot as a,ge as b,V as c,O as d,He as e,Ue as f,Xe as g,Ye as h,je as i,$e as j,Dt as k,Ct as l,Ve as m,It as n,R as o,W as p,Ke as q,Bt as r,Nt as s,Wt as t,Ht as u,jt as v,$t as w,Vt as x,Kt as y,qt as z,Jt as A,b as B,Qt as C,Zt as D,u as E,me as F,rr as G,ye as H,Te as I,sr as J,q as K,dr as L,ur as M,hr as N,k as O,z as P,F as Q,m as R,M as S,E as T,St as U,Y as V,At as W,oe as X,ae as Y,Et as Z,vt as _,Mt as $,fe as aa,de as ba,N as ca,ue as da,Lt as ea,_t as fa,j as ga,Rt as ha,zt as ia,Cr as ja,Z as ka,ee as la,at as ma,wr as na,Rr as oa,Ur as pa,jr as qa,$r as ra,Vr as sa,Kr as ta,kt as ua,qr as va};
|
|
2
|
-
//# sourceMappingURL=chunk-7XCRX6GE.js.map
|
|
@@ -1,7 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"version": 3,
|
|
3
|
-
"sources": ["../../../src/kit/shared.ts", "../../../src/kit/style.ts", "../../../src/kit/cartesian.ts", "../../../src/kit/chart-canvas.ts", "../../../src/kit/entries.ts", "../../../src/kit/paints.ts", "../../../src/kit/horizontal-axis.ts", "../../../src/kit/motion.ts", "../../../src/kit/vertical-axis.ts", "../../../src/kit/chart-legend.ts", "../../../src/kit/pie-legend.ts", "../../../src/kit/polar.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 lerpNumber,\n type DataRecord,\n type Fill,\n type Insets,\n type Shadow,\n type Stroke,\n type TextStyle,\n} from \"@motionscript/sdk\"\nimport { niceStep } from \"@motionscript/sdk/component\"\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 /** The legend caption; empty or absent shows `field`. */\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. */\nconst 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/** 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\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\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/**\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\n/** `[lo, hi]` nudged out to bounds a whole number of tidy steps apart, about `divisions` of them. */\nexport function niceRange([lo, hi]: Range, divisions: number): Range {\n const segments = Math.max(1, Math.round(divisions))\n if (hi === lo) return constantScale(lo, segments)\n const step = niceStep((hi - lo) / segments)\n return [Math.floor(lo / step) * step, Math.ceil(hi / step) * step]\n}\n\n/**\n * The scale for constant data. A zero-width scale would put every tick on one\n * value and the line on the floor, so it widens by a step sized to the\n * magnitude (`5` gets `[3, 7]`), or `[0, 1]` for zero.\n */\nfunction constantScale(value: number, segments: number): Range {\n if (value === 0) return [0, 1]\n const step = niceStep(Math.abs(value) / segments)\n return [value - step, value + step]\n}\n\n/**\n * Ticks for a range worked out from the data: every multiple of the tidiest\n * step (1, 2 or 5 times a power of ten) that divides it into about `divisions`\n * parts, so zero is a tick whenever the range spans it. A range no such step\n * divides (an author's) is split evenly instead.\n */\nexport function niceTicks([lo, hi]: Range, divisions: number): number[] {\n const span = hi - lo\n const target = Math.max(1, Math.round(divisions))\n if (!(span > 0)) return markerValues([lo, hi], target)\n const whole = (v: number) => Math.abs(v - Math.round(v)) < 1e-6\n const base = niceStep(span / target)\n let best: number | undefined\n for (const step of ladder(base)) {\n const parts = span / step\n if (!whole(parts) || !whole(lo / step) || parts < 2 || parts > 8) continue\n if (best === undefined || Math.abs(parts - target) < Math.abs(span / best - target)) best = step\n }\n if (best === undefined) return markerValues([lo, hi], target)\n const first = Math.round(lo / best)\n return Array.from({ length: Math.round(span / best) + 1 }, (_, k) => Number(((first + k) * best).toPrecision(12)))\n}\n\n/** `step` and its neighbours on the 1-2-5 ladder, two either side. */\nfunction ladder(step: number): number[] {\n const mag = 10 ** Math.floor(Math.log10(step))\n const rungs: number[] = []\n for (const m of [mag / 10, mag, mag * 10]) for (const k of [1, 2, 5]) rungs.push(k * m)\n const at = rungs.findIndex((r) => Math.abs(r - step) < step * 1e-9)\n return rungs.slice(Math.max(0, at - 2), at + 3)\n}\n", "/**\n * The chart family's style: one `style` entry per chart, built from the groups\n * below, so a look saved off one chart lays onto any other (a field the other\n * chart does not draw is dropped). A chart spreads the shared groups and adds a\n * `marks` group of its own. Every run of text a chart draws is its own\n * `Types.typography` field, so axis labels, titles, values and the legend are\n * each set the way a text node is.\n */\n\nimport {\n Types,\n textOps,\n type Fill,\n type StrokeResolved,\n type Stroke as _Stroke,\n type StyleInput,\n type TextStyle,\n // Named so the emitted style types reach these through the sdk, not core.\n type FillResolved as _FillResolved,\n type Type as _Type,\n} from \"@motionscript/sdk\"\n\nimport type { AxisConfig, ChartSeries, LegendConfig } from \"./shared\"\n\n/** The style family every chart shares; the built-in presets are written for it. */\nexport const CHART_STYLE_FAMILY = \"chart\"\n\n/** The out-of-the-box series fills, cycled by series (or row) index. */\nexport const CHART_PALETTE_DEFAULT = [\"#4f8cff\", \"#2fbf8f\", \"#f5a524\", \"#e5547a\", \"#9b6cf0\"] as const\n\n/** The default ink of values, legend captions and centre text, on the dark stage. */\nexport const CHART_FOREGROUND = \"#f4f4f5\"\n/** The default ink of axis markers, axis captions and spoke labels. */\nexport const CHART_MUTED = \"#a1a1aa\"\n\nexport const CHART_SERIES = {\n /** A fill per series (a pie's or radial's per row), cycled; each may stack several paints. */\n seriesFills: Types.palette(CHART_PALETTE_DEFAULT),\n}\n\nexport const CHART_BACKGROUND = {\n /** Behind the whole chart, legend and axes included; none by default, so the chart reads against the stage. */\n background: Types.fill([]),\n}\n\nexport const GRID_BACKGROUND = {\n ...CHART_BACKGROUND,\n /** Behind the plot only, under the grid lines; none by default. */\n gridBackground: Types.fill([]),\n}\n\n/** The legend's captions, which every chart with a legend draws. */\nexport const LEGEND_TEXT = {\n legendText: Types.typography({ fontSize: 28, fontWeight: 500, fill: CHART_FOREGROUND }),\n}\n\nexport const CARTESIAN_TEXT = {\n /** The markers under the plot: categories on a column chart, values on a horizontal bar chart. */\n xLabelText: Types.typography({ fontSize: 28, fontWeight: 500, fill: CHART_MUTED }),\n /** The caption under the plot. */\n xTitleText: Types.typography({ fontSize: 31, fontWeight: 600, fill: CHART_MUTED }),\n /** The markers beside the plot. */\n yLabelText: Types.typography({ fontSize: 28, fontWeight: 500, fill: CHART_MUTED }),\n /** The caption beside the plot, turned on its side. */\n yTitleText: Types.typography({ fontSize: 31, fontWeight: 600, fill: CHART_MUTED }),\n /** The figures printed by the marks. */\n valueText: Types.typography({ fontSize: 24, fontWeight: 600, fill: CHART_FOREGROUND }),\n ...LEGEND_TEXT,\n}\n\nexport const CARTESIAN_GRID = {\n /** The lines along the value ticks of a column chart (one per tick); empty draws none. */\n horizontalGrid: Types.stroke({ weight: 2, fill: \"white/15\" }),\n /** The lines under the category markers; empty draws none. */\n verticalGrid: Types.stroke([]),\n /** The baseline and the value-axis rule; empty draws none. */\n axisStroke: Types.stroke([]),\n /** Read as the chart is built: whether the category (x) axis row is drawn. */\n showXAxis: Types.boolean(true, { animatable: false }),\n /** Read as the chart is built: whether the value (y) axis column is drawn. */\n showYAxis: Types.boolean(true, { animatable: false }),\n}\n\nexport type LegendPosition = \"bottom\" | \"top\" | \"right\" | \"none\"\nexport type LegendSwatch = \"square\" | \"circle\" | \"line\"\n\nexport const CHART_LEGEND = {\n /** Read as the chart is built: where the legend sits, or `none`. */\n legend: Types.oneOf([\"bottom\", \"top\", \"right\", \"none\"] as const, { animatable: false }),\n swatch: Types.oneOf([\"square\", \"circle\", \"line\"] as const),\n}\n\n/** The fields every chart's style resolves, whichever groups it spreads. */\nexport interface ChartStyleBase {\n readonly seriesFills: readonly Fill[]\n readonly background: Fill\n readonly legendText: TextStyle\n readonly legend: LegendPosition\n readonly swatch: LegendSwatch\n}\n\n/** The cartesian fields, for the line and bar charts. */\nexport interface CartesianStyle extends ChartStyleBase {\n readonly gridBackground: Fill\n readonly xLabelText: TextStyle\n readonly xTitleText: TextStyle\n readonly yLabelText: TextStyle\n readonly yTitleText: TextStyle\n readonly valueText: TextStyle\n readonly horizontalGrid: StrokeResolved[]\n readonly verticalGrid: StrokeResolved[]\n readonly axisStroke: StrokeResolved[]\n readonly showXAxis: boolean\n readonly showYAxis: boolean\n}\n\n/** The fields a preset restates so its rules and text read on its background (a chart keeps those it draws). */\nconst _PRESET_FIELDS = {\n ...CHART_SERIES,\n ...GRID_BACKGROUND,\n ...CARTESIAN_TEXT,\n labelText: Types.typography(),\n centerText: Types.typography(),\n spokeText: Types.typography(),\n horizontalGrid: CARTESIAN_GRID.horizontalGrid,\n gridStroke: Types.stroke([]),\n spokeStroke: Types.stroke([]),\n track: Types.fill([]),\n}\n\n/** A preset's fields: any chart's, so one preset dresses every chart. */\nexport type ChartStylePreset = StyleInput<typeof _PRESET_FIELDS>\n\n/** Every text field's ink: `foreground` for values, the legend and centre text, `muted` for markers and captions. */\nfunction inks(foreground: string, muted: string) {\n const on = (fill: string) => ({ fill })\n return {\n xLabelText: on(muted),\n xTitleText: on(muted),\n yLabelText: on(muted),\n yTitleText: on(muted),\n valueText: on(foreground),\n legendText: on(foreground),\n labelText: on(muted),\n centerText: on(foreground),\n spokeText: on(muted),\n } satisfies ChartStylePreset\n}\n\n/** Every rule a chart draws, and a radial's track, in one paint. */\nfunction rules(fill: string) {\n return {\n horizontalGrid: { weight: 2, fill },\n gridStroke: { weight: 2, fill },\n spokeStroke: { weight: 2, fill },\n track: fill,\n } satisfies ChartStylePreset\n}\n\n/** Ready-made looks, each stating every colour so applying one replaces the last. */\nexport const CHART_STYLE_PRESETS = {\n midnight: {\n seriesFills: [...CHART_PALETTE_DEFAULT],\n ...inks(CHART_FOREGROUND, CHART_MUTED),\n ...rules(\"white/15\"),\n track: \"white/10\",\n background: [],\n gridBackground: [],\n },\n paper: {\n seriesFills: [\"#2563eb\", \"#059669\", \"#d97706\", \"#db2777\", \"#7c3aed\"],\n ...inks(\"#1c1917\", \"#57534e\"),\n ...rules(\"#1c1917/12\"),\n background: \"#fafaf9\",\n gridBackground: [],\n },\n ember: {\n seriesFills: [\"#d9603b\", \"#8194ad\", \"#e0a93b\", \"#5e9d6b\", \"#9ec85a\"],\n ...inks(\"#e9e1d4\", \"#8a7f70\"),\n ...rules(\"#2c2820\"),\n background: \"#15130e\",\n gridBackground: [],\n },\n neon: {\n seriesFills: [\"#22d3ee\", \"#a3e635\", \"#f472b6\", \"#facc15\", \"#818cf8\"],\n ...inks(\"#ffffff\", \"#94a3b8\"),\n ...rules(\"white/10\"),\n background: [],\n gridBackground: [],\n },\n ocean: {\n seriesFills: [\"#0ea5e9\", \"#14b8a6\", \"#6366f1\", \"#38bdf8\", \"#2dd4bf\"],\n ...inks(\"#e0f2fe\", \"#7dd3fc\"),\n ...rules(\"#7dd3fc/20\"),\n background: \"#082f49\",\n gridBackground: [],\n },\n sunset: {\n seriesFills: [\"#f97316\", \"#ef4444\", \"#ec4899\", \"#f59e0b\", \"#a855f7\"],\n ...inks(\"#fff7ed\", \"#fdba74\"),\n ...rules(\"#fdba74/20\"),\n background: [],\n gridBackground: [],\n },\n pastel: {\n seriesFills: [\"#a5b4fc\", \"#f9a8d4\", \"#86efac\", \"#fde68a\", \"#7dd3fc\"],\n ...inks(\"#f8fafc\", \"#cbd5e1\"),\n ...rules(\"white/12\"),\n background: [],\n gridBackground: [],\n },\n mono: {\n seriesFills: [\"#fafafa\", \"#a3a3a3\", \"#737373\", \"#d4d4d4\", \"#525252\"],\n ...inks(\"#fafafa\", \"#a3a3a3\"),\n ...rules(\"white/12\"),\n background: [],\n gridBackground: [],\n },\n} satisfies Record<string, ChartStylePreset>\n\n/** Series `index`'s fill: its own `fill`, else the style's series fills, cycled. */\nexport function paletteFill(style: Pick<ChartStyleBase, \"seriesFills\">, index: number, own?: Fill): Fill {\n if (own != null) return own\n const fills = style.seriesFills\n return fills.length > 0 ? fills[index % fills.length] : \"white\"\n}\n\n/** {@link paletteFill} for a series. */\nexport function seriesFill(style: Pick<ChartStyleBase, \"seriesFills\">, series: ChartSeries, index: number): Fill {\n return paletteFill(style, index, series.fill)\n}\n\n/** A text style's size in px; an autofit or unset size reads as `fallback`. */\nexport function sizeOf(text: TextStyle | undefined, fallback = 28): number {\n const size = text?.fontSize\n return typeof size === \"number\" && Number.isFinite(size) ? size : fallback\n}\n\n/**\n * `text` as a text node takes it, aligned where the chart puts it, with `over`\n * laid on top. Unset keys are dropped: an `undefined` spread onto a node is a\n * value, and an unset face must stay unset so the host's default applies.\n */\nexport function placedText(text: TextStyle, textAlign: TextStyle[\"textAlign\"] = \"center\", over?: TextStyle): TextStyle {\n return textOps.styleProps({ ...textOps.mergeStyle(text, over), textAlign }) as TextStyle\n}\n\n/** Axis markers on `axis`, aligned as that axis sets them. */\nexport function markerText(style: Pick<CartesianStyle, \"xLabelText\" | \"yLabelText\">, axis: \"x\" | \"y\"): TextStyle {\n return placedText(axis === \"x\" ? style.xLabelText : style.yLabelText, axis === \"x\" ? \"center\" : \"right\")\n}\n\n/** The figures printed by the marks. */\nexport function valueText(style: Pick<CartesianStyle, \"valueText\">, textAlign: TextStyle[\"textAlign\"] = \"center\"): TextStyle {\n return placedText(style.valueText, textAlign)\n}\n\n/**\n * The kit axis parts' config from a style. `x` is the axis under the plot;\n * its grid lines are vertical (one per x marker), the `y` axis's horizontal.\n */\nexport function axisConfigOf(\n style: Pick<CartesianStyle, \"verticalGrid\" | \"horizontalGrid\" | \"xLabelText\" | \"xTitleText\" | \"yLabelText\" | \"yTitleText\">,\n axis: \"x\" | \"y\"\n): AxisConfig {\n const gap = Math.round(sizeOf(axis === \"x\" ? style.xLabelText : style.yLabelText) * 0.6)\n return {\n labelStyle: markerText(style, axis),\n titleStyle: placedText(axis === \"x\" ? style.xTitleText : style.yTitleText),\n lineStyle: axis === \"x\" ? style.verticalGrid : style.horizontalGrid,\n tickPadding: axis === \"x\" ? { top: gap } : { right: gap },\n titlePadding: axis === \"x\" ? { top: Math.round(gap / 2) } : { right: gap },\n }\n}\n\n/** The kit legend's config: captions in `legendText`, the swatch shaped by `swatch` and sized off the captions. */\nexport function legendConfigOf(style: Pick<ChartStyleBase, \"swatch\" | \"legendText\">): LegendConfig {\n const type = sizeOf(style.legendText)\n const size = Math.max(8, Math.round(type * 0.6))\n const marker =\n style.swatch === \"line\"\n ? { width: Math.round(size * 2), height: Math.max(3, Math.round(size / 4)), borderRadius: size }\n : style.swatch === \"circle\"\n ? { width: size, height: size, borderRadius: size / 2 }\n : { width: size, height: size, borderRadius: Math.round(size / 4) }\n return {\n padding: 0,\n textStyle: placedText(style.legendText, \"left\"),\n itemGap: Math.round(type * 1.4),\n markerStyle: { ...marker, stroke: [], shadow: [] },\n }\n}\n\n/** Which text a chart drew from the retired shared text fields. */\nexport type ChartTextLayout = \"cartesian\" | \"pie\" | \"radar\" | \"radial\"\n\n/**\n * The `style` entry's hook for documents written before every run of text got\n * its own field (0.1.1-alpha.1): `barRadius` became `barCornerRadius`, `palette` became `seriesFills`; `foreground`,\n * `muted` and the one `fontFamily`/`fontSize`/`fontWeight` became the text\n * fields as each chart derived them; a cartesian or radar `background`, which\n * painted the plot, became `gridBackground`. A current style comes back as is.\n */\nexport function migrateChartStyle(layout: ChartTextLayout): (value: unknown) => unknown {\n return (value) => {\n if (typeof value !== \"object\" || value === null || Array.isArray(value)) return value\n const old = value as Record<string, unknown>\n const retired = [\"palette\", \"foreground\", \"muted\", \"fontFamily\", \"fontSize\", \"fontWeight\", \"barRadius\"]\n const plotBackground = layout === \"cartesian\" || layout === \"radar\"\n if (!retired.some((key) => key in old) && !(plotBackground && \"background\" in old && !(\"gridBackground\" in old))) return value\n\n const { palette, foreground, muted, fontFamily, fontSize, fontWeight, barRadius, ...rest } = old\n const out: Record<string, unknown> = { ...rest }\n // A bar radius rounded only the far end; its replacement states every corner.\n if (typeof barRadius === \"number\" && out.barCornerRadius === undefined) {\n out.barCornerRadius = { topLeft: barRadius, topRight: barRadius, bottomRight: 0, bottomLeft: 0 }\n }\n if (palette !== undefined && out.seriesFills === undefined) out.seriesFills = palette\n if (plotBackground && \"background\" in old && !(\"gridBackground\" in old)) {\n out.gridBackground = old.background\n delete out.background\n }\n const size = typeof fontSize === \"number\" ? fontSize : undefined\n const weight = typeof fontWeight === \"number\" ? fontWeight : undefined\n const text = (ink: unknown, scale = 1, heavier = 0): Record<string, unknown> | undefined => {\n const t: Record<string, unknown> = {}\n if (typeof fontFamily === \"string\" && fontFamily !== \"\") t.fontFamily = fontFamily\n if (size !== undefined) t.fontSize = Math.round(size * scale)\n if (weight !== undefined) t.fontWeight = Math.min(900, weight + heavier)\n if (ink !== undefined) t.fill = ink\n return Object.keys(t).length > 0 ? t : undefined\n }\n const fields: Record<string, Record<string, unknown> | undefined> = { legendText: text(foreground) }\n if (layout === \"cartesian\") {\n fields.xLabelText = text(muted)\n fields.yLabelText = text(muted)\n fields.xTitleText = text(muted, 1.1, 100)\n fields.yTitleText = text(muted, 1.1, 100)\n fields.valueText = text(foreground, 0.85, 100)\n } else if (layout === \"pie\") {\n fields.labelText = text(muted)\n fields.valueText = text(foreground, 1, 200)\n fields.centerText = text(foreground, 1.8, 300)\n } else if (layout === \"radar\") {\n fields.spokeText = text(muted)\n } else {\n fields.labelText = text(muted)\n fields.centerText = text(foreground, 1.8, 300)\n }\n for (const [key, field] of Object.entries(fields)) if (field && out[key] === undefined) out[key] = field\n return out\n }\n}\n", "import {\n Rect,\n RotatedBox,\n Text,\n textOps,\n type ChildView,\n type Fill,\n type FillResolved,\n type Insets,\n type Node2D,\n type Size2D,\n type TextStyle,\n} from \"@motionscript/sdk\"\n\nimport { sizeOf, type CartesianStyle, type LegendPosition } from \"./style\"\n\n/** Space between the frame's rows and columns: the plot and the legend, the axes and the legend. */\nexport function frameGap(style: Pick<CartesianStyle, \"legendText\">): number {\n return Math.round(sizeOf(style.legendText) * 0.9)\n}\n\n/** Room above the plot for the top value marker, which is centred on the top grid line. */\nexport function headroom(style: Pick<CartesianStyle, \"yLabelText\">): number {\n return Math.ceil(sizeOf(style.yLabelText) * 0.7)\n}\n\n/** How far an end marker of a horizontal value axis may hang past the plot: half a short caption. */\nexport function overhang(style: Pick<CartesianStyle, \"xLabelText\">): number {\n return Math.ceil(sizeOf(style.xLabelText) * 1.1)\n}\n\ninterface CartesianParts {\n /** Behind the whole chart, axes and legend included. */\n readonly background?: () => Fill\n /** The axis beside the plot, on its left. */\n readonly left?: Node2D\n /** An invisible twin of `left` under the plot, so the row there starts at the plot's left edge. */\n readonly ghost?: Node2D\n /** The box the grid and the marks share. */\n readonly plot: Node2D\n /** The axis under the plot. */\n readonly bottom?: Node2D\n readonly legend?: Node2D\n readonly legendAt: LegendPosition\n readonly gap: () => number\n readonly padding: () => Insets\n}\n\n/**\n * The frame the line and bar charts share. A legend above or below is centred\n * on the whole chart; one on the right is a column beside the plot. An axis the\n * style turns off is simply not here, and the plot takes its room.\n */\nexport function cartesianFrame(parts: CartesianParts): Node2D {\n const top = new Rect({ flow: \"horizontal\", width: \"fill\", height: \"fill\", children: [...(parts.left ? [parts.left] : []), parts.plot] })\n const rows: Node2D[] = [top as unknown as Node2D]\n if (parts.bottom) {\n rows.push(new Rect({ flow: \"horizontal\", width: \"fill\", height: \"hug\", children: [...(parts.ghost ? [parts.ghost] : []), parts.bottom] }) as unknown as Node2D)\n }\n const body = new Rect({ flow: \"vertical\", width: \"fill\", height: \"fill\", children: rows })\n const legend = parts.legend && parts.legendAt !== \"none\" ? parts.legend : undefined\n const main = new Rect({\n flow: \"horizontal\",\n width: \"fill\",\n height: \"fill\",\n align: \"center\",\n gap: parts.gap,\n children: [body, ...(legend && parts.legendAt === \"right\" ? [legend] : [])],\n })\n const across = (node: Node2D) => new Rect({ flow: \"horizontal\", width: \"fill\", height: \"hug\", align: \"center\", children: [node] })\n return new Rect({\n flow: \"vertical\",\n width: \"fill\",\n height: \"fill\",\n gap: parts.gap,\n padding: parts.padding,\n ...(parts.background ? { fill: parts.background } : {}),\n children: [\n ...(legend && parts.legendAt === \"top\" ? [across(legend)] : []),\n main,\n ...(legend && parts.legendAt === \"bottom\" ? [across(legend)] : []),\n ],\n }) as unknown as Node2D\n}\n\n/** Every view under `children`, depth first in build order: the axis beside the plot comes before its twin, which holds no parts. */\nexport function chartViews(children: readonly ChildView[]): ChildView[] {\n const out: ChildView[] = []\n const walk = (views: readonly ChildView[]) => {\n for (const view of views) {\n out.push(view)\n walk(view.children)\n }\n }\n walk(children)\n return out\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\n/**\n * A text style as props bound to `read`, so a style tween reaches text built\n * once. Only the keys set at build are bound: an unset family stays unset, so\n * the host's default face still applies.\n */\nexport function boundText(read: () => TextStyle): Record<string, unknown> {\n const keys = Object.keys(textOps.styleProps(read())) as (keyof TextStyle)[]\n const props: Record<string, unknown> = {}\n for (const key of keys) props[key] = () => read()[key]\n return props\n}\n\ninterface GhostSpec {\n readonly captions: () => readonly string[]\n /** How many captions the real axis built. */\n readonly count: number\n readonly text: () => TextStyle\n readonly title: string\n readonly titleText: () => TextStyle\n readonly tickPad: () => number\n readonly titlePad: () => number\n}\n\n/**\n * An invisible column as wide as a vertical axis built from the same captions:\n * the widest caption plus the tick padding, and the rotated title before it. A\n * plain tree, so a command looking for the axis never finds this instead.\n */\nexport function columnGhost(spec: GhostSpec): Node2D {\n const captions = Array.from({ length: spec.count }, (_, i) => new Text({ ...boundText(spec.text), text: () => spec.captions()[i] ?? \"\" }))\n const children: Node2D[] = []\n if (spec.title !== \"\") {\n children.push(new RotatedBox({ angle: -90, width: \"hug\", height: \"hug\", children: new Text({ ...boundText(spec.titleText), text: spec.title }) }) as unknown as Node2D)\n }\n children.push(new Rect({ flow: \"vertical\", width: \"hug\", height: \"hug\", padding: () => ({ right: spec.tickPad() }), children: captions }) as unknown as Node2D)\n return new Rect({ opacity: 0, flow: \"horizontal\", gap: spec.titlePad, width: \"hug\", height: 0, children }) as unknown as Node2D\n}\n\n/** `fill` with every layer's opacity scaled by `k`. */\nexport function fade(fill: Fill, k: number): Fill {\n const layers = (Array.isArray(fill) ? fill : [fill]) as FillResolved[]\n return layers.map((layer) => (typeof layer === \"object\" && layer !== null ? { ...layer, opacity: ((layer as { opacity?: number }).opacity ?? 1) * k } : layer)) as Fill\n}\n", "import {\n Graphics2D,\n Types,\n component2d,\n fillOps,\n strokeOps,\n type Fill,\n type FillResolved,\n type NodeOf,\n // Named so this component's emitted type reaches `Node2D` and its props through the sdk, not core.\n type Node2D as _Node2D,\n type Node2DProps as _Node2DProps,\n type RenderContext,\n type Stroke,\n type StrokeResolved,\n type Vector2,\n} from \"@motionscript/sdk\"\n\nimport { fresh } from \"./entries\"\nimport { loadPaints } from \"./paints\"\nimport type { Range } from \"./shared\"\n\nconst strokeEntry = () => Types.custom<Stroke, StrokeResolved[]>([], { resolve: strokeOps.resolve, lerp: strokeOps.lerp })\n\n/** Where along a scale a fraction lands in a run of `length` px centred on 0. */\nfunction along(value: number, [min, max]: Range, length: number): number {\n return (max <= min ? 0 : (value - min) / (max - min) - 0.5) * length\n}\n\n/** One rule per draw: stroking a union of open paths paints nothing, and a dashed rule keeps its own phase. */\nexport function rule(ctx: RenderContext, from: Vector2, to: Vector2, stroke: StrokeResolved[], opacity = 1): void {\n ctx.draw(new Graphics2D().line({ points: [from, to] }).stroke(stroke).opacity(opacity))\n}\n\n/**\n * The plot backdrop: the panel fill, the grid and the axis rules, sized from its\n * box. Grid lines are placed from data-unit marker positions mapped through the\n * extents, so each lands under its marker however the markers are spaced; a line\n * on an edge is drawn just inside it.\n */\nexport const ChartCanvas = component2d({\n key: \"chartCanvas\",\n state: {\n fill: Types.custom<Fill, FillResolved[]>([], { resolve: fillOps.resolve, lerp: fillOps.lerp }),\n /** The vertical grid lines, one per `xMarkers` entry. */\n xGridStroke: strokeEntry(),\n /** The horizontal grid lines, one per `yMarkers` entry. */\n yGridStroke: strokeEntry(),\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 /** The baseline and the value-axis rule. */\n axisStroke: strokeEntry(),\n /** Where the horizontal axis rule sits on the y scale, or `null` for none. */\n xAxisAt: Types.custom<number | null>(null),\n /** Where the vertical axis rule sits on the x scale, or `null` for none. */\n yAxisAt: Types.custom<number | null>(null),\n },\n load: (loader, state) => loadPaints(loader, { fills: [state.fill], strokes: [state.xGridStroke, state.yGridStroke, state.axisStroke] }),\n render: (ctx, state) => {\n const { width: W, height: H } = ctx.size\n if (W <= 0 || H <= 0) return\n if (state.fill.length > 0) ctx.draw(new Graphics2D().rect({ x: 0, y: 0, width: W, height: H }).fill(state.fill))\n\n const inside = (at: number, length: number, weight: number) => Math.max(-length / 2 + weight / 2, Math.min(length / 2 - weight / 2, at))\n const verticals = (values: readonly number[], stroke: StrokeResolved[]) => {\n const weight = stroke[0]?.weight ?? 0\n if (weight <= 0) return\n for (const v of values) {\n const x = inside(along(v, state.xExtent, W), W, weight)\n rule(ctx, { x, y: -H / 2 }, { x, y: H / 2 }, stroke)\n }\n }\n const horizontals = (values: readonly number[], stroke: StrokeResolved[]) => {\n const weight = stroke[0]?.weight ?? 0\n if (weight <= 0) return\n for (const v of values) {\n const y = inside(along(v, state.yExtent, H), H, weight)\n rule(ctx, { x: -W / 2, y }, { x: W / 2, y }, stroke)\n }\n }\n const within = ([min, max]: Range) => (v: number) => v >= Math.min(min, max) - 1e-9 && v <= Math.max(min, max) + 1e-9\n verticals(state.xMarkers.filter(within(state.xExtent)), state.xGridStroke)\n horizontals(state.yMarkers.filter(within(state.yExtent)), state.yGridStroke)\n if (state.xAxisAt !== null) horizontals([state.xAxisAt], state.axisStroke)\n if (state.yAxisAt !== null) verticals([state.yAxisAt], state.axisStroke)\n },\n})\n\nexport type ChartCanvas = NodeOf<typeof ChartCanvas>\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 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 Rect,\n Text,\n Types,\n component2d,\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 { boundText } from \"./cartesian\"\nimport { asParts, fresh } from \"./entries\"\nimport { armed, arrival, arrivalOf, arrivalsEntry, beats, frameEase, type Arrival } from \"./motion\"\nimport { DEFAULT_X_AXIS, type AxisConfig, type Range } from \"./shared\"\nimport { axisPads, markerCaption } from \"./vertical-axis\"\n\nconst SLIDE = 24\n\n/**\n * A row of {@link Text} markers under the plot, the mirror of `VerticalAxis`\n * (bound text and positions, landed resting state). Markers are placed by value\n * across the range, whatever they say: `2026-03` sits three months along, not\n * three slots along, unlike a bar chart's category axis. An end marker may hang\n * past the row by `overhang` px on either side, then is held inside it.\n */\nexport const HorizontalAxis = component2d({\n key: \"horizontalAxis\",\n state: {\n range: fresh<Range>(() => [0, 1]),\n /** Tick values in data units. */\n markers: fresh<number[]>(() => []),\n /** One caption per marker in its order; a missing one reads as the bare numeric value. */\n captions: fresh<string[]>(() => []),\n axis: Types.custom<AxisConfig>(DEFAULT_X_AXIS),\n /** Caption centred beneath the markers; empty hides it. */\n label: \"\",\n /** How far past the row's left and right ends a marker may reach, in px. */\n overhang: Types.custom<{ left: number; right: number }>({ left: 0, right: 0 }),\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 pads = () => axisPads(state.axis, \"top\")\n const sorted = () => [...state.markers].sort((a, b) => a - b)\n const fracAt = (value: number | undefined) => {\n if (value === undefined) return 0\n const [min, max] = state.range\n return max <= min ? 0 : (value - min) / (max - min)\n }\n\n const markers = state.markers.map((_, i) => {\n const width = () => (marker.parent as Node2D | null)?.layoutBounds.width ?? 0\n const marker: Node2D = new Text({\n ...boundText(() => state.axis.labelStyle),\n text: () => {\n const value = sorted()[i]\n return value === undefined ? \"\" : markerCaption(state, value)\n },\n x: () => {\n const w = width()\n const half = marker.layoutBounds.width / 2\n const centred = (fracAt(sorted()[i]) - 0.5) * w\n return Math.max(-w / 2 - state.overhang.left + half, Math.min(w / 2 + state.overhang.right - half, centred))\n },\n opacity: () => arrivalOf(state.arrivals, i).opacity,\n y: () => arrivalOf(state.arrivals, i).shift,\n })\n return marker\n })\n\n const children: Node2D[] = [\n new Rect({ width: \"fill\", height: \"hug\", padding: () => ({ top: pads().tick }), children: markers }) as unknown as Node2D,\n ]\n if (state.label !== \"\") {\n children.push(\n new Text({\n ...boundText(() => state.axis.titleStyle),\n text: state.label,\n opacity: () => arrivalOf(state.arrivals, \"label\").opacity,\n y: () => arrivalOf(state.arrivals, \"label\").shift,\n }) as unknown as Node2D\n )\n }\n return asParts([new Rect({ flow: \"vertical\", gap: () => pads().title, height: \"hug\", width: \"fill\", children }) as unknown as Node2D])\n },\n commands: {\n /** Stagger markers in left to right, then the caption. The duration is the whole entrance ({@link enterBudget}). */\n enter: {\n args: {\n stagger: Types.custom<number | undefined>(undefined),\n slide: Types.number(SLIDE),\n },\n run: (timeline, state) => {\n const { stagger, slide } = timeline.args\n const count = state.markers.length\n const captioned = state.label !== \"\"\n const from: Arrival = { opacity: 0, shift: slide }\n const keys = [...state.markers.keys(), ...(captioned ? [\"label\"] : [])]\n const arm = timeline.animate(() => ({ arrivals: armed(keys, from) }))\n if (count === 0) return arm\n const { step, per, caption } = enterBudget(timeline.duration, count, captioned, stagger)\n const ease = frameEase(timeline)\n const markers = state.markers.map((_, i) => ({ at: i * step, duration: per, piece: arrival(timeline, i, from, ease) }))\n const label = captioned ? [{ at: (count - 1) * step + per, duration: caption, piece: arrival(timeline, \"label\", from, ease) }] : []\n return timeline.together([arm, beats(timeline, [...markers, ...label])])\n },\n },\n },\n})\n\nexport type HorizontalAxis = NodeOf<typeof HorizontalAxis>\n", "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/** Where a legend waits before it comes up: below its place, above it, or to its right. */\nexport function legendAway(at: string): { x?: number; y?: number } {\n if (at === \"top\") return { y: LEGEND_SLIDE }\n if (at === \"right\") return { x: LEGEND_SLIDE }\n return { y: -LEGEND_SLIDE }\n}\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 Rect,\n RotatedBox,\n Text,\n Types,\n component2d,\n insetsOps,\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 { boundText } from \"./cartesian\"\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/** The gap between an axis's markers and the plot, and between the markers and the caption, read off its config. */\nexport function axisPads(axis: AxisConfig, side: \"top\" | \"right\"): { tick: number; title: number } {\n return { tick: insetsOps.resolve(axis.tickPadding)[side], title: insetsOps.resolve(axis.titlePadding)[side] }\n}\n\n/**\n * A column of right-aligned captions beside the plot: `place(i)` is caption\n * `i`'s centre height in the column (y-up), whose height it is handed. The\n * value axis and a horizontal bar chart's category axis are both this column.\n */\nexport function captionColumn(spec: {\n readonly count: number\n readonly axis: () => AxisConfig\n readonly text: (i: number) => string\n readonly place: (i: number, height: number) => number\n readonly arrivals: () => Readonly<Record<string, Arrival>>\n readonly opacity?: (i: number) => number\n readonly label: string\n}): Node2D {\n const pads = () => axisPads(spec.axis(), \"right\")\n const markers = Array.from({ length: spec.count }, (_, i) => {\n const column = () => (marker.parent as Node2D | null)?.layoutBounds ?? { width: 0, height: 0 }\n const marker: Node2D = new Text({\n ...boundText(() => spec.axis().labelStyle),\n text: () => spec.text(i),\n // Right-aligned against the tick padding: freeform children sit on the content box's centre.\n x: () => (column().width - pads().tick) / 2 - marker.layoutBounds.width / 2 + arrivalOf(spec.arrivals(), i).shift,\n y: () => spec.place(i, column().height),\n opacity: () => arrivalOf(spec.arrivals(), i).opacity * (spec.opacity?.(i) ?? 1),\n })\n return marker\n })\n const children: Node2D[] = []\n if (spec.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 ...boundText(() => spec.axis().titleStyle),\n text: spec.label,\n opacity: () => arrivalOf(spec.arrivals(), \"label\").opacity,\n x: () => arrivalOf(spec.arrivals(), \"label\").shift,\n }),\n }) as unknown as Node2D\n )\n }\n children.push(new Rect({ height: \"fill\", width: \"hug\", padding: () => ({ right: pads().tick }), children: markers }) as unknown as Node2D)\n return new Rect({ flow: \"horizontal\", gap: () => pads().title, height: \"fill\", children }) as unknown as Node2D\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` and right-aligned against the plot. Caption and position are bound, so\n * a rescale tweens live; only the marker count is fixed at construction. The\n * 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 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 // A slot with no value (the live list is shorter than the column built) renders empty, not its neighbour.\n return asParts([\n captionColumn({\n count: state.markers.length,\n axis: () => state.axis,\n text: (i) => {\n const value = sorted()[i]\n return value === undefined ? \"\" : markerCaption(state, value)\n },\n place: (i, height) => (fracAt(sorted()[i]) - 0.5) * height,\n arrivals: () => state.arrivals,\n label: state.label,\n }),\n ])\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 {\n Flow,\n Paint,\n Rect,\n Shapes,\n Text,\n Types,\n component2d,\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 { boundText } from \"./cartesian\"\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 swatch and caption; `shown` scales its length\n * along the legend (`along`) from nothing. The length is measured from the\n * content at any reveal, so a frame never depends on the entry once having been\n * fully shown.\n */\nconst LegendEntry = component2d({\n key: \"legendEntry\",\n state: { ...row, shown: Types.number(1), along: Types.oneOf([\"horizontal\", \"vertical\"] as const) },\n commands: { ...Paint.commands },\n measure: (measurer, state, children) => {\n const size = Flow.measure(measurer, state, children, Paint.inset(state))\n if (state.shown >= 1) return size\n return state.along === \"vertical\" ? { ...size, height: state.shown * size.height } : { ...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/**\n * A chart's legend: one entry per series, a colour swatch then its caption, in\n * a row (`flow: \"horizontal\"`) or a column (`\"vertical\"`, for a legend beside\n * the plot). This node is the row, so the parent places it.\n */\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 length, 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.flow === \"vertical\" ? Math.round(state.legend.itemGap * 0.4) : state.legend.itemGap),\n padding: (state) => state.legend.padding,\n align: (state) => (state.flow === \"vertical\" ? \"centerLeft\" : \"center\"),\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 const along = state.flow === \"vertical\" ? \"vertical\" : \"horizontal\"\n return state.series.map((series, index) =>\n LegendEntry({\n flow: \"horizontal\",\n gap: () => Math.round(((state.legend.textStyle.fontSize as number | undefined) ?? 24) * 0.45),\n align: \"center\",\n width: \"hug\",\n height: \"hug\",\n along,\n // The length 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 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 Text({ ...boundText(() => state.legend.textStyle), text: series.label || series.field }),\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", "import {\n Flow,\n Paint,\n Rect,\n Shapes,\n Text,\n Types,\n clamp,\n component2d,\n textOps,\n type NodeOf,\n // Named so the column's emitted type reaches the Rect surface it spreads through the sdk, not core.\n type Alignment as _Alignment,\n type CornerRadiusResolved as _CornerRadiusResolved,\n type CornerStyleResolved as _CornerStyleResolved,\n type Fill as _Fill,\n type FillResolved as _FillResolved,\n type FlowMode as _FlowMode,\n type FlowResolved as _FlowResolved,\n type GapSize as _GapSize,\n type Node2D as _Node2D,\n type Node2DProps as _Node2DProps,\n type RectCornerRadius as _RectCornerRadius,\n type RectCornerStyle as _RectCornerStyle,\n type Shadow as _Shadow,\n type ShadowResolved as _ShadowResolved,\n type Stroke as _Stroke,\n type StrokeResolved as _StrokeResolved,\n type Vector2 as _Vector2,\n} from \"@motionscript/sdk\"\n\nimport { fresh } from \"./entries\"\nimport { armed, arrival, arrivalOf, arrivalsEntry, beats, frameEase, type Arrival } from \"./motion\"\nimport { DEFAULT_LEGEND, type LegendConfig } from \"./shared\"\nimport type { PieSlice } from \"./polar\"\n\nconst SLIDE = 16\n\n/**\n * The legend of a {@link PieChart}: a column (it sits beside the ring, in the\n * vertical strip it leaves) of caption-and-swatch entries, one per slice. No\n * show/hide: removing a row would re-cut every other wedge's share. Selection\n * arrives through `dims`.\n */\nexport const PieLegend = component2d({\n key: \"pieLegend\",\n state: {\n ...Paint.state,\n ...Flow.state,\n ...Shapes.corners,\n /** One entry per slice, in ring order. */\n slices: fresh<PieSlice[]>(() => []),\n legend: Types.custom<LegendConfig>(DEFAULT_LEGEND),\n /** Per-slice opacity multiplier, the signal that dims the ring, so an entry fades in step with its wedge. Missing reads as 1. */\n dims: fresh<number[]>(() => []),\n arrivals: arrivalsEntry(),\n },\n // The flow must be stated: a `Rect` with none lays children out `freeform`, every caption on top of the last.\n defaults: {\n flow: \"vertical\",\n align: \"centerLeft\",\n width: \"hug\",\n height: \"hug\",\n gap: (state) => state.legend.itemGap / 3,\n padding: (state) => state.legend.padding,\n },\n // The selection dim rides a wrapper, so the entrance animates the entry's own opacity without the two fighting over one value.\n children: (state) => {\n const marker = () => state.legend.markerStyle\n return state.slices.map((_, index) =>\n Rect({\n width: \"hug\",\n height: \"hug\",\n flow: \"freeform\",\n opacity: () => clamp(state.dims[index] ?? 1, 0, 1),\n children: [\n Rect({\n flow: \"horizontal\",\n gap: () => Math.round(state.legend.textStyle.fontSize === undefined ? 12 : Number(state.legend.textStyle.fontSize) * 0.4),\n align: \"center\",\n width: \"hug\",\n height: \"hug\",\n opacity: () => arrivalOf(state.arrivals, index).opacity,\n x: () => arrivalOf(state.arrivals, index).shift,\n children: [\n Rect({\n width: () => marker().width,\n height: () => marker().height,\n cornerRadius: () => marker().borderRadius,\n fill: () => state.slices[index]?.fill ?? \"white\",\n }),\n Text({\n ...textOps.styleProps(state.legend.textStyle),\n fill: () => state.legend.textStyle.fill ?? \"white\",\n fontSize: () => state.legend.textStyle.fontSize ?? 28,\n fontWeight: () => state.legend.textStyle.fontWeight ?? 500,\n text: () => state.slices[index]?.category ?? \"\",\n }),\n ],\n }),\n ],\n })\n )\n },\n commands: {\n ...Paint.commands,\n /** Every entry shifted right and transparent: what a chart shows ahead of this legend's beat, since `enter` arms only on its first frame. */\n arm: (timeline, state) =>\n timeline.animate(() => ({ arrivals: armed([...state.slices.keys()], { opacity: 0, shift: SLIDE }) })),\n /** Slide and fade entries in from the right, top to bottom. The duration is the whole entrance, the stagger carved out of it. */\n enter: (timeline, state) => {\n const count = state.slices.length\n if (count === 0) return timeline.wait(timeline.duration)\n const from: Arrival = { opacity: 0, shift: SLIDE }\n const arm = timeline.animate(() => ({ arrivals: armed([...state.slices.keys()], from) }))\n // Each gap is a fifth of an entry's move, the axes' rhythm, solved from the budget.\n const per = timeline.duration / (1 + Math.max(0, count - 1) / 5)\n const step = per / 5\n const ease = frameEase(timeline)\n const entries = state.slices.map((_, i) => ({ at: i * step, duration: per, piece: arrival(timeline, i, from, ease) }))\n return timeline.together([arm, beats(timeline, entries)])\n },\n },\n measure: (measurer, state, children) => Flow.measure(measurer, state, children, Paint.inset(state)),\n layout: (box, state, children) => Flow.layout(box, state, children, Paint.inset(state)),\n render: (ctx, state) => Paint.draw(ctx, state, Shapes.rect(ctx.size, state)),\n})\n\nexport type PieLegend = NodeOf<typeof PieLegend>\n", "/** What the polar charts (pie, radial) share: slices, ring geometry, the hole's summary and the selection fade. */\n\nimport { clamp, fillOps, type Fill, type FillResolved, type TextStyle, type Vector2 } from \"@motionscript/sdk\"\n\n/** One resolved slice, which the ring and legend consume; the chart resolves it from `data` and two field names. */\nexport interface PieSlice {\n /** Label and legend caption. */\n category: string\n /** The wedge covers `value / (sum of all values)`. */\n value: number\n /** Wedge and swatch paint. */\n fill: Fill\n}\n\nexport const DEG = Math.PI / 180\n\n/**\n * Opacity of a slice under the selection: 1 while nothing is out (`focus` is the\n * most-grown pop) and for the selected slice itself, falling toward `dimOpacity`\n * for the rest as the selection grows.\n */\nexport function selectionFade(focus: number, dimOpacity: number, pop: number): number {\n if (focus <= 0) return 1\n return 1 - (1 - clamp(dimOpacity, 0, 1)) * focus * (1 - pop)\n}\n\n/** The point at radius `r`, angle `a` on a ring about the origin in centred y-up space. Angles run clockwise from 12 o'clock. */\nexport function ringPoint(r: number, a: number): Vector2 {\n return { x: r * Math.sin(a), y: r * Math.cos(a) }\n}\n\n/** The summary set in the ring's hole. */\nexport interface CenterConfig {\n labelStyle: TextStyle\n captionStyle: TextStyle\n}\n\n/** How far everything outside the selection fades while any slice is selected; fainter than a gapless chart's, as a ring's slices touch. */\nexport const PIE_SPOTLIGHT_DIM = 0.15\n\nconst resolvedFills = new WeakMap<object, FillResolved[]>()\n\nexport function resolvedFill(fill: Fill): FillResolved[] {\n if (typeof fill !== \"object\" || fill === null) return fillOps.resolve(fill)\n let resolved = resolvedFills.get(fill)\n if (resolved === undefined) resolvedFills.set(fill, resolved = fillOps.resolve(fill))\n return resolved\n}\n\n/** Each slice's paint, resolved once per fill object. */\nexport function ringFills(slices: readonly PieSlice[]): FillResolved[][] {\n return slices.map((slice) => resolvedFill(slice.fill))\n}\n\n", "/**\n * The chart kit: what the five 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/style\"\nexport * from \"./kit/cartesian\"\nexport * from \"./kit/chart-canvas\"\nexport * from \"./kit/horizontal-axis\"\nexport * from \"./kit/chart-legend\"\nexport * from \"./kit/entries\"\nexport * from \"./kit/motion\"\nexport * from \"./kit/paints\"\nexport * from \"./kit/pie-legend\"\nexport * from \"./kit/polar\"\nexport * from \"./kit/vertical-axis\"\nexport * from \"@motionscript/sdk/component\"\n"],
|
|
5
|
-
"mappings": "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",
|
|
6
|
-
"names": ["lerpNumber", "niceStep", "resolveAxisDomain", "domain", "previous", "lerpAxisDomain", "from", "to", "t", "lerpOptionalRange", "lerpOptionalTicks", "out", "blendOf", "lerpAxisEntry", "rangeMoved", "target", "markerValues", "blended", "moved", "auto", "settleAxisDomain", "drawn", "blend", "CHART_PALETTE", "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_LEGEND", "formatMarker", "value", "step", "decimals", "decimalsFor", "d", "scaled", "markerStep", "markers", "sorted", "a", "b", "i", "gap", "formatPercent", "fraction", "pct", "min", "max", "markerCount", "_", "niceRange", "lo", "hi", "divisions", "segments", "constantScale", "niceTicks", "span", "whole", "base", "best", "ladder", "parts", "first", "k", "mag", "rungs", "m", "at", "r", "Types", "textOps", "CHART_STYLE_FAMILY", "CHART_PALETTE_DEFAULT", "CHART_FOREGROUND", "CHART_MUTED", "CHART_SERIES", "CHART_BACKGROUND", "GRID_BACKGROUND", "LEGEND_TEXT", "CARTESIAN_TEXT", "CARTESIAN_GRID", "CHART_LEGEND", "_PRESET_FIELDS", "inks", "foreground", "muted", "on", "fill", "rules", "CHART_STYLE_PRESETS", "paletteFill", "style", "index", "own", "fills", "seriesFill", "series", "sizeOf", "text", "fallback", "size", "placedText", "textAlign", "over", "markerText", "axis", "valueText", "axisConfigOf", "gap", "legendConfigOf", "type", "marker", "migrateChartStyle", "layout", "value", "old", "retired", "plotBackground", "key", "palette", "fontFamily", "fontSize", "fontWeight", "barRadius", "rest", "out", "weight", "ink", "scale", "heavier", "t", "fields", "field", "Rect", "RotatedBox", "Text", "textOps", "frameGap", "style", "sizeOf", "headroom", "overhang", "cartesianFrame", "parts", "rows", "Rect", "body", "legend", "main", "across", "node", "chartViews", "children", "out", "walk", "views", "view", "laidOutSize", "bounds", "boundText", "read", "keys", "textOps", "props", "key", "columnGhost", "spec", "captions", "_", "i", "Text", "RotatedBox", "fade", "fill", "k", "layer", "Graphics2D", "Types", "component2d", "fillOps", "strokeOps", "Types", "fresh", "make", "options", "asParts", "nodes", "SERIES_ARG", "loadPaints", "loader", "paints", "fill", "strokes", "stroke", "shadows", "shadow", "strokeEntry", "Types", "strokeOps", "along", "value", "min", "max", "length", "rule", "ctx", "from", "to", "stroke", "opacity", "Graphics2D", "ChartCanvas", "component2d", "fillOps", "fresh", "loader", "state", "loadPaints", "W", "H", "inside", "at", "weight", "verticals", "values", "v", "x", "horizontals", "y", "within", "Rect", "Text", "Types", "component2d", "enterBudget", "Types", "easeOut", "identity", "t", "LEGEND_SLIDE", "legendAway", "at", "DEFAULT_MARKERS", "ENTER_SHARE", "frameEase", "timeline", "beats", "parts", "total", "natural", "end", "part", "k", "duration", "piece", "start", "length", "LANDED", "arrivalsEntry", "next", "previous", "arrivalOf", "arrivals", "key", "armed", "keys", "from", "record", "arrival", "ease", "e", "Rect", "RotatedBox", "Text", "Types", "component2d", "insetsOps", "enterBudget", "SLIDE", "markerCaption", "s", "value", "index", "formatMarker", "axisPads", "axis", "side", "insetsOps", "captionColumn", "spec", "pads", "markers", "_", "column", "marker", "Text", "boundText", "arrivalOf", "children", "RotatedBox", "Rect", "VerticalAxis", "component2d", "fresh", "Types", "DEFAULT_Y_AXIS", "arrivalsEntry", "state", "sorted", "a", "b", "fracAt", "min", "max", "i", "height", "timeline", "stagger", "slide", "count", "captioned", "from", "keys", "arm", "armed", "step", "per", "caption", "enterBudget", "ease", "frameEase", "arrival", "label", "beats", "SLIDE", "HorizontalAxis", "component2d", "fresh", "Types", "DEFAULT_X_AXIS", "arrivalsEntry", "state", "pads", "axisPads", "sorted", "b", "fracAt", "value", "min", "max", "markers", "_", "i", "width", "marker", "Text", "boundText", "markerCaption", "w", "half", "centred", "arrivalOf", "children", "Rect", "timeline", "stagger", "slide", "count", "captioned", "from", "keys", "arm", "armed", "step", "per", "caption", "enterBudget", "ease", "frameEase", "arrival", "label", "beats", "Flow", "Paint", "Rect", "Shapes", "Text", "Types", "component2d", "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", "along", "series", "Rect", "Text", "boundText", "timeline", "revealFrame", "frameEase", "entry", "i", "SPOTLIGHT_DIM", "target", "ease", "from", "t", "Flow", "Paint", "Rect", "Shapes", "Text", "Types", "clamp", "component2d", "textOps", "SLIDE", "PieLegend", "component2d", "Paint", "Flow", "Shapes", "fresh", "Types", "DEFAULT_LEGEND", "arrivalsEntry", "state", "marker", "_", "index", "Rect", "clamp", "arrivalOf", "Text", "textOps", "timeline", "armed", "count", "from", "arm", "per", "step", "ease", "frameEase", "entries", "i", "arrival", "beats", "measurer", "children", "box", "ctx", "clamp", "fillOps", "DEG", "selectionFade", "focus", "dimOpacity", "pop", "ringPoint", "r", "a", "PIE_SPOTLIGHT_DIM", "resolvedFills", "resolvedFill", "fill", "resolved", "ringFills", "slices", "slice"]
|
|
7
|
-
}
|