@coinbase/cds-web-visualization 0.0.0 → 3.4.0-beta.1
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 +26 -0
- package/README.md +3 -0
- package/dts/chart/CartesianChart.d.ts +36 -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 +34 -0
- package/dts/chart/Path.d.ts.map +1 -0
- package/dts/chart/PeriodSelector.d.ts +61 -0
- package/dts/chart/PeriodSelector.d.ts.map +1 -0
- package/dts/chart/Point.d.ts +153 -0
- package/dts/chart/Point.d.ts.map +1 -0
- package/dts/chart/area/Area.d.ts +48 -0
- package/dts/chart/area/Area.d.ts.map +1 -0
- package/dts/chart/area/AreaChart.d.ts +52 -0
- package/dts/chart/area/AreaChart.d.ts.map +1 -0
- package/dts/chart/area/DottedArea.d.ts +68 -0
- package/dts/chart/area/DottedArea.d.ts.map +1 -0
- package/dts/chart/area/GradientArea.d.ts +30 -0
- package/dts/chart/area/GradientArea.d.ts.map +1 -0
- package/dts/chart/area/SolidArea.d.ts +8 -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 +208 -0
- package/dts/chart/axis/Axis.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 +4 -0
- package/dts/chart/axis/index.d.ts.map +1 -0
- package/dts/chart/bar/Bar.d.ts +91 -0
- package/dts/chart/bar/Bar.d.ts.map +1 -0
- package/dts/chart/bar/BarChart.d.ts +53 -0
- package/dts/chart/bar/BarChart.d.ts.map +1 -0
- package/dts/chart/bar/BarPlot.d.ts +29 -0
- package/dts/chart/bar/BarPlot.d.ts.map +1 -0
- package/dts/chart/bar/BarStack.d.ts +111 -0
- package/dts/chart/bar/BarStack.d.ts.map +1 -0
- package/dts/chart/bar/BarStackGroup.d.ts +35 -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/index.d.ts +13 -0
- package/dts/chart/index.d.ts.map +1 -0
- package/dts/chart/line/DottedLine.d.ts +14 -0
- package/dts/chart/line/DottedLine.d.ts.map +1 -0
- package/dts/chart/line/GradientLine.d.ts +42 -0
- package/dts/chart/line/GradientLine.d.ts.map +1 -0
- package/dts/chart/line/Line.d.ts +80 -0
- package/dts/chart/line/Line.d.ts.map +1 -0
- package/dts/chart/line/LineChart.d.ts +59 -0
- package/dts/chart/line/LineChart.d.ts.map +1 -0
- package/dts/chart/line/ReferenceLine.d.ts +131 -0
- package/dts/chart/line/ReferenceLine.d.ts.map +1 -0
- package/dts/chart/line/SolidLine.d.ts +14 -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/scrubber/Scrubber.d.ts +149 -0
- package/dts/chart/scrubber/Scrubber.d.ts.map +1 -0
- package/dts/chart/scrubber/ScrubberBeacon.d.ts +93 -0
- package/dts/chart/scrubber/ScrubberBeacon.d.ts.map +1 -0
- package/dts/chart/scrubber/ScrubberBeaconLabel.d.ts +7 -0
- package/dts/chart/scrubber/ScrubberBeaconLabel.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 +2 -0
- package/dts/chart/scrubber/index.d.ts.map +1 -0
- package/dts/chart/text/ChartText.d.ts +114 -0
- package/dts/chart/text/ChartText.d.ts.map +1 -0
- package/dts/chart/text/SmartChartTextGroup.d.ts +55 -0
- package/dts/chart/text/SmartChartTextGroup.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 +97 -0
- package/dts/chart/utils/chart.d.ts.map +1 -0
- package/dts/chart/utils/context.d.ts +95 -0
- package/dts/chart/utils/context.d.ts.map +1 -0
- package/dts/chart/utils/index.d.ts +8 -0
- package/dts/chart/utils/index.d.ts.map +1 -0
- package/dts/chart/utils/path.d.ts +107 -0
- package/dts/chart/utils/path.d.ts.map +1 -0
- package/dts/chart/utils/point.d.ts +75 -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/index.d.ts +3 -0
- package/dts/index.d.ts.map +1 -0
- package/dts/sparkline/Counter.d.ts +8 -0
- package/dts/sparkline/Counter.d.ts.map +1 -0
- package/dts/sparkline/Sparkline.d.ts +67 -0
- package/dts/sparkline/Sparkline.d.ts.map +1 -0
- package/dts/sparkline/SparklineArea.d.ts +15 -0
- package/dts/sparkline/SparklineArea.d.ts.map +1 -0
- package/dts/sparkline/SparklineAreaPattern.d.ts +14 -0
- package/dts/sparkline/SparklineAreaPattern.d.ts.map +1 -0
- package/dts/sparkline/SparklineGradient.d.ts +23 -0
- package/dts/sparkline/SparklineGradient.d.ts.map +1 -0
- package/dts/sparkline/SparklinePath.d.ts +12 -0
- package/dts/sparkline/SparklinePath.d.ts.map +1 -0
- package/dts/sparkline/__figma__/Sparkline.figma.d.ts +2 -0
- package/dts/sparkline/__figma__/Sparkline.figma.d.ts.map +1 -0
- package/dts/sparkline/generateSparklineWithId.d.ts +11 -0
- package/dts/sparkline/generateSparklineWithId.d.ts.map +1 -0
- package/dts/sparkline/index.d.ts +6 -0
- package/dts/sparkline/index.d.ts.map +1 -0
- package/dts/sparkline/sparkline-interactive/InnerSparklineInteractiveProvider.d.ts +13 -0
- package/dts/sparkline/sparkline-interactive/InnerSparklineInteractiveProvider.d.ts.map +1 -0
- package/dts/sparkline/sparkline-interactive/SparklineInteractive.d.ts +199 -0
- package/dts/sparkline/sparkline-interactive/SparklineInteractive.d.ts.map +1 -0
- package/dts/sparkline/sparkline-interactive/SparklineInteractiveAnimatedPath.d.ts +26 -0
- package/dts/sparkline/sparkline-interactive/SparklineInteractiveAnimatedPath.d.ts.map +1 -0
- package/dts/sparkline/sparkline-interactive/SparklineInteractiveHoverDate.d.ts +5 -0
- package/dts/sparkline/sparkline-interactive/SparklineInteractiveHoverDate.d.ts.map +1 -0
- package/dts/sparkline/sparkline-interactive/SparklineInteractiveHoverPrice.d.ts +5 -0
- package/dts/sparkline/sparkline-interactive/SparklineInteractiveHoverPrice.d.ts.map +1 -0
- package/dts/sparkline/sparkline-interactive/SparklineInteractiveLineVertical.d.ts +8 -0
- package/dts/sparkline/sparkline-interactive/SparklineInteractiveLineVertical.d.ts.map +1 -0
- package/dts/sparkline/sparkline-interactive/SparklineInteractiveMarkerDates.d.ts +17 -0
- package/dts/sparkline/sparkline-interactive/SparklineInteractiveMarkerDates.d.ts.map +1 -0
- package/dts/sparkline/sparkline-interactive/SparklineInteractivePaths.d.ts +25 -0
- package/dts/sparkline/sparkline-interactive/SparklineInteractivePaths.d.ts.map +1 -0
- package/dts/sparkline/sparkline-interactive/SparklineInteractivePeriodSelector.d.ts +25 -0
- package/dts/sparkline/sparkline-interactive/SparklineInteractivePeriodSelector.d.ts.map +1 -0
- package/dts/sparkline/sparkline-interactive/SparklineInteractiveProvider.d.ts +25 -0
- package/dts/sparkline/sparkline-interactive/SparklineInteractiveProvider.d.ts.map +1 -0
- package/dts/sparkline/sparkline-interactive/SparklineInteractiveScrubHandler.d.ts +30 -0
- package/dts/sparkline/sparkline-interactive/SparklineInteractiveScrubHandler.d.ts.map +1 -0
- package/dts/sparkline/sparkline-interactive/SparklineInteractiveScrubProvider.d.ts +18 -0
- package/dts/sparkline/sparkline-interactive/SparklineInteractiveScrubProvider.d.ts.map +1 -0
- package/dts/sparkline/sparkline-interactive/SparklineInteractiveTimeseriesPaths.d.ts +31 -0
- package/dts/sparkline/sparkline-interactive/SparklineInteractiveTimeseriesPaths.d.ts.map +1 -0
- package/dts/sparkline/sparkline-interactive/__figma__/SparklineInteractive.figma.d.ts +2 -0
- package/dts/sparkline/sparkline-interactive/__figma__/SparklineInteractive.figma.d.ts.map +1 -0
- package/dts/sparkline/sparkline-interactive/fade.d.ts +3 -0
- package/dts/sparkline/sparkline-interactive/fade.d.ts.map +1 -0
- package/dts/sparkline/sparkline-interactive/useSparklineInteractiveConstants.d.ts +13 -0
- package/dts/sparkline/sparkline-interactive/useSparklineInteractiveConstants.d.ts.map +1 -0
- package/dts/sparkline/sparkline-interactive-header/SparklineInteractiveHeader.d.ts +112 -0
- package/dts/sparkline/sparkline-interactive-header/SparklineInteractiveHeader.d.ts.map +1 -0
- package/dts/sparkline/sparkline-interactive-header/__figma__/SparklineInteractiveHeader.figma.d.ts +2 -0
- package/dts/sparkline/sparkline-interactive-header/__figma__/SparklineInteractiveHeader.figma.d.ts.map +1 -0
- package/esm/chart/CartesianChart.css +1 -0
- package/esm/chart/CartesianChart.js +258 -0
- package/esm/chart/ChartProvider.js +10 -0
- package/esm/chart/Path.js +89 -0
- package/esm/chart/PeriodSelector.css +1 -0
- package/esm/chart/PeriodSelector.js +126 -0
- package/esm/chart/Point.css +2 -0
- package/esm/chart/Point.js +171 -0
- package/esm/chart/area/Area.js +85 -0
- package/esm/chart/area/AreaChart.js +164 -0
- package/esm/chart/area/DottedArea.js +141 -0
- package/esm/chart/area/GradientArea.js +111 -0
- package/esm/chart/area/SolidArea.js +29 -0
- package/esm/chart/area/index.js +7 -0
- package/esm/chart/axis/Axis.js +46 -0
- package/esm/chart/axis/XAxis.css +2 -0
- package/esm/chart/axis/XAxis.js +195 -0
- package/esm/chart/axis/YAxis.css +2 -0
- package/esm/chart/axis/YAxis.js +183 -0
- package/esm/chart/axis/index.js +5 -0
- package/esm/chart/bar/Bar.js +59 -0
- package/esm/chart/bar/BarChart.js +147 -0
- package/esm/chart/bar/BarPlot.js +96 -0
- package/esm/chart/bar/BarStack.js +519 -0
- package/esm/chart/bar/BarStackGroup.js +96 -0
- package/esm/chart/bar/DefaultBar.js +64 -0
- package/esm/chart/bar/DefaultBarStack.js +60 -0
- package/esm/chart/bar/index.js +9 -0
- package/esm/chart/index.js +14 -0
- package/esm/chart/line/DottedLine.js +38 -0
- package/esm/chart/line/GradientLine.js +58 -0
- package/esm/chart/line/Line.js +159 -0
- package/esm/chart/line/LineChart.js +120 -0
- package/esm/chart/line/ReferenceLine.js +142 -0
- package/esm/chart/line/SolidLine.js +34 -0
- package/esm/chart/line/index.js +8 -0
- package/esm/chart/scrubber/Scrubber.js +483 -0
- package/esm/chart/scrubber/ScrubberBeacon.js +195 -0
- package/esm/chart/scrubber/ScrubberBeaconLabel.js +33 -0
- package/esm/chart/scrubber/ScrubberProvider.js +228 -0
- package/esm/chart/scrubber/index.js +2 -0
- package/esm/chart/text/ChartText.js +236 -0
- package/esm/chart/text/SmartChartTextGroup.js +226 -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 +229 -0
- package/esm/chart/utils/context.js +15 -0
- package/esm/chart/utils/index.js +9 -0
- package/esm/chart/utils/path.js +204 -0
- package/esm/chart/utils/point.js +118 -0
- package/esm/chart/utils/scale.js +48 -0
- package/esm/index.js +4 -0
- package/esm/sparkline/Counter.css +3 -0
- package/esm/sparkline/Counter.js +35 -0
- package/esm/sparkline/Sparkline.js +164 -0
- package/esm/sparkline/SparklineArea.js +18 -0
- package/esm/sparkline/SparklineAreaPattern.js +37 -0
- package/esm/sparkline/SparklineGradient.js +30 -0
- package/esm/sparkline/SparklinePath.js +19 -0
- package/esm/sparkline/__figma__/Sparkline.figma.js +24 -0
- package/esm/sparkline/generateSparklineWithId.js +7 -0
- package/esm/sparkline/index.js +5 -0
- package/esm/sparkline/sparkline-interactive/InnerSparklineInteractiveProvider.js +21 -0
- package/esm/sparkline/sparkline-interactive/SparklineInteractive.js +317 -0
- package/esm/sparkline/sparkline-interactive/SparklineInteractiveAnimatedPath.js +108 -0
- package/esm/sparkline/sparkline-interactive/SparklineInteractiveHoverDate.css +2 -0
- package/esm/sparkline/sparkline-interactive/SparklineInteractiveHoverDate.js +26 -0
- package/esm/sparkline/sparkline-interactive/SparklineInteractiveHoverPrice.css +2 -0
- package/esm/sparkline/sparkline-interactive/SparklineInteractiveHoverPrice.js +24 -0
- package/esm/sparkline/sparkline-interactive/SparklineInteractiveLineVertical.css +4 -0
- package/esm/sparkline/sparkline-interactive/SparklineInteractiveLineVertical.js +65 -0
- package/esm/sparkline/sparkline-interactive/SparklineInteractiveMarkerDates.css +1 -0
- package/esm/sparkline/sparkline-interactive/SparklineInteractiveMarkerDates.js +80 -0
- package/esm/sparkline/sparkline-interactive/SparklineInteractivePaths.js +56 -0
- package/esm/sparkline/sparkline-interactive/SparklineInteractivePeriodSelector.js +70 -0
- package/esm/sparkline/sparkline-interactive/SparklineInteractiveProvider.js +45 -0
- package/esm/sparkline/sparkline-interactive/SparklineInteractiveScrubHandler.css +5 -0
- package/esm/sparkline/sparkline-interactive/SparklineInteractiveScrubHandler.js +199 -0
- package/esm/sparkline/sparkline-interactive/SparklineInteractiveScrubProvider.js +39 -0
- package/esm/sparkline/sparkline-interactive/SparklineInteractiveTimeseriesPaths.js +92 -0
- package/esm/sparkline/sparkline-interactive/__figma__/SparklineInteractive.figma.js +89 -0
- package/esm/sparkline/sparkline-interactive/fade.css +2 -0
- package/esm/sparkline/sparkline-interactive/fade.js +14 -0
- package/esm/sparkline/sparkline-interactive/useSparklineInteractiveConstants.js +28 -0
- package/esm/sparkline/sparkline-interactive-header/SparklineInteractiveHeader.js +225 -0
- package/esm/sparkline/sparkline-interactive-header/__figma__/SparklineInteractiveHeader.figma.js +108 -0
- package/package.json +68 -6
- package/index.js +0 -1
|
@@ -0,0 +1,229 @@
|
|
|
1
|
+
import { stack as d3Stack, stackOffsetDiverging, stackOrderNone } from 'd3-shape';
|
|
2
|
+
export const defaultStackId = 'DEFAULT_STACK_ID';
|
|
3
|
+
/**
|
|
4
|
+
* Type guard to check if bounds are complete with both min and max values.
|
|
5
|
+
* @param bounds - The bounds to validate
|
|
6
|
+
* @returns True if bounds has both min and max defined
|
|
7
|
+
*/
|
|
8
|
+
export const isValidBounds = bounds => bounds.min !== undefined && bounds.max !== undefined;
|
|
9
|
+
/**
|
|
10
|
+
* Calculates the domain of a chart from series data.
|
|
11
|
+
* Domain represents the range of x-values from the data.
|
|
12
|
+
*/
|
|
13
|
+
export const getChartDomain = (series, min, max) => {
|
|
14
|
+
const domain = {
|
|
15
|
+
min,
|
|
16
|
+
max
|
|
17
|
+
};
|
|
18
|
+
if (domain.min !== undefined && domain.max !== undefined) {
|
|
19
|
+
return domain;
|
|
20
|
+
}
|
|
21
|
+
if (series.length > 0) {
|
|
22
|
+
const maxDataLength = Math.max(...series.map(s => {
|
|
23
|
+
var _s$data;
|
|
24
|
+
return ((_s$data = s.data) === null || _s$data === void 0 ? void 0 : _s$data.length) || 0;
|
|
25
|
+
}));
|
|
26
|
+
if (maxDataLength > 0) {
|
|
27
|
+
if (domain.min === undefined) domain.min = 0;
|
|
28
|
+
if (domain.max === undefined) domain.max = maxDataLength - 1;
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
return domain;
|
|
32
|
+
};
|
|
33
|
+
|
|
34
|
+
/**
|
|
35
|
+
* Creates a composite stack key that includes both stack ID and y-axis ID.
|
|
36
|
+
* This ensures series with different y-scales don't get stacked together.
|
|
37
|
+
*/
|
|
38
|
+
const createStackKey = series => {
|
|
39
|
+
if (series.stackId === undefined) return undefined;
|
|
40
|
+
|
|
41
|
+
// Include y-axis ID to prevent cross-scale stacking
|
|
42
|
+
const yAxisId = series.yAxisId || 'default';
|
|
43
|
+
return "".concat(series.stackId, ":").concat(yAxisId);
|
|
44
|
+
};
|
|
45
|
+
|
|
46
|
+
/**
|
|
47
|
+
* Transforms series data into stacked data using D3's stack algorithm.
|
|
48
|
+
* Returns a map of series ID to transformed [baseline, value] tuples.
|
|
49
|
+
*
|
|
50
|
+
* @param series - Array of series with potential stack properties
|
|
51
|
+
* @returns Map of series ID to stacked data arrays
|
|
52
|
+
*/
|
|
53
|
+
export const getStackedSeriesData = series => {
|
|
54
|
+
const stackedDataMap = new Map();
|
|
55
|
+
const numericStackGroups = new Map();
|
|
56
|
+
const individualSeries = [];
|
|
57
|
+
series.forEach(s => {
|
|
58
|
+
var _s$data2;
|
|
59
|
+
const stackKey = createStackKey(s);
|
|
60
|
+
const hasTupleData = (_s$data2 = s.data) === null || _s$data2 === void 0 ? void 0 : _s$data2.some(val => Array.isArray(val));
|
|
61
|
+
if (hasTupleData || stackKey === undefined) {
|
|
62
|
+
individualSeries.push(s);
|
|
63
|
+
} else {
|
|
64
|
+
if (!numericStackGroups.has(stackKey)) {
|
|
65
|
+
numericStackGroups.set(stackKey, []);
|
|
66
|
+
}
|
|
67
|
+
numericStackGroups.get(stackKey).push(s);
|
|
68
|
+
}
|
|
69
|
+
});
|
|
70
|
+
individualSeries.forEach(s => {
|
|
71
|
+
if (!s.data) return;
|
|
72
|
+
const normalizedData = s.data.map(val => {
|
|
73
|
+
if (val === null) return null;
|
|
74
|
+
if (Array.isArray(val)) {
|
|
75
|
+
return val;
|
|
76
|
+
}
|
|
77
|
+
if (typeof val === 'number') {
|
|
78
|
+
return [0, val];
|
|
79
|
+
}
|
|
80
|
+
return null;
|
|
81
|
+
});
|
|
82
|
+
stackedDataMap.set(s.id, normalizedData);
|
|
83
|
+
});
|
|
84
|
+
numericStackGroups.forEach((groupSeries, stackKey) => {
|
|
85
|
+
const maxLength = Math.max(...groupSeries.map(s => {
|
|
86
|
+
var _s$data3;
|
|
87
|
+
return ((_s$data3 = s.data) === null || _s$data3 === void 0 ? void 0 : _s$data3.length) || 0;
|
|
88
|
+
}));
|
|
89
|
+
if (maxLength === 0) return;
|
|
90
|
+
const dataset = new Array(maxLength).fill(undefined).map((_, i) => {
|
|
91
|
+
const row = {};
|
|
92
|
+
for (const s of groupSeries) {
|
|
93
|
+
var _s$data4;
|
|
94
|
+
const val = (_s$data4 = s.data) === null || _s$data4 === void 0 ? void 0 : _s$data4[i];
|
|
95
|
+
const num = typeof val === 'number' ? val : 0;
|
|
96
|
+
row[s.id] = num;
|
|
97
|
+
}
|
|
98
|
+
return row;
|
|
99
|
+
});
|
|
100
|
+
const keys = groupSeries.map(s => s.id);
|
|
101
|
+
const stackedSeries = d3Stack().keys(keys).order(stackOrderNone).offset(stackOffsetDiverging)(dataset);
|
|
102
|
+
stackedSeries.forEach((layer, layerIndex) => {
|
|
103
|
+
const seriesId = keys[layerIndex];
|
|
104
|
+
const stackedData = layer.map(_ref => {
|
|
105
|
+
let [bottom, top] = _ref;
|
|
106
|
+
return [bottom, top];
|
|
107
|
+
});
|
|
108
|
+
stackedDataMap.set(seriesId, stackedData);
|
|
109
|
+
});
|
|
110
|
+
});
|
|
111
|
+
return stackedDataMap;
|
|
112
|
+
};
|
|
113
|
+
|
|
114
|
+
/**
|
|
115
|
+
* Calculates the range of a chart from series data.
|
|
116
|
+
* Range represents the range of y-values from the data.
|
|
117
|
+
* Handles stacking by transforming data when series have stack properties.
|
|
118
|
+
*/
|
|
119
|
+
export const getChartRange = (series, min, max) => {
|
|
120
|
+
const range = {
|
|
121
|
+
min,
|
|
122
|
+
max
|
|
123
|
+
};
|
|
124
|
+
if (range.min !== undefined && range.max !== undefined) {
|
|
125
|
+
return range;
|
|
126
|
+
}
|
|
127
|
+
if (series.length === 0) {
|
|
128
|
+
return range;
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
// Group series by composite stack key for proper calculation
|
|
132
|
+
const stackGroups = new Map();
|
|
133
|
+
series.forEach(s => {
|
|
134
|
+
const stackKey = createStackKey(s);
|
|
135
|
+
if (!stackGroups.has(stackKey)) {
|
|
136
|
+
stackGroups.set(stackKey, []);
|
|
137
|
+
}
|
|
138
|
+
stackGroups.get(stackKey).push(s);
|
|
139
|
+
});
|
|
140
|
+
|
|
141
|
+
// Check if we have any stacked series
|
|
142
|
+
const hasStacks = Array.from(stackGroups.keys()).some(k => k !== undefined);
|
|
143
|
+
if (hasStacks) {
|
|
144
|
+
// Get stacked data using the shared function
|
|
145
|
+
const stackedDataMap = getStackedSeriesData(series);
|
|
146
|
+
|
|
147
|
+
// Find the extreme values from the stacked data
|
|
148
|
+
let stackedMax = 0;
|
|
149
|
+
let stackedMin = 0;
|
|
150
|
+
stackedDataMap.forEach(stackedData => {
|
|
151
|
+
stackedData.forEach(point => {
|
|
152
|
+
if (point !== null) {
|
|
153
|
+
const [bottom, top] = point;
|
|
154
|
+
if (top > stackedMax) stackedMax = top;
|
|
155
|
+
if (bottom < stackedMin) stackedMin = bottom;
|
|
156
|
+
}
|
|
157
|
+
});
|
|
158
|
+
});
|
|
159
|
+
|
|
160
|
+
// Don't add padding - let D3's nice() function handle axis padding
|
|
161
|
+
if (range.min === undefined) range.min = Math.min(0, stackedMin);
|
|
162
|
+
if (range.max === undefined) range.max = Math.max(0, stackedMax);
|
|
163
|
+
} else {
|
|
164
|
+
// No stacking, calculate range from raw values
|
|
165
|
+
const allValues = [];
|
|
166
|
+
series.forEach(s => {
|
|
167
|
+
if (s.data) {
|
|
168
|
+
s.data.forEach(point => {
|
|
169
|
+
if (typeof point === 'number') {
|
|
170
|
+
allValues.push(point);
|
|
171
|
+
} else if (Array.isArray(point)) {
|
|
172
|
+
// Filter out null values from tuples
|
|
173
|
+
const validValues = point.filter(val => val !== null);
|
|
174
|
+
allValues.push(...validValues);
|
|
175
|
+
}
|
|
176
|
+
});
|
|
177
|
+
}
|
|
178
|
+
});
|
|
179
|
+
if (allValues.length > 0) {
|
|
180
|
+
const minValue = Math.min(...allValues);
|
|
181
|
+
const maxValue = Math.max(...allValues);
|
|
182
|
+
if (range.min === undefined) range.min = minValue;
|
|
183
|
+
if (range.max === undefined) range.max = maxValue;
|
|
184
|
+
}
|
|
185
|
+
}
|
|
186
|
+
return range;
|
|
187
|
+
};
|
|
188
|
+
export const defaultChartInset = {
|
|
189
|
+
top: 32,
|
|
190
|
+
left: 16,
|
|
191
|
+
bottom: 16,
|
|
192
|
+
right: 16
|
|
193
|
+
};
|
|
194
|
+
|
|
195
|
+
/**
|
|
196
|
+
* Normalize padding to include all sides with a value.
|
|
197
|
+
* @param padding - The padding to get.
|
|
198
|
+
* @param defaults - Optional complete default values to use instead of 0.
|
|
199
|
+
* @returns The calculated padding.
|
|
200
|
+
*/
|
|
201
|
+
/**
|
|
202
|
+
* Normalize inset to include all sides with a value.
|
|
203
|
+
* @param inset - The inset to get.
|
|
204
|
+
* @param defaults - Optional complete default values to use instead of 0.
|
|
205
|
+
* @returns The calculated inset.
|
|
206
|
+
*/
|
|
207
|
+
export const getChartInset = (inset, defaults) => {
|
|
208
|
+
var _inset$top, _inset$left, _inset$bottom, _inset$right;
|
|
209
|
+
const baseDefaults = defaults !== null && defaults !== void 0 ? defaults : {
|
|
210
|
+
top: 0,
|
|
211
|
+
left: 0,
|
|
212
|
+
bottom: 0,
|
|
213
|
+
right: 0
|
|
214
|
+
};
|
|
215
|
+
if (typeof inset === 'number') {
|
|
216
|
+
return {
|
|
217
|
+
top: inset,
|
|
218
|
+
left: inset,
|
|
219
|
+
bottom: inset,
|
|
220
|
+
right: inset
|
|
221
|
+
};
|
|
222
|
+
}
|
|
223
|
+
return {
|
|
224
|
+
top: (_inset$top = inset === null || inset === void 0 ? void 0 : inset.top) !== null && _inset$top !== void 0 ? _inset$top : baseDefaults.top,
|
|
225
|
+
left: (_inset$left = inset === null || inset === void 0 ? void 0 : inset.left) !== null && _inset$left !== void 0 ? _inset$left : baseDefaults.left,
|
|
226
|
+
bottom: (_inset$bottom = inset === null || inset === void 0 ? void 0 : inset.bottom) !== null && _inset$bottom !== void 0 ? _inset$bottom : baseDefaults.bottom,
|
|
227
|
+
right: (_inset$right = inset === null || inset === void 0 ? void 0 : inset.right) !== null && _inset$right !== void 0 ? _inset$right : baseDefaults.right
|
|
228
|
+
};
|
|
229
|
+
};
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { createContext, useContext } from 'react';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Context value for Cartesian (X/Y) coordinate charts.
|
|
5
|
+
* Contains axis-specific methods and properties for rectangular coordinate systems.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
export const ScrubberContext = /*#__PURE__*/createContext(undefined);
|
|
9
|
+
export const useScrubberContext = () => {
|
|
10
|
+
const context = useContext(ScrubberContext);
|
|
11
|
+
if (!context) {
|
|
12
|
+
throw new Error('useScrubberContext must be used within a Chart component');
|
|
13
|
+
}
|
|
14
|
+
return context;
|
|
15
|
+
};
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
// codegen:start {preset: barrel, include: ./*.ts, exclude: ./__tests__/*.ts}
|
|
2
|
+
export * from './axis';
|
|
3
|
+
export * from './bar';
|
|
4
|
+
export * from './chart';
|
|
5
|
+
export * from './context';
|
|
6
|
+
export * from './path';
|
|
7
|
+
export * from './point';
|
|
8
|
+
export * from './scale';
|
|
9
|
+
// codegen:end
|
|
@@ -0,0 +1,204 @@
|
|
|
1
|
+
import { area as d3Area, curveBumpX, curveCatmullRom, curveLinear, curveLinearClosed, curveMonotoneX, curveNatural, curveStep, curveStepAfter, curveStepBefore, line as d3Line } from 'd3-shape';
|
|
2
|
+
import { projectPoint, projectPoints } from './point';
|
|
3
|
+
import { isCategoricalScale } from './scale';
|
|
4
|
+
/**
|
|
5
|
+
* Get the d3 curve function for a path.
|
|
6
|
+
* See https://d3js.org/d3-shape/curve
|
|
7
|
+
* @param curve - The curve type. Defaults to 'linear'.
|
|
8
|
+
* @returns The d3 curve function.
|
|
9
|
+
*/
|
|
10
|
+
export const getPathCurveFunction = function () {
|
|
11
|
+
let curve = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 'linear';
|
|
12
|
+
switch (curve) {
|
|
13
|
+
case 'catmullRom':
|
|
14
|
+
return curveCatmullRom;
|
|
15
|
+
case 'monotone':
|
|
16
|
+
// When we support layout="vertical" this should dynamically switch to curveMonotoneY
|
|
17
|
+
return curveMonotoneX;
|
|
18
|
+
case 'natural':
|
|
19
|
+
return curveNatural;
|
|
20
|
+
case 'step':
|
|
21
|
+
return curveStep;
|
|
22
|
+
case 'stepBefore':
|
|
23
|
+
return curveStepBefore;
|
|
24
|
+
case 'stepAfter':
|
|
25
|
+
return curveStepAfter;
|
|
26
|
+
case 'bump':
|
|
27
|
+
// When we support layout="vertical" this should dynamically switch to curveBumpY
|
|
28
|
+
return curveBumpX;
|
|
29
|
+
case 'linearClosed':
|
|
30
|
+
return curveLinearClosed;
|
|
31
|
+
case 'linear':
|
|
32
|
+
default:
|
|
33
|
+
return curveLinear;
|
|
34
|
+
}
|
|
35
|
+
};
|
|
36
|
+
|
|
37
|
+
/**
|
|
38
|
+
* Generates an SVG line path string from data using chart scale functions.
|
|
39
|
+
*
|
|
40
|
+
* @example
|
|
41
|
+
* ```typescript
|
|
42
|
+
* const chartScale = getChartScale({ chartRect, domain, range, xScale, yScale });
|
|
43
|
+
* const path = getLinePath({ data: [1, 2, 3], chartScale, curve: 'linear' });
|
|
44
|
+
* ```
|
|
45
|
+
*/
|
|
46
|
+
export const getLinePath = _ref => {
|
|
47
|
+
var _pathGenerator;
|
|
48
|
+
let {
|
|
49
|
+
data,
|
|
50
|
+
curve = 'linear',
|
|
51
|
+
xScale,
|
|
52
|
+
yScale,
|
|
53
|
+
xData
|
|
54
|
+
} = _ref;
|
|
55
|
+
if (data.length === 0) {
|
|
56
|
+
return '';
|
|
57
|
+
}
|
|
58
|
+
const curveFunction = getPathCurveFunction(curve);
|
|
59
|
+
const dataPoints = projectPoints({
|
|
60
|
+
data,
|
|
61
|
+
xScale,
|
|
62
|
+
yScale,
|
|
63
|
+
xData
|
|
64
|
+
});
|
|
65
|
+
const pathGenerator = d3Line().x(d => d.x).y(d => d.y).curve(curveFunction).defined(d => d !== null); // Only draw lines where point is not null
|
|
66
|
+
|
|
67
|
+
return (_pathGenerator = pathGenerator(dataPoints)) !== null && _pathGenerator !== void 0 ? _pathGenerator : '';
|
|
68
|
+
};
|
|
69
|
+
|
|
70
|
+
/**
|
|
71
|
+
* Generates an SVG area path string from data using chart scale functions.
|
|
72
|
+
* Supports both single values (area from baseline to value) and tuples ([baseline, value]).
|
|
73
|
+
*
|
|
74
|
+
* @example
|
|
75
|
+
* ```typescript
|
|
76
|
+
* // Single values - area from baseline to value
|
|
77
|
+
* const area = getAreaPath({
|
|
78
|
+
* data: [1, 2, 3],
|
|
79
|
+
* xScale,
|
|
80
|
+
* yScale,
|
|
81
|
+
* });
|
|
82
|
+
*
|
|
83
|
+
* // Range values - area from low to high
|
|
84
|
+
* const rangeArea = getAreaPath({
|
|
85
|
+
* data: [[0, 3], [2, 4], [1, 5]],
|
|
86
|
+
* xScale,
|
|
87
|
+
* yScale,
|
|
88
|
+
* curve: 'monotone'
|
|
89
|
+
* });
|
|
90
|
+
* ```
|
|
91
|
+
*/
|
|
92
|
+
export const getAreaPath = _ref2 => {
|
|
93
|
+
let {
|
|
94
|
+
data,
|
|
95
|
+
curve = 'linear',
|
|
96
|
+
xScale,
|
|
97
|
+
yScale,
|
|
98
|
+
xData
|
|
99
|
+
} = _ref2;
|
|
100
|
+
if (data.length === 0) {
|
|
101
|
+
return '';
|
|
102
|
+
}
|
|
103
|
+
const curveFunction = getPathCurveFunction(curve);
|
|
104
|
+
const yDomain = yScale.domain();
|
|
105
|
+
const yMin = Math.min(...yDomain);
|
|
106
|
+
const normalizedData = data.map((item, index) => {
|
|
107
|
+
if (item === null) {
|
|
108
|
+
return null;
|
|
109
|
+
}
|
|
110
|
+
if (Array.isArray(item)) {
|
|
111
|
+
if (item.length >= 2 && typeof item[0] === 'number' && typeof item[1] === 'number') {
|
|
112
|
+
return [item[0], item[1]];
|
|
113
|
+
}
|
|
114
|
+
return null;
|
|
115
|
+
}
|
|
116
|
+
if (typeof item === 'number') {
|
|
117
|
+
return [yMin, item];
|
|
118
|
+
}
|
|
119
|
+
return null;
|
|
120
|
+
});
|
|
121
|
+
const dataPoints = normalizedData.map((range, index) => {
|
|
122
|
+
if (range === null) {
|
|
123
|
+
return {
|
|
124
|
+
x: 0,
|
|
125
|
+
low: null,
|
|
126
|
+
high: null,
|
|
127
|
+
isValid: false
|
|
128
|
+
};
|
|
129
|
+
}
|
|
130
|
+
let xValue = index;
|
|
131
|
+
if (!isCategoricalScale(xScale) && xData && xData[index] !== undefined) {
|
|
132
|
+
xValue = xData[index];
|
|
133
|
+
}
|
|
134
|
+
const xPoint = projectPoint({
|
|
135
|
+
x: xValue,
|
|
136
|
+
y: 0,
|
|
137
|
+
xScale,
|
|
138
|
+
yScale
|
|
139
|
+
});
|
|
140
|
+
const lowPoint = projectPoint({
|
|
141
|
+
x: xValue,
|
|
142
|
+
y: range[0],
|
|
143
|
+
xScale,
|
|
144
|
+
yScale
|
|
145
|
+
});
|
|
146
|
+
const highPoint = projectPoint({
|
|
147
|
+
x: xValue,
|
|
148
|
+
y: range[1],
|
|
149
|
+
xScale,
|
|
150
|
+
yScale
|
|
151
|
+
});
|
|
152
|
+
return {
|
|
153
|
+
x: xPoint.x,
|
|
154
|
+
low: lowPoint.y,
|
|
155
|
+
high: highPoint.y,
|
|
156
|
+
isValid: true
|
|
157
|
+
};
|
|
158
|
+
});
|
|
159
|
+
const areaGenerator = d3Area().x(d => d.x).y0(d => {
|
|
160
|
+
var _d$low;
|
|
161
|
+
return (_d$low = d.low) !== null && _d$low !== void 0 ? _d$low : 0;
|
|
162
|
+
}) // Bottom boundary (low values), fallback to 0
|
|
163
|
+
.y1(d => {
|
|
164
|
+
var _d$high;
|
|
165
|
+
return (_d$high = d.high) !== null && _d$high !== void 0 ? _d$high : 0;
|
|
166
|
+
}) // Top boundary (high values), fallback to 0
|
|
167
|
+
.curve(curveFunction).defined(d => d.isValid && d.low != null && d.high != null); // Only draw where both values exist
|
|
168
|
+
|
|
169
|
+
const result = areaGenerator(dataPoints);
|
|
170
|
+
return result !== null && result !== void 0 ? result : '';
|
|
171
|
+
};
|
|
172
|
+
|
|
173
|
+
/**
|
|
174
|
+
* Creates an SVG path string for a rectangle with selective corner rounding.
|
|
175
|
+
* Useful for creating bars in charts with optional rounded corners.
|
|
176
|
+
*
|
|
177
|
+
* @example
|
|
178
|
+
* ```typescript
|
|
179
|
+
* // Simple rectangle bar
|
|
180
|
+
* const barPath = getBarPath(10, 20, 50, 100, 0, false, false);
|
|
181
|
+
*
|
|
182
|
+
* // Bar with rounded top corners
|
|
183
|
+
* const roundedPath = getBarPath(10, 20, 50, 100, 8, true, false);
|
|
184
|
+
* ```
|
|
185
|
+
*/
|
|
186
|
+
export const getBarPath = (x, y, width, height, radius, roundTop, roundBottom) => {
|
|
187
|
+
const roundBothSides = roundTop && roundBottom;
|
|
188
|
+
const r = Math.min(radius, width / 2, roundBothSides ? height / 2 : height);
|
|
189
|
+
const topR = roundTop ? r : 0;
|
|
190
|
+
const bottomR = roundBottom ? r : 0;
|
|
191
|
+
|
|
192
|
+
// Build path with selective rounding
|
|
193
|
+
let path = "M ".concat(x + (roundTop ? r : 0), " ").concat(y);
|
|
194
|
+
path += " L ".concat(x + width - topR, " ").concat(y);
|
|
195
|
+
path += " A ".concat(topR, " ").concat(topR, " 0 0 1 ").concat(x + width, " ").concat(y + topR);
|
|
196
|
+
path += " L ".concat(x + width, " ").concat(y + height - bottomR);
|
|
197
|
+
path += " A ".concat(bottomR, " ").concat(bottomR, " 0 0 1 ").concat(x + width - bottomR, " ").concat(y + height);
|
|
198
|
+
path += " L ".concat(x + bottomR, " ").concat(y + height);
|
|
199
|
+
path += " A ".concat(bottomR, " ").concat(bottomR, " 0 0 1 ").concat(x, " ").concat(y + height - bottomR);
|
|
200
|
+
path += " L ".concat(x, " ").concat(y + topR);
|
|
201
|
+
path += " A ".concat(topR, " ").concat(topR, " 0 0 1 ").concat(x + topR, " ").concat(y);
|
|
202
|
+
path += ' Z';
|
|
203
|
+
return path;
|
|
204
|
+
};
|
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
import { isCategoricalScale, isLogScale, isNumericScale } from './scale';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Get a point from a data value and a scale.
|
|
5
|
+
* @note for categorical scales, the point will be centered within the band.
|
|
6
|
+
* @note for log scales, zero and negative values are clamped to a small positive value.
|
|
7
|
+
* @param data - the data value.
|
|
8
|
+
* @param scale - the scale function.
|
|
9
|
+
* @returns the pixel value (defaulting to 0 if data value is not defined in scale).
|
|
10
|
+
*/
|
|
11
|
+
export const getPointOnScale = (dataValue, scale) => {
|
|
12
|
+
var _scale2;
|
|
13
|
+
if (isCategoricalScale(scale)) {
|
|
14
|
+
var _scale, _scale$bandwidth;
|
|
15
|
+
const bandStart = (_scale = scale(dataValue)) !== null && _scale !== void 0 ? _scale : 0;
|
|
16
|
+
const bandwidth = (_scale$bandwidth = scale.bandwidth()) !== null && _scale$bandwidth !== void 0 ? _scale$bandwidth : 0;
|
|
17
|
+
return bandStart + bandwidth / 2;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
// For log scales, ensure the value is positive
|
|
21
|
+
let adjustedValue = dataValue;
|
|
22
|
+
if (isLogScale(scale) && dataValue <= 0) {
|
|
23
|
+
adjustedValue = 0.001; // Use a small positive value for log scales
|
|
24
|
+
}
|
|
25
|
+
return (_scale2 = scale(adjustedValue)) !== null && _scale2 !== void 0 ? _scale2 : 0;
|
|
26
|
+
};
|
|
27
|
+
|
|
28
|
+
/**
|
|
29
|
+
* Projects a data point to pixel coordinates using the chart scale.
|
|
30
|
+
* Automatically handles log scale transformations for zero/negative values.
|
|
31
|
+
*
|
|
32
|
+
* @example
|
|
33
|
+
* ```typescript
|
|
34
|
+
* const chartScale = getChartScale({ chartRect, domain, range, xScale, yScale });
|
|
35
|
+
* const pixelCoord = projectPoint({ x: 5, y: 10, chartScale });
|
|
36
|
+
* ```
|
|
37
|
+
* @example
|
|
38
|
+
* ```typescript
|
|
39
|
+
* const chartScale = getChartScale({ chartRect, domain, range, xScale, yScale });
|
|
40
|
+
* const pixelCoord = projectPoint({ x: 2, y: 10, chartScale, xData: ['Jan', 'Feb', 'Mar'] });
|
|
41
|
+
* ```
|
|
42
|
+
*/
|
|
43
|
+
export const projectPoint = _ref => {
|
|
44
|
+
let {
|
|
45
|
+
x,
|
|
46
|
+
y,
|
|
47
|
+
xScale,
|
|
48
|
+
yScale
|
|
49
|
+
} = _ref;
|
|
50
|
+
return {
|
|
51
|
+
x: getPointOnScale(x, xScale),
|
|
52
|
+
y: getPointOnScale(y, yScale)
|
|
53
|
+
};
|
|
54
|
+
};
|
|
55
|
+
|
|
56
|
+
/**
|
|
57
|
+
* Projects multiple data points to pixel coordinates using chart scale functions.
|
|
58
|
+
* Handles both numeric and band scales automatically.
|
|
59
|
+
*
|
|
60
|
+
* @example
|
|
61
|
+
* ```typescript
|
|
62
|
+
* const chartScale = getChartScale({ chartRect, domain, range, xScale, yScale });
|
|
63
|
+
* const pixelPoints = projectPoints({ data, chartScale });
|
|
64
|
+
* // For mixed scales
|
|
65
|
+
* const pixelPoints = projectPoints({ data, chartScale, xData: ['Jan', 'Feb', 'Mar'] });
|
|
66
|
+
* ```
|
|
67
|
+
*/
|
|
68
|
+
export const projectPoints = _ref2 => {
|
|
69
|
+
let {
|
|
70
|
+
data,
|
|
71
|
+
xScale,
|
|
72
|
+
yScale,
|
|
73
|
+
xData,
|
|
74
|
+
yData
|
|
75
|
+
} = _ref2;
|
|
76
|
+
if (data.length === 0) {
|
|
77
|
+
return [];
|
|
78
|
+
}
|
|
79
|
+
return data.map((value, index) => {
|
|
80
|
+
if (value === null) {
|
|
81
|
+
return null;
|
|
82
|
+
}
|
|
83
|
+
if (typeof value === 'object' && 'x' in value && 'y' in value) {
|
|
84
|
+
return projectPoint({
|
|
85
|
+
x: value.x,
|
|
86
|
+
y: value.y,
|
|
87
|
+
xScale,
|
|
88
|
+
yScale
|
|
89
|
+
});
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
// For scales with axis data, determine the correct x value
|
|
93
|
+
let xValue = index;
|
|
94
|
+
|
|
95
|
+
// For band scales, always use the index
|
|
96
|
+
if (!isCategoricalScale(xScale)) {
|
|
97
|
+
// For numeric scales with axis data, use the axis data values instead of indices
|
|
98
|
+
if (xData && Array.isArray(xData) && xData.length > 0) {
|
|
99
|
+
// Check if it's numeric data
|
|
100
|
+
if (typeof xData[0] === 'number') {
|
|
101
|
+
var _numericXData$index;
|
|
102
|
+
const numericXData = xData;
|
|
103
|
+
xValue = (_numericXData$index = numericXData[index]) !== null && _numericXData$index !== void 0 ? _numericXData$index : index;
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
let yValue = value;
|
|
108
|
+
if (isNumericScale(yScale) && yData && Array.isArray(yData) && yData.length > 0 && typeof yData[0] === 'number' && typeof value === 'number') {
|
|
109
|
+
yValue = value;
|
|
110
|
+
}
|
|
111
|
+
return projectPoint({
|
|
112
|
+
x: xValue,
|
|
113
|
+
y: yValue,
|
|
114
|
+
xScale,
|
|
115
|
+
yScale
|
|
116
|
+
});
|
|
117
|
+
});
|
|
118
|
+
};
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import { scaleBand, scaleLinear, scaleLog } from 'd3-scale';
|
|
2
|
+
|
|
3
|
+
// https://d3js.org/d3-scale - ideal next scale would be time
|
|
4
|
+
|
|
5
|
+
export const isCategoricalScale = scale => {
|
|
6
|
+
return scale !== undefined && 'bandwidth' in scale && typeof scale.bandwidth === 'function';
|
|
7
|
+
};
|
|
8
|
+
export const isNumericScale = scale => {
|
|
9
|
+
return scale !== undefined && !isCategoricalScale(scale);
|
|
10
|
+
};
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* Type guard to check if a scale is logarithmic.
|
|
14
|
+
*/
|
|
15
|
+
export const isLogScale = scale => {
|
|
16
|
+
return scale !== undefined && 'base' in scale && typeof scale.base === 'function';
|
|
17
|
+
};
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* Create a numeric scale (linear or logarithmic)
|
|
21
|
+
* @returns A numeric scale function
|
|
22
|
+
*/
|
|
23
|
+
export const getNumericScale = _ref => {
|
|
24
|
+
let {
|
|
25
|
+
scaleType,
|
|
26
|
+
domain,
|
|
27
|
+
range
|
|
28
|
+
} = _ref;
|
|
29
|
+
const scale = scaleType === 'log' ? scaleLog() : scaleLinear();
|
|
30
|
+
return scale.domain([domain.min, domain.max]).range([range.min, range.max]);
|
|
31
|
+
};
|
|
32
|
+
|
|
33
|
+
/**
|
|
34
|
+
* Create a categorical scale (band)
|
|
35
|
+
* @returns A categorical scale function
|
|
36
|
+
*/
|
|
37
|
+
export const getCategoricalScale = _ref2 => {
|
|
38
|
+
let {
|
|
39
|
+
domain,
|
|
40
|
+
range,
|
|
41
|
+
padding = 0.1
|
|
42
|
+
} = _ref2;
|
|
43
|
+
const domainArray = Array.from({
|
|
44
|
+
length: domain.max - domain.min + 1
|
|
45
|
+
}, (_, i) => i);
|
|
46
|
+
const scale = scaleBand().domain(domainArray).range([range.min, range.max]).padding(padding);
|
|
47
|
+
return scale;
|
|
48
|
+
};
|
package/esm/index.js
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
.cds-containerCss-co2zq3s{position:relative;display:-webkit-inline-box;display:-webkit-inline-flex;display:-ms-inline-flexbox;display:inline-flex;-webkit-align-items:center;-webkit-box-align:center;-ms-flex-align:center;align-items:center;}
|
|
2
|
+
.cds-hiddenCss-h1nhoofs{visibility:hidden;}
|
|
3
|
+
.cds-visibleCss-vhca54u{position:absolute;top:0;left:0;width:100%;height:100%;display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-align-items:center;-webkit-box-align:center;-ms-flex-align:center;align-items:center;}.cds-visibleCss-vhca54u > *{width:100%;height:100%;display:-webkit-inline-box;display:-webkit-inline-flex;display:-ms-inline-flexbox;display:inline-flex;-webkit-align-items:center;-webkit-box-align:center;-ms-flex-align:center;align-items:center;}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import React, { useMemo } from 'react';
|
|
2
|
+
import { useCounter } from '@coinbase/cds-common/visualizations/useCounter';
|
|
3
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
4
|
+
const containerCss = "cds-containerCss-co2zq3s";
|
|
5
|
+
const hiddenCss = "cds-hiddenCss-h1nhoofs";
|
|
6
|
+
const visibleCss = "cds-visibleCss-vhca54u";
|
|
7
|
+
export const Counter = _ref => {
|
|
8
|
+
let {
|
|
9
|
+
startNum,
|
|
10
|
+
endNum,
|
|
11
|
+
renderNum,
|
|
12
|
+
durationInMillis
|
|
13
|
+
} = _ref;
|
|
14
|
+
const count = useCounter({
|
|
15
|
+
startNum,
|
|
16
|
+
endNum,
|
|
17
|
+
durationInMillis
|
|
18
|
+
});
|
|
19
|
+
const renderFunction = useMemo(() => {
|
|
20
|
+
return num => {
|
|
21
|
+
return renderNum ? renderNum(num) : num;
|
|
22
|
+
};
|
|
23
|
+
}, [renderNum]);
|
|
24
|
+
return /*#__PURE__*/_jsxs("div", {
|
|
25
|
+
className: containerCss,
|
|
26
|
+
children: [/*#__PURE__*/_jsx("span", {
|
|
27
|
+
className: hiddenCss,
|
|
28
|
+
children: renderFunction(endNum)
|
|
29
|
+
}), /*#__PURE__*/_jsx("span", {
|
|
30
|
+
className: visibleCss,
|
|
31
|
+
children: renderFunction(count)
|
|
32
|
+
})]
|
|
33
|
+
});
|
|
34
|
+
};
|
|
35
|
+
import "./Counter.css";
|