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.
Files changed (208) hide show
  1. package/README.md +144 -0
  2. package/dist/ExplorEda.cjs +4608 -10858
  3. package/dist/ExplorEda.cjs.map +1 -1
  4. package/dist/ExplorEda.css +2332 -1653
  5. package/dist/ExplorEda.css.map +1 -1
  6. package/dist/ExplorEda.d.cts +125 -278
  7. package/dist/ExplorEda.d.ts +125 -278
  8. package/dist/ExplorEda.js +4521 -10782
  9. package/dist/ExplorEda.js.map +1 -1
  10. package/dist/calculations.cjs +18 -0
  11. package/dist/calculations.cjs.map +1 -0
  12. package/dist/calculations.d.cts +63 -0
  13. package/dist/calculations.d.ts +63 -0
  14. package/dist/calculations.js +3 -0
  15. package/dist/calculations.js.map +1 -0
  16. package/dist/charts/bar.cjs +27 -0
  17. package/dist/charts/bar.cjs.map +1 -0
  18. package/dist/charts/bar.d.cts +2 -0
  19. package/dist/charts/bar.d.ts +2 -0
  20. package/dist/charts/bar.js +18 -0
  21. package/dist/charts/bar.js.map +1 -0
  22. package/dist/charts/box-plot.cjs +26 -0
  23. package/dist/charts/box-plot.cjs.map +1 -0
  24. package/dist/charts/box-plot.d.cts +2 -0
  25. package/dist/charts/box-plot.d.ts +2 -0
  26. package/dist/charts/box-plot.js +17 -0
  27. package/dist/charts/box-plot.js.map +1 -0
  28. package/dist/charts/color-legend.cjs +22 -0
  29. package/dist/charts/color-legend.cjs.map +1 -0
  30. package/dist/charts/color-legend.d.cts +2 -0
  31. package/dist/charts/color-legend.d.ts +2 -0
  32. package/dist/charts/color-legend.js +13 -0
  33. package/dist/charts/color-legend.js.map +1 -0
  34. package/dist/charts/data-table.cjs +22 -0
  35. package/dist/charts/data-table.cjs.map +1 -0
  36. package/dist/charts/data-table.d.cts +2 -0
  37. package/dist/charts/data-table.d.ts +2 -0
  38. package/dist/charts/data-table.js +13 -0
  39. package/dist/charts/data-table.js.map +1 -0
  40. package/dist/charts/line.cjs +30 -0
  41. package/dist/charts/line.cjs.map +1 -0
  42. package/dist/charts/line.d.cts +2 -0
  43. package/dist/charts/line.d.ts +2 -0
  44. package/dist/charts/line.js +17 -0
  45. package/dist/charts/line.js.map +1 -0
  46. package/dist/charts/markdown.cjs +16 -0
  47. package/dist/charts/markdown.cjs.map +1 -0
  48. package/dist/charts/markdown.css +77 -0
  49. package/dist/charts/markdown.css.map +1 -0
  50. package/dist/charts/markdown.d.cts +2 -0
  51. package/dist/charts/markdown.d.ts +2 -0
  52. package/dist/charts/markdown.js +7 -0
  53. package/dist/charts/markdown.js.map +1 -0
  54. package/dist/charts/pivot-table.cjs +23 -0
  55. package/dist/charts/pivot-table.cjs.map +1 -0
  56. package/dist/charts/pivot-table.d.cts +2 -0
  57. package/dist/charts/pivot-table.d.ts +2 -0
  58. package/dist/charts/pivot-table.js +14 -0
  59. package/dist/charts/pivot-table.js.map +1 -0
  60. package/dist/charts/row.cjs +27 -0
  61. package/dist/charts/row.cjs.map +1 -0
  62. package/dist/charts/row.d.cts +6 -0
  63. package/dist/charts/row.d.ts +6 -0
  64. package/dist/charts/row.js +18 -0
  65. package/dist/charts/row.js.map +1 -0
  66. package/dist/charts/scatter.cjs +24 -0
  67. package/dist/charts/scatter.cjs.map +1 -0
  68. package/dist/charts/scatter.d.cts +2 -0
  69. package/dist/charts/scatter.d.ts +2 -0
  70. package/dist/charts/scatter.js +15 -0
  71. package/dist/charts/scatter.js.map +1 -0
  72. package/dist/charts/summary-table.cjs +19 -0
  73. package/dist/charts/summary-table.cjs.map +1 -0
  74. package/dist/charts/summary-table.d.cts +2 -0
  75. package/dist/charts/summary-table.d.ts +2 -0
  76. package/dist/charts/summary-table.js +10 -0
  77. package/dist/charts/summary-table.js.map +1 -0
  78. package/dist/charts/three-d-scatter.cjs +24 -0
  79. package/dist/charts/three-d-scatter.cjs.map +1 -0
  80. package/dist/charts/three-d-scatter.d.cts +6 -0
  81. package/dist/charts/three-d-scatter.d.ts +6 -0
  82. package/dist/charts/three-d-scatter.js +15 -0
  83. package/dist/charts/three-d-scatter.js.map +1 -0
  84. package/dist/chunk-3PGYFLE3.cjs +499 -0
  85. package/dist/chunk-3PGYFLE3.cjs.map +1 -0
  86. package/dist/chunk-4HNDKMWF.js +167 -0
  87. package/dist/chunk-4HNDKMWF.js.map +1 -0
  88. package/dist/chunk-4QNENKTV.cjs +1214 -0
  89. package/dist/chunk-4QNENKTV.cjs.map +1 -0
  90. package/dist/chunk-54M32JJB.js +132 -0
  91. package/dist/chunk-54M32JJB.js.map +1 -0
  92. package/dist/chunk-5B23JVH3.cjs +2238 -0
  93. package/dist/chunk-5B23JVH3.cjs.map +1 -0
  94. package/dist/chunk-5LH6NSNL.js +456 -0
  95. package/dist/chunk-5LH6NSNL.js.map +1 -0
  96. package/dist/chunk-6DOKKCJ5.cjs +313 -0
  97. package/dist/chunk-6DOKKCJ5.cjs.map +1 -0
  98. package/dist/chunk-6HZX5CBT.cjs +1074 -0
  99. package/dist/chunk-6HZX5CBT.cjs.map +1 -0
  100. package/dist/chunk-6U5DOIQM.js +1071 -0
  101. package/dist/chunk-6U5DOIQM.js.map +1 -0
  102. package/dist/chunk-7GBZIK2R.cjs +80 -0
  103. package/dist/chunk-7GBZIK2R.cjs.map +1 -0
  104. package/dist/chunk-7PTJNIOD.js +520 -0
  105. package/dist/chunk-7PTJNIOD.js.map +1 -0
  106. package/dist/chunk-AHZYQ7FN.js +319 -0
  107. package/dist/chunk-AHZYQ7FN.js.map +1 -0
  108. package/dist/chunk-AOODAOL4.cjs +55 -0
  109. package/dist/chunk-AOODAOL4.cjs.map +1 -0
  110. package/dist/chunk-ASKFIRMC.cjs +165 -0
  111. package/dist/chunk-ASKFIRMC.cjs.map +1 -0
  112. package/dist/chunk-B7OQUBH4.cjs +171 -0
  113. package/dist/chunk-B7OQUBH4.cjs.map +1 -0
  114. package/dist/chunk-BIMEHDLB.js +72 -0
  115. package/dist/chunk-BIMEHDLB.js.map +1 -0
  116. package/dist/chunk-C62KHV7S.js +1225 -0
  117. package/dist/chunk-C62KHV7S.js.map +1 -0
  118. package/dist/chunk-C7GQT65O.cjs +1119 -0
  119. package/dist/chunk-C7GQT65O.cjs.map +1 -0
  120. package/dist/chunk-CGDWDV4Z.js +1211 -0
  121. package/dist/chunk-CGDWDV4Z.js.map +1 -0
  122. package/dist/chunk-CJQQFNEY.js +69 -0
  123. package/dist/chunk-CJQQFNEY.js.map +1 -0
  124. package/dist/chunk-DHYLSXNR.js +964 -0
  125. package/dist/chunk-DHYLSXNR.js.map +1 -0
  126. package/dist/chunk-DKFA4KOJ.cjs +87 -0
  127. package/dist/chunk-DKFA4KOJ.cjs.map +1 -0
  128. package/dist/chunk-DS5BS7PP.cjs +357 -0
  129. package/dist/chunk-DS5BS7PP.cjs.map +1 -0
  130. package/dist/chunk-EGMFQSGK.js +909 -0
  131. package/dist/chunk-EGMFQSGK.js.map +1 -0
  132. package/dist/chunk-EU5EFHO5.cjs +53 -0
  133. package/dist/chunk-EU5EFHO5.cjs.map +1 -0
  134. package/dist/chunk-FM46QSDM.js +837 -0
  135. package/dist/chunk-FM46QSDM.js.map +1 -0
  136. package/dist/chunk-GV2LRR32.cjs +843 -0
  137. package/dist/chunk-GV2LRR32.cjs.map +1 -0
  138. package/dist/chunk-H3XKFSA5.cjs +322 -0
  139. package/dist/chunk-H3XKFSA5.cjs.map +1 -0
  140. package/dist/chunk-H5AVMMCE.js +347 -0
  141. package/dist/chunk-H5AVMMCE.js.map +1 -0
  142. package/dist/chunk-JDMUN4VK.cjs +986 -0
  143. package/dist/chunk-JDMUN4VK.cjs.map +1 -0
  144. package/dist/chunk-JNO7OXCC.js +2171 -0
  145. package/dist/chunk-JNO7OXCC.js.map +1 -0
  146. package/dist/chunk-JQMG4ZR7.js +111 -0
  147. package/dist/chunk-JQMG4ZR7.js.map +1 -0
  148. package/dist/chunk-L2Q2R43U.cjs +118 -0
  149. package/dist/chunk-L2Q2R43U.cjs.map +1 -0
  150. package/dist/chunk-LBTZVERO.js +466 -0
  151. package/dist/chunk-LBTZVERO.js.map +1 -0
  152. package/dist/chunk-LUUGGTTK.cjs +1227 -0
  153. package/dist/chunk-LUUGGTTK.cjs.map +1 -0
  154. package/dist/chunk-MEEPH7ZC.cjs +911 -0
  155. package/dist/chunk-MEEPH7ZC.cjs.map +1 -0
  156. package/dist/chunk-MJPDJ5AS.js +184 -0
  157. package/dist/chunk-MJPDJ5AS.js.map +1 -0
  158. package/dist/chunk-MJROUIDZ.cjs +219 -0
  159. package/dist/chunk-MJROUIDZ.cjs.map +1 -0
  160. package/dist/chunk-MUWSBYJS.js +528 -0
  161. package/dist/chunk-MUWSBYJS.js.map +1 -0
  162. package/dist/chunk-NDF5LCST.js +1088 -0
  163. package/dist/chunk-NDF5LCST.js.map +1 -0
  164. package/dist/chunk-NGWTPED4.js +311 -0
  165. package/dist/chunk-NGWTPED4.js.map +1 -0
  166. package/dist/chunk-PP4VCONW.js +739 -0
  167. package/dist/chunk-PP4VCONW.js.map +1 -0
  168. package/dist/chunk-PRMC2A6P.cjs +488 -0
  169. package/dist/chunk-PRMC2A6P.cjs.map +1 -0
  170. package/dist/chunk-PST6UU6S.cjs +742 -0
  171. package/dist/chunk-PST6UU6S.cjs.map +1 -0
  172. package/dist/chunk-Q7LK2UWH.js +33 -0
  173. package/dist/chunk-Q7LK2UWH.js.map +1 -0
  174. package/dist/chunk-SFV5LZPD.js +162 -0
  175. package/dist/chunk-SFV5LZPD.js.map +1 -0
  176. package/dist/chunk-SKXGYJJG.cjs +370 -0
  177. package/dist/chunk-SKXGYJJG.cjs.map +1 -0
  178. package/dist/chunk-SWLNKY6R.js +477 -0
  179. package/dist/chunk-SWLNKY6R.js.map +1 -0
  180. package/dist/chunk-TGVLNHUB.cjs +483 -0
  181. package/dist/chunk-TGVLNHUB.cjs.map +1 -0
  182. package/dist/chunk-TLLRW6S3.js +74 -0
  183. package/dist/chunk-TLLRW6S3.js.map +1 -0
  184. package/dist/chunk-TRAIXZ6M.cjs +140 -0
  185. package/dist/chunk-TRAIXZ6M.cjs.map +1 -0
  186. package/dist/chunk-U74A5VK5.cjs +74 -0
  187. package/dist/chunk-U74A5VK5.cjs.map +1 -0
  188. package/dist/chunk-UAVDLBTA.cjs +74 -0
  189. package/dist/chunk-UAVDLBTA.cjs.map +1 -0
  190. package/dist/chunk-UJWS6TRV.js +354 -0
  191. package/dist/chunk-UJWS6TRV.js.map +1 -0
  192. package/dist/chunk-UUJMUPB3.cjs +531 -0
  193. package/dist/chunk-UUJMUPB3.cjs.map +1 -0
  194. package/dist/chunk-VTKHZIJB.cjs +549 -0
  195. package/dist/chunk-VTKHZIJB.cjs.map +1 -0
  196. package/dist/chunk-YXPAWUXO.js +51 -0
  197. package/dist/chunk-YXPAWUXO.js.map +1 -0
  198. package/dist/chunk-ZD64SCZB.js +80 -0
  199. package/dist/chunk-ZD64SCZB.js.map +1 -0
  200. package/dist/core.cjs +28 -0
  201. package/dist/core.cjs.map +1 -0
  202. package/dist/core.d.cts +22 -0
  203. package/dist/core.d.ts +22 -0
  204. package/dist/core.js +3 -0
  205. package/dist/core.js.map +1 -0
  206. package/dist/dataLayerState-B4XmQjQN.d.cts +258 -0
  207. package/dist/dataLayerState-B4XmQjQN.d.ts +258 -0
  208. package/package.json +32 -52
