Skip to content

Commit

Permalink
style: fix vue-tsc warnings
Browse files Browse the repository at this point in the history
  • Loading branch information
BrewingWeasel committed Aug 17, 2024
1 parent 67f7f8d commit 1e6d891
Show file tree
Hide file tree
Showing 6 changed files with 267 additions and 178 deletions.
1 change: 0 additions & 1 deletion src/components/ButtonDialog.vue
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,6 @@ import {
Card,
CardContent,
CardDescription,
CardFooter,
CardHeader,
CardTitle,
} from "@/components/ui/card";
Expand Down
150 changes: 93 additions & 57 deletions src/components/ui/chart-bar/BarChart.vue
Original file line number Diff line number Diff line change
@@ -1,86 +1,122 @@
<script setup lang="ts" generic="T extends Record<string, any>">
import type { BulletLegendItemInterface } from '@unovis/ts'
import { VisAxis, VisGroupedBar, VisStackedBar, VisXYContainer } from '@unovis/vue'
import { Axis, GroupedBar, StackedBar } from '@unovis/ts'
import { type Component, computed, ref } from 'vue'
import { useMounted } from '@vueuse/core'
import type { BaseChartProps } from '.'
import { ChartCrosshair, ChartLegend, defaultColors } from '@/components/ui/chart'
import { cn } from '@/lib/utils'
import type { BulletLegendItemInterface } from "@unovis/ts";
import {
VisAxis,
VisGroupedBar,
VisStackedBar,
VisXYContainer,
} from "@unovis/vue";
import { Axis, GroupedBar, StackedBar } from "@unovis/ts";
import { type Component, computed, ref } from "vue";
import { useMounted } from "@vueuse/core";
import type { BaseChartProps } from ".";
import {
ChartCrosshair,
ChartLegend,
defaultColors,
} from "@/components/ui/chart";
import { cn } from "@/lib/utils";
const props = withDefaults(defineProps<BaseChartProps<T> & {
/**
* Render custom tooltip component.
*/
customTooltip?: Component
/**
* Change the type of the chart
* @default "grouped"
*/
type?: 'stacked' | 'grouped'
/**
* Rounded bar corners
* @default 0
*/
roundedCorners?: number
}>(), {
type: 'grouped',
margin: () => ({ top: 0, bottom: 0, left: 0, right: 0 }),
filterOpacity: 0.2,
roundedCorners: 0,
showXAxis: true,
showYAxis: true,
showTooltip: true,
showLegend: true,
showGridLine: true,
})
const props = withDefaults(
defineProps<
BaseChartProps<T> & {
/**
* Render custom tooltip component.
*/
customTooltip?: Component;
/**
* Change the type of the chart
* @default "grouped"
*/
type?: "stacked" | "grouped";
/**
* Rounded bar corners
* @default 0
*/
roundedCorners?: number;
}
>(),
{
type: "grouped",
margin: () => ({ top: 0, bottom: 0, left: 0, right: 0 }),
filterOpacity: 0.2,
roundedCorners: 0,
showXAxis: true,
showYAxis: true,
showTooltip: true,
showLegend: true,
showGridLine: true,
},
);
const emits = defineEmits<{
legendItemClick: [d: BulletLegendItemInterface, i: number]
}>()
legendItemClick: [d: BulletLegendItemInterface, i: number];
}>();
type KeyOfT = Extract<keyof T, string>
type Data = typeof props.data[number]
type KeyOfT = Extract<keyof T, string>;
type Data = (typeof props.data)[number];
const index = computed(() => props.index as KeyOfT)
const colors = computed(() => props.colors?.length ? props.colors : defaultColors(props.categories.length))
const legendItems = ref<BulletLegendItemInterface[]>(props.categories.map((category, i) => ({
name: category,
color: colors.value[i],
inactive: false,
})))
const index = computed(() => props.index as KeyOfT);
const colors = computed(() =>
props.colors?.length ? props.colors : defaultColors(props.categories.length),
);
const legendItems = ref<BulletLegendItemInterface[]>(
props.categories.map((category, i) => ({
name: category,
color: colors.value[i],
inactive: false,
})),
);
const isMounted = useMounted()
const isMounted = useMounted();
function handleLegendItemClick(d: BulletLegendItemInterface, i: number) {
emits('legendItemClick', d, i)
emits("legendItemClick", d, i);
}
const VisBarComponent = computed(() => props.type === 'grouped' ? VisGroupedBar : VisStackedBar)
const selectorsBar = computed(() => props.type === 'grouped' ? GroupedBar.selectors.bar : StackedBar.selectors.bar)
const VisBarComponent = computed(() =>
props.type === "grouped" ? VisGroupedBar : VisStackedBar,
);
const selectorsBar = computed(() =>
props.type === "grouped"
? GroupedBar.selectors.bar
: StackedBar.selectors.bar,
);
</script>

