@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.
- package/dist/core/row-models/coreRowModelsFeature.types.d.cts +1 -1
- package/dist/core/row-models/coreRowModelsFeature.types.d.ts +1 -1
- package/dist/core/row-models/coreRowModelsFeature.utils.cjs +1 -1
- package/dist/core/row-models/coreRowModelsFeature.utils.cjs.map +1 -1
- package/dist/core/row-models/coreRowModelsFeature.utils.d.cts +1 -1
- package/dist/core/row-models/coreRowModelsFeature.utils.d.ts +1 -1
- package/dist/core/row-models/coreRowModelsFeature.utils.js +1 -1
- package/dist/core/row-models/coreRowModelsFeature.utils.js.map +1 -1
- package/dist/features/aggregation/aggregationFeature.cjs +38 -0
- package/dist/features/aggregation/aggregationFeature.cjs.map +1 -0
- package/dist/features/aggregation/aggregationFeature.d.cts +10 -0
- package/dist/features/aggregation/aggregationFeature.d.ts +10 -0
- package/dist/features/aggregation/aggregationFeature.js +38 -0
- package/dist/features/aggregation/aggregationFeature.js.map +1 -0
- package/dist/features/aggregation/aggregationFeature.types.cjs +13 -0
- package/dist/features/aggregation/aggregationFeature.types.cjs.map +1 -0
- package/dist/features/aggregation/aggregationFeature.types.d.cts +172 -0
- package/dist/features/aggregation/aggregationFeature.types.d.ts +172 -0
- package/dist/features/aggregation/aggregationFeature.types.js +12 -0
- package/dist/features/aggregation/aggregationFeature.types.js.map +1 -0
- package/dist/features/aggregation/aggregationFeature.utils.cjs +198 -0
- package/dist/features/aggregation/aggregationFeature.utils.cjs.map +1 -0
- package/dist/features/aggregation/aggregationFeature.utils.d.cts +33 -0
- package/dist/features/aggregation/aggregationFeature.utils.d.ts +33 -0
- package/dist/features/aggregation/aggregationFeature.utils.js +192 -0
- package/dist/features/aggregation/aggregationFeature.utils.js.map +1 -0
- package/dist/features/aggregation/aggregationFns.cjs +240 -0
- package/dist/features/aggregation/aggregationFns.cjs.map +1 -0
- package/dist/features/aggregation/aggregationFns.d.cts +67 -0
- package/dist/features/aggregation/aggregationFns.d.ts +67 -0
- package/dist/features/aggregation/aggregationFns.js +229 -0
- package/dist/features/aggregation/aggregationFns.js.map +1 -0
- package/dist/features/column-filtering/columnFilteringFeature.types.d.cts +43 -3
- package/dist/features/column-filtering/columnFilteringFeature.types.d.ts +43 -3
- package/dist/features/column-filtering/columnFilteringFeature.utils.cjs +18 -9
- package/dist/features/column-filtering/columnFilteringFeature.utils.cjs.map +1 -1
- package/dist/features/column-filtering/columnFilteringFeature.utils.d.cts +6 -2
- package/dist/features/column-filtering/columnFilteringFeature.utils.d.ts +6 -2
- package/dist/features/column-filtering/columnFilteringFeature.utils.js +18 -9
- package/dist/features/column-filtering/columnFilteringFeature.utils.js.map +1 -1
- package/dist/features/column-filtering/createFilteredRowModel.cjs +7 -2
- package/dist/features/column-filtering/createFilteredRowModel.cjs.map +1 -1
- package/dist/features/column-filtering/createFilteredRowModel.d.cts +6 -2
- package/dist/features/column-filtering/createFilteredRowModel.d.ts +6 -2
- package/dist/features/column-filtering/createFilteredRowModel.js +7 -2
- package/dist/features/column-filtering/createFilteredRowModel.js.map +1 -1
- package/dist/features/column-filtering/filterFns.cjs +399 -0
- package/dist/features/column-filtering/filterFns.cjs.map +1 -0
- package/dist/features/column-filtering/filterFns.d.cts +210 -0
- package/dist/features/column-filtering/filterFns.d.ts +210 -0
- package/dist/features/column-filtering/filterFns.js +375 -0
- package/dist/features/column-filtering/filterFns.js.map +1 -0
- package/dist/features/column-grouping/columnGroupingFeature.cjs +3 -12
- package/dist/features/column-grouping/columnGroupingFeature.cjs.map +1 -1
- package/dist/features/column-grouping/columnGroupingFeature.d.cts +1 -1
- package/dist/features/column-grouping/columnGroupingFeature.d.ts +1 -1
- package/dist/features/column-grouping/columnGroupingFeature.js +4 -13
- package/dist/features/column-grouping/columnGroupingFeature.js.map +1 -1
- package/dist/features/column-grouping/columnGroupingFeature.types.d.cts +6 -49
- package/dist/features/column-grouping/columnGroupingFeature.types.d.ts +6 -49
- package/dist/features/column-grouping/columnGroupingFeature.utils.cjs +0 -50
- package/dist/features/column-grouping/columnGroupingFeature.utils.cjs.map +1 -1
- package/dist/features/column-grouping/columnGroupingFeature.utils.d.cts +2 -39
- package/dist/features/column-grouping/columnGroupingFeature.utils.d.ts +2 -39
- package/dist/features/column-grouping/columnGroupingFeature.utils.js +2 -49
- package/dist/features/column-grouping/columnGroupingFeature.utils.js.map +1 -1
- package/dist/features/column-grouping/createGroupedRowModel.cjs +23 -13
- package/dist/features/column-grouping/createGroupedRowModel.cjs.map +1 -1
- package/dist/features/column-grouping/createGroupedRowModel.d.cts +2 -3
- package/dist/features/column-grouping/createGroupedRowModel.d.ts +2 -3
- package/dist/features/column-grouping/createGroupedRowModel.js +25 -15
- package/dist/features/column-grouping/createGroupedRowModel.js.map +1 -1
- package/dist/features/global-filtering/globalFilteringFeature.utils.cjs +4 -2
- package/dist/features/global-filtering/globalFilteringFeature.utils.cjs.map +1 -1
- package/dist/features/global-filtering/globalFilteringFeature.utils.d.cts +2 -6
- package/dist/features/global-filtering/globalFilteringFeature.utils.d.ts +2 -6
- package/dist/features/global-filtering/globalFilteringFeature.utils.js +4 -2
- package/dist/features/global-filtering/globalFilteringFeature.utils.js.map +1 -1
- package/dist/features/row-sorting/createSortedRowModel.cjs +6 -2
- package/dist/features/row-sorting/createSortedRowModel.cjs.map +1 -1
- package/dist/features/row-sorting/createSortedRowModel.d.cts +6 -2
- package/dist/features/row-sorting/createSortedRowModel.d.ts +6 -2
- package/dist/features/row-sorting/createSortedRowModel.js +6 -2
- package/dist/features/row-sorting/createSortedRowModel.js.map +1 -1
- package/dist/features/row-sorting/rowSortingFeature.types.d.cts +32 -3
- package/dist/features/row-sorting/rowSortingFeature.types.d.ts +32 -3
- package/dist/features/row-sorting/rowSortingFeature.utils.cjs +20 -5
- package/dist/features/row-sorting/rowSortingFeature.utils.cjs.map +1 -1
- package/dist/features/row-sorting/rowSortingFeature.utils.js +20 -5
- package/dist/features/row-sorting/rowSortingFeature.utils.js.map +1 -1
- package/dist/{fns → features/row-sorting}/sortFns.cjs +69 -22
- package/dist/features/row-sorting/sortFns.cjs.map +1 -0
- package/dist/features/row-sorting/sortFns.d.cts +98 -0
- package/dist/features/row-sorting/sortFns.d.ts +98 -0
- package/dist/{fns → features/row-sorting}/sortFns.js +69 -23
- package/dist/features/row-sorting/sortFns.js.map +1 -0
- package/dist/features/stockFeatures.cjs +2 -0
- package/dist/features/stockFeatures.cjs.map +1 -1
- package/dist/features/stockFeatures.d.cts +2 -0
- package/dist/features/stockFeatures.d.ts +2 -0
- package/dist/features/stockFeatures.js +2 -0
- package/dist/features/stockFeatures.js.map +1 -1
- package/dist/helpers/tableFeatures.cjs +5 -4
- package/dist/helpers/tableFeatures.cjs.map +1 -1
- package/dist/helpers/tableFeatures.d.cts +5 -4
- package/dist/helpers/tableFeatures.d.ts +5 -4
- package/dist/helpers/tableFeatures.js +5 -4
- package/dist/helpers/tableFeatures.js.map +1 -1
- package/dist/index.cjs +18 -3
- package/dist/index.d.cts +10 -8
- package/dist/index.d.ts +10 -8
- package/dist/index.js +6 -4
- package/dist/static-functions.cjs +8 -3
- package/dist/static-functions.d.cts +3 -2
- package/dist/static-functions.d.ts +3 -2
- package/dist/static-functions.js +3 -2
- package/dist/types/Cell.d.cts +3 -1
- package/dist/types/Cell.d.ts +3 -1
- package/dist/types/Column.d.cts +4 -2
- package/dist/types/Column.d.ts +4 -2
- package/dist/types/ColumnDef.d.cts +5 -3
- package/dist/types/ColumnDef.d.ts +5 -3
- package/dist/types/Row.d.cts +3 -1
- package/dist/types/Row.d.ts +3 -1
- package/dist/types/RowModel.d.cts +1 -1
- package/dist/types/RowModel.d.ts +1 -1
- package/dist/types/RowModelFns.d.cts +3 -3
- package/dist/types/RowModelFns.d.ts +3 -3
- package/dist/types/Table.d.cts +1 -1
- package/dist/types/Table.d.ts +1 -1
- package/dist/types/TableFeatures.d.cts +19 -11
- package/dist/types/TableFeatures.d.ts +19 -11
- package/dist/types/TableOptions.d.cts +5 -3
- package/dist/types/TableOptions.d.ts +5 -3
- package/dist/types/TableState.d.cts +1 -1
- package/dist/types/TableState.d.ts +1 -1
- package/dist/types/type-utils.d.cts +8 -1
- package/dist/types/type-utils.d.ts +8 -1
- package/dist/worker/initTableWorker.cjs.map +1 -1
- package/dist/worker/initTableWorker.js.map +1 -1
- package/package.json +1 -1
- package/skills/aggregation/SKILL.md +131 -0
- package/skills/api-not-found/SKILL.md +1 -1
- package/skills/client-vs-server/SKILL.md +1 -1
- package/skills/column-faceting/SKILL.md +11 -5
- package/skills/column-filtering/SKILL.md +8 -3
- package/skills/column-ordering/SKILL.md +1 -1
- package/skills/column-pinning/SKILL.md +1 -1
- package/skills/column-resizing/SKILL.md +1 -1
- package/skills/column-sizing/SKILL.md +1 -1
- package/skills/column-visibility/SKILL.md +1 -1
- package/skills/core/SKILL.md +1 -1
- package/skills/custom-features/SKILL.md +1 -1
- package/skills/expanding/SKILL.md +1 -1
- package/skills/global-filtering/SKILL.md +3 -3
- package/skills/grouping/SKILL.md +12 -13
- package/skills/migrate-v8-to-v9/SKILL.md +21 -8
- package/skills/pagination/SKILL.md +1 -1
- package/skills/row-pinning/SKILL.md +1 -1
- package/skills/row-selection/SKILL.md +1 -1
- package/skills/sorting/SKILL.md +9 -3
- package/skills/table-features/SKILL.md +19 -13
- package/skills/typescript/SKILL.md +1 -1
- package/src/core/row-models/coreRowModelsFeature.utils.ts +1 -1
- package/src/features/aggregation/aggregationFeature.ts +59 -0
- package/src/features/aggregation/aggregationFeature.types.ts +312 -0
- package/src/features/aggregation/aggregationFeature.utils.ts +401 -0
- package/src/features/aggregation/aggregationFns.ts +336 -0
- package/src/features/column-filtering/columnFilteringFeature.types.ts +61 -1
- package/src/features/column-filtering/columnFilteringFeature.utils.ts +33 -19
- package/src/features/column-filtering/createFilteredRowModel.ts +13 -3
- package/src/features/column-filtering/filterFns.ts +533 -0
- package/src/features/column-grouping/columnGroupingFeature.ts +1 -20
- package/src/features/column-grouping/columnGroupingFeature.types.ts +4 -86
- package/src/features/column-grouping/columnGroupingFeature.utils.ts +1 -88
- package/src/features/column-grouping/createGroupedRowModel.ts +32 -38
- package/src/features/global-filtering/globalFilteringFeature.utils.ts +9 -1
- package/src/features/row-sorting/createSortedRowModel.ts +6 -2
- package/src/features/row-sorting/rowSortingFeature.types.ts +54 -2
- package/src/features/row-sorting/rowSortingFeature.utils.ts +46 -14
- package/src/{fns → features/row-sorting}/sortFns.ts +95 -81
- package/src/features/stockFeatures.ts +3 -0
- package/src/helpers/tableFeatures.ts +5 -4
- package/src/index.ts +7 -8
- package/src/static-functions.ts +1 -0
- package/src/types/Cell.ts +2 -0
- package/src/types/Column.ts +3 -1
- package/src/types/ColumnDef.ts +6 -3
- package/src/types/Row.ts +2 -0
- package/src/types/RowModelFns.ts +3 -3
- package/src/types/TableFeatures.ts +19 -11
- package/src/types/TableOptions.ts +5 -1
- package/src/types/type-utils.ts +8 -0
- package/src/worker/initTableWorker.ts +1 -1
- package/dist/fns/aggregationFns.cjs +0 -163
- package/dist/fns/aggregationFns.cjs.map +0 -1
- package/dist/fns/aggregationFns.d.cts +0 -85
- package/dist/fns/aggregationFns.d.ts +0 -85
- package/dist/fns/aggregationFns.js +0 -153
- package/dist/fns/aggregationFns.js.map +0 -1
- package/dist/fns/filterFns.cjs +0 -242
- package/dist/fns/filterFns.cjs.map +0 -1
- package/dist/fns/filterFns.d.cts +0 -178
- package/dist/fns/filterFns.d.ts +0 -178
- package/dist/fns/filterFns.js +0 -226
- package/dist/fns/filterFns.js.map +0 -1
- package/dist/fns/sortFns.cjs.map +0 -1
- package/dist/fns/sortFns.d.cts +0 -65
- package/dist/fns/sortFns.d.ts +0 -65
- package/dist/fns/sortFns.js.map +0 -1
- package/src/fns/aggregationFns.ts +0 -245
- package/src/fns/filterFns.ts +0 -455
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
const require_utils = require('../../utils.cjs');
|
|
2
|
-
const require_sortFns = require('
|
|
2
|
+
const require_sortFns = require('./sortFns.cjs');
|
|
3
3
|
|
|
4
4
|
//#region src/features/row-sorting/rowSortingFeature.utils.ts
|
|
5
5
|
/**
|
|
@@ -60,20 +60,31 @@ function table_resetSorting(table, defaultState) {
|
|
|
60
60
|
function column_getAutoSortFn(column) {
|
|
61
61
|
const sortFns = column.table._rowModelFns.sortFns;
|
|
62
62
|
const firstRows = column.table.getFilteredRowModel().flatRows.slice(0, 10);
|
|
63
|
+
let sortFnName;
|
|
63
64
|
let isString = false;
|
|
64
65
|
for (let i = 0; i < firstRows.length; i++) {
|
|
65
66
|
const value = firstRows[i].getValue(column.id);
|
|
66
67
|
if (Object.prototype.toString.call(value) === "[object Date]") {
|
|
67
|
-
|
|
68
|
+
sortFnName = "datetime";
|
|
69
|
+
break;
|
|
68
70
|
}
|
|
69
71
|
if (typeof value === "string") {
|
|
70
72
|
isString = true;
|
|
71
73
|
if (value.split(require_sortFns.reSplitAlphaNumeric).length > 1) {
|
|
72
|
-
|
|
74
|
+
sortFnName = "alphanumeric";
|
|
75
|
+
break;
|
|
73
76
|
}
|
|
74
77
|
}
|
|
75
78
|
}
|
|
76
|
-
if (isString)
|
|
79
|
+
if (!sortFnName && isString) sortFnName = "text";
|
|
80
|
+
if (sortFnName) {
|
|
81
|
+
let sortFn = sortFns?.[sortFnName];
|
|
82
|
+
if (!sortFn) {
|
|
83
|
+
if (process.env.NODE_ENV === "development") console.warn(`sortFn '${sortFnName}' (auto) for column '${column.id}' is not registered`);
|
|
84
|
+
if (sortFnName === "alphanumeric") sortFn = sortFns?.text;
|
|
85
|
+
}
|
|
86
|
+
if (sortFn) return sortFn;
|
|
87
|
+
}
|
|
77
88
|
return require_sortFns.sortFn_basic;
|
|
78
89
|
}
|
|
79
90
|
/**
|
|
@@ -106,7 +117,11 @@ function column_getAutoSortDir(column) {
|
|
|
106
117
|
*/
|
|
107
118
|
function column_getSortFn(column) {
|
|
108
119
|
const sortFns = column.table._rowModelFns.sortFns;
|
|
109
|
-
|
|
120
|
+
if (require_utils.isFunction(column.columnDef.sortFn)) return column.columnDef.sortFn;
|
|
121
|
+
if (column.columnDef.sortFn === "auto") return column_getAutoSortFn(column);
|
|
122
|
+
const sortFn = sortFns?.[column.columnDef.sortFn];
|
|
123
|
+
if (process.env.NODE_ENV === "development" && !sortFn) console.warn(`sortFn '${String(column.columnDef.sortFn)}' for column '${column.id}' is not registered`);
|
|
124
|
+
return sortFn ?? require_sortFns.sortFn_basic;
|
|
110
125
|
}
|
|
111
126
|
/**
|
|
112
127
|
* Applies the next sorting state for this column.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"rowSortingFeature.utils.cjs","names":["cloneState","reSplitAlphaNumeric","sortFn_basic","isFunction"],"sources":["../../../src/features/row-sorting/rowSortingFeature.utils.ts"],"sourcesContent":["import { reSplitAlphaNumeric, sortFn_basic } from '../../fns/sortFns'\nimport { cloneState, isFunction } from '../../utils'\nimport type { CellData, RowData, Updater } from '../../types/type-utils'\nimport type { TableFeatures } from '../../types/TableFeatures'\nimport type { Table_Internal } from '../../types/Table'\nimport type { Column_Internal } from '../../types/Column'\nimport type {\n SortDirection,\n SortFn,\n SortingState,\n} from './rowSortingFeature.types'\n\n// State Utils\n\n/**\n * Creates the default sorting state.\n *\n * The feature default is an empty array, meaning no columns are sorted. Reset\n * APIs use this value when `defaultState` is `true`.\n *\n * @example\n * ```ts\n * const sorting = getDefaultSortingState()\n * ```\n */\nexport function getDefaultSortingState(): SortingState {\n return []\n}\n\n/**\n * Routes a sorting updater through the table's sorting change handler.\n *\n * The updater may be a next `SortingState` array or a function of the previous\n * sorting state, matching the instance `table.setSorting` behavior.\n *\n * @example\n * ```ts\n * table_setSorting(table, (old) => [...old, { id: 'age', desc: true }])\n * ```\n */\nexport function table_setSorting<\n TFeatures extends TableFeatures,\n TData extends RowData,\n>(table: Table_Internal<TFeatures, TData>, updater: Updater<SortingState>) {\n table.options.onSortingChange?.(updater)\n}\n\n/**\n * Resets `sorting` to the configured initial state or feature default.\n *\n * With no argument, the reset clones `table.initialState.sorting` when it\n * exists. Passing `true` ignores initial state and resets to `[]`.\n *\n * @example\n * ```ts\n * table_resetSorting(table)\n * table_resetSorting(table, true)\n * ```\n */\nexport function table_resetSorting<\n TFeatures extends TableFeatures,\n TData extends RowData,\n>(table: Table_Internal<TFeatures, TData>, defaultState?: boolean) {\n table_setSorting(\n table,\n defaultState ? [] : cloneState(table.initialState.sorting ?? []),\n )\n}\n\n// Column Utils\n\n/**\n * Chooses a built-in sorting function from sampled filtered row values.\n *\n * Date-like values use `datetime`, mixed text/numeric strings use\n * `alphanumeric`, plain strings use `text`, and unknown values fall back to\n * `basic`.\n *\n * @example\n * ```ts\n * const sortFn = column_getAutoSortFn(column)\n * ```\n */\nexport function column_getAutoSortFn<\n TFeatures extends TableFeatures,\n TData extends RowData,\n TValue extends CellData = CellData,\n>(column: Column_Internal<TFeatures, TData, TValue>): SortFn<TFeatures, TData> {\n const sortFns: Record<string, SortFn<TFeatures, TData>> | undefined =\n column.table._rowModelFns.sortFns\n\n const firstRows = column.table.getFilteredRowModel().flatRows.slice(0, 10)\n\n let isString = false\n\n for (let i = 0; i < firstRows.length; i++) {\n const value = firstRows[i]!.getValue(column.id)\n\n if (Object.prototype.toString.call(value) === '[object Date]') {\n if (sortFns?.datetime) {\n return sortFns.datetime\n }\n }\n\n if (typeof value === 'string') {\n isString = true\n\n if (value.split(reSplitAlphaNumeric).length > 1) {\n if (sortFns?.alphanumeric) {\n return sortFns.alphanumeric\n }\n }\n }\n }\n\n if (isString) {\n return sortFns?.text ?? sortFn_basic\n }\n\n return sortFn_basic\n}\n\n/**\n * Chooses the default first sort direction from the first filtered row value.\n *\n * String columns start ascending so alphabetical order is natural; other value\n * types start descending.\n *\n * @example\n * ```ts\n * const direction = column_getAutoSortDir(column)\n * ```\n */\nexport function column_getAutoSortDir<\n TFeatures extends TableFeatures,\n TData extends RowData,\n TValue extends CellData = CellData,\n>(column: Column_Internal<TFeatures, TData, TValue>) {\n const firstRow = column.table.getFilteredRowModel().flatRows[0]\n\n const value = firstRow ? firstRow.getValue(column.id) : undefined\n\n if (typeof value === 'string') {\n return 'asc'\n }\n\n return 'desc'\n}\n\n/**\n * Resolves the sorting function configured for a column.\n *\n * Function-valued `columnDef.sortFn` is returned directly, `'auto'` delegates\n * to `column_getAutoSortFn`, and string values are looked up in the table's\n * sorting function registry before falling back to `basic`.\n *\n * @example\n * ```ts\n * const sortFn = column_getSortFn(column)\n * ```\n */\nexport function column_getSortFn<\n TFeatures extends TableFeatures,\n TData extends RowData,\n TValue extends CellData = CellData,\n>(column: Column_Internal<TFeatures, TData, TValue>): SortFn<TFeatures, TData> {\n const sortFns: Record<string, SortFn<TFeatures, TData>> | undefined =\n column.table._rowModelFns.sortFns\n\n return isFunction(column.columnDef.sortFn)\n ? column.columnDef.sortFn\n : column.columnDef.sortFn === 'auto'\n ? column_getAutoSortFn(column)\n : (sortFns?.[column.columnDef.sortFn as string] ?? sortFn_basic)\n}\n\n/**\n * Applies the next sorting state for this column.\n *\n * The toggle can add, replace, flip, or remove this column's sort entry. Multi\n * sorting respects `enableMultiSort`, `maxMultiSortColCount`, and the `multi`\n * argument.\n *\n * @example\n * ```ts\n * column_toggleSorting(column, undefined, true)\n * ```\n */\nexport function column_toggleSorting<\n TFeatures extends TableFeatures,\n TData extends RowData,\n TValue extends CellData = CellData,\n>(\n column: Column_Internal<TFeatures, TData, TValue>,\n desc?: boolean,\n multi?: boolean,\n) {\n // this needs to be outside of table.setSorting to be in sync with rerender\n const nextSortingOrder = column_getNextSortingOrder(column)\n const hasManualValue = typeof desc !== 'undefined'\n\n table_setSorting(column.table, (old) => {\n // Find any existing sorting for this column\n const existingIndex = old.findIndex((d) => d.id === column.id)\n const existingSorting =\n existingIndex === -1 ? undefined : old[existingIndex]\n\n let newSorting: SortingState = []\n\n // What should we do with this sort action?\n let sortAction: 'add' | 'remove' | 'toggle' | 'replace'\n const nextDesc = hasManualValue ? desc : nextSortingOrder === 'desc'\n\n // Multi-mode\n if (old.length && column_getCanMultiSort(column) && multi) {\n if (existingSorting) {\n sortAction = 'toggle'\n } else {\n sortAction = 'add'\n }\n } else {\n // Normal mode\n if (old.length && existingIndex !== old.length - 1) {\n sortAction = 'replace'\n } else if (existingSorting) {\n sortAction = 'toggle'\n } else {\n sortAction = 'replace'\n }\n }\n\n // Handle toggle states that will remove the sorting\n if (sortAction === 'toggle') {\n // If we are \"actually\" toggling (not a manual set value), should we remove the sorting?\n if (!hasManualValue) {\n // Is our intention to remove?\n if (!nextSortingOrder) {\n sortAction = 'remove'\n }\n }\n }\n\n if (sortAction === 'add') {\n newSorting = [\n ...old,\n {\n id: column.id,\n desc: nextDesc,\n },\n ]\n // Take latest n columns\n newSorting.splice(\n 0,\n newSorting.length -\n (column.table.options.maxMultiSortColCount ??\n Number.MAX_SAFE_INTEGER),\n )\n } else if (sortAction === 'toggle') {\n // This flips (or sets) the\n newSorting = old.map((d) => {\n if (d.id === column.id) {\n return {\n ...d,\n desc: nextDesc,\n }\n }\n return d\n })\n } else if (sortAction === 'remove') {\n newSorting = old.filter((d) => d.id !== column.id)\n } else {\n newSorting = [\n {\n id: column.id,\n desc: nextDesc,\n },\n ]\n }\n\n return newSorting\n })\n}\n\n/**\n * Resolves the first direction used when this column begins sorting.\n *\n * Column-level `sortDescFirst` wins, then table-level `sortDescFirst`, then the\n * auto direction inferred from sampled values.\n *\n * @example\n * ```ts\n * const firstDirection = column_getFirstSortDir(column)\n * ```\n */\nexport function column_getFirstSortDir<\n TFeatures extends TableFeatures,\n TData extends RowData,\n TValue extends CellData = CellData,\n>(column: Column_Internal<TFeatures, TData, TValue>) {\n const sortDescFirst =\n column.columnDef.sortDescFirst ??\n column.table.options.sortDescFirst ??\n column_getAutoSortDir(column) === 'desc'\n return sortDescFirst ? 'desc' : 'asc'\n}\n\n/**\n * Resolves the next sort order for this column's toggle cycle.\n *\n * The cycle starts with the first sort direction, flips between `asc` and\n * `desc`, and can return `false` when sorting removal is enabled.\n *\n * @example\n * ```ts\n * const nextOrder = column_getNextSortingOrder(column)\n * ```\n */\nexport function column_getNextSortingOrder<\n TFeatures extends TableFeatures,\n TData extends RowData,\n TValue extends CellData = CellData,\n>(column: Column_Internal<TFeatures, TData, TValue>, multi?: boolean) {\n const firstSortDirection = column_getFirstSortDir(column)\n const isSorted = column_getIsSorted(column)\n\n if (!isSorted) {\n return firstSortDirection\n }\n\n if (\n isSorted !== firstSortDirection &&\n (column.table.options.enableSortingRemoval ?? true) && // If enableSortRemove, enable in general\n (multi ? (column.table.options.enableMultiRemove ?? true) : true) // If multi, don't allow if enableMultiRemove))\n ) {\n return false\n }\n return isSorted === 'desc' ? 'asc' : 'desc'\n}\n\n/**\n * Checks whether this accessor column can participate in sorting.\n *\n * The column must have an accessor and sorting must be enabled by both the\n * column definition and table options.\n *\n * @example\n * ```ts\n * const canSort = column_getCanSort(column)\n * ```\n */\nexport function column_getCanSort<\n TFeatures extends TableFeatures,\n TData extends RowData,\n TValue extends CellData = CellData,\n>(column: Column_Internal<TFeatures, TData, TValue>) {\n return (\n (column.columnDef.enableSorting ?? true) &&\n (column.table.options.enableSorting ?? true) &&\n !!column.accessorFn\n )\n}\n\n/**\n * Checks whether this column can be added to a multi-sort state.\n *\n * Column-level `enableMultiSort` wins over table-level `enableMultiSort`; if\n * neither is set, accessor columns can multi-sort by default.\n *\n * @example\n * ```ts\n * const canMultiSort = column_getCanMultiSort(column)\n * ```\n */\nexport function column_getCanMultiSort<\n TFeatures extends TableFeatures,\n TData extends RowData,\n TValue extends CellData = CellData,\n>(column: Column_Internal<TFeatures, TData, TValue>): boolean {\n return (\n column.columnDef.enableMultiSort ??\n column.table.options.enableMultiSort ??\n !!column.accessorFn\n )\n}\n\n/**\n * Reads this column's current sort direction.\n *\n * The result is `false` when the column is not sorted, otherwise `'asc'` or\n * `'desc'` based on the column's entry in `state.sorting`.\n *\n * @example\n * ```ts\n * const direction = column_getIsSorted(column)\n * ```\n */\nexport function column_getIsSorted<\n TFeatures extends TableFeatures,\n TData extends RowData,\n TValue extends CellData = CellData,\n>(column: Column_Internal<TFeatures, TData, TValue>): false | SortDirection {\n const columnSort = column.table.atoms.sorting\n ?.get()\n ?.find((d) => d.id === column.id)\n return !columnSort ? false : columnSort.desc ? 'desc' : 'asc'\n}\n\n/**\n * Finds this column's position in the ordered `state.sorting` array.\n *\n * The result is `-1` when the column is not sorted.\n *\n * @example\n * ```ts\n * const index = column_getSortIndex(column)\n * ```\n */\nexport function column_getSortIndex<\n TFeatures extends TableFeatures,\n TData extends RowData,\n TValue extends CellData = CellData,\n>(column: Column_Internal<TFeatures, TData, TValue>): number {\n return (\n column.table.atoms.sorting?.get()?.findIndex((d) => d.id === column.id) ??\n -1\n )\n}\n\n/**\n * Removes this column from the sorting state.\n *\n * Other sorted columns are preserved, including their relative order.\n *\n * @example\n * ```ts\n * column_clearSorting(column)\n * ```\n */\nexport function column_clearSorting<\n TFeatures extends TableFeatures,\n TData extends RowData,\n TValue extends CellData = CellData,\n>(column: Column_Internal<TFeatures, TData, TValue>) {\n // clear sorting for just 1 column\n table_setSorting(column.table, (old) =>\n old.length ? old.filter((d) => d.id !== column.id) : [],\n )\n}\n\n/**\n * Creates a header event handler that toggles this column's sorting.\n *\n * The handler ignores events when the column cannot sort, persists React-style\n * synthetic events when present, and asks `options.isMultiSortEvent` whether\n * the event should add to a multi-sort.\n *\n * @example\n * ```ts\n * const onClick = column_getToggleSortingHandler(column)\n * ```\n */\nexport function column_getToggleSortingHandler<\n TFeatures extends TableFeatures,\n TData extends RowData,\n TValue extends CellData = CellData,\n>(column: Column_Internal<TFeatures, TData, TValue>) {\n const canSort = column_getCanSort(column)\n\n return (e: unknown) => {\n if (!canSort) return\n ;(e as any).persist?.()\n column_toggleSorting(\n column,\n\n undefined,\n column_getCanMultiSort(column)\n ? column.table.options.isMultiSortEvent?.(e)\n : false,\n )\n }\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"rowSortingFeature.utils.cjs","names":["cloneState","reSplitAlphaNumeric","sortFn_basic","isFunction"],"sources":["../../../src/features/row-sorting/rowSortingFeature.utils.ts"],"sourcesContent":["import { cloneState, isFunction } from '../../utils'\nimport { reSplitAlphaNumeric, sortFn_basic } from './sortFns'\nimport type { CellData, RowData, Updater } from '../../types/type-utils'\nimport type { TableFeatures } from '../../types/TableFeatures'\nimport type { Table_Internal } from '../../types/Table'\nimport type { Column_Internal } from '../../types/Column'\nimport type {\n SortDirection,\n SortFn,\n SortingState,\n} from './rowSortingFeature.types'\n\n// State Utils\n\n/**\n * Creates the default sorting state.\n *\n * The feature default is an empty array, meaning no columns are sorted. Reset\n * APIs use this value when `defaultState` is `true`.\n *\n * @example\n * ```ts\n * const sorting = getDefaultSortingState()\n * ```\n */\nexport function getDefaultSortingState(): SortingState {\n return []\n}\n\n/**\n * Routes a sorting updater through the table's sorting change handler.\n *\n * The updater may be a next `SortingState` array or a function of the previous\n * sorting state, matching the instance `table.setSorting` behavior.\n *\n * @example\n * ```ts\n * table_setSorting(table, (old) => [...old, { id: 'age', desc: true }])\n * ```\n */\nexport function table_setSorting<\n TFeatures extends TableFeatures,\n TData extends RowData,\n>(table: Table_Internal<TFeatures, TData>, updater: Updater<SortingState>) {\n table.options.onSortingChange?.(updater)\n}\n\n/**\n * Resets `sorting` to the configured initial state or feature default.\n *\n * With no argument, the reset clones `table.initialState.sorting` when it\n * exists. Passing `true` ignores initial state and resets to `[]`.\n *\n * @example\n * ```ts\n * table_resetSorting(table)\n * table_resetSorting(table, true)\n * ```\n */\nexport function table_resetSorting<\n TFeatures extends TableFeatures,\n TData extends RowData,\n>(table: Table_Internal<TFeatures, TData>, defaultState?: boolean) {\n table_setSorting(\n table,\n defaultState ? [] : cloneState(table.initialState.sorting ?? []),\n )\n}\n\n// Column Utils\n\n/**\n * Chooses a built-in sorting function from sampled filtered row values.\n *\n * Date-like values use `datetime`, mixed text/numeric strings use\n * `alphanumeric`, plain strings use `text`, and unknown values fall back to\n * `basic`.\n *\n * @example\n * ```ts\n * const sortFn = column_getAutoSortFn(column)\n * ```\n */\nexport function column_getAutoSortFn<\n TFeatures extends TableFeatures,\n TData extends RowData,\n TValue extends CellData = CellData,\n>(column: Column_Internal<TFeatures, TData, TValue>): SortFn<TFeatures, TData> {\n const sortFns: Record<string, SortFn<TFeatures, TData>> | undefined =\n column.table._rowModelFns.sortFns\n\n const firstRows = column.table.getFilteredRowModel().flatRows.slice(0, 10)\n\n let sortFnName: string | undefined\n let isString = false\n\n for (let i = 0; i < firstRows.length; i++) {\n const value = firstRows[i]!.getValue(column.id)\n\n if (Object.prototype.toString.call(value) === '[object Date]') {\n sortFnName = 'datetime'\n break\n }\n\n if (typeof value === 'string') {\n isString = true\n\n if (value.split(reSplitAlphaNumeric).length > 1) {\n sortFnName = 'alphanumeric'\n break\n }\n }\n }\n\n if (!sortFnName && isString) {\n sortFnName = 'text'\n }\n\n if (sortFnName) {\n let sortFn = sortFns?.[sortFnName]\n\n if (!sortFn) {\n if (process.env.NODE_ENV === 'development') {\n console.warn(\n `sortFn '${sortFnName}' (auto) for column '${column.id}' is not registered`,\n )\n }\n\n // String columns degrade to a registered text sort before basic\n if (sortFnName === 'alphanumeric') {\n sortFn = sortFns?.text\n }\n }\n\n if (sortFn) {\n return sortFn\n }\n }\n\n return sortFn_basic\n}\n\n/**\n * Chooses the default first sort direction from the first filtered row value.\n *\n * String columns start ascending so alphabetical order is natural; other value\n * types start descending.\n *\n * @example\n * ```ts\n * const direction = column_getAutoSortDir(column)\n * ```\n */\nexport function column_getAutoSortDir<\n TFeatures extends TableFeatures,\n TData extends RowData,\n TValue extends CellData = CellData,\n>(column: Column_Internal<TFeatures, TData, TValue>) {\n const firstRow = column.table.getFilteredRowModel().flatRows[0]\n\n const value = firstRow ? firstRow.getValue(column.id) : undefined\n\n if (typeof value === 'string') {\n return 'asc'\n }\n\n return 'desc'\n}\n\n/**\n * Resolves the sorting function configured for a column.\n *\n * Function-valued `columnDef.sortFn` is returned directly, `'auto'` delegates\n * to `column_getAutoSortFn`, and string values are looked up in the table's\n * sorting function registry before falling back to `basic`.\n *\n * @example\n * ```ts\n * const sortFn = column_getSortFn(column)\n * ```\n */\nexport function column_getSortFn<\n TFeatures extends TableFeatures,\n TData extends RowData,\n TValue extends CellData = CellData,\n>(column: Column_Internal<TFeatures, TData, TValue>): SortFn<TFeatures, TData> {\n const sortFns: Record<string, SortFn<TFeatures, TData>> | undefined =\n column.table._rowModelFns.sortFns\n\n if (isFunction(column.columnDef.sortFn)) {\n return column.columnDef.sortFn\n }\n\n if (column.columnDef.sortFn === 'auto') {\n return column_getAutoSortFn(column)\n }\n\n const sortFn = sortFns?.[column.columnDef.sortFn as string]\n\n if (process.env.NODE_ENV === 'development' && !sortFn) {\n console.warn(\n `sortFn '${String(column.columnDef.sortFn)}' for column '${column.id}' is not registered`,\n )\n }\n\n return sortFn ?? sortFn_basic\n}\n\n/**\n * Applies the next sorting state for this column.\n *\n * The toggle can add, replace, flip, or remove this column's sort entry. Multi\n * sorting respects `enableMultiSort`, `maxMultiSortColCount`, and the `multi`\n * argument.\n *\n * @example\n * ```ts\n * column_toggleSorting(column, undefined, true)\n * ```\n */\nexport function column_toggleSorting<\n TFeatures extends TableFeatures,\n TData extends RowData,\n TValue extends CellData = CellData,\n>(\n column: Column_Internal<TFeatures, TData, TValue>,\n desc?: boolean,\n multi?: boolean,\n) {\n // this needs to be outside of table.setSorting to be in sync with rerender\n const nextSortingOrder = column_getNextSortingOrder(column)\n const hasManualValue = typeof desc !== 'undefined'\n\n table_setSorting(column.table, (old) => {\n // Find any existing sorting for this column\n const existingIndex = old.findIndex((d) => d.id === column.id)\n const existingSorting =\n existingIndex === -1 ? undefined : old[existingIndex]\n\n let newSorting: SortingState = []\n\n // What should we do with this sort action?\n let sortAction: 'add' | 'remove' | 'toggle' | 'replace'\n const nextDesc = hasManualValue ? desc : nextSortingOrder === 'desc'\n\n // Multi-mode\n if (old.length && column_getCanMultiSort(column) && multi) {\n if (existingSorting) {\n sortAction = 'toggle'\n } else {\n sortAction = 'add'\n }\n } else {\n // Normal mode\n if (old.length && existingIndex !== old.length - 1) {\n sortAction = 'replace'\n } else if (existingSorting) {\n sortAction = 'toggle'\n } else {\n sortAction = 'replace'\n }\n }\n\n // Handle toggle states that will remove the sorting\n if (sortAction === 'toggle') {\n // If we are \"actually\" toggling (not a manual set value), should we remove the sorting?\n if (!hasManualValue) {\n // Is our intention to remove?\n if (!nextSortingOrder) {\n sortAction = 'remove'\n }\n }\n }\n\n if (sortAction === 'add') {\n newSorting = [\n ...old,\n {\n id: column.id,\n desc: nextDesc,\n },\n ]\n // Take latest n columns\n newSorting.splice(\n 0,\n newSorting.length -\n (column.table.options.maxMultiSortColCount ??\n Number.MAX_SAFE_INTEGER),\n )\n } else if (sortAction === 'toggle') {\n // This flips (or sets) the\n newSorting = old.map((d) => {\n if (d.id === column.id) {\n return {\n ...d,\n desc: nextDesc,\n }\n }\n return d\n })\n } else if (sortAction === 'remove') {\n newSorting = old.filter((d) => d.id !== column.id)\n } else {\n newSorting = [\n {\n id: column.id,\n desc: nextDesc,\n },\n ]\n }\n\n return newSorting\n })\n}\n\n/**\n * Resolves the first direction used when this column begins sorting.\n *\n * Column-level `sortDescFirst` wins, then table-level `sortDescFirst`, then the\n * auto direction inferred from sampled values.\n *\n * @example\n * ```ts\n * const firstDirection = column_getFirstSortDir(column)\n * ```\n */\nexport function column_getFirstSortDir<\n TFeatures extends TableFeatures,\n TData extends RowData,\n TValue extends CellData = CellData,\n>(column: Column_Internal<TFeatures, TData, TValue>) {\n const sortDescFirst =\n column.columnDef.sortDescFirst ??\n column.table.options.sortDescFirst ??\n column_getAutoSortDir(column) === 'desc'\n return sortDescFirst ? 'desc' : 'asc'\n}\n\n/**\n * Resolves the next sort order for this column's toggle cycle.\n *\n * The cycle starts with the first sort direction, flips between `asc` and\n * `desc`, and can return `false` when sorting removal is enabled.\n *\n * @example\n * ```ts\n * const nextOrder = column_getNextSortingOrder(column)\n * ```\n */\nexport function column_getNextSortingOrder<\n TFeatures extends TableFeatures,\n TData extends RowData,\n TValue extends CellData = CellData,\n>(column: Column_Internal<TFeatures, TData, TValue>, multi?: boolean) {\n const firstSortDirection = column_getFirstSortDir(column)\n const isSorted = column_getIsSorted(column)\n\n if (!isSorted) {\n return firstSortDirection\n }\n\n if (\n isSorted !== firstSortDirection &&\n (column.table.options.enableSortingRemoval ?? true) && // If enableSortRemove, enable in general\n (multi ? (column.table.options.enableMultiRemove ?? true) : true) // If multi, don't allow if enableMultiRemove))\n ) {\n return false\n }\n return isSorted === 'desc' ? 'asc' : 'desc'\n}\n\n/**\n * Checks whether this accessor column can participate in sorting.\n *\n * The column must have an accessor and sorting must be enabled by both the\n * column definition and table options.\n *\n * @example\n * ```ts\n * const canSort = column_getCanSort(column)\n * ```\n */\nexport function column_getCanSort<\n TFeatures extends TableFeatures,\n TData extends RowData,\n TValue extends CellData = CellData,\n>(column: Column_Internal<TFeatures, TData, TValue>) {\n return (\n (column.columnDef.enableSorting ?? true) &&\n (column.table.options.enableSorting ?? true) &&\n !!column.accessorFn\n )\n}\n\n/**\n * Checks whether this column can be added to a multi-sort state.\n *\n * Column-level `enableMultiSort` wins over table-level `enableMultiSort`; if\n * neither is set, accessor columns can multi-sort by default.\n *\n * @example\n * ```ts\n * const canMultiSort = column_getCanMultiSort(column)\n * ```\n */\nexport function column_getCanMultiSort<\n TFeatures extends TableFeatures,\n TData extends RowData,\n TValue extends CellData = CellData,\n>(column: Column_Internal<TFeatures, TData, TValue>): boolean {\n return (\n column.columnDef.enableMultiSort ??\n column.table.options.enableMultiSort ??\n !!column.accessorFn\n )\n}\n\n/**\n * Reads this column's current sort direction.\n *\n * The result is `false` when the column is not sorted, otherwise `'asc'` or\n * `'desc'` based on the column's entry in `state.sorting`.\n *\n * @example\n * ```ts\n * const direction = column_getIsSorted(column)\n * ```\n */\nexport function column_getIsSorted<\n TFeatures extends TableFeatures,\n TData extends RowData,\n TValue extends CellData = CellData,\n>(column: Column_Internal<TFeatures, TData, TValue>): false | SortDirection {\n const columnSort = column.table.atoms.sorting\n ?.get()\n ?.find((d) => d.id === column.id)\n return !columnSort ? false : columnSort.desc ? 'desc' : 'asc'\n}\n\n/**\n * Finds this column's position in the ordered `state.sorting` array.\n *\n * The result is `-1` when the column is not sorted.\n *\n * @example\n * ```ts\n * const index = column_getSortIndex(column)\n * ```\n */\nexport function column_getSortIndex<\n TFeatures extends TableFeatures,\n TData extends RowData,\n TValue extends CellData = CellData,\n>(column: Column_Internal<TFeatures, TData, TValue>): number {\n return (\n column.table.atoms.sorting?.get()?.findIndex((d) => d.id === column.id) ??\n -1\n )\n}\n\n/**\n * Removes this column from the sorting state.\n *\n * Other sorted columns are preserved, including their relative order.\n *\n * @example\n * ```ts\n * column_clearSorting(column)\n * ```\n */\nexport function column_clearSorting<\n TFeatures extends TableFeatures,\n TData extends RowData,\n TValue extends CellData = CellData,\n>(column: Column_Internal<TFeatures, TData, TValue>) {\n // clear sorting for just 1 column\n table_setSorting(column.table, (old) =>\n old.length ? old.filter((d) => d.id !== column.id) : [],\n )\n}\n\n/**\n * Creates a header event handler that toggles this column's sorting.\n *\n * The handler ignores events when the column cannot sort, persists React-style\n * synthetic events when present, and asks `options.isMultiSortEvent` whether\n * the event should add to a multi-sort.\n *\n * @example\n * ```ts\n * const onClick = column_getToggleSortingHandler(column)\n * ```\n */\nexport function column_getToggleSortingHandler<\n TFeatures extends TableFeatures,\n TData extends RowData,\n TValue extends CellData = CellData,\n>(column: Column_Internal<TFeatures, TData, TValue>) {\n const canSort = column_getCanSort(column)\n\n return (e: unknown) => {\n if (!canSort) return\n ;(e as any).persist?.()\n column_toggleSorting(\n column,\n\n undefined,\n column_getCanMultiSort(column)\n ? column.table.options.isMultiSortEvent?.(e)\n : false,\n )\n }\n}\n"],"mappings":"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"}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { cloneState, isFunction } from "../../utils.js";
|
|
2
|
-
import { reSplitAlphaNumeric, sortFn_basic } from "
|
|
2
|
+
import { reSplitAlphaNumeric, sortFn_basic } from "./sortFns.js";
|
|
3
3
|
|
|
4
4
|
//#region src/features/row-sorting/rowSortingFeature.utils.ts
|
|
5
5
|
/**
|
|
@@ -60,20 +60,31 @@ function table_resetSorting(table, defaultState) {
|
|
|
60
60
|
function column_getAutoSortFn(column) {
|
|
61
61
|
const sortFns = column.table._rowModelFns.sortFns;
|
|
62
62
|
const firstRows = column.table.getFilteredRowModel().flatRows.slice(0, 10);
|
|
63
|
+
let sortFnName;
|
|
63
64
|
let isString = false;
|
|
64
65
|
for (let i = 0; i < firstRows.length; i++) {
|
|
65
66
|
const value = firstRows[i].getValue(column.id);
|
|
66
67
|
if (Object.prototype.toString.call(value) === "[object Date]") {
|
|
67
|
-
|
|
68
|
+
sortFnName = "datetime";
|
|
69
|
+
break;
|
|
68
70
|
}
|
|
69
71
|
if (typeof value === "string") {
|
|
70
72
|
isString = true;
|
|
71
73
|
if (value.split(reSplitAlphaNumeric).length > 1) {
|
|
72
|
-
|
|
74
|
+
sortFnName = "alphanumeric";
|
|
75
|
+
break;
|
|
73
76
|
}
|
|
74
77
|
}
|
|
75
78
|
}
|
|
76
|
-
if (isString)
|
|
79
|
+
if (!sortFnName && isString) sortFnName = "text";
|
|
80
|
+
if (sortFnName) {
|
|
81
|
+
let sortFn = sortFns?.[sortFnName];
|
|
82
|
+
if (!sortFn) {
|
|
83
|
+
if (process.env.NODE_ENV === "development") console.warn(`sortFn '${sortFnName}' (auto) for column '${column.id}' is not registered`);
|
|
84
|
+
if (sortFnName === "alphanumeric") sortFn = sortFns?.text;
|
|
85
|
+
}
|
|
86
|
+
if (sortFn) return sortFn;
|
|
87
|
+
}
|
|
77
88
|
return sortFn_basic;
|
|
78
89
|
}
|
|
79
90
|
/**
|
|
@@ -106,7 +117,11 @@ function column_getAutoSortDir(column) {
|
|
|
106
117
|
*/
|
|
107
118
|
function column_getSortFn(column) {
|
|
108
119
|
const sortFns = column.table._rowModelFns.sortFns;
|
|
109
|
-
|
|
120
|
+
if (isFunction(column.columnDef.sortFn)) return column.columnDef.sortFn;
|
|
121
|
+
if (column.columnDef.sortFn === "auto") return column_getAutoSortFn(column);
|
|
122
|
+
const sortFn = sortFns?.[column.columnDef.sortFn];
|
|
123
|
+
if (process.env.NODE_ENV === "development" && !sortFn) console.warn(`sortFn '${String(column.columnDef.sortFn)}' for column '${column.id}' is not registered`);
|
|
124
|
+
return sortFn ?? sortFn_basic;
|
|
110
125
|
}
|
|
111
126
|
/**
|
|
112
127
|
* Applies the next sorting state for this column.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"rowSortingFeature.utils.js","names":[],"sources":["../../../src/features/row-sorting/rowSortingFeature.utils.ts"],"sourcesContent":["import { reSplitAlphaNumeric, sortFn_basic } from '../../fns/sortFns'\nimport { cloneState, isFunction } from '../../utils'\nimport type { CellData, RowData, Updater } from '../../types/type-utils'\nimport type { TableFeatures } from '../../types/TableFeatures'\nimport type { Table_Internal } from '../../types/Table'\nimport type { Column_Internal } from '../../types/Column'\nimport type {\n SortDirection,\n SortFn,\n SortingState,\n} from './rowSortingFeature.types'\n\n// State Utils\n\n/**\n * Creates the default sorting state.\n *\n * The feature default is an empty array, meaning no columns are sorted. Reset\n * APIs use this value when `defaultState` is `true`.\n *\n * @example\n * ```ts\n * const sorting = getDefaultSortingState()\n * ```\n */\nexport function getDefaultSortingState(): SortingState {\n return []\n}\n\n/**\n * Routes a sorting updater through the table's sorting change handler.\n *\n * The updater may be a next `SortingState` array or a function of the previous\n * sorting state, matching the instance `table.setSorting` behavior.\n *\n * @example\n * ```ts\n * table_setSorting(table, (old) => [...old, { id: 'age', desc: true }])\n * ```\n */\nexport function table_setSorting<\n TFeatures extends TableFeatures,\n TData extends RowData,\n>(table: Table_Internal<TFeatures, TData>, updater: Updater<SortingState>) {\n table.options.onSortingChange?.(updater)\n}\n\n/**\n * Resets `sorting` to the configured initial state or feature default.\n *\n * With no argument, the reset clones `table.initialState.sorting` when it\n * exists. Passing `true` ignores initial state and resets to `[]`.\n *\n * @example\n * ```ts\n * table_resetSorting(table)\n * table_resetSorting(table, true)\n * ```\n */\nexport function table_resetSorting<\n TFeatures extends TableFeatures,\n TData extends RowData,\n>(table: Table_Internal<TFeatures, TData>, defaultState?: boolean) {\n table_setSorting(\n table,\n defaultState ? [] : cloneState(table.initialState.sorting ?? []),\n )\n}\n\n// Column Utils\n\n/**\n * Chooses a built-in sorting function from sampled filtered row values.\n *\n * Date-like values use `datetime`, mixed text/numeric strings use\n * `alphanumeric`, plain strings use `text`, and unknown values fall back to\n * `basic`.\n *\n * @example\n * ```ts\n * const sortFn = column_getAutoSortFn(column)\n * ```\n */\nexport function column_getAutoSortFn<\n TFeatures extends TableFeatures,\n TData extends RowData,\n TValue extends CellData = CellData,\n>(column: Column_Internal<TFeatures, TData, TValue>): SortFn<TFeatures, TData> {\n const sortFns: Record<string, SortFn<TFeatures, TData>> | undefined =\n column.table._rowModelFns.sortFns\n\n const firstRows = column.table.getFilteredRowModel().flatRows.slice(0, 10)\n\n let isString = false\n\n for (let i = 0; i < firstRows.length; i++) {\n const value = firstRows[i]!.getValue(column.id)\n\n if (Object.prototype.toString.call(value) === '[object Date]') {\n if (sortFns?.datetime) {\n return sortFns.datetime\n }\n }\n\n if (typeof value === 'string') {\n isString = true\n\n if (value.split(reSplitAlphaNumeric).length > 1) {\n if (sortFns?.alphanumeric) {\n return sortFns.alphanumeric\n }\n }\n }\n }\n\n if (isString) {\n return sortFns?.text ?? sortFn_basic\n }\n\n return sortFn_basic\n}\n\n/**\n * Chooses the default first sort direction from the first filtered row value.\n *\n * String columns start ascending so alphabetical order is natural; other value\n * types start descending.\n *\n * @example\n * ```ts\n * const direction = column_getAutoSortDir(column)\n * ```\n */\nexport function column_getAutoSortDir<\n TFeatures extends TableFeatures,\n TData extends RowData,\n TValue extends CellData = CellData,\n>(column: Column_Internal<TFeatures, TData, TValue>) {\n const firstRow = column.table.getFilteredRowModel().flatRows[0]\n\n const value = firstRow ? firstRow.getValue(column.id) : undefined\n\n if (typeof value === 'string') {\n return 'asc'\n }\n\n return 'desc'\n}\n\n/**\n * Resolves the sorting function configured for a column.\n *\n * Function-valued `columnDef.sortFn` is returned directly, `'auto'` delegates\n * to `column_getAutoSortFn`, and string values are looked up in the table's\n * sorting function registry before falling back to `basic`.\n *\n * @example\n * ```ts\n * const sortFn = column_getSortFn(column)\n * ```\n */\nexport function column_getSortFn<\n TFeatures extends TableFeatures,\n TData extends RowData,\n TValue extends CellData = CellData,\n>(column: Column_Internal<TFeatures, TData, TValue>): SortFn<TFeatures, TData> {\n const sortFns: Record<string, SortFn<TFeatures, TData>> | undefined =\n column.table._rowModelFns.sortFns\n\n return isFunction(column.columnDef.sortFn)\n ? column.columnDef.sortFn\n : column.columnDef.sortFn === 'auto'\n ? column_getAutoSortFn(column)\n : (sortFns?.[column.columnDef.sortFn as string] ?? sortFn_basic)\n}\n\n/**\n * Applies the next sorting state for this column.\n *\n * The toggle can add, replace, flip, or remove this column's sort entry. Multi\n * sorting respects `enableMultiSort`, `maxMultiSortColCount`, and the `multi`\n * argument.\n *\n * @example\n * ```ts\n * column_toggleSorting(column, undefined, true)\n * ```\n */\nexport function column_toggleSorting<\n TFeatures extends TableFeatures,\n TData extends RowData,\n TValue extends CellData = CellData,\n>(\n column: Column_Internal<TFeatures, TData, TValue>,\n desc?: boolean,\n multi?: boolean,\n) {\n // this needs to be outside of table.setSorting to be in sync with rerender\n const nextSortingOrder = column_getNextSortingOrder(column)\n const hasManualValue = typeof desc !== 'undefined'\n\n table_setSorting(column.table, (old) => {\n // Find any existing sorting for this column\n const existingIndex = old.findIndex((d) => d.id === column.id)\n const existingSorting =\n existingIndex === -1 ? undefined : old[existingIndex]\n\n let newSorting: SortingState = []\n\n // What should we do with this sort action?\n let sortAction: 'add' | 'remove' | 'toggle' | 'replace'\n const nextDesc = hasManualValue ? desc : nextSortingOrder === 'desc'\n\n // Multi-mode\n if (old.length && column_getCanMultiSort(column) && multi) {\n if (existingSorting) {\n sortAction = 'toggle'\n } else {\n sortAction = 'add'\n }\n } else {\n // Normal mode\n if (old.length && existingIndex !== old.length - 1) {\n sortAction = 'replace'\n } else if (existingSorting) {\n sortAction = 'toggle'\n } else {\n sortAction = 'replace'\n }\n }\n\n // Handle toggle states that will remove the sorting\n if (sortAction === 'toggle') {\n // If we are \"actually\" toggling (not a manual set value), should we remove the sorting?\n if (!hasManualValue) {\n // Is our intention to remove?\n if (!nextSortingOrder) {\n sortAction = 'remove'\n }\n }\n }\n\n if (sortAction === 'add') {\n newSorting = [\n ...old,\n {\n id: column.id,\n desc: nextDesc,\n },\n ]\n // Take latest n columns\n newSorting.splice(\n 0,\n newSorting.length -\n (column.table.options.maxMultiSortColCount ??\n Number.MAX_SAFE_INTEGER),\n )\n } else if (sortAction === 'toggle') {\n // This flips (or sets) the\n newSorting = old.map((d) => {\n if (d.id === column.id) {\n return {\n ...d,\n desc: nextDesc,\n }\n }\n return d\n })\n } else if (sortAction === 'remove') {\n newSorting = old.filter((d) => d.id !== column.id)\n } else {\n newSorting = [\n {\n id: column.id,\n desc: nextDesc,\n },\n ]\n }\n\n return newSorting\n })\n}\n\n/**\n * Resolves the first direction used when this column begins sorting.\n *\n * Column-level `sortDescFirst` wins, then table-level `sortDescFirst`, then the\n * auto direction inferred from sampled values.\n *\n * @example\n * ```ts\n * const firstDirection = column_getFirstSortDir(column)\n * ```\n */\nexport function column_getFirstSortDir<\n TFeatures extends TableFeatures,\n TData extends RowData,\n TValue extends CellData = CellData,\n>(column: Column_Internal<TFeatures, TData, TValue>) {\n const sortDescFirst =\n column.columnDef.sortDescFirst ??\n column.table.options.sortDescFirst ??\n column_getAutoSortDir(column) === 'desc'\n return sortDescFirst ? 'desc' : 'asc'\n}\n\n/**\n * Resolves the next sort order for this column's toggle cycle.\n *\n * The cycle starts with the first sort direction, flips between `asc` and\n * `desc`, and can return `false` when sorting removal is enabled.\n *\n * @example\n * ```ts\n * const nextOrder = column_getNextSortingOrder(column)\n * ```\n */\nexport function column_getNextSortingOrder<\n TFeatures extends TableFeatures,\n TData extends RowData,\n TValue extends CellData = CellData,\n>(column: Column_Internal<TFeatures, TData, TValue>, multi?: boolean) {\n const firstSortDirection = column_getFirstSortDir(column)\n const isSorted = column_getIsSorted(column)\n\n if (!isSorted) {\n return firstSortDirection\n }\n\n if (\n isSorted !== firstSortDirection &&\n (column.table.options.enableSortingRemoval ?? true) && // If enableSortRemove, enable in general\n (multi ? (column.table.options.enableMultiRemove ?? true) : true) // If multi, don't allow if enableMultiRemove))\n ) {\n return false\n }\n return isSorted === 'desc' ? 'asc' : 'desc'\n}\n\n/**\n * Checks whether this accessor column can participate in sorting.\n *\n * The column must have an accessor and sorting must be enabled by both the\n * column definition and table options.\n *\n * @example\n * ```ts\n * const canSort = column_getCanSort(column)\n * ```\n */\nexport function column_getCanSort<\n TFeatures extends TableFeatures,\n TData extends RowData,\n TValue extends CellData = CellData,\n>(column: Column_Internal<TFeatures, TData, TValue>) {\n return (\n (column.columnDef.enableSorting ?? true) &&\n (column.table.options.enableSorting ?? true) &&\n !!column.accessorFn\n )\n}\n\n/**\n * Checks whether this column can be added to a multi-sort state.\n *\n * Column-level `enableMultiSort` wins over table-level `enableMultiSort`; if\n * neither is set, accessor columns can multi-sort by default.\n *\n * @example\n * ```ts\n * const canMultiSort = column_getCanMultiSort(column)\n * ```\n */\nexport function column_getCanMultiSort<\n TFeatures extends TableFeatures,\n TData extends RowData,\n TValue extends CellData = CellData,\n>(column: Column_Internal<TFeatures, TData, TValue>): boolean {\n return (\n column.columnDef.enableMultiSort ??\n column.table.options.enableMultiSort ??\n !!column.accessorFn\n )\n}\n\n/**\n * Reads this column's current sort direction.\n *\n * The result is `false` when the column is not sorted, otherwise `'asc'` or\n * `'desc'` based on the column's entry in `state.sorting`.\n *\n * @example\n * ```ts\n * const direction = column_getIsSorted(column)\n * ```\n */\nexport function column_getIsSorted<\n TFeatures extends TableFeatures,\n TData extends RowData,\n TValue extends CellData = CellData,\n>(column: Column_Internal<TFeatures, TData, TValue>): false | SortDirection {\n const columnSort = column.table.atoms.sorting\n ?.get()\n ?.find((d) => d.id === column.id)\n return !columnSort ? false : columnSort.desc ? 'desc' : 'asc'\n}\n\n/**\n * Finds this column's position in the ordered `state.sorting` array.\n *\n * The result is `-1` when the column is not sorted.\n *\n * @example\n * ```ts\n * const index = column_getSortIndex(column)\n * ```\n */\nexport function column_getSortIndex<\n TFeatures extends TableFeatures,\n TData extends RowData,\n TValue extends CellData = CellData,\n>(column: Column_Internal<TFeatures, TData, TValue>): number {\n return (\n column.table.atoms.sorting?.get()?.findIndex((d) => d.id === column.id) ??\n -1\n )\n}\n\n/**\n * Removes this column from the sorting state.\n *\n * Other sorted columns are preserved, including their relative order.\n *\n * @example\n * ```ts\n * column_clearSorting(column)\n * ```\n */\nexport function column_clearSorting<\n TFeatures extends TableFeatures,\n TData extends RowData,\n TValue extends CellData = CellData,\n>(column: Column_Internal<TFeatures, TData, TValue>) {\n // clear sorting for just 1 column\n table_setSorting(column.table, (old) =>\n old.length ? old.filter((d) => d.id !== column.id) : [],\n )\n}\n\n/**\n * Creates a header event handler that toggles this column's sorting.\n *\n * The handler ignores events when the column cannot sort, persists React-style\n * synthetic events when present, and asks `options.isMultiSortEvent` whether\n * the event should add to a multi-sort.\n *\n * @example\n * ```ts\n * const onClick = column_getToggleSortingHandler(column)\n * ```\n */\nexport function column_getToggleSortingHandler<\n TFeatures extends TableFeatures,\n TData extends RowData,\n TValue extends CellData = CellData,\n>(column: Column_Internal<TFeatures, TData, TValue>) {\n const canSort = column_getCanSort(column)\n\n return (e: unknown) => {\n if (!canSort) return\n ;(e as any).persist?.()\n column_toggleSorting(\n column,\n\n undefined,\n column_getCanMultiSort(column)\n ? column.table.options.isMultiSortEvent?.(e)\n : false,\n )\n }\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"rowSortingFeature.utils.js","names":[],"sources":["../../../src/features/row-sorting/rowSortingFeature.utils.ts"],"sourcesContent":["import { cloneState, isFunction } from '../../utils'\nimport { reSplitAlphaNumeric, sortFn_basic } from './sortFns'\nimport type { CellData, RowData, Updater } from '../../types/type-utils'\nimport type { TableFeatures } from '../../types/TableFeatures'\nimport type { Table_Internal } from '../../types/Table'\nimport type { Column_Internal } from '../../types/Column'\nimport type {\n SortDirection,\n SortFn,\n SortingState,\n} from './rowSortingFeature.types'\n\n// State Utils\n\n/**\n * Creates the default sorting state.\n *\n * The feature default is an empty array, meaning no columns are sorted. Reset\n * APIs use this value when `defaultState` is `true`.\n *\n * @example\n * ```ts\n * const sorting = getDefaultSortingState()\n * ```\n */\nexport function getDefaultSortingState(): SortingState {\n return []\n}\n\n/**\n * Routes a sorting updater through the table's sorting change handler.\n *\n * The updater may be a next `SortingState` array or a function of the previous\n * sorting state, matching the instance `table.setSorting` behavior.\n *\n * @example\n * ```ts\n * table_setSorting(table, (old) => [...old, { id: 'age', desc: true }])\n * ```\n */\nexport function table_setSorting<\n TFeatures extends TableFeatures,\n TData extends RowData,\n>(table: Table_Internal<TFeatures, TData>, updater: Updater<SortingState>) {\n table.options.onSortingChange?.(updater)\n}\n\n/**\n * Resets `sorting` to the configured initial state or feature default.\n *\n * With no argument, the reset clones `table.initialState.sorting` when it\n * exists. Passing `true` ignores initial state and resets to `[]`.\n *\n * @example\n * ```ts\n * table_resetSorting(table)\n * table_resetSorting(table, true)\n * ```\n */\nexport function table_resetSorting<\n TFeatures extends TableFeatures,\n TData extends RowData,\n>(table: Table_Internal<TFeatures, TData>, defaultState?: boolean) {\n table_setSorting(\n table,\n defaultState ? [] : cloneState(table.initialState.sorting ?? []),\n )\n}\n\n// Column Utils\n\n/**\n * Chooses a built-in sorting function from sampled filtered row values.\n *\n * Date-like values use `datetime`, mixed text/numeric strings use\n * `alphanumeric`, plain strings use `text`, and unknown values fall back to\n * `basic`.\n *\n * @example\n * ```ts\n * const sortFn = column_getAutoSortFn(column)\n * ```\n */\nexport function column_getAutoSortFn<\n TFeatures extends TableFeatures,\n TData extends RowData,\n TValue extends CellData = CellData,\n>(column: Column_Internal<TFeatures, TData, TValue>): SortFn<TFeatures, TData> {\n const sortFns: Record<string, SortFn<TFeatures, TData>> | undefined =\n column.table._rowModelFns.sortFns\n\n const firstRows = column.table.getFilteredRowModel().flatRows.slice(0, 10)\n\n let sortFnName: string | undefined\n let isString = false\n\n for (let i = 0; i < firstRows.length; i++) {\n const value = firstRows[i]!.getValue(column.id)\n\n if (Object.prototype.toString.call(value) === '[object Date]') {\n sortFnName = 'datetime'\n break\n }\n\n if (typeof value === 'string') {\n isString = true\n\n if (value.split(reSplitAlphaNumeric).length > 1) {\n sortFnName = 'alphanumeric'\n break\n }\n }\n }\n\n if (!sortFnName && isString) {\n sortFnName = 'text'\n }\n\n if (sortFnName) {\n let sortFn = sortFns?.[sortFnName]\n\n if (!sortFn) {\n if (process.env.NODE_ENV === 'development') {\n console.warn(\n `sortFn '${sortFnName}' (auto) for column '${column.id}' is not registered`,\n )\n }\n\n // String columns degrade to a registered text sort before basic\n if (sortFnName === 'alphanumeric') {\n sortFn = sortFns?.text\n }\n }\n\n if (sortFn) {\n return sortFn\n }\n }\n\n return sortFn_basic\n}\n\n/**\n * Chooses the default first sort direction from the first filtered row value.\n *\n * String columns start ascending so alphabetical order is natural; other value\n * types start descending.\n *\n * @example\n * ```ts\n * const direction = column_getAutoSortDir(column)\n * ```\n */\nexport function column_getAutoSortDir<\n TFeatures extends TableFeatures,\n TData extends RowData,\n TValue extends CellData = CellData,\n>(column: Column_Internal<TFeatures, TData, TValue>) {\n const firstRow = column.table.getFilteredRowModel().flatRows[0]\n\n const value = firstRow ? firstRow.getValue(column.id) : undefined\n\n if (typeof value === 'string') {\n return 'asc'\n }\n\n return 'desc'\n}\n\n/**\n * Resolves the sorting function configured for a column.\n *\n * Function-valued `columnDef.sortFn` is returned directly, `'auto'` delegates\n * to `column_getAutoSortFn`, and string values are looked up in the table's\n * sorting function registry before falling back to `basic`.\n *\n * @example\n * ```ts\n * const sortFn = column_getSortFn(column)\n * ```\n */\nexport function column_getSortFn<\n TFeatures extends TableFeatures,\n TData extends RowData,\n TValue extends CellData = CellData,\n>(column: Column_Internal<TFeatures, TData, TValue>): SortFn<TFeatures, TData> {\n const sortFns: Record<string, SortFn<TFeatures, TData>> | undefined =\n column.table._rowModelFns.sortFns\n\n if (isFunction(column.columnDef.sortFn)) {\n return column.columnDef.sortFn\n }\n\n if (column.columnDef.sortFn === 'auto') {\n return column_getAutoSortFn(column)\n }\n\n const sortFn = sortFns?.[column.columnDef.sortFn as string]\n\n if (process.env.NODE_ENV === 'development' && !sortFn) {\n console.warn(\n `sortFn '${String(column.columnDef.sortFn)}' for column '${column.id}' is not registered`,\n )\n }\n\n return sortFn ?? sortFn_basic\n}\n\n/**\n * Applies the next sorting state for this column.\n *\n * The toggle can add, replace, flip, or remove this column's sort entry. Multi\n * sorting respects `enableMultiSort`, `maxMultiSortColCount`, and the `multi`\n * argument.\n *\n * @example\n * ```ts\n * column_toggleSorting(column, undefined, true)\n * ```\n */\nexport function column_toggleSorting<\n TFeatures extends TableFeatures,\n TData extends RowData,\n TValue extends CellData = CellData,\n>(\n column: Column_Internal<TFeatures, TData, TValue>,\n desc?: boolean,\n multi?: boolean,\n) {\n // this needs to be outside of table.setSorting to be in sync with rerender\n const nextSortingOrder = column_getNextSortingOrder(column)\n const hasManualValue = typeof desc !== 'undefined'\n\n table_setSorting(column.table, (old) => {\n // Find any existing sorting for this column\n const existingIndex = old.findIndex((d) => d.id === column.id)\n const existingSorting =\n existingIndex === -1 ? undefined : old[existingIndex]\n\n let newSorting: SortingState = []\n\n // What should we do with this sort action?\n let sortAction: 'add' | 'remove' | 'toggle' | 'replace'\n const nextDesc = hasManualValue ? desc : nextSortingOrder === 'desc'\n\n // Multi-mode\n if (old.length && column_getCanMultiSort(column) && multi) {\n if (existingSorting) {\n sortAction = 'toggle'\n } else {\n sortAction = 'add'\n }\n } else {\n // Normal mode\n if (old.length && existingIndex !== old.length - 1) {\n sortAction = 'replace'\n } else if (existingSorting) {\n sortAction = 'toggle'\n } else {\n sortAction = 'replace'\n }\n }\n\n // Handle toggle states that will remove the sorting\n if (sortAction === 'toggle') {\n // If we are \"actually\" toggling (not a manual set value), should we remove the sorting?\n if (!hasManualValue) {\n // Is our intention to remove?\n if (!nextSortingOrder) {\n sortAction = 'remove'\n }\n }\n }\n\n if (sortAction === 'add') {\n newSorting = [\n ...old,\n {\n id: column.id,\n desc: nextDesc,\n },\n ]\n // Take latest n columns\n newSorting.splice(\n 0,\n newSorting.length -\n (column.table.options.maxMultiSortColCount ??\n Number.MAX_SAFE_INTEGER),\n )\n } else if (sortAction === 'toggle') {\n // This flips (or sets) the\n newSorting = old.map((d) => {\n if (d.id === column.id) {\n return {\n ...d,\n desc: nextDesc,\n }\n }\n return d\n })\n } else if (sortAction === 'remove') {\n newSorting = old.filter((d) => d.id !== column.id)\n } else {\n newSorting = [\n {\n id: column.id,\n desc: nextDesc,\n },\n ]\n }\n\n return newSorting\n })\n}\n\n/**\n * Resolves the first direction used when this column begins sorting.\n *\n * Column-level `sortDescFirst` wins, then table-level `sortDescFirst`, then the\n * auto direction inferred from sampled values.\n *\n * @example\n * ```ts\n * const firstDirection = column_getFirstSortDir(column)\n * ```\n */\nexport function column_getFirstSortDir<\n TFeatures extends TableFeatures,\n TData extends RowData,\n TValue extends CellData = CellData,\n>(column: Column_Internal<TFeatures, TData, TValue>) {\n const sortDescFirst =\n column.columnDef.sortDescFirst ??\n column.table.options.sortDescFirst ??\n column_getAutoSortDir(column) === 'desc'\n return sortDescFirst ? 'desc' : 'asc'\n}\n\n/**\n * Resolves the next sort order for this column's toggle cycle.\n *\n * The cycle starts with the first sort direction, flips between `asc` and\n * `desc`, and can return `false` when sorting removal is enabled.\n *\n * @example\n * ```ts\n * const nextOrder = column_getNextSortingOrder(column)\n * ```\n */\nexport function column_getNextSortingOrder<\n TFeatures extends TableFeatures,\n TData extends RowData,\n TValue extends CellData = CellData,\n>(column: Column_Internal<TFeatures, TData, TValue>, multi?: boolean) {\n const firstSortDirection = column_getFirstSortDir(column)\n const isSorted = column_getIsSorted(column)\n\n if (!isSorted) {\n return firstSortDirection\n }\n\n if (\n isSorted !== firstSortDirection &&\n (column.table.options.enableSortingRemoval ?? true) && // If enableSortRemove, enable in general\n (multi ? (column.table.options.enableMultiRemove ?? true) : true) // If multi, don't allow if enableMultiRemove))\n ) {\n return false\n }\n return isSorted === 'desc' ? 'asc' : 'desc'\n}\n\n/**\n * Checks whether this accessor column can participate in sorting.\n *\n * The column must have an accessor and sorting must be enabled by both the\n * column definition and table options.\n *\n * @example\n * ```ts\n * const canSort = column_getCanSort(column)\n * ```\n */\nexport function column_getCanSort<\n TFeatures extends TableFeatures,\n TData extends RowData,\n TValue extends CellData = CellData,\n>(column: Column_Internal<TFeatures, TData, TValue>) {\n return (\n (column.columnDef.enableSorting ?? true) &&\n (column.table.options.enableSorting ?? true) &&\n !!column.accessorFn\n )\n}\n\n/**\n * Checks whether this column can be added to a multi-sort state.\n *\n * Column-level `enableMultiSort` wins over table-level `enableMultiSort`; if\n * neither is set, accessor columns can multi-sort by default.\n *\n * @example\n * ```ts\n * const canMultiSort = column_getCanMultiSort(column)\n * ```\n */\nexport function column_getCanMultiSort<\n TFeatures extends TableFeatures,\n TData extends RowData,\n TValue extends CellData = CellData,\n>(column: Column_Internal<TFeatures, TData, TValue>): boolean {\n return (\n column.columnDef.enableMultiSort ??\n column.table.options.enableMultiSort ??\n !!column.accessorFn\n )\n}\n\n/**\n * Reads this column's current sort direction.\n *\n * The result is `false` when the column is not sorted, otherwise `'asc'` or\n * `'desc'` based on the column's entry in `state.sorting`.\n *\n * @example\n * ```ts\n * const direction = column_getIsSorted(column)\n * ```\n */\nexport function column_getIsSorted<\n TFeatures extends TableFeatures,\n TData extends RowData,\n TValue extends CellData = CellData,\n>(column: Column_Internal<TFeatures, TData, TValue>): false | SortDirection {\n const columnSort = column.table.atoms.sorting\n ?.get()\n ?.find((d) => d.id === column.id)\n return !columnSort ? false : columnSort.desc ? 'desc' : 'asc'\n}\n\n/**\n * Finds this column's position in the ordered `state.sorting` array.\n *\n * The result is `-1` when the column is not sorted.\n *\n * @example\n * ```ts\n * const index = column_getSortIndex(column)\n * ```\n */\nexport function column_getSortIndex<\n TFeatures extends TableFeatures,\n TData extends RowData,\n TValue extends CellData = CellData,\n>(column: Column_Internal<TFeatures, TData, TValue>): number {\n return (\n column.table.atoms.sorting?.get()?.findIndex((d) => d.id === column.id) ??\n -1\n )\n}\n\n/**\n * Removes this column from the sorting state.\n *\n * Other sorted columns are preserved, including their relative order.\n *\n * @example\n * ```ts\n * column_clearSorting(column)\n * ```\n */\nexport function column_clearSorting<\n TFeatures extends TableFeatures,\n TData extends RowData,\n TValue extends CellData = CellData,\n>(column: Column_Internal<TFeatures, TData, TValue>) {\n // clear sorting for just 1 column\n table_setSorting(column.table, (old) =>\n old.length ? old.filter((d) => d.id !== column.id) : [],\n )\n}\n\n/**\n * Creates a header event handler that toggles this column's sorting.\n *\n * The handler ignores events when the column cannot sort, persists React-style\n * synthetic events when present, and asks `options.isMultiSortEvent` whether\n * the event should add to a multi-sort.\n *\n * @example\n * ```ts\n * const onClick = column_getToggleSortingHandler(column)\n * ```\n */\nexport function column_getToggleSortingHandler<\n TFeatures extends TableFeatures,\n TData extends RowData,\n TValue extends CellData = CellData,\n>(column: Column_Internal<TFeatures, TData, TValue>) {\n const canSort = column_getCanSort(column)\n\n return (e: unknown) => {\n if (!canSort) return\n ;(e as any).persist?.()\n column_toggleSorting(\n column,\n\n undefined,\n column_getCanMultiSort(column)\n ? column.table.options.isMultiSortEvent?.(e)\n : false,\n )\n }\n}\n"],"mappings":"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"}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
|
|
2
|
-
//#region src/
|
|
2
|
+
//#region src/features/row-sorting/sortFns.ts
|
|
3
3
|
/**
|
|
4
4
|
* Regular expression used to split mixed text and numeric chunks.
|
|
5
5
|
*
|
|
@@ -8,55 +8,93 @@
|
|
|
8
8
|
*/
|
|
9
9
|
const reSplitAlphaNumeric = /([0-9]+)/gm;
|
|
10
10
|
/**
|
|
11
|
+
* Builds a `SortFn` from a value-level comparator plus an optional
|
|
12
|
+
* `resolveDataValue` normalizer.
|
|
13
|
+
*
|
|
14
|
+
* The `sort` comparator receives both rows' data values, each already passed
|
|
15
|
+
* through `resolveDataValue` when one is defined. Keeping normalization in the
|
|
16
|
+
* resolver means a variant of an existing sorting function only has to swap
|
|
17
|
+
* the resolver, not re-implement the comparison.
|
|
18
|
+
*
|
|
19
|
+
* The definition is attached to the returned function, so a variant can be
|
|
20
|
+
* created by spreading a built-in sorting function and overriding what
|
|
21
|
+
* differs:
|
|
22
|
+
*
|
|
23
|
+
* ```ts
|
|
24
|
+
* const stripDiacritics = (value: string) =>
|
|
25
|
+
* value.normalize('NFD').replace(/\p{Diacritic}/gu, '')
|
|
26
|
+
*
|
|
27
|
+
* const alphanumericIgnoreDiacritics = constructSortFn({
|
|
28
|
+
* ...sortFn_alphanumeric,
|
|
29
|
+
* resolveDataValue: (value) =>
|
|
30
|
+
* stripDiacritics(sortFn_alphanumeric.resolveDataValue!(value)),
|
|
31
|
+
* })
|
|
32
|
+
* ```
|
|
33
|
+
*/
|
|
34
|
+
function constructSortFn(def) {
|
|
35
|
+
const sortFn = Object.assign((rowA, rowB, columnId) => {
|
|
36
|
+
let dataValueA = rowA.getValue(columnId);
|
|
37
|
+
let dataValueB = rowB.getValue(columnId);
|
|
38
|
+
const resolveDataValue = sortFn.resolveDataValue;
|
|
39
|
+
if (resolveDataValue) {
|
|
40
|
+
dataValueA = resolveDataValue(dataValueA);
|
|
41
|
+
dataValueB = resolveDataValue(dataValueB);
|
|
42
|
+
}
|
|
43
|
+
return sortFn.sort(dataValueA, dataValueB, rowA, rowB, columnId);
|
|
44
|
+
}, def);
|
|
45
|
+
return sortFn;
|
|
46
|
+
}
|
|
47
|
+
/**
|
|
11
48
|
* Sorts rows with the built-in alphanumeric strategy.
|
|
12
49
|
*
|
|
13
50
|
* This comparator returns ascending-order results; descending order is applied by the sorting row model.
|
|
14
51
|
*/
|
|
15
|
-
const sortFn_alphanumeric = (
|
|
16
|
-
|
|
17
|
-
|
|
52
|
+
const sortFn_alphanumeric = constructSortFn({
|
|
53
|
+
resolveDataValue: (dataValue) => toString(dataValue).toLowerCase(),
|
|
54
|
+
sort: (dataValueA, dataValueB) => compareAlphanumeric(dataValueA, dataValueB)
|
|
55
|
+
});
|
|
18
56
|
/**
|
|
19
57
|
* Sorts rows with the built-in alphanumeric case sensitive strategy.
|
|
20
58
|
*
|
|
21
59
|
* This comparator returns ascending-order results; descending order is applied by the sorting row model.
|
|
22
60
|
*/
|
|
23
|
-
const sortFn_alphanumericCaseSensitive = (
|
|
24
|
-
|
|
25
|
-
|
|
61
|
+
const sortFn_alphanumericCaseSensitive = constructSortFn({
|
|
62
|
+
resolveDataValue: (dataValue) => toString(dataValue),
|
|
63
|
+
sort: (dataValueA, dataValueB) => compareAlphanumeric(dataValueA, dataValueB)
|
|
64
|
+
});
|
|
26
65
|
/**
|
|
27
66
|
* Sorts rows with the built-in text strategy.
|
|
28
67
|
*
|
|
29
68
|
* This comparator returns ascending-order results; descending order is applied by the sorting row model.
|
|
30
69
|
*/
|
|
31
|
-
const sortFn_text = (
|
|
32
|
-
|
|
33
|
-
|
|
70
|
+
const sortFn_text = constructSortFn({
|
|
71
|
+
resolveDataValue: (dataValue) => toString(dataValue).toLowerCase(),
|
|
72
|
+
sort: (dataValueA, dataValueB) => compareBasic(dataValueA, dataValueB)
|
|
73
|
+
});
|
|
34
74
|
/**
|
|
35
75
|
* Sorts rows with the built-in text case sensitive strategy.
|
|
36
76
|
*
|
|
37
77
|
* This comparator returns ascending-order results; descending order is applied by the sorting row model.
|
|
38
78
|
*/
|
|
39
|
-
const sortFn_textCaseSensitive = (
|
|
40
|
-
|
|
41
|
-
|
|
79
|
+
const sortFn_textCaseSensitive = constructSortFn({
|
|
80
|
+
resolveDataValue: (dataValue) => toString(dataValue),
|
|
81
|
+
sort: (dataValueA, dataValueB) => compareBasic(dataValueA, dataValueB)
|
|
82
|
+
});
|
|
42
83
|
/**
|
|
43
84
|
* Sorts rows with the built-in datetime strategy.
|
|
44
85
|
*
|
|
45
86
|
* This comparator returns ascending-order results; descending order is applied by the sorting row model.
|
|
46
87
|
*/
|
|
47
|
-
const sortFn_datetime = (
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
};
|
|
88
|
+
const sortFn_datetime = constructSortFn({
|
|
89
|
+
resolveDataValue: (dataValue) => toDateSortValue(dataValue),
|
|
90
|
+
sort: (dataValueA, dataValueB) => dataValueA > dataValueB ? 1 : dataValueA < dataValueB ? -1 : 0
|
|
91
|
+
});
|
|
52
92
|
/**
|
|
53
93
|
* Sorts rows with the built-in basic strategy.
|
|
54
94
|
*
|
|
55
95
|
* This comparator returns ascending-order results; descending order is applied by the sorting row model.
|
|
56
96
|
*/
|
|
57
|
-
const sortFn_basic = (
|
|
58
|
-
return compareBasic(rowA.getValue(columnId), rowB.getValue(columnId));
|
|
59
|
-
};
|
|
97
|
+
const sortFn_basic = constructSortFn({ sort: (dataValueA, dataValueB) => compareBasic(dataValueA, dataValueB) });
|
|
60
98
|
function compareBasic(a, b) {
|
|
61
99
|
return a === b ? 0 : a > b ? 1 : -1;
|
|
62
100
|
}
|
|
@@ -156,7 +194,15 @@ function countRemainingChunks(str, start) {
|
|
|
156
194
|
/**
|
|
157
195
|
* The built-in sorting function registry.
|
|
158
196
|
*
|
|
159
|
-
*
|
|
197
|
+
* Registering this full object opts out of tree-shaking: every built-in
|
|
198
|
+
* sorting function ends up in your bundle. Prefer importing the `sortFn_*`
|
|
199
|
+
* functions you actually use and registering just those in the `sortFns`
|
|
200
|
+
* slot, or passing them directly to the `sortFn` column option.
|
|
201
|
+
*
|
|
202
|
+
* @deprecated Import individual `sortFn_*` functions instead for a smaller
|
|
203
|
+
* bundle. This export still works and is not going away in v9, but built-in
|
|
204
|
+
* name resolution (including `sortFn: 'auto'`) only finds functions you
|
|
205
|
+
* register yourself.
|
|
160
206
|
*/
|
|
161
207
|
const sortFns = {
|
|
162
208
|
alphanumeric: sortFn_alphanumeric,
|
|
@@ -168,6 +214,7 @@ const sortFns = {
|
|
|
168
214
|
};
|
|
169
215
|
|
|
170
216
|
//#endregion
|
|
217
|
+
exports.constructSortFn = constructSortFn;
|
|
171
218
|
exports.reSplitAlphaNumeric = reSplitAlphaNumeric;
|
|
172
219
|
exports.sortFn_alphanumeric = sortFn_alphanumeric;
|
|
173
220
|
exports.sortFn_alphanumericCaseSensitive = sortFn_alphanumericCaseSensitive;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sortFns.cjs","names":[],"sources":["../../../src/features/row-sorting/sortFns.ts"],"sourcesContent":["import type { CreatedSortFn, SortFnDef } from './rowSortingFeature.types'\nimport type { RowData } from '../../types/type-utils'\nimport type { TableFeatures } from '../../types/TableFeatures'\nimport type { Row } from '../../types/Row'\n\n/**\n * Regular expression used to split mixed text and numeric chunks.\n *\n * The alphanumeric sort functions use these chunks for natural sorting of\n * strings like `item2` before `item10`.\n */\nexport const reSplitAlphaNumeric = /([0-9]+)/gm\n\n/**\n * Builds a `SortFn` from a value-level comparator plus an optional\n * `resolveDataValue` normalizer.\n *\n * The `sort` comparator receives both rows' data values, each already passed\n * through `resolveDataValue` when one is defined. Keeping normalization in the\n * resolver means a variant of an existing sorting function only has to swap\n * the resolver, not re-implement the comparison.\n *\n * The definition is attached to the returned function, so a variant can be\n * created by spreading a built-in sorting function and overriding what\n * differs:\n *\n * ```ts\n * const stripDiacritics = (value: string) =>\n * value.normalize('NFD').replace(/\\p{Diacritic}/gu, '')\n *\n * const alphanumericIgnoreDiacritics = constructSortFn({\n * ...sortFn_alphanumeric,\n * resolveDataValue: (value) =>\n * stripDiacritics(sortFn_alphanumeric.resolveDataValue!(value)),\n * })\n * ```\n */\nexport function constructSortFn<\n TFeatures extends TableFeatures = any,\n TData extends RowData = any,\n>(def: SortFnDef<TFeatures, TData>): CreatedSortFn<TFeatures, TData> {\n const sortFn: CreatedSortFn<TFeatures, TData> = Object.assign(\n <TRowFeatures extends TableFeatures, TRowData extends RowData>(\n rowA: Row<TRowFeatures, TRowData>,\n rowB: Row<TRowFeatures, TRowData>,\n columnId: string,\n ): number => {\n let dataValueA = rowA.getValue(columnId)\n let dataValueB = rowB.getValue(columnId)\n const resolveDataValue = sortFn.resolveDataValue\n if (resolveDataValue) {\n dataValueA = resolveDataValue(dataValueA)\n dataValueB = resolveDataValue(dataValueB)\n }\n // The def's comparator is typed against the factory's TFeatures/TData;\n // the caller's row generics are erased at this boundary.\n return sortFn.sort(\n dataValueA,\n dataValueB,\n rowA as any,\n rowB as any,\n columnId,\n )\n },\n def,\n )\n return sortFn\n}\n\n/**\n * Sorts rows with the built-in alphanumeric strategy.\n *\n * This comparator returns ascending-order results; descending order is applied by the sorting row model.\n */\nexport const sortFn_alphanumeric = constructSortFn({\n resolveDataValue: (dataValue) => toString(dataValue).toLowerCase(),\n sort: (dataValueA, dataValueB) => compareAlphanumeric(dataValueA, dataValueB),\n})\n\n/**\n * Sorts rows with the built-in alphanumeric case sensitive strategy.\n *\n * This comparator returns ascending-order results; descending order is applied by the sorting row model.\n */\nexport const sortFn_alphanumericCaseSensitive = constructSortFn({\n resolveDataValue: (dataValue) => toString(dataValue),\n sort: (dataValueA, dataValueB) => compareAlphanumeric(dataValueA, dataValueB),\n})\n\n// The text sort is more basic (less numeric support)\n// but is much faster\n/**\n * Sorts rows with the built-in text strategy.\n *\n * This comparator returns ascending-order results; descending order is applied by the sorting row model.\n */\nexport const sortFn_text = constructSortFn({\n resolveDataValue: (dataValue) => toString(dataValue).toLowerCase(),\n sort: (dataValueA, dataValueB) => compareBasic(dataValueA, dataValueB),\n})\n\n// The text sort is more basic (less numeric support)\n// but is much faster\n/**\n * Sorts rows with the built-in text case sensitive strategy.\n *\n * This comparator returns ascending-order results; descending order is applied by the sorting row model.\n */\nexport const sortFn_textCaseSensitive = constructSortFn({\n resolveDataValue: (dataValue) => toString(dataValue),\n sort: (dataValueA, dataValueB) => compareBasic(dataValueA, dataValueB),\n})\n\n/**\n * Sorts rows with the built-in datetime strategy.\n *\n * This comparator returns ascending-order results; descending order is applied by the sorting row model.\n */\nexport const sortFn_datetime = constructSortFn({\n resolveDataValue: (dataValue) => toDateSortValue(dataValue),\n // Can handle nullish values\n // Use > and < because == (and ===) doesn't work with\n // Date objects (would require calling getTime()).\n sort: (dataValueA, dataValueB) =>\n dataValueA > dataValueB ? 1 : dataValueA < dataValueB ? -1 : 0,\n})\n\n/**\n * Sorts rows with the built-in basic strategy.\n *\n * This comparator returns ascending-order results; descending order is applied by the sorting row model.\n */\nexport const sortFn_basic = constructSortFn({\n sort: (dataValueA, dataValueB) => compareBasic(dataValueA, dataValueB),\n})\n\n// Utils\n\nfunction compareBasic(a: any, b: any) {\n return a === b ? 0 : a > b ? 1 : -1\n}\n\nfunction toDateSortValue(value: any) {\n return value instanceof Date ? value.getTime() : value\n}\n\nfunction toString(a: any) {\n if (typeof a === 'number') {\n if (isNaN(a) || a === Infinity || a === -Infinity) {\n return ''\n }\n return String(a)\n }\n if (typeof a === 'string') {\n return a\n }\n return ''\n}\n\n// Mixed sorting is slow, but very inclusive of many edge cases.\n// It handles numbers, mixed alphanumeric combinations, and even\n// null, undefined, and Infinity\nfunction compareAlphanumeric(aStr: string, bStr: string) {\n let ai = 0\n let bi = 0\n const aLen = aStr.length\n const bLen = bStr.length\n\n while (ai < aLen && bi < bLen) {\n const aIsNumeric = isDigit(aStr.charCodeAt(ai))\n const bIsNumeric = isDigit(bStr.charCodeAt(bi))\n\n const aEnd = findChunkEnd(aStr, ai, aIsNumeric)\n const bEnd = findChunkEnd(bStr, bi, bIsNumeric)\n\n // Both are string chunks\n if (!aIsNumeric && !bIsNumeric) {\n const stringComparison = compareStringChunks(\n aStr,\n ai,\n aEnd,\n bStr,\n bi,\n bEnd,\n )\n if (stringComparison) {\n return stringComparison\n }\n ai = aEnd\n bi = bEnd\n continue\n }\n\n // One is a string chunk, one is a number chunk — the string sorts first\n if (aIsNumeric !== bIsNumeric) {\n return aIsNumeric ? 1 : -1\n }\n\n // Both are numeric chunks\n const numericComparison = compareNumericChunks(\n aStr,\n ai,\n aEnd,\n bStr,\n bi,\n bEnd,\n )\n if (numericComparison) {\n return numericComparison\n }\n\n ai = aEnd\n bi = bEnd\n }\n\n // One side is exhausted — compare the counts of remaining non-empty chunks\n return countRemainingChunks(aStr, ai) - countRemainingChunks(bStr, bi)\n}\n\nfunction isDigit(charCode: number) {\n return charCode >= 48 && charCode <= 57\n}\n\nfunction findChunkEnd(str: string, start: number, isNumeric: boolean) {\n let end = start + 1\n while (end < str.length && isDigit(str.charCodeAt(end)) === isNumeric) {\n end++\n }\n return end\n}\n\nfunction compareStringChunks(\n aStr: string,\n aStart: number,\n aEnd: number,\n bStr: string,\n bStart: number,\n bEnd: number,\n) {\n const aLength = aEnd - aStart\n const bLength = bEnd - bStart\n const minLength = aLength < bLength ? aLength : bLength\n\n for (let i = 0; i < minLength; i++) {\n const aCode = aStr.charCodeAt(aStart + i)\n const bCode = bStr.charCodeAt(bStart + i)\n\n if (aCode > bCode) {\n return 1\n }\n if (bCode > aCode) {\n return -1\n }\n }\n\n if (aLength > bLength) {\n return 1\n }\n if (bLength > aLength) {\n return -1\n }\n return 0\n}\n\nfunction compareNumericChunks(\n aStr: string,\n aStart: number,\n aEnd: number,\n bStr: string,\n bStart: number,\n bEnd: number,\n) {\n let aSignificantStart = aStart\n while (\n aSignificantStart < aEnd &&\n aStr.charCodeAt(aSignificantStart) === 48\n ) {\n aSignificantStart++\n }\n\n let bSignificantStart = bStart\n while (\n bSignificantStart < bEnd &&\n bStr.charCodeAt(bSignificantStart) === 48\n ) {\n bSignificantStart++\n }\n\n const aSignificantLength = aEnd - aSignificantStart\n const bSignificantLength = bEnd - bSignificantStart\n\n if (aSignificantLength === 0 && bSignificantLength === 0) {\n return 0\n }\n\n if (aSignificantLength <= 15 && bSignificantLength <= 15) {\n const an = parseSmallInt(aStr, aSignificantStart, aEnd)\n const bn = parseSmallInt(bStr, bSignificantStart, bEnd)\n\n if (an > bn) {\n return 1\n }\n if (bn > an) {\n return -1\n }\n return 0\n }\n\n // Preserve parseInt precision-collapse behavior for unusually large chunks.\n const an = parseInt(aStr.slice(aStart, aEnd), 10)\n const bn = parseInt(bStr.slice(bStart, bEnd), 10)\n\n if (an > bn) {\n return 1\n }\n if (bn > an) {\n return -1\n }\n return 0\n}\n\nfunction parseSmallInt(str: string, start: number, end: number) {\n let result = 0\n for (let i = start; i < end; i++) {\n result = result * 10 + str.charCodeAt(i) - 48\n }\n return result\n}\n\nfunction countRemainingChunks(str: string, start: number) {\n let count = 0\n let index = start\n\n while (index < str.length) {\n count++\n index = findChunkEnd(str, index, isDigit(str.charCodeAt(index)))\n }\n\n return count\n}\n\n// Exports\n\n/**\n * The built-in sorting function registry.\n *\n * Registering this full object opts out of tree-shaking: every built-in\n * sorting function ends up in your bundle. Prefer importing the `sortFn_*`\n * functions you actually use and registering just those in the `sortFns`\n * slot, or passing them directly to the `sortFn` column option.\n *\n * @deprecated Import individual `sortFn_*` functions instead for a smaller\n * bundle. This export still works and is not going away in v9, but built-in\n * name resolution (including `sortFn: 'auto'`) only finds functions you\n * register yourself.\n */\nexport const sortFns = {\n alphanumeric: sortFn_alphanumeric,\n alphanumericCaseSensitive: sortFn_alphanumericCaseSensitive,\n basic: sortFn_basic,\n datetime: sortFn_datetime,\n text: sortFn_text,\n textCaseSensitive: sortFn_textCaseSensitive,\n}\n\nexport type BuiltInSortFn = keyof typeof sortFns\n"],"mappings":"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"}
|
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
import { RowData } from "../../types/type-utils.cjs";
|
|
2
|
+
import { CreatedSortFn, SortFnDef } from "./rowSortingFeature.types.cjs";
|
|
3
|
+
import { TableFeatures } from "../../types/TableFeatures.cjs";
|
|
4
|
+
|
|
5
|
+
//#region src/features/row-sorting/sortFns.d.ts
|
|
6
|
+
/**
|
|
7
|
+
* Regular expression used to split mixed text and numeric chunks.
|
|
8
|
+
*
|
|
9
|
+
* The alphanumeric sort functions use these chunks for natural sorting of
|
|
10
|
+
* strings like `item2` before `item10`.
|
|
11
|
+
*/
|
|
12
|
+
declare const reSplitAlphaNumeric: RegExp;
|
|
13
|
+
/**
|
|
14
|
+
* Builds a `SortFn` from a value-level comparator plus an optional
|
|
15
|
+
* `resolveDataValue` normalizer.
|
|
16
|
+
*
|
|
17
|
+
* The `sort` comparator receives both rows' data values, each already passed
|
|
18
|
+
* through `resolveDataValue` when one is defined. Keeping normalization in the
|
|
19
|
+
* resolver means a variant of an existing sorting function only has to swap
|
|
20
|
+
* the resolver, not re-implement the comparison.
|
|
21
|
+
*
|
|
22
|
+
* The definition is attached to the returned function, so a variant can be
|
|
23
|
+
* created by spreading a built-in sorting function and overriding what
|
|
24
|
+
* differs:
|
|
25
|
+
*
|
|
26
|
+
* ```ts
|
|
27
|
+
* const stripDiacritics = (value: string) =>
|
|
28
|
+
* value.normalize('NFD').replace(/\p{Diacritic}/gu, '')
|
|
29
|
+
*
|
|
30
|
+
* const alphanumericIgnoreDiacritics = constructSortFn({
|
|
31
|
+
* ...sortFn_alphanumeric,
|
|
32
|
+
* resolveDataValue: (value) =>
|
|
33
|
+
* stripDiacritics(sortFn_alphanumeric.resolveDataValue!(value)),
|
|
34
|
+
* })
|
|
35
|
+
* ```
|
|
36
|
+
*/
|
|
37
|
+
declare function constructSortFn<TFeatures extends TableFeatures = any, TData extends RowData = any>(def: SortFnDef<TFeatures, TData>): CreatedSortFn<TFeatures, TData>;
|
|
38
|
+
/**
|
|
39
|
+
* Sorts rows with the built-in alphanumeric strategy.
|
|
40
|
+
*
|
|
41
|
+
* This comparator returns ascending-order results; descending order is applied by the sorting row model.
|
|
42
|
+
*/
|
|
43
|
+
declare const sortFn_alphanumeric: CreatedSortFn<any, any>;
|
|
44
|
+
/**
|
|
45
|
+
* Sorts rows with the built-in alphanumeric case sensitive strategy.
|
|
46
|
+
*
|
|
47
|
+
* This comparator returns ascending-order results; descending order is applied by the sorting row model.
|
|
48
|
+
*/
|
|
49
|
+
declare const sortFn_alphanumericCaseSensitive: CreatedSortFn<any, any>;
|
|
50
|
+
/**
|
|
51
|
+
* Sorts rows with the built-in text strategy.
|
|
52
|
+
*
|
|
53
|
+
* This comparator returns ascending-order results; descending order is applied by the sorting row model.
|
|
54
|
+
*/
|
|
55
|
+
declare const sortFn_text: CreatedSortFn<any, any>;
|
|
56
|
+
/**
|
|
57
|
+
* Sorts rows with the built-in text case sensitive strategy.
|
|
58
|
+
*
|
|
59
|
+
* This comparator returns ascending-order results; descending order is applied by the sorting row model.
|
|
60
|
+
*/
|
|
61
|
+
declare const sortFn_textCaseSensitive: CreatedSortFn<any, any>;
|
|
62
|
+
/**
|
|
63
|
+
* Sorts rows with the built-in datetime strategy.
|
|
64
|
+
*
|
|
65
|
+
* This comparator returns ascending-order results; descending order is applied by the sorting row model.
|
|
66
|
+
*/
|
|
67
|
+
declare const sortFn_datetime: CreatedSortFn<any, any>;
|
|
68
|
+
/**
|
|
69
|
+
* Sorts rows with the built-in basic strategy.
|
|
70
|
+
*
|
|
71
|
+
* This comparator returns ascending-order results; descending order is applied by the sorting row model.
|
|
72
|
+
*/
|
|
73
|
+
declare const sortFn_basic: CreatedSortFn<any, any>;
|
|
74
|
+
/**
|
|
75
|
+
* The built-in sorting function registry.
|
|
76
|
+
*
|
|
77
|
+
* Registering this full object opts out of tree-shaking: every built-in
|
|
78
|
+
* sorting function ends up in your bundle. Prefer importing the `sortFn_*`
|
|
79
|
+
* functions you actually use and registering just those in the `sortFns`
|
|
80
|
+
* slot, or passing them directly to the `sortFn` column option.
|
|
81
|
+
*
|
|
82
|
+
* @deprecated Import individual `sortFn_*` functions instead for a smaller
|
|
83
|
+
* bundle. This export still works and is not going away in v9, but built-in
|
|
84
|
+
* name resolution (including `sortFn: 'auto'`) only finds functions you
|
|
85
|
+
* register yourself.
|
|
86
|
+
*/
|
|
87
|
+
declare const sortFns: {
|
|
88
|
+
alphanumeric: CreatedSortFn<any, any>;
|
|
89
|
+
alphanumericCaseSensitive: CreatedSortFn<any, any>;
|
|
90
|
+
basic: CreatedSortFn<any, any>;
|
|
91
|
+
datetime: CreatedSortFn<any, any>;
|
|
92
|
+
text: CreatedSortFn<any, any>;
|
|
93
|
+
textCaseSensitive: CreatedSortFn<any, any>;
|
|
94
|
+
};
|
|
95
|
+
type BuiltInSortFn = keyof typeof sortFns;
|
|
96
|
+
//#endregion
|
|
97
|
+
export { BuiltInSortFn, constructSortFn, reSplitAlphaNumeric, sortFn_alphanumeric, sortFn_alphanumericCaseSensitive, sortFn_basic, sortFn_datetime, sortFn_text, sortFn_textCaseSensitive, sortFns };
|
|
98
|
+
//# sourceMappingURL=sortFns.d.cts.map
|