redux-devtools/packages/d3tooltip/src/index.js
2019-01-10 20:51:14 +02:00

79 lines
1.8 KiB
JavaScript

import { is } from 'ramda';
import utils from './utils';
const { prependClass, functor } = utils.default || utils;
const defaultOptions = {
left: undefined, // mouseX
top: undefined, // mouseY
offset: { left: 0, top: 0 },
root: undefined
};
export default function tooltip(d3, className = 'tooltip', options = {}) {
const { left, top, offset, root } = { ...defaultOptions, ...options };
let attrs = { class: className };
let text = () => '';
let styles = {};
let el;
const anchor = root || d3.select('body');
const rootNode = anchor.node();
function tip(selection) {
selection.on({
'mouseover.tip': node => {
let [mouseX, mouseY] = d3.mouse(rootNode);
let [x, y] = [left || mouseX + offset.left, top || mouseY - offset.top];
anchor.selectAll(`div.${className}`).remove();
el = anchor
.append('div')
.attr(prependClass(className)(attrs))
.style({
position: 'absolute',
'z-index': 1001,
left: x + 'px',
top: y + 'px',
...styles
})
.html(() => text(node));
},
'mousemove.tip': node => {
let [mouseX, mouseY] = d3.mouse(rootNode);
let [x, y] = [left || mouseX + offset.left, top || mouseY - offset.top];
el.style({
left: x + 'px',
top: y + 'px'
}).html(() => text(node));
},
'mouseout.tip': () => el.remove()
});
}
tip.attr = function setAttr(d) {
if (is(Object, d)) {
attrs = { ...attrs, ...d };
}
return this;
};
tip.style = function setStyle(d) {
if (is(Object, d)) {
styles = { ...styles, ...d };
}
return this;
};
tip.text = function setText(d) {
text = functor(d);
return this;
};
return tip;
}