victory-voronoi-container
Version:
Interactive Voronoi Mouseover Component for Victory
225 lines (222 loc) • 7.83 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.useVictoryVoronoiContainer = exports.VictoryVoronoiContainer = exports.VICTORY_VORONOI_CONTAINER_DEFAULT_PROPS = void 0;
var _react = _interopRequireDefault(require("react"));
var _defaults = _interopRequireDefault(require("lodash/defaults"));
var _pick = _interopRequireDefault(require("lodash/pick"));
var _victoryTooltip = require("victory-tooltip");
var _victoryCore = require("victory-core");
var _voronoiHelpers = require("./voronoi-helpers");
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
const VICTORY_VORONOI_CONTAINER_DEFAULT_PROPS = exports.VICTORY_VORONOI_CONTAINER_DEFAULT_PROPS = {
activateData: true,
activateLabels: true,
labelComponent: /*#__PURE__*/_react.default.createElement(_victoryTooltip.VictoryTooltip, null),
voronoiPadding: 5
};
const getPoint = point => {
const whitelist = ["_x", "_x1", "_x0", "_y", "_y1", "_y0"];
return (0, _pick.default)(point, whitelist);
};
const useVictoryVoronoiContainer = initialProps => {
const props = {
...VICTORY_VORONOI_CONTAINER_DEFAULT_PROPS,
...initialProps
};
const {
children
} = props;
const getDimension = () => {
const {
horizontal,
voronoiDimension
} = props;
if (!horizontal || !voronoiDimension) {
return voronoiDimension;
}
return voronoiDimension === "x" ? "y" : "x";
};
const getLabelPosition = (labelProps, points) => {
const {
mousePosition,
mouseFollowTooltips
} = props;
const voronoiDimension = getDimension();
const point = getPoint(points[0]);
// @ts-expect-error scale is defined but the types do not reflect that
const basePosition = _victoryCore.Helpers.scalePoint(props, point);
let center = mouseFollowTooltips ? mousePosition : undefined;
if (!voronoiDimension || points.length < 2) {
return {
...basePosition,
center: (0, _defaults.default)({}, labelProps.center, center)
};
}
const x = voronoiDimension === "y" ? mousePosition.x : basePosition.x;
const y = voronoiDimension === "x" ? mousePosition.y : basePosition.y;
center = mouseFollowTooltips ? mousePosition : {
x,
y
};
return {
x,
y,
center: (0, _defaults.default)({}, labelProps.center, center)
};
};
const getStyle = (points, type) => {
const {
labels,
labelComponent,
theme
} = props;
const componentProps = labelComponent.props || {};
const themeStyles = theme && theme.voronoi && theme.voronoi.style ? theme.voronoi.style : {};
const componentStyleArray = type === "flyout" ? componentProps.flyoutStyle : componentProps.style;
return points.reduce((memo, datum, index) => {
const labelProps = (0, _defaults.default)({}, componentProps, {
datum,
active: true
});
const text = _victoryCore.Helpers.isFunction(labels) ? labels(labelProps) : undefined;
const textArray = text !== undefined ? `${text}`.split("\n") : [];
const baseStyle = datum.style && datum.style[type] || {};
const componentStyle = Array.isArray(componentStyleArray) ? componentStyleArray[index] : componentStyleArray;
const style = _victoryCore.Helpers.evaluateStyle((0, _defaults.default)({}, componentStyle, baseStyle, themeStyles[type]), labelProps);
const styleArray = textArray.length ? textArray.map(() => style) : [style];
return memo.concat(styleArray);
}, []);
};
const getDefaultLabelProps = points => {
const {
voronoiDimension,
horizontal,
mouseFollowTooltips
} = props;
const point = getPoint(points[0]);
const multiPoint = voronoiDimension && points.length > 1;
const y = point._y1 !== undefined ? point._y1 : point._y;
const defaultHorizontalOrientation = y < 0 ? "left" : "right";
const defaultOrientation = y < 0 ? "bottom" : "top";
const labelOrientation = horizontal ? defaultHorizontalOrientation : defaultOrientation;
const orientation = mouseFollowTooltips ? undefined : labelOrientation;
return {
orientation,
pointerLength: multiPoint ? 0 : undefined,
constrainToVisibleArea: multiPoint || mouseFollowTooltips ? true : undefined
};
};
const getLabelProps = points => {
const {
labels,
scale,
labelComponent,
theme,
width,
height
} = props;
const componentProps = labelComponent.props || {};
const text = points.reduce((memo, datum) => {
const labelProps = (0, _defaults.default)({}, componentProps, {
datum,
active: true
});
const t = _victoryCore.Helpers.isFunction(labels) ? labels(labelProps) : null;
if (t === null || t === undefined) {
return memo;
}
return memo.concat(`${t}`.split("\n"));
}, []);
// remove properties from first point to make datum
// eslint-disable-next-line @typescript-eslint/no-unused-vars
const {
childName,
eventKey,
style,
continuous,
...datum
} = points[0];
const name = props.name === childName ? childName : `${props.name}-${childName}`;
const labelProps = (0, _defaults.default)({
key: `${name}-${eventKey}-voronoi-tooltip`,
id: `${name}-${eventKey}-voronoi-tooltip`,
active: true,
renderInPortal: false,
activePoints: points,
datum,
scale,
theme
}, componentProps, {
text,
width,
height,
style: getStyle(points, "labels"),
flyoutStyle: getStyle(points, "flyout")[0]
}, getDefaultLabelProps(points));
const labelPosition = getLabelPosition(labelProps, points);
return (0, _defaults.default)({}, labelPosition, labelProps);
};
const getTooltip = () => {
const {
labels,
activePoints,
labelComponent
} = props;
if (!labels) {
return null;
}
if (Array.isArray(activePoints) && activePoints.length) {
const labelProps = getLabelProps(activePoints);
const {
text
} = labelProps;
const showLabel = Array.isArray(text) ? text.filter(Boolean).length : text;
return showLabel ? /*#__PURE__*/_react.default.cloneElement(labelComponent, labelProps) : null;
}
return null;
};
return {
props,
children: [..._react.default.Children.toArray(children), getTooltip()]
};
};
exports.useVictoryVoronoiContainer = useVictoryVoronoiContainer;
const VictoryVoronoiContainer = initialProps => {
const {
props,
children
} = useVictoryVoronoiContainer(initialProps);
return /*#__PURE__*/_react.default.createElement(_victoryCore.VictoryContainer, props, children);
};
exports.VictoryVoronoiContainer = VictoryVoronoiContainer;
VictoryVoronoiContainer.role = "container";
VictoryVoronoiContainer.defaultEvents = initialProps => {
const props = {
...VICTORY_VORONOI_CONTAINER_DEFAULT_PROPS,
...initialProps
};
const createEventHandler = (handler, disabled) =>
// eslint-disable-next-line max-params
(event, targetProps, eventKey, context) => disabled || props.disable ? {} : handler(event, {
...props,
...targetProps
}, eventKey, context);
return [{
target: "parent",
eventHandlers: {
onMouseLeave: createEventHandler(_voronoiHelpers.VoronoiHelpers.onMouseLeave),
onTouchCancel: createEventHandler(_voronoiHelpers.VoronoiHelpers.onMouseLeave),
onMouseMove: createEventHandler(_voronoiHelpers.VoronoiHelpers.onMouseMove),
onTouchMove: createEventHandler(_voronoiHelpers.VoronoiHelpers.onMouseMove)
}
}, {
target: "data",
eventHandlers: props.disable ? {} : {
onMouseOver: () => null,
onMouseOut: () => null,
onMouseMove: () => null
}
}];
};