@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.mjs
CHANGED
|
@@ -329,7 +329,7 @@ var SpreadsheetCell = ({
|
|
|
329
329
|
onKeyDown: handleCellKeyDown,
|
|
330
330
|
"data-cell-id": `${rowId}-${column.id}`,
|
|
331
331
|
className: cn(
|
|
332
|
-
"border border-gray-200 group cursor-pointer select-none",
|
|
332
|
+
"border border-gray-200 group cursor-pointer transition-colors select-none",
|
|
333
333
|
compactMode ? "text-[10px]" : "text-xs",
|
|
334
334
|
cellPadding,
|
|
335
335
|
column.align === "right" && "text-right",
|
|
@@ -1080,71 +1080,56 @@ function ColumnHeaderActions({
|
|
|
1080
1080
|
unpinnedTitle = "Pin column",
|
|
1081
1081
|
className
|
|
1082
1082
|
}) {
|
|
1083
|
-
|
|
1084
|
-
|
|
1085
|
-
|
|
1086
|
-
|
|
1087
|
-
|
|
1088
|
-
|
|
1089
|
-
|
|
1090
|
-
|
|
1091
|
-
|
|
1092
|
-
|
|
1093
|
-
|
|
1094
|
-
|
|
1095
|
-
onKeyDown: handleKeyDown,
|
|
1096
|
-
children: [
|
|
1097
|
-
enableFiltering && onFilterClick && /* @__PURE__ */ jsx4(
|
|
1098
|
-
"button",
|
|
1099
|
-
{
|
|
1100
|
-
type: "button",
|
|
1101
|
-
onClick: (e) => {
|
|
1102
|
-
e.stopPropagation();
|
|
1103
|
-
onFilterClick();
|
|
1104
|
-
},
|
|
1105
|
-
className: cn(
|
|
1106
|
-
"p-0.5 hover:bg-gray-200 rounded transition-opacity",
|
|
1107
|
-
hasActiveFilter ? "text-blue-600 opacity-100" : "text-gray-400 opacity-0 group-hover:opacity-100"
|
|
1108
|
-
),
|
|
1109
|
-
title: filterTitle,
|
|
1110
|
-
children: /* @__PURE__ */ jsx4(HiFilter, { className: "h-3 w-3" })
|
|
1111
|
-
}
|
|
1083
|
+
return /* @__PURE__ */ jsxs4("div", { className: cn("flex items-center gap-0.5", className), children: [
|
|
1084
|
+
enableFiltering && onFilterClick && /* @__PURE__ */ jsx4(
|
|
1085
|
+
"button",
|
|
1086
|
+
{
|
|
1087
|
+
type: "button",
|
|
1088
|
+
onClick: (e) => {
|
|
1089
|
+
e.stopPropagation();
|
|
1090
|
+
onFilterClick();
|
|
1091
|
+
},
|
|
1092
|
+
className: cn(
|
|
1093
|
+
"p-0.5 hover:bg-gray-200 rounded transition-opacity",
|
|
1094
|
+
hasActiveFilter ? "text-blue-600 opacity-100" : "text-gray-400 opacity-0 group-hover:opacity-100"
|
|
1112
1095
|
),
|
|
1113
|
-
|
|
1114
|
-
|
|
1115
|
-
|
|
1116
|
-
|
|
1117
|
-
|
|
1118
|
-
|
|
1119
|
-
|
|
1120
|
-
|
|
1121
|
-
|
|
1122
|
-
|
|
1123
|
-
|
|
1124
|
-
|
|
1125
|
-
|
|
1126
|
-
|
|
1127
|
-
|
|
1096
|
+
title: filterTitle,
|
|
1097
|
+
children: /* @__PURE__ */ jsx4(HiFilter, { className: "h-3 w-3" })
|
|
1098
|
+
}
|
|
1099
|
+
),
|
|
1100
|
+
enableHighlighting && onHighlightClick && /* @__PURE__ */ jsx4(
|
|
1101
|
+
"button",
|
|
1102
|
+
{
|
|
1103
|
+
type: "button",
|
|
1104
|
+
onClick: (e) => {
|
|
1105
|
+
e.stopPropagation();
|
|
1106
|
+
onHighlightClick();
|
|
1107
|
+
},
|
|
1108
|
+
className: cn(
|
|
1109
|
+
"p-0.5 hover:bg-gray-200 rounded transition-opacity",
|
|
1110
|
+
hasActiveHighlight ? "text-amber-500 opacity-100" : "text-gray-400 opacity-0 group-hover:opacity-100"
|
|
1128
1111
|
),
|
|
1129
|
-
|
|
1130
|
-
|
|
1131
|
-
|
|
1132
|
-
|
|
1133
|
-
|
|
1134
|
-
|
|
1135
|
-
|
|
1136
|
-
|
|
1137
|
-
|
|
1138
|
-
|
|
1139
|
-
|
|
1140
|
-
|
|
1141
|
-
|
|
1142
|
-
|
|
1143
|
-
|
|
1144
|
-
)
|
|
1145
|
-
|
|
1146
|
-
|
|
1147
|
-
|
|
1112
|
+
title: highlightTitle,
|
|
1113
|
+
children: /* @__PURE__ */ jsx4(AiFillHighlight, { className: "h-3 w-3" })
|
|
1114
|
+
}
|
|
1115
|
+
),
|
|
1116
|
+
enablePinning && onPinClick && /* @__PURE__ */ jsx4(
|
|
1117
|
+
"button",
|
|
1118
|
+
{
|
|
1119
|
+
type: "button",
|
|
1120
|
+
onClick: (e) => {
|
|
1121
|
+
e.stopPropagation();
|
|
1122
|
+
onPinClick();
|
|
1123
|
+
},
|
|
1124
|
+
className: cn(
|
|
1125
|
+
"p-0.5 hover:bg-gray-200 rounded transition-opacity",
|
|
1126
|
+
isPinned ? "text-blue-600 opacity-100" : "text-gray-400 opacity-0 group-hover:opacity-100"
|
|
1127
|
+
),
|
|
1128
|
+
title: isPinned ? pinnedTitle : unpinnedTitle,
|
|
1129
|
+
children: isPinned ? /* @__PURE__ */ jsx4(MdPushPin, { className: "h-3 w-3" }) : /* @__PURE__ */ jsx4(MdOutlinePushPin, { className: "h-3 w-3" })
|
|
1130
|
+
}
|
|
1131
|
+
)
|
|
1132
|
+
] });
|
|
1148
1133
|
}
|
|
1149
1134
|
ColumnHeaderActions.displayName = "ColumnHeaderActions";
|
|
1150
1135
|
|
|
@@ -1239,22 +1224,17 @@ function useSpreadsheetPinning({
|
|
|
1239
1224
|
columns,
|
|
1240
1225
|
columnGroups,
|
|
1241
1226
|
showRowIndex = true,
|
|
1242
|
-
defaultPinnedColumns = []
|
|
1243
|
-
defaultPinRowIndex = false
|
|
1227
|
+
defaultPinnedColumns = []
|
|
1244
1228
|
}) {
|
|
1245
1229
|
const [pinnedColumns, setPinnedColumns] = useState3(() => {
|
|
1246
1230
|
const map = /* @__PURE__ */ new Map();
|
|
1247
1231
|
defaultPinnedColumns.forEach((col) => {
|
|
1248
|
-
|
|
1249
|
-
map.set(col, "left");
|
|
1250
|
-
}
|
|
1232
|
+
map.set(col, "left");
|
|
1251
1233
|
});
|
|
1252
1234
|
return map;
|
|
1253
1235
|
});
|
|
1254
|
-
const [isRowIndexPinned, setIsRowIndexPinned] = useState3(
|
|
1255
|
-
defaultPinRowIndex || defaultPinnedColumns.includes(ROW_INDEX_COLUMN_ID)
|
|
1256
|
-
);
|
|
1257
1236
|
const [collapsedGroups, setCollapsedGroups] = useState3(/* @__PURE__ */ new Set());
|
|
1237
|
+
const isRowIndexPinned = pinnedColumns.has(ROW_INDEX_COLUMN_ID);
|
|
1258
1238
|
const handleTogglePin = useCallback((columnId) => {
|
|
1259
1239
|
setPinnedColumns((prev) => {
|
|
1260
1240
|
const newMap = new Map(prev);
|
|
@@ -1266,21 +1246,12 @@ function useSpreadsheetPinning({
|
|
|
1266
1246
|
return newMap;
|
|
1267
1247
|
});
|
|
1268
1248
|
}, []);
|
|
1269
|
-
const handleToggleRowIndexPin = useCallback(() => {
|
|
1270
|
-
setIsRowIndexPinned((prev) => !prev);
|
|
1271
|
-
}, []);
|
|
1272
1249
|
const setPinnedColumnsFromIds = useCallback((columnIds) => {
|
|
1273
1250
|
const map = /* @__PURE__ */ new Map();
|
|
1274
1251
|
columnIds.forEach((col) => {
|
|
1275
|
-
|
|
1276
|
-
map.set(col, "left");
|
|
1277
|
-
}
|
|
1252
|
+
map.set(col, "left");
|
|
1278
1253
|
});
|
|
1279
1254
|
setPinnedColumns(map);
|
|
1280
|
-
setIsRowIndexPinned(columnIds.includes(ROW_INDEX_COLUMN_ID));
|
|
1281
|
-
}, []);
|
|
1282
|
-
const setRowIndexPinned = useCallback((pinned) => {
|
|
1283
|
-
setIsRowIndexPinned(pinned);
|
|
1284
1255
|
}, []);
|
|
1285
1256
|
const handleToggleGroupCollapse = useCallback((groupId) => {
|
|
1286
1257
|
setCollapsedGroups((prev) => {
|
|
@@ -1306,14 +1277,17 @@ function useSpreadsheetPinning({
|
|
|
1306
1277
|
return pinnedColumns.has(column.id);
|
|
1307
1278
|
});
|
|
1308
1279
|
}
|
|
1309
|
-
|
|
1280
|
+
const nonRowIndexPinned = Array.from(pinnedColumns.keys()).filter(
|
|
1281
|
+
(id) => id !== ROW_INDEX_COLUMN_ID
|
|
1282
|
+
);
|
|
1283
|
+
if (nonRowIndexPinned.length === 0) {
|
|
1310
1284
|
return result;
|
|
1311
1285
|
}
|
|
1312
1286
|
const leftPinned = [];
|
|
1313
1287
|
const unpinned = [];
|
|
1314
1288
|
const rightPinned = [];
|
|
1315
|
-
const pinnedLeftIds = Array.from(pinnedColumns.entries()).filter(([, side]) => side === "left").map(([id]) => id);
|
|
1316
|
-
const pinnedRightIds = Array.from(pinnedColumns.entries()).filter(([, side]) => side === "right").map(([id]) => id);
|
|
1289
|
+
const pinnedLeftIds = Array.from(pinnedColumns.entries()).filter(([id, side]) => side === "left" && id !== ROW_INDEX_COLUMN_ID).map(([id]) => id);
|
|
1290
|
+
const pinnedRightIds = Array.from(pinnedColumns.entries()).filter(([id, side]) => side === "right" && id !== ROW_INDEX_COLUMN_ID).map(([id]) => id);
|
|
1317
1291
|
for (const column of result) {
|
|
1318
1292
|
const pinSide = pinnedColumns.get(column.id);
|
|
1319
1293
|
if (pinSide === "left") {
|
|
@@ -1328,23 +1302,24 @@ function useSpreadsheetPinning({
|
|
|
1328
1302
|
rightPinned.sort((a, b) => pinnedRightIds.indexOf(a.id) - pinnedRightIds.indexOf(b.id));
|
|
1329
1303
|
return [...leftPinned, ...unpinned, ...rightPinned];
|
|
1330
1304
|
}, [columns, columnGroups, collapsedGroups, pinnedColumns]);
|
|
1331
|
-
const getRowIndexLeftOffset = useCallback(() => {
|
|
1332
|
-
return 0;
|
|
1333
|
-
}, []);
|
|
1334
1305
|
const getColumnLeftOffset = useCallback(
|
|
1335
1306
|
(columnId) => {
|
|
1336
|
-
|
|
1307
|
+
if (columnId === ROW_INDEX_COLUMN_ID) {
|
|
1308
|
+
return 0;
|
|
1309
|
+
}
|
|
1310
|
+
const pinnedLeft = Array.from(pinnedColumns.entries()).filter(([id, side]) => side === "left" && id !== ROW_INDEX_COLUMN_ID).map(([id]) => id);
|
|
1337
1311
|
const index = pinnedLeft.indexOf(columnId);
|
|
1338
|
-
const
|
|
1312
|
+
const isRowIndexPinnedNow = pinnedColumns.has(ROW_INDEX_COLUMN_ID);
|
|
1313
|
+
const baseOffset = showRowIndex && isRowIndexPinnedNow ? ROW_INDEX_COLUMN_WIDTH : 0;
|
|
1339
1314
|
if (index === -1) return baseOffset;
|
|
1340
1315
|
let offset = baseOffset;
|
|
1341
1316
|
for (let i = 0; i < index; i++) {
|
|
1342
1317
|
const col = columns.find((c) => c.id === pinnedLeft[i]);
|
|
1343
|
-
offset += col?.
|
|
1318
|
+
offset += col?.minWidth || col?.width || 100;
|
|
1344
1319
|
}
|
|
1345
1320
|
return offset;
|
|
1346
1321
|
},
|
|
1347
|
-
[pinnedColumns, columns, showRowIndex
|
|
1322
|
+
[pinnedColumns, columns, showRowIndex]
|
|
1348
1323
|
);
|
|
1349
1324
|
const isColumnPinned = useCallback(
|
|
1350
1325
|
(columnId) => {
|
|
@@ -1364,12 +1339,9 @@ function useSpreadsheetPinning({
|
|
|
1364
1339
|
collapsedGroups,
|
|
1365
1340
|
visibleColumns,
|
|
1366
1341
|
handleTogglePin,
|
|
1367
|
-
handleToggleRowIndexPin,
|
|
1368
1342
|
handleToggleGroupCollapse,
|
|
1369
1343
|
setPinnedColumnsFromIds,
|
|
1370
|
-
setRowIndexPinned,
|
|
1371
1344
|
getColumnLeftOffset,
|
|
1372
|
-
getRowIndexLeftOffset,
|
|
1373
1345
|
isColumnPinned,
|
|
1374
1346
|
getColumnPinSide
|
|
1375
1347
|
};
|
|
@@ -2202,13 +2174,14 @@ function useSpreadsheetFiltering({
|
|
|
2202
2174
|
onSortChange,
|
|
2203
2175
|
serverSide = false,
|
|
2204
2176
|
controlledFilters,
|
|
2205
|
-
controlledSortConfig
|
|
2177
|
+
controlledSortConfig,
|
|
2178
|
+
defaultSortConfig
|
|
2206
2179
|
}) {
|
|
2207
2180
|
const [internalFilters, setInternalFilters] = useState7(
|
|
2208
2181
|
{}
|
|
2209
2182
|
);
|
|
2210
2183
|
const [internalSortConfig, setInternalSortConfig] = useState7(
|
|
2211
|
-
null
|
|
2184
|
+
defaultSortConfig ?? null
|
|
2212
2185
|
);
|
|
2213
2186
|
const [activeFilterColumn, setActiveFilterColumn] = useState7(null);
|
|
2214
2187
|
const filters = controlledFilters ?? internalFilters;
|
|
@@ -3336,7 +3309,8 @@ function Spreadsheet({
|
|
|
3336
3309
|
onSortChange,
|
|
3337
3310
|
serverSide,
|
|
3338
3311
|
controlledFilters,
|
|
3339
|
-
controlledSortConfig
|
|
3312
|
+
controlledSortConfig,
|
|
3313
|
+
defaultSortConfig: spreadsheetSettings.defaultSort
|
|
3340
3314
|
});
|
|
3341
3315
|
const {
|
|
3342
3316
|
getCellHighlight,
|
|
@@ -3368,7 +3342,8 @@ function Spreadsheet({
|
|
|
3368
3342
|
getColumnPinSide
|
|
3369
3343
|
} = useSpreadsheetPinning({
|
|
3370
3344
|
columns,
|
|
3371
|
-
columnGroups
|
|
3345
|
+
columnGroups,
|
|
3346
|
+
defaultPinnedColumns: initialSettings?.defaultPinnedColumns
|
|
3372
3347
|
});
|
|
3373
3348
|
const {
|
|
3374
3349
|
getCellComments,
|
|
@@ -3437,6 +3412,27 @@ function Spreadsheet({
|
|
|
3437
3412
|
defaultSort: sortConfig
|
|
3438
3413
|
}));
|
|
3439
3414
|
}, [sortConfig]);
|
|
3415
|
+
useEffect6(() => {
|
|
3416
|
+
const pinnedColumnIds = Array.from(pinnedColumns.keys());
|
|
3417
|
+
setSpreadsheetSettings((prev) => {
|
|
3418
|
+
const prevIds = prev.defaultPinnedColumns;
|
|
3419
|
+
if (prevIds.length === pinnedColumnIds.length && prevIds.every((id, idx) => id === pinnedColumnIds[idx])) {
|
|
3420
|
+
return prev;
|
|
3421
|
+
}
|
|
3422
|
+
return {
|
|
3423
|
+
...prev,
|
|
3424
|
+
defaultPinnedColumns: pinnedColumnIds
|
|
3425
|
+
};
|
|
3426
|
+
});
|
|
3427
|
+
}, [pinnedColumns]);
|
|
3428
|
+
const isInitialMount = useRef5(true);
|
|
3429
|
+
useEffect6(() => {
|
|
3430
|
+
if (isInitialMount.current) {
|
|
3431
|
+
isInitialMount.current = false;
|
|
3432
|
+
return;
|
|
3433
|
+
}
|
|
3434
|
+
onSettingsChange?.(spreadsheetSettings);
|
|
3435
|
+
}, [spreadsheetSettings, onSettingsChange]);
|
|
3440
3436
|
const applyUndo = useCallback7(() => {
|
|
3441
3437
|
const entry = popUndoEntry();
|
|
3442
3438
|
if (!entry || !onCellsEdit) return;
|