|
1 | 1 | <script setup lang="ts"> |
2 | 2 | import { GraphWidgetData } from "@/types"; |
3 | 3 | import { DashboardWidgetProps } from "@/dashboard/types"; |
4 | | - import { VisXYContainer, VisAxis, VisLine, VisTooltip, VisCrosshair, VisScatter } from "@unovis/vue"; |
| 4 | + import { VisXYContainer, VisAxis, VisLine, VisTooltip, VisCrosshair, VisScatter, VisArea } from "@unovis/vue"; |
5 | 5 | import { |
6 | 6 | AxisConfigInterface, BulletLegendConfigInterface, |
7 | 7 | CrosshairConfigInterface, |
8 | 8 | CurveType, |
9 | 9 | LineConfigInterface, ScatterConfigInterface, XYContainerConfigInterface, |
10 | | - Scale, TextAlign, FitMode, Scatter, |
| 10 | + Scale, TextAlign, FitMode, Scatter, AreaConfigInterface, |
11 | 11 | } from "@unovis/ts"; |
12 | 12 | import { Datum, useXYChart } from "@/dashboard/components/widgets/graph/useXYChart"; |
13 | 13 | import { ChartContainer, ChartLegendContent, ChartTooltip, ChartCrosshair } from "@/components/ui/chart"; |
| 14 | + import { computed } from "vue"; |
14 | 15 |
|
15 | 16 | const props = defineProps<DashboardWidgetProps<GraphWidgetData>>(); |
16 | 17 |
|
| 18 | + // props.value.datasets = props.value?.datasets.toReversed(); |
| 19 | +
|
17 | 20 | const { data, x, y, color, tooltipTemplate, xScale, xTickValues, tickFormat, chartConfig } = useXYChart(props); |
18 | 21 |
|
19 | 22 | // const rotate = computed(() => props.value?.labels?.length >= 10); |
| 23 | + const svgDefs = computed(() => props.value?.datasets.map((dataset, i) => ` |
| 24 | + <linearGradient id="fill-${i}" x1="0" y1="0" x2="0" y2="1"> |
| 25 | + <stop |
| 26 | + offset="5%" |
| 27 | + stop-color="${dataset.color}" |
| 28 | + stop-opacity="0.8" |
| 29 | + /> |
| 30 | + <stop |
| 31 | + offset="95%" |
| 32 | + stop-color="${dataset.color}" |
| 33 | + stop-opacity="0.1" |
| 34 | + /> |
| 35 | + </linearGradient> |
| 36 | + `).join('')); |
20 | 37 | </script> |
21 | 38 |
|
22 | 39 | <template> |
23 | 40 | <ChartContainer class="flex flex-col" :config="chartConfig"> |
24 | | - <VisXYContainer class="flex-1 min-h-0" v-bind="{ |
25 | | - xScale, |
26 | | - components: props.value?.datasets.map(dataset => new Scatter({ |
27 | | - size: 5, x: x, y: y, color: color |
28 | | - })), |
29 | | - } as XYContainerConfigInterface<Datum>" :data="data"> |
| 41 | + <VisXYContainer class="flex-1 min-h-0" |
| 42 | + v-bind="{ |
| 43 | + xScale: xScale, |
| 44 | + svgDefs: svgDefs, |
| 45 | + } as XYContainerConfigInterface<Datum>" |
| 46 | + :data="data" |
| 47 | + > |
30 | 48 | <template v-if="!props.widget.minimal"> |
31 | 49 | <VisAxis |
32 | 50 | v-bind="{ |
33 | 51 | type: 'x', |
34 | 52 | tickFormat: tickFormat, |
35 | 53 | tickValues: xTickValues, |
36 | | - // minMaxTicksOnly: true |
37 | | - // tickValues: props.value?.labels.length < 5 ? props.value?.labels.map((_, i) => x(null, i)) as number[] : undefined, |
38 | | - // numTicks: props.value?.labels.length < 10 ? props.value?.labels.length - 1 : undefined, |
39 | | - // tickTextAlign: rotate ? TextAlign.Left : TextAlign.Center, |
40 | | - // tickTextFitMode: rotate ? FitMode.Wrap : FitMode.Trim, |
41 | | - // tickTextAngle: rotate ? 45 : undefined, |
42 | | - // tickTextWidth: rotate ? 100 : undefined, |
| 54 | + gridLine: false, |
| 55 | + domainLine: false, |
43 | 56 | } as AxisConfigInterface<Datum>" |
44 | 57 | /> |
45 | | - <VisAxis v-bind="{ type: 'y' } as AxisConfigInterface<Datum>" /> |
| 58 | + <VisAxis v-bind="{ |
| 59 | + type: 'y', |
| 60 | + domainLine: false, |
| 61 | + } as AxisConfigInterface<Datum>" /> |
46 | 62 | </template> |
47 | 63 |
|
48 | 64 | <VisLine |
|
55 | 71 | } as LineConfigInterface<Datum>" |
56 | 72 | /> |
57 | 73 |
|
| 74 | + <template v-if="props.widget.options.filled"> |
| 75 | + <template v-for="(dataset, i) in props.value?.datasets.toReversed()"> |
| 76 | + <VisArea |
| 77 | + v-bind="{ |
| 78 | + x: x, |
| 79 | + y: (d) => d[i], |
| 80 | + color: () => `url(#fill-${i})`, |
| 81 | + opacity: 0.6, |
| 82 | + curveType: props.widget.options.curved ? CurveType.MonotoneX : CurveType.Linear, |
| 83 | + } as AreaConfigInterface<Datum>" |
| 84 | + /> |
| 85 | + </template> |
| 86 | + </template> |
| 87 | + |
58 | 88 | <ChartCrosshair |
59 | 89 | v-bind="{ |
60 | 90 | color: color, |
|
64 | 94 | /> |
65 | 95 | <ChartTooltip /> |
66 | 96 |
|
67 | | - <template v-if="props.value?.labels.length < 40"> |
68 | | - <template v-for="dataset in props.value?.datasets"> |
69 | | - <VisScatter |
70 | | - v-bind="{ size: 4, x: x, y: y, strokeColor: color, color: 'var(--background)' } as ScatterConfigInterface<Datum>" |
71 | | - /> |
72 | | - </template> |
73 | | - </template> |
74 | | - |
| 97 | +<!-- <template v-if="props.value?.labels.length < 40">--> |
| 98 | +<!-- <template v-for="dataset in props.value?.datasets">--> |
| 99 | +<!-- <VisScatter--> |
| 100 | +<!-- v-bind="{ size: 4, x: x, y: y, strokeColor: color, color: 'var(--background)' } as ScatterConfigInterface<Datum>"--> |
| 101 | +<!-- />--> |
| 102 | +<!-- </template>--> |
| 103 | +<!-- </template>--> |
75 | 104 | </VisXYContainer> |
76 | 105 | <template v-if="props.widget.showLegend && !props.widget.minimal"> |
77 | 106 | <ChartLegendContent /> |
|
0 commit comments