@mozaic-ds/chart 0.1.0-beta.0 → 0.1.0-beta.10

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 (43) hide show
  1. package/dist/mozaic-chart.js +3390 -2582
  2. package/dist/mozaic-chart.umd.cjs +11 -11
  3. package/dist/style.css +1 -1
  4. package/package.json +38 -24
  5. package/src/components/bar/BarChart.stories.ts +13 -9
  6. package/src/components/bar/BarChart.vue +234 -106
  7. package/src/components/bar/index.ts +8 -0
  8. package/src/components/doughnut/DoughnutChart.stories.ts +3 -0
  9. package/src/components/doughnut/DoughnutChart.vue +205 -95
  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 +310 -219
  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 +231 -126
  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/BarChartFunctions.ts +16 -20
  24. package/src/services/ChartsCommonLegend.ts +54 -47
  25. package/src/services/ColorFunctions.ts +4 -0
  26. package/src/services/DoughnutChartFunctions.ts +111 -59
  27. package/src/services/FormatUtilities.ts +1 -1
  28. package/src/services/GenericTooltipService.ts +55 -34
  29. package/src/services/MixedBarLineFunctions.ts +280 -0
  30. package/src/services/RadarChartFunctions.ts +13 -11
  31. package/src/services/patterns/ChartDesign.ts +15 -9
  32. package/src/services/patterns/patternCircles.ts +63 -50
  33. package/src/services/patterns/patternDashedDiagonals.ts +46 -32
  34. package/src/services/patterns/patternDiagonals.ts +85 -71
  35. package/src/services/patterns/patternSquares.ts +56 -44
  36. package/src/services/patterns/patternVerticalLines.ts +41 -28
  37. package/src/services/patterns/patternZigzag.ts +20 -7
  38. package/src/stories/Changelog.mdx +6 -0
  39. package/src/stories/Contributing.mdx +101 -0
  40. package/src/stories/GettingStarted.mdx +92 -0
  41. package/src/stories/SupportAndOnboarding.mdx +44 -0
  42. package/src/types/MixedBarLineData.ts +7 -0
  43. package/src/types/TooltipChartType.ts +1 -0
