@tanstack/react-table 0.0.1-alpha.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 (49) hide show
  1. package/dist/react-table.development.js +3406 -0
  2. package/dist/react-table.development.js.map +1 -0
  3. package/dist/react-table.production.min.js +2 -0
  4. package/dist/react-table.production.min.js.map +1 -0
  5. package/lib/index.js +65 -0
  6. package/package.json +122 -0
  7. package/src/.DS_Store +0 -0
  8. package/src/aggregationTypes.ts +115 -0
  9. package/src/core.tsx +1194 -0
  10. package/src/createTable.tsx +181 -0
  11. package/src/features/Expanding.ts +388 -0
  12. package/src/features/Filters.ts +707 -0
  13. package/src/features/Grouping.ts +451 -0
  14. package/src/features/Headers.ts +907 -0
  15. package/src/features/Ordering.ts +134 -0
  16. package/src/features/Pinning.ts +213 -0
  17. package/src/features/Sorting.ts +487 -0
  18. package/src/features/Visibility.ts +281 -0
  19. package/src/features/notest/useAbsoluteLayout.test.js +152 -0
  20. package/src/features/notest/useBlockLayout.test.js +158 -0
  21. package/src/features/notest/useColumnOrder.test.js +186 -0
  22. package/src/features/notest/useExpanded.test.js +125 -0
  23. package/src/features/notest/useFilters.test.js +393 -0
  24. package/src/features/notest/useFiltersAndRowSelect.test.js +256 -0
  25. package/src/features/notest/useFlexLayout.test.js +152 -0
  26. package/src/features/notest/useGroupBy.test.js +259 -0
  27. package/src/features/notest/usePagination.test.js +231 -0
  28. package/src/features/notest/useResizeColumns.test.js +229 -0
  29. package/src/features/notest/useRowSelect.test.js +250 -0
  30. package/src/features/notest/useRowState.test.js +178 -0
  31. package/src/features/tests/Visibility.test.tsx +225 -0
  32. package/src/features/tests/__snapshots__/Visibility.test.tsx.snap +390 -0
  33. package/src/features/tests/withSorting.notest.tsx +341 -0
  34. package/src/features/withColumnResizing.ts +281 -0
  35. package/src/features/withPagination.ts +208 -0
  36. package/src/features/withRowSelection.ts +467 -0
  37. package/src/filterTypes.ts +251 -0
  38. package/src/index.tsx +7 -0
  39. package/src/sortTypes.ts +159 -0
  40. package/src/test-utils/makeTestData.ts +41 -0
  41. package/src/tests/__snapshots__/core.test.tsx.snap +148 -0
  42. package/src/tests/core.test.tsx +241 -0
  43. package/src/types.ts +285 -0
  44. package/src/utils/columnFilterRowsFn.ts +162 -0
  45. package/src/utils/expandRowsFn.ts +53 -0
  46. package/src/utils/globalFilterRowsFn.ts +129 -0
  47. package/src/utils/groupRowsFn.ts +196 -0
  48. package/src/utils/sortRowsFn.ts +115 -0
  49. package/src/utils.tsx +243 -0
