Skip to content

Commit 752407e

Browse files
authored
feat: events utils (#963)
utils to handle chart clicks were added
1 parent 5bd9805 commit 752407e

File tree

10 files changed

+306
-1
lines changed

10 files changed

+306
-1
lines changed

.size-limit.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
[
22
{
33
"path": "dist/index.js",
4-
"limit": "1.7 KB",
4+
"limit": "1.9 KB",
55
"webpack": false,
66
"running": false
77
},

sandboxes/events/index.html

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
<!DOCTYPE html>
2+
<html lang="en">
3+
<head>
4+
<meta charset="UTF-8" />
5+
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
6+
<script type="module" defer src="./index.ts"></script>
7+
</head>
8+
<body>
9+
<div id="app"></div>
10+
</body>
11+
</html>

sandboxes/events/index.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
import { createApp } from 'vue'
2+
import App from './src/App.vue'
3+
4+
createApp(App).mount('#app')

sandboxes/events/package.json

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
{
2+
"type": "module",
3+
"scripts": {
4+
"start": "vite"
5+
},
6+
"dependencies": {
7+
"chart.js": "^4.0.0",
8+
"vue": "^3.2.31",
9+
"vue-chartjs": "^5.0.0"
10+
},
11+
"devDependencies": {
12+
"@vitejs/plugin-vue": "^3.0.1",
13+
"typescript": "^4.9.3",
14+
"vite": "^3.2.4"
15+
}
16+
}

sandboxes/events/src/App.vue

Lines changed: 89 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,89 @@
1+
<template>
2+
<Chart
3+
ref="chartRef"
4+
type="bar"
5+
:data="data"
6+
:options="options"
7+
@click="onClick"
8+
/>
9+
</template>
10+
11+
<script lang="ts">
12+
import { ref } from 'vue'
13+
import {
14+
Chart as ChartJS,
15+
Title,
16+
Tooltip,
17+
Legend,
18+
BarElement,
19+
CategoryScale,
20+
LinearScale,
21+
InteractionItem
22+
} from 'chart.js'
23+
import {
24+
ChartComponentRef,
25+
Chart,
26+
getDatasetAtEvent,
27+
getElementAtEvent,
28+
getElementsAtEvent
29+
} from 'vue-chartjs'
30+
import * as chartConfig from './chartConfig.js'
31+
32+
ChartJS.register(CategoryScale, LinearScale, BarElement, Title, Tooltip, Legend)
33+
34+
export default {
35+
name: 'App',
36+
components: {
37+
Chart
38+
},
39+
setup() {
40+
const datasetAtEvent = (dataset: InteractionItem[]) => {
41+
if (!dataset.length) return
42+
43+
const datasetIndex = dataset[0].datasetIndex
44+
45+
console.log('dataset', chartConfig.data.datasets[datasetIndex].label)
46+
}
47+
48+
const elementAtEvent = (element: InteractionItem[]) => {
49+
if (!element.length) return
50+
51+
const { datasetIndex, index } = element[0]
52+
53+
console.log(
54+
'element',
55+
chartConfig.data.labels[index],
56+
chartConfig.data.datasets[datasetIndex].data[index]
57+
)
58+
}
59+
60+
const elementsAtEvent = (elements: InteractionItem[]) => {
61+
if (!elements.length) return
62+
63+
console.log('elements', elements)
64+
}
65+
66+
const chartRef = ref<ChartComponentRef>(null)
67+
68+
const onClick = (event: MouseEvent) => {
69+
const {
70+
value: { chart }
71+
} = chartRef
72+
73+
if (!chart) {
74+
return
75+
}
76+
77+
datasetAtEvent(getDatasetAtEvent(chart, event))
78+
elementAtEvent(getElementAtEvent(chart, event))
79+
elementsAtEvent(getElementsAtEvent(chart, event))
80+
}
81+
82+
return {
83+
chartRef,
84+
onClick,
85+
...chartConfig
86+
}
87+
}
88+
}
89+
</script>

sandboxes/events/src/chartConfig.ts

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
export const data = {
2+
labels: [
3+
'January',
4+
'February',
5+
'March',
6+
'April',
7+
'May',
8+
'June',
9+
'July',
10+
'August',
11+
'September',
12+
'October',
13+
'November',
14+
'December'
15+
],
16+
datasets: [
17+
{
18+
label: 'Data One',
19+
backgroundColor: '#f87979',
20+
data: [40, 20, 12, 39, 10, 40, 39, 80, 40, 20, 12, 11]
21+
}
22+
]
23+
}
24+
25+
export const options = {
26+
responsive: true,
27+
maintainAspectRatio: false
28+
}

sandboxes/events/vite.config.js

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
import { defineConfig } from 'vite'
2+
import vue from '@vitejs/plugin-vue'
3+
4+
export default defineConfig({
5+
plugins: [vue()]
6+
})

src/index.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,11 @@ import {
1212
} from './typedCharts.js'
1313

1414
export type { ChartProps, ChartComponentRef } from './types.js'
15+
export {
16+
getDatasetAtEvent,
17+
getElementAtEvent,
18+
getElementsAtEvent
19+
} from './utils.js'
1520
export {
1621
Chart,
1722
createTypedChart,

src/utils.ts

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -91,3 +91,48 @@ export function cloneData<
9191

9292
return nextData
9393
}
94+
95+
/**
96+
* Get dataset from mouse click event
97+
* @param chart - Chart.js instance
98+
* @param event - Mouse click event
99+
* @returns Dataset
100+
*/
101+
export function getDatasetAtEvent(chart: Chart, event: MouseEvent) {
102+
return chart.getElementsAtEventForMode(
103+
event,
104+
'dataset',
105+
{ intersect: true },
106+
false
107+
)
108+
}
109+
110+
/**
111+
* Get single dataset element from mouse click event
112+
* @param chart - Chart.js instance
113+
* @param event - Mouse click event
114+
* @returns Dataset
115+
*/
116+
export function getElementAtEvent(chart: Chart, event: MouseEvent) {
117+
return chart.getElementsAtEventForMode(
118+
event,
119+
'nearest',
120+
{ intersect: true },
121+
false
122+
)
123+
}
124+
125+
/**
126+
* Get all dataset elements from mouse click event
127+
* @param chart - Chart.js instance
128+
* @param event - Mouse click event
129+
* @returns Dataset
130+
*/
131+
export function getElementsAtEvent(chart: Chart, event: MouseEvent) {
132+
return chart.getElementsAtEventForMode(
133+
event,
134+
'index',
135+
{ intersect: true },
136+
false
137+
)
138+
}

stories/chart.stories.ts

Lines changed: 101 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,101 @@
1+
import 'chart.js/auto'
2+
import type { InteractionItem } from 'chart.js'
3+
import { ref } from 'vue'
4+
import {
5+
ChartComponentRef,
6+
Chart,
7+
getDatasetAtEvent,
8+
getElementAtEvent,
9+
getElementsAtEvent
10+
} from '../src/index.js'
11+
import * as barChartConfig from '../sandboxes/bar/src/chartConfig.js'
12+
13+
export default {
14+
title: 'Chart',
15+
component: Chart,
16+
parameters: {
17+
layout: 'centered'
18+
}
19+
}
20+
21+
export function Default(args) {
22+
return {
23+
components: { Chart },
24+
template: '<Chart v-bind="args" />',
25+
setup() {
26+
return { args }
27+
}
28+
}
29+
}
30+
31+
Default.args = {
32+
id: 'bar-chart',
33+
type: 'bar',
34+
width: 400,
35+
height: 400,
36+
...barChartConfig
37+
}
38+
39+
export function Events(args) {
40+
return {
41+
components: { Chart },
42+
template: '<Chart ref="chartRef" @click="onClick" v-bind="args" />',
43+
setup() {
44+
const datasetAtEvent = (dataset: InteractionItem[]) => {
45+
if (!dataset.length) return
46+
47+
const datasetIndex = dataset[0].datasetIndex
48+
49+
console.log('dataset', barChartConfig.data.datasets[datasetIndex].label)
50+
}
51+
52+
const elementAtEvent = (element: InteractionItem[]) => {
53+
if (!element.length) return
54+
55+
const { datasetIndex, index } = element[0]
56+
57+
console.log(
58+
'element',
59+
barChartConfig.data.labels[index],
60+
barChartConfig.data.datasets[datasetIndex].data[index]
61+
)
62+
}
63+
64+
const elementsAtEvent = (elements: InteractionItem[]) => {
65+
if (!elements.length) return
66+
67+
console.log('elements', elements)
68+
}
69+
70+
const chartRef = ref<ChartComponentRef>(null)
71+
72+
const onClick = (event: MouseEvent) => {
73+
const {
74+
value: { chart }
75+
} = chartRef
76+
77+
if (!chart) {
78+
return
79+
}
80+
81+
datasetAtEvent(getDatasetAtEvent(chart, event))
82+
elementAtEvent(getElementAtEvent(chart, event))
83+
elementsAtEvent(getElementsAtEvent(chart, event))
84+
}
85+
86+
return {
87+
chartRef,
88+
args,
89+
onClick
90+
}
91+
}
92+
}
93+
}
94+
95+
Events.args = {
96+
id: 'bar-chart',
97+
type: 'bar',
98+
width: 400,
99+
height: 400,
100+
...barChartConfig
101+
}

0 commit comments

Comments
 (0)