@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,217 +1,265 @@
1
1
  <template>
2
2
  <div class="container">
3
3
  <div class="main">
4
- <Line
5
- v-if="chartData"
6
- ref="cockpitLineChartRef"
7
- :data="chartData"
8
- :options="options"
9
- :plugins='htmlLegendPlugin'
10
- :chart-id='chartId'
11
- :cssClasses:='cssClasses'
12
- :styles='styles'
13
- :style='{ width, height, cursor:"pointer"}'
14
- />
15
- </div>
16
- <div ref="legendContainer" />
4
+ <Line
5
+ v-if="chartData"
6
+ ref="lineChartRef"
7
+ :id="chartId"
8
+ :data="chartData"
9
+ :options="options"
10
+ :plugins="htmlLegendPlugin"
11
+ :class="cssClasses"
12
+ :style="[{ width, height, cursor: 'pointer' }, styles]"
13
+ />
14
+ </div>
15
+ <div ref="legendContainer" />
17
16
  </div>
18
- </template>
19
-
20
- <script setup lang="ts">
21
-
22
- import type { Ref } from 'vue';
23
- import { computed, ref, PropType } from 'vue';
24
- import { Line } from 'vue-chartjs';
25
- import { LineData } from '../../types/LineChart';
26
- import { GenericTooltipService } from '../../services/GenericTooltipService';
27
- import type { Context } from '../../services/GenericTooltipService';
28
- import { TooltipChartType } from '../../types/TooltipChartType';
29
- import { formatTicks } from '../../services/FormatUtilities';
30
- import type { ChartItem } from '../../services/ChartsCommonLegend';
31
- import ChartDesign from '../../services/patterns/ChartDesign';
32
-
33
- import {
34
- createHtmlLegendItemText,
35
- createHtmlLegendListElement,
36
- createLegendElementWithSquareArea,
37
- getOrCreateLegendList,
38
- createLegendCheckbox,
39
- switchItemVisibility
40
- } from '../../services/ChartsCommonLegend';
41
-
42
- import {
43
- CategoryScale,
44
- Chart as ChartJS,
45
- Legend,
46
- LinearScale,
47
- LineElement,
48
- PointElement,
49
- Title,
50
- Tooltip,
51
- Plugin
52
- } from 'chart.js';
53
-
54
- ChartJS.register(
55
- Title,
56
- Tooltip,
57
- Legend,
58
- PointElement,
59
- LineElement,
60
- CategoryScale,
61
- LinearScale
62
- );
63
-
64
- const {
65
- colourSets,
66
- patternsStandardList
67
- } = ChartDesign();
17
+ </template>
68
18
 
19
+ <script setup lang="ts">
20
+ import type { Ref } from 'vue';
21
+ import { computed, ref, PropType } from 'vue';
22
+ import { Line } from 'vue-chartjs';
23
+ import { LineData } from '../../types/LineChart';
24
+ import { GenericTooltipService } from '../../services/GenericTooltipService';
25
+ import type { Context } from '../../services/GenericTooltipService';
26
+ import { TooltipChartType } from '../../types/TooltipChartType';
27
+ import { formatWithThousandsSeprators } from '../../services/FormatUtilities';
28
+ import type { ChartItem } from '../../services/ChartsCommonLegend';
29
+ import ChartDesign from '../../services/patterns/ChartDesign';
69
30
 
