minerva-design 1.2.0 → 1.3.0
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 +7 -0
- package/dist/charts/canvas.d.cts +4 -1
- package/dist/charts/canvas.d.ts +4 -1
- package/dist/charts/core.cjs +1 -1
- package/dist/charts/core.d.cts +5 -2
- package/dist/charts/core.d.ts +5 -2
- package/dist/charts/core.js +6 -4
- package/dist/charts/engine/canvas.cjs +1 -1
- package/dist/charts/engine/canvas.cjs.map +1 -1
- package/dist/charts/engine/canvas.js +65 -53
- package/dist/charts/engine/canvas.js.map +1 -1
- package/dist/charts/engine/chart.cjs +1 -2
- package/dist/charts/engine/chart.cjs.map +1 -1
- package/dist/charts/engine/chart.js +342 -323
- package/dist/charts/engine/chart.js.map +1 -1
- package/dist/charts/engine/color.cjs +1 -1
- package/dist/charts/engine/color.cjs.map +1 -1
- package/dist/charts/engine/color.d.cts +17 -0
- package/dist/charts/engine/color.d.ts +17 -0
- package/dist/charts/engine/color.js +27 -3
- package/dist/charts/engine/color.js.map +1 -1
- package/dist/charts/engine/controller.cjs +2 -2
- package/dist/charts/engine/controller.cjs.map +1 -1
- package/dist/charts/engine/controller.d.cts +6 -0
- package/dist/charts/engine/controller.d.ts +6 -0
- package/dist/charts/engine/controller.js +317 -253
- package/dist/charts/engine/controller.js.map +1 -1
- package/dist/charts/engine/curve.cjs +2 -0
- package/dist/charts/engine/curve.cjs.map +1 -0
- package/dist/charts/engine/curve.d.cts +15 -0
- package/dist/charts/engine/curve.d.ts +15 -0
- package/dist/charts/engine/curve.js +56 -0
- package/dist/charts/engine/curve.js.map +1 -0
- package/dist/charts/engine/data.cjs +1 -1
- package/dist/charts/engine/data.cjs.map +1 -1
- package/dist/charts/engine/data.d.cts +15 -2
- package/dist/charts/engine/data.d.ts +15 -2
- package/dist/charts/engine/data.js +98 -38
- package/dist/charts/engine/data.js.map +1 -1
- package/dist/charts/engine/dom.cjs +1 -1
- package/dist/charts/engine/dom.cjs.map +1 -1
- package/dist/charts/engine/dom.d.cts +5 -3
- package/dist/charts/engine/dom.d.ts +5 -3
- package/dist/charts/engine/dom.js +27 -22
- package/dist/charts/engine/dom.js.map +1 -1
- package/dist/charts/engine/items.cjs +1 -1
- package/dist/charts/engine/items.cjs.map +1 -1
- package/dist/charts/engine/items.js +132 -61
- package/dist/charts/engine/items.js.map +1 -1
- package/dist/charts/engine/model.cjs +1 -1
- package/dist/charts/engine/model.cjs.map +1 -1
- package/dist/charts/engine/model.d.cts +30 -3
- package/dist/charts/engine/model.d.ts +30 -3
- package/dist/charts/engine/model.js +225 -108
- package/dist/charts/engine/model.js.map +1 -1
- package/dist/charts/engine/overlay.cjs +1 -1
- package/dist/charts/engine/overlay.cjs.map +1 -1
- package/dist/charts/engine/overlay.d.cts +2 -0
- package/dist/charts/engine/overlay.d.ts +2 -0
- package/dist/charts/engine/overlay.js +16 -16
- package/dist/charts/engine/overlay.js.map +1 -1
- package/dist/charts/engine/presets.cjs +2 -2
- package/dist/charts/engine/presets.cjs.map +1 -1
- package/dist/charts/engine/presets.d.cts +71 -5
- package/dist/charts/engine/presets.d.ts +71 -5
- package/dist/charts/engine/presets.js +120 -33
- package/dist/charts/engine/presets.js.map +1 -1
- package/dist/charts/engine/renderers/canvas2d.cjs +1 -1
- package/dist/charts/engine/renderers/canvas2d.cjs.map +1 -1
- package/dist/charts/engine/renderers/canvas2d.js +149 -111
- package/dist/charts/engine/renderers/canvas2d.js.map +1 -1
- package/dist/charts/engine/renderers/range.cjs +1 -1
- package/dist/charts/engine/renderers/range.cjs.map +1 -1
- package/dist/charts/engine/renderers/range.js +4 -4
- package/dist/charts/engine/renderers/range.js.map +1 -1
- package/dist/charts/engine/renderers/shaders.cjs +37 -19
- package/dist/charts/engine/renderers/shaders.cjs.map +1 -1
- package/dist/charts/engine/renderers/shaders.d.cts +2 -2
- package/dist/charts/engine/renderers/shaders.d.ts +2 -2
- package/dist/charts/engine/renderers/shaders.js +37 -19
- package/dist/charts/engine/renderers/shaders.js.map +1 -1
- package/dist/charts/engine/renderers/types.cjs.map +1 -1
- package/dist/charts/engine/renderers/types.d.cts +11 -4
- package/dist/charts/engine/renderers/types.d.ts +11 -4
- package/dist/charts/engine/renderers/types.js.map +1 -1
- package/dist/charts/engine/renderers/webgl2.cjs +1 -1
- package/dist/charts/engine/renderers/webgl2.cjs.map +1 -1
- package/dist/charts/engine/renderers/webgl2.js +33 -12
- package/dist/charts/engine/renderers/webgl2.js.map +1 -1
- package/dist/charts/engine/renderers/webgpu.cjs +1 -1
- package/dist/charts/engine/renderers/webgpu.cjs.map +1 -1
- package/dist/charts/engine/renderers/webgpu.js +18 -15
- package/dist/charts/engine/renderers/webgpu.js.map +1 -1
- package/dist/charts/engine/scene.cjs +1 -1
- package/dist/charts/engine/scene.cjs.map +1 -1
- package/dist/charts/engine/scene.d.cts +19 -6
- package/dist/charts/engine/scene.d.ts +19 -6
- package/dist/charts/engine/scene.js +201 -89
- package/dist/charts/engine/scene.js.map +1 -1
- package/dist/charts/engine/shapes/canvas.cjs +2 -0
- package/dist/charts/engine/shapes/canvas.cjs.map +1 -0
- package/dist/charts/engine/shapes/canvas.d.cts +58 -0
- package/dist/charts/engine/shapes/canvas.d.ts +58 -0
- package/dist/charts/engine/shapes/canvas.js +159 -0
- package/dist/charts/engine/shapes/canvas.js.map +1 -0
- package/dist/charts/engine/shapes/chart.cjs +2 -0
- package/dist/charts/engine/shapes/chart.cjs.map +1 -0
- package/dist/charts/engine/shapes/chart.d.cts +6 -0
- package/dist/charts/engine/shapes/chart.d.ts +6 -0
- package/dist/charts/engine/shapes/chart.js +273 -0
- package/dist/charts/engine/shapes/chart.js.map +1 -0
- package/dist/charts/engine/shapes/draw.cjs +2 -0
- package/dist/charts/engine/shapes/draw.cjs.map +1 -0
- package/dist/charts/engine/shapes/draw.d.cts +20 -0
- package/dist/charts/engine/shapes/draw.d.ts +20 -0
- package/dist/charts/engine/shapes/draw.js +152 -0
- package/dist/charts/engine/shapes/draw.js.map +1 -0
- package/dist/charts/engine/shapes/funnel.cjs +2 -0
- package/dist/charts/engine/shapes/funnel.cjs.map +1 -0
- package/dist/charts/engine/shapes/funnel.d.cts +6 -0
- package/dist/charts/engine/shapes/funnel.d.ts +6 -0
- package/dist/charts/engine/shapes/funnel.js +149 -0
- package/dist/charts/engine/shapes/funnel.js.map +1 -0
- package/dist/charts/engine/shapes/gauge.cjs +2 -0
- package/dist/charts/engine/shapes/gauge.cjs.map +1 -0
- package/dist/charts/engine/shapes/gauge.d.cts +7 -0
- package/dist/charts/engine/shapes/gauge.d.ts +7 -0
- package/dist/charts/engine/shapes/gauge.js +173 -0
- package/dist/charts/engine/shapes/gauge.js.map +1 -0
- package/dist/charts/engine/shapes/hit.cjs +2 -0
- package/dist/charts/engine/shapes/hit.cjs.map +1 -0
- package/dist/charts/engine/shapes/hit.d.cts +28 -0
- package/dist/charts/engine/shapes/hit.d.ts +28 -0
- package/dist/charts/engine/shapes/hit.js +124 -0
- package/dist/charts/engine/shapes/hit.js.map +1 -0
- package/dist/charts/engine/shapes/index.d.cts +9 -0
- package/dist/charts/engine/shapes/index.d.ts +9 -0
- package/dist/charts/engine/shapes/layout.cjs +3 -0
- package/dist/charts/engine/shapes/layout.cjs.map +1 -0
- package/dist/charts/engine/shapes/layout.d.cts +88 -0
- package/dist/charts/engine/shapes/layout.d.ts +88 -0
- package/dist/charts/engine/shapes/layout.js +266 -0
- package/dist/charts/engine/shapes/layout.js.map +1 -0
- package/dist/charts/engine/shapes/pie.cjs +2 -0
- package/dist/charts/engine/shapes/pie.cjs.map +1 -0
- package/dist/charts/engine/shapes/pie.d.cts +20 -0
- package/dist/charts/engine/shapes/pie.d.ts +20 -0
- package/dist/charts/engine/shapes/pie.js +302 -0
- package/dist/charts/engine/shapes/pie.js.map +1 -0
- package/dist/charts/engine/shapes/radar.cjs +2 -0
- package/dist/charts/engine/shapes/radar.cjs.map +1 -0
- package/dist/charts/engine/shapes/radar.d.cts +8 -0
- package/dist/charts/engine/shapes/radar.d.ts +8 -0
- package/dist/charts/engine/shapes/radar.js +197 -0
- package/dist/charts/engine/shapes/radar.js.map +1 -0
- package/dist/charts/engine/shapes/runtime.cjs +2 -0
- package/dist/charts/engine/shapes/runtime.cjs.map +1 -0
- package/dist/charts/engine/shapes/runtime.d.cts +29 -0
- package/dist/charts/engine/shapes/runtime.d.ts +29 -0
- package/dist/charts/engine/shapes/runtime.js +97 -0
- package/dist/charts/engine/shapes/runtime.js.map +1 -0
- package/dist/charts/engine/shapes/scene.cjs +2 -0
- package/dist/charts/engine/shapes/scene.cjs.map +1 -0
- package/dist/charts/engine/shapes/scene.d.cts +257 -0
- package/dist/charts/engine/shapes/scene.d.ts +257 -0
- package/dist/charts/engine/shapes/scene.js +123 -0
- package/dist/charts/engine/shapes/scene.js.map +1 -0
- package/dist/charts/engine/shapes/treemap.cjs +2 -0
- package/dist/charts/engine/shapes/treemap.cjs.map +1 -0
- package/dist/charts/engine/shapes/treemap.d.cts +14 -0
- package/dist/charts/engine/shapes/treemap.d.ts +14 -0
- package/dist/charts/engine/shapes/treemap.js +213 -0
- package/dist/charts/engine/shapes/treemap.js.map +1 -0
- package/dist/charts/engine/shapes/types.d.cts +292 -0
- package/dist/charts/engine/shapes/types.d.ts +292 -0
- package/dist/charts/engine/signature.cjs +2 -0
- package/dist/charts/engine/signature.cjs.map +1 -0
- package/dist/charts/engine/signature.d.cts +9 -0
- package/dist/charts/engine/signature.d.ts +9 -0
- package/dist/charts/engine/signature.js +13 -0
- package/dist/charts/engine/signature.js.map +1 -0
- package/dist/charts/engine/theme.cjs +1 -1
- package/dist/charts/engine/theme.cjs.map +1 -1
- package/dist/charts/engine/theme.d.cts +10 -1
- package/dist/charts/engine/theme.d.ts +10 -1
- package/dist/charts/engine/theme.js +40 -16
- package/dist/charts/engine/theme.js.map +1 -1
- package/dist/charts/engine/types.d.cts +70 -9
- package/dist/charts/engine/types.d.ts +70 -9
- package/dist/charts/index.cjs +1 -1
- package/dist/charts/index.d.cts +4 -2
- package/dist/charts/index.d.ts +4 -2
- package/dist/charts/index.js +8 -5
- package/dist/charts/react/Chart.cjs +1 -1
- package/dist/charts/react/Chart.cjs.map +1 -1
- package/dist/charts/react/Chart.d.cts +8 -1
- package/dist/charts/react/Chart.d.ts +8 -1
- package/dist/charts/react/Chart.js +66 -47
- package/dist/charts/react/Chart.js.map +1 -1
- package/dist/charts/react/charts.cjs +1 -1
- package/dist/charts/react/charts.cjs.map +1 -1
- package/dist/charts/react/charts.d.cts +10 -2
- package/dist/charts/react/charts.d.ts +10 -2
- package/dist/charts/react/charts.js +174 -51
- package/dist/charts/react/charts.js.map +1 -1
- package/dist/charts/react/shapes.cjs +2 -0
- package/dist/charts/react/shapes.cjs.map +1 -0
- package/dist/charts/react/shapes.d.cts +255 -0
- package/dist/charts/react/shapes.d.ts +255 -0
- package/dist/charts/react/shapes.js +242 -0
- package/dist/charts/react/shapes.js.map +1 -0
- package/dist/charts/react/types.d.cts +73 -4
- package/dist/charts/react/types.d.ts +73 -4
- package/dist/native/charts/src/engine/color.cjs +1 -1
- package/dist/native/charts/src/engine/color.cjs.map +1 -1
- package/dist/native/charts/src/engine/color.js +12 -3
- package/dist/native/charts/src/engine/color.js.map +1 -1
- package/dist/native/charts/src/engine/controller.cjs +2 -2
- package/dist/native/charts/src/engine/controller.cjs.map +1 -1
- package/dist/native/charts/src/engine/controller.js +334 -270
- package/dist/native/charts/src/engine/controller.js.map +1 -1
- package/dist/native/charts/src/engine/curve.cjs +2 -0
- package/dist/native/charts/src/engine/curve.cjs.map +1 -0
- package/dist/native/charts/src/engine/curve.js +56 -0
- package/dist/native/charts/src/engine/curve.js.map +1 -0
- package/dist/native/charts/src/engine/data.cjs +1 -1
- package/dist/native/charts/src/engine/data.cjs.map +1 -1
- package/dist/native/charts/src/engine/data.js +98 -38
- package/dist/native/charts/src/engine/data.js.map +1 -1
- package/dist/native/charts/src/engine/model.cjs +1 -1
- package/dist/native/charts/src/engine/model.cjs.map +1 -1
- package/dist/native/charts/src/engine/model.js +229 -112
- package/dist/native/charts/src/engine/model.js.map +1 -1
- package/dist/native/charts/src/engine/overlay.cjs +1 -1
- package/dist/native/charts/src/engine/overlay.cjs.map +1 -1
- package/dist/native/charts/src/engine/overlay.js +16 -16
- package/dist/native/charts/src/engine/overlay.js.map +1 -1
- package/dist/native/charts/src/engine/presets.cjs +1 -1
- package/dist/native/charts/src/engine/presets.cjs.map +1 -1
- package/dist/native/charts/src/engine/presets.js +11 -4
- package/dist/native/charts/src/engine/presets.js.map +1 -1
- package/dist/native/charts/src/engine/scene.cjs +1 -1
- package/dist/native/charts/src/engine/scene.cjs.map +1 -1
- package/dist/native/charts/src/engine/scene.js +209 -97
- package/dist/native/charts/src/engine/scene.js.map +1 -1
- package/dist/native/charts/src/engine/theme.cjs.map +1 -1
- package/dist/native/charts/src/engine/theme.js.map +1 -1
- package/dist/native/components/Chart/scene.cjs +1 -1
- package/dist/native/components/Chart/scene.cjs.map +1 -1
- package/dist/native/components/Chart/scene.js +31 -19
- package/dist/native/components/Chart/scene.js.map +1 -1
- package/dist/native/source/components/Chart/scene.tsx +54 -20
- package/dist/taro/index.js +1059 -579
- package/dist/uni/charts-canvas.js +3 -1
- package/dist/weapp/controls.js +966 -225
- package/package.json +1 -1
|
@@ -0,0 +1,257 @@
|
|
|
1
|
+
import { Rgba } from '../color.js';
|
|
2
|
+
import { ChartTheme } from '../theme.js';
|
|
3
|
+
import { ChartPadding } from '../types.js';
|
|
4
|
+
import { ShapeChartType } from './types.js';
|
|
5
|
+
export declare const TAU: number;
|
|
6
|
+
/** Rectangle in CSS pixels */
|
|
7
|
+
export interface ShapeRect {
|
|
8
|
+
x: number;
|
|
9
|
+
y: number;
|
|
10
|
+
width: number;
|
|
11
|
+
height: number;
|
|
12
|
+
}
|
|
13
|
+
interface NodeBase {
|
|
14
|
+
/** Index of the item the node belongs to (hover, dimming); none for decorations */
|
|
15
|
+
hit?: number;
|
|
16
|
+
/** Opacity multiplier */
|
|
17
|
+
alpha?: number;
|
|
18
|
+
/** Offset applied while the node's item is hovered (pie slices pop out) */
|
|
19
|
+
shift?: [number, number];
|
|
20
|
+
}
|
|
21
|
+
/** Annular sector (pie slice, donut segment, ring) */
|
|
22
|
+
export interface SectorNode extends NodeBase {
|
|
23
|
+
kind: "sector";
|
|
24
|
+
cx: number;
|
|
25
|
+
cy: number;
|
|
26
|
+
r0: number;
|
|
27
|
+
r1: number;
|
|
28
|
+
/** Canvas angles (radians, clockwise from 3 o'clock) */
|
|
29
|
+
a0: number;
|
|
30
|
+
a1: number;
|
|
31
|
+
/** Gap with the neighbours, in pixels */
|
|
32
|
+
pad: number;
|
|
33
|
+
/** Corner radius, in pixels */
|
|
34
|
+
corner: number;
|
|
35
|
+
fill: string;
|
|
36
|
+
}
|
|
37
|
+
/** Polygon (radar grid / series, funnel stage); `hole` is cut out */
|
|
38
|
+
export interface PolygonNode extends NodeBase {
|
|
39
|
+
kind: "polygon";
|
|
40
|
+
/** Flat x, y list */
|
|
41
|
+
points: number[];
|
|
42
|
+
hole?: number[];
|
|
43
|
+
fill?: string;
|
|
44
|
+
stroke?: string;
|
|
45
|
+
lineWidth?: number;
|
|
46
|
+
/** Corner radius, in pixels */
|
|
47
|
+
radius?: number;
|
|
48
|
+
/** Fill / stroke width when hovered */
|
|
49
|
+
hoverFill?: string;
|
|
50
|
+
hoverLineWidth?: number;
|
|
51
|
+
/** Lightens the shape when hovered */
|
|
52
|
+
brighten?: boolean;
|
|
53
|
+
}
|
|
54
|
+
export interface RectNode extends NodeBase {
|
|
55
|
+
kind: "rect";
|
|
56
|
+
x: number;
|
|
57
|
+
y: number;
|
|
58
|
+
width: number;
|
|
59
|
+
height: number;
|
|
60
|
+
radius: number;
|
|
61
|
+
fill: string;
|
|
62
|
+
brighten?: boolean;
|
|
63
|
+
}
|
|
64
|
+
/** Stroked arc (gauge track / value) */
|
|
65
|
+
export interface ArcNode extends NodeBase {
|
|
66
|
+
kind: "arc";
|
|
67
|
+
cx: number;
|
|
68
|
+
cy: number;
|
|
69
|
+
r: number;
|
|
70
|
+
a0: number;
|
|
71
|
+
a1: number;
|
|
72
|
+
width: number;
|
|
73
|
+
color: string;
|
|
74
|
+
cap: "round" | "butt";
|
|
75
|
+
}
|
|
76
|
+
/** Dot; without fill nor stroke it is only a hit area */
|
|
77
|
+
export interface CircleNode extends NodeBase {
|
|
78
|
+
kind: "circle";
|
|
79
|
+
cx: number;
|
|
80
|
+
cy: number;
|
|
81
|
+
r: number;
|
|
82
|
+
fill?: string;
|
|
83
|
+
stroke?: string;
|
|
84
|
+
lineWidth?: number;
|
|
85
|
+
/** Radar: indicator of the vertex */
|
|
86
|
+
indicator?: number;
|
|
87
|
+
/** Radius and halo color when the vertex is hovered */
|
|
88
|
+
hoverR?: number;
|
|
89
|
+
halo?: string;
|
|
90
|
+
}
|
|
91
|
+
export interface LineNode extends NodeBase {
|
|
92
|
+
kind: "line";
|
|
93
|
+
points: number[];
|
|
94
|
+
color: string;
|
|
95
|
+
width: number;
|
|
96
|
+
dash?: number[];
|
|
97
|
+
}
|
|
98
|
+
export interface TextNode extends NodeBase {
|
|
99
|
+
kind: "text";
|
|
100
|
+
x: number;
|
|
101
|
+
y: number;
|
|
102
|
+
text: string;
|
|
103
|
+
font: string;
|
|
104
|
+
color: string;
|
|
105
|
+
align: "left" | "center" | "right";
|
|
106
|
+
baseline: "top" | "middle" | "bottom" | "alphabetic";
|
|
107
|
+
/** Radar: indicator of the label */
|
|
108
|
+
indicator?: number;
|
|
109
|
+
hoverColor?: string;
|
|
110
|
+
hoverFont?: string;
|
|
111
|
+
}
|
|
112
|
+
/** Radar: dashed guide from the center to the hovered indicator */
|
|
113
|
+
export interface GuideNode extends NodeBase {
|
|
114
|
+
kind: "guide";
|
|
115
|
+
cx: number;
|
|
116
|
+
cy: number;
|
|
117
|
+
/** End of each spoke */
|
|
118
|
+
ends: [number, number][];
|
|
119
|
+
color: string;
|
|
120
|
+
}
|
|
121
|
+
export type ShapeNode = SectorNode | PolygonNode | RectNode | ArcNode | CircleNode | LineNode | TextNode | GuideNode;
|
|
122
|
+
/** A row of the default tooltip */
|
|
123
|
+
export interface ShapeTooltipRow {
|
|
124
|
+
name: string;
|
|
125
|
+
value: string;
|
|
126
|
+
color?: string;
|
|
127
|
+
strong?: boolean;
|
|
128
|
+
}
|
|
129
|
+
/** Something the pointer / keyboard can focus */
|
|
130
|
+
export interface ShapeItem {
|
|
131
|
+
index: number;
|
|
132
|
+
name: string;
|
|
133
|
+
value: number;
|
|
134
|
+
percent: number;
|
|
135
|
+
/** `percent` formatted for screen readers (`percentFormat`) */
|
|
136
|
+
share?: string;
|
|
137
|
+
color: string;
|
|
138
|
+
path?: string[];
|
|
139
|
+
/** Anchor of the tooltip when focused with the keyboard */
|
|
140
|
+
x: number;
|
|
141
|
+
y: number;
|
|
142
|
+
/** Rows of the default tooltip */
|
|
143
|
+
rows: ShapeTooltipRow[];
|
|
144
|
+
/** Radar: one entry per indicator */
|
|
145
|
+
indicators?: {
|
|
146
|
+
name: string;
|
|
147
|
+
value: number;
|
|
148
|
+
percent: number;
|
|
149
|
+
x: number;
|
|
150
|
+
y: number;
|
|
151
|
+
}[];
|
|
152
|
+
}
|
|
153
|
+
/** What is hovered: an item (and a radar indicator) */
|
|
154
|
+
export interface ShapeHover {
|
|
155
|
+
index: number;
|
|
156
|
+
indicator?: number;
|
|
157
|
+
}
|
|
158
|
+
export interface ShapeLegendEntry {
|
|
159
|
+
/** Index passed to `toggle` */
|
|
160
|
+
index: number;
|
|
161
|
+
name: string;
|
|
162
|
+
color: string;
|
|
163
|
+
hidden: boolean;
|
|
164
|
+
}
|
|
165
|
+
export interface ShapeScene {
|
|
166
|
+
type: ShapeChartType;
|
|
167
|
+
/** Size of the whole drawing */
|
|
168
|
+
width: number;
|
|
169
|
+
height: number;
|
|
170
|
+
nodes: ShapeNode[];
|
|
171
|
+
/** Focusable items, in keyboard order */
|
|
172
|
+
items: ShapeItem[];
|
|
173
|
+
/** Opacity of the other marks while one is hovered */
|
|
174
|
+
dim: number;
|
|
175
|
+
/** Entry animation of funnels / treemaps: fade and scale around a point */
|
|
176
|
+
enter?: {
|
|
177
|
+
alpha: number;
|
|
178
|
+
scale: number;
|
|
179
|
+
cx: number;
|
|
180
|
+
cy: number;
|
|
181
|
+
};
|
|
182
|
+
/** Radar geometry used by hit testing (and to keep the tooltip off the labels) */
|
|
183
|
+
radar?: {
|
|
184
|
+
cx: number;
|
|
185
|
+
cy: number;
|
|
186
|
+
radius: number;
|
|
187
|
+
angles: number[];
|
|
188
|
+
series: {
|
|
189
|
+
index: number;
|
|
190
|
+
points: number[];
|
|
191
|
+
}[];
|
|
192
|
+
/** Boxes of the indicator labels */
|
|
193
|
+
labels?: ShapeRect[];
|
|
194
|
+
};
|
|
195
|
+
/** No data to draw (placeholder shown) */
|
|
196
|
+
empty: boolean;
|
|
197
|
+
}
|
|
198
|
+
/** Measures a text in a CSS font */
|
|
199
|
+
export type MeasureText = (text: string, font: string) => number;
|
|
200
|
+
/** Approximate width of a text without a canvas (tests, SSR) */
|
|
201
|
+
export declare const estimateText: MeasureText;
|
|
202
|
+
/** What the layouts of every type get */
|
|
203
|
+
export interface LayoutContext {
|
|
204
|
+
theme: ChartTheme;
|
|
205
|
+
measure: MeasureText;
|
|
206
|
+
hidden: ReadonlySet<number>;
|
|
207
|
+
/** Entry progress, eased (1 when done) */
|
|
208
|
+
enter: number;
|
|
209
|
+
/** Displayed (animated) value of a key */
|
|
210
|
+
value(key: string, target: number): number;
|
|
211
|
+
format(value: number): string;
|
|
212
|
+
/** Formats a share (0-1): `percentFormat` or one decimal */
|
|
213
|
+
percent(share: number): string;
|
|
214
|
+
/** Color of the `i`-th mark (custom `color` or the palette) */
|
|
215
|
+
color(css: string | undefined, i: number): Rgba;
|
|
216
|
+
/** Drawing area, padding excluded */
|
|
217
|
+
area: ShapeRect;
|
|
218
|
+
}
|
|
219
|
+
export type LayoutResult = Omit<ShapeScene, "type" | "width" | "height">;
|
|
220
|
+
export declare const clamp: (v: number, lo: number, hi: number) => number;
|
|
221
|
+
/** Non-negative finite number */
|
|
222
|
+
export declare const positive: (v: number | undefined) => number;
|
|
223
|
+
export declare const finite: (v: number | undefined, fallback?: number) => number;
|
|
224
|
+
export declare const sum: (values: readonly number[]) => number;
|
|
225
|
+
export declare const easeOutCubic: (t: number) => number;
|
|
226
|
+
export declare const defaultFormat: (value: number) => string;
|
|
227
|
+
/** Share 0-1 as a percent with one decimal: `0.4` -> `40.0%` */
|
|
228
|
+
export declare const formatPercent: (p: number) => string;
|
|
229
|
+
export declare const inset: (rect: ShapeRect, padding?: ChartPadding) => ShapeRect;
|
|
230
|
+
/** Shortens a text with an ellipsis so it fits in `max` pixels ("" if nothing fits) */
|
|
231
|
+
export declare const ellipsize: (text: string, max: number, font: string, measure: MeasureText) => string;
|
|
232
|
+
/** Stable keys of named values: the name, `name#2` for duplicates */
|
|
233
|
+
export declare const uniqueKeys: (names: readonly string[]) => string[];
|
|
234
|
+
/** WCAG relative luminance of an opaque color */
|
|
235
|
+
export declare const relativeLuminance: (c: Rgba) => number;
|
|
236
|
+
/** `top` composited over the opaque `bottom` */
|
|
237
|
+
export declare const over: (top: Rgba, bottom: Rgba) => Rgba;
|
|
238
|
+
/** WCAG contrast ratio (1-21) of `ink` drawn on the opaque `fill` */
|
|
239
|
+
export declare const contrastRatio: (ink: Rgba, fill: Rgba) => number;
|
|
240
|
+
/** Light or dark ink, whichever contrasts more with the fill, and its contrast */
|
|
241
|
+
export declare const inkOn: (fill: Rgba, backdrop?: Rgba) => {
|
|
242
|
+
ink: Rgba;
|
|
243
|
+
css: string;
|
|
244
|
+
contrast: number;
|
|
245
|
+
};
|
|
246
|
+
/** Readable text color on a fill (WCAG contrast) */
|
|
247
|
+
export declare const textOn: (fill: Rgba, backdrop?: Rgba) => string;
|
|
248
|
+
/**
|
|
249
|
+
* Fill adjusted so that its best ink reaches `target` contrast: darkened
|
|
250
|
+
* under white text, lightened under dark text (at most `limit` of the way)
|
|
251
|
+
*/
|
|
252
|
+
export declare const readableFill: (fill: Rgba, target?: number, limit?: number) => Rgba;
|
|
253
|
+
/** Resolves a custom color with the theme resolver (static parsing otherwise) */
|
|
254
|
+
export declare const resolveWith: (theme: ChartTheme, css: string | undefined, fallback: Rgba) => Rgba;
|
|
255
|
+
/** Placeholder of a chart without data: a muted ring and "No data" */
|
|
256
|
+
export declare const emptyLayout: (c: LayoutContext) => LayoutResult;
|
|
257
|
+
export {};
|
|
@@ -0,0 +1,123 @@
|
|
|
1
|
+
import { mix as e, parseColor as t, toCss as n } from "../color.js";
|
|
2
|
+
import { font as r } from "../overlay.js";
|
|
3
|
+
import { formatCompact as i } from "../format.js";
|
|
4
|
+
//#region src/engine/shapes/scene.ts
|
|
5
|
+
var a = Math.PI * 2, o = (e, t) => {
|
|
6
|
+
let n = /(\d+(?:\.\d+)?)px/.exec(t);
|
|
7
|
+
return e.length * (n ? Number(n[1]) : 12) * .6;
|
|
8
|
+
}, s = (e, t, n) => e < t ? t : e > n ? n : e, c = (e) => typeof e == "number" && Number.isFinite(e) && e > 0 ? e : 0, l = (e, t = 0) => typeof e == "number" && Number.isFinite(e) ? e : t, u = (e) => {
|
|
9
|
+
let t = 0;
|
|
10
|
+
for (let n of e) t += n;
|
|
11
|
+
return t;
|
|
12
|
+
}, d = (e) => 1 - (1 - s(e, 0, 1)) ** 3, f = (e) => i(e), p = (e) => Number.isFinite(e) ? `${(e * 100).toFixed(1)}%` : "–", m = (e, t) => {
|
|
13
|
+
let n = t?.top ?? 8, r = t?.right ?? 8, i = t?.bottom ?? 8, a = t?.left ?? 8;
|
|
14
|
+
return {
|
|
15
|
+
x: e.x + a,
|
|
16
|
+
y: e.y + n,
|
|
17
|
+
width: Math.max(0, e.width - a - r),
|
|
18
|
+
height: Math.max(0, e.height - n - i)
|
|
19
|
+
};
|
|
20
|
+
}, h = (e, t, n, r) => {
|
|
21
|
+
if (r(e, n) <= t) return e;
|
|
22
|
+
if (r("…", n) > t) return "";
|
|
23
|
+
let i = 0, a = e.length;
|
|
24
|
+
for (; i < a;) {
|
|
25
|
+
let o = i + a + 1 >> 1;
|
|
26
|
+
r(e.slice(0, o) + "…", n) <= t ? i = o : a = o - 1;
|
|
27
|
+
}
|
|
28
|
+
return i ? e.slice(0, i).trimEnd() + "…" : "";
|
|
29
|
+
}, g = (e) => {
|
|
30
|
+
let t = /* @__PURE__ */ new Map();
|
|
31
|
+
return e.map((e) => {
|
|
32
|
+
let n = (t.get(e) ?? 0) + 1;
|
|
33
|
+
return t.set(e, n), n === 1 ? e : `${e}#${n}`;
|
|
34
|
+
});
|
|
35
|
+
}, _ = [
|
|
36
|
+
1,
|
|
37
|
+
1,
|
|
38
|
+
1,
|
|
39
|
+
.96
|
|
40
|
+
], v = [
|
|
41
|
+
15 / 255,
|
|
42
|
+
23 / 255,
|
|
43
|
+
42 / 255,
|
|
44
|
+
.88
|
|
45
|
+
], y = (e) => e <= .04045 ? e / 12.92 : ((e + .055) / 1.055) ** 2.4, b = (e) => .2126 * y(e[0]) + .7152 * y(e[1]) + .0722 * y(e[2]), x = (e, t) => {
|
|
46
|
+
let n = s(e[3], 0, 1);
|
|
47
|
+
return [
|
|
48
|
+
e[0] * n + t[0] * (1 - n),
|
|
49
|
+
e[1] * n + t[1] * (1 - n),
|
|
50
|
+
e[2] * n + t[2] * (1 - n),
|
|
51
|
+
1
|
|
52
|
+
];
|
|
53
|
+
}, S = (e, t) => {
|
|
54
|
+
let n = b(x(e, t)), r = b(t);
|
|
55
|
+
return (Math.max(n, r) + .05) / (Math.min(n, r) + .05);
|
|
56
|
+
}, C = [
|
|
57
|
+
1,
|
|
58
|
+
1,
|
|
59
|
+
1,
|
|
60
|
+
1
|
|
61
|
+
], w = (e, t = C) => {
|
|
62
|
+
let r = x(e, x(t, C)), i = S(_, r), a = S(v, r);
|
|
63
|
+
return i >= a ? {
|
|
64
|
+
ink: _,
|
|
65
|
+
css: n(_),
|
|
66
|
+
contrast: i
|
|
67
|
+
} : {
|
|
68
|
+
ink: v,
|
|
69
|
+
css: n(v),
|
|
70
|
+
contrast: a
|
|
71
|
+
};
|
|
72
|
+
}, T = (e, t) => w(e, t).css, E = (t, n = 4.5, r = .3) => {
|
|
73
|
+
let i = w(t);
|
|
74
|
+
if (i.contrast >= n) return t;
|
|
75
|
+
let a = i.ink === _ ? [
|
|
76
|
+
0,
|
|
77
|
+
0,
|
|
78
|
+
0,
|
|
79
|
+
t[3]
|
|
80
|
+
] : [
|
|
81
|
+
1,
|
|
82
|
+
1,
|
|
83
|
+
1,
|
|
84
|
+
t[3]
|
|
85
|
+
];
|
|
86
|
+
for (let o = .04; o <= r + 1e-9; o += .04) {
|
|
87
|
+
let r = e(t, a, o);
|
|
88
|
+
if (i = w(r), i.contrast >= n) return r;
|
|
89
|
+
}
|
|
90
|
+
return e(t, a, r);
|
|
91
|
+
}, D = (e, n, r) => n ? e.resolve ? e.resolve(n, r) : t(n) ?? r : r, O = (e) => {
|
|
92
|
+
let { area: t, theme: i } = e, o = t.x + t.width / 2, s = t.y + t.height / 2, c = Math.max(0, Math.min(t.width, t.height) / 2 - 6);
|
|
93
|
+
return {
|
|
94
|
+
nodes: [{
|
|
95
|
+
kind: "sector",
|
|
96
|
+
cx: o,
|
|
97
|
+
cy: s,
|
|
98
|
+
r0: c * .66,
|
|
99
|
+
r1: c,
|
|
100
|
+
a0: 0,
|
|
101
|
+
a1: a,
|
|
102
|
+
pad: 0,
|
|
103
|
+
corner: 0,
|
|
104
|
+
fill: n(i.grid, .8)
|
|
105
|
+
}, {
|
|
106
|
+
kind: "text",
|
|
107
|
+
x: o,
|
|
108
|
+
y: s,
|
|
109
|
+
text: "No data",
|
|
110
|
+
font: r(i, 12),
|
|
111
|
+
color: n(i.textMuted),
|
|
112
|
+
align: "center",
|
|
113
|
+
baseline: "middle"
|
|
114
|
+
}],
|
|
115
|
+
items: [],
|
|
116
|
+
dim: 1,
|
|
117
|
+
empty: !0
|
|
118
|
+
};
|
|
119
|
+
};
|
|
120
|
+
//#endregion
|
|
121
|
+
export { a as TAU, s as clamp, S as contrastRatio, f as defaultFormat, d as easeOutCubic, h as ellipsize, O as emptyLayout, o as estimateText, l as finite, p as formatPercent, w as inkOn, m as inset, x as over, c as positive, E as readableFill, b as relativeLuminance, D as resolveWith, u as sum, T as textOn, g as uniqueKeys };
|
|
122
|
+
|
|
123
|
+
//# sourceMappingURL=scene.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"scene.js","names":["TAU","estimateText","size","f","text","clamp","v","lo","hi","positive","finite","fallback","sum","s","values","easeOutCubic","t","defaultFormat","formatCompact","value","formatPercent","p","inset","top","padding","right","bottom","left","rect","ellipsize","measure","font","max","mid","uniqueKeys","seen","names","name","LIGHT_INK","DARK_INK","channel","relativeLuminance","c","over","a","contrastRatio","ink","fill","b","WHITE","inkOn","solid","backdrop","light","dark","toCss","textOn","readableFill","best","target","toward","limit","next","mix","resolveWith","css","theme","parseColor","emptyLayout","cx","area","cy","r1"],"sources":["../../../../../charts/src/engine/shapes/scene.ts"],"sourcesContent":["// Drawable scene of a shape chart: resolved geometry, colors and texts,\n// produced by the (DOM-free) layouts and consumed by draw / hit testing.\n\nimport { mix, parseColor, toCss, type Rgba } from \"../color\";\nimport { formatCompact } from \"../format\";\nimport { font } from \"../overlay\";\nimport type { ChartTheme } from \"../theme\";\nimport type { ChartPadding } from \"../types\";\nimport type { ShapeChartType } from \"./types\";\n\nexport const TAU = Math.PI * 2;\n\n/** Rectangle in CSS pixels */\nexport interface ShapeRect {\n x: number;\n y: number;\n width: number;\n height: number;\n}\n\ninterface NodeBase {\n /** Index of the item the node belongs to (hover, dimming); none for decorations */\n hit?: number;\n /** Opacity multiplier */\n alpha?: number;\n /** Offset applied while the node's item is hovered (pie slices pop out) */\n shift?: [number, number];\n}\n\n/** Annular sector (pie slice, donut segment, ring) */\nexport interface SectorNode extends NodeBase {\n kind: \"sector\";\n cx: number;\n cy: number;\n r0: number;\n r1: number;\n /** Canvas angles (radians, clockwise from 3 o'clock) */\n a0: number;\n a1: number;\n /** Gap with the neighbours, in pixels */\n pad: number;\n /** Corner radius, in pixels */\n corner: number;\n fill: string;\n}\n\n/** Polygon (radar grid / series, funnel stage); `hole` is cut out */\nexport interface PolygonNode extends NodeBase {\n kind: \"polygon\";\n /** Flat x, y list */\n points: number[];\n hole?: number[];\n fill?: string;\n stroke?: string;\n lineWidth?: number;\n /** Corner radius, in pixels */\n radius?: number;\n /** Fill / stroke width when hovered */\n hoverFill?: string;\n hoverLineWidth?: number;\n /** Lightens the shape when hovered */\n brighten?: boolean;\n}\n\nexport interface RectNode extends NodeBase {\n kind: \"rect\";\n x: number;\n y: number;\n width: number;\n height: number;\n radius: number;\n fill: string;\n brighten?: boolean;\n}\n\n/** Stroked arc (gauge track / value) */\nexport interface ArcNode extends NodeBase {\n kind: \"arc\";\n cx: number;\n cy: number;\n r: number;\n a0: number;\n a1: number;\n width: number;\n color: string;\n cap: \"round\" | \"butt\";\n}\n\n/** Dot; without fill nor stroke it is only a hit area */\nexport interface CircleNode extends NodeBase {\n kind: \"circle\";\n cx: number;\n cy: number;\n r: number;\n fill?: string;\n stroke?: string;\n lineWidth?: number;\n /** Radar: indicator of the vertex */\n indicator?: number;\n /** Radius and halo color when the vertex is hovered */\n hoverR?: number;\n halo?: string;\n}\n\nexport interface LineNode extends NodeBase {\n kind: \"line\";\n points: number[];\n color: string;\n width: number;\n dash?: number[];\n}\n\nexport interface TextNode extends NodeBase {\n kind: \"text\";\n x: number;\n y: number;\n text: string;\n font: string;\n color: string;\n align: \"left\" | \"center\" | \"right\";\n baseline: \"top\" | \"middle\" | \"bottom\" | \"alphabetic\";\n /** Radar: indicator of the label */\n indicator?: number;\n hoverColor?: string;\n hoverFont?: string;\n}\n\n/** Radar: dashed guide from the center to the hovered indicator */\nexport interface GuideNode extends NodeBase {\n kind: \"guide\";\n cx: number;\n cy: number;\n /** End of each spoke */\n ends: [number, number][];\n color: string;\n}\n\nexport type ShapeNode =\n | SectorNode\n | PolygonNode\n | RectNode\n | ArcNode\n | CircleNode\n | LineNode\n | TextNode\n | GuideNode;\n\n/** A row of the default tooltip */\nexport interface ShapeTooltipRow {\n name: string;\n value: string;\n color?: string;\n strong?: boolean;\n}\n\n/** Something the pointer / keyboard can focus */\nexport interface ShapeItem {\n index: number;\n name: string;\n value: number;\n percent: number;\n /** `percent` formatted for screen readers (`percentFormat`) */\n share?: string;\n color: string;\n path?: string[];\n /** Anchor of the tooltip when focused with the keyboard */\n x: number;\n y: number;\n /** Rows of the default tooltip */\n rows: ShapeTooltipRow[];\n /** Radar: one entry per indicator */\n indicators?: {\n name: string;\n value: number;\n percent: number;\n x: number;\n y: number;\n }[];\n}\n\n/** What is hovered: an item (and a radar indicator) */\nexport interface ShapeHover {\n index: number;\n indicator?: number;\n}\n\nexport interface ShapeLegendEntry {\n /** Index passed to `toggle` */\n index: number;\n name: string;\n color: string;\n hidden: boolean;\n}\n\nexport interface ShapeScene {\n type: ShapeChartType;\n /** Size of the whole drawing */\n width: number;\n height: number;\n nodes: ShapeNode[];\n /** Focusable items, in keyboard order */\n items: ShapeItem[];\n /** Opacity of the other marks while one is hovered */\n dim: number;\n /** Entry animation of funnels / treemaps: fade and scale around a point */\n enter?: { alpha: number; scale: number; cx: number; cy: number };\n /** Radar geometry used by hit testing (and to keep the tooltip off the labels) */\n radar?: {\n cx: number;\n cy: number;\n radius: number;\n angles: number[];\n series: { index: number; points: number[] }[];\n /** Boxes of the indicator labels */\n labels?: ShapeRect[];\n };\n /** No data to draw (placeholder shown) */\n empty: boolean;\n}\n\n/** Measures a text in a CSS font */\nexport type MeasureText = (text: string, font: string) => number;\n\n/** Approximate width of a text without a canvas (tests, SSR) */\nexport const estimateText: MeasureText = (text, f) => {\n const size = /(\\d+(?:\\.\\d+)?)px/.exec(f);\n return text.length * (size ? Number(size[1]) : 12) * 0.6;\n};\n\n/** What the layouts of every type get */\nexport interface LayoutContext {\n theme: ChartTheme;\n measure: MeasureText;\n hidden: ReadonlySet<number>;\n /** Entry progress, eased (1 when done) */\n enter: number;\n /** Displayed (animated) value of a key */\n value(key: string, target: number): number;\n format(value: number): string;\n /** Formats a share (0-1): `percentFormat` or one decimal */\n percent(share: number): string;\n /** Color of the `i`-th mark (custom `color` or the palette) */\n color(css: string | undefined, i: number): Rgba;\n /** Drawing area, padding excluded */\n area: ShapeRect;\n}\n\nexport type LayoutResult = Omit<ShapeScene, \"type\" | \"width\" | \"height\">;\n\nexport const clamp = (v: number, lo: number, hi: number) =>\n v < lo ? lo : v > hi ? hi : v;\n\n/** Non-negative finite number */\nexport const positive = (v: number | undefined) =>\n typeof v === \"number\" && Number.isFinite(v) && v > 0 ? v : 0;\n\nexport const finite = (v: number | undefined, fallback = 0) =>\n typeof v === \"number\" && Number.isFinite(v) ? v : fallback;\n\nexport const sum = (values: readonly number[]) => {\n let s = 0;\n for (const v of values) s += v;\n return s;\n};\n\nexport const easeOutCubic = (t: number) => 1 - Math.pow(1 - clamp(t, 0, 1), 3);\n\nexport const defaultFormat = (value: number) => formatCompact(value);\n\n/** Share 0-1 as a percent with one decimal: `0.4` -> `40.0%` */\nexport const formatPercent = (p: number) =>\n Number.isFinite(p) ? `${(p * 100).toFixed(1)}%` : \"–\";\n\nexport const inset = (rect: ShapeRect, padding?: ChartPadding): ShapeRect => {\n const top = padding?.top ?? 8;\n const right = padding?.right ?? 8;\n const bottom = padding?.bottom ?? 8;\n const left = padding?.left ?? 8;\n return {\n x: rect.x + left,\n y: rect.y + top,\n width: Math.max(0, rect.width - left - right),\n height: Math.max(0, rect.height - top - bottom),\n };\n};\n\n/** Shortens a text with an ellipsis so it fits in `max` pixels (\"\" if nothing fits) */\nexport const ellipsize = (\n text: string,\n max: number,\n font: string,\n measure: MeasureText,\n): string => {\n if (measure(text, font) <= max) return text;\n if (measure(\"…\", font) > max) return \"\";\n let lo = 0;\n let hi = text.length;\n while (lo < hi) {\n const mid = (lo + hi + 1) >> 1;\n if (measure(text.slice(0, mid) + \"…\", font) <= max) lo = mid;\n else hi = mid - 1;\n }\n return lo ? text.slice(0, lo).trimEnd() + \"…\" : \"\";\n};\n\n/** Stable keys of named values: the name, `name#2` for duplicates */\nexport const uniqueKeys = (names: readonly string[]) => {\n const seen = new Map<string, number>();\n return names.map((name) => {\n const n = (seen.get(name) ?? 0) + 1;\n seen.set(name, n);\n return n === 1 ? name : `${name}#${n}`;\n });\n};\n\nconst LIGHT_INK: Rgba = [1, 1, 1, 0.96];\nconst DARK_INK: Rgba = [15 / 255, 23 / 255, 42 / 255, 0.88];\n\nconst channel = (v: number) =>\n v <= 0.04045 ? v / 12.92 : Math.pow((v + 0.055) / 1.055, 2.4);\n\n/** WCAG relative luminance of an opaque color */\nexport const relativeLuminance = (c: Rgba) =>\n 0.2126 * channel(c[0]) + 0.7152 * channel(c[1]) + 0.0722 * channel(c[2]);\n\n/** `top` composited over the opaque `bottom` */\nexport const over = (top: Rgba, bottom: Rgba): Rgba => {\n const a = clamp(top[3], 0, 1);\n return [\n top[0] * a + bottom[0] * (1 - a),\n top[1] * a + bottom[1] * (1 - a),\n top[2] * a + bottom[2] * (1 - a),\n 1,\n ];\n};\n\n/** WCAG contrast ratio (1-21) of `ink` drawn on the opaque `fill` */\nexport const contrastRatio = (ink: Rgba, fill: Rgba) => {\n const a = relativeLuminance(over(ink, fill));\n const b = relativeLuminance(fill);\n return (Math.max(a, b) + 0.05) / (Math.min(a, b) + 0.05);\n};\n\nconst WHITE: Rgba = [1, 1, 1, 1];\n\n/** Light or dark ink, whichever contrasts more with the fill, and its contrast */\nexport const inkOn = (\n fill: Rgba,\n backdrop: Rgba = WHITE,\n): { ink: Rgba; css: string; contrast: number } => {\n const solid = over(fill, over(backdrop, WHITE));\n const light = contrastRatio(LIGHT_INK, solid);\n const dark = contrastRatio(DARK_INK, solid);\n return light >= dark\n ? { ink: LIGHT_INK, css: toCss(LIGHT_INK), contrast: light }\n : { ink: DARK_INK, css: toCss(DARK_INK), contrast: dark };\n};\n\n/** Readable text color on a fill (WCAG contrast) */\nexport const textOn = (fill: Rgba, backdrop?: Rgba) =>\n inkOn(fill, backdrop).css;\n\n/**\n * Fill adjusted so that its best ink reaches `target` contrast: darkened\n * under white text, lightened under dark text (at most `limit` of the way)\n */\nexport const readableFill = (fill: Rgba, target = 4.5, limit = 0.3): Rgba => {\n let best = inkOn(fill);\n if (best.contrast >= target) return fill;\n const toward: Rgba =\n best.ink === LIGHT_INK ? [0, 0, 0, fill[3]] : [1, 1, 1, fill[3]];\n for (let t = 0.04; t <= limit + 1e-9; t += 0.04) {\n const next = mix(fill, toward, t);\n best = inkOn(next);\n if (best.contrast >= target) return next;\n }\n return mix(fill, toward, limit);\n};\n\n/** Resolves a custom color with the theme resolver (static parsing otherwise) */\nexport const resolveWith = (\n theme: ChartTheme,\n css: string | undefined,\n fallback: Rgba,\n): Rgba => {\n if (!css) return fallback;\n return theme.resolve\n ? theme.resolve(css, fallback)\n : (parseColor(css) ?? fallback);\n};\n\n/** Placeholder of a chart without data: a muted ring and \"No data\" */\nexport const emptyLayout = (c: LayoutContext): LayoutResult => {\n const { area, theme } = c;\n const cx = area.x + area.width / 2;\n const cy = area.y + area.height / 2;\n const r1 = Math.max(0, Math.min(area.width, area.height) / 2 - 6);\n return {\n nodes: [\n {\n kind: \"sector\",\n cx,\n cy,\n r0: r1 * 0.66,\n r1,\n a0: 0,\n a1: TAU,\n pad: 0,\n corner: 0,\n fill: toCss(theme.grid, 0.8),\n },\n {\n kind: \"text\",\n x: cx,\n y: cy,\n text: \"No data\",\n font: font(theme, 12),\n color: toCss(theme.textMuted),\n align: \"center\",\n baseline: \"middle\",\n },\n ],\n items: [],\n dim: 1,\n empty: true,\n };\n};\n"],"mappings":"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"}
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
const e=require("../color.cjs"),t=require("../overlay.cjs"),n=require("./scene.cjs");var r=20,i=(e,t)=>{let r=e.map(()=>({x:t.x,y:t.y,width:0,height:0})),i=n.sum(e.map(e=>Math.max(0,e)));if(i<=0||t.width<=0||t.height<=0)return r;let a=t.width*t.height/i,o=e.map(e=>Math.max(0,e)*a),{x:s,y:c,width:l,height:u}=t,d=(e,t,n,r)=>{let i=e*e,a=r*r;return Math.max(a*n/i,i/(a*t))},f=(e,t)=>{if(l>=u){let n=u>0?Math.min(l,t/u):0,i=c;for(let t of e){let e=n>0?o[t]/n:0;r[t]={x:s,y:i,width:n,height:e},i+=e}s+=n,l=Math.max(0,l-n)}else{let n=l>0?Math.min(u,t/l):0,i=s;for(let t of e){let e=n>0?o[t]/n:0;r[t]={x:i,y:c,width:e,height:n},i+=e}c+=n,u=Math.max(0,u-n)}},p=[],m=0,h=1/0,g=0;return o.forEach((e,t)=>{if(!(e<=0)){if(p.length){let t=Math.min(l,u);d(m+e,Math.min(h,e),Math.max(g,e),t)>d(m,h,g,t)&&(f(p,m),p=[],m=0,h=1/0,g=0)}p.push(t),m+=e,h=Math.min(h,e),g=Math.max(g,e)}}),p.length&&f(p,m),r},a=(e,t)=>{let r=0,i=(e,a,o,s)=>{let c=n.uniqueKeys(e.map(e=>e.name));return e.map((e,l)=>{let u=o.length?s:l,d=`${a}/${c[l]}`,f=[...o,e.name];if(e.children?.length){let t=i(e.children,d,f,u);return{node:e,key:d,path:f,top:u,leaf:-1,target:n.sum(t.map(e=>e.target)),children:t}}return{node:e,key:d,path:f,top:u,leaf:r++,target:t.has(u)?0:n.positive(e.value),children:[]}})};return i(e.data,``,[],0)},o=(e,t,n)=>{let r=e=>e.forEach(e=>{e.children.length?r(e.children):n.set(e.key,e.target)});r(a(e,t))},s=(e,t)=>({x:e.x+t,y:e.y+t,width:Math.max(0,e.width-2*t),height:Math.max(0,e.height-2*t)}),c=(o,c)=>{let{theme:l,area:u,measure:d,hidden:f}=c,p=a(o,f),m=n.sum(p.map(e=>e.target)),h=new Map,g=e=>{let t=e.children.length?n.sum(e.children.map(g)):Math.max(0,c.value(e.key,e.target));return h.set(e,t),t},_=n.sum(p.map(g));if(m<=0&&_<=1e-9)return n.emptyLayout(c);let v=Math.max(0,n.finite(o.gap,2)),y=o.headers!==!1,b=t.font(l,12,500),x=t.font(l,11),S=t.font(l,11,600),C=[],w=[],T=n.relativeLuminance(l.background)<.2,E=(t,a,o)=>{let u=t.filter(e=>(h.get(e)??0)>1e-9).sort((e,t)=>(h.get(t)??0)-(h.get(e)??0)),f=i(u.map(e=>h.get(e)??0),a),p=Math.min(.14,.5/Math.max(1,u.length-1));u.forEach((t,i)=>{let a=s(f[i],v/2);if(a.width<1||a.height<1)return;let u=o?t.node.color?n.resolveWith(l,t.node.color,o):e.mix(o,l.background,i*p):c.color(t.node.color,t.top);if(t.children.length){let i=a;if(y&&a.height>34&&a.width>36){C.push({kind:`rect`,x:a.x,y:a.y,width:a.width,height:a.height,radius:4,fill:e.toCss(u,.14)});let o=n.ellipsize(t.node.name,a.width-12,S,d);o&&C.push({kind:`text`,x:a.x+6,y:a.y+r/2+1,text:o,font:S,color:e.toCss(l.text,.85),align:`left`,baseline:`middle`}),i={x:a.x+2,y:a.y+r,width:a.width-4,height:a.height-r-2}}E(t.children,i,u);return}let h=n.readableFill(T?e.mix(u,l.background,.18):u),g=e.toCss(h);if(C.push({kind:`rect`,x:a.x,y:a.y,width:a.width,height:a.height,radius:Math.min(4,a.width/2,a.height/2),fill:g,hit:t.leaf,brighten:!0}),a.width>=36&&a.height>=22){let e=n.textOn(h),r=n.ellipsize(t.node.name,a.width-12,b,d);r&&C.push({kind:`text`,x:a.x+6,y:a.y+6,text:r,font:b,color:e,align:`left`,baseline:`top`,hit:t.leaf});let i=c.format(t.target);r&&a.height>=38&&d(i,x)<=a.width-12&&C.push({kind:`text`,x:a.x+6,y:a.y+22,text:i,font:x,color:e,align:`left`,baseline:`top`,hit:t.leaf})}if(t.target>0){let e=m>0?t.target/m:0;w.push({index:t.leaf,name:t.node.name,value:t.target,percent:e,share:c.percent(e),color:g,path:t.path,x:a.x+a.width/2,y:a.y+a.height/2,rows:[{name:`Value`,value:c.format(t.target)},{name:`Share`,value:c.percent(e)}]})}})};E(p,u,null),w.sort((e,t)=>e.index-t.index);let D=n.clamp(c.enter,0,1);return{nodes:C,items:w,dim:.55,empty:!1,...D<1?{enter:{alpha:D,scale:.94+.06*D,cx:u.x+u.width/2,cy:u.y+u.height/2}}:{}}};exports.layoutTreemap=c,exports.squarify=i,exports.treemapValues=o;
|
|
2
|
+
//# sourceMappingURL=treemap.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"treemap.cjs","names":["sum","uniqueKeys","positive","emptyLayout","finite","font","relativeLuminance","resolveWith","mix","toCss","ellipsize","readableFill","textOn","clamp","require_color","require_overlay","require_scene","HEADER","squarify","out","values","rect","total","v","scale","areas","w","h","worst","s2","s","side2","side","max","min","place","cw","yy","y","i","row","hh","rh","xx","x","ww","rowSum","rowMin","rowMax","a","build","leafCount","walk","keys","nodes","nd","t","parentPath","top","j","key","parentKey","path","node","children","ch","hidden","o","treemapValues","visit","b","shrink","r","d","layoutTreemap","tree","rootTotal","shown","measureShown","shownTotal","gap","headers","nameFont","theme","valueFont","headerFont","items","dark","level","sorted","list","rects","step","cell","color","parentColor","content","title","measure","fill","css","ink","name","value","percent","area","enter"],"sources":["../../../../../charts/src/engine/shapes/treemap.ts"],"sourcesContent":["// Treemap layout: squarified rectangles, parent headers, a palette color per\n// top-level node and lighter shades for its children.\n\nimport { mix, toCss, type Rgba } from \"../color\";\nimport { font } from \"../overlay\";\nimport {\n clamp,\n ellipsize,\n emptyLayout,\n finite,\n positive,\n readableFill,\n relativeLuminance,\n resolveWith,\n sum,\n textOn,\n uniqueKeys,\n type LayoutContext,\n type LayoutResult,\n type ShapeItem,\n type ShapeNode,\n type ShapeRect,\n} from \"./scene\";\nimport type { TreemapChartOptions, TreemapNode } from \"./types\";\n\nconst HEADER = 20;\n\n/**\n * Squarified treemap (Bruls et al.): rectangles of areas proportional to\n * `values` (best sorted descending) filling `rect`, with aspect ratios close to 1.\n */\nexport const squarify = (\n values: readonly number[],\n rect: ShapeRect,\n): ShapeRect[] => {\n const out: ShapeRect[] = values.map(() => ({\n x: rect.x,\n y: rect.y,\n width: 0,\n height: 0,\n }));\n const total = sum(values.map((v) => Math.max(0, v)));\n if (total <= 0 || rect.width <= 0 || rect.height <= 0) return out;\n const scale = (rect.width * rect.height) / total;\n const areas = values.map((v) => Math.max(0, v) * scale);\n let { x, y, width: w, height: h } = rect;\n\n const worst = (s: number, min: number, max: number, side: number) => {\n const s2 = s * s;\n const side2 = side * side;\n return Math.max((side2 * max) / s2, s2 / (side2 * min));\n };\n const place = (row: number[], s: number) => {\n if (w >= h) {\n const cw = h > 0 ? Math.min(w, s / h) : 0;\n let yy = y;\n for (const i of row) {\n const hh = cw > 0 ? areas[i] / cw : 0;\n out[i] = { x, y: yy, width: cw, height: hh };\n yy += hh;\n }\n x += cw;\n w = Math.max(0, w - cw);\n } else {\n const rh = w > 0 ? Math.min(h, s / w) : 0;\n let xx = x;\n for (const i of row) {\n const ww = rh > 0 ? areas[i] / rh : 0;\n out[i] = { x: xx, y, width: ww, height: rh };\n xx += ww;\n }\n y += rh;\n h = Math.max(0, h - rh);\n }\n };\n\n let row: number[] = [];\n let rowSum = 0;\n let rowMin = Infinity;\n let rowMax = 0;\n areas.forEach((a, i) => {\n if (a <= 0) return;\n if (row.length) {\n const side = Math.min(w, h);\n const next = worst(\n rowSum + a,\n Math.min(rowMin, a),\n Math.max(rowMax, a),\n side,\n );\n if (next > worst(rowSum, rowMin, rowMax, side)) {\n place(row, rowSum);\n row = [];\n rowSum = 0;\n rowMin = Infinity;\n rowMax = 0;\n }\n }\n row.push(i);\n rowSum += a;\n rowMin = Math.min(rowMin, a);\n rowMax = Math.max(rowMax, a);\n });\n if (row.length) place(row, rowSum);\n return out;\n};\n\ninterface Built {\n node: TreemapNode;\n key: string;\n path: string[];\n top: number;\n /** Index in the flattened leaves (leaves only) */\n leaf: number;\n target: number;\n children: Built[];\n}\n\n/** Tree with the target values; hidden top-level nodes count 0 */\nconst build = (\n o: TreemapChartOptions,\n hidden: ReadonlySet<number>,\n): Built[] => {\n let leafCount = 0;\n const walk = (\n nodes: readonly TreemapNode[],\n parentKey: string,\n parentPath: string[],\n top: number,\n ): Built[] => {\n const keys = uniqueKeys(nodes.map((nd) => nd.name));\n return nodes.map((node, j) => {\n const t = parentPath.length ? top : j;\n const key = `${parentKey}/${keys[j]}`;\n const path = [...parentPath, node.name];\n if (node.children?.length) {\n const children = walk(node.children, key, path, t);\n return {\n node,\n key,\n path,\n top: t,\n leaf: -1,\n target: sum(children.map((ch) => ch.target)),\n children,\n };\n }\n return {\n node,\n key,\n path,\n top: t,\n leaf: leafCount++,\n target: hidden.has(t) ? 0 : positive(node.value),\n children: [],\n };\n });\n };\n return walk(o.data, \"\", [], 0);\n};\n\nexport const treemapValues = (\n o: TreemapChartOptions,\n hidden: ReadonlySet<number>,\n out: Map<string, number>,\n) => {\n const visit = (nodes: Built[]) =>\n nodes.forEach((b) => {\n if (b.children.length) visit(b.children);\n else out.set(b.key, b.target);\n });\n visit(build(o, hidden));\n};\n\n/** Leaves in the flattened order (the hover / click `index`) */\nexport const treemapLeaves = (data: readonly TreemapNode[]) => {\n const leaves: { node: TreemapNode; path: string[] }[] = [];\n const visit = (nodes: readonly TreemapNode[], path: string[]) =>\n nodes.forEach((node) => {\n const p = [...path, node.name];\n if (node.children?.length) visit(node.children, p);\n else leaves.push({ node, path: p });\n });\n visit(data, []);\n return leaves;\n};\n\nconst shrink = (r: ShapeRect, d: number): ShapeRect => ({\n x: r.x + d,\n y: r.y + d,\n width: Math.max(0, r.width - 2 * d),\n height: Math.max(0, r.height - 2 * d),\n});\n\nexport const layoutTreemap = (\n o: TreemapChartOptions,\n c: LayoutContext,\n): LayoutResult => {\n const { theme, area, measure, hidden } = c;\n const tree = build(o, hidden);\n const rootTotal = sum(tree.map((b) => b.target));\n // displayed (animated) values\n const shown = new Map<Built, number>();\n const measureShown = (b: Built): number => {\n const v = b.children.length\n ? sum(b.children.map(measureShown))\n : Math.max(0, c.value(b.key, b.target));\n shown.set(b, v);\n return v;\n };\n const shownTotal = sum(tree.map(measureShown));\n if (rootTotal <= 0 && shownTotal <= 1e-9) return emptyLayout(c);\n\n const gap = Math.max(0, finite(o.gap, 2));\n const headers = o.headers !== false;\n const nameFont = font(theme, 12, 500);\n const valueFont = font(theme, 11);\n const headerFont = font(theme, 11, 600);\n const nodes: ShapeNode[] = [];\n const items: ShapeItem[] = [];\n // dark themes: fills slightly toward the background so that labels read well\n const dark = relativeLuminance(theme.background) < 0.2;\n\n const level = (list: Built[], rect: ShapeRect, parentColor: Rgba | null) => {\n const sorted = list\n .filter((b) => (shown.get(b) ?? 0) > 1e-9)\n .sort((a, b) => (shown.get(b) ?? 0) - (shown.get(a) ?? 0));\n const rects = squarify(\n sorted.map((b) => shown.get(b) ?? 0),\n rect,\n );\n const step = Math.min(0.14, 0.5 / Math.max(1, sorted.length - 1));\n sorted.forEach((b, j) => {\n const cell = shrink(rects[j], gap / 2);\n if (cell.width < 1 || cell.height < 1) return;\n const color = parentColor\n ? b.node.color\n ? resolveWith(theme, b.node.color, parentColor)\n : mix(parentColor, theme.background, j * step)\n : c.color(b.node.color, b.top);\n if (b.children.length) {\n let content = cell;\n if (headers && cell.height > HEADER + 14 && cell.width > 36) {\n nodes.push({\n kind: \"rect\",\n x: cell.x,\n y: cell.y,\n width: cell.width,\n height: cell.height,\n radius: 4,\n fill: toCss(color, 0.14),\n });\n const title = ellipsize(\n b.node.name,\n cell.width - 12,\n headerFont,\n measure,\n );\n if (title)\n nodes.push({\n kind: \"text\",\n x: cell.x + 6,\n y: cell.y + HEADER / 2 + 1,\n text: title,\n font: headerFont,\n color: toCss(theme.text, 0.85),\n align: \"left\",\n baseline: \"middle\",\n });\n content = {\n x: cell.x + 2,\n y: cell.y + HEADER,\n width: cell.width - 4,\n height: cell.height - HEADER - 2,\n };\n }\n level(b.children, content, color);\n return;\n }\n const fill = readableFill(\n dark ? mix(color, theme.background, 0.18) : color,\n );\n const css = toCss(fill);\n nodes.push({\n kind: \"rect\",\n x: cell.x,\n y: cell.y,\n width: cell.width,\n height: cell.height,\n radius: Math.min(4, cell.width / 2, cell.height / 2),\n fill: css,\n hit: b.leaf,\n brighten: true,\n });\n if (cell.width >= 36 && cell.height >= 22) {\n const ink = textOn(fill);\n const name = ellipsize(b.node.name, cell.width - 12, nameFont, measure);\n if (name)\n nodes.push({\n kind: \"text\",\n x: cell.x + 6,\n y: cell.y + 6,\n text: name,\n font: nameFont,\n color: ink,\n align: \"left\",\n baseline: \"top\",\n hit: b.leaf,\n });\n const value = c.format(b.target);\n if (\n name &&\n cell.height >= 38 &&\n measure(value, valueFont) <= cell.width - 12\n )\n nodes.push({\n kind: \"text\",\n x: cell.x + 6,\n y: cell.y + 22,\n text: value,\n font: valueFont,\n color: ink,\n align: \"left\",\n baseline: \"top\",\n hit: b.leaf,\n });\n }\n if (b.target > 0) {\n const percent = rootTotal > 0 ? b.target / rootTotal : 0;\n items.push({\n index: b.leaf,\n name: b.node.name,\n value: b.target,\n percent,\n share: c.percent(percent),\n color: css,\n path: b.path,\n x: cell.x + cell.width / 2,\n y: cell.y + cell.height / 2,\n rows: [\n { name: \"Value\", value: c.format(b.target) },\n { name: \"Share\", value: c.percent(percent) },\n ],\n });\n }\n });\n };\n level(tree, area, null);\n items.sort((a, b) => a.index - b.index);\n\n const enter = clamp(c.enter, 0, 1);\n return {\n nodes,\n items,\n dim: 0.55,\n empty: false,\n ...(enter < 1\n ? {\n enter: {\n alpha: enter,\n scale: 0.94 + 0.06 * enter,\n cx: area.x + area.width / 2,\n cy: area.y + area.height / 2,\n },\n }\n : {}),\n };\n};\n"],"mappings":"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"}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { LayoutContext, LayoutResult, ShapeRect } from './scene.cjs';
|
|
2
|
+
import { TreemapChartOptions, TreemapNode } from './types.cjs';
|
|
3
|
+
/**
|
|
4
|
+
* Squarified treemap (Bruls et al.): rectangles of areas proportional to
|
|
5
|
+
* `values` (best sorted descending) filling `rect`, with aspect ratios close to 1.
|
|
6
|
+
*/
|
|
7
|
+
export declare const squarify: (values: readonly number[], rect: ShapeRect) => ShapeRect[];
|
|
8
|
+
export declare const treemapValues: (o: TreemapChartOptions, hidden: ReadonlySet<number>, out: Map<string, number>) => void;
|
|
9
|
+
/** Leaves in the flattened order (the hover / click `index`) */
|
|
10
|
+
export declare const treemapLeaves: (data: readonly TreemapNode[]) => {
|
|
11
|
+
node: TreemapNode;
|
|
12
|
+
path: string[];
|
|
13
|
+
}[];
|
|
14
|
+
export declare const layoutTreemap: (o: TreemapChartOptions, c: LayoutContext) => LayoutResult;
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { LayoutContext, LayoutResult, ShapeRect } from './scene.js';
|
|
2
|
+
import { TreemapChartOptions, TreemapNode } from './types.js';
|
|
3
|
+
/**
|
|
4
|
+
* Squarified treemap (Bruls et al.): rectangles of areas proportional to
|
|
5
|
+
* `values` (best sorted descending) filling `rect`, with aspect ratios close to 1.
|
|
6
|
+
*/
|
|
7
|
+
export declare const squarify: (values: readonly number[], rect: ShapeRect) => ShapeRect[];
|
|
8
|
+
export declare const treemapValues: (o: TreemapChartOptions, hidden: ReadonlySet<number>, out: Map<string, number>) => void;
|
|
9
|
+
/** Leaves in the flattened order (the hover / click `index`) */
|
|
10
|
+
export declare const treemapLeaves: (data: readonly TreemapNode[]) => {
|
|
11
|
+
node: TreemapNode;
|
|
12
|
+
path: string[];
|
|
13
|
+
}[];
|
|
14
|
+
export declare const layoutTreemap: (o: TreemapChartOptions, c: LayoutContext) => LayoutResult;
|