@mozaic-ds/chart 0.1.0-beta.29 → 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 (56) hide show
  1. package/README.md +1 -1
  2. package/dist/mozaic-chart.js +2303 -2109
  3. package/dist/mozaic-chart.umd.cjs +9 -9
  4. package/dist/style.css +1 -1
  5. package/package.json +1 -1
  6. package/src/assets/base.css +1 -1
  7. package/src/components/bar/BarChart.stories.ts +99 -99
  8. package/src/components/bar/BarChart.vue +70 -53
  9. package/src/components/bar/index.ts +3 -3
  10. package/src/components/bubble/BubbleChart.stories.ts +12 -12
  11. package/src/components/bubble/BubbleChart.vue +118 -91
  12. package/src/components/bubble/index.ts +3 -3
  13. package/src/components/doughnut/DoughnutChart.stories.ts +38 -37
  14. package/src/components/doughnut/DoughnutChart.vue +89 -71
  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 +38 -38
  18. package/src/components/line/LineChart.vue +54 -51
  19. package/src/components/line/index.ts +3 -3
  20. package/src/components/mixed/MixedBarLineChart.stories.ts +15 -15
  21. package/src/components/mixed/MixedBarLineChart.vue +44 -44
  22. package/src/components/mixed/index.ts +1 -1
  23. package/src/components/radar/RadarChart.stories.ts +100 -100
  24. package/src/components/radar/RadarChart.vue +41 -34
  25. package/src/components/radar/index.ts +3 -3
  26. package/src/main.ts +14 -7
  27. package/src/plugin.ts +9 -9
  28. package/src/services/BarChartFunctions.ts +133 -35
  29. package/src/services/BubbleTooltipService.ts +58 -56
  30. package/src/services/ChartsCommonLegend.ts +271 -127
  31. package/src/services/ColorFunctions.ts +1 -1
  32. package/src/services/DoughnutChartFunctions.ts +42 -13
  33. package/src/services/FormatUtilities.ts +28 -14
  34. package/src/services/GenericTooltipService.ts +125 -65
  35. package/src/services/MixedBarLineFunctions.ts +46 -44
  36. package/src/services/PatternFunctions.ts +25 -18
  37. package/src/services/RadarChartFunctions.ts +5 -5
  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 +2 -2
  46. package/src/stories/Contributing.mdx +2 -2
  47. package/src/stories/GettingStarted.mdx +5 -5
  48. package/src/stories/SupportAndOnboarding.mdx +6 -6
  49. package/src/types/AxisDefinition.ts +0 -2
  50. package/src/types/Chart.ts +9 -7
  51. package/src/types/DoughnutData.ts +8 -0
  52. package/src/types/GenericData.ts +10 -10
  53. package/src/types/LineChart.ts +4 -4
  54. package/src/types/RadarData.ts +33 -29
  55. package/src/types/TooltipChartType.ts +7 -7
  56. package/src/vite-env.d.ts +3 -3
@@ -7,35 +7,41 @@
7
7
  :id="chartId"
8
8
  :data="doughnutChartData"
9
9
  :options="options"
10
- :plugins="htmlLegendPlugin"
10
+ :plugins="doughnutPlugins"
11
11
  :max-values="maxValues"
12
12
  :class="cssClasses"
13
13
  :style="[{ width, height, cursor: 'pointer' }, styles]"
14
14
  />
15
+ <span v-if="enableCenteredLabel" class="centered-label">
16
+ {{ centeredLabel }}
17
+ </span>
15
18
  </div>
16
19
  <div ref="legendContainer" />
17
20
  </div>
18
21
  </template>
19
22
 
20
23
  <script setup lang="ts">
21
- import { onMounted, watch } from 'vue';
24
+ import { watch } from 'vue';
22
25
  import { Doughnut } from 'vue-chartjs';
23
26
  import { computed, ref, PropType } from 'vue';
