@tanstack/table-core 9.0.0-beta.28 → 9.0.0-beta.30

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 (30) hide show
  1. package/dist/features/column-filtering/columnFilteringFeature.utils.cjs +1 -1
  2. package/dist/features/column-filtering/columnFilteringFeature.utils.cjs.map +1 -1
  3. package/dist/features/column-filtering/columnFilteringFeature.utils.js +1 -1
  4. package/dist/features/column-filtering/columnFilteringFeature.utils.js.map +1 -1
  5. package/dist/features/global-filtering/globalFilteringFeature.utils.d.cts +1 -0
  6. package/dist/features/global-filtering/globalFilteringFeature.utils.d.ts +1 -0
  7. package/dist/features/row-sorting/createSortedRowModel.cjs +41 -34
  8. package/dist/features/row-sorting/createSortedRowModel.cjs.map +1 -1
  9. package/dist/features/row-sorting/createSortedRowModel.js +42 -35
  10. package/dist/features/row-sorting/createSortedRowModel.js.map +1 -1
  11. package/dist/fns/aggregationFns.cjs +21 -19
  12. package/dist/fns/aggregationFns.cjs.map +1 -1
  13. package/dist/fns/aggregationFns.js +21 -19
  14. package/dist/fns/aggregationFns.js.map +1 -1
  15. package/dist/fns/filterFns.cjs +59 -14
  16. package/dist/fns/filterFns.cjs.map +1 -1
  17. package/dist/fns/filterFns.d.cts +11 -4
  18. package/dist/fns/filterFns.d.ts +11 -4
  19. package/dist/fns/filterFns.js +59 -14
  20. package/dist/fns/filterFns.js.map +1 -1
  21. package/dist/fns/sortFns.cjs +77 -28
  22. package/dist/fns/sortFns.cjs.map +1 -1
  23. package/dist/fns/sortFns.js +77 -28
  24. package/dist/fns/sortFns.js.map +1 -1
  25. package/package.json +1 -1
  26. package/src/features/column-filtering/columnFilteringFeature.utils.ts +4 -4
  27. package/src/features/row-sorting/createSortedRowModel.ts +65 -55
  28. package/src/fns/aggregationFns.ts +19 -19
  29. package/src/fns/filterFns.ts +96 -32
  30. package/src/fns/sortFns.ts +158 -46
@@ -103,8 +103,8 @@ export const sortFn_datetime = <
103
103
  rowB: Row<TFeatures, TData>,
104
104
  columnId: string,
