@mozaic-ds/chart 0.1.0-beta.3 → 0.1.0-beta.5

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.
@@ -1,32 +1,37 @@
1
1
  <template>
2
2
  <div class="container">
3
- <div class='main'>
3
+ <div class="main">
4
4
  <Radar
5
- v-if="radarData"
6
- :data='radarData'
7
- :options='chartOptions'
8
- :plugins="radarPlugins"
9
- :chart-id='chartId'
10
- :cssClasses:='cssClasses'
11
- :styles='styles'
12
- :style='{ height, cursor:"pointer",}'
5
+ v-if="radarData"
6
+ :id="chartId"
7
+ :data="radarData"
8
+ :options="chartOptions"
9
+ :plugins="radarPlugins"
10
+ :class="cssClasses"
11
+ :style="[{ height, cursor: 'pointer' }, styles]"
13
12
  />
14
13
  </div>
15
- <div ref='legendContainer' class='legendContainer' />
14
+ <div ref="legendContainer" class="legendContainer" />
16
15
  </div>
17
16
  </template>
18
17
 
19
- <script setup lang='ts'>
18
+ <script setup lang="ts">
20
19
  import { PropType, ref, computed } from 'vue';
21
20
  import type { Area } from '../../types/RadarData';
22
21
  import { Radar } from 'vue-chartjs';
23
22
  import type { ActiveElement, ChartData } from 'chart.js';
24
- import {Context, GenericTooltipService} from '../../services/GenericTooltipService';
25
- import { formatWithThousandsSeprators, numberWithThousandSeparators } from '../../services/FormatUtilities';
23
+ import {
24
+ Context,
25
+ GenericTooltipService,
26
+ } from '../../services/GenericTooltipService';
27
+ import {
28
+ formatWithThousandsSeprators,
29
+ numberWithThousandSeparators,
30
+ } from '../../services/FormatUtilities';
26
31
  import { TooltipChartType } from '../../types/TooltipChartType';
27
32
  import { drawLabels } from '../../services/RadarChartFunctions';
28
33
  import type { Chart, ChartItem } from '../../services/ChartsCommonLegend';
