@tanstack/table-core 9.0.0-beta.46 → 9.0.0-beta.48

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 (212) hide show
  1. package/dist/core/row-models/coreRowModelsFeature.types.d.cts +1 -1
  2. package/dist/core/row-models/coreRowModelsFeature.types.d.ts +1 -1
  3. package/dist/core/row-models/coreRowModelsFeature.utils.cjs +1 -1
  4. package/dist/core/row-models/coreRowModelsFeature.utils.cjs.map +1 -1
  5. package/dist/core/row-models/coreRowModelsFeature.utils.d.cts +1 -1
  6. package/dist/core/row-models/coreRowModelsFeature.utils.d.ts +1 -1
  7. package/dist/core/row-models/coreRowModelsFeature.utils.js +1 -1
  8. package/dist/core/row-models/coreRowModelsFeature.utils.js.map +1 -1
  9. package/dist/features/aggregation/aggregationFeature.cjs +38 -0
  10. package/dist/features/aggregation/aggregationFeature.cjs.map +1 -0
  11. package/dist/features/aggregation/aggregationFeature.d.cts +10 -0
  12. package/dist/features/aggregation/aggregationFeature.d.ts +10 -0
  13. package/dist/features/aggregation/aggregationFeature.js +38 -0
  14. package/dist/features/aggregation/aggregationFeature.js.map +1 -0
  15. package/dist/features/aggregation/aggregationFeature.types.cjs +13 -0
  16. package/dist/features/aggregation/aggregationFeature.types.cjs.map +1 -0
  17. package/dist/features/aggregation/aggregationFeature.types.d.cts +172 -0
  18. package/dist/features/aggregation/aggregationFeature.types.d.ts +172 -0
  19. package/dist/features/aggregation/aggregationFeature.types.js +12 -0
  20. package/dist/features/aggregation/aggregationFeature.types.js.map +1 -0
  21. package/dist/features/aggregation/aggregationFeature.utils.cjs +198 -0
  22. package/dist/features/aggregation/aggregationFeature.utils.cjs.map +1 -0
  23. package/dist/features/aggregation/aggregationFeature.utils.d.cts +33 -0
  24. package/dist/features/aggregation/aggregationFeature.utils.d.ts +33 -0
  25. package/dist/features/aggregation/aggregationFeature.utils.js +192 -0
  26. package/dist/features/aggregation/aggregationFeature.utils.js.map +1 -0
  27. package/dist/features/aggregation/aggregationFns.cjs +240 -0
  28. package/dist/features/aggregation/aggregationFns.cjs.map +1 -0
  29. package/dist/features/aggregation/aggregationFns.d.cts +67 -0
  30. package/dist/features/aggregation/aggregationFns.d.ts +67 -0
  31. package/dist/features/aggregation/aggregationFns.js +229 -0
  32. package/dist/features/aggregation/aggregationFns.js.map +1 -0
  33. package/dist/features/column-filtering/columnFilteringFeature.types.d.cts +43 -3
  34. package/dist/features/column-filtering/columnFilteringFeature.types.d.ts +43 -3
  35. package/dist/features/column-filtering/columnFilteringFeature.utils.cjs +18 -9
  36. package/dist/features/column-filtering/columnFilteringFeature.utils.cjs.map +1 -1
  37. package/dist/features/column-filtering/columnFilteringFeature.utils.d.cts +6 -2
  38. package/dist/features/column-filtering/columnFilteringFeature.utils.d.ts +6 -2
  39. package/dist/features/column-filtering/columnFilteringFeature.utils.js +18 -9
  40. package/dist/features/column-filtering/columnFilteringFeature.utils.js.map +1 -1
  41. package/dist/features/column-filtering/createFilteredRowModel.cjs +7 -2
  42. package/dist/features/column-filtering/createFilteredRowModel.cjs.map +1 -1
  43. package/dist/features/column-filtering/createFilteredRowModel.d.cts +6 -2
  44. package/dist/features/column-filtering/createFilteredRowModel.d.ts +6 -2
  45. package/dist/features/column-filtering/createFilteredRowModel.js +7 -2
  46. package/dist/features/column-filtering/createFilteredRowModel.js.map +1 -1
  47. package/dist/features/column-filtering/filterFns.cjs +399 -0
  48. package/dist/features/column-filtering/filterFns.cjs.map +1 -0
  49. package/dist/features/column-filtering/filterFns.d.cts +210 -0
  50. package/dist/features/column-filtering/filterFns.d.ts +210 -0
  51. package/dist/features/column-filtering/filterFns.js +375 -0
  52. package/dist/features/column-filtering/filterFns.js.map +1 -0
  53. package/dist/features/column-grouping/columnGroupingFeature.cjs +3 -12
  54. package/dist/features/column-grouping/columnGroupingFeature.cjs.map +1 -1
  55. package/dist/features/column-grouping/columnGroupingFeature.d.cts +1 -1
  56. package/dist/features/column-grouping/columnGroupingFeature.d.ts +1 -1
  57. package/dist/features/column-grouping/columnGroupingFeature.js +4 -13
  58. package/dist/features/column-grouping/columnGroupingFeature.js.map +1 -1
  59. package/dist/features/column-grouping/columnGroupingFeature.types.d.cts +6 -49
  60. package/dist/features/column-grouping/columnGroupingFeature.types.d.ts +6 -49
  61. package/dist/features/column-grouping/columnGroupingFeature.utils.cjs +0 -50
  62. package/dist/features/column-grouping/columnGroupingFeature.utils.cjs.map +1 -1
  63. package/dist/features/column-grouping/columnGroupingFeature.utils.d.cts +2 -39
  64. package/dist/features/column-grouping/columnGroupingFeature.utils.d.ts +2 -39
  65. package/dist/features/column-grouping/columnGroupingFeature.utils.js +2 -49
  66. package/dist/features/column-grouping/columnGroupingFeature.utils.js.map +1 -1
  67. package/dist/features/column-grouping/createGroupedRowModel.cjs +23 -13
  68. package/dist/features/column-grouping/createGroupedRowModel.cjs.map +1 -1
  69. package/dist/features/column-grouping/createGroupedRowModel.d.cts +2 -3
  70. package/dist/features/column-grouping/createGroupedRowModel.d.ts +2 -3
  71. package/dist/features/column-grouping/createGroupedRowModel.js +25 -15
  72. package/dist/features/column-grouping/createGroupedRowModel.js.map +1 -1
  73. package/dist/features/global-filtering/globalFilteringFeature.utils.cjs +4 -2
  74. package/dist/features/global-filtering/globalFilteringFeature.utils.cjs.map +1 -1
  75. package/dist/features/global-filtering/globalFilteringFeature.utils.d.cts +2 -6
  76. package/dist/features/global-filtering/globalFilteringFeature.utils.d.ts +2 -6
  77. package/dist/features/global-filtering/globalFilteringFeature.utils.js +4 -2
  78. package/dist/features/global-filtering/globalFilteringFeature.utils.js.map +1 -1
  79. package/dist/features/row-sorting/createSortedRowModel.cjs +6 -2
  80. package/dist/features/row-sorting/createSortedRowModel.cjs.map +1 -1
  81. package/dist/features/row-sorting/createSortedRowModel.d.cts +6 -2
  82. package/dist/features/row-sorting/createSortedRowModel.d.ts +6 -2
  83. package/dist/features/row-sorting/createSortedRowModel.js +6 -2
  84. package/dist/features/row-sorting/createSortedRowModel.js.map +1 -1
  85. package/dist/features/row-sorting/rowSortingFeature.types.d.cts +32 -3
  86. package/dist/features/row-sorting/rowSortingFeature.types.d.ts +32 -3
  87. package/dist/features/row-sorting/rowSortingFeature.utils.cjs +20 -5
  88. package/dist/features/row-sorting/rowSortingFeature.utils.cjs.map +1 -1
  89. package/dist/features/row-sorting/rowSortingFeature.utils.js +20 -5
  90. package/dist/features/row-sorting/rowSortingFeature.utils.js.map +1 -1
  91. package/dist/{fns → features/row-sorting}/sortFns.cjs +69 -22
  92. package/dist/features/row-sorting/sortFns.cjs.map +1 -0
  93. package/dist/features/row-sorting/sortFns.d.cts +98 -0
  94. package/dist/features/row-sorting/sortFns.d.ts +98 -0
  95. package/dist/{fns → features/row-sorting}/sortFns.js +69 -23
  96. package/dist/features/row-sorting/sortFns.js.map +1 -0
  97. package/dist/features/stockFeatures.cjs +2 -0
  98. package/dist/features/stockFeatures.cjs.map +1 -1
  99. package/dist/features/stockFeatures.d.cts +2 -0
  100. package/dist/features/stockFeatures.d.ts +2 -0
  101. package/dist/features/stockFeatures.js +2 -0
  102. package/dist/features/stockFeatures.js.map +1 -1
  103. package/dist/helpers/tableFeatures.cjs +5 -4
  104. package/dist/helpers/tableFeatures.cjs.map +1 -1
  105. package/dist/helpers/tableFeatures.d.cts +5 -4
  106. package/dist/helpers/tableFeatures.d.ts +5 -4
  107. package/dist/helpers/tableFeatures.js +5 -4
  108. package/dist/helpers/tableFeatures.js.map +1 -1
  109. package/dist/index.cjs +18 -3
  110. package/dist/index.d.cts +10 -8
  111. package/dist/index.d.ts +10 -8
  112. package/dist/index.js +6 -4
  113. package/dist/static-functions.cjs +8 -3
  114. package/dist/static-functions.d.cts +3 -2
  115. package/dist/static-functions.d.ts +3 -2
  116. package/dist/static-functions.js +3 -2
  117. package/dist/types/Cell.d.cts +3 -1
  118. package/dist/types/Cell.d.ts +3 -1
  119. package/dist/types/Column.d.cts +4 -2
  120. package/dist/types/Column.d.ts +4 -2
  121. package/dist/types/ColumnDef.d.cts +5 -3
  122. package/dist/types/ColumnDef.d.ts +5 -3
  123. package/dist/types/Row.d.cts +3 -1
  124. package/dist/types/Row.d.ts +3 -1
  125. package/dist/types/RowModel.d.cts +1 -1
  126. package/dist/types/RowModel.d.ts +1 -1
  127. package/dist/types/RowModelFns.d.cts +3 -3
  128. package/dist/types/RowModelFns.d.ts +3 -3
  129. package/dist/types/Table.d.cts +1 -1
  130. package/dist/types/Table.d.ts +1 -1
  131. package/dist/types/TableFeatures.d.cts +19 -11
  132. package/dist/types/TableFeatures.d.ts +19 -11
  133. package/dist/types/TableOptions.d.cts +5 -3
  134. package/dist/types/TableOptions.d.ts +5 -3
  135. package/dist/types/TableState.d.cts +1 -1
  136. package/dist/types/TableState.d.ts +1 -1
  137. package/dist/types/type-utils.d.cts +8 -1
  138. package/dist/types/type-utils.d.ts +8 -1
  139. package/dist/worker/initTableWorker.cjs.map +1 -1
  140. package/dist/worker/initTableWorker.js.map +1 -1
  141. package/package.json +1 -1
  142. package/skills/aggregation/SKILL.md +131 -0
  143. package/skills/api-not-found/SKILL.md +1 -1
  144. package/skills/client-vs-server/SKILL.md +1 -1
  145. package/skills/column-faceting/SKILL.md +11 -5
  146. package/skills/column-filtering/SKILL.md +8 -3
  147. package/skills/column-ordering/SKILL.md +1 -1
  148. package/skills/column-pinning/SKILL.md +1 -1
  149. package/skills/column-resizing/SKILL.md +1 -1
  150. package/skills/column-sizing/SKILL.md +1 -1
  151. package/skills/column-visibility/SKILL.md +1 -1
  152. package/skills/core/SKILL.md +1 -1
  153. package/skills/custom-features/SKILL.md +1 -1
  154. package/skills/expanding/SKILL.md +1 -1
  155. package/skills/global-filtering/SKILL.md +3 -3
  156. package/skills/grouping/SKILL.md +12 -13
  157. package/skills/migrate-v8-to-v9/SKILL.md +21 -8
  158. package/skills/pagination/SKILL.md +1 -1
  159. package/skills/row-pinning/SKILL.md +1 -1
  160. package/skills/row-selection/SKILL.md +1 -1
  161. package/skills/sorting/SKILL.md +9 -3
  162. package/skills/table-features/SKILL.md +19 -13
  163. package/skills/typescript/SKILL.md +1 -1
  164. package/src/core/row-models/coreRowModelsFeature.utils.ts +1 -1
  165. package/src/features/aggregation/aggregationFeature.ts +59 -0
  166. package/src/features/aggregation/aggregationFeature.types.ts +312 -0
  167. package/src/features/aggregation/aggregationFeature.utils.ts +401 -0
  168. package/src/features/aggregation/aggregationFns.ts +336 -0
  169. package/src/features/column-filtering/columnFilteringFeature.types.ts +61 -1
  170. package/src/features/column-filtering/columnFilteringFeature.utils.ts +33 -19
  171. package/src/features/column-filtering/createFilteredRowModel.ts +13 -3
  172. package/src/features/column-filtering/filterFns.ts +533 -0
  173. package/src/features/column-grouping/columnGroupingFeature.ts +1 -20
  174. package/src/features/column-grouping/columnGroupingFeature.types.ts +4 -86
  175. package/src/features/column-grouping/columnGroupingFeature.utils.ts +1 -88
  176. package/src/features/column-grouping/createGroupedRowModel.ts +32 -38
  177. package/src/features/global-filtering/globalFilteringFeature.utils.ts +9 -1
  178. package/src/features/row-sorting/createSortedRowModel.ts +6 -2
  179. package/src/features/row-sorting/rowSortingFeature.types.ts +54 -2
  180. package/src/features/row-sorting/rowSortingFeature.utils.ts +46 -14
  181. package/src/{fns → features/row-sorting}/sortFns.ts +95 -81
  182. package/src/features/stockFeatures.ts +3 -0
  183. package/src/helpers/tableFeatures.ts +5 -4
  184. package/src/index.ts +7 -8
  185. package/src/static-functions.ts +1 -0
  186. package/src/types/Cell.ts +2 -0
  187. package/src/types/Column.ts +3 -1
  188. package/src/types/ColumnDef.ts +6 -3
  189. package/src/types/Row.ts +2 -0
  190. package/src/types/RowModelFns.ts +3 -3
  191. package/src/types/TableFeatures.ts +19 -11
  192. package/src/types/TableOptions.ts +5 -1
  193. package/src/types/type-utils.ts +8 -0
  194. package/src/worker/initTableWorker.ts +1 -1
  195. package/dist/fns/aggregationFns.cjs +0 -163
  196. package/dist/fns/aggregationFns.cjs.map +0 -1
  197. package/dist/fns/aggregationFns.d.cts +0 -85
  198. package/dist/fns/aggregationFns.d.ts +0 -85
  199. package/dist/fns/aggregationFns.js +0 -153
  200. package/dist/fns/aggregationFns.js.map +0 -1
  201. package/dist/fns/filterFns.cjs +0 -242
  202. package/dist/fns/filterFns.cjs.map +0 -1
  203. package/dist/fns/filterFns.d.cts +0 -178
  204. package/dist/fns/filterFns.d.ts +0 -178
  205. package/dist/fns/filterFns.js +0 -226
  206. package/dist/fns/filterFns.js.map +0 -1
  207. package/dist/fns/sortFns.cjs.map +0 -1
  208. package/dist/fns/sortFns.d.cts +0 -65
  209. package/dist/fns/sortFns.d.ts +0 -65
  210. package/dist/fns/sortFns.js.map +0 -1
  211. package/src/fns/aggregationFns.ts +0 -245
  212. package/src/fns/filterFns.ts +0 -455
