@tanstack/table-core 8.0.0-alpha.10

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 (112) hide show
  1. package/build/cjs/_virtual/_rollupPluginBabelHelpers.js +112 -0
  2. package/build/cjs/_virtual/_rollupPluginBabelHelpers.js.map +1 -0
  3. package/build/cjs/aggregationTypes.js +130 -0
  4. package/build/cjs/aggregationTypes.js.map +1 -0
  5. package/build/cjs/core.js +545 -0
  6. package/build/cjs/core.js.map +1 -0
  7. package/build/cjs/createTable.js +65 -0
  8. package/build/cjs/createTable.js.map +1 -0
  9. package/build/cjs/features/ColumnSizing.js +316 -0
  10. package/build/cjs/features/ColumnSizing.js.map +1 -0
  11. package/build/cjs/features/Expanding.js +238 -0
  12. package/build/cjs/features/Expanding.js.map +1 -0
  13. package/build/cjs/features/Filters.js +413 -0
  14. package/build/cjs/features/Filters.js.map +1 -0
  15. package/build/cjs/features/Grouping.js +227 -0
  16. package/build/cjs/features/Grouping.js.map +1 -0
  17. package/build/cjs/features/Headers.js +630 -0
  18. package/build/cjs/features/Headers.js.map +1 -0
  19. package/build/cjs/features/Ordering.js +86 -0
  20. package/build/cjs/features/Ordering.js.map +1 -0
  21. package/build/cjs/features/Pagination.js +193 -0
  22. package/build/cjs/features/Pagination.js.map +1 -0
  23. package/build/cjs/features/Pinning.js +148 -0
  24. package/build/cjs/features/Pinning.js.map +1 -0
  25. package/build/cjs/features/RowSelection.js +525 -0
  26. package/build/cjs/features/RowSelection.js.map +1 -0
  27. package/build/cjs/features/Sorting.js +313 -0
  28. package/build/cjs/features/Sorting.js.map +1 -0
  29. package/build/cjs/features/Visibility.js +172 -0
  30. package/build/cjs/features/Visibility.js.map +1 -0
  31. package/build/cjs/filterTypes.js +172 -0
  32. package/build/cjs/filterTypes.js.map +1 -0
  33. package/build/cjs/index.js +75 -0
  34. package/build/cjs/index.js.map +1 -0
  35. package/build/cjs/sortTypes.js +122 -0
  36. package/build/cjs/sortTypes.js.map +1 -0
  37. package/build/cjs/types.js +22 -0
  38. package/build/cjs/types.js.map +1 -0
  39. package/build/cjs/utils/columnFilterRowsFn.js +131 -0
  40. package/build/cjs/utils/columnFilterRowsFn.js.map +1 -0
  41. package/build/cjs/utils/expandRowsFn.js +38 -0
  42. package/build/cjs/utils/expandRowsFn.js.map +1 -0
  43. package/build/cjs/utils/globalFilterRowsFn.js +101 -0
  44. package/build/cjs/utils/globalFilterRowsFn.js.map +1 -0
  45. package/build/cjs/utils/groupRowsFn.js +155 -0
  46. package/build/cjs/utils/groupRowsFn.js.map +1 -0
  47. package/build/cjs/utils/paginateRowsFn.js +44 -0
  48. package/build/cjs/utils/paginateRowsFn.js.map +1 -0
  49. package/build/cjs/utils/sortRowsFn.js +94 -0
  50. package/build/cjs/utils/sortRowsFn.js.map +1 -0
  51. package/build/cjs/utils.js +167 -0
  52. package/build/cjs/utils.js.map +1 -0
  53. package/build/esm/index.js +4689 -0
  54. package/build/esm/index.js.map +1 -0
  55. package/build/stats-html.html +2689 -0
  56. package/build/stats-react.json +939 -0
  57. package/build/types/aggregationTypes.d.ts +22 -0
  58. package/build/types/core.d.ts +105 -0
  59. package/build/types/createTable.d.ts +42 -0
  60. package/build/types/features/ColumnSizing.d.ts +75 -0
  61. package/build/types/features/Expanding.d.ts +50 -0
  62. package/build/types/features/Filters.d.ts +92 -0
  63. package/build/types/features/Grouping.d.ts +85 -0
  64. package/build/types/features/Headers.d.ts +43 -0
  65. package/build/types/features/Ordering.d.ts +21 -0
  66. package/build/types/features/Pagination.d.ts +41 -0
  67. package/build/types/features/Pinning.d.ts +41 -0
  68. package/build/types/features/RowSelection.d.ts +60 -0
  69. package/build/types/features/Sorting.d.ts +81 -0
  70. package/build/types/features/Visibility.d.ts +49 -0
  71. package/build/types/filterTypes.d.ts +50 -0
  72. package/build/types/index.d.ts +23 -0
  73. package/build/types/sortTypes.d.ts +18 -0
  74. package/build/types/types.d.ts +138 -0
  75. package/build/types/utils/columnFilterRowsFn.d.ts +2 -0
  76. package/build/types/utils/expandRowsFn.d.ts +2 -0
  77. package/build/types/utils/globalFilterRowsFn.d.ts +2 -0
  78. package/build/types/utils/groupRowsFn.d.ts +2 -0
  79. package/build/types/utils/paginateRowsFn.d.ts +2 -0
  80. package/build/types/utils/sortRowsFn.d.ts +2 -0
  81. package/build/types/utils.d.ts +23 -0
  82. package/build/umd/index.development.js +4728 -0
  83. package/build/umd/index.development.js.map +1 -0
  84. package/build/umd/index.production.js +12 -0
  85. package/build/umd/index.production.js.map +1 -0
  86. package/package.json +40 -0
  87. package/src/.DS_Store +0 -0
  88. package/src/aggregationTypes.ts +115 -0
  89. package/src/core.tsx +763 -0
  90. package/src/createTable.tsx +137 -0
  91. package/src/features/ColumnSizing.ts +432 -0
  92. package/src/features/Expanding.ts +320 -0
  93. package/src/features/Filters.ts +567 -0
  94. package/src/features/Grouping.ts +363 -0
  95. package/src/features/Headers.ts +747 -0
  96. package/src/features/Ordering.ts +112 -0
  97. package/src/features/Pagination.ts +252 -0
  98. package/src/features/Pinning.ts +177 -0
  99. package/src/features/RowSelection.ts +655 -0
  100. package/src/features/Sorting.ts +460 -0
  101. package/src/features/Visibility.ts +242 -0
  102. package/src/filterTypes.ts +188 -0
  103. package/src/index.tsx +23 -0
  104. package/src/sortTypes.ts +147 -0
  105. package/src/types.ts +311 -0
  106. package/src/utils/columnFilterRowsFn.ts +113 -0
  107. package/src/utils/expandRowsFn.ts +30 -0
  108. package/src/utils/globalFilterRowsFn.ts +89 -0
  109. package/src/utils/groupRowsFn.ts +170 -0
  110. package/src/utils/paginateRowsFn.ts +28 -0
  111. package/src/utils/sortRowsFn.ts +95 -0
  112. package/src/utils.tsx +221 -0
