@tanstack/react-table 8.0.0-alpha.2 → 8.0.0-alpha.22

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 (99) hide show
  1. package/build/cjs/_virtual/_rollupPluginBabelHelpers.js +0 -78
  2. package/build/cjs/_virtual/_rollupPluginBabelHelpers.js.map +1 -1
  3. package/build/cjs/index.js +96 -12
  4. package/build/cjs/index.js.map +1 -1
  5. package/build/esm/index.js +40 -3663
  6. package/build/esm/index.js.map +1 -1
  7. package/build/stats-html.html +1 -1
  8. package/build/stats-react.json +28 -676
  9. package/build/types/index.d.ts +13 -7
  10. package/build/umd/index.development.js +50 -3665
  11. package/build/umd/index.development.js.map +1 -1
  12. package/build/umd/index.production.js +1 -1
  13. package/build/umd/index.production.js.map +1 -1
  14. package/package.json +4 -1
  15. package/src/index.tsx +104 -7
  16. package/build/cjs/aggregationTypes.js +0 -130
  17. package/build/cjs/aggregationTypes.js.map +0 -1
  18. package/build/cjs/core.js +0 -519
  19. package/build/cjs/core.js.map +0 -1
  20. package/build/cjs/createTable.js +0 -103
  21. package/build/cjs/createTable.js.map +0 -1
  22. package/build/cjs/features/ColumnSizing.js +0 -331
  23. package/build/cjs/features/ColumnSizing.js.map +0 -1
  24. package/build/cjs/features/Expanding.js +0 -234
  25. package/build/cjs/features/Expanding.js.map +0 -1
  26. package/build/cjs/features/Filters.js +0 -396
  27. package/build/cjs/features/Filters.js.map +0 -1
  28. package/build/cjs/features/Grouping.js +0 -228
  29. package/build/cjs/features/Grouping.js.map +0 -1
  30. package/build/cjs/features/Headers.js +0 -486
  31. package/build/cjs/features/Headers.js.map +0 -1
  32. package/build/cjs/features/Ordering.js +0 -83
  33. package/build/cjs/features/Ordering.js.map +0 -1
  34. package/build/cjs/features/Pinning.js +0 -163
  35. package/build/cjs/features/Pinning.js.map +0 -1
  36. package/build/cjs/features/Sorting.js +0 -269
  37. package/build/cjs/features/Sorting.js.map +0 -1
  38. package/build/cjs/features/Visibility.js +0 -160
  39. package/build/cjs/features/Visibility.js.map +0 -1
  40. package/build/cjs/filterTypes.js +0 -172
  41. package/build/cjs/filterTypes.js.map +0 -1
  42. package/build/cjs/sortTypes.js +0 -121
  43. package/build/cjs/sortTypes.js.map +0 -1
  44. package/build/cjs/utils/columnFilterRowsFn.js +0 -130
  45. package/build/cjs/utils/columnFilterRowsFn.js.map +0 -1
  46. package/build/cjs/utils/expandRowsFn.js +0 -38
  47. package/build/cjs/utils/expandRowsFn.js.map +0 -1
  48. package/build/cjs/utils/globalFilterRowsFn.js +0 -100
  49. package/build/cjs/utils/globalFilterRowsFn.js.map +0 -1
  50. package/build/cjs/utils/groupRowsFn.js +0 -154
  51. package/build/cjs/utils/groupRowsFn.js.map +0 -1
  52. package/build/cjs/utils/sortRowsFn.js +0 -93
  53. package/build/cjs/utils/sortRowsFn.js.map +0 -1
  54. package/build/cjs/utils.js +0 -143
  55. package/build/cjs/utils.js.map +0 -1
  56. package/build/types/aggregationTypes.d.ts +0 -22
  57. package/build/types/core.d.ts +0 -126
  58. package/build/types/createTable.d.ts +0 -35
  59. package/build/types/features/ColumnSizing.d.ts +0 -73
  60. package/build/types/features/Expanding.d.ts +0 -52
  61. package/build/types/features/Filters.d.ts +0 -93
  62. package/build/types/features/Grouping.d.ts +0 -82
  63. package/build/types/features/Headers.d.ts +0 -41
  64. package/build/types/features/Ordering.d.ts +0 -19
  65. package/build/types/features/Pinning.d.ts +0 -39
  66. package/build/types/features/Sorting.d.ts +0 -75
  67. package/build/types/features/Visibility.d.ts +0 -47
  68. package/build/types/filterTypes.d.ts +0 -50
  69. package/build/types/sortTypes.d.ts +0 -17
  70. package/build/types/types.d.ts +0 -124
  71. package/build/types/utils/columnFilterRowsFn.d.ts +0 -2
  72. package/build/types/utils/expandRowsFn.d.ts +0 -2
  73. package/build/types/utils/globalFilterRowsFn.d.ts +0 -2
  74. package/build/types/utils/groupRowsFn.d.ts +0 -2
  75. package/build/types/utils/sortRowsFn.d.ts +0 -2
  76. package/build/types/utils.d.ts +0 -24
  77. package/src/aggregationTypes.ts +0 -115
  78. package/src/core.tsx +0 -1232
  79. package/src/createTable.tsx +0 -181
  80. package/src/features/ColumnSizing.ts +0 -482
  81. package/src/features/Expanding.ts +0 -388
  82. package/src/features/Filters.ts +0 -707
  83. package/src/features/Grouping.ts +0 -451
  84. package/src/features/Headers.ts +0 -944
  85. package/src/features/Ordering.ts +0 -134
  86. package/src/features/Pinning.ts +0 -213
  87. package/src/features/Sorting.ts +0 -487
  88. package/src/features/Visibility.ts +0 -281
  89. package/src/features/withPagination.oldts +0 -208
  90. package/src/features/withRowSelection.oldts +0 -467
  91. package/src/filterTypes.ts +0 -251
  92. package/src/sortTypes.ts +0 -159
  93. package/src/types.ts +0 -314
  94. package/src/utils/columnFilterRowsFn.ts +0 -162
  95. package/src/utils/expandRowsFn.ts +0 -53
  96. package/src/utils/globalFilterRowsFn.ts +0 -129
  97. package/src/utils/groupRowsFn.ts +0 -196
  98. package/src/utils/sortRowsFn.ts +0 -115
  99. package/src/utils.tsx +0 -249