@@ -1,4 +1,4 @@
1
- import { cloneState, hasOwn, isFunction } from '../../utils'
1
+ import { cloneState, hasOwn } from '../../utils'
2
2
  import type { Column_Internal } from '../../types/Column'
3
3
  import type { CellData, RowData, Updater } from '../../types/type-utils'
4
4
  import type { TableFeatures } from '../../types/TableFeatures'
@@ -6,7 +6,6 @@ import type { Table_Internal } from '../../types/Table'
6
6
  import type { Row } from '../../types/Row'
7
7
  import type { Cell } from '../../types/Cell'
8
8
  import type {
9
- AggregationFn,
10
9
  GroupingState,
11
10
  Row_ColumnGrouping,
12
11
  } from './columnGroupingFeature.types'
@@ -135,69 +134,6 @@ export function column_getToggleGroupingHandler<
135
134
  }
136
135
  }
137
136
 
138
- /**
139
- * Chooses a built-in aggregation function from the first core row value.
140
- *
141
- * Numeric columns default to `sum`, date-like values default to `extent`, and
142
- * other value types leave aggregation unspecified.
143
- *
144
- * @example
145
- * ```ts
146
- * const aggregationFn = column_getAutoAggregationFn(column)
147
- * ```
148
- */
149
- export function column_getAutoAggregationFn<
150
- TFeatures extends TableFeatures,
151
- TData extends RowData,
152
- TValue extends CellData = CellData,
153
- >(column: Column_Internal<TFeatures, TData, TValue>) {
154
- const aggregationFns:
155
- | Record<string, AggregationFn<TFeatures, TData>>
156
- | undefined = column.table._rowModelFns.aggregationFns
157
-
158
- const firstRow = column.table.getCoreRowModel().flatRows[0]
159
-
160
- const value = firstRow?.getValue(column.id)
161
-
162
- if (typeof value === 'number') {
163
- return aggregationFns?.sum
164
- }
165
-
166
- if (Object.prototype.toString.call(value) === '[object Date]') {
167
- return aggregationFns?.extent
168
- }
169
-
170
- return undefined
171
- }
172
-
173
- /**
174
- * Resolves the aggregation function configured for a column.
175
- *
176
- * Function-valued `columnDef.aggregationFn` is returned directly, `'auto'`
177
- * delegates to `column_getAutoAggregationFn`, and string values are looked up in
178
- * the table's aggregation function registry.
179
- *
180
- * @example
181
- * ```ts
182
- * const aggregationFn = column_getAggregationFn(column)
183
- * ```
184
- */
185
- export function column_getAggregationFn<
186
- TFeatures extends TableFeatures,
187
- TData extends RowData,
188
- TValue extends CellData = CellData,
189
- >(column: Column_Internal<TFeatures, TData, TValue>) {
190
- const aggregationFns:
191
- | Record<string, AggregationFn<TFeatures, TData>>
192
- | undefined = column.table._rowModelFns.aggregationFns
193
-
194
- return isFunction(column.columnDef.aggregationFn)
195
- ? column.columnDef.aggregationFn
196
- : column.columnDef.aggregationFn === 'auto'
197
- ? column_getAutoAggregationFn(column)
198
- : aggregationFns?.[column.columnDef.aggregationFn as string]
199
- }
200
-
201
137
  /**
202
138
  * Routes a grouping updater through the table's grouping change handler.
203
139
  *
@@ -333,26 +269,3 @@ export function cell_getIsPlaceholder<
333
269
  >(cell: Cell<TFeatures, TData, TValue>) {
334
270
  return !cell_getIsGrouped(cell) && column_getIsGrouped(cell.column)
335
271
  }
336
-
337
- /**
338
- * Checks whether this cell should render an aggregated value.
339
- *
340
- * Aggregated cells are non-placeholder, non-grouped cells on rows that have
341
- * subRows.
342
- *
343
- * @example
344
- * ```ts
345
- * const isAggregated = cell_getIsAggregated(cell)
346
- * ```
347
- */
348
- export function cell_getIsAggregated<
349
- TFeatures extends TableFeatures,
350
- TData extends RowData,
351
- TValue extends CellData = CellData,
352
- >(cell: Cell<TFeatures, TData, TValue>) {
353
- return (
354
- !cell_getIsGrouped(cell) &&
355
- !cell_getIsPlaceholder(cell) &&
356
- !!cell.row.subRows.length
357
- )
358
- }
@@ -1,13 +1,13 @@
1
- import { flattenBy, hasOwn, makeObjectMap, tableMemo } from '../../utils'
1
+ import { hasOwn, makeObjectMap, tableMemo } from '../../utils'
2
2
  import { constructRow } from '../../core/rows/constructRow'