<template>
<div :class="cn('w-full h-[400px] flex flex-col items-end', $attrs.class ?? '')">
<ChartLegend v-if="showLegend" v-model:items="legendItems" @legend-item-click="handleLegendItemClick" />
<div
:class="cn('w-full h-[400px] flex flex-col items-end', $attrs.class ?? '')"
>
<ChartLegend
v-if="showLegend"
v-model:items="legendItems"
@legend-item-click="handleLegendItemClick"
/>

<VisXYContainer
:data="data"
:style="{ height: isMounted ? '100%' : 'auto' }"
:margin="margin"
>
<ChartCrosshair v-if="showTooltip" :colors="colors" :items="legendItems" :custom-tooltip="customTooltip" :index="index" />
<ChartCrosshair
v-if="showTooltip"
:colors="colors"
:items="legendItems"
:custom-tooltip="customTooltip"
:index="index"
/>

<VisBarComponent
:x="(d: Data, i: number) => i"
:y="categories.map(category => (d: Data) => d[category]) "
:x="(_: Data, i: number) => i"
:y="categories.map((category) => (d: Data) => d[category])"
:color="colors"
:rounded-corners="roundedCorners"
:bar-padding="0.05"
:attributes="{
[selectorsBar]: {
opacity: (d: Data, i:number) => {
const pos = i % categories.length
return legendItems[pos]?.inactive ? filterOpacity : 1
opacity: (_: Data, i: number) => {
const pos = i % categories.length;
return legendItems[pos]?.inactive ? filterOpacity : 1;
},
},
}"
Expand Down
158 changes: 96 additions & 62 deletions src/components/ui/chart-donut/DonutChart.vue
Original file line number Diff line number Diff line change
@@ -1,67 +1,95 @@
<script setup lang="ts" generic="T extends Record<string, any>">
import { VisDonut, VisSingleContainer } from '@unovis/vue'
import { Donut } from '@unovis/ts'
import { type Component, computed, ref } from 'vue'
import { useMounted } from '@vueuse/core'
import type { BaseChartProps } from '.'
import { ChartSingleTooltip, defaultColors } from '@/components/ui/chart'
import { cn } from '@/lib/utils'
import { VisDonut, VisSingleContainer } from "@unovis/vue";
import { Donut } from "@unovis/ts";
import { type Component, computed, ref } from "vue";
import { useMounted } from "@vueuse/core";
import type { BaseChartProps } from ".";
import { ChartSingleTooltip, defaultColors } from "@/components/ui/chart";
import { cn } from "@/lib/utils";
const props = withDefaults(defineProps<Pick<BaseChartProps<T>, 'data' | 'colors' | 'index' | 'margin' | 'showLegend' | 'showTooltip' | 'filterOpacity'> & {
/**
* Sets the name of the key containing the quantitative chart values.
*/
category: KeyOfT
/**
* Change the type of the chart
* @default "donut"
*/
type?: 'donut' | 'pie'
/**
* Function to sort the segment
*/
sortFunction?: (a: any, b: any) => number | undefined
/**
* Controls the formatting for the label.
*/
valueFormatter?: (tick: number, i?: number, ticks?: number[]) => string
/**
* Render custom tooltip component.
*/
customTooltip?: Component
}>(), {
margin: () => ({ top: 0, bottom: 0, left: 0, right: 0 }),
sortFunction: () => undefined,
valueFormatter: (tick: number) => `${tick}`,
type: 'donut',
filterOpacity: 0.2,
showTooltip: true,
showLegend: true,
})
const props = withDefaults(
defineProps<
Pick<
BaseChartProps<T>,
| "data"
| "colors"
| "index"
| "margin"
| "showLegend"
| "showTooltip"
| "filterOpacity"
> & {
/**
* Sets the name of the key containing the quantitative chart values.
*/
category: KeyOfT;
/**
* Change the type of the chart
* @default "donut"
*/
type?: "donut" | "pie";
/**
* Function to sort the segment
*/
sortFunction?: (a: any, b: any) => number | undefined;
/**
* Controls the formatting for the label.
*/
valueFormatter?: (tick: number, i?: number, ticks?: number[]) => string;
/**
* Render custom tooltip component.
*/
customTooltip?: Component;
}
>(),
{
margin: () => ({ top: 0, bottom: 0, left: 0, right: 0 }),
sortFunction: () => undefined,
valueFormatter: (tick: number) => `${tick}`,
type: "donut",
filterOpacity: 0.2,
showTooltip: true,
showLegend: true,
},
);
type KeyOfT = Extract<keyof T, string>
type Data = typeof props.data[number]
type KeyOfT = Extract<keyof T, string>;
type Data = (typeof props.data)[number];
const category = computed(() => props.category as KeyOfT)
const index = computed(() => props.index as KeyOfT)
const category = computed(() => props.category as KeyOfT);
const index = computed(() => props.index as KeyOfT);
const isMounted = useMounted()
const activeSegmentKey = ref<string>()
const colors = computed(() => props.colors?.length ? props.colors : defaultColors(props.data.filter(d => d[props.category]).filter(Boolean).length))
const legendItems = computed(() => props.data.map((item, i) => ({
name: item[props.index],
color: colors.value[i],
inactive: false,
})))
const isMounted = useMounted();
const activeSegmentKey = ref<string>();
const colors = computed(() =>
props.colors?.length
? props.colors
: defaultColors(
props.data.filter((d) => d[props.category]).filter(Boolean).length,
),
);
const legendItems = computed(() =>
props.data.map((item, i) => ({
name: item[props.index],
color: colors.value[i],
inactive: false,
})),
);
const totalValue = computed(() => props.data.reduce((prev, curr) => {
return prev + curr[props.category]
}, 0))
const totalValue = computed(() =>
props.data.reduce((prev, curr) => {
return prev + curr[props.category];
}, 0),
);
</script>

