@cfasim-ui/charts 0.1.9 → 0.2.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/dist/ChartMenu/ChartMenu.d.ts +9 -0
- package/dist/ChartMenu/download.d.ts +4 -0
- package/dist/ChartTooltip/ChartTooltip.d.ts +37 -0
- package/dist/ChartTooltip/ChartTooltip.test.d.ts +1 -0
- package/dist/ChoroplethMap/ChoroplethMap.d.ts +91 -0
- package/dist/ChoroplethMap/ChoroplethMap.test.d.ts +1 -0
- package/dist/ChoroplethMap/hsaMapping.d.ts +4 -0
- package/dist/DataTable/DataTable.d.ts +21 -0
- package/dist/DataTable/DataTable.test.d.ts +1 -0
- package/dist/LineChart/LineChart.d.ts +96 -0
- package/dist/LineChart/LineChart.spec.d.ts +1 -0
- package/dist/LineChart/LineChart.test.d.ts +1 -0
- package/dist/index.css +2 -0
- package/dist/index.d.ts +4 -0
- package/dist/index.js +5236 -0
- package/package.json +18 -4
- package/src/ChartMenu/ChartMenu.vue +0 -140
- package/src/ChartMenu/download.ts +0 -44
- package/src/ChoroplethMap/ChoroplethMap.md +0 -330
- package/src/ChoroplethMap/ChoroplethMap.test.ts +0 -468
- package/src/ChoroplethMap/ChoroplethMap.vue +0 -629
- package/src/ChoroplethMap/hsaMapping.ts +0 -4116
- package/src/DataTable/DataTable.md +0 -101
- package/src/DataTable/DataTable.test.ts +0 -177
- package/src/DataTable/DataTable.vue +0 -217
- package/src/LineChart/LineChart.md +0 -182
- package/src/LineChart/LineChart.spec.ts +0 -11
- package/src/LineChart/LineChart.vue +0 -465
- package/src/index.ts +0 -21
|
@@ -1,465 +0,0 @@
|
|
|
1
|
-
<script setup lang="ts">
|
|
2
|
-
import { computed, ref, onMounted, onUnmounted } from "vue";
|
|
3
|
-
import ChartMenu from "../ChartMenu/ChartMenu.vue";
|
|
4
|
-
import type { ChartMenuItem } from "../ChartMenu/ChartMenu.vue";
|
|
5
|
-
import { saveSvg, savePng, downloadCsv } from "../ChartMenu/download.js";
|
|
6
|
-
|
|
7
|
-
export interface Series {
|
|
8
|
-
data: number[];
|
|
9
|
-
color?: string;
|
|
10
|
-
dashed?: boolean;
|
|
11
|
-
strokeWidth?: number;
|
|
12
|
-
opacity?: number;
|
|
13
|
-
}
|
|
14
|
-
|
|
15
|
-
export interface Area {
|
|
16
|
-
upper: number[];
|
|
17
|
-
lower: number[];
|
|
18
|
-
color?: string;
|
|
19
|
-
opacity?: number;
|
|
20
|
-
}
|
|
21
|
-
|
|
22
|
-
const props = withDefaults(
|
|
23
|
-
defineProps<{
|
|
24
|
-
data?: number[];
|
|
25
|
-
series?: Series[];
|
|
26
|
-
areas?: Area[];
|
|
27
|
-
width?: number;
|
|
28
|
-
height?: number;
|
|
29
|
-
lineOpacity?: number;
|
|
30
|
-
title?: string;
|
|
31
|
-
xLabel?: string;
|
|
32
|
-
yLabel?: string;
|
|
33
|
-
yMin?: number;
|
|
34
|
-
xMin?: number;
|
|
35
|
-
xLabels?: string[];
|
|
36
|
-
debounce?: number;
|
|
37
|
-
menu?: boolean | string;
|
|
38
|
-
xGrid?: boolean;
|
|
39
|
-
yGrid?: boolean;
|
|
40
|
-
}>(),
|
|
41
|
-
{ lineOpacity: 1, menu: true },
|
|
42
|
-
);
|
|
43
|
-
|
|
44
|
-
const containerRef = ref<HTMLElement | null>(null);
|
|
45
|
-
const svgRef = ref<SVGSVGElement | null>(null);
|
|
46
|
-
const measuredWidth = ref(0);
|
|
47
|
-
let observer: ResizeObserver | null = null;
|
|
48
|
-
let resizeTimeout: ReturnType<typeof setTimeout> | null = null;
|
|
49
|
-
|
|
50
|
-
onMounted(() => {
|
|
51
|
-
if (containerRef.value) {
|
|
52
|
-
measuredWidth.value = containerRef.value.clientWidth;
|
|
53
|
-
observer = new ResizeObserver((entries) => {
|
|
54
|
-
const entry = entries[0];
|
|
55
|
-
if (!entry) return;
|
|
56
|
-
if (props.debounce) {
|
|
57
|
-
if (resizeTimeout) clearTimeout(resizeTimeout);
|
|
58
|
-
resizeTimeout = setTimeout(() => {
|
|
59
|
-
measuredWidth.value = entry.contentRect.width;
|
|
60
|
-
}, props.debounce);
|
|
61
|
-
} else {
|
|
62
|
-
measuredWidth.value = entry.contentRect.width;
|
|
63
|
-
}
|
|
64
|
-
});
|
|
65
|
-
observer.observe(containerRef.value);
|
|
66
|
-
}
|
|
67
|
-
});
|
|
68
|
-
|
|
69
|
-
onUnmounted(() => {
|
|
70
|
-
observer?.disconnect();
|
|
71
|
-
if (resizeTimeout) clearTimeout(resizeTimeout);
|
|
72
|
-
});
|
|
73
|
-
|
|
74
|
-
const width = computed(() => props.width ?? (measuredWidth.value || 400));
|
|
75
|
-
const height = computed(() => props.height ?? 200);
|
|
76
|
-
|
|
77
|
-
const padding = computed(() => ({
|
|
78
|
-
top: props.title ? 30 : 10,
|
|
79
|
-
right: 10,
|
|
80
|
-
bottom: props.xLabel ? 46 : 30,
|
|
81
|
-
left: props.yLabel ? 66 : 50,
|
|
82
|
-
}));
|
|
83
|
-
|
|
84
|
-
const innerW = computed(
|
|
85
|
-
() => width.value - padding.value.left - padding.value.right,
|
|
86
|
-
);
|
|
87
|
-
const innerH = computed(
|
|
88
|
-
() => height.value - padding.value.top - padding.value.bottom,
|
|
89
|
-
);
|
|
90
|
-
|
|
91
|
-
const allSeries = computed<Series[]>(() => {
|
|
92
|
-
if (props.series && props.series.length > 0) return props.series;
|
|
93
|
-
if (props.data) return [{ data: props.data }];
|
|
94
|
-
return [];
|
|
95
|
-
});
|
|
96
|
-
|
|
97
|
-
const allAreas = computed<Area[]>(() => props.areas ?? []);
|
|
98
|
-
|
|
99
|
-
const maxLen = computed(() => {
|
|
100
|
-
let m = 0;
|
|
101
|
-
for (const s of allSeries.value) {
|
|
102
|
-
if (s.data.length > m) m = s.data.length;
|
|
103
|
-
}
|
|
104
|
-
for (const a of allAreas.value) {
|
|
105
|
-
if (a.upper.length > m) m = a.upper.length;
|
|
106
|
-
if (a.lower.length > m) m = a.lower.length;
|
|
107
|
-
}
|
|
108
|
-
return m;
|
|
109
|
-
});
|
|
110
|
-
|
|
111
|
-
const extent = computed(() => {
|
|
112
|
-
let min = Infinity;
|
|
113
|
-
let max = -Infinity;
|
|
114
|
-
for (const s of allSeries.value) {
|
|
115
|
-
for (const v of s.data) {
|
|
116
|
-
if (!isFinite(v)) continue;
|
|
117
|
-
if (v < min) min = v;
|
|
118
|
-
if (v > max) max = v;
|
|
119
|
-
}
|
|
120
|
-
}
|
|
121
|
-
for (const a of allAreas.value) {
|
|
122
|
-
for (const v of a.upper) {
|
|
123
|
-
if (!isFinite(v)) continue;
|
|
124
|
-
if (v < min) min = v;
|
|
125
|
-
if (v > max) max = v;
|
|
126
|
-
}
|
|
127
|
-
for (const v of a.lower) {
|
|
128
|
-
if (!isFinite(v)) continue;
|
|
129
|
-
if (v < min) min = v;
|
|
130
|
-
if (v > max) max = v;
|
|
131
|
-
}
|
|
132
|
-
}
|
|
133
|
-
if (!isFinite(min)) return { min: 0, max: 0, range: 1 };
|
|
134
|
-
if (props.yMin != null && props.yMin < min) min = props.yMin;
|
|
135
|
-
return { min, max, range: max - min || 1 };
|
|
136
|
-
});
|
|
137
|
-
|
|
138
|
-
function toPath(data: number[]): string {
|
|
139
|
-
if (data.length === 0) return "";
|
|
140
|
-
const { min, range } = extent.value;
|
|
141
|
-
const len = maxLen.value;
|
|
142
|
-
const xScale = innerW.value / (len - 1 || 1);
|
|
143
|
-
const yScale = innerH.value / range;
|
|
144
|
-
const py = padding.value.top + innerH.value;
|
|
145
|
-
let d = "";
|
|
146
|
-
let inSegment = false;
|
|
147
|
-
for (let i = 0; i < data.length; i++) {
|
|
148
|
-
if (!isFinite(data[i])) {
|
|
149
|
-
inSegment = false;
|
|
150
|
-
continue;
|
|
151
|
-
}
|
|
152
|
-
const x = padding.value.left + i * xScale;
|
|
153
|
-
const y = py - (data[i] - min) * yScale;
|
|
154
|
-
d += inSegment ? `L${x},${y}` : `M${x},${y}`;
|
|
155
|
-
inSegment = true;
|
|
156
|
-
}
|
|
157
|
-
return d;
|
|
158
|
-
}
|
|
159
|
-
|
|
160
|
-
function toAreaPath(upper: number[], lower: number[]): string {
|
|
161
|
-
const len = Math.min(upper.length, lower.length);
|
|
162
|
-
if (len === 0) return "";
|
|
163
|
-
const { min, range } = extent.value;
|
|
164
|
-
const ml = maxLen.value;
|
|
165
|
-
const xScale = innerW.value / (ml - 1 || 1);
|
|
166
|
-
const yScale = innerH.value / range;
|
|
167
|
-
const py = padding.value.top + innerH.value;
|
|
168
|
-
const x = (i: number) => padding.value.left + i * xScale;
|
|
169
|
-
const y = (v: number) => py - (v - min) * yScale;
|
|
170
|
-
// Collect contiguous segments where both upper and lower are finite
|
|
171
|
-
const segments: number[][] = [];
|
|
172
|
-
let seg: number[] = [];
|
|
173
|
-
for (let i = 0; i < len; i++) {
|
|
174
|
-
if (isFinite(upper[i]) && isFinite(lower[i])) {
|
|
175
|
-
seg.push(i);
|
|
176
|
-
} else if (seg.length) {
|
|
177
|
-
segments.push(seg);
|
|
178
|
-
seg = [];
|
|
179
|
-
}
|
|
180
|
-
}
|
|
181
|
-
if (seg.length) segments.push(seg);
|
|
182
|
-
let d = "";
|
|
183
|
-
for (const s of segments) {
|
|
184
|
-
d += `M${x(s[0])},${y(upper[s[0]])}`;
|
|
185
|
-
for (let j = 1; j < s.length; j++) d += `L${x(s[j])},${y(upper[s[j]])}`;
|
|
186
|
-
for (let j = s.length - 1; j >= 0; j--)
|
|
187
|
-
d += `L${x(s[j])},${y(lower[s[j]])}`;
|
|
188
|
-
d += "Z";
|
|
189
|
-
}
|
|
190
|
-
return d;
|
|
191
|
-
}
|
|
192
|
-
|
|
193
|
-
function niceStep(range: number, targetTicks: number): number {
|
|
194
|
-
const rough = range / targetTicks;
|
|
195
|
-
const mag = Math.pow(10, Math.floor(Math.log10(rough)));
|
|
196
|
-
const norm = rough / mag;
|
|
197
|
-
let step: number;
|
|
198
|
-
if (norm <= 1.5) step = 1;
|
|
199
|
-
else if (norm <= 3) step = 2;
|
|
200
|
-
else if (norm <= 7) step = 5;
|
|
201
|
-
else step = 10;
|
|
202
|
-
return step * mag;
|
|
203
|
-
}
|
|
204
|
-
|
|
205
|
-
/** Round to nearest half-pixel so 1px SVG strokes stay sharp. */
|
|
206
|
-
function snap(v: number): number {
|
|
207
|
-
return Math.round(v) + 0.5;
|
|
208
|
-
}
|
|
209
|
-
|
|
210
|
-
const numFmt = new Intl.NumberFormat();
|
|
211
|
-
function formatTick(v: number): string {
|
|
212
|
-
if (Math.abs(v) >= 1000) return numFmt.format(v);
|
|
213
|
-
if (Number.isInteger(v)) return v.toString();
|
|
214
|
-
return v.toFixed(1);
|
|
215
|
-
}
|
|
216
|
-
|
|
217
|
-
const yTicks = computed(() => {
|
|
218
|
-
const { min, max } = extent.value;
|
|
219
|
-
if (min === max) {
|
|
220
|
-
return [
|
|
221
|
-
{
|
|
222
|
-
value: formatTick(min),
|
|
223
|
-
y: snap(padding.value.top + innerH.value / 2),
|
|
224
|
-
},
|
|
225
|
-
];
|
|
226
|
-
}
|
|
227
|
-
const targetTicks = Math.max(3, Math.floor(innerH.value / 50));
|
|
228
|
-
const step = niceStep(max - min, targetTicks);
|
|
229
|
-
const start = Math.ceil(min / step) * step;
|
|
230
|
-
const ticks: { value: string; y: number }[] = [];
|
|
231
|
-
for (let v = start; v <= max; v += step) {
|
|
232
|
-
ticks.push({
|
|
233
|
-
value: formatTick(v),
|
|
234
|
-
y: snap(
|
|
235
|
-
padding.value.top +
|
|
236
|
-
innerH.value -
|
|
237
|
-
((v - min) / extent.value.range) * innerH.value,
|
|
238
|
-
),
|
|
239
|
-
});
|
|
240
|
-
}
|
|
241
|
-
return ticks;
|
|
242
|
-
});
|
|
243
|
-
|
|
244
|
-
const xTicks = computed(() => {
|
|
245
|
-
const len = maxLen.value;
|
|
246
|
-
if (len <= 1) return [];
|
|
247
|
-
const labels = props.xLabels;
|
|
248
|
-
if (labels && labels.length === len) {
|
|
249
|
-
const targetTicks = Math.max(3, Math.floor(innerW.value / 80));
|
|
250
|
-
const step = Math.max(1, Math.round((len - 1) / targetTicks));
|
|
251
|
-
const ticks: { value: string; x: number }[] = [];
|
|
252
|
-
for (let i = 0; i < len; i += step) {
|
|
253
|
-
ticks.push({
|
|
254
|
-
value: labels[i],
|
|
255
|
-
x: snap(padding.value.left + (i / (len - 1)) * innerW.value),
|
|
256
|
-
});
|
|
257
|
-
}
|
|
258
|
-
return ticks;
|
|
259
|
-
}
|
|
260
|
-
const offset = props.xMin ?? 0;
|
|
261
|
-
const targetTicks = Math.max(3, Math.floor(innerW.value / 80));
|
|
262
|
-
const step = niceStep(len - 1, targetTicks);
|
|
263
|
-
const ticks: { value: string; x: number }[] = [];
|
|
264
|
-
for (let i = 0; i <= len - 1; i += step) {
|
|
265
|
-
const idx = Math.round(i);
|
|
266
|
-
ticks.push({
|
|
267
|
-
value: formatTick(idx + offset),
|
|
268
|
-
x: snap(padding.value.left + (idx / (len - 1)) * innerW.value),
|
|
269
|
-
});
|
|
270
|
-
}
|
|
271
|
-
return ticks;
|
|
272
|
-
});
|
|
273
|
-
|
|
274
|
-
function menuFilename() {
|
|
275
|
-
return typeof props.menu === "string" ? props.menu : "chart";
|
|
276
|
-
}
|
|
277
|
-
|
|
278
|
-
function getSvgEl(): SVGSVGElement | null {
|
|
279
|
-
return svgRef.value;
|
|
280
|
-
}
|
|
281
|
-
|
|
282
|
-
function toCsv(): string {
|
|
283
|
-
const series = allSeries.value;
|
|
284
|
-
if (series.length === 0) return "";
|
|
285
|
-
const len = maxLen.value;
|
|
286
|
-
const headers =
|
|
287
|
-
series.length === 1
|
|
288
|
-
? ["index", "value"]
|
|
289
|
-
: ["index", ...series.map((_, i) => `series_${i}`)];
|
|
290
|
-
const rows = [headers.join(",")];
|
|
291
|
-
for (let r = 0; r < len; r++) {
|
|
292
|
-
const cells = [r.toString()];
|
|
293
|
-
for (const s of series) {
|
|
294
|
-
cells.push(r < s.data.length ? String(s.data[r]) : "");
|
|
295
|
-
}
|
|
296
|
-
rows.push(cells.join(","));
|
|
297
|
-
}
|
|
298
|
-
return rows.join("\n");
|
|
299
|
-
}
|
|
300
|
-
|
|
301
|
-
const menuItems = computed<ChartMenuItem[]>(() => {
|
|
302
|
-
const fname = menuFilename();
|
|
303
|
-
return [
|
|
304
|
-
{
|
|
305
|
-
label: "Save as SVG",
|
|
306
|
-
action: () => {
|
|
307
|
-
const el = getSvgEl();
|
|
308
|
-
if (el) saveSvg(el, fname);
|
|
309
|
-
},
|
|
310
|
-
},
|
|
311
|
-
{
|
|
312
|
-
label: "Save as PNG",
|
|
313
|
-
action: () => {
|
|
314
|
-
const el = getSvgEl();
|
|
315
|
-
if (el) savePng(el, fname);
|
|
316
|
-
},
|
|
317
|
-
},
|
|
318
|
-
{ label: "Download CSV", action: () => downloadCsv(toCsv(), fname) },
|
|
319
|
-
];
|
|
320
|
-
});
|
|
321
|
-
</script>
|
|
322
|
-
|
|
323
|
-
<template>
|
|
324
|
-
<div ref="containerRef" class="line-chart-wrapper">
|
|
325
|
-
<ChartMenu v-if="menu" :items="menuItems" />
|
|
326
|
-
<svg ref="svgRef" :width="width" :height="height">
|
|
327
|
-
<!-- title -->
|
|
328
|
-
<text
|
|
329
|
-
v-if="title"
|
|
330
|
-
:x="width / 2"
|
|
331
|
-
:y="18"
|
|
332
|
-
text-anchor="middle"
|
|
333
|
-
font-size="14"
|
|
334
|
-
font-weight="600"
|
|
335
|
-
fill="currentColor"
|
|
336
|
-
>
|
|
337
|
-
{{ title }}
|
|
338
|
-
</text>
|
|
339
|
-
<!-- axes -->
|
|
340
|
-
<line
|
|
341
|
-
:x1="snap(padding.left)"
|
|
342
|
-
:y1="snap(padding.top)"
|
|
343
|
-
:x2="snap(padding.left)"
|
|
344
|
-
:y2="snap(padding.top + innerH)"
|
|
345
|
-
stroke="currentColor"
|
|
346
|
-
stroke-opacity="0.3"
|
|
347
|
-
/>
|
|
348
|
-
<line
|
|
349
|
-
:x1="snap(padding.left)"
|
|
350
|
-
:y1="snap(padding.top + innerH)"
|
|
351
|
-
:x2="snap(padding.left + innerW)"
|
|
352
|
-
:y2="snap(padding.top + innerH)"
|
|
353
|
-
stroke="currentColor"
|
|
354
|
-
stroke-opacity="0.3"
|
|
355
|
-
/>
|
|
356
|
-
<!-- y grid lines -->
|
|
357
|
-
<template v-if="yGrid">
|
|
358
|
-
<line
|
|
359
|
-
v-for="(tick, i) in yTicks"
|
|
360
|
-
:key="'yg' + i"
|
|
361
|
-
:x1="padding.left"
|
|
362
|
-
:y1="tick.y"
|
|
363
|
-
:x2="padding.left + innerW"
|
|
364
|
-
:y2="tick.y"
|
|
365
|
-
stroke="currentColor"
|
|
366
|
-
stroke-opacity="0.1"
|
|
367
|
-
/>
|
|
368
|
-
</template>
|
|
369
|
-
<!-- x grid lines -->
|
|
370
|
-
<template v-if="xGrid">
|
|
371
|
-
<line
|
|
372
|
-
v-for="(tick, i) in xTicks"
|
|
373
|
-
:key="'xg' + i"
|
|
374
|
-
:x1="tick.x"
|
|
375
|
-
:y1="padding.top"
|
|
376
|
-
:x2="tick.x"
|
|
377
|
-
:y2="padding.top + innerH"
|
|
378
|
-
stroke="currentColor"
|
|
379
|
-
stroke-opacity="0.1"
|
|
380
|
-
/>
|
|
381
|
-
</template>
|
|
382
|
-
<!-- y tick labels -->
|
|
383
|
-
<text
|
|
384
|
-
v-for="(tick, i) in yTicks"
|
|
385
|
-
:key="'y' + i"
|
|
386
|
-
:x="padding.left - 6"
|
|
387
|
-
:y="tick.y"
|
|
388
|
-
text-anchor="end"
|
|
389
|
-
dominant-baseline="middle"
|
|
390
|
-
font-size="10"
|
|
391
|
-
fill="currentColor"
|
|
392
|
-
fill-opacity="0.6"
|
|
393
|
-
>
|
|
394
|
-
{{ tick.value }}
|
|
395
|
-
</text>
|
|
396
|
-
<!-- y axis label -->
|
|
397
|
-
<text
|
|
398
|
-
v-if="yLabel"
|
|
399
|
-
:x="0"
|
|
400
|
-
:y="0"
|
|
401
|
-
:transform="`translate(14, ${padding.top + innerH / 2}) rotate(-90)`"
|
|
402
|
-
text-anchor="middle"
|
|
403
|
-
font-size="13"
|
|
404
|
-
fill="currentColor"
|
|
405
|
-
>
|
|
406
|
-
{{ yLabel }}
|
|
407
|
-
</text>
|
|
408
|
-
<!-- x tick labels -->
|
|
409
|
-
<text
|
|
410
|
-
v-for="(tick, i) in xTicks"
|
|
411
|
-
:key="'x' + i"
|
|
412
|
-
:x="tick.x"
|
|
413
|
-
:y="padding.top + innerH + 16"
|
|
414
|
-
text-anchor="middle"
|
|
415
|
-
font-size="10"
|
|
416
|
-
fill="currentColor"
|
|
417
|
-
fill-opacity="0.6"
|
|
418
|
-
>
|
|
419
|
-
{{ tick.value }}
|
|
420
|
-
</text>
|
|
421
|
-
<!-- x axis label -->
|
|
422
|
-
<text
|
|
423
|
-
v-if="xLabel"
|
|
424
|
-
:x="padding.left + innerW / 2"
|
|
425
|
-
:y="height - 4"
|
|
426
|
-
text-anchor="middle"
|
|
427
|
-
font-size="13"
|
|
428
|
-
fill="currentColor"
|
|
429
|
-
>
|
|
430
|
-
{{ xLabel }}
|
|
431
|
-
</text>
|
|
432
|
-
<!-- areas -->
|
|
433
|
-
<path
|
|
434
|
-
v-for="(a, i) in allAreas"
|
|
435
|
-
:key="'area' + i"
|
|
436
|
-
:d="toAreaPath(a.upper, a.lower)"
|
|
437
|
-
:fill="a.color ?? 'currentColor'"
|
|
438
|
-
:fill-opacity="a.opacity ?? 0.2"
|
|
439
|
-
stroke="none"
|
|
440
|
-
/>
|
|
441
|
-
<!-- data lines -->
|
|
442
|
-
<path
|
|
443
|
-
v-for="(s, i) in allSeries"
|
|
444
|
-
:key="i"
|
|
445
|
-
:d="toPath(s.data)"
|
|
446
|
-
fill="none"
|
|
447
|
-
:stroke="s.color ?? 'currentColor'"
|
|
448
|
-
:stroke-width="s.strokeWidth ?? 1.5"
|
|
449
|
-
:stroke-opacity="s.opacity ?? lineOpacity"
|
|
450
|
-
:stroke-dasharray="s.dashed ? '6 3' : undefined"
|
|
451
|
-
/>
|
|
452
|
-
</svg>
|
|
453
|
-
</div>
|
|
454
|
-
</template>
|
|
455
|
-
|
|
456
|
-
<style scoped>
|
|
457
|
-
.line-chart-wrapper {
|
|
458
|
-
position: relative;
|
|
459
|
-
width: 100%;
|
|
460
|
-
}
|
|
461
|
-
|
|
462
|
-
.line-chart-wrapper:hover :deep(.chart-menu-button) {
|
|
463
|
-
opacity: 1;
|
|
464
|
-
}
|
|
465
|
-
</style>
|
package/src/index.ts
DELETED
|
@@ -1,21 +0,0 @@
|
|
|
1
|
-
export {
|
|
2
|
-
default as LineChart,
|
|
3
|
-
type Series,
|
|
4
|
-
type Area,
|
|
5
|
-
} from "./LineChart/LineChart.vue";
|
|
6
|
-
export {
|
|
7
|
-
default as ChoroplethMap,
|
|
8
|
-
type GeoType,
|
|
9
|
-
type StateData,
|
|
10
|
-
type ChoroplethColorScale,
|
|
11
|
-
type ThresholdStop,
|
|
12
|
-
type CategoricalStop,
|
|
13
|
-
} from "./ChoroplethMap/ChoroplethMap.vue";
|
|
14
|
-
export {
|
|
15
|
-
default as DataTable,
|
|
16
|
-
type TableData,
|
|
17
|
-
type TableRecord,
|
|
18
|
-
type ColumnAlign,
|
|
19
|
-
type ColumnConfig,
|
|
20
|
-
type ColumnWidth,
|
|
21
|
-
} from "./DataTable/DataTable.vue";
|