3
3
  import { table_getColumn } from '../../core/columns/coreColumnsFeature.utils'
4
4
  import { table_autoResetExpanded } from '../row-expanding/rowExpandingFeature.utils'
5
5
  import { table_autoResetPageIndex } from '../row-pagination/rowPaginationFeature.utils'
6
6
  import {
7
- column_getAggregationFn,
8
- row_getGroupingValue,
9
- } from './columnGroupingFeature.utils'
10
- import type { Column } from '../../types/Column'
7
+ aggregateColumnValue,
8
+ normalizeAggregationRows,
9
+ } from '../aggregation/aggregationFeature.utils'
10
+ import { row_getGroupingValue } from './columnGroupingFeature.utils'
11
11
  import type { Row_ColumnGrouping } from './columnGroupingFeature.types'
12
12
  import type { TableFeatures } from '../../types/TableFeatures'
13
13
  import type { RowModel } from '../../core/row-models/coreRowModelsFeature.types'
@@ -20,9 +20,8 @@ import type { RowData } from '../../types/type-utils'
20
20
  *
21
21
  * The factory reads the relevant table state atoms and options, then returns a row model function used by the table row-model pipeline.
22
22
  *
23
- * Register aggregation functions with the `aggregationFns` slot on the
24
- * `features` option:
25
- * `tableFeatures({ columnGroupingFeature, groupedRowModel: createGroupedRowModel(), aggregationFns })`.
23
+ * When aggregationFeature is also registered, grouped rows use its shared
24
+ * executor for non-group values. Grouping remains useful without aggregation.
26
25
  */
