diff --git a/front/components/About/AboutChartView.vue b/front/components/About/AboutChartView.vue index 92cdac8..e3c1157 100644 --- a/front/components/About/AboutChartView.vue +++ b/front/components/About/AboutChartView.vue @@ -1,34 +1,33 @@ @@ -167,21 +174,51 @@ const currentChartData = computed((): ChartConfig => {
{{ tab.total }}
- + + + + + + + + + + diff --git a/front/components/AboutChartTooltip.vue b/front/components/AboutChartTooltip.vue deleted file mode 100644 index 4d99b56..0000000 --- a/front/components/AboutChartTooltip.vue +++ /dev/null @@ -1,43 +0,0 @@ - - - diff --git a/front/components/ui/chart-area/AreaChart.vue b/front/components/ui/chart-area/AreaChart.vue deleted file mode 100644 index 84518eb..0000000 --- a/front/components/ui/chart-area/AreaChart.vue +++ /dev/null @@ -1,179 +0,0 @@ - - - diff --git a/front/components/ui/chart-area/index.ts b/front/components/ui/chart-area/index.ts deleted file mode 100644 index 717d1b8..0000000 --- a/front/components/ui/chart-area/index.ts +++ /dev/null @@ -1,74 +0,0 @@ -export { default as AreaChart } from "./AreaChart.vue"; - -import type { Spacing } from "@unovis/ts"; - -type KeyOf> = Extract; - -export interface BaseChartProps> { - /** - * 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[]; - /** - * Sets the key to map the data to the axis. - */ - index: KeyOf; - /** - * 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; -} diff --git a/front/components/ui/chart/ChartContainer.vue b/front/components/ui/chart/ChartContainer.vue new file mode 100644 index 0000000..fc92b9c --- /dev/null +++ b/front/components/ui/chart/ChartContainer.vue @@ -0,0 +1,61 @@ + + + + + diff --git a/front/components/ui/chart/ChartCrosshair.vue b/front/components/ui/chart/ChartCrosshair.vue deleted file mode 100644 index d150b31..0000000 --- a/front/components/ui/chart/ChartCrosshair.vue +++ /dev/null @@ -1,51 +0,0 @@ - - - diff --git a/front/components/ui/chart/ChartLegend.vue b/front/components/ui/chart/ChartLegend.vue deleted file mode 100644 index 882646b..0000000 --- a/front/components/ui/chart/ChartLegend.vue +++ /dev/null @@ -1,72 +0,0 @@ - - - diff --git a/front/components/ui/chart/ChartLegendContent.vue b/front/components/ui/chart/ChartLegendContent.vue new file mode 100644 index 0000000..131ca7c --- /dev/null +++ b/front/components/ui/chart/ChartLegendContent.vue @@ -0,0 +1,56 @@ + + + diff --git a/front/components/ui/chart/ChartSingleTooltip.vue b/front/components/ui/chart/ChartSingleTooltip.vue deleted file mode 100644 index 3032eb6..0000000 --- a/front/components/ui/chart/ChartSingleTooltip.vue +++ /dev/null @@ -1,74 +0,0 @@ - - - diff --git a/front/components/ui/chart/ChartStyle.vue b/front/components/ui/chart/ChartStyle.vue new file mode 100644 index 0000000..fc39110 --- /dev/null +++ b/front/components/ui/chart/ChartStyle.vue @@ -0,0 +1,37 @@ + + + diff --git a/front/components/ui/chart/ChartTooltip.vue b/front/components/ui/chart/ChartTooltip.vue deleted file mode 100644 index dbee0a0..0000000 --- a/front/components/ui/chart/ChartTooltip.vue +++ /dev/null @@ -1,40 +0,0 @@ - - - diff --git a/front/components/ui/chart/ChartTooltipContent.vue b/front/components/ui/chart/ChartTooltipContent.vue new file mode 100644 index 0000000..38082fe --- /dev/null +++ b/front/components/ui/chart/ChartTooltipContent.vue @@ -0,0 +1,109 @@ + + + diff --git a/front/components/ui/chart/index.ts b/front/components/ui/chart/index.ts index a707057..e6fab41 100644 --- a/front/components/ui/chart/index.ts +++ b/front/components/ui/chart/index.ts @@ -1,21 +1,26 @@ -export { default as ChartCrosshair } from "./ChartCrosshair.vue"; -export { default as ChartLegend } from "./ChartLegend.vue"; -export { default as ChartSingleTooltip } from "./ChartSingleTooltip.vue"; -export { default as ChartTooltip } from "./ChartTooltip.vue"; +import type { Component, Ref } from 'vue' +import { createContext } from 'reka-ui' -export function defaultColors(count: number = 3) { - const quotient = Math.floor(count / 2); - const remainder = count % 2; +export { default as ChartContainer } from './ChartContainer.vue' +export { default as ChartLegendContent } from './ChartLegendContent.vue' +export { default as ChartTooltipContent } from './ChartTooltipContent.vue' +export { componentToString } from './utils' - const primaryCount = quotient + remainder; - const secondaryCount = quotient; - return [ - ...Array.from(new Array(primaryCount).keys()).map( - (i) => `hsl(var(--vis-primary-color) / ${1 - (1 / primaryCount) * i})`, - ), - ...Array.from(new Array(secondaryCount).keys()).map( - (i) => - `hsl(var(--vis-secondary-color) / ${1 - (1 / secondaryCount) * i})`, - ), - ]; +// Format: { THEME_NAME: CSS_SELECTOR } +export const THEMES = { light: '', dark: '.dark' } as const + +export type ChartConfig = { + [k in string]: { + label?: string | Component + icon?: string | Component + } & ({ color?: string; theme?: never } | { color?: never; theme: Record }) } + +interface ChartContextProps { + id: string + config: Ref +} + +export const [useChart, provideChartContext] = createContext('Chart') + +export { VisCrosshair as ChartCrosshair, VisTooltip as ChartTooltip } from '@unovis/vue' diff --git a/front/components/ui/chart/utils.ts b/front/components/ui/chart/utils.ts new file mode 100644 index 0000000..01ef6ed --- /dev/null +++ b/front/components/ui/chart/utils.ts @@ -0,0 +1,42 @@ +import type { ChartConfig } from '.' +import { isClient } from '@vueuse/core' +import { useId } from 'reka-ui' +import { h, render } from 'vue' + +// Simple cache using a Map to store serialized object keys +const cache = new Map() + +// Convert object to a consistent string key +function serializeKey(key: Record): string { + return JSON.stringify(key, Object.keys(key).sort()) +} + +interface Constructor

{ + __isFragment?: never + __isTeleport?: never + __isSuspense?: never + new (...args: any[]): { + $props: P + } +} + +export function componentToString

(config: ChartConfig, component: Constructor

, props?: P) { + if (!isClient) return + + // This function will be called once during mount lifecycle + const id = useId() + + // https://unovis.dev/docs/auxiliary/Crosshair#component-props + return (_data: any, x: number | Date) => { + const data = 'data' in _data ? _data.data : _data + const serializedKey = `${id}-${serializeKey(data)}` + const cachedContent = cache.get(serializedKey) + if (cachedContent) return cachedContent + + const vnode = h(component, { ...props, payload: data, config, x }) + const div = document.createElement('div') + render(vnode, div) + cache.set(serializedKey, div.innerHTML) + return div.innerHTML + } +}