@xcelsior/ui-spreadsheets 1.0.18 → 1.1.0

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.
@@ -18,12 +18,6 @@ export interface SpreadsheetSettings {
18
18
  autoSave?: boolean;
19
19
  /** Whether compact view is enabled */
20
20
  compactView?: boolean;
21
- /** Whether to show row index column */
22
- showRowIndex?: boolean;
23
- /** Whether row index column is pinned */
24
- pinRowIndex?: boolean;
25
- /** Row index column highlight color */
26
- rowIndexHighlightColor?: string;
27
21
  }
28
22
 
29
23
  export interface SpreadsheetSettingsModalProps {
@@ -50,9 +44,6 @@ const DEFAULT_SETTINGS: SpreadsheetSettings = {
50
44
  defaultZoom: 100,
51
45
  autoSave: true,
52
46
  compactView: false,
53
- showRowIndex: true,
54
- pinRowIndex: false,
55
- rowIndexHighlightColor: undefined,
56
47
  };
57
48
 
58
49
  /**
@@ -221,17 +212,12 @@ export const SpreadsheetSettingsModal: React.FC<SpreadsheetSettingsModalProps> =
221
212
  Select which columns should be pinned to the left by default.
222
213
  </p>
223
214
  <div className="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 gap-2">
224
- {/* Row Index Column - Special handling */}
215
+ {/* Row Index Column */}
225
216
  <button
226
217
  type="button"
227
- onClick={() =>
228
- setLocalSettings({
229
- ...localSettings,
230
- pinRowIndex: !localSettings.pinRowIndex,
231
- })
232
- }
218
+ onClick={() => togglePinnedColumn('__row_index__')}
233
219
  className={`flex items-center gap-2 p-3 rounded-lg border transition-colors text-left ${
234
- localSettings.pinRowIndex !== false
220
+ localSettings.defaultPinnedColumns.includes('__row_index__')
235
221
  ? 'bg-blue-50 border-blue-300 text-blue-700'
236
222
  : 'bg-gray-50 border-gray-200 text-gray-700 hover:border-blue-300'
237
223
  }`}
@@ -263,69 +249,6 @@ export const SpreadsheetSettingsModal: React.FC<SpreadsheetSettingsModalProps> =
263
249
  );
264
250
  })}
265
251
  </div>
266
-
267
- {/* Row Index Highlight */}
268
- <div className="mt-6 p-4 bg-amber-50 border border-amber-200 rounded-lg">
269
- <p className="text-sm font-semibold text-gray-900 mb-3">
270
- Row Index Column Highlight
271
- </p>
272
- <p className="text-sm text-gray-600 mb-3">
273
- Apply a highlight color to the # (row index) column to make it
274
- stand out.
275
- </p>
276
- <div className="flex items-center gap-2 flex-wrap">
277
- {[
278
- '#fef3c7',
279
- '#dbeafe',
280
- '#dcfce7',
281
- '#fce7f3',
282
- '#f3e8ff',
283
- '#e0e7ff',
284
- '#fed7d7',
285
- '#c6f6d5',
286
- ].map((color) => (
287
- <button
288
- key={color}
289
- type="button"
290
- onClick={() =>
291
- setLocalSettings({
292
- ...localSettings,
293
- rowIndexHighlightColor:
294
- localSettings.rowIndexHighlightColor ===
295
- color
296
- ? undefined
297
- : color,
298
- })
299
- }
300
- className={`w-8 h-8 rounded-lg border-2 transition-all ${
301
- localSettings.rowIndexHighlightColor === color
302
- ? 'border-blue-600 scale-110 ring-2 ring-blue-300'
303
- : 'border-gray-300 hover:border-gray-400'
304
- }`}
305
- style={{ backgroundColor: color }}
306
- title={
307
- localSettings.rowIndexHighlightColor === color
308
- ? 'Remove highlight'
309
- : 'Apply highlight'
310
- }
311
- />
312
- ))}
313
- {localSettings.rowIndexHighlightColor && (
314
- <button
315
- type="button"
316
- onClick={() =>
317
- setLocalSettings({
318
- ...localSettings,
319
- rowIndexHighlightColor: undefined,
320
- })
321
- }
322
- className="text-sm text-red-600 hover:text-red-700 ml-2 px-2 py-1 rounded hover:bg-red-50"
323
- >
324
- Clear
325
- </button>
326
- )}
327
- </div>
328
- </div>
329
252
  </div>
330
253
  )}
331
254
 
@@ -393,36 +316,6 @@ export const SpreadsheetSettingsModal: React.FC<SpreadsheetSettingsModalProps> =
393
316
  Customize the display and behavior of the spreadsheet.
