chore: arrange interface, expose margin, slot

This commit is contained in:
zernonia 2024-04-16 12:09:17 +08:00
parent 4ebc0af75d
commit db81b6c175
19 changed files with 234 additions and 427 deletions

View File

@ -125,6 +125,10 @@ export const docsConfig: DocsConfig = {
title: 'Charts', title: 'Charts',
label: 'Alpha', label: 'Alpha',
items: [ items: [
{
title: 'Guide',
href: '/docs/charts/guide',
},
{ {
title: 'Area', title: 'Area',
href: '/docs/charts/area', href: '/docs/charts/area',

View File

@ -1,6 +1,6 @@
--- ---
title: Area title: Area
description: Displays a callout for user attention. description: An area chart visually represents data over time, displaying trends and patterns through filled-in areas under a line graph.
label: Alpha label: Alpha
--- ---

View File

@ -1,6 +1,6 @@
--- ---
title: Bar title: Bar
description: Displays a callout for user attention. description: An line chart visually represents data using rectangular bars of varying lengths to compare quantities across different categories or groups.
label: Alpha label: Alpha
--- ---

View File

@ -1,6 +1,6 @@
--- ---
title: Donut title: Donut
description: Displays a callout for user attention. description: An line chart visually represents data in a circular form, similar to a pie chart but with a central void, emphasizing proportions within categories.
label: Alpha label: Alpha
--- ---

View File

@ -0,0 +1,3 @@
chartinggg
hihi

View File

@ -1,6 +1,6 @@
--- ---
title: Line title: Line
description: Displays a callout for user attention. description: An line chart visually displays data points connected by straight lines, illustrating trends or relationships over a continuous axis.
label: Alpha label: Alpha
--- ---

View File

@ -4,64 +4,10 @@ import { VisArea, VisAxis, VisLine, VisXYContainer } from '@unovis/vue'
import { Area, Axis, Line } from '@unovis/ts' import { Area, Axis, Line } from '@unovis/ts'
import { computed, ref } from 'vue' import { computed, ref } from 'vue'
import { useMounted } from '@vueuse/core' import { useMounted } from '@vueuse/core'
import { ChartCrosshair, ChartLegend, defaultColors } from '@/lib/registry/default/ui/chart' import { type BaseChartProps, ChartCrosshair, ChartLegend, defaultColors } from '@/lib/registry/default/ui/chart'
import { cn } from '@/lib/utils' import { cn } from '@/lib/utils'
const props = withDefaults(defineProps<{ const props = withDefaults(defineProps<BaseChartProps<T> & {
/**
* The source data, in which each entry is a dictionary.
*/
data: T[]
/**
* Select the categories from your data. Used to populate the legend and toolip.
*/
categories: KeyOfT[]
/**
* Sets the key to map the data to the axis.
*/
index: KeyOfT
/**
* Change the default colors.
*/
colors?: string[]
/**
* Change the opacity of the non-selected field
* @default 0.2
*/
filterOpacity?: number
/**
* Function to format X label
*/
xFormatter?: (tick: number | Date, i: number, ticks: number[] | Date[]) => string
/**
* Function to format Y label
*/
yFormatter?: (tick: number | Date, i: number, ticks: number[] | Date[]) => string
/**
* Controls the visibility of the X axis.
* @default true
*/
showXAxis?: boolean
/**
* Controls the visibility of the Y axis.
* @default true
*/
showYAxis?: boolean
/**
* Controls the visibility of tooltip.
* @default true
*/
showTooltip?: boolean
/**
* Controls the visibility of legend.
* @default true
*/
showLegend?: boolean
/**
* Controls the visibility of gridline.
* @default true
*/
showGridLine?: boolean
/** /**
* Controls the visibility of gradient. * Controls the visibility of gradient.
* @default true * @default true
@ -69,6 +15,7 @@ const props = withDefaults(defineProps<{
showGradiant?: boolean showGradiant?: boolean
}>(), { }>(), {
filterOpacity: 0.2, filterOpacity: 0.2,
margin: () => ({ top: 0, bottom: 0, left: 0, right: 0 }),
showXAxis: true, showXAxis: true,
showYAxis: true, showYAxis: true,
showTooltip: true, showTooltip: true,
@ -170,6 +117,8 @@ function handleLegendItemClick(d: BulletLegendItemInterface, i: number) {
}" }"
tick-text-color="hsl(var(--muted-foreground))" tick-text-color="hsl(var(--muted-foreground))"
/> />
<slot />
</VisXYContainer> </VisXYContainer>
</div> </div>
</template> </template>

View File

@ -4,71 +4,18 @@ import { VisAxis, VisGroupedBar, VisStackedBar, VisXYContainer } from '@unovis/v
import { Axis, GroupedBar, StackedBar } from '@unovis/ts' import { Axis, GroupedBar, StackedBar } from '@unovis/ts'
import { computed, ref } from 'vue' import { computed, ref } from 'vue'
import { useMounted } from '@vueuse/core' import { useMounted } from '@vueuse/core'
import { ChartCrosshair, ChartLegend, defaultColors } from '@/lib/registry/default/ui/chart' import { type BaseChartProps, ChartCrosshair, ChartLegend, defaultColors } from '@/lib/registry/default/ui/chart'
import { cn } from '@/lib/utils' import { cn } from '@/lib/utils'
const props = withDefaults(defineProps<{ const props = withDefaults(defineProps<BaseChartProps<T> & {
/**
* The source data, in which each entry is a dictionary.
*/
data: T[]
/**
* Select the categories from your data. Used to populate the legend and toolip.
*/
categories: Array<KeyOfT>
/**
* Sets the key to map the data to the axis.
*/
index: KeyOfT
/**
* Change the default colors.
*/
colors?: string[]
/**
* Change the opacity of the non-selected field
* @default 0.2
*/
filterOpacity?: number
/** /**
* Change the type of the chart * Change the type of the chart
* @default "grouped" * @default "grouped"
*/ */
type?: 'stacked' | 'grouped' type?: 'stacked' | 'grouped'
/**
* Function to format X label
*/
xFormatter?: (tick: number | Date, i: number, ticks: number[] | Date[]) => string
/**
* Function to format Y label
*/
yFormatter?: (tick: number | Date, i: number, ticks: number[] | Date[]) => string
/**
* Controls the visibility of the X axis.
* @default true
*/
showXAxis?: boolean
/**
* Controls the visibility of the Y axis.
* @default true
*/
showYAxis?: boolean
/**
* Controls the visibility of tooltip.
* @default true
*/
showTooltip?: boolean
/**
* Controls the visibility of legend.
* @default true
*/
showLegend?: boolean
/**
* Controls the visibility of gridline.
* @default true
*/
showGridLine?: boolean
}>(), { }>(), {
type: 'grouped', type: 'grouped',
margin: () => ({ top: 0, bottom: 0, left: 0, right: 0 }),
filterOpacity: 0.2, filterOpacity: 0.2,
showXAxis: true, showXAxis: true,
showYAxis: true, showYAxis: true,
@ -147,6 +94,8 @@ const selectorsBar = computed(() => props.type === 'grouped' ? GroupedBar.select
}" }"
tick-text-color="hsl(var(--muted-foreground))" tick-text-color="hsl(var(--muted-foreground))"
/> />
<slot />
</VisXYContainer> </VisXYContainer>
</div> </div>
</template> </template>

View File

@ -3,36 +3,19 @@ import { VisDonut, VisSingleContainer } from '@unovis/vue'
import { Donut } from '@unovis/ts' import { Donut } from '@unovis/ts'
import { computed, ref } from 'vue' import { computed, ref } from 'vue'
import { useMounted } from '@vueuse/core' import { useMounted } from '@vueuse/core'
import { ChartSingleTooltip, defaultColors } from '@/lib/registry/default/ui/chart' import { type BaseChartProps, ChartSingleTooltip, defaultColors } from '@/lib/registry/default/ui/chart'
import { cn } from '@/lib/utils' import { cn } from '@/lib/utils'
const props = withDefaults(defineProps<{ const props = withDefaults(defineProps<Pick<BaseChartProps<T>, 'data' | 'colors' | 'index' | 'margin' | 'showLegend' | 'showTooltip' | 'filterOpacity'> & {
/**
* The source data, in which each entry is a dictionary.
*/
data: T[]
/**
* Sets the key to map the data to the chart.
*/
index: KeyOfT
/** /**
* Sets the name of the key containing the quantitative chart values. * Sets the name of the key containing the quantitative chart values.
*/ */
category: KeyOfT category: KeyOfT
/**
* Change the default colors.
*/
colors?: string[]
/** /**
* Change the type of the chart * Change the type of the chart
* @default "donut" * @default "donut"
*/ */
type?: 'donut' | 'pie' type?: 'donut' | 'pie'
/**
* Change the opacity of the non-selected field
* @default 0.2
*/
filterOpacity?: number
/** /**
* Function to sort the segment * Function to sort the segment
*/ */
@ -41,17 +24,9 @@ const props = withDefaults(defineProps<{
* Controls the formatting for the label. * Controls the formatting for the label.
*/ */
valueFormatter?: (tick: number, i?: number, ticks?: number[]) => string valueFormatter?: (tick: number, i?: number, ticks?: number[]) => string
/**
* Controls the visibility of tooltip.
* @default true
*/
showTooltip?: boolean
/**
* Controls the visibility of legend.
* @default true
*/
showLegend?: boolean
}>(), { }>(), {
margin: () => ({ top: 0, bottom: 0, left: 0, right: 0 }),
sortFunction: () => undefined, sortFunction: () => undefined,
valueFormatter: (tick: number) => `${tick}`, valueFormatter: (tick: number) => `${tick}`,
type: 'donut', type: 'donut',
@ -113,6 +88,8 @@ const totalValue = computed(() => props.data.reduce((prev, curr) => {
}, },
}" }"
/> />
<slot />
</VisSingleContainer> </VisSingleContainer>
</div> </div>
</template> </template>

View File

@ -4,66 +4,12 @@ import { VisAxis, VisLine, VisXYContainer } from '@unovis/vue'
import { Axis, Line } from '@unovis/ts' import { Axis, Line } from '@unovis/ts'
import { computed, ref } from 'vue' import { computed, ref } from 'vue'
import { useMounted } from '@vueuse/core' import { useMounted } from '@vueuse/core'
import { ChartCrosshair, ChartLegend, defaultColors } from '@/lib/registry/default/ui/chart' import { type BaseChartProps, ChartCrosshair, ChartLegend, defaultColors } from '@/lib/registry/default/ui/chart'
import { cn } from '@/lib/utils' import { cn } from '@/lib/utils'
const props = withDefaults(defineProps<{ const props = withDefaults(defineProps<BaseChartProps<T>>(), {
/**
* The source data, in which each entry is a dictionary.
*/
data: T[]
/**
* Select the categories from your data. Used to populate the legend and toolip.
*/
categories: KeyOfT[]
/**
* Sets the key to map the data to the axis.
*/
index: KeyOfT
/**
* Change the default colors.
*/
colors?: string[]
/**
* Change the opacity of the non-selected field
* @default 0.2
*/
filterOpacity?: number
/**
* Function to format X label
*/
xFormatter?: (tick: number | Date, i: number, ticks: number[] | Date[]) => string
/**
* Function to format Y label
*/
yFormatter?: (tick: number | Date, i: number, ticks: number[] | Date[]) => string
/**
* Controls the visibility of the X axis.
* @default true
*/
showXAxis?: boolean
/**
* Controls the visibility of the Y axis.
* @default true
*/
showYAxis?: boolean
/**
* Controls the visibility of tooltip.
* @default true
*/
showTooltip?: boolean
/**
* Controls the visibility of legend.
* @default true
*/
showLegend?: boolean
/**
* Controls the visibility of gridline.
* @default true
*/
showGridLine?: boolean
}>(), {
filterOpacity: 0.2, filterOpacity: 0.2,
margin: () => ({ top: 0, bottom: 0, left: 0, right: 0 }),
showXAxis: true, showXAxis: true,
showYAxis: true, showYAxis: true,
showTooltip: true, showTooltip: true,
@ -140,6 +86,8 @@ function handleLegendItemClick(d: BulletLegendItemInterface, i: number) {
}" }"
tick-text-color="hsl(var(--muted-foreground))" tick-text-color="hsl(var(--muted-foreground))"
/> />
<slot />
</VisXYContainer> </VisXYContainer>
</div> </div>
</template> </template>

View File

@ -14,3 +14,5 @@ export function defaultColors(count: number = 3) {
...Array.from(Array(secondaryCount).keys()).map(i => `hsl(var(--vis-secondary-color) / ${1 - (1 / secondaryCount) * i})`), ...Array.from(Array(secondaryCount).keys()).map(i => `hsl(var(--vis-secondary-color) / ${1 - (1 / secondaryCount) * i})`),
] ]
} }
export * from './interface'

View File

@ -0,0 +1,64 @@
import type { Spacing } from '@unovis/ts'
type KeyOf<T extends Record<string, any>> = Extract<keyof T, string>
export interface BaseChartProps<T extends Record<string, any>> {
/**
* The source data, in which each entry is a dictionary.
*/
data: T[]
/**
* Select the categories from your data. Used to populate the legend and toolip.
*/
categories: KeyOf<T>[]
/**
* Sets the key to map the data to the axis.
*/
index: KeyOf<T>
/**
* Change the default colors.
*/
colors?: string[]
/**
* Margin of each the container
*/
margin?: Spacing
/**
* Change the opacity of the non-selected field
* @default 0.2
*/
filterOpacity?: number
/**
* Function to format X label
*/
xFormatter?: (tick: number | Date, i: number, ticks: number[] | Date[]) => string
/**
* Function to format Y label
*/
yFormatter?: (tick: number | Date, i: number, ticks: number[] | Date[]) => string
/**
* Controls the visibility of the X axis.
* @default true
*/
showXAxis?: boolean
/**
* Controls the visibility of the Y axis.
* @default true
*/
showYAxis?: boolean
/**
* Controls the visibility of tooltip.
* @default true
*/
showTooltip?: boolean
/**
* Controls the visibility of legend.
* @default true
*/
showLegend?: boolean
/**
* Controls the visibility of gridline.
* @default true
*/
showGridLine?: boolean
}

View File

@ -1,6 +1,8 @@
<script setup lang="ts"> <script setup lang="ts">
import { VisLine, VisScatter, VisStackedBar, VisXYContainer } from '@unovis/vue' import { VisScatter, VisStackedBar, VisXYContainer } from '@unovis/vue'
import { Card, CardContent, CardHeader, CardTitle } from '@/lib/registry/new-york/ui/card' import { Card, CardContent, CardHeader, CardTitle } from '@/lib/registry/new-york/ui/card'
import { LineChart } from '@/lib/registry/new-york/ui/chart-line'
import { BarChart } from '@/lib/registry/new-york/ui/chart-bar'
type Data = typeof data[number] type Data = typeof data[number]
const data = [ const data = [
@ -13,9 +15,6 @@ const data = [
{ revenue: 11244, subscription: 278 }, { revenue: 11244, subscription: 278 },
{ revenue: 26475, subscription: 189 }, { revenue: 26475, subscription: 189 },
] ]
const lineX = (d: Data, i: number) => i
const lineY = (d: Data) => d.revenue
</script> </script>
<template> <template>
@ -35,18 +34,27 @@ const lineY = (d: Data) => d.revenue
</p> </p>
<div class="h-20"> <div class="h-20">
<VisXYContainer <LineChart
height="80px" class="h-[80px]"
:data="data" :margin="{ :data="data"
top: 5, :margin="{ top: 5, right: 10, left: 10, bottom: 0 }"
right: 10, :categories="['revenue']"
left: 10, :index="'revenue'"
bottom: 0, :show-grid-line="false"
}" :show-legend="false"
:show-tooltip="false"
:show-x-axis="false"
:show-y-axis="false"
> >
<VisLine :x="lineX" :y="lineY" color="hsl(var(--primary))" /> <VisScatter
<VisScatter :x="lineX" :y="lineY" :size="6" stroke-color="hsl(var(--primary))" :stroke-width="2" color="white" /> color="white"
</VisXYContainer> stroke-color="hsl(var(--primary))"
:x="(d: Data, i: number) => i"
:y="(d: Data) => d.revenue"
:size="6"
:stroke-width="2"
/>
</LineChart>
</div> </div>
</CardContent> </CardContent>
</Card> </Card>
@ -66,16 +74,27 @@ const lineY = (d: Data) => d.revenue
</p> </p>
<div class="mt-4 h-20"> <div class="mt-4 h-20">
<VisXYContainer <BarChart
class="h-[80px]"
:data="data"
:categories="['subscription']"
:index="'subscription'"
:show-grid-line="false"
:show-legend="false"
:show-x-axis="false"
:show-y-axis="false"
:show-tooltip="false"
/>
<!-- <VisXYContainer
height="80px" :data="data" height="80px" :data="data"
> >
<VisStackedBar <VisStackedBar
:x="lineX" :x="(d: Data, i:number) => i"
:y="(d: Data) => d.subscription" :y="(d: Data) => d.subscription"
:bar-padding="0.1" :bar-padding="0.1"
:rounded-corners="0" color="hsl(var(--primary))" :rounded-corners="0" color="hsl(var(--primary))"
/> />
</VisXYContainer> </VisXYContainer> -->
</div> </div>
</CardContent> </CardContent>
</Card> </Card>

View File

@ -1,67 +1,13 @@
<script setup lang="ts" generic="T extends Record<string, any>"> <script setup lang="ts" generic="T extends Record<string, any>">
import type { BulletLegendItemInterface } from '@unovis/ts' import type { BulletLegendItemInterface, Spacing } from '@unovis/ts'
import { VisArea, VisAxis, VisLine, VisXYContainer } from '@unovis/vue' import { VisArea, VisAxis, VisLine, VisXYContainer } from '@unovis/vue'
import { Area, Axis, Line } from '@unovis/ts' import { Area, Axis, Line } from '@unovis/ts'
import { computed, ref } from 'vue' import { computed, ref } from 'vue'
import { useMounted } from '@vueuse/core' import { useMounted } from '@vueuse/core'
import { ChartCrosshair, ChartLegend, defaultColors } from '@/lib/registry/new-york/ui/chart' import { type BaseChartProps, ChartCrosshair, ChartLegend, defaultColors } from '@/lib/registry/new-york/ui/chart'
import { cn } from '@/lib/utils' import { cn } from '@/lib/utils'
const props = withDefaults(defineProps<{ const props = withDefaults(defineProps<BaseChartProps<T> & {
/**
* The source data, in which each entry is a dictionary.
*/
data: T[]
/**
* Select the categories from your data. Used to populate the legend and toolip.
*/
categories: KeyOfT[]
/**
* Sets the key to map the data to the axis.
*/
index: KeyOfT
/**
* Change the default colors.
*/
colors?: string[]
/**
* Change the opacity of the non-selected field
* @default 0.2
*/
filterOpacity?: number
/**
* Function to format X label
*/
xFormatter?: (tick: number | Date, i: number, ticks: number[] | Date[]) => string
/**
* Function to format Y label
*/
yFormatter?: (tick: number | Date, i: number, ticks: number[] | Date[]) => string
/**
* Controls the visibility of the X axis.
* @default true
*/
showXAxis?: boolean
/**
* Controls the visibility of the Y axis.
* @default true
*/
showYAxis?: boolean
/**
* Controls the visibility of tooltip.
* @default true
*/
showTooltip?: boolean
/**
* Controls the visibility of legend.
* @default true
*/
showLegend?: boolean
/**
* Controls the visibility of gridline.
* @default true
*/
showGridLine?: boolean
/** /**
* Controls the visibility of gradient. * Controls the visibility of gradient.
* @default true * @default true
@ -69,6 +15,7 @@ const props = withDefaults(defineProps<{
showGradiant?: boolean showGradiant?: boolean
}>(), { }>(), {
filterOpacity: 0.2, filterOpacity: 0.2,
margin: () => ({ top: 0, bottom: 0, left: 0, right: 0 }),
showXAxis: true, showXAxis: true,
showYAxis: true, showYAxis: true,
showTooltip: true, showTooltip: true,
@ -170,6 +117,8 @@ function handleLegendItemClick(d: BulletLegendItemInterface, i: number) {
}" }"
tick-text-color="hsl(var(--muted-foreground))" tick-text-color="hsl(var(--muted-foreground))"
/> />
<slot />
</VisXYContainer> </VisXYContainer>
</div> </div>
</template> </template>

View File

@ -1,74 +1,21 @@
<script setup lang="ts" generic="T extends Record<string, any>"> <script setup lang="ts" generic="T extends Record<string, any>">
import type { BulletLegendItemInterface } from '@unovis/ts' import type { BulletLegendItemInterface, Spacing } from '@unovis/ts'
import { VisAxis, VisGroupedBar, VisStackedBar, VisXYContainer } from '@unovis/vue' import { VisAxis, VisGroupedBar, VisStackedBar, VisXYContainer } from '@unovis/vue'
import { Axis, GroupedBar, StackedBar } from '@unovis/ts' import { Axis, GroupedBar, StackedBar } from '@unovis/ts'
import { computed, ref } from 'vue' import { computed, ref } from 'vue'
import { useMounted } from '@vueuse/core' import { useMounted } from '@vueuse/core'
import { ChartCrosshair, ChartLegend, defaultColors } from '@/lib/registry/new-york/ui/chart' import { type BaseChartProps, ChartCrosshair, ChartLegend, defaultColors } from '@/lib/registry/new-york/ui/chart'
import { cn } from '@/lib/utils' import { cn } from '@/lib/utils'
const props = withDefaults(defineProps<{ const props = withDefaults(defineProps<BaseChartProps<T> & {
/**
* The source data, in which each entry is a dictionary.
*/
data: T[]
/**
* Select the categories from your data. Used to populate the legend and toolip.
*/
categories: Array<KeyOfT>
/**
* Sets the key to map the data to the axis.
*/
index: KeyOfT
/**
* Change the default colors.
*/
colors?: string[]
/**
* Change the opacity of the non-selected field
* @default 0.2
*/
filterOpacity?: number
/** /**
* Change the type of the chart * Change the type of the chart
* @default "grouped" * @default "grouped"
*/ */
type?: 'stacked' | 'grouped' type?: 'stacked' | 'grouped'
/**
* Function to format X label
*/
xFormatter?: (tick: number | Date, i: number, ticks: number[] | Date[]) => string
/**
* Function to format Y label
*/
yFormatter?: (tick: number | Date, i: number, ticks: number[] | Date[]) => string
/**
* Controls the visibility of the X axis.
* @default true
*/
showXAxis?: boolean
/**
* Controls the visibility of the Y axis.
* @default true
*/
showYAxis?: boolean
/**
* Controls the visibility of tooltip.
* @default true
*/
showTooltip?: boolean
/**
* Controls the visibility of legend.
* @default true
*/
showLegend?: boolean
/**
* Controls the visibility of gridline.
* @default true
*/
showGridLine?: boolean
}>(), { }>(), {
type: 'grouped', type: 'grouped',
margin: () => ({ top: 0, bottom: 0, left: 0, right: 0 }),
filterOpacity: 0.2, filterOpacity: 0.2,
showXAxis: true, showXAxis: true,
showYAxis: true, showYAxis: true,
@ -106,15 +53,19 @@ const selectorsBar = computed(() => props.type === 'grouped' ? GroupedBar.select
<div :class="cn('w-full h-[400px] flex flex-col items-end', $attrs.class ?? '')"> <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" /> <ChartLegend v-if="showLegend" v-model:items="legendItems" @legend-item-click="handleLegendItemClick" />
<VisXYContainer :style="{ height: isMounted ? '100%' : 'auto' }" :margin="{ left: 20, right: 20 }" :data="data"> <VisXYContainer
:data="data"
:style="{ height: isMounted ? '100%' : 'auto' }"
:margin="margin"
>
<ChartCrosshair v-if="showTooltip" :colors="colors" :items="legendItems" :index="index" /> <ChartCrosshair v-if="showTooltip" :colors="colors" :items="legendItems" :index="index" />
<VisBarComponent <VisBarComponent
:x="(d: Data, i: number) => i" :x="(d: Data, i: number) => i"
:y="categories.map(category => (d: Data) => d[category]) " :y="categories.map(category => (d: Data) => d[category]) "
:color="colors" :color="colors"
:rounded-corners="4" :rounded-corners="0"
:bar-padding="0.1" :bar-padding="0.05"
:attributes="{ :attributes="{
[selectorsBar]: { [selectorsBar]: {
opacity: (d: Data, i:number) => { opacity: (d: Data, i:number) => {
@ -147,6 +98,8 @@ const selectorsBar = computed(() => props.type === 'grouped' ? GroupedBar.select
}" }"
tick-text-color="hsl(var(--muted-foreground))" tick-text-color="hsl(var(--muted-foreground))"
/> />
<slot />
</VisXYContainer> </VisXYContainer>
</div> </div>
</template> </template>

View File

@ -1,38 +1,21 @@
<script setup lang="ts" generic="T extends Record<string, any>"> <script setup lang="ts" generic="T extends Record<string, any>">
import { VisDonut, VisSingleContainer } from '@unovis/vue' import { VisDonut, VisSingleContainer } from '@unovis/vue'
import { Donut } from '@unovis/ts' import { Donut, type Spacing } from '@unovis/ts'
import { computed, ref } from 'vue' import { computed, ref } from 'vue'
import { useMounted } from '@vueuse/core' import { useMounted } from '@vueuse/core'
import { ChartSingleTooltip, defaultColors } from '@/lib/registry/new-york/ui/chart' import { type BaseChartProps, ChartSingleTooltip, defaultColors } from '@/lib/registry/new-york/ui/chart'
import { cn } from '@/lib/utils' import { cn } from '@/lib/utils'
const props = withDefaults(defineProps<{ const props = withDefaults(defineProps<Pick<BaseChartProps<T>, 'data' | 'colors' | 'index' | 'margin' | 'showLegend' | 'showTooltip' | 'filterOpacity'> & {
/**
* The source data, in which each entry is a dictionary.
*/
data: T[]
/**
* Sets the key to map the data to the chart.
*/
index: KeyOfT
/** /**
* Sets the name of the key containing the quantitative chart values. * Sets the name of the key containing the quantitative chart values.
*/ */
category: KeyOfT category: KeyOfT
/**
* Change the default colors.
*/
colors?: string[]
/** /**
* Change the type of the chart * Change the type of the chart
* @default "donut" * @default "donut"
*/ */
type?: 'donut' | 'pie' type?: 'donut' | 'pie'
/**
* Change the opacity of the non-selected field
* @default 0.2
*/
filterOpacity?: number
/** /**
* Function to sort the segment * Function to sort the segment
*/ */
@ -41,17 +24,9 @@ const props = withDefaults(defineProps<{
* Controls the formatting for the label. * Controls the formatting for the label.
*/ */
valueFormatter?: (tick: number, i?: number, ticks?: number[]) => string valueFormatter?: (tick: number, i?: number, ticks?: number[]) => string
/**
* Controls the visibility of tooltip.
* @default true
*/
showTooltip?: boolean
/**
* Controls the visibility of legend.
* @default true
*/
showLegend?: boolean
}>(), { }>(), {
margin: () => ({ top: 0, bottom: 0, left: 0, right: 0 }),
sortFunction: () => undefined, sortFunction: () => undefined,
valueFormatter: (tick: number) => `${tick}`, valueFormatter: (tick: number) => `${tick}`,
type: 'donut', type: 'donut',
@ -114,6 +89,8 @@ const totalValue = computed(() => props.data.reduce((prev, curr) => {
}, },
}" }"
/> />
<slot />
</VisSingleContainer> </VisSingleContainer>
</div> </div>
</template> </template>

View File

@ -1,69 +1,14 @@
<script setup lang="ts" generic="T extends Record<string, any>"> <script setup lang="ts" generic="T extends Record<string, any>">
import type { BulletLegendItemInterface } from '@unovis/ts' import { Axis, type BulletLegendItemInterface, Line, type Spacing } from '@unovis/ts'
import { VisAxis, VisLine, VisXYContainer } from '@unovis/vue' import { VisAxis, VisLine, VisXYContainer } from '@unovis/vue'
import { Axis, Line } from '@unovis/ts'
import { computed, ref } from 'vue' import { computed, ref } from 'vue'
import { useMounted } from '@vueuse/core' import { useMounted } from '@vueuse/core'
import { ChartCrosshair, ChartLegend, defaultColors } from '@/lib/registry/new-york/ui/chart' import { type BaseChartProps, ChartCrosshair, ChartLegend, defaultColors } from '@/lib/registry/new-york/ui/chart'
import { cn } from '@/lib/utils' import { cn } from '@/lib/utils'
const props = withDefaults(defineProps<{ const props = withDefaults(defineProps<BaseChartProps<T>>(), {
/**
* The source data, in which each entry is a dictionary.
*/
data: T[]
/**
* Select the categories from your data. Used to populate the legend and toolip.
*/
categories: KeyOfT[]
/**
* Sets the key to map the data to the axis.
*/
index: KeyOfT
/**
* Change the default colors.
*/
colors?: string[]
/**
* Change the opacity of the non-selected field
* @default 0.2
*/
filterOpacity?: number
/**
* Function to format X label
*/
xFormatter?: (tick: number | Date, i: number, ticks: number[] | Date[]) => string
/**
* Function to format Y label
*/
yFormatter?: (tick: number | Date, i: number, ticks: number[] | Date[]) => string
/**
* Controls the visibility of the X axis.
* @default true
*/
showXAxis?: boolean
/**
* Controls the visibility of the Y axis.
* @default true
*/
showYAxis?: boolean
/**
* Controls the visibility of tooltip.
* @default true
*/
showTooltip?: boolean
/**
* Controls the visibility of legend.
* @default true
*/
showLegend?: boolean
/**
* Controls the visibility of gridline.
* @default true
*/
showGridLine?: boolean
}>(), {
filterOpacity: 0.2, filterOpacity: 0.2,
margin: () => ({ top: 0, bottom: 0, left: 0, right: 0 }),
showXAxis: true, showXAxis: true,
showYAxis: true, showYAxis: true,
showTooltip: true, showTooltip: true,
@ -99,7 +44,7 @@ function handleLegendItemClick(d: BulletLegendItemInterface, i: number) {
<ChartLegend v-if="showLegend" v-model:items="legendItems" @legend-item-click="handleLegendItemClick" /> <ChartLegend v-if="showLegend" v-model:items="legendItems" @legend-item-click="handleLegendItemClick" />
<VisXYContainer <VisXYContainer
:margin="{ left: 20, right: 20 }" :margin="margin"
:data="data" :data="data"
:style="{ height: isMounted ? '100%' : 'auto' }" :style="{ height: isMounted ? '100%' : 'auto' }"
> >
@ -140,6 +85,8 @@ function handleLegendItemClick(d: BulletLegendItemInterface, i: number) {
}" }"
tick-text-color="hsl(var(--muted-foreground))" tick-text-color="hsl(var(--muted-foreground))"
/> />
<slot />
</VisXYContainer> </VisXYContainer>
</div> </div>
</template> </template>

View File

@ -14,3 +14,5 @@ export function defaultColors(count: number = 3) {
...Array.from(Array(secondaryCount).keys()).map(i => `hsl(var(--vis-secondary-color) / ${1 - (1 / secondaryCount) * i})`), ...Array.from(Array(secondaryCount).keys()).map(i => `hsl(var(--vis-secondary-color) / ${1 - (1 / secondaryCount) * i})`),
] ]
} }
export * from './interface'

View File

@ -0,0 +1,64 @@
import type { Spacing } from '@unovis/ts'
type KeyOf<T extends Record<string, any>> = Extract<keyof T, string>
export interface BaseChartProps<T extends Record<string, any>> {
/**
* The source data, in which each entry is a dictionary.
*/
data: T[]
/**
* Select the categories from your data. Used to populate the legend and toolip.
*/
categories: KeyOf<T>[]
/**
* Sets the key to map the data to the axis.
*/
index: KeyOf<T>
/**
* Change the default colors.
*/
colors?: string[]
/**
* Margin of each the container
*/
margin?: Spacing
/**
* Change the opacity of the non-selected field
* @default 0.2
*/
filterOpacity?: number
/**
* Function to format X label
*/
xFormatter?: (tick: number | Date, i: number, ticks: number[] | Date[]) => string
/**
* Function to format Y label
*/
yFormatter?: (tick: number | Date, i: number, ticks: number[] | Date[]) => string
/**
* Controls the visibility of the X axis.
* @default true
*/
showXAxis?: boolean
/**
* Controls the visibility of the Y axis.
* @default true
*/
showYAxis?: boolean
/**
* Controls the visibility of tooltip.
* @default true
*/
showTooltip?: boolean
/**
* Controls the visibility of legend.
* @default true
*/
showLegend?: boolean
/**
* Controls the visibility of gridline.
* @default true
*/
showGridLine?: boolean
}