Skip to content

Commit

Permalink
feat: events utils (#963)
Browse files Browse the repository at this point in the history
utils to handle chart clicks were added
  • Loading branch information
dangreen committed Dec 5, 2022
1 parent 5bd9805 commit 752407e
Show file tree
Hide file tree
Showing 10 changed files with 306 additions and 1 deletion.
2 changes: 1 addition & 1 deletion .size-limit.json
@@ -1,7 +1,7 @@
[
{
"path": "dist/index.js",
"limit": "1.7 KB",
"limit": "1.9 KB",
"webpack": false,
"running": false
},
Expand Down
11 changes: 11 additions & 0 deletions sandboxes/events/index.html
@@ -0,0 +1,11 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<script type="module" defer src="./index.ts"></script>
</head>
<body>
<div id="app"></div>
</body>
</html>
4 changes: 4 additions & 0 deletions sandboxes/events/index.ts
@@ -0,0 +1,4 @@
import { createApp } from 'vue'
import App from './src/App.vue'

createApp(App).mount('#app')
16 changes: 16 additions & 0 deletions sandboxes/events/package.json
@@ -0,0 +1,16 @@
{
"type": "module",
"scripts": {
"start": "vite"
},
"dependencies": {
"chart.js": "^4.0.0",
"vue": "^3.2.31",
"vue-chartjs": "^5.0.0"
},
"devDependencies": {
"@vitejs/plugin-vue": "^3.0.1",
"typescript": "^4.9.3",
"vite": "^3.2.4"
}
}
89 changes: 89 additions & 0 deletions sandboxes/events/src/App.vue
@@ -0,0 +1,89 @@
<template>
<Chart
ref="chartRef"
type="bar"
:data="data"
:options="options"
@click="onClick"
/>
</template>

<script lang="ts">
import { ref } from 'vue'
import {
Chart as ChartJS,
Title,
Tooltip,
Legend,
BarElement,
CategoryScale,
LinearScale,
InteractionItem
} from 'chart.js'
import {
ChartComponentRef,
Chart,
getDatasetAtEvent,
getElementAtEvent,
getElementsAtEvent
} from 'vue-chartjs'
import * as chartConfig from './chartConfig.js'
ChartJS.register(CategoryScale, LinearScale, BarElement, Title, Tooltip, Legend)
export default {
name: 'App',
components: {
Chart
},
setup() {
const datasetAtEvent = (dataset: InteractionItem[]) => {
if (!dataset.length) return
const datasetIndex = dataset[0].datasetIndex
console.log('dataset', chartConfig.data.datasets[datasetIndex].label)
}
const elementAtEvent = (element: InteractionItem[]) => {
if (!element.length) return
const { datasetIndex, index } = element[0]
console.log(
'element',
chartConfig.data.labels[index],
chartConfig.data.datasets[datasetIndex].data[index]
)
}
const elementsAtEvent = (elements: InteractionItem[]) => {
if (!elements.length) return
console.log('elements', elements)
}
const chartRef = ref<ChartComponentRef>(null)
const onClick = (event: MouseEvent) => {
const {
value: { chart }
} = chartRef
if (!chart) {
return
}
datasetAtEvent(getDatasetAtEvent(chart, event))
elementAtEvent(getElementAtEvent(chart, event))
elementsAtEvent(getElementsAtEvent(chart, event))
}
return {
chartRef,
onClick,
...chartConfig
}
}
}
</script>
28 changes: 28 additions & 0 deletions sandboxes/events/src/chartConfig.ts
@@ -0,0 +1,28 @@
export const data = {
labels: [
'January',
'February',
'March',
'April',
'May',
'June',
'July',
'August',
'September',
'October',
'November',
'December'
],
datasets: [
{
label: 'Data One',
backgroundColor: '#f87979',
data: [40, 20, 12, 39, 10, 40, 39, 80, 40, 20, 12, 11]
}
]
}

export const options = {
responsive: true,
maintainAspectRatio: false
}
6 changes: 6 additions & 0 deletions sandboxes/events/vite.config.js
@@ -0,0 +1,6 @@
import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'

export default defineConfig({
plugins: [vue()]
})
5 changes: 5 additions & 0 deletions src/index.ts
Expand Up @@ -12,6 +12,11 @@ import {
} from './typedCharts.js'

export type { ChartProps, ChartComponentRef } from './types.js'
export {
getDatasetAtEvent,
getElementAtEvent,
getElementsAtEvent
} from './utils.js'
export {
Chart,
createTypedChart,
Expand Down
45 changes: 45 additions & 0 deletions src/utils.ts
Expand Up @@ -91,3 +91,48 @@ export function cloneData<

return nextData
}

/**
* Get dataset from mouse click event
* @param chart - Chart.js instance
* @param event - Mouse click event
* @returns Dataset
*/
export function getDatasetAtEvent(chart: Chart, event: MouseEvent) {
return chart.getElementsAtEventForMode(
event,
'dataset',
{ intersect: true },
false
)
}

/**
* Get single dataset element from mouse click event
* @param chart - Chart.js instance
* @param event - Mouse click event
* @returns Dataset
*/
export function getElementAtEvent(chart: Chart, event: MouseEvent) {
return chart.getElementsAtEventForMode(
event,
'nearest',
{ intersect: true },
false
)
}

/**
* Get all dataset elements from mouse click event
* @param chart - Chart.js instance
* @param event - Mouse click event
* @returns Dataset
*/
export function getElementsAtEvent(chart: Chart, event: MouseEvent) {
return chart.getElementsAtEventForMode(
event,
'index',
{ intersect: true },
false
)
}
101 changes: 101 additions & 0 deletions stories/chart.stories.ts
@@ -0,0 +1,101 @@
import 'chart.js/auto'
import type { InteractionItem } from 'chart.js'
import { ref } from 'vue'
import {
ChartComponentRef,
Chart,
getDatasetAtEvent,
getElementAtEvent,
getElementsAtEvent
} from '../src/index.js'
import * as barChartConfig from '../sandboxes/bar/src/chartConfig.js'

export default {
title: 'Chart',
component: Chart,
parameters: {
layout: 'centered'
}
}

export function Default(args) {
return {
components: { Chart },
template: '<Chart v-bind="args" />',
setup() {
return { args }
}
}
}

Default.args = {
id: 'bar-chart',
type: 'bar',
width: 400,
height: 400,
...barChartConfig
}

export function Events(args) {
return {
components: { Chart },
template: '<Chart ref="chartRef" @click="onClick" v-bind="args" />',
setup() {
const datasetAtEvent = (dataset: InteractionItem[]) => {
if (!dataset.length) return

const datasetIndex = dataset[0].datasetIndex

console.log('dataset', barChartConfig.data.datasets[datasetIndex].label)
}

const elementAtEvent = (element: InteractionItem[]) => {
if (!element.length) return

const { datasetIndex, index } = element[0]

console.log(
'element',
barChartConfig.data.labels[index],
barChartConfig.data.datasets[datasetIndex].data[index]
)
}

const elementsAtEvent = (elements: InteractionItem[]) => {
if (!elements.length) return

console.log('elements', elements)
}

const chartRef = ref<ChartComponentRef>(null)

const onClick = (event: MouseEvent) => {
const {
value: { chart }
} = chartRef

if (!chart) {
return
}

datasetAtEvent(getDatasetAtEvent(chart, event))
elementAtEvent(getElementAtEvent(chart, event))
elementsAtEvent(getElementsAtEvent(chart, event))
}

return {
chartRef,
args,
onClick
}
}
}
}

Events.args = {
id: 'bar-chart',
type: 'bar',
width: 400,
height: 400,
...barChartConfig
}

0 comments on commit 752407e

Please sign in to comment.