exploreda 0.0.6 → 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 -11288
  3. package/dist/ExplorEda.cjs.map +1 -1
  4. package/dist/ExplorEda.css +2282 -1689
  5. package/dist/ExplorEda.css.map +1 -1
  6. package/dist/ExplorEda.d.cts +124 -278
  7. package/dist/ExplorEda.d.ts +124 -278
  8. package/dist/ExplorEda.js +4479 -11166
  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 +30 -52
@@ -0,0 +1,911 @@
1
+ 'use strict';
2
+
3
+ var chunkU74A5VK5_cjs = require('./chunk-U74A5VK5.cjs');
4
+ var chunkASKFIRMC_cjs = require('./chunk-ASKFIRMC.cjs');
5
+ var chunkDKFA4KOJ_cjs = require('./chunk-DKFA4KOJ.cjs');
6
+ var chunkEU5EFHO5_cjs = require('./chunk-EU5EFHO5.cjs');
7
+ var chunk3PGYFLE3_cjs = require('./chunk-3PGYFLE3.cjs');
8
+ var chunkMJROUIDZ_cjs = require('./chunk-MJROUIDZ.cjs');
9
+ var chunk5B23JVH3_cjs = require('./chunk-5B23JVH3.cjs');
10
+ var lucideReact = require('lucide-react');
11
+ var react = require('react');
12
+ var jsxRuntime = require('react/jsx-runtime');
13
+
14
+ // src/components/charts/PivotTable/utils/calculations.ts
15
+ var numericAggregations = /* @__PURE__ */ new Set([
16
+ "sum",
17
+ "avg",
18
+ "min",
19
+ "max",
20
+ "median",
21
+ "stddev",
22
+ "variance"
23
+ ]);
24
+ function aggregate(name, values) {
25
+ const includedIndexes = /* @__PURE__ */ new Set();
26
+ const numeric = numericAggregations.has(name) ? chunk5B23JVH3_cjs.numericInputs(values) : { inputs: [], exclusions: [] };
27
+ numeric.inputs.forEach(({ index }) => includedIndexes.add(index));
28
+ if (name === "count") {
29
+ values.forEach((_, index) => includedIndexes.add(index));
30
+ return { value: values.length, includedIndexes, numericExclusions: [] };
31
+ }
32
+ if (name === "countUnique") {
33
+ values.forEach((_, index) => includedIndexes.add(index));
34
+ return {
35
+ value: new Set(values).size,
36
+ includedIndexes,
37
+ numericExclusions: []
38
+ };
39
+ }
40
+ if (name === "mode") {
41
+ values.forEach((_, index) => includedIndexes.add(index));
42
+ const counts = /* @__PURE__ */ new Map();
43
+ values.forEach((value2) => {
44
+ const key = value2 ?? null;
45
+ counts.set(key, (counts.get(key) || 0) + 1);
46
+ });
47
+ let maxCount = 0;
48
+ let value = void 0;
49
+ counts.forEach((count, candidate) => {
50
+ if (count > maxCount) {
51
+ maxCount = count;
52
+ value = candidate === null ? void 0 : candidate;
53
+ }
54
+ });
55
+ return { value, includedIndexes, numericExclusions: [] };
56
+ }
57
+ if (name === "singleValue") {
58
+ if (values.length === 0) {
59
+ return { value: void 0, includedIndexes, numericExclusions: [] };
60
+ }
61
+ const uniqueValues = new Set(values.map((value) => chunk5B23JVH3_cjs.categoryKey(value)));
62
+ if (uniqueValues.size !== 1) {
63
+ throw new Error("Multiple values found when single value expected");
64
+ }
65
+ values.forEach((_, index) => includedIndexes.add(index));
66
+ return { value: values[0], includedIndexes, numericExclusions: [] };
67
+ }
68
+ if (!numericAggregations.has(name)) {
69
+ throw new Error(`Unsupported aggregation: ${name}`);
70
+ }
71
+ const numbers = numeric.inputs.map(({ value }) => value);
72
+ if (numbers.length === 0) {
73
+ return {
74
+ value: void 0,
75
+ includedIndexes,
76
+ numericExclusions: numeric.exclusions
77
+ };
78
+ }
79
+ if (name === "sum") {
80
+ return {
81
+ value: numbers.reduce((sum, value) => sum + value, 0),
82
+ includedIndexes,
83
+ numericExclusions: numeric.exclusions
84
+ };
85
+ }
86
+ if (name === "avg") {
87
+ return {
88
+ value: numbers.reduce((sum, value) => sum + value, 0) / numbers.length,
89
+ includedIndexes,
90
+ numericExclusions: numeric.exclusions
91
+ };
92
+ }
93
+ if (name === "min") {
94
+ return {
95
+ value: Math.min(...numbers),
96
+ includedIndexes,
97
+ numericExclusions: numeric.exclusions
98
+ };
99
+ }
100
+ if (name === "max") {
101
+ return {
102
+ value: Math.max(...numbers),
103
+ includedIndexes,
104
+ numericExclusions: numeric.exclusions
105
+ };
106
+ }
107
+ if (name === "median") {
108
+ const sorted = [...numbers].sort((a, b) => a - b);
109
+ const mid = Math.floor(sorted.length / 2);
110
+ return {
111
+ value: sorted.length % 2 ? sorted[mid] : (sorted[mid - 1] + sorted[mid]) / 2,
112
+ includedIndexes,
113
+ numericExclusions: numeric.exclusions
114
+ };
115
+ }
116
+ const average = numbers.reduce((sum, value) => sum + value, 0) / numbers.length;
117
+ const squareDiffs = numbers.map((value) => (value - average) ** 2);
118
+ const variance = squareDiffs.reduce((sum, value) => sum + value, 0) / squareDiffs.length;
119
+ return {
120
+ value: name === "stddev" ? Math.sqrt(variance) : variance,
121
+ includedIndexes,
122
+ numericExclusions: numeric.exclusions
123
+ };
124
+ }
125
+ function generateHeaders(data, field) {
126
+ if (!field) {
127
+ return [];
128
+ }
129
+ const uniqueValues = /* @__PURE__ */ new Map();
130
+ data.forEach((row) => {
131
+ const value = chunk5B23JVH3_cjs.categoryValue(row[field]);
132
+ const key = chunk5B23JVH3_cjs.categoryKey(value);
133
+ if (!uniqueValues.has(key)) {
134
+ uniqueValues.set(key, value);
135
+ }
136
+ });
137
+ return Array.from(uniqueValues.values()).sort((left, right) => chunk5B23JVH3_cjs.categoryKey(left).localeCompare(chunk5B23JVH3_cjs.categoryKey(right))).map((value) => ({
138
+ label: chunk5B23JVH3_cjs.categoryLabel(value),
139
+ field,
140
+ value,
141
+ children: [],
142
+ span: 1,
143
+ depth: 0
144
+ }));
145
+ }
146
+ function makeContributors(rows, groupingKeys, valueField, result) {
147
+ const exclusionByIndex = new Map(
148
+ result.numericExclusions.map((exclusion) => [
149
+ exclusion.index,
150
+ exclusion.reason
151
+ ])
152
+ );
153
+ const contributors = rows.map((row, index) => ({
154
+ sourceId: row.__ID,
155
+ groupingKeys,
156
+ input: row[valueField],
157
+ included: result.includedIndexes.has(index),
158
+ exclusionReason: exclusionByIndex.get(index)
159
+ }));
160
+ return {
161
+ contributors,
162
+ numericExclusions: result.numericExclusions.map(({ index, reason }) => ({
163
+ sourceId: rows[index]?.__ID,
164
+ value: rows[index]?.[valueField],
165
+ reason
166
+ }))
167
+ };
168
+ }
169
+ function generateCell(rows, groupingKeys, columnField, columnValue, isTotal, valueField) {
170
+ const values = rows.map((row) => row[valueField.field]);
171
+ let result;
172
+ let error;
173
+ try {
174
+ result = aggregate(valueField.aggregation, values);
175
+ } catch (caught) {
176
+ result = {
177
+ value: void 0,
178
+ includedIndexes: /* @__PURE__ */ new Set(),
179
+ numericExclusions: []
180
+ };
181
+ error = caught instanceof Error ? caught.message : "Aggregation failed";
182
+ }
183
+ const { contributors, numericExclusions } = makeContributors(
184
+ rows,
185
+ groupingKeys,
186
+ valueField.field,
187
+ result
188
+ );
189
+ const status = error ? "error" : rows.length === 0 ? "empty" : result.numericExclusions.length > 0 && result.includedIndexes.size === 0 ? "invalid" : "ok";
190
+ return {
191
+ key: {
192
+ columnField,
193
+ columnValue,
194
+ valueField: valueField.field,
195
+ isTotal
196
+ },
197
+ value: result.value,
198
+ rawValue: result.value,
199
+ aggregation: valueField.aggregation,
200
+ status,
201
+ error,
202
+ contributors,
203
+ numericExclusions
204
+ };
205
+ }
206
+ function generateCells(rowData, columnHeaders, rowKeys, hasColumnField, valueFields) {
207
+ const cells = [];
208
+ const headers = hasColumnField ? columnHeaders : [{ field: "total", value: "total" }];
209
+ headers.forEach((header) => {
210
+ const columnData = hasColumnField ? rowData.filter(
211
+ (row) => chunk5B23JVH3_cjs.categoryEqual(chunk5B23JVH3_cjs.categoryValue(row[header.field]), header.value)
212
+ ) : rowData;
213
+ const groupingKeys = !hasColumnField ? rowKeys : [...rowKeys, { field: header.field, value: header.value }];
214
+ valueFields.forEach((valueField) => {
215
+ cells.push(
216
+ generateCell(
217
+ columnData,
218
+ groupingKeys,
219
+ hasColumnField ? header.field : "total",
220
+ header.value,
221
+ !hasColumnField,
222
+ valueField
223
+ )
224
+ );
225
+ });
226
+ });
227
+ return cells;
228
+ }
229
+ function generateRows(data, rowFields, columnField, valueFields) {
230
+ const rows = [];
231
+ const columnHeaders = generateHeaders(data, columnField);
232
+ const rowGroups = /* @__PURE__ */ new Map();
233
+ data.forEach((item) => {
234
+ const keyString = JSON.stringify(
235
+ rowFields.map((field) => chunk5B23JVH3_cjs.categoryKey(chunk5B23JVH3_cjs.categoryValue(item[field])))
236
+ );
237
+ if (!rowGroups.has(keyString)) {
238
+ rowGroups.set(keyString, []);
239
+ }
240
+ rowGroups.get(keyString).push(item);
241
+ });
242
+ rowGroups.forEach((groupData) => {
243
+ const keys = rowFields.map((field) => ({
244
+ field,
245
+ value: chunk5B23JVH3_cjs.categoryValue(groupData[0][field])
246
+ }));
247
+ const headers = keys.map((key, index) => ({
248
+ label: chunk5B23JVH3_cjs.categoryLabel(key.value),
249
+ field: key.field,
250
+ value: key.value,
251
+ span: 1,
252
+ depth: index
253
+ }));
254
+ rows.push({
255
+ keys,
256
+ headers,
257
+ cells: generateCells(
258
+ groupData,
259
+ columnHeaders,
260
+ keys,
261
+ Boolean(columnField),
262
+ valueFields
263
+ )
264
+ });
265
+ });
266
+ return rows;
267
+ }
268
+ function calculatePivotData(data, settings) {
269
+ return {
270
+ headers: generateHeaders(data, settings.columnField),
271
+ rows: generateRows(
272
+ data,
273
+ settings.rowFields,
274
+ settings.columnField,
275
+ settings.valueFields
276
+ )
277
+ };
278
+ }
279
+ function displayValue(value) {
280
+ if (value === void 0 || value === null || value === "") {
281
+ return "Missing";
282
+ }
283
+ if (typeof value === "number") {
284
+ return String(value);
285
+ }
286
+ if (typeof value === "string") {
287
+ return JSON.stringify(value);
288
+ }
289
+ return String(value);
290
+ }
291
+ function displayExactValue(value) {
292
+ if (value === void 0) {
293
+ return "undefined";
294
+ }
295
+ if (value === null) {
296
+ return "null";
297
+ }
298
+ if (typeof value === "string") {
299
+ return JSON.stringify(value);
300
+ }
301
+ return String(value);
302
+ }
303
+ function displayCellValue(cell) {
304
+ if (cell.status === "empty") {
305
+ return "No rows";
306
+ }
307
+ if (cell.status === "error") {
308
+ return "Conflict";
309
+ }
310
+ if (cell.status === "invalid") {
311
+ return "No valid numbers";
312
+ }
313
+ return displayValue(cell.value);
314
+ }
315
+ function cellName(cell, rowHeaders) {
316
+ const rowLabel = rowHeaders.map((header) => header.label).join(" / ");
317
+ const columnLabel = cell.key.isTotal ? "Total" : displayValue(cell.key.columnValue);
318
+ return [rowLabel, columnLabel, cell.key.valueField].filter(Boolean).join(" \xB7 ");
319
+ }
320
+ function PivotTable({ settings, height, facetIds }) {
321
+ const getColumnData = chunk5B23JVH3_cjs.useDataLayer((state) => state.getColumnData);
322
+ const getFieldLabel = chunk5B23JVH3_cjs.useDataLayer((state) => state.getFieldLabel);
323
+ const formatFieldValue = chunk5B23JVH3_cjs.useDataLayer((state) => state.formatFieldValue);
324
+ const fieldSettings = chunk5B23JVH3_cjs.useDataLayer((state) => state.fieldSettings);
325
+ const updateChart = chunk5B23JVH3_cjs.useDataLayer((state) => state.updateChart);
326
+ const allLiveIds = chunkDKFA4KOJ_cjs.useGetLiveIds(settings);
327
+ const pivotData = react.useMemo(() => {
328
+ const liveIds = facetIds ? allLiveIds.filter((id) => facetIds.includes(id)) : allLiveIds;
329
+ const allFields = /* @__PURE__ */ new Set([
330
+ ...settings.rowFields,
331
+ settings.columnField,
332
+ ...settings.valueFields.map((f) => f.field)
333
+ ]);
334
+ const fieldData = {};
335
+ allFields.forEach((field) => {
336
+ fieldData[field] = getColumnData(field);
337
+ });
338
+ const data = liveIds.map((id) => {
339
+ const row = {
340
+ __ID: id
341
+ };
342
+ allFields.forEach((field) => {
343
+ row[field] = fieldData[field]?.[id];
344
+ });
345
+ return row;
346
+ });
347
+ return calculatePivotData(data, settings);
348
+ }, [facetIds, allLiveIds, settings, getColumnData]);
349
+ const [selectedCell, setSelectedCell] = react.useState(null);
350
+ const lastTrigger = react.useRef(null);
351
+ const [contributorPage, setContributorPage] = react.useState(0);
352
+ react.useEffect(() => {
353
+ setSelectedCell(null);
354
+ }, [pivotData, settings]);
355
+ react.useEffect(() => {
356
+ setContributorPage(0);
357
+ }, [selectedCell]);
358
+ const handleFilterClick = react.useCallback(
359
+ (field, value) => {
360
+ const currentFilters = settings.filters || [];
361
+ const existingFilterIndex = currentFilters.findIndex(
362
+ (f) => f.type === "value" && f.field === field && chunk5B23JVH3_cjs.categoryIncludes(f.values, value)
363
+ );
364
+ let newFilters;
365
+ if (existingFilterIndex >= 0) {
366
+ newFilters = [
367
+ ...currentFilters.slice(0, existingFilterIndex),
368
+ ...currentFilters.slice(existingFilterIndex + 1)
369
+ ];
370
+ } else {
371
+ const newFilter = {
372
+ type: "value",
373
+ field,
374
+ values: [value]
375
+ };
376
+ newFilters = [...currentFilters, newFilter];
377
+ }
378
+ updateChart(settings.id, {
379
+ ...settings,
380
+ filters: newFilters
381
+ });
382
+ },
383
+ [settings, updateChart]
384
+ );
385
+ const isValueFiltered = react.useCallback(
386
+ (field, value) => {
387
+ const currentFilters = settings.filters || [];
388
+ const fieldFilters = currentFilters.filter((f) => f.field === field);
389
+ if (fieldFilters.length === 0) {
390
+ return false;
391
+ }
392
+ return fieldFilters.some((filter) => chunkEU5EFHO5_cjs.applyFilter(value, filter));
393
+ },
394
+ [settings.filters]
395
+ );
396
+ const isCellFiltered = react.useCallback(
397
+ (rowHeaders, cellKey) => {
398
+ const currentFilters = settings.filters || [];
399
+ if (currentFilters.length === 0) {
400
+ return false;
401
+ }
402
+ const rowFieldFilters = rowHeaders.map((header) => {
403
+ const fieldFilters = currentFilters.filter(
404
+ (f) => f.field === header.field
405
+ );
406
+ return {
407
+ header,
408
+ filters: fieldFilters
409
+ };
410
+ });
411
+ const hasRowFilters = rowFieldFilters.some((rf) => rf.filters.length > 0);
412
+ const rowMatches = !hasRowFilters || rowFieldFilters.every(
413
+ ({ header, filters }) => filters.length === 0 || filters.some((filter) => chunkEU5EFHO5_cjs.applyFilter(header.value, filter))
414
+ );
415
+ const columnFilters = currentFilters.filter(
416
+ (f) => !cellKey.isTotal && f.field === cellKey.columnField
417
+ );
418
+ const hasColumnFilters = columnFilters.length > 0;
419
+ const columnMatches = !hasColumnFilters || columnFilters.some(
420
+ (filter) => chunkEU5EFHO5_cjs.applyFilter(cellKey.columnValue, filter)
421
+ );
422
+ return rowMatches && columnMatches;
423
+ },
424
+ [settings.filters]
425
+ );
426
+ const filterButton = (header) => /* @__PURE__ */ jsxRuntime.jsxs(
427
+ "button",
428
+ {
429
+ type: "button",
430
+ className: "eda-pivot-filter",
431
+ "aria-label": `Filter ${header.field} by ${header.label}`,
432
+ "aria-pressed": isValueFiltered(header.field, header.value),
433
+ onClick: () => handleFilterClick(header.field, header.value),
434
+ children: [
435
+ /* @__PURE__ */ jsxRuntime.jsx("span", { children: chunk5B23JVH3_cjs.hasFieldDisplayFormat(fieldSettings[header.field]) ? formatFieldValue?.(header.field, header.value) ?? header.label : header.label }),
436
+ /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Filter, { "aria-hidden": "true" })
437
+ ]
438
+ }
439
+ );
440
+ const valueLabel = (field, aggregation, label) => label || `${getFieldLabel?.(field) ?? field} (${aggregation})`;
441
+ const displayPivotCell = (cell) => {
442
+ if (cell.status !== "ok") return displayCellValue(cell);
443
+ return chunk5B23JVH3_cjs.hasFieldDisplayFormat(fieldSettings[cell.key.valueField]) ? formatFieldValue?.(cell.key.valueField, cell.value) ?? displayCellValue(cell) : displayCellValue(cell);
444
+ };
445
+ const selectedCellName = selectedCell ? cellName(selectedCell.cell, selectedCell.rowHeaders) : "";
446
+ const valueColumnCount = settings.valueFields.length * (settings.columnField ? pivotData.headers.length : 1);
447
+ const contributorPageSize = 50;
448
+ const contributorCount = selectedCell?.cell.contributors.length ?? 0;
449
+ const contributorPageCount = Math.max(
450
+ 1,
451
+ Math.ceil(contributorCount / contributorPageSize)
452
+ );
453
+ const contributorStart = contributorPage * contributorPageSize;
454
+ const visibleContributors = selectedCell?.cell.contributors.slice(
455
+ contributorStart,
456
+ contributorStart + contributorPageSize
457
+ ) ?? [];
458
+ return /* @__PURE__ */ jsxRuntime.jsxs(
459
+ "div",
460
+ {
461
+ className: "w-full min-h-0 overflow-auto",
462
+ style: { height },
463
+ tabIndex: 0,
464
+ "aria-label": "Pivot table, scroll to see more",
465
+ children: [
466
+ /* @__PURE__ */ jsxRuntime.jsxs(
467
+ "table",
468
+ {
469
+ className: "eda-pivot-table",
470
+ style: {
471
+ minWidth: settings.rowFields.length * 140 + valueColumnCount * 112
472
+ },
473
+ children: [
474
+ /* @__PURE__ */ jsxRuntime.jsx("caption", { className: "sr-only", children: chunk5B23JVH3_cjs.getChartSummary(settings) }),
475
+ /* @__PURE__ */ jsxRuntime.jsxs("colgroup", { children: [
476
+ settings.rowFields.map((field) => /* @__PURE__ */ jsxRuntime.jsx("col", { style: { width: 140 } }, field)),
477
+ Array.from({ length: valueColumnCount }, (_, index) => /* @__PURE__ */ jsxRuntime.jsx("col", {}, index))
478
+ ] }),
479
+ /* @__PURE__ */ jsxRuntime.jsxs("thead", { className: "sticky top-0 z-30", children: [
480
+ /* @__PURE__ */ jsxRuntime.jsxs("tr", { children: [
481
+ settings.rowFields.map((field, index) => /* @__PURE__ */ jsxRuntime.jsx(
482
+ "th",
483
+ {
484
+ scope: "col",
485
+ rowSpan: settings.columnField ? 2 : 1,
486
+ className: "eda-pivot-row-label",
487
+ style: { left: index * 140, zIndex: 20 - index },
488
+ children: getFieldLabel?.(field) ?? field
489
+ },
490
+ field
491
+ )),
492
+ settings.columnField ? pivotData.headers.map((header) => /* @__PURE__ */ jsxRuntime.jsx(
493
+ "th",
494
+ {
495
+ scope: "colgroup",
496
+ colSpan: settings.valueFields.length,
497
+ children: filterButton(header)
498
+ },
499
+ `${header.field}-${chunk5B23JVH3_cjs.categoryKey(header.value)}`
500
+ )) : settings.valueFields.map((valueField) => /* @__PURE__ */ jsxRuntime.jsx("th", { scope: "col", children: valueLabel(
501
+ valueField.field,
502
+ valueField.aggregation,
503
+ valueField.label
504
+ ) }, valueField.field))
505
+ ] }),
506
+ settings.columnField && /* @__PURE__ */ jsxRuntime.jsx("tr", { children: pivotData.headers.flatMap(
507
+ (header) => settings.valueFields.map((valueField) => /* @__PURE__ */ jsxRuntime.jsx(
508
+ "th",
509
+ {
510
+ scope: "col",
511
+ children: valueLabel(
512
+ valueField.field,
513
+ valueField.aggregation,
514
+ valueField.label
515
+ )
516
+ },
517
+ `${header.field}-${chunk5B23JVH3_cjs.categoryKey(header.value)}-${valueField.field}`
518
+ ))
519
+ ) })
520
+ ] }),
521
+ /* @__PURE__ */ jsxRuntime.jsxs("tbody", { children: [
522
+ pivotData.rows.map((row) => /* @__PURE__ */ jsxRuntime.jsxs(
523
+ "tr",
524
+ {
525
+ children: [
526
+ row.headers.map((header, index) => /* @__PURE__ */ jsxRuntime.jsx(
527
+ "th",
528
+ {
529
+ scope: "row",
530
+ className: "eda-pivot-row-label",
531
+ style: { left: index * 140, zIndex: 10 - index },
532
+ children: filterButton(header)
533
+ },
534
+ `${header.field}-${chunk5B23JVH3_cjs.categoryKey(header.value)}`
535
+ )),
536
+ row.cells.map((cell) => /* @__PURE__ */ jsxRuntime.jsx(
537
+ "td",
538
+ {
539
+ className: chunk5B23JVH3_cjs.cn(
540
+ isCellFiltered(row.headers, cell.key) && "is-selected"
541
+ ),
542
+ children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center justify-end gap-2", children: [
543
+ /* @__PURE__ */ jsxRuntime.jsx(
544
+ chunk5B23JVH3_cjs.ActionTooltip,
545
+ {
546
+ content: cell.error ?? cellName(cell, row.headers),
547
+ children: /* @__PURE__ */ jsxRuntime.jsx("span", { tabIndex: cell.error ? 0 : void 0, children: displayPivotCell(cell) })
548
+ }
549
+ ),
550
+ /* @__PURE__ */ jsxRuntime.jsx(
551
+ "button",
552
+ {
553
+ type: "button",
554
+ className: "rounded px-1 text-[10px] text-muted-foreground underline-offset-2 hover:underline focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring",
555
+ "aria-haspopup": "dialog",
556
+ "aria-label": `Inspect ${cellName(cell, row.headers)}`,
557
+ onClick: (event) => {
558
+ lastTrigger.current = event.currentTarget;
559
+ setSelectedCell({ cell, rowHeaders: row.headers });
560
+ },
561
+ children: "Inspect"
562
+ }
563
+ )
564
+ ] })
565
+ },
566
+ `${cell.key.isTotal ? "total" : cell.key.columnField}-${chunk5B23JVH3_cjs.categoryKey(cell.key.columnValue)}-${cell.key.valueField}`
567
+ ))
568
+ ]
569
+ },
570
+ JSON.stringify(
571
+ row.keys.map((key) => [key.field, chunk5B23JVH3_cjs.categoryKey(key.value)])
572
+ )
573
+ )),
574
+ pivotData.rows.length === 0 && /* @__PURE__ */ jsxRuntime.jsx("tr", { children: /* @__PURE__ */ jsxRuntime.jsx(
575
+ "td",
576
+ {
577
+ colSpan: settings.rowFields.length + valueColumnCount,
578
+ className: "text-muted-foreground",
579
+ children: "No matching rows"
580
+ }
581
+ ) })
582
+ ] })
583
+ ]
584
+ }
585
+ ),
586
+ /* @__PURE__ */ jsxRuntime.jsx(
587
+ chunkMJROUIDZ_cjs.Dialog,
588
+ {
589
+ open: selectedCell !== null,
590
+ onOpenChange: (open) => {
591
+ if (!open) {
592
+ setSelectedCell(null);
593
+ window.setTimeout(() => lastTrigger.current?.focus(), 0);
594
+ }
595
+ },
596
+ children: /* @__PURE__ */ jsxRuntime.jsx(chunkMJROUIDZ_cjs.DialogContent, { className: "max-h-[80vh] max-w-3xl overflow-y-auto", children: selectedCell && /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
597
+ /* @__PURE__ */ jsxRuntime.jsxs(chunkMJROUIDZ_cjs.DialogHeader, { children: [
598
+ /* @__PURE__ */ jsxRuntime.jsxs(chunkMJROUIDZ_cjs.DialogTitle, { children: [
599
+ "Inspect ",
600
+ selectedCellName
601
+ ] }),
602
+ /* @__PURE__ */ jsxRuntime.jsx(chunkMJROUIDZ_cjs.DialogDescription, { children: "This cell uses the current filtered rows and the same aggregation as the table." })
603
+ ] }),
604
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "grid gap-2 text-sm sm:grid-cols-3", children: [
605
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
606
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "text-muted-foreground", children: "Aggregation" }),
607
+ /* @__PURE__ */ jsxRuntime.jsx("div", { children: selectedCell.cell.aggregation })
608
+ ] }),
609
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
610
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "text-muted-foreground", children: "Result" }),
611
+ /* @__PURE__ */ jsxRuntime.jsx("div", { children: displayPivotCell(selectedCell.cell) })
612
+ ] }),
613
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
614
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "text-muted-foreground", children: "Contributors" }),
615
+ /* @__PURE__ */ jsxRuntime.jsx("div", { children: selectedCell.cell.contributors.length })
616
+ ] })
617
+ ] }),
618
+ selectedCell.cell.error && /* @__PURE__ */ jsxRuntime.jsxs(
619
+ "p",
620
+ {
621
+ role: "alert",
622
+ className: "rounded border border-destructive/50 p-2 text-sm text-destructive",
623
+ children: [
624
+ selectedCell.cell.error,
625
+ ". The other pivot cells remain available."
626
+ ]
627
+ }
628
+ ),
629
+ selectedCell.cell.numericExclusions.length > 0 && /* @__PURE__ */ jsxRuntime.jsxs("p", { className: "text-sm text-muted-foreground", children: [
630
+ selectedCell.cell.numericExclusions.length,
631
+ " numeric value(s) excluded; the result uses the",
632
+ " ",
633
+ selectedCell.cell.contributors.filter(
634
+ (contributor) => contributor.included
635
+ ).length,
636
+ " ",
637
+ "valid value(s)."
638
+ ] }),
639
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "overflow-auto rounded border", children: [
640
+ /* @__PURE__ */ jsxRuntime.jsxs("table", { className: "w-full text-left text-sm", children: [
641
+ /* @__PURE__ */ jsxRuntime.jsx("caption", { className: "sr-only", children: "Pivot cell contributors" }),
642
+ /* @__PURE__ */ jsxRuntime.jsx("thead", { className: "bg-muted", children: /* @__PURE__ */ jsxRuntime.jsxs("tr", { children: [
643
+ /* @__PURE__ */ jsxRuntime.jsx("th", { className: "p-2", scope: "col", children: "Source row ID (zero-based)" }),
644
+ /* @__PURE__ */ jsxRuntime.jsx("th", { className: "p-2", scope: "col", children: "Grouping keys" }),
645
+ /* @__PURE__ */ jsxRuntime.jsx("th", { className: "p-2", scope: "col", children: "Input" }),
646
+ /* @__PURE__ */ jsxRuntime.jsx("th", { className: "p-2", scope: "col", children: "Used" })
647
+ ] }) }),
648
+ /* @__PURE__ */ jsxRuntime.jsx("tbody", { children: visibleContributors.map((contributor, index) => /* @__PURE__ */ jsxRuntime.jsxs(
649
+ "tr",
650
+ {
651
+ className: "border-t",
652
+ children: [
653
+ /* @__PURE__ */ jsxRuntime.jsx("td", { className: "p-2", children: contributor.sourceId ?? "Unknown" }),
654
+ /* @__PURE__ */ jsxRuntime.jsx("td", { className: "p-2", children: contributor.groupingKeys.map(
655
+ (key) => `${key.field}=${displayValue(key.value)}`
656
+ ).join(", ") }),
657
+ /* @__PURE__ */ jsxRuntime.jsx("td", { className: "p-2", children: displayExactValue(contributor.input) }),
658
+ /* @__PURE__ */ jsxRuntime.jsx("td", { className: "p-2", children: contributor.included ? "Yes" : contributor.exclusionReason || "No" })
659
+ ]
660
+ },
661
+ `${contributor.sourceId ?? "unknown"}-${index}`
662
+ )) })
663
+ ] }),
664
+ contributorCount === 0 && /* @__PURE__ */ jsxRuntime.jsx("p", { className: "p-3 text-sm text-muted-foreground", children: "No rows match this cell." })
665
+ ] }),
666
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center justify-between gap-3 text-sm text-muted-foreground", children: [
667
+ /* @__PURE__ */ jsxRuntime.jsxs("span", { children: [
668
+ "Showing ",
669
+ contributorCount === 0 ? 0 : contributorStart + 1,
670
+ "\u2013",
671
+ Math.min(
672
+ contributorStart + contributorPageSize,
673
+ contributorCount
674
+ ),
675
+ " ",
676
+ "of ",
677
+ contributorCount,
678
+ " source rows"
679
+ ] }),
680
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex gap-2", children: [
681
+ /* @__PURE__ */ jsxRuntime.jsx(
682
+ "button",
683
+ {
684
+ type: "button",
685
+ className: "rounded border px-2 py-1 disabled:cursor-not-allowed disabled:opacity-50",
686
+ disabled: contributorPage === 0,
687
+ onClick: () => setContributorPage((page) => page - 1),
688
+ children: "Previous"
689
+ }
690
+ ),
691
+ /* @__PURE__ */ jsxRuntime.jsx(
692
+ "button",
693
+ {
694
+ type: "button",
695
+ className: "rounded border px-2 py-1 disabled:cursor-not-allowed disabled:opacity-50",
696
+ disabled: contributorPage >= contributorPageCount - 1,
697
+ onClick: () => setContributorPage((page) => page + 1),
698
+ children: "Next"
699
+ }
700
+ )
701
+ ] })
702
+ ] })
703
+ ] }) })
704
+ }
705
+ )
706
+ ]
707
+ }
708
+ );
709
+ }
710
+ var AGGREGATION_OPTIONS = [
711
+ { label: "Sum", value: "sum" },
712
+ { label: "Count", value: "count" },
713
+ { label: "Average", value: "avg" },
714
+ { label: "Min", value: "min" },
715
+ { label: "Max", value: "max" },
716
+ { label: "Median", value: "median" },
717
+ { label: "Mode", value: "mode" },
718
+ { label: "StdDev", value: "stddev" },
719
+ { label: "Variance", value: "variance" },
720
+ { label: "Count Unique", value: "countUnique" },
721
+ { label: "Single Value", value: "singleValue" }
722
+ ];
723
+ function PivotTableSettingsPanel({
724
+ settings,
725
+ onSettingsChange
726
+ }) {
727
+ const availableFields = chunk3PGYFLE3_cjs.useColumnNames();
728
+ const fieldOptions = availableFields.map((f) => ({
729
+ label: f,
730
+ value: f
731
+ }));
732
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-4", children: [
733
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-2", children: [
734
+ /* @__PURE__ */ jsxRuntime.jsx(chunkMJROUIDZ_cjs.Label, { children: "Row Fields" }),
735
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "max-w-[400px]", children: /* @__PURE__ */ jsxRuntime.jsx(
736
+ chunk3PGYFLE3_cjs.multi_select_default,
737
+ {
738
+ options: fieldOptions,
739
+ value: settings.rowFields.map((f) => ({
740
+ label: f,
741
+ value: f
742
+ })),
743
+ onChange: (values) => onSettingsChange({
744
+ ...settings,
745
+ rowFields: values.map((v) => v.value)
746
+ })
747
+ }
748
+ ) })
749
+ ] }),
750
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "space-y-2", children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: "max-w-[400px]", children: /* @__PURE__ */ jsxRuntime.jsx(
751
+ chunkASKFIRMC_cjs.FieldSelector,
752
+ {
753
+ label: "Column Field",
754
+ value: settings.columnField,
755
+ onChange: (value) => onSettingsChange({ ...settings, columnField: value })
756
+ }
757
+ ) }) }),
758
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-2", children: [
759
+ /* @__PURE__ */ jsxRuntime.jsx(chunkMJROUIDZ_cjs.Label, { children: "Value Fields" }),
760
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "max-w-[400px] space-y-2", children: [
761
+ settings.valueFields.map((valueField, index) => /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-2", children: [
762
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex-1", children: /* @__PURE__ */ jsxRuntime.jsx(
763
+ chunkASKFIRMC_cjs.ComboBox,
764
+ {
765
+ options: fieldOptions,
766
+ value: fieldOptions.find((f) => f.value === valueField.field),
767
+ onChange: (option) => {
768
+ const newValueFields = [...settings.valueFields];
769
+ newValueFields[index] = {
770
+ ...valueField,
771
+ field: option?.value || valueField.field
772
+ };
773
+ onSettingsChange({
774
+ ...settings,
775
+ valueFields: newValueFields
776
+ });
777
+ },
778
+ optionToString: (option) => option.label
779
+ }
780
+ ) }),
781
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex-1", children: /* @__PURE__ */ jsxRuntime.jsx(
782
+ chunkASKFIRMC_cjs.ComboBox,
783
+ {
784
+ options: AGGREGATION_OPTIONS,
785
+ value: AGGREGATION_OPTIONS.find(
786
+ (o) => o.value === valueField.aggregation
787
+ ),
788
+ onChange: (option) => {
789
+ if (!option) {
790
+ return;
791
+ }
792
+ const newValueFields = [...settings.valueFields];
793
+ newValueFields[index] = {
794
+ ...valueField,
795
+ aggregation: option.value
796
+ };
797
+ onSettingsChange({
798
+ ...settings,
799
+ valueFields: newValueFields
800
+ });
801
+ },
802
+ optionToString: (option) => option.label
803
+ }
804
+ ) }),
805
+ /* @__PURE__ */ jsxRuntime.jsx(
806
+ "button",
807
+ {
808
+ className: "p-2 hover:bg-accent rounded",
809
+ onClick: () => {
810
+ const newValueFields = settings.valueFields.filter(
811
+ (_, i) => i !== index
812
+ );
813
+ onSettingsChange({
814
+ ...settings,
815
+ valueFields: newValueFields
816
+ });
817
+ },
818
+ children: "\xD7"
819
+ }
820
+ )
821
+ ] }, index)),
822
+ /* @__PURE__ */ jsxRuntime.jsx(
823
+ "button",
824
+ {
825
+ className: "text-sm text-primary hover:text-primary/80",
826
+ onClick: () => {
827
+ const field = availableFields[0];
828
+ if (!field) {
829
+ return;
830
+ }
831
+ onSettingsChange({
832
+ ...settings,
833
+ valueFields: [
834
+ ...settings.valueFields,
835
+ {
836
+ field,
837
+ aggregation: "count"
838
+ }
839
+ ]
840
+ });
841
+ },
842
+ children: "+ Add Value Field"
843
+ }
844
+ )
845
+ ] })
846
+ ] })
847
+ ] });
848
+ }
849
+
850
+ // src/components/charts/PivotTable/definition.ts
851
+ var VALID_AGGREGATIONS = /* @__PURE__ */ new Set([
852
+ "sum",
853
+ "count",
854
+ "avg",
855
+ "min",
856
+ "max",
857
+ "median",
858
+ "mode",
859
+ "stddev",
860
+ "variance",
861
+ "countUnique",
862
+ "singleValue"
863
+ ]);
864
+ var pivotTableDefinition = {
865
+ type: "pivot",
866
+ name: "Pivot Table",
867
+ description: "Interactive pivot table for data analysis",
868
+ icon: lucideReact.Table,
869
+ component: PivotTable,
870
+ settingsPanel: PivotTableSettingsPanel,
871
+ createDefaultSettings: (layout) => ({
872
+ ...chunkU74A5VK5_cjs.DEFAULT_CHART_SETTINGS,
873
+ id: crypto.randomUUID(),
874
+ type: "pivot",
875
+ title: "Pivot Table",
876
+ layout,
877
+ margin: { top: 0, right: 0, bottom: 0, left: 0 },
878
+ rowFields: [],
879
+ columnField: "",
880
+ valueFields: [],
881
+ filters: []
882
+ }),
883
+ validateSettings: (settings) => {
884
+ const rowFields = Array.isArray(settings.rowFields) && settings.rowFields.every(
885
+ (field) => typeof field === "string" && field.trim().length > 0
886
+ );
887
+ const columnField = typeof settings.columnField === "string" && (settings.columnField === "" || settings.columnField.trim().length > 0);
888
+ const valueFields = Array.isArray(settings.valueFields) && settings.valueFields.length > 0 && settings.valueFields.every(
889
+ (valueField) => typeof valueField.field === "string" && valueField.field.trim().length > 0 && VALID_AGGREGATIONS.has(valueField.aggregation)
890
+ );
891
+ return rowFields && columnField && valueFields && new Set(settings.rowFields).size === settings.rowFields.length && (!settings.columnField || !settings.rowFields.includes(settings.columnField));
892
+ },
893
+ getFilterFunction: (settings, fieldGetter) => {
894
+ const fields = [...settings.rowFields, settings.columnField];
895
+ const filters = settings.filters.filter(
896
+ (filter) => filter.type === "value" && fields.includes(filter.field)
897
+ );
898
+ const activeFields = [...new Set(filters.map((filter) => filter.field))];
899
+ const groups = activeFields.map((field) => ({
900
+ data: fieldGetter(field),
901
+ filters: filters.filter((filter) => filter.field === field)
902
+ }));
903
+ return (id) => groups.every(
904
+ (group) => group.filters.some((filter) => chunkEU5EFHO5_cjs.applyFilter(group.data[id], filter))
905
+ );
906
+ }
907
+ };
908
+
909
+ exports.pivotTableDefinition = pivotTableDefinition;
910
+ //# sourceMappingURL=chunk-MEEPH7ZC.cjs.map
911
+ //# sourceMappingURL=chunk-MEEPH7ZC.cjs.map