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