29
- import { addAlpha } from '../../services/ColorFunctions'
34
+ import { addAlpha } from '../../services/ColorFunctions';
30
35
  import {
31
36
  Chart as ChartJS,
32
37
  Filler,
@@ -36,7 +41,7 @@ import {
36
41
  RadialLinearScale,
37
42
  Title,
38
43
  Tooltip,
39
- Plugin
44
+ Plugin,
40
45
  } from 'chart.js';
41
46
 
42
47
  import {
@@ -46,7 +51,7 @@ import {
46
51
  createLegendElementWithSquareArea,
47
52
  getOrCreateLegendList,
48
53
  hideAllButThis,
49
- switchItemVisibility
54
+ switchItemVisibility,
50
55
  } from '../../services/ChartsCommonLegend';
51
56
 
52
57
  import ChartDesign from '../../services/patterns/ChartDesign';
@@ -58,75 +63,105 @@ ChartJS.register(
58
63
  RadialLinearScale,
59
64
  LineElement,
60
65
  PointElement,
61
- Filler,
66
+ Filler
62
67
  );
63
68
 
64
- const {
65
- colourSets,
66
- patternsStandardList
67
- } = ChartDesign();
69
+ const { colourSets, patternsStandardList } = ChartDesign();
68
70
 
69
71
  const radarComponentChartProps = defineProps({
70
- chartId: {
71
- type: String,
72
- default: 'radar-chart',
73
- },
74
- height: {
75
- type: String,
76
- default: '400px',
77
- },
78
- labels: {
72
+ /**
73
+ * Value of the id attribute present on the <canvas> tag element the chart
74
+ */
75
+ chartId: {
76
+ type: String,
77
+ default: 'radar-chart',
78
+ },
79
+ /**
80
+ * Value of the `height` css property used to define the height of the <canvas> element
81
+ */
82
+ height: {
83
+ type: String,
84
+ default: '400px',
85
+ },
86
+ /**
87
+ * Labels used to label the index axis (default x axes). See [Data structures documentation](https://www.chartjs.org/docs/latest/general/data-structures.html)
88
+ */
89
+ labels: {
79
90
  type: Array as PropType<string[]>,
80
- default: () => []
81
- },
82
- // disable accessibility patterns
83
- disableAccessibility: {
84
- type: Boolean,
85
- default: false
86
- },
87
- // colourSet props is used to choose the colour set of the charts as defined in the Figma prototypes.
88
- // 7 colour sets are currently defined :
89
- // - Default 0 corresponds to the current one
90
- // - 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
91
- // Remark : All the sets are defined in /src/services/patterns/ChartDesign.ts
92
- colourSet: {
93
- type: Number,
94
- default: 0
95
- },
96
- // 6 patterns exist and are not randomly given but follow the order defined in patternsStandardList /src/services/patterns/ChartDesign.ts
97
- // Additionally, a pattern has only one possible colour per colour set as defined in the Figma prototype.
98
- // In some use cases, the chart may need to show a different orders of these patterns, this can be changed using the props newPatternsOrder
99
- newPatternsOrder: {
100
- type: Array as PropType<number[]>,
101
- default: () => [0,1,2,3,4,5]
102
- },
103
- areas: {
104
- type: Array as PropType<Area[]>,
105
- default: () => []
106
- },
107
- cssClasses: {
108
- default: '',
109
- type: String,
110
- },
111
- styles: {
112
- type: Object as PropType<Partial<CSSStyleDeclaration>>,
113
- default: () => {},
114
- },
115
- plugins: {
116
- type: Array as PropType<Plugin<'radar'>[]>,
117
- default: () => [],
118
- },
119
- })
91
+ default: () => [],
92
+ },
93
+ /**
94
+ * Disable accessibility patterns
95
+ */
96
+ disableAccessibility: {
97
+ type: Boolean,
98
+ default: false,
99
+ },
100
+ /**
101
+ * Used to choose the colour set of the charts as defined in the Figma prototypes.
102
+ * 7 colour sets are currently defined:
103
+ * - Default 0 corresponds to the current one
104
+ * - 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)
105
+ * Note: All the sets are defined in /src/services/patterns/ChartDesign.ts
106
+ */
107
+ colourSet: {
108
+ type: Number,
109
+ default: 0,
110
+ },
111
+ /**
112
+ * 6 patterns exist and are not randomly given but follow the order defined in [patternsStandardList](/src/services/patterns/ChartDesign.ts)
113
+ * Additionally, a pattern has only one possible colour per colour set as defined in the Figma prototype.
114
+ * In some use cases, the chart may need to show a different orders of these patterns, this can be changed using the props newPatternsOrder
115
+ */
116
+ newPatternsOrder: {
117
+ type: Array as PropType<number[]>,
118
+ default: () => [0, 1, 2, 3, 4, 5],
119
+ },
120
+ /**
121
+ * Value of the `datasets` key present in the `data` object passed to the Chart config
122
+ */
123
+ datasets: {
124
+ type: Array as PropType<Area[]>,
125
+ default: () => [],
126
+ },
127
+ /**
128
+ * Add custom CSS classes to the <canvas> element
129
+ */
130
+ cssClasses: {
131
+ default: '',
132
+ type: String,
133
+ },
134
+ /**
135
+ * Add custom CSS styles to the <canvas> element
136
+ */
137
+ styles: {
138
+ type: Object as PropType<Partial<CSSStyleDeclaration>>,
139
+ default: () => {},
140
+ },
141
+ /**
142
+ * Value of the `plugins` key passed to the Chart config
143
+ */
144
+ plugins: {
145
+ type: Array as PropType<Plugin<'radar'>[]>,
146
+ default: () => [],
147
+ },
148
+ });
120
149
 
