@motionscript/charts 0.1.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 +38 -0
- package/README.md +98 -28
- package/dist/bar-chart/bar-chart.d.ts +242 -119
- package/dist/bar-chart/bar-chart.d.ts.map +1 -1
- package/dist/bar-chart/bar-chart.js +231 -260
- package/dist/bar-chart/bar-chart.js.map +1 -1
- package/dist/bar-chart/category-axis.d.ts +16 -38
- package/dist/bar-chart/category-axis.d.ts.map +1 -1
- package/dist/bar-chart/category-axis.js +59 -68
- package/dist/bar-chart/category-axis.js.map +1 -1
- package/dist/bar-chart/chart-bars.d.ts +60 -91
- package/dist/bar-chart/chart-bars.d.ts.map +1 -1
- package/dist/bar-chart/chart-bars.js +88 -125
- package/dist/bar-chart/chart-bars.js.map +1 -1
- package/dist/bar-chart/index.d.ts +5 -13
- package/dist/bar-chart/index.d.ts.map +1 -1
- package/dist/bar-chart/index.js +2 -9
- package/dist/bar-chart/index.js.map +1 -1
- package/dist/bar-chart/shared.d.ts +40 -132
- package/dist/bar-chart/shared.d.ts.map +1 -1
- package/dist/bar-chart/shared.js +70 -158
- 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 +8 -17
- package/dist/engine.d.ts.map +1 -1
- package/dist/engine.js +8 -17
- 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 -35
- package/dist/kit/cartesian.d.ts.map +1 -1
- package/dist/kit/cartesian.js +80 -42
- package/dist/kit/cartesian.js.map +1 -1
- package/dist/kit/chart-canvas.d.ts +37 -40
- package/dist/kit/chart-canvas.d.ts.map +1 -1
- package/dist/kit/chart-canvas.js +53 -47
- package/dist/kit/chart-canvas.js.map +1 -1
- package/dist/kit/chart-legend.d.ts +16 -59
- package/dist/kit/chart-legend.d.ts.map +1 -1
- package/dist/kit/chart-legend.js +38 -76
- package/dist/kit/chart-legend.js.map +1 -1
- package/dist/kit/entries.d.ts +2 -0
- package/dist/kit/entries.d.ts.map +1 -1
- package/dist/kit/entries.js +2 -0
- package/dist/kit/entries.js.map +1 -1
- package/dist/kit/horizontal-axis.d.ts +77 -0
- package/dist/kit/horizontal-axis.d.ts.map +1 -0
- package/dist/kit/horizontal-axis.js +99 -0
- package/dist/kit/horizontal-axis.js.map +1 -0
- package/dist/kit/motion.d.ts +16 -3
- package/dist/kit/motion.d.ts.map +1 -1
- package/dist/kit/motion.js +15 -1
- package/dist/kit/motion.js.map +1 -1
- package/dist/{pie-chart → kit}/pie-legend.d.ts +14 -29
- package/dist/kit/pie-legend.d.ts.map +1 -0
- package/dist/kit/pie-legend.js +93 -0
- 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 +60 -214
- package/dist/kit/shared.d.ts.map +1 -1
- package/dist/kit/shared.js +91 -291
- 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 +36 -45
- package/dist/kit/vertical-axis.d.ts.map +1 -1
- package/dist/kit/vertical-axis.js +69 -81
- package/dist/kit/vertical-axis.js.map +1 -1
- package/dist/line-chart/chart-line.d.ts +107 -40
- package/dist/line-chart/chart-line.d.ts.map +1 -1
- package/dist/line-chart/chart-line.js +172 -89
- package/dist/line-chart/chart-line.js.map +1 -1
- package/dist/line-chart/chart-region.d.ts +14 -27
- package/dist/line-chart/chart-region.d.ts.map +1 -1
- package/dist/line-chart/chart-region.js +13 -28
- package/dist/line-chart/chart-region.js.map +1 -1
- package/dist/line-chart/index.d.ts +5 -18
- package/dist/line-chart/index.d.ts.map +1 -1
- package/dist/line-chart/index.js +3 -16
- package/dist/line-chart/index.js.map +1 -1
- package/dist/line-chart/line-chart.d.ts +272 -119
- package/dist/line-chart/line-chart.d.ts.map +1 -1
- package/dist/line-chart/line-chart.js +309 -257
- package/dist/line-chart/line-chart.js.map +1 -1
- package/dist/line-chart/shared.d.ts +73 -130
- package/dist/line-chart/shared.d.ts.map +1 -1
- package/dist/line-chart/shared.js +195 -156
- package/dist/line-chart/shared.js.map +1 -1
- package/dist/line-chart/x-scale.d.ts +16 -55
- package/dist/line-chart/x-scale.d.ts.map +1 -1
- package/dist/line-chart/x-scale.js +44 -111
- package/dist/line-chart/x-scale.js.map +1 -1
- package/dist/nodes.d.ts +3 -13
- package/dist/nodes.d.ts.map +1 -1
- package/dist/nodes.js +9 -13
- package/dist/nodes.js.map +1 -1
- package/dist/pie-chart/index.d.ts +3 -15
- package/dist/pie-chart/index.d.ts.map +1 -1
- package/dist/pie-chart/index.js +1 -11
- package/dist/pie-chart/index.js.map +1 -1
- package/dist/pie-chart/pie-chart.d.ts +147 -85
- package/dist/pie-chart/pie-chart.d.ts.map +1 -1
- package/dist/pie-chart/pie-chart.js +65 -86
- package/dist/pie-chart/pie-chart.js.map +1 -1
- package/dist/pie-chart/pie-ring.d.ts +65 -196
- package/dist/pie-chart/pie-ring.d.ts.map +1 -1
- package/dist/pie-chart/pie-ring.js +154 -292
- package/dist/pie-chart/pie-ring.js.map +1 -1
- package/dist/pie-chart/shared.d.ts +78 -172
- package/dist/pie-chart/shared.d.ts.map +1 -1
- package/dist/pie-chart/shared.js +54 -177
- 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 +274 -315
- package/src/bar-chart/category-axis.ts +53 -88
- package/src/bar-chart/chart-bars.ts +108 -205
- package/src/bar-chart/index.ts +8 -19
- package/src/bar-chart/shared.ts +81 -309
- package/src/engine.ts +8 -17
- package/src/index.ts +2 -0
- package/src/kit/cartesian.ts +118 -55
- package/src/kit/chart-canvas.ts +50 -80
- package/src/kit/chart-legend.ts +36 -97
- package/src/kit/entries.ts +4 -1
- package/src/kit/horizontal-axis.ts +114 -0
- package/src/kit/motion.ts +18 -2
- package/src/{pie-chart → kit}/pie-legend.ts +25 -65
- package/src/kit/polar.ts +54 -0
- package/src/kit/shared.ts +104 -487
- package/src/kit/style.ts +257 -0
- package/src/kit/vertical-axis.ts +81 -115
- package/src/line-chart/chart-line.ts +185 -91
- package/src/line-chart/chart-region.ts +14 -31
- package/src/line-chart/index.ts +14 -22
- package/src/line-chart/line-chart.ts +377 -315
- package/src/line-chart/shared.ts +229 -304
- package/src/line-chart/x-scale.ts +44 -121
- package/src/nodes.ts +9 -13
- package/src/pie-chart/index.ts +3 -35
- package/src/pie-chart/pie-chart.ts +83 -134
- package/src/pie-chart/pie-ring.ts +162 -368
- package/src/pie-chart/shared.ts +92 -379
- 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-TJNHLQGV.js +0 -2
- package/dist/browser/chunks/chunk-TJNHLQGV.js.map +0 -7
- package/dist/kit/chart-border.d.ts +0 -27
- package/dist/kit/chart-border.d.ts.map +0 -1
- package/dist/kit/chart-border.js +0 -28
- package/dist/kit/chart-border.js.map +0 -1
- package/dist/line-chart/horizontal-axis.d.ts +0 -79
- package/dist/line-chart/horizontal-axis.d.ts.map +0 -1
- package/dist/line-chart/horizontal-axis.js +0 -129
- 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 +0 -117
- package/dist/pie-chart/pie-legend.js.map +0 -1
- package/src/kit/chart-border.ts +0 -50
- package/src/line-chart/horizontal-axis.ts +0 -151
package/dist/kit/entries.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"entries.js","sourceRoot":"","sources":["../../src/kit/entries.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,
|
|
1
|
+
{"version":3,"file":"entries.js","sourceRoot":"","sources":["../../src/kit/entries.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAA2D,MAAM,mBAAmB,CAAA;AAElG;;;GAGG;AACH,MAAM,UAAU,KAAK,CAAY,IAAa,EAAE,OAAyE;IACvH,yEAAyE;IACzE,OAAO,KAAK,CAAC,MAAM,CAAQ,IAAqB,EAAE,OAAO,CAAC,CAAA;AAC5D,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,OAAO,CAAC,KAAwB;IAC9C,OAAO,KAAsC,CAAA;AAC/C,CAAC;AAED,4FAA4F;AAC5F,MAAM,CAAC,MAAM,UAAU,GAAG,KAAK,CAAC,MAAM,CAAiF,CAAC,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,GAAG,EAAE,CAAC,EAAE,IAAI,EAAE,CAAC,EAAE,CAAC,CAAA","sourcesContent":["import { Types, type Element, type EntryOptions, type Node2D, type Type } from \"@motionscript/sdk\"\n\n/**\n * An entry made fresh for every node: each node gets its own array or box\n * rather than one shared literal, and a host is told no default for it.\n */\nexport function fresh<T, In = T>(make: () => T, options?: { readonly resolve?: (value: In) => T; readonly kind?: string }): Type<In, T> {\n // A function default is a factory: the component calls it once per node.\n return Types.custom<In, T>(make as unknown as In, options)\n}\n\n/**\n * Nodes a `children` builder made with `new`, as the elements it returns. A\n * part built that way can be read in a binding — its own box, or its parent's,\n * which is the component it was built for — where a call would hand back only\n * the element.\n */\nexport function asParts(nodes: readonly Node2D[]): readonly Element[] {\n return nodes as unknown as readonly Element[]\n}\n\n/** The argument every per-series command takes: an index into `series`, offered by name. */\nexport const SERIES_ARG = Types.custom<number, number, EntryOptions & { readonly min: number; readonly step: number }>(0, { kind: \"series\", min: 0, step: 1 })\n"]}
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
import { type NodeOf, type Node2D, type Node2DProps as _Node2DProps } from "@motionscript/sdk";
|
|
2
|
+
import { type Arrival } from "./motion.js";
|
|
3
|
+
import { type AxisConfig, type Range } from "./shared.js";
|
|
4
|
+
/**
|
|
5
|
+
* A row of {@link Text} markers under the plot, the mirror of `VerticalAxis`
|
|
6
|
+
* (bound text and positions, landed resting state). Markers are placed by value
|
|
7
|
+
* across the range, whatever they say: `2026-03` sits three months along, not
|
|
8
|
+
* three slots along, unlike a bar chart's category axis. An end marker may hang
|
|
9
|
+
* past the row by `overhang` px on either side, then is held inside it.
|
|
10
|
+
*/
|
|
11
|
+
export declare const HorizontalAxis: import("@motionscript/sdk").Component<"horizontalAxis", import("@motionscript/sdk").Merge<import("@motionscript/sdk").Box2DState, {
|
|
12
|
+
readonly range: import("@motionscript/sdk").Type<Range, Range, false>;
|
|
13
|
+
/** Tick values in data units. */
|
|
14
|
+
readonly markers: import("@motionscript/sdk").Type<number[], number[], false>;
|
|
15
|
+
/** One caption per marker in its order; a missing one reads as the bare numeric value. */
|
|
16
|
+
readonly captions: import("@motionscript/sdk").Type<string[], string[], false>;
|
|
17
|
+
readonly axis: import("@motionscript/sdk").Type<AxisConfig, AxisConfig, false>;
|
|
18
|
+
/** Caption centred beneath the markers; empty hides it. */
|
|
19
|
+
readonly label: "";
|
|
20
|
+
/** How far past the row's left and right ends a marker may reach, in px. */
|
|
21
|
+
readonly overhang: import("@motionscript/sdk").Type<{
|
|
22
|
+
left: number;
|
|
23
|
+
right: number;
|
|
24
|
+
}, {
|
|
25
|
+
left: number;
|
|
26
|
+
right: number;
|
|
27
|
+
}, false>;
|
|
28
|
+
readonly arrivals: import("@motionscript/sdk").Type<Readonly<Record<string, Arrival>>, Readonly<Record<string, Arrival>>, false>;
|
|
29
|
+
}>, {
|
|
30
|
+
readonly enter: {
|
|
31
|
+
readonly stagger: import("@motionscript/sdk").Type<number | undefined, number | undefined, false>;
|
|
32
|
+
readonly slide: import("@motionscript/sdk").Type<number, number, false>;
|
|
33
|
+
};
|
|
34
|
+
}, null, Node2D<_Node2DProps>, import("@motionscript/sdk").CallProps<import("@motionscript/sdk").Merge<import("@motionscript/sdk").Box2DState, {
|
|
35
|
+
readonly range: import("@motionscript/sdk").Type<Range, Range, false>;
|
|
36
|
+
/** Tick values in data units. */
|
|
37
|
+
readonly markers: import("@motionscript/sdk").Type<number[], number[], false>;
|
|
38
|
+
/** One caption per marker in its order; a missing one reads as the bare numeric value. */
|
|
39
|
+
readonly captions: import("@motionscript/sdk").Type<string[], string[], false>;
|
|
40
|
+
readonly axis: import("@motionscript/sdk").Type<AxisConfig, AxisConfig, false>;
|
|
41
|
+
/** Caption centred beneath the markers; empty hides it. */
|
|
42
|
+
readonly label: "";
|
|
43
|
+
/** How far past the row's left and right ends a marker may reach, in px. */
|
|
44
|
+
readonly overhang: import("@motionscript/sdk").Type<{
|
|
45
|
+
left: number;
|
|
46
|
+
right: number;
|
|
47
|
+
}, {
|
|
48
|
+
left: number;
|
|
49
|
+
right: number;
|
|
50
|
+
}, false>;
|
|
51
|
+
readonly arrivals: import("@motionscript/sdk").Type<Readonly<Record<string, Arrival>>, Readonly<Record<string, Arrival>>, false>;
|
|
52
|
+
}>, null, import("@motionscript/sdk").BuiltNode<import("@motionscript/sdk").Merge<import("@motionscript/sdk").Box2DState, {
|
|
53
|
+
readonly range: import("@motionscript/sdk").Type<Range, Range, false>;
|
|
54
|
+
/** Tick values in data units. */
|
|
55
|
+
readonly markers: import("@motionscript/sdk").Type<number[], number[], false>;
|
|
56
|
+
/** One caption per marker in its order; a missing one reads as the bare numeric value. */
|
|
57
|
+
readonly captions: import("@motionscript/sdk").Type<string[], string[], false>;
|
|
58
|
+
readonly axis: import("@motionscript/sdk").Type<AxisConfig, AxisConfig, false>;
|
|
59
|
+
/** Caption centred beneath the markers; empty hides it. */
|
|
60
|
+
readonly label: "";
|
|
61
|
+
/** How far past the row's left and right ends a marker may reach, in px. */
|
|
62
|
+
readonly overhang: import("@motionscript/sdk").Type<{
|
|
63
|
+
left: number;
|
|
64
|
+
right: number;
|
|
65
|
+
}, {
|
|
66
|
+
left: number;
|
|
67
|
+
right: number;
|
|
68
|
+
}, false>;
|
|
69
|
+
readonly arrivals: import("@motionscript/sdk").Type<Readonly<Record<string, Arrival>>, Readonly<Record<string, Arrival>>, false>;
|
|
70
|
+
}>, {
|
|
71
|
+
readonly enter: {
|
|
72
|
+
readonly stagger: import("@motionscript/sdk").Type<number | undefined, number | undefined, false>;
|
|
73
|
+
readonly slide: import("@motionscript/sdk").Type<number, number, false>;
|
|
74
|
+
};
|
|
75
|
+
}, Node2D<_Node2DProps>>>>;
|
|
76
|
+
export type HorizontalAxis = NodeOf<typeof HorizontalAxis>;
|
|
77
|
+
//# sourceMappingURL=horizontal-axis.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"horizontal-axis.d.ts","sourceRoot":"","sources":["../../src/kit/horizontal-axis.ts"],"names":[],"mappings":"AAAA,OAAO,EAKL,KAAK,MAAM,EAEX,KAAK,MAAM,EACX,KAAK,WAAW,IAAI,YAAY,EACjC,MAAM,mBAAmB,CAAA;AAK1B,OAAO,EAA8D,KAAK,OAAO,EAAE,MAAM,UAAU,CAAA;AACnG,OAAO,EAAkB,KAAK,UAAU,EAAE,KAAK,KAAK,EAAE,MAAM,UAAU,CAAA;AAKtE;;;;;;GAMG;AACH,eAAO,MAAM,cAAc;;IAIvB,iCAAiC;;IAEjC,0FAA0F;;;IAG1F,2DAA2D;;IAE3D,4EAA4E;;cAC7C,MAAM;eAAS,MAAM;;cAArB,MAAM;eAAS,MAAM;;;;;;;;;;IARpD,iCAAiC;;IAEjC,0FAA0F;;;IAG1F,2DAA2D;;IAE3D,4EAA4E;;cAC7C,MAAM;eAAS,MAAM;;cAArB,MAAM;eAAS,MAAM;;;;;IARpD,iCAAiC;;IAEjC,0FAA0F;;;IAG1F,2DAA2D;;IAE3D,4EAA4E;;cAC7C,MAAM;eAAS,MAAM;;cAArB,MAAM;eAAS,MAAM;;;;;;;;0BAwEtD,CAAA;AAEF,MAAM,MAAM,cAAc,GAAG,MAAM,CAAC,OAAO,cAAc,CAAC,CAAA"}
|
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
import { Rect, Text, Types, component2d, } from "@motionscript/sdk";
|
|
2
|
+
import { enterBudget } from "@motionscript/sdk/component";
|
|
3
|
+
import { boundText } from "./cartesian.js";
|
|
4
|
+
import { asParts, fresh } from "./entries.js";
|
|
5
|
+
import { armed, arrival, arrivalOf, arrivalsEntry, beats, frameEase } from "./motion.js";
|
|
6
|
+
import { DEFAULT_X_AXIS } from "./shared.js";
|
|
7
|
+
import { axisPads, markerCaption } from "./vertical-axis.js";
|
|
8
|
+
const SLIDE = 24;
|
|
9
|
+
/**
|
|
10
|
+
* A row of {@link Text} markers under the plot, the mirror of `VerticalAxis`
|
|
11
|
+
* (bound text and positions, landed resting state). Markers are placed by value
|
|
12
|
+
* across the range, whatever they say: `2026-03` sits three months along, not
|
|
13
|
+
* three slots along, unlike a bar chart's category axis. An end marker may hang
|
|
14
|
+
* past the row by `overhang` px on either side, then is held inside it.
|
|
15
|
+
*/
|
|
16
|
+
export const HorizontalAxis = component2d({
|
|
17
|
+
key: "horizontalAxis",
|
|
18
|
+
state: {
|
|
19
|
+
range: fresh(() => [0, 1]),
|
|
20
|
+
/** Tick values in data units. */
|
|
21
|
+
markers: fresh(() => []),
|
|
22
|
+
/** One caption per marker in its order; a missing one reads as the bare numeric value. */
|
|
23
|
+
captions: fresh(() => []),
|
|
24
|
+
axis: Types.custom(DEFAULT_X_AXIS),
|
|
25
|
+
/** Caption centred beneath the markers; empty hides it. */
|
|
26
|
+
label: "",
|
|
27
|
+
/** How far past the row's left and right ends a marker may reach, in px. */
|
|
28
|
+
overhang: Types.custom({ left: 0, right: 0 }),
|
|
29
|
+
arrivals: arrivalsEntry(),
|
|
30
|
+
},
|
|
31
|
+
// A node made of markers would otherwise hug them.
|
|
32
|
+
defaults: { width: "fill", height: "fill" },
|
|
33
|
+
children: (state) => {
|
|
34
|
+
const pads = () => axisPads(state.axis, "top");
|
|
35
|
+
const sorted = () => [...state.markers].sort((a, b) => a - b);
|
|
36
|
+
const fracAt = (value) => {
|
|
37
|
+
if (value === undefined)
|
|
38
|
+
return 0;
|
|
39
|
+
const [min, max] = state.range;
|
|
40
|
+
return max <= min ? 0 : (value - min) / (max - min);
|
|
41
|
+
};
|
|
42
|
+
const markers = state.markers.map((_, i) => {
|
|
43
|
+
const width = () => marker.parent?.layoutBounds.width ?? 0;
|
|
44
|
+
const marker = new Text({
|
|
45
|
+
...boundText(() => state.axis.labelStyle),
|
|
46
|
+
text: () => {
|
|
47
|
+
const value = sorted()[i];
|
|
48
|
+
return value === undefined ? "" : markerCaption(state, value);
|
|
49
|
+
},
|
|
50
|
+
x: () => {
|
|
51
|
+
const w = width();
|
|
52
|
+
const half = marker.layoutBounds.width / 2;
|
|
53
|
+
const centred = (fracAt(sorted()[i]) - 0.5) * w;
|
|
54
|
+
return Math.max(-w / 2 - state.overhang.left + half, Math.min(w / 2 + state.overhang.right - half, centred));
|
|
55
|
+
},
|
|
56
|
+
opacity: () => arrivalOf(state.arrivals, i).opacity,
|
|
57
|
+
y: () => arrivalOf(state.arrivals, i).shift,
|
|
58
|
+
});
|
|
59
|
+
return marker;
|
|
60
|
+
});
|
|
61
|
+
const children = [
|
|
62
|
+
new Rect({ width: "fill", height: "hug", padding: () => ({ top: pads().tick }), children: markers }),
|
|
63
|
+
];
|
|
64
|
+
if (state.label !== "") {
|
|
65
|
+
children.push(new Text({
|
|
66
|
+
...boundText(() => state.axis.titleStyle),
|
|
67
|
+
text: state.label,
|
|
68
|
+
opacity: () => arrivalOf(state.arrivals, "label").opacity,
|
|
69
|
+
y: () => arrivalOf(state.arrivals, "label").shift,
|
|
70
|
+
}));
|
|
71
|
+
}
|
|
72
|
+
return asParts([new Rect({ flow: "vertical", gap: () => pads().title, height: "hug", width: "fill", children })]);
|
|
73
|
+
},
|
|
74
|
+
commands: {
|
|
75
|
+
/** Stagger markers in left to right, then the caption. The duration is the whole entrance ({@link enterBudget}). */
|
|
76
|
+
enter: {
|
|
77
|
+
args: {
|
|
78
|
+
stagger: Types.custom(undefined),
|
|
79
|
+
slide: Types.number(SLIDE),
|
|
80
|
+
},
|
|
81
|
+
run: (timeline, state) => {
|
|
82
|
+
const { stagger, slide } = timeline.args;
|
|
83
|
+
const count = state.markers.length;
|
|
84
|
+
const captioned = state.label !== "";
|
|
85
|
+
const from = { opacity: 0, shift: slide };
|
|
86
|
+
const keys = [...state.markers.keys(), ...(captioned ? ["label"] : [])];
|
|
87
|
+
const arm = timeline.animate(() => ({ arrivals: armed(keys, from) }));
|
|
88
|
+
if (count === 0)
|
|
89
|
+
return arm;
|
|
90
|
+
const { step, per, caption } = enterBudget(timeline.duration, count, captioned, stagger);
|
|
91
|
+
const ease = frameEase(timeline);
|
|
92
|
+
const markers = state.markers.map((_, i) => ({ at: i * step, duration: per, piece: arrival(timeline, i, from, ease) }));
|
|
93
|
+
const label = captioned ? [{ at: (count - 1) * step + per, duration: caption, piece: arrival(timeline, "label", from, ease) }] : [];
|
|
94
|
+
return timeline.together([arm, beats(timeline, [...markers, ...label])]);
|
|
95
|
+
},
|
|
96
|
+
},
|
|
97
|
+
},
|
|
98
|
+
});
|
|
99
|
+
//# sourceMappingURL=horizontal-axis.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"horizontal-axis.js","sourceRoot":"","sources":["../../src/kit/horizontal-axis.ts"],"names":[],"mappings":"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","sourcesContent":["import {\n Rect,\n Text,\n Types,\n component2d,\n type NodeOf,\n // Named so this component's emitted type reaches `Node2D` and its props through the sdk, not core.\n type Node2D,\n type Node2DProps as _Node2DProps,\n} from \"@motionscript/sdk\"\nimport { enterBudget } from \"@motionscript/sdk/component\"\n\nimport { boundText } from \"./cartesian\"\nimport { asParts, fresh } from \"./entries\"\nimport { armed, arrival, arrivalOf, arrivalsEntry, beats, frameEase, type Arrival } from \"./motion\"\nimport { DEFAULT_X_AXIS, type AxisConfig, type Range } from \"./shared\"\nimport { axisPads, markerCaption } from \"./vertical-axis\"\n\nconst SLIDE = 24\n\n/**\n * A row of {@link Text} markers under the plot, the mirror of `VerticalAxis`\n * (bound text and positions, landed resting state). Markers are placed by value\n * across the range, whatever they say: `2026-03` sits three months along, not\n * three slots along, unlike a bar chart's category axis. An end marker may hang\n * past the row by `overhang` px on either side, then is held inside it.\n */\nexport const HorizontalAxis = component2d({\n key: \"horizontalAxis\",\n state: {\n range: fresh<Range>(() => [0, 1]),\n /** Tick values in data units. */\n markers: fresh<number[]>(() => []),\n /** One caption per marker in its order; a missing one reads as the bare numeric value. */\n captions: fresh<string[]>(() => []),\n axis: Types.custom<AxisConfig>(DEFAULT_X_AXIS),\n /** Caption centred beneath the markers; empty hides it. */\n label: \"\",\n /** How far past the row's left and right ends a marker may reach, in px. */\n overhang: Types.custom<{ left: number; right: number }>({ left: 0, right: 0 }),\n arrivals: arrivalsEntry(),\n },\n // A node made of markers would otherwise hug them.\n defaults: { width: \"fill\", height: \"fill\" },\n children: (state) => {\n const pads = () => axisPads(state.axis, \"top\")\n const sorted = () => [...state.markers].sort((a, b) => a - b)\n const fracAt = (value: number | undefined) => {\n if (value === undefined) return 0\n const [min, max] = state.range\n return max <= min ? 0 : (value - min) / (max - min)\n }\n\n const markers = state.markers.map((_, i) => {\n const width = () => (marker.parent as Node2D | null)?.layoutBounds.width ?? 0\n const marker: Node2D = new Text({\n ...boundText(() => state.axis.labelStyle),\n text: () => {\n const value = sorted()[i]\n return value === undefined ? \"\" : markerCaption(state, value)\n },\n x: () => {\n const w = width()\n const half = marker.layoutBounds.width / 2\n const centred = (fracAt(sorted()[i]) - 0.5) * w\n return Math.max(-w / 2 - state.overhang.left + half, Math.min(w / 2 + state.overhang.right - half, centred))\n },\n opacity: () => arrivalOf(state.arrivals, i).opacity,\n y: () => arrivalOf(state.arrivals, i).shift,\n })\n return marker\n })\n\n const children: Node2D[] = [\n new Rect({ width: \"fill\", height: \"hug\", padding: () => ({ top: pads().tick }), children: markers }) as unknown as Node2D,\n ]\n if (state.label !== \"\") {\n children.push(\n new Text({\n ...boundText(() => state.axis.titleStyle),\n text: state.label,\n opacity: () => arrivalOf(state.arrivals, \"label\").opacity,\n y: () => arrivalOf(state.arrivals, \"label\").shift,\n }) as unknown as Node2D\n )\n }\n return asParts([new Rect({ flow: \"vertical\", gap: () => pads().title, height: \"hug\", width: \"fill\", children }) as unknown as Node2D])\n },\n commands: {\n /** Stagger markers in left to right, then the caption. The duration is the whole entrance ({@link enterBudget}). */\n enter: {\n args: {\n stagger: Types.custom<number | undefined>(undefined),\n slide: Types.number(SLIDE),\n },\n run: (timeline, state) => {\n const { stagger, slide } = timeline.args\n const count = state.markers.length\n const captioned = state.label !== \"\"\n const from: Arrival = { opacity: 0, shift: slide }\n const keys = [...state.markers.keys(), ...(captioned ? [\"label\"] : [])]\n const arm = timeline.animate(() => ({ arrivals: armed(keys, from) }))\n if (count === 0) return arm\n const { step, per, caption } = enterBudget(timeline.duration, count, captioned, stagger)\n const ease = frameEase(timeline)\n const markers = state.markers.map((_, i) => ({ at: i * step, duration: per, piece: arrival(timeline, i, from, ease) }))\n const label = captioned ? [{ at: (count - 1) * step + per, duration: caption, piece: arrival(timeline, \"label\", from, ease) }] : []\n return timeline.together([arm, beats(timeline, [...markers, ...label])])\n },\n },\n },\n})\n\nexport type HorizontalAxis = NodeOf<typeof HorizontalAxis>\n"]}
|
package/dist/kit/motion.d.ts
CHANGED
|
@@ -1,6 +1,21 @@
|
|
|
1
1
|
import { type EasingFunction, type Piece, type Timeline } from "@motionscript/sdk";
|
|
2
2
|
/** Any component's timeline: these helpers only build pieces, which every timeline builds alike. */
|
|
3
|
-
type AnyTimeline = Timeline<any, any>;
|
|
3
|
+
export type AnyTimeline = Timeline<any, any>;
|
|
4
|
+
/** How far a legend starts below its slot when `enter` brings it in, in px. */
|
|
5
|
+
export declare const LEGEND_SLIDE = 20;
|
|
6
|
+
/** Where a legend waits before it comes up: below its place, above it, or to its right. */
|
|
7
|
+
export declare function legendAway(at: string): {
|
|
8
|
+
x?: number;
|
|
9
|
+
y?: number;
|
|
10
|
+
};
|
|
11
|
+
/** Marker count when an axis states no ticks. */
|
|
12
|
+
export declare const DEFAULT_MARKERS = 5;
|
|
13
|
+
/** How a cartesian `enter` splits its duration: axes arriving, marks drawing, legend coming up. Sums to 1. */
|
|
14
|
+
export declare const ENTER_SHARE: {
|
|
15
|
+
readonly axes: 0.35;
|
|
16
|
+
readonly marks: 0.5;
|
|
17
|
+
readonly legend: 0.15;
|
|
18
|
+
};
|
|
4
19
|
/**
|
|
5
20
|
* The ease a part's own frames apply to `t`: none when its command was given
|
|
6
21
|
* one, which already eases every frame the command builds, and otherwise the
|
|
@@ -29,7 +44,6 @@ export interface Arrival {
|
|
|
29
44
|
}
|
|
30
45
|
/** Each piece's arrival, by key. An unlisted piece has landed. */
|
|
31
46
|
export type Arrivals = Readonly<Record<string, Arrival>>;
|
|
32
|
-
export declare const LANDED: Arrival;
|
|
33
47
|
/**
|
|
34
48
|
* A part's private record of its pieces' arrivals. A write merges into it, so
|
|
35
49
|
* beats placed apart each write their own piece and leave the others as the
|
|
@@ -44,5 +58,4 @@ export declare function armed(keys: readonly (string | number)[], from: Arrival)
|
|
|
44
58
|
* `{ opacity: 1, [axis]: 0 }`, eased by `ease`.
|
|
45
59
|
*/
|
|
46
60
|
export declare function arrival(timeline: AnyTimeline, key: string | number, from: Arrival, ease: EasingFunction): Piece;
|
|
47
|
-
export {};
|
|
48
61
|
//# sourceMappingURL=motion.d.ts.map
|
package/dist/kit/motion.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"motion.d.ts","sourceRoot":"","sources":["../../src/kit/motion.ts"],"names":[],"mappings":"AAAA,OAAO,EAAkB,KAAK,cAAc,EAAE,KAAK,KAAK,EAAE,KAAK,QAAQ,EAAE,MAAM,mBAAmB,CAAA;AAIlG,oGAAoG;AACpG,
|
|
1
|
+
{"version":3,"file":"motion.d.ts","sourceRoot":"","sources":["../../src/kit/motion.ts"],"names":[],"mappings":"AAAA,OAAO,EAAkB,KAAK,cAAc,EAAE,KAAK,KAAK,EAAE,KAAK,QAAQ,EAAE,MAAM,mBAAmB,CAAA;AAIlG,oGAAoG;AACpG,MAAM,MAAM,WAAW,GAAG,QAAQ,CAAC,GAAG,EAAE,GAAG,CAAC,CAAA;AAE5C,+EAA+E;AAC/E,eAAO,MAAM,YAAY,KAAK,CAAA;AAE9B,2FAA2F;AAC3F,wBAAgB,UAAU,CAAC,EAAE,EAAE,MAAM,GAAG;IAAE,CAAC,CAAC,EAAE,MAAM,CAAC;IAAC,CAAC,CAAC,EAAE,MAAM,CAAA;CAAE,CAIjE;AAED,iDAAiD;AACjD,eAAO,MAAM,eAAe,IAAI,CAAA;AAEhC,8GAA8G;AAC9G,eAAO,MAAM,WAAW;;;;CAAoD,CAAA;AAE5E;;;;GAIG;AACH,wBAAgB,SAAS,CAAC,QAAQ,EAAE;IAAE,QAAQ,CAAC,MAAM,EAAE,cAAc,GAAG,SAAS,CAAA;CAAE,GAAG,cAAc,CAEnG;AAED,8FAA8F;AAC9F,MAAM,WAAW,IAAI;IACnB,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAA;IACnB,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAA;IACzB,QAAQ,CAAC,KAAK,EAAE,KAAK,CAAA;CACtB;AAED;;;;;GAKG;AACH,wBAAgB,KAAK,CAAC,QAAQ,EAAE,WAAW,EAAE,KAAK,EAAE,SAAS,IAAI,EAAE,GAAG,KAAK,CAW1E;AAED,gHAAgH;AAChH,MAAM,WAAW,OAAO;IACtB,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAA;IACxB,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAA;CACvB;AAED,kEAAkE;AAClE,MAAM,MAAM,QAAQ,GAAG,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAAA;AAIxD;;;;GAIG;AACH,wBAAgB,aAAa,kHAE5B;AAED,wBAAgB,SAAS,CAAC,QAAQ,EAAE,QAAQ,EAAE,GAAG,EAAE,MAAM,GAAG,MAAM,GAAG,OAAO,CAE3E;AAED,gFAAgF;AAChF,wBAAgB,KAAK,CAAC,IAAI,EAAE,SAAS,CAAC,MAAM,GAAG,MAAM,CAAC,EAAE,EAAE,IAAI,EAAE,OAAO,GAAG,QAAQ,CAIjF;AAED;;;GAGG;AACH,wBAAgB,OAAO,CAAC,QAAQ,EAAE,WAAW,EAAE,GAAG,EAAE,MAAM,GAAG,MAAM,EAAE,IAAI,EAAE,OAAO,EAAE,IAAI,EAAE,cAAc,GAAG,KAAK,CAY/G"}
|
package/dist/kit/motion.js
CHANGED
|
@@ -1,5 +1,19 @@
|
|
|
1
1
|
import { Types, easeOut } from "@motionscript/sdk";
|
|
2
2
|
const identity = (t) => t;
|
|
3
|
+
/** How far a legend starts below its slot when `enter` brings it in, in px. */
|
|
4
|
+
export const LEGEND_SLIDE = 20;
|
|
5
|
+
/** Where a legend waits before it comes up: below its place, above it, or to its right. */
|
|
6
|
+
export function legendAway(at) {
|
|
7
|
+
if (at === "top")
|
|
8
|
+
return { y: LEGEND_SLIDE };
|
|
9
|
+
if (at === "right")
|
|
10
|
+
return { x: LEGEND_SLIDE };
|
|
11
|
+
return { y: -LEGEND_SLIDE };
|
|
12
|
+
}
|
|
13
|
+
/** Marker count when an axis states no ticks. */
|
|
14
|
+
export const DEFAULT_MARKERS = 5;
|
|
15
|
+
/** How a cartesian `enter` splits its duration: axes arriving, marks drawing, legend coming up. Sums to 1. */
|
|
16
|
+
export const ENTER_SHARE = { axes: 0.35, marks: 0.5, legend: 0.15 };
|
|
3
17
|
/**
|
|
4
18
|
* The ease a part's own frames apply to `t`: none when its command was given
|
|
5
19
|
* one, which already eases every frame the command builds, and otherwise the
|
|
@@ -24,7 +38,7 @@ export function beats(timeline, parts) {
|
|
|
24
38
|
return timeline.sequence([timeline.wait(start), piece, timeline.wait(Math.max(0, total - start - length))]);
|
|
25
39
|
}));
|
|
26
40
|
}
|
|
27
|
-
|
|
41
|
+
const LANDED = { opacity: 1, shift: 0 };
|
|
28
42
|
/**
|
|
29
43
|
* A part's private record of its pieces' arrivals. A write merges into it, so
|
|
30
44
|
* beats placed apart each write their own piece and leave the others as the
|
package/dist/kit/motion.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"motion.js","sourceRoot":"","sources":["../../src/kit/motion.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,OAAO,EAAkD,MAAM,mBAAmB,CAAA;AAElG,MAAM,QAAQ,GAAmB,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAA;AAKzC;;;;GAIG;AACH,MAAM,UAAU,SAAS,CAAC,QAAyD;IACjF,OAAO,QAAQ,CAAC,MAAM,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,OAAO,EAAE,CAAA;AAC/C,CAAC;AASD;;;;;GAKG;AACH,MAAM,UAAU,KAAK,CAAC,QAAqB,EAAE,KAAsB;IACjE,MAAM,KAAK,GAAG,QAAQ,CAAC,QAAQ,CAAA;IAC/B,MAAM,OAAO,GAAG,KAAK,CAAC,MAAM,CAAC,CAAC,GAAG,EAAE,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,GAAG,CAAC,GAAG,EAAE,IAAI,CAAC,EAAE,GAAG,IAAI,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC,CAAA;IACtF,MAAM,CAAC,GAAG,OAAO,GAAG,KAAK,IAAI,OAAO,GAAG,CAAC,CAAC,CAAC,CAAC,KAAK,GAAG,OAAO,CAAC,CAAC,CAAC,CAAC,CAAA;IAC9D,OAAO,QAAQ,CAAC,QAAQ,CACtB,KAAK,CAAC,GAAG,CAAC,CAAC,EAAE,EAAE,EAAE,QAAQ,EAAE,KAAK,EAAE,EAAE,EAAE;QACpC,MAAM,KAAK,GAAG,EAAE,GAAG,CAAC,CAAA;QACpB,MAAM,MAAM,GAAG,QAAQ,GAAG,CAAC,CAAA;QAC3B,OAAO,QAAQ,CAAC,QAAQ,CAAC,CAAC,QAAQ,CAAC,IAAI,CAAC,KAAK,CAAC,EAAE,KAAK,EAAE,QAAQ,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,KAAK,GAAG,KAAK,GAAG,MAAM,CAAC,CAAC,CAAC,CAAC,CAAA;IAC7G,CAAC,CAAC,CACH,CAAA;AACH,CAAC;AAWD,MAAM,
|
|
1
|
+
{"version":3,"file":"motion.js","sourceRoot":"","sources":["../../src/kit/motion.ts"],"names":[],"mappings":"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","sourcesContent":["import { Types, easeOut, type EasingFunction, type Piece, type Timeline } from \"@motionscript/sdk\"\n\nconst identity: EasingFunction = (t) => t\n\n/** Any component's timeline: these helpers only build pieces, which every timeline builds alike. */\nexport type AnyTimeline = Timeline<any, any>\n\n/** How far a legend starts below its slot when `enter` brings it in, in px. */\nexport const LEGEND_SLIDE = 20\n\n/** Where a legend waits before it comes up: below its place, above it, or to its right. */\nexport function legendAway(at: string): { x?: number; y?: number } {\n if (at === \"top\") return { y: LEGEND_SLIDE }\n if (at === \"right\") return { x: LEGEND_SLIDE }\n return { y: -LEGEND_SLIDE }\n}\n\n/** Marker count when an axis states no ticks. */\nexport const DEFAULT_MARKERS = 5\n\n/** How a cartesian `enter` splits its duration: axes arriving, marks drawing, legend coming up. Sums to 1. */\nexport const ENTER_SHARE = { axes: 0.35, marks: 0.5, legend: 0.15 } as const\n\n/**\n * The ease a part's own frames apply to `t`: none when its command was given\n * one, which already eases every frame the command builds, and otherwise the\n * ease-out every chart command defaults to.\n */\nexport function frameEase(timeline: { readonly easing: EasingFunction | undefined }): EasingFunction {\n return timeline.easing ? identity : easeOut()\n}\n\n/** A piece of a command placed at its own time: from `at` seconds, for `duration` seconds. */\nexport interface Beat {\n readonly at: number\n readonly duration: number\n readonly piece: Piece\n}\n\n/**\n * `beats` at their own offsets over the command, each eased on its own and held\n * at its last frame once it is done. A beat ahead of the playhead writes nothing,\n * so whatever stands before it is written by a piece ahead of these. Beats that\n * run past the command are played faster to end with it.\n */\nexport function beats(timeline: AnyTimeline, parts: readonly Beat[]): Piece {\n const total = timeline.duration\n const natural = parts.reduce((end, part) => Math.max(end, part.at + part.duration), 0)\n const k = natural > total && natural > 0 ? total / natural : 1\n return timeline.together(\n parts.map(({ at, duration, piece }) => {\n const start = at * k\n const length = duration * k\n return timeline.sequence([timeline.wait(start), piece, timeline.wait(Math.max(0, total - start - length))])\n })\n )\n}\n\n/** How far one piece of a staggered entrance has come: its opacity, and how far it still sits off its place. */\nexport interface Arrival {\n readonly opacity: number\n readonly shift: number\n}\n\n/** Each piece's arrival, by key. An unlisted piece has landed. */\nexport type Arrivals = Readonly<Record<string, Arrival>>\n\nconst LANDED: Arrival = { opacity: 1, shift: 0 }\n\n/**\n * A part's private record of its pieces' arrivals. A write merges into it, so\n * beats placed apart each write their own piece and leave the others as the\n * frame left them.\n */\nexport function arrivalsEntry() {\n return Types.custom<Arrivals>({}, { private: true, resolve: (next: Arrivals, previous?: Arrivals) => ({ ...previous, ...next }) })\n}\n\nexport function arrivalOf(arrivals: Arrivals, key: string | number): Arrival {\n return arrivals[key] ?? LANDED\n}\n\n/** Every piece in `keys` armed at `from`: the first frame of their entrance. */\nexport function armed(keys: readonly (string | number)[], from: Arrival): Arrivals {\n const record: Record<string, Arrival> = {}\n for (const key of keys) record[key] = from\n return record\n}\n\n/**\n * A piece arriving from `from` over its beat: a part armed at `from` tweened to\n * `{ opacity: 1, [axis]: 0 }`, eased by `ease`.\n */\nexport function arrival(timeline: AnyTimeline, key: string | number, from: Arrival, ease: EasingFunction): Piece {\n return timeline.animate((t) => {\n const e = ease(t)\n return {\n arrivals: {\n [key]: {\n opacity: from.opacity + (LANDED.opacity - from.opacity) * e,\n shift: from.shift + (LANDED.shift - from.shift) * e,\n },\n },\n }\n })\n}\n"]}
|
|
@@ -1,37 +1,18 @@
|
|
|
1
|
-
import { type NodeOf, type
|
|
2
|
-
import { type Arrival } from "
|
|
3
|
-
import { type LegendConfig } from "
|
|
4
|
-
import type { PieSlice } from "./
|
|
5
|
-
export interface PieLegendProps extends RectProps {
|
|
6
|
-
/** One entry per slice, in ring order. */
|
|
7
|
-
slices: PieSlice[];
|
|
8
|
-
/** Padding, caption style, gaps, and swatch geometry — see {@link LegendConfig}. */
|
|
9
|
-
legend: LegendConfig;
|
|
10
|
-
/**
|
|
11
|
-
* Per-slice opacity multiplier, by index — the same signal that dims the ring,
|
|
12
|
-
* so an entry fades in step with the wedge it names. Missing entries read as 1.
|
|
13
|
-
*/
|
|
14
|
-
dims: number[];
|
|
15
|
-
}
|
|
1
|
+
import { type NodeOf, type Alignment as _Alignment, type CornerRadiusResolved as _CornerRadiusResolved, type CornerStyleResolved as _CornerStyleResolved, type Fill as _Fill, type FillResolved as _FillResolved, type FlowMode as _FlowMode, type FlowResolved as _FlowResolved, type GapSize as _GapSize, type Node2D as _Node2D, type Node2DProps as _Node2DProps, type RectCornerRadius as _RectCornerRadius, type RectCornerStyle as _RectCornerStyle, type Shadow as _Shadow, type ShadowResolved as _ShadowResolved, type Stroke as _Stroke, type StrokeResolved as _StrokeResolved, type Vector2 as _Vector2 } from "@motionscript/sdk";
|
|
2
|
+
import { type Arrival } from "./motion.js";
|
|
3
|
+
import { type LegendConfig } from "./shared.js";
|
|
4
|
+
import type { PieSlice } from "./polar.js";
|
|
16
5
|
/**
|
|
17
|
-
* The legend of a {@link PieChart}: a
|
|
18
|
-
*
|
|
19
|
-
*
|
|
20
|
-
*
|
|
21
|
-
* ring rather than beneath the plot — a pie is as tall as it is wide, so the
|
|
22
|
-
* space it leaves over is a vertical strip. It is otherwise the same entry: the
|
|
23
|
-
* swatch carries the colour, the caption reads in the legend's neutral ink, and
|
|
24
|
-
* both take the shared {@link LegendConfig}.
|
|
25
|
-
*
|
|
26
|
-
* There is no show/hide here. A pie's marks are its *rows*, and a row that
|
|
27
|
-
* shouldn't be in the chart shouldn't be in the table — removing one would
|
|
28
|
-
* silently re-cut every other wedge's share, which is a different chart rather
|
|
29
|
-
* than the same chart with something hidden. Selection is what a pie has
|
|
30
|
-
* instead, and it arrives through {@link PieLegendProps.dims}.
|
|
6
|
+
* The legend of a {@link PieChart}: a column (it sits beside the ring, in the
|
|
7
|
+
* vertical strip it leaves) of caption-and-swatch entries, one per slice. No
|
|
8
|
+
* show/hide: removing a row would re-cut every other wedge's share. Selection
|
|
9
|
+
* arrives through `dims`.
|
|
31
10
|
*/
|
|
32
11
|
export declare const PieLegend: import("@motionscript/sdk").Component<"pieLegend", import("@motionscript/sdk").Merge<import("@motionscript/sdk").Box2DState, {
|
|
12
|
+
/** One entry per slice, in ring order. */
|
|
33
13
|
readonly slices: import("@motionscript/sdk").Type<PieSlice[], PieSlice[], false>;
|
|
34
14
|
readonly legend: import("@motionscript/sdk").Type<LegendConfig, LegendConfig, false>;
|
|
15
|
+
/** Per-slice opacity multiplier, the signal that dims the ring, so an entry fades in step with its wedge. Missing reads as 1. */
|
|
35
16
|
readonly dims: import("@motionscript/sdk").Type<number[], number[], false>;
|
|
36
17
|
readonly arrivals: import("@motionscript/sdk").Type<Readonly<Record<string, Arrival>>, Readonly<Record<string, Arrival>>, false>;
|
|
37
18
|
readonly cornerRadius: import("@motionscript/sdk").Attribute<_RectCornerRadius, _CornerRadiusResolved>;
|
|
@@ -60,8 +41,10 @@ export declare const PieLegend: import("@motionscript/sdk").Component<"pieLegend
|
|
|
60
41
|
readonly portion: import("@motionscript/sdk").Type<number, number, false>;
|
|
61
42
|
};
|
|
62
43
|
}, null, _Node2D<_Node2DProps>, import("@motionscript/sdk").CallProps<import("@motionscript/sdk").Merge<import("@motionscript/sdk").Box2DState, {
|
|
44
|
+
/** One entry per slice, in ring order. */
|
|
63
45
|
readonly slices: import("@motionscript/sdk").Type<PieSlice[], PieSlice[], false>;
|
|
64
46
|
readonly legend: import("@motionscript/sdk").Type<LegendConfig, LegendConfig, false>;
|
|
47
|
+
/** Per-slice opacity multiplier, the signal that dims the ring, so an entry fades in step with its wedge. Missing reads as 1. */
|
|
65
48
|
readonly dims: import("@motionscript/sdk").Type<number[], number[], false>;
|
|
66
49
|
readonly arrivals: import("@motionscript/sdk").Type<Readonly<Record<string, Arrival>>, Readonly<Record<string, Arrival>>, false>;
|
|
67
50
|
readonly cornerRadius: import("@motionscript/sdk").Attribute<_RectCornerRadius, _CornerRadiusResolved>;
|
|
@@ -79,8 +62,10 @@ export declare const PieLegend: import("@motionscript/sdk").Component<"pieLegend
|
|
|
79
62
|
readonly start: import("@motionscript/sdk").Type<number, number, false>;
|
|
80
63
|
readonly end: import("@motionscript/sdk").Type<number, number, false>;
|
|
81
64
|
}>, null, import("@motionscript/sdk").BuiltNode<import("@motionscript/sdk").Merge<import("@motionscript/sdk").Box2DState, {
|
|
65
|
+
/** One entry per slice, in ring order. */
|
|
82
66
|
readonly slices: import("@motionscript/sdk").Type<PieSlice[], PieSlice[], false>;
|
|
83
67
|
readonly legend: import("@motionscript/sdk").Type<LegendConfig, LegendConfig, false>;
|
|
68
|
+
/** Per-slice opacity multiplier, the signal that dims the ring, so an entry fades in step with its wedge. Missing reads as 1. */
|
|
84
69
|
readonly dims: import("@motionscript/sdk").Type<number[], number[], false>;
|
|
85
70
|
readonly arrivals: import("@motionscript/sdk").Type<Readonly<Record<string, Arrival>>, Readonly<Record<string, Arrival>>, false>;
|
|
86
71
|
readonly cornerRadius: import("@motionscript/sdk").Attribute<_RectCornerRadius, _CornerRadiusResolved>;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"pie-legend.d.ts","sourceRoot":"","sources":["../../src/kit/pie-legend.ts"],"names":[],"mappings":"AAAA,OAAO,EAUL,KAAK,MAAM,EAEX,KAAK,SAAS,IAAI,UAAU,EAC5B,KAAK,oBAAoB,IAAI,qBAAqB,EAClD,KAAK,mBAAmB,IAAI,oBAAoB,EAChD,KAAK,IAAI,IAAI,KAAK,EAClB,KAAK,YAAY,IAAI,aAAa,EAClC,KAAK,QAAQ,IAAI,SAAS,EAC1B,KAAK,YAAY,IAAI,aAAa,EAClC,KAAK,OAAO,IAAI,QAAQ,EACxB,KAAK,MAAM,IAAI,OAAO,EACtB,KAAK,WAAW,IAAI,YAAY,EAChC,KAAK,gBAAgB,IAAI,iBAAiB,EAC1C,KAAK,eAAe,IAAI,gBAAgB,EACxC,KAAK,MAAM,IAAI,OAAO,EACtB,KAAK,cAAc,IAAI,eAAe,EACtC,KAAK,MAAM,IAAI,OAAO,EACtB,KAAK,cAAc,IAAI,eAAe,EACtC,KAAK,OAAO,IAAI,QAAQ,EACzB,MAAM,mBAAmB,CAAA;AAG1B,OAAO,EAA8D,KAAK,OAAO,EAAE,MAAM,UAAU,CAAA;AACnG,OAAO,EAAkB,KAAK,YAAY,EAAE,MAAM,UAAU,CAAA;AAC5D,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAA;AAIvC;;;;;GAKG;AACH,eAAO,MAAM,SAAS;IAMlB,0CAA0C;;;IAG1C,iIAAiI;;;;;;;;;;;;;;;;;;;;;;;;;;;;;IAHjI,0CAA0C;;;IAG1C,iIAAiI;;;;;;;;;;;;;;;;;;IAHjI,0CAA0C;;;IAG1C,iIAAiI;;;;;;;;;;;;;;;;;;;;;;;;;;;;2BAyEnI,CAAA;AAEF,MAAM,MAAM,SAAS,GAAG,MAAM,CAAC,OAAO,SAAS,CAAC,CAAA"}
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
import { Flow, Paint, Rect, Shapes, Text, Types, clamp, component2d, textOps, } from "@motionscript/sdk";
|
|
2
|
+
import { fresh } from "./entries.js";
|
|
3
|
+
import { armed, arrival, arrivalOf, arrivalsEntry, beats, frameEase } from "./motion.js";
|
|
4
|
+
import { DEFAULT_LEGEND } from "./shared.js";
|
|
5
|
+
const SLIDE = 16;
|
|
6
|
+
/**
|
|
7
|
+
* The legend of a {@link PieChart}: a column (it sits beside the ring, in the
|
|
8
|
+
* vertical strip it leaves) of caption-and-swatch entries, one per slice. No
|
|
9
|
+
* show/hide: removing a row would re-cut every other wedge's share. Selection
|
|
10
|
+
* arrives through `dims`.
|
|
11
|
+
*/
|
|
12
|
+
export const PieLegend = component2d({
|
|
13
|
+
key: "pieLegend",
|
|
14
|
+
state: {
|
|
15
|
+
...Paint.state,
|
|
16
|
+
...Flow.state,
|
|
17
|
+
...Shapes.corners,
|
|
18
|
+
/** One entry per slice, in ring order. */
|
|
19
|
+
slices: fresh(() => []),
|
|
20
|
+
legend: Types.custom(DEFAULT_LEGEND),
|
|
21
|
+
/** Per-slice opacity multiplier, the signal that dims the ring, so an entry fades in step with its wedge. Missing reads as 1. */
|
|
22
|
+
dims: fresh(() => []),
|
|
23
|
+
arrivals: arrivalsEntry(),
|
|
24
|
+
},
|
|
25
|
+
// The flow must be stated: a `Rect` with none lays children out `freeform`, every caption on top of the last.
|
|
26
|
+
defaults: {
|
|
27
|
+
flow: "vertical",
|
|
28
|
+
align: "centerLeft",
|
|
29
|
+
width: "hug",
|
|
30
|
+
height: "hug",
|
|
31
|
+
gap: (state) => state.legend.itemGap / 3,
|
|
32
|
+
padding: (state) => state.legend.padding,
|
|
33
|
+
},
|
|
34
|
+
// The selection dim rides a wrapper, so the entrance animates the entry's own opacity without the two fighting over one value.
|
|
35
|
+
children: (state) => {
|
|
36
|
+
const marker = () => state.legend.markerStyle;
|
|
37
|
+
return state.slices.map((_, index) => Rect({
|
|
38
|
+
width: "hug",
|
|
39
|
+
height: "hug",
|
|
40
|
+
flow: "freeform",
|
|
41
|
+
opacity: () => clamp(state.dims[index] ?? 1, 0, 1),
|
|
42
|
+
children: [
|
|
43
|
+
Rect({
|
|
44
|
+
flow: "horizontal",
|
|
45
|
+
gap: () => Math.round(state.legend.textStyle.fontSize === undefined ? 12 : Number(state.legend.textStyle.fontSize) * 0.4),
|
|
46
|
+
align: "center",
|
|
47
|
+
width: "hug",
|
|
48
|
+
height: "hug",
|
|
49
|
+
opacity: () => arrivalOf(state.arrivals, index).opacity,
|
|
50
|
+
x: () => arrivalOf(state.arrivals, index).shift,
|
|
51
|
+
children: [
|
|
52
|
+
Rect({
|
|
53
|
+
width: () => marker().width,
|
|
54
|
+
height: () => marker().height,
|
|
55
|
+
cornerRadius: () => marker().borderRadius,
|
|
56
|
+
fill: () => state.slices[index]?.fill ?? "white",
|
|
57
|
+
}),
|
|
58
|
+
Text({
|
|
59
|
+
...textOps.styleProps(state.legend.textStyle),
|
|
60
|
+
fill: () => state.legend.textStyle.fill ?? "white",
|
|
61
|
+
fontSize: () => state.legend.textStyle.fontSize ?? 28,
|
|
62
|
+
fontWeight: () => state.legend.textStyle.fontWeight ?? 500,
|
|
63
|
+
text: () => state.slices[index]?.category ?? "",
|
|
64
|
+
}),
|
|
65
|
+
],
|
|
66
|
+
}),
|
|
67
|
+
],
|
|
68
|
+
}));
|
|
69
|
+
},
|
|
70
|
+
commands: {
|
|
71
|
+
...Paint.commands,
|
|
72
|
+
/** Every entry shifted right and transparent: what a chart shows ahead of this legend's beat, since `enter` arms only on its first frame. */
|
|
73
|
+
arm: (timeline, state) => timeline.animate(() => ({ arrivals: armed([...state.slices.keys()], { opacity: 0, shift: SLIDE }) })),
|
|
74
|
+
/** Slide and fade entries in from the right, top to bottom. The duration is the whole entrance, the stagger carved out of it. */
|
|
75
|
+
enter: (timeline, state) => {
|
|
76
|
+
const count = state.slices.length;
|
|
77
|
+
if (count === 0)
|
|
78
|
+
return timeline.wait(timeline.duration);
|
|
79
|
+
const from = { opacity: 0, shift: SLIDE };
|
|
80
|
+
const arm = timeline.animate(() => ({ arrivals: armed([...state.slices.keys()], from) }));
|
|
81
|
+
// Each gap is a fifth of an entry's move, the axes' rhythm, solved from the budget.
|
|
82
|
+
const per = timeline.duration / (1 + Math.max(0, count - 1) / 5);
|
|
83
|
+
const step = per / 5;
|
|
84
|
+
const ease = frameEase(timeline);
|
|
85
|
+
const entries = state.slices.map((_, i) => ({ at: i * step, duration: per, piece: arrival(timeline, i, from, ease) }));
|
|
86
|
+
return timeline.together([arm, beats(timeline, entries)]);
|
|
87
|
+
},
|
|
88
|
+
},
|
|
89
|
+
measure: (measurer, state, children) => Flow.measure(measurer, state, children, Paint.inset(state)),
|
|
90
|
+
layout: (box, state, children) => Flow.layout(box, state, children, Paint.inset(state)),
|
|
91
|
+
render: (ctx, state) => Paint.draw(ctx, state, Shapes.rect(ctx.size, state)),
|
|
92
|
+
});
|
|
93
|
+
//# sourceMappingURL=pie-legend.js.map
|
|
@@ -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"]}
|