@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 CHANGED
@@ -1,7 +1,9 @@
1
1
  "use strict";
2
+ var __create = Object.create;
2
3
  var __defProp = Object.defineProperty;
3
4
  var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
5
  var __getOwnPropNames = Object.getOwnPropertyNames;
6
+ var __getProtoOf = Object.getPrototypeOf;
5
7
  var __hasOwnProp = Object.prototype.hasOwnProperty;
6
8
  var __export = (target, all) => {
7
9
  for (var name in all)
@@ -15,6 +17,14 @@ var __copyProps = (to, from, except, desc) => {
15
17
  }
16
18
  return to;
17
19
  };
20
+ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
21
+ // If the importer is in node compatibility mode or this is not an ESM
22
+ // file that has been converted to a CommonJS file using a Babel-
23
+ // compatible transform (i.e. "__esModule" has not been set), then set
24
+ // "default" to the CommonJS "module.exports" for node compatibility.
25
+ isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
26
+ mod
27
+ ));
18
28
  var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
19
29
 
20
30
  // src/index.ts
@@ -29,10 +39,10 @@ __export(index_exports, {
29
39
  enableDemoMode: () => enableDemoMode,
30
40
  exportPivotToCSV: () => exportPivotToCSV,
31
41
  exportToCSV: () => exportToCSV,
32
- formatCellValue: () => import_tinypivot_core2.formatCellValue,
42
+ formatCellValue: () => import_tinypivot_core3.formatCellValue,
33
43
  formatSelectionForClipboard: () => formatSelectionForClipboard,
34
- getAggregationLabel: () => import_tinypivot_core5.getAggregationLabel,
35
- getColumnUniqueValues: () => import_tinypivot_core2.getColumnUniqueValues,
44
+ getAggregationLabel: () => import_tinypivot_core6.getAggregationLabel,
45
+ getColumnUniqueValues: () => import_tinypivot_core3.getColumnUniqueValues,
36
46
  setLicenseKey: () => setLicenseKey,
37
47
  useColumnResize: () => useColumnResize,
38
48
  useExcelGrid: () => useExcelGrid,
@@ -234,21 +244,690 @@ function CalculatedFieldModal({
234
244
  return (0, import_react_dom.createPortal)(modalContent, document.body);
235
245
  }
236
246
 
247
+ // src/components/ChartBuilder.tsx
248
+ var import_tinypivot_core2 = require("@smallwebco/tinypivot-core");
249
+ var import_react2 = require("react");
250
+ var import_react_apexcharts = __toESM(require("react-apexcharts"), 1);
251
+ var import_jsx_runtime2 = require("react/jsx-runtime");
252
+ function ChartBuilder({
253
+ data,
254
+ theme = "light",
255
+ onConfigChange
256
+ }) {
257
+ const [chartConfig, setChartConfig] = (0, import_react2.useState)((0, import_tinypivot_core2.createDefaultChartConfig)());
258
+ const [draggingField, setDraggingField] = (0, import_react2.useState)(null);
259
+ const [dragOverZone, setDragOverZone] = (0, import_react2.useState)(null);
260
+ const fieldInfos = (0, import_react2.useMemo)(() => (0, import_tinypivot_core2.analyzeFieldsForChart)(data), [data]);
261
+ const dimensions = (0, import_react2.useMemo)(
262
+ () => fieldInfos.filter((f) => f.role === "dimension" || f.role === "temporal"),
263
+ [fieldInfos]
264
+ );
265
+ const measures = (0, import_react2.useMemo)(
266
+ () => fieldInfos.filter((f) => f.role === "measure"),
267
+ [fieldInfos]
268
+ );
269
+ const guidance = (0, import_react2.useMemo)(() => (0, import_tinypivot_core2.getChartGuidance)(chartConfig), [chartConfig]);
270
+ const chartIsValid = (0, import_react2.useMemo)(() => (0, import_tinypivot_core2.isChartConfigValid)(chartConfig), [chartConfig]);
271
+ const selectedChartType = (0, import_react2.useMemo)(
272
+ () => import_tinypivot_core2.CHART_TYPES.find((ct) => ct.type === chartConfig.type),
273
+ [chartConfig.type]
274
+ );
275
+ const isScatterType = (0, import_react2.useMemo)(
276
+ () => ["scatter", "bubble"].includes(chartConfig.type),
277
+ [chartConfig.type]
278
+ );
279
+ const isHeatmapType = (0, import_react2.useMemo)(
280
+ () => chartConfig.type === "heatmap",
281
+ [chartConfig.type]
282
+ );
283
+ const zoneLabels = (0, import_react2.useMemo)(() => {
284
+ const type = chartConfig.type;
285
+ switch (type) {
286
+ case "scatter":
287
+ case "bubble":
288
+ return {
289
+ xAxis: "X-Axis (measure)",
290
+ xAxisPlaceholder: "Drop a measure",
291
+ yAxis: "Y-Axis (measure)",
292
+ yAxisPlaceholder: "Drop a measure",
293
+ series: "Color by (optional)",
294
+ seriesPlaceholder: "Group points by dimension",
295
+ showSize: type === "bubble",
296
+ showSeries: true
297
+ };
298
+ case "heatmap":
299
+ return {
300
+ xAxis: "X-Axis (dimension)",
301
+ xAxisPlaceholder: "Drop a dimension",
302
+ yAxis: "Y-Axis (dimension)",
303
+ yAxisPlaceholder: "Drop a dimension",
304
+ series: "Value / Intensity",
305
+ seriesPlaceholder: "Drop a measure for color intensity",
306
+ showSize: false,
307
+ showSeries: true
308
+ };
309
+ case "pie":
310
+ case "donut":
311
+ return {
312
+ xAxis: "Slices (dimension)",
313
+ xAxisPlaceholder: "Drop a dimension",
314
+ yAxis: "Values (measure)",
315
+ yAxisPlaceholder: "Drop a measure",
316
+ series: "",
317
+ seriesPlaceholder: "",
318
+ showSize: false,
319
+ showSeries: false
320
+ };
321
+ case "radar":
322
+ return {
323
+ xAxis: "Axes (dimension)",
324
+ xAxisPlaceholder: "Drop a dimension",
325
+ yAxis: "Values (measure)",
326
+ yAxisPlaceholder: "Drop a measure",
327
+ series: "Compare by (optional)",
328
+ seriesPlaceholder: "Group by dimension",
329
+ showSize: false,
330
+ showSeries: true
331
+ };
332
+ default:
333
+ return {
334
+ xAxis: "X-Axis (dimension)",
335
+ xAxisPlaceholder: "Drop a dimension",
336
+ yAxis: "Y-Axis (measure)",
337
+ yAxisPlaceholder: "Drop a measure",
338
+ series: "Color / Series (optional)",
339
+ seriesPlaceholder: "Group by dimension",
340
+ showSize: false,
341
+ showSeries: true
342
+ };
343
+ }
344
+ }, [chartConfig.type]);
345
+ const handleDragStart = (0, import_react2.useCallback)((field, event) => {
346
+ setDraggingField(field);
347
+ event.dataTransfer?.setData("text/plain", field.field);
348
+ }, []);
349
+ const handleDragEnd = (0, import_react2.useCallback)(() => {
350
+ setDraggingField(null);
351
+ setDragOverZone(null);
352
+ }, []);
353
+ const handleDragOver = (0, import_react2.useCallback)((zone, event) => {
354
+ event.preventDefault();
355
+ setDragOverZone(zone);
356
+ }, []);
357
+ const handleDragLeave = (0, import_react2.useCallback)(() => {
358
+ setDragOverZone(null);
359
+ }, []);
360
+ const handleDrop = (0, import_react2.useCallback)((zone, event) => {
361
+ event.preventDefault();
362
+ setDragOverZone(null);
363
+ if (!draggingField)
364
+ return;
365
+ const field = draggingField;
366
+ const chartField = {
367
+ field: field.field,
368
+ label: field.label,
369
+ role: field.role,
370
+ aggregation: field.role === "measure" ? "sum" : void 0
371
+ };
372
+ let newConfig = { ...chartConfig };
373
+ switch (zone) {
374
+ case "xAxis":
375
+ newConfig = { ...newConfig, xAxis: chartField };
376
+ break;
377
+ case "yAxis":
378
+ newConfig = { ...newConfig, yAxis: chartField };
379
+ break;
380
+ case "series":
381
+ newConfig = { ...newConfig, seriesField: chartField };
382
+ break;
383
+ case "size":
384
+ newConfig = { ...newConfig, sizeField: chartField };
385
+ break;
386
+ case "color":
387
+ newConfig = { ...newConfig, colorField: chartField };
388
+ break;
389
+ }
390
+ setChartConfig(newConfig);
391
+ onConfigChange?.(newConfig);
392
+ }, [chartConfig, draggingField, onConfigChange]);
393
+ const removeField = (0, import_react2.useCallback)((zone) => {
394
+ let newConfig = { ...chartConfig };
395
+ switch (zone) {
396
+ case "xAxis":
397
+ newConfig = { ...newConfig, xAxis: void 0 };
398
+ break;
399
+ case "yAxis":
400
+ newConfig = { ...newConfig, yAxis: void 0 };
401
+ break;
402
+ case "series":
403
+ newConfig = { ...newConfig, seriesField: void 0 };
404
+ break;
405
+ case "size":
406
+ newConfig = { ...newConfig, sizeField: void 0 };
407
+ break;
408
+ case "color":
409
+ newConfig = { ...newConfig, colorField: void 0 };
410
+ break;
411
+ }
412
+ setChartConfig(newConfig);
413
+ onConfigChange?.(newConfig);
414
+ }, [chartConfig, onConfigChange]);
415
+ const selectChartType = (0, import_react2.useCallback)((type) => {
416
+ const newConfig = { ...chartConfig, type };
417
+ setChartConfig(newConfig);
418
+ onConfigChange?.(newConfig);
419
+ }, [chartConfig, onConfigChange]);
420
+ const updateAggregation = (0, import_react2.useCallback)((zone, aggregation) => {
421
+ let field;
422
+ switch (zone) {
423
+ case "xAxis":
424
+ field = chartConfig.xAxis;
425
+ break;
426
+ case "yAxis":
427
+ field = chartConfig.yAxis;
428
+ break;
429
+ case "size":
430
+ field = chartConfig.sizeField;
431
+ break;
432
+ case "color":
433
+ field = chartConfig.colorField;
434
+ break;
435
+ default:
436
+ return;
437
+ }
438
+ if (!field)
439
+ return;
440
+ const updated = { ...field, aggregation };
441
+ let newConfig = { ...chartConfig };
442
+ switch (zone) {
443
+ case "xAxis":
444
+ newConfig = { ...newConfig, xAxis: updated };
445
+ break;
446
+ case "yAxis":
447
+ newConfig = { ...newConfig, yAxis: updated };
448
+ break;
449
+ case "size":
450
+ newConfig = { ...newConfig, sizeField: updated };
451
+ break;
452
+ case "color":
453
+ newConfig = { ...newConfig, colorField: updated };
454
+ break;
455
+ }
456
+ setChartConfig(newConfig);
457
+ onConfigChange?.(newConfig);
458
+ }, [chartConfig, onConfigChange]);
459
+ const getApexChartType = (0, import_react2.useCallback)((type) => {
460
+ const mapping = {
461
+ bar: "bar",
462
+ line: "line",
463
+ area: "area",
464
+ pie: "pie",
465
+ donut: "donut",
466
+ radar: "radar",
467
+ scatter: "scatter",
468
+ bubble: "bubble",
469
+ heatmap: "heatmap"
470
+ };
471
+ return mapping[type] || "bar";
472
+ }, []);
473
+ const formatValue = (0, import_react2.useCallback)((val, format, decimals) => {
474
+ if (val === null || val === void 0)
475
+ return "";
476
+ if (typeof val !== "number")
477
+ return String(val);
478
+ if (Number.isNaN(val))
479
+ return "";
480
+ const dec = decimals ?? 0;
481
+ if (format === "percent") {
482
+ return `${val.toFixed(dec)}%`;
483
+ }
484
+ if (format === "currency") {
485
+ return `$${val.toLocaleString(void 0, { minimumFractionDigits: dec, maximumFractionDigits: dec })}`;
486
+ }
487
+ if (Math.abs(val) >= 1e3) {
488
+ return val.toLocaleString(void 0, { maximumFractionDigits: dec });
489
+ }
490
+ return val.toFixed(dec);
491
+ }, []);
492
+ const chartOptions = (0, import_react2.useMemo)(() => {
493
+ const isDark = theme === "dark";
494
+ const config = chartConfig;
495
+ const options = config.options || {};
496
+ const baseOptions = {
497
+ chart: {
498
+ type: getApexChartType(config.type),
499
+ background: "transparent",
500
+ foreColor: isDark ? "#e2e8f0" : "#334155",
501
+ toolbar: {
502
+ show: true,
503
+ tools: {
504
+ download: true,
505
+ selection: false,
506
+ zoom: options.enableZoom ?? false,
507
+ zoomin: options.enableZoom ?? false,
508
+ zoomout: options.enableZoom ?? false,
509
+ pan: false,
510
+ reset: options.enableZoom ?? false
511
+ },
512
+ export: {
513
+ csv: { filename: "chart-data" },
514
+ svg: { filename: "chart" },
515
+ png: { filename: "chart" }
516
+ }
517
+ },
518
+ animations: {
519
+ enabled: options.animated ?? true,
520
+ speed: 400,
521
+ dynamicAnimation: { enabled: true, speed: 300 }
522
+ },
523
+ fontFamily: "system-ui, -apple-system, sans-serif"
524
+ },
525
+ colors: options.colors || import_tinypivot_core2.CHART_COLORS,
526
+ theme: {
527
+ mode: isDark ? "dark" : "light"
528
+ },
529
+ grid: {
530
+ show: options.showGrid ?? true,
531
+ borderColor: isDark ? "#334155" : "#e2e8f0"
532
+ },
533
+ legend: {
534
+ show: options.showLegend ?? true,
535
+ position: options.legendPosition || "top"
536
+ },
537
+ dataLabels: {
538
+ enabled: options.showDataLabels ?? false
539
+ },
540
+ tooltip: {
541
+ theme: isDark ? "dark" : "light",
542
+ style: {
543
+ fontSize: "12px"
544
+ }
545
+ },
546
+ stroke: {
547
+ curve: "smooth",
548
+ width: config.type === "line" ? 3 : config.type === "area" ? 2 : 0
549
+ },
550
+ fill: {
551
+ opacity: config.type === "area" ? 0.4 : 1
552
+ }
553
+ };
554
+ if (config.xAxis) {
555
+ baseOptions.xaxis = {
556
+ ...baseOptions.xaxis,
557
+ title: { text: options.xAxisTitle || config.xAxis.label },
558
+ labels: {
559
+ style: { colors: isDark ? "#94a3b8" : "#64748b" }
560
+ }
561
+ };
562
+ }
563
+ if (config.yAxis && !["pie", "donut", "radar"].includes(config.type)) {
564
+ baseOptions.yaxis = {
565
+ title: { text: options.yAxisTitle || config.yAxis.label },
566
+ labels: {
567
+ style: { colors: isDark ? "#94a3b8" : "#64748b" },
568
+ formatter: (val) => formatValue(val, options.valueFormat, options.decimals)
569
+ }
570
+ };
571
+ }
572
+ if (options.title) {
573
+ baseOptions.title = {
574
+ text: options.title,
575
+ style: {
576
+ fontSize: "16px",
577
+ fontWeight: "600",
578
+ color: isDark ? "#e2e8f0" : "#334155"
579
+ }
580
+ };
581
+ }
582
+ if (options.stacked && ["bar", "area"].includes(config.type)) {
583
+ baseOptions.chart.stacked = true;
584
+ }
585
+ if (config.type === "pie" || config.type === "donut") {
586
+ baseOptions.plotOptions = {
587
+ pie: {
588
+ donut: {
589
+ size: config.type === "donut" ? "55%" : "0%",
590
+ labels: {
591
+ show: config.type === "donut",
592
+ total: {
593
+ show: true,
594
+ label: "Total",
595
+ formatter: (w) => {
596
+ const total = w.globals.seriesTotals.reduce((a, b) => a + b, 0);
597
+ return formatValue(total, options.valueFormat, options.decimals);
598
+ }
599
+ }
600
+ }
601
+ }
602
+ }
603
+ };
604
+ }
605
+ if (config.type === "radar") {
606
+ baseOptions.plotOptions = {
607
+ radar: {
608
+ polygons: {
609
+ strokeColors: isDark ? "#334155" : "#e2e8f0",
610
+ fill: { colors: isDark ? ["#1e293b", "#0f172a"] : ["#f8fafc", "#f1f5f9"] }
611
+ }
612
+ }
613
+ };
614
+ }
615
+ return baseOptions;
616
+ }, [chartConfig, theme, getApexChartType, formatValue]);
617
+ const chartSeries = (0, import_react2.useMemo)(() => {
618
+ const config = chartConfig;
619
+ if (!chartIsValid)
620
+ return [];
621
+ if (config.type === "pie" || config.type === "donut") {
622
+ const chartData2 = (0, import_tinypivot_core2.processChartDataForPie)(data, config);
623
+ return chartData2.series[0]?.data || [];
624
+ }
625
+ if (config.type === "scatter" || config.type === "bubble") {
626
+ const scatterData = (0, import_tinypivot_core2.processChartDataForScatter)(data, config);
627
+ return scatterData.series;
628
+ }
629
+ if (config.type === "heatmap") {
630
+ const heatmapData = (0, import_tinypivot_core2.processChartDataForHeatmap)(data, config);
631
+ return heatmapData.series;
632
+ }
633
+ const chartData = (0, import_tinypivot_core2.processChartData)(data, config);
634
+ return chartData.series;
635
+ }, [data, chartConfig, chartIsValid]);
636
+ const chartLabels = (0, import_react2.useMemo)(() => {
637
+ const config = chartConfig;
638
+ if (!chartIsValid)
639
+ return [];
640
+ if (config.type === "pie" || config.type === "donut") {
641
+ const chartData2 = (0, import_tinypivot_core2.processChartDataForPie)(data, config);
642
+ return chartData2.categories;
643
+ }
644
+ const chartData = (0, import_tinypivot_core2.processChartData)(data, config);
645
+ return chartData.categories;
646
+ }, [data, chartConfig, chartIsValid]);
647
+ const chartOptionsWithCategories = (0, import_react2.useMemo)(() => {
648
+ const options = { ...chartOptions };
649
+ const config = chartConfig;
650
+ if (!["pie", "donut", "scatter", "bubble", "heatmap"].includes(config.type)) {
651
+ options.xaxis = {
652
+ ...options.xaxis,
653
+ categories: chartLabels
654
+ };
655
+ }
656
+ if (config.type === "pie" || config.type === "donut") {
657
+ options.labels = chartLabels;
658
+ }
659
+ if (config.type === "heatmap") {
660
+ options.chart = {
661
+ ...options.chart,
662
+ type: "heatmap"
663
+ };
664
+ options.xaxis = {
665
+ ...options.xaxis,
666
+ type: "category"
667
+ };
668
+ options.dataLabels = {
669
+ enabled: true,
670
+ style: {
671
+ colors: ["#fff"],
672
+ fontSize: "10px"
673
+ },
674
+ formatter: (val) => {
675
+ if (val === null || val === void 0)
676
+ return "";
677
+ if (typeof val !== "number")
678
+ return String(val);
679
+ if (val >= 1e6)
680
+ return `${(val / 1e6).toFixed(1)}M`;
681
+ if (val >= 1e3)
682
+ return `${(val / 1e3).toFixed(0)}K`;
683
+ return Math.round(val).toLocaleString();
684
+ }
685
+ };
686
+ options.plotOptions = {
687
+ heatmap: {
688
+ shadeIntensity: 0.5,
689
+ radius: 2,
690
+ enableShades: true,
691
+ colorScale: {
692
+ inverse: false
693
+ }
694
+ }
695
+ };
696
+ options.colors = ["#6366f1"];
697
+ options.legend = { show: false };
698
+ }
699
+ return options;
700
+ }, [chartOptions, chartConfig, chartLabels]);
701
+ const getChartIcon = (0, import_react2.useCallback)((type) => {
702
+ const icons = {
703
+ bar: "M3 3v18h18V3H3zm4 14H5v-6h2v6zm4 0H9V7h2v10zm4 0h-2V9h2v8zm4 0h-2v-4h2v4z",
704
+ line: "M3.5 18.5l6-6 4 4 8-8M14.5 8.5h6v6",
705
+ area: "M3 17l6-6 4 4 8-8v10H3z",
706
+ 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",
707
+ 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",
708
+ 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",
709
+ 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",
710
+ heatmap: "M3 3h4v4H3V3zm6 0h4v4H9V3zm6 0h4v4h-4V3zM3 9h4v4H3V9zm6 0h4v4H9V9zm6 0h4v4h-4V9zM3 15h4v4H3v-4zm6 0h4v4H9v-4zm6 0h4v4h-4v-4z",
711
+ 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"
712
+ };
713
+ return icons[type] || icons.bar;
714
+ }, []);
715
+ (0, import_react2.useEffect)(() => {
716
+ onConfigChange?.(chartConfig);
717
+ }, []);
718
+ return /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "vpg-chart-builder", children: [
719
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { className: "vpg-chart-type-bar", children: import_tinypivot_core2.CHART_TYPES.map((ct) => /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(
720
+ "button",
721
+ {
722
+ className: `vpg-chart-type-btn ${chartConfig.type === ct.type ? "active" : ""}`,
723
+ title: ct.description,
724
+ onClick: () => selectChartType(ct.type),
725
+ children: [
726
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("svg", { className: "vpg-icon", viewBox: "0 0 24 24", fill: "currentColor", children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("path", { d: getChartIcon(ct.type) }) }),
727
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: "vpg-chart-type-label", children: ct.label.replace(" Chart", "") })
728
+ ]
729
+ },
730
+ ct.type
731
+ )) }),
732
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "vpg-chart-builder-content", children: [
733
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "vpg-chart-fields-panel", children: [
734
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "vpg-chart-fields-section", children: [
735
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("h4", { className: "vpg-chart-fields-title", children: [
736
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("svg", { className: "vpg-icon-sm", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("path", { d: "M4 6h16M4 12h10M4 18h6" }) }),
737
+ "Dimensions",
738
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: "vpg-chart-fields-hint", children: "(text/date)" })
739
+ ] }),
740
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "vpg-chart-fields-list", children: [
741
+ dimensions.map((field) => /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(
742
+ "div",
743
+ {
744
+ className: "vpg-chart-field-chip vpg-field-dimension",
745
+ draggable: true,
746
+ onDragStart: (e) => handleDragStart(field, e),
747
+ onDragEnd: handleDragEnd,
748
+ children: [
749
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: "vpg-field-name", children: field.label }),
750
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: "vpg-field-type", children: field.role === "temporal" ? "date" : "text" })
751
+ ]
752
+ },
753
+ field.field
754
+ )),
755
+ dimensions.length === 0 && /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { className: "vpg-chart-fields-empty", children: "No dimension fields detected" })
756
+ ] })
757
+ ] }),
758
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "vpg-chart-fields-section", children: [
759
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("h4", { className: "vpg-chart-fields-title", children: [
760
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("svg", { className: "vpg-icon-sm", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("path", { d: "M16 8v8M12 11v5M8 14v2M4 4v16h16" }) }),
761
+ "Measures",
762
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: "vpg-chart-fields-hint", children: "(numbers)" })
763
+ ] }),
764
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "vpg-chart-fields-list", children: [
765
+ measures.map((field) => /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(
766
+ "div",
767
+ {
768
+ className: "vpg-chart-field-chip vpg-field-measure",
769
+ draggable: true,
770
+ onDragStart: (e) => handleDragStart(field, e),
771
+ onDragEnd: handleDragEnd,
772
+ children: [
773
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: "vpg-field-name", children: field.label }),
774
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: "vpg-field-type", children: "#" })
775
+ ]
776
+ },
777
+ field.field
778
+ )),
779
+ measures.length === 0 && /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { className: "vpg-chart-fields-empty", children: "No numeric fields detected" })
780
+ ] })
781
+ ] })
782
+ ] }),
783
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "vpg-chart-config-panel", children: [
784
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "vpg-chart-drop-zone-wrapper", children: [
785
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("label", { className: "vpg-chart-zone-label", children: zoneLabels.xAxis }),
786
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
787
+ "div",
788
+ {
789
+ className: `vpg-chart-drop-zone ${dragOverZone === "xAxis" ? "drag-over" : ""} ${chartConfig.xAxis ? "has-field" : ""}`,
790
+ onDragOver: (e) => handleDragOver("xAxis", e),
791
+ onDragLeave: handleDragLeave,
792
+ onDrop: (e) => handleDrop("xAxis", e),
793
+ children: chartConfig.xAxis ? /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(import_jsx_runtime2.Fragment, { children: [
794
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: "vpg-zone-field-name", children: chartConfig.xAxis.label }),
795
+ isScatterType && chartConfig.xAxis.role === "measure" && /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
796
+ "select",
797
+ {
798
+ className: "vpg-zone-aggregation",
799
+ value: chartConfig.xAxis.aggregation || "sum",
800
+ onChange: (e) => updateAggregation("xAxis", e.target.value),
801
+ children: import_tinypivot_core2.CHART_AGGREGATIONS.map((agg) => /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("option", { value: agg.value, children: agg.symbol }, agg.value))
802
+ }
803
+ ),
804
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("button", { className: "vpg-zone-remove-btn", onClick: () => removeField("xAxis"), children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("svg", { className: "vpg-icon-xs", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("path", { d: "M6 18L18 6M6 6l12 12" }) }) })
805
+ ] }) : /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: "vpg-zone-placeholder", children: zoneLabels.xAxisPlaceholder })
806
+ }
807
+ )
808
+ ] }),
809
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "vpg-chart-drop-zone-wrapper", children: [
810
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("label", { className: "vpg-chart-zone-label", children: zoneLabels.yAxis }),
811
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
812
+ "div",
813
+ {
814
+ className: `vpg-chart-drop-zone ${dragOverZone === "yAxis" ? "drag-over" : ""} ${chartConfig.yAxis ? "has-field" : ""}`,
815
+ onDragOver: (e) => handleDragOver("yAxis", e),
816
+ onDragLeave: handleDragLeave,
817
+ onDrop: (e) => handleDrop("yAxis", e),
818
+ children: chartConfig.yAxis ? /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(import_jsx_runtime2.Fragment, { children: [
819
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: "vpg-zone-field-name", children: chartConfig.yAxis.label }),
820
+ chartConfig.yAxis.role === "measure" && !isHeatmapType && /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
821
+ "select",
822
+ {
823
+ className: "vpg-zone-aggregation",
824
+ value: chartConfig.yAxis.aggregation || "sum",
825
+ onChange: (e) => updateAggregation("yAxis", e.target.value),
826
+ children: import_tinypivot_core2.CHART_AGGREGATIONS.map((agg) => /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("option", { value: agg.value, children: agg.symbol }, agg.value))
827
+ }
828
+ ),
829
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("button", { className: "vpg-zone-remove-btn", onClick: () => removeField("yAxis"), children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("svg", { className: "vpg-icon-xs", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("path", { d: "M6 18L18 6M6 6l12 12" }) }) })
830
+ ] }) : /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: "vpg-zone-placeholder", children: zoneLabels.yAxisPlaceholder })
831
+ }
832
+ )
833
+ ] }),
834
+ zoneLabels.showSeries && /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "vpg-chart-drop-zone-wrapper", children: [
835
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("label", { className: "vpg-chart-zone-label", children: zoneLabels.series }),
836
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
837
+ "div",
838
+ {
839
+ className: `vpg-chart-drop-zone vpg-zone-optional ${dragOverZone === "series" ? "drag-over" : ""} ${(isHeatmapType ? chartConfig.colorField : chartConfig.seriesField) ? "has-field" : ""}`,
840
+ onDragOver: (e) => handleDragOver(isHeatmapType ? "color" : "series", e),
841
+ onDragLeave: handleDragLeave,
842
+ onDrop: (e) => handleDrop(isHeatmapType ? "color" : "series", e),
843
+ children: (isHeatmapType ? chartConfig.colorField : chartConfig.seriesField) ? /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(import_jsx_runtime2.Fragment, { children: [
844
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: "vpg-zone-field-name", children: isHeatmapType ? chartConfig.colorField?.label : chartConfig.seriesField?.label }),
845
+ isHeatmapType && chartConfig.colorField?.role === "measure" && /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
846
+ "select",
847
+ {
848
+ className: "vpg-zone-aggregation",
849
+ value: chartConfig.colorField?.aggregation || "sum",
850
+ onChange: (e) => updateAggregation("color", e.target.value),
851
+ children: import_tinypivot_core2.CHART_AGGREGATIONS.map((agg) => /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("option", { value: agg.value, children: agg.symbol }, agg.value))
852
+ }
853
+ ),
854
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("button", { className: "vpg-zone-remove-btn", onClick: () => removeField(isHeatmapType ? "color" : "series"), children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("svg", { className: "vpg-icon-xs", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("path", { d: "M6 18L18 6M6 6l12 12" }) }) })
855
+ ] }) : /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: "vpg-zone-placeholder", children: zoneLabels.seriesPlaceholder })
856
+ }
857
+ )
858
+ ] }),
859
+ zoneLabels.showSize && /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "vpg-chart-drop-zone-wrapper", children: [
860
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("label", { className: "vpg-chart-zone-label", children: "Size (number)" }),
861
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
862
+ "div",
863
+ {
864
+ className: `vpg-chart-drop-zone vpg-zone-optional ${dragOverZone === "size" ? "drag-over" : ""} ${chartConfig.sizeField ? "has-field" : ""}`,
865
+ onDragOver: (e) => handleDragOver("size", e),
866
+ onDragLeave: handleDragLeave,
867
+ onDrop: (e) => handleDrop("size", e),
868
+ children: chartConfig.sizeField ? /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(import_jsx_runtime2.Fragment, { children: [
869
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: "vpg-zone-field-name", children: chartConfig.sizeField.label }),
870
+ chartConfig.sizeField.role === "measure" && /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
871
+ "select",
872
+ {
873
+ className: "vpg-zone-aggregation",
874
+ value: chartConfig.sizeField.aggregation || "sum",
875
+ onChange: (e) => updateAggregation("size", e.target.value),
876
+ children: import_tinypivot_core2.CHART_AGGREGATIONS.map((agg) => /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("option", { value: agg.value, children: agg.symbol }, agg.value))
877
+ }
878
+ ),
879
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("button", { className: "vpg-zone-remove-btn", onClick: () => removeField("size"), children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("svg", { className: "vpg-icon-xs", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("path", { d: "M6 18L18 6M6 6l12 12" }) }) })
880
+ ] }) : /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: "vpg-zone-placeholder", children: "Drop a number for bubble size" })
881
+ }
882
+ )
883
+ ] }),
884
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "vpg-chart-guidance", children: [
885
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("svg", { className: "vpg-icon-sm", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", children: [
886
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("circle", { cx: "12", cy: "12", r: "10" }),
887
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("path", { d: "M12 16v-4M12 8h.01" })
888
+ ] }),
889
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { children: guidance })
890
+ ] })
891
+ ] }),
892
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { className: "vpg-chart-preview-panel", children: chartIsValid ? /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { className: "vpg-chart-container", children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
893
+ import_react_apexcharts.default,
894
+ {
895
+ type: getApexChartType(chartConfig.type),
896
+ options: chartOptionsWithCategories,
897
+ series: chartSeries,
898
+ height: "100%"
899
+ },
900
+ `${chartConfig.type}-${JSON.stringify(chartConfig.xAxis)}-${JSON.stringify(chartConfig.yAxis)}`
901
+ ) }) : /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "vpg-chart-empty-state", children: [
902
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("svg", { className: "vpg-icon-lg", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "1.5", children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("path", { d: getChartIcon(chartConfig.type) }) }),
903
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("h3", { children: "Build your chart" }),
904
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("p", { children: "Drag fields from the left panel to configure your visualization" }),
905
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "vpg-chart-hint", children: [
906
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("strong", { children: selectedChartType?.label }),
907
+ ":",
908
+ " ",
909
+ selectedChartType?.description
910
+ ] })
911
+ ] }) })
912
+ ] })
913
+ ] });
914
+ }
915
+
237
916
  // src/components/ColumnFilter.tsx
