@@ -7,60 +7,93 @@ import {
77} from 'echarts/charts' ;
88import type { ComposeOption } from 'echarts/core' ;
99import { GridComponent , type GridComponentOption } from 'echarts/components' ;
10- import { ChartContext , defaultSetOptionOpt , echarts , useInitialChartContext , useRegister } from './shared.js' ;
10+ import type { ComponentOption } from 'echarts/types/src/util/types.js' ;
11+ import {
12+ ChartContext ,
13+ defaultSetOptionOpt ,
14+ echarts ,
15+ useInitialChartContext ,
16+ useRegister ,
17+ type EChartExt ,
18+ type Simplify ,
19+ } from './shared.js' ;
1120
1221function assignForwardedRef < T > ( ref : React . ForwardedRef < T > , value : T | null ) {
1322 if ( ! ref ) return ;
1423 if ( typeof ref === 'function' ) ref ( value ) ;
1524 else ref . current = value ;
1625}
1726
18- type LineChartOption = echarts . EChartsCoreOption &
19- ComposeOption < LineSeriesOption | GridComponentOption | PieSeriesOption > ;
20-
21- interface LineChartProps extends LineChartOption {
27+ interface ChartBaseProps < T extends readonly ChartComponentType < any > [ ] > {
2228 className ?: string ;
2329 style ?: React . CSSProperties ;
2430 containerProps ?: React . HTMLAttributes < HTMLDivElement > ;
31+ compose ?: [ ...T ] ;
32+ children ?: React . ReactNode ;
2533}
2634
27- export const LineChart = forwardRef (
28- (
29- { className, style, containerProps, children, ...props } : React . PropsWithChildren < LineChartProps > ,
30- ref : React . ForwardedRef < echarts . ECharts >
31- ) => {
32- const containerRef = useRef < HTMLDivElement > ( null ) ;
33- const chartRef = useRef < echarts . ECharts | null > ( null ) ;
34- const ctx = useInitialChartContext ( ) ;
35+ type InferChartComponentOption <
36+ T extends readonly ChartComponentType < any > [ ] ,
37+ U = T [ number ]
38+ > = U extends ChartComponentType < infer P > ? P : never ;
39+
40+ interface ChartComponentType < T extends ComponentOption > {
41+ < U extends readonly ChartComponentType < any > [ ] = [ ] > (
42+ props : ChartBaseProps < U > &
43+ echarts . EChartsCoreOption &
44+ Simplify < ComposeOption < T | InferChartComponentOption < U > > > & { ref ?: React . Ref < echarts . ECharts > }
45+ ) : React . JSX . Element ;
46+
47+ ext : EChartExt ;
48+ }
3549
36- useRegister ( ( echarts ) => {
37- // TODO: Make different charts composable.
38- echarts . use ( [ EChartLineChart , GridComponent , EChartPieChart ] ) ;
39- } ) ;
50+ function defineChart < T extends ComponentOption > ( ext : EChartExt ) {
51+ const ChartComponent = forwardRef (
52+ (
53+ { className, style, containerProps, compose, children, ...props } : ChartBaseProps < any > ,
54+ ref : React . ForwardedRef < echarts . ECharts >
55+ ) => {
56+ const containerRef = useRef < HTMLDivElement > ( null ) ;
57+ const chartRef = useRef < echarts . ECharts | null > ( null ) ;
58+ const ctx = useInitialChartContext ( ) ;
4059
41- useLayoutEffect ( ( ) => {
42- const chart = ( chartRef . current = echarts . init ( containerRef . current , null ) ) ;
43- assignForwardedRef ( ref , chart ) ;
44- return ( ) => {
45- chart . dispose ( ) ;
46- assignForwardedRef ( ref , null ) ;
47- } ;
48- } , [ ] ) ;
60+ useRegister ( ( echarts ) => {
61+ echarts . use ( [ ext , compose ?. map ( ( comp ) => comp . ext ) . flat ( ) || [ ] ] . flat ( ) ) ;
62+ } ) ;
63+
64+ useLayoutEffect ( ( ) => {
65+ const chart = ( chartRef . current = echarts . init ( containerRef . current , null ) ) ;
66+ assignForwardedRef ( ref , chart ) ;
67+ return ( ) => {
68+ chart . dispose ( ) ;
69+ assignForwardedRef ( ref , null ) ;
70+ } ;
71+ } , [ ] ) ;
72+
73+ useLayoutEffect ( ( ) => {
74+ const chart = chartRef . current ;
75+ if ( ! chart ) return ;
76+ for ( const opt of ctx . options ) chart . setOption ( opt , defaultSetOptionOpt ) ;
77+ chart . setOption ( props , defaultSetOptionOpt ) ;
78+ chart . setOption ( chart . getOption ( ) , { notMerge : true } ) ; // used for toolbox.restore snapshot
79+ ctx . options . length = 0 ;
80+ } ) ;
81+
82+ return (
83+ < ChartContext . Provider value = { ctx } >
84+ < div className = { className } style = { style } { ...containerProps } ref = { containerRef } />
85+ { children }
86+ </ ChartContext . Provider >
87+ ) ;
88+ }
89+ ) as unknown as ChartComponentType < T > ;
90+ ChartComponent . ext = ext ;
91+ return ChartComponent ;
92+ }
4993
50- useLayoutEffect ( ( ) => {
51- const chart = chartRef . current ;
52- if ( ! chart ) return ;
53- for ( const opt of ctx . options ) chart . setOption ( opt , defaultSetOptionOpt ) ;
54- chart . setOption ( props , defaultSetOptionOpt ) ;
55- chart . setOption ( chart . getOption ( ) , { notMerge : true } ) ; // used for toolbox.restore snapshot
56- ctx . options . length = 0 ;
57- } ) ;
94+ export const LineChart = /*#__PURE__*/ defineChart < LineSeriesOption | GridComponentOption > ( [
95+ EChartLineChart ,
96+ GridComponent ,
97+ ] ) ;
5898
59- return (
60- < ChartContext . Provider value = { ctx } >
61- < div className = { className } style = { style } { ...containerProps } ref = { containerRef } />
62- { children }
63- </ ChartContext . Provider >
64- ) ;
65- }
66- ) as ( props : React . PropsWithChildren < LineChartProps > & { ref ?: React . Ref < echarts . ECharts > } ) => React . JSX . Element ;
99+ export const PieChart = /*#__PURE__*/ defineChart < PieSeriesOption > ( [ EChartPieChart ] ) ;
0 commit comments