@mozaic-ds/chart 0.1.0-beta.4 → 0.1.0-beta.40
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/README.md +85 -9
- package/dist/mozaic-chart.js +4747 -2614
- package/dist/mozaic-chart.umd.cjs +17 -11
- package/dist/style.css +1 -1
- package/package.json +24 -11
- package/src/assets/base.css +1 -1
- package/src/assets/img/bubbles.svg +4 -0
- package/src/components/bar/BarChart.stories.ts +181 -101
- package/src/components/bar/BarChart.vue +370 -139
- package/src/components/bar/index.ts +3 -3
- package/src/components/bubble/BubbleChart.stories.ts +66 -0
- package/src/components/bubble/BubbleChart.vue +432 -0
- package/src/components/bubble/index.ts +8 -0
- package/src/components/doughnut/DoughnutChart.stories.ts +38 -36
- package/src/components/doughnut/DoughnutChart.vue +243 -114
- package/src/components/doughnut/index.ts +3 -3
- package/src/components/index.ts +4 -4
- package/src/components/line/LineChart.stories.ts +52 -27
- package/src/components/line/LineChart.vue +381 -255
- package/src/components/line/index.ts +3 -3
- package/src/components/mixed/MixedBarLineChart.stories.ts +91 -0
- package/src/components/mixed/MixedBarLineChart.vue +469 -0
- package/src/components/mixed/index.ts +8 -0
- package/src/components/radar/RadarChart.stories.ts +102 -102
- package/src/components/radar/RadarChart.vue +222 -167
- package/src/components/radar/index.ts +3 -3
- package/src/main.ts +14 -5
- package/src/plugin.ts +9 -7
- package/src/services/BarChartFunctions.ts +139 -35
- package/src/services/BubbleTooltipService.ts +67 -0
- package/src/services/ChartsCommonLegend.ts +315 -139
- package/src/services/ColorFunctions.ts +1 -1
- package/src/services/DoughnutChartFunctions.ts +132 -55
- package/src/services/FormatUtilities.ts +25 -19
- package/src/services/GenericTooltipService.ts +141 -66
- package/src/services/MixedBarLineFunctions.ts +262 -0
- package/src/services/PatternFunctions.ts +25 -18
- package/src/services/RadarChartFunctions.ts +39 -12
- package/src/services/patterns/ChartDesign.ts +35 -24
- package/src/services/patterns/patternCircles.ts +63 -36
- package/src/services/patterns/patternDashedDiagonals.ts +64 -57
- package/src/services/patterns/patternDiagonals.ts +138 -106
- package/src/services/patterns/patternSquares.ts +86 -80
- package/src/services/patterns/patternVerticalLines.ts +76 -69
- package/src/services/patterns/patternZigzag.ts +92 -85
- package/src/stories/Changelog.mdx +6 -0
- package/src/stories/Contributing.mdx +101 -0
- package/src/stories/GettingStarted.mdx +92 -0
- package/src/stories/SupportAndOnboarding.mdx +44 -0
- package/src/types/AxisDefinition.ts +4 -0
- package/src/types/BarData.ts +1 -0
- package/src/types/Chart.ts +9 -7
- package/src/types/DoughnutData.ts +8 -0
- package/src/types/GenericData.ts +10 -10
- package/src/types/LineChart.ts +5 -4
- package/src/types/MixedBarLineData.ts +7 -0
- package/src/types/RadarData.ts +33 -29
- package/src/types/TooltipChartType.ts +7 -6
- package/src/vite-env.d.ts +3 -3
|
@@ -1,102 +1,206 @@
|
|
|
1
1
|
import { reactive, ref } from 'vue';
|
|
2
2
|
import type { Ref } from 'vue';
|
|
3
|
-
import {
|
|
4
|
-
getHtmlLegendPlugin
|
|
5
|
-
} from './ChartsCommonLegend';
|
|
3
|
+
import { getHtmlLegendPlugin } from './ChartsCommonLegend';
|
|
6
4
|
import PatternFunctions from './PatternFunctions';
|
|
7
5
|
import { addAlpha } from './ColorFunctions';
|
|
8
6
|
|
|
9
7
|
const { getPatternIndexWithShift } = PatternFunctions();
|
|
10
8
|
|
|
11
9
|
interface Dataset {
|
|
12
|
-
data:
|
|
13
|
-
label: any
|
|
10
|
+
data: number[];
|
|
11
|
+
label: any;
|
|
12
|
+
stack?: number;
|
|
14
13
|
}
|
|
15
14
|
|
|
16
15
|
export default function () {
|
|
17
16
|
const borderWidth = ref(3);
|
|
18
17
|
const barChartRef = ref(null as any);
|
|
19
|
-
const onHoverIndex: { dataSetIndex: number
|
|
18
|
+
const onHoverIndex: { dataSetIndex: number; columnIndex: number } = reactive({
|
|
20
19
|
dataSetIndex: -1,
|
|
21
20
|
columnIndex: -1
|
|
22
21
|
});
|
|
23
22
|
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
23
|
+
function privateGetHtmlLegendPlugin(
|
|
24
|
+
legendContainer: Ref,
|
|
25
|
+
selectMode: Ref<boolean>,
|
|
26
|
+
disableAccessibility: Ref<boolean>,
|
|
27
|
+
patternsColors: Ref<string[]>,
|
|
28
|
+
patternsList: Ref<
|
|
29
|
+
((
|
|
30
|
+
hover: boolean,
|
|
31
|
+
color: string,
|
|
32
|
+
disableAccessibility: boolean
|
|
33
|
+
) => CanvasPattern)[]
|
|
34
|
+
>,
|
|
35
|
+
enableHoverFeature: Ref<boolean>,
|
|
36
|
+
disableLegendClick: Ref<boolean>
|
|
37
|
+
) {
|
|
38
|
+
return getHtmlLegendPlugin(
|
|
39
|
+
legendContainer,
|
|
40
|
+
selectMode,
|
|
41
|
+
onHoverIndex,
|
|
42
|
+
disableAccessibility,
|
|
43
|
+
patternsColors,
|
|
44
|
+
patternsList,
|
|
45
|
+
enableHoverFeature,
|
|
46
|
+
undefined,
|
|
47
|
+
null,
|
|
48
|
+
disableLegendClick
|
|
49
|
+
);
|
|
27
50
|
}
|
|
28
51
|
// Hack to force the chart to reload on Hover
|
|
29
|
-
function reloadChart
|
|
52
|
+
function reloadChart() {
|
|
30
53
|
borderWidth.value = 4;
|
|
31
54
|
borderWidth.value = 3;
|
|
32
55
|
}
|
|
33
56
|
|
|
34
|
-
function getStackedDatasets
|
|
57
|
+
function getStackedDatasets(
|
|
58
|
+
datasets: Dataset[],
|
|
59
|
+
stackDatasets: boolean,
|
|
60
|
+
disableAccessibility: boolean,
|
|
61
|
+
patternsColors: string[],
|
|
62
|
+
patternsList: ((
|
|
63
|
+
hover: boolean,
|
|
64
|
+
color: string,
|
|
65
|
+
disableAccessibility: boolean
|
|
66
|
+
) => CanvasPattern)[],
|
|
67
|
+
patternShifting?: number
|
|
68
|
+
) {
|
|
35
69
|
// Hack to force refresh
|
|
36
70
|
const borderWithValue = borderWidth.value;
|
|
37
|
-
return datasets.map((dataset,
|
|
71
|
+
return datasets.map((dataset, datasetIndex) => {
|
|
38
72
|
return {
|
|
39
73
|
borderColor: function (context: any) {
|
|
40
|
-
return disableAccessibility
|
|
74
|
+
return disableAccessibility
|
|
75
|
+
? '#00000000'
|
|
76
|
+
: getBorderColor(
|
|
77
|
+
datasetIndex,
|
|
78
|
+
context.index,
|
|
79
|
+
patternsColors,
|
|
80
|
+
patternShifting
|
|
81
|
+
);
|
|
41
82
|
},
|
|
42
83
|
backgroundColor: function (context: any) {
|
|
43
|
-
return getPattern(
|
|
84
|
+
return getPattern(
|
|
85
|
+
datasetIndex,
|
|
86
|
+
context.index,
|
|
87
|
+
disableAccessibility,
|
|
88
|
+
patternsColors,
|
|
89
|
+
patternsList,
|
|
90
|
+
patternShifting
|
|
91
|
+
);
|
|
92
|
+
},
|
|
93
|
+
borderWidth: function () {
|
|
94
|
+
return disableAccessibility ? 1 : borderWithValue;
|
|
44
95
|
},
|
|
45
|
-
|
|
96
|
+
|
|
46
97
|
data: dataset.data,
|
|
47
98
|
label: dataset.label,
|
|
48
|
-
stack: `Stack ${stackDatasets ?
|
|
99
|
+
stack: `Stack ${stackDatasets ? dataset.stack : datasetIndex}`
|
|
49
100
|
};
|
|
50
101
|
});
|
|
51
102
|
}
|
|
52
103
|
|
|
53
|
-
function getDatasets
|
|
54
|
-
|
|
104
|
+
function getDatasets(
|
|
105
|
+
firstDataSet: Dataset,
|
|
106
|
+
secondDataSet: Dataset,
|
|
107
|
+
patternsColors: string[],
|
|
108
|
+
patternsList: ((
|
|
109
|
+
hover: boolean,
|
|
110
|
+
color: string,
|
|
111
|
+
disableAccessibility: boolean
|
|
112
|
+
) => CanvasPattern)[],
|
|
113
|
+
disableAccessibility: boolean
|
|
114
|
+
) {
|
|
115
|
+
return getStackedDatasets(
|
|
116
|
+
[firstDataSet, secondDataSet],
|
|
117
|
+
false,
|
|
118
|
+
disableAccessibility,
|
|
119
|
+
patternsColors,
|
|
120
|
+
patternsList
|
|
121
|
+
);
|
|
55
122
|
}
|
|
56
123
|
|
|
57
|
-
function getBorderColor
|
|
124
|
+
function getBorderColor(
|
|
125
|
+
dataSetIndex: number,
|
|
126
|
+
contextIndex: number,
|
|
127
|
+
patternsColors: string[],
|
|
128
|
+
patternShifting?: number
|
|
129
|
+
) {
|
|
58
130
|
const index = getPatternIndexWithShift(dataSetIndex, patternShifting);
|
|
59
131
|
if (displayFullOpacity(dataSetIndex, contextIndex)) {
|
|
60
132
|
return patternsColors[index];
|
|
61
133
|
} else {
|
|
62
|
-
return addAlpha(patternsColors[index],0.2);
|
|
134
|
+
return addAlpha(patternsColors[index], 0.2);
|
|
63
135
|
}
|
|
64
136
|
}
|
|
65
137
|
|
|
66
|
-
function getPattern
|
|
138
|
+
function getPattern(
|
|
139
|
+
dataSetIndex: number,
|
|
140
|
+
contextIndex: number,
|
|
141
|
+
disableAccessibility: boolean,
|
|
142
|
+
patternsColors: string[],
|
|
143
|
+
patternsList: ((
|
|
144
|
+
hover: boolean,
|
|
145
|
+
color: string,
|
|
146
|
+
disableAccessibility: boolean
|
|
147
|
+
) => CanvasPattern)[],
|
|
148
|
+
patternShifting?: number
|
|
149
|
+
) {
|
|
67
150
|
const index = getPatternIndexWithShift(dataSetIndex, patternShifting);
|
|
68
151
|
if (displayFullOpacity(dataSetIndex, contextIndex)) {
|
|
69
|
-
return patternsList[index](
|
|
152
|
+
return patternsList[index](
|
|
153
|
+
false,
|
|
154
|
+
patternsColors[index],
|
|
155
|
+
disableAccessibility
|
|
156
|
+
);
|
|
70
157
|
} else {
|
|
71
|
-
return patternsList[index](
|
|
158
|
+
return patternsList[index](
|
|
159
|
+
true,
|
|
160
|
+
patternsColors[index],
|
|
161
|
+
disableAccessibility
|
|
162
|
+
);
|
|
72
163
|
}
|
|
73
164
|
}
|
|
74
165
|
|
|
75
|
-
function nothingHovered
|
|
166
|
+
function nothingHovered(): boolean {
|
|
76
167
|
return onHoverIndex.dataSetIndex < 0;
|
|
77
168
|
}
|
|
78
169
|
|
|
79
|
-
function columnHovered
|
|
80
|
-
return
|
|
170
|
+
function columnHovered(dataSetIndex: number, contextIndex: number): boolean {
|
|
171
|
+
return (
|
|
172
|
+
onHoverIndex.dataSetIndex === dataSetIndex &&
|
|
173
|
+
onHoverIndex.columnIndex === contextIndex
|
|
174
|
+
);
|
|
81
175
|
}
|
|
82
176
|
|
|
83
|
-
function legendHovered
|
|
84
|
-
return
|
|
177
|
+
function legendHovered(dataSetIndex: number): boolean {
|
|
178
|
+
return (
|
|
179
|
+
onHoverIndex.dataSetIndex === dataSetIndex && onHoverIndex.columnIndex < 0
|
|
180
|
+
);
|
|
85
181
|
}
|
|
86
182
|
|
|
87
|
-
function displayFullOpacity
|
|
88
|
-
|
|
183
|
+
function displayFullOpacity(
|
|
184
|
+
dataSetIndex: number,
|
|
185
|
+
contextIndex: number
|
|
186
|
+
): boolean {
|
|
187
|
+
return (
|
|
188
|
+
nothingHovered() ||
|
|
89
189
|
columnHovered(dataSetIndex, contextIndex) ||
|
|
90
|
-
legendHovered(dataSetIndex)
|
|
190
|
+
legendHovered(dataSetIndex)
|
|
191
|
+
);
|
|
91
192
|
}
|
|
92
193
|
|
|
93
|
-
function resetOnHoverIndex
|
|
194
|
+
function resetOnHoverIndex() {
|
|
94
195
|
onHoverIndex.dataSetIndex = -1;
|
|
95
196
|
onHoverIndex.columnIndex = -1;
|
|
96
197
|
}
|
|
97
198
|
|
|
98
|
-
function getOnHoverOptions
|
|
99
|
-
return (
|
|
199
|
+
function getOnHoverOptions() {
|
|
200
|
+
return (
|
|
201
|
+
_ignore: unknown,
|
|
202
|
+
activeElements: Array<{ index: number; datasetIndex: number }>
|
|
203
|
+
) => {
|
|
100
204
|
if (activeElements[0] !== undefined) {
|
|
101
205
|
onHoverIndex.dataSetIndex = activeElements[0].datasetIndex;
|
|
102
206
|
onHoverIndex.columnIndex = activeElements[0].index;
|
|
@@ -117,6 +221,6 @@ export default function () {
|
|
|
117
221
|
privateGetHtmlLegendPlugin,
|
|
118
222
|
getPatternIndexWithShift,
|
|
119
223
|
barChartRef,
|
|
120
|
-
borderWidth
|
|
224
|
+
borderWidth
|
|
121
225
|
};
|
|
122
226
|
}
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
import { Context, GenericTooltipService } from './GenericTooltipService';
|
|
2
|
+
|
|
3
|
+
export type BubbleTooltipLine = {
|
|
4
|
+
label: string;
|
|
5
|
+
value: string;
|
|
6
|
+
unit: string;
|
|
7
|
+
};
|
|
8
|
+
const tooltipLineStyle =
|
|
9
|
+
'background: white; border-bottom: 1px solid #CCCCCC; border-radius: 5px; padding: 10px 20px';
|
|
10
|
+
|
|
11
|
+
export class BubbleTooltipService extends GenericTooltipService {
|
|
12
|
+
fontProperties = 'font-family: Arial; font-size: 16px';
|
|
13
|
+
|
|
14
|
+
createBubbleTooltip(
|
|
15
|
+
context: Context,
|
|
16
|
+
lines: BubbleTooltipLine[],
|
|
17
|
+
title: string
|
|
18
|
+
) {
|
|
19
|
+
if (!title || title === '') {
|
|
20
|
+
return;
|
|
21
|
+
}
|
|
22
|
+
let tooltipEl = document.querySelector(
|
|
23
|
+
'#chartjs-tooltip'
|
|
24
|
+
) as HTMLElement | null;
|
|
25
|
+
if (!tooltipEl) {
|
|
26
|
+
tooltipEl = this.createNewTooltipElement();
|
|
27
|
+
}
|
|
28
|
+
const tooltipModel = context.tooltip;
|
|
29
|
+
if (tooltipModel.opacity === 0) {
|
|
30
|
+
tooltipEl.style.opacity = '0';
|
|
31
|
+
return;
|
|
32
|
+
}
|
|
33
|
+
if (tooltipModel.body) {
|
|
34
|
+
this.titleLines = tooltipModel.title || [];
|
|
35
|
+
const bodyLines = tooltipModel.body.map(this.getBody);
|
|
36
|
+
const body = bodyLines[0];
|
|
37
|
+
this.addBubbleLegendToDom(lines, body, tooltipEl, title);
|
|
38
|
+
}
|
|
39
|
+
this.handleTooltipPosition(context, tooltipModel, tooltipEl);
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
addBubbleLegendToDom(
|
|
43
|
+
lines: BubbleTooltipLine[],
|
|
44
|
+
body: Array<string>,
|
|
45
|
+
tooltipEl: HTMLElement,
|
|
46
|
+
title: string
|
|
47
|
+
) {
|
|
48
|
+
const legendText = body[0].split(':')[0];
|
|
49
|
+
const spanText = `<span style="${this.fontProperties}">${title}</span>`;
|
|
50
|
+
let innerHtml = `<div style="${tooltipLineStyle}; font-weight: bold" class="tooltipTitle">${spanText}</div>`;
|
|
51
|
+
const innerHtmlToAdd = this.getBubbleInnerHtml(lines);
|
|
52
|
+
innerHtml += innerHtmlToAdd;
|
|
53
|
+
const tableRoot = tooltipEl?.querySelector('.tooltipCtn') as HTMLElement;
|
|
54
|
+
tableRoot.innerHTML = innerHtml;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
getBubbleInnerHtml(lines: BubbleTooltipLine[]): string {
|
|
58
|
+
let innerLinesHtml = '';
|
|
59
|
+
lines.forEach((line) => {
|
|
60
|
+
innerLinesHtml += `<div style="${this.fontProperties}; ${tooltipLineStyle}; display:flex; justify-content: space-between;">`;
|
|
61
|
+
innerLinesHtml += `<div>${line.label}</div>`;
|
|
62
|
+
innerLinesHtml += `<div>${line.value} ${line.unit}</div>`;
|
|
63
|
+
innerLinesHtml += `</div>`;
|
|
64
|
+
});
|
|
65
|
+
return `<div>${innerLinesHtml}</div>`;
|
|
66
|
+
}
|
|
67
|
+
}
|