394
317
  </p>
395
318
 
396
- {/* Row Index Options */}
397
- <div className="p-4 bg-blue-50 border border-blue-200 rounded-lg">
398
- <p className="text-sm font-semibold text-gray-900 mb-3">
399
- Row Index Column
400
- </p>
401
- <div className="space-y-3">
402
- {/* Show Row Index */}
403
- <label className="flex items-center gap-3 cursor-pointer">
404
- <input
405
- type="checkbox"
406
- checked={localSettings.showRowIndex !== false}
407
- onChange={(e) =>
408
- setLocalSettings({
409
- ...localSettings,
410
- showRowIndex: e.target.checked,
411
- })
412
- }
413
- className="w-4 h-4 cursor-pointer rounded border-gray-300 text-blue-600 focus:ring-blue-500"
414
- />
415
- <span className="text-sm text-gray-700">
416
- Show row index (#) column
417
- </span>
418
- </label>
419
- <p className="text-xs text-gray-500 ml-7">
420
- Tip: Use the "Pinned Columns" tab to pin and highlight the
421
- row index column.
422
- </p>
423
- </div>
424
- </div>
425
-
426
319
  {/* Page Size */}
427
320
  <div>
428
321
  <label className="block text-sm font-medium text-gray-900 mb-2">
@@ -7,7 +7,6 @@ export {
7
7
  export {
8
8
  useSpreadsheetHighlighting,
9
9
  HIGHLIGHT_COLORS,
10
- ROW_INDEX_COLUMN_ID,
11
10
  type UseSpreadsheetHighlightingOptions,
12
11
  type UseSpreadsheetHighlightingReturn,
13
12
  } from './useSpreadsheetHighlighting';
@@ -15,7 +14,6 @@ export {
15
14
  export {
16
15
  useSpreadsheetPinning,
17
16
  ROW_INDEX_COLUMN_WIDTH,
18
- ROW_INDEX_COLUMN_ID as PINNING_ROW_INDEX_COLUMN_ID,
19
17
  type UseSpreadsheetPinningOptions,
20
18
  type UseSpreadsheetPinningReturn,
21
19
  } from './useSpreadsheetPinning';
@@ -68,9 +68,6 @@ export interface UseSpreadsheetHighlightingReturn {
68
68
  clearAllHighlights: () => void;
69
69
  }
70
70
 
71
- // Special column ID for row index
72
- export const ROW_INDEX_COLUMN_ID = '__row_index__';
73
-
74
71
  export function useSpreadsheetHighlighting({
75
72
  externalRowHighlights,
76
73
  onRowHighlight,
@@ -3,7 +3,7 @@ import type { SpreadsheetColumn, SpreadsheetColumnGroup } from '../types';
3
3
 
4
4
  // Special column ID for row index
5
5
  export const ROW_INDEX_COLUMN_ID = '__row_index__';
6
- export const ROW_INDEX_COLUMN_WIDTH = 56;
6
+ export const ROW_INDEX_COLUMN_WIDTH = 80;
7
7
 
8
8
  export interface UseSpreadsheetPinningOptions<T> {
9
9
  columns: SpreadsheetColumn<T>[];
@@ -28,6 +28,8 @@ export interface UseSpreadsheetPinningReturn<T> {
28
28
  handleTogglePin: (columnId: string) => void;
29
29
  handleToggleRowIndexPin: () => void;
30
30
  handleToggleGroupCollapse: (groupId: string) => void;
31
+ setPinnedColumnsFromIds: (columnIds: string[]) => void;
32
+ setRowIndexPinned: (pinned: boolean) => void;
31
33
 
32
34
  // Offset calculations
33
35
  getColumnLeftOffset: (columnId: string) => number;
@@ -45,16 +47,21 @@ export function useSpreadsheetPinning<T>({
45
47
  defaultPinnedColumns = [],
46
48
  defaultPinRowIndex = false,
47
49
  }: UseSpreadsheetPinningOptions<T>): UseSpreadsheetPinningReturn<T> {
48
- // Initialize pinned columns from defaults
50
+ // Initialize pinned columns from defaults (excluding row index which is handled separately)
49
51
  const [pinnedColumns, setPinnedColumns] = useState<Map<string, 'left' | 'right'>>(() => {
50
52
  const map = new Map<string, 'left' | 'right'>();
51
53
  defaultPinnedColumns.forEach((col) => {
52
- map.set(col, 'left');
54
+ if (col !== ROW_INDEX_COLUMN_ID) {
55
+ map.set(col, 'left');
56
+ }
53
57
  });
54
58
  return map;
55
59
  });
56
60
 
57
- const [isRowIndexPinned, setIsRowIndexPinned] = useState(defaultPinRowIndex);
61
+ // Check if row index should be pinned from either defaultPinRowIndex or defaultPinnedColumns
62
+ const [isRowIndexPinned, setIsRowIndexPinned] = useState(
63
+ defaultPinRowIndex || defaultPinnedColumns.includes(ROW_INDEX_COLUMN_ID)
64
+ );
58
65
  const [collapsedGroups, setCollapsedGroups] = useState<Set<string>>(new Set());
59
66
 
60
67
  // Toggle column pin
@@ -75,6 +82,24 @@ export function useSpreadsheetPinning<T>({
75
82
  setIsRowIndexPinned((prev) => !prev);
76
83
  }, []);
77
84
 
85
+ // Set pinned columns from an array of column IDs
86
+ const setPinnedColumnsFromIds = useCallback((columnIds: string[]) => {
87
+ const map = new Map<string, 'left' | 'right'>();
88
+ columnIds.forEach((col) => {
89
+ if (col !== ROW_INDEX_COLUMN_ID) {
90
+ map.set(col, 'left');
91
+ }
92
+ });
93
+ setPinnedColumns(map);
94
+ // Also update row index pinned state
95
+ setIsRowIndexPinned(columnIds.includes(ROW_INDEX_COLUMN_ID));
96
+ }, []);
97
+
98
+ // Set row index pinned state directly
99
+ const setRowIndexPinned = useCallback((pinned: boolean) => {
100
+ setIsRowIndexPinned(pinned);
101
+ }, []);
102
+
78
103
  // Toggle group collapse
79
104
  const handleToggleGroupCollapse = useCallback((groupId: string) => {
80
105
  setCollapsedGroups((prev) => {
@@ -195,6 +220,8 @@ export function useSpreadsheetPinning<T>({
195
220
  handleTogglePin,
196
221
  handleToggleRowIndexPin,
197
222
  handleToggleGroupCollapse,
223
+ setPinnedColumnsFromIds,
224
+ setRowIndexPinned,
198
225
  getColumnLeftOffset,
199
226
  getRowIndexLeftOffset,
200
227
  isColumnPinned,
package/src/types.ts CHANGED
@@ -344,8 +344,6 @@ export interface SpreadsheetProps<T = any> {
344
344
  showToolbar?: boolean;
345
345
  /** Whether to show pagination */
346
346
  showPagination?: boolean;
347
- /** Whether to show row index column (#) */
348
- showRowIndex?: boolean;
349
347
  /** Whether to enable row selection */
350
348
  enableRowSelection?: boolean;
351
349
  /** Whether to enable cell editing */
@@ -356,18 +354,34 @@ export interface SpreadsheetProps<T = any> {
356
354
  enableHighlighting?: boolean;
357
355
  /** Whether to enable undo/redo */
358
356
  enableUndoRedo?: boolean;
359
- /** Initial page size */
360
- defaultPageSize?: number;
361
357
  /** Available page size options */
362
358
  pageSizeOptions?: number[];
363
- /** Initial zoom level */
364
- defaultZoom?: number;
365
- /** Whether to auto-save changes */
366
- autoSave?: boolean;
367
359
  /** Callback when changes are saved (called for both auto-save and manual save) */
368
360
  onSave?: () => void | Promise<void>;
369
- /** Whether to use compact mode (smaller cells) */
370
- compactMode?: boolean;
361
+ /** Initial settings (optional). All settings can be changed by user in the settings modal. */
362
+ settings?: {
363
+ /** Default pinned column IDs */
364
+ defaultPinnedColumns?: string[];
365
+ /** Default sort configuration */
366
+ defaultSort?: SpreadsheetSortConfig | null;
367
+ /** Default page size */
368
+ defaultPageSize?: number;
369
+ /** Default zoom level */
370
+ defaultZoom?: number;
371
+ /** Whether auto-save is enabled */
372
+ autoSave?: boolean;
373
+ /** Whether compact view is enabled */
374
+ compactView?: boolean;
375
+ };
376
+ /** Callback when spreadsheet settings are changed by the user */
377
+ onSettingsChange?: (settings: {
378
+ compactView?: boolean;
379
+ autoSave?: boolean;
380
+ defaultPageSize?: number;
381
+ defaultZoom?: number;
382
+ defaultPinnedColumns?: string[];
383
+ defaultSort?: SpreadsheetSortConfig | null;
384
+ }) => void;
371
385
  /** Loading state */
372
386
  isLoading?: boolean;
373
387
  /** Custom className */