@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.mjs CHANGED
@@ -361,6 +361,11 @@ var SpreadsheetCell = ({
361
361
  style: {
362
362
  backgroundColor: isInSelection ? "rgb(239 246 255)" : getBackgroundColor(),
363
363
  minWidth: column.minWidth || column.width,
364
+ // Pinned columns need fixed width so sticky offset calculations are accurate
365
+ ...isPinned && {
366
+ width: column.minWidth || column.width,
367
+ maxWidth: column.minWidth || column.width
368
+ },
364
369
  ...positionStyles,
365
370
  ...selectionBorderStyles
366
371
  },
@@ -1202,6 +1207,11 @@ var SpreadsheetHeader = ({
1202
1207
  backgroundColor: highlightColor || "rgb(243 244 246)",
1203
1208
  // gray-100
1204
1209
  minWidth: column.minWidth || column.width,
1210
+ // Pinned columns need fixed width so sticky offset calculations are accurate
1211
+ ...isPinned && {
1212
+ width: column.minWidth || column.width,
1213
+ maxWidth: column.minWidth || column.width
1214
+ },
1205
1215
  top: 0,
1206
1216
  // For sticky header
1207
1217
  ...positionStyles
@@ -3839,11 +3849,13 @@ function Spreadsheet({
3839
3849
  column: col
3840
3850
  }));
3841
3851
  }
3842
- const items = [];
3852
+ const leftPinnedItems = [];
3853
+ const middleItems = [];
3854
+ const rightPinnedItems = [];
3843
3855
  for (const group of columnGroups) {
3844
3856
  const isCollapsed = collapsedGroups.has(group.id);
3845
3857
  if (isCollapsed) {
3846
- items.push({
3858
+ middleItems.push({
3847
3859
  type: "collapsed-placeholder",
3848
3860
  groupId: group.id,
3849
3861
  headerColor: group.headerColor
@@ -3855,7 +3867,14 @@ function Spreadsheet({
3855
3867
  return true;
3856
3868
  });
3857
3869
  for (const col of groupVisibleCols) {
3858
- items.push({ type: "column", column: col });
3870
+ const pinSide = pinnedColumns.get(col.id);
3871
+ if (pinSide === "left") {
3872
+ leftPinnedItems.push({ type: "column", column: col });
3873
+ } else if (pinSide === "right") {
3874
+ rightPinnedItems.push({ type: "column", column: col });
3875
+ } else {
3876
+ middleItems.push({ type: "column", column: col });
3877
+ }
3859
3878
  }
3860
3879
  }
3861
3880
  const allGroupedIds = new Set(
@@ -3863,11 +3882,78 @@ function Spreadsheet({
3863
3882
  );
3864
3883
  for (const col of visibleColumns) {
3865
3884
  if (!allGroupedIds.has(col.id)) {
3866
- items.push({ type: "column", column: col });
3885
+ const pinSide = pinnedColumns.get(col.id);
3886
+ if (pinSide === "left") {
3887
+ leftPinnedItems.push({ type: "column", column: col });
3888
+ } else if (pinSide === "right") {
3889
+ rightPinnedItems.push({ type: "column", column: col });
3890
+ } else {
3891
+ middleItems.push({ type: "column", column: col });
3892
+ }
3867
3893
  }
3868
3894
  }
3869
- return items;
3895
+ const pinnedLeftOrder = Array.from(pinnedColumns.entries()).filter(([id, side]) => side === "left" && id !== ROW_INDEX_COLUMN_ID).map(([id]) => id);
3896
+ const pinnedRightOrder = Array.from(pinnedColumns.entries()).filter(([, side]) => side === "right").map(([id]) => id);
3897
+ leftPinnedItems.sort(
3898
+ (a, b) => pinnedLeftOrder.indexOf(a.column.id) - pinnedLeftOrder.indexOf(b.column.id)
3899
+ );
3900
+ rightPinnedItems.sort(
3901
+ (a, b) => pinnedRightOrder.indexOf(a.column.id) - pinnedRightOrder.indexOf(b.column.id)
3902
+ );
3903
+ return [...leftPinnedItems, ...middleItems, ...rightPinnedItems];
3870
3904
  }, [columnGroups, collapsedGroups, columns, pinnedColumns, visibleColumns]);
3905
+ const groupHeaderItems = useMemo5(() => {
3906
+ if (!columnGroups || columnGroups.length === 0) return null;
3907
+ const leftPinned = [];
3908
+ const groups = [];
3909
+ const rightPinned = [];
3910
+ for (const group of columnGroups) {
3911
+ const isCollapsed = collapsedGroups.has(group.id);
3912
+ const groupColumns = (columns || []).filter((c) => group.columns.includes(c.id));
3913
+ const visibleGroupColumns = isCollapsed ? groupColumns.filter((c) => pinnedColumns.has(c.id)) : groupColumns;
3914
+ let movedLeftCount = 0;
3915
+ let movedRightCount = 0;
3916
+ for (const col of visibleGroupColumns) {
3917
+ const pinSide = pinnedColumns.get(col.id);
3918
+ if (pinSide === "left") {
3919
+ movedLeftCount++;
3920
+ leftPinned.push({
3921
+ type: "pinned-column",
3922
+ columnId: col.id,
3923
+ headerColor: group.headerColor,
3924
+ pinSide: "left"
3925
+ });
3926
+ } else if (pinSide === "right") {
3927
+ movedRightCount++;
3928
+ rightPinned.push({
3929
+ type: "pinned-column",
3930
+ columnId: col.id,
3931
+ headerColor: group.headerColor,
3932
+ pinSide: "right"
3933
+ });
3934
+ }
3935
+ }
3936
+ const remainingCols = visibleGroupColumns.length - movedLeftCount - movedRightCount;
3937
+ const colSpan = remainingCols + (isCollapsed ? 1 : 0);
3938
+ if (colSpan > 0) {
3939
+ groups.push({
3940
+ type: "group",
3941
+ group,
3942
+ colSpan,
3943
+ isCollapsed
3944
+ });
3945
+ }
3946
+ }
3947
+ const pinnedLeftOrder = Array.from(pinnedColumns.entries()).filter(([id, side]) => side === "left" && id !== ROW_INDEX_COLUMN_ID).map(([id]) => id);
3948
+ const pinnedRightOrder = Array.from(pinnedColumns.entries()).filter(([, side]) => side === "right").map(([id]) => id);
3949
+ leftPinned.sort(
3950
+ (a, b) => pinnedLeftOrder.indexOf(a.columnId) - pinnedLeftOrder.indexOf(b.columnId)
3951
+ );
3952
+ rightPinned.sort(
3953
+ (a, b) => pinnedRightOrder.indexOf(a.columnId) - pinnedRightOrder.indexOf(b.columnId)
3954
+ );
3955
+ return [...leftPinned, ...groups, ...rightPinned];
3956
+ }, [columnGroups, collapsedGroups, columns, pinnedColumns]);
3871
3957
  return /* @__PURE__ */ jsxs12("div", { className: cn("flex flex-col h-full bg-white", className), children: [
3872
3958
  showToolbar && /* @__PURE__ */ jsx12(
3873
3959
  SpreadsheetToolbar,
@@ -3907,7 +3993,7 @@ function Spreadsheet({
3907
3993
  },
3908
3994
  children: /* @__PURE__ */ jsxs12("table", { className: "w-full border-separate border-spacing-0 text-xs select-none", children: [
3909
3995
  /* @__PURE__ */ jsxs12("thead", { children: [
3910
- columnGroups && /* @__PURE__ */ jsxs12("tr", { children: [
3996
+ columnGroups && groupHeaderItems && /* @__PURE__ */ jsxs12("tr", { children: [
3911
3997
  /* @__PURE__ */ jsx12(
3912
3998
  RowIndexColumnHeader,
3913
3999
  {
@@ -3920,16 +4006,33 @@ function Spreadsheet({
3920
4006
  compactMode: effectiveCompactMode
3921
4007
  }
3922
4008
  ),
3923
- columnGroups.map((group) => {
3924
- const groupColumns = (columns || []).filter(
3925
- (c) => group.columns.includes(c.id)
3926
- );
3927
- const isCollapsed = collapsedGroups.has(group.id);
3928
- const visibleGroupColumns = isCollapsed ? groupColumns.filter((c) => pinnedColumns.has(c.id)) : groupColumns;
3929
- const colSpan = Math.max(
3930
- 1,
3931
- visibleGroupColumns.length + (isCollapsed ? 1 : 0)
3932
- );
4009
+ groupHeaderItems.map((item) => {
4010
+ if (item.type === "pinned-column") {
4011
+ const col = columns.find(
4012
+ (c) => c.id === item.columnId
4013
+ );
4014
+ const isPinnedLeft = item.pinSide === "left";
4015
+ return /* @__PURE__ */ jsx12(
4016
+ "th",
4017
+ {
4018
+ className: cn(
4019
+ "border border-gray-200 px-2 py-1.5 text-center font-bold text-gray-700",
4020
+ "z-30"
4021
+ ),
4022
+ style: {
4023
+ backgroundColor: item.headerColor || "rgb(243 244 246)",
4024
+ position: "sticky",
4025
+ left: isPinnedLeft ? `${getColumnLeftOffset(item.columnId)}px` : void 0,
4026
+ right: !isPinnedLeft ? `${getColumnRightOffset(item.columnId)}px` : void 0,
4027
+ minWidth: col?.minWidth || col?.width,
4028
+ width: col?.minWidth || col?.width,
4029
+ maxWidth: col?.minWidth || col?.width
4030
+ }
4031
+ },
4032
+ `pinned-group-${item.columnId}`
4033
+ );
4034
+ }
4035
+ const { group, colSpan, isCollapsed } = item;
3933
4036
  return /* @__PURE__ */ jsx12(
3934
4037
  "th",
3935
4038
  {