27
26
  export function createGroupedRowModel<
28
27
  TFeatures extends TableFeatures,
@@ -37,6 +36,7 @@ export function createGroupedRowModel<
37
36
  memoDeps: () => [
38
37
  table.atoms.grouping?.get(),
39
38
  table.getPreGroupedRowModel(),
39
+ table.options.columns,
40
40
  ],
41
41
  fn: () => _createGroupedRowModel(table),
42
42
  onAfterUpdate: () => {
@@ -118,10 +118,7 @@ function _createGroupedRowModel<
118
118
  subRow.parentId = id
119
119
  })
120
120
 
121
- // Flatten the leaf rows of the rows in this group
122
- const leafRows = depth
123
- ? flattenBy(groupedRows, (row) => row.subRows)
124
- : groupedRows
121
+ const leafRows = normalizeAggregationRows(groupedRows)
125
122
 
126
123
  const row = constructRow(
127
124
  table,
@@ -139,8 +136,12 @@ function _createGroupedRowModel<
139
136
  subRows,
140
137
  leafRows,
141
138
  getValue: (colId: string) => {
142
- // Don't aggregate columns that are in the grouping
143
- if (existingGrouping.includes(colId)) {
139
+ const groupingIndex = existingGrouping.indexOf(colId)
140
+
141
+ // The active grouping column and ancestor grouping columns expose
142
+ // their inherited grouping values. Columns grouped at deeper
143
+ // levels are still eligible for aggregation here.
144
+ if (groupingIndex !== -1 && groupingIndex <= depth) {
144
145
  if (hasOwn(row._valuesCache, colId)) {
145
146
  return row._valuesCache[colId]
146
147
  }
@@ -153,32 +154,25 @@ function _createGroupedRowModel<
153
154
  return row._valuesCache[colId]
154
155
  }
155
156
 
156
- if (
157
- row._groupingValuesCache &&
158
- hasOwn(row._groupingValuesCache, colId)
159
- ) {
160
- return row._groupingValuesCache[colId]
161
- }
162
-
163
- // Aggregate the values
164
- const column = table.getColumn(colId)
165
- const aggregateFn = column_getAggregationFn(
166
- column as Column<TFeatures, TData, unknown>,
167
- )
168
-
169
- if (!row._groupingValuesCache) {
170
- row._groupingValuesCache = makeObjectMap()
157
+ const aggregationCache = (row as any)._aggregationValuesCache as
158
+ | Record<string, unknown>
159
+ | undefined
160
+ if (aggregationCache && hasOwn(aggregationCache, colId)) {
161
+ return aggregationCache[colId]
171
162
  }
172
163
 
173
- if (aggregateFn) {
174
- row._groupingValuesCache[colId] = aggregateFn(
175
- colId,
176
- leafRows,
177
- groupedRows,
178
- )
179
-
180
- return row._groupingValuesCache[colId]
181
- }
164
+ const column = table.getColumn(colId) as any
165
+ if (typeof column.getAggregationFns !== 'function') return undefined
166
+
167
+ const cache = ((row as any)._aggregationValuesCache ??=
168
+ makeObjectMap())
169
+ cache[colId] = aggregateColumnValue({
170
+ childRows: subRows,
171
+ column,
172
+ groupingRow: row,
173
+ rows: leafRows,
174
+ })
175
+ return cache[colId]
182
176
  },
183
177
  })
184
178
 
@@ -1,4 +1,4 @@
1
- import { filterFn_includesString } from '../../fns/filterFns'
1
+ import { filterFn_includesString } from '../column-filtering/filterFns'
2
2
  import { cloneState, isFunction } from '../../utils'
3
3
  import type { Column_Internal } from '../../types/Column'
4
4
  import type { FilterFn } from '../column-filtering/columnFilteringFeature.types'
@@ -74,6 +74,14 @@ export function table_getGlobalFilterFn<
74
74
  ? table_getGlobalAutoFilterFn()
75
75
  : filterFns?.[globalFilterFn as string]
76
76
 
77
+ if (
78
+ process.env.NODE_ENV === 'development' &&
79
+ !filterFn &&
80
+ globalFilterFn != null
81
+ ) {
82
+ console.warn(`globalFilterFn '${String(globalFilterFn)}' is not registered`)
83
+ }
84
+
77
85
  return filterFn
78
86
  }
