react-open-source-grid 1.6.4 → 1.6.5
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/assets/{index-BczRxCQn.js → index-BbaZajrS.js} +197 -74
- package/dist/assets/index.js +1 -1
- package/dist/assets/{layoutPersistence-C_jVd_iy.js → layoutPersistence-CPItuVwj.js} +1 -1
- package/dist/index.html +1 -1
- package/dist/lib/components/DataGrid/PivotToolbar.d.ts +29 -0
- package/dist/lib/components/DataGrid/index.d.ts +4 -0
- package/dist/lib/components/DataGrid/pivotEngine.d.ts +55 -0
- package/dist/lib/components/DataGrid/types.d.ts +2 -0
- package/dist/lib/components/PivotDemo.d.ts +8 -0
- package/dist/lib/index.cjs +509 -21
- package/dist/lib/index.js +505 -21
- package/package.json +1 -1
package/dist/lib/index.js
CHANGED
|
@@ -8043,6 +8043,195 @@ var GridApiImpl = class {
|
|
|
8043
8043
|
}
|
|
8044
8044
|
};
|
|
8045
8045
|
|
|
8046
|
+
// src/components/DataGrid/pivotEngine.ts
|
|
8047
|
+
var AGGREGATORS = {
|
|
8048
|
+
sum: (values) => values.reduce((acc, val) => acc + val, 0),
|
|
8049
|
+
count: (values) => values.length,
|
|
8050
|
+
avg: (values) => values.length > 0 ? values.reduce((acc, val) => acc + val, 0) / values.length : 0,
|
|
8051
|
+
min: (values) => values.length > 0 ? Math.min(...values) : 0,
|
|
8052
|
+
max: (values) => values.length > 0 ? Math.max(...values) : 0
|
|
8053
|
+
};
|
|
8054
|
+
function getUniqueValues(data, column) {
|
|
8055
|
+
const uniqueSet = /* @__PURE__ */ new Set();
|
|
8056
|
+
data.forEach((row) => {
|
|
8057
|
+
const value = row[column];
|
|
8058
|
+
if (value !== null && value !== void 0) {
|
|
8059
|
+
uniqueSet.add(String(value));
|
|
8060
|
+
}
|
|
8061
|
+
});
|
|
8062
|
+
return Array.from(uniqueSet).sort();
|
|
8063
|
+
}
|
|
8064
|
+
function getAggregatorFn(aggregator) {
|
|
8065
|
+
if (typeof aggregator === "function") {
|
|
8066
|
+
return aggregator;
|
|
8067
|
+
}
|
|
8068
|
+
return AGGREGATORS[aggregator] || AGGREGATORS.sum;
|
|
8069
|
+
}
|
|
8070
|
+
function toNumber(value) {
|
|
8071
|
+
if (typeof value === "number") return value;
|
|
8072
|
+
if (typeof value === "string") {
|
|
8073
|
+
const num = parseFloat(value);
|
|
8074
|
+
return isNaN(num) ? 0 : num;
|
|
8075
|
+
}
|
|
8076
|
+
return 0;
|
|
8077
|
+
}
|
|
8078
|
+
function buildPivot(data, config) {
|
|
8079
|
+
const {
|
|
8080
|
+
pivotColumn,
|
|
8081
|
+
valueColumn,
|
|
8082
|
+
rowGroupColumn,
|
|
8083
|
+
aggregator,
|
|
8084
|
+
showTotals = false,
|
|
8085
|
+
showGrandTotal = false
|
|
8086
|
+
} = config;
|
|
8087
|
+
if (!data || data.length === 0) {
|
|
8088
|
+
return {
|
|
8089
|
+
columns: [],
|
|
8090
|
+
rows: [],
|
|
8091
|
+
pivotValues: []
|
|
8092
|
+
};
|
|
8093
|
+
}
|
|
8094
|
+
const pivotValues = getUniqueValues(data, pivotColumn);
|
|
8095
|
+
const rowGroupValues = getUniqueValues(data, rowGroupColumn);
|
|
8096
|
+
const aggregatorFn = getAggregatorFn(aggregator);
|
|
8097
|
+
const groupedData = /* @__PURE__ */ new Map();
|
|
8098
|
+
rowGroupValues.forEach((rowValue) => {
|
|
8099
|
+
const pivotMap = /* @__PURE__ */ new Map();
|
|
8100
|
+
pivotValues.forEach((pivotValue) => {
|
|
8101
|
+
pivotMap.set(pivotValue, []);
|
|
8102
|
+
});
|
|
8103
|
+
groupedData.set(rowValue, pivotMap);
|
|
8104
|
+
});
|
|
8105
|
+
data.forEach((row) => {
|
|
8106
|
+
const rowValue = String(row[rowGroupColumn] ?? "");
|
|
8107
|
+
const pivotValue = String(row[pivotColumn] ?? "");
|
|
8108
|
+
const value = toNumber(row[valueColumn]);
|
|
8109
|
+
if (groupedData.has(rowValue)) {
|
|
8110
|
+
const pivotMap = groupedData.get(rowValue);
|
|
8111
|
+
if (pivotMap.has(pivotValue)) {
|
|
8112
|
+
pivotMap.get(pivotValue).push(value);
|
|
8113
|
+
}
|
|
8114
|
+
}
|
|
8115
|
+
});
|
|
8116
|
+
const columns = [
|
|
8117
|
+
{
|
|
8118
|
+
field: rowGroupColumn,
|
|
8119
|
+
headerName: formatHeaderName(rowGroupColumn),
|
|
8120
|
+
width: 180,
|
|
8121
|
+
sortable: true,
|
|
8122
|
+
filterable: true,
|
|
8123
|
+
isPivotColumn: false
|
|
8124
|
+
}
|
|
8125
|
+
];
|
|
8126
|
+
pivotValues.forEach((pivotValue) => {
|
|
8127
|
+
columns.push({
|
|
8128
|
+
field: pivotValue,
|
|
8129
|
+
headerName: pivotValue,
|
|
8130
|
+
width: 120,
|
|
8131
|
+
sortable: true,
|
|
8132
|
+
filterable: true,
|
|
8133
|
+
isPivotColumn: true
|
|
8134
|
+
});
|
|
8135
|
+
});
|
|
8136
|
+
if (showGrandTotal) {
|
|
8137
|
+
columns.push({
|
|
8138
|
+
field: "__grandTotal",
|
|
8139
|
+
headerName: "Grand Total",
|
|
8140
|
+
width: 120,
|
|
8141
|
+
sortable: true,
|
|
8142
|
+
filterable: false,
|
|
8143
|
+
isTotalColumn: true
|
|
8144
|
+
});
|
|
8145
|
+
}
|
|
8146
|
+
const rows = [];
|
|
8147
|
+
rowGroupValues.forEach((rowValue) => {
|
|
8148
|
+
const pivotMap = groupedData.get(rowValue);
|
|
8149
|
+
const row = {
|
|
8150
|
+
[rowGroupColumn]: rowValue,
|
|
8151
|
+
__id: rowValue
|
|
8152
|
+
// Add unique ID for grid
|
|
8153
|
+
};
|
|
8154
|
+
let grandTotal = 0;
|
|
8155
|
+
pivotValues.forEach((pivotValue) => {
|
|
8156
|
+
const values = pivotMap.get(pivotValue);
|
|
8157
|
+
const aggregatedValue = aggregatorFn(values);
|
|
8158
|
+
row[pivotValue] = aggregatedValue;
|
|
8159
|
+
grandTotal += aggregatedValue;
|
|
8160
|
+
});
|
|
8161
|
+
if (showGrandTotal) {
|
|
8162
|
+
row["__grandTotal"] = grandTotal;
|
|
8163
|
+
}
|
|
8164
|
+
rows.push(row);
|
|
8165
|
+
});
|
|
8166
|
+
let totalsRow;
|
|
8167
|
+
if (showTotals) {
|
|
8168
|
+
totalsRow = {
|
|
8169
|
+
[rowGroupColumn]: "Total",
|
|
8170
|
+
__id: "__totals",
|
|
8171
|
+
__isTotal: true
|
|
8172
|
+
};
|
|
8173
|
+
let overallGrandTotal = 0;
|
|
8174
|
+
pivotValues.forEach((pivotValue) => {
|
|
8175
|
+
const allValues = [];
|
|
8176
|
+
groupedData.forEach((pivotMap) => {
|
|
8177
|
+
const values = pivotMap.get(pivotValue);
|
|
8178
|
+
allValues.push(...values);
|
|
8179
|
+
});
|
|
8180
|
+
const total = aggregatorFn(allValues);
|
|
8181
|
+
totalsRow[pivotValue] = total;
|
|
8182
|
+
overallGrandTotal += total;
|
|
8183
|
+
});
|
|
8184
|
+
if (showGrandTotal) {
|
|
8185
|
+
totalsRow["__grandTotal"] = overallGrandTotal;
|
|
8186
|
+
}
|
|
8187
|
+
}
|
|
8188
|
+
return {
|
|
8189
|
+
columns,
|
|
8190
|
+
rows,
|
|
8191
|
+
pivotValues,
|
|
8192
|
+
totalsRow
|
|
8193
|
+
};
|
|
8194
|
+
}
|
|
8195
|
+
function formatHeaderName(field) {
|
|
8196
|
+
return field.split(/(?=[A-Z])|_|-/).map((word) => word.charAt(0).toUpperCase() + word.slice(1).toLowerCase()).join(" ");
|
|
8197
|
+
}
|
|
8198
|
+
function exportPivotToCSV(pivotResult) {
|
|
8199
|
+
const { columns, rows, totalsRow } = pivotResult;
|
|
8200
|
+
const headers = columns.map((col) => col.headerName).join(",");
|
|
8201
|
+
const dataRows = rows.map((row) => {
|
|
8202
|
+
return columns.map((col) => {
|
|
8203
|
+
const value = row[col.field];
|
|
8204
|
+
if (typeof value === "string" && value.includes(",")) {
|
|
8205
|
+
return `"${value}"`;
|
|
8206
|
+
}
|
|
8207
|
+
return value ?? "";
|
|
8208
|
+
}).join(",");
|
|
8209
|
+
});
|
|
8210
|
+
if (totalsRow) {
|
|
8211
|
+
const totalRow = columns.map((col) => {
|
|
8212
|
+
const value = totalsRow[col.field];
|
|
8213
|
+
if (typeof value === "string" && value.includes(",")) {
|
|
8214
|
+
return `"${value}"`;
|
|
8215
|
+
}
|
|
8216
|
+
return value ?? "";
|
|
8217
|
+
}).join(",");
|
|
8218
|
+
dataRows.push(totalRow);
|
|
8219
|
+
}
|
|
8220
|
+
return [headers, ...dataRows].join("\n");
|
|
8221
|
+
}
|
|
8222
|
+
function downloadCSV(csvContent, filename = "pivot-table.csv") {
|
|
8223
|
+
const blob = new Blob([csvContent], { type: "text/csv;charset=utf-8;" });
|
|
8224
|
+
const link = document.createElement("a");
|
|
8225
|
+
const url = URL.createObjectURL(blob);
|
|
8226
|
+
link.setAttribute("href", url);
|
|
8227
|
+
link.setAttribute("download", filename);
|
|
8228
|
+
link.style.visibility = "hidden";
|
|
8229
|
+
document.body.appendChild(link);
|
|
8230
|
+
link.click();
|
|
8231
|
+
document.body.removeChild(link);
|
|
8232
|
+
URL.revokeObjectURL(url);
|
|
8233
|
+
}
|
|
8234
|
+
|
|
8046
8235
|
// src/components/DataGrid/DataGrid.tsx
|
|
8047
8236
|
var DataGrid = forwardRef(({
|
|
8048
8237
|
columns,
|
|
@@ -8057,6 +8246,7 @@ var DataGrid = forwardRef(({
|
|
|
8057
8246
|
rowPinConfig,
|
|
8058
8247
|
contextMenuConfig,
|
|
8059
8248
|
tooltipConfig,
|
|
8249
|
+
pivotConfig,
|
|
8060
8250
|
tableId,
|
|
8061
8251
|
theme: _theme = "quartz",
|
|
8062
8252
|
densityMode: _densityMode = "normal",
|
|
@@ -8077,6 +8267,42 @@ var DataGrid = forwardRef(({
|
|
|
8077
8267
|
);
|
|
8078
8268
|
const [internalRows, setInternalRows] = useState14(null);
|
|
8079
8269
|
const activeRows = internalRows !== null ? internalRows : rows;
|
|
8270
|
+
const { pivotedData, effectiveColumns } = useMemo4(() => {
|
|
8271
|
+
if (!pivotConfig) {
|
|
8272
|
+
return { pivotedData: activeRows, effectiveColumns: columns };
|
|
8273
|
+
}
|
|
8274
|
+
const pivotResult = buildPivot(activeRows, pivotConfig);
|
|
8275
|
+
console.log("Pivot Result:", {
|
|
8276
|
+
columnsCount: pivotResult.columns.length,
|
|
8277
|
+
columns: pivotResult.columns.map((c) => c.field),
|
|
8278
|
+
rowsCount: pivotResult.rows.length,
|
|
8279
|
+
sampleRow: pivotResult.rows[0]
|
|
8280
|
+
});
|
|
8281
|
+
const pivotColumns = pivotResult.columns.map((col) => ({
|
|
8282
|
+
field: col.field,
|
|
8283
|
+
headerName: col.headerName,
|
|
8284
|
+
width: col.width || 120,
|
|
8285
|
+
sortable: col.sortable !== false,
|
|
8286
|
+
filterable: col.filterable !== false,
|
|
8287
|
+
editable: false,
|
|
8288
|
+
renderCell: col.isTotalColumn || col.isPivotColumn ? (row) => {
|
|
8289
|
+
const value = row[col.field];
|
|
8290
|
+
if (typeof value === "number") {
|
|
8291
|
+
return /* @__PURE__ */ React20.createElement("span", { style: {
|
|
8292
|
+
fontWeight: col.isTotalColumn ? "700" : "600",
|
|
8293
|
+
color: col.isTotalColumn ? "#0f766e" : "#475569"
|
|
8294
|
+
} }, value.toLocaleString(void 0, { minimumFractionDigits: 2, maximumFractionDigits: 2 }));
|
|
8295
|
+
}
|
|
8296
|
+
return value;
|
|
8297
|
+
} : void 0
|
|
8298
|
+
}));
|
|
8299
|
+
const allRows = pivotResult.totalsRow ? [...pivotResult.rows, pivotResult.totalsRow] : pivotResult.rows;
|
|
8300
|
+
const rowsWithId = allRows.map((row, index) => ({
|
|
8301
|
+
...row,
|
|
8302
|
+
id: row.__id || row.id || `pivot-row-${index}`
|
|
8303
|
+
}));
|
|
8304
|
+
return { pivotedData: rowsWithId, effectiveColumns: pivotColumns };
|
|
8305
|
+
}, [activeRows, columns, pivotConfig]);
|
|
8080
8306
|
const rowsRef = useRef10(rows);
|
|
8081
8307
|
useEffect9(() => {
|
|
8082
8308
|
if (rows !== rowsRef.current) {
|
|
@@ -8179,8 +8405,8 @@ var DataGrid = forwardRef(({
|
|
|
8179
8405
|
gridApiRef.current = new GridApiImpl(
|
|
8180
8406
|
state,
|
|
8181
8407
|
dispatch,
|
|
8182
|
-
|
|
8183
|
-
|
|
8408
|
+
effectiveColumns,
|
|
8409
|
+
pivotedData,
|
|
8184
8410
|
containerRef,
|
|
8185
8411
|
persistenceManager,
|
|
8186
8412
|
setInternalRows
|
|
@@ -8190,24 +8416,24 @@ var DataGrid = forwardRef(({
|
|
|
8190
8416
|
useEffect9(() => {
|
|
8191
8417
|
if (gridApiRef.current && !gridApiRef.current.isDestroyed()) {
|
|
8192
8418
|
gridApiRef.current.updateState(state);
|
|
8193
|
-
gridApiRef.current.updateData(
|
|
8419
|
+
gridApiRef.current.updateData(effectiveColumns, pivotedData);
|
|
8194
8420
|
gridApiRef.current.updateCallbacks(setInternalRows);
|
|
8195
8421
|
}
|
|
8196
|
-
}, [state,
|
|
8422
|
+
}, [state, effectiveColumns, pivotedData, setInternalRows]);
|
|
8197
8423
|
useImperativeHandle(ref, () => {
|
|
8198
8424
|
if (!gridApiRef.current || gridApiRef.current.isDestroyed()) {
|
|
8199
8425
|
gridApiRef.current = new GridApiImpl(
|
|
8200
8426
|
state,
|
|
8201
8427
|
dispatch,
|
|
8202
|
-
|
|
8203
|
-
|
|
8428
|
+
effectiveColumns,
|
|
8429
|
+
pivotedData,
|
|
8204
8430
|
containerRef,
|
|
8205
8431
|
persistenceManager,
|
|
8206
8432
|
setInternalRows
|
|
8207
8433
|
);
|
|
8208
8434
|
}
|
|
8209
8435
|
return gridApiRef.current;
|
|
8210
|
-
}, [state,
|
|
8436
|
+
}, [state, effectiveColumns, pivotedData, persistenceManager]);
|
|
8211
8437
|
const onGridReadyCalledRef = useRef10(false);
|
|
8212
8438
|
const onGridReadyCallbackRef = useRef10(onGridReady);
|
|
8213
8439
|
useEffect9(() => {
|
|
@@ -8288,9 +8514,11 @@ var DataGrid = forwardRef(({
|
|
|
8288
8514
|
...middleColumns,
|
|
8289
8515
|
...pinnedRightFields
|
|
8290
8516
|
];
|
|
8517
|
+
console.log("Display column order:", displayColumnOrder, "from state.columnOrder:", state.columnOrder);
|
|
8291
8518
|
useEffect9(() => {
|
|
8292
|
-
|
|
8293
|
-
|
|
8519
|
+
console.log("Dispatching RESET_COLUMNS with", effectiveColumns.length, "columns:", effectiveColumns.map((c) => c.field));
|
|
8520
|
+
dispatch({ type: "RESET_COLUMNS", payload: effectiveColumns });
|
|
8521
|
+
}, [effectiveColumns]);
|
|
8294
8522
|
useEffect9(() => {
|
|
8295
8523
|
if (onSelectionChange) {
|
|
8296
8524
|
onSelectionChange(Array.from(state.selection.selectedRows));
|
|
@@ -8306,17 +8534,17 @@ var DataGrid = forwardRef(({
|
|
|
8306
8534
|
}, [state.pinnedRowsTop, state.pinnedRowsBottom]);
|
|
8307
8535
|
useEffect9(() => {
|
|
8308
8536
|
if (state.sortConfig.field) {
|
|
8309
|
-
const column =
|
|
8537
|
+
const column = effectiveColumns.find((c) => c.field === state.sortConfig.field);
|
|
8310
8538
|
if (column) {
|
|
8311
8539
|
announceSorting(column.headerName, state.sortConfig.direction);
|
|
8312
8540
|
}
|
|
8313
8541
|
}
|
|
8314
|
-
}, [state.sortConfig.field, state.sortConfig.direction]);
|
|
8542
|
+
}, [state.sortConfig.field, state.sortConfig.direction, effectiveColumns]);
|
|
8315
8543
|
const sortedRows = useMemo4(() => {
|
|
8316
8544
|
if (!state.sortConfig.field || !state.sortConfig.direction) {
|
|
8317
|
-
return
|
|
8545
|
+
return pivotedData;
|
|
8318
8546
|
}
|
|
8319
|
-
const sorted = [...
|
|
8547
|
+
const sorted = [...pivotedData].sort((a, b) => {
|
|
8320
8548
|
const aValue = a[state.sortConfig.field];
|
|
8321
8549
|
const bValue = b[state.sortConfig.field];
|
|
8322
8550
|
if (aValue == null && bValue == null) return 0;
|
|
@@ -8333,7 +8561,7 @@ var DataGrid = forwardRef(({
|
|
|
8333
8561
|
sorted.reverse();
|
|
8334
8562
|
}
|
|
8335
8563
|
return sorted;
|
|
8336
|
-
}, [
|
|
8564
|
+
}, [pivotedData, state.sortConfig]);
|
|
8337
8565
|
const filteredRows = useMemo4(() => {
|
|
8338
8566
|
if (!hasActiveFilters(state.filterConfig)) {
|
|
8339
8567
|
return sortedRows;
|
|
@@ -8479,7 +8707,7 @@ var DataGrid = forwardRef(({
|
|
|
8479
8707
|
/* @__PURE__ */ React20.createElement("div", { style: { position: "relative", display: "flex", alignItems: "center", justifyContent: "space-between", paddingLeft: "16px", paddingRight: "16px", paddingTop: "10px", paddingBottom: "10px", backgroundColor: "var(--grid-bg-alt)", borderBottom: "var(--grid-border-width, 1px) solid var(--grid-border)", zIndex: 30 } }, /* @__PURE__ */ React20.createElement("div", { style: { position: "relative", display: "flex", alignItems: "center", gap: "8px" } }, /* @__PURE__ */ React20.createElement(
|
|
8480
8708
|
ColumnChooser,
|
|
8481
8709
|
{
|
|
8482
|
-
columns,
|
|
8710
|
+
columns: effectiveColumns,
|
|
8483
8711
|
columnOrder: state.columnOrder,
|
|
8484
8712
|
hiddenColumns: state.hiddenColumns,
|
|
8485
8713
|
onToggleVisibility: (field) => dispatch({ type: "TOGGLE_COLUMN_VISIBILITY", payload: field }),
|
|
@@ -8489,7 +8717,7 @@ var DataGrid = forwardRef(({
|
|
|
8489
8717
|
), /* @__PURE__ */ React20.createElement(
|
|
8490
8718
|
ExportMenu,
|
|
8491
8719
|
{
|
|
8492
|
-
columns,
|
|
8720
|
+
columns: effectiveColumns,
|
|
8493
8721
|
fullDataset: rows,
|
|
8494
8722
|
filteredData: filteredRows.filter((r) => !("isGroup" in r)),
|
|
8495
8723
|
selectedRows: state.selection.selectedRows,
|
|
@@ -8507,7 +8735,7 @@ var DataGrid = forwardRef(({
|
|
|
8507
8735
|
/* @__PURE__ */ React20.createElement(
|
|
8508
8736
|
GroupByPanel,
|
|
8509
8737
|
{
|
|
8510
|
-
columns,
|
|
8738
|
+
columns: effectiveColumns,
|
|
8511
8739
|
groupBy: state.groupBy,
|
|
8512
8740
|
dispatch
|
|
8513
8741
|
}
|
|
@@ -8515,7 +8743,7 @@ var DataGrid = forwardRef(({
|
|
|
8515
8743
|
/* @__PURE__ */ React20.createElement("div", { role: "rowgroup", style: { position: "sticky", top: 0, zIndex: 20, width: "100%" } }, /* @__PURE__ */ React20.createElement(
|
|
8516
8744
|
GridHeader,
|
|
8517
8745
|
{
|
|
8518
|
-
columns,
|
|
8746
|
+
columns: effectiveColumns,
|
|
8519
8747
|
columnOrder: state.columnOrder,
|
|
8520
8748
|
displayColumnOrder,
|
|
8521
8749
|
columnWidths: state.columnWidths,
|
|
@@ -8534,7 +8762,7 @@ var DataGrid = forwardRef(({
|
|
|
8534
8762
|
), /* @__PURE__ */ React20.createElement(
|
|
8535
8763
|
ColumnFilters,
|
|
8536
8764
|
{
|
|
8537
|
-
columns,
|
|
8765
|
+
columns: effectiveColumns,
|
|
8538
8766
|
displayColumnOrder,
|
|
8539
8767
|
columnWidths: state.columnWidths,
|
|
8540
8768
|
filterConfig: state.filterConfig,
|
|
@@ -8547,7 +8775,7 @@ var DataGrid = forwardRef(({
|
|
|
8547
8775
|
/* @__PURE__ */ React20.createElement(
|
|
8548
8776
|
GridBody,
|
|
8549
8777
|
{
|
|
8550
|
-
columns,
|
|
8778
|
+
columns: effectiveColumns,
|
|
8551
8779
|
rows: (virtualScrollConfig == null ? void 0 : virtualScrollConfig.enabled) ? unpinnedRows : paginatedRows,
|
|
8552
8780
|
pinnedRowsTop: pinnedRowsTopData,
|
|
8553
8781
|
pinnedRowsBottom: pinnedRowsBottomData,
|
|
@@ -8587,7 +8815,7 @@ var DataGrid = forwardRef(({
|
|
|
8587
8815
|
(footerConfig == null ? void 0 : footerConfig.show) && footerConfig.aggregates && /* @__PURE__ */ React20.createElement(
|
|
8588
8816
|
GridFooter,
|
|
8589
8817
|
{
|
|
8590
|
-
columns,
|
|
8818
|
+
columns: effectiveColumns,
|
|
8591
8819
|
displayColumnOrder,
|
|
8592
8820
|
columnWidths: state.columnWidths,
|
|
8593
8821
|
aggregates: globalAggregates,
|
|
@@ -11752,6 +11980,258 @@ function createMockFeed(config) {
|
|
|
11752
11980
|
createConnection: () => createMockWebSocket(feed)
|
|
11753
11981
|
};
|
|
11754
11982
|
}
|
|
11983
|
+
|
|
11984
|
+
// src/components/DataGrid/PivotToolbar.tsx
|
|
11985
|
+
import React29, { useState as useState20, useMemo as useMemo8 } from "react";
|
|
11986
|
+
var AGGREGATOR_OPTIONS = [
|
|
11987
|
+
{ value: "sum", label: "Sum" },
|
|
11988
|
+
{ value: "avg", label: "Average" },
|
|
11989
|
+
{ value: "count", label: "Count" },
|
|
11990
|
+
{ value: "min", label: "Minimum" },
|
|
11991
|
+
{ value: "max", label: "Maximum" }
|
|
11992
|
+
];
|
|
11993
|
+
var PivotToolbar = ({
|
|
11994
|
+
columns,
|
|
11995
|
+
pivotConfig,
|
|
11996
|
+
onPivotToggle,
|
|
11997
|
+
onConfigChange,
|
|
11998
|
+
isPivotMode = false,
|
|
11999
|
+
style,
|
|
12000
|
+
className
|
|
12001
|
+
}) => {
|
|
12002
|
+
const [isExpanded, setIsExpanded] = useState20(isPivotMode);
|
|
12003
|
+
const [rowGroupColumn, setRowGroupColumn] = useState20((pivotConfig == null ? void 0 : pivotConfig.rowGroupColumn) || "");
|
|
12004
|
+
const [pivotColumn, setPivotColumn] = useState20((pivotConfig == null ? void 0 : pivotConfig.pivotColumn) || "");
|
|
12005
|
+
const [valueColumn, setValueColumn] = useState20((pivotConfig == null ? void 0 : pivotConfig.valueColumn) || "");
|
|
12006
|
+
const [aggregator, setAggregator] = useState20(
|
|
12007
|
+
(pivotConfig == null ? void 0 : pivotConfig.aggregator) || "sum"
|
|
12008
|
+
);
|
|
12009
|
+
const [showTotals, setShowTotals] = useState20((pivotConfig == null ? void 0 : pivotConfig.showTotals) ?? true);
|
|
12010
|
+
const [showGrandTotal, setShowGrandTotal] = useState20((pivotConfig == null ? void 0 : pivotConfig.showGrandTotal) ?? true);
|
|
12011
|
+
const isConfigValid = useMemo8(() => {
|
|
12012
|
+
return rowGroupColumn && pivotColumn && valueColumn;
|
|
12013
|
+
}, [rowGroupColumn, pivotColumn, valueColumn]);
|
|
12014
|
+
const handleApply = () => {
|
|
12015
|
+
if (!isConfigValid) return;
|
|
12016
|
+
const config = {
|
|
12017
|
+
rowGroupColumn,
|
|
12018
|
+
pivotColumn,
|
|
12019
|
+
valueColumn,
|
|
12020
|
+
aggregator,
|
|
12021
|
+
showTotals,
|
|
12022
|
+
showGrandTotal
|
|
12023
|
+
};
|
|
12024
|
+
onConfigChange(config);
|
|
12025
|
+
onPivotToggle(true);
|
|
12026
|
+
};
|
|
12027
|
+
const handleClear = () => {
|
|
12028
|
+
setRowGroupColumn("");
|
|
12029
|
+
setPivotColumn("");
|
|
12030
|
+
setValueColumn("");
|
|
12031
|
+
setAggregator("sum");
|
|
12032
|
+
setShowTotals(true);
|
|
12033
|
+
setShowGrandTotal(true);
|
|
12034
|
+
onConfigChange(null);
|
|
12035
|
+
onPivotToggle(false);
|
|
12036
|
+
setIsExpanded(false);
|
|
12037
|
+
};
|
|
12038
|
+
const handleToggle = () => {
|
|
12039
|
+
setIsExpanded(!isExpanded);
|
|
12040
|
+
};
|
|
12041
|
+
return /* @__PURE__ */ React29.createElement(
|
|
12042
|
+
"div",
|
|
12043
|
+
{
|
|
12044
|
+
className,
|
|
12045
|
+
style: {
|
|
12046
|
+
backgroundColor: "#f8fafc",
|
|
12047
|
+
border: "1px solid #e2e8f0",
|
|
12048
|
+
borderRadius: "8px",
|
|
12049
|
+
padding: "12px",
|
|
12050
|
+
...style
|
|
12051
|
+
}
|
|
12052
|
+
},
|
|
12053
|
+
/* @__PURE__ */ React29.createElement("div", { style: { display: "flex", alignItems: "center", justifyContent: "space-between", marginBottom: isExpanded ? "12px" : "0" } }, /* @__PURE__ */ React29.createElement("div", { style: { display: "flex", alignItems: "center", gap: "8px" } }, /* @__PURE__ */ React29.createElement("span", { style: { fontSize: "20px" } }, "\u{1F4CA}"), /* @__PURE__ */ React29.createElement("h3", { style: { margin: 0, fontSize: "14px", fontWeight: "600", color: "#1e293b" } }, "Pivot Table"), isPivotMode && /* @__PURE__ */ React29.createElement("span", { style: {
|
|
12054
|
+
backgroundColor: "#10b981",
|
|
12055
|
+
color: "white",
|
|
12056
|
+
padding: "2px 8px",
|
|
12057
|
+
borderRadius: "12px",
|
|
12058
|
+
fontSize: "11px",
|
|
12059
|
+
fontWeight: "600"
|
|
12060
|
+
} }, "Active")), /* @__PURE__ */ React29.createElement("div", { style: { display: "flex", gap: "8px" } }, isPivotMode && /* @__PURE__ */ React29.createElement(
|
|
12061
|
+
"button",
|
|
12062
|
+
{
|
|
12063
|
+
onClick: handleClear,
|
|
12064
|
+
style: {
|
|
12065
|
+
padding: "6px 12px",
|
|
12066
|
+
fontSize: "13px",
|
|
12067
|
+
fontWeight: "500",
|
|
12068
|
+
color: "#dc2626",
|
|
12069
|
+
backgroundColor: "#fee2e2",
|
|
12070
|
+
border: "1px solid #fecaca",
|
|
12071
|
+
borderRadius: "6px",
|
|
12072
|
+
cursor: "pointer",
|
|
12073
|
+
transition: "all 0.15s"
|
|
12074
|
+
},
|
|
12075
|
+
onMouseEnter: (e) => {
|
|
12076
|
+
e.currentTarget.style.backgroundColor = "#fecaca";
|
|
12077
|
+
},
|
|
12078
|
+
onMouseLeave: (e) => {
|
|
12079
|
+
e.currentTarget.style.backgroundColor = "#fee2e2";
|
|
12080
|
+
}
|
|
12081
|
+
},
|
|
12082
|
+
"Clear Pivot"
|
|
12083
|
+
), /* @__PURE__ */ React29.createElement(
|
|
12084
|
+
"button",
|
|
12085
|
+
{
|
|
12086
|
+
onClick: handleToggle,
|
|
12087
|
+
style: {
|
|
12088
|
+
padding: "6px 10px",
|
|
12089
|
+
fontSize: "13px",
|
|
12090
|
+
color: "#64748b",
|
|
12091
|
+
backgroundColor: "white",
|
|
12092
|
+
border: "1px solid #cbd5e1",
|
|
12093
|
+
borderRadius: "6px",
|
|
12094
|
+
cursor: "pointer",
|
|
12095
|
+
transition: "all 0.15s"
|
|
12096
|
+
},
|
|
12097
|
+
onMouseEnter: (e) => {
|
|
12098
|
+
e.currentTarget.style.backgroundColor = "#f1f5f9";
|
|
12099
|
+
},
|
|
12100
|
+
onMouseLeave: (e) => {
|
|
12101
|
+
e.currentTarget.style.backgroundColor = "white";
|
|
12102
|
+
}
|
|
12103
|
+
},
|
|
12104
|
+
isExpanded ? "\u25B2" : "\u25BC"
|
|
12105
|
+
))),
|
|
12106
|
+
isExpanded && /* @__PURE__ */ React29.createElement("div", { style: { display: "grid", gridTemplateColumns: "repeat(auto-fit, minmax(200px, 1fr))", gap: "12px" } }, /* @__PURE__ */ React29.createElement("div", null, /* @__PURE__ */ React29.createElement("label", { style: { display: "block", fontSize: "12px", fontWeight: "600", color: "#475569", marginBottom: "6px" } }, "Row Group By ", /* @__PURE__ */ React29.createElement("span", { style: { color: "#dc2626" } }, "*")), /* @__PURE__ */ React29.createElement(
|
|
12107
|
+
"select",
|
|
12108
|
+
{
|
|
12109
|
+
value: rowGroupColumn,
|
|
12110
|
+
onChange: (e) => setRowGroupColumn(e.target.value),
|
|
12111
|
+
style: {
|
|
12112
|
+
width: "100%",
|
|
12113
|
+
padding: "8px",
|
|
12114
|
+
fontSize: "13px",
|
|
12115
|
+
border: "1px solid #cbd5e1",
|
|
12116
|
+
borderRadius: "6px",
|
|
12117
|
+
backgroundColor: "white",
|
|
12118
|
+
color: "#1e293b",
|
|
12119
|
+
cursor: "pointer"
|
|
12120
|
+
}
|
|
12121
|
+
},
|
|
12122
|
+
/* @__PURE__ */ React29.createElement("option", { value: "" }, "Select column..."),
|
|
12123
|
+
columns.map((col) => /* @__PURE__ */ React29.createElement("option", { key: col.field, value: col.field }, col.headerName))
|
|
12124
|
+
)), /* @__PURE__ */ React29.createElement("div", null, /* @__PURE__ */ React29.createElement("label", { style: { display: "block", fontSize: "12px", fontWeight: "600", color: "#475569", marginBottom: "6px" } }, "Pivot Column ", /* @__PURE__ */ React29.createElement("span", { style: { color: "#dc2626" } }, "*")), /* @__PURE__ */ React29.createElement(
|
|
12125
|
+
"select",
|
|
12126
|
+
{
|
|
12127
|
+
value: pivotColumn,
|
|
12128
|
+
onChange: (e) => setPivotColumn(e.target.value),
|
|
12129
|
+
style: {
|
|
12130
|
+
width: "100%",
|
|
12131
|
+
padding: "8px",
|
|
12132
|
+
fontSize: "13px",
|
|
12133
|
+
border: "1px solid #cbd5e1",
|
|
12134
|
+
borderRadius: "6px",
|
|
12135
|
+
backgroundColor: "white",
|
|
12136
|
+
color: "#1e293b",
|
|
12137
|
+
cursor: "pointer"
|
|
12138
|
+
}
|
|
12139
|
+
},
|
|
12140
|
+
/* @__PURE__ */ React29.createElement("option", { value: "" }, "Select column..."),
|
|
12141
|
+
columns.map((col) => /* @__PURE__ */ React29.createElement("option", { key: col.field, value: col.field }, col.headerName))
|
|
12142
|
+
)), /* @__PURE__ */ React29.createElement("div", null, /* @__PURE__ */ React29.createElement("label", { style: { display: "block", fontSize: "12px", fontWeight: "600", color: "#475569", marginBottom: "6px" } }, "Value Column ", /* @__PURE__ */ React29.createElement("span", { style: { color: "#dc2626" } }, "*")), /* @__PURE__ */ React29.createElement(
|
|
12143
|
+
"select",
|
|
12144
|
+
{
|
|
12145
|
+
value: valueColumn,
|
|
12146
|
+
onChange: (e) => setValueColumn(e.target.value),
|
|
12147
|
+
style: {
|
|
12148
|
+
width: "100%",
|
|
12149
|
+
padding: "8px",
|
|
12150
|
+
fontSize: "13px",
|
|
12151
|
+
border: "1px solid #cbd5e1",
|
|
12152
|
+
borderRadius: "6px",
|
|
12153
|
+
backgroundColor: "white",
|
|
12154
|
+
color: "#1e293b",
|
|
12155
|
+
cursor: "pointer"
|
|
12156
|
+
}
|
|
12157
|
+
},
|
|
12158
|
+
/* @__PURE__ */ React29.createElement("option", { value: "" }, "Select column..."),
|
|
12159
|
+
columns.map((col) => /* @__PURE__ */ React29.createElement("option", { key: col.field, value: col.field }, col.headerName))
|
|
12160
|
+
)), /* @__PURE__ */ React29.createElement("div", null, /* @__PURE__ */ React29.createElement("label", { style: { display: "block", fontSize: "12px", fontWeight: "600", color: "#475569", marginBottom: "6px" } }, "Aggregation"), /* @__PURE__ */ React29.createElement(
|
|
12161
|
+
"select",
|
|
12162
|
+
{
|
|
12163
|
+
value: aggregator,
|
|
12164
|
+
onChange: (e) => setAggregator(e.target.value),
|
|
12165
|
+
style: {
|
|
12166
|
+
width: "100%",
|
|
12167
|
+
padding: "8px",
|
|
12168
|
+
fontSize: "13px",
|
|
12169
|
+
border: "1px solid #cbd5e1",
|
|
12170
|
+
borderRadius: "6px",
|
|
12171
|
+
backgroundColor: "white",
|
|
12172
|
+
color: "#1e293b",
|
|
12173
|
+
cursor: "pointer"
|
|
12174
|
+
}
|
|
12175
|
+
},
|
|
12176
|
+
AGGREGATOR_OPTIONS.map((opt) => /* @__PURE__ */ React29.createElement("option", { key: opt.value, value: opt.value }, opt.label))
|
|
12177
|
+
)), /* @__PURE__ */ React29.createElement("div", { style: { display: "flex", flexDirection: "column", gap: "8px", justifyContent: "center" } }, /* @__PURE__ */ React29.createElement("label", { style: { display: "flex", alignItems: "center", gap: "6px", fontSize: "13px", color: "#475569", cursor: "pointer" } }, /* @__PURE__ */ React29.createElement(
|
|
12178
|
+
"input",
|
|
12179
|
+
{
|
|
12180
|
+
type: "checkbox",
|
|
12181
|
+
checked: showTotals,
|
|
12182
|
+
onChange: (e) => setShowTotals(e.target.checked),
|
|
12183
|
+
style: { cursor: "pointer" }
|
|
12184
|
+
}
|
|
12185
|
+
), "Show Totals Row"), /* @__PURE__ */ React29.createElement("label", { style: { display: "flex", alignItems: "center", gap: "6px", fontSize: "13px", color: "#475569", cursor: "pointer" } }, /* @__PURE__ */ React29.createElement(
|
|
12186
|
+
"input",
|
|
12187
|
+
{
|
|
12188
|
+
type: "checkbox",
|
|
12189
|
+
checked: showGrandTotal,
|
|
12190
|
+
onChange: (e) => setShowGrandTotal(e.target.checked),
|
|
12191
|
+
style: { cursor: "pointer" }
|
|
12192
|
+
}
|
|
12193
|
+
), "Show Grand Total Column")), /* @__PURE__ */ React29.createElement("div", { style: { display: "flex", alignItems: "flex-end" } }, /* @__PURE__ */ React29.createElement(
|
|
12194
|
+
"button",
|
|
12195
|
+
{
|
|
12196
|
+
onClick: handleApply,
|
|
12197
|
+
disabled: !isConfigValid,
|
|
12198
|
+
style: {
|
|
12199
|
+
width: "100%",
|
|
12200
|
+
padding: "10px",
|
|
12201
|
+
fontSize: "14px",
|
|
12202
|
+
fontWeight: "600",
|
|
12203
|
+
color: "white",
|
|
12204
|
+
backgroundColor: isConfigValid ? "#2563eb" : "#94a3b8",
|
|
12205
|
+
border: "none",
|
|
12206
|
+
borderRadius: "6px",
|
|
12207
|
+
cursor: isConfigValid ? "pointer" : "not-allowed",
|
|
12208
|
+
transition: "all 0.15s",
|
|
12209
|
+
boxShadow: isConfigValid ? "0 2px 4px rgba(37, 99, 235, 0.2)" : "none"
|
|
12210
|
+
},
|
|
12211
|
+
onMouseEnter: (e) => {
|
|
12212
|
+
if (isConfigValid) {
|
|
12213
|
+
e.currentTarget.style.backgroundColor = "#1d4ed8";
|
|
12214
|
+
}
|
|
12215
|
+
},
|
|
12216
|
+
onMouseLeave: (e) => {
|
|
12217
|
+
if (isConfigValid) {
|
|
12218
|
+
e.currentTarget.style.backgroundColor = "#2563eb";
|
|
12219
|
+
}
|
|
12220
|
+
}
|
|
12221
|
+
},
|
|
12222
|
+
"Apply Pivot"
|
|
12223
|
+
))),
|
|
12224
|
+
isExpanded && /* @__PURE__ */ React29.createElement("div", { style: {
|
|
12225
|
+
marginTop: "12px",
|
|
12226
|
+
padding: "10px",
|
|
12227
|
+
backgroundColor: "#eff6ff",
|
|
12228
|
+
border: "1px solid #bfdbfe",
|
|
12229
|
+
borderRadius: "6px",
|
|
12230
|
+
fontSize: "12px",
|
|
12231
|
+
color: "#1e40af"
|
|
12232
|
+
} }, /* @__PURE__ */ React29.createElement("strong", null, "\u{1F4A1} Tip:"), " Select a Row Group column to organize data by, a Pivot column whose values become new columns, and a Value column to aggregate.")
|
|
12233
|
+
);
|
|
12234
|
+
};
|
|
11755
12235
|
export {
|
|
11756
12236
|
AdvancedFilterBuilder,
|
|
11757
12237
|
BadgeCell,
|
|
@@ -11774,6 +12254,7 @@ export {
|
|
|
11774
12254
|
LocalStorageAdapter,
|
|
11775
12255
|
MarketDataEngine,
|
|
11776
12256
|
MarketDataGrid,
|
|
12257
|
+
PivotToolbar,
|
|
11777
12258
|
PriorityIndicator,
|
|
11778
12259
|
ProgressBar,
|
|
11779
12260
|
Rating,
|
|
@@ -11786,6 +12267,7 @@ export {
|
|
|
11786
12267
|
VirtualScroller,
|
|
11787
12268
|
WebSocketMockFeed,
|
|
11788
12269
|
alpineTheme,
|
|
12270
|
+
buildPivot,
|
|
11789
12271
|
buildTreeFromFlat,
|
|
11790
12272
|
collapseAllNodes,
|
|
11791
12273
|
countTreeNodes,
|
|
@@ -11796,7 +12278,9 @@ export {
|
|
|
11796
12278
|
createPreset,
|
|
11797
12279
|
darkTheme,
|
|
11798
12280
|
densityConfigs,
|
|
12281
|
+
downloadCSV,
|
|
11799
12282
|
expandAllNodes,
|
|
12283
|
+
exportPivotToCSV,
|
|
11800
12284
|
exportToCSV,
|
|
11801
12285
|
exportToXLSX,
|
|
11802
12286
|
filterTree,
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "react-open-source-grid",
|
|
3
3
|
"private": false,
|
|
4
|
-
"version": "1.6.
|
|
4
|
+
"version": "1.6.5",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"description": "A high-performance React DataGrid component with advanced features like virtual scrolling, infinite scrolling, tree data, market data mode, and more",
|
|
7
7
|
"main": "./dist/lib/index.cjs",
|