@mozaic-ds/chart 0.1.0-beta.16 → 0.1.0-beta.18
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.
- package/dist/mozaic-chart.js +3314 -2318
- package/dist/mozaic-chart.umd.cjs +13 -7
- package/dist/style.css +1 -1
- package/package.json +2 -1
- package/src/assets/img/bubbles.svg +4 -0
- package/src/components/bar/BarChart.stories.ts +5 -0
- package/src/components/bar/BarChart.vue +57 -26
- package/src/components/bubble/BubbleChart.stories.ts +66 -0
- package/src/components/bubble/BubbleChart.vue +326 -0
- package/src/components/bubble/index.ts +8 -0
- package/src/components/doughnut/DoughnutChart.vue +26 -8
- package/src/components/line/LineChart.stories.ts +2 -0
- package/src/components/line/LineChart.vue +25 -0
- package/src/components/mixed/MixedBarLineChart.stories.ts +3 -0
- package/src/components/mixed/MixedBarLineChart.vue +9 -6
- package/src/components/radar/RadarChart.vue +3 -0
- package/src/main.ts +2 -1
- package/src/plugin.ts +1 -0
- package/src/services/BarChartFunctions.ts +10 -7
- package/src/services/BubbleTooltipService.ts +65 -0
- package/src/services/ChartsCommonLegend.ts +47 -31
- package/src/services/DoughnutChartFunctions.ts +8 -5
- package/src/services/GenericTooltipService.ts +6 -5
- package/src/services/MixedBarLineFunctions.ts +4 -2
- package/src/types/AxisDefinition.ts +6 -0
- package/src/types/BarData.ts +1 -0
|
@@ -90,6 +90,13 @@ const doughnutDataProps = defineProps({
|
|
|
90
90
|
type: Boolean,
|
|
91
91
|
default: false,
|
|
92
92
|
},
|
|
93
|
+
/**
|
|
94
|
+
* Enable hover feature (may cause strange behavior when used with width and height in %)
|
|
95
|
+
*/
|
|
96
|
+
enableHoverFeature: {
|
|
97
|
+
type: Boolean,
|
|
98
|
+
default: false,
|
|
99
|
+
},
|
|
93
100
|
/**
|
|
94
101
|
* Used to choose the colour set of the charts as defined in the Figma prototypes.
|
|
95
102
|
* 7 colour sets are currently defined:
|
|
@@ -187,9 +194,10 @@ const doughnutChartData = computed<any>(() => {
|
|
|
187
194
|
backgroundColor: getBackgroundColor(
|
|
188
195
|
patternsColors.value,
|
|
189
196
|
patternsOrderedList.value,
|
|
190
|
-
doughnutDataProps.disableAccessibility
|
|
197
|
+
doughnutDataProps.disableAccessibility,
|
|
198
|
+
doughnutDataProps.enableHoverFeature
|
|
191
199
|
),
|
|
192
|
-
borderColor: getBorderColor(patternsColors.value),
|
|
200
|
+
borderColor: getBorderColor(patternsColors.value, doughnutDataProps.enableHoverFeature),
|
|
193
201
|
},
|
|
194
202
|
],
|
|
195
203
|
};
|
|
@@ -216,7 +224,7 @@ const options = computed(() => {
|
|
|
216
224
|
const colors = patternsColors.value;
|
|
217
225
|
const patterns = patternsOrderedList.value;
|
|
218
226
|
return {
|
|
219
|
-
onHover: getOnHoverOptions(),
|
|
227
|
+
onHover: doughnutDataProps.enableHoverFeature? getOnHoverOptions() : () => {},
|
|
220
228
|
plugins: {
|
|
221
229
|
legend: {
|
|
222
230
|
display: false,
|
|
@@ -231,6 +239,9 @@ const options = computed(() => {
|
|
|
231
239
|
title: {
|
|
232
240
|
display: false,
|
|
233
241
|
},
|
|
242
|
+
datalabels: {
|
|
243
|
+
display: false
|
|
244
|
+
},
|
|
234
245
|
tooltip: {
|
|
235
246
|
enabled: false,
|
|
236
247
|
external: function (context: Context) {
|
|
@@ -262,6 +273,9 @@ const doughnutDataAndLabels = {
|
|
|
262
273
|
const disablePattern = computed(() => {
|
|
263
274
|
return doughnutDataProps.disableAccessibility;
|
|
264
275
|
});
|
|
276
|
+
const enableHover = computed(() => {
|
|
277
|
+
return doughnutDataProps.enableHoverFeature;
|
|
278
|
+
})
|
|
265
279
|
|
|
266
280
|
const htmlLegendPlugin = computed(() =>
|
|
267
281
|
privateGetHtmlLegendPlugin(
|
|
@@ -271,7 +285,8 @@ const htmlLegendPlugin = computed(() =>
|
|
|
271
285
|
patternsColors,
|
|
272
286
|
patternsOrderedList,
|
|
273
287
|
doughnutDataProps.maxValues,
|
|
274
|
-
doughnutDataAndLabels
|
|
288
|
+
doughnutDataAndLabels,
|
|
289
|
+
enableHover
|
|
275
290
|
)
|
|
276
291
|
);
|
|
277
292
|
|
|
@@ -279,15 +294,17 @@ onMounted(() => {
|
|
|
279
294
|
getBackgroundColor(
|
|
280
295
|
patternsColors.value,
|
|
281
296
|
patternsOrderedList.value,
|
|
282
|
-
doughnutDataProps.disableAccessibility
|
|
297
|
+
doughnutDataProps.disableAccessibility,
|
|
298
|
+
enableHover.value
|
|
283
299
|
);
|
|
284
300
|
});
|
|
285
301
|
watch(onHoverIndex, (newValue, oldValue) => {
|
|
286
|
-
if (newValue !== oldValue) {
|
|
302
|
+
if (newValue !== oldValue && enableHover.value) {
|
|
287
303
|
getBackgroundColor(
|
|
288
304
|
patternsColors.value,
|
|
289
305
|
patternsOrderedList.value,
|
|
290
|
-
doughnutDataProps.disableAccessibility
|
|
306
|
+
doughnutDataProps.disableAccessibility,
|
|
307
|
+
enableHover.value
|
|
291
308
|
);
|
|
292
309
|
}
|
|
293
310
|
});
|
|
@@ -296,7 +313,8 @@ watch(disablePattern, () => {
|
|
|
296
313
|
getBackgroundColor(
|
|
297
314
|
patternsColors.value,
|
|
298
315
|
patternsOrderedList.value,
|
|
299
|
-
doughnutDataProps.disableAccessibility
|
|
316
|
+
doughnutDataProps.disableAccessibility,
|
|
317
|
+
enableHover.value
|
|
300
318
|
);
|
|
301
319
|
});
|
|
302
320
|
</script>
|
|
@@ -140,6 +140,20 @@ const lineDataProps = defineProps({
|
|
|
140
140
|
type: Array as PropType<string[]>,
|
|
141
141
|
default: () => [],
|
|
142
142
|
},
|
|
143
|
+
/**
|
|
144
|
+
* X axis title
|
|
145
|
+
*/
|
|
146
|
+
xAxisTitle: {
|
|
147
|
+
type: String,
|
|
148
|
+
default: null,
|
|
149
|
+
},
|
|
150
|
+
/**
|
|
151
|
+
* Y axis title
|
|
152
|
+
*/
|
|
153
|
+
yAxisTitle: {
|
|
154
|
+
type: String,
|
|
155
|
+
default: null,
|
|
156
|
+
},
|
|
143
157
|
/**
|
|
144
158
|
* Add custom CSS classes to the <canvas> element
|
|
145
159
|
*/
|
|
@@ -277,6 +291,9 @@ const options = computed(() => ({
|
|
|
277
291
|
legend: {
|
|
278
292
|
display: false,
|
|
279
293
|
},
|
|
294
|
+
datalabels: {
|
|
295
|
+
display: false
|
|
296
|
+
},
|
|
280
297
|
tooltip: {
|
|
281
298
|
enabled: false,
|
|
282
299
|
external: function (context: Context) {
|
|
@@ -298,10 +315,18 @@ const options = computed(() => ({
|
|
|
298
315
|
scales: {
|
|
299
316
|
x: {
|
|
300
317
|
offset: true,
|
|
318
|
+
title: {
|
|
319
|
+
display: lineDataProps.xAxisTitle !== null,
|
|
320
|
+
text: lineDataProps.xAxisTitle
|
|
321
|
+
},
|
|
301
322
|
},
|
|
302
323
|
y: {
|
|
303
324
|
type: 'linear' as const,
|
|
304
325
|
display: true,
|
|
326
|
+
title: {
|
|
327
|
+
display: lineDataProps.yAxisTitle !== null,
|
|
328
|
+
text: lineDataProps.yAxisTitle
|
|
329
|
+
},
|
|
305
330
|
position: 'left' as const,
|
|
306
331
|
grid: {
|
|
307
332
|
drawOnChartArea: true,
|
|
@@ -198,21 +198,21 @@ const mixedBarLineDataProps = defineProps({
|
|
|
198
198
|
*/
|
|
199
199
|
xAxisTitle: {
|
|
200
200
|
type: String,
|
|
201
|
-
default:
|
|
201
|
+
default: null,
|
|
202
202
|
},
|
|
203
203
|
/**
|
|
204
204
|
* Title of the y left axis
|
|
205
205
|
*/
|
|
206
206
|
yLeftAxisTitle: {
|
|
207
207
|
type: String,
|
|
208
|
-
default:
|
|
208
|
+
default: null,
|
|
209
209
|
},
|
|
210
210
|
/**
|
|
211
211
|
* Title of the y right axis
|
|
212
212
|
*/
|
|
213
213
|
yRightAxisTitle: {
|
|
214
214
|
type: String,
|
|
215
|
-
default:
|
|
215
|
+
default: null,
|
|
216
216
|
},
|
|
217
217
|
});
|
|
218
218
|
|
|
@@ -302,6 +302,9 @@ const options = computed(() => ({
|
|
|
302
302
|
title: {
|
|
303
303
|
display: false,
|
|
304
304
|
},
|
|
305
|
+
datalabels: {
|
|
306
|
+
display: false
|
|
307
|
+
},
|
|
305
308
|
tooltip: {
|
|
306
309
|
enabled: false,
|
|
307
310
|
external: function (context: Context) {
|
|
@@ -324,7 +327,7 @@ const options = computed(() => ({
|
|
|
324
327
|
x: {
|
|
325
328
|
offset: true,
|
|
326
329
|
title: {
|
|
327
|
-
display:
|
|
330
|
+
display: mixedBarLineDataProps.xAxisTitle !== null,
|
|
328
331
|
text: mixedBarLineDataProps.xAxisTitle,
|
|
329
332
|
},
|
|
330
333
|
},
|
|
@@ -336,7 +339,7 @@ const options = computed(() => ({
|
|
|
336
339
|
drawOnChartArea: true,
|
|
337
340
|
},
|
|
338
341
|
title: {
|
|
339
|
-
display:
|
|
342
|
+
display: mixedBarLineDataProps.yLeftAxisTitle !== null,
|
|
340
343
|
text: mixedBarLineDataProps.yLeftAxisTitle,
|
|
341
344
|
},
|
|
342
345
|
ticks: {
|
|
@@ -357,7 +360,7 @@ const options = computed(() => ({
|
|
|
357
360
|
drawOnChartArea: false,
|
|
358
361
|
},
|
|
359
362
|
title: {
|
|
360
|
-
display:
|
|
363
|
+
display: mixedBarLineDataProps.yRightAxisTitle !== null,
|
|
361
364
|
text: mixedBarLineDataProps.yRightAxisTitle,
|
|
362
365
|
},
|
|
363
366
|
ticks: {
|
package/src/main.ts
CHANGED
|
@@ -3,5 +3,6 @@ import DoughnutChart from "./components/doughnut/DoughnutChart.vue";
|
|
|
3
3
|
import LineChart from "./components/line/LineChart.vue";
|
|
4
4
|
import RadarChart from "./components/radar/RadarChart.vue";
|
|
5
5
|
import MixedBarLineChart from "./components/mixed/MixedBarLineChart.vue";
|
|
6
|
+
import BubbleChart from "./components/bubble/BubbleChart.vue";
|
|
6
7
|
|
|
7
|
-
export { BarChart, DoughnutChart, LineChart, RadarChart, MixedBarLineChart };
|
|
8
|
+
export { BarChart, DoughnutChart, LineChart, RadarChart, MixedBarLineChart, BubbleChart };
|
package/src/plugin.ts
CHANGED
|
@@ -5,12 +5,14 @@ import {
|
|
|
5
5
|
} from './ChartsCommonLegend';
|
|
6
6
|
import PatternFunctions from './PatternFunctions';
|
|
7
7
|
import { addAlpha } from './ColorFunctions';
|
|
8
|
+
import {getVirtualNodeHeight} from 'mermaid/dist/diagrams/timeline/svgDraw';
|
|
8
9
|
|
|
9
10
|
const { getPatternIndexWithShift } = PatternFunctions();
|
|
10
11
|
|
|
11
12
|
interface Dataset {
|
|
12
|
-
data:
|
|
13
|
+
data: number[],
|
|
13
14
|
label: any,
|
|
15
|
+
stack?: number,
|
|
14
16
|
}
|
|
15
17
|
|
|
16
18
|
export default function () {
|
|
@@ -22,8 +24,8 @@ export default function () {
|
|
|
22
24
|
});
|
|
23
25
|
|
|
24
26
|
|
|
25
|
-
function privateGetHtmlLegendPlugin(legendContainer: Ref, selectMode: Ref<boolean>, disableAccessibility: Ref<boolean>, patternsColors: Ref<string[]>, patternsList: Ref<((hover: boolean, color: string, disableAccessibility: boolean) => CanvasPattern)[]>) {
|
|
26
|
-
return getHtmlLegendPlugin(legendContainer, selectMode, onHoverIndex, disableAccessibility,
|
|
27
|
+
function privateGetHtmlLegendPlugin(legendContainer: Ref, selectMode: Ref<boolean>, disableAccessibility: Ref<boolean>, patternsColors: Ref<string[]>, patternsList: Ref<((hover: boolean, color: string, disableAccessibility: boolean) => CanvasPattern)[]>, enableHoverFeature: Ref<boolean>) {
|
|
28
|
+
return getHtmlLegendPlugin(legendContainer, selectMode, onHoverIndex, disableAccessibility, patternsColors, patternsList, enableHoverFeature);
|
|
27
29
|
}
|
|
28
30
|
// Hack to force the chart to reload on Hover
|
|
29
31
|
function reloadChart () {
|
|
@@ -34,18 +36,19 @@ export default function () {
|
|
|
34
36
|
function getStackedDatasets (datasets: Dataset[], stackDatasets: boolean, disableAccessibility: boolean, patternsColors: string[], patternsList: ((hover: boolean, color: string, disableAccessibility: boolean) => CanvasPattern)[], patternShifting?: number) {
|
|
35
37
|
// Hack to force refresh
|
|
36
38
|
const borderWithValue = borderWidth.value;
|
|
37
|
-
return datasets.map((dataset,
|
|
39
|
+
return datasets.map((dataset, datasetIndex) => {
|
|
38
40
|
return {
|
|
39
41
|
borderColor: function (context: any) {
|
|
40
|
-
return disableAccessibility ? '#00000000' : getBorderColor(
|
|
42
|
+
return disableAccessibility ? '#00000000' : getBorderColor(datasetIndex, context.index, patternsColors, patternShifting);
|
|
41
43
|
},
|
|
42
44
|
backgroundColor: function (context: any) {
|
|
43
|
-
return getPattern(
|
|
45
|
+
return getPattern(datasetIndex, context.index, disableAccessibility, patternsColors, patternsList, patternShifting);
|
|
44
46
|
},
|
|
45
47
|
borderWidth: function () {return disableAccessibility ? 1 : borderWithValue},
|
|
48
|
+
|
|
46
49
|
data: dataset.data,
|
|
47
50
|
label: dataset.label,
|
|
48
|
-
stack: `Stack ${stackDatasets ?
|
|
51
|
+
stack: `Stack ${stackDatasets ? dataset.stack : datasetIndex}`
|
|
49
52
|
};
|
|
50
53
|
});
|
|
51
54
|
}
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
import {Context, GenericTooltipService} from './GenericTooltipService';
|
|
2
|
+
|
|
3
|
+
export type BubbleTooltipLine = {
|
|
4
|
+
label: string,
|
|
5
|
+
value: string,
|
|
6
|
+
unit: string,
|
|
7
|
+
}
|
|
8
|
+
const tooltipLineStyle = 'background: white; border-bottom: 1px solid #CCCCCC; border-radius: 5px; padding: 10px 20px';
|
|
9
|
+
|
|
10
|
+
export class BubbleTooltipService extends GenericTooltipService {
|
|
11
|
+
fontProperties = 'font-family: Arial; font-size: 16px';
|
|
12
|
+
|
|
13
|
+
createBubbleTooltip(
|
|
14
|
+
context: Context,
|
|
15
|
+
lines: BubbleTooltipLine[],
|
|
16
|
+
title: string,
|
|
17
|
+
) {
|
|
18
|
+
if(!title || title === ''){
|
|
19
|
+
return;
|
|
20
|
+
}
|
|
21
|
+
let tooltipEl = document.querySelector('#chartjs-tooltip') as HTMLElement | null;
|
|
22
|
+
if (!tooltipEl) {
|
|
23
|
+
tooltipEl = this.createNewTooltipElement();
|
|
24
|
+
}
|
|
25
|
+
const tooltipModel = context.tooltip;
|
|
26
|
+
if (tooltipModel.opacity === 0) {
|
|
27
|
+
tooltipEl.style.opacity = '0';
|
|
28
|
+
return;
|
|
29
|
+
}
|
|
30
|
+
if (tooltipModel.body) {
|
|
31
|
+
this.titleLines = tooltipModel.title || [];
|
|
32
|
+
const bodyLines = tooltipModel.body.map(this.getBody);
|
|
33
|
+
const body = bodyLines[0];
|
|
34
|
+
this.addBubbleLegendToDom(lines, body, tooltipEl, title);
|
|
35
|
+
|
|
36
|
+
}
|
|
37
|
+
this.handleTooltipPosition(context, tooltipModel, tooltipEl);
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
addBubbleLegendToDom(
|
|
41
|
+
lines: BubbleTooltipLine[],
|
|
42
|
+
body: Array<string>,
|
|
43
|
+
tooltipEl: HTMLElement,
|
|
44
|
+
title: string,
|
|
45
|
+
) {
|
|
46
|
+
const legendText = body[0].split(':')[0];
|
|
47
|
+
const spanText = `<span style="${this.fontProperties}">${title}</span>`;
|
|
48
|
+
let innerHtml = `<div style="${tooltipLineStyle}; font-weight: bold" class="tooltipTitle">${spanText}</div>`;
|
|
49
|
+
const innerHtmlToAdd = this.getBubbleInnerHtml(lines);
|
|
50
|
+
innerHtml += innerHtmlToAdd;
|
|
51
|
+
const tableRoot = tooltipEl?.querySelector('.tooltipCtn') as HTMLElement;
|
|
52
|
+
tableRoot.innerHTML = innerHtml;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
getBubbleInnerHtml(lines: BubbleTooltipLine[]): string {
|
|
56
|
+
let innerLinesHtml = '';
|
|
57
|
+
lines.forEach(line => {
|
|
58
|
+
innerLinesHtml += `<div style="${this.fontProperties}; ${tooltipLineStyle}; display:flex; justify-content: space-between;">`;
|
|
59
|
+
innerLinesHtml += `<div>${line.label}</div>`;
|
|
60
|
+
innerLinesHtml += `<div>${line.value}${line.unit}</div>`;
|
|
61
|
+
innerLinesHtml += `</div>`;
|
|
62
|
+
})
|
|
63
|
+
return `<div>${innerLinesHtml}</div>`;
|
|
64
|
+
}
|
|
65
|
+
}
|
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
import type {
|
|
2
|
-
import type {
|
|
3
|
-
import type {
|
|
1
|
+
import type {Ref} from 'vue';
|
|
2
|
+
import type {HTMLLegendPlugin} from "../types/Chart";
|
|
3
|
+
import type {ChartOptions} from 'chart.js';
|
|
4
4
|
import PatternFunctions from './PatternFunctions';
|
|
5
|
-
import {
|
|
5
|
+
import {formatValueAndRate} from './FormatUtilities';
|
|
6
6
|
import QuestionMarkSvg from '@mozaic-ds/icons/svg/Navigation_Notification_Question_24px.svg';
|
|
7
7
|
|
|
8
8
|
const { getPatternCanvas } = PatternFunctions();
|
|
@@ -43,7 +43,7 @@ export interface ChartItem {
|
|
|
43
43
|
lineCap?: string;
|
|
44
44
|
}
|
|
45
45
|
|
|
46
|
-
export function getHtmlLegendPlugin(legendContainer: Ref, selectMode: Ref<boolean>, onHoverIndex: any, disableAccessibility: Ref<boolean>, patternsColors: Ref<string[]>, patternsList: Ref<((hover: boolean, color: string, disableAccessibility: boolean) => CanvasPattern)[]>, maxValueToDisplay?: number, chartData?: any): HTMLLegendPlugin[] {
|
|
46
|
+
export function getHtmlLegendPlugin(legendContainer: Ref, selectMode: Ref<boolean>, onHoverIndex: any, disableAccessibility: Ref<boolean>, patternsColors: Ref<string[]>, patternsList: Ref<((hover: boolean, color: string, disableAccessibility: boolean) => CanvasPattern)[]>, enableHoverFeature: Ref<boolean>, maxValueToDisplay?: number, chartData?: any): HTMLLegendPlugin[] {
|
|
47
47
|
return [{
|
|
48
48
|
id: 'htmlLegend',
|
|
49
49
|
afterUpdate (chart: any) {
|
|
@@ -72,9 +72,9 @@ export function getHtmlLegendPlugin(legendContainer: Ref, selectMode: Ref<boolea
|
|
|
72
72
|
li.style.cursor = 'pointer';
|
|
73
73
|
let liContent: HTMLElement;
|
|
74
74
|
if (!selectMode.value) {
|
|
75
|
-
liContent = createLegendElementWithPatterns(item, chart, onHoverIndex, disableAccessibility.value, patternsColors.value, patternsList.value);
|
|
75
|
+
liContent = createLegendElementWithPatterns(item, chart, onHoverIndex, disableAccessibility.value, patternsColors.value, patternsList.value, enableHoverFeature.value);
|
|
76
76
|
} else {
|
|
77
|
-
liContent = createLegendElementWithCheckbox(chart, item, selectMode, onHoverIndex, patternsColors.value);
|
|
77
|
+
liContent = createLegendElementWithCheckbox(chart, item, selectMode, onHoverIndex, patternsColors.value, enableHoverFeature.value);
|
|
78
78
|
}
|
|
79
79
|
liContent.style.boxSizing = 'border-box';
|
|
80
80
|
li.appendChild(liContent);
|
|
@@ -108,6 +108,9 @@ export function createTooltipAndItsIcon (doughnutData: any, maxValueToDisplay: n
|
|
|
108
108
|
icon.onmouseover = () => {
|
|
109
109
|
(iconWrapper.firstElementChild as HTMLElement).style.visibility = 'visible';
|
|
110
110
|
};
|
|
111
|
+
icon.onmouseleave = () => {
|
|
112
|
+
(iconWrapper.firstElementChild as HTMLElement).style.visibility = 'hidden';
|
|
113
|
+
};
|
|
111
114
|
iconTopWrapper.appendChild(iconWrapper);
|
|
112
115
|
iconWrapper.appendChild(tooltip);
|
|
113
116
|
iconWrapper.appendChild(icon);
|
|
@@ -153,7 +156,7 @@ doughnutData.data.slice(startIndex).forEach((_ignore: any, index: number) => {
|
|
|
153
156
|
}
|
|
154
157
|
|
|
155
158
|
export function createLegendElementWithPatterns
|
|
156
|
-
(item: ChartItem, chart: Chart, onHoverIndex: any | null, disableAccessibility: boolean, patternsColors: string[], patternsList: ((hover: boolean, color: string, disableAccessibility: boolean) => CanvasPattern)[])
|
|
159
|
+
(item: ChartItem, chart: Chart, onHoverIndex: any | null, disableAccessibility: boolean, patternsColors: string[], patternsList: ((hover: boolean, color: string, disableAccessibility: boolean) => CanvasPattern)[], enableHoverFeature: boolean)
|
|
157
160
|
: HTMLElement {
|
|
158
161
|
const isDoughnut: boolean = chart.config.type === 'doughnut';
|
|
159
162
|
const index: number = isDoughnut ? item.index : item.datasetIndex;
|
|
@@ -167,38 +170,42 @@ export function createLegendElementWithPatterns
|
|
|
167
170
|
boxSpan.style.borderColor = patternsColors[index];
|
|
168
171
|
boxSpan.style.borderWidth = LEGEND_BOX_BORDER;
|
|
169
172
|
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
173
|
+
if (enableHoverFeature) {
|
|
174
|
+
boxSpan.onmouseover = ():void => {
|
|
175
|
+
isDoughnut ? onHoverIndex.value = index : onHoverIndex.dataSetIndex = index;
|
|
176
|
+
};
|
|
177
|
+
boxSpan.onmouseleave = (): void => {
|
|
178
|
+
isDoughnut ? onHoverIndex.value = null : onHoverIndex.dataSetIndex = -1;
|
|
179
|
+
};
|
|
180
|
+
}
|
|
176
181
|
return boxSpan;
|
|
177
182
|
}
|
|
178
183
|
|
|
179
184
|
export function createLegendElementWithCheckbox
|
|
180
|
-
(chart: Chart, item: ChartItem, selectMode: Ref<boolean>, onHoverIndex: any | null, patternsColors: string[]): HTMLElement {
|
|
185
|
+
(chart: Chart, item: ChartItem, selectMode: Ref<boolean>, onHoverIndex: any | null, patternsColors: string[], enableHoverFeature: boolean): HTMLElement {
|
|
181
186
|
const isDoughnut: boolean = chart.config.type === 'doughnut';
|
|
182
187
|
const index: number = isDoughnut ? item.index : item.datasetIndex;
|
|
183
188
|
const checkbox: HTMLElement = createLegendCheckbox(chart, item, patternsColors);
|
|
184
189
|
const labels = chart.config.data.labels;
|
|
185
190
|
const allCheckBoxesVisible: boolean =
|
|
186
191
|
labels.every((label: string, index: number) => chart.getDataVisibility(index));
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
192
|
+
if (allCheckBoxesVisible) {
|
|
193
|
+
if (isDoughnut) {
|
|
194
|
+
selectMode.value = false;
|
|
195
|
+
onHoverIndex.value = -1;
|
|
196
|
+
}
|
|
197
|
+
return checkbox;
|
|
191
198
|
}
|
|
192
|
-
|
|
199
|
+
if (enableHoverFeature) {
|
|
200
|
+
checkbox.onmouseover = ():void => {
|
|
201
|
+
isDoughnut ? onHoverIndex.value = index : onHoverIndex.dataSetIndex = index;
|
|
202
|
+
chart.update();
|
|
203
|
+
};
|
|
204
|
+
checkbox.onmouseleave = (): void => {
|
|
205
|
+
isDoughnut ? onHoverIndex.value = null : onHoverIndex.dataSetIndex = -1;
|
|
206
|
+
chart.update();
|
|
207
|
+
};
|
|
193
208
|
}
|
|
194
|
-
checkbox.onmouseover = ():void => {
|
|
195
|
-
isDoughnut ? onHoverIndex.value = index : onHoverIndex.dataSetIndex = index;
|
|
196
|
-
chart.update();
|
|
197
|
-
};
|
|
198
|
-
checkbox.onmouseleave = (): void => {
|
|
199
|
-
isDoughnut ? onHoverIndex.value = null : onHoverIndex.dataSetIndex = -1;
|
|
200
|
-
chart.update();
|
|
201
|
-
};
|
|
202
209
|
return checkbox;
|
|
203
210
|
}
|
|
204
211
|
|
|
@@ -269,8 +276,8 @@ export function addCheckboxStyle (isDataSetVisible: boolean, item: ChartItem, ch
|
|
|
269
276
|
//Default white for patterns chart
|
|
270
277
|
backgroundColor = isDefaultWhiteColor(item.strokeStyle)? patternColor: item.strokeStyle;
|
|
271
278
|
borderColor = isDefaultWhiteColor(item.strokeStyle)? patternColor: item.strokeStyle;
|
|
279
|
+
checkbox.setAttribute('checked', '' + isDataSetVisible);
|
|
272
280
|
}
|
|
273
|
-
checkbox.setAttribute('checked', '' + isDataSetVisible);
|
|
274
281
|
checkbox.setAttribute('class', 'mc-checkbox__input');
|
|
275
282
|
checkbox.setAttribute('style', `background-color: ${backgroundColor};
|
|
276
283
|
width: ${LEGEND_BOX_SIZE};
|
|
@@ -285,7 +292,7 @@ export function createLegendCheckbox (chart: Chart, item: ChartItem, patternsCol
|
|
|
285
292
|
const checkbox = document.createElement('input');
|
|
286
293
|
checkbox.setAttribute('type', 'checkbox');
|
|
287
294
|
checkbox.setAttribute('data-test-id', `legend-checkbox-${index}`);
|
|
288
|
-
const isDataSetVisible =
|
|
295
|
+
const isDataSetVisible = isChartDataVisible(chart, index);
|
|
289
296
|
const patternColor = patternsColors? patternsColors[index]:undefined;
|
|
290
297
|
addCheckboxStyle(isDataSetVisible, item, checkbox, patternColor as string);
|
|
291
298
|
return checkbox;
|
|
@@ -320,17 +327,26 @@ function allDataVisible (chart: Chart): boolean {
|
|
|
320
327
|
let allVisible = true;
|
|
321
328
|
const chartsData: unknown[] = getChartsData(chart);
|
|
322
329
|
chartsData.forEach((_data, dataIndex) => {
|
|
323
|
-
allVisible = allVisible && chart
|
|
330
|
+
allVisible = allVisible && isChartDataVisible(chart, dataIndex);
|
|
324
331
|
});
|
|
325
332
|
return allVisible;
|
|
326
333
|
}
|
|
327
334
|
|
|
335
|
+
function isChartDataVisible(chart: Chart, dataIndex: number): boolean {
|
|
336
|
+
if (isMonoDataSetChart(chart)) {
|
|
337
|
+
return chart.getDataVisibility(dataIndex);
|
|
338
|
+
} else {
|
|
339
|
+
return chart.isDatasetVisible(dataIndex);
|
|
340
|
+
}
|
|
341
|
+
}
|
|
342
|
+
|
|
328
343
|
export function switchItemVisibility (chart: Chart, elementIndex: number, selectMode?: Ref) {
|
|
329
344
|
if (isMonoDataSetChart(chart)) {
|
|
330
345
|
chart.toggleDataVisibility(elementIndex);
|
|
331
346
|
} else {
|
|
332
347
|
chart.setDatasetVisibility(elementIndex, !chart.isDatasetVisible(elementIndex));
|
|
333
348
|
}
|
|
349
|
+
|
|
334
350
|
if (selectMode && allDataVisible(chart)) {
|
|
335
351
|
selectMode.value = false;
|
|
336
352
|
}
|
|
@@ -23,7 +23,8 @@ export default function () {
|
|
|
23
23
|
) => CanvasPattern)[]
|
|
24
24
|
>,
|
|
25
25
|
maxValueToDisplay: number,
|
|
26
|
-
doughnutData: any
|
|
26
|
+
doughnutData: any,
|
|
27
|
+
enableHoverFeature: Ref<boolean>
|
|
27
28
|
) {
|
|
28
29
|
return getHtmlLegendPlugin(
|
|
29
30
|
legendContainer,
|
|
@@ -32,6 +33,7 @@ export default function () {
|
|
|
32
33
|
disableAccessibility,
|
|
33
34
|
patternsColors,
|
|
34
35
|
patternsList,
|
|
36
|
+
enableHoverFeature,
|
|
35
37
|
maxValueToDisplay,
|
|
36
38
|
doughnutData
|
|
37
39
|
);
|
|
@@ -44,9 +46,10 @@ export default function () {
|
|
|
44
46
|
color: string,
|
|
45
47
|
disableAccessibility: boolean
|
|
46
48
|
) => CanvasPattern)[],
|
|
47
|
-
disableAccessibility: boolean
|
|
49
|
+
disableAccessibility: boolean,
|
|
50
|
+
enableHoverFeature: boolean
|
|
48
51
|
) {
|
|
49
|
-
if (onHoverIndex.value !== null) {
|
|
52
|
+
if (onHoverIndex.value !== null && enableHoverFeature) {
|
|
50
53
|
return patternsList.map((pattern, index) =>
|
|
51
54
|
onHoverIndex.value === index
|
|
52
55
|
? pattern(false, patternsColors[index], disableAccessibility)
|
|
@@ -59,8 +62,8 @@ export default function () {
|
|
|
59
62
|
}
|
|
60
63
|
}
|
|
61
64
|
|
|
62
|
-
function getBorderColor(patternsColors: string[]): string[] {
|
|
63
|
-
if (onHoverIndex.value !== null) {
|
|
65
|
+
function getBorderColor(patternsColors: string[], enableHoverFeature: boolean): string[] {
|
|
66
|
+
if (onHoverIndex.value !== null && enableHoverFeature) {
|
|
64
67
|
return patternsColors.map((color, index) =>
|
|
65
68
|
onHoverIndex.value === index ? color : addAlpha(color, 0.2)
|
|
66
69
|
);
|
|
@@ -43,7 +43,8 @@ export type Context = {
|
|
|
43
43
|
type?: string
|
|
44
44
|
},
|
|
45
45
|
dataIndex?: number,
|
|
46
|
-
datasetIndex?: number
|
|
46
|
+
datasetIndex?: number,
|
|
47
|
+
raw: any
|
|
47
48
|
}[];
|
|
48
49
|
opacity : number;
|
|
49
50
|
body: {
|
|
@@ -148,7 +149,7 @@ export class GenericTooltipService {
|
|
|
148
149
|
this.handleTooltipPosition(context, tooltipModel, tooltipEl);
|
|
149
150
|
}
|
|
150
151
|
|
|
151
|
-
|
|
152
|
+
protected handleTooltipPosition
|
|
152
153
|
(context: Context, tooltipModel: { caretX: number, caretY: number }, tooltipEl: HTMLElement) {
|
|
153
154
|
const position = context.chart.canvas.getBoundingClientRect();
|
|
154
155
|
const screenWidth = window.innerWidth;
|
|
@@ -170,7 +171,7 @@ export class GenericTooltipService {
|
|
|
170
171
|
}
|
|
171
172
|
}
|
|
172
173
|
|
|
173
|
-
|
|
174
|
+
protected createNewTooltipElement () {
|
|
174
175
|
const tooltipEl = document.createElement('div');
|
|
175
176
|
tooltipEl.id = 'chartjs-tooltip';
|
|
176
177
|
tooltipEl.style.backgroundColor = 'white';
|
|
@@ -229,7 +230,7 @@ export class GenericTooltipService {
|
|
|
229
230
|
patternsColors: string[],
|
|
230
231
|
patternsList: ((hover: boolean, color: string, disableAccessibility: boolean) => CanvasPattern)[],
|
|
231
232
|
disableAccessibility: boolean = false,
|
|
232
|
-
datasetType?: string
|
|
233
|
+
datasetType?: string
|
|
233
234
|
) {
|
|
234
235
|
let innerHtml = innerHTMLtext;
|
|
235
236
|
let legendImage = `<div class="legendIcon" style="${legendIconStyle}">`;
|
|
@@ -240,7 +241,7 @@ export class GenericTooltipService {
|
|
|
240
241
|
innerHtml += innerHtmlToAdd;
|
|
241
242
|
const tableRoot = tooltipEl?.querySelector('.tooltipCtn') as HTMLElement | null;
|
|
242
243
|
if (tableRoot?.innerHTML != null) {
|
|
243
|
-
datasetType ? this.setInnerHtmlAndPattern(tableRoot, innerHtml, patternsColors, patternsList, disableAccessibility, datasetType)
|
|
244
|
+
datasetType ? this.setInnerHtmlAndPattern(tableRoot, innerHtml, patternsColors, patternsList, disableAccessibility, datasetType)
|
|
244
245
|
: this.setInnerHtmlAndPattern(tableRoot, innerHtml, patternsColors, patternsList, disableAccessibility);
|
|
245
246
|
}
|
|
246
247
|
}
|
|
@@ -76,7 +76,8 @@ export default function () {
|
|
|
76
76
|
{ datasetIndex: -1 },
|
|
77
77
|
disableAccessibility.value,
|
|
78
78
|
patternsColors.value,
|
|
79
|
-
patternsList.value
|
|
79
|
+
patternsList.value,
|
|
80
|
+
false
|
|
80
81
|
);
|
|
81
82
|
}
|
|
82
83
|
} else {
|
|
@@ -85,7 +86,8 @@ export default function () {
|
|
|
85
86
|
item,
|
|
86
87
|
selectMode,
|
|
87
88
|
{ datasetIndex: -1 },
|
|
88
|
-
patternsColors.value
|
|
89
|
+
patternsColors.value,
|
|
90
|
+
false
|
|
89
91
|
);
|
|
90
92
|
}
|
|
91
93
|
liContent.style.boxSizing = 'border-box';
|