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,520 @@
1
+ import { scaleSymlog, scaleLinear, scaleBand } from 'd3-scale';
2
+ import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
3
+ import { useRef, useState } from 'react';
4
+
5
+ // src/components/charts/Axis/numericScale.ts
6
+ function numericScale(axis) {
7
+ return axis?.scaleType === "symlog" ? scaleSymlog() : scaleLinear();
8
+ }
9
+ function describeScale(scale, scaleType) {
10
+ if ("bandwidth" in scale) {
11
+ return {
12
+ type: "band",
13
+ domain: scale.domain(),
14
+ range: scale.range(),
15
+ padding: scale.padding()
16
+ };
17
+ }
18
+ return {
19
+ type: scaleType === "symlog" ? "symlog" : "linear",
20
+ domain: scale.domain(),
21
+ range: scale.range()
22
+ };
23
+ }
24
+ function buildScale(descriptor) {
25
+ if (descriptor.type === "band") {
26
+ return scaleBand().domain(descriptor.domain).range(descriptor.range).padding(descriptor.padding);
27
+ }
28
+ return numericScale({ scaleType: descriptor.type }).domain(descriptor.domain).range(descriptor.range);
29
+ }
30
+ var MIN_LABEL_GAP = 8;
31
+ var X_LABEL_CHAR_WIDTH = 6;
32
+ var Y_LABEL_HEIGHT = 12;
33
+ function truncate(text, max) {
34
+ return text.length > max ? `${text.slice(0, max - 1)}\u2026` : text;
35
+ }
36
+ function spacedTicks(ticks, position2, size) {
37
+ let edge = -Infinity;
38
+ return [...ticks].sort((a, b) => position2(a) - position2(b)).filter((tick) => {
39
+ const half = size(tick) / 2;
40
+ if (position2(tick) - half < edge + MIN_LABEL_GAP) return false;
41
+ edge = position2(tick) + half;
42
+ return true;
43
+ });
44
+ }
45
+ function position(scale, tick) {
46
+ return "bandwidth" in scale ? (scale(String(tick)) ?? 0) + scale.bandwidth() / 2 : scale(Number(tick));
47
+ }
48
+ var AXIS_WORD = { x: "Horizontal", y: "Vertical" };
49
+ function planAxis(axis, input, plotWidth, plotHeight, margin) {
50
+ const { scale, format } = input;
51
+ const band = "bandwidth" in scale;
52
+ const requested = Math.max(2, input.density ?? 5);
53
+ const candidates = band ? scale.domain() : scale.ticks(requested);
54
+ const shown = band ? candidates : spacedTicks(
55
+ candidates,
56
+ (tick) => position(scale, tick),
57
+ axis === "x" ? (tick) => format(tick).length * X_LABEL_CHAR_WIDTH : () => Y_LABEL_HEIGHT
58
+ );
59
+ const maxLabelChars = axis === "x" ? band ? Math.max(3, Math.floor(scale.step() / 7)) : 20 : Math.max(5, Math.floor((margin.left - 12 - 4) / 6));
60
+ const word = AXIS_WORD[axis];
61
+ const guides = [];
62
+ if (input.rule !== false) {
63
+ guides.push({
64
+ id: `${axis}:rule`,
65
+ axis,
66
+ role: "rule",
67
+ source: "scale",
68
+ ariaLabel: `${word} axis`,
69
+ line: axis === "x" ? { x1: 0, y1: plotHeight, x2: plotWidth, y2: plotHeight } : { x1: 0, y1: plotHeight, x2: 0, y2: 0 }
70
+ });
71
+ }
72
+ for (const tick of shown) {
73
+ const at = position(scale, tick);
74
+ const fullText = format(tick);
75
+ guides.push({
76
+ id: `${axis}:tick:${String(tick)}`,
77
+ axis,
78
+ role: "tick",
79
+ value: tick,
80
+ source: "scale",
81
+ ariaLabel: `${word} tick ${fullText}`,
82
+ line: axis === "x" ? { x1: at, y1: plotHeight, x2: at, y2: plotHeight + 4 } : void 0,
83
+ label: axis === "x" ? {
84
+ text: truncate(fullText, maxLabelChars),
85
+ fullText,
86
+ x: at,
87
+ y: plotHeight + 17,
88
+ anchor: "middle",
89
+ fontSize: 10
90
+ } : {
91
+ text: truncate(fullText, maxLabelChars),
92
+ fullText,
93
+ x: -9,
94
+ y: at,
95
+ anchor: "end",
96
+ fontSize: 10,
97
+ dy: ".32em"
98
+ }
99
+ });
100
+ }
101
+ if (input.label && !(axis === "y" && band)) {
102
+ guides.push({
103
+ id: `${axis}:label`,
104
+ axis,
105
+ role: "label",
106
+ source: input.labelSource ?? "chart-setting",
107
+ ariaLabel: `${word} axis label ${input.label}`,
108
+ label: axis === "x" ? {
109
+ text: input.label,
110
+ fullText: input.label,
111
+ x: plotWidth / 2,
112
+ y: plotHeight + Math.max(32, margin.bottom - 8),
113
+ anchor: "middle",
114
+ fontSize: 11
115
+ } : {
116
+ text: input.label,
117
+ fullText: input.label,
118
+ x: -plotHeight / 2,
119
+ y: -(margin.left - 12),
120
+ anchor: "middle",
121
+ fontSize: 11,
122
+ rotate: -90
123
+ }
124
+ });
125
+ }
126
+ if (input.zero && !band && Number.isFinite(scale(0))) {
127
+ const at = scale(0);
128
+ guides.push({
129
+ id: `${axis}:zero`,
130
+ axis,
131
+ role: "zero",
132
+ value: 0,
133
+ source: "scale",
134
+ ariaLabel: "Zero baseline",
135
+ line: axis === "y" ? { x1: 0, y1: at, x2: plotWidth, y2: at } : { x1: at, y1: 0, x2: at, y2: plotHeight }
136
+ });
137
+ }
138
+ const gridRequested = input.density || 5;
139
+ const linear = band ? void 0 : scale;
140
+ const gridValues = input.grid && linear ? linear.ticks(gridRequested) : [];
141
+ const gridGuides = gridValues.map((tick) => {
142
+ const at = linear(tick);
143
+ return {
144
+ id: `grid:${axis}:${tick}`,
145
+ axis,
146
+ role: "grid",
147
+ value: tick,
148
+ source: "scale",
149
+ ariaLabel: `${axis === "x" ? "Horizontal" : "Vertical"} grid line ${tick}`,
150
+ line: axis === "x" ? { x1: at, y1: 0, x2: at, y2: plotHeight } : { x1: 0, y1: at, x2: plotWidth, y2: at }
151
+ };
152
+ });
153
+ return {
154
+ axis,
155
+ field: input.field,
156
+ fieldLabel: input.fieldLabel,
157
+ scale: describeScale(scale, input.scaleType),
158
+ labelText: input.label,
159
+ labelSource: input.labelSource,
160
+ ticks: {
161
+ requested,
162
+ candidates,
163
+ shown,
164
+ omitted: candidates.filter((tick) => !shown.includes(tick)),
165
+ minLabelGap: MIN_LABEL_GAP,
166
+ labelSpacing: axis === "x" ? `${X_LABEL_CHAR_WIDTH} px per character` : `${Y_LABEL_HEIGHT} px per label`,
167
+ maxLabelChars
168
+ },
169
+ grid: input.grid && !band ? { requested: gridRequested, values: gridValues } : void 0,
170
+ domainSource: input.domainSource,
171
+ guides,
172
+ gridGuides
173
+ };
174
+ }
175
+ function planAxes({
176
+ x,
177
+ y,
178
+ plotWidth,
179
+ plotHeight,
180
+ margin,
181
+ marginPolicy
182
+ }) {
183
+ return {
184
+ x: planAxis("x", x, plotWidth, plotHeight, margin),
185
+ y: planAxis("y", y, plotWidth, plotHeight, margin),
186
+ plotWidth,
187
+ plotHeight,
188
+ margin,
189
+ marginPolicy
190
+ };
191
+ }
192
+ function planChartMargin({
193
+ margin,
194
+ width,
195
+ yDomain,
196
+ hasXLabel,
197
+ hasYLabel
198
+ }) {
199
+ const labelLeftMargin = Math.max(
200
+ margin.left,
201
+ ...scaleLinear().domain(yDomain).ticks(5).map((tick) => String(tick).length * 7 + (hasYLabel ? 38 : 18))
202
+ );
203
+ const minPlotWidth = Math.min(
204
+ 80,
205
+ Math.max(0, width - margin.left - margin.right)
206
+ );
207
+ const maxLeftMargin = Math.max(0, width - margin.right - minPlotWidth);
208
+ const bottomMargin = Math.max(margin.bottom, hasXLabel ? 46 : 28);
209
+ return {
210
+ margin: {
211
+ ...margin,
212
+ left: Math.min(labelLeftMargin, maxLeftMargin),
213
+ bottom: bottomMargin
214
+ },
215
+ policy: {
216
+ requestedLeftMargin: margin.left,
217
+ labelLeftMargin,
218
+ maxLeftMargin,
219
+ minPlotWidth,
220
+ bottomMargin
221
+ }
222
+ };
223
+ }
224
+ function findAxisGuide(plan, id) {
225
+ for (const axis of [plan.x, plan.y]) {
226
+ const guide = axis.guides.find((item) => item.id === id) ?? axis.gridGuides.find((item) => item.id === id);
227
+ if (guide) return { guide, axis };
228
+ }
229
+ return void 0;
230
+ }
231
+ var GUIDE_DESCRIPTION = "Alt+Enter to inspect";
232
+ var activeLine = { stroke: "var(--primary)", strokeWidth: 2.5 };
233
+ function interactiveProps(guide, interactive) {
234
+ return interactive ? {
235
+ tabIndex: 0,
236
+ role: "button",
237
+ "aria-label": guide.ariaLabel,
238
+ "aria-description": GUIDE_DESCRIPTION
239
+ } : { "aria-label": guide.ariaLabel };
240
+ }
241
+ function GuideShape({
242
+ guide,
243
+ active
244
+ }) {
245
+ const { line, label } = guide;
246
+ return /* @__PURE__ */ jsxs(Fragment, { children: [
247
+ line && /* @__PURE__ */ jsx(
248
+ "line",
249
+ {
250
+ ...line,
251
+ className: "stroke-border",
252
+ style: active ? activeLine : void 0
253
+ }
254
+ ),
255
+ label && /* @__PURE__ */ jsx(
256
+ "text",
257
+ {
258
+ x: label.x,
259
+ y: label.y,
260
+ dy: label.dy,
261
+ transform: label.rotate ? `rotate(${label.rotate})` : void 0,
262
+ textAnchor: label.anchor,
263
+ fontSize: label.fontSize,
264
+ fill: active ? "var(--primary)" : void 0,
265
+ textDecoration: active ? "underline" : void 0,
266
+ "aria-label": label.fullText,
267
+ children: label.text
268
+ }
269
+ )
270
+ ] });
271
+ }
272
+ function PlannedGrid({
273
+ plan,
274
+ interactive = false,
275
+ activeId
276
+ }) {
277
+ const guides = [...plan.x.gridGuides, ...plan.y.gridGuides];
278
+ if (!guides.length) return null;
279
+ return /* @__PURE__ */ jsx(
280
+ "g",
281
+ {
282
+ className: "stroke-border",
283
+ opacity: 0.55,
284
+ pointerEvents: interactive ? void 0 : "none",
285
+ children: guides.map((guide) => /* @__PURE__ */ jsxs("g", { children: [
286
+ /* @__PURE__ */ jsx(
287
+ "line",
288
+ {
289
+ ...guide.line,
290
+ pointerEvents: "none",
291
+ style: guide.id === activeId ? activeLine : void 0
292
+ }
293
+ ),
294
+ interactive && /* @__PURE__ */ jsx(
295
+ "line",
296
+ {
297
+ ...guide.line,
298
+ "data-plan-id": guide.id,
299
+ className: "chart-guide-hit",
300
+ stroke: "transparent",
301
+ strokeWidth: 10,
302
+ pointerEvents: "stroke",
303
+ ...interactiveProps(guide, true)
304
+ }
305
+ )
306
+ ] }, guide.id))
307
+ }
308
+ );
309
+ }
310
+ function PlannedAxes({
311
+ plan,
312
+ interactive = false,
313
+ activeId
314
+ }) {
315
+ return /* @__PURE__ */ jsx(
316
+ "g",
317
+ {
318
+ className: "fill-muted-foreground",
319
+ pointerEvents: interactive ? "auto" : "none",
320
+ children: [...plan.x.guides, ...plan.y.guides].map((guide) => /* @__PURE__ */ jsx(
321
+ "g",
322
+ {
323
+ "data-plan-id": guide.id,
324
+ className: "chart-guide",
325
+ ...interactiveProps(guide, interactive),
326
+ children: /* @__PURE__ */ jsx(GuideShape, { guide, active: guide.id === activeId })
327
+ },
328
+ guide.id
329
+ ))
330
+ }
331
+ );
332
+ }
333
+ var clamp = (value, max) => Math.max(0, Math.min(value, max));
334
+ function useBrush({
335
+ svgRef,
336
+ marginLeft,
337
+ marginTop,
338
+ innerWidth,
339
+ innerHeight,
340
+ mode,
341
+ onBrushChange,
342
+ onPlotClick,
343
+ defaultExtent
344
+ }) {
345
+ const gesture = useRef(null);
346
+ const wasDrag = useRef(false);
347
+ const draftRef = useRef(null);
348
+ const [draft, setDraft] = useState(null);
349
+ const extent = draft ?? defaultExtent;
350
+ const position2 = (event) => {
351
+ const rect = svgRef.current.getBoundingClientRect();
352
+ return [
353
+ event.clientX - rect.left - marginLeft,
354
+ event.clientY - rect.top - marginTop
355
+ ];
356
+ };
357
+ const cancel = () => {
358
+ gesture.current = null;
359
+ draftRef.current = null;
360
+ setDraft(null);
361
+ };
362
+ const clear = () => {
363
+ cancel();
364
+ onBrushChange?.(null);
365
+ };
366
+ const handlePointerDown = (event) => {
367
+ wasDrag.current = false;
368
+ if (mode === "none" || event.button !== 0 || !svgRef.current) return;
369
+ const [x, y] = position2(event);
370
+ if (x < 0 || x > innerWidth || y < 0 || y > innerHeight) return;
371
+ event.stopPropagation();
372
+ event.currentTarget.focus({ preventScroll: true });
373
+ let edges = "";
374
+ let inside = false;
375
+ if (extent) {
376
+ const [[x0, y0], [x1, y1]] = extent;
377
+ inside = x >= x0 - 6 && x <= x1 + 6 && y >= y0 - 6 && y <= y1 + 6;
378
+ if (inside) {
379
+ if (Math.abs(x - x0) < 6) edges += "l";
380
+ else if (Math.abs(x - x1) < 6) edges += "r";
381
+ if (mode === "2d") {
382
+ if (Math.abs(y - y0) < 6) edges += "t";
383
+ else if (Math.abs(y - y1) < 6) edges += "b";
384
+ }
385
+ }
386
+ }
387
+ gesture.current = {
388
+ start: [x, y],
389
+ original: extent ?? null,
390
+ kind: edges ? "resize" : inside ? "move" : "draw",
391
+ edges,
392
+ moved: false
393
+ };
394
+ };
395
+ const handlePointerMove = (event) => {
396
+ const active = gesture.current;
397
+ if (!active || !svgRef.current) return;
398
+ const raw = position2(event);
399
+ if (!active.moved && Math.hypot(raw[0] - active.start[0], raw[1] - active.start[1]) < 3)
400
+ return;
401
+ if (!active.moved) event.currentTarget.setPointerCapture?.(event.pointerId);
402
+ active.moved = true;
403
+ wasDrag.current = true;
404
+ event.preventDefault();
405
+ const x = clamp(raw[0], innerWidth), y = clamp(raw[1], innerHeight);
406
+ let next;
407
+ if (active.kind === "move" && active.original) {
408
+ const [[x0, y0], [x1, y1]] = active.original;
409
+ const left = clamp(x0 + x - active.start[0], innerWidth - (x1 - x0));
410
+ const top = mode === "horizontal" ? 0 : clamp(y0 + y - active.start[1], innerHeight - (y1 - y0));
411
+ next = [
412
+ [left, top],
413
+ [left + x1 - x0, top + y1 - y0]
414
+ ];
415
+ } else if (active.kind === "resize" && active.original) {
416
+ const [[x0, y0], [x1, y1]] = active.original;
417
+ const left = active.edges.includes("l") ? x : x0;
418
+ const right = active.edges.includes("r") ? x : x1;
419
+ const top = active.edges.includes("t") ? y : y0;
420
+ const bottom = active.edges.includes("b") ? y : y1;
421
+ next = [
422
+ [Math.min(left, right), Math.min(top, bottom)],
423
+ [Math.max(left, right), Math.max(top, bottom)]
424
+ ];
425
+ } else {
426
+ next = [
427
+ [
428
+ Math.min(x, active.start[0]),
429
+ mode === "horizontal" ? 0 : Math.min(y, active.start[1])
430
+ ],
431
+ [
432
+ Math.max(x, active.start[0]),
433
+ mode === "horizontal" ? innerHeight : Math.max(y, active.start[1])
434
+ ]
435
+ ];
436
+ }
437
+ draftRef.current = next;
438
+ setDraft(next);
439
+ };
440
+ const handlePointerUp = (event) => {
441
+ const active = gesture.current;
442
+ if (!active) return;
443
+ const next = draftRef.current;
444
+ if (event.currentTarget.hasPointerCapture?.(event.pointerId))
445
+ event.currentTarget.releasePointerCapture(event.pointerId);
446
+ cancel();
447
+ if (!active.moved) {
448
+ if (active.kind === "draw" && !onPlotClick?.(active.start, event))
449
+ onBrushChange?.(null);
450
+ return;
451
+ }
452
+ if (next && next[1][0] - next[0][0] >= 3 && (mode === "horizontal" || next[1][1] - next[0][1] >= 3))
453
+ onBrushChange?.(next);
454
+ else onBrushChange?.(null);
455
+ };
456
+ const renderBrush = extent && mode !== "none" ? /* @__PURE__ */ jsxs("g", { className: "eda-brush", children: [
457
+ /* @__PURE__ */ jsx(
458
+ "rect",
459
+ {
460
+ x: extent[0][0],
461
+ y: extent[0][1],
462
+ width: Math.max(0, extent[1][0] - extent[0][0]),
463
+ height: Math.max(0, extent[1][1] - extent[0][1]),
464
+ fill: "var(--primary)",
465
+ fillOpacity: 0.09,
466
+ stroke: "var(--primary)",
467
+ strokeWidth: 1.25,
468
+ style: { cursor: "move" }
469
+ }
470
+ ),
471
+ [extent[0][0], extent[1][0]].map((x, index) => /* @__PURE__ */ jsx(
472
+ "rect",
473
+ {
474
+ x: x - 2,
475
+ y: (extent[0][1] + extent[1][1]) / 2 - 8,
476
+ width: 4,
477
+ height: 16,
478
+ rx: 2,
479
+ fill: "var(--primary)",
480
+ style: { cursor: "ew-resize" }
481
+ },
482
+ index
483
+ )),
484
+ mode === "2d" && [extent[0][1], extent[1][1]].map((y, index) => /* @__PURE__ */ jsx(
485
+ "rect",
486
+ {
487
+ x: (extent[0][0] + extent[1][0]) / 2 - 8,
488
+ y: y - 2,
489
+ width: 16,
490
+ height: 4,
491
+ rx: 2,
492
+ fill: "var(--primary)",
493
+ style: { cursor: "ns-resize" }
494
+ },
495
+ index
496
+ ))
497
+ ] }) : null;
498
+ return {
499
+ extent,
500
+ handlePointerDown,
501
+ handlePointerMove,
502
+ handlePointerUp,
503
+ cancel,
504
+ clear,
505
+ wasDrag,
506
+ renderBrush,
507
+ getCursor: () => mode === "none" ? "default" : "crosshair"
508
+ };
509
+ }
510
+
511
+ // src/hooks/getAxisFilter.ts
512
+ function getRangeFilterForField(filters, field) {
513
+ return filters.find(
514
+ (f) => f.type === "range" && f.field === field
515
+ );
516
+ }
517
+
518
+ export { PlannedAxes, PlannedGrid, buildScale, describeScale, findAxisGuide, getRangeFilterForField, numericScale, planAxes, planChartMargin, useBrush };
519
+ //# sourceMappingURL=chunk-7PTJNIOD.js.map
520
+ //# sourceMappingURL=chunk-7PTJNIOD.js.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":["position","scaleLinear","jsxs","jsx"],"mappings":"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","file":"chunk-7PTJNIOD.js","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"]}