react-restyle-components 0.4.24 → 0.4.26

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.
@@ -1,13 +1,41 @@
1
1
  'use client';
2
2
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
3
3
  import React, { forwardRef, useState, useCallback, useMemo, useRef, } from 'react';
4
- import { TableRoot, Toolbar, ToolbarGroup, SearchInput, ToolbarButton, TableWrapper, StyledTable, TableHeader, HeaderRow, HeaderCell, SortIcon, FilterRow, FilterCell, TableBody, TableRow, TableCell, Checkbox, ExpandButton, ExpandedRow, ExpandedCell, TableFooter, FooterRow, FooterCell, PaginationWrapper, PaginationInfo, PaginationControls, PageButton, PageSizeSelect, QuickJumper, EmptyState, LoadingOverlay, LoadingSpinner, EditableCell, CellEditor, ColumnTogglePanel, ColumnToggleHeader, ColumnToggleSearch, ColumnToggleList, ColumnToggleItem, } from './elements';
4
+ import { TableRoot, Toolbar, ToolbarGroup, SearchInput, ToolbarButton, TableWrapper, StyledTable, TableHeader, HeaderRow, HeaderCell, TableBody, TableRow, TableCell, Checkbox, ExpandButton, ExpandedRow, ExpandedCell, TableFooter, FooterRow, FooterCell, PaginationWrapper, PaginationInfo, PaginationControls, PageButton, PageSizeSelect, QuickJumper, EmptyState, LoadingOverlay, LoadingSpinner, EditableCell, CellEditor, ColumnTogglePanel, ColumnToggleHeader, ColumnToggleSearch, ColumnToggleList, ColumnToggleItem, } from './elements';
5
5
  import { useSortState, useFilterState, usePaginationState, useRowSelection, useRowExpansion, useColumnVisibility, useTableDebounce, sortData, filterData, paginateData, getNestedValue, exportToCSV, } from './hooks';
6
6
  import { getFilterComponent } from './filters';
7
+ import { Tooltip } from '../Tooltip';
7
8
  // Icons
