@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.cjs +919 -542
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +8 -2
- package/dist/index.d.ts +8 -2
- package/dist/index.js +917 -540
- package/dist/index.js.map +1 -1
- package/dist/style.css +299 -0
- package/package.json +2 -2
package/dist/index.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
// src/components/DataGrid.tsx
|
|
2
|
-
import { useState as
|
|
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
|
|
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
|
-
|
|
19
|
-
|
|
20
|
-
|
|
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
|
-
|
|
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
|
|
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] =
|
|
753
|
-
const [localSelected, setLocalSelected] =
|
|
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 =
|
|
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 =
|
|
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 =
|
|
1061
|
+
const isAllSelected = useMemo6(
|
|
771
1062
|
() => allValues.every((v) => localSelected.has(v)),
|
|
772
1063
|
[allValues, localSelected]
|
|
773
1064
|
);
|
|
774
|
-
const toggleValue =
|
|
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 =
|
|
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 =
|
|
1085
|
+
const clearAll = useCallback6(() => {
|
|
795
1086
|
setLocalSelected(/* @__PURE__ */ new Set());
|
|
796
1087
|
}, []);
|
|
797
|
-
const applyFilter =
|
|
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 =
|
|
1096
|
+
const sortAscending = useCallback6(() => {
|
|
806
1097
|
onSort(sortDirection === "asc" ? null : "asc");
|
|
807
1098
|
}, [sortDirection, onSort]);
|
|
808
|
-
const sortDescending =
|
|
1099
|
+
const sortDescending = useCallback6(() => {
|
|
809
1100
|
onSort(sortDirection === "desc" ? null : "desc");
|
|
810
1101
|
}, [sortDirection, onSort]);
|
|
811
|
-
const clearFilter =
|
|
1102
|
+
const clearFilter = useCallback6(() => {
|
|
812
1103
|
setLocalSelected(/* @__PURE__ */ new Set());
|
|
813
1104
|
onFilter([]);
|
|
814
1105
|
onClose();
|
|
815
1106
|
}, [onFilter, onClose]);
|
|
816
|
-
|
|
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
|
-
|
|
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
|
-
|
|
1139
|
+
useEffect4(() => {
|
|
837
1140
|
searchInputRef.current?.focus();
|
|
838
1141
|
}, []);
|
|
839
|
-
|
|
1142
|
+
useEffect4(() => {
|
|
840
1143
|
setLocalSelected(new Set(selectedValues));
|
|
841
1144
|
}, [selectedValues]);
|
|
842
|
-
|
|
843
|
-
|
|
844
|
-
|
|
845
|
-
|
|
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__ */
|
|
851
|
-
/* @__PURE__ */
|
|
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__ */
|
|
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__ */
|
|
1176
|
+
/* @__PURE__ */ jsx2("span", { children: isNumericColumn ? "1\u21929" : "A\u2192Z" })
|
|
868
1177
|
]
|
|
869
1178
|
}
|
|
870
1179
|
),
|
|
871
|
-
/* @__PURE__ */
|
|
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__ */
|
|
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__ */
|
|
1196
|
+
/* @__PURE__ */ jsx2("span", { children: isNumericColumn ? "9\u21921" : "Z\u2192A" })
|
|
888
1197
|
]
|
|
889
1198
|
}
|
|
890
1199
|
)
|
|
891
1200
|
] }),
|
|
892
|
-
/* @__PURE__ */
|
|
893
|
-
/* @__PURE__ */
|
|
894
|
-
/* @__PURE__ */
|
|
895
|
-
"
|
|
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
|
-
|
|
898
|
-
|
|
899
|
-
|
|
900
|
-
|
|
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__ */
|
|
904
|
-
"
|
|
1221
|
+
),
|
|
1222
|
+
/* @__PURE__ */ jsxs2(
|
|
1223
|
+
"button",
|
|
905
1224
|
{
|
|
906
|
-
|
|
907
|
-
|
|
908
|
-
|
|
909
|
-
|
|
910
|
-
|
|
911
|
-
|
|
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__ */
|
|
917
|
-
/* @__PURE__ */
|
|
918
|
-
/* @__PURE__ */
|
|
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: "
|
|
1250
|
+
d: "M21 21l-6-6m2-5a7 7 0 11-14 0 7 7 0 0114 0z"
|
|
925
1251
|
}
|
|
926
1252
|
) }),
|
|
927
|
-
|
|
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
|
-
|
|
934
|
-
|
|
935
|
-
|
|
936
|
-
|
|
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
|
-
"
|
|
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__ */
|
|
943
|
-
|
|
944
|
-
|
|
1319
|
+
isNumericColumn && filterMode === "range" && /* @__PURE__ */ jsxs2(Fragment, { children: [
|
|
1320
|
+
/* @__PURE__ */ jsx2(
|
|
1321
|
+
NumericRangeFilter,
|
|
945
1322
|
{
|
|
946
|
-
|
|
947
|
-
|
|
948
|
-
|
|
949
|
-
|
|
950
|
-
|
|
951
|
-
|
|
952
|
-
|
|
953
|
-
|
|
954
|
-
|
|
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
|
|
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
|
|
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
|
|
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] =
|
|
988
|
-
const [formula, setFormula] =
|
|
989
|
-
const [formatAs, setFormatAs] =
|
|
990
|
-
const [decimals, setDecimals] =
|
|
991
|
-
const [error, setError] =
|
|
992
|
-
|
|
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 =
|
|
1374
|
+
const validationError = useMemo7(() => {
|
|
1009
1375
|
if (!formula.trim()) return null;
|
|
1010
1376
|
return validateSimpleFormula(formula, availableFields);
|
|
1011
1377
|
}, [formula, availableFields]);
|
|
1012
|
-
const insertField =
|
|
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 =
|
|
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 =
|
|
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 =
|
|
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__ */
|
|
1055
|
-
/* @__PURE__ */
|
|
1056
|
-
/* @__PURE__ */
|
|
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__ */
|
|
1426
|
+
/* @__PURE__ */ jsx3("button", { className: "vpg-modal-close", onClick: onClose, children: "\xD7" })
|
|
1061
1427
|
] }),
|
|
1062
|
-
/* @__PURE__ */
|
|
1063
|
-
/* @__PURE__ */
|
|
1064
|
-
/* @__PURE__ */
|
|
1065
|
-
/* @__PURE__ */
|
|
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__ */
|
|
1077
|
-
/* @__PURE__ */
|
|
1078
|
-
/* @__PURE__ */
|
|
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__ */
|
|
1089
|
-
validationError && /* @__PURE__ */
|
|
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__ */
|
|
1092
|
-
/* @__PURE__ */
|
|
1093
|
-
/* @__PURE__ */
|
|
1094
|
-
/* @__PURE__ */
|
|
1095
|
-
/* @__PURE__ */
|
|
1096
|
-
/* @__PURE__ */
|
|
1097
|
-
/* @__PURE__ */
|
|
1098
|
-
/* @__PURE__ */
|
|
1099
|
-
/* @__PURE__ */
|
|
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__ */
|
|
1103
|
-
/* @__PURE__ */
|
|
1104
|
-
availableFields.length > 0 ? /* @__PURE__ */
|
|
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__ */
|
|
1478
|
+
)) }) : /* @__PURE__ */ jsx3("div", { className: "vpg-no-fields", children: "No numeric fields available" })
|
|
1113
1479
|
] }),
|
|
1114
|
-
/* @__PURE__ */
|
|
1115
|
-
/* @__PURE__ */
|
|
1116
|
-
/* @__PURE__ */
|
|
1117
|
-
/* @__PURE__ */
|
|
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__ */
|
|
1125
|
-
/* @__PURE__ */
|
|
1126
|
-
/* @__PURE__ */
|
|
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__ */
|
|
1132
|
-
/* @__PURE__ */
|
|
1133
|
-
/* @__PURE__ */
|
|
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__ */
|
|
1512
|
+
error && /* @__PURE__ */ jsx3("div", { className: "vpg-error vpg-error-box", children: error })
|
|
1147
1513
|
] }),
|
|
1148
|
-
/* @__PURE__ */
|
|
1149
|
-
/* @__PURE__ */
|
|
1150
|
-
/* @__PURE__ */
|
|
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
|
|
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] =
|
|
1198
|
-
const [showCalcModal, setShowCalcModal] =
|
|
1199
|
-
const [editingCalcField, setEditingCalcField] =
|
|
1200
|
-
const numericFieldNames =
|
|
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 =
|
|
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 =
|
|
1583
|
+
const allAvailableFields = useMemo8(() => [
|
|
1218
1584
|
...availableFields.map((f) => ({ ...f, isCalculated: false })),
|
|
1219
1585
|
...calculatedFieldsAsStats
|
|
1220
1586
|
], [availableFields, calculatedFieldsAsStats]);
|
|
1221
|
-
const assignedFields =
|
|
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 =
|
|
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 =
|
|
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 =
|
|
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 =
|
|
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 =
|
|
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 =
|
|
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 =
|
|
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 =
|
|
1659
|
+
const handleTotalsToggle = useCallback8((checked) => {
|
|
1294
1660
|
onShowRowTotalsChange(checked);
|
|
1295
1661
|
onShowColumnTotalsChange(checked);
|
|
1296
1662
|
}, [onShowRowTotalsChange, onShowColumnTotalsChange]);
|
|
1297
|
-
const openCalcModal =
|
|
1663
|
+
const openCalcModal = useCallback8((field) => {
|
|
1298
1664
|
setEditingCalcField(field || null);
|
|
1299
1665
|
setShowCalcModal(true);
|
|
1300
1666
|
}, []);
|
|
1301
|
-
const handleSaveCalcField =
|
|
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 =
|
|
1676
|
+
const handleCloseCalcModal = useCallback8(() => {
|
|
1311
1677
|
setShowCalcModal(false);
|
|
1312
1678
|
setEditingCalcField(null);
|
|
1313
1679
|
}, []);
|
|
1314
|
-
return /* @__PURE__ */
|
|
1315
|
-
/* @__PURE__ */
|
|
1316
|
-
/* @__PURE__ */
|
|
1317
|
-
/* @__PURE__ */
|
|
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__ */
|
|
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__ */
|
|
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__ */
|
|
1347
|
-
/* @__PURE__ */
|
|
1348
|
-
/* @__PURE__ */
|
|
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__ */
|
|
1358
|
-
/* @__PURE__ */
|
|
1359
|
-
/* @__PURE__ */
|
|
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__ */
|
|
1362
|
-
(field.assignedTo === "row" || field.assignedTo === "column") && /* @__PURE__ */
|
|
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__ */
|
|
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__ */
|
|
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__ */
|
|
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__ */
|
|
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__ */
|
|
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__ */
|
|
1431
|
-
/* @__PURE__ */
|
|
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__ */
|
|
1799
|
+
/* @__PURE__ */ jsx4("span", { className: "vpg-count", children: unassignedFields.length })
|
|
1434
1800
|
] }) }),
|
|
1435
|
-
/* @__PURE__ */
|
|
1436
|
-
/* @__PURE__ */
|
|
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__ */
|
|
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__ */
|
|
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__ */
|
|
1466
|
-
filteredUnassignedFields.map((field) => /* @__PURE__ */
|
|
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__ */
|
|
1476
|
-
/* @__PURE__ */
|
|
1477
|
-
field.isCalculated ? /* @__PURE__ */
|
|
1478
|
-
/* @__PURE__ */
|
|
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__ */
|
|
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__ */
|
|
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__ */
|
|
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__ */
|
|
1881
|
+
unassignedFields.length === 0 && /* @__PURE__ */ jsx4("div", { className: "vpg-empty-hint", children: "All fields assigned" })
|
|
1516
1882
|
] })
|
|
1517
1883
|
] }),
|
|
1518
|
-
/* @__PURE__ */
|
|
1519
|
-
/* @__PURE__ */
|
|
1520
|
-
/* @__PURE__ */
|
|
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__ */
|
|
1894
|
+
/* @__PURE__ */ jsx4("span", { children: "Totals" })
|
|
1529
1895
|
] }),
|
|
1530
|
-
/* @__PURE__ */
|
|
1531
|
-
/* @__PURE__ */
|
|
1532
|
-
/* @__PURE__ */
|
|
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__ */
|
|
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
|
|
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
|
|
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 =
|
|
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 =
|
|
1948
|
+
const isCalculatedField = useCallback9((field) => {
|
|
1583
1949
|
return field.startsWith("calc:");
|
|
1584
1950
|
}, []);
|
|
1585
|
-
const [dragOverArea, setDragOverArea] =
|
|
1586
|
-
const [reorderDragSource, setReorderDragSource] =
|
|
1587
|
-
const [reorderDropTarget, setReorderDropTarget] =
|
|
1588
|
-
const [sortDirection, setSortDirection] =
|
|
1589
|
-
const [sortTarget, setSortTarget] =
|
|
1590
|
-
const toggleSort =
|
|
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] =
|
|
1599
|
-
const [selectionStart, setSelectionStart] =
|
|
1600
|
-
const [selectionEnd, setSelectionEnd] =
|
|
1601
|
-
const [isSelecting, setIsSelecting] =
|
|
1602
|
-
const [showCopyToast, setShowCopyToast] =
|
|
1603
|
-
const [copyToastMessage, setCopyToastMessage] =
|
|
1604
|
-
const selectionBounds =
|
|
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 =
|
|
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 =
|
|
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 =
|
|
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
|
-
|
|
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 =
|
|
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 =
|
|
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
|
-
|
|
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 =
|
|
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 =
|
|
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 =
|
|
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 =
|
|
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] =
|
|
1779
|
-
const filterTooltipDetails =
|
|
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 =
|
|
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 =
|
|
2166
|
+
const handleDragLeave = useCallback9(() => {
|
|
1801
2167
|
setDragOverArea(null);
|
|
1802
2168
|
}, []);
|
|
1803
|
-
const handleDrop =
|
|
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 =
|
|
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 =
|
|
2207
|
+
const handleChipDragEnd = useCallback9(() => {
|
|
1842
2208
|
setReorderDragSource(null);
|
|
1843
2209
|
setReorderDropTarget(null);
|
|
1844
2210
|
}, []);
|
|
1845
|
-
const handleChipDragOver =
|
|
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 =
|
|
2221
|
+
const handleChipDragLeave = useCallback9(() => {
|
|
1856
2222
|
setReorderDropTarget(null);
|
|
1857
2223
|
}, []);
|
|
1858
|
-
const handleChipDrop =
|
|
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 =
|
|
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 =
|
|
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__ */
|
|
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__ */
|
|
1903
|
-
/* @__PURE__ */
|
|
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__ */
|
|
1907
|
-
/* @__PURE__ */
|
|
1908
|
-
/* @__PURE__ */
|
|
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__ */
|
|
2283
|
+
/* @__PURE__ */ jsx5("span", { children: "Pivot Table" })
|
|
1918
2284
|
] }),
|
|
1919
|
-
/* @__PURE__ */
|
|
1920
|
-
hasActiveFilters && /* @__PURE__ */
|
|
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__ */
|
|
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__ */
|
|
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__ */
|
|
2311
|
+
/* @__PURE__ */ jsxs5("span", { className: "vpg-filter-text", children: [
|
|
1946
2312
|
"Filtered: ",
|
|
1947
|
-
/* @__PURE__ */
|
|
1948
|
-
filteredRowCount !== void 0 && totalRowCount !== void 0 && /* @__PURE__ */
|
|
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__ */
|
|
1957
|
-
/* @__PURE__ */
|
|
1958
|
-
filterTooltipDetails.map((filter) => /* @__PURE__ */
|
|
1959
|
-
/* @__PURE__ */
|
|
1960
|
-
/* @__PURE__ */
|
|
1961
|
-
filter.values.map((val, idx) => /* @__PURE__ */
|
|
1962
|
-
filter.remaining > 0 && /* @__PURE__ */
|
|
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__ */
|
|
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__ */
|
|
1981
|
-
/* @__PURE__ */
|
|
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__ */
|
|
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__ */
|
|
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__ */
|
|
2000
|
-
/* @__PURE__ */
|
|
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__ */
|
|
2010
|
-
/* @__PURE__ */
|
|
2011
|
-
/* @__PURE__ */
|
|
2012
|
-
] }) }) : /* @__PURE__ */
|
|
2013
|
-
/* @__PURE__ */
|
|
2014
|
-
/* @__PURE__ */
|
|
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__ */
|
|
2023
|
-
/* @__PURE__ */
|
|
2024
|
-
/* @__PURE__ */
|
|
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__ */
|
|
2027
|
-
rowFields.map((field, idx) => /* @__PURE__ */
|
|
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__ */
|
|
2039
|
-
/* @__PURE__ */
|
|
2040
|
-
/* @__PURE__ */
|
|
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__ */
|
|
2421
|
+
rowFields.length === 0 && /* @__PURE__ */ jsx5("span", { className: "vpg-zone-hint", children: "Drop here" })
|
|
2056
2422
|
] })
|
|
2057
2423
|
]
|
|
2058
2424
|
}
|
|
2059
2425
|
),
|
|
2060
|
-
/* @__PURE__ */
|
|
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__ */
|
|
2069
|
-
/* @__PURE__ */
|
|
2070
|
-
/* @__PURE__ */
|
|
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__ */
|
|
2073
|
-
columnFields.map((field, idx) => /* @__PURE__ */
|
|
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__ */
|
|
2085
|
-
/* @__PURE__ */
|
|
2086
|
-
/* @__PURE__ */
|
|
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__ */
|
|
2467
|
+
columnFields.length === 0 && /* @__PURE__ */ jsx5("span", { className: "vpg-zone-hint", children: "Drop here" })
|
|
2102
2468
|
] })
|
|
2103
2469
|
]
|
|
2104
2470
|
}
|
|
2105
2471
|
),
|
|
2106
|
-
/* @__PURE__ */
|
|
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__ */
|
|
2115
|
-
/* @__PURE__ */
|
|
2116
|
-
/* @__PURE__ */
|
|
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__ */
|
|
2119
|
-
valueFields.map((vf) => /* @__PURE__ */
|
|
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__ */
|
|
2125
|
-
/* @__PURE__ */
|
|
2126
|
-
/* @__PURE__ */
|
|
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__ */
|
|
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__ */
|
|
2145
|
-
/* @__PURE__ */
|
|
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__ */
|
|
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__ */
|
|
2529
|
+
/* @__PURE__ */ jsx5("span", { className: "vpg-placeholder-text", children: valueFields.length === 0 ? /* @__PURE__ */ jsxs5(Fragment3, { children: [
|
|
2164
2530
|
"Add a ",
|
|
2165
|
-
/* @__PURE__ */
|
|
2531
|
+
/* @__PURE__ */ jsx5("strong", { children: "Values" }),
|
|
2166
2532
|
" field to see your pivot table"
|
|
2167
|
-
] }) : rowFields.length === 0 && columnFields.length === 0 ? /* @__PURE__ */
|
|
2533
|
+
] }) : rowFields.length === 0 && columnFields.length === 0 ? /* @__PURE__ */ jsxs5(Fragment3, { children: [
|
|
2168
2534
|
"Add ",
|
|
2169
|
-
/* @__PURE__ */
|
|
2535
|
+
/* @__PURE__ */ jsx5("strong", { children: "Row" }),
|
|
2170
2536
|
" or ",
|
|
2171
|
-
/* @__PURE__ */
|
|
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__ */
|
|
2176
|
-
/* @__PURE__ */
|
|
2177
|
-
levelIdx === 0 && /* @__PURE__ */
|
|
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__ */
|
|
2184
|
-
/* @__PURE__ */
|
|
2185
|
-
/* @__PURE__ */
|
|
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__ */
|
|
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__ */
|
|
2196
|
-
/* @__PURE__ */
|
|
2197
|
-
levelIdx === columnHeaderCells.length - 1 && /* @__PURE__ */
|
|
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__ */
|
|
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__ */
|
|
2205
|
-
sortedRowIndices.map((sortedIdx) => /* @__PURE__ */
|
|
2206
|
-
/* @__PURE__ */
|
|
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__ */
|
|
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__ */
|
|
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__ */
|
|
2223
|
-
/* @__PURE__ */
|
|
2224
|
-
pivotResult.columnTotals.map((cell, colIdx) => /* @__PURE__ */
|
|
2225
|
-
pivotResult.rowTotals.length > 0 && /* @__PURE__ */
|
|
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__ */
|
|
2230
|
-
/* @__PURE__ */
|
|
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__ */
|
|
2237
|
-
/* @__PURE__ */
|
|
2238
|
-
/* @__PURE__ */
|
|
2239
|
-
/* @__PURE__ */
|
|
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__ */
|
|
2242
|
-
/* @__PURE__ */
|
|
2243
|
-
/* @__PURE__ */
|
|
2244
|
-
/* @__PURE__ */
|
|
2245
|
-
/* @__PURE__ */
|
|
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__ */
|
|
2248
|
-
/* @__PURE__ */
|
|
2249
|
-
/* @__PURE__ */
|
|
2250
|
-
/* @__PURE__ */
|
|
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__ */
|
|
2257
|
-
/* @__PURE__ */
|
|
2258
|
-
/* @__PURE__ */
|
|
2259
|
-
/* @__PURE__ */
|
|
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__ */
|
|
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
|
|
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 =
|
|
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] =
|
|
2309
|
-
const [globalSearchTerm, setGlobalSearchTerm] =
|
|
2310
|
-
const [showSearchInput, setShowSearchInput] =
|
|
2311
|
-
const [currentPage, setCurrentPage] =
|
|
2312
|
-
const [columnWidths, setColumnWidths] =
|
|
2313
|
-
const [resizingColumnId, setResizingColumnId] =
|
|
2314
|
-
const [resizeStartX, setResizeStartX] =
|
|
2315
|
-
const [resizeStartWidth, setResizeStartWidth] =
|
|
2316
|
-
const [gridHeight, setGridHeight] =
|
|
2317
|
-
const [isResizingVertically, setIsResizingVertically] =
|
|
2318
|
-
const [verticalResizeStartY, setVerticalResizeStartY] =
|
|
2319
|
-
const [verticalResizeStartHeight, setVerticalResizeStartHeight] =
|
|
2320
|
-
const [showCopyToast, setShowCopyToast] =
|
|
2321
|
-
const [copyToastMessage, setCopyToastMessage] =
|
|
2322
|
-
const [viewMode, setViewMode] =
|
|
2323
|
-
const [showPivotConfig, setShowPivotConfig] =
|
|
2324
|
-
const [draggingField, setDraggingField] =
|
|
2325
|
-
const [activeFilterColumn, setActiveFilterColumn] =
|
|
2326
|
-
const [filterDropdownPosition, setFilterDropdownPosition] =
|
|
2327
|
-
const [selectedCell, setSelectedCell] =
|
|
2328
|
-
const [selectionStart, setSelectionStart] =
|
|
2329
|
-
const [selectionEnd, setSelectionEnd] =
|
|
2330
|
-
const [isSelecting, setIsSelecting] =
|
|
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 =
|
|
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 =
|
|
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 =
|
|
2392
|
-
const searchFilteredData =
|
|
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 =
|
|
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 =
|
|
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
|
-
|
|
2788
|
+
useEffect7(() => {
|
|
2420
2789
|
setCurrentPage(1);
|
|
2421
2790
|
}, [columnFilters, globalSearchTerm]);
|
|
2422
|
-
const selectionBounds =
|
|
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 =
|
|
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
|
-
|
|
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 =
|
|
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
|
-
|
|
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 =
|
|
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
|
-
|
|
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 =
|
|
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 =
|
|
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 =
|
|
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 =
|
|
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
|
-
|
|
3005
|
+
useEffect7(() => {
|
|
2637
3006
|
const handleMouseUp = () => setIsSelecting(false);
|
|
2638
3007
|
document.addEventListener("mouseup", handleMouseUp);
|
|
2639
3008
|
return () => document.removeEventListener("mouseup", handleMouseUp);
|
|
2640
3009
|
}, []);
|
|
2641
|
-
|
|
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 =
|
|
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 =
|
|
3057
|
+
const closeFilterDropdown = useCallback10(() => {
|
|
2689
3058
|
setActiveFilterColumn(null);
|
|
2690
3059
|
}, []);
|
|
2691
|
-
const handleFilter =
|
|
3060
|
+
const handleFilter = useCallback10(
|
|
2692
3061
|
(columnId, values) => {
|
|
2693
3062
|
setColumnFilter(columnId, values);
|
|
2694
3063
|
},
|
|
2695
3064
|
[setColumnFilter]
|
|
2696
3065
|
);
|
|
2697
|
-
const
|
|
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 =
|
|
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 =
|
|
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__ */
|
|
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__ */
|
|
2770
|
-
/* @__PURE__ */
|
|
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__ */
|
|
2774
|
-
/* @__PURE__ */
|
|
2775
|
-
showPivot && /* @__PURE__ */
|
|
2776
|
-
/* @__PURE__ */
|
|
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__ */
|
|
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__ */
|
|
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__ */
|
|
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__ */
|
|
2816
|
-
enableSearch && /* @__PURE__ */
|
|
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__ */
|
|
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__ */
|
|
2833
|
-
/* @__PURE__ */
|
|
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__ */
|
|
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__ */
|
|
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__ */
|
|
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__ */
|
|
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__ */
|
|
2888
|
-
/* @__PURE__ */
|
|
2889
|
-
/* @__PURE__ */
|
|
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__ */
|
|
2900
|
-
/* @__PURE__ */
|
|
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__ */
|
|
3283
|
+
/* @__PURE__ */ jsxs6("span", { children: [
|
|
2909
3284
|
activeFilterCount,
|
|
2910
3285
|
" filter",
|
|
2911
3286
|
activeFilterCount > 1 ? "s" : ""
|
|
2912
3287
|
] })
|
|
2913
3288
|
] }),
|
|
2914
|
-
globalSearchTerm && /* @__PURE__ */
|
|
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__ */
|
|
2921
|
-
/* @__PURE__ */
|
|
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__ */
|
|
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__ */
|
|
2942
|
-
/* @__PURE__ */
|
|
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__ */
|
|
3325
|
+
/* @__PURE__ */ jsx6("span", { children: "Pivot configured" })
|
|
2951
3326
|
] })
|
|
2952
3327
|
] })
|
|
2953
3328
|
] }),
|
|
2954
|
-
/* @__PURE__ */
|
|
2955
|
-
viewMode === "grid" && activeFilterCount > 0 && /* @__PURE__ */
|
|
2956
|
-
/* @__PURE__ */
|
|
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__ */
|
|
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__ */
|
|
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__ */
|
|
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__ */
|
|
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__ */
|
|
3008
|
-
loading && /* @__PURE__ */
|
|
3009
|
-
/* @__PURE__ */
|
|
3010
|
-
/* @__PURE__ */
|
|
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__ */
|
|
3013
|
-
/* @__PURE__ */
|
|
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__ */
|
|
3397
|
+
/* @__PURE__ */ jsx6("span", { children: "No data available" })
|
|
3023
3398
|
] }),
|
|
3024
|
-
!loading && data.length > 0 && filteredRowCount === 0 && /* @__PURE__ */
|
|
3025
|
-
/* @__PURE__ */
|
|
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__ */
|
|
3035
|
-
/* @__PURE__ */
|
|
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__ */
|
|
3038
|
-
/* @__PURE__ */
|
|
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__ */
|
|
3054
|
-
/* @__PURE__ */
|
|
3055
|
-
/* @__PURE__ */
|
|
3056
|
-
getSortDirection(colId) && /* @__PURE__ */
|
|
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__ */
|
|
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__ */
|
|
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__ */
|
|
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__ */
|
|
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__ */
|
|
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__ */
|
|
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__ */
|
|
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__ */
|
|
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__ */
|
|
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__ */
|
|
3153
|
-
showPivotConfig && canUsePivot && /* @__PURE__ */
|
|
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__ */
|
|
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__ */
|
|
3208
|
-
/* @__PURE__ */
|
|
3209
|
-
/* @__PURE__ */
|
|
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__ */
|
|
3215
|
-
/* @__PURE__ */
|
|
3216
|
-
totalSearchedRows !== totalRowCount && /* @__PURE__ */
|
|
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__ */
|
|
3596
|
+
] }) : filteredRowCount === totalRowCount && totalSearchedRows === totalRowCount ? /* @__PURE__ */ jsxs6("span", { children: [
|
|
3222
3597
|
totalRowCount.toLocaleString(),
|
|
3223
3598
|
" records"
|
|
3224
|
-
] }) : /* @__PURE__ */
|
|
3225
|
-
/* @__PURE__ */
|
|
3226
|
-
/* @__PURE__ */
|
|
3227
|
-
/* @__PURE__ */
|
|
3228
|
-
/* @__PURE__ */
|
|
3229
|
-
] }) : /* @__PURE__ */
|
|
3230
|
-
/* @__PURE__ */
|
|
3231
|
-
/* @__PURE__ */
|
|
3232
|
-
/* @__PURE__ */
|
|
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__ */
|
|
3238
|
-
/* @__PURE__ */
|
|
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__ */
|
|
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__ */
|
|
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__ */
|
|
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__ */
|
|
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__ */
|
|
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__ */
|
|
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__ */
|
|
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__ */
|
|
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__ */
|
|
3314
|
-
/* @__PURE__ */
|
|
3315
|
-
/* @__PURE__ */
|
|
3316
|
-
/* @__PURE__ */
|
|
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__ */
|
|
3319
|
-
/* @__PURE__ */
|
|
3320
|
-
/* @__PURE__ */
|
|
3321
|
-
/* @__PURE__ */
|
|
3322
|
-
/* @__PURE__ */
|
|
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__ */
|
|
3325
|
-
/* @__PURE__ */
|
|
3326
|
-
/* @__PURE__ */
|
|
3327
|
-
/* @__PURE__ */
|
|
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__ */
|
|
3332
|
-
/* @__PURE__ */
|
|
3333
|
-
/* @__PURE__ */
|
|
3334
|
-
/* @__PURE__ */
|
|
3335
|
-
] }) : showWatermark ? /* @__PURE__ */
|
|
3336
|
-
/* @__PURE__ */
|
|
3337
|
-
/* @__PURE__ */
|
|
3338
|
-
/* @__PURE__ */
|
|
3339
|
-
/* @__PURE__ */
|
|
3340
|
-
/* @__PURE__ */
|
|
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__ */
|
|
3346
|
-
/* @__PURE__ */
|
|
3347
|
-
/* @__PURE__ */
|
|
3348
|
-
/* @__PURE__ */
|
|
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__ */
|
|
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__ */
|
|
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
|
}
|