@pagamio/frontend-commons-lib 0.8.212 → 0.8.214
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/lib/api/TanstackQueryProvider.d.ts +146 -0
- package/lib/api/TanstackQueryProvider.js +140 -0
- package/lib/api/index.d.ts +2 -0
- package/lib/api/index.js +2 -0
- package/lib/api/tanstackQuery.d.ts +249 -0
- package/lib/api/tanstackQuery.js +299 -0
- package/lib/components/layout/Sidebar.js +50 -16
- package/lib/components/ui/Sheet.d.ts +1 -1
- package/lib/context/SidebarContext.d.ts +20 -0
- package/lib/dashboard-visuals-v2/DashboardWrapperV2.d.ts +81 -0
- package/lib/dashboard-visuals-v2/DashboardWrapperV2.js +217 -0
- package/lib/dashboard-visuals-v2/cards/CardGrid.d.ts +22 -0
- package/lib/dashboard-visuals-v2/cards/CardGrid.js +27 -0
- package/lib/dashboard-visuals-v2/cards/InfoCard.d.ts +7 -0
- package/lib/dashboard-visuals-v2/cards/InfoCard.js +26 -0
- package/lib/dashboard-visuals-v2/cards/MetricCard.d.ts +7 -0
- package/lib/dashboard-visuals-v2/cards/MetricCard.js +37 -0
- package/lib/dashboard-visuals-v2/cards/StatCard.d.ts +7 -0
- package/lib/dashboard-visuals-v2/cards/StatCard.js +92 -0
- package/lib/dashboard-visuals-v2/cards/TopItemsCard.d.ts +7 -0
- package/lib/dashboard-visuals-v2/cards/TopItemsCard.js +34 -0
- package/lib/dashboard-visuals-v2/cards/TransactionListCard.d.ts +7 -0
- package/lib/dashboard-visuals-v2/cards/TransactionListCard.js +24 -0
- package/lib/dashboard-visuals-v2/cards/index.d.ts +9 -0
- package/lib/dashboard-visuals-v2/cards/index.js +9 -0
- package/lib/dashboard-visuals-v2/charts/AreaChart.d.ts +7 -0
- package/lib/dashboard-visuals-v2/charts/AreaChart.js +124 -0
- package/lib/dashboard-visuals-v2/charts/BarChart.d.ts +7 -0
- package/lib/dashboard-visuals-v2/charts/BarChart.js +106 -0
- package/lib/dashboard-visuals-v2/charts/BaseChart.d.ts +61 -0
- package/lib/dashboard-visuals-v2/charts/BaseChart.js +173 -0
- package/lib/dashboard-visuals-v2/charts/DonutChart.d.ts +7 -0
- package/lib/dashboard-visuals-v2/charts/DonutChart.js +108 -0
- package/lib/dashboard-visuals-v2/charts/HeatmapChart.d.ts +7 -0
- package/lib/dashboard-visuals-v2/charts/HeatmapChart.js +101 -0
- package/lib/dashboard-visuals-v2/charts/LineChart.d.ts +7 -0
- package/lib/dashboard-visuals-v2/charts/LineChart.js +109 -0
- package/lib/dashboard-visuals-v2/charts/MixedChart.d.ts +7 -0
- package/lib/dashboard-visuals-v2/charts/MixedChart.js +106 -0
- package/lib/dashboard-visuals-v2/charts/PieChart.d.ts +7 -0
- package/lib/dashboard-visuals-v2/charts/PieChart.js +10 -0
- package/lib/dashboard-visuals-v2/charts/RadialChart.d.ts +7 -0
- package/lib/dashboard-visuals-v2/charts/RadialChart.js +72 -0
- package/lib/dashboard-visuals-v2/charts/index.d.ts +12 -0
- package/lib/dashboard-visuals-v2/charts/index.js +12 -0
- package/lib/dashboard-visuals-v2/components/DataFetchingVisual.d.ts +0 -0
- package/lib/dashboard-visuals-v2/components/DataFetchingVisual.js +1 -0
- package/lib/dashboard-visuals-v2/components/index.d.ts +0 -0
- package/lib/dashboard-visuals-v2/components/index.js +1 -0
- package/lib/dashboard-visuals-v2/hooks/index.d.ts +4 -0
- package/lib/dashboard-visuals-v2/hooks/index.js +4 -0
- package/lib/dashboard-visuals-v2/hooks/useChartData.d.ts +72 -0
- package/lib/dashboard-visuals-v2/hooks/useChartData.js +122 -0
- package/lib/dashboard-visuals-v2/index.d.ts +10 -0
- package/lib/dashboard-visuals-v2/index.js +16 -0
- package/lib/dashboard-visuals-v2/types/card.types.d.ts +237 -0
- package/lib/dashboard-visuals-v2/types/card.types.js +30 -0
- package/lib/dashboard-visuals-v2/types/chart.types.d.ts +308 -0
- package/lib/dashboard-visuals-v2/types/chart.types.js +25 -0
- package/lib/dashboard-visuals-v2/types/index.d.ts +6 -0
- package/lib/dashboard-visuals-v2/types/index.js +6 -0
- package/lib/dashboard-visuals-v2/utils/index.d.ts +0 -0
- package/lib/dashboard-visuals-v2/utils/index.js +1 -0
- package/lib/dashboard-visuals-v2/utils/propsTransformer.d.ts +0 -0
- package/lib/dashboard-visuals-v2/utils/propsTransformer.js +1 -0
- package/lib/dashboard-visuals-v2/visualRegistry.d.ts +59 -0
- package/lib/dashboard-visuals-v2/visualRegistry.js +110 -0
- package/lib/data-table-v2/DataTable.d.ts +7 -0
- package/lib/data-table-v2/DataTable.js +206 -0
- package/lib/data-table-v2/components/DataTableBody.d.ts +19 -0
- package/lib/data-table-v2/components/DataTableBody.js +20 -0
- package/lib/data-table-v2/components/DataTableEmpty.d.ts +17 -0
- package/lib/data-table-v2/components/DataTableEmpty.js +13 -0
- package/lib/data-table-v2/components/DataTableError.d.ts +16 -0
- package/lib/data-table-v2/components/DataTableError.js +14 -0
- package/lib/data-table-v2/components/DataTableHeader.d.ts +15 -0
- package/lib/data-table-v2/components/DataTableHeader.js +31 -0
- package/lib/data-table-v2/components/DataTableLoading.d.ts +14 -0
- package/lib/data-table-v2/components/DataTableLoading.js +19 -0
- package/lib/data-table-v2/components/DataTablePagination.d.ts +36 -0
- package/lib/data-table-v2/components/DataTablePagination.js +20 -0
- package/lib/data-table-v2/components/DataTableRowActions.d.ts +13 -0
- package/lib/data-table-v2/components/DataTableRowActions.js +57 -0
- package/lib/data-table-v2/components/DataTableSearch.d.ts +19 -0
- package/lib/data-table-v2/components/DataTableSearch.js +33 -0
- package/lib/data-table-v2/components/DataTableToolbar.d.ts +54 -0
- package/lib/data-table-v2/components/DataTableToolbar.js +28 -0
- package/lib/data-table-v2/components/index.d.ts +12 -0
- package/lib/data-table-v2/components/index.js +12 -0
- package/lib/data-table-v2/hooks/index.d.ts +4 -0
- package/lib/data-table-v2/hooks/index.js +4 -0
- package/lib/data-table-v2/hooks/useTableData.d.ts +118 -0
- package/lib/data-table-v2/hooks/useTableData.js +210 -0
- package/lib/data-table-v2/index.d.ts +9 -0
- package/lib/data-table-v2/index.js +12 -0
- package/lib/data-table-v2/types/index.d.ts +296 -0
- package/lib/data-table-v2/types/index.js +1 -0
- package/lib/data-table-v2/utils/export.d.ts +26 -0
- package/lib/data-table-v2/utils/export.js +92 -0
- package/lib/data-table-v2/utils/index.d.ts +4 -0
- package/lib/data-table-v2/utils/index.js +4 -0
- package/lib/index.d.ts +4 -0
- package/lib/index.js +23 -0
- package/lib/styles.css +219 -0
- package/package.json +7 -1
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview V2 Visual Registry - Maps visual type strings to ApexCharts components
|
|
3
|
+
* Compatible with V1 registry keys for easy migration
|
|
4
|
+
*/
|
|
5
|
+
import type React from 'react';
|
|
6
|
+
/**
|
|
7
|
+
* Visual type enum for type-safe visual selection
|
|
8
|
+
*/
|
|
9
|
+
export declare const VisualType: {
|
|
10
|
+
readonly BarChart: "BarChart";
|
|
11
|
+
readonly LineChart: "LineChart";
|
|
12
|
+
readonly AreaChart: "AreaChart";
|
|
13
|
+
readonly DonutChart: "DonutChart";
|
|
14
|
+
readonly PieChart: "PieChart";
|
|
15
|
+
readonly HeatmapChart: "HeatmapChart";
|
|
16
|
+
readonly RadialChart: "RadialChart";
|
|
17
|
+
readonly GaugeChart: "GaugeChart";
|
|
18
|
+
readonly MixedChart: "MixedChart";
|
|
19
|
+
readonly BarLineChart: "BarLineChart";
|
|
20
|
+
readonly HorizontalBarChart: "HorizontalBarChart";
|
|
21
|
+
readonly GroupedBarChart: "GroupedBarChart";
|
|
22
|
+
readonly Tile: "Tile";
|
|
23
|
+
readonly StatCard: "StatCard";
|
|
24
|
+
readonly MetricCard: "MetricCard";
|
|
25
|
+
readonly InfoCard: "InfoCard";
|
|
26
|
+
readonly TopItemsCard: "TopItemsCard";
|
|
27
|
+
readonly ItemPerformanceCard: "ItemPerformanceCard";
|
|
28
|
+
readonly TransactionListCard: "TransactionListCard";
|
|
29
|
+
};
|
|
30
|
+
export type VisualTypeKey = keyof typeof VisualType;
|
|
31
|
+
/**
|
|
32
|
+
* V2 Component Registry
|
|
33
|
+
* Maps visual type strings to their corresponding V2 (ApexCharts) components
|
|
34
|
+
*/
|
|
35
|
+
declare const visualRegistryV2: Record<string, React.FC<any>>;
|
|
36
|
+
/**
|
|
37
|
+
* Get a visual component from the registry
|
|
38
|
+
* @param type - The visual type string
|
|
39
|
+
* @returns The component or undefined if not found
|
|
40
|
+
*/
|
|
41
|
+
export declare function getVisualComponent(type: string): React.FC<any> | undefined;
|
|
42
|
+
/**
|
|
43
|
+
* Check if a visual type is registered
|
|
44
|
+
* @param type - The visual type string
|
|
45
|
+
* @returns Boolean indicating if the type is registered
|
|
46
|
+
*/
|
|
47
|
+
export declare function isRegisteredVisual(type: string): boolean;
|
|
48
|
+
/**
|
|
49
|
+
* Get all registered visual types
|
|
50
|
+
* @returns Array of registered visual type strings
|
|
51
|
+
*/
|
|
52
|
+
export declare function getRegisteredVisualTypes(): string[];
|
|
53
|
+
/**
|
|
54
|
+
* Register a custom visual component
|
|
55
|
+
* @param type - The visual type string
|
|
56
|
+
* @param component - The React component to register
|
|
57
|
+
*/
|
|
58
|
+
export declare function registerVisual(type: string, component: React.FC<any>): void;
|
|
59
|
+
export default visualRegistryV2;
|
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
import { InfoCard } from './cards/InfoCard';
|
|
2
|
+
import { MetricCard } from './cards/MetricCard';
|
|
3
|
+
import { StatCard } from './cards/StatCard';
|
|
4
|
+
import { TopItemsCard } from './cards/TopItemsCard';
|
|
5
|
+
import { TransactionListCard } from './cards/TransactionListCard';
|
|
6
|
+
import { AreaChart } from './charts/AreaChart';
|
|
7
|
+
import { BarChart } from './charts/BarChart';
|
|
8
|
+
import { DonutChart } from './charts/DonutChart';
|
|
9
|
+
import { HeatmapChart } from './charts/HeatmapChart';
|
|
10
|
+
import { LineChart } from './charts/LineChart';
|
|
11
|
+
import { MixedChart } from './charts/MixedChart';
|
|
12
|
+
import { PieChart } from './charts/PieChart';
|
|
13
|
+
import { RadialChart } from './charts/RadialChart';
|
|
14
|
+
/**
|
|
15
|
+
* Visual type enum for type-safe visual selection
|
|
16
|
+
*/
|
|
17
|
+
export const VisualType = {
|
|
18
|
+
// Charts
|
|
19
|
+
BarChart: 'BarChart',
|
|
20
|
+
LineChart: 'LineChart',
|
|
21
|
+
AreaChart: 'AreaChart',
|
|
22
|
+
DonutChart: 'DonutChart',
|
|
23
|
+
PieChart: 'PieChart',
|
|
24
|
+
HeatmapChart: 'HeatmapChart',
|
|
25
|
+
RadialChart: 'RadialChart',
|
|
26
|
+
GaugeChart: 'GaugeChart', // Alias for RadialChart
|
|
27
|
+
MixedChart: 'MixedChart',
|
|
28
|
+
BarLineChart: 'BarLineChart', // Alias for MixedChart
|
|
29
|
+
HorizontalBarChart: 'HorizontalBarChart',
|
|
30
|
+
GroupedBarChart: 'GroupedBarChart',
|
|
31
|
+
// Cards/Tiles
|
|
32
|
+
Tile: 'Tile',
|
|
33
|
+
StatCard: 'StatCard',
|
|
34
|
+
MetricCard: 'MetricCard',
|
|
35
|
+
InfoCard: 'InfoCard',
|
|
36
|
+
TopItemsCard: 'TopItemsCard',
|
|
37
|
+
ItemPerformanceCard: 'ItemPerformanceCard',
|
|
38
|
+
TransactionListCard: 'TransactionListCard',
|
|
39
|
+
};
|
|
40
|
+
/**
|
|
41
|
+
* V2 Component Registry
|
|
42
|
+
* Maps visual type strings to their corresponding V2 (ApexCharts) components
|
|
43
|
+
*/
|
|
44
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
45
|
+
const visualRegistryV2 = {
|
|
46
|
+
// Chart components
|
|
47
|
+
BarChart,
|
|
48
|
+
LineChart,
|
|
49
|
+
AreaChart,
|
|
50
|
+
DonutChart,
|
|
51
|
+
PieChart,
|
|
52
|
+
HeatmapChart,
|
|
53
|
+
RadialChart,
|
|
54
|
+
MixedChart,
|
|
55
|
+
// Aliases for V1 compatibility
|
|
56
|
+
GaugeChart: RadialChart,
|
|
57
|
+
MultiGaugeChart: RadialChart,
|
|
58
|
+
SpeedometerChart: RadialChart,
|
|
59
|
+
BarLineChart: MixedChart,
|
|
60
|
+
LineGraph: LineChart,
|
|
61
|
+
// Horizontal bar is bar chart with horizontal prop
|
|
62
|
+
// eslint-disable-next-line @typescript-eslint/naming-convention
|
|
63
|
+
HorizontalBarChart: (props) => BarChart({ ...props, horizontal: true }),
|
|
64
|
+
// Grouped bar is bar chart with multi-series
|
|
65
|
+
GroupedBarChart: BarChart,
|
|
66
|
+
// Card/Tile components
|
|
67
|
+
Tile: StatCard,
|
|
68
|
+
StatCard,
|
|
69
|
+
MetricCard,
|
|
70
|
+
InfoCard,
|
|
71
|
+
TopItemsCard,
|
|
72
|
+
TransactionListCard,
|
|
73
|
+
// Aliases for V1 compatibility
|
|
74
|
+
ItemPerformanceCard: TopItemsCard,
|
|
75
|
+
SelectedEventTile: StatCard,
|
|
76
|
+
};
|
|
77
|
+
/**
|
|
78
|
+
* Get a visual component from the registry
|
|
79
|
+
* @param type - The visual type string
|
|
80
|
+
* @returns The component or undefined if not found
|
|
81
|
+
*/
|
|
82
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
83
|
+
export function getVisualComponent(type) {
|
|
84
|
+
return visualRegistryV2[type];
|
|
85
|
+
}
|
|
86
|
+
/**
|
|
87
|
+
* Check if a visual type is registered
|
|
88
|
+
* @param type - The visual type string
|
|
89
|
+
* @returns Boolean indicating if the type is registered
|
|
90
|
+
*/
|
|
91
|
+
export function isRegisteredVisual(type) {
|
|
92
|
+
return type in visualRegistryV2;
|
|
93
|
+
}
|
|
94
|
+
/**
|
|
95
|
+
* Get all registered visual types
|
|
96
|
+
* @returns Array of registered visual type strings
|
|
97
|
+
*/
|
|
98
|
+
export function getRegisteredVisualTypes() {
|
|
99
|
+
return Object.keys(visualRegistryV2);
|
|
100
|
+
}
|
|
101
|
+
/**
|
|
102
|
+
* Register a custom visual component
|
|
103
|
+
* @param type - The visual type string
|
|
104
|
+
* @param component - The React component to register
|
|
105
|
+
*/
|
|
106
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
107
|
+
export function registerVisual(type, component) {
|
|
108
|
+
visualRegistryV2[type] = component;
|
|
109
|
+
}
|
|
110
|
+
export default visualRegistryV2;
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import type { DataTableProps } from './types';
|
|
2
|
+
/**
|
|
3
|
+
* DataTable V2 Component
|
|
4
|
+
* Headless table powered by TanStack Table
|
|
5
|
+
*/
|
|
6
|
+
export declare function DataTable<TData>({ data, columns: columnConfig, rowSelection: rowSelectionOptions, pagination: paginationOptions, sorting: sortingOptions, filtering: filteringOptions, columnVisibility: columnVisibilityOptions, export: exportOptions, rowActions, bulkActions, loading, error, emptyMessage, title, description, striped, hoverable, bordered, compact, stickyHeader, maxHeight, onRowClick, onRowDoubleClick, getRowId, rowClassName, className, classNames, headerContent, footerContent, onRefresh, }: DataTableProps<TData>): import("react/jsx-runtime").JSX.Element;
|
|
7
|
+
export default DataTable;
|
|
@@ -0,0 +1,206 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
/**
|
|
3
|
+
* @fileoverview DataTable V2 - Main Component using TanStack Table
|
|
4
|
+
*/
|
|
5
|
+
import { getCoreRowModel, getFilteredRowModel, getPaginationRowModel, getSortedRowModel, useReactTable, } from '@tanstack/react-table';
|
|
6
|
+
import React, { useCallback, useMemo, useState } from 'react';
|
|
7
|
+
import { cn } from '../helpers';
|
|
8
|
+
import { DataTableBody, DataTableEmpty, DataTableError, DataTableHeader, DataTableLoading, DataTablePagination, DataTableRowActions, DataTableToolbar, } from './components';
|
|
9
|
+
/**
|
|
10
|
+
* Convert DataTableColumn to TanStack ColumnDef
|
|
11
|
+
*/
|
|
12
|
+
function toColumnDef(column) {
|
|
13
|
+
return {
|
|
14
|
+
id: column.id,
|
|
15
|
+
accessorKey: column.accessorKey,
|
|
16
|
+
accessorFn: column.accessorFn,
|
|
17
|
+
header: column.header,
|
|
18
|
+
cell: column.cell,
|
|
19
|
+
footer: column.footer,
|
|
20
|
+
enableSorting: column.enableSorting ?? true,
|
|
21
|
+
enableColumnFilter: column.enableFiltering ?? false,
|
|
22
|
+
enableHiding: column.enableHiding ?? true,
|
|
23
|
+
size: column.size,
|
|
24
|
+
minSize: column.minSize,
|
|
25
|
+
maxSize: column.maxSize,
|
|
26
|
+
filterFn: column.filterFn,
|
|
27
|
+
aggregationFn: column.aggregationFn,
|
|
28
|
+
meta: {
|
|
29
|
+
align: column.align,
|
|
30
|
+
},
|
|
31
|
+
};
|
|
32
|
+
}
|
|
33
|
+
/**
|
|
34
|
+
* DataTable V2 Component
|
|
35
|
+
* Headless table powered by TanStack Table
|
|
36
|
+
*/
|
|
37
|
+
export function DataTable({ data, columns: columnConfig, rowSelection: rowSelectionOptions, pagination: paginationOptions, sorting: sortingOptions, filtering: filteringOptions, columnVisibility: columnVisibilityOptions, export: exportOptions, rowActions, bulkActions, loading = false, error, emptyMessage = 'No data available', title, description, striped = false, hoverable = true, bordered = false, compact = false, stickyHeader = false, maxHeight, onRowClick, onRowDoubleClick, getRowId, rowClassName, className, classNames, headerContent, footerContent, onRefresh, }) {
|
|
38
|
+
// State
|
|
39
|
+
const [sorting, setSorting] = useState(sortingOptions?.initialSorting ?? []);
|
|
40
|
+
const [columnFilters, setColumnFilters] = useState(filteringOptions?.initialFilters ?? []);
|
|
41
|
+
const [globalFilter, setGlobalFilter] = useState('');
|
|
42
|
+
const [columnVisibility, setColumnVisibility] = useState(columnVisibilityOptions?.initialVisibility ?? {});
|
|
43
|
+
const [rowSelectionState, setRowSelectionState] = useState(rowSelectionOptions?.selectedRowIds ?? {});
|
|
44
|
+
// Convert column config to TanStack ColumnDef
|
|
45
|
+
const columns = useMemo(() => {
|
|
46
|
+
const cols = [];
|
|
47
|
+
// Add selection column if enabled
|
|
48
|
+
if (rowSelectionOptions?.enabled) {
|
|
49
|
+
cols.push({
|
|
50
|
+
id: 'select',
|
|
51
|
+
header: rowSelectionOptions.enableSelectAll !== false
|
|
52
|
+
? ({ table }) => (_jsx("input", { type: "checkbox", checked: table.getIsAllPageRowsSelected(), onChange: table.getToggleAllPageRowsSelectedHandler(), className: "rounded border-gray-300 text-blue-600 focus:ring-blue-500" }))
|
|
53
|
+
: undefined,
|
|
54
|
+
cell: ({ row }) => (_jsx("input", { type: "checkbox", checked: row.getIsSelected(), disabled: !row.getCanSelect(), onChange: row.getToggleSelectedHandler(), onClick: (e) => e.stopPropagation(), className: "rounded border-gray-300 text-blue-600 focus:ring-blue-500" })),
|
|
55
|
+
enableSorting: false,
|
|
56
|
+
enableHiding: false,
|
|
57
|
+
size: 40,
|
|
58
|
+
});
|
|
59
|
+
}
|
|
60
|
+
// Add data columns
|
|
61
|
+
cols.push(...columnConfig.map(toColumnDef));
|
|
62
|
+
// Add actions column if provided
|
|
63
|
+
if (rowActions && rowActions.length > 0) {
|
|
64
|
+
cols.push({
|
|
65
|
+
id: 'actions',
|
|
66
|
+
header: '',
|
|
67
|
+
cell: ({ row }) => _jsx(DataTableRowActions, { row: row.original, actions: rowActions }),
|
|
68
|
+
enableSorting: false,
|
|
69
|
+
enableHiding: false,
|
|
70
|
+
size: 50,
|
|
71
|
+
});
|
|
72
|
+
}
|
|
73
|
+
return cols;
|
|
74
|
+
}, [columnConfig, rowSelectionOptions, rowActions]);
|
|
75
|
+
// Create table instance
|
|
76
|
+
const table = useReactTable({
|
|
77
|
+
data,
|
|
78
|
+
columns,
|
|
79
|
+
state: {
|
|
80
|
+
sorting,
|
|
81
|
+
columnFilters,
|
|
82
|
+
globalFilter,
|
|
83
|
+
columnVisibility,
|
|
84
|
+
rowSelection: rowSelectionState,
|
|
85
|
+
},
|
|
86
|
+
onSortingChange: (updater) => {
|
|
87
|
+
const newSorting = typeof updater === 'function' ? updater(sorting) : updater;
|
|
88
|
+
setSorting(newSorting);
|
|
89
|
+
sortingOptions?.onSortingChange?.(newSorting);
|
|
90
|
+
},
|
|
91
|
+
onColumnFiltersChange: (updater) => {
|
|
92
|
+
const newFilters = typeof updater === 'function' ? updater(columnFilters) : updater;
|
|
93
|
+
setColumnFilters(newFilters);
|
|
94
|
+
filteringOptions?.onFiltersChange?.(newFilters);
|
|
95
|
+
},
|
|
96
|
+
onGlobalFilterChange: setGlobalFilter,
|
|
97
|
+
onColumnVisibilityChange: (updater) => {
|
|
98
|
+
const newVisibility = typeof updater === 'function' ? updater(columnVisibility) : updater;
|
|
99
|
+
setColumnVisibility(newVisibility);
|
|
100
|
+
columnVisibilityOptions?.onVisibilityChange?.(newVisibility);
|
|
101
|
+
},
|
|
102
|
+
onRowSelectionChange: (updater) => {
|
|
103
|
+
const newSelection = typeof updater === 'function' ? updater(rowSelectionState) : updater;
|
|
104
|
+
setRowSelectionState(newSelection);
|
|
105
|
+
},
|
|
106
|
+
getCoreRowModel: getCoreRowModel(),
|
|
107
|
+
getSortedRowModel: sortingOptions?.enabled !== false ? getSortedRowModel() : undefined,
|
|
108
|
+
getFilteredRowModel: filteringOptions?.enabled !== false ? getFilteredRowModel() : undefined,
|
|
109
|
+
getPaginationRowModel: paginationOptions?.enabled !== false ? getPaginationRowModel() : undefined,
|
|
110
|
+
getRowId: getRowId,
|
|
111
|
+
enableRowSelection: rowSelectionOptions?.enabled ?? false,
|
|
112
|
+
enableMultiRowSelection: rowSelectionOptions?.mode !== 'single',
|
|
113
|
+
enableSorting: sortingOptions?.enabled ?? true,
|
|
114
|
+
enableMultiSort: sortingOptions?.enableMultiSort ?? false,
|
|
115
|
+
enableGlobalFilter: filteringOptions?.enableGlobalFilter ?? true,
|
|
116
|
+
enableColumnFilters: filteringOptions?.enableColumnFilters ?? false,
|
|
117
|
+
manualSorting: sortingOptions?.serverSide,
|
|
118
|
+
manualFiltering: filteringOptions?.serverSide,
|
|
119
|
+
manualPagination: paginationOptions?.serverSide,
|
|
120
|
+
pageCount: paginationOptions?.serverSide
|
|
121
|
+
? Math.ceil((paginationOptions.totalRows ?? 0) / (paginationOptions.pageSize ?? 10))
|
|
122
|
+
: undefined,
|
|
123
|
+
});
|
|
124
|
+
// Update pagination if controlled
|
|
125
|
+
React.useEffect(() => {
|
|
126
|
+
if (paginationOptions?.pageSize) {
|
|
127
|
+
table.setPageSize(paginationOptions.pageSize);
|
|
128
|
+
}
|
|
129
|
+
if (typeof paginationOptions?.pageIndex === 'number') {
|
|
130
|
+
table.setPageIndex(paginationOptions.pageIndex);
|
|
131
|
+
}
|
|
132
|
+
}, [paginationOptions?.pageSize, paginationOptions?.pageIndex, table]);
|
|
133
|
+
// Notify parent of selection changes
|
|
134
|
+
React.useEffect(() => {
|
|
135
|
+
if (rowSelectionOptions?.onSelectionChange) {
|
|
136
|
+
const selectedRows = table.getSelectedRowModel().rows.map((row) => row.original);
|
|
137
|
+
rowSelectionOptions.onSelectionChange(selectedRows);
|
|
138
|
+
}
|
|
139
|
+
}, [rowSelectionState, table, rowSelectionOptions]);
|
|
140
|
+
// Export handler
|
|
141
|
+
const handleExport = useCallback((format) => {
|
|
142
|
+
if (exportOptions?.onExport) {
|
|
143
|
+
const exportData = table.getFilteredRowModel().rows.map((row) => row.original);
|
|
144
|
+
exportOptions.onExport(format, exportData);
|
|
145
|
+
return;
|
|
146
|
+
}
|
|
147
|
+
// Default export implementation
|
|
148
|
+
const rows = table.getFilteredRowModel().rows;
|
|
149
|
+
const exportColumns = columns.filter((col) => {
|
|
150
|
+
if (col.id === 'select' || col.id === 'actions')
|
|
151
|
+
return false;
|
|
152
|
+
if (exportOptions?.includeColumns?.length) {
|
|
153
|
+
return exportOptions.includeColumns.includes(col.id ?? '');
|
|
154
|
+
}
|
|
155
|
+
if (exportOptions?.excludeColumns?.length) {
|
|
156
|
+
return !exportOptions.excludeColumns.includes(col.id ?? '');
|
|
157
|
+
}
|
|
158
|
+
return true;
|
|
159
|
+
});
|
|
160
|
+
const exportData = rows.map((row) => {
|
|
161
|
+
const rowData = {};
|
|
162
|
+
exportColumns.forEach((col) => {
|
|
163
|
+
const cellValue = row.getValue(col.id ?? '');
|
|
164
|
+
rowData[col.id ?? ''] = cellValue;
|
|
165
|
+
});
|
|
166
|
+
return rowData;
|
|
167
|
+
});
|
|
168
|
+
const filename = exportOptions?.filename ?? 'export';
|
|
169
|
+
if (format === 'csv') {
|
|
170
|
+
const headers = exportColumns.map((col) => col.id ?? '').join(',');
|
|
171
|
+
const csvRows = exportData.map((row) => exportColumns.map((col) => JSON.stringify(row[col.id ?? ''] ?? '')).join(','));
|
|
172
|
+
const csv = [headers, ...csvRows].join('\n');
|
|
173
|
+
downloadFile(csv, `${filename}.csv`, 'text/csv');
|
|
174
|
+
}
|
|
175
|
+
else if (format === 'json') {
|
|
176
|
+
const json = JSON.stringify(exportData, null, 2);
|
|
177
|
+
downloadFile(json, `${filename}.json`, 'application/json');
|
|
178
|
+
}
|
|
179
|
+
}, [table, columns, exportOptions]);
|
|
180
|
+
// Get selected rows for bulk actions
|
|
181
|
+
const selectedRows = useMemo(() => table.getSelectedRowModel().rows.map((row) => row.original), [table, rowSelectionState]);
|
|
182
|
+
// Column count for empty/loading states
|
|
183
|
+
const colCount = columns.length;
|
|
184
|
+
return (_jsxs("div", { className: cn('bg-white rounded-lg border border-gray-200 shadow-sm overflow-hidden', className, classNames?.wrapper), children: [_jsx(DataTableToolbar, { title: title, description: description, globalFilter: globalFilter, setGlobalFilter: setGlobalFilter, enableGlobalFilter: filteringOptions?.enableGlobalFilter !== false, globalFilterPlaceholder: filteringOptions?.globalFilterPlaceholder, filterDebounceMs: filteringOptions?.filterDebounceMs, columnVisibility: columnVisibility, setColumnVisibility: setColumnVisibility, columnVisibilityOptions: columnVisibilityOptions, allColumns: table.getAllColumns(), exportOptions: exportOptions, onExport: exportOptions?.enabled ? handleExport : undefined, onRefresh: onRefresh, selectedCount: selectedRows.length, bulkActions: bulkActions, selectedRows: selectedRows, headerContent: headerContent, classNames: classNames }), _jsx("div", { className: cn('overflow-auto', maxHeight && 'overflow-y-auto'), style: { maxHeight: maxHeight }, children: _jsxs("table", { className: cn('w-full text-sm', bordered && 'border-collapse', compact && 'text-xs', classNames?.table), children: [_jsx(DataTableHeader, { table: table, stickyHeader: stickyHeader, classNames: classNames }), loading ? (_jsx(DataTableLoading, { rowCount: 5, colCount: colCount, classNames: classNames })) : error ? (_jsx("tbody", { children: _jsx(DataTableError, { error: error, onRetry: onRefresh, classNames: classNames, colSpan: colCount }) })) : table.getRowModel().rows.length === 0 ? (_jsx("tbody", { children: _jsx(DataTableEmpty, { message: emptyMessage, classNames: classNames, colSpan: colCount }) })) : (_jsx(DataTableBody, { table: table, striped: striped, hoverable: hoverable, onRowClick: onRowClick, onRowDoubleClick: onRowDoubleClick, rowClassName: rowClassName, classNames: classNames }))] }) }), paginationOptions?.enabled !== false && !loading && !error && data.length > 0 && (_jsx(DataTablePagination, { pageIndex: table.getState().pagination.pageIndex, pageSize: table.getState().pagination.pageSize, totalRows: paginationOptions?.serverSide ? (paginationOptions.totalRows ?? 0) : data.length, pageCount: table.getPageCount(), canPreviousPage: table.getCanPreviousPage(), canNextPage: table.getCanNextPage(), previousPage: table.previousPage, nextPage: table.nextPage, firstPage: () => table.setPageIndex(0), lastPage: () => table.setPageIndex(table.getPageCount() - 1), setPageIndex: table.setPageIndex, setPageSize: (size) => {
|
|
185
|
+
table.setPageSize(size);
|
|
186
|
+
paginationOptions?.onPaginationChange?.({
|
|
187
|
+
pageIndex: 0,
|
|
188
|
+
pageSize: size,
|
|
189
|
+
});
|
|
190
|
+
}, options: paginationOptions, classNames: classNames })), footerContent && _jsx("div", { className: "px-4 py-3 border-t border-gray-200", children: footerContent })] }));
|
|
191
|
+
}
|
|
192
|
+
/**
|
|
193
|
+
* Utility function to download file
|
|
194
|
+
*/
|
|
195
|
+
function downloadFile(content, filename, mimeType) {
|
|
196
|
+
const blob = new Blob([content], { type: mimeType });
|
|
197
|
+
const url = URL.createObjectURL(blob);
|
|
198
|
+
const link = document.createElement('a');
|
|
199
|
+
link.href = url;
|
|
200
|
+
link.download = filename;
|
|
201
|
+
document.body.appendChild(link);
|
|
202
|
+
link.click();
|
|
203
|
+
document.body.removeChild(link);
|
|
204
|
+
URL.revokeObjectURL(url);
|
|
205
|
+
}
|
|
206
|
+
export default DataTable;
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview DataTable Body Component
|
|
3
|
+
*/
|
|
4
|
+
import { type Table } from '@tanstack/react-table';
|
|
5
|
+
import type { DataTableClassNames } from '../types';
|
|
6
|
+
interface DataTableBodyProps<TData> {
|
|
7
|
+
table: Table<TData>;
|
|
8
|
+
striped?: boolean;
|
|
9
|
+
hoverable?: boolean;
|
|
10
|
+
onRowClick?: (row: TData) => void;
|
|
11
|
+
onRowDoubleClick?: (row: TData) => void;
|
|
12
|
+
rowClassName?: string | ((row: TData, index: number) => string);
|
|
13
|
+
classNames?: DataTableClassNames;
|
|
14
|
+
}
|
|
15
|
+
/**
|
|
16
|
+
* DataTable Body Component
|
|
17
|
+
*/
|
|
18
|
+
export declare function DataTableBody<TData>({ table, striped, hoverable, onRowClick, onRowDoubleClick, rowClassName, classNames, }: DataTableBodyProps<TData>): import("react/jsx-runtime").JSX.Element;
|
|
19
|
+
export default DataTableBody;
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
+
/**
|
|
3
|
+
* @fileoverview DataTable Body Component
|
|
4
|
+
*/
|
|
5
|
+
import { flexRender } from '@tanstack/react-table';
|
|
6
|
+
import { cn } from '../../helpers';
|
|
7
|
+
/**
|
|
8
|
+
* DataTable Body Component
|
|
9
|
+
*/
|
|
10
|
+
export function DataTableBody({ table, striped, hoverable, onRowClick, onRowDoubleClick, rowClassName, classNames, }) {
|
|
11
|
+
const rows = table.getRowModel().rows;
|
|
12
|
+
return (_jsx("tbody", { className: cn('divide-y divide-gray-200', classNames?.tbody), children: rows.map((row, index) => {
|
|
13
|
+
const customClassName = typeof rowClassName === 'function' ? rowClassName(row.original, index) : rowClassName;
|
|
14
|
+
return (_jsx("tr", { className: cn('transition-colors', striped && index % 2 === 1 && 'bg-gray-50/50', hoverable && 'hover:bg-gray-50', (onRowClick || onRowDoubleClick) && 'cursor-pointer', row.getIsSelected() && 'bg-blue-50', customClassName, classNames?.tr), onClick: () => onRowClick?.(row.original), onDoubleClick: () => onRowDoubleClick?.(row.original), children: row.getVisibleCells().map((cell) => {
|
|
15
|
+
const alignment = cell.column.columnDef.meta?.align ?? 'left';
|
|
16
|
+
return (_jsx("td", { className: cn('px-4 py-3 text-sm text-gray-900', alignment === 'center' && 'text-center', alignment === 'right' && 'text-right', classNames?.td), children: flexRender(cell.column.columnDef.cell, cell.getContext()) }, cell.id));
|
|
17
|
+
}) }, row.id));
|
|
18
|
+
}) }));
|
|
19
|
+
}
|
|
20
|
+
export default DataTableBody;
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import type { DataTableClassNames } from '../types';
|
|
3
|
+
interface DataTableEmptyProps {
|
|
4
|
+
/** Empty message */
|
|
5
|
+
message?: string | React.ReactNode;
|
|
6
|
+
/** Custom icon */
|
|
7
|
+
icon?: React.ReactNode;
|
|
8
|
+
/** Custom classNames */
|
|
9
|
+
classNames?: DataTableClassNames;
|
|
10
|
+
/** Number of columns for colspan */
|
|
11
|
+
colSpan?: number;
|
|
12
|
+
}
|
|
13
|
+
/**
|
|
14
|
+
* DataTable Empty State Component
|
|
15
|
+
*/
|
|
16
|
+
export declare function DataTableEmpty({ message, icon, classNames, colSpan }: DataTableEmptyProps): import("react/jsx-runtime").JSX.Element;
|
|
17
|
+
export default DataTableEmpty;
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
/**
|
|
3
|
+
* @fileoverview DataTable Empty State Component
|
|
4
|
+
*/
|
|
5
|
+
import { Inbox } from 'lucide-react';
|
|
6
|
+
import { cn } from '../../helpers';
|
|
7
|
+
/**
|
|
8
|
+
* DataTable Empty State Component
|
|
9
|
+
*/
|
|
10
|
+
export function DataTableEmpty({ message = 'No data available', icon, classNames, colSpan = 1 }) {
|
|
11
|
+
return (_jsx("tr", { children: _jsx("td", { colSpan: colSpan, className: cn('px-4 py-12', classNames?.empty), children: _jsxs("div", { className: "flex flex-col items-center justify-center text-gray-500", children: [icon ?? _jsx(Inbox, { className: "w-12 h-12 mb-3 text-gray-300" }), _jsx("div", { className: "text-sm", children: message })] }) }) }));
|
|
12
|
+
}
|
|
13
|
+
export default DataTableEmpty;
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import type { DataTableClassNames } from '../types';
|
|
2
|
+
interface DataTableErrorProps {
|
|
3
|
+
/** Error message or object */
|
|
4
|
+
error?: Error | string | null;
|
|
5
|
+
/** Retry handler */
|
|
6
|
+
onRetry?: () => void;
|
|
7
|
+
/** Custom classNames */
|
|
8
|
+
classNames?: DataTableClassNames;
|
|
9
|
+
/** Number of columns for colspan */
|
|
10
|
+
colSpan?: number;
|
|
11
|
+
}
|
|
12
|
+
/**
|
|
13
|
+
* DataTable Error State Component
|
|
14
|
+
*/
|
|
15
|
+
export declare function DataTableError({ error, onRetry, classNames, colSpan }: DataTableErrorProps): import("react/jsx-runtime").JSX.Element;
|
|
16
|
+
export default DataTableError;
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
/**
|
|
3
|
+
* @fileoverview DataTable Error State Component
|
|
4
|
+
*/
|
|
5
|
+
import { AlertCircle, RefreshCw } from 'lucide-react';
|
|
6
|
+
import { cn } from '../../helpers';
|
|
7
|
+
/**
|
|
8
|
+
* DataTable Error State Component
|
|
9
|
+
*/
|
|
10
|
+
export function DataTableError({ error, onRetry, classNames, colSpan = 1 }) {
|
|
11
|
+
const errorMessage = error instanceof Error ? error.message : typeof error === 'string' ? error : 'An error occurred while loading data';
|
|
12
|
+
return (_jsx("tr", { children: _jsx("td", { colSpan: colSpan, className: cn('px-4 py-12', classNames?.error), children: _jsxs("div", { className: "flex flex-col items-center justify-center", children: [_jsx(AlertCircle, { className: "w-12 h-12 mb-3 text-red-400" }), _jsx("div", { className: "text-sm text-red-600 mb-3", children: errorMessage }), onRetry && (_jsxs("button", { onClick: onRetry, className: "flex items-center gap-2 px-4 py-2 text-sm font-medium text-gray-700 bg-white border border-gray-300 rounded-md hover:bg-gray-50 transition-colors", children: [_jsx(RefreshCw, { className: "w-4 h-4" }), "Retry"] }))] }) }) }));
|
|
13
|
+
}
|
|
14
|
+
export default DataTableError;
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview DataTable Header Component
|
|
3
|
+
*/
|
|
4
|
+
import { type Table } from '@tanstack/react-table';
|
|
5
|
+
import type { DataTableClassNames } from '../types';
|
|
6
|
+
interface DataTableHeaderProps<TData> {
|
|
7
|
+
table: Table<TData>;
|
|
8
|
+
stickyHeader?: boolean;
|
|
9
|
+
classNames?: DataTableClassNames;
|
|
10
|
+
}
|
|
11
|
+
/**
|
|
12
|
+
* DataTable Header Component
|
|
13
|
+
*/
|
|
14
|
+
export declare function DataTableHeader<TData>({ table, stickyHeader, classNames }: DataTableHeaderProps<TData>): import("react/jsx-runtime").JSX.Element;
|
|
15
|
+
export default DataTableHeader;
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
/**
|
|
3
|
+
* @fileoverview DataTable Header Component
|
|
4
|
+
*/
|
|
5
|
+
import { flexRender } from '@tanstack/react-table';
|
|
6
|
+
import { ChevronDown, ChevronUp, ChevronsUpDown } from 'lucide-react';
|
|
7
|
+
import { cn } from '../../helpers';
|
|
8
|
+
/**
|
|
9
|
+
* Sort indicator component
|
|
10
|
+
*/
|
|
11
|
+
function SortIndicator({ direction }) {
|
|
12
|
+
if (direction === 'asc') {
|
|
13
|
+
return _jsx(ChevronUp, { className: "w-4 h-4 ml-1" });
|
|
14
|
+
}
|
|
15
|
+
if (direction === 'desc') {
|
|
16
|
+
return _jsx(ChevronDown, { className: "w-4 h-4 ml-1" });
|
|
17
|
+
}
|
|
18
|
+
return _jsx(ChevronsUpDown, { className: "w-4 h-4 ml-1 opacity-30" });
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* DataTable Header Component
|
|
22
|
+
*/
|
|
23
|
+
export function DataTableHeader({ table, stickyHeader, classNames }) {
|
|
24
|
+
return (_jsx("thead", { className: cn('bg-gray-50 border-b border-gray-200', stickyHeader && 'sticky top-0 z-10', classNames?.thead), children: table.getHeaderGroups().map((headerGroup) => (_jsx("tr", { className: classNames?.tr, children: headerGroup.headers.map((header) => {
|
|
25
|
+
const canSort = header.column.getCanSort();
|
|
26
|
+
const sortDirection = header.column.getIsSorted();
|
|
27
|
+
const alignment = header.column.columnDef.meta?.align ?? 'left';
|
|
28
|
+
return (_jsx("th", { colSpan: header.colSpan, style: { width: header.getSize() !== 150 ? header.getSize() : undefined }, className: cn('px-4 py-3 text-xs font-semibold text-gray-600 uppercase tracking-wider', alignment === 'center' && 'text-center', alignment === 'right' && 'text-right', canSort && 'cursor-pointer select-none hover:bg-gray-100', classNames?.th), onClick: canSort ? header.column.getToggleSortingHandler() : undefined, children: header.isPlaceholder ? null : (_jsxs("div", { className: cn('flex items-center', alignment === 'center' && 'justify-center', alignment === 'right' && 'justify-end'), children: [flexRender(header.column.columnDef.header, header.getContext()), canSort && _jsx(SortIndicator, { direction: sortDirection })] })) }, header.id));
|
|
29
|
+
}) }, headerGroup.id))) }));
|
|
30
|
+
}
|
|
31
|
+
export default DataTableHeader;
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import type { DataTableClassNames } from '../types';
|
|
2
|
+
interface DataTableLoadingProps {
|
|
3
|
+
/** Number of skeleton rows */
|
|
4
|
+
rowCount?: number;
|
|
5
|
+
/** Number of columns for skeleton */
|
|
6
|
+
colCount?: number;
|
|
7
|
+
/** Custom classNames */
|
|
8
|
+
classNames?: DataTableClassNames;
|
|
9
|
+
}
|
|
10
|
+
/**
|
|
11
|
+
* DataTable Loading State Component
|
|
12
|
+
*/
|
|
13
|
+
export declare function DataTableLoading({ rowCount, colCount, classNames }: DataTableLoadingProps): import("react/jsx-runtime").JSX.Element;
|
|
14
|
+
export default DataTableLoading;
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
+
import { cn } from '../../helpers';
|
|
3
|
+
/**
|
|
4
|
+
* DataTable Loading State Component
|
|
5
|
+
*/
|
|
6
|
+
export function DataTableLoading({ rowCount = 5, colCount = 4, classNames }) {
|
|
7
|
+
return (_jsx("tbody", { className: cn('animate-pulse', classNames?.loading), children: Array.from({ length: rowCount })
|
|
8
|
+
.map((value, index) => {
|
|
9
|
+
void value;
|
|
10
|
+
return index;
|
|
11
|
+
})
|
|
12
|
+
.map((rowIndex) => (_jsx("tr", { className: "border-b border-gray-100", children: Array.from({ length: colCount })
|
|
13
|
+
.map((value, index) => {
|
|
14
|
+
void value;
|
|
15
|
+
return index;
|
|
16
|
+
})
|
|
17
|
+
.map((colIndex) => (_jsx("td", { className: "px-4 py-3", children: _jsx("div", { className: "h-4 bg-gray-200 rounded w-full max-w-[150px]" }) }, colIndex))) }, rowIndex))) }));
|
|
18
|
+
}
|
|
19
|
+
export default DataTableLoading;
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import type { DataTableClassNames, PaginationOptions } from '../types';
|
|
2
|
+
interface DataTablePaginationProps {
|
|
3
|
+
/** Current page index (0-based) */
|
|
4
|
+
pageIndex: number;
|
|
5
|
+
/** Items per page */
|
|
6
|
+
pageSize: number;
|
|
7
|
+
/** Total number of rows */
|
|
8
|
+
totalRows: number;
|
|
9
|
+
/** Total number of pages */
|
|
10
|
+
pageCount: number;
|
|
11
|
+
/** Can go to previous page */
|
|
12
|
+
canPreviousPage: boolean;
|
|
13
|
+
/** Can go to next page */
|
|
14
|
+
canNextPage: boolean;
|
|
15
|
+
/** Go to previous page */
|
|
16
|
+
previousPage: () => void;
|
|
17
|
+
/** Go to next page */
|
|
18
|
+
nextPage: () => void;
|
|
19
|
+
/** Go to first page */
|
|
20
|
+
firstPage: () => void;
|
|
21
|
+
/** Go to last page */
|
|
22
|
+
lastPage: () => void;
|
|
23
|
+
/** Set page index */
|
|
24
|
+
setPageIndex: (index: number) => void;
|
|
25
|
+
/** Set page size */
|
|
26
|
+
setPageSize: (size: number) => void;
|
|
27
|
+
/** Pagination options */
|
|
28
|
+
options?: PaginationOptions;
|
|
29
|
+
/** Custom classNames */
|
|
30
|
+
classNames?: DataTableClassNames;
|
|
31
|
+
}
|
|
32
|
+
/**
|
|
33
|
+
* DataTable Pagination Component
|
|
34
|
+
*/
|
|
35
|
+
export declare function DataTablePagination({ pageIndex, pageSize, totalRows, pageCount, canPreviousPage, canNextPage, previousPage, nextPage, firstPage, lastPage, setPageIndex, setPageSize, options, classNames, }: DataTablePaginationProps): import("react/jsx-runtime").JSX.Element;
|
|
36
|
+
export default DataTablePagination;
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
/**
|
|
3
|
+
* @fileoverview DataTable Pagination Component
|
|
4
|
+
*/
|
|
5
|
+
import { ChevronLeft, ChevronRight, ChevronsLeft, ChevronsRight } from 'lucide-react';
|
|
6
|
+
import { cn } from '../../helpers';
|
|
7
|
+
/**
|
|
8
|
+
* DataTable Pagination Component
|
|
9
|
+
*/
|
|
10
|
+
export function DataTablePagination({ pageIndex, pageSize, totalRows, pageCount, canPreviousPage, canNextPage, previousPage, nextPage, firstPage, lastPage, setPageIndex, setPageSize, options = {}, classNames, }) {
|
|
11
|
+
const { pageSizeOptions = [10, 25, 50, 100], showPageSizeSelector = true, showPageInfo = true } = options;
|
|
12
|
+
// Calculate display range
|
|
13
|
+
const start = totalRows === 0 ? 0 : pageIndex * pageSize + 1;
|
|
14
|
+
const end = Math.min((pageIndex + 1) * pageSize, totalRows);
|
|
15
|
+
return (_jsxs("div", { className: cn('flex items-center justify-between px-4 py-3 border-t border-gray-200 bg-white', classNames?.pagination), children: [_jsx("div", { className: "flex items-center gap-2", children: showPageSizeSelector && (_jsxs(_Fragment, { children: [_jsx("span", { className: "text-sm text-gray-600", children: "Rows per page:" }), _jsx("select", { value: pageSize, onChange: (e) => setPageSize(Number(e.target.value)), className: "px-2 py-1 text-sm border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500 focus:border-transparent", children: pageSizeOptions.map((size) => (_jsx("option", { value: size, children: size }, size))) })] })) }), showPageInfo && (_jsxs("div", { className: "text-sm text-gray-600", children: [start, "-", end, " of ", totalRows.toLocaleString()] })), _jsxs("div", { className: "flex items-center gap-1", children: [_jsx("button", { onClick: firstPage, disabled: !canPreviousPage, className: cn('p-1.5 rounded-md transition-colors', canPreviousPage ? 'text-gray-600 hover:bg-gray-100' : 'text-gray-300 cursor-not-allowed'), "aria-label": "First page", children: _jsx(ChevronsLeft, { className: "w-4 h-4" }) }), _jsx("button", { onClick: previousPage, disabled: !canPreviousPage, className: cn('p-1.5 rounded-md transition-colors', canPreviousPage ? 'text-gray-600 hover:bg-gray-100' : 'text-gray-300 cursor-not-allowed'), "aria-label": "Previous page", children: _jsx(ChevronLeft, { className: "w-4 h-4" }) }), _jsxs("div", { className: "flex items-center gap-1 mx-2", children: [_jsx("span", { className: "text-sm text-gray-600", children: "Page" }), _jsx("input", { type: "number", min: 1, max: pageCount, value: pageIndex + 1, onChange: (e) => {
|
|
16
|
+
const page = e.target.value ? Number(e.target.value) - 1 : 0;
|
|
17
|
+
setPageIndex(Math.min(Math.max(0, page), pageCount - 1));
|
|
18
|
+
}, className: "w-14 px-2 py-1 text-sm text-center border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500 focus:border-transparent" }), _jsxs("span", { className: "text-sm text-gray-600", children: ["of ", pageCount] })] }), _jsx("button", { onClick: nextPage, disabled: !canNextPage, className: cn('p-1.5 rounded-md transition-colors', canNextPage ? 'text-gray-600 hover:bg-gray-100' : 'text-gray-300 cursor-not-allowed'), "aria-label": "Next page", children: _jsx(ChevronRight, { className: "w-4 h-4" }) }), _jsx("button", { onClick: lastPage, disabled: !canNextPage, className: cn('p-1.5 rounded-md transition-colors', canNextPage ? 'text-gray-600 hover:bg-gray-100' : 'text-gray-300 cursor-not-allowed'), "aria-label": "Last page", children: _jsx(ChevronsRight, { className: "w-4 h-4" }) })] })] }));
|
|
19
|
+
}
|
|
20
|
+
export default DataTablePagination;
|