@smallwebco/tinypivot-react 1.0.27 → 1.0.29

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.d.cts CHANGED
@@ -98,6 +98,7 @@ interface PivotSkeletonProps {
98
98
  rowFields: string[];
99
99
  columnFields: string[];
100
100
  valueFields: PivotValueField[];
101
+ calculatedFields?: CalculatedField[];
101
102
  isConfigured: boolean;
102
103
  draggingField: string | null;
103
104
  pivotResult: PivotResult | null;
@@ -115,7 +116,7 @@ interface PivotSkeletonProps {
115
116
  onReorderRowFields: (fields: string[]) => void;
116
117
  onReorderColumnFields: (fields: string[]) => void;
117
118
  }
118
- declare function PivotSkeleton({ rowFields, columnFields, valueFields, isConfigured, draggingField, pivotResult, fontSize, activeFilters, totalRowCount, filteredRowCount, onAddRowField, onRemoveRowField, onAddColumnField, onRemoveColumnField, onAddValueField, onRemoveValueField, onReorderRowFields, onReorderColumnFields, }: PivotSkeletonProps): react_jsx_runtime.JSX.Element;
119
+ declare function PivotSkeleton({ rowFields, columnFields, valueFields, calculatedFields, isConfigured, draggingField, pivotResult, fontSize, activeFilters, totalRowCount, filteredRowCount, onAddRowField, onRemoveRowField, onAddColumnField, onRemoveColumnField, onAddValueField, onRemoveValueField, onReorderRowFields, onReorderColumnFields, }: PivotSkeletonProps): react_jsx_runtime.JSX.Element;
119
120
 
120
121
  interface ExcelGridOptions<T> {
121
122
  data: T[];
package/dist/index.d.ts CHANGED
@@ -98,6 +98,7 @@ interface PivotSkeletonProps {
98
98
  rowFields: string[];
99
99
  columnFields: string[];
100
100
  valueFields: PivotValueField[];
101
+ calculatedFields?: CalculatedField[];
101
102
  isConfigured: boolean;
102
103
  draggingField: string | null;
103
104
  pivotResult: PivotResult | null;
@@ -115,7 +116,7 @@ interface PivotSkeletonProps {
115
116
  onReorderRowFields: (fields: string[]) => void;
116
117
  onReorderColumnFields: (fields: string[]) => void;
117
118
  }
118
- declare function PivotSkeleton({ rowFields, columnFields, valueFields, isConfigured, draggingField, pivotResult, fontSize, activeFilters, totalRowCount, filteredRowCount, onAddRowField, onRemoveRowField, onAddColumnField, onRemoveColumnField, onAddValueField, onRemoveValueField, onReorderRowFields, onReorderColumnFields, }: PivotSkeletonProps): react_jsx_runtime.JSX.Element;
119
+ declare function PivotSkeleton({ rowFields, columnFields, valueFields, calculatedFields, isConfigured, draggingField, pivotResult, fontSize, activeFilters, totalRowCount, filteredRowCount, onAddRowField, onRemoveRowField, onAddColumnField, onRemoveColumnField, onAddValueField, onRemoveValueField, onReorderRowFields, onReorderColumnFields, }: PivotSkeletonProps): react_jsx_runtime.JSX.Element;
119
120
 
120
121
  interface ExcelGridOptions<T> {
121
122
  data: T[];
package/dist/index.js CHANGED
@@ -1,5 +1,5 @@
1
1
  // src/components/DataGrid.tsx
2
- import { useState as useState9, useMemo as useMemo9, useCallback as useCallback9, useEffect as useEffect5, useRef as useRef2 } from "react";
2
+ import { useState as useState9, useMemo as useMemo9, useCallback as useCallback9, useEffect as useEffect6, useRef as useRef2 } from "react";
3
3
  import { createPortal as createPortal2 } from "react-dom";
4
4
 
5
5
  // src/hooks/useExcelGrid.ts
@@ -444,9 +444,7 @@ function usePivotTable(data) {
444
444
  }
445
445
  }, [availableFields, requirePro]);
446
446
  const addCalculatedField = useCallback3((field) => {
447
- console.log("[usePivotTable] addCalculatedField called with:", field);
448
447
  setCalculatedFields((prev) => {
449
- console.log("[usePivotTable] Previous calculatedFields:", prev);
450
448
  const existing = prev.findIndex((f) => f.id === field.id);
451
449
  let updated;
452
450
  if (existing >= 0) {
@@ -454,7 +452,6 @@ function usePivotTable(data) {
454
452
  } else {
455
453
  updated = [...prev, field];
456
454
  }
457
- console.log("[usePivotTable] Updated calculatedFields:", updated);
458
455
  saveCalculatedFields(updated);
459
456
  return updated;
460
457
  });
@@ -1029,15 +1026,11 @@ function CalculatedFieldModal({
1029
1026
  });
1030
1027
  }, []);
1031
1028
  const handleSave = useCallback6(() => {
1032
- console.log("[CalculatedFieldModal] handleSave called");
1033
- console.log("[CalculatedFieldModal] name:", name, "formula:", formula);
1034
- console.log("[CalculatedFieldModal] availableFields:", availableFields);
1035
1029
  if (!name.trim()) {
1036
1030
  setError("Name is required");
1037
1031
  return;
1038
1032
  }
1039
1033
  const validationResult = validateSimpleFormula(formula, availableFields);
1040
- console.log("[CalculatedFieldModal] validationResult:", validationResult);
1041
1034
  if (validationResult) {
1042
1035
  setError(validationResult);
1043
1036
  return;
@@ -1049,7 +1042,6 @@ function CalculatedFieldModal({
1049
1042
  formatAs,
1050
1043
  decimals
1051
1044
  };
1052
- console.log("[CalculatedFieldModal] Calling onSave with:", field);
1053
1045
  onSave(field);
1054
1046
  onClose();
1055
1047
  }, [name, formula, formatAs, decimals, existingField, availableFields, onSave, onClose]);
@@ -1210,9 +1202,8 @@ function PivotConfig({
1210
1202
  [availableFields]
1211
1203
  );
1212
1204
  const calculatedFieldsAsStats = useMemo7(() => {
1213
- console.log("[PivotConfig] calculatedFields prop:", calculatedFields);
1214
1205
  if (!calculatedFields) return [];
1215
- const stats = calculatedFields.map((calc) => ({
1206
+ return calculatedFields.map((calc) => ({
1216
1207
  field: `calc:${calc.id}`,
1217
1208
  type: "number",
1218
1209
  uniqueCount: 0,
@@ -1222,17 +1213,11 @@ function PivotConfig({
1222
1213
  calcName: calc.name,
1223
1214
  calcFormula: calc.formula
1224
1215
  }));
1225
- console.log("[PivotConfig] calculatedFieldsAsStats:", stats);
1226
- return stats;
1227
1216
  }, [calculatedFields]);
1228
- const allAvailableFields = useMemo7(() => {
1229
- const all = [
1230
- ...availableFields.map((f) => ({ ...f, isCalculated: false })),
1231
- ...calculatedFieldsAsStats
1232
- ];
1233
- console.log("[PivotConfig] allAvailableFields:", all.length, "items, calc fields:", calculatedFieldsAsStats.length);
1234
- return all;
1235
- }, [availableFields, calculatedFieldsAsStats]);
1217
+ const allAvailableFields = useMemo7(() => [
1218
+ ...availableFields.map((f) => ({ ...f, isCalculated: false })),
1219
+ ...calculatedFieldsAsStats
1220
+ ], [availableFields, calculatedFieldsAsStats]);
1236
1221
  const assignedFields = useMemo7(() => {
1237
1222
  const rowSet = new Set(rowFields);
1238
1223
  const colSet = new Set(columnFields);
@@ -1314,14 +1299,9 @@ function PivotConfig({
1314
1299
  setShowCalcModal(true);
1315
1300
  }, []);
1316
1301
  const handleSaveCalcField = useCallback7((field) => {
1317
- console.log("[PivotConfig] handleSaveCalcField called with:", field);
1318
- console.log("[PivotConfig] editingCalcField:", editingCalcField);
1319
- console.log("[PivotConfig] onAddCalculatedField exists:", !!onAddCalculatedField);
1320
1302
  if (editingCalcField && onUpdateCalculatedField) {
1321
- console.log("[PivotConfig] Calling onUpdateCalculatedField");
1322
1303
  onUpdateCalculatedField(field);
1323
1304
  } else if (onAddCalculatedField) {
1324
- console.log("[PivotConfig] Calling onAddCalculatedField");
1325
1305
  onAddCalculatedField(field);
1326
1306
  }
1327
1307
  setShowCalcModal(false);
@@ -1566,13 +1546,14 @@ function PivotConfig({
1566
1546
  }
1567
1547
 
1568
1548
  // src/components/PivotSkeleton.tsx
1569
- import { useState as useState8, useMemo as useMemo8, useCallback as useCallback8 } from "react";
1549
+ import { useState as useState8, useMemo as useMemo8, useCallback as useCallback8, useEffect as useEffect5 } from "react";
1570
1550
  import { getAggregationLabel as getAggregationLabel2, getAggregationSymbol as getAggregationSymbol2 } from "@smallwebco/tinypivot-core";
1571
1551
  import { Fragment as Fragment2, jsx as jsx4, jsxs as jsxs4 } from "react/jsx-runtime";
1572
1552
  function PivotSkeleton({
1573
1553
  rowFields,
1574
1554
  columnFields,
1575
1555
  valueFields,
1556
+ calculatedFields,
1576
1557
  isConfigured,
1577
1558
  draggingField,
1578
1559
  pivotResult,
@@ -1590,6 +1571,17 @@ function PivotSkeleton({
1590
1571
  onReorderColumnFields
1591
1572
  }) {
1592
1573
  const { showWatermark, canUsePivot, isDemo } = useLicense();
1574
+ const getValueFieldDisplayName = useCallback8((field) => {
1575
+ if (field.startsWith("calc:")) {
1576
+ const calcId = field.replace("calc:", "");
1577
+ const calcField = calculatedFields?.find((c) => c.id === calcId);
1578
+ return calcField?.name || field;
1579
+ }
1580
+ return field;
1581
+ }, [calculatedFields]);
1582
+ const isCalculatedField = useCallback8((field) => {
1583
+ return field.startsWith("calc:");
1584
+ }, []);
1593
1585
  const [dragOverArea, setDragOverArea] = useState8(null);
1594
1586
  const [reorderDragSource, setReorderDragSource] = useState8(null);
1595
1587
  const [reorderDropTarget, setReorderDropTarget] = useState8(null);
@@ -1603,6 +1595,58 @@ function PivotSkeleton({
1603
1595
  setSortDirection("asc");
1604
1596
  }
1605
1597
  }, [sortTarget]);
1598
+ const [selectedCell, setSelectedCell] = useState8(null);
1599
+ const [selectionStart, setSelectionStart] = useState8(null);
1600
+ const [selectionEnd, setSelectionEnd] = useState8(null);
1601
+ const [isSelecting, setIsSelecting] = useState8(false);
1602
+ const [showCopyToast, setShowCopyToast] = useState8(false);
1603
+ const [copyToastMessage, setCopyToastMessage] = useState8("");
1604
+ const selectionBounds = useMemo8(() => {
1605
+ if (!selectionStart || !selectionEnd) return null;
1606
+ return {
1607
+ minRow: Math.min(selectionStart.row, selectionEnd.row),
1608
+ maxRow: Math.max(selectionStart.row, selectionEnd.row),
1609
+ minCol: Math.min(selectionStart.col, selectionEnd.col),
1610
+ maxCol: Math.max(selectionStart.col, selectionEnd.col)
1611
+ };
1612
+ }, [selectionStart, selectionEnd]);
1613
+ const handleCellMouseDown = useCallback8(
1614
+ (rowIndex, colIndex, event) => {
1615
+ event.preventDefault();
1616
+ if (event.shiftKey && selectedCell) {
1617
+ setSelectionEnd({ row: rowIndex, col: colIndex });
1618
+ } else {
1619
+ setSelectedCell({ row: rowIndex, col: colIndex });
1620
+ setSelectionStart({ row: rowIndex, col: colIndex });
1621
+ setSelectionEnd({ row: rowIndex, col: colIndex });
1622
+ setIsSelecting(true);
1623
+ }
1624
+ },
1625
+ [selectedCell]
1626
+ );
1627
+ const handleCellMouseEnter = useCallback8(
1628
+ (rowIndex, colIndex) => {
1629
+ if (isSelecting) {
1630
+ setSelectionEnd({ row: rowIndex, col: colIndex });
1631
+ }
1632
+ },
1633
+ [isSelecting]
1634
+ );
1635
+ const isCellSelected = useCallback8(
1636
+ (rowIndex, colIndex) => {
1637
+ if (!selectionBounds) {
1638
+ return selectedCell?.row === rowIndex && selectedCell?.col === colIndex;
1639
+ }
1640
+ const { minRow, maxRow, minCol, maxCol } = selectionBounds;
1641
+ return rowIndex >= minRow && rowIndex <= maxRow && colIndex >= minCol && colIndex <= maxCol;
1642
+ },
1643
+ [selectionBounds, selectedCell]
1644
+ );
1645
+ useEffect5(() => {
1646
+ const handleMouseUp = () => setIsSelecting(false);
1647
+ document.addEventListener("mouseup", handleMouseUp);
1648
+ return () => document.removeEventListener("mouseup", handleMouseUp);
1649
+ }, []);
1606
1650
  const sortedRowIndices = useMemo8(() => {
1607
1651
  if (!pivotResult) return [];
1608
1652
  const indices = pivotResult.rowHeaders.map((_, i) => i);
@@ -1627,11 +1671,83 @@ function PivotSkeleton({
1627
1671
  });
1628
1672
  return indices;
1629
1673
  }, [pivotResult, sortTarget, sortDirection]);
1674
+ const copySelectionToClipboard = useCallback8(() => {
1675
+ if (!selectionBounds || !pivotResult) return;
1676
+ const { minRow, maxRow, minCol, maxCol } = selectionBounds;
1677
+ const lines = [];
1678
+ for (let r = minRow; r <= maxRow; r++) {
1679
+ const sortedIdx = sortedRowIndices[r];
1680
+ if (sortedIdx === void 0) continue;
1681
+ const rowValues = [];
1682
+ for (let c = minCol; c <= maxCol; c++) {
1683
+ const cell = pivotResult.data[sortedIdx]?.[c];
1684
+ rowValues.push(cell?.formattedValue ?? "");
1685
+ }
1686
+ lines.push(rowValues.join(" "));
1687
+ }
1688
+ const text = lines.join("\n");
1689
+ navigator.clipboard.writeText(text).then(() => {
1690
+ const cellCount = (maxRow - minRow + 1) * (maxCol - minCol + 1);
1691
+ setCopyToastMessage(`Copied ${cellCount} cell${cellCount > 1 ? "s" : ""}`);
1692
+ setShowCopyToast(true);
1693
+ setTimeout(() => setShowCopyToast(false), 2e3);
1694
+ }).catch((err) => {
1695
+ console.error("Copy failed:", err);
1696
+ });
1697
+ }, [selectionBounds, pivotResult, sortedRowIndices]);
1698
+ useEffect5(() => {
1699
+ const handleKeydown = (event) => {
1700
+ if (!selectionBounds) return;
1701
+ if ((event.ctrlKey || event.metaKey) && event.key === "c") {
1702
+ event.preventDefault();
1703
+ copySelectionToClipboard();
1704
+ return;
1705
+ }
1706
+ if (event.key === "Escape") {
1707
+ setSelectedCell(null);
1708
+ setSelectionStart(null);
1709
+ setSelectionEnd(null);
1710
+ }
1711
+ };
1712
+ document.addEventListener("keydown", handleKeydown);
1713
+ return () => document.removeEventListener("keydown", handleKeydown);
1714
+ }, [selectionBounds, copySelectionToClipboard]);
1715
+ const selectionStats = useMemo8(() => {
1716
+ if (!selectionBounds || !pivotResult) return null;
1717
+ const { minRow, maxRow, minCol, maxCol } = selectionBounds;
1718
+ const values = [];
1719
+ let count = 0;
1720
+ for (let r = minRow; r <= maxRow; r++) {
1721
+ const sortedIdx = sortedRowIndices[r];
1722
+ if (sortedIdx === void 0) continue;
1723
+ for (let c = minCol; c <= maxCol; c++) {
1724
+ const cell = pivotResult.data[sortedIdx]?.[c];
1725
+ count++;
1726
+ if (cell?.value !== null && cell?.value !== void 0 && typeof cell.value === "number") {
1727
+ values.push(cell.value);
1728
+ }
1729
+ }
1730
+ }
1731
+ if (count <= 1) return null;
1732
+ const sum = values.reduce((a, b) => a + b, 0);
1733
+ const avg = values.length > 0 ? sum / values.length : 0;
1734
+ return {
1735
+ count,
1736
+ numericCount: values.length,
1737
+ sum,
1738
+ avg
1739
+ };
1740
+ }, [selectionBounds, pivotResult, sortedRowIndices]);
1741
+ const formatStatValue = useCallback8((val) => {
1742
+ if (Math.abs(val) >= 1e6) return `${(val / 1e6).toFixed(2)}M`;
1743
+ if (Math.abs(val) >= 1e3) return `${(val / 1e3).toFixed(2)}K`;
1744
+ return val.toFixed(2);
1745
+ }, []);
1630
1746
  const columnHeaderCells = useMemo8(() => {
1631
1747
  if (!pivotResult || pivotResult.headers.length === 0) {
1632
1748
  return [
1633
1749
  valueFields.map((vf) => ({
1634
- label: `${vf.field} (${getAggregationLabel2(vf.aggregation)})`,
1750
+ label: `${getValueFieldDisplayName(vf.field)} (${getAggregationLabel2(vf.aggregation)})`,
1635
1751
  colspan: 1
1636
1752
  }))
1637
1753
  ];
@@ -1783,6 +1899,10 @@ function PivotSkeleton({
1783
1899
  {
1784
1900
  className: `vpg-pivot-skeleton vpg-font-${currentFontSize} ${draggingField ? "vpg-is-dragging" : ""}`,
1785
1901
  children: [
1902
+ showCopyToast && /* @__PURE__ */ jsxs4("div", { className: "vpg-toast", children: [
1903
+ /* @__PURE__ */ jsx4("svg", { className: "vpg-icon", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: /* @__PURE__ */ jsx4("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "M5 13l4 4L19 7" }) }),
1904
+ copyToastMessage
1905
+ ] }),
1786
1906
  /* @__PURE__ */ jsxs4("div", { className: "vpg-skeleton-header", children: [
1787
1907
  /* @__PURE__ */ jsxs4("div", { className: "vpg-skeleton-title", children: [
1788
1908
  /* @__PURE__ */ jsx4("svg", { className: "vpg-icon", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: /* @__PURE__ */ jsx4(
@@ -1999,10 +2119,10 @@ function PivotSkeleton({
1999
2119
  valueFields.map((vf) => /* @__PURE__ */ jsxs4(
2000
2120
  "div",
2001
2121
  {
2002
- className: "vpg-mini-chip vpg-value-chip",
2122
+ className: `vpg-mini-chip vpg-value-chip${isCalculatedField(vf.field) ? " vpg-calc-chip" : ""}`,
2003
2123
  children: [
2004
- /* @__PURE__ */ jsx4("span", { className: "vpg-agg-symbol", children: getAggregationSymbol2(vf.aggregation) }),
2005
- /* @__PURE__ */ jsx4("span", { className: "vpg-mini-name", children: vf.field }),
2124
+ /* @__PURE__ */ jsx4("span", { className: "vpg-agg-symbol", children: isCalculatedField(vf.field) ? "\u0192" : getAggregationSymbol2(vf.aggregation) }),
2125
+ /* @__PURE__ */ jsx4("span", { className: "vpg-mini-name", children: getValueFieldDisplayName(vf.field) }),
2006
2126
  /* @__PURE__ */ jsx4(
2007
2127
  "button",
2008
2128
  {
@@ -2084,14 +2204,19 @@ function PivotSkeleton({
2084
2204
  /* @__PURE__ */ jsxs4("tbody", { children: [
2085
2205
  sortedRowIndices.map((sortedIdx) => /* @__PURE__ */ jsxs4("tr", { className: "vpg-data-row", children: [
2086
2206
  /* @__PURE__ */ jsx4("th", { className: "vpg-row-header-cell", children: pivotResult.rowHeaders[sortedIdx].map((val, idx) => /* @__PURE__ */ jsx4("span", { className: "vpg-row-value", children: val }, idx)) }),
2087
- pivotResult.data[sortedIdx].map((cell, colIdx) => /* @__PURE__ */ jsx4(
2088
- "td",
2089
- {
2090
- className: `vpg-data-cell ${cell.value === null ? "vpg-is-null" : ""}`,
2091
- children: cell.formattedValue
2092
- },
2093
- colIdx
2094
- )),
2207
+ pivotResult.data[sortedIdx].map((cell, colIdx) => {
2208
+ const displayRowIdx = sortedRowIndices.indexOf(sortedIdx);
2209
+ return /* @__PURE__ */ jsx4(
2210
+ "td",
2211
+ {
2212
+ className: `vpg-data-cell ${isCellSelected(displayRowIdx, colIdx) ? "selected" : ""} ${cell.value === null ? "vpg-is-null" : ""}`,
2213
+ onMouseDown: (e) => handleCellMouseDown(displayRowIdx, colIdx, e),
2214
+ onMouseEnter: () => handleCellMouseEnter(displayRowIdx, colIdx),
2215
+ children: cell.formattedValue
2216
+ },
2217
+ colIdx
2218
+ );
2219
+ }),
2095
2220
  pivotResult.rowTotals[sortedIdx] && /* @__PURE__ */ jsx4("td", { className: "vpg-data-cell vpg-total-cell", children: pivotResult.rowTotals[sortedIdx].formattedValue })
2096
2221
  ] }, sortedIdx)),
2097
2222
  pivotResult.columnTotals.length > 0 && /* @__PURE__ */ jsxs4("tr", { className: "vpg-totals-row", children: [
@@ -2101,12 +2226,32 @@ function PivotSkeleton({
2101
2226
  ] })
2102
2227
  ] })
2103
2228
  ] }) }),
2104
- isConfigured && pivotResult && /* @__PURE__ */ jsx4("div", { className: "vpg-skeleton-footer", children: /* @__PURE__ */ jsxs4("span", { children: [
2105
- pivotResult.rowHeaders.length,
2106
- " rows \xD7 ",
2107
- pivotResult.data[0]?.length || 0,
2108
- " columns"
2109
- ] }) })
2229
+ isConfigured && pivotResult && /* @__PURE__ */ jsxs4("div", { className: "vpg-skeleton-footer", children: [
2230
+ /* @__PURE__ */ jsxs4("span", { className: "vpg-footer-info", children: [
2231
+ pivotResult.rowHeaders.length,
2232
+ " rows \xD7 ",
2233
+ pivotResult.data[0]?.length || 0,
2234
+ " columns"
2235
+ ] }),
2236
+ selectionStats && selectionStats.count > 1 && /* @__PURE__ */ jsxs4("div", { className: "vpg-selection-stats", children: [
2237
+ /* @__PURE__ */ jsxs4("span", { className: "vpg-stat", children: [
2238
+ /* @__PURE__ */ jsx4("span", { className: "vpg-stat-label", children: "Count:" }),
2239
+ /* @__PURE__ */ jsx4("span", { className: "vpg-stat-value", children: selectionStats.count })
2240
+ ] }),
2241
+ selectionStats.numericCount > 0 && /* @__PURE__ */ jsxs4(Fragment2, { children: [
2242
+ /* @__PURE__ */ jsx4("span", { className: "vpg-stat-divider", children: "|" }),
2243
+ /* @__PURE__ */ jsxs4("span", { className: "vpg-stat", children: [
2244
+ /* @__PURE__ */ jsx4("span", { className: "vpg-stat-label", children: "Sum:" }),
2245
+ /* @__PURE__ */ jsx4("span", { className: "vpg-stat-value", children: formatStatValue(selectionStats.sum) })
2246
+ ] }),
2247
+ /* @__PURE__ */ jsx4("span", { className: "vpg-stat-divider", children: "|" }),
2248
+ /* @__PURE__ */ jsxs4("span", { className: "vpg-stat", children: [
2249
+ /* @__PURE__ */ jsx4("span", { className: "vpg-stat-label", children: "Avg:" }),
2250
+ /* @__PURE__ */ jsx4("span", { className: "vpg-stat-value", children: formatStatValue(selectionStats.avg) })
2251
+ ] })
2252
+ ] })
2253
+ ] })
2254
+ ] })
2110
2255
  ] }),
2111
2256
  showWatermark && canUsePivot && /* @__PURE__ */ jsx4("div", { className: `vpg-watermark ${isDemo ? "vpg-demo-mode" : ""}`, children: isDemo ? /* @__PURE__ */ jsxs4(Fragment2, { children: [
2112
2257
  /* @__PURE__ */ jsx4("span", { className: "vpg-demo-badge", children: "DEMO" }),
@@ -2271,7 +2416,7 @@ function DataGrid({
2271
2416
  const end = start + pageSize;
2272
2417
  return searchFilteredData.slice(start, end);
2273
2418
  }, [enablePagination, searchFilteredData, currentPage, pageSize]);
2274
- useEffect5(() => {
2419
+ useEffect6(() => {
2275
2420
  setCurrentPage(1);
2276
2421
  }, [columnFilters, globalSearchTerm]);
2277
2422
  const selectionBounds = useMemo9(() => {
@@ -2309,7 +2454,7 @@ function DataGrid({
2309
2454
  const avg = sum / values.length;
2310
2455
  return { count, sum, avg, numericCount: values.length };
2311
2456
  }, [selectionBounds, rows, columnKeys]);
2312
- useEffect5(() => {
2457
+ useEffect6(() => {
2313
2458
  if (data.length === 0) return;
2314
2459
  const widths = {};
2315
2460
  const sampleSize = Math.min(100, data.length);
@@ -2340,7 +2485,7 @@ function DataGrid({
2340
2485
  },
2341
2486
  [enableColumnResize, columnWidths]
2342
2487
  );
2343
- useEffect5(() => {
2488
+ useEffect6(() => {
2344
2489
  if (!resizingColumnId) return;
2345
2490
  const handleResizeMove = (event) => {
2346
2491
  const diff = event.clientX - resizeStartX;
@@ -2370,7 +2515,7 @@ function DataGrid({
2370
2515
  },
2371
2516
  [enableVerticalResize, gridHeight]
2372
2517
  );
2373
- useEffect5(() => {
2518
+ useEffect6(() => {
2374
2519
  if (!isResizingVertically) return;
2375
2520
  const handleVerticalResizeMove = (event) => {
2376
2521
  const diff = event.clientY - verticalResizeStartY;
@@ -2488,12 +2633,12 @@ function DataGrid({
2488
2633
  },
2489
2634
  [isSelecting]
2490
2635
  );
2491
- useEffect5(() => {
2636
+ useEffect6(() => {
2492
2637
  const handleMouseUp = () => setIsSelecting(false);
2493
2638
  document.addEventListener("mouseup", handleMouseUp);
2494
2639
  return () => document.removeEventListener("mouseup", handleMouseUp);
2495
2640
  }, []);
2496
- useEffect5(() => {
2641
+ useEffect6(() => {
2497
2642
  const handleKeydown = (event) => {
2498
2643
  if ((event.ctrlKey || event.metaKey) && event.key === "c" && selectionBounds) {
2499
2644
  event.preventDefault();
@@ -3039,6 +3184,7 @@ function DataGrid({
3039
3184
  rowFields: pivotRowFields,
3040
3185
  columnFields: pivotColumnFields,
3041
3186
  valueFields: pivotValueFields,
3187
+ calculatedFields: pivotCalculatedFields,
3042
3188
  isConfigured: pivotIsConfigured,
3043
3189
  draggingField,
3044
3190
  pivotResult,