121
- const patternsColors = computed(() => radarComponentChartProps.newPatternsOrder.length !== 6
122
- ? colourSets[radarComponentChartProps.colourSet]
123
- : radarComponentChartProps.newPatternsOrder.map((id)=> {return colourSets[radarComponentChartProps.colourSet][id]})
124
- )
150
+ const patternsColors = computed(() =>
151
+ radarComponentChartProps.newPatternsOrder.length !== 6
152
+ ? colourSets[radarComponentChartProps.colourSet]
153
+ : radarComponentChartProps.newPatternsOrder.map((id) => {
154
+ return colourSets[radarComponentChartProps.colourSet][id];
155
+ })
156
+ );
125
157
 
126
- const patternsOrderedList = computed(() => radarComponentChartProps.newPatternsOrder.length !== 6
127
- ? patternsStandardList
128
- : radarComponentChartProps.newPatternsOrder.map((id)=> {return patternsStandardList[id]})
129
- )
158
+ const patternsOrderedList = computed(() =>
159
+ radarComponentChartProps.newPatternsOrder.length !== 6
160
+ ? patternsStandardList
161
+ : radarComponentChartProps.newPatternsOrder.map((id) => {
162
+ return patternsStandardList[id];
163
+ })
164
+ );
130
165
 
131
166
  const radarData = computed<ChartData<'radar'>>(() => ({
132
167
  labels: getRadarLabels(),
@@ -135,7 +170,7 @@ const radarData = computed<ChartData<'radar'>>(() => ({
135
170
  label: 'Data One',
136
171
  backgroundColor: addAlpha(patternsColors.value[0], 0.1),
137
172
  borderColor: patternsColors.value[0],
138
- pointBackgroundColor: '#FFFFFF',
173
+ pointBackgroundColor: '#FFFFFF',
139
174
  pointBorderColor: patternsColors.value[0],
140
175
  pointBorderWidth: 2,
141
176
  borderWidth: 2,
@@ -143,7 +178,9 @@ const radarData = computed<ChartData<'radar'>>(() => ({
143
178
  pointRadius: 5,
144
179
  pointHoverBackgroundColor: patternsColors.value[0],
145
180
  pointHoverBorderColor: patternsColors.value[0],
146
- data: radarComponentChartProps.areas[0].areaData.map((x: { position: number }) => x.position)
181
+ data: radarComponentChartProps.datasets[0].areaData.map(
182
+ (x: { position: number }) => x.position
183
+ ),
147
184
  },
148
185
  {
149
186
  label: 'Data Two',
@@ -158,26 +195,32 @@ const radarData = computed<ChartData<'radar'>>(() => ({
158
195
  pointStyle: 'rectRot',
159
196
  pointHoverBackgroundColor: patternsColors.value[1],
160
197
  pointHoverBorderColor: patternsColors.value[1],
161
- data: radarComponentChartProps.areas[1].areaData.map((x: { position: number }) => x.position)
162
- }
163
- ]
198
+ data: radarComponentChartProps.datasets[1].areaData.map(
199
+ (x: { position: number }) => x.position
200
+ ),
201
+ },
202
+ ],
164
203
  }));
165
204
 
166
205
  const chartOptions: any = {
167
- onClick: (_ingnore: unknown, clickedElements: ActiveElement[], chart: Chart) => {
206
+ onClick: (
207
+ _ingnore: unknown,
208
+ clickedElements: ActiveElement[],
209
+ chart: Chart
210
+ ) => {
168
211
  if (clickedElements[0]) {
169
212
  hideAllButThis(chart, clickedElements[0].datasetIndex, selectMode);
170
213
  }
171
214
  },
172
215
  plugins: {
173
216
  htmlLegend: {
174
- containerID: 'legend-container'
217
+ containerID: 'legend-container',
175
218
  },
176
219
  legend: {
177
- display: false
220
+ display: false,
178
221
  },
179
222
  title: {
180
- display: false
223
+ display: false,
181
224
  },
182
225
  tooltip: {
183
226
  enabled: false,
@@ -191,58 +234,64 @@ const chartOptions: any = {
191
234
  patternsOrderedList.value,
192
235
  radarComponentChartProps.disableAccessibility
193
236
  );
194
- }
195
- }
237
+ },
238
+ },
196
239
  },
197
240
  layout: {
198
- padding: 65
241
+ padding: 65,
199
242
  },
200
243
  scales: {
201
244
  r: {
202
245
  min: 0,
203
246
  max: 100,
204
247
  pointLabels: {
205
- display: false,
206
- font: {
207
- size: 16
208
- }
248
+ display: false,
249
+ font: {
250
+ size: 16,
251
+ },
209
252
  },
210
253
  ticks: {
211
254
  display: false,
212
- stepSize: 25
213
- }
214
- }
215
- }
216
- };
255
+ stepSize: 25,
256
+ },
257
+ },
258
+ },
259
+ };
217
260
  const legendContainer = ref(null);
