-
Notifications
You must be signed in to change notification settings - Fork 11
/
Copy pathisland.tsx
102 lines (91 loc) · 2.65 KB
/
island.tsx
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
// Copyright 2018-2023 the Deno authors. All rights reserved. MIT license.
import { ChartJs } from "./deps.ts";
import type { JSX } from "preact";
import { useEffect, useRef } from "preact/hooks";
export type ChartType = ChartJs.ChartType;
export type DefaultDataPoint<TType extends ChartType> =
ChartJs.DefaultDataPoint<TType>;
export type ChartProps<
Type extends ChartType,
Data = DefaultDataPoint<Type>,
Label = unknown,
> = ChartJs.ChartConfiguration<Type, Data, Label> & {
canvas?: JSX.HTMLAttributes<HTMLCanvasElement>;
};
/**
* A hook which takes in a Chart.js configuration object and returns `canvasRef` and `chartRef`.
*
* `canvasRef` is a reference to the canvas element which the chart is rendered to.
* `chartRef` is a reference to the Chart.js instance.
*/
function useChart<
Type extends ChartType,
Data = DefaultDataPoint<Type>,
Label = unknown,
>(options: ChartJs.ChartConfiguration<Type, Data, Label>) {
const canvasRef = useRef<HTMLCanvasElement | null>(null);
const chartRef = useRef<ChartJs.Chart<Type, Data, Label> | null>(null);
useEffect(() => {
if (canvasRef.current === null) {
throw new Error("canvas is null");
}
if (chartRef.current) {
chartRef.current.destroy();
}
chartRef.current = new ChartJs.Chart(
canvasRef.current,
options,
);
return () => {
chartRef.current?.destroy();
};
}, [canvasRef, options]);
return { canvasRef, chartRef };
}
/**
* A JSX component which can be used to client side render a chart inline
* within a page.
*
* View {@linkcode ChartProps} for a list of properties that can be set
* on the component.
*
* ### Example
*
* ```tsx
* import { Chart } from "https://deno.land/x/fresh_charts/island.tsx";
* import { ChartColors } from "https://deno.land/x/fresh_charts/utils.ts";
*
* export default App() {
* return <>
* <h1>Chart Example</h1>
* <Chart
* type="line"
* options={{
* scales: { yAxes: [{ ticks: { beginAtZero: true } }] },
* }}
* data={{
* labels: ["1", "2", "3"],
* datasets: [{
* label: "Sessions",
* data: [123, 234, 234],
* borderColor: ChartColors.Red,
* borderWidth: 1,
* }, {
* label: "Users",
* data: [346, 233, 123],
* borderColor: ChartColors.Blue,
* borderWidth: 1,
* }],
* }}
* />
* <>;
* }
* ```
*/
export function Chart<Type extends ChartType>(props: ChartProps<Type>) {
const { canvasRef, chartRef } = useChart<Type>(props);
useEffect(() => {
chartRef.current?.render();
}, []);
return <canvas ref={canvasRef} />;
}