@@ -0,0 +1,531 @@
1
+ 'use strict';
2
+
3
+ var d3Scale = require('d3-scale');
4
+ var jsxRuntime = require('react/jsx-runtime');
5
+ var react = require('react');
6
+
7
+ // src/components/charts/Axis/numericScale.ts
8
+ function numericScale(axis) {
9
+ return axis?.scaleType === "symlog" ? d3Scale.scaleSymlog() : d3Scale.scaleLinear();
10
+ }
11
+ function describeScale(scale, scaleType) {
12
+ if ("bandwidth" in scale) {
13
+ return {
14
+ type: "band",
15
+ domain: scale.domain(),
16
+ range: scale.range(),
17
+ padding: scale.padding()
18
+ };
19
+ }
20
+ return {
21
+ type: scaleType === "symlog" ? "symlog" : "linear",
22
+ domain: scale.domain(),
23
+ range: scale.range()
24
+ };
25
+ }
26
+ function buildScale(descriptor) {
27
+ if (descriptor.type === "band") {
28
+ return d3Scale.scaleBand().domain(descriptor.domain).range(descriptor.range).padding(descriptor.padding);
29
+ }
30
+ return numericScale({ scaleType: descriptor.type }).domain(descriptor.domain).range(descriptor.range);
31
+ }
32
+ var MIN_LABEL_GAP = 8;
33
+ var X_LABEL_CHAR_WIDTH = 6;
34
+ var Y_LABEL_HEIGHT = 12;
35
+ function truncate(text, max) {
36
+ return text.length > max ? `${text.slice(0, max - 1)}\u2026` : text;
37
+ }
38
+ function spacedTicks(ticks, position2, size) {
39
+ let edge = -Infinity;
40
+ return [...ticks].sort((a, b) => position2(a) - position2(b)).filter((tick) => {
41
+ const half = size(tick) / 2;
42
+ if (position2(tick) - half < edge + MIN_LABEL_GAP) return false;
43
+ edge = position2(tick) + half;
44
+ return true;
45
+ });
46
+ }
47
+ function position(scale, tick) {
48
+ return "bandwidth" in scale ? (scale(String(tick)) ?? 0) + scale.bandwidth() / 2 : scale(Number(tick));
49
+ }
50
+ var AXIS_WORD = { x: "Horizontal", y: "Vertical" };
51
+ function planAxis(axis, input, plotWidth, plotHeight, margin) {
52
+ const { scale, format } = input;
53
+ const band = "bandwidth" in scale;
54
+ const requested = Math.max(2, input.density ?? 5);
55
+ const candidates = band ? scale.domain() : scale.ticks(requested);
56
+ const shown = band ? candidates : spacedTicks(
57
+ candidates,
58
+ (tick) => position(scale, tick),
59
+ axis === "x" ? (tick) => format(tick).length * X_LABEL_CHAR_WIDTH : () => Y_LABEL_HEIGHT
60
+ );
61
+ const maxLabelChars = axis === "x" ? band ? Math.max(3, Math.floor(scale.step() / 7)) : 20 : Math.max(5, Math.floor((margin.left - 12 - 4) / 6));
62
+ const word = AXIS_WORD[axis];
63
+ const guides = [];
64
+ if (input.rule !== false) {
65
+ guides.push({
66
+ id: `${axis}:rule`,
67
+ axis,
68
+ role: "rule",
69
+ source: "scale",
70
+ ariaLabel: `${word} axis`,
71
+ line: axis === "x" ? { x1: 0, y1: plotHeight, x2: plotWidth, y2: plotHeight } : { x1: 0, y1: plotHeight, x2: 0, y2: 0 }
72
+ });
73
+ }
74
+ for (const tick of shown) {
75
+ const at = position(scale, tick);
76
+ const fullText = format(tick);
77
+ guides.push({
78
+ id: `${axis}:tick:${String(tick)}`,
79
+ axis,
80
+ role: "tick",
81
+ value: tick,
82
+ source: "scale",
83
+ ariaLabel: `${word} tick ${fullText}`,
84
+ line: axis === "x" ? { x1: at, y1: plotHeight, x2: at, y2: plotHeight + 4 } : void 0,
85
+ label: axis === "x" ? {
86
+ text: truncate(fullText, maxLabelChars),
87
+ fullText,
88
+ x: at,
89
+ y: plotHeight + 17,
90
+ anchor: "middle",
91
+ fontSize: 10
92
+ } : {
93
+ text: truncate(fullText, maxLabelChars),
94
+ fullText,
95
+ x: -9,
96
+ y: at,
97
+ anchor: "end",
98
+ fontSize: 10,
99
+ dy: ".32em"
100
+ }
101
+ });
102
+ }
103
+ if (input.label && !(axis === "y" && band)) {
104
+ guides.push({
105
+ id: `${axis}:label`,
106
+ axis,
107
+ role: "label",
108
+ source: input.labelSource ?? "chart-setting",
109
+ ariaLabel: `${word} axis label ${input.label}`,
110
+ label: axis === "x" ? {
111
+ text: input.label,
112
+ fullText: input.label,
113
+ x: plotWidth / 2,
114
+ y: plotHeight + Math.max(32, margin.bottom - 8),
115
+ anchor: "middle",
116
+ fontSize: 11
117
+ } : {
118
+ text: input.label,
119
+ fullText: input.label,
120
+ x: -plotHeight / 2,
121
+ y: -(margin.left - 12),
122
+ anchor: "middle",
123
+ fontSize: 11,
124
+ rotate: -90
125
+ }
126
+ });
127
+ }
128
+ if (input.zero && !band && Number.isFinite(scale(0))) {
129
+ const at = scale(0);
130
+ guides.push({
131
+ id: `${axis}:zero`,
132
+ axis,
133
+ role: "zero",
134
+ value: 0,
135
+ source: "scale",
136
+ ariaLabel: "Zero baseline",
137
+ line: axis === "y" ? { x1: 0, y1: at, x2: plotWidth, y2: at } : { x1: at, y1: 0, x2: at, y2: plotHeight }
138
+ });
139
+ }
140
+ const gridRequested = input.density || 5;
141
+ const linear = band ? void 0 : scale;
142
+ const gridValues = input.grid && linear ? linear.ticks(gridRequested) : [];
143
+ const gridGuides = gridValues.map((tick) => {
144
+ const at = linear(tick);
145
+ return {
146
+ id: `grid:${axis}:${tick}`,
147
+ axis,
148
+ role: "grid",
149
+ value: tick,
150
+ source: "scale",
151
+ ariaLabel: `${axis === "x" ? "Horizontal" : "Vertical"} grid line ${tick}`,
152
+ line: axis === "x" ? { x1: at, y1: 0, x2: at, y2: plotHeight } : { x1: 0, y1: at, x2: plotWidth, y2: at }
153
+ };
154
+ });
155
+ return {
156
+ axis,
157
+ field: input.field,
158
+ fieldLabel: input.fieldLabel,
159
+ scale: describeScale(scale, input.scaleType),
160
+ labelText: input.label,
161
+ labelSource: input.labelSource,
162
+ ticks: {
163
+ requested,
164
+ candidates,
165
+ shown,
166
+ omitted: candidates.filter((tick) => !shown.includes(tick)),
167
+ minLabelGap: MIN_LABEL_GAP,
168
+ labelSpacing: axis === "x" ? `${X_LABEL_CHAR_WIDTH} px per character` : `${Y_LABEL_HEIGHT} px per label`,
169
+ maxLabelChars
170
+ },
171
+ grid: input.grid && !band ? { requested: gridRequested, values: gridValues } : void 0,
172
+ domainSource: input.domainSource,
173
+ guides,
174
+ gridGuides
175
+ };
176
+ }
177
+ function planAxes({
178
+ x,
179
+ y,
180
+ plotWidth,
181
+ plotHeight,
182
+ margin,
183
+ marginPolicy
184
+ }) {
185
+ return {
186
+ x: planAxis("x", x, plotWidth, plotHeight, margin),
187
+ y: planAxis("y", y, plotWidth, plotHeight, margin),
188
+ plotWidth,
189
+ plotHeight,
190
+ margin,
191
+ marginPolicy
192
+ };
193
+ }
194
+ function planChartMargin({
195
+ margin,
196
+ width,
197
+ yDomain,
198
+ hasXLabel,
199
+ hasYLabel
200
+ }) {
201
+ const labelLeftMargin = Math.max(
202
+ margin.left,
203
+ ...d3Scale.scaleLinear().domain(yDomain).ticks(5).map((tick) => String(tick).length * 7 + (hasYLabel ? 38 : 18))
204
+ );
205
+ const minPlotWidth = Math.min(
206
+ 80,
207
+ Math.max(0, width - margin.left - margin.right)
208
+ );
209
+ const maxLeftMargin = Math.max(0, width - margin.right - minPlotWidth);
210
+ const bottomMargin = Math.max(margin.bottom, hasXLabel ? 46 : 28);
211
+ return {
212
+ margin: {
213
+ ...margin,
214
+ left: Math.min(labelLeftMargin, maxLeftMargin),
215
+ bottom: bottomMargin
216
+ },
217
+ policy: {
218
+ requestedLeftMargin: margin.left,
219
+ labelLeftMargin,
220
+ maxLeftMargin,
221
+ minPlotWidth,
222
+ bottomMargin
223
+ }
224
+ };
225
+ }
226
+ function findAxisGuide(plan, id) {
227
+ for (const axis of [plan.x, plan.y]) {
228
+ const guide = axis.guides.find((item) => item.id === id) ?? axis.gridGuides.find((item) => item.id === id);
229
+ if (guide) return { guide, axis };
230
+ }
231
+ return void 0;
232
+ }
233
+ var GUIDE_DESCRIPTION = "Alt+Enter to inspect";
234
+ var activeLine = { stroke: "var(--primary)", strokeWidth: 2.5 };
235
+ function interactiveProps(guide, interactive) {
236
+ return interactive ? {
237
+ tabIndex: 0,
238
+ role: "button",
239
+ "aria-label": guide.ariaLabel,
240
+ "aria-description": GUIDE_DESCRIPTION
241
+ } : { "aria-label": guide.ariaLabel };
242
+ }
243
+ function GuideShape({
244
+ guide,
245
+ active
246
+ }) {
247
+ const { line, label } = guide;
248
+ return /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
249
+ line && /* @__PURE__ */ jsxRuntime.jsx(
250
+ "line",
251
+ {
252
+ ...line,
253
+ className: "stroke-border",
254
+ style: active ? activeLine : void 0
255
+ }
256
+ ),
257
+ label && /* @__PURE__ */ jsxRuntime.jsx(
258
+ "text",
259
+ {
260
+ x: label.x,
261
+ y: label.y,
262
+ dy: label.dy,
263
+ transform: label.rotate ? `rotate(${label.rotate})` : void 0,
264
+ textAnchor: label.anchor,
265
+ fontSize: label.fontSize,
266
+ fill: active ? "var(--primary)" : void 0,
267
+ textDecoration: active ? "underline" : void 0,
268
+ "aria-label": label.fullText,
269
+ children: label.text
270
+ }
271
+ )
272
+ ] });
273
+ }
274
+ function PlannedGrid({
275
+ plan,
276
+ interactive = false,
277
+ activeId
278
+ }) {
279
+ const guides = [...plan.x.gridGuides, ...plan.y.gridGuides];
280
+ if (!guides.length) return null;
281
+ return /* @__PURE__ */ jsxRuntime.jsx(
282
+ "g",
283
+ {
284
+ className: "stroke-border",
285
+ opacity: 0.55,
286
+ pointerEvents: interactive ? void 0 : "none",
287
+ children: guides.map((guide) => /* @__PURE__ */ jsxRuntime.jsxs("g", { children: [
288
+ /* @__PURE__ */ jsxRuntime.jsx(
289
+ "line",
290
+ {
291
+ ...guide.line,
292
+ pointerEvents: "none",
293
+ style: guide.id === activeId ? activeLine : void 0
294
+ }
295
+ ),
296
+ interactive && /* @__PURE__ */ jsxRuntime.jsx(
297
+ "line",
298
+ {
299
+ ...guide.line,
300
+ "data-plan-id": guide.id,
301
+ className: "chart-guide-hit",
302
+ stroke: "transparent",
303
+ strokeWidth: 10,
304
+ pointerEvents: "stroke",
305
+ ...interactiveProps(guide, true)
306
+ }
307
+ )
308
+ ] }, guide.id))
309
+ }
310
+ );
311
+ }
312
+ function PlannedAxes({
313
+ plan,
314
+ interactive = false,
315
+ activeId
316
+ }) {
317
+ return /* @__PURE__ */ jsxRuntime.jsx(
318
+ "g",
319
+ {
320
+ className: "fill-muted-foreground",
321
+ pointerEvents: interactive ? "auto" : "none",
322
+ children: [...plan.x.guides, ...plan.y.guides].map((guide) => /* @__PURE__ */ jsxRuntime.jsx(
323
+ "g",
324
+ {
325
+ "data-plan-id": guide.id,
326
+ className: "chart-guide",
327
+ ...interactiveProps(guide, interactive),
328
+ children: /* @__PURE__ */ jsxRuntime.jsx(GuideShape, { guide, active: guide.id === activeId })
329
+ },
330
+ guide.id
331
+ ))
332
+ }
333
+ );
334
+ }
335
+ var clamp = (value, max) => Math.max(0, Math.min(value, max));
336
+ function useBrush({
337
+ svgRef,
338
+ marginLeft,
339
+ marginTop,
340
+ innerWidth,
341
+ innerHeight,
342
+ mode,
343
+ onBrushChange,
344
+ onPlotClick,
345
+ defaultExtent
346
+ }) {
347
+ const gesture = react.useRef(null);
348
+ const wasDrag = react.useRef(false);
349
+ const draftRef = react.useRef(null);
350
+ const [draft, setDraft] = react.useState(null);
351
+ const extent = draft ?? defaultExtent;
352
+ const position2 = (event) => {
353
+ const rect = svgRef.current.getBoundingClientRect();
354
+ return [
355
+ event.clientX - rect.left - marginLeft,
356
+ event.clientY - rect.top - marginTop
357
+ ];
358
+ };
359
+ const cancel = () => {
360
+ gesture.current = null;
361
+ draftRef.current = null;
362
+ setDraft(null);
363
+ };
364
+ const clear = () => {
365
+ cancel();
366
+ onBrushChange?.(null);
367
+ };
368
+ const handlePointerDown = (event) => {
369
+ wasDrag.current = false;
370
+ if (mode === "none" || event.button !== 0 || !svgRef.current) return;
371
+ const [x, y] = position2(event);
372
+ if (x < 0 || x > innerWidth || y < 0 || y > innerHeight) return;
373
+ event.stopPropagation();
374
+ event.currentTarget.focus({ preventScroll: true });
375
+ let edges = "";
376
+ let inside = false;
377
+ if (extent) {
378
+ const [[x0, y0], [x1, y1]] = extent;
379
+ inside = x >= x0 - 6 && x <= x1 + 6 && y >= y0 - 6 && y <= y1 + 6;
380
+ if (inside) {
381
+ if (Math.abs(x - x0) < 6) edges += "l";
382
+ else if (Math.abs(x - x1) < 6) edges += "r";
383
+ if (mode === "2d") {
384
+ if (Math.abs(y - y0) < 6) edges += "t";
385
+ else if (Math.abs(y - y1) < 6) edges += "b";
386
+ }
387
+ }
388
+ }
389
+ gesture.current = {
390
+ start: [x, y],
391
+ original: extent ?? null,
392
+ kind: edges ? "resize" : inside ? "move" : "draw",
393
+ edges,
394
+ moved: false
395
+ };
396
+ };
397
+ const handlePointerMove = (event) => {
398
+ const active = gesture.current;
399
+ if (!active || !svgRef.current) return;
400
+ const raw = position2(event);
401
+ if (!active.moved && Math.hypot(raw[0] - active.start[0], raw[1] - active.start[1]) < 3)
402
+ return;
403
+ if (!active.moved) event.currentTarget.setPointerCapture?.(event.pointerId);
404
+ active.moved = true;
405
+ wasDrag.current = true;
406
+ event.preventDefault();
407
+ const x = clamp(raw[0], innerWidth), y = clamp(raw[1], innerHeight);
408
+ let next;
409
+ if (active.kind === "move" && active.original) {
410
+ const [[x0, y0], [x1, y1]] = active.original;
411
+ const left = clamp(x0 + x - active.start[0], innerWidth - (x1 - x0));
412
+ const top = mode === "horizontal" ? 0 : clamp(y0 + y - active.start[1], innerHeight - (y1 - y0));
413
+ next = [
414
+ [left, top],
415
+ [left + x1 - x0, top + y1 - y0]
416
+ ];
417
+ } else if (active.kind === "resize" && active.original) {
418
+ const [[x0, y0], [x1, y1]] = active.original;
419
+ const left = active.edges.includes("l") ? x : x0;
420
+ const right = active.edges.includes("r") ? x : x1;
421
+ const top = active.edges.includes("t") ? y : y0;
422
+ const bottom = active.edges.includes("b") ? y : y1;
423
+ next = [
424
+ [Math.min(left, right), Math.min(top, bottom)],
425
+ [Math.max(left, right), Math.max(top, bottom)]
426
+ ];
427
+ } else {
428
+ next = [
429
+ [
430
+ Math.min(x, active.start[0]),
431
+ mode === "horizontal" ? 0 : Math.min(y, active.start[1])
432
+ ],
433
+ [
434
+ Math.max(x, active.start[0]),
435
+ mode === "horizontal" ? innerHeight : Math.max(y, active.start[1])
436
+ ]
437
+ ];
438
+ }
439
+ draftRef.current = next;
440
+ setDraft(next);
441
+ };
442
+ const handlePointerUp = (event) => {
443
+ const active = gesture.current;
444
+ if (!active) return;
445
+ const next = draftRef.current;
446
+ if (event.currentTarget.hasPointerCapture?.(event.pointerId))
447
+ event.currentTarget.releasePointerCapture(event.pointerId);
448
+ cancel();
449
+ if (!active.moved) {
450
+ if (active.kind === "draw" && !onPlotClick?.(active.start, event))
451
+ onBrushChange?.(null);
452
+ return;
453
+ }
454
+ if (next && next[1][0] - next[0][0] >= 3 && (mode === "horizontal" || next[1][1] - next[0][1] >= 3))
455
+ onBrushChange?.(next);
456
+ else onBrushChange?.(null);
457
+ };
458
+ const renderBrush = extent && mode !== "none" ? /* @__PURE__ */ jsxRuntime.jsxs("g", { className: "eda-brush", children: [
459
+ /* @__PURE__ */ jsxRuntime.jsx(
460
+ "rect",
461
+ {
462
+ x: extent[0][0],
463
+ y: extent[0][1],
464
+ width: Math.max(0, extent[1][0] - extent[0][0]),
465
+ height: Math.max(0, extent[1][1] - extent[0][1]),
466
+ fill: "var(--primary)",
467
+ fillOpacity: 0.09,
468
+ stroke: "var(--primary)",
469
+ strokeWidth: 1.25,
470
+ style: { cursor: "move" }
471
+ }
472
+ ),
473
+ [extent[0][0], extent[1][0]].map((x, index) => /* @__PURE__ */ jsxRuntime.jsx(
474
+ "rect",
475
+ {
476
+ x: x - 2,
477
+ y: (extent[0][1] + extent[1][1]) / 2 - 8,
478
+ width: 4,
479
+ height: 16,
480
+ rx: 2,
481
+ fill: "var(--primary)",
482
+ style: { cursor: "ew-resize" }
483
+ },
484
+ index
485
+ )),
486
+ mode === "2d" && [extent[0][1], extent[1][1]].map((y, index) => /* @__PURE__ */ jsxRuntime.jsx(
487
+ "rect",
488
+ {
489
+ x: (extent[0][0] + extent[1][0]) / 2 - 8,
490
+ y: y - 2,
491
+ width: 16,
492
+ height: 4,
493
+ rx: 2,
494
+ fill: "var(--primary)",
495
+ style: { cursor: "ns-resize" }
496
+ },
497
+ index
498
+ ))
499
+ ] }) : null;
500
+ return {
501
+ extent,
502
+ handlePointerDown,
503
+ handlePointerMove,
504
+ handlePointerUp,
505
+ cancel,
506
+ clear,
507
+ wasDrag,
508
+ renderBrush,
509
+ getCursor: () => mode === "none" ? "default" : "crosshair"
510
+ };
511
+ }
512
+
513
+ // src/hooks/getAxisFilter.ts
514
+ function getRangeFilterForField(filters, field) {
515
+ return filters.find(
516
+ (f) => f.type === "range" && f.field === field
517
+ );
518
+ }
519
+
520
+ exports.PlannedAxes = PlannedAxes;
521
+ exports.PlannedGrid = PlannedGrid;
522
+ exports.buildScale = buildScale;
523
+ exports.describeScale = describeScale;
524
+ exports.findAxisGuide = findAxisGuide;
525
+ exports.getRangeFilterForField = getRangeFilterForField;
526
+ exports.numericScale = numericScale;
527
+ exports.planAxes = planAxes;
528
+ exports.planChartMargin = planChartMargin;
529
+ exports.useBrush = useBrush;
530
+ //# sourceMappingURL=chunk-UUJMUPB3.cjs.map
531
+ //# sourceMappingURL=chunk-UUJMUPB3.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/components/charts/Axis/numericScale.ts","../src/components/charts/Axis/axisPlan.ts","../src/components/charts/Axis/AxisLayer.tsx","../src/hooks/useBrush.tsx","../src/hooks/getAxisFilter.ts"],"names":["scaleSymlog","scaleLinear","scaleBand","position","jsxs","Fragment","jsx","useRef","useState"],"mappings":"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","file":"chunk-UUJMUPB3.cjs","sourcesContent":["import { scaleLinear, scaleSymlog, type ScaleLinear } from \"d3-scale\";\nimport type { AxisSettings } from \"@/types/ChartTypes\";\n\nexport function numericScale(axis?: AxisSettings): ScaleLinear<number, number> {\n return (\n axis?.scaleType === \"symlog\" ? scaleSymlog() : scaleLinear()\n ) as ScaleLinear<number, number>;\n}\n","import {\n scaleBand,\n scaleLinear,\n type ScaleBand,\n type ScaleLinear,\n} from \"d3-scale\";\nimport type { MarginSettings } from \"@/types/ChartTypes\";\nimport { numericScale } from \"./numericScale\";\n\nexport type AxisName = \"x\" | \"y\";\nexport type ChartScale = ScaleLinear<number, number> | ScaleBand<string>;\n\nexport type ScaleDescriptor =\n | {\n type: \"band\";\n domain: string[];\n range: [number, number];\n padding: number;\n }\n | {\n type: \"linear\" | \"symlog\";\n domain: [number, number];\n range: [number, number];\n };\n\n/** Records a D3 scale so a trace can show it and a renderer can rebuild it. */\nexport function describeScale(\n scale: ChartScale,\n scaleType?: string\n): ScaleDescriptor {\n if (\"bandwidth\" in scale) {\n return {\n type: \"band\",\n domain: scale.domain(),\n range: scale.range() as [number, number],\n padding: scale.padding(),\n };\n }\n return {\n type: scaleType === \"symlog\" ? \"symlog\" : \"linear\",\n domain: scale.domain() as [number, number],\n range: scale.range() as [number, number],\n };\n}\n\nexport function buildScale(descriptor: ScaleDescriptor): ChartScale {\n if (descriptor.type === \"band\") {\n return scaleBand<string>()\n .domain(descriptor.domain)\n .range(descriptor.range)\n .padding(descriptor.padding);\n }\n return numericScale({ scaleType: descriptor.type })\n .domain(descriptor.domain)\n .range(descriptor.range);\n}\n\nexport type GuideRole = \"rule\" | \"tick\" | \"grid\" | \"label\" | \"zero\";\nexport type GuideSource = \"scale\" | \"chart-setting\" | \"field-label\";\n\nexport interface GuideLine {\n x1: number;\n y1: number;\n x2: number;\n y2: number;\n}\n\nexport interface GuideText {\n text: string;\n fullText: string;\n x: number;\n y: number;\n anchor: \"start\" | \"middle\" | \"end\";\n fontSize: number;\n dy?: string;\n rotate?: number;\n}\n\n/** One selectable axis object in plot coordinates. */\nexport interface AxisGuide {\n id: string;\n axis: AxisName;\n role: GuideRole;\n value?: number | string;\n source: GuideSource;\n ariaLabel: string;\n line?: GuideLine;\n label?: GuideText;\n}\n\nexport interface AxisDomainSource {\n /** Which rows set the domain, in words a reader can check. */\n population: string;\n rows: number;\n bounds: [number, number];\n padding: string;\n lower?: { label: string; value: number };\n upper?: { label: string; value: number };\n}\n\nexport interface AxisPlan {\n axis: AxisName;\n field?: string;\n fieldLabel?: string;\n scale: ScaleDescriptor;\n labelText?: string;\n labelSource?: GuideSource;\n ticks: {\n requested: number;\n candidates: (number | string)[];\n shown: (number | string)[];\n omitted: (number | string)[];\n minLabelGap: number;\n labelSpacing: string;\n maxLabelChars: number;\n };\n grid?: { requested: number; values: number[] };\n domainSource?: AxisDomainSource;\n guides: AxisGuide[];\n gridGuides: AxisGuide[];\n}\n\nexport interface MarginPolicy {\n requestedLeftMargin: number;\n labelLeftMargin: number;\n maxLeftMargin: number;\n minPlotWidth: number;\n bottomMargin: number;\n}\n\nexport interface ChartAxesPlan {\n x: AxisPlan;\n y: AxisPlan;\n plotWidth: number;\n plotHeight: number;\n margin: MarginSettings;\n marginPolicy?: MarginPolicy;\n}\n\nexport interface AxisInput {\n scale: ChartScale;\n scaleType?: string;\n field?: string;\n fieldLabel?: string;\n /** Tick density from the chart setting. Undefined uses 5. */\n density?: number;\n grid?: boolean;\n format: (value: string | number) => string;\n label?: string;\n labelSource?: GuideSource;\n rule?: boolean;\n zero?: boolean;\n domainSource?: AxisDomainSource;\n}\n\nconst MIN_LABEL_GAP = 8;\nconst X_LABEL_CHAR_WIDTH = 6;\nconst Y_LABEL_HEIGHT = 12;\n\nfunction truncate(text: string, max: number) {\n return text.length > max ? `${text.slice(0, max - 1)}…` : text;\n}\n\n/** Keeps label order by position and drops a label that would overlap the last kept one. */\nfunction spacedTicks<T extends number | string>(\n ticks: T[],\n position: (tick: T) => number,\n size: (tick: T) => number\n) {\n let edge = -Infinity;\n return [...ticks]\n .sort((a, b) => position(a) - position(b))\n .filter((tick) => {\n const half = size(tick) / 2;\n if (position(tick) - half < edge + MIN_LABEL_GAP) return false;\n edge = position(tick) + half;\n return true;\n });\n}\n\nfunction position(scale: ChartScale, tick: number | string) {\n return \"bandwidth\" in scale\n ? (scale(String(tick)) ?? 0) + scale.bandwidth() / 2\n : scale(Number(tick));\n}\n\nconst AXIS_WORD = { x: \"Horizontal\", y: \"Vertical\" } as const;\n\nfunction planAxis(\n axis: AxisName,\n input: AxisInput,\n plotWidth: number,\n plotHeight: number,\n margin: MarginSettings\n): AxisPlan {\n const { scale, format } = input;\n const band = \"bandwidth\" in scale;\n // Density sets the D3 candidate target. Spacing then drops overlapping labels.\n const requested = Math.max(2, input.density ?? 5);\n const candidates: (number | string)[] = band\n ? scale.domain()\n : scale.ticks(requested);\n const shown = band\n ? candidates\n : spacedTicks(\n candidates,\n (tick) => position(scale, tick),\n axis === \"x\"\n ? (tick) => format(tick).length * X_LABEL_CHAR_WIDTH\n : () => Y_LABEL_HEIGHT\n );\n const maxLabelChars =\n axis === \"x\"\n ? band\n ? Math.max(3, Math.floor(scale.step() / 7))\n : 20\n : Math.max(5, Math.floor((margin.left - 12 - 4) / 6));\n const word = AXIS_WORD[axis];\n const guides: AxisGuide[] = [];\n if (input.rule !== false) {\n guides.push({\n id: `${axis}:rule`,\n axis,\n role: \"rule\",\n source: \"scale\",\n ariaLabel: `${word} axis`,\n line:\n axis === \"x\"\n ? { x1: 0, y1: plotHeight, x2: plotWidth, y2: plotHeight }\n : { x1: 0, y1: plotHeight, x2: 0, y2: 0 },\n });\n }\n for (const tick of shown) {\n const at = position(scale, tick);\n const fullText = format(tick);\n guides.push({\n id: `${axis}:tick:${String(tick)}`,\n axis,\n role: \"tick\",\n value: tick,\n source: \"scale\",\n ariaLabel: `${word} tick ${fullText}`,\n line:\n axis === \"x\"\n ? { x1: at, y1: plotHeight, x2: at, y2: plotHeight + 4 }\n : undefined,\n label:\n axis === \"x\"\n ? {\n text: truncate(fullText, maxLabelChars),\n fullText,\n x: at,\n y: plotHeight + 17,\n anchor: \"middle\",\n fontSize: 10,\n }\n : {\n text: truncate(fullText, maxLabelChars),\n fullText,\n x: -9,\n y: at,\n anchor: \"end\",\n fontSize: 10,\n dy: \".32em\",\n },\n });\n }\n // A band Y axis names its categories in the tick labels, so it has no title.\n if (input.label && !(axis === \"y\" && band)) {\n guides.push({\n id: `${axis}:label`,\n axis,\n role: \"label\",\n source: input.labelSource ?? \"chart-setting\",\n ariaLabel: `${word} axis label ${input.label}`,\n label:\n axis === \"x\"\n ? {\n text: input.label,\n fullText: input.label,\n x: plotWidth / 2,\n y: plotHeight + Math.max(32, margin.bottom - 8),\n anchor: \"middle\",\n fontSize: 11,\n }\n : {\n text: input.label,\n fullText: input.label,\n x: -plotHeight / 2,\n y: -(margin.left - 12),\n anchor: \"middle\",\n fontSize: 11,\n rotate: -90,\n },\n });\n }\n if (input.zero && !band && Number.isFinite(scale(0))) {\n const at = scale(0);\n guides.push({\n id: `${axis}:zero`,\n axis,\n role: \"zero\",\n value: 0,\n source: \"scale\",\n ariaLabel: \"Zero baseline\",\n line:\n axis === \"y\"\n ? { x1: 0, y1: at, x2: plotWidth, y2: at }\n : { x1: at, y1: 0, x2: at, y2: plotHeight },\n });\n }\n const gridRequested = input.density || 5;\n const linear = band ? undefined : scale;\n const gridValues = input.grid && linear ? linear.ticks(gridRequested) : [];\n const gridGuides = gridValues.map((tick): AxisGuide => {\n const at = linear!(tick);\n return {\n id: `grid:${axis}:${tick}`,\n axis,\n role: \"grid\",\n value: tick,\n source: \"scale\",\n ariaLabel: `${axis === \"x\" ? \"Horizontal\" : \"Vertical\"} grid line ${tick}`,\n line:\n axis === \"x\"\n ? { x1: at, y1: 0, x2: at, y2: plotHeight }\n : { x1: 0, y1: at, x2: plotWidth, y2: at },\n };\n });\n return {\n axis,\n field: input.field,\n fieldLabel: input.fieldLabel,\n scale: describeScale(scale, input.scaleType),\n labelText: input.label,\n labelSource: input.labelSource,\n ticks: {\n requested,\n candidates,\n shown,\n omitted: candidates.filter((tick) => !shown.includes(tick)),\n minLabelGap: MIN_LABEL_GAP,\n labelSpacing:\n axis === \"x\"\n ? `${X_LABEL_CHAR_WIDTH} px per character`\n : `${Y_LABEL_HEIGHT} px per label`,\n maxLabelChars,\n },\n grid: input.grid && !band ? { requested: gridRequested, values: gridValues } : undefined,\n domainSource: input.domainSource,\n guides,\n gridGuides,\n };\n}\n\n/** Plans both axes and their grid lines. Drawing and tracing read the same objects. */\nexport function planAxes({\n x,\n y,\n plotWidth,\n plotHeight,\n margin,\n marginPolicy,\n}: {\n x: AxisInput;\n y: AxisInput;\n plotWidth: number;\n plotHeight: number;\n margin: MarginSettings;\n marginPolicy?: MarginPolicy;\n}): ChartAxesPlan {\n return {\n x: planAxis(\"x\", x, plotWidth, plotHeight, margin),\n y: planAxis(\"y\", y, plotWidth, plotHeight, margin),\n plotWidth,\n plotHeight,\n margin,\n marginPolicy,\n };\n}\n\n/** Widens the left margin for Y labels while keeping a minimum plot width. */\nexport function planChartMargin({\n margin,\n width,\n yDomain,\n hasXLabel,\n hasYLabel,\n}: {\n margin: MarginSettings;\n width: number;\n yDomain: [number, number];\n hasXLabel: boolean;\n hasYLabel: boolean;\n}): { margin: MarginSettings; policy: MarginPolicy } {\n const labelLeftMargin = Math.max(\n margin.left,\n ...scaleLinear()\n .domain(yDomain)\n .ticks(5)\n .map((tick) => String(tick).length * 7 + (hasYLabel ? 38 : 18))\n );\n const minPlotWidth = Math.min(\n 80,\n Math.max(0, width - margin.left - margin.right)\n );\n const maxLeftMargin = Math.max(0, width - margin.right - minPlotWidth);\n const bottomMargin = Math.max(margin.bottom, hasXLabel ? 46 : 28);\n return {\n margin: {\n ...margin,\n left: Math.min(labelLeftMargin, maxLeftMargin),\n bottom: bottomMargin,\n },\n policy: {\n requestedLeftMargin: margin.left,\n labelLeftMargin,\n maxLeftMargin,\n minPlotWidth,\n bottomMargin,\n },\n };\n}\n\nexport function axisGuides(plan: ChartAxesPlan): AxisGuide[] {\n return [\n ...plan.x.gridGuides,\n ...plan.y.gridGuides,\n ...plan.x.guides,\n ...plan.y.guides,\n ];\n}\n\nexport function findAxisGuide(plan: ChartAxesPlan, id: string) {\n for (const axis of [plan.x, plan.y]) {\n const guide =\n axis.guides.find((item) => item.id === id) ??\n axis.gridGuides.find((item) => item.id === id);\n if (guide) return { guide, axis };\n }\n return undefined;\n}\n","import type { AxisGuide, ChartAxesPlan } from \"./axisPlan\";\n\nconst GUIDE_DESCRIPTION = \"Alt+Enter to inspect\";\n\nconst activeLine = { stroke: \"var(--primary)\", strokeWidth: 2.5 };\n\nfunction interactiveProps(guide: AxisGuide, interactive: boolean) {\n return interactive\n ? {\n tabIndex: 0,\n role: \"button\" as const,\n \"aria-label\": guide.ariaLabel,\n \"aria-description\": GUIDE_DESCRIPTION,\n }\n : { \"aria-label\": guide.ariaLabel };\n}\n\nfunction GuideShape({\n guide,\n active,\n}: {\n guide: AxisGuide;\n active: boolean;\n}) {\n const { line, label } = guide;\n return (\n <>\n {line && (\n <line\n {...line}\n className=\"stroke-border\"\n style={active ? activeLine : undefined}\n />\n )}\n {label && (\n <text\n x={label.x}\n y={label.y}\n dy={label.dy}\n transform={label.rotate ? `rotate(${label.rotate})` : undefined}\n textAnchor={label.anchor}\n fontSize={label.fontSize}\n fill={active ? \"var(--primary)\" : undefined}\n textDecoration={active ? \"underline\" : undefined}\n aria-label={label.fullText}\n >\n {label.text}\n </text>\n )}\n </>\n );\n}\n\n/** Draws planned grid lines. Place it inside the plot clip. */\nexport function PlannedGrid({\n plan,\n interactive = false,\n activeId,\n}: {\n plan: ChartAxesPlan;\n interactive?: boolean;\n activeId?: string | null;\n}) {\n const guides = [...plan.x.gridGuides, ...plan.y.gridGuides];\n if (!guides.length) return null;\n return (\n <g\n className=\"stroke-border\"\n opacity={0.55}\n pointerEvents={interactive ? undefined : \"none\"}\n >\n {guides.map((guide) => (\n <g key={guide.id}>\n <line\n {...guide.line}\n pointerEvents=\"none\"\n style={guide.id === activeId ? activeLine : undefined}\n />\n {interactive && (\n <line\n {...guide.line}\n data-plan-id={guide.id}\n className=\"chart-guide-hit\"\n stroke=\"transparent\"\n strokeWidth={10}\n pointerEvents=\"stroke\"\n {...interactiveProps(guide, true)}\n />\n )}\n </g>\n ))}\n </g>\n );\n}\n\n/** Draws planned axis rules, ticks, labels and the zero line. */\nexport function PlannedAxes({\n plan,\n interactive = false,\n activeId,\n}: {\n plan: ChartAxesPlan;\n interactive?: boolean;\n activeId?: string | null;\n}) {\n return (\n <g\n className=\"fill-muted-foreground\"\n pointerEvents={interactive ? \"auto\" : \"none\"}\n >\n {[...plan.x.guides, ...plan.y.guides].map((guide) => (\n <g\n key={guide.id}\n data-plan-id={guide.id}\n className=\"chart-guide\"\n {...interactiveProps(guide, interactive)}\n >\n <GuideShape guide={guide} active={guide.id === activeId} />\n </g>\n ))}\n </g>\n );\n}\n","import { PointerEvent, RefObject, useRef, useState } from \"react\";\n\ntype Extent = [[number, number], [number, number]];\ntype Point = [number, number];\ninterface Options {\n svgRef: RefObject<SVGSVGElement | null>;\n marginLeft: number;\n marginTop: number;\n innerWidth: number;\n innerHeight: number;\n mode: \"horizontal\" | \"2d\" | \"none\";\n onBrushChange?: (extent: Extent | null) => void;\n onPlotClick?: (point: Point, event: PointerEvent<SVGSVGElement>) => boolean;\n defaultExtent?: Extent | null;\n}\ninterface Gesture {\n start: Point;\n original: Extent | null;\n kind: \"draw\" | \"move\" | \"resize\";\n edges: string;\n moved: boolean;\n}\nconst clamp = (value: number, max: number) => Math.max(0, Math.min(value, max));\n\nexport function useBrush({\n svgRef,\n marginLeft,\n marginTop,\n innerWidth,\n innerHeight,\n mode,\n onBrushChange,\n onPlotClick,\n defaultExtent,\n}: Options) {\n const gesture = useRef<Gesture | null>(null);\n const wasDrag = useRef(false);\n const draftRef = useRef<Extent | null>(null);\n const [draft, setDraft] = useState<Extent | null>(null);\n // External selections only supply the resting state. They never interrupt a gesture.\n const extent = draft ?? defaultExtent;\n const position = (event: PointerEvent): Point => {\n const rect = svgRef.current!.getBoundingClientRect();\n return [\n event.clientX - rect.left - marginLeft,\n event.clientY - rect.top - marginTop,\n ];\n };\n const cancel = () => {\n gesture.current = null;\n draftRef.current = null;\n setDraft(null);\n };\n const clear = () => {\n cancel();\n onBrushChange?.(null);\n };\n\n const handlePointerDown = (event: PointerEvent<SVGSVGElement>) => {\n wasDrag.current = false;\n if (mode === \"none\" || event.button !== 0 || !svgRef.current) return;\n const [x, y] = position(event);\n if (x < 0 || x > innerWidth || y < 0 || y > innerHeight) return;\n event.stopPropagation();\n event.currentTarget.focus({ preventScroll: true });\n let edges = \"\";\n let inside = false;\n if (extent) {\n const [[x0, y0], [x1, y1]] = extent;\n inside = x >= x0 - 6 && x <= x1 + 6 && y >= y0 - 6 && y <= y1 + 6;\n if (inside) {\n if (Math.abs(x - x0) < 6) edges += \"l\";\n else if (Math.abs(x - x1) < 6) edges += \"r\";\n if (mode === \"2d\") {\n if (Math.abs(y - y0) < 6) edges += \"t\";\n else if (Math.abs(y - y1) < 6) edges += \"b\";\n }\n }\n }\n gesture.current = {\n start: [x, y],\n original: extent ?? null,\n kind: edges ? \"resize\" : inside ? \"move\" : \"draw\",\n edges,\n moved: false,\n };\n };\n\n const handlePointerMove = (event: PointerEvent<SVGSVGElement>) => {\n const active = gesture.current;\n if (!active || !svgRef.current) return;\n const raw = position(event);\n if (\n !active.moved &&\n Math.hypot(raw[0] - active.start[0], raw[1] - active.start[1]) < 3\n )\n return;\n // Capture only a confirmed drag so clicks on marks keep their original target.\n if (!active.moved) event.currentTarget.setPointerCapture?.(event.pointerId);\n active.moved = true;\n wasDrag.current = true;\n event.preventDefault();\n const x = clamp(raw[0], innerWidth),\n y = clamp(raw[1], innerHeight);\n let next: Extent;\n if (active.kind === \"move\" && active.original) {\n const [[x0, y0], [x1, y1]] = active.original;\n const left = clamp(x0 + x - active.start[0], innerWidth - (x1 - x0));\n const top =\n mode === \"horizontal\"\n ? 0\n : clamp(y0 + y - active.start[1], innerHeight - (y1 - y0));\n next = [\n [left, top],\n [left + x1 - x0, top + y1 - y0],\n ];\n } else if (active.kind === \"resize\" && active.original) {\n const [[x0, y0], [x1, y1]] = active.original;\n const left = active.edges.includes(\"l\") ? x : x0;\n const right = active.edges.includes(\"r\") ? x : x1;\n const top = active.edges.includes(\"t\") ? y : y0;\n const bottom = active.edges.includes(\"b\") ? y : y1;\n next = [\n [Math.min(left, right), Math.min(top, bottom)],\n [Math.max(left, right), Math.max(top, bottom)],\n ];\n } else {\n next = [\n [\n Math.min(x, active.start[0]),\n mode === \"horizontal\" ? 0 : Math.min(y, active.start[1]),\n ],\n [\n Math.max(x, active.start[0]),\n mode === \"horizontal\" ? innerHeight : Math.max(y, active.start[1]),\n ],\n ];\n }\n draftRef.current = next;\n setDraft(next);\n };\n\n const handlePointerUp = (event: PointerEvent<SVGSVGElement>) => {\n const active = gesture.current;\n if (!active) return;\n const next = draftRef.current;\n if (event.currentTarget.hasPointerCapture?.(event.pointerId))\n event.currentTarget.releasePointerCapture(event.pointerId);\n cancel();\n if (!active.moved) {\n if (active.kind === \"draw\" && !onPlotClick?.(active.start, event))\n onBrushChange?.(null);\n return;\n }\n if (\n next &&\n next[1][0] - next[0][0] >= 3 &&\n (mode === \"horizontal\" || next[1][1] - next[0][1] >= 3)\n )\n onBrushChange?.(next);\n else onBrushChange?.(null);\n };\n\n const renderBrush =\n extent && mode !== \"none\" ? (\n <g className=\"eda-brush\">\n <rect\n x={extent[0][0]}\n y={extent[0][1]}\n width={Math.max(0, extent[1][0] - extent[0][0])}\n height={Math.max(0, extent[1][1] - extent[0][1])}\n fill=\"var(--primary)\"\n fillOpacity={0.09}\n stroke=\"var(--primary)\"\n strokeWidth={1.25}\n style={{ cursor: \"move\" }}\n />\n {[extent[0][0], extent[1][0]].map((x, index) => (\n <rect\n key={index}\n x={x - 2}\n y={(extent[0][1] + extent[1][1]) / 2 - 8}\n width={4}\n height={16}\n rx={2}\n fill=\"var(--primary)\"\n style={{ cursor: \"ew-resize\" }}\n />\n ))}\n {mode === \"2d\" &&\n [extent[0][1], extent[1][1]].map((y, index) => (\n <rect\n key={index}\n x={(extent[0][0] + extent[1][0]) / 2 - 8}\n y={y - 2}\n width={16}\n height={4}\n rx={2}\n fill=\"var(--primary)\"\n style={{ cursor: \"ns-resize\" }}\n />\n ))}\n </g>\n ) : null;\n return {\n extent,\n handlePointerDown,\n handlePointerMove,\n handlePointerUp,\n cancel,\n clear,\n wasDrag,\n renderBrush,\n getCursor: () => (mode === \"none\" ? \"default\" : \"crosshair\"),\n };\n}\n","import { Filter, RangeFilter } from \"@/types/FilterTypes\";\n\nexport function getRangeFilterForField(\n filters: Filter[],\n field: string\n): RangeFilter | undefined {\n return filters.find(\n (f): f is RangeFilter => f.type === \"range\" && f.field === field\n );\n}\n"]}