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,986 @@
1
+ 'use strict';
2
+
3
+ var chunkTRAIXZ6M_cjs = require('./chunk-TRAIXZ6M.cjs');
4
+ var chunkB7OQUBH4_cjs = require('./chunk-B7OQUBH4.cjs');
5
+ var chunkU74A5VK5_cjs = require('./chunk-U74A5VK5.cjs');
6
+ var chunkDS5BS7PP_cjs = require('./chunk-DS5BS7PP.cjs');
7
+ var chunkUUJMUPB3_cjs = require('./chunk-UUJMUPB3.cjs');
8
+ var chunkASKFIRMC_cjs = require('./chunk-ASKFIRMC.cjs');
9
+ var chunkAOODAOL4_cjs = require('./chunk-AOODAOL4.cjs');
10
+ var chunkDKFA4KOJ_cjs = require('./chunk-DKFA4KOJ.cjs');
11
+ var chunkEU5EFHO5_cjs = require('./chunk-EU5EFHO5.cjs');
12
+ var chunkMJROUIDZ_cjs = require('./chunk-MJROUIDZ.cjs');
13
+ var chunk5B23JVH3_cjs = require('./chunk-5B23JVH3.cjs');
14
+ var lucideReact = require('lucide-react');
15
+ var React = require('react');
16
+ var d3Scale = require('d3-scale');
17
+ var jsxRuntime = require('react/jsx-runtime');
18
+ var SliderPrimitive = require('@radix-ui/react-slider');
19
+
20
+ function _interopNamespace(e) {
21
+ if (e && e.__esModule) return e;
22
+ var n = Object.create(null);
23
+ if (e) {
24
+ Object.keys(e).forEach(function (k) {
25
+ if (k !== 'default') {
26
+ var d = Object.getOwnPropertyDescriptor(e, k);
27
+ Object.defineProperty(n, k, d.get ? d : {
28
+ enumerable: true,
29
+ get: function () { return e[k]; }
30
+ });
31
+ }
32
+ });
33
+ }
34
+ n.default = e;
35
+ return Object.freeze(n);
36
+ }
37
+
38
+ var React__namespace = /*#__PURE__*/_interopNamespace(React);
39
+ var SliderPrimitive__namespace = /*#__PURE__*/_interopNamespace(SliderPrimitive);
40
+
41
+ // src/components/charts/BarChart/bins.ts
42
+ function numericBins(all, values, count) {
43
+ const low = Math.min(...all);
44
+ const high = Math.max(...all);
45
+ if (!Number.isFinite(low) || !Number.isFinite(high)) return [];
46
+ const min = low === high ? low - 0.5 : low;
47
+ const max = low === high ? high + 0.5 : high;
48
+ const size = Math.max(2, Math.min(100, Math.round(count)));
49
+ const step = (max - min) / size;
50
+ const bins = Array.from({ length: size }, (_, i) => {
51
+ const start = min + i * step;
52
+ const end = min + (i + 1) * step;
53
+ return {
54
+ label: `[${start}, ${end}${i === size - 1 ? "]" : ")"}`,
55
+ start,
56
+ end,
57
+ value: 0,
58
+ isNumeric: true
59
+ };
60
+ });
61
+ for (const value of values) {
62
+ if (!Number.isFinite(value) || value < min || value > max) continue;
63
+ bins[Math.min(size - 1, Math.floor((value - min) / step))].value++;
64
+ }
65
+ return bins;
66
+ }
67
+
68
+ // src/components/charts/BarChart/barPlan.ts
69
+ var X_SCALE_PADDING = 0.05;
70
+ var Y_SCALE_PADDING = 0.1;
71
+ var DEFAULT_FILL = "#3479a8";
72
+ var FILTERED_OUT_FILL = "rgb(156 163 175)";
73
+ function isNumericBarField(settings, snapshot) {
74
+ return !settings.aggregateId && snapshot.fieldType !== "categorical" && !settings.forceString && snapshot.allValues.some((value) => chunk5B23JVH3_cjs.finiteNumber(value) !== void 0) && snapshot.allValues.filter((value) => !chunk5B23JVH3_cjs.isMissingValue(value)).every(chunk5B23JVH3_cjs.isNumberLike);
75
+ }
76
+ function countRows(settings, snapshot) {
77
+ const spec = {
78
+ id: `${settings.id}:count`,
79
+ name: `Count by ${settings.field}`,
80
+ groupField: settings.field,
81
+ aggregation: "count"
82
+ };
83
+ const result = chunk5B23JVH3_cjs.calculateGroupedAggregate(
84
+ snapshot.liveIds.map((id) => ({
85
+ __ID: id,
86
+ [settings.field]: snapshot.fieldData[id]
87
+ })),
88
+ spec
89
+ );
90
+ const byKey = new Map(
91
+ result.rows.map((row) => [chunk5B23JVH3_cjs.categoryKey(row.groupValue), row])
92
+ );
93
+ const categories = new Map(
94
+ snapshot.allValues.map((value) => [chunk5B23JVH3_cjs.categoryKey(value), chunk5B23JVH3_cjs.categoryValue(value)])
95
+ );
96
+ const rows = [...categories].map(
97
+ ([key, category]) => byKey.get(key) ?? {
98
+ id: `${spec.id}:${key}`,
99
+ groupValue: category,
100
+ groupLabel: chunk5B23JVH3_cjs.categoryLabel(category),
101
+ value: 0,
102
+ rowCount: 0,
103
+ contributors: []
104
+ }
105
+ );
106
+ return { ...result, rows };
107
+ }
108
+ function binRows(settings, snapshot) {
109
+ const all = chunk5B23JVH3_cjs.finiteNumbers(snapshot.allValues);
110
+ const live = snapshot.liveIds.flatMap((id) => {
111
+ const value = chunk5B23JVH3_cjs.finiteNumber(snapshot.fieldData[id]);
112
+ return value === void 0 ? [] : [{ id, value }];
113
+ });
114
+ const bins = numericBins(
115
+ all,
116
+ live.map((item) => item.value),
117
+ settings.binCount || 20
118
+ );
119
+ const members = bins.map(() => []);
120
+ if (bins.length) {
121
+ const min = bins[0].start;
122
+ const max = bins[bins.length - 1].end;
123
+ const step = (max - min) / bins.length;
124
+ for (const item of live) {
125
+ if (item.value < min || item.value > max) continue;
126
+ members[Math.min(bins.length - 1, Math.floor((item.value - min) / step))].push(item);
127
+ }
128
+ }
129
+ return bins.map((bin, index) => ({
130
+ bin: { start: bin.start, end: bin.end },
131
+ id: `bin:${bin.start}:${bin.end}`,
132
+ groupValue: bin.start,
133
+ groupLabel: bin.label,
134
+ value: bin.value,
135
+ rowCount: members[index].length,
136
+ contributors: members[index].map((item) => ({
137
+ sourceId: item.id,
138
+ input: snapshot.fieldData[item.id],
139
+ included: true
140
+ }))
141
+ }));
142
+ }
143
+ function extremes(values) {
144
+ const lower = values.reduce(
145
+ (winner, item) => item.value < (winner?.value ?? 0) ? item : winner,
146
+ void 0
147
+ );
148
+ const upper = values.reduce(
149
+ (winner, item) => item.value > (winner?.value ?? 0) ? item : winner,
150
+ void 0
151
+ );
152
+ const end = (item) => item ? { source: "bar", id: item.id, label: item.label, value: item.value } : { source: "zero", value: 0 };
153
+ return { lower: end(lower), upper: end(upper) };
154
+ }
155
+ function planBarChart({
156
+ settings,
157
+ snapshot,
158
+ width,
159
+ height,
160
+ getColor,
161
+ getFieldLabel,
162
+ formatFieldValue,
163
+ aggregateScope = "This result uses the current globally filtered source rows"
164
+ }) {
165
+ const numeric = isNumericBarField(settings, snapshot);
166
+ const mode = settings.aggregateId ? "aggregate" : numeric ? "bin" : "count";
167
+ const spec = snapshot.aggregate?.spec;
168
+ const result = mode === "aggregate" ? snapshot.aggregate : mode === "count" ? countRows(settings, snapshot) : void 0;
169
+ const rows = mode === "bin" ? binRows(settings, snapshot) : result?.rows ?? [];
170
+ let domainValues;
171
+ if (mode === "aggregate") {
172
+ domainValues = rows.flatMap(
173
+ (row) => typeof row.value === "number" && Number.isFinite(row.value) ? [{ id: row.id, label: row.groupLabel, value: row.value }] : []
174
+ );
175
+ } else if (mode === "bin") {
176
+ const all = chunk5B23JVH3_cjs.finiteNumbers(snapshot.allValues);
177
+ domainValues = numericBins(all, all, settings.binCount || 20).map(
178
+ (bin) => ({ id: `bin:${bin.start}:${bin.end}`, label: bin.label, value: bin.value })
179
+ );
180
+ } else {
181
+ const counts = /* @__PURE__ */ new Map();
182
+ for (const value of snapshot.allValues) {
183
+ const key = chunk5B23JVH3_cjs.categoryKey(value);
184
+ const item = counts.get(key);
185
+ if (item) item.value += 1;
186
+ else
187
+ counts.set(key, {
188
+ id: `${settings.id}:count:${key}`,
189
+ label: chunk5B23JVH3_cjs.categoryLabel(chunk5B23JVH3_cjs.categoryValue(value)),
190
+ value: 1
191
+ });
192
+ }
193
+ domainValues = [...counts.values()];
194
+ }
195
+ const { lower, upper } = extremes(domainValues);
196
+ let yDomain;
197
+ let padding;
198
+ if (mode === "aggregate") {
199
+ const pad = lower.value === upper.value ? 0.5 : (upper.value - lower.value) * Y_SCALE_PADDING;
200
+ yDomain = [lower.value - (lower.value < 0 ? pad : 0), upper.value + pad];
201
+ padding = lower.value === upper.value ? "0.5 above and below" : "10% of the value span";
202
+ } else {
203
+ yDomain = [0, Math.max(1, upper.value * (1 + Y_SCALE_PADDING))];
204
+ padding = "10% above the tallest bar";
205
+ }
206
+ const xField = mode === "aggregate" && spec ? spec.groupField : settings.field;
207
+ const yField = mode === "aggregate" && spec && spec.aggregation !== "count" ? spec.measureField : void 0;
208
+ const xLabel = chunk5B23JVH3_cjs.getChartAxisLabel(
209
+ xField,
210
+ settings.xAxisLabel,
211
+ getFieldLabel
212
+ );
213
+ const yLabel = settings.yAxisLabel || (mode === "aggregate" && spec ? spec.aggregation === "count" ? "Count" : getFieldLabel(spec.measureField ?? "Measure") : "");
214
+ const { margin, policy } = chunkUUJMUPB3_cjs.planChartMargin({
215
+ margin: settings.margin,
216
+ width,
217
+ yDomain,
218
+ hasXLabel: Boolean(xLabel),
219
+ hasYLabel: Boolean(yLabel)
220
+ });
221
+ const plotWidth = width - margin.left - margin.right;
222
+ const plotHeight = height - margin.top - margin.bottom;
223
+ let xScale;
224
+ let xDomainSource;
225
+ if (mode === "bin") {
226
+ const all = chunk5B23JVH3_cjs.finiteNumbers(snapshot.allValues);
227
+ const low = Math.min(...all);
228
+ const high = Math.max(...all);
229
+ const min = low === high ? low - 0.5 : low;
230
+ const max = low === high ? high + 0.5 : high;
231
+ const pad = (max - min) * X_SCALE_PADDING;
232
+ xScale = chunkUUJMUPB3_cjs.numericScale(settings.xAxis).domain([min - pad, max + pad]).range([0, plotWidth]);
233
+ xDomainSource = {
234
+ population: "all source rows",
235
+ rows: all.length,
236
+ bounds: [low, high],
237
+ padding: "5% on each side"
238
+ };
239
+ } else {
240
+ const labels = mode === "aggregate" ? rows.map((row) => row.groupLabel) : Array.from(new Set(snapshot.allValues.map(chunk5B23JVH3_cjs.categoryLabel)));
241
+ xScale = d3Scale.scaleBand().domain(labels).range([0, plotWidth]).padding(0.3);
242
+ }
243
+ const yScale = chunkUUJMUPB3_cjs.numericScale(settings.yAxis).domain(yDomain).range([plotHeight, 0]);
244
+ const baseline = yScale(0);
245
+ const format = (field) => (value) => field && formatFieldValue ? formatFieldValue(field, value) : chunkDS5BS7PP_cjs.formatTick(value);
246
+ const symlog = (label, type) => [label, type === "symlog" && "symlog"].filter(Boolean).join(" \xB7 ");
247
+ const axes = chunkUUJMUPB3_cjs.planAxes({
248
+ plotWidth,
249
+ plotHeight,
250
+ margin,
251
+ marginPolicy: policy,
252
+ x: {
253
+ scale: xScale,
254
+ scaleType: settings.xAxis.scaleType,
255
+ field: xField,
256
+ fieldLabel: xField ? getFieldLabel(xField) : void 0,
257
+ density: settings.xGridLines,
258
+ grid: settings.xAxis.grid,
259
+ format: format(xField),
260
+ label: symlog(xLabel, settings.xAxis.scaleType),
261
+ labelSource: settings.xAxisLabel ? "chart-setting" : "field-label",
262
+ domainSource: xDomainSource
263
+ },
264
+ y: {
265
+ scale: yScale,
266
+ scaleType: settings.yAxis.scaleType,
267
+ field: yField,
268
+ fieldLabel: yLabel || void 0,
269
+ density: settings.yGridLines,
270
+ grid: settings.yAxis.grid ?? true,
271
+ format: format(yField),
272
+ label: symlog(yLabel, settings.yAxis.scaleType),
273
+ labelSource: settings.yAxisLabel ? "chart-setting" : "field-label",
274
+ zero: true,
275
+ domainSource: {
276
+ population: mode === "aggregate" ? "the current aggregate result" : "all source rows",
277
+ rows: domainValues.length,
278
+ bounds: [lower.value, upper.value],
279
+ padding,
280
+ lower: lower.label ? { label: lower.label, value: lower.value } : void 0,
281
+ upper: upper.label ? { label: upper.label, value: upper.value } : void 0
282
+ }
283
+ }
284
+ });
285
+ const valueFilter = mode === "aggregate" ? void 0 : settings.filters.find(
286
+ (filter) => filter.type === "value" && filter.field === settings.field
287
+ );
288
+ const rangeFilter = mode === "bin" ? chunkUUJMUPB3_cjs.getRangeFilterForField(settings.filters, settings.field) : void 0;
289
+ const bars = [];
290
+ const unplotted = [];
291
+ rows.forEach((row, order) => {
292
+ if (typeof row.value !== "number" || !Number.isFinite(row.value)) {
293
+ unplotted.push({ row, reason: "No valid numbers" });
294
+ return;
295
+ }
296
+ let x;
297
+ let barWidth;
298
+ let bin;
299
+ if (row.bin) {
300
+ const linear = xScale;
301
+ const { start, end } = row.bin;
302
+ bin = { start, end, closed: order === rows.length - 1 };
303
+ x = linear(start);
304
+ const span = linear(end) - x;
305
+ if (span < 1) return;
306
+ barWidth = Math.max(0, span - 1);
307
+ } else {
308
+ const band = xScale;
309
+ const at = band(row.groupLabel);
310
+ if (at === void 0 || band.bandwidth() < 1) return;
311
+ x = at;
312
+ barWidth = band.bandwidth();
313
+ }
314
+ const valuePosition = yScale(row.value);
315
+ const baseFill = getColor(row.groupValue) || DEFAULT_FILL;
316
+ const passes = rangeFilter ? chunkEU5EFHO5_cjs.applyFilter(row.groupValue, rangeFilter) : valueFilter ? chunkEU5EFHO5_cjs.applyFilter(row.groupValue, valueFilter) : true;
317
+ bars.push({
318
+ id: `bar:${row.id}`,
319
+ order,
320
+ label: row.groupLabel,
321
+ groupValue: row.groupValue,
322
+ bin,
323
+ value: row.value,
324
+ x,
325
+ y: Math.min(baseline, valuePosition),
326
+ width: barWidth,
327
+ height: Math.max(1, Math.abs(baseline - valuePosition)),
328
+ baseline,
329
+ fill: passes ? baseFill : FILTERED_OUT_FILL,
330
+ fillSource: passes ? { kind: "color-scale", scaleId: settings.colorScaleId, value: row.groupValue } : {
331
+ kind: "own-filter",
332
+ scaleId: settings.colorScaleId,
333
+ value: row.groupValue,
334
+ baseFill
335
+ },
336
+ selected: mode === "count" && valueFilter ? chunkEU5EFHO5_cjs.applyFilter(row.groupValue, valueFilter) : void 0,
337
+ row
338
+ });
339
+ });
340
+ return {
341
+ revision: snapshot.revision,
342
+ mode,
343
+ width,
344
+ height,
345
+ field: xField,
346
+ fieldLabel: getFieldLabel(xField),
347
+ valueLabel: yLabel || "Row count",
348
+ aggregation: mode === "aggregate" && spec ? `${spec.aggregation}${spec.measureField ? ` of ${getFieldLabel(spec.measureField)}` : ""}` : "count",
349
+ axes,
350
+ xScale: chunkUUJMUPB3_cjs.describeScale(xScale, settings.xAxis.scaleType),
351
+ yScale: chunkUUJMUPB3_cjs.describeScale(yScale, settings.yAxis.scaleType),
352
+ bars,
353
+ groupOrder: rows.map((row) => row.groupLabel),
354
+ unplotted,
355
+ domain: {
356
+ population: mode === "aggregate" ? "current result" : "all source rows",
357
+ values: domainValues,
358
+ lower,
359
+ upper,
360
+ padding,
361
+ domain: yDomain
362
+ },
363
+ zeroBaseline: baseline,
364
+ scopeNote: mode === "aggregate" ? aggregateScope : mode === "count" ? "Rows after other chart filters; this chart's selected categories are shown in color" : "Rows after other chart filters; this chart's range is shown in color"
365
+ };
366
+ }
367
+ function findBarForRow(plan, id) {
368
+ return plan.bars.find(
369
+ (bar) => bar.row.contributors.some((contributor) => contributor.sourceId === id)
370
+ );
371
+ }
372
+ function barAt(plan, x, y) {
373
+ return plan.bars.find(
374
+ (bar) => x >= bar.x && x <= bar.x + bar.width && y >= bar.y && y <= bar.y + bar.height
375
+ );
376
+ }
377
+
378
+ // src/components/charts/BarChart/barTrace.ts
379
+ function resolveBarTrace(plan, kind, id) {
380
+ if (kind === "guide") return chunkTRAIXZ6M_cjs.resolveGuideTrace(plan.axes, id, plan.revision);
381
+ if (kind !== "bar") return void 0;
382
+ const mark = plan.bars.find((bar) => bar.id === id);
383
+ if (!mark) return void 0;
384
+ return {
385
+ kind: "bar",
386
+ id,
387
+ revision: plan.revision,
388
+ mark,
389
+ mode: plan.mode,
390
+ field: plan.field,
391
+ fieldLabel: plan.fieldLabel,
392
+ valueLabel: plan.valueLabel,
393
+ aggregation: plan.aggregation,
394
+ groupOrder: plan.groupOrder,
395
+ domain: plan.domain,
396
+ xScale: plan.xScale,
397
+ yScale: plan.yScale,
398
+ scopeNote: plan.scopeNote
399
+ };
400
+ }
401
+ function barTraceTargets(plan) {
402
+ return [
403
+ ...plan.bars.map((bar) => ({
404
+ kind: "bar",
405
+ id: bar.id,
406
+ label: `Bar: ${bar.label}`
407
+ })),
408
+ ...chunkTRAIXZ6M_cjs.guideTargets(plan.axes)
409
+ ];
410
+ }
411
+ function findBarTraceRow(plan, id) {
412
+ const bar = findBarForRow(plan, id);
413
+ return bar && { kind: "bar", id: bar.id };
414
+ }
415
+ function HoverReadout({ plan, id }) {
416
+ const bar = plan.bars.find((item) => item.id === id);
417
+ const guide = bar ? void 0 : chunkUUJMUPB3_cjs.findAxisGuide(plan.axes, id)?.guide;
418
+ if (!bar && !guide) return null;
419
+ return /* @__PURE__ */ jsxRuntime.jsx(
420
+ "div",
421
+ {
422
+ className: "pointer-events-none absolute left-2 top-2 max-w-[min(16rem,70%)] rounded border border-border bg-card/95 px-2 py-1 text-xs text-card-foreground shadow-sm",
423
+ role: "status",
424
+ children: bar ? /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
425
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
426
+ "Bar \xB7 ",
427
+ bar.label
428
+ ] }),
429
+ /* @__PURE__ */ jsxRuntime.jsx("div", { children: bar.bin ? `Bin interval: ${bar.bin.start} to ${bar.bin.end}` : `Value: ${bar.value}` })
430
+ ] }) : /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
431
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
432
+ guide.axis === "x" ? "Horizontal" : "Vertical",
433
+ " ",
434
+ guide.role
435
+ ] }),
436
+ guide.value !== void 0 && /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
437
+ "Value: ",
438
+ String(guide.value)
439
+ ] }),
440
+ guide.role !== "zero" && guide.label && /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
441
+ "Label: ",
442
+ guide.label.fullText
443
+ ] })
444
+ ] })
445
+ }
446
+ );
447
+ }
448
+ function BarChart({
449
+ settings,
450
+ width,
451
+ height,
452
+ facetIds,
453
+ aggregateResult,
454
+ aggregateScope
455
+ }) {
456
+ const getAggregateResult = chunk5B23JVH3_cjs.useDataLayer((s) => s.getAggregateResult);
457
+ const getFieldLabel = chunk5B23JVH3_cjs.useDataLayer((s) => s.getFieldLabel);
458
+ const formatFieldValue = chunk5B23JVH3_cjs.useDataLayer((s) => s.formatFieldValue);
459
+ const fieldSettings = chunk5B23JVH3_cjs.useDataLayer((s) => s.fieldSettings);
460
+ const nonce = chunk5B23JVH3_cjs.useDataLayer((s) => s.nonce);
461
+ const aggregates = chunk5B23JVH3_cjs.useDataLayer((s) => s.aggregates);
462
+ const updateChart = chunk5B23JVH3_cjs.useDataLayer((s) => s.updateChart);
463
+ const { getColorForValue } = chunkB7OQUBH4_cjs.useColorScales();
464
+ const liveIds = chunkDKFA4KOJ_cjs.useGetLiveIds(settings, facetIds);
465
+ const allValues = chunkDKFA4KOJ_cjs.useGetColumnDataForIds(settings.field);
466
+ const fieldData = chunkDKFA4KOJ_cjs.useGetColumnData(settings.field);
467
+ const revision = chunkTRAIXZ6M_cjs.useTraceRevision(settings);
468
+ const trace = chunkTRAIXZ6M_cjs.useChartTrace();
469
+ const traceApi = chunkTRAIXZ6M_cjs.useChartTraceApi();
470
+ const owner = React.useId();
471
+ const [hoveredId, setHoveredId] = React.useState(null);
472
+ const resolvedAggregate = React.useMemo(() => {
473
+ return settings.aggregateId ? getAggregateResult(settings.aggregateId, liveIds) : void 0;
474
+ }, [
475
+ settings.aggregateId,
476
+ getAggregateResult,
477
+ aggregates,
478
+ fieldSettings,
479
+ liveIds,
480
+ nonce
481
+ ]);
482
+ const plan = React.useMemo(
483
+ () => planBarChart({
484
+ settings,
485
+ width,
486
+ height,
487
+ snapshot: {
488
+ revision,
489
+ allValues,
490
+ liveIds,
491
+ fieldData,
492
+ fieldType: fieldSettings[settings.field]?.type,
493
+ aggregate: aggregateResult ?? resolvedAggregate
494
+ },
495
+ getColor: (value) => getColorForValue(settings.colorScaleId, value, "#3479a8"),
496
+ getFieldLabel,
497
+ formatFieldValue,
498
+ aggregateScope
499
+ }),
500
+ // Label and format getters are stable; field settings carry their changes.
501
+ // eslint-disable-next-line react-hooks/exhaustive-deps
502
+ [
503
+ settings,
504
+ width,
505
+ height,
506
+ revision,
507
+ allValues,
508
+ liveIds,
509
+ fieldData,
510
+ fieldSettings,
511
+ aggregateResult,
512
+ resolvedAggregate,
513
+ getColorForValue,
514
+ aggregateScope
515
+ ]
516
+ );
517
+ const xScale = React.useMemo(() => chunkUUJMUPB3_cjs.buildScale(plan.xScale), [plan.xScale]);
518
+ const yScale = React.useMemo(
519
+ () => chunkUUJMUPB3_cjs.buildScale(plan.yScale),
520
+ [plan.yScale]
521
+ );
522
+ const source = React.useMemo(
523
+ () => ({
524
+ role: "chart",
525
+ revision: plan.revision,
526
+ resolve: (kind, id) => resolveBarTrace(plan, kind, id),
527
+ findRow: (id) => findBarTraceRow(plan, id),
528
+ targets: () => barTraceTargets(plan)
529
+ }),
530
+ [plan]
531
+ );
532
+ chunkTRAIXZ6M_cjs.useTraceSource(owner, source);
533
+ const inspect = React.useCallback(
534
+ (kind, id) => traceApi?.inspect(owner, kind, id),
535
+ [owner, traceApi]
536
+ );
537
+ const selected = trace?.selection?.owner === owner ? trace.selection : void 0;
538
+ const valueFilter = settings.filters.find(
539
+ (f) => f.type === "value" && f.field === settings.field
540
+ );
541
+ const toggleCategory = React.useCallback(
542
+ (label) => {
543
+ const filterValues = valueFilter?.values ?? [];
544
+ const newValues = chunk5B23JVH3_cjs.categoryIncludes(filterValues, label) ? filterValues.filter((f) => !chunk5B23JVH3_cjs.categoryEqual(f, label)) : [...filterValues, label];
545
+ const newFilters = settings.filters.filter(
546
+ (f) => f.type !== "value" || f.field !== settings.field
547
+ );
548
+ if (newValues.length > 0) {
549
+ newFilters.push({
550
+ type: "value",
551
+ field: settings.field,
552
+ values: newValues
553
+ });
554
+ }
555
+ updateChart(settings.id, { filters: newFilters });
556
+ },
557
+ [settings.id, settings.field, settings.filters, updateChart, valueFilter]
558
+ );
559
+ const handleBrushChange = React.useCallback(
560
+ (extent) => {
561
+ const newFilters = settings.filters.filter(
562
+ (f) => f.field !== settings.field
563
+ );
564
+ if (extent && plan.mode === "bin") {
565
+ const linear = xScale;
566
+ newFilters.push({
567
+ type: "range",
568
+ field: settings.field,
569
+ min: linear.invert(extent[0][0]),
570
+ max: linear.invert(extent[1][0])
571
+ });
572
+ } else if (extent) {
573
+ return;
574
+ }
575
+ updateChart(settings.id, { filters: newFilters });
576
+ },
577
+ [plan.mode, settings.field, settings.filters, settings.id, updateChart, xScale]
578
+ );
579
+ const isCount = plan.mode === "count";
580
+ const isAggregate = plan.mode === "aggregate";
581
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "relative", style: { width, height }, children: [
582
+ /* @__PURE__ */ jsxRuntime.jsx(
583
+ chunkDS5BS7PP_cjs.BaseChart,
584
+ {
585
+ width,
586
+ height,
587
+ xScale,
588
+ yScale,
589
+ axes: plan.axes,
590
+ brushingMode: plan.mode === "bin" ? "horizontal" : "none",
591
+ onBrushChange: handleBrushChange,
592
+ settings,
593
+ onInspectGuide: (id) => inspect("guide", id),
594
+ onHoverTarget: setHoveredId,
595
+ onInspectPlot: ([x, y]) => {
596
+ const bar = barAt(plan, x, y);
597
+ return bar ? Boolean(inspect("bar", bar.id)) : false;
598
+ },
599
+ activeGuideId: selected?.kind === "guide" ? selected.id : hoveredId,
600
+ children: /* @__PURE__ */ jsxRuntime.jsx("g", { children: plan.bars.map((bar) => {
601
+ const measureLabel = isAggregate ? chunk5B23JVH3_cjs.displayAggregateValue(bar.value) : `${bar.value} records`;
602
+ const clickable = isCount || plan.mode === "bin";
603
+ return /* @__PURE__ */ jsxRuntime.jsx(
604
+ "rect",
605
+ {
606
+ "data-plan-id": bar.id,
607
+ "data-aggregate-row-id": bar.row.id,
608
+ x: bar.x,
609
+ y: bar.y,
610
+ width: bar.width,
611
+ height: bar.height,
612
+ rx: 1.5,
613
+ role: "button",
614
+ tabIndex: 0,
615
+ "aria-label": `${bar.label}: ${measureLabel}`,
616
+ "aria-pressed": bar.selected,
617
+ className: `chart-mark ${clickable ? "cursor-pointer" : ""}`,
618
+ style: {
619
+ fill: bar.fill,
620
+ ...selected?.id === bar.id ? { stroke: "var(--primary)", strokeWidth: 2 } : {}
621
+ },
622
+ onKeyDown: (event) => {
623
+ if (event.key !== "Enter" && event.key !== " ") return;
624
+ if (event.altKey && event.key === "Enter") {
625
+ event.preventDefault();
626
+ inspect("bar", bar.id);
627
+ } else if (isCount && !event.altKey) {
628
+ event.preventDefault();
629
+ toggleCategory(bar.groupValue);
630
+ }
631
+ },
632
+ onClick: (event) => {
633
+ if (event.altKey) {
634
+ event.preventDefault();
635
+ event.stopPropagation();
636
+ inspect("bar", bar.id);
637
+ } else if (isCount) {
638
+ toggleCategory(bar.groupValue);
639
+ }
640
+ }
641
+ },
642
+ bar.id
643
+ );
644
+ }) })
645
+ }
646
+ ),
647
+ hoveredId && /* @__PURE__ */ jsxRuntime.jsx(HoverReadout, { plan, id: hoveredId })
648
+ ] });
649
+ }
650
+ function Slider({
651
+ className,
652
+ defaultValue,
653
+ value,
654
+ min = 0,
655
+ max = 100,
656
+ ...props
657
+ }) {
658
+ const _values = React__namespace.useMemo(
659
+ () => Array.isArray(value) ? value : Array.isArray(defaultValue) ? defaultValue : [min, max],
660
+ [value, defaultValue, min, max]
661
+ );
662
+ return /* @__PURE__ */ jsxRuntime.jsxs(
663
+ SliderPrimitive__namespace.Root,
664
+ {
665
+ "data-slot": "slider",
666
+ defaultValue,
667
+ value,
668
+ min,
669
+ max,
670
+ className: chunk5B23JVH3_cjs.cn(
671
+ "relative flex w-full touch-none items-center select-none data-[disabled]:opacity-50 data-[orientation=vertical]:h-full data-[orientation=vertical]:min-h-44 data-[orientation=vertical]:w-auto data-[orientation=vertical]:flex-col",
672
+ className
673
+ ),
674
+ ...props,
675
+ children: [
676
+ /* @__PURE__ */ jsxRuntime.jsx(
677
+ SliderPrimitive__namespace.Track,
678
+ {
679
+ "data-slot": "slider-track",
680
+ className: chunk5B23JVH3_cjs.cn(
681
+ "bg-muted relative grow overflow-hidden rounded-full data-[orientation=horizontal]:h-1.5 data-[orientation=horizontal]:w-full data-[orientation=vertical]:h-full data-[orientation=vertical]:w-1.5"
682
+ ),
683
+ children: /* @__PURE__ */ jsxRuntime.jsx(
684
+ SliderPrimitive__namespace.Range,
685
+ {
686
+ "data-slot": "slider-range",
687
+ className: chunk5B23JVH3_cjs.cn(
688
+ "bg-primary absolute data-[orientation=horizontal]:h-full data-[orientation=vertical]:w-full"
689
+ )
690
+ }
691
+ )
692
+ }
693
+ ),
694
+ Array.from({ length: _values.length }, (_, index) => /* @__PURE__ */ jsxRuntime.jsx(
695
+ SliderPrimitive__namespace.Thumb,
696
+ {
697
+ "data-slot": "slider-thumb",
698
+ className: "border-primary bg-background ring-ring/20 block size-4 shrink-0 rounded-full border shadow-sm transition-[color,box-shadow] hover:ring-4 focus-visible:ring-4 focus-visible:outline-hidden disabled:pointer-events-none disabled:opacity-50"
699
+ },
700
+ index
701
+ ))
702
+ ]
703
+ }
704
+ );
705
+ }
706
+ function getAggregateName(aggregation, groupField, measureField) {
707
+ if (aggregation === "count") {
708
+ return `Count by ${groupField}`;
709
+ }
710
+ return `${aggregation === "sum" ? "Sum" : "Average"} of ${measureField ?? ""} by ${groupField}`;
711
+ }
712
+ function BarChartSettingsPanel({
713
+ settings,
714
+ onSettingsChange
715
+ }) {
716
+ const { getOrCreateScaleForField } = chunkB7OQUBH4_cjs.useColorScales();
717
+ const aggregate = chunk5B23JVH3_cjs.useDataLayer(
718
+ (state) => settings.aggregateId ? state.getAggregate(settings.aggregateId) : void 0
719
+ );
720
+ const addAggregate = chunk5B23JVH3_cjs.useDataLayer((state) => state.addAggregate);
721
+ const updateAggregate = chunk5B23JVH3_cjs.useDataLayer((state) => state.updateAggregate);
722
+ const getColumnNames = chunk5B23JVH3_cjs.useDataLayer((state) => state.getColumnNames);
723
+ const getColumnData = chunk5B23JVH3_cjs.useDataLayer((state) => state.getColumnData);
724
+ const calculations = chunk5B23JVH3_cjs.useDataLayer((state) => state.calculations);
725
+ const fieldProfiles = chunk5B23JVH3_cjs.useDataLayer((state) => state.fieldProfiles);
726
+ const fieldNames = React.useMemo(() => {
727
+ return getColumnNames();
728
+ }, [getColumnNames, calculations]);
729
+ const measureFields = React.useMemo(() => {
730
+ const numeric = fieldNames.filter(
731
+ (field) => fieldProfiles.some(
732
+ (profile) => profile.name === field && profile.dataType === "numeric"
733
+ )
734
+ );
735
+ calculations.forEach((calculation) => {
736
+ const values = Object.values(getColumnData(calculation.resultColumnName));
737
+ if (values.some((value) => chunk5B23JVH3_cjs.finiteNumber(value) !== void 0)) {
738
+ numeric.push(calculation.resultColumnName);
739
+ }
740
+ });
741
+ if (aggregate?.measureField && !numeric.includes(aggregate.measureField)) {
742
+ numeric.unshift(aggregate.measureField);
743
+ }
744
+ return numeric;
745
+ }, [
746
+ aggregate?.measureField,
747
+ calculations,
748
+ fieldNames,
749
+ fieldProfiles,
750
+ getColumnData
751
+ ]);
752
+ const [error, setError] = React.useState();
753
+ const createAggregate = (aggregation) => {
754
+ const measureField = measureFields[0];
755
+ if (aggregation !== "count" && !measureField) {
756
+ setError("Sum and average need a numeric measure field.");
757
+ return;
758
+ }
759
+ try {
760
+ const aggregate2 = addAggregate({
761
+ name: getAggregateName(aggregation, settings.field, measureField),
762
+ groupField: settings.field,
763
+ aggregation,
764
+ ...aggregation === "count" ? {} : { measureField }
765
+ });
766
+ onSettingsChange({
767
+ ...settings,
768
+ field: aggregate2.measureField ?? aggregate2.groupField,
769
+ aggregateId: aggregate2.id,
770
+ title: aggregate2.name,
771
+ xAxisLabel: "",
772
+ yAxisLabel: ""
773
+ });
774
+ setError(void 0);
775
+ } catch (cause) {
776
+ setError(
777
+ cause instanceof Error ? cause.message : "Could not create grouped bar"
778
+ );
779
+ }
780
+ };
781
+ if (settings.aggregateId) {
782
+ if (!aggregate) {
783
+ return /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-sm text-destructive", children: "Bar aggregation not found." });
784
+ }
785
+ const updateDefinition = (updates) => {
786
+ try {
787
+ const next = { ...aggregate, ...updates };
788
+ const name = getAggregateName(
789
+ next.aggregation,
790
+ next.groupField,
791
+ next.measureField
792
+ );
793
+ updateAggregate(settings.aggregateId, { ...updates, name });
794
+ onSettingsChange({
795
+ ...settings,
796
+ field: next.aggregation === "count" ? next.groupField : next.measureField ?? next.groupField,
797
+ ...settings.title === aggregate.name ? { title: name } : {}
798
+ });
799
+ setError(void 0);
800
+ } catch (cause) {
801
+ setError(
802
+ cause instanceof Error ? cause.message : "Could not update grouped summary"
803
+ );
804
+ }
805
+ };
806
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-4", children: [
807
+ error && /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-sm text-destructive", role: "alert", children: error }),
808
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "grid grid-cols-[120px_1fr] items-center gap-4", children: [
809
+ /* @__PURE__ */ jsxRuntime.jsx(chunkMJROUIDZ_cjs.Label, { children: "Group by" }),
810
+ /* @__PURE__ */ jsxRuntime.jsx(
811
+ chunkASKFIRMC_cjs.FieldSelector,
812
+ {
813
+ label: "",
814
+ placeholder: "Group by",
815
+ value: aggregate.groupField,
816
+ onChange: (value) => updateDefinition({ groupField: value })
817
+ }
818
+ ),
819
+ /* @__PURE__ */ jsxRuntime.jsx(chunkMJROUIDZ_cjs.Label, { htmlFor: "bar-operation", children: "Operation" }),
820
+ /* @__PURE__ */ jsxRuntime.jsxs(
821
+ "select",
822
+ {
823
+ id: "bar-operation",
824
+ className: "h-9 rounded-md border-input bg-background px-2 text-sm",
825
+ value: aggregate.aggregation,
826
+ onChange: (event) => {
827
+ if (event.target.value === "category") {
828
+ onSettingsChange({
829
+ ...settings,
830
+ field: aggregate.groupField,
831
+ aggregateId: void 0,
832
+ ...settings.title === aggregate.name ? { title: "" } : {}
833
+ });
834
+ return;
835
+ }
836
+ updateDefinition({
837
+ aggregation: event.target.value,
838
+ ...event.target.value !== "count" && !aggregate.measureField ? { measureField: measureFields[0] } : {}
839
+ });
840
+ },
841
+ children: [
842
+ /* @__PURE__ */ jsxRuntime.jsx("option", { value: "category", children: "Category counts / bins" }),
843
+ /* @__PURE__ */ jsxRuntime.jsx("option", { value: "count", children: "Count rows" }),
844
+ /* @__PURE__ */ jsxRuntime.jsx("option", { value: "sum", disabled: !measureFields.length, children: "Sum" }),
845
+ /* @__PURE__ */ jsxRuntime.jsx("option", { value: "average", disabled: !measureFields.length, children: "Average" })
846
+ ]
847
+ }
848
+ ),
849
+ aggregate.aggregation !== "count" && /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
850
+ /* @__PURE__ */ jsxRuntime.jsx(chunkMJROUIDZ_cjs.Label, { children: "Measure" }),
851
+ /* @__PURE__ */ jsxRuntime.jsx(
852
+ chunkASKFIRMC_cjs.FieldSelector,
853
+ {
854
+ label: "",
855
+ placeholder: "Measure",
856
+ value: aggregate.measureField ?? "",
857
+ fields: measureFields,
858
+ onChange: (value) => updateDefinition({ measureField: value })
859
+ }
860
+ )
861
+ ] })
862
+ ] })
863
+ ] });
864
+ }
865
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-4", children: [
866
+ error && /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-sm text-destructive", role: "alert", children: error }),
867
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "grid grid-cols-[120px_1fr] items-center gap-4", children: [
868
+ /* @__PURE__ */ jsxRuntime.jsx(chunkMJROUIDZ_cjs.Label, { children: "Group by" }),
869
+ /* @__PURE__ */ jsxRuntime.jsx(
870
+ chunkASKFIRMC_cjs.FieldSelector,
871
+ {
872
+ label: "",
873
+ placeholder: "Group by",
874
+ value: settings.field,
875
+ onChange: (value) => onSettingsChange({ ...settings, field: value })
876
+ }
877
+ ),
878
+ /* @__PURE__ */ jsxRuntime.jsx(chunkMJROUIDZ_cjs.Label, { htmlFor: "bar-operation", children: "Operation" }),
879
+ /* @__PURE__ */ jsxRuntime.jsxs(
880
+ "select",
881
+ {
882
+ id: "bar-operation",
883
+ className: "h-9 rounded-md border-input bg-background px-2 text-sm",
884
+ defaultValue: "category",
885
+ onChange: (event) => {
886
+ if (event.target.value !== "category") {
887
+ createAggregate(event.target.value);
888
+ }
889
+ },
890
+ children: [
891
+ /* @__PURE__ */ jsxRuntime.jsx("option", { value: "category", children: "Count rows" }),
892
+ /* @__PURE__ */ jsxRuntime.jsx("option", { value: "sum", disabled: !measureFields.length, children: "Sum" }),
893
+ /* @__PURE__ */ jsxRuntime.jsx("option", { value: "average", disabled: !measureFields.length, children: "Average" })
894
+ ]
895
+ }
896
+ ),
897
+ /* @__PURE__ */ jsxRuntime.jsxs(chunkMJROUIDZ_cjs.Label, { children: [
898
+ "Bins \xB7 ",
899
+ settings.binCount ?? 10
900
+ ] }),
901
+ /* @__PURE__ */ jsxRuntime.jsx(
902
+ Slider,
903
+ {
904
+ "aria-label": "Histogram bin count",
905
+ value: [settings.binCount ?? 10],
906
+ min: 2,
907
+ max: 50,
908
+ step: 1,
909
+ onValueChange: ([value]) => onSettingsChange({ ...settings, binCount: value })
910
+ }
911
+ ),
912
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "col-start-2", children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center space-x-2", children: [
913
+ /* @__PURE__ */ jsxRuntime.jsx(
914
+ chunkAOODAOL4_cjs.Switch,
915
+ {
916
+ id: "forceString",
917
+ checked: settings.forceString,
918
+ onCheckedChange: (checked) => onSettingsChange({
919
+ ...settings,
920
+ forceString: checked
921
+ })
922
+ }
923
+ ),
924
+ /* @__PURE__ */ jsxRuntime.jsx(chunkMJROUIDZ_cjs.Label, { htmlFor: "forceString", children: "Treat values as categories" })
925
+ ] }) }),
926
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "col-start-2", children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center space-x-2", children: [
927
+ /* @__PURE__ */ jsxRuntime.jsx(
928
+ chunkAOODAOL4_cjs.Switch,
929
+ {
930
+ id: "colorField",
931
+ checked: settings.field === settings.colorField,
932
+ onCheckedChange: (checked) => onSettingsChange({
933
+ ...settings,
934
+ colorField: checked ? settings.field : void 0,
935
+ colorScaleId: checked && settings.field ? getOrCreateScaleForField(settings.field) : void 0
936
+ })
937
+ }
938
+ ),
939
+ /* @__PURE__ */ jsxRuntime.jsx(chunkMJROUIDZ_cjs.Label, { htmlFor: "colorField", children: "Use as color field" })
940
+ ] }) })
941
+ ] })
942
+ ] });
943
+ }
944
+
945
+ // src/components/charts/BarChart/definition.ts
946
+ var barChartDefinition = {
947
+ type: "bar",
948
+ name: "Bar Chart",
949
+ description: "Display data as vertical bars",
950
+ icon: lucideReact.ChartBarBig,
951
+ component: BarChart,
952
+ settingsPanel: BarChartSettingsPanel,
953
+ createDefaultSettings: (layout, field) => ({
954
+ ...chunkU74A5VK5_cjs.DEFAULT_CHART_SETTINGS,
955
+ id: crypto.randomUUID(),
956
+ field: field ?? "",
957
+ binCount: 10,
958
+ type: "bar",
959
+ title: "Bar Chart",
960
+ layout,
961
+ margin: { top: 20, right: 20, bottom: 30, left: 60 },
962
+ filters: []
963
+ }),
964
+ validateSettings: (settings) => {
965
+ return !!settings.field;
966
+ },
967
+ getFilterFunction: (settings, fieldGetter) => {
968
+ const filter = settings.aggregateId ? [...settings.filters].reverse().find(
969
+ (f) => f.type === "range" || f.type === "date-range"
970
+ ) : settings.filters.find((f) => f.field === settings.field);
971
+ const dataHash = fieldGetter(filter?.field ?? settings.field);
972
+ return (d) => {
973
+ const value = dataHash[d];
974
+ if (filter) {
975
+ if (!chunkEU5EFHO5_cjs.applyFilter(value, filter)) {
976
+ return false;
977
+ }
978
+ }
979
+ return true;
980
+ };
981
+ }
982
+ };
983
+
984
+ exports.barChartDefinition = barChartDefinition;
985
+ //# sourceMappingURL=chunk-JDMUN4VK.cjs.map
986
+ //# sourceMappingURL=chunk-JDMUN4VK.cjs.map