This commit is contained in:
freedakgmail
2025-11-22 23:49:24 +08:00
parent b83382b604
commit c033e46782
3580 changed files with 1745279 additions and 2428 deletions
@@ -0,0 +1 @@
../../echarts@6.0.0/node_modules/echarts
@@ -0,0 +1,21 @@
MIT License
Copyright (c) 2018 AntV team
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do { so, subject } to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
@@ -0,0 +1,424 @@
# echarts-for-react
The simplest, and the best React wrapper for [Apache ECharts](https://github.com/apache/incubator-echarts). Using visualization with MCP Server [mcp-server-chart](https://github.com/antvis/mcp-server-chart).
[![npm](https://img.shields.io/npm/v/echarts-for-react.svg)](https://www.npmjs.com/package/echarts-for-react)
[![build](https://github.com/hustcc/echarts-for-react/actions/workflows/build.yml/badge.svg)](https://github.com/hustcc/echarts-for-react/actions/workflows/build.yml)
[![Coverage](https://img.shields.io/coveralls/hustcc/echarts-for-react/master.svg)](https://coveralls.io/github/hustcc/echarts-for-react)
[![NPM downloads](https://img.shields.io/npm/dm/echarts-for-react.svg)](https://www.npmjs.com/package/echarts-for-react)
[![License](https://img.shields.io/npm/l/echarts-for-react.svg)](https://www.npmjs.com/package/echarts-for-react)
![ECharts Ver](https://img.shields.io/badge/echarts-%5E3.0.0%20%7C%7C%20%5E4.0.0%20%7C%7C%20%5E5.0.0%20%5E6.0.0-blue.svg)
![React Ver](https://img.shields.io/badge/React-%20%5E15.0.0%20%7C%7C%20%20%5E16.0.0%20%7C%7C%20%20%5E17.0.0-blue.svg)
## Install
```bach
$ npm install --save echarts-for-react
# `echarts` is the peerDependence of `echarts-for-react`, you can install echarts with your own version.
$ npm install --save echarts
```
Then use it.
```ts
import ReactECharts from 'echarts-for-react';
// render echarts option.
<ReactECharts option={this.getOption()} />
```
You can run website.
```bash
$ git clone git@github.com:hustcc/echarts-for-react.git
$ npm install
$ npm start
```
Then open [http://127.0.0.1:8081/](http://127.0.0.1:8081/) in your browser. or see [https://git.hust.cc/echarts-for-react/](https://git.hust.cc/echarts-for-react/) which is deploy on gh-pages.
## Usage
Code of a simple demo code showed below. For more example can see: [https://git.hust.cc/echarts-for-react/](https://git.hust.cc/echarts-for-react/)
```ts
import React from 'react';
import ReactECharts from 'echarts-for-react'; // or var ReactECharts = require('echarts-for-react');
<ReactECharts
option={this.getOption()}
notMerge={true}
lazyUpdate={true}
theme={"theme_name"}
onChartReady={this.onChartReadyCallback}
onEvents={EventsDict}
opts={}
/>
```
Import ECharts.js modules manually to reduce bundle size
**With Echarts.js v5 or v6:**
```ts
import React from 'react';
// import the core library.
import ReactEChartsCore from 'echarts-for-react/lib/core';
// Import the echarts core module, which provides the necessary interfaces for using echarts.
import * as echarts from 'echarts/core';
// Import charts, all with Chart suffix
import {
// LineChart,
BarChart,
// PieChart,
// ScatterChart,
// RadarChart,
// MapChart,
// TreeChart,
// TreemapChart,
// GraphChart,
// GaugeChart,
// FunnelChart,
// ParallelChart,
// SankeyChart,
// BoxplotChart,
// CandlestickChart,
// EffectScatterChart,
// LinesChart,
// HeatmapChart,
// PictorialBarChart,
// ThemeRiverChart,
// SunburstChart,
// CustomChart,
} from 'echarts/charts';
// import components, all suffixed with Component
import {
// GridSimpleComponent,
GridComponent,
// PolarComponent,
// RadarComponent,
// GeoComponent,
// SingleAxisComponent,
// ParallelComponent,
// CalendarComponent,
// GraphicComponent,
// ToolboxComponent,
TooltipComponent,
// AxisPointerComponent,
// BrushComponent,
TitleComponent,
// TimelineComponent,
// MarkPointComponent,
// MarkLineComponent,
// MarkAreaComponent,
// LegendComponent,
// LegendScrollComponent,
// LegendPlainComponent,
// DataZoomComponent,
// DataZoomInsideComponent,
// DataZoomSliderComponent,
// VisualMapComponent,
// VisualMapContinuousComponent,
// VisualMapPiecewiseComponent,
// AriaComponent,
// TransformComponent,
DatasetComponent,
} from 'echarts/components';
// Import renderer, note that introducing the CanvasRenderer or SVGRenderer is a required step
import {
CanvasRenderer,
// SVGRenderer,
} from 'echarts/renderers';
// Register the required components
echarts.use(
[TitleComponent, TooltipComponent, GridComponent, BarChart, CanvasRenderer]
);
// The usage of ReactEChartsCore are same with above.
<ReactEChartsCore
echarts={echarts}
option={this.getOption()}
notMerge={true}
lazyUpdate={true}
theme={"theme_name"}
onChartReady={this.onChartReadyCallback}
onEvents={EventsDict}
opts={}
/>
```
**With Echarts.js v3 or v4:**
```ts
import React from 'react';
// import the core library.
import ReactEChartsCore from 'echarts-for-react/lib/core';
// then import echarts modules those you have used manually.
import echarts from 'echarts/lib/echarts';
// import 'echarts/lib/chart/line';
import 'echarts/lib/chart/bar';
// import 'echarts/lib/chart/pie';
// import 'echarts/lib/chart/scatter';
// import 'echarts/lib/chart/radar';
// import 'echarts/lib/chart/map';
// import 'echarts/lib/chart/treemap';
// import 'echarts/lib/chart/graph';
// import 'echarts/lib/chart/gauge';
// import 'echarts/lib/chart/funnel';
// import 'echarts/lib/chart/parallel';
// import 'echarts/lib/chart/sankey';
// import 'echarts/lib/chart/boxplot';
// import 'echarts/lib/chart/candlestick';
// import 'echarts/lib/chart/effectScatter';
// import 'echarts/lib/chart/lines';
// import 'echarts/lib/chart/heatmap';
// import 'echarts/lib/component/graphic';
// import 'echarts/lib/component/grid';
// import 'echarts/lib/component/legend';
import 'echarts/lib/component/tooltip';
// import 'echarts/lib/component/polar';
// import 'echarts/lib/component/geo';
// import 'echarts/lib/component/parallel';
// import 'echarts/lib/component/singleAxis';
// import 'echarts/lib/component/brush';
import 'echarts/lib/component/title';
// import 'echarts/lib/component/dataZoom';
// import 'echarts/lib/component/visualMap';
// import 'echarts/lib/component/markPoint';
// import 'echarts/lib/component/markLine';
// import 'echarts/lib/component/markArea';
// import 'echarts/lib/component/timeline';
// import 'echarts/lib/component/toolbox';
// import 'zrender/lib/vml/vml';
// The usage of ReactEChartsCore are same with above.
<ReactEChartsCore
echarts={echarts}
option={this.getOption()}
notMerge={true}
lazyUpdate={true}
theme={"theme_name"}
onChartReady={this.onChartReadyCallback}
onEvents={EventsDict}
opts={}
/>
```
For **Next.js** user, code transpilation is needed. For Next.js 13.1 or higher, as all `next-transpile-modules` features are natively built-in and the package has been deprecated, so please add `transpilePackages: ['echarts', 'zrender']` into `nextConfig` object:
```js
// next.config.js
/** @type {import('next').NextConfig} */
const nextConfig = {
// ...existing properties,
transpilePackages: ['echarts', 'zrender'],
}
module.exports = nextConfig
```
For Next.js with version < 13.1:
```js
// next.config.js
const withTM = require("next-transpile-modules")(["echarts", "zrender"]);
module.exports = withTM({})
```
## Props of Component
- **`option`** (required, object)
the echarts option config, can see [https://echarts.apache.org/option.html#title](https://echarts.apache.org/option.html#title).
- **`notMerge`** (optional, object)
when `setOption`, not merge the data, default is `false`. See [https://echarts.apache.org/api.html#echartsInstance.setOption](https://echarts.apache.org/api.html#echartsInstance.setOption).
- **`replaceMerge`** (optional, string | string[])
when `setOption`, default is `null`. See [https://echarts.apache.org/api.html#echartsInstance.setOption](https://echarts.apache.org/api.html#echartsInstance.setOption).
- **`lazyUpdate`** (optional, object)
when `setOption`, lazy update the data, default is `false`. See [https://echarts.apache.org/api.html#echartsInstance.setOption](https://echarts.apache.org/api.html#echartsInstance.setOption).
- **`style`** (optional, object)
the `style` of echarts div. `object`, default is {height: '300px'}.
- **`className`** (optional, string)
the `class` of echarts div. you can setting the css style of charts by class name.
- **`theme`** (optional, string)
the `theme` of echarts. `string`, should `registerTheme` before use it (theme object format: [https://github.com/ecomfe/echarts/blob/master/theme/dark.js](https://github.com/ecomfe/echarts/blob/master/theme/dark.js)). e.g.
```ts
// import echarts
import echarts from 'echarts';
...
// register theme object
echarts.registerTheme('my_theme', {
backgroundColor: '#f4cccc'
});
...
// render the echarts use option `theme`
<ReactECharts
option={this.getOption()}
style={{height: '300px', width: '100%'}}
className='echarts-for-echarts'
theme='my_theme' />
```
- **`onChartReady`** (optional, function)
when the chart is ready, will callback the function with the `echarts object` as it's paramter.
- **`loadingOption`** (optional, object)
the echarts loading option config, can see [https://echarts.apache.org/api.html#echartsInstance.showLoading](https://echarts.apache.org/api.html#echartsInstance.showLoading).
- **`showLoading`** (optional, bool, default: false)
`bool`, when the chart is rendering, show the loading mask.
- **`onEvents`** (optional, array(string=>function) )
binding the echarts event, will callback with the `echarts event object`, and `the echart object` as it's paramters. e.g:
```ts
const onEvents = {
'click': this.onChartClick,
'legendselectchanged': this.onChartLegendselectchanged
}
...
<ReactECharts
option={this.getOption()}
style={{ height: '300px', width: '100%' }}
onEvents={onEvents}
/>
```
for more event key name, see: [https://echarts.apache.org/api.html#events](https://echarts.apache.org/api.html#events)
- **`opts`** (optional, object)
the `opts` of echarts. `object`, will be used when initial echarts instance by `echarts.init`. Document [here](https://echarts.apache.org/api.html#echarts.init).
```ts
<ReactECharts
option={this.getOption()}
style={{ height: '300px' }}
opts={{renderer: 'svg'}} // use svg to render the chart.
/>
```
- **`autoResize`** (optional, boolean)
decide whether to trigger `this.resize` when window resize. default is `true`.
## Component API & Echarts API
the Component only has `one API` named `getEchartsInstance`.
- **`getEchartsInstance()`** : get the echarts instance object, then you can use any `API of echarts`.
for example:
```ts
// render the echarts component below with rel
<ReactECharts
ref={(e) => { this.echartRef = e; }}
option={this.getOption()}
/>
// then get the `ReactECharts` use this.echarts_react
const echartInstance = this.echartRef.getEchartsInstance();
// then you can use any API of echarts.
const base64 = echartInstance.getDataURL();
```
TypeScript and `useRef()` example:
```ts
const getOption = () => {/** */};
export default function App() {
const echartsRef = useRef<InstanceType<typeof ReactEcharts>>(null);
useEffect(() => {
if (echartsRef.current) {
const echartsInstance = echartsRef.current.getEchartsInstance();
// do something
echartsInstance.resize();
}
}, []);
return <ReactEcharts ref={echartsRef} option={getOption()} />;
}
```
**About API of echarts, can see** [https://echarts.apache.org/api.html#echartsInstance](https://echarts.apache.org/api.html#echartsInstance).
You can use the API to do:
1. `binding / unbinding` event.
2. `dynamic charts` with dynamic data.
3. get the echarts dom / dataURL / base64, save the chart to png.
4. `release` the charts.
## FAQ
### How to render the chart with svg when using echarts 4.x
Use the props `opts` of component with `renderer = 'svg'`. For example:
```ts
<ReactECharts
option={this.getOption()}
style={{height: '300px'}}
opts={{renderer: 'svg'}} // use svg to render the chart.
/>
```
### How to resolve Error `Component series.scatter3D not exists. Load it first.`
Install and import [`echarts-gl`](https://www.npmjs.com/package/echarts-gl) module when you want to create a [GL instance](https://www.echartsjs.com/examples/zh/index.html#chart-type-globe)
```sh
npm install --save echarts-gl
```
```ts
import 'echarts-gl'
import ReactECharts from "echarts-for-react";
<ReactECharts
option={GL_OPTION}
/>
```
## LICENSE
MIT@[hustcc](https://github.com/hustcc).
@@ -0,0 +1,48 @@
import type { ECharts } from 'echarts';
import { PureComponent } from 'react';
import { EChartsReactProps } from './types';
/**
* core component for echarts binding
*/
export default class EChartsReactCore extends PureComponent<EChartsReactProps> {
/**
* echarts render container
*/
ele: HTMLElement;
/**
* if this is the first time we are resizing
*/
private isInitialResize;
/**
* echarts library entry
*/
protected echarts: any;
constructor(props: EChartsReactProps);
componentDidMount(): void;
componentDidUpdate(prevProps: EChartsReactProps): void;
componentWillUnmount(): void;
initEchartsInstance(): Promise<ECharts>;
/**
* return the existing echart object
*/
getEchartsInstance(): ECharts;
/**
* dispose echarts and clear size-sensor
*/
private dispose;
/**
* render a new echarts instance
*/
private renderNewEcharts;
private bindEvents;
private offEvents;
/**
* render the echarts
*/
private updateEChartsOption;
/**
* resize wrapper
*/
private resize;
render(): JSX.Element;
}
@@ -0,0 +1,221 @@
import { __assign, __awaiter, __extends, __generator, __rest } from "tslib";
import React, { PureComponent } from 'react';
import { bind, clear } from 'size-sensor';
import { pick } from './helper/pick';
import { isFunction } from './helper/is-function';
import { isString } from './helper/is-string';
import { isEqual } from './helper/is-equal';
/**
* core component for echarts binding
*/
var EChartsReactCore = /** @class */ (function (_super) {
__extends(EChartsReactCore, _super);
function EChartsReactCore(props) {
var _this = _super.call(this, props) || this;
_this.echarts = props.echarts;
_this.ele = null;
_this.isInitialResize = true;
return _this;
}
EChartsReactCore.prototype.componentDidMount = function () {
this.renderNewEcharts();
};
// update
EChartsReactCore.prototype.componentDidUpdate = function (prevProps) {
/**
* if shouldSetOption return false, then return, not update echarts options
* default is true
*/
var shouldSetOption = this.props.shouldSetOption;
if (isFunction(shouldSetOption) && !shouldSetOption(prevProps, this.props)) {
return;
}
// 以下属性修改的时候,需要 dispose 之后再新建
// 1. 切换 theme 的时候
// 2. 修改 opts 的时候
if (!isEqual(prevProps.theme, this.props.theme) || !isEqual(prevProps.opts, this.props.opts)) {
this.dispose();
this.renderNewEcharts(); // 重建
return;
}
// 修改 onEvent 的时候先移除历史事件再添加
var echartsInstance = this.getEchartsInstance();
if (!isEqual(prevProps.onEvents, this.props.onEvents)) {
this.offEvents(echartsInstance, prevProps.onEvents);
this.bindEvents(echartsInstance, this.props.onEvents);
}
// when these props are not isEqual, update echarts
var pickKeys = ['option', 'notMerge', 'replaceMerge', 'lazyUpdate', 'showLoading', 'loadingOption'];
if (!isEqual(pick(this.props, pickKeys), pick(prevProps, pickKeys))) {
this.updateEChartsOption();
}
/**
* when style or class name updated, change size.
*/
if (!isEqual(prevProps.style, this.props.style) || !isEqual(prevProps.className, this.props.className)) {
this.resize();
}
};
EChartsReactCore.prototype.componentWillUnmount = function () {
this.dispose();
};
/*
* initialise an echarts instance
*/
EChartsReactCore.prototype.initEchartsInstance = function () {
return __awaiter(this, void 0, void 0, function () {
var _this = this;
return __generator(this, function (_a) {
return [2 /*return*/, new Promise(function (resolve) {
// create temporary echart instance
_this.echarts.init(_this.ele, _this.props.theme, _this.props.opts);
var echartsInstance = _this.getEchartsInstance();
echartsInstance.on('finished', function () {
// get final width and height
var width = _this.ele.clientWidth;
var height = _this.ele.clientHeight;
// dispose temporary echart instance
_this.echarts.dispose(_this.ele);
// recreate echart instance
// we use final width and height only if not originally provided as opts
var opts = __assign({ width: width, height: height }, _this.props.opts);
resolve(_this.echarts.init(_this.ele, _this.props.theme, opts));
});
})];
});
});
};
/**
* return the existing echart object
*/
EChartsReactCore.prototype.getEchartsInstance = function () {
return this.echarts.getInstanceByDom(this.ele);
};
/**
* dispose echarts and clear size-sensor
*/
EChartsReactCore.prototype.dispose = function () {
if (this.ele) {
try {
clear(this.ele);
}
catch (e) {
console.warn(e);
}
// dispose echarts instance
this.echarts.dispose(this.ele);
}
};
/**
* render a new echarts instance
*/
EChartsReactCore.prototype.renderNewEcharts = function () {
return __awaiter(this, void 0, void 0, function () {
var _a, onEvents, onChartReady, _b, autoResize, echartsInstance;
var _this = this;
return __generator(this, function (_c) {
switch (_c.label) {
case 0:
_a = this.props, onEvents = _a.onEvents, onChartReady = _a.onChartReady, _b = _a.autoResize, autoResize = _b === void 0 ? true : _b;
// 1. init echarts instance
return [4 /*yield*/, this.initEchartsInstance()];
case 1:
// 1. init echarts instance
_c.sent();
echartsInstance = this.updateEChartsOption();
// 3. bind events
this.bindEvents(echartsInstance, onEvents || {});
// 4. on chart ready
if (isFunction(onChartReady))
onChartReady(echartsInstance);
// 5. on resize
if (this.ele && autoResize) {
bind(this.ele, function () {
_this.resize();
});
}
return [2 /*return*/];
}
});
});
};
// bind the events
EChartsReactCore.prototype.bindEvents = function (instance, events) {
function _bindEvent(eventName, func) {
// ignore the event config which not satisfy
if (isString(eventName) && isFunction(func)) {
// binding event
instance.on(eventName, function (param) {
func(param, instance);
});
}
}
// loop and bind
for (var eventName in events) {
if (Object.prototype.hasOwnProperty.call(events, eventName)) {
_bindEvent(eventName, events[eventName]);
}
}
};
// off the events
EChartsReactCore.prototype.offEvents = function (instance, events) {
if (!events)
return;
// loop and off
for (var eventName in events) {
if (isString(eventName)) {
instance.off(eventName, events[eventName]);
}
}
};
/**
* render the echarts
*/
EChartsReactCore.prototype.updateEChartsOption = function () {
var _a = this.props, option = _a.option, _b = _a.notMerge, notMerge = _b === void 0 ? false : _b, _c = _a.replaceMerge, replaceMerge = _c === void 0 ? null : _c, _d = _a.lazyUpdate, lazyUpdate = _d === void 0 ? false : _d, showLoading = _a.showLoading, _e = _a.loadingOption, loadingOption = _e === void 0 ? null : _e;
// 1. get or initial the echarts object
var echartInstance = this.getEchartsInstance();
// 2. set the echarts option
echartInstance.setOption(option, { notMerge: notMerge, replaceMerge: replaceMerge, lazyUpdate: lazyUpdate });
// 3. set loading mask
if (showLoading)
echartInstance.showLoading(loadingOption);
else
echartInstance.hideLoading();
return echartInstance;
};
/**
* resize wrapper
*/
EChartsReactCore.prototype.resize = function () {
// 1. get the echarts object
var echartsInstance = this.getEchartsInstance();
// 2. call echarts instance resize if not the initial resize
// resize should not happen on first render as it will cancel initial echarts animations
if (!this.isInitialResize) {
try {
echartsInstance.resize({
width: 'auto',
height: 'auto',
});
}
catch (e) {
console.warn(e);
}
}
// 3. update variable for future calls
this.isInitialResize = false;
};
EChartsReactCore.prototype.render = function () {
var _this = this;
var _a = this.props, style = _a.style, _b = _a.className, className = _b === void 0 ? '' : _b, echarts = _a.echarts, option = _a.option, theme = _a.theme, notMerge = _a.notMerge, replaceMerge = _a.replaceMerge, lazyUpdate = _a.lazyUpdate, showLoading = _a.showLoading, loadingOption = _a.loadingOption, opts = _a.opts, onChartReady = _a.onChartReady, onEvents = _a.onEvents, shouldSetOption = _a.shouldSetOption, autoResize = _a.autoResize, divHTMLAttributes = __rest(_a, ["style", "className", "echarts", "option", "theme", "notMerge", "replaceMerge", "lazyUpdate", "showLoading", "loadingOption", "opts", "onChartReady", "onEvents", "shouldSetOption", "autoResize"]);
// default height = 300
var newStyle = __assign({ height: 300 }, style);
return (React.createElement("div", __assign({ ref: function (e) {
_this.ele = e;
}, style: newStyle, className: "echarts-for-react ".concat(className) }, divHTMLAttributes)));
};
return EChartsReactCore;
}(PureComponent));
export default EChartsReactCore;
//# sourceMappingURL=core.js.map
File diff suppressed because one or more lines are too long
@@ -0,0 +1,2 @@
import isEqual from 'fast-deep-equal';
export { isEqual };
@@ -0,0 +1,3 @@
import isEqual from 'fast-deep-equal';
export { isEqual };
//# sourceMappingURL=is-equal.js.map
@@ -0,0 +1 @@
{"version":3,"file":"is-equal.js","sourceRoot":"","sources":["../../src/helper/is-equal.ts"],"names":[],"mappings":"AAAA,OAAO,OAAO,MAAM,iBAAiB,CAAC;AAEtC,OAAO,EAAE,OAAO,EAAE,CAAC","sourcesContent":["import isEqual from 'fast-deep-equal';\n\nexport { isEqual };\n"]}
@@ -0,0 +1 @@
export declare function isFunction(v: any): boolean;
@@ -0,0 +1,4 @@
export function isFunction(v) {
return typeof v === 'function';
}
//# sourceMappingURL=is-function.js.map
@@ -0,0 +1 @@
{"version":3,"file":"is-function.js","sourceRoot":"","sources":["../../src/helper/is-function.ts"],"names":[],"mappings":"AAAA,MAAM,UAAU,UAAU,CAAC,CAAM;IAC/B,OAAO,OAAO,CAAC,KAAK,UAAU,CAAC;AACjC,CAAC","sourcesContent":["export function isFunction(v: any): boolean {\n return typeof v === 'function';\n}\n"]}
@@ -0,0 +1 @@
export declare function isString(v: any): boolean;
@@ -0,0 +1,4 @@
export function isString(v) {
return typeof v === 'string';
}
//# sourceMappingURL=is-string.js.map
@@ -0,0 +1 @@
{"version":3,"file":"is-string.js","sourceRoot":"","sources":["../../src/helper/is-string.ts"],"names":[],"mappings":"AAAA,MAAM,UAAU,QAAQ,CAAC,CAAM;IAC7B,OAAO,OAAO,CAAC,KAAK,QAAQ,CAAC;AAC/B,CAAC","sourcesContent":["export function isString(v: any): boolean {\n return typeof v === 'string';\n}\n"]}
@@ -0,0 +1,6 @@
/**
* 保留 object 中的部分内容
* @param obj
* @param keys
*/
export declare function pick<T extends object>(obj: T, keys: readonly (keyof T)[]): Partial<T>;
@@ -0,0 +1,13 @@
/**
* 保留 object 中的部分内容
* @param obj
* @param keys
*/
export function pick(obj, keys) {
var r = {};
keys.forEach(function (key) {
r[key] = obj[key];
});
return r;
}
//# sourceMappingURL=pick.js.map
@@ -0,0 +1 @@
{"version":3,"file":"pick.js","sourceRoot":"","sources":["../../src/helper/pick.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AACH,MAAM,UAAU,IAAI,CAAmB,GAAM,EAAE,IAA0B;IACvE,IAAM,CAAC,GAAG,EAAgB,CAAC;IAC3B,IAAI,CAAC,OAAO,CAAC,UAAC,GAAG;QACf,CAAC,CAAC,GAAG,CAAC,GAAG,GAAG,CAAC,GAAG,CAAC,CAAC;IACpB,CAAC,CAAC,CAAC;IACH,OAAO,CAAC,CAAC;AACX,CAAC","sourcesContent":["/**\n * 保留 object 中的部分内容\n * @param obj\n * @param keys\n */\nexport function pick<T extends object>(obj: T, keys: readonly (keyof T)[]): Partial<T> {\n const r = {} as Partial<T>;\n keys.forEach((key) => {\n r[key] = obj[key];\n });\n return r;\n}\n"]}
@@ -0,0 +1,6 @@
import { EChartsReactProps, EChartsOption, EChartsInstance } from './types';
import EChartsReactCore from './core';
export type { EChartsReactProps, EChartsOption, EChartsInstance };
export default class EChartsReact extends EChartsReactCore {
constructor(props: EChartsReactProps);
}
@@ -0,0 +1,16 @@
import { __extends } from "tslib";
import * as echarts from 'echarts';
import EChartsReactCore from './core';
// export the Component the echarts Object.
var EChartsReact = /** @class */ (function (_super) {
__extends(EChartsReact, _super);
function EChartsReact(props) {
var _this = _super.call(this, props) || this;
// 初始化为 echarts 整个包
_this.echarts = echarts;
return _this;
}
return EChartsReact;
}(EChartsReactCore));
export default EChartsReact;
//# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AAAA,OAAO,KAAK,OAAO,MAAM,SAAS,CAAC;AAEnC,OAAO,gBAAgB,MAAM,QAAQ,CAAC;AAItC,2CAA2C;AAC3C;IAA0C,gCAAgB;IACxD,sBAAY,KAAwB;QAApC,YACE,kBAAM,KAAK,CAAC,SAIb;QAFC,mBAAmB;QACnB,KAAI,CAAC,OAAO,GAAG,OAAO,CAAC;;IACzB,CAAC;IACH,mBAAC;AAAD,CAAC,AAPD,CAA0C,gBAAgB,GAOzD","sourcesContent":["import * as echarts from 'echarts';\nimport { EChartsReactProps, EChartsOption, EChartsInstance } from './types';\nimport EChartsReactCore from './core';\n\nexport type { EChartsReactProps, EChartsOption, EChartsInstance };\n\n// export the Component the echarts Object.\nexport default class EChartsReact extends EChartsReactCore {\n constructor(props: EChartsReactProps) {\n super(props);\n\n // 初始化为 echarts 整个包\n this.echarts = echarts;\n }\n}\n"]}
@@ -0,0 +1,70 @@
/// <reference types="react" />
import type { EChartsType } from 'echarts';
/**
* Solve the type conflict caused by multiple type files
*/
export type EChartsOption = any;
export type EChartsInstance = EChartsType;
export type Opts = {
readonly devicePixelRatio?: number;
readonly renderer?: 'canvas' | 'svg';
readonly width?: number | null | undefined | 'auto';
readonly height?: number | null | undefined | 'auto';
readonly locale?: string;
};
export type EChartsReactProps = React.HTMLAttributes<HTMLDivElement> & {
/**
* echarts library entry, use it for import necessary.
*/
readonly echarts?: any;
/**
* echarts option
*/
readonly option: EChartsOption;
/**
* echarts theme config, can be:
* 1. theme name string
* 2. theme object
*/
readonly theme?: string | Record<string, any>;
/**
* notMerge config for echarts, default is `false`
*/
readonly notMerge?: boolean;
/**
* replaceMerge config for echarts, default is `null`
*/
readonly replaceMerge?: string | string[];
/**
* lazyUpdate config for echarts, default is `false`
*/
readonly lazyUpdate?: boolean;
/**
* showLoading config for echarts, default is `false`
*/
readonly showLoading?: boolean;
/**
* loadingOption config for echarts, default is `null`
*/
readonly loadingOption?: any;
/**
* echarts opts config, default is `{}`
*/
readonly opts?: Opts;
/**
* when after chart render, do the callback with echarts instance
*/
readonly onChartReady?: (instance: EChartsInstance) => void;
/**
* bind events, default is `{}`
*/
readonly onEvents?: Record<string, Function>;
/**
* should update echarts options
*/
readonly shouldSetOption?: (prevProps: EChartsReactProps, props: EChartsReactProps) => boolean;
/**
* should trigger resize when window resize
*/
readonly autoResize?: boolean;
};
@@ -0,0 +1,2 @@
export {};
//# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
{"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"","sourcesContent":["import type { EChartsType } from 'echarts';\n\n/**\n * Solve the type conflict caused by multiple type files\n */\nexport type EChartsOption = any;\n\nexport type EChartsInstance = EChartsType;\n\nexport type Opts = {\n readonly devicePixelRatio?: number;\n readonly renderer?: 'canvas' | 'svg';\n readonly width?: number | null | undefined | 'auto';\n readonly height?: number | null | undefined | 'auto';\n readonly locale?: string;\n};\n\nexport type EChartsReactProps = React.HTMLAttributes<HTMLDivElement> & {\n /**\n * echarts library entry, use it for import necessary.\n */\n readonly echarts?: any;\n /**\n * echarts option\n */\n readonly option: EChartsOption;\n /**\n * echarts theme config, can be:\n * 1. theme name string\n * 2. theme object\n */\n readonly theme?: string | Record<string, any>;\n /**\n * notMerge config for echarts, default is `false`\n */\n readonly notMerge?: boolean;\n /**\n * replaceMerge config for echarts, default is `null`\n */\n readonly replaceMerge?: string | string[];\n /**\n * lazyUpdate config for echarts, default is `false`\n */\n readonly lazyUpdate?: boolean;\n /**\n * showLoading config for echarts, default is `false`\n */\n readonly showLoading?: boolean;\n /**\n * loadingOption config for echarts, default is `null`\n */\n readonly loadingOption?: any;\n /**\n * echarts opts config, default is `{}`\n */\n readonly opts?: Opts;\n /**\n * when after chart render, do the callback with echarts instance\n */\n readonly onChartReady?: (instance: EChartsInstance) => void;\n /**\n * bind events, default is `{}`\n */\n readonly onEvents?: Record<string, Function>;\n /**\n * should update echarts options\n */\n readonly shouldSetOption?: (prevProps: EChartsReactProps, props: EChartsReactProps) => boolean;\n\n /**\n * should trigger resize when window resize\n */\n readonly autoResize?: boolean;\n};\n"]}
@@ -0,0 +1,48 @@
import type { ECharts } from 'echarts';
import { PureComponent } from 'react';
import { EChartsReactProps } from './types';
/**
* core component for echarts binding
*/
export default class EChartsReactCore extends PureComponent<EChartsReactProps> {
/**
* echarts render container
*/
ele: HTMLElement;
/**
* if this is the first time we are resizing
*/
private isInitialResize;
/**
* echarts library entry
*/
protected echarts: any;
constructor(props: EChartsReactProps);
componentDidMount(): void;
componentDidUpdate(prevProps: EChartsReactProps): void;
componentWillUnmount(): void;
initEchartsInstance(): Promise<ECharts>;
/**
* return the existing echart object
*/
getEchartsInstance(): ECharts;
/**
* dispose echarts and clear size-sensor
*/
private dispose;
/**
* render a new echarts instance
*/
private renderNewEcharts;
private bindEvents;
private offEvents;
/**
* render the echarts
*/
private updateEChartsOption;
/**
* resize wrapper
*/
private resize;
render(): JSX.Element;
}
@@ -0,0 +1,223 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
var tslib_1 = require("tslib");
var react_1 = tslib_1.__importStar(require("react"));
var size_sensor_1 = require("size-sensor");
var pick_1 = require("./helper/pick");
var is_function_1 = require("./helper/is-function");
var is_string_1 = require("./helper/is-string");
var is_equal_1 = require("./helper/is-equal");
/**
* core component for echarts binding
*/
var EChartsReactCore = /** @class */ (function (_super) {
tslib_1.__extends(EChartsReactCore, _super);
function EChartsReactCore(props) {
var _this = _super.call(this, props) || this;
_this.echarts = props.echarts;
_this.ele = null;
_this.isInitialResize = true;
return _this;
}
EChartsReactCore.prototype.componentDidMount = function () {
this.renderNewEcharts();
};
// update
EChartsReactCore.prototype.componentDidUpdate = function (prevProps) {
/**
* if shouldSetOption return false, then return, not update echarts options
* default is true
*/
var shouldSetOption = this.props.shouldSetOption;
if ((0, is_function_1.isFunction)(shouldSetOption) && !shouldSetOption(prevProps, this.props)) {
return;
}
// 以下属性修改的时候,需要 dispose 之后再新建
// 1. 切换 theme 的时候
// 2. 修改 opts 的时候
if (!(0, is_equal_1.isEqual)(prevProps.theme, this.props.theme) || !(0, is_equal_1.isEqual)(prevProps.opts, this.props.opts)) {
this.dispose();
this.renderNewEcharts(); // 重建
return;
}
// 修改 onEvent 的时候先移除历史事件再添加
var echartsInstance = this.getEchartsInstance();
if (!(0, is_equal_1.isEqual)(prevProps.onEvents, this.props.onEvents)) {
this.offEvents(echartsInstance, prevProps.onEvents);
this.bindEvents(echartsInstance, this.props.onEvents);
}
// when these props are not isEqual, update echarts
var pickKeys = ['option', 'notMerge', 'replaceMerge', 'lazyUpdate', 'showLoading', 'loadingOption'];
if (!(0, is_equal_1.isEqual)((0, pick_1.pick)(this.props, pickKeys), (0, pick_1.pick)(prevProps, pickKeys))) {
this.updateEChartsOption();
}
/**
* when style or class name updated, change size.
*/
if (!(0, is_equal_1.isEqual)(prevProps.style, this.props.style) || !(0, is_equal_1.isEqual)(prevProps.className, this.props.className)) {
this.resize();
}
};
EChartsReactCore.prototype.componentWillUnmount = function () {
this.dispose();
};
/*
* initialise an echarts instance
*/
EChartsReactCore.prototype.initEchartsInstance = function () {
return tslib_1.__awaiter(this, void 0, void 0, function () {
var _this = this;
return tslib_1.__generator(this, function (_a) {
return [2 /*return*/, new Promise(function (resolve) {
// create temporary echart instance
_this.echarts.init(_this.ele, _this.props.theme, _this.props.opts);
var echartsInstance = _this.getEchartsInstance();
echartsInstance.on('finished', function () {
// get final width and height
var width = _this.ele.clientWidth;
var height = _this.ele.clientHeight;
// dispose temporary echart instance
_this.echarts.dispose(_this.ele);
// recreate echart instance
// we use final width and height only if not originally provided as opts
var opts = tslib_1.__assign({ width: width, height: height }, _this.props.opts);
resolve(_this.echarts.init(_this.ele, _this.props.theme, opts));
});
})];
});
});
};
/**
* return the existing echart object
*/
EChartsReactCore.prototype.getEchartsInstance = function () {
return this.echarts.getInstanceByDom(this.ele);
};
/**
* dispose echarts and clear size-sensor
*/
EChartsReactCore.prototype.dispose = function () {
if (this.ele) {
try {
(0, size_sensor_1.clear)(this.ele);
}
catch (e) {
console.warn(e);
}
// dispose echarts instance
this.echarts.dispose(this.ele);
}
};
/**
* render a new echarts instance
*/
EChartsReactCore.prototype.renderNewEcharts = function () {
return tslib_1.__awaiter(this, void 0, void 0, function () {
var _a, onEvents, onChartReady, _b, autoResize, echartsInstance;
var _this = this;
return tslib_1.__generator(this, function (_c) {
switch (_c.label) {
case 0:
_a = this.props, onEvents = _a.onEvents, onChartReady = _a.onChartReady, _b = _a.autoResize, autoResize = _b === void 0 ? true : _b;
// 1. init echarts instance
return [4 /*yield*/, this.initEchartsInstance()];
case 1:
// 1. init echarts instance
_c.sent();
echartsInstance = this.updateEChartsOption();
// 3. bind events
this.bindEvents(echartsInstance, onEvents || {});
// 4. on chart ready
if ((0, is_function_1.isFunction)(onChartReady))
onChartReady(echartsInstance);
// 5. on resize
if (this.ele && autoResize) {
(0, size_sensor_1.bind)(this.ele, function () {
_this.resize();
});
}
return [2 /*return*/];
}
});
});
};
// bind the events
EChartsReactCore.prototype.bindEvents = function (instance, events) {
function _bindEvent(eventName, func) {
// ignore the event config which not satisfy
if ((0, is_string_1.isString)(eventName) && (0, is_function_1.isFunction)(func)) {
// binding event
instance.on(eventName, function (param) {
func(param, instance);
});
}
}
// loop and bind
for (var eventName in events) {
if (Object.prototype.hasOwnProperty.call(events, eventName)) {
_bindEvent(eventName, events[eventName]);
}
}
};
// off the events
EChartsReactCore.prototype.offEvents = function (instance, events) {
if (!events)
return;
// loop and off
for (var eventName in events) {
if ((0, is_string_1.isString)(eventName)) {
instance.off(eventName, events[eventName]);
}
}
};
/**
* render the echarts
*/
EChartsReactCore.prototype.updateEChartsOption = function () {
var _a = this.props, option = _a.option, _b = _a.notMerge, notMerge = _b === void 0 ? false : _b, _c = _a.replaceMerge, replaceMerge = _c === void 0 ? null : _c, _d = _a.lazyUpdate, lazyUpdate = _d === void 0 ? false : _d, showLoading = _a.showLoading, _e = _a.loadingOption, loadingOption = _e === void 0 ? null : _e;
// 1. get or initial the echarts object
var echartInstance = this.getEchartsInstance();
// 2. set the echarts option
echartInstance.setOption(option, { notMerge: notMerge, replaceMerge: replaceMerge, lazyUpdate: lazyUpdate });
// 3. set loading mask
if (showLoading)
echartInstance.showLoading(loadingOption);
else
echartInstance.hideLoading();
return echartInstance;
};
/**
* resize wrapper
*/
EChartsReactCore.prototype.resize = function () {
// 1. get the echarts object
var echartsInstance = this.getEchartsInstance();
// 2. call echarts instance resize if not the initial resize
// resize should not happen on first render as it will cancel initial echarts animations
if (!this.isInitialResize) {
try {
echartsInstance.resize({
width: 'auto',
height: 'auto',
});
}
catch (e) {
console.warn(e);
}
}
// 3. update variable for future calls
this.isInitialResize = false;
};
EChartsReactCore.prototype.render = function () {
var _this = this;
var _a = this.props, style = _a.style, _b = _a.className, className = _b === void 0 ? '' : _b, echarts = _a.echarts, option = _a.option, theme = _a.theme, notMerge = _a.notMerge, replaceMerge = _a.replaceMerge, lazyUpdate = _a.lazyUpdate, showLoading = _a.showLoading, loadingOption = _a.loadingOption, opts = _a.opts, onChartReady = _a.onChartReady, onEvents = _a.onEvents, shouldSetOption = _a.shouldSetOption, autoResize = _a.autoResize, divHTMLAttributes = tslib_1.__rest(_a, ["style", "className", "echarts", "option", "theme", "notMerge", "replaceMerge", "lazyUpdate", "showLoading", "loadingOption", "opts", "onChartReady", "onEvents", "shouldSetOption", "autoResize"]);
// default height = 300
var newStyle = tslib_1.__assign({ height: 300 }, style);
return (react_1.default.createElement("div", tslib_1.__assign({ ref: function (e) {
_this.ele = e;
}, style: newStyle, className: "echarts-for-react ".concat(className) }, divHTMLAttributes)));
};
return EChartsReactCore;
}(react_1.PureComponent));
exports.default = EChartsReactCore;
//# sourceMappingURL=core.js.map
File diff suppressed because one or more lines are too long
@@ -0,0 +1,2 @@
import isEqual from 'fast-deep-equal';
export { isEqual };
@@ -0,0 +1,7 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.isEqual = void 0;
var tslib_1 = require("tslib");
var fast_deep_equal_1 = tslib_1.__importDefault(require("fast-deep-equal"));
exports.isEqual = fast_deep_equal_1.default;
//# sourceMappingURL=is-equal.js.map
@@ -0,0 +1 @@
{"version":3,"file":"is-equal.js","sourceRoot":"","sources":["../../src/helper/is-equal.ts"],"names":[],"mappings":";;;;AAAA,4EAAsC;AAE7B,kBAFF,yBAAO,CAEE","sourcesContent":["import isEqual from 'fast-deep-equal';\n\nexport { isEqual };\n"]}
@@ -0,0 +1 @@
export declare function isFunction(v: any): boolean;
@@ -0,0 +1,8 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.isFunction = void 0;
function isFunction(v) {
return typeof v === 'function';
}
exports.isFunction = isFunction;
//# sourceMappingURL=is-function.js.map
@@ -0,0 +1 @@
{"version":3,"file":"is-function.js","sourceRoot":"","sources":["../../src/helper/is-function.ts"],"names":[],"mappings":";;;AAAA,SAAgB,UAAU,CAAC,CAAM;IAC/B,OAAO,OAAO,CAAC,KAAK,UAAU,CAAC;AACjC,CAAC;AAFD,gCAEC","sourcesContent":["export function isFunction(v: any): boolean {\n return typeof v === 'function';\n}\n"]}
@@ -0,0 +1 @@
export declare function isString(v: any): boolean;
@@ -0,0 +1,8 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.isString = void 0;
function isString(v) {
return typeof v === 'string';
}
exports.isString = isString;
//# sourceMappingURL=is-string.js.map
@@ -0,0 +1 @@
{"version":3,"file":"is-string.js","sourceRoot":"","sources":["../../src/helper/is-string.ts"],"names":[],"mappings":";;;AAAA,SAAgB,QAAQ,CAAC,CAAM;IAC7B,OAAO,OAAO,CAAC,KAAK,QAAQ,CAAC;AAC/B,CAAC;AAFD,4BAEC","sourcesContent":["export function isString(v: any): boolean {\n return typeof v === 'string';\n}\n"]}
@@ -0,0 +1,6 @@
/**
* 保留 object 中的部分内容
* @param obj
* @param keys
*/
export declare function pick<T extends object>(obj: T, keys: readonly (keyof T)[]): Partial<T>;
@@ -0,0 +1,17 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.pick = void 0;
/**
* 保留 object 中的部分内容
* @param obj
* @param keys
*/
function pick(obj, keys) {
var r = {};
keys.forEach(function (key) {
r[key] = obj[key];
});
return r;
}
exports.pick = pick;
//# sourceMappingURL=pick.js.map
@@ -0,0 +1 @@
{"version":3,"file":"pick.js","sourceRoot":"","sources":["../../src/helper/pick.ts"],"names":[],"mappings":";;;AAAA;;;;GAIG;AACH,SAAgB,IAAI,CAAmB,GAAM,EAAE,IAA0B;IACvE,IAAM,CAAC,GAAG,EAAgB,CAAC;IAC3B,IAAI,CAAC,OAAO,CAAC,UAAC,GAAG;QACf,CAAC,CAAC,GAAG,CAAC,GAAG,GAAG,CAAC,GAAG,CAAC,CAAC;IACpB,CAAC,CAAC,CAAC;IACH,OAAO,CAAC,CAAC;AACX,CAAC;AAND,oBAMC","sourcesContent":["/**\n * 保留 object 中的部分内容\n * @param obj\n * @param keys\n */\nexport function pick<T extends object>(obj: T, keys: readonly (keyof T)[]): Partial<T> {\n const r = {} as Partial<T>;\n keys.forEach((key) => {\n r[key] = obj[key];\n });\n return r;\n}\n"]}
@@ -0,0 +1,6 @@
import { EChartsReactProps, EChartsOption, EChartsInstance } from './types';
import EChartsReactCore from './core';
export type { EChartsReactProps, EChartsOption, EChartsInstance };
export default class EChartsReact extends EChartsReactCore {
constructor(props: EChartsReactProps);
}
@@ -0,0 +1,18 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
var tslib_1 = require("tslib");
var echarts = tslib_1.__importStar(require("echarts"));
var core_1 = tslib_1.__importDefault(require("./core"));
// export the Component the echarts Object.
var EChartsReact = /** @class */ (function (_super) {
tslib_1.__extends(EChartsReact, _super);
function EChartsReact(props) {
var _this = _super.call(this, props) || this;
// 初始化为 echarts 整个包
_this.echarts = echarts;
return _this;
}
return EChartsReact;
}(core_1.default));
exports.default = EChartsReact;
//# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";;;AAAA,uDAAmC;AAEnC,wDAAsC;AAItC,2CAA2C;AAC3C;IAA0C,wCAAgB;IACxD,sBAAY,KAAwB;QAApC,YACE,kBAAM,KAAK,CAAC,SAIb;QAFC,mBAAmB;QACnB,KAAI,CAAC,OAAO,GAAG,OAAO,CAAC;;IACzB,CAAC;IACH,mBAAC;AAAD,CAAC,AAPD,CAA0C,cAAgB,GAOzD","sourcesContent":["import * as echarts from 'echarts';\nimport { EChartsReactProps, EChartsOption, EChartsInstance } from './types';\nimport EChartsReactCore from './core';\n\nexport type { EChartsReactProps, EChartsOption, EChartsInstance };\n\n// export the Component the echarts Object.\nexport default class EChartsReact extends EChartsReactCore {\n constructor(props: EChartsReactProps) {\n super(props);\n\n // 初始化为 echarts 整个包\n this.echarts = echarts;\n }\n}\n"]}
@@ -0,0 +1,70 @@
/// <reference types="react" />
import type { EChartsType } from 'echarts';
/**
* Solve the type conflict caused by multiple type files
*/
export type EChartsOption = any;
export type EChartsInstance = EChartsType;
export type Opts = {
readonly devicePixelRatio?: number;
readonly renderer?: 'canvas' | 'svg';
readonly width?: number | null | undefined | 'auto';
readonly height?: number | null | undefined | 'auto';
readonly locale?: string;
};
export type EChartsReactProps = React.HTMLAttributes<HTMLDivElement> & {
/**
* echarts library entry, use it for import necessary.
*/
readonly echarts?: any;
/**
* echarts option
*/
readonly option: EChartsOption;
/**
* echarts theme config, can be:
* 1. theme name string
* 2. theme object
*/
readonly theme?: string | Record<string, any>;
/**
* notMerge config for echarts, default is `false`
*/
readonly notMerge?: boolean;
/**
* replaceMerge config for echarts, default is `null`
*/
readonly replaceMerge?: string | string[];
/**
* lazyUpdate config for echarts, default is `false`
*/
readonly lazyUpdate?: boolean;
/**
* showLoading config for echarts, default is `false`
*/
readonly showLoading?: boolean;
/**
* loadingOption config for echarts, default is `null`
*/
readonly loadingOption?: any;
/**
* echarts opts config, default is `{}`
*/
readonly opts?: Opts;
/**
* when after chart render, do the callback with echarts instance
*/
readonly onChartReady?: (instance: EChartsInstance) => void;
/**
* bind events, default is `{}`
*/
readonly onEvents?: Record<string, Function>;
/**
* should update echarts options
*/
readonly shouldSetOption?: (prevProps: EChartsReactProps, props: EChartsReactProps) => boolean;
/**
* should trigger resize when window resize
*/
readonly autoResize?: boolean;
};
@@ -0,0 +1,3 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
//# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
{"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"","sourcesContent":["import type { EChartsType } from 'echarts';\n\n/**\n * Solve the type conflict caused by multiple type files\n */\nexport type EChartsOption = any;\n\nexport type EChartsInstance = EChartsType;\n\nexport type Opts = {\n readonly devicePixelRatio?: number;\n readonly renderer?: 'canvas' | 'svg';\n readonly width?: number | null | undefined | 'auto';\n readonly height?: number | null | undefined | 'auto';\n readonly locale?: string;\n};\n\nexport type EChartsReactProps = React.HTMLAttributes<HTMLDivElement> & {\n /**\n * echarts library entry, use it for import necessary.\n */\n readonly echarts?: any;\n /**\n * echarts option\n */\n readonly option: EChartsOption;\n /**\n * echarts theme config, can be:\n * 1. theme name string\n * 2. theme object\n */\n readonly theme?: string | Record<string, any>;\n /**\n * notMerge config for echarts, default is `false`\n */\n readonly notMerge?: boolean;\n /**\n * replaceMerge config for echarts, default is `null`\n */\n readonly replaceMerge?: string | string[];\n /**\n * lazyUpdate config for echarts, default is `false`\n */\n readonly lazyUpdate?: boolean;\n /**\n * showLoading config for echarts, default is `false`\n */\n readonly showLoading?: boolean;\n /**\n * loadingOption config for echarts, default is `null`\n */\n readonly loadingOption?: any;\n /**\n * echarts opts config, default is `{}`\n */\n readonly opts?: Opts;\n /**\n * when after chart render, do the callback with echarts instance\n */\n readonly onChartReady?: (instance: EChartsInstance) => void;\n /**\n * bind events, default is `{}`\n */\n readonly onEvents?: Record<string, Function>;\n /**\n * should update echarts options\n */\n readonly shouldSetOption?: (prevProps: EChartsReactProps, props: EChartsReactProps) => boolean;\n\n /**\n * should trigger resize when window resize\n */\n readonly autoResize?: boolean;\n};\n"]}
@@ -0,0 +1,116 @@
{
"name": "echarts-for-react",
"version": "3.0.5",
"description": " Apache Echarts components for React.",
"main": "lib/index.js",
"module": "esm/index.js",
"types": "lib/index.d.ts",
"files": [
"lib",
"esm",
"src"
],
"scripts": {
"docs:dev": "NODE_ENV=development dumi dev",
"docs:build": "NODE_ENV=production dumi build",
"docs:deploy": "rimraf dist && npm run docs:build && gh-pages -d dist",
"start": "npm run docs:dev",
"lint": "eslint src __tests__ && prettier src __tests__ --check",
"fix": "eslint src __tests__ --fix && prettier src __tests__ --write",
"clean": "rimraf lib esm dist",
"test": "jest",
"lib": "run-p lib:*",
"lib:cjs": "tsc -p tsconfig.json --target ES5 --module commonjs --outDir lib",
"lib:esm": "tsc -p tsconfig.json --target ES5 --module ESNext --outDir esm",
"build": "npm run clean && npm run test && npm run lib"
},
"repository": {
"type": "git",
"url": "https://github.com/hustcc/echarts-for-react.git"
},
"keywords": [
"react",
"component",
"echarts-react",
"echarts",
"react-echarts",
"chart",
"charts",
"graph",
"react-component"
],
"author": "hustcc (http://github.com/hustcc)",
"license": "MIT",
"bugs": {
"url": "https://github.com/hustcc/echarts-for-react/issues"
},
"homepage": "https://github.com/hustcc/echarts-for-react",
"devDependencies": {
"@commitlint/cli": "^12.0.0",
"@commitlint/config-angular": "^12.0.0",
"@types/jest": "^24.0.0",
"@types/node": "^14.14.31",
"@types/react": "^17.0.2",
"@typescript-eslint/eslint-plugin": "^4.15.2",
"@typescript-eslint/parser": "^4.15.2",
"cross-env": "^7.0.3",
"dumi": "^1.1.6",
"dumi-theme-default": "^1.0.6",
"echarts": "^6.0.0",
"echarts-gl": "^2.0.2",
"eslint": "^7.20.0",
"eslint-config-prettier": "^8.1.0",
"eslint-plugin-import": "^2.22.1",
"eslint-plugin-prettier": "^3.3.1",
"gh-pages": "^3.1.0",
"husky": "^5.1.1",
"jest": "^24.0.0",
"jest-canvas-mock": "^2.3.1",
"jest-electron": "^0.1.11",
"lint-md-cli": "^0.1.2",
"lint-staged": "^10.5.4",
"lodash.clonedeep": "^4.5.0",
"miz": "^1.0.1",
"npm-run-all": "^4.1.5",
"prettier": "^2.2.1",
"rimraf": "^3.0.2",
"ts-jest": "^24.0.2",
"ts-loader": "^8.0.17",
"typescript": "^4.2.2"
},
"dependencies": {
"size-sensor": "^1.0.1",
"fast-deep-equal": "^3.1.3"
},
"peerDependencies": {
"react": "^15.0.0 || >=16.0.0",
"echarts": "^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0"
},
"jest": {
"runner": "jest-electron/runner",
"testEnvironment": "jest-electron/environment",
"preset": "ts-jest",
"collectCoverage": true,
"collectCoverageFrom": [
"src/**/*.ts",
"!**/node_modules/**",
"!**/vendor/**"
],
"testRegex": "/__tests__/.*-spec\\.tsx?$"
},
"husky": {
"hooks": {
"pre-commit": "lint-staged",
"commit-msg": "commitlint -E HUSKY_GIT_PARAMS"
}
},
"lint-staged": {
"*.ts": [
"eslint --fix",
"prettier --write"
],
"*.md": [
"lint-md --fix"
]
}
}
@@ -0,0 +1,275 @@
import type { ECharts } from 'echarts';
import React, { PureComponent } from 'react';
import { bind, clear } from 'size-sensor';
import { pick } from './helper/pick';
import { isFunction } from './helper/is-function';
import { isString } from './helper/is-string';
import { isEqual } from './helper/is-equal';
import { EChartsReactProps, EChartsInstance } from './types';
/**
* core component for echarts binding
*/
export default class EChartsReactCore extends PureComponent<EChartsReactProps> {
/**
* echarts render container
*/
public ele: HTMLElement;
/**
* if this is the first time we are resizing
*/
private isInitialResize: boolean;
/**
* echarts library entry
*/
protected echarts: any;
constructor(props: EChartsReactProps) {
super(props);
this.echarts = props.echarts;
this.ele = null;
this.isInitialResize = true;
}
componentDidMount() {
this.renderNewEcharts();
}
// update
componentDidUpdate(prevProps: EChartsReactProps) {
/**
* if shouldSetOption return false, then return, not update echarts options
* default is true
*/
const { shouldSetOption } = this.props;
if (isFunction(shouldSetOption) && !shouldSetOption(prevProps, this.props)) {
return;
}
// 以下属性修改的时候,需要 dispose 之后再新建
// 1. 切换 theme 的时候
// 2. 修改 opts 的时候
if (!isEqual(prevProps.theme, this.props.theme) || !isEqual(prevProps.opts, this.props.opts)) {
this.dispose();
this.renderNewEcharts(); // 重建
return;
}
// 修改 onEvent 的时候先移除历史事件再添加
const echartsInstance = this.getEchartsInstance();
if (!isEqual(prevProps.onEvents, this.props.onEvents)) {
this.offEvents(echartsInstance, prevProps.onEvents);
this.bindEvents(echartsInstance, this.props.onEvents);
}
// when these props are not isEqual, update echarts
const pickKeys = ['option', 'notMerge', 'replaceMerge', 'lazyUpdate', 'showLoading', 'loadingOption'] as const;
if (!isEqual(pick(this.props, pickKeys), pick(prevProps as any, pickKeys))) {
this.updateEChartsOption();
}
/**
* when style or class name updated, change size.
*/
if (!isEqual(prevProps.style, this.props.style) || !isEqual(prevProps.className, this.props.className)) {
this.resize();
}
}
componentWillUnmount() {
this.dispose();
}
/*
* initialise an echarts instance
*/
public async initEchartsInstance(): Promise<ECharts> {
return new Promise((resolve) => {
// create temporary echart instance
this.echarts.init(this.ele, this.props.theme, this.props.opts);
const echartsInstance = this.getEchartsInstance();
echartsInstance.on('finished', () => {
// get final width and height
const width = this.ele.clientWidth;
const height = this.ele.clientHeight;
// dispose temporary echart instance
this.echarts.dispose(this.ele);
// recreate echart instance
// we use final width and height only if not originally provided as opts
const opts = {
width,
height,
...this.props.opts,
};
resolve(this.echarts.init(this.ele, this.props.theme, opts));
});
});
}
/**
* return the existing echart object
*/
public getEchartsInstance(): ECharts {
return this.echarts.getInstanceByDom(this.ele);
}
/**
* dispose echarts and clear size-sensor
*/
private dispose() {
if (this.ele) {
try {
clear(this.ele);
} catch (e) {
console.warn(e);
}
// dispose echarts instance
this.echarts.dispose(this.ele);
}
}
/**
* render a new echarts instance
*/
private async renderNewEcharts() {
const { onEvents, onChartReady, autoResize = true } = this.props;
// 1. init echarts instance
await this.initEchartsInstance();
// 2. update echarts instance
const echartsInstance = this.updateEChartsOption();
// 3. bind events
this.bindEvents(echartsInstance, onEvents || {});
// 4. on chart ready
if (isFunction(onChartReady)) onChartReady(echartsInstance);
// 5. on resize
if (this.ele && autoResize) {
bind(this.ele, () => {
this.resize();
});
}
}
// bind the events
private bindEvents(instance, events: EChartsReactProps['onEvents']) {
function _bindEvent(eventName: string, func: Function) {
// ignore the event config which not satisfy
if (isString(eventName) && isFunction(func)) {
// binding event
instance.on(eventName, (param) => {
func(param, instance);
});
}
}
// loop and bind
for (const eventName in events) {
if (Object.prototype.hasOwnProperty.call(events, eventName)) {
_bindEvent(eventName, events[eventName]);
}
}
}
// off the events
private offEvents(instance, events: EChartsReactProps['onEvents']) {
if (!events) return;
// loop and off
for (const eventName in events) {
if (isString(eventName)) {
instance.off(eventName, events[eventName]);
}
}
}
/**
* render the echarts
*/
private updateEChartsOption(): EChartsInstance {
const {
option,
notMerge = false,
replaceMerge = null,
lazyUpdate = false,
showLoading,
loadingOption = null,
} = this.props;
// 1. get or initial the echarts object
const echartInstance = this.getEchartsInstance();
// 2. set the echarts option
echartInstance.setOption(option, { notMerge, replaceMerge, lazyUpdate });
// 3. set loading mask
if (showLoading) echartInstance.showLoading(loadingOption);
else echartInstance.hideLoading();
return echartInstance;
}
/**
* resize wrapper
*/
private resize() {
// 1. get the echarts object
const echartsInstance = this.getEchartsInstance();
// 2. call echarts instance resize if not the initial resize
// resize should not happen on first render as it will cancel initial echarts animations
if (!this.isInitialResize) {
try {
echartsInstance.resize({
width: 'auto',
height: 'auto',
});
} catch (e) {
console.warn(e);
}
}
// 3. update variable for future calls
this.isInitialResize = false;
}
render(): JSX.Element {
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 };
return (
<div
ref={(e: HTMLElement) => {
this.ele = e;
}}
style={newStyle}
className={`echarts-for-react ${className}`}
{...divHTMLAttributes}
/>
);
}
}
@@ -0,0 +1,3 @@
import isEqual from 'fast-deep-equal';
export { isEqual };
@@ -0,0 +1,3 @@
export function isFunction(v: any): boolean {
return typeof v === 'function';
}
@@ -0,0 +1,3 @@
export function isString(v: any): boolean {
return typeof v === 'string';
}
@@ -0,0 +1,12 @@
/**
* 保留 object 中的部分内容
* @param obj
* @param keys
*/
export function pick<T extends object>(obj: T, keys: readonly (keyof T)[]): Partial<T> {
const r = {} as Partial<T>;
keys.forEach((key) => {
r[key] = obj[key];
});
return r;
}
@@ -0,0 +1,15 @@
import * as echarts from 'echarts';
import { EChartsReactProps, EChartsOption, EChartsInstance } from './types';
import EChartsReactCore from './core';
export type { EChartsReactProps, EChartsOption, EChartsInstance };
// export the Component the echarts Object.
export default class EChartsReact extends EChartsReactCore {
constructor(props: EChartsReactProps) {
super(props);
// 初始化为 echarts 整个包
this.echarts = echarts;
}
}
@@ -0,0 +1,74 @@
import type { EChartsType } from 'echarts';
/**
* Solve the type conflict caused by multiple type files
*/
export type EChartsOption = any;
export type EChartsInstance = EChartsType;
export type Opts = {
readonly devicePixelRatio?: number;
readonly renderer?: 'canvas' | 'svg';
readonly width?: number | null | undefined | 'auto';
readonly height?: number | null | undefined | 'auto';
readonly locale?: string;
};
export type EChartsReactProps = React.HTMLAttributes<HTMLDivElement> & {
/**
* echarts library entry, use it for import necessary.
*/
readonly echarts?: any;
/**
* echarts option
*/
readonly option: EChartsOption;
/**
* echarts theme config, can be:
* 1. theme name string
* 2. theme object
*/
readonly theme?: string | Record<string, any>;
/**
* notMerge config for echarts, default is `false`
*/
readonly notMerge?: boolean;
/**
* replaceMerge config for echarts, default is `null`
*/
readonly replaceMerge?: string | string[];
/**
* lazyUpdate config for echarts, default is `false`
*/
readonly lazyUpdate?: boolean;
/**
* showLoading config for echarts, default is `false`
*/
readonly showLoading?: boolean;
/**
* loadingOption config for echarts, default is `null`
*/
readonly loadingOption?: any;
/**
* echarts opts config, default is `{}`
*/
readonly opts?: Opts;
/**
* when after chart render, do the callback with echarts instance
*/
readonly onChartReady?: (instance: EChartsInstance) => void;
/**
* bind events, default is `{}`
*/
readonly onEvents?: Record<string, Function>;
/**
* should update echarts options
*/
readonly shouldSetOption?: (prevProps: EChartsReactProps, props: EChartsReactProps) => boolean;
/**
* should trigger resize when window resize
*/
readonly autoResize?: boolean;
};
@@ -0,0 +1 @@
../../fast-deep-equal@3.1.3/node_modules/fast-deep-equal
@@ -0,0 +1 @@
../../react@19.2.0/node_modules/react
@@ -0,0 +1 @@
../../size-sensor@1.0.2/node_modules/size-sensor