79
87
 
@@ -14,8 +14,12 @@ import type { RowData } from '../../types/type-utils'
14
14
  *
15
15
  * The factory reads the relevant table state atoms and options, then returns a row model function used by the table row-model pipeline.
16
16
  *
17
- * Register sorting functions with the `sortFns` slot on the `features` option:
18
- * `tableFeatures({ rowSortingFeature, sortedRowModel: createSortedRowModel(), sortFns })`.
17
+ * Register the sorting functions you use with the `sortFns` slot on the
18
+ * `features` option:
19
+ * `tableFeatures({ rowSortingFeature, sortedRowModel: createSortedRowModel(), sortFns: { alphanumeric: sortFn_alphanumeric } })`.
20
+ * Importing individual `sortFn_*` functions keeps unused built-ins out of
21
+ * your bundle; sorting functions passed directly to the `sortFn` column
22
+ * option need no registration at all.
19
23
  */
20
24
  export function createSortedRowModel<
21
25
  TFeatures extends TableFeatures,
@@ -1,6 +1,11 @@
1
1
  import type { RowModel } from '../../core/row-models/coreRowModelsFeature.types'
2
- import type { BuiltInSortFn } from '../../fns/sortFns'
3
- import type { OnChangeFn, RowData, Updater } from '../../types/type-utils'
2
+ import type { BuiltInSortFn } from './sortFns'
3
+ import type {
4
+ OnChangeFn,
5
+ RowData,
6
+ TransformDataValueFn,
7
+ Updater,
8
+ } from '../../types/type-utils'
4
9
  import type { IsAny, TableFeatures } from '../../types/TableFeatures'
5
10
  import type { Row } from '../../types/Row'
6
11
 
@@ -35,6 +40,53 @@ export interface SortFn<
35
40
  rowB: Row<TFeatures, TData>,
36
41
  columnId: string,
37
42
  ): number
