@rakeyshgidwani/roger-ui-bank-theme-stan-design 0.1.4 → 0.1.5

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.
Files changed (164) hide show
  1. package/CHANGELOG.md +1 -1
  2. package/dist/index.d.ts +131 -131
  3. package/dist/index.esm.js +148 -148
  4. package/dist/index.js +148 -148
  5. package/dist/styles.css +1 -1
  6. package/package.json +1 -1
  7. package/src/components/ui/accessibility-demo.tsx +271 -0
  8. package/src/components/ui/advanced-component-architecture-demo.tsx +916 -0
  9. package/src/components/ui/advanced-transition-system-demo.tsx +670 -0
  10. package/src/components/ui/advanced-transition-system.tsx +395 -0
  11. package/src/components/ui/animation/animated-container.tsx +166 -0
  12. package/src/components/ui/animation/index.ts +19 -0
  13. package/src/components/ui/animation/staggered-container.tsx +68 -0
  14. package/src/components/ui/animation-demo.tsx +250 -0
  15. package/src/components/ui/badge.tsx +33 -0
  16. package/src/components/ui/battery-conscious-animation-demo.tsx +568 -0
  17. package/src/components/ui/border-radius-shadow-demo.tsx +187 -0
  18. package/src/components/ui/button.tsx +36 -0
  19. package/src/components/ui/card.tsx +207 -0
  20. package/src/components/ui/checkbox.tsx +30 -0
  21. package/src/components/ui/color-preview.tsx +411 -0
  22. package/src/components/ui/data-display/chart.tsx +653 -0
  23. package/src/components/ui/data-display/data-grid-simple.tsx +76 -0
  24. package/src/components/ui/data-display/data-grid.tsx +680 -0
  25. package/src/components/ui/data-display/list.tsx +456 -0
  26. package/src/components/ui/data-display/table.tsx +482 -0
  27. package/src/components/ui/data-display/timeline.tsx +441 -0
  28. package/src/components/ui/data-display/tree.tsx +602 -0
  29. package/src/components/ui/data-display/types.ts +536 -0
  30. package/src/components/ui/enterprise-mobile-experience-demo.tsx +749 -0
  31. package/src/components/ui/enterprise-mobile-experience.tsx +464 -0
  32. package/src/components/ui/feedback/alert.tsx +157 -0
  33. package/src/components/ui/feedback/progress.tsx +292 -0
  34. package/src/components/ui/feedback/skeleton.tsx +185 -0
  35. package/src/components/ui/feedback/toast.tsx +280 -0
  36. package/src/components/ui/feedback/types.ts +125 -0
  37. package/src/components/ui/font-preview.tsx +288 -0
  38. package/src/components/ui/form-demo.tsx +553 -0
  39. package/src/components/ui/hardware-acceleration-demo.tsx +547 -0
  40. package/src/components/ui/input.tsx +35 -0
  41. package/src/components/ui/label.tsx +16 -0
  42. package/src/components/ui/layout-demo.tsx +367 -0
  43. package/src/components/ui/layouts/adaptive-layout.tsx +139 -0
  44. package/src/components/ui/layouts/desktop-layout.tsx +224 -0
  45. package/src/components/ui/layouts/index.ts +10 -0
  46. package/src/components/ui/layouts/mobile-layout.tsx +162 -0
  47. package/src/components/ui/layouts/tablet-layout.tsx +197 -0
  48. package/src/components/ui/mobile-form-validation.tsx +451 -0
  49. package/src/components/ui/mobile-input-demo.tsx +201 -0
  50. package/src/components/ui/mobile-input.tsx +281 -0
  51. package/src/components/ui/mobile-skeleton-loading-demo.tsx +638 -0
  52. package/src/components/ui/navigation/breadcrumb.tsx +158 -0
  53. package/src/components/ui/navigation/index.ts +36 -0
  54. package/src/components/ui/navigation/menu.tsx +374 -0
  55. package/src/components/ui/navigation/navigation-demo.tsx +324 -0
  56. package/src/components/ui/navigation/pagination.tsx +272 -0
  57. package/src/components/ui/navigation/sidebar.tsx +383 -0
  58. package/src/components/ui/navigation/stepper.tsx +303 -0
  59. package/src/components/ui/navigation/tabs.tsx +205 -0
  60. package/src/components/ui/navigation/types.ts +299 -0
  61. package/src/components/ui/overlay/backdrop.tsx +81 -0
  62. package/src/components/ui/overlay/focus-manager.tsx +143 -0
  63. package/src/components/ui/overlay/index.ts +36 -0
  64. package/src/components/ui/overlay/modal.tsx +270 -0
  65. package/src/components/ui/overlay/overlay-manager.tsx +110 -0
  66. package/src/components/ui/overlay/popover.tsx +462 -0
  67. package/src/components/ui/overlay/portal.tsx +79 -0
  68. package/src/components/ui/overlay/tooltip.tsx +303 -0
  69. package/src/components/ui/overlay/types.ts +196 -0
  70. package/src/components/ui/performance-demo.tsx +596 -0
  71. package/src/components/ui/semantic-input-system-demo.tsx +502 -0
  72. package/src/components/ui/semantic-input-system-demo.tsx.disabled +873 -0
  73. package/src/components/ui/tablet-layout.tsx +192 -0
  74. package/src/components/ui/theme-customizer.tsx +386 -0
  75. package/src/components/ui/theme-preview.tsx +310 -0
  76. package/src/components/ui/theme-switcher.tsx +264 -0
  77. package/src/components/ui/theme-toggle.tsx +38 -0
  78. package/src/components/ui/token-demo.tsx +195 -0
  79. package/src/components/ui/touch-demo.tsx +462 -0
  80. package/src/components/ui/touch-friendly-interface-demo.tsx +519 -0
  81. package/src/components/ui/touch-friendly-interface.tsx +296 -0
  82. package/src/hooks/index.ts +190 -0
  83. package/src/hooks/use-accessibility-support.ts +518 -0
  84. package/src/hooks/use-adaptive-layout.ts +289 -0
  85. package/src/hooks/use-advanced-patterns.ts +294 -0
  86. package/src/hooks/use-advanced-transition-system.ts +393 -0
  87. package/src/hooks/use-animation-profile.ts +288 -0
  88. package/src/hooks/use-battery-animations.ts +384 -0
  89. package/src/hooks/use-battery-conscious-loading.ts +475 -0
  90. package/src/hooks/use-battery-optimization.ts +330 -0
  91. package/src/hooks/use-battery-status.ts +299 -0
  92. package/src/hooks/use-component-performance.ts +344 -0
  93. package/src/hooks/use-device-loading-states.ts +459 -0
  94. package/src/hooks/use-device.tsx +110 -0
  95. package/src/hooks/use-enterprise-mobile-experience.ts +488 -0
  96. package/src/hooks/use-form-feedback.ts +403 -0
  97. package/src/hooks/use-form-performance.ts +513 -0
  98. package/src/hooks/use-frame-rate.ts +251 -0
  99. package/src/hooks/use-gestures.ts +338 -0
  100. package/src/hooks/use-hardware-acceleration.ts +341 -0
  101. package/src/hooks/use-input-accessibility.ts +455 -0
  102. package/src/hooks/use-input-performance.ts +506 -0
  103. package/src/hooks/use-layout-performance.ts +319 -0
  104. package/src/hooks/use-loading-accessibility.ts +535 -0
  105. package/src/hooks/use-loading-performance.ts +473 -0
  106. package/src/hooks/use-memory-usage.ts +287 -0
  107. package/src/hooks/use-mobile-form-layout.ts +464 -0
  108. package/src/hooks/use-mobile-form-validation.ts +518 -0
  109. package/src/hooks/use-mobile-keyboard-optimization.ts +472 -0
  110. package/src/hooks/use-mobile-layout.ts +302 -0
  111. package/src/hooks/use-mobile-optimization.ts +406 -0
  112. package/src/hooks/use-mobile-skeleton.ts +402 -0
  113. package/src/hooks/use-mobile-touch.ts +414 -0
  114. package/src/hooks/use-performance-throttling.ts +348 -0
  115. package/src/hooks/use-performance.ts +316 -0
  116. package/src/hooks/use-reusable-architecture.ts +414 -0
  117. package/src/hooks/use-semantic-input-types.ts +357 -0
  118. package/src/hooks/use-semantic-input.ts +565 -0
  119. package/src/hooks/use-tablet-layout.ts +384 -0
  120. package/src/hooks/use-touch-friendly-input.ts +524 -0
  121. package/src/hooks/use-touch-friendly-interface.ts +331 -0
  122. package/src/hooks/use-touch-optimization.ts +375 -0
  123. package/src/index.ts +279 -279
  124. package/src/lib/utils.ts +6 -0
  125. package/src/themes/README.md +272 -0
  126. package/src/themes/ThemeContext.tsx +31 -0
  127. package/src/themes/ThemeProvider.tsx +232 -0
  128. package/src/themes/accessibility/index.ts +27 -0
  129. package/src/themes/accessibility.ts +259 -0
  130. package/src/themes/aria-patterns.ts +420 -0
  131. package/src/themes/base-themes.ts +55 -0
  132. package/src/themes/colorManager.ts +380 -0
  133. package/src/themes/examples/dark-theme.ts +154 -0
  134. package/src/themes/examples/minimal-theme.ts +108 -0
  135. package/src/themes/focus-management.ts +701 -0
  136. package/src/themes/fontLoader.ts +201 -0
  137. package/src/themes/high-contrast.ts +621 -0
  138. package/src/themes/index.ts +19 -0
  139. package/src/themes/inheritance.ts +227 -0
  140. package/src/themes/keyboard-navigation.ts +550 -0
  141. package/src/themes/motion-reduction.ts +662 -0
  142. package/src/themes/navigation.ts +238 -0
  143. package/src/themes/screen-reader.ts +645 -0
  144. package/src/themes/systemThemeDetector.ts +182 -0
  145. package/src/themes/themeCSSUpdater.ts +262 -0
  146. package/src/themes/themePersistence.ts +238 -0
  147. package/src/themes/themes/default.ts +586 -0
  148. package/src/themes/themes/harvey.ts +554 -0
  149. package/src/themes/themes/stan-design.ts +683 -0
  150. package/src/themes/types.ts +460 -0
  151. package/src/themes/useSystemTheme.ts +48 -0
  152. package/src/themes/useTheme.ts +87 -0
  153. package/src/themes/validation.ts +462 -0
  154. package/src/tokens/index.ts +34 -0
  155. package/src/tokens/tokenExporter.ts +397 -0
  156. package/src/tokens/tokenGenerator.ts +276 -0
  157. package/src/tokens/tokenManager.ts +248 -0
  158. package/src/tokens/tokenValidator.ts +543 -0
  159. package/src/tokens/types.ts +78 -0
  160. package/src/utils/bundle-analyzer.ts +260 -0
  161. package/src/utils/bundle-splitting.ts +483 -0
  162. package/src/utils/lazy-loading.ts +441 -0
  163. package/src/utils/performance-monitor.ts +513 -0
  164. package/src/utils/tree-shaking.ts +274 -0