@@ -0,0 +1,181 @@
1
+ import * as React from 'react'
2
+ import { Cell, Column, Row } from '.'
3
+ import { createTableInstance } from './core'
4
+ import { ReactTable, ColumnDef, AccessorFn, Options } from './types'
5
+ import { Overwrite } from './utils'
6
+
7
+ type TableHelper<TData, TValue, TFilterFns, TSortingFns, TAggregationFns> = {
8
+ RowType: <TTData>() => TableHelper<
9
+ TTData,
10
+ TValue,
11
+ TFilterFns,
12
+ TSortingFns,
13
+ TAggregationFns
14
+ >
15
+
16
+ FilterFns: <TTFilterFns>(
17
+ filterFns: TTFilterFns
18
+ ) => TableHelper<TData, TValue, TTFilterFns, TSortingFns, TAggregationFns>
19
+
20
+ SortingFns: <TTSortingFns>(
21
+ sortingFns: TTSortingFns
22
+ ) => TableHelper<TData, TValue, TFilterFns, TTSortingFns, TAggregationFns>
23
+
24
+ AggregationFns: <TTAggregationFns>(
25
+ aggregationFns: TTAggregationFns
26
+ ) => TableHelper<TData, TValue, TFilterFns, TSortingFns, TTAggregationFns>
27
+
28
+ createColumns: (
29
+ columns: ColumnDef<
30
+ TData,
31
+ TValue,
32
+ TFilterFns,
33
+ TSortingFns,
34
+ TAggregationFns
35
+ >[]
36
+ ) => ColumnDef<TData, TValue, TFilterFns, TSortingFns, TAggregationFns>[]
37
+
38
+ createGroup: (
39
+ column: Overwrite<
40
+ ColumnDef<TData, unknown, TFilterFns, TSortingFns, TAggregationFns>,
41
+ { __generated?: never; accessorFn?: never; accessorKey?: never }
42
+ >
43
+ ) => ColumnDef<TData, unknown, TFilterFns, TSortingFns, TAggregationFns>
44
+
45
+ createColumn: <TAccessor extends AccessorFn<TData> | keyof TData>(
46
+ accessor: TAccessor,
47
+ column: TAccessor extends (...args: any[]) => any
48
+ ? // Accessor Fn
49
+ Overwrite<
50
+ ColumnDef<
51
+ TData,
52
+ ReturnType<TAccessor>,
53
+ TFilterFns,
54
+ TSortingFns,
55
+ TAggregationFns
56
+ >,
57
+ {
58
+ __generated?: never
59
+ accessorFn?: never
60
+ accessorKey?: never
61
+ id: string
62
+ }
63
+ >
64
+ : TAccessor extends keyof TData
65
+ ? // Accessor Key
66
+ Overwrite<
67
+ ColumnDef<
68
+ TData,
69
+ TData[TAccessor],
70
+ TFilterFns,
71
+ TSortingFns,
72
+ TAggregationFns
73
+ >,
74
+ { __generated?: never; accessorFn?: never; accessorKey?: never }
75
+ >
76
+ : never
77
+ ) => ColumnDef<
78
+ TData,
79
+ TAccessor extends (...args: any[]) => any
80
+ ? ReturnType<TAccessor>
81
+ : TAccessor extends keyof TData
82
+ ? TData[TAccessor]
83
+ : never,
84
+ TFilterFns,
85
+ TSortingFns,
86
+ TAggregationFns
87
+ >
88
+
89
+ useTable: <TData, TValue, TFilterFns, TSortingFns, TAggregationFns>(
90
+ options: Options<TData, TValue, TFilterFns, TSortingFns, TAggregationFns>
91
+ ) => ReactTable<TData, TValue, TFilterFns, TSortingFns, TAggregationFns>
92
+
93
+ types: {
94
+ instance: ReactTable<
95
+ TData,
96
+ TValue,
97
+ TFilterFns,
98
+ TSortingFns,
99
+ TAggregationFns
100
+ >
101
+ columnDef: ColumnDef<
102
+ TData,
103
+ TValue,
104
+ TFilterFns,
105
+ TSortingFns,
106
+ TAggregationFns
107
+ >
108
+ column: Column<TData, TValue, TFilterFns, TSortingFns, TAggregationFns>
109
+ row: Row<TData, TValue, TFilterFns, TSortingFns, TAggregationFns>
110
+ cell: Cell<TData, TValue, TFilterFns, TSortingFns, TAggregationFns>
111
+ }
112
+ }
113
+
114
+ export function createTable<
115
+ TData,
116
+ TValue,
117
+ TFilterFns,
118
+ TSortingFns,
119
+ TAggregationFns
120
+ >(): TableHelper<TData, TValue, TFilterFns, TSortingFns, TAggregationFns> {
121
+ return {
122
+ RowType: () => createTable(),
123
+ FilterFns: () => createTable(),
124
+ SortingFns: () => createTable(),
125
+ AggregationFns: () => createTable(),
126
+ createColumns: columns => columns,
127
+ createColumn: (accessor, column) => {
128
+ column = {
129
+ ...column,
130
+ id: column.id,
131
+ }
132
+
133
+ if (typeof accessor === 'string') {
134
+ return {
135
+ ...column,
136
+ id: column.id ?? accessor,
137
+ accessorKey: accessor,
138
+ __generated: true,
139
+ }
140
+ }
141
+
142
+ if (typeof accessor === 'function') {
143
+ return {
144
+ ...column,
145
+ accessorFn: accessor,
146
+ __generated: true,
147
+ }
148
+ }
149
+
150
+ throw new Error('Invalid accessor')
151
+ },
152
+ createGroup: column => ({
153
+ ...column,
154
+ __generated: true,
155
+ }),
156
+ useTable: <TData, TValue, TFilterFns, TSortingFns, TAggregationFns>(
157
+ options: Options<TData, TValue, TFilterFns, TSortingFns, TAggregationFns>
158
+ ): ReactTable<TData, TValue, TFilterFns, TSortingFns, TAggregationFns> => {
159
+ const instanceRef = React.useRef<
160
+ ReactTable<TData, TValue, TFilterFns, TSortingFns, TAggregationFns>
161
+ >(undefined!)
162
+
163
+ const rerender = React.useReducer(() => ({}), {})[1]
164
+
165
+ if (!instanceRef.current) {
166
+ instanceRef.current = createTableInstance<
167
+ TData,
168
+ TValue,
169
+ TFilterFns,
170
+ TSortingFns,
171
+ TAggregationFns
172
+ >(options, rerender)
173
+ }
174
+
175
+ instanceRef.current.updateOptions(options)
176
+
177
+ return instanceRef.current
178
+ },
179
+ types: undefined as any,
180
+ } as TableHelper<TData, TValue, TFilterFns, TSortingFns, TAggregationFns>
181
+ }
@@ -0,0 +1,388 @@
1
+ import { MouseEvent, TouchEvent } from 'react'
2
+ import { RowModel } from '..'
3
+ import {
4
+ Getter,
5
+ OnChangeFn,
6
+ PropGetterValue,
7
+ ReactTable,
8
+ Row,
9
+ Updater,
10
+ } from '../types'
11
+ import { functionalUpdate, makeStateUpdater, memo, propGetter } from '../utils'
12
+
13
+ export type ExpandedStateList = Record<string, boolean>
14
+ export type ExpandedState = true | Record<string, boolean>
15
+ export type ExpandedTableState = {
16
+ expanded: ExpandedState
17
+ }
18
+
19
+ export type ExpandedRow = {
20
+ toggleExpanded: (expanded?: boolean) => void
21
+ getIsExpanded: () => boolean
22
+ getCanExpand: () => boolean
23
+ getToggleExpandedProps: <TGetter extends Getter<ToggleExpandedProps>>(
24
+ userProps?: TGetter
25
+ ) => undefined | PropGetterValue<ToggleExpandedProps, TGetter>
26
+ }
27
+
28
+ export type ExpandedOptions<
29
+ TData,
30
+ TValue,
31
+ TFilterFns,
32
+ TSortingFns,
33
+ TAggregationFns
34
+ > = {
35
+ onExpandedChange?: OnChangeFn<ExpandedState>
36
+ autoResetExpanded?: boolean
37
+ enableExpanded?: boolean
38
+ expandRowsFn?: (
39
+ instance: ReactTable<
40
+ TData,
41
+ TValue,
42
+ TFilterFns,
43
+ TSortingFns,
44
+ TAggregationFns
45
+ >,
46
+ expandedState: ExpandedState,
47
+ groupedRowModel: RowModel<
48
+ TData,
49
+ TValue,
50
+ TFilterFns,
51
+ TSortingFns,
52
+ TAggregationFns
53
+ >
54
+ ) => RowModel<TData, TValue, TFilterFns, TSortingFns, TAggregationFns>
55
+ expandSubRows?: boolean
56
+ defaultCanExpand?: boolean
57
+ getIsRowExpanded?: (
58
+ row: Row<TData, TValue, TFilterFns, TSortingFns, TAggregationFns>
59
+ ) => boolean
60
+ getRowCanExpand?: (
61
+ row: Row<TData, TValue, TFilterFns, TSortingFns, TAggregationFns>
62
+ ) => boolean
63
+ paginateExpandedRows?: boolean
64
+ }
65
+
66
+ export type ToggleExpandedProps = {
67
+ title?: string
68
+ onClick?: (event: MouseEvent | TouchEvent) => void
69
+ }
70
+
71
+ export type ExpandedInstance<
72
+ TData,
73
+ TValue,
74
+ TFilterFns,
75
+ TSortingFns,
76
+ TAggregationFns
77
+ > = {
78
+ setExpanded: (updater: Updater<ExpandedState>) => void
79
+ toggleRowExpanded: (rowId: string, expanded?: boolean) => void
80
+ toggleAllRowsExpanded: (expanded?: boolean) => void
81
+ resetExpanded: () => void
82
+ getRowCanExpand: (rowId: string) => boolean
83
+ getIsRowExpanded: (rowId: string) => boolean
84
+ getToggleExpandedProps: <TGetter extends Getter<ToggleExpandedProps>>(
85
+ rowId: string,
86
+ userProps?: TGetter
87
+ ) => undefined | PropGetterValue<ToggleExpandedProps, TGetter>
88
+ getToggleAllRowsExpandedProps: <TGetter extends Getter<ToggleExpandedProps>>(
89
+ userProps?: TGetter
90
+ ) => undefined | PropGetterValue<ToggleExpandedProps, TGetter>
91
+ getIsAllRowsExpanded: () => boolean
92
+ getExpandedDepth: () => number
93
+ getExpandedRowModel: () => RowModel<
94
+ TData,
95
+ TValue,
96
+ TFilterFns,
97
+ TSortingFns,
98
+ TAggregationFns
99
+ >
100
+ getPreExpandedRows: () => Row<
101
+ TData,
102
+ TValue,
103
+ TFilterFns,
104
+ TSortingFns,
105
+ TAggregationFns
106
+ >[]
107
+ getPreExpandedFlatRows: () => Row<
108
+ TData,
109
+ TValue,
110
+ TFilterFns,
111
+ TSortingFns,
112
+ TAggregationFns
113
+ >[]
114
+ getPreExpandedRowsById: () => Record<
115
+ string,
116
+ Row<TData, TValue, TFilterFns, TSortingFns, TAggregationFns>
117
+ >
118
+ getExpandedRows: () => Row<
119
+ TData,
120
+ TValue,
121
+ TFilterFns,
122
+ TSortingFns,
123
+ TAggregationFns
124
+ >[]
125
+ getExpandedFlatRows: () => Row<
126
+ TData,
127
+ TValue,
128
+ TFilterFns,
129
+ TSortingFns,
130
+ TAggregationFns
131
+ >[]
132
+ getExpandedRowsById: () => Record<
133
+ string,
134
+ Row<TData, TValue, TFilterFns, TSortingFns, TAggregationFns>
135
+ >
136
+ }
137
+
138
+ //
139
+
140
+ export function getInitialState(): ExpandedTableState {
141
+ return {
142
+ expanded: {},
143
+ }
144
+ }
145
+
146
+ export function getDefaultOptions<
147
+ TData,
148
+ TValue,
149
+ TFilterFns,
150
+ TSortingFns,
151
+ TAggregationFns
152
+ >(
153
+ instance: ReactTable<TData, TValue, TFilterFns, TSortingFns, TAggregationFns>
154
+ ): ExpandedOptions<TData, TValue, TFilterFns, TSortingFns, TAggregationFns> {
155
+ return {
156
+ onExpandedChange: makeStateUpdater('expanded', instance),
157
+ autoResetExpanded: true,
158
+ getIsRowExpanded: row => !!(row?.original as { expanded?: any }).expanded,
159
+ expandSubRows: true,
160
+ paginateExpandedRows: true,
161
+ }
162
+ }
163
+
164
+ export function getInstance<
165
+ TData,
166
+ TValue,
167
+ TFilterFns,
168
+ TSortingFns,
169
+ TAggregationFns
170
+ >(
171
+ instance: ReactTable<TData, TValue, TFilterFns, TSortingFns, TAggregationFns>
172
+ ): ExpandedInstance<TData, TValue, TFilterFns, TSortingFns, TAggregationFns> {
173
+ return {
174
+ setExpanded: updater =>
175
+ instance.options.onExpandedChange?.(
176
+ updater,
177
+ functionalUpdate(updater, instance.getState().expanded)
178
+ ),
179
+ toggleRowExpanded: (rowId, expanded) => {
180
+ if (!rowId) return
181
+
182
+ instance.setExpanded((old = {}) => {
183
+ const exists = old === true ? true : !!old?.[rowId]
184
+
185
+ let oldExpanded: ExpandedStateList = {}
186
+
187
+ if (old === true) {
188
+ Object.keys(instance.getRowsById()).forEach(rowId => {
189
+ oldExpanded[rowId] = true
190
+ })
191
+ } else {
192
+ oldExpanded = old
193
+ }
194
+
195
+ expanded = expanded ?? !exists
196
+
197
+ if (!exists && expanded) {
198
+ return {
199
+ ...oldExpanded,
200
+ [rowId]: true,
201
+ }
202
+ }
203
+
204
+ if (exists && !expanded) {
205
+ const { [rowId]: _, ...rest } = oldExpanded
206
+ return rest
207
+ }
208
+
209
+ return old
210
+ })
211
+ },
212
+ toggleAllRowsExpanded: expanded => {
213
+ if (expanded ?? !instance.getIsAllRowsExpanded()) {
214
+ instance.setExpanded(true)
215
+ } else {
216
+ instance.setExpanded({})
217
+ }
218
+ },
219
+ resetExpanded: () => {
220
+ instance.setExpanded(instance.options?.initialState?.expanded ?? {})
221
+ },
222
+ getIsRowExpanded: rowId => {
223
+ const row = instance.getRow(rowId)
224
+
225
+ if (!row) {
226
+ if (process.env.NODE_ENV !== 'production') {
227
+ console.warn(
228
+ `[ReactTable] getIsRowExpanded: no row found with id ${rowId}`
229
+ )
230
+ }
231
+ throw new Error()
232
+ }
233
+
234
+ const expanded = instance.getState().expanded
235
+
236
+ return !!(
237
+ instance.options.getIsRowExpanded?.(row) ??
238
+ (expanded || expanded?.[rowId])
239
+ )
240
+ },
241
+ getRowCanExpand: rowId => {
242
+ const row = instance.getRow(rowId)
243
+
244
+ if (!row) {
245
+ if (process.env.NODE_ENV !== 'production') {
246
+ console.warn(
247
+ `[ReactTable] getRowCanExpand: no row found with id ${rowId}`
248
+ )
249
+ }
250
+ throw new Error()
251
+ }
252
+
253
+ return (
254
+ instance.options.getRowCanExpand?.(row) ??
255
+ instance.options.enableExpanded ??
256
+ instance.options.defaultCanExpand ??
257
+ !!row.subRows?.length
258
+ )
259
+ },
260
+ getToggleExpandedProps: (rowId, userProps) => {
261
+ const row = instance.getRow(rowId)
262
+
263
+ if (!row) {
264
+ return
265
+ }
266
+
267
+ const canExpand = instance.getRowCanExpand(rowId)
268
+
269
+ const initialProps: ToggleExpandedProps = {
270
+ title: canExpand ? 'Toggle Expanded' : undefined,
271
+ onClick: canExpand
272
+ ? (e: MouseEvent | TouchEvent) => {
273
+ e.persist()
274
+ instance.toggleRowExpanded(rowId)
275
+ }
276
+ : undefined,
277
+ }
278
+
279
+ return propGetter(initialProps, userProps)
280
+ },
281
+ getToggleAllRowsExpandedProps: userProps => {
282
+ const initialProps: ToggleExpandedProps = {
283
+ title: 'Toggle All Expanded',
284
+ onClick: (e: MouseEvent | TouchEvent) => {
285
+ e.persist()
286
+ instance.toggleAllRowsExpanded()
287
+ },
288
+ }
289
+
290
+ return propGetter(initialProps, userProps)
291
+ },
292
+ getIsAllRowsExpanded: () => {
293
+ const expanded = instance.getState().expanded
294
+
295
+ // If expanded is true, save some cycles and return true
296
+ if (expanded === true) {
297
+ return true
298
+ }
299
+
300
+ // If any row is not expanded, return false
301
+ if (
302
+ Object.keys(instance.getRowsById()).some(
303
+ id => !instance.getIsRowExpanded(id)
304
+ )
305
+ ) {
306
+ return false
307
+ }
308
+
309
+ // They must all be expanded :shrug:
310
+ return true
311
+ },
312
+ getExpandedDepth: () => {
313
+ let maxDepth = 0
314
+
315
+ const rowIds =
316
+ instance.getState().expanded === true
317
+ ? Object.keys(instance.getRowsById())
318
+ : Object.keys(instance.getState().expanded)
319
+
320
+ rowIds.forEach(id => {
321
+ const splitId = id.split('.')
322
+ maxDepth = Math.max(maxDepth, splitId.length)
323
+ })
324
+
325
+ return maxDepth
326
+ },
327
+ getExpandedRowModel: memo(
328
+ () => [
329
+ instance.getState().expanded,
330
+ instance.getGroupedRowModel(),
331
+ instance.options.expandRowsFn,
332
+ instance.options.paginateExpandedRows,
333
+ ],
334
+ (expanded, rowModel, expandRowsFn, paginateExpandedRows) => {
335
+ if (
336
+ !expandRowsFn ||
337
+ // Do not expand if rows are not included in pagination
338
+ !paginateExpandedRows ||
339
+ !Object.keys(expanded ?? {}).length
340
+ ) {
341
+ return rowModel
342
+ }
343
+
344
+ if (process.env.NODE_ENV !== 'production' && instance.options.debug)
345
+ console.info('Expanding...')
346
+
347
+ return expandRowsFn(instance, expanded, rowModel)
348
+ },
349
+ 'getExpandedRowModel',
350
+ instance.options.debug
351
+ ),
352
+
353
+ getPreExpandedRows: () => instance.getGroupedRowModel().rows,
354
+ getPreExpandedFlatRows: () => instance.getGroupedRowModel().flatRows,
355
+ getPreExpandedRowsById: () => instance.getGroupedRowModel().rowsById,
356
+ getExpandedRows: () => instance.getExpandedRowModel().rows,
357
+ getExpandedFlatRows: () => instance.getExpandedRowModel().flatRows,
358
+ getExpandedRowsById: () => instance.getExpandedRowModel().rowsById,
359
+ }
360
+ }
361
+
362
+ export function createRow<
363
+ TData,
364
+ TValue,
365
+ TFilterFns,
366
+ TSortingFns,
367
+ TAggregationFns
368
+ >(
369
+ row: Row<TData, TValue, TFilterFns, TSortingFns, TAggregationFns>,
370
+ instance: ReactTable<TData, TValue, TFilterFns, TSortingFns, TAggregationFns>
371
+ ): ExpandedRow {
372
+ return {
373
+ toggleExpanded: expanded =>
374
+ void instance.toggleRowExpanded(row.id, expanded),
375
+ getIsExpanded: () => instance.getIsRowExpanded(row.id),
376
+ getCanExpand: () => row.subRows && !!row.subRows.length,
377
+ getToggleExpandedProps: userProps => {
378
+ const initialProps: ToggleExpandedProps = {
379
+ title: 'Toggle Row Expanded',
380
+ onClick: (e: MouseEvent | TouchEvent) => {
381
+ e.stopPropagation()
382
+ instance.toggleRowExpanded(row.id)
383
+ },
384
+ }
385
+ return propGetter(initialProps, userProps)
386
+ },
387
+ }
388
+ }