@motionscript/charts 0.1.1-alpha.0 → 0.1.1-alpha.2
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 +34 -0
- package/README.md +109 -28
- package/dist/bar-chart/bar-chart.d.ts +265 -39
- package/dist/bar-chart/bar-chart.d.ts.map +1 -1
- package/dist/bar-chart/bar-chart.js +219 -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 +76 -52
- package/dist/bar-chart/chart-bars.d.ts.map +1 -1
- package/dist/bar-chart/chart-bars.js +105 -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 +41 -65
- package/dist/bar-chart/shared.d.ts.map +1 -1
- package/dist/bar-chart/shared.js +73 -117
- package/dist/bar-chart/shared.js.map +1 -1
- package/dist/browser/chunks/chunk-7XCRX6GE.js +2 -0
- package/dist/browser/chunks/chunk-7XCRX6GE.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 +51 -15
- package/dist/kit/cartesian.d.ts.map +1 -1
- package/dist/kit/cartesian.js +81 -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 +517 -0
- package/dist/kit/style.d.ts.map +1 -0
- package/dist/kit/style.js +292 -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 +281 -18
- package/dist/line-chart/line-chart.d.ts.map +1 -1
- package/dist/line-chart/line-chart.js +284 -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 +38 -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 +61 -62
- package/dist/pie-chart/shared.d.ts.map +1 -1
- package/dist/pie-chart/shared.js +44 -123
- 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 +212 -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 +49 -0
- package/dist/radar-chart/radar-grid.d.ts.map +1 -0
- package/dist/radar-chart/radar-grid.js +63 -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 +78 -0
- package/dist/radar-chart/shared.d.ts.map +1 -0
- package/dist/radar-chart/shared.js +129 -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 +210 -0
- package/dist/radial-chart/radial-chart.d.ts.map +1 -0
- package/dist/radial-chart/radial-chart.js +175 -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 +77 -0
- package/dist/radial-chart/shared.d.ts.map +1 -0
- package/dist/radial-chart/shared.js +78 -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 +263 -179
- package/src/bar-chart/category-axis.ts +46 -40
- package/src/bar-chart/chart-bars.ts +136 -117
- package/src/bar-chart/index.ts +7 -10
- package/src/bar-chart/shared.ts +88 -233
- package/src/engine.ts +5 -2
- package/src/index.ts +2 -0
- package/src/kit/cartesian.ts +121 -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 +353 -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 +353 -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 +54 -35
- package/src/pie-chart/pie-ring.ts +92 -71
- package/src/pie-chart/shared.ts +80 -270
- package/src/radar-chart/index.ts +4 -0
- package/src/radar-chart/radar-chart.ts +290 -0
- package/src/radar-chart/radar-grid.ts +83 -0
- package/src/radar-chart/radar-series.ts +88 -0
- package/src/radar-chart/shared.ts +153 -0
- package/src/radial-chart/index.ts +5 -0
- package/src/radial-chart/radial-chart.ts +212 -0
- package/src/radial-chart/radial-rings.ts +328 -0
- package/src/radial-chart/shared.ts +126 -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,78 @@
|
|
|
1
|
+
import { type TextStyle, type DataRecord, type Size2D, type StrokeResolved, type Stroke as _Stroke, type Vector2 } from "@motionscript/sdk";
|
|
2
|
+
import { type ChartSeries } from "../kit/shared.js";
|
|
3
|
+
/** The radar chart's text: the category names around the rim, and the legend. */
|
|
4
|
+
export declare const RADAR_TEXT: {
|
|
5
|
+
legendText: import("@motionscript/sdk").Type<TextStyle, TextStyle, false>;
|
|
6
|
+
spokeText: import("@motionscript/sdk").Type<TextStyle, TextStyle, false>;
|
|
7
|
+
};
|
|
8
|
+
export type GridShape = "polygon" | "circle";
|
|
9
|
+
/** The radar chart's own grid group: the web the polygons are drawn over. */
|
|
10
|
+
export declare const RADAR_GRID: {
|
|
11
|
+
/** Whether the rings are straight-edged (a polygon through the spokes) or round. */
|
|
12
|
+
gridShape: import("@motionscript/sdk").Type<"circle" | "polygon", "circle" | "polygon", false>;
|
|
13
|
+
/** How many rings, outermost at the scale's maximum. */
|
|
14
|
+
gridLevels: import("@motionscript/sdk").Type<number, number, false>;
|
|
15
|
+
/** The rings; empty draws none. */
|
|
16
|
+
gridStroke: import("@motionscript/sdk").Type<_Stroke, StrokeResolved[], false>;
|
|
17
|
+
/** The line from the centre out to each category; empty draws none. */
|
|
18
|
+
spokeStroke: import("@motionscript/sdk").Type<_Stroke, StrokeResolved[], false>;
|
|
19
|
+
/** Read as the chart is built: whether the category names stand around the rim. */
|
|
20
|
+
spokeLabels: import("@motionscript/sdk").Type<boolean, boolean, false>;
|
|
21
|
+
};
|
|
22
|
+
export declare const RADAR_MARKS: {
|
|
23
|
+
/** Outline weight of each series' polygon. */
|
|
24
|
+
strokeWidth: import("@motionscript/sdk").Type<number, number, false>;
|
|
25
|
+
/** How strongly each polygon is filled in its series colour; 0 leaves an outline. */
|
|
26
|
+
areaOpacity: import("@motionscript/sdk").Type<number, number, false>;
|
|
27
|
+
/** Whether a dot marks each value on its spoke. */
|
|
28
|
+
dots: import("@motionscript/sdk").Type<boolean, boolean, false>;
|
|
29
|
+
dotSize: import("@motionscript/sdk").Type<number, number, false>;
|
|
30
|
+
};
|
|
31
|
+
/** The grid and marks fields the parts read, whichever way the chart's style is spelled. */
|
|
32
|
+
export interface RadarStyle {
|
|
33
|
+
readonly gridShape: GridShape;
|
|
34
|
+
readonly gridLevels: number;
|
|
35
|
+
readonly gridStroke: StrokeResolved[];
|
|
36
|
+
readonly spokeStroke: StrokeResolved[];
|
|
37
|
+
readonly spokeLabels: boolean;
|
|
38
|
+
readonly strokeWidth: number;
|
|
39
|
+
readonly areaOpacity: number;
|
|
40
|
+
readonly dots: boolean;
|
|
41
|
+
readonly dotSize: number;
|
|
42
|
+
readonly spokeText: TextStyle;
|
|
43
|
+
}
|
|
44
|
+
/** Spoke `index` of `count`, as a unit direction: 12 o'clock first, clockwise on screen, y up. */
|
|
45
|
+
export declare function spokeDirection(index: number, count: number): Vector2;
|
|
46
|
+
/** One category per data row. */
|
|
47
|
+
export declare function categoriesOf(data: readonly DataRecord[], field: string): string[];
|
|
48
|
+
/** One list of values per series, a value per row. */
|
|
49
|
+
export declare function valuesOf(data: readonly DataRecord[], series: readonly ChartSeries[]): number[][];
|
|
50
|
+
/** `value` rounded up to a tidy 1, 1.5, 2, 2.5, 3, 4, 5, 6, 8 times a power of ten. */
|
|
51
|
+
export declare function niceCeil(value: number): number;
|
|
52
|
+
/**
|
|
53
|
+
* The scale the web is drawn to: `min` (default 0) to `max`, which when unset
|
|
54
|
+
* (or not above `min`) is the largest value rounded up tidily.
|
|
55
|
+
*/
|
|
56
|
+
export declare function scaleOf(values: readonly (readonly number[])[], min: number, max: number): {
|
|
57
|
+
min: number;
|
|
58
|
+
max: number;
|
|
59
|
+
};
|
|
60
|
+
/** Where `value` stands between the scale's ends, `0`-`1`. */
|
|
61
|
+
export declare function fractionOf(value: number, scale: {
|
|
62
|
+
min: number;
|
|
63
|
+
max: number;
|
|
64
|
+
}): number;
|
|
65
|
+
export type LabelAnchor = "centerLeft" | "centerRight" | "bottomCenter" | "topCenter";
|
|
66
|
+
/** Which corner of a category's label touches the point beside its spoke's end. */
|
|
67
|
+
export declare function labelAnchor(index: number, count: number): LabelAnchor;
|
|
68
|
+
export declare function labelPad(fontSize: number): number;
|
|
69
|
+
/** Rough size of a label, since the web is fitted before any text is measured. */
|
|
70
|
+
export declare function labelSize(caption: string, fontSize: number): Size2D;
|
|
71
|
+
/**
|
|
72
|
+
* The rim's radius for a box: the largest the web can be with every label
|
|
73
|
+
* (when there are labels) still inside it.
|
|
74
|
+
*/
|
|
75
|
+
export declare function fitRadius(box: Size2D, categories: readonly string[], fontSize: number, labelled: boolean): number;
|
|
76
|
+
/** Where spoke `index`'s label is pinned: just past the rim, centre-relative, y up. */
|
|
77
|
+
export declare function labelPoint(index: number, count: number, radius: number, fontSize: number): Vector2;
|
|
78
|
+
//# sourceMappingURL=shared.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"shared.d.ts","sourceRoot":"","sources":["../../src/radar-chart/shared.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,129 @@
|
|
|
1
|
+
import { Types } from "@motionscript/sdk";
|
|
2
|
+
import { num, text } from "../kit/shared.js";
|
|
3
|
+
import { CHART_MUTED, LEGEND_TEXT } from "../kit/style.js";
|
|
4
|
+
/** The radar chart's text: the category names around the rim, and the legend. */
|
|
5
|
+
export const RADAR_TEXT = {
|
|
6
|
+
spokeText: Types.typography({ fontSize: 28, fontWeight: 500, fill: CHART_MUTED }),
|
|
7
|
+
...LEGEND_TEXT,
|
|
8
|
+
};
|
|
9
|
+
/** The radar chart's own grid group: the web the polygons are drawn over. */
|
|
10
|
+
export const RADAR_GRID = {
|
|
11
|
+
/** Whether the rings are straight-edged (a polygon through the spokes) or round. */
|
|
12
|
+
gridShape: Types.oneOf(["polygon", "circle"]),
|
|
13
|
+
/** How many rings, outermost at the scale's maximum. */
|
|
14
|
+
gridLevels: Types.number(4, { min: 1, max: 10, step: 1 }),
|
|
15
|
+
/** The rings; empty draws none. */
|
|
16
|
+
gridStroke: Types.stroke({ weight: 2, fill: "white/15" }),
|
|
17
|
+
/** The line from the centre out to each category; empty draws none. */
|
|
18
|
+
spokeStroke: Types.stroke({ weight: 2, fill: "white/15" }),
|
|
19
|
+
/** Read as the chart is built: whether the category names stand around the rim. */
|
|
20
|
+
spokeLabels: Types.boolean(true, { animatable: false }),
|
|
21
|
+
};
|
|
22
|
+
export const RADAR_MARKS = {
|
|
23
|
+
/** Outline weight of each series' polygon. */
|
|
24
|
+
strokeWidth: Types.number(4, { min: 0, max: 24, step: 1, unit: "px" }),
|
|
25
|
+
/** How strongly each polygon is filled in its series colour; 0 leaves an outline. */
|
|
26
|
+
areaOpacity: Types.number(0.25, { min: 0, max: 1, step: 0.05 }),
|
|
27
|
+
/** Whether a dot marks each value on its spoke. */
|
|
28
|
+
dots: Types.boolean(true),
|
|
29
|
+
dotSize: Types.number(10, { min: 2, max: 40, step: 1, unit: "px" }),
|
|
30
|
+
};
|
|
31
|
+
/** Fraction of the label's font size between the rim and the label. */
|
|
32
|
+
const LABEL_PAD = 0.55;
|
|
33
|
+
/** Glyph width as a fraction of the font size, for fitting labels. */
|
|
34
|
+
const GLYPH = 0.58;
|
|
35
|
+
/** Room kept clear around the web when nothing else claims it, in px. */
|
|
36
|
+
const MARGIN = 10;
|
|
37
|
+
/** Below this a spoke counts as vertical, and its label centres over it. */
|
|
38
|
+
const SIDE = 0.35;
|
|
39
|
+
/** Spoke `index` of `count`, as a unit direction: 12 o'clock first, clockwise on screen, y up. */
|
|
40
|
+
export function spokeDirection(index, count) {
|
|
41
|
+
const angle = (index / Math.max(1, count)) * Math.PI * 2;
|
|
42
|
+
return { x: Math.sin(angle), y: Math.cos(angle) };
|
|
43
|
+
}
|
|
44
|
+
/** One category per data row. */
|
|
45
|
+
export function categoriesOf(data, field) {
|
|
46
|
+
return data.map((row) => text(row, field));
|
|
47
|
+
}
|
|
48
|
+
/** One list of values per series, a value per row. */
|
|
49
|
+
export function valuesOf(data, series) {
|
|
50
|
+
return series.map((s) => data.map((row) => num(row, s.field)));
|
|
51
|
+
}
|
|
52
|
+
const MANTISSAS = [1, 1.2, 1.5, 2, 2.5, 3, 4, 5, 6, 8, 10];
|
|
53
|
+
/** `value` rounded up to a tidy 1, 1.5, 2, 2.5, 3, 4, 5, 6, 8 times a power of ten. */
|
|
54
|
+
export function niceCeil(value) {
|
|
55
|
+
if (!(value > 0))
|
|
56
|
+
return 1;
|
|
57
|
+
const power = 10 ** Math.floor(Math.log10(value));
|
|
58
|
+
const mantissa = value / power;
|
|
59
|
+
const pick = MANTISSAS.find((m) => m >= mantissa - 1e-9) ?? 10;
|
|
60
|
+
return pick * power;
|
|
61
|
+
}
|
|
62
|
+
/**
|
|
63
|
+
* The scale the web is drawn to: `min` (default 0) to `max`, which when unset
|
|
64
|
+
* (or not above `min`) is the largest value rounded up tidily.
|
|
65
|
+
*/
|
|
66
|
+
export function scaleOf(values, min, max) {
|
|
67
|
+
if (max > min)
|
|
68
|
+
return { min, max };
|
|
69
|
+
let top = min;
|
|
70
|
+
for (const list of values)
|
|
71
|
+
for (const v of list)
|
|
72
|
+
top = Math.max(top, v);
|
|
73
|
+
const span = niceCeil(top - min);
|
|
74
|
+
return { min, max: min + span };
|
|
75
|
+
}
|
|
76
|
+
/** Where `value` stands between the scale's ends, `0`-`1`. */
|
|
77
|
+
export function fractionOf(value, scale) {
|
|
78
|
+
const span = scale.max - scale.min;
|
|
79
|
+
if (span <= 0)
|
|
80
|
+
return 0;
|
|
81
|
+
return Math.min(1, Math.max(0, (value - scale.min) / span));
|
|
82
|
+
}
|
|
83
|
+
/** Which corner of a category's label touches the point beside its spoke's end. */
|
|
84
|
+
export function labelAnchor(index, count) {
|
|
85
|
+
const { x, y } = spokeDirection(index, count);
|
|
86
|
+
if (x > SIDE)
|
|
87
|
+
return "centerLeft";
|
|
88
|
+
if (x < -SIDE)
|
|
89
|
+
return "centerRight";
|
|
90
|
+
return y >= 0 ? "bottomCenter" : "topCenter";
|
|
91
|
+
}
|
|
92
|
+
export function labelPad(fontSize) {
|
|
93
|
+
return fontSize * LABEL_PAD;
|
|
94
|
+
}
|
|
95
|
+
/** Rough size of a label, since the web is fitted before any text is measured. */
|
|
96
|
+
export function labelSize(caption, fontSize) {
|
|
97
|
+
return { width: caption.length * fontSize * GLYPH, height: fontSize * 1.25 };
|
|
98
|
+
}
|
|
99
|
+
/**
|
|
100
|
+
* The rim's radius for a box: the largest the web can be with every label
|
|
101
|
+
* (when there are labels) still inside it.
|
|
102
|
+
*/
|
|
103
|
+
export function fitRadius(box, categories, fontSize, labelled) {
|
|
104
|
+
let radius = Math.min(box.width, box.height) / 2 - MARGIN;
|
|
105
|
+
if (!labelled)
|
|
106
|
+
return Math.max(0, radius);
|
|
107
|
+
const pad = labelPad(fontSize);
|
|
108
|
+
const count = categories.length;
|
|
109
|
+
categories.forEach((caption, i) => {
|
|
110
|
+
const { x, y } = spokeDirection(i, count);
|
|
111
|
+
const size = labelSize(caption, fontSize);
|
|
112
|
+
const side = labelAnchor(i, count);
|
|
113
|
+
// How much of the label hangs past its anchor point on each axis.
|
|
114
|
+
const reachX = side === "centerLeft" || side === "centerRight" ? size.width : size.width / 2;
|
|
115
|
+
const reachY = side === "bottomCenter" || side === "topCenter" ? size.height : size.height / 2;
|
|
116
|
+
if (Math.abs(x) > 1e-6)
|
|
117
|
+
radius = Math.min(radius, (box.width / 2 - reachX - MARGIN / 2) / Math.abs(x) - pad);
|
|
118
|
+
if (Math.abs(y) > 1e-6)
|
|
119
|
+
radius = Math.min(radius, (box.height / 2 - reachY - MARGIN / 2) / Math.abs(y) - pad);
|
|
120
|
+
});
|
|
121
|
+
return Math.max(0, radius);
|
|
122
|
+
}
|
|
123
|
+
/** Where spoke `index`'s label is pinned: just past the rim, centre-relative, y up. */
|
|
124
|
+
export function labelPoint(index, count, radius, fontSize) {
|
|
125
|
+
const { x, y } = spokeDirection(index, count);
|
|
126
|
+
const r = radius + labelPad(fontSize);
|
|
127
|
+
return { x: x * r, y: y * r };
|
|
128
|
+
}
|
|
129
|
+
//# sourceMappingURL=shared.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"shared.js","sourceRoot":"","sources":["../../src/radar-chart/shared.ts"],"names":[],"mappings":"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","sourcesContent":["import { Types, type TextStyle, type DataRecord, type Size2D, type StrokeResolved, type Stroke as _Stroke, type Vector2 } from \"@motionscript/sdk\"\n\nimport { num, text, type ChartSeries } from \"../kit/shared\"\nimport { CHART_MUTED, LEGEND_TEXT } from \"../kit/style\"\n\n/** The radar chart's text: the category names around the rim, and the legend. */\nexport const RADAR_TEXT = {\n spokeText: Types.typography({ fontSize: 28, fontWeight: 500, fill: CHART_MUTED }),\n ...LEGEND_TEXT,\n}\n\nexport type GridShape = \"polygon\" | \"circle\"\n\n/** The radar chart's own grid group: the web the polygons are drawn over. */\nexport const RADAR_GRID = {\n /** Whether the rings are straight-edged (a polygon through the spokes) or round. */\n gridShape: Types.oneOf([\"polygon\", \"circle\"] as const),\n /** How many rings, outermost at the scale's maximum. */\n gridLevels: Types.number(4, { min: 1, max: 10, step: 1 }),\n /** The rings; empty draws none. */\n gridStroke: Types.stroke({ weight: 2, fill: \"white/15\" }),\n /** The line from the centre out to each category; empty draws none. */\n spokeStroke: Types.stroke({ weight: 2, fill: \"white/15\" }),\n /** Read as the chart is built: whether the category names stand around the rim. */\n spokeLabels: Types.boolean(true, { animatable: false }),\n}\n\nexport const RADAR_MARKS = {\n /** Outline weight of each series' polygon. */\n strokeWidth: Types.number(4, { min: 0, max: 24, step: 1, unit: \"px\" }),\n /** How strongly each polygon is filled in its series colour; 0 leaves an outline. */\n areaOpacity: Types.number(0.25, { min: 0, max: 1, step: 0.05 }),\n /** Whether a dot marks each value on its spoke. */\n dots: Types.boolean(true),\n dotSize: Types.number(10, { min: 2, max: 40, step: 1, unit: \"px\" }),\n}\n\n/** The grid and marks fields the parts read, whichever way the chart's style is spelled. */\nexport interface RadarStyle {\n readonly gridShape: GridShape\n readonly gridLevels: number\n readonly gridStroke: StrokeResolved[]\n readonly spokeStroke: StrokeResolved[]\n readonly spokeLabels: boolean\n readonly strokeWidth: number\n readonly areaOpacity: number\n readonly dots: boolean\n readonly dotSize: number\n readonly spokeText: TextStyle\n}\n\n/** Fraction of the label's font size between the rim and the label. */\nconst LABEL_PAD = 0.55\n/** Glyph width as a fraction of the font size, for fitting labels. */\nconst GLYPH = 0.58\n/** Room kept clear around the web when nothing else claims it, in px. */\nconst MARGIN = 10\n/** Below this a spoke counts as vertical, and its label centres over it. */\nconst SIDE = 0.35\n\n/** Spoke `index` of `count`, as a unit direction: 12 o'clock first, clockwise on screen, y up. */\nexport function spokeDirection(index: number, count: number): Vector2 {\n const angle = (index / Math.max(1, count)) * Math.PI * 2\n return { x: Math.sin(angle), y: Math.cos(angle) }\n}\n\n/** One category per data row. */\nexport function categoriesOf(data: readonly DataRecord[], field: string): string[] {\n return data.map((row) => text(row, field))\n}\n\n/** One list of values per series, a value per row. */\nexport function valuesOf(data: readonly DataRecord[], series: readonly ChartSeries[]): number[][] {\n return series.map((s) => data.map((row) => num(row, s.field)))\n}\n\nconst MANTISSAS = [1, 1.2, 1.5, 2, 2.5, 3, 4, 5, 6, 8, 10]\n\n/** `value` rounded up to a tidy 1, 1.5, 2, 2.5, 3, 4, 5, 6, 8 times a power of ten. */\nexport function niceCeil(value: number): number {\n if (!(value > 0)) return 1\n const power = 10 ** Math.floor(Math.log10(value))\n const mantissa = value / power\n const pick = MANTISSAS.find((m) => m >= mantissa - 1e-9) ?? 10\n return pick * power\n}\n\n/**\n * The scale the web is drawn to: `min` (default 0) to `max`, which when unset\n * (or not above `min`) is the largest value rounded up tidily.\n */\nexport function scaleOf(values: readonly (readonly number[])[], min: number, max: number): { min: number; max: number } {\n if (max > min) return { min, max }\n let top = min\n for (const list of values) for (const v of list) top = Math.max(top, v)\n const span = niceCeil(top - min)\n return { min, max: min + span }\n}\n\n/** Where `value` stands between the scale's ends, `0`-`1`. */\nexport function fractionOf(value: number, scale: { min: number; max: number }): number {\n const span = scale.max - scale.min\n if (span <= 0) return 0\n return Math.min(1, Math.max(0, (value - scale.min) / span))\n}\n\nexport type LabelAnchor = \"centerLeft\" | \"centerRight\" | \"bottomCenter\" | \"topCenter\"\n\n/** Which corner of a category's label touches the point beside its spoke's end. */\nexport function labelAnchor(index: number, count: number): LabelAnchor {\n const { x, y } = spokeDirection(index, count)\n if (x > SIDE) return \"centerLeft\"\n if (x < -SIDE) return \"centerRight\"\n return y >= 0 ? \"bottomCenter\" : \"topCenter\"\n}\n\nexport function labelPad(fontSize: number): number {\n return fontSize * LABEL_PAD\n}\n\n/** Rough size of a label, since the web is fitted before any text is measured. */\nexport function labelSize(caption: string, fontSize: number): Size2D {\n return { width: caption.length * fontSize * GLYPH, height: fontSize * 1.25 }\n}\n\n/**\n * The rim's radius for a box: the largest the web can be with every label\n * (when there are labels) still inside it.\n */\nexport function fitRadius(box: Size2D, categories: readonly string[], fontSize: number, labelled: boolean): number {\n let radius = Math.min(box.width, box.height) / 2 - MARGIN\n if (!labelled) return Math.max(0, radius)\n const pad = labelPad(fontSize)\n const count = categories.length\n categories.forEach((caption, i) => {\n const { x, y } = spokeDirection(i, count)\n const size = labelSize(caption, fontSize)\n const side = labelAnchor(i, count)\n // How much of the label hangs past its anchor point on each axis.\n const reachX = side === \"centerLeft\" || side === \"centerRight\" ? size.width : size.width / 2\n const reachY = side === \"bottomCenter\" || side === \"topCenter\" ? size.height : size.height / 2\n if (Math.abs(x) > 1e-6) radius = Math.min(radius, (box.width / 2 - reachX - MARGIN / 2) / Math.abs(x) - pad)\n if (Math.abs(y) > 1e-6) radius = Math.min(radius, (box.height / 2 - reachY - MARGIN / 2) / Math.abs(y) - pad)\n })\n return Math.max(0, radius)\n}\n\n/** Where spoke `index`'s label is pinned: just past the rim, centre-relative, y up. */\nexport function labelPoint(index: number, count: number, radius: number, fontSize: number): Vector2 {\n const { x, y } = spokeDirection(index, count)\n const r = radius + labelPad(fontSize)\n return { x: x * r, y: y * r }\n}\n"]}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
export { RadialChart } from "./radial-chart.js";
|
|
2
|
+
export type { RadialChartValues } from "./radial-chart.js";
|
|
3
|
+
export { RadialRings, RadialGeometry, bandPath } from "./radial-rings.js";
|
|
4
|
+
export { RADIAL_STYLE_GROUPS, radialFractions, radialMax, resolveRadialRows, rowValue } from "./shared.js";
|
|
5
|
+
export type { RadialMarks, RadialRow, RadialStyle } from "./shared.js";
|
|
6
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/radial-chart/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAA;AAC5C,YAAY,EAAE,iBAAiB,EAAE,MAAM,gBAAgB,CAAA;AACvD,OAAO,EAAE,WAAW,EAAE,cAAc,EAAE,QAAQ,EAAE,MAAM,gBAAgB,CAAA;AACtE,OAAO,EAAE,mBAAmB,EAAE,eAAe,EAAE,SAAS,EAAE,iBAAiB,EAAE,QAAQ,EAAE,MAAM,UAAU,CAAA;AACvG,YAAY,EAAE,WAAW,EAAE,SAAS,EAAE,WAAW,EAAE,MAAM,UAAU,CAAA"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/radial-chart/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAA;AAE5C,OAAO,EAAE,WAAW,EAAE,cAAc,EAAE,QAAQ,EAAE,MAAM,gBAAgB,CAAA;AACtE,OAAO,EAAE,mBAAmB,EAAE,eAAe,EAAE,SAAS,EAAE,iBAAiB,EAAE,QAAQ,EAAE,MAAM,UAAU,CAAA","sourcesContent":["export { RadialChart } from \"./radial-chart\"\nexport type { RadialChartValues } from \"./radial-chart\"\nexport { RadialRings, RadialGeometry, bandPath } from \"./radial-rings\"\nexport { RADIAL_STYLE_GROUPS, radialFractions, radialMax, resolveRadialRows, rowValue } from \"./shared\"\nexport type { RadialMarks, RadialRow, RadialStyle } from \"./shared\"\n"]}
|
|
@@ -0,0 +1,210 @@
|
|
|
1
|
+
import { type DataRecord, type NodeOf, type Node2D, type Node2DProps as _Node2DProps, type TextStyle as _TextStyle, type Fill as _Fill, type FillResolved as _FillResolved } from "@motionscript/sdk";
|
|
2
|
+
import { type RadialStyle } from "./shared.js";
|
|
3
|
+
export interface RadialChartValues {
|
|
4
|
+
readonly data: DataRecord[];
|
|
5
|
+
readonly categoryField: string;
|
|
6
|
+
readonly valueField: string;
|
|
7
|
+
readonly max: number;
|
|
8
|
+
readonly style: RadialStyle;
|
|
9
|
+
readonly pops: number[];
|
|
10
|
+
}
|
|
11
|
+
/**
|
|
12
|
+
* A radial bar chart: one concentric ring per row, the first row outermost,
|
|
13
|
+
* each an arc from `startAngle` sweeping `value / max` of `sweep` degrees.
|
|
14
|
+
* Rows are the marks and none can be hidden; `selectRing` thickens a ring and
|
|
15
|
+
* dims the rest.
|
|
16
|
+
*/
|
|
17
|
+
export declare const RadialChart: import("@motionscript/sdk").Component<"radialChart", import("@motionscript/sdk").Merge<import("@motionscript/sdk").Box2DState, {
|
|
18
|
+
readonly data: import("@motionscript/sdk").Type<DataRecord[], DataRecord[], false>;
|
|
19
|
+
/** Ring caption, used on the ring labels and the legend. */
|
|
20
|
+
readonly categoryField: "";
|
|
21
|
+
/** Ring magnitude: the arc's share of the full sweep. */
|
|
22
|
+
readonly valueField: "";
|
|
23
|
+
/** The value a full sweep stands for. 0 lets the largest value fill its ring. */
|
|
24
|
+
readonly max: import("@motionscript/sdk").Type<number, number, false>;
|
|
25
|
+
readonly style: import("@motionscript/sdk").Type<import("@motionscript/sdk").StyleInput<{
|
|
26
|
+
background: import("@motionscript/sdk").Type<_Fill, _FillResolved[], false>;
|
|
27
|
+
} & {
|
|
28
|
+
legend: import("@motionscript/sdk").Type<"right" | "top" | "bottom" | "none", "right" | "top" | "bottom" | "none", false>;
|
|
29
|
+
swatch: import("@motionscript/sdk").Type<"square" | "circle" | "line", "square" | "circle" | "line", false>;
|
|
30
|
+
} & {
|
|
31
|
+
legendText: import("@motionscript/sdk").Type<_TextStyle, _TextStyle, false>;
|
|
32
|
+
labelText: import("@motionscript/sdk").Type<_TextStyle, _TextStyle, false>;
|
|
33
|
+
centerText: import("@motionscript/sdk").Type<_TextStyle, _TextStyle, false>;
|
|
34
|
+
} & {
|
|
35
|
+
seriesFills: import("@motionscript/sdk").Type<_Fill[], _FillResolved[][], false>;
|
|
36
|
+
} & {
|
|
37
|
+
innerRadius: import("@motionscript/sdk").Type<number, number, false>;
|
|
38
|
+
ringGap: import("@motionscript/sdk").Type<number, number, false>;
|
|
39
|
+
sweep: import("@motionscript/sdk").Type<number, number, false>;
|
|
40
|
+
startAngle: import("@motionscript/sdk").Type<number, number, false>;
|
|
41
|
+
track: import("@motionscript/sdk").Type<_Fill, _FillResolved[], false>;
|
|
42
|
+
roundCaps: import("@motionscript/sdk").Type<boolean, boolean, false>;
|
|
43
|
+
} & {
|
|
44
|
+
ringLabels: import("@motionscript/sdk").Type<boolean, boolean, false>;
|
|
45
|
+
}>, import("@motionscript/sdk").StyleValues<{
|
|
46
|
+
background: import("@motionscript/sdk").Type<_Fill, _FillResolved[], false>;
|
|
47
|
+
} & {
|
|
48
|
+
legend: import("@motionscript/sdk").Type<"right" | "top" | "bottom" | "none", "right" | "top" | "bottom" | "none", false>;
|
|
49
|
+
swatch: import("@motionscript/sdk").Type<"square" | "circle" | "line", "square" | "circle" | "line", false>;
|
|
50
|
+
} & {
|
|
51
|
+
legendText: import("@motionscript/sdk").Type<_TextStyle, _TextStyle, false>;
|
|
52
|
+
labelText: import("@motionscript/sdk").Type<_TextStyle, _TextStyle, false>;
|
|
53
|
+
centerText: import("@motionscript/sdk").Type<_TextStyle, _TextStyle, false>;
|
|
54
|
+
} & {
|
|
55
|
+
seriesFills: import("@motionscript/sdk").Type<_Fill[], _FillResolved[][], false>;
|
|
56
|
+
} & {
|
|
57
|
+
innerRadius: import("@motionscript/sdk").Type<number, number, false>;
|
|
58
|
+
ringGap: import("@motionscript/sdk").Type<number, number, false>;
|
|
59
|
+
sweep: import("@motionscript/sdk").Type<number, number, false>;
|
|
60
|
+
startAngle: import("@motionscript/sdk").Type<number, number, false>;
|
|
61
|
+
track: import("@motionscript/sdk").Type<_Fill, _FillResolved[], false>;
|
|
62
|
+
roundCaps: import("@motionscript/sdk").Type<boolean, boolean, false>;
|
|
63
|
+
} & {
|
|
64
|
+
ringLabels: import("@motionscript/sdk").Type<boolean, boolean, false>;
|
|
65
|
+
}>, false>;
|
|
66
|
+
/** Gap between the rings and the legend, in px. */
|
|
67
|
+
readonly gap: 40;
|
|
68
|
+
/** Text set in the centre hole. */
|
|
69
|
+
readonly centerLabel: "";
|
|
70
|
+
/** Smaller second line under `centerLabel`. */
|
|
71
|
+
readonly centerCaption: "";
|
|
72
|
+
/** How far each ring is emphasised, `0`-`1` per index. Here because the rings and the legend both read it. */
|
|
73
|
+
readonly pops: import("@motionscript/sdk").Type<number[], number[], false>;
|
|
74
|
+
/** Read as the chart is built: whether the centre summary is drawn at rest. A scene that wants it to land later sets `false` and runs `revealCenter`. */
|
|
75
|
+
readonly showCenter: import("@motionscript/sdk").Type<boolean, boolean, false>;
|
|
76
|
+
}>, {
|
|
77
|
+
readonly enter: {};
|
|
78
|
+
readonly revealCenter: {};
|
|
79
|
+
readonly selectRing: {
|
|
80
|
+
readonly ringIndex: import("@motionscript/sdk").Type<number, number, false>;
|
|
81
|
+
};
|
|
82
|
+
readonly clearSelection: {};
|
|
83
|
+
}, readonly [], Node2D<_Node2DProps>, import("@motionscript/sdk").CallProps<import("@motionscript/sdk").Merge<import("@motionscript/sdk").Box2DState, {
|
|
84
|
+
readonly data: import("@motionscript/sdk").Type<DataRecord[], DataRecord[], false>;
|
|
85
|
+
/** Ring caption, used on the ring labels and the legend. */
|
|
86
|
+
readonly categoryField: "";
|
|
87
|
+
/** Ring magnitude: the arc's share of the full sweep. */
|
|
88
|
+
readonly valueField: "";
|
|
89
|
+
/** The value a full sweep stands for. 0 lets the largest value fill its ring. */
|
|
90
|
+
readonly max: import("@motionscript/sdk").Type<number, number, false>;
|
|
91
|
+
readonly style: import("@motionscript/sdk").Type<import("@motionscript/sdk").StyleInput<{
|
|
92
|
+
background: import("@motionscript/sdk").Type<_Fill, _FillResolved[], false>;
|
|
93
|
+
} & {
|
|
94
|
+
legend: import("@motionscript/sdk").Type<"right" | "top" | "bottom" | "none", "right" | "top" | "bottom" | "none", false>;
|
|
95
|
+
swatch: import("@motionscript/sdk").Type<"square" | "circle" | "line", "square" | "circle" | "line", false>;
|
|
96
|
+
} & {
|
|
97
|
+
legendText: import("@motionscript/sdk").Type<_TextStyle, _TextStyle, false>;
|
|
98
|
+
labelText: import("@motionscript/sdk").Type<_TextStyle, _TextStyle, false>;
|
|
99
|
+
centerText: import("@motionscript/sdk").Type<_TextStyle, _TextStyle, false>;
|
|
100
|
+
} & {
|
|
101
|
+
seriesFills: import("@motionscript/sdk").Type<_Fill[], _FillResolved[][], false>;
|
|
102
|
+
} & {
|
|
103
|
+
innerRadius: import("@motionscript/sdk").Type<number, number, false>;
|
|
104
|
+
ringGap: import("@motionscript/sdk").Type<number, number, false>;
|
|
105
|
+
sweep: import("@motionscript/sdk").Type<number, number, false>;
|
|
106
|
+
startAngle: import("@motionscript/sdk").Type<number, number, false>;
|
|
107
|
+
track: import("@motionscript/sdk").Type<_Fill, _FillResolved[], false>;
|
|
108
|
+
roundCaps: import("@motionscript/sdk").Type<boolean, boolean, false>;
|
|
109
|
+
} & {
|
|
110
|
+
ringLabels: import("@motionscript/sdk").Type<boolean, boolean, false>;
|
|
111
|
+
}>, import("@motionscript/sdk").StyleValues<{
|
|
112
|
+
background: import("@motionscript/sdk").Type<_Fill, _FillResolved[], false>;
|
|
113
|
+
} & {
|
|
114
|
+
legend: import("@motionscript/sdk").Type<"right" | "top" | "bottom" | "none", "right" | "top" | "bottom" | "none", false>;
|
|
115
|
+
swatch: import("@motionscript/sdk").Type<"square" | "circle" | "line", "square" | "circle" | "line", false>;
|
|
116
|
+
} & {
|
|
117
|
+
legendText: import("@motionscript/sdk").Type<_TextStyle, _TextStyle, false>;
|
|
118
|
+
labelText: import("@motionscript/sdk").Type<_TextStyle, _TextStyle, false>;
|
|
119
|
+
centerText: import("@motionscript/sdk").Type<_TextStyle, _TextStyle, false>;
|
|
120
|
+
} & {
|
|
121
|
+
seriesFills: import("@motionscript/sdk").Type<_Fill[], _FillResolved[][], false>;
|
|
122
|
+
} & {
|
|
123
|
+
innerRadius: import("@motionscript/sdk").Type<number, number, false>;
|
|
124
|
+
ringGap: import("@motionscript/sdk").Type<number, number, false>;
|
|
125
|
+
sweep: import("@motionscript/sdk").Type<number, number, false>;
|
|
126
|
+
startAngle: import("@motionscript/sdk").Type<number, number, false>;
|
|
127
|
+
track: import("@motionscript/sdk").Type<_Fill, _FillResolved[], false>;
|
|
128
|
+
roundCaps: import("@motionscript/sdk").Type<boolean, boolean, false>;
|
|
129
|
+
} & {
|
|
130
|
+
ringLabels: import("@motionscript/sdk").Type<boolean, boolean, false>;
|
|
131
|
+
}>, false>;
|
|
132
|
+
/** Gap between the rings and the legend, in px. */
|
|
133
|
+
readonly gap: 40;
|
|
134
|
+
/** Text set in the centre hole. */
|
|
135
|
+
readonly centerLabel: "";
|
|
136
|
+
/** Smaller second line under `centerLabel`. */
|
|
137
|
+
readonly centerCaption: "";
|
|
138
|
+
/** How far each ring is emphasised, `0`-`1` per index. Here because the rings and the legend both read it. */
|
|
139
|
+
readonly pops: import("@motionscript/sdk").Type<number[], number[], false>;
|
|
140
|
+
/** Read as the chart is built: whether the centre summary is drawn at rest. A scene that wants it to land later sets `false` and runs `revealCenter`. */
|
|
141
|
+
readonly showCenter: import("@motionscript/sdk").Type<boolean, boolean, false>;
|
|
142
|
+
}>, readonly [], import("@motionscript/sdk").BuiltNode<import("@motionscript/sdk").Merge<import("@motionscript/sdk").Box2DState, {
|
|
143
|
+
readonly data: import("@motionscript/sdk").Type<DataRecord[], DataRecord[], false>;
|
|
144
|
+
/** Ring caption, used on the ring labels and the legend. */
|
|
145
|
+
readonly categoryField: "";
|
|
146
|
+
/** Ring magnitude: the arc's share of the full sweep. */
|
|
147
|
+
readonly valueField: "";
|
|
148
|
+
/** The value a full sweep stands for. 0 lets the largest value fill its ring. */
|
|
149
|
+
readonly max: import("@motionscript/sdk").Type<number, number, false>;
|
|
150
|
+
readonly style: import("@motionscript/sdk").Type<import("@motionscript/sdk").StyleInput<{
|
|
151
|
+
background: import("@motionscript/sdk").Type<_Fill, _FillResolved[], false>;
|
|
152
|
+
} & {
|
|
153
|
+
legend: import("@motionscript/sdk").Type<"right" | "top" | "bottom" | "none", "right" | "top" | "bottom" | "none", false>;
|
|
154
|
+
swatch: import("@motionscript/sdk").Type<"square" | "circle" | "line", "square" | "circle" | "line", false>;
|
|
155
|
+
} & {
|
|
156
|
+
legendText: import("@motionscript/sdk").Type<_TextStyle, _TextStyle, false>;
|
|
157
|
+
labelText: import("@motionscript/sdk").Type<_TextStyle, _TextStyle, false>;
|
|
158
|
+
centerText: import("@motionscript/sdk").Type<_TextStyle, _TextStyle, false>;
|
|
159
|
+
} & {
|
|
160
|
+
seriesFills: import("@motionscript/sdk").Type<_Fill[], _FillResolved[][], false>;
|
|
161
|
+
} & {
|
|
162
|
+
innerRadius: import("@motionscript/sdk").Type<number, number, false>;
|
|
163
|
+
ringGap: import("@motionscript/sdk").Type<number, number, false>;
|
|
164
|
+
sweep: import("@motionscript/sdk").Type<number, number, false>;
|
|
165
|
+
startAngle: import("@motionscript/sdk").Type<number, number, false>;
|
|
166
|
+
track: import("@motionscript/sdk").Type<_Fill, _FillResolved[], false>;
|
|
167
|
+
roundCaps: import("@motionscript/sdk").Type<boolean, boolean, false>;
|
|
168
|
+
} & {
|
|
169
|
+
ringLabels: import("@motionscript/sdk").Type<boolean, boolean, false>;
|
|
170
|
+
}>, import("@motionscript/sdk").StyleValues<{
|
|
171
|
+
background: import("@motionscript/sdk").Type<_Fill, _FillResolved[], false>;
|
|
172
|
+
} & {
|
|
173
|
+
legend: import("@motionscript/sdk").Type<"right" | "top" | "bottom" | "none", "right" | "top" | "bottom" | "none", false>;
|
|
174
|
+
swatch: import("@motionscript/sdk").Type<"square" | "circle" | "line", "square" | "circle" | "line", false>;
|
|
175
|
+
} & {
|
|
176
|
+
legendText: import("@motionscript/sdk").Type<_TextStyle, _TextStyle, false>;
|
|
177
|
+
labelText: import("@motionscript/sdk").Type<_TextStyle, _TextStyle, false>;
|
|
178
|
+
centerText: import("@motionscript/sdk").Type<_TextStyle, _TextStyle, false>;
|
|
179
|
+
} & {
|
|
180
|
+
seriesFills: import("@motionscript/sdk").Type<_Fill[], _FillResolved[][], false>;
|
|
181
|
+
} & {
|
|
182
|
+
innerRadius: import("@motionscript/sdk").Type<number, number, false>;
|
|
183
|
+
ringGap: import("@motionscript/sdk").Type<number, number, false>;
|
|
184
|
+
sweep: import("@motionscript/sdk").Type<number, number, false>;
|
|
185
|
+
startAngle: import("@motionscript/sdk").Type<number, number, false>;
|
|
186
|
+
track: import("@motionscript/sdk").Type<_Fill, _FillResolved[], false>;
|
|
187
|
+
roundCaps: import("@motionscript/sdk").Type<boolean, boolean, false>;
|
|
188
|
+
} & {
|
|
189
|
+
ringLabels: import("@motionscript/sdk").Type<boolean, boolean, false>;
|
|
190
|
+
}>, false>;
|
|
191
|
+
/** Gap between the rings and the legend, in px. */
|
|
192
|
+
readonly gap: 40;
|
|
193
|
+
/** Text set in the centre hole. */
|
|
194
|
+
readonly centerLabel: "";
|
|
195
|
+
/** Smaller second line under `centerLabel`. */
|
|
196
|
+
readonly centerCaption: "";
|
|
197
|
+
/** How far each ring is emphasised, `0`-`1` per index. Here because the rings and the legend both read it. */
|
|
198
|
+
readonly pops: import("@motionscript/sdk").Type<number[], number[], false>;
|
|
199
|
+
/** Read as the chart is built: whether the centre summary is drawn at rest. A scene that wants it to land later sets `false` and runs `revealCenter`. */
|
|
200
|
+
readonly showCenter: import("@motionscript/sdk").Type<boolean, boolean, false>;
|
|
201
|
+
}>, {
|
|
202
|
+
readonly enter: {};
|
|
203
|
+
readonly revealCenter: {};
|
|
204
|
+
readonly selectRing: {
|
|
205
|
+
readonly ringIndex: import("@motionscript/sdk").Type<number, number, false>;
|
|
206
|
+
};
|
|
207
|
+
readonly clearSelection: {};
|
|
208
|
+
}, Node2D<_Node2DProps>>>>;
|
|
209
|
+
export type RadialChart = NodeOf<typeof RadialChart>;
|
|
210
|
+
//# sourceMappingURL=radial-chart.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"radial-chart.d.ts","sourceRoot":"","sources":["../../src/radial-chart/radial-chart.ts"],"names":[],"mappings":"AAAA,OAAO,EAOL,KAAK,UAAU,EACf,KAAK,MAAM,EAEX,KAAK,MAAM,EACX,KAAK,WAAW,IAAI,YAAY,EAChC,KAAK,SAAS,IAAI,UAAU,EAC5B,KAAK,IAAI,IAAI,KAAK,EAClB,KAAK,YAAY,IAAI,aAAa,EACnC,MAAM,mBAAmB,CAAA;AAQ1B,OAAO,EAQL,KAAK,WAAW,EACjB,MAAM,UAAU,CAAA;AAEjB,MAAM,WAAW,iBAAiB;IAChC,QAAQ,CAAC,IAAI,EAAE,UAAU,EAAE,CAAA;IAC3B,QAAQ,CAAC,aAAa,EAAE,MAAM,CAAA;IAC9B,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAA;IAC3B,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAA;IACpB,QAAQ,CAAC,KAAK,EAAE,WAAW,CAAA;IAC3B,QAAQ,CAAC,IAAI,EAAE,MAAM,EAAE,CAAA;CACxB;AAwCD;;;;;GAKG;AACH,eAAO,MAAM,WAAW;;IAIpB,4DAA4D;;IAE5D,yDAAyD;;IAEzD,iFAAiF;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;IAGjF,mDAAmD;;IAEnD,mCAAmC;;IAEnC,+CAA+C;;IAE/C,8GAA8G;;IAE9G,yJAAyJ;;;;;;;;;;;IAfzJ,4DAA4D;;IAE5D,yDAAyD;;IAEzD,iFAAiF;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;IAGjF,mDAAmD;;IAEnD,mCAAmC;;IAEnC,+CAA+C;;IAE/C,8GAA8G;;IAE9G,yJAAyJ;;;;IAfzJ,4DAA4D;;IAE5D,yDAAyD;;IAEzD,iFAAiF;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;IAGjF,mDAAmD;;IAEnD,mCAAmC;;IAEnC,+CAA+C;;IAE/C,8GAA8G;;IAE9G,yJAAyJ;;;;;;;;;0BAuG3J,CAAA;AAEF,MAAM,MAAM,WAAW,GAAG,MAAM,CAAC,OAAO,WAAW,CAAC,CAAA"}
|