UNPKG

reaviz

Version:

Data Visualization using React

1,282 lines 467 kB
(function() { "use strict"; try { if (typeof document != "undefined") { var elementStyle = document.createElement("style"); elementStyle.appendChild(document.createTextNode("._handle_bk7m7_1 {\n fill: var(--color-handle-fill);\n stroke: var(--color-handle-stroke);\n}\n\n._dragging_bk7m7_6 {\n fill: var(--color-handle-drag-fill);\n}\n\n._dot_bk7m7_10 {\n fill: var(--color-handle-dots);\n}\n\n._line_bk7m7_14 {\n stroke: var(--color-handle-line);\n}\n._slice_1knu8_1 {\n fill: var(--color-primary);\n}\n\n._unsliced_1knu8_5 {\n fill: var(--color-background);\n opacity: 0.5;\n pointer-events: none;\n}\n._container_1u3dt_1 {\n /** Old mappings - to be removed in next major */\n --color-background: rgb(51, 51, 51);\n --color-on-background: #fff;\n\n --color-tooltip: rgba(0, 5, 11, 0.9);\n --color-on-tooltip: #fff;\n\n --color-handle-fill: #2c343a;\n --color-handle-stroke: #67c2e4;\n --color-handle-drag-fill: transparent;\n --color-handle-dots: #67c2e4;\n --color-handle-line: #67c2e4;\n\n /** New mappings */\n --tooltip-background: var(--color-tooltip);\n --tooltip-color: var(--color-on-tooltip);\n --tooltip-border-radius: 5px;\n --tooltip-spacing: 5px;\n\n --chart-background: var(--color-background);\n --chart-color: var(--color-on-background);\n\n --chart-handle-fill: var(--color-handle-fill);\n --chart-handle-stroke: var(--color-handle-stroke);\n --chart-handle-drag-fill: var(--color-handle-drag-fill);\n --chart-handle-dots: var(--color-handle-dots);\n --chart-handle-line: var(--color-handle-line);\n}\n\n ._container_1u3dt_1 ._svg_1u3dt_30:focus {\n outline: none;\n }\n\n ._container_1u3dt_1 ._svg_1u3dt_30:focus-visible {\n outline: auto;\n }\n._container_19vag_1 {\n display: flex;\n overflow: auto;\n}\n\n ._container_19vag_1._horizontal_19vag_5 {\n align-items: center;\n flex-direction: row;\n }\n\n ._container_19vag_1._vertical_19vag_10 {\n flex-direction: column;\n }\n._symbol_f5unn_1 {\n width: 15px;\n height: 3px;\n}\n._entry_1493o_1 {\n display: flex;\n color: var(--color-on-primary);\n padding: 8px;\n will-change: transparency;\n transition: opacity 150ms ease-in;\n}\n\n ._entry_1493o_1._vertical_1493o_8 {\n flex-direction: row;\n align-items: center;\n }\n\n ._entry_1493o_1._vertical_1493o_8:first-child {\n padding-top: 0;\n }\n\n ._entry_1493o_1._vertical_1493o_8:last-child {\n padding-bottom: 0;\n }\n\n ._entry_1493o_1._vertical_1493o_8 ._label_1493o_20 {\n margin-left: 8px;\n }\n\n ._entry_1493o_1._vertical_1493o_8 svg {\n display: block;\n margin: 0 auto;\n }\n\n ._entry_1493o_1._horizontal_1493o_30 {\n align-items: center;\n flex-direction: row;\n }\n\n ._entry_1493o_1._horizontal_1493o_30:first-child {\n padding-left: 0;\n }\n\n ._entry_1493o_1._horizontal_1493o_30:last-child {\n padding-right: 0;\n }\n\n ._entry_1493o_1._horizontal_1493o_30 ._label_1493o_20 {\n margin-left: 8px;\n }\n\n ._entry_1493o_1 ._label_1493o_20 {\n font-size: 12px;\n }\n\n ._entry_1493o_1 svg {\n width: 15px;\n height: 15px;\n }\n._container_1gnp9_1 {\n display: flex;\n height: 100%;\n}\n\n ._container_1gnp9_1._vertical_1gnp9_5 {\n flex-direction: column;\n max-width: 55px;\n }\n\n ._container_1gnp9_1._vertical_1gnp9_5 ._start_1gnp9_9,\n ._container_1gnp9_1._vertical_1gnp9_5 ._end_1gnp9_10 {\n text-align: center;\n padding: 5px 0;\n width: 100%;\n }\n\n ._container_1gnp9_1._vertical_1gnp9_5 ._gradient_1gnp9_16 {\n width: 25px;\n margin: 0 auto;\n }\n\n ._container_1gnp9_1._horizontal_1gnp9_22 {\n flex-direction: row-reverse;\n }\n\n ._container_1gnp9_1._horizontal_1gnp9_22 ._start_1gnp9_9,\n ._container_1gnp9_1._horizontal_1gnp9_22 ._end_1gnp9_10 {\n max-width: 20%;\n }\n\n ._container_1gnp9_1._horizontal_1gnp9_22 ._start_1gnp9_9 {\n text-align: right;\n padding-left: 5px;\n }\n\n ._container_1gnp9_1._horizontal_1gnp9_22 ._end_1gnp9_10 {\n text-align: left;\n padding-right: 5px;\n }\n\n ._container_1gnp9_1 ._gradient_1gnp9_16 {\n flex: 1;\n width: 100%;\n border-radius: 2px;\n }\n\n ._container_1gnp9_1 ._start_1gnp9_9,\n ._container_1gnp9_1 ._end_1gnp9_10 {\n color: var(--color-on-primary);\n font-size: 12px;\n white-space: nowrap;\n overflow: hidden;\n text-overflow: ellipsis;\n }\n._gridLine_5yx3q_1 {\n shape-rendering: crispEdges;\n pointer-events: none;\n}\n._gridStripe_xcrvl_1 {\n pointer-events: none;\n}\n._markLine_1sfls_1 {\n pointer-events: none;\n stroke-dasharray: 4, 4;\n stroke-linecap: round;\n}\n._label_uiu20_1 {\n font-size: 16px;\n margin-bottom: 3px;\n color: var(--color-on-tooltip);\n}\n\n._value_uiu20_7 {\n font-size: 13px;\n color: var(--color-on-tooltip);\n opacity: 0.7;\n}\n\n._subValue_uiu20_13 {\n display: block;\n text-align: left;\n padding: 3px 5px;\n}\n\n._subValue_uiu20_13 ._subValueColor_uiu20_18 {\n width: 5px;\n height: 15px;\n margin-right: 8px;\n display: inline-block;\n }\n\n._subValue_uiu20_13 ._subValueName_uiu20_25 {\n margin-right: 5px;\n }\n._base_b22et_1 {\n white-space: nowrap;\n text-align: center;\n will-change: transform, opacity;\n background-color: var(--tooltip-background);\n color: var(--tooltip-color);\n padding: var(--tooltip-spacing);\n border-radius: var(--tooltip-border-radius);\n}\n\n ._base_b22et_1 ._disablePointer_b22et_10 {\n cursor: not-allowed;\n }\n._inactive_jp2yc_1 {\n opacity: 0.2;\n}\n\n._hidden_jp2yc_5 {\n opacity: 0;\n}\n._scatterPlot_gc5eo_1 {\n overflow: visible;\n}\n._point_u68jv_1 {\n stroke: rgba(255, 255, 255, 0.5);\n stroke-width: 1px;\n}\n._areaChart_yyojn_1 {\n overflow: visible;\n}\n._barChart_sfjii_1 {\n overflow: visible;\n}\n\n ._barChart_sfjii_1._stackedNormalized_sfjii_4 .bar, ._barChart_sfjii_1._stacked_sfjii_4 .bar, ._barChart_sfjii_1._marimekko_sfjii_6 .bar {\n stroke: var(--color-background);\n stroke-width: 0.2;\n }\n._marker_agib4_1 {\n fill: var(--color-primary);\n cursor: pointer;\n}\n._label_qd893_1 {\n font-size: 12px;\n -webkit-user-select: none;\n -moz-user-select: none;\n user-select: none;\n pointer-events: none;\n}\n._link_1oi50_1 {\n fill: none;\n transition: stroke-opacity 100ms ease-in-out, stroke 100ms ease-in-out;\n mix-blend-mode: initial;\n}\n\n._tooltip_1oi50_7 {\n text-align: center;\n pointer-events: none;\n}\n\n._tooltip_1oi50_7 ._tooltipLabel_1oi50_11 {\n font-size: 16px;\n margin-bottom: 3px;\n color: rgba(255, 255, 255, 1);\n text-align: center;\n }\n\n._tooltip_1oi50_7 ._tooltipValue_1oi50_18 {\n font-size: 13px;\n color: rgba(255, 255, 255, 0.7);\n text-align: center;\n }\n._node_oqk6h_1 {\n transition: opacity 100ms ease-in-out, fill-opacity 100ms ease-in-out;\n}\n\n._tooltip_oqk6h_5 {\n text-align: center;\n padding: 0 8px;\n pointer-events: none;\n}\n\n._tooltip_oqk6h_5 ._tooltipLabel_oqk6h_10 {\n font-size: 16px;\n margin-bottom: 3px;\n color: rgba(255, 255, 255, 1);\n text-align: center;\n }\n\n._tooltip_oqk6h_5 ._tooltipValue_oqk6h_17 {\n font-size: 13px;\n color: rgba(255, 255, 255, 0.7);\n text-align: center;\n }\n._inactive_kwc4n_1 {\n opacity: 0.4;\n transition: opacity 200ms ease-in-out;\n}\n\n._hidden_kwc4n_6 {\n opacity: 0;\n}\n._valueLabel_1eyd5_1 {\n font-size: 14px;\n font-weight: 400;\n fill: var(--color-on-background);\n opacity: 0.6;\n}\n._valueLabel_1h164_1 {\n font-size: 18px;\n font-weight: 400;\n fill: var(--color-on-background);\n}\n._stackedValueLabel_1w6zx_1 {\n font-size: 18px;\n font-weight: 400;\n fill: var(--color-on-background);\n}\n._stackedDescriptionLabel_1h95t_1 {\n font-size: 12px;\n font-weight: 400;\n fill: var(--color-on-background);\n}\n._cell_r3f8c_1 {\n transition: stroke 150ms ease-in-out;\n}\n._item_18e6r_1 {\n margin-bottom: 5px;\n align-items: center;\n display: grid;\n grid-column-gap: 5px;\n grid-row-gap: 3px;\n}\n\n ._item_18e6r_1._labelStart_18e6r_8._valueEnd_18e6r_9 {\n grid-template-columns: 2fr 2fr 1fr;\n grid-template-areas: 'label bar value-label';\n }\n\n ._item_18e6r_1._labelBottom_18e6r_15._valueEnd_18e6r_9 {\n grid-template-columns: 1fr 50px;\n grid-template-areas:\n 'bar value-label'\n 'label label';\n }\n\n ._item_18e6r_1._labelNone_18e6r_24 ._label_18e6r_8 {\n display: none;\n }\n\n ._item_18e6r_1._labelNone_18e6r_24._valueEnd_18e6r_9 {\n grid-template-columns: 1fr 50px;\n grid-template-areas: 'bar value-label';\n }\n\n ._item_18e6r_1._labelEnd_18e6r_35._valueStart_18e6r_36 {\n grid-template-columns: 50px 1fr 1fr;\n grid-template-areas: 'value-label bar label';\n }\n\n ._item_18e6r_1._labelTop_18e6r_42._valueStart_18e6r_36 {\n grid-template-columns: 50px 1fr;\n grid-template-areas:\n 'label label'\n 'value-label bar';\n }\n\n ._item_18e6r_1._labelTop_18e6r_42._valueEnd_18e6r_9 {\n grid-template-columns: 1fr 50px;\n grid-template-areas:\n 'label label'\n 'bar value-label';\n }\n\n ._item_18e6r_1._labelTop_18e6r_42._valueBottom_18e6r_57 {\n grid-template-columns: 1fr;\n grid-template-areas:\n 'label'\n 'bar'\n 'value-label';\n }\n\n ._item_18e6r_1._labelTop_18e6r_42._valueNone_18e6r_65 {\n grid-template-columns: 1fr;\n grid-template-areas:\n 'label'\n 'bar';\n }\n\n ._item_18e6r_1._labelTop_18e6r_42._valueNone_18e6r_65 ._valueLabel_18e6r_71 {\n display: none;\n }\n\n ._item_18e6r_1._clickable_18e6r_77 {\n cursor: pointer;\n }\n\n ._item_18e6r_1 ._label_18e6r_8,\n ._item_18e6r_1 ._valueLabel_18e6r_71 {\n cursor: inherit;\n }\n\n ._item_18e6r_1 ._label_18e6r_8 {\n grid-area: label;\n }\n\n ._item_18e6r_1 ._valueLabel_18e6r_71 {\n grid-area: value-label;\n line-height: 10px;\n text-overflow: ellipsis;\n overflow-x: hidden;\n }\n\n ._item_18e6r_1 ._outerBar_18e6r_97 {\n grid-area: bar;\n width: 100%;\n height: 10px;\n display: flex;\n align-items: center;\n }\n\n ._item_18e6r_1 ._bar_18e6r_105 {\n height: 5px;\n }\n._container_13giw_1 {\n display: flex;\n flex-direction: row;\n justify-content: space-between;\n align-items: center;\n}\n\n ._container_13giw_1 > div {\n flex: 1;\n }\n._wordLabel_uwka2_1 {\n -webkit-user-select: none;\n -moz-user-select: none;\n user-select: none;\n}\n\n._clickable_uwka2_5 {\n cursor: pointer;\n}")); document.head.appendChild(elementStyle); } } catch (e) { console.error("vite-plugin-css-injected-by-js", e); } })(); (function(global, factory) { typeof exports === "object" && typeof module !== "undefined" ? factory(exports, require("react/jsx-runtime"), require("reablocks"), require("react"), require("human-format"), require("d3-array"), require("d3-shape"), require("transformation-matrix"), require("classnames"), require("ellipsize"), require("d3-scale"), require("big-integer"), require("chroma-js"), require("@floating-ui/dom"), require("react-fast-compare"), require("motion/react"), require("d3-interpolate"), require("safe-identifier"), require("d3-geo"), require("d3-sankey"), require("@upsetjs/venn.js"), require("invert-color"), require("d3-hierarchy"), require("d3-cloud")) : typeof define === "function" && define.amd ? define(["exports", "react/jsx-runtime", "reablocks", "react", "human-format", "d3-array", "d3-shape", "transformation-matrix", "classnames", "ellipsize", "d3-scale", "big-integer", "chroma-js", "@floating-ui/dom", "react-fast-compare", "motion/react", "d3-interpolate", "safe-identifier", "d3-geo", "d3-sankey", "@upsetjs/venn.js", "invert-color", "d3-hierarchy", "d3-cloud"], factory) : (global = typeof globalThis !== "undefined" ? globalThis : global || self, factory(global.reaviz = {}, global.jsxRuntime, global.reablocks, global.react, global.humanFormat, global.d3Array, global.d3Shape, global.transformationMatrix, global.classNames, global.ellipsize, global.d3Scale, global.bigInt, global.chroma, global.dom, global.isEqual, global.react$1, global.d3Interpolate, global.safeIdentifier, global.d3Geo, global.d3Sankey, global.venn_js, global.invert, global.d3Hierarchy, global.cloud)); })(this, function(exports2, jsxRuntime, reablocks, react, humanFormat, d3Array, d3Shape, transformationMatrix, classNames, ellipsize, d3Scale, bigInt, chroma, dom, isEqual, react$1, d3Interpolate, safeIdentifier, d3Geo, d3Sankey, venn_js, invert, d3Hierarchy, cloud) { "use strict"; const humanFormatScale = new humanFormat.Scale({ k: 1e3, M: 1e6, B: 1e9 }); const humanFormatMillionScale = new humanFormat.Scale({ M: 1, B: 1e3, T: 1e6 }); const ONE_MILLION = 1e6; const ONE_BILLION = 1e9; const humanFormatBigInteger = (bigInteger) => { if (bigInteger.greater(ONE_BILLION)) { return humanFormat(bigInteger.divide(ONE_MILLION).toJSNumber(), { scale: humanFormatMillionScale }); } return humanFormat(bigInteger.toJSNumber(), { scale: humanFormatScale }); }; const bigIntegerToLocaleString = (bigInteger) => { let i = 0; let formattedString = ""; for (const c of bigInteger.toString().split("").reverse()) { if (i > 0 && i % 3 === 0) { formattedString = "," + formattedString; } formattedString = c + formattedString; i++; } return formattedString; }; function parseMargins(margins) { let top = 0; let right = 0; let bottom = 0; let left = 0; if (Array.isArray(margins)) { if (margins.length === 2) { top = margins[0]; bottom = margins[0]; left = margins[1]; right = margins[1]; } else if (margins.length === 4) { top = margins[0]; right = margins[1]; bottom = margins[2]; left = margins[3]; } } else if (margins !== void 0) { top = margins; right = margins; bottom = margins; left = margins; } return { top, right, bottom, left }; } function calculateMarginOffsets(height, width, margins) { const { left, right, bottom, top } = margins; const newHeight = height - top - bottom; const newWidth = width - left - right; return { height: newHeight, width: newWidth }; } function getDimension({ xOffset, yOffset, height, width, margins }) { const parsedMargins = parseMargins(margins); const marginDims = calculateMarginOffsets(height, width, parsedMargins); const chartWidth = marginDims.width - xOffset; const chartHeight = marginDims.height - yOffset; return { xOffset, yOffset, height, width, chartWidth, chartHeight, xMargin: xOffset + parsedMargins.left, yMargin: parsedMargins.top }; } function extent(data, attr) { const accessor = (val, fn) => { if (Array.isArray(val.data)) { return fn(val.data, (vv) => vv[attr]); } return val[attr]; }; const minVal = d3Array.min(data, (d) => accessor(d, d3Array.min)); const maxVal = d3Array.max(data, (d) => accessor(d, d3Array.max)); return [minVal, maxVal]; } function getYDomain({ data, scaled = false, isDiverging = false }) { const [startY, endY] = extent(data, "y"); const [startY1, endY1] = extent(data, "y1"); if (startY < 0 || isDiverging) { const posStart = -startY; const maxNum = Math.max(posStart, endY); return [-maxNum, maxNum]; } if (scaled) { return [startY1, endY1]; } return [0, endY1]; } function getXDomain({ data, scaled = false, isDiverging = false }) { const startX0 = extent(data, "x0")[0]; const endX1 = extent(data, "x1")[1]; if (typeof startX0 === "number" && typeof endX1 === "number") { if (startX0 < 0 || isDiverging) { const posStart = -startX0; const maxNum = Math.max(posStart, endX1); return [-maxNum, maxNum]; } if (!scaled) { return [0, endX1]; } } return [startX0, endX1]; } const getNavigatorLanguage = () => { if (typeof window === "undefined") { return "en"; } if (navigator.languages && navigator.languages.length) { return navigator.languages[0]; } if (navigator.userLanguage || navigator.language || navigator.browserLanguage) { return "en"; } }; const locale = getNavigatorLanguage(); const options = { year: "numeric", month: "numeric", day: "numeric", hour12: true, formatMatcher: "best fit" }; function formatValue(value2) { if (value2 !== void 0) { if (value2 instanceof Date) { return value2.toLocaleDateString(locale, options); } else if (typeof value2 === "number") { return value2.toLocaleString(); } return value2; } return "No value"; } function getAriaLabel(datapoint) { const isArray = Array.isArray(datapoint); if (isArray) { return datapoint == null ? void 0 : datapoint.map((row) => getAriaLabel(row)).join(", "); } else { const key = (datapoint == null ? void 0 : datapoint.key) || (datapoint == null ? void 0 : datapoint.x); const value2 = (datapoint == null ? void 0 : datapoint.data) || (datapoint == null ? void 0 : datapoint.y); return `${key}: ${formatValue(value2)}`; } } function interpolate(type) { if (type === "smooth") { return d3Shape.curveMonotoneX; } else if (type === "step") { return d3Shape.curveStep; } else { return d3Shape.curveLinear; } } const scaleBandInvert = (scale, round = false) => { const domain = scale.domain(); const paddingOuter = scale(domain[0]); const eachBand = scale.step(); const [, end2] = scale.range(); return (offset) => { let band = Math.min( (offset - paddingOuter) / eachBand, domain.length - 0.01 ); if (band < 0 && Math.abs(band) > domain.length - 1) { band = Math.floor(Math.abs(band)) * -1; } let index = round ? Math.round(band) % domain.length : Math.floor(band) % domain.length; if (end2 === 0) { index = index * -1; } return domain[Math.max(0, Math.min(index, domain.length - 1))]; }; }; const getClosestContinousScalePoint = ({ pos, scale, data, attr = "x", roundDown = false }) => { const domain = scale.invert(pos); const bisect = d3Array.bisector((d) => { return attr === "i" ? d[attr] + 1 : d[attr]; }).right; const index = bisect(data, domain); const minIndex = Math.max(0, index - 1); const before = data[minIndex]; if (roundDown) { return before; } const maxIndex = Math.min(data.length - 1, index); const after = data[maxIndex]; let beforeVal = before[attr]; let afterVal = after[attr]; beforeVal = domain - beforeVal; afterVal = afterVal - domain; return beforeVal < afterVal ? before : after; }; const getClosestBandScalePoint = ({ pos, scale, data, roundClosest = false }) => { const domain = scale.domain(); let prop; if (scale.mariemkoInvert) { prop = scale.mariemkoInvert(pos); } else { prop = scaleBandInvert(scale, roundClosest)(pos); } const idx = domain.indexOf(prop); return data[idx]; }; const getParentSVG = (event) => { let node2 = event.target.ownerSVGElement; if (node2) { while (node2.ownerSVGElement) { node2 = node2.ownerSVGElement; } } return node2; }; const getPositionForTarget = ({ target, clientX, clientY }) => { const rect = target.getBoundingClientRect(); return { x: clientX - ((rect == null ? void 0 : rect.left) || 0) - target.clientLeft, y: clientY - ((rect == null ? void 0 : rect.top) || 0) - target.clientTop }; }; const getPointFromMatrix = (event, matrix) => { const parent = getParentSVG(event); if (!parent) { return null; } const { top, left } = parent.getBoundingClientRect(); const x = event.clientX - left; const y = event.clientY - top; return transformationMatrix.applyToPoint(transformationMatrix.inverse(matrix), { x, y }); }; const getLimitMatrix = (height, width, matrix) => transformationMatrix.applyToPoints(matrix, [ { x: 0, y: 0 }, { x: width, y: height } ]); const constrainMatrix = (height, width, matrix) => { const [min, max] = getLimitMatrix(height, width, matrix); if (max.x < width || max.y < height) { return true; } if (min.x > 0 || min.y > 0) { return true; } return false; }; const lessThanScaleFactorMin = (value2, scaleFactor) => value2.scaleFactorMin && value2.d * scaleFactor <= value2.scaleFactorMin; const moreThanScaleFactorMax = (value2, scaleFactor) => value2.scaleFactorMax && value2.d * scaleFactor >= value2.scaleFactorMax; const isZoomLevelGoingOutOfBounds = (value2, scaleFactor) => { const a = lessThanScaleFactorMin(value2, scaleFactor) && scaleFactor < 1; const b = moreThanScaleFactorMax(value2, scaleFactor) && scaleFactor > 1; return a || b; }; function toggleTextSelection(allowSelection) { const style = allowSelection ? "" : "none"; [ "-webkit-touch-callout", "-webkit-user-select", "-khtml-user-select", "-moz-user-select", "-ms-user-select", "user-select" ].forEach((prop) => document.body.style[prop] = style); } function calculateShowStroke(current, data) { const i = data.indexOf(current); let showLine = false; const prev = data[i - 1]; if (i > 0 && prev.y) { showLine = true; } const cur = data[i]; if (cur.y) { showLine = true; } const next = data[i + 1]; if (i < data.length - 1 && next.y) { showLine = true; } return showLine; } const ONE_DAY = 60 * 60 * 24; const DURATION_TICK_STEPS = [ 1e-3, // 1 ms 5e-3, // 5 ms 0.01, // 10 ms 0.05, // 50 ms 0.1, // 100 ms 0.5, // 500 ms 1, // 1 s 5, // 5 s 10, // 10 s 15, // 15 s 60, // 1 m 60 * 15, // 15 m 60 * 30, // 30 m 60 * 60, // 1 h 60 * 60 * 2, // 2 h 60 * 60 * 4, // 4 h 60 * 60 * 6, // 6 h 60 * 60 * 8, // 8 h 60 * 60 * 12, // 12 h ONE_DAY // 24 h ]; function reduceTicks(ticks, maxTicks) { if (ticks.length > maxTicks) { const reduced = []; const modulus = Math.floor(ticks.length / maxTicks); for (let i = 0; i < ticks.length; i++) { if (i % modulus === 0) { reduced.push(ticks[i]); } } ticks = reduced; } return ticks; } function getMaxTicks(size, dimension) { const tickWidth = Math.max(size, 0); return Math.floor(dimension / tickWidth); } function getDurationTicks(domain, maxTicks) { const domainWidth = domain[1] - domain[0]; let tickStep = null; for (const s of DURATION_TICK_STEPS) { if (domainWidth / s < maxTicks) { tickStep = s; break; } } if (tickStep === null) { const numDayTicks = domainWidth / ONE_DAY; const dayStep = Math.ceil(numDayTicks / maxTicks); tickStep = ONE_DAY * dayStep; } const ticks = [domain[0]]; while (ticks[ticks.length - 1] + tickStep <= domain[1]) { ticks.push(ticks[ticks.length - 1] + tickStep); } return ticks; } function getTicks(scale, tickValues, type, maxTicks = 100, interval) { let result; if (tickValues) { result = tickValues; } else { if (scale.ticks) { if (type === "duration") { result = getDurationTicks(scale.domain(), maxTicks); } else if (interval) { result = scale.ticks(interval); } else { if (type === "time") { result = scale.ticks(); result = reduceTicks(result, maxTicks); } else { result = scale.ticks(maxTicks); } } } else { tickValues = scale.domain(); result = reduceTicks(tickValues, maxTicks); } } return result; } const getDegrees = (radians) => radians / Math.PI * 180 - 90; const roundDecimals = (value2, decimals = 5) => parseFloat(value2.toFixed(decimals)); const functionProps = (prop, val, data) => { if (typeof val === "function") { return val(data); } else if (prop === "className") { return classNames(val); } else if (val !== void 0 || val !== null) { return val; } return {}; }; const constructFunctionProps = (props, data) => ({ className: functionProps("className", props.className, data), style: functionProps("style", props.style, data) }); function uniqueBy(data, ...accessors) { const result = []; const ittr = (arr, depth) => { for (const a of arr) { const acc = accessors[depth]; if (acc === void 0) { throw new Error(`Accessor not found for depth: ${depth}`); } const val = acc(a); if (Array.isArray(val)) { ittr(val, depth + 1); } else if (!result.includes(val)) { result.push(val); } } }; ittr(data, 0); return result; } const cache = {}; const calculateDimensions = (text, fontFamily, fontSize) => { const key = `${text}_${fontFamily}_${fontSize}`; if (cache[key]) { return cache[key]; } if (typeof window === "undefined" || typeof document === "undefined") { const height = parseInt(typeof fontSize === "string" ? fontSize : fontSize.toString(), 10); const dimensions2 = { height, // 8 is an approximation of the width of a character width: text.length * 8 }; cache[key] = dimensions2; return dimensions2; } const element = document.createElement("div"); element.style.fontFamily = fontFamily; element.style.fontSize = typeof fontSize === "string" ? fontSize : `${fontSize}px`; element.style.position = "absolute"; element.style.left = "-9999px"; element.style.whiteSpace = "nowrap"; element.style.height = "auto"; element.style.fontWeight = "normal"; element.style.lineHeight = "normal"; element.style.width = "auto"; element.style.wordBreak = "normal"; element.textContent = text; document.body.appendChild(element); const dimensions = { height: element.offsetHeight, width: element.offsetWidth }; document.body.removeChild(element); cache[key] = dimensions; return dimensions; }; function wrapText({ key, x = 0, size, paddingY, wrap = true, paddingX, width, height, fontFamily, fontSize, visibility = "auto" }) { size = size || calculateDimensions(key, fontFamily, fontSize); const words = key.toString().split(/\s+/); if (words.length > 1 && size.width > width) { let rows = []; let maxWidth = 0; let maxHeight = 0; let curText = ""; let currWidth = 0; let nextText = ""; let nextWidth = 0; for (const word of words) { nextText = curText === "" ? word : `${curText} ${word}`; nextWidth = calculateDimensions(nextText, fontFamily, fontSize).width; if (nextWidth <= width - (paddingX ? 2 * paddingX : 0)) { curText = nextText; currWidth = nextWidth; } else { rows.push(curText); maxWidth = Math.max(maxWidth, currWidth); curText = word; currWidth = calculateDimensions(curText, fontFamily, fontSize).width; } } rows.push(curText); maxHeight = rows.length * size.height; if (visibility !== "always") { if (height && maxHeight >= height - (paddingY ? 2 * paddingY : 0)) { return null; } if (width && maxWidth >= width - (paddingX ? 2 * paddingX : 0)) { return null; } } if (!wrap && rows.length > 1) { return rows[0]; } return rows.map((r, i) => /* @__PURE__ */ jsxRuntime.jsx( "tspan", { dominantBaseline: "alphabetic", style: { baselineShift: "0%" }, dy: i > 0 ? size.height : height ? size.height / 2 - 5 : -maxHeight / 2 + size.height, x, children: r }, i )); } if (visibility !== "always") { if (height && size.height + paddingY >= height) { return null; } if (width && size.width + paddingX >= width) { return null; } } return /* @__PURE__ */ jsxRuntime.jsx( "tspan", { dominantBaseline: "alphabetic", style: { baselineShift: "0%" }, dy: size.height / 2 - 5, x, children: key } ); } const useHoverIntent = ({ sensitivity = 7, interval = 50, timeout = 10, disabled, onPointerOver, onPointerOut }) => { const mouseOver = react.useRef(false); const timer = react.useRef(null); const state = react.useRef(0); const coords = react.useRef({ x: null, y: null, px: null, py: null }); const onMouseMove = react.useCallback((event) => { coords.current.x = event.clientX; coords.current.y = event.clientY; }, []); const comparePosition = react.useCallback( (event) => { timer.current = clearTimeout(timer.current); const { px, x, py, y } = coords.current; if (Math.abs(px - x) + Math.abs(py - y) < sensitivity) { state.current = 1; onPointerOver(event); } else { coords.current.px = x; coords.current.py = y; timer.current = setTimeout(() => comparePosition(event), interval); } }, [interval, onPointerOver, sensitivity] ); const cleanup = react.useCallback(() => { clearTimeout(timer.current); document.removeEventListener("mousemove", onMouseMove, false); }, [onMouseMove]); const pointerOver = react.useCallback( (event) => { if (!disabled) { mouseOver.current = true; cleanup(); if (state.current !== 1) { coords.current.px = event.nativeEvent.x; coords.current.py = event.nativeEvent.y; document.addEventListener("mousemove", onMouseMove, false); timer.current = setTimeout(() => comparePosition(event), timeout); } } }, [cleanup, comparePosition, disabled, onMouseMove, timeout] ); const delay = react.useCallback( (event) => { timer.current = clearTimeout(timer.current); state.current = 0; onPointerOut(event); }, [onPointerOut] ); const pointerOut = react.useCallback( (event) => { mouseOver.current = false; cleanup(); if (state.current === 1) { timer.current = setTimeout(() => delay(event), timeout); } }, [cleanup, delay, timeout] ); return { pointerOver, pointerOut }; }; const useResizeObserver = () => { const ref = react.useRef(null); const [size, setSize] = react.useState({ width: void 0, height: void 0 }); react.useEffect(() => { const element = ref.current; if (!element) return; const resizeObserver = new ResizeObserver((entries) => { if (entries.length === 0) return; const entry2 = entries[0]; setSize({ width: entry2.contentRect.width, height: entry2.contentRect.height }); }); resizeObserver.observe(element); return () => { resizeObserver.unobserve(element); }; }, []); return [ref, size]; }; const mergeDefaultProps = (defaultProps, props = {}) => { const filteredProps = Object.fromEntries( Object.entries(props).filter(([_, value2]) => value2 !== void 0) ); return { ...defaultProps, ...filteredProps }; }; const LinearAxisLine = (props) => { const { strokeColor, strokeWidth, strokeGradient, scale, orientation, className } = mergeDefaultProps(linearAxisLineDefaultProps, props); const id = reablocks.useId(); const [range0, range1] = scale.range(); return /* @__PURE__ */ jsxRuntime.jsxs(react.Fragment, { children: [ /* @__PURE__ */ jsxRuntime.jsx( "line", { className, x1: orientation === "vertical" ? 0 : range0, x2: orientation === "vertical" ? 1e-5 : range1, y1: orientation === "vertical" ? range0 : 0, y2: orientation === "vertical" ? range1 : 1e-5, strokeWidth, stroke: strokeGradient ? `url(#axis-gradient-${id})` : strokeColor } ), strokeGradient && /* @__PURE__ */ jsxRuntime.jsx( reablocks.CloneElement, { element: strokeGradient, id: `axis-gradient-${id}` } ) ] }); }; const linearAxisLineDefaultProps = { strokeColor: "#8F979F", strokeWidth: 1 }; const LinearAxisTickLine = (props) => { const { size, position, orientation, strokeColor, strokeWidth, className } = { ...LINEAR_AXIS_TICK_LINE_DEFAULT_PROPS, ...props }; const path2 = react.useMemo(() => { const isVertical = orientation === "vertical"; const tickSize = size || 0; const start2 = position === "start" ? tickSize * -1 : position === "center" ? tickSize * -0.5 : 0; const end2 = start2 + tickSize; return { x1: isVertical ? end2 : 0, x2: isVertical ? start2 : 0, y1: isVertical ? 0 : start2, y2: isVertical ? 0 : end2 }; }, [orientation, position, size]); return /* @__PURE__ */ jsxRuntime.jsx( "line", { className, strokeWidth, stroke: strokeColor, ...path2 } ); }; const LINEAR_AXIS_TICK_LINE_DEFAULT_PROPS = { strokeColor: "#8F979F", strokeWidth: 1, size: 5 }; const LinearAxisTickLabel = (props) => { const { text, fullText, angle, orientation, half, line: line2, textAnchor, position, className, fill, fontSize, fontFamily, rotation, padding, formatTooltip, align } = mergeDefaultProps(LINEAR_AXIS_TICK_LABEL_DEFAULT_PROPS, props); function getAlign() { if ((align === "inside" || align === "outside") && half === "center") { return "center"; } if (align === "inside") { return half === "start" ? "end" : "start"; } if (align === "outside") { return half === "start" ? "start" : "end"; } return align; } function getTickLineSpacing() { if (!line2) { return [0, 0]; } const lineProps = { ...LINEAR_AXIS_TICK_LINE_DEFAULT_PROPS, ...line2.props }; const size = lineProps.size ?? 3; const position2 = lineProps.position ?? "center"; if (position2 === "start") { return [size * -1, 0]; } else if (position2 === "end") { return [0, size]; } else { return [size * -0.5, size * 0.5]; } } function getOffset() { const adjustedPadding = typeof padding === "number" ? { fromAxis: padding, alongAxis: padding } : padding; const spacing = getTickLineSpacing(); const offset1 = position === "start" ? spacing[0] - adjustedPadding.fromAxis : position === "end" ? spacing[1] + adjustedPadding.fromAxis : 0; const align2 = getAlign(); let offset2 = 0; offset2 += align2 === "center" ? 0 : align2 === "start" ? -adjustedPadding.alongAxis : adjustedPadding.alongAxis; const horz = orientation === "horizontal"; return { [horz ? "x" : "y"]: offset2, [horz ? "y" : "x"]: offset1 }; } function getTextPosition() { let transform = ""; let newtextAnchor = ""; let alignmentBaseline = "middle"; if (angle !== 0) { transform = `rotate(${angle})`; newtextAnchor = "end"; } else { const align2 = getAlign(); if (orientation === "horizontal") { newtextAnchor = align2 === "center" ? "middle" : align2 === "start" ? "end" : "start"; if (position === "start") { alignmentBaseline = "baseline"; } else if (position === "end") { alignmentBaseline = "hanging"; } } else { alignmentBaseline = align2 === "center" ? "middle" : align2 === "start" ? "baseline" : "hanging"; if (position === "start") { newtextAnchor = "end"; } else if (position === "end") { newtextAnchor = "start"; } else { newtextAnchor = "middle"; } } } return { transform, textAnchor: textAnchor || newtextAnchor, alignmentBaseline }; } const { x, y } = getOffset(); const textPosition = getTextPosition(); const titleHover = typeof formatTooltip === "function" ? formatTooltip(fullText) : fullText; return /* @__PURE__ */ jsxRuntime.jsxs( "g", { transform: `translate(${x}, ${y})`, fontSize, fontFamily, children: [ /* @__PURE__ */ jsxRuntime.jsx("title", { children: titleHover }), /* @__PURE__ */ jsxRuntime.jsx("text", { ...textPosition, fill, className, children: text }) ] } ); }; const LINEAR_AXIS_TICK_LABEL_DEFAULT_PROPS = { fill: "#8F979F", fontSize: 11, fontFamily: "sans-serif", rotation: true, padding: 5, align: "center" }; const LinearAxisTickSeries = (props) => { const { scale, orientation, height, width, label: label2, tickSize, tickValues, interval, line: line2, axis } = mergeDefaultProps(LINEAR_AXIS_TICK_SERIES_DEFAULT_PROPS, props); const labelProps = react.useMemo( () => ({ ...LINEAR_AXIS_TICK_LABEL_DEFAULT_PROPS, ...(label2 == null ? void 0 : label2.props) ?? {} }), [label2 == null ? void 0 : label2.props] ); const getAdjustedScale = react.useCallback(() => { if (scale.bandwidth) { let offset = scale.bandwidth() / 2; if (scale.round()) { offset = Math.round(offset); } return (d) => +scale(d) + offset; } else { return (d) => +scale(d); } }, [scale]); const getPosition = react.useCallback( (scaledTick) => { if (orientation === "horizontal") { return { x: scaledTick, y: 0 }; } else { return { x: 0, y: scaledTick }; } }, [orientation] ); const getDimension2 = react.useCallback(() => { return orientation === "vertical" ? height : width; }, [height, orientation, width]); const labelFormatFn = react.useMemo(() => { if (labelProps.format) { return labelProps.format; } else if (scale.tickFormat) { return scale.tickFormat.apply(scale, [5]); } else { return (v) => formatValue(v); } }, [labelProps.format, scale]); const ticks = react.useMemo(() => { const dimension = getDimension2(); const maxTicks = getMaxTicks(tickSize, dimension); const ticks2 = getTicks(scale, tickValues, axis.type, maxTicks, interval); const adjustedScale = getAdjustedScale(); const format = labelFormatFn; const midpoint = dimension / 2; return ticks2.map((tick) => { var _a; const fullText = format(tick); const scaledTick = adjustedScale(tick); const position = getPosition(scaledTick); const text = ellipsize(fullText, 18); const size = label2 ? calculateDimensions( text, labelProps.fontFamily, (_a = labelProps.fontSize) == null ? void 0 : _a.toString() ) : {}; return { ...position, ...size, text, fullText, half: scaledTick === midpoint ? "center" : scaledTick < midpoint ? "start" : "end" }; }); }, [ axis.type, getAdjustedScale, getDimension2, getPosition, interval, label2, labelProps, labelFormatFn, scale, tickSize, tickValues ]); const angle = react.useMemo(() => { if (!label2) { return 0; } const dimension = getDimension2(); const maxTicksLength = d3Array.max(ticks, (tick) => tick.width); let angle2 = 0; if (labelProps.rotation) { if (labelProps.rotation === true) { let baseWidth = maxTicksLength; const maxBaseWidth = Math.floor(dimension / ticks.length); while (baseWidth > maxBaseWidth && angle2 > -90) { angle2 -= 30; baseWidth = Math.cos(angle2 * (Math.PI / 180)) * maxTicksLength; } } else { angle2 = labelProps.rotation; } } return angle2; }, [getDimension2, label2, labelProps, ticks]); return /* @__PURE__ */ jsxRuntime.jsx(react.Fragment, { children: ticks.map((tick, i) => /* @__PURE__ */ jsxRuntime.jsxs("g", { transform: `translate(${tick.x}, ${tick.y})`, children: [ line2 && /* @__PURE__ */ jsxRuntime.jsx( reablocks.CloneElement, { element: line2, height, width, orientation } ), label2 && /* @__PURE__ */ jsxRuntime.jsx( reablocks.CloneElement, { element: label2, text: tick.text, fullText: tick.fullText, half: tick.half, angle, orientation, line: line2 } ) ] }, i)) }); }; const LINEAR_AXIS_TICK_SERIES_DEFAULT_PROPS = { line: /* @__PURE__ */ jsxRuntime.jsx( LinearAxisTickLine, { ...LINEAR_AXIS_TICK_LINE_DEFAULT_PROPS, height: 10, width: 10, orientation: "horizontal", position: "center" } ), label: /* @__PURE__ */ jsxRuntime.jsx( LinearAxisTickLabel, { line: /* @__PURE__ */ jsxRuntime.jsx( LinearAxisTickLine, { ...LINEAR_AXIS_TICK_LINE_DEFAULT_PROPS, orientation: "horizontal", position: "center", height: 5, width: 5 } ), text: "", fullText: "", angle: 0, orientation: "horizontal", half: "start", position: "center" } ), tickSize: 30 }; const MIN_DIMENSION_CHANGE = 6; const LinearAxis = (props) => { const { position, tickSeries, axisLine, height, width, scale, orientation, visibility = "visible", onDimensionsChange } = mergeDefaultProps(LINEAR_AXIS_DEFAULT_PROPS, props); const tickSeriesProps = react.useMemo( () => mergeDefaultProps( LINEAR_AXIS_TICK_SERIES_DEFAULT_PROPS, tickSeries == null ? void 0 : tickSeries.props ), [tickSeries == null ? void 0 : tickSeries.props] ); const containerRef = react.createRef(); const [dimensions, setDimensions] = react.useState({ height, width }); const updateDimensions = react.useCallback(() => { const shouldOffset = position !== "center"; let height2; let width2; if (shouldOffset) { const dims = containerRef.current.getBoundingClientRect(); width2 = Math.floor(dims.width); height2 = Math.floor(dims.height); } if (orientation === "vertical") { if (Math.abs(dimensions.width - width2) > MIN_DIMENSION_CHANGE) { setDimensions({ ...dimensions, width: width2 }); onDimensionsChange({ width: width2 }); } } else { if (dimensions.height !== height2) { setDimensions({ ...dimensions, height: height2 }); onDimensionsChange({ height: height2 }); } } }, [containerRef, dimensions, onDimensionsChange, orientation, position]); react.useEffect(() => { updateDimensions(); }, [updateDimensions, height, width, scale]); function getPosition() { let translateY2 = 0; let translateX2 = 0; if (position === "end" && orientation === "horizontal") { translateY2 = height; } else if (position === "center" && orientation === "horizontal") { translateY2 = height / 2; } else if (position === "end" && orientation === "vertical") { translateX2 = width; } else if (position === "center" && orientation === "vertical") { translateX2 = width / 2; } return { translateX: translateX2, translateY: translateY2 }; } const { translateX, translateY } = getPosition(); return /* @__PURE__ */ jsxRuntime.jsxs( "g", { transform: `translate(${translateX}, ${translateY})`, ref: containerRef, visibility, children: [ axisLine && /* @__PURE__ */ jsxRuntime.jsx( reablocks.CloneElement, { element: axisLine, height, width, scale, orientation } ), (tickSeriesProps.line || tickSeriesProps.label) && /* @__PURE__ */ jsxRuntime.jsx( reablocks.CloneElement, { element: tickSeries, height, width, scale, orientation, axis: props } ) ] } ); }; const LINEAR_AXIS_DEFAULT_PROPS = { scaled: false, roundDomains: false, axisLine: /* @__PURE__ */ jsxRuntime.jsx(LinearAxisLine, {}), onDimensionsChange: () => void 0 }; const LinearXAxisTickLabel = (props) => /* @__PURE__ */ jsxRuntime.jsx( LinearAxisTickLabel, { ...mergeDefaultProps(LINEAR_X_AXIS_TICK_LABEL_DEFAULT_PROPS, props) } ); const LINEAR_X_AXIS_TICK_LABEL_DEFAULT_PROPS = { ...LINEAR_AXIS_TICK_LABEL_DEFAULT_PROPS, rotation: true, position: "end", align: "center" }; const LinearXAxisTickLine = (props) => /* @__PURE__ */ jsxRuntime.jsx( LinearAxisTickLine, { ...mergeDefaultProps(LINEAR_X_AXIS_TICK_LINE_DEFAULT_PROPS, props) } ); const LINEAR_X_AXIS_TICK_LINE_DEFAULT_PROPS = { ...LINEAR_AXIS_TICK_LINE_DEFAULT_PROPS, position: "end" }; const LinearXAxisTickSeries = (props) => { var _a, _b; const xTickSeriesProps = mergeDefaultProps( LINEAR_X_AXIS_TICK_SERIES_DEFAULT_PROPS, props ); return /* @__PURE__ */ jsxRuntime.jsx( LinearAxisTickSeries, { ...xTickSeriesProps, line: (xTickSeriesProps == null ? void 0 : xTickSeriesProps.line) ? /* @__PURE__ */ jsxRuntime.jsx( LinearXAxisTickLine, { ...mergeDefaultProps( LINEAR_X_AXIS_TICK_LINE_DEFAULT_PROPS, (_a = props == null ? void 0 : props.line) == null ? void 0 : _a.props ) } ) : null, label: (xTickSeriesProps == null ? void 0 : xTickSeriesProps.label) ? /* @__PURE__ */ jsxRuntime.jsx( LinearXAxisTickLabel, { ...mergeDefaultProps( LINEAR_X_AXIS_TICK_LABEL_DEFAULT_PROPS, (_b = props == null ? void 0 : props.label) == null ? void 0 : _b.props ) } ) : null } ); }; const LINEAR_X_AXIS_TICK_SERIES_DEFAULT_PROPS = { ...LINEAR_AXIS_TICK_SERIES_DEFAULT_PROPS, tickSize: 75, line: /* @__PURE__ */ jsxRuntime.jsx(LinearXAxisTickLine, { ...LINEAR_X_AXIS_TICK_LINE_DEFAULT_PROPS }), label: /* @__PURE__ */ jsxRuntime.jsx(LinearXAxisTickLabel, { ...LINEAR_X_AXIS_TICK_LABEL_DEFAULT_PROPS }) }; const LinearXAxis = (props) => { var _a; const xAxisProps = react.useMemo( () => mergeDefaultProps(LINEAR_X_AXIS_DEFAULT_PROPS, props), [props] ); return /* @__PURE__ */ jsxRuntime.jsx( LinearAxis, { ...xAxisProps, tickSeries: xAxisProps.tickSeries && /* @__PURE__ */ jsxRuntime.jsx( LinearXAxisTickSeries, { ...mergeDefaultProps( LINEAR_X_AXIS_TICK_SERIES_DEFAULT_PROPS, (_a = xAxisProps == null ? void 0 : xAxisProps.tickSeries) == null ? void 0 : _a.props ) } ) } ); }; const LINEAR_X_AXIS_DEFAULT_PROPS = { ...LINEAR_AXIS_DEFAULT_PROPS, position: "end", roundDomains: false, scaled: false, type: "value", orientation: "horizontal", tickSeries: /* @__PURE__ */ jsxRuntime.jsx(LinearXAxisTickSeries, {}) }; const LinearYAxisTickLabel = (props) => /* @__PURE__ */ jsxRuntime.jsx( LinearAxisTickLabel, { ...mergeDefaultProps(LINEAR_Y_AXIS_TICK_LABEL_DEFAULT_PROPS, props) } ); const LINEAR_Y_AXIS_TICK_LABEL_DEFAULT_PROPS = { ...LINEAR_AXIS_TICK_LABEL_DEFAULT_PROPS, rotation: false, position: "start", align: "center" }; const LinearYAxisTickLine = (props) => /* @__PURE__ */ jsxRuntime.jsx( LinearAxisTickLine, { ...mergeDefaultProps(LINEAR_Y_AXIS_TICK_LINE_DEFAULT_PROPS, props) } ); const LINEAR_Y_AXIS_TICK_LINE_DEFAULT_PROPS = { ...LINEAR_AXIS_TICK_LINE_DEFAULT_PROPS, position: "start" }; const LinearYAxisTickSeries = (props) => { var _a, _b; const yTickSeriesProps = mergeDefaultProps( LINEAR_Y_AXIS_TICK_SERIES_DEFAULT_PROPS, props );