218
261
  const selectMode = ref(false);
219
- function splitLabelIfTooLong (axisLabel: string, buildValue: string) {
262
+ function splitLabelIfTooLong(axisLabel: string, buildValue: string) {
220
263
  const radarLimitLabelLength = 15;
221
- if (axisLabel.length > radarLimitLabelLength && axisLabel.includes(' ', radarLimitLabelLength)) {
222
- const indexOfFirstSpaceAfterLimit: number = axisLabel.indexOf(' ', radarLimitLabelLength);
264
+ if (
265
+ axisLabel.length > radarLimitLabelLength &&
266
+ axisLabel.includes(' ', radarLimitLabelLength)
267
+ ) {
268
+ const indexOfFirstSpaceAfterLimit: number = axisLabel.indexOf(
269
+ ' ',
270
+ radarLimitLabelLength
271
+ );
223
272
  return [
224
273
  axisLabel.substring(0, indexOfFirstSpaceAfterLimit),
225
274
  axisLabel.substring(indexOfFirstSpaceAfterLimit),
226
- buildValue
275
+ buildValue,
227
276
  ];
228
277
  }
229
- return [
230
- axisLabel,
231
- buildValue
232
- ];
278
+ return [axisLabel, buildValue];
233
279
  }
234
280
  const getRadarLabels = () => {
235
281
  return radarComponentChartProps.labels.map((label: string, index: number) => {
236
- const buildValue = radarComponentChartProps.areas[0].areaData[index].value
237
- ? `${formatNumber(radarComponentChartProps.areas[0].areaData[index].value + '')} ${radarComponentChartProps.areas[0].areaData[index].unit}`
282
+ const buildValue = radarComponentChartProps.datasets[0].areaData[index]
283
+ .value
284
+ ? `${formatNumber(
285
+ radarComponentChartProps.datasets[0].areaData[index].value + ''
286
+ )} ${radarComponentChartProps.datasets[0].areaData[index].unit}`
238
287
  : 'No Data';
239
288
  return splitLabelIfTooLong(label, buildValue);
240
289
  });
241
- }
290
+ };
242
291
  const formatNumber = (numberFromJson: string) => {
243
292
  return formatWithThousandsSeprators(parseFloat(numberFromJson));
244
293
  };
245
- function createLegendElementWithCheckbox (chart: any, item: ChartItem) {
294
+ function createLegendElementWithCheckbox(chart: any, item: ChartItem) {
246
295
  const liContent = createLegendCheckbox(chart, item);
247
296
  liContent.onclick = (e: Event) => {
248
297
  switchItemVisibility(chart, item.datasetIndex, selectMode);
@@ -251,44 +300,53 @@ function createLegendElementWithCheckbox (chart: any, item: ChartItem) {
251
300
  return liContent;
252
301
  }
253
302
 
254
- const radarPlugins = [{
255
- id: 'htmlLegend',
256
- afterUpdate (chart: any) {
257
- const ul = getOrCreateLegendList(legendContainer, 'row');
258
- while (ul.firstChild) {
259
- ul.firstChild.remove();
260
- }
261
- const items = chart.options.plugins.legend.labels.generateLabels(chart).reverse();
262
- items.forEach((item: ChartItem) => {
263
- const li = createHtmlLegendListElement(chart, selectMode, item.datasetIndex);
264
- let liContent;
265
- li.style.marginRight = '0.625rem';
266
- if (!selectMode.value) {
267
- liContent = createLegendElementWithSquareArea(item, true);
268
- } else {
269
- liContent = createLegendElementWithCheckbox(chart, item);
303
+ const radarPlugins = [
304
+ {
305
+ id: 'htmlLegend',
306
+ afterUpdate(chart: any) {
307
+ const ul = getOrCreateLegendList(legendContainer, 'row');
308
+ while (ul.firstChild) {
309
+ ul.firstChild.remove();
270
310
  }
271
- li.appendChild(liContent);
272
- li.appendChild(createHtmlLegendItemText(item));
273
- ul.appendChild(li);
274
- });
275
- }
276
- },{
277
- id: 'radarLabelPlugin',
278
- beforeDraw (chart: any) {
279
- drawLabels(chart, radarComponentChartProps);
311
+ const items = chart.options.plugins.legend.labels
312
+ .generateLabels(chart)
313
+ .reverse();
314
+ items.forEach((item: ChartItem) => {
315
+ const li = createHtmlLegendListElement(
316
+ chart,
317
+ selectMode,
318
+ item.datasetIndex
319
+ );
320
+ let liContent;
321
+ li.style.marginRight = '0.625rem';
322
+ if (!selectMode.value) {
323
+ liContent = createLegendElementWithSquareArea(item, true);
324
+ } else {
325
+ liContent = createLegendElementWithCheckbox(chart, item);
326
+ }
327
+ li.appendChild(liContent);
328
+ li.appendChild(createHtmlLegendItemText(item));
329
+ ul.appendChild(li);
330
+ });
331
+ },
280
332
  },
281
- }];
333
+ {
334
+ id: 'radarLabelPlugin',
335
+ beforeDraw(chart: any) {
336
+ drawLabels(chart, radarComponentChartProps);
337
+ },
338
+ },
339
+ ];
282
340
 
283
341
  const getTooltipData = (context: Context): string => {
284
- const datasetIndex: number | undefined = context.tooltip.dataPoints[0].datasetIndex;
285
- const dataIndex: number | undefined = context.tooltip.dataPoints[0].dataIndex;
286
- if (datasetIndex && dataIndex) {
287
- const data = radarComponentChartProps.areas[datasetIndex];
288
- return data.areaData[dataIndex].value.toFixed(2) + ' ' +
289
- data.areaData[dataIndex].unit;
290
- }
291
- return '';
342
+ const datasetIndex = context.tooltip.dataPoints[0].datasetIndex as number;
343
+ const dataIndex = context.tooltip.dataPoints[0].dataIndex as number;
344
+ const data = radarComponentChartProps.datasets[datasetIndex];
345
+ return (
346
+ data.areaData[dataIndex].value.toFixed(2) +
347
+ ' ' +
348
+ data.areaData[dataIndex].unit
349
+ );
292
350
  };
293
351
  </script>
294
352
 
@@ -306,4 +364,4 @@ const getTooltipData = (context: Context): string => {
306
364
  justify-content: center;
307
365
  align-items: center;
308
366
  }
309
- </style>
367
+ </style>
package/src/main.ts CHANGED
@@ -1,5 +1,6 @@
1
- import { createApp } from "vue";
2
- import App from "./App.vue";
3
- import MozaicChart from "./plugin";
1
+ import BarChart from "./components/bar/BarChart.vue";
2
+ import DoughnutChart from "./components/doughnut/DoughnutChart.vue";
3
+ import LineChart from "./components/line/LineChart.vue";
4
+ import RadarChart from "./components/radar/RadarChart.vue";
4
5
 
5
- createApp(App).use(MozaicChart).mount("#app");
6
+ export { BarChart, DoughnutChart, LineChart, RadarChart };
package/src/plugin.ts CHANGED
@@ -2,7 +2,7 @@ import type { App } from "vue";
2
2
  import * as Components from "./components";
3
3
 
4
4
  const MozaicChart = {
5
- install: (app: App) => {
5
+ install: (app: App, options: {}) => {
6
6
  Object.keys(Components).forEach((name) => {
7
7
  // @ts-ignore
8
8
  app.component(name, Components[name]);