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

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 (59) hide show
  1. package/dist/mozaic-chart.js +4453 -2623
  2. package/dist/mozaic-chart.umd.cjs +17 -11
  3. package/dist/style.css +1 -1
  4. package/package.json +25 -10
  5. package/src/assets/base.css +1 -1
  6. package/src/assets/img/bubbles.svg +4 -0
  7. package/src/components/bar/BarChart.stories.ts +105 -103
  8. package/src/components/bar/BarChart.vue +257 -131
  9. package/src/components/bar/index.ts +3 -3
  10. package/src/components/bubble/BubbleChart.stories.ts +66 -0
  11. package/src/components/bubble/BubbleChart.vue +363 -0
  12. package/src/components/bubble/index.ts +8 -0
  13. package/src/components/doughnut/DoughnutChart.stories.ts +38 -36
  14. package/src/components/doughnut/DoughnutChart.vue +210 -111
  15. package/src/components/doughnut/index.ts +3 -3
  16. package/src/components/index.ts +4 -4
  17. package/src/components/line/LineChart.stories.ts +52 -27
  18. package/src/components/line/LineChart.vue +346 -254
  19. package/src/components/line/index.ts +3 -3
  20. package/src/components/mixed/MixedBarLineChart.stories.ts +91 -0
  21. package/src/components/mixed/MixedBarLineChart.vue +413 -0
  22. package/src/components/mixed/index.ts +8 -0
  23. package/src/components/radar/RadarChart.stories.ts +102 -102
  24. package/src/components/radar/RadarChart.vue +204 -165
  25. package/src/components/radar/index.ts +3 -3
  26. package/src/main.ts +14 -4
  27. package/src/plugin.ts +10 -8
  28. package/src/services/BarChartFunctions.ts +136 -35
  29. package/src/services/BubbleTooltipService.ts +67 -0
  30. package/src/services/ChartsCommonLegend.ts +309 -137
  31. package/src/services/ColorFunctions.ts +1 -1
  32. package/src/services/DoughnutChartFunctions.ts +132 -55
  33. package/src/services/FormatUtilities.ts +28 -14
  34. package/src/services/GenericTooltipService.ts +140 -65
  35. package/src/services/MixedBarLineFunctions.ts +262 -0
  36. package/src/services/PatternFunctions.ts +25 -18
  37. package/src/services/RadarChartFunctions.ts +33 -12
  38. package/src/services/patterns/ChartDesign.ts +35 -24
  39. package/src/services/patterns/patternCircles.ts +63 -36
  40. package/src/services/patterns/patternDashedDiagonals.ts +64 -57
  41. package/src/services/patterns/patternDiagonals.ts +138 -106
  42. package/src/services/patterns/patternSquares.ts +86 -80
  43. package/src/services/patterns/patternVerticalLines.ts +76 -69
  44. package/src/services/patterns/patternZigzag.ts +92 -85
  45. package/src/stories/Changelog.mdx +6 -0
  46. package/src/stories/Contributing.mdx +101 -0
  47. package/src/stories/GettingStarted.mdx +92 -0
  48. package/src/stories/SupportAndOnboarding.mdx +44 -0
  49. package/src/types/AxisDefinition.ts +4 -0
  50. package/src/types/BarData.ts +1 -0
  51. package/src/types/Chart.ts +9 -7
  52. package/src/types/DoughnutData.ts +8 -0
  53. package/src/types/GenericData.ts +10 -10
  54. package/src/types/LineChart.ts +4 -4
  55. package/src/types/MixedBarLineData.ts +7 -0
  56. package/src/types/RadarData.ts +33 -29
  57. package/src/types/TooltipChartType.ts +7 -6
  58. package/src/vite-env.d.ts +3 -3
  59. package/src/App.vue +0 -80
