@smallwebco/tinypivot-react 1.0.24 → 1.0.26
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 +687 -376
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +9 -2
- package/dist/index.d.ts +9 -2
- package/dist/index.js +687 -374
- package/dist/index.js.map +1 -1
- package/dist/style.css +292 -14
- package/package.json +2 -2
package/dist/index.cjs
CHANGED
|
@@ -45,8 +45,8 @@ __export(index_exports, {
|
|
|
45
45
|
module.exports = __toCommonJS(index_exports);
|
|
46
46
|
|
|
47
47
|
// src/components/DataGrid.tsx
|
|
48
|
-
var
|
|
49
|
-
var
|
|
48
|
+
var import_react9 = require("react");
|
|
49
|
+
var import_react_dom2 = require("react-dom");
|
|
50
50
|
|
|
51
51
|
// src/hooks/useExcelGrid.ts
|
|
52
52
|
var import_react = require("react");
|
|
@@ -312,6 +312,7 @@ function usePivotTable(data) {
|
|
|
312
312
|
const [valueFields, setValueFields] = (0, import_react3.useState)([]);
|
|
313
313
|
const [showRowTotals, setShowRowTotals] = (0, import_react3.useState)(true);
|
|
314
314
|
const [showColumnTotals, setShowColumnTotals] = (0, import_react3.useState)(true);
|
|
315
|
+
const [calculatedFields, setCalculatedFields] = (0, import_react3.useState)(() => (0, import_tinypivot_core3.loadCalculatedFields)());
|
|
315
316
|
const [currentStorageKey, setCurrentStorageKey] = (0, import_react3.useState)(null);
|
|
316
317
|
const availableFields = (0, import_react3.useMemo)(() => {
|
|
317
318
|
return (0, import_tinypivot_core3.computeAvailableFields)(data);
|
|
@@ -336,9 +337,10 @@ function usePivotTable(data) {
|
|
|
336
337
|
columnFields,
|
|
337
338
|
valueFields,
|
|
338
339
|
showRowTotals,
|
|
339
|
-
showColumnTotals
|
|
340
|
+
showColumnTotals,
|
|
341
|
+
calculatedFields
|
|
340
342
|
});
|
|
341
|
-
}, [data, isConfigured, canUsePivot, rowFields, columnFields, valueFields, showRowTotals, showColumnTotals]);
|
|
343
|
+
}, [data, isConfigured, canUsePivot, rowFields, columnFields, valueFields, showRowTotals, showColumnTotals, calculatedFields]);
|
|
342
344
|
(0, import_react3.useEffect)(() => {
|
|
343
345
|
if (data.length === 0) return;
|
|
344
346
|
const newKeys = Object.keys(data[0]);
|
|
@@ -352,6 +354,9 @@ function usePivotTable(data) {
|
|
|
352
354
|
setValueFields(savedConfig.valueFields);
|
|
353
355
|
setShowRowTotals(savedConfig.showRowTotals);
|
|
354
356
|
setShowColumnTotals(savedConfig.showColumnTotals);
|
|
357
|
+
if (savedConfig.calculatedFields) {
|
|
358
|
+
setCalculatedFields(savedConfig.calculatedFields);
|
|
359
|
+
}
|
|
355
360
|
} else {
|
|
356
361
|
const currentConfig = {
|
|
357
362
|
rowFields,
|
|
@@ -375,10 +380,11 @@ function usePivotTable(data) {
|
|
|
375
380
|
columnFields,
|
|
376
381
|
valueFields,
|
|
377
382
|
showRowTotals,
|
|
378
|
-
showColumnTotals
|
|
383
|
+
showColumnTotals,
|
|
384
|
+
calculatedFields
|
|
379
385
|
};
|
|
380
386
|
(0, import_tinypivot_core3.savePivotConfig)(currentStorageKey, config);
|
|
381
|
-
}, [currentStorageKey, rowFields, columnFields, valueFields, showRowTotals, showColumnTotals]);
|
|
387
|
+
}, [currentStorageKey, rowFields, columnFields, valueFields, showRowTotals, showColumnTotals, calculatedFields]);
|
|
382
388
|
const addRowField = (0, import_react3.useCallback)(
|
|
383
389
|
(field) => {
|
|
384
390
|
if (!requirePro("Pivot Table - Row Fields")) return;
|
|
@@ -457,6 +463,27 @@ function usePivotTable(data) {
|
|
|
457
463
|
setValueFields([{ field: numericFields[0].field, aggregation: "sum" }]);
|
|
458
464
|
}
|
|
459
465
|
}, [availableFields, requirePro]);
|
|
466
|
+
const addCalculatedField = (0, import_react3.useCallback)((field) => {
|
|
467
|
+
setCalculatedFields((prev) => {
|
|
468
|
+
const existing = prev.findIndex((f) => f.id === field.id);
|
|
469
|
+
let updated;
|
|
470
|
+
if (existing >= 0) {
|
|
471
|
+
updated = [...prev.slice(0, existing), field, ...prev.slice(existing + 1)];
|
|
472
|
+
} else {
|
|
473
|
+
updated = [...prev, field];
|
|
474
|
+
}
|
|
475
|
+
(0, import_tinypivot_core3.saveCalculatedFields)(updated);
|
|
476
|
+
return updated;
|
|
477
|
+
});
|
|
478
|
+
}, []);
|
|
479
|
+
const removeCalculatedField = (0, import_react3.useCallback)((id) => {
|
|
480
|
+
setCalculatedFields((prev) => {
|
|
481
|
+
const updated = prev.filter((f) => f.id !== id);
|
|
482
|
+
(0, import_tinypivot_core3.saveCalculatedFields)(updated);
|
|
483
|
+
return updated;
|
|
484
|
+
});
|
|
485
|
+
setValueFields((prev) => prev.filter((v) => v.field !== `calc:${id}`));
|
|
486
|
+
}, []);
|
|
460
487
|
return {
|
|
461
488
|
// State
|
|
462
489
|
rowFields,
|
|
@@ -464,6 +491,7 @@ function usePivotTable(data) {
|
|
|
464
491
|
valueFields,
|
|
465
492
|
showRowTotals,
|
|
466
493
|
showColumnTotals,
|
|
494
|
+
calculatedFields,
|
|
467
495
|
// Computed
|
|
468
496
|
availableFields,
|
|
469
497
|
unassignedFields,
|
|
@@ -482,7 +510,9 @@ function usePivotTable(data) {
|
|
|
482
510
|
setShowColumnTotals,
|
|
483
511
|
autoSuggestConfig,
|
|
484
512
|
setRowFields,
|
|
485
|
-
setColumnFields
|
|
513
|
+
setColumnFields,
|
|
514
|
+
addCalculatedField,
|
|
515
|
+
removeCalculatedField
|
|
486
516
|
};
|
|
487
517
|
}
|
|
488
518
|
|
|
@@ -954,10 +984,197 @@ function ColumnFilter({
|
|
|
954
984
|
}
|
|
955
985
|
|
|
956
986
|
// src/components/PivotConfig.tsx
|
|
987
|
+
var import_react7 = require("react");
|
|
988
|
+
var import_tinypivot_core6 = require("@smallwebco/tinypivot-core");
|
|
989
|
+
|
|
990
|
+
// src/components/CalculatedFieldModal.tsx
|
|
957
991
|
var import_react6 = require("react");
|
|
992
|
+
var import_react_dom = require("react-dom");
|
|
958
993
|
var import_tinypivot_core5 = require("@smallwebco/tinypivot-core");
|
|
959
994
|
var import_jsx_runtime2 = require("react/jsx-runtime");
|
|
960
|
-
function
|
|
995
|
+
function CalculatedFieldModal({
|
|
996
|
+
show,
|
|
997
|
+
availableFields,
|
|
998
|
+
existingField,
|
|
999
|
+
onClose,
|
|
1000
|
+
onSave
|
|
1001
|
+
}) {
|
|
1002
|
+
const [name, setName] = (0, import_react6.useState)("");
|
|
1003
|
+
const [formula, setFormula] = (0, import_react6.useState)("");
|
|
1004
|
+
const [formatAs, setFormatAs] = (0, import_react6.useState)("number");
|
|
1005
|
+
const [decimals, setDecimals] = (0, import_react6.useState)(2);
|
|
1006
|
+
const [error, setError] = (0, import_react6.useState)(null);
|
|
1007
|
+
(0, import_react6.useEffect)(() => {
|
|
1008
|
+
if (show) {
|
|
1009
|
+
if (existingField) {
|
|
1010
|
+
setName(existingField.name);
|
|
1011
|
+
setFormula(existingField.formula);
|
|
1012
|
+
setFormatAs(existingField.formatAs || "number");
|
|
1013
|
+
setDecimals(existingField.decimals ?? 2);
|
|
1014
|
+
} else {
|
|
1015
|
+
setName("");
|
|
1016
|
+
setFormula("");
|
|
1017
|
+
setFormatAs("number");
|
|
1018
|
+
setDecimals(2);
|
|
1019
|
+
}
|
|
1020
|
+
setError(null);
|
|
1021
|
+
}
|
|
1022
|
+
}, [show, existingField]);
|
|
1023
|
+
const validationError = (0, import_react6.useMemo)(() => {
|
|
1024
|
+
if (!formula.trim()) return null;
|
|
1025
|
+
return (0, import_tinypivot_core5.validateSimpleFormula)(formula, availableFields);
|
|
1026
|
+
}, [formula, availableFields]);
|
|
1027
|
+
const insertField = (0, import_react6.useCallback)((field) => {
|
|
1028
|
+
setFormula((prev) => {
|
|
1029
|
+
if (prev.trim() && !prev.endsWith(" ")) {
|
|
1030
|
+
return prev + " " + field;
|
|
1031
|
+
}
|
|
1032
|
+
return prev + field;
|
|
1033
|
+
});
|
|
1034
|
+
}, []);
|
|
1035
|
+
const insertOperator = (0, import_react6.useCallback)((op) => {
|
|
1036
|
+
setFormula((prev) => {
|
|
1037
|
+
if (prev.trim() && !prev.endsWith(" ")) {
|
|
1038
|
+
return prev + " " + op + " ";
|
|
1039
|
+
}
|
|
1040
|
+
return prev + op + " ";
|
|
1041
|
+
});
|
|
1042
|
+
}, []);
|
|
1043
|
+
const handleSave = (0, import_react6.useCallback)(() => {
|
|
1044
|
+
if (!name.trim()) {
|
|
1045
|
+
setError("Name is required");
|
|
1046
|
+
return;
|
|
1047
|
+
}
|
|
1048
|
+
const validationResult = (0, import_tinypivot_core5.validateSimpleFormula)(formula, availableFields);
|
|
1049
|
+
if (validationResult) {
|
|
1050
|
+
setError(validationResult);
|
|
1051
|
+
return;
|
|
1052
|
+
}
|
|
1053
|
+
const field = {
|
|
1054
|
+
id: existingField?.id || `calc_${Date.now()}`,
|
|
1055
|
+
name: name.trim(),
|
|
1056
|
+
formula: formula.trim(),
|
|
1057
|
+
formatAs,
|
|
1058
|
+
decimals
|
|
1059
|
+
};
|
|
1060
|
+
onSave(field);
|
|
1061
|
+
onClose();
|
|
1062
|
+
}, [name, formula, formatAs, decimals, existingField, availableFields, onSave, onClose]);
|
|
1063
|
+
const handleOverlayClick = (0, import_react6.useCallback)((e) => {
|
|
1064
|
+
if (e.target === e.currentTarget) {
|
|
1065
|
+
onClose();
|
|
1066
|
+
}
|
|
1067
|
+
}, [onClose]);
|
|
1068
|
+
if (!show) return null;
|
|
1069
|
+
const modalContent = /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { className: "vpg-modal-overlay", onClick: handleOverlayClick, children: /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "vpg-modal", children: [
|
|
1070
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "vpg-modal-header", children: [
|
|
1071
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("h3", { children: [
|
|
1072
|
+
existingField ? "Edit" : "Create",
|
|
1073
|
+
" Calculated Field"
|
|
1074
|
+
] }),
|
|
1075
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("button", { className: "vpg-modal-close", onClick: onClose, children: "\xD7" })
|
|
1076
|
+
] }),
|
|
1077
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "vpg-modal-body", children: [
|
|
1078
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "vpg-form-group", children: [
|
|
1079
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("label", { className: "vpg-label", children: "Name" }),
|
|
1080
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
|
|
1081
|
+
"input",
|
|
1082
|
+
{
|
|
1083
|
+
type: "text",
|
|
1084
|
+
className: "vpg-input",
|
|
1085
|
+
placeholder: "e.g., Profit Margin %",
|
|
1086
|
+
value: name,
|
|
1087
|
+
onChange: (e) => setName(e.target.value)
|
|
1088
|
+
}
|
|
1089
|
+
)
|
|
1090
|
+
] }),
|
|
1091
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "vpg-form-group", children: [
|
|
1092
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("label", { className: "vpg-label", children: "Formula" }),
|
|
1093
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
|
|
1094
|
+
"textarea",
|
|
1095
|
+
{
|
|
1096
|
+
className: "vpg-textarea",
|
|
1097
|
+
placeholder: "e.g., revenue / units",
|
|
1098
|
+
rows: 2,
|
|
1099
|
+
value: formula,
|
|
1100
|
+
onChange: (e) => setFormula(e.target.value)
|
|
1101
|
+
}
|
|
1102
|
+
),
|
|
1103
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { className: "vpg-formula-hint", children: "Use field names with math operators: + - * / ( )" }),
|
|
1104
|
+
validationError && /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { className: "vpg-error", children: validationError })
|
|
1105
|
+
] }),
|
|
1106
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "vpg-form-group", children: [
|
|
1107
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("label", { className: "vpg-label-small", children: "Operators" }),
|
|
1108
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "vpg-button-group", children: [
|
|
1109
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("button", { className: "vpg-insert-btn vpg-op-btn", onClick: () => insertOperator("+"), children: "+" }),
|
|
1110
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("button", { className: "vpg-insert-btn vpg-op-btn", onClick: () => insertOperator("-"), children: "\u2212" }),
|
|
1111
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("button", { className: "vpg-insert-btn vpg-op-btn", onClick: () => insertOperator("*"), children: "\xD7" }),
|
|
1112
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("button", { className: "vpg-insert-btn vpg-op-btn", onClick: () => insertOperator("/"), children: "\xF7" }),
|
|
1113
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("button", { className: "vpg-insert-btn vpg-op-btn", onClick: () => insertOperator("("), children: "(" }),
|
|
1114
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("button", { className: "vpg-insert-btn vpg-op-btn", onClick: () => insertOperator(")"), children: ")" })
|
|
1115
|
+
] })
|
|
1116
|
+
] }),
|
|
1117
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "vpg-form-group", children: [
|
|
1118
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("label", { className: "vpg-label-small", children: "Insert Field" }),
|
|
1119
|
+
availableFields.length > 0 ? /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { className: "vpg-button-group vpg-field-buttons", children: availableFields.map((field) => /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
|
|
1120
|
+
"button",
|
|
1121
|
+
{
|
|
1122
|
+
className: "vpg-insert-btn vpg-field-btn",
|
|
1123
|
+
onClick: () => insertField(field),
|
|
1124
|
+
children: field
|
|
1125
|
+
},
|
|
1126
|
+
field
|
|
1127
|
+
)) }) : /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { className: "vpg-no-fields", children: "No numeric fields available" })
|
|
1128
|
+
] }),
|
|
1129
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "vpg-form-row", children: [
|
|
1130
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "vpg-form-group vpg-form-group-half", children: [
|
|
1131
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("label", { className: "vpg-label", children: "Format As" }),
|
|
1132
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(
|
|
1133
|
+
"select",
|
|
1134
|
+
{
|
|
1135
|
+
className: "vpg-select",
|
|
1136
|
+
value: formatAs,
|
|
1137
|
+
onChange: (e) => setFormatAs(e.target.value),
|
|
1138
|
+
children: [
|
|
1139
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("option", { value: "number", children: "Number" }),
|
|
1140
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("option", { value: "percent", children: "Percentage" }),
|
|
1141
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("option", { value: "currency", children: "Currency ($)" })
|
|
1142
|
+
]
|
|
1143
|
+
}
|
|
1144
|
+
)
|
|
1145
|
+
] }),
|
|
1146
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "vpg-form-group vpg-form-group-half", children: [
|
|
1147
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("label", { className: "vpg-label", children: "Decimals" }),
|
|
1148
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
|
|
1149
|
+
"input",
|
|
1150
|
+
{
|
|
1151
|
+
type: "number",
|
|
1152
|
+
className: "vpg-input",
|
|
1153
|
+
min: 0,
|
|
1154
|
+
max: 6,
|
|
1155
|
+
value: decimals,
|
|
1156
|
+
onChange: (e) => setDecimals(Number(e.target.value))
|
|
1157
|
+
}
|
|
1158
|
+
)
|
|
1159
|
+
] })
|
|
1160
|
+
] }),
|
|
1161
|
+
error && /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { className: "vpg-error vpg-error-box", children: error })
|
|
1162
|
+
] }),
|
|
1163
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "vpg-modal-footer", children: [
|
|
1164
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("button", { className: "vpg-btn vpg-btn-secondary", onClick: onClose, children: "Cancel" }),
|
|
1165
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("button", { className: "vpg-btn vpg-btn-primary", onClick: handleSave, children: [
|
|
1166
|
+
existingField ? "Update" : "Add",
|
|
1167
|
+
" Field"
|
|
1168
|
+
] })
|
|
1169
|
+
] })
|
|
1170
|
+
] }) });
|
|
1171
|
+
return (0, import_react_dom.createPortal)(modalContent, document.body);
|
|
1172
|
+
}
|
|
1173
|
+
|
|
1174
|
+
// src/components/PivotConfig.tsx
|
|
1175
|
+
var import_jsx_runtime3 = require("react/jsx-runtime");
|
|
1176
|
+
function getFieldIcon(type, isCalculated) {
|
|
1177
|
+
if (isCalculated) return "\u0192";
|
|
961
1178
|
switch (type) {
|
|
962
1179
|
case "number":
|
|
963
1180
|
return "#";
|
|
@@ -975,7 +1192,9 @@ function PivotConfig({
|
|
|
975
1192
|
columnFields,
|
|
976
1193
|
valueFields,
|
|
977
1194
|
showRowTotals,
|
|
1195
|
+
calculatedFields,
|
|
978
1196
|
onShowRowTotalsChange,
|
|
1197
|
+
onShowColumnTotalsChange,
|
|
979
1198
|
onClearConfig,
|
|
980
1199
|
onAutoSuggest,
|
|
981
1200
|
onDragStart,
|
|
@@ -985,35 +1204,70 @@ function PivotConfig({
|
|
|
985
1204
|
onRemoveColumnField,
|
|
986
1205
|
onRemoveValueField,
|
|
987
1206
|
onAddRowField,
|
|
988
|
-
onAddColumnField
|
|
1207
|
+
onAddColumnField,
|
|
1208
|
+
onAddCalculatedField,
|
|
1209
|
+
onRemoveCalculatedField,
|
|
1210
|
+
onUpdateCalculatedField
|
|
989
1211
|
}) {
|
|
990
|
-
const
|
|
991
|
-
const [
|
|
992
|
-
const
|
|
1212
|
+
const [fieldSearch, setFieldSearch] = (0, import_react7.useState)("");
|
|
1213
|
+
const [showCalcModal, setShowCalcModal] = (0, import_react7.useState)(false);
|
|
1214
|
+
const [editingCalcField, setEditingCalcField] = (0, import_react7.useState)(null);
|
|
1215
|
+
const numericFieldNames = (0, import_react7.useMemo)(
|
|
1216
|
+
() => availableFields.filter((f) => f.isNumeric).map((f) => f.field),
|
|
1217
|
+
[availableFields]
|
|
1218
|
+
);
|
|
1219
|
+
const calculatedFieldsAsStats = (0, import_react7.useMemo)(() => {
|
|
1220
|
+
if (!calculatedFields) return [];
|
|
1221
|
+
return calculatedFields.map((calc) => ({
|
|
1222
|
+
field: `calc:${calc.id}`,
|
|
1223
|
+
type: "number",
|
|
1224
|
+
uniqueCount: 0,
|
|
1225
|
+
isNumeric: true,
|
|
1226
|
+
isCalculated: true,
|
|
1227
|
+
calcId: calc.id,
|
|
1228
|
+
calcName: calc.name,
|
|
1229
|
+
calcFormula: calc.formula
|
|
1230
|
+
}));
|
|
1231
|
+
}, [calculatedFields]);
|
|
1232
|
+
const allAvailableFields = (0, import_react7.useMemo)(() => [
|
|
1233
|
+
...availableFields.map((f) => ({ ...f, isCalculated: false })),
|
|
1234
|
+
...calculatedFieldsAsStats
|
|
1235
|
+
], [availableFields, calculatedFieldsAsStats]);
|
|
1236
|
+
const assignedFields = (0, import_react7.useMemo)(() => {
|
|
993
1237
|
const rowSet = new Set(rowFields);
|
|
994
1238
|
const colSet = new Set(columnFields);
|
|
995
1239
|
const valueMap = new Map(valueFields.map((v) => [v.field, v]));
|
|
996
|
-
return
|
|
1240
|
+
return allAvailableFields.filter((f) => rowSet.has(f.field) || colSet.has(f.field) || valueMap.has(f.field)).map((f) => ({
|
|
997
1241
|
...f,
|
|
998
1242
|
assignedTo: rowSet.has(f.field) ? "row" : colSet.has(f.field) ? "column" : "value",
|
|
999
1243
|
valueConfig: valueMap.get(f.field)
|
|
1000
1244
|
}));
|
|
1001
|
-
}, [
|
|
1002
|
-
const unassignedFields = (0,
|
|
1245
|
+
}, [allAvailableFields, rowFields, columnFields, valueFields]);
|
|
1246
|
+
const unassignedFields = (0, import_react7.useMemo)(() => {
|
|
1003
1247
|
const rowSet = new Set(rowFields);
|
|
1004
1248
|
const colSet = new Set(columnFields);
|
|
1005
1249
|
const valSet = new Set(valueFields.map((v) => v.field));
|
|
1006
|
-
return
|
|
1250
|
+
return allAvailableFields.filter(
|
|
1007
1251
|
(f) => !rowSet.has(f.field) && !colSet.has(f.field) && !valSet.has(f.field)
|
|
1008
1252
|
);
|
|
1009
|
-
}, [
|
|
1010
|
-
const filteredUnassignedFields = (0,
|
|
1253
|
+
}, [allAvailableFields, rowFields, columnFields, valueFields]);
|
|
1254
|
+
const filteredUnassignedFields = (0, import_react7.useMemo)(() => {
|
|
1011
1255
|
if (!fieldSearch.trim()) return unassignedFields;
|
|
1012
1256
|
const search = fieldSearch.toLowerCase().trim();
|
|
1013
|
-
return unassignedFields.filter((f) =>
|
|
1257
|
+
return unassignedFields.filter((f) => {
|
|
1258
|
+
const fieldName = f.field.toLowerCase();
|
|
1259
|
+
const displayName = f.isCalculated && f.calcName ? f.calcName.toLowerCase() : "";
|
|
1260
|
+
return fieldName.includes(search) || displayName.includes(search);
|
|
1261
|
+
});
|
|
1014
1262
|
}, [unassignedFields, fieldSearch]);
|
|
1015
1263
|
const assignedCount = assignedFields.length;
|
|
1016
|
-
const
|
|
1264
|
+
const getFieldDisplayName = (0, import_react7.useCallback)((field) => {
|
|
1265
|
+
if (field.isCalculated && field.calcName) {
|
|
1266
|
+
return field.calcName;
|
|
1267
|
+
}
|
|
1268
|
+
return field.field;
|
|
1269
|
+
}, []);
|
|
1270
|
+
const handleDragStart = (0, import_react7.useCallback)(
|
|
1017
1271
|
(field, event) => {
|
|
1018
1272
|
event.dataTransfer?.setData("text/plain", field);
|
|
1019
1273
|
event.dataTransfer.effectAllowed = "move";
|
|
@@ -1021,13 +1275,13 @@ function PivotConfig({
|
|
|
1021
1275
|
},
|
|
1022
1276
|
[onDragStart]
|
|
1023
1277
|
);
|
|
1024
|
-
const handleAggregationChange = (0,
|
|
1278
|
+
const handleAggregationChange = (0, import_react7.useCallback)(
|
|
1025
1279
|
(field, currentAgg, newAgg) => {
|
|
1026
1280
|
onUpdateAggregation(field, currentAgg, newAgg);
|
|
1027
1281
|
},
|
|
1028
1282
|
[onUpdateAggregation]
|
|
1029
1283
|
);
|
|
1030
|
-
const toggleRowColumn = (0,
|
|
1284
|
+
const toggleRowColumn = (0, import_react7.useCallback)(
|
|
1031
1285
|
(field, currentAssignment) => {
|
|
1032
1286
|
if (currentAssignment === "row") {
|
|
1033
1287
|
onRemoveRowField(field);
|
|
@@ -1039,7 +1293,7 @@ function PivotConfig({
|
|
|
1039
1293
|
},
|
|
1040
1294
|
[onRemoveRowField, onAddColumnField, onRemoveColumnField, onAddRowField]
|
|
1041
1295
|
);
|
|
1042
|
-
const removeField = (0,
|
|
1296
|
+
const removeField = (0, import_react7.useCallback)(
|
|
1043
1297
|
(field, assignedTo, valueConfig) => {
|
|
1044
1298
|
if (assignedTo === "row") {
|
|
1045
1299
|
onRemoveRowField(field);
|
|
@@ -1051,10 +1305,31 @@ function PivotConfig({
|
|
|
1051
1305
|
},
|
|
1052
1306
|
[onRemoveRowField, onRemoveColumnField, onRemoveValueField]
|
|
1053
1307
|
);
|
|
1054
|
-
|
|
1055
|
-
|
|
1056
|
-
|
|
1057
|
-
|
|
1308
|
+
const handleTotalsToggle = (0, import_react7.useCallback)((checked) => {
|
|
1309
|
+
onShowRowTotalsChange(checked);
|
|
1310
|
+
onShowColumnTotalsChange(checked);
|
|
1311
|
+
}, [onShowRowTotalsChange, onShowColumnTotalsChange]);
|
|
1312
|
+
const openCalcModal = (0, import_react7.useCallback)((field) => {
|
|
1313
|
+
setEditingCalcField(field || null);
|
|
1314
|
+
setShowCalcModal(true);
|
|
1315
|
+
}, []);
|
|
1316
|
+
const handleSaveCalcField = (0, import_react7.useCallback)((field) => {
|
|
1317
|
+
if (editingCalcField && onUpdateCalculatedField) {
|
|
1318
|
+
onUpdateCalculatedField(field);
|
|
1319
|
+
} else if (onAddCalculatedField) {
|
|
1320
|
+
onAddCalculatedField(field);
|
|
1321
|
+
}
|
|
1322
|
+
setShowCalcModal(false);
|
|
1323
|
+
setEditingCalcField(null);
|
|
1324
|
+
}, [editingCalcField, onAddCalculatedField, onUpdateCalculatedField]);
|
|
1325
|
+
const handleCloseCalcModal = (0, import_react7.useCallback)(() => {
|
|
1326
|
+
setShowCalcModal(false);
|
|
1327
|
+
setEditingCalcField(null);
|
|
1328
|
+
}, []);
|
|
1329
|
+
return /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { className: "vpg-pivot-config", children: [
|
|
1330
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { className: "vpg-config-header", children: [
|
|
1331
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("h3", { className: "vpg-config-title", children: [
|
|
1332
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("svg", { className: "vpg-icon", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
|
|
1058
1333
|
"path",
|
|
1059
1334
|
{
|
|
1060
1335
|
strokeLinecap: "round",
|
|
@@ -1065,13 +1340,13 @@ function PivotConfig({
|
|
|
1065
1340
|
) }),
|
|
1066
1341
|
"Fields"
|
|
1067
1342
|
] }),
|
|
1068
|
-
/* @__PURE__ */ (0,
|
|
1343
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("div", { className: "vpg-header-actions", children: assignedCount > 0 && /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
|
|
1069
1344
|
"button",
|
|
1070
1345
|
{
|
|
1071
1346
|
className: "vpg-action-btn vpg-clear-btn",
|
|
1072
1347
|
title: "Clear all",
|
|
1073
1348
|
onClick: onClearConfig,
|
|
1074
|
-
children: /* @__PURE__ */ (0,
|
|
1349
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("svg", { className: "vpg-icon-sm", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
|
|
1075
1350
|
"path",
|
|
1076
1351
|
{
|
|
1077
1352
|
strokeLinecap: "round",
|
|
@@ -1083,23 +1358,23 @@ function PivotConfig({
|
|
|
1083
1358
|
}
|
|
1084
1359
|
) })
|
|
1085
1360
|
] }),
|
|
1086
|
-
assignedCount > 0 && /* @__PURE__ */ (0,
|
|
1087
|
-
/* @__PURE__ */ (0,
|
|
1088
|
-
/* @__PURE__ */ (0,
|
|
1361
|
+
assignedCount > 0 && /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { className: "vpg-assigned-section", children: [
|
|
1362
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("div", { className: "vpg-section-label", children: "Active" }),
|
|
1363
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("div", { className: "vpg-assigned-list", children: assignedFields.map((field) => /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(
|
|
1089
1364
|
"div",
|
|
1090
1365
|
{
|
|
1091
|
-
className: `vpg-assigned-item vpg-type-${field.assignedTo}`,
|
|
1092
|
-
title: field.field,
|
|
1366
|
+
className: `vpg-assigned-item vpg-type-${field.assignedTo}${field.isCalculated ? " vpg-type-calc" : ""}`,
|
|
1367
|
+
title: field.isCalculated ? field.calcFormula : field.field,
|
|
1093
1368
|
draggable: true,
|
|
1094
1369
|
onDragStart: (e) => handleDragStart(field.field, e),
|
|
1095
1370
|
onDragEnd,
|
|
1096
1371
|
children: [
|
|
1097
|
-
/* @__PURE__ */ (0,
|
|
1098
|
-
/* @__PURE__ */ (0,
|
|
1099
|
-
/* @__PURE__ */ (0,
|
|
1372
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { className: "vpg-item-main", children: [
|
|
1373
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.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") }),
|
|
1374
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("span", { className: "vpg-item-name", children: getFieldDisplayName(field) })
|
|
1100
1375
|
] }),
|
|
1101
|
-
/* @__PURE__ */ (0,
|
|
1102
|
-
(field.assignedTo === "row" || field.assignedTo === "column") && /* @__PURE__ */ (0,
|
|
1376
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { className: "vpg-item-actions", children: [
|
|
1377
|
+
(field.assignedTo === "row" || field.assignedTo === "column") && /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
|
|
1103
1378
|
"button",
|
|
1104
1379
|
{
|
|
1105
1380
|
className: "vpg-toggle-btn",
|
|
@@ -1108,14 +1383,14 @@ function PivotConfig({
|
|
|
1108
1383
|
e.stopPropagation();
|
|
1109
1384
|
toggleRowColumn(field.field, field.assignedTo);
|
|
1110
1385
|
},
|
|
1111
|
-
children: /* @__PURE__ */ (0,
|
|
1386
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
|
|
1112
1387
|
"svg",
|
|
1113
1388
|
{
|
|
1114
1389
|
className: "vpg-icon-xs",
|
|
1115
1390
|
fill: "none",
|
|
1116
1391
|
stroke: "currentColor",
|
|
1117
1392
|
viewBox: "0 0 24 24",
|
|
1118
|
-
children: /* @__PURE__ */ (0,
|
|
1393
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
|
|
1119
1394
|
"path",
|
|
1120
1395
|
{
|
|
1121
1396
|
strokeLinecap: "round",
|
|
@@ -1128,7 +1403,7 @@ function PivotConfig({
|
|
|
1128
1403
|
)
|
|
1129
1404
|
}
|
|
1130
1405
|
),
|
|
1131
|
-
field.assignedTo === "value" && field.valueConfig && /* @__PURE__ */ (0,
|
|
1406
|
+
field.assignedTo === "value" && field.valueConfig && /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
|
|
1132
1407
|
"select",
|
|
1133
1408
|
{
|
|
1134
1409
|
className: "vpg-agg-select",
|
|
@@ -1142,14 +1417,14 @@ function PivotConfig({
|
|
|
1142
1417
|
);
|
|
1143
1418
|
},
|
|
1144
1419
|
onClick: (e) => e.stopPropagation(),
|
|
1145
|
-
children:
|
|
1420
|
+
children: import_tinypivot_core6.AGGREGATION_OPTIONS.map((agg) => /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("option", { value: agg.value, children: [
|
|
1146
1421
|
agg.symbol,
|
|
1147
1422
|
" ",
|
|
1148
1423
|
agg.label
|
|
1149
1424
|
] }, agg.value))
|
|
1150
1425
|
}
|
|
1151
1426
|
),
|
|
1152
|
-
/* @__PURE__ */ (0,
|
|
1427
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
|
|
1153
1428
|
"button",
|
|
1154
1429
|
{
|
|
1155
1430
|
className: "vpg-remove-btn",
|
|
@@ -1167,13 +1442,13 @@ function PivotConfig({
|
|
|
1167
1442
|
field.field
|
|
1168
1443
|
)) })
|
|
1169
1444
|
] }),
|
|
1170
|
-
/* @__PURE__ */ (0,
|
|
1171
|
-
/* @__PURE__ */ (0,
|
|
1445
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { className: "vpg-unassigned-section", children: [
|
|
1446
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("div", { className: "vpg-section-header", children: /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { className: "vpg-section-label", children: [
|
|
1172
1447
|
"Available ",
|
|
1173
|
-
/* @__PURE__ */ (0,
|
|
1448
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("span", { className: "vpg-count", children: unassignedFields.length })
|
|
1174
1449
|
] }) }),
|
|
1175
|
-
/* @__PURE__ */ (0,
|
|
1176
|
-
/* @__PURE__ */ (0,
|
|
1450
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { className: "vpg-field-search", children: [
|
|
1451
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("svg", { className: "vpg-search-icon", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
|
|
1177
1452
|
"path",
|
|
1178
1453
|
{
|
|
1179
1454
|
strokeLinecap: "round",
|
|
@@ -1182,7 +1457,7 @@ function PivotConfig({
|
|
|
1182
1457
|
d: "M21 21l-6-6m2-5a7 7 0 11-14 0 7 7 0 0114 0z"
|
|
1183
1458
|
}
|
|
1184
1459
|
) }),
|
|
1185
|
-
/* @__PURE__ */ (0,
|
|
1460
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
|
|
1186
1461
|
"input",
|
|
1187
1462
|
{
|
|
1188
1463
|
type: "text",
|
|
@@ -1192,7 +1467,7 @@ function PivotConfig({
|
|
|
1192
1467
|
className: "vpg-search-input"
|
|
1193
1468
|
}
|
|
1194
1469
|
),
|
|
1195
|
-
fieldSearch && /* @__PURE__ */ (0,
|
|
1470
|
+
fieldSearch && /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("button", { className: "vpg-clear-search", onClick: () => setFieldSearch(""), children: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("svg", { className: "vpg-icon-xs", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
|
|
1196
1471
|
"path",
|
|
1197
1472
|
{
|
|
1198
1473
|
strokeLinecap: "round",
|
|
@@ -1202,64 +1477,93 @@ function PivotConfig({
|
|
|
1202
1477
|
}
|
|
1203
1478
|
) }) })
|
|
1204
1479
|
] }),
|
|
1205
|
-
/* @__PURE__ */ (0,
|
|
1206
|
-
filteredUnassignedFields.map((field) => /* @__PURE__ */ (0,
|
|
1480
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { className: "vpg-field-list", children: [
|
|
1481
|
+
filteredUnassignedFields.map((field) => /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(
|
|
1207
1482
|
"div",
|
|
1208
1483
|
{
|
|
1209
|
-
className: `vpg-field-item
|
|
1210
|
-
title: field.field,
|
|
1484
|
+
className: `vpg-field-item${field.isNumeric && !field.isCalculated ? " vpg-is-numeric" : ""}${field.isCalculated ? " vpg-is-calculated" : ""}`,
|
|
1485
|
+
title: field.isCalculated ? field.calcFormula : field.field,
|
|
1211
1486
|
draggable: true,
|
|
1212
1487
|
onDragStart: (e) => handleDragStart(field.field, e),
|
|
1213
1488
|
onDragEnd,
|
|
1214
1489
|
children: [
|
|
1215
|
-
/* @__PURE__ */ (0,
|
|
1216
|
-
/* @__PURE__ */ (0,
|
|
1217
|
-
/* @__PURE__ */ (0,
|
|
1490
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("span", { className: `vpg-field-type-icon${field.isCalculated ? " vpg-calc-type" : ""}`, title: field.type, children: getFieldIcon(field.type, field.isCalculated) }),
|
|
1491
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("span", { className: "vpg-field-name", children: getFieldDisplayName(field) }),
|
|
1492
|
+
field.isCalculated ? /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(import_jsx_runtime3.Fragment, { children: [
|
|
1493
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
|
|
1494
|
+
"button",
|
|
1495
|
+
{
|
|
1496
|
+
className: "vpg-field-edit",
|
|
1497
|
+
title: "Edit calculated field",
|
|
1498
|
+
onClick: (e) => {
|
|
1499
|
+
e.stopPropagation();
|
|
1500
|
+
const calcField = calculatedFields?.find((c) => c.id === field.calcId);
|
|
1501
|
+
if (calcField) openCalcModal(calcField);
|
|
1502
|
+
},
|
|
1503
|
+
children: "\u270E"
|
|
1504
|
+
}
|
|
1505
|
+
),
|
|
1506
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
|
|
1507
|
+
"button",
|
|
1508
|
+
{
|
|
1509
|
+
className: "vpg-field-delete",
|
|
1510
|
+
title: "Delete calculated field",
|
|
1511
|
+
onClick: (e) => {
|
|
1512
|
+
e.stopPropagation();
|
|
1513
|
+
if (field.calcId && onRemoveCalculatedField) {
|
|
1514
|
+
onRemoveCalculatedField(field.calcId);
|
|
1515
|
+
}
|
|
1516
|
+
},
|
|
1517
|
+
children: "\xD7"
|
|
1518
|
+
}
|
|
1519
|
+
)
|
|
1520
|
+
] }) : /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("span", { className: "vpg-unique-count", children: field.uniqueCount })
|
|
1218
1521
|
]
|
|
1219
1522
|
},
|
|
1220
1523
|
field.field
|
|
1221
1524
|
)),
|
|
1222
|
-
filteredUnassignedFields.length === 0 && fieldSearch && /* @__PURE__ */ (0,
|
|
1525
|
+
filteredUnassignedFields.length === 0 && fieldSearch && /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { className: "vpg-empty-hint", children: [
|
|
1223
1526
|
'No fields match "',
|
|
1224
1527
|
fieldSearch,
|
|
1225
1528
|
'"'
|
|
1226
1529
|
] }),
|
|
1227
|
-
unassignedFields.length === 0 && /* @__PURE__ */ (0,
|
|
1530
|
+
unassignedFields.length === 0 && /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("div", { className: "vpg-empty-hint", children: "All fields assigned" })
|
|
1228
1531
|
] })
|
|
1229
1532
|
] }),
|
|
1230
|
-
/* @__PURE__ */ (0,
|
|
1231
|
-
/* @__PURE__ */ (0,
|
|
1232
|
-
/* @__PURE__ */ (0,
|
|
1533
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { className: "vpg-options-section", children: [
|
|
1534
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("label", { className: "vpg-option-toggle", children: [
|
|
1535
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
|
|
1233
1536
|
"input",
|
|
1234
1537
|
{
|
|
1235
1538
|
type: "checkbox",
|
|
1236
1539
|
checked: showRowTotals,
|
|
1237
|
-
onChange: (e) =>
|
|
1540
|
+
onChange: (e) => handleTotalsToggle(e.target.checked)
|
|
1238
1541
|
}
|
|
1239
1542
|
),
|
|
1240
|
-
/* @__PURE__ */ (0,
|
|
1543
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("span", { children: "Totals" })
|
|
1241
1544
|
] }),
|
|
1242
|
-
/* @__PURE__ */ (0,
|
|
1243
|
-
/* @__PURE__ */ (0,
|
|
1244
|
-
|
|
1245
|
-
{
|
|
1246
|
-
strokeLinecap: "round",
|
|
1247
|
-
strokeLinejoin: "round",
|
|
1248
|
-
strokeWidth: 2,
|
|
1249
|
-
d: "M13 10V3L4 14h7v7l9-11h-7z"
|
|
1250
|
-
}
|
|
1251
|
-
) }),
|
|
1252
|
-
"Auto"
|
|
1545
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("button", { className: "vpg-calc-btn", onClick: () => openCalcModal(), title: "Add calculated field (e.g. Profit Margin %)", children: [
|
|
1546
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("span", { className: "vpg-calc-icon", children: "\u0192" }),
|
|
1547
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("span", { children: "+ Calc" })
|
|
1253
1548
|
] })
|
|
1254
1549
|
] }),
|
|
1255
|
-
|
|
1550
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
|
|
1551
|
+
CalculatedFieldModal,
|
|
1552
|
+
{
|
|
1553
|
+
show: showCalcModal,
|
|
1554
|
+
availableFields: numericFieldNames,
|
|
1555
|
+
existingField: editingCalcField,
|
|
1556
|
+
onClose: handleCloseCalcModal,
|
|
1557
|
+
onSave: handleSaveCalcField
|
|
1558
|
+
}
|
|
1559
|
+
)
|
|
1256
1560
|
] });
|
|
1257
1561
|
}
|
|
1258
1562
|
|
|
1259
1563
|
// src/components/PivotSkeleton.tsx
|
|
1260
|
-
var
|
|
1261
|
-
var
|
|
1262
|
-
var
|
|
1564
|
+
var import_react8 = require("react");
|
|
1565
|
+
var import_tinypivot_core7 = require("@smallwebco/tinypivot-core");
|
|
1566
|
+
var import_jsx_runtime4 = require("react/jsx-runtime");
|
|
1263
1567
|
function PivotSkeleton({
|
|
1264
1568
|
rowFields,
|
|
1265
1569
|
columnFields,
|
|
@@ -1281,12 +1585,12 @@ function PivotSkeleton({
|
|
|
1281
1585
|
onReorderColumnFields
|
|
1282
1586
|
}) {
|
|
1283
1587
|
const { showWatermark, canUsePivot, isDemo } = useLicense();
|
|
1284
|
-
const [dragOverArea, setDragOverArea] = (0,
|
|
1285
|
-
const [reorderDragSource, setReorderDragSource] = (0,
|
|
1286
|
-
const [reorderDropTarget, setReorderDropTarget] = (0,
|
|
1287
|
-
const [sortDirection, setSortDirection] = (0,
|
|
1288
|
-
const [sortTarget, setSortTarget] = (0,
|
|
1289
|
-
const toggleSort = (0,
|
|
1588
|
+
const [dragOverArea, setDragOverArea] = (0, import_react8.useState)(null);
|
|
1589
|
+
const [reorderDragSource, setReorderDragSource] = (0, import_react8.useState)(null);
|
|
1590
|
+
const [reorderDropTarget, setReorderDropTarget] = (0, import_react8.useState)(null);
|
|
1591
|
+
const [sortDirection, setSortDirection] = (0, import_react8.useState)("asc");
|
|
1592
|
+
const [sortTarget, setSortTarget] = (0, import_react8.useState)("row");
|
|
1593
|
+
const toggleSort = (0, import_react8.useCallback)((target = "row") => {
|
|
1290
1594
|
if (sortTarget === target) {
|
|
1291
1595
|
setSortDirection((prev) => prev === "asc" ? "desc" : "asc");
|
|
1292
1596
|
} else {
|
|
@@ -1294,7 +1598,7 @@ function PivotSkeleton({
|
|
|
1294
1598
|
setSortDirection("asc");
|
|
1295
1599
|
}
|
|
1296
1600
|
}, [sortTarget]);
|
|
1297
|
-
const sortedRowIndices = (0,
|
|
1601
|
+
const sortedRowIndices = (0, import_react8.useMemo)(() => {
|
|
1298
1602
|
if (!pivotResult) return [];
|
|
1299
1603
|
const indices = pivotResult.rowHeaders.map((_, i) => i);
|
|
1300
1604
|
const headers = pivotResult.rowHeaders;
|
|
@@ -1318,11 +1622,11 @@ function PivotSkeleton({
|
|
|
1318
1622
|
});
|
|
1319
1623
|
return indices;
|
|
1320
1624
|
}, [pivotResult, sortTarget, sortDirection]);
|
|
1321
|
-
const columnHeaderCells = (0,
|
|
1625
|
+
const columnHeaderCells = (0, import_react8.useMemo)(() => {
|
|
1322
1626
|
if (!pivotResult || pivotResult.headers.length === 0) {
|
|
1323
1627
|
return [
|
|
1324
1628
|
valueFields.map((vf) => ({
|
|
1325
|
-
label: `${vf.field} (${(0,
|
|
1629
|
+
label: `${vf.field} (${(0, import_tinypivot_core7.getAggregationLabel)(vf.aggregation)})`,
|
|
1326
1630
|
colspan: 1
|
|
1327
1631
|
}))
|
|
1328
1632
|
];
|
|
@@ -1346,12 +1650,12 @@ function PivotSkeleton({
|
|
|
1346
1650
|
return result;
|
|
1347
1651
|
}, [pivotResult, valueFields]);
|
|
1348
1652
|
const hasActiveFilters = activeFilters && activeFilters.length > 0;
|
|
1349
|
-
const filterSummary = (0,
|
|
1653
|
+
const filterSummary = (0, import_react8.useMemo)(() => {
|
|
1350
1654
|
if (!activeFilters || activeFilters.length === 0) return "";
|
|
1351
1655
|
return activeFilters.map((f) => f.column).join(", ");
|
|
1352
1656
|
}, [activeFilters]);
|
|
1353
|
-
const [showFilterTooltip, setShowFilterTooltip] = (0,
|
|
1354
|
-
const filterTooltipDetails = (0,
|
|
1657
|
+
const [showFilterTooltip, setShowFilterTooltip] = (0, import_react8.useState)(false);
|
|
1658
|
+
const filterTooltipDetails = (0, import_react8.useMemo)(() => {
|
|
1355
1659
|
if (!activeFilters || activeFilters.length === 0) return [];
|
|
1356
1660
|
return activeFilters.map((f) => {
|
|
1357
1661
|
const maxDisplay = 5;
|
|
@@ -1364,7 +1668,7 @@ function PivotSkeleton({
|
|
|
1364
1668
|
};
|
|
1365
1669
|
});
|
|
1366
1670
|
}, [activeFilters]);
|
|
1367
|
-
const handleDragOver = (0,
|
|
1671
|
+
const handleDragOver = (0, import_react8.useCallback)(
|
|
1368
1672
|
(area, event) => {
|
|
1369
1673
|
event.preventDefault();
|
|
1370
1674
|
event.dataTransfer.dropEffect = "move";
|
|
@@ -1372,10 +1676,10 @@ function PivotSkeleton({
|
|
|
1372
1676
|
},
|
|
1373
1677
|
[]
|
|
1374
1678
|
);
|
|
1375
|
-
const handleDragLeave = (0,
|
|
1679
|
+
const handleDragLeave = (0, import_react8.useCallback)(() => {
|
|
1376
1680
|
setDragOverArea(null);
|
|
1377
1681
|
}, []);
|
|
1378
|
-
const handleDrop = (0,
|
|
1682
|
+
const handleDrop = (0, import_react8.useCallback)(
|
|
1379
1683
|
(area, event) => {
|
|
1380
1684
|
event.preventDefault();
|
|
1381
1685
|
const field = event.dataTransfer?.getData("text/plain");
|
|
@@ -1402,7 +1706,7 @@ function PivotSkeleton({
|
|
|
1402
1706
|
},
|
|
1403
1707
|
[rowFields, columnFields, valueFields, onAddRowField, onRemoveRowField, onAddColumnField, onRemoveColumnField, onAddValueField, onRemoveValueField]
|
|
1404
1708
|
);
|
|
1405
|
-
const handleChipDragStart = (0,
|
|
1709
|
+
const handleChipDragStart = (0, import_react8.useCallback)(
|
|
1406
1710
|
(zone, index, event) => {
|
|
1407
1711
|
setReorderDragSource({ zone, index });
|
|
1408
1712
|
event.dataTransfer.effectAllowed = "move";
|
|
@@ -1413,11 +1717,11 @@ function PivotSkeleton({
|
|
|
1413
1717
|
},
|
|
1414
1718
|
[]
|
|
1415
1719
|
);
|
|
1416
|
-
const handleChipDragEnd = (0,
|
|
1720
|
+
const handleChipDragEnd = (0, import_react8.useCallback)(() => {
|
|
1417
1721
|
setReorderDragSource(null);
|
|
1418
1722
|
setReorderDropTarget(null);
|
|
1419
1723
|
}, []);
|
|
1420
|
-
const handleChipDragOver = (0,
|
|
1724
|
+
const handleChipDragOver = (0, import_react8.useCallback)(
|
|
1421
1725
|
(zone, index, event) => {
|
|
1422
1726
|
event.preventDefault();
|
|
1423
1727
|
if (reorderDragSource && reorderDragSource.zone === zone) {
|
|
@@ -1427,10 +1731,10 @@ function PivotSkeleton({
|
|
|
1427
1731
|
},
|
|
1428
1732
|
[reorderDragSource]
|
|
1429
1733
|
);
|
|
1430
|
-
const handleChipDragLeave = (0,
|
|
1734
|
+
const handleChipDragLeave = (0, import_react8.useCallback)(() => {
|
|
1431
1735
|
setReorderDropTarget(null);
|
|
1432
1736
|
}, []);
|
|
1433
|
-
const handleChipDrop = (0,
|
|
1737
|
+
const handleChipDrop = (0, import_react8.useCallback)(
|
|
1434
1738
|
(zone, targetIndex, event) => {
|
|
1435
1739
|
event.preventDefault();
|
|
1436
1740
|
event.stopPropagation();
|
|
@@ -1456,27 +1760,27 @@ function PivotSkeleton({
|
|
|
1456
1760
|
},
|
|
1457
1761
|
[reorderDragSource, rowFields, columnFields, onReorderRowFields, onReorderColumnFields]
|
|
1458
1762
|
);
|
|
1459
|
-
const isChipDragSource = (0,
|
|
1763
|
+
const isChipDragSource = (0, import_react8.useCallback)(
|
|
1460
1764
|
(zone, index) => {
|
|
1461
1765
|
return reorderDragSource?.zone === zone && reorderDragSource?.index === index;
|
|
1462
1766
|
},
|
|
1463
1767
|
[reorderDragSource]
|
|
1464
1768
|
);
|
|
1465
|
-
const isChipDropTarget = (0,
|
|
1769
|
+
const isChipDropTarget = (0, import_react8.useCallback)(
|
|
1466
1770
|
(zone, index) => {
|
|
1467
1771
|
return reorderDropTarget?.zone === zone && reorderDropTarget?.index === index;
|
|
1468
1772
|
},
|
|
1469
1773
|
[reorderDropTarget]
|
|
1470
1774
|
);
|
|
1471
1775
|
const currentFontSize = fontSize;
|
|
1472
|
-
return /* @__PURE__ */ (0,
|
|
1776
|
+
return /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(
|
|
1473
1777
|
"div",
|
|
1474
1778
|
{
|
|
1475
1779
|
className: `vpg-pivot-skeleton vpg-font-${currentFontSize} ${draggingField ? "vpg-is-dragging" : ""}`,
|
|
1476
1780
|
children: [
|
|
1477
|
-
/* @__PURE__ */ (0,
|
|
1478
|
-
/* @__PURE__ */ (0,
|
|
1479
|
-
/* @__PURE__ */ (0,
|
|
1781
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { className: "vpg-skeleton-header", children: [
|
|
1782
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { className: "vpg-skeleton-title", children: [
|
|
1783
|
+
/* @__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)(
|
|
1480
1784
|
"path",
|
|
1481
1785
|
{
|
|
1482
1786
|
strokeLinecap: "round",
|
|
@@ -1485,24 +1789,24 @@ function PivotSkeleton({
|
|
|
1485
1789
|
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"
|
|
1486
1790
|
}
|
|
1487
1791
|
) }),
|
|
1488
|
-
/* @__PURE__ */ (0,
|
|
1792
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("span", { children: "Pivot Table" })
|
|
1489
1793
|
] }),
|
|
1490
|
-
/* @__PURE__ */ (0,
|
|
1491
|
-
hasActiveFilters && /* @__PURE__ */ (0,
|
|
1794
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { className: "vpg-header-right", children: [
|
|
1795
|
+
hasActiveFilters && /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(
|
|
1492
1796
|
"div",
|
|
1493
1797
|
{
|
|
1494
1798
|
className: "vpg-filter-indicator",
|
|
1495
1799
|
onMouseEnter: () => setShowFilterTooltip(true),
|
|
1496
1800
|
onMouseLeave: () => setShowFilterTooltip(false),
|
|
1497
1801
|
children: [
|
|
1498
|
-
/* @__PURE__ */ (0,
|
|
1802
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
|
|
1499
1803
|
"svg",
|
|
1500
1804
|
{
|
|
1501
1805
|
className: "vpg-filter-icon",
|
|
1502
1806
|
fill: "none",
|
|
1503
1807
|
stroke: "currentColor",
|
|
1504
1808
|
viewBox: "0 0 24 24",
|
|
1505
|
-
children: /* @__PURE__ */ (0,
|
|
1809
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
|
|
1506
1810
|
"path",
|
|
1507
1811
|
{
|
|
1508
1812
|
strokeLinecap: "round",
|
|
@@ -1513,10 +1817,10 @@ function PivotSkeleton({
|
|
|
1513
1817
|
)
|
|
1514
1818
|
}
|
|
1515
1819
|
),
|
|
1516
|
-
/* @__PURE__ */ (0,
|
|
1820
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("span", { className: "vpg-filter-text", children: [
|
|
1517
1821
|
"Filtered: ",
|
|
1518
|
-
/* @__PURE__ */ (0,
|
|
1519
|
-
filteredRowCount !== void 0 && totalRowCount !== void 0 && /* @__PURE__ */ (0,
|
|
1822
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("strong", { children: filterSummary }),
|
|
1823
|
+
filteredRowCount !== void 0 && totalRowCount !== void 0 && /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("span", { className: "vpg-filter-count", children: [
|
|
1520
1824
|
"(",
|
|
1521
1825
|
filteredRowCount.toLocaleString(),
|
|
1522
1826
|
" of ",
|
|
@@ -1524,20 +1828,20 @@ function PivotSkeleton({
|
|
|
1524
1828
|
" rows)"
|
|
1525
1829
|
] })
|
|
1526
1830
|
] }),
|
|
1527
|
-
showFilterTooltip && /* @__PURE__ */ (0,
|
|
1528
|
-
/* @__PURE__ */ (0,
|
|
1529
|
-
filterTooltipDetails.map((filter) => /* @__PURE__ */ (0,
|
|
1530
|
-
/* @__PURE__ */ (0,
|
|
1531
|
-
/* @__PURE__ */ (0,
|
|
1532
|
-
filter.values.map((val, idx) => /* @__PURE__ */ (0,
|
|
1533
|
-
filter.remaining > 0 && /* @__PURE__ */ (0,
|
|
1831
|
+
showFilterTooltip && /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { className: "vpg-filter-tooltip", children: [
|
|
1832
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("div", { className: "vpg-tooltip-header", children: "Active Filters" }),
|
|
1833
|
+
filterTooltipDetails.map((filter) => /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { className: "vpg-tooltip-filter", children: [
|
|
1834
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("div", { className: "vpg-tooltip-column", children: filter.column }),
|
|
1835
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { className: "vpg-tooltip-values", children: [
|
|
1836
|
+
filter.values.map((val, idx) => /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("span", { className: "vpg-tooltip-value", children: val }, idx)),
|
|
1837
|
+
filter.remaining > 0 && /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("span", { className: "vpg-tooltip-more", children: [
|
|
1534
1838
|
"+",
|
|
1535
1839
|
filter.remaining,
|
|
1536
1840
|
" more"
|
|
1537
1841
|
] })
|
|
1538
1842
|
] })
|
|
1539
1843
|
] }, filter.column)),
|
|
1540
|
-
filteredRowCount !== void 0 && totalRowCount !== void 0 && /* @__PURE__ */ (0,
|
|
1844
|
+
filteredRowCount !== void 0 && totalRowCount !== void 0 && /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { className: "vpg-tooltip-summary", children: [
|
|
1541
1845
|
"Showing ",
|
|
1542
1846
|
filteredRowCount.toLocaleString(),
|
|
1543
1847
|
" of ",
|
|
@@ -1548,18 +1852,18 @@ function PivotSkeleton({
|
|
|
1548
1852
|
]
|
|
1549
1853
|
}
|
|
1550
1854
|
),
|
|
1551
|
-
isConfigured && /* @__PURE__ */ (0,
|
|
1552
|
-
/* @__PURE__ */ (0,
|
|
1855
|
+
isConfigured && /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { className: "vpg-config-summary", children: [
|
|
1856
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("span", { className: "vpg-summary-badge vpg-rows", children: [
|
|
1553
1857
|
rowFields.length,
|
|
1554
1858
|
" row",
|
|
1555
1859
|
rowFields.length !== 1 ? "s" : ""
|
|
1556
1860
|
] }),
|
|
1557
|
-
/* @__PURE__ */ (0,
|
|
1861
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("span", { className: "vpg-summary-badge vpg-cols", children: [
|
|
1558
1862
|
columnFields.length,
|
|
1559
1863
|
" col",
|
|
1560
1864
|
columnFields.length !== 1 ? "s" : ""
|
|
1561
1865
|
] }),
|
|
1562
|
-
/* @__PURE__ */ (0,
|
|
1866
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("span", { className: "vpg-summary-badge vpg-vals", children: [
|
|
1563
1867
|
valueFields.length,
|
|
1564
1868
|
" val",
|
|
1565
1869
|
valueFields.length !== 1 ? "s" : ""
|
|
@@ -1567,8 +1871,8 @@ function PivotSkeleton({
|
|
|
1567
1871
|
] })
|
|
1568
1872
|
] })
|
|
1569
1873
|
] }),
|
|
1570
|
-
!canUsePivot ? /* @__PURE__ */ (0,
|
|
1571
|
-
/* @__PURE__ */ (0,
|
|
1874
|
+
!canUsePivot ? /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("div", { className: "vpg-pro-required", children: /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { className: "vpg-pro-content", children: [
|
|
1875
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("svg", { className: "vpg-pro-icon", fill: "none", viewBox: "0 0 24 24", stroke: "currentColor", children: /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
|
|
1572
1876
|
"path",
|
|
1573
1877
|
{
|
|
1574
1878
|
strokeLinecap: "round",
|
|
@@ -1577,12 +1881,12 @@ function PivotSkeleton({
|
|
|
1577
1881
|
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"
|
|
1578
1882
|
}
|
|
1579
1883
|
) }),
|
|
1580
|
-
/* @__PURE__ */ (0,
|
|
1581
|
-
/* @__PURE__ */ (0,
|
|
1582
|
-
/* @__PURE__ */ (0,
|
|
1583
|
-
] }) }) : /* @__PURE__ */ (0,
|
|
1584
|
-
/* @__PURE__ */ (0,
|
|
1585
|
-
/* @__PURE__ */ (0,
|
|
1884
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("h3", { children: "Pro Feature" }),
|
|
1885
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("p", { children: "Pivot Table functionality requires a Pro license." }),
|
|
1886
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("a", { href: "https://tiny-pivot.com/#pricing", target: "_blank", rel: "noopener noreferrer", className: "vpg-pro-link", children: "Get Pro License \u2192" })
|
|
1887
|
+
] }) }) : /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(import_jsx_runtime4.Fragment, { children: [
|
|
1888
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { className: "vpg-config-bar", children: [
|
|
1889
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(
|
|
1586
1890
|
"div",
|
|
1587
1891
|
{
|
|
1588
1892
|
className: `vpg-drop-zone vpg-row-zone ${dragOverArea === "row" ? "vpg-drag-over" : ""}`,
|
|
@@ -1590,12 +1894,12 @@ function PivotSkeleton({
|
|
|
1590
1894
|
onDragLeave: handleDragLeave,
|
|
1591
1895
|
onDrop: (e) => handleDrop("row", e),
|
|
1592
1896
|
children: [
|
|
1593
|
-
/* @__PURE__ */ (0,
|
|
1594
|
-
/* @__PURE__ */ (0,
|
|
1595
|
-
/* @__PURE__ */ (0,
|
|
1897
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { className: "vpg-zone-header", children: [
|
|
1898
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("span", { className: "vpg-zone-icon vpg-row-icon", children: "\u2193" }),
|
|
1899
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("span", { className: "vpg-zone-label", children: "Rows" })
|
|
1596
1900
|
] }),
|
|
1597
|
-
/* @__PURE__ */ (0,
|
|
1598
|
-
rowFields.map((field, idx) => /* @__PURE__ */ (0,
|
|
1901
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { className: "vpg-zone-chips", children: [
|
|
1902
|
+
rowFields.map((field, idx) => /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(
|
|
1599
1903
|
"div",
|
|
1600
1904
|
{
|
|
1601
1905
|
className: `vpg-mini-chip vpg-row-chip ${isChipDragSource("row", idx) ? "vpg-chip-dragging" : ""} ${isChipDropTarget("row", idx) ? "vpg-chip-drop-target" : ""}`,
|
|
@@ -1606,9 +1910,9 @@ function PivotSkeleton({
|
|
|
1606
1910
|
onDragLeave: handleChipDragLeave,
|
|
1607
1911
|
onDrop: (e) => handleChipDrop("row", idx, e),
|
|
1608
1912
|
children: [
|
|
1609
|
-
/* @__PURE__ */ (0,
|
|
1610
|
-
/* @__PURE__ */ (0,
|
|
1611
|
-
/* @__PURE__ */ (0,
|
|
1913
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("span", { className: "vpg-drag-handle", children: "\u22EE\u22EE" }),
|
|
1914
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("span", { className: "vpg-mini-name", children: field }),
|
|
1915
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
|
|
1612
1916
|
"button",
|
|
1613
1917
|
{
|
|
1614
1918
|
className: "vpg-mini-remove",
|
|
@@ -1623,12 +1927,12 @@ function PivotSkeleton({
|
|
|
1623
1927
|
},
|
|
1624
1928
|
field
|
|
1625
1929
|
)),
|
|
1626
|
-
rowFields.length === 0 && /* @__PURE__ */ (0,
|
|
1930
|
+
rowFields.length === 0 && /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("span", { className: "vpg-zone-hint", children: "Drop here" })
|
|
1627
1931
|
] })
|
|
1628
1932
|
]
|
|
1629
1933
|
}
|
|
1630
1934
|
),
|
|
1631
|
-
/* @__PURE__ */ (0,
|
|
1935
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(
|
|
1632
1936
|
"div",
|
|
1633
1937
|
{
|
|
1634
1938
|
className: `vpg-drop-zone vpg-column-zone ${dragOverArea === "column" ? "vpg-drag-over" : ""}`,
|
|
@@ -1636,12 +1940,12 @@ function PivotSkeleton({
|
|
|
1636
1940
|
onDragLeave: handleDragLeave,
|
|
1637
1941
|
onDrop: (e) => handleDrop("column", e),
|
|
1638
1942
|
children: [
|
|
1639
|
-
/* @__PURE__ */ (0,
|
|
1640
|
-
/* @__PURE__ */ (0,
|
|
1641
|
-
/* @__PURE__ */ (0,
|
|
1943
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { className: "vpg-zone-header", children: [
|
|
1944
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("span", { className: "vpg-zone-icon vpg-column-icon", children: "\u2192" }),
|
|
1945
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("span", { className: "vpg-zone-label", children: "Columns" })
|
|
1642
1946
|
] }),
|
|
1643
|
-
/* @__PURE__ */ (0,
|
|
1644
|
-
columnFields.map((field, idx) => /* @__PURE__ */ (0,
|
|
1947
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { className: "vpg-zone-chips", children: [
|
|
1948
|
+
columnFields.map((field, idx) => /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(
|
|
1645
1949
|
"div",
|
|
1646
1950
|
{
|
|
1647
1951
|
className: `vpg-mini-chip vpg-column-chip ${isChipDragSource("column", idx) ? "vpg-chip-dragging" : ""} ${isChipDropTarget("column", idx) ? "vpg-chip-drop-target" : ""}`,
|
|
@@ -1652,9 +1956,9 @@ function PivotSkeleton({
|
|
|
1652
1956
|
onDragLeave: handleChipDragLeave,
|
|
1653
1957
|
onDrop: (e) => handleChipDrop("column", idx, e),
|
|
1654
1958
|
children: [
|
|
1655
|
-
/* @__PURE__ */ (0,
|
|
1656
|
-
/* @__PURE__ */ (0,
|
|
1657
|
-
/* @__PURE__ */ (0,
|
|
1959
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("span", { className: "vpg-drag-handle", children: "\u22EE\u22EE" }),
|
|
1960
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("span", { className: "vpg-mini-name", children: field }),
|
|
1961
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
|
|
1658
1962
|
"button",
|
|
1659
1963
|
{
|
|
1660
1964
|
className: "vpg-mini-remove",
|
|
@@ -1669,12 +1973,12 @@ function PivotSkeleton({
|
|
|
1669
1973
|
},
|
|
1670
1974
|
field
|
|
1671
1975
|
)),
|
|
1672
|
-
columnFields.length === 0 && /* @__PURE__ */ (0,
|
|
1976
|
+
columnFields.length === 0 && /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("span", { className: "vpg-zone-hint", children: "Drop here" })
|
|
1673
1977
|
] })
|
|
1674
1978
|
]
|
|
1675
1979
|
}
|
|
1676
1980
|
),
|
|
1677
|
-
/* @__PURE__ */ (0,
|
|
1981
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(
|
|
1678
1982
|
"div",
|
|
1679
1983
|
{
|
|
1680
1984
|
className: `vpg-drop-zone vpg-value-zone ${dragOverArea === "value" ? "vpg-drag-over" : ""}`,
|
|
@@ -1682,19 +1986,19 @@ function PivotSkeleton({
|
|
|
1682
1986
|
onDragLeave: handleDragLeave,
|
|
1683
1987
|
onDrop: (e) => handleDrop("value", e),
|
|
1684
1988
|
children: [
|
|
1685
|
-
/* @__PURE__ */ (0,
|
|
1686
|
-
/* @__PURE__ */ (0,
|
|
1687
|
-
/* @__PURE__ */ (0,
|
|
1989
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { className: "vpg-zone-header", children: [
|
|
1990
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("span", { className: "vpg-zone-icon vpg-value-icon", children: "\u03A3" }),
|
|
1991
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("span", { className: "vpg-zone-label", children: "Values" })
|
|
1688
1992
|
] }),
|
|
1689
|
-
/* @__PURE__ */ (0,
|
|
1690
|
-
valueFields.map((vf) => /* @__PURE__ */ (0,
|
|
1993
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { className: "vpg-zone-chips", children: [
|
|
1994
|
+
valueFields.map((vf) => /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(
|
|
1691
1995
|
"div",
|
|
1692
1996
|
{
|
|
1693
1997
|
className: "vpg-mini-chip vpg-value-chip",
|
|
1694
1998
|
children: [
|
|
1695
|
-
/* @__PURE__ */ (0,
|
|
1696
|
-
/* @__PURE__ */ (0,
|
|
1697
|
-
/* @__PURE__ */ (0,
|
|
1999
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("span", { className: "vpg-agg-symbol", children: (0, import_tinypivot_core7.getAggregationSymbol)(vf.aggregation) }),
|
|
2000
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("span", { className: "vpg-mini-name", children: vf.field }),
|
|
2001
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
|
|
1698
2002
|
"button",
|
|
1699
2003
|
{
|
|
1700
2004
|
className: "vpg-mini-remove",
|
|
@@ -1706,21 +2010,21 @@ function PivotSkeleton({
|
|
|
1706
2010
|
},
|
|
1707
2011
|
`${vf.field}-${vf.aggregation}`
|
|
1708
2012
|
)),
|
|
1709
|
-
valueFields.length === 0 && /* @__PURE__ */ (0,
|
|
2013
|
+
valueFields.length === 0 && /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("span", { className: "vpg-zone-hint", children: "Drop numeric" })
|
|
1710
2014
|
] })
|
|
1711
2015
|
]
|
|
1712
2016
|
}
|
|
1713
2017
|
)
|
|
1714
2018
|
] }),
|
|
1715
|
-
(!isConfigured || !pivotResult) && /* @__PURE__ */ (0,
|
|
1716
|
-
/* @__PURE__ */ (0,
|
|
2019
|
+
(!isConfigured || !pivotResult) && /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("div", { className: "vpg-placeholder", children: /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { className: "vpg-placeholder-content", children: [
|
|
2020
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
|
|
1717
2021
|
"svg",
|
|
1718
2022
|
{
|
|
1719
2023
|
className: "vpg-placeholder-icon",
|
|
1720
2024
|
fill: "none",
|
|
1721
2025
|
viewBox: "0 0 24 24",
|
|
1722
2026
|
stroke: "currentColor",
|
|
1723
|
-
children: /* @__PURE__ */ (0,
|
|
2027
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
|
|
1724
2028
|
"path",
|
|
1725
2029
|
{
|
|
1726
2030
|
strokeLinecap: "round",
|
|
@@ -1731,51 +2035,51 @@ function PivotSkeleton({
|
|
|
1731
2035
|
)
|
|
1732
2036
|
}
|
|
1733
2037
|
),
|
|
1734
|
-
/* @__PURE__ */ (0,
|
|
2038
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("span", { className: "vpg-placeholder-text", children: valueFields.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(import_jsx_runtime4.Fragment, { children: [
|
|
1735
2039
|
"Add a ",
|
|
1736
|
-
/* @__PURE__ */ (0,
|
|
2040
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("strong", { children: "Values" }),
|
|
1737
2041
|
" field to see your pivot table"
|
|
1738
|
-
] }) : rowFields.length === 0 && columnFields.length === 0 ? /* @__PURE__ */ (0,
|
|
2042
|
+
] }) : rowFields.length === 0 && columnFields.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(import_jsx_runtime4.Fragment, { children: [
|
|
1739
2043
|
"Add ",
|
|
1740
|
-
/* @__PURE__ */ (0,
|
|
2044
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("strong", { children: "Row" }),
|
|
1741
2045
|
" or ",
|
|
1742
|
-
/* @__PURE__ */ (0,
|
|
2046
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("strong", { children: "Column" }),
|
|
1743
2047
|
" fields to group your data"
|
|
1744
2048
|
] }) : "Your pivot table will appear here" })
|
|
1745
2049
|
] }) }),
|
|
1746
|
-
isConfigured && pivotResult && /* @__PURE__ */ (0,
|
|
1747
|
-
/* @__PURE__ */ (0,
|
|
1748
|
-
levelIdx === 0 && /* @__PURE__ */ (0,
|
|
2050
|
+
isConfigured && pivotResult && /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("div", { className: "vpg-table-container", children: /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("table", { className: "vpg-pivot-table", children: [
|
|
2051
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("thead", { children: columnHeaderCells.map((headerRow, levelIdx) => /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("tr", { className: "vpg-column-header-row", children: [
|
|
2052
|
+
levelIdx === 0 && /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
|
|
1749
2053
|
"th",
|
|
1750
2054
|
{
|
|
1751
2055
|
className: "vpg-row-header-label",
|
|
1752
2056
|
rowSpan: columnHeaderCells.length,
|
|
1753
2057
|
onClick: () => toggleSort("row"),
|
|
1754
|
-
children: /* @__PURE__ */ (0,
|
|
1755
|
-
/* @__PURE__ */ (0,
|
|
1756
|
-
/* @__PURE__ */ (0,
|
|
2058
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { className: "vpg-header-content", children: [
|
|
2059
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("span", { children: rowFields.join(" / ") || "Rows" }),
|
|
2060
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("span", { className: `vpg-sort-indicator ${sortTarget === "row" ? "active" : ""}`, children: sortTarget === "row" ? sortDirection === "asc" ? "\u2191" : "\u2193" : "\u21C5" })
|
|
1757
2061
|
] })
|
|
1758
2062
|
}
|
|
1759
2063
|
),
|
|
1760
|
-
headerRow.map((cell, idx) => /* @__PURE__ */ (0,
|
|
2064
|
+
headerRow.map((cell, idx) => /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
|
|
1761
2065
|
"th",
|
|
1762
2066
|
{
|
|
1763
2067
|
className: "vpg-column-header-cell",
|
|
1764
2068
|
colSpan: cell.colspan,
|
|
1765
2069
|
onClick: () => levelIdx === columnHeaderCells.length - 1 && toggleSort(idx),
|
|
1766
|
-
children: /* @__PURE__ */ (0,
|
|
1767
|
-
/* @__PURE__ */ (0,
|
|
1768
|
-
levelIdx === columnHeaderCells.length - 1 && /* @__PURE__ */ (0,
|
|
2070
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { className: "vpg-header-content", children: [
|
|
2071
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("span", { children: cell.label }),
|
|
2072
|
+
levelIdx === columnHeaderCells.length - 1 && /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("span", { className: `vpg-sort-indicator ${sortTarget === idx ? "active" : ""}`, children: sortTarget === idx ? sortDirection === "asc" ? "\u2191" : "\u2193" : "\u21C5" })
|
|
1769
2073
|
] })
|
|
1770
2074
|
},
|
|
1771
2075
|
idx
|
|
1772
2076
|
)),
|
|
1773
|
-
pivotResult.rowTotals.length > 0 && levelIdx === 0 && /* @__PURE__ */ (0,
|
|
2077
|
+
pivotResult.rowTotals.length > 0 && levelIdx === 0 && /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("th", { className: "vpg-total-header", rowSpan: columnHeaderCells.length, children: "Total" })
|
|
1774
2078
|
] }, `header-${levelIdx}`)) }),
|
|
1775
|
-
/* @__PURE__ */ (0,
|
|
1776
|
-
sortedRowIndices.map((sortedIdx) => /* @__PURE__ */ (0,
|
|
1777
|
-
/* @__PURE__ */ (0,
|
|
1778
|
-
pivotResult.data[sortedIdx].map((cell, colIdx) => /* @__PURE__ */ (0,
|
|
2079
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("tbody", { children: [
|
|
2080
|
+
sortedRowIndices.map((sortedIdx) => /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("tr", { className: "vpg-data-row", children: [
|
|
2081
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("th", { className: "vpg-row-header-cell", children: pivotResult.rowHeaders[sortedIdx].map((val, idx) => /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("span", { className: "vpg-row-value", children: val }, idx)) }),
|
|
2082
|
+
pivotResult.data[sortedIdx].map((cell, colIdx) => /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
|
|
1779
2083
|
"td",
|
|
1780
2084
|
{
|
|
1781
2085
|
className: `vpg-data-cell ${cell.value === null ? "vpg-is-null" : ""}`,
|
|
@@ -1783,26 +2087,26 @@ function PivotSkeleton({
|
|
|
1783
2087
|
},
|
|
1784
2088
|
colIdx
|
|
1785
2089
|
)),
|
|
1786
|
-
pivotResult.rowTotals[sortedIdx] && /* @__PURE__ */ (0,
|
|
2090
|
+
pivotResult.rowTotals[sortedIdx] && /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("td", { className: "vpg-data-cell vpg-total-cell", children: pivotResult.rowTotals[sortedIdx].formattedValue })
|
|
1787
2091
|
] }, sortedIdx)),
|
|
1788
|
-
pivotResult.columnTotals.length > 0 && /* @__PURE__ */ (0,
|
|
1789
|
-
/* @__PURE__ */ (0,
|
|
1790
|
-
pivotResult.columnTotals.map((cell, colIdx) => /* @__PURE__ */ (0,
|
|
1791
|
-
pivotResult.rowTotals.length > 0 && /* @__PURE__ */ (0,
|
|
2092
|
+
pivotResult.columnTotals.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("tr", { className: "vpg-totals-row", children: [
|
|
2093
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("th", { className: "vpg-row-header-cell vpg-total-label", children: "Total" }),
|
|
2094
|
+
pivotResult.columnTotals.map((cell, colIdx) => /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("td", { className: "vpg-data-cell vpg-total-cell", children: cell.formattedValue }, colIdx)),
|
|
2095
|
+
pivotResult.rowTotals.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("td", { className: "vpg-data-cell vpg-grand-total-cell", children: pivotResult.grandTotal.formattedValue })
|
|
1792
2096
|
] })
|
|
1793
2097
|
] })
|
|
1794
2098
|
] }) }),
|
|
1795
|
-
isConfigured && pivotResult && /* @__PURE__ */ (0,
|
|
2099
|
+
isConfigured && pivotResult && /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("div", { className: "vpg-skeleton-footer", children: /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("span", { children: [
|
|
1796
2100
|
pivotResult.rowHeaders.length,
|
|
1797
2101
|
" rows \xD7 ",
|
|
1798
2102
|
pivotResult.data[0]?.length || 0,
|
|
1799
2103
|
" columns"
|
|
1800
2104
|
] }) })
|
|
1801
2105
|
] }),
|
|
1802
|
-
showWatermark && canUsePivot && /* @__PURE__ */ (0,
|
|
1803
|
-
/* @__PURE__ */ (0,
|
|
1804
|
-
/* @__PURE__ */ (0,
|
|
1805
|
-
/* @__PURE__ */ (0,
|
|
2106
|
+
showWatermark && canUsePivot && /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("div", { className: `vpg-watermark ${isDemo ? "vpg-demo-mode" : ""}`, children: isDemo ? /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(import_jsx_runtime4.Fragment, { children: [
|
|
2107
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("span", { className: "vpg-demo-badge", children: "DEMO" }),
|
|
2108
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("span", { children: "Pro features unlocked for evaluation" }),
|
|
2109
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
|
|
1806
2110
|
"a",
|
|
1807
2111
|
{
|
|
1808
2112
|
href: "https://tiny-pivot.com/#pricing",
|
|
@@ -1812,14 +2116,14 @@ function PivotSkeleton({
|
|
|
1812
2116
|
children: "Get Pro License \u2192"
|
|
1813
2117
|
}
|
|
1814
2118
|
)
|
|
1815
|
-
] }) : /* @__PURE__ */ (0,
|
|
2119
|
+
] }) : /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("a", { href: "https://tiny-pivot.com", target: "_blank", rel: "noopener noreferrer", children: "Powered by TinyPivot" }) })
|
|
1816
2120
|
]
|
|
1817
2121
|
}
|
|
1818
2122
|
);
|
|
1819
2123
|
}
|
|
1820
2124
|
|
|
1821
2125
|
// src/components/DataGrid.tsx
|
|
1822
|
-
var
|
|
2126
|
+
var import_jsx_runtime5 = require("react/jsx-runtime");
|
|
1823
2127
|
var MIN_COL_WIDTH = 120;
|
|
1824
2128
|
var MAX_COL_WIDTH = 350;
|
|
1825
2129
|
function DataGrid({
|
|
@@ -1845,37 +2149,37 @@ function DataGrid({
|
|
|
1845
2149
|
onCopy
|
|
1846
2150
|
}) {
|
|
1847
2151
|
const { showWatermark, canUsePivot, isDemo } = useLicense();
|
|
1848
|
-
const currentTheme = (0,
|
|
2152
|
+
const currentTheme = (0, import_react9.useMemo)(() => {
|
|
1849
2153
|
if (theme === "auto") {
|
|
1850
2154
|
return window.matchMedia?.("(prefers-color-scheme: dark)").matches ? "dark" : "light";
|
|
1851
2155
|
}
|
|
1852
2156
|
return theme;
|
|
1853
2157
|
}, [theme]);
|
|
1854
|
-
const [currentFontSize, setCurrentFontSize] = (0,
|
|
1855
|
-
const [globalSearchTerm, setGlobalSearchTerm] = (0,
|
|
1856
|
-
const [showSearchInput, setShowSearchInput] = (0,
|
|
1857
|
-
const [currentPage, setCurrentPage] = (0,
|
|
1858
|
-
const [columnWidths, setColumnWidths] = (0,
|
|
1859
|
-
const [resizingColumnId, setResizingColumnId] = (0,
|
|
1860
|
-
const [resizeStartX, setResizeStartX] = (0,
|
|
1861
|
-
const [resizeStartWidth, setResizeStartWidth] = (0,
|
|
1862
|
-
const [gridHeight, setGridHeight] = (0,
|
|
1863
|
-
const [isResizingVertically, setIsResizingVertically] = (0,
|
|
1864
|
-
const [verticalResizeStartY, setVerticalResizeStartY] = (0,
|
|
1865
|
-
const [verticalResizeStartHeight, setVerticalResizeStartHeight] = (0,
|
|
1866
|
-
const [showCopyToast, setShowCopyToast] = (0,
|
|
1867
|
-
const [copyToastMessage, setCopyToastMessage] = (0,
|
|
1868
|
-
const [viewMode, setViewMode] = (0,
|
|
1869
|
-
const [showPivotConfig, setShowPivotConfig] = (0,
|
|
1870
|
-
const [draggingField, setDraggingField] = (0,
|
|
1871
|
-
const [activeFilterColumn, setActiveFilterColumn] = (0,
|
|
1872
|
-
const [filterDropdownPosition, setFilterDropdownPosition] = (0,
|
|
1873
|
-
const [selectedCell, setSelectedCell] = (0,
|
|
1874
|
-
const [selectionStart, setSelectionStart] = (0,
|
|
1875
|
-
const [selectionEnd, setSelectionEnd] = (0,
|
|
1876
|
-
const [isSelecting, setIsSelecting] = (0,
|
|
1877
|
-
const tableContainerRef = (0,
|
|
1878
|
-
const tableBodyRef = (0,
|
|
2158
|
+
const [currentFontSize, setCurrentFontSize] = (0, import_react9.useState)(initialFontSize);
|
|
2159
|
+
const [globalSearchTerm, setGlobalSearchTerm] = (0, import_react9.useState)("");
|
|
2160
|
+
const [showSearchInput, setShowSearchInput] = (0, import_react9.useState)(false);
|
|
2161
|
+
const [currentPage, setCurrentPage] = (0, import_react9.useState)(1);
|
|
2162
|
+
const [columnWidths, setColumnWidths] = (0, import_react9.useState)({});
|
|
2163
|
+
const [resizingColumnId, setResizingColumnId] = (0, import_react9.useState)(null);
|
|
2164
|
+
const [resizeStartX, setResizeStartX] = (0, import_react9.useState)(0);
|
|
2165
|
+
const [resizeStartWidth, setResizeStartWidth] = (0, import_react9.useState)(0);
|
|
2166
|
+
const [gridHeight, setGridHeight] = (0, import_react9.useState)(initialHeight);
|
|
2167
|
+
const [isResizingVertically, setIsResizingVertically] = (0, import_react9.useState)(false);
|
|
2168
|
+
const [verticalResizeStartY, setVerticalResizeStartY] = (0, import_react9.useState)(0);
|
|
2169
|
+
const [verticalResizeStartHeight, setVerticalResizeStartHeight] = (0, import_react9.useState)(0);
|
|
2170
|
+
const [showCopyToast, setShowCopyToast] = (0, import_react9.useState)(false);
|
|
2171
|
+
const [copyToastMessage, setCopyToastMessage] = (0, import_react9.useState)("");
|
|
2172
|
+
const [viewMode, setViewMode] = (0, import_react9.useState)("grid");
|
|
2173
|
+
const [showPivotConfig, setShowPivotConfig] = (0, import_react9.useState)(true);
|
|
2174
|
+
const [draggingField, setDraggingField] = (0, import_react9.useState)(null);
|
|
2175
|
+
const [activeFilterColumn, setActiveFilterColumn] = (0, import_react9.useState)(null);
|
|
2176
|
+
const [filterDropdownPosition, setFilterDropdownPosition] = (0, import_react9.useState)({ top: 0, left: 0, maxHeight: 400 });
|
|
2177
|
+
const [selectedCell, setSelectedCell] = (0, import_react9.useState)(null);
|
|
2178
|
+
const [selectionStart, setSelectionStart] = (0, import_react9.useState)(null);
|
|
2179
|
+
const [selectionEnd, setSelectionEnd] = (0, import_react9.useState)(null);
|
|
2180
|
+
const [isSelecting, setIsSelecting] = (0, import_react9.useState)(false);
|
|
2181
|
+
const tableContainerRef = (0, import_react9.useRef)(null);
|
|
2182
|
+
const tableBodyRef = (0, import_react9.useRef)(null);
|
|
1879
2183
|
const fontSizeOptions = [
|
|
1880
2184
|
{ value: "xs", label: "S" },
|
|
1881
2185
|
{ value: "sm", label: "M" },
|
|
@@ -1896,7 +2200,7 @@ function DataGrid({
|
|
|
1896
2200
|
columnFilters,
|
|
1897
2201
|
activeFilters
|
|
1898
2202
|
} = useExcelGrid({ data, enableSorting: true, enableFiltering: true });
|
|
1899
|
-
const filteredDataForPivot = (0,
|
|
2203
|
+
const filteredDataForPivot = (0, import_react9.useMemo)(() => {
|
|
1900
2204
|
const filteredRows = table.getFilteredRowModel().rows;
|
|
1901
2205
|
return filteredRows.map((row) => row.original);
|
|
1902
2206
|
}, [table, columnFilters]);
|
|
@@ -1906,6 +2210,7 @@ function DataGrid({
|
|
|
1906
2210
|
valueFields: pivotValueFields,
|
|
1907
2211
|
showRowTotals: pivotShowRowTotals,
|
|
1908
2212
|
showColumnTotals: pivotShowColumnTotals,
|
|
2213
|
+
calculatedFields: pivotCalculatedFields,
|
|
1909
2214
|
availableFields: pivotAvailableFields,
|
|
1910
2215
|
isConfigured: pivotIsConfigured,
|
|
1911
2216
|
pivotResult,
|
|
@@ -1921,9 +2226,11 @@ function DataGrid({
|
|
|
1921
2226
|
setShowRowTotals: setPivotShowRowTotals,
|
|
1922
2227
|
setShowColumnTotals: setPivotShowColumnTotals,
|
|
1923
2228
|
setRowFields,
|
|
1924
|
-
setColumnFields
|
|
2229
|
+
setColumnFields,
|
|
2230
|
+
addCalculatedField,
|
|
2231
|
+
removeCalculatedField
|
|
1925
2232
|
} = usePivotTable(filteredDataForPivot);
|
|
1926
|
-
const activeFilterInfo = (0,
|
|
2233
|
+
const activeFilterInfo = (0, import_react9.useMemo)(() => {
|
|
1927
2234
|
if (activeFilters.length === 0) return null;
|
|
1928
2235
|
return activeFilters.map((f) => ({
|
|
1929
2236
|
column: f.column,
|
|
@@ -1931,8 +2238,8 @@ function DataGrid({
|
|
|
1931
2238
|
values: f.values || []
|
|
1932
2239
|
}));
|
|
1933
2240
|
}, [activeFilters]);
|
|
1934
|
-
const rows = (0,
|
|
1935
|
-
const searchFilteredData = (0,
|
|
2241
|
+
const rows = (0, import_react9.useMemo)(() => table.getFilteredRowModel().rows, [table, columnFilters]);
|
|
2242
|
+
const searchFilteredData = (0, import_react9.useMemo)(() => {
|
|
1936
2243
|
if (!globalSearchTerm.trim() || !enableSearch) {
|
|
1937
2244
|
return rows;
|
|
1938
2245
|
}
|
|
@@ -1949,20 +2256,20 @@ function DataGrid({
|
|
|
1949
2256
|
});
|
|
1950
2257
|
}, [rows, globalSearchTerm, enableSearch, columnKeys]);
|
|
1951
2258
|
const totalSearchedRows = searchFilteredData.length;
|
|
1952
|
-
const totalPages = (0,
|
|
2259
|
+
const totalPages = (0, import_react9.useMemo)(() => {
|
|
1953
2260
|
if (!enablePagination) return 1;
|
|
1954
2261
|
return Math.max(1, Math.ceil(totalSearchedRows / pageSize));
|
|
1955
2262
|
}, [enablePagination, totalSearchedRows, pageSize]);
|
|
1956
|
-
const paginatedRows = (0,
|
|
2263
|
+
const paginatedRows = (0, import_react9.useMemo)(() => {
|
|
1957
2264
|
if (!enablePagination) return searchFilteredData;
|
|
1958
2265
|
const start = (currentPage - 1) * pageSize;
|
|
1959
2266
|
const end = start + pageSize;
|
|
1960
2267
|
return searchFilteredData.slice(start, end);
|
|
1961
2268
|
}, [enablePagination, searchFilteredData, currentPage, pageSize]);
|
|
1962
|
-
(0,
|
|
2269
|
+
(0, import_react9.useEffect)(() => {
|
|
1963
2270
|
setCurrentPage(1);
|
|
1964
2271
|
}, [columnFilters, globalSearchTerm]);
|
|
1965
|
-
const selectionBounds = (0,
|
|
2272
|
+
const selectionBounds = (0, import_react9.useMemo)(() => {
|
|
1966
2273
|
if (!selectionStart || !selectionEnd) return null;
|
|
1967
2274
|
return {
|
|
1968
2275
|
minRow: Math.min(selectionStart.row, selectionEnd.row),
|
|
@@ -1971,7 +2278,7 @@ function DataGrid({
|
|
|
1971
2278
|
maxCol: Math.max(selectionStart.col, selectionEnd.col)
|
|
1972
2279
|
};
|
|
1973
2280
|
}, [selectionStart, selectionEnd]);
|
|
1974
|
-
const selectionStats = (0,
|
|
2281
|
+
const selectionStats = (0, import_react9.useMemo)(() => {
|
|
1975
2282
|
if (!selectionBounds) return null;
|
|
1976
2283
|
const { minRow, maxRow, minCol, maxCol } = selectionBounds;
|
|
1977
2284
|
const values = [];
|
|
@@ -1997,7 +2304,7 @@ function DataGrid({
|
|
|
1997
2304
|
const avg = sum / values.length;
|
|
1998
2305
|
return { count, sum, avg, numericCount: values.length };
|
|
1999
2306
|
}, [selectionBounds, rows, columnKeys]);
|
|
2000
|
-
(0,
|
|
2307
|
+
(0, import_react9.useEffect)(() => {
|
|
2001
2308
|
if (data.length === 0) return;
|
|
2002
2309
|
const widths = {};
|
|
2003
2310
|
const sampleSize = Math.min(100, data.length);
|
|
@@ -2017,7 +2324,7 @@ function DataGrid({
|
|
|
2017
2324
|
}
|
|
2018
2325
|
setColumnWidths(widths);
|
|
2019
2326
|
}, [data, columnKeys]);
|
|
2020
|
-
const startColumnResize = (0,
|
|
2327
|
+
const startColumnResize = (0, import_react9.useCallback)(
|
|
2021
2328
|
(columnId, event) => {
|
|
2022
2329
|
if (!enableColumnResize) return;
|
|
2023
2330
|
event.preventDefault();
|
|
@@ -2028,7 +2335,7 @@ function DataGrid({
|
|
|
2028
2335
|
},
|
|
2029
2336
|
[enableColumnResize, columnWidths]
|
|
2030
2337
|
);
|
|
2031
|
-
(0,
|
|
2338
|
+
(0, import_react9.useEffect)(() => {
|
|
2032
2339
|
if (!resizingColumnId) return;
|
|
2033
2340
|
const handleResizeMove = (event) => {
|
|
2034
2341
|
const diff = event.clientX - resizeStartX;
|
|
@@ -2048,7 +2355,7 @@ function DataGrid({
|
|
|
2048
2355
|
document.removeEventListener("mouseup", handleResizeEnd);
|
|
2049
2356
|
};
|
|
2050
2357
|
}, [resizingColumnId, resizeStartX, resizeStartWidth]);
|
|
2051
|
-
const startVerticalResize = (0,
|
|
2358
|
+
const startVerticalResize = (0, import_react9.useCallback)(
|
|
2052
2359
|
(event) => {
|
|
2053
2360
|
if (!enableVerticalResize) return;
|
|
2054
2361
|
event.preventDefault();
|
|
@@ -2058,7 +2365,7 @@ function DataGrid({
|
|
|
2058
2365
|
},
|
|
2059
2366
|
[enableVerticalResize, gridHeight]
|
|
2060
2367
|
);
|
|
2061
|
-
(0,
|
|
2368
|
+
(0, import_react9.useEffect)(() => {
|
|
2062
2369
|
if (!isResizingVertically) return;
|
|
2063
2370
|
const handleVerticalResizeMove = (event) => {
|
|
2064
2371
|
const diff = event.clientY - verticalResizeStartY;
|
|
@@ -2075,7 +2382,7 @@ function DataGrid({
|
|
|
2075
2382
|
document.removeEventListener("mouseup", handleVerticalResizeEnd);
|
|
2076
2383
|
};
|
|
2077
2384
|
}, [isResizingVertically, verticalResizeStartY, verticalResizeStartHeight, minHeight, maxHeight]);
|
|
2078
|
-
const handleExport = (0,
|
|
2385
|
+
const handleExport = (0, import_react9.useCallback)(() => {
|
|
2079
2386
|
if (viewMode === "pivot") {
|
|
2080
2387
|
if (!pivotResult) return;
|
|
2081
2388
|
const pivotFilename = exportFilename.replace(".csv", "-pivot.csv");
|
|
@@ -2120,7 +2427,7 @@ function DataGrid({
|
|
|
2120
2427
|
columnKeys,
|
|
2121
2428
|
onExport
|
|
2122
2429
|
]);
|
|
2123
|
-
const copySelectionToClipboard = (0,
|
|
2430
|
+
const copySelectionToClipboard = (0, import_react9.useCallback)(() => {
|
|
2124
2431
|
if (!selectionBounds || !enableClipboard) return;
|
|
2125
2432
|
const text = formatSelectionForClipboard(
|
|
2126
2433
|
rows.map((r) => r.original),
|
|
@@ -2144,7 +2451,7 @@ function DataGrid({
|
|
|
2144
2451
|
}
|
|
2145
2452
|
);
|
|
2146
2453
|
}, [selectionBounds, enableClipboard, rows, columnKeys, onCopy]);
|
|
2147
|
-
const handleMouseDown = (0,
|
|
2454
|
+
const handleMouseDown = (0, import_react9.useCallback)(
|
|
2148
2455
|
(rowIndex, colIndex, event) => {
|
|
2149
2456
|
event.preventDefault();
|
|
2150
2457
|
if (event.shiftKey && selectedCell) {
|
|
@@ -2168,7 +2475,7 @@ function DataGrid({
|
|
|
2168
2475
|
},
|
|
2169
2476
|
[selectedCell, rows, columnKeys, onCellClick]
|
|
2170
2477
|
);
|
|
2171
|
-
const handleMouseEnter = (0,
|
|
2478
|
+
const handleMouseEnter = (0, import_react9.useCallback)(
|
|
2172
2479
|
(rowIndex, colIndex) => {
|
|
2173
2480
|
if (isSelecting) {
|
|
2174
2481
|
setSelectionEnd({ row: rowIndex, col: colIndex });
|
|
@@ -2176,12 +2483,12 @@ function DataGrid({
|
|
|
2176
2483
|
},
|
|
2177
2484
|
[isSelecting]
|
|
2178
2485
|
);
|
|
2179
|
-
(0,
|
|
2486
|
+
(0, import_react9.useEffect)(() => {
|
|
2180
2487
|
const handleMouseUp = () => setIsSelecting(false);
|
|
2181
2488
|
document.addEventListener("mouseup", handleMouseUp);
|
|
2182
2489
|
return () => document.removeEventListener("mouseup", handleMouseUp);
|
|
2183
2490
|
}, []);
|
|
2184
|
-
(0,
|
|
2491
|
+
(0, import_react9.useEffect)(() => {
|
|
2185
2492
|
const handleKeydown = (event) => {
|
|
2186
2493
|
if ((event.ctrlKey || event.metaKey) && event.key === "c" && selectionBounds) {
|
|
2187
2494
|
event.preventDefault();
|
|
@@ -2199,7 +2506,7 @@ function DataGrid({
|
|
|
2199
2506
|
document.addEventListener("keydown", handleKeydown);
|
|
2200
2507
|
return () => document.removeEventListener("keydown", handleKeydown);
|
|
2201
2508
|
}, [selectionBounds, copySelectionToClipboard]);
|
|
2202
|
-
const openFilterDropdown = (0,
|
|
2509
|
+
const openFilterDropdown = (0, import_react9.useCallback)(
|
|
2203
2510
|
(columnId, event) => {
|
|
2204
2511
|
event.stopPropagation();
|
|
2205
2512
|
const target = event.currentTarget;
|
|
@@ -2228,16 +2535,16 @@ function DataGrid({
|
|
|
2228
2535
|
},
|
|
2229
2536
|
[]
|
|
2230
2537
|
);
|
|
2231
|
-
const closeFilterDropdown = (0,
|
|
2538
|
+
const closeFilterDropdown = (0, import_react9.useCallback)(() => {
|
|
2232
2539
|
setActiveFilterColumn(null);
|
|
2233
2540
|
}, []);
|
|
2234
|
-
const handleFilter = (0,
|
|
2541
|
+
const handleFilter = (0, import_react9.useCallback)(
|
|
2235
2542
|
(columnId, values) => {
|
|
2236
2543
|
setColumnFilter(columnId, values);
|
|
2237
2544
|
},
|
|
2238
2545
|
[setColumnFilter]
|
|
2239
2546
|
);
|
|
2240
|
-
const handleSort = (0,
|
|
2547
|
+
const handleSort = (0, import_react9.useCallback)(
|
|
2241
2548
|
(columnId, direction) => {
|
|
2242
2549
|
if (direction === null) {
|
|
2243
2550
|
const current = getSortDirection(columnId);
|
|
@@ -2261,7 +2568,7 @@ function DataGrid({
|
|
|
2261
2568
|
},
|
|
2262
2569
|
[getSortDirection, toggleSort]
|
|
2263
2570
|
);
|
|
2264
|
-
const isCellSelected = (0,
|
|
2571
|
+
const isCellSelected = (0, import_react9.useCallback)(
|
|
2265
2572
|
(rowIndex, colIndex) => {
|
|
2266
2573
|
if (!selectionBounds) {
|
|
2267
2574
|
return selectedCell?.row === rowIndex && selectedCell?.col === colIndex;
|
|
@@ -2299,30 +2606,30 @@ function DataGrid({
|
|
|
2299
2606
|
}
|
|
2300
2607
|
return String(value);
|
|
2301
2608
|
};
|
|
2302
|
-
const totalTableWidth = (0,
|
|
2609
|
+
const totalTableWidth = (0, import_react9.useMemo)(() => {
|
|
2303
2610
|
return columnKeys.reduce((sum, key) => sum + (columnWidths[key] || MIN_COL_WIDTH), 0);
|
|
2304
2611
|
}, [columnKeys, columnWidths]);
|
|
2305
2612
|
const activeFilterCount = columnFilters.length;
|
|
2306
|
-
return /* @__PURE__ */ (0,
|
|
2613
|
+
return /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(
|
|
2307
2614
|
"div",
|
|
2308
2615
|
{
|
|
2309
2616
|
className: `vpg-data-grid vpg-font-${currentFontSize} vpg-theme-${currentTheme} ${stripedRows ? "vpg-striped" : ""} ${resizingColumnId ? "vpg-resizing" : ""} ${isResizingVertically ? "vpg-resizing-vertical" : ""}`,
|
|
2310
2617
|
style: { height: `${gridHeight}px` },
|
|
2311
2618
|
children: [
|
|
2312
|
-
showCopyToast && /* @__PURE__ */ (0,
|
|
2313
|
-
/* @__PURE__ */ (0,
|
|
2619
|
+
showCopyToast && /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { className: "vpg-toast", children: [
|
|
2620
|
+
/* @__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" }) }),
|
|
2314
2621
|
copyToastMessage
|
|
2315
2622
|
] }),
|
|
2316
|
-
/* @__PURE__ */ (0,
|
|
2317
|
-
/* @__PURE__ */ (0,
|
|
2318
|
-
showPivot && /* @__PURE__ */ (0,
|
|
2319
|
-
/* @__PURE__ */ (0,
|
|
2623
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { className: "vpg-toolbar", children: [
|
|
2624
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { className: "vpg-toolbar-left", children: [
|
|
2625
|
+
showPivot && /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { className: "vpg-view-toggle", children: [
|
|
2626
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(
|
|
2320
2627
|
"button",
|
|
2321
2628
|
{
|
|
2322
2629
|
className: `vpg-view-btn ${viewMode === "grid" ? "active" : ""}`,
|
|
2323
2630
|
onClick: () => setViewMode("grid"),
|
|
2324
2631
|
children: [
|
|
2325
|
-
/* @__PURE__ */ (0,
|
|
2632
|
+
/* @__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)(
|
|
2326
2633
|
"path",
|
|
2327
2634
|
{
|
|
2328
2635
|
strokeLinecap: "round",
|
|
@@ -2335,13 +2642,13 @@ function DataGrid({
|
|
|
2335
2642
|
]
|
|
2336
2643
|
}
|
|
2337
2644
|
),
|
|
2338
|
-
/* @__PURE__ */ (0,
|
|
2645
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(
|
|
2339
2646
|
"button",
|
|
2340
2647
|
{
|
|
2341
2648
|
className: `vpg-view-btn vpg-pivot-btn ${viewMode === "pivot" ? "active" : ""}`,
|
|
2342
2649
|
onClick: () => setViewMode("pivot"),
|
|
2343
2650
|
children: [
|
|
2344
|
-
/* @__PURE__ */ (0,
|
|
2651
|
+
/* @__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)(
|
|
2345
2652
|
"path",
|
|
2346
2653
|
{
|
|
2347
2654
|
strokeLinecap: "round",
|
|
@@ -2355,14 +2662,14 @@ function DataGrid({
|
|
|
2355
2662
|
}
|
|
2356
2663
|
)
|
|
2357
2664
|
] }),
|
|
2358
|
-
viewMode === "grid" && /* @__PURE__ */ (0,
|
|
2359
|
-
enableSearch && /* @__PURE__ */ (0,
|
|
2665
|
+
viewMode === "grid" && /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(import_jsx_runtime5.Fragment, { children: [
|
|
2666
|
+
enableSearch && /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("div", { className: "vpg-search-container", children: !showSearchInput ? /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
|
|
2360
2667
|
"button",
|
|
2361
2668
|
{
|
|
2362
2669
|
className: "vpg-icon-btn",
|
|
2363
2670
|
title: "Search (Ctrl+F)",
|
|
2364
2671
|
onClick: () => setShowSearchInput(true),
|
|
2365
|
-
children: /* @__PURE__ */ (0,
|
|
2672
|
+
children: /* @__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)(
|
|
2366
2673
|
"path",
|
|
2367
2674
|
{
|
|
2368
2675
|
strokeLinecap: "round",
|
|
@@ -2372,15 +2679,15 @@ function DataGrid({
|
|
|
2372
2679
|
}
|
|
2373
2680
|
) })
|
|
2374
2681
|
}
|
|
2375
|
-
) : /* @__PURE__ */ (0,
|
|
2376
|
-
/* @__PURE__ */ (0,
|
|
2682
|
+
) : /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { className: "vpg-search-box", children: [
|
|
2683
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
|
|
2377
2684
|
"svg",
|
|
2378
2685
|
{
|
|
2379
2686
|
className: "vpg-search-icon",
|
|
2380
2687
|
fill: "none",
|
|
2381
2688
|
stroke: "currentColor",
|
|
2382
2689
|
viewBox: "0 0 24 24",
|
|
2383
|
-
children: /* @__PURE__ */ (0,
|
|
2690
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
|
|
2384
2691
|
"path",
|
|
2385
2692
|
{
|
|
2386
2693
|
strokeLinecap: "round",
|
|
@@ -2391,7 +2698,7 @@ function DataGrid({
|
|
|
2391
2698
|
)
|
|
2392
2699
|
}
|
|
2393
2700
|
),
|
|
2394
|
-
/* @__PURE__ */ (0,
|
|
2701
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
|
|
2395
2702
|
"input",
|
|
2396
2703
|
{
|
|
2397
2704
|
type: "text",
|
|
@@ -2408,14 +2715,14 @@ function DataGrid({
|
|
|
2408
2715
|
autoFocus: true
|
|
2409
2716
|
}
|
|
2410
2717
|
),
|
|
2411
|
-
globalSearchTerm && /* @__PURE__ */ (0,
|
|
2718
|
+
globalSearchTerm && /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("button", { className: "vpg-search-clear", onClick: () => setGlobalSearchTerm(""), children: /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
|
|
2412
2719
|
"svg",
|
|
2413
2720
|
{
|
|
2414
2721
|
className: "vpg-icon-xs",
|
|
2415
2722
|
fill: "none",
|
|
2416
2723
|
stroke: "currentColor",
|
|
2417
2724
|
viewBox: "0 0 24 24",
|
|
2418
|
-
children: /* @__PURE__ */ (0,
|
|
2725
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
|
|
2419
2726
|
"path",
|
|
2420
2727
|
{
|
|
2421
2728
|
strokeLinecap: "round",
|
|
@@ -2427,9 +2734,9 @@ function DataGrid({
|
|
|
2427
2734
|
}
|
|
2428
2735
|
) })
|
|
2429
2736
|
] }) }),
|
|
2430
|
-
/* @__PURE__ */ (0,
|
|
2431
|
-
/* @__PURE__ */ (0,
|
|
2432
|
-
/* @__PURE__ */ (0,
|
|
2737
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { className: "vpg-font-size-control", children: [
|
|
2738
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)("span", { className: "vpg-label", children: "Size:" }),
|
|
2739
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)("div", { className: "vpg-font-size-toggle", children: fontSizeOptions.map((opt) => /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
|
|
2433
2740
|
"button",
|
|
2434
2741
|
{
|
|
2435
2742
|
className: `vpg-font-size-btn ${currentFontSize === opt.value ? "active" : ""}`,
|
|
@@ -2439,8 +2746,8 @@ function DataGrid({
|
|
|
2439
2746
|
opt.value
|
|
2440
2747
|
)) })
|
|
2441
2748
|
] }),
|
|
2442
|
-
activeFilterCount > 0 && /* @__PURE__ */ (0,
|
|
2443
|
-
/* @__PURE__ */ (0,
|
|
2749
|
+
activeFilterCount > 0 && /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { className: "vpg-filter-info", children: [
|
|
2750
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)("svg", { className: "vpg-icon", fill: "currentColor", viewBox: "0 0 20 20", children: /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
|
|
2444
2751
|
"path",
|
|
2445
2752
|
{
|
|
2446
2753
|
fillRule: "evenodd",
|
|
@@ -2448,26 +2755,26 @@ function DataGrid({
|
|
|
2448
2755
|
clipRule: "evenodd"
|
|
2449
2756
|
}
|
|
2450
2757
|
) }),
|
|
2451
|
-
/* @__PURE__ */ (0,
|
|
2758
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("span", { children: [
|
|
2452
2759
|
activeFilterCount,
|
|
2453
2760
|
" filter",
|
|
2454
2761
|
activeFilterCount > 1 ? "s" : ""
|
|
2455
2762
|
] })
|
|
2456
2763
|
] }),
|
|
2457
|
-
globalSearchTerm && /* @__PURE__ */ (0,
|
|
2764
|
+
globalSearchTerm && /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("div", { className: "vpg-search-info", children: /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("span", { children: [
|
|
2458
2765
|
totalSearchedRows,
|
|
2459
2766
|
" match",
|
|
2460
2767
|
totalSearchedRows !== 1 ? "es" : ""
|
|
2461
2768
|
] }) })
|
|
2462
2769
|
] }),
|
|
2463
|
-
viewMode === "pivot" && canUsePivot && /* @__PURE__ */ (0,
|
|
2464
|
-
/* @__PURE__ */ (0,
|
|
2770
|
+
viewMode === "pivot" && canUsePivot && /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(import_jsx_runtime5.Fragment, { children: [
|
|
2771
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(
|
|
2465
2772
|
"button",
|
|
2466
2773
|
{
|
|
2467
2774
|
className: `vpg-config-toggle ${showPivotConfig ? "active" : ""}`,
|
|
2468
2775
|
onClick: () => setShowPivotConfig(!showPivotConfig),
|
|
2469
2776
|
children: [
|
|
2470
|
-
/* @__PURE__ */ (0,
|
|
2777
|
+
/* @__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)(
|
|
2471
2778
|
"path",
|
|
2472
2779
|
{
|
|
2473
2780
|
strokeLinecap: "round",
|
|
@@ -2481,8 +2788,8 @@ function DataGrid({
|
|
|
2481
2788
|
]
|
|
2482
2789
|
}
|
|
2483
2790
|
),
|
|
2484
|
-
pivotIsConfigured && /* @__PURE__ */ (0,
|
|
2485
|
-
/* @__PURE__ */ (0,
|
|
2791
|
+
pivotIsConfigured && /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { className: "vpg-pivot-status", children: [
|
|
2792
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)("svg", { className: "vpg-icon", fill: "currentColor", viewBox: "0 0 20 20", children: /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
|
|
2486
2793
|
"path",
|
|
2487
2794
|
{
|
|
2488
2795
|
fillRule: "evenodd",
|
|
@@ -2490,13 +2797,13 @@ function DataGrid({
|
|
|
2490
2797
|
clipRule: "evenodd"
|
|
2491
2798
|
}
|
|
2492
2799
|
) }),
|
|
2493
|
-
/* @__PURE__ */ (0,
|
|
2800
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)("span", { children: "Pivot configured" })
|
|
2494
2801
|
] })
|
|
2495
2802
|
] })
|
|
2496
2803
|
] }),
|
|
2497
|
-
/* @__PURE__ */ (0,
|
|
2498
|
-
viewMode === "grid" && activeFilterCount > 0 && /* @__PURE__ */ (0,
|
|
2499
|
-
/* @__PURE__ */ (0,
|
|
2804
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { className: "vpg-toolbar-right", children: [
|
|
2805
|
+
viewMode === "grid" && activeFilterCount > 0 && /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("button", { className: "vpg-clear-filters", onClick: clearAllFilters, children: [
|
|
2806
|
+
/* @__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)(
|
|
2500
2807
|
"path",
|
|
2501
2808
|
{
|
|
2502
2809
|
strokeLinecap: "round",
|
|
@@ -2507,13 +2814,13 @@ function DataGrid({
|
|
|
2507
2814
|
) }),
|
|
2508
2815
|
"Clear Filters"
|
|
2509
2816
|
] }),
|
|
2510
|
-
enableClipboard && selectionBounds && viewMode === "grid" && /* @__PURE__ */ (0,
|
|
2817
|
+
enableClipboard && selectionBounds && viewMode === "grid" && /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
|
|
2511
2818
|
"button",
|
|
2512
2819
|
{
|
|
2513
2820
|
className: "vpg-icon-btn",
|
|
2514
2821
|
title: "Copy selection (Ctrl+C)",
|
|
2515
2822
|
onClick: copySelectionToClipboard,
|
|
2516
|
-
children: /* @__PURE__ */ (0,
|
|
2823
|
+
children: /* @__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)(
|
|
2517
2824
|
"path",
|
|
2518
2825
|
{
|
|
2519
2826
|
strokeLinecap: "round",
|
|
@@ -2524,14 +2831,14 @@ function DataGrid({
|
|
|
2524
2831
|
) })
|
|
2525
2832
|
}
|
|
2526
2833
|
),
|
|
2527
|
-
enableExport && (viewMode === "grid" || viewMode === "pivot" && pivotIsConfigured) && /* @__PURE__ */ (0,
|
|
2834
|
+
enableExport && (viewMode === "grid" || viewMode === "pivot" && pivotIsConfigured) && /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(
|
|
2528
2835
|
"button",
|
|
2529
2836
|
{
|
|
2530
2837
|
className: "vpg-export-btn",
|
|
2531
2838
|
title: viewMode === "pivot" ? "Export Pivot to CSV" : "Export to CSV",
|
|
2532
2839
|
onClick: handleExport,
|
|
2533
2840
|
children: [
|
|
2534
|
-
/* @__PURE__ */ (0,
|
|
2841
|
+
/* @__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)(
|
|
2535
2842
|
"path",
|
|
2536
2843
|
{
|
|
2537
2844
|
strokeLinecap: "round",
|
|
@@ -2547,13 +2854,13 @@ function DataGrid({
|
|
|
2547
2854
|
)
|
|
2548
2855
|
] })
|
|
2549
2856
|
] }),
|
|
2550
|
-
viewMode === "grid" && /* @__PURE__ */ (0,
|
|
2551
|
-
loading && /* @__PURE__ */ (0,
|
|
2552
|
-
/* @__PURE__ */ (0,
|
|
2553
|
-
/* @__PURE__ */ (0,
|
|
2857
|
+
viewMode === "grid" && /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { ref: tableContainerRef, className: "vpg-grid-container", tabIndex: 0, children: [
|
|
2858
|
+
loading && /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { className: "vpg-loading", children: [
|
|
2859
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)("div", { className: "vpg-spinner" }),
|
|
2860
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)("span", { children: "Loading data..." })
|
|
2554
2861
|
] }),
|
|
2555
|
-
!loading && data.length === 0 && /* @__PURE__ */ (0,
|
|
2556
|
-
/* @__PURE__ */ (0,
|
|
2862
|
+
!loading && data.length === 0 && /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { className: "vpg-empty", children: [
|
|
2863
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)("div", { className: "vpg-empty-icon", children: /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("svg", { className: "vpg-icon-lg", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
|
|
2557
2864
|
"path",
|
|
2558
2865
|
{
|
|
2559
2866
|
strokeLinecap: "round",
|
|
@@ -2562,10 +2869,10 @@ function DataGrid({
|
|
|
2562
2869
|
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"
|
|
2563
2870
|
}
|
|
2564
2871
|
) }) }),
|
|
2565
|
-
/* @__PURE__ */ (0,
|
|
2872
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)("span", { children: "No data available" })
|
|
2566
2873
|
] }),
|
|
2567
|
-
!loading && data.length > 0 && filteredRowCount === 0 && /* @__PURE__ */ (0,
|
|
2568
|
-
/* @__PURE__ */ (0,
|
|
2874
|
+
!loading && data.length > 0 && filteredRowCount === 0 && /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { className: "vpg-empty", children: [
|
|
2875
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)("div", { className: "vpg-empty-icon vpg-warning", children: /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("svg", { className: "vpg-icon-lg", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
|
|
2569
2876
|
"path",
|
|
2570
2877
|
{
|
|
2571
2878
|
strokeLinecap: "round",
|
|
@@ -2574,11 +2881,11 @@ function DataGrid({
|
|
|
2574
2881
|
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"
|
|
2575
2882
|
}
|
|
2576
2883
|
) }) }),
|
|
2577
|
-
/* @__PURE__ */ (0,
|
|
2578
|
-
/* @__PURE__ */ (0,
|
|
2884
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)("span", { children: "No matching records" }),
|
|
2885
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)("button", { className: "vpg-clear-link", onClick: clearAllFilters, children: "Clear all filters" })
|
|
2579
2886
|
] }),
|
|
2580
|
-
!loading && filteredRowCount > 0 && /* @__PURE__ */ (0,
|
|
2581
|
-
/* @__PURE__ */ (0,
|
|
2887
|
+
!loading && filteredRowCount > 0 && /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("div", { className: "vpg-table-wrapper", children: /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("table", { className: "vpg-table", style: { minWidth: `${totalTableWidth}px` }, children: [
|
|
2888
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)("thead", { children: /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("tr", { children: columnKeys.map((colId, colIndex) => /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(
|
|
2582
2889
|
"th",
|
|
2583
2890
|
{
|
|
2584
2891
|
className: `vpg-header-cell ${hasActiveFilter(colId) ? "vpg-has-filter" : ""} ${getSortDirection(colId) !== null ? "vpg-is-sorted" : ""} ${activeFilterColumn === colId ? "vpg-is-active" : ""}`,
|
|
@@ -2593,16 +2900,16 @@ function DataGrid({
|
|
|
2593
2900
|
}
|
|
2594
2901
|
},
|
|
2595
2902
|
children: [
|
|
2596
|
-
/* @__PURE__ */ (0,
|
|
2597
|
-
/* @__PURE__ */ (0,
|
|
2598
|
-
/* @__PURE__ */ (0,
|
|
2599
|
-
getSortDirection(colId) && /* @__PURE__ */ (0,
|
|
2903
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { className: "vpg-header-content", children: [
|
|
2904
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)("span", { className: "vpg-header-text", children: colId }),
|
|
2905
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { className: "vpg-header-icons", children: [
|
|
2906
|
+
getSortDirection(colId) && /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("span", { className: "vpg-sort-indicator", children: getSortDirection(colId) === "asc" ? /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
|
|
2600
2907
|
"svg",
|
|
2601
2908
|
{
|
|
2602
2909
|
className: "vpg-icon-sm",
|
|
2603
2910
|
fill: "currentColor",
|
|
2604
2911
|
viewBox: "0 0 20 20",
|
|
2605
|
-
children: /* @__PURE__ */ (0,
|
|
2912
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
|
|
2606
2913
|
"path",
|
|
2607
2914
|
{
|
|
2608
2915
|
fillRule: "evenodd",
|
|
@@ -2611,13 +2918,13 @@ function DataGrid({
|
|
|
2611
2918
|
}
|
|
2612
2919
|
)
|
|
2613
2920
|
}
|
|
2614
|
-
) : /* @__PURE__ */ (0,
|
|
2921
|
+
) : /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
|
|
2615
2922
|
"svg",
|
|
2616
2923
|
{
|
|
2617
2924
|
className: "vpg-icon-sm",
|
|
2618
2925
|
fill: "currentColor",
|
|
2619
2926
|
viewBox: "0 0 20 20",
|
|
2620
|
-
children: /* @__PURE__ */ (0,
|
|
2927
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
|
|
2621
2928
|
"path",
|
|
2622
2929
|
{
|
|
2623
2930
|
fillRule: "evenodd",
|
|
@@ -2627,13 +2934,13 @@ function DataGrid({
|
|
|
2627
2934
|
)
|
|
2628
2935
|
}
|
|
2629
2936
|
) }),
|
|
2630
|
-
hasActiveFilter(colId) && /* @__PURE__ */ (0,
|
|
2937
|
+
hasActiveFilter(colId) && /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("span", { className: "vpg-filter-indicator", children: /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
|
|
2631
2938
|
"svg",
|
|
2632
2939
|
{
|
|
2633
2940
|
className: "vpg-icon-xs",
|
|
2634
2941
|
fill: "currentColor",
|
|
2635
2942
|
viewBox: "0 0 20 20",
|
|
2636
|
-
children: /* @__PURE__ */ (0,
|
|
2943
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
|
|
2637
2944
|
"path",
|
|
2638
2945
|
{
|
|
2639
2946
|
fillRule: "evenodd",
|
|
@@ -2643,14 +2950,14 @@ function DataGrid({
|
|
|
2643
2950
|
)
|
|
2644
2951
|
}
|
|
2645
2952
|
) }),
|
|
2646
|
-
/* @__PURE__ */ (0,
|
|
2953
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)("span", { className: "vpg-dropdown-arrow", title: "Filter & Sort", children: /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
|
|
2647
2954
|
"svg",
|
|
2648
2955
|
{
|
|
2649
2956
|
className: "vpg-icon-sm",
|
|
2650
2957
|
fill: "none",
|
|
2651
2958
|
stroke: "currentColor",
|
|
2652
2959
|
viewBox: "0 0 24 24",
|
|
2653
|
-
children: /* @__PURE__ */ (0,
|
|
2960
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
|
|
2654
2961
|
"path",
|
|
2655
2962
|
{
|
|
2656
2963
|
strokeLinecap: "round",
|
|
@@ -2663,7 +2970,7 @@ function DataGrid({
|
|
|
2663
2970
|
) })
|
|
2664
2971
|
] })
|
|
2665
2972
|
] }),
|
|
2666
|
-
enableColumnResize && /* @__PURE__ */ (0,
|
|
2973
|
+
enableColumnResize && /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
|
|
2667
2974
|
"div",
|
|
2668
2975
|
{
|
|
2669
2976
|
className: "vpg-resize-handle",
|
|
@@ -2674,7 +2981,7 @@ function DataGrid({
|
|
|
2674
2981
|
},
|
|
2675
2982
|
colId
|
|
2676
2983
|
)) }) }),
|
|
2677
|
-
/* @__PURE__ */ (0,
|
|
2984
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)("tbody", { ref: tableBodyRef, children: paginatedRows.map((row, rowIndex) => /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("tr", { className: "vpg-row", children: columnKeys.map((colId, colIndex) => /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
|
|
2678
2985
|
"td",
|
|
2679
2986
|
{
|
|
2680
2987
|
className: `vpg-cell ${isCellSelected(rowIndex, colIndex) ? "vpg-selected" : ""} ${getColumnStats(colId).type === "number" ? "vpg-is-number" : ""}`,
|
|
@@ -2692,8 +2999,8 @@ function DataGrid({
|
|
|
2692
2999
|
)) }, row.id)) })
|
|
2693
3000
|
] }) })
|
|
2694
3001
|
] }),
|
|
2695
|
-
viewMode === "pivot" && /* @__PURE__ */ (0,
|
|
2696
|
-
showPivotConfig && canUsePivot && /* @__PURE__ */ (0,
|
|
3002
|
+
viewMode === "pivot" && /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { className: "vpg-pivot-container", children: [
|
|
3003
|
+
showPivotConfig && canUsePivot && /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("div", { className: "vpg-pivot-config-panel", children: /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
|
|
2697
3004
|
PivotConfig,
|
|
2698
3005
|
{
|
|
2699
3006
|
availableFields: pivotAvailableFields,
|
|
@@ -2702,6 +3009,7 @@ function DataGrid({
|
|
|
2702
3009
|
valueFields: pivotValueFields,
|
|
2703
3010
|
showRowTotals: pivotShowRowTotals,
|
|
2704
3011
|
showColumnTotals: pivotShowColumnTotals,
|
|
3012
|
+
calculatedFields: pivotCalculatedFields,
|
|
2705
3013
|
onShowRowTotalsChange: setPivotShowRowTotals,
|
|
2706
3014
|
onShowColumnTotalsChange: setPivotShowColumnTotals,
|
|
2707
3015
|
onClearConfig: clearPivotConfig,
|
|
@@ -2714,10 +3022,13 @@ function DataGrid({
|
|
|
2714
3022
|
onAddColumnField: addColumnField,
|
|
2715
3023
|
onRemoveColumnField: removeColumnField,
|
|
2716
3024
|
onAddValueField: addValueField,
|
|
2717
|
-
onRemoveValueField: removeValueField
|
|
3025
|
+
onRemoveValueField: removeValueField,
|
|
3026
|
+
onAddCalculatedField: addCalculatedField,
|
|
3027
|
+
onRemoveCalculatedField: removeCalculatedField,
|
|
3028
|
+
onUpdateCalculatedField: addCalculatedField
|
|
2718
3029
|
}
|
|
2719
3030
|
) }),
|
|
2720
|
-
/* @__PURE__ */ (0,
|
|
3031
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)("div", { className: `vpg-pivot-main ${!showPivotConfig ? "vpg-full-width" : ""}`, children: /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
|
|
2721
3032
|
PivotSkeleton,
|
|
2722
3033
|
{
|
|
2723
3034
|
rowFields: pivotRowFields,
|
|
@@ -2742,44 +3053,44 @@ function DataGrid({
|
|
|
2742
3053
|
}
|
|
2743
3054
|
) })
|
|
2744
3055
|
] }),
|
|
2745
|
-
/* @__PURE__ */ (0,
|
|
2746
|
-
/* @__PURE__ */ (0,
|
|
2747
|
-
/* @__PURE__ */ (0,
|
|
3056
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { className: "vpg-footer", children: [
|
|
3057
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)("div", { className: "vpg-footer-left", children: viewMode === "grid" ? enablePagination ? /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(import_jsx_runtime5.Fragment, { children: [
|
|
3058
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("span", { children: [
|
|
2748
3059
|
((currentPage - 1) * pageSize + 1).toLocaleString(),
|
|
2749
3060
|
"-",
|
|
2750
3061
|
Math.min(currentPage * pageSize, totalSearchedRows).toLocaleString()
|
|
2751
3062
|
] }),
|
|
2752
|
-
/* @__PURE__ */ (0,
|
|
2753
|
-
/* @__PURE__ */ (0,
|
|
2754
|
-
totalSearchedRows !== totalRowCount && /* @__PURE__ */ (0,
|
|
3063
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)("span", { className: "vpg-separator", children: "of" }),
|
|
3064
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)("span", { children: totalSearchedRows.toLocaleString() }),
|
|
3065
|
+
totalSearchedRows !== totalRowCount && /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("span", { className: "vpg-filtered-note", children: [
|
|
2755
3066
|
"(",
|
|
2756
3067
|
totalRowCount.toLocaleString(),
|
|
2757
3068
|
" total)"
|
|
2758
3069
|
] })
|
|
2759
|
-
] }) : filteredRowCount === totalRowCount && totalSearchedRows === totalRowCount ? /* @__PURE__ */ (0,
|
|
3070
|
+
] }) : filteredRowCount === totalRowCount && totalSearchedRows === totalRowCount ? /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("span", { children: [
|
|
2760
3071
|
totalRowCount.toLocaleString(),
|
|
2761
3072
|
" records"
|
|
2762
|
-
] }) : /* @__PURE__ */ (0,
|
|
2763
|
-
/* @__PURE__ */ (0,
|
|
2764
|
-
/* @__PURE__ */ (0,
|
|
2765
|
-
/* @__PURE__ */ (0,
|
|
2766
|
-
/* @__PURE__ */ (0,
|
|
2767
|
-
] }) : /* @__PURE__ */ (0,
|
|
2768
|
-
/* @__PURE__ */ (0,
|
|
2769
|
-
/* @__PURE__ */ (0,
|
|
2770
|
-
/* @__PURE__ */ (0,
|
|
3073
|
+
] }) : /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(import_jsx_runtime5.Fragment, { children: [
|
|
3074
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)("span", { className: "vpg-filtered-count", children: totalSearchedRows.toLocaleString() }),
|
|
3075
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)("span", { className: "vpg-separator", children: "of" }),
|
|
3076
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)("span", { children: totalRowCount.toLocaleString() }),
|
|
3077
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)("span", { className: "vpg-separator", children: "records" })
|
|
3078
|
+
] }) : /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(import_jsx_runtime5.Fragment, { children: [
|
|
3079
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)("span", { className: "vpg-pivot-label", children: "Pivot Table" }),
|
|
3080
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)("span", { className: "vpg-separator", children: "\u2022" }),
|
|
3081
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("span", { children: [
|
|
2771
3082
|
totalRowCount.toLocaleString(),
|
|
2772
3083
|
" source records"
|
|
2773
3084
|
] })
|
|
2774
3085
|
] }) }),
|
|
2775
|
-
enablePagination && viewMode === "grid" && totalPages > 1 && /* @__PURE__ */ (0,
|
|
2776
|
-
/* @__PURE__ */ (0,
|
|
3086
|
+
enablePagination && viewMode === "grid" && totalPages > 1 && /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { className: "vpg-pagination", children: [
|
|
3087
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
|
|
2777
3088
|
"button",
|
|
2778
3089
|
{
|
|
2779
3090
|
className: "vpg-page-btn",
|
|
2780
3091
|
disabled: currentPage === 1,
|
|
2781
3092
|
onClick: () => setCurrentPage(1),
|
|
2782
|
-
children: /* @__PURE__ */ (0,
|
|
3093
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("svg", { className: "vpg-icon-sm", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
|
|
2783
3094
|
"path",
|
|
2784
3095
|
{
|
|
2785
3096
|
strokeLinecap: "round",
|
|
@@ -2790,13 +3101,13 @@ function DataGrid({
|
|
|
2790
3101
|
) })
|
|
2791
3102
|
}
|
|
2792
3103
|
),
|
|
2793
|
-
/* @__PURE__ */ (0,
|
|
3104
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
|
|
2794
3105
|
"button",
|
|
2795
3106
|
{
|
|
2796
3107
|
className: "vpg-page-btn",
|
|
2797
3108
|
disabled: currentPage === 1,
|
|
2798
3109
|
onClick: () => setCurrentPage((p) => Math.max(1, p - 1)),
|
|
2799
|
-
children: /* @__PURE__ */ (0,
|
|
3110
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("svg", { className: "vpg-icon-sm", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
|
|
2800
3111
|
"path",
|
|
2801
3112
|
{
|
|
2802
3113
|
strokeLinecap: "round",
|
|
@@ -2807,19 +3118,19 @@ function DataGrid({
|
|
|
2807
3118
|
) })
|
|
2808
3119
|
}
|
|
2809
3120
|
),
|
|
2810
|
-
/* @__PURE__ */ (0,
|
|
3121
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("span", { className: "vpg-page-info", children: [
|
|
2811
3122
|
"Page ",
|
|
2812
3123
|
currentPage,
|
|
2813
3124
|
" of ",
|
|
2814
3125
|
totalPages
|
|
2815
3126
|
] }),
|
|
2816
|
-
/* @__PURE__ */ (0,
|
|
3127
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
|
|
2817
3128
|
"button",
|
|
2818
3129
|
{
|
|
2819
3130
|
className: "vpg-page-btn",
|
|
2820
3131
|
disabled: currentPage === totalPages,
|
|
2821
3132
|
onClick: () => setCurrentPage((p) => Math.min(totalPages, p + 1)),
|
|
2822
|
-
children: /* @__PURE__ */ (0,
|
|
3133
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("svg", { className: "vpg-icon-sm", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
|
|
2823
3134
|
"path",
|
|
2824
3135
|
{
|
|
2825
3136
|
strokeLinecap: "round",
|
|
@@ -2830,13 +3141,13 @@ function DataGrid({
|
|
|
2830
3141
|
) })
|
|
2831
3142
|
}
|
|
2832
3143
|
),
|
|
2833
|
-
/* @__PURE__ */ (0,
|
|
3144
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
|
|
2834
3145
|
"button",
|
|
2835
3146
|
{
|
|
2836
3147
|
className: "vpg-page-btn",
|
|
2837
3148
|
disabled: currentPage === totalPages,
|
|
2838
3149
|
onClick: () => setCurrentPage(totalPages),
|
|
2839
|
-
children: /* @__PURE__ */ (0,
|
|
3150
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("svg", { className: "vpg-icon-sm", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
|
|
2840
3151
|
"path",
|
|
2841
3152
|
{
|
|
2842
3153
|
strokeLinecap: "round",
|
|
@@ -2848,45 +3159,45 @@ function DataGrid({
|
|
|
2848
3159
|
}
|
|
2849
3160
|
)
|
|
2850
3161
|
] }),
|
|
2851
|
-
viewMode === "grid" && selectionStats && selectionStats.count > 1 && /* @__PURE__ */ (0,
|
|
2852
|
-
/* @__PURE__ */ (0,
|
|
2853
|
-
/* @__PURE__ */ (0,
|
|
2854
|
-
/* @__PURE__ */ (0,
|
|
3162
|
+
viewMode === "grid" && selectionStats && selectionStats.count > 1 && /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { className: "vpg-selection-stats", children: [
|
|
3163
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("span", { className: "vpg-stat", children: [
|
|
3164
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)("span", { className: "vpg-stat-label", children: "Count:" }),
|
|
3165
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)("span", { className: "vpg-stat-value", children: selectionStats.count })
|
|
2855
3166
|
] }),
|
|
2856
|
-
selectionStats.numericCount > 0 && /* @__PURE__ */ (0,
|
|
2857
|
-
/* @__PURE__ */ (0,
|
|
2858
|
-
/* @__PURE__ */ (0,
|
|
2859
|
-
/* @__PURE__ */ (0,
|
|
2860
|
-
/* @__PURE__ */ (0,
|
|
3167
|
+
selectionStats.numericCount > 0 && /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(import_jsx_runtime5.Fragment, { children: [
|
|
3168
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)("span", { className: "vpg-stat-divider", children: "|" }),
|
|
3169
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("span", { className: "vpg-stat", children: [
|
|
3170
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)("span", { className: "vpg-stat-label", children: "Sum:" }),
|
|
3171
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)("span", { className: "vpg-stat-value", children: formatStatValue(selectionStats.sum) })
|
|
2861
3172
|
] }),
|
|
2862
|
-
/* @__PURE__ */ (0,
|
|
2863
|
-
/* @__PURE__ */ (0,
|
|
2864
|
-
/* @__PURE__ */ (0,
|
|
2865
|
-
/* @__PURE__ */ (0,
|
|
3173
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)("span", { className: "vpg-stat-divider", children: "|" }),
|
|
3174
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("span", { className: "vpg-stat", children: [
|
|
3175
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)("span", { className: "vpg-stat-label", children: "Avg:" }),
|
|
3176
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)("span", { className: "vpg-stat-value", children: formatStatValue(selectionStats.avg) })
|
|
2866
3177
|
] })
|
|
2867
3178
|
] })
|
|
2868
3179
|
] }),
|
|
2869
|
-
/* @__PURE__ */ (0,
|
|
2870
|
-
/* @__PURE__ */ (0,
|
|
2871
|
-
/* @__PURE__ */ (0,
|
|
2872
|
-
/* @__PURE__ */ (0,
|
|
2873
|
-
] }) : showWatermark ? /* @__PURE__ */ (0,
|
|
2874
|
-
/* @__PURE__ */ (0,
|
|
2875
|
-
/* @__PURE__ */ (0,
|
|
2876
|
-
/* @__PURE__ */ (0,
|
|
2877
|
-
/* @__PURE__ */ (0,
|
|
2878
|
-
/* @__PURE__ */ (0,
|
|
3180
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)("div", { className: "vpg-footer-right", children: isDemo ? /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { className: "vpg-demo-banner", children: [
|
|
3181
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)("span", { className: "vpg-demo-badge", children: "DEMO" }),
|
|
3182
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)("span", { children: "Pro features enabled" }),
|
|
3183
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)("a", { href: "https://tiny-pivot.com/#pricing", target: "_blank", rel: "noopener noreferrer", children: "Get License \u2192" })
|
|
3184
|
+
] }) : showWatermark ? /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("span", { className: "vpg-watermark-inline", children: /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("a", { href: "https://tiny-pivot.com", target: "_blank", rel: "noopener noreferrer", children: [
|
|
3185
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.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: [
|
|
3186
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)("rect", { x: "3", y: "3", width: "7", height: "7" }),
|
|
3187
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)("rect", { x: "14", y: "3", width: "7", height: "7" }),
|
|
3188
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)("rect", { x: "14", y: "14", width: "7", height: "7" }),
|
|
3189
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)("rect", { x: "3", y: "14", width: "7", height: "7" })
|
|
2879
3190
|
] }),
|
|
2880
3191
|
"Powered by TinyPivot"
|
|
2881
3192
|
] }) }) : null })
|
|
2882
3193
|
] }),
|
|
2883
|
-
enableVerticalResize && /* @__PURE__ */ (0,
|
|
2884
|
-
/* @__PURE__ */ (0,
|
|
2885
|
-
/* @__PURE__ */ (0,
|
|
2886
|
-
/* @__PURE__ */ (0,
|
|
3194
|
+
enableVerticalResize && /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("div", { className: "vpg-vertical-resize-handle", onMouseDown: startVerticalResize, children: /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { className: "vpg-resize-grip", children: [
|
|
3195
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)("span", {}),
|
|
3196
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)("span", {}),
|
|
3197
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)("span", {})
|
|
2887
3198
|
] }) }),
|
|
2888
|
-
activeFilterColumn && (0,
|
|
2889
|
-
/* @__PURE__ */ (0,
|
|
3199
|
+
activeFilterColumn && (0, import_react_dom2.createPortal)(
|
|
3200
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
|
|
2890
3201
|
"div",
|
|
2891
3202
|
{
|
|
2892
3203
|
className: "vpg-filter-portal",
|
|
@@ -2897,7 +3208,7 @@ function DataGrid({
|
|
|
2897
3208
|
maxHeight: `${filterDropdownPosition.maxHeight}px`,
|
|
2898
3209
|
zIndex: 9999
|
|
2899
3210
|
},
|
|
2900
|
-
children: /* @__PURE__ */ (0,
|
|
3211
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
|
|
2901
3212
|
ColumnFilter,
|
|
2902
3213
|
{
|
|
2903
3214
|
columnId: activeFilterColumn,
|