vue-chrts 0.0.118 → 0.0.119
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/.vscode/extensions.json +3 -0
- package/image.png +0 -0
- package/index.html +14 -0
- package/package.json +1 -5
- package/src/components/Area/AreaChart.vue +141 -0
- package/src/components/Area/index.ts +1 -0
- package/src/components/AreaStacked/AreaStackedChart.vue +51 -0
- package/{dist/components/AreaStacked/index.d.ts → src/components/AreaStacked/index.ts} +1 -1
- package/src/components/Bar/BarChart.vue +130 -0
- package/src/components/Bar/index.ts +1 -0
- package/src/components/Crosshair/Crosshair.vue +46 -0
- package/src/components/Crosshair/index.ts +1 -0
- package/src/components/Donut/DonutChart.vue +71 -0
- package/src/components/Donut/index.ts +1 -0
- package/src/components/Line/LineChart.vue +94 -0
- package/src/components/Line/index.ts +1 -0
- package/src/components/Tooltip.vue +17 -0
- package/src/components.ts +6 -0
- package/src/index.ts +6 -0
- package/src/shims-vue.d.ts +1 -0
- package/src-demo/AdminTemplate.vue +5 -0
- package/src-demo/App.vue +37 -0
- package/src-demo/AreaChartPage.vue +125 -0
- package/src-demo/BarChartPage.vue +166 -0
- package/src-demo/DashboardTemplate.vue +687 -0
- package/src-demo/Homepage.vue +325 -0
- package/src-demo/LineChartPage.vue +140 -0
- package/src-demo/assets/main.css +34 -0
- package/src-demo/components/Progress/Progress.vue +42 -0
- package/src-demo/components/Progress/index.ts +1 -0
- package/src-demo/components/Status/Status.vue +95 -0
- package/src-demo/components/Status/index.ts +1 -0
- package/src-demo/components/charts.ts +37 -0
- package/src-demo/components/index.ts +49 -0
- package/src-demo/data/AreaChartData.ts +294 -0
- package/src-demo/data/BarChartData.ts +79 -0
- package/src-demo/data/IncomeExpenseData.ts +189 -0
- package/src-demo/data/InvestmentData.ts +352 -0
- package/src-demo/data/RevenueData.ts +58 -0
- package/src-demo/data/VisitorsData.ts +260 -0
- package/src-demo/elements/Button.vue +13 -0
- package/src-demo/elements/Card.vue +17 -0
- package/src-demo/elements/Dropdown.vue +112 -0
- package/src-demo/elements/Logo.vue +8 -0
- package/src-demo/elements/Table.vue +363 -0
- package/src-demo/elements/TopBar.vue +40 -0
- package/src-demo/index.ts +58 -0
- package/tsconfig.json +11 -0
- package/vite.config.ts +60 -0
- package/dist/components/Area/AreaChart.vue.d.ts +0 -37
- package/dist/components/Area/index.d.ts +0 -1
- package/dist/components/AreaStacked/AreaStackedChart.vue.d.ts +0 -18
- package/dist/components/Bar/BarChart.vue.d.ts +0 -37
- package/dist/components/Bar/index.d.ts +0 -1
- package/dist/components/Crosshair/Crosshair.vue.d.ts +0 -38
- package/dist/components/Crosshair/index.d.ts +0 -1
- package/dist/components/Donut/DonutChart.vue.d.ts +0 -31
- package/dist/components/Donut/index.d.ts +0 -1
- package/dist/components/Line/LineChart.vue.d.ts +0 -28
- package/dist/components/Line/index.d.ts +0 -1
- package/dist/components/Tooltip.vue.d.ts +0 -14
- package/dist/components.d.ts +0 -6
- package/dist/index.cjs +0 -502
- package/dist/index.cjs.map +0 -1
- package/dist/index.d.ts +0 -5
- package/dist/index.js +0 -9615
- package/dist/index.js.map +0 -1
- /package/{dist → public}/vite.svg +0 -0
package/image.png
ADDED
|
Binary file
|
package/index.html
ADDED
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
<!doctype html>
|
|
2
|
+
<html lang="en">
|
|
3
|
+
<head>
|
|
4
|
+
<meta charset="UTF-8" />
|
|
5
|
+
<link rel="icon" type="image/svg+xml" href="/vite.svg" />
|
|
6
|
+
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
|
7
|
+
<title>Vite + Vue + TS</title>
|
|
8
|
+
</head>
|
|
9
|
+
<body class="bg-white dark:bg-background">
|
|
10
|
+
<div id="app">
|
|
11
|
+
</div>
|
|
12
|
+
<script type="module" src="/src-demo/index.ts"></script>
|
|
13
|
+
</body>
|
|
14
|
+
</html>
|
package/package.json
CHANGED
|
@@ -0,0 +1,141 @@
|
|
|
1
|
+
<script setup lang="ts" generic="T">
|
|
2
|
+
import { computed, createApp } from "vue";
|
|
3
|
+
import type { BulletLegendItemInterface, NumericAccessor } from "@unovis/ts";
|
|
4
|
+
import { CurveType, Position } from "@unovis/ts";
|
|
5
|
+
import {
|
|
6
|
+
VisArea,
|
|
7
|
+
VisAxis,
|
|
8
|
+
VisBulletLegend,
|
|
9
|
+
VisCrosshair,
|
|
10
|
+
VisLine,
|
|
11
|
+
VisTooltip,
|
|
12
|
+
VisXYContainer,
|
|
13
|
+
} from "@unovis/vue";
|
|
14
|
+
|
|
15
|
+
import Tooltip from "./../Tooltip.vue";
|
|
16
|
+
import { PaginationPosition } from "../..";
|
|
17
|
+
|
|
18
|
+
export type AreaChartProps<T> = {
|
|
19
|
+
data: T[];
|
|
20
|
+
height: number;
|
|
21
|
+
xLabel?: string;
|
|
22
|
+
yLabel?: string;
|
|
23
|
+
categories: Record<string, BulletLegendItemInterface>;
|
|
24
|
+
xFormatter: (i: number, idx: number) => string;
|
|
25
|
+
yFormatter?: (i: number, idx?: number) => string | number;
|
|
26
|
+
curveType?: CurveType;
|
|
27
|
+
xNumTicks?: number;
|
|
28
|
+
yNumTicks?: number;
|
|
29
|
+
hideLegend?: boolean;
|
|
30
|
+
hideTooltip?: boolean;
|
|
31
|
+
gridLineX?: boolean;
|
|
32
|
+
domainLineX?: boolean;
|
|
33
|
+
gridLineY?: boolean;
|
|
34
|
+
domainLineY?: boolean;
|
|
35
|
+
paginationPoisition?: PaginationPosition;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
const props = withDefaults(
|
|
39
|
+
defineProps<AreaChartProps<T>>(),
|
|
40
|
+
{
|
|
41
|
+
xNumTicks: (props) =>
|
|
42
|
+
props.data.length > 24 ? 24 / 4 : props.data.length - 1,
|
|
43
|
+
yNumTicks: (props) =>
|
|
44
|
+
props.data.length > 24 ? 24 / 4 : props.data.length - 1,
|
|
45
|
+
}
|
|
46
|
+
);
|
|
47
|
+
|
|
48
|
+
const colors = Object.values(props.categories).map((c) => c.color);
|
|
49
|
+
|
|
50
|
+
const generateTooltip = computed(() => (d: T) => {
|
|
51
|
+
const app = createApp(Tooltip, {
|
|
52
|
+
data: d,
|
|
53
|
+
categories: props.categories,
|
|
54
|
+
});
|
|
55
|
+
|
|
56
|
+
const container = document.createElement("div");
|
|
57
|
+
app.mount(container);
|
|
58
|
+
|
|
59
|
+
const html = container.innerHTML;
|
|
60
|
+
app.unmount();
|
|
61
|
+
|
|
62
|
+
return html;
|
|
63
|
+
});
|
|
64
|
+
|
|
65
|
+
function accessors(id: string): { y: NumericAccessor<T>; color: string } {
|
|
66
|
+
return {
|
|
67
|
+
y: (d: T) => Number(d[id as keyof typeof d]),
|
|
68
|
+
color: props.categories[id]?.color ?? "#3b82f6",
|
|
69
|
+
};
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
const svgDefs = colors
|
|
73
|
+
.map(
|
|
74
|
+
(color, index) => `
|
|
75
|
+
<linearGradient id="gradient${index}-${color}" gradientTransform="rotate(90)">
|
|
76
|
+
<stop offset="0%" stop-color="${color}" stop-opacity="1" />
|
|
77
|
+
<stop offset="100%" stop-color="${color}" stop-opacity="0" />
|
|
78
|
+
</linearGradient>
|
|
79
|
+
`
|
|
80
|
+
)
|
|
81
|
+
.join("");
|
|
82
|
+
</script>
|
|
83
|
+
|
|
84
|
+
<template>
|
|
85
|
+
<div
|
|
86
|
+
class="flex flex-col space-y-4"
|
|
87
|
+
:class="{
|
|
88
|
+
'flex-col-reverse': props.paginationPoisition === 'top',
|
|
89
|
+
}"
|
|
90
|
+
>
|
|
91
|
+
<VisXYContainer :data="data" :height="height" :svg-defs="svgDefs">
|
|
92
|
+
<VisTooltip
|
|
93
|
+
v-if="!hideTooltip"
|
|
94
|
+
:horizontal-placement="Position.Right"
|
|
95
|
+
:vertical-placement="Position.Top"
|
|
96
|
+
/>
|
|
97
|
+
<template v-for="(i, iKey) in Object.keys(props.categories)" :key="iKey">
|
|
98
|
+
<VisArea
|
|
99
|
+
:x="(_: T, i: number) => i"
|
|
100
|
+
v-bind="accessors(i)"
|
|
101
|
+
:color="`url(#gradient${iKey}-${colors[iKey]})`"
|
|
102
|
+
:opacity="0.5"
|
|
103
|
+
:curve-type="curveType ?? CurveType.MonotoneX"
|
|
104
|
+
/>
|
|
105
|
+
<VisLine
|
|
106
|
+
:x="(_: any, i: number) => i"
|
|
107
|
+
:y="(d: T) => d[i as keyof typeof d]"
|
|
108
|
+
:color="colors[iKey]"
|
|
109
|
+
:curve-type="curveType ?? CurveType.MonotoneX"
|
|
110
|
+
/>
|
|
111
|
+
</template>
|
|
112
|
+
|
|
113
|
+
<VisAxis
|
|
114
|
+
type="x"
|
|
115
|
+
:tick-format="xFormatter"
|
|
116
|
+
:num-ticks="xNumTicks"
|
|
117
|
+
:label="xLabel"
|
|
118
|
+
:grid-line="gridLineX"
|
|
119
|
+
:domain-line="domainLineX"
|
|
120
|
+
:tick-line="!!gridLineX"
|
|
121
|
+
/>
|
|
122
|
+
<VisAxis
|
|
123
|
+
type="y"
|
|
124
|
+
:num-ticks="yNumTicks ?? data.length"
|
|
125
|
+
:tick-format="yFormatter"
|
|
126
|
+
:label="yLabel"
|
|
127
|
+
:grid-line="gridLineY"
|
|
128
|
+
:domain-line="domainLineY"
|
|
129
|
+
:tick-line="!!gridLineY"
|
|
130
|
+
/>
|
|
131
|
+
<VisCrosshair
|
|
132
|
+
v-if="!hideTooltip"
|
|
133
|
+
color="#666"
|
|
134
|
+
:template="generateTooltip"
|
|
135
|
+
/>
|
|
136
|
+
</VisXYContainer>
|
|
137
|
+
<div v-if="!hideLegend" class="flex items center justify-end">
|
|
138
|
+
<VisBulletLegend :items="Object.values(categories)" />
|
|
139
|
+
</div>
|
|
140
|
+
</div>
|
|
141
|
+
</template>
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { default as AreaChart } from './AreaChart.vue';
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
<script setup lang="ts" generic="T">
|
|
2
|
+
import { VisXYContainer, VisAxis, VisArea, VisBulletLegend } from '@unovis/vue'
|
|
3
|
+
import { BulletLegendItemInterface, CurveType } from '@unovis/ts'
|
|
4
|
+
|
|
5
|
+
export type AreaStackedChartProps<T> = {
|
|
6
|
+
data: T[];
|
|
7
|
+
categories: Record<string, BulletLegendItemInterface>;
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
const props = defineProps<AreaStackedChartProps<T>>()
|
|
11
|
+
|
|
12
|
+
const x = (d: any) => {
|
|
13
|
+
return Number.parseInt(d.time)
|
|
14
|
+
}
|
|
15
|
+
const y = [
|
|
16
|
+
(d: any) => d.firstTime,
|
|
17
|
+
(d: any) => d.returning
|
|
18
|
+
]
|
|
19
|
+
</script>
|
|
20
|
+
|
|
21
|
+
<template>
|
|
22
|
+
<div class="flex flex-col space-y-4">
|
|
23
|
+
<VisXYContainer
|
|
24
|
+
:data="data"
|
|
25
|
+
:height="200"
|
|
26
|
+
>
|
|
27
|
+
<VisArea
|
|
28
|
+
:x="x"
|
|
29
|
+
:y="y"
|
|
30
|
+
:color="Object.values(props.categories).map((i) => i.color) "
|
|
31
|
+
:curve-type="CurveType.Linear"
|
|
32
|
+
/>
|
|
33
|
+
<VisAxis
|
|
34
|
+
type="x"
|
|
35
|
+
label="Time"
|
|
36
|
+
:num-ticks="12"
|
|
37
|
+
|
|
38
|
+
/>
|
|
39
|
+
<VisAxis
|
|
40
|
+
type="y"
|
|
41
|
+
label="Number of visitors"
|
|
42
|
+
:num-ticks="3"
|
|
43
|
+
/>
|
|
44
|
+
</VisXYContainer>
|
|
45
|
+
<div class="flex items center justify-end">
|
|
46
|
+
<VisBulletLegend
|
|
47
|
+
:items="Object.values(categories)"
|
|
48
|
+
/>
|
|
49
|
+
</div>
|
|
50
|
+
</div>
|
|
51
|
+
</template>
|
|
@@ -1 +1 @@
|
|
|
1
|
-
export { default as AreaStackedChart } from './AreaStackedChart.vue';
|
|
1
|
+
export { default as AreaStackedChart } from './AreaStackedChart.vue';
|
|
@@ -0,0 +1,130 @@
|
|
|
1
|
+
<script setup lang="ts" generic="T">
|
|
2
|
+
import { computed, ComputedRef, createApp } from "vue";
|
|
3
|
+
import { BulletLegendItemInterface, GroupedBar, Orientation } from "@unovis/ts";
|
|
4
|
+
|
|
5
|
+
import {
|
|
6
|
+
VisAxis,
|
|
7
|
+
VisBulletLegend,
|
|
8
|
+
VisGroupedBar,
|
|
9
|
+
VisStackedBar,
|
|
10
|
+
VisTooltip,
|
|
11
|
+
VisXYContainer,
|
|
12
|
+
} from "@unovis/vue";
|
|
13
|
+
|
|
14
|
+
import Tooltip from "./../Tooltip.vue";
|
|
15
|
+
import { PaginationPosition } from "../..";
|
|
16
|
+
|
|
17
|
+
export type BarChartProps<T> = {
|
|
18
|
+
data: T[];
|
|
19
|
+
stacked?: boolean;
|
|
20
|
+
height: number;
|
|
21
|
+
xLabel?: string;
|
|
22
|
+
yLabel?: string;
|
|
23
|
+
categories: Record<string, BulletLegendItemInterface>;
|
|
24
|
+
xFormatter: (i: number, idx?: number) => string | number;
|
|
25
|
+
yFormatter?: (i: number, idx?: number) => string | number;
|
|
26
|
+
yNumTicks?: number;
|
|
27
|
+
xNumTicks?: number;
|
|
28
|
+
yAxis: (keyof T)[];
|
|
29
|
+
groupPadding?: number;
|
|
30
|
+
barPadding?: number;
|
|
31
|
+
radius?: number;
|
|
32
|
+
hideLegend?: boolean;
|
|
33
|
+
orientation?: Orientation;
|
|
34
|
+
paginationPosition?: PaginationPosition;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
const props = withDefaults(
|
|
38
|
+
defineProps<BarChartProps<T>>(),
|
|
39
|
+
{
|
|
40
|
+
orientation: Orientation.Vertical,
|
|
41
|
+
paginationPosition: PaginationPosition.Bottom
|
|
42
|
+
}
|
|
43
|
+
);
|
|
44
|
+
|
|
45
|
+
const yAxis: ComputedRef<((d: T) => T[keyof T])[]> = computed(() => {
|
|
46
|
+
return props.yAxis.map((key) => (d: T) => {
|
|
47
|
+
return d[key];
|
|
48
|
+
});
|
|
49
|
+
});
|
|
50
|
+
|
|
51
|
+
const color = (_: T, i: number) => Object.values(props.categories)[i].color;
|
|
52
|
+
|
|
53
|
+
const generateTooltip = computed(() => (d: T) => {
|
|
54
|
+
const app = createApp(Tooltip, {
|
|
55
|
+
data: d,
|
|
56
|
+
categories: props.categories,
|
|
57
|
+
});
|
|
58
|
+
|
|
59
|
+
const container = document.createElement("div");
|
|
60
|
+
app.mount(container);
|
|
61
|
+
|
|
62
|
+
const html = container.innerHTML;
|
|
63
|
+
app.unmount();
|
|
64
|
+
|
|
65
|
+
return html;
|
|
66
|
+
});
|
|
67
|
+
|
|
68
|
+
const PaginationPositionTop = computed(() => props.paginationPosition === PaginationPosition.Top)
|
|
69
|
+
</script>
|
|
70
|
+
|
|
71
|
+
<template>
|
|
72
|
+
<div
|
|
73
|
+
class="flex flex-col space-y-4"
|
|
74
|
+
:class="{'flex-col-reverse' : PaginationPositionTop}"
|
|
75
|
+
>
|
|
76
|
+
<VisXYContainer :height="height">
|
|
77
|
+
<VisTooltip
|
|
78
|
+
:triggers="{
|
|
79
|
+
[GroupedBar.selectors.bar]: generateTooltip,
|
|
80
|
+
}"
|
|
81
|
+
/>
|
|
82
|
+
|
|
83
|
+
<VisGroupedBar
|
|
84
|
+
v-if="!stacked"
|
|
85
|
+
:data="data"
|
|
86
|
+
:x="(_: T, i: number) => i"
|
|
87
|
+
:y="yAxis"
|
|
88
|
+
:grid-line="false"
|
|
89
|
+
:domain-line="false"
|
|
90
|
+
:color="color"
|
|
91
|
+
:rounded-corners="radius ?? 0"
|
|
92
|
+
:group-padding="groupPadding ?? 0"
|
|
93
|
+
:bar-padding="barPadding ?? 0.2"
|
|
94
|
+
:orientation="orientation ?? Orientation.Vertical"
|
|
95
|
+
/>
|
|
96
|
+
<VisStackedBar
|
|
97
|
+
v-else
|
|
98
|
+
:data="data"
|
|
99
|
+
:x="(_: T, i: number) => i"
|
|
100
|
+
:y="yAxis"
|
|
101
|
+
:grid-line="false"
|
|
102
|
+
:domain-line="false"
|
|
103
|
+
:color="color"
|
|
104
|
+
:rounded-corners="radius ?? 0"
|
|
105
|
+
:group-padding="groupPadding ?? 0"
|
|
106
|
+
:bar-padding="barPadding ?? 0.2"
|
|
107
|
+
:orientation="orientation ?? Orientation.Vertical"
|
|
108
|
+
/>
|
|
109
|
+
<VisAxis
|
|
110
|
+
type="x"
|
|
111
|
+
:label="xLabel"
|
|
112
|
+
:grid-line="false"
|
|
113
|
+
:domain-line="false"
|
|
114
|
+
:tick-format="xFormatter"
|
|
115
|
+
:num-ticks="xNumTicks"
|
|
116
|
+
:tick-line="false"
|
|
117
|
+
/>
|
|
118
|
+
<VisAxis
|
|
119
|
+
type="y"
|
|
120
|
+
:label="yLabel"
|
|
121
|
+
:grid-line="orientation !== Orientation.Horizontal"
|
|
122
|
+
:domain-line="false"
|
|
123
|
+
:tick-format="yFormatter"
|
|
124
|
+
/>
|
|
125
|
+
</VisXYContainer>
|
|
126
|
+
<div v-if="!hideLegend" class="flex items center justify-end" :class="{'pb-4' : PaginationPositionTop}">
|
|
127
|
+
<VisBulletLegend :items="Object.values(categories)" />
|
|
128
|
+
</div>
|
|
129
|
+
</div>
|
|
130
|
+
</template>
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { default as BarChart } from './BarChart.vue';
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
<script setup lang="ts">
|
|
2
|
+
import type { BulletLegendItemInterface } from '@unovis/ts'
|
|
3
|
+
import { omit } from '@unovis/ts'
|
|
4
|
+
import { VisCrosshair, VisTooltip } from '@unovis/vue'
|
|
5
|
+
import { type Component, createApp } from 'vue'
|
|
6
|
+
|
|
7
|
+
const props = withDefaults(defineProps<{
|
|
8
|
+
colors: string[]
|
|
9
|
+
index: string
|
|
10
|
+
items: BulletLegendItemInterface[]
|
|
11
|
+
customTooltip?: Component
|
|
12
|
+
}>(), {
|
|
13
|
+
colors: () => [],
|
|
14
|
+
})
|
|
15
|
+
|
|
16
|
+
// Use weakmap to store reference to each datapoint for Tooltip
|
|
17
|
+
const wm = new WeakMap()
|
|
18
|
+
function template(d: any) {
|
|
19
|
+
if (wm.has(d)) {
|
|
20
|
+
return wm.get(d)
|
|
21
|
+
}
|
|
22
|
+
else {
|
|
23
|
+
if (typeof window !== 'undefined') {
|
|
24
|
+
const componentDiv = document.createElement('div')
|
|
25
|
+
const omittedData = Object.entries(omit(d, [props.index])).map(([key, value]) => {
|
|
26
|
+
const legendReference = props.items.find(i => i.name === key)
|
|
27
|
+
return { ...legendReference, value }
|
|
28
|
+
})
|
|
29
|
+
const TooltipComponent = props.customTooltip ?? VisTooltip
|
|
30
|
+
createApp(TooltipComponent, { title: d[props.index].toString(), data: omittedData }).mount(componentDiv)
|
|
31
|
+
wm.set(d, componentDiv.innerHTML)
|
|
32
|
+
return componentDiv.innerHTML
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
function color(_: unknown, i: number) {
|
|
39
|
+
return props.colors[i] ?? 'transparent'
|
|
40
|
+
}
|
|
41
|
+
</script>
|
|
42
|
+
|
|
43
|
+
<template>
|
|
44
|
+
<VisTooltip :horizontal-shift="20" :vertical-shift="20" />
|
|
45
|
+
<VisCrosshair :template="template" :color="color" />
|
|
46
|
+
</template>
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { default as Crosshair } from './Crosshair.vue';
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
<script setup lang="ts">
|
|
2
|
+
import { Donut } from "@unovis/ts";
|
|
3
|
+
import {
|
|
4
|
+
VisBulletLegend,
|
|
5
|
+
VisDonut,
|
|
6
|
+
VisSingleContainer,
|
|
7
|
+
VisTooltip,
|
|
8
|
+
} from "@unovis/vue";
|
|
9
|
+
|
|
10
|
+
export type DonutChartProps = {
|
|
11
|
+
type?: string;
|
|
12
|
+
data: number[];
|
|
13
|
+
height: number;
|
|
14
|
+
radius: number;
|
|
15
|
+
hidePagination?: boolean
|
|
16
|
+
labels: {
|
|
17
|
+
name: string;
|
|
18
|
+
color: string;
|
|
19
|
+
}[];
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
const props = defineProps<DonutChartProps>();
|
|
23
|
+
|
|
24
|
+
const value = (d: number) => d;
|
|
25
|
+
|
|
26
|
+
const isHalf = props.type === "half";
|
|
27
|
+
|
|
28
|
+
const tooltip = {
|
|
29
|
+
[Donut.selectors.segment]: (d: any) => {
|
|
30
|
+
console.log();
|
|
31
|
+
|
|
32
|
+
return `<div class='flex items-center'><div class='w-2 h-2 rounded-full mr-2' style='background-color: ${
|
|
33
|
+
props.labels[d.index].color
|
|
34
|
+
} ;'></div>
|
|
35
|
+
<div>${d.data}</div>
|
|
36
|
+
</vistooltip>
|
|
37
|
+
</vissinglecontainer>
|
|
38
|
+
</div>`;
|
|
39
|
+
},
|
|
40
|
+
};
|
|
41
|
+
</script>
|
|
42
|
+
|
|
43
|
+
<template>
|
|
44
|
+
<div class="flex items-center justify-center">
|
|
45
|
+
<VisSingleContainer
|
|
46
|
+
:class="isHalf ? 'mt-24' : ''"
|
|
47
|
+
:data="data"
|
|
48
|
+
:height="height"
|
|
49
|
+
:margin="{}"
|
|
50
|
+
>
|
|
51
|
+
<VisTooltip
|
|
52
|
+
:horizontal-shift="20"
|
|
53
|
+
:vertical-shift="20"
|
|
54
|
+
:triggers="tooltip"
|
|
55
|
+
/>
|
|
56
|
+
|
|
57
|
+
<VisDonut
|
|
58
|
+
:value="value"
|
|
59
|
+
:corner-radius="radius"
|
|
60
|
+
:color="props.labels.map((l) => l.color)"
|
|
61
|
+
:angle-range="isHalf ? [-1.5707963267948966, 1.5707963267948966] : []"
|
|
62
|
+
/>
|
|
63
|
+
</VisSingleContainer>
|
|
64
|
+
|
|
65
|
+
<slot />
|
|
66
|
+
</div>
|
|
67
|
+
|
|
68
|
+
<div v-if="!hidePagination" class="flex items-center justify-center mt-4">
|
|
69
|
+
<VisBulletLegend :items="labels" />
|
|
70
|
+
</div>
|
|
71
|
+
</template>
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { default as DonutChart } from './DonutChart.vue';
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
<script setup lang="ts" generic="T">
|
|
2
|
+
import { computed, createApp } from "vue";
|
|
3
|
+
|
|
4
|
+
import { CurveType, BulletLegendItemInterface, Position } from "@unovis/ts";
|
|
5
|
+
|
|
6
|
+
import Tooltip from "./../Tooltip.vue";
|
|
7
|
+
import { PaginationPosition } from "../..";
|
|
8
|
+
|
|
9
|
+
import {
|
|
10
|
+
VisAxis,
|
|
11
|
+
VisBulletLegend,
|
|
12
|
+
VisCrosshair,
|
|
13
|
+
VisLine,
|
|
14
|
+
VisXYContainer,
|
|
15
|
+
VisTooltip,
|
|
16
|
+
} from "@unovis/vue";
|
|
17
|
+
|
|
18
|
+
export type LineChartProps<T> = {
|
|
19
|
+
data: T[];
|
|
20
|
+
height: number;
|
|
21
|
+
xLabel?: string;
|
|
22
|
+
yLabel?: string;
|
|
23
|
+
categories: Record<string, BulletLegendItemInterface>;
|
|
24
|
+
xFormatter: (i: number, idx: number) => string;
|
|
25
|
+
yFormatter?: (i: number, idx: number) => string;
|
|
26
|
+
curveType?: CurveType;
|
|
27
|
+
yNumTicks?: number;
|
|
28
|
+
xNumTicks?: number;
|
|
29
|
+
paginationPosition?: PaginationPosition;
|
|
30
|
+
};
|
|
31
|
+
|
|
32
|
+
const props = defineProps<LineChartProps<T>>();
|
|
33
|
+
|
|
34
|
+
const color = (key: number) => Object.values(props.categories)[key].color;
|
|
35
|
+
|
|
36
|
+
const generateTooltip = computed(() => (d: T) => {
|
|
37
|
+
const app = createApp(Tooltip, {
|
|
38
|
+
data: d,
|
|
39
|
+
categories: props.categories,
|
|
40
|
+
});
|
|
41
|
+
|
|
42
|
+
const container = document.createElement("div");
|
|
43
|
+
app.mount(container);
|
|
44
|
+
|
|
45
|
+
const html = container.innerHTML;
|
|
46
|
+
app.unmount();
|
|
47
|
+
|
|
48
|
+
return html;
|
|
49
|
+
});
|
|
50
|
+
</script>
|
|
51
|
+
|
|
52
|
+
<template>
|
|
53
|
+
<div
|
|
54
|
+
class="space-y-4 flex flex-col"
|
|
55
|
+
:class="{
|
|
56
|
+
'flex-col-reverse': props.paginationPosition === 'top',
|
|
57
|
+
}"
|
|
58
|
+
>
|
|
59
|
+
<VisXYContainer :data="data" :height="height">
|
|
60
|
+
<VisTooltip
|
|
61
|
+
:horizontal-placement="Position.Right"
|
|
62
|
+
:vertical-placement="Position.Top"
|
|
63
|
+
/>
|
|
64
|
+
<template v-for="(i, iKey) in Object.keys(props.categories)" :key="iKey">
|
|
65
|
+
<VisLine
|
|
66
|
+
:x="(_: any, i: number) => i"
|
|
67
|
+
:y="(d: T) => d[i as keyof typeof d]"
|
|
68
|
+
:color="color(iKey)"
|
|
69
|
+
:curve-type="curveType ?? CurveType.MonotoneX"
|
|
70
|
+
/>
|
|
71
|
+
</template>
|
|
72
|
+
<VisAxis
|
|
73
|
+
type="x"
|
|
74
|
+
:tick-format="xFormatter"
|
|
75
|
+
:num-ticks="xNumTicks ?? 4"
|
|
76
|
+
:label="xLabel"
|
|
77
|
+
:label-margin="8"
|
|
78
|
+
:domain-line="false"
|
|
79
|
+
:grid-line="false"
|
|
80
|
+
/>
|
|
81
|
+
<VisAxis
|
|
82
|
+
type="y"
|
|
83
|
+
:num-ticks="yNumTicks ?? 4"
|
|
84
|
+
:tick-format="yFormatter"
|
|
85
|
+
:label="yLabel"
|
|
86
|
+
:domain-line="false"
|
|
87
|
+
/>
|
|
88
|
+
<VisCrosshair color="#666" :template="generateTooltip" />
|
|
89
|
+
</VisXYContainer>
|
|
90
|
+
<div class="flex items center justify-end">
|
|
91
|
+
<VisBulletLegend :items="Object.values(categories)" />
|
|
92
|
+
</div>
|
|
93
|
+
</div>
|
|
94
|
+
</template>
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { default as LineChart } from './LineChart.vue';
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<div class="flex flex-col">
|
|
3
|
+
<template v-for="[key, value] in Object.entries(data)" :key="key">
|
|
4
|
+
<div class="flex items-center mr-2 mt-2">
|
|
5
|
+
<!-- <span class="w-3 h-3 rounded-full bg-[#10b981] mr-2"></span> -->
|
|
6
|
+
<span class="font-semibold capitalize text-white/75">{{ key }}:</span>
|
|
7
|
+
</div>
|
|
8
|
+
<span class="font-normal">{{ value }}</span>
|
|
9
|
+
</template>
|
|
10
|
+
</div>
|
|
11
|
+
</template>
|
|
12
|
+
|
|
13
|
+
<script lang="ts" setup generic="T">
|
|
14
|
+
const props = defineProps<{
|
|
15
|
+
data: T;
|
|
16
|
+
}>();
|
|
17
|
+
</script>
|
package/src/index.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
declare module '*.vue';
|
package/src-demo/App.vue
ADDED
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
<script lang="ts" setup>
|
|
2
|
+
import { computed } from "vue";
|
|
3
|
+
|
|
4
|
+
import { useColorMode } from "@vueuse/core";
|
|
5
|
+
useColorMode();
|
|
6
|
+
|
|
7
|
+
const displayCopyright = computed(() => {
|
|
8
|
+
const currentYear = new Date().getFullYear();
|
|
9
|
+
return `Made with 💚 ~ © ${currentYear} Dennis Adriaansen, Inc. All rights reserved.`;
|
|
10
|
+
});
|
|
11
|
+
</script>
|
|
12
|
+
|
|
13
|
+
<template>
|
|
14
|
+
<div>
|
|
15
|
+
<RouterView />
|
|
16
|
+
<div class="border-t border-border mt-8">
|
|
17
|
+
<div class="max-w-7xl mx-auto py-8 flex items-center justify-between">
|
|
18
|
+
<div v-html="displayCopyright"></div>
|
|
19
|
+
<div>
|
|
20
|
+
<a href="https://x.com/DennisAdriaans" target="_blank">
|
|
21
|
+
<svg
|
|
22
|
+
xmlns="http://www.w3.org/2000/svg"
|
|
23
|
+
viewBox="0 0 30 30"
|
|
24
|
+
width="30px"
|
|
25
|
+
height="30px"
|
|
26
|
+
>
|
|
27
|
+
<path
|
|
28
|
+
fill="currentColor"
|
|
29
|
+
d="M26.37,26l-8.795-12.822l0.015,0.012L25.52,4h-2.65l-6.46,7.48L11.28,4H4.33l8.211,11.971L12.54,15.97L3.88,26h2.65 l7.182-8.322L19.42,26H26.37z M10.23,6l12.34,18h-2.1L8.12,6H10.23z"
|
|
30
|
+
/>
|
|
31
|
+
</svg>
|
|
32
|
+
</a>
|
|
33
|
+
</div>
|
|
34
|
+
</div>
|
|
35
|
+
</div>
|
|
36
|
+
</div>
|
|
37
|
+
</template>
|