@mozaic-ds/chart 0.1.0-beta.1 → 0.1.0-beta.11

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (34) hide show
  1. package/dist/mozaic-chart.js +2801 -2129
  2. package/dist/mozaic-chart.umd.cjs +11 -11
  3. package/dist/style.css +1 -1
  4. package/package.json +25 -11
  5. package/src/components/bar/BarChart.stories.ts +7 -10
  6. package/src/components/bar/BarChart.vue +212 -136
  7. package/src/components/bar/index.ts +8 -0
  8. package/src/components/doughnut/DoughnutChart.stories.ts +1 -0
  9. package/src/components/doughnut/DoughnutChart.vue +163 -100
  10. package/src/components/doughnut/index.ts +8 -0
  11. package/src/components/index.ts +4 -0
  12. package/src/components/line/LineChart.stories.ts +0 -1
  13. package/src/components/line/LineChart.vue +305 -257
  14. package/src/components/line/index.ts +8 -0
  15. package/src/components/mixed/MixedBarLineChart.stories.ts +87 -0
  16. package/src/components/mixed/MixedBarLineChart.vue +404 -0
  17. package/src/components/mixed/index.ts +8 -0
  18. package/src/components/radar/RadarChart.stories.ts +2 -2
  19. package/src/components/radar/RadarChart.vue +210 -150
  20. package/src/components/radar/index.ts +8 -0
  21. package/src/main.ts +2 -1
  22. package/src/plugin.ts +19 -0
  23. package/src/services/ChartsCommonLegend.ts +35 -23
  24. package/src/services/DoughnutChartFunctions.ts +101 -56
  25. package/src/services/FormatUtilities.ts +1 -1
  26. package/src/services/GenericTooltipService.ts +21 -7
  27. package/src/services/MixedBarLineFunctions.ts +280 -0
  28. package/src/services/RadarChartFunctions.ts +13 -11
  29. package/src/stories/Changelog.mdx +6 -0
  30. package/src/stories/Contributing.mdx +101 -0
  31. package/src/stories/GettingStarted.mdx +92 -0
  32. package/src/stories/SupportAndOnboarding.mdx +44 -0
  33. package/src/types/MixedBarLineData.ts +7 -0
  34. package/src/types/TooltipChartType.ts +1 -0
@@ -1,85 +1,130 @@
1
- import { ref } from 'vue';
2
- import type { Ref } from 'vue';
3
- import {
4
- getHtmlLegendPlugin
5
- } from '../services/ChartsCommonLegend';
6
- import { formatWithThousandsSeprators } from '../services/FormatUtilities';
1
+ import { ref } from "vue";
2
+ import type { Ref } from "vue";
3
+ import { getHtmlLegendPlugin } from "../services/ChartsCommonLegend";
4
+ import { formatWithThousandsSeprators } from "../services/FormatUtilities";
7
5
 
8
- import ChartDesign from './patterns/ChartDesign';
9
- import {addAlpha} from './ColorFunctions';
6
+ import { addAlpha } from "./ColorFunctions";
10
7
 