70
- const legendContainer = ref(null);
71
- const selectMode = ref(false);
72
- const lineDataProps = defineProps({
73
- chartId: {
74
- type: String,
75
- default: 'radar-chart',
76
- },
77
- rawTitle: {
78
- type: String,
79
- default: 'sales',
80
- },
81
- width: {
82
- type: String,
83
- default: '200px',
84
- },
85
- height: {
86
- type: String,
87
- default: '400px',
88
- },
89
- // disable accessibility patterns
90
- disableAccessibility: {
91
- type: Boolean,
92
- default: false
93
- },
94
- // colourSet props is used to choose the colour set of the charts as defined in the Figma prototypes.
95
- // 7 colour sets are currently defined :
96
- // - Default 0 corresponds to the current one
97
- // - 1 to 6 corresponds to the "new" colour sets : https://www.figma.com/file/Hn6PyvnR385Ta0XN3KqOI9/04.-Dataviz---Documentation-(read-only)?type=design&node-id=1-69316&mode=design&t=sDytQ5BipsryWkuA-0
98
- // Remark : All the sets are defined in /src/services/patterns/ChartDesign.ts
99
- colourSet: {
100
- type: Number,
101
- default: 0
102
- },
103
- // 6 patterns exist and are not randomly given but follow the order defined in patternsStandardList /src/services/patterns/ChartDesign.ts
104
- // Additionally, a pattern has only one possible colour per colour set as defined in the Figma prototype.
105
- // In some use cases, the chart may need to show a different orders of these patterns, this can be changed using the props newPatternsOrder
106
- newPatternsOrder: {
107
- type: Array as PropType<number[]>,
108
- default: () => [0,1,2,3,4,5]
109
- },
110
- lines: {
111
- type: Array as PropType<LineData[]>,
112
- default: () => {},
113
- },
114
- labels: {
115
- type: Array as PropType<string[]>,
116
- default: () => []
117
- },
118
- cssClasses: {
119
- default: '',
120
- type: String,
121
- },
122
- styles: {
123
- type: Object as PropType<Partial<CSSStyleDeclaration>>,
124
- default: () => {},
125
- },
126
- plugins: {
127
- type: Array as PropType<Plugin<'line'>[]>,
128
- default: () => [],
129
- },
130
- })
131
-
132
- const patternsColors = computed(() => lineDataProps.newPatternsOrder.length !== 6
133
- ? colourSets[lineDataProps.colourSet]
134
- : lineDataProps.newPatternsOrder.map((id)=> {return colourSets[lineDataProps.colourSet][id]})
135
- )
31
+ import {
32
+ createHtmlLegendItemText,
33
+ createHtmlLegendListElement,
34
+ createLegendElementWithSquareArea,
35
+ getOrCreateLegendList,
36
+ createLegendCheckbox,
37
+ switchItemVisibility,
38
+ } from '../../services/ChartsCommonLegend';
39
+
40
+ import {
41
+ CategoryScale,
42
+ Chart as ChartJS,
43
+ Legend,
44
+ LinearScale,
45
+ LineElement,
46
+ PointElement,
47
+ Title,
48
+ Tooltip,
49
+ Plugin,
50
+ } from 'chart.js';
51
+
52
+ ChartJS.register(
53
+ Title,
54
+ Tooltip,
55
+ Legend,
56
+ PointElement,
57
+ LineElement,
58
+ CategoryScale,
59
+ LinearScale
60
+ );
61
+
62
+ const { colourSets, patternsStandardList } = ChartDesign();
63
+
64
+ const legendContainer = ref(null);
65
+ const selectMode = ref(false);
66
+ const lineDataProps = defineProps({
67
+ /**
68
+ * Value of the id attribute present on the <canvas> tag element the chart
69
+ */
70
+ chartId: {
71
+ type: String,
72
+ default: 'radar-chart',
73
+ },
74
+ /**
75
+ * Label of the first line in the Tooltip
76
+ */
77
+ tooltipFirstLineLabel: {
78
+ type: String,
79
+ default: 'content',
80
+ },
81
+ /**
82
+ * Label of the second line in the Tooltip
83
+ */
84
+ tooltipSecondLineLabel: {
85
+ type: String,
86
+ default: 'content2',
87
+ },
88
+ /**
89
+ * Value of the `width` css property used to define the width of the <canvas> element
90
+ */
91
+ width: {
92
+ type: String,
93
+ default: '200px',
94
+ },
95
+ /**
96
+ * Value of the `height` css property used to define the height of the <canvas> element
97
+ */
98
+ height: {
99
+ type: String,
100
+ default: '400px',
101
+ },
102
+ /**
103
+ * Disable accessibility patterns
104
+ */
105
+ disableAccessibility: {
106
+ type: Boolean,
107
+ default: false,
108
+ },
109
+ /**
110
+ * Used to choose the colour set of the charts as defined in the Figma prototypes.
111
+ * 7 colour sets are currently defined:
112
+ * - Default 0 corresponds to the current one
113
+ * - 1 to 6 corresponds to the "new" [colour sets](https://www.figma.com/file/Hn6PyvnR385Ta0XN3KqOI9/04.-Dataviz---Documentation-(read-only)?type=design&node-id=1-69316&mode=design&t=sDytQ5BipsryWkuA-0)
114
+ * Note: All the sets are defined in /src/services/patterns/ChartDesign.ts
115
+ */
116
+ colourSet: {
117
+ type: Number,
118
+ default: 0,
119
+ },
120
+ /**
121
+ * 6 patterns exist and are not randomly given but follow the order defined in [patternsStandardList](/src/services/patterns/ChartDesign.ts)
122
+ * Additionally, a pattern has only one possible colour per colour set as defined in the Figma prototype.
123
+ * In some use cases, the chart may need to show a different orders of these patterns, this can be changed using the props newPatternsOrder
124
+ */
125
+ newPatternsOrder: {
126
+ type: Array as PropType<number[]>,
127
+ default: () => [0, 1, 2, 3, 4, 5],
128
+ },
129
+ /**
130
+ * Line data _(can contain `label`, `data` and `unit` keys)_
131
+ */
132
+ lines: {
133
+ type: Array as PropType<LineData[]>,
134
+ default: () => {},
135
+ },
136
+ /**
137
+ * Labels used to label the index axis (default x axes). See [Data structures documentation](https://www.chartjs.org/docs/latest/general/data-structures.html)
138
+ */
139
+ labels: {
140
+ type: Array as PropType<string[]>,
141
+ default: () => [],
142
+ },
143
+ /**
144
+ * Add custom CSS classes to the <canvas> element
145
+ */
146
+ cssClasses: {
147
+ type: String,
148
+ default: undefined,
149
+ },
150
+ /**
151
+ * Add custom CSS styles to the <canvas> element
152
+ */
153
+ styles: {
154
+ type: Object as PropType<Partial<CSSStyleDeclaration>>,
155
+ default: () => {},
156
+ },
157
+ /**
158
+ * Value of the `plugins` key passed to the Chart config
159
+ */
160
+ plugins: {
161
+ type: Array as PropType<Plugin<'line'>[]>,
162
+ default: () => [],
163
+ },
164
+ });
136
165
 
