@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.
Files changed (66) hide show
  1. package/CHANGELOG.md +87 -48
  2. package/README.md +94 -4
  3. package/dist/DataTable.d.ts +6 -6
  4. package/dist/DataTableCell.d.ts +299 -295
  5. package/dist/DataTableCols.d.ts +5 -0
  6. package/dist/DataTableContext.d.ts +10 -0
  7. package/dist/DataTableHead.d.ts +2 -2
  8. package/dist/DataTableProvider.d.ts +12 -0
  9. package/dist/DataTableRow.d.ts +1 -1
  10. package/dist/DataTableTBody.d.ts +1 -1
  11. package/dist/DataTableTH.d.ts +6 -6
  12. package/dist/RowsPerPage.d.ts +0 -1
  13. package/dist/SortableTable.d.ts +6 -6
  14. package/dist/SortableTableHead.d.ts +6 -6
  15. package/dist/SortableTableHeadWrapper.d.ts +9 -0
  16. package/dist/SortableTableTH.d.ts +6 -6
  17. package/dist/StandaloneDataTable.d.ts +6 -0
  18. package/dist/StandaloneSortHelper.d.ts +5 -0
  19. package/dist/StandaloneSortableTable.d.ts +6 -0
  20. package/dist/Table.d.ts +6 -5
  21. package/dist/index.cjs.js +30 -28
  22. package/dist/index.cjs.js.map +1 -1
  23. package/dist/index.d.ts +20 -10
  24. package/dist/index.es.js +521 -388
  25. package/dist/index.es.js.map +1 -1
  26. package/dist/types.d.ts +104 -105
  27. package/dist/useField.d.ts +6 -0
  28. package/dist/useTableContext.d.ts +2 -0
  29. package/dist/useTableFields.d.ts +9 -0
  30. package/dist/useTableSort.d.ts +9 -0
  31. package/eslint.config.mjs +3 -3
  32. package/package.json +7 -5
  33. package/src/DataTable.tsx +23 -28
  34. package/src/DataTableCell.tsx +33 -28
  35. package/src/DataTableCols.tsx +18 -0
  36. package/src/DataTableContext.ts +13 -0
  37. package/src/DataTableHead.tsx +9 -9
  38. package/src/DataTableProvider.tsx +62 -0
  39. package/src/DataTableRow.tsx +10 -8
  40. package/src/DataTableTBody.tsx +1 -5
  41. package/src/DataTableTH.tsx +11 -9
  42. package/src/RowsPerPage.tsx +6 -9
  43. package/src/SortableTable.tsx +26 -28
  44. package/src/SortableTableHead.tsx +17 -16
  45. package/src/SortableTableHeadWrapper.tsx +20 -0
  46. package/src/SortableTableTH.tsx +11 -8
  47. package/src/StandaloneDataTable.tsx +16 -0
  48. package/src/StandaloneSortHelper.tsx +15 -0
  49. package/src/StandaloneSortableTable.tsx +21 -0
  50. package/src/Table.tsx +49 -44
  51. package/src/TablePagination.tsx +4 -6
  52. package/src/index.tsx +26 -12
  53. package/src/types.ts +127 -128
  54. package/src/useField.ts +19 -0
  55. package/src/useTableContext.ts +10 -0
  56. package/src/useTableFields.ts +20 -0
  57. package/src/useTableSort.ts +20 -0
  58. package/test/Main.tsx +37 -0
  59. package/test/TableColumnsHandler.tsx +28 -0
  60. package/test/TestTable.tsx +51 -68
  61. package/test/data.ts +232 -232
  62. package/test/index.tsx +11 -11
  63. package/test/tableFields.tsx +52 -0
  64. package/test/utils.ts +19 -0
  65. package/tsconfig.json +1 -0
  66. 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 classNames from "classnames";