238
- var import_react3 = require("react");
917
+ var import_react4 = require("react");
239
918
 
240
919
  // src/components/NumericRangeFilter.tsx
241
- var import_react2 = require("react");
242
- var import_jsx_runtime2 = require("react/jsx-runtime");
920
+ var import_react3 = require("react");
921
+ var import_jsx_runtime3 = require("react/jsx-runtime");
243
922
  function NumericRangeFilter({
244
923
  dataMin,
245
924
  dataMax,
246
925
  currentRange,
247
926
  onChange
248
927
  }) {
249
- const [localMin, setLocalMin] = (0, import_react2.useState)(currentRange?.min ?? null);
250
- const [localMax, setLocalMax] = (0, import_react2.useState)(currentRange?.max ?? null);
251
- const step = (0, import_react2.useMemo)(() => {
928
+ const [localMin, setLocalMin] = (0, import_react3.useState)(currentRange?.min ?? null);
929
+ const [localMax, setLocalMax] = (0, import_react3.useState)(currentRange?.max ?? null);
930
+ const step = (0, import_react3.useMemo)(() => {
252
931
  const range = dataMax - dataMin;
253
932
  if (range === 0)
254
933
  return 1;
@@ -262,7 +941,7 @@ function NumericRangeFilter({
262
941
  return 10;
263
942
  return 10 ** (Math.floor(Math.log10(range)) - 2);
264
943
  }, [dataMin, dataMax]);
265
- const formatValue = (0, import_react2.useCallback)((val) => {
944
+ const formatValue = (0, import_react3.useCallback)((val) => {
266
945
  if (val === null)
267
946
  return "";
268
947
  if (Number.isInteger(val))
@@ -270,17 +949,17 @@ function NumericRangeFilter({
270
949
  return val.toLocaleString(void 0, { maximumFractionDigits: 2 });
271
950
  }, []);
272
951
  const isFilterActive = localMin !== null || localMax !== null;
273
- const minPercent = (0, import_react2.useMemo)(() => {
952
+ const minPercent = (0, import_react3.useMemo)(() => {
274
953
  if (localMin === null || dataMax === dataMin)
275
954
  return 0;
276
955
  return (localMin - dataMin) / (dataMax - dataMin) * 100;
277
956
  }, [localMin, dataMin, dataMax]);
278
- const maxPercent = (0, import_react2.useMemo)(() => {
957
+ const maxPercent = (0, import_react3.useMemo)(() => {
279
958
  if (localMax === null || dataMax === dataMin)
280
959
  return 100;
281
960
  return (localMax - dataMin) / (dataMax - dataMin) * 100;
282
961
  }, [localMax, dataMin, dataMax]);
283
- const handleMinSlider = (0, import_react2.useCallback)((event) => {
962
+ const handleMinSlider = (0, import_react3.useCallback)((event) => {
284
963
  const value = Number.parseFloat(event.target.value);
285
964
  setLocalMin(() => {
286
965
  if (localMax !== null && value > localMax) {
@@ -289,7 +968,7 @@ function NumericRangeFilter({
289
968
  return value;
290
969
  });
291
970
  }, [localMax]);
292
- const handleMaxSlider = (0, import_react2.useCallback)((event) => {
971
+ const handleMaxSlider = (0, import_react3.useCallback)((event) => {
293
972
  const value = Number.parseFloat(event.target.value);
294
973
  setLocalMax(() => {
295
974
  if (localMin !== null && value < localMin) {
@@ -298,14 +977,14 @@ function NumericRangeFilter({
298
977
  return value;
299
978
  });
300
979
  }, [localMin]);
301
- const handleSliderChange = (0, import_react2.useCallback)(() => {
980
+ const handleSliderChange = (0, import_react3.useCallback)(() => {
302
981
  if (localMin === null && localMax === null) {
303
982
  onChange(null);
304
983
  } else {
305
984
  onChange({ min: localMin, max: localMax });
306
985
  }
307
986
  }, [localMin, localMax, onChange]);
308
- const handleMinInput = (0, import_react2.useCallback)((event) => {
987
+ const handleMinInput = (0, import_react3.useCallback)((event) => {
309
988
  const value = event.target.value === "" ? null : Number.parseFloat(event.target.value);
310
989
  if (value !== null && !Number.isNaN(value)) {
311
990
  setLocalMin(Math.max(dataMin, Math.min(value, localMax ?? dataMax)));
@@ -313,7 +992,7 @@ function NumericRangeFilter({
313
992
  setLocalMin(null);
314
993
  }
315
994
  }, [dataMin, dataMax, localMax]);
316
- const handleMaxInput = (0, import_react2.useCallback)((event) => {
995
+ const handleMaxInput = (0, import_react3.useCallback)((event) => {
317
996
  const value = event.target.value === "" ? null : Number.parseFloat(event.target.value);
318
997
  if (value !== null && !Number.isNaN(value)) {
319
998
  setLocalMax(Math.min(dataMax, Math.max(value, localMin ?? dataMin)));
@@ -321,39 +1000,39 @@ function NumericRangeFilter({
321
1000
  setLocalMax(null);
322
1001
  }
323
1002
  }, [dataMin, dataMax, localMin]);
324
- const handleInputBlur = (0, import_react2.useCallback)(() => {
1003
+ const handleInputBlur = (0, import_react3.useCallback)(() => {
325
1004
  if (localMin === null && localMax === null) {
326
1005
  onChange(null);
327
1006
  } else {
328
1007
  onChange({ min: localMin, max: localMax });
329
1008
  }
330
1009
  }, [localMin, localMax, onChange]);
331
- const clearFilter = (0, import_react2.useCallback)(() => {
1010
+ const clearFilter = (0, import_react3.useCallback)(() => {
332
1011
  setLocalMin(null);
333
1012
  setLocalMax(null);
334
1013
  onChange(null);
335
1014
  }, [onChange]);
336
- const setFullRange = (0, import_react2.useCallback)(() => {
1015
+ const setFullRange = (0, import_react3.useCallback)(() => {
337
1016
  setLocalMin(dataMin);
338
1017
  setLocalMax(dataMax);
339
1018
  onChange({ min: dataMin, max: dataMax });
340
1019
  }, [dataMin, dataMax, onChange]);
341
- (0, import_react2.useEffect)(() => {
1020
+ (0, import_react3.useEffect)(() => {
342
1021
  setLocalMin(currentRange?.min ?? null);
343
1022
  setLocalMax(currentRange?.max ?? null);
344
1023
  }, [currentRange]);
345
- return /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "vpg-range-filter", children: [
346
- /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "vpg-range-info", children: [
347
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: "vpg-range-label", children: "Data range:" }),
348
- /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("span", { className: "vpg-range-bounds", children: [
1024
+ return /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { className: "vpg-range-filter", children: [
1025
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { className: "vpg-range-info", children: [
1026
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("span", { className: "vpg-range-label", children: "Data range:" }),
1027
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("span", { className: "vpg-range-bounds", children: [
349
1028
  formatValue(dataMin),
350
1029
  " ",
351
1030
  "\u2013",
352
1031
  formatValue(dataMax)
353
1032
  ] })
354
1033
  ] }),
355
- /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "vpg-slider-container", children: [
356
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { className: "vpg-slider-track", children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
1034
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { className: "vpg-slider-container", children: [
1035
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("div", { className: "vpg-slider-track", children: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
357
1036
  "div",
358
1037
  {
359
1038
  className: "vpg-slider-fill",
@@ -363,7 +1042,7 @@ function NumericRangeFilter({
363
1042
  }
364
1043
  }
365
1044
  ) }),
366
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
1045
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
367
1046
  "input",
368
1047
  {
369
1048
  type: "range",
@@ -377,7 +1056,7 @@ function NumericRangeFilter({
377
1056
  onTouchEnd: handleSliderChange
378
1057
  }
379
1058
  ),
380
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
1059
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
381
1060
  "input",
382
1061
  {
383
1062
  type: "range",
@@ -392,10 +1071,10 @@ function NumericRangeFilter({
392
1071
  }
393
1072
  )
394
1073
  ] }),
395
- /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "vpg-range-inputs", children: [
396
- /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "vpg-input-group", children: [
397
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("label", { className: "vpg-input-label", children: "Min" }),
398
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
1074
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { className: "vpg-range-inputs", children: [
1075
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { className: "vpg-input-group", children: [
1076
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("label", { className: "vpg-input-label", children: "Min" }),
1077
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
399
1078
  "input",
400
1079
  {
401
1080
  type: "number",
@@ -408,10 +1087,10 @@ function NumericRangeFilter({
408
1087
  }
409
1088
  )
410
1089
  ] }),
411
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: "vpg-input-separator", children: "to" }),
412
- /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "vpg-input-group", children: [
413
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("label", { className: "vpg-input-label", children: "Max" }),
414
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
1090
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("span", { className: "vpg-input-separator", children: "to" }),
1091
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { className: "vpg-input-group", children: [
1092
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("label", { className: "vpg-input-label", children: "Max" }),
1093
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
415
1094
  "input",
416
1095
  {
417
1096
  type: "number",
@@ -425,15 +1104,15 @@ function NumericRangeFilter({
425
1104
  )
426
1105
  ] })
427
1106
  ] }),
428
- /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "vpg-range-actions", children: [
429
- /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(
1107
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { className: "vpg-range-actions", children: [
1108
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(
430
1109
  "button",
431
1110
  {
432
1111
  className: "vpg-range-btn",
433
1112
  disabled: !isFilterActive,
434
1113
  onClick: clearFilter,
435
1114
  children: [
436
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("svg", { className: "vpg-icon-xs", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
1115
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("svg", { className: "vpg-icon-xs", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
437
1116
  "path",
438
1117
  {
439
1118
  strokeLinecap: "round",
@@ -446,8 +1125,8 @@ function NumericRangeFilter({
446
1125
  ]
447
1126
  }
448
1127
  ),
449
- /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("button", { className: "vpg-range-btn", onClick: setFullRange, children: [
450
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("svg", { className: "vpg-icon-xs", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
1128
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("button", { className: "vpg-range-btn", onClick: setFullRange, children: [
1129
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("svg", { className: "vpg-icon-xs", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
451
1130
  "path",
452
1131
  {
453
1132
  strokeLinecap: "round",
@@ -459,8 +1138,8 @@ function NumericRangeFilter({
459
1138
  "Full Range"
460
1139
  ] })
461
1140
  ] }),
462
- isFilterActive && /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "vpg-filter-summary", children: [
463
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("svg", { className: "vpg-icon-xs", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
1141
+ isFilterActive && /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { className: "vpg-filter-summary", children: [
1142
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("svg", { className: "vpg-icon-xs", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
464
1143
  "path",
465
1144
  {
466
1145
  strokeLinecap: "round",
@@ -469,15 +1148,15 @@ function NumericRangeFilter({
469
1148
  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"
470
1149
  }
471
1150
  ) }),
472
- /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("span", { children: [
1151
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("span", { children: [
473
1152
  "Showing values",
474
1153
  " ",
475
- localMin !== null && /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("strong", { children: [
1154
+ localMin !== null && /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("strong", { children: [
476
1155
  "\u2265",
477
1156
  formatValue(localMin)
478
1157
  ] }),
479
1158
  localMin !== null && localMax !== null && " and ",
480
- localMax !== null && /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("strong", { children: [
1159
+ localMax !== null && /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("strong", { children: [
481
1160
  "\u2264",
482
1161
  formatValue(localMax)
483
1162
  ] })
@@ -487,7 +1166,7 @@ function NumericRangeFilter({
487
1166
  }
488
1167
 
489
1168
  // src/components/ColumnFilter.tsx
490
- var import_jsx_runtime3 = require("react/jsx-runtime");
1169
+ var import_jsx_runtime4 = require("react/jsx-runtime");
491
1170
  function ColumnFilter({
492
1171
  columnName,
493
1172
  stats,
@@ -499,33 +1178,33 @@ function ColumnFilter({
499
1178
  onClose,
500
1179
  onRangeFilter
501
1180
  }) {
502
- const [searchQuery, setSearchQuery] = (0, import_react3.useState)("");
503
- const [localSelected, setLocalSelected] = (0, import_react3.useState)(new Set(selectedValues));
504
- const dropdownRef = (0, import_react3.useRef)(null);
505
- const searchInputRef = (0, import_react3.useRef)(null);
1181
+ const [searchQuery, setSearchQuery] = (0, import_react4.useState)("");
1182
+ const [localSelected, setLocalSelected] = (0, import_react4.useState)(new Set(selectedValues));
1183
+ const dropdownRef = (0, import_react4.useRef)(null);
1184
+ const searchInputRef = (0, import_react4.useRef)(null);
506
1185
  const isNumericColumn = stats.type === "number" && stats.numericMin !== void 0 && stats.numericMax !== void 0;
507
- const [filterMode, setFilterMode] = (0, import_react3.useState)(numericRange ? "range" : "values");
508
- const [localRange, setLocalRange] = (0, import_react3.useState)(numericRange ?? null);
1186
+ const [filterMode, setFilterMode] = (0, import_react4.useState)(numericRange ? "range" : "values");
1187
+ const [localRange, setLocalRange] = (0, import_react4.useState)(numericRange ?? null);
509
1188
  const hasBlankValues = stats.nullCount > 0;
510
- const filteredValues = (0, import_react3.useMemo)(() => {
1189
+ const filteredValues = (0, import_react4.useMemo)(() => {
511
1190
  const values = stats.uniqueValues;
512
1191
  if (!searchQuery)
513
1192
  return values;
514
1193
  const query = searchQuery.toLowerCase();
515
1194
  return values.filter((v) => v.toLowerCase().includes(query));
516
1195
  }, [stats.uniqueValues, searchQuery]);
517
- const allValues = (0, import_react3.useMemo)(() => {
1196
+ const allValues = (0, import_react4.useMemo)(() => {
518
1197
  const values = [...filteredValues];
519
1198
  if (hasBlankValues && (!searchQuery || "(blank)".includes(searchQuery.toLowerCase()))) {
520
1199
  values.unshift("(blank)");
521
1200
  }
522
1201
  return values;
523
1202
  }, [filteredValues, hasBlankValues, searchQuery]);
524
- const _isAllSelected = (0, import_react3.useMemo)(
1203
+ const _isAllSelected = (0, import_react4.useMemo)(
525
1204
  () => allValues.every((v) => localSelected.has(v)),
526
1205
  [allValues, localSelected]
527
1206
  );
528
- const toggleValue = (0, import_react3.useCallback)((value) => {
1207
+ const toggleValue = (0, import_react4.useCallback)((value) => {
529
1208
  setLocalSelected((prev) => {
530
1209
  const next = new Set(prev);
531
1210
  if (next.has(value)) {
@@ -536,7 +1215,7 @@ function ColumnFilter({
536
1215
  return next;
537
1216
  });
538
1217
  }, []);
539
- const selectAll = (0, import_react3.useCallback)(() => {
1218
+ const selectAll = (0, import_react4.useCallback)(() => {
540
1219
  setLocalSelected((prev) => {
541
1220
  const next = new Set(prev);
542
1221
  for (const value of allValues) {
@@ -545,10 +1224,10 @@ function ColumnFilter({
545
1224
  return next;
546
1225
  });
547
1226
  }, [allValues]);
548
- const clearAll = (0, import_react3.useCallback)(() => {
1227
+ const clearAll = (0, import_react4.useCallback)(() => {
549
1228
  setLocalSelected(/* @__PURE__ */ new Set());
550
1229
  }, []);
551
- const applyFilter = (0, import_react3.useCallback)(() => {
1230
+ const applyFilter = (0, import_react4.useCallback)(() => {
552
1231
  if (localSelected.size === 0) {
553
1232
  onFilter([]);
554
1233
  } else {
@@ -556,30 +1235,30 @@ function ColumnFilter({
556
1235
  }
557
1236
  onClose();
558
1237
  }, [localSelected, onFilter, onClose]);
559
- const sortAscending = (0, import_react3.useCallback)(() => {
1238
+ const sortAscending = (0, import_react4.useCallback)(() => {
560
1239
  onSort(sortDirection === "asc" ? null : "asc");
561
1240
  }, [sortDirection, onSort]);
562
- const sortDescending = (0, import_react3.useCallback)(() => {
1241
+ const sortDescending = (0, import_react4.useCallback)(() => {
563
1242
  onSort(sortDirection === "desc" ? null : "desc");
564
1243
  }, [sortDirection, onSort]);
565
- const clearFilter = (0, import_react3.useCallback)(() => {
1244
+ const clearFilter = (0, import_react4.useCallback)(() => {
566
1245
  setLocalSelected(/* @__PURE__ */ new Set());
567
1246
  onFilter([]);
568
1247
  onClose();
569
1248
  }, [onFilter, onClose]);
570
- const handleRangeChange = (0, import_react3.useCallback)((range) => {
1249
+ const handleRangeChange = (0, import_react4.useCallback)((range) => {
571
1250
  setLocalRange(range);
572
1251
  }, []);
573
- const applyRangeFilter = (0, import_react3.useCallback)(() => {
1252
+ const applyRangeFilter = (0, import_react4.useCallback)(() => {
574
1253
  onRangeFilter?.(localRange);
575
1254
  onClose();
576
1255
  }, [localRange, onRangeFilter, onClose]);
577
- const clearRangeFilter = (0, import_react3.useCallback)(() => {
1256
+ const clearRangeFilter = (0, import_react4.useCallback)(() => {
578
1257
  setLocalRange(null);
579
1258
  onRangeFilter?.(null);
580
1259
  onClose();
581
1260
  }, [onRangeFilter, onClose]);
582
- (0, import_react3.useEffect)(() => {
1261
+ (0, import_react4.useEffect)(() => {
583
1262
  const handleClickOutside = (event) => {
584
1263
  if (dropdownRef.current && !dropdownRef.current.contains(event.target)) {
585
1264
  onClose();
@@ -588,7 +1267,7 @@ function ColumnFilter({
588
1267
  document.addEventListener("mousedown", handleClickOutside);
589
1268
  return () => document.removeEventListener("mousedown", handleClickOutside);
590
1269
  }, [onClose]);
591
- (0, import_react3.useEffect)(() => {
1270
+ (0, import_react4.useEffect)(() => {
592
1271
  const handleKeydown = (event) => {
593
1272
  if (event.key === "Escape") {
594
1273
  onClose();
@@ -599,36 +1278,36 @@ function ColumnFilter({
599
1278
  document.addEventListener("keydown", handleKeydown);
600
1279
  return () => document.removeEventListener("keydown", handleKeydown);
601
1280
  }, [onClose, applyFilter]);
602
- (0, import_react3.useEffect)(() => {
1281
+ (0, import_react4.useEffect)(() => {
603
1282
  searchInputRef.current?.focus();
604
1283
  }, []);
605
- (0, import_react3.useEffect)(() => {
1284
+ (0, import_react4.useEffect)(() => {
606
1285
  setLocalSelected(new Set(selectedValues));
607
1286
  }, [selectedValues]);
608
- (0, import_react3.useEffect)(() => {
1287
+ (0, import_react4.useEffect)(() => {
609
1288
  setLocalRange(numericRange ?? null);
610
1289
  if (numericRange) {
611
1290
  setFilterMode("range");
612
1291
  }
613
1292
  }, [numericRange]);
614
- return /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { ref: dropdownRef, className: "vpg-filter-dropdown", children: [
615
- /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { className: "vpg-filter-header", children: [
616
- /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("span", { className: "vpg-filter-title", children: columnName }),
617
- /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("span", { className: "vpg-filter-count", children: [
1293
+ return /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { ref: dropdownRef, className: "vpg-filter-dropdown", children: [
1294
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { className: "vpg-filter-header", children: [
1295
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("span", { className: "vpg-filter-title", children: columnName }),
1296
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("span", { className: "vpg-filter-count", children: [
618
1297
  stats.uniqueValues.length.toLocaleString(),
619
1298
  " ",
620
1299
  "unique"
621
1300
  ] })
622
1301
  ] }),
623
- /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { className: "vpg-sort-controls", children: [
624
- /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(
1302
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { className: "vpg-sort-controls", children: [
1303
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(
625
1304
  "button",
626
1305
  {
627
1306
  className: `vpg-sort-btn ${sortDirection === "asc" ? "active" : ""}`,
628
1307
  title: isNumericColumn ? "Sort Low to High" : "Sort A to Z",
629
1308
  onClick: sortAscending,
630
1309
  children: [
631
- /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("svg", { className: "vpg-icon-sm", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
1310
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("svg", { className: "vpg-icon-sm", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
632
1311
  "path",
633
1312
  {
634
1313
  strokeLinecap: "round",
@@ -637,18 +1316,18 @@ function ColumnFilter({
637
1316
  d: "M3 4h13M3 8h9m-9 4h6m4 0l4-4m0 0l4 4m-4-4v12"
638
1317
  }
639
1318
  ) }),
640
- /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("span", { children: isNumericColumn ? "1\u21929" : "A\u2192Z" })
1319
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("span", { children: isNumericColumn ? "1\u21929" : "A\u2192Z" })
641
1320
  ]
642
1321
  }
643
1322
  ),
644
- /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(
1323
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(
645
1324
  "button",
646
1325
  {
647
1326
  className: `vpg-sort-btn ${sortDirection === "desc" ? "active" : ""}`,
648
1327
  title: isNumericColumn ? "Sort High to Low" : "Sort Z to A",
649
1328
  onClick: sortDescending,
650
1329
  children: [
651
- /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("svg", { className: "vpg-icon-sm", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
1330
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("svg", { className: "vpg-icon-sm", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
652
1331
  "path",
653
1332
  {
654
1333
  strokeLinecap: "round",
@@ -657,20 +1336,20 @@ function ColumnFilter({
657
1336
  d: "M3 4h13M3 8h9m-9 4h9m5-4v12m0 0l-4-4m4 4l4-4"
658
1337
  }
659
1338
  ) }),
660
- /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("span", { children: isNumericColumn ? "9\u21921" : "Z\u2192A" })
1339
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("span", { children: isNumericColumn ? "9\u21921" : "Z\u2192A" })
661
1340
  ]
662
1341
  }
663
1342
  )
664
1343
  ] }),
665
- /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("div", { className: "vpg-divider" }),
666
- isNumericColumn && /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { className: "vpg-filter-tabs", children: [
667
- /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(
1344
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("div", { className: "vpg-divider" }),
1345
+ isNumericColumn && /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { className: "vpg-filter-tabs", children: [
1346
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(
668
1347
  "button",
669
1348
  {
670
1349
  className: `vpg-tab-btn ${filterMode === "values" ? "active" : ""}`,
671
1350
  onClick: () => setFilterMode("values"),
672
1351
  children: [
673
- /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("svg", { className: "vpg-icon-sm", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
1352
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("svg", { className: "vpg-icon-sm", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
674
1353
  "path",
675
1354
  {
676
1355
  strokeLinecap: "round",
@@ -683,13 +1362,13 @@ function ColumnFilter({
683
1362
  ]
684
1363
  }
685
1364
  ),
686
- /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(
1365
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(
687
1366
  "button",
688
1367
  {
689
1368
  className: `vpg-tab-btn ${filterMode === "range" ? "active" : ""}`,
690
1369
  onClick: () => setFilterMode("range"),
691
1370
  children: [
692
- /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("svg", { className: "vpg-icon-sm", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
1371
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("svg", { className: "vpg-icon-sm", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
693
1372
  "path",
694
1373
  {
695
1374
  strokeLinecap: "round",
@@ -703,9 +1382,9 @@ function ColumnFilter({
703
1382
  }
704
1383
  )
705
1384
  ] }),
706
- (!isNumericColumn || filterMode === "values") && /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(import_jsx_runtime3.Fragment, { children: [
707
- /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { className: "vpg-search-container", children: [
708
- /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("svg", { className: "vpg-search-icon", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
1385
+ (!isNumericColumn || filterMode === "values") && /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(import_jsx_runtime4.Fragment, { children: [
1386
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { className: "vpg-search-container", children: [
1387
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("svg", { className: "vpg-search-icon", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
709
1388
  "path",
710
1389
  {
711
1390
  strokeLinecap: "round",
@@ -714,7 +1393,7 @@ function ColumnFilter({
714
1393
  d: "M21 21l-6-6m2-5a7 7 0 11-14 0 7 7 0 0114 0z"
715
1394
  }
716
1395
  ) }),
717
- /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
1396
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
718
1397
  "input",
719
1398
  {
720
1399
  ref: searchInputRef,
@@ -725,11 +1404,11 @@ function ColumnFilter({
725
1404
  className: "vpg-search-input"
726
1405
  }
727
1406
  ),
728
- searchQuery && /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("button", { className: "vpg-clear-search", onClick: () => setSearchQuery(""), children: "\xD7" })
1407
+ searchQuery && /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("button", { className: "vpg-clear-search", onClick: () => setSearchQuery(""), children: "\xD7" })
729
1408
  ] }),
730
- /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { className: "vpg-bulk-actions", children: [
731
- /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("button", { className: "vpg-bulk-btn", onClick: selectAll, children: [
732
- /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("svg", { className: "vpg-icon-sm", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
1409
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { className: "vpg-bulk-actions", children: [
1410
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("button", { className: "vpg-bulk-btn", onClick: selectAll, children: [
1411
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("svg", { className: "vpg-icon-sm", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
733
1412
  "path",
734
1413
  {
735
1414
  strokeLinecap: "round",
@@ -740,8 +1419,8 @@ function ColumnFilter({
740
1419
  ) }),
741
1420
  "Select All"
742
1421
  ] }),
743
- /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("button", { className: "vpg-bulk-btn", onClick: clearAll, children: [
744
- /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("svg", { className: "vpg-icon-sm", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
1422
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("button", { className: "vpg-bulk-btn", onClick: clearAll, children: [
1423
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("svg", { className: "vpg-icon-sm", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
745
1424
  "path",
746
1425
  {
747
1426
  strokeLinecap: "round",
@@ -753,13 +1432,13 @@ function ColumnFilter({
753
1432
  "Clear All"
754
1433
  ] })
755
1434
  ] }),
756
- /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { className: "vpg-values-list", children: [
757
- allValues.map((value) => /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(
1435
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { className: "vpg-values-list", children: [
1436
+ allValues.map((value) => /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(
758
1437
  "label",
759
1438
  {
760
1439
  className: `vpg-value-item ${localSelected.has(value) ? "selected" : ""}`,
761
1440
  children: [
762
- /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
1441
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
763
1442
  "input",
764
1443
  {
765
1444
  type: "checkbox",
@@ -768,20 +1447,20 @@ function ColumnFilter({
768
1447
  className: "vpg-value-checkbox"
769
1448
  }
770
1449
  ),
771
- /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("span", { className: `vpg-value-text ${value === "(blank)" ? "vpg-blank" : ""}`, children: value })
1450
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("span", { className: `vpg-value-text ${value === "(blank)" ? "vpg-blank" : ""}`, children: value })
772
1451
  ]
773
1452
  },
774
1453
  value
775
1454
  )),
776
- allValues.length === 0 && /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("div", { className: "vpg-no-results", children: "No matching values" })
1455
+ allValues.length === 0 && /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("div", { className: "vpg-no-results", children: "No matching values" })
777
1456
  ] }),
778
- /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { className: "vpg-filter-footer", children: [
779
- /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("button", { className: "vpg-btn-clear", onClick: clearFilter, children: "Clear Filter" }),
780
- /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("button", { className: "vpg-btn-apply", onClick: applyFilter, children: "Apply" })
1457
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { className: "vpg-filter-footer", children: [
1458
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("button", { className: "vpg-btn-clear", onClick: clearFilter, children: "Clear Filter" }),
1459
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("button", { className: "vpg-btn-apply", onClick: applyFilter, children: "Apply" })
781
1460
  ] })
782
1461
  ] }),
783
- isNumericColumn && filterMode === "range" && /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(import_jsx_runtime3.Fragment, { children: [
784
- /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
1462
+ isNumericColumn && filterMode === "range" && /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(import_jsx_runtime4.Fragment, { children: [
1463
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
785
1464
  NumericRangeFilter,
786
1465
  {
787
1466
  dataMin: stats.numericMin,
@@ -790,26 +1469,26 @@ function ColumnFilter({
790
1469
  onChange: handleRangeChange
791
1470
  }
792
1471
  ),
793
- /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { className: "vpg-filter-footer", children: [
794
- /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("button", { className: "vpg-btn-clear", onClick: clearRangeFilter, children: "Clear Filter" }),
795
- /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("button", { className: "vpg-btn-apply", onClick: applyRangeFilter, children: "Apply" })
1472
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { className: "vpg-filter-footer", children: [
1473
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("button", { className: "vpg-btn-clear", onClick: clearRangeFilter, children: "Clear Filter" }),
1474
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("button", { className: "vpg-btn-apply", onClick: applyRangeFilter, children: "Apply" })
796
1475
  ] })
797
1476
  ] })
798
1477
  ] });
799
1478
  }
800
1479
 
801
1480
  // src/components/DataGrid.tsx
802
- var import_react10 = require("react");
1481
+ var import_react11 = require("react");
803
1482
  var import_react_dom2 = require("react-dom");
804
1483
 
805
1484
  // src/hooks/useExcelGrid.ts
806
- var import_tinypivot_core2 = require("@smallwebco/tinypivot-core");
1485
+ var import_tinypivot_core3 = require("@smallwebco/tinypivot-core");
807
1486
  var import_react_table = require("@tanstack/react-table");
808
- var import_react4 = require("react");
1487
+ var import_react5 = require("react");
809
1488
  var multiSelectFilter = (row, columnId, filterValue) => {
810
1489
  if (!filterValue)
811
1490
  return true;
812
- if ((0, import_tinypivot_core2.isNumericRange)(filterValue)) {
1491
+ if ((0, import_tinypivot_core3.isNumericRange)(filterValue)) {
813
1492
  const cellValue = row.getValue(columnId);
814
1493
  if (cellValue === null || cellValue === void 0 || cellValue === "") {
815
1494
  return false;
@@ -833,25 +1512,25 @@ var multiSelectFilter = (row, columnId, filterValue) => {
833
1512
  };
834
1513
  function useExcelGrid(options) {
835
1514
  const { data, enableSorting = true, enableFiltering = true } = options;
836
- const [sorting, setSorting] = (0, import_react4.useState)([]);
837
- const [columnFilters, setColumnFilters] = (0, import_react4.useState)([]);
838
- const [columnVisibility, setColumnVisibility] = (0, import_react4.useState)({});
839
- const [globalFilter, setGlobalFilter] = (0, import_react4.useState)("");
840
- const [columnStatsCache, setColumnStatsCache] = (0, import_react4.useState)({});
841
- const dataSignature = (0, import_react4.useMemo)(
1515
+ const [sorting, setSorting] = (0, import_react5.useState)([]);
1516
+ const [columnFilters, setColumnFilters] = (0, import_react5.useState)([]);
1517
+ const [columnVisibility, setColumnVisibility] = (0, import_react5.useState)({});
1518
+ const [globalFilter, setGlobalFilter] = (0, import_react5.useState)("");
1519
+ const [columnStatsCache, setColumnStatsCache] = (0, import_react5.useState)({});
1520
+ const dataSignature = (0, import_react5.useMemo)(
842
1521
  () => `${Date.now()}-${Math.random().toString(36).slice(2)}`,
843
1522
  [data]
844
1523
  );
845
- const columnKeys = (0, import_react4.useMemo)(() => {
1524
+ const columnKeys = (0, import_react5.useMemo)(() => {
846
1525
  if (data.length === 0)
847
1526
  return [];
848
1527
  return Object.keys(data[0]);
849
1528
  }, [data]);
850
- const getColumnStats = (0, import_react4.useCallback)(
1529
+ const getColumnStats = (0, import_react5.useCallback)(
851
1530
  (columnKey) => {
852
1531
  const cacheKey = `${columnKey}-${dataSignature}`;
853
1532
  if (!columnStatsCache[cacheKey]) {
854
- const stats = (0, import_tinypivot_core2.getColumnUniqueValues)(data, columnKey);
1533
+ const stats = (0, import_tinypivot_core3.getColumnUniqueValues)(data, columnKey);
855
1534
  setColumnStatsCache((prev) => ({ ...prev, [cacheKey]: stats }));
856
1535
  return stats;
857
1536
  }
@@ -859,20 +1538,20 @@ function useExcelGrid(options) {
859
1538
  },
860
1539
  [data, columnStatsCache, dataSignature]
861
1540
  );
862
- const clearStatsCache = (0, import_react4.useCallback)(() => {
1541
+ const clearStatsCache = (0, import_react5.useCallback)(() => {
863
1542
  setColumnStatsCache({});
864
1543
  }, []);
865
- (0, import_react4.useEffect)(() => {
1544
+ (0, import_react5.useEffect)(() => {
866
1545
  clearStatsCache();
867
1546
  }, [dataSignature, clearStatsCache]);
868
- const columnDefs = (0, import_react4.useMemo)(() => {
1547
+ const columnDefs = (0, import_react5.useMemo)(() => {
869
1548
  return columnKeys.map((key) => {
870
1549
  const stats = getColumnStats(key);
871
1550
  return {
872
1551
  id: key,
873
1552
  accessorKey: key,
874
1553
  header: key,
875
- cell: (info) => (0, import_tinypivot_core2.formatCellValue)(info.getValue(), stats.type),
1554
+ cell: (info) => (0, import_tinypivot_core3.formatCellValue)(info.getValue(), stats.type),
876
1555
  filterFn: multiSelectFilter,
877
1556
  meta: {
878
1557
  type: stats.type,
@@ -905,10 +1584,10 @@ function useExcelGrid(options) {
905
1584
  });
906
1585
  const filteredRowCount = table.getFilteredRowModel().rows.length;
907
1586
  const totalRowCount = data.length;
908
- const activeFilters = (0, import_react4.useMemo)(() => {
1587
+ const activeFilters = (0, import_react5.useMemo)(() => {
909
1588
  return columnFilters.map((f) => {
910
1589
  const filterValue = f.value;
911
- if (filterValue && (0, import_tinypivot_core2.isNumericRange)(filterValue)) {
1590
+ if (filterValue && (0, import_tinypivot_core3.isNumericRange)(filterValue)) {
912
1591
  return {
913
1592
  column: f.id,
914
1593
  type: "range",
@@ -924,7 +1603,7 @@ function useExcelGrid(options) {
924
1603
  };
925
1604
  });
926
1605
  }, [columnFilters]);
927
- const hasActiveFilter = (0, import_react4.useCallback)(
1606
+ const hasActiveFilter = (0, import_react5.useCallback)(
928
1607
  (columnId) => {
929
1608
  const column = table.getColumn(columnId);
930
1609
  if (!column)
@@ -932,14 +1611,14 @@ function useExcelGrid(options) {
932
1611
  const filterValue = column.getFilterValue();
933
1612
  if (!filterValue)
934
1613
  return false;
935
- if ((0, import_tinypivot_core2.isNumericRange)(filterValue)) {
1614
+ if ((0, import_tinypivot_core3.isNumericRange)(filterValue)) {
936
1615
  return filterValue.min !== null || filterValue.max !== null;
937
1616
  }
938
1617
  return Array.isArray(filterValue) && filterValue.length > 0;
939
1618
  },
940
1619
  [table]
941
1620
  );
942
- const setColumnFilter = (0, import_react4.useCallback)(
1621
+ const setColumnFilter = (0, import_react5.useCallback)(
943
1622
  (columnId, values) => {
944
1623
  const column = table.getColumn(columnId);
945
1624
  if (column) {
@@ -948,7 +1627,7 @@ function useExcelGrid(options) {
948
1627
  },
949
1628
  [table]
950
1629
  );
951
- const setNumericRangeFilter = (0, import_react4.useCallback)(
1630
+ const setNumericRangeFilter = (0, import_react5.useCallback)(
952
1631
  (columnId, range) => {
953
1632
  const column = table.getColumn(columnId);
954
1633
  if (column) {
@@ -961,25 +1640,25 @@ function useExcelGrid(options) {
961
1640
  },
962
1641
  [table]
963
1642
  );
964
- const getNumericRangeFilter = (0, import_react4.useCallback)(
1643
+ const getNumericRangeFilter = (0, import_react5.useCallback)(
965
1644
  (columnId) => {
966
1645
  const column = table.getColumn(columnId);
967
1646
  if (!column)
968
1647
  return null;
969
1648
  const filterValue = column.getFilterValue();
970
- if (filterValue && (0, import_tinypivot_core2.isNumericRange)(filterValue)) {
1649
+ if (filterValue && (0, import_tinypivot_core3.isNumericRange)(filterValue)) {
971
1650
  return filterValue;
972
1651
  }
973
1652
  return null;
974
1653
  },
975
1654
  [table]
976
1655
  );
977
- const clearAllFilters = (0, import_react4.useCallback)(() => {
1656
+ const clearAllFilters = (0, import_react5.useCallback)(() => {
978
1657
  table.resetColumnFilters();
979
1658
  setGlobalFilter("");
980
1659
  setColumnFilters([]);
981
1660
  }, [table]);
982
- const getColumnFilterValues = (0, import_react4.useCallback)(
1661
+ const getColumnFilterValues = (0, import_react5.useCallback)(
983
1662
  (columnId) => {
984
1663
  const column = table.getColumn(columnId);
985
1664
  if (!column)
@@ -989,7 +1668,7 @@ function useExcelGrid(options) {
989
1668
  },
990
1669
  [table]
991
1670
  );
992
- const toggleSort = (0, import_react4.useCallback)((columnId) => {
1671
+ const toggleSort = (0, import_react5.useCallback)((columnId) => {
993
1672
  setSorting((prev) => {
994
1673
  const current = prev.find((s) => s.id === columnId);
995
1674
  if (!current) {
@@ -1001,7 +1680,7 @@ function useExcelGrid(options) {
1001
1680
  }
1002
1681
  });
1003
1682
  }, []);
1004
- const getSortDirection = (0, import_react4.useCallback)(
1683
+ const getSortDirection = (0, import_react5.useCallback)(
1005
1684
  (columnId) => {
1006
1685
  const sort = sorting.find((s) => s.id === columnId);
1007
1686
  if (!sort)
@@ -1042,60 +1721,60 @@ function useExcelGrid(options) {
1042
1721
  }
1043
1722
 
1044
1723
  // src/hooks/useGridFeatures.ts
1045
- var import_tinypivot_core3 = require("@smallwebco/tinypivot-core");
1046
- var import_react5 = require("react");
1724
+ var import_tinypivot_core4 = require("@smallwebco/tinypivot-core");
1725
+ var import_react6 = require("react");
1047
1726
  function exportToCSV(data, columns, options) {
1048
- (0, import_tinypivot_core3.exportToCSV)(data, columns, options);
1727
+ (0, import_tinypivot_core4.exportToCSV)(data, columns, options);
1049
1728
  }
1050
1729
  function exportPivotToCSV(pivotData, rowFields, columnFields, valueFields, options) {
1051
- (0, import_tinypivot_core3.exportPivotToCSV)(pivotData, rowFields, columnFields, valueFields, options);
1730
+ (0, import_tinypivot_core4.exportPivotToCSV)(pivotData, rowFields, columnFields, valueFields, options);
1052
1731
  }
1053
1732
  function copyToClipboard(text, onSuccess, onError) {
1054
- (0, import_tinypivot_core3.copyToClipboard)(text, onSuccess, onError);
1733
+ (0, import_tinypivot_core4.copyToClipboard)(text, onSuccess, onError);
1055
1734
  }
1056
1735
  function formatSelectionForClipboard(rows, columns, selectionBounds) {
1057
- return (0, import_tinypivot_core3.formatSelectionForClipboard)(rows, columns, selectionBounds);
1736
+ return (0, import_tinypivot_core4.formatSelectionForClipboard)(rows, columns, selectionBounds);
1058
1737
  }
1059
1738
  function usePagination(data, options = {}) {
1060
- const [pageSize, setPageSize] = (0, import_react5.useState)(options.pageSize ?? 50);
1061
- const [currentPage, setCurrentPage] = (0, import_react5.useState)(options.currentPage ?? 1);
1062
- const totalPages = (0, import_react5.useMemo)(
1739
+ const [pageSize, setPageSize] = (0, import_react6.useState)(options.pageSize ?? 50);
1740
+ const [currentPage, setCurrentPage] = (0, import_react6.useState)(options.currentPage ?? 1);
1741
+ const totalPages = (0, import_react6.useMemo)(
1063
1742
  () => Math.max(1, Math.ceil(data.length / pageSize)),
1064
1743
  [data.length, pageSize]
1065
1744
  );
1066
- const paginatedData = (0, import_react5.useMemo)(() => {
1745
+ const paginatedData = (0, import_react6.useMemo)(() => {
1067
1746
  const start = (currentPage - 1) * pageSize;
1068
1747
  const end = start + pageSize;
1069
1748
  return data.slice(start, end);
1070
1749
  }, [data, currentPage, pageSize]);
1071
- const startIndex = (0, import_react5.useMemo)(() => (currentPage - 1) * pageSize + 1, [currentPage, pageSize]);
1072
- const endIndex = (0, import_react5.useMemo)(
1750
+ const startIndex = (0, import_react6.useMemo)(() => (currentPage - 1) * pageSize + 1, [currentPage, pageSize]);
1751
+ const endIndex = (0, import_react6.useMemo)(
1073
1752
  () => Math.min(currentPage * pageSize, data.length),
1074
1753
  [currentPage, pageSize, data.length]
1075
1754
  );
1076
- const goToPage = (0, import_react5.useCallback)(
1755
+ const goToPage = (0, import_react6.useCallback)(
1077
1756
  (page) => {
1078
1757
  setCurrentPage(Math.max(1, Math.min(page, totalPages)));
1079
1758
  },
1080
1759
  [totalPages]
1081
1760
  );
1082
- const nextPage = (0, import_react5.useCallback)(() => {
1761
+ const nextPage = (0, import_react6.useCallback)(() => {
1083
1762
  if (currentPage < totalPages) {
1084
1763
  setCurrentPage((prev) => prev + 1);
1085
1764
  }
1086
1765
  }, [currentPage, totalPages]);
1087
- const prevPage = (0, import_react5.useCallback)(() => {
1766
+ const prevPage = (0, import_react6.useCallback)(() => {
1088
1767
  if (currentPage > 1) {
1089
1768
  setCurrentPage((prev) => prev - 1);
1090
1769
  }
1091
1770
  }, [currentPage]);
1092
- const firstPage = (0, import_react5.useCallback)(() => {
1771
+ const firstPage = (0, import_react6.useCallback)(() => {
1093
1772
  setCurrentPage(1);
1094
1773
  }, []);
1095
- const lastPage = (0, import_react5.useCallback)(() => {
1774
+ const lastPage = (0, import_react6.useCallback)(() => {
1096
1775
  setCurrentPage(totalPages);
1097
1776
  }, [totalPages]);
1098
- const updatePageSize = (0, import_react5.useCallback)((size) => {
1777
+ const updatePageSize = (0, import_react6.useCallback)((size) => {
1099
1778
  setPageSize(size);
1100
1779
  setCurrentPage(1);
1101
1780
  }, []);
@@ -1115,9 +1794,9 @@ function usePagination(data, options = {}) {
1115
1794
  };
1116
1795
  }
1117
1796
  function useGlobalSearch(data, columns) {
1118
- const [searchTerm, setSearchTerm] = (0, import_react5.useState)("");
1119
- const [caseSensitive, setCaseSensitive] = (0, import_react5.useState)(false);
1120
- const filteredData = (0, import_react5.useMemo)(() => {
1797
+ const [searchTerm, setSearchTerm] = (0, import_react6.useState)("");
1798
+ const [caseSensitive, setCaseSensitive] = (0, import_react6.useState)(false);
1799
+ const filteredData = (0, import_react6.useMemo)(() => {
1121
1800
  if (!searchTerm.trim()) {
1122
1801
  return data;
1123
1802
  }
@@ -1135,7 +1814,7 @@ function useGlobalSearch(data, columns) {
1135
1814
  return false;
1136
1815
  });
1137
1816
  }, [data, columns, searchTerm, caseSensitive]);
1138
- const clearSearch = (0, import_react5.useCallback)(() => {
1817
+ const clearSearch = (0, import_react6.useCallback)(() => {
1139
1818
  setSearchTerm("");
1140
1819
  }, []);
1141
1820
  return {
@@ -1148,17 +1827,17 @@ function useGlobalSearch(data, columns) {
1148
1827
  };
1149
1828
  }
1150
1829
  function useRowSelection(data) {
1151
- const [selectedRowIndices, setSelectedRowIndices] = (0, import_react5.useState)(/* @__PURE__ */ new Set());
1152
- const selectedRows = (0, import_react5.useMemo)(() => {
1830
+ const [selectedRowIndices, setSelectedRowIndices] = (0, import_react6.useState)(/* @__PURE__ */ new Set());
1831
+ const selectedRows = (0, import_react6.useMemo)(() => {
1153
1832
  return Array.from(selectedRowIndices).sort((a, b) => a - b).map((idx) => data[idx]).filter(Boolean);
1154
1833
  }, [data, selectedRowIndices]);
1155
- const allSelected = (0, import_react5.useMemo)(() => {
1834
+ const allSelected = (0, import_react6.useMemo)(() => {
1156
1835
  return data.length > 0 && selectedRowIndices.size === data.length;
1157
1836
  }, [data.length, selectedRowIndices.size]);
1158
- const someSelected = (0, import_react5.useMemo)(() => {
1837
+ const someSelected = (0, import_react6.useMemo)(() => {
1159
1838
  return selectedRowIndices.size > 0 && selectedRowIndices.size < data.length;
1160
1839
  }, [data.length, selectedRowIndices.size]);
1161
- const toggleRow = (0, import_react5.useCallback)((index) => {
1840
+ const toggleRow = (0, import_react6.useCallback)((index) => {
1162
1841
  setSelectedRowIndices((prev) => {
1163
1842
  const next = new Set(prev);
1164
1843
  if (next.has(index)) {
@@ -1169,36 +1848,36 @@ function useRowSelection(data) {
1169
1848
  return next;
1170
1849
  });
1171
1850
  }, []);
1172
- const selectRow = (0, import_react5.useCallback)((index) => {
1851
+ const selectRow = (0, import_react6.useCallback)((index) => {
1173
1852
  setSelectedRowIndices((prev) => /* @__PURE__ */ new Set([...prev, index]));
1174
1853
  }, []);
1175
- const deselectRow = (0, import_react5.useCallback)((index) => {
1854
+ const deselectRow = (0, import_react6.useCallback)((index) => {
1176
1855
  setSelectedRowIndices((prev) => {
1177
1856
  const next = new Set(prev);
1178
1857
  next.delete(index);
1179
1858
  return next;
1180
1859
  });
1181
1860
  }, []);
1182
- const selectAll = (0, import_react5.useCallback)(() => {
1861
+ const selectAll = (0, import_react6.useCallback)(() => {
1183
1862
  setSelectedRowIndices(new Set(data.map((_, idx) => idx)));
1184
1863
  }, [data]);
1185
- const deselectAll = (0, import_react5.useCallback)(() => {
1864
+ const deselectAll = (0, import_react6.useCallback)(() => {
1186
1865
  setSelectedRowIndices(/* @__PURE__ */ new Set());
1187
1866
  }, []);
1188
- const toggleAll = (0, import_react5.useCallback)(() => {
1867
+ const toggleAll = (0, import_react6.useCallback)(() => {
1189
1868
  if (allSelected) {
1190
1869
  deselectAll();
1191
1870
  } else {
1192
1871
  selectAll();
1193
1872
  }
1194
1873
  }, [allSelected, selectAll, deselectAll]);
1195
- const isSelected = (0, import_react5.useCallback)(
1874
+ const isSelected = (0, import_react6.useCallback)(
1196
1875
  (index) => {
1197
1876
  return selectedRowIndices.has(index);
1198
1877
  },
1199
1878
  [selectedRowIndices]
1200
1879
  );
1201
- const selectRange = (0, import_react5.useCallback)((startIndex, endIndex) => {
1880
+ const selectRange = (0, import_react6.useCallback)((startIndex, endIndex) => {
1202
1881
  const min = Math.min(startIndex, endIndex);
1203
1882
  const max = Math.max(startIndex, endIndex);
1204
1883
  setSelectedRowIndices((prev) => {
@@ -1225,10 +1904,10 @@ function useRowSelection(data) {
1225
1904
  };
1226
1905
  }
1227
1906
  function useColumnResize(initialWidths, minWidth = 60, maxWidth = 600) {
1228
- const [columnWidths, setColumnWidths] = (0, import_react5.useState)({ ...initialWidths });
1229
- const [isResizing, setIsResizing] = (0, import_react5.useState)(false);
1230
- const [resizingColumn, setResizingColumn] = (0, import_react5.useState)(null);
1231
- const startResize = (0, import_react5.useCallback)(
1907
+ const [columnWidths, setColumnWidths] = (0, import_react6.useState)({ ...initialWidths });
1908
+ const [isResizing, setIsResizing] = (0, import_react6.useState)(false);
1909
+ const [resizingColumn, setResizingColumn] = (0, import_react6.useState)(null);
1910
+ const startResize = (0, import_react6.useCallback)(
1232
1911
  (columnId, event) => {
1233
1912
  setIsResizing(true);
1234
1913
  setResizingColumn(columnId);
@@ -1253,7 +1932,7 @@ function useColumnResize(initialWidths, minWidth = 60, maxWidth = 600) {
1253
1932
  },
1254
1933
  [columnWidths, minWidth, maxWidth]
1255
1934
  );
1256
- const resetColumnWidth = (0, import_react5.useCallback)(
1935
+ const resetColumnWidth = (0, import_react6.useCallback)(
1257
1936
  (columnId) => {
1258
1937
  if (initialWidths[columnId]) {
1259
1938
  setColumnWidths((prev) => ({
@@ -1264,7 +1943,7 @@ function useColumnResize(initialWidths, minWidth = 60, maxWidth = 600) {
1264
1943
  },
1265
1944
  [initialWidths]
1266
1945
  );
1267
- const resetAllWidths = (0, import_react5.useCallback)(() => {
1946
+ const resetAllWidths = (0, import_react6.useCallback)(() => {
1268
1947
  setColumnWidths({ ...initialWidths });
1269
1948
  }, [initialWidths]);
1270
1949
  return {
@@ -1279,16 +1958,16 @@ function useColumnResize(initialWidths, minWidth = 60, maxWidth = 600) {
1279
1958
  }
1280
1959
 
1281
1960
  // src/hooks/useLicense.ts
1282
- var import_tinypivot_core4 = require("@smallwebco/tinypivot-core");
1283
- var import_react6 = require("react");
1284
- var globalLicenseInfo = (0, import_tinypivot_core4.getFreeLicenseInfo)();
1961
+ var import_tinypivot_core5 = require("@smallwebco/tinypivot-core");
1962
+ var import_react7 = require("react");
1963
+ var globalLicenseInfo = (0, import_tinypivot_core5.getFreeLicenseInfo)();
1285
1964
  var globalDemoMode = false;
1286
1965
  var listeners = /* @__PURE__ */ new Set();
1287
1966
  function notifyListeners() {
1288
1967
  listeners.forEach((listener) => listener());
1289
1968
  }
1290
1969
  async function setLicenseKey(key) {
1291
- globalLicenseInfo = await (0, import_tinypivot_core4.validateLicenseKey)(key);
1970
+ globalLicenseInfo = await (0, import_tinypivot_core5.validateLicenseKey)(key);
1292
1971
  if (!globalLicenseInfo.isValid) {
1293
1972
  console.warn("[TinyPivot] Invalid or expired license key. Running in free mode.");
1294
1973
  } else if (globalLicenseInfo.type !== "free") {
@@ -1297,7 +1976,7 @@ async function setLicenseKey(key) {
1297
1976
  notifyListeners();
1298
1977
  }
1299
1978
  async function enableDemoMode(secret) {
1300
- const demoLicense = await (0, import_tinypivot_core4.getDemoLicenseInfo)(secret);
1979
+ const demoLicense = await (0, import_tinypivot_core5.getDemoLicenseInfo)(secret);
1301
1980
  if (!demoLicense) {
1302
1981
  console.warn("[TinyPivot] Demo mode activation failed - invalid secret");
1303
1982
  return false;
@@ -1309,40 +1988,44 @@ async function enableDemoMode(secret) {
1309
1988
  return true;
1310
1989
  }
1311
1990
  function configureLicenseSecret(secret) {
1312
- (0, import_tinypivot_core4.configureLicenseSecret)(secret);
1991
+ (0, import_tinypivot_core5.configureLicenseSecret)(secret);
1313
1992
  }
1314
1993
  function useLicense() {
1315
- const [, forceUpdate] = (0, import_react6.useState)({});
1316
- (0, import_react6.useState)(() => {
1994
+ const [, forceUpdate] = (0, import_react7.useState)({});
1995
+ (0, import_react7.useState)(() => {
1317
1996
  const update = () => forceUpdate({});
1318
1997
  listeners.add(update);
1319
1998
  return () => listeners.delete(update);
1320
1999
  });
1321
2000
  const isDemo = globalDemoMode;
1322
2001
  const licenseInfo = globalLicenseInfo;
1323
- const isPro = (0, import_react6.useMemo)(
1324
- () => globalDemoMode || (0, import_tinypivot_core4.isPro)(licenseInfo),
2002
+ const isPro = (0, import_react7.useMemo)(
2003
+ () => globalDemoMode || (0, import_tinypivot_core5.isPro)(licenseInfo),
1325
2004
  [licenseInfo]
1326
2005
  );
1327
- const canUsePivot = (0, import_react6.useMemo)(
1328
- () => globalDemoMode || (0, import_tinypivot_core4.canUsePivot)(licenseInfo),
2006
+ const canUsePivot = (0, import_react7.useMemo)(
2007
+ () => globalDemoMode || (0, import_tinypivot_core5.canUsePivot)(licenseInfo),
1329
2008
  [licenseInfo]
1330
2009
  );
1331
- const canUseAdvancedAggregations = (0, import_react6.useMemo)(
2010
+ const canUseAdvancedAggregations = (0, import_react7.useMemo)(
1332
2011
  () => globalDemoMode || licenseInfo.features.advancedAggregations,
1333
2012
  [licenseInfo]
1334
2013
  );
1335
- const canUsePercentageMode = (0, import_react6.useMemo)(
2014
+ const canUsePercentageMode = (0, import_react7.useMemo)(
1336
2015
  () => globalDemoMode || licenseInfo.features.percentageMode,
1337
2016
  [licenseInfo]
1338
2017
  );
1339
- const showWatermark = (0, import_react6.useMemo)(
1340
- () => (0, import_tinypivot_core4.shouldShowWatermark)(licenseInfo, globalDemoMode),
2018
+ const canUseCharts = (0, import_react7.useMemo)(
2019
+ () => globalDemoMode || (0, import_tinypivot_core5.canUseCharts)(licenseInfo),
2020
+ [licenseInfo]
2021
+ );
2022
+ const showWatermark = (0, import_react7.useMemo)(
2023
+ () => (0, import_tinypivot_core5.shouldShowWatermark)(licenseInfo, globalDemoMode),
1341
2024
  [licenseInfo]
1342
2025
  );
1343
- const requirePro = (0, import_react6.useCallback)((feature) => {
2026
+ const requirePro = (0, import_react7.useCallback)((feature) => {
1344
2027
  if (!isPro) {
1345
- (0, import_tinypivot_core4.logProRequired)(feature);
2028
+ (0, import_tinypivot_core5.logProRequired)(feature);
1346
2029
  return false;
1347
2030
  }
1348
2031
  return true;
@@ -1354,31 +2037,32 @@ function useLicense() {
1354
2037
  canUsePivot,
1355
2038
  canUseAdvancedAggregations,
1356
2039
  canUsePercentageMode,
2040
+ canUseCharts,
1357
2041
  showWatermark,
1358
2042
  requirePro
1359
2043
  };
1360
2044
  }
1361
2045
 
1362
2046
  // src/hooks/usePivotTable.ts
1363
- var import_tinypivot_core5 = require("@smallwebco/tinypivot-core");
1364
- var import_react7 = require("react");
2047
+ var import_tinypivot_core6 = require("@smallwebco/tinypivot-core");
2048
+ var import_react8 = require("react");
1365
2049
  function usePivotTable(data) {
1366
2050
  const { canUsePivot, requirePro } = useLicense();
1367
- const [rowFields, setRowFieldsState] = (0, import_react7.useState)([]);
1368
- const [columnFields, setColumnFieldsState] = (0, import_react7.useState)([]);
1369
- const [valueFields, setValueFields] = (0, import_react7.useState)([]);
1370
- const [showRowTotals, setShowRowTotals] = (0, import_react7.useState)(true);
1371
- const [showColumnTotals, setShowColumnTotals] = (0, import_react7.useState)(true);
1372
- const [calculatedFields, setCalculatedFields] = (0, import_react7.useState)(() => (0, import_tinypivot_core5.loadCalculatedFields)());
1373
- const [currentStorageKey, setCurrentStorageKey] = (0, import_react7.useState)(null);
1374
- const availableFields = (0, import_react7.useMemo)(() => {
1375
- return (0, import_tinypivot_core5.computeAvailableFields)(data);
2051
+ const [rowFields, setRowFieldsState] = (0, import_react8.useState)([]);
2052
+ const [columnFields, setColumnFieldsState] = (0, import_react8.useState)([]);
2053
+ const [valueFields, setValueFields] = (0, import_react8.useState)([]);
2054
+ const [showRowTotals, setShowRowTotals] = (0, import_react8.useState)(true);
2055
+ const [showColumnTotals, setShowColumnTotals] = (0, import_react8.useState)(true);
2056
+ const [calculatedFields, setCalculatedFields] = (0, import_react8.useState)(() => (0, import_tinypivot_core6.loadCalculatedFields)());
2057
+ const [currentStorageKey, setCurrentStorageKey] = (0, import_react8.useState)(null);
2058
+ const availableFields = (0, import_react8.useMemo)(() => {
2059
+ return (0, import_tinypivot_core6.computeAvailableFields)(data);
1376
2060
  }, [data]);
1377
- const unassignedFields = (0, import_react7.useMemo)(() => {
1378
- return (0, import_tinypivot_core5.getUnassignedFields)(availableFields, rowFields, columnFields, valueFields);
2061
+ const unassignedFields = (0, import_react8.useMemo)(() => {
2062
+ return (0, import_tinypivot_core6.getUnassignedFields)(availableFields, rowFields, columnFields, valueFields);
1379
2063
  }, [availableFields, rowFields, columnFields, valueFields]);
1380
- const isConfigured = (0, import_react7.useMemo)(() => {
1381
- return (0, import_tinypivot_core5.isPivotConfigured)({
2064
+ const isConfigured = (0, import_react8.useMemo)(() => {
2065
+ return (0, import_tinypivot_core6.isPivotConfigured)({
1382
2066
  rowFields,
1383
2067
  columnFields,
1384
2068
  valueFields,
@@ -1386,12 +2070,12 @@ function usePivotTable(data) {
1386
2070
  showColumnTotals
1387
2071
  });
1388
2072
  }, [rowFields, columnFields, valueFields, showRowTotals, showColumnTotals]);
1389
- const pivotResult = (0, import_react7.useMemo)(() => {
2073
+ const pivotResult = (0, import_react8.useMemo)(() => {
1390
2074
  if (!isConfigured)
1391
2075
  return null;
1392
2076
  if (!canUsePivot)
1393
2077
  return null;
1394
- return (0, import_tinypivot_core5.computePivotResult)(data, {
2078
+ return (0, import_tinypivot_core6.computePivotResult)(data, {
1395
2079
  rowFields,
1396
2080
  columnFields,
1397
2081
  valueFields,
@@ -1400,15 +2084,15 @@ function usePivotTable(data) {
1400
2084
  calculatedFields
1401
2085
  });
1402
2086
  }, [data, isConfigured, canUsePivot, rowFields, columnFields, valueFields, showRowTotals, showColumnTotals, calculatedFields]);
1403
- (0, import_react7.useEffect)(() => {
2087
+ (0, import_react8.useEffect)(() => {
1404
2088
  if (data.length === 0)
1405
2089
  return;
1406
2090
  const newKeys = Object.keys(data[0]);
1407
- const storageKey = (0, import_tinypivot_core5.generateStorageKey)(newKeys);
2091
+ const storageKey = (0, import_tinypivot_core6.generateStorageKey)(newKeys);
1408
2092
  if (storageKey !== currentStorageKey) {
1409
2093
  setCurrentStorageKey(storageKey);
1410
- const savedConfig = (0, import_tinypivot_core5.loadPivotConfig)(storageKey);
1411
- if (savedConfig && (0, import_tinypivot_core5.isConfigValidForFields)(savedConfig, newKeys)) {
2094
+ const savedConfig = (0, import_tinypivot_core6.loadPivotConfig)(storageKey);
2095
+ if (savedConfig && (0, import_tinypivot_core6.isConfigValidForFields)(savedConfig, newKeys)) {
1412
2096
  setRowFieldsState(savedConfig.rowFields);
1413
2097
  setColumnFieldsState(savedConfig.columnFields);
1414
2098
  setValueFields(savedConfig.valueFields);
@@ -1425,7 +2109,7 @@ function usePivotTable(data) {
1425
2109
  showRowTotals,
1426
2110
  showColumnTotals
1427
2111
  };
1428
- if (!(0, import_tinypivot_core5.isConfigValidForFields)(currentConfig, newKeys)) {
2112
+ if (!(0, import_tinypivot_core6.isConfigValidForFields)(currentConfig, newKeys)) {
1429
2113
  setRowFieldsState([]);
1430
2114
  setColumnFieldsState([]);
1431
2115
  setValueFields([]);
@@ -1433,7 +2117,7 @@ function usePivotTable(data) {
1433
2117
  }
1434
2118
  }
1435
2119
  }, [data]);
1436
- (0, import_react7.useEffect)(() => {
2120
+ (0, import_react8.useEffect)(() => {
1437
2121
  if (!currentStorageKey)
1438
2122
  return;
1439
2123
  const config = {
@@ -1444,9 +2128,9 @@ function usePivotTable(data) {
1444
2128
  showColumnTotals,
1445
2129
  calculatedFields
1446
2130
  };
1447
- (0, import_tinypivot_core5.savePivotConfig)(currentStorageKey, config);
2131
+ (0, import_tinypivot_core6.savePivotConfig)(currentStorageKey, config);
1448
2132
  }, [currentStorageKey, rowFields, columnFields, valueFields, showRowTotals, showColumnTotals, calculatedFields]);
1449
- const addRowField = (0, import_react7.useCallback)(
2133
+ const addRowField = (0, import_react8.useCallback)(
1450
2134
  (field) => {
1451
2135
  if (!rowFields.includes(field)) {
1452
2136
  setRowFieldsState((prev) => [...prev, field]);
@@ -1454,13 +2138,13 @@ function usePivotTable(data) {
1454
2138
  },
1455
2139
  [rowFields]
1456
2140
  );
1457
- const removeRowField = (0, import_react7.useCallback)((field) => {
2141
+ const removeRowField = (0, import_react8.useCallback)((field) => {
1458
2142
  setRowFieldsState((prev) => prev.filter((f) => f !== field));
1459
2143
  }, []);
1460
- const setRowFields = (0, import_react7.useCallback)((fields) => {
2144
+ const setRowFields = (0, import_react8.useCallback)((fields) => {
1461
2145
  setRowFieldsState(fields);
1462
2146
  }, []);
1463
- const addColumnField = (0, import_react7.useCallback)(
2147
+ const addColumnField = (0, import_react8.useCallback)(
1464
2148
  (field) => {
1465
2149
  if (!columnFields.includes(field)) {
1466
2150
  setColumnFieldsState((prev) => [...prev, field]);
@@ -1468,13 +2152,13 @@ function usePivotTable(data) {
1468
2152
  },
1469
2153
  [columnFields]
1470
2154
  );
1471
- const removeColumnField = (0, import_react7.useCallback)((field) => {
2155
+ const removeColumnField = (0, import_react8.useCallback)((field) => {
1472
2156
  setColumnFieldsState((prev) => prev.filter((f) => f !== field));
1473
2157
  }, []);
1474
- const setColumnFields = (0, import_react7.useCallback)((fields) => {
2158
+ const setColumnFields = (0, import_react8.useCallback)((fields) => {
1475
2159
  setColumnFieldsState(fields);
1476
2160
  }, []);
1477
- const addValueField = (0, import_react7.useCallback)(
2161
+ const addValueField = (0, import_react8.useCallback)(
1478
2162
  (field, aggregation = "sum") => {
1479
2163
  if (aggregation !== "sum" && !requirePro(`${aggregation} aggregation`)) {
1480
2164
  return;
@@ -1488,7 +2172,7 @@ function usePivotTable(data) {
1488
2172
  },
1489
2173
  [requirePro]
1490
2174
  );
1491
- const removeValueField = (0, import_react7.useCallback)((field, aggregation) => {
2175
+ const removeValueField = (0, import_react8.useCallback)((field, aggregation) => {
1492
2176
  setValueFields((prev) => {
1493
2177
  if (aggregation) {
1494
2178
  return prev.filter((v) => !(v.field === field && v.aggregation === aggregation));
@@ -1496,7 +2180,7 @@ function usePivotTable(data) {
1496
2180
  return prev.filter((v) => v.field !== field);
1497
2181
  });
1498
2182
  }, []);
1499
- const updateValueFieldAggregation = (0, import_react7.useCallback)(
2183
+ const updateValueFieldAggregation = (0, import_react8.useCallback)(
1500
2184
  (field, oldAgg, newAgg) => {
1501
2185
  setValueFields(
1502
2186
  (prev) => prev.map((v) => {
@@ -1509,12 +2193,12 @@ function usePivotTable(data) {
1509
2193
  },
1510
2194
  []
1511
2195
  );
1512
- const clearConfig = (0, import_react7.useCallback)(() => {
2196
+ const clearConfig = (0, import_react8.useCallback)(() => {
1513
2197
  setRowFieldsState([]);
1514
2198
  setColumnFieldsState([]);
1515
2199
  setValueFields([]);
1516
2200
  }, []);
1517
- const autoSuggestConfig = (0, import_react7.useCallback)(() => {
2201
+ const autoSuggestConfig = (0, import_react8.useCallback)(() => {
1518
2202
  if (!requirePro("Pivot Table - Auto Suggest"))
1519
2203
  return;
1520
2204
  if (availableFields.length === 0)
@@ -1526,7 +2210,7 @@ function usePivotTable(data) {
1526
2210
  setValueFields([{ field: numericFields[0].field, aggregation: "sum" }]);
1527
2211
  }
1528
2212
  }, [availableFields, requirePro]);
1529
- const addCalculatedField = (0, import_react7.useCallback)((field) => {
2213
+ const addCalculatedField = (0, import_react8.useCallback)((field) => {
1530
2214
  setCalculatedFields((prev) => {
1531
2215
  const existing = prev.findIndex((f) => f.id === field.id);
1532
2216
  let updated;
@@ -1535,14 +2219,14 @@ function usePivotTable(data) {
1535
2219
  } else {
1536
2220
  updated = [...prev, field];
1537
2221
  }
1538
- (0, import_tinypivot_core5.saveCalculatedFields)(updated);
2222
+ (0, import_tinypivot_core6.saveCalculatedFields)(updated);
1539
2223
  return updated;
1540
2224
  });
1541
2225
  }, []);
1542
- const removeCalculatedField = (0, import_react7.useCallback)((id) => {
2226
+ const removeCalculatedField = (0, import_react8.useCallback)((id) => {
1543
2227
  setCalculatedFields((prev) => {
1544
2228
  const updated = prev.filter((f) => f.id !== id);
1545
- (0, import_tinypivot_core5.saveCalculatedFields)(updated);
2229
+ (0, import_tinypivot_core6.saveCalculatedFields)(updated);
1546
2230
  return updated;
1547
2231
  });
1548
2232
  setValueFields((prev) => prev.filter((v) => v.field !== `calc:${id}`));
@@ -1580,9 +2264,9 @@ function usePivotTable(data) {
1580
2264
  }
1581
2265
 
1582
2266
  // src/components/PivotConfig.tsx
1583
- var import_tinypivot_core6 = require("@smallwebco/tinypivot-core");
1584
- var import_react8 = require("react");
1585
- var import_jsx_runtime4 = require("react/jsx-runtime");
2267
+ var import_tinypivot_core7 = require("@smallwebco/tinypivot-core");
2268
+ var import_react9 = require("react");
2269
+ var import_jsx_runtime5 = require("react/jsx-runtime");
1586
2270
  function aggregationRequiresPro(agg) {
1587
2271
  return agg !== "sum";
1588
2272
  }
@@ -1623,15 +2307,15 @@ function PivotConfig({
1623
2307
  onRemoveCalculatedField,
1624
2308
  onUpdateCalculatedField
1625
2309
  }) {
1626
- const [fieldSearch, setFieldSearch] = (0, import_react8.useState)("");
1627
- const [showCalcModal, setShowCalcModal] = (0, import_react8.useState)(false);
1628
- const [editingCalcField, setEditingCalcField] = (0, import_react8.useState)(null);
2310
+ const [fieldSearch, setFieldSearch] = (0, import_react9.useState)("");
2311
+ const [showCalcModal, setShowCalcModal] = (0, import_react9.useState)(false);
2312
+ const [editingCalcField, setEditingCalcField] = (0, import_react9.useState)(null);
1629
2313
  const { canUseAdvancedAggregations } = useLicense();
1630
- const isAggregationAvailable = (0, import_react8.useCallback)((agg) => {
2314
+ const isAggregationAvailable = (0, import_react9.useCallback)((agg) => {
1631
2315
  return !aggregationRequiresPro(agg) || canUseAdvancedAggregations;
1632
2316
  }, [canUseAdvancedAggregations]);
1633
- const numericFieldNames = (0, import_react8.useMemo)(() => availableFields.filter((f) => f.isNumeric).map((f) => f.field), [availableFields]);
1634
- const calculatedFieldsAsStats = (0, import_react8.useMemo)(() => {
2317
+ const numericFieldNames = (0, import_react9.useMemo)(() => availableFields.filter((f) => f.isNumeric).map((f) => f.field), [availableFields]);
2318
+ const calculatedFieldsAsStats = (0, import_react9.useMemo)(() => {
1635
2319
  if (!calculatedFields)
1636
2320
  return [];
1637
2321
  return calculatedFields.map((calc) => ({
@@ -1645,11 +2329,11 @@ function PivotConfig({
1645
2329
  calcFormula: calc.formula
1646
2330
  }));
1647
2331
  }, [calculatedFields]);
1648
- const allAvailableFields = (0, import_react8.useMemo)(() => [
2332
+ const allAvailableFields = (0, import_react9.useMemo)(() => [
1649
2333
  ...availableFields.map((f) => ({ ...f, isCalculated: false })),
1650
2334
  ...calculatedFieldsAsStats
1651
2335
  ], [availableFields, calculatedFieldsAsStats]);
1652
- const assignedFields = (0, import_react8.useMemo)(() => {
2336
+ const assignedFields = (0, import_react9.useMemo)(() => {
1653
2337
  const rowSet = new Set(rowFields);
1654
2338
  const colSet = new Set(columnFields);
1655
2339
  const valueMap = new Map(valueFields.map((v) => [v.field, v]));
@@ -1659,7 +2343,7 @@ function PivotConfig({
1659
2343
  valueConfig: valueMap.get(f.field)
1660
2344
  }));
1661
2345
  }, [allAvailableFields, rowFields, columnFields, valueFields]);
1662
- const unassignedFields = (0, import_react8.useMemo)(() => {
2346
+ const unassignedFields = (0, import_react9.useMemo)(() => {
1663
2347
  const rowSet = new Set(rowFields);
1664
2348
  const colSet = new Set(columnFields);
1665
2349
  const valSet = new Set(valueFields.map((v) => v.field));
@@ -1667,7 +2351,7 @@ function PivotConfig({
1667
2351
  (f) => !rowSet.has(f.field) && !colSet.has(f.field) && !valSet.has(f.field)
1668
2352
  );
1669
2353
  }, [allAvailableFields, rowFields, columnFields, valueFields]);
1670
- const filteredUnassignedFields = (0, import_react8.useMemo)(() => {
2354
+ const filteredUnassignedFields = (0, import_react9.useMemo)(() => {
1671
2355
  if (!fieldSearch.trim())
1672
2356
  return unassignedFields;
1673
2357
  const search = fieldSearch.toLowerCase().trim();
@@ -1678,13 +2362,13 @@ function PivotConfig({
1678
2362
  });
1679
2363
  }, [unassignedFields, fieldSearch]);
1680
2364
  const assignedCount = assignedFields.length;
1681
- const getFieldDisplayName = (0, import_react8.useCallback)((field) => {
2365
+ const getFieldDisplayName = (0, import_react9.useCallback)((field) => {
1682
2366
  if (field.isCalculated && field.calcName) {
1683
2367
  return field.calcName;
1684
2368
  }
1685
2369
  return field.field;
1686
2370
  }, []);
1687
- const handleDragStart = (0, import_react8.useCallback)(
2371
+ const handleDragStart = (0, import_react9.useCallback)(
1688
2372
  (field, event) => {
1689
2373
  event.dataTransfer?.setData("text/plain", field);
1690
2374
  event.dataTransfer.effectAllowed = "move";
@@ -1692,7 +2376,7 @@ function PivotConfig({
1692
2376
  },
1693
2377
  [onDragStart]
1694
2378
  );
1695
- const handleAggregationChange = (0, import_react8.useCallback)(
2379
+ const handleAggregationChange = (0, import_react9.useCallback)(
1696
2380
  (field, currentAgg, newAgg) => {
1697
2381
  if (!isAggregationAvailable(newAgg)) {
1698
2382
  console.warn(`[TinyPivot] "${newAgg}" aggregation requires a Pro license. Visit https://tiny-pivot.com/#pricing to upgrade.`);
@@ -1702,7 +2386,7 @@ function PivotConfig({
1702
2386
  },
1703
2387
  [onUpdateAggregation, isAggregationAvailable]
1704
2388
  );
1705
- const toggleRowColumn = (0, import_react8.useCallback)(
2389
+ const toggleRowColumn = (0, import_react9.useCallback)(
1706
2390
  (field, currentAssignment) => {
1707
2391
  if (currentAssignment === "row") {
1708
2392
  onRemoveRowField(field);
@@ -1714,7 +2398,7 @@ function PivotConfig({
1714
2398
  },
1715
2399
  [onRemoveRowField, onAddColumnField, onRemoveColumnField, onAddRowField]
1716
2400
  );
1717
- const removeField = (0, import_react8.useCallback)(
2401
+ const removeField = (0, import_react9.useCallback)(
1718
2402
  (field, assignedTo, valueConfig) => {
1719
2403
  if (assignedTo === "row") {
1720
2404
  onRemoveRowField(field);
@@ -1726,15 +2410,15 @@ function PivotConfig({
1726
2410
  },
1727
2411
  [onRemoveRowField, onRemoveColumnField, onRemoveValueField]
1728
2412
  );
1729
- const handleTotalsToggle = (0, import_react8.useCallback)((checked) => {
2413
+ const handleTotalsToggle = (0, import_react9.useCallback)((checked) => {
1730
2414
  onShowRowTotalsChange(checked);
1731
2415
  onShowColumnTotalsChange(checked);
1732
2416
  }, [onShowRowTotalsChange, onShowColumnTotalsChange]);
1733
- const openCalcModal = (0, import_react8.useCallback)((field) => {
2417
+ const openCalcModal = (0, import_react9.useCallback)((field) => {
1734
2418
  setEditingCalcField(field || null);
1735
2419
  setShowCalcModal(true);
1736
2420
  }, []);
1737
- const handleSaveCalcField = (0, import_react8.useCallback)((field) => {
2421
+ const handleSaveCalcField = (0, import_react9.useCallback)((field) => {
1738
2422
  if (editingCalcField && onUpdateCalculatedField) {
1739
2423
  onUpdateCalculatedField(field);
1740
2424
  } else if (onAddCalculatedField) {
@@ -1743,14 +2427,14 @@ function PivotConfig({
1743
2427
  setShowCalcModal(false);
1744
2428
  setEditingCalcField(null);
1745
2429
  }, [editingCalcField, onAddCalculatedField, onUpdateCalculatedField]);
1746
- const handleCloseCalcModal = (0, import_react8.useCallback)(() => {
2430
+ const handleCloseCalcModal = (0, import_react9.useCallback)(() => {
1747
2431
  setShowCalcModal(false);
1748
2432
  setEditingCalcField(null);
1749
2433
  }, []);
1750
- return /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { className: "vpg-pivot-config", children: [
1751
- /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { className: "vpg-config-header", children: [
1752
- /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("h3", { className: "vpg-config-title", children: [
1753
- /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("svg", { className: "vpg-icon", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
2434
+ return /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { className: "vpg-pivot-config", children: [
2435
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { className: "vpg-config-header", children: [
2436
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("h3", { className: "vpg-config-title", children: [
2437
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("svg", { className: "vpg-icon", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
1754
2438
  "path",
1755
2439
  {
1756
2440
  strokeLinecap: "round",
@@ -1761,13 +2445,13 @@ function PivotConfig({
1761
2445
  ) }),
1762
2446
  "Fields"
1763
2447
  ] }),
1764
- /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("div", { className: "vpg-header-actions", children: assignedCount > 0 && /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
2448
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("div", { className: "vpg-header-actions", children: assignedCount > 0 && /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
1765
2449
  "button",
1766
2450
  {
1767
2451
  className: "vpg-action-btn vpg-clear-btn",
1768
2452
  title: "Clear all",
1769
2453
  onClick: onClearConfig,
1770
- children: /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("svg", { className: "vpg-icon-sm", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
2454
+ children: /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("svg", { className: "vpg-icon-sm", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
1771
2455
  "path",
1772
2456
  {
1773
2457
  strokeLinecap: "round",
@@ -1779,9 +2463,9 @@ function PivotConfig({
1779
2463
  }
1780
2464
  ) })
1781
2465
  ] }),
1782
- assignedCount > 0 && /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { className: "vpg-assigned-section", children: [
1783
- /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("div", { className: "vpg-section-label", children: "Active" }),
1784
- /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("div", { className: "vpg-assigned-list", children: assignedFields.map((field) => /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(
2466
+ assignedCount > 0 && /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { className: "vpg-assigned-section", children: [
2467
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("div", { className: "vpg-section-label", children: "Active" }),
2468
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("div", { className: "vpg-assigned-list", children: assignedFields.map((field) => /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(
1785
2469
  "div",
1786
2470
  {
1787
2471
  className: `vpg-assigned-item vpg-type-${field.assignedTo}${field.isCalculated ? " vpg-type-calc" : ""}`,
@@ -1790,12 +2474,12 @@ function PivotConfig({
1790
2474
  onDragStart: (e) => handleDragStart(field.field, e),
1791
2475
  onDragEnd,
1792
2476
  children: [
1793
- /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { className: "vpg-item-main", children: [
1794
- /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("span", { className: `vpg-item-badge ${field.assignedTo}${field.isCalculated ? " calc" : ""}`, children: field.isCalculated ? "\u0192" : field.assignedTo === "row" ? "R" : field.assignedTo === "column" ? "C" : (0, import_tinypivot_core6.getAggregationSymbol)(field.valueConfig?.aggregation || "sum") }),
1795
- /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("span", { className: "vpg-item-name", children: getFieldDisplayName(field) })
2477
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { className: "vpg-item-main", children: [
2478
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("span", { className: `vpg-item-badge ${field.assignedTo}${field.isCalculated ? " calc" : ""}`, children: field.isCalculated ? "\u0192" : field.assignedTo === "row" ? "R" : field.assignedTo === "column" ? "C" : (0, import_tinypivot_core7.getAggregationSymbol)(field.valueConfig?.aggregation || "sum") }),
2479
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("span", { className: "vpg-item-name", children: getFieldDisplayName(field) })
1796
2480
  ] }),
1797
- /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { className: "vpg-item-actions", children: [
1798
- (field.assignedTo === "row" || field.assignedTo === "column") && /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
2481
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { className: "vpg-item-actions", children: [
2482
+ (field.assignedTo === "row" || field.assignedTo === "column") && /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
1799
2483
  "button",
1800
2484
  {
1801
2485
  className: "vpg-toggle-btn",
@@ -1804,14 +2488,14 @@ function PivotConfig({
1804
2488
  e.stopPropagation();
1805
2489
  toggleRowColumn(field.field, field.assignedTo);
1806
2490
  },
1807
- children: /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
2491
+ children: /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
1808
2492
  "svg",
1809
2493
  {
1810
2494
  className: "vpg-icon-xs",
1811
2495
  fill: "none",
1812
2496
  stroke: "currentColor",
1813
2497
  viewBox: "0 0 24 24",
1814
- children: /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
2498
+ children: /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
1815
2499
  "path",
1816
2500
  {
1817
2501
  strokeLinecap: "round",
@@ -1824,7 +2508,7 @@ function PivotConfig({
1824
2508
  )
1825
2509
  }
1826
2510
  ),
1827
- field.assignedTo === "value" && field.valueConfig && /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
2511
+ field.assignedTo === "value" && field.valueConfig && /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
1828
2512
  "select",
1829
2513
  {
1830
2514
  className: "vpg-agg-select",
@@ -1838,7 +2522,7 @@ function PivotConfig({
1838
2522
  );
1839
2523
  },
1840
2524
  onClick: (e) => e.stopPropagation(),
1841
- children: import_tinypivot_core6.AGGREGATION_OPTIONS.map((agg) => /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(
2525
+ children: import_tinypivot_core7.AGGREGATION_OPTIONS.map((agg) => /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(
1842
2526
  "option",
1843
2527
  {
1844
2528
  value: agg.value,
@@ -1854,7 +2538,7 @@ function PivotConfig({
1854
2538
  ))
1855
2539
  }
1856
2540
  ),
1857
- /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
2541
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
1858
2542
  "button",
1859
2543
  {
1860
2544
  className: "vpg-remove-btn",
@@ -1872,14 +2556,14 @@ function PivotConfig({
1872
2556
  field.field
1873
2557
  )) })
1874
2558
  ] }),
1875
- /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { className: "vpg-unassigned-section", children: [
1876
- /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("div", { className: "vpg-section-header", children: /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { className: "vpg-section-label", children: [
2559
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { className: "vpg-unassigned-section", children: [
2560
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("div", { className: "vpg-section-header", children: /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { className: "vpg-section-label", children: [
1877
2561
  "Available",
1878
2562
  " ",
1879
- /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("span", { className: "vpg-count", children: unassignedFields.length })
2563
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("span", { className: "vpg-count", children: unassignedFields.length })
1880
2564
  ] }) }),
1881
- /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { className: "vpg-field-search", children: [
1882
- /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("svg", { className: "vpg-search-icon", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
2565
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { className: "vpg-field-search", children: [
2566
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("svg", { className: "vpg-search-icon", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
1883
2567
  "path",
1884
2568
  {
1885
2569
  strokeLinecap: "round",
@@ -1888,7 +2572,7 @@ function PivotConfig({
1888
2572
  d: "M21 21l-6-6m2-5a7 7 0 11-14 0 7 7 0 0114 0z"
1889
2573
  }
1890
2574
  ) }),
1891
- /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
2575
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
1892
2576
  "input",
1893
2577
  {
1894
2578
  type: "text",
@@ -1898,7 +2582,7 @@ function PivotConfig({
1898
2582
  className: "vpg-search-input"
1899
2583
  }
1900
2584
  ),
1901
- fieldSearch && /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("button", { className: "vpg-clear-search", onClick: () => setFieldSearch(""), children: /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("svg", { className: "vpg-icon-xs", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
2585
+ fieldSearch && /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("button", { className: "vpg-clear-search", onClick: () => setFieldSearch(""), children: /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("svg", { className: "vpg-icon-xs", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
1902
2586
  "path",
1903
2587
  {
1904
2588
  strokeLinecap: "round",
@@ -1908,8 +2592,8 @@ function PivotConfig({
1908
2592
  }
1909
2593
  ) }) })
1910
2594
  ] }),
1911
- /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { className: "vpg-field-list", children: [
1912
- filteredUnassignedFields.map((field) => /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(
2595
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { className: "vpg-field-list", children: [
2596
+ filteredUnassignedFields.map((field) => /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(
1913
2597
  "div",
1914
2598
  {
1915
2599
  className: `vpg-field-item${field.isNumeric && !field.isCalculated ? " vpg-is-numeric" : ""}${field.isCalculated ? " vpg-is-calculated" : ""}`,
@@ -1918,10 +2602,10 @@ function PivotConfig({
1918
2602
  onDragStart: (e) => handleDragStart(field.field, e),
1919
2603
  onDragEnd,
1920
2604
  children: [
1921
- /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("span", { className: `vpg-field-type-icon${field.isCalculated ? " vpg-calc-type" : ""}`, title: field.type, children: getFieldIcon(field.type, field.isCalculated) }),
1922
- /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("span", { className: "vpg-field-name", children: getFieldDisplayName(field) }),
1923
- field.isCalculated ? /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(import_jsx_runtime4.Fragment, { children: [
1924
- /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
2605
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("span", { className: `vpg-field-type-icon${field.isCalculated ? " vpg-calc-type" : ""}`, title: field.type, children: getFieldIcon(field.type, field.isCalculated) }),
2606
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("span", { className: "vpg-field-name", children: getFieldDisplayName(field) }),
2607
+ field.isCalculated ? /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(import_jsx_runtime5.Fragment, { children: [
2608
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
1925
2609
  "button",
1926
2610
  {
1927
2611
  className: "vpg-field-edit",
@@ -1935,7 +2619,7 @@ function PivotConfig({
1935
2619
  children: "\u270E"
1936
2620
  }
1937
2621
  ),
1938
- /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
2622
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
1939
2623
  "button",
1940
2624
  {
1941
2625
  className: "vpg-field-delete",
@@ -1949,22 +2633,22 @@ function PivotConfig({
1949
2633
  children: "\xD7"
1950
2634
  }
1951
2635
  )
1952
- ] }) : /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("span", { className: "vpg-unique-count", children: field.uniqueCount })
2636
+ ] }) : /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("span", { className: "vpg-unique-count", children: field.uniqueCount })
1953
2637
  ]
1954
2638
  },
1955
2639
  field.field
1956
2640
  )),
1957
- filteredUnassignedFields.length === 0 && fieldSearch && /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { className: "vpg-empty-hint", children: [
2641
+ filteredUnassignedFields.length === 0 && fieldSearch && /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { className: "vpg-empty-hint", children: [
1958
2642
  'No fields match "',
1959
2643
  fieldSearch,
1960
2644
  '"'
1961
2645
  ] }),
1962
- unassignedFields.length === 0 && /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("div", { className: "vpg-empty-hint", children: "All fields assigned" })
2646
+ unassignedFields.length === 0 && /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("div", { className: "vpg-empty-hint", children: "All fields assigned" })
1963
2647
  ] })
1964
2648
  ] }),
1965
- /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { className: "vpg-options-section", children: [
1966
- /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("label", { className: "vpg-option-toggle", children: [
1967
- /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
2649
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { className: "vpg-options-section", children: [
2650
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("label", { className: "vpg-option-toggle", children: [
2651
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
1968
2652
  "input",
1969
2653
  {
1970
2654
  type: "checkbox",
@@ -1972,14 +2656,14 @@ function PivotConfig({
1972
2656
  onChange: (e) => handleTotalsToggle(e.target.checked)
1973
2657
  }
1974
2658
  ),
1975
- /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("span", { children: "Totals" })
2659
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("span", { children: "Totals" })
1976
2660
  ] }),
1977
- /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("button", { className: "vpg-calc-btn", onClick: () => openCalcModal(), title: "Add calculated field (e.g. Profit Margin %)", children: [
1978
- /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("span", { className: "vpg-calc-icon", children: "\u0192" }),
1979
- /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("span", { children: "+ Calc" })
2661
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("button", { className: "vpg-calc-btn", onClick: () => openCalcModal(), title: "Add calculated field (e.g. Profit Margin %)", children: [
2662
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("span", { className: "vpg-calc-icon", children: "\u0192" }),
2663
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("span", { children: "+ Calc" })
1980
2664
  ] })
1981
2665
  ] }),
1982
- /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
2666
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
1983
2667
  CalculatedFieldModal,
1984
2668
  {
1985
2669
  show: showCalcModal,
@@ -1993,9 +2677,9 @@ function PivotConfig({
1993
2677
  }
1994
2678
 
1995
2679
  // src/components/PivotSkeleton.tsx
1996
- var import_tinypivot_core7 = require("@smallwebco/tinypivot-core");
1997
- var import_react9 = require("react");
1998
- var import_jsx_runtime5 = require("react/jsx-runtime");
2680
+ var import_tinypivot_core8 = require("@smallwebco/tinypivot-core");
2681
+ var import_react10 = require("react");
2682
+ var import_jsx_runtime6 = require("react/jsx-runtime");
1999
2683
  function PivotSkeleton({
2000
2684
  rowFields,
2001
2685
  columnFields,
@@ -2018,7 +2702,7 @@ function PivotSkeleton({
2018
2702
  onReorderColumnFields
2019
2703
  }) {
2020
2704
  const { showWatermark, canUsePivot, isDemo } = useLicense();
2021
- const getValueFieldDisplayName = (0, import_react9.useCallback)((field) => {
2705
+ const getValueFieldDisplayName = (0, import_react10.useCallback)((field) => {
2022
2706
  if (field.startsWith("calc:")) {
2023
2707
  const calcId = field.replace("calc:", "");
2024
2708
  const calcField = calculatedFields?.find((c) => c.id === calcId);
@@ -2026,15 +2710,15 @@ function PivotSkeleton({
2026
2710
  }
2027
2711
  return field;
2028
2712
  }, [calculatedFields]);
2029
- const isCalculatedField = (0, import_react9.useCallback)((field) => {
2713
+ const isCalculatedField = (0, import_react10.useCallback)((field) => {
2030
2714
  return field.startsWith("calc:");
2031
2715
  }, []);
2032
- const [dragOverArea, setDragOverArea] = (0, import_react9.useState)(null);
2033
- const [reorderDragSource, setReorderDragSource] = (0, import_react9.useState)(null);
2034
- const [reorderDropTarget, setReorderDropTarget] = (0, import_react9.useState)(null);
2035
- const [sortDirection, setSortDirection] = (0, import_react9.useState)("asc");
2036
- const [sortTarget, setSortTarget] = (0, import_react9.useState)("row");
2037
- const toggleSort = (0, import_react9.useCallback)((target = "row") => {
2716
+ const [dragOverArea, setDragOverArea] = (0, import_react10.useState)(null);
2717
+ const [reorderDragSource, setReorderDragSource] = (0, import_react10.useState)(null);
2718
+ const [reorderDropTarget, setReorderDropTarget] = (0, import_react10.useState)(null);
2719
+ const [sortDirection, setSortDirection] = (0, import_react10.useState)("asc");
2720
+ const [sortTarget, setSortTarget] = (0, import_react10.useState)("row");
2721
+ const toggleSort = (0, import_react10.useCallback)((target = "row") => {
2038
2722
  if (sortTarget === target) {
2039
2723
  setSortDirection((prev) => prev === "asc" ? "desc" : "asc");
2040
2724
  } else {
@@ -2042,13 +2726,13 @@ function PivotSkeleton({
2042
2726
  setSortDirection("asc");
2043
2727
  }
2044
2728
  }, [sortTarget]);
2045
- const [selectedCell, setSelectedCell] = (0, import_react9.useState)(null);
2046
- const [selectionStart, setSelectionStart] = (0, import_react9.useState)(null);
2047
- const [selectionEnd, setSelectionEnd] = (0, import_react9.useState)(null);
2048
- const [isSelecting, setIsSelecting] = (0, import_react9.useState)(false);
2049
- const [showCopyToast, setShowCopyToast] = (0, import_react9.useState)(false);
2050
- const [copyToastMessage, setCopyToastMessage] = (0, import_react9.useState)("");
2051
- const selectionBounds = (0, import_react9.useMemo)(() => {
2729
+ const [selectedCell, setSelectedCell] = (0, import_react10.useState)(null);
2730
+ const [selectionStart, setSelectionStart] = (0, import_react10.useState)(null);
2731
+ const [selectionEnd, setSelectionEnd] = (0, import_react10.useState)(null);
2732
+ const [isSelecting, setIsSelecting] = (0, import_react10.useState)(false);
2733
+ const [showCopyToast, setShowCopyToast] = (0, import_react10.useState)(false);
2734
+ const [copyToastMessage, setCopyToastMessage] = (0, import_react10.useState)("");
2735
+ const selectionBounds = (0, import_react10.useMemo)(() => {
2052
2736
  if (!selectionStart || !selectionEnd)
2053
2737
  return null;
2054
2738
  return {
@@ -2058,7 +2742,7 @@ function PivotSkeleton({
2058
2742
  maxCol: Math.max(selectionStart.col, selectionEnd.col)
2059
2743
  };
2060
2744
  }, [selectionStart, selectionEnd]);
2061
- const handleCellMouseDown = (0, import_react9.useCallback)(
2745
+ const handleCellMouseDown = (0, import_react10.useCallback)(
2062
2746
  (rowIndex, colIndex, event) => {
2063
2747
  event.preventDefault();
2064
2748
  if (event.shiftKey && selectedCell) {
@@ -2072,7 +2756,7 @@ function PivotSkeleton({
2072
2756
  },
2073
2757
  [selectedCell]
2074
2758
  );
2075
- const handleCellMouseEnter = (0, import_react9.useCallback)(
2759
+ const handleCellMouseEnter = (0, import_react10.useCallback)(
2076
2760
  (rowIndex, colIndex) => {
2077
2761
  if (isSelecting) {
2078
2762
  setSelectionEnd({ row: rowIndex, col: colIndex });
@@ -2080,7 +2764,7 @@ function PivotSkeleton({
2080
2764
  },
2081
2765
  [isSelecting]
2082
2766
  );
2083
- const isCellSelected = (0, import_react9.useCallback)(
2767
+ const isCellSelected = (0, import_react10.useCallback)(
2084
2768
  (rowIndex, colIndex) => {
2085
2769
  if (!selectionBounds) {
2086
2770
  return selectedCell?.row === rowIndex && selectedCell?.col === colIndex;
@@ -2090,12 +2774,12 @@ function PivotSkeleton({
2090
2774
  },
2091
2775
  [selectionBounds, selectedCell]
2092
2776
  );
2093
- (0, import_react9.useEffect)(() => {
2777
+ (0, import_react10.useEffect)(() => {
2094
2778
  const handleMouseUp = () => setIsSelecting(false);
2095
2779
  document.addEventListener("mouseup", handleMouseUp);
2096
2780
  return () => document.removeEventListener("mouseup", handleMouseUp);
2097
2781
  }, []);
2098
- const sortedRowIndices = (0, import_react9.useMemo)(() => {
2782
+ const sortedRowIndices = (0, import_react10.useMemo)(() => {
2099
2783
  if (!pivotResult)
2100
2784
  return [];
2101
2785
  const indices = pivotResult.rowHeaders.map((_, i) => i);
@@ -2123,7 +2807,7 @@ function PivotSkeleton({
2123
2807
  });
2124
2808
  return indices;
2125
2809
  }, [pivotResult, sortTarget, sortDirection]);
2126
- const copySelectionToClipboard = (0, import_react9.useCallback)(() => {
2810
+ const copySelectionToClipboard = (0, import_react10.useCallback)(() => {
2127
2811
  if (!selectionBounds || !pivotResult)
2128
2812
  return;
2129
2813
  const { minRow, maxRow, minCol, maxCol } = selectionBounds;
@@ -2149,7 +2833,7 @@ function PivotSkeleton({
2149
2833
  console.error("Copy failed:", err);
2150
2834
  });
2151
2835
  }, [selectionBounds, pivotResult, sortedRowIndices]);
2152
- (0, import_react9.useEffect)(() => {
2836
+ (0, import_react10.useEffect)(() => {
2153
2837
  const handleKeydown = (event) => {
2154
2838
  if (!selectionBounds)
2155
2839
  return;
@@ -2167,7 +2851,7 @@ function PivotSkeleton({
2167
2851
  document.addEventListener("keydown", handleKeydown);
2168
2852
  return () => document.removeEventListener("keydown", handleKeydown);
2169
2853
  }, [selectionBounds, copySelectionToClipboard]);
2170
- const selectionStats = (0, import_react9.useMemo)(() => {
2854
+ const selectionStats = (0, import_react10.useMemo)(() => {
2171
2855
  if (!selectionBounds || !pivotResult)
2172
2856
  return null;
2173
2857
  const { minRow, maxRow, minCol, maxCol } = selectionBounds;
@@ -2196,18 +2880,18 @@ function PivotSkeleton({
2196
2880
  avg
2197
2881
  };
2198
2882
  }, [selectionBounds, pivotResult, sortedRowIndices]);
2199
- const formatStatValue = (0, import_react9.useCallback)((val) => {
2883
+ const formatStatValue = (0, import_react10.useCallback)((val) => {
2200
2884
  if (Math.abs(val) >= 1e6)
2201
2885
  return `${(val / 1e6).toFixed(2)}M`;
2202
2886
  if (Math.abs(val) >= 1e3)
2203
2887
  return `${(val / 1e3).toFixed(2)}K`;
2204
2888
  return val.toFixed(2);
2205
2889
  }, []);
2206
- const columnHeaderCells = (0, import_react9.useMemo)(() => {
2890
+ const columnHeaderCells = (0, import_react10.useMemo)(() => {
2207
2891
  if (!pivotResult || pivotResult.headers.length === 0) {
2208
2892
  return [
2209
2893
  valueFields.map((vf) => ({
2210
- label: `${getValueFieldDisplayName(vf.field)} (${(0, import_tinypivot_core7.getAggregationLabel)(vf.aggregation)})`,
2894
+ label: `${getValueFieldDisplayName(vf.field)} (${(0, import_tinypivot_core8.getAggregationLabel)(vf.aggregation)})`,
2211
2895
  colspan: 1
2212
2896
  }))
2213
2897
  ];
@@ -2231,13 +2915,13 @@ function PivotSkeleton({
2231
2915
  return result;
2232
2916
  }, [pivotResult, valueFields]);
2233
2917
  const hasActiveFilters = activeFilters && activeFilters.length > 0;
2234
- const filterSummary = (0, import_react9.useMemo)(() => {
2918
+ const filterSummary = (0, import_react10.useMemo)(() => {
2235
2919
  if (!activeFilters || activeFilters.length === 0)
2236
2920
  return "";
2237
2921
  return activeFilters.map((f) => f.column).join(", ");
2238
2922
  }, [activeFilters]);
2239
- const [showFilterTooltip, setShowFilterTooltip] = (0, import_react9.useState)(false);
2240
- const filterTooltipDetails = (0, import_react9.useMemo)(() => {
2923
+ const [showFilterTooltip, setShowFilterTooltip] = (0, import_react10.useState)(false);
2924
+ const filterTooltipDetails = (0, import_react10.useMemo)(() => {
2241
2925
  if (!activeFilters || activeFilters.length === 0)
2242
2926
  return [];
2243
2927
  return activeFilters.map((f) => {
@@ -2262,7 +2946,7 @@ function PivotSkeleton({
2262
2946
  };
2263
2947
  });
2264
2948
  }, [activeFilters]);
2265
- const handleDragOver = (0, import_react9.useCallback)(
2949
+ const handleDragOver = (0, import_react10.useCallback)(
2266
2950
  (area, event) => {
2267
2951
  event.preventDefault();
2268
2952
  event.dataTransfer.dropEffect = "move";
@@ -2270,10 +2954,10 @@ function PivotSkeleton({
2270
2954
  },
2271
2955
  []
2272
2956
  );
2273
- const handleDragLeave = (0, import_react9.useCallback)(() => {
2957
+ const handleDragLeave = (0, import_react10.useCallback)(() => {
2274
2958
  setDragOverArea(null);
2275
2959
  }, []);
2276
- const handleDrop = (0, import_react9.useCallback)(
2960
+ const handleDrop = (0, import_react10.useCallback)(
2277
2961
  (area, event) => {
2278
2962
  event.preventDefault();
2279
2963
  const field = event.dataTransfer?.getData("text/plain");
@@ -2303,7 +2987,7 @@ function PivotSkeleton({
2303
2987
  },
2304
2988
  [rowFields, columnFields, valueFields, onAddRowField, onRemoveRowField, onAddColumnField, onRemoveColumnField, onAddValueField, onRemoveValueField]
2305
2989
  );
2306
- const handleChipDragStart = (0, import_react9.useCallback)(
2990
+ const handleChipDragStart = (0, import_react10.useCallback)(
2307
2991
  (zone, index, event) => {
2308
2992
  setReorderDragSource({ zone, index });
2309
2993
  event.dataTransfer.effectAllowed = "move";
@@ -2314,11 +2998,11 @@ function PivotSkeleton({
2314
2998
  },
2315
2999
  []
2316
3000
  );
2317
- const handleChipDragEnd = (0, import_react9.useCallback)(() => {
3001
+ const handleChipDragEnd = (0, import_react10.useCallback)(() => {
2318
3002
  setReorderDragSource(null);
2319
3003
  setReorderDropTarget(null);
2320
3004
  }, []);
2321
- const handleChipDragOver = (0, import_react9.useCallback)(
3005
+ const handleChipDragOver = (0, import_react10.useCallback)(
2322
3006
  (zone, index, event) => {
2323
3007
  event.preventDefault();
2324
3008
  if (reorderDragSource && reorderDragSource.zone === zone) {
@@ -2328,10 +3012,10 @@ function PivotSkeleton({
2328
3012
  },
2329
3013
  [reorderDragSource]
2330
3014
  );
2331
- const handleChipDragLeave = (0, import_react9.useCallback)(() => {
3015
+ const handleChipDragLeave = (0, import_react10.useCallback)(() => {
2332
3016
  setReorderDropTarget(null);
2333
3017
  }, []);
2334
- const handleChipDrop = (0, import_react9.useCallback)(
3018
+ const handleChipDrop = (0, import_react10.useCallback)(
2335
3019
  (zone, targetIndex, event) => {
2336
3020
  event.preventDefault();
2337
3021
  event.stopPropagation();
@@ -2357,13 +3041,13 @@ function PivotSkeleton({
2357
3041
  },
2358
3042
  [reorderDragSource, rowFields, columnFields, onReorderRowFields, onReorderColumnFields]
2359
3043
  );
2360
- const isChipDragSource = (0, import_react9.useCallback)(
3044
+ const isChipDragSource = (0, import_react10.useCallback)(
2361
3045
  (zone, index) => {
2362
3046
  return reorderDragSource?.zone === zone && reorderDragSource?.index === index;
2363
3047
  },
2364
3048
  [reorderDragSource]
2365
3049
  );
2366
- const isChipDropTarget = (0, import_react9.useCallback)(
3050
+ const isChipDropTarget = (0, import_react10.useCallback)(
2367
3051
  (zone, index) => {
2368
3052
  return reorderDropTarget?.zone === zone && reorderDropTarget?.index === index;
2369
3053
  },
@@ -2371,25 +3055,25 @@ function PivotSkeleton({
2371
3055
  );
2372
3056
  const currentFontSize = fontSize;
2373
3057
  const rowHeaderWidth = 180;
2374
- const rowHeaderColWidth = (0, import_react9.useMemo)(() => {
3058
+ const rowHeaderColWidth = (0, import_react10.useMemo)(() => {
2375
3059
  const numCols = Math.max(rowFields.length, 1);
2376
3060
  return Math.max(rowHeaderWidth / numCols, 80);
2377
3061
  }, [rowFields.length]);
2378
- const getRowHeaderLeftOffset = (0, import_react9.useCallback)((fieldIdx) => {
3062
+ const getRowHeaderLeftOffset = (0, import_react10.useCallback)((fieldIdx) => {
2379
3063
  return fieldIdx * rowHeaderColWidth;
2380
3064
  }, [rowHeaderColWidth]);
2381
- return /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(
3065
+ return /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(
2382
3066
  "div",
2383
3067
  {
2384
3068
  className: `vpg-pivot-skeleton vpg-font-${currentFontSize} ${draggingField ? "vpg-is-dragging" : ""}`,
2385
3069
  children: [
2386
- showCopyToast && /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { className: "vpg-toast", children: [
2387
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("svg", { className: "vpg-icon", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "M5 13l4 4L19 7" }) }),
3070
+ showCopyToast && /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { className: "vpg-toast", children: [
3071
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("svg", { className: "vpg-icon", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "M5 13l4 4L19 7" }) }),
2388
3072
  copyToastMessage
2389
3073
  ] }),
2390
- /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { className: "vpg-skeleton-header", children: [
2391
- /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { className: "vpg-skeleton-title", children: [
2392
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("svg", { className: "vpg-icon", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
3074
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { className: "vpg-skeleton-header", children: [
3075
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { className: "vpg-skeleton-title", children: [
3076
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("svg", { className: "vpg-icon", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
2393
3077
  "path",
2394
3078
  {
2395
3079
  strokeLinecap: "round",
@@ -2398,24 +3082,24 @@ function PivotSkeleton({
2398
3082
  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"
2399
3083
  }
2400
3084
  ) }),
2401
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("span", { children: "Pivot Table" })
3085
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", { children: "Pivot Table" })
2402
3086
  ] }),
2403
- /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { className: "vpg-header-right", children: [
2404
- hasActiveFilters && /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(
3087
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { className: "vpg-header-right", children: [
3088
+ hasActiveFilters && /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(
2405
3089
  "div",
2406
3090
  {
2407
3091
  className: "vpg-filter-indicator",
2408
3092
  onMouseEnter: () => setShowFilterTooltip(true),
2409
3093
  onMouseLeave: () => setShowFilterTooltip(false),
2410
3094
  children: [
2411
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
3095
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
2412
3096
  "svg",
2413
3097
  {
2414
3098
  className: "vpg-filter-icon",
2415
3099
  fill: "none",
2416
3100
  stroke: "currentColor",
2417
3101
  viewBox: "0 0 24 24",
2418
- children: /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
3102
+ children: /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
2419
3103
  "path",
2420
3104
  {
2421
3105
  strokeLinecap: "round",
@@ -2426,11 +3110,11 @@ function PivotSkeleton({
2426
3110
  )
2427
3111
  }
2428
3112
  ),
2429
- /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("span", { className: "vpg-filter-text", children: [
3113
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("span", { className: "vpg-filter-text", children: [
2430
3114
  "Filtered:",
2431
3115
  " ",
2432
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("strong", { children: filterSummary }),
2433
- filteredRowCount !== void 0 && totalRowCount !== void 0 && /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("span", { className: "vpg-filter-count", children: [
3116
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("strong", { children: filterSummary }),
3117
+ filteredRowCount !== void 0 && totalRowCount !== void 0 && /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("span", { className: "vpg-filter-count", children: [
2434
3118
  "(",
2435
3119
  filteredRowCount.toLocaleString(),
2436
3120
  " ",
@@ -2441,13 +3125,13 @@ function PivotSkeleton({
2441
3125
  "rows)"
2442
3126
  ] })
2443
3127
  ] }),
2444
- showFilterTooltip && /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { className: "vpg-filter-tooltip", children: [
2445
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("div", { className: "vpg-tooltip-header", children: "Active Filters" }),
2446
- filterTooltipDetails.map((filter) => /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { className: "vpg-tooltip-filter", children: [
2447
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("div", { className: "vpg-tooltip-column", children: filter.column }),
2448
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("div", { className: "vpg-tooltip-values", children: filter.isRange ? /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("span", { className: "vpg-tooltip-value vpg-range-value", children: filter.displayText }) : /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(import_jsx_runtime5.Fragment, { children: [
2449
- filter.values.map((val, idx) => /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("span", { className: "vpg-tooltip-value", children: val }, idx)),
2450
- filter.remaining > 0 && /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("span", { className: "vpg-tooltip-more", children: [
3128
+ showFilterTooltip && /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { className: "vpg-filter-tooltip", children: [
3129
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("div", { className: "vpg-tooltip-header", children: "Active Filters" }),
3130
+ filterTooltipDetails.map((filter) => /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { className: "vpg-tooltip-filter", children: [
3131
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("div", { className: "vpg-tooltip-column", children: filter.column }),
3132
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("div", { className: "vpg-tooltip-values", children: filter.isRange ? /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", { className: "vpg-tooltip-value vpg-range-value", children: filter.displayText }) : /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(import_jsx_runtime6.Fragment, { children: [
3133
+ filter.values.map((val, idx) => /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", { className: "vpg-tooltip-value", children: val }, idx)),
3134
+ filter.remaining > 0 && /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("span", { className: "vpg-tooltip-more", children: [
2451
3135
  "+",
2452
3136
  filter.remaining,
2453
3137
  " ",
@@ -2455,7 +3139,7 @@ function PivotSkeleton({
2455
3139
  ] })
2456
3140
  ] }) })
2457
3141
  ] }, filter.column)),
2458
- filteredRowCount !== void 0 && totalRowCount !== void 0 && /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { className: "vpg-tooltip-summary", children: [
3142
+ filteredRowCount !== void 0 && totalRowCount !== void 0 && /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { className: "vpg-tooltip-summary", children: [
2459
3143
  "Showing",
2460
3144
  " ",
2461
3145
  filteredRowCount.toLocaleString(),
@@ -2470,20 +3154,20 @@ function PivotSkeleton({
2470
3154
  ]
2471
3155
  }
2472
3156
  ),
2473
- isConfigured && /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { className: "vpg-config-summary", children: [
2474
- /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("span", { className: "vpg-summary-badge vpg-rows", children: [
3157
+ isConfigured && /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { className: "vpg-config-summary", children: [
3158
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("span", { className: "vpg-summary-badge vpg-rows", children: [
2475
3159
  rowFields.length,
2476
3160
  " ",
2477
3161
  "row",
2478
3162
  rowFields.length !== 1 ? "s" : ""
2479
3163
  ] }),
2480
- /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("span", { className: "vpg-summary-badge vpg-cols", children: [
3164
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("span", { className: "vpg-summary-badge vpg-cols", children: [
2481
3165
  columnFields.length,
2482
3166
  " ",
2483
3167
  "col",
2484
3168
  columnFields.length !== 1 ? "s" : ""
2485
3169
  ] }),
2486
- /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("span", { className: "vpg-summary-badge vpg-vals", children: [
3170
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("span", { className: "vpg-summary-badge vpg-vals", children: [
2487
3171
  valueFields.length,
2488
3172
  " ",
2489
3173
  "val",
@@ -2492,8 +3176,8 @@ function PivotSkeleton({
2492
3176
  ] })
2493
3177
  ] })
2494
3178
  ] }),
2495
- !canUsePivot ? /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("div", { className: "vpg-pro-required", children: /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { className: "vpg-pro-content", children: [
2496
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("svg", { className: "vpg-pro-icon", fill: "none", viewBox: "0 0 24 24", stroke: "currentColor", children: /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
3179
+ !canUsePivot ? /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("div", { className: "vpg-pro-required", children: /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { className: "vpg-pro-content", children: [
3180
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("svg", { className: "vpg-pro-icon", fill: "none", viewBox: "0 0 24 24", stroke: "currentColor", children: /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
2497
3181
  "path",
2498
3182
  {
2499
3183
  strokeLinecap: "round",
@@ -2502,12 +3186,12 @@ function PivotSkeleton({
2502
3186
  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"
2503
3187
  }
2504
3188
  ) }),
2505
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("h3", { children: "Pro Feature" }),
2506
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("p", { children: "Pivot Table functionality requires a Pro license." }),
2507
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("a", { href: "https://tiny-pivot.com/#pricing", target: "_blank", rel: "noopener noreferrer", className: "vpg-pro-link", children: "Get Pro License \u2192" })
2508
- ] }) }) : /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(import_jsx_runtime5.Fragment, { children: [
2509
- /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { className: "vpg-config-bar", children: [
2510
- /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(
3189
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("h3", { children: "Pro Feature" }),
3190
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("p", { children: "Pivot Table functionality requires a Pro license." }),
3191
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("a", { href: "https://tiny-pivot.com/#pricing", target: "_blank", rel: "noopener noreferrer", className: "vpg-pro-link", children: "Get Pro License \u2192" })
3192
+ ] }) }) : /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(import_jsx_runtime6.Fragment, { children: [
3193
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { className: "vpg-config-bar", children: [
3194
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(
2511
3195
  "div",
2512
3196
  {
2513
3197
  className: `vpg-drop-zone vpg-row-zone ${dragOverArea === "row" ? "vpg-drag-over" : ""}`,
@@ -2515,12 +3199,12 @@ function PivotSkeleton({
2515
3199
  onDragLeave: handleDragLeave,
2516
3200
  onDrop: (e) => handleDrop("row", e),
2517
3201
  children: [
2518
- /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { className: "vpg-zone-header", children: [
2519
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("span", { className: "vpg-zone-icon vpg-row-icon", children: "\u2193" }),
2520
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("span", { className: "vpg-zone-label", children: "Rows" })
3202
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { className: "vpg-zone-header", children: [
3203
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", { className: "vpg-zone-icon vpg-row-icon", children: "\u2193" }),
3204
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", { className: "vpg-zone-label", children: "Rows" })
2521
3205
  ] }),
2522
- /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { className: "vpg-zone-chips", children: [
2523
- rowFields.map((field, idx) => /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(
3206
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { className: "vpg-zone-chips", children: [
3207
+ rowFields.map((field, idx) => /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(
2524
3208
  "div",
2525
3209
  {
2526
3210
  className: `vpg-mini-chip vpg-row-chip ${isChipDragSource("row", idx) ? "vpg-chip-dragging" : ""} ${isChipDropTarget("row", idx) ? "vpg-chip-drop-target" : ""}`,
@@ -2531,9 +3215,9 @@ function PivotSkeleton({
2531
3215
  onDragLeave: handleChipDragLeave,
2532
3216
  onDrop: (e) => handleChipDrop("row", idx, e),
2533
3217
  children: [
2534
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("span", { className: "vpg-drag-handle", children: "\u22EE\u22EE" }),
2535
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("span", { className: "vpg-mini-name", children: field }),
2536
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
3218
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", { className: "vpg-drag-handle", children: "\u22EE\u22EE" }),
3219
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", { className: "vpg-mini-name", children: field }),
3220
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
2537
3221
  "button",
2538
3222
  {
2539
3223
  className: "vpg-mini-remove",
@@ -2548,12 +3232,12 @@ function PivotSkeleton({
2548
3232
  },
2549
3233
  field
2550
3234
  )),
2551
- rowFields.length === 0 && /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("span", { className: "vpg-zone-hint", children: "Drop here" })
3235
+ rowFields.length === 0 && /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", { className: "vpg-zone-hint", children: "Drop here" })
2552
3236
  ] })
2553
3237
  ]
2554
3238
  }
2555
3239
  ),
2556
- /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(
3240
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(
2557
3241
  "div",
2558
3242
  {
2559
3243
  className: `vpg-drop-zone vpg-column-zone ${dragOverArea === "column" ? "vpg-drag-over" : ""}`,
@@ -2561,12 +3245,12 @@ function PivotSkeleton({
2561
3245
  onDragLeave: handleDragLeave,
2562
3246
  onDrop: (e) => handleDrop("column", e),
2563
3247
  children: [
2564
- /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { className: "vpg-zone-header", children: [
2565
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("span", { className: "vpg-zone-icon vpg-column-icon", children: "\u2192" }),
2566
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("span", { className: "vpg-zone-label", children: "Columns" })
3248
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { className: "vpg-zone-header", children: [
3249
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", { className: "vpg-zone-icon vpg-column-icon", children: "\u2192" }),
3250
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", { className: "vpg-zone-label", children: "Columns" })
2567
3251
  ] }),
2568
- /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { className: "vpg-zone-chips", children: [
2569
- columnFields.map((field, idx) => /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(
3252
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { className: "vpg-zone-chips", children: [
3253
+ columnFields.map((field, idx) => /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(
2570
3254
  "div",
2571
3255
  {
2572
3256
  className: `vpg-mini-chip vpg-column-chip ${isChipDragSource("column", idx) ? "vpg-chip-dragging" : ""} ${isChipDropTarget("column", idx) ? "vpg-chip-drop-target" : ""}`,
@@ -2577,9 +3261,9 @@ function PivotSkeleton({
2577
3261
  onDragLeave: handleChipDragLeave,
2578
3262
  onDrop: (e) => handleChipDrop("column", idx, e),
2579
3263
  children: [
2580
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("span", { className: "vpg-drag-handle", children: "\u22EE\u22EE" }),
2581
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("span", { className: "vpg-mini-name", children: field }),
2582
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
3264
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", { className: "vpg-drag-handle", children: "\u22EE\u22EE" }),
3265
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", { className: "vpg-mini-name", children: field }),
3266
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
2583
3267
  "button",
2584
3268
  {
2585
3269
  className: "vpg-mini-remove",
@@ -2594,12 +3278,12 @@ function PivotSkeleton({
2594
3278
  },
2595
3279
  field
2596
3280
  )),
2597
- columnFields.length === 0 && /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("span", { className: "vpg-zone-hint", children: "Drop here" })
3281
+ columnFields.length === 0 && /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", { className: "vpg-zone-hint", children: "Drop here" })
2598
3282
  ] })
2599
3283
  ]
2600
3284
  }
2601
3285
  ),
2602
- /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(
3286
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(
2603
3287
  "div",
2604
3288
  {
2605
3289
  className: `vpg-drop-zone vpg-value-zone ${dragOverArea === "value" ? "vpg-drag-over" : ""}`,
@@ -2607,19 +3291,19 @@ function PivotSkeleton({
2607
3291
  onDragLeave: handleDragLeave,
2608
3292
  onDrop: (e) => handleDrop("value", e),
2609
3293
  children: [
2610
- /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { className: "vpg-zone-header", children: [
2611
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("span", { className: "vpg-zone-icon vpg-value-icon", children: "\u03A3" }),
2612
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("span", { className: "vpg-zone-label", children: "Values" })
3294
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { className: "vpg-zone-header", children: [
3295
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", { className: "vpg-zone-icon vpg-value-icon", children: "\u03A3" }),
3296
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", { className: "vpg-zone-label", children: "Values" })
2613
3297
  ] }),
2614
- /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { className: "vpg-zone-chips", children: [
2615
- valueFields.map((vf) => /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(
3298
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { className: "vpg-zone-chips", children: [
3299
+ valueFields.map((vf) => /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(
2616
3300
  "div",
2617
3301
  {
2618
3302
  className: `vpg-mini-chip vpg-value-chip${isCalculatedField(vf.field) ? " vpg-calc-chip" : ""}`,
2619
3303
  children: [
2620
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("span", { className: "vpg-agg-symbol", children: isCalculatedField(vf.field) ? "\u0192" : (0, import_tinypivot_core7.getAggregationSymbol)(vf.aggregation) }),
2621
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("span", { className: "vpg-mini-name", children: getValueFieldDisplayName(vf.field) }),
2622
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
3304
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", { className: "vpg-agg-symbol", children: isCalculatedField(vf.field) ? "\u0192" : (0, import_tinypivot_core8.getAggregationSymbol)(vf.aggregation) }),
3305
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", { className: "vpg-mini-name", children: getValueFieldDisplayName(vf.field) }),
3306
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
2623
3307
  "button",
2624
3308
  {
2625
3309
  className: "vpg-mini-remove",
@@ -2631,21 +3315,21 @@ function PivotSkeleton({
2631
3315
  },
2632
3316
  `${vf.field}-${vf.aggregation}`
2633
3317
  )),
2634
- valueFields.length === 0 && /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("span", { className: "vpg-zone-hint", children: "Drop numeric" })
3318
+ valueFields.length === 0 && /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", { className: "vpg-zone-hint", children: "Drop numeric" })
2635
3319
  ] })
2636
3320
  ]
2637
3321
  }
2638
3322
  )
2639
3323
  ] }),
2640
- (!isConfigured || !pivotResult) && /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("div", { className: "vpg-placeholder", children: /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { className: "vpg-placeholder-content", children: [
2641
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
3324
+ (!isConfigured || !pivotResult) && /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("div", { className: "vpg-placeholder", children: /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { className: "vpg-placeholder-content", children: [
3325
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
2642
3326
  "svg",
2643
3327
  {
2644
3328
  className: "vpg-placeholder-icon",
2645
3329
  fill: "none",
2646
3330
  viewBox: "0 0 24 24",
2647
3331
  stroke: "currentColor",
2648
- children: /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
3332
+ children: /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
2649
3333
  "path",
2650
3334
  {
2651
3335
  strokeLinecap: "round",
@@ -2656,58 +3340,58 @@ function PivotSkeleton({
2656
3340
  )
2657
3341
  }
2658
3342
  ),
2659
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("span", { className: "vpg-placeholder-text", children: valueFields.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(import_jsx_runtime5.Fragment, { children: [
3343
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", { className: "vpg-placeholder-text", children: valueFields.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(import_jsx_runtime6.Fragment, { children: [
2660
3344
  "Add a",
2661
3345
  " ",
2662
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("strong", { children: "Values" }),
3346
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("strong", { children: "Values" }),
2663
3347
  " ",
2664
3348
  "field to see your pivot table"
2665
- ] }) : rowFields.length === 0 && columnFields.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(import_jsx_runtime5.Fragment, { children: [
3349
+ ] }) : rowFields.length === 0 && columnFields.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(import_jsx_runtime6.Fragment, { children: [
2666
3350
  "Add",
2667
3351
  " ",
2668
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("strong", { children: "Row" }),
3352
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("strong", { children: "Row" }),
2669
3353
  " ",
2670
3354
  "or",
2671
3355
  " ",
2672
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("strong", { children: "Column" }),
3356
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("strong", { children: "Column" }),
2673
3357
  " ",
2674
3358
  "fields to group your data"
2675
3359
  ] }) : "Your pivot table will appear here" })
2676
3360
  ] }) }),
2677
- isConfigured && pivotResult && /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("div", { className: "vpg-table-container", children: /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("table", { className: "vpg-pivot-table", children: [
2678
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("thead", { children: columnHeaderCells.map((headerRow, levelIdx) => /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("tr", { className: "vpg-column-header-row", children: [
2679
- levelIdx === 0 && (rowFields.length > 0 ? rowFields : ["Rows"]).map((field, fieldIdx) => /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
3361
+ isConfigured && pivotResult && /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("div", { className: "vpg-table-container", children: /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("table", { className: "vpg-pivot-table", children: [
3362
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("thead", { children: columnHeaderCells.map((headerRow, levelIdx) => /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("tr", { className: "vpg-column-header-row", children: [
3363
+ levelIdx === 0 && (rowFields.length > 0 ? rowFields : ["Rows"]).map((field, fieldIdx) => /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
2680
3364
  "th",
2681
3365
  {
2682
3366
  className: "vpg-row-header-label",
2683
3367
  rowSpan: columnHeaderCells.length,
2684
3368
  style: { width: `${rowHeaderColWidth}px`, minWidth: "80px", left: `${getRowHeaderLeftOffset(fieldIdx)}px` },
2685
3369
  onClick: () => toggleSort("row"),
2686
- children: /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { className: "vpg-header-content", children: [
2687
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("span", { children: field }),
2688
- (fieldIdx === rowFields.length - 1 || rowFields.length === 0) && /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("span", { className: `vpg-sort-indicator ${sortTarget === "row" ? "active" : ""}`, children: sortTarget === "row" ? sortDirection === "asc" ? "\u2191" : "\u2193" : "\u21C5" })
3370
+ children: /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { className: "vpg-header-content", children: [
3371
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", { children: field }),
3372
+ (fieldIdx === rowFields.length - 1 || rowFields.length === 0) && /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", { className: `vpg-sort-indicator ${sortTarget === "row" ? "active" : ""}`, children: sortTarget === "row" ? sortDirection === "asc" ? "\u2191" : "\u2193" : "\u21C5" })
2689
3373
  ] })
2690
3374
  },
2691
3375
  `row-header-${fieldIdx}`
2692
3376
  )),
2693
- headerRow.map((cell, idx) => /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
3377
+ headerRow.map((cell, idx) => /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
2694
3378
  "th",
2695
3379
  {
2696
3380
  className: "vpg-column-header-cell",
2697
3381
  colSpan: cell.colspan,
2698
3382
  onClick: () => levelIdx === columnHeaderCells.length - 1 && toggleSort(idx),
2699
- children: /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { className: "vpg-header-content", children: [
2700
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("span", { children: cell.label }),
2701
- levelIdx === columnHeaderCells.length - 1 && /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("span", { className: `vpg-sort-indicator ${sortTarget === idx ? "active" : ""}`, children: sortTarget === idx ? sortDirection === "asc" ? "\u2191" : "\u2193" : "\u21C5" })
3383
+ children: /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { className: "vpg-header-content", children: [
3384
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", { children: cell.label }),
3385
+ levelIdx === columnHeaderCells.length - 1 && /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", { className: `vpg-sort-indicator ${sortTarget === idx ? "active" : ""}`, children: sortTarget === idx ? sortDirection === "asc" ? "\u2191" : "\u2193" : "\u21C5" })
2702
3386
  ] })
2703
3387
  },
2704
3388
  idx
2705
3389
  )),
2706
- pivotResult.rowTotals.length > 0 && levelIdx === 0 && /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("th", { className: "vpg-total-header", rowSpan: columnHeaderCells.length, children: "Total" })
3390
+ pivotResult.rowTotals.length > 0 && levelIdx === 0 && /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("th", { className: "vpg-total-header", rowSpan: columnHeaderCells.length, children: "Total" })
2707
3391
  ] }, `header-${levelIdx}`)) }),
2708
- /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("tbody", { children: [
2709
- sortedRowIndices.map((sortedIdx) => /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("tr", { className: "vpg-data-row", children: [
2710
- pivotResult.rowHeaders[sortedIdx].map((val, idx) => /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
3392
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("tbody", { children: [
3393
+ sortedRowIndices.map((sortedIdx) => /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("tr", { className: "vpg-data-row", children: [
3394
+ pivotResult.rowHeaders[sortedIdx].map((val, idx) => /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
2711
3395
  "th",
2712
3396
  {
2713
3397
  className: "vpg-row-header-cell",
@@ -2718,7 +3402,7 @@ function PivotSkeleton({
2718
3402
  )),
2719
3403
  pivotResult.data[sortedIdx].map((cell, colIdx) => {
2720
3404
  const displayRowIdx = sortedRowIndices.indexOf(sortedIdx);
2721
- return /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
3405
+ return /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
2722
3406
  "td",
2723
3407
  {
2724
3408
  className: `vpg-data-cell ${isCellSelected(displayRowIdx, colIdx) ? "selected" : ""} ${cell.value === null ? "vpg-is-null" : ""}`,
@@ -2729,10 +3413,10 @@ function PivotSkeleton({
2729
3413
  colIdx
2730
3414
  );
2731
3415
  }),
2732
- pivotResult.rowTotals[sortedIdx] && /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("td", { className: "vpg-data-cell vpg-total-cell", children: pivotResult.rowTotals[sortedIdx].formattedValue })
3416
+ pivotResult.rowTotals[sortedIdx] && /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("td", { className: "vpg-data-cell vpg-total-cell", children: pivotResult.rowTotals[sortedIdx].formattedValue })
2733
3417
  ] }, sortedIdx)),
2734
- pivotResult.columnTotals.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("tr", { className: "vpg-totals-row", children: [
2735
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
3418
+ pivotResult.columnTotals.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("tr", { className: "vpg-totals-row", children: [
3419
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
2736
3420
  "th",
2737
3421
  {
2738
3422
  className: "vpg-row-header-cell vpg-total-label",
@@ -2741,13 +3425,13 @@ function PivotSkeleton({
2741
3425
  children: "Total"
2742
3426
  }
2743
3427
  ),
2744
- pivotResult.columnTotals.map((cell, colIdx) => /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("td", { className: "vpg-data-cell vpg-total-cell", children: cell.formattedValue }, colIdx)),
2745
- pivotResult.rowTotals.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("td", { className: "vpg-data-cell vpg-grand-total-cell", children: pivotResult.grandTotal.formattedValue })
3428
+ pivotResult.columnTotals.map((cell, colIdx) => /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("td", { className: "vpg-data-cell vpg-total-cell", children: cell.formattedValue }, colIdx)),
3429
+ pivotResult.rowTotals.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("td", { className: "vpg-data-cell vpg-grand-total-cell", children: pivotResult.grandTotal.formattedValue })
2746
3430
  ] })
2747
3431
  ] })
2748
3432
  ] }) }),
2749
- isConfigured && pivotResult && /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { className: "vpg-skeleton-footer", children: [
2750
- /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("span", { className: "vpg-footer-info", children: [
3433
+ isConfigured && pivotResult && /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { className: "vpg-skeleton-footer", children: [
3434
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("span", { className: "vpg-footer-info", children: [
2751
3435
  pivotResult.rowHeaders.length,
2752
3436
  " ",
2753
3437
  "rows \xD7",
@@ -2755,30 +3439,30 @@ function PivotSkeleton({
2755
3439
  " ",
2756
3440
  "columns"
2757
3441
  ] }),
2758
- selectionStats && selectionStats.count > 1 && /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { className: "vpg-selection-stats", children: [
2759
- /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("span", { className: "vpg-stat", children: [
2760
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("span", { className: "vpg-stat-label", children: "Count:" }),
2761
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("span", { className: "vpg-stat-value", children: selectionStats.count })
3442
+ selectionStats && selectionStats.count > 1 && /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { className: "vpg-selection-stats", children: [
3443
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("span", { className: "vpg-stat", children: [
3444
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", { className: "vpg-stat-label", children: "Count:" }),
3445
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", { className: "vpg-stat-value", children: selectionStats.count })
2762
3446
  ] }),
2763
- selectionStats.numericCount > 0 && /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(import_jsx_runtime5.Fragment, { children: [
2764
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("span", { className: "vpg-stat-divider", children: "|" }),
2765
- /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("span", { className: "vpg-stat", children: [
2766
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("span", { className: "vpg-stat-label", children: "Sum:" }),
2767
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("span", { className: "vpg-stat-value", children: formatStatValue(selectionStats.sum) })
3447
+ selectionStats.numericCount > 0 && /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(import_jsx_runtime6.Fragment, { children: [
3448
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", { className: "vpg-stat-divider", children: "|" }),
3449
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("span", { className: "vpg-stat", children: [
3450
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", { className: "vpg-stat-label", children: "Sum:" }),
3451
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", { className: "vpg-stat-value", children: formatStatValue(selectionStats.sum) })
2768
3452
  ] }),
2769
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("span", { className: "vpg-stat-divider", children: "|" }),
2770
- /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("span", { className: "vpg-stat", children: [
2771
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("span", { className: "vpg-stat-label", children: "Avg:" }),
2772
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("span", { className: "vpg-stat-value", children: formatStatValue(selectionStats.avg) })
3453
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", { className: "vpg-stat-divider", children: "|" }),
3454
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("span", { className: "vpg-stat", children: [
3455
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", { className: "vpg-stat-label", children: "Avg:" }),
3456
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", { className: "vpg-stat-value", children: formatStatValue(selectionStats.avg) })
2773
3457
  ] })
2774
3458
  ] })
2775
3459
  ] })
2776
3460
  ] })
2777
3461
  ] }),
2778
- showWatermark && canUsePivot && /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("div", { className: `vpg-watermark ${isDemo ? "vpg-demo-mode" : ""}`, children: isDemo ? /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(import_jsx_runtime5.Fragment, { children: [
2779
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("span", { className: "vpg-demo-badge", children: "DEMO" }),
2780
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("span", { children: "Pro features unlocked for evaluation" }),
2781
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
3462
+ showWatermark && canUsePivot && /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("div", { className: `vpg-watermark ${isDemo ? "vpg-demo-mode" : ""}`, children: isDemo ? /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(import_jsx_runtime6.Fragment, { children: [
3463
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", { className: "vpg-demo-badge", children: "DEMO" }),
3464
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", { children: "Pro features unlocked for evaluation" }),
3465
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
2782
3466
  "a",
2783
3467
  {
2784
3468
  href: "https://tiny-pivot.com/#pricing",
@@ -2788,14 +3472,14 @@ function PivotSkeleton({
2788
3472
  children: "Get Pro License \u2192"
2789
3473
  }
2790
3474
  )
2791
- ] }) : /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("a", { href: "https://tiny-pivot.com", target: "_blank", rel: "noopener noreferrer", children: "Powered by TinyPivot" }) })
3475
+ ] }) : /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("a", { href: "https://tiny-pivot.com", target: "_blank", rel: "noopener noreferrer", children: "Powered by TinyPivot" }) })
2792
3476
  ]
2793
3477
  }
2794
3478
  );
2795
3479
  }
2796
3480
 
2797
3481
  // src/components/DataGrid.tsx
2798
- var import_jsx_runtime6 = require("react/jsx-runtime");
3482
+ var import_jsx_runtime7 = require("react/jsx-runtime");
2799
3483
  var MIN_COL_WIDTH = 120;
2800
3484
  var MAX_COL_WIDTH = 350;
2801
3485
  function DataGrid({
@@ -2820,38 +3504,42 @@ function DataGrid({
2820
3504
  onExport,
2821
3505
  onCopy
2822
3506
  }) {
2823
- const { showWatermark, canUsePivot, isDemo, isPro } = useLicense();
2824
- const currentTheme = (0, import_react10.useMemo)(() => {
3507
+ const { showWatermark, canUsePivot, canUseCharts, isDemo, isPro } = useLicense();
3508
+ const currentTheme = (0, import_react11.useMemo)(() => {
2825
3509
  if (theme === "auto") {
2826
3510
  return window.matchMedia?.("(prefers-color-scheme: dark)").matches ? "dark" : "light";
2827
3511
  }
2828
3512
  return theme;
2829
3513
  }, [theme]);
2830
- const [currentFontSize, setCurrentFontSize] = (0, import_react10.useState)(initialFontSize);
2831
- const [globalSearchTerm, setGlobalSearchTerm] = (0, import_react10.useState)("");
2832
- const [showSearchInput, setShowSearchInput] = (0, import_react10.useState)(false);
2833
- const [currentPage, setCurrentPage] = (0, import_react10.useState)(1);
2834
- const [columnWidths, setColumnWidths] = (0, import_react10.useState)({});
2835
- const [resizingColumnId, setResizingColumnId] = (0, import_react10.useState)(null);
2836
- const [resizeStartX, setResizeStartX] = (0, import_react10.useState)(0);
2837
- const [resizeStartWidth, setResizeStartWidth] = (0, import_react10.useState)(0);
2838
- const [gridHeight, setGridHeight] = (0, import_react10.useState)(initialHeight);
2839
- const [isResizingVertically, setIsResizingVertically] = (0, import_react10.useState)(false);
2840
- const [verticalResizeStartY, setVerticalResizeStartY] = (0, import_react10.useState)(0);
2841
- const [verticalResizeStartHeight, setVerticalResizeStartHeight] = (0, import_react10.useState)(0);
2842
- const [showCopyToast, setShowCopyToast] = (0, import_react10.useState)(false);
2843
- const [copyToastMessage, setCopyToastMessage] = (0, import_react10.useState)("");
2844
- const [viewMode, setViewMode] = (0, import_react10.useState)("grid");
2845
- const [showPivotConfig, setShowPivotConfig] = (0, import_react10.useState)(true);
2846
- const [draggingField, setDraggingField] = (0, import_react10.useState)(null);
2847
- const [activeFilterColumn, setActiveFilterColumn] = (0, import_react10.useState)(null);
2848
- const [filterDropdownPosition, setFilterDropdownPosition] = (0, import_react10.useState)({ top: 0, left: 0, maxHeight: 400 });
2849
- const [selectedCell, setSelectedCell] = (0, import_react10.useState)(null);
2850
- const [selectionStart, setSelectionStart] = (0, import_react10.useState)(null);
2851
- const [selectionEnd, setSelectionEnd] = (0, import_react10.useState)(null);
2852
- const [isSelecting, setIsSelecting] = (0, import_react10.useState)(false);
2853
- const tableContainerRef = (0, import_react10.useRef)(null);
2854
- const tableBodyRef = (0, import_react10.useRef)(null);
3514
+ const [currentFontSize, setCurrentFontSize] = (0, import_react11.useState)(initialFontSize);
3515
+ const [globalSearchTerm, setGlobalSearchTerm] = (0, import_react11.useState)("");
3516
+ const [showSearchInput, setShowSearchInput] = (0, import_react11.useState)(false);
3517
+ const [currentPage, setCurrentPage] = (0, import_react11.useState)(1);
3518
+ const [columnWidths, setColumnWidths] = (0, import_react11.useState)({});
3519
+ const [resizingColumnId, setResizingColumnId] = (0, import_react11.useState)(null);
3520
+ const [resizeStartX, setResizeStartX] = (0, import_react11.useState)(0);
3521
+ const [resizeStartWidth, setResizeStartWidth] = (0, import_react11.useState)(0);
3522
+ const [gridHeight, setGridHeight] = (0, import_react11.useState)(initialHeight);
3523
+ const [isResizingVertically, setIsResizingVertically] = (0, import_react11.useState)(false);
3524
+ const [verticalResizeStartY, setVerticalResizeStartY] = (0, import_react11.useState)(0);
3525
+ const [verticalResizeStartHeight, setVerticalResizeStartHeight] = (0, import_react11.useState)(0);
3526
+ const [showCopyToast, setShowCopyToast] = (0, import_react11.useState)(false);
3527
+ const [copyToastMessage, setCopyToastMessage] = (0, import_react11.useState)("");
3528
+ const [viewMode, setViewMode] = (0, import_react11.useState)("grid");
3529
+ const [_chartConfig, setChartConfig] = (0, import_react11.useState)(null);
3530
+ const handleChartConfigChange = (0, import_react11.useCallback)((config) => {
3531
+ setChartConfig(config);
3532
+ }, []);
3533
+ const [showPivotConfig, setShowPivotConfig] = (0, import_react11.useState)(true);
3534
+ const [draggingField, setDraggingField] = (0, import_react11.useState)(null);
3535
+ const [activeFilterColumn, setActiveFilterColumn] = (0, import_react11.useState)(null);
3536
+ const [filterDropdownPosition, setFilterDropdownPosition] = (0, import_react11.useState)({ top: 0, left: 0, maxHeight: 400 });
3537
+ const [selectedCell, setSelectedCell] = (0, import_react11.useState)(null);
3538
+ const [selectionStart, setSelectionStart] = (0, import_react11.useState)(null);
3539
+ const [selectionEnd, setSelectionEnd] = (0, import_react11.useState)(null);
3540
+ const [isSelecting, setIsSelecting] = (0, import_react11.useState)(false);
3541
+ const tableContainerRef = (0, import_react11.useRef)(null);
3542
+ const tableBodyRef = (0, import_react11.useRef)(null);
2855
3543
  const fontSizeOptions = [
2856
3544
  { value: "xs", label: "S" },
2857
3545
  { value: "sm", label: "M" },
@@ -2875,7 +3563,7 @@ function DataGrid({
2875
3563
  setNumericRangeFilter,
2876
3564
  getNumericRangeFilter
2877
3565
  } = useExcelGrid({ data, enableSorting: true, enableFiltering: true });
2878
- const filteredDataForPivot = (0, import_react10.useMemo)(() => {
3566
+ const filteredDataForPivot = (0, import_react11.useMemo)(() => {
2879
3567
  const filteredRows = table.getFilteredRowModel().rows;
2880
3568
  return filteredRows.map((row) => row.original);
2881
3569
  }, [table, columnFilters]);
@@ -2905,7 +3593,7 @@ function DataGrid({
2905
3593
  addCalculatedField,
2906
3594
  removeCalculatedField
2907
3595
  } = usePivotTable(filteredDataForPivot);
2908
- const activeFilterInfo = (0, import_react10.useMemo)(() => {
3596
+ const activeFilterInfo = (0, import_react11.useMemo)(() => {
2909
3597
  if (activeFilters.length === 0)
2910
3598
  return null;
2911
3599
  return activeFilters.map((f) => {
@@ -2930,8 +3618,8 @@ function DataGrid({
2930
3618
  };
2931
3619
  });
2932
3620
  }, [activeFilters]);
2933
- const rows = (0, import_react10.useMemo)(() => table.getFilteredRowModel().rows, [table, columnFilters]);
2934
- const searchFilteredData = (0, import_react10.useMemo)(() => {
3621
+ const rows = (0, import_react11.useMemo)(() => table.getFilteredRowModel().rows, [table, columnFilters]);
3622
+ const searchFilteredData = (0, import_react11.useMemo)(() => {
2935
3623
  if (!globalSearchTerm.trim() || !enableSearch) {
2936
3624
  return rows;
2937
3625
  }
@@ -2949,22 +3637,22 @@ function DataGrid({
2949
3637
  });
2950
3638
  }, [rows, globalSearchTerm, enableSearch, columnKeys]);
2951
3639
  const totalSearchedRows = searchFilteredData.length;
2952
- const totalPages = (0, import_react10.useMemo)(() => {
3640
+ const totalPages = (0, import_react11.useMemo)(() => {
2953
3641
  if (!enablePagination)
2954
3642
  return 1;
2955
3643
  return Math.max(1, Math.ceil(totalSearchedRows / pageSize));
2956
3644
  }, [enablePagination, totalSearchedRows, pageSize]);
2957
- const paginatedRows = (0, import_react10.useMemo)(() => {
3645
+ const paginatedRows = (0, import_react11.useMemo)(() => {
2958
3646
  if (!enablePagination)
2959
3647
  return searchFilteredData;
2960
3648
  const start = (currentPage - 1) * pageSize;
2961
3649
  const end = start + pageSize;
2962
3650
  return searchFilteredData.slice(start, end);
2963
3651
  }, [enablePagination, searchFilteredData, currentPage, pageSize]);
2964
- (0, import_react10.useEffect)(() => {
3652
+ (0, import_react11.useEffect)(() => {
2965
3653
  setCurrentPage(1);
2966
3654
  }, [columnFilters, globalSearchTerm]);
2967
- const selectionBounds = (0, import_react10.useMemo)(() => {
3655
+ const selectionBounds = (0, import_react11.useMemo)(() => {
2968
3656
  if (!selectionStart || !selectionEnd)
2969
3657
  return null;
2970
3658
  return {
@@ -2974,7 +3662,7 @@ function DataGrid({
2974
3662
  maxCol: Math.max(selectionStart.col, selectionEnd.col)
2975
3663
  };
2976
3664
  }, [selectionStart, selectionEnd]);
2977
- const selectionStats = (0, import_react10.useMemo)(() => {
3665
+ const selectionStats = (0, import_react11.useMemo)(() => {
2978
3666
  if (!selectionBounds)
2979
3667
  return null;
2980
3668
  const { minRow, maxRow, minCol, maxCol } = selectionBounds;
@@ -3004,7 +3692,7 @@ function DataGrid({
3004
3692
  const avg = sum / values.length;
3005
3693
  return { count, sum, avg, numericCount: values.length };
3006
3694
  }, [selectionBounds, rows, columnKeys]);
3007
- (0, import_react10.useEffect)(() => {
3695
+ (0, import_react11.useEffect)(() => {
3008
3696
  if (typeof document === "undefined")
3009
3697
  return;
3010
3698
  if (data.length === 0)
@@ -3028,7 +3716,7 @@ function DataGrid({
3028
3716
  }
3029
3717
  setColumnWidths(widths);
3030
3718
  }, [data, columnKeys]);
3031
- const startColumnResize = (0, import_react10.useCallback)(
3719
+ const startColumnResize = (0, import_react11.useCallback)(
3032
3720
  (columnId, event) => {
3033
3721
  if (!enableColumnResize)
3034
3722
  return;
@@ -3040,7 +3728,7 @@ function DataGrid({
3040
3728
  },
3041
3729
  [enableColumnResize, columnWidths]
3042
3730
  );
3043
- (0, import_react10.useEffect)(() => {
3731
+ (0, import_react11.useEffect)(() => {
3044
3732
  if (!resizingColumnId)
3045
3733
  return;
3046
3734
  const handleResizeMove = (event) => {
@@ -3061,7 +3749,7 @@ function DataGrid({
3061
3749
  document.removeEventListener("mouseup", handleResizeEnd);
3062
3750
  };
3063
3751
  }, [resizingColumnId, resizeStartX, resizeStartWidth]);
3064
- const startVerticalResize = (0, import_react10.useCallback)(
3752
+ const startVerticalResize = (0, import_react11.useCallback)(
3065
3753
  (event) => {
3066
3754
  if (!enableVerticalResize)
3067
3755
  return;
@@ -3072,7 +3760,7 @@ function DataGrid({
3072
3760
  },
3073
3761
  [enableVerticalResize, gridHeight]
3074
3762
  );
3075
- (0, import_react10.useEffect)(() => {
3763
+ (0, import_react11.useEffect)(() => {
3076
3764
  if (!isResizingVertically)
3077
3765
  return;
3078
3766
  const handleVerticalResizeMove = (event) => {
@@ -3090,7 +3778,7 @@ function DataGrid({
3090
3778
  document.removeEventListener("mouseup", handleVerticalResizeEnd);
3091
3779
  };
3092
3780
  }, [isResizingVertically, verticalResizeStartY, verticalResizeStartHeight, minHeight, maxHeight]);
3093
- const handleExport = (0, import_react10.useCallback)(() => {
3781
+ const handleExport = (0, import_react11.useCallback)(() => {
3094
3782
  if (viewMode === "pivot") {
3095
3783
  if (!pivotResult)
3096
3784
  return;
@@ -3136,7 +3824,7 @@ function DataGrid({
3136
3824
  columnKeys,
3137
3825
  onExport
3138
3826
  ]);
3139
- const copySelectionToClipboard = (0, import_react10.useCallback)(() => {
3827
+ const copySelectionToClipboard = (0, import_react11.useCallback)(() => {
3140
3828
  if (!selectionBounds || !enableClipboard)
3141
3829
  return;
3142
3830
  const text = formatSelectionForClipboard(
@@ -3161,7 +3849,7 @@ function DataGrid({
3161
3849
  }
3162
3850
  );
3163
3851
  }, [selectionBounds, enableClipboard, rows, columnKeys, onCopy]);
3164
- const handleMouseDown = (0, import_react10.useCallback)(
3852
+ const handleMouseDown = (0, import_react11.useCallback)(
3165
3853
  (rowIndex, colIndex, event) => {
3166
3854
  event.preventDefault();
3167
3855
  if (event.shiftKey && selectedCell) {
@@ -3185,7 +3873,7 @@ function DataGrid({
3185
3873
  },
3186
3874
  [selectedCell, rows, columnKeys, onCellClick]
3187
3875
  );
3188
- const handleMouseEnter = (0, import_react10.useCallback)(
3876
+ const handleMouseEnter = (0, import_react11.useCallback)(
3189
3877
  (rowIndex, colIndex) => {
3190
3878
  if (isSelecting) {
3191
3879
  setSelectionEnd({ row: rowIndex, col: colIndex });
@@ -3193,12 +3881,12 @@ function DataGrid({
3193
3881
  },
3194
3882
  [isSelecting]
3195
3883
  );
3196
- (0, import_react10.useEffect)(() => {
3884
+ (0, import_react11.useEffect)(() => {
3197
3885
  const handleMouseUp = () => setIsSelecting(false);
3198
3886
  document.addEventListener("mouseup", handleMouseUp);
3199
3887
  return () => document.removeEventListener("mouseup", handleMouseUp);
3200
3888
  }, []);
3201
- (0, import_react10.useEffect)(() => {
3889
+ (0, import_react11.useEffect)(() => {
3202
3890
  const handleKeydown = (event) => {
3203
3891
  if ((event.ctrlKey || event.metaKey) && event.key === "c" && selectionBounds) {
3204
3892
  event.preventDefault();
@@ -3216,7 +3904,7 @@ function DataGrid({
3216
3904
  document.addEventListener("keydown", handleKeydown);
3217
3905
  return () => document.removeEventListener("keydown", handleKeydown);
3218
3906
  }, [selectionBounds, copySelectionToClipboard]);
3219
- const openFilterDropdown = (0, import_react10.useCallback)(
3907
+ const openFilterDropdown = (0, import_react11.useCallback)(
3220
3908
  (columnId, event) => {
3221
3909
  event.stopPropagation();
3222
3910
  const target = event.currentTarget;
@@ -3245,22 +3933,22 @@ function DataGrid({
3245
3933
  },
3246
3934
  []
3247
3935
  );
3248
- const closeFilterDropdown = (0, import_react10.useCallback)(() => {
3936
+ const closeFilterDropdown = (0, import_react11.useCallback)(() => {
3249
3937
  setActiveFilterColumn(null);
3250
3938
  }, []);
3251
- const handleFilter = (0, import_react10.useCallback)(
3939
+ const handleFilter = (0, import_react11.useCallback)(
3252
3940
  (columnId, values) => {
3253
3941
  setColumnFilter(columnId, values);
3254
3942
  },
3255
3943
  [setColumnFilter]
3256
3944
  );
3257
- const handleRangeFilter = (0, import_react10.useCallback)(
3945
+ const handleRangeFilter = (0, import_react11.useCallback)(
3258
3946
  (columnId, range) => {
3259
3947
  setNumericRangeFilter(columnId, range);
3260
3948
  },
3261
3949
  [setNumericRangeFilter]
3262
3950
  );
3263
- const handleSort = (0, import_react10.useCallback)(
3951
+ const handleSort = (0, import_react11.useCallback)(
3264
3952
  (columnId, direction) => {
3265
3953
  if (direction === null) {
3266
3954
  const current = getSortDirection(columnId);
@@ -3284,7 +3972,7 @@ function DataGrid({
3284
3972
  },
3285
3973
  [getSortDirection, toggleSort]
3286
3974
  );
3287
- const isCellSelected = (0, import_react10.useCallback)(
3975
+ const isCellSelected = (0, import_react11.useCallback)(
3288
3976
  (rowIndex, colIndex) => {
3289
3977
  if (!selectionBounds) {
3290
3978
  return selectedCell?.row === rowIndex && selectedCell?.col === colIndex;
@@ -3326,30 +4014,30 @@ function DataGrid({
3326
4014
  }
3327
4015
  return String(value);
3328
4016
  };
3329
- const totalTableWidth = (0, import_react10.useMemo)(() => {
4017
+ const totalTableWidth = (0, import_react11.useMemo)(() => {
3330
4018
  return columnKeys.reduce((sum, key) => sum + (columnWidths[key] || MIN_COL_WIDTH), 0);
3331
4019
  }, [columnKeys, columnWidths]);
3332
4020
  const activeFilterCount = columnFilters.length;
3333
- return /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(
4021
+ return /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(
3334
4022
  "div",
3335
4023
  {
3336
4024
  className: `vpg-data-grid vpg-font-${currentFontSize} vpg-theme-${currentTheme} ${stripedRows ? "vpg-striped" : ""} ${resizingColumnId ? "vpg-resizing" : ""} ${isResizingVertically ? "vpg-resizing-vertical" : ""}`,
3337
4025
  style: { height: `${gridHeight}px` },
3338
4026
  children: [
3339
- showCopyToast && /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { className: "vpg-toast", children: [
3340
- /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("svg", { className: "vpg-icon", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "M5 13l4 4L19 7" }) }),
4027
+ showCopyToast && /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { className: "vpg-toast", children: [
4028
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("svg", { className: "vpg-icon", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "M5 13l4 4L19 7" }) }),
3341
4029
  copyToastMessage
3342
4030
  ] }),
3343
- /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { className: "vpg-toolbar", children: [
3344
- /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { className: "vpg-toolbar-left", children: [
3345
- showPivot && /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { className: "vpg-view-toggle", children: [
3346
- /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(
4031
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { className: "vpg-toolbar", children: [
4032
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { className: "vpg-toolbar-left", children: [
4033
+ showPivot && /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { className: "vpg-view-toggle", children: [
4034
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(
3347
4035
  "button",
3348
4036
  {
3349
4037
  className: `vpg-view-btn ${viewMode === "grid" ? "active" : ""}`,
3350
4038
  onClick: () => setViewMode("grid"),
3351
4039
  children: [
3352
- /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("svg", { className: "vpg-icon", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
4040
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("svg", { className: "vpg-icon", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
3353
4041
  "path",
3354
4042
  {
3355
4043
  strokeLinecap: "round",
@@ -3362,13 +4050,13 @@ function DataGrid({
3362
4050
  ]
3363
4051
  }
3364
4052
  ),
3365
- /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(
4053
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(
3366
4054
  "button",
3367
4055
  {
3368
4056
  className: `vpg-view-btn vpg-pivot-btn ${viewMode === "pivot" ? "active" : ""}`,
3369
4057
  onClick: () => setViewMode("pivot"),
3370
4058
  children: [
3371
- /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("svg", { className: "vpg-icon", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
4059
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("svg", { className: "vpg-icon", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
3372
4060
  "path",
3373
4061
  {
3374
4062
  strokeLinecap: "round",
@@ -3380,16 +4068,37 @@ function DataGrid({
3380
4068
  "Pivot"
3381
4069
  ]
3382
4070
  }
4071
+ ),
4072
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(
4073
+ "button",
4074
+ {
4075
+ className: `vpg-view-btn vpg-chart-btn ${viewMode === "chart" ? "active" : ""} ${!canUseCharts ? "vpg-pro-feature" : ""}`,
4076
+ title: canUseCharts ? "Chart Builder" : "Chart Builder (Pro feature)",
4077
+ onClick: () => canUseCharts && setViewMode("chart"),
4078
+ children: [
4079
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("svg", { className: "vpg-icon", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
4080
+ "path",
4081
+ {
4082
+ strokeLinecap: "round",
4083
+ strokeLinejoin: "round",
4084
+ strokeWidth: 2,
4085
+ 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"
4086
+ }
4087
+ ) }),
4088
+ "Chart",
4089
+ !canUseCharts && /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("span", { className: "vpg-pro-badge", children: "Pro" })
4090
+ ]
4091
+ }
3383
4092
  )
3384
4093
  ] }),
3385
- viewMode === "grid" && /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(import_jsx_runtime6.Fragment, { children: [
3386
- enableSearch && /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("div", { className: "vpg-search-container", children: !showSearchInput ? /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
4094
+ viewMode === "grid" && /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(import_jsx_runtime7.Fragment, { children: [
4095
+ enableSearch && /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", { className: "vpg-search-container", children: !showSearchInput ? /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
3387
4096
  "button",
3388
4097
  {
3389
4098
  className: "vpg-icon-btn",
3390
4099
  title: "Search (Ctrl+F)",
3391
4100
  onClick: () => setShowSearchInput(true),
3392
- children: /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("svg", { className: "vpg-icon", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
4101
+ children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("svg", { className: "vpg-icon", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
3393
4102
  "path",
3394
4103
  {
3395
4104
  strokeLinecap: "round",
@@ -3399,15 +4108,15 @@ function DataGrid({
3399
4108
  }
3400
4109
  ) })
3401
4110
  }
3402
- ) : /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { className: "vpg-search-box", children: [
3403
- /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
4111
+ ) : /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { className: "vpg-search-box", children: [
4112
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
3404
4113
  "svg",
3405
4114
  {
3406
4115
  className: "vpg-search-icon",
3407
4116
  fill: "none",
3408
4117
  stroke: "currentColor",
3409
4118
  viewBox: "0 0 24 24",
3410
- children: /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
4119
+ children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
3411
4120
  "path",
3412
4121
  {
3413
4122
  strokeLinecap: "round",
@@ -3418,7 +4127,7 @@ function DataGrid({
3418
4127
  )
3419
4128
  }
3420
4129
  ),
3421
- /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
4130
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
3422
4131
  "input",
3423
4132
  {
3424
4133
  type: "text",
@@ -3435,14 +4144,14 @@ function DataGrid({
3435
4144
  autoFocus: true
3436
4145
  }
3437
4146
  ),
3438
- globalSearchTerm && /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("button", { className: "vpg-search-clear", onClick: () => setGlobalSearchTerm(""), children: /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
4147
+ globalSearchTerm && /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("button", { className: "vpg-search-clear", onClick: () => setGlobalSearchTerm(""), children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
3439
4148
  "svg",
3440
4149
  {
3441
4150
  className: "vpg-icon-xs",
3442
4151
  fill: "none",
3443
4152
  stroke: "currentColor",
3444
4153
  viewBox: "0 0 24 24",
3445
- children: /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
4154
+ children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
3446
4155
  "path",
3447
4156
  {
3448
4157
  strokeLinecap: "round",
@@ -3454,9 +4163,9 @@ function DataGrid({
3454
4163
  }
3455
4164
  ) })
3456
4165
  ] }) }),
3457
- /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { className: "vpg-font-size-control", children: [
3458
- /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", { className: "vpg-label", children: "Size:" }),
3459
- /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("div", { className: "vpg-font-size-toggle", children: fontSizeOptions.map((opt) => /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
4166
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { className: "vpg-font-size-control", children: [
4167
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("span", { className: "vpg-label", children: "Size:" }),
4168
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", { className: "vpg-font-size-toggle", children: fontSizeOptions.map((opt) => /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
3460
4169
  "button",
3461
4170
  {
3462
4171
  className: `vpg-font-size-btn ${currentFontSize === opt.value ? "active" : ""}`,
@@ -3466,8 +4175,8 @@ function DataGrid({
3466
4175
  opt.value
3467
4176
  )) })
3468
4177
  ] }),
3469
- activeFilterCount > 0 && /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { className: "vpg-filter-info", children: [
3470
- /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("svg", { className: "vpg-icon", fill: "currentColor", viewBox: "0 0 20 20", children: /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
4178
+ activeFilterCount > 0 && /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { className: "vpg-filter-info", children: [
4179
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("svg", { className: "vpg-icon", fill: "currentColor", viewBox: "0 0 20 20", children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
3471
4180
  "path",
3472
4181
  {
3473
4182
  fillRule: "evenodd",
@@ -3475,28 +4184,28 @@ function DataGrid({
3475
4184
  clipRule: "evenodd"
3476
4185
  }
3477
4186
  ) }),
3478
- /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("span", { children: [
4187
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("span", { children: [
3479
4188
  activeFilterCount,
3480
4189
  " ",
3481
4190
  "filter",
3482
4191
  activeFilterCount > 1 ? "s" : ""
3483
4192
  ] })
3484
4193
  ] }),
3485
- globalSearchTerm && /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("div", { className: "vpg-search-info", children: /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("span", { children: [
4194
+ globalSearchTerm && /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", { className: "vpg-search-info", children: /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("span", { children: [
3486
4195
  totalSearchedRows,
3487
4196
  " ",
3488
4197
  "match",
3489
4198
  totalSearchedRows !== 1 ? "es" : ""
3490
4199
  ] }) })
3491
4200
  ] }),
3492
- viewMode === "pivot" && canUsePivot && /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(import_jsx_runtime6.Fragment, { children: [
3493
- /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(
4201
+ viewMode === "pivot" && canUsePivot && /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(import_jsx_runtime7.Fragment, { children: [
4202
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(
3494
4203
  "button",
3495
4204
  {
3496
4205
  className: `vpg-config-toggle ${showPivotConfig ? "active" : ""}`,
3497
4206
  onClick: () => setShowPivotConfig(!showPivotConfig),
3498
4207
  children: [
3499
- /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("svg", { className: "vpg-icon", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
4208
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("svg", { className: "vpg-icon", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
3500
4209
  "path",
3501
4210
  {
3502
4211
  strokeLinecap: "round",
@@ -3511,8 +4220,8 @@ function DataGrid({
3511
4220
  ]
3512
4221
  }
3513
4222
  ),
3514
- pivotIsConfigured && /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { className: "vpg-pivot-status", children: [
3515
- /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("svg", { className: "vpg-icon", fill: "currentColor", viewBox: "0 0 20 20", children: /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
4223
+ pivotIsConfigured && /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { className: "vpg-pivot-status", children: [
4224
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("svg", { className: "vpg-icon", fill: "currentColor", viewBox: "0 0 20 20", children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
3516
4225
  "path",
3517
4226
  {
3518
4227
  fillRule: "evenodd",
@@ -3520,13 +4229,13 @@ function DataGrid({
3520
4229
  clipRule: "evenodd"
3521
4230
  }
3522
4231
  ) }),
3523
- /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", { children: "Pivot configured" })
4232
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("span", { children: "Pivot configured" })
3524
4233
  ] })
3525
4234
  ] })
3526
4235
  ] }),
3527
- /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { className: "vpg-toolbar-right", children: [
3528
- viewMode === "grid" && activeFilterCount > 0 && /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("button", { className: "vpg-clear-filters", onClick: clearAllFilters, children: [
3529
- /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("svg", { className: "vpg-icon", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
4236
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { className: "vpg-toolbar-right", children: [
4237
+ viewMode === "grid" && activeFilterCount > 0 && /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("button", { className: "vpg-clear-filters", onClick: clearAllFilters, children: [
4238
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("svg", { className: "vpg-icon", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
3530
4239
  "path",
3531
4240
  {
3532
4241
  strokeLinecap: "round",
@@ -3537,13 +4246,13 @@ function DataGrid({
3537
4246
  ) }),
3538
4247
  "Clear Filters"
3539
4248
  ] }),
3540
- enableClipboard && selectionBounds && viewMode === "grid" && /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
4249
+ enableClipboard && selectionBounds && viewMode === "grid" && /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
3541
4250
  "button",
3542
4251
  {
3543
4252
  className: "vpg-icon-btn",
3544
4253
  title: "Copy selection (Ctrl+C)",
3545
4254
  onClick: copySelectionToClipboard,
3546
- children: /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("svg", { className: "vpg-icon", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
4255
+ children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("svg", { className: "vpg-icon", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
3547
4256
  "path",
3548
4257
  {
3549
4258
  strokeLinecap: "round",
@@ -3554,14 +4263,14 @@ function DataGrid({
3554
4263
  ) })
3555
4264
  }
3556
4265
  ),
3557
- enableExport && viewMode === "grid" && /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(
4266
+ enableExport && viewMode === "grid" && /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(
3558
4267
  "button",
3559
4268
  {
3560
4269
  className: "vpg-export-btn",
3561
4270
  title: "Export to CSV",
3562
4271
  onClick: handleExport,
3563
4272
  children: [
3564
- /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("svg", { className: "vpg-icon", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
4273
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("svg", { className: "vpg-icon", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
3565
4274
  "path",
3566
4275
  {
3567
4276
  strokeLinecap: "round",
@@ -3574,7 +4283,7 @@ function DataGrid({
3574
4283
  ]
3575
4284
  }
3576
4285
  ),
3577
- enableExport && viewMode === "pivot" && pivotIsConfigured && /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(
4286
+ enableExport && viewMode === "pivot" && pivotIsConfigured && /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(
3578
4287
  "button",
3579
4288
  {
3580
4289
  className: `vpg-export-btn ${!isPro ? "vpg-export-btn-disabled" : ""}`,
@@ -3582,7 +4291,7 @@ function DataGrid({
3582
4291
  title: isPro ? "Export Pivot to CSV" : "Export Pivot to CSV (Pro feature)",
3583
4292
  onClick: () => isPro && handleExport(),
3584
4293
  children: [
3585
- /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("svg", { className: "vpg-icon", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
4294
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("svg", { className: "vpg-icon", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
3586
4295
  "path",
3587
4296
  {
3588
4297
  strokeLinecap: "round",
@@ -3598,13 +4307,13 @@ function DataGrid({
3598
4307
  )
3599
4308
  ] })
3600
4309
  ] }),
3601
- viewMode === "grid" && /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { ref: tableContainerRef, className: "vpg-grid-container", tabIndex: 0, children: [
3602
- loading && /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { className: "vpg-loading", children: [
3603
- /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("div", { className: "vpg-spinner" }),
3604
- /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", { children: "Loading data..." })
4310
+ viewMode === "grid" && /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { ref: tableContainerRef, className: "vpg-grid-container", tabIndex: 0, children: [
4311
+ loading && /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { className: "vpg-loading", children: [
4312
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", { className: "vpg-spinner" }),
4313
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("span", { children: "Loading data..." })
3605
4314
  ] }),
3606
- !loading && data.length === 0 && /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { className: "vpg-empty", children: [
3607
- /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("div", { className: "vpg-empty-icon", children: /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("svg", { className: "vpg-icon-lg", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
4315
+ !loading && data.length === 0 && /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { className: "vpg-empty", children: [
4316
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", { className: "vpg-empty-icon", children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("svg", { className: "vpg-icon-lg", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
3608
4317
  "path",
3609
4318
  {
3610
4319
  strokeLinecap: "round",
@@ -3613,10 +4322,10 @@ function DataGrid({
3613
4322
  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"
3614
4323
  }
3615
4324
  ) }) }),
3616
- /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", { children: "No data available" })
4325
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("span", { children: "No data available" })
3617
4326
  ] }),
3618
- !loading && data.length > 0 && filteredRowCount === 0 && /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { className: "vpg-empty", children: [
3619
- /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("div", { className: "vpg-empty-icon vpg-warning", children: /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("svg", { className: "vpg-icon-lg", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
4327
+ !loading && data.length > 0 && filteredRowCount === 0 && /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { className: "vpg-empty", children: [
4328
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", { className: "vpg-empty-icon vpg-warning", children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("svg", { className: "vpg-icon-lg", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
3620
4329
  "path",
3621
4330
  {
3622
4331
  strokeLinecap: "round",
@@ -3625,11 +4334,11 @@ function DataGrid({
3625
4334
  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"
3626
4335
  }
3627
4336
  ) }) }),
3628
- /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", { children: "No matching records" }),
3629
- /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("button", { className: "vpg-clear-link", onClick: clearAllFilters, children: "Clear all filters" })
4337
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("span", { children: "No matching records" }),
4338
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("button", { className: "vpg-clear-link", onClick: clearAllFilters, children: "Clear all filters" })
3630
4339
  ] }),
3631
- !loading && filteredRowCount > 0 && /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("div", { className: "vpg-table-wrapper", children: /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("table", { className: "vpg-table", style: { minWidth: `${totalTableWidth}px` }, children: [
3632
- /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("thead", { children: /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("tr", { children: columnKeys.map((colId) => /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(
4340
+ !loading && filteredRowCount > 0 && /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", { className: "vpg-table-wrapper", children: /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("table", { className: "vpg-table", style: { minWidth: `${totalTableWidth}px` }, children: [
4341
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("thead", { children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("tr", { children: columnKeys.map((colId) => /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(
3633
4342
  "th",
3634
4343
  {
3635
4344
  className: `vpg-header-cell ${hasActiveFilter(colId) ? "vpg-has-filter" : ""} ${getSortDirection(colId) !== null ? "vpg-is-sorted" : ""} ${activeFilterColumn === colId ? "vpg-is-active" : ""}`,
@@ -3644,16 +4353,16 @@ function DataGrid({
3644
4353
  }
3645
4354
  },
3646
4355
  children: [
3647
- /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { className: "vpg-header-content", children: [
3648
- /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", { className: "vpg-header-text", children: colId }),
3649
- /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { className: "vpg-header-icons", children: [
3650
- getSortDirection(colId) && /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", { className: "vpg-sort-indicator", children: getSortDirection(colId) === "asc" ? /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
4356
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { className: "vpg-header-content", children: [
4357
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("span", { className: "vpg-header-text", children: colId }),
4358
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { className: "vpg-header-icons", children: [
4359
+ getSortDirection(colId) && /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("span", { className: "vpg-sort-indicator", children: getSortDirection(colId) === "asc" ? /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
3651
4360
  "svg",
3652
4361
  {
3653
4362
  className: "vpg-icon-sm",
3654
4363
  fill: "currentColor",
3655
4364
  viewBox: "0 0 20 20",
3656
- children: /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
4365
+ children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
3657
4366
  "path",
3658
4367
  {
3659
4368
  fillRule: "evenodd",
@@ -3662,13 +4371,13 @@ function DataGrid({
3662
4371
  }
3663
4372
  )
3664
4373
  }
3665
- ) : /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
4374
+ ) : /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
3666
4375
  "svg",
3667
4376
  {
3668
4377
  className: "vpg-icon-sm",
3669
4378
  fill: "currentColor",
3670
4379
  viewBox: "0 0 20 20",
3671
- children: /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
4380
+ children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
3672
4381
  "path",
3673
4382
  {
3674
4383
  fillRule: "evenodd",
@@ -3678,13 +4387,13 @@ function DataGrid({
3678
4387
  )
3679
4388
  }
3680
4389
  ) }),
3681
- hasActiveFilter(colId) && /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", { className: "vpg-filter-indicator", children: /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
4390
+ hasActiveFilter(colId) && /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("span", { className: "vpg-filter-indicator", children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
3682
4391
  "svg",
3683
4392
  {
3684
4393
  className: "vpg-icon-xs",
3685
4394
  fill: "currentColor",
3686
4395
  viewBox: "0 0 20 20",
3687
- children: /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
4396
+ children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
3688
4397
  "path",
3689
4398
  {
3690
4399
  fillRule: "evenodd",
@@ -3694,14 +4403,14 @@ function DataGrid({
3694
4403
  )
3695
4404
  }
3696
4405
  ) }),
3697
- /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", { className: "vpg-dropdown-arrow", title: "Filter & Sort", children: /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
4406
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("span", { className: "vpg-dropdown-arrow", title: "Filter & Sort", children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
3698
4407
  "svg",
3699
4408
  {
3700
4409
  className: "vpg-icon-sm",
3701
4410
  fill: "none",
3702
4411
  stroke: "currentColor",
3703
4412
  viewBox: "0 0 24 24",
3704
- children: /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
4413
+ children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
3705
4414
  "path",
3706
4415
  {
3707
4416
  strokeLinecap: "round",
@@ -3714,7 +4423,7 @@ function DataGrid({
3714
4423
  ) })
3715
4424
  ] })
3716
4425
  ] }),
3717
- enableColumnResize && /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
4426
+ enableColumnResize && /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
3718
4427
  "div",
3719
4428
  {
3720
4429
  className: "vpg-resize-handle",
@@ -3725,7 +4434,7 @@ function DataGrid({
3725
4434
  },
3726
4435
  colId
3727
4436
  )) }) }),
3728
- /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("tbody", { ref: tableBodyRef, children: paginatedRows.map((row, rowIndex) => /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("tr", { className: "vpg-row", children: columnKeys.map((colId, colIndex) => /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
4437
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("tbody", { ref: tableBodyRef, children: paginatedRows.map((row, rowIndex) => /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("tr", { className: "vpg-row", children: columnKeys.map((colId, colIndex) => /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
3729
4438
  "td",
3730
4439
  {
3731
4440
  className: `vpg-cell ${isCellSelected(rowIndex, colIndex) ? "vpg-selected" : ""} ${getColumnStats(colId).type === "number" ? "vpg-is-number" : ""}`,
@@ -3743,8 +4452,8 @@ function DataGrid({
3743
4452
  )) }, row.id)) })
3744
4453
  ] }) })
3745
4454
  ] }),
3746
- viewMode === "pivot" && /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { className: "vpg-pivot-container", children: [
3747
- showPivotConfig && canUsePivot && /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("div", { className: "vpg-pivot-config-panel", children: /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
4455
+ viewMode === "pivot" && /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { className: "vpg-pivot-container", children: [
4456
+ showPivotConfig && canUsePivot && /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", { className: "vpg-pivot-config-panel", children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
3748
4457
  PivotConfig,
3749
4458
  {
3750
4459
  availableFields: pivotAvailableFields,
@@ -3772,7 +4481,7 @@ function DataGrid({
3772
4481
  onUpdateCalculatedField: addCalculatedField
3773
4482
  }
3774
4483
  ) }),
3775
- /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("div", { className: `vpg-pivot-main ${!showPivotConfig ? "vpg-full-width" : ""}`, children: /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
4484
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", { className: `vpg-pivot-main ${!showPivotConfig ? "vpg-full-width" : ""}`, children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
3776
4485
  PivotSkeleton,
3777
4486
  {
3778
4487
  rowFields: pivotRowFields,
@@ -3798,47 +4507,78 @@ function DataGrid({
3798
4507
  }
3799
4508
  ) })
3800
4509
  ] }),
3801
- /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { className: "vpg-footer", children: [
3802
- /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("div", { className: "vpg-footer-left", children: viewMode === "grid" ? enablePagination ? /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(import_jsx_runtime6.Fragment, { children: [
3803
- /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("span", { children: [
4510
+ viewMode === "chart" && /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { className: "vpg-chart-view", children: [
4511
+ activeFilterInfo && activeFilterInfo.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { className: "vpg-chart-filter-bar", children: [
4512
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("svg", { className: "vpg-icon", fill: "currentColor", viewBox: "0 0 20 20", children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("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" }) }),
4513
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("span", { children: [
4514
+ "Chart showing",
4515
+ filteredRowCount.toLocaleString(),
4516
+ " ",
4517
+ "of",
4518
+ totalRowCount.toLocaleString(),
4519
+ " ",
4520
+ "records"
4521
+ ] }),
4522
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("button", { className: "vpg-chart-clear-filters", onClick: clearAllFilters, children: "Clear filters" })
4523
+ ] }),
4524
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
4525
+ ChartBuilder,
4526
+ {
4527
+ data: filteredDataForPivot,
4528
+ theme: currentTheme,
4529
+ onConfigChange: handleChartConfigChange
4530
+ }
4531
+ )
4532
+ ] }),
4533
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { className: "vpg-footer", children: [
4534
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", { className: "vpg-footer-left", children: viewMode === "grid" ? enablePagination ? /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(import_jsx_runtime7.Fragment, { children: [
4535
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("span", { children: [
3804
4536
  ((currentPage - 1) * pageSize + 1).toLocaleString(),
3805
4537
  "-",
3806
4538
  Math.min(currentPage * pageSize, totalSearchedRows).toLocaleString()
3807
4539
  ] }),
3808
- /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", { className: "vpg-separator", children: "of" }),
3809
- /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", { children: totalSearchedRows.toLocaleString() }),
3810
- totalSearchedRows !== totalRowCount && /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("span", { className: "vpg-filtered-note", children: [
4540
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("span", { className: "vpg-separator", children: "of" }),
4541
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("span", { children: totalSearchedRows.toLocaleString() }),
4542
+ totalSearchedRows !== totalRowCount && /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("span", { className: "vpg-filtered-note", children: [
3811
4543
  "(",
3812
4544
  totalRowCount.toLocaleString(),
3813
4545
  " ",
3814
4546
  "total)"
3815
4547
  ] })
3816
- ] }) : filteredRowCount === totalRowCount && totalSearchedRows === totalRowCount ? /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("span", { children: [
4548
+ ] }) : filteredRowCount === totalRowCount && totalSearchedRows === totalRowCount ? /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("span", { children: [
3817
4549
  totalRowCount.toLocaleString(),
3818
4550
  " ",
3819
4551
  "records"
3820
- ] }) : /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(import_jsx_runtime6.Fragment, { children: [
3821
- /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", { className: "vpg-filtered-count", children: totalSearchedRows.toLocaleString() }),
3822
- /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", { className: "vpg-separator", children: "of" }),
3823
- /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", { children: totalRowCount.toLocaleString() }),
3824
- /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", { className: "vpg-separator", children: "records" })
3825
- ] }) : /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(import_jsx_runtime6.Fragment, { children: [
3826
- /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", { className: "vpg-pivot-label", children: "Pivot Table" }),
3827
- /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", { className: "vpg-separator", children: "\u2022" }),
3828
- /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("span", { children: [
4552
+ ] }) : /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(import_jsx_runtime7.Fragment, { children: [
4553
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("span", { className: "vpg-filtered-count", children: totalSearchedRows.toLocaleString() }),
4554
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("span", { className: "vpg-separator", children: "of" }),
4555
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("span", { children: totalRowCount.toLocaleString() }),
4556
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("span", { className: "vpg-separator", children: "records" })
4557
+ ] }) : viewMode === "pivot" ? /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(import_jsx_runtime7.Fragment, { children: [
4558
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("span", { className: "vpg-pivot-label", children: "Pivot Table" }),
4559
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("span", { className: "vpg-separator", children: "\u2022" }),
4560
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("span", { children: [
3829
4561
  totalRowCount.toLocaleString(),
3830
4562
  " ",
3831
4563
  "source records"
3832
4564
  ] })
4565
+ ] }) : /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(import_jsx_runtime7.Fragment, { children: [
4566
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("span", { className: "vpg-chart-label", children: "Chart Builder" }),
4567
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("span", { className: "vpg-separator", children: "\u2022" }),
4568
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("span", { children: [
4569
+ totalRowCount.toLocaleString(),
4570
+ " ",
4571
+ "records"
4572
+ ] })
3833
4573
  ] }) }),
3834
- enablePagination && viewMode === "grid" && totalPages > 1 && /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { className: "vpg-pagination", children: [
3835
- /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
4574
+ enablePagination && viewMode === "grid" && totalPages > 1 && /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { className: "vpg-pagination", children: [
4575
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
3836
4576
  "button",
3837
4577
  {
3838
4578
  className: "vpg-page-btn",
3839
4579
  disabled: currentPage === 1,
3840
4580
  onClick: () => setCurrentPage(1),
3841
- children: /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("svg", { className: "vpg-icon-sm", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
4581
+ children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("svg", { className: "vpg-icon-sm", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
3842
4582
  "path",
3843
4583
  {
3844
4584
  strokeLinecap: "round",
@@ -3849,13 +4589,13 @@ function DataGrid({
3849
4589
  ) })
3850
4590
  }
3851
4591
  ),
3852
- /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
4592
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
3853
4593
  "button",
3854
4594
  {
3855
4595
  className: "vpg-page-btn",
3856
4596
  disabled: currentPage === 1,
3857
4597
  onClick: () => setCurrentPage((p) => Math.max(1, p - 1)),
3858
- children: /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("svg", { className: "vpg-icon-sm", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
4598
+ children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("svg", { className: "vpg-icon-sm", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
3859
4599
  "path",
3860
4600
  {
3861
4601
  strokeLinecap: "round",
@@ -3866,7 +4606,7 @@ function DataGrid({
3866
4606
  ) })
3867
4607
  }
3868
4608
  ),
3869
- /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("span", { className: "vpg-page-info", children: [
4609
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("span", { className: "vpg-page-info", children: [
3870
4610
  "Page",
3871
4611
  " ",
3872
4612
  currentPage,
@@ -3875,13 +4615,13 @@ function DataGrid({
3875
4615
  " ",
3876
4616
  totalPages
3877
4617
  ] }),
3878
- /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
4618
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
3879
4619
  "button",
3880
4620
  {
3881
4621
  className: "vpg-page-btn",
3882
4622
  disabled: currentPage === totalPages,
3883
4623
  onClick: () => setCurrentPage((p) => Math.min(totalPages, p + 1)),
3884
- children: /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("svg", { className: "vpg-icon-sm", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
4624
+ children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("svg", { className: "vpg-icon-sm", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
3885
4625
  "path",
3886
4626
  {
3887
4627
  strokeLinecap: "round",
@@ -3892,13 +4632,13 @@ function DataGrid({
3892
4632
  ) })
3893
4633
  }
3894
4634
  ),
3895
- /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
4635
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
3896
4636
  "button",
3897
4637
  {
3898
4638
  className: "vpg-page-btn",
3899
4639
  disabled: currentPage === totalPages,
3900
4640
  onClick: () => setCurrentPage(totalPages),
3901
- children: /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("svg", { className: "vpg-icon-sm", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
4641
+ children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("svg", { className: "vpg-icon-sm", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
3902
4642
  "path",
3903
4643
  {
3904
4644
  strokeLinecap: "round",
@@ -3910,45 +4650,45 @@ function DataGrid({
3910
4650
  }
3911
4651
  )
3912
4652
  ] }),
3913
- viewMode === "grid" && selectionStats && selectionStats.count > 1 && /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { className: "vpg-selection-stats", children: [
3914
- /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("span", { className: "vpg-stat", children: [
3915
- /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", { className: "vpg-stat-label", children: "Count:" }),
3916
- /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", { className: "vpg-stat-value", children: selectionStats.count })
4653
+ viewMode === "grid" && selectionStats && selectionStats.count > 1 && /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { className: "vpg-selection-stats", children: [
4654
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("span", { className: "vpg-stat", children: [
4655
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("span", { className: "vpg-stat-label", children: "Count:" }),
4656
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("span", { className: "vpg-stat-value", children: selectionStats.count })
3917
4657
  ] }),
3918
- selectionStats.numericCount > 0 && /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(import_jsx_runtime6.Fragment, { children: [
3919
- /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", { className: "vpg-stat-divider", children: "|" }),
3920
- /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("span", { className: "vpg-stat", children: [
3921
- /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", { className: "vpg-stat-label", children: "Sum:" }),
3922
- /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", { className: "vpg-stat-value", children: formatStatValue(selectionStats.sum) })
4658
+ selectionStats.numericCount > 0 && /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(import_jsx_runtime7.Fragment, { children: [
4659
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("span", { className: "vpg-stat-divider", children: "|" }),
4660
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("span", { className: "vpg-stat", children: [
4661
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("span", { className: "vpg-stat-label", children: "Sum:" }),
4662
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("span", { className: "vpg-stat-value", children: formatStatValue(selectionStats.sum) })
3923
4663
  ] }),
3924
- /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", { className: "vpg-stat-divider", children: "|" }),
3925
- /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("span", { className: "vpg-stat", children: [
3926
- /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", { className: "vpg-stat-label", children: "Avg:" }),
3927
- /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", { className: "vpg-stat-value", children: formatStatValue(selectionStats.avg) })
4664
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("span", { className: "vpg-stat-divider", children: "|" }),
4665
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("span", { className: "vpg-stat", children: [
4666
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("span", { className: "vpg-stat-label", children: "Avg:" }),
4667
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("span", { className: "vpg-stat-value", children: formatStatValue(selectionStats.avg) })
3928
4668
  ] })
3929
4669
  ] })
3930
4670
  ] }),
3931
- /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("div", { className: "vpg-footer-right", children: isDemo ? /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { className: "vpg-demo-banner", children: [
3932
- /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", { className: "vpg-demo-badge", children: "DEMO" }),
3933
- /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", { children: "Pro features enabled" }),
3934
- /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("a", { href: "https://tiny-pivot.com/#pricing", target: "_blank", rel: "noopener noreferrer", children: "Get License \u2192" })
3935
- ] }) : showWatermark ? /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", { className: "vpg-watermark-inline", children: /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("a", { href: "https://tiny-pivot.com", target: "_blank", rel: "noopener noreferrer", children: [
3936
- /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("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: [
3937
- /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("rect", { x: "3", y: "3", width: "7", height: "7" }),
3938
- /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("rect", { x: "14", y: "3", width: "7", height: "7" }),
3939
- /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("rect", { x: "14", y: "14", width: "7", height: "7" }),
3940
- /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("rect", { x: "3", y: "14", width: "7", height: "7" })
4671
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", { className: "vpg-footer-right", children: isDemo ? /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { className: "vpg-demo-banner", children: [
4672
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("span", { className: "vpg-demo-badge", children: "DEMO" }),
4673
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("span", { children: "Pro features enabled" }),
4674
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("a", { href: "https://tiny-pivot.com/#pricing", target: "_blank", rel: "noopener noreferrer", children: "Get License \u2192" })
4675
+ ] }) : showWatermark ? /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("span", { className: "vpg-watermark-inline", children: /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("a", { href: "https://tiny-pivot.com", target: "_blank", rel: "noopener noreferrer", children: [
4676
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("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: [
4677
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("rect", { x: "3", y: "3", width: "7", height: "7" }),
4678
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("rect", { x: "14", y: "3", width: "7", height: "7" }),
4679
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("rect", { x: "14", y: "14", width: "7", height: "7" }),
4680
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("rect", { x: "3", y: "14", width: "7", height: "7" })
3941
4681
  ] }),
3942
4682
  "Powered by TinyPivot"
3943
4683
  ] }) }) : null })
3944
4684
  ] }),
3945
- enableVerticalResize && /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("div", { className: "vpg-vertical-resize-handle", onMouseDown: startVerticalResize, children: /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { className: "vpg-resize-grip", children: [
3946
- /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", {}),
3947
- /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", {}),
3948
- /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", {})
4685
+ enableVerticalResize && /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", { className: "vpg-vertical-resize-handle", onMouseDown: startVerticalResize, children: /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { className: "vpg-resize-grip", children: [
4686
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("span", {}),
4687
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("span", {}),
4688
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("span", {})
3949
4689
  ] }) }),
3950
4690
  activeFilterColumn && typeof document !== "undefined" && (0, import_react_dom2.createPortal)(
3951
- /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
4691
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
3952
4692
  "div",
3953
4693
  {
3954
4694
  className: "vpg-filter-portal",
@@ -3959,7 +4699,7 @@ function DataGrid({
3959
4699
  maxHeight: `${filterDropdownPosition.maxHeight}px`,
3960
4700
  zIndex: 9999
3961
4701
  },
3962
- children: /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
4702
+ children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
3963
4703
  ColumnFilter,
3964
4704
  {
3965
4705
  columnId: activeFilterColumn,