@motionscript/charts 0.1.1-alpha.0 → 0.1.1-alpha.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +19 -0
- package/README.md +98 -28
- package/dist/bar-chart/bar-chart.d.ts +233 -39
- package/dist/bar-chart/bar-chart.d.ts.map +1 -1
- package/dist/bar-chart/bar-chart.js +215 -171
- package/dist/bar-chart/bar-chart.js.map +1 -1
- package/dist/bar-chart/category-axis.d.ts +12 -7
- package/dist/bar-chart/category-axis.d.ts.map +1 -1
- package/dist/bar-chart/category-axis.js +56 -42
- package/dist/bar-chart/category-axis.js.map +1 -1
- package/dist/bar-chart/chart-bars.d.ts +52 -52
- package/dist/bar-chart/chart-bars.d.ts.map +1 -1
- package/dist/bar-chart/chart-bars.js +80 -89
- package/dist/bar-chart/chart-bars.js.map +1 -1
- package/dist/bar-chart/index.d.ts +4 -4
- package/dist/bar-chart/index.d.ts.map +1 -1
- package/dist/bar-chart/index.js +2 -2
- package/dist/bar-chart/index.js.map +1 -1
- package/dist/bar-chart/shared.d.ts +36 -65
- package/dist/bar-chart/shared.d.ts.map +1 -1
- package/dist/bar-chart/shared.js +68 -117
- package/dist/bar-chart/shared.js.map +1 -1
- package/dist/browser/chunks/chunk-R3Q5EE6E.js +2 -0
- package/dist/browser/chunks/chunk-R3Q5EE6E.js.map +7 -0
- package/dist/browser/index.js +1 -1
- package/dist/browser/index.js.map +4 -4
- package/dist/browser/kit.js +1 -1
- package/dist/browser/manifest.json +1 -1
- package/dist/engine.d.ts +5 -2
- package/dist/engine.d.ts.map +1 -1
- package/dist/engine.js +5 -2
- package/dist/engine.js.map +1 -1
- package/dist/index.d.ts +2 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2 -0
- package/dist/index.js.map +1 -1
- package/dist/kit/cartesian.d.ts +49 -15
- package/dist/kit/cartesian.d.ts.map +1 -1
- package/dist/kit/cartesian.js +79 -29
- package/dist/kit/cartesian.js.map +1 -1
- package/dist/kit/chart-canvas.d.ts +32 -24
- package/dist/kit/chart-canvas.d.ts.map +1 -1
- package/dist/kit/chart-canvas.js +52 -46
- package/dist/kit/chart-canvas.js.map +1 -1
- package/dist/kit/chart-legend.d.ts +8 -4
- package/dist/kit/chart-legend.d.ts.map +1 -1
- package/dist/kit/chart-legend.js +30 -20
- package/dist/kit/chart-legend.js.map +1 -1
- package/dist/{line-chart → kit}/horizontal-axis.d.ts +31 -6
- package/dist/kit/horizontal-axis.d.ts.map +1 -0
- package/dist/{line-chart → kit}/horizontal-axis.js +23 -24
- package/dist/kit/horizontal-axis.js.map +1 -0
- package/dist/kit/motion.d.ts +5 -0
- package/dist/kit/motion.d.ts.map +1 -1
- package/dist/kit/motion.js +8 -0
- package/dist/kit/motion.js.map +1 -1
- package/dist/{pie-chart → kit}/pie-legend.d.ts +3 -3
- package/dist/kit/pie-legend.d.ts.map +1 -0
- package/dist/{pie-chart → kit}/pie-legend.js +11 -10
- package/dist/kit/pie-legend.js.map +1 -0
- package/dist/kit/polar.d.ts +31 -0
- package/dist/kit/polar.d.ts.map +1 -0
- package/dist/kit/polar.js +33 -0
- package/dist/kit/polar.js.map +1 -0
- package/dist/kit/shared.d.ts +11 -50
- package/dist/kit/shared.d.ts.map +1 -1
- package/dist/kit/shared.js +58 -141
- package/dist/kit/shared.js.map +1 -1
- package/dist/kit/style.d.ts +254 -0
- package/dist/kit/style.d.ts.map +1 -0
- package/dist/kit/style.js +197 -0
- package/dist/kit/style.js.map +1 -0
- package/dist/kit/vertical-axis.d.ts +22 -2
- package/dist/kit/vertical-axis.d.ts.map +1 -1
- package/dist/kit/vertical-axis.js +56 -43
- package/dist/kit/vertical-axis.js.map +1 -1
- package/dist/line-chart/chart-line.d.ts +95 -3
- package/dist/line-chart/chart-line.d.ts.map +1 -1
- package/dist/line-chart/chart-line.js +165 -53
- package/dist/line-chart/chart-line.js.map +1 -1
- package/dist/line-chart/chart-region.d.ts +1 -1
- package/dist/line-chart/chart-region.d.ts.map +1 -1
- package/dist/line-chart/chart-region.js +7 -8
- package/dist/line-chart/chart-region.js.map +1 -1
- package/dist/line-chart/index.d.ts +5 -6
- package/dist/line-chart/index.d.ts.map +1 -1
- package/dist/line-chart/index.js +3 -4
- package/dist/line-chart/index.js.map +1 -1
- package/dist/line-chart/line-chart.d.ts +257 -18
- package/dist/line-chart/line-chart.d.ts.map +1 -1
- package/dist/line-chart/line-chart.js +282 -134
- package/dist/line-chart/line-chart.js.map +1 -1
- package/dist/line-chart/shared.d.ts +51 -34
- package/dist/line-chart/shared.d.ts.map +1 -1
- package/dist/line-chart/shared.js +175 -83
- package/dist/line-chart/shared.js.map +1 -1
- package/dist/line-chart/x-scale.d.ts +2 -0
- package/dist/line-chart/x-scale.d.ts.map +1 -1
- package/dist/line-chart/x-scale.js +15 -0
- package/dist/line-chart/x-scale.js.map +1 -1
- package/dist/nodes.d.ts +3 -1
- package/dist/nodes.d.ts.map +1 -1
- package/dist/nodes.js +9 -1
- package/dist/nodes.js.map +1 -1
- package/dist/pie-chart/index.d.ts +2 -3
- package/dist/pie-chart/index.d.ts.map +1 -1
- package/dist/pie-chart/index.js +1 -2
- package/dist/pie-chart/index.js.map +1 -1
- package/dist/pie-chart/pie-chart.d.ts +114 -18
- package/dist/pie-chart/pie-chart.d.ts.map +1 -1
- package/dist/pie-chart/pie-chart.js +37 -24
- package/dist/pie-chart/pie-chart.js.map +1 -1
- package/dist/pie-chart/pie-ring.d.ts +16 -5
- package/dist/pie-chart/pie-ring.d.ts.map +1 -1
- package/dist/pie-chart/pie-ring.js +89 -55
- package/dist/pie-chart/pie-ring.js.map +1 -1
- package/dist/pie-chart/shared.d.ts +53 -61
- package/dist/pie-chart/shared.d.ts.map +1 -1
- package/dist/pie-chart/shared.js +41 -121
- package/dist/pie-chart/shared.js.map +1 -1
- package/dist/radar-chart/index.d.ts +5 -0
- package/dist/radar-chart/index.d.ts.map +1 -0
- package/dist/radar-chart/index.js +5 -0
- package/dist/radar-chart/index.js.map +1 -0
- package/dist/radar-chart/radar-chart.d.ts +218 -0
- package/dist/radar-chart/radar-chart.d.ts.map +1 -0
- package/dist/radar-chart/radar-chart.js +224 -0
- package/dist/radar-chart/radar-chart.js.map +1 -0
- package/dist/radar-chart/radar-grid.d.ts +43 -0
- package/dist/radar-chart/radar-grid.d.ts.map +1 -0
- package/dist/radar-chart/radar-grid.js +61 -0
- package/dist/radar-chart/radar-grid.js.map +1 -0
- package/dist/radar-chart/radar-series.d.ts +59 -0
- package/dist/radar-chart/radar-series.d.ts.map +1 -0
- package/dist/radar-chart/radar-series.js +71 -0
- package/dist/radar-chart/radar-series.js.map +1 -0
- package/dist/radar-chart/shared.d.ts +73 -0
- package/dist/radar-chart/shared.d.ts.map +1 -0
- package/dist/radar-chart/shared.js +123 -0
- package/dist/radar-chart/shared.js.map +1 -0
- package/dist/radial-chart/index.d.ts +6 -0
- package/dist/radial-chart/index.d.ts.map +1 -0
- package/dist/radial-chart/index.js +4 -0
- package/dist/radial-chart/index.js.map +1 -0
- package/dist/radial-chart/radial-chart.d.ts +216 -0
- package/dist/radial-chart/radial-chart.d.ts.map +1 -0
- package/dist/radial-chart/radial-chart.js +174 -0
- package/dist/radial-chart/radial-chart.js.map +1 -0
- package/dist/radial-chart/radial-rings.d.ts +121 -0
- package/dist/radial-chart/radial-rings.d.ts.map +1 -0
- package/dist/radial-chart/radial-rings.js +273 -0
- package/dist/radial-chart/radial-rings.js.map +1 -0
- package/dist/radial-chart/shared.d.ts +73 -0
- package/dist/radial-chart/shared.d.ts.map +1 -0
- package/dist/radial-chart/shared.js +79 -0
- package/dist/radial-chart/shared.js.map +1 -0
- package/package.json +4 -4
- package/registry.json +21 -6
- package/src/bar-chart/bar-chart.ts +252 -179
- package/src/bar-chart/category-axis.ts +46 -40
- package/src/bar-chart/chart-bars.ts +97 -117
- package/src/bar-chart/index.ts +7 -10
- package/src/bar-chart/shared.ts +78 -238
- package/src/engine.ts +5 -2
- package/src/index.ts +2 -0
- package/src/kit/cartesian.ts +118 -40
- package/src/kit/chart-canvas.ts +49 -54
- package/src/kit/chart-legend.ts +28 -20
- package/src/kit/horizontal-axis.ts +114 -0
- package/src/kit/motion.ts +7 -0
- package/src/{pie-chart → kit}/pie-legend.ts +12 -11
- package/src/kit/polar.ts +54 -0
- package/src/kit/shared.ts +55 -277
- package/src/kit/style.ts +257 -0
- package/src/kit/vertical-axis.ts +67 -48
- package/src/line-chart/chart-line.ts +176 -54
- package/src/line-chart/chart-region.ts +6 -10
- package/src/line-chart/index.ts +14 -10
- package/src/line-chart/line-chart.ts +347 -151
- package/src/line-chart/shared.ts +193 -174
- package/src/line-chart/x-scale.ts +13 -0
- package/src/nodes.ts +9 -1
- package/src/pie-chart/index.ts +2 -23
- package/src/pie-chart/pie-chart.ts +52 -35
- package/src/pie-chart/pie-ring.ts +92 -71
- package/src/pie-chart/shared.ts +68 -266
- package/src/radar-chart/index.ts +4 -0
- package/src/radar-chart/radar-chart.ts +287 -0
- package/src/radar-chart/radar-grid.ts +78 -0
- package/src/radar-chart/radar-series.ts +88 -0
- package/src/radar-chart/shared.ts +146 -0
- package/src/radial-chart/index.ts +5 -0
- package/src/radial-chart/radial-chart.ts +210 -0
- package/src/radial-chart/radial-rings.ts +328 -0
- package/src/radial-chart/shared.ts +114 -0
- package/dist/browser/chunks/chunk-4SMRCU24.js +0 -2
- package/dist/browser/chunks/chunk-4SMRCU24.js.map +0 -7
- package/dist/kit/chart-border.d.ts +0 -18
- package/dist/kit/chart-border.d.ts.map +0 -1
- package/dist/kit/chart-border.js +0 -23
- package/dist/kit/chart-border.js.map +0 -1
- package/dist/line-chart/horizontal-axis.d.ts.map +0 -1
- package/dist/line-chart/horizontal-axis.js.map +0 -1
- package/dist/pie-chart/pie-legend.d.ts.map +0 -1
- package/dist/pie-chart/pie-legend.js.map +0 -1
- package/src/kit/chart-border.ts +0 -36
- package/src/line-chart/horizontal-axis.ts +0 -122
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"pie-legend.js","sourceRoot":"","sources":["../../src/kit/pie-legend.ts"],"names":[],"mappings":"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","sourcesContent":["import {\n Flow,\n Paint,\n Rect,\n Shapes,\n Text,\n Types,\n clamp,\n component2d,\n textOps,\n type NodeOf,\n // Named so the column's emitted type reaches the Rect surface it spreads through the sdk, not core.\n type Alignment as _Alignment,\n type CornerRadiusResolved as _CornerRadiusResolved,\n type CornerStyleResolved as _CornerStyleResolved,\n type Fill as _Fill,\n type FillResolved as _FillResolved,\n type FlowMode as _FlowMode,\n type FlowResolved as _FlowResolved,\n type GapSize as _GapSize,\n type Node2D as _Node2D,\n type Node2DProps as _Node2DProps,\n type RectCornerRadius as _RectCornerRadius,\n type RectCornerStyle as _RectCornerStyle,\n type Shadow as _Shadow,\n type ShadowResolved as _ShadowResolved,\n type Stroke as _Stroke,\n type StrokeResolved as _StrokeResolved,\n type Vector2 as _Vector2,\n} from \"@motionscript/sdk\"\n\nimport { fresh } from \"./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"]}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
/** What the polar charts (pie, radial) share: slices, ring geometry, the hole's summary and the selection fade. */
|
|
2
|
+
import { type Fill, type FillResolved, type TextStyle, type Vector2 } from "@motionscript/sdk";
|
|
3
|
+
/** One resolved slice, which the ring and legend consume; the chart resolves it from `data` and two field names. */
|
|
4
|
+
export interface PieSlice {
|
|
5
|
+
/** Label and legend caption. */
|
|
6
|
+
category: string;
|
|
7
|
+
/** The wedge covers `value / (sum of all values)`. */
|
|
8
|
+
value: number;
|
|
9
|
+
/** Wedge and swatch paint. */
|
|
10
|
+
fill: Fill;
|
|
11
|
+
}
|
|
12
|
+
export declare const DEG: number;
|
|
13
|
+
/**
|
|
14
|
+
* Opacity of a slice under the selection: 1 while nothing is out (`focus` is the
|
|
15
|
+
* most-grown pop) and for the selected slice itself, falling toward `dimOpacity`
|
|
16
|
+
* for the rest as the selection grows.
|
|
17
|
+
*/
|
|
18
|
+
export declare function selectionFade(focus: number, dimOpacity: number, pop: number): number;
|
|
19
|
+
/** 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. */
|
|
20
|
+
export declare function ringPoint(r: number, a: number): Vector2;
|
|
21
|
+
/** The summary set in the ring's hole. */
|
|
22
|
+
export interface CenterConfig {
|
|
23
|
+
labelStyle: TextStyle;
|
|
24
|
+
captionStyle: TextStyle;
|
|
25
|
+
}
|
|
26
|
+
/** How far everything outside the selection fades while any slice is selected; fainter than a gapless chart's, as a ring's slices touch. */
|
|
27
|
+
export declare const PIE_SPOTLIGHT_DIM = 0.15;
|
|
28
|
+
export declare function resolvedFill(fill: Fill): FillResolved[];
|
|
29
|
+
/** Each slice's paint, resolved once per fill object. */
|
|
30
|
+
export declare function ringFills(slices: readonly PieSlice[]): FillResolved[][];
|
|
31
|
+
//# sourceMappingURL=polar.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"polar.d.ts","sourceRoot":"","sources":["../../src/kit/polar.ts"],"names":[],"mappings":"AAAA,mHAAmH;AAEnH,OAAO,EAAkB,KAAK,IAAI,EAAE,KAAK,YAAY,EAAE,KAAK,SAAS,EAAE,KAAK,OAAO,EAAE,MAAM,mBAAmB,CAAA;AAE9G,oHAAoH;AACpH,MAAM,WAAW,QAAQ;IACvB,gCAAgC;IAChC,QAAQ,EAAE,MAAM,CAAA;IAChB,sDAAsD;IACtD,KAAK,EAAE,MAAM,CAAA;IACb,8BAA8B;IAC9B,IAAI,EAAE,IAAI,CAAA;CACX;AAED,eAAO,MAAM,GAAG,QAAgB,CAAA;AAEhC;;;;GAIG;AACH,wBAAgB,aAAa,CAAC,KAAK,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,MAAM,CAGpF;AAED,iIAAiI;AACjI,wBAAgB,SAAS,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,MAAM,GAAG,OAAO,CAEvD;AAED,0CAA0C;AAC1C,MAAM,WAAW,YAAY;IAC3B,UAAU,EAAE,SAAS,CAAA;IACrB,YAAY,EAAE,SAAS,CAAA;CACxB;AAED,4IAA4I;AAC5I,eAAO,MAAM,iBAAiB,OAAO,CAAA;AAIrC,wBAAgB,YAAY,CAAC,IAAI,EAAE,IAAI,GAAG,YAAY,EAAE,CAKvD;AAED,yDAAyD;AACzD,wBAAgB,SAAS,CAAC,MAAM,EAAE,SAAS,QAAQ,EAAE,GAAG,YAAY,EAAE,EAAE,CAEvE"}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
/** What the polar charts (pie, radial) share: slices, ring geometry, the hole's summary and the selection fade. */
|
|
2
|
+
import { clamp, fillOps } from "@motionscript/sdk";
|
|
3
|
+
export const DEG = Math.PI / 180;
|
|
4
|
+
/**
|
|
5
|
+
* Opacity of a slice under the selection: 1 while nothing is out (`focus` is the
|
|
6
|
+
* most-grown pop) and for the selected slice itself, falling toward `dimOpacity`
|
|
7
|
+
* for the rest as the selection grows.
|
|
8
|
+
*/
|
|
9
|
+
export function selectionFade(focus, dimOpacity, pop) {
|
|
10
|
+
if (focus <= 0)
|
|
11
|
+
return 1;
|
|
12
|
+
return 1 - (1 - clamp(dimOpacity, 0, 1)) * focus * (1 - pop);
|
|
13
|
+
}
|
|
14
|
+
/** 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. */
|
|
15
|
+
export function ringPoint(r, a) {
|
|
16
|
+
return { x: r * Math.sin(a), y: r * Math.cos(a) };
|
|
17
|
+
}
|
|
18
|
+
/** How far everything outside the selection fades while any slice is selected; fainter than a gapless chart's, as a ring's slices touch. */
|
|
19
|
+
export const PIE_SPOTLIGHT_DIM = 0.15;
|
|
20
|
+
const resolvedFills = new WeakMap();
|
|
21
|
+
export function resolvedFill(fill) {
|
|
22
|
+
if (typeof fill !== "object" || fill === null)
|
|
23
|
+
return fillOps.resolve(fill);
|
|
24
|
+
let resolved = resolvedFills.get(fill);
|
|
25
|
+
if (resolved === undefined)
|
|
26
|
+
resolvedFills.set(fill, resolved = fillOps.resolve(fill));
|
|
27
|
+
return resolved;
|
|
28
|
+
}
|
|
29
|
+
/** Each slice's paint, resolved once per fill object. */
|
|
30
|
+
export function ringFills(slices) {
|
|
31
|
+
return slices.map((slice) => resolvedFill(slice.fill));
|
|
32
|
+
}
|
|
33
|
+
//# sourceMappingURL=polar.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"polar.js","sourceRoot":"","sources":["../../src/kit/polar.ts"],"names":[],"mappings":"AAAA,mHAAmH;AAEnH,OAAO,EAAE,KAAK,EAAE,OAAO,EAA8D,MAAM,mBAAmB,CAAA;AAY9G,MAAM,CAAC,MAAM,GAAG,GAAG,IAAI,CAAC,EAAE,GAAG,GAAG,CAAA;AAEhC;;;;GAIG;AACH,MAAM,UAAU,aAAa,CAAC,KAAa,EAAE,UAAkB,EAAE,GAAW;IAC1E,IAAI,KAAK,IAAI,CAAC;QAAE,OAAO,CAAC,CAAA;IACxB,OAAO,CAAC,GAAG,CAAC,CAAC,GAAG,KAAK,CAAC,UAAU,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC,GAAG,KAAK,GAAG,CAAC,CAAC,GAAG,GAAG,CAAC,CAAA;AAC9D,CAAC;AAED,iIAAiI;AACjI,MAAM,UAAU,SAAS,CAAC,CAAS,EAAE,CAAS;IAC5C,OAAO,EAAE,CAAC,EAAE,CAAC,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAA;AACnD,CAAC;AAQD,4IAA4I;AAC5I,MAAM,CAAC,MAAM,iBAAiB,GAAG,IAAI,CAAA;AAErC,MAAM,aAAa,GAAG,IAAI,OAAO,EAA0B,CAAA;AAE3D,MAAM,UAAU,YAAY,CAAC,IAAU;IACrC,IAAI,OAAO,IAAI,KAAK,QAAQ,IAAI,IAAI,KAAK,IAAI;QAAE,OAAO,OAAO,CAAC,OAAO,CAAC,IAAI,CAAC,CAAA;IAC3E,IAAI,QAAQ,GAAG,aAAa,CAAC,GAAG,CAAC,IAAI,CAAC,CAAA;IACtC,IAAI,QAAQ,KAAK,SAAS;QAAE,aAAa,CAAC,GAAG,CAAC,IAAI,EAAE,QAAQ,GAAG,OAAO,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAA;IACrF,OAAO,QAAQ,CAAA;AACjB,CAAC;AAED,yDAAyD;AACzD,MAAM,UAAU,SAAS,CAAC,MAA2B;IACnD,OAAO,MAAM,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,YAAY,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,CAAA;AACxD,CAAC","sourcesContent":["/** 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"]}
|
package/dist/kit/shared.d.ts
CHANGED
|
@@ -14,7 +14,8 @@ import { type DataRecord, type Fill, type Insets, type Shadow, type Stroke, type
|
|
|
14
14
|
export interface ChartSeries {
|
|
15
15
|
/** Key into each data row for this series' value. */
|
|
16
16
|
field: string;
|
|
17
|
-
|
|
17
|
+
/** The legend caption; empty or absent shows `field`. */
|
|
18
|
+
label?: string;
|
|
18
19
|
/** Overrides the theme palette's entry for this series' index, for its mark and legend swatch. */
|
|
19
20
|
fill?: Fill;
|
|
20
21
|
/** Defaults to `true`. */
|
|
@@ -78,18 +79,6 @@ export interface AxisDomainBlend extends AxisDomainConfig {
|
|
|
78
79
|
export declare function lerpAxisEntry(from: AxisDomainConfig, to: AxisDomainConfig, t: number): AxisDomainConfig;
|
|
79
80
|
/** `domain` as drawn: `drawn` resolves a plain domain's auto `range` and `ticks`; a blend is the lerp of what its ends draw. */
|
|
80
81
|
export declare function settleAxisDomain(domain: AxisDomainConfig, drawn: (domain: AxisDomainConfig) => AxisDomainConfig): AxisDomainConfig;
|
|
81
|
-
/** The colour tokens the default themes are built from: a dark plot panel with warm-grey axis furniture. */
|
|
82
|
-
export declare const CHART_PALETTE: {
|
|
83
|
-
readonly plotFill: "#15130e";
|
|
84
|
-
readonly borderColor: "#4a4036";
|
|
85
|
-
readonly gridColor: "#2c2820";
|
|
86
|
-
/** Axis markers, axis captions and legend labels. */
|
|
87
|
-
readonly markerColor: "#8a7f70";
|
|
88
|
-
/** A spotlit region's dashed rules and wash. */
|
|
89
|
-
readonly regionColor: "#d99a3a";
|
|
90
|
-
};
|
|
91
|
-
/** The out-of-the-box series palette, cycled by series index. */
|
|
92
|
-
export declare const DEFAULT_SERIES_COLORS: readonly ["#d9603b", "#8194ad", "#e0a93b", "#5e9d6b", "#9ec85a"];
|
|
93
82
|
/** Opacity an un-spotlighted series fades to, mark and legend entry alike. */
|
|
94
83
|
export declare const SPOTLIGHT_DIM = 0.2;
|
|
95
84
|
/**
|
|
@@ -132,46 +121,9 @@ export interface LegendConfig {
|
|
|
132
121
|
itemGap: number;
|
|
133
122
|
markerStyle: LegendMarkerConfig;
|
|
134
123
|
}
|
|
135
|
-
/** The plot panel a cartesian chart draws its marks over. */
|
|
136
|
-
export interface PlotAreaConfig {
|
|
137
|
-
stroke: Stroke;
|
|
138
|
-
fill: Fill;
|
|
139
|
-
shadow: Shadow;
|
|
140
|
-
}
|
|
141
124
|
export declare const DEFAULT_X_AXIS: AxisConfig;
|
|
142
125
|
export declare const DEFAULT_Y_AXIS: AxisConfig;
|
|
143
|
-
/** Unpainted but framed: a chart reads against the stage rather than punching a panel into it. */
|
|
144
|
-
export declare const DEFAULT_PLOT_AREA: PlotAreaConfig;
|
|
145
126
|
export declare const DEFAULT_LEGEND: LegendConfig;
|
|
146
|
-
/** {@link DEFAULT_SERIES_COLORS} as 4px strokes. */
|
|
147
|
-
export declare const DEFAULT_SERIES_STROKES: Stroke[];
|
|
148
|
-
/** {@link DEFAULT_SERIES_COLORS} as solid fills. */
|
|
149
|
-
export declare const DEFAULT_SERIES_FILLS: Fill[];
|
|
150
|
-
export declare function resolveAxisConfig(axis: Partial<AxisConfig> | undefined, previous: AxisConfig): AxisConfig;
|
|
151
|
-
export declare function lerpAxisConfig(from: AxisConfig, to: AxisConfig, t: number): AxisConfig;
|
|
152
|
-
export declare function resolvePlotArea(plotArea: Partial<PlotAreaConfig> | undefined, previous: PlotAreaConfig): PlotAreaConfig;
|
|
153
|
-
export declare function lerpPlotArea(from: PlotAreaConfig, to: PlotAreaConfig, t: number): PlotAreaConfig;
|
|
154
|
-
/** A legend theme as the author may state it: every branch optional. */
|
|
155
|
-
export type LegendTheme = Partial<Omit<LegendConfig, "markerStyle">> & {
|
|
156
|
-
markerStyle?: Partial<LegendMarkerConfig>;
|
|
157
|
-
};
|
|
158
|
-
export declare function resolveLegendConfig(legend: LegendTheme | undefined, previous: LegendConfig): LegendConfig;
|
|
159
|
-
export declare function lerpLegendConfig(from: LegendConfig, to: LegendConfig, t: number): LegendConfig;
|
|
160
|
-
/** A palette override replaces the previous palette outright. */
|
|
161
|
-
export declare function resolveSeriesStrokes(styles: Stroke[] | undefined, previous: Stroke[]): Stroke[];
|
|
162
|
-
/** Pairwise by index; a palette that grows/shrinks holds the longer side's tail. */
|
|
163
|
-
export declare function lerpSeriesStrokes(from: Stroke[], to: Stroke[], t: number): Stroke[];
|
|
164
|
-
/** The fill-palette twin of {@link resolveSeriesStrokes}, for filled marks. */
|
|
165
|
-
export declare function resolveSeriesFills(fills: Fill[] | undefined, previous: Fill[]): Fill[];
|
|
166
|
-
/** The fill-palette twin of {@link lerpSeriesStrokes}. */
|
|
167
|
-
export declare function lerpSeriesFills(from: Fill[], to: Fill[], t: number): Fill[];
|
|
168
|
-
/**
|
|
169
|
-
* The stroke for series `index`: the palette's entry at `index % palette.length`,
|
|
170
|
-
* with the series' own `fill`, if set, replacing just the topmost layer's colour.
|
|
171
|
-
*/
|
|
172
|
-
export declare function resolveSeriesStroke(palette: Stroke[], series: ChartSeries, index: number): Stroke;
|
|
173
|
-
/** The colour {@link resolveSeriesStroke} draws series `index` in, for a legend swatch. */
|
|
174
|
-
export declare function resolveSeriesFill(palette: Stroke[], series: ChartSeries, index: number): Fill;
|
|
175
127
|
/**
|
|
176
128
|
* Format a marker value: integers plain, otherwise one decimal, or as many as
|
|
177
129
|
* the tick `step` needs to tell neighbours apart (a unit axis ticked every 0.05
|
|
@@ -184,4 +136,13 @@ export declare function markerStep(markers: readonly number[]): number | undefin
|
|
|
184
136
|
export declare function formatPercent(fraction: number): string;
|
|
185
137
|
/** `markerCount` evenly-spaced tick values across `[min, max]`, ends inclusive. */
|
|
186
138
|
export declare function markerValues([min, max]: Range, markerCount: number): number[];
|
|
139
|
+
/** `[lo, hi]` nudged out to bounds a whole number of tidy steps apart, about `divisions` of them. */
|
|
140
|
+
export declare function niceRange([lo, hi]: Range, divisions: number): Range;
|
|
141
|
+
/**
|
|
142
|
+
* Ticks for a range worked out from the data: every multiple of the tidiest
|
|
143
|
+
* step (1, 2 or 5 times a power of ten) that divides it into about `divisions`
|
|
144
|
+
* parts, so zero is a tick whenever the range spans it. A range no such step
|
|
145
|
+
* divides (an author's) is split evenly instead.
|
|
146
|
+
*/
|
|
147
|
+
export declare function niceTicks([lo, hi]: Range, divisions: number): number[];
|
|
187
148
|
//# sourceMappingURL=shared.d.ts.map
|
package/dist/kit/shared.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"shared.d.ts","sourceRoot":"","sources":["../../src/kit/shared.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH,OAAO,
|
|
1
|
+
{"version":3,"file":"shared.d.ts","sourceRoot":"","sources":["../../src/kit/shared.ts"],"names":[],"mappings":"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"}
|
package/dist/kit/shared.js
CHANGED
|
@@ -9,7 +9,8 @@
|
|
|
9
9
|
* the midpoint: defaulting the missing side to 0 would animate a font weight
|
|
10
10
|
* down to nothing on the way to "unset".
|
|
11
11
|
*/
|
|
12
|
-
import {
|
|
12
|
+
import { lerpNumber, } from "@motionscript/sdk";
|
|
13
|
+
import { niceStep } from "@motionscript/sdk/component";
|
|
13
14
|
/**
|
|
14
15
|
* Merges partial input onto `previous`, so a later `.set({ yAxis: {...} })`
|
|
15
16
|
* patches `label`/`range`/`ticks` independently. An unset `range`/`ticks` is the
|
|
@@ -87,7 +88,7 @@ export function settleAxisDomain(domain, drawn) {
|
|
|
87
88
|
return lerpAxisDomain(settleAxisDomain(blend.from, drawn), settleAxisDomain(blend.to, drawn), blend.t);
|
|
88
89
|
}
|
|
89
90
|
/** The colour tokens the default themes are built from: a dark plot panel with warm-grey axis furniture. */
|
|
90
|
-
|
|
91
|
+
const CHART_PALETTE = {
|
|
91
92
|
plotFill: "#15130e",
|
|
92
93
|
borderColor: "#4a4036",
|
|
93
94
|
gridColor: "#2c2820",
|
|
@@ -96,14 +97,6 @@ export const CHART_PALETTE = {
|
|
|
96
97
|
/** A spotlit region's dashed rules and wash. */
|
|
97
98
|
regionColor: "#d99a3a",
|
|
98
99
|
};
|
|
99
|
-
/** The out-of-the-box series palette, cycled by series index. */
|
|
100
|
-
export const DEFAULT_SERIES_COLORS = [
|
|
101
|
-
"#d9603b",
|
|
102
|
-
"#8194ad",
|
|
103
|
-
"#e0a93b",
|
|
104
|
-
"#5e9d6b",
|
|
105
|
-
"#9ec85a",
|
|
106
|
-
];
|
|
107
100
|
/** Opacity an un-spotlighted series fades to, mark and legend entry alike. */
|
|
108
101
|
export const SPOTLIGHT_DIM = 0.2;
|
|
109
102
|
/**
|
|
@@ -182,12 +175,6 @@ export const DEFAULT_Y_AXIS = {
|
|
|
182
175
|
tickPadding: 40,
|
|
183
176
|
titlePadding: 24,
|
|
184
177
|
};
|
|
185
|
-
/** Unpainted but framed: a chart reads against the stage rather than punching a panel into it. */
|
|
186
|
-
export const DEFAULT_PLOT_AREA = {
|
|
187
|
-
fill: [],
|
|
188
|
-
stroke: { weight: 6, fill: CHART_PALETTE.borderColor },
|
|
189
|
-
shadow: [],
|
|
190
|
-
};
|
|
191
178
|
export const DEFAULT_LEGEND = {
|
|
192
179
|
padding: 0,
|
|
193
180
|
textStyle: {
|
|
@@ -205,131 +192,6 @@ export const DEFAULT_LEGEND = {
|
|
|
205
192
|
shadow: [],
|
|
206
193
|
},
|
|
207
194
|
};
|
|
208
|
-
/** {@link DEFAULT_SERIES_COLORS} as 4px strokes. */
|
|
209
|
-
export const DEFAULT_SERIES_STROKES = DEFAULT_SERIES_COLORS.map((fill) => ({ weight: 4, fill }));
|
|
210
|
-
/** {@link DEFAULT_SERIES_COLORS} as solid fills. */
|
|
211
|
-
export const DEFAULT_SERIES_FILLS = DEFAULT_SERIES_COLORS.map((fill) => fill);
|
|
212
|
-
export function resolveAxisConfig(axis, previous) {
|
|
213
|
-
return {
|
|
214
|
-
labelStyle: textOps.resolveStyle(axis?.labelStyle, previous.labelStyle),
|
|
215
|
-
titleStyle: textOps.resolveStyle(axis?.titleStyle, previous.titleStyle),
|
|
216
|
-
lineStyle: strokeOps.resolve(axis?.lineStyle ?? previous.lineStyle),
|
|
217
|
-
tickPadding: insetsOps.resolve(axis?.tickPadding ?? previous.tickPadding, previous.tickPadding),
|
|
218
|
-
titlePadding: insetsOps.resolve(axis?.titlePadding ?? previous.titlePadding, previous.titlePadding),
|
|
219
|
-
};
|
|
220
|
-
}
|
|
221
|
-
export function lerpAxisConfig(from, to, t) {
|
|
222
|
-
return {
|
|
223
|
-
labelStyle: textOps.lerpStyle(from.labelStyle, to.labelStyle, t),
|
|
224
|
-
titleStyle: textOps.lerpStyle(from.titleStyle, to.titleStyle, t),
|
|
225
|
-
lineStyle: strokeOps.lerp(from.lineStyle, to.lineStyle, t),
|
|
226
|
-
tickPadding: insetsOps.lerp(from.tickPadding, to.tickPadding, t),
|
|
227
|
-
titlePadding: insetsOps.lerp(from.titlePadding, to.titlePadding, t),
|
|
228
|
-
};
|
|
229
|
-
}
|
|
230
|
-
export function resolvePlotArea(plotArea, previous) {
|
|
231
|
-
return {
|
|
232
|
-
fill: fillOps.resolve(plotArea?.fill ?? previous.fill),
|
|
233
|
-
stroke: strokeOps.resolve(plotArea?.stroke ?? previous.stroke),
|
|
234
|
-
shadow: shadowOps.resolve(plotArea?.shadow ?? previous.shadow),
|
|
235
|
-
};
|
|
236
|
-
}
|
|
237
|
-
export function lerpPlotArea(from, to, t) {
|
|
238
|
-
return {
|
|
239
|
-
fill: fillOps.lerp(from.fill, to.fill, t),
|
|
240
|
-
stroke: strokeOps.lerp(from.stroke, to.stroke, t),
|
|
241
|
-
shadow: shadowOps.lerp(from.shadow, to.shadow, t),
|
|
242
|
-
};
|
|
243
|
-
}
|
|
244
|
-
function resolveLegendMarkerConfig(marker, previous) {
|
|
245
|
-
return {
|
|
246
|
-
width: marker?.width ?? previous.width,
|
|
247
|
-
height: marker?.height ?? previous.height,
|
|
248
|
-
borderRadius: marker?.borderRadius ?? previous.borderRadius,
|
|
249
|
-
stroke: strokeOps.resolve(marker?.stroke ?? previous.stroke),
|
|
250
|
-
shadow: shadowOps.resolve(marker?.shadow ?? previous.shadow),
|
|
251
|
-
};
|
|
252
|
-
}
|
|
253
|
-
function lerpLegendMarkerConfig(from, to, t) {
|
|
254
|
-
return {
|
|
255
|
-
width: lerpNumber(from.width, to.width, t),
|
|
256
|
-
height: lerpNumber(from.height, to.height, t),
|
|
257
|
-
borderRadius: lerpNumber(from.borderRadius, to.borderRadius, t),
|
|
258
|
-
stroke: strokeOps.lerp(from.stroke, to.stroke, t),
|
|
259
|
-
shadow: shadowOps.lerp(from.shadow, to.shadow, t),
|
|
260
|
-
};
|
|
261
|
-
}
|
|
262
|
-
export function resolveLegendConfig(legend, previous) {
|
|
263
|
-
return {
|
|
264
|
-
padding: insetsOps.resolve(legend?.padding ?? previous.padding, previous.padding),
|
|
265
|
-
textStyle: textOps.resolveStyle(legend?.textStyle, previous.textStyle),
|
|
266
|
-
itemGap: legend?.itemGap ?? previous.itemGap,
|
|
267
|
-
markerStyle: resolveLegendMarkerConfig(legend?.markerStyle, previous.markerStyle),
|
|
268
|
-
};
|
|
269
|
-
}
|
|
270
|
-
export function lerpLegendConfig(from, to, t) {
|
|
271
|
-
return {
|
|
272
|
-
padding: insetsOps.lerp(from.padding, to.padding, t),
|
|
273
|
-
textStyle: textOps.lerpStyle(from.textStyle, to.textStyle, t),
|
|
274
|
-
itemGap: lerpNumber(from.itemGap, to.itemGap, t),
|
|
275
|
-
markerStyle: lerpLegendMarkerConfig(from.markerStyle, to.markerStyle, t),
|
|
276
|
-
};
|
|
277
|
-
}
|
|
278
|
-
/** A palette override replaces the previous palette outright. */
|
|
279
|
-
export function resolveSeriesStrokes(styles, previous) {
|
|
280
|
-
return (styles ?? previous).map((s) => strokeOps.resolve(s));
|
|
281
|
-
}
|
|
282
|
-
/** Pairwise by index; a palette that grows/shrinks holds the longer side's tail. */
|
|
283
|
-
export function lerpSeriesStrokes(from, to, t) {
|
|
284
|
-
const n = Math.max(from.length, to.length);
|
|
285
|
-
const out = [];
|
|
286
|
-
for (let i = 0; i < n; i++) {
|
|
287
|
-
const a = (from[i] ?? to[i]);
|
|
288
|
-
const b = (to[i] ?? from[i]);
|
|
289
|
-
out.push(strokeOps.lerp(a, b, t));
|
|
290
|
-
}
|
|
291
|
-
return out;
|
|
292
|
-
}
|
|
293
|
-
/** The fill-palette twin of {@link resolveSeriesStrokes}, for filled marks. */
|
|
294
|
-
export function resolveSeriesFills(fills, previous) {
|
|
295
|
-
return (fills ?? previous).map((f) => fillOps.resolve(f));
|
|
296
|
-
}
|
|
297
|
-
/** The fill-palette twin of {@link lerpSeriesStrokes}. */
|
|
298
|
-
export function lerpSeriesFills(from, to, t) {
|
|
299
|
-
const n = Math.max(from.length, to.length);
|
|
300
|
-
const out = [];
|
|
301
|
-
for (let i = 0; i < n; i++) {
|
|
302
|
-
const a = (from[i] ?? to[i]);
|
|
303
|
-
const b = (to[i] ?? from[i]);
|
|
304
|
-
out.push(fillOps.lerp(a, b, t));
|
|
305
|
-
}
|
|
306
|
-
return out;
|
|
307
|
-
}
|
|
308
|
-
/**
|
|
309
|
-
* The stroke for series `index`: the palette's entry at `index % palette.length`,
|
|
310
|
-
* with the series' own `fill`, if set, replacing just the topmost layer's colour.
|
|
311
|
-
*/
|
|
312
|
-
export function resolveSeriesStroke(palette, series, index) {
|
|
313
|
-
const entry = palette.length > 0
|
|
314
|
-
? palette[index % palette.length]
|
|
315
|
-
: { weight: 4, fill: "white" };
|
|
316
|
-
if (series.fill == null)
|
|
317
|
-
return entry;
|
|
318
|
-
const layers = strokeOps.resolve(entry);
|
|
319
|
-
if (layers.length === 0)
|
|
320
|
-
return { weight: 4, fill: series.fill };
|
|
321
|
-
const next = [...layers];
|
|
322
|
-
next[next.length - 1] = {
|
|
323
|
-
...next[next.length - 1],
|
|
324
|
-
fill: fillOps.resolve(series.fill),
|
|
325
|
-
};
|
|
326
|
-
return next;
|
|
327
|
-
}
|
|
328
|
-
/** The colour {@link resolveSeriesStroke} draws series `index` in, for a legend swatch. */
|
|
329
|
-
export function resolveSeriesFill(palette, series, index) {
|
|
330
|
-
const layers = strokeOps.resolve(resolveSeriesStroke(palette, series, index));
|
|
331
|
-
return layers[layers.length - 1]?.fill ?? "white";
|
|
332
|
-
}
|
|
333
195
|
/**
|
|
334
196
|
* Format a marker value: integers plain, otherwise one decimal, or as many as
|
|
335
197
|
* the tick `step` needs to tell neighbours apart (a unit axis ticked every 0.05
|
|
@@ -376,4 +238,59 @@ export function markerValues([min, max], markerCount) {
|
|
|
376
238
|
const n = Math.max(2, Math.round(markerCount));
|
|
377
239
|
return Array.from({ length: n + 1 }, (_, i) => min + ((max - min) / n) * i);
|
|
378
240
|
}
|
|
241
|
+
/** `[lo, hi]` nudged out to bounds a whole number of tidy steps apart, about `divisions` of them. */
|
|
242
|
+
export function niceRange([lo, hi], divisions) {
|
|
243
|
+
const segments = Math.max(1, Math.round(divisions));
|
|
244
|
+
if (hi === lo)
|
|
245
|
+
return constantScale(lo, segments);
|
|
246
|
+
const step = niceStep((hi - lo) / segments);
|
|
247
|
+
return [Math.floor(lo / step) * step, Math.ceil(hi / step) * step];
|
|
248
|
+
}
|
|
249
|
+
/**
|
|
250
|
+
* The scale for constant data. A zero-width scale would put every tick on one
|
|
251
|
+
* value and the line on the floor, so it widens by a step sized to the
|
|
252
|
+
* magnitude (`5` gets `[3, 7]`), or `[0, 1]` for zero.
|
|
253
|
+
*/
|
|
254
|
+
function constantScale(value, segments) {
|
|
255
|
+
if (value === 0)
|
|
256
|
+
return [0, 1];
|
|
257
|
+
const step = niceStep(Math.abs(value) / segments);
|
|
258
|
+
return [value - step, value + step];
|
|
259
|
+
}
|
|
260
|
+
/**
|
|
261
|
+
* Ticks for a range worked out from the data: every multiple of the tidiest
|
|
262
|
+
* step (1, 2 or 5 times a power of ten) that divides it into about `divisions`
|
|
263
|
+
* parts, so zero is a tick whenever the range spans it. A range no such step
|
|
264
|
+
* divides (an author's) is split evenly instead.
|
|
265
|
+
*/
|
|
266
|
+
export function niceTicks([lo, hi], divisions) {
|
|
267
|
+
const span = hi - lo;
|
|
268
|
+
const target = Math.max(1, Math.round(divisions));
|
|
269
|
+
if (!(span > 0))
|
|
270
|
+
return markerValues([lo, hi], target);
|
|
271
|
+
const whole = (v) => Math.abs(v - Math.round(v)) < 1e-6;
|
|
272
|
+
const base = niceStep(span / target);
|
|
273
|
+
let best;
|
|
274
|
+
for (const step of ladder(base)) {
|
|
275
|
+
const parts = span / step;
|
|
276
|
+
if (!whole(parts) || !whole(lo / step) || parts < 2 || parts > 8)
|
|
277
|
+
continue;
|
|
278
|
+
if (best === undefined || Math.abs(parts - target) < Math.abs(span / best - target))
|
|
279
|
+
best = step;
|
|
280
|
+
}
|
|
281
|
+
if (best === undefined)
|
|
282
|
+
return markerValues([lo, hi], target);
|
|
283
|
+
const first = Math.round(lo / best);
|
|
284
|
+
return Array.from({ length: Math.round(span / best) + 1 }, (_, k) => Number(((first + k) * best).toPrecision(12)));
|
|
285
|
+
}
|
|
286
|
+
/** `step` and its neighbours on the 1-2-5 ladder, two either side. */
|
|
287
|
+
function ladder(step) {
|
|
288
|
+
const mag = 10 ** Math.floor(Math.log10(step));
|
|
289
|
+
const rungs = [];
|
|
290
|
+
for (const m of [mag / 10, mag, mag * 10])
|
|
291
|
+
for (const k of [1, 2, 5])
|
|
292
|
+
rungs.push(k * m);
|
|
293
|
+
const at = rungs.findIndex((r) => Math.abs(r - step) < step * 1e-9);
|
|
294
|
+
return rungs.slice(Math.max(0, at - 2), at + 3);
|
|
295
|
+
}
|
|
379
296
|
//# sourceMappingURL=shared.js.map
|
package/dist/kit/shared.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"shared.js","sourceRoot":"","sources":["../../src/kit/shared.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH,OAAO,EACL,OAAO,EACP,UAAU,EACV,SAAS,EACT,SAAS,EACT,SAAS,EACT,OAAO,GAWR,MAAM,mBAAmB,CAAA;AAmC1B;;;;GAIG;AACH,MAAM,UAAU,iBAAiB,CAC/B,MAAoC,EACpC,QAA2B;IAE3B,OAAO;QACL,KAAK,EAAE,MAAM,EAAE,KAAK,IAAI,QAAQ,EAAE,KAAK,IAAI,EAAE;QAC7C,KAAK,EAAE,MAAM,EAAE,KAAK,IAAI,QAAQ,EAAE,KAAK;QACvC,KAAK,EAAE,MAAM,EAAE,KAAK,IAAI,QAAQ,EAAE,KAAK;QACvC,MAAM,EAAE,MAAM,EAAE,MAAM,IAAI,QAAQ,EAAE,MAAM;KAC3C,CAAA;AACH,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,cAAc,CAC5B,IAAsB,EACtB,EAAoB,EACpB,CAAS;IAET,OAAO;QACL,KAAK,EAAE,CAAC,GAAG,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,CAAC,KAAK;QACtC,KAAK,EAAE,iBAAiB,CAAC,IAAI,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,EAAE,CAAC,CAAC;QACjD,KAAK,EAAE,iBAAiB,CAAC,IAAI,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,EAAE,CAAC,CAAC;QACjD,MAAM,EAAE,CAAC,GAAG,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,MAAM;KAC1C,CAAA;AACH,CAAC;AAED,SAAS,iBAAiB,CACxB,IAAuB,EACvB,EAAqB,EACrB,CAAS;IAET,IAAI,CAAC,IAAI,IAAI,CAAC,EAAE;QAAE,OAAO,CAAC,GAAG,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAA;IAC5C,OAAO,CAAC,UAAU,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,UAAU,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAA;AACvE,CAAC;AAED,SAAS,iBAAiB,CACxB,IAA0B,EAC1B,EAAwB,EACxB,CAAS;IAET,IAAI,CAAC,IAAI,IAAI,CAAC,EAAE;QAAE,OAAO,CAAC,GAAG,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAA;IAC5C,MAAM,CAAC,GAAG,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,MAAM,EAAE,EAAE,CAAC,MAAM,CAAC,CAAA;IAC1C,MAAM,GAAG,GAAa,EAAE,CAAA;IACxB,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC;QAC3B,GAAG,CAAC,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAA;IAC7D,CAAC;IACD,OAAO,GAAG,CAAA;AACZ,CAAC;AAaD,SAAS,OAAO,CAAC,MAAwB;IACvC,OAAQ,MAAmC,CAAC,KAAK,CAAA;AACnD,CAAC;AAED;;;;;;GAMG;AACH,MAAM,UAAU,aAAa,CAAC,IAAsB,EAAE,EAAoB,EAAE,CAAS;IACnF,uGAAuG;IACvG,MAAM,UAAU,GAAG,EAAE,CAAC,KAAK,KAAK,IAAI,CAAC,KAAK,CAAA;IAC1C,MAAM,MAAM,GAAG,UAAU,IAAI,EAAE,CAAC,KAAK,IAAI,EAAE,CAAC,KAAK,IAAI,EAAE,CAAC,KAAK,KAAK,IAAI,CAAC,KAAK;QAC1E,CAAC,CAAC,EAAE,GAAG,EAAE,EAAE,KAAK,EAAE,YAAY,CAAC,EAAE,CAAC,KAAK,EAAE,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,EAAE,CAAC,KAAK,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,EAAE;QAC5E,CAAC,CAAC,EAAE,CAAA;IACN,MAAM,OAAO,GAAG,OAAO,CAAC,IAAI,CAAC,KAAK,SAAS,CAAA;IAC3C,MAAM,KAAK,GAAG,OAAO,IAAI,UAAU,IAAI,MAAM,CAAC,KAAK,KAAK,IAAI,CAAC,KAAK,CAAA;IAClE,MAAM,IAAI,GAAG,OAAO,IAAI,IAAI,CAAC,KAAK,KAAK,SAAS,IAAI,IAAI,CAAC,KAAK,KAAK,SAAS,IAAI,MAAM,CAAC,KAAK,KAAK,SAAS,IAAI,MAAM,CAAC,KAAK,KAAK,SAAS,CAAA;IACxI,IAAI,CAAC,KAAK,IAAI,CAAC,IAAI;QAAE,OAAO,cAAc,CAAC,IAAI,EAAE,MAAM,EAAE,CAAC,CAAC,CAAA;IAC3D,IAAI,CAAC,KAAK,CAAC;QAAE,OAAO,IAAI,CAAA;IACxB,IAAI,CAAC,KAAK,CAAC;QAAE,OAAO,MAAM,CAAA;IAC1B,MAAM,KAAK,GAAoB,EAAE,GAAG,cAAc,CAAC,IAAI,EAAE,MAAM,EAAE,CAAC,CAAC,EAAE,KAAK,EAAE,EAAE,IAAI,EAAE,EAAE,EAAE,MAAM,EAAE,CAAC,EAAE,EAAE,CAAA;IACrG,OAAO,KAAK,CAAA;AACd,CAAC;AAED,gIAAgI;AAChI,MAAM,UAAU,gBAAgB,CAAC,MAAwB,EAAE,KAAqD;IAC9G,MAAM,KAAK,GAAG,OAAO,CAAC,MAAM,CAAC,CAAA;IAC7B,IAAI,CAAC,KAAK;QAAE,OAAO,KAAK,CAAC,MAAM,CAAC,CAAA;IAChC,OAAO,cAAc,CAAC,gBAAgB,CAAC,KAAK,CAAC,IAAI,EAAE,KAAK,CAAC,EAAE,gBAAgB,CAAC,KAAK,CAAC,EAAE,EAAE,KAAK,CAAC,EAAE,KAAK,CAAC,CAAC,CAAC,CAAA;AACxG,CAAC;AAED,4GAA4G;AAC5G,MAAM,CAAC,MAAM,aAAa,GAAG;IAC3B,QAAQ,EAAE,SAAS;IACnB,WAAW,EAAE,SAAS;IACtB,SAAS,EAAE,SAAS;IACpB,qDAAqD;IACrD,WAAW,EAAE,SAAS;IACtB,gDAAgD;IAChD,WAAW,EAAE,SAAS;CACd,CAAA;AAEV,iEAAiE;AACjE,MAAM,CAAC,MAAM,qBAAqB,GAAG;IACnC,SAAS;IACT,SAAS;IACT,SAAS;IACT,SAAS;IACT,SAAS;CACD,CAAA;AAEV,8EAA8E;AAC9E,MAAM,CAAC,MAAM,aAAa,GAAG,GAAG,CAAA;AAEhC;;;GAGG;AACH,MAAM,UAAU,GAAG,CAAC,GAAe,EAAE,KAAyB;IAC5D,IAAI,KAAK,KAAK,SAAS;QAAE,OAAO,CAAC,CAAA;IACjC,MAAM,CAAC,GAAG,GAAG,CAAC,KAAK,CAAC,CAAA;IACpB,6EAA6E;IAC7E,oEAAoE;IACpE,OAAO,OAAO,CAAC,KAAK,QAAQ,IAAI,MAAM,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAA;AAC5D,CAAC;AAED,gIAAgI;AAChI,MAAM,UAAU,IAAI,CAAC,GAAe,EAAE,KAAyB;IAC7D,IAAI,KAAK,KAAK,SAAS,IAAI,KAAK,KAAK,EAAE;QAAE,OAAO,EAAE,CAAA;IAClD,MAAM,CAAC,GAAG,GAAG,CAAC,KAAK,CAAC,CAAA;IACpB,OAAO,CAAC,KAAK,SAAS,IAAI,CAAC,KAAK,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,CAAA;AACvD,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,aAAa,CAC3B,IAAkB,EAClB,UAAoB,EAAE;IAEtB,IAAI,IAAI,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,EAAE,CAAA;IAChC,MAAM,IAAI,GAAG,IAAI,GAAG,CAAC,OAAO,CAAC,CAAA;IAC7B,MAAM,IAAI,GAAG,IAAI,GAAG,EAAU,CAAA;IAC9B,MAAM,KAAK,GAAa,EAAE,CAAA;IAC1B,KAAK,MAAM,GAAG,IAAI,IAAI;QACpB,KAAK,MAAM,GAAG,IAAI,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC;YAChC,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,EAAE,CAAC;gBACrC,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,CAAA;gBACb,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,CAAA;YACjB,CAAC;IAEL,OAAO,KAAK,CAAC,MAAM,CAAC,CAAC,GAAG,EAAE,EAAE;QAC1B,IAAI,QAAQ,GAAG,KAAK,CAAA;QACpB,KAAK,MAAM,GAAG,IAAI,IAAI,EAAE,CAAC;YACvB,MAAM,CAAC,GAAG,GAAG,CAAC,GAAG,CAAC,CAAA;YAClB,IAAI,CAAC,KAAK,SAAS,IAAI,CAAC,KAAK,EAAE;gBAAE,SAAQ;YACzC,IAAI,OAAO,CAAC,KAAK,QAAQ;gBAAE,OAAO,KAAK,CAAA;YACvC,QAAQ,GAAG,IAAI,CAAA;QACjB,CAAC;QACD,OAAO,QAAQ,CAAA;IACjB,CAAC,CAAC,CAAA;AACJ,CAAC;AAuCD,MAAM,gBAAgB,GAAc;IAClC,QAAQ,EAAE,EAAE;IACZ,UAAU,EAAE,GAAG;IACf,SAAS,EAAE,QAAQ;IACnB,IAAI,EAAE,aAAa,CAAC,WAAW;CAChC,CAAA;AACD,MAAM,gBAAgB,GAAc;IAClC,QAAQ,EAAE,EAAE;IACZ,UAAU,EAAE,GAAG;IACf,SAAS,EAAE,QAAQ;IACnB,IAAI,EAAE,aAAa,CAAC,WAAW;CAChC,CAAA;AACD,MAAM,eAAe,GAAW,EAAE,MAAM,EAAE,CAAC,EAAE,IAAI,EAAE,aAAa,CAAC,SAAS,EAAE,CAAA;AAE5E,MAAM,CAAC,MAAM,cAAc,GAAe;IACxC,UAAU,EAAE,gBAAgB;IAC5B,UAAU,EAAE,gBAAgB;IAC5B,SAAS,EAAE,eAAe;IAC1B,WAAW,EAAE,EAAE;IACf,YAAY,EAAE,CAAC;CAChB,CAAA;AAED,MAAM,CAAC,MAAM,cAAc,GAAe;IACxC,UAAU,EAAE,EAAE,GAAG,gBAAgB,EAAE,UAAU,EAAE,GAAG,EAAE,SAAS,EAAE,OAAO,EAAE;IACxE,UAAU,EAAE,gBAAgB;IAC5B,SAAS,EAAE,eAAe;IAC1B,WAAW,EAAE,EAAE;IACf,YAAY,EAAE,EAAE;CACjB,CAAA;AAED,kGAAkG;AAClG,MAAM,CAAC,MAAM,iBAAiB,GAAmB;IAC/C,IAAI,EAAE,EAAE;IACR,MAAM,EAAE,EAAE,MAAM,EAAE,CAAC,EAAE,IAAI,EAAE,aAAa,CAAC,WAAW,EAAE;IACtD,MAAM,EAAE,EAAE;CACX,CAAA;AAED,MAAM,CAAC,MAAM,cAAc,GAAiB;IAC1C,OAAO,EAAE,CAAC;IACV,SAAS,EAAE;QACT,QAAQ,EAAE,EAAE;QACZ,UAAU,EAAE,GAAG;QACf,SAAS,EAAE,MAAM;QACjB,IAAI,EAAE,aAAa,CAAC,WAAW;KAChC;IACD,OAAO,EAAE,EAAE;IACX,WAAW,EAAE;QACX,KAAK,EAAE,EAAE;QACT,MAAM,EAAE,EAAE;QACV,YAAY,EAAE,CAAC;QACf,MAAM,EAAE,EAAE;QACV,MAAM,EAAE,EAAE;KACX;CACF,CAAA;AAED,oDAAoD;AACpD,MAAM,CAAC,MAAM,sBAAsB,GAAa,qBAAqB,CAAC,GAAG,CACvE,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,IAAI,EAAE,CAAC,CAChC,CAAA;AAED,oDAAoD;AACpD,MAAM,CAAC,MAAM,oBAAoB,GAAW,qBAAqB,CAAC,GAAG,CACnE,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CACf,CAAA;AAED,MAAM,UAAU,iBAAiB,CAC/B,IAAqC,EACrC,QAAoB;IAEpB,OAAO;QACL,UAAU,EAAE,OAAO,CAAC,YAAY,CAAC,IAAI,EAAE,UAAU,EAAE,QAAQ,CAAC,UAAU,CAAC;QACvE,UAAU,EAAE,OAAO,CAAC,YAAY,CAAC,IAAI,EAAE,UAAU,EAAE,QAAQ,CAAC,UAAU,CAAC;QACvE,SAAS,EAAE,SAAS,CAAC,OAAO,CAAC,IAAI,EAAE,SAAS,IAAI,QAAQ,CAAC,SAAS,CAAC;QACnE,WAAW,EAAE,SAAS,CAAC,OAAO,CAC5B,IAAI,EAAE,WAAW,IAAI,QAAQ,CAAC,WAAW,EACzC,QAAQ,CAAC,WAA6B,CACvC;QACD,YAAY,EAAE,SAAS,CAAC,OAAO,CAC7B,IAAI,EAAE,YAAY,IAAI,QAAQ,CAAC,YAAY,EAC3C,QAAQ,CAAC,YAA8B,CACxC;KACF,CAAA;AACH,CAAC;AAED,MAAM,UAAU,cAAc,CAC5B,IAAgB,EAChB,EAAc,EACd,CAAS;IAET,OAAO;QACL,UAAU,EAAE,OAAO,CAAC,SAAS,CAAC,IAAI,CAAC,UAAU,EAAE,EAAE,CAAC,UAAU,EAAE,CAAC,CAAC;QAChE,UAAU,EAAE,OAAO,CAAC,SAAS,CAAC,IAAI,CAAC,UAAU,EAAE,EAAE,CAAC,UAAU,EAAE,CAAC,CAAC;QAChE,SAAS,EAAE,SAAS,CAAC,IAAI,CACvB,IAAI,CAAC,SAA6B,EAClC,EAAE,CAAC,SAA6B,EAChC,CAAC,CACF;QACD,WAAW,EAAE,SAAS,CAAC,IAAI,CACzB,IAAI,CAAC,WAA6B,EAClC,EAAE,CAAC,WAA6B,EAChC,CAAC,CACF;QACD,YAAY,EAAE,SAAS,CAAC,IAAI,CAC1B,IAAI,CAAC,YAA8B,EACnC,EAAE,CAAC,YAA8B,EACjC,CAAC,CACF;KACF,CAAA;AACH,CAAC;AAED,MAAM,UAAU,eAAe,CAC7B,QAA6C,EAC7C,QAAwB;IAExB,OAAO;QACL,IAAI,EAAE,OAAO,CAAC,OAAO,CAAC,QAAQ,EAAE,IAAI,IAAI,QAAQ,CAAC,IAAI,CAAC;QACtD,MAAM,EAAE,SAAS,CAAC,OAAO,CAAC,QAAQ,EAAE,MAAM,IAAI,QAAQ,CAAC,MAAM,CAAC;QAC9D,MAAM,EAAE,SAAS,CAAC,OAAO,CAAC,QAAQ,EAAE,MAAM,IAAI,QAAQ,CAAC,MAAM,CAAC;KAC/D,CAAA;AACH,CAAC;AAED,MAAM,UAAU,YAAY,CAC1B,IAAoB,EACpB,EAAkB,EAClB,CAAS;IAET,OAAO;QACL,IAAI,EAAE,OAAO,CAAC,IAAI,CAChB,IAAI,CAAC,IAAsB,EAC3B,EAAE,CAAC,IAAsB,EACzB,CAAC,CACF;QACD,MAAM,EAAE,SAAS,CAAC,IAAI,CACpB,IAAI,CAAC,MAA0B,EAC/B,EAAE,CAAC,MAA0B,EAC7B,CAAC,CACF;QACD,MAAM,EAAE,SAAS,CAAC,IAAI,CACpB,IAAI,CAAC,MAA0B,EAC/B,EAAE,CAAC,MAA0B,EAC7B,CAAC,CACF;KACF,CAAA;AACH,CAAC;AAED,SAAS,yBAAyB,CAChC,MAA+C,EAC/C,QAA4B;IAE5B,OAAO;QACL,KAAK,EAAE,MAAM,EAAE,KAAK,IAAI,QAAQ,CAAC,KAAK;QACtC,MAAM,EAAE,MAAM,EAAE,MAAM,IAAI,QAAQ,CAAC,MAAM;QACzC,YAAY,EAAE,MAAM,EAAE,YAAY,IAAI,QAAQ,CAAC,YAAY;QAC3D,MAAM,EAAE,SAAS,CAAC,OAAO,CAAC,MAAM,EAAE,MAAM,IAAI,QAAQ,CAAC,MAAM,CAAC;QAC5D,MAAM,EAAE,SAAS,CAAC,OAAO,CAAC,MAAM,EAAE,MAAM,IAAI,QAAQ,CAAC,MAAM,CAAC;KAC7D,CAAA;AACH,CAAC;AAED,SAAS,sBAAsB,CAC7B,IAAwB,EACxB,EAAsB,EACtB,CAAS;IAET,OAAO;QACL,KAAK,EAAE,UAAU,CAAC,IAAI,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,EAAE,CAAC,CAAC;QAC1C,MAAM,EAAE,UAAU,CAAC,IAAI,CAAC,MAAM,EAAE,EAAE,CAAC,MAAM,EAAE,CAAC,CAAC;QAC7C,YAAY,EAAE,UAAU,CAAC,IAAI,CAAC,YAAY,EAAE,EAAE,CAAC,YAAY,EAAE,CAAC,CAAC;QAC/D,MAAM,EAAE,SAAS,CAAC,IAAI,CACpB,IAAI,CAAC,MAA0B,EAC/B,EAAE,CAAC,MAA0B,EAC7B,CAAC,CACF;QACD,MAAM,EAAE,SAAS,CAAC,IAAI,CACpB,IAAI,CAAC,MAA0B,EAC/B,EAAE,CAAC,MAA0B,EAC7B,CAAC,CACF;KACF,CAAA;AACH,CAAC;AAOD,MAAM,UAAU,mBAAmB,CACjC,MAA+B,EAC/B,QAAsB;IAEtB,OAAO;QACL,OAAO,EAAE,SAAS,CAAC,OAAO,CACxB,MAAM,EAAE,OAAO,IAAI,QAAQ,CAAC,OAAO,EACnC,QAAQ,CAAC,OAAyB,CACnC;QACD,SAAS,EAAE,OAAO,CAAC,YAAY,CAAC,MAAM,EAAE,SAAS,EAAE,QAAQ,CAAC,SAAS,CAAC;QACtE,OAAO,EAAE,MAAM,EAAE,OAAO,IAAI,QAAQ,CAAC,OAAO;QAC5C,WAAW,EAAE,yBAAyB,CACpC,MAAM,EAAE,WAAW,EACnB,QAAQ,CAAC,WAAW,CACrB;KACF,CAAA;AACH,CAAC;AAED,MAAM,UAAU,gBAAgB,CAC9B,IAAkB,EAClB,EAAgB,EAChB,CAAS;IAET,OAAO;QACL,OAAO,EAAE,SAAS,CAAC,IAAI,CACrB,IAAI,CAAC,OAAyB,EAC9B,EAAE,CAAC,OAAyB,EAC5B,CAAC,CACF;QACD,SAAS,EAAE,OAAO,CAAC,SAAS,CAAC,IAAI,CAAC,SAAS,EAAE,EAAE,CAAC,SAAS,EAAE,CAAC,CAAC;QAC7D,OAAO,EAAE,UAAU,CAAC,IAAI,CAAC,OAAO,EAAE,EAAE,CAAC,OAAO,EAAE,CAAC,CAAC;QAChD,WAAW,EAAE,sBAAsB,CAAC,IAAI,CAAC,WAAW,EAAE,EAAE,CAAC,WAAW,EAAE,CAAC,CAAC;KACzE,CAAA;AACH,CAAC;AAED,iEAAiE;AACjE,MAAM,UAAU,oBAAoB,CAClC,MAA4B,EAC5B,QAAkB;IAElB,OAAO,CAAC,MAAM,IAAI,QAAQ,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,SAAS,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,CAAA;AAC9D,CAAC;AAED,oFAAoF;AACpF,MAAM,UAAU,iBAAiB,CAC/B,IAAc,EACd,EAAY,EACZ,CAAS;IAET,MAAM,CAAC,GAAG,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,MAAM,EAAE,EAAE,CAAC,MAAM,CAAC,CAAA;IAC1C,MAAM,GAAG,GAAa,EAAE,CAAA;IACxB,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC;QAC3B,MAAM,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,CAAqB,CAAA;QAChD,MAAM,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,IAAI,CAAC,CAAC,CAAC,CAAqB,CAAA;QAChD,GAAG,CAAC,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC,CAAA;IACnC,CAAC;IACD,OAAO,GAAG,CAAA;AACZ,CAAC;AAED,+EAA+E;AAC/E,MAAM,UAAU,kBAAkB,CAChC,KAAyB,EACzB,QAAgB;IAEhB,OAAO,CAAC,KAAK,IAAI,QAAQ,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,CAAA;AAC3D,CAAC;AAED,0DAA0D;AAC1D,MAAM,UAAU,eAAe,CAAC,IAAY,EAAE,EAAU,EAAE,CAAS;IACjE,MAAM,CAAC,GAAG,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,MAAM,EAAE,EAAE,CAAC,MAAM,CAAC,CAAA;IAC1C,MAAM,GAAG,GAAW,EAAE,CAAA;IACtB,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC;QAC3B,MAAM,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,CAAmB,CAAA;QAC9C,MAAM,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,IAAI,CAAC,CAAC,CAAC,CAAmB,CAAA;QAC9C,GAAG,CAAC,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC,CAAA;IACjC,CAAC;IACD,OAAO,GAAG,CAAA;AACZ,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,mBAAmB,CACjC,OAAiB,EACjB,MAAmB,EACnB,KAAa;IAEb,MAAM,KAAK,GACT,OAAO,CAAC,MAAM,GAAG,CAAC;QAChB,CAAC,CAAC,OAAO,CAAC,KAAK,GAAG,OAAO,CAAC,MAAM,CAAC;QACjC,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,IAAI,EAAE,OAAO,EAAE,CAAA;IAClC,IAAI,MAAM,CAAC,IAAI,IAAI,IAAI;QAAE,OAAO,KAAK,CAAA;IACrC,MAAM,MAAM,GAAG,SAAS,CAAC,OAAO,CAAC,KAAK,CAAC,CAAA;IACvC,IAAI,MAAM,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,EAAE,MAAM,EAAE,CAAC,EAAE,IAAI,EAAE,MAAM,CAAC,IAAI,EAAE,CAAA;IAChE,MAAM,IAAI,GAAG,CAAC,GAAG,MAAM,CAAC,CAAA;IACxB,IAAI,CAAC,IAAI,CAAC,MAAM,GAAG,CAAC,CAAC,GAAG;QACtB,GAAG,IAAI,CAAC,IAAI,CAAC,MAAM,GAAG,CAAC,CAAC;QACxB,IAAI,EAAE,OAAO,CAAC,OAAO,CAAC,MAAM,CAAC,IAAI,CAAC;KACnC,CAAA;IACD,OAAO,IAAI,CAAA;AACb,CAAC;AAED,2FAA2F;AAC3F,MAAM,UAAU,iBAAiB,CAC/B,OAAiB,EACjB,MAAmB,EACnB,KAAa;IAEb,MAAM,MAAM,GAAG,SAAS,CAAC,OAAO,CAAC,mBAAmB,CAAC,OAAO,EAAE,MAAM,EAAE,KAAK,CAAC,CAAC,CAAA;IAC7E,OAAO,MAAM,CAAC,MAAM,CAAC,MAAM,GAAG,CAAC,CAAC,EAAE,IAAI,IAAI,OAAO,CAAA;AACnD,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,YAAY,CAAC,KAAa,EAAE,IAAa;IACvD,IAAI,MAAM,CAAC,SAAS,CAAC,KAAK,CAAC;QAAE,OAAO,MAAM,CAAC,KAAK,CAAC,CAAA;IACjD,MAAM,QAAQ,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,KAAK,SAAS,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,WAAW,CAAC,IAAI,CAAC,CAAC,CAAA;IACxE,OAAO,KAAK,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC,OAAO,CAAC,aAAa,EAAE,IAAI,CAAC,CAAC,OAAO,CAAC,KAAK,EAAE,EAAE,CAAC,CAAA;AAChF,CAAC;AAED,oEAAoE;AACpE,SAAS,WAAW,CAAC,IAAY;IAC/B,IAAI,CAAC,CAAC,IAAI,GAAG,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,IAAI,CAAC;QAAE,OAAO,CAAC,CAAA;IACnD,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,IAAI,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC;QAC5B,MAAM,MAAM,GAAG,IAAI,GAAG,EAAE,IAAI,CAAC,CAAA;QAC7B,IAAI,IAAI,CAAC,GAAG,CAAC,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,GAAG,IAAI,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,MAAM,CAAC;YAAE,OAAO,CAAC,CAAA;IAClF,CAAC;IACD,8EAA8E;IAC9E,OAAO,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAA;AACnE,CAAC;AAED,iGAAiG;AACjG,MAAM,UAAU,UAAU,CAAC,OAA0B;IACnD,MAAM,MAAM,GAAG,CAAC,GAAG,OAAO,CAAC,CAAC,MAAM,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,CAAA;IACzE,IAAI,IAAwB,CAAA;IAC5B,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;QACvC,MAAM,GAAG,GAAG,MAAM,CAAC,CAAC,CAAC,GAAG,MAAM,CAAC,CAAC,GAAG,CAAC,CAAC,CAAA;QACrC,IAAI,GAAG,GAAG,KAAK,IAAI,CAAC,IAAI,KAAK,SAAS,IAAI,GAAG,GAAG,IAAI,CAAC;YAAE,IAAI,GAAG,GAAG,CAAA;IACnE,CAAC;IACD,OAAO,IAAI,CAAA;AACb,CAAC;AAED,uFAAuF;AACvF,MAAM,UAAU,aAAa,CAAC,QAAgB;IAC5C,MAAM,GAAG,GAAG,QAAQ,GAAG,GAAG,CAAA;IAC1B,IAAI,MAAM,CAAC,SAAS,CAAC,GAAG,CAAC;QAAE,OAAO,GAAG,GAAG,GAAG,CAAA;IAC3C,OAAO,GAAG,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,MAAM,EAAE,EAAE,CAAC,GAAG,CAAA;AACjD,CAAC;AAED,mFAAmF;AACnF,MAAM,UAAU,YAAY,CAAC,CAAC,GAAG,EAAE,GAAG,CAAQ,EAAE,WAAmB;IACjE,MAAM,CAAC,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,KAAK,CAAC,WAAW,CAAC,CAAC,CAAA;IAC9C,OAAO,KAAK,CAAC,IAAI,CAAC,EAAE,MAAM,EAAE,CAAC,GAAG,CAAC,EAAE,EAAE,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,GAAG,GAAG,CAAC,CAAC,GAAG,GAAG,GAAG,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC,CAAA;AAC7E,CAAC","sourcesContent":["/**\n * What every chart shares: series, axis scaling and formatting, and the theme\n * leaves each chart's theme is assembled from. No `Node` imports, so a host's\n * inspector mappings can build a partial theme without the components.\n *\n * A mapper merges partial input onto a `previous` resolved value (idempotent). A\n * tween interpolates two resolved values leaf by leaf, but categorical fields\n * (`fontFamily`, `textAlign`) and any field `undefined` on either side step at\n * the midpoint: defaulting the missing side to 0 would animate a font weight\n * down to nothing on the way to \"unset\".\n */\n\nimport {\n fillOps,\n lerpNumber,\n shadowOps,\n strokeOps,\n insetsOps,\n textOps,\n type DataRecord,\n type Fill,\n type FillResolved,\n type Insets,\n type InsetsResolved,\n type Shadow,\n type ShadowResolved,\n type Stroke,\n type StrokeResolved,\n type TextStyle,\n} from \"@motionscript/sdk\"\n\n/** One series of a chart: a column of the table, captioned and painted. */\nexport interface ChartSeries {\n /** Key into each data row for this series' value. */\n field: string\n label: string\n /** Overrides the theme palette's entry for this series' index, for its mark and legend swatch. */\n fill?: Fill\n /** Defaults to `true`. */\n enabled?: boolean\n}\n\n/** A `[min, max]` numeric range in data units. */\nexport type Range = [min: number, max: number]\n\n/** One axis's *data* domain, as opposed to {@link AxisConfig}, which is how it is styled. */\nexport interface AxisDomainConfig {\n /** Caption drawn alongside the axis; `\"\"` hides it. */\n label?: string\n /** Derived from the data bounds when omitted. */\n range?: Range\n /** Derived (five evenly spaced) when omitted. */\n ticks?: number[]\n /**\n * A `number-format` pattern such as `#,##0.00` or `$#,##0`. It lives here, not\n * in {@link AxisConfig}, because it says what the column holds and has to\n * survive a re-theme.\n */\n format?: string\n}\n\n/** An {@link AxisDomainConfig} with `range` and `ticks` worked out. */\nexport type ResolvedAxisDomain = AxisDomainConfig & { readonly range: Range; readonly ticks: number[] }\n\n/**\n * Merges partial input onto `previous`, so a later `.set({ yAxis: {...} })`\n * patches `label`/`range`/`ticks` independently. An unset `range`/`ticks` is the\n * auto-derive signal.\n */\nexport function resolveAxisDomain(\n domain: AxisDomainConfig | undefined,\n previous?: AxisDomainConfig\n): AxisDomainConfig {\n return {\n label: domain?.label ?? previous?.label ?? \"\",\n range: domain?.range ?? previous?.range,\n ticks: domain?.ticks ?? previous?.ticks,\n format: domain?.format ?? previous?.format,\n }\n}\n\n/**\n * Interpolates `range` and `ticks` numerically (ticks pairwise by index).\n * `label`, `format`, and either field when one side is auto, step at the\n * midpoint: there is no halfway between `$#,##0` and `0.0%`.\n */\nexport function lerpAxisDomain(\n from: AxisDomainConfig,\n to: AxisDomainConfig,\n t: number\n): AxisDomainConfig {\n return {\n label: t < 0.5 ? from.label : to.label,\n range: lerpOptionalRange(from.range, to.range, t),\n ticks: lerpOptionalTicks(from.ticks, to.ticks, t),\n format: t < 0.5 ? from.format : to.format,\n }\n}\n\nfunction lerpOptionalRange(\n from: Range | undefined,\n to: Range | undefined,\n t: number\n): Range | undefined {\n if (!from || !to) return t < 0.5 ? from : to\n return [lerpNumber(from[0], to[0], t), lerpNumber(from[1], to[1], t)]\n}\n\nfunction lerpOptionalTicks(\n from: number[] | undefined,\n to: number[] | undefined,\n t: number\n): number[] | undefined {\n if (!from || !to) return t < 0.5 ? from : to\n const n = Math.max(from.length, to.length)\n const out: number[] = []\n for (let i = 0; i < n; i++) {\n out.push(lerpNumber(from[i] ?? to[i], to[i] ?? from[i], t))\n }\n return out\n}\n\n/**\n * An axis domain part-way through a tween that leaves or reaches a `range` or\n * `ticks` left to the data: both ends as stored, and how far along. Only the\n * chart knows what an auto side draws as, so {@link settleAxisDomain} resolves\n * it there. Its own fields are the plain {@link lerpAxisDomain} of its ends, so\n * a mapper merging onto one still reads a domain.\n */\nexport interface AxisDomainBlend extends AxisDomainConfig {\n readonly blend: { readonly from: AxisDomainConfig; readonly to: AxisDomainConfig; readonly t: number }\n}\n\nfunction blendOf(domain: AxisDomainConfig): AxisDomainBlend[\"blend\"] | undefined {\n return (domain as Partial<AxisDomainBlend>).blend\n}\n\n/**\n * The axis entry tween behind `to({ yAxis: { range } })`. Between explicit\n * domains it is {@link lerpAxisDomain}, and a restated `range` without `ticks`\n * spreads ticks across it, keeping their count. When either end leaves `range`\n * or `ticks` to the data, the value between is an {@link AxisDomainBlend}, so a\n * rescale from an auto axis is continuous rather than a cut at the midpoint.\n */\nexport function lerpAxisEntry(from: AxisDomainConfig, to: AxisDomainConfig, t: number): AxisDomainConfig {\n // The mapper merged the request onto `from`, so a field it left unstated is `from`'s own, by identity.\n const rangeMoved = to.range !== from.range\n const target = rangeMoved && to.range && to.ticks && to.ticks === from.ticks\n ? { ...to, ticks: markerValues(to.range, Math.max(2, to.ticks.length) - 1) }\n : to\n const blended = blendOf(from) !== undefined\n const moved = blended || rangeMoved || target.ticks !== from.ticks\n const auto = blended || from.range === undefined || from.ticks === undefined || target.range === undefined || target.ticks === undefined\n if (!moved || !auto) return lerpAxisDomain(from, target, t)\n if (t === 0) return from\n if (t === 1) return target\n const blend: AxisDomainBlend = { ...lerpAxisDomain(from, target, t), blend: { from, to: target, t } }\n return blend\n}\n\n/** `domain` as drawn: `drawn` resolves a plain domain's auto `range` and `ticks`; a blend is the lerp of what its ends draw. */\nexport function settleAxisDomain(domain: AxisDomainConfig, drawn: (domain: AxisDomainConfig) => AxisDomainConfig): AxisDomainConfig {\n const blend = blendOf(domain)\n if (!blend) return drawn(domain)\n return lerpAxisDomain(settleAxisDomain(blend.from, drawn), settleAxisDomain(blend.to, drawn), blend.t)\n}\n\n/** The colour tokens the default themes are built from: a dark plot panel with warm-grey axis furniture. */\nexport const CHART_PALETTE = {\n plotFill: \"#15130e\",\n borderColor: \"#4a4036\",\n gridColor: \"#2c2820\",\n /** Axis markers, axis captions and legend labels. */\n markerColor: \"#8a7f70\",\n /** A spotlit region's dashed rules and wash. */\n regionColor: \"#d99a3a\",\n} as const\n\n/** The out-of-the-box series palette, cycled by series index. */\nexport const DEFAULT_SERIES_COLORS = [\n \"#d9603b\",\n \"#8194ad\",\n \"#e0a93b\",\n \"#5e9d6b\",\n \"#9ec85a\",\n] as const\n\n/** Opacity an un-spotlighted series fades to, mark and legend entry alike. */\nexport const SPOTLIGHT_DIM = 0.2\n\n/**\n * Reads a numeric field off a row. A string column plots as 0, so a quoted or\n * unit-suffixed column needs the CSV parser's numeric coercion first.\n */\nexport function num(row: DataRecord, field: string | undefined): number {\n if (field === undefined) return 0\n const v = row[field]\n // A `NaN` or infinite cell is no more a measurement than a missing one: read\n // as 0, it cannot poison the scale and turn every point into `NaN`.\n return typeof v === \"number\" && Number.isFinite(v) ? v : 0\n}\n\n/** The counterpart to {@link num} for the columns a chart names things by; a missing cell reads as empty, not `\"undefined\"`. */\nexport function text(row: DataRecord, field: string | undefined): string {\n if (field === undefined || field === \"\") return \"\"\n const v = row[field]\n return v === undefined || v === null ? \"\" : String(v)\n}\n\n/**\n * Every numeric column of `data` in header order, skipping `exclude`. A column\n * is numeric only if every non-empty cell is a number, so a stray text cell\n * drops the column rather than plotting zeros.\n */\nexport function numericFields(\n data: DataRecord[],\n exclude: string[] = []\n): string[] {\n if (data.length === 0) return []\n const skip = new Set(exclude)\n const seen = new Set<string>()\n const order: string[] = []\n for (const row of data)\n for (const key of Object.keys(row))\n if (!skip.has(key) && !seen.has(key)) {\n seen.add(key)\n order.push(key)\n }\n\n return order.filter((key) => {\n let sawValue = false\n for (const row of data) {\n const v = row[key]\n if (v === undefined || v === \"\") continue\n if (typeof v !== \"number\") return false\n sawValue = true\n }\n return sawValue\n })\n}\n\n/** One axis's (x or y) style vocabulary. */\nexport interface AxisConfig {\n /** Style of each marker along the axis. */\n labelStyle: TextStyle\n titleStyle: TextStyle\n /** This axis's grid lines: weight and fill honoured, dash/cap/join ignored (they are filled rects). */\n lineStyle: Stroke\n /** Gap between the plot and the marker row; only the side facing the plot is read (`.top` horizontal, `.right` vertical). */\n tickPadding: Insets\n /** Gap between the marker row and the caption, read the same side. */\n titlePadding: Insets\n}\n\n/** A legend's per-series colour swatch. */\nexport interface LegendMarkerConfig {\n width: number\n height: number\n borderRadius: number\n stroke: Stroke\n shadow: Shadow\n}\n\nexport interface LegendConfig {\n padding: Insets\n /** Only the swatch carries the series colour. */\n textStyle: TextStyle\n itemGap: number\n markerStyle: LegendMarkerConfig\n}\n\n/** The plot panel a cartesian chart draws its marks over. */\nexport interface PlotAreaConfig {\n stroke: Stroke\n fill: Fill\n shadow: Shadow\n}\n\nconst AXIS_LABEL_STYLE: TextStyle = {\n fontSize: 24,\n fontWeight: 700,\n textAlign: \"center\",\n fill: CHART_PALETTE.markerColor,\n}\nconst AXIS_TITLE_STYLE: TextStyle = {\n fontSize: 30,\n fontWeight: 600,\n textAlign: \"center\",\n fill: CHART_PALETTE.markerColor,\n}\nconst AXIS_LINE_STYLE: Stroke = { weight: 2, fill: CHART_PALETTE.gridColor }\n\nexport const DEFAULT_X_AXIS: AxisConfig = {\n labelStyle: AXIS_LABEL_STYLE,\n titleStyle: AXIS_TITLE_STYLE,\n lineStyle: AXIS_LINE_STYLE,\n tickPadding: 20,\n titlePadding: 4,\n}\n\nexport const DEFAULT_Y_AXIS: AxisConfig = {\n labelStyle: { ...AXIS_LABEL_STYLE, fontWeight: 500, textAlign: \"right\" },\n titleStyle: AXIS_TITLE_STYLE,\n lineStyle: AXIS_LINE_STYLE,\n tickPadding: 40,\n titlePadding: 24,\n}\n\n/** Unpainted but framed: a chart reads against the stage rather than punching a panel into it. */\nexport const DEFAULT_PLOT_AREA: PlotAreaConfig = {\n fill: [],\n stroke: { weight: 6, fill: CHART_PALETTE.borderColor },\n shadow: [],\n}\n\nexport const DEFAULT_LEGEND: LegendConfig = {\n padding: 0,\n textStyle: {\n fontSize: 30,\n fontWeight: 600,\n textAlign: \"left\",\n fill: CHART_PALETTE.markerColor,\n },\n itemGap: 44,\n markerStyle: {\n width: 60,\n height: 24,\n borderRadius: 6,\n stroke: [],\n shadow: [],\n },\n}\n\n/** {@link DEFAULT_SERIES_COLORS} as 4px strokes. */\nexport const DEFAULT_SERIES_STROKES: Stroke[] = DEFAULT_SERIES_COLORS.map(\n (fill) => ({ weight: 4, fill })\n)\n\n/** {@link DEFAULT_SERIES_COLORS} as solid fills. */\nexport const DEFAULT_SERIES_FILLS: Fill[] = DEFAULT_SERIES_COLORS.map(\n (fill) => fill\n)\n\nexport function resolveAxisConfig(\n axis: Partial<AxisConfig> | undefined,\n previous: AxisConfig\n): AxisConfig {\n return {\n labelStyle: textOps.resolveStyle(axis?.labelStyle, previous.labelStyle),\n titleStyle: textOps.resolveStyle(axis?.titleStyle, previous.titleStyle),\n lineStyle: strokeOps.resolve(axis?.lineStyle ?? previous.lineStyle),\n tickPadding: insetsOps.resolve(\n axis?.tickPadding ?? previous.tickPadding,\n previous.tickPadding as InsetsResolved\n ),\n titlePadding: insetsOps.resolve(\n axis?.titlePadding ?? previous.titlePadding,\n previous.titlePadding as InsetsResolved\n ),\n }\n}\n\nexport function lerpAxisConfig(\n from: AxisConfig,\n to: AxisConfig,\n t: number\n): AxisConfig {\n return {\n labelStyle: textOps.lerpStyle(from.labelStyle, to.labelStyle, t),\n titleStyle: textOps.lerpStyle(from.titleStyle, to.titleStyle, t),\n lineStyle: strokeOps.lerp(\n from.lineStyle as StrokeResolved[],\n to.lineStyle as StrokeResolved[],\n t\n ),\n tickPadding: insetsOps.lerp(\n from.tickPadding as InsetsResolved,\n to.tickPadding as InsetsResolved,\n t\n ),\n titlePadding: insetsOps.lerp(\n from.titlePadding as InsetsResolved,\n to.titlePadding as InsetsResolved,\n t\n ),\n }\n}\n\nexport function resolvePlotArea(\n plotArea: Partial<PlotAreaConfig> | undefined,\n previous: PlotAreaConfig\n): PlotAreaConfig {\n return {\n fill: fillOps.resolve(plotArea?.fill ?? previous.fill),\n stroke: strokeOps.resolve(plotArea?.stroke ?? previous.stroke),\n shadow: shadowOps.resolve(plotArea?.shadow ?? previous.shadow),\n }\n}\n\nexport function lerpPlotArea(\n from: PlotAreaConfig,\n to: PlotAreaConfig,\n t: number\n): PlotAreaConfig {\n return {\n fill: fillOps.lerp(\n from.fill as FillResolved[],\n to.fill as FillResolved[],\n t\n ),\n stroke: strokeOps.lerp(\n from.stroke as StrokeResolved[],\n to.stroke as StrokeResolved[],\n t\n ),\n shadow: shadowOps.lerp(\n from.shadow as ShadowResolved[],\n to.shadow as ShadowResolved[],\n t\n ),\n }\n}\n\nfunction resolveLegendMarkerConfig(\n marker: Partial<LegendMarkerConfig> | undefined,\n previous: LegendMarkerConfig\n): LegendMarkerConfig {\n return {\n width: marker?.width ?? previous.width,\n height: marker?.height ?? previous.height,\n borderRadius: marker?.borderRadius ?? previous.borderRadius,\n stroke: strokeOps.resolve(marker?.stroke ?? previous.stroke),\n shadow: shadowOps.resolve(marker?.shadow ?? previous.shadow),\n }\n}\n\nfunction lerpLegendMarkerConfig(\n from: LegendMarkerConfig,\n to: LegendMarkerConfig,\n t: number\n): LegendMarkerConfig {\n return {\n width: lerpNumber(from.width, to.width, t),\n height: lerpNumber(from.height, to.height, t),\n borderRadius: lerpNumber(from.borderRadius, to.borderRadius, t),\n stroke: strokeOps.lerp(\n from.stroke as StrokeResolved[],\n to.stroke as StrokeResolved[],\n t\n ),\n shadow: shadowOps.lerp(\n from.shadow as ShadowResolved[],\n to.shadow as ShadowResolved[],\n t\n ),\n }\n}\n\n/** A legend theme as the author may state it: every branch optional. */\nexport type LegendTheme = Partial<Omit<LegendConfig, \"markerStyle\">> & {\n markerStyle?: Partial<LegendMarkerConfig>\n}\n\nexport function resolveLegendConfig(\n legend: LegendTheme | undefined,\n previous: LegendConfig\n): LegendConfig {\n return {\n padding: insetsOps.resolve(\n legend?.padding ?? previous.padding,\n previous.padding as InsetsResolved\n ),\n textStyle: textOps.resolveStyle(legend?.textStyle, previous.textStyle),\n itemGap: legend?.itemGap ?? previous.itemGap,\n markerStyle: resolveLegendMarkerConfig(\n legend?.markerStyle,\n previous.markerStyle\n ),\n }\n}\n\nexport function lerpLegendConfig(\n from: LegendConfig,\n to: LegendConfig,\n t: number\n): LegendConfig {\n return {\n padding: insetsOps.lerp(\n from.padding as InsetsResolved,\n to.padding as InsetsResolved,\n t\n ),\n textStyle: textOps.lerpStyle(from.textStyle, to.textStyle, t),\n itemGap: lerpNumber(from.itemGap, to.itemGap, t),\n markerStyle: lerpLegendMarkerConfig(from.markerStyle, to.markerStyle, t),\n }\n}\n\n/** A palette override replaces the previous palette outright. */\nexport function resolveSeriesStrokes(\n styles: Stroke[] | undefined,\n previous: Stroke[]\n): Stroke[] {\n return (styles ?? previous).map((s) => strokeOps.resolve(s))\n}\n\n/** Pairwise by index; a palette that grows/shrinks holds the longer side's tail. */\nexport function lerpSeriesStrokes(\n from: Stroke[],\n to: Stroke[],\n t: number\n): Stroke[] {\n const n = Math.max(from.length, to.length)\n const out: Stroke[] = []\n for (let i = 0; i < n; i++) {\n const a = (from[i] ?? to[i]) as StrokeResolved[]\n const b = (to[i] ?? from[i]) as StrokeResolved[]\n out.push(strokeOps.lerp(a, b, t))\n }\n return out\n}\n\n/** The fill-palette twin of {@link resolveSeriesStrokes}, for filled marks. */\nexport function resolveSeriesFills(\n fills: Fill[] | undefined,\n previous: Fill[]\n): Fill[] {\n return (fills ?? previous).map((f) => fillOps.resolve(f))\n}\n\n/** The fill-palette twin of {@link lerpSeriesStrokes}. */\nexport function lerpSeriesFills(from: Fill[], to: Fill[], t: number): Fill[] {\n const n = Math.max(from.length, to.length)\n const out: Fill[] = []\n for (let i = 0; i < n; i++) {\n const a = (from[i] ?? to[i]) as FillResolved[]\n const b = (to[i] ?? from[i]) as FillResolved[]\n out.push(fillOps.lerp(a, b, t))\n }\n return out\n}\n\n/**\n * The stroke for series `index`: the palette's entry at `index % palette.length`,\n * with the series' own `fill`, if set, replacing just the topmost layer's colour.\n */\nexport function resolveSeriesStroke(\n palette: Stroke[],\n series: ChartSeries,\n index: number\n): Stroke {\n const entry: Stroke =\n palette.length > 0\n ? palette[index % palette.length]\n : { weight: 4, fill: \"white\" }\n if (series.fill == null) return entry\n const layers = strokeOps.resolve(entry)\n if (layers.length === 0) return { weight: 4, fill: series.fill }\n const next = [...layers]\n next[next.length - 1] = {\n ...next[next.length - 1],\n fill: fillOps.resolve(series.fill),\n }\n return next\n}\n\n/** The colour {@link resolveSeriesStroke} draws series `index` in, for a legend swatch. */\nexport function resolveSeriesFill(\n palette: Stroke[],\n series: ChartSeries,\n index: number\n): Fill {\n const layers = strokeOps.resolve(resolveSeriesStroke(palette, series, index))\n return layers[layers.length - 1]?.fill ?? \"white\"\n}\n\n/**\n * Format a marker value: integers plain, otherwise one decimal, or as many as\n * the tick `step` needs to tell neighbours apart (a unit axis ticked every 0.05\n * gets two, not `0.1 0.1 0.2 0.2 0.3`). Trailing zeros are dropped.\n */\nexport function formatMarker(value: number, step?: number): string {\n if (Number.isInteger(value)) return String(value)\n const decimals = Math.max(1, step === undefined ? 1 : decimalsFor(step))\n return value.toFixed(decimals).replace(/(\\.\\d*?)0+$/, \"$1\").replace(/\\.$/, \"\")\n}\n\n/** Decimal places needed to write `step` exactly, capped at six. */\nfunction decimalsFor(step: number): number {\n if (!(step > 0) || !Number.isFinite(step)) return 1\n for (let d = 0; d <= 6; d++) {\n const scaled = step * 10 ** d\n if (Math.abs(scaled - Math.round(scaled)) < 1e-6 * Math.max(1, scaled)) return d\n }\n // An irrational-looking step (a third): as many places as separate the ticks.\n return Math.min(6, Math.max(1, Math.ceil(-Math.log10(step)) + 1))\n}\n\n/** The gap between neighbouring tick values, or `undefined` for fewer than two distinct ones. */\nexport function markerStep(markers: readonly number[]): number | undefined {\n const sorted = [...markers].filter(Number.isFinite).sort((a, b) => a - b)\n let step: number | undefined\n for (let i = 1; i < sorted.length; i++) {\n const gap = sorted[i] - sorted[i - 1]\n if (gap > 1e-12 && (step === undefined || gap < step)) step = gap\n }\n return step\n}\n\n/** Format a fraction in `[0, 1]` as a percentage: integers plain, else one decimal. */\nexport function formatPercent(fraction: number): string {\n const pct = fraction * 100\n if (Number.isInteger(pct)) return `${pct}%`\n return `${pct.toFixed(1).replace(/\\.0$/, \"\")}%`\n}\n\n/** `markerCount` evenly-spaced tick values across `[min, max]`, ends inclusive. */\nexport function markerValues([min, max]: Range, markerCount: number): number[] {\n const n = Math.max(2, Math.round(markerCount))\n return Array.from({ length: n + 1 }, (_, i) => min + ((max - min) / n) * i)\n}\n"]}
|
|
1
|
+
{"version":3,"file":"shared.js","sourceRoot":"","sources":["../../src/kit/shared.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH,OAAO,EACL,UAAU,GAOX,MAAM,mBAAmB,CAAA;AAC1B,OAAO,EAAE,QAAQ,EAAE,MAAM,6BAA6B,CAAA;AAoCtD;;;;GAIG;AACH,MAAM,UAAU,iBAAiB,CAC/B,MAAoC,EACpC,QAA2B;IAE3B,OAAO;QACL,KAAK,EAAE,MAAM,EAAE,KAAK,IAAI,QAAQ,EAAE,KAAK,IAAI,EAAE;QAC7C,KAAK,EAAE,MAAM,EAAE,KAAK,IAAI,QAAQ,EAAE,KAAK;QACvC,KAAK,EAAE,MAAM,EAAE,KAAK,IAAI,QAAQ,EAAE,KAAK;QACvC,MAAM,EAAE,MAAM,EAAE,MAAM,IAAI,QAAQ,EAAE,MAAM;KAC3C,CAAA;AACH,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,cAAc,CAC5B,IAAsB,EACtB,EAAoB,EACpB,CAAS;IAET,OAAO;QACL,KAAK,EAAE,CAAC,GAAG,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,CAAC,KAAK;QACtC,KAAK,EAAE,iBAAiB,CAAC,IAAI,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,EAAE,CAAC,CAAC;QACjD,KAAK,EAAE,iBAAiB,CAAC,IAAI,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,EAAE,CAAC,CAAC;QACjD,MAAM,EAAE,CAAC,GAAG,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,MAAM;KAC1C,CAAA;AACH,CAAC;AAED,SAAS,iBAAiB,CACxB,IAAuB,EACvB,EAAqB,EACrB,CAAS;IAET,IAAI,CAAC,IAAI,IAAI,CAAC,EAAE;QAAE,OAAO,CAAC,GAAG,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAA;IAC5C,OAAO,CAAC,UAAU,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,UAAU,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAA;AACvE,CAAC;AAED,SAAS,iBAAiB,CACxB,IAA0B,EAC1B,EAAwB,EACxB,CAAS;IAET,IAAI,CAAC,IAAI,IAAI,CAAC,EAAE;QAAE,OAAO,CAAC,GAAG,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAA;IAC5C,MAAM,CAAC,GAAG,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,MAAM,EAAE,EAAE,CAAC,MAAM,CAAC,CAAA;IAC1C,MAAM,GAAG,GAAa,EAAE,CAAA;IACxB,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC;QAC3B,GAAG,CAAC,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAA;IAC7D,CAAC;IACD,OAAO,GAAG,CAAA;AACZ,CAAC;AAaD,SAAS,OAAO,CAAC,MAAwB;IACvC,OAAQ,MAAmC,CAAC,KAAK,CAAA;AACnD,CAAC;AAED;;;;;;GAMG;AACH,MAAM,UAAU,aAAa,CAAC,IAAsB,EAAE,EAAoB,EAAE,CAAS;IACnF,uGAAuG;IACvG,MAAM,UAAU,GAAG,EAAE,CAAC,KAAK,KAAK,IAAI,CAAC,KAAK,CAAA;IAC1C,MAAM,MAAM,GAAG,UAAU,IAAI,EAAE,CAAC,KAAK,IAAI,EAAE,CAAC,KAAK,IAAI,EAAE,CAAC,KAAK,KAAK,IAAI,CAAC,KAAK;QAC1E,CAAC,CAAC,EAAE,GAAG,EAAE,EAAE,KAAK,EAAE,YAAY,CAAC,EAAE,CAAC,KAAK,EAAE,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,EAAE,CAAC,KAAK,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,EAAE;QAC5E,CAAC,CAAC,EAAE,CAAA;IACN,MAAM,OAAO,GAAG,OAAO,CAAC,IAAI,CAAC,KAAK,SAAS,CAAA;IAC3C,MAAM,KAAK,GAAG,OAAO,IAAI,UAAU,IAAI,MAAM,CAAC,KAAK,KAAK,IAAI,CAAC,KAAK,CAAA;IAClE,MAAM,IAAI,GAAG,OAAO,IAAI,IAAI,CAAC,KAAK,KAAK,SAAS,IAAI,IAAI,CAAC,KAAK,KAAK,SAAS,IAAI,MAAM,CAAC,KAAK,KAAK,SAAS,IAAI,MAAM,CAAC,KAAK,KAAK,SAAS,CAAA;IACxI,IAAI,CAAC,KAAK,IAAI,CAAC,IAAI;QAAE,OAAO,cAAc,CAAC,IAAI,EAAE,MAAM,EAAE,CAAC,CAAC,CAAA;IAC3D,IAAI,CAAC,KAAK,CAAC;QAAE,OAAO,IAAI,CAAA;IACxB,IAAI,CAAC,KAAK,CAAC;QAAE,OAAO,MAAM,CAAA;IAC1B,MAAM,KAAK,GAAoB,EAAE,GAAG,cAAc,CAAC,IAAI,EAAE,MAAM,EAAE,CAAC,CAAC,EAAE,KAAK,EAAE,EAAE,IAAI,EAAE,EAAE,EAAE,MAAM,EAAE,CAAC,EAAE,EAAE,CAAA;IACrG,OAAO,KAAK,CAAA;AACd,CAAC;AAED,gIAAgI;AAChI,MAAM,UAAU,gBAAgB,CAAC,MAAwB,EAAE,KAAqD;IAC9G,MAAM,KAAK,GAAG,OAAO,CAAC,MAAM,CAAC,CAAA;IAC7B,IAAI,CAAC,KAAK;QAAE,OAAO,KAAK,CAAC,MAAM,CAAC,CAAA;IAChC,OAAO,cAAc,CAAC,gBAAgB,CAAC,KAAK,CAAC,IAAI,EAAE,KAAK,CAAC,EAAE,gBAAgB,CAAC,KAAK,CAAC,EAAE,EAAE,KAAK,CAAC,EAAE,KAAK,CAAC,CAAC,CAAC,CAAA;AACxG,CAAC;AAED,4GAA4G;AAC5G,MAAM,aAAa,GAAG;IACpB,QAAQ,EAAE,SAAS;IACnB,WAAW,EAAE,SAAS;IACtB,SAAS,EAAE,SAAS;IACpB,qDAAqD;IACrD,WAAW,EAAE,SAAS;IACtB,gDAAgD;IAChD,WAAW,EAAE,SAAS;CACd,CAAA;AAEV,8EAA8E;AAC9E,MAAM,CAAC,MAAM,aAAa,GAAG,GAAG,CAAA;AAEhC;;;GAGG;AACH,MAAM,UAAU,GAAG,CAAC,GAAe,EAAE,KAAyB;IAC5D,IAAI,KAAK,KAAK,SAAS;QAAE,OAAO,CAAC,CAAA;IACjC,MAAM,CAAC,GAAG,GAAG,CAAC,KAAK,CAAC,CAAA;IACpB,6EAA6E;IAC7E,oEAAoE;IACpE,OAAO,OAAO,CAAC,KAAK,QAAQ,IAAI,MAAM,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAA;AAC5D,CAAC;AAED,gIAAgI;AAChI,MAAM,UAAU,IAAI,CAAC,GAAe,EAAE,KAAyB;IAC7D,IAAI,KAAK,KAAK,SAAS,IAAI,KAAK,KAAK,EAAE;QAAE,OAAO,EAAE,CAAA;IAClD,MAAM,CAAC,GAAG,GAAG,CAAC,KAAK,CAAC,CAAA;IACpB,OAAO,CAAC,KAAK,SAAS,IAAI,CAAC,KAAK,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,CAAA;AACvD,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,aAAa,CAC3B,IAAkB,EAClB,UAAoB,EAAE;IAEtB,IAAI,IAAI,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,EAAE,CAAA;IAChC,MAAM,IAAI,GAAG,IAAI,GAAG,CAAC,OAAO,CAAC,CAAA;IAC7B,MAAM,IAAI,GAAG,IAAI,GAAG,EAAU,CAAA;IAC9B,MAAM,KAAK,GAAa,EAAE,CAAA;IAC1B,KAAK,MAAM,GAAG,IAAI,IAAI;QACpB,KAAK,MAAM,GAAG,IAAI,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC;YAChC,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,EAAE,CAAC;gBACrC,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,CAAA;gBACb,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,CAAA;YACjB,CAAC;IAEL,OAAO,KAAK,CAAC,MAAM,CAAC,CAAC,GAAG,EAAE,EAAE;QAC1B,IAAI,QAAQ,GAAG,KAAK,CAAA;QACpB,KAAK,MAAM,GAAG,IAAI,IAAI,EAAE,CAAC;YACvB,MAAM,CAAC,GAAG,GAAG,CAAC,GAAG,CAAC,CAAA;YAClB,IAAI,CAAC,KAAK,SAAS,IAAI,CAAC,KAAK,EAAE;gBAAE,SAAQ;YACzC,IAAI,OAAO,CAAC,KAAK,QAAQ;gBAAE,OAAO,KAAK,CAAA;YACvC,QAAQ,GAAG,IAAI,CAAA;QACjB,CAAC;QACD,OAAO,QAAQ,CAAA;IACjB,CAAC,CAAC,CAAA;AACJ,CAAC;AAgCD,MAAM,gBAAgB,GAAc;IAClC,QAAQ,EAAE,EAAE;IACZ,UAAU,EAAE,GAAG;IACf,SAAS,EAAE,QAAQ;IACnB,IAAI,EAAE,aAAa,CAAC,WAAW;CAChC,CAAA;AACD,MAAM,gBAAgB,GAAc;IAClC,QAAQ,EAAE,EAAE;IACZ,UAAU,EAAE,GAAG;IACf,SAAS,EAAE,QAAQ;IACnB,IAAI,EAAE,aAAa,CAAC,WAAW;CAChC,CAAA;AACD,MAAM,eAAe,GAAW,EAAE,MAAM,EAAE,CAAC,EAAE,IAAI,EAAE,aAAa,CAAC,SAAS,EAAE,CAAA;AAE5E,MAAM,CAAC,MAAM,cAAc,GAAe;IACxC,UAAU,EAAE,gBAAgB;IAC5B,UAAU,EAAE,gBAAgB;IAC5B,SAAS,EAAE,eAAe;IAC1B,WAAW,EAAE,EAAE;IACf,YAAY,EAAE,CAAC;CAChB,CAAA;AAED,MAAM,CAAC,MAAM,cAAc,GAAe;IACxC,UAAU,EAAE,EAAE,GAAG,gBAAgB,EAAE,UAAU,EAAE,GAAG,EAAE,SAAS,EAAE,OAAO,EAAE;IACxE,UAAU,EAAE,gBAAgB;IAC5B,SAAS,EAAE,eAAe;IAC1B,WAAW,EAAE,EAAE;IACf,YAAY,EAAE,EAAE;CACjB,CAAA;AAED,MAAM,CAAC,MAAM,cAAc,GAAiB;IAC1C,OAAO,EAAE,CAAC;IACV,SAAS,EAAE;QACT,QAAQ,EAAE,EAAE;QACZ,UAAU,EAAE,GAAG;QACf,SAAS,EAAE,MAAM;QACjB,IAAI,EAAE,aAAa,CAAC,WAAW;KAChC;IACD,OAAO,EAAE,EAAE;IACX,WAAW,EAAE;QACX,KAAK,EAAE,EAAE;QACT,MAAM,EAAE,EAAE;QACV,YAAY,EAAE,CAAC;QACf,MAAM,EAAE,EAAE;QACV,MAAM,EAAE,EAAE;KACX;CACF,CAAA;AAED;;;;GAIG;AACH,MAAM,UAAU,YAAY,CAAC,KAAa,EAAE,IAAa;IACvD,IAAI,MAAM,CAAC,SAAS,CAAC,KAAK,CAAC;QAAE,OAAO,MAAM,CAAC,KAAK,CAAC,CAAA;IACjD,MAAM,QAAQ,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,KAAK,SAAS,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,WAAW,CAAC,IAAI,CAAC,CAAC,CAAA;IACxE,OAAO,KAAK,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC,OAAO,CAAC,aAAa,EAAE,IAAI,CAAC,CAAC,OAAO,CAAC,KAAK,EAAE,EAAE,CAAC,CAAA;AAChF,CAAC;AAED,oEAAoE;AACpE,SAAS,WAAW,CAAC,IAAY;IAC/B,IAAI,CAAC,CAAC,IAAI,GAAG,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,IAAI,CAAC;QAAE,OAAO,CAAC,CAAA;IACnD,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,IAAI,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC;QAC5B,MAAM,MAAM,GAAG,IAAI,GAAG,EAAE,IAAI,CAAC,CAAA;QAC7B,IAAI,IAAI,CAAC,GAAG,CAAC,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,GAAG,IAAI,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,MAAM,CAAC;YAAE,OAAO,CAAC,CAAA;IAClF,CAAC;IACD,8EAA8E;IAC9E,OAAO,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAA;AACnE,CAAC;AAED,iGAAiG;AACjG,MAAM,UAAU,UAAU,CAAC,OAA0B;IACnD,MAAM,MAAM,GAAG,CAAC,GAAG,OAAO,CAAC,CAAC,MAAM,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,CAAA;IACzE,IAAI,IAAwB,CAAA;IAC5B,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;QACvC,MAAM,GAAG,GAAG,MAAM,CAAC,CAAC,CAAC,GAAG,MAAM,CAAC,CAAC,GAAG,CAAC,CAAC,CAAA;QACrC,IAAI,GAAG,GAAG,KAAK,IAAI,CAAC,IAAI,KAAK,SAAS,IAAI,GAAG,GAAG,IAAI,CAAC;YAAE,IAAI,GAAG,GAAG,CAAA;IACnE,CAAC;IACD,OAAO,IAAI,CAAA;AACb,CAAC;AAED,uFAAuF;AACvF,MAAM,UAAU,aAAa,CAAC,QAAgB;IAC5C,MAAM,GAAG,GAAG,QAAQ,GAAG,GAAG,CAAA;IAC1B,IAAI,MAAM,CAAC,SAAS,CAAC,GAAG,CAAC;QAAE,OAAO,GAAG,GAAG,GAAG,CAAA;IAC3C,OAAO,GAAG,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,MAAM,EAAE,EAAE,CAAC,GAAG,CAAA;AACjD,CAAC;AAED,mFAAmF;AACnF,MAAM,UAAU,YAAY,CAAC,CAAC,GAAG,EAAE,GAAG,CAAQ,EAAE,WAAmB;IACjE,MAAM,CAAC,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,KAAK,CAAC,WAAW,CAAC,CAAC,CAAA;IAC9C,OAAO,KAAK,CAAC,IAAI,CAAC,EAAE,MAAM,EAAE,CAAC,GAAG,CAAC,EAAE,EAAE,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,GAAG,GAAG,CAAC,CAAC,GAAG,GAAG,GAAG,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC,CAAA;AAC7E,CAAC;AAED,qGAAqG;AACrG,MAAM,UAAU,SAAS,CAAC,CAAC,EAAE,EAAE,EAAE,CAAQ,EAAE,SAAiB;IAC1D,MAAM,QAAQ,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,KAAK,CAAC,SAAS,CAAC,CAAC,CAAA;IACnD,IAAI,EAAE,KAAK,EAAE;QAAE,OAAO,aAAa,CAAC,EAAE,EAAE,QAAQ,CAAC,CAAA;IACjD,MAAM,IAAI,GAAG,QAAQ,CAAC,CAAC,EAAE,GAAG,EAAE,CAAC,GAAG,QAAQ,CAAC,CAAA;IAC3C,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,EAAE,GAAG,IAAI,CAAC,GAAG,IAAI,EAAE,IAAI,CAAC,IAAI,CAAC,EAAE,GAAG,IAAI,CAAC,GAAG,IAAI,CAAC,CAAA;AACpE,CAAC;AAED;;;;GAIG;AACH,SAAS,aAAa,CAAC,KAAa,EAAE,QAAgB;IACpD,IAAI,KAAK,KAAK,CAAC;QAAE,OAAO,CAAC,CAAC,EAAE,CAAC,CAAC,CAAA;IAC9B,MAAM,IAAI,GAAG,QAAQ,CAAC,IAAI,CAAC,GAAG,CAAC,KAAK,CAAC,GAAG,QAAQ,CAAC,CAAA;IACjD,OAAO,CAAC,KAAK,GAAG,IAAI,EAAE,KAAK,GAAG,IAAI,CAAC,CAAA;AACrC,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,SAAS,CAAC,CAAC,EAAE,EAAE,EAAE,CAAQ,EAAE,SAAiB;IAC1D,MAAM,IAAI,GAAG,EAAE,GAAG,EAAE,CAAA;IACpB,MAAM,MAAM,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,KAAK,CAAC,SAAS,CAAC,CAAC,CAAA;IACjD,IAAI,CAAC,CAAC,IAAI,GAAG,CAAC,CAAC;QAAE,OAAO,YAAY,CAAC,CAAC,EAAE,EAAE,EAAE,CAAC,EAAE,MAAM,CAAC,CAAA;IACtD,MAAM,KAAK,GAAG,CAAC,CAAS,EAAE,EAAE,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,GAAG,IAAI,CAAA;IAC/D,MAAM,IAAI,GAAG,QAAQ,CAAC,IAAI,GAAG,MAAM,CAAC,CAAA;IACpC,IAAI,IAAwB,CAAA;IAC5B,KAAK,MAAM,IAAI,IAAI,MAAM,CAAC,IAAI,CAAC,EAAE,CAAC;QAChC,MAAM,KAAK,GAAG,IAAI,GAAG,IAAI,CAAA;QACzB,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,EAAE,GAAG,IAAI,CAAC,IAAI,KAAK,GAAG,CAAC,IAAI,KAAK,GAAG,CAAC;YAAE,SAAQ;QAC1E,IAAI,IAAI,KAAK,SAAS,IAAI,IAAI,CAAC,GAAG,CAAC,KAAK,GAAG,MAAM,CAAC,GAAG,IAAI,CAAC,GAAG,CAAC,IAAI,GAAG,IAAI,GAAG,MAAM,CAAC;YAAE,IAAI,GAAG,IAAI,CAAA;IAClG,CAAC;IACD,IAAI,IAAI,KAAK,SAAS;QAAE,OAAO,YAAY,CAAC,CAAC,EAAE,EAAE,EAAE,CAAC,EAAE,MAAM,CAAC,CAAA;IAC7D,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,EAAE,GAAG,IAAI,CAAC,CAAA;IACnC,OAAO,KAAK,CAAC,IAAI,CAAC,EAAE,MAAM,EAAE,IAAI,CAAC,KAAK,CAAC,IAAI,GAAG,IAAI,CAAC,GAAG,CAAC,EAAE,EAAE,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,MAAM,CAAC,CAAC,CAAC,KAAK,GAAG,CAAC,CAAC,GAAG,IAAI,CAAC,CAAC,WAAW,CAAC,EAAE,CAAC,CAAC,CAAC,CAAA;AACpH,CAAC;AAED,sEAAsE;AACtE,SAAS,MAAM,CAAC,IAAY;IAC1B,MAAM,GAAG,GAAG,EAAE,IAAI,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,CAAA;IAC9C,MAAM,KAAK,GAAa,EAAE,CAAA;IAC1B,KAAK,MAAM,CAAC,IAAI,CAAC,GAAG,GAAG,EAAE,EAAE,GAAG,EAAE,GAAG,GAAG,EAAE,CAAC;QAAE,KAAK,MAAM,CAAC,IAAI,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC;YAAE,KAAK,CAAC,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC,CAAA;IACvF,MAAM,EAAE,GAAG,KAAK,CAAC,SAAS,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,GAAG,IAAI,CAAC,GAAG,IAAI,GAAG,IAAI,CAAC,CAAA;IACnE,OAAO,KAAK,CAAC,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,EAAE,GAAG,CAAC,CAAC,EAAE,EAAE,GAAG,CAAC,CAAC,CAAA;AACjD,CAAC","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"]}
|