105
105
  ) => {
106
- const a: number | string = rowA.getValue(columnId)
107
- const b: number | string = rowB.getValue(columnId)
106
+ const a = toDateSortValue(rowA.getValue(columnId))
107
+ const b = toDateSortValue(rowB.getValue(columnId))
108
108
 
109
109
  // Can handle nullish values
110
110
  // Use > and < because == (and ===) doesn't work with
@@ -134,6 +134,10 @@ function compareBasic(a: any, b: any) {
134
134
  return a === b ? 0 : a > b ? 1 : -1
135
135
  }
136
136
 
137
+ function toDateSortValue(value: any) {
138
+ return value instanceof Date ? value.getTime() : value
139
+ }
140
+
137
141
  function toString(a: any) {
138
142
  if (typeof a === 'number') {
139
143
  if (isNaN(a) || a === Infinity || a === -Infinity) {
@@ -151,74 +155,182 @@ function toString(a: any) {
151
155
  // It handles numbers, mixed alphanumeric combinations, and even
152
156
  // null, undefined, and Infinity
153
157
  function compareAlphanumeric(aStr: string, bStr: string) {
154
- const a = aStr.split(reSplitAlphaNumeric)
155
- const b = bStr.split(reSplitAlphaNumeric)
156
-
157
158
  let ai = 0
158
159
  let bi = 0
159
- const aLen = a.length
160
- const bLen = b.length
160
+ const aLen = aStr.length
161
+ const bLen = bStr.length
161
162
 
162
163
  while (ai < aLen && bi < bLen) {
163
- // Skip the empty boundary chunks that .filter(Boolean) used to remove
164
- if (!a[ai]) {
165
- ai++
164
+ const aIsNumeric = isDigit(aStr.charCodeAt(ai))
165
+ const bIsNumeric = isDigit(bStr.charCodeAt(bi))
166
+
167
+ const aEnd = findChunkEnd(aStr, ai, aIsNumeric)
168
+ const bEnd = findChunkEnd(bStr, bi, bIsNumeric)
169
+
170
+ // Both are string chunks
171
+ if (!aIsNumeric && !bIsNumeric) {
172
+ const stringComparison = compareStringChunks(
173
+ aStr,
174
+ ai,
175
+ aEnd,
176
+ bStr,
177
+ bi,
178
+ bEnd,
179
+ )
180
+ if (stringComparison) {
181
+ return stringComparison
182
+ }
183
+ ai = aEnd
184
+ bi = bEnd
166
185
  continue
167
186
  }
168
- if (!b[bi]) {
169
- bi++
170
- continue
187
+
188
+ // One is a string chunk, one is a number chunk — the string sorts first
189
+ if (aIsNumeric !== bIsNumeric) {
190
+ return aIsNumeric ? 1 : -1
171
191
  }
172
192
 
173
- const aa = a[ai++]!
174
- const bb = b[bi++]!
193
+ // Both are numeric chunks
194
+ const numericComparison = compareNumericChunks(
195
+ aStr,
196
+ ai,
197
+ aEnd,
198
+ bStr,
199
+ bi,
200
+ bEnd,
201
+ )
202
+ if (numericComparison) {
203
+ return numericComparison
204
+ }
175
205
 
176
- // Chunks are either all-digit (parseInt always succeeds) or digit-free
177
- // (parseInt is always NaN), so NaN-ness fully classifies each chunk
178
- const an = parseInt(aa, 10)
179
- const bn = parseInt(bb, 10)
206
+ ai = aEnd
207
+ bi = bEnd
208
+ }
180
209
 
181
- const aIsNaN = isNaN(an)
182
- const bIsNaN = isNaN(bn)
210
+ // One side is exhausted — compare the counts of remaining non-empty chunks
211
+ return countRemainingChunks(aStr, ai) - countRemainingChunks(bStr, bi)
212
+ }
183
213
 
184
- // Both are string
185
- if (aIsNaN && bIsNaN) {
186
- if (aa > bb) {
187
- return 1
188
- }
189
- if (bb > aa) {
190
- return -1
191
- }
192
- continue
193
- }
214
+ function isDigit(charCode: number) {
215
+ return charCode >= 48 && charCode <= 57
216
+ }
217
+
218
+ function findChunkEnd(str: string, start: number, isNumeric: boolean) {
219
+ let end = start + 1
220
+ while (end < str.length && isDigit(str.charCodeAt(end)) === isNumeric) {
221
+ end++
222
+ }
223
+ return end
224
+ }
225
+
226
+ function compareStringChunks(
227
+ aStr: string,
228
+ aStart: number,
229
+ aEnd: number,
230
+ bStr: string,
231
+ bStart: number,
232
+ bEnd: number,
233
+ ) {
234
+ const aLength = aEnd - aStart
235
+ const bLength = bEnd - bStart
236
+ const minLength = aLength < bLength ? aLength : bLength
237
+
238
+ for (let i = 0; i < minLength; i++) {
239
+ const aCode = aStr.charCodeAt(aStart + i)
240
+ const bCode = bStr.charCodeAt(bStart + i)
194
241
 
195
- // One is a string, one is a number — the string chunk sorts first
196
- if (aIsNaN || bIsNaN) {
197
- return aIsNaN ? -1 : 1
242
+ if (aCode > bCode) {
243
+ return 1
244
+ }
245
+ if (bCode > aCode) {
246
+ return -1
198
247
  }
248
+ }
249
+
250
+ if (aLength > bLength) {
251
+ return 1
252
+ }
253
+ if (bLength > aLength) {
254
+ return -1
255
+ }
256
+ return 0
257
+ }
258
+
259
+ function compareNumericChunks(
260
+ aStr: string,
261
+ aStart: number,
262
+ aEnd: number,
263
+ bStr: string,
264
+ bStart: number,
265
+ bEnd: number,
266
+ ) {
267
+ let aSignificantStart = aStart
268
+ while (
269
+ aSignificantStart < aEnd &&
270
+ aStr.charCodeAt(aSignificantStart) === 48
271
+ ) {
272
+ aSignificantStart++
273
+ }
274
+
275
+ let bSignificantStart = bStart
276
+ while (
277
+ bSignificantStart < bEnd &&
278
+ bStr.charCodeAt(bSignificantStart) === 48
279
+ ) {
280
+ bSignificantStart++
281
+ }
282
+
283
+ const aSignificantLength = aEnd - aSignificantStart
284
+ const bSignificantLength = bEnd - bSignificantStart
285
+
286
+ if (aSignificantLength === 0 && bSignificantLength === 0) {
287
+ return 0
288
+ }
289
+
290
+ if (aSignificantLength <= 15 && bSignificantLength <= 15) {
291
+ const an = parseSmallInt(aStr, aSignificantStart, aEnd)
292
+ const bn = parseSmallInt(bStr, bSignificantStart, bEnd)
199
293
 
200
- // Both are numbers
201
294
  if (an > bn) {
202
295
  return 1
203
296
  }
204
297
  if (bn > an) {
205
298
  return -1
206
299
  }
300
+ return 0
207
301
  }
208
302
 
209
- // One side is exhausted compare the counts of remaining non-empty chunks
210
- let remaining = 0
211
- for (; ai < aLen; ai++) {
212
- if (a[ai]) {
213
- remaining++
214
- }
303
+ // Preserve parseInt precision-collapse behavior for unusually large chunks.
304
+ const an = parseInt(aStr.slice(aStart, aEnd), 10)
305
+ const bn = parseInt(bStr.slice(bStart, bEnd), 10)
306
+
307
+ if (an > bn) {
308
+ return 1
215
309
  }
216
- for (; bi < bLen; bi++) {
217
- if (b[bi]) {
218
- remaining--
219
- }
310
+ if (bn > an) {
311
+ return -1
312
+ }
313
+ return 0
314
+ }
315
+
316
+ function parseSmallInt(str: string, start: number, end: number) {
317
+ let result = 0
318
+ for (let i = start; i < end; i++) {
319
+ result = result * 10 + str.charCodeAt(i) - 48
320
+ }
321
+ return result
322
+ }
323
+
324
+ function countRemainingChunks(str: string, start: number) {
325
+ let count = 0
326
+ let index = start
327
+
328
+ while (index < str.length) {
329
+ count++
330
+ index = findChunkEnd(str, index, isDigit(str.charCodeAt(index)))
220
331
  }
221
- return remaining
332
+
333
+ return count
222
334
  }
223
335
 
224
336
  // Exports