43
+ /**
44
+ * Normalizes each row's value before the two sides are compared. Only
45
+ * honored by sorting functions built with `constructSortFn` (including all
46
+ * built-in sorting functions).
47
+ */
48
+ resolveDataValue?: TransformDataValueFn
49
+ }
50
+
51
+ /**
52
+ * The definition object accepted by `constructSortFn`.
53
+ *
54
+ * `sort` is a value-level comparator: it receives both rows' (resolved) data
55
+ * values instead of the whole rows, so normalization concerns stay in
56
+ * `resolveDataValue`.
57
+ */
58
+ export interface SortFnDef<
59
+ in out TFeatures extends TableFeatures,
60
+ in out TData extends RowData,
61
+ > {
62
+ sort: (
63
+ dataValueA: any,
64
+ dataValueB: any,
65
+ rowA: Row<TFeatures, TData>,
66
+ rowB: Row<TFeatures, TData>,
67
+ columnId: string,
68
+ ) => number
69
+ resolveDataValue?: TransformDataValueFn
70
+ }
71
+
72
+ /**
73
+ * The shape returned by `constructSortFn`: a `SortFn` with its definition
74
+ * attached, so variants can be built by spreading it into another
75
+ * `constructSortFn` call.
76
+ *
77
+ * The call signature is generic so a created sorting function can be used
78
+ * with any table's rows, regardless of the feature set it was defined
79
+ * against.
80
+ */
81
+ export interface CreatedSortFn<
82
+ in out TFeatures extends TableFeatures,
83
+ in out TData extends RowData,
84
+ > extends SortFnDef<TFeatures, TData> {
85
+ <TRowFeatures extends TableFeatures, TRowData extends RowData>(
86
+ rowA: Row<TRowFeatures, TRowData>,
87
+ rowB: Row<TRowFeatures, TRowData>,
88
+ columnId: string,
89
+ ): number
38
90
  }
39
91
 
40
92
  export type CustomSortFns<
@@ -1,5 +1,5 @@
1
- import { reSplitAlphaNumeric, sortFn_basic } from '../../fns/sortFns'
2
1
  import { cloneState, isFunction } from '../../utils'
2
+ import { reSplitAlphaNumeric, sortFn_basic } from './sortFns'
3
3
  import type { CellData, RowData, Updater } from '../../types/type-utils'
4
4
  import type { TableFeatures } from '../../types/TableFeatures'
5
5
  import type { Table_Internal } from '../../types/Table'
@@ -91,30 +91,50 @@ export function column_getAutoSortFn<
91
91
 
92
92
  const firstRows = column.table.getFilteredRowModel().flatRows.slice(0, 10)
93
93
 
94
+ let sortFnName: string | undefined
94
95
  let isString = false
95
96
 
96
97
  for (let i = 0; i < firstRows.length; i++) {
97
98
  const value = firstRows[i]!.getValue(column.id)
98
99
 
99
100
  if (Object.prototype.toString.call(value) === '[object Date]') {
100
- if (sortFns?.datetime) {
101
- return sortFns.datetime
102
- }
101
+ sortFnName = 'datetime'
102
+ break
103
103
  }
104
104
 
105
105
  if (typeof value === 'string') {
106
106
  isString = true
107
107
 
108
108
  if (value.split(reSplitAlphaNumeric).length > 1) {
109
- if (sortFns?.alphanumeric) {
110
- return sortFns.alphanumeric
111
- }
109
+ sortFnName = 'alphanumeric'
110
+ break
112
111
  }
113
112
  }
114
113
  }
115
114
 
116
- if (isString) {
117
- return sortFns?.text ?? sortFn_basic
115
+ if (!sortFnName && isString) {
116
+ sortFnName = 'text'
117
+ }
118
+
119
+ if (sortFnName) {
120
+ let sortFn = sortFns?.[sortFnName]
121
+
122
+ if (!sortFn) {
123
+ if (process.env.NODE_ENV === 'development') {
124
+ console.warn(
125
+ `sortFn '${sortFnName}' (auto) for column '${column.id}' is not registered`,
126
+ )
127
+ }
128
+
129
+ // String columns degrade to a registered text sort before basic
130
+ if (sortFnName === 'alphanumeric') {
131
+ sortFn = sortFns?.text
132
+ }
133
+ }
134
+
135
+ if (sortFn) {
136
+ return sortFn
137
+ }
118
138
  }
119
139
 
120
140
  return sortFn_basic
@@ -167,11 +187,23 @@ export function column_getSortFn<
167
187
  const sortFns: Record<string, SortFn<TFeatures, TData>> | undefined =
168
188
  column.table._rowModelFns.sortFns
169
189
 
170
- return isFunction(column.columnDef.sortFn)
171
- ? column.columnDef.sortFn
172
- : column.columnDef.sortFn === 'auto'
173
- ? column_getAutoSortFn(column)
174
- : (sortFns?.[column.columnDef.sortFn as string] ?? sortFn_basic)
190
+ if (isFunction(column.columnDef.sortFn)) {
191
+ return column.columnDef.sortFn
192
+ }
193
+
194
+ if (column.columnDef.sortFn === 'auto') {
195
+ return column_getAutoSortFn(column)
196
+ }
197
+
198
+ const sortFn = sortFns?.[column.columnDef.sortFn as string]
199
+
200
+ if (process.env.NODE_ENV === 'development' && !sortFn) {
201
+ console.warn(
202
+ `sortFn '${String(column.columnDef.sortFn)}' for column '${column.id}' is not registered`,
203
+ )
204
+ }
205
+
206
+ return sortFn ?? sortFn_basic
175
207
  }
176
208
 
