@cfasim-ui/charts 0.1.2 → 0.1.4
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/package.json +12 -2
- package/src/ChoroplethMap/ChoroplethMap.md +330 -0
- package/src/ChoroplethMap/ChoroplethMap.test.ts +468 -0
- package/src/ChoroplethMap/ChoroplethMap.vue +629 -0
- package/src/ChoroplethMap/hsaMapping.ts +4116 -0
- package/src/LineChart/LineChart.vue +54 -1
- package/src/index.ts +13 -1
|
@@ -12,16 +12,26 @@ export interface Series {
|
|
|
12
12
|
opacity?: number;
|
|
13
13
|
}
|
|
14
14
|
|
|
15
|
+
export interface Area {
|
|
16
|
+
upper: number[];
|
|
17
|
+
lower: number[];
|
|
18
|
+
color?: string;
|
|
19
|
+
opacity?: number;
|
|
20
|
+
}
|
|
21
|
+
|
|
15
22
|
const props = withDefaults(
|
|
16
23
|
defineProps<{
|
|
17
24
|
data?: number[];
|
|
18
25
|
series?: Series[];
|
|
26
|
+
areas?: Area[];
|
|
19
27
|
width?: number;
|
|
20
28
|
height?: number;
|
|
21
29
|
lineOpacity?: number;
|
|
22
30
|
title?: string;
|
|
23
31
|
xLabel?: string;
|
|
24
32
|
yLabel?: string;
|
|
33
|
+
yMin?: number;
|
|
34
|
+
xMin?: number;
|
|
25
35
|
debounce?: number;
|
|
26
36
|
menu?: boolean | string;
|
|
27
37
|
}>(),
|
|
@@ -81,11 +91,17 @@ const allSeries = computed<Series[]>(() => {
|
|
|
81
91
|
return [];
|
|
82
92
|
});
|
|
83
93
|
|
|
94
|
+
const allAreas = computed<Area[]>(() => props.areas ?? []);
|
|
95
|
+
|
|
84
96
|
const maxLen = computed(() => {
|
|
85
97
|
let m = 0;
|
|
86
98
|
for (const s of allSeries.value) {
|
|
87
99
|
if (s.data.length > m) m = s.data.length;
|
|
88
100
|
}
|
|
101
|
+
for (const a of allAreas.value) {
|
|
102
|
+
if (a.upper.length > m) m = a.upper.length;
|
|
103
|
+
if (a.lower.length > m) m = a.lower.length;
|
|
104
|
+
}
|
|
89
105
|
return m;
|
|
90
106
|
});
|
|
91
107
|
|
|
@@ -98,7 +114,18 @@ const extent = computed(() => {
|
|
|
98
114
|
if (v > max) max = v;
|
|
99
115
|
}
|
|
100
116
|
}
|
|
117
|
+
for (const a of allAreas.value) {
|
|
118
|
+
for (const v of a.upper) {
|
|
119
|
+
if (v < min) min = v;
|
|
120
|
+
if (v > max) max = v;
|
|
121
|
+
}
|
|
122
|
+
for (const v of a.lower) {
|
|
123
|
+
if (v < min) min = v;
|
|
124
|
+
if (v > max) max = v;
|
|
125
|
+
}
|
|
126
|
+
}
|
|
101
127
|
if (!isFinite(min)) return { min: 0, max: 0, range: 1 };
|
|
128
|
+
if (props.yMin != null && props.yMin < min) min = props.yMin;
|
|
102
129
|
return { min, max, range: max - min || 1 };
|
|
103
130
|
});
|
|
104
131
|
|
|
@@ -116,6 +143,22 @@ function toPath(data: number[]): string {
|
|
|
116
143
|
return d;
|
|
117
144
|
}
|
|
118
145
|
|
|
146
|
+
function toAreaPath(upper: number[], lower: number[]): string {
|
|
147
|
+
const len = Math.min(upper.length, lower.length);
|
|
148
|
+
if (len === 0) return "";
|
|
149
|
+
const { min, range } = extent.value;
|
|
150
|
+
const ml = maxLen.value;
|
|
151
|
+
const xScale = innerW.value / (ml - 1 || 1);
|
|
152
|
+
const yScale = innerH.value / range;
|
|
153
|
+
const py = padding.value.top + innerH.value;
|
|
154
|
+
const x = (i: number) => padding.value.left + i * xScale;
|
|
155
|
+
const y = (v: number) => py - (v - min) * yScale;
|
|
156
|
+
let d = `M${x(0)},${y(upper[0])}`;
|
|
157
|
+
for (let i = 1; i < len; i++) d += `L${x(i)},${y(upper[i])}`;
|
|
158
|
+
for (let i = len - 1; i >= 0; i--) d += `L${x(i)},${y(lower[i])}`;
|
|
159
|
+
return d + "Z";
|
|
160
|
+
}
|
|
161
|
+
|
|
119
162
|
function niceStep(range: number, targetTicks: number): number {
|
|
120
163
|
const rough = range / targetTicks;
|
|
121
164
|
const mag = Math.pow(10, Math.floor(Math.log10(rough)));
|
|
@@ -164,13 +207,14 @@ const yTicks = computed(() => {
|
|
|
164
207
|
const xTicks = computed(() => {
|
|
165
208
|
const len = maxLen.value;
|
|
166
209
|
if (len <= 1) return [];
|
|
210
|
+
const offset = props.xMin ?? 0;
|
|
167
211
|
const targetTicks = Math.max(3, Math.floor(innerW.value / 80));
|
|
168
212
|
const step = niceStep(len - 1, targetTicks);
|
|
169
213
|
const ticks: { value: string; x: number }[] = [];
|
|
170
214
|
for (let i = 0; i <= len - 1; i += step) {
|
|
171
215
|
const idx = Math.round(i);
|
|
172
216
|
ticks.push({
|
|
173
|
-
value: idx
|
|
217
|
+
value: formatTick(idx + offset),
|
|
174
218
|
x: padding.value.left + (idx / (len - 1)) * innerW.value,
|
|
175
219
|
});
|
|
176
220
|
}
|
|
@@ -309,6 +353,15 @@ const menuItems = computed<ChartMenuItem[]>(() => {
|
|
|
309
353
|
>
|
|
310
354
|
{{ xLabel }}
|
|
311
355
|
</text>
|
|
356
|
+
<!-- areas -->
|
|
357
|
+
<path
|
|
358
|
+
v-for="(a, i) in allAreas"
|
|
359
|
+
:key="'area' + i"
|
|
360
|
+
:d="toAreaPath(a.upper, a.lower)"
|
|
361
|
+
:fill="a.color ?? 'currentColor'"
|
|
362
|
+
:fill-opacity="a.opacity ?? 0.2"
|
|
363
|
+
stroke="none"
|
|
364
|
+
/>
|
|
312
365
|
<!-- data lines -->
|
|
313
366
|
<path
|
|
314
367
|
v-for="(s, i) in allSeries"
|
package/src/index.ts
CHANGED
|
@@ -1,4 +1,16 @@
|
|
|
1
|
-
export {
|
|
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";
|
|
2
14
|
export {
|
|
3
15
|
default as DataTable,
|
|
4
16
|
type TableData,
|