@xcelsior/ui-spreadsheets 1.3.4 → 1.4.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.
- package/.omc/state/idle-notif-cooldown.json +1 -1
- package/dist/index.d.mts +15 -0
- package/dist/index.d.ts +15 -0
- package/dist/index.js +251 -11
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +272 -32
- package/dist/index.mjs.map +1 -1
- package/dist/styles/globals.css +43 -8
- package/dist/styles/globals.css.map +1 -1
- package/package.json +2 -2
- package/src/components/ColumnHeaderActions.tsx +37 -1
- package/src/components/Spreadsheet.tsx +20 -0
- package/src/components/SpreadsheetHeader.tsx +2 -0
- package/src/components/SpreadsheetSettingsModal.tsx +197 -5
- package/src/components/SpreadsheetToolbar.tsx +26 -1
- package/src/hooks/useSpreadsheetPinning.ts +13 -2
- package/src/types.ts +11 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { useState, useEffect } from 'react';
|
|
2
|
-
import { HiX, HiCog, HiViewBoards, HiSortAscending, HiEye } from 'react-icons/hi';
|
|
3
|
-
import type { SpreadsheetColumn, SpreadsheetSortConfig } from '../types';
|
|
1
|
+
import { useState, useEffect, useMemo } from 'react';
|
|
2
|
+
import { HiX, HiCog, HiViewBoards, HiSortAscending, HiEye, HiEyeOff } from 'react-icons/hi';
|
|
3
|
+
import type { SpreadsheetColumn, SpreadsheetColumnGroup, SpreadsheetSortConfig } from '../types';
|
|
4
4
|
|
|
5
5
|
/**
|
|
6
6
|
* Settings configuration for the Spreadsheet
|
|
@@ -22,6 +22,8 @@ export interface SpreadsheetSettings {
|
|
|
22
22
|
columnWidths?: Record<string, number>;
|
|
23
23
|
/** Column IDs with duplicate checking enabled */
|
|
24
24
|
duplicateCheckColumns?: string[];
|
|
25
|
+
/** Column IDs that are hidden from view */
|
|
26
|
+
hiddenColumns?: string[];
|
|
25
27
|
}
|
|
26
28
|
|
|
27
29
|
export interface SpreadsheetSettingsModalProps {
|
|
@@ -35,6 +37,8 @@ export interface SpreadsheetSettingsModalProps {
|
|
|
35
37
|
onSave: (settings: SpreadsheetSettings) => void;
|
|
36
38
|
/** Available columns for pinning/sorting */
|
|
37
39
|
columns: SpreadsheetColumn[];
|
|
40
|
+
/** Column groups for organized visibility toggles */
|
|
41
|
+
columnGroups?: SpreadsheetColumnGroup[];
|
|
38
42
|
/** Title for the modal */
|
|
39
43
|
title?: string;
|
|
40
44
|
/** Available page size options */
|
|
@@ -71,10 +75,11 @@ export const SpreadsheetSettingsModal: React.FC<SpreadsheetSettingsModalProps> =
|
|
|
71
75
|
settings,
|
|
72
76
|
onSave,
|
|
73
77
|
columns,
|
|
78
|
+
columnGroups,
|
|
74
79
|
title = 'Spreadsheet Settings',
|
|
75
80
|
pageSizeOptions = [25, 50, 100, 200],
|
|
76
81
|
}) => {
|
|
77
|
-
const [activeTab, setActiveTab] = useState<'columns' | 'sorting' | 'display'>('
|
|
82
|
+
const [activeTab, setActiveTab] = useState<'visibility' | 'columns' | 'sorting' | 'display'>('visibility');
|
|
78
83
|
const [localSettings, setLocalSettings] = useState<SpreadsheetSettings>(settings);
|
|
79
84
|
|
|
80
85
|
// Update local settings when parent settings change
|
|
@@ -82,6 +87,18 @@ export const SpreadsheetSettingsModal: React.FC<SpreadsheetSettingsModalProps> =
|
|
|
82
87
|
setLocalSettings(settings);
|
|
83
88
|
}, [settings]);
|
|
84
89
|
|
|
90
|
+
const hiddenColumnsSet = useMemo(
|
|
91
|
+
() => new Set(localSettings.hiddenColumns ?? []),
|
|
92
|
+
[localSettings.hiddenColumns]
|
|
93
|
+
);
|
|
94
|
+
|
|
95
|
+
/** Columns not assigned to any group */
|
|
96
|
+
const ungroupedColumns = useMemo(() => {
|
|
97
|
+
if (!columnGroups?.length) return columns;
|
|
98
|
+
const groupedIds = new Set(columnGroups.flatMap((g) => g.columns));
|
|
99
|
+
return columns.filter((c) => !groupedIds.has(c.id));
|
|
100
|
+
}, [columns, columnGroups]);
|
|
101
|
+
|
|
85
102
|
if (!isOpen) return null;
|
|
86
103
|
|
|
87
104
|
const handleSave = () => {
|
|
@@ -137,7 +154,28 @@ export const SpreadsheetSettingsModal: React.FC<SpreadsheetSettingsModalProps> =
|
|
|
137
154
|
}
|
|
138
155
|
};
|
|
139
156
|
|
|
157
|
+
const hiddenCount = hiddenColumnsSet.size;
|
|
158
|
+
|
|
159
|
+
const toggleColumnVisibility = (columnId: string) => {
|
|
160
|
+
const isHidden = hiddenColumnsSet.has(columnId);
|
|
161
|
+
const newHidden = isHidden
|
|
162
|
+
? (localSettings.hiddenColumns ?? []).filter((id) => id !== columnId)
|
|
163
|
+
: [...(localSettings.hiddenColumns ?? []), columnId];
|
|
164
|
+
setLocalSettings({ ...localSettings, hiddenColumns: newHidden });
|
|
165
|
+
};
|
|
166
|
+
|
|
167
|
+
const setGroupVisibility = (groupColumnIds: string[], visible: boolean) => {
|
|
168
|
+
const currentHidden = new Set(localSettings.hiddenColumns ?? []);
|
|
169
|
+
if (visible) {
|
|
170
|
+
groupColumnIds.forEach((id) => currentHidden.delete(id));
|
|
171
|
+
} else {
|
|
172
|
+
groupColumnIds.forEach((id) => currentHidden.add(id));
|
|
173
|
+
}
|
|
174
|
+
setLocalSettings({ ...localSettings, hiddenColumns: Array.from(currentHidden) });
|
|
175
|
+
};
|
|
176
|
+
|
|
140
177
|
const tabs = [
|
|
178
|
+
{ id: 'visibility' as const, label: `Column Visibility${hiddenCount > 0 ? ` (${hiddenCount})` : ''}`, Icon: HiEyeOff },
|
|
141
179
|
{ id: 'columns' as const, label: 'Pinned Columns', Icon: HiViewBoards },
|
|
142
180
|
{ id: 'sorting' as const, label: 'Default Sorting', Icon: HiSortAscending },
|
|
143
181
|
{ id: 'display' as const, label: 'Display Options', Icon: HiEye },
|
|
@@ -158,7 +196,7 @@ export const SpreadsheetSettingsModal: React.FC<SpreadsheetSettingsModalProps> =
|
|
|
158
196
|
onKeyDown={(e) => e.key === 'Escape' && onClose()}
|
|
159
197
|
aria-label="Close settings"
|
|
160
198
|
/>
|
|
161
|
-
<div className="bg-white rounded-lg w-[
|
|
199
|
+
<div className="bg-white rounded-lg w-[70%] max-w-1/2 max-h-[70vh] flex flex-col shadow-xl relative z-10">
|
|
162
200
|
{/* Header */}
|
|
163
201
|
<div className="px-6 py-5 border-b border-gray-200 flex items-center justify-between">
|
|
164
202
|
<div className="flex items-center gap-3">
|
|
@@ -197,6 +235,160 @@ export const SpreadsheetSettingsModal: React.FC<SpreadsheetSettingsModalProps> =
|
|
|
197
235
|
|
|
198
236
|
{/* Content */}
|
|
199
237
|
<div className="flex-1 overflow-auto p-6">
|
|
238
|
+
{/* Column Visibility Tab */}
|
|
239
|
+
{activeTab === 'visibility' && (
|
|
240
|
+
<div>
|
|
241
|
+
<div className="p-4 bg-amber-50 border border-amber-200 rounded-lg mb-4 flex gap-3">
|
|
242
|
+
<HiEyeOff className="h-4 w-4 text-amber-600 shrink-0 mt-0.5" />
|
|
243
|
+
<div>
|
|
244
|
+
<p className="text-sm font-semibold text-gray-900 mb-1">
|
|
245
|
+
Column Visibility
|
|
246
|
+
</p>
|
|
247
|
+
<p className="text-sm text-gray-600">
|
|
248
|
+
Toggle columns on or off. Hidden columns are removed from the table but their data is preserved.
|
|
249
|
+
{hiddenCount > 0 && (
|
|
250
|
+
<span className="ml-1 font-medium text-amber-700">
|
|
251
|
+
{hiddenCount} column{hiddenCount !== 1 ? 's' : ''} hidden.
|
|
252
|
+
</span>
|
|
253
|
+
)}
|
|
254
|
+
</p>
|
|
255
|
+
</div>
|
|
256
|
+
</div>
|
|
257
|
+
|
|
258
|
+
{/* Show All / Hide All quick actions */}
|
|
259
|
+
<div className="flex gap-2 mb-4">
|
|
260
|
+
<button
|
|
261
|
+
type="button"
|
|
262
|
+
onClick={() => setLocalSettings({ ...localSettings, hiddenColumns: [] })}
|
|
263
|
+
className="px-3 py-1.5 text-xs font-medium text-green-700 bg-green-50 border border-green-200 rounded-lg hover:bg-green-100 transition-colors"
|
|
264
|
+
>
|
|
265
|
+
Show All
|
|
266
|
+
</button>
|
|
267
|
+
<button
|
|
268
|
+
type="button"
|
|
269
|
+
onClick={() =>
|
|
270
|
+
setLocalSettings({
|
|
271
|
+
...localSettings,
|
|
272
|
+
hiddenColumns: columns.map((c) => c.id),
|
|
273
|
+
})
|
|
274
|
+
}
|
|
275
|
+
className="px-3 py-1.5 text-xs font-medium text-red-700 bg-red-50 border border-red-200 rounded-lg hover:bg-red-100 transition-colors"
|
|
276
|
+
>
|
|
277
|
+
Hide All
|
|
278
|
+
</button>
|
|
279
|
+
</div>
|
|
280
|
+
|
|
281
|
+
{/* Grouped columns */}
|
|
282
|
+
{columnGroups?.map((group) => {
|
|
283
|
+
const groupCols = columns.filter((c) => group.columns.includes(c.id));
|
|
284
|
+
if (groupCols.length === 0) return null;
|
|
285
|
+
const hiddenInGroup = groupCols.filter((c) => hiddenColumnsSet.has(c.id)).length;
|
|
286
|
+
const allHidden = hiddenInGroup === groupCols.length;
|
|
287
|
+
const allVisible = hiddenInGroup === 0;
|
|
288
|
+
|
|
289
|
+
return (
|
|
290
|
+
<div key={group.id} className="mb-4">
|
|
291
|
+
<div className="flex items-center justify-between mb-2">
|
|
292
|
+
<div className="flex items-center gap-2">
|
|
293
|
+
<div
|
|
294
|
+
className="w-3 h-3 rounded-sm"
|
|
295
|
+
style={{ backgroundColor: group.headerColor }}
|
|
296
|
+
/>
|
|
297
|
+
<span className="text-sm font-medium text-gray-900">
|
|
298
|
+
{group.label}
|
|
299
|
+
</span>
|
|
300
|
+
<span className="text-xs text-gray-500">
|
|
301
|
+
({groupCols.length - hiddenInGroup}/{groupCols.length})
|
|
302
|
+
</span>
|
|
303
|
+
</div>
|
|
304
|
+
<div className="flex gap-1">
|
|
305
|
+
<button
|
|
306
|
+
type="button"
|
|
307
|
+
onClick={() => setGroupVisibility(group.columns, true)}
|
|
308
|
+
disabled={allVisible}
|
|
309
|
+
className="px-2 py-0.5 text-xs text-green-700 hover:bg-green-50 rounded transition-colors disabled:opacity-40 disabled:cursor-not-allowed"
|
|
310
|
+
>
|
|
311
|
+
Show all
|
|
312
|
+
</button>
|
|
313
|
+
<button
|
|
314
|
+
type="button"
|
|
315
|
+
onClick={() => setGroupVisibility(group.columns, false)}
|
|
316
|
+
disabled={allHidden}
|
|
317
|
+
className="px-2 py-0.5 text-xs text-red-700 hover:bg-red-50 rounded transition-colors disabled:opacity-40 disabled:cursor-not-allowed"
|
|
318
|
+
>
|
|
319
|
+
Hide all
|
|
320
|
+
</button>
|
|
321
|
+
</div>
|
|
322
|
+
</div>
|
|
323
|
+
<div className="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 gap-2">
|
|
324
|
+
{groupCols.map((column) => {
|
|
325
|
+
const isHidden = hiddenColumnsSet.has(column.id);
|
|
326
|
+
return (
|
|
327
|
+
<button
|
|
328
|
+
key={column.id}
|
|
329
|
+
type="button"
|
|
330
|
+
onClick={() => toggleColumnVisibility(column.id)}
|
|
331
|
+
className={`flex items-center gap-2 p-3 rounded-lg border transition-colors text-left ${
|
|
332
|
+
isHidden
|
|
333
|
+
? 'bg-gray-100 border-gray-200 text-gray-400'
|
|
334
|
+
: 'bg-green-50 border-green-300 text-green-800'
|
|
335
|
+
}`}
|
|
336
|
+
>
|
|
337
|
+
{isHidden ? (
|
|
338
|
+
<HiEyeOff className="h-4 w-4 shrink-0" />
|
|
339
|
+
) : (
|
|
340
|
+
<HiEye className="h-4 w-4 shrink-0" />
|
|
341
|
+
)}
|
|
342
|
+
<span className="text-sm flex-1 truncate">
|
|
343
|
+
{column.label}
|
|
344
|
+
</span>
|
|
345
|
+
</button>
|
|
346
|
+
);
|
|
347
|
+
})}
|
|
348
|
+
</div>
|
|
349
|
+
</div>
|
|
350
|
+
);
|
|
351
|
+
})}
|
|
352
|
+
|
|
353
|
+
{/* Ungrouped columns */}
|
|
354
|
+
{ungroupedColumns.length > 0 && (
|
|
355
|
+
<div className="mb-4">
|
|
356
|
+
{columnGroups?.length ? (
|
|
357
|
+
<div className="flex items-center gap-2 mb-2">
|
|
358
|
+
<span className="text-sm font-medium text-gray-900">Other</span>
|
|
359
|
+
</div>
|
|
360
|
+
) : null}
|
|
361
|
+
<div className="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 gap-2">
|
|
362
|
+
{ungroupedColumns.map((column) => {
|
|
363
|
+
const isHidden = hiddenColumnsSet.has(column.id);
|
|
364
|
+
return (
|
|
365
|
+
<button
|
|
366
|
+
key={column.id}
|
|
367
|
+
type="button"
|
|
368
|
+
onClick={() => toggleColumnVisibility(column.id)}
|
|
369
|
+
className={`flex items-center gap-2 p-3 rounded-lg border transition-colors text-left ${
|
|
370
|
+
isHidden
|
|
371
|
+
? 'bg-gray-100 border-gray-200 text-gray-400'
|
|
372
|
+
: 'bg-green-50 border-green-300 text-green-800'
|
|
373
|
+
}`}
|
|
374
|
+
>
|
|
375
|
+
{isHidden ? (
|
|
376
|
+
<HiEyeOff className="h-4 w-4 shrink-0" />
|
|
377
|
+
) : (
|
|
378
|
+
<HiEye className="h-4 w-4 shrink-0" />
|
|
379
|
+
)}
|
|
380
|
+
<span className="text-sm flex-1 truncate">
|
|
381
|
+
{column.label}
|
|
382
|
+
</span>
|
|
383
|
+
</button>
|
|
384
|
+
);
|
|
385
|
+
})}
|
|
386
|
+
</div>
|
|
387
|
+
</div>
|
|
388
|
+
)}
|
|
389
|
+
</div>
|
|
390
|
+
)}
|
|
391
|
+
|
|
200
392
|
{/* Pinned Columns Tab */}
|
|
201
393
|
{activeTab === 'columns' && (
|
|
202
394
|
<div>
|
|
@@ -68,6 +68,9 @@ export const SpreadsheetToolbar: React.FC<SpreadsheetToolbarProps> = ({
|
|
|
68
68
|
onClearFilter,
|
|
69
69
|
showFiltersPanel,
|
|
70
70
|
onToggleFiltersPanel,
|
|
71
|
+
hiddenColumnCount = 0,
|
|
72
|
+
onShowAllColumns,
|
|
73
|
+
onManageColumns,
|
|
71
74
|
className,
|
|
72
75
|
}) => {
|
|
73
76
|
const [showMoreMenu, setShowMoreMenu] = React.useState(false);
|
|
@@ -309,6 +312,28 @@ export const SpreadsheetToolbar: React.FC<SpreadsheetToolbarProps> = ({
|
|
|
309
312
|
</button>
|
|
310
313
|
)}
|
|
311
314
|
|
|
315
|
+
{/* Hidden columns indicator */}
|
|
316
|
+
{hiddenColumnCount > 0 && (
|
|
317
|
+
<div className="flex items-center gap-1.5 px-2.5 py-1.5 bg-amber-50 border border-amber-200 rounded text-xs text-amber-700">
|
|
318
|
+
<span className="font-medium">{hiddenColumnCount} hidden</span>
|
|
319
|
+
<button
|
|
320
|
+
type="button"
|
|
321
|
+
onClick={onShowAllColumns}
|
|
322
|
+
className="text-amber-800 underline hover:text-amber-900 transition-colors"
|
|
323
|
+
>
|
|
324
|
+
Show
|
|
325
|
+
</button>
|
|
326
|
+
<span className="text-amber-300">|</span>
|
|
327
|
+
<button
|
|
328
|
+
type="button"
|
|
329
|
+
onClick={onManageColumns}
|
|
330
|
+
className="text-amber-800 underline hover:text-amber-900 transition-colors"
|
|
331
|
+
>
|
|
332
|
+
Manage
|
|
333
|
+
</button>
|
|
334
|
+
</div>
|
|
335
|
+
)}
|
|
336
|
+
|
|
312
337
|
{/* More menu dropdown */}
|
|
313
338
|
<div className="relative" ref={menuRef}>
|
|
314
339
|
<button
|
|
@@ -323,7 +348,7 @@ export const SpreadsheetToolbar: React.FC<SpreadsheetToolbarProps> = ({
|
|
|
323
348
|
|
|
324
349
|
{/* Dropdown Menu */}
|
|
325
350
|
{showMoreMenu && (
|
|
326
|
-
<div className="absolute right-0 top-full mt-1 bg-white border border-gray-200 shadow-lg rounded py-1 min-w-[180px] z-
|
|
351
|
+
<div className="absolute right-0 top-full mt-1 bg-white border border-gray-200 shadow-lg rounded py-1 min-w-[180px] z-[60]">
|
|
327
352
|
{onSettings && (
|
|
328
353
|
<button
|
|
329
354
|
type={'button'}
|
|
@@ -15,6 +15,8 @@ export interface UseSpreadsheetPinningOptions<T> {
|
|
|
15
15
|
defaultPinnedRightColumns?: string[];
|
|
16
16
|
/** Function to get the current (possibly resized) width for a column */
|
|
17
17
|
getColumnWidth?: (columnId: string, defaultWidth?: number) => number | undefined;
|
|
18
|
+
/** Column IDs that are hidden from view */
|
|
19
|
+
hiddenColumns?: string[];
|
|
18
20
|
}
|
|
19
21
|
|
|
20
22
|
export interface UseSpreadsheetPinningReturn<T> {
|
|
@@ -40,6 +42,7 @@ export function useSpreadsheetPinning<T>({
|
|
|
40
42
|
defaultPinnedColumns = [],
|
|
41
43
|
defaultPinnedRightColumns = [],
|
|
42
44
|
getColumnWidth,
|
|
45
|
+
hiddenColumns = [],
|
|
43
46
|
}: UseSpreadsheetPinningOptions<T>): UseSpreadsheetPinningReturn<T> {
|
|
44
47
|
const [pinnedColumns, setPinnedColumns] = useState<Map<string, 'left' | 'right'>>(() => {
|
|
45
48
|
const map = new Map<string, 'left' | 'right'>();
|
|
@@ -139,12 +142,20 @@ export function useSpreadsheetPinning<T>({
|
|
|
139
142
|
});
|
|
140
143
|
}, []);
|
|
141
144
|
|
|
142
|
-
//
|
|
145
|
+
// Stable reference for hidden columns set
|
|
146
|
+
const hiddenColumnsSet = useMemo(() => new Set(hiddenColumns), [hiddenColumns]);
|
|
147
|
+
|
|
148
|
+
// Visible columns — filtered by hidden columns and collapse, natural order preserved
|
|
143
149
|
const visibleColumns = useMemo(() => {
|
|
144
150
|
if (!columns || !Array.isArray(columns) || columns.length === 0) return [];
|
|
145
151
|
|
|
146
152
|
let result: SpreadsheetColumn<T>[] = [...columns];
|
|
147
153
|
|
|
154
|
+
// Filter out hidden columns
|
|
155
|
+
if (hiddenColumnsSet.size > 0) {
|
|
156
|
+
result = result.filter((column) => !hiddenColumnsSet.has(column.id));
|
|
157
|
+
}
|
|
158
|
+
|
|
148
159
|
if (columnGroups && Array.isArray(columnGroups)) {
|
|
149
160
|
result = result.filter((column) => {
|
|
150
161
|
const group = columnGroups.find((g) => g.columns.includes(column.id));
|
|
@@ -155,7 +166,7 @@ export function useSpreadsheetPinning<T>({
|
|
|
155
166
|
}
|
|
156
167
|
|
|
157
168
|
return result;
|
|
158
|
-
}, [columns, columnGroups, collapsedGroups, pinnedColumns]);
|
|
169
|
+
}, [columns, columnGroups, collapsedGroups, pinnedColumns, hiddenColumnsSet]);
|
|
159
170
|
|
|
160
171
|
// Measure after render when layout changes
|
|
161
172
|
useEffect(() => {
|
package/src/types.ts
CHANGED
|
@@ -415,6 +415,8 @@ export interface SpreadsheetProps<T = any> {
|
|
|
415
415
|
compactView?: boolean;
|
|
416
416
|
/** Persisted column widths (columnId → width in px) */
|
|
417
417
|
columnWidths?: Record<string, number>;
|
|
418
|
+
/** Column IDs that are hidden from view */
|
|
419
|
+
hiddenColumns?: string[];
|
|
418
420
|
};
|
|
419
421
|
/** Callback when spreadsheet settings are changed by the user */
|
|
420
422
|
onSettingsChange?: (settings: {
|
|
@@ -425,6 +427,7 @@ export interface SpreadsheetProps<T = any> {
|
|
|
425
427
|
defaultPinnedColumns?: string[];
|
|
426
428
|
defaultPinnedRightColumns?: string[];
|
|
427
429
|
defaultSort?: SpreadsheetSortConfig | null;
|
|
430
|
+
hiddenColumns?: string[];
|
|
428
431
|
}) => void;
|
|
429
432
|
/** Loading state */
|
|
430
433
|
isLoading?: boolean;
|
|
@@ -623,6 +626,8 @@ export interface SpreadsheetHeaderProps {
|
|
|
623
626
|
onDuplicateCheckClick?: () => void;
|
|
624
627
|
/** Number of rows with duplicate values (shown as badge when > 0) */
|
|
625
628
|
duplicateCount?: number;
|
|
629
|
+
/** Callback when hide column is clicked */
|
|
630
|
+
onHideClick?: () => void;
|
|
626
631
|
/** Resize handle props from useSpreadsheetColumnResize */
|
|
627
632
|
resizeHandleProps?: {
|
|
628
633
|
onMouseDown: (e: React.MouseEvent) => void;
|
|
@@ -763,6 +768,12 @@ export interface SpreadsheetToolbarProps {
|
|
|
763
768
|
showFiltersPanel?: boolean;
|
|
764
769
|
/** Callback to toggle the active filters panel */
|
|
765
770
|
onToggleFiltersPanel?: () => void;
|
|
771
|
+
/** Number of hidden columns (shows indicator when > 0) */
|
|
772
|
+
hiddenColumnCount?: number;
|
|
773
|
+
/** Callback to show all hidden columns */
|
|
774
|
+
onShowAllColumns?: () => void;
|
|
775
|
+
/** Callback to open column visibility settings */
|
|
776
|
+
onManageColumns?: () => void;
|
|
766
777
|
/** Custom className */
|
|
767
778
|
className?: string;
|
|
768
779
|
}
|