@smallwebco/tinypivot-react 1.0.29 → 1.0.31

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.js CHANGED
@@ -1,5 +1,5 @@
1
1
  // src/components/DataGrid.tsx
2
- import { useState as useState9, useMemo as useMemo9, useCallback as useCallback9, useEffect as useEffect6, useRef as useRef2 } from "react";
2
+ import { useState as useState10, useMemo as useMemo10, useCallback as useCallback10, useEffect as useEffect7, useRef as useRef2 } from "react";
3
3
  import { createPortal as createPortal2 } from "react-dom";
4
4
 
5
5
  // src/hooks/useExcelGrid.ts
@@ -10,14 +10,27 @@ import {
10
10
  getFilteredRowModel,
11
11
  getSortedRowModel
12
12
  } from "@tanstack/react-table";
13
- import { getColumnUniqueValues, formatCellValue } from "@smallwebco/tinypivot-core";
13
+ import { getColumnUniqueValues, formatCellValue, isNumericRange } from "@smallwebco/tinypivot-core";
14
14
  var multiSelectFilter = (row, columnId, filterValue) => {
15
- if (!filterValue || !Array.isArray(filterValue) || filterValue.length === 0) {
15
+ if (!filterValue) return true;
16
+ if (isNumericRange(filterValue)) {
17
+ const cellValue = row.getValue(columnId);
18
+ if (cellValue === null || cellValue === void 0 || cellValue === "") {
19
+ return false;
20
+ }
21
+ const num = typeof cellValue === "number" ? cellValue : Number.parseFloat(String(cellValue));
22
+ if (Number.isNaN(num)) return false;
23
+ const { min, max } = filterValue;
24
+ if (min !== null && num < min) return false;
25
+ if (max !== null && num > max) return false;
16
26
  return true;
17
27
  }
18
- const cellValue = row.getValue(columnId);
19
- const cellString = cellValue === null || cellValue === void 0 || cellValue === "" ? "(blank)" : String(cellValue);
20
- return filterValue.includes(cellString);
28
+ if (Array.isArray(filterValue) && filterValue.length > 0) {
29
+ const cellValue = row.getValue(columnId);
30
+ const cellString = cellValue === null || cellValue === void 0 || cellValue === "" ? "(blank)" : String(cellValue);
31
+ return filterValue.includes(cellString);
32
+ }
33
+ return true;
21
34
  };
22
35
  function useExcelGrid(options) {
23
36
  const { data, enableSorting = true, enableFiltering = true } = options;
@@ -103,7 +116,11 @@ function useExcelGrid(options) {
103
116
  const column = table.getColumn(columnId);
104
117
  if (!column) return false;
105
118
  const filterValue = column.getFilterValue();
106
- return filterValue !== void 0 && Array.isArray(filterValue) && filterValue.length > 0;
119
+ if (!filterValue) return false;
120
+ if (isNumericRange(filterValue)) {
121
+ return filterValue.min !== null || filterValue.max !== null;
122
+ }
123
+ return Array.isArray(filterValue) && filterValue.length > 0;
107
124
  },
108
125
  [table]
109
126
  );
@@ -116,6 +133,31 @@ function useExcelGrid(options) {
116
133
  },
117
134
  [table]
118
135
  );
