@visactor/openinula-vchart
Version:
The openinula version of VChart 4.x
99 lines (90 loc) • 5.66 kB
JavaScript
import React, { useState, useEffect, useRef, useImperativeHandle } from "openinula";
import withContainer from "../containers/withContainer";
import RootChartContext from "../context/chart";
import { isEqual, isNil, pickWithout } from "@visactor/vutils";
import { toArray } from "../util";
import { REACT_PRIVATE_PROPS } from "../constants";
import { bindEventsToChart, CHART_EVENTS_KEYS, CHART_EVENTS } from "../eventsUtils";
import { initCustomTooltip } from "../components/tooltip/util";
const notSpecKeys = [ ...REACT_PRIVATE_PROPS, ...CHART_EVENTS_KEYS, "vchartConstructor", "vchartConstrouctor", "useSyncRender", "skipFunctionDiff", "onError", "onReady", "spec", "container", "options" ], getComponentId = (child, index) => `${child && child.type && (child.type.displayName || child.type.name)}-${index}`, parseSpecFromChildren = props => {
const specFromChildren = {};
return toArray(props.children).map(((child, index) => {
const parseSpec = child && child.type && child.type.parseSpec;
if (parseSpec && child.props) {
const specResult = parseSpec(isNil(child.props.componentId) ? Object.assign(Object.assign({}, child.props), {
componentId: getComponentId(child, index)
}) : child.props);
specResult.isSingle ? specFromChildren[specResult.specName] = specResult.spec : (specFromChildren[specResult.specName] || (specFromChildren[specResult.specName] = []),
specFromChildren[specResult.specName].push(specResult.spec));
}
})), specFromChildren;
}, BaseChart = React.forwardRef(((props, ref) => {
const [updateId, setUpdateId] = useState(0), chartContext = useRef({});
useImperativeHandle(ref, (() => {
var _a;
return null === (_a = chartContext.current) || void 0 === _a ? void 0 : _a.chart;
}));
const hasSpec = !!props.spec, isUnmount = useRef(!1), prevSpec = useRef(pickWithout(props, notSpecKeys)), specFromChildren = useRef(null), eventsBinded = React.useRef(null), skipFunctionDiff = !!props.skipFunctionDiff, [tooltipNode, setTooltipNode] = useState(null), parseSpec = props => {
let spec;
spec = hasSpec && props.spec ? props.spec : Object.assign(Object.assign({}, prevSpec.current), specFromChildren.current);
const tooltipSpec = initCustomTooltip(setTooltipNode, props, spec.tooltip);
return tooltipSpec && (spec.tooltip = tooltipSpec), spec;
}, handleChartRender = () => {
if (!isUnmount.current) {
if (!chartContext.current || !chartContext.current.chart) return;
bindEventsToChart(chartContext.current.chart, props, eventsBinded.current, CHART_EVENTS),
setUpdateId(updateId + 1), props.onReady && props.onReady(chartContext.current.chart, 0 === updateId);
}
};
return useEffect((() => {
var _a;
const newSpecFromChildren = hasSpec ? null : parseSpecFromChildren(props);
if (!(null === (_a = chartContext.current) || void 0 === _a ? void 0 : _a.chart)) return hasSpec || (specFromChildren.current = newSpecFromChildren),
(props => {
var _a;
const cs = new (null !== (_a = props.vchartConstructor) && void 0 !== _a ? _a : props.vchartConstrouctor)(parseSpec(props), Object.assign(Object.assign({}, props.options), {
onError: props.onError,
autoFit: !0,
dom: props.container
}));
chartContext.current = Object.assign(Object.assign({}, chartContext.current), {
chart: cs
}), isUnmount.current = !1;
})(props), chartContext.current.chart && (chartContext.current.chart.renderSync({
reuse: !1
}), handleChartRender()), void (eventsBinded.current = props);
if (hasSpec) return void (isEqual(eventsBinded.current.spec, props.spec, {
skipFunction: skipFunctionDiff
}) || (eventsBinded.current = props, chartContext.current.chart.updateSpecSync(parseSpec(props), void 0, {
morph: !1,
enableExitAnimation: !1
}), handleChartRender()));
const newSpec = pickWithout(props, notSpecKeys);
isEqual(newSpec, prevSpec.current, {
skipFunction: skipFunctionDiff
}) && isEqual(newSpecFromChildren, specFromChildren.current) || (prevSpec.current = newSpec,
specFromChildren.current = newSpecFromChildren, chartContext.current.chart.updateSpecSync(parseSpec(props), void 0, {
morph: !1,
enableExitAnimation: !1
}), handleChartRender());
}), [ props ]), useEffect((() => () => {
chartContext && chartContext.current && chartContext.current.chart && (chartContext.current.chart.release(),
chartContext.current.chart = null), eventsBinded.current = null, isUnmount.current = !0;
}), []), React.createElement(RootChartContext.Provider, {
value: chartContext.current
}, toArray(props.children).map(((child, index) => {
if ("string" == typeof child) return;
const childId = getComponentId(child, index);
return React.createElement(React.Fragment, {
key: childId
}, React.cloneElement(child, {
updateId: updateId,
componentId: childId
}));
})), tooltipNode);
}));
export const createChart = (componentName, defaultProps, callback) => {
const Com = withContainer(BaseChart, componentName, (props => callback ? callback(props, defaultProps) : defaultProps ? Object.assign(props, defaultProps) : props));
return Com.displayName = componentName, Com;
};
//# sourceMappingURL=BaseChart.js.map