@apptane/react-ui-charts
Version:
Chart components in Apptane React UI framework
319 lines (278 loc) • 10.5 kB
JavaScript
import _defineProperty from "@babel/runtime/helpers/defineProperty";
import _objectWithoutProperties from "@babel/runtime/helpers/objectWithoutProperties";
const _excluded = ["context"],
_excluded2 = ["axisYVisible", "gridYVisible", "legendInteractive", "tooltipVisible", "formatYTooltip"];
function ownKeys(object, enumerableOnly) { var keys = Object.keys(object); if (Object.getOwnPropertySymbols) { var symbols = Object.getOwnPropertySymbols(object); enumerableOnly && (symbols = symbols.filter(function (sym) { return Object.getOwnPropertyDescriptor(object, sym).enumerable; })), keys.push.apply(keys, symbols); } return keys; }
function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = null != arguments[i] ? arguments[i] : {}; i % 2 ? ownKeys(Object(source), !0).forEach(function (key) { _defineProperty(target, key, source[key]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)) : ownKeys(Object(source)).forEach(function (key) { Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key)); }); } return target; }
/* eslint-disable @typescript-eslint/no-non-null-assertion */
import { useComponentId, warning } from "@apptane/react-ui-core";
import { useContext, useMemo } from "react";
import { area, curveBumpX, curveCatmullRom, curveLinear, curveMonotoneX, curveNatural, curveStep, line } from "d3-shape";
import { ChartNumericDataContext, ChartOrdinalDataContext, ChartTimeDataContext } from "../parts/ChartDataContext.js";
import { ChartDatumContext } from "../parts/ChartDatumContext.js";
import { findValue } from "./common.js";
import { formatNumericTooltip, useXYPaneData } from "./commonXY.js";
import { useGradientDefs } from "./gradients.js";
import { XYChartPane } from "./XYChartPane.js";
import { XYTooltipLayer } from "./XYTooltipLayer.js";
import { jsx as _jsx } from "@emotion/react/jsx-runtime";
import { jsxs as _jsxs } from "@emotion/react/jsx-runtime";
function curveFn(curve) {
switch (curve) {
case "linear":
return curveLinear;
case "bump":
return curveBumpX;
case "catmullRom":
return curveCatmullRom.alpha(0.5);
case "monotone":
return curveMonotoneX;
case "natural":
return curveNatural;
case "step":
return curveStep;
}
}
const createLineGenerator = curve => line().defined(d => d.c != null).x(d => d.c.x).y(d => d.c.y).curve(curveFn(curve));
const lineGenerator = {
linear: createLineGenerator("linear"),
bump: createLineGenerator("bump"),
catmullRom: createLineGenerator("catmullRom"),
monotone: createLineGenerator("monotone"),
natural: createLineGenerator("natural"),
step: createLineGenerator("step")
};
const createAreaGenerator = curve => area().defined(d => d.c != null).x(d => d.c.x).y1(d => d.c.y).curve(curveFn(curve));
const createBandGenerator = curve => area().defined(d => d.c != null).x(d => d.c.x).y0(d => d.c.y0).y1(d => d.c.y1).curve(curveFn(curve));
function XYLineLayer(_ref) {
let {
componentId,
data,
curve,
offset
} = _ref;
const selectedDatumId = useContext(ChartDatumContext);
const generator = lineGenerator[curve];
const lines = [];
data.forEach(_ref2 => {
let {
id,
index,
color,
pri,
sec
} = _ref2;
const selected = id === selectedDatumId;
const key = id !== null && id !== void 0 ? id : "_".concat(index);
[pri, sec].forEach((_, i) => {
if (_ != null && _.length > 0) {
var _generator;
lines.push(_jsx("path", {
d: (_generator = generator(_)) !== null && _generator !== void 0 ? _generator : undefined,
fill: "none",
stroke: color,
strokeDasharray: i === 1 ? "2" : undefined,
strokeWidth: selected ? 2 : undefined
}, "".concat(key, "-").concat(i)));
}
});
});
return _jsx("g", {
transform: "translate(".concat(offset, ",0)"),
strokeWidth: 1.5,
clipPath: "url(#".concat(componentId, "-main-clip)"),
children: lines
});
}
function XYBandLayer(_ref3) {
let {
componentId,
data,
curve,
offset
} = _ref3;
const selectedDatumId = useContext(ChartDatumContext);
const generator = useMemo(() => createBandGenerator(curve), [curve]);
return _jsx("g", {
transform: "translate(".concat(offset, ",0)"),
clipPath: "url(#".concat(componentId, "-main-clip)"),
children: data.map(_ref4 => {
var _generator2;
let {
id,
index,
loColor,
bands
} = _ref4;
return bands && bands.length > 0 && _jsx("path", {
d: (_generator2 = generator(bands)) !== null && _generator2 !== void 0 ? _generator2 : undefined,
fill: loColor,
opacity: selectedDatumId != null ? id !== selectedDatumId ? 0.5 : undefined : 0.65
}, id !== null && id !== void 0 ? id : "_".concat(index));
})
});
}
function XYAreaLayer(_ref5) {
let {
componentId,
data,
curve,
offset,
stacked,
gradient,
baseline = 0
} = _ref5;
const selectedDatumId = useContext(ChartDatumContext); // no gradient in stacked mode since areas are overlapping
const gradientEnabled = gradient && !stacked;
const generator = useMemo(() => createAreaGenerator(curve).y0(baseline), [curve, baseline]);
const areas = [];
for (let i = stacked ? data.length - 1 : 0; stacked ? i >= 0 : i < data.length; stacked ? --i : ++i) {
const {
id,
index,
hiColor,
loColor,
gradientId,
pri,
sec
} = data[i];
const selected = selectedDatumId != null && id === selectedDatumId;
const key = id !== null && id !== void 0 ? id : "_".concat(index);
[pri, sec].forEach((_, i) => {
if (_ != null && _.length > 0) {
var _generator3;
areas.push(_jsx("path", {
d: (_generator3 = generator(_)) !== null && _generator3 !== void 0 ? _generator3 : undefined,
fill: gradientEnabled ? "url(#".concat(selected ? gradientId + "-active" : gradientId, ")") : selected ? hiColor : loColor
}, "".concat(key, "-").concat(i)));
}
});
}
return _jsx("g", {
transform: "translate(".concat(offset, ",0)"),
strokeWidth: 0,
clipPath: "url(#".concat(componentId, "-main-clip)"),
children: areas
});
}
function findNearestDatum(cx, cy, data, domainX, domainY, x) {
if (domainX == null || x == null) {
return undefined;
}
let datum;
let distance = Infinity;
data.forEach(d => {
const p = findValue(d, p => domainX.isEqual(p.x, x));
if (p != null) {
const _p = p;
if (_p.c != null) {
const m = Math.abs(_p.c.y - cy);
if (isFinite(m) && m < distance) {
datum = d;
distance = m;
}
}
}
});
return datum;
}
function XYLineChartPaneBase(_ref6) {
var _props$formatYTooltip;
let {
context
} = _ref6,
props = _objectWithoutProperties(_ref6, _excluded);
const p = props;
const [computed, domainX, scaleY, layers] = useXYPaneData(context, p);
const offset = props.axisYWidth;
const baseline = scaleY ? scaleY.range()[1] : 0;
return _jsxs(XYChartPane, _objectSpread(_objectSpread(_objectSpread({}, p), {}, {
defs: useGradientDefs(computed, props.gradient == true && props.stacked != true),
computed: computed,
computedDomainX: domainX,
findDatum: props.legendInteractive ? findNearestDatum : undefined
}, context), {}, {
invertY: scaleY === null || scaleY === void 0 ? void 0 : scaleY.invert,
tooltipOffset: props.theme.charts.xy.style.tooltip.offset,
formatTooltipValue: (_props$formatYTooltip = props.formatYTooltip) !== null && _props$formatYTooltip !== void 0 ? _props$formatYTooltip : p.formatYDomain,
children: [layers, computed && props.area && _jsx(XYAreaLayer, {
componentId: props.componentId,
offset: offset,
curve: props.curve,
data: computed,
stacked: !!props.stacked,
gradient: !!props.gradient,
baseline: baseline
}), computed && !props.area && _jsx(XYBandLayer, {
componentId: props.componentId,
offset: offset,
curve: props.curve,
data: computed
}), computed && _jsx(XYLineLayer, {
componentId: props.componentId,
offset: offset,
curve: props.curve,
data: computed
}), computed && domainX && props.tooltipVisible && _jsx(XYTooltipLayer, {
theme: props.theme,
colorMode: props.colorMode,
offset: offset,
data: computed,
domainX: domainX,
baseline: baseline
})]
}));
}
function XYTimeLineChartPane(props) {
const context = useContext(ChartTimeDataContext);
return _jsx(XYLineChartPaneBase, _objectSpread(_objectSpread({}, props), {}, {
context: context
}));
}
function XYNumericLineChartPane(props) {
const context = useContext(ChartNumericDataContext);
return _jsx(XYLineChartPaneBase, _objectSpread(_objectSpread({}, props), {}, {
context: context
}));
}
function XYOrdinalLineChartPane(props) {
const context = useContext(ChartOrdinalDataContext);
return _jsx(XYLineChartPaneBase, _objectSpread(_objectSpread({}, props), {}, {
context: context
}));
}
export function XYLineChartPane(props) {
const componentId = useComponentId("--apptane-chart");
const _ref7 = props,
{
axisYVisible = true,
gridYVisible = true,
legendInteractive = true,
tooltipVisible = true,
formatYTooltip = formatNumericTooltip
} = _ref7,
p = _objectWithoutProperties(_ref7, _excluded2); // see XYChartPanes
const curve = p.curve === true ? "monotone" : typeof p.curve === "string" ? p.curve : "linear";
const propsEx = {
componentId,
axisYVisible,
gridYVisible,
legendInteractive,
tooltipVisible,
formatYTooltip: formatYTooltip,
curve: curve,
axisYWidth: axisYVisible ? p.axisYWidth : 0
};
switch (p.domainXType) {
case "time":
return _jsx(XYTimeLineChartPane, _objectSpread(_objectSpread({}, p), propsEx));
case "numeric":
return _jsx(XYNumericLineChartPane, _objectSpread(_objectSpread({}, p), propsEx));
case "ordinal":
return _jsx(XYOrdinalLineChartPane, _objectSpread(_objectSpread({}, p), propsEx));
default:
warning(false, "Chart pane does not have 'domainXType' specified");
return null;
}
}
//# sourceMappingURL=XYLineChartPane.js.map