137
- const patternsOrderedList = lineDataProps.newPatternsOrder.length !== 6
138
- ? patternsStandardList
139
- : lineDataProps.newPatternsOrder.map((id)=> {return patternsStandardList[id]})
166
+ const patternsColors = computed(() =>
167
+ lineDataProps.newPatternsOrder.length !== 6
168
+ ? colourSets[lineDataProps.colourSet]
169
+ : lineDataProps.newPatternsOrder.map((id) => {
170
+ return colourSets[lineDataProps.colourSet][id];
171
+ })
172
+ );
140
173
 
141
- const getTooltipData = (context: Context) => {
142
- const datasetIndex = context.tooltip.dataPoints[0].datasetIndex;
143
- const dataIndex = context.tooltip.dataPoints[0].dataIndex;
144
- if (!dataIndex || !datasetIndex) {
145
- return '';
146
- }
147
- const formattedValue = lineDataProps.lines[datasetIndex].data[dataIndex].toFixed(2);
148
- return lineDataProps.lines[datasetIndex].unit ? formattedValue +
149
- ' ' + lineDataProps.lines[datasetIndex].unit
150
- : formattedValue;
174
+ const patternsOrderedList =
175
+ lineDataProps.newPatternsOrder.length !== 6
176
+ ? patternsStandardList
177
+ : lineDataProps.newPatternsOrder.map((id) => {
178
+ return patternsStandardList[id];
179
+ });
180
+
181
+ const getTooltipData = (context: Context) => {
182
+ const datasetIndex = context.tooltip.dataPoints[0].datasetIndex as number;
183
+ const dataIndex = context.tooltip.dataPoints[0].dataIndex as number;
184
+ const formattedValue =
185
+ lineDataProps.lines[datasetIndex].data[dataIndex].toFixed(2);
186
+ return lineDataProps.lines[datasetIndex].unit
187
+ ? formattedValue + ' ' + lineDataProps.lines[datasetIndex].unit
188
+ : formattedValue;
189
+ };
190
+
191
+ const tooltipFirstLine = computed(() => {
192
+ return lineDataProps.tooltipFirstLineLabel;
193
+ });
194
+ const tooltipSecondLine = computed(() => {
195
+ return lineDataProps.tooltipSecondLineLabel;
196
+ });
197
+
198
+ const chartData = computed(() => {
199
+ return {
200
+ labels: lineDataProps.labels.map((label: string) => label),
201
+ datasets: [
202
+ {
203
+ type: 'line' as const,
204
+ borderColor: patternsColors.value[0],
205
+ pointStyle: 'rectRot',
206
+ pointBackgroundColor: '#FFFFFF',
207
+ pointRadius: 5,
208
+ label: lineDataProps.lines[0].label,
209
+ data: lineDataProps.lines[0].data,
210
+ borderWidth: 2,
211
+ },
212
+ {
213
+ type: 'line' as const,
214
+ borderColor: patternsColors.value[1],
215
+ pointStyle: 'circle',
216
+ pointBackgroundColor: '#FFFFFF',
217
+ pointRadius: 5,
218
+ label: lineDataProps.lines[1].label,
219
+ data: lineDataProps.lines[1].data,
220
+ borderWidth: 2,
221
+ },
222
+ ],
151
223
  };
152
-
153
- const tooltipFirstLine = 'months';
154
- const tooltipValueAttribute = computed(() => {
155
- return lineDataProps.rawTitle;
156
- });
157
-
158
- const chartData = computed(() => {
159
- return {
160
- labels: lineDataProps.labels.map((label: string) => label),
161
- datasets: [
162
- {
163
- type: 'line' as const,
164
- borderColor: patternsColors.value[0],
165
- pointStyle: 'rectRot',
166
- pointBackgroundColor: '#FFFFFF',
167
- pointRadius: 5,
168
- label: lineDataProps.lines[0].label,
169
- data: lineDataProps.lines[0].data,
170
- borderWidth: 2
171
- },
172
- {
173
- type: 'line' as const,
174
- borderColor: patternsColors.value[1],
175
- pointStyle: 'circle',
176
- pointBackgroundColor: '#FFFFFF',
177
- pointRadius: 5,
178
- label: lineDataProps.lines[1].label,
179
- data: lineDataProps.lines[1].data,
180
- borderWidth: 2
181
- }
182
- ]
183
- };
184
- });
185
-
186
- function getHtmlLegendPlugin(legendContainer: Ref, selectMode: Ref) {
187
- return [{
224
+ });
225
+
226
+ function getHtmlLegendPlugin(legendContainer: Ref, selectMode: Ref) {
227
+ return [
228
+ {
188
229
  id: 'htmlLegend',
189
- afterUpdate (chart: any) {
230
+ afterUpdate(chart: any) {
190
231
  const ul = getOrCreateLegendList(legendContainer, 'column');
191
232
  ul.style.display = 'flex';
192
233
  ul.style.flexDirection = 'row';
234
+ ul.style.margin = '1.375rem 1.0625rem';
193
235
  while (ul.firstChild) {
194
236
  ul.firstChild.remove();
195
237
  }
196
238
  const items = chart.options.plugins.legend.labels.generateLabels(chart);
197
239
  items.forEach((item: ChartItem) => {
198
- const li = createHtmlLegendListElement(chart, selectMode, item.datasetIndex);
199
- let liContent: HTMLElement;
200
- if (!selectMode.value) {
201
- liContent = createLegendElementWithSquareArea(item);
202
- } else {
203
- liContent = createLegendElementWithCheckbox(chart, item);
204
- }
205
- li.style.marginRight = '10px';
206
- li.appendChild(liContent);
207
- li.appendChild(createHtmlLegendItemText(item));
208
- ul.appendChild(li);
240
+ const li = createHtmlLegendListElement(
241
+ chart,
242
+ selectMode,
243
+ item.datasetIndex
244
+ );
245
+ let liContent: HTMLElement;
246
+ if (!selectMode.value) {
247
+ liContent = createLegendElementWithSquareArea(item, null);
248
+ } else {
249
+ liContent = createLegendElementWithCheckbox(chart, item);
250
+ }
251
+ liContent.style.boxSizing = 'border-box';
252
+ li.style.marginRight = '10px';
253
+ li.appendChild(liContent);
254
+ li.appendChild(createHtmlLegendItemText(item));
255
+ ul.appendChild(li);
209
256
  });
210
- }
211
- }];
212
- }
257
+ },
258
+ },
259
+ ];
260
+ }
213
261
 
214
- function createLegendElementWithCheckbox (chart: any, item: ChartItem) {
262
+ function createLegendElementWithCheckbox(chart: any, item: ChartItem) {
215
263
  const liContent = createLegendCheckbox(chart, item);
216
264
  liContent.onclick = (e: Event) => {
217
265
  switchItemVisibility(chart, item.datasetIndex, selectMode);
@@ -219,70 +267,70 @@ const patternsOrderedList = lineDataProps.newPatternsOrder.length !== 6
219
267
  };
220
268
  return liContent;
221
269
  }
222
-
223
- const htmlLegendPlugin = getHtmlLegendPlugin(legendContainer, selectMode);
224
-
225
- const options = computed(() => ({
226
- responsive: true,
227
- maintainAspectRatio: true,
228
- plugins: {
229
- legend: {
230
- display: false
270
+
271
+ const htmlLegendPlugin = getHtmlLegendPlugin(legendContainer, selectMode);
272
+
273
+ const options = computed(() => ({
274
+ responsive: true,
275
+ maintainAspectRatio: false,
276
+ plugins: {
277
+ legend: {
278
+ display: false,
279
+ },
280
+ tooltip: {
281
+ enabled: false,
282
+ external: function (context: Context) {
283
+ new GenericTooltipService().createTooltip(
284
+ context,
285
+ getTooltipData,
286
+ {
287
+ chartType: TooltipChartType.LINE_CHART,
288
+ firstLineLabel: tooltipFirstLine.value,
289
+ secondLineLabel: tooltipSecondLine.value,
290
+ },
291
+ patternsColors.value,
292
+ patternsOrderedList,
293
+ lineDataProps.disableAccessibility
294
+ );
231
295
  },
232
- tooltip: {
233
- enabled: false,
234
- external: function (context: Context) {
235
- new GenericTooltipService().createTooltip(
236
- context,
237
- getTooltipData,
238
- {
239
- chartType: TooltipChartType.LINE_CHART,
240
- firstLineLabel: tooltipFirstLine,
241
- secondLineLabel: tooltipValueAttribute.value
242
- },
243
- patternsColors.value,
244
- patternsOrderedList,
245
- lineDataProps.disableAccessibility
246
- );
247
- }
248
- }
249
296
  },
250
- scales: {
251
- x: {
252
- offset: true,
297
+ },
298
+ scales: {
299
+ x: {
300
+ offset: true,
301
+ },
302
+ y: {
303
+ type: 'linear' as const,
304
+ display: true,
305
+ position: 'left' as const,
306
+ grid: {
307
+ drawOnChartArea: true,
253
308
  },
254
- y: {
255
- type: 'linear' as const,
256
- display: true,
257
- position: 'left' as const,
258
- grid: {
259
- drawOnChartArea: true
309
+ ticks: {
310
+ callback: function (val: number | string) {
311
+ const unit = lineDataProps.lines[0].unit;
312
+ return `${formatWithThousandsSeprators(val as number)} ${
313
+ unit ? unit : ''
314
+ }`;
260
315
  },
261
- ticks: {
262
- callback: function (val: number | string) {
263
- const unit = lineDataProps.lines[0].unit;
264
- return formatTicks(val as number, unit ? unit : null);
265
- },
266
- maxTicksLimit: 8,
267
- }
268
- }
269
- }
270
- }));
271
- </script>
272
-
273
- <style scoped>
274
- .container {
275
- -moz-osx-font-smoothing: grayscale;
276
- -webkit-font-smoothing: antialiased;
277
- font-weight: 400;
278
- font-family: 'Roboto', sans-serif;
279
- }
280
- .main {
281
- display: flex;
282
- flex-direction: column;
283
- justify-content: center;
284
- align-items: center;
285
- margin-bottom: 20px;
286
- }
287
- </style>
288
-
316
+ },
317
+ },
318
+ },
319
+ }));
320
+ </script>
321
+
322
+ <style scoped>
323
+ .container {
324
+ -moz-osx-font-smoothing: grayscale;
325
+ -webkit-font-smoothing: antialiased;
326
+ font-weight: 400;
327
+ font-family: 'Roboto', sans-serif;
328
+ }
329
+ .main {
330
+ display: flex;
331
+ flex-direction: column;
332
+ justify-content: center;
333
+ align-items: center;
334
+ margin-bottom: 20px;
335
+ }
336
+ </style>
@@ -0,0 +1,8 @@
1
+ import type { App } from "vue";
2
+ import LineChart from "./LineChart.vue";
3
+
4
+ LineChart.install = (app: App) => {
5
+ app.component("LineChart", LineChart);
6
+ };
7
+
8
+ export { LineChart };