<template>
<div :class="cn('w-full h-48 flex flex-col items-end', $attrs.class ?? '')">
<VisSingleContainer :style="{ height: isMounted ? '100%' : 'auto' }" :margin="{ left: 20, right: 20 }" :data="data">
<VisSingleContainer
:style="{ height: isMounted ? '100%' : 'auto' }"
:margin="{ left: 20, right: 20 }"
:data="data"
>
<ChartSingleTooltip
:selector="Donut.selectors.segment"
:index="category"
Expand All @@ -79,15 +107,21 @@ const totalValue = computed(() => props.data.reduce((prev, curr) => {
:central-label="type === 'donut' ? valueFormatter(totalValue) : ''"
:events="{
[Donut.selectors.segment]: {
click: (d: Data, ev: PointerEvent, i: number, elements: HTMLElement[]) => {
click: (
d: Data,
_: PointerEvent,
i: number,
elements: HTMLElement[],
) => {
if (d?.data?.[index] === activeSegmentKey) {
activeSegmentKey = undefined
elements.forEach(el => el.style.opacity = '1')
}
else {
activeSegmentKey = d?.data?.[index]
elements.forEach(el => el.style.opacity = `${filterOpacity}`)
elements[i].style.opacity = '1'
activeSegmentKey = undefined;
elements.forEach((el) => (el.style.opacity = '1'));
} else {
activeSegmentKey = d?.data?.[index];
elements.forEach(
(el) => (el.style.opacity = `${filterOpacity}`),
);
elements[i].style.opacity = '1';
}
},
},
Expand Down
Loading

0 comments on commit 1e6d891

Please sign in to comment.