{"version":3,"file":"index.d.ts","sources":["../src/types.ts","../src/plugin.ts"],"sourcesContent":["import {\r\n    ArcElement,\r\n    CanvasFontSpec,\r\n    Chart,\r\n    ChartArea,\r\n    ChartDataset,\r\n    FontSpec,\r\n    Point,\r\n    Scriptable,\r\n    ScriptableAndScriptableOptions,\r\n    ScriptableChartContext\r\n} from \"chart.js\";\r\n\r\nexport type Rect = {\r\n    x: number;\r\n    y: number;\r\n    width: number;\r\n    height: number;\r\n}\r\n\r\nexport type Size = {\r\n    width: number;\r\n    height: number;\r\n}\r\n\r\nexport type Center = {\r\n    x: number;\r\n    y: number;\r\n    d: number;\r\n    arc: ArcElement;\r\n    anchor: Point;\r\n    copy: Point;\r\n}\r\n\r\nexport type FontOptions = FontSpec & {\r\n    resizable?: boolean;\r\n    minSize?: number;\r\n    maxSize?: number;\r\n}\r\n\r\nexport type TRBL = {\r\n    top: number;\r\n    right: number;\r\n    bottom: number;\r\n    left: number;\r\n}\r\n\r\nexport type OutLabelsContext = {\r\n    chart: Chart<'doughnut' | 'pie'>;\r\n    dataIndex: number;\r\n    dataset: ChartDataset<'doughnut' | 'pie'>;\r\n    labels: string[];\r\n    datasetIndex: number;\r\n    percent: number;\r\n}\r\n\r\nexport type OutLabelsOptions = {\r\n    display?: Scriptable<boolean, OutLabelsContext>;\r\n    text?: Scriptable<string, OutLabelsContext>;\r\n\r\n    textAlign?: string;\r\n    color?: string;\r\n    borderRadius?: number;\r\n    borderWidth?: number;\r\n    lineWidth?: number;\r\n    stickLength?: number;\r\n    percentPrecision?: number;\r\n    valuePrecision?: number;\r\n\r\n    padding?: number | TRBL;\r\n\r\n    font?: ScriptableAndScriptableOptions<Partial<FontOptions>, ScriptableChartContext>;\r\n\r\n    backgroundColor?: Scriptable<string, OutLabelsContext>;\r\n    borderColor?: Scriptable<string, OutLabelsContext>;\r\n    lineColor?: Scriptable<string, OutLabelsContext>;\r\n}\r\n\r\nexport type ResolvedOutLabelsOptions = {\r\n    textAlign: CanvasTextAlign;\r\n    color: string | CanvasGradient | CanvasPattern;\r\n    borderRadius: number;\r\n    borderWidth: number;\r\n    lineWidth: number;\r\n\r\n    padding: ChartArea;\r\n\r\n    font: CanvasFontSpec;\r\n\r\n    backgroundColor: string | CanvasGradient | CanvasPattern;\r\n    borderColor: string | CanvasGradient | CanvasPattern;\r\n    lineColor: string | CanvasGradient | CanvasPattern;\r\n}","'use strict';\r\n\r\nimport {\r\n\tArcElement,\r\n\tChart,\r\n\tChartConfiguration,\r\n\tChartDataset,\r\n\tChartType,\r\n\tPlugin\r\n} from 'chart.js';\r\nimport defaults from './defaults';\r\n\r\nimport OutLabel from './OutLabel';\r\nimport { merge, resolve } from 'chart.js/helpers';\r\nimport { OutLabelsContext, OutLabelsOptions } from './types';\r\n\r\ndeclare type OutLabelsPluginType = Plugin<'doughnut' | 'pie', OutLabelsOptions>;\r\n\r\ndeclare module 'chart.js' {\r\n    // eslint-disable-next-line @typescript-eslint/no-unused-vars\r\n    interface PluginOptionsByType<TType extends ChartType> {\r\n        outlabels?: OutLabelsOptions\r\n    }\r\n}\r\n\r\nconst LABEL_KEY = OutLabel.LABEL_KEY;\r\n\r\nconst symSizeChanged = Symbol(\"sizeChanged\");\r\n\r\nfunction configure(dataset: ChartDataset<'doughnut' | 'pie', number[]>, options?: OutLabelsOptions) {\r\n\tlet override = (dataset as any).outlabels;\r\n\tlet config = {};\r\n\r\n\tif (override === false) {\r\n\t\treturn null;\r\n\t}\r\n\tif (override === true) {\r\n\t\toverride = {};\r\n\t}\r\n\r\n\treturn merge(config, [options, override]) as OutLabelsOptions;\r\n}\r\n\r\nfunction isPluginApplicableToDataset(\r\n\t\tchart: Chart<'doughnut' | 'pie', number[], unknown>,\r\n\t\tdataset?: ChartDataset<'doughnut' | 'pie', number[]>) {\r\n\tconst datasetType = dataset?.type || (chart.config as ChartConfiguration)?.type;\r\n\treturn ['pie', 'doughnut'].includes(datasetType);\r\n}\r\n\r\nfunction computeLargestCircleProps(chart: Chart<'doughnut' | 'pie', number[], unknown>) {\r\n\t// given how the data sets are arranged from largest to smallest,\r\n\t// simply return the first value\r\n\tfor (let i = 0; i < chart.data.datasets.length; i++) {\r\n\t\tif (!chart.isDatasetVisible(i)) {\r\n\t\t\tcontinue;\r\n\t\t}\r\n\t\tconst elements = chart.getDatasetMeta(i).data;\r\n\t\tfor (let j = 0; j < elements.length; j++) {\r\n\t\t\tconst el = elements[j];\r\n\t\t\tconst label = el[LABEL_KEY] as OutLabel | undefined;\r\n\t\t\tif (!label) {\r\n\t\t\t\tcontinue;\r\n\t\t\t}\r\n\r\n\t\t\treturn el.getProps([\"x\", \"y\", \"outerRadius\"], true)\r\n\t\t}\r\n\t}\r\n\treturn null;\r\n}\r\n\r\nconst OutLabelsPlugin: OutLabelsPluginType = {\r\n\tid: 'outlabels',\r\n\r\n\tdefaults: defaults,\r\n\r\n\tresize: function(chart) {\r\n\t\tchart[symSizeChanged] = true;\r\n\t},\r\n\r\n\tafterDatasetUpdate: function(chart, args, options) {\r\n\t\tif (!isPluginApplicableToDataset(chart, chart.data.datasets[args.index])) {\r\n\t\t\treturn;\r\n\t\t}\r\n\t\tconst labels = chart.config.data.labels as string[];\r\n\t\tconst dataset = chart.data.datasets[args.index];\r\n\t\tconst config = configure(dataset, options);\r\n\t\tconst elements = (args.meta.data || []) as ArcElement[];\r\n\t\tconst ctx = chart.ctx;\r\n\r\n\t\tctx.save();\r\n\r\n\t\t// The code in the loops below deals with visibility of annular sectors in three aspects\r\n\t\t// 1. visibility of all annular sectors in a dataset. Determined by chart.isDatasetVisible(args.index),\r\n\t\t//    and can be changed with chart.show(args.index) and chart.hide(args.index)\r\n\t\t// 2. visibility of all annular sectors across multiple datasets which have the same index i. Determined by\r\n\t\t//    chart.getDataVisibility(i), and can be changed with chart.toggleDataVisibility(i) followed by chart.update()\r\n\t\t// 3. (Chart.js 4) visibility of a particular annular sector at index i in a particular dataset. Determined by\r\n\t\t//    chart.getDatasetMeta(args.index).data[i].hidden, which is equivalent in this plugin hook\r\n\t\t//    to args.meta.data[i].hidden,\r\n\t\t//    and can be changed with chart.show(args.index, i) and chart.hide(args.index, i)\r\n\t\t//\r\n\t\t// So this plugin checks that each annular sector is visible in all 3 aspects, before labelling it.\r\n\r\n\t\tconst elementsVisible = chart.isDatasetVisible(args.index);\r\n\r\n\t\tlet dataSum = 0;\r\n\t\tfor (let i = 0; i < dataset.data.length; i++) {\r\n\t\t\tif (chart.getDataVisibility(i) && !(elements[i] as any).hidden) {\r\n\t\t\t\tdataSum += dataset.data[i];\r\n\t\t\t}\r\n\t\t}\r\n\t\tfor (let i = 0; i < elements.length; i++) {\r\n\t\t\tconst el = elements[i];\r\n\t\t\tconst label = el[LABEL_KEY] as OutLabel | undefined;\r\n\t\t\tlet newLabel: OutLabel | undefined;\r\n\r\n\t\t\tif (dataSum && elementsVisible && chart.getDataVisibility(i) && !(el as any).hidden) {\r\n\t\t\t\tconst percent = dataSum ? 100 * dataset.data[i] / dataSum : 0;\r\n\t\t\t\tlet context: OutLabelsContext = {\r\n\t\t\t\t\tchart: chart,\r\n\t\t\t\t\tdataIndex: i,\r\n\t\t\t\t\tdataset: dataset,\r\n\t\t\t\t\tlabels: labels,\r\n\t\t\t\t\tdatasetIndex: args.index,\r\n\t\t\t\t\tpercent: percent\r\n\t\t\t\t};\r\n\t\t\t\t// Check whether the label should be displayed\r\n\t\t\t\tif (resolve([config && config.display, true], context, i)) {\r\n\t\t\t\t\ttry {\r\n\t\t\t\t\t\tnewLabel = new OutLabel(el, i, ctx, config, context);\r\n\t\t\t\t\t} catch(e) {\r\n\t\t\t\t\t\tconsole.log(e);\r\n\t\t\t\t\t\tnewLabel = null;\r\n\t\t\t\t\t}\r\n\t\t\t\t}\r\n\t\t\t}\r\n\r\n\t\t\tif (\r\n\t\t\t\tlabel && \r\n\t\t\t\tnewLabel && \r\n\t\t\t\t!chart[symSizeChanged] &&\r\n\t\t\t\t(label.label === newLabel.label) && \r\n\t\t\t\t(label.encodedText === newLabel.encodedText)\r\n\t\t\t) {\r\n\t\t\t\tnewLabel.offset = label.offset;\r\n\t\t\t}\r\n\r\n\t\t\tel[LABEL_KEY] = newLabel;\r\n\t\t}\r\n\r\n\t\tctx.restore();\r\n\t\tchart[symSizeChanged] = false;\r\n\t},\r\n\r\n\tafterDraw: function (chart) {\r\n\t\tconst largestCircleProps = computeLargestCircleProps(chart);\r\n\t\tfor (let i = 0; i < chart.data.datasets.length; i++) {\r\n\t\t\tconst elements = chart.getDatasetMeta(i).data as ArcElement[];\r\n\t\t\tfor (let j = 0; j < elements.length; j++) {\r\n\t\t\t\tconst el = elements[j];\r\n\t\t\t\tconst label = el[LABEL_KEY] as OutLabel | undefined;\r\n\t\t\t\tif (!label) {\r\n\t\t\t\t\tcontinue;\r\n\t\t\t\t}\r\n\r\n\t\t\t\tlabel.update(chart, el, i, j, {\r\n\t\t\t\t\tx: largestCircleProps.x,\r\n\t\t\t\t\ty: largestCircleProps.y\r\n\t\t\t\t}, largestCircleProps.outerRadius);\r\n\t\t\t\tlabel.drawLine();\r\n\t\t\t}\r\n\t\t}\r\n\t\tfor (let i = 0; i < chart.data.datasets.length; i++) {\r\n\t\t\tconst elements = chart.getDatasetMeta(i).data;\r\n\t\t\tfor (let j = 0; j < elements.length; j++) {\r\n\t\t\t\tconst el = elements[j];\r\n\t\t\t\tconst label = el[LABEL_KEY] as OutLabel | undefined;\r\n\t\t\t\tif (!label) {\r\n\t\t\t\t\tcontinue;\r\n\t\t\t\t}\r\n\r\n\t\t\t\tlabel.draw();\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n};\r\n\r\nexport default OutLabelsPlugin;"],"names":[],"mappings":";;;;;;;;AAmBO;AACP;AACA;AACA;AACA;AACO;AACP;AACA;AACA;AACA;AACA;AACO;AACP;AACA;AACA;AACA;AACA;AACA;AACA;AACO;AACP;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACpDA;AACA;AACA;AACA;AACA;AACA;AACA;;"}