177
209
  /**
@@ -1,6 +1,7 @@
1
- import type { RowData } from '../types/type-utils'
2
- import type { TableFeatures } from '../types/TableFeatures'
3
- import type { Row } from '../types/Row'
1
+ import type { CreatedSortFn, SortFnDef } from './rowSortingFeature.types'
2
+ import type { RowData } from '../../types/type-utils'
3
+ import type { TableFeatures } from '../../types/TableFeatures'
4
+ import type { Row } from '../../types/Row'
4
5
 
5
6
  /**
6
7
  * Regular expression used to split mixed text and numeric chunks.
@@ -11,122 +12,127 @@ import type { Row } from '../types/Row'
11
12
  export const reSplitAlphaNumeric = /([0-9]+)/gm
12
13
 
13
14
  /**
14
- * Sorts rows with the built-in alphanumeric strategy.
15
+ * Builds a `SortFn` from a value-level comparator plus an optional
16
+ * `resolveDataValue` normalizer.
15
17
  *
16
- * This comparator returns ascending-order results; descending order is applied by the sorting row model.
18
+ * The `sort` comparator receives both rows' data values, each already passed
19
+ * through `resolveDataValue` when one is defined. Keeping normalization in the
20
+ * resolver means a variant of an existing sorting function only has to swap
21
+ * the resolver, not re-implement the comparison.
22
+ *
23
+ * The definition is attached to the returned function, so a variant can be
24
+ * created by spreading a built-in sorting function and overriding what
25
+ * differs:
26
+ *
27
+ * ```ts
28
+ * const stripDiacritics = (value: string) =>
29
+ * value.normalize('NFD').replace(/\p{Diacritic}/gu, '')
30
+ *
31
+ * const alphanumericIgnoreDiacritics = constructSortFn({
32
+ * ...sortFn_alphanumeric,
33
+ * resolveDataValue: (value) =>
34
+ * stripDiacritics(sortFn_alphanumeric.resolveDataValue!(value)),
35
+ * })
36
+ * ```
17
37
  */