8
9
  const SearchIcon = () => (_jsxs("svg", { viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", children: [_jsx("circle", { cx: "11", cy: "11", r: "8" }), _jsx("path", { d: "M21 21l-4.35-4.35", strokeLinecap: "round" })] }));
10
+ // Arrow Up Icon with configurable size
11
+ const ArrowUpIcon = ({ size = 14 }) => (_jsx("svg", { viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2.5", strokeLinecap: "round", strokeLinejoin: "round", style: { width: size, height: size }, children: _jsx("path", { d: "M12 19V5M5 12l7-7 7 7" }) }));
12
+ // Arrow Down Icon with configurable size
13
+ const ArrowDownIcon = ({ size = 14 }) => (_jsx("svg", { viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2.5", strokeLinecap: "round", strokeLinejoin: "round", style: { width: size, height: size }, children: _jsx("path", { d: "M12 5v14M5 12l7 7 7-7" }) }));
14
+ // Legacy triangle icons (kept for backward compatibility)
9
15
  const SortUpIcon = () => (_jsx("svg", { viewBox: "0 0 10 10", fill: "currentColor", children: _jsx("path", { d: "M5 0L10 6H0L5 0z" }) }));
10
16
  const SortDownIcon = () => (_jsx("svg", { viewBox: "0 0 10 10", fill: "currentColor", children: _jsx("path", { d: "M5 10L0 4h10L5 10z" }) }));
17
+ // Default sort caret component with arrow icons
18
+ const DefaultSortCaret = ({ order, }) => {
19
+ const getSizeConfig = () => {
20
+ switch (order) {
21
+ case 'asc':
22
+ return { up: 16, down: 10 };
23
+ case 'desc':
24
+ return { up: 10, down: 16 };
25
+ default:
26
+ return { up: 14, down: 14 };
27
+ }
28
+ };
29
+ const { up, down } = getSizeConfig();
30
+ return (_jsxs("div", { style: {
31
+ display: 'flex',
32
+ flexDirection: 'row',
33
+ alignItems: 'center',
34
+ justifyContent: 'center',
35
+ gap: 2,
36
+ color: 'white',
37
+ }, children: [_jsx(ArrowUpIcon, { size: up }), _jsx(ArrowDownIcon, { size: down })] }));
38
+ };
11
39
  const ChevronLeftIcon = () => (_jsx("svg", { viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", children: _jsx("path", { d: "M15 18l-6-6 6-6", strokeLinecap: "round", strokeLinejoin: "round" }) }));
12
40
  const ChevronRightIcon = () => (_jsx("svg", { viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", children: _jsx("path", { d: "M9 18l6-6-6-6", strokeLinecap: "round", strokeLinejoin: "round" }) }));
13
41
  const ChevronsLeftIcon = () => (_jsx("svg", { viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", children: _jsx("path", { d: "M11 17l-5-5 5-5M18 17l-5-5 5-5", strokeLinecap: "round", strokeLinejoin: "round" }) }));
@@ -18,14 +46,84 @@ const FilterIcon = () => (_jsx("svg", { viewBox: "0 0 24 24", fill: "none", stro
18
46
  const DownloadIcon = () => (_jsx("svg", { viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", children: _jsx("path", { d: "M21 15v4a2 2 0 01-2 2H5a2 2 0 01-2-2v-4M7 10l5 5 5-5M12 15V3", strokeLinecap: "round", strokeLinejoin: "round" }) }));
19
47
  const ColumnsIcon = () => (_jsxs("svg", { viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", children: [_jsx("rect", { x: "3", y: "3", width: "7", height: "18", rx: "1" }), _jsx("rect", { x: "14", y: "3", width: "7", height: "18", rx: "1" })] }));
20
48
  const EmptyIcon = () => (_jsxs("svg", { viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "1.5", children: [_jsx("rect", { x: "3", y: "3", width: "18", height: "18", rx: "2" }), _jsx("path", { d: "M3 9h18M9 3v18", strokeLinecap: "round" })] }));
49
+ const EditIcon = () => (_jsxs("svg", { viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", children: [_jsx("path", { d: "M11 4H4a2 2 0 00-2 2v14a2 2 0 002 2h14a2 2 0 002-2v-7", strokeLinecap: "round", strokeLinejoin: "round" }), _jsx("path", { d: "M18.5 2.5a2.121 2.121 0 013 3L12 15l-4 1 1-4 9.5-9.5z", strokeLinecap: "round", strokeLinejoin: "round" })] }));
50
+ const DeleteIcon = () => (_jsx("svg", { viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", children: _jsx("path", { d: "M3 6h18M19 6v14a2 2 0 01-2 2H7a2 2 0 01-2-2V6m3 0V4a2 2 0 012-2h4a2 2 0 012 2v2", strokeLinecap: "round", strokeLinejoin: "round" }) }));
51
+ const ViewIcon = () => (_jsxs("svg", { viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", children: [_jsx("path", { d: "M1 12s4-8 11-8 11 8 11 8-4 8-11 8-11-8-11-8z", strokeLinecap: "round", strokeLinejoin: "round" }), _jsx("circle", { cx: "12", cy: "12", r: "3" })] }));
52
+ const RefreshIcon = () => (_jsxs("svg", { viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", children: [_jsx("path", { d: "M23 4v6h-6M1 20v-6h6", strokeLinecap: "round", strokeLinejoin: "round" }), _jsx("path", { d: "M3.51 9a9 9 0 0114.85-3.36L23 10M1 14l4.64 4.36A9 9 0 0020.49 15", strokeLinecap: "round", strokeLinejoin: "round" })] }));
53
+ const PrintIcon = () => (_jsxs("svg", { viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", children: [_jsx("path", { d: "M6 9V2h12v7M6 18H4a2 2 0 01-2-2v-5a2 2 0 012-2h16a2 2 0 012 2v5a2 2 0 01-2 2h-2", strokeLinecap: "round", strokeLinejoin: "round" }), _jsx("rect", { x: "6", y: "14", width: "12", height: "8" })] }));
54
+ const ErrorIcon = () => (_jsxs("svg", { viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", children: [_jsx("circle", { cx: "12", cy: "12", r: "10" }), _jsx("path", { d: "M12 8v4M12 16h.01", strokeLinecap: "round", strokeLinejoin: "round" })] }));
21
55
  export const Table = forwardRef(function TableComponent(props, ref) {
22
- const { id, data, columns, keyField = '_id', loading = false, loadingIndicator, pagination = true, paginationConfig, totalSize, remote = false, defaultSort, sort: controlledSort, filterable = false, defaultFilters, filters: controlledFilters, searchable = false, searchPlaceholder = 'Search...', defaultSearchValue = '', searchValue: controlledSearchValue, searchDebounce = 300, rowSelection, expandable, editMode = 'none', onCellEdit, exportable = false, exportFileName = 'table_export', columnToggle = false, bordered = true, striped = false, hover = true, compact = false, stickyHeader = false, maxHeight, rowClassName, rowStyle, classNames = {}, styles = {}, className, style, emptyText = 'No data available', onChange, onPageChange, onSortChange, onFilterChange, onSearch, onRowClick, onRowDoubleClick, onClearFilters, toolbar, hideToolbar = false, showFooter = false, caption, ...rest } = props;
56
+ const { id, data, columns, keyField = '_id', loading = false, loadingIndicator, pagination = true, paginationConfig, totalSize, remote = false, defaultSort, sort: controlledSort, filterable = false, defaultFilters, filters: controlledFilters, defaultShowFilters = true, showFilters: controlledShowFilters, onShowFiltersChange, showFilterToggle = true, searchable = true, searchPlaceholder = 'Search...', defaultSearchValue = '', searchValue: controlledSearchValue, searchDebounce = 300, rowSelection, expandable, editMode = 'none', onCellEdit, exportable = true, exportFileName = 'table_export', columnToggle = false, bordered = true, striped = false, hover = true, compact = false, cellPadding, stickyHeader = false, maxHeight, rowClassName, rowStyle, classNames = {}, styles = {}, className, style, emptyText = 'No data available', onChange, onPageChange, onSortChange, onFilterChange, onSearch, onRowClick, onRowDoubleClick, onClearFilters, toolbar, hideToolbar = false, showFooter = false, caption,
57
+ // Quick configuration props
58
+ isDelete = false, isEditModify, isUpdate, isExport, isSelectRow, fileName, hideExcelSheet = false,
59
+ // Quick callbacks
60
+ onSelectedRow, onUpdateItem, onPageSizeChange, onFilter, clearAllFilter,
61
+ // Dynamic configuration
62
+ dynamicStylingFields, fieldTypeConfig,
63
+ // Action column
64
+ showActionColumn, actionColumnWidth = 100, actionColumnTitle = 'Actions', actionColumnPosition = 'last', actionColumnRender, onDelete, onEdit, onView, isView = false,
65
+ // Row number
66
+ showRowNumber = false, rowNumberWidth = 50, rowNumberTitle = '#', rowNumberRender,
67
+ // Toolbar customization
68
+ toolbarPosition = 'top', toolbarLeft, toolbarRight, toolbarCenter,
69
+ // Refresh
70
+ refreshable = false, onRefresh,
71
+ // Print
72
+ printable = false, onPrint,
73
+ // Size
74
+ size = 'medium',
75
+ // Error state
76
+ error, onRetry,
77
+ // Skeleton loading
78
+ skeletonLoading = false, skeletonRowCount = 5,
79
+ // Hide header
80
+ hideHeader = false,
81
+ // Highlighted rows
82
+ highlightedRowKeys = [], highlightRowStyle, highlightRowClassName,
83
+ // Events
84
+ onRowMouseEnter, onRowMouseLeave, onCellClick, onHeaderClick, ...rest } = props;
85
+ // Resolve aliases
86
+ const resolvedExportable = isExport ?? exportable;
87
+ const resolvedExportFileName = fileName ?? exportFileName;
88
+ const resolvedIsEdit = isEditModify ?? isUpdate ?? false;
89
+ const resolvedIsView = isView;
90
+ const resolvedShowActionColumn = showActionColumn ?? (isDelete || resolvedIsEdit || resolvedIsView);
91
+ // Handle isSelectRow shorthand
92
+ const resolvedRowSelection = isSelectRow
93
+ ? {
94
+ mode: 'checkbox',
95
+ ...rowSelection,
96
+ onChange: (keys, rows) => {
97
+ rowSelection?.onChange?.(keys, rows);
98
+ onSelectedRow?.(rows);
99
+ },
100
+ }
101
+ : rowSelection;
102
+ // Size configuration
103
+ const sizeConfig = {
104
+ small: { padding: '4px 8px', fontSize: '12px' },
105
+ medium: { padding: '8px 12px', fontSize: '14px' },
106
+ large: { padding: '12px 16px', fontSize: '16px' },
107
+ };
23
108
  // Refs
24
109
  const tableRef = useRef(null);
25
110
  // State
26
111
  const [internalSearchValue, setInternalSearchValue] = useState(defaultSearchValue);
112
+ const [internalShowFilters, setInternalShowFilters] = useState(defaultShowFilters);
27
113
  const [columnToggleOpen, setColumnToggleOpen] = useState(false);
28
114
  const [columnSearch, setColumnSearch] = useState('');
115
+ // Filter visibility (controlled or uncontrolled)
116
+ const isFilterVisibilityControlled = controlledShowFilters !== undefined;
117
+ const showFilterRow = isFilterVisibilityControlled
118
+ ? controlledShowFilters
119
+ : internalShowFilters;
120
+ const handleToggleFilters = useCallback(() => {
121
+ const newValue = !showFilterRow;
122
+ if (!isFilterVisibilityControlled) {
123
+ setInternalShowFilters(newValue);
124
+ }
125
+ onShowFiltersChange?.(newValue);
126
+ }, [showFilterRow, isFilterVisibilityControlled, onShowFiltersChange]);
29
127
  const [editingCell, setEditingCell] = useState(null);
30
128
  const [editValue, setEditValue] = useState(null);
31
129
  const searchValue = controlledSearchValue ?? internalSearchValue;
@@ -58,7 +156,17 @@ export const Table = forwardRef(function TableComponent(props, ref) {
58
156
  result = paginateData(result, page, pageSize);
59
157
  }
60
158
  return result;
61
- }, [data, filters, sort, page, pageSize, debouncedSearchValue, remote, pagination, columns]);
159
+ }, [
160
+ data,
161
+ filters,
162
+ sort,
163
+ page,
164
+ pageSize,
165
+ debouncedSearchValue,
166
+ remote,
167
+ pagination,
168
+ columns,
169
+ ]);
62
170
  // Calculate total for client-side
63
171
  const calculatedTotal = useMemo(() => {
64
172
  if (remote)
@@ -82,14 +190,17 @@ export const Table = forwardRef(function TableComponent(props, ref) {
82
190
  // Handle filter
83
191
  const handleFilterChange = useCallback((field, value) => {
84
192
  setFilter(field, value);
85
- onFilterChange?.({ ...filters, [field]: value });
86
- onChange?.({ type: 'filter', filters: { ...filters, [field]: value } });
193
+ const newFilters = { ...filters, [field]: value };
194
+ onFilterChange?.(newFilters);
195
+ onFilter?.('filter', newFilters, page, pageSize);
196
+ onChange?.({ type: 'filter', filters: newFilters });
87
197
  }, [filters, setFilter, onFilterChange, onChange]);
88
198
  // Handle clear all filters
89
199
  const handleClearFilters = useCallback(() => {
90
200
  clearFilters();
91
201
  setInternalSearchValue('');
92
202
  onClearFilters?.();
203
+ clearAllFilter?.();
93
204
  onFilterChange?.({});
94
205
  onChange?.({ type: 'filter', filters: {} });
95
206
  }, [clearFilters, onClearFilters, onFilterChange, onChange]);
@@ -97,13 +208,18 @@ export const Table = forwardRef(function TableComponent(props, ref) {
97
208
  const handlePageChange = useCallback((newPage) => {
98
209
  goToPage(newPage);
99
210
  onPageChange?.(newPage, pageSize);
211
+ onPageSizeChange?.(newPage, pageSize);
100
212
  onChange?.({ type: 'pagination', pagination: { page: newPage, pageSize } });
101
- }, [goToPage, pageSize, onPageChange, onChange]);
213
+ }, [goToPage, pageSize, onPageChange, onPageSizeChange, onChange]);
102
214
  // Handle page size change
103
215
  const handlePageSizeChange = useCallback((newSize) => {
104
216
  changePageSize(newSize);
105
217
  onPageChange?.(0, newSize);
106
- onChange?.({ type: 'pagination', pagination: { page: 0, pageSize: newSize } });
218
+ onPageSizeChange?.(0, newSize);
219
+ onChange?.({
220
+ type: 'pagination',
221
+ pagination: { page: 0, pageSize: newSize },
222
+ });
107
223
  }, [changePageSize, onPageChange, onChange]);
108
224
  // Handle row click
109
225
  const handleRowClick = useCallback((row, rowIndex, e) => {
@@ -123,22 +239,45 @@ export const Table = forwardRef(function TableComponent(props, ref) {
123
239
  }
124
240
  onRowClick?.(row, rowIndex, e);
125
241
  }, [rowSelection, expandable, toggleRow, toggleExpand, onRowClick]);
242
+ // Helper to check if cell is editable and get custom editor
243
+ const getCellEditableInfo = useCallback((column, row, rowIndex, colIndex) => {
244
+ if (!column.editable) {
245
+ return { isEditable: false };
246
+ }
247
+ if (typeof column.editable === 'boolean') {
248
+ return { isEditable: column.editable };
249
+ }
250
+ // It's a function
251
+ const cellValue = getNestedValue(row, column.dataField);
252
+ const result = column.editable(cellValue, row, rowIndex, colIndex);
253
+ if (typeof result === 'boolean') {
254
+ return { isEditable: result };
255
+ }
256
+ // Result is a custom editor (ReactNode)
257
+ return { isEditable: true, customEditor: result };
258
+ }, []);
126
259
  // Handle cell edit
127
- const handleCellDoubleClick = useCallback((row, rowIndex, column, e) => {
128
- if (editMode === 'none' || !column.editable)
260
+ const handleCellDoubleClick = useCallback((row, rowIndex, column, colIndex, e) => {
261
+ if (editMode === 'none')
262
+ return;
263
+ const { isEditable } = getCellEditableInfo(column, row, rowIndex, colIndex);
264
+ if (!isEditable)
129
265
  return;
130
266
  if (editMode === 'dblclick') {
131
267
  setEditingCell({ row: rowIndex, field: column.dataField });
132
268
  setEditValue(getNestedValue(row, column.dataField));
133
269
  }
134
270
  onRowDoubleClick?.(row, rowIndex, e);
135
- }, [editMode, onRowDoubleClick]);
136
- const handleCellClick = useCallback((row, rowIndex, column) => {
137
- if (editMode !== 'click' || !column.editable)
271
+ }, [editMode, onRowDoubleClick, getCellEditableInfo]);
272
+ const handleCellClick = useCallback((row, rowIndex, column, colIndex) => {
273
+ if (editMode !== 'click')
274
+ return;
275
+ const { isEditable } = getCellEditableInfo(column, row, rowIndex, colIndex);
276
+ if (!isEditable)
138
277
  return;
139
278
  setEditingCell({ row: rowIndex, field: column.dataField });
140
279
  setEditValue(getNestedValue(row, column.dataField));
141
- }, [editMode]);
280
+ }, [editMode, getCellEditableInfo]);
142
281
  const handleCellEditComplete = useCallback((row, rowIndex, column) => {
143
282
  if (editingCell) {
144
283
  // Validate
@@ -150,15 +289,159 @@ export const Table = forwardRef(function TableComponent(props, ref) {
150
289
  return;
151
290
  }
152
291
  }
292
+ const rowId = row[keyField];
153
293
  onCellEdit?.(editValue, column.dataField, row, rowIndex);
294
+ onUpdateItem?.(editValue, column.dataField, rowId);
154
295
  }
155
296
  setEditingCell(null);
156
- }, [editingCell, editValue, onCellEdit]);
297
+ }, [editingCell, editValue, onCellEdit, onUpdateItem, keyField]);
298
+ // Helper to get nested value from object
299
+ const getNestedValueLocal = (obj, path) => {
300
+ return path.split('.').reduce((acc, key) => acc?.[key], obj);
301
+ };
302
+ // Process field value based on fieldTypeConfig (matching reference implementation)
303
+ const processFieldValue = useCallback((value, dataField, row) => {
304
+ const config = fieldTypeConfig?.[dataField];
305
+ const fieldType = config?.type || 'string';
306
+ switch (fieldType) {
307
+ case 'array':
308
+ if (config?.fields && config.fields.length > 0) {
309
+ // Array of objects with specific fields to extract
310
+ if (!Array.isArray(value))
311
+ return value || '';
312
+ return value
313
+ .slice(0, config.maxItems || value.length)
314
+ .map((item) => {
315
+ if (typeof item === 'object' && config.fields) {
316
+ // Extract only specified fields from the object
317
+ return config.fields
318
+ .map((field) => item[field])
319
+ .filter(Boolean)
320
+ .join(', ');
321
+ }
322
+ else if (typeof item === 'string') {
323
+ return item;
324
+ }
325
+ return '';
326
+ })
327
+ .filter(Boolean)
328
+ .join(config.separator || '; ');
329
+ }
330
+ else {
331
+ // Default array handling
332
+ if (!Array.isArray(value))
333
+ return value || '';
334
+ return value
335
+ .map((item) => typeof item === 'object' ? JSON.stringify(item) : item)
336
+ .join('; ');
337
+ }
338
+ case 'object':
339
+ if (!value || typeof value !== 'object')
340
+ return '';
341
+ const fields = config?.fields || config?.keys || [];
342
+ const labelMap = config?.labelMap || {};
343
+ if (fields.length > 0) {
344
+ // Extract specific fields with optional label mapping
345
+ return fields
346
+ .map((field) => {
347
+ const nestedValue = getNestedValueLocal(value, field);
348
+ if (nestedValue !== undefined && nestedValue !== null) {
349
+ const label = labelMap[field] || field;
350
+ return `${label}: ${nestedValue}`;
351
+ }
352
+ return null;
353
+ })
354
+ .filter(Boolean)
355
+ .join(', ');
356
+ }
357
+ else {
358
+ // Default object handling
359
+ return Object.entries(value)
360
+ .map(([key, val]) => typeof val === 'boolean'
361
+ ? `${key}: ${val ? 'Yes' : 'No'}`
362
+ : `${key}: ${val}`)
363
+ .join(', ');
364
+ }
365
+ case 'date':
366
+ if (!value)
367
+ return '';
368
+ try {
369
+ const date = new Date(value);
370
+ const format = config?.dateFormat || 'YYYY-MM-DD HH:mm:ss';
371
+ // Simple date formatting
372
+ return date.toISOString().slice(0, 19).replace('T', ' ');
373
+ }
374
+ catch {
375
+ return String(value);
376
+ }
377
+ case 'number':
378
+ return value !== undefined && value !== null
379
+ ? String(Number(value))
380
+ : '';
381
+ case 'boolean':
382
+ return typeof value === 'boolean' ? (value ? 'Yes' : 'No') : '';
383
+ case 'string':
384
+ case 'text':
385
+ default:
386
+ if (typeof value === 'boolean')
387
+ return value ? 'Yes' : 'No';
388
+ return value !== undefined && value !== null ? String(value) : '';
389
+ }
390
+ }, [fieldTypeConfig]);
157
391
  // Handle export
158
392
  const handleExport = useCallback(() => {
159
- const exportData = remote ? data : filterData(data, filters, columns, debouncedSearchValue);
160
- exportToCSV(exportData, visibleColumns, exportFileName);
161
- }, [data, filters, columns, debouncedSearchValue, visibleColumns, exportFileName, remote]);
393
+ const exportData = remote
394
+ ? data
395
+ : filterData(data, filters, columns, debouncedSearchValue);
396
+ // Filter columns based on hideExcelSheet array and csvExport !== false
397
+ let exportColumns = visibleColumns.filter((col) => col.csvExport !== false);
398
+ if (Array.isArray(hideExcelSheet)) {
399
+ exportColumns = exportColumns.filter((col) => !hideExcelSheet.includes(col.dataField));
400
+ }
401
+ // Also filter based on fieldTypeConfig hideFromExport or csvExport
402
+ if (fieldTypeConfig) {
403
+ exportColumns = exportColumns.filter((col) => {
404
+ const config = fieldTypeConfig[col.dataField];
405
+ if (config?.hideFromExport)
406
+ return false;
407
+ if (config?.csvExport === false)
408
+ return false;
409
+ return true;
410
+ });
411
+ }
412
+ // Create enhanced columns with export formatters
413
+ const enhancedColumns = exportColumns.map((col) => {
414
+ const config = fieldTypeConfig?.[col.dataField];
415
+ // If column already has csvFormatter, use it
416
+ if (col.csvFormatter) {
417
+ return col;
418
+ }
419
+ // If config has exportFormatter, use it
420
+ if (config?.exportFormatter) {
421
+ return { ...col, csvFormatter: config.exportFormatter };
422
+ }
423
+ // If config has type, create formatter based on type
424
+ if (config?.type) {
425
+ return {
426
+ ...col,
427
+ csvFormatter: (cell, row) => processFieldValue(cell, col.dataField, row),
428
+ };
429
+ }
430
+ return col;
431
+ });
432
+ exportToCSV(exportData, enhancedColumns, resolvedExportFileName);
433
+ }, [
434
+ data,
435
+ filters,
436
+ columns,
437
+ debouncedSearchValue,
438
+ visibleColumns,
439
+ hideExcelSheet,
440
+ fieldTypeConfig,
441
+ processFieldValue,
442
+ resolvedExportFileName,
443
+ remote,
444
+ ]);
162
445
  // Handle checkbox change
163
446
  const handleCheckboxChange = useCallback((row, e) => {
164
447
  e.stopPropagation();
@@ -190,8 +473,27 @@ export const Table = forwardRef(function TableComponent(props, ref) {
190
473
  // Render cell content
191
474
  const renderCellContent = useCallback((row, column, rowIndex, colIndex) => {
192
475
  const value = getNestedValue(row, column.dataField);
193
- const isEditing = editingCell?.row === rowIndex && editingCell?.field === column.dataField;
476
+ const isEditing = editingCell?.row === rowIndex &&
477
+ editingCell?.field === column.dataField;
194
478
  if (isEditing) {
479
+ // Check for custom editorRenderer
480
+ if (column.editorRenderer) {
481
+ const editorProps = {
482
+ value: editValue,
483
+ onUpdate: (newValue) => {
484
+ setEditValue(newValue);
485
+ handleCellEditComplete(row, rowIndex, column);
486
+ },
487
+ onCancel: () => setEditingCell(null),
488
+ onBlur: () => handleCellEditComplete(row, rowIndex, column),
489
+ row,
490
+ column,
491
+ rowIndex,
492
+ columnIndex: colIndex,
493
+ };
494
+ return column.editorRenderer(editorProps, editValue, row, column, rowIndex, colIndex);
495
+ }
496
+ // Default editor
195
497
  return (_jsx(CellEditor, { type: column.editorType === 'number' ? 'number' : 'text', value: editValue ?? '', onChange: (e) => setEditValue(e.target.value), onBlur: () => handleCellEditComplete(row, rowIndex, column), onKeyDown: (e) => {
196
498
  if (e.key === 'Enter') {
197
499
  handleCellEditComplete(row, rowIndex, column);
@@ -199,7 +501,7 @@ export const Table = forwardRef(function TableComponent(props, ref) {
199
501
  if (e.key === 'Escape') {
200
502
  setEditingCell(null);
201
503
  }
202
- }, autoFocus: true }));
504
+ }, className: column.editorClasses, style: column.editorStyle, autoFocus: true }));
203
505
  }
204
506
  if (column.formatter) {
205
507
  return column.formatter(value, row, rowIndex, colIndex);
@@ -227,7 +529,25 @@ export const Table = forwardRef(function TableComponent(props, ref) {
227
529
  if (toolbar)
228
530
  return toolbar;
229
531
  const hasFilters = Object.keys(filters).length > 0 || searchValue;
230
- return (_jsxs(Toolbar, { className: classNames.toolbar, style: styles.toolbar, children: [_jsxs(ToolbarGroup, { children: [searchable && (_jsxs(SearchInput, { children: [_jsx(SearchIcon, {}), _jsx("input", { type: "text", value: searchValue, onChange: (e) => handleSearchChange(e.target.value), placeholder: searchPlaceholder })] })), hasFilters && (_jsxs(ToolbarButton, { onClick: handleClearFilters, children: [_jsx(CloseIcon, {}), "Clear Filters"] }))] }), _jsxs(ToolbarGroup, { children: [exportable && (_jsxs(ToolbarButton, { onClick: handleExport, children: [_jsx(DownloadIcon, {}), "Export"] })), columnToggle && (_jsxs("div", { style: { position: 'relative' }, children: [_jsxs(ToolbarButton, { "$active": columnToggleOpen, onClick: () => setColumnToggleOpen(!columnToggleOpen), children: [_jsx(ColumnsIcon, {}), "Columns"] }), columnToggleOpen && (_jsxs(ColumnTogglePanel, { children: [_jsxs(ColumnToggleHeader, { children: [_jsx("span", { children: "Toggle Columns" }), _jsx("button", { onClick: () => setColumnToggleOpen(false), children: _jsx(CloseIcon, {}) })] }), _jsx(ColumnToggleSearch, { children: _jsx("input", { type: "text", value: columnSearch, onChange: (e) => setColumnSearch(e.target.value), placeholder: "Search columns..." }) }), _jsx(ColumnToggleList, { children: filteredToggleColumns.map((column) => (_jsxs(ColumnToggleItem, { children: [_jsx("input", { type: "checkbox", checked: !isColumnHidden(column.dataField), onChange: () => toggleColumn(column.dataField) }), _jsx("span", { children: column.text })] }, column.dataField))) })] }))] }))] })] }));
532
+ return (_jsxs(Toolbar, { className: classNames.toolbar, style: styles.toolbar, children: [_jsxs(ToolbarGroup, { children: [toolbarLeft, searchable && (_jsxs(SearchInput, { children: [_jsx(SearchIcon, {}), _jsx("input", { type: "text", value: searchValue, onChange: (e) => handleSearchChange(e.target.value), placeholder: searchPlaceholder })] })), searchable && (_jsx(ToolbarButton, { onClick: () => handleSearchChange(''), disabled: !searchValue, style: { opacity: searchValue ? 1 : 0.6 }, children: "Clear" })), _jsx(ToolbarButton, { onClick: handleClearFilters, disabled: !hasFilters, style: { opacity: hasFilters ? 1 : 0.6 }, children: "Clear all filters" }), resolvedExportable && hideExcelSheet !== true && (_jsxs(ToolbarButton, { onClick: handleExport, children: [_jsx(DownloadIcon, {}), "Export CSV"] })), showFilterToggle && (_jsxs("div", { style: { position: 'relative' }, children: [_jsx(Tooltip, { content: "Show/Hide Columns", position: "bottom", children: _jsx(ToolbarButton, { "$active": columnToggleOpen, onClick: () => setColumnToggleOpen(!columnToggleOpen), "aria-label": "Toggle column visibility", style: { padding: '0 8px' }, children: _jsx(FilterIcon, {}) }) }), columnToggleOpen && (_jsxs(ColumnTogglePanel, { children: [_jsxs(ColumnToggleHeader, { children: [_jsx("span", { children: "Show/Hide Columns" }), _jsx("button", { onClick: () => setColumnToggleOpen(false), children: _jsx(CloseIcon, {}) })] }), _jsx(ColumnToggleSearch, { children: _jsx("input", { type: "text", value: columnSearch, onChange: (e) => setColumnSearch(e.target.value), placeholder: "Search columns..." }) }), _jsxs(ColumnToggleList, { children: [_jsxs(ColumnToggleItem, { style: {
533
+ borderBottom: '1px solid #e5e7eb',
534
+ paddingBottom: 8,
535
+ marginBottom: 4,
536
+ }, children: [_jsx("input", { type: "checkbox", checked: filteredToggleColumns.length > 0 &&
537
+ filteredToggleColumns.every((col) => !isColumnHidden(col.dataField)), onChange: (e) => {
538
+ filteredToggleColumns.forEach((col) => {
539
+ if (e.target.checked) {
540
+ if (isColumnHidden(col.dataField)) {
541
+ toggleColumn(col.dataField);
542
+ }
543
+ }
544
+ else {
545
+ if (!isColumnHidden(col.dataField)) {
546
+ toggleColumn(col.dataField);
547
+ }
548
+ }
549
+ });
550
+ } }), _jsx("span", { style: { fontWeight: 600 }, children: "Select All" })] }), filteredToggleColumns.map((column) => (_jsxs(ColumnToggleItem, { children: [_jsx("input", { type: "checkbox", checked: !isColumnHidden(column.dataField), onChange: () => toggleColumn(column.dataField) }), _jsx("span", { children: column.text })] }, column.dataField)))] })] }))] }))] }), toolbarCenter, _jsxs(ToolbarGroup, { children: [refreshable && (_jsxs(ToolbarButton, { onClick: onRefresh, children: [_jsx(RefreshIcon, {}), "Refresh"] })), printable && (_jsxs(ToolbarButton, { onClick: onPrint, children: [_jsx(PrintIcon, {}), "Print"] })), columnToggle && (_jsxs("div", { style: { position: 'relative' }, children: [_jsxs(ToolbarButton, { "$active": columnToggleOpen, onClick: () => setColumnToggleOpen(!columnToggleOpen), children: [_jsx(ColumnsIcon, {}), "Columns"] }), columnToggleOpen && (_jsxs(ColumnTogglePanel, { children: [_jsxs(ColumnToggleHeader, { children: [_jsx("span", { children: "Toggle Columns" }), _jsx("button", { onClick: () => setColumnToggleOpen(false), children: _jsx(CloseIcon, {}) })] }), _jsx(ColumnToggleSearch, { children: _jsx("input", { type: "text", value: columnSearch, onChange: (e) => setColumnSearch(e.target.value), placeholder: "Search columns..." }) }), _jsx(ColumnToggleList, { children: filteredToggleColumns.map((column) => (_jsxs(ColumnToggleItem, { children: [_jsx("input", { type: "checkbox", checked: !isColumnHidden(column.dataField), onChange: () => toggleColumn(column.dataField) }), _jsx("span", { children: column.text })] }, column.dataField))) })] }))] })), toolbarRight] })] }));
231
551
  };
232
552
  // Render pagination
233
553
  const renderPagination = () => {
@@ -287,28 +607,103 @@ export const Table = forwardRef(function TableComponent(props, ref) {
287
607
  }
288
608
  } })] }))] }));
289
609
  };
290
- // Has any filter active
291
- const hasFilters = filterable && columns.some((c) => c.filter !== false);
292
- return (_jsxs(TableRoot, { ref: ref, "$bordered": bordered, "$compact": compact, className: className || classNames.root, style: { ...styles.root, ...style, position: 'relative' }, "aria-label": rest['aria-label'], "aria-labelledby": rest['aria-labelledby'], children: [loading && (_jsx(LoadingOverlay, { className: classNames.loading, style: styles.loading, children: loadingIndicator || _jsx(LoadingSpinner, {}) })), renderToolbar(), _jsx(TableWrapper, { "$maxHeight": maxHeight, "$stickyHeader": stickyHeader, className: classNames.wrapper, style: styles.wrapper, children: _jsxs(StyledTable, { ref: tableRef, "$striped": striped, "$hover": hover, "$compact": compact, role: "grid", children: [caption && _jsx("caption", { className: "sr-only", children: caption }), _jsxs(TableHeader, { "$sticky": stickyHeader, className: classNames.header, style: styles.header, children: [_jsxs(HeaderRow, { className: classNames.headerRow, style: styles.headerRow, children: [rowSelection?.mode === 'checkbox' && (_jsx(HeaderCell, { "$align": "center", "$sortable": false, "$compact": compact, "$width": rowSelection.columnWidth || 40, children: !rowSelection.hideSelectAll && (_jsx(Checkbox, { checked: isAllSelected, ref: (el) => {
293
- if (el)
294
- el.indeterminate = isIndeterminate;
295
- }, onChange: handleSelectAllChange })) })), expandable && (_jsx(HeaderCell, { "$align": "center", "$sortable": false, "$compact": compact, "$width": expandable.columnWidth || 40 })), visibleColumns.map((column, colIndex) => (_jsxs(HeaderCell, { "$align": column.headerAlign || column.align || 'left', "$sortable": !!column.sort, "$compact": compact, "$width": column.width, "$minWidth": column.minWidth, "$pinned": column.pinned, className: column.headerClasses || classNames.headerCell, style: typeof column.headerStyle === 'function'
610
+ // Check if any columns have filters
611
+ const hasFilterableColumns = filterable ||
612
+ columns.some((c) => typeof c.filter === 'function' ||
613
+ c.filterComponent ||
614
+ c.filter === true);
615
+ // Should show filter row - check if there are filterable columns AND filters are visible
616
+ const shouldShowFilterRow = hasFilterableColumns && showFilterRow;
617
+ return (_jsxs(TableRoot, { ref: ref, "$bordered": bordered, "$compact": compact, className: className || classNames.root, style: { ...styles.root, ...style, position: 'relative' }, "aria-label": rest['aria-label'], "aria-labelledby": rest['aria-labelledby'], children: [loading && (_jsx(LoadingOverlay, { className: classNames.loading, style: styles.loading, children: loadingIndicator || _jsx(LoadingSpinner, {}) })), renderToolbar(), _jsx(TableWrapper, { "$maxHeight": maxHeight, "$stickyHeader": stickyHeader, className: classNames.wrapper, style: styles.wrapper, children: _jsxs(StyledTable, { ref: tableRef, "$striped": striped, "$hover": hover, "$compact": compact, role: "grid", children: [caption && _jsx("caption", { className: "sr-only", children: caption }), _jsx(TableHeader, { "$sticky": stickyHeader, className: classNames.header, style: styles.header, children: _jsxs(HeaderRow, { className: classNames.headerRow, style: styles.headerRow, children: [rowSelection?.mode === 'checkbox' && (_jsx(HeaderCell, { "$align": "center", "$sortable": false, "$compact": compact, "$width": rowSelection.columnWidth || 40, children: !rowSelection.hideSelectAll && (_jsx(Checkbox, { checked: isAllSelected, ref: (el) => {
618
+ if (el)
619
+ el.indeterminate = isIndeterminate;
620
+ }, onChange: handleSelectAllChange })) })), expandable && (_jsx(HeaderCell, { "$align": "center", "$sortable": false, "$compact": compact, "$width": expandable.columnWidth || 40 })), showRowNumber && (_jsx(HeaderCell, { "$align": "center", "$sortable": false, "$compact": compact, "$width": rowNumberWidth, children: rowNumberTitle })), visibleColumns.map((column, colIndex) => {
621
+ // Determine if column has a filter
622
+ const hasColumnFilter = typeof column.filter === 'function' ||
623
+ column.filter === true ||
624
+ column.filterComponent ||
625
+ column.filterRenderer;
626
+ // Get the filter component
627
+ const FilterComponent = hasColumnFilter
628
+ ? (typeof column.filter === 'function'
629
+ ? column.filter
630
+ : null) ||
631
+ column.filterComponent ||
632
+ getFilterComponent(column.filterType || 'text')
633
+ : null;
634
+ const onFilter = (value) => handleFilterChange(column.dataField, value);
635
+ return (_jsx(HeaderCell, { "$align": column.headerAlign || column.align || 'left', "$sortable": !!column.sort, "$compact": compact, "$width": column.width, "$minWidth": column.minWidth, "$pinned": column.pinned, "$customClass": !!column.headerClasses, className: [column.headerClasses, classNames.headerCell]
636
+ .filter(Boolean)
637
+ .join(' '), style: typeof column.headerStyle === 'function'
296
638
  ? column.headerStyle(column)
297
- : column.headerStyle || styles.headerCell, onClick: () => handleSortClick(column), role: "columnheader", "aria-sort": sort.field === column.dataField
639
+ : column.headerStyle || styles.headerCell, role: "columnheader", "aria-sort": sort.field === column.dataField
298
640
  ? sort.order === 'asc'
299
641
  ? 'ascending'
300
642
  : sort.order === 'desc'
301
643
  ? 'descending'
302
644
  : 'none'
303
- : undefined, children: [column.headerFormatter
304
- ? column.headerFormatter(column, colIndex)
305
- : column.headerText || column.text, column.sort && (_jsxs(SortIcon, { "$active": sort.field === column.dataField, "$direction": sort.field === column.dataField ? sort.order || undefined : undefined, children: [_jsx(SortUpIcon, {}), _jsx(SortDownIcon, {})] }))] }, column.dataField)))] }), hasFilters && (_jsxs(FilterRow, { children: [rowSelection?.mode === 'checkbox' && _jsx(FilterCell, { "$compact": compact }), expandable && _jsx(FilterCell, { "$compact": compact }), visibleColumns.map((column) => {
306
- const FilterComponent = column.filterComponent ||
307
- getFilterComponent(column.filterType || 'text');
308
- return (_jsx(FilterCell, { "$compact": compact, children: column.filter !== false && (_jsx(FilterComponent, { column: column, value: filters[column.dataField], onChange: (value) => handleFilterChange(column.dataField, value), onClear: () => handleFilterChange(column.dataField, null) })) }, column.dataField));
309
- })] }))] }), _jsx(TableBody, { className: classNames.body, style: styles.body, children: processedData.length === 0 ? (_jsx("tr", { children: _jsx("td", { colSpan: visibleColumns.length +
645
+ : undefined, children: (() => {
646
+ // Check visibility props (default to true if not specified)
647
+ const headerStyleObj = typeof column.headerStyle === 'function'
648
+ ? column.headerStyle(column)
649
+ : column.headerStyle;
650
+ // isHeaderTitle: show title (default true, false to hide)
651
+ const showTitle = column.isHeaderTitle !== false &&
652
+ column.hideHeaderText !== true &&
653
+ !(headerStyleObj && headerStyleObj.fontSize === 0);
654
+ // isHeaderFilterComp: show filter (default true)
655
+ const showFilter = column.isHeaderFilterComp !== false &&
656
+ shouldShowFilterRow &&
657
+ hasColumnFilter &&
658
+ FilterComponent;
659
+ // isHeaderSort: show sort icon (default true)
660
+ const showSort = column.isHeaderSort !== false && column.sort;
661
+ return (_jsxs("div", { style: {
662
+ display: 'flex',
663
+ flexDirection: 'column',
664
+ gap: 4,
665
+ width: '100%',
666
+ }, children: [showTitle && (_jsx("span", { style: {
667
+ color: 'white',
668
+ fontWeight: 600,
669
+ fontSize: 12,
670
+ whiteSpace: 'nowrap',
671
+ cursor: showSort ? 'pointer' : 'default',
672
+ }, onClick: () => showSort && handleSortClick(column), children: column.headerFormatter
673
+ ? column.headerFormatter(column, colIndex)
674
+ : column.headerText || column.text })), (showFilter || showSort) && (_jsxs("div", { style: {
675
+ display: 'flex',
676
+ alignItems: 'center',
677
+ justifyContent: 'center',
678
+ gap: 6,
679
+ width: '100%',
680
+ minHeight: 24,
681
+ }, children: [showFilter && (_jsx("div", { style: {
682
+ width: showSort ? '80%' : '100%',
683
+ minWidth: 0,
684
+ flexShrink: 1,
685
+ display: 'flex',
686
+ alignItems: 'center',
687
+ }, onClick: (e) => e.stopPropagation(), children: column.filterRenderer ? (column.filterRenderer(onFilter, column)) : (_jsx(FilterComponent, { column: column, value: filters[column.dataField], onChange: onFilter, onClear: () => handleFilterChange(column.dataField, null) })) })), showSort && (_jsx("div", { style: {
688
+ width: showFilter ? '20%' : '100%',
689
+ minWidth: 24,
690
+ height: 24,
691
+ display: 'flex',
692
+ alignItems: 'center',
693
+ justifyContent: 'center',
694
+ flexShrink: 0,
695
+ cursor: 'pointer',
696
+ }, onClick: () => handleSortClick(column), children: column.sortCaret ? (column.sortCaret(sort.field === column.dataField
697
+ ? sort.order
698
+ : null, column)) : (_jsx(DefaultSortCaret, { order: sort.field === column.dataField
699
+ ? sort.order
700
+ : null, column: column })) }))] }))] }));
701
+ })() }, column.dataField));
702
+ }), resolvedShowActionColumn && (_jsx(HeaderCell, { "$align": "center", "$sortable": false, "$compact": compact, "$width": actionColumnWidth, children: "Actions" }))] }) }), _jsx(TableBody, { className: classNames.body, style: styles.body, children: processedData.length === 0 ? (_jsx("tr", { children: _jsx("td", { colSpan: visibleColumns.length +
310
703
  (rowSelection?.mode === 'checkbox' ? 1 : 0) +
311
- (expandable ? 1 : 0), children: _jsxs(EmptyState, { className: classNames.empty, style: styles.empty, children: [_jsx(EmptyIcon, {}), _jsx("span", { children: emptyText })] }) }) })) : (processedData.map((row, rowIndex) => {
704
+ (expandable ? 1 : 0) +
705
+ (showRowNumber ? 1 : 0) +
706
+ (resolvedShowActionColumn ? 1 : 0), children: _jsxs(EmptyState, { className: classNames.empty, style: styles.empty, children: [_jsx(EmptyIcon, {}), _jsx("span", { children: emptyText })] }) }) })) : (processedData.map((row, rowIndex) => {
312
707
  const rowKey = getRowKey(row);
313
708
  const rowSelected = isSelected(rowKey);
314
709
  const rowExpanded = isExpanded(rowKey);
@@ -328,30 +723,99 @@ export const Table = forwardRef(function TableComponent(props, ref) {
328
723
  return (_jsxs(React.Fragment, { children: [_jsxs(TableRow, { "$selected": rowSelected, "$clickable": !!onRowClick ||
329
724
  rowSelection?.mode === 'single' ||
330
725
  expandable?.expandRowByClick === true, "$disabled": !!checkboxProps?.disabled, className: `${classNames.row || ''} ${rowClass || ''} ${rowSelected
331
- ? typeof rowSelection?.selectedRowClassName === 'function'
726
+ ? typeof rowSelection?.selectedRowClassName ===
727
+ 'function'
332
728
  ? rowSelection.selectedRowClassName(row)
333
729
  : rowSelection?.selectedRowClassName || ''
334
- : ''}`, style: { ...styles.row, ...rowStyles, ...selectedStyle }, onClick: (e) => handleRowClick(row, rowIndex, e), onDoubleClick: (e) => handleCellDoubleClick(row, rowIndex, visibleColumns[0], e), role: "row", "aria-selected": rowSelected, children: [rowSelection?.mode === 'checkbox' && (_jsx(TableCell, { "$align": "center", "$compact": compact, children: _jsx(Checkbox, { checked: rowSelected, disabled: checkboxProps?.disabled, onChange: (e) => handleCheckboxChange(row, e), onClick: (e) => e.stopPropagation() }) })), expandable && (_jsx(TableCell, { "$align": "center", "$compact": compact, children: isExpandable && (_jsx(ExpandButton, { "$expanded": rowExpanded, onClick: (e) => handleExpandClick(row, e), children: expandable.expandIcon ? (expandable.expandIcon({
730
+ : ''}`, style: { ...styles.row, ...rowStyles, ...selectedStyle }, onClick: (e) => handleRowClick(row, rowIndex, e), onDoubleClick: (e) => handleCellDoubleClick(row, rowIndex, visibleColumns[0], 0, e), role: "row", "aria-selected": rowSelected, children: [rowSelection?.mode === 'checkbox' && (_jsx(TableCell, { "$align": "center", "$compact": compact, "$padding": cellPadding, children: _jsx(Checkbox, { checked: rowSelected, disabled: checkboxProps?.disabled, onChange: (e) => handleCheckboxChange(row, e), onClick: (e) => e.stopPropagation() }) })), expandable && (_jsx(TableCell, { "$align": "center", "$compact": compact, "$padding": cellPadding, children: isExpandable && (_jsx(ExpandButton, { "$expanded": rowExpanded, onClick: (e) => handleExpandClick(row, e), children: expandable.expandIcon ? (expandable.expandIcon({
335
731
  expanded: rowExpanded,
336
732
  row,
337
733
  onExpand: () => toggleExpand(row),
338
- })) : (_jsx(ExpandIcon, {})) })) })), visibleColumns.map((column, colIndex) => {
734
+ })) : (_jsx(ExpandIcon, {})) })) })), showRowNumber && (_jsx(TableCell, { "$align": "center", "$compact": compact, "$padding": cellPadding, style: {
735
+ width: rowNumberWidth,
736
+ color: '#6b7280',
737
+ fontWeight: 500,
738
+ }, children: rowNumberRender
739
+ ? rowNumberRender(rowIndex + 1, row)
740
+ : rowIndex + 1 + page * pageSize })), visibleColumns.map((column, colIndex) => {
339
741
  const cellClass = typeof column.classes === 'function'
340
- ? column.classes(getNestedValue(row, column.dataField), row, rowIndex)
742
+ ? column.classes(getNestedValue(row, column.dataField), row, rowIndex, colIndex)
341
743
  : column.classes;
342
744
  const cellStyle = typeof column.style === 'function'
343
- ? column.style(getNestedValue(row, column.dataField), row, rowIndex)
745
+ ? column.style(getNestedValue(row, column.dataField), row, rowIndex, colIndex)
344
746
  : column.style;
345
- return (_jsx(TableCell, { "$align": column.align || 'left', "$compact": compact, "$pinned": column.pinned, className: cellClass || classNames.cell, style: { ...styles.cell, ...cellStyle }, onClick: () => handleCellClick(row, rowIndex, column), onDoubleClick: (e) => handleCellDoubleClick(row, rowIndex, column, e), role: "gridcell", children: column.editable && editMode !== 'none' ? (_jsx(EditableCell, { "$editing": editingCell?.row === rowIndex &&
346
- editingCell?.field === column.dataField, children: renderCellContent(row, column, rowIndex, colIndex) })) : (renderCellContent(row, column, rowIndex, colIndex)) }, column.dataField));
347
- })] }), expandable && rowExpanded && isExpandable && (_jsx(ExpandedRow, { children: _jsx(ExpandedCell, { colSpan: visibleColumns.length +
747
+ return (_jsx(TableCell, { "$align": column.align || 'left', "$compact": compact, "$padding": cellPadding, "$pinned": column.pinned, className: cellClass || classNames.cell, style: { ...styles.cell, ...cellStyle }, onClick: () => handleCellClick(row, rowIndex, column, colIndex), onDoubleClick: (e) => handleCellDoubleClick(row, rowIndex, column, colIndex, e), role: "gridcell", children: (() => {
748
+ const editInfo = getCellEditableInfo(column, row, rowIndex, colIndex);
749
+ if (editInfo.isEditable &&
750
+ editMode !== 'none') {
751
+ // Check for custom editor
752
+ if (editInfo.customEditor) {
753
+ return editInfo.customEditor;
754
+ }
755
+ return (_jsx(EditableCell, { "$editing": editingCell?.row === rowIndex &&
756
+ editingCell?.field === column.dataField, children: renderCellContent(row, column, rowIndex, colIndex) }));
757
+ }
758
+ return renderCellContent(row, column, rowIndex, colIndex);
759
+ })() }, column.dataField));
760
+ }), resolvedShowActionColumn && (_jsx(TableCell, { "$align": "center", "$compact": compact, "$padding": cellPadding, style: {
761
+ width: actionColumnWidth,
762
+ whiteSpace: 'nowrap',
763
+ }, children: actionColumnRender ? (actionColumnRender(row, rowIndex)) : (_jsxs("div", { style: {
764
+ display: 'flex',
765
+ gap: '4px',
766
+ justifyContent: 'center',
767
+ }, children: [resolvedIsView && (_jsx("button", { onClick: (e) => {
768
+ e.stopPropagation();
769
+ onView?.(row, rowIndex);
770
+ }, style: {
771
+ padding: '4px 8px',
772
+ background: '#10b981',
773
+ color: 'white',
774
+ border: 'none',
775
+ borderRadius: '4px',
776
+ cursor: 'pointer',
777
+ display: 'flex',
778
+ alignItems: 'center',
779
+ gap: '4px',
780
+ fontSize: '12px',
781
+ }, title: "View", children: _jsx(ViewIcon, {}) })), resolvedIsEdit && (_jsx("button", { onClick: (e) => {
782
+ e.stopPropagation();
783
+ onEdit?.(row, rowIndex);
784
+ }, style: {
785
+ padding: '4px 8px',
786
+ background: '#3b82f6',
787
+ color: 'white',
788
+ border: 'none',
789
+ borderRadius: '4px',
790
+ cursor: 'pointer',
791
+ display: 'flex',
792
+ alignItems: 'center',
793
+ gap: '4px',
794
+ fontSize: '12px',
795
+ }, title: "Edit", children: _jsx(EditIcon, {}) })), isDelete && (_jsx("button", { onClick: (e) => {
796
+ e.stopPropagation();
797
+ onDelete?.(row, rowIndex);
798
+ }, style: {
799
+ padding: '4px 8px',
800
+ background: '#ef4444',
801
+ color: 'white',
802
+ border: 'none',
803
+ borderRadius: '4px',
804
+ cursor: 'pointer',
805
+ display: 'flex',
806
+ alignItems: 'center',
807
+ gap: '4px',
808
+ fontSize: '12px',
809
+ }, title: "Delete", children: _jsx(DeleteIcon, {}) }))] })) }))] }), expandable && rowExpanded && isExpandable && (_jsx(ExpandedRow, { children: _jsx(ExpandedCell, { colSpan: visibleColumns.length +
348
810
  (rowSelection?.mode === 'checkbox' ? 1 : 0) +
349
- 1, children: expandable.expandedRowRender?.(row, rowIndex, rowExpanded) }) }))] }, rowKey));
350
- })) }), showFooter && (_jsx(TableFooter, { className: classNames.footer, style: styles.footer, children: _jsxs(FooterRow, { className: classNames.footerRow, style: styles.footerRow, children: [rowSelection?.mode === 'checkbox' && (_jsx(FooterCell, { "$align": "center", "$compact": compact })), expandable && _jsx(FooterCell, { "$align": "center", "$compact": compact }), visibleColumns.map((column) => (_jsx(FooterCell, { "$align": column.align || 'left', "$compact": compact, className: classNames.footerCell, style: styles.footerCell, children: typeof column.footer === 'function'
811
+ (expandable ? 1 : 0) +
812
+ (showRowNumber ? 1 : 0) +
813
+ (resolvedShowActionColumn ? 1 : 0), children: expandable.expandedRowRender?.(row, rowIndex, rowExpanded) }) }))] }, rowKey));
814
+ })) }), showFooter && (_jsx(TableFooter, { className: classNames.footer, style: styles.footer, children: _jsxs(FooterRow, { className: classNames.footerRow, style: styles.footerRow, children: [rowSelection?.mode === 'checkbox' && (_jsx(FooterCell, { "$align": "center", "$compact": compact })), expandable && (_jsx(FooterCell, { "$align": "center", "$compact": compact })), showRowNumber && (_jsx(FooterCell, { "$align": "center", "$compact": compact })), visibleColumns.map((column) => (_jsx(FooterCell, { "$align": column.align || 'left', "$compact": compact, className: classNames.footerCell, style: styles.footerCell, children: typeof column.footer === 'function'
351
815
  ? column.footer(column, data)
352
816
  : column.footerFormatter
353
817
  ? column.footerFormatter(column, data)
354
- : column.footer }, column.dataField)))] }) }))] }) }), renderPagination()] }));
818
+ : column.footer }, column.dataField))), resolvedShowActionColumn && (_jsx(FooterCell, { "$align": "center", "$compact": compact }))] }) }))] }) }), renderPagination()] }));
355
819
  });
356
820
  Table.displayName = 'Table';
357
821
  export default Table;