@@ -0,0 +1,363 @@
1
+ <template>
2
+ <div class="container">
3
+ <div class="main">
4
+ <Bubble
5
+ v-if="chartData"
6
+ ref="bubbleChartRef"
7
+ :id="chartId"
8
+ :data="chartData"
9
+ :options="options"
10
+ :class="cssClasses"
11
+ :style="[{ width, height, cursor: 'pointer' }, styles]"
12
+ />
13
+ </div>
14
+ <div class="chart-legend">
15
+ <img
16
+ src="../../assets/img/bubbles.svg"
17
+ :alt="rAxis.title"
18
+ class="bubble-icon mu-mr-025"
19
+ />
20
+ <div class="size-legend-label">
21
+ {{ rAxis.title }}
22
+ </div>
23
+ </div>
24
+ </div>
25
+ </template>
26
+
27
+ <script setup lang="ts">
28
+ import { computed, PropType } from 'vue';
29
+ import { Bubble } from 'vue-chartjs';
30
+ import ChartDataLabels from 'chartjs-plugin-datalabels';
31
+ import { addAlpha } from '../../services/ColorFunctions';
32
+
33
+ import {
34
+ CategoryScale,
35
+ Chart as ChartJS,
36
+ Legend,
37
+ LinearScale,
38
+ Plugin,
39
+ PointElement,
40
+ Title,
41
+ Tooltip
42
+ } from 'chart.js';
43
+ import ChartDesign from '../../services/patterns/ChartDesign';
44
+ import { Context } from '../../services/GenericTooltipService';
45
+ import { BubbleTooltipService } from '../../services/BubbleTooltipService';
46
+ import { formatWithThousandsSeprators } from '../../services/FormatUtilities';
47
+ import { AxisDefinition } from '../../types/AxisDefinition';
48
+
49
+ ChartJS.register(
50
+ Title,
51
+ Tooltip,
52
+ Legend,
53
+ PointElement,
54
+ CategoryScale,
55
+ LinearScale,
56
+ ChartDataLabels
57
+ );
58
+
59
+ const { colourSets } = ChartDesign();
60
+
61
+ const bubbleDataProps = defineProps({
62
+ /**
63
+ * Value of the id attribute present on the <canvas> tag element the chart
64
+ */
65
+ chartId: {
66
+ type: String,
67
+ default: 'bubble-chart'
68
+ },
69
+ /**
70
+ * Labels used to label the series. See [Data structures documentation](https://www.chartjs.org/docs/latest/general/data-structures.html)
71
+ */
72
+ labels: {
73
+ type: Array as PropType<string[]>,
74
+ default: () => []
75
+ },
76
+ /**
77
+ * Used to choose the colour set of the charts as defined in the Figma prototypes.
78
+ * 7 colour sets are currently defined:
79
+ * - Default 0 corresponds to the current one
80
+ * - 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)
81
+ * Note: All the sets are defined in /src/services/patterns/ChartDesign.ts
82
+ */
83
+ colourSet: {
84
+ type: Number,
85
+ default: 0
86
+ },
87
+ /**
88
+ * 6 colors exist in the colourSet (0 to 5)
89
+ * In some use cases, you may need to specify the colours for each dataset
90
+ */
91
+ colours: {
92
+ type: Array as PropType<number[]>,
93
+ default: () => []
94
+ },
95
+ /**
96
+ * In some use cases, you may need to specify the shapes for each dataset
97
+ * Default shape is circle, implementation is done using the Point Styles of chartjs :
98
+ * cf. https://www.chartjs.org/docs/latest/configuration/elements.html#point-styles
99
+ */
100
+ shapes: {
101
+ type: Array as PropType<string[]>,
102
+ default: () => []
103
+ },
104
+ /**
105
+ * Value of the `datasets` key present in the `data` object passed to the Chart config
106
+ */
107
+ datasets: {
108
+ type: Array as PropType<any[]>,
109
+ default: () => []
110
+ },
111
+ /**
112
+ * Value of the `width` css property used to define the width of the <canvas> element
113
+ */
114
+ width: {
115
+ type: String,
116
+ default: '400px'
117
+ },
118
+ /**
119
+ * Value of the `height` css property used to define the height of the <canvas> element
120
+ */
121
+ height: {
122
+ type: String,
123
+ default: '300px'
124
+ },
125
+ /**
126
+ * Add custom CSS classes to the <canvas> element
127
+ */
128
+ cssClasses: {
129
+ type: String,
130
+ default: undefined
131
+ },
132
+ /**
133
+ * Add custom CSS styles to the <canvas> element
134
+ */
135
+ styles: {
136
+ type: Object as PropType<Partial<CSSStyleDeclaration>>,
137
+ default: () => {}
138
+ },
139
+ /**
140
+ * Minimum size for a bubble
141
+ */
142
+ bubbleMin: {
143
+ type: Number,
144
+ default: 10
145
+ },
146
+ /**
147
+ * Maximum size for a bubble
148
+ */
149
+ bubbleMax: {
150
+ type: Number,
151
+ default: 40
152
+ },
153
+ /**
154
+ * Value of the `plugins` key passed to the Chart config
155
+ */
156
+ plugins: {
157
+ type: Array as PropType<Plugin<any>[]>,
158
+ default: () => []
159
+ },
160
+ /**
161
+ * If set to true the label of the dataserie will be shown on top of the bubble
162
+ */
163
+ displayBubbleLabel: {
164
+ type: Boolean,
165
+ default: false
166
+ },
167
+ /**
168
+ * X axis data : title and unit
169
+ */
170
+ xAxis: {
171
+ type: Object as PropType<AxisDefinition>,
172
+ default: null,
173
+ required: true
174
+ },
175
+ /**
176
+ * Y axis data : title and unit
177
+ */
178
+ yAxis: {
179
+ type: Object as PropType<AxisDefinition>,
180
+ default: null,
181
+ required: true
182
+ },
183
+ /**
184
+ * X axis data : title and unit
185
+ */
186
+ rAxis: {
187
+ type: Object as PropType<AxisDefinition>,
188
+ default: null,
189
+ required: true
190
+ },
191
+ /**
192
+ * Show axis labels
193
+ */
194
+ displayAxisLabels: {
195
+ type: Boolean,
196
+ default: true
197
+ }
198
+ });
199
+
200
+ const normalizeDatasets = function (dataSets: Array<Array<any>>) {
201
+ const rValues: Array<number> = [];
202
+ dataSets.forEach((dataSerie: Array<any>) => {
203
+ dataSerie.forEach((item: any) => {
204
+ rValues.push(item.r);
205
+ });
206
+ });
207
+ const max = Math.max(...rValues);
208
+ const min = Math.min(...rValues);
209
+ const rMax = bubbleDataProps.bubbleMax;
210
+ const rMin = bubbleDataProps.bubbleMin;
211
+
212
+ return dataSets.map((dataSerie: Array<any>) => {
213
+ if (max === min) {
214
+ return dataSerie.map((item) => {
215
+ return {
216
+ x: item.x,
217
+ y: item.y,
218
+ r: rMin + (rMax - rMin) / 2
219
+ };
220
+ });
221
+ } else {
222
+ return dataSerie.map((item) => {
223
+ return {
224
+ x: item.x,
225
+ y: item.y,
226
+ r: rMin + ((item.r - min) * (rMax - rMin)) / (max - min)
227
+ };
228
+ });
229
+ }
230
+ });
231
+ };
232
+
233
+ const chartData = computed(() => {
234
+ const chartColourSet = colourSets[bubbleDataProps.colourSet];
235
+ return {
236
+ datasets: normalizeDatasets(bubbleDataProps.datasets).map(
237
+ (data, index) => ({
238
+ data: data,
239
+ pointStyle: bubbleDataProps.shapes[index],
240
+ backgroundColor: addAlpha(
241
+ chartColourSet[bubbleDataProps.colours[index]],
242
+ 0.2
243
+ ),
244
+ borderColor: chartColourSet[bubbleDataProps.colours[index]],
245
+ label: bubbleDataProps.labels[index]
246
+ })
247
+ )
248
+ };
249
+ });
250
+
251
+ const options = computed(() => ({
252
+ responsive: false,
253
+ // eslint-disable-next-line
254
+ scales: {
255
+ x: {
256
+ offset: true,
257
+ title: {
258
+ display: bubbleDataProps.displayAxisLabels,
259
+ text: bubbleDataProps.xAxis.title
260
+ }
261
+ },
262
+ y: {
263
+ offset: true,
264
+ title: {
265
+ display: bubbleDataProps.displayAxisLabels,
266
+ text: bubbleDataProps.yAxis.title
267
+ }
268
+ }
269
+ },
270
+ plugins: {
271
+ responsive: true,
272
+ maintainAspectRatio: false,
273
+ legend: {
274
+ display: false
275
+ },
276
+ title: {
277
+ display: false
278
+ },
279
+ datalabels: {
280
+ display: bubbleDataProps.displayBubbleLabel,
281
+ anchor: 'end' as const,
282
+ align: 'end' as const,
283
+ color: 'black',
284
+ formatter: function <T extends { dataset: any }>(
285
+ _value: any,
286
+ context: T
287
+ ) {
288
+ return context.dataset.label;
289
+ },
290
+ padding: 0
291
+ },
292
+ tooltip: {
293
+ enabled: false,
294
+ position: 'nearest' as const,
295
+ external: function (context: Context) {
296
+ const datasetIndex: number =
297
+ context.tooltip?.dataPoints?.[0].datasetIndex || 0;
298
+ const dataIndex: number =
299
+ context.tooltip.dataPoints?.[0].dataIndex || 0;
300
+ const currentBubble: { x: number; y: number; r: number } =
301
+ bubbleDataProps.datasets[datasetIndex][dataIndex];
302
+ new BubbleTooltipService().createBubbleTooltip(
303
+ context,
304
+ [
305
+ {
306
+ label: bubbleDataProps.xAxis.title,
307
+ value: `${formatWithThousandsSeprators(currentBubble.x)}`,
308
+ unit: bubbleDataProps.xAxis?.unit
309
+ },
310
+ {
311
+ label: bubbleDataProps.yAxis.title,
312
+ value: `${formatWithThousandsSeprators(currentBubble.y)}`,
313
+ unit: bubbleDataProps.yAxis?.unit
314
+ },
315
+ {
316
+ label: bubbleDataProps.rAxis.title,
317
+ value: `${formatWithThousandsSeprators(currentBubble.r)}`,
318
+ unit: bubbleDataProps.rAxis?.unit
319
+ }
320
+ ],
321
+ bubbleDataProps.labels[datasetIndex]
322
+ );
323
+ }
324
+ }
325
+ }
326
+ }));
327
+ </script>
328
+
329
+ <style lang="scss">
330
+ @import 'settings-tools/all-settings';
331
+ @import 'components/c.checkbox';
332
+ </style>
333
+
334
+ <style scoped>
335
+ .container {
336
+ -moz-osx-font-smoothing: grayscale;
337
+ -webkit-font-smoothing: antialiased;
338
+ font-weight: 400;
339
+ font-family: 'Roboto', sans-serif;
340
+ }
341
+
342
+ .main {
343
+ display: flex;
344
+ flex-direction: column;
345
+ justify-content: center;
346
+ align-items: center;
347
+ margin-bottom: 20px;
348
+ }
349
+
350
+ .chart-legend {
351
+ display: flex;
352
+ gap: 4px;
353
+ font-size: 14px;
354
+ align-items: center;
355
+ margin: 1.375rem 1.0625rem;
356
+ color: rgb(102, 102, 102);
357
+ }
358
+
359
+ .bubble-icon {
360
+ width: 16px;
361
+ height: 16px;
362
+ }
363
+ </style>
@@ -0,0 +1,8 @@
1
+ import type { App } from 'vue';
2
+ import BubbleChart from './BubbleChart.vue';
3
+
4
+ BubbleChart.install = (app: App) => {
5
+ app.component('BubbleChart', BubbleChart);
6
+ };
7
+
8
+ export { BubbleChart };
@@ -1,11 +1,11 @@
1
1
  // DoughnutChart.stories.ts;