18
- export const sortFn_alphanumeric = <
19
- TFeatures extends TableFeatures,
20
- TData extends RowData,
21
- >(
22
- rowA: Row<TFeatures, TData>,
23
- rowB: Row<TFeatures, TData>,
24
- columnId: string,
25
- ) => {
26
- return compareAlphanumeric(
27
- toString(rowA.getValue(columnId)).toLowerCase(),
28
- toString(rowB.getValue(columnId)).toLowerCase(),
38
+ export function constructSortFn<
39
+ TFeatures extends TableFeatures = any,
40
+ TData extends RowData = any,
41
+ >(def: SortFnDef<TFeatures, TData>): CreatedSortFn<TFeatures, TData> {
42
+ const sortFn: CreatedSortFn<TFeatures, TData> = Object.assign(
43
+ <TRowFeatures extends TableFeatures, TRowData extends RowData>(
44
+ rowA: Row<TRowFeatures, TRowData>,
45
+ rowB: Row<TRowFeatures, TRowData>,
46
+ columnId: string,
47
+ ): number => {
48
+ let dataValueA = rowA.getValue(columnId)
49
+ let dataValueB = rowB.getValue(columnId)
50
+ const resolveDataValue = sortFn.resolveDataValue
51
+ if (resolveDataValue) {
52
+ dataValueA = resolveDataValue(dataValueA)
53
+ dataValueB = resolveDataValue(dataValueB)
54
+ }
55
+ // The def's comparator is typed against the factory's TFeatures/TData;
56
+ // the caller's row generics are erased at this boundary.
57
+ return sortFn.sort(
58
+ dataValueA,
59
+ dataValueB,
60
+ rowA as any,
61
+ rowB as any,
62
+ columnId,
63
+ )
64
+ },
65
+ def,
29
66
  )
67
+ return sortFn
30
68
  }
31
69
 
70
+ /**
71
+ * Sorts rows with the built-in alphanumeric strategy.
72
+ *
73
+ * This comparator returns ascending-order results; descending order is applied by the sorting row model.
74
+ */
75
+ export const sortFn_alphanumeric = constructSortFn({
76
+ resolveDataValue: (dataValue) => toString(dataValue).toLowerCase(),
77
+ sort: (dataValueA, dataValueB) => compareAlphanumeric(dataValueA, dataValueB),
78
+ })
79
+
32
80
  /**
33
81
  * Sorts rows with the built-in alphanumeric case sensitive strategy.
34
82
  *
35
83
  * This comparator returns ascending-order results; descending order is applied by the sorting row model.
36
84
  */
37
- export const sortFn_alphanumericCaseSensitive = <
38
- TFeatures extends TableFeatures,
39
- TData extends RowData,
40
- >(
41
- rowA: Row<TFeatures, TData>,
42
- rowB: Row<TFeatures, TData>,
43
- columnId: string,
44
- ) => {
45
- return compareAlphanumeric(
46
- toString(rowA.getValue(columnId)),
47
- toString(rowB.getValue(columnId)),
48
- )
49
- }
85
+ export const sortFn_alphanumericCaseSensitive = constructSortFn({
86
+ resolveDataValue: (dataValue) => toString(dataValue),
87
+ sort: (dataValueA, dataValueB) => compareAlphanumeric(dataValueA, dataValueB),
88
+ })
50
89
 
51
- // The text filter is more basic (less numeric support)
90
+ // The text sort is more basic (less numeric support)
52
91
  // but is much faster
53
92
  /**
54
93
  * Sorts rows with the built-in text strategy.
55
94
  *
56
95
  * This comparator returns ascending-order results; descending order is applied by the sorting row model.
57
96
  */
58
- export const sortFn_text = <
59
- TFeatures extends TableFeatures,
60
- TData extends RowData,
61
- >(
62
- rowA: Row<TFeatures, TData>,
63
- rowB: Row<TFeatures, TData>,
64
- columnId: string,
65
- ) => {
66
- return compareBasic(
67
- toString(rowA.getValue(columnId)).toLowerCase(),
68
- toString(rowB.getValue(columnId)).toLowerCase(),
69
- )
70
- }
97
+ export const sortFn_text = constructSortFn({
98
+ resolveDataValue: (dataValue) => toString(dataValue).toLowerCase(),
99
+ sort: (dataValueA, dataValueB) => compareBasic(dataValueA, dataValueB),
100
+ })
71
101
 
72
- // The text filter is more basic (less numeric support)
102
+ // The text sort is more basic (less numeric support)
73
103
  // but is much faster
74
104
  /**
75
105
  * Sorts rows with the built-in text case sensitive strategy.
76
106
  *
77
107
  * This comparator returns ascending-order results; descending order is applied by the sorting row model.
78
108
  */
79
- export const sortFn_textCaseSensitive = <
80
- TFeatures extends TableFeatures,
81
- TData extends RowData,
82
- >(
83
- rowA: Row<TFeatures, TData>,
84
- rowB: Row<TFeatures, TData>,
85
- columnId: string,
86
- ) => {
87
- return compareBasic(
88
- toString(rowA.getValue(columnId)),
89
- toString(rowB.getValue(columnId)),
90
- )
91
- }
109
+ export const sortFn_textCaseSensitive = constructSortFn({
110
+ resolveDataValue: (dataValue) => toString(dataValue),
111
+ sort: (dataValueA, dataValueB) => compareBasic(dataValueA, dataValueB),
112
+ })
92
113
 
93
114
  /**
94
115
  * Sorts rows with the built-in datetime strategy.
95
116
  *
96
117
  * This comparator returns ascending-order results; descending order is applied by the sorting row model.
97
118
  */
98
- export const sortFn_datetime = <
99
- TFeatures extends TableFeatures,
100
- TData extends RowData,
101
- >(
102
- rowA: Row<TFeatures, TData>,
103
- rowB: Row<TFeatures, TData>,
104
- columnId: string,
105
- ) => {
106
- const a = toDateSortValue(rowA.getValue(columnId))
107
- const b = toDateSortValue(rowB.getValue(columnId))
108
-
119
+ export const sortFn_datetime = constructSortFn({
120
+ resolveDataValue: (dataValue) => toDateSortValue(dataValue),
109
121
  // Can handle nullish values
110
122
  // Use > and < because == (and ===) doesn't work with
111
123
  // Date objects (would require calling getTime()).
112
- return a > b ? 1 : a < b ? -1 : 0
113
- }
124
+ sort: (dataValueA, dataValueB) =>
125
+ dataValueA > dataValueB ? 1 : dataValueA < dataValueB ? -1 : 0,
126
+ })
114
127
 
115
128
  /**
116
129
  * Sorts rows with the built-in basic strategy.
117
130
  *
118
131
  * This comparator returns ascending-order results; descending order is applied by the sorting row model.
119
132
  */
120
- export const sortFn_basic = <
121
- TFeatures extends TableFeatures,
122
- TData extends RowData,
123
- >(
124
- rowA: Row<TFeatures, TData>,
125
- rowB: Row<TFeatures, TData>,
126
- columnId: string,
127
- ) => {
128
- return compareBasic(rowA.getValue(columnId), rowB.getValue(columnId))
129
- }
133
+ export const sortFn_basic = constructSortFn({
134
+ sort: (dataValueA, dataValueB) => compareBasic(dataValueA, dataValueB),
135
+ })
130
136
 
131
137
  // Utils
132
138
 
@@ -338,7 +344,15 @@ function countRemainingChunks(str: string, start: number) {
338
344
  /**
339
345
  * The built-in sorting function registry.
340
346
  *
341
- * Pass this object to sorted row model creation or extend it with custom sorting functions.
347
+ * Registering this full object opts out of tree-shaking: every built-in
348
+ * sorting function ends up in your bundle. Prefer importing the `sortFn_*`
349
+ * functions you actually use and registering just those in the `sortFns`
350
+ * slot, or passing them directly to the `sortFn` column option.
351
+ *
352
+ * @deprecated Import individual `sortFn_*` functions instead for a smaller
353
+ * bundle. This export still works and is not going away in v9, but built-in
354
+ * name resolution (including `sortFn: 'auto'`) only finds functions you
355
+ * register yourself.
342
356
  */
343
357
  export const sortFns = {
344
358
  alphanumeric: sortFn_alphanumeric,
@@ -1,4 +1,5 @@
1
1
  import { columnFacetingFeature } from './column-faceting/columnFacetingFeature'
2
+ import { aggregationFeature } from './aggregation/aggregationFeature'
2
3
  import { columnFilteringFeature } from './column-filtering/columnFilteringFeature'
3
4
  import { columnGroupingFeature } from './column-grouping/columnGroupingFeature'
4
5
  import { columnOrderingFeature } from './column-ordering/columnOrderingFeature'
@@ -14,6 +15,7 @@ import { rowSelectionFeature } from './row-selection/rowSelectionFeature'
14
15
  import { rowSortingFeature } from './row-sorting/rowSortingFeature'
15
16
 
16
17
  export interface StockFeatures {
18
+ aggregationFeature: typeof aggregationFeature
17
19
  columnFacetingFeature: typeof columnFacetingFeature
18
20
  columnFilteringFeature: typeof columnFilteringFeature
19
21
  columnGroupingFeature: typeof columnGroupingFeature
@@ -36,6 +38,7 @@ export interface StockFeatures {
36
38
  * Use individual feature exports for tree-shaking, or this aggregate when a table should include every built-in feature.
37
39
  */
38
40
  export const stockFeatures: StockFeatures = {
41
+ aggregationFeature,
39
42
  columnFacetingFeature,
40
43
  columnFilteringFeature,
41
44
  columnGroupingFeature,