24
- import type { DoughnutData } from '../../types/DoughnutData';
25
- import { TooltipChartType } from '../../types/TooltipChartType';
26
- import type { Context } from '../../services/GenericTooltipService';
27
- import doughnutChartFunction from '../../services/DoughnutChartFunctions';
28
- import { GenericTooltipService } from '../../services/GenericTooltipService';
29
- import { formatWithThousandsSeprators } from '../../services/FormatUtilities';
30
- import type { GenericData } from '../../types/GenericData';
31
- import ChartDesign from '../../services/patterns/ChartDesign';
27
+ import type {
28
+ DoughnutChartData,
29
+ DoughnutData,
30
+ DoughnutPlugin
31
+ } from '@/types/DoughnutData';
32
+ import { TooltipChartType } from '@/types/TooltipChartType';
33
+ import type { Context } from '@/services/GenericTooltipService';
34
+ import doughnutChartFunction from '@/services/DoughnutChartFunctions';
35
+ import { GenericTooltipService } from '@/services/GenericTooltipService';
36
+ import { formatWithThousandsSeprators } from '@/services/FormatUtilities';
37
+ import ChartDesign from '@/services/patterns/ChartDesign';
32
38
  import {
33
39
  Chart as ChartJS,
34
40
  Title,
35
41
  Tooltip,
36
42
  Legend,
37
43
  ArcElement,
38
- Plugin,
44
+ Plugin
39
45
  } from 'chart.js';
40
46
  ChartJS.register(Title, Tooltip, Legend, ArcElement);
41
47
 
@@ -44,12 +50,14 @@ const { colourSets, patternsStandardList } = ChartDesign();
44
50
  const {
45
51
  onHoverIndex,
46
52
  doughnutRef,
53
+ centeredLabel,
47
54
  getBackgroundColor,
48
55
  privateGetHtmlLegendPlugin,
56
+ getCenteredLabelPlugin,
49
57
  getOnHoverOptions,
50
58
  groupDataAfterNthValue,
51
59
  getDoughnutLabels,
52
- getBorderColor,
60
+ getBorderColor
53
61
  } = doughnutChartFunction();
54
62
  const selectMode = ref(false);
55
63
  const legendContainer = ref<HTMLElement | null>(null);
@@ -60,42 +68,49 @@ const doughnutDataProps = defineProps({
60
68
  */
61
69
  chartId: {
62
70
  type: String,
63
- default: 'doughnut-chart',
71
+ default: 'doughnut-chart'
64
72
  },
65
73
  /**
66
74
  * Data to be passed to Chart
67
75
  */
68
76
  data: {
69
77
  type: Array as PropType<DoughnutData[]>,
70
- default: () => [],
78
+ default: () => []
71
79
  },
72
80
  /**
73
81
  * Labels used to label the index axis (default x axes). See [Data structures documentation](https://www.chartjs.org/docs/latest/general/data-structures.html)
74
82
  */
75
83
  labels: {
76
84
  type: Array as PropType<string[]>,
77
- default: () => [],
85
+ default: () => []
78
86
  },
79
87
  /**
80
88
  * Add custom CSS classes to the <canvas> element
81
89
  */
82
90
  cssClasses: {
83
91
  type: String,
84
- default: undefined,
92
+ default: undefined
93
+ },
94
+ /**
95
+ * Add centered label in the middle of the <canvas> element
96
+ */
97
+ enableCenteredLabel: {
98
+ type: Boolean,
99
+ default: false
85
100
  },
86
101
  /**
87
102
  * Disable accessibility patterns
88
103
  */
89
104
  disableAccessibility: {
90
105
  type: Boolean,
91
- default: false,
106
+ default: false
92
107
  },
93
108
  /**
94
109
  * Enable hover feature (may cause strange behavior when used with width and height in %)
95
110
  */
96
- enableHoverFeature: {
111
+ enableHoverFeature: {
97
112
  type: Boolean,
98
- default: false,
113
+ default: false
99
114
  },
100
115
  /**
101
116
  * Used to choose the colour set of the charts as defined in the Figma prototypes.
@@ -106,7 +121,7 @@ const doughnutDataProps = defineProps({
106
121
  */
107
122
  colourSet: {
108
123
  type: Number,
109
- default: 0,
124
+ default: 0
110
125
  },
111
126
  /**
112
127
  * 6 patterns exist and are not randomly given but follow the order defined in [patternsStandardList](/src/services/patterns/ChartDesign.ts)
@@ -115,52 +130,56 @@ const doughnutDataProps = defineProps({
115
130
  */
116
131
  newPatternsOrder: {
117
132
  type: Array as PropType<number[]>,
118
- default: () => [0, 1, 2, 3, 4, 5],
133
+ default: () => [0, 1, 2, 3, 4, 5]
119
134
  },
120
135
  /**
121
136
  * Value of the `width` css property used to define the width of the <canvas> element
122
137
  */
123
138
  width: {
124
139
  type: String,
125
- default: '400px',
140
+ default: '400px'
126
141
  },
127
142
  /**
128
143
  * Value of the `height` css property used to define the height of the <canvas> element
129
144
  */
130
145
  height: {
131
146
  type: String,
132
- default: '400px',
147
+ default: '400px'
133
148
  },
134
149
  /**
135
150
  * Maximum number of data to be displayed in the Chart
136
151
  */
137
152
  maxValues: {
138
153
  type: Number,
139
- default: 5,
154
+ default: 5
140
155
  },
141
156
  /**
142
157
  * Add custom CSS styles to the <canvas> element
143
158
  */
144
159
  styles: {
145
160
  type: Object as PropType<Partial<CSSStyleDeclaration>>,
146
- default: () => {},
161
+ default: () => {}
147
162
  },
148
163
  /**
149
164
  * Value of the `plugins` key passed to the Chart config
150
165
  */
151
166
  plugins: {
152
167
  type: Array as PropType<Plugin<'doughnut'>[]>,
153
- default: () => [],
168
+ default: () => []
154
169
  },
155
170
  /**
156
171
  * Value of the 'others' label if maxValue is reached
157
172
  */
158
173
  othersLabel: {
159
174
  type: String,
160
- default: 'others',
161
- },
175
+ default: 'others'
176
+ }
162
177
  });
