@xcelsior/ui-spreadsheets 1.1.12 → 1.1.14
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 +190 -187
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +180 -177
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
- package/src/components/Spreadsheet.stories.tsx +285 -25
- package/src/components/Spreadsheet.tsx +21 -19
- package/src/components/SpreadsheetCell.tsx +5 -3
- package/src/components/SpreadsheetHeader.tsx +5 -3
- package/src/hooks/useSpreadsheetPinning.ts +8 -3
package/dist/index.js
CHANGED
|
@@ -187,7 +187,162 @@ function cn(...inputs) {
|
|
|
187
187
|
}
|
|
188
188
|
|
|
189
189
|
// src/components/SpreadsheetCell.tsx
|
|
190
|
+
var import_react4 = require("react");
|
|
191
|
+
|
|
192
|
+
// src/hooks/useSpreadsheetPinning.ts
|
|
190
193
|
var import_react3 = require("react");
|
|
194
|
+
var ROW_INDEX_COLUMN_ID = "__row_index__";
|
|
195
|
+
var ROW_INDEX_COLUMN_WIDTH = 80;
|
|
196
|
+
var MIN_PINNED_COLUMN_WIDTH = 100;
|
|
197
|
+
function useSpreadsheetPinning({
|
|
198
|
+
columns,
|
|
199
|
+
columnGroups,
|
|
200
|
+
showRowIndex = true,
|
|
201
|
+
defaultPinnedColumns = [],
|
|
202
|
+
defaultPinnedRightColumns = []
|
|
203
|
+
}) {
|
|
204
|
+
const [pinnedColumns, setPinnedColumns] = (0, import_react3.useState)(() => {
|
|
205
|
+
const map = /* @__PURE__ */ new Map();
|
|
206
|
+
defaultPinnedColumns.forEach((col) => {
|
|
207
|
+
map.set(col, "left");
|
|
208
|
+
});
|
|
209
|
+
defaultPinnedRightColumns.forEach((col) => {
|
|
210
|
+
map.set(col, "right");
|
|
211
|
+
});
|
|
212
|
+
return map;
|
|
213
|
+
});
|
|
214
|
+
const [collapsedGroups, setCollapsedGroups] = (0, import_react3.useState)(/* @__PURE__ */ new Set());
|
|
215
|
+
const isRowIndexPinned = pinnedColumns.has(ROW_INDEX_COLUMN_ID);
|
|
216
|
+
const handleTogglePin = (0, import_react3.useCallback)((columnId) => {
|
|
217
|
+
setPinnedColumns((prev) => {
|
|
218
|
+
const newMap = new Map(prev);
|
|
219
|
+
if (newMap.has(columnId)) {
|
|
220
|
+
newMap.delete(columnId);
|
|
221
|
+
} else {
|
|
222
|
+
newMap.set(columnId, "left");
|
|
223
|
+
}
|
|
224
|
+
return newMap;
|
|
225
|
+
});
|
|
226
|
+
}, []);
|
|
227
|
+
const setPinnedColumnsFromIds = (0, import_react3.useCallback)((columnIds) => {
|
|
228
|
+
const map = /* @__PURE__ */ new Map();
|
|
229
|
+
columnIds.forEach((col) => {
|
|
230
|
+
map.set(col, "left");
|
|
231
|
+
});
|
|
232
|
+
setPinnedColumns(map);
|
|
233
|
+
}, []);
|
|
234
|
+
const handleToggleGroupCollapse = (0, import_react3.useCallback)((groupId) => {
|
|
235
|
+
setCollapsedGroups((prev) => {
|
|
236
|
+
const newSet = new Set(prev);
|
|
237
|
+
if (newSet.has(groupId)) {
|
|
238
|
+
newSet.delete(groupId);
|
|
239
|
+
} else {
|
|
240
|
+
newSet.add(groupId);
|
|
241
|
+
}
|
|
242
|
+
return newSet;
|
|
243
|
+
});
|
|
244
|
+
}, []);
|
|
245
|
+
const visibleColumns = (0, import_react3.useMemo)(() => {
|
|
246
|
+
if (!columns || !Array.isArray(columns) || columns.length === 0) {
|
|
247
|
+
return [];
|
|
248
|
+
}
|
|
249
|
+
let result = [...columns];
|
|
250
|
+
if (columnGroups && Array.isArray(columnGroups)) {
|
|
251
|
+
result = result.filter((column) => {
|
|
252
|
+
const group = columnGroups.find((g) => g.columns.includes(column.id));
|
|
253
|
+
if (!group) return true;
|
|
254
|
+
if (!collapsedGroups.has(group.id)) return true;
|
|
255
|
+
return pinnedColumns.has(column.id);
|
|
256
|
+
});
|
|
257
|
+
}
|
|
258
|
+
const nonRowIndexPinned = Array.from(pinnedColumns.keys()).filter(
|
|
259
|
+
(id) => id !== ROW_INDEX_COLUMN_ID
|
|
260
|
+
);
|
|
261
|
+
if (nonRowIndexPinned.length === 0) {
|
|
262
|
+
return result;
|
|
263
|
+
}
|
|
264
|
+
const leftPinned = [];
|
|
265
|
+
const unpinned = [];
|
|
266
|
+
const rightPinned = [];
|
|
267
|
+
const pinnedLeftIds = Array.from(pinnedColumns.entries()).filter(([id, side]) => side === "left" && id !== ROW_INDEX_COLUMN_ID).map(([id]) => id);
|
|
268
|
+
const pinnedRightIds = Array.from(pinnedColumns.entries()).filter(([id, side]) => side === "right" && id !== ROW_INDEX_COLUMN_ID).map(([id]) => id);
|
|
269
|
+
for (const column of result) {
|
|
270
|
+
const pinSide = pinnedColumns.get(column.id);
|
|
271
|
+
if (pinSide === "left") {
|
|
272
|
+
leftPinned.push(column);
|
|
273
|
+
} else if (pinSide === "right") {
|
|
274
|
+
rightPinned.push(column);
|
|
275
|
+
} else {
|
|
276
|
+
unpinned.push(column);
|
|
277
|
+
}
|
|
278
|
+
}
|
|
279
|
+
leftPinned.sort((a, b) => pinnedLeftIds.indexOf(a.id) - pinnedLeftIds.indexOf(b.id));
|
|
280
|
+
rightPinned.sort((a, b) => pinnedRightIds.indexOf(a.id) - pinnedRightIds.indexOf(b.id));
|
|
281
|
+
return [...leftPinned, ...unpinned, ...rightPinned];
|
|
282
|
+
}, [columns, columnGroups, collapsedGroups, pinnedColumns]);
|
|
283
|
+
const getColumnLeftOffset = (0, import_react3.useCallback)(
|
|
284
|
+
(columnId) => {
|
|
285
|
+
if (columnId === ROW_INDEX_COLUMN_ID) {
|
|
286
|
+
return 0;
|
|
287
|
+
}
|
|
288
|
+
const pinnedLeft = Array.from(pinnedColumns.entries()).filter(([id, side]) => side === "left" && id !== ROW_INDEX_COLUMN_ID).map(([id]) => id);
|
|
289
|
+
const index = pinnedLeft.indexOf(columnId);
|
|
290
|
+
const isRowIndexPinnedNow = pinnedColumns.has(ROW_INDEX_COLUMN_ID);
|
|
291
|
+
const baseOffset = showRowIndex && isRowIndexPinnedNow ? ROW_INDEX_COLUMN_WIDTH : 0;
|
|
292
|
+
if (index === -1) return baseOffset;
|
|
293
|
+
let offset = baseOffset;
|
|
294
|
+
for (let i = 0; i < index; i++) {
|
|
295
|
+
const col = columns.find((c) => c.id === pinnedLeft[i]);
|
|
296
|
+
const configuredWidth = col?.minWidth || col?.width || MIN_PINNED_COLUMN_WIDTH;
|
|
297
|
+
offset += Math.max(configuredWidth, MIN_PINNED_COLUMN_WIDTH);
|
|
298
|
+
}
|
|
299
|
+
return offset;
|
|
300
|
+
},
|
|
301
|
+
[pinnedColumns, columns, showRowIndex]
|
|
302
|
+
);
|
|
303
|
+
const isColumnPinned = (0, import_react3.useCallback)(
|
|
304
|
+
(columnId) => {
|
|
305
|
+
return pinnedColumns.has(columnId);
|
|
306
|
+
},
|
|
307
|
+
[pinnedColumns]
|
|
308
|
+
);
|
|
309
|
+
const getColumnPinSide = (0, import_react3.useCallback)(
|
|
310
|
+
(columnId) => {
|
|
311
|
+
return pinnedColumns.get(columnId);
|
|
312
|
+
},
|
|
313
|
+
[pinnedColumns]
|
|
314
|
+
);
|
|
315
|
+
const getColumnRightOffset = (0, import_react3.useCallback)(
|
|
316
|
+
(columnId) => {
|
|
317
|
+
const pinnedRight = Array.from(pinnedColumns.entries()).filter(([, side]) => side === "right").map(([id]) => id);
|
|
318
|
+
const index = pinnedRight.indexOf(columnId);
|
|
319
|
+
if (index === -1) return 0;
|
|
320
|
+
let offset = 0;
|
|
321
|
+
for (let i = pinnedRight.length - 1; i > index; i--) {
|
|
322
|
+
const col = columns.find((c) => c.id === pinnedRight[i]);
|
|
323
|
+
const configuredWidth = col?.minWidth || col?.width || MIN_PINNED_COLUMN_WIDTH;
|
|
324
|
+
offset += Math.max(configuredWidth, MIN_PINNED_COLUMN_WIDTH);
|
|
325
|
+
}
|
|
326
|
+
return offset;
|
|
327
|
+
},
|
|
328
|
+
[pinnedColumns, columns]
|
|
329
|
+
);
|
|
330
|
+
return {
|
|
331
|
+
pinnedColumns,
|
|
332
|
+
isRowIndexPinned,
|
|
333
|
+
collapsedGroups,
|
|
334
|
+
visibleColumns,
|
|
335
|
+
handleTogglePin,
|
|
336
|
+
handleToggleGroupCollapse,
|
|
337
|
+
setPinnedColumnsFromIds,
|
|
338
|
+
getColumnLeftOffset,
|
|
339
|
+
getColumnRightOffset,
|
|
340
|
+
isColumnPinned,
|
|
341
|
+
getColumnPinSide
|
|
342
|
+
};
|
|
343
|
+
}
|
|
344
|
+
|
|
345
|
+
// src/components/SpreadsheetCell.tsx
|
|
191
346
|
var import_jsx_runtime = require("react/jsx-runtime");
|
|
192
347
|
var cellPaddingCompact = "px-1 py-px";
|
|
193
348
|
var cellPaddingNormal = "px-2 py-1";
|
|
@@ -224,13 +379,13 @@ var SpreadsheetCell = ({
|
|
|
224
379
|
onViewComments,
|
|
225
380
|
className
|
|
226
381
|
}) => {
|
|
227
|
-
const [localValue, setLocalValue] = (0,
|
|
228
|
-
const inputRef = (0,
|
|
229
|
-
const selectRef = (0,
|
|
230
|
-
(0,
|
|
382
|
+
const [localValue, setLocalValue] = (0, import_react4.useState)(value);
|
|
383
|
+
const inputRef = (0, import_react4.useRef)(null);
|
|
384
|
+
const selectRef = (0, import_react4.useRef)(null);
|
|
385
|
+
(0, import_react4.useEffect)(() => {
|
|
231
386
|
setLocalValue(value);
|
|
232
387
|
}, [value]);
|
|
233
|
-
(0,
|
|
388
|
+
(0, import_react4.useEffect)(() => {
|
|
234
389
|
if (isEditing) {
|
|
235
390
|
if (column.type === "select") {
|
|
236
391
|
selectRef.current?.focus();
|
|
@@ -403,10 +558,11 @@ var SpreadsheetCell = ({
|
|
|
403
558
|
style: {
|
|
404
559
|
backgroundColor: isInSelection ? "rgb(239 246 255)" : getBackgroundColor(),
|
|
405
560
|
minWidth: column.minWidth || column.width,
|
|
406
|
-
// Pinned columns
|
|
561
|
+
// Pinned columns must have a fixed width so sticky offsets stay correct.
|
|
562
|
+
// Enforce MIN_PINNED_COLUMN_WIDTH so header actions always fit.
|
|
407
563
|
...isPinned && {
|
|
408
|
-
width: column.minWidth || column.width,
|
|
409
|
-
maxWidth: column.minWidth || column.width
|
|
564
|
+
width: Math.max(column.minWidth || column.width || MIN_PINNED_COLUMN_WIDTH, MIN_PINNED_COLUMN_WIDTH),
|
|
565
|
+
maxWidth: Math.max(column.minWidth || column.width || MIN_PINNED_COLUMN_WIDTH, MIN_PINNED_COLUMN_WIDTH)
|
|
410
566
|
},
|
|
411
567
|
...positionStyles,
|
|
412
568
|
...selectionBorderStyles
|
|
@@ -479,7 +635,7 @@ var SpreadsheetCell = ({
|
|
|
479
635
|
);
|
|
480
636
|
};
|
|
481
637
|
SpreadsheetCell.displayName = "SpreadsheetCell";
|
|
482
|
-
var MemoizedSpreadsheetCell = (0,
|
|
638
|
+
var MemoizedSpreadsheetCell = (0, import_react4.memo)(SpreadsheetCell, (prevProps, nextProps) => {
|
|
483
639
|
if (prevProps.isEditing !== nextProps.isEditing) return false;
|
|
484
640
|
if (prevProps.isFocused !== nextProps.isFocused) return false;
|
|
485
641
|
if (prevProps.value !== nextProps.value) return false;
|
|
@@ -508,7 +664,7 @@ var MemoizedSpreadsheetCell = (0, import_react3.memo)(SpreadsheetCell, (prevProp
|
|
|
508
664
|
MemoizedSpreadsheetCell.displayName = "MemoizedSpreadsheetCell";
|
|
509
665
|
|
|
510
666
|
// src/components/SpreadsheetFilterDropdown.tsx
|
|
511
|
-
var
|
|
667
|
+
var import_react5 = require("react");
|
|
512
668
|
var import_jsx_runtime2 = require("react/jsx-runtime");
|
|
513
669
|
var TEXT_OPERATORS = [
|
|
514
670
|
{ value: "contains", label: "Contains" },
|
|
@@ -554,28 +710,28 @@ var SpreadsheetFilterDropdown = ({
|
|
|
554
710
|
onClose,
|
|
555
711
|
className
|
|
556
712
|
}) => {
|
|
557
|
-
const [textOperator, setTextOperator] = (0,
|
|
713
|
+
const [textOperator, setTextOperator] = (0, import_react5.useState)(
|
|
558
714
|
filter?.textCondition?.operator || "contains"
|
|
559
715
|
);
|
|
560
|
-
const [textValue, setTextValue] = (0,
|
|
561
|
-
const [numberOperator, setNumberOperator] = (0,
|
|
716
|
+
const [textValue, setTextValue] = (0, import_react5.useState)(filter?.textCondition?.value || "");
|
|
717
|
+
const [numberOperator, setNumberOperator] = (0, import_react5.useState)(
|
|
562
718
|
filter?.numberCondition?.operator || "equals"
|
|
563
719
|
);
|
|
564
|
-
const [numberValue, setNumberValue] = (0,
|
|
720
|
+
const [numberValue, setNumberValue] = (0, import_react5.useState)(
|
|
565
721
|
filter?.numberCondition?.value?.toString() || ""
|
|
566
722
|
);
|
|
567
|
-
const [numberValueTo, setNumberValueTo] = (0,
|
|
723
|
+
const [numberValueTo, setNumberValueTo] = (0, import_react5.useState)(
|
|
568
724
|
filter?.numberCondition?.valueTo?.toString() || ""
|
|
569
725
|
);
|
|
570
|
-
const [dateOperator, setDateOperator] = (0,
|
|
726
|
+
const [dateOperator, setDateOperator] = (0, import_react5.useState)(
|
|
571
727
|
filter?.dateCondition?.operator || "equals"
|
|
572
728
|
);
|
|
573
|
-
const [dateValue, setDateValue] = (0,
|
|
574
|
-
const [dateValueTo, setDateValueTo] = (0,
|
|
575
|
-
const dropdownRef = (0,
|
|
729
|
+
const [dateValue, setDateValue] = (0, import_react5.useState)(filter?.dateCondition?.value || "");
|
|
730
|
+
const [dateValueTo, setDateValueTo] = (0, import_react5.useState)(filter?.dateCondition?.valueTo || "");
|
|
731
|
+
const dropdownRef = (0, import_react5.useRef)(null);
|
|
576
732
|
const isNumeric = column.type === "number";
|
|
577
733
|
const isDate = column.type === "date";
|
|
578
|
-
(0,
|
|
734
|
+
(0, import_react5.useEffect)(() => {
|
|
579
735
|
const handleClickOutside = (event) => {
|
|
580
736
|
if (dropdownRef.current && !dropdownRef.current.contains(event.target)) {
|
|
581
737
|
onClose();
|
|
@@ -813,7 +969,7 @@ var SpreadsheetFilterDropdown = ({
|
|
|
813
969
|
SpreadsheetFilterDropdown.displayName = "SpreadsheetFilterDropdown";
|
|
814
970
|
|
|
815
971
|
// src/components/SpreadsheetToolbar.tsx
|
|
816
|
-
var
|
|
972
|
+
var import_react6 = __toESM(require("react"));
|
|
817
973
|
var import_jsx_runtime3 = require("react/jsx-runtime");
|
|
818
974
|
var SpreadsheetToolbar = ({
|
|
819
975
|
zoom,
|
|
@@ -840,9 +996,9 @@ var SpreadsheetToolbar = ({
|
|
|
840
996
|
onClearFilters,
|
|
841
997
|
className
|
|
842
998
|
}) => {
|
|
843
|
-
const [showMoreMenu, setShowMoreMenu] =
|
|
844
|
-
const menuRef =
|
|
845
|
-
|
|
999
|
+
const [showMoreMenu, setShowMoreMenu] = import_react6.default.useState(false);
|
|
1000
|
+
const menuRef = import_react6.default.useRef(null);
|
|
1001
|
+
import_react6.default.useEffect(() => {
|
|
846
1002
|
const handleClickOutside = (event) => {
|
|
847
1003
|
if (menuRef.current && !menuRef.current.contains(event.target)) {
|
|
848
1004
|
setShowMoreMenu(false);
|
|
@@ -1249,10 +1405,11 @@ var SpreadsheetHeader = ({
|
|
|
1249
1405
|
backgroundColor: highlightColor || "rgb(243 244 246)",
|
|
1250
1406
|
// gray-100
|
|
1251
1407
|
minWidth: column.minWidth || column.width,
|
|
1252
|
-
// Pinned columns
|
|
1408
|
+
// Pinned columns must have a fixed width so sticky offsets stay correct.
|
|
1409
|
+
// Enforce MIN_PINNED_COLUMN_WIDTH so header actions (pin/filter/highlight) always fit.
|
|
1253
1410
|
...isPinned && {
|
|
1254
|
-
width: column.minWidth || column.width,
|
|
1255
|
-
maxWidth: column.minWidth || column.width
|
|
1411
|
+
width: Math.max(column.minWidth || column.width || MIN_PINNED_COLUMN_WIDTH, MIN_PINNED_COLUMN_WIDTH),
|
|
1412
|
+
maxWidth: Math.max(column.minWidth || column.width || MIN_PINNED_COLUMN_WIDTH, MIN_PINNED_COLUMN_WIDTH)
|
|
1256
1413
|
},
|
|
1257
1414
|
top: 0,
|
|
1258
1415
|
// For sticky header
|
|
@@ -1286,156 +1443,6 @@ var SpreadsheetHeader = ({
|
|
|
1286
1443
|
};
|
|
1287
1444
|
SpreadsheetHeader.displayName = "SpreadsheetHeader";
|
|
1288
1445
|
|
|
1289
|
-
// src/hooks/useSpreadsheetPinning.ts
|
|
1290
|
-
var import_react6 = require("react");
|
|
1291
|
-
var ROW_INDEX_COLUMN_ID = "__row_index__";
|
|
1292
|
-
var ROW_INDEX_COLUMN_WIDTH = 80;
|
|
1293
|
-
function useSpreadsheetPinning({
|
|
1294
|
-
columns,
|
|
1295
|
-
columnGroups,
|
|
1296
|
-
showRowIndex = true,
|
|
1297
|
-
defaultPinnedColumns = [],
|
|
1298
|
-
defaultPinnedRightColumns = []
|
|
1299
|
-
}) {
|
|
1300
|
-
const [pinnedColumns, setPinnedColumns] = (0, import_react6.useState)(() => {
|
|
1301
|
-
const map = /* @__PURE__ */ new Map();
|
|
1302
|
-
defaultPinnedColumns.forEach((col) => {
|
|
1303
|
-
map.set(col, "left");
|
|
1304
|
-
});
|
|
1305
|
-
defaultPinnedRightColumns.forEach((col) => {
|
|
1306
|
-
map.set(col, "right");
|
|
1307
|
-
});
|
|
1308
|
-
return map;
|
|
1309
|
-
});
|
|
1310
|
-
const [collapsedGroups, setCollapsedGroups] = (0, import_react6.useState)(/* @__PURE__ */ new Set());
|
|
1311
|
-
const isRowIndexPinned = pinnedColumns.has(ROW_INDEX_COLUMN_ID);
|
|
1312
|
-
const handleTogglePin = (0, import_react6.useCallback)((columnId) => {
|
|
1313
|
-
setPinnedColumns((prev) => {
|
|
1314
|
-
const newMap = new Map(prev);
|
|
1315
|
-
if (newMap.has(columnId)) {
|
|
1316
|
-
newMap.delete(columnId);
|
|
1317
|
-
} else {
|
|
1318
|
-
newMap.set(columnId, "left");
|
|
1319
|
-
}
|
|
1320
|
-
return newMap;
|
|
1321
|
-
});
|
|
1322
|
-
}, []);
|
|
1323
|
-
const setPinnedColumnsFromIds = (0, import_react6.useCallback)((columnIds) => {
|
|
1324
|
-
const map = /* @__PURE__ */ new Map();
|
|
1325
|
-
columnIds.forEach((col) => {
|
|
1326
|
-
map.set(col, "left");
|
|
1327
|
-
});
|
|
1328
|
-
setPinnedColumns(map);
|
|
1329
|
-
}, []);
|
|
1330
|
-
const handleToggleGroupCollapse = (0, import_react6.useCallback)((groupId) => {
|
|
1331
|
-
setCollapsedGroups((prev) => {
|
|
1332
|
-
const newSet = new Set(prev);
|
|
1333
|
-
if (newSet.has(groupId)) {
|
|
1334
|
-
newSet.delete(groupId);
|
|
1335
|
-
} else {
|
|
1336
|
-
newSet.add(groupId);
|
|
1337
|
-
}
|
|
1338
|
-
return newSet;
|
|
1339
|
-
});
|
|
1340
|
-
}, []);
|
|
1341
|
-
const visibleColumns = (0, import_react6.useMemo)(() => {
|
|
1342
|
-
if (!columns || !Array.isArray(columns) || columns.length === 0) {
|
|
1343
|
-
return [];
|
|
1344
|
-
}
|
|
1345
|
-
let result = [...columns];
|
|
1346
|
-
if (columnGroups && Array.isArray(columnGroups)) {
|
|
1347
|
-
result = result.filter((column) => {
|
|
1348
|
-
const group = columnGroups.find((g) => g.columns.includes(column.id));
|
|
1349
|
-
if (!group) return true;
|
|
1350
|
-
if (!collapsedGroups.has(group.id)) return true;
|
|
1351
|
-
return pinnedColumns.has(column.id);
|
|
1352
|
-
});
|
|
1353
|
-
}
|
|
1354
|
-
const nonRowIndexPinned = Array.from(pinnedColumns.keys()).filter(
|
|
1355
|
-
(id) => id !== ROW_INDEX_COLUMN_ID
|
|
1356
|
-
);
|
|
1357
|
-
if (nonRowIndexPinned.length === 0) {
|
|
1358
|
-
return result;
|
|
1359
|
-
}
|
|
1360
|
-
const leftPinned = [];
|
|
1361
|
-
const unpinned = [];
|
|
1362
|
-
const rightPinned = [];
|
|
1363
|
-
const pinnedLeftIds = Array.from(pinnedColumns.entries()).filter(([id, side]) => side === "left" && id !== ROW_INDEX_COLUMN_ID).map(([id]) => id);
|
|
1364
|
-
const pinnedRightIds = Array.from(pinnedColumns.entries()).filter(([id, side]) => side === "right" && id !== ROW_INDEX_COLUMN_ID).map(([id]) => id);
|
|
1365
|
-
for (const column of result) {
|
|
1366
|
-
const pinSide = pinnedColumns.get(column.id);
|
|
1367
|
-
if (pinSide === "left") {
|
|
1368
|
-
leftPinned.push(column);
|
|
1369
|
-
} else if (pinSide === "right") {
|
|
1370
|
-
rightPinned.push(column);
|
|
1371
|
-
} else {
|
|
1372
|
-
unpinned.push(column);
|
|
1373
|
-
}
|
|
1374
|
-
}
|
|
1375
|
-
leftPinned.sort((a, b) => pinnedLeftIds.indexOf(a.id) - pinnedLeftIds.indexOf(b.id));
|
|
1376
|
-
rightPinned.sort((a, b) => pinnedRightIds.indexOf(a.id) - pinnedRightIds.indexOf(b.id));
|
|
1377
|
-
return [...leftPinned, ...unpinned, ...rightPinned];
|
|
1378
|
-
}, [columns, columnGroups, collapsedGroups, pinnedColumns]);
|
|
1379
|
-
const getColumnLeftOffset = (0, import_react6.useCallback)(
|
|
1380
|
-
(columnId) => {
|
|
1381
|
-
if (columnId === ROW_INDEX_COLUMN_ID) {
|
|
1382
|
-
return 0;
|
|
1383
|
-
}
|
|
1384
|
-
const pinnedLeft = Array.from(pinnedColumns.entries()).filter(([id, side]) => side === "left" && id !== ROW_INDEX_COLUMN_ID).map(([id]) => id);
|
|
1385
|
-
const index = pinnedLeft.indexOf(columnId);
|
|
1386
|
-
const isRowIndexPinnedNow = pinnedColumns.has(ROW_INDEX_COLUMN_ID);
|
|
1387
|
-
const baseOffset = showRowIndex && isRowIndexPinnedNow ? ROW_INDEX_COLUMN_WIDTH : 0;
|
|
1388
|
-
if (index === -1) return baseOffset;
|
|
1389
|
-
let offset = baseOffset;
|
|
1390
|
-
for (let i = 0; i < index; i++) {
|
|
1391
|
-
const col = columns.find((c) => c.id === pinnedLeft[i]);
|
|
1392
|
-
offset += col?.minWidth || col?.width || 100;
|
|
1393
|
-
}
|
|
1394
|
-
return offset;
|
|
1395
|
-
},
|
|
1396
|
-
[pinnedColumns, columns, showRowIndex]
|
|
1397
|
-
);
|
|
1398
|
-
const isColumnPinned = (0, import_react6.useCallback)(
|
|
1399
|
-
(columnId) => {
|
|
1400
|
-
return pinnedColumns.has(columnId);
|
|
1401
|
-
},
|
|
1402
|
-
[pinnedColumns]
|
|
1403
|
-
);
|
|
1404
|
-
const getColumnPinSide = (0, import_react6.useCallback)(
|
|
1405
|
-
(columnId) => {
|
|
1406
|
-
return pinnedColumns.get(columnId);
|
|
1407
|
-
},
|
|
1408
|
-
[pinnedColumns]
|
|
1409
|
-
);
|
|
1410
|
-
const getColumnRightOffset = (0, import_react6.useCallback)(
|
|
1411
|
-
(columnId) => {
|
|
1412
|
-
const pinnedRight = Array.from(pinnedColumns.entries()).filter(([, side]) => side === "right").map(([id]) => id);
|
|
1413
|
-
const index = pinnedRight.indexOf(columnId);
|
|
1414
|
-
if (index === -1) return 0;
|
|
1415
|
-
let offset = 0;
|
|
1416
|
-
for (let i = pinnedRight.length - 1; i > index; i--) {
|
|
1417
|
-
const col = columns.find((c) => c.id === pinnedRight[i]);
|
|
1418
|
-
offset += col?.minWidth || col?.width || 100;
|
|
1419
|
-
}
|
|
1420
|
-
return offset;
|
|
1421
|
-
},
|
|
1422
|
-
[pinnedColumns, columns]
|
|
1423
|
-
);
|
|
1424
|
-
return {
|
|
1425
|
-
pinnedColumns,
|
|
1426
|
-
isRowIndexPinned,
|
|
1427
|
-
collapsedGroups,
|
|
1428
|
-
visibleColumns,
|
|
1429
|
-
handleTogglePin,
|
|
1430
|
-
handleToggleGroupCollapse,
|
|
1431
|
-
setPinnedColumnsFromIds,
|
|
1432
|
-
getColumnLeftOffset,
|
|
1433
|
-
getColumnRightOffset,
|
|
1434
|
-
isColumnPinned,
|
|
1435
|
-
getColumnPinSide
|
|
1436
|
-
};
|
|
1437
|
-
}
|
|
1438
|
-
|
|
1439
1446
|
// src/components/RowIndexColumnHeader.tsx
|
|
1440
1447
|
var import_jsx_runtime6 = require("react/jsx-runtime");
|
|
1441
1448
|
var cellPaddingCompact3 = "px-1 py-0.5";
|
|
@@ -3919,9 +3926,7 @@ function Spreadsheet({
|
|
|
3919
3926
|
}
|
|
3920
3927
|
}
|
|
3921
3928
|
}
|
|
3922
|
-
const allGroupedIds = new Set(
|
|
3923
|
-
columnGroups.flatMap((g) => g.columns)
|
|
3924
|
-
);
|
|
3929
|
+
const allGroupedIds = new Set(columnGroups.flatMap((g) => g.columns));
|
|
3925
3930
|
for (const col of visibleColumns) {
|
|
3926
3931
|
if (!allGroupedIds.has(col.id)) {
|
|
3927
3932
|
const pinSide = pinnedColumns.get(col.id);
|
|
@@ -4033,7 +4038,7 @@ function Spreadsheet({
|
|
|
4033
4038
|
style: {
|
|
4034
4039
|
zoom: zoom / 100
|
|
4035
4040
|
},
|
|
4036
|
-
children: /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("table", { className: "
|
|
4041
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("table", { className: "border-separate border-spacing-0 text-xs select-none", children: [
|
|
4037
4042
|
/* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("thead", { children: [
|
|
4038
4043
|
columnGroups && groupHeaderItems && /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("tr", { children: [
|
|
4039
4044
|
/* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
|
|
@@ -4050,9 +4055,7 @@ function Spreadsheet({
|
|
|
4050
4055
|
),
|
|
4051
4056
|
groupHeaderItems.map((item) => {
|
|
4052
4057
|
if (item.type === "pinned-column") {
|
|
4053
|
-
const col = columns.find(
|
|
4054
|
-
(c) => c.id === item.columnId
|
|
4055
|
-
);
|
|
4058
|
+
const col = columns.find((c) => c.id === item.columnId);
|
|
4056
4059
|
const isPinnedLeft = item.pinSide === "left";
|
|
4057
4060
|
return /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
|
|
4058
4061
|
"th",
|
|
@@ -4066,9 +4069,9 @@ function Spreadsheet({
|
|
|
4066
4069
|
position: "sticky",
|
|
4067
4070
|
left: isPinnedLeft ? `${getColumnLeftOffset(item.columnId)}px` : void 0,
|
|
4068
4071
|
right: !isPinnedLeft ? `${getColumnRightOffset(item.columnId)}px` : void 0,
|
|
4069
|
-
minWidth: col?.minWidth || col?.width,
|
|
4070
|
-
width: col?.minWidth || col?.width,
|
|
4071
|
-
maxWidth: col?.minWidth || col?.width
|
|
4072
|
+
minWidth: Math.max(col?.minWidth || col?.width || MIN_PINNED_COLUMN_WIDTH, MIN_PINNED_COLUMN_WIDTH),
|
|
4073
|
+
width: Math.max(col?.minWidth || col?.width || MIN_PINNED_COLUMN_WIDTH, MIN_PINNED_COLUMN_WIDTH),
|
|
4074
|
+
maxWidth: Math.max(col?.minWidth || col?.width || MIN_PINNED_COLUMN_WIDTH, MIN_PINNED_COLUMN_WIDTH)
|
|
4072
4075
|
}
|
|
4073
4076
|
},
|
|
4074
4077
|
`pinned-group-${item.columnId}`
|