@@ -2,24 +2,22 @@ import type { AppTheme } from '../../utils/types';
22
33import * as echarts from 'echarts' ;
44import { cloneDeep , merge } from 'lodash' ;
5- import React , { useEffect , useImperativeHandle , useRef , useState } from 'react' ;
5+ import { useEffect , useRef , useState } from 'react' ;
66
7- import { useAsync , useResize , useStorage } from '@react-devui/hooks' ;
7+ import { useAsync , useResize } from '@react-devui/hooks' ;
88import { getClassName } from '@react-devui/utils' ;
99
10- import { STORAGE_KEY } from '../../config/storage' ;
1110import chartTheme from './theme.json' ;
1211
13- echarts . registerTheme ( 'light' , chartTheme . light ) ;
14- echarts . registerTheme ( 'dark' , merge ( cloneDeep ( chartTheme . light ) , chartTheme . dark ) ) ;
15-
16- export interface AppChartProps < O extends echarts . EChartsOption > extends Omit < React . HTMLAttributes < HTMLDivElement > , 'children' > {
17- aOption : O | null ;
12+ export interface AppChartProps extends Omit < React . HTMLAttributes < HTMLDivElement > , 'children' > {
13+ aRenderer ?: 'canvas' | 'svg' ;
14+ onInit : ( instance : echarts . ECharts ) => void ;
1815}
1916
20- function Chart < O extends echarts . EChartsOption > ( props : AppChartProps < O > , ref : React . ForwardedRef < echarts . ECharts > ) : JSX . Element | null {
17+ export function AppChart ( props : AppChartProps ) : JSX . Element | null {
2118 const {
22- aOption,
19+ aRenderer = 'canvas' ,
20+ onInit,
2321
2422 ...restProps
2523 } = props ;
@@ -35,41 +33,62 @@ function Chart<O extends echarts.EChartsOption>(props: AppChartProps<O>, ref: Re
3533
3634 const async = useAsync ( ) ;
3735
38- const themeStorage = useStorage < AppTheme > ( ...STORAGE_KEY . theme ) ;
39-
40- const [ instance , setInstance ] = useState < echarts . ECharts | null > ( null ) ;
36+ const [ theme , setTheme ] = useState < AppTheme | null > ( null ) ;
4137
4238 useEffect ( ( ) => {
43- const instance = containerRef . current ? echarts . init ( containerRef . current , themeStorage . value , { renderer : 'svg' } ) : null ;
44- setInstance ( instance ) ;
39+ for ( const theme of [ 'light' , 'dark' ] as const ) {
40+ if ( document . body . className . includes ( theme ) ) {
41+ setTheme ( theme ) ;
42+ break ;
43+ }
44+ }
45+
46+ const observer = new MutationObserver ( ( ) => {
47+ setTheme ( document . body . className . includes ( 'dark' ) ? 'dark' : 'light' ) ;
48+ } ) ;
49+ observer . observe ( document . body , { attributeFilter : [ 'class' ] } ) ;
50+
4551 return ( ) => {
46- instance ?. dispose ( ) ;
52+ observer . disconnect ( ) ;
4753 } ;
48- } , [ themeStorage . value ] ) ;
54+ } , [ ] ) ;
4955
5056 useEffect ( ( ) => {
51- if ( instance && aOption ) {
52- instance . setOption ( aOption ) ;
57+ if ( containerRef . current && theme ) {
58+ const instance = echarts . init (
59+ containerRef . current ,
60+ JSON . parse (
61+ JSON . stringify ( theme === 'light' ? chartTheme . light : merge ( cloneDeep ( chartTheme . light ) , chartTheme . dark ) ) . replace (
62+ / v a r \( ( .+ ?) \) / g,
63+ ( match , p1 ) => {
64+ return getComputedStyle ( document . body ) . getPropertyValue ( p1 ) ;
65+ }
66+ )
67+ ) ,
68+ { renderer : aRenderer }
69+ ) ;
70+ onInit ( instance ) ;
71+ return ( ) => {
72+ instance . dispose ( ) ;
73+ } ;
5374 }
54- } , [ aOption , instance ] ) ;
75+ // eslint-disable-next-line react-hooks/exhaustive-deps
76+ } , [ aRenderer , theme ] ) ;
5577
5678 useResize ( elRef , ( ) => {
57- if ( instance ) {
58- dataRef . current . clearTid ?.( ) ;
59- dataRef . current . clearTid = async . setTimeout ( ( ) => {
60- dataRef . current . clearTid = undefined ;
61- instance . resize ( { animation : { duration : 200 } } ) ;
62- } , 100 ) ;
63- }
79+ dataRef . current . clearTid ?.( ) ;
80+ dataRef . current . clearTid = async . setTimeout ( ( ) => {
81+ dataRef . current . clearTid = undefined ;
82+ if ( containerRef . current ) {
83+ const instance = echarts . getInstanceByDom ( containerRef . current ) ;
84+ instance ?. resize ( { animation : { duration : 200 } } ) ;
85+ }
86+ } , 100 ) ;
6487 } ) ;
6588
66- useImperativeHandle < echarts . ECharts | null , echarts . ECharts | null > ( ref , ( ) => instance , [ instance ] ) ;
67-
6889 return (
6990 < div { ...restProps } ref = { elRef } className = { getClassName ( restProps . className , 'app-chart' ) } >
7091 < div ref = { containerRef } className = "app-chart__container" > </ div >
7192 </ div >
7293 ) ;
7394}
74-
75- export const AppChart = React . forwardRef ( Chart ) ;
0 commit comments