@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/DataTableCell.tsx
CHANGED
|
@@ -1,28 +1,33 @@
|
|
|
1
|
-
import
|
|
2
|
-
import type {DataTableCellProps} from "./types";
|
|
3
|
-
import
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
1
|
+
import {createElement, type ReactNode} from 'react';
|
|
2
|
+
import type {DataTableCellProps} from "./types";
|
|
3
|
+
import clsx from "clsx";
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
export default function DataTableCell<T = unknown>({field, row, className, as, ...rest}: DataTableCellProps<T>) {
|
|
7
|
+
if (field.visible === false) {
|
|
8
|
+
return null;
|
|
9
|
+
}
|
|
10
|
+
const cellClassName = clsx(
|
|
11
|
+
{[`text-${field.align}`]: !!field.align},
|
|
12
|
+
className,
|
|
13
|
+
typeof field.className === 'function' ? field.className(row) : field.className
|
|
14
|
+
);
|
|
15
|
+
return createElement(
|
|
16
|
+
(as ?? field.as) ?? 'td',
|
|
17
|
+
{
|
|
18
|
+
className: cellClassName,
|
|
19
|
+
scope: (as ?? field.as) === 'th' ? 'row' : undefined,
|
|
20
|
+
colSpan: field.colSpan,
|
|
21
|
+
...field.cellProps,
|
|
22
|
+
...rest
|
|
23
|
+
},
|
|
24
|
+
(row[field.field] === undefined && !field.render)
|
|
25
|
+
? null
|
|
26
|
+
: (
|
|
27
|
+
typeof field.render === 'function'
|
|
28
|
+
? field.render(row)
|
|
29
|
+
: row[field.field] as ReactNode
|
|
30
|
+
)
|
|
31
|
+
)
|
|
32
|
+
}
|
|
33
|
+
DataTableCell.displayName = 'DataTableCell';
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import {useTableFields} from "./useTableFields";
|
|
2
|
+
|
|
3
|
+
export default function DataTableCols<T = unknown>() {
|
|
4
|
+
const [fields] = useTableFields<T>()
|
|
5
|
+
return (
|
|
6
|
+
<colgroup>
|
|
7
|
+
{fields
|
|
8
|
+
.filter(field => field.visible !== false)
|
|
9
|
+
.map((field, index) => (
|
|
10
|
+
<col key={index}
|
|
11
|
+
className={field.colClassName}
|
|
12
|
+
span={field.colSpan ?? 1}/>
|
|
13
|
+
))}
|
|
14
|
+
</colgroup>
|
|
15
|
+
)
|
|
16
|
+
}
|
|
17
|
+
DataTableCols.displayName = 'DataTableCols';
|
|
18
|
+
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import {createContext} from "react";
|
|
2
|
+
import type {DataTableField, SortProps} from "./types";
|
|
3
|
+
|
|
4
|
+
export interface TableContextData<T = unknown> {
|
|
5
|
+
fields: DataTableField<T>[];
|
|
6
|
+
setFields: (next: DataTableField<T>[] | ((prev: DataTableField<T>[]) => DataTableField<T>[])) => void;
|
|
7
|
+
sort: SortProps<T>|null;
|
|
8
|
+
setSort: (next: SortProps<T> | null | ((prev:SortProps<T>|null) => SortProps<T>|null )) => void;
|
|
9
|
+
getField: (key: string | number) => DataTableField<T> | undefined;
|
|
10
|
+
updateField: (key: string | number, arg: Partial<DataTableField<T>>) => void;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
export const DataTableContext = createContext<TableContextData<unknown> | null>(null)
|
package/src/DataTableHead.tsx
CHANGED
|
@@ -1,18 +1,20 @@
|
|
|
1
|
-
import React from "react";
|
|
1
|
+
import React, {type TableHTMLAttributes} from "react";
|
|
2
2
|
import DataTableTH from "./DataTableTH";
|
|
3
|
-
import
|
|
4
|
-
import
|
|
3
|
+
import clsx from "clsx";
|
|
4
|
+
import {useTableFields} from "./useTableFields";
|
|
5
5
|
|
|
6
6
|
|
|
7
|
-
function DataTableHead<T = unknown>({
|
|
7
|
+
export default function DataTableHead<T = unknown>({...rest}: TableHTMLAttributes<HTMLTableSectionElement>) {
|
|
8
|
+
const [fields] = useTableFields<T>()
|
|
8
9
|
return (
|
|
9
10
|
<thead {...rest}>
|
|
10
11
|
<tr>
|
|
11
|
-
{fields
|
|
12
|
-
|
|
12
|
+
{fields
|
|
13
|
+
.map((field, index) => (
|
|
14
|
+
<DataTableTH key={String(field.id ?? index)}
|
|
13
15
|
{...field.thProps}
|
|
14
16
|
field={field}
|
|
15
|
-
className={
|
|
17
|
+
className={clsx(
|
|
16
18
|
typeof field.className === 'function'
|
|
17
19
|
? {[`text-${field.align}`]: !!field.align}
|
|
18
20
|
: field.className
|
|
@@ -22,6 +24,4 @@ function DataTableHead<T = unknown>({fields, ...rest}: DataTableHeadProps<T>) {
|
|
|
22
24
|
</thead>
|
|
23
25
|
)
|
|
24
26
|
}
|
|
25
|
-
|
|
26
27
|
DataTableHead.displayName = 'DataTableHead';
|
|
27
|
-
export default DataTableHead;
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
import {type ReactNode, useCallback, useMemo, useState} from "react";
|
|
2
|
+
import type {DataTableField, SortProps} from "./types";
|
|
3
|
+
import {DataTableContext, type TableContextData} from "./DataTableContext";
|
|
4
|
+
|
|
5
|
+
export interface TableProviderProps<T = unknown> {
|
|
6
|
+
initialFields: DataTableField<T>[];
|
|
7
|
+
initialSort?: SortProps<T>|null;
|
|
8
|
+
children: ReactNode;
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
export default function DataTableProvider<T = unknown>({
|
|
12
|
+
children,
|
|
13
|
+
initialFields = [],
|
|
14
|
+
initialSort = null,
|
|
15
|
+
}: TableProviderProps<T>) {
|
|
16
|
+
const [fields, setFieldsState] = useState<DataTableField<T>[]>(initialFields);
|
|
17
|
+
const [sort, setProviderSort] = useState<SortProps<T> | null>(initialSort);
|
|
18
|
+
|
|
19
|
+
const setFields = useCallback(
|
|
20
|
+
(fields: DataTableField<T>[] | ((prev: DataTableField<T>[]) => DataTableField<T>[])) => {
|
|
21
|
+
setFieldsState(fields)
|
|
22
|
+
}, []);
|
|
23
|
+
|
|
24
|
+
const setSort = useCallback(
|
|
25
|
+
(sort: SortProps<T> | null | ((sort:SortProps<T>|null) => SortProps<T> | null)) => {
|
|
26
|
+
setProviderSort(sort)
|
|
27
|
+
}, [])
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
const updateField = useCallback((key: string | number, arg: Partial<DataTableField<T>>) => {
|
|
31
|
+
const nextState = fields.map(field => {
|
|
32
|
+
if (field.id === key) {
|
|
33
|
+
return {...field, ...arg}
|
|
34
|
+
}
|
|
35
|
+
return field;
|
|
36
|
+
});
|
|
37
|
+
setFieldsState(nextState);
|
|
38
|
+
}, [fields])
|
|
39
|
+
|
|
40
|
+
const getField = useCallback((key: string | number) => fields.find(field => field.id === key), [fields]);
|
|
41
|
+
|
|
42
|
+
|
|
43
|
+
const value = useMemo<TableContextData<T>>(
|
|
44
|
+
() => ({
|
|
45
|
+
fields,
|
|
46
|
+
setFields,
|
|
47
|
+
sort,
|
|
48
|
+
setSort,
|
|
49
|
+
getField,
|
|
50
|
+
updateField
|
|
51
|
+
}),
|
|
52
|
+
[fields, setFields, sort, setSort, updateField, getField]
|
|
53
|
+
)
|
|
54
|
+
|
|
55
|
+
return (
|
|
56
|
+
<DataTableContext.Provider value={value as unknown as TableContextData<unknown>}>
|
|
57
|
+
{children}
|
|
58
|
+
</DataTableContext.Provider>
|
|
59
|
+
)
|
|
60
|
+
}
|
|
61
|
+
DataTableProvider.displayName = 'DataTableProvider';
|
|
62
|
+
|
package/src/DataTableRow.tsx
CHANGED
|
@@ -1,19 +1,20 @@
|
|
|
1
|
-
import React, {MouseEvent} from 'react';
|
|
2
|
-
import classNames from "classnames";
|
|
1
|
+
import React, {type MouseEvent} from 'react';
|
|
3
2
|
import type {DataTableRowProps} from "./types";
|
|
4
3
|
import DataTableCell from "./DataTableCell";
|
|
4
|
+
import clsx from "clsx";
|
|
5
|
+
import {useTableFields} from "./useTableFields";
|
|
5
6
|
|
|
6
7
|
|
|
7
|
-
function DataTableRow<T = unknown>({
|
|
8
|
+
export default function DataTableRow<T = unknown>({
|
|
8
9
|
className,
|
|
9
10
|
rowClassName,
|
|
10
11
|
selected,
|
|
11
|
-
fields,
|
|
12
12
|
row,
|
|
13
13
|
trRef,
|
|
14
14
|
onClick,
|
|
15
15
|
...rest
|
|
16
16
|
}: DataTableRowProps<T>) {
|
|
17
|
+
const [fields] = useTableFields<T>()
|
|
17
18
|
const clickHandler = (ev: MouseEvent<HTMLTableRowElement>) => {
|
|
18
19
|
onClick?.(row, ev)
|
|
19
20
|
}
|
|
@@ -25,13 +26,14 @@ function DataTableRow<T = unknown>({
|
|
|
25
26
|
|
|
26
27
|
return (
|
|
27
28
|
<tr ref={trRef}
|
|
28
|
-
className={
|
|
29
|
+
className={clsx({'table-active': selected}, className, _className)}
|
|
29
30
|
onClick={clickHandler}
|
|
30
31
|
{...rest}>
|
|
31
|
-
{fields
|
|
32
|
+
{fields
|
|
33
|
+
.map((field, index) => (
|
|
34
|
+
<DataTableCell key={String(field?.id ?? index)} field={field} row={row}/>
|
|
35
|
+
))}
|
|
32
36
|
</tr>
|
|
33
37
|
)
|
|
34
38
|
}
|
|
35
|
-
|
|
36
39
|
DataTableRow.displayName = 'DataTableRow';
|
|
37
|
-
export default DataTableRow;
|
package/src/DataTableTBody.tsx
CHANGED
|
@@ -3,8 +3,7 @@ import DataTableRow from "./DataTableRow";
|
|
|
3
3
|
import type {DataTableTBodyProps} from "./types";
|
|
4
4
|
|
|
5
5
|
|
|
6
|
-
function DataTableTBody<T = unknown>({
|
|
7
|
-
fields,
|
|
6
|
+
export default function DataTableTBody<T = unknown>({
|
|
8
7
|
data,
|
|
9
8
|
keyField,
|
|
10
9
|
rowClassName,
|
|
@@ -25,7 +24,6 @@ function DataTableTBody<T = unknown>({
|
|
|
25
24
|
return (
|
|
26
25
|
<DataTableRow key={keyValue} onClick={onSelectRow}
|
|
27
26
|
rowClassName={rowClassName}
|
|
28
|
-
fields={fields}
|
|
29
27
|
row={row} selected={isSelected}/>
|
|
30
28
|
)
|
|
31
29
|
})}
|
|
@@ -33,6 +31,4 @@ function DataTableTBody<T = unknown>({
|
|
|
33
31
|
</tbody>
|
|
34
32
|
)
|
|
35
33
|
}
|
|
36
|
-
|
|
37
34
|
DataTableTBody.displayName = 'DataTableTBody';
|
|
38
|
-
export default DataTableTBody
|
package/src/DataTableTH.tsx
CHANGED
|
@@ -1,15 +1,18 @@
|
|
|
1
1
|
import React from "react";
|
|
2
|
-
import classNames from "classnames";
|
|
3
2
|
import type {DataTableTHProps} from "./types";
|
|
3
|
+
import clsx from "clsx";
|
|
4
4
|
|
|
5
5
|
|
|
6
|
-
function DataTableTH<T = unknown>({
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
6
|
+
export default function DataTableTH<T = unknown>({
|
|
7
|
+
field,
|
|
8
|
+
className,
|
|
9
|
+
children,
|
|
10
|
+
...rest
|
|
11
|
+
}: DataTableTHProps<T>) {
|
|
12
|
+
if (field.visible === false) {
|
|
13
|
+
return null;
|
|
14
|
+
}
|
|
15
|
+
const thClassName = clsx({[`text-${field.align}`]: !!field.align}, className);
|
|
13
16
|
return (
|
|
14
17
|
<th className={thClassName} scope="col" {...rest}>
|
|
15
18
|
{children ?? field.title}
|
|
@@ -17,4 +20,3 @@ function DataTableTH<T = unknown>({
|
|
|
17
20
|
)
|
|
18
21
|
}
|
|
19
22
|
DataTableTH.displayName = 'DataTableTH';
|
|
20
|
-
export default DataTableTH;
|
package/src/RowsPerPage.tsx
CHANGED
|
@@ -1,11 +1,10 @@
|
|
|
1
|
-
import React, {ChangeEvent, useId} from 'react';
|
|
2
|
-
import classNames from "classnames";
|
|
1
|
+
import React, {type ChangeEvent, useId} from 'react';
|
|
3
2
|
import type {RowsPerPageProps} from "./types";
|
|
3
|
+
import clsx from "clsx";
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
const defaultRowsPerPageValues: number[] = [10, 25, 50, 100, 250, 500, 1000];
|
|
6
6
|
|
|
7
|
-
|
|
8
|
-
function RowsPerPage({
|
|
7
|
+
export default function RowsPerPage({
|
|
9
8
|
value,
|
|
10
9
|
pageValues = defaultRowsPerPageValues,
|
|
11
10
|
size,
|
|
@@ -16,8 +15,8 @@ function RowsPerPage({
|
|
|
16
15
|
}: RowsPerPageProps) {
|
|
17
16
|
const id = useId();
|
|
18
17
|
const changeHandler = (ev: ChangeEvent<HTMLSelectElement>) => onChange(Number(ev.target.value));
|
|
19
|
-
const selectClassName = className ??
|
|
20
|
-
const inputGroupClassName =
|
|
18
|
+
const selectClassName = className ?? clsx('form-select', {[`form-select-${size}`]: !!size});
|
|
19
|
+
const inputGroupClassName = clsx('input-group', {
|
|
21
20
|
[`input-group-${size}`]: !!size,
|
|
22
21
|
})
|
|
23
22
|
|
|
@@ -33,6 +32,4 @@ function RowsPerPage({
|
|
|
33
32
|
</div>
|
|
34
33
|
)
|
|
35
34
|
}
|
|
36
|
-
|
|
37
35
|
RowsPerPage.displayName = 'RowsPerPage';
|
|
38
|
-
export default RowsPerPage;
|
package/src/SortableTable.tsx
CHANGED
|
@@ -1,37 +1,37 @@
|
|
|
1
|
-
import React from 'react';
|
|
2
|
-
import classNames from "classnames";
|
|
3
|
-
import SortableTableHead from "./SortableTableHead";
|
|
4
|
-
import DataTableTBody from "./DataTableTBody";
|
|
5
1
|
import type {SortableTableProps} from "./types";
|
|
2
|
+
import clsx from "clsx";
|
|
6
3
|
import Table from "./Table";
|
|
4
|
+
import {DataTableCols, DataTableTBody} from "./index";
|
|
5
|
+
import React from "react";
|
|
6
|
+
import SortableTableHeadWrapper from "./SortableTableHeadWrapper";
|
|
7
7
|
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
const tableClassName = classNames('table', className, {
|
|
8
|
+
export default function SortableTable<T = unknown>({
|
|
9
|
+
className,
|
|
10
|
+
size,
|
|
11
|
+
responsive,
|
|
12
|
+
sticky,
|
|
13
|
+
data,
|
|
14
|
+
keyField,
|
|
15
|
+
rowClassName,
|
|
16
|
+
renderRow,
|
|
17
|
+
onSelectRow,
|
|
18
|
+
selected,
|
|
19
|
+
tableHeadProps,
|
|
20
|
+
children,
|
|
21
|
+
tfoot,
|
|
22
|
+
onChangeSort,
|
|
23
|
+
...rest
|
|
24
|
+
}: Omit<SortableTableProps<T>, 'fields' | 'currentSort'>) {
|
|
25
|
+
const tableClassName = clsx('table', className, {
|
|
27
26
|
[`table-${size}`]: !!size,
|
|
28
27
|
})
|
|
29
28
|
|
|
30
29
|
return (
|
|
31
|
-
<Table className={tableClassName} sticky={sticky} {...rest}>
|
|
32
|
-
<
|
|
30
|
+
<Table className={tableClassName} responsive={responsive} sticky={sticky} {...rest}>
|
|
31
|
+
<DataTableCols/>
|
|
32
|
+
<SortableTableHeadWrapper onChangeSort={onChangeSort} {...tableHeadProps}/>
|
|
33
33
|
{!!data.length && (
|
|
34
|
-
<DataTableTBody
|
|
34
|
+
<DataTableTBody data={data} keyField={keyField} rowClassName={rowClassName}
|
|
35
35
|
renderRow={renderRow}
|
|
36
36
|
onSelectRow={onSelectRow} selected={selected}/>
|
|
37
37
|
)}
|
|
@@ -40,6 +40,4 @@ function SortableTable<T = unknown>({
|
|
|
40
40
|
</Table>
|
|
41
41
|
)
|
|
42
42
|
}
|
|
43
|
-
|
|
44
43
|
SortableTable.displayName = 'SortableTable';
|
|
45
|
-
export default SortableTable;
|
|
@@ -1,26 +1,27 @@
|
|
|
1
1
|
import React from "react";
|
|
2
2
|
import SortableTableTH from "./SortableTableTH";
|
|
3
|
-
import classNames from "classnames";
|
|
4
3
|
import type {SortableTableHeadProps} from "./types";
|
|
4
|
+
import clsx from "clsx";
|
|
5
|
+
import {useTableFields} from "./useTableFields";
|
|
6
|
+
import {useTableSort} from "./useTableSort";
|
|
5
7
|
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
}: SortableTableHeadProps<T>) {
|
|
12
|
-
const {field, ascending} = currentSort;
|
|
8
|
+
export default function SortableTableHead<T = unknown>({
|
|
9
|
+
onChangeSort,
|
|
10
|
+
}: SortableTableHeadProps<T>) {
|
|
11
|
+
const [fields] = useTableFields<T>()
|
|
12
|
+
const [sort] = useTableSort<T>();
|
|
13
13
|
return (
|
|
14
14
|
<thead>
|
|
15
15
|
<tr>
|
|
16
|
-
{fields
|
|
16
|
+
{fields
|
|
17
|
+
.map((tableField, index) => (
|
|
17
18
|
<SortableTableTH<T> key={index} field={tableField}
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
19
|
+
sorted={sort?.field === tableField.field} ascending={sort?.ascending}
|
|
20
|
+
className={clsx(
|
|
21
|
+
typeof tableField.className === 'function'
|
|
22
|
+
? {[`text-${tableField.align}`]: !!tableField.align}
|
|
23
|
+
: tableField.className
|
|
24
|
+
)} onClick={onChangeSort}/>
|
|
24
25
|
))}
|
|
25
26
|
</tr>
|
|
26
27
|
</thead>
|
|
@@ -28,4 +29,4 @@ function SortableTableHead<T = unknown>({
|
|
|
28
29
|
}
|
|
29
30
|
|
|
30
31
|
SortableTableHead.displayName = 'SortableTableHead';
|
|
31
|
-
|
|
32
|
+
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import {useTableFields} from "./useTableFields";
|
|
2
|
+
import {useTableSort} from "./useTableSort";
|
|
3
|
+
import SortableTableHead from "./SortableTableHead";
|
|
4
|
+
import type {SortProps} from "./types";
|
|
5
|
+
|
|
6
|
+
export interface SortableTableHeadWrapperProps<T = unknown> {
|
|
7
|
+
onChangeSort: (sort: SortProps<T>) => void;
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
export default function SortableTableHeadWrapper<T = unknown>({
|
|
11
|
+
onChangeSort,
|
|
12
|
+
}: SortableTableHeadWrapperProps<T>) {
|
|
13
|
+
const [fields] = useTableFields<T>()
|
|
14
|
+
const [sort] = useTableSort<T>();
|
|
15
|
+
|
|
16
|
+
return (
|
|
17
|
+
<SortableTableHead fields={fields} currentSort={sort} onChangeSort={onChangeSort} />
|
|
18
|
+
)
|
|
19
|
+
}
|
|
20
|
+
SortableTableHeadWrapper.displayName = 'SortableTableHeadWrapper';
|
package/src/SortableTableTH.tsx
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import React from "react";
|
|
2
|
-
import classNames from "classnames";
|
|
3
2
|
import DataTableTH from "./DataTableTH";
|
|
4
3
|
import type {SortableTableTHProps, UIFlexAlign} from "./types";
|
|
5
4
|
import styled from '@emotion/styled';
|
|
5
|
+
import clsx from "clsx";
|
|
6
6
|
|
|
7
7
|
const flexJustifyContent = (align?: UIFlexAlign) => {
|
|
8
8
|
if (!align) {
|
|
@@ -25,30 +25,35 @@ const FieldTitle = styled.div<FieldTitleProps>`
|
|
|
25
25
|
width: 100%;
|
|
26
26
|
flex-direction: ${props => props.align === 'end' ? 'row-reverse' : 'row'};
|
|
27
27
|
justify-content: ${props => flexJustifyContent(props.align)};
|
|
28
|
+
|
|
28
29
|
.sort-icon {
|
|
29
30
|
flex-grow: ${props => props.align === 'end' ? '1' : '0'};
|
|
30
31
|
opacity: ${props => props.sorted ? 1 : 0};
|
|
31
32
|
}
|
|
33
|
+
|
|
32
34
|
&:hover .sort-icon {
|
|
33
|
-
color: ${props => props.sorted ? 'unset' : 'var(--bs-primary)'}
|
|
35
|
+
color: ${props => props.sorted ? 'unset' : 'var(--bs-primary)'};
|
|
34
36
|
opacity: 0.75;
|
|
35
37
|
transition: opacity 0.2s;
|
|
36
38
|
}
|
|
37
39
|
`
|
|
38
40
|
|
|
39
|
-
function SortableTableTH<T = unknown>({
|
|
41
|
+
export default function SortableTableTH<T = unknown>({
|
|
40
42
|
field,
|
|
41
43
|
sorted,
|
|
42
44
|
ascending,
|
|
43
45
|
className,
|
|
44
46
|
onClick
|
|
45
47
|
}: SortableTableTHProps<T>) {
|
|
48
|
+
if (field.visible === false) {
|
|
49
|
+
return null;
|
|
50
|
+
}
|
|
46
51
|
if (!field.sortable) {
|
|
47
52
|
return (<DataTableTH field={field} className={className}/>)
|
|
48
53
|
}
|
|
49
54
|
|
|
50
55
|
const {className: _thClassName, ...thProps} = field.thProps ?? {};
|
|
51
|
-
const thClassName =
|
|
56
|
+
const thClassName = clsx(
|
|
52
57
|
className,
|
|
53
58
|
_thClassName,
|
|
54
59
|
{[`text-${field.align}`]: !!field.align}
|
|
@@ -64,14 +69,12 @@ function SortableTableTH<T = unknown>({
|
|
|
64
69
|
}
|
|
65
70
|
|
|
66
71
|
return (
|
|
67
|
-
<th {...thProps} className={
|
|
72
|
+
<th {...thProps} className={clsx("sortable", thClassName)} scope="col" onClick={clickHandler}>
|
|
68
73
|
<FieldTitle sorted={sorted} align={field.align}>
|
|
69
74
|
<div className="field-title">{field.title}</div>
|
|
70
|
-
<div className={
|
|
75
|
+
<div className={clsx('me-1 sort-icon', iconClassName)}/>
|
|
71
76
|
</FieldTitle>
|
|
72
77
|
</th>
|
|
73
78
|
)
|
|
74
79
|
}
|
|
75
|
-
|
|
76
80
|
SortableTableTH.displayName = 'SortableTableTH';
|
|
77
|
-
export default SortableTableTH;
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import type {DataTableProps} from "./types";
|
|
2
|
+
import DataTableProvider from "./DataTableProvider";
|
|
3
|
+
import DataTable from "./DataTable";
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
export default function StandaloneDataTable<T = unknown>({
|
|
7
|
+
fields,
|
|
8
|
+
...rest
|
|
9
|
+
}: DataTableProps<T>) {
|
|
10
|
+
return (
|
|
11
|
+
<DataTableProvider initialFields={fields}>
|
|
12
|
+
<DataTable {...rest}/>
|
|
13
|
+
</DataTableProvider>
|
|
14
|
+
)
|
|
15
|
+
}
|
|
16
|
+
StandaloneDataTable.displayName = 'StandaloneDataTable';
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import type {SortProps} from "./types";
|
|
2
|
+
import {useTableSort} from "./useTableSort";
|
|
3
|
+
import {useEffect} from "react";
|
|
4
|
+
|
|
5
|
+
export interface StandaloneSortHelperProps<T = unknown> {
|
|
6
|
+
nextSort: SortProps<T>
|
|
7
|
+
}
|
|
8
|
+
export function StandaloneSortHelper<T = unknown>({nextSort}:StandaloneSortHelperProps<T>) {
|
|
9
|
+
const [, setNextSort] = useTableSort<T>();
|
|
10
|
+
useEffect(() => {
|
|
11
|
+
console.log('setNextSort', nextSort);
|
|
12
|
+
setNextSort(nextSort);
|
|
13
|
+
}, [nextSort, setNextSort]);
|
|
14
|
+
return null;
|
|
15
|
+
}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import type {SortableTableProps} from "./types";
|
|
3
|
+
import DataTableProvider from "./DataTableProvider";
|
|
4
|
+
import SortableTable from "./SortableTable";
|
|
5
|
+
import {StandaloneSortHelper} from "./StandaloneSortHelper";
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
export default function StandaloneSortableTable<T = unknown>({
|
|
9
|
+
fields,
|
|
10
|
+
currentSort,
|
|
11
|
+
...rest
|
|
12
|
+
}: SortableTableProps<T>) {
|
|
13
|
+
return (
|
|
14
|
+
<DataTableProvider initialFields={fields} initialSort={currentSort}>
|
|
15
|
+
<StandaloneSortHelper nextSort={currentSort} />
|
|
16
|
+
<SortableTable {...rest}/>
|
|
17
|
+
</DataTableProvider>
|
|
18
|
+
)
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
StandaloneSortableTable.displayName = 'StandaloneSortableTable';
|