@motionscript/charts 0.1.1-alpha.1 → 0.1.1-alpha.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +23 -0
- package/README.md +21 -12
- package/dist/bar-chart/bar-chart.d.ts +113 -81
- package/dist/bar-chart/bar-chart.d.ts.map +1 -1
- package/dist/bar-chart/bar-chart.js +9 -5
- package/dist/bar-chart/bar-chart.js.map +1 -1
- package/dist/bar-chart/chart-bars.d.ts +29 -5
- package/dist/bar-chart/chart-bars.d.ts.map +1 -1
- package/dist/bar-chart/chart-bars.js +33 -8
- package/dist/bar-chart/chart-bars.js.map +1 -1
- package/dist/bar-chart/shared.d.ts +10 -4
- package/dist/bar-chart/shared.d.ts.map +1 -1
- package/dist/bar-chart/shared.js +12 -5
- package/dist/bar-chart/shared.js.map +1 -1
- package/dist/browser/chunks/chunk-FJHNBNPQ.js +2 -0
- package/dist/browser/chunks/chunk-FJHNBNPQ.js.map +7 -0
- package/dist/browser/index.js +1 -1
- package/dist/browser/index.js.map +3 -3
- package/dist/browser/kit.js +1 -1
- package/dist/browser/manifest.json +1 -1
- package/dist/kit/cartesian.d.ts +6 -4
- package/dist/kit/cartesian.d.ts.map +1 -1
- package/dist/kit/cartesian.js +5 -3
- package/dist/kit/cartesian.js.map +1 -1
- package/dist/kit/style.d.ts +344 -76
- package/dist/kit/style.d.ts.map +1 -1
- package/dist/kit/style.js +198 -101
- package/dist/kit/style.js.map +1 -1
- package/dist/line-chart/line-chart.d.ts +97 -73
- package/dist/line-chart/line-chart.d.ts.map +1 -1
- package/dist/line-chart/line-chart.js +9 -7
- package/dist/line-chart/line-chart.js.map +1 -1
- package/dist/line-chart/shared.d.ts +2 -1
- package/dist/line-chart/shared.d.ts.map +1 -1
- package/dist/line-chart/shared.js +2 -0
- package/dist/line-chart/shared.js.map +1 -1
- package/dist/pie-chart/pie-chart.d.ts +43 -49
- package/dist/pie-chart/pie-chart.d.ts.map +1 -1
- package/dist/pie-chart/pie-chart.js +2 -1
- package/dist/pie-chart/pie-chart.js.map +1 -1
- package/dist/pie-chart/shared.d.ts +15 -10
- package/dist/pie-chart/shared.d.ts.map +1 -1
- package/dist/pie-chart/shared.js +18 -20
- package/dist/pie-chart/shared.js.map +1 -1
- package/dist/radar-chart/radar-chart.d.ts +37 -49
- package/dist/radar-chart/radar-chart.d.ts.map +1 -1
- package/dist/radar-chart/radar-chart.js +10 -11
- package/dist/radar-chart/radar-chart.js.map +1 -1
- package/dist/radar-chart/radar-grid.d.ts +7 -1
- package/dist/radar-chart/radar-grid.d.ts.map +1 -1
- package/dist/radar-chart/radar-grid.js +17 -15
- package/dist/radar-chart/radar-grid.js.map +1 -1
- package/dist/radar-chart/shared.d.ts +4 -2
- package/dist/radar-chart/shared.d.ts.map +1 -1
- package/dist/radar-chart/shared.js +3 -0
- package/dist/radar-chart/shared.js.map +1 -1
- package/dist/radial-chart/radial-chart.d.ts +37 -49
- package/dist/radial-chart/radial-chart.d.ts.map +1 -1
- package/dist/radial-chart/radial-chart.js +2 -1
- package/dist/radial-chart/radial-chart.js.map +1 -1
- package/dist/radial-chart/shared.d.ts +13 -11
- package/dist/radial-chart/shared.d.ts.map +1 -1
- package/dist/radial-chart/shared.js +12 -16
- package/dist/radial-chart/shared.js.map +1 -1
- package/package.json +4 -4
- package/src/bar-chart/bar-chart.ts +17 -6
- package/src/bar-chart/chart-bars.ts +48 -9
- package/src/bar-chart/shared.ts +23 -5
- package/src/kit/cartesian.ts +10 -7
- package/src/kit/style.ts +216 -118
- package/src/line-chart/line-chart.ts +14 -8
- package/src/line-chart/shared.ts +3 -1
- package/src/pie-chart/pie-chart.ts +3 -1
- package/src/pie-chart/shared.ts +26 -22
- package/src/radar-chart/radar-chart.ts +14 -13
- package/src/radar-chart/radar-grid.ts +18 -13
- package/src/radar-chart/shared.ts +5 -2
- package/src/radial-chart/radial-chart.ts +3 -1
- package/src/radial-chart/shared.ts +26 -18
- package/dist/browser/chunks/chunk-R3Q5EE6E.js +0 -2
- package/dist/browser/chunks/chunk-R3Q5EE6E.js.map +0 -7
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { type DataRecord, type NodeOf, type Node2D, type Node2DProps as _Node2DProps, type Fill as _Fill, type FillResolved as _FillResolved } from "@motionscript/sdk";
|
|
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
2
|
import { type PieLabelMode, type PieStyle } from "./shared.js";
|
|
3
3
|
export interface PieChartValues {
|
|
4
4
|
readonly data: DataRecord[];
|
|
@@ -25,41 +25,39 @@ export declare const PieChart: import("@motionscript/sdk").Component<"pieChart",
|
|
|
25
25
|
/** Slice magnitude: the wedge's share of the ring. */
|
|
26
26
|
readonly valueField: "";
|
|
27
27
|
readonly style: import("@motionscript/sdk").Type<import("@motionscript/sdk").StyleInput<{
|
|
28
|
+
background: import("@motionscript/sdk").Type<_Fill, _FillResolved[], false>;
|
|
29
|
+
} & {
|
|
28
30
|
legend: import("@motionscript/sdk").Type<"right" | "top" | "bottom" | "none", "right" | "top" | "bottom" | "none", false>;
|
|
29
31
|
swatch: import("@motionscript/sdk").Type<"square" | "circle" | "line", "square" | "circle" | "line", false>;
|
|
32
|
+
legendText: import("@motionscript/sdk").Type<_TextStyle, _TextStyle, false>;
|
|
30
33
|
} & {
|
|
31
|
-
|
|
32
|
-
fontSize: import("@motionscript/sdk").Type<number, number, false>;
|
|
33
|
-
fontWeight: import("@motionscript/sdk").Type<number, number, false>;
|
|
34
|
-
} & {
|
|
35
|
-
palette: import("@motionscript/sdk").Type<_Fill[], _FillResolved[][], false>;
|
|
36
|
-
foreground: import("@motionscript/sdk").Type<_Fill, _FillResolved[], false>;
|
|
37
|
-
muted: import("@motionscript/sdk").Type<_Fill, _FillResolved[], false>;
|
|
38
|
-
background: import("@motionscript/sdk").Type<_Fill, _FillResolved[], false>;
|
|
34
|
+
seriesFills: import("@motionscript/sdk").Type<_Fill[], _FillResolved[][], false>;
|
|
39
35
|
} & {
|
|
40
36
|
innerRadius: import("@motionscript/sdk").Type<number, number, false>;
|
|
41
37
|
sliceGap: import("@motionscript/sdk").Type<number, number, false>;
|
|
42
38
|
sliceRadius: import("@motionscript/sdk").Type<number, number, false>;
|
|
43
39
|
} & {
|
|
44
40
|
labelPlacement: import("@motionscript/sdk").Type<"inside" | "outside" | "none", "inside" | "outside" | "none", false>;
|
|
41
|
+
labelText: import("@motionscript/sdk").Type<_TextStyle, _TextStyle, false>;
|
|
42
|
+
valueText: import("@motionscript/sdk").Type<_TextStyle, _TextStyle, false>;
|
|
43
|
+
centerText: import("@motionscript/sdk").Type<_TextStyle, _TextStyle, false>;
|
|
45
44
|
}>, import("@motionscript/sdk").StyleValues<{
|
|
45
|
+
background: import("@motionscript/sdk").Type<_Fill, _FillResolved[], false>;
|
|
46
|
+
} & {
|
|
46
47
|
legend: import("@motionscript/sdk").Type<"right" | "top" | "bottom" | "none", "right" | "top" | "bottom" | "none", false>;
|
|
47
48
|
swatch: import("@motionscript/sdk").Type<"square" | "circle" | "line", "square" | "circle" | "line", false>;
|
|
49
|
+
legendText: import("@motionscript/sdk").Type<_TextStyle, _TextStyle, false>;
|
|
48
50
|
} & {
|
|
49
|
-
|
|
50
|
-
fontSize: import("@motionscript/sdk").Type<number, number, false>;
|
|
51
|
-
fontWeight: import("@motionscript/sdk").Type<number, number, false>;
|
|
52
|
-
} & {
|
|
53
|
-
palette: import("@motionscript/sdk").Type<_Fill[], _FillResolved[][], false>;
|
|
54
|
-
foreground: import("@motionscript/sdk").Type<_Fill, _FillResolved[], false>;
|
|
55
|
-
muted: import("@motionscript/sdk").Type<_Fill, _FillResolved[], false>;
|
|
56
|
-
background: import("@motionscript/sdk").Type<_Fill, _FillResolved[], false>;
|
|
51
|
+
seriesFills: import("@motionscript/sdk").Type<_Fill[], _FillResolved[][], false>;
|
|
57
52
|
} & {
|
|
58
53
|
innerRadius: import("@motionscript/sdk").Type<number, number, false>;
|
|
59
54
|
sliceGap: import("@motionscript/sdk").Type<number, number, false>;
|
|
60
55
|
sliceRadius: import("@motionscript/sdk").Type<number, number, false>;
|
|
61
56
|
} & {
|
|
62
57
|
labelPlacement: import("@motionscript/sdk").Type<"inside" | "outside" | "none", "inside" | "outside" | "none", false>;
|
|
58
|
+
labelText: import("@motionscript/sdk").Type<_TextStyle, _TextStyle, false>;
|
|
59
|
+
valueText: import("@motionscript/sdk").Type<_TextStyle, _TextStyle, false>;
|
|
60
|
+
centerText: import("@motionscript/sdk").Type<_TextStyle, _TextStyle, false>;
|
|
63
61
|
}>, false>;
|
|
64
62
|
/** What the ring's labels say. */
|
|
65
63
|
readonly labelMode: import("@motionscript/sdk").Type<PieLabelMode, PieLabelMode, false>;
|
|
@@ -93,41 +91,39 @@ export declare const PieChart: import("@motionscript/sdk").Component<"pieChart",
|
|
|
93
91
|
/** Slice magnitude: the wedge's share of the ring. */
|
|
94
92
|
readonly valueField: "";
|
|
95
93
|
readonly style: import("@motionscript/sdk").Type<import("@motionscript/sdk").StyleInput<{
|
|
94
|
+
background: import("@motionscript/sdk").Type<_Fill, _FillResolved[], false>;
|
|
95
|
+
} & {
|
|
96
96
|
legend: import("@motionscript/sdk").Type<"right" | "top" | "bottom" | "none", "right" | "top" | "bottom" | "none", false>;
|
|
97
97
|
swatch: import("@motionscript/sdk").Type<"square" | "circle" | "line", "square" | "circle" | "line", false>;
|
|
98
|
+
legendText: import("@motionscript/sdk").Type<_TextStyle, _TextStyle, false>;
|
|
98
99
|
} & {
|
|
99
|
-
|
|
100
|
-
fontSize: import("@motionscript/sdk").Type<number, number, false>;
|
|
101
|
-
fontWeight: import("@motionscript/sdk").Type<number, number, false>;
|
|
102
|
-
} & {
|
|
103
|
-
palette: import("@motionscript/sdk").Type<_Fill[], _FillResolved[][], false>;
|
|
104
|
-
foreground: import("@motionscript/sdk").Type<_Fill, _FillResolved[], false>;
|
|
105
|
-
muted: import("@motionscript/sdk").Type<_Fill, _FillResolved[], false>;
|
|
106
|
-
background: import("@motionscript/sdk").Type<_Fill, _FillResolved[], false>;
|
|
100
|
+
seriesFills: import("@motionscript/sdk").Type<_Fill[], _FillResolved[][], false>;
|
|
107
101
|
} & {
|
|
108
102
|
innerRadius: import("@motionscript/sdk").Type<number, number, false>;
|
|
109
103
|
sliceGap: import("@motionscript/sdk").Type<number, number, false>;
|
|
110
104
|
sliceRadius: import("@motionscript/sdk").Type<number, number, false>;
|
|
111
105
|
} & {
|
|
112
106
|
labelPlacement: import("@motionscript/sdk").Type<"inside" | "outside" | "none", "inside" | "outside" | "none", false>;
|
|
107
|
+
labelText: import("@motionscript/sdk").Type<_TextStyle, _TextStyle, false>;
|
|
108
|
+
valueText: import("@motionscript/sdk").Type<_TextStyle, _TextStyle, false>;
|
|
109
|
+
centerText: import("@motionscript/sdk").Type<_TextStyle, _TextStyle, false>;
|
|
113
110
|
}>, import("@motionscript/sdk").StyleValues<{
|
|
111
|
+
background: import("@motionscript/sdk").Type<_Fill, _FillResolved[], false>;
|
|
112
|
+
} & {
|
|
114
113
|
legend: import("@motionscript/sdk").Type<"right" | "top" | "bottom" | "none", "right" | "top" | "bottom" | "none", false>;
|
|
115
114
|
swatch: import("@motionscript/sdk").Type<"square" | "circle" | "line", "square" | "circle" | "line", false>;
|
|
115
|
+
legendText: import("@motionscript/sdk").Type<_TextStyle, _TextStyle, false>;
|
|
116
116
|
} & {
|
|
117
|
-
|
|
118
|
-
fontSize: import("@motionscript/sdk").Type<number, number, false>;
|
|
119
|
-
fontWeight: import("@motionscript/sdk").Type<number, number, false>;
|
|
120
|
-
} & {
|
|
121
|
-
palette: import("@motionscript/sdk").Type<_Fill[], _FillResolved[][], false>;
|
|
122
|
-
foreground: import("@motionscript/sdk").Type<_Fill, _FillResolved[], false>;
|
|
123
|
-
muted: import("@motionscript/sdk").Type<_Fill, _FillResolved[], false>;
|
|
124
|
-
background: import("@motionscript/sdk").Type<_Fill, _FillResolved[], false>;
|
|
117
|
+
seriesFills: import("@motionscript/sdk").Type<_Fill[], _FillResolved[][], false>;
|
|
125
118
|
} & {
|
|
126
119
|
innerRadius: import("@motionscript/sdk").Type<number, number, false>;
|
|
127
120
|
sliceGap: import("@motionscript/sdk").Type<number, number, false>;
|
|
128
121
|
sliceRadius: import("@motionscript/sdk").Type<number, number, false>;
|
|
129
122
|
} & {
|
|
130
123
|
labelPlacement: import("@motionscript/sdk").Type<"inside" | "outside" | "none", "inside" | "outside" | "none", false>;
|
|
124
|
+
labelText: import("@motionscript/sdk").Type<_TextStyle, _TextStyle, false>;
|
|
125
|
+
valueText: import("@motionscript/sdk").Type<_TextStyle, _TextStyle, false>;
|
|
126
|
+
centerText: import("@motionscript/sdk").Type<_TextStyle, _TextStyle, false>;
|
|
131
127
|
}>, false>;
|
|
132
128
|
/** What the ring's labels say. */
|
|
133
129
|
readonly labelMode: import("@motionscript/sdk").Type<PieLabelMode, PieLabelMode, false>;
|
|
@@ -148,41 +144,39 @@ export declare const PieChart: import("@motionscript/sdk").Component<"pieChart",
|
|
|
148
144
|
/** Slice magnitude: the wedge's share of the ring. */
|
|
149
145
|
readonly valueField: "";
|
|
150
146
|
readonly style: import("@motionscript/sdk").Type<import("@motionscript/sdk").StyleInput<{
|
|
147
|
+
background: import("@motionscript/sdk").Type<_Fill, _FillResolved[], false>;
|
|
148
|
+
} & {
|
|
151
149
|
legend: import("@motionscript/sdk").Type<"right" | "top" | "bottom" | "none", "right" | "top" | "bottom" | "none", false>;
|
|
152
150
|
swatch: import("@motionscript/sdk").Type<"square" | "circle" | "line", "square" | "circle" | "line", false>;
|
|
151
|
+
legendText: import("@motionscript/sdk").Type<_TextStyle, _TextStyle, false>;
|
|
153
152
|
} & {
|
|
154
|
-
|
|
155
|
-
fontSize: import("@motionscript/sdk").Type<number, number, false>;
|
|
156
|
-
fontWeight: import("@motionscript/sdk").Type<number, number, false>;
|
|
157
|
-
} & {
|
|
158
|
-
palette: import("@motionscript/sdk").Type<_Fill[], _FillResolved[][], false>;
|
|
159
|
-
foreground: import("@motionscript/sdk").Type<_Fill, _FillResolved[], false>;
|
|
160
|
-
muted: import("@motionscript/sdk").Type<_Fill, _FillResolved[], false>;
|
|
161
|
-
background: import("@motionscript/sdk").Type<_Fill, _FillResolved[], false>;
|
|
153
|
+
seriesFills: import("@motionscript/sdk").Type<_Fill[], _FillResolved[][], false>;
|
|
162
154
|
} & {
|
|
163
155
|
innerRadius: import("@motionscript/sdk").Type<number, number, false>;
|
|
164
156
|
sliceGap: import("@motionscript/sdk").Type<number, number, false>;
|
|
165
157
|
sliceRadius: import("@motionscript/sdk").Type<number, number, false>;
|
|
166
158
|
} & {
|
|
167
159
|
labelPlacement: import("@motionscript/sdk").Type<"inside" | "outside" | "none", "inside" | "outside" | "none", false>;
|
|
160
|
+
labelText: import("@motionscript/sdk").Type<_TextStyle, _TextStyle, false>;
|
|
161
|
+
valueText: import("@motionscript/sdk").Type<_TextStyle, _TextStyle, false>;
|
|
162
|
+
centerText: import("@motionscript/sdk").Type<_TextStyle, _TextStyle, false>;
|
|
168
163
|
}>, import("@motionscript/sdk").StyleValues<{
|
|
164
|
+
background: import("@motionscript/sdk").Type<_Fill, _FillResolved[], false>;
|
|
165
|
+
} & {
|
|
169
166
|
legend: import("@motionscript/sdk").Type<"right" | "top" | "bottom" | "none", "right" | "top" | "bottom" | "none", false>;
|
|
170
167
|
swatch: import("@motionscript/sdk").Type<"square" | "circle" | "line", "square" | "circle" | "line", false>;
|
|
168
|
+
legendText: import("@motionscript/sdk").Type<_TextStyle, _TextStyle, false>;
|
|
171
169
|
} & {
|
|
172
|
-
|
|
173
|
-
fontSize: import("@motionscript/sdk").Type<number, number, false>;
|
|
174
|
-
fontWeight: import("@motionscript/sdk").Type<number, number, false>;
|
|
175
|
-
} & {
|
|
176
|
-
palette: import("@motionscript/sdk").Type<_Fill[], _FillResolved[][], false>;
|
|
177
|
-
foreground: import("@motionscript/sdk").Type<_Fill, _FillResolved[], false>;
|
|
178
|
-
muted: import("@motionscript/sdk").Type<_Fill, _FillResolved[], false>;
|
|
179
|
-
background: import("@motionscript/sdk").Type<_Fill, _FillResolved[], false>;
|
|
170
|
+
seriesFills: import("@motionscript/sdk").Type<_Fill[], _FillResolved[][], false>;
|
|
180
171
|
} & {
|
|
181
172
|
innerRadius: import("@motionscript/sdk").Type<number, number, false>;
|
|
182
173
|
sliceGap: import("@motionscript/sdk").Type<number, number, false>;
|
|
183
174
|
sliceRadius: import("@motionscript/sdk").Type<number, number, false>;
|
|
184
175
|
} & {
|
|
185
176
|
labelPlacement: import("@motionscript/sdk").Type<"inside" | "outside" | "none", "inside" | "outside" | "none", false>;
|
|
177
|
+
labelText: import("@motionscript/sdk").Type<_TextStyle, _TextStyle, false>;
|
|
178
|
+
valueText: import("@motionscript/sdk").Type<_TextStyle, _TextStyle, false>;
|
|
179
|
+
centerText: import("@motionscript/sdk").Type<_TextStyle, _TextStyle, false>;
|
|
186
180
|
}>, false>;
|
|
187
181
|
/** What the ring's labels say. */
|
|
188
182
|
readonly labelMode: import("@motionscript/sdk").Type<PieLabelMode, PieLabelMode, false>;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"pie-chart.d.ts","sourceRoot":"","sources":["../../src/pie-chart/pie-chart.ts"],"names":[],"mappings":"AAAA,OAAO,EAOL,KAAK,UAAU,EACf,KAAK,MAAM,EAEX,KAAK,MAAM,EACX,KAAK,WAAW,IAAI,YAAY,EAChC,KAAK,IAAI,IAAI,KAAK,EAClB,KAAK,YAAY,IAAI,aAAa,EACnC,MAAM,mBAAmB,CAAA;AAO1B,OAAO,EASL,KAAK,YAAY,EAEjB,KAAK,QAAQ,EACd,MAAM,UAAU,CAAA;AAEjB,MAAM,WAAW,cAAc;IAC7B,QAAQ,CAAC,IAAI,EAAE,UAAU,EAAE,CAAA;IAC3B,QAAQ,CAAC,aAAa,EAAE,MAAM,CAAA;IAC9B,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAA;IAC3B,QAAQ,CAAC,KAAK,EAAE,QAAQ,CAAA;IACxB,QAAQ,CAAC,IAAI,EAAE,MAAM,EAAE,CAAA;CACxB;AAqBD,2FAA2F;AAC3F,wBAAgB,eAAe,CAAC,CAAC,EAAE,cAAc,EAAE,KAAK,EAAE,MAAM,GAAG,OAAO,CAEzE;AA2BD;;;;;;;;GAQG;AACH,eAAO,MAAM,QAAQ;;IAIjB,wDAAwD;;IAExD,sDAAsD
|
|
1
|
+
{"version":3,"file":"pie-chart.d.ts","sourceRoot":"","sources":["../../src/pie-chart/pie-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;AAO1B,OAAO,EASL,KAAK,YAAY,EAEjB,KAAK,QAAQ,EACd,MAAM,UAAU,CAAA;AAEjB,MAAM,WAAW,cAAc;IAC7B,QAAQ,CAAC,IAAI,EAAE,UAAU,EAAE,CAAA;IAC3B,QAAQ,CAAC,aAAa,EAAE,MAAM,CAAA;IAC9B,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAA;IAC3B,QAAQ,CAAC,KAAK,EAAE,QAAQ,CAAA;IACxB,QAAQ,CAAC,IAAI,EAAE,MAAM,EAAE,CAAA;CACxB;AAqBD,2FAA2F;AAC3F,wBAAgB,eAAe,CAAC,CAAC,EAAE,cAAc,EAAE,KAAK,EAAE,MAAM,GAAG,OAAO,CAEzE;AA2BD;;;;;;;;GAQG;AACH,eAAO,MAAM,QAAQ;;IAIjB,wDAAwD;;IAExD,sDAAsD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;IAGtD,kCAAkC;;IAElC,kDAAkD;;IAElD,mCAAmC;;IAEnC,+CAA+C;;IAE/C,kIAAkI;;IAElI,yJAAyJ;;;;;;;;;;;;;;;;;IAfzJ,wDAAwD;;IAExD,sDAAsD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;IAGtD,kCAAkC;;IAElC,kDAAkD;;IAElD,mCAAmC;;IAEnC,+CAA+C;;IAE/C,kIAAkI;;IAElI,yJAAyJ;;;;IAfzJ,wDAAwD;;IAExD,sDAAsD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;IAGtD,kCAAkC;;IAElC,kDAAkD;;IAElD,mCAAmC;;IAEnC,+CAA+C;;IAE/C,kIAAkI;;IAElI,yJAAyJ;;;;;;;;;;;;;;;0BA2H3J,CAAA;AAEF,MAAM,MAAM,QAAQ,GAAG,MAAM,CAAC,OAAO,QAAQ,CAAC,CAAA"}
|
|
@@ -3,7 +3,7 @@ import { asParts, fresh } from "../kit/entries.js";
|
|
|
3
3
|
import { beats } from "../kit/motion.js";
|
|
4
4
|
import { PieLegend } from "../kit/pie-legend.js";
|
|
5
5
|
import { PieRing } from "./pie-ring.js";
|
|
6
|
-
import { CHART_STYLE_FAMILY, CHART_STYLE_PRESETS, paletteFill } from "../kit/style.js";
|
|
6
|
+
import { CHART_STYLE_FAMILY, CHART_STYLE_PRESETS, migrateChartStyle, paletteFill } from "../kit/style.js";
|
|
7
7
|
import { PIE_SPOTLIGHT_DIM, PIE_STYLE_GROUPS, centerConfigOf, labelConfigOf, legendOf, resolvePieSlices, ringConfigOf, selectionFade, } from "./shared.js";
|
|
8
8
|
/** How `enter` divides its duration: wedges sweeping in, then labels and legend together. Sums to 1. */
|
|
9
9
|
const SWEEP_SHARE = 0.65;
|
|
@@ -81,6 +81,7 @@ export const PieChart = component2d({
|
|
|
81
81
|
height: "fill",
|
|
82
82
|
pops: (state) => slicesOf(state).map(() => 0),
|
|
83
83
|
},
|
|
84
|
+
migrate: { style: migrateChartStyle("pie") },
|
|
84
85
|
allowedChildren: [],
|
|
85
86
|
// The structure (a label and legend row per row) is read once; slices, paint and selection are bound, so a theme tween re-paints and a `set` of `data` re-cuts.
|
|
86
87
|
children: (state) => {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"pie-chart.js","sourceRoot":"","sources":["../../src/pie-chart/pie-chart.ts"],"names":[],"mappings":"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","sourcesContent":["import {\n Rect,\n Types,\n clamp,\n component2d,\n easeOut,\n type ChildView,\n type DataRecord,\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 type Fill as _Fill,\n type FillResolved as _FillResolved,\n} from \"@motionscript/sdk\"\n\nimport { asParts, fresh } from \"../kit/entries\"\nimport { beats, type AnyTimeline, type Beat } from \"../kit/motion\"\nimport { PieLegend } from \"../kit/pie-legend\"\nimport { PieRing } from \"./pie-ring\"\nimport { CHART_STYLE_FAMILY, CHART_STYLE_PRESETS, paletteFill } from \"../kit/style\"\nimport {\n PIE_SPOTLIGHT_DIM,\n PIE_STYLE_GROUPS,\n centerConfigOf,\n labelConfigOf,\n legendOf,\n resolvePieSlices,\n ringConfigOf,\n selectionFade,\n type PieLabelMode,\n type PieSlice,\n type PieStyle,\n} from \"./shared\"\n\nexport interface PieChartValues {\n readonly data: DataRecord[]\n readonly categoryField: string\n readonly valueField: string\n readonly style: PieStyle\n readonly pops: number[]\n}\n\n/** How `enter` divides its duration: wedges sweeping in, then labels and legend together. Sums to 1. */\nconst SWEEP_SHARE = 0.65\nconst LABEL_SHARE = 0.35\n\nconst SLICE_ARG = Types.number(0, { min: 0, step: 1 })\n\nfunction slicesOf(s: PieChartValues): PieSlice[] {\n return resolvePieSlices(\n s.data,\n s.categoryField,\n s.valueField,\n s.data.map((_, i) => paletteFill(s.style, i))\n )\n}\n\nfunction popAt(s: PieChartValues, index: number): number {\n return clamp(s.pops[index] ?? 0, 0, 1)\n}\n\n/** Whether slice `index` is past half way out, so a slice mid-swell is not yet counted. */\nexport function isSliceSelected(s: PieChartValues, index: number): boolean {\n return popAt(s, index) > 0.5\n}\n\n/** Per-slice opacity: 1 while nothing is out and for the selected slice, falling toward `dimOpacity` for the rest as the selection grows. */\nfunction sliceDims(s: PieChartValues): number[] {\n let focus = 0\n for (let i = 0; i < s.data.length; i++) focus = Math.max(focus, popAt(s, i))\n return s.data.map((_, i) => selectionFade(focus, PIE_SPOTLIGHT_DIM, popAt(s, i)))\n}\n\n/** Every slice's pop eased to what `pop` asks for. A move that changes nothing still takes its slot. */\nfunction popping(timeline: AnyTimeline, s: PieChartValues, pop: (index: number) => number) {\n const from = s.data.map((_, i) => popAt(s, i))\n const targets = s.data.map((_, i) => clamp(pop(i), 0, 1))\n if (from.every((value, i) => value === targets[i])) return timeline.wait(timeline.duration)\n return timeline.animate((t) => ({ pops: from.map((value, i) => value + (targets[i] - value) * t) }))\n}\n\n/** The ring and legend among the children; the last row is the one the chart built. */\nfunction partsOf(children: readonly ChildView[]) {\n for (let i = children.length - 1; i >= 0; i--) {\n const row = children[i]\n const ring = Rect.is(row) ? row.children.find(PieRing.is) : undefined\n if (ring) return { ring, legend: row.children.find(PieLegend.is) ?? null }\n }\n return null\n}\n\n/**\n * A pie or donut chart: a {@link PieRing} filling what the hugging {@link PieLegend}\n * leaves. One mark per row, not per column, and nothing to hide, since dropping\n * a slice would re-cut every other wedge; `selectSlice` and its siblings swell\n * a slice and dim the rest instead.\n *\n * Resting state is the finished chart, except the hole's summary, which\n * `showCenter: false` holds back for `revealCenter`.\n */\nexport const PieChart = component2d({\n key: \"pieChart\",\n state: {\n data: fresh<DataRecord[]>(() => [], { kind: \"dataset\" }),\n /** Slice caption, used on the labels and the legend. */\n categoryField: \"\",\n /** Slice magnitude: the wedge's share of the ring. */\n valueField: \"\",\n style: Types.style(CHART_STYLE_FAMILY, PIE_STYLE_GROUPS, { presets: CHART_STYLE_PRESETS }),\n /** What the ring's labels say. */\n labelMode: Types.custom<PieLabelMode>(\"percent\"),\n /** Gap between the ring and the legend, in px. */\n gap: 40,\n /** Text set in the ring's hole. */\n centerLabel: \"\",\n /** Smaller second line under `centerLabel`. */\n centerCaption: \"\",\n /** How far each slice is pushed out, `0`-`1` per index. Here, not on the ring, because the wedges and the legend both read it. */\n pops: fresh<number[]>(() => []),\n /** Read as the chart is built: whether the hole's summary is drawn at rest. A scene that wants it to land later sets `false` and runs `revealCenter`. */\n showCenter: Types.boolean(true, { animatable: false }),\n },\n defaults: {\n // A node made of parts that fill would otherwise hug them.\n width: \"fill\",\n height: \"fill\",\n pops: (state) => slicesOf(state).map(() => 0),\n },\n allowedChildren: [],\n // The structure (a label and legend row per row) is read once; slices, paint and selection are bound, so a theme tween re-paints and a `set` of `data` re-cuts.\n children: (state) => {\n const style = () => state.style\n const slices = () => slicesOf(state)\n const parts: Node2D[] = [\n new PieRing({\n width: \"fill\",\n height: \"fill\",\n slices,\n ring: () => ringConfigOf(style()),\n label: () => labelConfigOf(style()),\n centerStyle: () => centerConfigOf(style()),\n labelMode: state.labelMode,\n labelPlacement: state.style.labelPlacement,\n pops: () => state.pops,\n dimOpacity: PIE_SPOTLIGHT_DIM,\n centerLabel: state.centerLabel,\n centerCaption: state.centerCaption,\n centerReveal: state.showCenter === false ? 0 : 1,\n }) as unknown as Node2D,\n ]\n const position = state.style.legend\n if (position !== \"none\") {\n const side = position === \"right\"\n const legend = new PieLegend({\n slices,\n legend: () => legendOf(style()),\n dims: () => sliceDims(state),\n flow: side ? \"vertical\" : \"horizontal\",\n align: \"center\",\n // Spacing is fixed as built.\n gap: side ? legendOf(state.style).itemGap / 3 : legendOf(state.style).itemGap,\n padding: 0,\n }) as unknown as Node2D\n if (position === \"top\") parts.unshift(legend)\n else parts.push(legend)\n }\n const row = new Rect({\n flow: position === \"right\" || position === \"none\" ? \"horizontal\" : \"vertical\",\n width: \"fill\",\n height: \"fill\",\n gap: state.gap,\n padding: 24,\n align: \"center\",\n fill: () => state.style.background,\n children: parts,\n })\n return asParts([row as unknown as Node2D])\n },\n commands: {\n /** Wedges sweep in clockwise from `startAngle`, then labels fade up and the legend staggers in. `duration` is the whole entrance; the hole's summary keeps its own signal. */\n enter: {\n args: {},\n // Held from arrival, so it never shows finished ahead of its draw.\n entrance: true,\n easing: easeOut(),\n run: (timeline, _state, children) => {\n const parts = partsOf(children)\n if (!parts) return timeline.wait(timeline.duration)\n const { ring, legend } = parts\n const sweep = timeline.duration * SWEEP_SHARE\n const labels = timeline.duration * LABEL_SHARE\n const at0 = (piece: Beat[\"piece\"]): Beat => ({ at: 0, duration: 0, piece })\n return beats(timeline, [\n at0(ring.to({ growth: 0, labelReveal: 0 })),\n ...(legend ? [at0(legend.run(\"arm\"))] : []),\n { at: 0, duration: sweep, piece: ring.run(\"sweep\") },\n { at: sweep, duration: labels, piece: ring.run(\"revealLabels\") },\n ...(legend ? [{ at: sweep, duration: labels, piece: legend.run(\"enter\") }] : []),\n ])\n },\n },\n /** Fade the hole's summary up. Not part of `enter`: it is usually the conclusion, which a scene lands on its own beat. */\n revealCenter: {\n args: {},\n easing: easeOut(),\n run: (timeline, _state, children) => partsOf(children)?.ring.run(\"revealCenter\") ?? timeline.wait(timeline.duration),\n },\n /** Grow slice `index` out past the ring's rim and dim the rest, leaving any other selected slice where it is. */\n selectSlice: {\n args: { sliceIndex: SLICE_ARG },\n easing: easeOut(),\n run: (timeline, state) => {\n const index = timeline.args.sliceIndex\n return popping(timeline, state, (i) => (i === index ? 1 : popAt(state, i)))\n },\n },\n /** Settle slice `index` back flush with the ring. */\n deselectSlice: {\n args: { sliceIndex: SLICE_ARG },\n easing: easeOut(),\n run: (timeline, state) => {\n const index = timeline.args.sliceIndex\n return popping(timeline, state, (i) => (i === index ? 0 : popAt(state, i)))\n },\n },\n /** Move the focus to slice `index` alone, settling whatever else was out. */\n selectOnlySlice: {\n args: { sliceIndex: SLICE_ARG },\n easing: easeOut(),\n run: (timeline, state) => {\n const index = timeline.args.sliceIndex\n return popping(timeline, state, (i) => (i === index ? 1 : 0))\n },\n },\n /** Settle every slice flush and bring the whole chart back to full. */\n clearSelection: {\n args: {},\n easing: easeOut(),\n run: (timeline, state) => popping(timeline, state, () => 0),\n },\n },\n})\n\nexport type PieChart = NodeOf<typeof PieChart>\n"]}
|
|
1
|
+
{"version":3,"file":"pie-chart.js","sourceRoot":"","sources":["../../src/pie-chart/pie-chart.ts"],"names":[],"mappings":"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","sourcesContent":["import {\n Rect,\n Types,\n clamp,\n component2d,\n easeOut,\n type ChildView,\n type DataRecord,\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 type TextStyle as _TextStyle,\n type Fill as _Fill,\n type FillResolved as _FillResolved,\n} from \"@motionscript/sdk\"\n\nimport { asParts, fresh } from \"../kit/entries\"\nimport { beats, type AnyTimeline, type Beat } from \"../kit/motion\"\nimport { PieLegend } from \"../kit/pie-legend\"\nimport { PieRing } from \"./pie-ring\"\nimport { CHART_STYLE_FAMILY, CHART_STYLE_PRESETS, migrateChartStyle, paletteFill } from \"../kit/style\"\nimport {\n PIE_SPOTLIGHT_DIM,\n PIE_STYLE_GROUPS,\n centerConfigOf,\n labelConfigOf,\n legendOf,\n resolvePieSlices,\n ringConfigOf,\n selectionFade,\n type PieLabelMode,\n type PieSlice,\n type PieStyle,\n} from \"./shared\"\n\nexport interface PieChartValues {\n readonly data: DataRecord[]\n readonly categoryField: string\n readonly valueField: string\n readonly style: PieStyle\n readonly pops: number[]\n}\n\n/** How `enter` divides its duration: wedges sweeping in, then labels and legend together. Sums to 1. */\nconst SWEEP_SHARE = 0.65\nconst LABEL_SHARE = 0.35\n\nconst SLICE_ARG = Types.number(0, { min: 0, step: 1 })\n\nfunction slicesOf(s: PieChartValues): PieSlice[] {\n return resolvePieSlices(\n s.data,\n s.categoryField,\n s.valueField,\n s.data.map((_, i) => paletteFill(s.style, i))\n )\n}\n\nfunction popAt(s: PieChartValues, index: number): number {\n return clamp(s.pops[index] ?? 0, 0, 1)\n}\n\n/** Whether slice `index` is past half way out, so a slice mid-swell is not yet counted. */\nexport function isSliceSelected(s: PieChartValues, index: number): boolean {\n return popAt(s, index) > 0.5\n}\n\n/** Per-slice opacity: 1 while nothing is out and for the selected slice, falling toward `dimOpacity` for the rest as the selection grows. */\nfunction sliceDims(s: PieChartValues): number[] {\n let focus = 0\n for (let i = 0; i < s.data.length; i++) focus = Math.max(focus, popAt(s, i))\n return s.data.map((_, i) => selectionFade(focus, PIE_SPOTLIGHT_DIM, popAt(s, i)))\n}\n\n/** Every slice's pop eased to what `pop` asks for. A move that changes nothing still takes its slot. */\nfunction popping(timeline: AnyTimeline, s: PieChartValues, pop: (index: number) => number) {\n const from = s.data.map((_, i) => popAt(s, i))\n const targets = s.data.map((_, i) => clamp(pop(i), 0, 1))\n if (from.every((value, i) => value === targets[i])) return timeline.wait(timeline.duration)\n return timeline.animate((t) => ({ pops: from.map((value, i) => value + (targets[i] - value) * t) }))\n}\n\n/** The ring and legend among the children; the last row is the one the chart built. */\nfunction partsOf(children: readonly ChildView[]) {\n for (let i = children.length - 1; i >= 0; i--) {\n const row = children[i]\n const ring = Rect.is(row) ? row.children.find(PieRing.is) : undefined\n if (ring) return { ring, legend: row.children.find(PieLegend.is) ?? null }\n }\n return null\n}\n\n/**\n * A pie or donut chart: a {@link PieRing} filling what the hugging {@link PieLegend}\n * leaves. One mark per row, not per column, and nothing to hide, since dropping\n * a slice would re-cut every other wedge; `selectSlice` and its siblings swell\n * a slice and dim the rest instead.\n *\n * Resting state is the finished chart, except the hole's summary, which\n * `showCenter: false` holds back for `revealCenter`.\n */\nexport const PieChart = component2d({\n key: \"pieChart\",\n state: {\n data: fresh<DataRecord[]>(() => [], { kind: \"dataset\" }),\n /** Slice caption, used on the labels and the legend. */\n categoryField: \"\",\n /** Slice magnitude: the wedge's share of the ring. */\n valueField: \"\",\n style: Types.style(CHART_STYLE_FAMILY, PIE_STYLE_GROUPS, { presets: CHART_STYLE_PRESETS }),\n /** What the ring's labels say. */\n labelMode: Types.custom<PieLabelMode>(\"percent\"),\n /** Gap between the ring and the legend, in px. */\n gap: 40,\n /** Text set in the ring's hole. */\n centerLabel: \"\",\n /** Smaller second line under `centerLabel`. */\n centerCaption: \"\",\n /** How far each slice is pushed out, `0`-`1` per index. Here, not on the ring, because the wedges and the legend both read it. */\n pops: fresh<number[]>(() => []),\n /** Read as the chart is built: whether the hole's summary is drawn at rest. A scene that wants it to land later sets `false` and runs `revealCenter`. */\n showCenter: Types.boolean(true, { animatable: false }),\n },\n defaults: {\n // A node made of parts that fill would otherwise hug them.\n width: \"fill\",\n height: \"fill\",\n pops: (state) => slicesOf(state).map(() => 0),\n },\n migrate: { style: migrateChartStyle(\"pie\") },\n allowedChildren: [],\n // The structure (a label and legend row per row) is read once; slices, paint and selection are bound, so a theme tween re-paints and a `set` of `data` re-cuts.\n children: (state) => {\n const style = () => state.style\n const slices = () => slicesOf(state)\n const parts: Node2D[] = [\n new PieRing({\n width: \"fill\",\n height: \"fill\",\n slices,\n ring: () => ringConfigOf(style()),\n label: () => labelConfigOf(style()),\n centerStyle: () => centerConfigOf(style()),\n labelMode: state.labelMode,\n labelPlacement: state.style.labelPlacement,\n pops: () => state.pops,\n dimOpacity: PIE_SPOTLIGHT_DIM,\n centerLabel: state.centerLabel,\n centerCaption: state.centerCaption,\n centerReveal: state.showCenter === false ? 0 : 1,\n }) as unknown as Node2D,\n ]\n const position = state.style.legend\n if (position !== \"none\") {\n const side = position === \"right\"\n const legend = new PieLegend({\n slices,\n legend: () => legendOf(style()),\n dims: () => sliceDims(state),\n flow: side ? \"vertical\" : \"horizontal\",\n align: \"center\",\n // Spacing is fixed as built.\n gap: side ? legendOf(state.style).itemGap / 3 : legendOf(state.style).itemGap,\n padding: 0,\n }) as unknown as Node2D\n if (position === \"top\") parts.unshift(legend)\n else parts.push(legend)\n }\n const row = new Rect({\n flow: position === \"right\" || position === \"none\" ? \"horizontal\" : \"vertical\",\n width: \"fill\",\n height: \"fill\",\n gap: state.gap,\n padding: 24,\n align: \"center\",\n fill: () => state.style.background,\n children: parts,\n })\n return asParts([row as unknown as Node2D])\n },\n commands: {\n /** Wedges sweep in clockwise from `startAngle`, then labels fade up and the legend staggers in. `duration` is the whole entrance; the hole's summary keeps its own signal. */\n enter: {\n args: {},\n // Held from arrival, so it never shows finished ahead of its draw.\n entrance: true,\n easing: easeOut(),\n run: (timeline, _state, children) => {\n const parts = partsOf(children)\n if (!parts) return timeline.wait(timeline.duration)\n const { ring, legend } = parts\n const sweep = timeline.duration * SWEEP_SHARE\n const labels = timeline.duration * LABEL_SHARE\n const at0 = (piece: Beat[\"piece\"]): Beat => ({ at: 0, duration: 0, piece })\n return beats(timeline, [\n at0(ring.to({ growth: 0, labelReveal: 0 })),\n ...(legend ? [at0(legend.run(\"arm\"))] : []),\n { at: 0, duration: sweep, piece: ring.run(\"sweep\") },\n { at: sweep, duration: labels, piece: ring.run(\"revealLabels\") },\n ...(legend ? [{ at: sweep, duration: labels, piece: legend.run(\"enter\") }] : []),\n ])\n },\n },\n /** Fade the hole's summary up. Not part of `enter`: it is usually the conclusion, which a scene lands on its own beat. */\n revealCenter: {\n args: {},\n easing: easeOut(),\n run: (timeline, _state, children) => partsOf(children)?.ring.run(\"revealCenter\") ?? timeline.wait(timeline.duration),\n },\n /** Grow slice `index` out past the ring's rim and dim the rest, leaving any other selected slice where it is. */\n selectSlice: {\n args: { sliceIndex: SLICE_ARG },\n easing: easeOut(),\n run: (timeline, state) => {\n const index = timeline.args.sliceIndex\n return popping(timeline, state, (i) => (i === index ? 1 : popAt(state, i)))\n },\n },\n /** Settle slice `index` back flush with the ring. */\n deselectSlice: {\n args: { sliceIndex: SLICE_ARG },\n easing: easeOut(),\n run: (timeline, state) => {\n const index = timeline.args.sliceIndex\n return popping(timeline, state, (i) => (i === index ? 0 : popAt(state, i)))\n },\n },\n /** Move the focus to slice `index` alone, settling whatever else was out. */\n selectOnlySlice: {\n args: { sliceIndex: SLICE_ARG },\n easing: easeOut(),\n run: (timeline, state) => {\n const index = timeline.args.sliceIndex\n return popping(timeline, state, (i) => (i === index ? 1 : 0))\n },\n },\n /** Settle every slice flush and bring the whole chart back to full. */\n clearSelection: {\n args: {},\n easing: easeOut(),\n run: (timeline, state) => popping(timeline, state, () => 0),\n },\n },\n})\n\nexport type PieChart = NodeOf<typeof PieChart>\n"]}
|
|
@@ -4,7 +4,7 @@ import { type LegendConfig } from "../kit/shared.js";
|
|
|
4
4
|
import { DEG, PIE_SPOTLIGHT_DIM, ringPoint, selectionFade, type CenterConfig, type PieSlice } from "../kit/polar.js";
|
|
5
5
|
export { DEG, PIE_SPOTLIGHT_DIM, ringPoint, selectionFade, type CenterConfig, type PieSlice };
|
|
6
6
|
/**
|
|
7
|
-
* One slice per row, painted from `
|
|
7
|
+
* One slice per row, painted from `seriesFills` by row order (cycling). Paint comes
|
|
8
8
|
* from the palette, not the rows, because a pie's mark is a row where a line's
|
|
9
9
|
* colour belongs to a column; that lets a pie be fed a CSV of plain numbers.
|
|
10
10
|
*/
|
|
@@ -80,6 +80,9 @@ export interface LabelConfig {
|
|
|
80
80
|
}
|
|
81
81
|
/** What a pie's `style` resolves to. */
|
|
82
82
|
export interface PieStyle extends ChartStyleBase {
|
|
83
|
+
readonly labelText: TextStyle;
|
|
84
|
+
readonly valueText: TextStyle;
|
|
85
|
+
readonly centerText: TextStyle;
|
|
83
86
|
readonly innerRadius: number;
|
|
84
87
|
readonly sliceGap: number;
|
|
85
88
|
readonly sliceRadius: number;
|
|
@@ -87,16 +90,11 @@ export interface PieStyle extends ChartStyleBase {
|
|
|
87
90
|
}
|
|
88
91
|
/** The groups of a pie's `style`: no grid, as nothing is ruled. */
|
|
89
92
|
export declare const PIE_STYLE_GROUPS: {
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
foreground: import("@motionscript/sdk").Type<Fill, _FillResolved[], false>;
|
|
93
|
-
muted: import("@motionscript/sdk").Type<Fill, _FillResolved[], false>;
|
|
94
|
-
background: import("@motionscript/sdk").Type<Fill, _FillResolved[], false>;
|
|
93
|
+
series: {
|
|
94
|
+
seriesFills: import("@motionscript/sdk").Type<Fill[], _FillResolved[][], false>;
|
|
95
95
|
};
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
fontSize: import("@motionscript/sdk").Type<number, number, false>;
|
|
99
|
-
fontWeight: import("@motionscript/sdk").Type<number, number, false>;
|
|
96
|
+
background: {
|
|
97
|
+
background: import("@motionscript/sdk").Type<Fill, _FillResolved[], false>;
|
|
100
98
|
};
|
|
101
99
|
marks: {
|
|
102
100
|
/** Hole radius as a fraction of the outer radius: 0 is a pie, about 0.6 a donut. */
|
|
@@ -109,10 +107,17 @@ export declare const PIE_STYLE_GROUPS: {
|
|
|
109
107
|
labels: {
|
|
110
108
|
/** Read as the chart is built: inside the wedge, outside on a leader, or none. */
|
|
111
109
|
labelPlacement: import("@motionscript/sdk").Type<"inside" | "outside" | "none", "inside" | "outside" | "none", false>;
|
|
110
|
+
/** Each slice's name. */
|
|
111
|
+
labelText: import("@motionscript/sdk").Type<TextStyle, TextStyle, false>;
|
|
112
|
+
/** Each slice's share or value, beside its name; inside a wedge both are set larger, inked for contrast. */
|
|
113
|
+
valueText: import("@motionscript/sdk").Type<TextStyle, TextStyle, false>;
|
|
114
|
+
/** The summary in the hole; its caption is set smaller, in the slice names' ink. */
|
|
115
|
+
centerText: import("@motionscript/sdk").Type<TextStyle, TextStyle, false>;
|
|
112
116
|
};
|
|
113
117
|
legend: {
|
|
114
118
|
legend: import("@motionscript/sdk").Type<"right" | "top" | "bottom" | "none", "right" | "top" | "bottom" | "none", false>;
|
|
115
119
|
swatch: import("@motionscript/sdk").Type<"square" | "circle" | "line", "square" | "circle" | "line", false>;
|
|
120
|
+
legendText: import("@motionscript/sdk").Type<TextStyle, TextStyle, false>;
|
|
116
121
|
};
|
|
117
122
|
};
|
|
118
123
|
export declare function legendOf(style: PieStyle): LegendConfig;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"shared.d.ts","sourceRoot":"","sources":["../../src/pie-chart/shared.ts"],"names":[],"mappings":"AAAA,OAAO,EAAS,KAAK,IAAI,EAAE,KAAK,SAAS,EAAE,KAAK,MAAM,EAAE,KAAK,YAAY,IAAI,aAAa,EAAE,MAAM,mBAAmB,CAAA;AAErH,OAAO,
|
|
1
|
+
{"version":3,"file":"shared.d.ts","sourceRoot":"","sources":["../../src/pie-chart/shared.ts"],"names":[],"mappings":"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"}
|
package/dist/pie-chart/shared.js
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
import { Types } from "@motionscript/sdk";
|
|
2
|
-
import {
|
|
2
|
+
import { CHART_BACKGROUND, CHART_FOREGROUND, CHART_LEGEND, CHART_MUTED, CHART_SERIES, legendConfigOf, placedText, sizeOf, } from "../kit/style.js";
|
|
3
3
|
import { num, text } from "../kit/shared.js";
|
|
4
4
|
import { DEG, PIE_SPOTLIGHT_DIM, ringPoint, selectionFade } from "../kit/polar.js";
|
|
5
5
|
export { DEG, PIE_SPOTLIGHT_DIM, ringPoint, selectionFade };
|
|
6
6
|
/**
|
|
7
|
-
* One slice per row, painted from `
|
|
7
|
+
* One slice per row, painted from `seriesFills` by row order (cycling). Paint comes
|
|
8
8
|
* from the palette, not the rows, because a pie's mark is a row where a line's
|
|
9
9
|
* colour belongs to a column; that lets a pie be fed a CSV of plain numbers.
|
|
10
10
|
*/
|
|
@@ -73,8 +73,8 @@ export function relaxLabels(slots, minGap, top, bottom) {
|
|
|
73
73
|
}
|
|
74
74
|
/** The groups of a pie's `style`: no grid, as nothing is ruled. */
|
|
75
75
|
export const PIE_STYLE_GROUPS = {
|
|
76
|
-
|
|
77
|
-
|
|
76
|
+
series: CHART_SERIES,
|
|
77
|
+
background: CHART_BACKGROUND,
|
|
78
78
|
marks: {
|
|
79
79
|
/** Hole radius as a fraction of the outer radius: 0 is a pie, about 0.6 a donut. */
|
|
80
80
|
innerRadius: Types.number(0, { min: 0, max: 0.9, step: 0.05 }),
|
|
@@ -86,38 +86,36 @@ export const PIE_STYLE_GROUPS = {
|
|
|
86
86
|
labels: {
|
|
87
87
|
/** Read as the chart is built: inside the wedge, outside on a leader, or none. */
|
|
88
88
|
labelPlacement: Types.oneOf(["inside", "outside", "none"], { animatable: false }),
|
|
89
|
+
/** Each slice's name. */
|
|
90
|
+
labelText: Types.typography({ fontSize: 28, fontWeight: 500, fill: CHART_MUTED }),
|
|
91
|
+
/** Each slice's share or value, beside its name; inside a wedge both are set larger, inked for contrast. */
|
|
92
|
+
valueText: Types.typography({ fontSize: 28, fontWeight: 700, fill: CHART_FOREGROUND }),
|
|
93
|
+
/** The summary in the hole; its caption is set smaller, in the slice names' ink. */
|
|
94
|
+
centerText: Types.typography({ fontSize: 50, fontWeight: 800, fill: CHART_FOREGROUND }),
|
|
89
95
|
},
|
|
90
96
|
legend: CHART_LEGEND,
|
|
91
97
|
};
|
|
92
98
|
export function legendOf(style) {
|
|
93
99
|
return legendConfigOf(style);
|
|
94
100
|
}
|
|
95
|
-
function face(style) {
|
|
96
|
-
return style.fontFamily ? { fontFamily: style.fontFamily } : {};
|
|
97
|
-
}
|
|
98
101
|
export function ringConfigOf(style) {
|
|
99
102
|
return { gap: style.sliceGap, holeRadius: style.innerRadius, startAngle: 0, selectedGrow: 1.08, cornerRadius: style.sliceRadius };
|
|
100
103
|
}
|
|
101
104
|
export function labelConfigOf(style) {
|
|
102
|
-
const base =
|
|
103
|
-
const
|
|
105
|
+
const base = placedText(style.labelText);
|
|
106
|
+
const value = placedText(style.valueText);
|
|
104
107
|
return {
|
|
105
108
|
textStyle: base,
|
|
106
|
-
percentStyle:
|
|
107
|
-
insideStyle: { ...
|
|
108
|
-
leaderStroke: { weight: 2, fill: style.
|
|
109
|
+
percentStyle: value,
|
|
110
|
+
insideStyle: { ...value, fontSize: Math.round(sizeOf(style.valueText) * 1.9), fill: "#111113" },
|
|
111
|
+
leaderStroke: { weight: 2, fill: style.labelText.fill ?? "white" },
|
|
109
112
|
};
|
|
110
113
|
}
|
|
111
114
|
export function centerConfigOf(style) {
|
|
115
|
+
const size = sizeOf(style.centerText, 50);
|
|
112
116
|
return {
|
|
113
|
-
labelStyle:
|
|
114
|
-
|
|
115
|
-
fontSize: Math.round(style.fontSize * 1.8),
|
|
116
|
-
fontWeight: Math.min(900, style.fontWeight + 300),
|
|
117
|
-
textAlign: "center",
|
|
118
|
-
fill: style.foreground,
|
|
119
|
-
},
|
|
120
|
-
captionStyle: { ...face(style), fontSize: Math.round(style.fontSize * 0.8), fontWeight: style.fontWeight, textAlign: "center", fill: style.muted },
|
|
117
|
+
labelStyle: placedText(style.centerText),
|
|
118
|
+
captionStyle: placedText(style.labelText, "center", { fontSize: Math.round(size * 0.45) }),
|
|
121
119
|
};
|
|
122
120
|
}
|
|
123
121
|
//# sourceMappingURL=shared.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"shared.js","sourceRoot":"","sources":["../../src/pie-chart/shared.ts"],"names":[],"mappings":"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","sourcesContent":["import { Types, type Fill, type TextStyle, type Stroke, type FillResolved as _FillResolved } from \"@motionscript/sdk\"\n\nimport {\n CHART_COLORS,\n CHART_LEGEND,\n CHART_TEXT,\n legendConfigOf,\n type ChartStyleBase,\n} from \"../kit/style\"\nimport { num, text, type LegendConfig } from \"../kit/shared\"\nimport { DEG, PIE_SPOTLIGHT_DIM, ringPoint, selectionFade, type CenterConfig, type PieSlice } from \"../kit/polar\"\n\nexport { DEG, PIE_SPOTLIGHT_DIM, ringPoint, selectionFade, type CenterConfig, type PieSlice }\n\n/**\n * One slice per row, painted from `palette` by row order (cycling). Paint comes\n * from the palette, not the rows, because a pie's mark is a row where a line's\n * colour belongs to a column; that lets a pie be fed a CSV of plain numbers.\n */\nexport function resolvePieSlices(data: readonly Record<string, unknown>[], category: string, value: string, palette: readonly Fill[]): PieSlice[] {\n return data.map((row, i) => ({\n category: text(row as never, category),\n value: num(row as never, value),\n fill: palette.length > 0 ? palette[i % palette.length] : (\"white\" as Fill),\n }))\n}\n\n/** What a {@link PieChart}'s labels say. */\nexport type PieLabelMode =\n /** Two lines, whose order flips with placement: an outside label reads category over percentage, an inside label reads the percentage big over a small category. */\n | \"both\"\n | \"category\"\n | \"percent\"\n /** No labels and no leader lines. */\n | \"none\"\n\n/** `\"inside\"` centres the label in the wedge's band with no leader or gutter, so the ring draws bigger; `\"outside\"` sets it on a leader, which a sliver too narrow for text needs. */\nexport type PieLabelPlacement = \"inside\" | \"outside\" | \"none\"\n\n\n/** A slice's plotted value: negatives and non-finite values count as 0. */\nexport function sliceValue(slice: PieSlice): number {\n return slice.value > 0 && Number.isFinite(slice.value) ? slice.value : 0\n}\n\n/** Sum of every slice's plotted value, the denominator of every share. */\nexport function sliceTotal(slices: PieSlice[]): number {\n let sum = 0\n for (const slice of slices) sum += sliceValue(slice)\n return sum\n}\n\n/** One slice's resolved angular span on the ring. */\nexport interface PieArc {\n /** Index of the slice in the source list. */\n index: number\n /** Radians clockwise from 12 o'clock. */\n a0: number\n a1: number\n /** Where the slice's label and pop-out point. */\n mid: number\n /** Share of the total, `[0, 1]`. */\n fraction: number\n}\n\n/**\n * One arc per positive slice, walking clockwise from `startDegrees` and abutting.\n * Arcs are the undivided shares: a fixed angular gap would pinch shut at the\n * hole, so the gap is applied when the wedge is drawn, as a constant-width inset\n * off both ends.\n */\nexport function pieArcs(slices: PieSlice[], startDegrees: number): PieArc[] {\n const total = sliceTotal(slices)\n if (total <= 0) return []\n\n const arcs: PieArc[] = []\n let cursor = startDegrees * DEG\n slices.forEach((slice, index) => {\n const value = sliceValue(slice)\n if (value <= 0) return\n const fraction = value / total\n const a0 = cursor\n const a1 = a0 + fraction * Math.PI * 2\n cursor = a1\n arcs.push({ index, a0, a1, mid: (a0 + a1) / 2, fraction })\n })\n return arcs\n}\n\ninterface LabelSlot {\n /** Where the label would sit if nothing else were in the way. */\n ideal: number\n /** Written by {@link relaxLabels}. */\n y: number\n}\n\n/**\n * Spread one column of labels so none overlap, each near its `ideal` y and all\n * inside `[bottom, top]`. A top-down pass clears each label from the one above\n * by `minGap`; a reverse pass lifts a tail pushed past `bottom`. When the column\n * cannot hold them all, the reverse pass wins and the crowding is shared evenly.\n * Mutates each `y` and returns `slots` ordered top to bottom.\n */\nexport function relaxLabels<T extends LabelSlot>(slots: T[], minGap: number, top: number, bottom: number): T[] {\n slots.sort((a, b) => b.ideal - a.ideal)\n\n let ceiling = top\n for (const slot of slots) {\n slot.y = Math.min(slot.ideal, ceiling)\n ceiling = slot.y - minGap\n }\n\n let floor = bottom\n for (let i = slots.length - 1; i >= 0; i--) {\n slots[i].y = Math.max(slots[i].y, floor)\n floor = slots[i].y + minGap\n }\n\n return slots\n}\n\n/** The ring's geometry: everything about the wedges but their colour. */\nexport interface RingConfig {\n /** Channel between adjacent slices in px, constant across the band (an angular gap would splay open toward the rim). */\n gap: number\n /** Below 1 a fraction of the outer radius (`0.6` leaves a band 40% thick); 1 and up a pixel radius; `0` draws solid wedges. */\n holeRadius: number\n /** Degrees clockwise from 12 o'clock where the first slice begins. */\n startAngle: number\n /** How far a selected slice's rim reaches, as a multiple of the outer radius so the emphasis scales with the chart. Clamped to `[1, 1.6]`. */\n selectedGrow: number\n /** Rounding of each wedge corner, px. */\n cornerRadius: number\n}\n\n/** How the ring's labels are set, and the leader lines that point at them. */\nexport interface LabelConfig {\n /** The category caption outside the ring. */\n textStyle: TextStyle\n /** The percentage outside the ring. */\n percentStyle: TextStyle\n /** Both lines of a label inside its wedge; its fill is set per wedge, for contrast against the paint. */\n insideStyle: TextStyle\n /** Runs from a wedge out to its label. */\n leaderStroke: Stroke\n}\n\n/** What a pie's `style` resolves to. */\nexport interface PieStyle extends ChartStyleBase {\n readonly innerRadius: number\n readonly sliceGap: number\n readonly sliceRadius: number\n readonly labelPlacement: PieLabelPlacement\n}\n\n/** The groups of a pie's `style`: no grid, as nothing is ruled. */\nexport const PIE_STYLE_GROUPS = {\n colors: CHART_COLORS,\n text: CHART_TEXT,\n marks: {\n /** Hole radius as a fraction of the outer radius: 0 is a pie, about 0.6 a donut. */\n innerRadius: Types.number(0, { min: 0, max: 0.9, step: 0.05 }),\n /** Channel between neighbouring wedges, px. */\n sliceGap: Types.number(3, { min: 0, max: 40, step: 1, unit: \"px\" }),\n /** Rounding of each wedge corner, px. */\n sliceRadius: Types.number(4, { min: 0, max: 60, step: 1, unit: \"px\" }),\n },\n labels: {\n /** Read as the chart is built: inside the wedge, outside on a leader, or none. */\n labelPlacement: Types.oneOf([\"inside\", \"outside\", \"none\"] as const, { animatable: false }),\n },\n legend: CHART_LEGEND,\n}\n\nexport function legendOf(style: PieStyle): LegendConfig {\n return legendConfigOf(style)\n}\n\nfunction face(style: PieStyle): Pick<TextStyle, \"fontFamily\"> {\n return style.fontFamily ? { fontFamily: style.fontFamily } : {}\n}\n\nexport function ringConfigOf(style: PieStyle): RingConfig {\n return { gap: style.sliceGap, holeRadius: style.innerRadius, startAngle: 0, selectedGrow: 1.08, cornerRadius: style.sliceRadius }\n}\n\nexport function labelConfigOf(style: PieStyle): LabelConfig {\n const base: TextStyle = { ...face(style), fontSize: style.fontSize, fontWeight: style.fontWeight, textAlign: \"center\", fill: style.muted }\n const bold = Math.min(900, style.fontWeight + 200)\n return {\n textStyle: base,\n percentStyle: { ...base, fontWeight: bold, fill: style.foreground },\n insideStyle: { ...base, fontSize: Math.round(style.fontSize * 1.9), fontWeight: bold, fill: \"#111113\" },\n leaderStroke: { weight: 2, fill: style.muted },\n }\n}\n\nexport function centerConfigOf(style: PieStyle): CenterConfig {\n return {\n labelStyle: {\n ...face(style),\n fontSize: Math.round(style.fontSize * 1.8),\n fontWeight: Math.min(900, style.fontWeight + 300),\n textAlign: \"center\",\n fill: style.foreground,\n },\n captionStyle: { ...face(style), fontSize: Math.round(style.fontSize * 0.8), fontWeight: style.fontWeight, textAlign: \"center\", fill: style.muted },\n }\n}\n"]}
|
|
1
|
+
{"version":3,"file":"shared.js","sourceRoot":"","sources":["../../src/pie-chart/shared.ts"],"names":[],"mappings":"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","sourcesContent":["import { Types, type Fill, type TextStyle, type Stroke, type FillResolved as _FillResolved } from \"@motionscript/sdk\"\n\nimport {\n CHART_BACKGROUND,\n CHART_FOREGROUND,\n CHART_LEGEND,\n CHART_MUTED,\n CHART_SERIES,\n legendConfigOf,\n placedText,\n sizeOf,\n type ChartStyleBase,\n} from \"../kit/style\"\nimport { num, text, type LegendConfig } from \"../kit/shared\"\nimport { DEG, PIE_SPOTLIGHT_DIM, ringPoint, selectionFade, type CenterConfig, type PieSlice } from \"../kit/polar\"\n\nexport { DEG, PIE_SPOTLIGHT_DIM, ringPoint, selectionFade, type CenterConfig, type PieSlice }\n\n/**\n * One slice per row, painted from `seriesFills` by row order (cycling). Paint comes\n * from the palette, not the rows, because a pie's mark is a row where a line's\n * colour belongs to a column; that lets a pie be fed a CSV of plain numbers.\n */\nexport function resolvePieSlices(data: readonly Record<string, unknown>[], category: string, value: string, palette: readonly Fill[]): PieSlice[] {\n return data.map((row, i) => ({\n category: text(row as never, category),\n value: num(row as never, value),\n fill: palette.length > 0 ? palette[i % palette.length] : (\"white\" as Fill),\n }))\n}\n\n/** What a {@link PieChart}'s labels say. */\nexport type PieLabelMode =\n /** Two lines, whose order flips with placement: an outside label reads category over percentage, an inside label reads the percentage big over a small category. */\n | \"both\"\n | \"category\"\n | \"percent\"\n /** No labels and no leader lines. */\n | \"none\"\n\n/** `\"inside\"` centres the label in the wedge's band with no leader or gutter, so the ring draws bigger; `\"outside\"` sets it on a leader, which a sliver too narrow for text needs. */\nexport type PieLabelPlacement = \"inside\" | \"outside\" | \"none\"\n\n\n/** A slice's plotted value: negatives and non-finite values count as 0. */\nexport function sliceValue(slice: PieSlice): number {\n return slice.value > 0 && Number.isFinite(slice.value) ? slice.value : 0\n}\n\n/** Sum of every slice's plotted value, the denominator of every share. */\nexport function sliceTotal(slices: PieSlice[]): number {\n let sum = 0\n for (const slice of slices) sum += sliceValue(slice)\n return sum\n}\n\n/** One slice's resolved angular span on the ring. */\nexport interface PieArc {\n /** Index of the slice in the source list. */\n index: number\n /** Radians clockwise from 12 o'clock. */\n a0: number\n a1: number\n /** Where the slice's label and pop-out point. */\n mid: number\n /** Share of the total, `[0, 1]`. */\n fraction: number\n}\n\n/**\n * One arc per positive slice, walking clockwise from `startDegrees` and abutting.\n * Arcs are the undivided shares: a fixed angular gap would pinch shut at the\n * hole, so the gap is applied when the wedge is drawn, as a constant-width inset\n * off both ends.\n */\nexport function pieArcs(slices: PieSlice[], startDegrees: number): PieArc[] {\n const total = sliceTotal(slices)\n if (total <= 0) return []\n\n const arcs: PieArc[] = []\n let cursor = startDegrees * DEG\n slices.forEach((slice, index) => {\n const value = sliceValue(slice)\n if (value <= 0) return\n const fraction = value / total\n const a0 = cursor\n const a1 = a0 + fraction * Math.PI * 2\n cursor = a1\n arcs.push({ index, a0, a1, mid: (a0 + a1) / 2, fraction })\n })\n return arcs\n}\n\ninterface LabelSlot {\n /** Where the label would sit if nothing else were in the way. */\n ideal: number\n /** Written by {@link relaxLabels}. */\n y: number\n}\n\n/**\n * Spread one column of labels so none overlap, each near its `ideal` y and all\n * inside `[bottom, top]`. A top-down pass clears each label from the one above\n * by `minGap`; a reverse pass lifts a tail pushed past `bottom`. When the column\n * cannot hold them all, the reverse pass wins and the crowding is shared evenly.\n * Mutates each `y` and returns `slots` ordered top to bottom.\n */\nexport function relaxLabels<T extends LabelSlot>(slots: T[], minGap: number, top: number, bottom: number): T[] {\n slots.sort((a, b) => b.ideal - a.ideal)\n\n let ceiling = top\n for (const slot of slots) {\n slot.y = Math.min(slot.ideal, ceiling)\n ceiling = slot.y - minGap\n }\n\n let floor = bottom\n for (let i = slots.length - 1; i >= 0; i--) {\n slots[i].y = Math.max(slots[i].y, floor)\n floor = slots[i].y + minGap\n }\n\n return slots\n}\n\n/** The ring's geometry: everything about the wedges but their colour. */\nexport interface RingConfig {\n /** Channel between adjacent slices in px, constant across the band (an angular gap would splay open toward the rim). */\n gap: number\n /** Below 1 a fraction of the outer radius (`0.6` leaves a band 40% thick); 1 and up a pixel radius; `0` draws solid wedges. */\n holeRadius: number\n /** Degrees clockwise from 12 o'clock where the first slice begins. */\n startAngle: number\n /** How far a selected slice's rim reaches, as a multiple of the outer radius so the emphasis scales with the chart. Clamped to `[1, 1.6]`. */\n selectedGrow: number\n /** Rounding of each wedge corner, px. */\n cornerRadius: number\n}\n\n/** How the ring's labels are set, and the leader lines that point at them. */\nexport interface LabelConfig {\n /** The category caption outside the ring. */\n textStyle: TextStyle\n /** The percentage outside the ring. */\n percentStyle: TextStyle\n /** Both lines of a label inside its wedge; its fill is set per wedge, for contrast against the paint. */\n insideStyle: TextStyle\n /** Runs from a wedge out to its label. */\n leaderStroke: Stroke\n}\n\n/** What a pie's `style` resolves to. */\nexport interface PieStyle extends ChartStyleBase {\n readonly labelText: TextStyle\n readonly valueText: TextStyle\n readonly centerText: TextStyle\n readonly innerRadius: number\n readonly sliceGap: number\n readonly sliceRadius: number\n readonly labelPlacement: PieLabelPlacement\n}\n\n/** The groups of a pie's `style`: no grid, as nothing is ruled. */\nexport const PIE_STYLE_GROUPS = {\n series: CHART_SERIES,\n background: CHART_BACKGROUND,\n marks: {\n /** Hole radius as a fraction of the outer radius: 0 is a pie, about 0.6 a donut. */\n innerRadius: Types.number(0, { min: 0, max: 0.9, step: 0.05 }),\n /** Channel between neighbouring wedges, px. */\n sliceGap: Types.number(3, { min: 0, max: 40, step: 1, unit: \"px\" }),\n /** Rounding of each wedge corner, px. */\n sliceRadius: Types.number(4, { min: 0, max: 60, step: 1, unit: \"px\" }),\n },\n labels: {\n /** Read as the chart is built: inside the wedge, outside on a leader, or none. */\n labelPlacement: Types.oneOf([\"inside\", \"outside\", \"none\"] as const, { animatable: false }),\n /** Each slice's name. */\n labelText: Types.typography({ fontSize: 28, fontWeight: 500, fill: CHART_MUTED }),\n /** Each slice's share or value, beside its name; inside a wedge both are set larger, inked for contrast. */\n valueText: Types.typography({ fontSize: 28, fontWeight: 700, fill: CHART_FOREGROUND }),\n /** The summary in the hole; its caption is set smaller, in the slice names' ink. */\n centerText: Types.typography({ fontSize: 50, fontWeight: 800, fill: CHART_FOREGROUND }),\n },\n legend: CHART_LEGEND,\n}\n\nexport function legendOf(style: PieStyle): LegendConfig {\n return legendConfigOf(style)\n}\n\nexport function ringConfigOf(style: PieStyle): RingConfig {\n return { gap: style.sliceGap, holeRadius: style.innerRadius, startAngle: 0, selectedGrow: 1.08, cornerRadius: style.sliceRadius }\n}\n\nexport function labelConfigOf(style: PieStyle): LabelConfig {\n const base = placedText(style.labelText)\n const value = placedText(style.valueText)\n return {\n textStyle: base,\n percentStyle: value,\n insideStyle: { ...value, fontSize: Math.round(sizeOf(style.valueText) * 1.9), fill: \"#111113\" },\n leaderStroke: { weight: 2, fill: style.labelText.fill ?? \"white\" },\n }\n}\n\nexport function centerConfigOf(style: PieStyle): CenterConfig {\n const size = sizeOf(style.centerText, 50)\n return {\n labelStyle: placedText(style.centerText),\n captionStyle: placedText(style.labelText, \"center\", { fontSize: Math.round(size * 0.45) }),\n }\n}\n"]}
|