{
  "name": "chart",
  "dependencies": [
    "@unovis/vue",
    "@unovis/ts"
  ],
  "registryDependencies": [
    "button",
    "card"
  ],
  "files": [
    {
      "name": "ChartCrosshair.vue",
      "content": "<script setup lang=\"ts\">\nimport { VisCrosshair, VisTooltip } from '@unovis/vue'\nimport type { BulletLegendItemInterface } from '@unovis/ts'\nimport { omit } from '@unovis/ts'\nimport { type Component, createApp } from 'vue'\nimport { ChartTooltip } from '.'\n\nconst props = withDefaults(defineProps<{\n  colors: string[]\n  index: string\n  items: BulletLegendItemInterface[]\n  customTooltip?: Component\n}>(), {\n  colors: () => [],\n})\n\n// Use weakmap to store reference to each datapoint for Tooltip\nconst wm = new WeakMap()\nfunction template(d: any) {\n  if (wm.has(d)) {\n    return wm.get(d)\n  }\n  else {\n    const componentDiv = document.createElement('div')\n    const omittedData = Object.entries(omit(d, [props.index])).map(([key, value]) => {\n      const legendReference = props.items.find(i => i.name === key)\n      return { ...legendReference, value }\n    })\n    const TooltipComponent = props.customTooltip ?? ChartTooltip\n    createApp(TooltipComponent, { title: d[props.index].toString(), data: omittedData }).mount(componentDiv)\n    wm.set(d, componentDiv.innerHTML)\n    return componentDiv.innerHTML\n  }\n}\n\nfunction color(d: unknown, i: number) {\n  return props.colors[i] ?? 'transparent'\n}\n</script>\n\n<template>\n  <VisTooltip :horizontal-shift=\"20\" :vertical-shift=\"20\" />\n  <VisCrosshair :template=\"template\" :color=\"color\" />\n</template>\n"
    },
    {
      "name": "ChartLegend.vue",
      "content": "<script setup lang=\"ts\">\nimport { VisBulletLegend } from '@unovis/vue'\nimport type { BulletLegendItemInterface } from '@unovis/ts'\nimport { BulletLegend } from '@unovis/ts'\nimport { nextTick, onMounted, ref } from 'vue'\nimport { buttonVariants } from '@/lib/registry/default/ui/button'\n\nconst props = withDefaults(defineProps<{ items: BulletLegendItemInterface[] }>(), {\n  items: () => [],\n})\n\nconst emits = defineEmits<{\n  'legendItemClick': [d: BulletLegendItemInterface, i: number]\n  'update:items': [payload: BulletLegendItemInterface[]]\n}>()\n\nconst elRef = ref<HTMLElement>()\n\nonMounted(() => {\n  const selector = `.${BulletLegend.selectors.item}`\n  nextTick(() => {\n    const elements = elRef.value?.querySelectorAll(selector)\n    const classes = buttonVariants({ variant: 'ghost', size: 'xs' }).split(' ')\n    elements?.forEach(el => el.classList.add(...classes, '!inline-flex', '!mr-2'))\n  })\n})\n\nfunction onLegendItemClick(d: BulletLegendItemInterface, i: number) {\n  emits('legendItemClick', d, i)\n  const isBulletActive = !props.items[i].inactive\n  const isFilterApplied = props.items.some(i => i.inactive)\n  if (isFilterApplied && isBulletActive) {\n    // reset filter\n    emits('update:items', props.items.map(item => ({ ...item, inactive: false })))\n  }\n  else {\n    // apply selection, set other item as inactive\n    emits('update:items', props.items.map(item => item.name === d.name ? ({ ...d, inactive: false }) : { ...item, inactive: true }))\n  }\n}\n</script>\n\n<template>\n  <div ref=\"elRef\" class=\"w-max\">\n    <VisBulletLegend\n      :items=\"items\"\n      :on-legend-item-click=\"onLegendItemClick\"\n    />\n  </div>\n</template>\n"
    },
    {
      "name": "ChartSingleTooltip.vue",
      "content": "<script setup lang=\"ts\">\nimport { VisTooltip } from '@unovis/vue'\nimport type { BulletLegendItemInterface } from '@unovis/ts'\nimport { omit } from '@unovis/ts'\nimport { type Component, createApp } from 'vue'\nimport { ChartTooltip } from '.'\n\nconst props = withDefaults(defineProps<{\n  selector: string\n  index: string\n  items?: BulletLegendItemInterface[]\n  valueFormatter?: (tick: number, i?: number, ticks?: number[]) => string\n  customTooltip?: Component\n}>(), {\n  valueFormatter: (tick: number) => `${tick}`,\n})\n\n// Use weakmap to store reference to each datapoint for Tooltip\nconst wm = new WeakMap()\nfunction template(d: any, i: number, elements: (HTMLElement | SVGElement)[]) {\n  if (props.index in d) {\n    if (wm.has(d)) {\n      return wm.get(d)\n    }\n    else {\n      const componentDiv = document.createElement('div')\n      const omittedData = Object.entries(omit(d, [props.index])).map(([key, value]) => {\n        const legendReference = props.items?.find(i => i.name === key)\n        return { ...legendReference, value: props.valueFormatter(value) }\n      })\n      const TooltipComponent = props.customTooltip ?? ChartTooltip\n      createApp(TooltipComponent, { title: d[props.index], data: omittedData }).mount(componentDiv)\n      wm.set(d, componentDiv.innerHTML)\n      return componentDiv.innerHTML\n    }\n  }\n\n  else {\n    const data = d.data\n\n    if (wm.has(data)) {\n      return wm.get(data)\n    }\n    else {\n      const style = getComputedStyle(elements[i])\n      const omittedData = [{ name: data.name, value: props.valueFormatter(data[props.index]), color: style.fill }]\n      const componentDiv = document.createElement('div')\n      const TooltipComponent = props.customTooltip ?? ChartTooltip\n      createApp(TooltipComponent, { title: d[props.index], data: omittedData }).mount(componentDiv)\n      wm.set(d, componentDiv.innerHTML)\n      return componentDiv.innerHTML\n    }\n  }\n}\n</script>\n\n<template>\n  <VisTooltip\n    :horizontal-shift=\"20\" :vertical-shift=\"20\" :triggers=\"{\n      [selector]: template,\n    }\"\n  />\n</template>\n"
    },
    {
      "name": "ChartTooltip.vue",
      "content": "<script setup lang=\"ts\">\nimport { Card, CardContent, CardHeader, CardTitle } from '@/lib/registry/default/ui/card'\n\ndefineProps<{\n  title?: string\n  data: {\n    name: string\n    color: string\n    value: any\n  }[]\n}>()\n</script>\n\n<template>\n  <Card class=\"text-sm\">\n    <CardHeader v-if=\"title\" class=\"p-3 border-b\">\n      <CardTitle>\n        {{ title }}\n      </CardTitle>\n    </CardHeader>\n    <CardContent class=\"p-3 min-w-[180px] flex flex-col gap-1\">\n      <div v-for=\"(item, key) in data\" :key=\"key\" class=\"flex justify-between\">\n        <div class=\"flex items-center\">\n          <span class=\"w-2.5 h-2.5 mr-2\">\n            <svg width=\"100%\" height=\"100%\" viewBox=\"0 0 30 30\">\n              <path\n                d=\" M 15 15 m -14, 0 a 14,14 0 1,1 28,0 a 14,14 0 1,1 -28,0\"\n                :stroke=\"item.color\"\n                :fill=\"item.color\"\n                stroke-width=\"1\"\n              />\n            </svg>\n          </span>\n          <span>{{ item.name }}</span>\n        </div>\n        <span class=\"font-semibold ml-4\">{{ item.value }}</span>\n      </div>\n    </CardContent>\n  </Card>\n</template>\n"
    },
    {
      "name": "index.ts",
      "content": "export { default as ChartTooltip } from './ChartTooltip.vue'\nexport { default as ChartSingleTooltip } from './ChartSingleTooltip.vue'\nexport { default as ChartLegend } from './ChartLegend.vue'\nexport { default as ChartCrosshair } from './ChartCrosshair.vue'\n\nexport function defaultColors(count: number = 3) {\n  const quotient = Math.floor(count / 2)\n  const remainder = count % 2\n\n  const primaryCount = quotient + remainder\n  const secondaryCount = quotient\n  return [\n    ...Array.from(Array(primaryCount).keys()).map(i => `hsl(var(--vis-primary-color) / ${1 - (1 / primaryCount) * i})`),\n    ...Array.from(Array(secondaryCount).keys()).map(i => `hsl(var(--vis-secondary-color) / ${1 - (1 / secondaryCount) * i})`),\n  ]\n}\n\nexport * from './interface'\n"
    },
    {
      "name": "interface.ts",
      "content": "import 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   * Select the categories from your data. Used to populate the legend and toolip.\n   */\n  categories: KeyOf<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   * Function to format X label\n   */\n  xFormatter?: (tick: number | Date, i: number, ticks: number[] | Date[]) => string\n  /**\n   * Function to format Y label\n   */\n  yFormatter?: (tick: number | Date, i: number, ticks: number[] | Date[]) => string\n  /**\n   * Controls the visibility of the X axis.\n   * @default true\n   */\n  showXAxis?: boolean\n  /**\n   * Controls the visibility of the Y axis.\n   * @default true\n   */\n  showYAxis?: boolean\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   * Controls the visibility of gridline.\n   * @default true\n   */\n  showGridLine?: boolean\n}\n"
    }
  ],
  "type": "components:ui"
}
