nanoplot 0.0.51 → 0.0.52
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/index.css +4 -5
- package/dist/src/components/HydrateContext/HydrateContext.js +8 -6
- package/dist/src/components/Lines/Lines.js +3 -1
- package/dist/src/components/Tooltip/Popup.d.ts +3 -0
- package/dist/src/components/Tooltip/Popup.js +4 -4
- package/dist/src/components/Tooltip/Tooltip.d.ts +6 -0
- package/dist/src/components/Tooltip/Tooltip.js +3 -5
- package/dist/src/components/Tooltip/TooltipMouse.js +28 -12
- package/dist/src/components/Worldmap/Worldmap.d.ts +1 -2
- package/dist/src/components/Worldmap/Worldmap.js +2 -19
- package/dist/src/components/Worldmap/components/WorldmapTooltip.js +13 -13
- package/dist/src/hooks/use-graph/use-graph.d.ts +1 -0
- package/dist/src/hooks/use-graph/use-graph.js +13 -0
- package/dist/src/hooks/use-stateful-ref.d.ts +2 -2
- package/dist/src/hooks/use-stateful-ref.js +7 -1
- package/dist/src/models/domain/domain.d.ts +3 -2
- package/dist/src/utils/coordinates/coordinates.js +16 -2
- package/dist/src/utils/cx/cx.js +9 -2
- package/dist/src/utils/domain/utils/date-domain.d.ts +18 -0
- package/dist/src/utils/domain/utils/date-domain.js +296 -0
- package/dist/src/utils/domain/utils/range.js +31 -21
- package/dist/tsconfig.typings.tsbuildinfo +1 -1
- package/package.json +1 -1
- package/testing-library.ts +5 -7
- package/dist/src/utils/domain/date-domain.d.ts +0 -78
- package/dist/src/utils/domain/date-domain.js +0 -171
- package/dist/src/utils/refs/merge-refs.d.ts +0 -2
- package/dist/src/utils/refs/merge-refs.js +0 -13
package/dist/index.css
CHANGED
|
@@ -307,11 +307,6 @@
|
|
|
307
307
|
border-color: rgb(229 231 235 / var(--tw-border-opacity, 1));
|
|
308
308
|
}
|
|
309
309
|
|
|
310
|
-
.bg-black {
|
|
311
|
-
--tw-bg-opacity: 1;
|
|
312
|
-
background-color: rgb(0 0 0 / var(--tw-bg-opacity, 1));
|
|
313
|
-
}
|
|
314
|
-
|
|
315
310
|
.bg-current {
|
|
316
311
|
background-color: currentColor;
|
|
317
312
|
}
|
|
@@ -745,6 +740,10 @@
|
|
|
745
740
|
transform: translate(-50%,0);
|
|
746
741
|
}
|
|
747
742
|
|
|
743
|
+
.\[transform\:translate\(-50\%\2c calc\(-100\%-8px\)\)\] {
|
|
744
|
+
transform: translate(-50%,calc(-100% - 8px));
|
|
745
|
+
}
|
|
746
|
+
|
|
748
747
|
.\[transform\:translate\(0\2c -50\%\)\] {
|
|
749
748
|
transform: translate(0,-50%);
|
|
750
749
|
}
|
|
@@ -17,18 +17,20 @@ export const HydrateContext = (Component) => {
|
|
|
17
17
|
return (props) => {
|
|
18
18
|
const client = useContext(ClientContext);
|
|
19
19
|
const [ref, setRef] = useStatefulRef(); /* remount after set-ref */
|
|
20
|
-
const
|
|
20
|
+
const content = (() => {
|
|
21
21
|
var _a, _b, _c;
|
|
22
22
|
if (!ref.current)
|
|
23
23
|
return null;
|
|
24
24
|
if (client)
|
|
25
25
|
return client; /* <Graph/> was rendered in a browser context, no need to serialize/deserialize */
|
|
26
26
|
/* If Graph didn't send down it's javascript code, (i.e as server component, it's sent us the JSON for context in a script tag */
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
27
|
+
return (_c = document.getElementById(((_b = (_a = ref.current) === null || _a === void 0 ? void 0 : _a.closest("[data-ctx=graph]")) === null || _b === void 0 ? void 0 : _b.id) + "-context")) === null || _c === void 0 ? void 0 : _c.innerText;
|
|
28
|
+
})();
|
|
29
|
+
const ctx = useMemo(() => {
|
|
30
|
+
if (typeof content === "string")
|
|
31
|
+
return contextFromParse(content);
|
|
32
|
+
return content;
|
|
33
|
+
}, [content]);
|
|
32
34
|
return (React.createElement(React.Fragment, null,
|
|
33
35
|
React.createElement("div", { className: "[grid-area:graph]", ref: setRef }),
|
|
34
36
|
ctx && (React.createElement(GraphContextClient, { value: ctx },
|
|
@@ -36,6 +36,7 @@ export const Lines = ({ className, curve = "linear", joints, children, loading,
|
|
|
36
36
|
return React.createElement(LinesLoading, null);
|
|
37
37
|
return (React.createElement("svg", { viewBox: `0 0 ${viewbox.x} ${viewbox.y}`, preserveAspectRatio: "none", className: cx("lines h-full w-full [grid-area:graph] will-change-transform [transform:translateZ(0)]", className) },
|
|
38
38
|
lines.map(({ id, stroke, data: points }, i) => {
|
|
39
|
+
var _a, _b;
|
|
39
40
|
const isChunkingCandidate = !stroke.includes("linear-gradient") &&
|
|
40
41
|
curve ===
|
|
41
42
|
"linear"; /* chunking is for high-performance rendering, when chunked GPU performance can improve by 3x+ at cost of allocating more DOM nodes */
|
|
@@ -52,7 +53,8 @@ export const Lines = ({ className, curve = "linear", joints, children, loading,
|
|
|
52
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]") }));
|
|
53
54
|
})) : (React.createElement(React.Fragment, null,
|
|
54
55
|
React.createElement(Line, { d: path, stroke: stroke, fill: "transparent", className: cx("lines__stroke", disabled && "stroke-black dark:stroke-white [stroke-opacity:0.1]") }),
|
|
55
|
-
filled && points[0] && (React.createElement(Line, { d: path +
|
|
56
|
+
filled && 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: `linear-gradient(to bottom, ${toRgb(stroke, 0.5)}, ${toRgb(stroke, 0)})`, strokeOpacity: 0, className: "lines__fill" })))),
|
|
56
58
|
joints &&
|
|
57
59
|
points.map(({ x, y, xValue, yValue }, i) => {
|
|
58
60
|
const color = stroke.includes("linear-gradient")
|
|
@@ -10,11 +10,11 @@ var __rest = (this && this.__rest) || function (s, e) {
|
|
|
10
10
|
return t;
|
|
11
11
|
};
|
|
12
12
|
import React, { forwardRef } from "react";
|
|
13
|
-
import {
|
|
13
|
+
import { tw } from "../../utils/cx/cx";
|
|
14
14
|
export const POPUP_TRIANGLE_HEIGHT_PX = 12;
|
|
15
15
|
export const Popup = forwardRef((_a, ref) => {
|
|
16
|
-
var { radius = 5, children, border, background, target: { side, alignment } = { side: "bottom", alignment: "center" } } = _a, props = __rest(_a, ["radius", "children", "border", "background", "target"]);
|
|
17
|
-
return (React.createElement("div", Object.assign({}, props, { className:
|
|
16
|
+
var { radius = 5, children, border, background, target: { side, alignment } = { side: "bottom", alignment: "center" }, triangle } = _a, props = __rest(_a, ["radius", "children", "border", "background", "target", "triangle"]);
|
|
17
|
+
return (React.createElement("div", Object.assign({}, props, { className: tw("popup", "relative isolate pseudo-bg-inherit w-max text-white [--a:90deg] [--h:8px] [--p:50%] [--b:1px] [--p:50%] p-[12px] [border:var(--b)_solid_#0000] [background:padding-box_linear-gradient(black),border-box_rgb(45,45,45)] z-0", "before:content-[''] before:absolute before:z-[-1] before:[background-size:0_0,_100%_100%]", "after:content-[''] after:absolute after:z-[-1] after:[border:inherit] after:[background-size:100%_100%,0_0]", side === "top" &&
|
|
18
18
|
"[background-size:100%_calc(100%+var(--h))] [background-position:bottom] [border-radius:min(var(--r),var(--p)-var(--h)*tan(var(--a)/2))_min(var(--r),100%-var(--p)-var(--h)*tan(var(--a)/2))_var(--r)_var(--r)/var(--r)]", side === "top" &&
|
|
19
19
|
"before:[inset:calc(-1*var(--b)-var(--h))_calc(-1*var(--b))_calc(-1*var(--b))] before:[clip-path:polygon(min(100%,var(--p)+var(--h)*tan(var(--a)/2))_calc(var(--h)+var(--b)),min(100%,var(--p)+var(--h)*tan(var(--a)/2))_var(--h),var(--p)_0,max(0%,var(--p)-var(--h)*tan(var(--a)/2))_var(--h),max(0%,var(--p)-var(--h)*tan(var(--a)/2))_calc(var(--h)+var(--b)))]", side === "top" &&
|
|
20
20
|
"after:[inset:calc(-1*var(--b)-var(--h))_calc(-1*var(--b))_calc(-1*var(--b))] after:[clip-path:polygon(min(100%-var(--b),var(--p)+var(--h)*tan(var(--a)/2)-var(--b)*tan(45deg-var(--a)/4))_calc(var(--h)+var(--b)),var(--p)_calc(var(--b)/sin(var(--a)/2)),max(var(--b),var(--p)-var(--h)*tan(var(--a)/2)+var(--b)*tan(45deg-var(--a)/4))_calc(var(--h)+var(--b)),50%_50%)]", side === "bottom" &&
|
|
@@ -26,5 +26,5 @@ export const Popup = forwardRef((_a, ref) => {
|
|
|
26
26
|
"after:[inset:calc(-1*var(--b))_calc(-1*var(--b))_calc(-1*var(--b))_calc(-1*var(--b)-var(--h))] after:[clip-path:polygon(calc(var(--h)+var(--b))_min(100%-var(--b),var(--p)+var(--h)*tan(var(--a)/2)-var(--b)*tan(45deg-var(--a)/4)),calc(var(--b)/sin(var(--a)/2))_var(--p),calc(var(--h)+var(--b))_max(var(--b),var(--p)-var(--h)*tan(var(--a)/2)+var(--b)*tan(45deg-var(--a)/4)),50%_50%)]", side === "right" &&
|
|
27
27
|
"[background-size:calc(100%+var(--h))_100%] [border-radius:var(--r)/var(--r)_min(var(--r),var(--p)-var(--h)*tan(var(--a)/2))_min(var(--r),100%-var(--p)-var(--h)*tan(var(--a)/2))_var(--r)]", side === "right" &&
|
|
28
28
|
"before:[inset:calc(-1*var(--b))_calc(-1*var(--b)-var(--h))_calc(-1*var(--b))_calc(-1*var(--b))] before:[clip-path:polygon(calc(100%-var(--h)-var(--b))_min(100%,var(--p)+var(--h)*tan(var(--a)/2)),calc(100%-var(--h))_min(100%,var(--p)+var(--h)*tan(var(--a)/2)),100%_var(--p),calc(100%-var(--h))_max(0%,var(--p)-var(--h)*tan(var(--a)/2)),calc(100%-var(--h)-var(--b))_max(0%,var(--p)-var(--h)*tan(var(--a)/2)))]", side === "right" &&
|
|
29
|
-
"after:[inset:calc(-1*var(--b))_calc(-1*var(--b)-var(--h))_calc(-1*var(--b))_calc(-1*var(--b))] after:[clip-path:polygon(calc(100%-var(--h)-var(--b))_min(100%-var(--b),var(--p)+var(--h)*tan(var(--a)/2)-var(--b)*tan(45deg-var(--a)/4)),calc(100%-var(--b)/sin(var(--a)/2))_var(--p),calc(100%-var(--h)-var(--b))_max(var(--b),var(--p)-var(--h)*tan(var(--a)/2)+var(--b)*tan(45deg-var(--a)/4)),50%_50%)]", props.className), style: Object.assign(Object.assign({}, props.style), { "--r": radius
|
|
29
|
+
"after:[inset:calc(-1*var(--b))_calc(-1*var(--b)-var(--h))_calc(-1*var(--b))_calc(-1*var(--b))] after:[clip-path:polygon(calc(100%-var(--h)-var(--b))_min(100%-var(--b),var(--p)+var(--h)*tan(var(--a)/2)-var(--b)*tan(45deg-var(--a)/4)),calc(100%-var(--b)/sin(var(--a)/2))_var(--p),calc(100%-var(--h)-var(--b))_max(var(--b),var(--p)-var(--h)*tan(var(--a)/2)+var(--b)*tan(45deg-var(--a)/4)),50%_50%)]", props.className), style: Object.assign(Object.assign({}, props.style), { "--h": "8px", "--a": "90deg", "--r": `${radius}px`, "--b": "1px", "--p": `${triangle ? triangle.x * 100 : 50}%` }), ref: ref }), children));
|
|
30
30
|
});
|
|
@@ -15,6 +15,9 @@ export type Props = Omit<JSX.IntrinsicElements["div"], "onAnimationStart" | "onD
|
|
|
15
15
|
children?: React.ReactNode;
|
|
16
16
|
bounds?: React.RefObject<Element>;
|
|
17
17
|
contain?: React.RefObject<Element>;
|
|
18
|
+
triangle?: {
|
|
19
|
+
x: number;
|
|
20
|
+
};
|
|
18
21
|
border?: string;
|
|
19
22
|
collision?: boolean;
|
|
20
23
|
};
|
|
@@ -32,6 +35,9 @@ export declare const Tooltip: React.ForwardRefExoticComponent<Omit<React.Detaile
|
|
|
32
35
|
children?: React.ReactNode;
|
|
33
36
|
bounds?: React.RefObject<Element>;
|
|
34
37
|
contain?: React.RefObject<Element>;
|
|
38
|
+
triangle?: {
|
|
39
|
+
x: number;
|
|
40
|
+
};
|
|
35
41
|
border?: string;
|
|
36
42
|
collision?: boolean;
|
|
37
43
|
} & React.RefAttributes<HTMLDivElement>>;
|
|
@@ -16,12 +16,11 @@ import { Portal } from "../Portal/Portal";
|
|
|
16
16
|
import { useOnClickOutside } from "../../hooks/use-on-click-outside";
|
|
17
17
|
import { useStatefulRef } from "../../hooks/use-stateful-ref";
|
|
18
18
|
import { Popup } from "./Popup";
|
|
19
|
-
import { mergeRefs } from "../../utils/refs/merge-refs";
|
|
20
19
|
export const Tooltip = forwardRef((_a, ref) => {
|
|
21
20
|
var _b, _c;
|
|
22
|
-
var { active, border, delay = 0, position = { tooltip: { alignment: "center", side: "bottom" }, target: { alignment: "center", side: "top" } }, trigger, className, style, children, interactable, disabled, onClose = Object, bounds, contain, collision = true } = _a, rest = __rest(_a, ["active", "border", "delay", "position", "trigger", "className", "style", "children", "interactable", "disabled", "onClose", "bounds", "contain", "collision"]);
|
|
21
|
+
var { active, border, delay = 0, position = { tooltip: { alignment: "center", side: "bottom" }, target: { alignment: "center", side: "top" } }, trigger, className, style, children, interactable, disabled, onClose = Object, bounds, contain, triangle, collision = true } = _a, rest = __rest(_a, ["active", "border", "delay", "position", "trigger", "className", "style", "children", "interactable", "disabled", "onClose", "bounds", "contain", "triangle", "collision"]);
|
|
23
22
|
const target = useRef(null);
|
|
24
|
-
const [tooltipRef, setTooltipRef] = useStatefulRef();
|
|
23
|
+
const [tooltipRef, setTooltipRef] = useStatefulRef([ref]);
|
|
25
24
|
const [isInsideTooltip, setIsInsideTooltip] = useState(false);
|
|
26
25
|
const { styles: tetherStyles, positions: { tetherPosition: { alignment, side }, }, } = useTether({
|
|
27
26
|
targetPosition: position.target,
|
|
@@ -36,7 +35,6 @@ export const Tooltip = forwardRef((_a, ref) => {
|
|
|
36
35
|
onCollision: (collides) => {
|
|
37
36
|
if (!collision)
|
|
38
37
|
return { targetPosition: position.target, tetherPosition: position.tooltip };
|
|
39
|
-
console.log(collides);
|
|
40
38
|
return { targetPosition: position.target, tetherPosition: position.tooltip };
|
|
41
39
|
},
|
|
42
40
|
});
|
|
@@ -49,5 +47,5 @@ export const Tooltip = forwardRef((_a, ref) => {
|
|
|
49
47
|
: true;
|
|
50
48
|
return (React.createElement(React.Fragment, null,
|
|
51
49
|
trigger(target, open),
|
|
52
|
-
!disabled && isInsideContainer ? (React.createElement(Portal, null, open && Boolean(children) && (React.createElement(Popup, Object.assign({}, rest, { ref:
|
|
50
|
+
!disabled && isInsideContainer ? (React.createElement(Portal, null, open && Boolean(children) && (React.createElement(Popup, Object.assign({}, rest, { ref: setTooltipRef, style: Object.assign(Object.assign({}, tetherStyles), style), border: border, target: { side, alignment }, onMouseEnter: () => setIsInsideTooltip(true), onMouseLeave: () => setIsInsideTooltip(false), triangle: triangle, className: className }), children)))) : null));
|
|
53
51
|
});
|
|
@@ -9,25 +9,41 @@ var __rest = (this && this.__rest) || function (s, e) {
|
|
|
9
9
|
}
|
|
10
10
|
return t;
|
|
11
11
|
};
|
|
12
|
-
import React, { useEffect, useState } from "react";
|
|
12
|
+
import React, { useEffect, useRef, useState } from "react";
|
|
13
13
|
import { Tooltip } from "./Tooltip";
|
|
14
14
|
import { cx } from "../../utils/cx/cx";
|
|
15
|
+
import { MathUtils } from "../../utils/math/math";
|
|
15
16
|
export const TooltipMouse = (_a) => {
|
|
17
|
+
var _b;
|
|
16
18
|
var { active, children } = _a, props = __rest(_a, ["active", "children"]);
|
|
17
|
-
const
|
|
19
|
+
const tooltipRef = useRef(null);
|
|
20
|
+
const [mouse, setMouse] = useState({ x: 0, y: 0, triangle: { x: 0.5 } });
|
|
18
21
|
useEffect(() => {
|
|
19
|
-
const onMouseMove = (event) =>
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
22
|
+
const onMouseMove = (event) => {
|
|
23
|
+
var _a, _b, _c, _d;
|
|
24
|
+
const { width, height } = (_b = (_a = tooltipRef.current) === null || _a === void 0 ? void 0 : _a.getBoundingClientRect()) !== null && _b !== void 0 ? _b : { width: 0, height: 0 };
|
|
25
|
+
const VIEWPORT_PADDING_PX = 0;
|
|
26
|
+
const w = (width + VIEWPORT_PADDING_PX) / 2; // (because it's centered)
|
|
27
|
+
const h = (height + VIEWPORT_PADDING_PX) / 2; // (because it's centered)
|
|
28
|
+
const container = (_d = (_c = props.bounds) === null || _c === void 0 ? void 0 : _c.current) === null || _d === void 0 ? void 0 : _d.getBoundingClientRect();
|
|
29
|
+
const viewbox = {
|
|
30
|
+
width: container ? container.width + container.left : window.innerWidth,
|
|
31
|
+
height: container ? container.height + container.top : window.innerHeight,
|
|
32
|
+
};
|
|
33
|
+
const x = event.x + w > viewbox.width ? event.x - (event.x + w - viewbox.width) : event.x;
|
|
34
|
+
const y = event.y + h > viewbox.height ? event.y - (event.y + h - viewbox.height) : event.y;
|
|
35
|
+
const xPercentage = (event.x + w - viewbox.width) / width;
|
|
36
|
+
setMouse({
|
|
37
|
+
x,
|
|
38
|
+
y,
|
|
39
|
+
triangle: { x: MathUtils.clamp(0.5 + xPercentage, 0.5, 0.9) },
|
|
40
|
+
});
|
|
41
|
+
};
|
|
23
42
|
window.addEventListener("mousemove", onMouseMove);
|
|
24
43
|
return () => window.removeEventListener("mousemove", onMouseMove);
|
|
25
|
-
}, []);
|
|
26
|
-
|
|
27
|
-
// console.log(tooltipRef);
|
|
28
|
-
// }, [tooltipRef.current]);
|
|
29
|
-
return (React.createElement(Tooltip, Object.assign({ active: active, position: {
|
|
44
|
+
}, [(_b = props.bounds) === null || _b === void 0 ? void 0 : _b.current, tooltipRef.current]);
|
|
45
|
+
return (React.createElement(Tooltip, Object.assign({}, props, { active: active, position: {
|
|
30
46
|
target: { alignment: "center", side: "top" },
|
|
31
47
|
tooltip: { alignment: "center", side: "bottom" },
|
|
32
|
-
}, trigger: () => null, collision: false
|
|
48
|
+
}, trigger: () => null, collision: false, style: Object.assign(Object.assign({}, props.style), { left: mouse.x + window.scrollX, top: mouse.y + window.scrollY }), className: cx("absolute pointer-events-none [transform:translate(-50%,calc(-100%-8px))]", props.className), triangle: { x: mouse.triangle.x }, ref: tooltipRef }), children));
|
|
33
49
|
};
|
|
@@ -7,12 +7,11 @@ type Props = {
|
|
|
7
7
|
scale: number;
|
|
8
8
|
};
|
|
9
9
|
gradient?: `linear-gradient(${string})`;
|
|
10
|
-
tooltips?: Record<string, ReactNode>;
|
|
11
10
|
className?: string;
|
|
12
11
|
children?: ReactNode;
|
|
13
12
|
};
|
|
14
13
|
export declare const Worldmap: {
|
|
15
|
-
({
|
|
14
|
+
({ translate, gradient, className, children }: Props): React.JSX.Element | null;
|
|
16
15
|
Tooltip: React.ComponentType<{
|
|
17
16
|
tooltip: (datapoint: import("../../export").SegmentDataset[number]) => ReactNode;
|
|
18
17
|
}>;
|
|
@@ -2,14 +2,12 @@ import React, { useId } from "react";
|
|
|
2
2
|
import { useGraph } from "../../hooks/use-graph/use-graph";
|
|
3
3
|
import { cx } from "../../utils/cx/cx";
|
|
4
4
|
import { MathUtils } from "../../utils/math/math";
|
|
5
|
-
import { PathUtils } from "../../utils/path/path";
|
|
6
|
-
import { Popup } from "../Tooltip/Popup";
|
|
7
5
|
|
|
8
6
|
import { GradientUtils } from "../../utils/gradient/gradient";
|
|
9
7
|
import { GraphUtils } from "../../utils/graph/graph";
|
|
10
8
|
import { WorldmapTooltip } from "./components/WorldmapTooltip";
|
|
11
|
-
export const Worldmap = ({
|
|
12
|
-
var _a, _b, _c
|
|
9
|
+
export const Worldmap = ({ translate, gradient, className, children }) => {
|
|
10
|
+
var _a, _b, _c;
|
|
13
11
|
const { data, viewbox, domain } = useGraph();
|
|
14
12
|
const id = useId();
|
|
15
13
|
if (!GraphUtils.isSegmentData(data))
|
|
@@ -37,21 +35,6 @@ export const Worldmap = ({ tooltips, translate, gradient, className, children })
|
|
|
37
35
|
})();
|
|
38
36
|
return (React.createElement("path", { key: i, d: path, fill: fill, stroke: (_b = (_a = dataset[iso]) === null || _a === void 0 ? void 0 : _a.stroke) !== null && _b !== void 0 ? _b : "white", strokeWidth: 0.5, "data-iso": iso, className: `hover:stroke-white hover:stroke-[1.5] worldmap__country_${iso} worldmap__country` }));
|
|
39
37
|
})),
|
|
40
|
-
React.createElement("div", { className: "aspect-[1090/539] absolute [grid-area:graph] pointer-events-none h-full w-auto", style: { left: `${(_d = translate === null || translate === void 0 ? void 0 : translate.x) !== null && _d !== void 0 ? _d : 0}px` } },
|
|
41
|
-
React.createElement("div", { className: "relative h-full w-full" }, Object.entries(countries).map(([iso, path], i) => {
|
|
42
|
-
const { x, y } = PathUtils.center(path);
|
|
43
|
-
if (!dataset[iso])
|
|
44
|
-
return null;
|
|
45
|
-
const left = MathUtils.scale(x, 1090, 100);
|
|
46
|
-
const top = MathUtils.scale(y, 539, 100);
|
|
47
|
-
return (React.createElement(Popup, { key: i, target: { side: "bottom", alignment: "center" }, style: {
|
|
48
|
-
left: left > 85 ? undefined : left + "%",
|
|
49
|
-
right: left > 85 ? 100 - left + "%" : undefined,
|
|
50
|
-
top: top > 85 ? undefined : top + "%",
|
|
51
|
-
bottom: top > 85 ? 100 - top + "%" : undefined,
|
|
52
|
-
}, border: "rgb(45, 45, 45)", className: cx(`bg-black pointer-events-none`, styles.tooltip), "data-iso": iso },
|
|
53
|
-
React.createElement("div", null, (tooltips === null || tooltips === void 0 ? void 0 : tooltips[iso]) ? tooltips[iso] : iso)));
|
|
54
|
-
}))),
|
|
55
38
|
children));
|
|
56
39
|
};
|
|
57
40
|
Worldmap.Tooltip = WorldmapTooltip;
|
|
@@ -1,16 +1,18 @@
|
|
|
1
1
|
"use client";
|
|
2
2
|
import { useEffect, useState } from "react";
|
|
3
|
-
import { useGraph } from "../../../hooks/use-graph/use-graph";
|
|
3
|
+
import { useGraph, useGraphRef } from "../../../hooks/use-graph/use-graph";
|
|
4
4
|
import { HydrateContext } from "../../HydrateContext/HydrateContext";
|
|
5
5
|
import { GraphUtils } from "../../../utils/graph/graph";
|
|
6
6
|
import { TooltipMouse } from "../../Tooltip/TooltipMouse";
|
|
7
7
|
const WorldmapTooltipComponent = ({ tooltip }) => {
|
|
8
8
|
const { id, data } = useGraph();
|
|
9
|
-
const [
|
|
9
|
+
const [datapoint, setDatapoint] = useState();
|
|
10
|
+
const ref = useGraphRef();
|
|
10
11
|
if (!GraphUtils.isSegmentData(data))
|
|
11
12
|
return null;
|
|
12
13
|
const dataset = Object.fromEntries(data.map((datapoint) => { var _a; return [(_a = datapoint.id) !== null && _a !== void 0 ? _a : datapoint.name, datapoint]; }));
|
|
13
14
|
useEffect(() => {
|
|
15
|
+
/* Keeps 'Worldmap' as server component */
|
|
14
16
|
const countries = Array.from(document.querySelectorAll(`#${CSS.escape(id)} [data-iso]`)).filter((country) => {
|
|
15
17
|
return country instanceof Element && country.getAttribute("data-iso") !== null;
|
|
16
18
|
});
|
|
@@ -24,23 +26,21 @@ const WorldmapTooltipComponent = ({ tooltip }) => {
|
|
|
24
26
|
const datapoint = dataset[iso];
|
|
25
27
|
if (!datapoint)
|
|
26
28
|
return;
|
|
27
|
-
return
|
|
28
|
-
x: e.clientX + window.scrollX,
|
|
29
|
-
y: e.clientY + window.scrollY,
|
|
30
|
-
datapoint: Object.assign(Object.assign({}, dataset[iso]), { stroke: window.getComputedStyle(target).fill, fill: window.getComputedStyle(target).fill }),
|
|
31
|
-
});
|
|
29
|
+
return setDatapoint(Object.assign(Object.assign({}, dataset[iso]), { stroke: window.getComputedStyle(target).fill, fill: window.getComputedStyle(target).fill }));
|
|
32
30
|
};
|
|
33
|
-
const onMouseLeave = () =>
|
|
31
|
+
const onMouseLeave = () => setDatapoint(undefined);
|
|
34
32
|
const controller = new AbortController();
|
|
35
|
-
countries.forEach((country) =>
|
|
36
|
-
|
|
33
|
+
countries.forEach((country) => {
|
|
34
|
+
country.addEventListener("mouseleave", onMouseLeave, { signal: controller.signal, passive: true });
|
|
35
|
+
country.addEventListener("mousemove", onMouseMove, { signal: controller.signal, passive: true });
|
|
36
|
+
});
|
|
37
37
|
return () => controller.abort();
|
|
38
38
|
});
|
|
39
|
-
if (!
|
|
39
|
+
if (!datapoint)
|
|
40
40
|
return null;
|
|
41
|
-
const content = tooltip(
|
|
41
|
+
const content = tooltip(datapoint);
|
|
42
42
|
if (!content)
|
|
43
43
|
return null;
|
|
44
|
-
return React.createElement(TooltipMouse, { active: true },
|
|
44
|
+
return (React.createElement(TooltipMouse, { active: true, bounds: ref }, tooltip(datapoint)));
|
|
45
45
|
};
|
|
46
46
|
export const WorldmapTooltip = HydrateContext(WorldmapTooltipComponent);
|
|
@@ -67,3 +67,4 @@ export declare const GraphContextProvider: ({ value, children }: {
|
|
|
67
67
|
}) => import("react").JSX.Element;
|
|
68
68
|
export declare const useGraph: () => GraphContext;
|
|
69
69
|
export declare const useDataset: (dataset?: string) => Pick<GraphContext, "data" | "domain" | "colors">;
|
|
70
|
+
export declare const useGraphRef: () => import("react").RefObject<HTMLDivElement>;
|
|
@@ -1,5 +1,7 @@
|
|
|
1
|
+
import { useLayoutEffect } from "react";
|
|
1
2
|
import { GraphContextServer, useGraphServer } from "./use-server-graph";
|
|
2
3
|
import { GraphContextClient, useGraphClient } from "./use-client-graph";
|
|
4
|
+
import { useStatefulRef } from "../use-stateful-ref";
|
|
3
5
|
export const useGraphColumn = () => {
|
|
4
6
|
const ctx = useGraph();
|
|
5
7
|
const columns = ctx.layout.columns.split(" ");
|
|
@@ -15,3 +17,14 @@ export const useDataset = (dataset) => {
|
|
|
15
17
|
const context = useGraph();
|
|
16
18
|
return dataset ? context.datasets[dataset] : context;
|
|
17
19
|
};
|
|
20
|
+
export const useGraphRef = () => {
|
|
21
|
+
const [ref, setRef] = useStatefulRef();
|
|
22
|
+
const { id } = useGraph();
|
|
23
|
+
useLayoutEffect(() => {
|
|
24
|
+
const element = document.getElementById(id);
|
|
25
|
+
if (!element || !(element instanceof HTMLDivElement))
|
|
26
|
+
return;
|
|
27
|
+
setRef(element);
|
|
28
|
+
}, []);
|
|
29
|
+
return ref;
|
|
30
|
+
};
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { RefCallback, RefObject } from "react";
|
|
2
|
-
export declare const useStatefulRef: <T extends Element>() => [RefObject<T>, RefCallback<T>];
|
|
1
|
+
import React, { RefCallback, RefObject } from "react";
|
|
2
|
+
export declare const useStatefulRef: <T extends Element>(refs?: React.ForwardedRef<T>[]) => [RefObject<T>, RefCallback<T>];
|
|
@@ -1,11 +1,17 @@
|
|
|
1
1
|
import { useCallback, useRef, useState } from "react";
|
|
2
|
-
export const useStatefulRef = () => {
|
|
2
|
+
export const useStatefulRef = (refs = []) => {
|
|
3
3
|
const [, update] = useState(0);
|
|
4
4
|
const ref = useRef(null);
|
|
5
5
|
const setRef = useCallback((element) => {
|
|
6
6
|
/* stable function identity in ref prop on elements prevents unnecessary re-runs (see react docs) */
|
|
7
7
|
update((key) => key + 1);
|
|
8
8
|
ref.current = element;
|
|
9
|
+
refs.forEach((inputRef) => {
|
|
10
|
+
if (typeof inputRef === "function")
|
|
11
|
+
inputRef(element);
|
|
12
|
+
if (inputRef && "current" in inputRef)
|
|
13
|
+
inputRef.current = element;
|
|
14
|
+
});
|
|
9
15
|
}, []);
|
|
10
16
|
return [ref, setRef];
|
|
11
17
|
};
|
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
export type interval = "days" | "months" | "years" | "hours" | "minutes" | "seconds" | "milliseconds";
|
|
2
2
|
export type MinMax = "min" | "max";
|
|
3
|
-
export type
|
|
3
|
+
export type ISODuration = `P${string}`;
|
|
4
|
+
export type Expression = "auto" | "min" | "max" | `${MinMax} - ${number}` | `${MinMax} - ${number}%` | `${MinMax} - ${ISODuration}` | `${MinMax} + ${number}%` | `${MinMax} + ${number}` | `${MinMax} + ${ISODuration}` | number;
|
|
4
5
|
type From = "auto" | Expression | number;
|
|
5
6
|
type To = "auto" | Expression | number;
|
|
6
|
-
type Jumps = "auto" |
|
|
7
|
+
type Jumps = "auto" | ISODuration | number;
|
|
7
8
|
export type FromToJumps = {
|
|
8
9
|
from?: From;
|
|
9
10
|
to?: To;
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
export const CoordinatesUtils = {
|
|
2
2
|
xCoordinateFor: ({ domain, viewbox }) => {
|
|
3
|
-
var _a, _b;
|
|
3
|
+
var _a, _b, _c;
|
|
4
4
|
const length = domain.x.length;
|
|
5
5
|
const xTicks = domain.x.map((d) => +d.tick);
|
|
6
6
|
const coordinates = domain.x.map((d) => d.coordinate);
|
|
@@ -13,6 +13,13 @@ export const CoordinatesUtils = {
|
|
|
13
13
|
const crange = coordinates[length - 1] - coordinates[0];
|
|
14
14
|
const isDateTime = ((_a = domain.x[0]) === null || _a === void 0 ? void 0 : _a.tick) instanceof Date;
|
|
15
15
|
const isNumericalScale = typeof ((_b = domain.x[0]) === null || _b === void 0 ? void 0 : _b.tick) === "number";
|
|
16
|
+
const isCategoricalScale = typeof ((_c = domain.x[0]) === null || _c === void 0 ? void 0 : _c.tick) === "string";
|
|
17
|
+
if (isCategoricalScale) {
|
|
18
|
+
return (value) => {
|
|
19
|
+
var _a, _b;
|
|
20
|
+
return (_b = (_a = domain.x.find((d) => d.tick === value)) === null || _a === void 0 ? void 0 : _a.coordinate) !== null && _b !== void 0 ? _b : 0;
|
|
21
|
+
};
|
|
22
|
+
}
|
|
16
23
|
if (isLinearScale && (isDateTime || isNumericalScale)) {
|
|
17
24
|
return (value) => {
|
|
18
25
|
const v = (value instanceof Date ? value.getTime() : value); /* .getTime() on date's required; Performance improvement */
|
|
@@ -43,7 +50,7 @@ export const CoordinatesUtils = {
|
|
|
43
50
|
};
|
|
44
51
|
},
|
|
45
52
|
yCoordinateFor: ({ domain, viewbox }) => {
|
|
46
|
-
var _a, _b;
|
|
53
|
+
var _a, _b, _c;
|
|
47
54
|
const length = domain.y.length;
|
|
48
55
|
const yTicks = domain.y.map((d) => +d.tick);
|
|
49
56
|
const coordinates = domain.y.map((d) => d.coordinate);
|
|
@@ -56,6 +63,13 @@ export const CoordinatesUtils = {
|
|
|
56
63
|
const crange = coordinates[length - 1] - coordinates[0];
|
|
57
64
|
const isNumericalScale = typeof ((_a = domain.y[0]) === null || _a === void 0 ? void 0 : _a.tick) === "number";
|
|
58
65
|
const isDateTimeScale = ((_b = domain.y[0]) === null || _b === void 0 ? void 0 : _b.tick) instanceof Date;
|
|
66
|
+
const isCategoricalScale = typeof ((_c = domain.y[0]) === null || _c === void 0 ? void 0 : _c.tick) === "string";
|
|
67
|
+
if (isCategoricalScale) {
|
|
68
|
+
return (value) => {
|
|
69
|
+
var _a, _b;
|
|
70
|
+
return (_b = (_a = domain.y.find((d) => d.tick === value)) === null || _a === void 0 ? void 0 : _a.coordinate) !== null && _b !== void 0 ? _b : 0;
|
|
71
|
+
};
|
|
72
|
+
}
|
|
59
73
|
if (isLinearScale && (isNumericalScale || isDateTimeScale)) {
|
|
60
74
|
return (value) => {
|
|
61
75
|
const v = (value instanceof Date ? value.getTime() : value); /* .getTime() on date's required; Performance improvement */
|
package/dist/src/utils/cx/cx.js
CHANGED
|
@@ -9,12 +9,19 @@ export const cx = (...args) => {
|
|
|
9
9
|
.filter(Boolean)
|
|
10
10
|
.join(" ");
|
|
11
11
|
};
|
|
12
|
-
|
|
12
|
+
const unique = {
|
|
13
|
+
absolute: "position",
|
|
14
|
+
relative: "position",
|
|
15
|
+
static: "position",
|
|
16
|
+
};
|
|
17
|
+
/* deduplicates tailwind classes - localized mutation for perf, perf version */
|
|
13
18
|
export const tw = (...args) => {
|
|
14
19
|
const result = {};
|
|
15
20
|
cx(...args)
|
|
16
21
|
.replace(/\s+/g, " ")
|
|
17
22
|
.split(" ")
|
|
18
|
-
.forEach((cls) =>
|
|
23
|
+
.forEach((cls) => {
|
|
24
|
+
return (result[unique[cls] || cls.split("-")[0]] = cls);
|
|
25
|
+
});
|
|
19
26
|
return Object.values(result).join(" ");
|
|
20
27
|
};
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
export declare const parseDuration: (iso: string) => {
|
|
2
|
+
years: number;
|
|
3
|
+
months: number;
|
|
4
|
+
days: number;
|
|
5
|
+
hours: number;
|
|
6
|
+
minutes: number;
|
|
7
|
+
seconds: number;
|
|
8
|
+
};
|
|
9
|
+
export declare const getFloorDateFromDuration: (d: Date, duration: string) => Date;
|
|
10
|
+
export declare const getDateDomain: ({ min, max, duration }: {
|
|
11
|
+
min: Date;
|
|
12
|
+
max: Date;
|
|
13
|
+
duration: string;
|
|
14
|
+
}) => Date[];
|
|
15
|
+
export declare const getCeilDateFromDuration: (d: Date, duration: string) => Date;
|
|
16
|
+
export declare function getDurationFromRange(start: Date, end: Date): string;
|
|
17
|
+
export declare const removeDurationFromDate: (dte: Date, duration: string) => Date;
|
|
18
|
+
export declare const addDurationToDate: (dte: Date, duration: string) => Date;
|