2
2
 
3
- import type { Meta, StoryObj } from "@storybook/vue3";
4
- import DoughnutChart from "./DoughnutChart.vue";
3
+ import type { Meta, StoryObj } from '@storybook/vue3';
4
+ import DoughnutChart from './DoughnutChart.vue';
5
5
 
6
6
  const meta = {
7
- title: "Charts/Doughnut",
8
- component: DoughnutChart,
7
+ title: 'Charts/Doughnut',
8
+ component: DoughnutChart
9
9
  } satisfies Meta<typeof DoughnutChart>;
10
10
 
11
11
  export default meta;
@@ -13,70 +13,72 @@ type Story = StoryObj<typeof meta>;
13
13
 
14
14
  export const Default = {
15
15
  args: {
16
- height: "400px",
17
- width: "400px",
18
- labels: ["Data One", "Data Two"],
16
+ height: '400px',
17
+ width: '400px',
18
+ labels: ['Data One', 'Data Two'],
19
+ enableCenteredLabel: true,
19
20
  disableAccessibility: false,
20
21
  data: [
21
22
  {
22
23
  value: 2771824.19,
23
- unit: "",
24
- rate: 30.186240355262925,
24
+ unit: '',
25
+ rate: 30.186240355262925
25
26
  },
26
27
  {
27
28
  value: 1715453.65,
28
- unit: "",
29
- rate: 18.68195550931139,
30
- },
29
+ unit: '',
30
+ rate: 18.68195550931139
31
+ }
31
32
  ],
32
- },
33
+ maxValues: 2
34
+ }
33
35
  } satisfies Story;
