UNPKG

@trap_stevo/legendarybuilderproreact-ui

Version:

The legendary UI & utility API that makes your application a legendary application. ~ Created by Steven Compton

873 lines 36.6 kB
import _extends from "@babel/runtime/helpers/extends"; import _defineProperty from "@babel/runtime/helpers/defineProperty"; import _slicedToArray from "@babel/runtime/helpers/slicedToArray"; import _toConsumableArray from "@babel/runtime/helpers/toConsumableArray"; function ownKeys(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; } function _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys(Object(t), !0).forEach(function (r) { _defineProperty(e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; } import React, { useState, useEffect, useRef, useMemo, useCallback, useLayoutEffect } from "react"; import { createPortal } from "react-dom"; import { motion, AnimatePresence } from "framer-motion"; var minYRange = 1e-6; function clampYRange(min, max, clamp) { var ySource = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : []; if (clamp === true) { return [Math.max(min, Math.min.apply(Math, _toConsumableArray(ySource))), Math.min(max, Math.max.apply(Math, _toConsumableArray(ySource)))]; } if (Array.isArray(clamp) && clamp.length === 2) { return [Math.max(min, clamp[0]), Math.min(max, clamp[1])]; } return [min, max]; } ; function HUDMultiLineChart(_ref) { var _ref$toolTipContainer = _ref.toolTipContainerAnimationTransitionConfigurationSettings, toolTipContainerAnimationTransitionConfigurationSettings = _ref$toolTipContainer === void 0 ? {} : _ref$toolTipContainer, _ref$toolTipContainer2 = _ref.toolTipContainerInitialAnimationConfigurationSettings, toolTipContainerInitialAnimationConfigurationSettings = _ref$toolTipContainer2 === void 0 ? {} : _ref$toolTipContainer2, _ref$toolTipContainer3 = _ref.toolTipContainerExitAnimationConfigurationSettings, toolTipContainerExitAnimationConfigurationSettings = _ref$toolTipContainer3 === void 0 ? {} : _ref$toolTipContainer3, _ref$toolTipContainer4 = _ref.toolTipContainerAnimationConfigurationSettings, toolTipContainerAnimationConfigurationSettings = _ref$toolTipContainer4 === void 0 ? {} : _ref$toolTipContainer4, _ref$multiLineChartCo = _ref.multiLineChartContainerConfigurationSettings, multiLineChartContainerConfigurationSettings = _ref$multiLineChartCo === void 0 ? {} : _ref$multiLineChartCo, _ref$legendSeriesIndi = _ref.legendSeriesIndicatorConfigurationSettings, legendSeriesIndicatorConfigurationSettings = _ref$legendSeriesIndi === void 0 ? {} : _ref$legendSeriesIndi, _ref$toolTipContainer5 = _ref.toolTipContainerConfigurationSettings, toolTipContainerConfigurationSettings = _ref$toolTipContainer5 === void 0 ? {} : _ref$toolTipContainer5, _ref$multiLineChartCo2 = _ref.multiLineChartConfigurationSettings, multiLineChartConfigurationSettings = _ref$multiLineChartCo2 === void 0 ? {} : _ref$multiLineChartCo2, _ref$yAxisTickLabelCo = _ref.yAxisTickLabelConfigurationSettings, yAxisTickLabelConfigurationSettings = _ref$yAxisTickLabelCo === void 0 ? {} : _ref$yAxisTickLabelCo, _ref$xAxisTickLabelCo = _ref.xAxisTickLabelConfigurationSettings, xAxisTickLabelConfigurationSettings = _ref$xAxisTickLabelCo === void 0 ? {} : _ref$xAxisTickLabelCo, _ref$legendSeriesConf = _ref.legendSeriesConfigurationSettings, legendSeriesConfigurationSettings = _ref$legendSeriesConf === void 0 ? {} : _ref$legendSeriesConf, _ref$chartLegendConfi = _ref.chartLegendConfigurationSettings, chartLegendConfigurationSettings = _ref$chartLegendConfi === void 0 ? {} : _ref$chartLegendConfi, _ref$seriesLabelConfi = _ref.seriesLabelConfigurationSettings, seriesLabelConfigurationSettings = _ref$seriesLabelConfi === void 0 ? {} : _ref$seriesLabelConfi, _ref$yAxisTitleConfig = _ref.yAxisTitleConfigurationSettings, yAxisTitleConfigurationSettings = _ref$yAxisTitleConfig === void 0 ? {} : _ref$yAxisTitleConfig, _ref$xAxisTitleConfig = _ref.xAxisTitleConfigurationSettings, xAxisTitleConfigurationSettings = _ref$xAxisTitleConfig === void 0 ? {} : _ref$xAxisTitleConfig, _ref$multiLineChartCo3 = _ref.multiLineChartContainerConfigurations, multiLineChartContainerConfigurations = _ref$multiLineChartCo3 === void 0 ? {} : _ref$multiLineChartCo3, _ref$selectionIndicat = _ref.selectionIndicatorLineConfigurations, selectionIndicatorLineConfigurations = _ref$selectionIndicat === void 0 ? {} : _ref$selectionIndicat, _ref$legendSeriesIndi2 = _ref.legendSeriesIndicatorConfigurations, legendSeriesIndicatorConfigurations = _ref$legendSeriesIndi2 === void 0 ? {} : _ref$legendSeriesIndi2, _ref$legendSeriesLabe = _ref.legendSeriesLabelConfigurations, legendSeriesLabelConfigurations = _ref$legendSeriesLabe === void 0 ? {} : _ref$legendSeriesLabe, _ref$toolTipContainer6 = _ref.toolTipContainerConfigurations, toolTipContainerConfigurations = _ref$toolTipContainer6 === void 0 ? {} : _ref$toolTipContainer6, _ref$highlightedPoint = _ref.highlightedPointConfigurations, highlightedPointConfigurations = _ref$highlightedPoint === void 0 ? {} : _ref$highlightedPoint, _ref$seriesDataPointC = _ref.seriesDataPointConfigurations, seriesDataPointConfigurations = _ref$seriesDataPointC === void 0 ? {} : _ref$seriesDataPointC, _ref$multiLineChartCo4 = _ref.multiLineChartConfigurations, multiLineChartConfigurations = _ref$multiLineChartCo4 === void 0 ? {} : _ref$multiLineChartCo4, _ref$yAxisTickLabelCo2 = _ref.yAxisTickLabelConfigurations, yAxisTickLabelConfigurations = _ref$yAxisTickLabelCo2 === void 0 ? {} : _ref$yAxisTickLabelCo2, _ref$xAxisTickLabelCo2 = _ref.xAxisTickLabelConfigurations, xAxisTickLabelConfigurations = _ref$xAxisTickLabelCo2 === void 0 ? {} : _ref$xAxisTickLabelCo2, _ref$dragSelectionCon = _ref.dragSelectionConfigurations, dragSelectionConfigurations = _ref$dragSelectionCon === void 0 ? {} : _ref$dragSelectionCon, _ref$legendSeriesConf2 = _ref.legendSeriesConfigurations, legendSeriesConfigurations = _ref$legendSeriesConf2 === void 0 ? {} : _ref$legendSeriesConf2, _ref$chartLegendConfi2 = _ref.chartLegendConfigurations, chartLegendConfigurations = _ref$chartLegendConfi2 === void 0 ? {} : _ref$chartLegendConfi2, _ref$seriesLabelConfi2 = _ref.seriesLabelConfigurations, seriesLabelConfigurations = _ref$seriesLabelConfi2 === void 0 ? {} : _ref$seriesLabelConfi2, _ref$seriesLineConfig = _ref.seriesLineConfigurations, seriesLineConfigurations = _ref$seriesLineConfig === void 0 ? {} : _ref$seriesLineConfig, _ref$yAxisTitleConfig2 = _ref.yAxisTitleConfigurations, yAxisTitleConfigurations = _ref$yAxisTitleConfig2 === void 0 ? {} : _ref$yAxisTitleConfig2, _ref$xAxisTitleConfig2 = _ref.xAxisTitleConfigurations, xAxisTitleConfigurations = _ref$xAxisTitleConfig2 === void 0 ? {} : _ref$xAxisTitleConfig2, _ref$yAxisLineConfigu = _ref.yAxisLineConfigurations, yAxisLineConfigurations = _ref$yAxisLineConfigu === void 0 ? {} : _ref$yAxisLineConfigu, _ref$xAxisLineConfigu = _ref.xAxisLineConfigurations, xAxisLineConfigurations = _ref$xAxisLineConfigu === void 0 ? {} : _ref$xAxisLineConfigu, _ref$renderTooltip = _ref.renderTooltip, renderTooltip = _ref$renderTooltip === void 0 ? function (_ref2) { var _ref2$hoverPoints = _ref2.hoverPoints, hoverPoints = _ref2$hoverPoints === void 0 ? [] : _ref2$hoverPoints, hoverTime = _ref2.hoverTime, clientX = _ref2.clientX, clientY = _ref2.clientY, getSeriesLabel = _ref2.getSeriesLabel, getY = _ref2.getY; if (!hoverPoints.length) return null; return /*#__PURE__*/React.createElement("div", { style: { position: "relative", color: "#fff", borderRadius: 6, fontFamily: "monospace", fontSize: 12, zIndex: 1000 } }, hoverPoints.map(function (_ref3) { var point = _ref3.point, index = _ref3.index; return /*#__PURE__*/React.createElement("div", { key: index }, /*#__PURE__*/React.createElement("strong", null, getSeriesLabel(point, index)), ": ", getY(point).toFixed(2)); }), /*#__PURE__*/React.createElement("div", { style: { color: "#aaa", marginTop: 4 } }, new Date(hoverTime).toLocaleTimeString())); } : _ref$renderTooltip, _ref$getSeriesLabel = _ref.getSeriesLabel, getSeriesLabel = _ref$getSeriesLabel === void 0 ? function (series, i) { return "Series ".concat(i + 1); } : _ref$getSeriesLabel, _ref$getY = _ref.getY, getY = _ref$getY === void 0 ? function (d) { return d.value; } : _ref$getY, _ref$getX = _ref.getX, getX = _ref$getX === void 0 ? function (d) { return d.time; } : _ref$getX, _ref$formatTickX = _ref.formatTickX, formatTickX = _ref$formatTickX === void 0 ? function (t) { return new Date(t).toLocaleTimeString(); } : _ref$formatTickX, _ref$formatTickY = _ref.formatTickY, formatTickY = _ref$formatTickY === void 0 ? function (v) { return v.toFixed(2); } : _ref$formatTickY, _ref$onYValueWindowCh = _ref.onYValueWindowChange, onYValueWindowChange = _ref$onYValueWindowCh === void 0 ? null : _ref$onYValueWindowCh, _ref$onMaxZoomReached = _ref.onMaxZoomReached, onMaxZoomReached = _ref$onMaxZoomReached === void 0 ? null : _ref$onMaxZoomReached, onTimeWindowChange = _ref.onTimeWindowChange, onHoverPointChange = _ref.onHoverPointChange, _ref$yAxisTitle = _ref.yAxisTitle, yAxisTitle = _ref$yAxisTitle === void 0 ? "Speed (MB/s)" : _ref$yAxisTitle, _ref$xAxisTitle = _ref.xAxisTitle, xAxisTitle = _ref$xAxisTitle === void 0 ? "Progress (%)" : _ref$xAxisTitle, _ref$yValueWindow = _ref.yValueWindow, yValueWindow = _ref$yValueWindow === void 0 ? null : _ref$yValueWindow, timeWindow = _ref.timeWindow, _ref$yAxisLabelCount = _ref.yAxisLabelCount, yAxisLabelCount = _ref$yAxisLabelCount === void 0 ? 5 : _ref$yAxisLabelCount, _ref$xAxisLabelCount = _ref.xAxisLabelCount, xAxisLabelCount = _ref$xAxisLabelCount === void 0 ? 5 : _ref$xAxisLabelCount, _ref$initialHeight = _ref.initialHeight, initialHeight = _ref$initialHeight === void 0 ? 350 : _ref$initialHeight, _ref$initialWidth = _ref.initialWidth, initialWidth = _ref$initialWidth === void 0 ? 800 : _ref$initialWidth, minZoomDelta = _ref.minZoomDelta, _ref$clampYRangeToDat = _ref.clampYRangeToData, clampYRangeToData = _ref$clampYRangeToDat === void 0 ? true : _ref$clampYRangeToDat, _ref$enableDragToZoom = _ref.enableDragToZoom, enableDragToZoom = _ref$enableDragToZoom === void 0 ? true : _ref$enableDragToZoom, _ref$enableYZoom = _ref.enableYZoom, enableYZoom = _ref$enableYZoom === void 0 ? true : _ref$enableYZoom, _ref$enablePan = _ref.enablePan, enablePan = _ref$enablePan === void 0 ? true : _ref$enablePan, _ref$showGrid = _ref.showGrid, showGrid = _ref$showGrid === void 0 ? true : _ref$showGrid, _ref$snapToNearest = _ref.snapToNearest, snapToNearest = _ref$snapToNearest === void 0 ? false : _ref$snapToNearest, _ref$showEndLabels = _ref.showEndLabels, showEndLabels = _ref$showEndLabels === void 0 ? true : _ref$showEndLabels, _ref$showLineDots = _ref.showLineDots, showLineDots = _ref$showLineDots === void 0 ? true : _ref$showLineDots, _ref$highlightMode = _ref.highlightMode, highlightMode = _ref$highlightMode === void 0 ? "nearest" : _ref$highlightMode, _ref$legendPosition = _ref.legendPosition, legendPosition = _ref$legendPosition === void 0 ? "left" : _ref$legendPosition, _ref$margin = _ref.margin, margin = _ref$margin === void 0 ? { top: 20, right: 70, bottom: 60, left: 80 } : _ref$margin, _ref$lineColors = _ref.lineColors, lineColors = _ref$lineColors === void 0 ? [] : _ref$lineColors, _ref$data = _ref.data, data = _ref$data === void 0 ? [] : _ref$data; var _useState = useState({ height: initialHeight, width: initialWidth }), _useState2 = _slicedToArray(_useState, 2), containerSize = _useState2[0], setContainerSize = _useState2[1]; var _useState3 = useState(new Set(data.map(function (_, i) { return i; }))), _useState4 = _slicedToArray(_useState3, 2), visibleSeries = _useState4[0], setVisibleSeries = _useState4[1]; var _useState5 = useState({ x: 0, y: 0 }), _useState6 = _slicedToArray(_useState5, 2), tooltipMousePos = _useState6[0], setTooltipMousePos = _useState6[1]; var _useState7 = useState({ left: 0, top: 0 }), _useState8 = _slicedToArray(_useState7, 2), tooltipStyle = _useState8[0], setTooltipStyle = _useState8[1]; var _useState9 = useState([]), _useState10 = _slicedToArray(_useState9, 2), highlightedPoints = _useState10[0], setHighlightedPoints = _useState10[1]; var _useState11 = useState(null), _useState12 = _slicedToArray(_useState11, 2), internalYWindow = _useState12[0], setInternalYWindow = _useState12[1]; var _useState13 = useState(false), _useState14 = _slicedToArray(_useState13, 2), tooltipVisible = _useState14[0], setTooltipVisible = _useState14[1]; var _useState15 = useState(null), _useState16 = _slicedToArray(_useState15, 2), hoveredPoint = _useState16[0], setHoveredPoint = _useState16[1]; var _useState17 = useState(false), _useState18 = _slicedToArray(_useState17, 2), isYPanning = _useState18[0], setIsYPanning = _useState18[1]; var _useState19 = useState(null), _useState20 = _slicedToArray(_useState19, 2), dragStartX = _useState20[0], setDragStartX = _useState20[1]; var _useState21 = useState(null), _useState22 = _slicedToArray(_useState21, 2), panOriginY = _useState22[0], setPanOriginY = _useState22[1]; var _useState23 = useState(false), _useState24 = _slicedToArray(_useState23, 2), isPanning = _useState24[0], setIsPanning = _useState24[1]; var _useState25 = useState(null), _useState26 = _slicedToArray(_useState25, 2), panOrigin = _useState26[0], setPanOrigin = _useState26[1]; var _useState27 = useState(null), _useState28 = _slicedToArray(_useState27, 2), hoverTime = _useState28[0], setHoverTime = _useState28[1]; var _useState29 = useState(null), _useState30 = _slicedToArray(_useState29, 2), dragEndX = _useState30[0], setDragEndX = _useState30[1]; var tooltipHovered = useRef(false); var leaveTimeoutRef = useRef(null); var containerRef = useRef(null); var tooltipRef = useRef(null); var svgRef = useRef(null); var xMin = timeWindow[0]; var xMax = timeWindow[1]; var currentRange = xMax - xMin; var filteredData = useMemo(function () { return data.map(function (series, i) { return visibleSeries.has(i) ? { series: series, i: i } : null; }).filter(Boolean); }, [data, visibleSeries]); var allXValues = useMemo(function () { return filteredData.flatMap(function (_ref4) { var series = _ref4.series; return series.map(getX); }); }, [filteredData, getX]); var fullYValues = useMemo(function () { return filteredData.flatMap(function (_ref5) { var series = _ref5.series; return series.map(getY); }); }, [filteredData, getY]); var yValues = useMemo(function () { return filteredData.flatMap(function (_ref6) { var series = _ref6.series; return series.filter(function (p) { return getX(p) >= xMin && getX(p) <= xMax; }).map(getY); }); }, [filteredData, getX, getY, xMin, xMax]); var fullYMin = Math.min.apply(Math, _toConsumableArray(fullYValues)); var fullYMax = Math.max.apply(Math, _toConsumableArray(fullYValues)); var fullMinX = Math.min.apply(Math, _toConsumableArray(allXValues)); var fullMaxX = Math.max.apply(Math, _toConsumableArray(allXValues)); var yRangeToUse = yValueWindow !== null && yValueWindow !== void 0 ? yValueWindow : internalYWindow; var yMin, yMax; if (yRangeToUse) { yMin = yRangeToUse[0]; yMax = yRangeToUse[1]; } else { yMin = Math.min.apply(Math, _toConsumableArray(yValues)); yMax = Math.max.apply(Math, _toConsumableArray(yValues)); } var yFullyZoomedOut = Math.abs(yMax - yMin) >= Math.abs(fullYMax - fullYMin) - 1e-6; var width = containerSize.width, height = containerSize.height; var chartHeight = height - margin.top - margin.bottom; var chartWidth = width - margin.left - margin.right; var xScale = function xScale(x) { return (x - xMin) / (xMax - xMin) * chartWidth; }; var yScale = function yScale(y) { var normalized = (y - yMin) / (yMax - yMin); var clamped = Math.max(0, Math.min(1, normalized)); return chartHeight - clamped * chartHeight; }; var getTimeFromMouseX = function getTimeFromMouseX(clientX) { var rect = svgRef.current.getBoundingClientRect(); var x = clientX - rect.left - margin.left; var actualChartWidth = rect.width - margin.left - margin.right; var percent = x / actualChartWidth; return xMin + percent * (xMax - xMin); }; var handleWheelZoom = useCallback(function (e) { var zoomFactor = Math.max(0.25, Math.min(0.5, 1 / (yMax - yMin))); var rect = svgRef.current.getBoundingClientRect(); var mouseY = e.clientY - rect.top - margin.top; if (mouseY < 0 || mouseY > chartHeight) { return; } var yValueAtCursor = yMin + (1 - mouseY / chartHeight) * (yMax - yMin); var currentRange = yMax - yMin; var newRange = e.deltaY > 0 ? currentRange * (1 + zoomFactor) : currentRange * (1 - zoomFactor); if (newRange < minYRange) { onMaxZoomReached === null || onMaxZoomReached === void 0 || onMaxZoomReached(); return; } var newYMin = yValueAtCursor - (yValueAtCursor - yMin) / currentRange * newRange; var newYMax = yValueAtCursor + (yMax - yValueAtCursor) / currentRange * newRange; var _clampYRange = clampYRange(newYMin, newYMax, clampYRangeToData, yValues), _clampYRange2 = _slicedToArray(_clampYRange, 2), clampedMin = _clampYRange2[0], clampedMax = _clampYRange2[1]; (onYValueWindowChange || setInternalYWindow)([clampedMin, clampedMax]); }, [yMax, yMin, chartHeight, margin.top, onMaxZoomReached, clampYRangeToData, yValues, onYValueWindowChange]); var handleWheel = useCallback(function (e) { if (!enableYZoom || !e.ctrlKey) { return; } e.preventDefault(); handleWheelZoom(e); }, [enableYZoom, handleWheelZoom]); var handleMouseLeave = function handleMouseLeave() { leaveTimeoutRef.current = setTimeout(function () { if (!tooltipHovered.current) { setTooltipVisible(false); setHoveredPoint(null); setHighlightedPoints([]); setHoverTime(null); } }, 150); }; var handleMouseDown = function handleMouseDown(e) { var time = getTimeFromMouseX(e.clientX); if (enablePan && currentRange < fullMaxX - fullMinX) { setIsPanning(true); setPanOrigin(time); } if (enableYZoom) { setIsYPanning(true); setPanOriginY(e.clientY); } if (!isPanning && !isYPanning && enableDragToZoom) { setDragStartX(time); setDragEndX(null); } }; var handleMouseMove = function handleMouseMove(e) { var time = getTimeFromMouseX(e.clientX); if (snapToNearest) { var findClosestXPoint = function findClosestXPoint(series, xVal) { return series.reduce(function (closest, point) { var dx = Math.abs(getX(point) - xVal); return dx < Math.abs(getX(closest) - xVal) ? point : closest; }, series[0]); }; var snappedPoints = filteredData.map(function (_ref7) { var series = _ref7.series; return findClosestXPoint(series, time); }); if (highlightMode === "nearest") { var minDist = Infinity; var nearest = null; var nearestSeriesIndex = -1; snappedPoints.forEach(function (point, j) { var px = xScale(getX(point)); var py = yScale(getY(point)); var rect = svgRef.current.getBoundingClientRect(); var mouseX = e.clientX - rect.left - margin.left; var mouseY = e.clientY - rect.top - margin.top; var dist = Math.hypot(mouseX - px, mouseY - py); if (!isNaN(dist) && dist < minDist) { minDist = dist; nearest = point; nearestSeriesIndex = filteredData[j].i; } }); var result = nearest ? [{ point: nearest, index: nearestSeriesIndex }] : []; setHighlightedPoints(result); onHoverPointChange === null || onHoverPointChange === void 0 || onHoverPointChange(result); } else { var snappedHighlightedPoints = snappedPoints.map(function (point, j) { return { point: point, index: filteredData[j].i }; }).filter(function (_ref8) { var point = _ref8.point; return !isNaN(yScale(getY(point))); }); setHighlightedPoints(snappedHighlightedPoints); onHoverPointChange === null || onHoverPointChange === void 0 || onHoverPointChange(snappedHighlightedPoints); } setHoverTime(getX(snappedPoints[0])); } else { setHoverTime(time); setHighlightedPoints([]); } if (isPanning && panOrigin !== null) { var delta = panOrigin - time; var newStart = xMin + delta; var newEnd = xMax + delta; if (newStart < fullMinX) { newStart = fullMinX; newEnd = newStart + currentRange; } if (newEnd > fullMaxX) { newEnd = fullMaxX; newStart = newEnd - currentRange; } onTimeWindowChange([newStart, newEnd]); } if (isYPanning && panOriginY !== null && !e.ctrlKey) { var rect = svgRef.current.getBoundingClientRect(); var pixelDelta = e.clientY - panOriginY; var valueDelta = pixelDelta / chartHeight * (yMax - yMin); var newYMin = yMin + valueDelta; var newYMax = yMax + valueDelta; var _clampYRange3 = clampYRange(newYMin, newYMax, clampYRangeToData, yValues); var _clampYRange4 = _slicedToArray(_clampYRange3, 2); newYMin = _clampYRange4[0]; newYMax = _clampYRange4[1]; (onYValueWindowChange || setInternalYWindow)([newYMin, newYMax]); setPanOriginY(e.clientY); } if (dragStartX !== null) { setDragEndX(time); } setTooltipMousePos({ x: e.clientX, y: e.clientY }); setHoveredPoint({ hoverPoints: highlightedPoints, nearestPoint: highlightedPoints[0], hoverTime: hoverTime, getSeriesLabel: getSeriesLabel, getY: getY }); setTooltipVisible(true); }; var handleMouseUp = function handleMouseUp() { setIsPanning(false); setPanOrigin(null); setIsYPanning(false); setPanOriginY(null); if (dragStartX !== null && dragEndX !== null) { var delta = Math.abs(dragEndX - dragStartX); var threshold = minZoomDelta || currentRange * 0.01; if (delta > threshold) { var newMin = Math.min(dragStartX, dragEndX); var newMax = Math.max(dragStartX, dragEndX); onTimeWindowChange([newMin, newMax]); } } setDragStartX(null); setDragEndX(null); }; var handleDoubleClick = function handleDoubleClick() { onTimeWindowChange([fullMinX, fullMaxX]); if (!yValueWindow && enableYZoom) { var fullY = fullYValues; var _clampYRange5 = clampYRange(Math.min.apply(Math, _toConsumableArray(fullY)), Math.max.apply(Math, _toConsumableArray(fullY)), clampYRangeToData, fullY), _clampYRange6 = _slicedToArray(_clampYRange5, 2), newYMin = _clampYRange6[0], newYMax = _clampYRange6[1]; setInternalYWindow([newYMin, newYMax]); } }; useLayoutEffect(function () { if (!tooltipRef.current || !tooltipVisible || !svgRef.current) { return; } var svgRect = svgRef.current.getBoundingClientRect(); var tooltipRect = tooltipRef.current.getBoundingClientRect(); var left = tooltipMousePos.x + 12; var top = tooltipMousePos.y - tooltipRect.height - 12; if (left + tooltipRect.width > svgRect.right) { left = tooltipMousePos.x - tooltipRect.width - 12; } if (top < svgRect.top) { top = tooltipMousePos.y + 12; } setTooltipStyle({ left: left, top: top }); }, [tooltipMousePos, tooltipVisible]); useEffect(function () { if (!yValueWindow && (!internalYWindow || !Array.isArray(internalYWindow))) { var _clampYRange7 = clampYRange(fullYMin, fullYMax, clampYRangeToData, fullYValues), _clampYRange8 = _slicedToArray(_clampYRange7, 2), newYMin = _clampYRange8[0], newYMax = _clampYRange8[1]; setInternalYWindow([newYMin, newYMax]); } }, [yValueWindow, internalYWindow, fullYMin, fullYMax, clampYRangeToData, fullYValues]); useEffect(function () { var svg = svgRef.current; if (!svg) { return; } var wheelHandler = function wheelHandler(e) { handleWheel(e); }; svg.addEventListener("wheel", wheelHandler, { passive: false }); return function () { return svg.removeEventListener("wheel", wheelHandler); }; }, [handleWheel]); useEffect(function () { function handleMouseMove(e) { if (!tooltipRef.current) { return; } var rect = tooltipRef.current.getBoundingClientRect(); var padding = 12; var inside = e.clientX >= rect.left - padding && e.clientX <= rect.right + padding && e.clientY >= rect.top - padding && e.clientY <= rect.bottom + padding; tooltipHovered.current = inside; } ; window.addEventListener("mousemove", handleMouseMove); return function () { return window.removeEventListener("mousemove", handleMouseMove); }; }, []); useEffect(function () { setContainerSize({ height: initialHeight, width: initialWidth }); }, [initialHeight, initialWidth]); useEffect(function () { return function () { if (leaveTimeoutRef.current) { clearTimeout(leaveTimeoutRef.current); } }; }, []); var dragX1 = xScale(dragStartX !== null && dragStartX !== void 0 ? dragStartX : 0); var dragX2 = xScale(dragEndX !== null && dragEndX !== void 0 ? dragEndX : 0); var dragging = dragStartX !== null && dragEndX !== null; var legendStyle = useMemo(function () { return { display: "flex", flexDirection: legendPosition === "left" ? "column" : "row", userSelect: "none", fontFamily: "monospace", fontSize: 12, background: "#101010", gap: 8, padding: "8px 12px" }; }, [legendPosition]); return /*#__PURE__*/React.createElement("div", _extends({ ref: containerRef, style: _objectSpread({ display: "flex", flexDirection: legendPosition === "left" ? "row" : "column", overflow: "hidden", borderRadius: 8, background: "#0b0b0b", height: 400, width: "100%" }, multiLineChartContainerConfigurationSettings) }, multiLineChartContainerConfigurations), legendPosition === "left" && /*#__PURE__*/React.createElement("div", _extends({ style: _objectSpread(_objectSpread({}, legendStyle), chartLegendConfigurationSettings) }, chartLegendConfigurations), data.map(function (series, i) { var visible = visibleSeries.has(i); return /*#__PURE__*/React.createElement("div", _extends({ key: i, style: _objectSpread({ display: "flex", alignItems: "center", cursor: "pointer", border: "1px solid ".concat(visible ? "#333" : "#222"), borderRadius: 6, background: visible ? "#222" : "transparent", color: visible ? "#fff" : "#777", gap: 6, padding: "4px 8px" }, legendSeriesConfigurationSettings), onClick: function onClick() { setVisibleSeries(function (prev) { var next = new Set(prev); next.has(i) ? next["delete"](i) : next.add(i); return next; }); } }, legendSeriesConfigurations), /*#__PURE__*/React.createElement("div", _extends({ style: _objectSpread({ filter: visible ? "none" : "grayscale(1)", borderRadius: 2, background: lineColors[i] || "#1A73E8", height: 10, width: 10, opacity: visible ? 1 : 0.5 }, legendSeriesIndicatorConfigurationSettings) }, legendSeriesIndicatorConfigurations)), /*#__PURE__*/React.createElement("span", legendSeriesLabelConfigurations, getSeriesLabel(series, i))); })), /*#__PURE__*/React.createElement("svg", _extends({ ref: svgRef, style: _objectSpread({ cursor: isPanning ? "grabbing" : dragging ? "ew-resize" : "crosshair" }, multiLineChartConfigurationSettings), viewBox: "0 0 ".concat(width, " ").concat(height), height: "100%", width: "100%", onMouseLeave: handleMouseLeave, onMouseDown: handleMouseDown, onMouseMove: handleMouseMove, onMouseUp: handleMouseUp, onDoubleClick: handleDoubleClick }, multiLineChartConfigurations), /*#__PURE__*/React.createElement("g", { transform: "translate(".concat(margin.left, ", ").concat(margin.top, ")") }, /*#__PURE__*/React.createElement("text", { x: -margin.left - 20, y: chartHeight / 2, transform: "rotate(-90, ".concat(-margin.left - 20, ", ").concat(chartHeight / 2, ")"), textAnchor: "middle", fill: "#888", fontFamily: "monospace", fontSize: 12, style: _objectSpread({ userSelect: "none" }, yAxisTitleConfigurationSettings) }, yAxisTitle), showGrid && Array.from({ length: yAxisLabelCount }).map(function (_, i) { var yVal = yMin + i / (yAxisLabelCount - 1) * (yMax - yMin); var y = yScale(yVal); return /*#__PURE__*/React.createElement("g", { key: "y-".concat(i) }, /*#__PURE__*/React.createElement("line", _extends({ y2: y, y1: y, x2: chartWidth, x1: 0, strokeDasharray: "2 2", stroke: "#333" }, yAxisLineConfigurations)), /*#__PURE__*/React.createElement("text", _extends({ y: y, x: -8, alignmentBaseline: "middle", textAnchor: "end", fill: "#888", fontFamily: "monospace", fontSize: 10, style: _objectSpread({ userSelect: "none" }, yAxisTickLabelConfigurationSettings) }, yAxisTickLabelConfigurations), formatTickY(yVal))); }), showGrid && Array.from({ length: xAxisLabelCount }).map(function (_, i) { var xVal = xMin + i / (xAxisLabelCount - 1) * (xMax - xMin); var x = xScale(xVal); return /*#__PURE__*/React.createElement("g", { key: "x-".concat(i) }, /*#__PURE__*/React.createElement("line", _extends({ y2: chartHeight, y1: 0, x2: x, x1: x, strokeDasharray: "2 2", stroke: "#333" }, xAxisLineConfigurations)), /*#__PURE__*/React.createElement("text", _extends({ y: chartHeight + 14, x: x, textAnchor: "middle", fill: "#888", fontFamily: "monospace", fontSize: 10, style: _objectSpread({ userSelect: "none" }, xAxisTickLabelConfigurationSettings) }, xAxisTickLabelConfigurations), formatTickX(xVal))); }), filteredData.map(function (_ref9) { var series = _ref9.series, i = _ref9.i; var visiblePoints = series.filter(function (d) { var x = getX(d), y = getY(d); return x >= xMin && x <= xMax && y >= yMin && y <= yMax; }); if (visiblePoints.length === 0) { return null; } var path = visiblePoints.map(function (d, j) { return "".concat(j === 0 ? "M" : "L").concat(xScale(getX(d)), ",").concat(yScale(getY(d))); }).join(" "); return /*#__PURE__*/React.createElement("g", { key: i }, /*#__PURE__*/React.createElement(motion.path, _extends({ initial: { pathLength: 0 }, animate: { pathLength: 1 }, transition: { duration: 0.3 }, stroke: lineColors[i] || "#1A73E8", strokeWidth: 2, fill: "none", d: path }, seriesLineConfigurations)), showLineDots && visiblePoints.map(function (pt, j) { return /*#__PURE__*/React.createElement("circle", _extends({ key: j, cy: yScale(getY(pt)), cx: xScale(getX(pt)), fill: lineColors[i] || "#1A73E8", strokeWidth: 0.8, stroke: "#000", r: 2.5 }, seriesDataPointConfigurations)); }), showEndLabels && function () { var last = visiblePoints[visiblePoints.length - 1]; var x = xScale(getX(last)); var y = yScale(getY(last)); return /*#__PURE__*/React.createElement("text", _extends({ x: x + 8, y: y, alignmentBaseline: "middle", fontFamily: "monospace", fontSize: 11, fill: lineColors[i] || "#1A73E8", style: _objectSpread({ userSelect: "none" }, seriesLabelConfigurationSettings) }, seriesLabelConfigurations), getSeriesLabel(series, i)); }()); }), hoverTime !== null && /*#__PURE__*/React.createElement("line", _extends({ x2: xScale(hoverTime), x1: xScale(hoverTime), y2: chartHeight, y1: 0, pointerEvents: "none", strokeDasharray: "4 2", strokeWidth: 1, stroke: "#fff" }, selectionIndicatorLineConfigurations)), snapToNearest && highlightedPoints.map(function (_ref10) { var point = _ref10.point, index = _ref10.index; return /*#__PURE__*/React.createElement(motion.circle, _extends({ key: index, initial: { opacity: 0, r: 0 }, animate: { opacity: 1, r: 5 }, transition: { duration: 0.2 }, cx: xScale(getX(point)), cy: yScale(getY(point)), stroke: lineColors[index] || "#1A73E8", strokeWidth: 2, fill: "#fff", r: 5 }, highlightedPointConfigurations)); }), dragging && /*#__PURE__*/React.createElement("rect", _extends({ x: Math.min(dragX1, dragX2), y: 0, height: chartHeight, width: Math.abs(dragX2 - dragX1), fill: "#1A73E8", opacity: 0.2 }, dragSelectionConfigurations)), /*#__PURE__*/React.createElement("text", { x: chartWidth / 2, y: height - margin.bottom + 25, textAnchor: "middle", fill: "#888", fontFamily: "monospace", fontSize: 12, style: _objectSpread({ userSelect: "none" }, xAxisTitleConfigurationSettings) }, xAxisTitle))), tooltipVisible && hoveredPoint && /*#__PURE__*/createPortal( /*#__PURE__*/React.createElement(AnimatePresence, null, /*#__PURE__*/React.createElement(motion.div, _extends({ ref: tooltipRef, initial: _objectSpread({ opacity: 0, scale: 0.95 }, toolTipContainerInitialAnimationConfigurationSettings), animate: _objectSpread({ opacity: 1, scale: 1 }, toolTipContainerAnimationConfigurationSettings), exit: _objectSpread({ opacity: 0, scale: 0.95 }, toolTipContainerExitAnimationConfigurationSettings), transition: _objectSpread({ duration: 0.2 }, toolTipContainerAnimationTransitionConfigurationSettings), style: _objectSpread({ position: "fixed", pointerEvents: "auto", WebkitBackdropFilter: "blur(10px)", backdropFilter: "blur(10px)", fontSize: 13, border: "1px solid rgba(255,255,255,0.08)", borderRadius: 12, boxShadow: "0 8px 30px rgba(0, 0, 0, 0.3)", background: "rgba(15, 20, 30, 0.9)", color: "#fff", maxWidth: 260, zIndex: 9999, padding: 12, left: tooltipStyle.left, top: tooltipStyle.top }, toolTipContainerConfigurationSettings), onMouseEnter: function onMouseEnter() { return tooltipHovered.current = true; }, onMouseLeave: function onMouseLeave() { tooltipHovered.current = false; handleMouseLeave(); } }, toolTipContainerConfigurations), renderTooltip(hoveredPoint))), document.body)); } ; export default HUDMultiLineChart;