react-hook-tanstack-table 0.0.1
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/LICENSE +21 -0
- package/README.org +29 -0
- package/dist/TableContext.cjs +6 -0
- package/dist/TableContext.d.cts +7 -0
- package/dist/TableContext.d.cts.map +1 -0
- package/dist/TableContext.d.ts +7 -0
- package/dist/TableContext.d.ts.map +1 -0
- package/dist/TableContext.js +8 -0
- package/dist/TableContext.js.map +1 -0
- package/dist/hasTableArg-Bu3FbcSo.js +8 -0
- package/dist/hasTableArg-Bu3FbcSo.js.map +1 -0
- package/dist/hasTableArg-dMtayKWH.cjs +11 -0
- package/dist/index.cjs +40 -0
- package/dist/index.d.cts +11 -0
- package/dist/index.d.ts +11 -0
- package/dist/index.js +11 -0
- package/dist/invariant-BgWq7zZS.js +12 -0
- package/dist/invariant-BgWq7zZS.js.map +1 -0
- package/dist/invariant-D8b385d_.cjs +21 -0
- package/dist/isShallowEqual-D6PQ041u.cjs +36 -0
- package/dist/isShallowEqual-Kynsoe7a.js +33 -0
- package/dist/isShallowEqual-Kynsoe7a.js.map +1 -0
- package/dist/runGetters-BfRTE7LZ.js +16 -0
- package/dist/runGetters-BfRTE7LZ.js.map +1 -0
- package/dist/runGetters-Q-UsPG2j.cjs +19 -0
- package/dist/types-DIWB6wdO.d.cts +11 -0
- package/dist/types-DIWB6wdO.d.cts.map +1 -0
- package/dist/types-DIWB6wdO.d.ts +11 -0
- package/dist/types-DIWB6wdO.d.ts.map +1 -0
- package/dist/useCell.cjs +53 -0
- package/dist/useCell.d.cts +17 -0
- package/dist/useCell.d.cts.map +1 -0
- package/dist/useCell.d.ts +17 -0
- package/dist/useCell.d.ts.map +1 -0
- package/dist/useCell.js +53 -0
- package/dist/useCell.js.map +1 -0
- package/dist/useColumn.cjs +54 -0
- package/dist/useColumn.d.cts +19 -0
- package/dist/useColumn.d.cts.map +1 -0
- package/dist/useColumn.d.ts +19 -0
- package/dist/useColumn.d.ts.map +1 -0
- package/dist/useColumn.js +54 -0
- package/dist/useColumn.js.map +1 -0
- package/dist/useHeader.cjs +48 -0
- package/dist/useHeader.d.cts +19 -0
- package/dist/useHeader.d.cts.map +1 -0
- package/dist/useHeader.d.ts +19 -0
- package/dist/useHeader.d.ts.map +1 -0
- package/dist/useHeader.js +48 -0
- package/dist/useHeader.js.map +1 -0
- package/dist/useReactTable-Y2z5JrT_.js +70 -0
- package/dist/useReactTable-Y2z5JrT_.js.map +1 -0
- package/dist/useReactTable-nxQRPiMU.cjs +95 -0
- package/dist/useReactTable.cjs +3 -0
- package/dist/useReactTable.d.cts +10 -0
- package/dist/useReactTable.d.cts.map +1 -0
- package/dist/useReactTable.d.ts +10 -0
- package/dist/useReactTable.d.ts.map +1 -0
- package/dist/useReactTable.js +2 -0
- package/dist/useRow.cjs +54 -0
- package/dist/useRow.d.cts +19 -0
- package/dist/useRow.d.cts.map +1 -0
- package/dist/useRow.d.ts +19 -0
- package/dist/useRow.d.ts.map +1 -0
- package/dist/useRow.js +54 -0
- package/dist/useRow.js.map +1 -0
- package/dist/useTable.cjs +44 -0
- package/dist/useTable.d.cts +11 -0
- package/dist/useTable.d.cts.map +1 -0
- package/dist/useTable.d.ts +11 -0
- package/dist/useTable.d.ts.map +1 -0
- package/dist/useTable.js +44 -0
- package/dist/useTable.js.map +1 -0
- package/dist/useTableWithSelector-Bdsf6Zxk.cjs +79 -0
- package/dist/useTableWithSelector-D3f689pF.js +70 -0
- package/dist/useTableWithSelector-D3f689pF.js.map +1 -0
- package/dist/useTableWithSelector.cjs +3 -0
- package/dist/useTableWithSelector.d.cts +8 -0
- package/dist/useTableWithSelector.d.cts.map +1 -0
- package/dist/useTableWithSelector.d.ts +8 -0
- package/dist/useTableWithSelector.d.ts.map +1 -0
- package/dist/useTableWithSelector.js +2 -0
- package/package.json +99 -0
- package/src/contexts/TableContext.ts +7 -0
- package/src/hooks/useCell.ts +156 -0
- package/src/hooks/useColumn.ts +168 -0
- package/src/hooks/useHeader.ts +151 -0
- package/src/hooks/useReactTable.ts +88 -0
- package/src/hooks/useRow.ts +132 -0
- package/src/hooks/useTable.ts +113 -0
- package/src/hooks/useTableWithSelector.ts +143 -0
- package/src/index.ts +13 -0
- package/src/lib/hasTableArg.ts +19 -0
- package/src/lib/identity.ts +1 -0
- package/src/lib/invariant.ts +12 -0
- package/src/lib/isShallowEqual.ts +77 -0
- package/src/lib/runGetters.ts +17 -0
- package/src/lib/tableRegistry.ts +3 -0
- package/src/lib/uncapitalize.ts +2 -0
- package/src/lib/useLayoutEffect.ts +3 -0
- package/src/lib/useShallowMemo.ts +12 -0
- package/src/types.ts +24 -0
|
@@ -0,0 +1,156 @@
|
|
|
1
|
+
import { useCallback } from "react"
|
|
2
|
+
|
|
3
|
+
import type {
|
|
4
|
+
Cell,
|
|
5
|
+
Column,
|
|
6
|
+
RequiredKeys,
|
|
7
|
+
Row,
|
|
8
|
+
RowData,
|
|
9
|
+
Table,
|
|
10
|
+
TableOptionsResolved,
|
|
11
|
+
} from "@tanstack/table-core"
|
|
12
|
+
|
|
13
|
+
import { identity } from "../lib/identity"
|
|
14
|
+
import { hasTableArg } from "../lib/hasTableArg"
|
|
15
|
+
import { runGetters } from "../lib/runGetters"
|
|
16
|
+
import { isShallowEqual } from "../lib/isShallowEqual"
|
|
17
|
+
import { invariant } from "../lib/invariant"
|
|
18
|
+
|
|
19
|
+
import type { IsEqual, RunGetters } from "../types"
|
|
20
|
+
|
|
21
|
+
import type { ColumnValues } from "./useColumn"
|
|
22
|
+
import type { RowValues } from "./useRow"
|
|
23
|
+
import { useTableWithSelector } from "./useTableWithSelector"
|
|
24
|
+
|
|
25
|
+
export interface CellValues<TData extends RowData, TValue> extends RunGetters<
|
|
26
|
+
Cell<TData, TValue>
|
|
27
|
+
> {}
|
|
28
|
+
|
|
29
|
+
const cellValuesCache = new WeakMap<
|
|
30
|
+
RequiredKeys<TableOptionsResolved<any>, "state">,
|
|
31
|
+
Map<string, Map<string, CellValues<any, any>>>
|
|
32
|
+
>()
|
|
33
|
+
|
|
34
|
+
const getCellValues = <TData extends RowData, TValue>(
|
|
35
|
+
table: Table<TData>,
|
|
36
|
+
rowId: string,
|
|
37
|
+
columnId: string,
|
|
38
|
+
): CellValues<TData, TValue> => {
|
|
39
|
+
let cellCache = cellValuesCache.get(table.options)
|
|
40
|
+
if (!cellCache) {
|
|
41
|
+
cellCache = new Map()
|
|
42
|
+
cellValuesCache.set(table.options, cellCache)
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
let rowCache = cellCache.get(rowId)
|
|
46
|
+
if (!rowCache) {
|
|
47
|
+
rowCache = new Map()
|
|
48
|
+
cellCache.set(rowId, rowCache)
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
let cached = rowCache.get(columnId)
|
|
52
|
+
|
|
53
|
+
if (!cached) {
|
|
54
|
+
const cell = table
|
|
55
|
+
.getRow(rowId)
|
|
56
|
+
?.getAllCells()
|
|
57
|
+
.find((c) => c.column.id === columnId) as Cell<TData, TValue> | undefined
|
|
58
|
+
|
|
59
|
+
invariant(cell)
|
|
60
|
+
|
|
61
|
+
cached = runGetters(cell)
|
|
62
|
+
|
|
63
|
+
rowCache.set(columnId, cached)
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
return cached
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
type Selector<TData extends RowData, TValue, Selection> = (
|
|
70
|
+
cellValues: CellValues<TData, TValue>,
|
|
71
|
+
) => Selection
|
|
72
|
+
|
|
73
|
+
interface CellCoords<TData extends RowData, TValue> {
|
|
74
|
+
column: Column<TData, TValue> | ColumnValues<TData> | string
|
|
75
|
+
row: Row<TData> | RowValues<TData> | string
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
export const useCell = <
|
|
79
|
+
TData extends RowData,
|
|
80
|
+
TValue,
|
|
81
|
+
Selection = CellValues<TData, TValue>,
|
|
82
|
+
>(
|
|
83
|
+
...args:
|
|
84
|
+
| [
|
|
85
|
+
table: Table<TData> | undefined,
|
|
86
|
+
cell:
|
|
87
|
+
| Cell<TData, TValue>
|
|
88
|
+
| CellValues<TData, TValue>
|
|
89
|
+
| CellCoords<TData, TValue>,
|
|
90
|
+
selector?: Selector<TData, TValue, Selection> | undefined,
|
|
91
|
+
isEqual?: IsEqual<NoInfer<Selection>> | undefined,
|
|
92
|
+
]
|
|
93
|
+
| [
|
|
94
|
+
cell:
|
|
95
|
+
| Cell<TData, TValue>
|
|
96
|
+
| CellValues<TData, TValue>
|
|
97
|
+
| CellCoords<TData, TValue>,
|
|
98
|
+
selector?: Selector<TData, TValue, Selection> | undefined,
|
|
99
|
+
isEqual?: IsEqual<NoInfer<Selection>> | undefined,
|
|
100
|
+
]
|
|
101
|
+
): Selection => {
|
|
102
|
+
const [
|
|
103
|
+
table,
|
|
104
|
+
cellOrCoords,
|
|
105
|
+
selector = identity as never,
|
|
106
|
+
isEqual = isShallowEqual,
|
|
107
|
+
] = hasTableArg(args) ? args : [undefined, ...args]
|
|
108
|
+
|
|
109
|
+
const { columnId, rowId } =
|
|
110
|
+
"id" in cellOrCoords ?
|
|
111
|
+
{ columnId: cellOrCoords.column.id, rowId: cellOrCoords.row.id }
|
|
112
|
+
: {
|
|
113
|
+
columnId:
|
|
114
|
+
typeof cellOrCoords.column === "string" ?
|
|
115
|
+
cellOrCoords.column
|
|
116
|
+
: cellOrCoords.column.id,
|
|
117
|
+
rowId:
|
|
118
|
+
typeof cellOrCoords.row === "string" ?
|
|
119
|
+
cellOrCoords.row
|
|
120
|
+
: cellOrCoords.row.id,
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
const getSelection = useCallback(
|
|
124
|
+
(table: Table<TData>) => selector(getCellValues(table, rowId, columnId)),
|
|
125
|
+
[columnId, rowId, selector],
|
|
126
|
+
)
|
|
127
|
+
|
|
128
|
+
return useTableWithSelector(table, getSelection, isEqual)
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
const cellHook = useCell
|
|
132
|
+
|
|
133
|
+
const cellHookʹ =
|
|
134
|
+
<TData extends RowData, TValue>(
|
|
135
|
+
...args:
|
|
136
|
+
| [
|
|
137
|
+
table: Table<TData> | undefined,
|
|
138
|
+
cell:
|
|
139
|
+
| Cell<TData, TValue>
|
|
140
|
+
| CellValues<TData, TValue>
|
|
141
|
+
| CellCoords<TData, TValue>,
|
|
142
|
+
]
|
|
143
|
+
| [
|
|
144
|
+
cell:
|
|
145
|
+
| Cell<TData, TValue>
|
|
146
|
+
| CellValues<TData, TValue>
|
|
147
|
+
| CellCoords<TData, TValue>,
|
|
148
|
+
]
|
|
149
|
+
) =>
|
|
150
|
+
<Selection = CellValues<TData, TValue>>(
|
|
151
|
+
selector?: Selector<TData, TValue, Selection> | undefined,
|
|
152
|
+
isEqual?: IsEqual<NoInfer<Selection>> | undefined,
|
|
153
|
+
): Selection =>
|
|
154
|
+
cellHook(...[...args, selector, isEqual])
|
|
155
|
+
|
|
156
|
+
export { cellHookʹ as useCellʹ }
|
|
@@ -0,0 +1,168 @@
|
|
|
1
|
+
import { useCallback } from "react"
|
|
2
|
+
|
|
3
|
+
import type {
|
|
4
|
+
Column,
|
|
5
|
+
RequiredKeys,
|
|
6
|
+
RowData,
|
|
7
|
+
Table,
|
|
8
|
+
TableOptionsResolved,
|
|
9
|
+
} from "@tanstack/table-core"
|
|
10
|
+
|
|
11
|
+
import { identity } from "../lib/identity"
|
|
12
|
+
import { hasTableArg } from "../lib/hasTableArg"
|
|
13
|
+
import { runGetters } from "../lib/runGetters"
|
|
14
|
+
import { isShallowEqual } from "../lib/isShallowEqual"
|
|
15
|
+
import { invariant } from "../lib/invariant"
|
|
16
|
+
|
|
17
|
+
import type { IsEqual, RunGetters } from "../types"
|
|
18
|
+
|
|
19
|
+
import { useTableWithSelector } from "./useTableWithSelector"
|
|
20
|
+
|
|
21
|
+
export interface ColumnValues<
|
|
22
|
+
TData extends RowData,
|
|
23
|
+
TValue = unknown,
|
|
24
|
+
> extends RunGetters<Column<TData, TValue>> {}
|
|
25
|
+
|
|
26
|
+
const columnValuesCache = new WeakMap<
|
|
27
|
+
RequiredKeys<TableOptionsResolved<any>, "state">,
|
|
28
|
+
Map<string, ColumnValues<any, any>>
|
|
29
|
+
>()
|
|
30
|
+
|
|
31
|
+
const columnHandlersCache = new WeakMap<
|
|
32
|
+
Column<any, any>,
|
|
33
|
+
{
|
|
34
|
+
toggleGroupingHandler: ReturnType<
|
|
35
|
+
Column<any, any>["getToggleGroupingHandler"]
|
|
36
|
+
>
|
|
37
|
+
toggleSortingHandler: ReturnType<
|
|
38
|
+
Column<any, any>["getToggleSortingHandler"]
|
|
39
|
+
>
|
|
40
|
+
toggleVisibilityHandler: ReturnType<
|
|
41
|
+
Column<any, any>["getToggleVisibilityHandler"]
|
|
42
|
+
>
|
|
43
|
+
}
|
|
44
|
+
>()
|
|
45
|
+
|
|
46
|
+
const getColumnValues = <TData extends RowData, TValue = unknown>(
|
|
47
|
+
table: Table<TData>,
|
|
48
|
+
columnId: string,
|
|
49
|
+
): ColumnValues<TData, TValue> => {
|
|
50
|
+
let columnCache = columnValuesCache.get(table.options)
|
|
51
|
+
if (!columnCache) {
|
|
52
|
+
columnCache = new Map()
|
|
53
|
+
columnValuesCache.set(table.options, columnCache)
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
let cached = columnCache.get(columnId)
|
|
57
|
+
|
|
58
|
+
if (!cached) {
|
|
59
|
+
const column = table.getColumn(columnId) as
|
|
60
|
+
| Column<TData, TValue>
|
|
61
|
+
| undefined
|
|
62
|
+
|
|
63
|
+
invariant(column)
|
|
64
|
+
|
|
65
|
+
let cachedHandlers = columnHandlersCache.get(column)
|
|
66
|
+
if (!cachedHandlers) {
|
|
67
|
+
cachedHandlers = {
|
|
68
|
+
toggleGroupingHandler: column.getToggleGroupingHandler(),
|
|
69
|
+
toggleSortingHandler: column.getToggleSortingHandler(),
|
|
70
|
+
toggleVisibilityHandler: column.getToggleVisibilityHandler(),
|
|
71
|
+
}
|
|
72
|
+
columnHandlersCache.set(column, cachedHandlers)
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
const {
|
|
76
|
+
toggleGroupingHandler,
|
|
77
|
+
toggleSortingHandler,
|
|
78
|
+
toggleVisibilityHandler,
|
|
79
|
+
} = cachedHandlers
|
|
80
|
+
|
|
81
|
+
cached = {
|
|
82
|
+
...runGetters(column),
|
|
83
|
+
toggleGroupingHandler,
|
|
84
|
+
toggleSortingHandler,
|
|
85
|
+
toggleVisibilityHandler,
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
columnCache.set(columnId, cached)
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
return cached
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
type Selector<TData extends RowData, TValue, Selection> = (
|
|
95
|
+
table: ColumnValues<TData, TValue>,
|
|
96
|
+
) => Selection
|
|
97
|
+
|
|
98
|
+
export const useColumn = <
|
|
99
|
+
TData extends RowData,
|
|
100
|
+
TValue = unknown,
|
|
101
|
+
Selection = ColumnValues<TData, TValue>,
|
|
102
|
+
>(
|
|
103
|
+
...args:
|
|
104
|
+
| [
|
|
105
|
+
table: Table<TData> | undefined,
|
|
106
|
+
column:
|
|
107
|
+
| Column<TData, TValue>
|
|
108
|
+
| ColumnValues<TData, TValue>
|
|
109
|
+
| { id: string }
|
|
110
|
+
| string,
|
|
111
|
+
selector?: Selector<TData, TValue, Selection> | undefined,
|
|
112
|
+
isEqual?: IsEqual<NoInfer<Selection>> | undefined,
|
|
113
|
+
]
|
|
114
|
+
| [
|
|
115
|
+
column:
|
|
116
|
+
| Column<TData, TValue>
|
|
117
|
+
| ColumnValues<TData, TValue>
|
|
118
|
+
| { id: string }
|
|
119
|
+
| string,
|
|
120
|
+
selector?: Selector<TData, TValue, Selection> | undefined,
|
|
121
|
+
isEqual?: IsEqual<NoInfer<Selection>> | undefined,
|
|
122
|
+
]
|
|
123
|
+
): Selection => {
|
|
124
|
+
const [
|
|
125
|
+
table,
|
|
126
|
+
columnOrId,
|
|
127
|
+
selector = identity as never,
|
|
128
|
+
isEqual = isShallowEqual,
|
|
129
|
+
] = hasTableArg(args) ? args : [undefined, ...args]
|
|
130
|
+
|
|
131
|
+
const columnId = typeof columnOrId === "string" ? columnOrId : columnOrId.id
|
|
132
|
+
|
|
133
|
+
const getSelection = useCallback(
|
|
134
|
+
(table: Table<TData>) => selector(getColumnValues(table, columnId)),
|
|
135
|
+
[columnId, selector],
|
|
136
|
+
)
|
|
137
|
+
|
|
138
|
+
return useTableWithSelector(table, getSelection, isEqual)
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
const columnHook = useColumn
|
|
142
|
+
|
|
143
|
+
const columnHookʹ =
|
|
144
|
+
<TData extends RowData, TValue = unknown>(
|
|
145
|
+
...args:
|
|
146
|
+
| [
|
|
147
|
+
table: Table<TData> | undefined,
|
|
148
|
+
column:
|
|
149
|
+
| Column<TData, TValue>
|
|
150
|
+
| ColumnValues<TData, TValue>
|
|
151
|
+
| { id: string }
|
|
152
|
+
| string,
|
|
153
|
+
]
|
|
154
|
+
| [
|
|
155
|
+
column:
|
|
156
|
+
| Column<TData, TValue>
|
|
157
|
+
| ColumnValues<TData, TValue>
|
|
158
|
+
| { id: string }
|
|
159
|
+
| string,
|
|
160
|
+
]
|
|
161
|
+
) =>
|
|
162
|
+
<Selection = ColumnValues<TData, TValue>>(
|
|
163
|
+
selector?: Selector<TData, TValue, Selection> | undefined,
|
|
164
|
+
isEqual?: IsEqual<NoInfer<Selection>> | undefined,
|
|
165
|
+
): Selection =>
|
|
166
|
+
columnHook(...[...args, selector, isEqual])
|
|
167
|
+
|
|
168
|
+
export { columnHookʹ as useColumnʹ }
|
|
@@ -0,0 +1,151 @@
|
|
|
1
|
+
import { useCallback } from "react"
|
|
2
|
+
|
|
3
|
+
import type {
|
|
4
|
+
Header,
|
|
5
|
+
RequiredKeys,
|
|
6
|
+
RowData,
|
|
7
|
+
Table,
|
|
8
|
+
TableOptionsResolved,
|
|
9
|
+
} from "@tanstack/table-core"
|
|
10
|
+
|
|
11
|
+
import { identity } from "../lib/identity"
|
|
12
|
+
import { hasTableArg } from "../lib/hasTableArg"
|
|
13
|
+
import { runGetters } from "../lib/runGetters"
|
|
14
|
+
import { isShallowEqual } from "../lib/isShallowEqual"
|
|
15
|
+
import { invariant } from "../lib/invariant"
|
|
16
|
+
|
|
17
|
+
import type { IsEqual, RunGetters } from "../types"
|
|
18
|
+
|
|
19
|
+
import { useTableWithSelector } from "./useTableWithSelector"
|
|
20
|
+
|
|
21
|
+
export interface HeaderValues<TData extends RowData, TValue> extends RunGetters<
|
|
22
|
+
Header<TData, TValue>
|
|
23
|
+
> {}
|
|
24
|
+
|
|
25
|
+
const headerValuesCache = new WeakMap<
|
|
26
|
+
RequiredKeys<TableOptionsResolved<any>, "state">,
|
|
27
|
+
Map<string, HeaderValues<any, any>>
|
|
28
|
+
>()
|
|
29
|
+
|
|
30
|
+
const headerHandlersCache = new WeakMap<
|
|
31
|
+
Header<any, any>,
|
|
32
|
+
{
|
|
33
|
+
resizeHandler: ReturnType<Header<any, any>["getResizeHandler"]>
|
|
34
|
+
}
|
|
35
|
+
>()
|
|
36
|
+
|
|
37
|
+
const getHeaderValues = <TData extends RowData, TValue>(
|
|
38
|
+
table: Table<TData>,
|
|
39
|
+
headerId: string,
|
|
40
|
+
): HeaderValues<TData, TValue> => {
|
|
41
|
+
let headerCache = headerValuesCache.get(table.options)
|
|
42
|
+
if (!headerCache) {
|
|
43
|
+
headerCache = new Map()
|
|
44
|
+
headerValuesCache.set(table.options, headerCache)
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
let cached = headerCache.get(headerId)
|
|
48
|
+
|
|
49
|
+
if (!cached) {
|
|
50
|
+
const header = table.getFlatHeaders().find((h) => h.id === headerId) as
|
|
51
|
+
| Header<TData, TValue>
|
|
52
|
+
| undefined
|
|
53
|
+
|
|
54
|
+
invariant(header)
|
|
55
|
+
|
|
56
|
+
let cachedHandlers = headerHandlersCache.get(header)
|
|
57
|
+
if (!cachedHandlers) {
|
|
58
|
+
cachedHandlers = {
|
|
59
|
+
resizeHandler: header.getResizeHandler(),
|
|
60
|
+
}
|
|
61
|
+
headerHandlersCache.set(header, cachedHandlers)
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
const { resizeHandler } = cachedHandlers
|
|
65
|
+
|
|
66
|
+
cached = {
|
|
67
|
+
...runGetters(header),
|
|
68
|
+
resizeHandler,
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
headerCache.set(headerId, cached)
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
return cached
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
type Selector<TData extends RowData, TValue, Selection> = (
|
|
78
|
+
headerValues: HeaderValues<TData, TValue>,
|
|
79
|
+
) => Selection
|
|
80
|
+
|
|
81
|
+
export const useHeader = <
|
|
82
|
+
TData extends RowData,
|
|
83
|
+
TValue,
|
|
84
|
+
Selection = HeaderValues<TData, TValue>,
|
|
85
|
+
>(
|
|
86
|
+
...args:
|
|
87
|
+
| [
|
|
88
|
+
table: Table<TData> | undefined,
|
|
89
|
+
header:
|
|
90
|
+
| Header<TData, TValue>
|
|
91
|
+
| HeaderValues<TData, TValue>
|
|
92
|
+
| { id: string }
|
|
93
|
+
| string,
|
|
94
|
+
selector?: Selector<TData, TValue, Selection> | undefined,
|
|
95
|
+
isEqual?: IsEqual<NoInfer<Selection>> | undefined,
|
|
96
|
+
]
|
|
97
|
+
| [
|
|
98
|
+
header:
|
|
99
|
+
| Header<TData, TValue>
|
|
100
|
+
| HeaderValues<TData, TValue>
|
|
101
|
+
| { id: string }
|
|
102
|
+
| string,
|
|
103
|
+
selector?: Selector<TData, TValue, Selection> | undefined,
|
|
104
|
+
isEqual?: IsEqual<NoInfer<Selection>> | undefined,
|
|
105
|
+
]
|
|
106
|
+
): Selection => {
|
|
107
|
+
const [
|
|
108
|
+
table,
|
|
109
|
+
headerOrId,
|
|
110
|
+
selector = identity as never,
|
|
111
|
+
isEqual = isShallowEqual,
|
|
112
|
+
] = hasTableArg(args) ? args : [undefined, ...args]
|
|
113
|
+
|
|
114
|
+
const headerId = typeof headerOrId === "string" ? headerOrId : headerOrId.id
|
|
115
|
+
|
|
116
|
+
const getSelection = useCallback(
|
|
117
|
+
(table: Table<TData>) => selector(getHeaderValues(table, headerId)),
|
|
118
|
+
[headerId, selector],
|
|
119
|
+
)
|
|
120
|
+
|
|
121
|
+
return useTableWithSelector(table, getSelection, isEqual)
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
const headerHook = useHeader
|
|
125
|
+
|
|
126
|
+
const headerHookʹ =
|
|
127
|
+
<TData extends RowData, TValue>(
|
|
128
|
+
...args:
|
|
129
|
+
| [
|
|
130
|
+
table: Table<TData> | undefined,
|
|
131
|
+
header:
|
|
132
|
+
| Header<TData, TValue>
|
|
133
|
+
| HeaderValues<TData, TValue>
|
|
134
|
+
| { id: string }
|
|
135
|
+
| string,
|
|
136
|
+
]
|
|
137
|
+
| [
|
|
138
|
+
header:
|
|
139
|
+
| Header<TData, TValue>
|
|
140
|
+
| HeaderValues<TData, TValue>
|
|
141
|
+
| { id: string }
|
|
142
|
+
| string,
|
|
143
|
+
]
|
|
144
|
+
) =>
|
|
145
|
+
<Selection = HeaderValues<TData, TValue>>(
|
|
146
|
+
selector?: Selector<TData, TValue, Selection> | undefined,
|
|
147
|
+
isEqual?: IsEqual<NoInfer<Selection>> | undefined,
|
|
148
|
+
): Selection =>
|
|
149
|
+
headerHook(...[...args, selector, isEqual])
|
|
150
|
+
|
|
151
|
+
export { headerHookʹ as useHeaderʹ }
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
import { useCallback, useState } from "react"
|
|
2
|
+
|
|
3
|
+
import {
|
|
4
|
+
type OnChangeFn,
|
|
5
|
+
type RowData,
|
|
6
|
+
type Table,
|
|
7
|
+
type TableOptions,
|
|
8
|
+
type TableState,
|
|
9
|
+
createTable,
|
|
10
|
+
} from "@tanstack/table-core"
|
|
11
|
+
|
|
12
|
+
import { useShallowMemo } from "../lib/useShallowMemo"
|
|
13
|
+
import { tableRegistry } from "../lib/tableRegistry"
|
|
14
|
+
import { invariant } from "../lib/invariant"
|
|
15
|
+
import { useLayoutEffect } from "../lib/useLayoutEffect"
|
|
16
|
+
|
|
17
|
+
export const useReactTable = <TData extends RowData>({
|
|
18
|
+
state,
|
|
19
|
+
...options
|
|
20
|
+
}: TableOptions<TData>): Table<TData> => {
|
|
21
|
+
const memoOptions = useShallowMemo(options)
|
|
22
|
+
const memoState = useShallowMemo(state)
|
|
23
|
+
|
|
24
|
+
// We'll maintain both our internal state and any user-provided
|
|
25
|
+
// state.
|
|
26
|
+
const [internalState, setInternalState] = useState<TableState>(null!)
|
|
27
|
+
|
|
28
|
+
const onStateChange = useCallback<OnChangeFn<TableState>>(
|
|
29
|
+
(updater) => {
|
|
30
|
+
setInternalState(updater)
|
|
31
|
+
memoOptions.onStateChange?.call(undefined, updater)
|
|
32
|
+
},
|
|
33
|
+
[memoOptions.onStateChange],
|
|
34
|
+
)
|
|
35
|
+
|
|
36
|
+
// Create a new table and store it in state
|
|
37
|
+
const [table] = useState(() => {
|
|
38
|
+
// Compose in the generic memoOptions to the user memoOptions
|
|
39
|
+
const resolvedOptions = {
|
|
40
|
+
state: {}, // Dummy state
|
|
41
|
+
onStateChange: () => {}, // noop
|
|
42
|
+
renderFallbackValue: null,
|
|
43
|
+
...memoOptions,
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
const table = createTable<TData>(resolvedOptions)
|
|
47
|
+
|
|
48
|
+
table.setOptions((prev) => ({
|
|
49
|
+
...prev,
|
|
50
|
+
...memoOptions,
|
|
51
|
+
state: {
|
|
52
|
+
...table.initialState,
|
|
53
|
+
...memoState,
|
|
54
|
+
},
|
|
55
|
+
onStateChange,
|
|
56
|
+
}))
|
|
57
|
+
|
|
58
|
+
tableRegistry.set(table, { listeners: new Set() })
|
|
59
|
+
|
|
60
|
+
return table
|
|
61
|
+
})
|
|
62
|
+
|
|
63
|
+
if (!internalState) {
|
|
64
|
+
setInternalState(table.initialState)
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
useLayoutEffect(() => {
|
|
68
|
+
// Compose the default state above with any user state. This will allow the user
|
|
69
|
+
// to only control a subset of the state if desired.
|
|
70
|
+
table.setOptions((prev) => ({
|
|
71
|
+
...prev,
|
|
72
|
+
...memoOptions,
|
|
73
|
+
state: {
|
|
74
|
+
...internalState,
|
|
75
|
+
...memoState,
|
|
76
|
+
},
|
|
77
|
+
onStateChange,
|
|
78
|
+
}))
|
|
79
|
+
|
|
80
|
+
const { listeners } = tableRegistry.get(table) ?? {}
|
|
81
|
+
invariant(listeners)
|
|
82
|
+
for (const listener of listeners) {
|
|
83
|
+
listener()
|
|
84
|
+
}
|
|
85
|
+
}, [memoOptions, memoState, onStateChange, table, internalState])
|
|
86
|
+
|
|
87
|
+
return table
|
|
88
|
+
}
|
|
@@ -0,0 +1,132 @@
|
|
|
1
|
+
import { useCallback } from "react"
|
|
2
|
+
|
|
3
|
+
import type {
|
|
4
|
+
RequiredKeys,
|
|
5
|
+
Row,
|
|
6
|
+
RowData,
|
|
7
|
+
Table,
|
|
8
|
+
TableOptionsResolved,
|
|
9
|
+
} from "@tanstack/table-core"
|
|
10
|
+
|
|
11
|
+
import { identity } from "../lib/identity"
|
|
12
|
+
import { hasTableArg } from "../lib/hasTableArg"
|
|
13
|
+
import { runGetters } from "../lib/runGetters"
|
|
14
|
+
import { isShallowEqual } from "../lib/isShallowEqual"
|
|
15
|
+
|
|
16
|
+
import type { IsEqual, RunGetters } from "../types"
|
|
17
|
+
|
|
18
|
+
import { useTableWithSelector } from "./useTableWithSelector"
|
|
19
|
+
|
|
20
|
+
export interface RowValues<TData extends RowData> extends RunGetters<
|
|
21
|
+
Row<TData>
|
|
22
|
+
> {}
|
|
23
|
+
|
|
24
|
+
const hookRowCache = new WeakMap<
|
|
25
|
+
RequiredKeys<TableOptionsResolved<any>, "state">,
|
|
26
|
+
Map<string, RowValues<any>>
|
|
27
|
+
>()
|
|
28
|
+
|
|
29
|
+
const rowHandlersCache = new WeakMap<
|
|
30
|
+
Row<any>,
|
|
31
|
+
{
|
|
32
|
+
toggleExpandedHandler: ReturnType<Row<any>["getToggleExpandedHandler"]>
|
|
33
|
+
toggleSelectedHandler: ReturnType<Row<any>["getToggleSelectedHandler"]>
|
|
34
|
+
}
|
|
35
|
+
>()
|
|
36
|
+
|
|
37
|
+
const getRowValues = <TData extends RowData>(
|
|
38
|
+
table: Table<TData>,
|
|
39
|
+
rowId: string,
|
|
40
|
+
): RowValues<TData> => {
|
|
41
|
+
let rowCache = hookRowCache.get(table.options)
|
|
42
|
+
if (!rowCache) {
|
|
43
|
+
rowCache = new Map()
|
|
44
|
+
hookRowCache.set(table.options, rowCache)
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
let cached = rowCache.get(rowId)
|
|
48
|
+
|
|
49
|
+
if (!cached) {
|
|
50
|
+
const row = table.getRow(rowId)
|
|
51
|
+
|
|
52
|
+
let cachedHandlers = rowHandlersCache.get(row)
|
|
53
|
+
if (!cachedHandlers) {
|
|
54
|
+
cachedHandlers = {
|
|
55
|
+
toggleExpandedHandler: row.getToggleExpandedHandler(),
|
|
56
|
+
toggleSelectedHandler: row.getToggleSelectedHandler(),
|
|
57
|
+
}
|
|
58
|
+
rowHandlersCache.set(row, cachedHandlers)
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
const { toggleExpandedHandler, toggleSelectedHandler } = cachedHandlers
|
|
62
|
+
|
|
63
|
+
const { getGroupingValue, getUniqueValues, getValue, ...rest } = row
|
|
64
|
+
|
|
65
|
+
cached = {
|
|
66
|
+
...runGetters(rest),
|
|
67
|
+
getGroupingValue,
|
|
68
|
+
getUniqueValues,
|
|
69
|
+
getValue,
|
|
70
|
+
toggleExpandedHandler,
|
|
71
|
+
toggleSelectedHandler,
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
rowCache.set(rowId, cached)
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
return cached
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
type Selector<TData extends RowData, Selection> = (
|
|
81
|
+
rowValues: RowValues<TData>,
|
|
82
|
+
) => Selection
|
|
83
|
+
|
|
84
|
+
export const useRow = <TData extends RowData, Selection = RowValues<TData>>(
|
|
85
|
+
...args:
|
|
86
|
+
| [
|
|
87
|
+
table: Table<TData> | undefined,
|
|
88
|
+
row: Row<TData> | RowValues<TData> | { id: string } | string,
|
|
89
|
+
selector?: Selector<TData, Selection> | undefined,
|
|
90
|
+
isEqual?: IsEqual<NoInfer<Selection>> | undefined,
|
|
91
|
+
]
|
|
92
|
+
| [
|
|
93
|
+
row: Row<TData> | RowValues<TData> | { id: string } | string,
|
|
94
|
+
selector?: Selector<TData, Selection> | undefined,
|
|
95
|
+
isEqual?: IsEqual<NoInfer<Selection>> | undefined,
|
|
96
|
+
]
|
|
97
|
+
): Selection => {
|
|
98
|
+
const [
|
|
99
|
+
table,
|
|
100
|
+
rowOrId,
|
|
101
|
+
selector = identity as never,
|
|
102
|
+
isEqual = isShallowEqual,
|
|
103
|
+
] = hasTableArg(args) ? args : [undefined, ...args]
|
|
104
|
+
|
|
105
|
+
const rowId = typeof rowOrId === "string" ? rowOrId : rowOrId.id
|
|
106
|
+
|
|
107
|
+
const getSelection = useCallback(
|
|
108
|
+
(table: Table<TData>) => selector(getRowValues(table, rowId)),
|
|
109
|
+
[rowId, selector],
|
|
110
|
+
)
|
|
111
|
+
|
|
112
|
+
return useTableWithSelector(table, getSelection, isEqual)
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
const rowHook = useRow
|
|
116
|
+
|
|
117
|
+
const rowHookʹ =
|
|
118
|
+
<TData extends RowData>(
|
|
119
|
+
...args:
|
|
120
|
+
| [
|
|
121
|
+
table: Table<TData> | undefined,
|
|
122
|
+
row: Row<TData> | RowValues<TData> | { id: string } | string,
|
|
123
|
+
]
|
|
124
|
+
| [row: Row<TData> | RowValues<TData> | { id: string } | string]
|
|
125
|
+
) =>
|
|
126
|
+
<Selection = RowValues<TData>>(
|
|
127
|
+
selector?: Selector<TData, Selection> | undefined,
|
|
128
|
+
isEqual?: IsEqual<NoInfer<Selection>> | undefined,
|
|
129
|
+
): Selection =>
|
|
130
|
+
rowHook(...[...args, selector, isEqual])
|
|
131
|
+
|
|
132
|
+
export { rowHookʹ as useRowʹ }
|