@coinbase/cds-web-visualization 3.3.2 → 3.4.0-beta.10
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/CHANGELOG.md +50 -2
- package/dts/chart/CartesianChart.d.ts +72 -0
- package/dts/chart/CartesianChart.d.ts.map +1 -0
- package/dts/chart/ChartProvider.d.ts +6 -0
- package/dts/chart/ChartProvider.d.ts.map +1 -0
- package/dts/chart/Path.d.ts +54 -0
- package/dts/chart/Path.d.ts.map +1 -0
- package/dts/chart/PeriodSelector.d.ts +57 -0
- package/dts/chart/PeriodSelector.d.ts.map +1 -0
- package/dts/chart/area/Area.d.ts +78 -0
- package/dts/chart/area/Area.d.ts.map +1 -0
- package/dts/chart/area/AreaChart.d.ts +79 -0
- package/dts/chart/area/AreaChart.d.ts.map +1 -0
- package/dts/chart/area/DottedArea.d.ts +45 -0
- package/dts/chart/area/DottedArea.d.ts.map +1 -0
- package/dts/chart/area/GradientArea.d.ts +39 -0
- package/dts/chart/area/GradientArea.d.ts.map +1 -0
- package/dts/chart/area/SolidArea.d.ts +23 -0
- package/dts/chart/area/SolidArea.d.ts.map +1 -0
- package/dts/chart/area/index.d.ts +6 -0
- package/dts/chart/area/index.d.ts.map +1 -0
- package/dts/chart/axis/Axis.d.ts +255 -0
- package/dts/chart/axis/Axis.d.ts.map +1 -0
- package/dts/chart/axis/DefaultAxisTickLabel.d.ts +8 -0
- package/dts/chart/axis/DefaultAxisTickLabel.d.ts.map +1 -0
- package/dts/chart/axis/XAxis.d.ts +16 -0
- package/dts/chart/axis/XAxis.d.ts.map +1 -0
- package/dts/chart/axis/YAxis.d.ts +21 -0
- package/dts/chart/axis/YAxis.d.ts.map +1 -0
- package/dts/chart/axis/index.d.ts +5 -0
- package/dts/chart/axis/index.d.ts.map +1 -0
- package/dts/chart/bar/Bar.d.ts +94 -0
- package/dts/chart/bar/Bar.d.ts.map +1 -0
- package/dts/chart/bar/BarChart.d.ts +62 -0
- package/dts/chart/bar/BarChart.d.ts.map +1 -0
- package/dts/chart/bar/BarPlot.d.ts +30 -0
- package/dts/chart/bar/BarPlot.d.ts.map +1 -0
- package/dts/chart/bar/BarStack.d.ts +103 -0
- package/dts/chart/bar/BarStack.d.ts.map +1 -0
- package/dts/chart/bar/BarStackGroup.d.ts +36 -0
- package/dts/chart/bar/BarStackGroup.d.ts.map +1 -0
- package/dts/chart/bar/DefaultBar.d.ts +17 -0
- package/dts/chart/bar/DefaultBar.d.ts.map +1 -0
- package/dts/chart/bar/DefaultBarStack.d.ts +16 -0
- package/dts/chart/bar/DefaultBarStack.d.ts.map +1 -0
- package/dts/chart/bar/index.d.ts +8 -0
- package/dts/chart/bar/index.d.ts.map +1 -0
- package/dts/chart/gradient/Gradient.d.ts +35 -0
- package/dts/chart/gradient/Gradient.d.ts.map +1 -0
- package/dts/chart/gradient/index.d.ts +2 -0
- package/dts/chart/gradient/index.d.ts.map +1 -0
- package/dts/chart/index.d.ts +14 -0
- package/dts/chart/index.d.ts.map +1 -0
- package/dts/chart/line/DefaultReferenceLineLabel.d.ts +9 -0
- package/dts/chart/line/DefaultReferenceLineLabel.d.ts.map +1 -0
- package/dts/chart/line/DottedLine.d.ts +26 -0
- package/dts/chart/line/DottedLine.d.ts.map +1 -0
- package/dts/chart/line/Line.d.ts +122 -0
- package/dts/chart/line/Line.d.ts.map +1 -0
- package/dts/chart/line/LineChart.d.ts +77 -0
- package/dts/chart/line/LineChart.d.ts.map +1 -0
- package/dts/chart/line/ReferenceLine.d.ts +178 -0
- package/dts/chart/line/ReferenceLine.d.ts.map +1 -0
- package/dts/chart/line/SolidLine.d.ts +25 -0
- package/dts/chart/line/SolidLine.d.ts.map +1 -0
- package/dts/chart/line/index.d.ts +7 -0
- package/dts/chart/line/index.d.ts.map +1 -0
- package/dts/chart/point/DefaultPointLabel.d.ts +10 -0
- package/dts/chart/point/DefaultPointLabel.d.ts.map +1 -0
- package/dts/chart/point/Point.d.ts +201 -0
- package/dts/chart/point/Point.d.ts.map +1 -0
- package/dts/chart/point/index.d.ts +3 -0
- package/dts/chart/point/index.d.ts.map +1 -0
- package/dts/chart/scrubber/DefaultScrubberBeacon.d.ts +24 -0
- package/dts/chart/scrubber/DefaultScrubberBeacon.d.ts.map +1 -0
- package/dts/chart/scrubber/DefaultScrubberBeaconLabel.d.ts +12 -0
- package/dts/chart/scrubber/DefaultScrubberBeaconLabel.d.ts.map +1 -0
- package/dts/chart/scrubber/DefaultScrubberLabel.d.ts +10 -0
- package/dts/chart/scrubber/DefaultScrubberLabel.d.ts.map +1 -0
- package/dts/chart/scrubber/Scrubber.d.ts +290 -0
- package/dts/chart/scrubber/Scrubber.d.ts.map +1 -0
- package/dts/chart/scrubber/ScrubberBeaconGroup.d.ts +70 -0
- package/dts/chart/scrubber/ScrubberBeaconGroup.d.ts.map +1 -0
- package/dts/chart/scrubber/ScrubberBeaconLabelGroup.d.ts +32 -0
- package/dts/chart/scrubber/ScrubberBeaconLabelGroup.d.ts.map +1 -0
- package/dts/chart/scrubber/ScrubberProvider.d.ts +17 -0
- package/dts/chart/scrubber/ScrubberProvider.d.ts.map +1 -0
- package/dts/chart/scrubber/index.d.ts +5 -0
- package/dts/chart/scrubber/index.d.ts.map +1 -0
- package/dts/chart/text/ChartText.d.ts +117 -0
- package/dts/chart/text/ChartText.d.ts.map +1 -0
- package/dts/chart/text/ChartTextGroup.d.ts +61 -0
- package/dts/chart/text/ChartTextGroup.d.ts.map +1 -0
- package/dts/chart/text/index.d.ts +3 -0
- package/dts/chart/text/index.d.ts.map +1 -0
- package/dts/chart/utils/axis.d.ts +342 -0
- package/dts/chart/utils/axis.d.ts.map +1 -0
- package/dts/chart/utils/bar.d.ts +20 -0
- package/dts/chart/utils/bar.d.ts.map +1 -0
- package/dts/chart/utils/chart.d.ts +117 -0
- package/dts/chart/utils/chart.d.ts.map +1 -0
- package/dts/chart/utils/context.d.ts +101 -0
- package/dts/chart/utils/context.d.ts.map +1 -0
- package/dts/chart/utils/gradient.d.ts +104 -0
- package/dts/chart/utils/gradient.d.ts.map +1 -0
- package/dts/chart/utils/index.d.ts +12 -0
- package/dts/chart/utils/index.d.ts.map +1 -0
- package/dts/chart/utils/interpolate.d.ts +112 -0
- package/dts/chart/utils/interpolate.d.ts.map +1 -0
- package/dts/chart/utils/path.d.ts +130 -0
- package/dts/chart/utils/path.d.ts.map +1 -0
- package/dts/chart/utils/point.d.ts +104 -0
- package/dts/chart/utils/point.d.ts.map +1 -0
- package/dts/chart/utils/scale.d.ts +43 -0
- package/dts/chart/utils/scale.d.ts.map +1 -0
- package/dts/chart/utils/scrubber.d.ts +39 -0
- package/dts/chart/utils/scrubber.d.ts.map +1 -0
- package/dts/chart/utils/transition.d.ts +65 -0
- package/dts/chart/utils/transition.d.ts.map +1 -0
- package/dts/index.d.ts +1 -0
- package/dts/index.d.ts.map +1 -1
- package/dts/sparkline/Sparkline.d.ts +44 -9
- package/dts/sparkline/Sparkline.d.ts.map +1 -1
- package/dts/sparkline/SparklineArea.d.ts +4 -0
- package/dts/sparkline/SparklineArea.d.ts.map +1 -1
- package/dts/sparkline/SparklineAreaPattern.d.ts +5 -0
- package/dts/sparkline/SparklineAreaPattern.d.ts.map +1 -1
- package/dts/sparkline/SparklineGradient.d.ts +5 -0
- package/dts/sparkline/SparklineGradient.d.ts.map +1 -1
- package/dts/sparkline/generateSparklineWithId.d.ts +1 -0
- package/dts/sparkline/generateSparklineWithId.d.ts.map +1 -1
- package/dts/sparkline/sparkline-interactive/SparklineInteractive.d.ts +9 -0
- package/dts/sparkline/sparkline-interactive/SparklineInteractive.d.ts.map +1 -1
- package/dts/sparkline/sparkline-interactive/SparklineInteractiveAnimatedPath.d.ts +3 -0
- package/dts/sparkline/sparkline-interactive/SparklineInteractiveAnimatedPath.d.ts.map +1 -1
- package/dts/sparkline/sparkline-interactive/SparklineInteractivePaths.d.ts +2 -1
- package/dts/sparkline/sparkline-interactive/SparklineInteractivePaths.d.ts.map +1 -1
- package/esm/chart/CartesianChart.css +1 -0
- package/esm/chart/CartesianChart.js +313 -0
- package/esm/chart/ChartProvider.js +10 -0
- package/esm/chart/Path.js +95 -0
- package/esm/chart/PeriodSelector.css +1 -0
- package/esm/chart/PeriodSelector.js +112 -0
- package/esm/chart/area/Area.js +75 -0
- package/esm/chart/area/AreaChart.js +173 -0
- package/esm/chart/area/DottedArea.js +87 -0
- package/esm/chart/area/GradientArea.js +65 -0
- package/esm/chart/area/SolidArea.js +47 -0
- package/esm/chart/area/index.js +7 -0
- package/esm/chart/axis/Axis.js +25 -0
- package/esm/chart/axis/DefaultAxisTickLabel.js +15 -0
- package/esm/chart/axis/XAxis.css +2 -0
- package/esm/chart/axis/XAxis.js +219 -0
- package/esm/chart/axis/YAxis.css +2 -0
- package/esm/chart/axis/YAxis.js +214 -0
- package/esm/chart/axis/index.js +6 -0
- package/esm/chart/bar/Bar.js +61 -0
- package/esm/chart/bar/BarChart.js +130 -0
- package/esm/chart/bar/BarPlot.js +97 -0
- package/esm/chart/bar/BarStack.js +561 -0
- package/esm/chart/bar/BarStackGroup.js +86 -0
- package/esm/chart/bar/DefaultBar.js +61 -0
- package/esm/chart/bar/DefaultBarStack.js +58 -0
- package/esm/chart/bar/index.js +9 -0
- package/esm/chart/gradient/Gradient.js +104 -0
- package/esm/chart/gradient/index.js +1 -0
- package/esm/chart/index.js +15 -0
- package/esm/chart/line/DefaultReferenceLineLabel.js +81 -0
- package/esm/chart/line/DottedLine.js +59 -0
- package/esm/chart/line/Line.js +185 -0
- package/esm/chart/line/LineChart.js +132 -0
- package/esm/chart/line/ReferenceLine.js +140 -0
- package/esm/chart/line/SolidLine.js +55 -0
- package/esm/chart/line/index.js +8 -0
- package/esm/chart/point/DefaultPointLabel.js +44 -0
- package/esm/chart/point/Point.css +2 -0
- package/esm/chart/point/Point.js +180 -0
- package/esm/chart/point/index.js +2 -0
- package/esm/chart/scrubber/DefaultScrubberBeacon.js +155 -0
- package/esm/chart/scrubber/DefaultScrubberBeaconLabel.js +46 -0
- package/esm/chart/scrubber/DefaultScrubberLabel.js +30 -0
- package/esm/chart/scrubber/Scrubber.js +189 -0
- package/esm/chart/scrubber/ScrubberBeaconGroup.js +166 -0
- package/esm/chart/scrubber/ScrubberBeaconLabelGroup.js +186 -0
- package/esm/chart/scrubber/ScrubberProvider.js +228 -0
- package/esm/chart/scrubber/index.js +4 -0
- package/esm/chart/text/ChartText.js +230 -0
- package/esm/chart/text/ChartTextGroup.js +227 -0
- package/esm/chart/text/index.js +4 -0
- package/esm/chart/utils/axis.js +593 -0
- package/esm/chart/utils/bar.js +24 -0
- package/esm/chart/utils/chart.js +255 -0
- package/esm/chart/utils/context.js +15 -0
- package/esm/chart/utils/gradient.js +257 -0
- package/esm/chart/utils/index.js +13 -0
- package/esm/chart/utils/interpolate.js +644 -0
- package/esm/chart/utils/path.js +227 -0
- package/esm/chart/utils/point.js +187 -0
- package/esm/chart/utils/scale.js +48 -0
- package/esm/chart/utils/scrubber.js +132 -0
- package/esm/chart/utils/transition.js +111 -0
- package/esm/index.js +4 -1
- package/esm/sparkline/Sparkline.js +129 -15
- package/esm/sparkline/SparklineArea.js +7 -2
- package/esm/sparkline/SparklineAreaPattern.js +4 -2
- package/esm/sparkline/SparklineGradient.js +16 -58
- package/esm/sparkline/generateSparklineWithId.js +3 -2
- package/esm/sparkline/sparkline-interactive/SparklineInteractive.js +5 -1
- package/esm/sparkline/sparkline-interactive/SparklineInteractiveAnimatedPath.js +5 -2
- package/esm/sparkline/sparkline-interactive/SparklineInteractiveMarkerDates.js +1 -1
- package/esm/sparkline/sparkline-interactive/SparklineInteractivePaths.js +4 -0
- package/package.json +13 -9
|
@@ -0,0 +1,186 @@
|
|
|
1
|
+
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; }
|
|
2
|
+
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; }
|
|
3
|
+
function _defineProperty(e, r, t) { return (r = _toPropertyKey(r)) in e ? Object.defineProperty(e, r, { value: t, enumerable: !0, configurable: !0, writable: !0 }) : e[r] = t, e; }
|
|
4
|
+
function _toPropertyKey(t) { var i = _toPrimitive(t, "string"); return "symbol" == typeof i ? i : i + ""; }
|
|
5
|
+
function _toPrimitive(t, r) { if ("object" != typeof t || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || "default"); if ("object" != typeof i) return i; throw new TypeError("@@toPrimitive must return a primitive value."); } return ("string" === r ? String : Number)(t); }
|
|
6
|
+
import { memo, useCallback, useMemo, useState } from 'react';
|
|
7
|
+
import { useCartesianChartContext } from '../ChartProvider';
|
|
8
|
+
import { getPointOnScale, useScrubberContext } from '../utils';
|
|
9
|
+
import { calculateLabelYPositions, getLabelPosition } from '../utils/scrubber';
|
|
10
|
+
import { DefaultScrubberBeaconLabel } from './DefaultScrubberBeaconLabel';
|
|
11
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
12
|
+
const PositionedLabel = /*#__PURE__*/memo(_ref => {
|
|
13
|
+
let {
|
|
14
|
+
index,
|
|
15
|
+
positions,
|
|
16
|
+
position,
|
|
17
|
+
label,
|
|
18
|
+
color,
|
|
19
|
+
seriesId,
|
|
20
|
+
onDimensionsChange,
|
|
21
|
+
BeaconLabelComponent,
|
|
22
|
+
labelHorizontalOffset,
|
|
23
|
+
labelFont
|
|
24
|
+
} = _ref;
|
|
25
|
+
const pos = positions[index];
|
|
26
|
+
|
|
27
|
+
// Don't render if position is null (invalid data)
|
|
28
|
+
if (!pos) {
|
|
29
|
+
return null;
|
|
30
|
+
}
|
|
31
|
+
const x = pos.x;
|
|
32
|
+
const y = pos.y;
|
|
33
|
+
const dx = position === 'right' ? labelHorizontalOffset : -labelHorizontalOffset;
|
|
34
|
+
const horizontalAlignment = position === 'right' ? 'left' : 'right';
|
|
35
|
+
return /*#__PURE__*/_jsx(BeaconLabelComponent, {
|
|
36
|
+
color: color,
|
|
37
|
+
dx: dx,
|
|
38
|
+
font: labelFont,
|
|
39
|
+
horizontalAlignment: horizontalAlignment,
|
|
40
|
+
label: label,
|
|
41
|
+
onDimensionsChange: d => onDimensionsChange(seriesId, d),
|
|
42
|
+
seriesId: seriesId,
|
|
43
|
+
x: x,
|
|
44
|
+
y: y
|
|
45
|
+
});
|
|
46
|
+
});
|
|
47
|
+
export const ScrubberBeaconLabelGroup = /*#__PURE__*/memo(_ref2 => {
|
|
48
|
+
let {
|
|
49
|
+
labels,
|
|
50
|
+
labelMinGap = 4,
|
|
51
|
+
labelHorizontalOffset = 16,
|
|
52
|
+
labelFont,
|
|
53
|
+
BeaconLabelComponent = DefaultScrubberBeaconLabel
|
|
54
|
+
} = _ref2;
|
|
55
|
+
const {
|
|
56
|
+
getSeries,
|
|
57
|
+
getSeriesData,
|
|
58
|
+
getXScale,
|
|
59
|
+
getYScale,
|
|
60
|
+
getXAxis,
|
|
61
|
+
drawingArea,
|
|
62
|
+
dataLength
|
|
63
|
+
} = useCartesianChartContext();
|
|
64
|
+
const {
|
|
65
|
+
scrubberPosition
|
|
66
|
+
} = useScrubberContext();
|
|
67
|
+
const [labelDimensions, setLabelDimensions] = useState({});
|
|
68
|
+
const handleDimensionsChange = useCallback((seriesId, dimensions) => {
|
|
69
|
+
setLabelDimensions(prev => {
|
|
70
|
+
const existing = prev[seriesId];
|
|
71
|
+
if (existing && existing.width === dimensions.width && existing.height === dimensions.height) {
|
|
72
|
+
return prev;
|
|
73
|
+
}
|
|
74
|
+
return _objectSpread(_objectSpread({}, prev), {}, {
|
|
75
|
+
[seriesId]: dimensions
|
|
76
|
+
});
|
|
77
|
+
});
|
|
78
|
+
}, []);
|
|
79
|
+
const seriesInfo = useMemo(() => {
|
|
80
|
+
return labels.map(label => {
|
|
81
|
+
const series = getSeries(label.seriesId);
|
|
82
|
+
if (!series) return null;
|
|
83
|
+
const sourceData = getSeriesData(label.seriesId);
|
|
84
|
+
const yScale = getYScale(series.yAxisId);
|
|
85
|
+
return {
|
|
86
|
+
seriesId: label.seriesId,
|
|
87
|
+
sourceData,
|
|
88
|
+
yScale
|
|
89
|
+
};
|
|
90
|
+
}).filter(info => info !== null);
|
|
91
|
+
}, [labels, getSeries, getSeriesData, getYScale]);
|
|
92
|
+
const xScale = getXScale();
|
|
93
|
+
const xAxis = getXAxis();
|
|
94
|
+
const dataIndex = useMemo(() => {
|
|
95
|
+
return scrubberPosition !== null && scrubberPosition !== void 0 ? scrubberPosition : Math.max(0, dataLength - 1);
|
|
96
|
+
}, [scrubberPosition, dataLength]);
|
|
97
|
+
const dataX = useMemo(() => {
|
|
98
|
+
if (xAxis !== null && xAxis !== void 0 && xAxis.data && Array.isArray(xAxis.data) && xAxis.data[dataIndex] !== undefined) {
|
|
99
|
+
const dataValue = xAxis.data[dataIndex];
|
|
100
|
+
return typeof dataValue === 'string' ? dataIndex : dataValue;
|
|
101
|
+
}
|
|
102
|
+
return dataIndex;
|
|
103
|
+
}, [xAxis, dataIndex]);
|
|
104
|
+
const allLabelPositions = useMemo(() => {
|
|
105
|
+
if (!xScale || dataX === undefined) return [];
|
|
106
|
+
const sharedPixelX = getPointOnScale(dataX, xScale);
|
|
107
|
+
const desiredPositions = seriesInfo.map(info => {
|
|
108
|
+
let dataY;
|
|
109
|
+
if (info.yScale) {
|
|
110
|
+
if (info.sourceData && dataIndex !== undefined && dataIndex >= 0 && dataIndex < info.sourceData.length) {
|
|
111
|
+
const dataValue = info.sourceData[dataIndex];
|
|
112
|
+
if (Array.isArray(dataValue)) {
|
|
113
|
+
const validValues = dataValue.filter(val => val !== null);
|
|
114
|
+
if (validValues.length >= 1) {
|
|
115
|
+
dataY = validValues[validValues.length - 1];
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
if (dataY !== undefined && info.yScale) {
|
|
121
|
+
return {
|
|
122
|
+
seriesId: info.seriesId,
|
|
123
|
+
x: sharedPixelX,
|
|
124
|
+
desiredY: getPointOnScale(dataY, info.yScale)
|
|
125
|
+
};
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
// Return null for invalid data
|
|
129
|
+
return null;
|
|
130
|
+
});
|
|
131
|
+
const maxLabelHeight = Math.max(...Object.values(labelDimensions).map(dim => dim.height));
|
|
132
|
+
const maxLabelWidth = Math.max(...Object.values(labelDimensions).map(dim => dim.width));
|
|
133
|
+
|
|
134
|
+
// Only apply collision detection to valid positions
|
|
135
|
+
const validPositions = desiredPositions.filter(pos => pos !== null);
|
|
136
|
+
|
|
137
|
+
// Convert to LabelDimension format expected by utility
|
|
138
|
+
const dimensions = validPositions.map(pos => {
|
|
139
|
+
var _trackedDimensions$wi, _trackedDimensions$he;
|
|
140
|
+
const trackedDimensions = labelDimensions[pos.seriesId];
|
|
141
|
+
return {
|
|
142
|
+
seriesId: pos.seriesId,
|
|
143
|
+
width: (_trackedDimensions$wi = trackedDimensions === null || trackedDimensions === void 0 ? void 0 : trackedDimensions.width) !== null && _trackedDimensions$wi !== void 0 ? _trackedDimensions$wi : maxLabelWidth,
|
|
144
|
+
height: (_trackedDimensions$he = trackedDimensions === null || trackedDimensions === void 0 ? void 0 : trackedDimensions.height) !== null && _trackedDimensions$he !== void 0 ? _trackedDimensions$he : maxLabelHeight,
|
|
145
|
+
preferredX: pos.x,
|
|
146
|
+
preferredY: pos.desiredY
|
|
147
|
+
};
|
|
148
|
+
});
|
|
149
|
+
|
|
150
|
+
// Calculate Y positions with collision resolution for valid positions only
|
|
151
|
+
const yPositions = calculateLabelYPositions(dimensions, drawingArea, maxLabelHeight, labelMinGap);
|
|
152
|
+
|
|
153
|
+
// Return all positions (including null ones)
|
|
154
|
+
return desiredPositions.map(pos => {
|
|
155
|
+
var _yPositions$get;
|
|
156
|
+
if (!pos) return null;
|
|
157
|
+
return {
|
|
158
|
+
seriesId: pos.seriesId,
|
|
159
|
+
x: pos.x,
|
|
160
|
+
y: (_yPositions$get = yPositions.get(pos.seriesId)) !== null && _yPositions$get !== void 0 ? _yPositions$get : pos.desiredY
|
|
161
|
+
};
|
|
162
|
+
});
|
|
163
|
+
}, [seriesInfo, dataIndex, dataX, xScale, labelDimensions, drawingArea, labelMinGap]);
|
|
164
|
+
const currentPosition = useMemo(() => {
|
|
165
|
+
if (!xScale || dataX === undefined) return 'right';
|
|
166
|
+
const pixelX = getPointOnScale(dataX, xScale);
|
|
167
|
+
const maxWidth = Math.max(...Object.values(labelDimensions).map(dim => dim.width));
|
|
168
|
+
return getLabelPosition(pixelX, maxWidth, drawingArea, labelHorizontalOffset);
|
|
169
|
+
}, [dataX, xScale, labelDimensions, drawingArea, labelHorizontalOffset]);
|
|
170
|
+
return seriesInfo.map((info, index) => {
|
|
171
|
+
const labelInfo = labels.find(label => label.seriesId === info.seriesId);
|
|
172
|
+
if (!labelInfo) return;
|
|
173
|
+
return /*#__PURE__*/_jsx(PositionedLabel, {
|
|
174
|
+
BeaconLabelComponent: BeaconLabelComponent,
|
|
175
|
+
color: labelInfo.color,
|
|
176
|
+
index: index,
|
|
177
|
+
label: labelInfo.label,
|
|
178
|
+
labelFont: labelFont,
|
|
179
|
+
labelHorizontalOffset: labelHorizontalOffset,
|
|
180
|
+
onDimensionsChange: handleDimensionsChange,
|
|
181
|
+
position: currentPosition,
|
|
182
|
+
positions: allLabelPositions,
|
|
183
|
+
seriesId: info.seriesId
|
|
184
|
+
}, info.seriesId);
|
|
185
|
+
});
|
|
186
|
+
});
|
|
@@ -0,0 +1,228 @@
|
|
|
1
|
+
import React, { useCallback, useEffect, useMemo, useState } from 'react';
|
|
2
|
+
import { useCartesianChartContext } from '../ChartProvider';
|
|
3
|
+
import { isCategoricalScale, ScrubberContext } from '../utils';
|
|
4
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
5
|
+
/**
|
|
6
|
+
* A component which encapsulates the ScrubberContext.
|
|
7
|
+
* It depends on a ChartContext in order to provide accurate mouse tracking.
|
|
8
|
+
*/
|
|
9
|
+
export const ScrubberProvider = _ref => {
|
|
10
|
+
let {
|
|
11
|
+
children,
|
|
12
|
+
svgRef,
|
|
13
|
+
enableScrubbing,
|
|
14
|
+
onScrubberPositionChange
|
|
15
|
+
} = _ref;
|
|
16
|
+
const chartContext = useCartesianChartContext();
|
|
17
|
+
if (!chartContext) {
|
|
18
|
+
throw new Error('ScrubberProvider must be used within a ChartContext');
|
|
19
|
+
}
|
|
20
|
+
const {
|
|
21
|
+
getXScale,
|
|
22
|
+
getXAxis,
|
|
23
|
+
series
|
|
24
|
+
} = chartContext;
|
|
25
|
+
const [scrubberPosition, setScrubberPosition] = useState(undefined);
|
|
26
|
+
const getDataIndexFromX = useCallback(mouseX => {
|
|
27
|
+
const xScale = getXScale();
|
|
28
|
+
const xAxis = getXAxis();
|
|
29
|
+
if (!xScale || !xAxis) return 0;
|
|
30
|
+
if (isCategoricalScale(xScale)) {
|
|
31
|
+
var _ref2, _xScale$domain, _xScale$domain2, _xScale$bandwidth, _xScale$bandwidth2;
|
|
32
|
+
const categories = (_ref2 = (_xScale$domain = (_xScale$domain2 = xScale.domain) === null || _xScale$domain2 === void 0 ? void 0 : _xScale$domain2.call(xScale)) !== null && _xScale$domain !== void 0 ? _xScale$domain : xAxis.data) !== null && _ref2 !== void 0 ? _ref2 : [];
|
|
33
|
+
const bandwidth = (_xScale$bandwidth = (_xScale$bandwidth2 = xScale.bandwidth) === null || _xScale$bandwidth2 === void 0 ? void 0 : _xScale$bandwidth2.call(xScale)) !== null && _xScale$bandwidth !== void 0 ? _xScale$bandwidth : 0;
|
|
34
|
+
let closestIndex = 0;
|
|
35
|
+
let closestDistance = Infinity;
|
|
36
|
+
for (let i = 0; i < categories.length; i++) {
|
|
37
|
+
const xPos = xScale(i);
|
|
38
|
+
if (xPos !== undefined) {
|
|
39
|
+
const distance = Math.abs(mouseX - (xPos + bandwidth / 2));
|
|
40
|
+
if (distance < closestDistance) {
|
|
41
|
+
closestDistance = distance;
|
|
42
|
+
closestIndex = i;
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
return closestIndex;
|
|
47
|
+
} else {
|
|
48
|
+
// For numeric scales with axis data, find the nearest data point
|
|
49
|
+
const axisData = xAxis.data;
|
|
50
|
+
if (axisData && Array.isArray(axisData) && typeof axisData[0] === 'number') {
|
|
51
|
+
// We have numeric axis data - find the closest data point
|
|
52
|
+
const numericData = axisData;
|
|
53
|
+
let closestIndex = 0;
|
|
54
|
+
let closestDistance = Infinity;
|
|
55
|
+
for (let i = 0; i < numericData.length; i++) {
|
|
56
|
+
const xValue = numericData[i];
|
|
57
|
+
const xPos = xScale(xValue);
|
|
58
|
+
if (xPos !== undefined) {
|
|
59
|
+
const distance = Math.abs(mouseX - xPos);
|
|
60
|
+
if (distance < closestDistance) {
|
|
61
|
+
closestDistance = distance;
|
|
62
|
+
closestIndex = i;
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
return closestIndex;
|
|
67
|
+
} else {
|
|
68
|
+
var _domain$min, _domain$max;
|
|
69
|
+
const xValue = xScale.invert(mouseX);
|
|
70
|
+
const dataIndex = Math.round(xValue);
|
|
71
|
+
const domain = xAxis.domain;
|
|
72
|
+
return Math.max((_domain$min = domain.min) !== null && _domain$min !== void 0 ? _domain$min : 0, Math.min(dataIndex, (_domain$max = domain.max) !== null && _domain$max !== void 0 ? _domain$max : 0));
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
}, [getXScale, getXAxis]);
|
|
76
|
+
const handlePointerMove = useCallback((clientX, target) => {
|
|
77
|
+
if (!enableScrubbing || !series || series.length === 0) return;
|
|
78
|
+
const rect = target.getBoundingClientRect();
|
|
79
|
+
const x = clientX - rect.left;
|
|
80
|
+
const dataIndex = getDataIndexFromX(x);
|
|
81
|
+
if (dataIndex !== scrubberPosition) {
|
|
82
|
+
setScrubberPosition(dataIndex);
|
|
83
|
+
onScrubberPositionChange === null || onScrubberPositionChange === void 0 || onScrubberPositionChange(dataIndex);
|
|
84
|
+
}
|
|
85
|
+
}, [enableScrubbing, series, getDataIndexFromX, scrubberPosition, onScrubberPositionChange]);
|
|
86
|
+
const handleMouseMove = useCallback(event => {
|
|
87
|
+
const target = event.currentTarget;
|
|
88
|
+
handlePointerMove(event.clientX, target);
|
|
89
|
+
}, [handlePointerMove]);
|
|
90
|
+
const handleTouchMove = useCallback(event => {
|
|
91
|
+
if (!event.touches.length) return;
|
|
92
|
+
// Prevent scrolling while scrubbing
|
|
93
|
+
event.preventDefault();
|
|
94
|
+
const touch = event.touches[0];
|
|
95
|
+
const target = event.currentTarget;
|
|
96
|
+
handlePointerMove(touch.clientX, target);
|
|
97
|
+
}, [handlePointerMove]);
|
|
98
|
+
const handleTouchStart = useCallback(event => {
|
|
99
|
+
if (!enableScrubbing || !event.touches.length) return;
|
|
100
|
+
// Handle initial touch
|
|
101
|
+
const touch = event.touches[0];
|
|
102
|
+
const target = event.currentTarget;
|
|
103
|
+
handlePointerMove(touch.clientX, target);
|
|
104
|
+
}, [enableScrubbing, handlePointerMove]);
|
|
105
|
+
const handlePointerLeave = useCallback(() => {
|
|
106
|
+
if (!enableScrubbing) return;
|
|
107
|
+
setScrubberPosition(undefined);
|
|
108
|
+
onScrubberPositionChange === null || onScrubberPositionChange === void 0 || onScrubberPositionChange(undefined);
|
|
109
|
+
}, [enableScrubbing, onScrubberPositionChange]);
|
|
110
|
+
const handleMouseLeave = handlePointerLeave;
|
|
111
|
+
const handleTouchEnd = handlePointerLeave;
|
|
112
|
+
const handleKeyDown = useCallback(event => {
|
|
113
|
+
if (!enableScrubbing) return;
|
|
114
|
+
const xScale = getXScale();
|
|
115
|
+
const xAxis = getXAxis();
|
|
116
|
+
if (!xScale || !xAxis) return;
|
|
117
|
+
const isBand = isCategoricalScale(xScale);
|
|
118
|
+
|
|
119
|
+
// Determine the actual data indices we can navigate to
|
|
120
|
+
let minIndex;
|
|
121
|
+
let maxIndex;
|
|
122
|
+
let dataPoints;
|
|
123
|
+
if (isBand) {
|
|
124
|
+
var _ref3, _xScale$domain3, _xScale$domain4;
|
|
125
|
+
// For categorical scales, use the categories
|
|
126
|
+
const categories = (_ref3 = (_xScale$domain3 = (_xScale$domain4 = xScale.domain) === null || _xScale$domain4 === void 0 ? void 0 : _xScale$domain4.call(xScale)) !== null && _xScale$domain3 !== void 0 ? _xScale$domain3 : xAxis.data) !== null && _ref3 !== void 0 ? _ref3 : [];
|
|
127
|
+
minIndex = 0;
|
|
128
|
+
maxIndex = Math.max(0, categories.length - 1);
|
|
129
|
+
dataPoints = categories.length;
|
|
130
|
+
} else {
|
|
131
|
+
// For numeric scales, check if we have specific data points
|
|
132
|
+
const axisData = xAxis.data;
|
|
133
|
+
if (axisData && Array.isArray(axisData)) {
|
|
134
|
+
// We have specific data points - use their indices
|
|
135
|
+
minIndex = 0;
|
|
136
|
+
maxIndex = Math.max(0, axisData.length - 1);
|
|
137
|
+
dataPoints = axisData.length;
|
|
138
|
+
} else {
|
|
139
|
+
var _domain$min2, _domain$max2;
|
|
140
|
+
// Fall back to domain-based navigation for continuous scales without specific data
|
|
141
|
+
const domain = xAxis.domain;
|
|
142
|
+
minIndex = (_domain$min2 = domain.min) !== null && _domain$min2 !== void 0 ? _domain$min2 : 0;
|
|
143
|
+
maxIndex = (_domain$max2 = domain.max) !== null && _domain$max2 !== void 0 ? _domain$max2 : 0;
|
|
144
|
+
dataPoints = maxIndex - minIndex + 1;
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
const currentIndex = scrubberPosition !== null && scrubberPosition !== void 0 ? scrubberPosition : minIndex;
|
|
148
|
+
const dataRange = maxIndex - minIndex;
|
|
149
|
+
|
|
150
|
+
// Multi-step jump when shift is held (10% of data range, minimum 1, maximum 10)
|
|
151
|
+
const multiSkip = event.shiftKey;
|
|
152
|
+
const stepSize = multiSkip ? Math.min(10, Math.max(1, Math.floor(dataRange * 0.1))) : 1;
|
|
153
|
+
let newIndex;
|
|
154
|
+
switch (event.key) {
|
|
155
|
+
case 'ArrowLeft':
|
|
156
|
+
event.preventDefault();
|
|
157
|
+
newIndex = Math.max(minIndex, currentIndex - stepSize);
|
|
158
|
+
break;
|
|
159
|
+
case 'ArrowRight':
|
|
160
|
+
event.preventDefault();
|
|
161
|
+
newIndex = Math.min(maxIndex, currentIndex + stepSize);
|
|
162
|
+
break;
|
|
163
|
+
case 'Home':
|
|
164
|
+
event.preventDefault();
|
|
165
|
+
newIndex = minIndex;
|
|
166
|
+
break;
|
|
167
|
+
case 'End':
|
|
168
|
+
event.preventDefault();
|
|
169
|
+
newIndex = maxIndex;
|
|
170
|
+
break;
|
|
171
|
+
case 'Escape':
|
|
172
|
+
event.preventDefault();
|
|
173
|
+
newIndex = undefined; // Clear highlighting
|
|
174
|
+
break;
|
|
175
|
+
default:
|
|
176
|
+
return;
|
|
177
|
+
// Don't handle other keys
|
|
178
|
+
}
|
|
179
|
+
if (newIndex !== scrubberPosition) {
|
|
180
|
+
setScrubberPosition(newIndex);
|
|
181
|
+
onScrubberPositionChange === null || onScrubberPositionChange === void 0 || onScrubberPositionChange(newIndex);
|
|
182
|
+
}
|
|
183
|
+
}, [enableScrubbing, getXScale, getXAxis, scrubberPosition, onScrubberPositionChange]);
|
|
184
|
+
const handleBlur = useCallback(() => {
|
|
185
|
+
if (!enableScrubbing || scrubberPosition === undefined) return;
|
|
186
|
+
setScrubberPosition(undefined);
|
|
187
|
+
onScrubberPositionChange === null || onScrubberPositionChange === void 0 || onScrubberPositionChange(undefined);
|
|
188
|
+
}, [enableScrubbing, onScrubberPositionChange, scrubberPosition]);
|
|
189
|
+
|
|
190
|
+
// Attach event listeners to SVG element
|
|
191
|
+
useEffect(() => {
|
|
192
|
+
if (!(svgRef !== null && svgRef !== void 0 && svgRef.current) || !enableScrubbing) return;
|
|
193
|
+
const svg = svgRef.current;
|
|
194
|
+
|
|
195
|
+
// Add event listeners
|
|
196
|
+
svg.addEventListener('mousemove', handleMouseMove);
|
|
197
|
+
svg.addEventListener('mouseleave', handleMouseLeave);
|
|
198
|
+
svg.addEventListener('touchstart', handleTouchStart, {
|
|
199
|
+
passive: false
|
|
200
|
+
});
|
|
201
|
+
svg.addEventListener('touchmove', handleTouchMove, {
|
|
202
|
+
passive: false
|
|
203
|
+
});
|
|
204
|
+
svg.addEventListener('touchend', handleTouchEnd);
|
|
205
|
+
svg.addEventListener('touchcancel', handleTouchEnd);
|
|
206
|
+
svg.addEventListener('keydown', handleKeyDown);
|
|
207
|
+
svg.addEventListener('blur', handleBlur);
|
|
208
|
+
return () => {
|
|
209
|
+
svg.removeEventListener('mousemove', handleMouseMove);
|
|
210
|
+
svg.removeEventListener('mouseleave', handleMouseLeave);
|
|
211
|
+
svg.removeEventListener('touchstart', handleTouchStart);
|
|
212
|
+
svg.removeEventListener('touchmove', handleTouchMove);
|
|
213
|
+
svg.removeEventListener('touchend', handleTouchEnd);
|
|
214
|
+
svg.removeEventListener('touchcancel', handleTouchEnd);
|
|
215
|
+
svg.removeEventListener('keydown', handleKeyDown);
|
|
216
|
+
svg.removeEventListener('blur', handleBlur);
|
|
217
|
+
};
|
|
218
|
+
}, [svgRef, enableScrubbing, handleMouseMove, handleMouseLeave, handleTouchStart, handleTouchMove, handleTouchEnd, handleKeyDown, handleBlur]);
|
|
219
|
+
const contextValue = useMemo(() => ({
|
|
220
|
+
enableScrubbing: !!enableScrubbing,
|
|
221
|
+
scrubberPosition,
|
|
222
|
+
onScrubberPositionChange: setScrubberPosition
|
|
223
|
+
}), [enableScrubbing, scrubberPosition]);
|
|
224
|
+
return /*#__PURE__*/_jsx(ScrubberContext.Provider, {
|
|
225
|
+
value: contextValue,
|
|
226
|
+
children: children
|
|
227
|
+
});
|
|
228
|
+
};
|
|
@@ -0,0 +1,230 @@
|
|
|
1
|
+
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; }
|
|
2
|
+
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; }
|
|
3
|
+
function _defineProperty(e, r, t) { return (r = _toPropertyKey(r)) in e ? Object.defineProperty(e, r, { value: t, enumerable: !0, configurable: !0, writable: !0 }) : e[r] = t, e; }
|
|
4
|
+
function _toPropertyKey(t) { var i = _toPrimitive(t, "string"); return "symbol" == typeof i ? i : i + ""; }
|
|
5
|
+
function _toPrimitive(t, r) { if ("object" != typeof t || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || "default"); if ("object" != typeof i) return i; throw new TypeError("@@toPrimitive must return a primitive value."); } return ("string" === r ? String : Number)(t); }
|
|
6
|
+
import React, { memo, useEffect, useMemo, useRef, useState } from 'react';
|
|
7
|
+
import { cx } from '@coinbase/cds-web';
|
|
8
|
+
import { Box } from '@coinbase/cds-web/layout';
|
|
9
|
+
import { Text } from '@coinbase/cds-web/typography';
|
|
10
|
+
import { m as motion } from 'framer-motion';
|
|
11
|
+
import { useCartesianChartContext } from '../ChartProvider';
|
|
12
|
+
import { getChartInset } from '../utils';
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* The supported content types for ChartText.
|
|
16
|
+
*/
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* Horizontal alignment options for chart text.
|
|
20
|
+
*/
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
* Vertical alignment options for chart text.
|
|
24
|
+
*/
|
|
25
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
26
|
+
/**
|
|
27
|
+
* Get text anchor based on horizontal alignment.
|
|
28
|
+
*/
|
|
29
|
+
const getTextAnchor = alignment => {
|
|
30
|
+
switch (alignment) {
|
|
31
|
+
case 'left':
|
|
32
|
+
return 'start';
|
|
33
|
+
case 'center':
|
|
34
|
+
return 'middle';
|
|
35
|
+
case 'right':
|
|
36
|
+
return 'end';
|
|
37
|
+
}
|
|
38
|
+
};
|
|
39
|
+
|
|
40
|
+
/**
|
|
41
|
+
* Get dominant baseline based on vertical alignment.
|
|
42
|
+
*/
|
|
43
|
+
const getDominantBaseline = alignment => {
|
|
44
|
+
switch (alignment) {
|
|
45
|
+
case 'top':
|
|
46
|
+
return 'hanging';
|
|
47
|
+
case 'middle':
|
|
48
|
+
return 'central';
|
|
49
|
+
case 'bottom':
|
|
50
|
+
return 'ideographic';
|
|
51
|
+
}
|
|
52
|
+
};
|
|
53
|
+
export const ChartText = /*#__PURE__*/memo(_ref => {
|
|
54
|
+
let {
|
|
55
|
+
children,
|
|
56
|
+
x,
|
|
57
|
+
y,
|
|
58
|
+
horizontalAlignment = 'center',
|
|
59
|
+
verticalAlignment = 'middle',
|
|
60
|
+
dx,
|
|
61
|
+
dy,
|
|
62
|
+
disableRepositioning,
|
|
63
|
+
bounds,
|
|
64
|
+
opacity,
|
|
65
|
+
testID,
|
|
66
|
+
font = 'label2',
|
|
67
|
+
fontFamily,
|
|
68
|
+
fontSize,
|
|
69
|
+
fontWeight,
|
|
70
|
+
elevated,
|
|
71
|
+
color = 'var(--color-fgMuted)',
|
|
72
|
+
background = elevated ? 'var(--color-bg)' : 'transparent',
|
|
73
|
+
borderRadius,
|
|
74
|
+
inset: insetInput,
|
|
75
|
+
onDimensionsChange,
|
|
76
|
+
style,
|
|
77
|
+
styles,
|
|
78
|
+
className,
|
|
79
|
+
classNames
|
|
80
|
+
} = _ref;
|
|
81
|
+
const {
|
|
82
|
+
animate,
|
|
83
|
+
width: chartWidth,
|
|
84
|
+
height: chartHeight
|
|
85
|
+
} = useCartesianChartContext();
|
|
86
|
+
const fullChartBounds = useMemo(() => ({
|
|
87
|
+
x: 0,
|
|
88
|
+
y: 0,
|
|
89
|
+
width: chartWidth,
|
|
90
|
+
height: chartHeight
|
|
91
|
+
}), [chartWidth, chartHeight]);
|
|
92
|
+
const textRef = useRef(null);
|
|
93
|
+
const [textBBox, setTextBBox] = useState(null);
|
|
94
|
+
const isDimensionsReady = disableRepositioning || textRef.current !== null;
|
|
95
|
+
const backgroundRectDimensions = useMemo(() => {
|
|
96
|
+
if (!textBBox) {
|
|
97
|
+
return null;
|
|
98
|
+
}
|
|
99
|
+
const inset = getChartInset(insetInput);
|
|
100
|
+
return {
|
|
101
|
+
x: textBBox.x - inset.left,
|
|
102
|
+
y: textBBox.y - inset.top,
|
|
103
|
+
width: textBBox.width + inset.left + inset.right,
|
|
104
|
+
height: textBBox.height + inset.top + inset.bottom
|
|
105
|
+
};
|
|
106
|
+
}, [textBBox, insetInput]);
|
|
107
|
+
const overflowAmount = useMemo(() => {
|
|
108
|
+
if (disableRepositioning) {
|
|
109
|
+
return {
|
|
110
|
+
x: 0,
|
|
111
|
+
y: 0
|
|
112
|
+
};
|
|
113
|
+
}
|
|
114
|
+
const parentBounds = bounds !== null && bounds !== void 0 ? bounds : fullChartBounds;
|
|
115
|
+
if (!backgroundRectDimensions || !parentBounds || parentBounds.width <= 0 || parentBounds.height <= 0) {
|
|
116
|
+
return {
|
|
117
|
+
x: 0,
|
|
118
|
+
y: 0
|
|
119
|
+
};
|
|
120
|
+
}
|
|
121
|
+
let x = 0;
|
|
122
|
+
let y = 0;
|
|
123
|
+
if (backgroundRectDimensions.x < parentBounds.x) {
|
|
124
|
+
x = parentBounds.x - backgroundRectDimensions.x; // positive = shift right
|
|
125
|
+
} else if (backgroundRectDimensions.x + backgroundRectDimensions.width > parentBounds.x + parentBounds.width) {
|
|
126
|
+
x = parentBounds.x + parentBounds.width - (backgroundRectDimensions.x + backgroundRectDimensions.width); // negative = shift left
|
|
127
|
+
}
|
|
128
|
+
if (backgroundRectDimensions.y < parentBounds.y) {
|
|
129
|
+
y = parentBounds.y - backgroundRectDimensions.y; // positive = shift down
|
|
130
|
+
} else if (backgroundRectDimensions.y + backgroundRectDimensions.height > parentBounds.y + parentBounds.height) {
|
|
131
|
+
y = parentBounds.y + parentBounds.height - (backgroundRectDimensions.y + backgroundRectDimensions.height); // negative = shift up
|
|
132
|
+
}
|
|
133
|
+
return {
|
|
134
|
+
x,
|
|
135
|
+
y
|
|
136
|
+
};
|
|
137
|
+
}, [backgroundRectDimensions, fullChartBounds, bounds, disableRepositioning]);
|
|
138
|
+
|
|
139
|
+
// Compose the final reported rect including any overflow translation applied
|
|
140
|
+
const reportedRect = useMemo(() => {
|
|
141
|
+
if (!backgroundRectDimensions) return null;
|
|
142
|
+
return {
|
|
143
|
+
x: backgroundRectDimensions.x + overflowAmount.x,
|
|
144
|
+
y: backgroundRectDimensions.y + overflowAmount.y,
|
|
145
|
+
width: backgroundRectDimensions.width,
|
|
146
|
+
height: backgroundRectDimensions.height
|
|
147
|
+
};
|
|
148
|
+
}, [backgroundRectDimensions, overflowAmount.x, overflowAmount.y]);
|
|
149
|
+
useEffect(() => {
|
|
150
|
+
if (onDimensionsChange && reportedRect !== null) {
|
|
151
|
+
onDimensionsChange(reportedRect);
|
|
152
|
+
}
|
|
153
|
+
}, [reportedRect, onDimensionsChange]);
|
|
154
|
+
useEffect(() => {
|
|
155
|
+
if (textRef.current) {
|
|
156
|
+
const observer = new ResizeObserver(entries => {
|
|
157
|
+
for (const entry of entries) {
|
|
158
|
+
setTextBBox(entry.target.getBBox());
|
|
159
|
+
}
|
|
160
|
+
});
|
|
161
|
+
observer.observe(textRef.current);
|
|
162
|
+
|
|
163
|
+
// Cleanup function
|
|
164
|
+
return () => {
|
|
165
|
+
observer.disconnect();
|
|
166
|
+
};
|
|
167
|
+
}
|
|
168
|
+
}, []);
|
|
169
|
+
const textAnchor = useMemo(() => getTextAnchor(horizontalAlignment), [horizontalAlignment]);
|
|
170
|
+
const dominantBaseline = useMemo(() => getDominantBaseline(verticalAlignment), [verticalAlignment]);
|
|
171
|
+
|
|
172
|
+
// forces state update the bounding box when any properties that can affect the bounding box change
|
|
173
|
+
useEffect(() => {
|
|
174
|
+
if (textRef.current) {
|
|
175
|
+
setTextBBox(textRef.current.getBBox());
|
|
176
|
+
}
|
|
177
|
+
}, [textAnchor, dominantBaseline, dx, dy, x, y]);
|
|
178
|
+
const containerStyle = useMemo(() => _objectSpread(_objectSpread(_objectSpread({}, style), styles === null || styles === void 0 ? void 0 : styles.root), {}, {
|
|
179
|
+
transform: "translate(".concat(overflowAmount.x, "px, ").concat(overflowAmount.y, "px)")
|
|
180
|
+
}), [overflowAmount.x, overflowAmount.y, style, styles === null || styles === void 0 ? void 0 : styles.root]);
|
|
181
|
+
return /*#__PURE__*/_jsx(Box, {
|
|
182
|
+
"aria-hidden": "true",
|
|
183
|
+
as: "g",
|
|
184
|
+
className: cx(className, classNames === null || classNames === void 0 ? void 0 : classNames.root),
|
|
185
|
+
opacity: opacity,
|
|
186
|
+
style: containerStyle,
|
|
187
|
+
testID: testID,
|
|
188
|
+
children: /*#__PURE__*/_jsxs(motion.g, {
|
|
189
|
+
animate: {
|
|
190
|
+
opacity: isDimensionsReady ? 1 : 0
|
|
191
|
+
},
|
|
192
|
+
transition: animate ? {
|
|
193
|
+
duration: 0.2,
|
|
194
|
+
ease: 'easeOut'
|
|
195
|
+
} : undefined,
|
|
196
|
+
children: [/*#__PURE__*/_jsx(Box, {
|
|
197
|
+
as: "rect",
|
|
198
|
+
className: classNames === null || classNames === void 0 ? void 0 : classNames.backgroundRect,
|
|
199
|
+
fill: background,
|
|
200
|
+
filter: elevated ? 'drop-shadow(var(--shadow-elevation1))' : undefined,
|
|
201
|
+
height: backgroundRectDimensions === null || backgroundRectDimensions === void 0 ? void 0 : backgroundRectDimensions.height,
|
|
202
|
+
rx: borderRadius,
|
|
203
|
+
ry: borderRadius,
|
|
204
|
+
style: styles === null || styles === void 0 ? void 0 : styles.backgroundRect,
|
|
205
|
+
width: backgroundRectDimensions === null || backgroundRectDimensions === void 0 ? void 0 : backgroundRectDimensions.width,
|
|
206
|
+
x: backgroundRectDimensions === null || backgroundRectDimensions === void 0 ? void 0 : backgroundRectDimensions.x,
|
|
207
|
+
y: backgroundRectDimensions === null || backgroundRectDimensions === void 0 ? void 0 : backgroundRectDimensions.y
|
|
208
|
+
}), /*#__PURE__*/_jsx(Text, {
|
|
209
|
+
ref: textRef,
|
|
210
|
+
as: "text",
|
|
211
|
+
className: classNames === null || classNames === void 0 ? void 0 : classNames.text,
|
|
212
|
+
dominantBaseline: dominantBaseline,
|
|
213
|
+
dx: dx,
|
|
214
|
+
dy: dy,
|
|
215
|
+
fill: color,
|
|
216
|
+
font: font,
|
|
217
|
+
fontFamily: fontFamily,
|
|
218
|
+
fontSize: fontSize,
|
|
219
|
+
fontWeight: fontWeight,
|
|
220
|
+
style: styles === null || styles === void 0 ? void 0 : styles.text,
|
|
221
|
+
textAnchor: textAnchor,
|
|
222
|
+
x: x,
|
|
223
|
+
y: y,
|
|
224
|
+
children: /*#__PURE__*/_jsx("tspan", {
|
|
225
|
+
children: children
|
|
226
|
+
})
|
|
227
|
+
})]
|
|
228
|
+
})
|
|
229
|
+
});
|
|
230
|
+
});
|