exploreda 0.0.5 → 0.1.0
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/README.md +144 -0
- package/dist/ExplorEda.cjs +4608 -10858
- package/dist/ExplorEda.cjs.map +1 -1
- package/dist/ExplorEda.css +2332 -1653
- package/dist/ExplorEda.css.map +1 -1
- package/dist/ExplorEda.d.cts +125 -278
- package/dist/ExplorEda.d.ts +125 -278
- package/dist/ExplorEda.js +4521 -10782
- package/dist/ExplorEda.js.map +1 -1
- package/dist/calculations.cjs +18 -0
- package/dist/calculations.cjs.map +1 -0
- package/dist/calculations.d.cts +63 -0
- package/dist/calculations.d.ts +63 -0
- package/dist/calculations.js +3 -0
- package/dist/calculations.js.map +1 -0
- package/dist/charts/bar.cjs +27 -0
- package/dist/charts/bar.cjs.map +1 -0
- package/dist/charts/bar.d.cts +2 -0
- package/dist/charts/bar.d.ts +2 -0
- package/dist/charts/bar.js +18 -0
- package/dist/charts/bar.js.map +1 -0
- package/dist/charts/box-plot.cjs +26 -0
- package/dist/charts/box-plot.cjs.map +1 -0
- package/dist/charts/box-plot.d.cts +2 -0
- package/dist/charts/box-plot.d.ts +2 -0
- package/dist/charts/box-plot.js +17 -0
- package/dist/charts/box-plot.js.map +1 -0
- package/dist/charts/color-legend.cjs +22 -0
- package/dist/charts/color-legend.cjs.map +1 -0
- package/dist/charts/color-legend.d.cts +2 -0
- package/dist/charts/color-legend.d.ts +2 -0
- package/dist/charts/color-legend.js +13 -0
- package/dist/charts/color-legend.js.map +1 -0
- package/dist/charts/data-table.cjs +22 -0
- package/dist/charts/data-table.cjs.map +1 -0
- package/dist/charts/data-table.d.cts +2 -0
- package/dist/charts/data-table.d.ts +2 -0
- package/dist/charts/data-table.js +13 -0
- package/dist/charts/data-table.js.map +1 -0
- package/dist/charts/line.cjs +30 -0
- package/dist/charts/line.cjs.map +1 -0
- package/dist/charts/line.d.cts +2 -0
- package/dist/charts/line.d.ts +2 -0
- package/dist/charts/line.js +17 -0
- package/dist/charts/line.js.map +1 -0
- package/dist/charts/markdown.cjs +16 -0
- package/dist/charts/markdown.cjs.map +1 -0
- package/dist/charts/markdown.css +77 -0
- package/dist/charts/markdown.css.map +1 -0
- package/dist/charts/markdown.d.cts +2 -0
- package/dist/charts/markdown.d.ts +2 -0
- package/dist/charts/markdown.js +7 -0
- package/dist/charts/markdown.js.map +1 -0
- package/dist/charts/pivot-table.cjs +23 -0
- package/dist/charts/pivot-table.cjs.map +1 -0
- package/dist/charts/pivot-table.d.cts +2 -0
- package/dist/charts/pivot-table.d.ts +2 -0
- package/dist/charts/pivot-table.js +14 -0
- package/dist/charts/pivot-table.js.map +1 -0
- package/dist/charts/row.cjs +27 -0
- package/dist/charts/row.cjs.map +1 -0
- package/dist/charts/row.d.cts +6 -0
- package/dist/charts/row.d.ts +6 -0
- package/dist/charts/row.js +18 -0
- package/dist/charts/row.js.map +1 -0
- package/dist/charts/scatter.cjs +24 -0
- package/dist/charts/scatter.cjs.map +1 -0
- package/dist/charts/scatter.d.cts +2 -0
- package/dist/charts/scatter.d.ts +2 -0
- package/dist/charts/scatter.js +15 -0
- package/dist/charts/scatter.js.map +1 -0
- package/dist/charts/summary-table.cjs +19 -0
- package/dist/charts/summary-table.cjs.map +1 -0
- package/dist/charts/summary-table.d.cts +2 -0
- package/dist/charts/summary-table.d.ts +2 -0
- package/dist/charts/summary-table.js +10 -0
- package/dist/charts/summary-table.js.map +1 -0
- package/dist/charts/three-d-scatter.cjs +24 -0
- package/dist/charts/three-d-scatter.cjs.map +1 -0
- package/dist/charts/three-d-scatter.d.cts +6 -0
- package/dist/charts/three-d-scatter.d.ts +6 -0
- package/dist/charts/three-d-scatter.js +15 -0
- package/dist/charts/three-d-scatter.js.map +1 -0
- package/dist/chunk-3PGYFLE3.cjs +499 -0
- package/dist/chunk-3PGYFLE3.cjs.map +1 -0
- package/dist/chunk-4HNDKMWF.js +167 -0
- package/dist/chunk-4HNDKMWF.js.map +1 -0
- package/dist/chunk-4QNENKTV.cjs +1214 -0
- package/dist/chunk-4QNENKTV.cjs.map +1 -0
- package/dist/chunk-54M32JJB.js +132 -0
- package/dist/chunk-54M32JJB.js.map +1 -0
- package/dist/chunk-5B23JVH3.cjs +2238 -0
- package/dist/chunk-5B23JVH3.cjs.map +1 -0
- package/dist/chunk-5LH6NSNL.js +456 -0
- package/dist/chunk-5LH6NSNL.js.map +1 -0
- package/dist/chunk-6DOKKCJ5.cjs +313 -0
- package/dist/chunk-6DOKKCJ5.cjs.map +1 -0
- package/dist/chunk-6HZX5CBT.cjs +1074 -0
- package/dist/chunk-6HZX5CBT.cjs.map +1 -0
- package/dist/chunk-6U5DOIQM.js +1071 -0
- package/dist/chunk-6U5DOIQM.js.map +1 -0
- package/dist/chunk-7GBZIK2R.cjs +80 -0
- package/dist/chunk-7GBZIK2R.cjs.map +1 -0
- package/dist/chunk-7PTJNIOD.js +520 -0
- package/dist/chunk-7PTJNIOD.js.map +1 -0
- package/dist/chunk-AHZYQ7FN.js +319 -0
- package/dist/chunk-AHZYQ7FN.js.map +1 -0
- package/dist/chunk-AOODAOL4.cjs +55 -0
- package/dist/chunk-AOODAOL4.cjs.map +1 -0
- package/dist/chunk-ASKFIRMC.cjs +165 -0
- package/dist/chunk-ASKFIRMC.cjs.map +1 -0
- package/dist/chunk-B7OQUBH4.cjs +171 -0
- package/dist/chunk-B7OQUBH4.cjs.map +1 -0
- package/dist/chunk-BIMEHDLB.js +72 -0
- package/dist/chunk-BIMEHDLB.js.map +1 -0
- package/dist/chunk-C62KHV7S.js +1225 -0
- package/dist/chunk-C62KHV7S.js.map +1 -0
- package/dist/chunk-C7GQT65O.cjs +1119 -0
- package/dist/chunk-C7GQT65O.cjs.map +1 -0
- package/dist/chunk-CGDWDV4Z.js +1211 -0
- package/dist/chunk-CGDWDV4Z.js.map +1 -0
- package/dist/chunk-CJQQFNEY.js +69 -0
- package/dist/chunk-CJQQFNEY.js.map +1 -0
- package/dist/chunk-DHYLSXNR.js +964 -0
- package/dist/chunk-DHYLSXNR.js.map +1 -0
- package/dist/chunk-DKFA4KOJ.cjs +87 -0
- package/dist/chunk-DKFA4KOJ.cjs.map +1 -0
- package/dist/chunk-DS5BS7PP.cjs +357 -0
- package/dist/chunk-DS5BS7PP.cjs.map +1 -0
- package/dist/chunk-EGMFQSGK.js +909 -0
- package/dist/chunk-EGMFQSGK.js.map +1 -0
- package/dist/chunk-EU5EFHO5.cjs +53 -0
- package/dist/chunk-EU5EFHO5.cjs.map +1 -0
- package/dist/chunk-FM46QSDM.js +837 -0
- package/dist/chunk-FM46QSDM.js.map +1 -0
- package/dist/chunk-GV2LRR32.cjs +843 -0
- package/dist/chunk-GV2LRR32.cjs.map +1 -0
- package/dist/chunk-H3XKFSA5.cjs +322 -0
- package/dist/chunk-H3XKFSA5.cjs.map +1 -0
- package/dist/chunk-H5AVMMCE.js +347 -0
- package/dist/chunk-H5AVMMCE.js.map +1 -0
- package/dist/chunk-JDMUN4VK.cjs +986 -0
- package/dist/chunk-JDMUN4VK.cjs.map +1 -0
- package/dist/chunk-JNO7OXCC.js +2171 -0
- package/dist/chunk-JNO7OXCC.js.map +1 -0
- package/dist/chunk-JQMG4ZR7.js +111 -0
- package/dist/chunk-JQMG4ZR7.js.map +1 -0
- package/dist/chunk-L2Q2R43U.cjs +118 -0
- package/dist/chunk-L2Q2R43U.cjs.map +1 -0
- package/dist/chunk-LBTZVERO.js +466 -0
- package/dist/chunk-LBTZVERO.js.map +1 -0
- package/dist/chunk-LUUGGTTK.cjs +1227 -0
- package/dist/chunk-LUUGGTTK.cjs.map +1 -0
- package/dist/chunk-MEEPH7ZC.cjs +911 -0
- package/dist/chunk-MEEPH7ZC.cjs.map +1 -0
- package/dist/chunk-MJPDJ5AS.js +184 -0
- package/dist/chunk-MJPDJ5AS.js.map +1 -0
- package/dist/chunk-MJROUIDZ.cjs +219 -0
- package/dist/chunk-MJROUIDZ.cjs.map +1 -0
- package/dist/chunk-MUWSBYJS.js +528 -0
- package/dist/chunk-MUWSBYJS.js.map +1 -0
- package/dist/chunk-NDF5LCST.js +1088 -0
- package/dist/chunk-NDF5LCST.js.map +1 -0
- package/dist/chunk-NGWTPED4.js +311 -0
- package/dist/chunk-NGWTPED4.js.map +1 -0
- package/dist/chunk-PP4VCONW.js +739 -0
- package/dist/chunk-PP4VCONW.js.map +1 -0
- package/dist/chunk-PRMC2A6P.cjs +488 -0
- package/dist/chunk-PRMC2A6P.cjs.map +1 -0
- package/dist/chunk-PST6UU6S.cjs +742 -0
- package/dist/chunk-PST6UU6S.cjs.map +1 -0
- package/dist/chunk-Q7LK2UWH.js +33 -0
- package/dist/chunk-Q7LK2UWH.js.map +1 -0
- package/dist/chunk-SFV5LZPD.js +162 -0
- package/dist/chunk-SFV5LZPD.js.map +1 -0
- package/dist/chunk-SKXGYJJG.cjs +370 -0
- package/dist/chunk-SKXGYJJG.cjs.map +1 -0
- package/dist/chunk-SWLNKY6R.js +477 -0
- package/dist/chunk-SWLNKY6R.js.map +1 -0
- package/dist/chunk-TGVLNHUB.cjs +483 -0
- package/dist/chunk-TGVLNHUB.cjs.map +1 -0
- package/dist/chunk-TLLRW6S3.js +74 -0
- package/dist/chunk-TLLRW6S3.js.map +1 -0
- package/dist/chunk-TRAIXZ6M.cjs +140 -0
- package/dist/chunk-TRAIXZ6M.cjs.map +1 -0
- package/dist/chunk-U74A5VK5.cjs +74 -0
- package/dist/chunk-U74A5VK5.cjs.map +1 -0
- package/dist/chunk-UAVDLBTA.cjs +74 -0
- package/dist/chunk-UAVDLBTA.cjs.map +1 -0
- package/dist/chunk-UJWS6TRV.js +354 -0
- package/dist/chunk-UJWS6TRV.js.map +1 -0
- package/dist/chunk-UUJMUPB3.cjs +531 -0
- package/dist/chunk-UUJMUPB3.cjs.map +1 -0
- package/dist/chunk-VTKHZIJB.cjs +549 -0
- package/dist/chunk-VTKHZIJB.cjs.map +1 -0
- package/dist/chunk-YXPAWUXO.js +51 -0
- package/dist/chunk-YXPAWUXO.js.map +1 -0
- package/dist/chunk-ZD64SCZB.js +80 -0
- package/dist/chunk-ZD64SCZB.js.map +1 -0
- package/dist/core.cjs +28 -0
- package/dist/core.cjs.map +1 -0
- package/dist/core.d.cts +22 -0
- package/dist/core.d.ts +22 -0
- package/dist/core.js +3 -0
- package/dist/core.js.map +1 -0
- package/dist/dataLayerState-B4XmQjQN.d.cts +258 -0
- package/dist/dataLayerState-B4XmQjQN.d.ts +258 -0
- package/package.json +32 -52
|
@@ -0,0 +1,354 @@
|
|
|
1
|
+
import { planAxes, useBrush, PlannedGrid, PlannedAxes, findAxisGuide, getRangeFilterForField } from './chunk-7PTJNIOD.js';
|
|
2
|
+
import { useDataLayer, getChartAxisFields, getChartAxisLabel, getChartTitle, cn } from './chunk-JNO7OXCC.js';
|
|
3
|
+
import { useRef, useState, useId, useMemo, useCallback } from 'react';
|
|
4
|
+
import { scaleLinear } from 'd3-scale';
|
|
5
|
+
import { jsxs, jsx } from 'react/jsx-runtime';
|
|
6
|
+
|
|
7
|
+
// src/components/charts/Axis/Axis.tsx
|
|
8
|
+
function formatTick(value) {
|
|
9
|
+
if (typeof value === "string") return value;
|
|
10
|
+
return new Intl.NumberFormat("en-US", {
|
|
11
|
+
notation: Math.abs(value) >= 1e4 ? "compact" : "standard",
|
|
12
|
+
maximumFractionDigits: Math.abs(value) < 1 ? 3 : 2
|
|
13
|
+
}).format(value);
|
|
14
|
+
}
|
|
15
|
+
function useFilterExtent({
|
|
16
|
+
settings,
|
|
17
|
+
xScale,
|
|
18
|
+
yScale,
|
|
19
|
+
innerHeight
|
|
20
|
+
}) {
|
|
21
|
+
const convertFilterRangeToExtent = useCallback(
|
|
22
|
+
(filter, scale) => {
|
|
23
|
+
if (!filter || filter.min === void 0 || filter.max === void 0) {
|
|
24
|
+
return null;
|
|
25
|
+
}
|
|
26
|
+
const min = Math.round(scale(filter.min) * 1e4) / 1e4;
|
|
27
|
+
const max = Math.round(scale(filter.max) * 1e4) / 1e4;
|
|
28
|
+
return [min, max];
|
|
29
|
+
},
|
|
30
|
+
[]
|
|
31
|
+
);
|
|
32
|
+
const extent = useMemo(() => {
|
|
33
|
+
switch (settings.type) {
|
|
34
|
+
case "scatter": {
|
|
35
|
+
const xFilter = getRangeFilterForField(
|
|
36
|
+
settings.filters,
|
|
37
|
+
settings.xField
|
|
38
|
+
);
|
|
39
|
+
const yFilter = getRangeFilterForField(
|
|
40
|
+
settings.filters,
|
|
41
|
+
settings.yField
|
|
42
|
+
);
|
|
43
|
+
if (!xFilter || !yFilter) {
|
|
44
|
+
return null;
|
|
45
|
+
}
|
|
46
|
+
const xExtent = convertFilterRangeToExtent(xFilter, xScale);
|
|
47
|
+
const yExtent = convertFilterRangeToExtent(yFilter, yScale);
|
|
48
|
+
if (!xExtent || !yExtent) {
|
|
49
|
+
return null;
|
|
50
|
+
}
|
|
51
|
+
return [
|
|
52
|
+
[xExtent[0], yExtent[1]],
|
|
53
|
+
[xExtent[1], yExtent[0]]
|
|
54
|
+
];
|
|
55
|
+
}
|
|
56
|
+
case "line":
|
|
57
|
+
case "bar": {
|
|
58
|
+
if ("bandwidth" in xScale) {
|
|
59
|
+
return null;
|
|
60
|
+
}
|
|
61
|
+
const rangeFilter = getRangeFilterForField(
|
|
62
|
+
settings.filters,
|
|
63
|
+
settings.type === "line" ? settings.xField : settings.field
|
|
64
|
+
);
|
|
65
|
+
if (!rangeFilter) {
|
|
66
|
+
return null;
|
|
67
|
+
}
|
|
68
|
+
const xExtent = convertFilterRangeToExtent(rangeFilter, xScale);
|
|
69
|
+
if (!xExtent) {
|
|
70
|
+
return null;
|
|
71
|
+
}
|
|
72
|
+
return [
|
|
73
|
+
[xExtent[0], 0],
|
|
74
|
+
[xExtent[1], innerHeight]
|
|
75
|
+
];
|
|
76
|
+
}
|
|
77
|
+
case "row":
|
|
78
|
+
return null;
|
|
79
|
+
}
|
|
80
|
+
}, [settings, xScale, yScale, innerHeight, convertFilterRangeToExtent]);
|
|
81
|
+
return extent;
|
|
82
|
+
}
|
|
83
|
+
function planIdFromTarget(target) {
|
|
84
|
+
if (!(target instanceof Element)) return void 0;
|
|
85
|
+
return target.closest("[data-plan-id]")?.getAttribute("data-plan-id") ?? void 0;
|
|
86
|
+
}
|
|
87
|
+
function BaseChart({
|
|
88
|
+
width,
|
|
89
|
+
height,
|
|
90
|
+
xScale,
|
|
91
|
+
yScale,
|
|
92
|
+
axes: plannedAxes,
|
|
93
|
+
brushingMode = "none",
|
|
94
|
+
onBrushChange,
|
|
95
|
+
children,
|
|
96
|
+
overlay,
|
|
97
|
+
className,
|
|
98
|
+
settings,
|
|
99
|
+
axisFields: axisFieldsOverride,
|
|
100
|
+
xTickFormatter,
|
|
101
|
+
yTickFormatter,
|
|
102
|
+
onInspectGuide,
|
|
103
|
+
onHoverTarget,
|
|
104
|
+
onInspectPlot,
|
|
105
|
+
activeGuideId
|
|
106
|
+
}) {
|
|
107
|
+
const margin = plannedAxes?.margin ?? settings.margin;
|
|
108
|
+
const innerWidth = width - margin.left - margin.right;
|
|
109
|
+
const innerHeight = height - margin.top - margin.bottom;
|
|
110
|
+
const svgRef = useRef(null);
|
|
111
|
+
const [altPointer, setAltPointer] = useState(false);
|
|
112
|
+
const [altHover, setAltHover] = useState(false);
|
|
113
|
+
const chartId = useId();
|
|
114
|
+
const getFieldLabel = useDataLayer((state) => state.getFieldLabel);
|
|
115
|
+
const formatFieldValue = useDataLayer((state) => state.formatFieldValue);
|
|
116
|
+
const fieldSettings = useDataLayer((state) => state.fieldSettings);
|
|
117
|
+
const axisFields = axisFieldsOverride ?? getChartAxisFields(settings);
|
|
118
|
+
const formatAxisValue = (field, override) => override ?? (field && formatFieldValue ? (value) => formatFieldValue(field, value) : formatTick);
|
|
119
|
+
const xLabel = [
|
|
120
|
+
getChartAxisLabel(axisFields.x, settings.xAxisLabel, getFieldLabel),
|
|
121
|
+
settings.xAxis.scaleType === "symlog" && "symlog"
|
|
122
|
+
].filter(Boolean).join(" \xB7 ");
|
|
123
|
+
const yLabel = [
|
|
124
|
+
getChartAxisLabel(axisFields.y, settings.yAxisLabel, getFieldLabel),
|
|
125
|
+
settings.yAxis.scaleType === "symlog" && "symlog"
|
|
126
|
+
].filter(Boolean).join(" \xB7 ");
|
|
127
|
+
const axes = useMemo(
|
|
128
|
+
() => plannedAxes ?? planAxes({
|
|
129
|
+
plotWidth: innerWidth,
|
|
130
|
+
plotHeight: innerHeight,
|
|
131
|
+
margin,
|
|
132
|
+
x: {
|
|
133
|
+
scale: xScale,
|
|
134
|
+
scaleType: settings.xAxis.scaleType,
|
|
135
|
+
field: axisFields.x,
|
|
136
|
+
density: settings.xGridLines,
|
|
137
|
+
grid: settings.xAxis?.grid,
|
|
138
|
+
format: formatAxisValue(axisFields.x, xTickFormatter),
|
|
139
|
+
label: xLabel,
|
|
140
|
+
labelSource: settings.xAxisLabel ? "chart-setting" : "field-label"
|
|
141
|
+
},
|
|
142
|
+
y: {
|
|
143
|
+
scale: yScale,
|
|
144
|
+
scaleType: settings.yAxis.scaleType,
|
|
145
|
+
field: axisFields.y,
|
|
146
|
+
density: settings.yGridLines,
|
|
147
|
+
grid: settings.yAxis?.grid,
|
|
148
|
+
format: formatAxisValue(axisFields.y, yTickFormatter),
|
|
149
|
+
label: yLabel,
|
|
150
|
+
labelSource: settings.yAxisLabel ? "chart-setting" : "field-label"
|
|
151
|
+
}
|
|
152
|
+
}),
|
|
153
|
+
// Formatters read field settings, so they rerun when those change.
|
|
154
|
+
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
155
|
+
[
|
|
156
|
+
plannedAxes,
|
|
157
|
+
innerWidth,
|
|
158
|
+
innerHeight,
|
|
159
|
+
margin,
|
|
160
|
+
xScale,
|
|
161
|
+
yScale,
|
|
162
|
+
settings.xAxis,
|
|
163
|
+
settings.yAxis,
|
|
164
|
+
settings.xGridLines,
|
|
165
|
+
settings.yGridLines,
|
|
166
|
+
settings.xAxisLabel,
|
|
167
|
+
settings.yAxisLabel,
|
|
168
|
+
axisFields.x,
|
|
169
|
+
axisFields.y,
|
|
170
|
+
xLabel,
|
|
171
|
+
yLabel,
|
|
172
|
+
xTickFormatter,
|
|
173
|
+
yTickFormatter,
|
|
174
|
+
fieldSettings
|
|
175
|
+
]
|
|
176
|
+
);
|
|
177
|
+
const descriptionId = `${chartId}-description`;
|
|
178
|
+
const inspectedByBrush = useRef(false);
|
|
179
|
+
const chartTitle = getChartTitle(settings, getFieldLabel);
|
|
180
|
+
const chartDescription = [
|
|
181
|
+
`Interactive ${settings.type} chart.`,
|
|
182
|
+
settings.xAxisLabel && `Horizontal axis: ${settings.xAxisLabel}.`,
|
|
183
|
+
settings.yAxisLabel && `Vertical axis: ${settings.yAxisLabel}.`
|
|
184
|
+
].filter(Boolean).join(" ");
|
|
185
|
+
const xIsLinear = "invert" in xScale;
|
|
186
|
+
const yIsLinear = "invert" in yScale;
|
|
187
|
+
const extent = useFilterExtent({
|
|
188
|
+
settings: xIsLinear && yIsLinear ? settings : { ...settings, filters: [] },
|
|
189
|
+
xScale: xIsLinear ? xScale : scaleLinear().domain([0, 1]).range([0, innerWidth]),
|
|
190
|
+
yScale: yIsLinear ? yScale : scaleLinear().domain([0, 1]).range([0, innerHeight]),
|
|
191
|
+
innerHeight
|
|
192
|
+
});
|
|
193
|
+
const guideAt = (target) => {
|
|
194
|
+
const id = planIdFromTarget(target);
|
|
195
|
+
return id && findAxisGuide(axes, id) ? id : void 0;
|
|
196
|
+
};
|
|
197
|
+
const inspectTarget = (event) => {
|
|
198
|
+
if (!event.altKey || !onInspectGuide) return false;
|
|
199
|
+
const id = guideAt(event.target);
|
|
200
|
+
if (!id) return false;
|
|
201
|
+
onInspectGuide(id);
|
|
202
|
+
return true;
|
|
203
|
+
};
|
|
204
|
+
const inspectPlot = (event) => {
|
|
205
|
+
if (!event.altKey || !onInspectPlot) return false;
|
|
206
|
+
const rect = event.currentTarget.getBoundingClientRect();
|
|
207
|
+
const point = [
|
|
208
|
+
event.clientX - rect.left - margin.left,
|
|
209
|
+
event.clientY - rect.top - margin.top
|
|
210
|
+
];
|
|
211
|
+
if (point[0] < 0 || point[0] > innerWidth || point[1] < 0 || point[1] > innerHeight) {
|
|
212
|
+
return false;
|
|
213
|
+
}
|
|
214
|
+
return onInspectPlot(
|
|
215
|
+
point,
|
|
216
|
+
new DOMRect(event.clientX, event.clientY, 0, 0)
|
|
217
|
+
);
|
|
218
|
+
};
|
|
219
|
+
const brush = useBrush({
|
|
220
|
+
svgRef,
|
|
221
|
+
marginLeft: margin.left,
|
|
222
|
+
marginTop: margin.top,
|
|
223
|
+
innerWidth,
|
|
224
|
+
innerHeight,
|
|
225
|
+
mode: brushingMode,
|
|
226
|
+
onBrushChange,
|
|
227
|
+
onPlotClick: (_, event) => {
|
|
228
|
+
const handled = inspectTarget(event);
|
|
229
|
+
inspectedByBrush.current = handled;
|
|
230
|
+
return event.altKey || handled;
|
|
231
|
+
},
|
|
232
|
+
defaultExtent: extent
|
|
233
|
+
});
|
|
234
|
+
if (width < 1 || height < 1) {
|
|
235
|
+
return null;
|
|
236
|
+
}
|
|
237
|
+
const interactive = Boolean(onInspectGuide);
|
|
238
|
+
return /* @__PURE__ */ jsxs(
|
|
239
|
+
"svg",
|
|
240
|
+
{
|
|
241
|
+
ref: svgRef,
|
|
242
|
+
width,
|
|
243
|
+
height,
|
|
244
|
+
role: "group",
|
|
245
|
+
"aria-label": chartTitle,
|
|
246
|
+
"aria-describedby": descriptionId,
|
|
247
|
+
className: cn("select-none", className),
|
|
248
|
+
style: {
|
|
249
|
+
cursor: altHover ? "pointer" : brush.getCursor(),
|
|
250
|
+
touchAction: brushingMode === "none" ? "auto" : "none"
|
|
251
|
+
},
|
|
252
|
+
tabIndex: brushingMode === "none" ? void 0 : 0,
|
|
253
|
+
onKeyDown: (event) => {
|
|
254
|
+
if (event.key === "Escape") {
|
|
255
|
+
event.stopPropagation();
|
|
256
|
+
brush.clear();
|
|
257
|
+
}
|
|
258
|
+
},
|
|
259
|
+
onPointerDownCapture: (event) => {
|
|
260
|
+
onHoverTarget?.(null);
|
|
261
|
+
setAltHover(false);
|
|
262
|
+
if (interactive && guideAt(event.target)) {
|
|
263
|
+
if (!event.altKey) event.preventDefault();
|
|
264
|
+
else setAltPointer(true);
|
|
265
|
+
return;
|
|
266
|
+
}
|
|
267
|
+
if (interactive && event.altKey) {
|
|
268
|
+
setAltPointer(true);
|
|
269
|
+
return;
|
|
270
|
+
}
|
|
271
|
+
brush.handlePointerDown(event);
|
|
272
|
+
},
|
|
273
|
+
onPointerMoveCapture: (event) => {
|
|
274
|
+
brush.handlePointerMove(event);
|
|
275
|
+
const id = planIdFromTarget(event.target);
|
|
276
|
+
onHoverTarget?.(id ?? null);
|
|
277
|
+
setAltHover(Boolean(event.altKey && interactive && id));
|
|
278
|
+
},
|
|
279
|
+
onPointerUpCapture: brush.handlePointerUp,
|
|
280
|
+
onPointerCancel: () => {
|
|
281
|
+
setAltPointer(false);
|
|
282
|
+
setAltHover(false);
|
|
283
|
+
onHoverTarget?.(null);
|
|
284
|
+
brush.cancel();
|
|
285
|
+
},
|
|
286
|
+
onLostPointerCapture: () => {
|
|
287
|
+
setAltPointer(false);
|
|
288
|
+
setAltHover(false);
|
|
289
|
+
onHoverTarget?.(null);
|
|
290
|
+
brush.cancel();
|
|
291
|
+
},
|
|
292
|
+
onPointerLeave: () => {
|
|
293
|
+
setAltHover(false);
|
|
294
|
+
onHoverTarget?.(null);
|
|
295
|
+
},
|
|
296
|
+
onClick: (event) => {
|
|
297
|
+
if (inspectedByBrush.current) inspectedByBrush.current = false;
|
|
298
|
+
else if (!inspectTarget(event)) inspectPlot(event);
|
|
299
|
+
setAltPointer(false);
|
|
300
|
+
},
|
|
301
|
+
onKeyDownCapture: (event) => {
|
|
302
|
+
if (event.altKey && event.key === "Enter" && inspectTarget(event)) {
|
|
303
|
+
event.preventDefault();
|
|
304
|
+
event.stopPropagation();
|
|
305
|
+
}
|
|
306
|
+
},
|
|
307
|
+
"data-alt-hover": altHover ? "true" : void 0,
|
|
308
|
+
children: [
|
|
309
|
+
/* @__PURE__ */ jsx("desc", { id: descriptionId, children: chartDescription }),
|
|
310
|
+
/* @__PURE__ */ jsx("defs", { children: /* @__PURE__ */ jsx("clipPath", { id: `${chartId}-plot`, children: /* @__PURE__ */ jsx(
|
|
311
|
+
"rect",
|
|
312
|
+
{
|
|
313
|
+
x: 0,
|
|
314
|
+
y: 0,
|
|
315
|
+
width: Math.max(0, innerWidth),
|
|
316
|
+
height: Math.max(0, innerHeight)
|
|
317
|
+
}
|
|
318
|
+
) }) }),
|
|
319
|
+
/* @__PURE__ */ jsxs("g", { transform: `translate(${margin.left},${margin.top})`, children: [
|
|
320
|
+
/* @__PURE__ */ jsx(
|
|
321
|
+
PlannedGrid,
|
|
322
|
+
{
|
|
323
|
+
plan: axes,
|
|
324
|
+
interactive,
|
|
325
|
+
activeId: activeGuideId
|
|
326
|
+
}
|
|
327
|
+
),
|
|
328
|
+
/* @__PURE__ */ jsx("g", { clipPath: `url(#${chartId}-plot)`, children }),
|
|
329
|
+
/* @__PURE__ */ jsx(
|
|
330
|
+
"g",
|
|
331
|
+
{
|
|
332
|
+
clipPath: `url(#${chartId}-plot)`,
|
|
333
|
+
style: { pointerEvents: altPointer ? "none" : void 0 },
|
|
334
|
+
children: brush.renderBrush
|
|
335
|
+
}
|
|
336
|
+
),
|
|
337
|
+
/* @__PURE__ */ jsx(
|
|
338
|
+
PlannedAxes,
|
|
339
|
+
{
|
|
340
|
+
plan: axes,
|
|
341
|
+
interactive,
|
|
342
|
+
activeId: activeGuideId
|
|
343
|
+
}
|
|
344
|
+
),
|
|
345
|
+
overlay
|
|
346
|
+
] })
|
|
347
|
+
]
|
|
348
|
+
}
|
|
349
|
+
);
|
|
350
|
+
}
|
|
351
|
+
|
|
352
|
+
export { BaseChart, formatTick };
|
|
353
|
+
//# sourceMappingURL=chunk-UJWS6TRV.js.map
|
|
354
|
+
//# sourceMappingURL=chunk-UJWS6TRV.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/components/charts/Axis/Axis.tsx","../src/hooks/useFilterExtent.ts","../src/components/charts/BaseChart.tsx"],"names":["useMemo"],"mappings":"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","file":"chunk-UJWS6TRV.js","sourcesContent":["export function formatTick(value: string | number) {\n if (typeof value === \"string\") return value;\n return new Intl.NumberFormat(\"en-US\", {\n notation: Math.abs(value) >= 10000 ? \"compact\" : \"standard\",\n maximumFractionDigits: Math.abs(value) < 1 ? 3 : 2,\n }).format(value);\n}\n","import { ChartSettings } from \"@/types/ChartTypes\";\nimport { ScaleLinear } from \"d3-scale\";\nimport { useCallback, useMemo } from \"react\";\nimport { getRangeFilterForField } from \"./getAxisFilter\";\nimport { RangeFilter } from \"@/types/FilterTypes\";\n\ninterface UseFilterExtentProps {\n settings: ChartSettings;\n xScale: ScaleLinear<number, number>;\n yScale: ScaleLinear<number, number>;\n innerHeight: number;\n}\n\nexport function useFilterExtent({\n settings,\n xScale,\n yScale,\n innerHeight,\n}: UseFilterExtentProps) {\n const convertFilterRangeToExtent = useCallback(\n (filter: RangeFilter, scale: ScaleLinear<number, number>) => {\n if (!filter || filter.min === undefined || filter.max === undefined) {\n return null;\n }\n\n // Round to 4 decimal places to avoid floating point issues\n const min = Math.round(scale(filter.min) * 10000) / 10000;\n const max = Math.round(scale(filter.max) * 10000) / 10000;\n\n return [min, max] as [number, number];\n },\n []\n );\n\n const extent = useMemo(() => {\n switch (settings.type) {\n case \"scatter\": {\n const xFilter = getRangeFilterForField(\n settings.filters,\n settings.xField\n );\n const yFilter = getRangeFilterForField(\n settings.filters,\n settings.yField\n );\n\n if (!xFilter || !yFilter) {\n return null;\n }\n\n const xExtent = convertFilterRangeToExtent(xFilter, xScale);\n const yExtent = convertFilterRangeToExtent(yFilter, yScale);\n\n if (!xExtent || !yExtent) {\n return null;\n }\n\n return [\n [xExtent[0], yExtent[1]],\n [xExtent[1], yExtent[0]],\n ] as [[number, number], [number, number]];\n }\n\n case \"line\":\n case \"bar\": {\n if (\"bandwidth\" in xScale) {\n return null;\n }\n\n const rangeFilter = getRangeFilterForField(\n settings.filters,\n settings.type === \"line\" ? settings.xField : settings.field\n );\n if (!rangeFilter) {\n return null;\n }\n\n const xExtent = convertFilterRangeToExtent(rangeFilter, xScale);\n\n if (!xExtent) {\n return null;\n }\n\n return [\n [xExtent[0], 0],\n [xExtent[1], innerHeight],\n ] as [[number, number], [number, number]];\n }\n\n case \"row\":\n return null;\n }\n }, [settings, xScale, yScale, innerHeight, convertFilterRangeToExtent]);\n\n return extent;\n}\n","import { ReactNode, useId, useMemo, useRef, useState } from \"react\";\nimport { ScaleBand, ScaleLinear, scaleLinear } from \"d3-scale\";\nimport { formatTick } from \"./Axis/Axis\";\nimport { findAxisGuide, planAxes, type ChartAxesPlan } from \"./Axis/axisPlan\";\nimport { PlannedAxes, PlannedGrid } from \"./Axis/AxisLayer\";\nimport { useBrush } from \"@/hooks/useBrush\";\nimport { cn } from \"@/lib/utils\";\nimport { ChartSettings } from \"@/types/ChartTypes\";\nimport { useFilterExtent } from \"@/hooks/useFilterExtent\";\nimport { useDataLayer } from \"@/providers/DataLayerProvider\";\nimport {\n getChartAxisFields,\n getChartAxisLabel,\n getChartTitle,\n} from \"./chartAccessibility\";\n\ntype BrushMode = \"horizontal\" | \"2d\" | \"none\";\n\ninterface BaseChartProps {\n width: number;\n height: number;\n xScale: ScaleLinear<number, number> | ScaleBand<string>;\n yScale: ScaleLinear<number, number> | ScaleBand<string>;\n /** A chart that traces its guides passes its own plan so drawing and tracing agree. */\n axes?: ChartAxesPlan;\n brushingMode?: BrushMode;\n onBrushChange?: (extent: [[number, number], [number, number]] | null) => void;\n children: ReactNode;\n overlay?: ReactNode;\n className?: string;\n settings: ChartSettings;\n axisFields?: { x?: string; y?: string };\n xTickFormatter?: (value: string | number) => string;\n yTickFormatter?: (value: string | number) => string;\n /** Receives the planned id of an Alt-clicked axis guide. */\n onInspectGuide?: (id: string) => void;\n /** Receives the planned id under the pointer, or null. */\n onHoverTarget?: (id: string | null) => void;\n onInspectPlot?: (point: [number, number], anchor: DOMRect) => boolean;\n activeGuideId?: string | null;\n}\n\nfunction planIdFromTarget(target: EventTarget | null) {\n if (!(target instanceof Element)) return undefined;\n return (\n target.closest<SVGElement>(\"[data-plan-id]\")?.getAttribute(\"data-plan-id\") ??\n undefined\n );\n}\n\nexport function BaseChart({\n width,\n height,\n xScale,\n yScale,\n axes: plannedAxes,\n brushingMode = \"none\",\n onBrushChange,\n children,\n overlay,\n className,\n settings,\n axisFields: axisFieldsOverride,\n xTickFormatter,\n yTickFormatter,\n onInspectGuide,\n onHoverTarget,\n onInspectPlot,\n activeGuideId,\n}: BaseChartProps) {\n const margin = plannedAxes?.margin ?? settings.margin;\n\n const innerWidth = width - margin.left - margin.right;\n const innerHeight = height - margin.top - margin.bottom;\n const svgRef = useRef<SVGSVGElement>(null);\n const [altPointer, setAltPointer] = useState(false);\n const [altHover, setAltHover] = useState(false);\n const chartId = useId();\n const getFieldLabel = useDataLayer((state) => state.getFieldLabel);\n const formatFieldValue = useDataLayer((state) => state.formatFieldValue);\n const fieldSettings = useDataLayer((state) => state.fieldSettings);\n const axisFields = axisFieldsOverride ?? getChartAxisFields(settings);\n const formatAxisValue = (\n field: string | undefined,\n override?: (value: string | number) => string\n ) =>\n override ??\n (field && formatFieldValue\n ? (value: string | number) => formatFieldValue(field, value)\n : formatTick);\n const xLabel = [\n getChartAxisLabel(axisFields.x, settings.xAxisLabel, getFieldLabel),\n settings.xAxis.scaleType === \"symlog\" && \"symlog\",\n ]\n .filter(Boolean)\n .join(\" · \");\n const yLabel = [\n getChartAxisLabel(axisFields.y, settings.yAxisLabel, getFieldLabel),\n settings.yAxis.scaleType === \"symlog\" && \"symlog\",\n ]\n .filter(Boolean)\n .join(\" · \");\n // Charts without their own plan still draw from a plan, so axes follow one rule.\n const axes = useMemo(\n () =>\n plannedAxes ??\n planAxes({\n plotWidth: innerWidth,\n plotHeight: innerHeight,\n margin,\n x: {\n scale: xScale,\n scaleType: settings.xAxis.scaleType,\n field: axisFields.x,\n density: settings.xGridLines,\n grid: settings.xAxis?.grid,\n format: formatAxisValue(axisFields.x, xTickFormatter),\n label: xLabel,\n labelSource: settings.xAxisLabel ? \"chart-setting\" : \"field-label\",\n },\n y: {\n scale: yScale,\n scaleType: settings.yAxis.scaleType,\n field: axisFields.y,\n density: settings.yGridLines,\n grid: settings.yAxis?.grid,\n format: formatAxisValue(axisFields.y, yTickFormatter),\n label: yLabel,\n labelSource: settings.yAxisLabel ? \"chart-setting\" : \"field-label\",\n },\n }),\n // Formatters read field settings, so they rerun when those change.\n // eslint-disable-next-line react-hooks/exhaustive-deps\n [\n plannedAxes,\n innerWidth,\n innerHeight,\n margin,\n xScale,\n yScale,\n settings.xAxis,\n settings.yAxis,\n settings.xGridLines,\n settings.yGridLines,\n settings.xAxisLabel,\n settings.yAxisLabel,\n axisFields.x,\n axisFields.y,\n xLabel,\n yLabel,\n xTickFormatter,\n yTickFormatter,\n fieldSettings,\n ]\n );\n const descriptionId = `${chartId}-description`;\n const inspectedByBrush = useRef(false);\n const chartTitle = getChartTitle(settings, getFieldLabel);\n const chartDescription = [\n `Interactive ${settings.type} chart.`,\n settings.xAxisLabel && `Horizontal axis: ${settings.xAxisLabel}.`,\n settings.yAxisLabel && `Vertical axis: ${settings.yAxisLabel}.`,\n ]\n .filter(Boolean)\n .join(\" \");\n const xIsLinear = \"invert\" in xScale;\n const yIsLinear = \"invert\" in yScale;\n const extent = useFilterExtent({\n settings: xIsLinear && yIsLinear ? settings : { ...settings, filters: [] },\n xScale: xIsLinear\n ? xScale\n : scaleLinear().domain([0, 1]).range([0, innerWidth]),\n yScale: yIsLinear\n ? yScale\n : scaleLinear().domain([0, 1]).range([0, innerHeight]),\n innerHeight,\n });\n\n const guideAt = (target: EventTarget | null) => {\n const id = planIdFromTarget(target);\n return id && findAxisGuide(axes, id) ? id : undefined;\n };\n\n const inspectTarget = (event: {\n altKey: boolean;\n target: EventTarget | null;\n }) => {\n if (!event.altKey || !onInspectGuide) return false;\n const id = guideAt(event.target);\n if (!id) return false;\n onInspectGuide(id);\n return true;\n };\n\n const inspectPlot = (event: {\n altKey: boolean;\n clientX: number;\n clientY: number;\n currentTarget: SVGSVGElement;\n }) => {\n if (!event.altKey || !onInspectPlot) return false;\n const rect = event.currentTarget.getBoundingClientRect();\n const point: [number, number] = [\n event.clientX - rect.left - margin.left,\n event.clientY - rect.top - margin.top,\n ];\n if (\n point[0] < 0 ||\n point[0] > innerWidth ||\n point[1] < 0 ||\n point[1] > innerHeight\n ) {\n return false;\n }\n return onInspectPlot(\n point,\n new DOMRect(event.clientX, event.clientY, 0, 0)\n );\n };\n\n const brush = useBrush({\n svgRef,\n marginLeft: margin.left,\n marginTop: margin.top,\n innerWidth,\n innerHeight,\n mode: brushingMode as \"horizontal\" | \"2d\" | \"none\",\n onBrushChange,\n onPlotClick: (_, event) => {\n const handled = inspectTarget(event);\n inspectedByBrush.current = handled;\n return event.altKey || handled;\n },\n defaultExtent: extent,\n });\n\n if (width < 1 || height < 1) {\n return null;\n }\n\n const interactive = Boolean(onInspectGuide);\n\n return (\n <svg\n ref={svgRef}\n width={width}\n height={height}\n role=\"group\"\n aria-label={chartTitle}\n aria-describedby={descriptionId}\n className={cn(\"select-none\", className)}\n style={{\n cursor: altHover ? \"pointer\" : brush.getCursor(),\n touchAction: brushingMode === \"none\" ? \"auto\" : \"none\",\n }}\n tabIndex={brushingMode === \"none\" ? undefined : 0}\n onKeyDown={(event) => {\n if (event.key === \"Escape\") {\n event.stopPropagation();\n brush.clear();\n }\n }}\n onPointerDownCapture={(event) => {\n onHoverTarget?.(null);\n setAltHover(false);\n if (interactive && guideAt(event.target)) {\n // Guide clicks inspect or select the guide. They never start a brush.\n if (!event.altKey) event.preventDefault();\n else setAltPointer(true);\n return;\n }\n // Alt-click is inspection. Do not start a brush gesture that can clear or replace filters.\n if (interactive && event.altKey) {\n setAltPointer(true);\n return;\n }\n brush.handlePointerDown(event);\n }}\n onPointerMoveCapture={(event) => {\n brush.handlePointerMove(event);\n const id = planIdFromTarget(event.target);\n onHoverTarget?.(id ?? null);\n setAltHover(Boolean(event.altKey && interactive && id));\n }}\n onPointerUpCapture={brush.handlePointerUp}\n onPointerCancel={() => {\n setAltPointer(false);\n setAltHover(false);\n onHoverTarget?.(null);\n brush.cancel();\n }}\n onLostPointerCapture={() => {\n setAltPointer(false);\n setAltHover(false);\n onHoverTarget?.(null);\n brush.cancel();\n }}\n onPointerLeave={() => {\n setAltHover(false);\n onHoverTarget?.(null);\n }}\n onClick={(event) => {\n if (inspectedByBrush.current) inspectedByBrush.current = false;\n else if (!inspectTarget(event)) inspectPlot(event);\n setAltPointer(false);\n }}\n onKeyDownCapture={(event) => {\n if (event.altKey && event.key === \"Enter\" && inspectTarget(event)) {\n event.preventDefault();\n event.stopPropagation();\n }\n }}\n data-alt-hover={altHover ? \"true\" : undefined}\n >\n <desc id={descriptionId}>{chartDescription}</desc>\n <defs>\n <clipPath id={`${chartId}-plot`}>\n <rect\n x={0}\n y={0}\n width={Math.max(0, innerWidth)}\n height={Math.max(0, innerHeight)}\n />\n </clipPath>\n </defs>\n <g transform={`translate(${margin.left},${margin.top})`}>\n <PlannedGrid\n plan={axes}\n interactive={interactive}\n activeId={activeGuideId}\n />\n {/* Main content */}\n <g clipPath={`url(#${chartId}-plot)`}>{children}</g>\n\n {/* Brush overlay */}\n <g\n clipPath={`url(#${chartId}-plot)`}\n style={{ pointerEvents: altPointer ? \"none\" : undefined }}\n >\n {brush.renderBrush}\n </g>\n\n <PlannedAxes\n plan={axes}\n interactive={interactive}\n activeId={activeGuideId}\n />\n {overlay}\n </g>\n </svg>\n );\n}\n"]}
|