Simplify d3tooltip API

This commit is contained in:
Nathan Bierema 2023-01-02 11:09:04 -05:00
parent 71be671e6b
commit ccec529b11
6 changed files with 39 additions and 99 deletions

View File

@ -354,9 +354,11 @@ export default function (DOMNode: HTMLElement, options: Partial<Options> = {}) {
unknown,
null,
undefined
>('tooltip', { ...tooltipOptions, root })
.text((d, i) => getTooltipString(d.data, i, tooltipOptions))
.styles(tooltipOptions.styles)
>('tooltip', {
...tooltipOptions,
root,
text: (d) => getTooltipString(d.data, tooltipOptions),
})
);
}

View File

@ -73,11 +73,7 @@ export function getNodeGroupByDepthCount(rootNode: InternalNode) {
return nodeGroupByDepthCount;
}
export function getTooltipString(
node: InternalNode,
i: number | undefined,
{ indentationSize = 4 }
) {
export function getTooltipString(node: InternalNode, { indentationSize = 4 }) {
if (!is(Object, node)) return '';
const spacer = join('&nbsp;&nbsp;');

View File

@ -36,8 +36,7 @@
"prepublish": "pnpm run type-check && pnpm run lint"
},
"dependencies": {
"@babel/runtime": "^7.20.6",
"ramda": "^0.28.0"
"@babel/runtime": "^7.20.6"
},
"devDependencies": {
"@babel/cli": "^7.19.3",
@ -46,7 +45,6 @@
"@babel/preset-env": "^7.20.2",
"@babel/preset-typescript": "^7.18.6",
"@types/d3": "^4.13.12",
"@types/ramda": "^0.28.20",
"@typescript-eslint/eslint-plugin": "^5.47.0",
"@typescript-eslint/parser": "^5.47.0",
"d3": "^4.13.0",

View File

@ -1,13 +1,14 @@
import * as d3 from 'd3';
import type { BaseType, ContainerElement, Selection } from 'd3';
import { is } from 'ramda';
import functor from './utils/functor';
export type StyleValue = string | number | boolean;
interface Options<
GElement extends ContainerElement,
Datum,
PElement extends BaseType,
PDatum
RootGElement extends ContainerElement,
RootDatum,
RootPElement extends BaseType,
RootPDatum
> {
left: number | undefined;
top: number | undefined;
@ -15,37 +16,26 @@ interface Options<
left: number;
top: number;
};
root: Selection<GElement, Datum, PElement, PDatum> | undefined;
root:
| Selection<RootGElement, RootDatum, RootPElement, RootPDatum>
| undefined;
styles?: { [key: string]: StyleValue };
text?: string | ((datum: Datum) => string);
}
const defaultOptions: Options<ContainerElement, unknown, BaseType, unknown> = {
const defaultOptions: Options<
unknown,
ContainerElement,
unknown,
BaseType,
unknown
> = {
left: undefined, // mouseX
top: undefined, // mouseY
offset: { left: 0, top: 0 },
root: undefined,
};
export type StyleValue = string | number | boolean;
interface Tip<
GElement extends BaseType,
Datum,
PElement extends BaseType,
PDatum
> {
(selection: Selection<GElement, Datum, PElement, PDatum>): void;
styles: (
this: this,
value: { [key: string]: StyleValue } | undefined
) => this;
text: (
this: this,
value:
| string
| ((datum: Datum, index?: number, outerIndex?: number) => string)
) => this;
}
export function tooltip<
GElement extends BaseType,
Datum,
@ -58,20 +48,20 @@ export function tooltip<
>(
className = 'tooltip',
options: Partial<
Options<RootGElement, RootDatum, RootPElement, RootPDatum>
Options<Datum, RootGElement, RootDatum, RootPElement, RootPDatum>
> = {}
): Tip<GElement, Datum, PElement, PDatum> {
const { left, top, offset, root } = {
) {
const {
left,
top,
offset,
root,
styles = {},
text = '',
} = {
...defaultOptions,
...options,
} as Options<RootGElement, RootDatum, RootPElement, RootPDatum>;
let text: (
datum: Datum,
index?: number,
outerIndex?: number
) => string = () => '';
let styles: { [key: string]: StyleValue } = {};
} as Options<Datum, RootGElement, RootDatum, RootPElement, RootPDatum>;
let el: Selection<HTMLDivElement, RootDatum, BaseType, unknown>;
const anchor: Selection<
@ -82,7 +72,7 @@ export function tooltip<
> = root || d3.select<RootGElement, RootDatum>('body');
const rootNode = anchor.node()!;
function tip(selection: Selection<GElement, Datum, PElement, PDatum>) {
return function tip(selection: Selection<GElement, Datum, PElement, PDatum>) {
selection.on('mouseover.tip', (node) => {
const [mouseX, mouseY] = d3.mouse(rootNode);
const [x, y] = [left || mouseX + offset.left, top || mouseY - offset.top];
@ -96,7 +86,7 @@ export function tooltip<
.style('z-index', 1001)
.style('left', `${x}px`)
.style('top', `${y}px`)
.html(() => text(node));
.html(typeof text === 'function' ? () => text(node) : () => text);
for (const [key, value] of Object.entries(styles)) {
el.style(key, value);
@ -109,31 +99,9 @@ export function tooltip<
el.style('left', `${x}px`)
.style('top', `${y}px`)
.html(() => text(node));
.html(typeof text === 'function' ? () => text(node) : () => text);
});
selection.on('mouseout.tip', () => el.remove());
}
tip.styles = function setStyles(
this: typeof tip,
value: { [key: string]: StyleValue } | undefined
) {
if (is(Object, value)) {
styles = { ...styles, ...value };
}
return this;
};
tip.text = function setText(
this: typeof tip,
value:
| string
| ((datum: Datum, index?: number, outerIndex?: number) => string)
) {
text = functor(value);
return this;
};
return tip;
}

View File

@ -1,20 +0,0 @@
import { is } from 'ramda';
import { Primitive } from 'd3';
export default function functor<Datum>(
v: string | ((datum: Datum, index?: number, outerIndex?: number) => string)
): (datum: Datum, index?: number, outerIndex?: number) => string;
export default function functor<Datum>(
v:
| Primitive
| ((datum: Datum, index: number, outerIndex?: number) => Primitive)
): (datum: Datum, index?: number, outerIndex?: number) => Primitive;
export default function functor<Datum>(
v:
| Primitive
| ((datum: Datum, index: number, outerIndex?: number) => Primitive)
): (datum: Datum, index: number, outerIndex?: number) => Primitive {
return is(Function, v)
? (v as (datum: Datum, index: number, outerIndex?: number) => Primitive)
: () => v;
}

View File

@ -265,18 +265,15 @@ importers:
'@babel/preset-typescript': ^7.18.6
'@babel/runtime': ^7.20.6
'@types/d3': ^4.13.12
'@types/ramda': ^0.28.20
'@typescript-eslint/eslint-plugin': ^5.47.0
'@typescript-eslint/parser': ^5.47.0
d3: ^4.13.0
eslint: ^8.30.0
eslint-config-prettier: ^8.5.0
ramda: ^0.28.0
rimraf: ^3.0.2
typescript: ~4.9.4
dependencies:
'@babel/runtime': 7.20.6
ramda: 0.28.0
devDependencies:
'@babel/cli': 7.19.3_@babel+core@7.20.5
'@babel/core': 7.20.5
@ -284,7 +281,6 @@ importers:
'@babel/preset-env': 7.20.2_@babel+core@7.20.5
'@babel/preset-typescript': 7.18.6_@babel+core@7.20.5
'@types/d3': 4.13.12
'@types/ramda': 0.28.20
'@typescript-eslint/eslint-plugin': 5.47.0_ncmi6noazr3nzas7jxykisekym
'@typescript-eslint/parser': 5.47.0_lzzuuodtsqwxnvqeq4g4likcqa
d3: 4.13.0