163
178
 
179
+ const groupedData = computed(() =>
180
+ groupDataAfterNthValue(doughnutDataProps.data, doughnutDataProps.maxValues)
181
+ );
182
+
164
183
  const patternsColors = computed(() => {
165
184
  return doughnutDataProps.newPatternsOrder.length !== 6
166
185
  ? colourSets[doughnutDataProps.colourSet]
@@ -177,7 +196,7 @@ const patternsOrderedList = computed(() => {
177
196
  });
178
197
  });
179
198
 
180
- const doughnutChartData = computed<any>(() => {
199
+ const doughnutChartData = computed<DoughnutChartData>(() => {
181
200
  return {
182
201
  labels: getDoughnutLabels(
183
202
  doughnutDataProps.labels,
@@ -187,28 +206,26 @@ const doughnutChartData = computed<any>(() => {
187
206
  ),
188
207
  datasets: [
189
208
  {
190
- data: groupDataAfterNthValue(
191
- doughnutDataProps.data,
192
- doughnutDataProps.maxValues
193
- ).map((x: GenericData) => x.rate),
209
+ data: groupedData.value.map((x) => x.rate),
210
+ raw_value: groupedData.value.map((x) => x.value),
194
211
  backgroundColor: getBackgroundColor(
195
212
  patternsColors.value,
196
213
  patternsOrderedList.value,
197
214
  doughnutDataProps.disableAccessibility,
198
215
  doughnutDataProps.enableHoverFeature
199
216
  ),
200
- borderColor: getBorderColor(patternsColors.value, doughnutDataProps.enableHoverFeature),
201
- },
202
- ],
217
+ borderColor: getBorderColor(
218
+ patternsColors.value,
219
+ doughnutDataProps.enableHoverFeature
220
+ )
221
+ }
222
+ ]
203
223
  };
204
224
  });
205
225
 
206
226
  const getTooltipData = (context: Context) => {
207
227
  const dataIndex = context.tooltip.dataPoints[0].dataIndex as number;
208
- const tooltipData = groupDataAfterNthValue(
209
- doughnutDataProps.data,
210
- doughnutDataProps.maxValues
211
- )[dataIndex];
228
+ const tooltipData = groupedData.value[dataIndex];
212
229
  const rate = formatWithThousandsSeprators(tooltipData.rate);
213
230
  const value = formatWithThousandsSeprators(tooltipData.value);
214
231
  const unit = tooltipData.unit || '';
@@ -219,25 +236,25 @@ function getSpacing() {
219
236
  return doughnutDataProps.labels.length <= 1 ? 0 : 12;
220
237
  }
221
238
 
222
- // @ts-ignore
223
239
  const options = computed(() => {
224
240
  const colors = patternsColors.value;
225
241
  const patterns = patternsOrderedList.value;
226
242
  return {
227
- onHover: doughnutDataProps.enableHoverFeature? getOnHoverOptions() : () => {},
243
+ onHover: doughnutDataProps.enableHoverFeature
244
+ ? getOnHoverOptions()
245
+ : () => {},
228
246
  plugins: {
229
247
  legend: {
230
248
  display: false,
231
- // @ts-ignore
232
- position: 'bottom' as const,
233
- align: 'start' as const,
249
+ position: 'bottom',
250
+ align: 'start',
234
251
  labels: {
235
252
  pointStyle: 'rectRounded',
236
- usePointStyle: true,
237
- },
253
+ usePointStyle: true
254
+ }
238
255
  },
239
256
  title: {
240
- display: false,
257
+ display: false
241
258
  },
242
259
  datalabels: {
243
260
  display: false
@@ -249,35 +266,35 @@ const options = computed(() => {
249
266
  context,
250
267
  getTooltipData,
251
268
  {
252
- chartType: TooltipChartType.DOUGHNUT,
269
+ chartType: TooltipChartType.DOUGHNUT
253
270
  },
254
271
  colors,
255
272
  patterns,
256
273
  disablePattern.value
257
274
  );
258
- },
259
- },
275
+ }
276
+ }
260
277
  },
261
278
  radius: '90%',
262
279
  cutout: '70%',
263
280
  borderWidth: 3,
264
281
  spacing: getSpacing(),
265
- hoverOffset: 4,
266
- };
282
+ hoverOffset: 4
283
+ } as const;
267
284
  });
