@xcelsior/ui-spreadsheets 1.1.9 → 1.1.11
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 +174 -19
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +174 -19
- package/dist/index.mjs.map +1 -1
- package/dist/styles/globals.css +3 -0
- package/dist/styles/globals.css.map +1 -1
- package/package.json +1 -1
- package/src/components/Spreadsheet.stories.tsx +223 -17
- package/src/components/Spreadsheet.tsx +238 -23
package/dist/index.js
CHANGED
|
@@ -3874,6 +3874,118 @@ function Spreadsheet({
|
|
|
3874
3874
|
const handleRowIndexHighlightClick = (0, import_react17.useCallback)(() => {
|
|
3875
3875
|
setHighlightPickerColumn(ROW_INDEX_COLUMN_ID);
|
|
3876
3876
|
}, [setHighlightPickerColumn]);
|
|
3877
|
+
const columnRenderItems = (0, import_react17.useMemo)(() => {
|
|
3878
|
+
if (!columnGroups || columnGroups.length === 0) {
|
|
3879
|
+
return visibleColumns.map((col) => ({
|
|
3880
|
+
type: "column",
|
|
3881
|
+
column: col
|
|
3882
|
+
}));
|
|
3883
|
+
}
|
|
3884
|
+
const leftPinnedItems = [];
|
|
3885
|
+
const middleItems = [];
|
|
3886
|
+
const rightPinnedItems = [];
|
|
3887
|
+
for (const group of columnGroups) {
|
|
3888
|
+
const isCollapsed = collapsedGroups.has(group.id);
|
|
3889
|
+
if (isCollapsed) {
|
|
3890
|
+
middleItems.push({
|
|
3891
|
+
type: "collapsed-placeholder",
|
|
3892
|
+
groupId: group.id,
|
|
3893
|
+
headerColor: group.headerColor
|
|
3894
|
+
});
|
|
3895
|
+
}
|
|
3896
|
+
const groupVisibleCols = (columns || []).filter((c) => {
|
|
3897
|
+
if (!group.columns.includes(c.id)) return false;
|
|
3898
|
+
if (isCollapsed) return pinnedColumns.has(c.id);
|
|
3899
|
+
return true;
|
|
3900
|
+
});
|
|
3901
|
+
for (const col of groupVisibleCols) {
|
|
3902
|
+
const pinSide = pinnedColumns.get(col.id);
|
|
3903
|
+
if (pinSide === "left") {
|
|
3904
|
+
leftPinnedItems.push({ type: "column", column: col });
|
|
3905
|
+
} else if (pinSide === "right") {
|
|
3906
|
+
rightPinnedItems.push({ type: "column", column: col });
|
|
3907
|
+
} else {
|
|
3908
|
+
middleItems.push({ type: "column", column: col });
|
|
3909
|
+
}
|
|
3910
|
+
}
|
|
3911
|
+
}
|
|
3912
|
+
const allGroupedIds = new Set(
|
|
3913
|
+
columnGroups.flatMap((g) => g.columns)
|
|
3914
|
+
);
|
|
3915
|
+
for (const col of visibleColumns) {
|
|
3916
|
+
if (!allGroupedIds.has(col.id)) {
|
|
3917
|
+
const pinSide = pinnedColumns.get(col.id);
|
|
3918
|
+
if (pinSide === "left") {
|
|
3919
|
+
leftPinnedItems.push({ type: "column", column: col });
|
|
3920
|
+
} else if (pinSide === "right") {
|
|
3921
|
+
rightPinnedItems.push({ type: "column", column: col });
|
|
3922
|
+
} else {
|
|
3923
|
+
middleItems.push({ type: "column", column: col });
|
|
3924
|
+
}
|
|
3925
|
+
}
|
|
3926
|
+
}
|
|
3927
|
+
const pinnedLeftOrder = Array.from(pinnedColumns.entries()).filter(([id, side]) => side === "left" && id !== ROW_INDEX_COLUMN_ID).map(([id]) => id);
|
|
3928
|
+
const pinnedRightOrder = Array.from(pinnedColumns.entries()).filter(([, side]) => side === "right").map(([id]) => id);
|
|
3929
|
+
leftPinnedItems.sort(
|
|
3930
|
+
(a, b) => pinnedLeftOrder.indexOf(a.column.id) - pinnedLeftOrder.indexOf(b.column.id)
|
|
3931
|
+
);
|
|
3932
|
+
rightPinnedItems.sort(
|
|
3933
|
+
(a, b) => pinnedRightOrder.indexOf(a.column.id) - pinnedRightOrder.indexOf(b.column.id)
|
|
3934
|
+
);
|
|
3935
|
+
return [...leftPinnedItems, ...middleItems, ...rightPinnedItems];
|
|
3936
|
+
}, [columnGroups, collapsedGroups, columns, pinnedColumns, visibleColumns]);
|
|
3937
|
+
const groupHeaderItems = (0, import_react17.useMemo)(() => {
|
|
3938
|
+
if (!columnGroups || columnGroups.length === 0) return null;
|
|
3939
|
+
const leftPinned = [];
|
|
3940
|
+
const groups = [];
|
|
3941
|
+
const rightPinned = [];
|
|
3942
|
+
for (const group of columnGroups) {
|
|
3943
|
+
const isCollapsed = collapsedGroups.has(group.id);
|
|
3944
|
+
const groupColumns = (columns || []).filter((c) => group.columns.includes(c.id));
|
|
3945
|
+
const visibleGroupColumns = isCollapsed ? groupColumns.filter((c) => pinnedColumns.has(c.id)) : groupColumns;
|
|
3946
|
+
let movedLeftCount = 0;
|
|
3947
|
+
let movedRightCount = 0;
|
|
3948
|
+
for (const col of visibleGroupColumns) {
|
|
3949
|
+
const pinSide = pinnedColumns.get(col.id);
|
|
3950
|
+
if (pinSide === "left") {
|
|
3951
|
+
movedLeftCount++;
|
|
3952
|
+
leftPinned.push({
|
|
3953
|
+
type: "pinned-column",
|
|
3954
|
+
columnId: col.id,
|
|
3955
|
+
headerColor: group.headerColor,
|
|
3956
|
+
pinSide: "left"
|
|
3957
|
+
});
|
|
3958
|
+
} else if (pinSide === "right") {
|
|
3959
|
+
movedRightCount++;
|
|
3960
|
+
rightPinned.push({
|
|
3961
|
+
type: "pinned-column",
|
|
3962
|
+
columnId: col.id,
|
|
3963
|
+
headerColor: group.headerColor,
|
|
3964
|
+
pinSide: "right"
|
|
3965
|
+
});
|
|
3966
|
+
}
|
|
3967
|
+
}
|
|
3968
|
+
const remainingCols = visibleGroupColumns.length - movedLeftCount - movedRightCount;
|
|
3969
|
+
const colSpan = remainingCols + (isCollapsed ? 1 : 0);
|
|
3970
|
+
if (colSpan > 0) {
|
|
3971
|
+
groups.push({
|
|
3972
|
+
type: "group",
|
|
3973
|
+
group,
|
|
3974
|
+
colSpan,
|
|
3975
|
+
isCollapsed
|
|
3976
|
+
});
|
|
3977
|
+
}
|
|
3978
|
+
}
|
|
3979
|
+
const pinnedLeftOrder = Array.from(pinnedColumns.entries()).filter(([id, side]) => side === "left" && id !== ROW_INDEX_COLUMN_ID).map(([id]) => id);
|
|
3980
|
+
const pinnedRightOrder = Array.from(pinnedColumns.entries()).filter(([, side]) => side === "right").map(([id]) => id);
|
|
3981
|
+
leftPinned.sort(
|
|
3982
|
+
(a, b) => pinnedLeftOrder.indexOf(a.columnId) - pinnedLeftOrder.indexOf(b.columnId)
|
|
3983
|
+
);
|
|
3984
|
+
rightPinned.sort(
|
|
3985
|
+
(a, b) => pinnedRightOrder.indexOf(a.columnId) - pinnedRightOrder.indexOf(b.columnId)
|
|
3986
|
+
);
|
|
3987
|
+
return [...leftPinned, ...groups, ...rightPinned];
|
|
3988
|
+
}, [columnGroups, collapsedGroups, columns, pinnedColumns]);
|
|
3877
3989
|
return /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("div", { className: cn("flex flex-col h-full bg-white", className), children: [
|
|
3878
3990
|
showToolbar && /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
|
|
3879
3991
|
SpreadsheetToolbar,
|
|
@@ -3909,13 +4021,11 @@ function Spreadsheet({
|
|
|
3909
4021
|
"div",
|
|
3910
4022
|
{
|
|
3911
4023
|
style: {
|
|
3912
|
-
|
|
3913
|
-
transformOrigin: "top left",
|
|
3914
|
-
width: `${100 / (zoom / 100)}%`
|
|
4024
|
+
zoom: zoom / 100
|
|
3915
4025
|
},
|
|
3916
4026
|
children: /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("table", { className: "w-full border-separate border-spacing-0 text-xs select-none", children: [
|
|
3917
4027
|
/* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("thead", { children: [
|
|
3918
|
-
columnGroups && /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("tr", { children: [
|
|
4028
|
+
columnGroups && groupHeaderItems && /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("tr", { children: [
|
|
3919
4029
|
/* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
|
|
3920
4030
|
RowIndexColumnHeader,
|
|
3921
4031
|
{
|
|
@@ -3928,16 +4038,31 @@ function Spreadsheet({
|
|
|
3928
4038
|
compactMode: effectiveCompactMode
|
|
3929
4039
|
}
|
|
3930
4040
|
),
|
|
3931
|
-
|
|
3932
|
-
|
|
3933
|
-
|
|
3934
|
-
|
|
3935
|
-
|
|
3936
|
-
|
|
3937
|
-
|
|
3938
|
-
|
|
3939
|
-
|
|
3940
|
-
|
|
4041
|
+
groupHeaderItems.map((item) => {
|
|
4042
|
+
if (item.type === "pinned-column") {
|
|
4043
|
+
const col = columns.find(
|
|
4044
|
+
(c) => c.id === item.columnId
|
|
4045
|
+
);
|
|
4046
|
+
const isPinnedLeft = item.pinSide === "left";
|
|
4047
|
+
return /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
|
|
4048
|
+
"th",
|
|
4049
|
+
{
|
|
4050
|
+
className: cn(
|
|
4051
|
+
"border border-gray-200 px-2 py-1.5 text-center font-bold text-gray-700",
|
|
4052
|
+
"z-30"
|
|
4053
|
+
),
|
|
4054
|
+
style: {
|
|
4055
|
+
backgroundColor: item.headerColor || "rgb(243 244 246)",
|
|
4056
|
+
position: "sticky",
|
|
4057
|
+
left: isPinnedLeft ? `${getColumnLeftOffset(item.columnId)}px` : void 0,
|
|
4058
|
+
right: !isPinnedLeft ? `${getColumnRightOffset(item.columnId)}px` : void 0,
|
|
4059
|
+
minWidth: col?.minWidth || col?.width
|
|
4060
|
+
}
|
|
4061
|
+
},
|
|
4062
|
+
`pinned-group-${item.columnId}`
|
|
4063
|
+
);
|
|
4064
|
+
}
|
|
4065
|
+
const { group, colSpan, isCollapsed } = item;
|
|
3941
4066
|
return /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
|
|
3942
4067
|
"th",
|
|
3943
4068
|
{
|
|
@@ -3972,7 +4097,22 @@ function Spreadsheet({
|
|
|
3972
4097
|
compactMode: effectiveCompactMode
|
|
3973
4098
|
}
|
|
3974
4099
|
),
|
|
3975
|
-
|
|
4100
|
+
columnRenderItems.map((item) => {
|
|
4101
|
+
if (item.type === "collapsed-placeholder") {
|
|
4102
|
+
return /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
|
|
4103
|
+
"th",
|
|
4104
|
+
{
|
|
4105
|
+
className: "border border-gray-200 px-2 py-1 text-center text-gray-400",
|
|
4106
|
+
style: {
|
|
4107
|
+
backgroundColor: item.headerColor || "rgb(243 244 246)",
|
|
4108
|
+
minWidth: "30px"
|
|
4109
|
+
},
|
|
4110
|
+
children: "..."
|
|
4111
|
+
},
|
|
4112
|
+
`${item.groupId}-placeholder`
|
|
4113
|
+
);
|
|
4114
|
+
}
|
|
4115
|
+
const column = item.column;
|
|
3976
4116
|
const isPinnedLeft = isColumnPinned(column.id) && getColumnPinSide(column.id) === "left";
|
|
3977
4117
|
const isPinnedRight = isColumnPinned(column.id) && getColumnPinSide(column.id) === "right";
|
|
3978
4118
|
return /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
|
|
@@ -4011,7 +4151,7 @@ function Spreadsheet({
|
|
|
4011
4151
|
/* @__PURE__ */ (0, import_jsx_runtime12.jsx)("tbody", { children: isLoading ? /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("tr", { children: /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
|
|
4012
4152
|
"td",
|
|
4013
4153
|
{
|
|
4014
|
-
colSpan:
|
|
4154
|
+
colSpan: columnRenderItems.length + 1,
|
|
4015
4155
|
className: "text-center py-8 text-gray-500",
|
|
4016
4156
|
children: /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("div", { className: "flex items-center justify-center gap-2", children: [
|
|
4017
4157
|
/* @__PURE__ */ (0, import_jsx_runtime12.jsx)("div", { className: "w-4 h-4 border-2 border-blue-600 border-t-transparent rounded-full animate-spin" }),
|
|
@@ -4021,7 +4161,7 @@ function Spreadsheet({
|
|
|
4021
4161
|
) }) : paginatedData.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("tr", { children: /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
|
|
4022
4162
|
"td",
|
|
4023
4163
|
{
|
|
4024
|
-
colSpan:
|
|
4164
|
+
colSpan: columnRenderItems.length + 1,
|
|
4025
4165
|
className: "text-center py-8 text-gray-500",
|
|
4026
4166
|
children: emptyMessage
|
|
4027
4167
|
}
|
|
@@ -4166,7 +4306,20 @@ function Spreadsheet({
|
|
|
4166
4306
|
] })
|
|
4167
4307
|
}
|
|
4168
4308
|
),
|
|
4169
|
-
|
|
4309
|
+
columnRenderItems.map((item) => {
|
|
4310
|
+
if (item.type === "collapsed-placeholder") {
|
|
4311
|
+
return /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
|
|
4312
|
+
"td",
|
|
4313
|
+
{
|
|
4314
|
+
className: "border border-gray-200 px-2 py-1 text-center text-gray-300",
|
|
4315
|
+
style: {
|
|
4316
|
+
backgroundColor: item.headerColor || "rgb(243 244 246)"
|
|
4317
|
+
}
|
|
4318
|
+
},
|
|
4319
|
+
`${item.groupId}-placeholder`
|
|
4320
|
+
);
|
|
4321
|
+
}
|
|
4322
|
+
const column = item.column;
|
|
4170
4323
|
const value = column.getValue ? column.getValue(row) : row[column.id];
|
|
4171
4324
|
const isEditing = editingCell?.rowId === rowId && editingCell?.columnId === column.id;
|
|
4172
4325
|
const isFocused = focusedCell?.rowId === rowId && focusedCell?.columnId === column.id;
|
|
@@ -4201,7 +4354,9 @@ function Spreadsheet({
|
|
|
4201
4354
|
isPinned: isColPinned,
|
|
4202
4355
|
pinSide: colPinSide,
|
|
4203
4356
|
leftOffset: getColumnLeftOffset(column.id),
|
|
4204
|
-
rightOffset: getColumnRightOffset(
|
|
4357
|
+
rightOffset: getColumnRightOffset(
|
|
4358
|
+
column.id
|
|
4359
|
+
),
|
|
4205
4360
|
onClick: (e) => handleCellClick(rowId, column.id, e),
|
|
4206
4361
|
onConfirm: handleConfirmEdit,
|
|
4207
4362
|
onCancel: handleCancelEdit,
|