@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.mjs
CHANGED
|
@@ -3832,6 +3832,118 @@ function Spreadsheet({
|
|
|
3832
3832
|
const handleRowIndexHighlightClick = useCallback7(() => {
|
|
3833
3833
|
setHighlightPickerColumn(ROW_INDEX_COLUMN_ID);
|
|
3834
3834
|
}, [setHighlightPickerColumn]);
|
|
3835
|
+
const columnRenderItems = useMemo5(() => {
|
|
3836
|
+
if (!columnGroups || columnGroups.length === 0) {
|
|
3837
|
+
return visibleColumns.map((col) => ({
|
|
3838
|
+
type: "column",
|
|
3839
|
+
column: col
|
|
3840
|
+
}));
|
|
3841
|
+
}
|
|
3842
|
+
const leftPinnedItems = [];
|
|
3843
|
+
const middleItems = [];
|
|
3844
|
+
const rightPinnedItems = [];
|
|
3845
|
+
for (const group of columnGroups) {
|
|
3846
|
+
const isCollapsed = collapsedGroups.has(group.id);
|
|
3847
|
+
if (isCollapsed) {
|
|
3848
|
+
middleItems.push({
|
|
3849
|
+
type: "collapsed-placeholder",
|
|
3850
|
+
groupId: group.id,
|
|
3851
|
+
headerColor: group.headerColor
|
|
3852
|
+
});
|
|
3853
|
+
}
|
|
3854
|
+
const groupVisibleCols = (columns || []).filter((c) => {
|
|
3855
|
+
if (!group.columns.includes(c.id)) return false;
|
|
3856
|
+
if (isCollapsed) return pinnedColumns.has(c.id);
|
|
3857
|
+
return true;
|
|
3858
|
+
});
|
|
3859
|
+
for (const col of groupVisibleCols) {
|
|
3860
|
+
const pinSide = pinnedColumns.get(col.id);
|
|
3861
|
+
if (pinSide === "left") {
|
|
3862
|
+
leftPinnedItems.push({ type: "column", column: col });
|
|
3863
|
+
} else if (pinSide === "right") {
|
|
3864
|
+
rightPinnedItems.push({ type: "column", column: col });
|
|
3865
|
+
} else {
|
|
3866
|
+
middleItems.push({ type: "column", column: col });
|
|
3867
|
+
}
|
|
3868
|
+
}
|
|
3869
|
+
}
|
|
3870
|
+
const allGroupedIds = new Set(
|
|
3871
|
+
columnGroups.flatMap((g) => g.columns)
|
|
3872
|
+
);
|
|
3873
|
+
for (const col of visibleColumns) {
|
|
3874
|
+
if (!allGroupedIds.has(col.id)) {
|
|
3875
|
+
const pinSide = pinnedColumns.get(col.id);
|
|
3876
|
+
if (pinSide === "left") {
|
|
3877
|
+
leftPinnedItems.push({ type: "column", column: col });
|
|
3878
|
+
} else if (pinSide === "right") {
|
|
3879
|
+
rightPinnedItems.push({ type: "column", column: col });
|
|
3880
|
+
} else {
|
|
3881
|
+
middleItems.push({ type: "column", column: col });
|
|
3882
|
+
}
|
|
3883
|
+
}
|
|
3884
|
+
}
|
|
3885
|
+
const pinnedLeftOrder = Array.from(pinnedColumns.entries()).filter(([id, side]) => side === "left" && id !== ROW_INDEX_COLUMN_ID).map(([id]) => id);
|
|
3886
|
+
const pinnedRightOrder = Array.from(pinnedColumns.entries()).filter(([, side]) => side === "right").map(([id]) => id);
|
|
3887
|
+
leftPinnedItems.sort(
|
|
3888
|
+
(a, b) => pinnedLeftOrder.indexOf(a.column.id) - pinnedLeftOrder.indexOf(b.column.id)
|
|
3889
|
+
);
|
|
3890
|
+
rightPinnedItems.sort(
|
|
3891
|
+
(a, b) => pinnedRightOrder.indexOf(a.column.id) - pinnedRightOrder.indexOf(b.column.id)
|
|
3892
|
+
);
|
|
3893
|
+
return [...leftPinnedItems, ...middleItems, ...rightPinnedItems];
|
|
3894
|
+
}, [columnGroups, collapsedGroups, columns, pinnedColumns, visibleColumns]);
|
|
3895
|
+
const groupHeaderItems = useMemo5(() => {
|
|
3896
|
+
if (!columnGroups || columnGroups.length === 0) return null;
|
|
3897
|
+
const leftPinned = [];
|
|
3898
|
+
const groups = [];
|
|
3899
|
+
const rightPinned = [];
|
|
3900
|
+
for (const group of columnGroups) {
|
|
3901
|
+
const isCollapsed = collapsedGroups.has(group.id);
|
|
3902
|
+
const groupColumns = (columns || []).filter((c) => group.columns.includes(c.id));
|
|
3903
|
+
const visibleGroupColumns = isCollapsed ? groupColumns.filter((c) => pinnedColumns.has(c.id)) : groupColumns;
|
|
3904
|
+
let movedLeftCount = 0;
|
|
3905
|
+
let movedRightCount = 0;
|
|
3906
|
+
for (const col of visibleGroupColumns) {
|
|
3907
|
+
const pinSide = pinnedColumns.get(col.id);
|
|
3908
|
+
if (pinSide === "left") {
|
|
3909
|
+
movedLeftCount++;
|
|
3910
|
+
leftPinned.push({
|
|
3911
|
+
type: "pinned-column",
|
|
3912
|
+
columnId: col.id,
|
|
3913
|
+
headerColor: group.headerColor,
|
|
3914
|
+
pinSide: "left"
|
|
3915
|
+
});
|
|
3916
|
+
} else if (pinSide === "right") {
|
|
3917
|
+
movedRightCount++;
|
|
3918
|
+
rightPinned.push({
|
|
3919
|
+
type: "pinned-column",
|
|
3920
|
+
columnId: col.id,
|
|
3921
|
+
headerColor: group.headerColor,
|
|
3922
|
+
pinSide: "right"
|
|
3923
|
+
});
|
|
3924
|
+
}
|
|
3925
|
+
}
|
|
3926
|
+
const remainingCols = visibleGroupColumns.length - movedLeftCount - movedRightCount;
|
|
3927
|
+
const colSpan = remainingCols + (isCollapsed ? 1 : 0);
|
|
3928
|
+
if (colSpan > 0) {
|
|
3929
|
+
groups.push({
|
|
3930
|
+
type: "group",
|
|
3931
|
+
group,
|
|
3932
|
+
colSpan,
|
|
3933
|
+
isCollapsed
|
|
3934
|
+
});
|
|
3935
|
+
}
|
|
3936
|
+
}
|
|
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
|
+
leftPinned.sort(
|
|
3940
|
+
(a, b) => pinnedLeftOrder.indexOf(a.columnId) - pinnedLeftOrder.indexOf(b.columnId)
|
|
3941
|
+
);
|
|
3942
|
+
rightPinned.sort(
|
|
3943
|
+
(a, b) => pinnedRightOrder.indexOf(a.columnId) - pinnedRightOrder.indexOf(b.columnId)
|
|
3944
|
+
);
|
|
3945
|
+
return [...leftPinned, ...groups, ...rightPinned];
|
|
3946
|
+
}, [columnGroups, collapsedGroups, columns, pinnedColumns]);
|
|
3835
3947
|
return /* @__PURE__ */ jsxs12("div", { className: cn("flex flex-col h-full bg-white", className), children: [
|
|
3836
3948
|
showToolbar && /* @__PURE__ */ jsx12(
|
|
3837
3949
|
SpreadsheetToolbar,
|
|
@@ -3867,13 +3979,11 @@ function Spreadsheet({
|
|
|
3867
3979
|
"div",
|
|
3868
3980
|
{
|
|
3869
3981
|
style: {
|
|
3870
|
-
|
|
3871
|
-
transformOrigin: "top left",
|
|
3872
|
-
width: `${100 / (zoom / 100)}%`
|
|
3982
|
+
zoom: zoom / 100
|
|
3873
3983
|
},
|
|
3874
3984
|
children: /* @__PURE__ */ jsxs12("table", { className: "w-full border-separate border-spacing-0 text-xs select-none", children: [
|
|
3875
3985
|
/* @__PURE__ */ jsxs12("thead", { children: [
|
|
3876
|
-
columnGroups && /* @__PURE__ */ jsxs12("tr", { children: [
|
|
3986
|
+
columnGroups && groupHeaderItems && /* @__PURE__ */ jsxs12("tr", { children: [
|
|
3877
3987
|
/* @__PURE__ */ jsx12(
|
|
3878
3988
|
RowIndexColumnHeader,
|
|
3879
3989
|
{
|
|
@@ -3886,16 +3996,31 @@ function Spreadsheet({
|
|
|
3886
3996
|
compactMode: effectiveCompactMode
|
|
3887
3997
|
}
|
|
3888
3998
|
),
|
|
3889
|
-
|
|
3890
|
-
|
|
3891
|
-
|
|
3892
|
-
|
|
3893
|
-
|
|
3894
|
-
|
|
3895
|
-
|
|
3896
|
-
|
|
3897
|
-
|
|
3898
|
-
|
|
3999
|
+
groupHeaderItems.map((item) => {
|
|
4000
|
+
if (item.type === "pinned-column") {
|
|
4001
|
+
const col = columns.find(
|
|
4002
|
+
(c) => c.id === item.columnId
|
|
4003
|
+
);
|
|
4004
|
+
const isPinnedLeft = item.pinSide === "left";
|
|
4005
|
+
return /* @__PURE__ */ jsx12(
|
|
4006
|
+
"th",
|
|
4007
|
+
{
|
|
4008
|
+
className: cn(
|
|
4009
|
+
"border border-gray-200 px-2 py-1.5 text-center font-bold text-gray-700",
|
|
4010
|
+
"z-30"
|
|
4011
|
+
),
|
|
4012
|
+
style: {
|
|
4013
|
+
backgroundColor: item.headerColor || "rgb(243 244 246)",
|
|
4014
|
+
position: "sticky",
|
|
4015
|
+
left: isPinnedLeft ? `${getColumnLeftOffset(item.columnId)}px` : void 0,
|
|
4016
|
+
right: !isPinnedLeft ? `${getColumnRightOffset(item.columnId)}px` : void 0,
|
|
4017
|
+
minWidth: col?.minWidth || col?.width
|
|
4018
|
+
}
|
|
4019
|
+
},
|
|
4020
|
+
`pinned-group-${item.columnId}`
|
|
4021
|
+
);
|
|
4022
|
+
}
|
|
4023
|
+
const { group, colSpan, isCollapsed } = item;
|
|
3899
4024
|
return /* @__PURE__ */ jsx12(
|
|
3900
4025
|
"th",
|
|
3901
4026
|
{
|
|
@@ -3930,7 +4055,22 @@ function Spreadsheet({
|
|
|
3930
4055
|
compactMode: effectiveCompactMode
|
|
3931
4056
|
}
|
|
3932
4057
|
),
|
|
3933
|
-
|
|
4058
|
+
columnRenderItems.map((item) => {
|
|
4059
|
+
if (item.type === "collapsed-placeholder") {
|
|
4060
|
+
return /* @__PURE__ */ jsx12(
|
|
4061
|
+
"th",
|
|
4062
|
+
{
|
|
4063
|
+
className: "border border-gray-200 px-2 py-1 text-center text-gray-400",
|
|
4064
|
+
style: {
|
|
4065
|
+
backgroundColor: item.headerColor || "rgb(243 244 246)",
|
|
4066
|
+
minWidth: "30px"
|
|
4067
|
+
},
|
|
4068
|
+
children: "..."
|
|
4069
|
+
},
|
|
4070
|
+
`${item.groupId}-placeholder`
|
|
4071
|
+
);
|
|
4072
|
+
}
|
|
4073
|
+
const column = item.column;
|
|
3934
4074
|
const isPinnedLeft = isColumnPinned(column.id) && getColumnPinSide(column.id) === "left";
|
|
3935
4075
|
const isPinnedRight = isColumnPinned(column.id) && getColumnPinSide(column.id) === "right";
|
|
3936
4076
|
return /* @__PURE__ */ jsx12(
|
|
@@ -3969,7 +4109,7 @@ function Spreadsheet({
|
|
|
3969
4109
|
/* @__PURE__ */ jsx12("tbody", { children: isLoading ? /* @__PURE__ */ jsx12("tr", { children: /* @__PURE__ */ jsx12(
|
|
3970
4110
|
"td",
|
|
3971
4111
|
{
|
|
3972
|
-
colSpan:
|
|
4112
|
+
colSpan: columnRenderItems.length + 1,
|
|
3973
4113
|
className: "text-center py-8 text-gray-500",
|
|
3974
4114
|
children: /* @__PURE__ */ jsxs12("div", { className: "flex items-center justify-center gap-2", children: [
|
|
3975
4115
|
/* @__PURE__ */ jsx12("div", { className: "w-4 h-4 border-2 border-blue-600 border-t-transparent rounded-full animate-spin" }),
|
|
@@ -3979,7 +4119,7 @@ function Spreadsheet({
|
|
|
3979
4119
|
) }) : paginatedData.length === 0 ? /* @__PURE__ */ jsx12("tr", { children: /* @__PURE__ */ jsx12(
|
|
3980
4120
|
"td",
|
|
3981
4121
|
{
|
|
3982
|
-
colSpan:
|
|
4122
|
+
colSpan: columnRenderItems.length + 1,
|
|
3983
4123
|
className: "text-center py-8 text-gray-500",
|
|
3984
4124
|
children: emptyMessage
|
|
3985
4125
|
}
|
|
@@ -4124,7 +4264,20 @@ function Spreadsheet({
|
|
|
4124
4264
|
] })
|
|
4125
4265
|
}
|
|
4126
4266
|
),
|
|
4127
|
-
|
|
4267
|
+
columnRenderItems.map((item) => {
|
|
4268
|
+
if (item.type === "collapsed-placeholder") {
|
|
4269
|
+
return /* @__PURE__ */ jsx12(
|
|
4270
|
+
"td",
|
|
4271
|
+
{
|
|
4272
|
+
className: "border border-gray-200 px-2 py-1 text-center text-gray-300",
|
|
4273
|
+
style: {
|
|
4274
|
+
backgroundColor: item.headerColor || "rgb(243 244 246)"
|
|
4275
|
+
}
|
|
4276
|
+
},
|
|
4277
|
+
`${item.groupId}-placeholder`
|
|
4278
|
+
);
|
|
4279
|
+
}
|
|
4280
|
+
const column = item.column;
|
|
4128
4281
|
const value = column.getValue ? column.getValue(row) : row[column.id];
|
|
4129
4282
|
const isEditing = editingCell?.rowId === rowId && editingCell?.columnId === column.id;
|
|
4130
4283
|
const isFocused = focusedCell?.rowId === rowId && focusedCell?.columnId === column.id;
|
|
@@ -4159,7 +4312,9 @@ function Spreadsheet({
|
|
|
4159
4312
|
isPinned: isColPinned,
|
|
4160
4313
|
pinSide: colPinSide,
|
|
4161
4314
|
leftOffset: getColumnLeftOffset(column.id),
|
|
4162
|
-
rightOffset: getColumnRightOffset(
|
|
4315
|
+
rightOffset: getColumnRightOffset(
|
|
4316
|
+
column.id
|
|
4317
|
+
),
|
|
4163
4318
|
onClick: (e) => handleCellClick(rowId, column.id, e),
|
|
4164
4319
|
onConfirm: handleConfirmEdit,
|
|
4165
4320
|
onCancel: handleCancelEdit,
|