@@ -0,0 +1,460 @@
1
+ import { MouseEvent, TouchEvent } from 'react'
2
+ import { RowModel } from '..'
3
+ import { BuiltInSortType, reSplitAlphaNumeric, sortTypes } from '../sortTypes'
4
+
5
+ import {
6
+ Column,
7
+ Getter,
8
+ Header,
9
+ OnChangeFn,
10
+ PartialGenerics,
11
+ PropGetterValue,
12
+ TableInstance,
13
+ Row,
14
+ Updater,
15
+ } from '../types'
16
+
17
+ import {
18
+ functionalUpdate,
19
+ isFunction,
20
+ makeStateUpdater,
21
+ memo,
22
+ Overwrite,
23
+ propGetter,
24
+ } from '../utils'
25
+
26
+ export type SortDirection = 'asc' | 'desc'
27
+
28
+ export type ColumnSort = {
29
+ id: string
30
+ desc: boolean
31
+ }
32
+
33
+ export type SortingState = ColumnSort[]
34
+
35
+ export type SortingFn<TGenerics extends PartialGenerics> = {
36
+ (rowA: Row<TGenerics>, rowB: Row<TGenerics>, columnId: string): number
37
+ }
38
+
39
+ export type CustomSortingTypes<TGenerics extends PartialGenerics> = Record<
40
+ string,
41
+ SortingFn<TGenerics>
42
+ >
43
+
44
+ export type SortingTableState = {
45
+ sorting: SortingState
46
+ }
47
+
48
+ export type SortType<TGenerics extends PartialGenerics> =
49
+ | 'auto'
50
+ | BuiltInSortType
51
+ | keyof TGenerics['SortingFns']
52
+ | SortingFn<TGenerics>
53
+
54
+ export type SortingColumnDef<TGenerics extends PartialGenerics> = {
55
+ sortType?: SortType<Overwrite<TGenerics, { Value: any }>>
56
+ sortDescFirst?: boolean
57
+ enableSorting?: boolean
58
+ enableMultiSort?: boolean
59
+ defaultCanSort?: boolean
60
+ invertSorting?: boolean
61
+ sortUndefined?: false | -1 | 1
62
+ }
63
+
64
+ export type SortingColumn<TGenerics extends PartialGenerics> = {
65
+ sortType: SortType<Overwrite<TGenerics, { Value: any }>>
66
+ getCanSort: () => boolean
67
+ getCanMultiSort: () => boolean
68
+ getSortIndex: () => number
69
+ getIsSorted: () => false | SortDirection
70
+ toggleSorting: (desc?: boolean, isMulti?: boolean) => void
71
+ getToggleSortingProps: <TGetter extends Getter<ToggleSortingProps>>(
72
+ userProps?: TGetter
73
+ ) => undefined | PropGetterValue<ToggleSortingProps, TGetter>
74
+ }
75
+
76
+ export type SortingOptions<TGenerics extends PartialGenerics> = {
77
+ sortTypes?: TGenerics['SortingFns']
78
+ onSortingChange?: OnChangeFn<SortingState>
79
+ autoResetSorting?: boolean
80
+ enableSorting?: boolean
81
+ enableSortingRemoval?: boolean
82
+ enableMultiRemove?: boolean
83
+ enableMultiSort?: boolean
84
+ sortDescFirst?: boolean
85
+ sortRowsFn?: (
86
+ instance: TableInstance<TGenerics>,
87
+ rowModel: RowModel<TGenerics>
88
+ ) => RowModel<TGenerics>
89
+ maxMultiSortColCount?: number
90
+ isMultiSortEvent?: (e: MouseEvent | TouchEvent) => boolean
91
+ }
92
+
93
+ export type ToggleSortingProps = {
94
+ title?: string
95
+ onClick?: (event: MouseEvent | TouchEvent) => void
96
+ }
97
+
98
+ export type SortingInstance<TGenerics extends PartialGenerics> = {
99
+ _notifySortingReset: () => void
100
+ getColumnAutoSortingFn: (columnId: string) => SortingFn<TGenerics> | undefined
101
+ getColumnAutoSortDir: (columnId: string) => SortDirection
102
+
103
+ getColumnSortingFn: (columnId: string) => SortingFn<TGenerics> | undefined
104
+
105
+ setSorting: (updater: Updater<SortingState>) => void
106
+ toggleColumnSorting: (
107
+ columnId: string,
108
+ desc?: boolean,
109
+ multi?: boolean
110
+ ) => void
111
+ resetSorting: () => void
112
+ getColumnCanSort: (columnId: string) => boolean
113
+ getColumnCanMultiSort: (columnId: string) => boolean
114
+ getColumnIsSorted: (columnId: string) => false | 'asc' | 'desc'
115
+ getColumnSortIndex: (columnId: string) => number
116
+ getToggleSortingProps: <TGetter extends Getter<ToggleSortingProps>>(
117
+ columnId: string,
118
+ userProps?: TGetter
119
+ ) => undefined | PropGetterValue<ToggleSortingProps, TGetter>
120
+ getPreSortedRowModel: () => RowModel<TGenerics>
121
+ getSortedRowModel: () => RowModel<TGenerics>
122
+ }
123
+
124
+ //
125
+
126
+ export const Sorting = {
127
+ getDefaultColumn: <
128
+ TGenerics extends PartialGenerics
129
+ >(): SortingColumnDef<TGenerics> => {
130
+ return {
131
+ sortType: 'auto',
132
+ }
133
+ },
134
+
135
+ getInitialState: (): SortingTableState => {
136
+ return {
137
+ sorting: [],
138
+ }
139
+ },
140
+
141
+ getDefaultOptions: <TGenerics extends PartialGenerics>(
142
+ instance: TableInstance<TGenerics>
143
+ ): SortingOptions<TGenerics> => {
144
+ return {
145
+ onSortingChange: makeStateUpdater('sorting', instance),
146
+ autoResetSorting: true,
147
+ isMultiSortEvent: (e: MouseEvent | TouchEvent) => {
148
+ return e.shiftKey
149
+ },
150
+ }
151
+ },
152
+
153
+ createColumn: <TGenerics extends PartialGenerics>(
154
+ column: Column<TGenerics>,
155
+ instance: TableInstance<TGenerics>
156
+ ): SortingColumn<TGenerics> => {
157
+ return {
158
+ sortType: column.sortType,
159
+ getCanSort: () => instance.getColumnCanSort(column.id),
160
+ getCanMultiSort: () => instance.getColumnCanMultiSort(column.id),
161
+ getSortIndex: () => instance.getColumnSortIndex(column.id),
162
+ getIsSorted: () => instance.getColumnIsSorted(column.id),
163
+ toggleSorting: (desc, isMulti) =>
164
+ instance.toggleColumnSorting(column.id, desc, isMulti),
165
+ getToggleSortingProps: userProps =>
166
+ instance.getToggleSortingProps(column.id, userProps),
167
+ }
168
+ },
169
+
170
+ getInstance: <TGenerics extends PartialGenerics>(
171
+ instance: TableInstance<TGenerics>
172
+ ): SortingInstance<TGenerics> => {
173
+ let registered = false
174
+
175
+ return {
176
+ _notifySortingReset: () => {
177
+ if (!registered) {
178
+ registered = true
179
+ return
180
+ }
181
+
182
+ if (instance.options.autoResetAll === false) {
183
+ return
184
+ }
185
+
186
+ if (
187
+ instance.options.autoResetAll === true ||
188
+ instance.options.autoResetSorting
189
+ ) {
190
+ instance.resetSorting()
191
+ }
192
+ },
193
+ getColumnAutoSortingFn: columnId => {
194
+ const firstRows = instance
195
+ .getGlobalFilteredRowModel()
196
+ .flatRows.slice(100)
197
+
198
+ let isString = false
199
+
200
+ for (const row of firstRows) {
201
+ const value = row?.values[columnId]
202
+
203
+ if (Object.prototype.toString.call(value) === '[object Date]') {
204
+ return sortTypes.datetime
205
+ }
206
+
207
+ if (typeof value === 'string') {
208
+ isString = true
209
+
210
+ if (value.split(reSplitAlphaNumeric).length > 1) {
211
+ return sortTypes.alphanumeric
212
+ }
213
+ }
214
+ }
215
+
216
+ if (isString) {
217
+ return sortTypes.text
218
+ }
219
+
220
+ return sortTypes.basic
221
+ },
222
+ getColumnAutoSortDir: columnId => {
223
+ const firstRow = instance.getGlobalFilteredRowModel().flatRows[0]
224
+
225
+ const value = firstRow?.values[columnId]
226
+
227
+ if (typeof value === 'string') {
228
+ return 'asc'
229
+ }
230
+
231
+ return 'desc'
232
+ },
233
+ getColumnSortingFn: columnId => {
234
+ const column = instance.getColumn(columnId)
235
+ const userSortTypes = instance.options.sortTypes
236
+
237
+ if (!column) {
238
+ throw new Error()
239
+ }
240
+
241
+ return isFunction(column.sortType)
242
+ ? column.sortType
243
+ : column.sortType === 'auto'
244
+ ? instance.getColumnAutoSortingFn(columnId)
245
+ : (userSortTypes as Record<string, any>)?.[
246
+ column.sortType as string
247
+ ] ??
248
+ (sortTypes[
249
+ column.sortType as BuiltInSortType
250
+ ] as SortingFn<TGenerics>)
251
+ },
252
+
253
+ setSorting: updater =>
254
+ instance.options.onSortingChange?.(
255
+ updater,
256
+ functionalUpdate(updater, instance.getState().sorting)
257
+ ),
258
+
259
+ toggleColumnSorting: (columnId, desc, multi) => {
260
+ const column = instance.getColumn(columnId)
261
+
262
+ if (!column) {
263
+ throw new Error()
264
+ }
265
+
266
+ // if (column.columns.length) {
267
+ // column.columns.forEach((c, i) => {
268
+ // if (c.id) {
269
+ // instance.toggleColumnSorting(c.id, undefined, multi || !!i)
270
+ // }
271
+ // })
272
+ // return
273
+ // }
274
+
275
+ instance.setSorting(old => {
276
+ // Find any existing sorting for this column
277
+ const existingSorting = old?.find(d => d.id === columnId)
278
+ const existingIndex = old?.findIndex(d => d.id === columnId)
279
+ const hasDescDefined = typeof desc !== 'undefined' && desc !== null
280
+
281
+ let newSorting: SortingState = []
282
+
283
+ // What should we do with this sort action?
284
+ let sortAction
285
+
286
+ if (column.getCanMultiSort() && multi) {
287
+ if (existingSorting) {
288
+ sortAction = 'toggle'
289
+ } else {
290
+ sortAction = 'add'
291
+ }
292
+ } else {
293
+ // Normal mode
294
+ if (old?.length && existingIndex !== old.length - 1) {
295
+ sortAction = 'replace'
296
+ } else if (existingSorting) {
297
+ sortAction = 'toggle'
298
+ } else {
299
+ sortAction = 'replace'
300
+ }
301
+ }
302
+
303
+ const sortDescFirst =
304
+ column.sortDescFirst ??
305
+ instance.options.sortDescFirst ??
306
+ instance.getColumnAutoSortDir(columnId) === 'desc'
307
+
308
+ // Handle toggle states that will remove the sorting
309
+ if (
310
+ sortAction === 'toggle' && // Must be toggling
311
+ (instance.options.enableSortingRemoval ?? true) && // If enableSortRemove, enable in general
312
+ !hasDescDefined && // Must not be setting desc
313
+ (multi ? instance.options.enableMultiRemove ?? true : true) && // If multi, don't allow if enableMultiRemove
314
+ (existingSorting?.desc // Finally, detect if it should indeed be removed
315
+ ? !sortDescFirst
316
+ : sortDescFirst)
317
+ ) {
318
+ sortAction = 'remove'
319
+ }
320
+
321
+ if (sortAction === 'replace') {
322
+ newSorting = [
323
+ {
324
+ id: columnId,
325
+ desc: hasDescDefined ? desc! : !!sortDescFirst,
326
+ },
327
+ ]
328
+ } else if (sortAction === 'add' && old?.length) {
329
+ newSorting = [
330
+ ...old,
331
+ {
332
+ id: columnId,
333
+ desc: hasDescDefined ? desc! : !!sortDescFirst,
334
+ },
335
+ ]
336
+ // Take latest n columns
337
+ newSorting.splice(
338
+ 0,
339
+ newSorting.length -
340
+ (instance.options.maxMultiSortColCount ??
341
+ Number.MAX_SAFE_INTEGER)
342
+ )
343
+ } else if (sortAction === 'toggle' && old?.length) {
344
+ // This flips (or sets) the
345
+ newSorting = old.map(d => {
346
+ if (d.id === columnId) {
347
+ return {
348
+ ...d,
349
+ desc: hasDescDefined ? desc! : !existingSorting?.desc,
350
+ }
351
+ }
352
+ return d
353
+ })
354
+ } else if (sortAction === 'remove' && old?.length) {
355
+ newSorting = old.filter(d => d.id !== columnId)
356
+ }
357
+
358
+ return newSorting
359
+ })
360
+ },
361
+
362
+ getColumnCanSort: columnId => {
363
+ const column = instance.getColumn(columnId)
364
+
365
+ if (!column) {
366
+ throw new Error()
367
+ }
368
+
369
+ return (
370
+ column.enableSorting ??
371
+ instance.options.enableSorting ??
372
+ column.defaultCanSort ??
373
+ !!column.accessorFn
374
+ // (!!column.accessorFn ||
375
+ // column.columns?.some(c => c.id && instance.getColumnCanSort(c.id))) ??
376
+ // false
377
+ )
378
+ },
379
+
380
+ getColumnCanMultiSort: columnId => {
381
+ const column = instance.getColumn(columnId)
382
+
383
+ if (!column) {
384
+ throw new Error()
385
+ }
386
+
387
+ return (
388
+ column.enableMultiSort ??
389
+ instance.options.enableMultiSort ??
390
+ !!column.accessorFn
391
+ )
392
+ },
393
+
394
+ getColumnIsSorted: columnId => {
395
+ const columnSort = instance
396
+ .getState()
397
+ .sorting?.find(d => d.id === columnId)
398
+
399
+ return !columnSort ? false : columnSort.desc ? 'desc' : 'asc'
400
+ },
401
+
402
+ getColumnSortIndex: columnId =>
403
+ instance.getState().sorting?.findIndex(d => d.id === columnId) ?? -1,
404
+
405
+ resetSorting: () => {
406
+ instance.setSorting(instance.initialState?.sorting ?? [])
407
+ },
408
+
409
+ getToggleSortingProps: (columnId, userProps) => {
410
+ const column = instance.getColumn(columnId)
411
+
412
+ if (!column) {
413
+ throw new Error()
414
+ }
415
+
416
+ const canSort = column.getCanSort()
417
+
418
+ const initialProps: ToggleSortingProps = {
419
+ title: canSort ? 'Toggle Sorting' : undefined,
420
+ onClick: canSort
421
+ ? (e: MouseEvent | TouchEvent) => {
422
+ e.persist()
423
+ column.toggleSorting?.(
424
+ undefined,
425
+ column.getCanMultiSort()
426
+ ? instance.options.isMultiSortEvent?.(e)
427
+ : false
428
+ )
429
+ }
430
+ : undefined,
431
+ }
432
+
433
+ return propGetter(initialProps, userProps)
434
+ },
435
+
436
+ getPreSortedRowModel: () => instance.getGlobalFilteredRowModel(),
437
+ getSortedRowModel: memo(
438
+ () => [
439
+ instance.getState().sorting,
440
+ instance.getGlobalFilteredRowModel(),
441
+ instance.options.sortRowsFn,
442
+ ],
443
+ (sorting, rowModel, sortingFn) => {
444
+ if (!sortingFn || !sorting?.length) {
445
+ return rowModel
446
+ }
447
+
448
+ return sortingFn(instance, rowModel)
449
+ },
450
+ {
451
+ key: 'getSortedRowModel',
452
+ debug: () => instance.options.debugAll ?? instance.options.debugTable,
453
+ onChange: () => {
454
+ instance._notifyGroupingReset()
455
+ },
456
+ }
457
+ ),
458
+ }
459
+ },
460
+ }
@@ -0,0 +1,242 @@
1
+ import {
2
+ Cell,
3
+ Column,
4
+ Getter,
5
+ OnChangeFn,
6
+ PartialGenerics,
7
+ PropGetterValue,
8
+ TableInstance,
9
+ Updater,
10
+ } from '../types'
11
+ import { functionalUpdate, makeStateUpdater, memo, propGetter } from '../utils'
12
+
13
+ export type VisibilityOptions = {
14
+ onColumnVisibilityChange?: OnChangeFn<VisibilityState>
15
+ enableHiding?: boolean
16
+ }
17
+
18
+ export type VisibilityDefaultOptions = {
19
+ onColumnVisibilityChange: OnChangeFn<VisibilityState>
20
+ }
21
+
22
+ export type VisibilityState = Record<string, boolean>
23
+
24
+ export type VisibilityTableState = {
25
+ columnVisibility: VisibilityState
26
+ }
27
+
28
+ export type VisibilityInstance<TGenerics extends PartialGenerics> = {
29
+ getVisibleFlatColumns: () => Column<TGenerics>[]
30
+ getVisibleLeafColumns: () => Column<TGenerics>[]
31
+ setColumnVisibility: (updater: Updater<VisibilityState>) => void
32
+ toggleColumnVisibility: (columnId: string, value?: boolean) => void
33
+ toggleAllColumnsVisible: (value?: boolean) => void
34
+ getColumnIsVisible: (columId: string) => boolean
35
+ getColumnCanHide: (columnId: string) => boolean
36
+ getIsAllColumnsVisible: () => boolean
37
+ getIsSomeColumnsVisible: () => boolean
38
+ getToggleAllColumnsVisibilityProps: <
39
+ TGetter extends Getter<ToggleAllColumnsVisibilityProps>
40
+ >(
41
+ userProps?: TGetter
42
+ ) => undefined | PropGetterValue<ToggleAllColumnsVisibilityProps, TGetter>
43
+ }
44
+
45
+ type ToggleVisibilityProps = {}
46
+ type ToggleAllColumnsVisibilityProps = {}
47
+
48
+ export type VisibilityColumnDef = {
49
+ enableHiding?: boolean
50
+ defaultCanHide?: boolean
51
+ }
52
+
53
+ export type VisibilityRow<TGenerics extends PartialGenerics> = {
54
+ getVisibleCells: () => Cell<TGenerics>[]
55
+ }
56
+
57
+ export type VisibilityColumn = {
58
+ getCanHide: () => boolean
59
+ getIsVisible: () => boolean
60
+ toggleVisibility: (value?: boolean) => void
61
+ getToggleVisibilityProps: <TGetter extends Getter<ToggleVisibilityProps>>(
62
+ userProps?: TGetter
63
+ ) => PropGetterValue<ToggleVisibilityProps, TGetter>
64
+ }
65
+
66
+ //
67
+
68
+ export const Visibility = {
69
+ getInitialState: (): VisibilityTableState => {
70
+ return {
71
+ columnVisibility: {},
72
+ }
73
+ },
74
+
75
+ getDefaultOptions: <TGenerics extends PartialGenerics>(
76
+ instance: TableInstance<TGenerics>
77
+ ): VisibilityDefaultOptions => {
78
+ return {
79
+ onColumnVisibilityChange: makeStateUpdater('columnVisibility', instance),
80
+ }
81
+ },
82
+
83
+ getDefaultColumn: () => {
84
+ return {
85
+ defaultIsVisible: true,
86
+ }
87
+ },
88
+
89
+ createColumn: <TGenerics extends PartialGenerics>(
90
+ column: Column<TGenerics>,
91
+ instance: TableInstance<TGenerics>
92
+ ): VisibilityColumn => {
93
+ return {
94
+ getCanHide: () => instance.getColumnCanHide(column.id),
95
+ getIsVisible: () => instance.getColumnIsVisible(column.id),
96
+ toggleVisibility: value =>
97
+ instance.toggleColumnVisibility(column.id, value),
98
+ getToggleVisibilityProps: userProps => {
99
+ const props: ToggleVisibilityProps = {
100
+ type: 'checkbox',
101
+ checked: column.getIsVisible?.(),
102
+ title: 'Toggle Column Visibility',
103
+ onChange: (e: MouseEvent | TouchEvent) => {
104
+ column.toggleVisibility?.((e.target as HTMLInputElement).checked)
105
+ },
106
+ }
107
+
108
+ return propGetter(props, userProps)
109
+ },
110
+ }
111
+ },
112
+
113
+ getInstance: <TGenerics extends PartialGenerics>(
114
+ instance: TableInstance<TGenerics>
115
+ ): VisibilityInstance<TGenerics> => {
116
+ return {
117
+ getVisibleFlatColumns: memo(
118
+ () => [
119
+ instance.getAllFlatColumns(),
120
+ instance
121
+ .getAllFlatColumns()
122
+ .filter(d => d.getIsVisible?.())
123
+ .map(d => d.id)
124
+ .join('_'),
125
+ ],
126
+ allFlatColumns => {
127
+ return allFlatColumns.filter(d => d.getIsVisible?.())
128
+ },
129
+ {
130
+ key: 'getVisibleFlatColumns',
131
+ debug: () =>
132
+ instance.options.debugAll ?? instance.options.debugColumns,
133
+ }
134
+ ),
135
+
136
+ getVisibleLeafColumns: memo(
137
+ () => [
138
+ instance.getAllLeafColumns(),
139
+ instance
140
+ .getAllLeafColumns()
141
+ .filter(d => d.getIsVisible?.())
142
+ .map(d => d.id)
143
+ .join('_'),
144
+ ],
145
+ allFlatColumns => {
146
+ return allFlatColumns.filter(d => d.getIsVisible?.())
147
+ },
148
+ {
149
+ key: 'getVisibleLeafColumns',
150
+ debug: () =>
151
+ instance.options.debugAll ?? instance.options.debugColumns,
152
+ }
153
+ ),
154
+
155
+ setColumnVisibility: updater =>
156
+ instance.options.onColumnVisibilityChange?.(
157
+ updater,
158
+ functionalUpdate(updater, instance.getState().columnVisibility)
159
+ ),
160
+
161
+ toggleColumnVisibility: (columnId, value) => {
162
+ if (!columnId) return
163
+
164
+ if (instance.getColumnCanHide(columnId)) {
165
+ instance.setColumnVisibility(old => ({
166
+ ...old,
167
+ [columnId]: value ?? !instance.getColumnIsVisible(columnId),
168
+ }))
169
+ }
170
+ },
171
+
172
+ toggleAllColumnsVisible: value => {
173
+ value = value ?? !instance.getIsAllColumnsVisible()
174
+
175
+ instance.setColumnVisibility(
176
+ instance.getAllLeafColumns().reduce(
177
+ (obj, column) => ({
178
+ ...obj,
179
+ [column.id]: !value ? !column.getCanHide?.() : value,
180
+ }),
181
+ {}
182
+ )
183
+ )
184
+ },
185
+
186
+ getColumnIsVisible: columnId => {
187
+ const column = instance.getColumn(columnId)
188
+
189
+ if (!column) {
190
+ throw new Error()
191
+ }
192
+
193
+ return (
194
+ instance.getState().columnVisibility?.[columnId] ??
195
+ column.defaultIsVisible ??
196
+ true
197
+ )
198
+ },
199
+
200
+ getColumnCanHide: columnId => {
201
+ const column = instance.getColumn(columnId)
202
+
203
+ if (!column) {
204
+ throw new Error()
205
+ }
206
+
207
+ return (
208
+ instance.options.enableHiding ??
209
+ column.enableHiding ??
210
+ column.defaultCanHide ??
211
+ true
212
+ )
213
+ },
214
+
215
+ getIsAllColumnsVisible: () =>
216
+ !instance.getAllLeafColumns().some(column => !column.getIsVisible?.()),
217
+
218
+ getIsSomeColumnsVisible: () =>
219
+ instance.getAllLeafColumns().some(column => column.getIsVisible?.()),
220
+
221
+ getToggleAllColumnsVisibilityProps: userProps => {
222
+ const props: ToggleAllColumnsVisibilityProps = {
223
+ onChange: (e: MouseEvent) => {
224
+ instance.toggleAllColumnsVisible(
225
+ (e.target as HTMLInputElement)?.checked
226
+ )
227
+ },
228
+ type: 'checkbox',
229
+ title: 'Toggle visibility for all columns',
230
+ checked: instance.getIsAllColumnsVisible(),
231
+ indeterminate:
232
+ !instance.getIsAllColumnsVisible() &&
233
+ instance.getIsSomeColumnsVisible()
234
+ ? 'indeterminate'
235
+ : undefined,
236
+ }
237
+
238
+ return propGetter(props, userProps)
239
+ },
240
+ }
241
+ },
242
+ }