136
+ const setNumericRangeFilter = useCallback(
137
+ (columnId, range) => {
138
+ const column = table.getColumn(columnId);
139
+ if (column) {
140
+ if (!range || range.min === null && range.max === null) {
141
+ column.setFilterValue(void 0);
142
+ } else {
143
+ column.setFilterValue(range);
144
+ }
145
+ }
146
+ },
147
+ [table]
148
+ );
149
+ const getNumericRangeFilter = useCallback(
150
+ (columnId) => {
151
+ const column = table.getColumn(columnId);
152
+ if (!column) return null;
153
+ const filterValue = column.getFilterValue();
154
+ if (filterValue && isNumericRange(filterValue)) {
155
+ return filterValue;
156
+ }
157
+ return null;
158
+ },
159
+ [table]
160
+ );
119
161
  const clearAllFilters = useCallback(() => {
120
162
  table.resetColumnFilters();
121
163
  setGlobalFilter("");
@@ -174,7 +216,10 @@ function useExcelGrid(options) {
174
216
  getColumnFilterValues,
175
217
  clearAllFilters,
176
218
  toggleSort,
177
- getSortDirection
219
+ getSortDirection,
220
+ // Numeric range filters
221
+ setNumericRangeFilter,
222
+ getNumericRangeFilter
178
223
  };
179
224
  }
180
225
 
@@ -738,40 +783,286 @@ function useColumnResize(initialWidths, minWidth = 60, maxWidth = 600) {
738
783
  }
739
784
 
740
785
  // src/components/ColumnFilter.tsx
741
- import { useState as useState5, useEffect as useEffect3, useRef, useCallback as useCallback5, useMemo as useMemo5 } from "react";
786
+ import { useState as useState6, useEffect as useEffect4, useRef, useCallback as useCallback6, useMemo as useMemo6 } from "react";
787
+
788
+ // src/components/NumericRangeFilter.tsx
789
+ import { useState as useState5, useCallback as useCallback5, useMemo as useMemo5, useEffect as useEffect3 } from "react";
742
790
  import { jsx, jsxs } from "react/jsx-runtime";
791
+ function NumericRangeFilter({
792
+ dataMin,
793
+ dataMax,
794
+ currentRange,
795
+ onChange
796
+ }) {
797
+ const [localMin, setLocalMin] = useState5(currentRange?.min ?? null);
798
+ const [localMax, setLocalMax] = useState5(currentRange?.max ?? null);
799
+ const step = useMemo5(() => {
800
+ const range = dataMax - dataMin;
801
+ if (range === 0) return 1;
802
+ if (range <= 1) return 0.01;
803
+ if (range <= 10) return 0.1;
804
+ if (range <= 100) return 1;
805
+ if (range <= 1e3) return 10;
806
+ return Math.pow(10, Math.floor(Math.log10(range)) - 2);
807
+ }, [dataMin, dataMax]);
808
+ const formatValue = useCallback5((val) => {
809
+ if (val === null) return "";
810
+ if (Number.isInteger(val)) return val.toLocaleString();
811
+ return val.toLocaleString(void 0, { maximumFractionDigits: 2 });
812
+ }, []);
813
+ const isFilterActive = localMin !== null || localMax !== null;
814
+ const minPercent = useMemo5(() => {
815
+ if (localMin === null || dataMax === dataMin) return 0;
816
+ return (localMin - dataMin) / (dataMax - dataMin) * 100;
817
+ }, [localMin, dataMin, dataMax]);
818
+ const maxPercent = useMemo5(() => {
819
+ if (localMax === null || dataMax === dataMin) return 100;
820
+ return (localMax - dataMin) / (dataMax - dataMin) * 100;
821
+ }, [localMax, dataMin, dataMax]);
822
+ const handleMinSlider = useCallback5((event) => {
823
+ const value = Number.parseFloat(event.target.value);
824
+ setLocalMin((prev) => {
825
+ if (localMax !== null && value > localMax) {
826
+ return localMax;
827
+ }
828
+ return value;
829
+ });
830
+ }, [localMax]);
831
+ const handleMaxSlider = useCallback5((event) => {
832
+ const value = Number.parseFloat(event.target.value);
833
+ setLocalMax((prev) => {
834
+ if (localMin !== null && value < localMin) {
835
+ return localMin;
836
+ }
837
+ return value;
838
+ });
839
+ }, [localMin]);
840
+ const handleSliderChange = useCallback5(() => {
841
+ if (localMin === null && localMax === null) {
842
+ onChange(null);
843
+ } else {
844
+ onChange({ min: localMin, max: localMax });
845
+ }
846
+ }, [localMin, localMax, onChange]);
847
+ const handleMinInput = useCallback5((event) => {
848
+ const value = event.target.value === "" ? null : Number.parseFloat(event.target.value);
849
+ if (value !== null && !Number.isNaN(value)) {
850
+ setLocalMin(Math.max(dataMin, Math.min(value, localMax ?? dataMax)));
851
+ } else if (value === null) {
852
+ setLocalMin(null);
853
+ }
854
+ }, [dataMin, dataMax, localMax]);
855
+ const handleMaxInput = useCallback5((event) => {
856
+ const value = event.target.value === "" ? null : Number.parseFloat(event.target.value);
857
+ if (value !== null && !Number.isNaN(value)) {
858
+ setLocalMax(Math.min(dataMax, Math.max(value, localMin ?? dataMin)));
859
+ } else if (value === null) {
860
+ setLocalMax(null);
861
+ }
862
+ }, [dataMin, dataMax, localMin]);
863
+ const handleInputBlur = useCallback5(() => {
864
+ if (localMin === null && localMax === null) {
865
+ onChange(null);
866
+ } else {
867
+ onChange({ min: localMin, max: localMax });
868
+ }
869
+ }, [localMin, localMax, onChange]);
870
+ const clearFilter = useCallback5(() => {
871
+ setLocalMin(null);
872
+ setLocalMax(null);
873
+ onChange(null);
874
+ }, [onChange]);
875
+ const setFullRange = useCallback5(() => {
876
+ setLocalMin(dataMin);
877
+ setLocalMax(dataMax);
878
+ onChange({ min: dataMin, max: dataMax });
879
+ }, [dataMin, dataMax, onChange]);
880
+ useEffect3(() => {
881
+ setLocalMin(currentRange?.min ?? null);
882
+ setLocalMax(currentRange?.max ?? null);
883
+ }, [currentRange]);
884
+ return /* @__PURE__ */ jsxs("div", { className: "vpg-range-filter", children: [
885
+ /* @__PURE__ */ jsxs("div", { className: "vpg-range-info", children: [
886
+ /* @__PURE__ */ jsx("span", { className: "vpg-range-label", children: "Data range:" }),
887
+ /* @__PURE__ */ jsxs("span", { className: "vpg-range-bounds", children: [
888
+ formatValue(dataMin),
889
+ " \u2013 ",
890
+ formatValue(dataMax)
891
+ ] })
892
+ ] }),
893
+ /* @__PURE__ */ jsxs("div", { className: "vpg-slider-container", children: [
894
+ /* @__PURE__ */ jsx("div", { className: "vpg-slider-track", children: /* @__PURE__ */ jsx(
895
+ "div",
896
+ {
897
+ className: "vpg-slider-fill",
898
+ style: {
899
+ left: `${minPercent}%`,
900
+ right: `${100 - maxPercent}%`
901
+ }
902
+ }
903
+ ) }),
904
+ /* @__PURE__ */ jsx(
905
+ "input",
906
+ {
907
+ type: "range",
908
+ className: "vpg-slider vpg-slider-min",
909
+ min: dataMin,
910
+ max: dataMax,
911
+ step,
912
+ value: localMin ?? dataMin,
913
+ onChange: handleMinSlider,
914
+ onMouseUp: handleSliderChange,
915
+ onTouchEnd: handleSliderChange
916
+ }
917
+ ),
918
+ /* @__PURE__ */ jsx(
919
+ "input",
920
+ {
921
+ type: "range",
922
+ className: "vpg-slider vpg-slider-max",
923
+ min: dataMin,
924
+ max: dataMax,
925
+ step,
926
+ value: localMax ?? dataMax,
927
+ onChange: handleMaxSlider,
928
+ onMouseUp: handleSliderChange,
929
+ onTouchEnd: handleSliderChange
930
+ }
931
+ )
932
+ ] }),
933
+ /* @__PURE__ */ jsxs("div", { className: "vpg-range-inputs", children: [
934
+ /* @__PURE__ */ jsxs("div", { className: "vpg-input-group", children: [
935
+ /* @__PURE__ */ jsx("label", { className: "vpg-input-label", children: "Min" }),
936
+ /* @__PURE__ */ jsx(
937
+ "input",
938
+ {
939
+ type: "number",
940
+ className: "vpg-range-input",
941
+ placeholder: formatValue(dataMin),
942
+ value: localMin ?? "",
943
+ step,
944
+ onChange: handleMinInput,
945
+ onBlur: handleInputBlur
946
+ }
947
+ )
948
+ ] }),
949
+ /* @__PURE__ */ jsx("span", { className: "vpg-input-separator", children: "to" }),
950
+ /* @__PURE__ */ jsxs("div", { className: "vpg-input-group", children: [
951
+ /* @__PURE__ */ jsx("label", { className: "vpg-input-label", children: "Max" }),
952
+ /* @__PURE__ */ jsx(
953
+ "input",
954
+ {
955
+ type: "number",
956
+ className: "vpg-range-input",
957
+ placeholder: formatValue(dataMax),
958
+ value: localMax ?? "",
959
+ step,
960
+ onChange: handleMaxInput,
961
+ onBlur: handleInputBlur
962
+ }
963
+ )
964
+ ] })
965
+ ] }),
966
+ /* @__PURE__ */ jsxs("div", { className: "vpg-range-actions", children: [
967
+ /* @__PURE__ */ jsxs(
968
+ "button",
969
+ {
970
+ className: "vpg-range-btn",
971
+ disabled: !isFilterActive,
972
+ onClick: clearFilter,
973
+ children: [
974
+ /* @__PURE__ */ jsx("svg", { className: "vpg-icon-xs", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: /* @__PURE__ */ jsx(
975
+ "path",
976
+ {
977
+ strokeLinecap: "round",
978
+ strokeLinejoin: "round",
979
+ strokeWidth: 2,
980
+ d: "M6 18L18 6M6 6l12 12"
981
+ }
982
+ ) }),
983
+ "Clear"
984
+ ]
985
+ }
986
+ ),
987
+ /* @__PURE__ */ jsxs("button", { className: "vpg-range-btn", onClick: setFullRange, children: [
988
+ /* @__PURE__ */ jsx("svg", { className: "vpg-icon-xs", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: /* @__PURE__ */ jsx(
989
+ "path",
990
+ {
991
+ strokeLinecap: "round",
992
+ strokeLinejoin: "round",
993
+ strokeWidth: 2,
994
+ d: "M4 8V4m0 0h4M4 4l5 5m11-1V4m0 0h-4m4 0l-5 5M4 16v4m0 0h4m-4 0l5-5m11 5l-5-5m5 5v-4m0 4h-4"
995
+ }
996
+ ) }),
997
+ "Full Range"
998
+ ] })
999
+ ] }),
1000
+ isFilterActive && /* @__PURE__ */ jsxs("div", { className: "vpg-filter-summary", children: [
1001
+ /* @__PURE__ */ jsx("svg", { className: "vpg-icon-xs", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: /* @__PURE__ */ jsx(
1002
+ "path",
1003
+ {
1004
+ strokeLinecap: "round",
1005
+ strokeLinejoin: "round",
1006
+ strokeWidth: 2,
1007
+ 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"
1008
+ }
1009
+ ) }),
1010
+ /* @__PURE__ */ jsxs("span", { children: [
1011
+ "Showing values",
1012
+ " ",
1013
+ localMin !== null && /* @__PURE__ */ jsxs("strong", { children: [
1014
+ "\u2265 ",
1015
+ formatValue(localMin)
1016
+ ] }),
1017
+ localMin !== null && localMax !== null && " and ",
1018
+ localMax !== null && /* @__PURE__ */ jsxs("strong", { children: [
1019
+ "\u2264 ",
1020
+ formatValue(localMax)
1021
+ ] })
1022
+ ] })
1023
+ ] })
1024
+ ] });
1025
+ }
1026
+
1027
+ // src/components/ColumnFilter.tsx
1028
+ import { Fragment, jsx as jsx2, jsxs as jsxs2 } from "react/jsx-runtime";
743
1029
  function ColumnFilter({
744
1030
  columnName,
745
1031
  stats,
746
1032
  selectedValues,
747
1033
  sortDirection,
1034
+ numericRange,
748
1035
  onFilter,
749
1036
  onSort,
750
- onClose
1037
+ onClose,
1038
+ onRangeFilter
751
1039
  }) {
752
- const [searchQuery, setSearchQuery] = useState5("");
753
- const [localSelected, setLocalSelected] = useState5(new Set(selectedValues));
1040
+ const [searchQuery, setSearchQuery] = useState6("");
1041
+ const [localSelected, setLocalSelected] = useState6(new Set(selectedValues));
754
1042
  const dropdownRef = useRef(null);
755
1043
  const searchInputRef = useRef(null);
1044
+ const isNumericColumn = stats.type === "number" && stats.numericMin !== void 0 && stats.numericMax !== void 0;
1045
+ const [filterMode, setFilterMode] = useState6(numericRange ? "range" : "values");
1046
+ const [localRange, setLocalRange] = useState6(numericRange ?? null);
756
1047
  const hasBlankValues = stats.nullCount > 0;
757
- const filteredValues = useMemo5(() => {
1048
+ const filteredValues = useMemo6(() => {
758
1049
  const values = stats.uniqueValues;
759
1050
  if (!searchQuery) return values;
760
1051
  const query = searchQuery.toLowerCase();
761
1052
  return values.filter((v) => v.toLowerCase().includes(query));
762
1053
  }, [stats.uniqueValues, searchQuery]);
763
- const allValues = useMemo5(() => {
1054
+ const allValues = useMemo6(() => {
764
1055
  const values = [...filteredValues];
765
1056
  if (hasBlankValues && (!searchQuery || "(blank)".includes(searchQuery.toLowerCase()))) {
766
1057
  values.unshift("(blank)");
767
1058
  }
768
1059
  return values;
769
1060
  }, [filteredValues, hasBlankValues, searchQuery]);
770
- const isAllSelected = useMemo5(
1061
+ const isAllSelected = useMemo6(
771
1062
  () => allValues.every((v) => localSelected.has(v)),
772
1063
  [allValues, localSelected]
773
1064
  );
774
- const toggleValue = useCallback5((value) => {
1065
+ const toggleValue = useCallback6((value) => {
775
1066
  setLocalSelected((prev) => {
776
1067
  const next = new Set(prev);
777
1068
  if (next.has(value)) {
@@ -782,7 +1073,7 @@ function ColumnFilter({
782
1073
  return next;
783
1074
  });
784
1075
  }, []);
785
- const selectAll = useCallback5(() => {
1076
+ const selectAll = useCallback6(() => {
786
1077
  setLocalSelected((prev) => {
787
1078
  const next = new Set(prev);
788
1079
  for (const value of allValues) {
@@ -791,10 +1082,10 @@ function ColumnFilter({
791
1082
  return next;
792
1083
  });
793
1084
  }, [allValues]);
794
- const clearAll = useCallback5(() => {
1085
+ const clearAll = useCallback6(() => {
795
1086
  setLocalSelected(/* @__PURE__ */ new Set());
796
1087
  }, []);
797
- const applyFilter = useCallback5(() => {
1088
+ const applyFilter = useCallback6(() => {
798
1089
  if (localSelected.size === 0) {
799
1090
  onFilter([]);
800
1091
  } else {
@@ -802,18 +1093,30 @@ function ColumnFilter({
802
1093
  }
803
1094
  onClose();
804
1095
  }, [localSelected, onFilter, onClose]);
805
- const sortAscending = useCallback5(() => {
1096
+ const sortAscending = useCallback6(() => {
806
1097
  onSort(sortDirection === "asc" ? null : "asc");
807
1098
  }, [sortDirection, onSort]);
808
- const sortDescending = useCallback5(() => {
1099
+ const sortDescending = useCallback6(() => {
809
1100
  onSort(sortDirection === "desc" ? null : "desc");
810
1101
  }, [sortDirection, onSort]);
811
- const clearFilter = useCallback5(() => {
1102
+ const clearFilter = useCallback6(() => {
812
1103
  setLocalSelected(/* @__PURE__ */ new Set());
813
1104
  onFilter([]);
814
1105
  onClose();
815
1106
  }, [onFilter, onClose]);
816
- useEffect3(() => {
1107
+ const handleRangeChange = useCallback6((range) => {
1108
+ setLocalRange(range);
1109
+ }, []);
1110
+ const applyRangeFilter = useCallback6(() => {
1111
+ onRangeFilter?.(localRange);
1112
+ onClose();
1113
+ }, [localRange, onRangeFilter, onClose]);
1114
+ const clearRangeFilter = useCallback6(() => {
1115
+ setLocalRange(null);
1116
+ onRangeFilter?.(null);
1117
+ onClose();
1118
+ }, [onRangeFilter, onClose]);
1119
+ useEffect4(() => {
817
1120
  const handleClickOutside = (event) => {
818
1121
  if (dropdownRef.current && !dropdownRef.current.contains(event.target)) {
819
1122
  onClose();
@@ -822,7 +1125,7 @@ function ColumnFilter({
822
1125
  document.addEventListener("mousedown", handleClickOutside);
823
1126
  return () => document.removeEventListener("mousedown", handleClickOutside);
824
1127
  }, [onClose]);
825
- useEffect3(() => {
1128
+ useEffect4(() => {
826
1129
  const handleKeydown = (event) => {
827
1130
  if (event.key === "Escape") {
828
1131
  onClose();
@@ -833,29 +1136,35 @@ function ColumnFilter({
833
1136
  document.addEventListener("keydown", handleKeydown);
834
1137
  return () => document.removeEventListener("keydown", handleKeydown);
835
1138
  }, [onClose, applyFilter]);
836
- useEffect3(() => {
1139
+ useEffect4(() => {
837
1140
  searchInputRef.current?.focus();
838
1141
  }, []);
839
- useEffect3(() => {
1142
+ useEffect4(() => {
840
1143
  setLocalSelected(new Set(selectedValues));
841
1144
  }, [selectedValues]);
842
- return /* @__PURE__ */ jsxs("div", { ref: dropdownRef, className: "vpg-filter-dropdown", children: [
843
- /* @__PURE__ */ jsxs("div", { className: "vpg-filter-header", children: [
844
- /* @__PURE__ */ jsx("span", { className: "vpg-filter-title", children: columnName }),
845
- /* @__PURE__ */ jsxs("span", { className: "vpg-filter-count", children: [
1145
+ useEffect4(() => {
1146
+ setLocalRange(numericRange ?? null);
1147
+ if (numericRange) {
1148
+ setFilterMode("range");
1149
+ }
1150
+ }, [numericRange]);
1151
+ return /* @__PURE__ */ jsxs2("div", { ref: dropdownRef, className: "vpg-filter-dropdown", children: [
1152
+ /* @__PURE__ */ jsxs2("div", { className: "vpg-filter-header", children: [
1153
+ /* @__PURE__ */ jsx2("span", { className: "vpg-filter-title", children: columnName }),
1154
+ /* @__PURE__ */ jsxs2("span", { className: "vpg-filter-count", children: [
846
1155
  stats.uniqueValues.length.toLocaleString(),
847
1156
  " unique"
848
1157
  ] })
849
1158
  ] }),
850
- /* @__PURE__ */ jsxs("div", { className: "vpg-sort-controls", children: [
851
- /* @__PURE__ */ jsxs(
1159
+ /* @__PURE__ */ jsxs2("div", { className: "vpg-sort-controls", children: [
1160
+ /* @__PURE__ */ jsxs2(
852
1161
  "button",
853
1162
  {
854
1163
  className: `vpg-sort-btn ${sortDirection === "asc" ? "active" : ""}`,
855
- title: "Sort A to Z",
1164
+ title: isNumericColumn ? "Sort Low to High" : "Sort A to Z",
856
1165
  onClick: sortAscending,
857
1166
  children: [
858
- /* @__PURE__ */ jsx("svg", { className: "vpg-icon-sm", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: /* @__PURE__ */ jsx(
1167
+ /* @__PURE__ */ jsx2("svg", { className: "vpg-icon-sm", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: /* @__PURE__ */ jsx2(
859
1168
  "path",
860
1169
  {
861
1170
  strokeLinecap: "round",
@@ -864,18 +1173,18 @@ function ColumnFilter({
864
1173
  d: "M3 4h13M3 8h9m-9 4h6m4 0l4-4m0 0l4 4m-4-4v12"
865
1174
  }
866
1175
  ) }),
867
- /* @__PURE__ */ jsx("span", { children: "A\u2192Z" })
1176
+ /* @__PURE__ */ jsx2("span", { children: isNumericColumn ? "1\u21929" : "A\u2192Z" })
868
1177
  ]
869
1178
  }
870
1179
  ),
871
- /* @__PURE__ */ jsxs(
1180
+ /* @__PURE__ */ jsxs2(
872
1181
  "button",
873
1182
  {
874
1183
  className: `vpg-sort-btn ${sortDirection === "desc" ? "active" : ""}`,
875
- title: "Sort Z to A",
1184
+ title: isNumericColumn ? "Sort High to Low" : "Sort Z to A",
876
1185
  onClick: sortDescending,
877
1186
  children: [
878
- /* @__PURE__ */ jsx("svg", { className: "vpg-icon-sm", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: /* @__PURE__ */ jsx(
1187
+ /* @__PURE__ */ jsx2("svg", { className: "vpg-icon-sm", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: /* @__PURE__ */ jsx2(
879
1188
  "path",
880
1189
  {
881
1190
  strokeLinecap: "round",
@@ -884,99 +1193,156 @@ function ColumnFilter({
884
1193
  d: "M3 4h13M3 8h9m-9 4h9m5-4v12m0 0l-4-4m4 4l4-4"
885
1194
  }
886
1195
  ) }),
887
- /* @__PURE__ */ jsx("span", { children: "Z\u2192A" })
1196
+ /* @__PURE__ */ jsx2("span", { children: isNumericColumn ? "9\u21921" : "Z\u2192A" })
888
1197
  ]
889
1198
  }
890
1199
  )
891
1200
  ] }),
892
- /* @__PURE__ */ jsx("div", { className: "vpg-divider" }),
893
- /* @__PURE__ */ jsxs("div", { className: "vpg-search-container", children: [
894
- /* @__PURE__ */ jsx("svg", { className: "vpg-search-icon", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: /* @__PURE__ */ jsx(
895
- "path",
1201
+ /* @__PURE__ */ jsx2("div", { className: "vpg-divider" }),
1202
+ isNumericColumn && /* @__PURE__ */ jsxs2("div", { className: "vpg-filter-tabs", children: [
1203
+ /* @__PURE__ */ jsxs2(
1204
+ "button",
896
1205
  {
897
- strokeLinecap: "round",
898
- strokeLinejoin: "round",
899
- strokeWidth: 2,
900
- d: "M21 21l-6-6m2-5a7 7 0 11-14 0 7 7 0 0114 0z"
1206
+ className: `vpg-tab-btn ${filterMode === "values" ? "active" : ""}`,
1207
+ onClick: () => setFilterMode("values"),
1208
+ children: [
1209
+ /* @__PURE__ */ jsx2("svg", { className: "vpg-icon-sm", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: /* @__PURE__ */ jsx2(
1210
+ "path",
1211
+ {
1212
+ strokeLinecap: "round",
1213
+ strokeLinejoin: "round",
1214
+ strokeWidth: 2,
1215
+ d: "M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"
1216
+ }
1217
+ ) }),
1218
+ "Values"
1219
+ ]
901
1220
  }
902
- ) }),
903
- /* @__PURE__ */ jsx(
904
- "input",
1221
+ ),
1222
+ /* @__PURE__ */ jsxs2(
1223
+ "button",
905
1224
  {
906
- ref: searchInputRef,
907
- type: "text",
908
- value: searchQuery,
909
- onChange: (e) => setSearchQuery(e.target.value),
910
- placeholder: "Search values...",
911
- className: "vpg-search-input"
1225
+ className: `vpg-tab-btn ${filterMode === "range" ? "active" : ""}`,
1226
+ onClick: () => setFilterMode("range"),
1227
+ children: [
1228
+ /* @__PURE__ */ jsx2("svg", { className: "vpg-icon-sm", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: /* @__PURE__ */ jsx2(
1229
+ "path",
1230
+ {
1231
+ strokeLinecap: "round",
1232
+ strokeLinejoin: "round",
1233
+ strokeWidth: 2,
1234
+ d: "M7 21a4 4 0 01-4-4V5a2 2 0 012-2h4a2 2 0 012 2v12a4 4 0 01-4 4zm0 0h12a2 2 0 002-2v-4a2 2 0 00-2-2h-2.343M11 7.343l1.657-1.657a2 2 0 012.828 0l2.829 2.829a2 2 0 010 2.828l-8.486 8.485M7 17h.01"
1235
+ }
1236
+ ) }),
1237
+ "Range"
1238
+ ]
912
1239
  }
913
- ),
914
- searchQuery && /* @__PURE__ */ jsx("button", { className: "vpg-clear-search", onClick: () => setSearchQuery(""), children: "\xD7" })
1240
+ )
915
1241
  ] }),
916
- /* @__PURE__ */ jsxs("div", { className: "vpg-bulk-actions", children: [
917
- /* @__PURE__ */ jsxs("button", { className: "vpg-bulk-btn", onClick: selectAll, children: [
918
- /* @__PURE__ */ jsx("svg", { className: "vpg-icon-sm", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: /* @__PURE__ */ jsx(
1242
+ (!isNumericColumn || filterMode === "values") && /* @__PURE__ */ jsxs2(Fragment, { children: [
1243
+ /* @__PURE__ */ jsxs2("div", { className: "vpg-search-container", children: [
1244
+ /* @__PURE__ */ jsx2("svg", { className: "vpg-search-icon", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: /* @__PURE__ */ jsx2(
919
1245
  "path",
920
1246
  {
921
1247
  strokeLinecap: "round",
922
1248
  strokeLinejoin: "round",
923
1249
  strokeWidth: 2,
924
- d: "M9 12l2 2 4-4m6 2a9 9 0 11-18 0 9 9 0 0118 0z"
1250
+ d: "M21 21l-6-6m2-5a7 7 0 11-14 0 7 7 0 0114 0z"
925
1251
  }
926
1252
  ) }),
927
- "Select All"
928
- ] }),
929
- /* @__PURE__ */ jsxs("button", { className: "vpg-bulk-btn", onClick: clearAll, children: [
930
- /* @__PURE__ */ jsx("svg", { className: "vpg-icon-sm", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: /* @__PURE__ */ jsx(
931
- "path",
1253
+ /* @__PURE__ */ jsx2(
1254
+ "input",
932
1255
  {
933
- strokeLinecap: "round",
934
- strokeLinejoin: "round",
935
- strokeWidth: 2,
936
- d: "M6 18L18 6M6 6l12 12"
1256
+ ref: searchInputRef,
1257
+ type: "text",
1258
+ value: searchQuery,
1259
+ onChange: (e) => setSearchQuery(e.target.value),
1260
+ placeholder: "Search values...",
1261
+ className: "vpg-search-input"
937
1262
  }
938
- ) }),
939
- "Clear All"
1263
+ ),
1264
+ searchQuery && /* @__PURE__ */ jsx2("button", { className: "vpg-clear-search", onClick: () => setSearchQuery(""), children: "\xD7" })
1265
+ ] }),
1266
+ /* @__PURE__ */ jsxs2("div", { className: "vpg-bulk-actions", children: [
1267
+ /* @__PURE__ */ jsxs2("button", { className: "vpg-bulk-btn", onClick: selectAll, children: [
1268
+ /* @__PURE__ */ jsx2("svg", { className: "vpg-icon-sm", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: /* @__PURE__ */ jsx2(
1269
+ "path",
1270
+ {
1271
+ strokeLinecap: "round",
1272
+ strokeLinejoin: "round",
1273
+ strokeWidth: 2,
1274
+ d: "M9 12l2 2 4-4m6 2a9 9 0 11-18 0 9 9 0 0118 0z"
1275
+ }
1276
+ ) }),
1277
+ "Select All"
1278
+ ] }),
1279
+ /* @__PURE__ */ jsxs2("button", { className: "vpg-bulk-btn", onClick: clearAll, children: [
1280
+ /* @__PURE__ */ jsx2("svg", { className: "vpg-icon-sm", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: /* @__PURE__ */ jsx2(
1281
+ "path",
1282
+ {
1283
+ strokeLinecap: "round",
1284
+ strokeLinejoin: "round",
1285
+ strokeWidth: 2,
1286
+ d: "M6 18L18 6M6 6l12 12"
1287
+ }
1288
+ ) }),
1289
+ "Clear All"
1290
+ ] })
1291
+ ] }),
1292
+ /* @__PURE__ */ jsxs2("div", { className: "vpg-values-list", children: [
1293
+ allValues.map((value) => /* @__PURE__ */ jsxs2(
1294
+ "label",
1295
+ {
1296
+ className: `vpg-value-item ${localSelected.has(value) ? "selected" : ""}`,
1297
+ children: [
1298
+ /* @__PURE__ */ jsx2(
1299
+ "input",
1300
+ {
1301
+ type: "checkbox",
1302
+ checked: localSelected.has(value),
1303
+ onChange: () => toggleValue(value),
1304
+ className: "vpg-value-checkbox"
1305
+ }
1306
+ ),
1307
+ /* @__PURE__ */ jsx2("span", { className: `vpg-value-text ${value === "(blank)" ? "vpg-blank" : ""}`, children: value })
1308
+ ]
1309
+ },
1310
+ value
1311
+ )),
1312
+ allValues.length === 0 && /* @__PURE__ */ jsx2("div", { className: "vpg-no-results", children: "No matching values" })
1313
+ ] }),
1314
+ /* @__PURE__ */ jsxs2("div", { className: "vpg-filter-footer", children: [
1315
+ /* @__PURE__ */ jsx2("button", { className: "vpg-btn-clear", onClick: clearFilter, children: "Clear Filter" }),
1316
+ /* @__PURE__ */ jsx2("button", { className: "vpg-btn-apply", onClick: applyFilter, children: "Apply" })
940
1317
  ] })
941
1318
  ] }),
942
- /* @__PURE__ */ jsxs("div", { className: "vpg-values-list", children: [
943
- allValues.map((value) => /* @__PURE__ */ jsxs(
944
- "label",
1319
+ isNumericColumn && filterMode === "range" && /* @__PURE__ */ jsxs2(Fragment, { children: [
1320
+ /* @__PURE__ */ jsx2(
1321
+ NumericRangeFilter,
945
1322
  {
946
- className: `vpg-value-item ${localSelected.has(value) ? "selected" : ""}`,
947
- children: [
948
- /* @__PURE__ */ jsx(
949
- "input",
950
- {
951
- type: "checkbox",
952
- checked: localSelected.has(value),
953
- onChange: () => toggleValue(value),
954
- className: "vpg-value-checkbox"
955
- }
956
- ),
957
- /* @__PURE__ */ jsx("span", { className: `vpg-value-text ${value === "(blank)" ? "vpg-blank" : ""}`, children: value })
958
- ]
959
- },
960
- value
961
- )),
962
- allValues.length === 0 && /* @__PURE__ */ jsx("div", { className: "vpg-no-results", children: "No matching values" })
963
- ] }),
964
- /* @__PURE__ */ jsxs("div", { className: "vpg-filter-footer", children: [
965
- /* @__PURE__ */ jsx("button", { className: "vpg-btn-clear", onClick: clearFilter, children: "Clear Filter" }),
966
- /* @__PURE__ */ jsx("button", { className: "vpg-btn-apply", onClick: applyFilter, children: "Apply" })
1323
+ dataMin: stats.numericMin,
1324
+ dataMax: stats.numericMax,
1325
+ currentRange: localRange,
1326
+ onChange: handleRangeChange
1327
+ }
1328
+ ),
1329
+ /* @__PURE__ */ jsxs2("div", { className: "vpg-filter-footer", children: [
1330
+ /* @__PURE__ */ jsx2("button", { className: "vpg-btn-clear", onClick: clearRangeFilter, children: "Clear Filter" }),
1331
+ /* @__PURE__ */ jsx2("button", { className: "vpg-btn-apply", onClick: applyRangeFilter, children: "Apply" })
1332
+ ] })
967
1333
  ] })
968
1334
  ] });
969
1335
  }
970
1336
 
971
1337
  // src/components/PivotConfig.tsx
972
- import { useState as useState7, useMemo as useMemo7, useCallback as useCallback7 } from "react";
1338
+ import { useState as useState8, useMemo as useMemo8, useCallback as useCallback8 } from "react";
973
1339
  import { AGGREGATION_OPTIONS, getAggregationSymbol } from "@smallwebco/tinypivot-core";
974
1340
 
975
1341
  // src/components/CalculatedFieldModal.tsx
976
- import { useState as useState6, useEffect as useEffect4, useMemo as useMemo6, useCallback as useCallback6 } from "react";
1342
+ import { useState as useState7, useEffect as useEffect5, useMemo as useMemo7, useCallback as useCallback7 } from "react";
977
1343
  import { createPortal } from "react-dom";
978
1344
  import { validateSimpleFormula } from "@smallwebco/tinypivot-core";
979
- import { jsx as jsx2, jsxs as jsxs2 } from "react/jsx-runtime";
1345
+ import { jsx as jsx3, jsxs as jsxs3 } from "react/jsx-runtime";
980
1346
  function CalculatedFieldModal({
981
1347
  show,
982
1348
  availableFields,
@@ -984,12 +1350,12 @@ function CalculatedFieldModal({
984
1350
  onClose,
985
1351
  onSave
986
1352
  }) {
987
- const [name, setName] = useState6("");
988
- const [formula, setFormula] = useState6("");
989
- const [formatAs, setFormatAs] = useState6("number");
990
- const [decimals, setDecimals] = useState6(2);
991
- const [error, setError] = useState6(null);
992
- useEffect4(() => {
1353
+ const [name, setName] = useState7("");
1354
+ const [formula, setFormula] = useState7("");
1355
+ const [formatAs, setFormatAs] = useState7("number");
1356
+ const [decimals, setDecimals] = useState7(2);
1357
+ const [error, setError] = useState7(null);
1358
+ useEffect5(() => {
993
1359
  if (show) {
994
1360
  if (existingField) {
995
1361
  setName(existingField.name);
@@ -1005,11 +1371,11 @@ function CalculatedFieldModal({
1005
1371
  setError(null);
1006
1372
  }
1007
1373
  }, [show, existingField]);
1008
- const validationError = useMemo6(() => {
1374
+ const validationError = useMemo7(() => {
1009
1375
  if (!formula.trim()) return null;
1010
1376
  return validateSimpleFormula(formula, availableFields);
1011
1377
  }, [formula, availableFields]);
1012
- const insertField = useCallback6((field) => {
1378
+ const insertField = useCallback7((field) => {
1013
1379
  setFormula((prev) => {
1014
1380
  if (prev.trim() && !prev.endsWith(" ")) {
1015
1381
  return prev + " " + field;
@@ -1017,7 +1383,7 @@ function CalculatedFieldModal({
1017
1383
  return prev + field;
1018
1384
  });
1019
1385
  }, []);
1020
- const insertOperator = useCallback6((op) => {
1386
+ const insertOperator = useCallback7((op) => {
1021
1387
  setFormula((prev) => {
1022
1388
  if (prev.trim() && !prev.endsWith(" ")) {
1023
1389
  return prev + " " + op + " ";
@@ -1025,7 +1391,7 @@ function CalculatedFieldModal({
1025
1391
  return prev + op + " ";
1026
1392
  });
1027
1393
  }, []);
1028
- const handleSave = useCallback6(() => {
1394
+ const handleSave = useCallback7(() => {
1029
1395
  if (!name.trim()) {
1030
1396
  setError("Name is required");
1031
1397
  return;
@@ -1045,24 +1411,24 @@ function CalculatedFieldModal({
1045
1411
  onSave(field);
1046
1412
  onClose();
1047
1413
  }, [name, formula, formatAs, decimals, existingField, availableFields, onSave, onClose]);
1048
- const handleOverlayClick = useCallback6((e) => {
1414
+ const handleOverlayClick = useCallback7((e) => {
1049
1415
  if (e.target === e.currentTarget) {
1050
1416
  onClose();
1051
1417
  }
1052
1418
  }, [onClose]);
1053
1419
  if (!show) return null;
1054
- const modalContent = /* @__PURE__ */ jsx2("div", { className: "vpg-modal-overlay", onClick: handleOverlayClick, children: /* @__PURE__ */ jsxs2("div", { className: "vpg-modal", children: [
1055
- /* @__PURE__ */ jsxs2("div", { className: "vpg-modal-header", children: [
1056
- /* @__PURE__ */ jsxs2("h3", { children: [
1420
+ const modalContent = /* @__PURE__ */ jsx3("div", { className: "vpg-modal-overlay", onClick: handleOverlayClick, children: /* @__PURE__ */ jsxs3("div", { className: "vpg-modal", children: [
1421
+ /* @__PURE__ */ jsxs3("div", { className: "vpg-modal-header", children: [
1422
+ /* @__PURE__ */ jsxs3("h3", { children: [
1057
1423
  existingField ? "Edit" : "Create",
1058
1424
  " Calculated Field"
1059
1425
  ] }),
1060
- /* @__PURE__ */ jsx2("button", { className: "vpg-modal-close", onClick: onClose, children: "\xD7" })
1426
+ /* @__PURE__ */ jsx3("button", { className: "vpg-modal-close", onClick: onClose, children: "\xD7" })
1061
1427
  ] }),
1062
- /* @__PURE__ */ jsxs2("div", { className: "vpg-modal-body", children: [
1063
- /* @__PURE__ */ jsxs2("div", { className: "vpg-form-group", children: [
1064
- /* @__PURE__ */ jsx2("label", { className: "vpg-label", children: "Name" }),
1065
- /* @__PURE__ */ jsx2(
1428
+ /* @__PURE__ */ jsxs3("div", { className: "vpg-modal-body", children: [
1429
+ /* @__PURE__ */ jsxs3("div", { className: "vpg-form-group", children: [
1430
+ /* @__PURE__ */ jsx3("label", { className: "vpg-label", children: "Name" }),
1431
+ /* @__PURE__ */ jsx3(
1066
1432
  "input",
1067
1433
  {
1068
1434
  type: "text",
@@ -1073,9 +1439,9 @@ function CalculatedFieldModal({
1073
1439
  }
1074
1440
  )
1075
1441
  ] }),
1076
- /* @__PURE__ */ jsxs2("div", { className: "vpg-form-group", children: [
1077
- /* @__PURE__ */ jsx2("label", { className: "vpg-label", children: "Formula" }),
1078
- /* @__PURE__ */ jsx2(
1442
+ /* @__PURE__ */ jsxs3("div", { className: "vpg-form-group", children: [
1443
+ /* @__PURE__ */ jsx3("label", { className: "vpg-label", children: "Formula" }),
1444
+ /* @__PURE__ */ jsx3(
1079
1445
  "textarea",
1080
1446
  {
1081
1447
  className: "vpg-textarea",
@@ -1085,23 +1451,23 @@ function CalculatedFieldModal({
1085
1451
  onChange: (e) => setFormula(e.target.value)
1086
1452
  }
1087
1453
  ),
1088
- /* @__PURE__ */ jsx2("div", { className: "vpg-formula-hint", children: "Use field names with math operators: + - * / ( )" }),
1089
- validationError && /* @__PURE__ */ jsx2("div", { className: "vpg-error", children: validationError })
1454
+ /* @__PURE__ */ jsx3("div", { className: "vpg-formula-hint", children: "Use field names with math operators: + - * / ( )" }),
1455
+ validationError && /* @__PURE__ */ jsx3("div", { className: "vpg-error", children: validationError })
1090
1456
  ] }),
1091
- /* @__PURE__ */ jsxs2("div", { className: "vpg-form-group", children: [
1092
- /* @__PURE__ */ jsx2("label", { className: "vpg-label-small", children: "Operators" }),
1093
- /* @__PURE__ */ jsxs2("div", { className: "vpg-button-group", children: [
1094
- /* @__PURE__ */ jsx2("button", { className: "vpg-insert-btn vpg-op-btn", onClick: () => insertOperator("+"), children: "+" }),
1095
- /* @__PURE__ */ jsx2("button", { className: "vpg-insert-btn vpg-op-btn", onClick: () => insertOperator("-"), children: "\u2212" }),
1096
- /* @__PURE__ */ jsx2("button", { className: "vpg-insert-btn vpg-op-btn", onClick: () => insertOperator("*"), children: "\xD7" }),
1097
- /* @__PURE__ */ jsx2("button", { className: "vpg-insert-btn vpg-op-btn", onClick: () => insertOperator("/"), children: "\xF7" }),
1098
- /* @__PURE__ */ jsx2("button", { className: "vpg-insert-btn vpg-op-btn", onClick: () => insertOperator("("), children: "(" }),
1099
- /* @__PURE__ */ jsx2("button", { className: "vpg-insert-btn vpg-op-btn", onClick: () => insertOperator(")"), children: ")" })
1457
+ /* @__PURE__ */ jsxs3("div", { className: "vpg-form-group", children: [
1458
+ /* @__PURE__ */ jsx3("label", { className: "vpg-label-small", children: "Operators" }),
1459
+ /* @__PURE__ */ jsxs3("div", { className: "vpg-button-group", children: [
1460
+ /* @__PURE__ */ jsx3("button", { className: "vpg-insert-btn vpg-op-btn", onClick: () => insertOperator("+"), children: "+" }),
1461
+ /* @__PURE__ */ jsx3("button", { className: "vpg-insert-btn vpg-op-btn", onClick: () => insertOperator("-"), children: "\u2212" }),
1462
+ /* @__PURE__ */ jsx3("button", { className: "vpg-insert-btn vpg-op-btn", onClick: () => insertOperator("*"), children: "\xD7" }),
1463
+ /* @__PURE__ */ jsx3("button", { className: "vpg-insert-btn vpg-op-btn", onClick: () => insertOperator("/"), children: "\xF7" }),
1464
+ /* @__PURE__ */ jsx3("button", { className: "vpg-insert-btn vpg-op-btn", onClick: () => insertOperator("("), children: "(" }),
1465
+ /* @__PURE__ */ jsx3("button", { className: "vpg-insert-btn vpg-op-btn", onClick: () => insertOperator(")"), children: ")" })
1100
1466
  ] })
1101
1467
  ] }),
1102
- /* @__PURE__ */ jsxs2("div", { className: "vpg-form-group", children: [
1103
- /* @__PURE__ */ jsx2("label", { className: "vpg-label-small", children: "Insert Field" }),
1104
- availableFields.length > 0 ? /* @__PURE__ */ jsx2("div", { className: "vpg-button-group vpg-field-buttons", children: availableFields.map((field) => /* @__PURE__ */ jsx2(
1468
+ /* @__PURE__ */ jsxs3("div", { className: "vpg-form-group", children: [
1469
+ /* @__PURE__ */ jsx3("label", { className: "vpg-label-small", children: "Insert Field" }),
1470
+ availableFields.length > 0 ? /* @__PURE__ */ jsx3("div", { className: "vpg-button-group vpg-field-buttons", children: availableFields.map((field) => /* @__PURE__ */ jsx3(
1105
1471
  "button",
1106
1472
  {
1107
1473
  className: "vpg-insert-btn vpg-field-btn",
@@ -1109,28 +1475,28 @@ function CalculatedFieldModal({
1109
1475
  children: field
1110
1476
  },
1111
1477
  field
1112
- )) }) : /* @__PURE__ */ jsx2("div", { className: "vpg-no-fields", children: "No numeric fields available" })
1478
+ )) }) : /* @__PURE__ */ jsx3("div", { className: "vpg-no-fields", children: "No numeric fields available" })
1113
1479
  ] }),
1114
- /* @__PURE__ */ jsxs2("div", { className: "vpg-form-row", children: [
1115
- /* @__PURE__ */ jsxs2("div", { className: "vpg-form-group vpg-form-group-half", children: [
1116
- /* @__PURE__ */ jsx2("label", { className: "vpg-label", children: "Format As" }),
1117
- /* @__PURE__ */ jsxs2(
1480
+ /* @__PURE__ */ jsxs3("div", { className: "vpg-form-row", children: [
1481
+ /* @__PURE__ */ jsxs3("div", { className: "vpg-form-group vpg-form-group-half", children: [
1482
+ /* @__PURE__ */ jsx3("label", { className: "vpg-label", children: "Format As" }),
1483
+ /* @__PURE__ */ jsxs3(
1118
1484
  "select",
1119
1485
  {
1120
1486
  className: "vpg-select",
1121
1487
  value: formatAs,
1122
1488
  onChange: (e) => setFormatAs(e.target.value),
1123
1489
  children: [
1124
- /* @__PURE__ */ jsx2("option", { value: "number", children: "Number" }),
1125
- /* @__PURE__ */ jsx2("option", { value: "percent", children: "Percentage" }),
1126
- /* @__PURE__ */ jsx2("option", { value: "currency", children: "Currency ($)" })
1490
+ /* @__PURE__ */ jsx3("option", { value: "number", children: "Number" }),
1491
+ /* @__PURE__ */ jsx3("option", { value: "percent", children: "Percentage" }),
1492
+ /* @__PURE__ */ jsx3("option", { value: "currency", children: "Currency ($)" })
1127
1493
  ]
1128
1494
  }
1129
1495
  )
1130
1496
  ] }),
1131
- /* @__PURE__ */ jsxs2("div", { className: "vpg-form-group vpg-form-group-half", children: [
1132
- /* @__PURE__ */ jsx2("label", { className: "vpg-label", children: "Decimals" }),
1133
- /* @__PURE__ */ jsx2(
1497
+ /* @__PURE__ */ jsxs3("div", { className: "vpg-form-group vpg-form-group-half", children: [
1498
+ /* @__PURE__ */ jsx3("label", { className: "vpg-label", children: "Decimals" }),
1499
+ /* @__PURE__ */ jsx3(
1134
1500
  "input",
1135
1501
  {
1136
1502
  type: "number",
@@ -1143,11 +1509,11 @@ function CalculatedFieldModal({
1143
1509
  )
1144
1510
  ] })
1145
1511
  ] }),
1146
- error && /* @__PURE__ */ jsx2("div", { className: "vpg-error vpg-error-box", children: error })
1512
+ error && /* @__PURE__ */ jsx3("div", { className: "vpg-error vpg-error-box", children: error })
1147
1513
  ] }),
1148
- /* @__PURE__ */ jsxs2("div", { className: "vpg-modal-footer", children: [
1149
- /* @__PURE__ */ jsx2("button", { className: "vpg-btn vpg-btn-secondary", onClick: onClose, children: "Cancel" }),
1150
- /* @__PURE__ */ jsxs2("button", { className: "vpg-btn vpg-btn-primary", onClick: handleSave, children: [
1514
+ /* @__PURE__ */ jsxs3("div", { className: "vpg-modal-footer", children: [
1515
+ /* @__PURE__ */ jsx3("button", { className: "vpg-btn vpg-btn-secondary", onClick: onClose, children: "Cancel" }),
1516
+ /* @__PURE__ */ jsxs3("button", { className: "vpg-btn vpg-btn-primary", onClick: handleSave, children: [
1151
1517
  existingField ? "Update" : "Add",
1152
1518
  " Field"
1153
1519
  ] })
@@ -1157,7 +1523,7 @@ function CalculatedFieldModal({
1157
1523
  }
1158
1524
 
1159
1525
  // src/components/PivotConfig.tsx
1160
- import { Fragment, jsx as jsx3, jsxs as jsxs3 } from "react/jsx-runtime";
1526
+ import { Fragment as Fragment2, jsx as jsx4, jsxs as jsxs4 } from "react/jsx-runtime";
1161
1527
  function getFieldIcon(type, isCalculated) {
1162
1528
  if (isCalculated) return "\u0192";
1163
1529
  switch (type) {
@@ -1194,14 +1560,14 @@ function PivotConfig({
1194
1560
  onRemoveCalculatedField,
1195
1561
  onUpdateCalculatedField
1196
1562
  }) {
1197
- const [fieldSearch, setFieldSearch] = useState7("");
1198
- const [showCalcModal, setShowCalcModal] = useState7(false);
1199
- const [editingCalcField, setEditingCalcField] = useState7(null);
1200
- const numericFieldNames = useMemo7(
1563
+ const [fieldSearch, setFieldSearch] = useState8("");
1564
+ const [showCalcModal, setShowCalcModal] = useState8(false);
1565
+ const [editingCalcField, setEditingCalcField] = useState8(null);
1566
+ const numericFieldNames = useMemo8(
1201
1567
  () => availableFields.filter((f) => f.isNumeric).map((f) => f.field),
1202
1568
  [availableFields]
1203
1569
  );
1204
- const calculatedFieldsAsStats = useMemo7(() => {
1570
+ const calculatedFieldsAsStats = useMemo8(() => {
1205
1571
  if (!calculatedFields) return [];
1206
1572
  return calculatedFields.map((calc) => ({
1207
1573
  field: `calc:${calc.id}`,
@@ -1214,11 +1580,11 @@ function PivotConfig({
1214
1580
  calcFormula: calc.formula
1215
1581
  }));
1216
1582
  }, [calculatedFields]);
1217
- const allAvailableFields = useMemo7(() => [
1583
+ const allAvailableFields = useMemo8(() => [
1218
1584
  ...availableFields.map((f) => ({ ...f, isCalculated: false })),
1219
1585
  ...calculatedFieldsAsStats
1220
1586
  ], [availableFields, calculatedFieldsAsStats]);
1221
- const assignedFields = useMemo7(() => {
1587
+ const assignedFields = useMemo8(() => {
1222
1588
  const rowSet = new Set(rowFields);
1223
1589
  const colSet = new Set(columnFields);
1224
1590
  const valueMap = new Map(valueFields.map((v) => [v.field, v]));
@@ -1228,7 +1594,7 @@ function PivotConfig({
1228
1594
  valueConfig: valueMap.get(f.field)
1229
1595
  }));
1230
1596
  }, [allAvailableFields, rowFields, columnFields, valueFields]);
1231
- const unassignedFields = useMemo7(() => {
1597
+ const unassignedFields = useMemo8(() => {
1232
1598
  const rowSet = new Set(rowFields);
1233
1599
  const colSet = new Set(columnFields);
1234
1600
  const valSet = new Set(valueFields.map((v) => v.field));
@@ -1236,7 +1602,7 @@ function PivotConfig({
1236
1602
  (f) => !rowSet.has(f.field) && !colSet.has(f.field) && !valSet.has(f.field)
1237
1603
  );
1238
1604
  }, [allAvailableFields, rowFields, columnFields, valueFields]);
1239
- const filteredUnassignedFields = useMemo7(() => {
1605
+ const filteredUnassignedFields = useMemo8(() => {
1240
1606
  if (!fieldSearch.trim()) return unassignedFields;
1241
1607
  const search = fieldSearch.toLowerCase().trim();
1242
1608
  return unassignedFields.filter((f) => {
@@ -1246,13 +1612,13 @@ function PivotConfig({
1246
1612
  });
1247
1613
  }, [unassignedFields, fieldSearch]);
1248
1614
  const assignedCount = assignedFields.length;
1249
- const getFieldDisplayName = useCallback7((field) => {
1615
+ const getFieldDisplayName = useCallback8((field) => {
1250
1616
  if (field.isCalculated && field.calcName) {
1251
1617
  return field.calcName;
1252
1618
  }
1253
1619
  return field.field;
1254
1620
  }, []);
1255
- const handleDragStart = useCallback7(
1621
+ const handleDragStart = useCallback8(
1256
1622
  (field, event) => {
1257
1623
  event.dataTransfer?.setData("text/plain", field);
1258
1624
  event.dataTransfer.effectAllowed = "move";
@@ -1260,13 +1626,13 @@ function PivotConfig({
1260
1626
  },
1261
1627
  [onDragStart]
1262
1628
  );
1263
- const handleAggregationChange = useCallback7(
1629
+ const handleAggregationChange = useCallback8(
1264
1630
  (field, currentAgg, newAgg) => {
1265
1631
  onUpdateAggregation(field, currentAgg, newAgg);
1266
1632
  },
1267
1633
  [onUpdateAggregation]
1268
1634
  );
1269
- const toggleRowColumn = useCallback7(
1635
+ const toggleRowColumn = useCallback8(
1270
1636
  (field, currentAssignment) => {
1271
1637
  if (currentAssignment === "row") {
1272
1638
  onRemoveRowField(field);
@@ -1278,7 +1644,7 @@ function PivotConfig({
1278
1644
  },
1279
1645
  [onRemoveRowField, onAddColumnField, onRemoveColumnField, onAddRowField]
1280
1646
  );
1281
- const removeField = useCallback7(
1647
+ const removeField = useCallback8(
1282
1648
  (field, assignedTo, valueConfig) => {
1283
1649
  if (assignedTo === "row") {
1284
1650
  onRemoveRowField(field);
@@ -1290,15 +1656,15 @@ function PivotConfig({
1290
1656
  },
1291
1657
  [onRemoveRowField, onRemoveColumnField, onRemoveValueField]
1292
1658
  );
1293
- const handleTotalsToggle = useCallback7((checked) => {
1659
+ const handleTotalsToggle = useCallback8((checked) => {
1294
1660
  onShowRowTotalsChange(checked);
1295
1661
  onShowColumnTotalsChange(checked);
1296
1662
  }, [onShowRowTotalsChange, onShowColumnTotalsChange]);
1297
- const openCalcModal = useCallback7((field) => {
1663
+ const openCalcModal = useCallback8((field) => {
1298
1664
  setEditingCalcField(field || null);
1299
1665
  setShowCalcModal(true);
1300
1666
  }, []);
1301
- const handleSaveCalcField = useCallback7((field) => {
1667
+ const handleSaveCalcField = useCallback8((field) => {
1302
1668
  if (editingCalcField && onUpdateCalculatedField) {
1303
1669
  onUpdateCalculatedField(field);
1304
1670
  } else if (onAddCalculatedField) {
@@ -1307,14 +1673,14 @@ function PivotConfig({
1307
1673
  setShowCalcModal(false);
1308
1674
  setEditingCalcField(null);
1309
1675
  }, [editingCalcField, onAddCalculatedField, onUpdateCalculatedField]);
1310
- const handleCloseCalcModal = useCallback7(() => {
1676
+ const handleCloseCalcModal = useCallback8(() => {
1311
1677
  setShowCalcModal(false);
1312
1678
  setEditingCalcField(null);
1313
1679
  }, []);
1314
- return /* @__PURE__ */ jsxs3("div", { className: "vpg-pivot-config", children: [
1315
- /* @__PURE__ */ jsxs3("div", { className: "vpg-config-header", children: [
1316
- /* @__PURE__ */ jsxs3("h3", { className: "vpg-config-title", children: [
1317
- /* @__PURE__ */ jsx3("svg", { className: "vpg-icon", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: /* @__PURE__ */ jsx3(
1680
+ return /* @__PURE__ */ jsxs4("div", { className: "vpg-pivot-config", children: [
1681
+ /* @__PURE__ */ jsxs4("div", { className: "vpg-config-header", children: [
1682
+ /* @__PURE__ */ jsxs4("h3", { className: "vpg-config-title", children: [
1683
+ /* @__PURE__ */ jsx4("svg", { className: "vpg-icon", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: /* @__PURE__ */ jsx4(
1318
1684
  "path",
1319
1685
  {
1320
1686
  strokeLinecap: "round",
@@ -1325,13 +1691,13 @@ function PivotConfig({
1325
1691
  ) }),
1326
1692
  "Fields"
1327
1693
  ] }),
1328
- /* @__PURE__ */ jsx3("div", { className: "vpg-header-actions", children: assignedCount > 0 && /* @__PURE__ */ jsx3(
1694
+ /* @__PURE__ */ jsx4("div", { className: "vpg-header-actions", children: assignedCount > 0 && /* @__PURE__ */ jsx4(
1329
1695
  "button",
1330
1696
  {
1331
1697
  className: "vpg-action-btn vpg-clear-btn",
1332
1698
  title: "Clear all",
1333
1699
  onClick: onClearConfig,
1334
- children: /* @__PURE__ */ jsx3("svg", { className: "vpg-icon-sm", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: /* @__PURE__ */ jsx3(
1700
+ children: /* @__PURE__ */ jsx4("svg", { className: "vpg-icon-sm", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: /* @__PURE__ */ jsx4(
1335
1701
  "path",
1336
1702
  {
1337
1703
  strokeLinecap: "round",
@@ -1343,9 +1709,9 @@ function PivotConfig({
1343
1709
  }
1344
1710
  ) })
1345
1711
  ] }),
1346
- assignedCount > 0 && /* @__PURE__ */ jsxs3("div", { className: "vpg-assigned-section", children: [
1347
- /* @__PURE__ */ jsx3("div", { className: "vpg-section-label", children: "Active" }),
1348
- /* @__PURE__ */ jsx3("div", { className: "vpg-assigned-list", children: assignedFields.map((field) => /* @__PURE__ */ jsxs3(
1712
+ assignedCount > 0 && /* @__PURE__ */ jsxs4("div", { className: "vpg-assigned-section", children: [
1713
+ /* @__PURE__ */ jsx4("div", { className: "vpg-section-label", children: "Active" }),
1714
+ /* @__PURE__ */ jsx4("div", { className: "vpg-assigned-list", children: assignedFields.map((field) => /* @__PURE__ */ jsxs4(
1349
1715
  "div",
1350
1716
  {
1351
1717
  className: `vpg-assigned-item vpg-type-${field.assignedTo}${field.isCalculated ? " vpg-type-calc" : ""}`,
@@ -1354,12 +1720,12 @@ function PivotConfig({
1354
1720
  onDragStart: (e) => handleDragStart(field.field, e),
1355
1721
  onDragEnd,
1356
1722
  children: [
1357
- /* @__PURE__ */ jsxs3("div", { className: "vpg-item-main", children: [
1358
- /* @__PURE__ */ jsx3("span", { className: `vpg-item-badge ${field.assignedTo}${field.isCalculated ? " calc" : ""}`, children: field.isCalculated ? "\u0192" : field.assignedTo === "row" ? "R" : field.assignedTo === "column" ? "C" : getAggregationSymbol(field.valueConfig?.aggregation || "sum") }),
1359
- /* @__PURE__ */ jsx3("span", { className: "vpg-item-name", children: getFieldDisplayName(field) })
1723
+ /* @__PURE__ */ jsxs4("div", { className: "vpg-item-main", children: [
1724
+ /* @__PURE__ */ jsx4("span", { className: `vpg-item-badge ${field.assignedTo}${field.isCalculated ? " calc" : ""}`, children: field.isCalculated ? "\u0192" : field.assignedTo === "row" ? "R" : field.assignedTo === "column" ? "C" : getAggregationSymbol(field.valueConfig?.aggregation || "sum") }),
1725
+ /* @__PURE__ */ jsx4("span", { className: "vpg-item-name", children: getFieldDisplayName(field) })
1360
1726
  ] }),
1361
- /* @__PURE__ */ jsxs3("div", { className: "vpg-item-actions", children: [
1362
- (field.assignedTo === "row" || field.assignedTo === "column") && /* @__PURE__ */ jsx3(
1727
+ /* @__PURE__ */ jsxs4("div", { className: "vpg-item-actions", children: [
1728
+ (field.assignedTo === "row" || field.assignedTo === "column") && /* @__PURE__ */ jsx4(
1363
1729
  "button",
1364
1730
  {
1365
1731
  className: "vpg-toggle-btn",
@@ -1368,14 +1734,14 @@ function PivotConfig({
1368
1734
  e.stopPropagation();
1369
1735
  toggleRowColumn(field.field, field.assignedTo);
1370
1736
  },
1371
- children: /* @__PURE__ */ jsx3(
1737
+ children: /* @__PURE__ */ jsx4(
1372
1738
  "svg",
1373
1739
  {
1374
1740
  className: "vpg-icon-xs",
1375
1741
  fill: "none",
1376
1742
  stroke: "currentColor",
1377
1743
  viewBox: "0 0 24 24",
1378
- children: /* @__PURE__ */ jsx3(
1744
+ children: /* @__PURE__ */ jsx4(
1379
1745
  "path",
1380
1746
  {
1381
1747
  strokeLinecap: "round",
@@ -1388,7 +1754,7 @@ function PivotConfig({
1388
1754
  )
1389
1755
  }
1390
1756
  ),
1391
- field.assignedTo === "value" && field.valueConfig && /* @__PURE__ */ jsx3(
1757
+ field.assignedTo === "value" && field.valueConfig && /* @__PURE__ */ jsx4(
1392
1758
  "select",
1393
1759
  {
1394
1760
  className: "vpg-agg-select",
@@ -1402,14 +1768,14 @@ function PivotConfig({
1402
1768
  );
1403
1769
  },
1404
1770
  onClick: (e) => e.stopPropagation(),
1405
- children: AGGREGATION_OPTIONS.map((agg) => /* @__PURE__ */ jsxs3("option", { value: agg.value, children: [
1771
+ children: AGGREGATION_OPTIONS.map((agg) => /* @__PURE__ */ jsxs4("option", { value: agg.value, children: [
1406
1772
  agg.symbol,
1407
1773
  " ",
1408
1774
  agg.label
1409
1775
  ] }, agg.value))
1410
1776
  }
1411
1777
  ),
1412
- /* @__PURE__ */ jsx3(
1778
+ /* @__PURE__ */ jsx4(
1413
1779
  "button",
1414
1780
  {
1415
1781
  className: "vpg-remove-btn",
@@ -1427,13 +1793,13 @@ function PivotConfig({
1427
1793
  field.field
1428
1794
  )) })
1429
1795
  ] }),
1430
- /* @__PURE__ */ jsxs3("div", { className: "vpg-unassigned-section", children: [
1431
- /* @__PURE__ */ jsx3("div", { className: "vpg-section-header", children: /* @__PURE__ */ jsxs3("div", { className: "vpg-section-label", children: [
1796
+ /* @__PURE__ */ jsxs4("div", { className: "vpg-unassigned-section", children: [
1797
+ /* @__PURE__ */ jsx4("div", { className: "vpg-section-header", children: /* @__PURE__ */ jsxs4("div", { className: "vpg-section-label", children: [
1432
1798
  "Available ",
1433
- /* @__PURE__ */ jsx3("span", { className: "vpg-count", children: unassignedFields.length })
1799
+ /* @__PURE__ */ jsx4("span", { className: "vpg-count", children: unassignedFields.length })
1434
1800
  ] }) }),
1435
- /* @__PURE__ */ jsxs3("div", { className: "vpg-field-search", children: [
1436
- /* @__PURE__ */ jsx3("svg", { className: "vpg-search-icon", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: /* @__PURE__ */ jsx3(
1801
+ /* @__PURE__ */ jsxs4("div", { className: "vpg-field-search", children: [
1802
+ /* @__PURE__ */ jsx4("svg", { className: "vpg-search-icon", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: /* @__PURE__ */ jsx4(
1437
1803
  "path",
1438
1804
  {
1439
1805
  strokeLinecap: "round",
@@ -1442,7 +1808,7 @@ function PivotConfig({
1442
1808
  d: "M21 21l-6-6m2-5a7 7 0 11-14 0 7 7 0 0114 0z"
1443
1809
  }
1444
1810
  ) }),
1445
- /* @__PURE__ */ jsx3(
1811
+ /* @__PURE__ */ jsx4(
1446
1812
  "input",
1447
1813
  {
1448
1814
  type: "text",
@@ -1452,7 +1818,7 @@ function PivotConfig({
1452
1818
  className: "vpg-search-input"
1453
1819
  }
1454
1820
  ),
1455
- fieldSearch && /* @__PURE__ */ jsx3("button", { className: "vpg-clear-search", onClick: () => setFieldSearch(""), children: /* @__PURE__ */ jsx3("svg", { className: "vpg-icon-xs", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: /* @__PURE__ */ jsx3(
1821
+ fieldSearch && /* @__PURE__ */ jsx4("button", { className: "vpg-clear-search", onClick: () => setFieldSearch(""), children: /* @__PURE__ */ jsx4("svg", { className: "vpg-icon-xs", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: /* @__PURE__ */ jsx4(
1456
1822
  "path",
1457
1823
  {
1458
1824
  strokeLinecap: "round",
@@ -1462,8 +1828,8 @@ function PivotConfig({
1462
1828
  }
1463
1829
  ) }) })
1464
1830
  ] }),
1465
- /* @__PURE__ */ jsxs3("div", { className: "vpg-field-list", children: [
1466
- filteredUnassignedFields.map((field) => /* @__PURE__ */ jsxs3(
1831
+ /* @__PURE__ */ jsxs4("div", { className: "vpg-field-list", children: [
1832
+ filteredUnassignedFields.map((field) => /* @__PURE__ */ jsxs4(
1467
1833
  "div",
1468
1834
  {
1469
1835
  className: `vpg-field-item${field.isNumeric && !field.isCalculated ? " vpg-is-numeric" : ""}${field.isCalculated ? " vpg-is-calculated" : ""}`,
@@ -1472,10 +1838,10 @@ function PivotConfig({
1472
1838
  onDragStart: (e) => handleDragStart(field.field, e),
1473
1839
  onDragEnd,
1474
1840
  children: [
1475
- /* @__PURE__ */ jsx3("span", { className: `vpg-field-type-icon${field.isCalculated ? " vpg-calc-type" : ""}`, title: field.type, children: getFieldIcon(field.type, field.isCalculated) }),
1476
- /* @__PURE__ */ jsx3("span", { className: "vpg-field-name", children: getFieldDisplayName(field) }),
1477
- field.isCalculated ? /* @__PURE__ */ jsxs3(Fragment, { children: [
1478
- /* @__PURE__ */ jsx3(
1841
+ /* @__PURE__ */ jsx4("span", { className: `vpg-field-type-icon${field.isCalculated ? " vpg-calc-type" : ""}`, title: field.type, children: getFieldIcon(field.type, field.isCalculated) }),
1842
+ /* @__PURE__ */ jsx4("span", { className: "vpg-field-name", children: getFieldDisplayName(field) }),
1843
+ field.isCalculated ? /* @__PURE__ */ jsxs4(Fragment2, { children: [
1844
+ /* @__PURE__ */ jsx4(
1479
1845
  "button",
1480
1846
  {
1481
1847
  className: "vpg-field-edit",
@@ -1488,7 +1854,7 @@ function PivotConfig({
1488
1854
  children: "\u270E"
1489
1855
  }
1490
1856
  ),
1491
- /* @__PURE__ */ jsx3(
1857
+ /* @__PURE__ */ jsx4(
1492
1858
  "button",
1493
1859
  {
1494
1860
  className: "vpg-field-delete",
@@ -1502,22 +1868,22 @@ function PivotConfig({
1502
1868
  children: "\xD7"
1503
1869
  }
1504
1870
  )
1505
- ] }) : /* @__PURE__ */ jsx3("span", { className: "vpg-unique-count", children: field.uniqueCount })
1871
+ ] }) : /* @__PURE__ */ jsx4("span", { className: "vpg-unique-count", children: field.uniqueCount })
1506
1872
  ]
1507
1873
  },
1508
1874
  field.field
1509
1875
  )),
1510
- filteredUnassignedFields.length === 0 && fieldSearch && /* @__PURE__ */ jsxs3("div", { className: "vpg-empty-hint", children: [
1876
+ filteredUnassignedFields.length === 0 && fieldSearch && /* @__PURE__ */ jsxs4("div", { className: "vpg-empty-hint", children: [
1511
1877
  'No fields match "',
1512
1878
  fieldSearch,
1513
1879
  '"'
1514
1880
  ] }),
1515
- unassignedFields.length === 0 && /* @__PURE__ */ jsx3("div", { className: "vpg-empty-hint", children: "All fields assigned" })
1881
+ unassignedFields.length === 0 && /* @__PURE__ */ jsx4("div", { className: "vpg-empty-hint", children: "All fields assigned" })
1516
1882
  ] })
1517
1883
  ] }),
1518
- /* @__PURE__ */ jsxs3("div", { className: "vpg-options-section", children: [
1519
- /* @__PURE__ */ jsxs3("label", { className: "vpg-option-toggle", children: [
1520
- /* @__PURE__ */ jsx3(
1884
+ /* @__PURE__ */ jsxs4("div", { className: "vpg-options-section", children: [
1885
+ /* @__PURE__ */ jsxs4("label", { className: "vpg-option-toggle", children: [
1886
+ /* @__PURE__ */ jsx4(
1521
1887
  "input",
1522
1888
  {
1523
1889
  type: "checkbox",
@@ -1525,14 +1891,14 @@ function PivotConfig({
1525
1891
  onChange: (e) => handleTotalsToggle(e.target.checked)
1526
1892
  }
1527
1893
  ),
1528
- /* @__PURE__ */ jsx3("span", { children: "Totals" })
1894
+ /* @__PURE__ */ jsx4("span", { children: "Totals" })
1529
1895
  ] }),
1530
- /* @__PURE__ */ jsxs3("button", { className: "vpg-calc-btn", onClick: () => openCalcModal(), title: "Add calculated field (e.g. Profit Margin %)", children: [
1531
- /* @__PURE__ */ jsx3("span", { className: "vpg-calc-icon", children: "\u0192" }),
1532
- /* @__PURE__ */ jsx3("span", { children: "+ Calc" })
1896
+ /* @__PURE__ */ jsxs4("button", { className: "vpg-calc-btn", onClick: () => openCalcModal(), title: "Add calculated field (e.g. Profit Margin %)", children: [
1897
+ /* @__PURE__ */ jsx4("span", { className: "vpg-calc-icon", children: "\u0192" }),
1898
+ /* @__PURE__ */ jsx4("span", { children: "+ Calc" })
1533
1899
  ] })
1534
1900
  ] }),
1535
- /* @__PURE__ */ jsx3(
1901
+ /* @__PURE__ */ jsx4(
1536
1902
  CalculatedFieldModal,
1537
1903
  {
1538
1904
  show: showCalcModal,
@@ -1546,9 +1912,9 @@ function PivotConfig({
1546
1912
  }
1547
1913
 
1548
1914
  // src/components/PivotSkeleton.tsx
1549
- import { useState as useState8, useMemo as useMemo8, useCallback as useCallback8, useEffect as useEffect5 } from "react";
1915
+ import { useState as useState9, useMemo as useMemo9, useCallback as useCallback9, useEffect as useEffect6 } from "react";
1550
1916
  import { getAggregationLabel as getAggregationLabel2, getAggregationSymbol as getAggregationSymbol2 } from "@smallwebco/tinypivot-core";
1551
- import { Fragment as Fragment2, jsx as jsx4, jsxs as jsxs4 } from "react/jsx-runtime";
1917
+ import { Fragment as Fragment3, jsx as jsx5, jsxs as jsxs5 } from "react/jsx-runtime";
1552
1918
  function PivotSkeleton({
1553
1919
  rowFields,
1554
1920
  columnFields,
@@ -1571,7 +1937,7 @@ function PivotSkeleton({
1571
1937
  onReorderColumnFields
1572
1938
  }) {
1573
1939
  const { showWatermark, canUsePivot, isDemo } = useLicense();
1574
- const getValueFieldDisplayName = useCallback8((field) => {
1940
+ const getValueFieldDisplayName = useCallback9((field) => {
1575
1941
  if (field.startsWith("calc:")) {
1576
1942
  const calcId = field.replace("calc:", "");
1577
1943
  const calcField = calculatedFields?.find((c) => c.id === calcId);
@@ -1579,15 +1945,15 @@ function PivotSkeleton({
1579
1945
  }
1580
1946
  return field;
1581
1947
  }, [calculatedFields]);
1582
- const isCalculatedField = useCallback8((field) => {
1948
+ const isCalculatedField = useCallback9((field) => {
1583
1949
  return field.startsWith("calc:");
1584
1950
  }, []);
1585
- const [dragOverArea, setDragOverArea] = useState8(null);
1586
- const [reorderDragSource, setReorderDragSource] = useState8(null);
1587
- const [reorderDropTarget, setReorderDropTarget] = useState8(null);
1588
- const [sortDirection, setSortDirection] = useState8("asc");
1589
- const [sortTarget, setSortTarget] = useState8("row");
1590
- const toggleSort = useCallback8((target = "row") => {
1951
+ const [dragOverArea, setDragOverArea] = useState9(null);
1952
+ const [reorderDragSource, setReorderDragSource] = useState9(null);
1953
+ const [reorderDropTarget, setReorderDropTarget] = useState9(null);
1954
+ const [sortDirection, setSortDirection] = useState9("asc");
1955
+ const [sortTarget, setSortTarget] = useState9("row");
1956
+ const toggleSort = useCallback9((target = "row") => {
1591
1957
  if (sortTarget === target) {
1592
1958
  setSortDirection((prev) => prev === "asc" ? "desc" : "asc");
1593
1959
  } else {
@@ -1595,13 +1961,13 @@ function PivotSkeleton({
1595
1961
  setSortDirection("asc");
1596
1962
  }
1597
1963
  }, [sortTarget]);
1598
- const [selectedCell, setSelectedCell] = useState8(null);
1599
- const [selectionStart, setSelectionStart] = useState8(null);
1600
- const [selectionEnd, setSelectionEnd] = useState8(null);
1601
- const [isSelecting, setIsSelecting] = useState8(false);
1602
- const [showCopyToast, setShowCopyToast] = useState8(false);
1603
- const [copyToastMessage, setCopyToastMessage] = useState8("");
1604
- const selectionBounds = useMemo8(() => {
1964
+ const [selectedCell, setSelectedCell] = useState9(null);
1965
+ const [selectionStart, setSelectionStart] = useState9(null);
1966
+ const [selectionEnd, setSelectionEnd] = useState9(null);
1967
+ const [isSelecting, setIsSelecting] = useState9(false);
1968
+ const [showCopyToast, setShowCopyToast] = useState9(false);
1969
+ const [copyToastMessage, setCopyToastMessage] = useState9("");
1970
+ const selectionBounds = useMemo9(() => {
1605
1971
  if (!selectionStart || !selectionEnd) return null;
1606
1972
  return {
1607
1973
  minRow: Math.min(selectionStart.row, selectionEnd.row),
@@ -1610,7 +1976,7 @@ function PivotSkeleton({
1610
1976
  maxCol: Math.max(selectionStart.col, selectionEnd.col)
1611
1977
  };
1612
1978
  }, [selectionStart, selectionEnd]);
1613
- const handleCellMouseDown = useCallback8(
1979
+ const handleCellMouseDown = useCallback9(
1614
1980
  (rowIndex, colIndex, event) => {
1615
1981
  event.preventDefault();
1616
1982
  if (event.shiftKey && selectedCell) {
@@ -1624,7 +1990,7 @@ function PivotSkeleton({
1624
1990
  },
1625
1991
  [selectedCell]
1626
1992
  );
1627
- const handleCellMouseEnter = useCallback8(
1993
+ const handleCellMouseEnter = useCallback9(
1628
1994
  (rowIndex, colIndex) => {
1629
1995
  if (isSelecting) {
1630
1996
  setSelectionEnd({ row: rowIndex, col: colIndex });
@@ -1632,7 +1998,7 @@ function PivotSkeleton({
1632
1998
  },
1633
1999
  [isSelecting]
1634
2000
  );
1635
- const isCellSelected = useCallback8(
2001
+ const isCellSelected = useCallback9(
1636
2002
  (rowIndex, colIndex) => {
1637
2003
  if (!selectionBounds) {
1638
2004
  return selectedCell?.row === rowIndex && selectedCell?.col === colIndex;
@@ -1642,12 +2008,12 @@ function PivotSkeleton({
1642
2008
  },
1643
2009
  [selectionBounds, selectedCell]
1644
2010
  );
1645
- useEffect5(() => {
2011
+ useEffect6(() => {
1646
2012
  const handleMouseUp = () => setIsSelecting(false);
1647
2013
  document.addEventListener("mouseup", handleMouseUp);
1648
2014
  return () => document.removeEventListener("mouseup", handleMouseUp);
1649
2015
  }, []);
1650
- const sortedRowIndices = useMemo8(() => {
2016
+ const sortedRowIndices = useMemo9(() => {
1651
2017
  if (!pivotResult) return [];
1652
2018
  const indices = pivotResult.rowHeaders.map((_, i) => i);
1653
2019
  const headers = pivotResult.rowHeaders;
@@ -1671,7 +2037,7 @@ function PivotSkeleton({
1671
2037
  });
1672
2038
  return indices;
1673
2039
  }, [pivotResult, sortTarget, sortDirection]);
1674
- const copySelectionToClipboard = useCallback8(() => {
2040
+ const copySelectionToClipboard = useCallback9(() => {
1675
2041
  if (!selectionBounds || !pivotResult) return;
1676
2042
  const { minRow, maxRow, minCol, maxCol } = selectionBounds;
1677
2043
  const lines = [];
@@ -1695,7 +2061,7 @@ function PivotSkeleton({
1695
2061
  console.error("Copy failed:", err);
1696
2062
  });
1697
2063
  }, [selectionBounds, pivotResult, sortedRowIndices]);
1698
- useEffect5(() => {
2064
+ useEffect6(() => {
1699
2065
  const handleKeydown = (event) => {
1700
2066
  if (!selectionBounds) return;
1701
2067
  if ((event.ctrlKey || event.metaKey) && event.key === "c") {
@@ -1712,7 +2078,7 @@ function PivotSkeleton({
1712
2078
  document.addEventListener("keydown", handleKeydown);
1713
2079
  return () => document.removeEventListener("keydown", handleKeydown);
1714
2080
  }, [selectionBounds, copySelectionToClipboard]);
1715
- const selectionStats = useMemo8(() => {
2081
+ const selectionStats = useMemo9(() => {
1716
2082
  if (!selectionBounds || !pivotResult) return null;
1717
2083
  const { minRow, maxRow, minCol, maxCol } = selectionBounds;
1718
2084
  const values = [];
@@ -1738,12 +2104,12 @@ function PivotSkeleton({
1738
2104
  avg
1739
2105
  };
1740
2106
  }, [selectionBounds, pivotResult, sortedRowIndices]);
1741
- const formatStatValue = useCallback8((val) => {
2107
+ const formatStatValue = useCallback9((val) => {
1742
2108
  if (Math.abs(val) >= 1e6) return `${(val / 1e6).toFixed(2)}M`;
1743
2109
  if (Math.abs(val) >= 1e3) return `${(val / 1e3).toFixed(2)}K`;
1744
2110
  return val.toFixed(2);
1745
2111
  }, []);
1746
- const columnHeaderCells = useMemo8(() => {
2112
+ const columnHeaderCells = useMemo9(() => {
1747
2113
  if (!pivotResult || pivotResult.headers.length === 0) {
1748
2114
  return [
1749
2115
  valueFields.map((vf) => ({
@@ -1771,12 +2137,12 @@ function PivotSkeleton({
1771
2137
  return result;
1772
2138
  }, [pivotResult, valueFields]);
1773
2139
  const hasActiveFilters = activeFilters && activeFilters.length > 0;
1774
- const filterSummary = useMemo8(() => {
2140
+ const filterSummary = useMemo9(() => {
1775
2141
  if (!activeFilters || activeFilters.length === 0) return "";
1776
2142
  return activeFilters.map((f) => f.column).join(", ");
1777
2143
  }, [activeFilters]);
1778
- const [showFilterTooltip, setShowFilterTooltip] = useState8(false);
1779
- const filterTooltipDetails = useMemo8(() => {
2144
+ const [showFilterTooltip, setShowFilterTooltip] = useState9(false);
2145
+ const filterTooltipDetails = useMemo9(() => {
1780
2146
  if (!activeFilters || activeFilters.length === 0) return [];
1781
2147
  return activeFilters.map((f) => {
1782
2148
  const maxDisplay = 5;
@@ -1789,7 +2155,7 @@ function PivotSkeleton({
1789
2155
  };
1790
2156
  });
1791
2157
  }, [activeFilters]);
1792
- const handleDragOver = useCallback8(
2158
+ const handleDragOver = useCallback9(
1793
2159
  (area, event) => {
1794
2160
  event.preventDefault();
1795
2161
  event.dataTransfer.dropEffect = "move";
@@ -1797,10 +2163,10 @@ function PivotSkeleton({
1797
2163
  },
1798
2164
  []
1799
2165
  );
1800
- const handleDragLeave = useCallback8(() => {
2166
+ const handleDragLeave = useCallback9(() => {
1801
2167
  setDragOverArea(null);
1802
2168
  }, []);
1803
- const handleDrop = useCallback8(
2169
+ const handleDrop = useCallback9(
1804
2170
  (area, event) => {
1805
2171
  event.preventDefault();
1806
2172
  const field = event.dataTransfer?.getData("text/plain");
@@ -1827,7 +2193,7 @@ function PivotSkeleton({
1827
2193
  },
1828
2194
  [rowFields, columnFields, valueFields, onAddRowField, onRemoveRowField, onAddColumnField, onRemoveColumnField, onAddValueField, onRemoveValueField]
1829
2195
  );
1830
- const handleChipDragStart = useCallback8(
2196
+ const handleChipDragStart = useCallback9(
1831
2197
  (zone, index, event) => {
1832
2198
  setReorderDragSource({ zone, index });
1833
2199
  event.dataTransfer.effectAllowed = "move";
@@ -1838,11 +2204,11 @@ function PivotSkeleton({
1838
2204
  },
1839
2205
  []
1840
2206
  );
1841
- const handleChipDragEnd = useCallback8(() => {
2207
+ const handleChipDragEnd = useCallback9(() => {
1842
2208
  setReorderDragSource(null);
1843
2209
  setReorderDropTarget(null);
1844
2210
  }, []);
1845
- const handleChipDragOver = useCallback8(
2211
+ const handleChipDragOver = useCallback9(
1846
2212
  (zone, index, event) => {
1847
2213
  event.preventDefault();
1848
2214
  if (reorderDragSource && reorderDragSource.zone === zone) {
@@ -1852,10 +2218,10 @@ function PivotSkeleton({
1852
2218
  },
1853
2219
  [reorderDragSource]
1854
2220
  );
1855
- const handleChipDragLeave = useCallback8(() => {
2221
+ const handleChipDragLeave = useCallback9(() => {
1856
2222
  setReorderDropTarget(null);
1857
2223
  }, []);
1858
- const handleChipDrop = useCallback8(
2224
+ const handleChipDrop = useCallback9(
1859
2225
  (zone, targetIndex, event) => {
1860
2226
  event.preventDefault();
1861
2227
  event.stopPropagation();
@@ -1881,31 +2247,31 @@ function PivotSkeleton({
1881
2247
  },
1882
2248
  [reorderDragSource, rowFields, columnFields, onReorderRowFields, onReorderColumnFields]
1883
2249
  );
1884
- const isChipDragSource = useCallback8(
2250
+ const isChipDragSource = useCallback9(
1885
2251
  (zone, index) => {
1886
2252
  return reorderDragSource?.zone === zone && reorderDragSource?.index === index;
1887
2253
  },
1888
2254
  [reorderDragSource]
1889
2255
  );
1890
- const isChipDropTarget = useCallback8(
2256
+ const isChipDropTarget = useCallback9(
1891
2257
  (zone, index) => {
1892
2258
  return reorderDropTarget?.zone === zone && reorderDropTarget?.index === index;
1893
2259
  },
1894
2260
  [reorderDropTarget]
1895
2261
  );
1896
2262
  const currentFontSize = fontSize;
1897
- return /* @__PURE__ */ jsxs4(
2263
+ return /* @__PURE__ */ jsxs5(
1898
2264
  "div",
1899
2265
  {
1900
2266
  className: `vpg-pivot-skeleton vpg-font-${currentFontSize} ${draggingField ? "vpg-is-dragging" : ""}`,
1901
2267
  children: [
1902
- showCopyToast && /* @__PURE__ */ jsxs4("div", { className: "vpg-toast", children: [
1903
- /* @__PURE__ */ jsx4("svg", { className: "vpg-icon", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: /* @__PURE__ */ jsx4("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "M5 13l4 4L19 7" }) }),
2268
+ showCopyToast && /* @__PURE__ */ jsxs5("div", { className: "vpg-toast", children: [
2269
+ /* @__PURE__ */ jsx5("svg", { className: "vpg-icon", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: /* @__PURE__ */ jsx5("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "M5 13l4 4L19 7" }) }),
1904
2270
  copyToastMessage
1905
2271
  ] }),
1906
- /* @__PURE__ */ jsxs4("div", { className: "vpg-skeleton-header", children: [
1907
- /* @__PURE__ */ jsxs4("div", { className: "vpg-skeleton-title", children: [
1908
- /* @__PURE__ */ jsx4("svg", { className: "vpg-icon", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: /* @__PURE__ */ jsx4(
2272
+ /* @__PURE__ */ jsxs5("div", { className: "vpg-skeleton-header", children: [
2273
+ /* @__PURE__ */ jsxs5("div", { className: "vpg-skeleton-title", children: [
2274
+ /* @__PURE__ */ jsx5("svg", { className: "vpg-icon", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: /* @__PURE__ */ jsx5(
1909
2275
  "path",
1910
2276
  {
1911
2277
  strokeLinecap: "round",
@@ -1914,24 +2280,24 @@ function PivotSkeleton({
1914
2280
  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"
1915
2281
  }
1916
2282
  ) }),
1917
- /* @__PURE__ */ jsx4("span", { children: "Pivot Table" })
2283
+ /* @__PURE__ */ jsx5("span", { children: "Pivot Table" })
1918
2284
  ] }),
1919
- /* @__PURE__ */ jsxs4("div", { className: "vpg-header-right", children: [
1920
- hasActiveFilters && /* @__PURE__ */ jsxs4(
2285
+ /* @__PURE__ */ jsxs5("div", { className: "vpg-header-right", children: [
2286
+ hasActiveFilters && /* @__PURE__ */ jsxs5(
1921
2287
  "div",
1922
2288
  {
1923
2289
  className: "vpg-filter-indicator",
1924
2290
  onMouseEnter: () => setShowFilterTooltip(true),
1925
2291
  onMouseLeave: () => setShowFilterTooltip(false),
1926
2292
  children: [
1927
- /* @__PURE__ */ jsx4(
2293
+ /* @__PURE__ */ jsx5(
1928
2294
  "svg",
1929
2295
  {
1930
2296
  className: "vpg-filter-icon",
1931
2297
  fill: "none",
1932
2298
  stroke: "currentColor",
1933
2299
  viewBox: "0 0 24 24",
1934
- children: /* @__PURE__ */ jsx4(
2300
+ children: /* @__PURE__ */ jsx5(
1935
2301
  "path",
1936
2302
  {
1937
2303
  strokeLinecap: "round",
@@ -1942,10 +2308,10 @@ function PivotSkeleton({
1942
2308
  )
1943
2309
  }
1944
2310
  ),
1945
- /* @__PURE__ */ jsxs4("span", { className: "vpg-filter-text", children: [
2311
+ /* @__PURE__ */ jsxs5("span", { className: "vpg-filter-text", children: [
1946
2312
  "Filtered: ",
1947
- /* @__PURE__ */ jsx4("strong", { children: filterSummary }),
1948
- filteredRowCount !== void 0 && totalRowCount !== void 0 && /* @__PURE__ */ jsxs4("span", { className: "vpg-filter-count", children: [
2313
+ /* @__PURE__ */ jsx5("strong", { children: filterSummary }),
2314
+ filteredRowCount !== void 0 && totalRowCount !== void 0 && /* @__PURE__ */ jsxs5("span", { className: "vpg-filter-count", children: [
1949
2315
  "(",
1950
2316
  filteredRowCount.toLocaleString(),
1951
2317
  " of ",
@@ -1953,20 +2319,20 @@ function PivotSkeleton({
1953
2319
  " rows)"
1954
2320
  ] })
1955
2321
  ] }),
1956
- showFilterTooltip && /* @__PURE__ */ jsxs4("div", { className: "vpg-filter-tooltip", children: [
1957
- /* @__PURE__ */ jsx4("div", { className: "vpg-tooltip-header", children: "Active Filters" }),
1958
- filterTooltipDetails.map((filter) => /* @__PURE__ */ jsxs4("div", { className: "vpg-tooltip-filter", children: [
1959
- /* @__PURE__ */ jsx4("div", { className: "vpg-tooltip-column", children: filter.column }),
1960
- /* @__PURE__ */ jsxs4("div", { className: "vpg-tooltip-values", children: [
1961
- filter.values.map((val, idx) => /* @__PURE__ */ jsx4("span", { className: "vpg-tooltip-value", children: val }, idx)),
1962
- filter.remaining > 0 && /* @__PURE__ */ jsxs4("span", { className: "vpg-tooltip-more", children: [
2322
+ showFilterTooltip && /* @__PURE__ */ jsxs5("div", { className: "vpg-filter-tooltip", children: [
2323
+ /* @__PURE__ */ jsx5("div", { className: "vpg-tooltip-header", children: "Active Filters" }),
2324
+ filterTooltipDetails.map((filter) => /* @__PURE__ */ jsxs5("div", { className: "vpg-tooltip-filter", children: [
2325
+ /* @__PURE__ */ jsx5("div", { className: "vpg-tooltip-column", children: filter.column }),
2326
+ /* @__PURE__ */ jsxs5("div", { className: "vpg-tooltip-values", children: [
2327
+ filter.values.map((val, idx) => /* @__PURE__ */ jsx5("span", { className: "vpg-tooltip-value", children: val }, idx)),
2328
+ filter.remaining > 0 && /* @__PURE__ */ jsxs5("span", { className: "vpg-tooltip-more", children: [
1963
2329
  "+",
1964
2330
  filter.remaining,
1965
2331
  " more"
1966
2332
  ] })
1967
2333
  ] })
1968
2334
  ] }, filter.column)),
1969
- filteredRowCount !== void 0 && totalRowCount !== void 0 && /* @__PURE__ */ jsxs4("div", { className: "vpg-tooltip-summary", children: [
2335
+ filteredRowCount !== void 0 && totalRowCount !== void 0 && /* @__PURE__ */ jsxs5("div", { className: "vpg-tooltip-summary", children: [
1970
2336
  "Showing ",
1971
2337
  filteredRowCount.toLocaleString(),
1972
2338
  " of ",
@@ -1977,18 +2343,18 @@ function PivotSkeleton({
1977
2343
  ]
1978
2344
  }
1979
2345
  ),
1980
- isConfigured && /* @__PURE__ */ jsxs4("div", { className: "vpg-config-summary", children: [
1981
- /* @__PURE__ */ jsxs4("span", { className: "vpg-summary-badge vpg-rows", children: [
2346
+ isConfigured && /* @__PURE__ */ jsxs5("div", { className: "vpg-config-summary", children: [
2347
+ /* @__PURE__ */ jsxs5("span", { className: "vpg-summary-badge vpg-rows", children: [
1982
2348
  rowFields.length,
1983
2349
  " row",
1984
2350
  rowFields.length !== 1 ? "s" : ""
1985
2351
  ] }),
1986
- /* @__PURE__ */ jsxs4("span", { className: "vpg-summary-badge vpg-cols", children: [
2352
+ /* @__PURE__ */ jsxs5("span", { className: "vpg-summary-badge vpg-cols", children: [
1987
2353
  columnFields.length,
1988
2354
  " col",
1989
2355
  columnFields.length !== 1 ? "s" : ""
1990
2356
  ] }),
1991
- /* @__PURE__ */ jsxs4("span", { className: "vpg-summary-badge vpg-vals", children: [
2357
+ /* @__PURE__ */ jsxs5("span", { className: "vpg-summary-badge vpg-vals", children: [
1992
2358
  valueFields.length,
1993
2359
  " val",
1994
2360
  valueFields.length !== 1 ? "s" : ""
@@ -1996,8 +2362,8 @@ function PivotSkeleton({
1996
2362
  ] })
1997
2363
  ] })
1998
2364
  ] }),
1999
- !canUsePivot ? /* @__PURE__ */ jsx4("div", { className: "vpg-pro-required", children: /* @__PURE__ */ jsxs4("div", { className: "vpg-pro-content", children: [
2000
- /* @__PURE__ */ jsx4("svg", { className: "vpg-pro-icon", fill: "none", viewBox: "0 0 24 24", stroke: "currentColor", children: /* @__PURE__ */ jsx4(
2365
+ !canUsePivot ? /* @__PURE__ */ jsx5("div", { className: "vpg-pro-required", children: /* @__PURE__ */ jsxs5("div", { className: "vpg-pro-content", children: [
2366
+ /* @__PURE__ */ jsx5("svg", { className: "vpg-pro-icon", fill: "none", viewBox: "0 0 24 24", stroke: "currentColor", children: /* @__PURE__ */ jsx5(
2001
2367
  "path",
2002
2368
  {
2003
2369
  strokeLinecap: "round",
@@ -2006,12 +2372,12 @@ function PivotSkeleton({
2006
2372
  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"
2007
2373
  }
2008
2374
  ) }),
2009
- /* @__PURE__ */ jsx4("h3", { children: "Pro Feature" }),
2010
- /* @__PURE__ */ jsx4("p", { children: "Pivot Table functionality requires a Pro license." }),
2011
- /* @__PURE__ */ jsx4("a", { href: "https://tiny-pivot.com/#pricing", target: "_blank", rel: "noopener noreferrer", className: "vpg-pro-link", children: "Get Pro License \u2192" })
2012
- ] }) }) : /* @__PURE__ */ jsxs4(Fragment2, { children: [
2013
- /* @__PURE__ */ jsxs4("div", { className: "vpg-config-bar", children: [
2014
- /* @__PURE__ */ jsxs4(
2375
+ /* @__PURE__ */ jsx5("h3", { children: "Pro Feature" }),
2376
+ /* @__PURE__ */ jsx5("p", { children: "Pivot Table functionality requires a Pro license." }),
2377
+ /* @__PURE__ */ jsx5("a", { href: "https://tiny-pivot.com/#pricing", target: "_blank", rel: "noopener noreferrer", className: "vpg-pro-link", children: "Get Pro License \u2192" })
2378
+ ] }) }) : /* @__PURE__ */ jsxs5(Fragment3, { children: [
2379
+ /* @__PURE__ */ jsxs5("div", { className: "vpg-config-bar", children: [
2380
+ /* @__PURE__ */ jsxs5(
2015
2381
  "div",
2016
2382
  {
2017
2383
  className: `vpg-drop-zone vpg-row-zone ${dragOverArea === "row" ? "vpg-drag-over" : ""}`,
@@ -2019,12 +2385,12 @@ function PivotSkeleton({
2019
2385
  onDragLeave: handleDragLeave,
2020
2386
  onDrop: (e) => handleDrop("row", e),
2021
2387
  children: [
2022
- /* @__PURE__ */ jsxs4("div", { className: "vpg-zone-header", children: [
2023
- /* @__PURE__ */ jsx4("span", { className: "vpg-zone-icon vpg-row-icon", children: "\u2193" }),
2024
- /* @__PURE__ */ jsx4("span", { className: "vpg-zone-label", children: "Rows" })
2388
+ /* @__PURE__ */ jsxs5("div", { className: "vpg-zone-header", children: [
2389
+ /* @__PURE__ */ jsx5("span", { className: "vpg-zone-icon vpg-row-icon", children: "\u2193" }),
2390
+ /* @__PURE__ */ jsx5("span", { className: "vpg-zone-label", children: "Rows" })
2025
2391
  ] }),
2026
- /* @__PURE__ */ jsxs4("div", { className: "vpg-zone-chips", children: [
2027
- rowFields.map((field, idx) => /* @__PURE__ */ jsxs4(
2392
+ /* @__PURE__ */ jsxs5("div", { className: "vpg-zone-chips", children: [
2393
+ rowFields.map((field, idx) => /* @__PURE__ */ jsxs5(
2028
2394
  "div",
2029
2395
  {
2030
2396
  className: `vpg-mini-chip vpg-row-chip ${isChipDragSource("row", idx) ? "vpg-chip-dragging" : ""} ${isChipDropTarget("row", idx) ? "vpg-chip-drop-target" : ""}`,
@@ -2035,9 +2401,9 @@ function PivotSkeleton({
2035
2401
  onDragLeave: handleChipDragLeave,
2036
2402
  onDrop: (e) => handleChipDrop("row", idx, e),
2037
2403
  children: [
2038
- /* @__PURE__ */ jsx4("span", { className: "vpg-drag-handle", children: "\u22EE\u22EE" }),
2039
- /* @__PURE__ */ jsx4("span", { className: "vpg-mini-name", children: field }),
2040
- /* @__PURE__ */ jsx4(
2404
+ /* @__PURE__ */ jsx5("span", { className: "vpg-drag-handle", children: "\u22EE\u22EE" }),
2405
+ /* @__PURE__ */ jsx5("span", { className: "vpg-mini-name", children: field }),
2406
+ /* @__PURE__ */ jsx5(
2041
2407
  "button",
2042
2408
  {
2043
2409
  className: "vpg-mini-remove",
@@ -2052,12 +2418,12 @@ function PivotSkeleton({
2052
2418
  },
2053
2419
  field
2054
2420
  )),
2055
- rowFields.length === 0 && /* @__PURE__ */ jsx4("span", { className: "vpg-zone-hint", children: "Drop here" })
2421
+ rowFields.length === 0 && /* @__PURE__ */ jsx5("span", { className: "vpg-zone-hint", children: "Drop here" })
2056
2422
  ] })
2057
2423
  ]
2058
2424
  }
2059
2425
  ),
2060
- /* @__PURE__ */ jsxs4(
2426
+ /* @__PURE__ */ jsxs5(
2061
2427
  "div",
2062
2428
  {
2063
2429
  className: `vpg-drop-zone vpg-column-zone ${dragOverArea === "column" ? "vpg-drag-over" : ""}`,
@@ -2065,12 +2431,12 @@ function PivotSkeleton({
2065
2431
  onDragLeave: handleDragLeave,
2066
2432
  onDrop: (e) => handleDrop("column", e),
2067
2433
  children: [
2068
- /* @__PURE__ */ jsxs4("div", { className: "vpg-zone-header", children: [
2069
- /* @__PURE__ */ jsx4("span", { className: "vpg-zone-icon vpg-column-icon", children: "\u2192" }),
2070
- /* @__PURE__ */ jsx4("span", { className: "vpg-zone-label", children: "Columns" })
2434
+ /* @__PURE__ */ jsxs5("div", { className: "vpg-zone-header", children: [
2435
+ /* @__PURE__ */ jsx5("span", { className: "vpg-zone-icon vpg-column-icon", children: "\u2192" }),
2436
+ /* @__PURE__ */ jsx5("span", { className: "vpg-zone-label", children: "Columns" })
2071
2437
  ] }),
2072
- /* @__PURE__ */ jsxs4("div", { className: "vpg-zone-chips", children: [
2073
- columnFields.map((field, idx) => /* @__PURE__ */ jsxs4(
2438
+ /* @__PURE__ */ jsxs5("div", { className: "vpg-zone-chips", children: [
2439
+ columnFields.map((field, idx) => /* @__PURE__ */ jsxs5(
2074
2440
  "div",
2075
2441
  {
2076
2442
  className: `vpg-mini-chip vpg-column-chip ${isChipDragSource("column", idx) ? "vpg-chip-dragging" : ""} ${isChipDropTarget("column", idx) ? "vpg-chip-drop-target" : ""}`,
@@ -2081,9 +2447,9 @@ function PivotSkeleton({
2081
2447
  onDragLeave: handleChipDragLeave,
2082
2448
  onDrop: (e) => handleChipDrop("column", idx, e),
2083
2449
  children: [
2084
- /* @__PURE__ */ jsx4("span", { className: "vpg-drag-handle", children: "\u22EE\u22EE" }),
2085
- /* @__PURE__ */ jsx4("span", { className: "vpg-mini-name", children: field }),
2086
- /* @__PURE__ */ jsx4(
2450
+ /* @__PURE__ */ jsx5("span", { className: "vpg-drag-handle", children: "\u22EE\u22EE" }),
2451
+ /* @__PURE__ */ jsx5("span", { className: "vpg-mini-name", children: field }),
2452
+ /* @__PURE__ */ jsx5(
2087
2453
  "button",
2088
2454
  {
2089
2455
  className: "vpg-mini-remove",
@@ -2098,12 +2464,12 @@ function PivotSkeleton({
2098
2464
  },
2099
2465
  field
2100
2466
  )),
2101
- columnFields.length === 0 && /* @__PURE__ */ jsx4("span", { className: "vpg-zone-hint", children: "Drop here" })
2467
+ columnFields.length === 0 && /* @__PURE__ */ jsx5("span", { className: "vpg-zone-hint", children: "Drop here" })
2102
2468
  ] })
2103
2469
  ]
2104
2470
  }
2105
2471
  ),
2106
- /* @__PURE__ */ jsxs4(
2472
+ /* @__PURE__ */ jsxs5(
2107
2473
  "div",
2108
2474
  {
2109
2475
  className: `vpg-drop-zone vpg-value-zone ${dragOverArea === "value" ? "vpg-drag-over" : ""}`,
@@ -2111,19 +2477,19 @@ function PivotSkeleton({
2111
2477
  onDragLeave: handleDragLeave,
2112
2478
  onDrop: (e) => handleDrop("value", e),
2113
2479
  children: [
2114
- /* @__PURE__ */ jsxs4("div", { className: "vpg-zone-header", children: [
2115
- /* @__PURE__ */ jsx4("span", { className: "vpg-zone-icon vpg-value-icon", children: "\u03A3" }),
2116
- /* @__PURE__ */ jsx4("span", { className: "vpg-zone-label", children: "Values" })
2480
+ /* @__PURE__ */ jsxs5("div", { className: "vpg-zone-header", children: [
2481
+ /* @__PURE__ */ jsx5("span", { className: "vpg-zone-icon vpg-value-icon", children: "\u03A3" }),
2482
+ /* @__PURE__ */ jsx5("span", { className: "vpg-zone-label", children: "Values" })
2117
2483
  ] }),
2118
- /* @__PURE__ */ jsxs4("div", { className: "vpg-zone-chips", children: [
2119
- valueFields.map((vf) => /* @__PURE__ */ jsxs4(
2484
+ /* @__PURE__ */ jsxs5("div", { className: "vpg-zone-chips", children: [
2485
+ valueFields.map((vf) => /* @__PURE__ */ jsxs5(
2120
2486
  "div",
2121
2487
  {
2122
2488
  className: `vpg-mini-chip vpg-value-chip${isCalculatedField(vf.field) ? " vpg-calc-chip" : ""}`,
2123
2489
  children: [
2124
- /* @__PURE__ */ jsx4("span", { className: "vpg-agg-symbol", children: isCalculatedField(vf.field) ? "\u0192" : getAggregationSymbol2(vf.aggregation) }),
2125
- /* @__PURE__ */ jsx4("span", { className: "vpg-mini-name", children: getValueFieldDisplayName(vf.field) }),
2126
- /* @__PURE__ */ jsx4(
2490
+ /* @__PURE__ */ jsx5("span", { className: "vpg-agg-symbol", children: isCalculatedField(vf.field) ? "\u0192" : getAggregationSymbol2(vf.aggregation) }),
2491
+ /* @__PURE__ */ jsx5("span", { className: "vpg-mini-name", children: getValueFieldDisplayName(vf.field) }),
2492
+ /* @__PURE__ */ jsx5(
2127
2493
  "button",
2128
2494
  {
2129
2495
  className: "vpg-mini-remove",
@@ -2135,21 +2501,21 @@ function PivotSkeleton({
2135
2501
  },
2136
2502
  `${vf.field}-${vf.aggregation}`
2137
2503
  )),
2138
- valueFields.length === 0 && /* @__PURE__ */ jsx4("span", { className: "vpg-zone-hint", children: "Drop numeric" })
2504
+ valueFields.length === 0 && /* @__PURE__ */ jsx5("span", { className: "vpg-zone-hint", children: "Drop numeric" })
2139
2505
  ] })
2140
2506
  ]
2141
2507
  }
2142
2508
  )
2143
2509
  ] }),
2144
- (!isConfigured || !pivotResult) && /* @__PURE__ */ jsx4("div", { className: "vpg-placeholder", children: /* @__PURE__ */ jsxs4("div", { className: "vpg-placeholder-content", children: [
2145
- /* @__PURE__ */ jsx4(
2510
+ (!isConfigured || !pivotResult) && /* @__PURE__ */ jsx5("div", { className: "vpg-placeholder", children: /* @__PURE__ */ jsxs5("div", { className: "vpg-placeholder-content", children: [
2511
+ /* @__PURE__ */ jsx5(
2146
2512
  "svg",
2147
2513
  {
2148
2514
  className: "vpg-placeholder-icon",
2149
2515
  fill: "none",
2150
2516
  viewBox: "0 0 24 24",
2151
2517
  stroke: "currentColor",
2152
- children: /* @__PURE__ */ jsx4(
2518
+ children: /* @__PURE__ */ jsx5(
2153
2519
  "path",
2154
2520
  {
2155
2521
  strokeLinecap: "round",
@@ -2160,53 +2526,53 @@ function PivotSkeleton({
2160
2526
  )
2161
2527
  }
2162
2528
  ),
2163
- /* @__PURE__ */ jsx4("span", { className: "vpg-placeholder-text", children: valueFields.length === 0 ? /* @__PURE__ */ jsxs4(Fragment2, { children: [
2529
+ /* @__PURE__ */ jsx5("span", { className: "vpg-placeholder-text", children: valueFields.length === 0 ? /* @__PURE__ */ jsxs5(Fragment3, { children: [
2164
2530
  "Add a ",
2165
- /* @__PURE__ */ jsx4("strong", { children: "Values" }),
2531
+ /* @__PURE__ */ jsx5("strong", { children: "Values" }),
2166
2532
  " field to see your pivot table"
2167
- ] }) : rowFields.length === 0 && columnFields.length === 0 ? /* @__PURE__ */ jsxs4(Fragment2, { children: [
2533
+ ] }) : rowFields.length === 0 && columnFields.length === 0 ? /* @__PURE__ */ jsxs5(Fragment3, { children: [
2168
2534
  "Add ",
2169
- /* @__PURE__ */ jsx4("strong", { children: "Row" }),
2535
+ /* @__PURE__ */ jsx5("strong", { children: "Row" }),
2170
2536
  " or ",
2171
- /* @__PURE__ */ jsx4("strong", { children: "Column" }),
2537
+ /* @__PURE__ */ jsx5("strong", { children: "Column" }),
2172
2538
  " fields to group your data"
2173
2539
  ] }) : "Your pivot table will appear here" })
2174
2540
  ] }) }),
2175
- isConfigured && pivotResult && /* @__PURE__ */ jsx4("div", { className: "vpg-table-container", children: /* @__PURE__ */ jsxs4("table", { className: "vpg-pivot-table", children: [
2176
- /* @__PURE__ */ jsx4("thead", { children: columnHeaderCells.map((headerRow, levelIdx) => /* @__PURE__ */ jsxs4("tr", { className: "vpg-column-header-row", children: [
2177
- levelIdx === 0 && /* @__PURE__ */ jsx4(
2541
+ isConfigured && pivotResult && /* @__PURE__ */ jsx5("div", { className: "vpg-table-container", children: /* @__PURE__ */ jsxs5("table", { className: "vpg-pivot-table", children: [
2542
+ /* @__PURE__ */ jsx5("thead", { children: columnHeaderCells.map((headerRow, levelIdx) => /* @__PURE__ */ jsxs5("tr", { className: "vpg-column-header-row", children: [
2543
+ levelIdx === 0 && /* @__PURE__ */ jsx5(
2178
2544
  "th",
2179
2545
  {
2180
2546
  className: "vpg-row-header-label",
2181
2547
  rowSpan: columnHeaderCells.length,
2182
2548
  onClick: () => toggleSort("row"),
2183
- children: /* @__PURE__ */ jsxs4("div", { className: "vpg-header-content", children: [
2184
- /* @__PURE__ */ jsx4("span", { children: rowFields.join(" / ") || "Rows" }),
2185
- /* @__PURE__ */ jsx4("span", { className: `vpg-sort-indicator ${sortTarget === "row" ? "active" : ""}`, children: sortTarget === "row" ? sortDirection === "asc" ? "\u2191" : "\u2193" : "\u21C5" })
2549
+ children: /* @__PURE__ */ jsxs5("div", { className: "vpg-header-content", children: [
2550
+ /* @__PURE__ */ jsx5("span", { children: rowFields.join(" / ") || "Rows" }),
2551
+ /* @__PURE__ */ jsx5("span", { className: `vpg-sort-indicator ${sortTarget === "row" ? "active" : ""}`, children: sortTarget === "row" ? sortDirection === "asc" ? "\u2191" : "\u2193" : "\u21C5" })
2186
2552
  ] })
2187
2553
  }
2188
2554
  ),
2189
- headerRow.map((cell, idx) => /* @__PURE__ */ jsx4(
2555
+ headerRow.map((cell, idx) => /* @__PURE__ */ jsx5(
2190
2556
  "th",
2191
2557
  {
2192
2558
  className: "vpg-column-header-cell",
2193
2559
  colSpan: cell.colspan,
2194
2560
  onClick: () => levelIdx === columnHeaderCells.length - 1 && toggleSort(idx),
2195
- children: /* @__PURE__ */ jsxs4("div", { className: "vpg-header-content", children: [
2196
- /* @__PURE__ */ jsx4("span", { children: cell.label }),
2197
- levelIdx === columnHeaderCells.length - 1 && /* @__PURE__ */ jsx4("span", { className: `vpg-sort-indicator ${sortTarget === idx ? "active" : ""}`, children: sortTarget === idx ? sortDirection === "asc" ? "\u2191" : "\u2193" : "\u21C5" })
2561
+ children: /* @__PURE__ */ jsxs5("div", { className: "vpg-header-content", children: [
2562
+ /* @__PURE__ */ jsx5("span", { children: cell.label }),
2563
+ levelIdx === columnHeaderCells.length - 1 && /* @__PURE__ */ jsx5("span", { className: `vpg-sort-indicator ${sortTarget === idx ? "active" : ""}`, children: sortTarget === idx ? sortDirection === "asc" ? "\u2191" : "\u2193" : "\u21C5" })
2198
2564
  ] })
2199
2565
  },
2200
2566
  idx
2201
2567
  )),
2202
- pivotResult.rowTotals.length > 0 && levelIdx === 0 && /* @__PURE__ */ jsx4("th", { className: "vpg-total-header", rowSpan: columnHeaderCells.length, children: "Total" })
2568
+ pivotResult.rowTotals.length > 0 && levelIdx === 0 && /* @__PURE__ */ jsx5("th", { className: "vpg-total-header", rowSpan: columnHeaderCells.length, children: "Total" })
2203
2569
  ] }, `header-${levelIdx}`)) }),
2204
- /* @__PURE__ */ jsxs4("tbody", { children: [
2205
- sortedRowIndices.map((sortedIdx) => /* @__PURE__ */ jsxs4("tr", { className: "vpg-data-row", children: [
2206
- /* @__PURE__ */ jsx4("th", { className: "vpg-row-header-cell", children: pivotResult.rowHeaders[sortedIdx].map((val, idx) => /* @__PURE__ */ jsx4("span", { className: "vpg-row-value", children: val }, idx)) }),
2570
+ /* @__PURE__ */ jsxs5("tbody", { children: [
2571
+ sortedRowIndices.map((sortedIdx) => /* @__PURE__ */ jsxs5("tr", { className: "vpg-data-row", children: [
2572
+ /* @__PURE__ */ jsx5("th", { className: "vpg-row-header-cell", children: pivotResult.rowHeaders[sortedIdx].map((val, idx) => /* @__PURE__ */ jsx5("span", { className: "vpg-row-value", children: val }, idx)) }),
2207
2573
  pivotResult.data[sortedIdx].map((cell, colIdx) => {
2208
2574
  const displayRowIdx = sortedRowIndices.indexOf(sortedIdx);
2209
- return /* @__PURE__ */ jsx4(
2575
+ return /* @__PURE__ */ jsx5(
2210
2576
  "td",
2211
2577
  {
2212
2578
  className: `vpg-data-cell ${isCellSelected(displayRowIdx, colIdx) ? "selected" : ""} ${cell.value === null ? "vpg-is-null" : ""}`,
@@ -2217,46 +2583,46 @@ function PivotSkeleton({
2217
2583
  colIdx
2218
2584
  );
2219
2585
  }),
2220
- pivotResult.rowTotals[sortedIdx] && /* @__PURE__ */ jsx4("td", { className: "vpg-data-cell vpg-total-cell", children: pivotResult.rowTotals[sortedIdx].formattedValue })
2586
+ pivotResult.rowTotals[sortedIdx] && /* @__PURE__ */ jsx5("td", { className: "vpg-data-cell vpg-total-cell", children: pivotResult.rowTotals[sortedIdx].formattedValue })
2221
2587
  ] }, sortedIdx)),
2222
- pivotResult.columnTotals.length > 0 && /* @__PURE__ */ jsxs4("tr", { className: "vpg-totals-row", children: [
2223
- /* @__PURE__ */ jsx4("th", { className: "vpg-row-header-cell vpg-total-label", children: "Total" }),
2224
- pivotResult.columnTotals.map((cell, colIdx) => /* @__PURE__ */ jsx4("td", { className: "vpg-data-cell vpg-total-cell", children: cell.formattedValue }, colIdx)),
2225
- pivotResult.rowTotals.length > 0 && /* @__PURE__ */ jsx4("td", { className: "vpg-data-cell vpg-grand-total-cell", children: pivotResult.grandTotal.formattedValue })
2588
+ pivotResult.columnTotals.length > 0 && /* @__PURE__ */ jsxs5("tr", { className: "vpg-totals-row", children: [
2589
+ /* @__PURE__ */ jsx5("th", { className: "vpg-row-header-cell vpg-total-label", children: "Total" }),
2590
+ pivotResult.columnTotals.map((cell, colIdx) => /* @__PURE__ */ jsx5("td", { className: "vpg-data-cell vpg-total-cell", children: cell.formattedValue }, colIdx)),
2591
+ pivotResult.rowTotals.length > 0 && /* @__PURE__ */ jsx5("td", { className: "vpg-data-cell vpg-grand-total-cell", children: pivotResult.grandTotal.formattedValue })
2226
2592
  ] })
2227
2593
  ] })
2228
2594
  ] }) }),
2229
- isConfigured && pivotResult && /* @__PURE__ */ jsxs4("div", { className: "vpg-skeleton-footer", children: [
2230
- /* @__PURE__ */ jsxs4("span", { className: "vpg-footer-info", children: [
2595
+ isConfigured && pivotResult && /* @__PURE__ */ jsxs5("div", { className: "vpg-skeleton-footer", children: [
2596
+ /* @__PURE__ */ jsxs5("span", { className: "vpg-footer-info", children: [
2231
2597
  pivotResult.rowHeaders.length,
2232
2598
  " rows \xD7 ",
2233
2599
  pivotResult.data[0]?.length || 0,
2234
2600
  " columns"
2235
2601
  ] }),
2236
- selectionStats && selectionStats.count > 1 && /* @__PURE__ */ jsxs4("div", { className: "vpg-selection-stats", children: [
2237
- /* @__PURE__ */ jsxs4("span", { className: "vpg-stat", children: [
2238
- /* @__PURE__ */ jsx4("span", { className: "vpg-stat-label", children: "Count:" }),
2239
- /* @__PURE__ */ jsx4("span", { className: "vpg-stat-value", children: selectionStats.count })
2602
+ selectionStats && selectionStats.count > 1 && /* @__PURE__ */ jsxs5("div", { className: "vpg-selection-stats", children: [
2603
+ /* @__PURE__ */ jsxs5("span", { className: "vpg-stat", children: [
2604
+ /* @__PURE__ */ jsx5("span", { className: "vpg-stat-label", children: "Count:" }),
2605
+ /* @__PURE__ */ jsx5("span", { className: "vpg-stat-value", children: selectionStats.count })
2240
2606
  ] }),
2241
- selectionStats.numericCount > 0 && /* @__PURE__ */ jsxs4(Fragment2, { children: [
2242
- /* @__PURE__ */ jsx4("span", { className: "vpg-stat-divider", children: "|" }),
2243
- /* @__PURE__ */ jsxs4("span", { className: "vpg-stat", children: [
2244
- /* @__PURE__ */ jsx4("span", { className: "vpg-stat-label", children: "Sum:" }),
2245
- /* @__PURE__ */ jsx4("span", { className: "vpg-stat-value", children: formatStatValue(selectionStats.sum) })
2607
+ selectionStats.numericCount > 0 && /* @__PURE__ */ jsxs5(Fragment3, { children: [
2608
+ /* @__PURE__ */ jsx5("span", { className: "vpg-stat-divider", children: "|" }),
2609
+ /* @__PURE__ */ jsxs5("span", { className: "vpg-stat", children: [
2610
+ /* @__PURE__ */ jsx5("span", { className: "vpg-stat-label", children: "Sum:" }),
2611
+ /* @__PURE__ */ jsx5("span", { className: "vpg-stat-value", children: formatStatValue(selectionStats.sum) })
2246
2612
  ] }),
2247
- /* @__PURE__ */ jsx4("span", { className: "vpg-stat-divider", children: "|" }),
2248
- /* @__PURE__ */ jsxs4("span", { className: "vpg-stat", children: [
2249
- /* @__PURE__ */ jsx4("span", { className: "vpg-stat-label", children: "Avg:" }),
2250
- /* @__PURE__ */ jsx4("span", { className: "vpg-stat-value", children: formatStatValue(selectionStats.avg) })
2613
+ /* @__PURE__ */ jsx5("span", { className: "vpg-stat-divider", children: "|" }),
2614
+ /* @__PURE__ */ jsxs5("span", { className: "vpg-stat", children: [
2615
+ /* @__PURE__ */ jsx5("span", { className: "vpg-stat-label", children: "Avg:" }),
2616
+ /* @__PURE__ */ jsx5("span", { className: "vpg-stat-value", children: formatStatValue(selectionStats.avg) })
2251
2617
  ] })
2252
2618
  ] })
2253
2619
  ] })
2254
2620
  ] })
2255
2621
  ] }),
2256
- showWatermark && canUsePivot && /* @__PURE__ */ jsx4("div", { className: `vpg-watermark ${isDemo ? "vpg-demo-mode" : ""}`, children: isDemo ? /* @__PURE__ */ jsxs4(Fragment2, { children: [
2257
- /* @__PURE__ */ jsx4("span", { className: "vpg-demo-badge", children: "DEMO" }),
2258
- /* @__PURE__ */ jsx4("span", { children: "Pro features unlocked for evaluation" }),
2259
- /* @__PURE__ */ jsx4(
2622
+ showWatermark && canUsePivot && /* @__PURE__ */ jsx5("div", { className: `vpg-watermark ${isDemo ? "vpg-demo-mode" : ""}`, children: isDemo ? /* @__PURE__ */ jsxs5(Fragment3, { children: [
2623
+ /* @__PURE__ */ jsx5("span", { className: "vpg-demo-badge", children: "DEMO" }),
2624
+ /* @__PURE__ */ jsx5("span", { children: "Pro features unlocked for evaluation" }),
2625
+ /* @__PURE__ */ jsx5(
2260
2626
  "a",
2261
2627
  {
2262
2628
  href: "https://tiny-pivot.com/#pricing",
@@ -2266,14 +2632,14 @@ function PivotSkeleton({
2266
2632
  children: "Get Pro License \u2192"
2267
2633
  }
2268
2634
  )
2269
- ] }) : /* @__PURE__ */ jsx4("a", { href: "https://tiny-pivot.com", target: "_blank", rel: "noopener noreferrer", children: "Powered by TinyPivot" }) })
2635
+ ] }) : /* @__PURE__ */ jsx5("a", { href: "https://tiny-pivot.com", target: "_blank", rel: "noopener noreferrer", children: "Powered by TinyPivot" }) })
2270
2636
  ]
2271
2637
  }
2272
2638
  );
2273
2639
  }
2274
2640
 
2275
2641
  // src/components/DataGrid.tsx
2276
- import { Fragment as Fragment3, jsx as jsx5, jsxs as jsxs5 } from "react/jsx-runtime";
2642
+ import { Fragment as Fragment4, jsx as jsx6, jsxs as jsxs6 } from "react/jsx-runtime";
2277
2643
  var MIN_COL_WIDTH = 120;
2278
2644
  var MAX_COL_WIDTH = 350;
2279
2645
  function DataGrid({
@@ -2299,35 +2665,35 @@ function DataGrid({
2299
2665
  onCopy
2300
2666
  }) {
2301
2667
  const { showWatermark, canUsePivot, isDemo } = useLicense();
2302
- const currentTheme = useMemo9(() => {
2668
+ const currentTheme = useMemo10(() => {
2303
2669
  if (theme === "auto") {
2304
2670
  return window.matchMedia?.("(prefers-color-scheme: dark)").matches ? "dark" : "light";
2305
2671
  }
2306
2672
  return theme;
2307
2673
  }, [theme]);
2308
- const [currentFontSize, setCurrentFontSize] = useState9(initialFontSize);
2309
- const [globalSearchTerm, setGlobalSearchTerm] = useState9("");
2310
- const [showSearchInput, setShowSearchInput] = useState9(false);
2311
- const [currentPage, setCurrentPage] = useState9(1);
2312
- const [columnWidths, setColumnWidths] = useState9({});
2313
- const [resizingColumnId, setResizingColumnId] = useState9(null);
2314
- const [resizeStartX, setResizeStartX] = useState9(0);
2315
- const [resizeStartWidth, setResizeStartWidth] = useState9(0);
2316
- const [gridHeight, setGridHeight] = useState9(initialHeight);
2317
- const [isResizingVertically, setIsResizingVertically] = useState9(false);
2318
- const [verticalResizeStartY, setVerticalResizeStartY] = useState9(0);
2319
- const [verticalResizeStartHeight, setVerticalResizeStartHeight] = useState9(0);
2320
- const [showCopyToast, setShowCopyToast] = useState9(false);
2321
- const [copyToastMessage, setCopyToastMessage] = useState9("");
2322
- const [viewMode, setViewMode] = useState9("grid");
2323
- const [showPivotConfig, setShowPivotConfig] = useState9(true);
2324
- const [draggingField, setDraggingField] = useState9(null);
2325
- const [activeFilterColumn, setActiveFilterColumn] = useState9(null);
2326
- const [filterDropdownPosition, setFilterDropdownPosition] = useState9({ top: 0, left: 0, maxHeight: 400 });
2327
- const [selectedCell, setSelectedCell] = useState9(null);
2328
- const [selectionStart, setSelectionStart] = useState9(null);
2329
- const [selectionEnd, setSelectionEnd] = useState9(null);
2330
- const [isSelecting, setIsSelecting] = useState9(false);
2674
+ const [currentFontSize, setCurrentFontSize] = useState10(initialFontSize);
2675
+ const [globalSearchTerm, setGlobalSearchTerm] = useState10("");
2676
+ const [showSearchInput, setShowSearchInput] = useState10(false);
2677
+ const [currentPage, setCurrentPage] = useState10(1);
2678
+ const [columnWidths, setColumnWidths] = useState10({});
2679
+ const [resizingColumnId, setResizingColumnId] = useState10(null);
2680
+ const [resizeStartX, setResizeStartX] = useState10(0);
2681
+ const [resizeStartWidth, setResizeStartWidth] = useState10(0);
2682
+ const [gridHeight, setGridHeight] = useState10(initialHeight);
2683
+ const [isResizingVertically, setIsResizingVertically] = useState10(false);
2684
+ const [verticalResizeStartY, setVerticalResizeStartY] = useState10(0);
2685
+ const [verticalResizeStartHeight, setVerticalResizeStartHeight] = useState10(0);
2686
+ const [showCopyToast, setShowCopyToast] = useState10(false);
2687
+ const [copyToastMessage, setCopyToastMessage] = useState10("");
2688
+ const [viewMode, setViewMode] = useState10("grid");
2689
+ const [showPivotConfig, setShowPivotConfig] = useState10(true);
2690
+ const [draggingField, setDraggingField] = useState10(null);
2691
+ const [activeFilterColumn, setActiveFilterColumn] = useState10(null);
2692
+ const [filterDropdownPosition, setFilterDropdownPosition] = useState10({ top: 0, left: 0, maxHeight: 400 });
2693
+ const [selectedCell, setSelectedCell] = useState10(null);
2694
+ const [selectionStart, setSelectionStart] = useState10(null);
2695
+ const [selectionEnd, setSelectionEnd] = useState10(null);
2696
+ const [isSelecting, setIsSelecting] = useState10(false);
2331
2697
  const tableContainerRef = useRef2(null);
2332
2698
  const tableBodyRef = useRef2(null);
2333
2699
  const fontSizeOptions = [
@@ -2348,9 +2714,12 @@ function DataGrid({
2348
2714
  toggleSort,
2349
2715
  getSortDirection,
2350
2716
  columnFilters,
2351
- activeFilters
2717
+ activeFilters,
2718
+ // Numeric range filters
2719
+ setNumericRangeFilter,
2720
+ getNumericRangeFilter
2352
2721
  } = useExcelGrid({ data, enableSorting: true, enableFiltering: true });
2353
- const filteredDataForPivot = useMemo9(() => {
2722
+ const filteredDataForPivot = useMemo10(() => {
2354
2723
  const filteredRows = table.getFilteredRowModel().rows;
2355
2724
  return filteredRows.map((row) => row.original);
2356
2725
  }, [table, columnFilters]);
@@ -2380,7 +2749,7 @@ function DataGrid({
2380
2749
  addCalculatedField,
2381
2750
  removeCalculatedField
2382
2751
  } = usePivotTable(filteredDataForPivot);
2383
- const activeFilterInfo = useMemo9(() => {
2752
+ const activeFilterInfo = useMemo10(() => {
2384
2753
  if (activeFilters.length === 0) return null;
2385
2754
  return activeFilters.map((f) => ({
2386
2755
  column: f.column,
@@ -2388,8 +2757,8 @@ function DataGrid({
2388
2757
  values: f.values || []
2389
2758
  }));
2390
2759
  }, [activeFilters]);
2391
- const rows = useMemo9(() => table.getFilteredRowModel().rows, [table, columnFilters]);
2392
- const searchFilteredData = useMemo9(() => {
2760
+ const rows = useMemo10(() => table.getFilteredRowModel().rows, [table, columnFilters]);
2761
+ const searchFilteredData = useMemo10(() => {
2393
2762
  if (!globalSearchTerm.trim() || !enableSearch) {
2394
2763
  return rows;
2395
2764
  }
@@ -2406,20 +2775,20 @@ function DataGrid({
2406
2775
  });
2407
2776
  }, [rows, globalSearchTerm, enableSearch, columnKeys]);
2408
2777
  const totalSearchedRows = searchFilteredData.length;
2409
- const totalPages = useMemo9(() => {
2778
+ const totalPages = useMemo10(() => {
2410
2779
  if (!enablePagination) return 1;
2411
2780
  return Math.max(1, Math.ceil(totalSearchedRows / pageSize));
2412
2781
  }, [enablePagination, totalSearchedRows, pageSize]);
2413
- const paginatedRows = useMemo9(() => {
2782
+ const paginatedRows = useMemo10(() => {
2414
2783
  if (!enablePagination) return searchFilteredData;
2415
2784
  const start = (currentPage - 1) * pageSize;
2416
2785
  const end = start + pageSize;
2417
2786
  return searchFilteredData.slice(start, end);
2418
2787
  }, [enablePagination, searchFilteredData, currentPage, pageSize]);
2419
- useEffect6(() => {
2788
+ useEffect7(() => {
2420
2789
  setCurrentPage(1);
2421
2790
  }, [columnFilters, globalSearchTerm]);
2422
- const selectionBounds = useMemo9(() => {
2791
+ const selectionBounds = useMemo10(() => {
2423
2792
  if (!selectionStart || !selectionEnd) return null;
2424
2793
  return {
2425
2794
  minRow: Math.min(selectionStart.row, selectionEnd.row),
@@ -2428,7 +2797,7 @@ function DataGrid({
2428
2797
  maxCol: Math.max(selectionStart.col, selectionEnd.col)
2429
2798
  };
2430
2799
  }, [selectionStart, selectionEnd]);
2431
- const selectionStats = useMemo9(() => {
2800
+ const selectionStats = useMemo10(() => {
2432
2801
  if (!selectionBounds) return null;
2433
2802
  const { minRow, maxRow, minCol, maxCol } = selectionBounds;
2434
2803
  const values = [];
@@ -2454,7 +2823,7 @@ function DataGrid({
2454
2823
  const avg = sum / values.length;
2455
2824
  return { count, sum, avg, numericCount: values.length };
2456
2825
  }, [selectionBounds, rows, columnKeys]);
2457
- useEffect6(() => {
2826
+ useEffect7(() => {
2458
2827
  if (data.length === 0) return;
2459
2828
  const widths = {};
2460
2829
  const sampleSize = Math.min(100, data.length);
@@ -2474,7 +2843,7 @@ function DataGrid({
2474
2843
  }
2475
2844
  setColumnWidths(widths);
2476
2845
  }, [data, columnKeys]);
2477
- const startColumnResize = useCallback9(
2846
+ const startColumnResize = useCallback10(
2478
2847
  (columnId, event) => {
2479
2848
  if (!enableColumnResize) return;
2480
2849
  event.preventDefault();
@@ -2485,7 +2854,7 @@ function DataGrid({
2485
2854
  },
2486
2855
  [enableColumnResize, columnWidths]
2487
2856
  );
2488
- useEffect6(() => {
2857
+ useEffect7(() => {
2489
2858
  if (!resizingColumnId) return;
2490
2859
  const handleResizeMove = (event) => {
2491
2860
  const diff = event.clientX - resizeStartX;
@@ -2505,7 +2874,7 @@ function DataGrid({
2505
2874
  document.removeEventListener("mouseup", handleResizeEnd);
2506
2875
  };
2507
2876
  }, [resizingColumnId, resizeStartX, resizeStartWidth]);
2508
- const startVerticalResize = useCallback9(
2877
+ const startVerticalResize = useCallback10(
2509
2878
  (event) => {
2510
2879
  if (!enableVerticalResize) return;
2511
2880
  event.preventDefault();
@@ -2515,7 +2884,7 @@ function DataGrid({
2515
2884
  },
2516
2885
  [enableVerticalResize, gridHeight]
2517
2886
  );
2518
- useEffect6(() => {
2887
+ useEffect7(() => {
2519
2888
  if (!isResizingVertically) return;
2520
2889
  const handleVerticalResizeMove = (event) => {
2521
2890
  const diff = event.clientY - verticalResizeStartY;
@@ -2532,7 +2901,7 @@ function DataGrid({
2532
2901
  document.removeEventListener("mouseup", handleVerticalResizeEnd);
2533
2902
  };
2534
2903
  }, [isResizingVertically, verticalResizeStartY, verticalResizeStartHeight, minHeight, maxHeight]);
2535
- const handleExport = useCallback9(() => {
2904
+ const handleExport = useCallback10(() => {
2536
2905
  if (viewMode === "pivot") {
2537
2906
  if (!pivotResult) return;
2538
2907
  const pivotFilename = exportFilename.replace(".csv", "-pivot.csv");
@@ -2577,7 +2946,7 @@ function DataGrid({
2577
2946
  columnKeys,
2578
2947
  onExport
2579
2948
  ]);
2580
- const copySelectionToClipboard = useCallback9(() => {
2949
+ const copySelectionToClipboard = useCallback10(() => {
2581
2950
  if (!selectionBounds || !enableClipboard) return;
2582
2951
  const text = formatSelectionForClipboard(
2583
2952
  rows.map((r) => r.original),
@@ -2601,7 +2970,7 @@ function DataGrid({
2601
2970
  }
2602
2971
  );
2603
2972
  }, [selectionBounds, enableClipboard, rows, columnKeys, onCopy]);
2604
- const handleMouseDown = useCallback9(
2973
+ const handleMouseDown = useCallback10(
2605
2974
  (rowIndex, colIndex, event) => {
2606
2975
  event.preventDefault();
2607
2976
  if (event.shiftKey && selectedCell) {
@@ -2625,7 +2994,7 @@ function DataGrid({
2625
2994
  },
2626
2995
  [selectedCell, rows, columnKeys, onCellClick]
2627
2996
  );
2628
- const handleMouseEnter = useCallback9(
2997
+ const handleMouseEnter = useCallback10(
2629
2998
  (rowIndex, colIndex) => {
2630
2999
  if (isSelecting) {
2631
3000
  setSelectionEnd({ row: rowIndex, col: colIndex });
@@ -2633,12 +3002,12 @@ function DataGrid({
2633
3002
  },
2634
3003
  [isSelecting]
2635
3004
  );
2636
- useEffect6(() => {
3005
+ useEffect7(() => {
2637
3006
  const handleMouseUp = () => setIsSelecting(false);
2638
3007
  document.addEventListener("mouseup", handleMouseUp);
2639
3008
  return () => document.removeEventListener("mouseup", handleMouseUp);
2640
3009
  }, []);
2641
- useEffect6(() => {
3010
+ useEffect7(() => {
2642
3011
  const handleKeydown = (event) => {
2643
3012
  if ((event.ctrlKey || event.metaKey) && event.key === "c" && selectionBounds) {
2644
3013
  event.preventDefault();
@@ -2656,7 +3025,7 @@ function DataGrid({
2656
3025
  document.addEventListener("keydown", handleKeydown);
2657
3026
  return () => document.removeEventListener("keydown", handleKeydown);
2658
3027
  }, [selectionBounds, copySelectionToClipboard]);
2659
- const openFilterDropdown = useCallback9(
3028
+ const openFilterDropdown = useCallback10(
2660
3029
  (columnId, event) => {
2661
3030
  event.stopPropagation();
2662
3031
  const target = event.currentTarget;
@@ -2685,16 +3054,22 @@ function DataGrid({
2685
3054
  },
2686
3055
  []
2687
3056
  );
2688
- const closeFilterDropdown = useCallback9(() => {
3057
+ const closeFilterDropdown = useCallback10(() => {
2689
3058
  setActiveFilterColumn(null);
2690
3059
  }, []);
2691
- const handleFilter = useCallback9(
3060
+ const handleFilter = useCallback10(
2692
3061
  (columnId, values) => {
2693
3062
  setColumnFilter(columnId, values);
2694
3063
  },
2695
3064
  [setColumnFilter]
2696
3065
  );
2697
- const handleSort = useCallback9(
3066
+ const handleRangeFilter = useCallback10(
3067
+ (columnId, range) => {
3068
+ setNumericRangeFilter(columnId, range);
3069
+ },
3070
+ [setNumericRangeFilter]
3071
+ );
3072
+ const handleSort = useCallback10(
2698
3073
  (columnId, direction) => {
2699
3074
  if (direction === null) {
2700
3075
  const current = getSortDirection(columnId);
@@ -2718,7 +3093,7 @@ function DataGrid({
2718
3093
  },
2719
3094
  [getSortDirection, toggleSort]
2720
3095
  );
2721
- const isCellSelected = useCallback9(
3096
+ const isCellSelected = useCallback10(
2722
3097
  (rowIndex, colIndex) => {
2723
3098
  if (!selectionBounds) {
2724
3099
  return selectedCell?.row === rowIndex && selectedCell?.col === colIndex;
@@ -2756,30 +3131,30 @@ function DataGrid({
2756
3131
  }
2757
3132
  return String(value);
2758
3133
  };
2759
- const totalTableWidth = useMemo9(() => {
3134
+ const totalTableWidth = useMemo10(() => {
2760
3135
  return columnKeys.reduce((sum, key) => sum + (columnWidths[key] || MIN_COL_WIDTH), 0);
2761
3136
  }, [columnKeys, columnWidths]);
2762
3137
  const activeFilterCount = columnFilters.length;
2763
- return /* @__PURE__ */ jsxs5(
3138
+ return /* @__PURE__ */ jsxs6(
2764
3139
  "div",
2765
3140
  {
2766
3141
  className: `vpg-data-grid vpg-font-${currentFontSize} vpg-theme-${currentTheme} ${stripedRows ? "vpg-striped" : ""} ${resizingColumnId ? "vpg-resizing" : ""} ${isResizingVertically ? "vpg-resizing-vertical" : ""}`,
2767
3142
  style: { height: `${gridHeight}px` },
2768
3143
  children: [
2769
- showCopyToast && /* @__PURE__ */ jsxs5("div", { className: "vpg-toast", children: [
2770
- /* @__PURE__ */ jsx5("svg", { className: "vpg-icon", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: /* @__PURE__ */ jsx5("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "M5 13l4 4L19 7" }) }),
3144
+ showCopyToast && /* @__PURE__ */ jsxs6("div", { className: "vpg-toast", children: [
3145
+ /* @__PURE__ */ jsx6("svg", { className: "vpg-icon", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: /* @__PURE__ */ jsx6("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "M5 13l4 4L19 7" }) }),
2771
3146
  copyToastMessage
2772
3147
  ] }),
2773
- /* @__PURE__ */ jsxs5("div", { className: "vpg-toolbar", children: [
2774
- /* @__PURE__ */ jsxs5("div", { className: "vpg-toolbar-left", children: [
2775
- showPivot && /* @__PURE__ */ jsxs5("div", { className: "vpg-view-toggle", children: [
2776
- /* @__PURE__ */ jsxs5(
3148
+ /* @__PURE__ */ jsxs6("div", { className: "vpg-toolbar", children: [
3149
+ /* @__PURE__ */ jsxs6("div", { className: "vpg-toolbar-left", children: [
3150
+ showPivot && /* @__PURE__ */ jsxs6("div", { className: "vpg-view-toggle", children: [
3151
+ /* @__PURE__ */ jsxs6(
2777
3152
  "button",
2778
3153
  {
2779
3154
  className: `vpg-view-btn ${viewMode === "grid" ? "active" : ""}`,
2780
3155
  onClick: () => setViewMode("grid"),
2781
3156
  children: [
2782
- /* @__PURE__ */ jsx5("svg", { className: "vpg-icon", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: /* @__PURE__ */ jsx5(
3157
+ /* @__PURE__ */ jsx6("svg", { className: "vpg-icon", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: /* @__PURE__ */ jsx6(
2783
3158
  "path",
2784
3159
  {
2785
3160
  strokeLinecap: "round",
@@ -2792,13 +3167,13 @@ function DataGrid({
2792
3167
  ]
2793
3168
  }
2794
3169
  ),
2795
- /* @__PURE__ */ jsxs5(
3170
+ /* @__PURE__ */ jsxs6(
2796
3171
  "button",
2797
3172
  {
2798
3173
  className: `vpg-view-btn vpg-pivot-btn ${viewMode === "pivot" ? "active" : ""}`,
2799
3174
  onClick: () => setViewMode("pivot"),
2800
3175
  children: [
2801
- /* @__PURE__ */ jsx5("svg", { className: "vpg-icon", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: /* @__PURE__ */ jsx5(
3176
+ /* @__PURE__ */ jsx6("svg", { className: "vpg-icon", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: /* @__PURE__ */ jsx6(
2802
3177
  "path",
2803
3178
  {
2804
3179
  strokeLinecap: "round",
@@ -2812,14 +3187,14 @@ function DataGrid({
2812
3187
  }
2813
3188
  )
2814
3189
  ] }),
2815
- viewMode === "grid" && /* @__PURE__ */ jsxs5(Fragment3, { children: [
2816
- enableSearch && /* @__PURE__ */ jsx5("div", { className: "vpg-search-container", children: !showSearchInput ? /* @__PURE__ */ jsx5(
3190
+ viewMode === "grid" && /* @__PURE__ */ jsxs6(Fragment4, { children: [
3191
+ enableSearch && /* @__PURE__ */ jsx6("div", { className: "vpg-search-container", children: !showSearchInput ? /* @__PURE__ */ jsx6(
2817
3192
  "button",
2818
3193
  {
2819
3194
  className: "vpg-icon-btn",
2820
3195
  title: "Search (Ctrl+F)",
2821
3196
  onClick: () => setShowSearchInput(true),
2822
- children: /* @__PURE__ */ jsx5("svg", { className: "vpg-icon", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: /* @__PURE__ */ jsx5(
3197
+ children: /* @__PURE__ */ jsx6("svg", { className: "vpg-icon", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: /* @__PURE__ */ jsx6(
2823
3198
  "path",
2824
3199
  {
2825
3200
  strokeLinecap: "round",
@@ -2829,15 +3204,15 @@ function DataGrid({
2829
3204
  }
2830
3205
  ) })
2831
3206
  }
2832
- ) : /* @__PURE__ */ jsxs5("div", { className: "vpg-search-box", children: [
2833
- /* @__PURE__ */ jsx5(
3207
+ ) : /* @__PURE__ */ jsxs6("div", { className: "vpg-search-box", children: [
3208
+ /* @__PURE__ */ jsx6(
2834
3209
  "svg",
2835
3210
  {
2836
3211
  className: "vpg-search-icon",
2837
3212
  fill: "none",
2838
3213
  stroke: "currentColor",
2839
3214
  viewBox: "0 0 24 24",
2840
- children: /* @__PURE__ */ jsx5(
3215
+ children: /* @__PURE__ */ jsx6(
2841
3216
  "path",
2842
3217
  {
2843
3218
  strokeLinecap: "round",
@@ -2848,7 +3223,7 @@ function DataGrid({
2848
3223
  )
2849
3224
  }
2850
3225
  ),
2851
- /* @__PURE__ */ jsx5(
3226
+ /* @__PURE__ */ jsx6(
2852
3227
  "input",
2853
3228
  {
2854
3229
  type: "text",
@@ -2865,14 +3240,14 @@ function DataGrid({
2865
3240
  autoFocus: true
2866
3241
  }
2867
3242
  ),
2868
- globalSearchTerm && /* @__PURE__ */ jsx5("button", { className: "vpg-search-clear", onClick: () => setGlobalSearchTerm(""), children: /* @__PURE__ */ jsx5(
3243
+ globalSearchTerm && /* @__PURE__ */ jsx6("button", { className: "vpg-search-clear", onClick: () => setGlobalSearchTerm(""), children: /* @__PURE__ */ jsx6(
2869
3244
  "svg",
2870
3245
  {
2871
3246
  className: "vpg-icon-xs",
2872
3247
  fill: "none",
2873
3248
  stroke: "currentColor",
2874
3249
  viewBox: "0 0 24 24",
2875
- children: /* @__PURE__ */ jsx5(
3250
+ children: /* @__PURE__ */ jsx6(
2876
3251
  "path",
2877
3252
  {
2878
3253
  strokeLinecap: "round",
@@ -2884,9 +3259,9 @@ function DataGrid({
2884
3259
  }
2885
3260
  ) })
2886
3261
  ] }) }),
2887
- /* @__PURE__ */ jsxs5("div", { className: "vpg-font-size-control", children: [
2888
- /* @__PURE__ */ jsx5("span", { className: "vpg-label", children: "Size:" }),
2889
- /* @__PURE__ */ jsx5("div", { className: "vpg-font-size-toggle", children: fontSizeOptions.map((opt) => /* @__PURE__ */ jsx5(
3262
+ /* @__PURE__ */ jsxs6("div", { className: "vpg-font-size-control", children: [
3263
+ /* @__PURE__ */ jsx6("span", { className: "vpg-label", children: "Size:" }),
3264
+ /* @__PURE__ */ jsx6("div", { className: "vpg-font-size-toggle", children: fontSizeOptions.map((opt) => /* @__PURE__ */ jsx6(
2890
3265
  "button",
2891
3266
  {
2892
3267
  className: `vpg-font-size-btn ${currentFontSize === opt.value ? "active" : ""}`,
@@ -2896,8 +3271,8 @@ function DataGrid({
2896
3271
  opt.value
2897
3272
  )) })
2898
3273
  ] }),
2899
- activeFilterCount > 0 && /* @__PURE__ */ jsxs5("div", { className: "vpg-filter-info", children: [
2900
- /* @__PURE__ */ jsx5("svg", { className: "vpg-icon", fill: "currentColor", viewBox: "0 0 20 20", children: /* @__PURE__ */ jsx5(
3274
+ activeFilterCount > 0 && /* @__PURE__ */ jsxs6("div", { className: "vpg-filter-info", children: [
3275
+ /* @__PURE__ */ jsx6("svg", { className: "vpg-icon", fill: "currentColor", viewBox: "0 0 20 20", children: /* @__PURE__ */ jsx6(
2901
3276
  "path",
2902
3277
  {
2903
3278
  fillRule: "evenodd",
@@ -2905,26 +3280,26 @@ function DataGrid({
2905
3280
  clipRule: "evenodd"
2906
3281
  }
2907
3282
  ) }),
2908
- /* @__PURE__ */ jsxs5("span", { children: [
3283
+ /* @__PURE__ */ jsxs6("span", { children: [
2909
3284
  activeFilterCount,
2910
3285
  " filter",
2911
3286
  activeFilterCount > 1 ? "s" : ""
2912
3287
  ] })
2913
3288
  ] }),
2914
- globalSearchTerm && /* @__PURE__ */ jsx5("div", { className: "vpg-search-info", children: /* @__PURE__ */ jsxs5("span", { children: [
3289
+ globalSearchTerm && /* @__PURE__ */ jsx6("div", { className: "vpg-search-info", children: /* @__PURE__ */ jsxs6("span", { children: [
2915
3290
  totalSearchedRows,
2916
3291
  " match",
2917
3292
  totalSearchedRows !== 1 ? "es" : ""
2918
3293
  ] }) })
2919
3294
  ] }),
2920
- viewMode === "pivot" && canUsePivot && /* @__PURE__ */ jsxs5(Fragment3, { children: [
2921
- /* @__PURE__ */ jsxs5(
3295
+ viewMode === "pivot" && canUsePivot && /* @__PURE__ */ jsxs6(Fragment4, { children: [
3296
+ /* @__PURE__ */ jsxs6(
2922
3297
  "button",
2923
3298
  {
2924
3299
  className: `vpg-config-toggle ${showPivotConfig ? "active" : ""}`,
2925
3300
  onClick: () => setShowPivotConfig(!showPivotConfig),
2926
3301
  children: [
2927
- /* @__PURE__ */ jsx5("svg", { className: "vpg-icon", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: /* @__PURE__ */ jsx5(
3302
+ /* @__PURE__ */ jsx6("svg", { className: "vpg-icon", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: /* @__PURE__ */ jsx6(
2928
3303
  "path",
2929
3304
  {
2930
3305
  strokeLinecap: "round",
@@ -2938,8 +3313,8 @@ function DataGrid({
2938
3313
  ]
2939
3314
  }
2940
3315
  ),
2941
- pivotIsConfigured && /* @__PURE__ */ jsxs5("div", { className: "vpg-pivot-status", children: [
2942
- /* @__PURE__ */ jsx5("svg", { className: "vpg-icon", fill: "currentColor", viewBox: "0 0 20 20", children: /* @__PURE__ */ jsx5(
3316
+ pivotIsConfigured && /* @__PURE__ */ jsxs6("div", { className: "vpg-pivot-status", children: [
3317
+ /* @__PURE__ */ jsx6("svg", { className: "vpg-icon", fill: "currentColor", viewBox: "0 0 20 20", children: /* @__PURE__ */ jsx6(
2943
3318
  "path",
2944
3319
  {
2945
3320
  fillRule: "evenodd",
@@ -2947,13 +3322,13 @@ function DataGrid({
2947
3322
  clipRule: "evenodd"
2948
3323
  }
2949
3324
  ) }),
2950
- /* @__PURE__ */ jsx5("span", { children: "Pivot configured" })
3325
+ /* @__PURE__ */ jsx6("span", { children: "Pivot configured" })
2951
3326
  ] })
2952
3327
  ] })
2953
3328
  ] }),
2954
- /* @__PURE__ */ jsxs5("div", { className: "vpg-toolbar-right", children: [
2955
- viewMode === "grid" && activeFilterCount > 0 && /* @__PURE__ */ jsxs5("button", { className: "vpg-clear-filters", onClick: clearAllFilters, children: [
2956
- /* @__PURE__ */ jsx5("svg", { className: "vpg-icon", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: /* @__PURE__ */ jsx5(
3329
+ /* @__PURE__ */ jsxs6("div", { className: "vpg-toolbar-right", children: [
3330
+ viewMode === "grid" && activeFilterCount > 0 && /* @__PURE__ */ jsxs6("button", { className: "vpg-clear-filters", onClick: clearAllFilters, children: [
3331
+ /* @__PURE__ */ jsx6("svg", { className: "vpg-icon", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: /* @__PURE__ */ jsx6(
2957
3332
  "path",
2958
3333
  {
2959
3334
  strokeLinecap: "round",
@@ -2964,13 +3339,13 @@ function DataGrid({
2964
3339
  ) }),
2965
3340
  "Clear Filters"
2966
3341
  ] }),
2967
- enableClipboard && selectionBounds && viewMode === "grid" && /* @__PURE__ */ jsx5(
3342
+ enableClipboard && selectionBounds && viewMode === "grid" && /* @__PURE__ */ jsx6(
2968
3343
  "button",
2969
3344
  {
2970
3345
  className: "vpg-icon-btn",
2971
3346
  title: "Copy selection (Ctrl+C)",
2972
3347
  onClick: copySelectionToClipboard,
2973
- children: /* @__PURE__ */ jsx5("svg", { className: "vpg-icon", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: /* @__PURE__ */ jsx5(
3348
+ children: /* @__PURE__ */ jsx6("svg", { className: "vpg-icon", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: /* @__PURE__ */ jsx6(
2974
3349
  "path",
2975
3350
  {
2976
3351
  strokeLinecap: "round",
@@ -2981,14 +3356,14 @@ function DataGrid({
2981
3356
  ) })
2982
3357
  }
2983
3358
  ),
2984
- enableExport && (viewMode === "grid" || viewMode === "pivot" && pivotIsConfigured) && /* @__PURE__ */ jsxs5(
3359
+ enableExport && (viewMode === "grid" || viewMode === "pivot" && pivotIsConfigured) && /* @__PURE__ */ jsxs6(
2985
3360
  "button",
2986
3361
  {
2987
3362
  className: "vpg-export-btn",
2988
3363
  title: viewMode === "pivot" ? "Export Pivot to CSV" : "Export to CSV",
2989
3364
  onClick: handleExport,
2990
3365
  children: [
2991
- /* @__PURE__ */ jsx5("svg", { className: "vpg-icon", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: /* @__PURE__ */ jsx5(
3366
+ /* @__PURE__ */ jsx6("svg", { className: "vpg-icon", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: /* @__PURE__ */ jsx6(
2992
3367
  "path",
2993
3368
  {
2994
3369
  strokeLinecap: "round",
@@ -3004,13 +3379,13 @@ function DataGrid({
3004
3379
  )
3005
3380
  ] })
3006
3381
  ] }),
3007
- viewMode === "grid" && /* @__PURE__ */ jsxs5("div", { ref: tableContainerRef, className: "vpg-grid-container", tabIndex: 0, children: [
3008
- loading && /* @__PURE__ */ jsxs5("div", { className: "vpg-loading", children: [
3009
- /* @__PURE__ */ jsx5("div", { className: "vpg-spinner" }),
3010
- /* @__PURE__ */ jsx5("span", { children: "Loading data..." })
3382
+ viewMode === "grid" && /* @__PURE__ */ jsxs6("div", { ref: tableContainerRef, className: "vpg-grid-container", tabIndex: 0, children: [
3383
+ loading && /* @__PURE__ */ jsxs6("div", { className: "vpg-loading", children: [
3384
+ /* @__PURE__ */ jsx6("div", { className: "vpg-spinner" }),
3385
+ /* @__PURE__ */ jsx6("span", { children: "Loading data..." })
3011
3386
  ] }),
3012
- !loading && data.length === 0 && /* @__PURE__ */ jsxs5("div", { className: "vpg-empty", children: [
3013
- /* @__PURE__ */ jsx5("div", { className: "vpg-empty-icon", children: /* @__PURE__ */ jsx5("svg", { className: "vpg-icon-lg", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: /* @__PURE__ */ jsx5(
3387
+ !loading && data.length === 0 && /* @__PURE__ */ jsxs6("div", { className: "vpg-empty", children: [
3388
+ /* @__PURE__ */ jsx6("div", { className: "vpg-empty-icon", children: /* @__PURE__ */ jsx6("svg", { className: "vpg-icon-lg", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: /* @__PURE__ */ jsx6(
3014
3389
  "path",
3015
3390
  {
3016
3391
  strokeLinecap: "round",
@@ -3019,10 +3394,10 @@ function DataGrid({
3019
3394
  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"
3020
3395
  }
3021
3396
  ) }) }),
3022
- /* @__PURE__ */ jsx5("span", { children: "No data available" })
3397
+ /* @__PURE__ */ jsx6("span", { children: "No data available" })
3023
3398
  ] }),
3024
- !loading && data.length > 0 && filteredRowCount === 0 && /* @__PURE__ */ jsxs5("div", { className: "vpg-empty", children: [
3025
- /* @__PURE__ */ jsx5("div", { className: "vpg-empty-icon vpg-warning", children: /* @__PURE__ */ jsx5("svg", { className: "vpg-icon-lg", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: /* @__PURE__ */ jsx5(
3399
+ !loading && data.length > 0 && filteredRowCount === 0 && /* @__PURE__ */ jsxs6("div", { className: "vpg-empty", children: [
3400
+ /* @__PURE__ */ jsx6("div", { className: "vpg-empty-icon vpg-warning", children: /* @__PURE__ */ jsx6("svg", { className: "vpg-icon-lg", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: /* @__PURE__ */ jsx6(
3026
3401
  "path",
3027
3402
  {
3028
3403
  strokeLinecap: "round",
@@ -3031,11 +3406,11 @@ function DataGrid({
3031
3406
  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"
3032
3407
  }
3033
3408
  ) }) }),
3034
- /* @__PURE__ */ jsx5("span", { children: "No matching records" }),
3035
- /* @__PURE__ */ jsx5("button", { className: "vpg-clear-link", onClick: clearAllFilters, children: "Clear all filters" })
3409
+ /* @__PURE__ */ jsx6("span", { children: "No matching records" }),
3410
+ /* @__PURE__ */ jsx6("button", { className: "vpg-clear-link", onClick: clearAllFilters, children: "Clear all filters" })
3036
3411
  ] }),
3037
- !loading && filteredRowCount > 0 && /* @__PURE__ */ jsx5("div", { className: "vpg-table-wrapper", children: /* @__PURE__ */ jsxs5("table", { className: "vpg-table", style: { minWidth: `${totalTableWidth}px` }, children: [
3038
- /* @__PURE__ */ jsx5("thead", { children: /* @__PURE__ */ jsx5("tr", { children: columnKeys.map((colId, colIndex) => /* @__PURE__ */ jsxs5(
3412
+ !loading && filteredRowCount > 0 && /* @__PURE__ */ jsx6("div", { className: "vpg-table-wrapper", children: /* @__PURE__ */ jsxs6("table", { className: "vpg-table", style: { minWidth: `${totalTableWidth}px` }, children: [
3413
+ /* @__PURE__ */ jsx6("thead", { children: /* @__PURE__ */ jsx6("tr", { children: columnKeys.map((colId, colIndex) => /* @__PURE__ */ jsxs6(
3039
3414
  "th",
3040
3415
  {
3041
3416
  className: `vpg-header-cell ${hasActiveFilter(colId) ? "vpg-has-filter" : ""} ${getSortDirection(colId) !== null ? "vpg-is-sorted" : ""} ${activeFilterColumn === colId ? "vpg-is-active" : ""}`,
@@ -3050,16 +3425,16 @@ function DataGrid({
3050
3425
  }
3051
3426
  },
3052
3427
  children: [
3053
- /* @__PURE__ */ jsxs5("div", { className: "vpg-header-content", children: [
3054
- /* @__PURE__ */ jsx5("span", { className: "vpg-header-text", children: colId }),
3055
- /* @__PURE__ */ jsxs5("div", { className: "vpg-header-icons", children: [
3056
- getSortDirection(colId) && /* @__PURE__ */ jsx5("span", { className: "vpg-sort-indicator", children: getSortDirection(colId) === "asc" ? /* @__PURE__ */ jsx5(
3428
+ /* @__PURE__ */ jsxs6("div", { className: "vpg-header-content", children: [
3429
+ /* @__PURE__ */ jsx6("span", { className: "vpg-header-text", children: colId }),
3430
+ /* @__PURE__ */ jsxs6("div", { className: "vpg-header-icons", children: [
3431
+ getSortDirection(colId) && /* @__PURE__ */ jsx6("span", { className: "vpg-sort-indicator", children: getSortDirection(colId) === "asc" ? /* @__PURE__ */ jsx6(
3057
3432
  "svg",
3058
3433
  {
3059
3434
  className: "vpg-icon-sm",
3060
3435
  fill: "currentColor",
3061
3436
  viewBox: "0 0 20 20",
3062
- children: /* @__PURE__ */ jsx5(
3437
+ children: /* @__PURE__ */ jsx6(
3063
3438
  "path",
3064
3439
  {
3065
3440
  fillRule: "evenodd",
@@ -3068,13 +3443,13 @@ function DataGrid({
3068
3443
  }
3069
3444
  )
3070
3445
  }
3071
- ) : /* @__PURE__ */ jsx5(
3446
+ ) : /* @__PURE__ */ jsx6(
3072
3447
  "svg",
3073
3448
  {
3074
3449
  className: "vpg-icon-sm",
3075
3450
  fill: "currentColor",
3076
3451
  viewBox: "0 0 20 20",
3077
- children: /* @__PURE__ */ jsx5(
3452
+ children: /* @__PURE__ */ jsx6(
3078
3453
  "path",
3079
3454
  {
3080
3455
  fillRule: "evenodd",
@@ -3084,13 +3459,13 @@ function DataGrid({
3084
3459
  )
3085
3460
  }
3086
3461
  ) }),
3087
- hasActiveFilter(colId) && /* @__PURE__ */ jsx5("span", { className: "vpg-filter-indicator", children: /* @__PURE__ */ jsx5(
3462
+ hasActiveFilter(colId) && /* @__PURE__ */ jsx6("span", { className: "vpg-filter-indicator", children: /* @__PURE__ */ jsx6(
3088
3463
  "svg",
3089
3464
  {
3090
3465
  className: "vpg-icon-xs",
3091
3466
  fill: "currentColor",
3092
3467
  viewBox: "0 0 20 20",
3093
- children: /* @__PURE__ */ jsx5(
3468
+ children: /* @__PURE__ */ jsx6(
3094
3469
  "path",
3095
3470
  {
3096
3471
  fillRule: "evenodd",
@@ -3100,14 +3475,14 @@ function DataGrid({
3100
3475
  )
3101
3476
  }
3102
3477
  ) }),
3103
- /* @__PURE__ */ jsx5("span", { className: "vpg-dropdown-arrow", title: "Filter & Sort", children: /* @__PURE__ */ jsx5(
3478
+ /* @__PURE__ */ jsx6("span", { className: "vpg-dropdown-arrow", title: "Filter & Sort", children: /* @__PURE__ */ jsx6(
3104
3479
  "svg",
3105
3480
  {
3106
3481
  className: "vpg-icon-sm",
3107
3482
  fill: "none",
3108
3483
  stroke: "currentColor",
3109
3484
  viewBox: "0 0 24 24",
3110
- children: /* @__PURE__ */ jsx5(
3485
+ children: /* @__PURE__ */ jsx6(
3111
3486
  "path",
3112
3487
  {
3113
3488
  strokeLinecap: "round",
@@ -3120,7 +3495,7 @@ function DataGrid({
3120
3495
  ) })
3121
3496
  ] })
3122
3497
  ] }),
3123
- enableColumnResize && /* @__PURE__ */ jsx5(
3498
+ enableColumnResize && /* @__PURE__ */ jsx6(
3124
3499
  "div",
3125
3500
  {
3126
3501
  className: "vpg-resize-handle",
@@ -3131,7 +3506,7 @@ function DataGrid({
3131
3506
  },
3132
3507
  colId
3133
3508
  )) }) }),
3134
- /* @__PURE__ */ jsx5("tbody", { ref: tableBodyRef, children: paginatedRows.map((row, rowIndex) => /* @__PURE__ */ jsx5("tr", { className: "vpg-row", children: columnKeys.map((colId, colIndex) => /* @__PURE__ */ jsx5(
3509
+ /* @__PURE__ */ jsx6("tbody", { ref: tableBodyRef, children: paginatedRows.map((row, rowIndex) => /* @__PURE__ */ jsx6("tr", { className: "vpg-row", children: columnKeys.map((colId, colIndex) => /* @__PURE__ */ jsx6(
3135
3510
  "td",
3136
3511
  {
3137
3512
  className: `vpg-cell ${isCellSelected(rowIndex, colIndex) ? "vpg-selected" : ""} ${getColumnStats(colId).type === "number" ? "vpg-is-number" : ""}`,
@@ -3149,8 +3524,8 @@ function DataGrid({
3149
3524
  )) }, row.id)) })
3150
3525
  ] }) })
3151
3526
  ] }),
3152
- viewMode === "pivot" && /* @__PURE__ */ jsxs5("div", { className: "vpg-pivot-container", children: [
3153
- showPivotConfig && canUsePivot && /* @__PURE__ */ jsx5("div", { className: "vpg-pivot-config-panel", children: /* @__PURE__ */ jsx5(
3527
+ viewMode === "pivot" && /* @__PURE__ */ jsxs6("div", { className: "vpg-pivot-container", children: [
3528
+ showPivotConfig && canUsePivot && /* @__PURE__ */ jsx6("div", { className: "vpg-pivot-config-panel", children: /* @__PURE__ */ jsx6(
3154
3529
  PivotConfig,
3155
3530
  {
3156
3531
  availableFields: pivotAvailableFields,
@@ -3178,7 +3553,7 @@ function DataGrid({
3178
3553
  onUpdateCalculatedField: addCalculatedField
3179
3554
  }
3180
3555
  ) }),
3181
- /* @__PURE__ */ jsx5("div", { className: `vpg-pivot-main ${!showPivotConfig ? "vpg-full-width" : ""}`, children: /* @__PURE__ */ jsx5(
3556
+ /* @__PURE__ */ jsx6("div", { className: `vpg-pivot-main ${!showPivotConfig ? "vpg-full-width" : ""}`, children: /* @__PURE__ */ jsx6(
3182
3557
  PivotSkeleton,
3183
3558
  {
3184
3559
  rowFields: pivotRowFields,
@@ -3204,44 +3579,44 @@ function DataGrid({
3204
3579
  }
3205
3580
  ) })
3206
3581
  ] }),
3207
- /* @__PURE__ */ jsxs5("div", { className: "vpg-footer", children: [
3208
- /* @__PURE__ */ jsx5("div", { className: "vpg-footer-left", children: viewMode === "grid" ? enablePagination ? /* @__PURE__ */ jsxs5(Fragment3, { children: [
3209
- /* @__PURE__ */ jsxs5("span", { children: [
3582
+ /* @__PURE__ */ jsxs6("div", { className: "vpg-footer", children: [
3583
+ /* @__PURE__ */ jsx6("div", { className: "vpg-footer-left", children: viewMode === "grid" ? enablePagination ? /* @__PURE__ */ jsxs6(Fragment4, { children: [
3584
+ /* @__PURE__ */ jsxs6("span", { children: [
3210
3585
  ((currentPage - 1) * pageSize + 1).toLocaleString(),
3211
3586
  "-",
3212
3587
  Math.min(currentPage * pageSize, totalSearchedRows).toLocaleString()
3213
3588
  ] }),
3214
- /* @__PURE__ */ jsx5("span", { className: "vpg-separator", children: "of" }),
3215
- /* @__PURE__ */ jsx5("span", { children: totalSearchedRows.toLocaleString() }),
3216
- totalSearchedRows !== totalRowCount && /* @__PURE__ */ jsxs5("span", { className: "vpg-filtered-note", children: [
3589
+ /* @__PURE__ */ jsx6("span", { className: "vpg-separator", children: "of" }),
3590
+ /* @__PURE__ */ jsx6("span", { children: totalSearchedRows.toLocaleString() }),
3591
+ totalSearchedRows !== totalRowCount && /* @__PURE__ */ jsxs6("span", { className: "vpg-filtered-note", children: [
3217
3592
  "(",
3218
3593
  totalRowCount.toLocaleString(),
3219
3594
  " total)"
3220
3595
  ] })
3221
- ] }) : filteredRowCount === totalRowCount && totalSearchedRows === totalRowCount ? /* @__PURE__ */ jsxs5("span", { children: [
3596
+ ] }) : filteredRowCount === totalRowCount && totalSearchedRows === totalRowCount ? /* @__PURE__ */ jsxs6("span", { children: [
3222
3597
  totalRowCount.toLocaleString(),
3223
3598
  " records"
3224
- ] }) : /* @__PURE__ */ jsxs5(Fragment3, { children: [
3225
- /* @__PURE__ */ jsx5("span", { className: "vpg-filtered-count", children: totalSearchedRows.toLocaleString() }),
3226
- /* @__PURE__ */ jsx5("span", { className: "vpg-separator", children: "of" }),
3227
- /* @__PURE__ */ jsx5("span", { children: totalRowCount.toLocaleString() }),
3228
- /* @__PURE__ */ jsx5("span", { className: "vpg-separator", children: "records" })
3229
- ] }) : /* @__PURE__ */ jsxs5(Fragment3, { children: [
3230
- /* @__PURE__ */ jsx5("span", { className: "vpg-pivot-label", children: "Pivot Table" }),
3231
- /* @__PURE__ */ jsx5("span", { className: "vpg-separator", children: "\u2022" }),
3232
- /* @__PURE__ */ jsxs5("span", { children: [
3599
+ ] }) : /* @__PURE__ */ jsxs6(Fragment4, { children: [
3600
+ /* @__PURE__ */ jsx6("span", { className: "vpg-filtered-count", children: totalSearchedRows.toLocaleString() }),
3601
+ /* @__PURE__ */ jsx6("span", { className: "vpg-separator", children: "of" }),
3602
+ /* @__PURE__ */ jsx6("span", { children: totalRowCount.toLocaleString() }),
3603
+ /* @__PURE__ */ jsx6("span", { className: "vpg-separator", children: "records" })
3604
+ ] }) : /* @__PURE__ */ jsxs6(Fragment4, { children: [
3605
+ /* @__PURE__ */ jsx6("span", { className: "vpg-pivot-label", children: "Pivot Table" }),
3606
+ /* @__PURE__ */ jsx6("span", { className: "vpg-separator", children: "\u2022" }),
3607
+ /* @__PURE__ */ jsxs6("span", { children: [
3233
3608
  totalRowCount.toLocaleString(),
3234
3609
  " source records"
3235
3610
  ] })
3236
3611
  ] }) }),
3237
- enablePagination && viewMode === "grid" && totalPages > 1 && /* @__PURE__ */ jsxs5("div", { className: "vpg-pagination", children: [
3238
- /* @__PURE__ */ jsx5(
3612
+ enablePagination && viewMode === "grid" && totalPages > 1 && /* @__PURE__ */ jsxs6("div", { className: "vpg-pagination", children: [
3613
+ /* @__PURE__ */ jsx6(
3239
3614
  "button",
3240
3615
  {
3241
3616
  className: "vpg-page-btn",
3242
3617
  disabled: currentPage === 1,
3243
3618
  onClick: () => setCurrentPage(1),
3244
- children: /* @__PURE__ */ jsx5("svg", { className: "vpg-icon-sm", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: /* @__PURE__ */ jsx5(
3619
+ children: /* @__PURE__ */ jsx6("svg", { className: "vpg-icon-sm", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: /* @__PURE__ */ jsx6(
3245
3620
  "path",
3246
3621
  {
3247
3622
  strokeLinecap: "round",
@@ -3252,13 +3627,13 @@ function DataGrid({
3252
3627
  ) })
3253
3628
  }
3254
3629
  ),
3255
- /* @__PURE__ */ jsx5(
3630
+ /* @__PURE__ */ jsx6(
3256
3631
  "button",
3257
3632
  {
3258
3633
  className: "vpg-page-btn",
3259
3634
  disabled: currentPage === 1,
3260
3635
  onClick: () => setCurrentPage((p) => Math.max(1, p - 1)),
3261
- children: /* @__PURE__ */ jsx5("svg", { className: "vpg-icon-sm", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: /* @__PURE__ */ jsx5(
3636
+ children: /* @__PURE__ */ jsx6("svg", { className: "vpg-icon-sm", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: /* @__PURE__ */ jsx6(
3262
3637
  "path",
3263
3638
  {
3264
3639
  strokeLinecap: "round",
@@ -3269,19 +3644,19 @@ function DataGrid({
3269
3644
  ) })
3270
3645
  }
3271
3646
  ),
3272
- /* @__PURE__ */ jsxs5("span", { className: "vpg-page-info", children: [
3647
+ /* @__PURE__ */ jsxs6("span", { className: "vpg-page-info", children: [
3273
3648
  "Page ",
3274
3649
  currentPage,
3275
3650
  " of ",
3276
3651
  totalPages
3277
3652
  ] }),
3278
- /* @__PURE__ */ jsx5(
3653
+ /* @__PURE__ */ jsx6(
3279
3654
  "button",
3280
3655
  {
3281
3656
  className: "vpg-page-btn",
3282
3657
  disabled: currentPage === totalPages,
3283
3658
  onClick: () => setCurrentPage((p) => Math.min(totalPages, p + 1)),
3284
- children: /* @__PURE__ */ jsx5("svg", { className: "vpg-icon-sm", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: /* @__PURE__ */ jsx5(
3659
+ children: /* @__PURE__ */ jsx6("svg", { className: "vpg-icon-sm", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: /* @__PURE__ */ jsx6(
3285
3660
  "path",
3286
3661
  {
3287
3662
  strokeLinecap: "round",
@@ -3292,13 +3667,13 @@ function DataGrid({
3292
3667
  ) })
3293
3668
  }
3294
3669
  ),
3295
- /* @__PURE__ */ jsx5(
3670
+ /* @__PURE__ */ jsx6(
3296
3671
  "button",
3297
3672
  {
3298
3673
  className: "vpg-page-btn",
3299
3674
  disabled: currentPage === totalPages,
3300
3675
  onClick: () => setCurrentPage(totalPages),
3301
- children: /* @__PURE__ */ jsx5("svg", { className: "vpg-icon-sm", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: /* @__PURE__ */ jsx5(
3676
+ children: /* @__PURE__ */ jsx6("svg", { className: "vpg-icon-sm", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: /* @__PURE__ */ jsx6(
3302
3677
  "path",
3303
3678
  {
3304
3679
  strokeLinecap: "round",
@@ -3310,45 +3685,45 @@ function DataGrid({
3310
3685
  }
3311
3686
  )
3312
3687
  ] }),
3313
- viewMode === "grid" && selectionStats && selectionStats.count > 1 && /* @__PURE__ */ jsxs5("div", { className: "vpg-selection-stats", children: [
3314
- /* @__PURE__ */ jsxs5("span", { className: "vpg-stat", children: [
3315
- /* @__PURE__ */ jsx5("span", { className: "vpg-stat-label", children: "Count:" }),
3316
- /* @__PURE__ */ jsx5("span", { className: "vpg-stat-value", children: selectionStats.count })
3688
+ viewMode === "grid" && selectionStats && selectionStats.count > 1 && /* @__PURE__ */ jsxs6("div", { className: "vpg-selection-stats", children: [
3689
+ /* @__PURE__ */ jsxs6("span", { className: "vpg-stat", children: [
3690
+ /* @__PURE__ */ jsx6("span", { className: "vpg-stat-label", children: "Count:" }),
3691
+ /* @__PURE__ */ jsx6("span", { className: "vpg-stat-value", children: selectionStats.count })
3317
3692
  ] }),
3318
- selectionStats.numericCount > 0 && /* @__PURE__ */ jsxs5(Fragment3, { children: [
3319
- /* @__PURE__ */ jsx5("span", { className: "vpg-stat-divider", children: "|" }),
3320
- /* @__PURE__ */ jsxs5("span", { className: "vpg-stat", children: [
3321
- /* @__PURE__ */ jsx5("span", { className: "vpg-stat-label", children: "Sum:" }),
3322
- /* @__PURE__ */ jsx5("span", { className: "vpg-stat-value", children: formatStatValue(selectionStats.sum) })
3693
+ selectionStats.numericCount > 0 && /* @__PURE__ */ jsxs6(Fragment4, { children: [
3694
+ /* @__PURE__ */ jsx6("span", { className: "vpg-stat-divider", children: "|" }),
3695
+ /* @__PURE__ */ jsxs6("span", { className: "vpg-stat", children: [
3696
+ /* @__PURE__ */ jsx6("span", { className: "vpg-stat-label", children: "Sum:" }),
3697
+ /* @__PURE__ */ jsx6("span", { className: "vpg-stat-value", children: formatStatValue(selectionStats.sum) })
3323
3698
  ] }),
3324
- /* @__PURE__ */ jsx5("span", { className: "vpg-stat-divider", children: "|" }),
3325
- /* @__PURE__ */ jsxs5("span", { className: "vpg-stat", children: [
3326
- /* @__PURE__ */ jsx5("span", { className: "vpg-stat-label", children: "Avg:" }),
3327
- /* @__PURE__ */ jsx5("span", { className: "vpg-stat-value", children: formatStatValue(selectionStats.avg) })
3699
+ /* @__PURE__ */ jsx6("span", { className: "vpg-stat-divider", children: "|" }),
3700
+ /* @__PURE__ */ jsxs6("span", { className: "vpg-stat", children: [
3701
+ /* @__PURE__ */ jsx6("span", { className: "vpg-stat-label", children: "Avg:" }),
3702
+ /* @__PURE__ */ jsx6("span", { className: "vpg-stat-value", children: formatStatValue(selectionStats.avg) })
3328
3703
  ] })
3329
3704
  ] })
3330
3705
  ] }),
3331
- /* @__PURE__ */ jsx5("div", { className: "vpg-footer-right", children: isDemo ? /* @__PURE__ */ jsxs5("div", { className: "vpg-demo-banner", children: [
3332
- /* @__PURE__ */ jsx5("span", { className: "vpg-demo-badge", children: "DEMO" }),
3333
- /* @__PURE__ */ jsx5("span", { children: "Pro features enabled" }),
3334
- /* @__PURE__ */ jsx5("a", { href: "https://tiny-pivot.com/#pricing", target: "_blank", rel: "noopener noreferrer", children: "Get License \u2192" })
3335
- ] }) : showWatermark ? /* @__PURE__ */ jsx5("span", { className: "vpg-watermark-inline", children: /* @__PURE__ */ jsxs5("a", { href: "https://tiny-pivot.com", target: "_blank", rel: "noopener noreferrer", children: [
3336
- /* @__PURE__ */ jsxs5("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: [
3337
- /* @__PURE__ */ jsx5("rect", { x: "3", y: "3", width: "7", height: "7" }),
3338
- /* @__PURE__ */ jsx5("rect", { x: "14", y: "3", width: "7", height: "7" }),
3339
- /* @__PURE__ */ jsx5("rect", { x: "14", y: "14", width: "7", height: "7" }),
3340
- /* @__PURE__ */ jsx5("rect", { x: "3", y: "14", width: "7", height: "7" })
3706
+ /* @__PURE__ */ jsx6("div", { className: "vpg-footer-right", children: isDemo ? /* @__PURE__ */ jsxs6("div", { className: "vpg-demo-banner", children: [
3707
+ /* @__PURE__ */ jsx6("span", { className: "vpg-demo-badge", children: "DEMO" }),
3708
+ /* @__PURE__ */ jsx6("span", { children: "Pro features enabled" }),
3709
+ /* @__PURE__ */ jsx6("a", { href: "https://tiny-pivot.com/#pricing", target: "_blank", rel: "noopener noreferrer", children: "Get License \u2192" })
3710
+ ] }) : showWatermark ? /* @__PURE__ */ jsx6("span", { className: "vpg-watermark-inline", children: /* @__PURE__ */ jsxs6("a", { href: "https://tiny-pivot.com", target: "_blank", rel: "noopener noreferrer", children: [
3711
+ /* @__PURE__ */ jsxs6("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: [
3712
+ /* @__PURE__ */ jsx6("rect", { x: "3", y: "3", width: "7", height: "7" }),
3713
+ /* @__PURE__ */ jsx6("rect", { x: "14", y: "3", width: "7", height: "7" }),
3714
+ /* @__PURE__ */ jsx6("rect", { x: "14", y: "14", width: "7", height: "7" }),
3715
+ /* @__PURE__ */ jsx6("rect", { x: "3", y: "14", width: "7", height: "7" })
3341
3716
  ] }),
3342
3717
  "Powered by TinyPivot"
3343
3718
  ] }) }) : null })
3344
3719
  ] }),
3345
- enableVerticalResize && /* @__PURE__ */ jsx5("div", { className: "vpg-vertical-resize-handle", onMouseDown: startVerticalResize, children: /* @__PURE__ */ jsxs5("div", { className: "vpg-resize-grip", children: [
3346
- /* @__PURE__ */ jsx5("span", {}),
3347
- /* @__PURE__ */ jsx5("span", {}),
3348
- /* @__PURE__ */ jsx5("span", {})
3720
+ enableVerticalResize && /* @__PURE__ */ jsx6("div", { className: "vpg-vertical-resize-handle", onMouseDown: startVerticalResize, children: /* @__PURE__ */ jsxs6("div", { className: "vpg-resize-grip", children: [
3721
+ /* @__PURE__ */ jsx6("span", {}),
3722
+ /* @__PURE__ */ jsx6("span", {}),
3723
+ /* @__PURE__ */ jsx6("span", {})
3349
3724
  ] }) }),
3350
3725
  activeFilterColumn && createPortal2(
3351
- /* @__PURE__ */ jsx5(
3726
+ /* @__PURE__ */ jsx6(
3352
3727
  "div",
3353
3728
  {
3354
3729
  className: "vpg-filter-portal",
@@ -3359,7 +3734,7 @@ function DataGrid({
3359
3734
  maxHeight: `${filterDropdownPosition.maxHeight}px`,
3360
3735
  zIndex: 9999
3361
3736
  },
3362
- children: /* @__PURE__ */ jsx5(
3737
+ children: /* @__PURE__ */ jsx6(
3363
3738
  ColumnFilter,
3364
3739
  {
3365
3740
  columnId: activeFilterColumn,
@@ -3367,7 +3742,9 @@ function DataGrid({
3367
3742
  stats: getColumnStats(activeFilterColumn),
3368
3743
  selectedValues: getColumnFilterValues(activeFilterColumn),
3369
3744
  sortDirection: getSortDirection(activeFilterColumn),
3745
+ numericRange: getNumericRangeFilter(activeFilterColumn),
3370
3746
  onFilter: (values) => handleFilter(activeFilterColumn, values),
3747
+ onRangeFilter: (range) => handleRangeFilter(activeFilterColumn, range),
3371
3748
  onSort: (dir) => handleSort(activeFilterColumn, dir),
3372
3749
  onClose: closeFilterDropdown
3373
3750
  }