@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.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
- transform: `scale(${zoom / 100})`,
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
- columnGroups.map((group) => {
3890
- const groupColumns = (columns || []).filter(
3891
- (c) => group.columns.includes(c.id)
3892
- );
3893
- const isCollapsed = collapsedGroups.has(group.id);
3894
- const visibleGroupColumns = isCollapsed ? groupColumns.filter((c) => pinnedColumns.has(c.id)) : groupColumns;
3895
- const colSpan = Math.max(
3896
- 1,
3897
- visibleGroupColumns.length + (isCollapsed ? 1 : 0)
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
- visibleColumns.map((column) => {
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: visibleColumns.length + 1,
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: visibleColumns.length + 1,
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
- visibleColumns.map((column) => {
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(column.id),
4315
+ rightOffset: getColumnRightOffset(
4316
+ column.id
4317
+ ),
4163
4318
  onClick: (e) => handleCellClick(rowId, column.id, e),
4164
4319
  onConfirm: handleConfirmEdit,
4165
4320
  onCancel: handleCancelEdit,