{"version":3,"file":"vcdonut.mjs","sources":["../src/utils/misc.ts","../src/utils/colors.ts","../src/components/DonutSections.vue","../src/components/DonutChart.vue","../src/lib.ts"],"sourcesContent":["import { getCurrentInstance, onUnmounted, ref, watch, type Ref, type StyleValue } from 'vue';\n\nconst legendGap = '1em';\n\nexport const legendPlacementStyles: Record<\n  'top' | 'right' | 'bottom' | 'left',\n  {\n    container: StyleValue;\n    legend: StyleValue;\n  }\n> = {\n  top: {\n    container: { flexDirection: 'column' },\n    legend: { order: -1, margin: 0, marginBottom: legendGap },\n  },\n  right: {\n    container: {},\n    legend: {\n      flexDirection: 'column',\n      margin: 0,\n      marginLeft: legendGap,\n    },\n  },\n  bottom: {\n    container: { flexDirection: 'column' },\n    legend: {},\n  },\n  left: {\n    container: {},\n    legend: {\n      flexDirection: 'column',\n      order: -1,\n      margin: 0,\n      marginRight: legendGap,\n    },\n  },\n};\n\nexport function toPrecise(value: number): number {\n  return Number(value.toPrecision(15));\n}\n\nexport function useElementSize({\n  el,\n  onResize,\n}: {\n  el: Ref<HTMLElement | null | undefined>;\n  onResize?: (width: number, height: number) => void;\n}) {\n  const width = ref(0);\n  const height = ref(0);\n\n  const observer = new ResizeObserver((entries) => {\n    if (!el.value) return;\n    const entry = entries[0];\n    width.value = entry.contentRect.width;\n    height.value = entry.contentRect.height;\n    /* istanbul ignore else -- @preserve */\n    if (onResize) onResize(width.value, height.value);\n  });\n\n  watch(\n    el,\n    (newEl, oldEl) => {\n      if (oldEl) observer.unobserve(oldEl);\n      if (newEl) observer.observe(newEl);\n    },\n    { immediate: true },\n  );\n\n  const stop = () => {\n    observer.disconnect();\n  };\n\n  if (getCurrentInstance()) {\n    onUnmounted(() => {\n      stop();\n    });\n  }\n\n  return { width, height, stop };\n}\n","export const defaultColors: readonly string[] = [\n  '#FF6384',\n  '#36A2EB',\n  '#FFCE56',\n  '#F58231',\n  '#46F0F0',\n  '#D2F53C',\n  '#911EB4',\n  '#F032E6',\n  '#3CB44B',\n  '#FFE119',\n  '#E6194B',\n  '#FABEBE',\n  '#008080',\n  '#E6BEFF',\n  '#0082C8',\n  '#AA6E28',\n  '#FFFAC8',\n  '#800000',\n  '#AAFFC3',\n  '#808000',\n  '#FFD8B1',\n  '#000080',\n  '#808080',\n  '#000000',\n];\n\n/** returns a dispatcher that returns the next default color with every call */\nexport const getDefaultColorDispatcher = () => {\n  let currentDefaultColorIdx = 0;\n  let hasWrapped = false;\n  const dispatcher = () => {\n    if (currentDefaultColorIdx === 0 && hasWrapped) {\n      console.warn('Ran out of default colors, reusing colors');\n    }\n\n    const color = defaultColors[currentDefaultColorIdx];\n\n    currentDefaultColorIdx = (currentDefaultColorIdx + 1) % defaultColors.length;\n    if (currentDefaultColorIdx === 0) hasWrapped = true;\n\n    return color;\n  };\n\n  return dispatcher;\n};\n","<template>\n  <div class=\"cdc-sections\" :style=\"containerStyles\">\n    <div\n      v-for=\"(section, idx) in chunkedSectionsWithRenderData\"\n      :key=\"idx\"\n      class=\"cdc-section\"\n      :class=\"section.className\"\n      :style=\"section.sectionStyles\"\n      v-on=\"section.listeners\"\n    >\n      <div class=\"cdc-filler\" :style=\"section.fillerStyles\" :title=\"section.baseSection.label || ''\"></div>\n    </div>\n  </div>\n</template>\n\n<script setup lang=\"ts\">\nimport { computed, type StyleValue } from 'vue';\nimport type { DonutSection } from '@/utils/types';\nimport { toPrecise } from '@/utils/misc';\nimport { getDefaultColorDispatcher } from '@/utils/colors';\n\nexport interface Props {\n  sections: DonutSection[];\n  startAngle: number;\n  total: number;\n}\n\nexport interface Emits {\n  (e: 'section-click', data: { section: DonutSection; event: MouseEvent }): void;\n  (e: 'section-mouseenter', data: { section: DonutSection; event: MouseEvent }): void;\n  (e: 'section-mouseleave', data: { section: DonutSection; event: MouseEvent }): void;\n  (e: 'section-mouseover', data: { section: DonutSection; event: MouseEvent }): void;\n  (e: 'section-mouseout', data: { section: DonutSection; event: MouseEvent }): void;\n  (e: 'section-mousemove', data: { section: DonutSection; event: MouseEvent }): void;\n}\n\nconst props = defineProps<Props>();\nconst emit = defineEmits<Emits>();\n\nconst containerStyles = computed<StyleValue>(() => ({\n  transform: `rotate(${props.startAngle}deg)`,\n}));\n\ntype ChunkedSection = {\n  baseSection: DonutSection;\n  degree: number;\n  color: string;\n};\n\ntype ChunkedSectionWithRenderData = ChunkedSection & {\n  className: string;\n  fillerStyles: { backgroundColor: string; transform: string };\n  sectionStyles: { transform: string };\n  listeners: {\n    click: (e: MouseEvent) => void;\n    mouseenter: (e: MouseEvent) => void;\n    mouseleave: (e: MouseEvent) => void;\n    mouseover: (e: MouseEvent) => void;\n    mouseout: (e: MouseEvent) => void;\n    mousemove: (e: MouseEvent) => void;\n  };\n};\n\nenum SectionClass {\n  LEFT = 'cdc-section-left',\n  RIGHT = 'cdc-section-right',\n}\n\nconst chunkedSectionsWithRenderData = computed<ChunkedSectionWithRenderData[]>(() => {\n  const DEGREES_IN_A_CIRCLE = 360;\n  const MAX_DEGREES_PER_SECTION = 180;\n\n  let consumedDegrees = 0;\n  const getNextDefaultColor = getDefaultColorDispatcher();\n\n  // chunk sections that overlap both sides into smaller ones and assign colors\n  const chunkedSections: Array<ChunkedSection> = [];\n  props.sections.forEach((section) => {\n    const valToDeg = toPrecise(DEGREES_IN_A_CIRCLE * (section.value / (props.total || 1)));\n    const color = section.color || getNextDefaultColor();\n\n    const consumedWithCurrent = toPrecise(consumedDegrees + valToDeg);\n    if (consumedWithCurrent > MAX_DEGREES_PER_SECTION) {\n      const remainingDegreesInCurrent = toPrecise(MAX_DEGREES_PER_SECTION - consumedDegrees);\n      const remainingDegreesInNext = toPrecise(valToDeg - remainingDegreesInCurrent);\n\n      chunkedSections.push(\n        { baseSection: section, degree: remainingDegreesInCurrent, color },\n        { baseSection: section, degree: remainingDegreesInNext, color },\n      );\n    } else {\n      chunkedSections.push({ baseSection: section, degree: valToDeg, color });\n    }\n\n    consumedDegrees = consumedWithCurrent;\n    if (consumedDegrees >= MAX_DEGREES_PER_SECTION) {\n      consumedDegrees = toPrecise(consumedDegrees - MAX_DEGREES_PER_SECTION);\n    }\n  });\n\n  const ret: Array<ChunkedSectionWithRenderData> = [];\n\n  consumedDegrees = 0;\n  let offsetBy = 0;\n  chunkedSections.forEach((section) => {\n    if (section.degree === 0) return;\n\n    let [className, offset] = [SectionClass.RIGHT, -180];\n    if (consumedDegrees >= MAX_DEGREES_PER_SECTION) {\n      [className, offset] = [SectionClass.LEFT, 180]; // rendering on the left half of the donut\n    }\n\n    const fillerStyles = {\n      backgroundColor: section.color,\n      transform: `rotate(${toPrecise(offset + section.degree)}deg)`,\n    };\n\n    const sectionStyles = { transform: `rotate(${offsetBy}deg)` };\n\n    consumedDegrees = toPrecise(consumedDegrees + section.degree);\n    if (consumedDegrees === MAX_DEGREES_PER_SECTION) offsetBy = 0;\n    else offsetBy = toPrecise(offsetBy + section.degree);\n\n    const listeners = {\n      click: (e: MouseEvent) => emit('section-click', { section: section.baseSection, event: e }),\n      mouseenter: (e: MouseEvent) => emit('section-mouseenter', { section: section.baseSection, event: e }),\n      mouseleave: (e: MouseEvent) => emit('section-mouseleave', { section: section.baseSection, event: e }),\n      mouseover: (e: MouseEvent) => emit('section-mouseover', { section: section.baseSection, event: e }),\n      mouseout: (e: MouseEvent) => emit('section-mouseout', { section: section.baseSection, event: e }),\n      mousemove: (e: MouseEvent) => emit('section-mousemove', { section: section.baseSection, event: e }),\n    };\n\n    // renders the sections with correct colors and plugs in default colors if one isn\\'t specified with the \"color\" property renders the sections with correct colors and plugs in default colors if one isn\\'t specified with the \"color\" property renders the sections with correct colors and plugs in default colors if one isn\\'t specified with the \"color\" property renders the sections with correct colors and plugs in default colors if one isn\\'t specified with the \"color\" property\n\n    ret.push({\n      baseSection: section.baseSection,\n\n      degree: section.degree,\n      color: section.color,\n\n      className,\n\n      fillerStyles,\n      sectionStyles,\n\n      listeners,\n    });\n  });\n\n  return ret;\n});\n</script>\n","<template>\n  <div class=\"cdc-container\" :style=\"placementStyles?.container\">\n    <div ref=\"donutEl\" class=\"cdc\" :style=\"donutStyles\">\n      <donut-sections\n        :sections=\"props.sections\"\n        :start-angle=\"props.startAngle\"\n        :total=\"props.total\"\n        @section-click=\"emit('section-click', $event.section, $event.event)\"\n        @section-mouseenter=\"emit('section-mouseenter', $event.section, $event.event)\"\n        @section-mouseleave=\"emit('section-mouseleave', $event.section, $event.event)\"\n        @section-mouseover=\"emit('section-mouseover', $event.section, $event.event)\"\n        @section-mouseout=\"emit('section-mouseout', $event.section, $event.event)\"\n        @section-mousemove=\"emit('section-mousemove', $event.section, $event.event)\"\n      >\n      </donut-sections>\n      <div class=\"cdc-overlay\" :style=\"overlayStyles\">\n        <div class=\"cdc-text\" :style=\"donutTextStyles\">\n          <slot>{{ text }}</slot>\n        </div>\n      </div>\n    </div>\n\n    <slot name=\"legend\">\n      <div v-if=\"hasLegend\" class=\"cdc-legend\" :style=\"placementStyles?.legend\">\n        <span v-for=\"(legendItem, idx) in legendItems\" :key=\"idx\" class=\"cdc-legend-item\" :title=\"legendItem.value\">\n          <span class=\"cdc-legend-item-color\" :style=\"legendItem.styles\"></span>\n          <span>{{ legendItem.label }}</span>\n        </span>\n      </div>\n    </slot>\n  </div>\n</template>\n\n<script lang=\"ts\" setup>\nimport { computed, ref, watch, type StyleValue } from 'vue';\nimport { toPrecise, useElementSize } from '@/utils/misc';\nimport { getDefaultColorDispatcher } from '@/utils/colors';\nimport { legendPlacementStyles } from '@/utils/misc';\nimport DonutSections from '@/components/DonutSections.vue';\nimport type { DonutSection } from '@/utils/types';\nimport '@/styles/main.css';\n\nexport interface Props {\n  /** diameter of the donut */\n  size?: number;\n\n  /** unit to use for `size` */\n  unit?: string;\n\n  /** percent value for the donut ring's thickness */\n  thickness?: number;\n\n  /** text in the middle of the donut */\n  text?: string;\n\n  /** auto adjust text size based on donut size */\n  autoAdjustTextSize?: boolean;\n\n  /**\n   * color to use for the middle of the donut\n   * either set this to `transparent` or set `thickness` to 100 to make a pie chart\n   */\n  background?: string;\n\n  /** color to use for the empty ring areas */\n  foreground?: string;\n\n  /** sections of the donut */\n  sections?: DonutSection[];\n\n  /** total value of all sections */\n  total?: number;\n\n  /** show legend */\n  hasLegend?: boolean;\n\n  /** legend placement */\n  legendPlacement?: 'top' | 'right' | 'bottom' | 'left';\n\n  /** degree angle at which the first section begins */\n  startAngle?: number;\n\n  /** suppress validation warnings */\n  suppressValidationWarnings?: boolean;\n}\n\nexport interface Emits {\n  (e: 'section-click', section: DonutSection, event: MouseEvent): void;\n  (e: 'section-mouseenter', section: DonutSection, event: MouseEvent): void;\n  (e: 'section-mouseleave', section: DonutSection, event: MouseEvent): void;\n  (e: 'section-mouseover', section: DonutSection, event: MouseEvent): void;\n  (e: 'section-mouseout', section: DonutSection, event: MouseEvent): void;\n  (e: 'section-mousemove', section: DonutSection, event: MouseEvent): void;\n}\n\nconst props = withDefaults(defineProps<Props>(), {\n  size: 250,\n  unit: 'px',\n  thickness: 20,\n  text: '',\n  autoAdjustTextSize: true,\n  background: '#ffffff',\n  foreground: '#eeeeee',\n  sections: () => [],\n  total: 100,\n  hasLegend: false,\n  legendPlacement: 'bottom',\n  startAngle: 0,\n  suppressValidationWarnings: false,\n});\nconst emit = defineEmits<Emits>();\n\nconst donutEl = ref<HTMLElement>();\n\n// #region legend\n\nconst legendItems = computed(() => {\n  const getNextDefaultColor = getDefaultColorDispatcher();\n\n  const items: Array<{\n    label: string;\n    value: string;\n    styles: { backgroundColor: string };\n  }> = props.sections.map((section, idx) => ({\n    label: section.label || `Section ${idx + 1}`,\n    value: `${section.value} (${toPrecise(section.value / (props.total || 1)) * 100}%)`,\n    styles: {\n      backgroundColor: section.color || getNextDefaultColor(),\n    },\n  }));\n\n  return items;\n});\n\n// #endregion legend\n\n// #region dynamic font size\n\nconst fontSize = ref('1em');\n\nconst recalculateFontSize = () => {\n  if (!props.autoAdjustTextSize) {\n    fontSize.value = '1em';\n    return;\n  }\n\n  const scaleDownBy = 0.08;\n  let widthInPx: number | null = props.size;\n\n  if (props.unit !== 'px') {\n    /* istanbul ignore else -- @preserve */\n    if (donutEl.value) widthInPx = donutEl.value.clientWidth;\n    else widthInPx = null;\n  }\n\n  fontSize.value = widthInPx ? `${toPrecise(widthInPx * scaleDownBy)}px` : '1em';\n};\n\nuseElementSize({\n  el: donutEl,\n  onResize: recalculateFontSize,\n});\n\nwatch(\n  () => props.autoAdjustTextSize,\n  (autoAdjustTextSize) => {\n    if (autoAdjustTextSize) window.addEventListener('resize', recalculateFontSize);\n    else window.removeEventListener('resize', recalculateFontSize);\n\n    recalculateFontSize();\n  },\n);\n\n// #endregion dynamic font size\n\n// #region dynamic styles\n\nconst placementStyles = computed(() => {\n  if (!props.hasLegend) return null;\n  return legendPlacementStyles[props.legendPlacement];\n});\n\nconst donutStyles = computed<StyleValue>(() => {\n  const size = `${props.size}${props.unit}`;\n  return {\n    width: size,\n    paddingBottom: size,\n    backgroundColor: props.foreground,\n  };\n});\n\nconst overlayStyles = computed<StyleValue>(() => {\n  const size = 100 - props.thickness;\n\n  const sizePercent = `${size}%`;\n  const pos = `calc(50% - ${size / 2}%)`;\n\n  return {\n    height: sizePercent,\n    width: sizePercent,\n    top: pos,\n    left: pos,\n    backgroundColor: props.background,\n  };\n});\n\nconst donutTextStyles = computed<StyleValue>(() => ({\n  fontSize: fontSize.value,\n}));\n\n// #endregion dynamic styles\n\n// #region validation\n\nwatch(\n  () => props.size,\n  () => {\n    if (props.suppressValidationWarnings) return;\n    if (props.size < 0) console.warn('vue-css-donut-chart: `size` must be a positive number');\n  },\n  { immediate: true },\n);\n\nwatch(\n  () => props.thickness,\n  () => {\n    if (props.suppressValidationWarnings) return;\n    if (props.thickness < 0 || props.thickness > 100)\n      console.warn('vue-css-donut-chart: `thickness` must be between 0 and 100');\n  },\n  { immediate: true },\n);\n\nwatch(\n  [() => props.total, () => props.sections],\n  () => {\n    if (props.suppressValidationWarnings) return;\n\n    if (props.total < 0) {\n      console.warn('vue-css-donut-chart: `total` must be a positive number');\n      return;\n    }\n\n    const totalValue = toPrecise(\n      props.sections.reduce((acc, section) => acc + (typeof section.value === 'number' ? section.value : 0), 0),\n    );\n    if (totalValue > props.total) console.warn('vue-css-donut-chart: Sum of section values exceeds `total`');\n  },\n  { immediate: true, deep: true },\n);\n\n// #endregion validation\n</script>\n","import { type Plugin } from 'vue';\nimport DonutChart, { type Props as DonutChartProps, type Emits as DonutChartEmits } from '@/components/DonutChart.vue';\nimport type { DonutSection } from '@/utils/types';\n\nconst DonutPlugin: Plugin = {\n  install(app) {\n    app.component('VcDonut', DonutChart);\n  },\n};\n\nexport type { DonutSection, DonutChartProps, DonutChartEmits };\nexport { DonutChart as VcDonut };\nexport default DonutPlugin;\n"],"names":["legendGap","legendPlacementStyles","toPrecise","value","useElementSize","el","onResize","width","ref","height","observer","entries","entry","watch","newEl","oldEl","stop","getCurrentInstance","onUnmounted","defaultColors","getDefaultColorDispatcher","currentDefaultColorIdx","hasWrapped","color","props","__props","emit","__emit","containerStyles","computed","chunkedSectionsWithRenderData","consumedDegrees","getNextDefaultColor","chunkedSections","section","valToDeg","consumedWithCurrent","remainingDegreesInCurrent","remainingDegreesInNext","ret","offsetBy","className","offset","fillerStyles","sectionStyles","listeners","e","donutEl","legendItems","idx","fontSize","recalculateFontSize","scaleDownBy","widthInPx","autoAdjustTextSize","placementStyles","donutStyles","size","overlayStyles","sizePercent","pos","donutTextStyles","acc","DonutPlugin","app","DonutChart"],"mappings":"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"}