@chumsinc/sortable-tables 2.1.2 → 3.0.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/CHANGELOG.md +87 -48
- package/README.md +94 -4
- package/dist/DataTable.d.ts +6 -6
- package/dist/DataTableCell.d.ts +299 -295
- package/dist/DataTableCols.d.ts +5 -0
- package/dist/DataTableContext.d.ts +10 -0
- package/dist/DataTableHead.d.ts +2 -2
- package/dist/DataTableProvider.d.ts +12 -0
- package/dist/DataTableRow.d.ts +1 -1
- package/dist/DataTableTBody.d.ts +1 -1
- package/dist/DataTableTH.d.ts +6 -6
- package/dist/RowsPerPage.d.ts +0 -1
- package/dist/SortableTable.d.ts +6 -6
- package/dist/SortableTableHead.d.ts +6 -6
- package/dist/SortableTableHeadWrapper.d.ts +9 -0
- package/dist/SortableTableTH.d.ts +6 -6
- package/dist/StandaloneDataTable.d.ts +6 -0
- package/dist/StandaloneSortHelper.d.ts +5 -0
- package/dist/StandaloneSortableTable.d.ts +6 -0
- package/dist/Table.d.ts +6 -5
- package/dist/index.cjs.js +30 -28
- package/dist/index.cjs.js.map +1 -1
- package/dist/index.d.ts +20 -10
- package/dist/index.es.js +521 -388
- package/dist/index.es.js.map +1 -1
- package/dist/types.d.ts +104 -105
- package/dist/useField.d.ts +6 -0
- package/dist/useTableContext.d.ts +2 -0
- package/dist/useTableFields.d.ts +9 -0
- package/dist/useTableSort.d.ts +9 -0
- package/eslint.config.mjs +3 -3
- package/package.json +7 -5
- package/src/DataTable.tsx +23 -28
- package/src/DataTableCell.tsx +33 -28
- package/src/DataTableCols.tsx +18 -0
- package/src/DataTableContext.ts +13 -0
- package/src/DataTableHead.tsx +9 -9
- package/src/DataTableProvider.tsx +62 -0
- package/src/DataTableRow.tsx +10 -8
- package/src/DataTableTBody.tsx +1 -5
- package/src/DataTableTH.tsx +11 -9
- package/src/RowsPerPage.tsx +6 -9
- package/src/SortableTable.tsx +26 -28
- package/src/SortableTableHead.tsx +17 -16
- package/src/SortableTableHeadWrapper.tsx +20 -0
- package/src/SortableTableTH.tsx +11 -8
- package/src/StandaloneDataTable.tsx +16 -0
- package/src/StandaloneSortHelper.tsx +15 -0
- package/src/StandaloneSortableTable.tsx +21 -0
- package/src/Table.tsx +49 -44
- package/src/TablePagination.tsx +4 -6
- package/src/index.tsx +26 -12
- package/src/types.ts +127 -128
- package/src/useField.ts +19 -0
- package/src/useTableContext.ts +10 -0
- package/src/useTableFields.ts +20 -0
- package/src/useTableSort.ts +20 -0
- package/test/Main.tsx +37 -0
- package/test/TableColumnsHandler.tsx +28 -0
- package/test/TestTable.tsx +51 -68
- package/test/data.ts +232 -232
- package/test/index.tsx +11 -11
- package/test/tableFields.tsx +52 -0
- package/test/utils.ts +19 -0
- package/tsconfig.json +1 -0
- package/vite.config.ts +1 -2
package/src/Table.tsx
CHANGED
|
@@ -1,44 +1,49 @@
|
|
|
1
|
-
import React, {TableHTMLAttributes} from 'react';
|
|
2
|
-
import styled from "@emotion/styled";
|
|
3
|
-
import type {DataTableProps} from "./types";
|
|
4
|
-
import
|
|
5
|
-
|
|
6
|
-
export
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
1
|
+
import React, {type RefObject, type TableHTMLAttributes} from 'react';
|
|
2
|
+
import styled from "@emotion/styled";
|
|
3
|
+
import type {DataTableProps} from "./types";
|
|
4
|
+
import clsx from "clsx";
|
|
5
|
+
|
|
6
|
+
export interface StyledTableProps extends TableHTMLAttributes<HTMLTableElement>, Pick<DataTableProps, 'sticky' | 'responsive'> {
|
|
7
|
+
ref?: RefObject<HTMLTableElement>;
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
const StyledTable = styled.table<StyledTableProps>`
|
|
11
|
+
--table-sticky-top: ${props => props.sticky ? '0' : undefined};
|
|
12
|
+
|
|
13
|
+
thead {
|
|
14
|
+
tr:nth-of-type(1) td,
|
|
15
|
+
tr:nth-of-type(1) th {
|
|
16
|
+
top: var(--table-sticky-top, unset);
|
|
17
|
+
position: ${props => props.sticky ? "sticky" : "unset"};
|
|
18
|
+
z-index: ${props => props.sticky ? 10 : "unset"};
|
|
19
|
+
background: ${props => props.sticky ? "linear-gradient(var(--bs-table-bg) 75%, rgba(var(--bs-secondary-bg-rgb), 0.9))" : "unset"};
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
`
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
export default function Table({
|
|
26
|
+
sticky,
|
|
27
|
+
responsive,
|
|
28
|
+
children,
|
|
29
|
+
className,
|
|
30
|
+
ref,
|
|
31
|
+
...rest
|
|
32
|
+
}: StyledTableProps) {
|
|
33
|
+
if (responsive) {
|
|
34
|
+
const _className = clsx(className, {
|
|
35
|
+
'table-responsive': responsive === true,
|
|
36
|
+
[`table-responsive-${responsive}`]: responsive !== true,
|
|
37
|
+
})
|
|
38
|
+
return (
|
|
39
|
+
<div className={_className}>
|
|
40
|
+
<StyledTable ref={ref} {...rest}>{children}</StyledTable>
|
|
41
|
+
</div>
|
|
42
|
+
)
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
return (
|
|
46
|
+
<StyledTable className={className} sticky={sticky} ref={ref} {...rest}>{children}</StyledTable>
|
|
47
|
+
)
|
|
48
|
+
}
|
|
49
|
+
|
package/src/TablePagination.tsx
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
2
|
import RowsPerPage from "./RowsPerPage";
|
|
3
|
-
import classNames from "classnames";
|
|
4
3
|
import type {TablePaginationProps} from "./types";
|
|
4
|
+
import clsx from "clsx";
|
|
5
5
|
|
|
6
|
-
function TablePagination({
|
|
6
|
+
export default function TablePagination({
|
|
7
7
|
page,
|
|
8
8
|
rowsPerPage,
|
|
9
9
|
onChangePage,
|
|
@@ -20,10 +20,10 @@ function TablePagination({
|
|
|
20
20
|
const last = Math.min(page * rowsPerPage + rowsPerPage, count);
|
|
21
21
|
const lastPage = rowsPerPage === 0 ? 0 : Math.floor((count - 1) / rowsPerPage);
|
|
22
22
|
|
|
23
|
-
const buttonClassName =
|
|
23
|
+
const buttonClassName = clsx("btn btn-link", {[`btn-${size}`]: !!size});
|
|
24
24
|
|
|
25
25
|
return (
|
|
26
|
-
<div className={
|
|
26
|
+
<div className={clsx("row g-3 justify-content-end", className)} {...rest}>
|
|
27
27
|
{!!rowsPerPageProps && (
|
|
28
28
|
<div className="col-auto">
|
|
29
29
|
<RowsPerPage {...rowsPerPageProps} value={rowsPerPage} size={size}/>
|
|
@@ -67,6 +67,4 @@ function TablePagination({
|
|
|
67
67
|
</div>
|
|
68
68
|
)
|
|
69
69
|
}
|
|
70
|
-
|
|
71
70
|
TablePagination.displayname = 'TablePagination';
|
|
72
|
-
export default TablePagination
|
package/src/index.tsx
CHANGED
|
@@ -1,29 +1,43 @@
|
|
|
1
|
-
|
|
1
|
+
/* eslint-disable react-refresh/only-export-components */
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
export {default as DataTable} from './StandaloneDataTable';
|
|
2
5
|
export {default as DataTableRow} from './DataTableRow';
|
|
3
6
|
export {default as DataTableTBody} from './DataTableTBody';
|
|
4
7
|
export {default as DataTableTH} from './DataTableTH';
|
|
5
|
-
export {default as
|
|
8
|
+
export {default as StandaloneSortableTable} from './StandaloneSortableTable';
|
|
6
9
|
export {default as SortableTableHead} from './SortableTableHead';
|
|
7
10
|
export {default as SortableTableTH} from './SortableTableTH';
|
|
8
|
-
export {default as RowsPerPage
|
|
11
|
+
export {default as RowsPerPage} from './RowsPerPage';
|
|
9
12
|
export {default as TablePagination} from './TablePagination';
|
|
13
|
+
export {default as DataTableCols} from './DataTableCols'
|
|
14
|
+
export {default as DataTableWithContext} from './DataTable'
|
|
15
|
+
export {default as SortableTable} from './SortableTable'
|
|
16
|
+
export {default as DataTableProvider} from './DataTableProvider'
|
|
17
|
+
export {useField} from './useField'
|
|
18
|
+
export {useTableFields} from './useTableFields'
|
|
19
|
+
export {useTableSort} from './useTableSort'
|
|
20
|
+
export {useTableContext} from './useTableContext'
|
|
21
|
+
export {DataTableContext, type TableContextData} from './DataTableContext'
|
|
22
|
+
export type {TableProviderProps} from './DataTableProvider'
|
|
10
23
|
export type {
|
|
11
|
-
|
|
24
|
+
SortProps,
|
|
12
25
|
DataTableField,
|
|
13
|
-
DataTableTHProps,
|
|
14
|
-
DataTableClassNames,
|
|
15
|
-
DataTableProps,
|
|
16
26
|
SortableTableField,
|
|
27
|
+
DataTableColProps,
|
|
28
|
+
DataTableCellProps,
|
|
17
29
|
DataTableRowProps,
|
|
18
30
|
DataTableTBodyProps,
|
|
31
|
+
DataTableClassNames,
|
|
32
|
+
DataTableProps,
|
|
33
|
+
DataTableTHProps,
|
|
34
|
+
RowsPerPageProps,
|
|
19
35
|
SortableTableTHProps,
|
|
20
36
|
SortableTableHeadProps,
|
|
21
|
-
SortProps,
|
|
22
37
|
SortableTableProps,
|
|
23
|
-
UISize,
|
|
24
|
-
UIFlexAlign,
|
|
25
38
|
TablePaginationProps,
|
|
26
|
-
RowsPerPageProps,
|
|
27
39
|
UITableSize,
|
|
28
|
-
|
|
40
|
+
UISize,
|
|
41
|
+
UIFlexAlign
|
|
29
42
|
} from './types';
|
|
43
|
+
|
package/src/types.ts
CHANGED
|
@@ -1,128 +1,127 @@
|
|
|
1
|
-
import React, {type HTMLAttributes, type MouseEvent, type ReactNode, type TableHTMLAttributes} from 'react'
|
|
2
|
-
import {
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
export interface SortProps<T = unknown> {
|
|
6
|
-
field: keyof T;
|
|
7
|
-
ascending: boolean;
|
|
8
|
-
}
|
|
9
|
-
|
|
10
|
-
export type UISize = 'sm' | 'lg' | '';
|
|
11
|
-
export type UITableSize = UISize | 'xs';
|
|
12
|
-
|
|
13
|
-
export type DataTableClassNames<T = unknown> =
|
|
14
|
-
string
|
|
15
|
-
|
|
|
16
|
-
| ((row: T) => (string |
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
export type UIFlexAlign = 'start' | 'end' | 'center' | 'baseline' | 'stretch';
|
|
20
|
-
|
|
21
|
-
export interface DataTableField<T = unknown> {
|
|
22
|
-
id?: number | string;
|
|
23
|
-
field: keyof T;
|
|
24
|
-
title: ReactNode;
|
|
25
|
-
as?: 'td' | 'th';
|
|
26
|
-
align?: 'start' | 'center' | 'end';
|
|
27
|
-
render?: (row: T) => ReactNode;
|
|
28
|
-
className?: DataTableClassNames<T>;
|
|
29
|
-
colSpan?: number;
|
|
30
|
-
thProps?: Omit<DataTableTHProps<T>, 'field'>;
|
|
31
|
-
cellProps?: TableHTMLAttributes<HTMLTableCellElement
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
value: number;
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
}
|
|
128
|
-
|
|
1
|
+
import React, {type HTMLAttributes, type MouseEvent, type ReactNode, type TableHTMLAttributes} from 'react'
|
|
2
|
+
import type {ClassValue} from "clsx";
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
export interface SortProps<T = unknown> {
|
|
6
|
+
field: keyof T;
|
|
7
|
+
ascending: boolean;
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
export type UISize = 'sm' | 'lg' | '';
|
|
11
|
+
export type UITableSize = UISize | 'xs';
|
|
12
|
+
|
|
13
|
+
export type DataTableClassNames<T = unknown> =
|
|
14
|
+
string
|
|
15
|
+
| ClassValue
|
|
16
|
+
| ((row: T) => (string | ClassValue));
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
export type UIFlexAlign = 'start' | 'end' | 'center' | 'baseline' | 'stretch';
|
|
20
|
+
|
|
21
|
+
export interface DataTableField<T = unknown> {
|
|
22
|
+
id?: keyof T | (number & {}) | (string & {});
|
|
23
|
+
field: keyof T;
|
|
24
|
+
title: ReactNode;
|
|
25
|
+
as?: 'td' | 'th';
|
|
26
|
+
align?: 'start' | 'center' | 'end';
|
|
27
|
+
render?: (row: T) => ReactNode;
|
|
28
|
+
className?: DataTableClassNames<T>;
|
|
29
|
+
colSpan?: number;
|
|
30
|
+
thProps?: Omit<DataTableTHProps<T>, 'field'>;
|
|
31
|
+
cellProps?: TableHTMLAttributes<HTMLTableCellElement>;
|
|
32
|
+
visible?: boolean;
|
|
33
|
+
colClassName?: string;
|
|
34
|
+
sortable?: boolean;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
export type SortableTableField<T = unknown> = DataTableField<T>;
|
|
38
|
+
|
|
39
|
+
export interface DataTableProps<T = unknown> extends TableHTMLAttributes<HTMLTableElement> {
|
|
40
|
+
fields: DataTableField<T>[];
|
|
41
|
+
data: T[];
|
|
42
|
+
keyField: keyof T | ((row: T) => string | number);
|
|
43
|
+
size?: UITableSize;
|
|
44
|
+
sticky?: boolean;
|
|
45
|
+
responsive?: boolean | "sm" | "md" | "lg" | "xl" | 'xxl';
|
|
46
|
+
rowClassName?: DataTableClassNames<T>;
|
|
47
|
+
renderRow?: (row: T) => React.ReactNode;
|
|
48
|
+
onSelectRow?: (row: T, ev?: MouseEvent<HTMLTableRowElement>) => void;
|
|
49
|
+
selected?: string | number | ((row: T) => boolean);
|
|
50
|
+
tfoot?: React.ReactElement<HTMLTableSectionElement>;
|
|
51
|
+
tableHeadProps?: TableHTMLAttributes<HTMLTableSectionElement>;
|
|
52
|
+
children?: ReactNode;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
export interface DataTableCellProps<T = unknown> extends Omit<TableHTMLAttributes<HTMLTableCellElement>, 'className'> {
|
|
56
|
+
field: DataTableField<T>;
|
|
57
|
+
row: T;
|
|
58
|
+
as?: 'td' | 'th',
|
|
59
|
+
className?: string | ClassValue;
|
|
60
|
+
children?: React.ReactNode;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
export interface DataTableTHProps<T = unknown> extends Omit<DataTableCellProps<T>, 'row'> {
|
|
64
|
+
as?: 'th',
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
export interface DataTableTBodyProps<T = unknown> extends TableHTMLAttributes<HTMLTableSectionElement> {
|
|
68
|
+
data: T[];
|
|
69
|
+
keyField: keyof T | ((row: T) => string | number);
|
|
70
|
+
rowClassName?: DataTableClassNames<T>;
|
|
71
|
+
renderRow?: (row: T) => React.ReactNode;
|
|
72
|
+
onSelectRow?: (row: T, ev?: MouseEvent<HTMLTableRowElement>) => void;
|
|
73
|
+
selected?: string | number | ((row: T) => boolean);
|
|
74
|
+
children?: ReactNode;
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
export interface DataTableRowProps<T = unknown> extends Omit<TableHTMLAttributes<HTMLTableRowElement>, 'onClick'> {
|
|
78
|
+
rowClassName?: string | ClassValue | ((row: T) => string | ClassValue);
|
|
79
|
+
selected?: boolean;
|
|
80
|
+
row: T;
|
|
81
|
+
trRef?: React.Ref<HTMLTableRowElement>;
|
|
82
|
+
onClick?: (row: T, ev?: MouseEvent<HTMLTableRowElement>) => void;
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
export interface SortableTableProps<T = unknown> extends DataTableProps<T> {
|
|
86
|
+
fields: DataTableField<T>[];
|
|
87
|
+
currentSort: SortProps<T>;
|
|
88
|
+
onChangeSort: (sort: SortProps<T>) => void;
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
export interface SortableTableHeadProps<T = unknown> extends TableHTMLAttributes<HTMLTableSectionElement> {
|
|
92
|
+
fields: DataTableField<T>[];
|
|
93
|
+
currentSort: SortProps<T>|null;
|
|
94
|
+
onChangeSort: (sort: SortProps<T>) => void;
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
export interface SortableTableTHProps<T = unknown> extends Omit<DataTableTHProps<T>, 'onClick'> {
|
|
98
|
+
field: DataTableField<T>;
|
|
99
|
+
sorted?: boolean;
|
|
100
|
+
ascending?: boolean;
|
|
101
|
+
onClick: (sort: SortProps<T>) => void;
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
export interface RowsPerPageProps extends Omit<HTMLAttributes<HTMLSelectElement>, 'onChange'> {
|
|
105
|
+
value: number;
|
|
106
|
+
pageValues?: number[];
|
|
107
|
+
label?: string | React.ReactNode;
|
|
108
|
+
size?: UISize;
|
|
109
|
+
className?: string;
|
|
110
|
+
onChange: (value: number) => void;
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
export interface TablePaginationProps extends HTMLAttributes<HTMLDivElement> {
|
|
114
|
+
page: number;
|
|
115
|
+
rowsPerPage: number;
|
|
116
|
+
onChangePage: (page: number) => void;
|
|
117
|
+
count: number;
|
|
118
|
+
size?: UISize;
|
|
119
|
+
showFirst?: boolean;
|
|
120
|
+
showLast?: boolean;
|
|
121
|
+
rowsPerPageProps?: Omit<RowsPerPageProps, 'value'>;
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
|
|
125
|
+
export interface DataTableColProps<T = unknown> extends TableHTMLAttributes<HTMLTableSectionElement> {
|
|
126
|
+
fields: DataTableField<T>[];
|
|
127
|
+
}
|
package/src/useField.ts
ADDED
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import type {DataTableField} from "./types";
|
|
2
|
+
import {useContext} from "react";
|
|
3
|
+
import {DataTableContext, type TableContextData} from "./DataTableContext";
|
|
4
|
+
|
|
5
|
+
export type UseFieldArg<T = unknown> = keyof T & ((string | number) & {})
|
|
6
|
+
export function useField<T = unknown>(key: UseFieldArg<T>): [
|
|
7
|
+
field:DataTableField<T>|null,
|
|
8
|
+
updateField: (key: string|number, arg: Partial<DataTableField<T>>) => void
|
|
9
|
+
] {
|
|
10
|
+
const context = useContext(DataTableContext) as TableContextData<T>;
|
|
11
|
+
if (!context) {
|
|
12
|
+
throw new Error('useField must be used within a DataTableProvider');
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
return [
|
|
16
|
+
context.fields.find(field => field.id === key) ?? null,
|
|
17
|
+
context.updateField,
|
|
18
|
+
]
|
|
19
|
+
}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import {useContext} from "react";
|
|
2
|
+
import {DataTableContext, type TableContextData} from "./DataTableContext";
|
|
3
|
+
|
|
4
|
+
export function useTableContext<T = unknown>():TableContextData<T> {
|
|
5
|
+
const context = useContext(DataTableContext) as TableContextData<T>;
|
|
6
|
+
if (!context) {
|
|
7
|
+
throw new Error('useTableContext must be used within a DataTableProvider');
|
|
8
|
+
}
|
|
9
|
+
return context;
|
|
10
|
+
}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import {useContext} from "react";
|
|
2
|
+
import {DataTableContext, type TableContextData} from "./DataTableContext";
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Returns a tuple containing the fields and a function to update them.
|
|
6
|
+
* @returns [fields, setFields]
|
|
7
|
+
*/
|
|
8
|
+
export function useTableFields<T = unknown>(): [
|
|
9
|
+
fields: TableContextData<T>['fields'],
|
|
10
|
+
setFields: TableContextData<T>['setFields']
|
|
11
|
+
] {
|
|
12
|
+
const context = useContext(DataTableContext) as TableContextData<T>;
|
|
13
|
+
if (!context) {
|
|
14
|
+
throw new Error('useTableContext must be used within a DataTableProvider');
|
|
15
|
+
}
|
|
16
|
+
return [
|
|
17
|
+
context.fields,
|
|
18
|
+
context.setFields
|
|
19
|
+
];
|
|
20
|
+
}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import {useContext} from "react";
|
|
2
|
+
import {DataTableContext, type TableContextData} from "./DataTableContext";
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Returns a tuple containing the currentSort and a function to update the sort.
|
|
6
|
+
* @returns [sort, setSort]
|
|
7
|
+
*/
|
|
8
|
+
export function useTableSort<T = unknown>(): [
|
|
9
|
+
sort: TableContextData<T>['sort'],
|
|
10
|
+
setSort: TableContextData<T>['setSort']
|
|
11
|
+
] {
|
|
12
|
+
const context = useContext(DataTableContext) as TableContextData<T>;
|
|
13
|
+
if (!context) {
|
|
14
|
+
throw new Error('useTableSort must be used within a DataTableProvider');
|
|
15
|
+
}
|
|
16
|
+
return [
|
|
17
|
+
context.sort,
|
|
18
|
+
context.setSort
|
|
19
|
+
];
|
|
20
|
+
}
|
package/test/Main.tsx
ADDED
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import {useId, useState} from "react";
|
|
2
|
+
import {DataTableProvider, type SortProps, StandaloneSortableTable} from "../src";
|
|
3
|
+
import {type ProductLine, productLines, productLineSorter} from "./data";
|
|
4
|
+
import {tableFields} from "./tableFields";
|
|
5
|
+
import TestTable from "./TestTable";
|
|
6
|
+
|
|
7
|
+
export default function Main() {
|
|
8
|
+
const initialSort: SortProps<ProductLine> = {field: 'ProductLine', ascending: true};
|
|
9
|
+
const [list, setList] = useState<ProductLine[]>([...productLines].sort(productLineSorter(initialSort)));
|
|
10
|
+
const [sort, setSort] = useState<SortProps<ProductLine>>(initialSort);
|
|
11
|
+
const [withProvider, setWithProvider] = useState(true);
|
|
12
|
+
const idProviderCheckbox = useId();
|
|
13
|
+
|
|
14
|
+
const sortChangeHandler = (sort: SortProps<ProductLine>) => {
|
|
15
|
+
setList([...productLines.sort(productLineSorter(sort))])
|
|
16
|
+
setSort(sort);
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
return (
|
|
20
|
+
<div>
|
|
21
|
+
<div className="form-check form-check-inline">
|
|
22
|
+
<input className="form-check-input" type="checkbox" id={idProviderCheckbox} checked={withProvider}
|
|
23
|
+
onChange={e => setWithProvider(e.target.checked)}/>
|
|
24
|
+
<label className="form-check-label" htmlFor={idProviderCheckbox}>With DataTableProvider</label>
|
|
25
|
+
</div>
|
|
26
|
+
{withProvider && (
|
|
27
|
+
<DataTableProvider initialFields={tableFields} initialSort={initialSort}>
|
|
28
|
+
<TestTable data={list} onChangeSort={sortChangeHandler}/>
|
|
29
|
+
</DataTableProvider>
|
|
30
|
+
)}
|
|
31
|
+
{!withProvider && <StandaloneSortableTable fields={tableFields.map(f => ({...f, visible: true}))} data={list}
|
|
32
|
+
keyField={(row) => row.ProductLine}
|
|
33
|
+
currentSort={sort} onChangeSort={sortChangeHandler}/>
|
|
34
|
+
}
|
|
35
|
+
</div>
|
|
36
|
+
)
|
|
37
|
+
}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import {useTableContext} from "../src";
|
|
2
|
+
import React, {useCallback, useId} from "react";
|
|
3
|
+
import type {ProductLine} from "./data";
|
|
4
|
+
|
|
5
|
+
export default function TableColumnsHandler() {
|
|
6
|
+
const {updateField, getField} = useTableContext<ProductLine>();
|
|
7
|
+
const [visible, setVisible] = React.useState<boolean>(getField('ProductLineDesc')?.visible ?? true);
|
|
8
|
+
// const {sort} = useTableSort();
|
|
9
|
+
const id = useId();
|
|
10
|
+
|
|
11
|
+
const toggleFieldCollapse = useCallback((key: string, next: boolean) => {
|
|
12
|
+
console.debug('toggleFieldVisibility', key, next);
|
|
13
|
+
updateField(key, {visible: next})
|
|
14
|
+
setVisible(next);
|
|
15
|
+
}, [updateField]);
|
|
16
|
+
|
|
17
|
+
const handleVisibleChange = (ev: React.ChangeEvent<HTMLInputElement>) => {
|
|
18
|
+
toggleFieldCollapse('ProductLineDesc', ev.target.checked);
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
return (
|
|
22
|
+
<div style={{display: 'flex', alignItems: 'center', justifyContent: 'flex-start', gap: '1rem'}}>
|
|
23
|
+
<input type="checkbox" checked={visible} id={id} onChange={handleVisibleChange}/>
|
|
24
|
+
<label htmlFor={id}>Show Description</label>
|
|
25
|
+
{/*<code>{JSON.stringify(sort)}</code>*/}
|
|
26
|
+
</div>
|
|
27
|
+
)
|
|
28
|
+
}
|