34
36
 
35
37
  export const MultipleData = {
36
38
  args: {
37
- height: "400px",
38
- width: "400px",
39
+ height: '400px',
40
+ width: '400px',
39
41
  labels: [
40
- "Data One",
41
- "Data Two",
42
- "Data Three",
43
- "Data Four",
44
- "Data Five",
45
- "Data Six",
42
+ 'Data One',
43
+ 'Data Two',
44
+ 'Data Three',
45
+ 'Data Four',
46
+ 'Data Five',
47
+ 'Data Six'
46
48
  ],
47
49
  maxValues: 3,
48
50
  disableAccessibility: false,
49
51
  data: [
50
52
  {
51
53
  value: 2771824.19,
52
- unit: "",
53
- rate: 30.186240355262925,
54
+ unit: '',
55
+ rate: 30.186240355262925
54
56
  },
55
57
  {
56
58
  value: 1715453.65,
57
- unit: "",
58
- rate: 18.68195550931139,
59
+ unit: '',
60
+ rate: 18.68195550931139
59
61
  },
60
62
  {
61
63
  value: 1651575.28,
62
- unit: "",
63
- rate: 17.986295287685856,
64
+ unit: '',
65
+ rate: 17.986295287685856
64
66
  },
65
67
  {
66
68
  value: 1168958.3,
67
- unit: "",
68
- rate: 12.730409214402426,
69
+ unit: '',
70
+ rate: 12.730409214402426
69
71
  },
70
72
  {
71
73
  value: 949837.87,
72
- unit: "",
73
- rate: 10.34410275579238,
74
+ unit: '',
75
+ rate: 10.34410275579238
74
76
  },
75
77
  {
76
78
  value: 924760.17,
77
- unit: "",
78
- rate: 10.070996877545035,
79
- },
80
- ],
81
- },
79
+ unit: '',
80
+ rate: 10.070996877545035
81
+ }
82
+ ]
83
+ }
82
84
  } satisfies Story;