@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 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 items = [];
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
- items.push({
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
- items.push({ type: "column", column: col });
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
- items.push({ type: "column", column: col });
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
- return items;
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
- columnGroups.map((group) => {
3966
- const groupColumns = (columns || []).filter(
3967
- (c) => group.columns.includes(c.id)
3968
- );
3969
- const isCollapsed = collapsedGroups.has(group.id);
3970
- const visibleGroupColumns = isCollapsed ? groupColumns.filter((c) => pinnedColumns.has(c.id)) : groupColumns;
3971
- const colSpan = Math.max(
3972
- 1,
3973
- visibleGroupColumns.length + (isCollapsed ? 1 : 0)
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
  {