@xcelsior/ui-spreadsheets 1.1.1 → 1.1.3
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.js +95 -99
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +95 -99
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
- package/src/components/ColumnHeaderActions.tsx +2 -16
- package/src/components/Spreadsheet.stories.tsx +1 -0
- package/src/components/Spreadsheet.tsx +32 -1
- package/src/components/SpreadsheetCell.tsx +1 -1
- package/src/hooks/useSpreadsheetFiltering.ts +3 -1
- package/src/hooks/useSpreadsheetPinning.ts +26 -45
package/dist/index.js
CHANGED
|
@@ -370,7 +370,7 @@ var SpreadsheetCell = ({
|
|
|
370
370
|
onKeyDown: handleCellKeyDown,
|
|
371
371
|
"data-cell-id": `${rowId}-${column.id}`,
|
|
372
372
|
className: cn(
|
|
373
|
-
"border border-gray-200 group cursor-pointer select-none",
|
|
373
|
+
"border border-gray-200 group cursor-pointer transition-colors select-none",
|
|
374
374
|
compactMode ? "text-[10px]" : "text-xs",
|
|
375
375
|
cellPadding,
|
|
376
376
|
column.align === "right" && "text-right",
|
|
@@ -1121,71 +1121,56 @@ function ColumnHeaderActions({
|
|
|
1121
1121
|
unpinnedTitle = "Pin column",
|
|
1122
1122
|
className
|
|
1123
1123
|
}) {
|
|
1124
|
-
|
|
1125
|
-
|
|
1126
|
-
|
|
1127
|
-
|
|
1128
|
-
|
|
1129
|
-
|
|
1130
|
-
|
|
1131
|
-
|
|
1132
|
-
|
|
1133
|
-
|
|
1134
|
-
|
|
1135
|
-
|
|
1136
|
-
onKeyDown: handleKeyDown,
|
|
1137
|
-
children: [
|
|
1138
|
-
enableFiltering && onFilterClick && /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
|
|
1139
|
-
"button",
|
|
1140
|
-
{
|
|
1141
|
-
type: "button",
|
|
1142
|
-
onClick: (e) => {
|
|
1143
|
-
e.stopPropagation();
|
|
1144
|
-
onFilterClick();
|
|
1145
|
-
},
|
|
1146
|
-
className: cn(
|
|
1147
|
-
"p-0.5 hover:bg-gray-200 rounded transition-opacity",
|
|
1148
|
-
hasActiveFilter ? "text-blue-600 opacity-100" : "text-gray-400 opacity-0 group-hover:opacity-100"
|
|
1149
|
-
),
|
|
1150
|
-
title: filterTitle,
|
|
1151
|
-
children: /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(HiFilter, { className: "h-3 w-3" })
|
|
1152
|
-
}
|
|
1124
|
+
return /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { className: cn("flex items-center gap-0.5", className), children: [
|
|
1125
|
+
enableFiltering && onFilterClick && /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
|
|
1126
|
+
"button",
|
|
1127
|
+
{
|
|
1128
|
+
type: "button",
|
|
1129
|
+
onClick: (e) => {
|
|
1130
|
+
e.stopPropagation();
|
|
1131
|
+
onFilterClick();
|
|
1132
|
+
},
|
|
1133
|
+
className: cn(
|
|
1134
|
+
"p-0.5 hover:bg-gray-200 rounded transition-opacity",
|
|
1135
|
+
hasActiveFilter ? "text-blue-600 opacity-100" : "text-gray-400 opacity-0 group-hover:opacity-100"
|
|
1153
1136
|
),
|
|
1154
|
-
|
|
1155
|
-
|
|
1156
|
-
|
|
1157
|
-
|
|
1158
|
-
|
|
1159
|
-
|
|
1160
|
-
|
|
1161
|
-
|
|
1162
|
-
|
|
1163
|
-
|
|
1164
|
-
|
|
1165
|
-
|
|
1166
|
-
|
|
1167
|
-
|
|
1168
|
-
|
|
1137
|
+
title: filterTitle,
|
|
1138
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(HiFilter, { className: "h-3 w-3" })
|
|
1139
|
+
}
|
|
1140
|
+
),
|
|
1141
|
+
enableHighlighting && onHighlightClick && /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
|
|
1142
|
+
"button",
|
|
1143
|
+
{
|
|
1144
|
+
type: "button",
|
|
1145
|
+
onClick: (e) => {
|
|
1146
|
+
e.stopPropagation();
|
|
1147
|
+
onHighlightClick();
|
|
1148
|
+
},
|
|
1149
|
+
className: cn(
|
|
1150
|
+
"p-0.5 hover:bg-gray-200 rounded transition-opacity",
|
|
1151
|
+
hasActiveHighlight ? "text-amber-500 opacity-100" : "text-gray-400 opacity-0 group-hover:opacity-100"
|
|
1169
1152
|
),
|
|
1170
|
-
|
|
1171
|
-
|
|
1172
|
-
|
|
1173
|
-
|
|
1174
|
-
|
|
1175
|
-
|
|
1176
|
-
|
|
1177
|
-
|
|
1178
|
-
|
|
1179
|
-
|
|
1180
|
-
|
|
1181
|
-
|
|
1182
|
-
|
|
1183
|
-
|
|
1184
|
-
|
|
1185
|
-
)
|
|
1186
|
-
|
|
1187
|
-
|
|
1188
|
-
|
|
1153
|
+
title: highlightTitle,
|
|
1154
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(AiFillHighlight, { className: "h-3 w-3" })
|
|
1155
|
+
}
|
|
1156
|
+
),
|
|
1157
|
+
enablePinning && onPinClick && /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
|
|
1158
|
+
"button",
|
|
1159
|
+
{
|
|
1160
|
+
type: "button",
|
|
1161
|
+
onClick: (e) => {
|
|
1162
|
+
e.stopPropagation();
|
|
1163
|
+
onPinClick();
|
|
1164
|
+
},
|
|
1165
|
+
className: cn(
|
|
1166
|
+
"p-0.5 hover:bg-gray-200 rounded transition-opacity",
|
|
1167
|
+
isPinned ? "text-blue-600 opacity-100" : "text-gray-400 opacity-0 group-hover:opacity-100"
|
|
1168
|
+
),
|
|
1169
|
+
title: isPinned ? pinnedTitle : unpinnedTitle,
|
|
1170
|
+
children: isPinned ? /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(MdPushPin, { className: "h-3 w-3" }) : /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(MdOutlinePushPin, { className: "h-3 w-3" })
|
|
1171
|
+
}
|
|
1172
|
+
)
|
|
1173
|
+
] });
|
|
1189
1174
|
}
|
|
1190
1175
|
ColumnHeaderActions.displayName = "ColumnHeaderActions";
|
|
1191
1176
|
|
|
@@ -1280,22 +1265,17 @@ function useSpreadsheetPinning({
|
|
|
1280
1265
|
columns,
|
|
1281
1266
|
columnGroups,
|
|
1282
1267
|
showRowIndex = true,
|
|
1283
|
-
defaultPinnedColumns = []
|
|
1284
|
-
defaultPinRowIndex = false
|
|
1268
|
+
defaultPinnedColumns = []
|
|
1285
1269
|
}) {
|
|
1286
1270
|
const [pinnedColumns, setPinnedColumns] = (0, import_react6.useState)(() => {
|
|
1287
1271
|
const map = /* @__PURE__ */ new Map();
|
|
1288
1272
|
defaultPinnedColumns.forEach((col) => {
|
|
1289
|
-
|
|
1290
|
-
map.set(col, "left");
|
|
1291
|
-
}
|
|
1273
|
+
map.set(col, "left");
|
|
1292
1274
|
});
|
|
1293
1275
|
return map;
|
|
1294
1276
|
});
|
|
1295
|
-
const [isRowIndexPinned, setIsRowIndexPinned] = (0, import_react6.useState)(
|
|
1296
|
-
defaultPinRowIndex || defaultPinnedColumns.includes(ROW_INDEX_COLUMN_ID)
|
|
1297
|
-
);
|
|
1298
1277
|
const [collapsedGroups, setCollapsedGroups] = (0, import_react6.useState)(/* @__PURE__ */ new Set());
|
|
1278
|
+
const isRowIndexPinned = pinnedColumns.has(ROW_INDEX_COLUMN_ID);
|
|
1299
1279
|
const handleTogglePin = (0, import_react6.useCallback)((columnId) => {
|
|
1300
1280
|
setPinnedColumns((prev) => {
|
|
1301
1281
|
const newMap = new Map(prev);
|
|
@@ -1307,21 +1287,12 @@ function useSpreadsheetPinning({
|
|
|
1307
1287
|
return newMap;
|
|
1308
1288
|
});
|
|
1309
1289
|
}, []);
|
|
1310
|
-
const handleToggleRowIndexPin = (0, import_react6.useCallback)(() => {
|
|
1311
|
-
setIsRowIndexPinned((prev) => !prev);
|
|
1312
|
-
}, []);
|
|
1313
1290
|
const setPinnedColumnsFromIds = (0, import_react6.useCallback)((columnIds) => {
|
|
1314
1291
|
const map = /* @__PURE__ */ new Map();
|
|
1315
1292
|
columnIds.forEach((col) => {
|
|
1316
|
-
|
|
1317
|
-
map.set(col, "left");
|
|
1318
|
-
}
|
|
1293
|
+
map.set(col, "left");
|
|
1319
1294
|
});
|
|
1320
1295
|
setPinnedColumns(map);
|
|
1321
|
-
setIsRowIndexPinned(columnIds.includes(ROW_INDEX_COLUMN_ID));
|
|
1322
|
-
}, []);
|
|
1323
|
-
const setRowIndexPinned = (0, import_react6.useCallback)((pinned) => {
|
|
1324
|
-
setIsRowIndexPinned(pinned);
|
|
1325
1296
|
}, []);
|
|
1326
1297
|
const handleToggleGroupCollapse = (0, import_react6.useCallback)((groupId) => {
|
|
1327
1298
|
setCollapsedGroups((prev) => {
|
|
@@ -1347,14 +1318,17 @@ function useSpreadsheetPinning({
|
|
|
1347
1318
|
return pinnedColumns.has(column.id);
|
|
1348
1319
|
});
|
|
1349
1320
|
}
|
|
1350
|
-
|
|
1321
|
+
const nonRowIndexPinned = Array.from(pinnedColumns.keys()).filter(
|
|
1322
|
+
(id) => id !== ROW_INDEX_COLUMN_ID
|
|
1323
|
+
);
|
|
1324
|
+
if (nonRowIndexPinned.length === 0) {
|
|
1351
1325
|
return result;
|
|
1352
1326
|
}
|
|
1353
1327
|
const leftPinned = [];
|
|
1354
1328
|
const unpinned = [];
|
|
1355
1329
|
const rightPinned = [];
|
|
1356
|
-
const pinnedLeftIds = Array.from(pinnedColumns.entries()).filter(([, side]) => side === "left").map(([id]) => id);
|
|
1357
|
-
const pinnedRightIds = Array.from(pinnedColumns.entries()).filter(([, side]) => side === "right").map(([id]) => id);
|
|
1330
|
+
const pinnedLeftIds = Array.from(pinnedColumns.entries()).filter(([id, side]) => side === "left" && id !== ROW_INDEX_COLUMN_ID).map(([id]) => id);
|
|
1331
|
+
const pinnedRightIds = Array.from(pinnedColumns.entries()).filter(([id, side]) => side === "right" && id !== ROW_INDEX_COLUMN_ID).map(([id]) => id);
|
|
1358
1332
|
for (const column of result) {
|
|
1359
1333
|
const pinSide = pinnedColumns.get(column.id);
|
|
1360
1334
|
if (pinSide === "left") {
|
|
@@ -1369,23 +1343,24 @@ function useSpreadsheetPinning({
|
|
|
1369
1343
|
rightPinned.sort((a, b) => pinnedRightIds.indexOf(a.id) - pinnedRightIds.indexOf(b.id));
|
|
1370
1344
|
return [...leftPinned, ...unpinned, ...rightPinned];
|
|
1371
1345
|
}, [columns, columnGroups, collapsedGroups, pinnedColumns]);
|
|
1372
|
-
const getRowIndexLeftOffset = (0, import_react6.useCallback)(() => {
|
|
1373
|
-
return 0;
|
|
1374
|
-
}, []);
|
|
1375
1346
|
const getColumnLeftOffset = (0, import_react6.useCallback)(
|
|
1376
1347
|
(columnId) => {
|
|
1377
|
-
|
|
1348
|
+
if (columnId === ROW_INDEX_COLUMN_ID) {
|
|
1349
|
+
return 0;
|
|
1350
|
+
}
|
|
1351
|
+
const pinnedLeft = Array.from(pinnedColumns.entries()).filter(([id, side]) => side === "left" && id !== ROW_INDEX_COLUMN_ID).map(([id]) => id);
|
|
1378
1352
|
const index = pinnedLeft.indexOf(columnId);
|
|
1379
|
-
const
|
|
1353
|
+
const isRowIndexPinnedNow = pinnedColumns.has(ROW_INDEX_COLUMN_ID);
|
|
1354
|
+
const baseOffset = showRowIndex && isRowIndexPinnedNow ? ROW_INDEX_COLUMN_WIDTH : 0;
|
|
1380
1355
|
if (index === -1) return baseOffset;
|
|
1381
1356
|
let offset = baseOffset;
|
|
1382
1357
|
for (let i = 0; i < index; i++) {
|
|
1383
1358
|
const col = columns.find((c) => c.id === pinnedLeft[i]);
|
|
1384
|
-
offset += col?.
|
|
1359
|
+
offset += col?.minWidth || col?.width || 100;
|
|
1385
1360
|
}
|
|
1386
1361
|
return offset;
|
|
1387
1362
|
},
|
|
1388
|
-
[pinnedColumns, columns, showRowIndex
|
|
1363
|
+
[pinnedColumns, columns, showRowIndex]
|
|
1389
1364
|
);
|
|
1390
1365
|
const isColumnPinned = (0, import_react6.useCallback)(
|
|
1391
1366
|
(columnId) => {
|
|
@@ -1405,12 +1380,9 @@ function useSpreadsheetPinning({
|
|
|
1405
1380
|
collapsedGroups,
|
|
1406
1381
|
visibleColumns,
|
|
1407
1382
|
handleTogglePin,
|
|
1408
|
-
handleToggleRowIndexPin,
|
|
1409
1383
|
handleToggleGroupCollapse,
|
|
1410
1384
|
setPinnedColumnsFromIds,
|
|
1411
|
-
setRowIndexPinned,
|
|
1412
1385
|
getColumnLeftOffset,
|
|
1413
|
-
getRowIndexLeftOffset,
|
|
1414
1386
|
isColumnPinned,
|
|
1415
1387
|
getColumnPinSide
|
|
1416
1388
|
};
|
|
@@ -2243,13 +2215,14 @@ function useSpreadsheetFiltering({
|
|
|
2243
2215
|
onSortChange,
|
|
2244
2216
|
serverSide = false,
|
|
2245
2217
|
controlledFilters,
|
|
2246
|
-
controlledSortConfig
|
|
2218
|
+
controlledSortConfig,
|
|
2219
|
+
defaultSortConfig
|
|
2247
2220
|
}) {
|
|
2248
2221
|
const [internalFilters, setInternalFilters] = (0, import_react11.useState)(
|
|
2249
2222
|
{}
|
|
2250
2223
|
);
|
|
2251
2224
|
const [internalSortConfig, setInternalSortConfig] = (0, import_react11.useState)(
|
|
2252
|
-
null
|
|
2225
|
+
defaultSortConfig ?? null
|
|
2253
2226
|
);
|
|
2254
2227
|
const [activeFilterColumn, setActiveFilterColumn] = (0, import_react11.useState)(null);
|
|
2255
2228
|
const filters = controlledFilters ?? internalFilters;
|
|
@@ -3377,7 +3350,8 @@ function Spreadsheet({
|
|
|
3377
3350
|
onSortChange,
|
|
3378
3351
|
serverSide,
|
|
3379
3352
|
controlledFilters,
|
|
3380
|
-
controlledSortConfig
|
|
3353
|
+
controlledSortConfig,
|
|
3354
|
+
defaultSortConfig: spreadsheetSettings.defaultSort
|
|
3381
3355
|
});
|
|
3382
3356
|
const {
|
|
3383
3357
|
getCellHighlight,
|
|
@@ -3409,7 +3383,8 @@ function Spreadsheet({
|
|
|
3409
3383
|
getColumnPinSide
|
|
3410
3384
|
} = useSpreadsheetPinning({
|
|
3411
3385
|
columns,
|
|
3412
|
-
columnGroups
|
|
3386
|
+
columnGroups,
|
|
3387
|
+
defaultPinnedColumns: initialSettings?.defaultPinnedColumns
|
|
3413
3388
|
});
|
|
3414
3389
|
const {
|
|
3415
3390
|
getCellComments,
|
|
@@ -3478,6 +3453,27 @@ function Spreadsheet({
|
|
|
3478
3453
|
defaultSort: sortConfig
|
|
3479
3454
|
}));
|
|
3480
3455
|
}, [sortConfig]);
|
|
3456
|
+
(0, import_react16.useEffect)(() => {
|
|
3457
|
+
const pinnedColumnIds = Array.from(pinnedColumns.keys());
|
|
3458
|
+
setSpreadsheetSettings((prev) => {
|
|
3459
|
+
const prevIds = prev.defaultPinnedColumns;
|
|
3460
|
+
if (prevIds.length === pinnedColumnIds.length && prevIds.every((id, idx) => id === pinnedColumnIds[idx])) {
|
|
3461
|
+
return prev;
|
|
3462
|
+
}
|
|
3463
|
+
return {
|
|
3464
|
+
...prev,
|
|
3465
|
+
defaultPinnedColumns: pinnedColumnIds
|
|
3466
|
+
};
|
|
3467
|
+
});
|
|
3468
|
+
}, [pinnedColumns]);
|
|
3469
|
+
const isInitialMount = (0, import_react16.useRef)(true);
|
|
3470
|
+
(0, import_react16.useEffect)(() => {
|
|
3471
|
+
if (isInitialMount.current) {
|
|
3472
|
+
isInitialMount.current = false;
|
|
3473
|
+
return;
|
|
3474
|
+
}
|
|
3475
|
+
onSettingsChange?.(spreadsheetSettings);
|
|
3476
|
+
}, [spreadsheetSettings, onSettingsChange]);
|
|
3481
3477
|
const applyUndo = (0, import_react16.useCallback)(() => {
|
|
3482
3478
|
const entry = popUndoEntry();
|
|
3483
3479
|
if (!entry || !onCellsEdit) return;
|