@smallwebco/tinypivot-react 1.0.51 → 1.0.53
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.cjs +1379 -639
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +1 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.js +1339 -596
- package/dist/index.js.map +1 -1
- package/dist/style.css +469 -0
- package/package.json +4 -2
package/dist/index.js
CHANGED
|
@@ -188,21 +188,702 @@ function CalculatedFieldModal({
|
|
|
188
188
|
return createPortal(modalContent, document.body);
|
|
189
189
|
}
|
|
190
190
|
|
|
191
|
+
// src/components/ChartBuilder.tsx
|
|
192
|
+
import {
|
|
193
|
+
analyzeFieldsForChart,
|
|
194
|
+
CHART_AGGREGATIONS,
|
|
195
|
+
CHART_COLORS,
|
|
196
|
+
CHART_TYPES,
|
|
197
|
+
createDefaultChartConfig,
|
|
198
|
+
getChartGuidance,
|
|
199
|
+
isChartConfigValid,
|
|
200
|
+
processChartData,
|
|
201
|
+
processChartDataForHeatmap,
|
|
202
|
+
processChartDataForPie,
|
|
203
|
+
processChartDataForScatter
|
|
204
|
+
} from "@smallwebco/tinypivot-core";
|
|
205
|
+
import { useCallback as useCallback2, useEffect as useEffect2, useMemo as useMemo2, useState as useState2 } from "react";
|
|
206
|
+
import Chart from "react-apexcharts";
|
|
207
|
+
import { Fragment, jsx as jsx2, jsxs as jsxs2 } from "react/jsx-runtime";
|
|
208
|
+
function ChartBuilder({
|
|
209
|
+
data,
|
|
210
|
+
theme = "light",
|
|
211
|
+
onConfigChange
|
|
212
|
+
}) {
|
|
213
|
+
const [chartConfig, setChartConfig] = useState2(createDefaultChartConfig());
|
|
214
|
+
const [draggingField, setDraggingField] = useState2(null);
|
|
215
|
+
const [dragOverZone, setDragOverZone] = useState2(null);
|
|
216
|
+
const fieldInfos = useMemo2(() => analyzeFieldsForChart(data), [data]);
|
|
217
|
+
const dimensions = useMemo2(
|
|
218
|
+
() => fieldInfos.filter((f) => f.role === "dimension" || f.role === "temporal"),
|
|
219
|
+
[fieldInfos]
|
|
220
|
+
);
|
|
221
|
+
const measures = useMemo2(
|
|
222
|
+
() => fieldInfos.filter((f) => f.role === "measure"),
|
|
223
|
+
[fieldInfos]
|
|
224
|
+
);
|
|
225
|
+
const guidance = useMemo2(() => getChartGuidance(chartConfig), [chartConfig]);
|
|
226
|
+
const chartIsValid = useMemo2(() => isChartConfigValid(chartConfig), [chartConfig]);
|
|
227
|
+
const selectedChartType = useMemo2(
|
|
228
|
+
() => CHART_TYPES.find((ct) => ct.type === chartConfig.type),
|
|
229
|
+
[chartConfig.type]
|
|
230
|
+
);
|
|
231
|
+
const isScatterType = useMemo2(
|
|
232
|
+
() => ["scatter", "bubble"].includes(chartConfig.type),
|
|
233
|
+
[chartConfig.type]
|
|
234
|
+
);
|
|
235
|
+
const isHeatmapType = useMemo2(
|
|
236
|
+
() => chartConfig.type === "heatmap",
|
|
237
|
+
[chartConfig.type]
|
|
238
|
+
);
|
|
239
|
+
const zoneLabels = useMemo2(() => {
|
|
240
|
+
const type = chartConfig.type;
|
|
241
|
+
switch (type) {
|
|
242
|
+
case "scatter":
|
|
243
|
+
case "bubble":
|
|
244
|
+
return {
|
|
245
|
+
xAxis: "X-Axis (measure)",
|
|
246
|
+
xAxisPlaceholder: "Drop a measure",
|
|
247
|
+
yAxis: "Y-Axis (measure)",
|
|
248
|
+
yAxisPlaceholder: "Drop a measure",
|
|
249
|
+
series: "Color by (optional)",
|
|
250
|
+
seriesPlaceholder: "Group points by dimension",
|
|
251
|
+
showSize: type === "bubble",
|
|
252
|
+
showSeries: true
|
|
253
|
+
};
|
|
254
|
+
case "heatmap":
|
|
255
|
+
return {
|
|
256
|
+
xAxis: "X-Axis (dimension)",
|
|
257
|
+
xAxisPlaceholder: "Drop a dimension",
|
|
258
|
+
yAxis: "Y-Axis (dimension)",
|
|
259
|
+
yAxisPlaceholder: "Drop a dimension",
|
|
260
|
+
series: "Value / Intensity",
|
|
261
|
+
seriesPlaceholder: "Drop a measure for color intensity",
|
|
262
|
+
showSize: false,
|
|
263
|
+
showSeries: true
|
|
264
|
+
};
|
|
265
|
+
case "pie":
|
|
266
|
+
case "donut":
|
|
267
|
+
return {
|
|
268
|
+
xAxis: "Slices (dimension)",
|
|
269
|
+
xAxisPlaceholder: "Drop a dimension",
|
|
270
|
+
yAxis: "Values (measure)",
|
|
271
|
+
yAxisPlaceholder: "Drop a measure",
|
|
272
|
+
series: "",
|
|
273
|
+
seriesPlaceholder: "",
|
|
274
|
+
showSize: false,
|
|
275
|
+
showSeries: false
|
|
276
|
+
};
|
|
277
|
+
case "radar":
|
|
278
|
+
return {
|
|
279
|
+
xAxis: "Axes (dimension)",
|
|
280
|
+
xAxisPlaceholder: "Drop a dimension",
|
|
281
|
+
yAxis: "Values (measure)",
|
|
282
|
+
yAxisPlaceholder: "Drop a measure",
|
|
283
|
+
series: "Compare by (optional)",
|
|
284
|
+
seriesPlaceholder: "Group by dimension",
|
|
285
|
+
showSize: false,
|
|
286
|
+
showSeries: true
|
|
287
|
+
};
|
|
288
|
+
default:
|
|
289
|
+
return {
|
|
290
|
+
xAxis: "X-Axis (dimension)",
|
|
291
|
+
xAxisPlaceholder: "Drop a dimension",
|
|
292
|
+
yAxis: "Y-Axis (measure)",
|
|
293
|
+
yAxisPlaceholder: "Drop a measure",
|
|
294
|
+
series: "Color / Series (optional)",
|
|
295
|
+
seriesPlaceholder: "Group by dimension",
|
|
296
|
+
showSize: false,
|
|
297
|
+
showSeries: true
|
|
298
|
+
};
|
|
299
|
+
}
|
|
300
|
+
}, [chartConfig.type]);
|
|
301
|
+
const handleDragStart = useCallback2((field, event) => {
|
|
302
|
+
setDraggingField(field);
|
|
303
|
+
event.dataTransfer?.setData("text/plain", field.field);
|
|
304
|
+
}, []);
|
|
305
|
+
const handleDragEnd = useCallback2(() => {
|
|
306
|
+
setDraggingField(null);
|
|
307
|
+
setDragOverZone(null);
|
|
308
|
+
}, []);
|
|
309
|
+
const handleDragOver = useCallback2((zone, event) => {
|
|
310
|
+
event.preventDefault();
|
|
311
|
+
setDragOverZone(zone);
|
|
312
|
+
}, []);
|
|
313
|
+
const handleDragLeave = useCallback2(() => {
|
|
314
|
+
setDragOverZone(null);
|
|
315
|
+
}, []);
|
|
316
|
+
const handleDrop = useCallback2((zone, event) => {
|
|
317
|
+
event.preventDefault();
|
|
318
|
+
setDragOverZone(null);
|
|
319
|
+
if (!draggingField)
|
|
320
|
+
return;
|
|
321
|
+
const field = draggingField;
|
|
322
|
+
const chartField = {
|
|
323
|
+
field: field.field,
|
|
324
|
+
label: field.label,
|
|
325
|
+
role: field.role,
|
|
326
|
+
aggregation: field.role === "measure" ? "sum" : void 0
|
|
327
|
+
};
|
|
328
|
+
let newConfig = { ...chartConfig };
|
|
329
|
+
switch (zone) {
|
|
330
|
+
case "xAxis":
|
|
331
|
+
newConfig = { ...newConfig, xAxis: chartField };
|
|
332
|
+
break;
|
|
333
|
+
case "yAxis":
|
|
334
|
+
newConfig = { ...newConfig, yAxis: chartField };
|
|
335
|
+
break;
|
|
336
|
+
case "series":
|
|
337
|
+
newConfig = { ...newConfig, seriesField: chartField };
|
|
338
|
+
break;
|
|
339
|
+
case "size":
|
|
340
|
+
newConfig = { ...newConfig, sizeField: chartField };
|
|
341
|
+
break;
|
|
342
|
+
case "color":
|
|
343
|
+
newConfig = { ...newConfig, colorField: chartField };
|
|
344
|
+
break;
|
|
345
|
+
}
|
|
346
|
+
setChartConfig(newConfig);
|
|
347
|
+
onConfigChange?.(newConfig);
|
|
348
|
+
}, [chartConfig, draggingField, onConfigChange]);
|
|
349
|
+
const removeField = useCallback2((zone) => {
|
|
350
|
+
let newConfig = { ...chartConfig };
|
|
351
|
+
switch (zone) {
|
|
352
|
+
case "xAxis":
|
|
353
|
+
newConfig = { ...newConfig, xAxis: void 0 };
|
|
354
|
+
break;
|
|
355
|
+
case "yAxis":
|
|
356
|
+
newConfig = { ...newConfig, yAxis: void 0 };
|
|
357
|
+
break;
|
|
358
|
+
case "series":
|
|
359
|
+
newConfig = { ...newConfig, seriesField: void 0 };
|
|
360
|
+
break;
|
|
361
|
+
case "size":
|
|
362
|
+
newConfig = { ...newConfig, sizeField: void 0 };
|
|
363
|
+
break;
|
|
364
|
+
case "color":
|
|
365
|
+
newConfig = { ...newConfig, colorField: void 0 };
|
|
366
|
+
break;
|
|
367
|
+
}
|
|
368
|
+
setChartConfig(newConfig);
|
|
369
|
+
onConfigChange?.(newConfig);
|
|
370
|
+
}, [chartConfig, onConfigChange]);
|
|
371
|
+
const selectChartType = useCallback2((type) => {
|
|
372
|
+
const newConfig = { ...chartConfig, type };
|
|
373
|
+
setChartConfig(newConfig);
|
|
374
|
+
onConfigChange?.(newConfig);
|
|
375
|
+
}, [chartConfig, onConfigChange]);
|
|
376
|
+
const updateAggregation = useCallback2((zone, aggregation) => {
|
|
377
|
+
let field;
|
|
378
|
+
switch (zone) {
|
|
379
|
+
case "xAxis":
|
|
380
|
+
field = chartConfig.xAxis;
|
|
381
|
+
break;
|
|
382
|
+
case "yAxis":
|
|
383
|
+
field = chartConfig.yAxis;
|
|
384
|
+
break;
|
|
385
|
+
case "size":
|
|
386
|
+
field = chartConfig.sizeField;
|
|
387
|
+
break;
|
|
388
|
+
case "color":
|
|
389
|
+
field = chartConfig.colorField;
|
|
390
|
+
break;
|
|
391
|
+
default:
|
|
392
|
+
return;
|
|
393
|
+
}
|
|
394
|
+
if (!field)
|
|
395
|
+
return;
|
|
396
|
+
const updated = { ...field, aggregation };
|
|
397
|
+
let newConfig = { ...chartConfig };
|
|
398
|
+
switch (zone) {
|
|
399
|
+
case "xAxis":
|
|
400
|
+
newConfig = { ...newConfig, xAxis: updated };
|
|
401
|
+
break;
|
|
402
|
+
case "yAxis":
|
|
403
|
+
newConfig = { ...newConfig, yAxis: updated };
|
|
404
|
+
break;
|
|
405
|
+
case "size":
|
|
406
|
+
newConfig = { ...newConfig, sizeField: updated };
|
|
407
|
+
break;
|
|
408
|
+
case "color":
|
|
409
|
+
newConfig = { ...newConfig, colorField: updated };
|
|
410
|
+
break;
|
|
411
|
+
}
|
|
412
|
+
setChartConfig(newConfig);
|
|
413
|
+
onConfigChange?.(newConfig);
|
|
414
|
+
}, [chartConfig, onConfigChange]);
|
|
415
|
+
const getApexChartType = useCallback2((type) => {
|
|
416
|
+
const mapping = {
|
|
417
|
+
bar: "bar",
|
|
418
|
+
line: "line",
|
|
419
|
+
area: "area",
|
|
420
|
+
pie: "pie",
|
|
421
|
+
donut: "donut",
|
|
422
|
+
radar: "radar",
|
|
423
|
+
scatter: "scatter",
|
|
424
|
+
bubble: "bubble",
|
|
425
|
+
heatmap: "heatmap"
|
|
426
|
+
};
|
|
427
|
+
return mapping[type] || "bar";
|
|
428
|
+
}, []);
|
|
429
|
+
const formatValue = useCallback2((val, format, decimals) => {
|
|
430
|
+
if (val === null || val === void 0)
|
|
431
|
+
return "";
|
|
432
|
+
if (typeof val !== "number")
|
|
433
|
+
return String(val);
|
|
434
|
+
if (Number.isNaN(val))
|
|
435
|
+
return "";
|
|
436
|
+
const dec = decimals ?? 0;
|
|
437
|
+
if (format === "percent") {
|
|
438
|
+
return `${val.toFixed(dec)}%`;
|
|
439
|
+
}
|
|
440
|
+
if (format === "currency") {
|
|
441
|
+
return `$${val.toLocaleString(void 0, { minimumFractionDigits: dec, maximumFractionDigits: dec })}`;
|
|
442
|
+
}
|
|
443
|
+
if (Math.abs(val) >= 1e3) {
|
|
444
|
+
return val.toLocaleString(void 0, { maximumFractionDigits: dec });
|
|
445
|
+
}
|
|
446
|
+
return val.toFixed(dec);
|
|
447
|
+
}, []);
|
|
448
|
+
const chartOptions = useMemo2(() => {
|
|
449
|
+
const isDark = theme === "dark";
|
|
450
|
+
const config = chartConfig;
|
|
451
|
+
const options = config.options || {};
|
|
452
|
+
const baseOptions = {
|
|
453
|
+
chart: {
|
|
454
|
+
type: getApexChartType(config.type),
|
|
455
|
+
background: "transparent",
|
|
456
|
+
foreColor: isDark ? "#e2e8f0" : "#334155",
|
|
457
|
+
toolbar: {
|
|
458
|
+
show: true,
|
|
459
|
+
tools: {
|
|
460
|
+
download: true,
|
|
461
|
+
selection: false,
|
|
462
|
+
zoom: options.enableZoom ?? false,
|
|
463
|
+
zoomin: options.enableZoom ?? false,
|
|
464
|
+
zoomout: options.enableZoom ?? false,
|
|
465
|
+
pan: false,
|
|
466
|
+
reset: options.enableZoom ?? false
|
|
467
|
+
},
|
|
468
|
+
export: {
|
|
469
|
+
csv: { filename: "chart-data" },
|
|
470
|
+
svg: { filename: "chart" },
|
|
471
|
+
png: { filename: "chart" }
|
|
472
|
+
}
|
|
473
|
+
},
|
|
474
|
+
animations: {
|
|
475
|
+
enabled: options.animated ?? true,
|
|
476
|
+
speed: 400,
|
|
477
|
+
dynamicAnimation: { enabled: true, speed: 300 }
|
|
478
|
+
},
|
|
479
|
+
fontFamily: "system-ui, -apple-system, sans-serif"
|
|
480
|
+
},
|
|
481
|
+
colors: options.colors || CHART_COLORS,
|
|
482
|
+
theme: {
|
|
483
|
+
mode: isDark ? "dark" : "light"
|
|
484
|
+
},
|
|
485
|
+
grid: {
|
|
486
|
+
show: options.showGrid ?? true,
|
|
487
|
+
borderColor: isDark ? "#334155" : "#e2e8f0"
|
|
488
|
+
},
|
|
489
|
+
legend: {
|
|
490
|
+
show: options.showLegend ?? true,
|
|
491
|
+
position: options.legendPosition || "top"
|
|
492
|
+
},
|
|
493
|
+
dataLabels: {
|
|
494
|
+
enabled: options.showDataLabels ?? false
|
|
495
|
+
},
|
|
496
|
+
tooltip: {
|
|
497
|
+
theme: isDark ? "dark" : "light",
|
|
498
|
+
style: {
|
|
499
|
+
fontSize: "12px"
|
|
500
|
+
}
|
|
501
|
+
},
|
|
502
|
+
stroke: {
|
|
503
|
+
curve: "smooth",
|
|
504
|
+
width: config.type === "line" ? 3 : config.type === "area" ? 2 : 0
|
|
505
|
+
},
|
|
506
|
+
fill: {
|
|
507
|
+
opacity: config.type === "area" ? 0.4 : 1
|
|
508
|
+
}
|
|
509
|
+
};
|
|
510
|
+
if (config.xAxis) {
|
|
511
|
+
baseOptions.xaxis = {
|
|
512
|
+
...baseOptions.xaxis,
|
|
513
|
+
title: { text: options.xAxisTitle || config.xAxis.label },
|
|
514
|
+
labels: {
|
|
515
|
+
style: { colors: isDark ? "#94a3b8" : "#64748b" }
|
|
516
|
+
}
|
|
517
|
+
};
|
|
518
|
+
}
|
|
519
|
+
if (config.yAxis && !["pie", "donut", "radar"].includes(config.type)) {
|
|
520
|
+
baseOptions.yaxis = {
|
|
521
|
+
title: { text: options.yAxisTitle || config.yAxis.label },
|
|
522
|
+
labels: {
|
|
523
|
+
style: { colors: isDark ? "#94a3b8" : "#64748b" },
|
|
524
|
+
formatter: (val) => formatValue(val, options.valueFormat, options.decimals)
|
|
525
|
+
}
|
|
526
|
+
};
|
|
527
|
+
}
|
|
528
|
+
if (options.title) {
|
|
529
|
+
baseOptions.title = {
|
|
530
|
+
text: options.title,
|
|
531
|
+
style: {
|
|
532
|
+
fontSize: "16px",
|
|
533
|
+
fontWeight: "600",
|
|
534
|
+
color: isDark ? "#e2e8f0" : "#334155"
|
|
535
|
+
}
|
|
536
|
+
};
|
|
537
|
+
}
|
|
538
|
+
if (options.stacked && ["bar", "area"].includes(config.type)) {
|
|
539
|
+
baseOptions.chart.stacked = true;
|
|
540
|
+
}
|
|
541
|
+
if (config.type === "pie" || config.type === "donut") {
|
|
542
|
+
baseOptions.plotOptions = {
|
|
543
|
+
pie: {
|
|
544
|
+
donut: {
|
|
545
|
+
size: config.type === "donut" ? "55%" : "0%",
|
|
546
|
+
labels: {
|
|
547
|
+
show: config.type === "donut",
|
|
548
|
+
total: {
|
|
549
|
+
show: true,
|
|
550
|
+
label: "Total",
|
|
551
|
+
formatter: (w) => {
|
|
552
|
+
const total = w.globals.seriesTotals.reduce((a, b) => a + b, 0);
|
|
553
|
+
return formatValue(total, options.valueFormat, options.decimals);
|
|
554
|
+
}
|
|
555
|
+
}
|
|
556
|
+
}
|
|
557
|
+
}
|
|
558
|
+
}
|
|
559
|
+
};
|
|
560
|
+
}
|
|
561
|
+
if (config.type === "radar") {
|
|
562
|
+
baseOptions.plotOptions = {
|
|
563
|
+
radar: {
|
|
564
|
+
polygons: {
|
|
565
|
+
strokeColors: isDark ? "#334155" : "#e2e8f0",
|
|
566
|
+
fill: { colors: isDark ? ["#1e293b", "#0f172a"] : ["#f8fafc", "#f1f5f9"] }
|
|
567
|
+
}
|
|
568
|
+
}
|
|
569
|
+
};
|
|
570
|
+
}
|
|
571
|
+
return baseOptions;
|
|
572
|
+
}, [chartConfig, theme, getApexChartType, formatValue]);
|
|
573
|
+
const chartSeries = useMemo2(() => {
|
|
574
|
+
const config = chartConfig;
|
|
575
|
+
if (!chartIsValid)
|
|
576
|
+
return [];
|
|
577
|
+
if (config.type === "pie" || config.type === "donut") {
|
|
578
|
+
const chartData2 = processChartDataForPie(data, config);
|
|
579
|
+
return chartData2.series[0]?.data || [];
|
|
580
|
+
}
|
|
581
|
+
if (config.type === "scatter" || config.type === "bubble") {
|
|
582
|
+
const scatterData = processChartDataForScatter(data, config);
|
|
583
|
+
return scatterData.series;
|
|
584
|
+
}
|
|
585
|
+
if (config.type === "heatmap") {
|
|
586
|
+
const heatmapData = processChartDataForHeatmap(data, config);
|
|
587
|
+
return heatmapData.series;
|
|
588
|
+
}
|
|
589
|
+
const chartData = processChartData(data, config);
|
|
590
|
+
return chartData.series;
|
|
591
|
+
}, [data, chartConfig, chartIsValid]);
|
|
592
|
+
const chartLabels = useMemo2(() => {
|
|
593
|
+
const config = chartConfig;
|
|
594
|
+
if (!chartIsValid)
|
|
595
|
+
return [];
|
|
596
|
+
if (config.type === "pie" || config.type === "donut") {
|
|
597
|
+
const chartData2 = processChartDataForPie(data, config);
|
|
598
|
+
return chartData2.categories;
|
|
599
|
+
}
|
|
600
|
+
const chartData = processChartData(data, config);
|
|
601
|
+
return chartData.categories;
|
|
602
|
+
}, [data, chartConfig, chartIsValid]);
|
|
603
|
+
const chartOptionsWithCategories = useMemo2(() => {
|
|
604
|
+
const options = { ...chartOptions };
|
|
605
|
+
const config = chartConfig;
|
|
606
|
+
if (!["pie", "donut", "scatter", "bubble", "heatmap"].includes(config.type)) {
|
|
607
|
+
options.xaxis = {
|
|
608
|
+
...options.xaxis,
|
|
609
|
+
categories: chartLabels
|
|
610
|
+
};
|
|
611
|
+
}
|
|
612
|
+
if (config.type === "pie" || config.type === "donut") {
|
|
613
|
+
options.labels = chartLabels;
|
|
614
|
+
}
|
|
615
|
+
if (config.type === "heatmap") {
|
|
616
|
+
options.chart = {
|
|
617
|
+
...options.chart,
|
|
618
|
+
type: "heatmap"
|
|
619
|
+
};
|
|
620
|
+
options.xaxis = {
|
|
621
|
+
...options.xaxis,
|
|
622
|
+
type: "category"
|
|
623
|
+
};
|
|
624
|
+
options.dataLabels = {
|
|
625
|
+
enabled: true,
|
|
626
|
+
style: {
|
|
627
|
+
colors: ["#fff"],
|
|
628
|
+
fontSize: "10px"
|
|
629
|
+
},
|
|
630
|
+
formatter: (val) => {
|
|
631
|
+
if (val === null || val === void 0)
|
|
632
|
+
return "";
|
|
633
|
+
if (typeof val !== "number")
|
|
634
|
+
return String(val);
|
|
635
|
+
if (val >= 1e6)
|
|
636
|
+
return `${(val / 1e6).toFixed(1)}M`;
|
|
637
|
+
if (val >= 1e3)
|
|
638
|
+
return `${(val / 1e3).toFixed(0)}K`;
|
|
639
|
+
return Math.round(val).toLocaleString();
|
|
640
|
+
}
|
|
641
|
+
};
|
|
642
|
+
options.plotOptions = {
|
|
643
|
+
heatmap: {
|
|
644
|
+
shadeIntensity: 0.5,
|
|
645
|
+
radius: 2,
|
|
646
|
+
enableShades: true,
|
|
647
|
+
colorScale: {
|
|
648
|
+
inverse: false
|
|
649
|
+
}
|
|
650
|
+
}
|
|
651
|
+
};
|
|
652
|
+
options.colors = ["#6366f1"];
|
|
653
|
+
options.legend = { show: false };
|
|
654
|
+
}
|
|
655
|
+
return options;
|
|
656
|
+
}, [chartOptions, chartConfig, chartLabels]);
|
|
657
|
+
const getChartIcon = useCallback2((type) => {
|
|
658
|
+
const icons = {
|
|
659
|
+
bar: "M3 3v18h18V3H3zm4 14H5v-6h2v6zm4 0H9V7h2v10zm4 0h-2V9h2v8zm4 0h-2v-4h2v4z",
|
|
660
|
+
line: "M3.5 18.5l6-6 4 4 8-8M14.5 8.5h6v6",
|
|
661
|
+
area: "M3 17l6-6 4 4 8-8v10H3z",
|
|
662
|
+
pie: "M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm0 18c-4.41 0-8-3.59-8-8s3.59-8 8-8v8l5.66 5.66C14.28 19.04 13.18 20 12 20z",
|
|
663
|
+
donut: "M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm0 14c-2.21 0-4-1.79-4-4s1.79-4 4-4 4 1.79 4 4-1.79 4-4 4z",
|
|
664
|
+
scatter: "M7 14a2 2 0 1 0 0-4 2 2 0 0 0 0 4zm5-6a2 2 0 1 0 0-4 2 2 0 0 0 0 4zm5 8a2 2 0 1 0 0-4 2 2 0 0 0 0 4zm-3 4a2 2 0 1 0 0-4 2 2 0 0 0 0 4z",
|
|
665
|
+
bubble: "M7 14a3 3 0 1 0 0-6 3 3 0 0 0 0 6zm5-5a2 2 0 1 0 0-4 2 2 0 0 0 0 4zm5 7a4 4 0 1 0 0-8 4 4 0 0 0 0 8z",
|
|
666
|
+
heatmap: "M3 3h4v4H3V3zm6 0h4v4H9V3zm6 0h4v4h-4V3zM3 9h4v4H3V9zm6 0h4v4H9V9zm6 0h4v4h-4V9zM3 15h4v4H3v-4zm6 0h4v4H9v-4zm6 0h4v4h-4v-4z",
|
|
667
|
+
radar: "M12 2L4 6v6c0 5.55 3.84 10.74 8 12 4.16-1.26 8-6.45 8-12V6l-8-4zm0 3.18l6 3v5.09c0 4.08-2.76 7.91-6 9.14V5.18z"
|
|
668
|
+
};
|
|
669
|
+
return icons[type] || icons.bar;
|
|
670
|
+
}, []);
|
|
671
|
+
useEffect2(() => {
|
|
672
|
+
onConfigChange?.(chartConfig);
|
|
673
|
+
}, []);
|
|
674
|
+
return /* @__PURE__ */ jsxs2("div", { className: "vpg-chart-builder", children: [
|
|
675
|
+
/* @__PURE__ */ jsx2("div", { className: "vpg-chart-type-bar", children: CHART_TYPES.map((ct) => /* @__PURE__ */ jsxs2(
|
|
676
|
+
"button",
|
|
677
|
+
{
|
|
678
|
+
className: `vpg-chart-type-btn ${chartConfig.type === ct.type ? "active" : ""}`,
|
|
679
|
+
title: ct.description,
|
|
680
|
+
onClick: () => selectChartType(ct.type),
|
|
681
|
+
children: [
|
|
682
|
+
/* @__PURE__ */ jsx2("svg", { className: "vpg-icon", viewBox: "0 0 24 24", fill: "currentColor", children: /* @__PURE__ */ jsx2("path", { d: getChartIcon(ct.type) }) }),
|
|
683
|
+
/* @__PURE__ */ jsx2("span", { className: "vpg-chart-type-label", children: ct.label.replace(" Chart", "") })
|
|
684
|
+
]
|
|
685
|
+
},
|
|
686
|
+
ct.type
|
|
687
|
+
)) }),
|
|
688
|
+
/* @__PURE__ */ jsxs2("div", { className: "vpg-chart-builder-content", children: [
|
|
689
|
+
/* @__PURE__ */ jsxs2("div", { className: "vpg-chart-fields-panel", children: [
|
|
690
|
+
/* @__PURE__ */ jsxs2("div", { className: "vpg-chart-fields-section", children: [
|
|
691
|
+
/* @__PURE__ */ jsxs2("h4", { className: "vpg-chart-fields-title", children: [
|
|
692
|
+
/* @__PURE__ */ jsx2("svg", { className: "vpg-icon-sm", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", children: /* @__PURE__ */ jsx2("path", { d: "M4 6h16M4 12h10M4 18h6" }) }),
|
|
693
|
+
"Dimensions",
|
|
694
|
+
/* @__PURE__ */ jsx2("span", { className: "vpg-chart-fields-hint", children: "(text/date)" })
|
|
695
|
+
] }),
|
|
696
|
+
/* @__PURE__ */ jsxs2("div", { className: "vpg-chart-fields-list", children: [
|
|
697
|
+
dimensions.map((field) => /* @__PURE__ */ jsxs2(
|
|
698
|
+
"div",
|
|
699
|
+
{
|
|
700
|
+
className: "vpg-chart-field-chip vpg-field-dimension",
|
|
701
|
+
draggable: true,
|
|
702
|
+
onDragStart: (e) => handleDragStart(field, e),
|
|
703
|
+
onDragEnd: handleDragEnd,
|
|
704
|
+
children: [
|
|
705
|
+
/* @__PURE__ */ jsx2("span", { className: "vpg-field-name", children: field.label }),
|
|
706
|
+
/* @__PURE__ */ jsx2("span", { className: "vpg-field-type", children: field.role === "temporal" ? "date" : "text" })
|
|
707
|
+
]
|
|
708
|
+
},
|
|
709
|
+
field.field
|
|
710
|
+
)),
|
|
711
|
+
dimensions.length === 0 && /* @__PURE__ */ jsx2("div", { className: "vpg-chart-fields-empty", children: "No dimension fields detected" })
|
|
712
|
+
] })
|
|
713
|
+
] }),
|
|
714
|
+
/* @__PURE__ */ jsxs2("div", { className: "vpg-chart-fields-section", children: [
|
|
715
|
+
/* @__PURE__ */ jsxs2("h4", { className: "vpg-chart-fields-title", children: [
|
|
716
|
+
/* @__PURE__ */ jsx2("svg", { className: "vpg-icon-sm", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", children: /* @__PURE__ */ jsx2("path", { d: "M16 8v8M12 11v5M8 14v2M4 4v16h16" }) }),
|
|
717
|
+
"Measures",
|
|
718
|
+
/* @__PURE__ */ jsx2("span", { className: "vpg-chart-fields-hint", children: "(numbers)" })
|
|
719
|
+
] }),
|
|
720
|
+
/* @__PURE__ */ jsxs2("div", { className: "vpg-chart-fields-list", children: [
|
|
721
|
+
measures.map((field) => /* @__PURE__ */ jsxs2(
|
|
722
|
+
"div",
|
|
723
|
+
{
|
|
724
|
+
className: "vpg-chart-field-chip vpg-field-measure",
|
|
725
|
+
draggable: true,
|
|
726
|
+
onDragStart: (e) => handleDragStart(field, e),
|
|
727
|
+
onDragEnd: handleDragEnd,
|
|
728
|
+
children: [
|
|
729
|
+
/* @__PURE__ */ jsx2("span", { className: "vpg-field-name", children: field.label }),
|
|
730
|
+
/* @__PURE__ */ jsx2("span", { className: "vpg-field-type", children: "#" })
|
|
731
|
+
]
|
|
732
|
+
},
|
|
733
|
+
field.field
|
|
734
|
+
)),
|
|
735
|
+
measures.length === 0 && /* @__PURE__ */ jsx2("div", { className: "vpg-chart-fields-empty", children: "No numeric fields detected" })
|
|
736
|
+
] })
|
|
737
|
+
] })
|
|
738
|
+
] }),
|
|
739
|
+
/* @__PURE__ */ jsxs2("div", { className: "vpg-chart-config-panel", children: [
|
|
740
|
+
/* @__PURE__ */ jsxs2("div", { className: "vpg-chart-drop-zone-wrapper", children: [
|
|
741
|
+
/* @__PURE__ */ jsx2("label", { className: "vpg-chart-zone-label", children: zoneLabels.xAxis }),
|
|
742
|
+
/* @__PURE__ */ jsx2(
|
|
743
|
+
"div",
|
|
744
|
+
{
|
|
745
|
+
className: `vpg-chart-drop-zone ${dragOverZone === "xAxis" ? "drag-over" : ""} ${chartConfig.xAxis ? "has-field" : ""}`,
|
|
746
|
+
onDragOver: (e) => handleDragOver("xAxis", e),
|
|
747
|
+
onDragLeave: handleDragLeave,
|
|
748
|
+
onDrop: (e) => handleDrop("xAxis", e),
|
|
749
|
+
children: chartConfig.xAxis ? /* @__PURE__ */ jsxs2(Fragment, { children: [
|
|
750
|
+
/* @__PURE__ */ jsx2("span", { className: "vpg-zone-field-name", children: chartConfig.xAxis.label }),
|
|
751
|
+
isScatterType && chartConfig.xAxis.role === "measure" && /* @__PURE__ */ jsx2(
|
|
752
|
+
"select",
|
|
753
|
+
{
|
|
754
|
+
className: "vpg-zone-aggregation",
|
|
755
|
+
value: chartConfig.xAxis.aggregation || "sum",
|
|
756
|
+
onChange: (e) => updateAggregation("xAxis", e.target.value),
|
|
757
|
+
children: CHART_AGGREGATIONS.map((agg) => /* @__PURE__ */ jsx2("option", { value: agg.value, children: agg.symbol }, agg.value))
|
|
758
|
+
}
|
|
759
|
+
),
|
|
760
|
+
/* @__PURE__ */ jsx2("button", { className: "vpg-zone-remove-btn", onClick: () => removeField("xAxis"), children: /* @__PURE__ */ jsx2("svg", { className: "vpg-icon-xs", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", children: /* @__PURE__ */ jsx2("path", { d: "M6 18L18 6M6 6l12 12" }) }) })
|
|
761
|
+
] }) : /* @__PURE__ */ jsx2("span", { className: "vpg-zone-placeholder", children: zoneLabels.xAxisPlaceholder })
|
|
762
|
+
}
|
|
763
|
+
)
|
|
764
|
+
] }),
|
|
765
|
+
/* @__PURE__ */ jsxs2("div", { className: "vpg-chart-drop-zone-wrapper", children: [
|
|
766
|
+
/* @__PURE__ */ jsx2("label", { className: "vpg-chart-zone-label", children: zoneLabels.yAxis }),
|
|
767
|
+
/* @__PURE__ */ jsx2(
|
|
768
|
+
"div",
|
|
769
|
+
{
|
|
770
|
+
className: `vpg-chart-drop-zone ${dragOverZone === "yAxis" ? "drag-over" : ""} ${chartConfig.yAxis ? "has-field" : ""}`,
|
|
771
|
+
onDragOver: (e) => handleDragOver("yAxis", e),
|
|
772
|
+
onDragLeave: handleDragLeave,
|
|
773
|
+
onDrop: (e) => handleDrop("yAxis", e),
|
|
774
|
+
children: chartConfig.yAxis ? /* @__PURE__ */ jsxs2(Fragment, { children: [
|
|
775
|
+
/* @__PURE__ */ jsx2("span", { className: "vpg-zone-field-name", children: chartConfig.yAxis.label }),
|
|
776
|
+
chartConfig.yAxis.role === "measure" && !isHeatmapType && /* @__PURE__ */ jsx2(
|
|
777
|
+
"select",
|
|
778
|
+
{
|
|
779
|
+
className: "vpg-zone-aggregation",
|
|
780
|
+
value: chartConfig.yAxis.aggregation || "sum",
|
|
781
|
+
onChange: (e) => updateAggregation("yAxis", e.target.value),
|
|
782
|
+
children: CHART_AGGREGATIONS.map((agg) => /* @__PURE__ */ jsx2("option", { value: agg.value, children: agg.symbol }, agg.value))
|
|
783
|
+
}
|
|
784
|
+
),
|
|
785
|
+
/* @__PURE__ */ jsx2("button", { className: "vpg-zone-remove-btn", onClick: () => removeField("yAxis"), children: /* @__PURE__ */ jsx2("svg", { className: "vpg-icon-xs", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", children: /* @__PURE__ */ jsx2("path", { d: "M6 18L18 6M6 6l12 12" }) }) })
|
|
786
|
+
] }) : /* @__PURE__ */ jsx2("span", { className: "vpg-zone-placeholder", children: zoneLabels.yAxisPlaceholder })
|
|
787
|
+
}
|
|
788
|
+
)
|
|
789
|
+
] }),
|
|
790
|
+
zoneLabels.showSeries && /* @__PURE__ */ jsxs2("div", { className: "vpg-chart-drop-zone-wrapper", children: [
|
|
791
|
+
/* @__PURE__ */ jsx2("label", { className: "vpg-chart-zone-label", children: zoneLabels.series }),
|
|
792
|
+
/* @__PURE__ */ jsx2(
|
|
793
|
+
"div",
|
|
794
|
+
{
|
|
795
|
+
className: `vpg-chart-drop-zone vpg-zone-optional ${dragOverZone === "series" ? "drag-over" : ""} ${(isHeatmapType ? chartConfig.colorField : chartConfig.seriesField) ? "has-field" : ""}`,
|
|
796
|
+
onDragOver: (e) => handleDragOver(isHeatmapType ? "color" : "series", e),
|
|
797
|
+
onDragLeave: handleDragLeave,
|
|
798
|
+
onDrop: (e) => handleDrop(isHeatmapType ? "color" : "series", e),
|
|
799
|
+
children: (isHeatmapType ? chartConfig.colorField : chartConfig.seriesField) ? /* @__PURE__ */ jsxs2(Fragment, { children: [
|
|
800
|
+
/* @__PURE__ */ jsx2("span", { className: "vpg-zone-field-name", children: isHeatmapType ? chartConfig.colorField?.label : chartConfig.seriesField?.label }),
|
|
801
|
+
isHeatmapType && chartConfig.colorField?.role === "measure" && /* @__PURE__ */ jsx2(
|
|
802
|
+
"select",
|
|
803
|
+
{
|
|
804
|
+
className: "vpg-zone-aggregation",
|
|
805
|
+
value: chartConfig.colorField?.aggregation || "sum",
|
|
806
|
+
onChange: (e) => updateAggregation("color", e.target.value),
|
|
807
|
+
children: CHART_AGGREGATIONS.map((agg) => /* @__PURE__ */ jsx2("option", { value: agg.value, children: agg.symbol }, agg.value))
|
|
808
|
+
}
|
|
809
|
+
),
|
|
810
|
+
/* @__PURE__ */ jsx2("button", { className: "vpg-zone-remove-btn", onClick: () => removeField(isHeatmapType ? "color" : "series"), children: /* @__PURE__ */ jsx2("svg", { className: "vpg-icon-xs", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", children: /* @__PURE__ */ jsx2("path", { d: "M6 18L18 6M6 6l12 12" }) }) })
|
|
811
|
+
] }) : /* @__PURE__ */ jsx2("span", { className: "vpg-zone-placeholder", children: zoneLabels.seriesPlaceholder })
|
|
812
|
+
}
|
|
813
|
+
)
|
|
814
|
+
] }),
|
|
815
|
+
zoneLabels.showSize && /* @__PURE__ */ jsxs2("div", { className: "vpg-chart-drop-zone-wrapper", children: [
|
|
816
|
+
/* @__PURE__ */ jsx2("label", { className: "vpg-chart-zone-label", children: "Size (number)" }),
|
|
817
|
+
/* @__PURE__ */ jsx2(
|
|
818
|
+
"div",
|
|
819
|
+
{
|
|
820
|
+
className: `vpg-chart-drop-zone vpg-zone-optional ${dragOverZone === "size" ? "drag-over" : ""} ${chartConfig.sizeField ? "has-field" : ""}`,
|
|
821
|
+
onDragOver: (e) => handleDragOver("size", e),
|
|
822
|
+
onDragLeave: handleDragLeave,
|
|
823
|
+
onDrop: (e) => handleDrop("size", e),
|
|
824
|
+
children: chartConfig.sizeField ? /* @__PURE__ */ jsxs2(Fragment, { children: [
|
|
825
|
+
/* @__PURE__ */ jsx2("span", { className: "vpg-zone-field-name", children: chartConfig.sizeField.label }),
|
|
826
|
+
chartConfig.sizeField.role === "measure" && /* @__PURE__ */ jsx2(
|
|
827
|
+
"select",
|
|
828
|
+
{
|
|
829
|
+
className: "vpg-zone-aggregation",
|
|
830
|
+
value: chartConfig.sizeField.aggregation || "sum",
|
|
831
|
+
onChange: (e) => updateAggregation("size", e.target.value),
|
|
832
|
+
children: CHART_AGGREGATIONS.map((agg) => /* @__PURE__ */ jsx2("option", { value: agg.value, children: agg.symbol }, agg.value))
|
|
833
|
+
}
|
|
834
|
+
),
|
|
835
|
+
/* @__PURE__ */ jsx2("button", { className: "vpg-zone-remove-btn", onClick: () => removeField("size"), children: /* @__PURE__ */ jsx2("svg", { className: "vpg-icon-xs", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", children: /* @__PURE__ */ jsx2("path", { d: "M6 18L18 6M6 6l12 12" }) }) })
|
|
836
|
+
] }) : /* @__PURE__ */ jsx2("span", { className: "vpg-zone-placeholder", children: "Drop a number for bubble size" })
|
|
837
|
+
}
|
|
838
|
+
)
|
|
839
|
+
] }),
|
|
840
|
+
/* @__PURE__ */ jsxs2("div", { className: "vpg-chart-guidance", children: [
|
|
841
|
+
/* @__PURE__ */ jsxs2("svg", { className: "vpg-icon-sm", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", children: [
|
|
842
|
+
/* @__PURE__ */ jsx2("circle", { cx: "12", cy: "12", r: "10" }),
|
|
843
|
+
/* @__PURE__ */ jsx2("path", { d: "M12 16v-4M12 8h.01" })
|
|
844
|
+
] }),
|
|
845
|
+
/* @__PURE__ */ jsx2("span", { children: guidance })
|
|
846
|
+
] })
|
|
847
|
+
] }),
|
|
848
|
+
/* @__PURE__ */ jsx2("div", { className: "vpg-chart-preview-panel", children: chartIsValid ? /* @__PURE__ */ jsx2("div", { className: "vpg-chart-container", children: /* @__PURE__ */ jsx2(
|
|
849
|
+
Chart,
|
|
850
|
+
{
|
|
851
|
+
type: getApexChartType(chartConfig.type),
|
|
852
|
+
options: chartOptionsWithCategories,
|
|
853
|
+
series: chartSeries,
|
|
854
|
+
height: "100%"
|
|
855
|
+
},
|
|
856
|
+
`${chartConfig.type}-${JSON.stringify(chartConfig.xAxis)}-${JSON.stringify(chartConfig.yAxis)}`
|
|
857
|
+
) }) : /* @__PURE__ */ jsxs2("div", { className: "vpg-chart-empty-state", children: [
|
|
858
|
+
/* @__PURE__ */ jsx2("svg", { className: "vpg-icon-lg", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "1.5", children: /* @__PURE__ */ jsx2("path", { d: getChartIcon(chartConfig.type) }) }),
|
|
859
|
+
/* @__PURE__ */ jsx2("h3", { children: "Build your chart" }),
|
|
860
|
+
/* @__PURE__ */ jsx2("p", { children: "Drag fields from the left panel to configure your visualization" }),
|
|
861
|
+
/* @__PURE__ */ jsxs2("div", { className: "vpg-chart-hint", children: [
|
|
862
|
+
/* @__PURE__ */ jsx2("strong", { children: selectedChartType?.label }),
|
|
863
|
+
":",
|
|
864
|
+
" ",
|
|
865
|
+
selectedChartType?.description
|
|
866
|
+
] })
|
|
867
|
+
] }) })
|
|
868
|
+
] })
|
|
869
|
+
] });
|
|
870
|
+
}
|
|
871
|
+
|
|
191
872
|
// src/components/ColumnFilter.tsx
|
|
192
|
-
import { useCallback as
|
|
873
|
+
import { useCallback as useCallback4, useEffect as useEffect4, useMemo as useMemo4, useRef, useState as useState4 } from "react";
|
|
193
874
|
|
|
194
875
|
// src/components/NumericRangeFilter.tsx
|
|
195
|
-
import { useCallback as
|
|
196
|
-
import { jsx as
|
|
876
|
+
import { useCallback as useCallback3, useEffect as useEffect3, useMemo as useMemo3, useState as useState3 } from "react";
|
|
877
|
+
import { jsx as jsx3, jsxs as jsxs3 } from "react/jsx-runtime";
|
|
197
878
|
function NumericRangeFilter({
|
|
198
879
|
dataMin,
|
|
199
880
|
dataMax,
|
|
200
881
|
currentRange,
|
|
201
882
|
onChange
|
|
202
883
|
}) {
|
|
203
|
-
const [localMin, setLocalMin] =
|
|
204
|
-
const [localMax, setLocalMax] =
|
|
205
|
-
const step =
|
|
884
|
+
const [localMin, setLocalMin] = useState3(currentRange?.min ?? null);
|
|
885
|
+
const [localMax, setLocalMax] = useState3(currentRange?.max ?? null);
|
|
886
|
+
const step = useMemo3(() => {
|
|
206
887
|
const range = dataMax - dataMin;
|
|
207
888
|
if (range === 0)
|
|
208
889
|
return 1;
|
|
@@ -216,7 +897,7 @@ function NumericRangeFilter({
|
|
|
216
897
|
return 10;
|
|
217
898
|
return 10 ** (Math.floor(Math.log10(range)) - 2);
|
|
218
899
|
}, [dataMin, dataMax]);
|
|
219
|
-
const formatValue =
|
|
900
|
+
const formatValue = useCallback3((val) => {
|
|
220
901
|
if (val === null)
|
|
221
902
|
return "";
|
|
222
903
|
if (Number.isInteger(val))
|
|
@@ -224,17 +905,17 @@ function NumericRangeFilter({
|
|
|
224
905
|
return val.toLocaleString(void 0, { maximumFractionDigits: 2 });
|
|
225
906
|
}, []);
|
|
226
907
|
const isFilterActive = localMin !== null || localMax !== null;
|
|
227
|
-
const minPercent =
|
|
908
|
+
const minPercent = useMemo3(() => {
|
|
228
909
|
if (localMin === null || dataMax === dataMin)
|
|
229
910
|
return 0;
|
|
230
911
|
return (localMin - dataMin) / (dataMax - dataMin) * 100;
|
|
231
912
|
}, [localMin, dataMin, dataMax]);
|
|
232
|
-
const maxPercent =
|
|
913
|
+
const maxPercent = useMemo3(() => {
|
|
233
914
|
if (localMax === null || dataMax === dataMin)
|
|
234
915
|
return 100;
|
|
235
916
|
return (localMax - dataMin) / (dataMax - dataMin) * 100;
|
|
236
917
|
}, [localMax, dataMin, dataMax]);
|
|
237
|
-
const handleMinSlider =
|
|
918
|
+
const handleMinSlider = useCallback3((event) => {
|
|
238
919
|
const value = Number.parseFloat(event.target.value);
|
|
239
920
|
setLocalMin(() => {
|
|
240
921
|
if (localMax !== null && value > localMax) {
|
|
@@ -243,7 +924,7 @@ function NumericRangeFilter({
|
|
|
243
924
|
return value;
|
|
244
925
|
});
|
|
245
926
|
}, [localMax]);
|
|
246
|
-
const handleMaxSlider =
|
|
927
|
+
const handleMaxSlider = useCallback3((event) => {
|
|
247
928
|
const value = Number.parseFloat(event.target.value);
|
|
248
929
|
setLocalMax(() => {
|
|
249
930
|
if (localMin !== null && value < localMin) {
|
|
@@ -252,14 +933,14 @@ function NumericRangeFilter({
|
|
|
252
933
|
return value;
|
|
253
934
|
});
|
|
254
935
|
}, [localMin]);
|
|
255
|
-
const handleSliderChange =
|
|
936
|
+
const handleSliderChange = useCallback3(() => {
|
|
256
937
|
if (localMin === null && localMax === null) {
|
|
257
938
|
onChange(null);
|
|
258
939
|
} else {
|
|
259
940
|
onChange({ min: localMin, max: localMax });
|
|
260
941
|
}
|
|
261
942
|
}, [localMin, localMax, onChange]);
|
|
262
|
-
const handleMinInput =
|
|
943
|
+
const handleMinInput = useCallback3((event) => {
|
|
263
944
|
const value = event.target.value === "" ? null : Number.parseFloat(event.target.value);
|
|
264
945
|
if (value !== null && !Number.isNaN(value)) {
|
|
265
946
|
setLocalMin(Math.max(dataMin, Math.min(value, localMax ?? dataMax)));
|
|
@@ -267,7 +948,7 @@ function NumericRangeFilter({
|
|
|
267
948
|
setLocalMin(null);
|
|
268
949
|
}
|
|
269
950
|
}, [dataMin, dataMax, localMax]);
|
|
270
|
-
const handleMaxInput =
|
|
951
|
+
const handleMaxInput = useCallback3((event) => {
|
|
271
952
|
const value = event.target.value === "" ? null : Number.parseFloat(event.target.value);
|
|
272
953
|
if (value !== null && !Number.isNaN(value)) {
|
|
273
954
|
setLocalMax(Math.min(dataMax, Math.max(value, localMin ?? dataMin)));
|
|
@@ -275,39 +956,39 @@ function NumericRangeFilter({
|
|
|
275
956
|
setLocalMax(null);
|
|
276
957
|
}
|
|
277
958
|
}, [dataMin, dataMax, localMin]);
|
|
278
|
-
const handleInputBlur =
|
|
959
|
+
const handleInputBlur = useCallback3(() => {
|
|
279
960
|
if (localMin === null && localMax === null) {
|
|
280
961
|
onChange(null);
|
|
281
962
|
} else {
|
|
282
963
|
onChange({ min: localMin, max: localMax });
|
|
283
964
|
}
|
|
284
965
|
}, [localMin, localMax, onChange]);
|
|
285
|
-
const clearFilter =
|
|
966
|
+
const clearFilter = useCallback3(() => {
|
|
286
967
|
setLocalMin(null);
|
|
287
968
|
setLocalMax(null);
|
|
288
969
|
onChange(null);
|
|
289
970
|
}, [onChange]);
|
|
290
|
-
const setFullRange =
|
|
971
|
+
const setFullRange = useCallback3(() => {
|
|
291
972
|
setLocalMin(dataMin);
|
|
292
973
|
setLocalMax(dataMax);
|
|
293
974
|
onChange({ min: dataMin, max: dataMax });
|
|
294
975
|
}, [dataMin, dataMax, onChange]);
|
|
295
|
-
|
|
976
|
+
useEffect3(() => {
|
|
296
977
|
setLocalMin(currentRange?.min ?? null);
|
|
297
978
|
setLocalMax(currentRange?.max ?? null);
|
|
298
979
|
}, [currentRange]);
|
|
299
|
-
return /* @__PURE__ */
|
|
300
|
-
/* @__PURE__ */
|
|
301
|
-
/* @__PURE__ */
|
|
302
|
-
/* @__PURE__ */
|
|
980
|
+
return /* @__PURE__ */ jsxs3("div", { className: "vpg-range-filter", children: [
|
|
981
|
+
/* @__PURE__ */ jsxs3("div", { className: "vpg-range-info", children: [
|
|
982
|
+
/* @__PURE__ */ jsx3("span", { className: "vpg-range-label", children: "Data range:" }),
|
|
983
|
+
/* @__PURE__ */ jsxs3("span", { className: "vpg-range-bounds", children: [
|
|
303
984
|
formatValue(dataMin),
|
|
304
985
|
" ",
|
|
305
986
|
"\u2013",
|
|
306
987
|
formatValue(dataMax)
|
|
307
988
|
] })
|
|
308
989
|
] }),
|
|
309
|
-
/* @__PURE__ */
|
|
310
|
-
/* @__PURE__ */
|
|
990
|
+
/* @__PURE__ */ jsxs3("div", { className: "vpg-slider-container", children: [
|
|
991
|
+
/* @__PURE__ */ jsx3("div", { className: "vpg-slider-track", children: /* @__PURE__ */ jsx3(
|
|
311
992
|
"div",
|
|
312
993
|
{
|
|
313
994
|
className: "vpg-slider-fill",
|
|
@@ -317,7 +998,7 @@ function NumericRangeFilter({
|
|
|
317
998
|
}
|
|
318
999
|
}
|
|
319
1000
|
) }),
|
|
320
|
-
/* @__PURE__ */
|
|
1001
|
+
/* @__PURE__ */ jsx3(
|
|
321
1002
|
"input",
|
|
322
1003
|
{
|
|
323
1004
|
type: "range",
|
|
@@ -331,7 +1012,7 @@ function NumericRangeFilter({
|
|
|
331
1012
|
onTouchEnd: handleSliderChange
|
|
332
1013
|
}
|
|
333
1014
|
),
|
|
334
|
-
/* @__PURE__ */
|
|
1015
|
+
/* @__PURE__ */ jsx3(
|
|
335
1016
|
"input",
|
|
336
1017
|
{
|
|
337
1018
|
type: "range",
|
|
@@ -346,10 +1027,10 @@ function NumericRangeFilter({
|
|
|
346
1027
|
}
|
|
347
1028
|
)
|
|
348
1029
|
] }),
|
|
349
|
-
/* @__PURE__ */
|
|
350
|
-
/* @__PURE__ */
|
|
351
|
-
/* @__PURE__ */
|
|
352
|
-
/* @__PURE__ */
|
|
1030
|
+
/* @__PURE__ */ jsxs3("div", { className: "vpg-range-inputs", children: [
|
|
1031
|
+
/* @__PURE__ */ jsxs3("div", { className: "vpg-input-group", children: [
|
|
1032
|
+
/* @__PURE__ */ jsx3("label", { className: "vpg-input-label", children: "Min" }),
|
|
1033
|
+
/* @__PURE__ */ jsx3(
|
|
353
1034
|
"input",
|
|
354
1035
|
{
|
|
355
1036
|
type: "number",
|
|
@@ -362,10 +1043,10 @@ function NumericRangeFilter({
|
|
|
362
1043
|
}
|
|
363
1044
|
)
|
|
364
1045
|
] }),
|
|
365
|
-
/* @__PURE__ */
|
|
366
|
-
/* @__PURE__ */
|
|
367
|
-
/* @__PURE__ */
|
|
368
|
-
/* @__PURE__ */
|
|
1046
|
+
/* @__PURE__ */ jsx3("span", { className: "vpg-input-separator", children: "to" }),
|
|
1047
|
+
/* @__PURE__ */ jsxs3("div", { className: "vpg-input-group", children: [
|
|
1048
|
+
/* @__PURE__ */ jsx3("label", { className: "vpg-input-label", children: "Max" }),
|
|
1049
|
+
/* @__PURE__ */ jsx3(
|
|
369
1050
|
"input",
|
|
370
1051
|
{
|
|
371
1052
|
type: "number",
|
|
@@ -379,15 +1060,15 @@ function NumericRangeFilter({
|
|
|
379
1060
|
)
|
|
380
1061
|
] })
|
|
381
1062
|
] }),
|
|
382
|
-
/* @__PURE__ */
|
|
383
|
-
/* @__PURE__ */
|
|
1063
|
+
/* @__PURE__ */ jsxs3("div", { className: "vpg-range-actions", children: [
|
|
1064
|
+
/* @__PURE__ */ jsxs3(
|
|
384
1065
|
"button",
|
|
385
1066
|
{
|
|
386
1067
|
className: "vpg-range-btn",
|
|
387
1068
|
disabled: !isFilterActive,
|
|
388
1069
|
onClick: clearFilter,
|
|
389
1070
|
children: [
|
|
390
|
-
/* @__PURE__ */
|
|
1071
|
+
/* @__PURE__ */ jsx3("svg", { className: "vpg-icon-xs", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: /* @__PURE__ */ jsx3(
|
|
391
1072
|
"path",
|
|
392
1073
|
{
|
|
393
1074
|
strokeLinecap: "round",
|
|
@@ -400,8 +1081,8 @@ function NumericRangeFilter({
|
|
|
400
1081
|
]
|
|
401
1082
|
}
|
|
402
1083
|
),
|
|
403
|
-
/* @__PURE__ */
|
|
404
|
-
/* @__PURE__ */
|
|
1084
|
+
/* @__PURE__ */ jsxs3("button", { className: "vpg-range-btn", onClick: setFullRange, children: [
|
|
1085
|
+
/* @__PURE__ */ jsx3("svg", { className: "vpg-icon-xs", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: /* @__PURE__ */ jsx3(
|
|
405
1086
|
"path",
|
|
406
1087
|
{
|
|
407
1088
|
strokeLinecap: "round",
|
|
@@ -413,8 +1094,8 @@ function NumericRangeFilter({
|
|
|
413
1094
|
"Full Range"
|
|
414
1095
|
] })
|
|
415
1096
|
] }),
|
|
416
|
-
isFilterActive && /* @__PURE__ */
|
|
417
|
-
/* @__PURE__ */
|
|
1097
|
+
isFilterActive && /* @__PURE__ */ jsxs3("div", { className: "vpg-filter-summary", children: [
|
|
1098
|
+
/* @__PURE__ */ jsx3("svg", { className: "vpg-icon-xs", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: /* @__PURE__ */ jsx3(
|
|
418
1099
|
"path",
|
|
419
1100
|
{
|
|
420
1101
|
strokeLinecap: "round",
|
|
@@ -423,15 +1104,15 @@ function NumericRangeFilter({
|
|
|
423
1104
|
d: "M3 4a1 1 0 011-1h16a1 1 0 011 1v2.586a1 1 0 01-.293.707l-6.414 6.414a1 1 0 00-.293.707V17l-4 4v-6.586a1 1 0 00-.293-.707L3.293 7.293A1 1 0 013 6.586V4z"
|
|
424
1105
|
}
|
|
425
1106
|
) }),
|
|
426
|
-
/* @__PURE__ */
|
|
1107
|
+
/* @__PURE__ */ jsxs3("span", { children: [
|
|
427
1108
|
"Showing values",
|
|
428
1109
|
" ",
|
|
429
|
-
localMin !== null && /* @__PURE__ */
|
|
1110
|
+
localMin !== null && /* @__PURE__ */ jsxs3("strong", { children: [
|
|
430
1111
|
"\u2265",
|
|
431
1112
|
formatValue(localMin)
|
|
432
1113
|
] }),
|
|
433
1114
|
localMin !== null && localMax !== null && " and ",
|
|
434
|
-
localMax !== null && /* @__PURE__ */
|
|
1115
|
+
localMax !== null && /* @__PURE__ */ jsxs3("strong", { children: [
|
|
435
1116
|
"\u2264",
|
|
436
1117
|
formatValue(localMax)
|
|
437
1118
|
] })
|
|
@@ -441,7 +1122,7 @@ function NumericRangeFilter({
|
|
|
441
1122
|
}
|
|
442
1123
|
|
|
443
1124
|
// src/components/ColumnFilter.tsx
|
|
444
|
-
import { Fragment, jsx as
|
|
1125
|
+
import { Fragment as Fragment2, jsx as jsx4, jsxs as jsxs4 } from "react/jsx-runtime";
|
|
445
1126
|
function ColumnFilter({
|
|
446
1127
|
columnName,
|
|
447
1128
|
stats,
|
|
@@ -453,33 +1134,33 @@ function ColumnFilter({
|
|
|
453
1134
|
onClose,
|
|
454
1135
|
onRangeFilter
|
|
455
1136
|
}) {
|
|
456
|
-
const [searchQuery, setSearchQuery] =
|
|
457
|
-
const [localSelected, setLocalSelected] =
|
|
1137
|
+
const [searchQuery, setSearchQuery] = useState4("");
|
|
1138
|
+
const [localSelected, setLocalSelected] = useState4(new Set(selectedValues));
|
|
458
1139
|
const dropdownRef = useRef(null);
|
|
459
1140
|
const searchInputRef = useRef(null);
|
|
460
1141
|
const isNumericColumn = stats.type === "number" && stats.numericMin !== void 0 && stats.numericMax !== void 0;
|
|
461
|
-
const [filterMode, setFilterMode] =
|
|
462
|
-
const [localRange, setLocalRange] =
|
|
1142
|
+
const [filterMode, setFilterMode] = useState4(numericRange ? "range" : "values");
|
|
1143
|
+
const [localRange, setLocalRange] = useState4(numericRange ?? null);
|
|
463
1144
|
const hasBlankValues = stats.nullCount > 0;
|
|
464
|
-
const filteredValues =
|
|
1145
|
+
const filteredValues = useMemo4(() => {
|
|
465
1146
|
const values = stats.uniqueValues;
|
|
466
1147
|
if (!searchQuery)
|
|
467
1148
|
return values;
|
|
468
1149
|
const query = searchQuery.toLowerCase();
|
|
469
1150
|
return values.filter((v) => v.toLowerCase().includes(query));
|
|
470
1151
|
}, [stats.uniqueValues, searchQuery]);
|
|
471
|
-
const allValues =
|
|
1152
|
+
const allValues = useMemo4(() => {
|
|
472
1153
|
const values = [...filteredValues];
|
|
473
1154
|
if (hasBlankValues && (!searchQuery || "(blank)".includes(searchQuery.toLowerCase()))) {
|
|
474
1155
|
values.unshift("(blank)");
|
|
475
1156
|
}
|
|
476
1157
|
return values;
|
|
477
1158
|
}, [filteredValues, hasBlankValues, searchQuery]);
|
|
478
|
-
const _isAllSelected =
|
|
1159
|
+
const _isAllSelected = useMemo4(
|
|
479
1160
|
() => allValues.every((v) => localSelected.has(v)),
|
|
480
1161
|
[allValues, localSelected]
|
|
481
1162
|
);
|
|
482
|
-
const toggleValue =
|
|
1163
|
+
const toggleValue = useCallback4((value) => {
|
|
483
1164
|
setLocalSelected((prev) => {
|
|
484
1165
|
const next = new Set(prev);
|
|
485
1166
|
if (next.has(value)) {
|
|
@@ -490,7 +1171,7 @@ function ColumnFilter({
|
|
|
490
1171
|
return next;
|
|
491
1172
|
});
|
|
492
1173
|
}, []);
|
|
493
|
-
const selectAll =
|
|
1174
|
+
const selectAll = useCallback4(() => {
|
|
494
1175
|
setLocalSelected((prev) => {
|
|
495
1176
|
const next = new Set(prev);
|
|
496
1177
|
for (const value of allValues) {
|
|
@@ -499,10 +1180,10 @@ function ColumnFilter({
|
|
|
499
1180
|
return next;
|
|
500
1181
|
});
|
|
501
1182
|
}, [allValues]);
|
|
502
|
-
const clearAll =
|
|
1183
|
+
const clearAll = useCallback4(() => {
|
|
503
1184
|
setLocalSelected(/* @__PURE__ */ new Set());
|
|
504
1185
|
}, []);
|
|
505
|
-
const applyFilter =
|
|
1186
|
+
const applyFilter = useCallback4(() => {
|
|
506
1187
|
if (localSelected.size === 0) {
|
|
507
1188
|
onFilter([]);
|
|
508
1189
|
} else {
|
|
@@ -510,30 +1191,30 @@ function ColumnFilter({
|
|
|
510
1191
|
}
|
|
511
1192
|
onClose();
|
|
512
1193
|
}, [localSelected, onFilter, onClose]);
|
|
513
|
-
const sortAscending =
|
|
1194
|
+
const sortAscending = useCallback4(() => {
|
|
514
1195
|
onSort(sortDirection === "asc" ? null : "asc");
|
|
515
1196
|
}, [sortDirection, onSort]);
|
|
516
|
-
const sortDescending =
|
|
1197
|
+
const sortDescending = useCallback4(() => {
|
|
517
1198
|
onSort(sortDirection === "desc" ? null : "desc");
|
|
518
1199
|
}, [sortDirection, onSort]);
|
|
519
|
-
const clearFilter =
|
|
1200
|
+
const clearFilter = useCallback4(() => {
|
|
520
1201
|
setLocalSelected(/* @__PURE__ */ new Set());
|
|
521
1202
|
onFilter([]);
|
|
522
1203
|
onClose();
|
|
523
1204
|
}, [onFilter, onClose]);
|
|
524
|
-
const handleRangeChange =
|
|
1205
|
+
const handleRangeChange = useCallback4((range) => {
|
|
525
1206
|
setLocalRange(range);
|
|
526
1207
|
}, []);
|
|
527
|
-
const applyRangeFilter =
|
|
1208
|
+
const applyRangeFilter = useCallback4(() => {
|
|
528
1209
|
onRangeFilter?.(localRange);
|
|
529
1210
|
onClose();
|
|
530
1211
|
}, [localRange, onRangeFilter, onClose]);
|
|
531
|
-
const clearRangeFilter =
|
|
1212
|
+
const clearRangeFilter = useCallback4(() => {
|
|
532
1213
|
setLocalRange(null);
|
|
533
1214
|
onRangeFilter?.(null);
|
|
534
1215
|
onClose();
|
|
535
1216
|
}, [onRangeFilter, onClose]);
|
|
536
|
-
|
|
1217
|
+
useEffect4(() => {
|
|
537
1218
|
const handleClickOutside = (event) => {
|
|
538
1219
|
if (dropdownRef.current && !dropdownRef.current.contains(event.target)) {
|
|
539
1220
|
onClose();
|
|
@@ -542,7 +1223,7 @@ function ColumnFilter({
|
|
|
542
1223
|
document.addEventListener("mousedown", handleClickOutside);
|
|
543
1224
|
return () => document.removeEventListener("mousedown", handleClickOutside);
|
|
544
1225
|
}, [onClose]);
|
|
545
|
-
|
|
1226
|
+
useEffect4(() => {
|
|
546
1227
|
const handleKeydown = (event) => {
|
|
547
1228
|
if (event.key === "Escape") {
|
|
548
1229
|
onClose();
|
|
@@ -553,36 +1234,36 @@ function ColumnFilter({
|
|
|
553
1234
|
document.addEventListener("keydown", handleKeydown);
|
|
554
1235
|
return () => document.removeEventListener("keydown", handleKeydown);
|
|
555
1236
|
}, [onClose, applyFilter]);
|
|
556
|
-
|
|
1237
|
+
useEffect4(() => {
|
|
557
1238
|
searchInputRef.current?.focus();
|
|
558
1239
|
}, []);
|
|
559
|
-
|
|
1240
|
+
useEffect4(() => {
|
|
560
1241
|
setLocalSelected(new Set(selectedValues));
|
|
561
1242
|
}, [selectedValues]);
|
|
562
|
-
|
|
1243
|
+
useEffect4(() => {
|
|
563
1244
|
setLocalRange(numericRange ?? null);
|
|
564
1245
|
if (numericRange) {
|
|
565
1246
|
setFilterMode("range");
|
|
566
1247
|
}
|
|
567
1248
|
}, [numericRange]);
|
|
568
|
-
return /* @__PURE__ */
|
|
569
|
-
/* @__PURE__ */
|
|
570
|
-
/* @__PURE__ */
|
|
571
|
-
/* @__PURE__ */
|
|
1249
|
+
return /* @__PURE__ */ jsxs4("div", { ref: dropdownRef, className: "vpg-filter-dropdown", children: [
|
|
1250
|
+
/* @__PURE__ */ jsxs4("div", { className: "vpg-filter-header", children: [
|
|
1251
|
+
/* @__PURE__ */ jsx4("span", { className: "vpg-filter-title", children: columnName }),
|
|
1252
|
+
/* @__PURE__ */ jsxs4("span", { className: "vpg-filter-count", children: [
|
|
572
1253
|
stats.uniqueValues.length.toLocaleString(),
|
|
573
1254
|
" ",
|
|
574
1255
|
"unique"
|
|
575
1256
|
] })
|
|
576
1257
|
] }),
|
|
577
|
-
/* @__PURE__ */
|
|
578
|
-
/* @__PURE__ */
|
|
1258
|
+
/* @__PURE__ */ jsxs4("div", { className: "vpg-sort-controls", children: [
|
|
1259
|
+
/* @__PURE__ */ jsxs4(
|
|
579
1260
|
"button",
|
|
580
1261
|
{
|
|
581
1262
|
className: `vpg-sort-btn ${sortDirection === "asc" ? "active" : ""}`,
|
|
582
1263
|
title: isNumericColumn ? "Sort Low to High" : "Sort A to Z",
|
|
583
1264
|
onClick: sortAscending,
|
|
584
1265
|
children: [
|
|
585
|
-
/* @__PURE__ */
|
|
1266
|
+
/* @__PURE__ */ jsx4("svg", { className: "vpg-icon-sm", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: /* @__PURE__ */ jsx4(
|
|
586
1267
|
"path",
|
|
587
1268
|
{
|
|
588
1269
|
strokeLinecap: "round",
|
|
@@ -591,18 +1272,18 @@ function ColumnFilter({
|
|
|
591
1272
|
d: "M3 4h13M3 8h9m-9 4h6m4 0l4-4m0 0l4 4m-4-4v12"
|
|
592
1273
|
}
|
|
593
1274
|
) }),
|
|
594
|
-
/* @__PURE__ */
|
|
1275
|
+
/* @__PURE__ */ jsx4("span", { children: isNumericColumn ? "1\u21929" : "A\u2192Z" })
|
|
595
1276
|
]
|
|
596
1277
|
}
|
|
597
1278
|
),
|
|
598
|
-
/* @__PURE__ */
|
|
1279
|
+
/* @__PURE__ */ jsxs4(
|
|
599
1280
|
"button",
|
|
600
1281
|
{
|
|
601
1282
|
className: `vpg-sort-btn ${sortDirection === "desc" ? "active" : ""}`,
|
|
602
1283
|
title: isNumericColumn ? "Sort High to Low" : "Sort Z to A",
|
|
603
1284
|
onClick: sortDescending,
|
|
604
1285
|
children: [
|
|
605
|
-
/* @__PURE__ */
|
|
1286
|
+
/* @__PURE__ */ jsx4("svg", { className: "vpg-icon-sm", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: /* @__PURE__ */ jsx4(
|
|
606
1287
|
"path",
|
|
607
1288
|
{
|
|
608
1289
|
strokeLinecap: "round",
|
|
@@ -611,20 +1292,20 @@ function ColumnFilter({
|
|
|
611
1292
|
d: "M3 4h13M3 8h9m-9 4h9m5-4v12m0 0l-4-4m4 4l4-4"
|
|
612
1293
|
}
|
|
613
1294
|
) }),
|
|
614
|
-
/* @__PURE__ */
|
|
1295
|
+
/* @__PURE__ */ jsx4("span", { children: isNumericColumn ? "9\u21921" : "Z\u2192A" })
|
|
615
1296
|
]
|
|
616
1297
|
}
|
|
617
1298
|
)
|
|
618
1299
|
] }),
|
|
619
|
-
/* @__PURE__ */
|
|
620
|
-
isNumericColumn && /* @__PURE__ */
|
|
621
|
-
/* @__PURE__ */
|
|
1300
|
+
/* @__PURE__ */ jsx4("div", { className: "vpg-divider" }),
|
|
1301
|
+
isNumericColumn && /* @__PURE__ */ jsxs4("div", { className: "vpg-filter-tabs", children: [
|
|
1302
|
+
/* @__PURE__ */ jsxs4(
|
|
622
1303
|
"button",
|
|
623
1304
|
{
|
|
624
1305
|
className: `vpg-tab-btn ${filterMode === "values" ? "active" : ""}`,
|
|
625
1306
|
onClick: () => setFilterMode("values"),
|
|
626
1307
|
children: [
|
|
627
|
-
/* @__PURE__ */
|
|
1308
|
+
/* @__PURE__ */ jsx4("svg", { className: "vpg-icon-sm", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: /* @__PURE__ */ jsx4(
|
|
628
1309
|
"path",
|
|
629
1310
|
{
|
|
630
1311
|
strokeLinecap: "round",
|
|
@@ -637,13 +1318,13 @@ function ColumnFilter({
|
|
|
637
1318
|
]
|
|
638
1319
|
}
|
|
639
1320
|
),
|
|
640
|
-
/* @__PURE__ */
|
|
1321
|
+
/* @__PURE__ */ jsxs4(
|
|
641
1322
|
"button",
|
|
642
1323
|
{
|
|
643
1324
|
className: `vpg-tab-btn ${filterMode === "range" ? "active" : ""}`,
|
|
644
1325
|
onClick: () => setFilterMode("range"),
|
|
645
1326
|
children: [
|
|
646
|
-
/* @__PURE__ */
|
|
1327
|
+
/* @__PURE__ */ jsx4("svg", { className: "vpg-icon-sm", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: /* @__PURE__ */ jsx4(
|
|
647
1328
|
"path",
|
|
648
1329
|
{
|
|
649
1330
|
strokeLinecap: "round",
|
|
@@ -657,9 +1338,9 @@ function ColumnFilter({
|
|
|
657
1338
|
}
|
|
658
1339
|
)
|
|
659
1340
|
] }),
|
|
660
|
-
(!isNumericColumn || filterMode === "values") && /* @__PURE__ */
|
|
661
|
-
/* @__PURE__ */
|
|
662
|
-
/* @__PURE__ */
|
|
1341
|
+
(!isNumericColumn || filterMode === "values") && /* @__PURE__ */ jsxs4(Fragment2, { children: [
|
|
1342
|
+
/* @__PURE__ */ jsxs4("div", { className: "vpg-search-container", children: [
|
|
1343
|
+
/* @__PURE__ */ jsx4("svg", { className: "vpg-search-icon", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: /* @__PURE__ */ jsx4(
|
|
663
1344
|
"path",
|
|
664
1345
|
{
|
|
665
1346
|
strokeLinecap: "round",
|
|
@@ -668,7 +1349,7 @@ function ColumnFilter({
|
|
|
668
1349
|
d: "M21 21l-6-6m2-5a7 7 0 11-14 0 7 7 0 0114 0z"
|
|
669
1350
|
}
|
|
670
1351
|
) }),
|
|
671
|
-
/* @__PURE__ */
|
|
1352
|
+
/* @__PURE__ */ jsx4(
|
|
672
1353
|
"input",
|
|
673
1354
|
{
|
|
674
1355
|
ref: searchInputRef,
|
|
@@ -679,11 +1360,11 @@ function ColumnFilter({
|
|
|
679
1360
|
className: "vpg-search-input"
|
|
680
1361
|
}
|
|
681
1362
|
),
|
|
682
|
-
searchQuery && /* @__PURE__ */
|
|
1363
|
+
searchQuery && /* @__PURE__ */ jsx4("button", { className: "vpg-clear-search", onClick: () => setSearchQuery(""), children: "\xD7" })
|
|
683
1364
|
] }),
|
|
684
|
-
/* @__PURE__ */
|
|
685
|
-
/* @__PURE__ */
|
|
686
|
-
/* @__PURE__ */
|
|
1365
|
+
/* @__PURE__ */ jsxs4("div", { className: "vpg-bulk-actions", children: [
|
|
1366
|
+
/* @__PURE__ */ jsxs4("button", { className: "vpg-bulk-btn", onClick: selectAll, children: [
|
|
1367
|
+
/* @__PURE__ */ jsx4("svg", { className: "vpg-icon-sm", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: /* @__PURE__ */ jsx4(
|
|
687
1368
|
"path",
|
|
688
1369
|
{
|
|
689
1370
|
strokeLinecap: "round",
|
|
@@ -694,8 +1375,8 @@ function ColumnFilter({
|
|
|
694
1375
|
) }),
|
|
695
1376
|
"Select All"
|
|
696
1377
|
] }),
|
|
697
|
-
/* @__PURE__ */
|
|
698
|
-
/* @__PURE__ */
|
|
1378
|
+
/* @__PURE__ */ jsxs4("button", { className: "vpg-bulk-btn", onClick: clearAll, children: [
|
|
1379
|
+
/* @__PURE__ */ jsx4("svg", { className: "vpg-icon-sm", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: /* @__PURE__ */ jsx4(
|
|
699
1380
|
"path",
|
|
700
1381
|
{
|
|
701
1382
|
strokeLinecap: "round",
|
|
@@ -707,13 +1388,13 @@ function ColumnFilter({
|
|
|
707
1388
|
"Clear All"
|
|
708
1389
|
] })
|
|
709
1390
|
] }),
|
|
710
|
-
/* @__PURE__ */
|
|
711
|
-
allValues.map((value) => /* @__PURE__ */
|
|
1391
|
+
/* @__PURE__ */ jsxs4("div", { className: "vpg-values-list", children: [
|
|
1392
|
+
allValues.map((value) => /* @__PURE__ */ jsxs4(
|
|
712
1393
|
"label",
|
|
713
1394
|
{
|
|
714
1395
|
className: `vpg-value-item ${localSelected.has(value) ? "selected" : ""}`,
|
|
715
1396
|
children: [
|
|
716
|
-
/* @__PURE__ */
|
|
1397
|
+
/* @__PURE__ */ jsx4(
|
|
717
1398
|
"input",
|
|
718
1399
|
{
|
|
719
1400
|
type: "checkbox",
|
|
@@ -722,20 +1403,20 @@ function ColumnFilter({
|
|
|
722
1403
|
className: "vpg-value-checkbox"
|
|
723
1404
|
}
|
|
724
1405
|
),
|
|
725
|
-
/* @__PURE__ */
|
|
1406
|
+
/* @__PURE__ */ jsx4("span", { className: `vpg-value-text ${value === "(blank)" ? "vpg-blank" : ""}`, children: value })
|
|
726
1407
|
]
|
|
727
1408
|
},
|
|
728
1409
|
value
|
|
729
1410
|
)),
|
|
730
|
-
allValues.length === 0 && /* @__PURE__ */
|
|
1411
|
+
allValues.length === 0 && /* @__PURE__ */ jsx4("div", { className: "vpg-no-results", children: "No matching values" })
|
|
731
1412
|
] }),
|
|
732
|
-
/* @__PURE__ */
|
|
733
|
-
/* @__PURE__ */
|
|
734
|
-
/* @__PURE__ */
|
|
1413
|
+
/* @__PURE__ */ jsxs4("div", { className: "vpg-filter-footer", children: [
|
|
1414
|
+
/* @__PURE__ */ jsx4("button", { className: "vpg-btn-clear", onClick: clearFilter, children: "Clear Filter" }),
|
|
1415
|
+
/* @__PURE__ */ jsx4("button", { className: "vpg-btn-apply", onClick: applyFilter, children: "Apply" })
|
|
735
1416
|
] })
|
|
736
1417
|
] }),
|
|
737
|
-
isNumericColumn && filterMode === "range" && /* @__PURE__ */
|
|
738
|
-
/* @__PURE__ */
|
|
1418
|
+
isNumericColumn && filterMode === "range" && /* @__PURE__ */ jsxs4(Fragment2, { children: [
|
|
1419
|
+
/* @__PURE__ */ jsx4(
|
|
739
1420
|
NumericRangeFilter,
|
|
740
1421
|
{
|
|
741
1422
|
dataMin: stats.numericMin,
|
|
@@ -744,16 +1425,16 @@ function ColumnFilter({
|
|
|
744
1425
|
onChange: handleRangeChange
|
|
745
1426
|
}
|
|
746
1427
|
),
|
|
747
|
-
/* @__PURE__ */
|
|
748
|
-
/* @__PURE__ */
|
|
749
|
-
/* @__PURE__ */
|
|
1428
|
+
/* @__PURE__ */ jsxs4("div", { className: "vpg-filter-footer", children: [
|
|
1429
|
+
/* @__PURE__ */ jsx4("button", { className: "vpg-btn-clear", onClick: clearRangeFilter, children: "Clear Filter" }),
|
|
1430
|
+
/* @__PURE__ */ jsx4("button", { className: "vpg-btn-apply", onClick: applyRangeFilter, children: "Apply" })
|
|
750
1431
|
] })
|
|
751
1432
|
] })
|
|
752
1433
|
] });
|
|
753
1434
|
}
|
|
754
1435
|
|
|
755
1436
|
// src/components/DataGrid.tsx
|
|
756
|
-
import { useCallback as
|
|
1437
|
+
import { useCallback as useCallback11, useEffect as useEffect8, useMemo as useMemo11, useRef as useRef2, useState as useState11 } from "react";
|
|
757
1438
|
import { createPortal as createPortal2 } from "react-dom";
|
|
758
1439
|
|
|
759
1440
|
// src/hooks/useExcelGrid.ts
|
|
@@ -764,7 +1445,7 @@ import {
|
|
|
764
1445
|
getSortedRowModel,
|
|
765
1446
|
useReactTable
|
|
766
1447
|
} from "@tanstack/react-table";
|
|
767
|
-
import { useCallback as
|
|
1448
|
+
import { useCallback as useCallback5, useEffect as useEffect5, useMemo as useMemo5, useState as useState5 } from "react";
|
|
768
1449
|
var multiSelectFilter = (row, columnId, filterValue) => {
|
|
769
1450
|
if (!filterValue)
|
|
770
1451
|
return true;
|
|
@@ -792,21 +1473,21 @@ var multiSelectFilter = (row, columnId, filterValue) => {
|
|
|
792
1473
|
};
|
|
793
1474
|
function useExcelGrid(options) {
|
|
794
1475
|
const { data, enableSorting = true, enableFiltering = true } = options;
|
|
795
|
-
const [sorting, setSorting] =
|
|
796
|
-
const [columnFilters, setColumnFilters] =
|
|
797
|
-
const [columnVisibility, setColumnVisibility] =
|
|
798
|
-
const [globalFilter, setGlobalFilter] =
|
|
799
|
-
const [columnStatsCache, setColumnStatsCache] =
|
|
800
|
-
const dataSignature =
|
|
1476
|
+
const [sorting, setSorting] = useState5([]);
|
|
1477
|
+
const [columnFilters, setColumnFilters] = useState5([]);
|
|
1478
|
+
const [columnVisibility, setColumnVisibility] = useState5({});
|
|
1479
|
+
const [globalFilter, setGlobalFilter] = useState5("");
|
|
1480
|
+
const [columnStatsCache, setColumnStatsCache] = useState5({});
|
|
1481
|
+
const dataSignature = useMemo5(
|
|
801
1482
|
() => `${Date.now()}-${Math.random().toString(36).slice(2)}`,
|
|
802
1483
|
[data]
|
|
803
1484
|
);
|
|
804
|
-
const columnKeys =
|
|
1485
|
+
const columnKeys = useMemo5(() => {
|
|
805
1486
|
if (data.length === 0)
|
|
806
1487
|
return [];
|
|
807
1488
|
return Object.keys(data[0]);
|
|
808
1489
|
}, [data]);
|
|
809
|
-
const getColumnStats =
|
|
1490
|
+
const getColumnStats = useCallback5(
|
|
810
1491
|
(columnKey) => {
|
|
811
1492
|
const cacheKey = `${columnKey}-${dataSignature}`;
|
|
812
1493
|
if (!columnStatsCache[cacheKey]) {
|
|
@@ -818,13 +1499,13 @@ function useExcelGrid(options) {
|
|
|
818
1499
|
},
|
|
819
1500
|
[data, columnStatsCache, dataSignature]
|
|
820
1501
|
);
|
|
821
|
-
const clearStatsCache =
|
|
1502
|
+
const clearStatsCache = useCallback5(() => {
|
|
822
1503
|
setColumnStatsCache({});
|
|
823
1504
|
}, []);
|
|
824
|
-
|
|
1505
|
+
useEffect5(() => {
|
|
825
1506
|
clearStatsCache();
|
|
826
1507
|
}, [dataSignature, clearStatsCache]);
|
|
827
|
-
const columnDefs =
|
|
1508
|
+
const columnDefs = useMemo5(() => {
|
|
828
1509
|
return columnKeys.map((key) => {
|
|
829
1510
|
const stats = getColumnStats(key);
|
|
830
1511
|
return {
|
|
@@ -864,7 +1545,7 @@ function useExcelGrid(options) {
|
|
|
864
1545
|
});
|
|
865
1546
|
const filteredRowCount = table.getFilteredRowModel().rows.length;
|
|
866
1547
|
const totalRowCount = data.length;
|
|
867
|
-
const activeFilters =
|
|
1548
|
+
const activeFilters = useMemo5(() => {
|
|
868
1549
|
return columnFilters.map((f) => {
|
|
869
1550
|
const filterValue = f.value;
|
|
870
1551
|
if (filterValue && isNumericRange(filterValue)) {
|
|
@@ -883,7 +1564,7 @@ function useExcelGrid(options) {
|
|
|
883
1564
|
};
|
|
884
1565
|
});
|
|
885
1566
|
}, [columnFilters]);
|
|
886
|
-
const hasActiveFilter =
|
|
1567
|
+
const hasActiveFilter = useCallback5(
|
|
887
1568
|
(columnId) => {
|
|
888
1569
|
const column = table.getColumn(columnId);
|
|
889
1570
|
if (!column)
|
|
@@ -898,7 +1579,7 @@ function useExcelGrid(options) {
|
|
|
898
1579
|
},
|
|
899
1580
|
[table]
|
|
900
1581
|
);
|
|
901
|
-
const setColumnFilter =
|
|
1582
|
+
const setColumnFilter = useCallback5(
|
|
902
1583
|
(columnId, values) => {
|
|
903
1584
|
const column = table.getColumn(columnId);
|
|
904
1585
|
if (column) {
|
|
@@ -907,7 +1588,7 @@ function useExcelGrid(options) {
|
|
|
907
1588
|
},
|
|
908
1589
|
[table]
|
|
909
1590
|
);
|
|
910
|
-
const setNumericRangeFilter =
|
|
1591
|
+
const setNumericRangeFilter = useCallback5(
|
|
911
1592
|
(columnId, range) => {
|
|
912
1593
|
const column = table.getColumn(columnId);
|
|
913
1594
|
if (column) {
|
|
@@ -920,7 +1601,7 @@ function useExcelGrid(options) {
|
|
|
920
1601
|
},
|
|
921
1602
|
[table]
|
|
922
1603
|
);
|
|
923
|
-
const getNumericRangeFilter =
|
|
1604
|
+
const getNumericRangeFilter = useCallback5(
|
|
924
1605
|
(columnId) => {
|
|
925
1606
|
const column = table.getColumn(columnId);
|
|
926
1607
|
if (!column)
|
|
@@ -933,12 +1614,12 @@ function useExcelGrid(options) {
|
|
|
933
1614
|
},
|
|
934
1615
|
[table]
|
|
935
1616
|
);
|
|
936
|
-
const clearAllFilters =
|
|
1617
|
+
const clearAllFilters = useCallback5(() => {
|
|
937
1618
|
table.resetColumnFilters();
|
|
938
1619
|
setGlobalFilter("");
|
|
939
1620
|
setColumnFilters([]);
|
|
940
1621
|
}, [table]);
|
|
941
|
-
const getColumnFilterValues =
|
|
1622
|
+
const getColumnFilterValues = useCallback5(
|
|
942
1623
|
(columnId) => {
|
|
943
1624
|
const column = table.getColumn(columnId);
|
|
944
1625
|
if (!column)
|
|
@@ -948,7 +1629,7 @@ function useExcelGrid(options) {
|
|
|
948
1629
|
},
|
|
949
1630
|
[table]
|
|
950
1631
|
);
|
|
951
|
-
const toggleSort =
|
|
1632
|
+
const toggleSort = useCallback5((columnId) => {
|
|
952
1633
|
setSorting((prev) => {
|
|
953
1634
|
const current = prev.find((s) => s.id === columnId);
|
|
954
1635
|
if (!current) {
|
|
@@ -960,7 +1641,7 @@ function useExcelGrid(options) {
|
|
|
960
1641
|
}
|
|
961
1642
|
});
|
|
962
1643
|
}, []);
|
|
963
|
-
const getSortDirection =
|
|
1644
|
+
const getSortDirection = useCallback5(
|
|
964
1645
|
(columnId) => {
|
|
965
1646
|
const sort = sorting.find((s) => s.id === columnId);
|
|
966
1647
|
if (!sort)
|
|
@@ -1007,7 +1688,7 @@ import {
|
|
|
1007
1688
|
exportToCSV as coreExportToCSV,
|
|
1008
1689
|
formatSelectionForClipboard as coreFormatSelection
|
|
1009
1690
|
} from "@smallwebco/tinypivot-core";
|
|
1010
|
-
import { useCallback as
|
|
1691
|
+
import { useCallback as useCallback6, useMemo as useMemo6, useState as useState6 } from "react";
|
|
1011
1692
|
function exportToCSV(data, columns, options) {
|
|
1012
1693
|
coreExportToCSV(data, columns, options);
|
|
1013
1694
|
}
|
|
@@ -1021,45 +1702,45 @@ function formatSelectionForClipboard(rows, columns, selectionBounds) {
|
|
|
1021
1702
|
return coreFormatSelection(rows, columns, selectionBounds);
|
|
1022
1703
|
}
|
|
1023
1704
|
function usePagination(data, options = {}) {
|
|
1024
|
-
const [pageSize, setPageSize] =
|
|
1025
|
-
const [currentPage, setCurrentPage] =
|
|
1026
|
-
const totalPages =
|
|
1705
|
+
const [pageSize, setPageSize] = useState6(options.pageSize ?? 50);
|
|
1706
|
+
const [currentPage, setCurrentPage] = useState6(options.currentPage ?? 1);
|
|
1707
|
+
const totalPages = useMemo6(
|
|
1027
1708
|
() => Math.max(1, Math.ceil(data.length / pageSize)),
|
|
1028
1709
|
[data.length, pageSize]
|
|
1029
1710
|
);
|
|
1030
|
-
const paginatedData =
|
|
1711
|
+
const paginatedData = useMemo6(() => {
|
|
1031
1712
|
const start = (currentPage - 1) * pageSize;
|
|
1032
1713
|
const end = start + pageSize;
|
|
1033
1714
|
return data.slice(start, end);
|
|
1034
1715
|
}, [data, currentPage, pageSize]);
|
|
1035
|
-
const startIndex =
|
|
1036
|
-
const endIndex =
|
|
1716
|
+
const startIndex = useMemo6(() => (currentPage - 1) * pageSize + 1, [currentPage, pageSize]);
|
|
1717
|
+
const endIndex = useMemo6(
|
|
1037
1718
|
() => Math.min(currentPage * pageSize, data.length),
|
|
1038
1719
|
[currentPage, pageSize, data.length]
|
|
1039
1720
|
);
|
|
1040
|
-
const goToPage =
|
|
1721
|
+
const goToPage = useCallback6(
|
|
1041
1722
|
(page) => {
|
|
1042
1723
|
setCurrentPage(Math.max(1, Math.min(page, totalPages)));
|
|
1043
1724
|
},
|
|
1044
1725
|
[totalPages]
|
|
1045
1726
|
);
|
|
1046
|
-
const nextPage =
|
|
1727
|
+
const nextPage = useCallback6(() => {
|
|
1047
1728
|
if (currentPage < totalPages) {
|
|
1048
1729
|
setCurrentPage((prev) => prev + 1);
|
|
1049
1730
|
}
|
|
1050
1731
|
}, [currentPage, totalPages]);
|
|
1051
|
-
const prevPage =
|
|
1732
|
+
const prevPage = useCallback6(() => {
|
|
1052
1733
|
if (currentPage > 1) {
|
|
1053
1734
|
setCurrentPage((prev) => prev - 1);
|
|
1054
1735
|
}
|
|
1055
1736
|
}, [currentPage]);
|
|
1056
|
-
const firstPage =
|
|
1737
|
+
const firstPage = useCallback6(() => {
|
|
1057
1738
|
setCurrentPage(1);
|
|
1058
1739
|
}, []);
|
|
1059
|
-
const lastPage =
|
|
1740
|
+
const lastPage = useCallback6(() => {
|
|
1060
1741
|
setCurrentPage(totalPages);
|
|
1061
1742
|
}, [totalPages]);
|
|
1062
|
-
const updatePageSize =
|
|
1743
|
+
const updatePageSize = useCallback6((size) => {
|
|
1063
1744
|
setPageSize(size);
|
|
1064
1745
|
setCurrentPage(1);
|
|
1065
1746
|
}, []);
|
|
@@ -1079,9 +1760,9 @@ function usePagination(data, options = {}) {
|
|
|
1079
1760
|
};
|
|
1080
1761
|
}
|
|
1081
1762
|
function useGlobalSearch(data, columns) {
|
|
1082
|
-
const [searchTerm, setSearchTerm] =
|
|
1083
|
-
const [caseSensitive, setCaseSensitive] =
|
|
1084
|
-
const filteredData =
|
|
1763
|
+
const [searchTerm, setSearchTerm] = useState6("");
|
|
1764
|
+
const [caseSensitive, setCaseSensitive] = useState6(false);
|
|
1765
|
+
const filteredData = useMemo6(() => {
|
|
1085
1766
|
if (!searchTerm.trim()) {
|
|
1086
1767
|
return data;
|
|
1087
1768
|
}
|
|
@@ -1099,7 +1780,7 @@ function useGlobalSearch(data, columns) {
|
|
|
1099
1780
|
return false;
|
|
1100
1781
|
});
|
|
1101
1782
|
}, [data, columns, searchTerm, caseSensitive]);
|
|
1102
|
-
const clearSearch =
|
|
1783
|
+
const clearSearch = useCallback6(() => {
|
|
1103
1784
|
setSearchTerm("");
|
|
1104
1785
|
}, []);
|
|
1105
1786
|
return {
|
|
@@ -1112,17 +1793,17 @@ function useGlobalSearch(data, columns) {
|
|
|
1112
1793
|
};
|
|
1113
1794
|
}
|
|
1114
1795
|
function useRowSelection(data) {
|
|
1115
|
-
const [selectedRowIndices, setSelectedRowIndices] =
|
|
1116
|
-
const selectedRows =
|
|
1796
|
+
const [selectedRowIndices, setSelectedRowIndices] = useState6(/* @__PURE__ */ new Set());
|
|
1797
|
+
const selectedRows = useMemo6(() => {
|
|
1117
1798
|
return Array.from(selectedRowIndices).sort((a, b) => a - b).map((idx) => data[idx]).filter(Boolean);
|
|
1118
1799
|
}, [data, selectedRowIndices]);
|
|
1119
|
-
const allSelected =
|
|
1800
|
+
const allSelected = useMemo6(() => {
|
|
1120
1801
|
return data.length > 0 && selectedRowIndices.size === data.length;
|
|
1121
1802
|
}, [data.length, selectedRowIndices.size]);
|
|
1122
|
-
const someSelected =
|
|
1803
|
+
const someSelected = useMemo6(() => {
|
|
1123
1804
|
return selectedRowIndices.size > 0 && selectedRowIndices.size < data.length;
|
|
1124
1805
|
}, [data.length, selectedRowIndices.size]);
|
|
1125
|
-
const toggleRow =
|
|
1806
|
+
const toggleRow = useCallback6((index) => {
|
|
1126
1807
|
setSelectedRowIndices((prev) => {
|
|
1127
1808
|
const next = new Set(prev);
|
|
1128
1809
|
if (next.has(index)) {
|
|
@@ -1133,36 +1814,36 @@ function useRowSelection(data) {
|
|
|
1133
1814
|
return next;
|
|
1134
1815
|
});
|
|
1135
1816
|
}, []);
|
|
1136
|
-
const selectRow =
|
|
1817
|
+
const selectRow = useCallback6((index) => {
|
|
1137
1818
|
setSelectedRowIndices((prev) => /* @__PURE__ */ new Set([...prev, index]));
|
|
1138
1819
|
}, []);
|
|
1139
|
-
const deselectRow =
|
|
1820
|
+
const deselectRow = useCallback6((index) => {
|
|
1140
1821
|
setSelectedRowIndices((prev) => {
|
|
1141
1822
|
const next = new Set(prev);
|
|
1142
1823
|
next.delete(index);
|
|
1143
1824
|
return next;
|
|
1144
1825
|
});
|
|
1145
1826
|
}, []);
|
|
1146
|
-
const selectAll =
|
|
1827
|
+
const selectAll = useCallback6(() => {
|
|
1147
1828
|
setSelectedRowIndices(new Set(data.map((_, idx) => idx)));
|
|
1148
1829
|
}, [data]);
|
|
1149
|
-
const deselectAll =
|
|
1830
|
+
const deselectAll = useCallback6(() => {
|
|
1150
1831
|
setSelectedRowIndices(/* @__PURE__ */ new Set());
|
|
1151
1832
|
}, []);
|
|
1152
|
-
const toggleAll =
|
|
1833
|
+
const toggleAll = useCallback6(() => {
|
|
1153
1834
|
if (allSelected) {
|
|
1154
1835
|
deselectAll();
|
|
1155
1836
|
} else {
|
|
1156
1837
|
selectAll();
|
|
1157
1838
|
}
|
|
1158
1839
|
}, [allSelected, selectAll, deselectAll]);
|
|
1159
|
-
const isSelected =
|
|
1840
|
+
const isSelected = useCallback6(
|
|
1160
1841
|
(index) => {
|
|
1161
1842
|
return selectedRowIndices.has(index);
|
|
1162
1843
|
},
|
|
1163
1844
|
[selectedRowIndices]
|
|
1164
1845
|
);
|
|
1165
|
-
const selectRange =
|
|
1846
|
+
const selectRange = useCallback6((startIndex, endIndex) => {
|
|
1166
1847
|
const min = Math.min(startIndex, endIndex);
|
|
1167
1848
|
const max = Math.max(startIndex, endIndex);
|
|
1168
1849
|
setSelectedRowIndices((prev) => {
|
|
@@ -1189,10 +1870,10 @@ function useRowSelection(data) {
|
|
|
1189
1870
|
};
|
|
1190
1871
|
}
|
|
1191
1872
|
function useColumnResize(initialWidths, minWidth = 60, maxWidth = 600) {
|
|
1192
|
-
const [columnWidths, setColumnWidths] =
|
|
1193
|
-
const [isResizing, setIsResizing] =
|
|
1194
|
-
const [resizingColumn, setResizingColumn] =
|
|
1195
|
-
const startResize =
|
|
1873
|
+
const [columnWidths, setColumnWidths] = useState6({ ...initialWidths });
|
|
1874
|
+
const [isResizing, setIsResizing] = useState6(false);
|
|
1875
|
+
const [resizingColumn, setResizingColumn] = useState6(null);
|
|
1876
|
+
const startResize = useCallback6(
|
|
1196
1877
|
(columnId, event) => {
|
|
1197
1878
|
setIsResizing(true);
|
|
1198
1879
|
setResizingColumn(columnId);
|
|
@@ -1217,7 +1898,7 @@ function useColumnResize(initialWidths, minWidth = 60, maxWidth = 600) {
|
|
|
1217
1898
|
},
|
|
1218
1899
|
[columnWidths, minWidth, maxWidth]
|
|
1219
1900
|
);
|
|
1220
|
-
const resetColumnWidth =
|
|
1901
|
+
const resetColumnWidth = useCallback6(
|
|
1221
1902
|
(columnId) => {
|
|
1222
1903
|
if (initialWidths[columnId]) {
|
|
1223
1904
|
setColumnWidths((prev) => ({
|
|
@@ -1228,7 +1909,7 @@ function useColumnResize(initialWidths, minWidth = 60, maxWidth = 600) {
|
|
|
1228
1909
|
},
|
|
1229
1910
|
[initialWidths]
|
|
1230
1911
|
);
|
|
1231
|
-
const resetAllWidths =
|
|
1912
|
+
const resetAllWidths = useCallback6(() => {
|
|
1232
1913
|
setColumnWidths({ ...initialWidths });
|
|
1233
1914
|
}, [initialWidths]);
|
|
1234
1915
|
return {
|
|
@@ -1244,6 +1925,7 @@ function useColumnResize(initialWidths, minWidth = 60, maxWidth = 600) {
|
|
|
1244
1925
|
|
|
1245
1926
|
// src/hooks/useLicense.ts
|
|
1246
1927
|
import {
|
|
1928
|
+
canUseCharts as coreCanUseCharts,
|
|
1247
1929
|
canUsePivot as coreCanUsePivot,
|
|
1248
1930
|
configureLicenseSecret as coreConfigureLicenseSecret,
|
|
1249
1931
|
isPro as coreIsPro,
|
|
@@ -1253,7 +1935,7 @@ import {
|
|
|
1253
1935
|
logProRequired,
|
|
1254
1936
|
validateLicenseKey
|
|
1255
1937
|
} from "@smallwebco/tinypivot-core";
|
|
1256
|
-
import { useCallback as
|
|
1938
|
+
import { useCallback as useCallback7, useMemo as useMemo7, useState as useState7 } from "react";
|
|
1257
1939
|
var globalLicenseInfo = getFreeLicenseInfo();
|
|
1258
1940
|
var globalDemoMode = false;
|
|
1259
1941
|
var listeners = /* @__PURE__ */ new Set();
|
|
@@ -1285,35 +1967,39 @@ function configureLicenseSecret(secret) {
|
|
|
1285
1967
|
coreConfigureLicenseSecret(secret);
|
|
1286
1968
|
}
|
|
1287
1969
|
function useLicense() {
|
|
1288
|
-
const [, forceUpdate] =
|
|
1289
|
-
|
|
1970
|
+
const [, forceUpdate] = useState7({});
|
|
1971
|
+
useState7(() => {
|
|
1290
1972
|
const update = () => forceUpdate({});
|
|
1291
1973
|
listeners.add(update);
|
|
1292
1974
|
return () => listeners.delete(update);
|
|
1293
1975
|
});
|
|
1294
1976
|
const isDemo = globalDemoMode;
|
|
1295
1977
|
const licenseInfo = globalLicenseInfo;
|
|
1296
|
-
const isPro =
|
|
1978
|
+
const isPro = useMemo7(
|
|
1297
1979
|
() => globalDemoMode || coreIsPro(licenseInfo),
|
|
1298
1980
|
[licenseInfo]
|
|
1299
1981
|
);
|
|
1300
|
-
const canUsePivot =
|
|
1982
|
+
const canUsePivot = useMemo7(
|
|
1301
1983
|
() => globalDemoMode || coreCanUsePivot(licenseInfo),
|
|
1302
1984
|
[licenseInfo]
|
|
1303
1985
|
);
|
|
1304
|
-
const canUseAdvancedAggregations =
|
|
1986
|
+
const canUseAdvancedAggregations = useMemo7(
|
|
1305
1987
|
() => globalDemoMode || licenseInfo.features.advancedAggregations,
|
|
1306
1988
|
[licenseInfo]
|
|
1307
1989
|
);
|
|
1308
|
-
const canUsePercentageMode =
|
|
1990
|
+
const canUsePercentageMode = useMemo7(
|
|
1309
1991
|
() => globalDemoMode || licenseInfo.features.percentageMode,
|
|
1310
1992
|
[licenseInfo]
|
|
1311
1993
|
);
|
|
1312
|
-
const
|
|
1994
|
+
const canUseCharts = useMemo7(
|
|
1995
|
+
() => globalDemoMode || coreCanUseCharts(licenseInfo),
|
|
1996
|
+
[licenseInfo]
|
|
1997
|
+
);
|
|
1998
|
+
const showWatermark = useMemo7(
|
|
1313
1999
|
() => coreShouldShowWatermark(licenseInfo, globalDemoMode),
|
|
1314
2000
|
[licenseInfo]
|
|
1315
2001
|
);
|
|
1316
|
-
const requirePro =
|
|
2002
|
+
const requirePro = useCallback7((feature) => {
|
|
1317
2003
|
if (!isPro) {
|
|
1318
2004
|
logProRequired(feature);
|
|
1319
2005
|
return false;
|
|
@@ -1327,6 +2013,7 @@ function useLicense() {
|
|
|
1327
2013
|
canUsePivot,
|
|
1328
2014
|
canUseAdvancedAggregations,
|
|
1329
2015
|
canUsePercentageMode,
|
|
2016
|
+
canUseCharts,
|
|
1330
2017
|
showWatermark,
|
|
1331
2018
|
requirePro
|
|
1332
2019
|
};
|
|
@@ -1346,23 +2033,23 @@ import {
|
|
|
1346
2033
|
saveCalculatedFields,
|
|
1347
2034
|
savePivotConfig
|
|
1348
2035
|
} from "@smallwebco/tinypivot-core";
|
|
1349
|
-
import { useCallback as
|
|
2036
|
+
import { useCallback as useCallback8, useEffect as useEffect6, useMemo as useMemo8, useState as useState8 } from "react";
|
|
1350
2037
|
function usePivotTable(data) {
|
|
1351
2038
|
const { canUsePivot, requirePro } = useLicense();
|
|
1352
|
-
const [rowFields, setRowFieldsState] =
|
|
1353
|
-
const [columnFields, setColumnFieldsState] =
|
|
1354
|
-
const [valueFields, setValueFields] =
|
|
1355
|
-
const [showRowTotals, setShowRowTotals] =
|
|
1356
|
-
const [showColumnTotals, setShowColumnTotals] =
|
|
1357
|
-
const [calculatedFields, setCalculatedFields] =
|
|
1358
|
-
const [currentStorageKey, setCurrentStorageKey] =
|
|
1359
|
-
const availableFields =
|
|
2039
|
+
const [rowFields, setRowFieldsState] = useState8([]);
|
|
2040
|
+
const [columnFields, setColumnFieldsState] = useState8([]);
|
|
2041
|
+
const [valueFields, setValueFields] = useState8([]);
|
|
2042
|
+
const [showRowTotals, setShowRowTotals] = useState8(true);
|
|
2043
|
+
const [showColumnTotals, setShowColumnTotals] = useState8(true);
|
|
2044
|
+
const [calculatedFields, setCalculatedFields] = useState8(() => loadCalculatedFields());
|
|
2045
|
+
const [currentStorageKey, setCurrentStorageKey] = useState8(null);
|
|
2046
|
+
const availableFields = useMemo8(() => {
|
|
1360
2047
|
return computeAvailableFields(data);
|
|
1361
2048
|
}, [data]);
|
|
1362
|
-
const unassignedFields =
|
|
2049
|
+
const unassignedFields = useMemo8(() => {
|
|
1363
2050
|
return getUnassignedFields(availableFields, rowFields, columnFields, valueFields);
|
|
1364
2051
|
}, [availableFields, rowFields, columnFields, valueFields]);
|
|
1365
|
-
const isConfigured =
|
|
2052
|
+
const isConfigured = useMemo8(() => {
|
|
1366
2053
|
return isPivotConfigured({
|
|
1367
2054
|
rowFields,
|
|
1368
2055
|
columnFields,
|
|
@@ -1371,7 +2058,7 @@ function usePivotTable(data) {
|
|
|
1371
2058
|
showColumnTotals
|
|
1372
2059
|
});
|
|
1373
2060
|
}, [rowFields, columnFields, valueFields, showRowTotals, showColumnTotals]);
|
|
1374
|
-
const pivotResult =
|
|
2061
|
+
const pivotResult = useMemo8(() => {
|
|
1375
2062
|
if (!isConfigured)
|
|
1376
2063
|
return null;
|
|
1377
2064
|
if (!canUsePivot)
|
|
@@ -1385,7 +2072,7 @@ function usePivotTable(data) {
|
|
|
1385
2072
|
calculatedFields
|
|
1386
2073
|
});
|
|
1387
2074
|
}, [data, isConfigured, canUsePivot, rowFields, columnFields, valueFields, showRowTotals, showColumnTotals, calculatedFields]);
|
|
1388
|
-
|
|
2075
|
+
useEffect6(() => {
|
|
1389
2076
|
if (data.length === 0)
|
|
1390
2077
|
return;
|
|
1391
2078
|
const newKeys = Object.keys(data[0]);
|
|
@@ -1418,7 +2105,7 @@ function usePivotTable(data) {
|
|
|
1418
2105
|
}
|
|
1419
2106
|
}
|
|
1420
2107
|
}, [data]);
|
|
1421
|
-
|
|
2108
|
+
useEffect6(() => {
|
|
1422
2109
|
if (!currentStorageKey)
|
|
1423
2110
|
return;
|
|
1424
2111
|
const config = {
|
|
@@ -1431,7 +2118,7 @@ function usePivotTable(data) {
|
|
|
1431
2118
|
};
|
|
1432
2119
|
savePivotConfig(currentStorageKey, config);
|
|
1433
2120
|
}, [currentStorageKey, rowFields, columnFields, valueFields, showRowTotals, showColumnTotals, calculatedFields]);
|
|
1434
|
-
const addRowField =
|
|
2121
|
+
const addRowField = useCallback8(
|
|
1435
2122
|
(field) => {
|
|
1436
2123
|
if (!rowFields.includes(field)) {
|
|
1437
2124
|
setRowFieldsState((prev) => [...prev, field]);
|
|
@@ -1439,13 +2126,13 @@ function usePivotTable(data) {
|
|
|
1439
2126
|
},
|
|
1440
2127
|
[rowFields]
|
|
1441
2128
|
);
|
|
1442
|
-
const removeRowField =
|
|
2129
|
+
const removeRowField = useCallback8((field) => {
|
|
1443
2130
|
setRowFieldsState((prev) => prev.filter((f) => f !== field));
|
|
1444
2131
|
}, []);
|
|
1445
|
-
const setRowFields =
|
|
2132
|
+
const setRowFields = useCallback8((fields) => {
|
|
1446
2133
|
setRowFieldsState(fields);
|
|
1447
2134
|
}, []);
|
|
1448
|
-
const addColumnField =
|
|
2135
|
+
const addColumnField = useCallback8(
|
|
1449
2136
|
(field) => {
|
|
1450
2137
|
if (!columnFields.includes(field)) {
|
|
1451
2138
|
setColumnFieldsState((prev) => [...prev, field]);
|
|
@@ -1453,13 +2140,13 @@ function usePivotTable(data) {
|
|
|
1453
2140
|
},
|
|
1454
2141
|
[columnFields]
|
|
1455
2142
|
);
|
|
1456
|
-
const removeColumnField =
|
|
2143
|
+
const removeColumnField = useCallback8((field) => {
|
|
1457
2144
|
setColumnFieldsState((prev) => prev.filter((f) => f !== field));
|
|
1458
2145
|
}, []);
|
|
1459
|
-
const setColumnFields =
|
|
2146
|
+
const setColumnFields = useCallback8((fields) => {
|
|
1460
2147
|
setColumnFieldsState(fields);
|
|
1461
2148
|
}, []);
|
|
1462
|
-
const addValueField =
|
|
2149
|
+
const addValueField = useCallback8(
|
|
1463
2150
|
(field, aggregation = "sum") => {
|
|
1464
2151
|
if (aggregation !== "sum" && !requirePro(`${aggregation} aggregation`)) {
|
|
1465
2152
|
return;
|
|
@@ -1473,7 +2160,7 @@ function usePivotTable(data) {
|
|
|
1473
2160
|
},
|
|
1474
2161
|
[requirePro]
|
|
1475
2162
|
);
|
|
1476
|
-
const removeValueField =
|
|
2163
|
+
const removeValueField = useCallback8((field, aggregation) => {
|
|
1477
2164
|
setValueFields((prev) => {
|
|
1478
2165
|
if (aggregation) {
|
|
1479
2166
|
return prev.filter((v) => !(v.field === field && v.aggregation === aggregation));
|
|
@@ -1481,7 +2168,7 @@ function usePivotTable(data) {
|
|
|
1481
2168
|
return prev.filter((v) => v.field !== field);
|
|
1482
2169
|
});
|
|
1483
2170
|
}, []);
|
|
1484
|
-
const updateValueFieldAggregation =
|
|
2171
|
+
const updateValueFieldAggregation = useCallback8(
|
|
1485
2172
|
(field, oldAgg, newAgg) => {
|
|
1486
2173
|
setValueFields(
|
|
1487
2174
|
(prev) => prev.map((v) => {
|
|
@@ -1494,12 +2181,12 @@ function usePivotTable(data) {
|
|
|
1494
2181
|
},
|
|
1495
2182
|
[]
|
|
1496
2183
|
);
|
|
1497
|
-
const clearConfig =
|
|
2184
|
+
const clearConfig = useCallback8(() => {
|
|
1498
2185
|
setRowFieldsState([]);
|
|
1499
2186
|
setColumnFieldsState([]);
|
|
1500
2187
|
setValueFields([]);
|
|
1501
2188
|
}, []);
|
|
1502
|
-
const autoSuggestConfig =
|
|
2189
|
+
const autoSuggestConfig = useCallback8(() => {
|
|
1503
2190
|
if (!requirePro("Pivot Table - Auto Suggest"))
|
|
1504
2191
|
return;
|
|
1505
2192
|
if (availableFields.length === 0)
|
|
@@ -1511,7 +2198,7 @@ function usePivotTable(data) {
|
|
|
1511
2198
|
setValueFields([{ field: numericFields[0].field, aggregation: "sum" }]);
|
|
1512
2199
|
}
|
|
1513
2200
|
}, [availableFields, requirePro]);
|
|
1514
|
-
const addCalculatedField =
|
|
2201
|
+
const addCalculatedField = useCallback8((field) => {
|
|
1515
2202
|
setCalculatedFields((prev) => {
|
|
1516
2203
|
const existing = prev.findIndex((f) => f.id === field.id);
|
|
1517
2204
|
let updated;
|
|
@@ -1524,7 +2211,7 @@ function usePivotTable(data) {
|
|
|
1524
2211
|
return updated;
|
|
1525
2212
|
});
|
|
1526
2213
|
}, []);
|
|
1527
|
-
const removeCalculatedField =
|
|
2214
|
+
const removeCalculatedField = useCallback8((id) => {
|
|
1528
2215
|
setCalculatedFields((prev) => {
|
|
1529
2216
|
const updated = prev.filter((f) => f.id !== id);
|
|
1530
2217
|
saveCalculatedFields(updated);
|
|
@@ -1566,8 +2253,8 @@ function usePivotTable(data) {
|
|
|
1566
2253
|
|
|
1567
2254
|
// src/components/PivotConfig.tsx
|
|
1568
2255
|
import { AGGREGATION_OPTIONS, getAggregationSymbol } from "@smallwebco/tinypivot-core";
|
|
1569
|
-
import { useCallback as
|
|
1570
|
-
import { Fragment as
|
|
2256
|
+
import { useCallback as useCallback9, useMemo as useMemo9, useState as useState9 } from "react";
|
|
2257
|
+
import { Fragment as Fragment3, jsx as jsx5, jsxs as jsxs5 } from "react/jsx-runtime";
|
|
1571
2258
|
function aggregationRequiresPro(agg) {
|
|
1572
2259
|
return agg !== "sum";
|
|
1573
2260
|
}
|
|
@@ -1608,15 +2295,15 @@ function PivotConfig({
|
|
|
1608
2295
|
onRemoveCalculatedField,
|
|
1609
2296
|
onUpdateCalculatedField
|
|
1610
2297
|
}) {
|
|
1611
|
-
const [fieldSearch, setFieldSearch] =
|
|
1612
|
-
const [showCalcModal, setShowCalcModal] =
|
|
1613
|
-
const [editingCalcField, setEditingCalcField] =
|
|
2298
|
+
const [fieldSearch, setFieldSearch] = useState9("");
|
|
2299
|
+
const [showCalcModal, setShowCalcModal] = useState9(false);
|
|
2300
|
+
const [editingCalcField, setEditingCalcField] = useState9(null);
|
|
1614
2301
|
const { canUseAdvancedAggregations } = useLicense();
|
|
1615
|
-
const isAggregationAvailable =
|
|
2302
|
+
const isAggregationAvailable = useCallback9((agg) => {
|
|
1616
2303
|
return !aggregationRequiresPro(agg) || canUseAdvancedAggregations;
|
|
1617
2304
|
}, [canUseAdvancedAggregations]);
|
|
1618
|
-
const numericFieldNames =
|
|
1619
|
-
const calculatedFieldsAsStats =
|
|
2305
|
+
const numericFieldNames = useMemo9(() => availableFields.filter((f) => f.isNumeric).map((f) => f.field), [availableFields]);
|
|
2306
|
+
const calculatedFieldsAsStats = useMemo9(() => {
|
|
1620
2307
|
if (!calculatedFields)
|
|
1621
2308
|
return [];
|
|
1622
2309
|
return calculatedFields.map((calc) => ({
|
|
@@ -1630,11 +2317,11 @@ function PivotConfig({
|
|
|
1630
2317
|
calcFormula: calc.formula
|
|
1631
2318
|
}));
|
|
1632
2319
|
}, [calculatedFields]);
|
|
1633
|
-
const allAvailableFields =
|
|
2320
|
+
const allAvailableFields = useMemo9(() => [
|
|
1634
2321
|
...availableFields.map((f) => ({ ...f, isCalculated: false })),
|
|
1635
2322
|
...calculatedFieldsAsStats
|
|
1636
2323
|
], [availableFields, calculatedFieldsAsStats]);
|
|
1637
|
-
const assignedFields =
|
|
2324
|
+
const assignedFields = useMemo9(() => {
|
|
1638
2325
|
const rowSet = new Set(rowFields);
|
|
1639
2326
|
const colSet = new Set(columnFields);
|
|
1640
2327
|
const valueMap = new Map(valueFields.map((v) => [v.field, v]));
|
|
@@ -1644,7 +2331,7 @@ function PivotConfig({
|
|
|
1644
2331
|
valueConfig: valueMap.get(f.field)
|
|
1645
2332
|
}));
|
|
1646
2333
|
}, [allAvailableFields, rowFields, columnFields, valueFields]);
|
|
1647
|
-
const unassignedFields =
|
|
2334
|
+
const unassignedFields = useMemo9(() => {
|
|
1648
2335
|
const rowSet = new Set(rowFields);
|
|
1649
2336
|
const colSet = new Set(columnFields);
|
|
1650
2337
|
const valSet = new Set(valueFields.map((v) => v.field));
|
|
@@ -1652,7 +2339,7 @@ function PivotConfig({
|
|
|
1652
2339
|
(f) => !rowSet.has(f.field) && !colSet.has(f.field) && !valSet.has(f.field)
|
|
1653
2340
|
);
|
|
1654
2341
|
}, [allAvailableFields, rowFields, columnFields, valueFields]);
|
|
1655
|
-
const filteredUnassignedFields =
|
|
2342
|
+
const filteredUnassignedFields = useMemo9(() => {
|
|
1656
2343
|
if (!fieldSearch.trim())
|
|
1657
2344
|
return unassignedFields;
|
|
1658
2345
|
const search = fieldSearch.toLowerCase().trim();
|
|
@@ -1663,13 +2350,13 @@ function PivotConfig({
|
|
|
1663
2350
|
});
|
|
1664
2351
|
}, [unassignedFields, fieldSearch]);
|
|
1665
2352
|
const assignedCount = assignedFields.length;
|
|
1666
|
-
const getFieldDisplayName =
|
|
2353
|
+
const getFieldDisplayName = useCallback9((field) => {
|
|
1667
2354
|
if (field.isCalculated && field.calcName) {
|
|
1668
2355
|
return field.calcName;
|
|
1669
2356
|
}
|
|
1670
2357
|
return field.field;
|
|
1671
2358
|
}, []);
|
|
1672
|
-
const handleDragStart =
|
|
2359
|
+
const handleDragStart = useCallback9(
|
|
1673
2360
|
(field, event) => {
|
|
1674
2361
|
event.dataTransfer?.setData("text/plain", field);
|
|
1675
2362
|
event.dataTransfer.effectAllowed = "move";
|
|
@@ -1677,7 +2364,7 @@ function PivotConfig({
|
|
|
1677
2364
|
},
|
|
1678
2365
|
[onDragStart]
|
|
1679
2366
|
);
|
|
1680
|
-
const handleAggregationChange =
|
|
2367
|
+
const handleAggregationChange = useCallback9(
|
|
1681
2368
|
(field, currentAgg, newAgg) => {
|
|
1682
2369
|
if (!isAggregationAvailable(newAgg)) {
|
|
1683
2370
|
console.warn(`[TinyPivot] "${newAgg}" aggregation requires a Pro license. Visit https://tiny-pivot.com/#pricing to upgrade.`);
|
|
@@ -1687,7 +2374,7 @@ function PivotConfig({
|
|
|
1687
2374
|
},
|
|
1688
2375
|
[onUpdateAggregation, isAggregationAvailable]
|
|
1689
2376
|
);
|
|
1690
|
-
const toggleRowColumn =
|
|
2377
|
+
const toggleRowColumn = useCallback9(
|
|
1691
2378
|
(field, currentAssignment) => {
|
|
1692
2379
|
if (currentAssignment === "row") {
|
|
1693
2380
|
onRemoveRowField(field);
|
|
@@ -1699,7 +2386,7 @@ function PivotConfig({
|
|
|
1699
2386
|
},
|
|
1700
2387
|
[onRemoveRowField, onAddColumnField, onRemoveColumnField, onAddRowField]
|
|
1701
2388
|
);
|
|
1702
|
-
const removeField =
|
|
2389
|
+
const removeField = useCallback9(
|
|
1703
2390
|
(field, assignedTo, valueConfig) => {
|
|
1704
2391
|
if (assignedTo === "row") {
|
|
1705
2392
|
onRemoveRowField(field);
|
|
@@ -1711,15 +2398,15 @@ function PivotConfig({
|
|
|
1711
2398
|
},
|
|
1712
2399
|
[onRemoveRowField, onRemoveColumnField, onRemoveValueField]
|
|
1713
2400
|
);
|
|
1714
|
-
const handleTotalsToggle =
|
|
2401
|
+
const handleTotalsToggle = useCallback9((checked) => {
|
|
1715
2402
|
onShowRowTotalsChange(checked);
|
|
1716
2403
|
onShowColumnTotalsChange(checked);
|
|
1717
2404
|
}, [onShowRowTotalsChange, onShowColumnTotalsChange]);
|
|
1718
|
-
const openCalcModal =
|
|
2405
|
+
const openCalcModal = useCallback9((field) => {
|
|
1719
2406
|
setEditingCalcField(field || null);
|
|
1720
2407
|
setShowCalcModal(true);
|
|
1721
2408
|
}, []);
|
|
1722
|
-
const handleSaveCalcField =
|
|
2409
|
+
const handleSaveCalcField = useCallback9((field) => {
|
|
1723
2410
|
if (editingCalcField && onUpdateCalculatedField) {
|
|
1724
2411
|
onUpdateCalculatedField(field);
|
|
1725
2412
|
} else if (onAddCalculatedField) {
|
|
@@ -1728,14 +2415,14 @@ function PivotConfig({
|
|
|
1728
2415
|
setShowCalcModal(false);
|
|
1729
2416
|
setEditingCalcField(null);
|
|
1730
2417
|
}, [editingCalcField, onAddCalculatedField, onUpdateCalculatedField]);
|
|
1731
|
-
const handleCloseCalcModal =
|
|
2418
|
+
const handleCloseCalcModal = useCallback9(() => {
|
|
1732
2419
|
setShowCalcModal(false);
|
|
1733
2420
|
setEditingCalcField(null);
|
|
1734
2421
|
}, []);
|
|
1735
|
-
return /* @__PURE__ */
|
|
1736
|
-
/* @__PURE__ */
|
|
1737
|
-
/* @__PURE__ */
|
|
1738
|
-
/* @__PURE__ */
|
|
2422
|
+
return /* @__PURE__ */ jsxs5("div", { className: "vpg-pivot-config", children: [
|
|
2423
|
+
/* @__PURE__ */ jsxs5("div", { className: "vpg-config-header", children: [
|
|
2424
|
+
/* @__PURE__ */ jsxs5("h3", { className: "vpg-config-title", children: [
|
|
2425
|
+
/* @__PURE__ */ jsx5("svg", { className: "vpg-icon", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: /* @__PURE__ */ jsx5(
|
|
1739
2426
|
"path",
|
|
1740
2427
|
{
|
|
1741
2428
|
strokeLinecap: "round",
|
|
@@ -1746,13 +2433,13 @@ function PivotConfig({
|
|
|
1746
2433
|
) }),
|
|
1747
2434
|
"Fields"
|
|
1748
2435
|
] }),
|
|
1749
|
-
/* @__PURE__ */
|
|
2436
|
+
/* @__PURE__ */ jsx5("div", { className: "vpg-header-actions", children: assignedCount > 0 && /* @__PURE__ */ jsx5(
|
|
1750
2437
|
"button",
|
|
1751
2438
|
{
|
|
1752
2439
|
className: "vpg-action-btn vpg-clear-btn",
|
|
1753
2440
|
title: "Clear all",
|
|
1754
2441
|
onClick: onClearConfig,
|
|
1755
|
-
children: /* @__PURE__ */
|
|
2442
|
+
children: /* @__PURE__ */ jsx5("svg", { className: "vpg-icon-sm", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: /* @__PURE__ */ jsx5(
|
|
1756
2443
|
"path",
|
|
1757
2444
|
{
|
|
1758
2445
|
strokeLinecap: "round",
|
|
@@ -1764,9 +2451,9 @@ function PivotConfig({
|
|
|
1764
2451
|
}
|
|
1765
2452
|
) })
|
|
1766
2453
|
] }),
|
|
1767
|
-
assignedCount > 0 && /* @__PURE__ */
|
|
1768
|
-
/* @__PURE__ */
|
|
1769
|
-
/* @__PURE__ */
|
|
2454
|
+
assignedCount > 0 && /* @__PURE__ */ jsxs5("div", { className: "vpg-assigned-section", children: [
|
|
2455
|
+
/* @__PURE__ */ jsx5("div", { className: "vpg-section-label", children: "Active" }),
|
|
2456
|
+
/* @__PURE__ */ jsx5("div", { className: "vpg-assigned-list", children: assignedFields.map((field) => /* @__PURE__ */ jsxs5(
|
|
1770
2457
|
"div",
|
|
1771
2458
|
{
|
|
1772
2459
|
className: `vpg-assigned-item vpg-type-${field.assignedTo}${field.isCalculated ? " vpg-type-calc" : ""}`,
|
|
@@ -1775,12 +2462,12 @@ function PivotConfig({
|
|
|
1775
2462
|
onDragStart: (e) => handleDragStart(field.field, e),
|
|
1776
2463
|
onDragEnd,
|
|
1777
2464
|
children: [
|
|
1778
|
-
/* @__PURE__ */
|
|
1779
|
-
/* @__PURE__ */
|
|
1780
|
-
/* @__PURE__ */
|
|
2465
|
+
/* @__PURE__ */ jsxs5("div", { className: "vpg-item-main", children: [
|
|
2466
|
+
/* @__PURE__ */ jsx5("span", { className: `vpg-item-badge ${field.assignedTo}${field.isCalculated ? " calc" : ""}`, children: field.isCalculated ? "\u0192" : field.assignedTo === "row" ? "R" : field.assignedTo === "column" ? "C" : getAggregationSymbol(field.valueConfig?.aggregation || "sum") }),
|
|
2467
|
+
/* @__PURE__ */ jsx5("span", { className: "vpg-item-name", children: getFieldDisplayName(field) })
|
|
1781
2468
|
] }),
|
|
1782
|
-
/* @__PURE__ */
|
|
1783
|
-
(field.assignedTo === "row" || field.assignedTo === "column") && /* @__PURE__ */
|
|
2469
|
+
/* @__PURE__ */ jsxs5("div", { className: "vpg-item-actions", children: [
|
|
2470
|
+
(field.assignedTo === "row" || field.assignedTo === "column") && /* @__PURE__ */ jsx5(
|
|
1784
2471
|
"button",
|
|
1785
2472
|
{
|
|
1786
2473
|
className: "vpg-toggle-btn",
|
|
@@ -1789,14 +2476,14 @@ function PivotConfig({
|
|
|
1789
2476
|
e.stopPropagation();
|
|
1790
2477
|
toggleRowColumn(field.field, field.assignedTo);
|
|
1791
2478
|
},
|
|
1792
|
-
children: /* @__PURE__ */
|
|
2479
|
+
children: /* @__PURE__ */ jsx5(
|
|
1793
2480
|
"svg",
|
|
1794
2481
|
{
|
|
1795
2482
|
className: "vpg-icon-xs",
|
|
1796
2483
|
fill: "none",
|
|
1797
2484
|
stroke: "currentColor",
|
|
1798
2485
|
viewBox: "0 0 24 24",
|
|
1799
|
-
children: /* @__PURE__ */
|
|
2486
|
+
children: /* @__PURE__ */ jsx5(
|
|
1800
2487
|
"path",
|
|
1801
2488
|
{
|
|
1802
2489
|
strokeLinecap: "round",
|
|
@@ -1809,7 +2496,7 @@ function PivotConfig({
|
|
|
1809
2496
|
)
|
|
1810
2497
|
}
|
|
1811
2498
|
),
|
|
1812
|
-
field.assignedTo === "value" && field.valueConfig && /* @__PURE__ */
|
|
2499
|
+
field.assignedTo === "value" && field.valueConfig && /* @__PURE__ */ jsx5(
|
|
1813
2500
|
"select",
|
|
1814
2501
|
{
|
|
1815
2502
|
className: "vpg-agg-select",
|
|
@@ -1823,7 +2510,7 @@ function PivotConfig({
|
|
|
1823
2510
|
);
|
|
1824
2511
|
},
|
|
1825
2512
|
onClick: (e) => e.stopPropagation(),
|
|
1826
|
-
children: AGGREGATION_OPTIONS.map((agg) => /* @__PURE__ */
|
|
2513
|
+
children: AGGREGATION_OPTIONS.map((agg) => /* @__PURE__ */ jsxs5(
|
|
1827
2514
|
"option",
|
|
1828
2515
|
{
|
|
1829
2516
|
value: agg.value,
|
|
@@ -1839,7 +2526,7 @@ function PivotConfig({
|
|
|
1839
2526
|
))
|
|
1840
2527
|
}
|
|
1841
2528
|
),
|
|
1842
|
-
/* @__PURE__ */
|
|
2529
|
+
/* @__PURE__ */ jsx5(
|
|
1843
2530
|
"button",
|
|
1844
2531
|
{
|
|
1845
2532
|
className: "vpg-remove-btn",
|
|
@@ -1857,14 +2544,14 @@ function PivotConfig({
|
|
|
1857
2544
|
field.field
|
|
1858
2545
|
)) })
|
|
1859
2546
|
] }),
|
|
1860
|
-
/* @__PURE__ */
|
|
1861
|
-
/* @__PURE__ */
|
|
2547
|
+
/* @__PURE__ */ jsxs5("div", { className: "vpg-unassigned-section", children: [
|
|
2548
|
+
/* @__PURE__ */ jsx5("div", { className: "vpg-section-header", children: /* @__PURE__ */ jsxs5("div", { className: "vpg-section-label", children: [
|
|
1862
2549
|
"Available",
|
|
1863
2550
|
" ",
|
|
1864
|
-
/* @__PURE__ */
|
|
2551
|
+
/* @__PURE__ */ jsx5("span", { className: "vpg-count", children: unassignedFields.length })
|
|
1865
2552
|
] }) }),
|
|
1866
|
-
/* @__PURE__ */
|
|
1867
|
-
/* @__PURE__ */
|
|
2553
|
+
/* @__PURE__ */ jsxs5("div", { className: "vpg-field-search", children: [
|
|
2554
|
+
/* @__PURE__ */ jsx5("svg", { className: "vpg-search-icon", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: /* @__PURE__ */ jsx5(
|
|
1868
2555
|
"path",
|
|
1869
2556
|
{
|
|
1870
2557
|
strokeLinecap: "round",
|
|
@@ -1873,7 +2560,7 @@ function PivotConfig({
|
|
|
1873
2560
|
d: "M21 21l-6-6m2-5a7 7 0 11-14 0 7 7 0 0114 0z"
|
|
1874
2561
|
}
|
|
1875
2562
|
) }),
|
|
1876
|
-
/* @__PURE__ */
|
|
2563
|
+
/* @__PURE__ */ jsx5(
|
|
1877
2564
|
"input",
|
|
1878
2565
|
{
|
|
1879
2566
|
type: "text",
|
|
@@ -1883,7 +2570,7 @@ function PivotConfig({
|
|
|
1883
2570
|
className: "vpg-search-input"
|
|
1884
2571
|
}
|
|
1885
2572
|
),
|
|
1886
|
-
fieldSearch && /* @__PURE__ */
|
|
2573
|
+
fieldSearch && /* @__PURE__ */ jsx5("button", { className: "vpg-clear-search", onClick: () => setFieldSearch(""), children: /* @__PURE__ */ jsx5("svg", { className: "vpg-icon-xs", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: /* @__PURE__ */ jsx5(
|
|
1887
2574
|
"path",
|
|
1888
2575
|
{
|
|
1889
2576
|
strokeLinecap: "round",
|
|
@@ -1893,8 +2580,8 @@ function PivotConfig({
|
|
|
1893
2580
|
}
|
|
1894
2581
|
) }) })
|
|
1895
2582
|
] }),
|
|
1896
|
-
/* @__PURE__ */
|
|
1897
|
-
filteredUnassignedFields.map((field) => /* @__PURE__ */
|
|
2583
|
+
/* @__PURE__ */ jsxs5("div", { className: "vpg-field-list", children: [
|
|
2584
|
+
filteredUnassignedFields.map((field) => /* @__PURE__ */ jsxs5(
|
|
1898
2585
|
"div",
|
|
1899
2586
|
{
|
|
1900
2587
|
className: `vpg-field-item${field.isNumeric && !field.isCalculated ? " vpg-is-numeric" : ""}${field.isCalculated ? " vpg-is-calculated" : ""}`,
|
|
@@ -1903,10 +2590,10 @@ function PivotConfig({
|
|
|
1903
2590
|
onDragStart: (e) => handleDragStart(field.field, e),
|
|
1904
2591
|
onDragEnd,
|
|
1905
2592
|
children: [
|
|
1906
|
-
/* @__PURE__ */
|
|
1907
|
-
/* @__PURE__ */
|
|
1908
|
-
field.isCalculated ? /* @__PURE__ */
|
|
1909
|
-
/* @__PURE__ */
|
|
2593
|
+
/* @__PURE__ */ jsx5("span", { className: `vpg-field-type-icon${field.isCalculated ? " vpg-calc-type" : ""}`, title: field.type, children: getFieldIcon(field.type, field.isCalculated) }),
|
|
2594
|
+
/* @__PURE__ */ jsx5("span", { className: "vpg-field-name", children: getFieldDisplayName(field) }),
|
|
2595
|
+
field.isCalculated ? /* @__PURE__ */ jsxs5(Fragment3, { children: [
|
|
2596
|
+
/* @__PURE__ */ jsx5(
|
|
1910
2597
|
"button",
|
|
1911
2598
|
{
|
|
1912
2599
|
className: "vpg-field-edit",
|
|
@@ -1920,7 +2607,7 @@ function PivotConfig({
|
|
|
1920
2607
|
children: "\u270E"
|
|
1921
2608
|
}
|
|
1922
2609
|
),
|
|
1923
|
-
/* @__PURE__ */
|
|
2610
|
+
/* @__PURE__ */ jsx5(
|
|
1924
2611
|
"button",
|
|
1925
2612
|
{
|
|
1926
2613
|
className: "vpg-field-delete",
|
|
@@ -1934,22 +2621,22 @@ function PivotConfig({
|
|
|
1934
2621
|
children: "\xD7"
|
|
1935
2622
|
}
|
|
1936
2623
|
)
|
|
1937
|
-
] }) : /* @__PURE__ */
|
|
2624
|
+
] }) : /* @__PURE__ */ jsx5("span", { className: "vpg-unique-count", children: field.uniqueCount })
|
|
1938
2625
|
]
|
|
1939
2626
|
},
|
|
1940
2627
|
field.field
|
|
1941
2628
|
)),
|
|
1942
|
-
filteredUnassignedFields.length === 0 && fieldSearch && /* @__PURE__ */
|
|
2629
|
+
filteredUnassignedFields.length === 0 && fieldSearch && /* @__PURE__ */ jsxs5("div", { className: "vpg-empty-hint", children: [
|
|
1943
2630
|
'No fields match "',
|
|
1944
2631
|
fieldSearch,
|
|
1945
2632
|
'"'
|
|
1946
2633
|
] }),
|
|
1947
|
-
unassignedFields.length === 0 && /* @__PURE__ */
|
|
2634
|
+
unassignedFields.length === 0 && /* @__PURE__ */ jsx5("div", { className: "vpg-empty-hint", children: "All fields assigned" })
|
|
1948
2635
|
] })
|
|
1949
2636
|
] }),
|
|
1950
|
-
/* @__PURE__ */
|
|
1951
|
-
/* @__PURE__ */
|
|
1952
|
-
/* @__PURE__ */
|
|
2637
|
+
/* @__PURE__ */ jsxs5("div", { className: "vpg-options-section", children: [
|
|
2638
|
+
/* @__PURE__ */ jsxs5("label", { className: "vpg-option-toggle", children: [
|
|
2639
|
+
/* @__PURE__ */ jsx5(
|
|
1953
2640
|
"input",
|
|
1954
2641
|
{
|
|
1955
2642
|
type: "checkbox",
|
|
@@ -1957,14 +2644,14 @@ function PivotConfig({
|
|
|
1957
2644
|
onChange: (e) => handleTotalsToggle(e.target.checked)
|
|
1958
2645
|
}
|
|
1959
2646
|
),
|
|
1960
|
-
/* @__PURE__ */
|
|
2647
|
+
/* @__PURE__ */ jsx5("span", { children: "Totals" })
|
|
1961
2648
|
] }),
|
|
1962
|
-
/* @__PURE__ */
|
|
1963
|
-
/* @__PURE__ */
|
|
1964
|
-
/* @__PURE__ */
|
|
2649
|
+
/* @__PURE__ */ jsxs5("button", { className: "vpg-calc-btn", onClick: () => openCalcModal(), title: "Add calculated field (e.g. Profit Margin %)", children: [
|
|
2650
|
+
/* @__PURE__ */ jsx5("span", { className: "vpg-calc-icon", children: "\u0192" }),
|
|
2651
|
+
/* @__PURE__ */ jsx5("span", { children: "+ Calc" })
|
|
1965
2652
|
] })
|
|
1966
2653
|
] }),
|
|
1967
|
-
/* @__PURE__ */
|
|
2654
|
+
/* @__PURE__ */ jsx5(
|
|
1968
2655
|
CalculatedFieldModal,
|
|
1969
2656
|
{
|
|
1970
2657
|
show: showCalcModal,
|
|
@@ -1979,8 +2666,8 @@ function PivotConfig({
|
|
|
1979
2666
|
|
|
1980
2667
|
// src/components/PivotSkeleton.tsx
|
|
1981
2668
|
import { getAggregationLabel as getAggregationLabel2, getAggregationSymbol as getAggregationSymbol2 } from "@smallwebco/tinypivot-core";
|
|
1982
|
-
import { useCallback as
|
|
1983
|
-
import { Fragment as
|
|
2669
|
+
import { useCallback as useCallback10, useEffect as useEffect7, useMemo as useMemo10, useState as useState10 } from "react";
|
|
2670
|
+
import { Fragment as Fragment4, jsx as jsx6, jsxs as jsxs6 } from "react/jsx-runtime";
|
|
1984
2671
|
function PivotSkeleton({
|
|
1985
2672
|
rowFields,
|
|
1986
2673
|
columnFields,
|
|
@@ -2003,7 +2690,7 @@ function PivotSkeleton({
|
|
|
2003
2690
|
onReorderColumnFields
|
|
2004
2691
|
}) {
|
|
2005
2692
|
const { showWatermark, canUsePivot, isDemo } = useLicense();
|
|
2006
|
-
const getValueFieldDisplayName =
|
|
2693
|
+
const getValueFieldDisplayName = useCallback10((field) => {
|
|
2007
2694
|
if (field.startsWith("calc:")) {
|
|
2008
2695
|
const calcId = field.replace("calc:", "");
|
|
2009
2696
|
const calcField = calculatedFields?.find((c) => c.id === calcId);
|
|
@@ -2011,15 +2698,15 @@ function PivotSkeleton({
|
|
|
2011
2698
|
}
|
|
2012
2699
|
return field;
|
|
2013
2700
|
}, [calculatedFields]);
|
|
2014
|
-
const isCalculatedField =
|
|
2701
|
+
const isCalculatedField = useCallback10((field) => {
|
|
2015
2702
|
return field.startsWith("calc:");
|
|
2016
2703
|
}, []);
|
|
2017
|
-
const [dragOverArea, setDragOverArea] =
|
|
2018
|
-
const [reorderDragSource, setReorderDragSource] =
|
|
2019
|
-
const [reorderDropTarget, setReorderDropTarget] =
|
|
2020
|
-
const [sortDirection, setSortDirection] =
|
|
2021
|
-
const [sortTarget, setSortTarget] =
|
|
2022
|
-
const toggleSort =
|
|
2704
|
+
const [dragOverArea, setDragOverArea] = useState10(null);
|
|
2705
|
+
const [reorderDragSource, setReorderDragSource] = useState10(null);
|
|
2706
|
+
const [reorderDropTarget, setReorderDropTarget] = useState10(null);
|
|
2707
|
+
const [sortDirection, setSortDirection] = useState10("asc");
|
|
2708
|
+
const [sortTarget, setSortTarget] = useState10("row");
|
|
2709
|
+
const toggleSort = useCallback10((target = "row") => {
|
|
2023
2710
|
if (sortTarget === target) {
|
|
2024
2711
|
setSortDirection((prev) => prev === "asc" ? "desc" : "asc");
|
|
2025
2712
|
} else {
|
|
@@ -2027,13 +2714,13 @@ function PivotSkeleton({
|
|
|
2027
2714
|
setSortDirection("asc");
|
|
2028
2715
|
}
|
|
2029
2716
|
}, [sortTarget]);
|
|
2030
|
-
const [selectedCell, setSelectedCell] =
|
|
2031
|
-
const [selectionStart, setSelectionStart] =
|
|
2032
|
-
const [selectionEnd, setSelectionEnd] =
|
|
2033
|
-
const [isSelecting, setIsSelecting] =
|
|
2034
|
-
const [showCopyToast, setShowCopyToast] =
|
|
2035
|
-
const [copyToastMessage, setCopyToastMessage] =
|
|
2036
|
-
const selectionBounds =
|
|
2717
|
+
const [selectedCell, setSelectedCell] = useState10(null);
|
|
2718
|
+
const [selectionStart, setSelectionStart] = useState10(null);
|
|
2719
|
+
const [selectionEnd, setSelectionEnd] = useState10(null);
|
|
2720
|
+
const [isSelecting, setIsSelecting] = useState10(false);
|
|
2721
|
+
const [showCopyToast, setShowCopyToast] = useState10(false);
|
|
2722
|
+
const [copyToastMessage, setCopyToastMessage] = useState10("");
|
|
2723
|
+
const selectionBounds = useMemo10(() => {
|
|
2037
2724
|
if (!selectionStart || !selectionEnd)
|
|
2038
2725
|
return null;
|
|
2039
2726
|
return {
|
|
@@ -2043,7 +2730,7 @@ function PivotSkeleton({
|
|
|
2043
2730
|
maxCol: Math.max(selectionStart.col, selectionEnd.col)
|
|
2044
2731
|
};
|
|
2045
2732
|
}, [selectionStart, selectionEnd]);
|
|
2046
|
-
const handleCellMouseDown =
|
|
2733
|
+
const handleCellMouseDown = useCallback10(
|
|
2047
2734
|
(rowIndex, colIndex, event) => {
|
|
2048
2735
|
event.preventDefault();
|
|
2049
2736
|
if (event.shiftKey && selectedCell) {
|
|
@@ -2057,7 +2744,7 @@ function PivotSkeleton({
|
|
|
2057
2744
|
},
|
|
2058
2745
|
[selectedCell]
|
|
2059
2746
|
);
|
|
2060
|
-
const handleCellMouseEnter =
|
|
2747
|
+
const handleCellMouseEnter = useCallback10(
|
|
2061
2748
|
(rowIndex, colIndex) => {
|
|
2062
2749
|
if (isSelecting) {
|
|
2063
2750
|
setSelectionEnd({ row: rowIndex, col: colIndex });
|
|
@@ -2065,7 +2752,7 @@ function PivotSkeleton({
|
|
|
2065
2752
|
},
|
|
2066
2753
|
[isSelecting]
|
|
2067
2754
|
);
|
|
2068
|
-
const isCellSelected =
|
|
2755
|
+
const isCellSelected = useCallback10(
|
|
2069
2756
|
(rowIndex, colIndex) => {
|
|
2070
2757
|
if (!selectionBounds) {
|
|
2071
2758
|
return selectedCell?.row === rowIndex && selectedCell?.col === colIndex;
|
|
@@ -2075,12 +2762,12 @@ function PivotSkeleton({
|
|
|
2075
2762
|
},
|
|
2076
2763
|
[selectionBounds, selectedCell]
|
|
2077
2764
|
);
|
|
2078
|
-
|
|
2765
|
+
useEffect7(() => {
|
|
2079
2766
|
const handleMouseUp = () => setIsSelecting(false);
|
|
2080
2767
|
document.addEventListener("mouseup", handleMouseUp);
|
|
2081
2768
|
return () => document.removeEventListener("mouseup", handleMouseUp);
|
|
2082
2769
|
}, []);
|
|
2083
|
-
const sortedRowIndices =
|
|
2770
|
+
const sortedRowIndices = useMemo10(() => {
|
|
2084
2771
|
if (!pivotResult)
|
|
2085
2772
|
return [];
|
|
2086
2773
|
const indices = pivotResult.rowHeaders.map((_, i) => i);
|
|
@@ -2108,7 +2795,7 @@ function PivotSkeleton({
|
|
|
2108
2795
|
});
|
|
2109
2796
|
return indices;
|
|
2110
2797
|
}, [pivotResult, sortTarget, sortDirection]);
|
|
2111
|
-
const copySelectionToClipboard =
|
|
2798
|
+
const copySelectionToClipboard = useCallback10(() => {
|
|
2112
2799
|
if (!selectionBounds || !pivotResult)
|
|
2113
2800
|
return;
|
|
2114
2801
|
const { minRow, maxRow, minCol, maxCol } = selectionBounds;
|
|
@@ -2134,7 +2821,7 @@ function PivotSkeleton({
|
|
|
2134
2821
|
console.error("Copy failed:", err);
|
|
2135
2822
|
});
|
|
2136
2823
|
}, [selectionBounds, pivotResult, sortedRowIndices]);
|
|
2137
|
-
|
|
2824
|
+
useEffect7(() => {
|
|
2138
2825
|
const handleKeydown = (event) => {
|
|
2139
2826
|
if (!selectionBounds)
|
|
2140
2827
|
return;
|
|
@@ -2152,7 +2839,7 @@ function PivotSkeleton({
|
|
|
2152
2839
|
document.addEventListener("keydown", handleKeydown);
|
|
2153
2840
|
return () => document.removeEventListener("keydown", handleKeydown);
|
|
2154
2841
|
}, [selectionBounds, copySelectionToClipboard]);
|
|
2155
|
-
const selectionStats =
|
|
2842
|
+
const selectionStats = useMemo10(() => {
|
|
2156
2843
|
if (!selectionBounds || !pivotResult)
|
|
2157
2844
|
return null;
|
|
2158
2845
|
const { minRow, maxRow, minCol, maxCol } = selectionBounds;
|
|
@@ -2181,14 +2868,14 @@ function PivotSkeleton({
|
|
|
2181
2868
|
avg
|
|
2182
2869
|
};
|
|
2183
2870
|
}, [selectionBounds, pivotResult, sortedRowIndices]);
|
|
2184
|
-
const formatStatValue =
|
|
2871
|
+
const formatStatValue = useCallback10((val) => {
|
|
2185
2872
|
if (Math.abs(val) >= 1e6)
|
|
2186
2873
|
return `${(val / 1e6).toFixed(2)}M`;
|
|
2187
2874
|
if (Math.abs(val) >= 1e3)
|
|
2188
2875
|
return `${(val / 1e3).toFixed(2)}K`;
|
|
2189
2876
|
return val.toFixed(2);
|
|
2190
2877
|
}, []);
|
|
2191
|
-
const columnHeaderCells =
|
|
2878
|
+
const columnHeaderCells = useMemo10(() => {
|
|
2192
2879
|
if (!pivotResult || pivotResult.headers.length === 0) {
|
|
2193
2880
|
return [
|
|
2194
2881
|
valueFields.map((vf) => ({
|
|
@@ -2216,13 +2903,13 @@ function PivotSkeleton({
|
|
|
2216
2903
|
return result;
|
|
2217
2904
|
}, [pivotResult, valueFields]);
|
|
2218
2905
|
const hasActiveFilters = activeFilters && activeFilters.length > 0;
|
|
2219
|
-
const filterSummary =
|
|
2906
|
+
const filterSummary = useMemo10(() => {
|
|
2220
2907
|
if (!activeFilters || activeFilters.length === 0)
|
|
2221
2908
|
return "";
|
|
2222
2909
|
return activeFilters.map((f) => f.column).join(", ");
|
|
2223
2910
|
}, [activeFilters]);
|
|
2224
|
-
const [showFilterTooltip, setShowFilterTooltip] =
|
|
2225
|
-
const filterTooltipDetails =
|
|
2911
|
+
const [showFilterTooltip, setShowFilterTooltip] = useState10(false);
|
|
2912
|
+
const filterTooltipDetails = useMemo10(() => {
|
|
2226
2913
|
if (!activeFilters || activeFilters.length === 0)
|
|
2227
2914
|
return [];
|
|
2228
2915
|
return activeFilters.map((f) => {
|
|
@@ -2247,7 +2934,7 @@ function PivotSkeleton({
|
|
|
2247
2934
|
};
|
|
2248
2935
|
});
|
|
2249
2936
|
}, [activeFilters]);
|
|
2250
|
-
const handleDragOver =
|
|
2937
|
+
const handleDragOver = useCallback10(
|
|
2251
2938
|
(area, event) => {
|
|
2252
2939
|
event.preventDefault();
|
|
2253
2940
|
event.dataTransfer.dropEffect = "move";
|
|
@@ -2255,10 +2942,10 @@ function PivotSkeleton({
|
|
|
2255
2942
|
},
|
|
2256
2943
|
[]
|
|
2257
2944
|
);
|
|
2258
|
-
const handleDragLeave =
|
|
2945
|
+
const handleDragLeave = useCallback10(() => {
|
|
2259
2946
|
setDragOverArea(null);
|
|
2260
2947
|
}, []);
|
|
2261
|
-
const handleDrop =
|
|
2948
|
+
const handleDrop = useCallback10(
|
|
2262
2949
|
(area, event) => {
|
|
2263
2950
|
event.preventDefault();
|
|
2264
2951
|
const field = event.dataTransfer?.getData("text/plain");
|
|
@@ -2288,7 +2975,7 @@ function PivotSkeleton({
|
|
|
2288
2975
|
},
|
|
2289
2976
|
[rowFields, columnFields, valueFields, onAddRowField, onRemoveRowField, onAddColumnField, onRemoveColumnField, onAddValueField, onRemoveValueField]
|
|
2290
2977
|
);
|
|
2291
|
-
const handleChipDragStart =
|
|
2978
|
+
const handleChipDragStart = useCallback10(
|
|
2292
2979
|
(zone, index, event) => {
|
|
2293
2980
|
setReorderDragSource({ zone, index });
|
|
2294
2981
|
event.dataTransfer.effectAllowed = "move";
|
|
@@ -2299,11 +2986,11 @@ function PivotSkeleton({
|
|
|
2299
2986
|
},
|
|
2300
2987
|
[]
|
|
2301
2988
|
);
|
|
2302
|
-
const handleChipDragEnd =
|
|
2989
|
+
const handleChipDragEnd = useCallback10(() => {
|
|
2303
2990
|
setReorderDragSource(null);
|
|
2304
2991
|
setReorderDropTarget(null);
|
|
2305
2992
|
}, []);
|
|
2306
|
-
const handleChipDragOver =
|
|
2993
|
+
const handleChipDragOver = useCallback10(
|
|
2307
2994
|
(zone, index, event) => {
|
|
2308
2995
|
event.preventDefault();
|
|
2309
2996
|
if (reorderDragSource && reorderDragSource.zone === zone) {
|
|
@@ -2313,10 +3000,10 @@ function PivotSkeleton({
|
|
|
2313
3000
|
},
|
|
2314
3001
|
[reorderDragSource]
|
|
2315
3002
|
);
|
|
2316
|
-
const handleChipDragLeave =
|
|
3003
|
+
const handleChipDragLeave = useCallback10(() => {
|
|
2317
3004
|
setReorderDropTarget(null);
|
|
2318
3005
|
}, []);
|
|
2319
|
-
const handleChipDrop =
|
|
3006
|
+
const handleChipDrop = useCallback10(
|
|
2320
3007
|
(zone, targetIndex, event) => {
|
|
2321
3008
|
event.preventDefault();
|
|
2322
3009
|
event.stopPropagation();
|
|
@@ -2342,13 +3029,13 @@ function PivotSkeleton({
|
|
|
2342
3029
|
},
|
|
2343
3030
|
[reorderDragSource, rowFields, columnFields, onReorderRowFields, onReorderColumnFields]
|
|
2344
3031
|
);
|
|
2345
|
-
const isChipDragSource =
|
|
3032
|
+
const isChipDragSource = useCallback10(
|
|
2346
3033
|
(zone, index) => {
|
|
2347
3034
|
return reorderDragSource?.zone === zone && reorderDragSource?.index === index;
|
|
2348
3035
|
},
|
|
2349
3036
|
[reorderDragSource]
|
|
2350
3037
|
);
|
|
2351
|
-
const isChipDropTarget =
|
|
3038
|
+
const isChipDropTarget = useCallback10(
|
|
2352
3039
|
(zone, index) => {
|
|
2353
3040
|
return reorderDropTarget?.zone === zone && reorderDropTarget?.index === index;
|
|
2354
3041
|
},
|
|
@@ -2356,25 +3043,25 @@ function PivotSkeleton({
|
|
|
2356
3043
|
);
|
|
2357
3044
|
const currentFontSize = fontSize;
|
|
2358
3045
|
const rowHeaderWidth = 180;
|
|
2359
|
-
const rowHeaderColWidth =
|
|
3046
|
+
const rowHeaderColWidth = useMemo10(() => {
|
|
2360
3047
|
const numCols = Math.max(rowFields.length, 1);
|
|
2361
3048
|
return Math.max(rowHeaderWidth / numCols, 80);
|
|
2362
3049
|
}, [rowFields.length]);
|
|
2363
|
-
const getRowHeaderLeftOffset =
|
|
3050
|
+
const getRowHeaderLeftOffset = useCallback10((fieldIdx) => {
|
|
2364
3051
|
return fieldIdx * rowHeaderColWidth;
|
|
2365
3052
|
}, [rowHeaderColWidth]);
|
|
2366
|
-
return /* @__PURE__ */
|
|
3053
|
+
return /* @__PURE__ */ jsxs6(
|
|
2367
3054
|
"div",
|
|
2368
3055
|
{
|
|
2369
3056
|
className: `vpg-pivot-skeleton vpg-font-${currentFontSize} ${draggingField ? "vpg-is-dragging" : ""}`,
|
|
2370
3057
|
children: [
|
|
2371
|
-
showCopyToast && /* @__PURE__ */
|
|
2372
|
-
/* @__PURE__ */
|
|
3058
|
+
showCopyToast && /* @__PURE__ */ jsxs6("div", { className: "vpg-toast", children: [
|
|
3059
|
+
/* @__PURE__ */ jsx6("svg", { className: "vpg-icon", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: /* @__PURE__ */ jsx6("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "M5 13l4 4L19 7" }) }),
|
|
2373
3060
|
copyToastMessage
|
|
2374
3061
|
] }),
|
|
2375
|
-
/* @__PURE__ */
|
|
2376
|
-
/* @__PURE__ */
|
|
2377
|
-
/* @__PURE__ */
|
|
3062
|
+
/* @__PURE__ */ jsxs6("div", { className: "vpg-skeleton-header", children: [
|
|
3063
|
+
/* @__PURE__ */ jsxs6("div", { className: "vpg-skeleton-title", children: [
|
|
3064
|
+
/* @__PURE__ */ jsx6("svg", { className: "vpg-icon", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: /* @__PURE__ */ jsx6(
|
|
2378
3065
|
"path",
|
|
2379
3066
|
{
|
|
2380
3067
|
strokeLinecap: "round",
|
|
@@ -2383,24 +3070,24 @@ function PivotSkeleton({
|
|
|
2383
3070
|
d: "M4 5a1 1 0 011-1h14a1 1 0 011 1v2a1 1 0 01-1 1H5a1 1 0 01-1-1V5zM4 13a1 1 0 011-1h6a1 1 0 011 1v6a1 1 0 01-1 1H5a1 1 0 01-1-1v-6zM16 13a1 1 0 011-1h2a1 1 0 011 1v6a1 1 0 01-1 1h-2a1 1 0 01-1-1v-6z"
|
|
2384
3071
|
}
|
|
2385
3072
|
) }),
|
|
2386
|
-
/* @__PURE__ */
|
|
3073
|
+
/* @__PURE__ */ jsx6("span", { children: "Pivot Table" })
|
|
2387
3074
|
] }),
|
|
2388
|
-
/* @__PURE__ */
|
|
2389
|
-
hasActiveFilters && /* @__PURE__ */
|
|
3075
|
+
/* @__PURE__ */ jsxs6("div", { className: "vpg-header-right", children: [
|
|
3076
|
+
hasActiveFilters && /* @__PURE__ */ jsxs6(
|
|
2390
3077
|
"div",
|
|
2391
3078
|
{
|
|
2392
3079
|
className: "vpg-filter-indicator",
|
|
2393
3080
|
onMouseEnter: () => setShowFilterTooltip(true),
|
|
2394
3081
|
onMouseLeave: () => setShowFilterTooltip(false),
|
|
2395
3082
|
children: [
|
|
2396
|
-
/* @__PURE__ */
|
|
3083
|
+
/* @__PURE__ */ jsx6(
|
|
2397
3084
|
"svg",
|
|
2398
3085
|
{
|
|
2399
3086
|
className: "vpg-filter-icon",
|
|
2400
3087
|
fill: "none",
|
|
2401
3088
|
stroke: "currentColor",
|
|
2402
3089
|
viewBox: "0 0 24 24",
|
|
2403
|
-
children: /* @__PURE__ */
|
|
3090
|
+
children: /* @__PURE__ */ jsx6(
|
|
2404
3091
|
"path",
|
|
2405
3092
|
{
|
|
2406
3093
|
strokeLinecap: "round",
|
|
@@ -2411,11 +3098,11 @@ function PivotSkeleton({
|
|
|
2411
3098
|
)
|
|
2412
3099
|
}
|
|
2413
3100
|
),
|
|
2414
|
-
/* @__PURE__ */
|
|
3101
|
+
/* @__PURE__ */ jsxs6("span", { className: "vpg-filter-text", children: [
|
|
2415
3102
|
"Filtered:",
|
|
2416
3103
|
" ",
|
|
2417
|
-
/* @__PURE__ */
|
|
2418
|
-
filteredRowCount !== void 0 && totalRowCount !== void 0 && /* @__PURE__ */
|
|
3104
|
+
/* @__PURE__ */ jsx6("strong", { children: filterSummary }),
|
|
3105
|
+
filteredRowCount !== void 0 && totalRowCount !== void 0 && /* @__PURE__ */ jsxs6("span", { className: "vpg-filter-count", children: [
|
|
2419
3106
|
"(",
|
|
2420
3107
|
filteredRowCount.toLocaleString(),
|
|
2421
3108
|
" ",
|
|
@@ -2426,13 +3113,13 @@ function PivotSkeleton({
|
|
|
2426
3113
|
"rows)"
|
|
2427
3114
|
] })
|
|
2428
3115
|
] }),
|
|
2429
|
-
showFilterTooltip && /* @__PURE__ */
|
|
2430
|
-
/* @__PURE__ */
|
|
2431
|
-
filterTooltipDetails.map((filter) => /* @__PURE__ */
|
|
2432
|
-
/* @__PURE__ */
|
|
2433
|
-
/* @__PURE__ */
|
|
2434
|
-
filter.values.map((val, idx) => /* @__PURE__ */
|
|
2435
|
-
filter.remaining > 0 && /* @__PURE__ */
|
|
3116
|
+
showFilterTooltip && /* @__PURE__ */ jsxs6("div", { className: "vpg-filter-tooltip", children: [
|
|
3117
|
+
/* @__PURE__ */ jsx6("div", { className: "vpg-tooltip-header", children: "Active Filters" }),
|
|
3118
|
+
filterTooltipDetails.map((filter) => /* @__PURE__ */ jsxs6("div", { className: "vpg-tooltip-filter", children: [
|
|
3119
|
+
/* @__PURE__ */ jsx6("div", { className: "vpg-tooltip-column", children: filter.column }),
|
|
3120
|
+
/* @__PURE__ */ jsx6("div", { className: "vpg-tooltip-values", children: filter.isRange ? /* @__PURE__ */ jsx6("span", { className: "vpg-tooltip-value vpg-range-value", children: filter.displayText }) : /* @__PURE__ */ jsxs6(Fragment4, { children: [
|
|
3121
|
+
filter.values.map((val, idx) => /* @__PURE__ */ jsx6("span", { className: "vpg-tooltip-value", children: val }, idx)),
|
|
3122
|
+
filter.remaining > 0 && /* @__PURE__ */ jsxs6("span", { className: "vpg-tooltip-more", children: [
|
|
2436
3123
|
"+",
|
|
2437
3124
|
filter.remaining,
|
|
2438
3125
|
" ",
|
|
@@ -2440,7 +3127,7 @@ function PivotSkeleton({
|
|
|
2440
3127
|
] })
|
|
2441
3128
|
] }) })
|
|
2442
3129
|
] }, filter.column)),
|
|
2443
|
-
filteredRowCount !== void 0 && totalRowCount !== void 0 && /* @__PURE__ */
|
|
3130
|
+
filteredRowCount !== void 0 && totalRowCount !== void 0 && /* @__PURE__ */ jsxs6("div", { className: "vpg-tooltip-summary", children: [
|
|
2444
3131
|
"Showing",
|
|
2445
3132
|
" ",
|
|
2446
3133
|
filteredRowCount.toLocaleString(),
|
|
@@ -2455,20 +3142,20 @@ function PivotSkeleton({
|
|
|
2455
3142
|
]
|
|
2456
3143
|
}
|
|
2457
3144
|
),
|
|
2458
|
-
isConfigured && /* @__PURE__ */
|
|
2459
|
-
/* @__PURE__ */
|
|
3145
|
+
isConfigured && /* @__PURE__ */ jsxs6("div", { className: "vpg-config-summary", children: [
|
|
3146
|
+
/* @__PURE__ */ jsxs6("span", { className: "vpg-summary-badge vpg-rows", children: [
|
|
2460
3147
|
rowFields.length,
|
|
2461
3148
|
" ",
|
|
2462
3149
|
"row",
|
|
2463
3150
|
rowFields.length !== 1 ? "s" : ""
|
|
2464
3151
|
] }),
|
|
2465
|
-
/* @__PURE__ */
|
|
3152
|
+
/* @__PURE__ */ jsxs6("span", { className: "vpg-summary-badge vpg-cols", children: [
|
|
2466
3153
|
columnFields.length,
|
|
2467
3154
|
" ",
|
|
2468
3155
|
"col",
|
|
2469
3156
|
columnFields.length !== 1 ? "s" : ""
|
|
2470
3157
|
] }),
|
|
2471
|
-
/* @__PURE__ */
|
|
3158
|
+
/* @__PURE__ */ jsxs6("span", { className: "vpg-summary-badge vpg-vals", children: [
|
|
2472
3159
|
valueFields.length,
|
|
2473
3160
|
" ",
|
|
2474
3161
|
"val",
|
|
@@ -2477,8 +3164,8 @@ function PivotSkeleton({
|
|
|
2477
3164
|
] })
|
|
2478
3165
|
] })
|
|
2479
3166
|
] }),
|
|
2480
|
-
!canUsePivot ? /* @__PURE__ */
|
|
2481
|
-
/* @__PURE__ */
|
|
3167
|
+
!canUsePivot ? /* @__PURE__ */ jsx6("div", { className: "vpg-pro-required", children: /* @__PURE__ */ jsxs6("div", { className: "vpg-pro-content", children: [
|
|
3168
|
+
/* @__PURE__ */ jsx6("svg", { className: "vpg-pro-icon", fill: "none", viewBox: "0 0 24 24", stroke: "currentColor", children: /* @__PURE__ */ jsx6(
|
|
2482
3169
|
"path",
|
|
2483
3170
|
{
|
|
2484
3171
|
strokeLinecap: "round",
|
|
@@ -2487,12 +3174,12 @@ function PivotSkeleton({
|
|
|
2487
3174
|
d: "M12 15v2m-6 4h12a2 2 0 002-2v-6a2 2 0 00-2-2H6a2 2 0 00-2 2v6a2 2 0 002 2zm10-10V7a4 4 0 00-8 0v4h8z"
|
|
2488
3175
|
}
|
|
2489
3176
|
) }),
|
|
2490
|
-
/* @__PURE__ */
|
|
2491
|
-
/* @__PURE__ */
|
|
2492
|
-
/* @__PURE__ */
|
|
2493
|
-
] }) }) : /* @__PURE__ */
|
|
2494
|
-
/* @__PURE__ */
|
|
2495
|
-
/* @__PURE__ */
|
|
3177
|
+
/* @__PURE__ */ jsx6("h3", { children: "Pro Feature" }),
|
|
3178
|
+
/* @__PURE__ */ jsx6("p", { children: "Pivot Table functionality requires a Pro license." }),
|
|
3179
|
+
/* @__PURE__ */ jsx6("a", { href: "https://tiny-pivot.com/#pricing", target: "_blank", rel: "noopener noreferrer", className: "vpg-pro-link", children: "Get Pro License \u2192" })
|
|
3180
|
+
] }) }) : /* @__PURE__ */ jsxs6(Fragment4, { children: [
|
|
3181
|
+
/* @__PURE__ */ jsxs6("div", { className: "vpg-config-bar", children: [
|
|
3182
|
+
/* @__PURE__ */ jsxs6(
|
|
2496
3183
|
"div",
|
|
2497
3184
|
{
|
|
2498
3185
|
className: `vpg-drop-zone vpg-row-zone ${dragOverArea === "row" ? "vpg-drag-over" : ""}`,
|
|
@@ -2500,12 +3187,12 @@ function PivotSkeleton({
|
|
|
2500
3187
|
onDragLeave: handleDragLeave,
|
|
2501
3188
|
onDrop: (e) => handleDrop("row", e),
|
|
2502
3189
|
children: [
|
|
2503
|
-
/* @__PURE__ */
|
|
2504
|
-
/* @__PURE__ */
|
|
2505
|
-
/* @__PURE__ */
|
|
3190
|
+
/* @__PURE__ */ jsxs6("div", { className: "vpg-zone-header", children: [
|
|
3191
|
+
/* @__PURE__ */ jsx6("span", { className: "vpg-zone-icon vpg-row-icon", children: "\u2193" }),
|
|
3192
|
+
/* @__PURE__ */ jsx6("span", { className: "vpg-zone-label", children: "Rows" })
|
|
2506
3193
|
] }),
|
|
2507
|
-
/* @__PURE__ */
|
|
2508
|
-
rowFields.map((field, idx) => /* @__PURE__ */
|
|
3194
|
+
/* @__PURE__ */ jsxs6("div", { className: "vpg-zone-chips", children: [
|
|
3195
|
+
rowFields.map((field, idx) => /* @__PURE__ */ jsxs6(
|
|
2509
3196
|
"div",
|
|
2510
3197
|
{
|
|
2511
3198
|
className: `vpg-mini-chip vpg-row-chip ${isChipDragSource("row", idx) ? "vpg-chip-dragging" : ""} ${isChipDropTarget("row", idx) ? "vpg-chip-drop-target" : ""}`,
|
|
@@ -2516,9 +3203,9 @@ function PivotSkeleton({
|
|
|
2516
3203
|
onDragLeave: handleChipDragLeave,
|
|
2517
3204
|
onDrop: (e) => handleChipDrop("row", idx, e),
|
|
2518
3205
|
children: [
|
|
2519
|
-
/* @__PURE__ */
|
|
2520
|
-
/* @__PURE__ */
|
|
2521
|
-
/* @__PURE__ */
|
|
3206
|
+
/* @__PURE__ */ jsx6("span", { className: "vpg-drag-handle", children: "\u22EE\u22EE" }),
|
|
3207
|
+
/* @__PURE__ */ jsx6("span", { className: "vpg-mini-name", children: field }),
|
|
3208
|
+
/* @__PURE__ */ jsx6(
|
|
2522
3209
|
"button",
|
|
2523
3210
|
{
|
|
2524
3211
|
className: "vpg-mini-remove",
|
|
@@ -2533,12 +3220,12 @@ function PivotSkeleton({
|
|
|
2533
3220
|
},
|
|
2534
3221
|
field
|
|
2535
3222
|
)),
|
|
2536
|
-
rowFields.length === 0 && /* @__PURE__ */
|
|
3223
|
+
rowFields.length === 0 && /* @__PURE__ */ jsx6("span", { className: "vpg-zone-hint", children: "Drop here" })
|
|
2537
3224
|
] })
|
|
2538
3225
|
]
|
|
2539
3226
|
}
|
|
2540
3227
|
),
|
|
2541
|
-
/* @__PURE__ */
|
|
3228
|
+
/* @__PURE__ */ jsxs6(
|
|
2542
3229
|
"div",
|
|
2543
3230
|
{
|
|
2544
3231
|
className: `vpg-drop-zone vpg-column-zone ${dragOverArea === "column" ? "vpg-drag-over" : ""}`,
|
|
@@ -2546,12 +3233,12 @@ function PivotSkeleton({
|
|
|
2546
3233
|
onDragLeave: handleDragLeave,
|
|
2547
3234
|
onDrop: (e) => handleDrop("column", e),
|
|
2548
3235
|
children: [
|
|
2549
|
-
/* @__PURE__ */
|
|
2550
|
-
/* @__PURE__ */
|
|
2551
|
-
/* @__PURE__ */
|
|
3236
|
+
/* @__PURE__ */ jsxs6("div", { className: "vpg-zone-header", children: [
|
|
3237
|
+
/* @__PURE__ */ jsx6("span", { className: "vpg-zone-icon vpg-column-icon", children: "\u2192" }),
|
|
3238
|
+
/* @__PURE__ */ jsx6("span", { className: "vpg-zone-label", children: "Columns" })
|
|
2552
3239
|
] }),
|
|
2553
|
-
/* @__PURE__ */
|
|
2554
|
-
columnFields.map((field, idx) => /* @__PURE__ */
|
|
3240
|
+
/* @__PURE__ */ jsxs6("div", { className: "vpg-zone-chips", children: [
|
|
3241
|
+
columnFields.map((field, idx) => /* @__PURE__ */ jsxs6(
|
|
2555
3242
|
"div",
|
|
2556
3243
|
{
|
|
2557
3244
|
className: `vpg-mini-chip vpg-column-chip ${isChipDragSource("column", idx) ? "vpg-chip-dragging" : ""} ${isChipDropTarget("column", idx) ? "vpg-chip-drop-target" : ""}`,
|
|
@@ -2562,9 +3249,9 @@ function PivotSkeleton({
|
|
|
2562
3249
|
onDragLeave: handleChipDragLeave,
|
|
2563
3250
|
onDrop: (e) => handleChipDrop("column", idx, e),
|
|
2564
3251
|
children: [
|
|
2565
|
-
/* @__PURE__ */
|
|
2566
|
-
/* @__PURE__ */
|
|
2567
|
-
/* @__PURE__ */
|
|
3252
|
+
/* @__PURE__ */ jsx6("span", { className: "vpg-drag-handle", children: "\u22EE\u22EE" }),
|
|
3253
|
+
/* @__PURE__ */ jsx6("span", { className: "vpg-mini-name", children: field }),
|
|
3254
|
+
/* @__PURE__ */ jsx6(
|
|
2568
3255
|
"button",
|
|
2569
3256
|
{
|
|
2570
3257
|
className: "vpg-mini-remove",
|
|
@@ -2579,12 +3266,12 @@ function PivotSkeleton({
|
|
|
2579
3266
|
},
|
|
2580
3267
|
field
|
|
2581
3268
|
)),
|
|
2582
|
-
columnFields.length === 0 && /* @__PURE__ */
|
|
3269
|
+
columnFields.length === 0 && /* @__PURE__ */ jsx6("span", { className: "vpg-zone-hint", children: "Drop here" })
|
|
2583
3270
|
] })
|
|
2584
3271
|
]
|
|
2585
3272
|
}
|
|
2586
3273
|
),
|
|
2587
|
-
/* @__PURE__ */
|
|
3274
|
+
/* @__PURE__ */ jsxs6(
|
|
2588
3275
|
"div",
|
|
2589
3276
|
{
|
|
2590
3277
|
className: `vpg-drop-zone vpg-value-zone ${dragOverArea === "value" ? "vpg-drag-over" : ""}`,
|
|
@@ -2592,19 +3279,19 @@ function PivotSkeleton({
|
|
|
2592
3279
|
onDragLeave: handleDragLeave,
|
|
2593
3280
|
onDrop: (e) => handleDrop("value", e),
|
|
2594
3281
|
children: [
|
|
2595
|
-
/* @__PURE__ */
|
|
2596
|
-
/* @__PURE__ */
|
|
2597
|
-
/* @__PURE__ */
|
|
3282
|
+
/* @__PURE__ */ jsxs6("div", { className: "vpg-zone-header", children: [
|
|
3283
|
+
/* @__PURE__ */ jsx6("span", { className: "vpg-zone-icon vpg-value-icon", children: "\u03A3" }),
|
|
3284
|
+
/* @__PURE__ */ jsx6("span", { className: "vpg-zone-label", children: "Values" })
|
|
2598
3285
|
] }),
|
|
2599
|
-
/* @__PURE__ */
|
|
2600
|
-
valueFields.map((vf) => /* @__PURE__ */
|
|
3286
|
+
/* @__PURE__ */ jsxs6("div", { className: "vpg-zone-chips", children: [
|
|
3287
|
+
valueFields.map((vf) => /* @__PURE__ */ jsxs6(
|
|
2601
3288
|
"div",
|
|
2602
3289
|
{
|
|
2603
3290
|
className: `vpg-mini-chip vpg-value-chip${isCalculatedField(vf.field) ? " vpg-calc-chip" : ""}`,
|
|
2604
3291
|
children: [
|
|
2605
|
-
/* @__PURE__ */
|
|
2606
|
-
/* @__PURE__ */
|
|
2607
|
-
/* @__PURE__ */
|
|
3292
|
+
/* @__PURE__ */ jsx6("span", { className: "vpg-agg-symbol", children: isCalculatedField(vf.field) ? "\u0192" : getAggregationSymbol2(vf.aggregation) }),
|
|
3293
|
+
/* @__PURE__ */ jsx6("span", { className: "vpg-mini-name", children: getValueFieldDisplayName(vf.field) }),
|
|
3294
|
+
/* @__PURE__ */ jsx6(
|
|
2608
3295
|
"button",
|
|
2609
3296
|
{
|
|
2610
3297
|
className: "vpg-mini-remove",
|
|
@@ -2616,21 +3303,21 @@ function PivotSkeleton({
|
|
|
2616
3303
|
},
|
|
2617
3304
|
`${vf.field}-${vf.aggregation}`
|
|
2618
3305
|
)),
|
|
2619
|
-
valueFields.length === 0 && /* @__PURE__ */
|
|
3306
|
+
valueFields.length === 0 && /* @__PURE__ */ jsx6("span", { className: "vpg-zone-hint", children: "Drop numeric" })
|
|
2620
3307
|
] })
|
|
2621
3308
|
]
|
|
2622
3309
|
}
|
|
2623
3310
|
)
|
|
2624
3311
|
] }),
|
|
2625
|
-
(!isConfigured || !pivotResult) && /* @__PURE__ */
|
|
2626
|
-
/* @__PURE__ */
|
|
3312
|
+
(!isConfigured || !pivotResult) && /* @__PURE__ */ jsx6("div", { className: "vpg-placeholder", children: /* @__PURE__ */ jsxs6("div", { className: "vpg-placeholder-content", children: [
|
|
3313
|
+
/* @__PURE__ */ jsx6(
|
|
2627
3314
|
"svg",
|
|
2628
3315
|
{
|
|
2629
3316
|
className: "vpg-placeholder-icon",
|
|
2630
3317
|
fill: "none",
|
|
2631
3318
|
viewBox: "0 0 24 24",
|
|
2632
3319
|
stroke: "currentColor",
|
|
2633
|
-
children: /* @__PURE__ */
|
|
3320
|
+
children: /* @__PURE__ */ jsx6(
|
|
2634
3321
|
"path",
|
|
2635
3322
|
{
|
|
2636
3323
|
strokeLinecap: "round",
|
|
@@ -2641,58 +3328,58 @@ function PivotSkeleton({
|
|
|
2641
3328
|
)
|
|
2642
3329
|
}
|
|
2643
3330
|
),
|
|
2644
|
-
/* @__PURE__ */
|
|
3331
|
+
/* @__PURE__ */ jsx6("span", { className: "vpg-placeholder-text", children: valueFields.length === 0 ? /* @__PURE__ */ jsxs6(Fragment4, { children: [
|
|
2645
3332
|
"Add a",
|
|
2646
3333
|
" ",
|
|
2647
|
-
/* @__PURE__ */
|
|
3334
|
+
/* @__PURE__ */ jsx6("strong", { children: "Values" }),
|
|
2648
3335
|
" ",
|
|
2649
3336
|
"field to see your pivot table"
|
|
2650
|
-
] }) : rowFields.length === 0 && columnFields.length === 0 ? /* @__PURE__ */
|
|
3337
|
+
] }) : rowFields.length === 0 && columnFields.length === 0 ? /* @__PURE__ */ jsxs6(Fragment4, { children: [
|
|
2651
3338
|
"Add",
|
|
2652
3339
|
" ",
|
|
2653
|
-
/* @__PURE__ */
|
|
3340
|
+
/* @__PURE__ */ jsx6("strong", { children: "Row" }),
|
|
2654
3341
|
" ",
|
|
2655
3342
|
"or",
|
|
2656
3343
|
" ",
|
|
2657
|
-
/* @__PURE__ */
|
|
3344
|
+
/* @__PURE__ */ jsx6("strong", { children: "Column" }),
|
|
2658
3345
|
" ",
|
|
2659
3346
|
"fields to group your data"
|
|
2660
3347
|
] }) : "Your pivot table will appear here" })
|
|
2661
3348
|
] }) }),
|
|
2662
|
-
isConfigured && pivotResult && /* @__PURE__ */
|
|
2663
|
-
/* @__PURE__ */
|
|
2664
|
-
levelIdx === 0 && (rowFields.length > 0 ? rowFields : ["Rows"]).map((field, fieldIdx) => /* @__PURE__ */
|
|
3349
|
+
isConfigured && pivotResult && /* @__PURE__ */ jsx6("div", { className: "vpg-table-container", children: /* @__PURE__ */ jsxs6("table", { className: "vpg-pivot-table", children: [
|
|
3350
|
+
/* @__PURE__ */ jsx6("thead", { children: columnHeaderCells.map((headerRow, levelIdx) => /* @__PURE__ */ jsxs6("tr", { className: "vpg-column-header-row", children: [
|
|
3351
|
+
levelIdx === 0 && (rowFields.length > 0 ? rowFields : ["Rows"]).map((field, fieldIdx) => /* @__PURE__ */ jsx6(
|
|
2665
3352
|
"th",
|
|
2666
3353
|
{
|
|
2667
3354
|
className: "vpg-row-header-label",
|
|
2668
3355
|
rowSpan: columnHeaderCells.length,
|
|
2669
3356
|
style: { width: `${rowHeaderColWidth}px`, minWidth: "80px", left: `${getRowHeaderLeftOffset(fieldIdx)}px` },
|
|
2670
3357
|
onClick: () => toggleSort("row"),
|
|
2671
|
-
children: /* @__PURE__ */
|
|
2672
|
-
/* @__PURE__ */
|
|
2673
|
-
(fieldIdx === rowFields.length - 1 || rowFields.length === 0) && /* @__PURE__ */
|
|
3358
|
+
children: /* @__PURE__ */ jsxs6("div", { className: "vpg-header-content", children: [
|
|
3359
|
+
/* @__PURE__ */ jsx6("span", { children: field }),
|
|
3360
|
+
(fieldIdx === rowFields.length - 1 || rowFields.length === 0) && /* @__PURE__ */ jsx6("span", { className: `vpg-sort-indicator ${sortTarget === "row" ? "active" : ""}`, children: sortTarget === "row" ? sortDirection === "asc" ? "\u2191" : "\u2193" : "\u21C5" })
|
|
2674
3361
|
] })
|
|
2675
3362
|
},
|
|
2676
3363
|
`row-header-${fieldIdx}`
|
|
2677
3364
|
)),
|
|
2678
|
-
headerRow.map((cell, idx) => /* @__PURE__ */
|
|
3365
|
+
headerRow.map((cell, idx) => /* @__PURE__ */ jsx6(
|
|
2679
3366
|
"th",
|
|
2680
3367
|
{
|
|
2681
3368
|
className: "vpg-column-header-cell",
|
|
2682
3369
|
colSpan: cell.colspan,
|
|
2683
3370
|
onClick: () => levelIdx === columnHeaderCells.length - 1 && toggleSort(idx),
|
|
2684
|
-
children: /* @__PURE__ */
|
|
2685
|
-
/* @__PURE__ */
|
|
2686
|
-
levelIdx === columnHeaderCells.length - 1 && /* @__PURE__ */
|
|
3371
|
+
children: /* @__PURE__ */ jsxs6("div", { className: "vpg-header-content", children: [
|
|
3372
|
+
/* @__PURE__ */ jsx6("span", { children: cell.label }),
|
|
3373
|
+
levelIdx === columnHeaderCells.length - 1 && /* @__PURE__ */ jsx6("span", { className: `vpg-sort-indicator ${sortTarget === idx ? "active" : ""}`, children: sortTarget === idx ? sortDirection === "asc" ? "\u2191" : "\u2193" : "\u21C5" })
|
|
2687
3374
|
] })
|
|
2688
3375
|
},
|
|
2689
3376
|
idx
|
|
2690
3377
|
)),
|
|
2691
|
-
pivotResult.rowTotals.length > 0 && levelIdx === 0 && /* @__PURE__ */
|
|
3378
|
+
pivotResult.rowTotals.length > 0 && levelIdx === 0 && /* @__PURE__ */ jsx6("th", { className: "vpg-total-header", rowSpan: columnHeaderCells.length, children: "Total" })
|
|
2692
3379
|
] }, `header-${levelIdx}`)) }),
|
|
2693
|
-
/* @__PURE__ */
|
|
2694
|
-
sortedRowIndices.map((sortedIdx) => /* @__PURE__ */
|
|
2695
|
-
pivotResult.rowHeaders[sortedIdx].map((val, idx) => /* @__PURE__ */
|
|
3380
|
+
/* @__PURE__ */ jsxs6("tbody", { children: [
|
|
3381
|
+
sortedRowIndices.map((sortedIdx) => /* @__PURE__ */ jsxs6("tr", { className: "vpg-data-row", children: [
|
|
3382
|
+
pivotResult.rowHeaders[sortedIdx].map((val, idx) => /* @__PURE__ */ jsx6(
|
|
2696
3383
|
"th",
|
|
2697
3384
|
{
|
|
2698
3385
|
className: "vpg-row-header-cell",
|
|
@@ -2703,7 +3390,7 @@ function PivotSkeleton({
|
|
|
2703
3390
|
)),
|
|
2704
3391
|
pivotResult.data[sortedIdx].map((cell, colIdx) => {
|
|
2705
3392
|
const displayRowIdx = sortedRowIndices.indexOf(sortedIdx);
|
|
2706
|
-
return /* @__PURE__ */
|
|
3393
|
+
return /* @__PURE__ */ jsx6(
|
|
2707
3394
|
"td",
|
|
2708
3395
|
{
|
|
2709
3396
|
className: `vpg-data-cell ${isCellSelected(displayRowIdx, colIdx) ? "selected" : ""} ${cell.value === null ? "vpg-is-null" : ""}`,
|
|
@@ -2714,10 +3401,10 @@ function PivotSkeleton({
|
|
|
2714
3401
|
colIdx
|
|
2715
3402
|
);
|
|
2716
3403
|
}),
|
|
2717
|
-
pivotResult.rowTotals[sortedIdx] && /* @__PURE__ */
|
|
3404
|
+
pivotResult.rowTotals[sortedIdx] && /* @__PURE__ */ jsx6("td", { className: "vpg-data-cell vpg-total-cell", children: pivotResult.rowTotals[sortedIdx].formattedValue })
|
|
2718
3405
|
] }, sortedIdx)),
|
|
2719
|
-
pivotResult.columnTotals.length > 0 && /* @__PURE__ */
|
|
2720
|
-
/* @__PURE__ */
|
|
3406
|
+
pivotResult.columnTotals.length > 0 && /* @__PURE__ */ jsxs6("tr", { className: "vpg-totals-row", children: [
|
|
3407
|
+
/* @__PURE__ */ jsx6(
|
|
2721
3408
|
"th",
|
|
2722
3409
|
{
|
|
2723
3410
|
className: "vpg-row-header-cell vpg-total-label",
|
|
@@ -2726,13 +3413,13 @@ function PivotSkeleton({
|
|
|
2726
3413
|
children: "Total"
|
|
2727
3414
|
}
|
|
2728
3415
|
),
|
|
2729
|
-
pivotResult.columnTotals.map((cell, colIdx) => /* @__PURE__ */
|
|
2730
|
-
pivotResult.rowTotals.length > 0 && /* @__PURE__ */
|
|
3416
|
+
pivotResult.columnTotals.map((cell, colIdx) => /* @__PURE__ */ jsx6("td", { className: "vpg-data-cell vpg-total-cell", children: cell.formattedValue }, colIdx)),
|
|
3417
|
+
pivotResult.rowTotals.length > 0 && /* @__PURE__ */ jsx6("td", { className: "vpg-data-cell vpg-grand-total-cell", children: pivotResult.grandTotal.formattedValue })
|
|
2731
3418
|
] })
|
|
2732
3419
|
] })
|
|
2733
3420
|
] }) }),
|
|
2734
|
-
isConfigured && pivotResult && /* @__PURE__ */
|
|
2735
|
-
/* @__PURE__ */
|
|
3421
|
+
isConfigured && pivotResult && /* @__PURE__ */ jsxs6("div", { className: "vpg-skeleton-footer", children: [
|
|
3422
|
+
/* @__PURE__ */ jsxs6("span", { className: "vpg-footer-info", children: [
|
|
2736
3423
|
pivotResult.rowHeaders.length,
|
|
2737
3424
|
" ",
|
|
2738
3425
|
"rows \xD7",
|
|
@@ -2740,30 +3427,30 @@ function PivotSkeleton({
|
|
|
2740
3427
|
" ",
|
|
2741
3428
|
"columns"
|
|
2742
3429
|
] }),
|
|
2743
|
-
selectionStats && selectionStats.count > 1 && /* @__PURE__ */
|
|
2744
|
-
/* @__PURE__ */
|
|
2745
|
-
/* @__PURE__ */
|
|
2746
|
-
/* @__PURE__ */
|
|
3430
|
+
selectionStats && selectionStats.count > 1 && /* @__PURE__ */ jsxs6("div", { className: "vpg-selection-stats", children: [
|
|
3431
|
+
/* @__PURE__ */ jsxs6("span", { className: "vpg-stat", children: [
|
|
3432
|
+
/* @__PURE__ */ jsx6("span", { className: "vpg-stat-label", children: "Count:" }),
|
|
3433
|
+
/* @__PURE__ */ jsx6("span", { className: "vpg-stat-value", children: selectionStats.count })
|
|
2747
3434
|
] }),
|
|
2748
|
-
selectionStats.numericCount > 0 && /* @__PURE__ */
|
|
2749
|
-
/* @__PURE__ */
|
|
2750
|
-
/* @__PURE__ */
|
|
2751
|
-
/* @__PURE__ */
|
|
2752
|
-
/* @__PURE__ */
|
|
3435
|
+
selectionStats.numericCount > 0 && /* @__PURE__ */ jsxs6(Fragment4, { children: [
|
|
3436
|
+
/* @__PURE__ */ jsx6("span", { className: "vpg-stat-divider", children: "|" }),
|
|
3437
|
+
/* @__PURE__ */ jsxs6("span", { className: "vpg-stat", children: [
|
|
3438
|
+
/* @__PURE__ */ jsx6("span", { className: "vpg-stat-label", children: "Sum:" }),
|
|
3439
|
+
/* @__PURE__ */ jsx6("span", { className: "vpg-stat-value", children: formatStatValue(selectionStats.sum) })
|
|
2753
3440
|
] }),
|
|
2754
|
-
/* @__PURE__ */
|
|
2755
|
-
/* @__PURE__ */
|
|
2756
|
-
/* @__PURE__ */
|
|
2757
|
-
/* @__PURE__ */
|
|
3441
|
+
/* @__PURE__ */ jsx6("span", { className: "vpg-stat-divider", children: "|" }),
|
|
3442
|
+
/* @__PURE__ */ jsxs6("span", { className: "vpg-stat", children: [
|
|
3443
|
+
/* @__PURE__ */ jsx6("span", { className: "vpg-stat-label", children: "Avg:" }),
|
|
3444
|
+
/* @__PURE__ */ jsx6("span", { className: "vpg-stat-value", children: formatStatValue(selectionStats.avg) })
|
|
2758
3445
|
] })
|
|
2759
3446
|
] })
|
|
2760
3447
|
] })
|
|
2761
3448
|
] })
|
|
2762
3449
|
] }),
|
|
2763
|
-
showWatermark && canUsePivot && /* @__PURE__ */
|
|
2764
|
-
/* @__PURE__ */
|
|
2765
|
-
/* @__PURE__ */
|
|
2766
|
-
/* @__PURE__ */
|
|
3450
|
+
showWatermark && canUsePivot && /* @__PURE__ */ jsx6("div", { className: `vpg-watermark ${isDemo ? "vpg-demo-mode" : ""}`, children: isDemo ? /* @__PURE__ */ jsxs6(Fragment4, { children: [
|
|
3451
|
+
/* @__PURE__ */ jsx6("span", { className: "vpg-demo-badge", children: "DEMO" }),
|
|
3452
|
+
/* @__PURE__ */ jsx6("span", { children: "Pro features unlocked for evaluation" }),
|
|
3453
|
+
/* @__PURE__ */ jsx6(
|
|
2767
3454
|
"a",
|
|
2768
3455
|
{
|
|
2769
3456
|
href: "https://tiny-pivot.com/#pricing",
|
|
@@ -2773,14 +3460,14 @@ function PivotSkeleton({
|
|
|
2773
3460
|
children: "Get Pro License \u2192"
|
|
2774
3461
|
}
|
|
2775
3462
|
)
|
|
2776
|
-
] }) : /* @__PURE__ */
|
|
3463
|
+
] }) : /* @__PURE__ */ jsx6("a", { href: "https://tiny-pivot.com", target: "_blank", rel: "noopener noreferrer", children: "Powered by TinyPivot" }) })
|
|
2777
3464
|
]
|
|
2778
3465
|
}
|
|
2779
3466
|
);
|
|
2780
3467
|
}
|
|
2781
3468
|
|
|
2782
3469
|
// src/components/DataGrid.tsx
|
|
2783
|
-
import { Fragment as
|
|
3470
|
+
import { Fragment as Fragment5, jsx as jsx7, jsxs as jsxs7 } from "react/jsx-runtime";
|
|
2784
3471
|
var MIN_COL_WIDTH = 120;
|
|
2785
3472
|
var MAX_COL_WIDTH = 350;
|
|
2786
3473
|
function DataGrid({
|
|
@@ -2805,36 +3492,40 @@ function DataGrid({
|
|
|
2805
3492
|
onExport,
|
|
2806
3493
|
onCopy
|
|
2807
3494
|
}) {
|
|
2808
|
-
const { showWatermark, canUsePivot, isDemo, isPro } = useLicense();
|
|
2809
|
-
const currentTheme =
|
|
3495
|
+
const { showWatermark, canUsePivot, canUseCharts, isDemo, isPro } = useLicense();
|
|
3496
|
+
const currentTheme = useMemo11(() => {
|
|
2810
3497
|
if (theme === "auto") {
|
|
2811
3498
|
return window.matchMedia?.("(prefers-color-scheme: dark)").matches ? "dark" : "light";
|
|
2812
3499
|
}
|
|
2813
3500
|
return theme;
|
|
2814
3501
|
}, [theme]);
|
|
2815
|
-
const [currentFontSize, setCurrentFontSize] =
|
|
2816
|
-
const [globalSearchTerm, setGlobalSearchTerm] =
|
|
2817
|
-
const [showSearchInput, setShowSearchInput] =
|
|
2818
|
-
const [currentPage, setCurrentPage] =
|
|
2819
|
-
const [columnWidths, setColumnWidths] =
|
|
2820
|
-
const [resizingColumnId, setResizingColumnId] =
|
|
2821
|
-
const [resizeStartX, setResizeStartX] =
|
|
2822
|
-
const [resizeStartWidth, setResizeStartWidth] =
|
|
2823
|
-
const [gridHeight, setGridHeight] =
|
|
2824
|
-
const [isResizingVertically, setIsResizingVertically] =
|
|
2825
|
-
const [verticalResizeStartY, setVerticalResizeStartY] =
|
|
2826
|
-
const [verticalResizeStartHeight, setVerticalResizeStartHeight] =
|
|
2827
|
-
const [showCopyToast, setShowCopyToast] =
|
|
2828
|
-
const [copyToastMessage, setCopyToastMessage] =
|
|
2829
|
-
const [viewMode, setViewMode] =
|
|
2830
|
-
const [
|
|
2831
|
-
const
|
|
2832
|
-
|
|
2833
|
-
|
|
2834
|
-
const [
|
|
2835
|
-
const [
|
|
2836
|
-
const [
|
|
2837
|
-
const [
|
|
3502
|
+
const [currentFontSize, setCurrentFontSize] = useState11(initialFontSize);
|
|
3503
|
+
const [globalSearchTerm, setGlobalSearchTerm] = useState11("");
|
|
3504
|
+
const [showSearchInput, setShowSearchInput] = useState11(false);
|
|
3505
|
+
const [currentPage, setCurrentPage] = useState11(1);
|
|
3506
|
+
const [columnWidths, setColumnWidths] = useState11({});
|
|
3507
|
+
const [resizingColumnId, setResizingColumnId] = useState11(null);
|
|
3508
|
+
const [resizeStartX, setResizeStartX] = useState11(0);
|
|
3509
|
+
const [resizeStartWidth, setResizeStartWidth] = useState11(0);
|
|
3510
|
+
const [gridHeight, setGridHeight] = useState11(initialHeight);
|
|
3511
|
+
const [isResizingVertically, setIsResizingVertically] = useState11(false);
|
|
3512
|
+
const [verticalResizeStartY, setVerticalResizeStartY] = useState11(0);
|
|
3513
|
+
const [verticalResizeStartHeight, setVerticalResizeStartHeight] = useState11(0);
|
|
3514
|
+
const [showCopyToast, setShowCopyToast] = useState11(false);
|
|
3515
|
+
const [copyToastMessage, setCopyToastMessage] = useState11("");
|
|
3516
|
+
const [viewMode, setViewMode] = useState11("grid");
|
|
3517
|
+
const [_chartConfig, setChartConfig] = useState11(null);
|
|
3518
|
+
const handleChartConfigChange = useCallback11((config) => {
|
|
3519
|
+
setChartConfig(config);
|
|
3520
|
+
}, []);
|
|
3521
|
+
const [showPivotConfig, setShowPivotConfig] = useState11(true);
|
|
3522
|
+
const [draggingField, setDraggingField] = useState11(null);
|
|
3523
|
+
const [activeFilterColumn, setActiveFilterColumn] = useState11(null);
|
|
3524
|
+
const [filterDropdownPosition, setFilterDropdownPosition] = useState11({ top: 0, left: 0, maxHeight: 400 });
|
|
3525
|
+
const [selectedCell, setSelectedCell] = useState11(null);
|
|
3526
|
+
const [selectionStart, setSelectionStart] = useState11(null);
|
|
3527
|
+
const [selectionEnd, setSelectionEnd] = useState11(null);
|
|
3528
|
+
const [isSelecting, setIsSelecting] = useState11(false);
|
|
2838
3529
|
const tableContainerRef = useRef2(null);
|
|
2839
3530
|
const tableBodyRef = useRef2(null);
|
|
2840
3531
|
const fontSizeOptions = [
|
|
@@ -2860,7 +3551,7 @@ function DataGrid({
|
|
|
2860
3551
|
setNumericRangeFilter,
|
|
2861
3552
|
getNumericRangeFilter
|
|
2862
3553
|
} = useExcelGrid({ data, enableSorting: true, enableFiltering: true });
|
|
2863
|
-
const filteredDataForPivot =
|
|
3554
|
+
const filteredDataForPivot = useMemo11(() => {
|
|
2864
3555
|
const filteredRows = table.getFilteredRowModel().rows;
|
|
2865
3556
|
return filteredRows.map((row) => row.original);
|
|
2866
3557
|
}, [table, columnFilters]);
|
|
@@ -2890,7 +3581,7 @@ function DataGrid({
|
|
|
2890
3581
|
addCalculatedField,
|
|
2891
3582
|
removeCalculatedField
|
|
2892
3583
|
} = usePivotTable(filteredDataForPivot);
|
|
2893
|
-
const activeFilterInfo =
|
|
3584
|
+
const activeFilterInfo = useMemo11(() => {
|
|
2894
3585
|
if (activeFilters.length === 0)
|
|
2895
3586
|
return null;
|
|
2896
3587
|
return activeFilters.map((f) => {
|
|
@@ -2915,8 +3606,8 @@ function DataGrid({
|
|
|
2915
3606
|
};
|
|
2916
3607
|
});
|
|
2917
3608
|
}, [activeFilters]);
|
|
2918
|
-
const rows =
|
|
2919
|
-
const searchFilteredData =
|
|
3609
|
+
const rows = useMemo11(() => table.getFilteredRowModel().rows, [table, columnFilters]);
|
|
3610
|
+
const searchFilteredData = useMemo11(() => {
|
|
2920
3611
|
if (!globalSearchTerm.trim() || !enableSearch) {
|
|
2921
3612
|
return rows;
|
|
2922
3613
|
}
|
|
@@ -2934,22 +3625,22 @@ function DataGrid({
|
|
|
2934
3625
|
});
|
|
2935
3626
|
}, [rows, globalSearchTerm, enableSearch, columnKeys]);
|
|
2936
3627
|
const totalSearchedRows = searchFilteredData.length;
|
|
2937
|
-
const totalPages =
|
|
3628
|
+
const totalPages = useMemo11(() => {
|
|
2938
3629
|
if (!enablePagination)
|
|
2939
3630
|
return 1;
|
|
2940
3631
|
return Math.max(1, Math.ceil(totalSearchedRows / pageSize));
|
|
2941
3632
|
}, [enablePagination, totalSearchedRows, pageSize]);
|
|
2942
|
-
const paginatedRows =
|
|
3633
|
+
const paginatedRows = useMemo11(() => {
|
|
2943
3634
|
if (!enablePagination)
|
|
2944
3635
|
return searchFilteredData;
|
|
2945
3636
|
const start = (currentPage - 1) * pageSize;
|
|
2946
3637
|
const end = start + pageSize;
|
|
2947
3638
|
return searchFilteredData.slice(start, end);
|
|
2948
3639
|
}, [enablePagination, searchFilteredData, currentPage, pageSize]);
|
|
2949
|
-
|
|
3640
|
+
useEffect8(() => {
|
|
2950
3641
|
setCurrentPage(1);
|
|
2951
3642
|
}, [columnFilters, globalSearchTerm]);
|
|
2952
|
-
const selectionBounds =
|
|
3643
|
+
const selectionBounds = useMemo11(() => {
|
|
2953
3644
|
if (!selectionStart || !selectionEnd)
|
|
2954
3645
|
return null;
|
|
2955
3646
|
return {
|
|
@@ -2959,7 +3650,7 @@ function DataGrid({
|
|
|
2959
3650
|
maxCol: Math.max(selectionStart.col, selectionEnd.col)
|
|
2960
3651
|
};
|
|
2961
3652
|
}, [selectionStart, selectionEnd]);
|
|
2962
|
-
const selectionStats =
|
|
3653
|
+
const selectionStats = useMemo11(() => {
|
|
2963
3654
|
if (!selectionBounds)
|
|
2964
3655
|
return null;
|
|
2965
3656
|
const { minRow, maxRow, minCol, maxCol } = selectionBounds;
|
|
@@ -2989,7 +3680,7 @@ function DataGrid({
|
|
|
2989
3680
|
const avg = sum / values.length;
|
|
2990
3681
|
return { count, sum, avg, numericCount: values.length };
|
|
2991
3682
|
}, [selectionBounds, rows, columnKeys]);
|
|
2992
|
-
|
|
3683
|
+
useEffect8(() => {
|
|
2993
3684
|
if (typeof document === "undefined")
|
|
2994
3685
|
return;
|
|
2995
3686
|
if (data.length === 0)
|
|
@@ -3013,7 +3704,7 @@ function DataGrid({
|
|
|
3013
3704
|
}
|
|
3014
3705
|
setColumnWidths(widths);
|
|
3015
3706
|
}, [data, columnKeys]);
|
|
3016
|
-
const startColumnResize =
|
|
3707
|
+
const startColumnResize = useCallback11(
|
|
3017
3708
|
(columnId, event) => {
|
|
3018
3709
|
if (!enableColumnResize)
|
|
3019
3710
|
return;
|
|
@@ -3025,7 +3716,7 @@ function DataGrid({
|
|
|
3025
3716
|
},
|
|
3026
3717
|
[enableColumnResize, columnWidths]
|
|
3027
3718
|
);
|
|
3028
|
-
|
|
3719
|
+
useEffect8(() => {
|
|
3029
3720
|
if (!resizingColumnId)
|
|
3030
3721
|
return;
|
|
3031
3722
|
const handleResizeMove = (event) => {
|
|
@@ -3046,7 +3737,7 @@ function DataGrid({
|
|
|
3046
3737
|
document.removeEventListener("mouseup", handleResizeEnd);
|
|
3047
3738
|
};
|
|
3048
3739
|
}, [resizingColumnId, resizeStartX, resizeStartWidth]);
|
|
3049
|
-
const startVerticalResize =
|
|
3740
|
+
const startVerticalResize = useCallback11(
|
|
3050
3741
|
(event) => {
|
|
3051
3742
|
if (!enableVerticalResize)
|
|
3052
3743
|
return;
|
|
@@ -3057,7 +3748,7 @@ function DataGrid({
|
|
|
3057
3748
|
},
|
|
3058
3749
|
[enableVerticalResize, gridHeight]
|
|
3059
3750
|
);
|
|
3060
|
-
|
|
3751
|
+
useEffect8(() => {
|
|
3061
3752
|
if (!isResizingVertically)
|
|
3062
3753
|
return;
|
|
3063
3754
|
const handleVerticalResizeMove = (event) => {
|
|
@@ -3075,7 +3766,7 @@ function DataGrid({
|
|
|
3075
3766
|
document.removeEventListener("mouseup", handleVerticalResizeEnd);
|
|
3076
3767
|
};
|
|
3077
3768
|
}, [isResizingVertically, verticalResizeStartY, verticalResizeStartHeight, minHeight, maxHeight]);
|
|
3078
|
-
const handleExport =
|
|
3769
|
+
const handleExport = useCallback11(() => {
|
|
3079
3770
|
if (viewMode === "pivot") {
|
|
3080
3771
|
if (!pivotResult)
|
|
3081
3772
|
return;
|
|
@@ -3121,7 +3812,7 @@ function DataGrid({
|
|
|
3121
3812
|
columnKeys,
|
|
3122
3813
|
onExport
|
|
3123
3814
|
]);
|
|
3124
|
-
const copySelectionToClipboard =
|
|
3815
|
+
const copySelectionToClipboard = useCallback11(() => {
|
|
3125
3816
|
if (!selectionBounds || !enableClipboard)
|
|
3126
3817
|
return;
|
|
3127
3818
|
const text = formatSelectionForClipboard(
|
|
@@ -3146,7 +3837,7 @@ function DataGrid({
|
|
|
3146
3837
|
}
|
|
3147
3838
|
);
|
|
3148
3839
|
}, [selectionBounds, enableClipboard, rows, columnKeys, onCopy]);
|
|
3149
|
-
const handleMouseDown =
|
|
3840
|
+
const handleMouseDown = useCallback11(
|
|
3150
3841
|
(rowIndex, colIndex, event) => {
|
|
3151
3842
|
event.preventDefault();
|
|
3152
3843
|
if (event.shiftKey && selectedCell) {
|
|
@@ -3170,7 +3861,7 @@ function DataGrid({
|
|
|
3170
3861
|
},
|
|
3171
3862
|
[selectedCell, rows, columnKeys, onCellClick]
|
|
3172
3863
|
);
|
|
3173
|
-
const handleMouseEnter =
|
|
3864
|
+
const handleMouseEnter = useCallback11(
|
|
3174
3865
|
(rowIndex, colIndex) => {
|
|
3175
3866
|
if (isSelecting) {
|
|
3176
3867
|
setSelectionEnd({ row: rowIndex, col: colIndex });
|
|
@@ -3178,12 +3869,12 @@ function DataGrid({
|
|
|
3178
3869
|
},
|
|
3179
3870
|
[isSelecting]
|
|
3180
3871
|
);
|
|
3181
|
-
|
|
3872
|
+
useEffect8(() => {
|
|
3182
3873
|
const handleMouseUp = () => setIsSelecting(false);
|
|
3183
3874
|
document.addEventListener("mouseup", handleMouseUp);
|
|
3184
3875
|
return () => document.removeEventListener("mouseup", handleMouseUp);
|
|
3185
3876
|
}, []);
|
|
3186
|
-
|
|
3877
|
+
useEffect8(() => {
|
|
3187
3878
|
const handleKeydown = (event) => {
|
|
3188
3879
|
if ((event.ctrlKey || event.metaKey) && event.key === "c" && selectionBounds) {
|
|
3189
3880
|
event.preventDefault();
|
|
@@ -3201,7 +3892,7 @@ function DataGrid({
|
|
|
3201
3892
|
document.addEventListener("keydown", handleKeydown);
|
|
3202
3893
|
return () => document.removeEventListener("keydown", handleKeydown);
|
|
3203
3894
|
}, [selectionBounds, copySelectionToClipboard]);
|
|
3204
|
-
const openFilterDropdown =
|
|
3895
|
+
const openFilterDropdown = useCallback11(
|
|
3205
3896
|
(columnId, event) => {
|
|
3206
3897
|
event.stopPropagation();
|
|
3207
3898
|
const target = event.currentTarget;
|
|
@@ -3230,22 +3921,22 @@ function DataGrid({
|
|
|
3230
3921
|
},
|
|
3231
3922
|
[]
|
|
3232
3923
|
);
|
|
3233
|
-
const closeFilterDropdown =
|
|
3924
|
+
const closeFilterDropdown = useCallback11(() => {
|
|
3234
3925
|
setActiveFilterColumn(null);
|
|
3235
3926
|
}, []);
|
|
3236
|
-
const handleFilter =
|
|
3927
|
+
const handleFilter = useCallback11(
|
|
3237
3928
|
(columnId, values) => {
|
|
3238
3929
|
setColumnFilter(columnId, values);
|
|
3239
3930
|
},
|
|
3240
3931
|
[setColumnFilter]
|
|
3241
3932
|
);
|
|
3242
|
-
const handleRangeFilter =
|
|
3933
|
+
const handleRangeFilter = useCallback11(
|
|
3243
3934
|
(columnId, range) => {
|
|
3244
3935
|
setNumericRangeFilter(columnId, range);
|
|
3245
3936
|
},
|
|
3246
3937
|
[setNumericRangeFilter]
|
|
3247
3938
|
);
|
|
3248
|
-
const handleSort =
|
|
3939
|
+
const handleSort = useCallback11(
|
|
3249
3940
|
(columnId, direction) => {
|
|
3250
3941
|
if (direction === null) {
|
|
3251
3942
|
const current = getSortDirection(columnId);
|
|
@@ -3269,7 +3960,7 @@ function DataGrid({
|
|
|
3269
3960
|
},
|
|
3270
3961
|
[getSortDirection, toggleSort]
|
|
3271
3962
|
);
|
|
3272
|
-
const isCellSelected =
|
|
3963
|
+
const isCellSelected = useCallback11(
|
|
3273
3964
|
(rowIndex, colIndex) => {
|
|
3274
3965
|
if (!selectionBounds) {
|
|
3275
3966
|
return selectedCell?.row === rowIndex && selectedCell?.col === colIndex;
|
|
@@ -3311,30 +4002,30 @@ function DataGrid({
|
|
|
3311
4002
|
}
|
|
3312
4003
|
return String(value);
|
|
3313
4004
|
};
|
|
3314
|
-
const totalTableWidth =
|
|
4005
|
+
const totalTableWidth = useMemo11(() => {
|
|
3315
4006
|
return columnKeys.reduce((sum, key) => sum + (columnWidths[key] || MIN_COL_WIDTH), 0);
|
|
3316
4007
|
}, [columnKeys, columnWidths]);
|
|
3317
4008
|
const activeFilterCount = columnFilters.length;
|
|
3318
|
-
return /* @__PURE__ */
|
|
4009
|
+
return /* @__PURE__ */ jsxs7(
|
|
3319
4010
|
"div",
|
|
3320
4011
|
{
|
|
3321
4012
|
className: `vpg-data-grid vpg-font-${currentFontSize} vpg-theme-${currentTheme} ${stripedRows ? "vpg-striped" : ""} ${resizingColumnId ? "vpg-resizing" : ""} ${isResizingVertically ? "vpg-resizing-vertical" : ""}`,
|
|
3322
4013
|
style: { height: `${gridHeight}px` },
|
|
3323
4014
|
children: [
|
|
3324
|
-
showCopyToast && /* @__PURE__ */
|
|
3325
|
-
/* @__PURE__ */
|
|
4015
|
+
showCopyToast && /* @__PURE__ */ jsxs7("div", { className: "vpg-toast", children: [
|
|
4016
|
+
/* @__PURE__ */ jsx7("svg", { className: "vpg-icon", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: /* @__PURE__ */ jsx7("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "M5 13l4 4L19 7" }) }),
|
|
3326
4017
|
copyToastMessage
|
|
3327
4018
|
] }),
|
|
3328
|
-
/* @__PURE__ */
|
|
3329
|
-
/* @__PURE__ */
|
|
3330
|
-
showPivot && /* @__PURE__ */
|
|
3331
|
-
/* @__PURE__ */
|
|
4019
|
+
/* @__PURE__ */ jsxs7("div", { className: "vpg-toolbar", children: [
|
|
4020
|
+
/* @__PURE__ */ jsxs7("div", { className: "vpg-toolbar-left", children: [
|
|
4021
|
+
showPivot && /* @__PURE__ */ jsxs7("div", { className: "vpg-view-toggle", children: [
|
|
4022
|
+
/* @__PURE__ */ jsxs7(
|
|
3332
4023
|
"button",
|
|
3333
4024
|
{
|
|
3334
4025
|
className: `vpg-view-btn ${viewMode === "grid" ? "active" : ""}`,
|
|
3335
4026
|
onClick: () => setViewMode("grid"),
|
|
3336
4027
|
children: [
|
|
3337
|
-
/* @__PURE__ */
|
|
4028
|
+
/* @__PURE__ */ jsx7("svg", { className: "vpg-icon", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: /* @__PURE__ */ jsx7(
|
|
3338
4029
|
"path",
|
|
3339
4030
|
{
|
|
3340
4031
|
strokeLinecap: "round",
|
|
@@ -3347,13 +4038,13 @@ function DataGrid({
|
|
|
3347
4038
|
]
|
|
3348
4039
|
}
|
|
3349
4040
|
),
|
|
3350
|
-
/* @__PURE__ */
|
|
4041
|
+
/* @__PURE__ */ jsxs7(
|
|
3351
4042
|
"button",
|
|
3352
4043
|
{
|
|
3353
4044
|
className: `vpg-view-btn vpg-pivot-btn ${viewMode === "pivot" ? "active" : ""}`,
|
|
3354
4045
|
onClick: () => setViewMode("pivot"),
|
|
3355
4046
|
children: [
|
|
3356
|
-
/* @__PURE__ */
|
|
4047
|
+
/* @__PURE__ */ jsx7("svg", { className: "vpg-icon", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: /* @__PURE__ */ jsx7(
|
|
3357
4048
|
"path",
|
|
3358
4049
|
{
|
|
3359
4050
|
strokeLinecap: "round",
|
|
@@ -3365,16 +4056,37 @@ function DataGrid({
|
|
|
3365
4056
|
"Pivot"
|
|
3366
4057
|
]
|
|
3367
4058
|
}
|
|
4059
|
+
),
|
|
4060
|
+
/* @__PURE__ */ jsxs7(
|
|
4061
|
+
"button",
|
|
4062
|
+
{
|
|
4063
|
+
className: `vpg-view-btn vpg-chart-btn ${viewMode === "chart" ? "active" : ""} ${!canUseCharts ? "vpg-pro-feature" : ""}`,
|
|
4064
|
+
title: canUseCharts ? "Chart Builder" : "Chart Builder (Pro feature)",
|
|
4065
|
+
onClick: () => canUseCharts && setViewMode("chart"),
|
|
4066
|
+
children: [
|
|
4067
|
+
/* @__PURE__ */ jsx7("svg", { className: "vpg-icon", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: /* @__PURE__ */ jsx7(
|
|
4068
|
+
"path",
|
|
4069
|
+
{
|
|
4070
|
+
strokeLinecap: "round",
|
|
4071
|
+
strokeLinejoin: "round",
|
|
4072
|
+
strokeWidth: 2,
|
|
4073
|
+
d: "M9 19v-6a2 2 0 00-2-2H5a2 2 0 00-2 2v6a2 2 0 002 2h2a2 2 0 002-2zm0 0V9a2 2 0 012-2h2a2 2 0 012 2v10m-6 0a2 2 0 002 2h2a2 2 0 002-2m0 0V5a2 2 0 012-2h2a2 2 0 012 2v14a2 2 0 01-2 2h-2a2 2 0 01-2-2z"
|
|
4074
|
+
}
|
|
4075
|
+
) }),
|
|
4076
|
+
"Chart",
|
|
4077
|
+
!canUseCharts && /* @__PURE__ */ jsx7("span", { className: "vpg-pro-badge", children: "Pro" })
|
|
4078
|
+
]
|
|
4079
|
+
}
|
|
3368
4080
|
)
|
|
3369
4081
|
] }),
|
|
3370
|
-
viewMode === "grid" && /* @__PURE__ */
|
|
3371
|
-
enableSearch && /* @__PURE__ */
|
|
4082
|
+
viewMode === "grid" && /* @__PURE__ */ jsxs7(Fragment5, { children: [
|
|
4083
|
+
enableSearch && /* @__PURE__ */ jsx7("div", { className: "vpg-search-container", children: !showSearchInput ? /* @__PURE__ */ jsx7(
|
|
3372
4084
|
"button",
|
|
3373
4085
|
{
|
|
3374
4086
|
className: "vpg-icon-btn",
|
|
3375
4087
|
title: "Search (Ctrl+F)",
|
|
3376
4088
|
onClick: () => setShowSearchInput(true),
|
|
3377
|
-
children: /* @__PURE__ */
|
|
4089
|
+
children: /* @__PURE__ */ jsx7("svg", { className: "vpg-icon", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: /* @__PURE__ */ jsx7(
|
|
3378
4090
|
"path",
|
|
3379
4091
|
{
|
|
3380
4092
|
strokeLinecap: "round",
|
|
@@ -3384,15 +4096,15 @@ function DataGrid({
|
|
|
3384
4096
|
}
|
|
3385
4097
|
) })
|
|
3386
4098
|
}
|
|
3387
|
-
) : /* @__PURE__ */
|
|
3388
|
-
/* @__PURE__ */
|
|
4099
|
+
) : /* @__PURE__ */ jsxs7("div", { className: "vpg-search-box", children: [
|
|
4100
|
+
/* @__PURE__ */ jsx7(
|
|
3389
4101
|
"svg",
|
|
3390
4102
|
{
|
|
3391
4103
|
className: "vpg-search-icon",
|
|
3392
4104
|
fill: "none",
|
|
3393
4105
|
stroke: "currentColor",
|
|
3394
4106
|
viewBox: "0 0 24 24",
|
|
3395
|
-
children: /* @__PURE__ */
|
|
4107
|
+
children: /* @__PURE__ */ jsx7(
|
|
3396
4108
|
"path",
|
|
3397
4109
|
{
|
|
3398
4110
|
strokeLinecap: "round",
|
|
@@ -3403,7 +4115,7 @@ function DataGrid({
|
|
|
3403
4115
|
)
|
|
3404
4116
|
}
|
|
3405
4117
|
),
|
|
3406
|
-
/* @__PURE__ */
|
|
4118
|
+
/* @__PURE__ */ jsx7(
|
|
3407
4119
|
"input",
|
|
3408
4120
|
{
|
|
3409
4121
|
type: "text",
|
|
@@ -3420,14 +4132,14 @@ function DataGrid({
|
|
|
3420
4132
|
autoFocus: true
|
|
3421
4133
|
}
|
|
3422
4134
|
),
|
|
3423
|
-
globalSearchTerm && /* @__PURE__ */
|
|
4135
|
+
globalSearchTerm && /* @__PURE__ */ jsx7("button", { className: "vpg-search-clear", onClick: () => setGlobalSearchTerm(""), children: /* @__PURE__ */ jsx7(
|
|
3424
4136
|
"svg",
|
|
3425
4137
|
{
|
|
3426
4138
|
className: "vpg-icon-xs",
|
|
3427
4139
|
fill: "none",
|
|
3428
4140
|
stroke: "currentColor",
|
|
3429
4141
|
viewBox: "0 0 24 24",
|
|
3430
|
-
children: /* @__PURE__ */
|
|
4142
|
+
children: /* @__PURE__ */ jsx7(
|
|
3431
4143
|
"path",
|
|
3432
4144
|
{
|
|
3433
4145
|
strokeLinecap: "round",
|
|
@@ -3439,9 +4151,9 @@ function DataGrid({
|
|
|
3439
4151
|
}
|
|
3440
4152
|
) })
|
|
3441
4153
|
] }) }),
|
|
3442
|
-
/* @__PURE__ */
|
|
3443
|
-
/* @__PURE__ */
|
|
3444
|
-
/* @__PURE__ */
|
|
4154
|
+
/* @__PURE__ */ jsxs7("div", { className: "vpg-font-size-control", children: [
|
|
4155
|
+
/* @__PURE__ */ jsx7("span", { className: "vpg-label", children: "Size:" }),
|
|
4156
|
+
/* @__PURE__ */ jsx7("div", { className: "vpg-font-size-toggle", children: fontSizeOptions.map((opt) => /* @__PURE__ */ jsx7(
|
|
3445
4157
|
"button",
|
|
3446
4158
|
{
|
|
3447
4159
|
className: `vpg-font-size-btn ${currentFontSize === opt.value ? "active" : ""}`,
|
|
@@ -3451,8 +4163,8 @@ function DataGrid({
|
|
|
3451
4163
|
opt.value
|
|
3452
4164
|
)) })
|
|
3453
4165
|
] }),
|
|
3454
|
-
activeFilterCount > 0 && /* @__PURE__ */
|
|
3455
|
-
/* @__PURE__ */
|
|
4166
|
+
activeFilterCount > 0 && /* @__PURE__ */ jsxs7("div", { className: "vpg-filter-info", children: [
|
|
4167
|
+
/* @__PURE__ */ jsx7("svg", { className: "vpg-icon", fill: "currentColor", viewBox: "0 0 20 20", children: /* @__PURE__ */ jsx7(
|
|
3456
4168
|
"path",
|
|
3457
4169
|
{
|
|
3458
4170
|
fillRule: "evenodd",
|
|
@@ -3460,28 +4172,28 @@ function DataGrid({
|
|
|
3460
4172
|
clipRule: "evenodd"
|
|
3461
4173
|
}
|
|
3462
4174
|
) }),
|
|
3463
|
-
/* @__PURE__ */
|
|
4175
|
+
/* @__PURE__ */ jsxs7("span", { children: [
|
|
3464
4176
|
activeFilterCount,
|
|
3465
4177
|
" ",
|
|
3466
4178
|
"filter",
|
|
3467
4179
|
activeFilterCount > 1 ? "s" : ""
|
|
3468
4180
|
] })
|
|
3469
4181
|
] }),
|
|
3470
|
-
globalSearchTerm && /* @__PURE__ */
|
|
4182
|
+
globalSearchTerm && /* @__PURE__ */ jsx7("div", { className: "vpg-search-info", children: /* @__PURE__ */ jsxs7("span", { children: [
|
|
3471
4183
|
totalSearchedRows,
|
|
3472
4184
|
" ",
|
|
3473
4185
|
"match",
|
|
3474
4186
|
totalSearchedRows !== 1 ? "es" : ""
|
|
3475
4187
|
] }) })
|
|
3476
4188
|
] }),
|
|
3477
|
-
viewMode === "pivot" && canUsePivot && /* @__PURE__ */
|
|
3478
|
-
/* @__PURE__ */
|
|
4189
|
+
viewMode === "pivot" && canUsePivot && /* @__PURE__ */ jsxs7(Fragment5, { children: [
|
|
4190
|
+
/* @__PURE__ */ jsxs7(
|
|
3479
4191
|
"button",
|
|
3480
4192
|
{
|
|
3481
4193
|
className: `vpg-config-toggle ${showPivotConfig ? "active" : ""}`,
|
|
3482
4194
|
onClick: () => setShowPivotConfig(!showPivotConfig),
|
|
3483
4195
|
children: [
|
|
3484
|
-
/* @__PURE__ */
|
|
4196
|
+
/* @__PURE__ */ jsx7("svg", { className: "vpg-icon", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: /* @__PURE__ */ jsx7(
|
|
3485
4197
|
"path",
|
|
3486
4198
|
{
|
|
3487
4199
|
strokeLinecap: "round",
|
|
@@ -3496,8 +4208,8 @@ function DataGrid({
|
|
|
3496
4208
|
]
|
|
3497
4209
|
}
|
|
3498
4210
|
),
|
|
3499
|
-
pivotIsConfigured && /* @__PURE__ */
|
|
3500
|
-
/* @__PURE__ */
|
|
4211
|
+
pivotIsConfigured && /* @__PURE__ */ jsxs7("div", { className: "vpg-pivot-status", children: [
|
|
4212
|
+
/* @__PURE__ */ jsx7("svg", { className: "vpg-icon", fill: "currentColor", viewBox: "0 0 20 20", children: /* @__PURE__ */ jsx7(
|
|
3501
4213
|
"path",
|
|
3502
4214
|
{
|
|
3503
4215
|
fillRule: "evenodd",
|
|
@@ -3505,13 +4217,13 @@ function DataGrid({
|
|
|
3505
4217
|
clipRule: "evenodd"
|
|
3506
4218
|
}
|
|
3507
4219
|
) }),
|
|
3508
|
-
/* @__PURE__ */
|
|
4220
|
+
/* @__PURE__ */ jsx7("span", { children: "Pivot configured" })
|
|
3509
4221
|
] })
|
|
3510
4222
|
] })
|
|
3511
4223
|
] }),
|
|
3512
|
-
/* @__PURE__ */
|
|
3513
|
-
viewMode === "grid" && activeFilterCount > 0 && /* @__PURE__ */
|
|
3514
|
-
/* @__PURE__ */
|
|
4224
|
+
/* @__PURE__ */ jsxs7("div", { className: "vpg-toolbar-right", children: [
|
|
4225
|
+
viewMode === "grid" && activeFilterCount > 0 && /* @__PURE__ */ jsxs7("button", { className: "vpg-clear-filters", onClick: clearAllFilters, children: [
|
|
4226
|
+
/* @__PURE__ */ jsx7("svg", { className: "vpg-icon", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: /* @__PURE__ */ jsx7(
|
|
3515
4227
|
"path",
|
|
3516
4228
|
{
|
|
3517
4229
|
strokeLinecap: "round",
|
|
@@ -3522,13 +4234,13 @@ function DataGrid({
|
|
|
3522
4234
|
) }),
|
|
3523
4235
|
"Clear Filters"
|
|
3524
4236
|
] }),
|
|
3525
|
-
enableClipboard && selectionBounds && viewMode === "grid" && /* @__PURE__ */
|
|
4237
|
+
enableClipboard && selectionBounds && viewMode === "grid" && /* @__PURE__ */ jsx7(
|
|
3526
4238
|
"button",
|
|
3527
4239
|
{
|
|
3528
4240
|
className: "vpg-icon-btn",
|
|
3529
4241
|
title: "Copy selection (Ctrl+C)",
|
|
3530
4242
|
onClick: copySelectionToClipboard,
|
|
3531
|
-
children: /* @__PURE__ */
|
|
4243
|
+
children: /* @__PURE__ */ jsx7("svg", { className: "vpg-icon", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: /* @__PURE__ */ jsx7(
|
|
3532
4244
|
"path",
|
|
3533
4245
|
{
|
|
3534
4246
|
strokeLinecap: "round",
|
|
@@ -3539,14 +4251,14 @@ function DataGrid({
|
|
|
3539
4251
|
) })
|
|
3540
4252
|
}
|
|
3541
4253
|
),
|
|
3542
|
-
enableExport && viewMode === "grid" && /* @__PURE__ */
|
|
4254
|
+
enableExport && viewMode === "grid" && /* @__PURE__ */ jsxs7(
|
|
3543
4255
|
"button",
|
|
3544
4256
|
{
|
|
3545
4257
|
className: "vpg-export-btn",
|
|
3546
4258
|
title: "Export to CSV",
|
|
3547
4259
|
onClick: handleExport,
|
|
3548
4260
|
children: [
|
|
3549
|
-
/* @__PURE__ */
|
|
4261
|
+
/* @__PURE__ */ jsx7("svg", { className: "vpg-icon", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: /* @__PURE__ */ jsx7(
|
|
3550
4262
|
"path",
|
|
3551
4263
|
{
|
|
3552
4264
|
strokeLinecap: "round",
|
|
@@ -3559,7 +4271,7 @@ function DataGrid({
|
|
|
3559
4271
|
]
|
|
3560
4272
|
}
|
|
3561
4273
|
),
|
|
3562
|
-
enableExport && viewMode === "pivot" && pivotIsConfigured && /* @__PURE__ */
|
|
4274
|
+
enableExport && viewMode === "pivot" && pivotIsConfigured && /* @__PURE__ */ jsxs7(
|
|
3563
4275
|
"button",
|
|
3564
4276
|
{
|
|
3565
4277
|
className: `vpg-export-btn ${!isPro ? "vpg-export-btn-disabled" : ""}`,
|
|
@@ -3567,7 +4279,7 @@ function DataGrid({
|
|
|
3567
4279
|
title: isPro ? "Export Pivot to CSV" : "Export Pivot to CSV (Pro feature)",
|
|
3568
4280
|
onClick: () => isPro && handleExport(),
|
|
3569
4281
|
children: [
|
|
3570
|
-
/* @__PURE__ */
|
|
4282
|
+
/* @__PURE__ */ jsx7("svg", { className: "vpg-icon", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: /* @__PURE__ */ jsx7(
|
|
3571
4283
|
"path",
|
|
3572
4284
|
{
|
|
3573
4285
|
strokeLinecap: "round",
|
|
@@ -3583,13 +4295,13 @@ function DataGrid({
|
|
|
3583
4295
|
)
|
|
3584
4296
|
] })
|
|
3585
4297
|
] }),
|
|
3586
|
-
viewMode === "grid" && /* @__PURE__ */
|
|
3587
|
-
loading && /* @__PURE__ */
|
|
3588
|
-
/* @__PURE__ */
|
|
3589
|
-
/* @__PURE__ */
|
|
4298
|
+
viewMode === "grid" && /* @__PURE__ */ jsxs7("div", { ref: tableContainerRef, className: "vpg-grid-container", tabIndex: 0, children: [
|
|
4299
|
+
loading && /* @__PURE__ */ jsxs7("div", { className: "vpg-loading", children: [
|
|
4300
|
+
/* @__PURE__ */ jsx7("div", { className: "vpg-spinner" }),
|
|
4301
|
+
/* @__PURE__ */ jsx7("span", { children: "Loading data..." })
|
|
3590
4302
|
] }),
|
|
3591
|
-
!loading && data.length === 0 && /* @__PURE__ */
|
|
3592
|
-
/* @__PURE__ */
|
|
4303
|
+
!loading && data.length === 0 && /* @__PURE__ */ jsxs7("div", { className: "vpg-empty", children: [
|
|
4304
|
+
/* @__PURE__ */ jsx7("div", { className: "vpg-empty-icon", children: /* @__PURE__ */ jsx7("svg", { className: "vpg-icon-lg", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: /* @__PURE__ */ jsx7(
|
|
3593
4305
|
"path",
|
|
3594
4306
|
{
|
|
3595
4307
|
strokeLinecap: "round",
|
|
@@ -3598,10 +4310,10 @@ function DataGrid({
|
|
|
3598
4310
|
d: "M9 17v-2m3 2v-4m3 4v-6m2 10H7a2 2 0 01-2-2V5a2 2 0 012-2h5.586a1 1 0 01.707.293l5.414 5.414a1 1 0 01.293.707V19a2 2 0 01-2 2z"
|
|
3599
4311
|
}
|
|
3600
4312
|
) }) }),
|
|
3601
|
-
/* @__PURE__ */
|
|
4313
|
+
/* @__PURE__ */ jsx7("span", { children: "No data available" })
|
|
3602
4314
|
] }),
|
|
3603
|
-
!loading && data.length > 0 && filteredRowCount === 0 && /* @__PURE__ */
|
|
3604
|
-
/* @__PURE__ */
|
|
4315
|
+
!loading && data.length > 0 && filteredRowCount === 0 && /* @__PURE__ */ jsxs7("div", { className: "vpg-empty", children: [
|
|
4316
|
+
/* @__PURE__ */ jsx7("div", { className: "vpg-empty-icon vpg-warning", children: /* @__PURE__ */ jsx7("svg", { className: "vpg-icon-lg", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: /* @__PURE__ */ jsx7(
|
|
3605
4317
|
"path",
|
|
3606
4318
|
{
|
|
3607
4319
|
strokeLinecap: "round",
|
|
@@ -3610,11 +4322,11 @@ function DataGrid({
|
|
|
3610
4322
|
d: "M3 4a1 1 0 011-1h16a1 1 0 011 1v2.586a1 1 0 01-.293.707l-6.414 6.414a1 1 0 00-.293.707V17l-4 4v-6.586a1 1 0 00-.293-.707L3.293 7.293A1 1 0 013 6.586V4z"
|
|
3611
4323
|
}
|
|
3612
4324
|
) }) }),
|
|
3613
|
-
/* @__PURE__ */
|
|
3614
|
-
/* @__PURE__ */
|
|
4325
|
+
/* @__PURE__ */ jsx7("span", { children: "No matching records" }),
|
|
4326
|
+
/* @__PURE__ */ jsx7("button", { className: "vpg-clear-link", onClick: clearAllFilters, children: "Clear all filters" })
|
|
3615
4327
|
] }),
|
|
3616
|
-
!loading && filteredRowCount > 0 && /* @__PURE__ */
|
|
3617
|
-
/* @__PURE__ */
|
|
4328
|
+
!loading && filteredRowCount > 0 && /* @__PURE__ */ jsx7("div", { className: "vpg-table-wrapper", children: /* @__PURE__ */ jsxs7("table", { className: "vpg-table", style: { minWidth: `${totalTableWidth}px` }, children: [
|
|
4329
|
+
/* @__PURE__ */ jsx7("thead", { children: /* @__PURE__ */ jsx7("tr", { children: columnKeys.map((colId) => /* @__PURE__ */ jsxs7(
|
|
3618
4330
|
"th",
|
|
3619
4331
|
{
|
|
3620
4332
|
className: `vpg-header-cell ${hasActiveFilter(colId) ? "vpg-has-filter" : ""} ${getSortDirection(colId) !== null ? "vpg-is-sorted" : ""} ${activeFilterColumn === colId ? "vpg-is-active" : ""}`,
|
|
@@ -3629,16 +4341,16 @@ function DataGrid({
|
|
|
3629
4341
|
}
|
|
3630
4342
|
},
|
|
3631
4343
|
children: [
|
|
3632
|
-
/* @__PURE__ */
|
|
3633
|
-
/* @__PURE__ */
|
|
3634
|
-
/* @__PURE__ */
|
|
3635
|
-
getSortDirection(colId) && /* @__PURE__ */
|
|
4344
|
+
/* @__PURE__ */ jsxs7("div", { className: "vpg-header-content", children: [
|
|
4345
|
+
/* @__PURE__ */ jsx7("span", { className: "vpg-header-text", children: colId }),
|
|
4346
|
+
/* @__PURE__ */ jsxs7("div", { className: "vpg-header-icons", children: [
|
|
4347
|
+
getSortDirection(colId) && /* @__PURE__ */ jsx7("span", { className: "vpg-sort-indicator", children: getSortDirection(colId) === "asc" ? /* @__PURE__ */ jsx7(
|
|
3636
4348
|
"svg",
|
|
3637
4349
|
{
|
|
3638
4350
|
className: "vpg-icon-sm",
|
|
3639
4351
|
fill: "currentColor",
|
|
3640
4352
|
viewBox: "0 0 20 20",
|
|
3641
|
-
children: /* @__PURE__ */
|
|
4353
|
+
children: /* @__PURE__ */ jsx7(
|
|
3642
4354
|
"path",
|
|
3643
4355
|
{
|
|
3644
4356
|
fillRule: "evenodd",
|
|
@@ -3647,13 +4359,13 @@ function DataGrid({
|
|
|
3647
4359
|
}
|
|
3648
4360
|
)
|
|
3649
4361
|
}
|
|
3650
|
-
) : /* @__PURE__ */
|
|
4362
|
+
) : /* @__PURE__ */ jsx7(
|
|
3651
4363
|
"svg",
|
|
3652
4364
|
{
|
|
3653
4365
|
className: "vpg-icon-sm",
|
|
3654
4366
|
fill: "currentColor",
|
|
3655
4367
|
viewBox: "0 0 20 20",
|
|
3656
|
-
children: /* @__PURE__ */
|
|
4368
|
+
children: /* @__PURE__ */ jsx7(
|
|
3657
4369
|
"path",
|
|
3658
4370
|
{
|
|
3659
4371
|
fillRule: "evenodd",
|
|
@@ -3663,13 +4375,13 @@ function DataGrid({
|
|
|
3663
4375
|
)
|
|
3664
4376
|
}
|
|
3665
4377
|
) }),
|
|
3666
|
-
hasActiveFilter(colId) && /* @__PURE__ */
|
|
4378
|
+
hasActiveFilter(colId) && /* @__PURE__ */ jsx7("span", { className: "vpg-filter-indicator", children: /* @__PURE__ */ jsx7(
|
|
3667
4379
|
"svg",
|
|
3668
4380
|
{
|
|
3669
4381
|
className: "vpg-icon-xs",
|
|
3670
4382
|
fill: "currentColor",
|
|
3671
4383
|
viewBox: "0 0 20 20",
|
|
3672
|
-
children: /* @__PURE__ */
|
|
4384
|
+
children: /* @__PURE__ */ jsx7(
|
|
3673
4385
|
"path",
|
|
3674
4386
|
{
|
|
3675
4387
|
fillRule: "evenodd",
|
|
@@ -3679,14 +4391,14 @@ function DataGrid({
|
|
|
3679
4391
|
)
|
|
3680
4392
|
}
|
|
3681
4393
|
) }),
|
|
3682
|
-
/* @__PURE__ */
|
|
4394
|
+
/* @__PURE__ */ jsx7("span", { className: "vpg-dropdown-arrow", title: "Filter & Sort", children: /* @__PURE__ */ jsx7(
|
|
3683
4395
|
"svg",
|
|
3684
4396
|
{
|
|
3685
4397
|
className: "vpg-icon-sm",
|
|
3686
4398
|
fill: "none",
|
|
3687
4399
|
stroke: "currentColor",
|
|
3688
4400
|
viewBox: "0 0 24 24",
|
|
3689
|
-
children: /* @__PURE__ */
|
|
4401
|
+
children: /* @__PURE__ */ jsx7(
|
|
3690
4402
|
"path",
|
|
3691
4403
|
{
|
|
3692
4404
|
strokeLinecap: "round",
|
|
@@ -3699,7 +4411,7 @@ function DataGrid({
|
|
|
3699
4411
|
) })
|
|
3700
4412
|
] })
|
|
3701
4413
|
] }),
|
|
3702
|
-
enableColumnResize && /* @__PURE__ */
|
|
4414
|
+
enableColumnResize && /* @__PURE__ */ jsx7(
|
|
3703
4415
|
"div",
|
|
3704
4416
|
{
|
|
3705
4417
|
className: "vpg-resize-handle",
|
|
@@ -3710,7 +4422,7 @@ function DataGrid({
|
|
|
3710
4422
|
},
|
|
3711
4423
|
colId
|
|
3712
4424
|
)) }) }),
|
|
3713
|
-
/* @__PURE__ */
|
|
4425
|
+
/* @__PURE__ */ jsx7("tbody", { ref: tableBodyRef, children: paginatedRows.map((row, rowIndex) => /* @__PURE__ */ jsx7("tr", { className: "vpg-row", children: columnKeys.map((colId, colIndex) => /* @__PURE__ */ jsx7(
|
|
3714
4426
|
"td",
|
|
3715
4427
|
{
|
|
3716
4428
|
className: `vpg-cell ${isCellSelected(rowIndex, colIndex) ? "vpg-selected" : ""} ${getColumnStats(colId).type === "number" ? "vpg-is-number" : ""}`,
|
|
@@ -3728,8 +4440,8 @@ function DataGrid({
|
|
|
3728
4440
|
)) }, row.id)) })
|
|
3729
4441
|
] }) })
|
|
3730
4442
|
] }),
|
|
3731
|
-
viewMode === "pivot" && /* @__PURE__ */
|
|
3732
|
-
showPivotConfig && canUsePivot && /* @__PURE__ */
|
|
4443
|
+
viewMode === "pivot" && /* @__PURE__ */ jsxs7("div", { className: "vpg-pivot-container", children: [
|
|
4444
|
+
showPivotConfig && canUsePivot && /* @__PURE__ */ jsx7("div", { className: "vpg-pivot-config-panel", children: /* @__PURE__ */ jsx7(
|
|
3733
4445
|
PivotConfig,
|
|
3734
4446
|
{
|
|
3735
4447
|
availableFields: pivotAvailableFields,
|
|
@@ -3757,7 +4469,7 @@ function DataGrid({
|
|
|
3757
4469
|
onUpdateCalculatedField: addCalculatedField
|
|
3758
4470
|
}
|
|
3759
4471
|
) }),
|
|
3760
|
-
/* @__PURE__ */
|
|
4472
|
+
/* @__PURE__ */ jsx7("div", { className: `vpg-pivot-main ${!showPivotConfig ? "vpg-full-width" : ""}`, children: /* @__PURE__ */ jsx7(
|
|
3761
4473
|
PivotSkeleton,
|
|
3762
4474
|
{
|
|
3763
4475
|
rowFields: pivotRowFields,
|
|
@@ -3783,47 +4495,78 @@ function DataGrid({
|
|
|
3783
4495
|
}
|
|
3784
4496
|
) })
|
|
3785
4497
|
] }),
|
|
3786
|
-
/* @__PURE__ */
|
|
3787
|
-
/* @__PURE__ */
|
|
3788
|
-
/* @__PURE__ */
|
|
4498
|
+
viewMode === "chart" && /* @__PURE__ */ jsxs7("div", { className: "vpg-chart-view", children: [
|
|
4499
|
+
activeFilterInfo && activeFilterInfo.length > 0 && /* @__PURE__ */ jsxs7("div", { className: "vpg-chart-filter-bar", children: [
|
|
4500
|
+
/* @__PURE__ */ jsx7("svg", { className: "vpg-icon", fill: "currentColor", viewBox: "0 0 20 20", children: /* @__PURE__ */ jsx7("path", { fillRule: "evenodd", d: "M3 3a1 1 0 011-1h12a1 1 0 011 1v3a1 1 0 01-.293.707L12 11.414V15a1 1 0 01-.293.707l-2 2A1 1 0 018 17v-5.586L3.293 6.707A1 1 0 013 6V3z", clipRule: "evenodd" }) }),
|
|
4501
|
+
/* @__PURE__ */ jsxs7("span", { children: [
|
|
4502
|
+
"Chart showing",
|
|
4503
|
+
filteredRowCount.toLocaleString(),
|
|
4504
|
+
" ",
|
|
4505
|
+
"of",
|
|
4506
|
+
totalRowCount.toLocaleString(),
|
|
4507
|
+
" ",
|
|
4508
|
+
"records"
|
|
4509
|
+
] }),
|
|
4510
|
+
/* @__PURE__ */ jsx7("button", { className: "vpg-chart-clear-filters", onClick: clearAllFilters, children: "Clear filters" })
|
|
4511
|
+
] }),
|
|
4512
|
+
/* @__PURE__ */ jsx7(
|
|
4513
|
+
ChartBuilder,
|
|
4514
|
+
{
|
|
4515
|
+
data: filteredDataForPivot,
|
|
4516
|
+
theme: currentTheme,
|
|
4517
|
+
onConfigChange: handleChartConfigChange
|
|
4518
|
+
}
|
|
4519
|
+
)
|
|
4520
|
+
] }),
|
|
4521
|
+
/* @__PURE__ */ jsxs7("div", { className: "vpg-footer", children: [
|
|
4522
|
+
/* @__PURE__ */ jsx7("div", { className: "vpg-footer-left", children: viewMode === "grid" ? enablePagination ? /* @__PURE__ */ jsxs7(Fragment5, { children: [
|
|
4523
|
+
/* @__PURE__ */ jsxs7("span", { children: [
|
|
3789
4524
|
((currentPage - 1) * pageSize + 1).toLocaleString(),
|
|
3790
4525
|
"-",
|
|
3791
4526
|
Math.min(currentPage * pageSize, totalSearchedRows).toLocaleString()
|
|
3792
4527
|
] }),
|
|
3793
|
-
/* @__PURE__ */
|
|
3794
|
-
/* @__PURE__ */
|
|
3795
|
-
totalSearchedRows !== totalRowCount && /* @__PURE__ */
|
|
4528
|
+
/* @__PURE__ */ jsx7("span", { className: "vpg-separator", children: "of" }),
|
|
4529
|
+
/* @__PURE__ */ jsx7("span", { children: totalSearchedRows.toLocaleString() }),
|
|
4530
|
+
totalSearchedRows !== totalRowCount && /* @__PURE__ */ jsxs7("span", { className: "vpg-filtered-note", children: [
|
|
3796
4531
|
"(",
|
|
3797
4532
|
totalRowCount.toLocaleString(),
|
|
3798
4533
|
" ",
|
|
3799
4534
|
"total)"
|
|
3800
4535
|
] })
|
|
3801
|
-
] }) : filteredRowCount === totalRowCount && totalSearchedRows === totalRowCount ? /* @__PURE__ */
|
|
4536
|
+
] }) : filteredRowCount === totalRowCount && totalSearchedRows === totalRowCount ? /* @__PURE__ */ jsxs7("span", { children: [
|
|
3802
4537
|
totalRowCount.toLocaleString(),
|
|
3803
4538
|
" ",
|
|
3804
4539
|
"records"
|
|
3805
|
-
] }) : /* @__PURE__ */
|
|
3806
|
-
/* @__PURE__ */
|
|
3807
|
-
/* @__PURE__ */
|
|
3808
|
-
/* @__PURE__ */
|
|
3809
|
-
/* @__PURE__ */
|
|
3810
|
-
] }) : /* @__PURE__ */
|
|
3811
|
-
/* @__PURE__ */
|
|
3812
|
-
/* @__PURE__ */
|
|
3813
|
-
/* @__PURE__ */
|
|
4540
|
+
] }) : /* @__PURE__ */ jsxs7(Fragment5, { children: [
|
|
4541
|
+
/* @__PURE__ */ jsx7("span", { className: "vpg-filtered-count", children: totalSearchedRows.toLocaleString() }),
|
|
4542
|
+
/* @__PURE__ */ jsx7("span", { className: "vpg-separator", children: "of" }),
|
|
4543
|
+
/* @__PURE__ */ jsx7("span", { children: totalRowCount.toLocaleString() }),
|
|
4544
|
+
/* @__PURE__ */ jsx7("span", { className: "vpg-separator", children: "records" })
|
|
4545
|
+
] }) : viewMode === "pivot" ? /* @__PURE__ */ jsxs7(Fragment5, { children: [
|
|
4546
|
+
/* @__PURE__ */ jsx7("span", { className: "vpg-pivot-label", children: "Pivot Table" }),
|
|
4547
|
+
/* @__PURE__ */ jsx7("span", { className: "vpg-separator", children: "\u2022" }),
|
|
4548
|
+
/* @__PURE__ */ jsxs7("span", { children: [
|
|
3814
4549
|
totalRowCount.toLocaleString(),
|
|
3815
4550
|
" ",
|
|
3816
4551
|
"source records"
|
|
3817
4552
|
] })
|
|
4553
|
+
] }) : /* @__PURE__ */ jsxs7(Fragment5, { children: [
|
|
4554
|
+
/* @__PURE__ */ jsx7("span", { className: "vpg-chart-label", children: "Chart Builder" }),
|
|
4555
|
+
/* @__PURE__ */ jsx7("span", { className: "vpg-separator", children: "\u2022" }),
|
|
4556
|
+
/* @__PURE__ */ jsxs7("span", { children: [
|
|
4557
|
+
totalRowCount.toLocaleString(),
|
|
4558
|
+
" ",
|
|
4559
|
+
"records"
|
|
4560
|
+
] })
|
|
3818
4561
|
] }) }),
|
|
3819
|
-
enablePagination && viewMode === "grid" && totalPages > 1 && /* @__PURE__ */
|
|
3820
|
-
/* @__PURE__ */
|
|
4562
|
+
enablePagination && viewMode === "grid" && totalPages > 1 && /* @__PURE__ */ jsxs7("div", { className: "vpg-pagination", children: [
|
|
4563
|
+
/* @__PURE__ */ jsx7(
|
|
3821
4564
|
"button",
|
|
3822
4565
|
{
|
|
3823
4566
|
className: "vpg-page-btn",
|
|
3824
4567
|
disabled: currentPage === 1,
|
|
3825
4568
|
onClick: () => setCurrentPage(1),
|
|
3826
|
-
children: /* @__PURE__ */
|
|
4569
|
+
children: /* @__PURE__ */ jsx7("svg", { className: "vpg-icon-sm", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: /* @__PURE__ */ jsx7(
|
|
3827
4570
|
"path",
|
|
3828
4571
|
{
|
|
3829
4572
|
strokeLinecap: "round",
|
|
@@ -3834,13 +4577,13 @@ function DataGrid({
|
|
|
3834
4577
|
) })
|
|
3835
4578
|
}
|
|
3836
4579
|
),
|
|
3837
|
-
/* @__PURE__ */
|
|
4580
|
+
/* @__PURE__ */ jsx7(
|
|
3838
4581
|
"button",
|
|
3839
4582
|
{
|
|
3840
4583
|
className: "vpg-page-btn",
|
|
3841
4584
|
disabled: currentPage === 1,
|
|
3842
4585
|
onClick: () => setCurrentPage((p) => Math.max(1, p - 1)),
|
|
3843
|
-
children: /* @__PURE__ */
|
|
4586
|
+
children: /* @__PURE__ */ jsx7("svg", { className: "vpg-icon-sm", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: /* @__PURE__ */ jsx7(
|
|
3844
4587
|
"path",
|
|
3845
4588
|
{
|
|
3846
4589
|
strokeLinecap: "round",
|
|
@@ -3851,7 +4594,7 @@ function DataGrid({
|
|
|
3851
4594
|
) })
|
|
3852
4595
|
}
|
|
3853
4596
|
),
|
|
3854
|
-
/* @__PURE__ */
|
|
4597
|
+
/* @__PURE__ */ jsxs7("span", { className: "vpg-page-info", children: [
|
|
3855
4598
|
"Page",
|
|
3856
4599
|
" ",
|
|
3857
4600
|
currentPage,
|
|
@@ -3860,13 +4603,13 @@ function DataGrid({
|
|
|
3860
4603
|
" ",
|
|
3861
4604
|
totalPages
|
|
3862
4605
|
] }),
|
|
3863
|
-
/* @__PURE__ */
|
|
4606
|
+
/* @__PURE__ */ jsx7(
|
|
3864
4607
|
"button",
|
|
3865
4608
|
{
|
|
3866
4609
|
className: "vpg-page-btn",
|
|
3867
4610
|
disabled: currentPage === totalPages,
|
|
3868
4611
|
onClick: () => setCurrentPage((p) => Math.min(totalPages, p + 1)),
|
|
3869
|
-
children: /* @__PURE__ */
|
|
4612
|
+
children: /* @__PURE__ */ jsx7("svg", { className: "vpg-icon-sm", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: /* @__PURE__ */ jsx7(
|
|
3870
4613
|
"path",
|
|
3871
4614
|
{
|
|
3872
4615
|
strokeLinecap: "round",
|
|
@@ -3877,13 +4620,13 @@ function DataGrid({
|
|
|
3877
4620
|
) })
|
|
3878
4621
|
}
|
|
3879
4622
|
),
|
|
3880
|
-
/* @__PURE__ */
|
|
4623
|
+
/* @__PURE__ */ jsx7(
|
|
3881
4624
|
"button",
|
|
3882
4625
|
{
|
|
3883
4626
|
className: "vpg-page-btn",
|
|
3884
4627
|
disabled: currentPage === totalPages,
|
|
3885
4628
|
onClick: () => setCurrentPage(totalPages),
|
|
3886
|
-
children: /* @__PURE__ */
|
|
4629
|
+
children: /* @__PURE__ */ jsx7("svg", { className: "vpg-icon-sm", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: /* @__PURE__ */ jsx7(
|
|
3887
4630
|
"path",
|
|
3888
4631
|
{
|
|
3889
4632
|
strokeLinecap: "round",
|
|
@@ -3895,45 +4638,45 @@ function DataGrid({
|
|
|
3895
4638
|
}
|
|
3896
4639
|
)
|
|
3897
4640
|
] }),
|
|
3898
|
-
viewMode === "grid" && selectionStats && selectionStats.count > 1 && /* @__PURE__ */
|
|
3899
|
-
/* @__PURE__ */
|
|
3900
|
-
/* @__PURE__ */
|
|
3901
|
-
/* @__PURE__ */
|
|
4641
|
+
viewMode === "grid" && selectionStats && selectionStats.count > 1 && /* @__PURE__ */ jsxs7("div", { className: "vpg-selection-stats", children: [
|
|
4642
|
+
/* @__PURE__ */ jsxs7("span", { className: "vpg-stat", children: [
|
|
4643
|
+
/* @__PURE__ */ jsx7("span", { className: "vpg-stat-label", children: "Count:" }),
|
|
4644
|
+
/* @__PURE__ */ jsx7("span", { className: "vpg-stat-value", children: selectionStats.count })
|
|
3902
4645
|
] }),
|
|
3903
|
-
selectionStats.numericCount > 0 && /* @__PURE__ */
|
|
3904
|
-
/* @__PURE__ */
|
|
3905
|
-
/* @__PURE__ */
|
|
3906
|
-
/* @__PURE__ */
|
|
3907
|
-
/* @__PURE__ */
|
|
4646
|
+
selectionStats.numericCount > 0 && /* @__PURE__ */ jsxs7(Fragment5, { children: [
|
|
4647
|
+
/* @__PURE__ */ jsx7("span", { className: "vpg-stat-divider", children: "|" }),
|
|
4648
|
+
/* @__PURE__ */ jsxs7("span", { className: "vpg-stat", children: [
|
|
4649
|
+
/* @__PURE__ */ jsx7("span", { className: "vpg-stat-label", children: "Sum:" }),
|
|
4650
|
+
/* @__PURE__ */ jsx7("span", { className: "vpg-stat-value", children: formatStatValue(selectionStats.sum) })
|
|
3908
4651
|
] }),
|
|
3909
|
-
/* @__PURE__ */
|
|
3910
|
-
/* @__PURE__ */
|
|
3911
|
-
/* @__PURE__ */
|
|
3912
|
-
/* @__PURE__ */
|
|
4652
|
+
/* @__PURE__ */ jsx7("span", { className: "vpg-stat-divider", children: "|" }),
|
|
4653
|
+
/* @__PURE__ */ jsxs7("span", { className: "vpg-stat", children: [
|
|
4654
|
+
/* @__PURE__ */ jsx7("span", { className: "vpg-stat-label", children: "Avg:" }),
|
|
4655
|
+
/* @__PURE__ */ jsx7("span", { className: "vpg-stat-value", children: formatStatValue(selectionStats.avg) })
|
|
3913
4656
|
] })
|
|
3914
4657
|
] })
|
|
3915
4658
|
] }),
|
|
3916
|
-
/* @__PURE__ */
|
|
3917
|
-
/* @__PURE__ */
|
|
3918
|
-
/* @__PURE__ */
|
|
3919
|
-
/* @__PURE__ */
|
|
3920
|
-
] }) : showWatermark ? /* @__PURE__ */
|
|
3921
|
-
/* @__PURE__ */
|
|
3922
|
-
/* @__PURE__ */
|
|
3923
|
-
/* @__PURE__ */
|
|
3924
|
-
/* @__PURE__ */
|
|
3925
|
-
/* @__PURE__ */
|
|
4659
|
+
/* @__PURE__ */ jsx7("div", { className: "vpg-footer-right", children: isDemo ? /* @__PURE__ */ jsxs7("div", { className: "vpg-demo-banner", children: [
|
|
4660
|
+
/* @__PURE__ */ jsx7("span", { className: "vpg-demo-badge", children: "DEMO" }),
|
|
4661
|
+
/* @__PURE__ */ jsx7("span", { children: "Pro features enabled" }),
|
|
4662
|
+
/* @__PURE__ */ jsx7("a", { href: "https://tiny-pivot.com/#pricing", target: "_blank", rel: "noopener noreferrer", children: "Get License \u2192" })
|
|
4663
|
+
] }) : showWatermark ? /* @__PURE__ */ jsx7("span", { className: "vpg-watermark-inline", children: /* @__PURE__ */ jsxs7("a", { href: "https://tiny-pivot.com", target: "_blank", rel: "noopener noreferrer", children: [
|
|
4664
|
+
/* @__PURE__ */ jsxs7("svg", { xmlns: "http://www.w3.org/2000/svg", width: "12", height: "12", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: [
|
|
4665
|
+
/* @__PURE__ */ jsx7("rect", { x: "3", y: "3", width: "7", height: "7" }),
|
|
4666
|
+
/* @__PURE__ */ jsx7("rect", { x: "14", y: "3", width: "7", height: "7" }),
|
|
4667
|
+
/* @__PURE__ */ jsx7("rect", { x: "14", y: "14", width: "7", height: "7" }),
|
|
4668
|
+
/* @__PURE__ */ jsx7("rect", { x: "3", y: "14", width: "7", height: "7" })
|
|
3926
4669
|
] }),
|
|
3927
4670
|
"Powered by TinyPivot"
|
|
3928
4671
|
] }) }) : null })
|
|
3929
4672
|
] }),
|
|
3930
|
-
enableVerticalResize && /* @__PURE__ */
|
|
3931
|
-
/* @__PURE__ */
|
|
3932
|
-
/* @__PURE__ */
|
|
3933
|
-
/* @__PURE__ */
|
|
4673
|
+
enableVerticalResize && /* @__PURE__ */ jsx7("div", { className: "vpg-vertical-resize-handle", onMouseDown: startVerticalResize, children: /* @__PURE__ */ jsxs7("div", { className: "vpg-resize-grip", children: [
|
|
4674
|
+
/* @__PURE__ */ jsx7("span", {}),
|
|
4675
|
+
/* @__PURE__ */ jsx7("span", {}),
|
|
4676
|
+
/* @__PURE__ */ jsx7("span", {})
|
|
3934
4677
|
] }) }),
|
|
3935
4678
|
activeFilterColumn && typeof document !== "undefined" && createPortal2(
|
|
3936
|
-
/* @__PURE__ */
|
|
4679
|
+
/* @__PURE__ */ jsx7(
|
|
3937
4680
|
"div",
|
|
3938
4681
|
{
|
|
3939
4682
|
className: "vpg-filter-portal",
|
|
@@ -3944,7 +4687,7 @@ function DataGrid({
|
|
|
3944
4687
|
maxHeight: `${filterDropdownPosition.maxHeight}px`,
|
|
3945
4688
|
zIndex: 9999
|
|
3946
4689
|
},
|
|
3947
|
-
children: /* @__PURE__ */
|
|
4690
|
+
children: /* @__PURE__ */ jsx7(
|
|
3948
4691
|
ColumnFilter,
|
|
3949
4692
|
{
|
|
3950
4693
|
columnId: activeFilterColumn,
|