268
285
 
269
286
  const doughnutDataAndLabels = {
270
287
  data: doughnutDataProps.data,
271
- labels: doughnutDataProps.labels,
288
+ labels: doughnutDataProps.labels
272
289
  };
273
290
  const disablePattern = computed(() => {
274
291
  return doughnutDataProps.disableAccessibility;
275
292
  });
276
293
  const enableHover = computed(() => {
277
294
  return doughnutDataProps.enableHoverFeature;
278
- })
295
+ });
279
296
 
280
- const htmlLegendPlugin = computed(() =>
297
+ const doughnutPlugins = computed<DoughnutPlugin[]>(() => [
281
298
  privateGetHtmlLegendPlugin(
282
299
  legendContainer,
283
300
  selectMode,
@@ -287,17 +304,10 @@ const htmlLegendPlugin = computed(() =>
287
304
  doughnutDataProps.maxValues,
288
305
  doughnutDataAndLabels,
289
306
  enableHover
290
- )
291
- );
307
+ ) as unknown as DoughnutPlugin,
308
+ getCenteredLabelPlugin(doughnutDataProps.data)
309
+ ]);
292
310
 
293
- onMounted(() => {
294
- getBackgroundColor(
295
- patternsColors.value,
296
- patternsOrderedList.value,
297
- doughnutDataProps.disableAccessibility,
298
- enableHover.value
299
- );
300
- });
301
311
  watch(onHoverIndex, (newValue, oldValue) => {
302
312
  if (newValue !== oldValue && enableHover.value) {
303
313
  getBackgroundColor(
@@ -319,7 +329,7 @@ watch(disablePattern, () => {
319
329
  });
320
330
  </script>
321
331
 
322
- <style scoped>
332
+ <style lang="scss" scoped>
323
333
  .container {
324
334
  -moz-osx-font-smoothing: grayscale;
325
335
  -webkit-font-smoothing: antialiased;
@@ -328,9 +338,17 @@ watch(disablePattern, () => {
328
338
  }
329
339
 
330
340
  .main {
331
- display: flex;
332
- flex-direction: column;
333
- justify-content: center;
334
- align-items: center;
341
+ display: grid;
342
+ place-items: center;
343
+
344
+ canvas {
345
+ grid-area: 1 / 1;
346
+ }
347
+
348
+ .centered-label {
349
+ grid-area: 1 / 1;
350
+ place-self: center;
351
+ text-align: center;
352
+ }
335
353
  }
336
354
  </style>
@@ -1,8 +1,8 @@
1
- import type { App } from "vue";
2
- import DoughnutChart from "./DoughnutChart.vue";
1
+ import type { App } from 'vue';
2
+ import DoughnutChart from './DoughnutChart.vue';
3
3
 
4
4
  DoughnutChart.install = (app: App) => {
5
- app.component("DoughnutChart", DoughnutChart);
5
+ app.component('DoughnutChart', DoughnutChart);
6
6
  };
7
7
 
8
8
  export { DoughnutChart };
@@ -1,4 +1,4 @@
1
- export { BarChart } from "./bar";
2
- export { DoughnutChart } from "./doughnut";
3
- export { LineChart } from "./line";
4
- export { RadarChart } from "./radar";
1
+ export { BarChart } from './bar';
2
+ export { DoughnutChart } from './doughnut';
3
+ export { LineChart } from './line';
4
+ export { RadarChart } from './radar';
@@ -1,11 +1,11 @@
1
1
  // LineChart.stories.ts;
2
2
 
3
- import type { Meta, StoryObj } from "@storybook/vue3";
4
- import LineChart from "./LineChart.vue";
3
+ import type { Meta, StoryObj } from '@storybook/vue3';
4
+ import LineChart from './LineChart.vue';
5
5
 
6
6
  const meta = {
7
- title: "Charts/Line",
8
- component: LineChart,
7
+ title: 'Charts/Line',
8
+ component: LineChart
9
9
  } satisfies Meta<typeof LineChart>;
10
10
 
11
11
  export default meta;
@@ -13,73 +13,73 @@ type Story = StoryObj<typeof meta>;
13
13
 
14
14
  export const Default = {
15
15
  args: {
16
- width: "600px",
17
- height: "400px",
18
- labels: ["Data One", "Data Two", "Data Three"],
16
+ width: '600px',
17
+ height: '400px',
18
+ labels: ['Data One', 'Data Two', 'Data Three'],
19
19
  lines: [
20
20
  {
21
- label: "Data One",
21
+ label: 'Data One',
22
22
  data: [-22, 34, 11],
23
- unit: "%",
23
+ unit: '%'
24
24
  },
25
25
  {
26
- label: "Data Two",
26
+ label: 'Data Two',
27
27
  data: [-3, 28, 35],
28
- unit: "%",
29
- },
28
+ unit: '%'
29
+ }
30
30
  ],
31
31
  xAxisTitle: 'X Axis Title',
32
- yAxisTitle: 'Y Axis Title',
33
- },
32
+ yAxisTitle: 'Y Axis Title'
33
+ }
34
34
  } satisfies Story;
35
35
 
36
36
  export const MultipleData = {
37
37
  args: {
38
- width: "600px",
39
- height: "400px",
38
+ width: '600px',
39
+ height: '400px',
40
40
  labels: [
41
- "Data One",
42
- "Data Two",
43
- "Data Three",
44
- "Data Four",
45
- "Data Five",
46
- "Data Six",
41
+ 'Data One',
42
+ 'Data Two',
43
+ 'Data Three',
44
+ 'Data Four',
45
+ 'Data Five',
46
+ 'Data Six'
47
47
  ],
48
48
  lines: [
49
49
  {
50
- label: "Data One",
50
+ label: 'Data One',
51
51
  data: [-22, 34, 11, 1, 22, 21],
52
- unit: "%",
52
+ unit: '%'
53
53
  },
54
54
  {
55
- label: "Data Two",
55
+ label: 'Data Two',
56
56
  data: [-3, 28, 35, 10, 3, 18],
57
- unit: "%",
58
- },
59
- ],
60
- },
57
+ unit: '%'
58
+ }
59
+ ]
60
+ }
61
61
  } satisfies Story;
62
62
 
63
63
  export const LineChartWithSuggestedMinAndSuggestedMax = {
64
64
  args: {
65
- width: "600px",
66
- height: "400px",
67
- labels: ["Data One", "Data Two", "Data Three"],
65
+ width: '600px',
66
+ height: '400px',
67
+ labels: ['Data One', 'Data Two', 'Data Three'],
68
68
  lines: [
69
69
  {
70
- label: "Data One",
70
+ label: 'Data One',
71
71
  data: [20, 34, 11],
72
- unit: "",
72
+ unit: ''
73
73
  },
74
74
  {
75
- label: "Data Two",
75
+ label: 'Data Two',
76
76
  data: [45, 28, 35],
77
- unit: "",
78
- },
77
+ unit: ''
78
+ }
79
79
  ],
80
80
  xAxisTitle: 'X Axis Title',
81
81
  yAxisTitle: 'Y Axis Title',
82
82
  suggestedMin: 0,
83
83
  suggestedMax: 50
84
- },
84
+ }
85
85
  } satisfies Story;