11
8
  export default function () {
12
9
  const doughnutRef: Ref = ref(null);
13
10
  const onHoverIndex: Ref<number | null> = ref(null);
14
11
  const backgroundColor: Ref<CanvasPattern[] | null> = ref(null);
15
12
 
16
- function privateGetHtmlLegendPlugin(legendContainer: Ref, selectMode: Ref<boolean>, disableAccessibility: Ref<boolean>, patternsColors: Ref<string[]>, patternsList: Ref<((hover: boolean, color: string, disableAccessibility: boolean) => CanvasPattern)[]>, maxValueToDisplay: number, doughnutData: any) {
17
- return getHtmlLegendPlugin(legendContainer, selectMode, onHoverIndex, disableAccessibility, patternsColors, patternsList, maxValueToDisplay, doughnutData);
13
+ function privateGetHtmlLegendPlugin(
14
+ legendContainer: Ref,
15
+ selectMode: Ref<boolean>,
16
+ disableAccessibility: Ref<boolean>,
17
+ patternsColors: Ref<string[]>,
18
+ patternsList: Ref<
19
+ ((
20
+ hover: boolean,
21
+ color: string,
22
+ disableAccessibility: boolean
23
+ ) => CanvasPattern)[]
24
+ >,
25
+ maxValueToDisplay: number,
26
+ doughnutData: any
27
+ ) {
28
+ return getHtmlLegendPlugin(
29
+ legendContainer,
30
+ selectMode,
31
+ onHoverIndex,
32
+ disableAccessibility,
33
+ patternsColors,
34
+ patternsList,
35
+ maxValueToDisplay,
36
+ doughnutData
37
+ );
18
38
  }
19
39
 
20
-
21
- function getBackgroundColor(patternsColors: string[], patternsList: ((hover: boolean, color: string, disableAccessibility: boolean) => CanvasPattern)[], disableAccessibility: boolean) {
40
+ function getBackgroundColor(
41
+ patternsColors: string[],
42
+ patternsList: ((
43
+ hover: boolean,
44
+ color: string,
45
+ disableAccessibility: boolean
46
+ ) => CanvasPattern)[],
47
+ disableAccessibility: boolean
48
+ ) {
22
49
  if (onHoverIndex.value !== null) {
23
- return patternsList
24
- .map((pattern, index) => onHoverIndex.value === index ? pattern(false, patternsColors[index], disableAccessibility) : pattern(true, patternsColors[index], disableAccessibility));
50
+ return patternsList.map((pattern, index) =>
51
+ onHoverIndex.value === index
52
+ ? pattern(false, patternsColors[index], disableAccessibility)
53
+ : pattern(true, patternsColors[index], disableAccessibility)
54
+ );
25
55
  } else {
26
- return patternsList
27
- .map((pattern, index) => pattern(false, patternsColors[index], disableAccessibility),);
56
+ return patternsList.map((pattern, index) =>
57
+ pattern(false, patternsColors[index], disableAccessibility)
58
+ );
28
59
  }
29
60
  }
30
61
 
31
62
  function getBorderColor(patternsColors: string[]): string[] {
32
63
  if (onHoverIndex.value !== null) {
33
- return patternsColors.map((color, index) => onHoverIndex.value === index ? color : addAlpha(color, 0.2));
64
+ return patternsColors.map((color, index) =>
65
+ onHoverIndex.value === index ? color : addAlpha(color, 0.2)
66
+ );
34
67
  } else {
35
68
  return patternsColors;
36
69
  }
37
70
  }
38
71
 
72
+ function getOnHoverOptions() {
73
+ return (_ignore: unknown, activeElements: Array<any>): void => {
74
+ if (activeElements[0] !== undefined) {
75
+ onHoverIndex.value = activeElements[0].element.$context.index;
76
+ } else {
77
+ onHoverIndex.value = null;
78
+ }
79
+ };
80
+ }
39
81
 
40
- function getOnHoverOptions () {
41
- return (_ignore: unknown, activeElements: Array<any>): void => {
42
- if (activeElements[0] !== undefined) {
43
- onHoverIndex.value = activeElements[0].element.$context.index;
44
- } else {
45
- onHoverIndex.value = null;
46
- }
82
+ const getFormatedText = (str: string) => {
83
+ return str.charAt(0).toUpperCase() + str.slice(1).toLowerCase();
47
84
  };
48
- }
49
-
50
- const getFormatedText = (str: string) => {
51
- return str.charAt(0).toUpperCase() + str.slice(1).toLowerCase();
52
- };
53
85
 
54
- function getDoughnutLabels(labels: string[], data: any[], maxValues: number) {
55
- let truncatedLabels = labels.slice(0);
56
- let truncatedData = data.slice(0);
57
- if (labels.length > maxValues){
58
- truncatedData = groupDataAfterNthValue(data, maxValues);
59
- truncatedLabels = truncatedLabels.slice(0, maxValues - 1);
60
- truncatedLabels.push('others');
86
+ function getDoughnutLabels(
87
+ labels: string[],
88
+ data: any[],
89
+ maxValues: number,
90
+ othersLabel: string
91
+ ) {
92
+ let truncatedLabels = labels.slice(0);
93
+ let truncatedData = data.slice(0);
94
+ if (labels.length > maxValues) {
95
+ truncatedData = groupDataAfterNthValue(data, maxValues);
96
+ truncatedLabels = truncatedLabels.slice(0, maxValues - 1);
97
+ truncatedLabels.push(othersLabel);
98
+ }
99
+ return truncatedLabels.map(
100
+ (label: string, index: number) =>
101
+ `${getFormatedText(label)} (${formatWithThousandsSeprators(
102
+ truncatedData[index].rate as number
103
+ )} %)`
104
+ );
61
105
  }
62
- return truncatedLabels.map((label: string, index: number) => `${getFormatedText(label)} (${formatWithThousandsSeprators(truncatedData[index].rate as number)} %)`);
63
- }
64
106
 
65
- function groupDataAfterNthValue (data: any, maxValues: number): any[] {
66
- if (maxValues < 1) {
67
- return data;
68
- }
69
- let truncatedData = data.slice(0);
70
- if (data.length > maxValues) {
71
- truncatedData = truncatedData.slice(0, maxValues);
72
- truncatedData[maxValues - 1] = data.slice(maxValues).reduce((result: any, current: any) => {
73
- result.rate += current.rate;
74
- result.value += current.value;
75
- return result;
76
- }, {
77
- rate: data[maxValues - 1].rate,
78
- value: data[maxValues - 1].value
79
- });
107
+ function groupDataAfterNthValue(data: any, maxValues: number): any[] {
108
+ if (maxValues < 1) {
109
+ return data;
110
+ }
111
+ let truncatedData = data.slice(0);
112
+ if (data.length > maxValues) {
113
+ truncatedData = truncatedData.slice(0, maxValues);
114
+ truncatedData[maxValues - 1] = data.slice(maxValues).reduce(
115
+ (result: any, current: any) => {
116
+ result.rate += current.rate;
117
+ result.value += current.value;
118
+ return result;
119
+ },
120
+ {
121
+ rate: data[maxValues - 1].rate,
122
+ value: data[maxValues - 1].value,
123
+ }
124
+ );
125
+ }
126
+ return truncatedData;
80
127
  }
81
- return truncatedData;
82
- }
83
128
 
84
129
  return {
85
130
  onHoverIndex,
@@ -91,6 +136,6 @@ function groupDataAfterNthValue (data: any, maxValues: number): any[] {
91
136
  getFormatedText,
92
137
  getBorderColor,
93
138
  backgroundColor,
94
- doughnutRef
139
+ doughnutRef,
95
140
  };
96
141
  }
@@ -1,4 +1,4 @@
1
- export function formatTicks (val: number, unit?: string | null): string {
1
+ export function formatTicks (val: number, unit?: string): string {
2
2
  const fixedValue = parseInt(val.toFixed());
3
3
  return `${new Intl.NumberFormat().format(fixedValue)}${unit ? ' ' + unit : ''}`;
4
4
  }
@@ -39,6 +39,9 @@ export type Context = {
39
39
  replay?: unknown;
40
40
  tooltip: {
41
41
  dataPoints: {
42
+ dataset?: {
43
+ type?: string
44
+ },
42
45
  dataIndex?: number,
43
46
  datasetIndex?: number
44
47
  }[];
@@ -110,6 +113,7 @@ export class GenericTooltipService {
110
113
  const body = this.chartType === 'DOUGHNUT' ? [tooltipModel.title[0].split('(')[0].trim()]: bodyLines[0];
111
114
  let legendIconStyle = '';
112
115
  let legendInnerStyle = '';
116
+ const datasetType = context.tooltip?.dataPoints[0]?.dataset?.type;
113
117
 
114
118
  if (this.chartType === 'RADAR' || this.chartType === 'LINE_CHART') {
115
119
  legendIconStyle = this.createLegendStyle(context);
@@ -118,6 +122,13 @@ export class GenericTooltipService {
118
122
  this.chartType === 'DETAILS_BAR_CHART' ||
119
123
  this.chartType === 'DOUGHNUT') {
120
124
  legendIconStyle = this.createPatternLegendStyle(context);
125
+ } else if (this.chartType === 'MIXED_BAR_LINE_CHART') {
126
+ if (datasetType === 'bar') {
127
+ legendIconStyle = this.createPatternLegendStyle(context);
128
+ } else {
129
+ legendIconStyle = this.createLegendStyle(context);
130
+ legendInnerStyle = this.createLegendInnerStyle(context);
131
+ }
121
132
  }
122
133
 
123
134
  this.addLegendToDom(
@@ -129,7 +140,8 @@ export class GenericTooltipService {
129
140
  tooltipEl,
130
141
  patternsColors,
131
142
  patternsList,
132
- disableAccessibility
143
+ disableAccessibility,
144
+ datasetType
133
145
  );
134
146
  }
135
147
 
@@ -188,7 +200,8 @@ export class GenericTooltipService {
188
200
  style += ';margin-right: 10px';
189
201
  style += ';display: flex';
190
202
  style += ';align-items: center';
191
- style += ';justify-content: center;';
203
+ style += ';justify-content: center';
204
+ style += ';background: rgba(0, 0, 0, 0.1);';
192
205
  return style;
193
206
  }
194
207
 
@@ -215,7 +228,8 @@ export class GenericTooltipService {
215
228
  tooltipEl: HTMLElement,
216
229
  patternsColors: string[],
217
230
  patternsList: ((hover: boolean, color: string, disableAccessibility: boolean) => CanvasPattern)[],
218
- disableAccessibility: boolean = false
231
+ disableAccessibility: boolean = false,
232
+ datasetType?: string
219
233
  ) {
220
234
  let innerHtml = innerHTMLtext;
221
235
  let legendImage = `<div class="legendIcon" style="${legendIconStyle}">`;
@@ -225,9 +239,9 @@ export class GenericTooltipService {
225
239
  const innerHtmlToAdd = this.setInnerHtmlToAdd(body, style, legendImage);
226
240
  innerHtml += innerHtmlToAdd;
227
241
  const tableRoot = tooltipEl?.querySelector('.tooltipCtn') as HTMLElement | null;
228
-
229
242
  if (tableRoot?.innerHTML != null) {
230
- this.setInnerHtmlAndPattern(tableRoot, innerHtml, patternsColors, patternsList, disableAccessibility);
243
+ datasetType ? this.setInnerHtmlAndPattern(tableRoot, innerHtml, patternsColors, patternsList, disableAccessibility, datasetType)
244
+ : this.setInnerHtmlAndPattern(tableRoot, innerHtml, patternsColors, patternsList, disableAccessibility);
231
245
  }
232
246
  }
233
247
 
@@ -285,7 +299,7 @@ export class GenericTooltipService {
285
299
  }
286
300
 
287
301
 
288
- setInnerHtmlAndPattern(tableRoot: HTMLElement, innerHtml: string, patternsColors: string[], patternsList: ((hover: boolean, color: string, disableAccessibility: boolean) => CanvasPattern)[], disableAccessibility: boolean = false) {
302
+ setInnerHtmlAndPattern(tableRoot: HTMLElement, innerHtml: string, patternsColors: string[], patternsList: ((hover: boolean, color: string, disableAccessibility: boolean) => CanvasPattern)[], disableAccessibility: boolean = false, datasetType?: string) {
289
303
  tableRoot.innerHTML = innerHtml;
290
304
  const legendIconHtml = document.querySelector('.legendIcon') as HTMLElement;
291
305
  const img: HTMLImageElement = new Image();
@@ -298,7 +312,7 @@ export class GenericTooltipService {
298
312
  index = this.datasetIndex + 1;
299
313
  }
300
314
  const patternIndex = getPatternIndexWithShift(index, this.patternShifting);
301
- if (this.chartType !== 'LINE_CHART' && this.chartType !== 'RADAR') {
315
+ if (this.chartType !== 'LINE_CHART' && this.chartType !== 'RADAR' && datasetType !== 'line') {
302
316
  const pattern: CanvasPattern = patternsList[patternIndex - 1](false, patternsColors[patternIndex - 1], disableAccessibility);
303
317
  const patternCanvas: HTMLCanvasElement = getPatternCanvas(pattern, 22, 22);
304
318
  img.src = patternCanvas.toDataURL();
@@ -0,0 +1,280 @@
1
+ import { reactive, ref, type Ref } from 'vue';
2
+ import PatternFunctions from './PatternFunctions';
3
+ import { addAlpha } from './ColorFunctions';
4
+ import type { HTMLLegendPlugin } from '../types/Chart';
5
+ import {
6
+ getOrCreateLegendList,
7
+ createHtmlLegendListElement,
8
+ createLegendElementWithPatterns,
9
+ createLegendElementWithCheckbox,
10
+ createHtmlLegendItemText,
11
+ createLegendElementWithSquareArea,
12
+ type ChartItem,
13
+ } from './ChartsCommonLegend';
14
+
15
+ const { getPatternIndexWithShift } = PatternFunctions();
16
+
17
+ export default function () {
18
+ const borderWidth = ref(2);
19
+ const onHoverIndex: { dataSetIndex: number; columnIndex: number } = reactive({
20
+ dataSetIndex: -1,
21
+ columnIndex: -1,
22
+ });
23
+
24
+ interface Dataset {
25
+ data: any;
26
+ label: string;
27
+ type: any;
28
+ fill?: boolean;
29
+ }
30
+
31
+ function getHtmlLegendPlugin(
32
+ legendContainer: Ref,
33
+ selectMode: Ref<boolean>,
34
+ onHoverIndex: any,
35
+ disableAccessibility: Ref<boolean>,
36
+ patternsColors: Ref<string[]>,
37
+ patternsList: Ref<
38
+ ((
39
+ hover: boolean,
40
+ color: string,
41
+ disableAccessibility: boolean
42
+ ) => CanvasPattern)[]
43
+ >,
44
+ ): HTMLLegendPlugin[] {
45
+ return [
46
+ {
47
+ id: 'htmlLegend',
48
+ afterUpdate(chart: any) {
49
+ const ul: HTMLLIElement = getOrCreateLegendList(
50
+ legendContainer,
51
+ 'column'
52
+ );
53
+ ul.style.display = 'flex';
54
+ ul.style.margin = '1.375rem 1.0625rem';
55
+ ul.style.flexDirection = 'row-reverse';
56
+ ul.style.justifyContent = 'flex-end';
57
+ while (ul.firstChild) {
58
+ ul.firstChild.remove();
59
+ }
60
+ const items: ChartItem[] =
61
+ chart.options.plugins.legend.labels.generateLabels(chart);
62
+ items.forEach((item: ChartItem): void => {
63
+ const li: HTMLElement = createHtmlLegendListElement(
64
+ chart,
65
+ selectMode,
66
+ item.datasetIndex
67
+ );
68
+ let liContent: HTMLElement;
69
+ if (!selectMode.value) {
70
+ if (item?.lineCap) {
71
+ liContent = createLegendElementWithSquareArea(item, onHoverIndex);
72
+ } else {
73
+ liContent = createLegendElementWithPatterns(
74
+ item,
75
+ chart,
76
+ onHoverIndex,
77
+ disableAccessibility.value,
78
+ patternsColors.value,
79
+ patternsList.value
80
+ );
81
+ }
82
+ } else {
83
+ liContent = createLegendElementWithCheckbox(
84
+ chart,
85
+ item,
86
+ selectMode,
87
+ onHoverIndex,
88
+ disableAccessibility.value
89
+ );
90
+ }
91
+ liContent.style.boxSizing = 'border-box';
92
+ li.style.marginRight = '10px';
93
+ li.appendChild(liContent);
94
+ li.appendChild(createHtmlLegendItemText(item));
95
+ ul.appendChild(li);
96
+ });
97
+ },
98
+ },
99
+ ];
100
+ }
101
+
102
+ function privateGetHtmlLegendPlugin(
103
+ legendContainer: Ref,
104
+ selectMode: Ref<boolean>,
105
+ disableAccessibility: Ref<boolean>,
106
+ patternsColors: Ref<string[]>,
107
+ patternsList: Ref<
108
+ ((
109
+ hover: boolean,
110
+ color: string,
111
+ disableAccessibility: boolean
112
+ ) => CanvasPattern)[]
113
+ >
114
+ ) {
115
+ return getHtmlLegendPlugin(
116
+ legendContainer,
117
+ selectMode,
118
+ onHoverIndex,
119
+ disableAccessibility,
120
+ patternsColors,
121
+ patternsList
122
+ );
123
+ }
124
+
125
+ function getOnHoverOptions() {
126
+ return (
127
+ _ignore: unknown,
128
+ activeElements: Array<{ index: number; datasetIndex: number }>
129
+ ) => {
130
+ if (activeElements[0] !== undefined) {
131
+ onHoverIndex.dataSetIndex = activeElements[0].datasetIndex;
132
+ onHoverIndex.columnIndex = activeElements[0].index;
133
+ } else {
134
+ resetOnHoverIndex();
135
+ }
136
+ };
137
+ }
138
+
139
+ function resetOnHoverIndex() {
140
+ onHoverIndex.dataSetIndex = -1;
141
+ onHoverIndex.columnIndex = -1;
142
+ }
143
+
144
+ // Hack to force the chart to reload on Hover
145
+ function reloadChart() {
146
+ borderWidth.value = 3;
147
+ borderWidth.value = 2;
148
+ }
149
+
150
+ function getMixedDatasets(
151
+ datasets: Dataset[],
152
+ disableAccessibility: boolean,
153
+ patternsColors: string[],
154
+ patternsList: ((
155
+ hover: boolean,
156
+ color: string,
157
+ disableAccessibility: boolean
158
+ ) => CanvasPattern)[],
159
+ patternShifting?: number
160
+ ) {
161
+ // Hack to force refresh
162
+ const borderWithValue = borderWidth.value;
163
+ return datasets.map((dataset, index) => {
164
+ return {
165
+ type: dataset.type,
166
+ fill: dataset.type === 'bar' ? null : false,
167
+ borderWidth: function () {
168
+ return disableAccessibility ? 1 : borderWithValue;
169
+ },
170
+ borderColor: function (context: any) {
171
+ return disableAccessibility
172
+ ? '#00000000'
173
+ : getBorderColor(
174
+ index,
175
+ context.index,
176
+ patternsColors,
177
+ patternShifting
178
+ );
179
+ },
180
+ backgroundColor: function (context: any) {
181
+ return getPattern(
182
+ index,
183
+ context.index,
184
+ disableAccessibility,
185
+ patternsColors,
186
+ patternsList,
187
+ patternShifting
188
+ );
189
+ },
190
+ yAxisID: dataset.type === 'bar' ? 'A' : 'B',
191
+ pointStyle: index % 2 === 0 ? 'rectRot' : 'circle',
192
+ data: dataset.data,
193
+ label: dataset.label,
194
+ pointBackgroundColor: '#FFFFFF',
195
+ pointRadius: 5,
196
+ order: datasets.length - index,
197
+ };
198
+ });
199
+ }
200
+
201
+ function getBorderColor(
202
+ dataSetIndex: number,
203
+ contextIndex: number,
204
+ patternsColors: string[],
205
+ patternShifting?: number
206
+ ) {
207
+ const index = getPatternIndexWithShift(dataSetIndex, patternShifting);
208
+ if (displayFullOpacity(dataSetIndex, contextIndex)) {
209
+ return patternsColors[index];
210
+ } else {
211
+ return addAlpha(patternsColors[index], 0.2);
212
+ }
213
+ }
214
+
215
+ function getPattern(
216
+ dataSetIndex: number,
217
+ contextIndex: number,
218
+ disableAccessibility: boolean,
219
+ patternsColors: string[],
220
+ patternsList: ((
221
+ hover: boolean,
222
+ color: string,
223
+ disableAccessibility: boolean
224
+ ) => CanvasPattern)[],
225
+ patternShifting?: number
226
+ ) {
227
+ const index = getPatternIndexWithShift(dataSetIndex, patternShifting);
228
+ if (displayFullOpacity(dataSetIndex, contextIndex)) {
229
+ return patternsList[index](
230
+ false,
231
+ patternsColors[index],
232
+ disableAccessibility
233
+ );
234
+ } else {
235
+ return patternsList[index](
236
+ true,
237
+ patternsColors[index],
238
+ disableAccessibility
239
+ );
240
+ }
241
+ }
242
+
243
+ function displayFullOpacity(
244
+ dataSetIndex: number,
245
+ contextIndex: number
246
+ ): boolean {
247
+ return (
248
+ nothingHovered() ||
249
+ columnHovered(dataSetIndex, contextIndex) ||
250
+ legendHovered(dataSetIndex)
251
+ );
252
+ }
253
+
254
+ function nothingHovered(): boolean {
255
+ return onHoverIndex.dataSetIndex < 0;
256
+ }
257
+
258
+ function columnHovered(dataSetIndex: number, contextIndex: number): boolean {
259
+ return (
260
+ onHoverIndex.dataSetIndex === dataSetIndex &&
261
+ onHoverIndex.columnIndex === contextIndex
262
+ );
263
+ }
264
+
265
+ function legendHovered(dataSetIndex: number): boolean {
266
+ return (
267
+ onHoverIndex.dataSetIndex === dataSetIndex && onHoverIndex.columnIndex < 0
268
+ );
269
+ }
270
+
271
+ return {
272
+ privateGetHtmlLegendPlugin,
273
+ getOnHoverOptions,
274
+ getMixedDatasets,
275
+ reloadChart,
276
+ getBorderColor,
277
+ getPattern,
278
+ onHoverIndex,
279
+ };
280
+ }
@@ -1,6 +1,6 @@
1
1
  import type { Chart, RadialLinearScale } from 'chart.js';
2
2
 
3
- export function drawLabels (chart: Chart, props: any) {
3
+ export function drawLabels(chart: Chart, props: any) {
4
4
  const ctx = chart.ctx;
5
5
  const scale = chart.scales.r as RadialLinearScale;
6
6
  const labels = chart.data.labels as string[][];
@@ -14,37 +14,39 @@ export function drawLabels (chart: Chart, props: any) {
14
14
  const angle = (scale.getIndexAngle(index) - Math.PI / 2) % (2 * Math.PI);
15
15
  const position = scale.getPointPositionForValue(index, scale.max);
16
16
 
17
- ctx.textAlign = angle <= Math.PI / 2 || angle > 3 * Math.PI / 2 ? 'left' : 'right';
18
- let xOffset = angle <= Math.PI / 2 || angle > 3 * Math.PI / 2 ? 15 : -15;
17
+ ctx.textAlign =
18
+ angle <= Math.PI / 2 || angle > (3 * Math.PI) / 2 ? 'left' : 'right';
19
+ let xOffset = angle <= Math.PI / 2 || angle > (3 * Math.PI) / 2 ? 15 : -15;
19
20
 
20
21
  let yOffset;
21
22
  //top or bottom labels
22
- if ( angle < 0 || angle > Math.PI) {
23
+ if (angle < 0 || angle > Math.PI) {
23
24
  yOffset = -15;
24
25
  } else {
25
26
  yOffset = 15;
26
27
  }
27
28
 
28
29
  //bottom labels
29
- if ( angle > Math.PI / 4 && angle < 3 * Math.PI / 4) {
30
+ if (angle > Math.PI / 4 && angle < (3 * Math.PI) / 4) {
30
31
  yOffset *= 3;
31
32
  }
32
33
 
33
34
  //top labels left and right
34
- if ( angle < -Math.PI / 4 || angle > 5 * Math.PI / 4) {
35
+ if (angle < -Math.PI / 4 || angle > (5 * Math.PI) / 4) {
35
36
  yOffset *= 3;
36
37
  xOffset = 0;
37
38
  }
38
39
 
39
40
  // full top label
40
- if ( angle > 11 * Math.PI / 8 || angle < -3 * Math.PI / 8){
41
+ if (angle > (11 * Math.PI) / 8 || angle < (-3 * Math.PI) / 8) {
41
42
  ctx.textAlign = 'center';
42
43
  }
43
- const yPos = position.y + yOffset * (label.length - 1) / 2;
44
+ const yPos = position.y + (yOffset * (label.length - 1)) / 2;
44
45
  ctx.font = '15px Arial';
45
46
 
46
47
  label.forEach((text, i) => {
47
- const color = i === label.length - 1 ? buildColorArray(props)[index] : '#000000';
48
+ const color =
49
+ i === label.length - 1 ? buildColorArray(props)[index] : '#000000';
48
50
  ctx.fillStyle = color;
49
51
 
50
52
  const x = position.x + xOffset;
@@ -56,8 +58,8 @@ export function drawLabels (chart: Chart, props: any) {
56
58
  ctx.restore();
57
59
  }
58
60
 
59
- const buildColorArray = (props: any): string[]=> {
60
- return props.areas[0].areaData.map((x: { color: string }) => {
61
+ const buildColorArray = (props: any): string[] => {
62
+ return props.datasets[0].areaData.map((x: { color: string }) => {
61
63
  switch (x.color) {
62
64
  case 'red':
63
65
  return '#C61112';
@@ -0,0 +1,6 @@
1
+ import { Meta, Markdown } from "@storybook/blocks";
2
+ import Changelog from "../../CHANGELOG.md?raw";
3
+
4
+ <Meta title="Changelog" />
5
+
6
+ <Markdown>{Changelog}</Markdown>