@@ -1,129 +0,0 @@
1
- import { Options } from '..'
2
- import { ReactTable, Row, RowModel } from '../types'
3
-
4
- export const globalFilterRowsFn: Options<
5
- any,
6
- any,
7
- {},
8
- {},
9
- {}
10
- >['globalFilterRowsFn'] = <
11
- TData,
12
- TValue,
13
- TFilterFns,
14
- TSortingFns,
15
- TAggregationFns
16
- >(
17
- instance: ReactTable<TData, TValue, TFilterFns, TSortingFns, TAggregationFns>,
18
- globalFilter: any,
19
- rowModel: RowModel<TData, TValue, TFilterFns, TSortingFns, TAggregationFns>
20
- ): RowModel<TData, TValue, TFilterFns, TSortingFns, TAggregationFns> => {
21
- const newFilteredFlatRows: Row<
22
- TData,
23
- TValue,
24
- TFilterFns,
25
- TSortingFns,
26
- TAggregationFns
27
- >[] = []
28
- const newFilteredRowsById: Record<
29
- string,
30
- Row<TData, TValue, TFilterFns, TSortingFns, TAggregationFns>
31
- > = {}
32
-
33
- const filterFromChildrenUp = instance.options.filterFromChildrenUp
34
-
35
- const filterFn = instance.getGlobalFilterFn()
36
-
37
- if (!filterFn) {
38
- if (process.env.NODE_ENV !== 'production') {
39
- console.warn(`Could not find a valid 'globalFilterType'`)
40
- }
41
- return rowModel
42
- }
43
-
44
- const filterableColumns = instance
45
- .getAllLeafColumns()
46
- .filter(column => column.getCanGlobalFilter())
47
-
48
- const filterableColumnIds = filterableColumns.map(d => d.id)
49
-
50
- if (filterFromChildrenUp) {
51
- const recurseFilterRows = (
52
- rowsToFilter: Row<
53
- TData,
54
- TValue,
55
- TFilterFns,
56
- TSortingFns,
57
- TAggregationFns
58
- >[],
59
- depth = 0
60
- ) => {
61
- // Filter from children up
62
- rowsToFilter = rowsToFilter.filter(row => {
63
- if (!row.subRows?.length) {
64
- return true
65
- }
66
-
67
- row.subRows = recurseFilterRows(row.subRows, depth + 1)
68
-
69
- return row.subRows.length
70
- })
71
-
72
- rowsToFilter = filterFn(rowsToFilter, filterableColumnIds, globalFilter)
73
-
74
- // Apply the filter to any subRows
75
- rowsToFilter.forEach(row => {
76
- newFilteredFlatRows.push(row)
77
- newFilteredRowsById[row.id] = row
78
- })
79
-
80
- return rowsToFilter
81
- }
82
-
83
- return {
84
- rows: recurseFilterRows(rowModel.rows),
85
- flatRows: newFilteredFlatRows,
86
- rowsById: newFilteredRowsById,
87
- }
88
- }
89
-
90
- // Filters top level and nested rows
91
- const recurseFilterRows = (
92
- rowsToFilter: Row<
93
- TData,
94
- TValue,
95
- TFilterFns,
96
- TSortingFns,
97
- TAggregationFns
98
- >[],
99
- depth = 0
100
- ) => {
101
- // Filter from parents downward
102
- rowsToFilter = filterFn(rowsToFilter, filterableColumnIds, globalFilter)
103
-
104
- // Apply the filter to any subRows
105
- // We technically could do this recursively in the above loop,
106
- // but that would severely hinder the API for the user, since they
107
- // would be required to do that recursion in some scenarios
108
- rowsToFilter.forEach(row => {
109
- newFilteredFlatRows.push(row)
110
- newFilteredRowsById[row.id] = row
111
-
112
- if (!filterFromChildrenUp) {
113
- if (!row.subRows?.length) {
114
- return
115
- }
116
-
117
- row.subRows = recurseFilterRows(row.subRows, depth + 1)
118
- }
119
- })
120
-
121
- return rowsToFilter
122
- }
123
-
124
- return {
125
- rows: recurseFilterRows(rowModel.rows),
126
- flatRows: newFilteredFlatRows,
127
- rowsById: newFilteredRowsById,
128
- }
129
- }
@@ -1,196 +0,0 @@
1
- import { ReactTable, Row, RowModel } from '../types'
2
- import { Options } from '../types'
3
- import { GroupingState } from '../features/Grouping'
4
- import { flattenBy } from '../utils'
5
-
6
- export const groupRowsFn: Options<any, any, {}, {}, {}>['groupRowsFn'] = <
7
- TData,
8
- TValue,
9
- TFilterFns,
10
- TSortingFns,
11
- TAggregationFns
12
- >(
13
- instance: ReactTable<TData, TValue, TFilterFns, TSortingFns, TAggregationFns>,
14
- groupingState: GroupingState,
15
- sortedRowModel: RowModel<
16
- TData,
17
- TValue,
18
- TFilterFns,
19
- TSortingFns,
20
- TAggregationFns
21
- >
22
- ): RowModel<TData, TValue, TFilterFns, TSortingFns, TAggregationFns> => {
23
- // Filter the grouping list down to columns that exist
24
- const existingGrouping = groupingState.filter(columnId =>
25
- instance.getColumn(columnId)
26
- )
27
-
28
- // Find the columns that can or are aggregating
29
- // Uses each column to aggregate rows into a single value
30
- const aggregateRowsToValues = (
31
- leafRows: Row<TData, TValue, TFilterFns, TSortingFns, TAggregationFns>[],
32
- groupedRows: Row<TData, TValue, TFilterFns, TSortingFns, TAggregationFns>[],
33
- depth: number
34
- ) => {
35
- const values: Record<string, unknown> = {}
36
-
37
- instance.getAllLeafColumns().forEach(column => {
38
- // Don't aggregate columns that are in the grouping
39
- if (existingGrouping.includes(column.id)) {
40
- values[column.id] = groupedRows[0]
41
- ? groupedRows[0].values[column.id]
42
- : null
43
- return
44
- }
45
-
46
- // Aggregate the values
47
- const aggregateFn = instance.getColumnAggregationFn(column.id)
48
-
49
- if (aggregateFn) {
50
- // Get the columnValues to aggregate
51
- const groupedValues = groupedRows.map(row => row.values[column.id])
52
-
53
- // Get the columnValues to aggregate
54
- const leafValues = leafRows.map(row => {
55
- let columnValue = row.values[column.id]
56
-
57
- if (!depth && column.aggregateValue) {
58
- columnValue = column.aggregateValue(columnValue)
59
- }
60
-
61
- return columnValue
62
- })
63
-
64
- values[column.id] = aggregateFn(leafValues, groupedValues)
65
- } else if (column.aggregationType) {
66
- console.info({ column })
67
- throw new Error(
68
- process.env.NODE_ENV !== 'production'
69
- ? `React Table: Invalid column.aggregateType option for column listed above`
70
- : ''
71
- )
72
- } else {
73
- values[column.id] = null
74
- }
75
- })
76
-
77
- return values
78
- }
79
-
80
- const groupedFlatRows: Row<
81
- TData,
82
- TValue,
83
- TFilterFns,
84
- TSortingFns,
85
- TAggregationFns
86
- >[] = []
87
- const groupedRowsById: Record<
88
- string,
89
- Row<TData, TValue, TFilterFns, TSortingFns, TAggregationFns>
90
- > = {}
91
- // const onlyGroupedFlatRows: Row[] = [];
92
- // const onlyGroupedRowsById: Record<RowId, Row> = {};
93
- // const nonGroupedFlatRows: Row[] = [];
94
- // const nonGroupedRowsById: Record<RowId, Row> = {};
95
-
96
- // Recursively group the data
97
- const groupUpRecursively = (
98
- rows: Row<TData, TValue, TFilterFns, TSortingFns, TAggregationFns>[],
99
- depth = 0,
100
- parentId: string
101
- ) => {
102
- // This is the last level, just return the rows
103
- if (depth === existingGrouping.length) {
104
- return rows
105
- }
106
-
107
- const columnId = existingGrouping[depth]!
108
-
109
- // Group the rows together for this level
110
- const rowGroupsMap = groupBy(rows, columnId)
111
-
112
- // Peform aggregations for each group
113
- const aggregatedGroupedRows = Array.from(rowGroupsMap.entries()).map(
114
- ([groupingValue, groupedRows], index) => {
115
- let id = `${columnId}:${groupingValue}`
116
- id = parentId ? `${parentId}>${id}` : id
117
-
118
- // First, Recurse to group sub rows before aggregation
119
- const subRows = groupUpRecursively(groupedRows, depth + 1, id)
120
-
121
- // Flatten the leaf rows of the rows in this group
122
- const leafRows = depth
123
- ? flattenBy(groupedRows, row => row.leafRows)
124
- : groupedRows
125
-
126
- const values = aggregateRowsToValues(leafRows, groupedRows, depth)
127
-
128
- const row = instance.createRow(id, undefined, index, depth, values)
129
-
130
- Object.assign(row, {
131
- groupingColumnId: columnId,
132
- groupingValue,
133
- subRows,
134
- leafRows,
135
- })
136
-
137
- subRows.forEach(subRow => {
138
- groupedFlatRows.push(subRow)
139
- groupedRowsById[subRow.id] = subRow
140
- // if (subRow.getIsGrouped?.()) {
141
- // onlyGroupedFlatRows.push(subRow);
142
- // onlyGroupedRowsById[subRow.id] = subRow;
143
- // } else {
144
- // nonGroupedFlatRows.push(subRow);
145
- // nonGroupedRowsById[subRow.id] = subRow;
146
- // }
147
- })
148
-
149
- return row
150
- }
151
- )
152
-
153
- return aggregatedGroupedRows
154
- }
155
-
156
- const groupedRows = groupUpRecursively(sortedRowModel.rows, 0, '')
157
-
158
- groupedRows.forEach(subRow => {
159
- groupedFlatRows.push(subRow)
160
- groupedRowsById[subRow.id] = subRow
161
- // if (subRow.getIsGrouped?.()) {
162
- // onlyGroupedFlatRows.push(subRow);
163
- // onlyGroupedRowsById[subRow.id] = subRow;
164
- // } else {
165
- // nonGroupedFlatRows.push(subRow);
166
- // nonGroupedRowsById[subRow.id] = subRow;
167
- // }
168
- })
169
-
170
- return {
171
- rows: groupedRows,
172
- flatRows: groupedFlatRows,
173
- rowsById: groupedRowsById,
174
- }
175
- }
176
-
177
- function groupBy<TData, TValue, TFilterFns, TSortingFns, TAggregationFns>(
178
- rows: Row<TData, TValue, TFilterFns, TSortingFns, TAggregationFns>[],
179
- columnId: string
180
- ) {
181
- const groupMap = new Map<
182
- any,
183
- Row<TData, TValue, TFilterFns, TSortingFns, TAggregationFns>[]
184
- >()
185
-
186
- return rows.reduce((map, row) => {
187
- const resKey = `${row.values[columnId]}`
188
- const previous = map.get(resKey)
189
- if (!previous) {
190
- map.set(resKey, [row])
191
- } else {
192
- map.set(resKey, [...previous, row])
193
- }
194
- return map
195
- }, groupMap)
196
- }
@@ -1,115 +0,0 @@
1
- import { ReactTable, Row, RowModel } from '../types'
2
- import { SortingFn, SortingState } from '../features/Sorting'
3
- import { Options } from '../types'
4
-
5
- export const sortRowsFn: Options<any, any, {}, {}, {}>['sortRowsFn'] = <
6
- TData,
7
- TValue,
8
- TFilterFns,
9
- TSortingFns,
10
- TAggregationFns
11
- >(
12
- instance: ReactTable<TData, TValue, TFilterFns, TSortingFns, TAggregationFns>,
13
- sortingState: SortingState,
14
- rowModel: RowModel<TData, TValue, TFilterFns, TSortingFns, TAggregationFns>
15
- ): RowModel<TData, TValue, TFilterFns, TSortingFns, TAggregationFns> => {
16
- const sortedFlatRows: Row<
17
- TData,
18
- TValue,
19
- TFilterFns,
20
- TSortingFns,
21
- TAggregationFns
22
- >[] = []
23
-
24
- // Filter out sortings that correspond to non existing columns
25
- const availableSorting = sortingState.filter(sort =>
26
- instance.getColumnCanSort(sort.id)
27
- )
28
-
29
- const columnInfoById: Record<
30
- string,
31
- {
32
- sortUndefined?: false | -1 | 1
33
- invertSorting?: boolean
34
- sortingFn: SortingFn<
35
- TData,
36
- TValue,
37
- TFilterFns,
38
- TSortingFns,
39
- TAggregationFns
40
- >
41
- }
42
- > = {}
43
-
44
- availableSorting.forEach(sortEntry => {
45
- const column = instance.getColumn(sortEntry.id)!
46
-
47
- columnInfoById[sortEntry.id] = {
48
- sortUndefined: column.sortUndefined,
49
- invertSorting: column.invertSorting,
50
- sortingFn: instance.getColumnSortingFn(sortEntry.id)!,
51
- }
52
- })
53
-
54
- const sortData = (
55
- rows: Row<TData, TValue, TFilterFns, TSortingFns, TAggregationFns>[]
56
- ) => {
57
- // This will also perform a stable sorting using the row index
58
- // if needed.
59
- const sortedData = rows.slice()
60
-
61
- sortedData.sort((rowA, rowB) => {
62
- for (let i = 0; i < availableSorting.length; i += 1) {
63
- const sortEntry = availableSorting[i]!
64
- const columnInfo = columnInfoById[sortEntry.id]!
65
- const isDesc = sortEntry?.desc ?? false
66
-
67
- if (columnInfo.sortUndefined) {
68
- const aValue = rowA.values[sortEntry.id]
69
- const bValue = rowB.values[sortEntry.id]
70
-
71
- const aUndefined = typeof aValue === 'undefined'
72
- const bUndefined = typeof bValue === 'undefined'
73
-
74
- if (aUndefined || bUndefined) {
75
- return aUndefined && bUndefined ? 0 : aUndefined ? 1 : -1
76
- }
77
- }
78
-
79
- // This function should always return in ascending order
80
- let sortInt = columnInfo.sortingFn(rowA, rowB, sortEntry.id)
81
-
82
- if (sortInt !== 0) {
83
- if (isDesc) {
84
- sortInt *= -1
85
- }
86
-
87
- if (columnInfo.invertSorting) {
88
- sortInt *= -1
89
- }
90
-
91
- return sortInt
92
- }
93
- }
94
-
95
- return rowA.index - rowB.index
96
- })
97
-
98
- // If there are sub-rows, sort them
99
- sortedData.forEach(row => {
100
- sortedFlatRows.push(row)
101
- if (!row.subRows || row.subRows.length <= 1) {
102
- return
103
- }
104
- row.subRows = sortData(row.subRows)
105
- })
106
-
107
- return sortedData
108
- }
109
-
110
- return {
111
- rows: sortData(rowModel.rows),
112
- flatRows: sortedFlatRows,
113
- rowsById: rowModel.rowsById,
114
- }
115
- }
package/src/utils.tsx DELETED
@@ -1,249 +0,0 @@
1
- import React from 'react'
2
- import {
3
- Getter,
4
- NoInfer,
5
- PropGetterValue,
6
- Renderable,
7
- TableState,
8
- } from './types'
9
-
10
- export type IsAny<T> = 0 extends 1 & T ? true : false
11
- export type PartialKeys<T, K extends keyof T> = Omit<T, K> & Partial<Pick<T, K>>
12
- export type RequiredKeys<T, K extends keyof T> = Omit<T, K> &
13
- Required<Pick<T, K>>
14
- export type Overwrite<T, U> = Omit<T, keyof U> & U
15
-
16
- export type DataUpdateFunction<TInput, TOutput> = (input: TInput) => TOutput
17
-
18
- export type Updater<TInput, TOutput> =
19
- | TOutput
20
- | DataUpdateFunction<TInput, TOutput>
21
-
22
- export function functionalUpdate<TInput, TOutput = TInput>(
23
- updater: Updater<TInput, TOutput>,
24
- input: TInput
25
- ): TOutput {
26
- return typeof updater === 'function'
27
- ? (updater as DataUpdateFunction<TInput, TOutput>)(input)
28
- : updater
29
- }
30
-
31
- export function noop() {
32
- //
33
- }
34
-
35
- export function makeStateUpdater(key: keyof TableState, instance: unknown) {
36
- return (updater: Updater<any, any>) => {
37
- ;(instance as any).setState(<TTableState,>(old: TTableState) => {
38
- return {
39
- ...old,
40
- [key]: functionalUpdate(updater, (old as any)[key]),
41
- }
42
- })
43
- }
44
- }
45
-
46
- // SSR has issues with useLayoutEffect still, so use useEffect during SSR
47
- export const safeUseLayoutEffect =
48
- typeof document !== 'undefined' ? React.useLayoutEffect : React.useEffect
49
-
50
- export function useMountedLayoutEffect(fn: any, deps: any[]) {
51
- const mountedRef = React.useRef(false)
52
-
53
- safeUseLayoutEffect(() => {
54
- if (mountedRef.current) {
55
- fn()
56
- }
57
- mountedRef.current = true
58
- // eslint-disable-next-line
59
- }, deps)
60
- }
61
-
62
- export function useGetLatest<T>(obj: T): () => T {
63
- const ref = React.useRef<T>()
64
- ref.current = obj
65
-
66
- return React.useCallback(() => ref.current!, [])
67
- }
68
-
69
- type AnyFunction = (...args: any) => any
70
-
71
- export function isFunction<T extends AnyFunction>(d: any): d is T {
72
- return d instanceof Function
73
- }
74
-
75
- export function flattenBy<TNode>(
76
- arr: TNode[],
77
- getChildren: (item: TNode) => TNode[]
78
- ) {
79
- const flat: TNode[] = []
80
-
81
- const recurse = (subArr: TNode[]) => {
82
- subArr.forEach(item => {
83
- flat.push(item)
84
- const children = getChildren(item)
85
- if (children?.length) {
86
- recurse(children)
87
- }
88
- })
89
- }
90
-
91
- recurse(arr)
92
-
93
- return flat
94
- }
95
-
96
- type PropGetterImpl = <TBaseProps, TGetter extends Getter<TBaseProps>>(
97
- initial: TBaseProps,
98
- userProps?: TGetter
99
- ) => PropGetterValue<TBaseProps, TGetter>
100
-
101
- // @ts-ignore // Just rely on the type, not the implementation
102
- export const propGetter: PropGetterImpl = (initial, getter) => {
103
- if (isFunction(getter)) {
104
- return getter(initial)
105
- }
106
-
107
- return {
108
- ...initial,
109
- ...(getter ?? {}),
110
- }
111
- }
112
-
113
- export function memo<TDeps extends readonly any[], TResult>(
114
- getDeps: () => [...TDeps],
115
- fn: (...args: NoInfer<[...TDeps]>) => TResult,
116
- key?: string,
117
- debug?: boolean
118
- ): () => TResult {
119
- let deps: any[] = []
120
- let result: TResult | undefined
121
-
122
- return () => {
123
- const newDeps = getDeps()
124
- const newSerializedDeps = newDeps
125
- const oldSerializedDeps = deps
126
-
127
- const depsChanged =
128
- newSerializedDeps.length !== oldSerializedDeps.length ||
129
- newSerializedDeps.some(
130
- (dep: any, index: number) => oldSerializedDeps[index] !== dep
131
- )
132
-
133
- if (depsChanged) {
134
- if (debug) {
135
- console.info(key, {
136
- length: `${oldSerializedDeps.length} -> ${newSerializedDeps.length}`,
137
- ...newSerializedDeps
138
- .map((_, index) => {
139
- if (oldSerializedDeps[index] !== newSerializedDeps[index]) {
140
- return [
141
- index,
142
- oldSerializedDeps[index],
143
- newSerializedDeps[index],
144
- ]
145
- }
146
-
147
- return false
148
- })
149
- .filter(Boolean)
150
- .reduce(
151
- (accu, curr: any) => ({
152
- ...accu,
153
- [curr[0]]: curr.slice(1),
154
- }),
155
- {}
156
- ),
157
- parent,
158
- })
159
- }
160
- result = fn(...newDeps)
161
- deps = newSerializedDeps
162
- }
163
-
164
- return result!
165
- }
166
- }
167
-
168
- // Copied from: https://github.com/jonschlinkert/is-plain-object
169
- export function isPlainObject(o: any): o is Object {
170
- if (!hasObjectPrototype(o)) {
171
- return false
172
- }
173
-
174
- // If has modified constructor
175
- const ctor = o.constructor
176
- if (typeof ctor === 'undefined') {
177
- return true
178
- }
179
-
180
- // If has modified prototype
181
- const prot = ctor.prototype
182
- if (!hasObjectPrototype(prot)) {
183
- return false
184
- }
185
-
186
- // If constructor does not have an Object-specific method
187
- if (!prot.hasOwnProperty('isPrototypeOf')) {
188
- return false
189
- }
190
-
191
- // Most likely a plain Object
192
- return true
193
- }
194
-
195
- function hasObjectPrototype(o: any): boolean {
196
- return Object.prototype.toString.call(o) === '[object Object]'
197
- }
198
-
199
- export type Render = typeof flexRender
200
-
201
- export function flexRender<TProps extends {}>(
202
- Comp: Renderable<TProps>,
203
- props: TProps
204
- ): React.ReactNode {
205
- return !Comp ? null : isReactComponent(Comp) ? <Comp {...props} /> : Comp
206
- }
207
-
208
- function isReactComponent(component: unknown): component is React.FC {
209
- return (
210
- isClassComponent(component) ||
211
- typeof component === 'function' ||
212
- isExoticComponent(component)
213
- )
214
- }
215
-
216
- function isClassComponent(component: any) {
217
- return (
218
- typeof component === 'function' &&
219
- (() => {
220
- const proto = Object.getPrototypeOf(component)
221
- return proto.prototype && proto.prototype.isReactComponent
222
- })()
223
- )
224
- }
225
-
226
- function isExoticComponent(component: any) {
227
- return (
228
- typeof component === 'object' &&
229
- typeof component.$$typeof === 'symbol' &&
230
- ['react.memo', 'react.forward_ref'].includes(component.$$typeof.description)
231
- )
232
- }
233
-
234
- // export function hashString(str: string, seed = 0): string {
235
- // let h1 = 0xdeadbeef ^ seed,
236
- // h2 = 0x41c6ce57 ^ seed
237
- // for (let i = 0, ch; i < str.length; i++) {
238
- // ch = str.charCodeAt(i)
239
- // h1 = Math.imul(h1 ^ ch, 2654435761)
240
- // h2 = Math.imul(h2 ^ ch, 1597334677)
241
- // }
242
- // h1 =
243
- // Math.imul(h1 ^ (h1 >>> 16), 2246822507) ^
244
- // Math.imul(h2 ^ (h2 >>> 13), 3266489909)
245
- // h2 =
246
- // Math.imul(h2 ^ (h2 >>> 16), 2246822507) ^
247
- // Math.imul(h1 ^ (h1 >>> 13), 3266489909)
248
- // return (4294967296 * (2097151 & h2) + (h1 >>> 0)).toString()
249
- // }