diff --git a/.eslintrc b/.eslintrc index e520023..17bed46 100644 --- a/.eslintrc +++ b/.eslintrc @@ -18,7 +18,7 @@ "no-unused-vars": 0, // @typescript-eslint/no-unused-vars "no-inner-declarations": 0, "prettier/prettier": 2, - "@typescript-eslint/no-unused-vars": 1, + "@typescript-eslint/no-unused-vars": [1, { "ignoreRestSiblings": true }], "@typescript-eslint/no-non-null-assertion": 0, "@typescript-eslint/no-explicit-any": 0, "@typescript-eslint/no-use-before-define": [2, { "functions": false }], diff --git a/__tests__/charts/simple-spec.tsx b/__tests__/charts/simple-spec.tsx index 14d1684..18529d4 100644 --- a/__tests__/charts/simple-spec.tsx +++ b/__tests__/charts/simple-spec.tsx @@ -191,4 +191,29 @@ describe('chart', () => { }); }); }); + + describe('props', () => { + it('default', () => { + let instance; + const div = createDiv(); + div.style.display = 'block'; + div.style.width = '1200px'; + div.style.height = '720px'; + + const opts = { + width: null, + height: null, + }; + + const Comp = (instance = e)} option={options} opts={opts} data-testid="props-test" />; + render(Comp, div); + + expect(div.querySelector('[data-testid="props-test"]')).toBe(instance.ele); + + destroy(div); + expect(div.querySelector('*')).toBe(null); + + removeDom(div); + }); + }); }); diff --git a/__tests__/helper/pick-spec.ts b/__tests__/helper/pick-spec.ts index 57bf873..6348a20 100644 --- a/__tests__/helper/pick-spec.ts +++ b/__tests__/helper/pick-spec.ts @@ -2,9 +2,10 @@ import { pick } from '../../src/helper/pick'; describe('pick', () => { it('pick', () => { - expect(pick({ a: 1 }, [])).toEqual({}); - expect(pick({ a: 1 }, ['b'])).toEqual({}); - expect(pick({ a: 1 }, ['a'])).toEqual({ a: 1 }); - expect(pick({ a: 1 }, ['a', 'b'])).toEqual({ a: 1 }); + const obj: { a: number; b?: number } = { a: 1 }; + expect(pick(obj, [])).toEqual({}); + expect(pick(obj, ['b'])).toEqual({}); + expect(pick(obj, ['a'])).toEqual({ a: 1 }); + expect(pick(obj, ['a', 'b'])).toEqual({ a: 1 }); }); }); diff --git a/docs/examples/html-props.md b/docs/examples/html-props.md new file mode 100644 index 0000000..b133d2c --- /dev/null +++ b/docs/examples/html-props.md @@ -0,0 +1,92 @@ +--- +title: HTML Properties +order: 10 +--- + +## HTML Properties + +Unknown (non-ECharts) props are passed through to the div element. + +```tsx +import React from 'react'; +import ReactECharts from 'echarts-for-react'; + +const Page: React.FC = () => { + const option = { + title: { + text: '堆叠区域图' + }, + tooltip : { + trigger: 'axis' + }, + legend: { + data:['邮件营销','联盟广告','视频广告'] + }, + toolbox: { + feature: { + saveAsImage: {} + } + }, + grid: { + left: '3%', + right: '4%', + bottom: '3%', + containLabel: true + }, + xAxis : [ + { + type : 'category', + boundaryGap : false, + data : ['周一','周二','周三','周四','周五','周六','周日'] + } + ], + yAxis : [ + { + type : 'value' + } + ], + series : [ + { + name:'邮件营销', + type:'line', + stack: '总量', + areaStyle: {normal: {}}, + data:[120, 132, 101, 134, 90, 230, 210] + }, + { + name:'联盟广告', + type:'line', + stack: '总量', + areaStyle: {normal: {}}, + data:[220, 182, 191, 234, 290, 330, 310] + }, + { + name:'视频广告', + type:'line', + stack: '总量', + areaStyle: {normal: {}}, + data:[150, 232, 201, 154, 190, 330, 410] + } + ] + }; + + const handleDemoButton = () => { + console.log(document.querySelector(['[data-testid="html-props-demo"]'])); + window.alert('Open console, see the log detail.') + }; + + return ( + <> + + + + ); +}; + +export default Page; +``` diff --git a/src/core.tsx b/src/core.tsx index 371ed21..5da1bd9 100644 --- a/src/core.tsx +++ b/src/core.tsx @@ -52,10 +52,7 @@ export default class EChartsReactCore extends PureComponent { // 以下属性修改的时候,需要 dispose 之后再新建 // 1. 切换 theme 的时候 // 2. 修改 opts 的时候 - if ( - !isEqual(prevProps.theme, this.props.theme) || - !isEqual(prevProps.opts, this.props.opts) - ) { + if (!isEqual(prevProps.theme, this.props.theme) || !isEqual(prevProps.opts, this.props.opts)) { this.dispose(); this.renderNewEcharts(); // 重建 @@ -70,8 +67,8 @@ export default class EChartsReactCore extends PureComponent { } // when these props are not isEqual, update echarts - const pickKeys = ['option', 'notMerge', 'replaceMerge', 'lazyUpdate', 'showLoading', 'loadingOption']; - if (!isEqual(pick(this.props, pickKeys), pick(prevProps, pickKeys))) { + const pickKeys = ['option', 'notMerge', 'replaceMerge', 'lazyUpdate', 'showLoading', 'loadingOption'] as const; + if (!isEqual(pick(this.props, pickKeys), pick(prevProps as any, pickKeys))) { this.updateEChartsOption(); } @@ -243,7 +240,24 @@ export default class EChartsReactCore extends PureComponent { } render(): JSX.Element { - const { style, className = '' } = this.props; + const { + style, + className = '', + echarts, + option, + theme, + notMerge, + replaceMerge, + lazyUpdate, + showLoading, + loadingOption, + opts, + onChartReady, + onEvents, + shouldSetOption, + autoResize, + ...divHTMLAttributes + } = this.props; // default height = 300 const newStyle = { height: 300, ...style }; @@ -254,6 +268,7 @@ export default class EChartsReactCore extends PureComponent { }} style={newStyle} className={`echarts-for-react ${className}`} + {...divHTMLAttributes} /> ); } diff --git a/src/helper/pick.ts b/src/helper/pick.ts index ded83f8..eb394ec 100644 --- a/src/helper/pick.ts +++ b/src/helper/pick.ts @@ -3,8 +3,8 @@ * @param obj * @param keys */ -export function pick(obj: Record, keys: string[]): Record { - const r = {}; +export function pick(obj: T, keys: readonly (keyof T)[]): Partial { + const r = {} as Partial; keys.forEach((key) => { r[key] = obj[key]; }); diff --git a/src/types.ts b/src/types.ts index 60a6465..5cd94d6 100644 --- a/src/types.ts +++ b/src/types.ts @@ -1,4 +1,3 @@ -import type { CSSProperties } from 'react'; import type { EChartsType } from 'echarts'; /** @@ -16,19 +15,11 @@ export type Opts = { readonly locale?: string; }; -export type EChartsReactProps = { +export type EChartsReactProps = React.HTMLAttributes & { /** * echarts library entry, use it for import necessary. */ readonly echarts?: any; - /** - * `className` for container - */ - readonly className?: string; - /** - * `style` for container - */ - readonly style?: CSSProperties; /** * echarts option */