28 lines
4.7 KiB
JSON
28 lines
4.7 KiB
JSON
{
|
|
"name": "chart-donut",
|
|
"type": "registry:ui",
|
|
"dependencies": [
|
|
"@unovis/vue",
|
|
"@unovis/ts",
|
|
"@vueuse/core"
|
|
],
|
|
"registryDependencies": [
|
|
"utils",
|
|
"chart"
|
|
],
|
|
"files": [
|
|
{
|
|
"path": "ui/chart-donut/DonutChart.vue",
|
|
"content": "<script setup lang=\"ts\" generic=\"T extends Record<string, any>\">\nimport type { BaseChartProps } from '.'\nimport { cn } from '@/lib/utils'\nimport { ChartSingleTooltip, defaultColors } from '@/registry/new-york/ui/chart'\nimport { Donut } from '@unovis/ts'\nimport { VisDonut, VisSingleContainer } from '@unovis/vue'\nimport { useMounted } from '@vueuse/core'\nimport { type Component, computed, ref } from 'vue'\n\nconst props = withDefaults(defineProps<Pick<BaseChartProps<T>, 'data' | 'colors' | 'index' | 'margin' | 'showLegend' | 'showTooltip' | 'filterOpacity'> & {\n /**\n * Sets the name of the key containing the quantitative chart values.\n */\n category: KeyOfT\n /**\n * Change the type of the chart\n * @default \"donut\"\n */\n type?: 'donut' | 'pie'\n /**\n * Function to sort the segment\n */\n sortFunction?: (a: any, b: any) => number | undefined\n /**\n * Controls the formatting for the label.\n */\n valueFormatter?: (tick: number, i?: number, ticks?: number[]) => string\n /**\n * Render custom tooltip component.\n */\n customTooltip?: Component\n}>(), {\n margin: () => ({ top: 0, bottom: 0, left: 0, right: 0 }),\n sortFunction: () => undefined,\n valueFormatter: (tick: number) => `${tick}`,\n type: 'donut',\n filterOpacity: 0.2,\n showTooltip: true,\n showLegend: true,\n})\n\ntype KeyOfT = Extract<keyof T, string>\ntype Data = typeof props.data[number]\n\nconst category = computed(() => props.category as KeyOfT)\nconst index = computed(() => props.index as KeyOfT)\n\nconst isMounted = useMounted()\nconst activeSegmentKey = ref<string>()\nconst colors = computed(() => props.colors?.length ? props.colors : defaultColors(props.data.filter(d => d[props.category]).filter(Boolean).length))\nconst legendItems = computed(() => props.data.map((item, i) => ({\n name: item[props.index],\n color: colors.value[i],\n inactive: false,\n})))\n\nconst totalValue = computed(() => props.data.reduce((prev, curr) => {\n return prev + curr[props.category]\n}, 0))\n</script>\n\n<template>\n <div :class=\"cn('w-full h-48 flex flex-col items-end', $attrs.class ?? '')\">\n <VisSingleContainer :style=\"{ height: isMounted ? '100%' : 'auto' }\" :margin=\"{ left: 20, right: 20 }\" :data=\"data\">\n <ChartSingleTooltip\n :selector=\"Donut.selectors.segment\"\n :index=\"category\"\n :items=\"legendItems\"\n :value-formatter=\"valueFormatter\"\n :custom-tooltip=\"customTooltip\"\n />\n\n <VisDonut\n :value=\"(d: Data) => d[category]\"\n :sort-function=\"sortFunction\"\n :color=\"colors\"\n :arc-width=\"type === 'donut' ? 20 : 0\"\n :show-background=\"false\"\n :central-label=\"type === 'donut' ? valueFormatter(totalValue) : ''\"\n :events=\"{\n [Donut.selectors.segment]: {\n click: (d: Data, ev: PointerEvent, i: number, elements: HTMLElement[]) => {\n if (d?.data?.[index] === activeSegmentKey) {\n activeSegmentKey = undefined\n elements.forEach(el => el.style.opacity = '1')\n }\n else {\n activeSegmentKey = d?.data?.[index]\n elements.forEach(el => el.style.opacity = `${filterOpacity}`)\n elements[i].style.opacity = '1'\n }\n },\n },\n }\"\n />\n\n <slot />\n </VisSingleContainer>\n </div>\n</template>\n",
|
|
"type": "registry:ui",
|
|
"target": "chart-donut/DonutChart.vue"
|
|
},
|
|
{
|
|
"path": "ui/chart-donut/index.ts",
|
|
"content": "export { default as DonutChart } from './DonutChart.vue'\n\nimport type { Spacing } from '@unovis/ts'\n\ntype KeyOf<T extends Record<string, any>> = Extract<keyof T, string>\n\nexport interface BaseChartProps<T extends Record<string, any>> {\n /**\n * The source data, in which each entry is a dictionary.\n */\n data: T[]\n /**\n * Sets the key to map the data to the axis.\n */\n index: KeyOf<T>\n /**\n * Change the default colors.\n */\n colors?: string[]\n /**\n * Margin of each the container\n */\n margin?: Spacing\n /**\n * Change the opacity of the non-selected field\n * @default 0.2\n */\n filterOpacity?: number\n /**\n * Controls the visibility of tooltip.\n * @default true\n */\n showTooltip?: boolean\n /**\n * Controls the visibility of legend.\n * @default true\n */\n showLegend?: boolean\n}\n",
|
|
"type": "registry:ui",
|
|
"target": "chart-donut/index.ts"
|
|
}
|
|
]
|
|
}
|