@@ -0,0 +1,482 @@
1
+ import React, { useState, useCallback } from 'react';
2
+ import {
3
+ TableProps,
4
+ TableRowProps,
5
+ SortableColumn,
6
+ SortConfig,
7
+ PaginationConfig,
8
+ FilterConfig
9
+ } from './types';
10
+
11
+ // Simple icon components
12
+ const ChevronUpIcon: React.FC<{ className?: string }> = ({ className = '' }) => (
13
+ <svg className={`table__icon ${className}`} fill="none" viewBox="0 0 24 24" stroke="currentColor">
14
+ <path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M5 15l7-7 7 7" />
15
+ </svg>
16
+ );
17
+
18
+ const ChevronDownIcon: React.FC<{ className?: string }> = ({ className = '' }) => (
19
+ <svg className={`table__icon ${className}`} fill="none" viewBox="0 0 24 24" stroke="currentColor">
20
+ <path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M19 9l-7 7-7-7" />
21
+ </svg>
22
+ );
23
+
24
+ const ChevronRightIcon: React.FC<{ className?: string }> = ({ className = '' }) => (
25
+ <svg className={`table__icon ${className}`} fill="none" viewBox="0 0 24 24" stroke="currentColor">
26
+ <path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M9 5l7 7-7 7" />
27
+ </svg>
28
+ );
29
+
30
+ const SearchIcon: React.FC<{ className?: string }> = ({ className = '' }) => (
31
+ <svg className={`table__icon ${className}`} fill="none" viewBox="0 0 24 24" stroke="currentColor">
32
+ <path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M21 21l-6-6m2-5a7 7 0 11-14 0 7 7 0 0114 0z" />
33
+ </svg>
34
+ );
35
+
36
+ const FilterIcon: React.FC<{ className?: string }> = ({ className = '' }) => (
37
+ <svg className={`table__icon ${className}`} fill="none" viewBox="0 0 24 24" stroke="currentColor">
38
+ <path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M3 4a1 1 0 011-1h16a1 1 0 011 1v2.586a1 1 0 01-.293.707l-6.414 6.414a1 1 0 00-.293.707V17l-4 4v-6.586a1 1 0 00-.293-.707L3.293 7.207A1 1 0 013 6.5V4z" />
39
+ </svg>
40
+ );
41
+
42
+ // Table Header Component
43
+ const TableHeader: React.FC<{
44
+ columns: SortableColumn[];
45
+ sortable?: boolean;
46
+ sortConfig?: SortConfig;
47
+ onSort?: (config: SortConfig) => void;
48
+ selectable?: boolean;
49
+ onSelectAll?: (checked: boolean) => void;
50
+ allSelected?: boolean;
51
+ theme: 'stan-design' | 'enterprise' | 'harvey';
52
+ size: 'sm' | 'md' | 'lg';
53
+ variant: 'default' | 'bordered' | 'striped' | 'compact';
54
+ }> = ({
55
+ columns,
56
+ sortable,
57
+ sortConfig,
58
+ onSort,
59
+ selectable,
60
+ onSelectAll,
61
+ allSelected,
62
+ size
63
+ }) => {
64
+ // const { getTheme } = useTheme();
65
+ // const themeConfig = getTheme(theme);
66
+ // const colors = themeConfig?.colors || getDefaultColors();
67
+
68
+ const handleSort = useCallback((column: SortableColumn) => {
69
+ if (!sortable || !onSort || !column.sortable) return;
70
+
71
+ const newDirection = sortConfig?.key === column.key && sortConfig.direction === 'asc' ? 'desc' : 'asc';
72
+ onSort({ key: column.key, direction: newDirection });
73
+ }, [sortable, onSort, sortConfig]);
74
+
75
+ return (
76
+ <thead className="table__head">
77
+ <tr className="table__header-row">
78
+ {selectable && (
79
+ <th className={`table__header table__header--select table__header--${size}`}>
80
+ <input
81
+ type="checkbox"
82
+ checked={allSelected}
83
+ onChange={(e) => onSelectAll?.(e.target.checked)}
84
+ className="table__select-checkbox"
85
+ />
86
+ </th>
87
+ )}
88
+ {columns.map((column) => (
89
+ <th
90
+ key={column.key}
91
+ className={`table__header table__header--${size} table__header--${column.align || 'left'} ${sortable && column.sortable ? 'table__header--sortable' : ''} ${sortConfig?.key === column.key ? 'table__header--sorted' : ''}`}
92
+ style={{ width: column.width }}
93
+ onClick={() => handleSort(column)}
94
+ >
95
+ <div className={`table__header-content table__header-content--${column.align || 'left'}`}>
96
+ <span>{column.label}</span>
97
+ {sortable && column.sortable && sortConfig?.key === column.key && (
98
+ sortConfig.direction === 'asc' ? (
99
+ <ChevronUpIcon className="table__sort-icon" />
100
+ ) : (
101
+ <ChevronDownIcon className="table__sort-icon" />
102
+ )
103
+ )}
104
+ </div>
105
+ </th>
106
+ ))}
107
+ </tr>
108
+ </thead>
109
+ );
110
+ };
111
+
112
+ // Table Row Component
113
+ const TableRow: React.FC<TableRowProps> = ({
114
+ row,
115
+ index,
116
+ columns,
117
+ selected,
118
+ expanded,
119
+ onSelect,
120
+ onExpand,
121
+ onClick,
122
+ size,
123
+ variant
124
+ }) => {
125
+ // const { getTheme } = useTheme();
126
+ // const themeConfig = getTheme(theme);
127
+ // const colors = themeConfig?.colors || getDefaultColors();
128
+
129
+ return (
130
+ <tr
131
+ className={`table__row table__row--${size} table__row--${variant} ${selected ? 'table__row--selected' : ''} ${variant === 'striped' && index % 2 === 1 ? 'table__row--striped' : ''}`}
132
+ onClick={onClick}
133
+ >
134
+ <td className={`table__cell table__cell--select table__cell--${size}`}>
135
+ <input
136
+ type="checkbox"
137
+ checked={selected}
138
+ onChange={(e) => onSelect(e.target.checked)}
139
+ onClick={(e) => e.stopPropagation()}
140
+ className="table__select-checkbox"
141
+ />
142
+ </td>
143
+ {columns.map((column) => (
144
+ <td
145
+ key={column.key}
146
+ className={`table__cell table__cell--${size} table__cell--${column.align || 'left'}`}
147
+ style={{ width: column.width }}
148
+ >
149
+ {column.key === 'expand' ? (
150
+ <button
151
+ onClick={(e) => {
152
+ e.stopPropagation();
153
+ onExpand();
154
+ }}
155
+ className="table__expand-button"
156
+ >
157
+ <div className={`table__expand-icon ${expanded ? 'table__expand-icon--expanded' : ''}`}>
158
+ <ChevronRightIcon className="table__expand-chevron" />
159
+ </div>
160
+ </button>
161
+ ) : (
162
+ String(row[column.key] || '')
163
+ )}
164
+ </td>
165
+ ))}
166
+ </tr>
167
+ );
168
+ };
169
+
170
+ // Search and Filter Bar Component
171
+ const SearchFilterBar: React.FC<{
172
+ searchable?: boolean;
173
+ searchValue?: string;
174
+ onSearchChange?: (value: string) => void;
175
+ filters?: FilterConfig[];
176
+ theme: 'stan-design' | 'enterprise' | 'harvey';
177
+ size: 'sm' | 'md' | 'lg';
178
+ }> = ({
179
+ searchable,
180
+ searchValue,
181
+ onSearchChange,
182
+ filters,
183
+ size
184
+ }) => {
185
+ // const { getTheme } = useTheme();
186
+ // const themeConfig = getTheme(theme);
187
+ // const colors = themeConfig?.colors || getDefaultColors();
188
+
189
+ if (!searchable && (!filters || filters.length === 0)) return null;
190
+
191
+ return (
192
+ <div className={`table__search-filter-bar table__search-filter-bar--${size}`}>
193
+ {searchable && (
194
+ <div className="table__search-container">
195
+ <div className="table__search-icon">
196
+ <SearchIcon />
197
+ </div>
198
+ <input
199
+ type="text"
200
+ placeholder="Search..."
201
+ value={searchValue || ''}
202
+ onChange={(e) => onSearchChange?.(e.target.value)}
203
+ className={`table__search-input table__search-input--${size}`}
204
+ />
205
+ </div>
206
+ )}
207
+
208
+ {filters && filters.length > 0 && (
209
+ <div className="table__filters">
210
+ <div className="table__filter-icon">
211
+ <FilterIcon />
212
+ </div>
213
+ <span className={`table__filter-text table__filter-text--${size}`}>
214
+ Filters: {filters.length}
215
+ </span>
216
+ </div>
217
+ )}
218
+ </div>
219
+ );
220
+ };
221
+
222
+ // Pagination Component
223
+ const TablePagination: React.FC<{
224
+ pagination?: PaginationConfig;
225
+ onPageChange?: (page: number) => void;
226
+ onPageSizeChange?: (pageSize: number) => void;
227
+ theme: 'stan-design' | 'enterprise' | 'harvey';
228
+ size: 'sm' | 'md' | 'lg';
229
+ }> = ({ pagination, onPageChange, onPageSizeChange, size }) => {
230
+ // const { getTheme } = useTheme();
231
+ // const themeConfig = getTheme(theme);
232
+ // const colors = themeConfig?.colors || getDefaultColors();
233
+
234
+ if (!pagination) return null;
235
+
236
+ const { currentPage, pageSize, totalItems, pageSizeOptions = [10, 20, 50, 100] } = pagination;
237
+ const totalPages = Math.ceil(totalItems / pageSize);
238
+ const startItem = (currentPage - 1) * pageSize + 1;
239
+ const endItem = Math.min(currentPage * pageSize, totalItems);
240
+
241
+ return (
242
+ <div className={`table__pagination table__pagination--${size}`}>
243
+ <div className={`table__pagination-info table__pagination-info--${size}`}>
244
+ <span>
245
+ Showing {startItem}-{endItem} of {totalItems} items
246
+ </span>
247
+ <div className="table__pagination-size">
248
+ <span>Items per page:</span>
249
+ <select
250
+ value={pageSize}
251
+ onChange={(e) => onPageSizeChange?.(Number(e.target.value))}
252
+ className={`table__pagination-select table__pagination-select--${size}`}
253
+ >
254
+ {pageSizeOptions.map(option => (
255
+ <option key={option} value={option}>{option}</option>
256
+ ))}
257
+ </select>
258
+ </div>
259
+ </div>
260
+
261
+ <div className="table__pagination-controls">
262
+ <button
263
+ onClick={() => onPageChange?.(1)}
264
+ disabled={currentPage === 1}
265
+ className={`table__pagination-button table__pagination-button--${size} ${currentPage === 1 ? 'table__pagination-button--disabled' : ''}`}
266
+ >
267
+ First
268
+ </button>
269
+ <button
270
+ onClick={() => onPageChange?.(currentPage - 1)}
271
+ disabled={currentPage === 1}
272
+ className={`table__pagination-button table__pagination-button--${size} ${currentPage === 1 ? 'table__pagination-button--disabled' : ''}`}
273
+ >
274
+ Previous
275
+ </button>
276
+
277
+ <span className={`table__pagination-status table__pagination-status--${size}`}>
278
+ Page {currentPage} of {totalPages}
279
+ </span>
280
+
281
+ <button
282
+ onClick={() => onPageChange?.(currentPage + 1)}
283
+ disabled={currentPage === totalPages}
284
+ className={`table__pagination-button table__pagination-button--${size} ${currentPage === totalPages ? 'table__pagination-button--disabled' : ''}`}
285
+ >
286
+ Next
287
+ </button>
288
+ <button
289
+ onClick={() => onPageChange?.(totalPages)}
290
+ disabled={currentPage === totalPages}
291
+ className={`table__pagination-button table__pagination-button--${size} ${currentPage === totalPages ? 'table__pagination-button--disabled' : ''}`}
292
+ >
293
+ Last
294
+ </button>
295
+ </div>
296
+ </div>
297
+ );
298
+ };
299
+
300
+ // Main Table Component
301
+ export const Table: React.FC<TableProps> = ({
302
+ columns,
303
+ data,
304
+ sortable = false,
305
+ selectable = false,
306
+ onSort,
307
+ onSelectionChange,
308
+ onRowClick,
309
+ onRowExpand,
310
+ selectedKeys = [],
311
+ expandedKeys = [],
312
+ sortConfig,
313
+ pagination,
314
+ onPageChange,
315
+ onPageSizeChange,
316
+ filters,
317
+ // onFiltersChange, // TODO: Implement filters change handler
318
+ searchable = false,
319
+ searchValue,
320
+ onSearchChange,
321
+ rowKey = 'id',
322
+ loading = false,
323
+ error = null,
324
+ emptyMessage = 'No data available',
325
+ className = '',
326
+ theme = 'stan-design',
327
+ size = 'md',
328
+ variant = 'default'
329
+ }) => {
330
+ // const { getTheme } = useTheme();
331
+ // const themeConfig = getTheme(theme);
332
+ // const colors = themeConfig?.colors || getDefaultColors();
333
+
334
+ // Internal state for selection and expansion
335
+ const [internalSelectedKeys, setInternalSelectedKeys] = useState<string[]>(selectedKeys || []);
336
+ const [internalExpandedKeys, setInternalExpandedKeys] = useState<string[]>(expandedKeys || []);
337
+
338
+ // Use internal state for uncontrolled behavior, props for controlled
339
+ const currentSelectedKeys = selectedKeys || internalSelectedKeys;
340
+ const currentExpandedKeys = expandedKeys || internalExpandedKeys;
341
+
342
+ // Get row key function
343
+ const getRowKey = useCallback((row: Record<string, any>, index: number): string => {
344
+ if (typeof rowKey === 'function') {
345
+ return rowKey(row);
346
+ }
347
+ return row[rowKey] || `row-${index}`;
348
+ }, [rowKey]);
349
+
350
+ // Handle row selection
351
+ const handleRowSelect = useCallback((row: Record<string, any>, checked: boolean) => {
352
+ const key = getRowKey(row, 0);
353
+ let newSelectedKeys: string[];
354
+
355
+ if (checked) {
356
+ newSelectedKeys = [...currentSelectedKeys, key];
357
+ } else {
358
+ newSelectedKeys = currentSelectedKeys.filter(k => k !== key);
359
+ }
360
+
361
+ setInternalSelectedKeys(newSelectedKeys);
362
+ onSelectionChange?.(newSelectedKeys);
363
+ }, [currentSelectedKeys, onSelectionChange, getRowKey]);
364
+
365
+ // Handle select all
366
+ const handleSelectAll = useCallback((checked: boolean) => {
367
+ const newSelectedKeys = checked ? data.map((row, index) => getRowKey(row, index)) : [];
368
+ setInternalSelectedKeys(newSelectedKeys);
369
+ onSelectionChange?.(newSelectedKeys);
370
+ }, [data, onSelectionChange, getRowKey]);
371
+
372
+ // Handle row expansion
373
+ const handleRowExpand = useCallback((row: Record<string, any>) => {
374
+ const key = getRowKey(row, 0);
375
+ const expanded = currentExpandedKeys.includes(key);
376
+ const newExpandedKeys = expanded
377
+ ? currentExpandedKeys.filter(k => k !== key)
378
+ : [...currentExpandedKeys, key];
379
+
380
+ setInternalExpandedKeys(newExpandedKeys);
381
+ onRowExpand?.(row, !expanded);
382
+ }, [currentExpandedKeys, onRowExpand, getRowKey]);
383
+
384
+ // Handle row click
385
+ const handleRowClick = useCallback((row: Record<string, any>, index: number) => {
386
+ onRowClick?.(row, index);
387
+ }, [onRowClick]);
388
+
389
+ // Check if all rows are selected
390
+ const allSelected = data.length > 0 && currentSelectedKeys.length === data.length;
391
+
392
+ // Loading state
393
+ if (loading) {
394
+ return (
395
+ <div className="table__loading">
396
+ <div className={`table__loading-text table__loading-text--${size}`}>
397
+ Loading...
398
+ </div>
399
+ </div>
400
+ );
401
+ }
402
+
403
+ // Error state
404
+ if (error) {
405
+ return (
406
+ <div className="table__error">
407
+ <div className={`table__error-text table__error-text--${size}`}>
408
+ Error: {error}
409
+ </div>
410
+ </div>
411
+ );
412
+ }
413
+
414
+ // Empty state
415
+ if (data.length === 0) {
416
+ return (
417
+ <div className="table__empty">
418
+ <div className={`table__empty-text table__empty-text--${size}`}>
419
+ {emptyMessage}
420
+ </div>
421
+ </div>
422
+ );
423
+ }
424
+
425
+ return (
426
+ <div className={`table__container ${className || ''}`}>
427
+ <SearchFilterBar
428
+ searchable={searchable}
429
+ searchValue={searchValue}
430
+ onSearchChange={onSearchChange}
431
+ filters={filters}
432
+ theme={theme}
433
+ size={size}
434
+ />
435
+
436
+ <div className="table__wrapper">
437
+ <table className={`table__table table__table--${variant} table__table--${size}`}>
438
+ <TableHeader
439
+ columns={columns}
440
+ sortable={sortable}
441
+ sortConfig={sortConfig}
442
+ onSort={onSort}
443
+ selectable={selectable}
444
+ onSelectAll={handleSelectAll}
445
+ allSelected={allSelected}
446
+ theme={theme}
447
+ size={size}
448
+ variant={variant}
449
+ />
450
+ <tbody className="table__body">
451
+ {data.map((row, index) => (
452
+ <TableRow
453
+ key={getRowKey(row, index)}
454
+ row={row}
455
+ index={index}
456
+ columns={columns}
457
+ selected={currentSelectedKeys.includes(getRowKey(row, index))}
458
+ expanded={currentExpandedKeys.includes(getRowKey(row, index))}
459
+ onSelect={(checked) => handleRowSelect(row, checked)}
460
+ onExpand={() => handleRowExpand(row)}
461
+ onClick={() => handleRowClick(row, index)}
462
+ theme={theme}
463
+ size={size}
464
+ variant={variant}
465
+ />
466
+ ))}
467
+ </tbody>
468
+ </table>
469
+ </div>
470
+
471
+ <TablePagination
472
+ pagination={pagination}
473
+ onPageChange={onPageChange}
474
+ onPageSizeChange={onPageSizeChange}
475
+ theme={theme}
476
+ size={size}
477
+ />
478
+ </div>
479
+ );
480
+ };
481
+
482
+ export default Table;