@xcelsior/ui-spreadsheets 1.1.10 → 1.1.12
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 +119 -16
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +119 -16
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
- package/src/components/Spreadsheet.stories.tsx +121 -0
- package/src/components/Spreadsheet.tsx +161 -27
- package/src/components/SpreadsheetCell.tsx +5 -0
- package/src/components/SpreadsheetHeader.tsx +5 -0
package/dist/index.js
CHANGED
|
@@ -403,6 +403,11 @@ var SpreadsheetCell = ({
|
|
|
403
403
|
style: {
|
|
404
404
|
backgroundColor: isInSelection ? "rgb(239 246 255)" : getBackgroundColor(),
|
|
405
405
|
minWidth: column.minWidth || column.width,
|
|
406
|
+
// Pinned columns need fixed width so sticky offset calculations are accurate
|
|
407
|
+
...isPinned && {
|
|
408
|
+
width: column.minWidth || column.width,
|
|
409
|
+
maxWidth: column.minWidth || column.width
|
|
410
|
+
},
|
|
406
411
|
...positionStyles,
|
|
407
412
|
...selectionBorderStyles
|
|
408
413
|
},
|
|
@@ -1244,6 +1249,11 @@ var SpreadsheetHeader = ({
|
|
|
1244
1249
|
backgroundColor: highlightColor || "rgb(243 244 246)",
|
|
1245
1250
|
// gray-100
|
|
1246
1251
|
minWidth: column.minWidth || column.width,
|
|
1252
|
+
// Pinned columns need fixed width so sticky offset calculations are accurate
|
|
1253
|
+
...isPinned && {
|
|
1254
|
+
width: column.minWidth || column.width,
|
|
1255
|
+
maxWidth: column.minWidth || column.width
|
|
1256
|
+
},
|
|
1247
1257
|
top: 0,
|
|
1248
1258
|
// For sticky header
|
|
1249
1259
|
...positionStyles
|
|
@@ -3881,11 +3891,13 @@ function Spreadsheet({
|
|
|
3881
3891
|
column: col
|
|
3882
3892
|
}));
|
|
3883
3893
|
}
|
|
3884
|
-
const
|
|
3894
|
+
const leftPinnedItems = [];
|
|
3895
|
+
const middleItems = [];
|
|
3896
|
+
const rightPinnedItems = [];
|
|
3885
3897
|
for (const group of columnGroups) {
|
|
3886
3898
|
const isCollapsed = collapsedGroups.has(group.id);
|
|
3887
3899
|
if (isCollapsed) {
|
|
3888
|
-
|
|
3900
|
+
middleItems.push({
|
|
3889
3901
|
type: "collapsed-placeholder",
|
|
3890
3902
|
groupId: group.id,
|
|
3891
3903
|
headerColor: group.headerColor
|
|
@@ -3897,7 +3909,14 @@ function Spreadsheet({
|
|
|
3897
3909
|
return true;
|
|
3898
3910
|
});
|
|
3899
3911
|
for (const col of groupVisibleCols) {
|
|
3900
|
-
|
|
3912
|
+
const pinSide = pinnedColumns.get(col.id);
|
|
3913
|
+
if (pinSide === "left") {
|
|
3914
|
+
leftPinnedItems.push({ type: "column", column: col });
|
|
3915
|
+
} else if (pinSide === "right") {
|
|
3916
|
+
rightPinnedItems.push({ type: "column", column: col });
|
|
3917
|
+
} else {
|
|
3918
|
+
middleItems.push({ type: "column", column: col });
|
|
3919
|
+
}
|
|
3901
3920
|
}
|
|
3902
3921
|
}
|
|
3903
3922
|
const allGroupedIds = new Set(
|
|
@@ -3905,11 +3924,78 @@ function Spreadsheet({
|
|
|
3905
3924
|
);
|
|
3906
3925
|
for (const col of visibleColumns) {
|
|
3907
3926
|
if (!allGroupedIds.has(col.id)) {
|
|
3908
|
-
|
|
3927
|
+
const pinSide = pinnedColumns.get(col.id);
|
|
3928
|
+
if (pinSide === "left") {
|
|
3929
|
+
leftPinnedItems.push({ type: "column", column: col });
|
|
3930
|
+
} else if (pinSide === "right") {
|
|
3931
|
+
rightPinnedItems.push({ type: "column", column: col });
|
|
3932
|
+
} else {
|
|
3933
|
+
middleItems.push({ type: "column", column: col });
|
|
3934
|
+
}
|
|
3909
3935
|
}
|
|
3910
3936
|
}
|
|
3911
|
-
|
|
3937
|
+
const pinnedLeftOrder = Array.from(pinnedColumns.entries()).filter(([id, side]) => side === "left" && id !== ROW_INDEX_COLUMN_ID).map(([id]) => id);
|
|
3938
|
+
const pinnedRightOrder = Array.from(pinnedColumns.entries()).filter(([, side]) => side === "right").map(([id]) => id);
|
|
3939
|
+
leftPinnedItems.sort(
|
|
3940
|
+
(a, b) => pinnedLeftOrder.indexOf(a.column.id) - pinnedLeftOrder.indexOf(b.column.id)
|
|
3941
|
+
);
|
|
3942
|
+
rightPinnedItems.sort(
|
|
3943
|
+
(a, b) => pinnedRightOrder.indexOf(a.column.id) - pinnedRightOrder.indexOf(b.column.id)
|
|
3944
|
+
);
|
|
3945
|
+
return [...leftPinnedItems, ...middleItems, ...rightPinnedItems];
|
|
3912
3946
|
}, [columnGroups, collapsedGroups, columns, pinnedColumns, visibleColumns]);
|
|
3947
|
+
const groupHeaderItems = (0, import_react17.useMemo)(() => {
|
|
3948
|
+
if (!columnGroups || columnGroups.length === 0) return null;
|
|
3949
|
+
const leftPinned = [];
|
|
3950
|
+
const groups = [];
|
|
3951
|
+
const rightPinned = [];
|
|
3952
|
+
for (const group of columnGroups) {
|
|
3953
|
+
const isCollapsed = collapsedGroups.has(group.id);
|
|
3954
|
+
const groupColumns = (columns || []).filter((c) => group.columns.includes(c.id));
|
|
3955
|
+
const visibleGroupColumns = isCollapsed ? groupColumns.filter((c) => pinnedColumns.has(c.id)) : groupColumns;
|
|
3956
|
+
let movedLeftCount = 0;
|
|
3957
|
+
let movedRightCount = 0;
|
|
3958
|
+
for (const col of visibleGroupColumns) {
|
|
3959
|
+
const pinSide = pinnedColumns.get(col.id);
|
|
3960
|
+
if (pinSide === "left") {
|
|
3961
|
+
movedLeftCount++;
|
|
3962
|
+
leftPinned.push({
|
|
3963
|
+
type: "pinned-column",
|
|
3964
|
+
columnId: col.id,
|
|
3965
|
+
headerColor: group.headerColor,
|
|
3966
|
+
pinSide: "left"
|
|
3967
|
+
});
|
|
3968
|
+
} else if (pinSide === "right") {
|
|
3969
|
+
movedRightCount++;
|
|
3970
|
+
rightPinned.push({
|
|
3971
|
+
type: "pinned-column",
|
|
3972
|
+
columnId: col.id,
|
|
3973
|
+
headerColor: group.headerColor,
|
|
3974
|
+
pinSide: "right"
|
|
3975
|
+
});
|
|
3976
|
+
}
|
|
3977
|
+
}
|
|
3978
|
+
const remainingCols = visibleGroupColumns.length - movedLeftCount - movedRightCount;
|
|
3979
|
+
const colSpan = remainingCols + (isCollapsed ? 1 : 0);
|
|
3980
|
+
if (colSpan > 0) {
|
|
3981
|
+
groups.push({
|
|
3982
|
+
type: "group",
|
|
3983
|
+
group,
|
|
3984
|
+
colSpan,
|
|
3985
|
+
isCollapsed
|
|
3986
|
+
});
|
|
3987
|
+
}
|
|
3988
|
+
}
|
|
3989
|
+
const pinnedLeftOrder = Array.from(pinnedColumns.entries()).filter(([id, side]) => side === "left" && id !== ROW_INDEX_COLUMN_ID).map(([id]) => id);
|
|
3990
|
+
const pinnedRightOrder = Array.from(pinnedColumns.entries()).filter(([, side]) => side === "right").map(([id]) => id);
|
|
3991
|
+
leftPinned.sort(
|
|
3992
|
+
(a, b) => pinnedLeftOrder.indexOf(a.columnId) - pinnedLeftOrder.indexOf(b.columnId)
|
|
3993
|
+
);
|
|
3994
|
+
rightPinned.sort(
|
|
3995
|
+
(a, b) => pinnedRightOrder.indexOf(a.columnId) - pinnedRightOrder.indexOf(b.columnId)
|
|
3996
|
+
);
|
|
3997
|
+
return [...leftPinned, ...groups, ...rightPinned];
|
|
3998
|
+
}, [columnGroups, collapsedGroups, columns, pinnedColumns]);
|
|
3913
3999
|
return /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("div", { className: cn("flex flex-col h-full bg-white", className), children: [
|
|
3914
4000
|
showToolbar && /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
|
|
3915
4001
|
SpreadsheetToolbar,
|
|
@@ -3949,7 +4035,7 @@ function Spreadsheet({
|
|
|
3949
4035
|
},
|
|
3950
4036
|
children: /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("table", { className: "w-full border-separate border-spacing-0 text-xs select-none", children: [
|
|
3951
4037
|
/* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("thead", { children: [
|
|
3952
|
-
columnGroups && /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("tr", { children: [
|
|
4038
|
+
columnGroups && groupHeaderItems && /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("tr", { children: [
|
|
3953
4039
|
/* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
|
|
3954
4040
|
RowIndexColumnHeader,
|
|
3955
4041
|
{
|
|
@@ -3962,16 +4048,33 @@ function Spreadsheet({
|
|
|
3962
4048
|
compactMode: effectiveCompactMode
|
|
3963
4049
|
}
|
|
3964
4050
|
),
|
|
3965
|
-
|
|
3966
|
-
|
|
3967
|
-
|
|
3968
|
-
|
|
3969
|
-
|
|
3970
|
-
|
|
3971
|
-
|
|
3972
|
-
|
|
3973
|
-
|
|
3974
|
-
|
|
4051
|
+
groupHeaderItems.map((item) => {
|
|
4052
|
+
if (item.type === "pinned-column") {
|
|
4053
|
+
const col = columns.find(
|
|
4054
|
+
(c) => c.id === item.columnId
|
|
4055
|
+
);
|
|
4056
|
+
const isPinnedLeft = item.pinSide === "left";
|
|
4057
|
+
return /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
|
|
4058
|
+
"th",
|
|
4059
|
+
{
|
|
4060
|
+
className: cn(
|
|
4061
|
+
"border border-gray-200 px-2 py-1.5 text-center font-bold text-gray-700",
|
|
4062
|
+
"z-30"
|
|
4063
|
+
),
|
|
4064
|
+
style: {
|
|
4065
|
+
backgroundColor: item.headerColor || "rgb(243 244 246)",
|
|
4066
|
+
position: "sticky",
|
|
4067
|
+
left: isPinnedLeft ? `${getColumnLeftOffset(item.columnId)}px` : void 0,
|
|
4068
|
+
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
|
+
}
|
|
4073
|
+
},
|
|
4074
|
+
`pinned-group-${item.columnId}`
|
|
4075
|
+
);
|
|
4076
|
+
}
|
|
4077
|
+
const { group, colSpan, isCollapsed } = item;
|
|
3975
4078
|
return /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
|
|
3976
4079
|
"th",
|
|
3977
4080
|
{
|