nanoplot 0.0.69 → 0.0.71
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/src/components/Area/Area.d.ts +3 -2
- package/dist/src/components/Area/Area.js +2 -2
- package/dist/src/components/Bars/components/HorizontalBars.js +5 -7
- package/dist/src/components/Bars/components/VerticalBars.js +5 -5
- package/dist/src/components/GradientLegend/GradientLegend.js +2 -2
- package/dist/src/components/Heatmap/Heatmap.js +6 -6
- package/dist/src/components/Legend/Legend.d.ts +2 -1
- package/dist/src/components/Legend/Legend.js +30 -24
- package/dist/src/components/Lines/Lines.d.ts +30 -5
- package/dist/src/components/Lines/Lines.js +47 -56
- package/dist/src/components/Lines/components/Line.d.ts +1 -1
- package/dist/src/components/Lines/components/Line.js +14 -2
- package/dist/src/components/Lines/components/LinesJoints.d.ts +12 -0
- package/dist/src/components/Lines/components/LinesJoints.js +40 -0
- package/dist/src/components/Lines/components/LinesMouse.d.ts +18 -0
- package/dist/src/components/Lines/components/LinesMouse.js +24 -0
- package/dist/src/components/Lines/components/LinesTooltip.d.ts +3 -1
- package/dist/src/components/Lines/components/LinesTooltip.js +60 -128
- package/dist/src/components/Lines/components/LinesTooltipZone.d.ts +10 -0
- package/dist/src/components/Lines/components/LinesTooltipZone.js +14 -0
- package/dist/src/components/Overlay/Overlay.js +5 -5
- package/dist/src/components/Overlay/OverlayRect.js +5 -5
- package/dist/src/components/Pie/Pie.js +4 -4
- package/dist/src/components/Radar/Radar.js +4 -4
- package/dist/src/components/Scatter/components/ScatterLabels.js +5 -5
- package/dist/src/components/Scatter/components/ScatterTooltip.js +5 -5
- package/dist/src/components/Worldmap/Worldmap.js +2 -2
- package/dist/src/components/XAxis/XAxis.d.ts +5 -42
- package/dist/src/components/XAxis/XAxis.js +25 -9
- package/dist/src/components/YAxis/YAxis.js +4 -4
- package/dist/src/hooks/use-graph/use-graph.d.ts +41 -1
- package/dist/src/hooks/use-graph/use-graph.js +7 -1
- package/dist/src/hooks/use-mouse-coordinates.d.ts +7 -1
- package/dist/src/hooks/use-mouse-coordinates.js +68 -12
- package/dist/src/utils/coordinates/coordinates.d.ts +17 -1
- package/dist/src/utils/coordinates/coordinates.js +234 -0
- package/dist/src/utils/cx/cx.d.ts +3 -4
- package/dist/src/utils/cx/cx.js +31 -29
- package/dist/src/utils/domain/utils/date-domain.d.ts +1 -0
- package/dist/src/utils/domain/utils/date-domain.js +88 -41
- package/dist/src/utils/domain/utils/range.js +44 -24
- package/dist/src/utils/equals/equals.d.ts +1 -0
- package/dist/src/utils/equals/equals.js +18 -0
- package/dist/src/utils/gradient/gradient.js +8 -11
- package/dist/src/utils/math/math.d.ts +1 -3
- package/dist/src/utils/math/math.js +7 -8
- package/dist/tsconfig.typings.tsbuildinfo +1 -1
- package/package.json +1 -1
|
@@ -9,7 +9,7 @@ interface Props extends React.SVGAttributes<SVGSVGElement> {
|
|
|
9
9
|
export declare const Area: {
|
|
10
10
|
({ className, curve, children, loading }: Props): React.JSX.Element | null;
|
|
11
11
|
context(ctx: GraphContext): GraphContext;
|
|
12
|
-
Tooltip: React.ComponentType<React.HTMLAttributes<HTMLDivElement> & {
|
|
12
|
+
Tooltip: React.ComponentType<Omit<React.HTMLAttributes<HTMLDivElement> & {
|
|
13
13
|
tooltip?: ((points: Array<Omit<import("../../export").CartesianDataset[number], "data"> & {
|
|
14
14
|
data: import("../../export").CartesianDataset[number]["data"][number];
|
|
15
15
|
}>, x: number | string | Date) => React.ReactNode) | {
|
|
@@ -17,6 +17,7 @@ export declare const Area: {
|
|
|
17
17
|
display: (point: import("../../export").CartesianDataset[number]["data"][number]) => React.ReactNode;
|
|
18
18
|
};
|
|
19
19
|
joints?: boolean;
|
|
20
|
-
|
|
20
|
+
zoneRef: React.RefObject<SVGSVGElement | null>;
|
|
21
|
+
}, "zoneRef">>;
|
|
21
22
|
};
|
|
22
23
|
export {};
|
|
@@ -4,10 +4,10 @@ import { useGraph } from "../../hooks/use-graph/use-graph";
|
|
|
4
4
|
import { CurveUtils } from "../../utils/path/curve";
|
|
5
5
|
import { CoordinatesUtils } from "../../utils/coordinates/coordinates";
|
|
6
6
|
import { cx } from "../../utils/cx/cx";
|
|
7
|
-
import { LinesTooltip } from "../Lines/components/LinesTooltip";
|
|
8
7
|
import { ObjectUtils } from "../../utils/object/object";
|
|
9
8
|
import { Line } from "../Lines/components/Line";
|
|
10
9
|
import { ColorUtils } from "../../utils/color/color";
|
|
10
|
+
import { LinesTooltipZone } from "../Lines/components/LinesTooltipZone";
|
|
11
11
|
export const Area = ({ className, curve = "linear", children, loading }) => {
|
|
12
12
|
const { interactions: { pinned, hovered }, data, viewbox, domain, colors, } = useGraph();
|
|
13
13
|
if (!GraphUtils.isXYData(data))
|
|
@@ -55,4 +55,4 @@ export const Area = ({ className, curve = "linear", children, loading }) => {
|
|
|
55
55
|
Area.context = (ctx) => {
|
|
56
56
|
return Object.assign(Object.assign({}, ctx), { colors: ColorUtils.scheme.sunset });
|
|
57
57
|
};
|
|
58
|
-
Area.Tooltip =
|
|
58
|
+
Area.Tooltip = LinesTooltipZone;
|
|
@@ -16,7 +16,7 @@ import { useGraph } from "../../../hooks/use-graph/use-graph";
|
|
|
16
16
|
import { cx } from "../../../utils/cx/cx";
|
|
17
17
|
import { ObjectUtils } from "../../../utils/object/object";
|
|
18
18
|
import { Rect } from "./Rect";
|
|
19
|
-
import {
|
|
19
|
+
import { scale } from "../../../utils/math/math";
|
|
20
20
|
import { overlay } from "../../Overlay/Overlay";
|
|
21
21
|
import { ColorUtils } from "../../../utils/color/color";
|
|
22
22
|
export const HorizontalBars = ({ children, labels, size = 50, radius = 0, anchor = 0, className }) => {
|
|
@@ -54,9 +54,9 @@ export const HorizontalBars = ({ children, labels, size = 50, radius = 0, anchor
|
|
|
54
54
|
dataset.map((bar, i) => {
|
|
55
55
|
const position = typeof labels === "object" && "position" in labels ? labels.position : "center";
|
|
56
56
|
const collision = typeof labels === "object" && "collision" in labels ? labels.collision : true;
|
|
57
|
-
const width = Math.abs(
|
|
58
|
-
const height =
|
|
59
|
-
const top =
|
|
57
|
+
const width = Math.abs(scale(bar.x2 - bar.x1, context.viewbox.x, 100) - (position === "above" ? 100 : 0)) + "%";
|
|
58
|
+
const height = scale(bar.y2 - bar.y1, context.viewbox.y, 100);
|
|
59
|
+
const top = scale(bar.y1, context.viewbox.y, 100);
|
|
60
60
|
const label = (() => {
|
|
61
61
|
var _a;
|
|
62
62
|
if (typeof labels === "object" && "position" in labels)
|
|
@@ -67,9 +67,7 @@ export const HorizontalBars = ({ children, labels, size = 50, radius = 0, anchor
|
|
|
67
67
|
return (React.createElement(overlay.div, { key: i, className: "bars__label @container-[size] absolute text-center", style: {
|
|
68
68
|
width,
|
|
69
69
|
height: height + "%",
|
|
70
|
-
left: position === "above"
|
|
71
|
-
? "unset"
|
|
72
|
-
: MathUtils.scale(Math.min(bar.x1, bar.x2), context.viewbox.x, 100) + "%",
|
|
70
|
+
left: position === "above" ? "unset" : scale(Math.min(bar.x1, bar.x2), context.viewbox.x, 100) + "%",
|
|
73
71
|
right: position === "above" ? 0 : "unset",
|
|
74
72
|
top: top + "%",
|
|
75
73
|
} },
|
|
@@ -17,7 +17,7 @@ import { CoordinatesUtils } from "../../../utils/coordinates/coordinates";
|
|
|
17
17
|
import { ObjectUtils } from "../../../utils/object/object";
|
|
18
18
|
import { Rect } from "./Rect";
|
|
19
19
|
import { cx } from "../../../utils/cx/cx";
|
|
20
|
-
import {
|
|
20
|
+
import { scale } from "../../../utils/math/math";
|
|
21
21
|
import { overlay } from "../../Overlay/Overlay";
|
|
22
22
|
import { ColorUtils } from "../../../utils/color/color";
|
|
23
23
|
export const VerticalBars = (_a) => {
|
|
@@ -66,9 +66,9 @@ export const VerticalBars = (_a) => {
|
|
|
66
66
|
dataset.map((bar, i) => {
|
|
67
67
|
const position = typeof labels === "object" && "position" in labels ? labels.position : "center";
|
|
68
68
|
const collision = typeof labels === "object" && "collision" in labels ? labels.collision : true;
|
|
69
|
-
const width =
|
|
70
|
-
const height =
|
|
71
|
-
const top = position === "above" ? -4 :
|
|
69
|
+
const width = scale(bar.x2 - bar.x1, context.viewbox.x, 100) + "%";
|
|
70
|
+
const height = scale(Math.abs(bar.y1 - bar.y2), context.viewbox.y, 100);
|
|
71
|
+
const top = position === "above" ? -4 : scale(Math.min(bar.y2, bar.y1), context.viewbox.y, 100) + "%";
|
|
72
72
|
const label = (() => {
|
|
73
73
|
var _a;
|
|
74
74
|
if (typeof labels === "object" && "position" in labels)
|
|
@@ -79,7 +79,7 @@ export const VerticalBars = (_a) => {
|
|
|
79
79
|
return (React.createElement(overlay.div, { key: i, className: "bars__label @container-[size] absolute text-center", style: {
|
|
80
80
|
width,
|
|
81
81
|
height: Math.abs(height - (position === "above" ? 100 : 0)) + "%",
|
|
82
|
-
left: `${
|
|
82
|
+
left: `${scale(bar.x1, context.viewbox.x, 100)}%`,
|
|
83
83
|
top: top,
|
|
84
84
|
} },
|
|
85
85
|
React.createElement("div", { className: "h-full w-full relative" },
|
|
@@ -11,14 +11,14 @@ var __rest = (this && this.__rest) || function (s, e) {
|
|
|
11
11
|
};
|
|
12
12
|
import React from "react";
|
|
13
13
|
import { useGraphColumn } from "../../hooks/use-graph/use-graph";
|
|
14
|
-
import {
|
|
14
|
+
import { scale } from "../../utils/math/math";
|
|
15
15
|
import { cx } from "../../utils/cx/cx";
|
|
16
16
|
export const GradientLegend = (_a) => {
|
|
17
17
|
var { position, alignment = "center", gradient, scalars, labels = true } = _a, rest = __rest(_a, ["position", "alignment", "gradient", "scalars", "labels"]);
|
|
18
18
|
const column = useGraphColumn().column;
|
|
19
19
|
const ticks = scalars.map((tick, i, ticks) => {
|
|
20
20
|
if (typeof tick === "number")
|
|
21
|
-
return { label: tick, left:
|
|
21
|
+
return { label: tick, left: scale(i, ticks.length - 1, 100) + "%" };
|
|
22
22
|
return { label: tick.tick, left: tick.percent + "%" };
|
|
23
23
|
});
|
|
24
24
|
return (React.createElement("div", Object.assign({}, rest, { className: cx("gradient-legend w-[100%] px-[20px]", alignment === "center" && "mx-auto", alignment === "start" && "mr-auto", alignment === "end" && "ml-auto", rest.className), style: Object.assign({ gridColumn: column }, rest.style) }),
|
|
@@ -14,7 +14,7 @@ import { cx } from "../../utils/cx/cx";
|
|
|
14
14
|
import { Rect } from "../Bars/components/Rect";
|
|
15
15
|
import { GraphUtils } from "../../utils/graph/graph";
|
|
16
16
|
import { CoordinatesUtils } from "../../utils/coordinates/coordinates";
|
|
17
|
-
import {
|
|
17
|
+
import { scale } from "../../utils/math/math";
|
|
18
18
|
import { GradientUtils } from "../../utils/gradient/gradient";
|
|
19
19
|
import { overlay } from "../Overlay/Overlay";
|
|
20
20
|
import { ColorUtils } from "../../utils/color/color";
|
|
@@ -34,7 +34,7 @@ export const Heatmap = (_a) => {
|
|
|
34
34
|
const height = viewbox.y / yCategories.size;
|
|
35
35
|
const ticks = scalars.map((tick, i) => {
|
|
36
36
|
if (typeof tick === "number")
|
|
37
|
-
return { tick: tick, percent:
|
|
37
|
+
return { tick: tick, percent: scale(i, scalars.length - 1, 100) };
|
|
38
38
|
return tick;
|
|
39
39
|
});
|
|
40
40
|
const dataset = data.flatMap(({ data }) => {
|
|
@@ -57,9 +57,9 @@ export const Heatmap = (_a) => {
|
|
|
57
57
|
labels &&
|
|
58
58
|
dataset.map((rect, i) => {
|
|
59
59
|
const collision = typeof labels === "object" && "collision" in labels ? labels.collision : true;
|
|
60
|
-
const width =
|
|
61
|
-
const height =
|
|
62
|
-
const top =
|
|
60
|
+
const width = scale(rect.x2 - rect.x1, context.viewbox.x, 100) + "%";
|
|
61
|
+
const height = scale(rect.y2 - rect.y1, context.viewbox.y, 100);
|
|
62
|
+
const top = scale(rect.y1, context.viewbox.y, 100);
|
|
63
63
|
const label = (() => {
|
|
64
64
|
var _a;
|
|
65
65
|
if (typeof labels === "object")
|
|
@@ -70,7 +70,7 @@ export const Heatmap = (_a) => {
|
|
|
70
70
|
return (React.createElement(overlay.div, { key: i, className: "heatmap__labels @container-[size] absolute text-center", style: {
|
|
71
71
|
width,
|
|
72
72
|
height: height + "%",
|
|
73
|
-
left: `${
|
|
73
|
+
left: `${scale(rect.x1, context.viewbox.x, 100)}%`,
|
|
74
74
|
top: top + "%",
|
|
75
75
|
} },
|
|
76
76
|
React.createElement("div", { className: "h-full w-full relative" },
|
|
@@ -8,9 +8,10 @@ type Props = Omit<JSX.IntrinsicElements["div"], "onClick" | "onMouseEnter" | "on
|
|
|
8
8
|
onMouseLeave?: (datapoint: CartesianDatasetDefaulted[number] | SegmentDatasetDefaulted[number]) => void;
|
|
9
9
|
onMouseMove?: (datapoint: CartesianDatasetDefaulted[number] | SegmentDatasetDefaulted[number]) => void;
|
|
10
10
|
children?: ReactNode;
|
|
11
|
+
datasets?: string[];
|
|
11
12
|
};
|
|
12
13
|
export declare const Legend: {
|
|
13
|
-
({ position, alignment, onClick, onMouseEnter, onMouseMove, onMouseLeave, ...rest }: Props): JSX.Element;
|
|
14
|
+
({ position, alignment, onClick, onMouseEnter, onMouseMove, onMouseLeave, datasets, ...rest }: Props): JSX.Element;
|
|
14
15
|
context(ctx: GraphContext, { position }: Props): {
|
|
15
16
|
layout: {
|
|
16
17
|
rows: string;
|
|
@@ -11,35 +11,41 @@ var __rest = (this && this.__rest) || function (s, e) {
|
|
|
11
11
|
};
|
|
12
12
|
import React from "react";
|
|
13
13
|
import { Graph } from "../Graph/Graph";
|
|
14
|
-
import { useGraph } from "../../hooks/use-graph/use-graph";
|
|
14
|
+
import { useDatasets, useGraph, } from "../../hooks/use-graph/use-graph";
|
|
15
15
|
import { cx } from "../../utils/cx/cx";
|
|
16
16
|
import { GradientUtils } from "../../utils/gradient/gradient";
|
|
17
17
|
export const Legend = (_a) => {
|
|
18
|
-
var { position = "top", alignment = "center", onClick, onMouseEnter, onMouseMove, onMouseLeave } = _a, rest = __rest(_a, ["position", "alignment", "onClick", "onMouseEnter", "onMouseMove", "onMouseLeave"]);
|
|
18
|
+
var { position = "top", alignment = "center", onClick, onMouseEnter, onMouseMove, onMouseLeave, datasets } = _a, rest = __rest(_a, ["position", "alignment", "onClick", "onMouseEnter", "onMouseMove", "onMouseLeave", "datasets"]);
|
|
19
19
|
const context = useGraph();
|
|
20
|
+
const dsets = useDatasets(datasets);
|
|
20
21
|
const Element = position === "top" || position === "bottom" ? Graph.Row : Graph.Column;
|
|
21
|
-
const {
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
?
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
React.createElement("div", { className: cx("
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
22
|
+
const { interactions: { pinned, hovered }, } = context;
|
|
23
|
+
const render = (ctx) => {
|
|
24
|
+
return ctx.data
|
|
25
|
+
.map((dp) => { var _a; return (Object.assign(Object.assign({}, dp), { group: (_a = dp.group) !== null && _a !== void 0 ? _a : "" })); })
|
|
26
|
+
.sort((a, b) => a.group.localeCompare(b.group))
|
|
27
|
+
.map((datapoint, i, datapoints) => {
|
|
28
|
+
var _a, _b;
|
|
29
|
+
const { id, name, fill, stroke } = datapoint;
|
|
30
|
+
const disabled = pinned.length && !pinned.includes(String(id)) && !hovered.includes(String(id));
|
|
31
|
+
const isLastInGroup = ((_a = datapoints[i + 1]) === null || _a === void 0 ? void 0 : _a.group) ? datapoints[i + 1].group !== datapoint.group : false;
|
|
32
|
+
const bg = fill !== null && fill !== void 0 ? fill : stroke;
|
|
33
|
+
const deserialized = ((_b = bg === null || bg === void 0 ? void 0 : bg.replace("mask:", "")) === null || _b === void 0 ? void 0 : _b.includes("linear-gradient"))
|
|
34
|
+
? GradientUtils.deserialize({
|
|
35
|
+
gradient: bg.replace("mask:", ""),
|
|
36
|
+
viewbox: ctx.viewbox,
|
|
37
|
+
domain: ctx.domain,
|
|
38
|
+
})
|
|
39
|
+
: bg;
|
|
40
|
+
return (React.createElement("div", { key: i, className: cx("flex items-center", (onClick || onMouseEnter || onMouseLeave || onMouseMove) && "cursor-pointer user-select-none"), onClick: () => onClick === null || onClick === void 0 ? void 0 : onClick(datapoint), onMouseEnter: () => onMouseEnter === null || onMouseEnter === void 0 ? void 0 : onMouseEnter(datapoint), onMouseLeave: () => onMouseLeave === null || onMouseLeave === void 0 ? void 0 : onMouseLeave(datapoint), onMouseMove: () => onMouseMove === null || onMouseMove === void 0 ? void 0 : onMouseMove(datapoint) },
|
|
41
|
+
React.createElement("div", { className: cx("size-4 mr-1 rounded-full", disabled && "bg-gray-400 opacity-[0.8]"), style: disabled ? undefined : { background: deserialized } }),
|
|
42
|
+
React.createElement("div", { className: cx("text-nowrap", disabled && "text-gray-400") }, name),
|
|
43
|
+
isLastInGroup && React.createElement("div", { className: "h-[16px] bg-gray-700 w-[1px] ml-[10px]" })));
|
|
44
|
+
});
|
|
45
|
+
};
|
|
46
|
+
return (React.createElement(Element, Object.assign({}, rest, { className: cx("flex gap-3", (position === "left" || position === "right") && "flex-col", position === "right" && "pl-4", position === "left" && "pr-4", position === "top" && "pb-3 pt-2", position === "bottom" && "pt-3 pb-2", alignment === "start" && "justify-start", alignment === "end" && "justify-end", alignment === "center" && "justify-center", rest.className) }),
|
|
47
|
+
render(context),
|
|
48
|
+
dsets.map((d) => render(d))));
|
|
43
49
|
};
|
|
44
50
|
Legend.context = (ctx, { position = "top" }) => {
|
|
45
51
|
const rows = (() => {
|
|
@@ -1,17 +1,19 @@
|
|
|
1
1
|
import React, { ReactNode } from "react";
|
|
2
|
+
import { GraphContext } from "../../hooks/use-graph/use-graph";
|
|
2
3
|
import { CurveUtils } from "../../utils/path/curve";
|
|
3
4
|
interface Props extends React.SVGAttributes<SVGSVGElement> {
|
|
4
5
|
children?: ReactNode;
|
|
5
6
|
curve?: keyof typeof CurveUtils;
|
|
6
7
|
joints?: boolean | {
|
|
7
|
-
border:
|
|
8
|
+
border: string;
|
|
8
9
|
};
|
|
9
10
|
loading?: boolean;
|
|
10
|
-
|
|
11
|
+
datasets?: string[];
|
|
12
|
+
context?: GraphContext;
|
|
11
13
|
}
|
|
12
14
|
export declare const Lines: {
|
|
13
|
-
(
|
|
14
|
-
Tooltip: React.ComponentType<React.HTMLAttributes<HTMLDivElement> & {
|
|
15
|
+
(props: Props): React.JSX.Element | null;
|
|
16
|
+
Tooltip: React.ComponentType<Omit<React.HTMLAttributes<HTMLDivElement> & {
|
|
15
17
|
tooltip?: ((points: Array<Omit<import("../../export").CartesianDataset[number], "data"> & {
|
|
16
18
|
data: import("../../export").CartesianDataset[number]["data"][number];
|
|
17
19
|
}>, x: number | string | Date) => React.ReactNode) | {
|
|
@@ -19,6 +21,29 @@ export declare const Lines: {
|
|
|
19
21
|
display: (point: import("../../export").CartesianDataset[number]["data"][number]) => React.ReactNode;
|
|
20
22
|
};
|
|
21
23
|
joints?: boolean;
|
|
22
|
-
|
|
24
|
+
zoneRef: React.RefObject<SVGSVGElement | null>;
|
|
25
|
+
}, "zoneRef">>;
|
|
26
|
+
Mouse: ({ joints, datasets, onMove, onLeave, onEnter, className }: {
|
|
27
|
+
cross?: {
|
|
28
|
+
x: true;
|
|
29
|
+
y: true;
|
|
30
|
+
};
|
|
31
|
+
joints?: boolean | {
|
|
32
|
+
border: string;
|
|
33
|
+
};
|
|
34
|
+
className?: string;
|
|
35
|
+
datasets?: string[];
|
|
36
|
+
onMove?: (e: React.MouseEvent<SVGSVGElement>, mouse: ReturnType<typeof import("../../hooks/use-mouse-coordinates").useMouseCoordinates>) => void;
|
|
37
|
+
onEnter?: (e: React.MouseEvent<SVGSVGElement>) => void;
|
|
38
|
+
onLeave?: (e: React.MouseEvent<SVGSVGElement>) => void;
|
|
39
|
+
}) => React.JSX.Element;
|
|
40
|
+
Joints: ({ context, border, at, strokeWidth }: {
|
|
41
|
+
at?: {
|
|
42
|
+
x: string | number | Date;
|
|
43
|
+
};
|
|
44
|
+
border?: string;
|
|
45
|
+
strokeWidth?: number;
|
|
46
|
+
context: GraphContext;
|
|
47
|
+
}) => (React.JSX.Element | null)[] | null;
|
|
23
48
|
};
|
|
24
49
|
export {};
|
|
@@ -1,76 +1,67 @@
|
|
|
1
1
|
import React from "react";
|
|
2
2
|
import { GraphUtils } from "../../utils/graph/graph";
|
|
3
|
-
import {
|
|
3
|
+
import { useDatasets, useGraph, useIsZooming } from "../../hooks/use-graph/use-graph";
|
|
4
4
|
import { CurveUtils } from "../../utils/path/curve";
|
|
5
5
|
import { CoordinatesUtils } from "../../utils/coordinates/coordinates";
|
|
6
6
|
import { LinesLoading } from "./components/LinesLoading";
|
|
7
7
|
import { cx, tw } from "../../utils/cx/cx";
|
|
8
|
-
import { LinesTooltip } from "./components/LinesTooltip";
|
|
9
8
|
import { Line } from "./components/Line";
|
|
10
9
|
import { toRgb } from "../../utils/color/to-rgb";
|
|
11
|
-
import {
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
10
|
+
import { LinesTooltipZone } from "./components/LinesTooltipZone";
|
|
11
|
+
import { LinesMouse } from "./components/LinesMouse";
|
|
12
|
+
import { LinesJoints } from "./components/LinesJoints";
|
|
13
|
+
const chunk = (a, s) => {
|
|
14
|
+
const len = Math.ceil(a.length / s);
|
|
15
|
+
const r = new Array(len);
|
|
16
|
+
for (let i = 0, j = 0; i < a.length; i += s, j++) {
|
|
17
|
+
r[j] = a.slice(i, i + s);
|
|
16
18
|
}
|
|
17
|
-
return
|
|
19
|
+
return r;
|
|
18
20
|
};
|
|
19
|
-
export const Lines = (
|
|
20
|
-
const {
|
|
21
|
-
const
|
|
21
|
+
export const Lines = (props) => {
|
|
22
|
+
const { children, className, curve = "linear", joints, loading = false, datasets, context: ctx } = props;
|
|
23
|
+
const graph = useGraph();
|
|
24
|
+
const dsets = useDatasets(datasets);
|
|
22
25
|
const isZooming = useIsZooming();
|
|
26
|
+
const context = ctx !== null && ctx !== void 0 ? ctx : graph;
|
|
27
|
+
const { data, viewbox, interactions: { pinned, hovered }, colors, } = context;
|
|
23
28
|
if (!GraphUtils.isXYData(data))
|
|
24
29
|
return null;
|
|
25
|
-
const
|
|
26
|
-
const yForValue = CoordinatesUtils.yCoordinateFor({ domain, viewbox });
|
|
30
|
+
const xyForDataset = CoordinatesUtils.xyCoordinatesForDataset(context);
|
|
27
31
|
const lines = data.map((line, i) => {
|
|
28
32
|
var _a, _b;
|
|
29
|
-
return Object.assign(Object.assign({}, line), { id: String(line.id), stroke: (_b = (_a = line.stroke) !== null && _a !== void 0 ? _a : colors[i]) !== null && _b !== void 0 ? _b : colors.at(-1), fill: line.fill,
|
|
30
|
-
x: xForValue(xy.x),
|
|
31
|
-
y: yForValue(xy.y),
|
|
32
|
-
xValue: xy.x,
|
|
33
|
-
yValue: xy.y,
|
|
34
|
-
})) });
|
|
33
|
+
return Object.assign(Object.assign({}, line), { id: String(line.id), stroke: (_b = (_a = line.stroke) !== null && _a !== void 0 ? _a : colors[i]) !== null && _b !== void 0 ? _b : colors.at(-1), fill: line.fill, coordinates: xyForDataset(line.data) });
|
|
35
34
|
});
|
|
36
35
|
if (loading)
|
|
37
36
|
return React.createElement(LinesLoading, null);
|
|
38
|
-
return (React.createElement(
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
/* chunking is for high-performance rendering, when chunked GPU performance can improve by 3x+ at cost of allocating more DOM nodes */
|
|
42
|
-
const isChunkingCandidate = !stroke.includes("linear-gradient") && points.length > 5000 && curve === "linear";
|
|
43
|
-
const path = isChunkingCandidate ? "" : CurveUtils[curve](points);
|
|
44
|
-
const disabled = pinned.length && !pinned.includes(id) && !hovered.includes(id);
|
|
45
|
-
const isInteractiveFill = hovered.includes(id) || (pinned.includes(id) && !disabled) || fill;
|
|
46
|
-
const identifier = id.replace(/[^a-zA-Z0-9]/g, "");
|
|
47
|
-
return (React.createElement(React.Fragment, { key: i },
|
|
48
|
-
isInteractiveFill && !disabled && (React.createElement("linearGradient", { id: identifier, x1: "0", y1: "0", x2: "0", y2: "1" },
|
|
49
|
-
React.createElement("stop", { offset: "5%", stopColor: stroke, stopOpacity: "0.5" }),
|
|
50
|
-
React.createElement("stop", { offset: "95%", stopColor: stroke, stopOpacity: "0" }))),
|
|
51
|
-
isChunkingCandidate ? (chunk(points, 1000 /* chunk size determined by GPU benchmarking */).map((chunk, i) => {
|
|
52
|
-
const chunkedPath = CurveUtils[curve](chunk);
|
|
53
|
-
return (React.createElement(Line, { key: i, d: chunkedPath, stroke: stroke, fill: "transparent", className: cx("lines__stroke", disabled && "stroke-black dark:stroke-white [stroke-opacity:0.1]") }));
|
|
54
|
-
})) : (React.createElement(React.Fragment, null,
|
|
55
|
-
React.createElement(Line, { d: path, stroke: stroke, fill: "transparent", className: cx("lines__stroke", disabled && "stroke-black dark:stroke-white [stroke-opacity:0.1]") }),
|
|
56
|
-
isInteractiveFill && points[0] && (React.createElement(Line, { d: path +
|
|
57
|
-
`L ${(_b = (_a = points[points.length - 1]) === null || _a === void 0 ? void 0 : _a.x) !== null && _b !== void 0 ? _b : 0} ${viewbox.y} L 0 ${viewbox.y} L ${points[0].x} ${viewbox.y} Z`, stroke: "transparent", fill: fill || `linear-gradient(to bottom, ${toRgb(stroke, 0.5)}, ${toRgb(stroke, 0)})`, strokeOpacity: 0, className: "lines__fill" })))),
|
|
58
|
-
joints &&
|
|
59
|
-
points.map(({ x, y, xValue, yValue }, i) => {
|
|
60
|
-
const color = stroke.includes("linear-gradient")
|
|
61
|
-
? GradientUtils.gradientColorFromValue({
|
|
62
|
-
viewbox,
|
|
63
|
-
domain,
|
|
64
|
-
point: { x: xValue, y: yValue },
|
|
65
|
-
gradient: stroke,
|
|
66
|
-
dataset: points,
|
|
67
|
-
})
|
|
68
|
-
: stroke;
|
|
69
|
-
return (React.createElement(React.Fragment, { key: i },
|
|
70
|
-
typeof joints === "object" && joints.border && (React.createElement("path", { d: `M ${x} ${y} h 0.001`, strokeWidth: 8, stroke: "white", strokeLinecap: "round", strokeLinejoin: "round", vectorEffect: "non-scaling-stroke", className: "lines__joints" })),
|
|
71
|
-
React.createElement("path", { d: `M ${x} ${y} h 0.001`, strokeWidth: 7, stroke: color, strokeLinecap: "round", strokeLinejoin: "round", vectorEffect: "non-scaling-stroke", className: "lines__joints" })));
|
|
72
|
-
})));
|
|
37
|
+
return (React.createElement(React.Fragment, null,
|
|
38
|
+
dsets.map((dset, i) => {
|
|
39
|
+
return React.createElement(Lines, Object.assign({}, props, { datasets: undefined, context: dset, key: i })); // recurse for each dataset.
|
|
73
40
|
}),
|
|
74
|
-
|
|
41
|
+
React.createElement("svg", { viewBox: `0 0 ${viewbox.x} ${viewbox.y}`, preserveAspectRatio: "none", className: tw("absolute overflow-visible lines h-full w-full [grid-area:graph] will-change-transform [transform:translateZ(0)]", isZooming && "block overflow-hidden", className) },
|
|
42
|
+
lines.map(({ id, stroke, fill, coordinates: points }, i) => {
|
|
43
|
+
var _a, _b;
|
|
44
|
+
/* chunking is for high-performance rendering, when chunked GPU performance can improve by 3x+ at cost of allocating more DOM nodes */
|
|
45
|
+
const isChunkingCandidate = !stroke.includes("linear-gradient") && points.length > 5000 && curve === "linear";
|
|
46
|
+
const path = isChunkingCandidate ? "" : CurveUtils[curve](points);
|
|
47
|
+
const disabled = pinned.length && !pinned.includes(id) && !hovered.includes(id);
|
|
48
|
+
const isInteractiveFill = hovered.includes(id) || (pinned.includes(id) && !disabled) || fill;
|
|
49
|
+
const identifier = id.replace(/[^a-zA-Z0-9]/g, "");
|
|
50
|
+
return (React.createElement(React.Fragment, { key: i },
|
|
51
|
+
isInteractiveFill && !disabled && (React.createElement("linearGradient", { id: identifier, x1: "0", y1: "0", x2: "0", y2: "1" },
|
|
52
|
+
React.createElement("stop", { offset: "5%", stopColor: stroke, stopOpacity: "0.5" }),
|
|
53
|
+
React.createElement("stop", { offset: "95%", stopColor: stroke, stopOpacity: "0" }))),
|
|
54
|
+
isChunkingCandidate ? (chunk(points, 1000 /* chunk size determined by GPU benchmarking */).map((chunk, i) => {
|
|
55
|
+
const chunkedPath = CurveUtils[curve](chunk);
|
|
56
|
+
return (React.createElement(Line, { key: i, d: chunkedPath, stroke: stroke, fill: "transparent", className: cx("lines__stroke", disabled && "stroke-black dark:stroke-white [stroke-opacity:0.1]") }));
|
|
57
|
+
})) : (React.createElement(React.Fragment, null,
|
|
58
|
+
React.createElement(Line, { d: path, stroke: stroke, fill: "transparent", className: cx("lines__stroke", disabled && "stroke-black dark:stroke-white [stroke-opacity:0.1]") }),
|
|
59
|
+
isInteractiveFill && points[0] && (React.createElement(Line, { d: path +
|
|
60
|
+
`L ${(_b = (_a = points.at(-1)) === null || _a === void 0 ? void 0 : _a.x) !== null && _b !== void 0 ? _b : 0} ${viewbox.y} L 0 ${viewbox.y} L ${points[0].x} ${viewbox.y} Z`, stroke: "transparent", fill: fill || `linear-gradient(to bottom, ${toRgb(stroke, 0.5)}, ${toRgb(stroke, 0)})`, strokeOpacity: 0, className: "lines__fill" })))),
|
|
61
|
+
joints && (React.createElement(Lines.Joints, { context: context, border: typeof joints === "object" ? joints["border"] : undefined }))));
|
|
62
|
+
}),
|
|
63
|
+
children)));
|
|
75
64
|
};
|
|
76
|
-
Lines.Tooltip =
|
|
65
|
+
Lines.Tooltip = LinesTooltipZone;
|
|
66
|
+
Lines.Mouse = LinesMouse;
|
|
67
|
+
Lines.Joints = LinesJoints;
|
|
@@ -9,5 +9,5 @@ type Props = JSX.IntrinsicElements["path"] & {
|
|
|
9
9
|
y: number;
|
|
10
10
|
}>;
|
|
11
11
|
};
|
|
12
|
-
export declare const Line: ({ stroke, d, disabled, fill, className, points }: Props) => JSX.Element;
|
|
12
|
+
export declare const Line: ({ stroke, d, disabled, fill, className, points, ...rest }: Props) => JSX.Element;
|
|
13
13
|
export {};
|
|
@@ -1,6 +1,18 @@
|
|
|
1
|
+
var __rest = (this && this.__rest) || function (s, e) {
|
|
2
|
+
var t = {};
|
|
3
|
+
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)
|
|
4
|
+
t[p] = s[p];
|
|
5
|
+
if (s != null && typeof Object.getOwnPropertySymbols === "function")
|
|
6
|
+
for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {
|
|
7
|
+
if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i]))
|
|
8
|
+
t[p[i]] = s[p[i]];
|
|
9
|
+
}
|
|
10
|
+
return t;
|
|
11
|
+
};
|
|
1
12
|
import React, { useId } from "react";
|
|
2
13
|
import { LinearGradient } from "../../LinearGradient/LinearGradient";
|
|
3
|
-
export const Line = (
|
|
14
|
+
export const Line = (_a) => {
|
|
15
|
+
var { stroke, d, disabled, fill, className, points } = _a, rest = __rest(_a, ["stroke", "d", "disabled", "fill", "className", "points"]);
|
|
4
16
|
const strokeId = useId();
|
|
5
17
|
const fillId = useId();
|
|
6
18
|
const clipId = useId();
|
|
@@ -14,5 +26,5 @@ export const Line = ({ stroke, d, disabled, fill, className, points }) => {
|
|
|
14
26
|
React.createElement("rect", { width: "100%", height: "100%", fill: "black" }),
|
|
15
27
|
React.createElement("path", { d: d, fill: "none", stroke: "white", strokeWidth: 1.5, vectorEffect: "non-scaling-stroke" }))),
|
|
16
28
|
isMaskStroke && React.createElement("rect", { width: "100%", height: "100%", fill: `url(#${strokeId})`, mask: `url(#${clipId})` }),
|
|
17
|
-
!isMaskStroke && (React.createElement("path", { d: d, stroke: isGradientStroke ? `url(#${strokeId})` : stroke, fill: isGradientFill ? `url(#${fillId})` : fill, vectorEffect: "non-scaling-stroke", strokeWidth: 1.5, className: className }))));
|
|
29
|
+
!isMaskStroke && (React.createElement("path", Object.assign({ d: d, stroke: isGradientStroke ? `url(#${strokeId})` : stroke, fill: isGradientFill ? `url(#${fillId})` : fill, vectorEffect: "non-scaling-stroke", strokeWidth: 1.5, className: className }, rest)))));
|
|
18
30
|
};
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { GraphContext } from "../../../hooks/use-graph/use-graph";
|
|
2
|
+
import * as React from "react";
|
|
3
|
+
type Props = {
|
|
4
|
+
at?: {
|
|
5
|
+
x: string | number | Date;
|
|
6
|
+
};
|
|
7
|
+
border?: string;
|
|
8
|
+
strokeWidth?: number;
|
|
9
|
+
context: GraphContext;
|
|
10
|
+
};
|
|
11
|
+
export declare const LinesJoints: ({ context, border, at, strokeWidth }: Props) => (React.JSX.Element | null)[] | null;
|
|
12
|
+
export {};
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import * as React from "react";
|
|
2
|
+
import { GraphUtils } from "../../../utils/graph/graph";
|
|
3
|
+
import { GradientUtils } from "../../../utils/gradient/gradient";
|
|
4
|
+
import { equals } from "../../../utils/equals/equals";
|
|
5
|
+
import { CoordinatesUtils } from "../../../utils/coordinates/coordinates";
|
|
6
|
+
export const LinesJoints = ({ context, border, at, strokeWidth = 8 }) => {
|
|
7
|
+
if (!GraphUtils.isXYData(context.data))
|
|
8
|
+
return null;
|
|
9
|
+
const xyForPoints = CoordinatesUtils.xyCoordinatesForDataset(context);
|
|
10
|
+
return context.data.flatMap(({ data, stroke }, i) => {
|
|
11
|
+
const points = xyForPoints(data);
|
|
12
|
+
const isLinearGradient = stroke === null || stroke === void 0 ? void 0 : stroke.includes("linear-gradient");
|
|
13
|
+
if (isLinearGradient && stroke) {
|
|
14
|
+
return data.map(({ x, y }, ii) => {
|
|
15
|
+
if ((at === null || at === void 0 ? void 0 : at.x) && !equals(x, at.x))
|
|
16
|
+
return null;
|
|
17
|
+
const color = GradientUtils.gradientColorFromValue({
|
|
18
|
+
gradient: stroke,
|
|
19
|
+
point: { x, y },
|
|
20
|
+
dataset: data,
|
|
21
|
+
viewbox: context.viewbox,
|
|
22
|
+
domain: context.domain,
|
|
23
|
+
});
|
|
24
|
+
const coordinates = points[ii];
|
|
25
|
+
return (React.createElement(React.Fragment, { key: i + "|" + ii },
|
|
26
|
+
border && (React.createElement("path", { stroke: border, fill: border, d: `M ${coordinates.x} ${coordinates.y} h 0.001`, strokeWidth: strokeWidth + 1, strokeLinecap: "round", vectorEffect: "non-scaling-stroke" })),
|
|
27
|
+
React.createElement("path", { stroke: color, fill: color, d: `M ${coordinates.x} ${coordinates.y} h 0.001`, strokeWidth: strokeWidth, strokeLinecap: "round", vectorEffect: "non-scaling-stroke" })));
|
|
28
|
+
});
|
|
29
|
+
}
|
|
30
|
+
let path = "";
|
|
31
|
+
for (let i = 0; i < data.length; i++) {
|
|
32
|
+
if ((at === null || at === void 0 ? void 0 : at.x) && !equals(data[i].x, at.x))
|
|
33
|
+
continue; /* Skip if at.x is set and data[i].x !== at.x */
|
|
34
|
+
path += `M ${points[i].x} ${points[i].y} h 0.001 `; /* += for perf; see V8 and other engine string types. */
|
|
35
|
+
}
|
|
36
|
+
return (React.createElement(React.Fragment, { key: i },
|
|
37
|
+
border && (React.createElement("path", { stroke: border, fill: border, d: path, strokeWidth: strokeWidth + 1, strokeLinecap: "round", vectorEffect: "non-scaling-stroke" })),
|
|
38
|
+
React.createElement("path", { stroke: stroke, fill: stroke, d: path, strokeWidth: strokeWidth, strokeLinecap: "round", vectorEffect: "non-scaling-stroke" })));
|
|
39
|
+
});
|
|
40
|
+
};
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { useMouseCoordinates } from "../../../hooks/use-mouse-coordinates";
|
|
2
|
+
import { MouseEvent } from "react";
|
|
3
|
+
type Props = {
|
|
4
|
+
cross?: {
|
|
5
|
+
x: true;
|
|
6
|
+
y: true;
|
|
7
|
+
};
|
|
8
|
+
joints?: boolean | {
|
|
9
|
+
border: string;
|
|
10
|
+
};
|
|
11
|
+
className?: string;
|
|
12
|
+
datasets?: string[];
|
|
13
|
+
onMove?: (e: MouseEvent<SVGSVGElement>, mouse: ReturnType<typeof useMouseCoordinates>) => void;
|
|
14
|
+
onEnter?: (e: MouseEvent<SVGSVGElement>) => void;
|
|
15
|
+
onLeave?: (e: MouseEvent<SVGSVGElement>) => void;
|
|
16
|
+
};
|
|
17
|
+
export declare const LinesMouse: ({ joints, datasets, onMove, onLeave, onEnter, className }: Props) => import("react").JSX.Element;
|
|
18
|
+
export {};
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { useMouseCoordinates } from "../../../hooks/use-mouse-coordinates";
|
|
3
|
+
import { useRef } from "react";
|
|
4
|
+
import { useDatasets, useGraph, useIsZooming } from "../../../hooks/use-graph/use-graph";
|
|
5
|
+
import { tw } from "../../../utils/cx/cx";
|
|
6
|
+
import { Lines } from "../Lines";
|
|
7
|
+
export const LinesMouse = ({ joints, datasets, onMove, onLeave, onEnter, className }) => {
|
|
8
|
+
const ref = useRef(null);
|
|
9
|
+
const isZooming = useIsZooming();
|
|
10
|
+
const context = useGraph();
|
|
11
|
+
const { viewbox } = context;
|
|
12
|
+
const dsets = useDatasets(datasets);
|
|
13
|
+
const mouse = useMouseCoordinates(ref, { x: true, lazy: true });
|
|
14
|
+
return (React.createElement("svg", { ref: ref, viewBox: `0 0 ${viewbox.x} ${viewbox.y}`, preserveAspectRatio: "none", className: tw("lines-tooltip h-full w-full [grid-area:graph] absolute overflow-visible [backface-visibility:hidden]", isZooming && "block overflow-hidden", className), onMouseEnter: onEnter, onMouseLeave: onLeave, onMouseMove: (e) => onMove === null || onMove === void 0 ? void 0 : onMove(e, mouse) },
|
|
15
|
+
(mouse === null || mouse === void 0 ? void 0 : mouse.closest.x) && joints && (React.createElement(Lines.Joints, { context: context, at: { x: mouse.closest.x }, border: typeof joints === "object" ? joints["border"] : undefined })),
|
|
16
|
+
(mouse === null || mouse === void 0 ? void 0 : mouse.closest.x) &&
|
|
17
|
+
joints &&
|
|
18
|
+
dsets.map((dataset, i) => {
|
|
19
|
+
return (React.createElement(Lines.Joints, { context: dataset, at: { x: mouse.closest.x }, border: typeof joints === "object" ? joints["border"] : undefined, key: i }));
|
|
20
|
+
}),
|
|
21
|
+
mouse && (React.createElement(React.Fragment, null,
|
|
22
|
+
React.createElement("line", { x1: 0, y1: mouse.coordinates.y, x2: viewbox.x, y2: mouse.coordinates.y, stroke: "currentColor", strokeDasharray: "4,4", strokeWidth: 10, className: "stroke-gray-200 dark:stroke-white" }),
|
|
23
|
+
React.createElement("line", { x1: mouse.coordinates.x, y1: viewbox.y, x2: mouse.coordinates.x, y2: 0, strokeDasharray: "6,6", className: "stroke-gray-200 dark:stroke-white", strokeWidth: 5 })))));
|
|
24
|
+
};
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import * as React from "react";
|
|
2
|
+
import { RefObject } from "react";
|
|
2
3
|
import { CartesianDataset } from "../../../hooks/use-graph/use-graph";
|
|
3
4
|
type Props = React.HTMLAttributes<HTMLDivElement> & {
|
|
4
5
|
tooltip?: ((points: Array<Omit<CartesianDataset[number], "data"> & {
|
|
@@ -8,6 +9,7 @@ type Props = React.HTMLAttributes<HTMLDivElement> & {
|
|
|
8
9
|
display: (point: CartesianDataset[number]["data"][number]) => React.ReactNode;
|
|
9
10
|
};
|
|
10
11
|
joints?: boolean;
|
|
12
|
+
zoneRef: RefObject<SVGSVGElement | null>;
|
|
11
13
|
};
|
|
12
|
-
export declare const LinesTooltip: React.
|
|
14
|
+
export declare const LinesTooltip: ({ tooltip, joints, zoneRef: ref, ...rest }: Props) => React.JSX.Element | null;
|
|
13
15
|
export {};
|