@reactorui/datagrid 1.1.1 → 1.2.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/README.md +194 -12
- package/dist/components/DataGrid/DataGrid.d.ts +1 -1
- package/dist/components/DataGrid/DataGrid.d.ts.map +1 -1
- package/dist/components/DataGrid/DataGrid.js +39 -46
- package/dist/components/Filter/FilterControls.d.ts +3 -1
- package/dist/components/Filter/FilterControls.d.ts.map +1 -1
- package/dist/components/Filter/FilterControls.js +9 -19
- package/dist/components/Pagination/Pagination.d.ts +3 -0
- package/dist/components/Pagination/Pagination.d.ts.map +1 -1
- package/dist/components/Pagination/Pagination.js +6 -4
- package/dist/components/Search/SearchInput.d.ts +2 -0
- package/dist/components/Search/SearchInput.d.ts.map +1 -1
- package/dist/components/Search/SearchInput.js +6 -7
- package/dist/components/Table/TableBody.d.ts +1 -1
- package/dist/components/Table/TableBody.d.ts.map +1 -1
- package/dist/components/Table/TableBody.js +21 -8
- package/dist/components/Table/TableHeader.d.ts.map +1 -1
- package/dist/components/Table/TableHeader.js +37 -3
- package/dist/themes/index.d.ts +23 -1
- package/dist/themes/index.d.ts.map +1 -1
- package/dist/themes/index.js +89 -2
- package/dist/types/index.d.ts +21 -0
- package/dist/types/index.d.ts.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -22,8 +22,8 @@ A high-performance, feature-rich React data grid component with TypeScript suppo
|
|
|
22
22
|
- 🔍 **Advanced Filtering** - Type-aware filters with multiple operators (string, number, date, boolean)
|
|
23
23
|
- 🔄 **Flexible Data Sources** - Works with any data fetching strategy (REST, GraphQL, local)
|
|
24
24
|
- 📱 **Responsive Design** - Mobile-first with touch-friendly interactions
|
|
25
|
-
- 🎨 **Customizable Theming** -
|
|
26
|
-
- 🌙 **Dark Mode Ready** - Built-in dark mode support
|
|
25
|
+
- 🎨 **Fully Customizable Theming** - Pass custom theme objects to match your design system
|
|
26
|
+
- 🌙 **Dark Mode Ready** - Built-in dark mode support with zinc palette option
|
|
27
27
|
- ♿ **Accessibility First** - WCAG compliant with keyboard navigation and ARIA labels
|
|
28
28
|
- 🔧 **TypeScript Native** - Full type safety and comprehensive IntelliSense support
|
|
29
29
|
- 🎯 **Rich Event System** - 20+ events covering every user interaction
|
|
@@ -120,6 +120,149 @@ function App() {
|
|
|
120
120
|
}
|
|
121
121
|
```
|
|
122
122
|
|
|
123
|
+
## 🎨 Custom Theming
|
|
124
|
+
|
|
125
|
+
The DataGrid supports full theme customization via the `theme` prop. You can override any part of the default theme to match your design system.
|
|
126
|
+
|
|
127
|
+
### Theme Interface
|
|
128
|
+
|
|
129
|
+
```tsx
|
|
130
|
+
interface Theme {
|
|
131
|
+
// Container
|
|
132
|
+
container: string;
|
|
133
|
+
|
|
134
|
+
// Table
|
|
135
|
+
table: string;
|
|
136
|
+
header: string;
|
|
137
|
+
headerCell: string;
|
|
138
|
+
row: string;
|
|
139
|
+
cell: string;
|
|
140
|
+
selectedRow: string;
|
|
141
|
+
|
|
142
|
+
// Controls
|
|
143
|
+
searchInput: string;
|
|
144
|
+
select: string;
|
|
145
|
+
button: string;
|
|
146
|
+
buttonSecondary: string;
|
|
147
|
+
buttonDanger: string;
|
|
148
|
+
|
|
149
|
+
// Text
|
|
150
|
+
text: string;
|
|
151
|
+
textMuted: string;
|
|
152
|
+
textError: string;
|
|
153
|
+
|
|
154
|
+
// Pagination
|
|
155
|
+
pagination: string;
|
|
156
|
+
paginationButton: string;
|
|
157
|
+
paginationText: string;
|
|
158
|
+
|
|
159
|
+
// States
|
|
160
|
+
loadingSkeleton: string;
|
|
161
|
+
emptyState: string;
|
|
162
|
+
errorState: string;
|
|
163
|
+
|
|
164
|
+
// Filter
|
|
165
|
+
filterDropdown: string;
|
|
166
|
+
filterTag: string;
|
|
167
|
+
filterTagRemove: string;
|
|
168
|
+
}
|
|
169
|
+
```
|
|
170
|
+
|
|
171
|
+
### Custom Theme Example
|
|
172
|
+
|
|
173
|
+
```tsx
|
|
174
|
+
import { DataGrid, Theme } from '@reactorui/datagrid';
|
|
175
|
+
|
|
176
|
+
// Define your custom theme (partial overrides supported)
|
|
177
|
+
const myTheme: Partial<Theme> = {
|
|
178
|
+
container: 'bg-white dark:bg-zinc-900 rounded-xl border border-zinc-200 dark:border-zinc-700',
|
|
179
|
+
row: 'bg-white dark:bg-zinc-900 hover:bg-zinc-50 dark:hover:bg-zinc-800',
|
|
180
|
+
cell: 'px-4 py-3 text-sm text-gray-900 dark:text-zinc-100 border-b dark:border-zinc-700',
|
|
181
|
+
searchInput:
|
|
182
|
+
'px-3 py-2 border dark:border-zinc-700 rounded-lg dark:bg-zinc-800 dark:text-zinc-100',
|
|
183
|
+
pagination:
|
|
184
|
+
'flex items-center justify-between px-4 py-3 dark:bg-zinc-900 border-t dark:border-zinc-700',
|
|
185
|
+
};
|
|
186
|
+
|
|
187
|
+
function App() {
|
|
188
|
+
return <DataGrid data={data} theme={myTheme} />;
|
|
189
|
+
}
|
|
190
|
+
```
|
|
191
|
+
|
|
192
|
+
### Using createZincTheme Helper
|
|
193
|
+
|
|
194
|
+
For projects using the `zinc` color palette (like Tailwind's neutral grays), use the built-in helper:
|
|
195
|
+
|
|
196
|
+
```tsx
|
|
197
|
+
import { DataGrid, createZincTheme } from '@reactorui/datagrid';
|
|
198
|
+
|
|
199
|
+
// Creates a complete theme with zinc palette for dark mode
|
|
200
|
+
const zincTheme = createZincTheme('default'); // or 'striped' or 'bordered'
|
|
201
|
+
|
|
202
|
+
function App() {
|
|
203
|
+
return <DataGrid data={data} theme={zincTheme} />;
|
|
204
|
+
}
|
|
205
|
+
```
|
|
206
|
+
|
|
207
|
+
### Theme + Variant
|
|
208
|
+
|
|
209
|
+
Custom themes merge with the selected variant:
|
|
210
|
+
|
|
211
|
+
```tsx
|
|
212
|
+
// Striped variant + custom zinc dark mode
|
|
213
|
+
<DataGrid
|
|
214
|
+
data={data}
|
|
215
|
+
variant="striped"
|
|
216
|
+
theme={{
|
|
217
|
+
container: 'bg-white dark:bg-zinc-900 rounded-xl',
|
|
218
|
+
row: 'odd:bg-white dark:odd:bg-zinc-900 even:bg-zinc-50 dark:even:bg-zinc-800/50',
|
|
219
|
+
}}
|
|
220
|
+
/>
|
|
221
|
+
```
|
|
222
|
+
|
|
223
|
+
### Integration with Design Systems
|
|
224
|
+
|
|
225
|
+
Example integrating with a custom ThemeStyles system:
|
|
226
|
+
|
|
227
|
+
```tsx
|
|
228
|
+
// utils/dataGridTheme.ts
|
|
229
|
+
import { Theme } from '@reactorui/datagrid';
|
|
230
|
+
|
|
231
|
+
export const appDataGridTheme: Partial<Theme> = {
|
|
232
|
+
container:
|
|
233
|
+
'bg-white dark:bg-zinc-900 rounded-lg shadow-sm border border-gray-200 dark:border-zinc-700',
|
|
234
|
+
table: 'w-full bg-white dark:bg-zinc-900',
|
|
235
|
+
header: 'bg-gray-50 dark:bg-zinc-800 border-b border-gray-200 dark:border-zinc-700',
|
|
236
|
+
headerCell: 'px-4 py-3 text-left text-xs font-medium text-gray-500 dark:text-zinc-400 uppercase',
|
|
237
|
+
row: 'bg-white dark:bg-zinc-900 hover:bg-gray-50 dark:hover:bg-zinc-800 transition-colors',
|
|
238
|
+
cell: 'px-4 py-3 text-sm text-gray-900 dark:text-zinc-100 border-b dark:border-zinc-700',
|
|
239
|
+
selectedRow: 'bg-blue-50 dark:bg-blue-900/20 hover:bg-blue-100 dark:hover:bg-blue-900/30',
|
|
240
|
+
searchInput:
|
|
241
|
+
'px-3 py-2 border dark:border-zinc-700 rounded-md dark:bg-zinc-800 dark:text-zinc-100',
|
|
242
|
+
select: 'px-2 py-1 border dark:border-zinc-700 rounded dark:bg-zinc-800 dark:text-zinc-100',
|
|
243
|
+
button: 'px-3 py-2 bg-blue-600 text-white rounded-md hover:bg-blue-700',
|
|
244
|
+
buttonSecondary:
|
|
245
|
+
'px-3 py-2 bg-gray-100 dark:bg-zinc-800 text-gray-700 dark:text-zinc-300 rounded-md',
|
|
246
|
+
text: 'text-gray-700 dark:text-zinc-300',
|
|
247
|
+
textMuted: 'text-gray-500 dark:text-zinc-500',
|
|
248
|
+
textError: 'text-red-600 dark:text-red-400',
|
|
249
|
+
pagination:
|
|
250
|
+
'flex items-center justify-between px-4 py-3 dark:bg-zinc-900 border-t dark:border-zinc-700',
|
|
251
|
+
paginationButton: 'px-3 py-1 text-sm border dark:border-zinc-700 rounded dark:bg-zinc-800',
|
|
252
|
+
paginationText: 'text-sm text-gray-700 dark:text-zinc-300',
|
|
253
|
+
emptyState: 'text-gray-500 dark:text-zinc-400',
|
|
254
|
+
filterDropdown:
|
|
255
|
+
'absolute z-50 mt-2 bg-white dark:bg-zinc-800 border dark:border-zinc-700 rounded-lg shadow-lg',
|
|
256
|
+
filterTag:
|
|
257
|
+
'inline-flex items-center gap-1 px-2 py-1 text-xs bg-blue-100 dark:bg-blue-900/30 text-blue-700 dark:text-blue-300 rounded-md',
|
|
258
|
+
};
|
|
259
|
+
|
|
260
|
+
// Usage
|
|
261
|
+
import { appDataGridTheme } from './utils/dataGridTheme';
|
|
262
|
+
|
|
263
|
+
<DataGrid data={data} theme={appDataGridTheme} />;
|
|
264
|
+
```
|
|
265
|
+
|
|
123
266
|
## 🌐 Server-Side Data (Controlled Mode)
|
|
124
267
|
|
|
125
268
|
The DataGrid is a **controlled presentation component**. You handle data fetching; the grid handles display.
|
|
@@ -247,7 +390,7 @@ For large datasets, enable scrollable body with fixed headers:
|
|
|
247
390
|
|
|
248
391
|
## 🎯 Event System
|
|
249
392
|
|
|
250
|
-
### Filter Events
|
|
393
|
+
### Filter Events
|
|
251
394
|
|
|
252
395
|
```tsx
|
|
253
396
|
<DataGrid
|
|
@@ -360,15 +503,16 @@ For large datasets, enable scrollable body with fixed headers:
|
|
|
360
503
|
| `currentPage` | `number` | - | Controlled current page |
|
|
361
504
|
| `error` | `string \| null` | - | Error message to display |
|
|
362
505
|
|
|
363
|
-
### Layout
|
|
506
|
+
### Layout & Styling
|
|
364
507
|
|
|
365
|
-
| Prop | Type | Default | Description
|
|
366
|
-
| -------------- | -------------------------------------- | ----------- |
|
|
367
|
-
| `maxHeight` | `string \| number` | - | Fixed height with scrollable body
|
|
368
|
-
| `stickyHeader` | `boolean` | `false` | Enable sticky table header
|
|
369
|
-
| `className` | `string` | `''` | Additional CSS classes
|
|
370
|
-
| `variant` | `'default' \| 'striped' \| 'bordered'` | `'default'` | Visual theme
|
|
371
|
-
| `size` | `'sm' \| 'md' \| 'lg'` | `'md'` | Padding/text size
|
|
508
|
+
| Prop | Type | Default | Description |
|
|
509
|
+
| -------------- | -------------------------------------- | ----------- | ------------------------------------ |
|
|
510
|
+
| `maxHeight` | `string \| number` | - | Fixed height with scrollable body |
|
|
511
|
+
| `stickyHeader` | `boolean` | `false` | Enable sticky table header |
|
|
512
|
+
| `className` | `string` | `''` | Additional CSS classes |
|
|
513
|
+
| `variant` | `'default' \| 'striped' \| 'bordered'` | `'default'` | Visual theme variant |
|
|
514
|
+
| `size` | `'sm' \| 'md' \| 'lg'` | `'md'` | Padding/text size |
|
|
515
|
+
| `theme` | `Partial<Theme>` | - | Custom theme overrides (see Theming) |
|
|
372
516
|
|
|
373
517
|
### Features
|
|
374
518
|
|
|
@@ -438,6 +582,8 @@ interface Column<T> {
|
|
|
438
582
|
|
|
439
583
|
## 🎨 Theming & Styling
|
|
440
584
|
|
|
585
|
+
### Built-in Variants
|
|
586
|
+
|
|
441
587
|
```tsx
|
|
442
588
|
// Clean, minimal design
|
|
443
589
|
<DataGrid variant="default" data={data} />
|
|
@@ -459,6 +605,27 @@ interface Column<T> {
|
|
|
459
605
|
</div>
|
|
460
606
|
```
|
|
461
607
|
|
|
608
|
+
### Custom Theme
|
|
609
|
+
|
|
610
|
+
```tsx
|
|
611
|
+
import { DataGrid, createZincTheme } from '@reactorui/datagrid';
|
|
612
|
+
|
|
613
|
+
// Option 1: Use zinc theme helper
|
|
614
|
+
<DataGrid data={data} theme={createZincTheme('default')} />
|
|
615
|
+
|
|
616
|
+
// Option 2: Partial overrides
|
|
617
|
+
<DataGrid
|
|
618
|
+
data={data}
|
|
619
|
+
theme={{
|
|
620
|
+
container: 'bg-white dark:bg-slate-900 rounded-2xl',
|
|
621
|
+
row: 'hover:bg-slate-50 dark:hover:bg-slate-800',
|
|
622
|
+
}}
|
|
623
|
+
/>
|
|
624
|
+
|
|
625
|
+
// Option 3: Complete custom theme
|
|
626
|
+
<DataGrid data={data} theme={myCompleteTheme} />
|
|
627
|
+
```
|
|
628
|
+
|
|
462
629
|
## 🧪 Testing
|
|
463
630
|
|
|
464
631
|
```bash
|
|
@@ -489,6 +656,13 @@ test('handles filter application', async () => {
|
|
|
489
656
|
expect.any(Array)
|
|
490
657
|
);
|
|
491
658
|
});
|
|
659
|
+
|
|
660
|
+
test('applies custom theme', () => {
|
|
661
|
+
const customTheme = { container: 'custom-class dark:bg-zinc-900' };
|
|
662
|
+
const { container } = render(<DataGrid data={testData} theme={customTheme} />);
|
|
663
|
+
|
|
664
|
+
expect(container.firstChild).toHaveClass('dark:bg-zinc-900');
|
|
665
|
+
});
|
|
492
666
|
```
|
|
493
667
|
|
|
494
668
|
## ⚠️ Migration Guide
|
|
@@ -560,7 +734,7 @@ function MyGrid() {
|
|
|
560
734
|
// ✅ Set filterMode to enable callbacks
|
|
561
735
|
<DataGrid
|
|
562
736
|
data={data}
|
|
563
|
-
filterMode="server" // or "
|
|
737
|
+
filterMode="server" // or "client&server"
|
|
564
738
|
onApplyFilter={(f) => fetchWithFilter(f)}
|
|
565
739
|
/>
|
|
566
740
|
```
|
|
@@ -575,6 +749,14 @@ npm run typecheck # Type checking
|
|
|
575
749
|
npm run lint # Linting
|
|
576
750
|
```
|
|
577
751
|
|
|
752
|
+
## 📤 Publishing
|
|
753
|
+
|
|
754
|
+
```bash
|
|
755
|
+
npm run build # Build the package
|
|
756
|
+
npm version patch|minor|major # Bump version
|
|
757
|
+
npm publish --access public # Publish to npm
|
|
758
|
+
```
|
|
759
|
+
|
|
578
760
|
## 📄 License
|
|
579
761
|
|
|
580
762
|
MIT License - see [LICENSE](LICENSE) file for details.
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { DataGridProps } from '../../types';
|
|
2
2
|
export declare const DataGrid: <T extends {
|
|
3
3
|
[key: string]: any;
|
|
4
|
-
} = any>({ data, columns: columnsProp, loading: simpleLoading, loadingState: externalLoadingState, totalRecords: externalTotalRecords, error: externalError, currentPage: externalCurrentPage, enableSearch, enableSorting, enableFilters, enableSelection, enableDelete, enableRefresh, deleteConfirmation, filterMode, maxHeight, stickyHeader, pageSize, pageSizeOptions, variant, size, className, onPageChange, onPageSizeChange, onSortChange, onSearchChange, onApplyFilter, onRemoveFilter, onClearFilters, onFilterChange, onTableRowClick, onTableRowDoubleClick, onRowSelect, onSelectionChange, onTableRowHover, onCellClick, onTableRefresh, onBulkDelete, endpoint, httpConfig, serverPageSize, onDataLoad, onDataError, onLoadingStateChange, ...rest }: DataGridProps<T>) => import("react/jsx-runtime").JSX.Element;
|
|
4
|
+
} = any>({ data, columns: columnsProp, loading: simpleLoading, loadingState: externalLoadingState, totalRecords: externalTotalRecords, error: externalError, currentPage: externalCurrentPage, enableSearch, enableSorting, enableFilters, enableSelection, enableDelete, enableRefresh, deleteConfirmation, filterMode, maxHeight, stickyHeader, pageSize, pageSizeOptions, variant, size, className, theme: customTheme, onPageChange, onPageSizeChange, onSortChange, onSearchChange, onApplyFilter, onRemoveFilter, onClearFilters, onFilterChange, onTableRowClick, onTableRowDoubleClick, onRowSelect, onSelectionChange, onTableRowHover, onCellClick, onTableRefresh, onBulkDelete, endpoint, httpConfig, serverPageSize, onDataLoad, onDataError, onLoadingStateChange, ...rest }: DataGridProps<T>) => import("react/jsx-runtime").JSX.Element;
|
|
5
5
|
//# sourceMappingURL=DataGrid.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"DataGrid.d.ts","sourceRoot":"","sources":["../../../src/components/DataGrid/DataGrid.tsx"],"names":[],"mappings":"AAGA,OAAO,EAAE,aAAa,EAAwB,MAAM,aAAa,CAAC;AA0ClE,eAAO,MAAM,QAAQ,GAAI,CAAC,SAAS;IAAE,CAAC,GAAG,EAAE,MAAM,GAAG,GAAG,CAAA;CAAE,GAAG,GAAG,EAAE
|
|
1
|
+
{"version":3,"file":"DataGrid.d.ts","sourceRoot":"","sources":["../../../src/components/DataGrid/DataGrid.tsx"],"names":[],"mappings":"AAGA,OAAO,EAAE,aAAa,EAAwB,MAAM,aAAa,CAAC;AA0ClE,eAAO,MAAM,QAAQ,GAAI,CAAC,SAAS;IAAE,CAAC,GAAG,EAAE,MAAM,GAAG,GAAG,CAAA;CAAE,GAAG,GAAG,EAAE,mvBAyE9D,aAAa,CAAC,CAAC,CAAC,4CAwYlB,CAAC"}
|
|
@@ -28,7 +28,7 @@ maxHeight, stickyHeader = false,
|
|
|
28
28
|
// Pagination
|
|
29
29
|
pageSize = 10, pageSizeOptions = [5, 10, 25, 50, 100],
|
|
30
30
|
// Styling
|
|
31
|
-
variant = 'default', size = 'md', className = '',
|
|
31
|
+
variant = 'default', size = 'md', className = '', theme: customTheme,
|
|
32
32
|
// Pagination Events
|
|
33
33
|
onPageChange, onPageSizeChange,
|
|
34
34
|
// Sort & Search Events
|
|
@@ -41,7 +41,8 @@ onTableRowClick, onTableRowDoubleClick, onRowSelect, onSelectionChange, onTableR
|
|
|
41
41
|
onTableRefresh, onBulkDelete,
|
|
42
42
|
// DEPRECATED Props (kept for backward compatibility)
|
|
43
43
|
endpoint, httpConfig, serverPageSize, onDataLoad, onDataError, onLoadingStateChange, ...rest }) => {
|
|
44
|
-
|
|
44
|
+
// Merge variant theme with custom theme overrides
|
|
45
|
+
const theme = useMemo(() => getTheme(variant, customTheme), [variant, customTheme]);
|
|
45
46
|
// ===== Deprecation Warnings =====
|
|
46
47
|
React.useEffect(() => {
|
|
47
48
|
if (process.env.NODE_ENV !== 'production') {
|
|
@@ -110,55 +111,49 @@ endpoint, httpConfig, serverPageSize, onDataLoad, onDataError, onLoadingStateCha
|
|
|
110
111
|
onClearFilters,
|
|
111
112
|
onFilterChange,
|
|
112
113
|
});
|
|
113
|
-
//
|
|
114
|
+
// ===== Column Configuration =====
|
|
114
115
|
const columns = useMemo(() => {
|
|
115
116
|
if (columnsProp.length > 0)
|
|
116
117
|
return columnsProp;
|
|
117
|
-
if (data.length
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
}
|
|
127
|
-
return [];
|
|
118
|
+
if (!data || data.length === 0)
|
|
119
|
+
return [];
|
|
120
|
+
// Auto-detect columns from first row
|
|
121
|
+
return Object.keys(data[0]).map((key) => ({
|
|
122
|
+
key,
|
|
123
|
+
label: key.charAt(0).toUpperCase() + key.slice(1).replace(/([A-Z])/g, ' $1'),
|
|
124
|
+
sortable: true,
|
|
125
|
+
filterable: true,
|
|
126
|
+
dataType: inferDataType(data[0][key]),
|
|
127
|
+
}));
|
|
128
128
|
}, [columnsProp, data]);
|
|
129
|
-
// Selection change effect
|
|
130
|
-
const previousSelectedData = React.useRef([]);
|
|
131
|
-
React.useLayoutEffect(() => {
|
|
132
|
-
const hasChanged = selectedData.length !== previousSelectedData.current.length ||
|
|
133
|
-
selectedData.some((item, index) => item !== previousSelectedData.current[index]);
|
|
134
|
-
if (hasChanged && onSelectionChange) {
|
|
135
|
-
previousSelectedData.current = selectedData;
|
|
136
|
-
onSelectionChange(selectedData);
|
|
137
|
-
}
|
|
138
|
-
}, [selectedData, onSelectionChange]);
|
|
139
129
|
// Handle row selection with callback
|
|
140
|
-
const handleRowSelect = useCallback((
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
130
|
+
const handleRowSelect = useCallback((row, isSelected) => {
|
|
131
|
+
const rowId = getRowId(row);
|
|
132
|
+
selectRow(rowId, isSelected);
|
|
133
|
+
onRowSelect?.(row, isSelected);
|
|
134
|
+
// Calculate new selection for callback
|
|
135
|
+
const newSelectedRows = new Set(selectedRows);
|
|
136
|
+
isSelected ? newSelectedRows.add(rowId) : newSelectedRows.delete(rowId);
|
|
137
|
+
const newSelectedData = data.filter((r) => newSelectedRows.has(getRowId(r)));
|
|
138
|
+
onSelectionChange?.(newSelectedData);
|
|
139
|
+
}, [selectRow, onRowSelect, onSelectionChange, getRowId, selectedRows, data]);
|
|
140
|
+
// Handle select all with callback
|
|
141
|
+
const handleSelectAll = useCallback((selected) => {
|
|
142
|
+
selectAll(selected);
|
|
143
|
+
// Call onSelectionChange with all or none
|
|
144
|
+
const newSelectedData = selected ? paginatedData : [];
|
|
145
|
+
onSelectionChange?.(newSelectedData);
|
|
146
|
+
}, [selectAll, onSelectionChange, paginatedData]);
|
|
147
|
+
// Handle delete
|
|
150
148
|
const handleDelete = useCallback(() => {
|
|
151
149
|
if (selectedRows.size === 0)
|
|
152
150
|
return;
|
|
153
151
|
const executeDelete = () => {
|
|
154
|
-
|
|
155
|
-
onBulkDelete(selectedData);
|
|
156
|
-
}
|
|
152
|
+
onBulkDelete?.(selectedData);
|
|
157
153
|
};
|
|
158
154
|
if (deleteConfirmation) {
|
|
159
|
-
const
|
|
160
|
-
|
|
161
|
-
if (window.confirm(message)) {
|
|
155
|
+
const confirmMessage = `Are you sure you want to delete ${selectedRows.size} selected item${selectedRows.size === 1 ? '' : 's'}?`;
|
|
156
|
+
if (window.confirm(confirmMessage)) {
|
|
162
157
|
executeDelete();
|
|
163
158
|
}
|
|
164
159
|
}
|
|
@@ -175,17 +170,15 @@ endpoint, httpConfig, serverPageSize, onDataLoad, onDataError, onLoadingStateCha
|
|
|
175
170
|
const hasFixedLayout = maxHeight !== undefined || stickyHeader;
|
|
176
171
|
// Error state
|
|
177
172
|
if (externalError) {
|
|
178
|
-
return (_jsx("div", { className: `${theme.container} ${className}`, ...rest, children: _jsxs("div", { className: "px-4 py-8 text-center", children: [_jsx("div", { className:
|
|
173
|
+
return (_jsx("div", { className: `${theme.container} ${className}`, ...rest, children: _jsxs("div", { className: "px-4 py-8 text-center", children: [_jsx("div", { className: `${theme.textError} mb-2`, children: "Error loading data" }), _jsx("div", { className: `text-sm ${theme.textMuted} mb-4`, children: externalError }), _jsx("button", { onClick: handleRefresh, className: theme.button, children: "Try Again" })] }) }));
|
|
179
174
|
}
|
|
180
175
|
return (_jsxs("div", { className: `${theme.container} ${className} ${hasFixedLayout ? 'flex flex-col' : ''}`, style: hasFixedLayout && maxHeight
|
|
181
176
|
? { maxHeight: typeof maxHeight === 'number' ? `${maxHeight}px` : maxHeight }
|
|
182
|
-
: undefined, ...rest, children: [_jsx("div", { className: "px-4 py-4 flex-shrink-0", children: _jsxs("div", { className: "flex justify-between items-center gap-4", children: [_jsxs("div", { className: "flex items-center gap-2 flex-shrink-0", children: [_jsx("span", { className:
|
|
177
|
+
: undefined, ...rest, children: [_jsx("div", { className: "px-4 py-4 flex-shrink-0", children: _jsxs("div", { className: "flex justify-between items-center gap-4", children: [_jsxs("div", { className: "flex items-center gap-2 flex-shrink-0", children: [_jsx("span", { className: `text-sm ${theme.text}`, children: "Show" }), _jsx("select", { value: currentPageSize, onChange: (e) => setCurrentPageSize(parseInt(e.target.value)), disabled: isAnyLoading, className: theme.select, children: pageSizeOptions.map((size) => (_jsx("option", { value: size, children: size }, size))) }), _jsx("span", { className: `text-sm ${theme.text}`, children: "entries" }), enableFilters && (_jsx(FilterControls, { columns: columns, activeFilters: activeFilters, onApplyFilter: addFilter, onRemoveFilter: removeFilter, onClearFilters: clearFilters, disabled: isDataLoading, filterLoading: isFilterLoading, theme: theme }))] }), _jsxs("div", { className: "flex items-center gap-2 flex-shrink-0", children: [enableSearch && (_jsxs("div", { className: "w-64 relative", children: [_jsx(SearchInput, { value: searchTerm, onChange: setSearchTerm, placeholder: "Search...", disabled: isAnyLoading, className: theme.searchInput }), isSearchLoading && (_jsx("div", { className: "absolute right-3 top-1/2 -translate-y-1/2", children: _jsx(Spinner, { className: `w-4 h-4 ${theme.textMuted}` }) }))] })), enableRefresh && (_jsx("button", { onClick: handleRefresh, disabled: isAnyLoading, title: isRefreshLoading ? 'Refreshing...' : 'Refresh data', className: `${theme.buttonSecondary} flex items-center justify-center`, children: _jsx("svg", { className: "w-4 h-4", style: isRefreshLoading ? { animation: 'spin 1s linear infinite' } : undefined, fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: _jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "M4 4v5h.582m15.356 2A8.001 8.001 0 004.582 9m0 0H9m11 11v-5h-.581m0 0a8.003 8.003 0 01-15.357-2m15.357 2H15" }) }) })), enableDelete && enableSelection && (_jsxs("button", { onClick: handleDelete, disabled: selectedRows.size === 0 || isAnyLoading, title: selectedRows.size === 0
|
|
183
178
|
? 'Select rows to delete'
|
|
184
179
|
: isDeleteLoading
|
|
185
180
|
? 'Deleting...'
|
|
186
|
-
: `Delete ${selectedRows.size} selected item${selectedRows.size === 1 ? '' : 's'}`, className:
|
|
187
|
-
? 'bg-gray-100 dark:bg-gray-700 text-gray-400 dark:text-gray-500 cursor-not-allowed'
|
|
188
|
-
: 'bg-gray-100 dark:bg-gray-700 text-gray-800 dark:text-gray-200 hover:bg-gray-200 dark:hover:bg-gray-600 cursor-pointer'}`, children: [isDeleteLoading ? (_jsx(Spinner, { className: "w-4 h-4" })) : (_jsx("svg", { className: "w-4 h-4", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: _jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "M19 7l-.867 12.142A2 2 0 0116.138 21H7.862a2 2 0 01-1.995-1.858L5 7m5 4v6m4-6v6m1-10V4a1 1 0 00-1-1h-4a1 1 0 00-1 1v3M4 7h16" }) })), selectedRows.size > 0 && (_jsx("span", { className: "text-sm", children: isDeleteLoading ? 'Deleting...' : `(${selectedRows.size} selected)` }))] }))] })] }) }), _jsx("div", { className: `
|
|
181
|
+
: `Delete ${selectedRows.size} selected item${selectedRows.size === 1 ? '' : 's'}`, className: `${theme.buttonSecondary} flex items-center gap-1 ${selectedRows.size === 0 || isAnyLoading ? 'opacity-50 cursor-not-allowed' : ''}`, children: [isDeleteLoading ? (_jsx(Spinner, { className: "w-4 h-4" })) : (_jsx("svg", { className: "w-4 h-4", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: _jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "M19 7l-.867 12.142A2 2 0 0116.138 21H7.862a2 2 0 01-1.995-1.858L5 7m5 4v6m4-6v6m1-10V4a1 1 0 00-1-1h-4a1 1 0 00-1 1v3M4 7h16" }) })), selectedRows.size > 0 && (_jsx("span", { className: "text-sm", children: isDeleteLoading ? 'Deleting...' : `(${selectedRows.size} selected)` }))] }))] })] }) }), _jsx("div", { className: `
|
|
189
182
|
${hasFixedLayout ? 'flex-1 overflow-auto min-h-0' : 'overflow-x-auto'}
|
|
190
|
-
`, children: _jsxs("table", { className: theme.table, children: [_jsx(TableHeader, { columns: columns, sortConfig: sortConfig, onSort: enableSorting ? setSort : undefined, enableSelection: enableSelection, selectedCount: selectedRows.size, totalCount: paginatedData.length, onSelectAll: enableSelection ?
|
|
183
|
+
`, children: _jsxs("table", { className: theme.table, children: [_jsx(TableHeader, { columns: columns, sortConfig: sortConfig, onSort: enableSorting ? setSort : undefined, enableSelection: enableSelection, selectedCount: selectedRows.size, totalCount: paginatedData.length, onSelectAll: enableSelection ? handleSelectAll : undefined, theme: theme, sticky: hasFixedLayout }), _jsx(TableBody, { columns: columns, data: paginatedData, selectedRows: selectedRows, onSelectRow: enableSelection ? handleRowSelect : undefined, onRowClick: onTableRowClick, onRowDoubleClick: onTableRowDoubleClick, onRowHover: onTableRowHover, onCellClick: onCellClick, enableSelection: enableSelection, loading: isDataLoading, theme: theme, getRowId: getRowId })] }) }), _jsxs("div", { className: `${theme.pagination} flex-shrink-0`, children: [_jsxs("div", { className: `${theme.paginationText} flex-shrink-0`, children: ["Showing ", paginationInfo.start, "-", paginationInfo.end, " of", ' ', paginationInfo.totalRecords.toLocaleString(), " records"] }), _jsxs("div", { className: "flex items-center gap-2 flex-shrink-0", children: [_jsx("button", { onClick: navigatePrevious, disabled: !paginationInfo.hasPrevious || isAnyLoading, className: theme.paginationButton, children: "Previous" }), _jsxs("span", { className: `${theme.paginationText} px-2`, children: ["Page ", currentPage, " ", paginationInfo.totalPages > 0 && `of ${paginationInfo.totalPages}`] }), _jsx("button", { onClick: navigateNext, disabled: !paginationInfo.hasNext || isAnyLoading, className: theme.paginationButton, children: "Next" })] })] })] }));
|
|
191
184
|
};
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { Column, ActiveFilter } from '../../types';
|
|
2
|
+
import { Theme } from '../../themes';
|
|
2
3
|
interface FilterControlsProps<T> {
|
|
3
4
|
columns: Column<T>[];
|
|
4
5
|
activeFilters: ActiveFilter[];
|
|
@@ -7,7 +8,8 @@ interface FilterControlsProps<T> {
|
|
|
7
8
|
onClearFilters: () => void;
|
|
8
9
|
disabled?: boolean;
|
|
9
10
|
filterLoading?: boolean;
|
|
11
|
+
theme: Theme;
|
|
10
12
|
}
|
|
11
|
-
export declare const FilterControls: <T>({ columns, activeFilters, onApplyFilter, onRemoveFilter, onClearFilters, disabled, filterLoading, }: FilterControlsProps<T>) => import("react/jsx-runtime").JSX.Element;
|
|
13
|
+
export declare const FilterControls: <T>({ columns, activeFilters, onApplyFilter, onRemoveFilter, onClearFilters, disabled, filterLoading, theme, }: FilterControlsProps<T>) => import("react/jsx-runtime").JSX.Element;
|
|
12
14
|
export {};
|
|
13
15
|
//# sourceMappingURL=FilterControls.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"FilterControls.d.ts","sourceRoot":"","sources":["../../../src/components/Filter/FilterControls.tsx"],"names":[],"mappings":"AAIA,OAAO,EAAE,MAAM,EAAE,YAAY,EAAkB,MAAM,aAAa,CAAC;
|
|
1
|
+
{"version":3,"file":"FilterControls.d.ts","sourceRoot":"","sources":["../../../src/components/Filter/FilterControls.tsx"],"names":[],"mappings":"AAIA,OAAO,EAAE,MAAM,EAAE,YAAY,EAAkB,MAAM,aAAa,CAAC;AACnE,OAAO,EAAE,KAAK,EAAE,MAAM,cAAc,CAAC;AAMrC,UAAU,mBAAmB,CAAC,CAAC;IAC7B,OAAO,EAAE,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC;IACrB,aAAa,EAAE,YAAY,EAAE,CAAC;IAC9B,aAAa,EAAE,CAAC,MAAM,EAAE,IAAI,CAAC,YAAY,EAAE,OAAO,CAAC,KAAK,IAAI,CAAC;IAC7D,cAAc,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;IACxC,cAAc,EAAE,MAAM,IAAI,CAAC;IAC3B,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,aAAa,CAAC,EAAE,OAAO,CAAC;IACxB,KAAK,EAAE,KAAK,CAAC;CACd;AAuED,eAAO,MAAM,cAAc,GAAI,CAAC,EAAG,4GAShC,mBAAmB,CAAC,CAAC,CAAC,4CAuUxB,CAAC"}
|
|
@@ -39,25 +39,13 @@ const OPERATORS = {
|
|
|
39
39
|
};
|
|
40
40
|
const DEFAULT_OPERATORS = [{ value: 'eq', label: 'equals' }];
|
|
41
41
|
// ============================================================================
|
|
42
|
-
// Styles
|
|
43
|
-
// ============================================================================
|
|
44
|
-
const styles = {
|
|
45
|
-
select: 'w-full px-3 py-2.5 border border-gray-300 dark:border-gray-600 rounded-md text-sm bg-white dark:bg-gray-800 text-gray-900 dark:text-gray-100 focus:outline-none focus:ring-2 focus:ring-blue-500 dark:focus:ring-blue-400 disabled:bg-gray-50 dark:disabled:bg-gray-700 disabled:text-gray-500 dark:disabled:text-gray-400 disabled:cursor-not-allowed',
|
|
46
|
-
input: 'w-full px-3 py-2.5 border border-gray-300 dark:border-gray-600 rounded-md text-sm bg-white dark:bg-gray-800 text-gray-900 dark:text-gray-100 placeholder-gray-500 dark:placeholder-gray-400 focus:outline-none focus:ring-2 focus:ring-blue-500 dark:focus:ring-blue-400 disabled:bg-gray-50 dark:disabled:bg-gray-700 disabled:cursor-not-allowed',
|
|
47
|
-
inputDisabled: 'w-full px-3 py-2.5 border border-gray-300 dark:border-gray-600 rounded-md text-sm bg-gray-50 dark:bg-gray-700 text-gray-500 dark:text-gray-400 cursor-not-allowed',
|
|
48
|
-
buttonPrimary: 'w-full px-4 py-2.5 bg-blue-600 dark:bg-blue-700 text-white text-sm font-medium rounded-md hover:bg-blue-700 dark:hover:bg-blue-600 focus:outline-none focus:ring-2 focus:ring-blue-500 dark:focus:ring-blue-400 disabled:bg-gray-300 dark:disabled:bg-gray-600 disabled:text-gray-500 dark:disabled:text-gray-400 disabled:cursor-not-allowed transition-colors duration-150',
|
|
49
|
-
label: 'block text-sm font-medium text-gray-700 dark:text-gray-300 mb-1.5',
|
|
50
|
-
filterTag: 'inline-flex items-center gap-1.5 px-2.5 py-1 bg-blue-100 dark:bg-blue-900/30 text-blue-800 dark:text-blue-200 rounded-md text-xs font-medium whitespace-nowrap',
|
|
51
|
-
filterTagRemove: 'ml-0.5 text-blue-600 dark:text-blue-300 hover:text-blue-800 dark:hover:text-blue-100 focus:outline-none',
|
|
52
|
-
};
|
|
53
|
-
// ============================================================================
|
|
54
42
|
// Filter Icon
|
|
55
43
|
// ============================================================================
|
|
56
44
|
const FilterIcon = ({ className = 'w-4 h-4' }) => (_jsx("svg", { className: className, fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", xmlns: "http://www.w3.org/2000/svg", children: _jsx("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.293A1 1 0 013 6.586V4z" }) }));
|
|
57
45
|
// ============================================================================
|
|
58
46
|
// Component
|
|
59
47
|
// ============================================================================
|
|
60
|
-
export const FilterControls = ({ columns, activeFilters, onApplyFilter, onRemoveFilter, onClearFilters, disabled = false, filterLoading = false, }) => {
|
|
48
|
+
export const FilterControls = ({ columns, activeFilters, onApplyFilter, onRemoveFilter, onClearFilters, disabled = false, filterLoading = false, theme, }) => {
|
|
61
49
|
const [isOpen, setIsOpen] = useState(false);
|
|
62
50
|
const [filterColumn, setFilterColumn] = useState('');
|
|
63
51
|
const [filterOperator, setFilterOperator] = useState('eq');
|
|
@@ -163,19 +151,21 @@ export const FilterControls = ({ columns, activeFilters, onApplyFilter, onRemove
|
|
|
163
151
|
}, [canApply, handleApply, isDisabled]);
|
|
164
152
|
// Render value input based on data type
|
|
165
153
|
const renderValueInput = () => {
|
|
154
|
+
const inputClass = `w-full px-3 py-2.5 ${theme.searchInput}`;
|
|
155
|
+
const disabledClass = `w-full px-3 py-2.5 ${theme.select} opacity-50 cursor-not-allowed`;
|
|
166
156
|
if (!selectedColumn) {
|
|
167
|
-
return (_jsx("input", { type: "text", disabled: true, value: "", placeholder: "Select column first", className:
|
|
157
|
+
return (_jsx("input", { type: "text", disabled: true, value: "", placeholder: "Select column first", className: disabledClass }));
|
|
168
158
|
}
|
|
169
159
|
const commonProps = {
|
|
170
160
|
value: filterValue,
|
|
171
161
|
onChange: (e) => setFilterValue(e.target.value),
|
|
172
162
|
onKeyDown: handleKeyDown,
|
|
173
163
|
disabled: isDisabled,
|
|
174
|
-
className:
|
|
164
|
+
className: inputClass,
|
|
175
165
|
};
|
|
176
166
|
switch (selectedColumn.dataType) {
|
|
177
167
|
case 'boolean':
|
|
178
|
-
return (_jsxs("select", { ...commonProps, className:
|
|
168
|
+
return (_jsxs("select", { ...commonProps, className: `w-full px-3 py-2.5 ${theme.select}`, children: [_jsx("option", { value: "", children: "Select value" }), _jsx("option", { value: "true", children: "True" }), _jsx("option", { value: "false", children: "False" })] }));
|
|
179
169
|
case 'date':
|
|
180
170
|
return _jsx("input", { ...commonProps, type: "date" });
|
|
181
171
|
case 'datetime':
|
|
@@ -188,11 +178,11 @@ export const FilterControls = ({ columns, activeFilters, onApplyFilter, onRemove
|
|
|
188
178
|
};
|
|
189
179
|
return (_jsxs("div", { className: "flex items-center gap-2 min-w-0 flex-1", children: [_jsxs("button", { ref: buttonRef, onClick: () => setIsOpen(!isOpen), disabled: isDisabled, title: filterCount > 0
|
|
190
180
|
? `${filterCount} filter${filterCount === 1 ? '' : 's'} active`
|
|
191
|
-
: 'Add filter', className:
|
|
192
|
-
createPortal(_jsx("div", { ref: popoverRef, className:
|
|
181
|
+
: 'Add filter', className: `relative flex-shrink-0 p-2 ${theme.text} ${theme.buttonSecondary.replace(/px-3 py-2/g, '')} rounded-md disabled:opacity-50 disabled:cursor-not-allowed transition-colors duration-150`, children: [_jsx(FilterIcon, { className: "w-5 h-5" }), filterCount > 0 && (_jsx("span", { className: "absolute -top-1 -right-1 min-w-[18px] h-[18px] flex items-center justify-center px-1 text-xs font-medium text-white bg-blue-600 dark:bg-blue-500 rounded-full", children: filterCount }))] }), activeFilters.length > 0 && (_jsx("div", { className: "flex-1 min-w-0 overflow-x-auto", style: { scrollbarWidth: 'none', msOverflowStyle: 'none' }, children: _jsxs("div", { className: "flex items-center gap-1.5 py-0.5", children: [activeFilters.map((filter, index) => (_jsxs("span", { className: theme.filterTag, children: [filter.label, _jsx("button", { onClick: () => onRemoveFilter(index), disabled: isDisabled, className: theme.filterTagRemove, "aria-label": `Remove filter: ${filter.label}`, children: "\u00D7" })] }, `${filter.column}-${index}`))), activeFilters.length > 1 && (_jsx("button", { onClick: onClearFilters, disabled: isDisabled, className: `flex-shrink-0 text-xs ${theme.textError} whitespace-nowrap px-2 py-1 hover:bg-red-50 dark:hover:bg-red-900/20 rounded transition-colors`, children: "Clear all" }))] }) })), isOpen &&
|
|
182
|
+
createPortal(_jsx("div", { ref: popoverRef, className: `fixed w-80 ${theme.filterDropdown}`, style: {
|
|
193
183
|
top: popoverPosition.top,
|
|
194
184
|
padding: 14,
|
|
195
185
|
left: popoverPosition.left,
|
|
196
186
|
zIndex: 99999,
|
|
197
|
-
}, children: _jsxs("div", { className: "p-5 space-y-4", children: [_jsxs("div", { className: "flex items-center justify-between", children: [_jsx("h3", { className:
|
|
187
|
+
}, children: _jsxs("div", { className: "p-5 space-y-4", children: [_jsxs("div", { className: "flex items-center justify-between", children: [_jsx("h3", { className: `text-base font-semibold ${theme.text.replace('text-gray-700', 'text-gray-900').replace('dark:text-zinc-300', 'dark:text-zinc-100')}`, children: "Add Filter" }), _jsx("button", { onClick: () => setIsOpen(false), className: `p-1 ${theme.textMuted} hover:${theme.text} rounded-md ${theme.buttonSecondary.replace(/px-3 py-2 bg-\S+ /g, '')} transition-colors`, children: _jsx("svg", { className: "w-5 h-5", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: _jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "M6 18L18 6M6 6l12 12" }) }) })] }), _jsxs("div", { children: [_jsx("label", { className: `block text-sm font-medium ${theme.text} mb-1.5`, children: "Column" }), _jsxs("select", { value: filterColumn, onChange: (e) => handleColumnChange(e.target.value), disabled: isDisabled, className: `w-full px-3 py-2.5 ${theme.select}`, children: [_jsx("option", { value: "", children: "Select column" }), filterableColumns.map((col) => (_jsx("option", { value: String(col.key), children: col.label }, String(col.key))))] })] }), _jsxs("div", { children: [_jsx("label", { className: `block text-sm font-medium ${theme.text} mb-1.5`, children: "Operator" }), _jsx("select", { value: filterOperator, onChange: (e) => setFilterOperator(e.target.value), disabled: isDisabled || !filterColumn, className: `w-full px-3 py-2.5 ${theme.select}`, children: operatorOptions.map((op) => (_jsx("option", { value: op.value, children: op.label }, op.value))) })] }), _jsxs("div", { children: [_jsx("label", { className: `block text-sm font-medium ${theme.text} mb-1.5`, children: "Value" }), renderValueInput()] }), _jsx("button", { onClick: handleApply, disabled: isDisabled || !canApply, className: `w-full px-4 py-2.5 ${theme.button} font-medium`, children: "Apply Filter" })] }) }), document.body)] }));
|
|
198
188
|
};
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
|
+
import { Theme } from '../../themes';
|
|
2
3
|
interface PaginationProps {
|
|
3
4
|
currentPage: number;
|
|
4
5
|
totalPages: number;
|
|
@@ -11,6 +12,8 @@ interface PaginationProps {
|
|
|
11
12
|
onPageSizeChange: (size: number) => void;
|
|
12
13
|
hasNext: boolean;
|
|
13
14
|
hasPrevious: boolean;
|
|
15
|
+
disabled?: boolean;
|
|
16
|
+
theme: Theme;
|
|
14
17
|
}
|
|
15
18
|
export declare const Pagination: React.FC<PaginationProps>;
|
|
16
19
|
export {};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Pagination.d.ts","sourceRoot":"","sources":["../../../src/components/Pagination/Pagination.tsx"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"Pagination.d.ts","sourceRoot":"","sources":["../../../src/components/Pagination/Pagination.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,MAAM,OAAO,CAAC;AAC1B,OAAO,EAAE,KAAK,EAAE,MAAM,cAAc,CAAC;AAErC,UAAU,eAAe;IACvB,WAAW,EAAE,MAAM,CAAC;IACpB,UAAU,EAAE,MAAM,CAAC;IACnB,QAAQ,EAAE,MAAM,CAAC;IACjB,eAAe,EAAE,MAAM,EAAE,CAAC;IAC1B,YAAY,EAAE,MAAM,CAAC;IACrB,YAAY,EAAE,MAAM,CAAC;IACrB,UAAU,EAAE,MAAM,CAAC;IACnB,YAAY,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAC;IACrC,gBAAgB,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAC;IACzC,OAAO,EAAE,OAAO,CAAC;IACjB,WAAW,EAAE,OAAO,CAAC;IACrB,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,KAAK,EAAE,KAAK,CAAC;CACd;AAED,eAAO,MAAM,UAAU,EAAE,KAAK,CAAC,EAAE,CAAC,eAAe,CAiFhD,CAAC"}
|
|
@@ -1,12 +1,14 @@
|
|
|
1
1
|
import { jsxs as _jsxs, jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
-
export const Pagination = ({ currentPage, totalPages, pageSize, pageSizeOptions, totalRecords, displayStart, displayEnd, onPageChange, onPageSizeChange, hasNext, hasPrevious, }) => {
|
|
2
|
+
export const Pagination = ({ currentPage, totalPages, pageSize, pageSizeOptions, totalRecords, displayStart, displayEnd, onPageChange, onPageSizeChange, hasNext, hasPrevious, disabled = false, theme, }) => {
|
|
3
3
|
const handlePageChange = (page) => {
|
|
4
|
-
if (page >= 1 && page <= totalPages) {
|
|
4
|
+
if (page >= 1 && page <= totalPages && !disabled) {
|
|
5
5
|
onPageChange(page);
|
|
6
6
|
}
|
|
7
7
|
};
|
|
8
8
|
const handlePageSizeChange = (newSize) => {
|
|
9
|
-
|
|
9
|
+
if (!disabled) {
|
|
10
|
+
onPageSizeChange(newSize);
|
|
11
|
+
}
|
|
10
12
|
};
|
|
11
|
-
return (_jsxs("div", { className:
|
|
13
|
+
return (_jsxs("div", { className: `flex flex-col sm:flex-row justify-between items-start sm:items-center gap-4 ${theme.pagination}`, children: [_jsxs("div", { className: theme.paginationText, children: ["Showing ", displayStart, "-", displayEnd, " of ", totalRecords.toLocaleString(), " records"] }), _jsxs("div", { className: "flex items-center gap-6", children: [_jsxs("div", { className: "flex items-center gap-2", children: [_jsx("span", { className: theme.paginationText, children: "Show:" }), _jsx("select", { value: pageSize, onChange: (e) => handlePageSizeChange(parseInt(e.target.value)), disabled: disabled, className: theme.select, children: pageSizeOptions.map((size) => (_jsx("option", { value: size, children: size }, size))) }), _jsx("span", { className: theme.paginationText, children: "entries" })] }), _jsxs("div", { className: "flex items-center gap-2", children: [_jsx("button", { onClick: () => handlePageChange(currentPage - 1), disabled: !hasPrevious || disabled, className: theme.paginationButton, children: "Previous" }), _jsxs("span", { className: `${theme.paginationText} px-2`, children: ["Page ", currentPage, " ", totalPages > 0 && `of ${totalPages}`] }), _jsx("button", { onClick: () => handlePageChange(currentPage + 1), disabled: !hasNext || disabled, className: theme.paginationButton, children: "Next" })] })] })] }));
|
|
12
14
|
};
|
|
@@ -1,10 +1,12 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
|
+
import { Theme } from '../../themes';
|
|
2
3
|
interface SearchInputProps {
|
|
3
4
|
value: string;
|
|
4
5
|
onChange: (value: string) => void;
|
|
5
6
|
placeholder?: string;
|
|
6
7
|
disabled?: boolean;
|
|
7
8
|
className?: string;
|
|
9
|
+
theme?: Theme;
|
|
8
10
|
}
|
|
9
11
|
export declare const SearchInput: React.FC<SearchInputProps>;
|
|
10
12
|
export {};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"SearchInput.d.ts","sourceRoot":"","sources":["../../../src/components/Search/SearchInput.tsx"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"SearchInput.d.ts","sourceRoot":"","sources":["../../../src/components/Search/SearchInput.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,MAAM,OAAO,CAAC;AAC1B,OAAO,EAAE,KAAK,EAAE,MAAM,cAAc,CAAC;AAErC,UAAU,gBAAgB;IACxB,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;IAClC,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,KAAK,CAAC,EAAE,KAAK,CAAC;CACf;AAED,eAAO,MAAM,WAAW,EAAE,KAAK,CAAC,EAAE,CAAC,gBAAgB,CA0ClD,CAAC"}
|
|
@@ -1,9 +1,8 @@
|
|
|
1
1
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
-
export const SearchInput = ({ value, onChange, placeholder = 'Search...', disabled = false, className = '', }) => {
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
` }), _jsx("div", { className: "absolute inset-y-0 left-0 pl-3 flex items-center pointer-events-none", children: _jsx("svg", { className: "h-4 w-4 text-gray-400", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: _jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "M21 21l-6-6m2-5a7 7 0 11-14 0 7 7 0 0114 0z" }) }) })] }));
|
|
2
|
+
export const SearchInput = ({ value, onChange, placeholder = 'Search...', disabled = false, className = '', theme, }) => {
|
|
3
|
+
// Fallback styles if no theme provided (backward compatibility)
|
|
4
|
+
const inputStyles = theme?.searchInput ??
|
|
5
|
+
'px-3 py-2 border border-gray-300 dark:border-gray-600 rounded-md text-sm bg-white dark:bg-gray-800 text-gray-900 dark:text-gray-100 placeholder-gray-500 dark:placeholder-gray-400 focus:outline-none focus:ring-2 focus:ring-blue-500 dark:focus:ring-blue-400';
|
|
6
|
+
const iconStyles = theme?.textMuted ?? 'text-gray-400 dark:text-gray-500';
|
|
7
|
+
return (_jsxs("div", { className: "relative", children: [_jsx("input", { type: "text", value: value, onChange: (e) => onChange(e.target.value), placeholder: placeholder, disabled: disabled, className: `w-full pl-10 ${inputStyles} disabled:opacity-50 disabled:cursor-not-allowed ${className}` }), _jsx("div", { className: "absolute inset-y-0 left-0 pl-3 flex items-center pointer-events-none", children: _jsx("svg", { className: `h-4 w-4 ${iconStyles}`, fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: _jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "M21 21l-6-6m2-5a7 7 0 11-14 0 7 7 0 0114 0z" }) }) })] }));
|
|
9
8
|
};
|
|
@@ -5,7 +5,7 @@ interface TableBodyProps<T> {
|
|
|
5
5
|
columns: Column<T>[];
|
|
6
6
|
data: T[];
|
|
7
7
|
selectedRows: Set<string>;
|
|
8
|
-
onSelectRow?: (
|
|
8
|
+
onSelectRow?: (row: T, selected: boolean) => void;
|
|
9
9
|
onRowClick?: (row: T, event: React.MouseEvent) => void;
|
|
10
10
|
onRowDoubleClick?: (row: T, event: React.MouseEvent) => void;
|
|
11
11
|
onRowHover?: (row: T | null, event: React.MouseEvent) => void;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"TableBody.d.ts","sourceRoot":"","sources":["../../../src/components/Table/TableBody.tsx"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"TableBody.d.ts","sourceRoot":"","sources":["../../../src/components/Table/TableBody.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,MAAM,OAAO,CAAC;AAC1B,OAAO,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AACrC,OAAO,EAAE,KAAK,EAAE,MAAM,cAAc,CAAC;AAErC,UAAU,cAAc,CAAC,CAAC;IACxB,OAAO,EAAE,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC;IACrB,IAAI,EAAE,CAAC,EAAE,CAAC;IACV,YAAY,EAAE,GAAG,CAAC,MAAM,CAAC,CAAC;IAC1B,WAAW,CAAC,EAAE,CAAC,GAAG,EAAE,CAAC,EAAE,QAAQ,EAAE,OAAO,KAAK,IAAI,CAAC;IAClD,UAAU,CAAC,EAAE,CAAC,GAAG,EAAE,CAAC,EAAE,KAAK,EAAE,KAAK,CAAC,UAAU,KAAK,IAAI,CAAC;IACvD,gBAAgB,CAAC,EAAE,CAAC,GAAG,EAAE,CAAC,EAAE,KAAK,EAAE,KAAK,CAAC,UAAU,KAAK,IAAI,CAAC;IAC7D,UAAU,CAAC,EAAE,CAAC,GAAG,EAAE,CAAC,GAAG,IAAI,EAAE,KAAK,EAAE,KAAK,CAAC,UAAU,KAAK,IAAI,CAAC;IAC9D,WAAW,CAAC,EAAE,CAAC,KAAK,EAAE,GAAG,EAAE,GAAG,EAAE,CAAC,EAAE,MAAM,EAAE,MAAM,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,KAAK,CAAC,UAAU,KAAK,IAAI,CAAC;IACvF,eAAe,EAAE,OAAO,CAAC;IACzB,OAAO,EAAE,OAAO,CAAC;IACjB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,KAAK,EAAE,KAAK,CAAC;IACb,QAAQ,CAAC,EAAE,CAAC,GAAG,EAAE,CAAC,KAAK,MAAM,CAAC;CAC/B;AAED,eAAO,MAAM,SAAS,GAAI,CAAC,SAAS,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,EAAE,+JActD,cAAc,CAAC,CAAC,CAAC,4CAuLnB,CAAC"}
|
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
// File: src/components/Table/TableBody.tsx
|
|
2
3
|
import React from 'react';
|
|
3
4
|
export const TableBody = ({ columns, data, selectedRows, onSelectRow, onRowClick, onRowDoubleClick, onRowHover, onCellClick, enableSelection, loading, emptyMessage = 'No data available', theme, getRowId, }) => {
|
|
4
|
-
// Generate stable row IDs
|
|
5
|
+
// Generate stable row IDs
|
|
5
6
|
const rowIdMap = React.useMemo(() => {
|
|
6
7
|
const map = new Map();
|
|
7
8
|
data.forEach((row, index) => {
|
|
8
|
-
// Always generate based on index and content hash
|
|
9
9
|
const contentHash = JSON.stringify(row)
|
|
10
10
|
.slice(0, 50)
|
|
11
11
|
.replace(/[^a-zA-Z0-9]/g, '');
|
|
@@ -40,7 +40,7 @@ export const TableBody = ({ columns, data, selectedRows, onSelectRow, onRowClick
|
|
|
40
40
|
if (enableSelection && onSelectRow) {
|
|
41
41
|
const rowId = getStableRowId(row);
|
|
42
42
|
const isSelected = selectedRows.has(rowId);
|
|
43
|
-
onSelectRow(
|
|
43
|
+
onSelectRow(row, !isSelected);
|
|
44
44
|
}
|
|
45
45
|
};
|
|
46
46
|
const handleCellClick = (row, column, event) => {
|
|
@@ -49,19 +49,32 @@ export const TableBody = ({ columns, data, selectedRows, onSelectRow, onRowClick
|
|
|
49
49
|
onCellClick(value, row, column, event);
|
|
50
50
|
}
|
|
51
51
|
};
|
|
52
|
+
// Extract background from theme.table for tbody
|
|
53
|
+
const tbodyBg = theme.table.includes('bg-')
|
|
54
|
+
? theme.table
|
|
55
|
+
.split(' ')
|
|
56
|
+
.filter((c) => c.startsWith('bg-') || c.startsWith('dark:bg-'))
|
|
57
|
+
.join(' ')
|
|
58
|
+
: '';
|
|
52
59
|
if (loading) {
|
|
53
|
-
return (_jsx("tbody", { className:
|
|
60
|
+
return (_jsx("tbody", { className: tbodyBg, children: _jsx("tr", { children: _jsx("td", { colSpan: columns.length + (enableSelection ? 1 : 0), className: `px-4 py-12 text-center ${theme.textMuted}`, children: _jsxs("div", { className: "flex items-center justify-center gap-2", children: [_jsxs("svg", { className: "h-5 w-5 text-blue-600 dark:text-blue-400", style: { animation: 'spin 1s linear infinite' }, xmlns: "http://www.w3.org/2000/svg", fill: "none", viewBox: "0 0 24 24", children: [_jsx("style", { children: `@keyframes spin { from { transform: rotate(0deg); } to { transform: rotate(360deg); } }` }), _jsx("circle", { cx: "12", cy: "12", r: "10", stroke: "currentColor", strokeWidth: "4", style: { opacity: 0.25 } }), _jsx("path", { style: { opacity: 0.75 }, fill: "currentColor", d: "M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z" })] }), _jsx("span", { children: "Loading..." })] }) }) }) }));
|
|
54
61
|
}
|
|
55
62
|
if (data.length === 0) {
|
|
56
|
-
return (_jsx("tbody", { className:
|
|
63
|
+
return (_jsx("tbody", { className: tbodyBg, children: _jsx("tr", { children: _jsx("td", { colSpan: columns.length + (enableSelection ? 1 : 0), className: `px-4 py-8 text-center ${theme.emptyState} ${tbodyBg}`, children: emptyMessage }) }) }));
|
|
57
64
|
}
|
|
58
|
-
|
|
65
|
+
// Extract border color from theme for dividers
|
|
66
|
+
const borderColor = theme.cell
|
|
67
|
+
.match(/border-\S+/g)
|
|
68
|
+
?.filter((c) => !c.includes('border-b') && !c.includes('border-r'))?.[0] ||
|
|
69
|
+
'border-gray-200 dark:border-gray-600';
|
|
70
|
+
const divideBorder = borderColor.replace('border-', 'divide-');
|
|
71
|
+
return (_jsx("tbody", { className: `divide-y ${divideBorder}`, children: data.map((row) => {
|
|
59
72
|
const rowId = getStableRowId(row);
|
|
60
73
|
const isSelected = selectedRows.has(rowId);
|
|
61
74
|
return (_jsxs("tr", { className: `cursor-pointer ${isSelected ? theme.selectedRow : theme.row}`, onClick: (e) => handleRowClick(row, e), onDoubleClick: (e) => onRowDoubleClick?.(row, e), onMouseEnter: (e) => onRowHover?.(row, e), onMouseLeave: (e) => onRowHover?.(null, e), children: [enableSelection && (_jsx("td", { className: theme.cell, children: _jsx("input", { type: "checkbox", checked: isSelected, onChange: (e) => {
|
|
62
75
|
e.stopPropagation();
|
|
63
|
-
onSelectRow?.(
|
|
64
|
-
}, className:
|
|
76
|
+
onSelectRow?.(row, e.target.checked);
|
|
77
|
+
}, className: `w-4 h-4 text-blue-600 rounded focus:ring-blue-500 dark:focus:ring-blue-400 ${tbodyBg} ${borderColor}` }) })), columns.map((column) => (_jsx("td", { className: theme.cell, style: {
|
|
65
78
|
width: column.width,
|
|
66
79
|
minWidth: column.minWidth,
|
|
67
80
|
maxWidth: column.maxWidth,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"TableHeader.d.ts","sourceRoot":"","sources":["../../../src/components/Table/TableHeader.tsx"],"names":[],"mappings":"AAGA,OAAO,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AACjD,OAAO,EAAE,KAAK,EAAE,MAAM,cAAc,CAAC;AAErC,UAAU,gBAAgB,CAAC,CAAC;IAC1B,OAAO,EAAE,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC;IACrB,UAAU,EAAE,UAAU,CAAC;IACvB,MAAM,CAAC,EAAE,CAAC,MAAM,EAAE,MAAM,KAAK,IAAI,CAAC;IAClC,eAAe,EAAE,OAAO,CAAC;IACzB,aAAa,EAAE,MAAM,CAAC;IACtB,UAAU,EAAE,MAAM,CAAC;IACnB,WAAW,CAAC,EAAE,CAAC,QAAQ,EAAE,OAAO,KAAK,IAAI,CAAC;IAC1C,KAAK,EAAE,KAAK,CAAC;IACb,MAAM,CAAC,EAAE,OAAO,CAAC;CAClB;AAED,eAAO,MAAM,WAAW,GAAI,CAAC,EAAG,0GAU7B,gBAAgB,CAAC,CAAC,CAAC,
|
|
1
|
+
{"version":3,"file":"TableHeader.d.ts","sourceRoot":"","sources":["../../../src/components/Table/TableHeader.tsx"],"names":[],"mappings":"AAGA,OAAO,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AACjD,OAAO,EAAE,KAAK,EAAE,MAAM,cAAc,CAAC;AAErC,UAAU,gBAAgB,CAAC,CAAC;IAC1B,OAAO,EAAE,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC;IACrB,UAAU,EAAE,UAAU,CAAC;IACvB,MAAM,CAAC,EAAE,CAAC,MAAM,EAAE,MAAM,KAAK,IAAI,CAAC;IAClC,eAAe,EAAE,OAAO,CAAC;IACzB,aAAa,EAAE,MAAM,CAAC;IACtB,UAAU,EAAE,MAAM,CAAC;IACnB,WAAW,CAAC,EAAE,CAAC,QAAQ,EAAE,OAAO,KAAK,IAAI,CAAC;IAC1C,KAAK,EAAE,KAAK,CAAC;IACb,MAAM,CAAC,EAAE,OAAO,CAAC;CAClB;AAED,eAAO,MAAM,WAAW,GAAI,CAAC,EAAG,0GAU7B,gBAAgB,CAAC,CAAC,CAAC,4CAgJrB,CAAC"}
|
|
@@ -2,7 +2,7 @@ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
|
2
2
|
export const TableHeader = ({ columns, sortConfig, onSort, enableSelection, selectedCount, totalCount, onSelectAll, theme, sticky = false, }) => {
|
|
3
3
|
const getSortIcon = (columnKey) => {
|
|
4
4
|
if (sortConfig.column !== columnKey) {
|
|
5
|
-
return (_jsx("svg", { className:
|
|
5
|
+
return (_jsx("svg", { className: `w-4 h-4 ${theme.textMuted}`, fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: _jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "M7 16V4m0 0L3 8m4-4l4 4m6 0v12m0 0l4-4m-4 4l-4-4" }) }));
|
|
6
6
|
}
|
|
7
7
|
if (sortConfig.direction === 'asc') {
|
|
8
8
|
return (_jsx("svg", { className: "w-4 h-4 text-blue-500 dark:text-blue-400", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: _jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "M5 15l7-7 7 7" }) }));
|
|
@@ -11,12 +11,46 @@ export const TableHeader = ({ columns, sortConfig, onSort, enableSelection, sele
|
|
|
11
11
|
};
|
|
12
12
|
// Sticky styles
|
|
13
13
|
const stickyClass = sticky ? 'sticky top-0 z-10' : '';
|
|
14
|
+
// Extract background from header theme for hover
|
|
15
|
+
const headerBg = theme.header.match(/(?:dark:)?bg-\S+/g) || [];
|
|
16
|
+
const hoverBg = headerBg.length > 0
|
|
17
|
+
? headerBg
|
|
18
|
+
.map((bg) => {
|
|
19
|
+
// Convert bg-gray-50 -> hover:bg-gray-100, dark:bg-gray-700 -> dark:hover:bg-gray-600
|
|
20
|
+
if (bg.startsWith('dark:')) {
|
|
21
|
+
const color = bg.replace('dark:bg-', '');
|
|
22
|
+
const parts = color.match(/(\w+)-(\d+)/);
|
|
23
|
+
if (parts) {
|
|
24
|
+
const newShade = Math.max(parseInt(parts[2]) - 100, 600);
|
|
25
|
+
return `dark:hover:bg-${parts[1]}-${newShade}`;
|
|
26
|
+
}
|
|
27
|
+
return `dark:hover:bg-${color}`;
|
|
28
|
+
}
|
|
29
|
+
else {
|
|
30
|
+
const color = bg.replace('bg-', '');
|
|
31
|
+
const parts = color.match(/(\w+)-(\d+)/);
|
|
32
|
+
if (parts) {
|
|
33
|
+
const newShade = Math.min(parseInt(parts[2]) + 50, 200);
|
|
34
|
+
return `hover:bg-${parts[1]}-${newShade}`;
|
|
35
|
+
}
|
|
36
|
+
return `hover:bg-${color}`;
|
|
37
|
+
}
|
|
38
|
+
})
|
|
39
|
+
.join(' ')
|
|
40
|
+
: 'hover:bg-gray-100 dark:hover:bg-gray-600';
|
|
41
|
+
// Extract border from theme for checkbox
|
|
42
|
+
const borderColor = theme.headerCell
|
|
43
|
+
.match(/(?:dark:)?border-\S+/g)
|
|
44
|
+
?.filter((c) => !c.includes('border-r') && !c.includes('border-b'))?.[0] ||
|
|
45
|
+
'border-gray-300 dark:border-gray-600';
|
|
46
|
+
// Extract background for checkbox
|
|
47
|
+
const checkboxBg = theme.table.match(/(?:dark:)?bg-\S+/g)?.join(' ') || 'bg-white dark:bg-gray-800';
|
|
14
48
|
return (_jsx("thead", { className: `${theme.header} ${stickyClass}`, children: _jsxs("tr", { children: [enableSelection && (_jsx("th", { className: `w-12 ${theme.headerCell}`, role: "columnheader", "aria-label": "Select all rows", children: _jsx("input", { type: "checkbox", checked: selectedCount > 0 && selectedCount === totalCount, ref: (el) => {
|
|
15
49
|
if (el) {
|
|
16
50
|
el.indeterminate = selectedCount > 0 && selectedCount < totalCount;
|
|
17
51
|
}
|
|
18
|
-
}, onChange: (e) => onSelectAll?.(e.target.checked), className:
|
|
19
|
-
?
|
|
52
|
+
}, onChange: (e) => onSelectAll?.(e.target.checked), className: `w-4 h-4 text-blue-600 ${checkboxBg} ${borderColor} rounded focus:ring-blue-500 dark:focus:ring-blue-400`, "aria-label": "Select all rows" }) })), columns.map((column) => (_jsx("th", { role: "columnheader", className: `${theme.headerCell} ${column.sortable && onSort
|
|
53
|
+
? `cursor-pointer ${hoverBg} select-none transition-colors duration-150`
|
|
20
54
|
: ''}`, onClick: () => column.sortable && onSort && onSort(String(column.key)), style: {
|
|
21
55
|
width: column.width,
|
|
22
56
|
minWidth: column.minWidth,
|
package/dist/themes/index.d.ts
CHANGED
|
@@ -7,8 +7,22 @@ export interface Theme {
|
|
|
7
7
|
cell: string;
|
|
8
8
|
selectedRow: string;
|
|
9
9
|
searchInput: string;
|
|
10
|
+
select: string;
|
|
10
11
|
button: string;
|
|
12
|
+
buttonSecondary: string;
|
|
13
|
+
buttonDanger: string;
|
|
14
|
+
text: string;
|
|
15
|
+
textMuted: string;
|
|
16
|
+
textError: string;
|
|
11
17
|
pagination: string;
|
|
18
|
+
paginationButton: string;
|
|
19
|
+
paginationText: string;
|
|
20
|
+
loadingSkeleton: string;
|
|
21
|
+
emptyState: string;
|
|
22
|
+
errorState: string;
|
|
23
|
+
filterDropdown: string;
|
|
24
|
+
filterTag: string;
|
|
25
|
+
filterTagRemove: string;
|
|
12
26
|
}
|
|
13
27
|
export declare const defaultTheme: Theme;
|
|
14
28
|
export declare const stripedTheme: Theme;
|
|
@@ -18,5 +32,13 @@ export declare const themes: {
|
|
|
18
32
|
striped: Theme;
|
|
19
33
|
bordered: Theme;
|
|
20
34
|
};
|
|
21
|
-
export
|
|
35
|
+
export type ThemeVariant = keyof typeof themes;
|
|
36
|
+
/**
|
|
37
|
+
* Get a theme by variant name, optionally merged with custom overrides
|
|
38
|
+
*/
|
|
39
|
+
export declare const getTheme: (variant?: ThemeVariant, customTheme?: Partial<Theme>) => Theme;
|
|
40
|
+
/**
|
|
41
|
+
* Create a theme with zinc palette for dark mode (matches Smithers ThemeStyles)
|
|
42
|
+
*/
|
|
43
|
+
export declare const createZincTheme: (variant?: ThemeVariant) => Theme;
|
|
22
44
|
//# sourceMappingURL=index.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/themes/index.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/themes/index.ts"],"names":[],"mappings":"AAEA,MAAM,WAAW,KAAK;IAEpB,SAAS,EAAE,MAAM,CAAC;IAGlB,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;IACf,UAAU,EAAE,MAAM,CAAC;IACnB,GAAG,EAAE,MAAM,CAAC;IACZ,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,MAAM,CAAC;IAGpB,WAAW,EAAE,MAAM,CAAC;IACpB,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,MAAM,CAAC;IACf,eAAe,EAAE,MAAM,CAAC;IACxB,YAAY,EAAE,MAAM,CAAC;IAGrB,IAAI,EAAE,MAAM,CAAC;IACb,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,MAAM,CAAC;IAGlB,UAAU,EAAE,MAAM,CAAC;IACnB,gBAAgB,EAAE,MAAM,CAAC;IACzB,cAAc,EAAE,MAAM,CAAC;IAGvB,eAAe,EAAE,MAAM,CAAC;IACxB,UAAU,EAAE,MAAM,CAAC;IACnB,UAAU,EAAE,MAAM,CAAC;IAGnB,cAAc,EAAE,MAAM,CAAC;IACvB,SAAS,EAAE,MAAM,CAAC;IAClB,eAAe,EAAE,MAAM,CAAC;CACzB;AAED,eAAO,MAAM,YAAY,EAAE,KAiD1B,CAAC;AAEF,eAAO,MAAM,YAAY,EAAE,KAG1B,CAAC;AAEF,eAAO,MAAM,aAAa,EAAE,KAS3B,CAAC;AAEF,eAAO,MAAM,MAAM;;;;CAIlB,CAAC;AAEF,MAAM,MAAM,YAAY,GAAG,MAAM,OAAO,MAAM,CAAC;AAE/C;;GAEG;AACH,eAAO,MAAM,QAAQ,GACnB,UAAS,YAAwB,EACjC,cAAc,OAAO,CAAC,KAAK,CAAC,KAC3B,KAUF,CAAC;AAEF;;GAEG;AACH,eAAO,MAAM,eAAe,GAAI,UAAS,YAAwB,KAAG,KAoDnE,CAAC"}
|
package/dist/themes/index.js
CHANGED
|
@@ -1,14 +1,36 @@
|
|
|
1
|
+
// File: src/themes/index.ts
|
|
1
2
|
export const defaultTheme = {
|
|
3
|
+
// Container
|
|
2
4
|
container: 'bg-white dark:bg-gray-900 rounded-lg shadow-sm border border-gray-200 dark:border-gray-700',
|
|
5
|
+
// Table
|
|
3
6
|
table: 'w-full bg-white dark:bg-gray-800',
|
|
4
7
|
header: 'bg-gray-50 dark:bg-gray-700 border-b border-gray-200 dark:border-gray-600',
|
|
5
8
|
headerCell: 'px-4 py-3 text-left text-xs font-medium text-gray-500 dark:text-gray-400 uppercase tracking-wider bg-gray-50 dark:bg-gray-700',
|
|
6
9
|
row: 'bg-white dark:bg-gray-800 hover:bg-gray-50 dark:hover:bg-gray-700 transition-colors duration-150',
|
|
7
10
|
cell: 'px-4 py-3 text-sm text-gray-900 dark:text-gray-100 border-b border-gray-200 dark:border-gray-600',
|
|
8
11
|
selectedRow: 'bg-blue-50 dark:bg-blue-900/20 hover:bg-blue-100 dark:hover:bg-blue-900/30',
|
|
12
|
+
// Controls
|
|
9
13
|
searchInput: 'px-3 py-2 border border-gray-300 dark:border-gray-600 rounded-md text-sm bg-white dark:bg-gray-800 text-gray-900 dark:text-gray-100 placeholder-gray-500 dark:placeholder-gray-400 focus:outline-none focus:ring-2 focus:ring-blue-500 dark:focus:ring-blue-400',
|
|
14
|
+
select: 'px-2 py-1 border border-gray-300 dark:border-gray-600 rounded text-sm bg-white dark:bg-gray-800 text-gray-900 dark:text-gray-100 focus:outline-none focus:ring-2 focus:ring-blue-500 dark:focus:ring-blue-400 disabled:opacity-50',
|
|
10
15
|
button: 'px-3 py-2 bg-blue-600 dark:bg-blue-700 text-white text-sm rounded-md hover:bg-blue-700 dark:hover:bg-blue-600 focus:outline-none focus:ring-2 focus:ring-blue-500 dark:focus:ring-blue-400 disabled:opacity-50 disabled:cursor-not-allowed',
|
|
16
|
+
buttonSecondary: 'px-3 py-2 bg-gray-100 dark:bg-gray-700 text-gray-700 dark:text-gray-300 text-sm rounded-md hover:bg-gray-200 dark:hover:bg-gray-600 focus:outline-none focus:ring-2 focus:ring-blue-500 dark:focus:ring-blue-400 disabled:opacity-50 disabled:cursor-not-allowed transition-colors duration-150',
|
|
17
|
+
buttonDanger: 'px-3 py-2 bg-red-600 dark:bg-red-700 text-white text-sm rounded-md hover:bg-red-700 dark:hover:bg-red-600 focus:outline-none focus:ring-2 focus:ring-red-500 dark:focus:ring-red-400 disabled:opacity-50 disabled:cursor-not-allowed',
|
|
18
|
+
// Text
|
|
19
|
+
text: 'text-gray-700 dark:text-gray-300',
|
|
20
|
+
textMuted: 'text-gray-500 dark:text-gray-400',
|
|
21
|
+
textError: 'text-red-600 dark:text-red-400',
|
|
22
|
+
// Pagination
|
|
11
23
|
pagination: 'flex items-center justify-between px-4 py-3 bg-white dark:bg-gray-900 border-t border-gray-200 dark:border-gray-600',
|
|
24
|
+
paginationButton: 'px-3 py-1 text-sm border border-gray-300 dark:border-gray-600 rounded bg-white dark:bg-gray-800 text-gray-700 dark:text-gray-300 hover:bg-gray-50 dark:hover:bg-gray-700 focus:outline-none focus:ring-2 focus:ring-blue-500 dark:focus:ring-blue-400 disabled:opacity-50 disabled:cursor-not-allowed transition-colors duration-150',
|
|
25
|
+
paginationText: 'text-sm text-gray-700 dark:text-gray-300',
|
|
26
|
+
// States
|
|
27
|
+
loadingSkeleton: 'animate-pulse bg-gray-200 dark:bg-gray-700 rounded',
|
|
28
|
+
emptyState: 'text-gray-500 dark:text-gray-400',
|
|
29
|
+
errorState: 'text-red-600 dark:text-red-400',
|
|
30
|
+
// Filter
|
|
31
|
+
filterDropdown: 'absolute z-50 mt-2 bg-white dark:bg-gray-800 border border-gray-200 dark:border-gray-600 rounded-lg shadow-lg',
|
|
32
|
+
filterTag: 'inline-flex items-center gap-1 px-2 py-1 text-xs bg-blue-100 dark:bg-blue-900/30 text-blue-700 dark:text-blue-300 rounded-md',
|
|
33
|
+
filterTagRemove: 'hover:bg-blue-200 dark:hover:bg-blue-800 rounded p-0.5 transition-colors',
|
|
12
34
|
};
|
|
13
35
|
export const stripedTheme = {
|
|
14
36
|
...defaultTheme,
|
|
@@ -26,6 +48,71 @@ export const themes = {
|
|
|
26
48
|
striped: stripedTheme,
|
|
27
49
|
bordered: borderedTheme,
|
|
28
50
|
};
|
|
29
|
-
|
|
30
|
-
|
|
51
|
+
/**
|
|
52
|
+
* Get a theme by variant name, optionally merged with custom overrides
|
|
53
|
+
*/
|
|
54
|
+
export const getTheme = (variant = 'default', customTheme) => {
|
|
55
|
+
const baseTheme = themes[variant] || themes.default;
|
|
56
|
+
if (!customTheme)
|
|
57
|
+
return baseTheme;
|
|
58
|
+
// Deep merge custom theme with base theme
|
|
59
|
+
return {
|
|
60
|
+
...baseTheme,
|
|
61
|
+
...customTheme,
|
|
62
|
+
};
|
|
63
|
+
};
|
|
64
|
+
/**
|
|
65
|
+
* Create a theme with zinc palette for dark mode (matches Smithers ThemeStyles)
|
|
66
|
+
*/
|
|
67
|
+
export const createZincTheme = (variant = 'default') => {
|
|
68
|
+
const base = themes[variant] || themes.default;
|
|
69
|
+
return {
|
|
70
|
+
...base,
|
|
71
|
+
container: base.container
|
|
72
|
+
.replace(/dark:bg-gray-900/g, 'dark:bg-zinc-900')
|
|
73
|
+
.replace(/dark:border-gray-700/g, 'dark:border-zinc-700'),
|
|
74
|
+
table: base.table.replace(/dark:bg-gray-800/g, 'dark:bg-zinc-900'),
|
|
75
|
+
header: base.header
|
|
76
|
+
.replace(/dark:bg-gray-700/g, 'dark:bg-zinc-800')
|
|
77
|
+
.replace(/dark:border-gray-600/g, 'dark:border-zinc-700'),
|
|
78
|
+
headerCell: base.headerCell
|
|
79
|
+
.replace(/dark:text-gray-400/g, 'dark:text-zinc-400')
|
|
80
|
+
.replace(/dark:bg-gray-700/g, 'dark:bg-zinc-800'),
|
|
81
|
+
row: base.row
|
|
82
|
+
.replace(/dark:bg-gray-800/g, 'dark:bg-zinc-900')
|
|
83
|
+
.replace(/dark:hover:bg-gray-700/g, 'dark:hover:bg-zinc-800'),
|
|
84
|
+
cell: base.cell
|
|
85
|
+
.replace(/dark:text-gray-100/g, 'dark:text-zinc-100')
|
|
86
|
+
.replace(/dark:border-gray-600/g, 'dark:border-zinc-700'),
|
|
87
|
+
selectedRow: base.selectedRow.replace(/dark:bg-blue-900\/20/g, 'dark:bg-blue-900/20'),
|
|
88
|
+
searchInput: base.searchInput
|
|
89
|
+
.replace(/dark:border-gray-600/g, 'dark:border-zinc-700')
|
|
90
|
+
.replace(/dark:bg-gray-800/g, 'dark:bg-zinc-800')
|
|
91
|
+
.replace(/dark:text-gray-100/g, 'dark:text-zinc-100')
|
|
92
|
+
.replace(/dark:placeholder-gray-400/g, 'dark:placeholder-zinc-500'),
|
|
93
|
+
select: base.select
|
|
94
|
+
.replace(/dark:border-gray-600/g, 'dark:border-zinc-700')
|
|
95
|
+
.replace(/dark:bg-gray-800/g, 'dark:bg-zinc-800')
|
|
96
|
+
.replace(/dark:text-gray-100/g, 'dark:text-zinc-100'),
|
|
97
|
+
buttonSecondary: base.buttonSecondary
|
|
98
|
+
.replace(/dark:bg-gray-700/g, 'dark:bg-zinc-800')
|
|
99
|
+
.replace(/dark:text-gray-300/g, 'dark:text-zinc-300')
|
|
100
|
+
.replace(/dark:hover:bg-gray-600/g, 'dark:hover:bg-zinc-700'),
|
|
101
|
+
text: 'text-gray-700 dark:text-zinc-300',
|
|
102
|
+
textMuted: 'text-gray-500 dark:text-zinc-500',
|
|
103
|
+
pagination: base.pagination
|
|
104
|
+
.replace(/dark:bg-gray-900/g, 'dark:bg-zinc-900')
|
|
105
|
+
.replace(/dark:border-gray-600/g, 'dark:border-zinc-700'),
|
|
106
|
+
paginationButton: base.paginationButton
|
|
107
|
+
.replace(/dark:border-gray-600/g, 'dark:border-zinc-700')
|
|
108
|
+
.replace(/dark:bg-gray-800/g, 'dark:bg-zinc-800')
|
|
109
|
+
.replace(/dark:text-gray-300/g, 'dark:text-zinc-300')
|
|
110
|
+
.replace(/dark:hover:bg-gray-700/g, 'dark:hover:bg-zinc-700'),
|
|
111
|
+
paginationText: 'text-sm text-gray-700 dark:text-zinc-300',
|
|
112
|
+
loadingSkeleton: 'animate-pulse bg-gray-200 dark:bg-zinc-700 rounded',
|
|
113
|
+
emptyState: 'text-gray-500 dark:text-zinc-400',
|
|
114
|
+
filterDropdown: base.filterDropdown
|
|
115
|
+
.replace(/dark:bg-gray-800/g, 'dark:bg-zinc-800')
|
|
116
|
+
.replace(/dark:border-gray-600/g, 'dark:border-zinc-700'),
|
|
117
|
+
};
|
|
31
118
|
};
|
package/dist/types/index.d.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { ReactNode, HTMLAttributes } from 'react';
|
|
2
|
+
import { Theme } from '../themes';
|
|
2
3
|
export interface BaseRowData {
|
|
3
4
|
id?: string | number;
|
|
4
5
|
[key: string]: any;
|
|
@@ -162,6 +163,26 @@ export interface DataGridProps<T = BaseRowData> extends Omit<HTMLAttributes<HTML
|
|
|
162
163
|
className?: string;
|
|
163
164
|
variant?: 'default' | 'striped' | 'bordered';
|
|
164
165
|
size?: 'sm' | 'md' | 'lg';
|
|
166
|
+
/**
|
|
167
|
+
* Custom theme overrides. Merges with the variant theme.
|
|
168
|
+
* Use to customize colors, borders, backgrounds, etc.
|
|
169
|
+
*
|
|
170
|
+
* @example
|
|
171
|
+
* // Override specific properties
|
|
172
|
+
* <DataGrid
|
|
173
|
+
* data={data}
|
|
174
|
+
* theme={{
|
|
175
|
+
* container: 'bg-white dark:bg-zinc-900 rounded-lg border border-zinc-700',
|
|
176
|
+
* row: 'bg-white dark:bg-zinc-900 hover:bg-zinc-50 dark:hover:bg-zinc-800',
|
|
177
|
+
* }}
|
|
178
|
+
* />
|
|
179
|
+
*
|
|
180
|
+
* @example
|
|
181
|
+
* // Use createZincTheme for full dark mode compatibility
|
|
182
|
+
* import { createZincTheme } from '@reactorui/datagrid';
|
|
183
|
+
* <DataGrid data={data} theme={createZincTheme('default')} />
|
|
184
|
+
*/
|
|
185
|
+
theme?: Partial<Theme>;
|
|
165
186
|
onPageChange?: OnPageChangeCallback;
|
|
166
187
|
onPageSizeChange?: OnPageSizeChangeCallback;
|
|
167
188
|
onSortChange?: OnSortChangeCallback;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/types/index.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,SAAS,EAAE,cAAc,EAAE,MAAM,OAAO,CAAC;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/types/index.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@reactorui/datagrid",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.2.0",
|
|
4
4
|
"description": "A flexible, high-performance React data grid component with TypeScript support, advanced filtering, pagination, sorting, and customizable theming",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"module": "dist/index.js",
|