5
-
6
- export type StyledTableProps = TableHTMLAttributes<HTMLTableElement> & Pick<DataTableProps, 'sticky' | 'responsive'>
7
-
8
- const StyledTable = styled.table<StyledTableProps>`
9
- --table-sticky-top: ${props => props.sticky ? '0' : undefined};
10
-
11
- thead {
12
- tr:nth-of-type(1) td,
13
- tr:nth-of-type(1) th {
14
- top: var(--table-sticky-top, unset);
15
- position: ${props => props.sticky ? "sticky" : "unset"};
16
- z-index: ${props => props.sticky ? 10 : "unset"};
17
- background: ${props => props.sticky ? "linear-gradient(var(--bs-table-bg) 75%, rgba(var(--bs-secondary-bg-rgb), 0.9))" : "unset"};
18
- }
19
- }
20
- `
21
-
22
- export default React.forwardRef<HTMLTableElement, StyledTableProps>(
23
- function Table({
24
- sticky,
25
- responsive,
26
- children,
27
- className,
28
- ...rest
29
- }, ref) {
30
- if (responsive) {
31
- const _className = classNames(className, {
32
- 'table-responsive': responsive === true,
33
- [`table-responsive-${responsive}`]: responsive !== true,
34
- })
35
- return (
36
- <div className={_className}>
37
- <StyledTable ref={ref} {...rest}>{children}</StyledTable>
38
- </div>
39
- )
40
- }
41
- return (
42
- <StyledTable className={className} sticky={sticky} ref={ref} {...rest}>{children}</StyledTable>
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
+
@@ -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 = classNames("btn btn-link", {[`btn-${size}`]: !!size});
23
+ const buttonClassName = clsx("btn btn-link", {[`btn-${size}`]: !!size});
24
24
 
25
25
  return (
26
- <div className={classNames("row g-3 justify-content-end", className)} {...rest}>
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
- export {default as DataTable} from './DataTable';
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 SortableTable} from './SortableTable';
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, defaultRowsPerPageValues} from './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
- DataTableHeadProps,
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
- DataTableCellProps
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 {Argument} from "classnames";
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
- | Argument
16
- | ((row: T) => (string | Argument));
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
- export interface SortableTableField<T = unknown> extends DataTableField<T> {
35
- sortable?: boolean;
36
- }
37
-
38
- export interface DataTableProps<T = unknown> extends TableHTMLAttributes<HTMLTableElement> {
39
- fields: DataTableField<T>[];
40
- data: T[];
41
- keyField: keyof T | ((row: T) => string | number);
42
- size?: UITableSize;
43
- sticky?: boolean;
44
- responsive?: boolean | "sm" | "md" | "lg" | "xl" | 'xxl';
45
- rowClassName?: DataTableClassNames<T>;
46
- renderRow?: (row: T) => React.ReactNode;
47
- onSelectRow?: (row: T, ev?: MouseEvent<HTMLTableRowElement>) => void;
48
- selected?: string | number | ((row: T) => boolean);
49
- tfoot?: React.ReactElement<HTMLTableSectionElement>;
50
- tableHeadProps?: DataTableHeadProps<T>;
51
- children?: ReactNode;
52
- }
53
-
54
- export interface DataTableCellProps<T = unknown> extends Omit<TableHTMLAttributes<HTMLTableCellElement>, 'className'> {
55
- field: DataTableField<T>;
56
- row: T;
57
- as?: 'td' | 'th',
58
- className?: string | Argument;
59
- children?: React.ReactNode;
60
- }
61
-
62
- export interface DataTableTHProps<T = unknown> extends Omit<DataTableCellProps<T>, 'row'> {
63
- as?: 'th',
64
- }
65
-
66
- export interface DataTableHeadProps<T = unknown> extends TableHTMLAttributes<HTMLTableSectionElement> {
67
- fields: DataTableField<T>[];
68
- }
69
-
70
- export interface DataTableTBodyProps<T = unknown> extends TableHTMLAttributes<HTMLTableSectionElement> {
71
- fields: DataTableField<T>[];
72
- data: T[];
73
- keyField: keyof T | ((row: T) => string | number);
74
- rowClassName?: DataTableClassNames<T>;
75
- renderRow?: (row: T) => React.ReactNode;
76
- onSelectRow?: (row: T, ev?: MouseEvent<HTMLTableRowElement>) => void;
77
- selected?: string | number | ((row: T) => boolean);
78
- children?: ReactNode;
79
- }
80
-
81
- export interface DataTableRowProps<T = unknown> extends Omit<TableHTMLAttributes<HTMLTableRowElement>, 'onClick'> {
82
- rowClassName?: string | Argument | ((row: T) => string | Argument);
83
- selected?: boolean;
84
- fields: DataTableField<T>[];
85
- row: T;
86
- trRef?: React.Ref<HTMLTableRowElement>;
87
- onClick?: (row: T, ev?: MouseEvent<HTMLTableRowElement>) => void;
88
- }
89
-
90
- export interface SortableTableProps<T = unknown> extends DataTableProps<T> {
91
- fields: SortableTableField<T>[];
92
- currentSort: SortProps<T>;
93
- onChangeSort: (sort: SortProps<T>) => void;
94
- }
95
-
96
- export interface SortableTableHeadProps<T = unknown> extends DataTableHeadProps<T> {
97
- currentSort: SortProps<T>;
98
- fields: SortableTableField<T>[];
99
- onChangeSort: (sort: SortProps<T>) => void;
100
- }
101
-
102
- export interface SortableTableTHProps<T = unknown> extends Omit<DataTableTHProps<T>, 'onClick'> {
103
- field: SortableTableField<T>;
104
- sorted?: boolean;
105
- ascending?: boolean;
106
- onClick: (sort: SortProps<T>) => void;
107
- }
108
-
109
- export interface RowsPerPageProps extends Omit<HTMLAttributes<HTMLSelectElement>, 'onChange'> {
110
- value: number;
111
- pageValues?: number[];
112
- label?: string | React.ReactNode;
113
- size?: UISize;
114
- className?: string;
115
- onChange: (value: number) => void;
116
- }
117
-
118
- export interface TablePaginationProps extends HTMLAttributes<HTMLDivElement> {
119
- page: number;
120
- rowsPerPage: number;
121
- onChangePage: (page: number) => void;
122
- count: number;
123
- size?: UISize;
124
- showFirst?: boolean;
125
- showLast?: boolean;
126
- rowsPerPageProps?: Omit<RowsPerPageProps, 'value'>;
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
+ }
@@ -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
+ }