@xcelsior/ui-spreadsheets 1.1.1 → 1.1.3

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
@@ -329,7 +329,7 @@ var SpreadsheetCell = ({
329
329
  onKeyDown: handleCellKeyDown,
330
330
  "data-cell-id": `${rowId}-${column.id}`,
331
331
  className: cn(
332
- "border border-gray-200 group cursor-pointer select-none",
332
+ "border border-gray-200 group cursor-pointer transition-colors select-none",
333
333
  compactMode ? "text-[10px]" : "text-xs",
334
334
  cellPadding,
335
335
  column.align === "right" && "text-right",
@@ -1080,71 +1080,56 @@ function ColumnHeaderActions({
1080
1080
  unpinnedTitle = "Pin column",
1081
1081
  className
1082
1082
  }) {
1083
- const handleClick = (e) => {
1084
- e.stopPropagation();
1085
- };
1086
- const handleKeyDown = (e) => {
1087
- e.stopPropagation();
1088
- };
1089
- return /* @__PURE__ */ jsxs4(
1090
- "button",
1091
- {
1092
- type: "button",
1093
- className: cn("flex items-center gap-0.5", className),
1094
- onClick: handleClick,
1095
- onKeyDown: handleKeyDown,
1096
- children: [
1097
- enableFiltering && onFilterClick && /* @__PURE__ */ jsx4(
1098
- "button",
1099
- {
1100
- type: "button",
1101
- onClick: (e) => {
1102
- e.stopPropagation();
1103
- onFilterClick();
1104
- },
1105
- className: cn(
1106
- "p-0.5 hover:bg-gray-200 rounded transition-opacity",
1107
- hasActiveFilter ? "text-blue-600 opacity-100" : "text-gray-400 opacity-0 group-hover:opacity-100"
1108
- ),
1109
- title: filterTitle,
1110
- children: /* @__PURE__ */ jsx4(HiFilter, { className: "h-3 w-3" })
1111
- }
1083
+ return /* @__PURE__ */ jsxs4("div", { className: cn("flex items-center gap-0.5", className), children: [
1084
+ enableFiltering && onFilterClick && /* @__PURE__ */ jsx4(
1085
+ "button",
1086
+ {
1087
+ type: "button",
1088
+ onClick: (e) => {
1089
+ e.stopPropagation();
1090
+ onFilterClick();
1091
+ },
1092
+ className: cn(
1093
+ "p-0.5 hover:bg-gray-200 rounded transition-opacity",
1094
+ hasActiveFilter ? "text-blue-600 opacity-100" : "text-gray-400 opacity-0 group-hover:opacity-100"
1112
1095
  ),
1113
- enableHighlighting && onHighlightClick && /* @__PURE__ */ jsx4(
1114
- "button",
1115
- {
1116
- type: "button",
1117
- onClick: (e) => {
1118
- e.stopPropagation();
1119
- onHighlightClick();
1120
- },
1121
- className: cn(
1122
- "p-0.5 hover:bg-gray-200 rounded transition-opacity",
1123
- hasActiveHighlight ? "text-amber-500 opacity-100" : "text-gray-400 opacity-0 group-hover:opacity-100"
1124
- ),
1125
- title: highlightTitle,
1126
- children: /* @__PURE__ */ jsx4(AiFillHighlight, { className: "h-3 w-3" })
1127
- }
1096
+ title: filterTitle,
1097
+ children: /* @__PURE__ */ jsx4(HiFilter, { className: "h-3 w-3" })
1098
+ }
1099
+ ),
1100
+ enableHighlighting && onHighlightClick && /* @__PURE__ */ jsx4(
1101
+ "button",
1102
+ {
1103
+ type: "button",
1104
+ onClick: (e) => {
1105
+ e.stopPropagation();
1106
+ onHighlightClick();
1107
+ },
1108
+ className: cn(
1109
+ "p-0.5 hover:bg-gray-200 rounded transition-opacity",
1110
+ hasActiveHighlight ? "text-amber-500 opacity-100" : "text-gray-400 opacity-0 group-hover:opacity-100"
1128
1111
  ),
1129
- enablePinning && onPinClick && /* @__PURE__ */ jsx4(
1130
- "button",
1131
- {
1132
- type: "button",
1133
- onClick: (e) => {
1134
- e.stopPropagation();
1135
- onPinClick();
1136
- },
1137
- className: cn(
1138
- "p-0.5 hover:bg-gray-200 rounded transition-opacity",
1139
- isPinned ? "text-blue-600 opacity-100" : "text-gray-400 opacity-0 group-hover:opacity-100"
1140
- ),
1141
- title: isPinned ? pinnedTitle : unpinnedTitle,
1142
- children: isPinned ? /* @__PURE__ */ jsx4(MdPushPin, { className: "h-3 w-3" }) : /* @__PURE__ */ jsx4(MdOutlinePushPin, { className: "h-3 w-3" })
1143
- }
1144
- )
1145
- ]
1146
- }
1147
- );
1112
+ title: highlightTitle,
1113
+ children: /* @__PURE__ */ jsx4(AiFillHighlight, { className: "h-3 w-3" })
1114
+ }
1115
+ ),
1116
+ enablePinning && onPinClick && /* @__PURE__ */ jsx4(
1117
+ "button",
1118
+ {
1119
+ type: "button",
1120
+ onClick: (e) => {
1121
+ e.stopPropagation();
1122
+ onPinClick();
1123
+ },
1124
+ className: cn(
1125
+ "p-0.5 hover:bg-gray-200 rounded transition-opacity",
1126
+ isPinned ? "text-blue-600 opacity-100" : "text-gray-400 opacity-0 group-hover:opacity-100"
1127
+ ),
1128
+ title: isPinned ? pinnedTitle : unpinnedTitle,
1129
+ children: isPinned ? /* @__PURE__ */ jsx4(MdPushPin, { className: "h-3 w-3" }) : /* @__PURE__ */ jsx4(MdOutlinePushPin, { className: "h-3 w-3" })
1130
+ }
1131
+ )
1132
+ ] });
1148
1133
  }
1149
1134
  ColumnHeaderActions.displayName = "ColumnHeaderActions";
1150
1135
 
@@ -1239,22 +1224,17 @@ function useSpreadsheetPinning({
1239
1224
  columns,
1240
1225
  columnGroups,
1241
1226
  showRowIndex = true,
1242
- defaultPinnedColumns = [],
1243
- defaultPinRowIndex = false
1227
+ defaultPinnedColumns = []
1244
1228
  }) {
1245
1229
  const [pinnedColumns, setPinnedColumns] = useState3(() => {
1246
1230
  const map = /* @__PURE__ */ new Map();
1247
1231
  defaultPinnedColumns.forEach((col) => {
1248
- if (col !== ROW_INDEX_COLUMN_ID) {
1249
- map.set(col, "left");
1250
- }
1232
+ map.set(col, "left");
1251
1233
  });
1252
1234
  return map;
1253
1235
  });
1254
- const [isRowIndexPinned, setIsRowIndexPinned] = useState3(
1255
- defaultPinRowIndex || defaultPinnedColumns.includes(ROW_INDEX_COLUMN_ID)
1256
- );
1257
1236
  const [collapsedGroups, setCollapsedGroups] = useState3(/* @__PURE__ */ new Set());
1237
+ const isRowIndexPinned = pinnedColumns.has(ROW_INDEX_COLUMN_ID);
1258
1238
  const handleTogglePin = useCallback((columnId) => {
1259
1239
  setPinnedColumns((prev) => {
1260
1240
  const newMap = new Map(prev);
@@ -1266,21 +1246,12 @@ function useSpreadsheetPinning({
1266
1246
  return newMap;
1267
1247
  });
1268
1248
  }, []);
1269
- const handleToggleRowIndexPin = useCallback(() => {
1270
- setIsRowIndexPinned((prev) => !prev);
1271
- }, []);
1272
1249
  const setPinnedColumnsFromIds = useCallback((columnIds) => {
1273
1250
  const map = /* @__PURE__ */ new Map();
1274
1251
  columnIds.forEach((col) => {
1275
- if (col !== ROW_INDEX_COLUMN_ID) {
1276
- map.set(col, "left");
1277
- }
1252
+ map.set(col, "left");
1278
1253
  });
1279
1254
  setPinnedColumns(map);
1280
- setIsRowIndexPinned(columnIds.includes(ROW_INDEX_COLUMN_ID));
1281
- }, []);
1282
- const setRowIndexPinned = useCallback((pinned) => {
1283
- setIsRowIndexPinned(pinned);
1284
1255
  }, []);
1285
1256
  const handleToggleGroupCollapse = useCallback((groupId) => {
1286
1257
  setCollapsedGroups((prev) => {
@@ -1306,14 +1277,17 @@ function useSpreadsheetPinning({
1306
1277
  return pinnedColumns.has(column.id);
1307
1278
  });
1308
1279
  }
1309
- if (pinnedColumns.size === 0) {
1280
+ const nonRowIndexPinned = Array.from(pinnedColumns.keys()).filter(
1281
+ (id) => id !== ROW_INDEX_COLUMN_ID
1282
+ );
1283
+ if (nonRowIndexPinned.length === 0) {
1310
1284
  return result;
1311
1285
  }
1312
1286
  const leftPinned = [];
1313
1287
  const unpinned = [];
1314
1288
  const rightPinned = [];
1315
- const pinnedLeftIds = Array.from(pinnedColumns.entries()).filter(([, side]) => side === "left").map(([id]) => id);
1316
- const pinnedRightIds = Array.from(pinnedColumns.entries()).filter(([, side]) => side === "right").map(([id]) => id);
1289
+ const pinnedLeftIds = Array.from(pinnedColumns.entries()).filter(([id, side]) => side === "left" && id !== ROW_INDEX_COLUMN_ID).map(([id]) => id);
1290
+ const pinnedRightIds = Array.from(pinnedColumns.entries()).filter(([id, side]) => side === "right" && id !== ROW_INDEX_COLUMN_ID).map(([id]) => id);
1317
1291
  for (const column of result) {
1318
1292
  const pinSide = pinnedColumns.get(column.id);
1319
1293
  if (pinSide === "left") {
@@ -1328,23 +1302,24 @@ function useSpreadsheetPinning({
1328
1302
  rightPinned.sort((a, b) => pinnedRightIds.indexOf(a.id) - pinnedRightIds.indexOf(b.id));
1329
1303
  return [...leftPinned, ...unpinned, ...rightPinned];
1330
1304
  }, [columns, columnGroups, collapsedGroups, pinnedColumns]);
1331
- const getRowIndexLeftOffset = useCallback(() => {
1332
- return 0;
1333
- }, []);
1334
1305
  const getColumnLeftOffset = useCallback(
1335
1306
  (columnId) => {
1336
- const pinnedLeft = Array.from(pinnedColumns.entries()).filter(([, side]) => side === "left").map(([id]) => id);
1307
+ if (columnId === ROW_INDEX_COLUMN_ID) {
1308
+ return 0;
1309
+ }
1310
+ const pinnedLeft = Array.from(pinnedColumns.entries()).filter(([id, side]) => side === "left" && id !== ROW_INDEX_COLUMN_ID).map(([id]) => id);
1337
1311
  const index = pinnedLeft.indexOf(columnId);
1338
- const baseOffset = showRowIndex && isRowIndexPinned ? ROW_INDEX_COLUMN_WIDTH : 0;
1312
+ const isRowIndexPinnedNow = pinnedColumns.has(ROW_INDEX_COLUMN_ID);
1313
+ const baseOffset = showRowIndex && isRowIndexPinnedNow ? ROW_INDEX_COLUMN_WIDTH : 0;
1339
1314
  if (index === -1) return baseOffset;
1340
1315
  let offset = baseOffset;
1341
1316
  for (let i = 0; i < index; i++) {
1342
1317
  const col = columns.find((c) => c.id === pinnedLeft[i]);
1343
- offset += col?.width || col?.minWidth || 100;
1318
+ offset += col?.minWidth || col?.width || 100;
1344
1319
  }
1345
1320
  return offset;
1346
1321
  },
1347
- [pinnedColumns, columns, showRowIndex, isRowIndexPinned]
1322
+ [pinnedColumns, columns, showRowIndex]
1348
1323
  );
1349
1324
  const isColumnPinned = useCallback(
1350
1325
  (columnId) => {
@@ -1364,12 +1339,9 @@ function useSpreadsheetPinning({
1364
1339
  collapsedGroups,
1365
1340
  visibleColumns,
1366
1341
  handleTogglePin,
1367
- handleToggleRowIndexPin,
1368
1342
  handleToggleGroupCollapse,
1369
1343
  setPinnedColumnsFromIds,
1370
- setRowIndexPinned,
1371
1344
  getColumnLeftOffset,
1372
- getRowIndexLeftOffset,
1373
1345
  isColumnPinned,
1374
1346
  getColumnPinSide
1375
1347
  };
@@ -2202,13 +2174,14 @@ function useSpreadsheetFiltering({
2202
2174
  onSortChange,
2203
2175
  serverSide = false,
2204
2176
  controlledFilters,
2205
- controlledSortConfig
2177
+ controlledSortConfig,
2178
+ defaultSortConfig
2206
2179
  }) {
2207
2180
  const [internalFilters, setInternalFilters] = useState7(
2208
2181
  {}
2209
2182
  );
2210
2183
  const [internalSortConfig, setInternalSortConfig] = useState7(
2211
- null
2184
+ defaultSortConfig ?? null
2212
2185
  );
2213
2186
  const [activeFilterColumn, setActiveFilterColumn] = useState7(null);
2214
2187
  const filters = controlledFilters ?? internalFilters;
@@ -3336,7 +3309,8 @@ function Spreadsheet({
3336
3309
  onSortChange,
3337
3310
  serverSide,
3338
3311
  controlledFilters,
3339
- controlledSortConfig: controlledSortConfig ?? spreadsheetSettings?.defaultSort
3312
+ controlledSortConfig,
3313
+ defaultSortConfig: spreadsheetSettings.defaultSort
3340
3314
  });
3341
3315
  const {
3342
3316
  getCellHighlight,
@@ -3368,7 +3342,8 @@ function Spreadsheet({
3368
3342
  getColumnPinSide
3369
3343
  } = useSpreadsheetPinning({
3370
3344
  columns,
3371
- columnGroups
3345
+ columnGroups,
3346
+ defaultPinnedColumns: initialSettings?.defaultPinnedColumns
3372
3347
  });
3373
3348
  const {
3374
3349
  getCellComments,
@@ -3437,6 +3412,27 @@ function Spreadsheet({
3437
3412
  defaultSort: sortConfig
3438
3413
  }));
3439
3414
  }, [sortConfig]);
3415
+ useEffect6(() => {
3416
+ const pinnedColumnIds = Array.from(pinnedColumns.keys());
3417
+ setSpreadsheetSettings((prev) => {
3418
+ const prevIds = prev.defaultPinnedColumns;
3419
+ if (prevIds.length === pinnedColumnIds.length && prevIds.every((id, idx) => id === pinnedColumnIds[idx])) {
3420
+ return prev;
3421
+ }
3422
+ return {
3423
+ ...prev,
3424
+ defaultPinnedColumns: pinnedColumnIds
3425
+ };
3426
+ });
3427
+ }, [pinnedColumns]);
3428
+ const isInitialMount = useRef5(true);
3429
+ useEffect6(() => {
3430
+ if (isInitialMount.current) {
3431
+ isInitialMount.current = false;
3432
+ return;
3433
+ }
3434
+ onSettingsChange?.(spreadsheetSettings);
3435
+ }, [spreadsheetSettings, onSettingsChange]);
3440
3436
  const applyUndo = useCallback7(() => {
3441
3437
  const entry = popUndoEntry();
3442
3438
  if (!entry || !onCellsEdit) return;