package/dist/style.css CHANGED
@@ -1 +1 @@
1
- .container[data-v-3e53e20e]{-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased;font-weight:400;font-family:Roboto,sans-serif}.main[data-v-3e53e20e]{display:flex;flex-direction:column;justify-content:center;align-items:center;margin-bottom:20px}.container[data-v-6b16e20b]{-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased;font-weight:400;font-family:Roboto,sans-serif}.main[data-v-6b16e20b]{display:flex;flex-direction:column;justify-content:center;align-items:center}.container[data-v-2b308814]{-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased;font-weight:400;font-family:Roboto,sans-serif}.main[data-v-2b308814]{display:flex;flex-direction:column;justify-content:center;align-items:center;margin-bottom:20px}.container[data-v-9f1e4973]{-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased;font-weight:400;font-family:Roboto,sans-serif}.main[data-v-9f1e4973]{height:600px;display:flex;flex-direction:column;justify-content:center;align-items:center}
1
+ .mc-checkbox__input:checked{background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' height='1rem' width='1rem' fill='%23ffffff' viewBox='0 0 16 16'%3E%3Cpath d='M7.63 11.21a1 1 0 0 1-1.38 0l-2.92-2.6a1 1 0 1 1 1.34-1.48l2.22 2 4.41-4.34a1 1 0 1 1 1.4 1.42z'/%3E%3C/svg%3E");background-position:center center}.mc-checkbox__input:indeterminate{background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' height='1rem' width='1rem' fill='%23ffffff' viewBox='0 0 16 16'%3E%3Cpath d='M12 9H4a1 1 0 010-2h8a1 1 0 010 2z'/%3E%3C/svg%3E")}.mc-checkbox__input:disabled:checked{background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' height='1rem' width='1rem' fill='%23999999' viewBox='0 0 16 16'%3E%3Cpath d='M7.63 11.21a1 1 0 0 1-1.38 0l-2.92-2.6a1 1 0 1 1 1.34-1.48l2.22 2 4.41-4.34a1 1 0 1 1 1.4 1.42z'/%3E%3C/svg%3E")}.mc-checkbox__input:disabled:indeterminate{background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' height='1rem' width='1rem' fill='%23999999' viewBox='0 0 16 16'%3E%3Cpath d='M12 9H4a1 1 0 010-2h8a1 1 0 010 2z'/%3E%3C/svg%3E")}.container[data-v-fae6dcc9]{-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased;font-weight:400;font-family:Roboto,sans-serif}.main[data-v-fae6dcc9]{display:flex;flex-direction:column;justify-content:center;align-items:center;margin-bottom:20px}.container[data-v-9f73f105]{-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased;font-weight:400;font-family:Roboto,sans-serif}.main[data-v-9f73f105]{display:flex;flex-direction:column;justify-content:center;align-items:center}.container[data-v-9a586c1a]{-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased;font-weight:400;font-family:Roboto,sans-serif}.main[data-v-9a586c1a]{display:flex;flex-direction:column;justify-content:center;align-items:center;margin-bottom:20px}.container[data-v-26475601]{-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased;font-weight:400;font-family:Roboto,sans-serif}.main[data-v-26475601]{height:600px;display:flex;flex-direction:column;justify-content:center;align-items:center}.mc-checkbox{align-items:center;display:flex}.mc-checkbox__label{font-size:1rem;line-height:1.125;cursor:pointer;margin-left:.5rem;color:#000}.mc-checkbox__input{font-family:LeroyMerlin,sans-serif;font-weight:400;box-sizing:border-box;outline:none;-webkit-appearance:none;-moz-appearance:none;appearance:none;padding:0;margin:0;box-shadow:none;border:none;min-width:20px;min-height:20px;width:1.25rem;height:1.25rem;border-radius:4px;border:2px solid #666666;background-color:#fff;position:relative;transition:all .2s ease;cursor:pointer}.mc-checkbox__input[type=number]::-webkit-inner-spin-button,.mc-checkbox__input[type=number]::-webkit-outer-spin-button{-webkit-appearance:none;-moz-appearance:none;appearance:none;margin:0}.mc-checkbox__input[type=number]{-moz-appearance:textfield}.mc-checkbox__input[type=search]::-webkit-search-decoration:hover,.mc-checkbox__input[type=search]::-webkit-search-cancel-button:hover{cursor:pointer}.mc-checkbox__input::-ms-check{background-color:#fff;border:2px solid #666666;border-radius:4px;color:#fff}.mc-checkbox__input:hover{border-color:#191919}.mc-checkbox__input:hover::-ms-check{border-color:#191919}.mc-checkbox__input:focus{box-shadow:0 0 0 .125rem #fff,0 0 0 .25rem #0b96cc}.mc-checkbox__input:focus::-ms-check{box-shadow:0 0 0 .125rem #fff,0 0 0 .25rem #0b96cc}.mc-checkbox__input:checked,.mc-checkbox__input:indeterminate{background-color:#46a610;border-color:#46a610;background-size:1rem 1rem}.mc-checkbox__input:checked{background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' height='1rem' width='1rem' fill='%23ffffff' viewBox='0 0 16 16'%3E%3Cpath d='M7.63 11.21a1 1 0 0 1-1.38 0l-2.92-2.6a1 1 0 1 1 1.34-1.48l2.22 2 4.41-4.34a1 1 0 1 1 1.4 1.42z'/%3E%3C/svg%3E");background-position:center center}.mc-checkbox__input:checked::-ms-check{background-color:#46a610;border-color:#46a610}.mc-checkbox__input:checked:hover:not(:disabled){border-color:#035010}.mc-checkbox__input:checked:hover:not(:disabled)::-ms-check{border-color:#035010}.mc-checkbox__input:indeterminate{background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' height='1rem' width='1rem' fill='%23ffffff' viewBox='0 0 16 16'%3E%3Cpath d='M12 9H4a1 1 0 010-2h8a1 1 0 010 2z'/%3E%3C/svg%3E")}.mc-checkbox__input:disabled{background-color:#e6e6e6;border-color:#e6e6e6;cursor:not-allowed}.mc-checkbox__input:disabled::-ms-check{background-color:#e6e6e6;border-color:#e6e6e6}.mc-checkbox__input:disabled:checked{background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' height='1rem' width='1rem' fill='%23999999' viewBox='0 0 16 16'%3E%3Cpath d='M7.63 11.21a1 1 0 0 1-1.38 0l-2.92-2.6a1 1 0 1 1 1.34-1.48l2.22 2 4.41-4.34a1 1 0 1 1 1.4 1.42z'/%3E%3C/svg%3E")}.mc-checkbox__input:disabled:indeterminate{background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' height='1rem' width='1rem' fill='%23999999' viewBox='0 0 16 16'%3E%3Cpath d='M12 9H4a1 1 0 010-2h8a1 1 0 010 2z'/%3E%3C/svg%3E")}.mc-checkbox__input:disabled+.mc-checkbox__label{color:gray}.mc-checkbox__input.is-invalid{border-color:#c61112}.mc-checkbox__input.is-invalid::-ms-check{border-color:#c61112}.mc-checkbox__input.is-invalid:hover{border-color:#530000}.mc-checkbox__input.is-invalid:hover::-ms-check{border-color:#530000}.container[data-v-0dd46b73]{-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased;font-weight:400;font-family:Roboto,sans-serif}.main[data-v-0dd46b73]{display:flex;flex-direction:column;justify-content:center;align-items:center;margin-bottom:20px}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@mozaic-ds/chart",
3
- "version": "0.1.0-beta.0",
3
+ "version": "0.1.0-beta.10",
4
4
  "type": "module",
5
5
  "scripts": {
6
6
  "build": "vue-tsc && vite build",
@@ -14,10 +14,11 @@
14
14
  "npm:publishBeta": "npm publish --tag beta --access public",
15
15
  "prepublishOnly": "npm run build",
16
16
  "preview": "vite preview",
17
- "release": "dotenv release-it",
18
- "release:beta": "dotenv release-it --preRelease=beta",
17
+ "release": "release-it",
18
+ "release:beta": "release-it --preRelease=beta",
19
19
  "storybook": "storybook dev -p 6006",
20
- "test": "vitest"
20
+ "test": "vitest --run",
21
+ "vitest": "vitest ChartsCommonLegend.test.ts"
21
22
  },
22
23
  "bugs": {
23
24
  "url": "https://github.com/adeo/mozaic-chart/issues"
@@ -25,7 +26,9 @@
25
26
  "homepage": "https://github.com/adeo/mozaic-chart#readme",
26
27
  "files": [
27
28
  "dist/*",
28
- "src/*"
29
+ "src/*",
30
+ "types/*",
31
+ "*.d.ts"
29
32
  ],
30
33
  "main": "./dist/mozaic-chart.umd.cjs",
31
34
  "module": "./dist/mozaic-chart.js",
@@ -33,40 +36,51 @@
33
36
  ".": {
34
37
  "import": "./dist/mozaic-chart.js",
35
38
  "require": "./dist/mozaic-chart.umd.cjs"
39
+ },
40
+ "./dist/style.css": {
41
+ "import": "./dist/style.css",
42
+ "require": "./dist/style.css"
36
43
  }
37
44
  },
38
45
  "dependencies": {
39
- "@mozaic-ds/vue-3": "0.49.3",
40
- "vue": "^3.2.41"
46
+ "@mozaic-ds/vue-3": "0.50.0",
47
+ "chart.js": "^4.3.3",
48
+ "vue": "^3.2.41",
49
+ "vue-chartjs": "5.2.0"
41
50
  },
42
51
  "devDependencies": {
43
- "@babel/core": "^7.22.6",
52
+ "@babel/core": "^7.22.10",
53
+ "@code-hike/mdx": "^0.9.0",
54
+ "@geometricpanda/storybook-addon-badges": "^2.0.0",
44
55
  "@release-it/conventional-changelog": "^7.0.0",
45
- "@storybook/addon-essentials": "^7.0.25",
46
- "@storybook/addon-interactions": "^7.0.25",
47
- "@storybook/addon-links": "^7.0.25",
48
- "@storybook/blocks": "^7.0.25",
56
+ "@storybook/addon-docs": "^7.3.2",
57
+ "@storybook/addon-essentials": "^7.3.2",
58
+ "@storybook/addon-interactions": "^7.3.2",
59
+ "@storybook/addon-links": "^7.3.2",
60
+ "@storybook/blocks": "^7.3.2",
61
+ "@storybook/design-system": "^7.15.15",
49
62
  "@storybook/testing-library": "^0.2.0",
50
- "@storybook/vue3": "^7.0.25",
51
- "@storybook/vue3-vite": "^7.0.25",
63
+ "@storybook/vue3": "^7.3.2",
64
+ "@storybook/vue3-vite": "^7.3.2",
52
65
  "@vitejs/plugin-vue": "^4.2.3",
53
- "@vitest/coverage-c8": "^0.32.4",
54
- "@vue/test-utils": "^2.4.0",
55
- "babel-loader": "^9.1.2",
56
- "chart.js": "^4.3.0",
57
- "chromatic": "^6.19.9",
66
+ "@vitest/coverage-v8": "^0.34.1",
67
+ "@vue/test-utils": "^2.4.1",
68
+ "babel-loader": "^9.1.3",
69
+ "chromatic": "^6.22.0",
58
70
  "dotenv-cli": "^7.2.1",
59
71
  "jsdom": "^22.1.0",
72
+ "mdx-mermaid": "^2.0.0",
73
+ "mermaid": "^10.3.1",
60
74
  "react": "^18.2.0",
61
75
  "react-dom": "^18.2.0",
62
76
  "release-it": "^16.1.3",
63
- "storybook": "^7.0.25",
77
+ "remark-gfm": "^3.0.1",
78
+ "storybook": "^7.3.2",
64
79
  "typescript": "^5.1.6",
65
- "vite": "^4.3.9",
66
- "vitest": "^0.32.4",
67
- "vue-chartjs": "5.2.0",
80
+ "vite": "^4.4.9",
81
+ "vitest": "^0.34.1",
68
82
  "vue-loader": "^17.2.2",
69
- "vue-tsc": "^1.8.3"
83
+ "vue-tsc": "^1.8.8"
70
84
  },
71
85
  "keywords": [
72
86
  "Adeo",
@@ -15,10 +15,12 @@ export const Default = {
15
15
  args: {
16
16
  width: "500px",
17
17
  height: "400px",
18
- rawTitle: "Bar title",
19
- firstTooltip: "content",
20
- secondTooltip: "content2",
18
+ tooltipFirstLineLabel: "content",
19
+ tooltipSecondLineLabel: "content2",
20
+ disableAccessibility: false,
21
+ newPatternsOrder: [0, 4, 1, 2, 3, 5],
21
22
  labels: ["Data One", "Data Two", "Data Three"],
23
+ colourSet: 0,
22
24
  datasets: [
23
25
  {
24
26
  label: "Data One",
@@ -69,9 +71,9 @@ export const MultipleData = {
69
71
  args: {
70
72
  width: "700px",
71
73
  height: "400px",
72
- rawTitle: "Test title",
73
- firstTooltip: "content",
74
- secondTooltip: "content2",
74
+ tooltipFirstLineLabel: "content",
75
+ tooltipSecondLineLabel: "content2",
76
+ disableAccessibility: false,
75
77
  labels: [
76
78
  "Data One",
77
79
  "Data Two",
@@ -86,6 +88,7 @@ export const MultipleData = {
86
88
  "Data Eleven",
87
89
  "Data Twelve",
88
90
  ],
91
+ colourSet: 1,
89
92
  datasets: [
90
93
  {
91
94
  label: "Data One",
@@ -226,11 +229,12 @@ export const StackedBarChart = {
226
229
  args: {
227
230
  width: "700px",
228
231
  height: "400px",
229
- firstTooltip: "content",
230
- secondTooltip: "content2",
231
- rawTitle: "Stacked Bar Chart Title",
232
+ tooltipFirstLineLabel: "content",
233
+ tooltipSecondLineLabel: "content2",
234
+ disableAccessibility: false,
232
235
  stacked: true,
233
236
  labels: ["Category One", "Category Two", "Category Three"],
237
+ colourSet: 3,
234
238
  datasets: [
235
239
  {
236
240
  label: "Dataset One",
@@ -1,16 +1,15 @@
1
1
  <template>
2
2
  <div class="container">
3
3
  <div class="main">
4
- <Bar
4
+ <Bar
5
5
  v-if="chartData"
6
- ref="barChartRef"
7
- :data="chartData"
6
+ ref="barChartRef"
7
+ :id="chartId"
8
+ :data="chartData"
8
9
  :options="options"
9
10
  :plugins="htmlLegendPlugin"
10
- :style="{ width, height }"
11
- :chart-id="chartId"
12
- :cssClasses:="cssClasses"
13
- :styles="styles"
11
+ :class="cssClasses"
12
+ :style="[{ width, height, cursor: 'pointer' }, styles]"
14
13
  />
15
14
  </div>
16
15
  <div ref="legendContainer" />
@@ -19,16 +18,28 @@
19
18
 
20
19
  <script setup lang="ts">
21
20
  import { computed, ref, watch, PropType } from 'vue';
21
+ import { Bar, Chart } from 'vue-chartjs';
22
22
  import type { Ref } from 'vue';
23
- import { Bar } from 'vue-chartjs';
24
23
  import barChartFunctions from '../../services/BarChartFunctions';
25
24
  import type { Context } from '../../services/GenericTooltipService';
26
25
  import { GenericTooltipService } from '../../services/GenericTooltipService';
27
26
  import { TooltipChartType } from '../../types/TooltipChartType';
28
- import { formatTicks, formatWithThousandsSeprators } from '../../services/FormatUtilities';
29
- import { BarElement, CategoryScale, Chart as ChartJS, Legend, LinearScale, Title, Tooltip, Plugin } from 'chart.js';
30
- import { ButtonName } from '../../types/ButtonName';
31
- import { BarData } from "../../types/BarData";
27
+ import {
28
+ formatTicks,
29
+ formatWithThousandsSeprators,
30
+ } from '../../services/FormatUtilities';
31
+ import {
32
+ BarElement,
33
+ CategoryScale,
34
+ Chart as ChartJS,
35
+ Legend,
36
+ LinearScale,
37
+ Title,
38
+ Tooltip,
39
+ Plugin,
40
+ } from 'chart.js';
41
+ import { BarData } from '../../types/BarData';
42
+ import ChartDesign from '../../services/patterns/ChartDesign';
32
43
 
33
44
  ChartJS.register(
34
45
  Title,
@@ -39,62 +50,145 @@ ChartJS.register(
39
50
  LinearScale
40
51
  );
41
52
 
53
+ const { colourSets, patternsStandardList } = ChartDesign();
54
+
42
55
  const legendContainer = ref(null);
43
56
  const selectMode = ref(false);
44
57
  const barDataProps = defineProps({
45
- chartId: {
46
- type: String,
47
- default: "radar-chart",
48
- },
49
- rawTitle: {
50
- type: String,
51
- default: 'sales',
52
- },
53
- unit: {
54
- type: String,
55
- default: '%',
56
- },
57
- labels: {
58
- type: Array as PropType<string[]>,
59
- default: () => []
60
- },
61
- datasets: {
62
- type: Array as PropType<BarData[]>,
63
- default: () => []
64
- },
65
- width: {
66
- type: String,
67
- default: '400px',
68
- },
69
- height: {
70
- type: String,
71
- default: '300px',
72
- },
73
- cssClasses: {
74
- default: "",
75
- type: String,
76
- },
77
- styles: {
78
- type: Object as PropType<Partial<CSSStyleDeclaration>>,
79
- default: () => {},
80
- },
81
- plugins: {
82
- type: Array as PropType<Plugin<"bar">[]>,
83
- default: () => [],
84
- },
85
- stacked: {
86
- type: Boolean,
87
- default: false,
88
- },
89
- firstTooltip: {
90
- type: String,
91
- default: 'content'
92
- },
93
- secondTooltip: {
94
- type: String,
95
- default: 'content2'
96
- }
97
- })
58
+ /**
59
+ * Value of the id attribute present on the <canvas> tag element the chart
60
+ */
61
+ chartId: {
62
+ type: String,
63
+ default: 'radar-chart',
64
+ },
65
+ /**
66
+ * Unit of values on canvas Y axis
67
+ */
68
+ unit: {
69
+ type: String,
70
+ default: '%',
71
+ },
72
+ /**
73
+ * 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
+ */
75
+ labels: {
76
+ type: Array as PropType<string[]>,
77
+ default: () => [],
78
+ },
79
+ /**
80
+ * Used to choose the colour set of the charts as defined in the Figma prototypes.
81
+ * 7 colour sets are currently defined:
82
+ * - Default 0 corresponds to the current one
83
+ * - 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)
84
+ * Note: All the sets are defined in /src/services/patterns/ChartDesign.ts
85
+ */
86
+ colourSet: {
87
+ type: Number,
88
+ default: 0,
89
+ },
90
+ /**
91
+ * 6 patterns exist and are not randomly given but follow the order defined in [patternsStandardList](/src/services/patterns/ChartDesign.ts)
92
+ * Additionally, a pattern has only one possible colour per colour set as defined in the Figma prototype.
93
+ * In some use cases, the chart may need to show a different orders of these patterns, this can be changed using the props newPatternsOrder
94
+ */
95
+ newPatternsOrder: {
96
+ type: Array as PropType<number[]>,
97
+ default: () => [0, 1, 2, 3, 4, 5],
98
+ },
99
+ /**
100
+ * Value of the `datasets` key present in the `data` object passed to the Chart config
101
+ */
102
+ datasets: {
103
+ type: Array as PropType<BarData[]>,
104
+ default: () => [],
105
+ },
106
+ /**
107
+ * Value of the `width` css property used to define the width of the <canvas> element
108
+ */
109
+ width: {
110
+ type: String,
111
+ default: '400px',
112
+ },
113
+ /**
114
+ * Value of the `height` css property used to define the height of the <canvas> element
115
+ */
116
+ height: {
117
+ type: String,
118
+ default: '300px',
119
+ },
120
+ /**
121
+ * Add custom CSS classes to the <canvas> element
122
+ */
123
+ cssClasses: {
124
+ type: String,
125
+ default: undefined,
126
+ },
127
+ /**
128
+ * Add custom CSS styles to the <canvas> element
129
+ */
130
+ styles: {
131
+ type: Object as PropType<Partial<CSSStyleDeclaration>>,
132
+ default: () => {},
133
+ },
134
+ /**
135
+ * Value of the `plugins` key passed to the Chart config
136
+ */
137
+ plugins: {
138
+ type: Array as PropType<Plugin<'bar'>[]>,
139
+ default: () => [],
140
+ },
141
+ /**
142
+ * Activates "stacked" mode
143
+ */
144
+ stacked: {
145
+ type: Boolean,
146
+ default: false,
147
+ },
148
+ /**
149
+ * Disable accessibility patterns
150
+ */
151
+ disableAccessibility: {
152
+ type: Boolean,
153
+ default: false,
154
+ },
155
+ /**
156
+ * Label of the first line in the Tooltip
157
+ */
158
+ tooltipFirstLineLabel: {
159
+ type: String,
160
+ default: 'content',
161
+ },
162
+ /**
163
+ * Label of the second line in the Tooltip
164
+ */
165
+ tooltipSecondLineLabel: {
166
+ type: String,
167
+ default: 'content2',
168
+ },
169
+ });
170
+
171
+ // computed to make the colors list reactive to the props
172
+ const patternsColors = computed(() => {
173
+ return barDataProps.newPatternsOrder.length !== patternsStandardList.length
174
+ ? colourSets[barDataProps.colourSet]
175
+ : barDataProps.newPatternsOrder.map((id) => {
176
+ return colourSets[barDataProps.colourSet][id];
177
+ });
178
+ });
179
+
180
+ // computed to make the patterns list reactive to the props
181
+ const patternsOrderedList = computed(() => {
182
+ return barDataProps.newPatternsOrder.length !== patternsStandardList.length
183
+ ? patternsStandardList
184
+ : barDataProps.newPatternsOrder.map((id) => {
185
+ return patternsStandardList[id];
186
+ });
187
+ });
188
+
189
+ const disablePattern = computed(() => {
190
+ return barDataProps.disableAccessibility;
191
+ });
98
192
 
99
193
  const {
100
194
  onHoverIndex,
@@ -113,12 +207,14 @@ const chartData = computed(() => {
113
207
  datasets: getStackedDatasets(
114
208
  barDataProps.datasets.map((dataset, index) => ({
115
209
  data: getChartData(index, indexOfOthersLabelIfNull.value),
116
- label: barDataProps.datasets[index].label
117
- })
118
- ),
210
+ label: barDataProps.datasets[index].label,
211
+ })),
119
212
  barDataProps.stacked,
213
+ barDataProps.disableAccessibility,
214
+ patternsColors.value,
215
+ patternsOrderedList.value,
120
216
  0
121
- )
217
+ ),
122
218
  };
123
219
  });
124
220
 
@@ -126,43 +222,52 @@ let xValue: string;
126
222
  let yValue: string;
127
223
 
128
224
  const gettooltipContent = (): void => {
129
- xValue = barDataProps.firstTooltip;
130
- yValue = barDataProps.secondTooltip;
225
+ xValue = barDataProps.tooltipFirstLineLabel;
226
+ yValue = barDataProps.tooltipSecondLineLabel;
131
227
  };
132
228
 
133
229
  const indexOfOthersLabelIfNull: Ref<number | null> = computed(() => {
134
230
  const labels = barDataProps.labels;
135
231
  if (labels.includes('other')) {
136
232
  const index = labels.indexOf('other');
137
- if (barDataProps.datasets[0].data[index].rate + '' === '0' &&
138
- barDataProps.datasets[1].data[index].rate + '' === '0') {
233
+ if (
234
+ barDataProps.datasets[0].data[index].rate + '' === '0' &&
235
+ barDataProps.datasets[1].data[index].rate + '' === '0'
236
+ ) {
139
237
  return index;
140
238
  }
141
239
  }
142
240
  return null;
143
241
  });
144
242
 
145
- const getChartData = (index: number, indexOfValueToHide: number | null, isStacked: boolean = false) => {
243
+ const getChartData = (
244
+ index: number,
245
+ indexOfValueToHide: number | null,
246
+ isStacked: boolean = false
247
+ ) => {
146
248
  const data = Object.assign([], barDataProps.datasets[index].data);
147
249
  if (indexOfValueToHide && indexOfOthersLabelIfNull.value) {
148
250
  data.splice(indexOfOthersLabelIfNull.value, 1);
149
251
  }
150
-
151
- return data.map((data: { rate: number }) => data.rate);
252
+
253
+ return data.map((data: { rate?: number, amount?: number}) =>
254
+ barDataProps.unit === '%' ? data.rate : data.amount
255
+ );
152
256
  };
153
257
 
154
258
  const getTooltipData = (context: Context) => {
155
- const datasetIndex = context.tooltip.dataPoints[0].datasetIndex;
156
- const dataIndex = context.tooltip.dataPoints[0].dataIndex;
157
- const percent = parseFloat(context.tooltip.body[0].lines[0].split(':')[1].replace(',', '.')).toFixed(2) +
158
- '% ';
159
- if (!dataIndex || !datasetIndex) {
160
- return '';
161
- }
162
- const rawdata =
163
- barDataProps.datasets[datasetIndex].data[dataIndex];
164
- const data = formatWithThousandsSeprators(rawdata.amount);
165
- return percent + data + rawdata.amountUnit;
259
+ const datasetIndex = context.tooltip.dataPoints[0].datasetIndex as number;
260
+ const dataIndex = context.tooltip.dataPoints[0].dataIndex as number;
261
+ const rate: string = context.tooltip.body[0].lines[0].split(':')[1];
262
+ const rawdata = barDataProps.datasets[datasetIndex].data[dataIndex];
263
+ const percent = rawdata.rate
264
+ ? parseFloat(rate.replace(',', '.')).toFixed(2) + '% '
265
+ : '';
266
+ const amountUnit = rawdata.amountUnit ? rawdata.amountUnit : '';
267
+ const data = rawdata.amount
268
+ ? formatWithThousandsSeprators(rawdata.amount)
269
+ : '';
270
+ return percent + (percent && data ? '/ ' : '') + data + amountUnit;
166
271
  };
167
272
 
168
273
  const getChartLabels = (indexOfValueToHide: number | null) => {
@@ -179,8 +284,8 @@ const options = computed(() => ({
179
284
  onHover: getOnHoverOptions(),
180
285
  elements: {
181
286
  bar: {
182
- borderSkipped: false
183
- }
287
+ borderSkipped: false,
288
+ },
184
289
  },
185
290
  plugins: {
186
291
  responsive: true,
@@ -189,7 +294,7 @@ const options = computed(() => ({
189
294
  display: false,
190
295
  },
191
296
  title: {
192
- display: false
297
+ display: false,
193
298
  },
194
299
  tooltip: {
195
300
  enabled: false,
@@ -201,35 +306,58 @@ const options = computed(() => ({
201
306
  {
202
307
  chartType: TooltipChartType.BAR_CHART,
203
308
  firstLineLabel: xValue,
204
- secondLineLabel: yValue
205
- }
309
+ secondLineLabel: yValue,
310
+ },
311
+ patternsColors.value,
312
+ patternsOrderedList.value,
313
+ barDataProps.disableAccessibility
206
314
  );
207
- }
208
- }
315
+ },
316
+ },
209
317
  },
210
318
  scales: {
211
319
  x: {
212
- stacked: true,
320
+ stacked: barDataProps.stacked,
213
321
  },
214
322
  y: {
215
- stacked: true,
323
+ stacked: barDataProps.stacked,
216
324
  ticks: {
217
325
  callback: function (val: string | number) {
218
- return formatTicks(val as number, barDataProps.unit);
326
+ return barDataProps.unit === '%'
327
+ ? formatTicks(val as number, barDataProps.unit)
328
+ : formatWithThousandsSeprators(val as number) +
329
+ ' ' +
330
+ barDataProps.unit;
219
331
  },
220
- maxTicksLimit: 8,
221
- }
222
- }
223
- }
332
+ },
333
+ },
334
+ },
224
335
  }));
225
336
 
226
- const htmlLegendPlugin = privateGetHtmlLegendPlugin(legendContainer, selectMode);
337
+ const htmlLegendPlugin = ref(
338
+ privateGetHtmlLegendPlugin(
339
+ legendContainer,
340
+ selectMode,
341
+ disablePattern,
342
+ patternsColors,
343
+ patternsOrderedList
344
+ )
345
+ );
227
346
 
228
- watch(onHoverIndex, () => {
229
- reloadChart();
230
- }, { deep: true });
347
+ watch(
348
+ onHoverIndex,
349
+ () => {
350
+ reloadChart();
351
+ },
352
+ { deep: true }
353
+ );
231
354
  </script>
232
355
 
356
+ <style lang="scss">
357
+ @import 'settings-tools/all-settings';
358
+ @import 'components/c.checkbox';
359
+ </style>
360
+
233
361
  <style scoped>
234
362
  .container {
235
363
  -moz-osx-font-smoothing: grayscale;
@@ -244,4 +372,4 @@ watch(onHoverIndex, () => {
244
372
  align-items: center;
245
373
  margin-bottom: 20px;
246
374
  }
247
- </style>
375
+ </style>
@@ -0,0 +1,8 @@
1
+ import type { App } from "vue";
2
+ import BarChart from "./BarChart.vue";
3
+
4
+ BarChart.install = (app: App) => {
5
+ app.component("BarChart", BarChart);
6
+ };
7
+
8
+ export { BarChart };
@@ -16,6 +16,7 @@ export const Default = {
16
16
  height: "400px",
17
17
  width: "400px",
18
18
  labels: ["Data One", "Data Two"],
19
+ disableAccessibility: false,
19
20
  data: [
20
21
  {
21
22
  value: 2771824.19,
@@ -28,6 +29,7 @@ export const Default = {
28
29
  rate: 18.68195550931139,
29
30
  },
30
31
  ],
32
+ maxValues: 2,
31
33
  },
32
34
  } satisfies Story;
33
35
 
@@ -44,6 +46,7 @@ export const MultipleData = {
44
46
  "Data Six",
45
47
  ],
46
48
  maxValues: 3,
49
+ disableAccessibility: false,
47
50
  data: [
48
51
  {
49
52
  value: 2771824.19,