mviz 1.4.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +174 -0
- package/dist/charts/area.d.ts +14 -0
- package/dist/charts/area.d.ts.map +1 -0
- package/dist/charts/area.js +137 -0
- package/dist/charts/area.js.map +1 -0
- package/dist/charts/bar.d.ts +14 -0
- package/dist/charts/bar.d.ts.map +1 -0
- package/dist/charts/bar.js +191 -0
- package/dist/charts/bar.js.map +1 -0
- package/dist/charts/boxplot.d.ts +14 -0
- package/dist/charts/boxplot.d.ts.map +1 -0
- package/dist/charts/boxplot.js +79 -0
- package/dist/charts/boxplot.js.map +1 -0
- package/dist/charts/bubble.d.ts +14 -0
- package/dist/charts/bubble.d.ts.map +1 -0
- package/dist/charts/bubble.js +127 -0
- package/dist/charts/bubble.js.map +1 -0
- package/dist/charts/calendar.d.ts +14 -0
- package/dist/charts/calendar.d.ts.map +1 -0
- package/dist/charts/calendar.js +94 -0
- package/dist/charts/calendar.js.map +1 -0
- package/dist/charts/combo.d.ts +14 -0
- package/dist/charts/combo.d.ts.map +1 -0
- package/dist/charts/combo.js +163 -0
- package/dist/charts/combo.js.map +1 -0
- package/dist/charts/dumbbell.d.ts +17 -0
- package/dist/charts/dumbbell.d.ts.map +1 -0
- package/dist/charts/dumbbell.js +368 -0
- package/dist/charts/dumbbell.js.map +1 -0
- package/dist/charts/funnel.d.ts +14 -0
- package/dist/charts/funnel.d.ts.map +1 -0
- package/dist/charts/funnel.js +145 -0
- package/dist/charts/funnel.js.map +1 -0
- package/dist/charts/heatmap.d.ts +14 -0
- package/dist/charts/heatmap.d.ts.map +1 -0
- package/dist/charts/heatmap.js +202 -0
- package/dist/charts/heatmap.js.map +1 -0
- package/dist/charts/histogram.d.ts +14 -0
- package/dist/charts/histogram.d.ts.map +1 -0
- package/dist/charts/histogram.js +103 -0
- package/dist/charts/histogram.js.map +1 -0
- package/dist/charts/index.d.ts +40 -0
- package/dist/charts/index.d.ts.map +1 -0
- package/dist/charts/index.js +42 -0
- package/dist/charts/index.js.map +1 -0
- package/dist/charts/line.d.ts +14 -0
- package/dist/charts/line.d.ts.map +1 -0
- package/dist/charts/line.js +134 -0
- package/dist/charts/line.js.map +1 -0
- package/dist/charts/pie.d.ts +14 -0
- package/dist/charts/pie.d.ts.map +1 -0
- package/dist/charts/pie.js +75 -0
- package/dist/charts/pie.js.map +1 -0
- package/dist/charts/registry.d.ts +36 -0
- package/dist/charts/registry.d.ts.map +1 -0
- package/dist/charts/registry.js +55 -0
- package/dist/charts/registry.js.map +1 -0
- package/dist/charts/sankey.d.ts +14 -0
- package/dist/charts/sankey.d.ts.map +1 -0
- package/dist/charts/sankey.js +74 -0
- package/dist/charts/sankey.js.map +1 -0
- package/dist/charts/scatter.d.ts +14 -0
- package/dist/charts/scatter.d.ts.map +1 -0
- package/dist/charts/scatter.js +130 -0
- package/dist/charts/scatter.js.map +1 -0
- package/dist/charts/sparkline.d.ts +19 -0
- package/dist/charts/sparkline.d.ts.map +1 -0
- package/dist/charts/sparkline.js +154 -0
- package/dist/charts/sparkline.js.map +1 -0
- package/dist/charts/waterfall.d.ts +14 -0
- package/dist/charts/waterfall.d.ts.map +1 -0
- package/dist/charts/waterfall.js +232 -0
- package/dist/charts/waterfall.js.map +1 -0
- package/dist/charts/xmr.d.ts +14 -0
- package/dist/charts/xmr.d.ts.map +1 -0
- package/dist/charts/xmr.js +456 -0
- package/dist/charts/xmr.js.map +1 -0
- package/dist/cli.d.ts +12 -0
- package/dist/cli.d.ts.map +1 -0
- package/dist/cli.js +120 -0
- package/dist/cli.js.map +1 -0
- package/dist/components/alert.d.ts +10 -0
- package/dist/components/alert.d.ts.map +1 -0
- package/dist/components/alert.js +65 -0
- package/dist/components/alert.js.map +1 -0
- package/dist/components/big_value.d.ts +10 -0
- package/dist/components/big_value.d.ts.map +1 -0
- package/dist/components/big_value.js +78 -0
- package/dist/components/big_value.js.map +1 -0
- package/dist/components/delta.d.ts +10 -0
- package/dist/components/delta.d.ts.map +1 -0
- package/dist/components/delta.js +83 -0
- package/dist/components/delta.js.map +1 -0
- package/dist/components/empty_space.d.ts +10 -0
- package/dist/components/empty_space.d.ts.map +1 -0
- package/dist/components/empty_space.js +29 -0
- package/dist/components/empty_space.js.map +1 -0
- package/dist/components/index.d.ts +21 -0
- package/dist/components/index.d.ts.map +1 -0
- package/dist/components/index.js +23 -0
- package/dist/components/index.js.map +1 -0
- package/dist/components/note.d.ts +10 -0
- package/dist/components/note.d.ts.map +1 -0
- package/dist/components/note.js +66 -0
- package/dist/components/note.js.map +1 -0
- package/dist/components/registry.d.ts +24 -0
- package/dist/components/registry.d.ts.map +1 -0
- package/dist/components/registry.js +36 -0
- package/dist/components/registry.js.map +1 -0
- package/dist/components/table.d.ts +90 -0
- package/dist/components/table.d.ts.map +1 -0
- package/dist/components/table.js +610 -0
- package/dist/components/table.js.map +1 -0
- package/dist/components/text.d.ts +10 -0
- package/dist/components/text.d.ts.map +1 -0
- package/dist/components/text.js +46 -0
- package/dist/components/text.js.map +1 -0
- package/dist/components/textarea.d.ts +10 -0
- package/dist/components/textarea.d.ts.map +1 -0
- package/dist/components/textarea.js +79 -0
- package/dist/components/textarea.js.map +1 -0
- package/dist/core/colors.d.ts +45 -0
- package/dist/core/colors.d.ts.map +1 -0
- package/dist/core/colors.js +93 -0
- package/dist/core/colors.js.map +1 -0
- package/dist/core/css.d.ts +20 -0
- package/dist/core/css.d.ts.map +1 -0
- package/dist/core/css.js +97 -0
- package/dist/core/css.js.map +1 -0
- package/dist/core/exceptions.d.ts +59 -0
- package/dist/core/exceptions.d.ts.map +1 -0
- package/dist/core/exceptions.js +100 -0
- package/dist/core/exceptions.js.map +1 -0
- package/dist/core/formatting.d.ts +53 -0
- package/dist/core/formatting.d.ts.map +1 -0
- package/dist/core/formatting.js +491 -0
- package/dist/core/formatting.js.map +1 -0
- package/dist/core/index.d.ts +10 -0
- package/dist/core/index.d.ts.map +1 -0
- package/dist/core/index.js +10 -0
- package/dist/core/index.js.map +1 -0
- package/dist/core/serializer.d.ts +29 -0
- package/dist/core/serializer.d.ts.map +1 -0
- package/dist/core/serializer.js +84 -0
- package/dist/core/serializer.js.map +1 -0
- package/dist/core/themes.d.ts +138 -0
- package/dist/core/themes.d.ts.map +1 -0
- package/dist/core/themes.js +484 -0
- package/dist/core/themes.js.map +1 -0
- package/dist/core/version-check.d.ts +23 -0
- package/dist/core/version-check.d.ts.map +1 -0
- package/dist/core/version-check.js +163 -0
- package/dist/core/version-check.js.map +1 -0
- package/dist/generate_test_harness.d.ts +13 -0
- package/dist/generate_test_harness.d.ts.map +1 -0
- package/dist/generate_test_harness.js +35 -0
- package/dist/generate_test_harness.js.map +1 -0
- package/dist/index.d.ts +17 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +19 -0
- package/dist/index.js.map +1 -0
- package/dist/layout/converter.d.ts +22 -0
- package/dist/layout/converter.d.ts.map +1 -0
- package/dist/layout/converter.js +46 -0
- package/dist/layout/converter.js.map +1 -0
- package/dist/layout/csv.d.ts +15 -0
- package/dist/layout/csv.d.ts.map +1 -0
- package/dist/layout/csv.js +88 -0
- package/dist/layout/csv.js.map +1 -0
- package/dist/layout/dispatcher.d.ts +13 -0
- package/dist/layout/dispatcher.d.ts.map +1 -0
- package/dist/layout/dispatcher.js +47 -0
- package/dist/layout/dispatcher.js.map +1 -0
- package/dist/layout/index.d.ts +8 -0
- package/dist/layout/index.d.ts.map +1 -0
- package/dist/layout/index.js +8 -0
- package/dist/layout/index.js.map +1 -0
- package/dist/layout/parser.d.ts +19 -0
- package/dist/layout/parser.d.ts.map +1 -0
- package/dist/layout/parser.js +888 -0
- package/dist/layout/parser.js.map +1 -0
- package/dist/layout/templates.d.ts +32 -0
- package/dist/layout/templates.d.ts.map +1 -0
- package/dist/layout/templates.js +1016 -0
- package/dist/layout/templates.js.map +1 -0
- package/dist/types.d.ts +144 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +5 -0
- package/dist/types.js.map +1 -0
- package/dist/vitest.config.d.ts +3 -0
- package/dist/vitest.config.d.ts.map +1 -0
- package/dist/vitest.config.js +14 -0
- package/dist/vitest.config.js.map +1 -0
- package/package.json +79 -0
|
@@ -0,0 +1,368 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Dumbbell chart generator
|
|
3
|
+
*
|
|
4
|
+
* Dumbbell plots show comparisons between two values for each category,
|
|
5
|
+
* connected by a line with directional color-coding.
|
|
6
|
+
*/
|
|
7
|
+
import { COLORS, FONT_SIZE_TINY, DUMBBELL_SYMBOL_SIZE, DEFAULT_CHART_HEIGHT, getThemeColors, } from '../core/themes.js';
|
|
8
|
+
import { wrapHtml } from '../core/serializer.js';
|
|
9
|
+
import { inferFormat, getAxisFormatterJs } from '../core/formatting.js';
|
|
10
|
+
import { registerChart, registerOptions } from './registry.js';
|
|
11
|
+
// Directional colors
|
|
12
|
+
const POSITIVE_COLOR = COLORS.POSITIVE_GREEN;
|
|
13
|
+
const NEGATIVE_COLOR = COLORS.ERROR_RED;
|
|
14
|
+
const NEUTRAL_COLOR = '#888888';
|
|
15
|
+
// Dark mode variants
|
|
16
|
+
const POSITIVE_COLOR_DARK = '#6ed020';
|
|
17
|
+
const NEGATIVE_COLOR_DARK = '#e05040';
|
|
18
|
+
const NEUTRAL_COLOR_DARK = '#a0a0a0';
|
|
19
|
+
/**
|
|
20
|
+
* Get a nice floor value for axis
|
|
21
|
+
*/
|
|
22
|
+
function niceFloor(val, step) {
|
|
23
|
+
return Math.floor(val / step) * step;
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* Get a nice ceiling value for axis
|
|
27
|
+
*/
|
|
28
|
+
function niceCeil(val, step) {
|
|
29
|
+
return Math.ceil(val / step) * step;
|
|
30
|
+
}
|
|
31
|
+
/**
|
|
32
|
+
* Get a nice step size based on data range
|
|
33
|
+
*/
|
|
34
|
+
function getNiceStep(dataRange) {
|
|
35
|
+
if (dataRange <= 0)
|
|
36
|
+
return 1;
|
|
37
|
+
const magnitude = Math.pow(10, Math.floor(Math.log10(dataRange)));
|
|
38
|
+
const normalized = dataRange / magnitude;
|
|
39
|
+
if (normalized <= 2)
|
|
40
|
+
return magnitude / 5;
|
|
41
|
+
if (normalized <= 5)
|
|
42
|
+
return magnitude / 2;
|
|
43
|
+
return magnitude;
|
|
44
|
+
}
|
|
45
|
+
/**
|
|
46
|
+
* Build ECharts options for a dumbbell plot with directional coloring
|
|
47
|
+
*/
|
|
48
|
+
export function buildDumbbellOptions(spec) {
|
|
49
|
+
const data = (spec.data ?? []);
|
|
50
|
+
const categoryField = spec.category ?? 'category';
|
|
51
|
+
const startField = spec.start ?? 'start';
|
|
52
|
+
const endField = spec.end ?? 'end';
|
|
53
|
+
const startLabel = spec.startLabel ?? startField.replace(/_/g, ' ');
|
|
54
|
+
const endLabel = spec.endLabel ?? endField.replace(/_/g, ' ');
|
|
55
|
+
const theme = (spec.theme ?? 'light');
|
|
56
|
+
const higherIsBetter = spec.higherIsBetter ?? true;
|
|
57
|
+
const showValues = spec.showValues ?? true;
|
|
58
|
+
const colors = getThemeColors(theme);
|
|
59
|
+
const isDark = theme === 'dark';
|
|
60
|
+
// Get directional colors based on theme
|
|
61
|
+
const positiveColor = isDark ? POSITIVE_COLOR_DARK : POSITIVE_COLOR;
|
|
62
|
+
const negativeColor = isDark ? NEGATIVE_COLOR_DARK : NEGATIVE_COLOR;
|
|
63
|
+
const neutralColor = isDark ? NEUTRAL_COLOR_DARK : NEUTRAL_COLOR;
|
|
64
|
+
// Extract data
|
|
65
|
+
const categories = data.map((d) => String(d[categoryField] ?? ''));
|
|
66
|
+
const startValues = data.map((d) => (d[startField] ?? 0));
|
|
67
|
+
const endValues = data.map((d) => (d[endField] ?? 0));
|
|
68
|
+
// Determine color for each row
|
|
69
|
+
const rowColors = startValues.map((s, i) => {
|
|
70
|
+
const e = endValues[i];
|
|
71
|
+
if (s === e)
|
|
72
|
+
return neutralColor;
|
|
73
|
+
if (higherIsBetter) {
|
|
74
|
+
return e > s ? positiveColor : negativeColor;
|
|
75
|
+
}
|
|
76
|
+
return e < s ? positiveColor : negativeColor;
|
|
77
|
+
});
|
|
78
|
+
// Infer value format
|
|
79
|
+
const sampleValue = startValues[0] ?? 0;
|
|
80
|
+
const valueFormat = spec.format ?? inferFormat(startField, sampleValue);
|
|
81
|
+
const isCurrency = valueFormat?.includes('usd');
|
|
82
|
+
const axisFormatter = getAxisFormatterJs(valueFormat);
|
|
83
|
+
// Calculate axis limits
|
|
84
|
+
const allValues = [...startValues, ...endValues];
|
|
85
|
+
let xMin = spec.xMin;
|
|
86
|
+
let xMax = spec.xMax;
|
|
87
|
+
if (allValues.length > 0) {
|
|
88
|
+
const minVal = Math.min(...allValues);
|
|
89
|
+
const maxVal = Math.max(...allValues);
|
|
90
|
+
const dataRange = maxVal !== minVal ? maxVal - minVal : Math.max(Math.abs(maxVal), 1);
|
|
91
|
+
const step = getNiceStep(dataRange);
|
|
92
|
+
const padding = Math.max(dataRange * 0.15, step);
|
|
93
|
+
const rawMin = minVal - padding;
|
|
94
|
+
const rawMax = maxVal + padding;
|
|
95
|
+
if (xMin === undefined) {
|
|
96
|
+
xMin = minVal >= 0 ? Math.max(0, niceFloor(rawMin, step)) : niceFloor(rawMin, step);
|
|
97
|
+
}
|
|
98
|
+
if (xMax === undefined) {
|
|
99
|
+
xMax = niceCeil(rawMax, step);
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
// Value formatter for labels inside dots
|
|
103
|
+
const valueFormatterJs = `function(params) {
|
|
104
|
+
var v = params.value[0];
|
|
105
|
+
var abs = Math.abs(v);
|
|
106
|
+
var isCurrency = ${isCurrency ? 'true' : 'false'};
|
|
107
|
+
var prefix = isCurrency ? '$' : '';
|
|
108
|
+
if (abs >= 1000000) {
|
|
109
|
+
var val = v / 1000000;
|
|
110
|
+
var formatted = isCurrency ? Math.round(val) : (Math.abs(val) >= 10 ? Math.round(val) : val.toFixed(1));
|
|
111
|
+
return prefix + formatted + 'm';
|
|
112
|
+
}
|
|
113
|
+
if (abs >= 1000) {
|
|
114
|
+
var val = v / 1000;
|
|
115
|
+
var formatted = isCurrency ? Math.round(val) : (Math.abs(val) >= 10 ? Math.round(val) : val.toFixed(1));
|
|
116
|
+
return prefix + formatted + 'k';
|
|
117
|
+
}
|
|
118
|
+
return isCurrency ? prefix + Math.round(v) : v;
|
|
119
|
+
}`;
|
|
120
|
+
// Build line data for custom series
|
|
121
|
+
const lineData = startValues.map((s, i) => {
|
|
122
|
+
const e = endValues[i];
|
|
123
|
+
const c = rowColors[i];
|
|
124
|
+
const isNoChange = s === e ? 1 : 0;
|
|
125
|
+
return [i, s, e, c, isNoChange];
|
|
126
|
+
});
|
|
127
|
+
// Custom render function for connecting lines with arrows
|
|
128
|
+
const renderItemJs = `function(params, api) {
|
|
129
|
+
var categoryIndex = api.value(0);
|
|
130
|
+
var start = api.value(1);
|
|
131
|
+
var end = api.value(2);
|
|
132
|
+
var color = api.value(3);
|
|
133
|
+
var isNoChange = api.value(4);
|
|
134
|
+
var startCoord = api.coord([start, categoryIndex]);
|
|
135
|
+
var endCoord = api.coord([end, categoryIndex]);
|
|
136
|
+
|
|
137
|
+
var dx = endCoord[0] - startCoord[0];
|
|
138
|
+
var absDx = Math.abs(dx);
|
|
139
|
+
var dotRadius = ${Math.floor(DUMBBELL_SYMBOL_SIZE / 2)};
|
|
140
|
+
var arrowSize = 5;
|
|
141
|
+
var arrowWidth = 3;
|
|
142
|
+
|
|
143
|
+
if (isNoChange || absDx < 1) {
|
|
144
|
+
return null;
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
var dotDiameter = dotRadius * 2;
|
|
148
|
+
if (absDx < dotDiameter) {
|
|
149
|
+
return null;
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
var lineStartX = startCoord[0] + (dx > 0 ? dotRadius : -dotRadius);
|
|
153
|
+
var lineEndX = endCoord[0] - (dx > 0 ? dotRadius : -dotRadius);
|
|
154
|
+
var lineClearance = Math.abs(lineEndX - lineStartX);
|
|
155
|
+
|
|
156
|
+
if (lineClearance < arrowSize + 2) {
|
|
157
|
+
return {
|
|
158
|
+
type: 'line',
|
|
159
|
+
shape: {
|
|
160
|
+
x1: lineStartX,
|
|
161
|
+
y1: startCoord[1],
|
|
162
|
+
x2: lineEndX,
|
|
163
|
+
y2: endCoord[1]
|
|
164
|
+
},
|
|
165
|
+
style: {
|
|
166
|
+
stroke: color,
|
|
167
|
+
lineWidth: 2
|
|
168
|
+
}
|
|
169
|
+
};
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
var arrowTipX = lineEndX;
|
|
173
|
+
var arrowBaseX = arrowTipX - (dx > 0 ? arrowSize : -arrowSize);
|
|
174
|
+
|
|
175
|
+
return {
|
|
176
|
+
type: 'group',
|
|
177
|
+
children: [
|
|
178
|
+
{
|
|
179
|
+
type: 'line',
|
|
180
|
+
shape: {
|
|
181
|
+
x1: lineStartX,
|
|
182
|
+
y1: startCoord[1],
|
|
183
|
+
x2: arrowBaseX,
|
|
184
|
+
y2: endCoord[1]
|
|
185
|
+
},
|
|
186
|
+
style: {
|
|
187
|
+
stroke: color,
|
|
188
|
+
lineWidth: 2
|
|
189
|
+
}
|
|
190
|
+
},
|
|
191
|
+
{
|
|
192
|
+
type: 'polygon',
|
|
193
|
+
shape: {
|
|
194
|
+
points: [
|
|
195
|
+
[arrowTipX, endCoord[1]],
|
|
196
|
+
[arrowBaseX, endCoord[1] - arrowWidth],
|
|
197
|
+
[arrowBaseX, endCoord[1] + arrowWidth]
|
|
198
|
+
]
|
|
199
|
+
},
|
|
200
|
+
style: {
|
|
201
|
+
fill: color
|
|
202
|
+
}
|
|
203
|
+
}
|
|
204
|
+
]
|
|
205
|
+
};
|
|
206
|
+
}`;
|
|
207
|
+
const series = [
|
|
208
|
+
// Connecting lines with arrows
|
|
209
|
+
{
|
|
210
|
+
name: 'range',
|
|
211
|
+
type: 'custom',
|
|
212
|
+
renderItem: { _js_: renderItemJs },
|
|
213
|
+
encode: { x: [1, 2], y: 0 },
|
|
214
|
+
data: lineData,
|
|
215
|
+
z: 1,
|
|
216
|
+
},
|
|
217
|
+
];
|
|
218
|
+
// Start dots - outline style
|
|
219
|
+
const startData = startValues.map((v, i) => ({
|
|
220
|
+
value: [v, i],
|
|
221
|
+
itemStyle: {
|
|
222
|
+
color: colors.background,
|
|
223
|
+
borderColor: rowColors[i],
|
|
224
|
+
borderWidth: 2,
|
|
225
|
+
opacity: 1,
|
|
226
|
+
},
|
|
227
|
+
label: {
|
|
228
|
+
show: showValues,
|
|
229
|
+
position: 'inside',
|
|
230
|
+
fontSize: FONT_SIZE_TINY - 2,
|
|
231
|
+
fontWeight: 'bold',
|
|
232
|
+
color: rowColors[i],
|
|
233
|
+
formatter: { _js_: valueFormatterJs },
|
|
234
|
+
},
|
|
235
|
+
}));
|
|
236
|
+
series.push({
|
|
237
|
+
name: startLabel,
|
|
238
|
+
type: 'scatter',
|
|
239
|
+
data: startData,
|
|
240
|
+
symbolSize: DUMBBELL_SYMBOL_SIZE,
|
|
241
|
+
z: 10,
|
|
242
|
+
});
|
|
243
|
+
// End dots - filled style
|
|
244
|
+
const endData = endValues.map((v, i) => ({
|
|
245
|
+
value: [v, i],
|
|
246
|
+
itemStyle: {
|
|
247
|
+
color: rowColors[i],
|
|
248
|
+
opacity: 1,
|
|
249
|
+
},
|
|
250
|
+
label: {
|
|
251
|
+
show: showValues,
|
|
252
|
+
position: 'inside',
|
|
253
|
+
fontSize: FONT_SIZE_TINY - 2,
|
|
254
|
+
fontWeight: 'bold',
|
|
255
|
+
color: '#ffffff',
|
|
256
|
+
formatter: { _js_: valueFormatterJs },
|
|
257
|
+
},
|
|
258
|
+
}));
|
|
259
|
+
series.push({
|
|
260
|
+
name: endLabel,
|
|
261
|
+
type: 'scatter',
|
|
262
|
+
data: endData,
|
|
263
|
+
symbolSize: DUMBBELL_SYMBOL_SIZE,
|
|
264
|
+
z: 10,
|
|
265
|
+
});
|
|
266
|
+
// Tooltip formatter
|
|
267
|
+
const tooltipFormatterJs = `function(params) {
|
|
268
|
+
if (params.seriesName === 'range') return '';
|
|
269
|
+
var cat = ${JSON.stringify(categories)}[params.data.value ? params.data.value[1] : params.data[1]];
|
|
270
|
+
var val = params.data.value ? params.data.value[0] : params.data[0];
|
|
271
|
+
return '<strong>' + cat + '</strong><br/>' + params.seriesName + ': ' + val;
|
|
272
|
+
}`;
|
|
273
|
+
return {
|
|
274
|
+
backgroundColor: 'transparent',
|
|
275
|
+
animation: false,
|
|
276
|
+
tooltip: {
|
|
277
|
+
trigger: 'item',
|
|
278
|
+
backgroundColor: colors.paper,
|
|
279
|
+
borderColor: colors.border,
|
|
280
|
+
textStyle: { color: colors.text },
|
|
281
|
+
formatter: { _js_: tooltipFormatterJs },
|
|
282
|
+
},
|
|
283
|
+
legend: {
|
|
284
|
+
show: true,
|
|
285
|
+
data: [
|
|
286
|
+
{
|
|
287
|
+
name: startLabel,
|
|
288
|
+
icon: 'circle',
|
|
289
|
+
itemStyle: {
|
|
290
|
+
color: colors.background,
|
|
291
|
+
borderColor: colors.textSecondary,
|
|
292
|
+
borderWidth: 2,
|
|
293
|
+
},
|
|
294
|
+
},
|
|
295
|
+
{
|
|
296
|
+
name: endLabel,
|
|
297
|
+
icon: 'circle',
|
|
298
|
+
itemStyle: {
|
|
299
|
+
color: colors.textSecondary,
|
|
300
|
+
},
|
|
301
|
+
},
|
|
302
|
+
],
|
|
303
|
+
bottom: 0,
|
|
304
|
+
textStyle: { color: colors.textSecondary, fontSize: FONT_SIZE_TINY },
|
|
305
|
+
},
|
|
306
|
+
grid: {
|
|
307
|
+
left: '3%',
|
|
308
|
+
right: '4%',
|
|
309
|
+
top: '3%',
|
|
310
|
+
bottom: '15%',
|
|
311
|
+
containLabel: true,
|
|
312
|
+
},
|
|
313
|
+
xAxis: {
|
|
314
|
+
type: 'value',
|
|
315
|
+
min: xMin,
|
|
316
|
+
max: xMax,
|
|
317
|
+
axisLine: { show: false },
|
|
318
|
+
axisTick: { show: false },
|
|
319
|
+
axisLabel: {
|
|
320
|
+
color: colors.textSecondary,
|
|
321
|
+
...(axisFormatter && { formatter: axisFormatter }),
|
|
322
|
+
},
|
|
323
|
+
splitLine: { lineStyle: { color: colors.border, type: [2, 3], opacity: 0.6 } },
|
|
324
|
+
},
|
|
325
|
+
yAxis: {
|
|
326
|
+
type: 'category',
|
|
327
|
+
data: categories,
|
|
328
|
+
inverse: true,
|
|
329
|
+
axisLine: { show: false },
|
|
330
|
+
axisTick: { show: false },
|
|
331
|
+
axisLabel: {
|
|
332
|
+
color: colors.textSecondary,
|
|
333
|
+
rotate: 0,
|
|
334
|
+
interval: 0,
|
|
335
|
+
},
|
|
336
|
+
},
|
|
337
|
+
series,
|
|
338
|
+
};
|
|
339
|
+
}
|
|
340
|
+
/**
|
|
341
|
+
* Calculate minimum height for dumbbell chart based on number of rows
|
|
342
|
+
*/
|
|
343
|
+
function calculateDumbbellHeight(numRows, specHeight) {
|
|
344
|
+
// Each row needs symbol size plus small gap to prevent vertical overlap
|
|
345
|
+
// With 22px symbols, 4px gap gives minimal spacing without excessive whitespace
|
|
346
|
+
const rowHeight = DUMBBELL_SYMBOL_SIZE + 4; // symbol + small gap
|
|
347
|
+
const legendHeight = 40;
|
|
348
|
+
const gridPadding = 60; // top + bottom margins
|
|
349
|
+
const minHeight = (numRows * rowHeight) + legendHeight + gridPadding;
|
|
350
|
+
// Use spec height if provided and larger than minimum, otherwise use calculated minimum
|
|
351
|
+
if (typeof specHeight === 'number') {
|
|
352
|
+
return Math.max(specHeight, minHeight);
|
|
353
|
+
}
|
|
354
|
+
return Math.max(DEFAULT_CHART_HEIGHT, minHeight);
|
|
355
|
+
}
|
|
356
|
+
/**
|
|
357
|
+
* Generate a dumbbell chart
|
|
358
|
+
*/
|
|
359
|
+
function generateDumbbell(spec) {
|
|
360
|
+
const data = (spec.data ?? []);
|
|
361
|
+
const height = calculateDumbbellHeight(data.length, spec.height);
|
|
362
|
+
return wrapHtml('chart', buildDumbbellOptions(spec), '', '100%', height);
|
|
363
|
+
}
|
|
364
|
+
// Register the chart
|
|
365
|
+
registerChart('dumbbell')(generateDumbbell);
|
|
366
|
+
registerOptions('dumbbell')(buildDumbbellOptions);
|
|
367
|
+
export { generateDumbbell };
|
|
368
|
+
//# sourceMappingURL=dumbbell.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"dumbbell.js","sourceRoot":"","sources":["../../charts/dumbbell.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Funnel chart generator
|
|
3
|
+
*/
|
|
4
|
+
import type { ChartSpec } from '../types.js';
|
|
5
|
+
/**
|
|
6
|
+
* Build ECharts options for a funnel chart
|
|
7
|
+
*/
|
|
8
|
+
export declare function buildFunnelOptions(spec: ChartSpec): Record<string, unknown>;
|
|
9
|
+
/**
|
|
10
|
+
* Generate a funnel chart
|
|
11
|
+
*/
|
|
12
|
+
declare function generateFunnel(spec: ChartSpec): string;
|
|
13
|
+
export { generateFunnel };
|
|
14
|
+
//# sourceMappingURL=funnel.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"funnel.d.ts","sourceRoot":"","sources":["../../charts/funnel.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,KAAK,EAAE,SAAS,EAAoB,MAAM,aAAa,CAAC;AAmE/D;;GAEG;AACH,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,SAAS,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAsE3E;AAED;;GAEG;AACH,iBAAS,cAAc,CAAC,IAAI,EAAE,SAAS,GAAG,MAAM,CAG/C;AAMD,OAAO,EAAE,cAAc,EAAE,CAAC"}
|
|
@@ -0,0 +1,145 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Funnel chart generator
|
|
3
|
+
*/
|
|
4
|
+
import { FONT_SIZE_XXS, getThemeColors, getPalette } from '../core/themes.js';
|
|
5
|
+
import { wrapHtml } from '../core/serializer.js';
|
|
6
|
+
import { inferFormat } from '../core/formatting.js';
|
|
7
|
+
import { registerChart, registerOptions } from './registry.js';
|
|
8
|
+
/**
|
|
9
|
+
* Get JavaScript formatter for funnel chart labels/tooltips
|
|
10
|
+
*/
|
|
11
|
+
function getFunnelFormatterJs(fmt) {
|
|
12
|
+
// Smart auto-formatting based on magnitude
|
|
13
|
+
if (fmt === 'auto' || fmt === 'usd_auto' || fmt === null || fmt === undefined) {
|
|
14
|
+
const isCurrency = fmt === 'usd_auto' ? 'true' : 'false';
|
|
15
|
+
return {
|
|
16
|
+
_js_: `function(params) {
|
|
17
|
+
var v = params.value;
|
|
18
|
+
if (v == null) return params.name;
|
|
19
|
+
var abs = Math.abs(v);
|
|
20
|
+
var neg = v < 0;
|
|
21
|
+
var p = ${isCurrency} ? '$' : '';
|
|
22
|
+
var r;
|
|
23
|
+
if (abs >= 1e9) {
|
|
24
|
+
var s = abs / 1e9;
|
|
25
|
+
r = s >= 100 ? p + s.toFixed(1) + 'b' : s >= 10 ? p + s.toFixed(2) + 'b' : p + s.toFixed(3) + 'b';
|
|
26
|
+
} else if (abs >= 1e6) {
|
|
27
|
+
var s = abs / 1e6;
|
|
28
|
+
r = s >= 100 ? p + s.toFixed(1) + 'm' : s >= 10 ? p + s.toFixed(2) + 'm' : p + s.toFixed(3) + 'm';
|
|
29
|
+
} else if (abs >= 1e4) {
|
|
30
|
+
var s = abs / 1e3;
|
|
31
|
+
r = s >= 100 ? p + s.toFixed(1) + 'k' : p + s.toFixed(2) + 'k';
|
|
32
|
+
} else if (abs >= 1e3) {
|
|
33
|
+
r = p + abs.toLocaleString('en-US', {maximumFractionDigits: 0});
|
|
34
|
+
} else {
|
|
35
|
+
r = abs === Math.floor(abs) ? p + abs : p + abs.toFixed(2);
|
|
36
|
+
}
|
|
37
|
+
var formatted = neg ? '(' + r + ')' : r;
|
|
38
|
+
return params.name + ': ' + formatted;
|
|
39
|
+
}`,
|
|
40
|
+
};
|
|
41
|
+
}
|
|
42
|
+
// Specific format handlers
|
|
43
|
+
switch (fmt) {
|
|
44
|
+
case 'usd':
|
|
45
|
+
return { _js_: "function(params) { return params.name + ': $' + params.value.toLocaleString(); }" };
|
|
46
|
+
case 'usd0k':
|
|
47
|
+
return {
|
|
48
|
+
_js_: "function(params) { return params.name + ': $' + (params.value/1000).toFixed(0) + 'k'; }",
|
|
49
|
+
};
|
|
50
|
+
case 'pct':
|
|
51
|
+
case 'pct1':
|
|
52
|
+
return {
|
|
53
|
+
_js_: "function(params) { return params.name + ': ' + (params.value * 100).toFixed(1) + '%'; }",
|
|
54
|
+
};
|
|
55
|
+
case 'pct0':
|
|
56
|
+
return {
|
|
57
|
+
_js_: "function(params) { return params.name + ': ' + (params.value * 100).toFixed(0) + '%'; }",
|
|
58
|
+
};
|
|
59
|
+
case 'num0':
|
|
60
|
+
return { _js_: "function(params) { return params.name + ': ' + params.value.toLocaleString(); }" };
|
|
61
|
+
case 'num1':
|
|
62
|
+
return { _js_: "function(params) { return params.name + ': ' + params.value.toFixed(1); }" };
|
|
63
|
+
default:
|
|
64
|
+
return { _js_: "function(params) { return params.name + ': ' + params.value.toLocaleString(); }" };
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
/**
|
|
68
|
+
* Build ECharts options for a funnel chart
|
|
69
|
+
*/
|
|
70
|
+
export function buildFunnelOptions(spec) {
|
|
71
|
+
const data = (spec.data ?? []);
|
|
72
|
+
const valueField = spec.value ?? 'value';
|
|
73
|
+
const nameField = spec.name ?? 'name';
|
|
74
|
+
const theme = (spec.theme ?? 'light');
|
|
75
|
+
const colors = getThemeColors(theme);
|
|
76
|
+
const palette = getPalette(theme);
|
|
77
|
+
// Build funnel data
|
|
78
|
+
const funnelData = data.map((d) => ({
|
|
79
|
+
name: String(d[nameField] ?? ''),
|
|
80
|
+
value: (d[valueField] ?? 0),
|
|
81
|
+
}));
|
|
82
|
+
// Sort descending by value
|
|
83
|
+
funnelData.sort((a, b) => b.value - a.value);
|
|
84
|
+
// Assign colors
|
|
85
|
+
funnelData.forEach((item, i) => {
|
|
86
|
+
item.itemStyle = { color: palette[i % palette.length] };
|
|
87
|
+
});
|
|
88
|
+
// Infer format from value field name or use explicit format
|
|
89
|
+
const sampleValue = funnelData[0]?.value ?? 0;
|
|
90
|
+
const valueFormat = spec.format ?? inferFormat(valueField, sampleValue);
|
|
91
|
+
// Get JavaScript formatter
|
|
92
|
+
const formatter = getFunnelFormatterJs(valueFormat);
|
|
93
|
+
return {
|
|
94
|
+
backgroundColor: 'transparent',
|
|
95
|
+
animation: false,
|
|
96
|
+
tooltip: {
|
|
97
|
+
trigger: 'item',
|
|
98
|
+
backgroundColor: colors.paper,
|
|
99
|
+
borderColor: colors.border,
|
|
100
|
+
textStyle: { color: colors.text },
|
|
101
|
+
formatter,
|
|
102
|
+
},
|
|
103
|
+
series: [
|
|
104
|
+
{
|
|
105
|
+
type: 'funnel',
|
|
106
|
+
left: '12%',
|
|
107
|
+
width: '76%',
|
|
108
|
+
top: '8%',
|
|
109
|
+
bottom: '8%',
|
|
110
|
+
min: 0,
|
|
111
|
+
max: funnelData[0]?.value ?? 100,
|
|
112
|
+
minSize: '0%',
|
|
113
|
+
maxSize: '100%',
|
|
114
|
+
sort: 'descending',
|
|
115
|
+
gap: 2,
|
|
116
|
+
label: {
|
|
117
|
+
show: true,
|
|
118
|
+
position: 'inside',
|
|
119
|
+
formatter,
|
|
120
|
+
color: '#fff',
|
|
121
|
+
fontSize: FONT_SIZE_XXS,
|
|
122
|
+
},
|
|
123
|
+
itemStyle: {
|
|
124
|
+
borderWidth: 0,
|
|
125
|
+
},
|
|
126
|
+
emphasis: {
|
|
127
|
+
disabled: true,
|
|
128
|
+
},
|
|
129
|
+
data: funnelData,
|
|
130
|
+
},
|
|
131
|
+
],
|
|
132
|
+
};
|
|
133
|
+
}
|
|
134
|
+
/**
|
|
135
|
+
* Generate a funnel chart
|
|
136
|
+
*/
|
|
137
|
+
function generateFunnel(spec) {
|
|
138
|
+
const height = typeof spec.height === 'number' ? spec.height : 300;
|
|
139
|
+
return wrapHtml('chart', buildFunnelOptions(spec), '', '100%', height);
|
|
140
|
+
}
|
|
141
|
+
// Register the chart
|
|
142
|
+
registerChart('funnel')(generateFunnel);
|
|
143
|
+
registerOptions('funnel')(buildFunnelOptions);
|
|
144
|
+
export { generateFunnel };
|
|
145
|
+
//# sourceMappingURL=funnel.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"funnel.js","sourceRoot":"","sources":["../../charts/funnel.ts"],"names":[],"mappings":"AAAA;;GAEG;AAGH,OAAO,EAAE,aAAa,EAAE,cAAc,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAC;AAC9E,OAAO,EAAE,QAAQ,EAAE,MAAM,uBAAuB,CAAC;AACjD,OAAO,EAAE,WAAW,EAAmB,MAAM,uBAAuB,CAAC;AACrE,OAAO,EAAE,aAAa,EAAE,eAAe,EAAE,MAAM,eAAe,CAAC;AAE/D;;GAEG;AACH,SAAS,oBAAoB,CAAC,GAAsB;IAClD,2CAA2C;IAC3C,IAAI,GAAG,KAAK,MAAM,IAAI,GAAG,KAAK,UAAU,IAAI,GAAG,KAAK,IAAI,IAAI,GAAG,KAAK,SAAS,EAAE,CAAC;QAC9E,MAAM,UAAU,GAAG,GAAG,KAAK,UAAU,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,OAAO,CAAC;QACzD,OAAO;YACL,IAAI,EAAE;;;;;YAKA,UAAU;;;;;;;;;;;;;;;;;;EAkBpB;SACG,CAAC;IACJ,CAAC;IAED,2BAA2B;IAC3B,QAAQ,GAAG,EAAE,CAAC;QACZ,KAAK,KAAK;YACR,OAAO,EAAE,IAAI,EAAE,kFAAkF,EAAE,CAAC;QACtG,KAAK,OAAO;YACV,OAAO;gBACL,IAAI,EAAE,yFAAyF;aAChG,CAAC;QACJ,KAAK,KAAK,CAAC;QACX,KAAK,MAAM;YACT,OAAO;gBACL,IAAI,EAAE,yFAAyF;aAChG,CAAC;QACJ,KAAK,MAAM;YACT,OAAO;gBACL,IAAI,EAAE,yFAAyF;aAChG,CAAC;QACJ,KAAK,MAAM;YACT,OAAO,EAAE,IAAI,EAAE,iFAAiF,EAAE,CAAC;QACrG,KAAK,MAAM;YACT,OAAO,EAAE,IAAI,EAAE,2EAA2E,EAAE,CAAC;QAC/F;YACE,OAAO,EAAE,IAAI,EAAE,iFAAiF,EAAE,CAAC;IACvG,CAAC;AACH,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,kBAAkB,CAAC,IAAe;IAChD,MAAM,IAAI,GAAG,CAAC,IAAI,CAAC,IAAI,IAAI,EAAE,CAAgB,CAAC;IAC9C,MAAM,UAAU,GAAI,IAAI,CAAC,KAAgB,IAAI,OAAO,CAAC;IACrD,MAAM,SAAS,GAAI,IAAI,CAAC,IAAe,IAAI,MAAM,CAAC;IAClD,MAAM,KAAK,GAAG,CAAC,IAAI,CAAC,KAAK,IAAI,OAAO,CAAU,CAAC;IAE/C,MAAM,MAAM,GAAG,cAAc,CAAC,KAAK,CAAC,CAAC;IACrC,MAAM,OAAO,GAAG,UAAU,CAAC,KAAK,CAAC,CAAC;IAElC,oBAAoB;IACpB,MAAM,UAAU,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;QAClC,IAAI,EAAE,MAAM,CAAC,CAAC,CAAC,SAAS,CAAC,IAAI,EAAE,CAAC;QAChC,KAAK,EAAE,CAAC,CAAC,CAAC,UAAU,CAAC,IAAI,CAAC,CAAW;KACtC,CAAC,CAAC,CAAC;IAEJ,2BAA2B;IAC3B,UAAU,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,KAAK,GAAG,CAAC,CAAC,KAAK,CAAC,CAAC;IAE7C,gBAAgB;IAChB,UAAU,CAAC,OAAO,CAAC,CAAC,IAAI,EAAE,CAAC,EAAE,EAAE;QAC5B,IAAgC,CAAC,SAAS,GAAG,EAAE,KAAK,EAAE,OAAO,CAAC,CAAC,GAAG,OAAO,CAAC,MAAM,CAAC,EAAE,CAAC;IACvF,CAAC,CAAC,CAAC;IAEH,4DAA4D;IAC5D,MAAM,WAAW,GAAG,UAAU,CAAC,CAAC,CAAC,EAAE,KAAK,IAAI,CAAC,CAAC;IAC9C,MAAM,WAAW,GAAI,IAAI,CAAC,MAAqB,IAAI,WAAW,CAAC,UAAU,EAAE,WAAW,CAAC,CAAC;IAExF,2BAA2B;IAC3B,MAAM,SAAS,GAAG,oBAAoB,CAAC,WAAW,CAAC,CAAC;IAEpD,OAAO;QACL,eAAe,EAAE,aAAa;QAC9B,SAAS,EAAE,KAAK;QAChB,OAAO,EAAE;YACP,OAAO,EAAE,MAAM;YACf,eAAe,EAAE,MAAM,CAAC,KAAK;YAC7B,WAAW,EAAE,MAAM,CAAC,MAAM;YAC1B,SAAS,EAAE,EAAE,KAAK,EAAE,MAAM,CAAC,IAAI,EAAE;YACjC,SAAS;SACV;QACD,MAAM,EAAE;YACN;gBACE,IAAI,EAAE,QAAQ;gBACd,IAAI,EAAE,KAAK;gBACX,KAAK,EAAE,KAAK;gBACZ,GAAG,EAAE,IAAI;gBACT,MAAM,EAAE,IAAI;gBACZ,GAAG,EAAE,CAAC;gBACN,GAAG,EAAE,UAAU,CAAC,CAAC,CAAC,EAAE,KAAK,IAAI,GAAG;gBAChC,OAAO,EAAE,IAAI;gBACb,OAAO,EAAE,MAAM;gBACf,IAAI,EAAE,YAAY;gBAClB,GAAG,EAAE,CAAC;gBACN,KAAK,EAAE;oBACL,IAAI,EAAE,IAAI;oBACV,QAAQ,EAAE,QAAQ;oBAClB,SAAS;oBACT,KAAK,EAAE,MAAM;oBACb,QAAQ,EAAE,aAAa;iBACxB;gBACD,SAAS,EAAE;oBACT,WAAW,EAAE,CAAC;iBACf;gBACD,QAAQ,EAAE;oBACR,QAAQ,EAAE,IAAI;iBACf;gBACD,IAAI,EAAE,UAAU;aACjB;SACF;KACF,CAAC;AACJ,CAAC;AAED;;GAEG;AACH,SAAS,cAAc,CAAC,IAAe;IACrC,MAAM,MAAM,GAAG,OAAO,IAAI,CAAC,MAAM,KAAK,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,GAAG,CAAC;IACnE,OAAO,QAAQ,CAAC,OAAO,EAAE,kBAAkB,CAAC,IAAI,CAAC,EAAE,EAAE,EAAE,MAAM,EAAE,MAAM,CAAC,CAAC;AACzE,CAAC;AAED,qBAAqB;AACrB,aAAa,CAAC,QAAQ,CAAC,CAAC,cAAc,CAAC,CAAC;AACxC,eAAe,CAAC,QAAQ,CAAC,CAAC,kBAAkB,CAAC,CAAC;AAE9C,OAAO,EAAE,cAAc,EAAE,CAAC"}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Heatmap chart generator
|
|
3
|
+
*/
|
|
4
|
+
import type { ChartSpec } from '../types.js';
|
|
5
|
+
/**
|
|
6
|
+
* Build ECharts options for a heatmap
|
|
7
|
+
*/
|
|
8
|
+
export declare function buildHeatmapOptions(spec: ChartSpec): Record<string, unknown>;
|
|
9
|
+
/**
|
|
10
|
+
* Generate a heatmap chart
|
|
11
|
+
*/
|
|
12
|
+
declare function generateHeatmap(spec: ChartSpec): string;
|
|
13
|
+
export { generateHeatmap };
|
|
14
|
+
//# sourceMappingURL=heatmap.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"heatmap.d.ts","sourceRoot":"","sources":["../../charts/heatmap.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,KAAK,EAAE,SAAS,EAAgC,MAAM,aAAa,CAAC;AA+F3E;;GAEG;AACH,wBAAgB,mBAAmB,CAAC,IAAI,EAAE,SAAS,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAsG5E;AAED;;GAEG;AACH,iBAAS,eAAe,CAAC,IAAI,EAAE,SAAS,GAAG,MAAM,CAGhD;AAMD,OAAO,EAAE,eAAe,EAAE,CAAC"}
|