@tanstack/table-core 9.0.0-beta.28 → 9.0.0-beta.30
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/features/column-filtering/columnFilteringFeature.utils.cjs +1 -1
- package/dist/features/column-filtering/columnFilteringFeature.utils.cjs.map +1 -1
- package/dist/features/column-filtering/columnFilteringFeature.utils.js +1 -1
- package/dist/features/column-filtering/columnFilteringFeature.utils.js.map +1 -1
- package/dist/features/global-filtering/globalFilteringFeature.utils.d.cts +1 -0
- package/dist/features/global-filtering/globalFilteringFeature.utils.d.ts +1 -0
- package/dist/features/row-sorting/createSortedRowModel.cjs +41 -34
- package/dist/features/row-sorting/createSortedRowModel.cjs.map +1 -1
- package/dist/features/row-sorting/createSortedRowModel.js +42 -35
- package/dist/features/row-sorting/createSortedRowModel.js.map +1 -1
- package/dist/fns/aggregationFns.cjs +21 -19
- package/dist/fns/aggregationFns.cjs.map +1 -1
- package/dist/fns/aggregationFns.js +21 -19
- package/dist/fns/aggregationFns.js.map +1 -1
- package/dist/fns/filterFns.cjs +59 -14
- package/dist/fns/filterFns.cjs.map +1 -1
- package/dist/fns/filterFns.d.cts +11 -4
- package/dist/fns/filterFns.d.ts +11 -4
- package/dist/fns/filterFns.js +59 -14
- package/dist/fns/filterFns.js.map +1 -1
- package/dist/fns/sortFns.cjs +77 -28
- package/dist/fns/sortFns.cjs.map +1 -1
- package/dist/fns/sortFns.js +77 -28
- package/dist/fns/sortFns.js.map +1 -1
- package/package.json +1 -1
- package/src/features/column-filtering/columnFilteringFeature.utils.ts +4 -4
- package/src/features/row-sorting/createSortedRowModel.ts +65 -55
- package/src/fns/aggregationFns.ts +19 -19
- package/src/fns/filterFns.ts +96 -32
- package/src/fns/sortFns.ts +158 -46
|
@@ -34,8 +34,8 @@ function column_getAutoFilterFn(column) {
|
|
|
34
34
|
if (typeof value === "string") return filterFns === null || filterFns === void 0 ? void 0 : filterFns.includesString;
|
|
35
35
|
if (typeof value === "number") return filterFns === null || filterFns === void 0 ? void 0 : filterFns.inNumberRange;
|
|
36
36
|
if (typeof value === "boolean") return filterFns === null || filterFns === void 0 ? void 0 : filterFns.equals;
|
|
37
|
-
if (value !== null && typeof value === "object") return filterFns === null || filterFns === void 0 ? void 0 : filterFns.equals;
|
|
38
37
|
if (Array.isArray(value)) return filterFns === null || filterFns === void 0 ? void 0 : filterFns.arrIncludes;
|
|
38
|
+
if (value !== null && typeof value === "object") return filterFns === null || filterFns === void 0 ? void 0 : filterFns.equals;
|
|
39
39
|
return filterFns === null || filterFns === void 0 ? void 0 : filterFns.weakEquals;
|
|
40
40
|
}
|
|
41
41
|
/**
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"columnFilteringFeature.utils.cjs","names":["isFunction","functionalUpdate","cloneState"],"sources":["../../../src/features/column-filtering/columnFilteringFeature.utils.ts"],"sourcesContent":["import { cloneState, functionalUpdate, 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 ColumnFiltersState,\n FilterFn,\n} from './columnFilteringFeature.types'\n\n/**\n * Creates the default column filter state.\n *\n * The feature default is an empty array, meaning no column filters are active.\n * Reset APIs use this value when `defaultState` is `true`.\n *\n * @example\n * ```ts\n * const filters = getDefaultColumnFiltersState()\n * ```\n */\nexport function getDefaultColumnFiltersState(): ColumnFiltersState {\n return []\n}\n\n/**\n * Chooses a built-in filter function from the column's first core row value.\n *\n * Strings use `includesString`, numbers use `inNumberRange`, booleans and\n * objects use `equals`, arrays use `arrIncludes`, and unknown values fall back\n * to `weakEquals`.\n *\n * @example\n * ```ts\n * const filterFn = column_getAutoFilterFn(column)\n * ```\n */\nexport function column_getAutoFilterFn<\n TFeatures extends TableFeatures,\n TData extends RowData,\n TValue extends CellData = CellData,\n>(column: Column_Internal<TFeatures, TData, TValue>) {\n const filterFns: Record<string, FilterFn<TFeatures, TData>> | undefined =\n column.table._rowModelFns.filterFns\n\n const firstRow = column.table.getCoreRowModel().flatRows[0]\n\n const value = firstRow ? firstRow.getValue(column.id) : undefined\n\n if (typeof value === 'string') {\n return filterFns?.includesString\n }\n\n if (typeof value === 'number') {\n return filterFns?.inNumberRange\n }\n\n if (typeof value === 'boolean') {\n return filterFns?.equals\n }\n\n if (value !== null && typeof value === 'object') {\n return filterFns?.equals\n }\n\n if (Array.isArray(value)) {\n return filterFns?.arrIncludes\n }\n\n return filterFns?.weakEquals\n}\n\n/**\n * Resolves the filter function configured for a column.\n *\n * Function-valued `columnDef.filterFn` is returned directly, `'auto'` delegates\n * to `column_getAutoFilterFn`, and string values are looked up in the table's\n * filter function registry.\n *\n * @example\n * ```ts\n * const filterFn = column_getFilterFn(column)\n * ```\n */\nexport function column_getFilterFn<\n TFeatures extends TableFeatures,\n TData extends RowData,\n TValue extends CellData = CellData,\n>(\n column: Column_Internal<TFeatures, TData, TValue>,\n): FilterFn<TFeatures, TData> | undefined {\n let filterFn = null\n const filterFns: Record<string, FilterFn<TFeatures, TData>> | undefined =\n column.table._rowModelFns.filterFns\n filterFn = isFunction(column.columnDef.filterFn)\n ? column.columnDef.filterFn\n : column.columnDef.filterFn === 'auto'\n ? column_getAutoFilterFn(column)\n : filterFns?.[column.columnDef.filterFn as string]\n\n if (process.env.NODE_ENV === 'development' && !filterFn) {\n console.warn(\n `Could not find a valid 'column.filterFn' for column with the ID: ${column.id}.`,\n )\n }\n\n return filterFn ?? undefined\n}\n\n/**\n * Checks whether column filtering is enabled for this accessor column.\n *\n * The column must have an accessor and filtering must be enabled by the column\n * definition, `enableColumnFilters`, and the table-wide `enableFilters` option.\n *\n * @example\n * ```ts\n * const canFilter = column_getCanFilter(column)\n * ```\n */\nexport function column_getCanFilter<\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.enableColumnFilter ?? true) &&\n (column.table.options.enableColumnFilters ?? true) &&\n (column.table.options.enableFilters ?? true) &&\n !!column.accessorFn\n )\n}\n\n/**\n * Checks whether this column currently has an entry in `state.columnFilters`.\n *\n * This only reflects filter state presence; it does not indicate whether the\n * filter removes any rows.\n *\n * @example\n * ```ts\n * const isFiltered = column_getIsFiltered(column)\n * ```\n */\nexport function column_getIsFiltered<\n TFeatures extends TableFeatures,\n TData extends RowData,\n TValue extends CellData = CellData,\n>(column: Column_Internal<TFeatures, TData, TValue>) {\n return column_getFilterIndex(column) > -1\n}\n\n/**\n * Reads this column's current filter value from `state.columnFilters`.\n *\n * Missing filter entries return `undefined`.\n *\n * @example\n * ```ts\n * const value = column_getFilterValue(column)\n * ```\n */\nexport function column_getFilterValue<\n TFeatures extends TableFeatures,\n TData extends RowData,\n TValue extends CellData = CellData,\n>(column: Column_Internal<TFeatures, TData, TValue>) {\n return column.table.atoms.columnFilters\n ?.get()\n ?.find((d) => d.id === column.id)?.value\n}\n\n/**\n * Finds this column's position in the ordered `state.columnFilters` array.\n *\n * The result is `-1` when the column has no active filter.\n *\n * @example\n * ```ts\n * const index = column_getFilterIndex(column)\n * ```\n */\nexport function column_getFilterIndex<\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.columnFilters\n ?.get()\n ?.findIndex((d) => d.id === column.id) ?? -1\n )\n}\n\n/**\n * Adds, updates, or removes this column's filter value.\n *\n * The incoming value may be an updater. After resolution, `autoRemove` rules\n * decide whether the filter should be removed instead of stored.\n *\n * @example\n * ```ts\n * column_setFilterValue(column, (old) => String(old ?? '').trim())\n * ```\n */\nexport function column_setFilterValue<\n TFeatures extends TableFeatures,\n TData extends RowData,\n TValue extends CellData = CellData,\n>(column: Column_Internal<TFeatures, TData, TValue>, value: any) {\n table_setColumnFilters(column.table, (old) => {\n const filterFn = column_getFilterFn(column)\n const previousFilter = old.find((d) => d.id === column.id)\n\n const newFilter = functionalUpdate(\n value,\n previousFilter ? previousFilter.value : undefined,\n )\n\n if (shouldAutoRemoveFilter(filterFn, newFilter, column)) {\n return old.filter((d) => d.id !== column.id)\n }\n\n const newFilterObj = { id: column.id, value: newFilter }\n\n if (previousFilter) {\n return old.map((d) => {\n if (d.id === column.id) {\n return newFilterObj\n }\n return d\n })\n }\n\n if (old.length) {\n return [...old, newFilterObj]\n }\n\n return [newFilterObj]\n })\n}\n\n/**\n * Routes a column filter updater through the table's filter change handler.\n *\n * The resolved filters are cleaned before they are emitted: filters for known\n * columns are removed when their filter function says the value should be\n * auto-removed.\n *\n * @example\n * ```ts\n * table_setColumnFilters(table, (old) => old.filter((filter) => filter.id !== 'age'))\n * ```\n */\nexport function table_setColumnFilters<\n TFeatures extends TableFeatures,\n TData extends RowData,\n>(\n table: Table_Internal<TFeatures, TData>,\n updater: Updater<ColumnFiltersState>,\n) {\n const leafColumnsById = table.getAllLeafColumnsById()\n\n const updateFn = (old: ColumnFiltersState) => {\n return functionalUpdate(updater, old).filter((filter) => {\n const column = leafColumnsById[filter.id]\n\n if (column) {\n const filterFn = column_getFilterFn(column)\n\n if (shouldAutoRemoveFilter(filterFn, filter.value, column)) {\n return false\n }\n }\n\n return true\n })\n }\n\n table.options.onColumnFiltersChange?.(updateFn)\n}\n\n/**\n * Resets `columnFilters` to the configured initial state or feature default.\n *\n * With no argument, the reset clones `table.initialState.columnFilters` when it\n * exists. Passing `true` ignores initial state and resets to `[]`.\n *\n * @example\n * ```ts\n * table_resetColumnFilters(table)\n * table_resetColumnFilters(table, true)\n * ```\n */\nexport function table_resetColumnFilters<\n TFeatures extends TableFeatures,\n TData extends RowData,\n>(table: Table_Internal<TFeatures, TData>, defaultState?: boolean) {\n table_setColumnFilters(\n table,\n defaultState ? [] : cloneState(table.initialState.columnFilters ?? []),\n )\n}\n\n/**\n * Returns whether a filter value should be removed from filter state.\n *\n * This checks the filter function's `autoRemove` hook and built-in empty-value rules.\n *\n * @example\n * ```ts\n * const removeFilter = shouldAutoRemoveFilter(filterFn, value, column)\n * ```\n */\nexport function shouldAutoRemoveFilter<\n TFeatures extends TableFeatures,\n TData extends RowData,\n TValue extends CellData = CellData,\n>(\n filterFn?: FilterFn<TFeatures, TData>,\n value?: any,\n column?: Column_Internal<TFeatures, TData, TValue>,\n) {\n return (\n (filterFn && filterFn.autoRemove\n ? filterFn.autoRemove(value, column as any)\n : false) ||\n typeof value === 'undefined' ||\n (typeof value === 'string' && !value)\n )\n}\n"],"mappings":";;;;;;;;;;;;;;AAqBA,SAAgB,+BAAmD;CACjE,OAAO,CAAC;AACV;;;;;;;;;;;;;AAcA,SAAgB,uBAId,QAAmD;CACnD,MAAM,YACJ,OAAO,MAAM,aAAa;CAE5B,MAAM,WAAW,OAAO,MAAM,gBAAgB,CAAC,CAAC,SAAS;CAEzD,MAAM,QAAQ,WAAW,SAAS,SAAS,OAAO,EAAE,IAAI;CAExD,IAAI,OAAO,UAAU,UACnB,6DAAO,UAAW;CAGpB,IAAI,OAAO,UAAU,UACnB,6DAAO,UAAW;CAGpB,IAAI,OAAO,UAAU,WACnB,6DAAO,UAAW;CAGpB,IAAI,UAAU,QAAQ,OAAO,UAAU,UACrC,6DAAO,UAAW;CAGpB,IAAI,MAAM,QAAQ,KAAK,GACrB,6DAAO,UAAW;CAGpB,6DAAO,UAAW;AACpB;;;;;;;;;;;;;AAcA,SAAgB,mBAKd,QACwC;CACxC,IAAI,WAAW;CACf,MAAM,YACJ,OAAO,MAAM,aAAa;CAC5B,WAAWA,yBAAW,OAAO,UAAU,QAAQ,IAC3C,OAAO,UAAU,WACjB,OAAO,UAAU,aAAa,SAC5B,uBAAuB,MAAM,0DAC7B,UAAY,OAAO,UAAU;CAEnC,IAAI,QAAQ,IAAI,aAAa,iBAAiB,CAAC,UAC7C,QAAQ,KACN,oEAAoE,OAAO,GAAG,EAChF;CAGF,OAAO,YAAY;AACrB;;;;;;;;;;;;AAaA,SAAgB,oBAId,QAAmD;CACnD,QACG,OAAO,UAAU,sBAAsB,UACvC,OAAO,MAAM,QAAQ,uBAAuB,UAC5C,OAAO,MAAM,QAAQ,iBAAiB,SACvC,CAAC,CAAC,OAAO;AAEb;;;;;;;;;;;;AAaA,SAAgB,qBAId,QAAmD;CACnD,OAAO,sBAAsB,MAAM,IAAI;AACzC;;;;;;;;;;;AAYA,SAAgB,sBAId,QAAmD;;CACnD,gCAAO,OAAO,MAAM,MAAM,8GACtB,IAAI,kGACJ,MAAM,MAAM,EAAE,OAAO,OAAO,EAAE,iFAAG;AACvC;;;;;;;;;;;AAYA,SAAgB,sBAId,QAA2D;;CAC3D,kCACE,OAAO,MAAM,MAAM,iHACf,IAAI,mFACJ,WAAW,MAAM,EAAE,OAAO,OAAO,EAAE,MAAK;AAEhD;;;;;;;;;;;;AAaA,SAAgB,sBAId,QAAmD,OAAY;CAC/D,uBAAuB,OAAO,QAAQ,QAAQ;EAC5C,MAAM,WAAW,mBAAmB,MAAM;EAC1C,MAAM,iBAAiB,IAAI,MAAM,MAAM,EAAE,OAAO,OAAO,EAAE;EAEzD,MAAM,YAAYC,+BAChB,OACA,iBAAiB,eAAe,QAAQ,MAC1C;EAEA,IAAI,uBAAuB,UAAU,WAAW,MAAM,GACpD,OAAO,IAAI,QAAQ,MAAM,EAAE,OAAO,OAAO,EAAE;EAG7C,MAAM,eAAe;GAAE,IAAI,OAAO;GAAI,OAAO;EAAU;EAEvD,IAAI,gBACF,OAAO,IAAI,KAAK,MAAM;GACpB,IAAI,EAAE,OAAO,OAAO,IAClB,OAAO;GAET,OAAO;EACT,CAAC;EAGH,IAAI,IAAI,QACN,OAAO,CAAC,GAAG,KAAK,YAAY;EAG9B,OAAO,CAAC,YAAY;CACtB,CAAC;AACH;;;;;;;;;;;;;AAcA,SAAgB,uBAId,OACA,SACA;;CACA,MAAM,kBAAkB,MAAM,sBAAsB;CAEpD,MAAM,YAAY,QAA4B;EAC5C,OAAOA,+BAAiB,SAAS,GAAG,CAAC,CAAC,QAAQ,WAAW;GACvD,MAAM,SAAS,gBAAgB,OAAO;GAEtC,IAAI,QAGF;QAAI,uBAFa,mBAAmB,MAEF,GAAG,OAAO,OAAO,MAAM,GACvD,OAAO;GACT;GAGF,OAAO;EACT,CAAC;CACH;CAEA,iDAAM,SAAQ,kHAAwB,QAAQ;AAChD;;;;;;;;;;;;;AAcA,SAAgB,yBAGd,OAAyC,cAAwB;CACjE,uBACE,OACA,eAAe,CAAC,IAAIC,yBAAW,MAAM,aAAa,iBAAiB,CAAC,CAAC,CACvE;AACF;;;;;;;;;;;AAYA,SAAgB,uBAKd,UACA,OACA,QACA;CACA,QACG,YAAY,SAAS,aAClB,SAAS,WAAW,OAAO,MAAa,IACxC,UACJ,OAAO,UAAU,eAChB,OAAO,UAAU,YAAY,CAAC;AAEnC"}
|
|
1
|
+
{"version":3,"file":"columnFilteringFeature.utils.cjs","names":["isFunction","functionalUpdate","cloneState"],"sources":["../../../src/features/column-filtering/columnFilteringFeature.utils.ts"],"sourcesContent":["import { cloneState, functionalUpdate, 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 ColumnFiltersState,\n FilterFn,\n} from './columnFilteringFeature.types'\n\n/**\n * Creates the default column filter state.\n *\n * The feature default is an empty array, meaning no column filters are active.\n * Reset APIs use this value when `defaultState` is `true`.\n *\n * @example\n * ```ts\n * const filters = getDefaultColumnFiltersState()\n * ```\n */\nexport function getDefaultColumnFiltersState(): ColumnFiltersState {\n return []\n}\n\n/**\n * Chooses a built-in filter function from the column's first core row value.\n *\n * Strings use `includesString`, numbers use `inNumberRange`, booleans and\n * objects use `equals`, arrays use `arrIncludes`, and unknown values fall back\n * to `weakEquals`.\n *\n * @example\n * ```ts\n * const filterFn = column_getAutoFilterFn(column)\n * ```\n */\nexport function column_getAutoFilterFn<\n TFeatures extends TableFeatures,\n TData extends RowData,\n TValue extends CellData = CellData,\n>(column: Column_Internal<TFeatures, TData, TValue>) {\n const filterFns: Record<string, FilterFn<TFeatures, TData>> | undefined =\n column.table._rowModelFns.filterFns\n\n const firstRow = column.table.getCoreRowModel().flatRows[0]\n\n const value = firstRow ? firstRow.getValue(column.id) : undefined\n\n if (typeof value === 'string') {\n return filterFns?.includesString\n }\n\n if (typeof value === 'number') {\n return filterFns?.inNumberRange\n }\n\n if (typeof value === 'boolean') {\n return filterFns?.equals\n }\n\n if (Array.isArray(value)) {\n return filterFns?.arrIncludes\n }\n\n if (value !== null && typeof value === 'object') {\n return filterFns?.equals\n }\n\n return filterFns?.weakEquals\n}\n\n/**\n * Resolves the filter function configured for a column.\n *\n * Function-valued `columnDef.filterFn` is returned directly, `'auto'` delegates\n * to `column_getAutoFilterFn`, and string values are looked up in the table's\n * filter function registry.\n *\n * @example\n * ```ts\n * const filterFn = column_getFilterFn(column)\n * ```\n */\nexport function column_getFilterFn<\n TFeatures extends TableFeatures,\n TData extends RowData,\n TValue extends CellData = CellData,\n>(\n column: Column_Internal<TFeatures, TData, TValue>,\n): FilterFn<TFeatures, TData> | undefined {\n let filterFn = null\n const filterFns: Record<string, FilterFn<TFeatures, TData>> | undefined =\n column.table._rowModelFns.filterFns\n filterFn = isFunction(column.columnDef.filterFn)\n ? column.columnDef.filterFn\n : column.columnDef.filterFn === 'auto'\n ? column_getAutoFilterFn(column)\n : filterFns?.[column.columnDef.filterFn as string]\n\n if (process.env.NODE_ENV === 'development' && !filterFn) {\n console.warn(\n `Could not find a valid 'column.filterFn' for column with the ID: ${column.id}.`,\n )\n }\n\n return filterFn ?? undefined\n}\n\n/**\n * Checks whether column filtering is enabled for this accessor column.\n *\n * The column must have an accessor and filtering must be enabled by the column\n * definition, `enableColumnFilters`, and the table-wide `enableFilters` option.\n *\n * @example\n * ```ts\n * const canFilter = column_getCanFilter(column)\n * ```\n */\nexport function column_getCanFilter<\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.enableColumnFilter ?? true) &&\n (column.table.options.enableColumnFilters ?? true) &&\n (column.table.options.enableFilters ?? true) &&\n !!column.accessorFn\n )\n}\n\n/**\n * Checks whether this column currently has an entry in `state.columnFilters`.\n *\n * This only reflects filter state presence; it does not indicate whether the\n * filter removes any rows.\n *\n * @example\n * ```ts\n * const isFiltered = column_getIsFiltered(column)\n * ```\n */\nexport function column_getIsFiltered<\n TFeatures extends TableFeatures,\n TData extends RowData,\n TValue extends CellData = CellData,\n>(column: Column_Internal<TFeatures, TData, TValue>) {\n return column_getFilterIndex(column) > -1\n}\n\n/**\n * Reads this column's current filter value from `state.columnFilters`.\n *\n * Missing filter entries return `undefined`.\n *\n * @example\n * ```ts\n * const value = column_getFilterValue(column)\n * ```\n */\nexport function column_getFilterValue<\n TFeatures extends TableFeatures,\n TData extends RowData,\n TValue extends CellData = CellData,\n>(column: Column_Internal<TFeatures, TData, TValue>) {\n return column.table.atoms.columnFilters\n ?.get()\n ?.find((d) => d.id === column.id)?.value\n}\n\n/**\n * Finds this column's position in the ordered `state.columnFilters` array.\n *\n * The result is `-1` when the column has no active filter.\n *\n * @example\n * ```ts\n * const index = column_getFilterIndex(column)\n * ```\n */\nexport function column_getFilterIndex<\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.columnFilters\n ?.get()\n ?.findIndex((d) => d.id === column.id) ?? -1\n )\n}\n\n/**\n * Adds, updates, or removes this column's filter value.\n *\n * The incoming value may be an updater. After resolution, `autoRemove` rules\n * decide whether the filter should be removed instead of stored.\n *\n * @example\n * ```ts\n * column_setFilterValue(column, (old) => String(old ?? '').trim())\n * ```\n */\nexport function column_setFilterValue<\n TFeatures extends TableFeatures,\n TData extends RowData,\n TValue extends CellData = CellData,\n>(column: Column_Internal<TFeatures, TData, TValue>, value: any) {\n table_setColumnFilters(column.table, (old) => {\n const filterFn = column_getFilterFn(column)\n const previousFilter = old.find((d) => d.id === column.id)\n\n const newFilter = functionalUpdate(\n value,\n previousFilter ? previousFilter.value : undefined,\n )\n\n if (shouldAutoRemoveFilter(filterFn, newFilter, column)) {\n return old.filter((d) => d.id !== column.id)\n }\n\n const newFilterObj = { id: column.id, value: newFilter }\n\n if (previousFilter) {\n return old.map((d) => {\n if (d.id === column.id) {\n return newFilterObj\n }\n return d\n })\n }\n\n if (old.length) {\n return [...old, newFilterObj]\n }\n\n return [newFilterObj]\n })\n}\n\n/**\n * Routes a column filter updater through the table's filter change handler.\n *\n * The resolved filters are cleaned before they are emitted: filters for known\n * columns are removed when their filter function says the value should be\n * auto-removed.\n *\n * @example\n * ```ts\n * table_setColumnFilters(table, (old) => old.filter((filter) => filter.id !== 'age'))\n * ```\n */\nexport function table_setColumnFilters<\n TFeatures extends TableFeatures,\n TData extends RowData,\n>(\n table: Table_Internal<TFeatures, TData>,\n updater: Updater<ColumnFiltersState>,\n) {\n const leafColumnsById = table.getAllLeafColumnsById()\n\n const updateFn = (old: ColumnFiltersState) => {\n return functionalUpdate(updater, old).filter((filter) => {\n const column = leafColumnsById[filter.id]\n\n if (column) {\n const filterFn = column_getFilterFn(column)\n\n if (shouldAutoRemoveFilter(filterFn, filter.value, column)) {\n return false\n }\n }\n\n return true\n })\n }\n\n table.options.onColumnFiltersChange?.(updateFn)\n}\n\n/**\n * Resets `columnFilters` to the configured initial state or feature default.\n *\n * With no argument, the reset clones `table.initialState.columnFilters` when it\n * exists. Passing `true` ignores initial state and resets to `[]`.\n *\n * @example\n * ```ts\n * table_resetColumnFilters(table)\n * table_resetColumnFilters(table, true)\n * ```\n */\nexport function table_resetColumnFilters<\n TFeatures extends TableFeatures,\n TData extends RowData,\n>(table: Table_Internal<TFeatures, TData>, defaultState?: boolean) {\n table_setColumnFilters(\n table,\n defaultState ? [] : cloneState(table.initialState.columnFilters ?? []),\n )\n}\n\n/**\n * Returns whether a filter value should be removed from filter state.\n *\n * This checks the filter function's `autoRemove` hook and built-in empty-value rules.\n *\n * @example\n * ```ts\n * const removeFilter = shouldAutoRemoveFilter(filterFn, value, column)\n * ```\n */\nexport function shouldAutoRemoveFilter<\n TFeatures extends TableFeatures,\n TData extends RowData,\n TValue extends CellData = CellData,\n>(\n filterFn?: FilterFn<TFeatures, TData>,\n value?: any,\n column?: Column_Internal<TFeatures, TData, TValue>,\n) {\n return (\n (filterFn && filterFn.autoRemove\n ? filterFn.autoRemove(value, column as any)\n : false) ||\n typeof value === 'undefined' ||\n (typeof value === 'string' && !value)\n )\n}\n"],"mappings":"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"}
|
|
@@ -34,8 +34,8 @@ function column_getAutoFilterFn(column) {
|
|
|
34
34
|
if (typeof value === "string") return filterFns === null || filterFns === void 0 ? void 0 : filterFns.includesString;
|
|
35
35
|
if (typeof value === "number") return filterFns === null || filterFns === void 0 ? void 0 : filterFns.inNumberRange;
|
|
36
36
|
if (typeof value === "boolean") return filterFns === null || filterFns === void 0 ? void 0 : filterFns.equals;
|
|
37
|
-
if (value !== null && typeof value === "object") return filterFns === null || filterFns === void 0 ? void 0 : filterFns.equals;
|
|
38
37
|
if (Array.isArray(value)) return filterFns === null || filterFns === void 0 ? void 0 : filterFns.arrIncludes;
|
|
38
|
+
if (value !== null && typeof value === "object") return filterFns === null || filterFns === void 0 ? void 0 : filterFns.equals;
|
|
39
39
|
return filterFns === null || filterFns === void 0 ? void 0 : filterFns.weakEquals;
|
|
40
40
|
}
|
|
41
41
|
/**
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"columnFilteringFeature.utils.js","names":[],"sources":["../../../src/features/column-filtering/columnFilteringFeature.utils.ts"],"sourcesContent":["import { cloneState, functionalUpdate, 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 ColumnFiltersState,\n FilterFn,\n} from './columnFilteringFeature.types'\n\n/**\n * Creates the default column filter state.\n *\n * The feature default is an empty array, meaning no column filters are active.\n * Reset APIs use this value when `defaultState` is `true`.\n *\n * @example\n * ```ts\n * const filters = getDefaultColumnFiltersState()\n * ```\n */\nexport function getDefaultColumnFiltersState(): ColumnFiltersState {\n return []\n}\n\n/**\n * Chooses a built-in filter function from the column's first core row value.\n *\n * Strings use `includesString`, numbers use `inNumberRange`, booleans and\n * objects use `equals`, arrays use `arrIncludes`, and unknown values fall back\n * to `weakEquals`.\n *\n * @example\n * ```ts\n * const filterFn = column_getAutoFilterFn(column)\n * ```\n */\nexport function column_getAutoFilterFn<\n TFeatures extends TableFeatures,\n TData extends RowData,\n TValue extends CellData = CellData,\n>(column: Column_Internal<TFeatures, TData, TValue>) {\n const filterFns: Record<string, FilterFn<TFeatures, TData>> | undefined =\n column.table._rowModelFns.filterFns\n\n const firstRow = column.table.getCoreRowModel().flatRows[0]\n\n const value = firstRow ? firstRow.getValue(column.id) : undefined\n\n if (typeof value === 'string') {\n return filterFns?.includesString\n }\n\n if (typeof value === 'number') {\n return filterFns?.inNumberRange\n }\n\n if (typeof value === 'boolean') {\n return filterFns?.equals\n }\n\n if (value !== null && typeof value === 'object') {\n return filterFns?.equals\n }\n\n if (Array.isArray(value)) {\n return filterFns?.arrIncludes\n }\n\n return filterFns?.weakEquals\n}\n\n/**\n * Resolves the filter function configured for a column.\n *\n * Function-valued `columnDef.filterFn` is returned directly, `'auto'` delegates\n * to `column_getAutoFilterFn`, and string values are looked up in the table's\n * filter function registry.\n *\n * @example\n * ```ts\n * const filterFn = column_getFilterFn(column)\n * ```\n */\nexport function column_getFilterFn<\n TFeatures extends TableFeatures,\n TData extends RowData,\n TValue extends CellData = CellData,\n>(\n column: Column_Internal<TFeatures, TData, TValue>,\n): FilterFn<TFeatures, TData> | undefined {\n let filterFn = null\n const filterFns: Record<string, FilterFn<TFeatures, TData>> | undefined =\n column.table._rowModelFns.filterFns\n filterFn = isFunction(column.columnDef.filterFn)\n ? column.columnDef.filterFn\n : column.columnDef.filterFn === 'auto'\n ? column_getAutoFilterFn(column)\n : filterFns?.[column.columnDef.filterFn as string]\n\n if (process.env.NODE_ENV === 'development' && !filterFn) {\n console.warn(\n `Could not find a valid 'column.filterFn' for column with the ID: ${column.id}.`,\n )\n }\n\n return filterFn ?? undefined\n}\n\n/**\n * Checks whether column filtering is enabled for this accessor column.\n *\n * The column must have an accessor and filtering must be enabled by the column\n * definition, `enableColumnFilters`, and the table-wide `enableFilters` option.\n *\n * @example\n * ```ts\n * const canFilter = column_getCanFilter(column)\n * ```\n */\nexport function column_getCanFilter<\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.enableColumnFilter ?? true) &&\n (column.table.options.enableColumnFilters ?? true) &&\n (column.table.options.enableFilters ?? true) &&\n !!column.accessorFn\n )\n}\n\n/**\n * Checks whether this column currently has an entry in `state.columnFilters`.\n *\n * This only reflects filter state presence; it does not indicate whether the\n * filter removes any rows.\n *\n * @example\n * ```ts\n * const isFiltered = column_getIsFiltered(column)\n * ```\n */\nexport function column_getIsFiltered<\n TFeatures extends TableFeatures,\n TData extends RowData,\n TValue extends CellData = CellData,\n>(column: Column_Internal<TFeatures, TData, TValue>) {\n return column_getFilterIndex(column) > -1\n}\n\n/**\n * Reads this column's current filter value from `state.columnFilters`.\n *\n * Missing filter entries return `undefined`.\n *\n * @example\n * ```ts\n * const value = column_getFilterValue(column)\n * ```\n */\nexport function column_getFilterValue<\n TFeatures extends TableFeatures,\n TData extends RowData,\n TValue extends CellData = CellData,\n>(column: Column_Internal<TFeatures, TData, TValue>) {\n return column.table.atoms.columnFilters\n ?.get()\n ?.find((d) => d.id === column.id)?.value\n}\n\n/**\n * Finds this column's position in the ordered `state.columnFilters` array.\n *\n * The result is `-1` when the column has no active filter.\n *\n * @example\n * ```ts\n * const index = column_getFilterIndex(column)\n * ```\n */\nexport function column_getFilterIndex<\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.columnFilters\n ?.get()\n ?.findIndex((d) => d.id === column.id) ?? -1\n )\n}\n\n/**\n * Adds, updates, or removes this column's filter value.\n *\n * The incoming value may be an updater. After resolution, `autoRemove` rules\n * decide whether the filter should be removed instead of stored.\n *\n * @example\n * ```ts\n * column_setFilterValue(column, (old) => String(old ?? '').trim())\n * ```\n */\nexport function column_setFilterValue<\n TFeatures extends TableFeatures,\n TData extends RowData,\n TValue extends CellData = CellData,\n>(column: Column_Internal<TFeatures, TData, TValue>, value: any) {\n table_setColumnFilters(column.table, (old) => {\n const filterFn = column_getFilterFn(column)\n const previousFilter = old.find((d) => d.id === column.id)\n\n const newFilter = functionalUpdate(\n value,\n previousFilter ? previousFilter.value : undefined,\n )\n\n if (shouldAutoRemoveFilter(filterFn, newFilter, column)) {\n return old.filter((d) => d.id !== column.id)\n }\n\n const newFilterObj = { id: column.id, value: newFilter }\n\n if (previousFilter) {\n return old.map((d) => {\n if (d.id === column.id) {\n return newFilterObj\n }\n return d\n })\n }\n\n if (old.length) {\n return [...old, newFilterObj]\n }\n\n return [newFilterObj]\n })\n}\n\n/**\n * Routes a column filter updater through the table's filter change handler.\n *\n * The resolved filters are cleaned before they are emitted: filters for known\n * columns are removed when their filter function says the value should be\n * auto-removed.\n *\n * @example\n * ```ts\n * table_setColumnFilters(table, (old) => old.filter((filter) => filter.id !== 'age'))\n * ```\n */\nexport function table_setColumnFilters<\n TFeatures extends TableFeatures,\n TData extends RowData,\n>(\n table: Table_Internal<TFeatures, TData>,\n updater: Updater<ColumnFiltersState>,\n) {\n const leafColumnsById = table.getAllLeafColumnsById()\n\n const updateFn = (old: ColumnFiltersState) => {\n return functionalUpdate(updater, old).filter((filter) => {\n const column = leafColumnsById[filter.id]\n\n if (column) {\n const filterFn = column_getFilterFn(column)\n\n if (shouldAutoRemoveFilter(filterFn, filter.value, column)) {\n return false\n }\n }\n\n return true\n })\n }\n\n table.options.onColumnFiltersChange?.(updateFn)\n}\n\n/**\n * Resets `columnFilters` to the configured initial state or feature default.\n *\n * With no argument, the reset clones `table.initialState.columnFilters` when it\n * exists. Passing `true` ignores initial state and resets to `[]`.\n *\n * @example\n * ```ts\n * table_resetColumnFilters(table)\n * table_resetColumnFilters(table, true)\n * ```\n */\nexport function table_resetColumnFilters<\n TFeatures extends TableFeatures,\n TData extends RowData,\n>(table: Table_Internal<TFeatures, TData>, defaultState?: boolean) {\n table_setColumnFilters(\n table,\n defaultState ? [] : cloneState(table.initialState.columnFilters ?? []),\n )\n}\n\n/**\n * Returns whether a filter value should be removed from filter state.\n *\n * This checks the filter function's `autoRemove` hook and built-in empty-value rules.\n *\n * @example\n * ```ts\n * const removeFilter = shouldAutoRemoveFilter(filterFn, value, column)\n * ```\n */\nexport function shouldAutoRemoveFilter<\n TFeatures extends TableFeatures,\n TData extends RowData,\n TValue extends CellData = CellData,\n>(\n filterFn?: FilterFn<TFeatures, TData>,\n value?: any,\n column?: Column_Internal<TFeatures, TData, TValue>,\n) {\n return (\n (filterFn && filterFn.autoRemove\n ? filterFn.autoRemove(value, column as any)\n : false) ||\n typeof value === 'undefined' ||\n (typeof value === 'string' && !value)\n )\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"columnFilteringFeature.utils.js","names":[],"sources":["../../../src/features/column-filtering/columnFilteringFeature.utils.ts"],"sourcesContent":["import { cloneState, functionalUpdate, 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 ColumnFiltersState,\n FilterFn,\n} from './columnFilteringFeature.types'\n\n/**\n * Creates the default column filter state.\n *\n * The feature default is an empty array, meaning no column filters are active.\n * Reset APIs use this value when `defaultState` is `true`.\n *\n * @example\n * ```ts\n * const filters = getDefaultColumnFiltersState()\n * ```\n */\nexport function getDefaultColumnFiltersState(): ColumnFiltersState {\n return []\n}\n\n/**\n * Chooses a built-in filter function from the column's first core row value.\n *\n * Strings use `includesString`, numbers use `inNumberRange`, booleans and\n * objects use `equals`, arrays use `arrIncludes`, and unknown values fall back\n * to `weakEquals`.\n *\n * @example\n * ```ts\n * const filterFn = column_getAutoFilterFn(column)\n * ```\n */\nexport function column_getAutoFilterFn<\n TFeatures extends TableFeatures,\n TData extends RowData,\n TValue extends CellData = CellData,\n>(column: Column_Internal<TFeatures, TData, TValue>) {\n const filterFns: Record<string, FilterFn<TFeatures, TData>> | undefined =\n column.table._rowModelFns.filterFns\n\n const firstRow = column.table.getCoreRowModel().flatRows[0]\n\n const value = firstRow ? firstRow.getValue(column.id) : undefined\n\n if (typeof value === 'string') {\n return filterFns?.includesString\n }\n\n if (typeof value === 'number') {\n return filterFns?.inNumberRange\n }\n\n if (typeof value === 'boolean') {\n return filterFns?.equals\n }\n\n if (Array.isArray(value)) {\n return filterFns?.arrIncludes\n }\n\n if (value !== null && typeof value === 'object') {\n return filterFns?.equals\n }\n\n return filterFns?.weakEquals\n}\n\n/**\n * Resolves the filter function configured for a column.\n *\n * Function-valued `columnDef.filterFn` is returned directly, `'auto'` delegates\n * to `column_getAutoFilterFn`, and string values are looked up in the table's\n * filter function registry.\n *\n * @example\n * ```ts\n * const filterFn = column_getFilterFn(column)\n * ```\n */\nexport function column_getFilterFn<\n TFeatures extends TableFeatures,\n TData extends RowData,\n TValue extends CellData = CellData,\n>(\n column: Column_Internal<TFeatures, TData, TValue>,\n): FilterFn<TFeatures, TData> | undefined {\n let filterFn = null\n const filterFns: Record<string, FilterFn<TFeatures, TData>> | undefined =\n column.table._rowModelFns.filterFns\n filterFn = isFunction(column.columnDef.filterFn)\n ? column.columnDef.filterFn\n : column.columnDef.filterFn === 'auto'\n ? column_getAutoFilterFn(column)\n : filterFns?.[column.columnDef.filterFn as string]\n\n if (process.env.NODE_ENV === 'development' && !filterFn) {\n console.warn(\n `Could not find a valid 'column.filterFn' for column with the ID: ${column.id}.`,\n )\n }\n\n return filterFn ?? undefined\n}\n\n/**\n * Checks whether column filtering is enabled for this accessor column.\n *\n * The column must have an accessor and filtering must be enabled by the column\n * definition, `enableColumnFilters`, and the table-wide `enableFilters` option.\n *\n * @example\n * ```ts\n * const canFilter = column_getCanFilter(column)\n * ```\n */\nexport function column_getCanFilter<\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.enableColumnFilter ?? true) &&\n (column.table.options.enableColumnFilters ?? true) &&\n (column.table.options.enableFilters ?? true) &&\n !!column.accessorFn\n )\n}\n\n/**\n * Checks whether this column currently has an entry in `state.columnFilters`.\n *\n * This only reflects filter state presence; it does not indicate whether the\n * filter removes any rows.\n *\n * @example\n * ```ts\n * const isFiltered = column_getIsFiltered(column)\n * ```\n */\nexport function column_getIsFiltered<\n TFeatures extends TableFeatures,\n TData extends RowData,\n TValue extends CellData = CellData,\n>(column: Column_Internal<TFeatures, TData, TValue>) {\n return column_getFilterIndex(column) > -1\n}\n\n/**\n * Reads this column's current filter value from `state.columnFilters`.\n *\n * Missing filter entries return `undefined`.\n *\n * @example\n * ```ts\n * const value = column_getFilterValue(column)\n * ```\n */\nexport function column_getFilterValue<\n TFeatures extends TableFeatures,\n TData extends RowData,\n TValue extends CellData = CellData,\n>(column: Column_Internal<TFeatures, TData, TValue>) {\n return column.table.atoms.columnFilters\n ?.get()\n ?.find((d) => d.id === column.id)?.value\n}\n\n/**\n * Finds this column's position in the ordered `state.columnFilters` array.\n *\n * The result is `-1` when the column has no active filter.\n *\n * @example\n * ```ts\n * const index = column_getFilterIndex(column)\n * ```\n */\nexport function column_getFilterIndex<\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.columnFilters\n ?.get()\n ?.findIndex((d) => d.id === column.id) ?? -1\n )\n}\n\n/**\n * Adds, updates, or removes this column's filter value.\n *\n * The incoming value may be an updater. After resolution, `autoRemove` rules\n * decide whether the filter should be removed instead of stored.\n *\n * @example\n * ```ts\n * column_setFilterValue(column, (old) => String(old ?? '').trim())\n * ```\n */\nexport function column_setFilterValue<\n TFeatures extends TableFeatures,\n TData extends RowData,\n TValue extends CellData = CellData,\n>(column: Column_Internal<TFeatures, TData, TValue>, value: any) {\n table_setColumnFilters(column.table, (old) => {\n const filterFn = column_getFilterFn(column)\n const previousFilter = old.find((d) => d.id === column.id)\n\n const newFilter = functionalUpdate(\n value,\n previousFilter ? previousFilter.value : undefined,\n )\n\n if (shouldAutoRemoveFilter(filterFn, newFilter, column)) {\n return old.filter((d) => d.id !== column.id)\n }\n\n const newFilterObj = { id: column.id, value: newFilter }\n\n if (previousFilter) {\n return old.map((d) => {\n if (d.id === column.id) {\n return newFilterObj\n }\n return d\n })\n }\n\n if (old.length) {\n return [...old, newFilterObj]\n }\n\n return [newFilterObj]\n })\n}\n\n/**\n * Routes a column filter updater through the table's filter change handler.\n *\n * The resolved filters are cleaned before they are emitted: filters for known\n * columns are removed when their filter function says the value should be\n * auto-removed.\n *\n * @example\n * ```ts\n * table_setColumnFilters(table, (old) => old.filter((filter) => filter.id !== 'age'))\n * ```\n */\nexport function table_setColumnFilters<\n TFeatures extends TableFeatures,\n TData extends RowData,\n>(\n table: Table_Internal<TFeatures, TData>,\n updater: Updater<ColumnFiltersState>,\n) {\n const leafColumnsById = table.getAllLeafColumnsById()\n\n const updateFn = (old: ColumnFiltersState) => {\n return functionalUpdate(updater, old).filter((filter) => {\n const column = leafColumnsById[filter.id]\n\n if (column) {\n const filterFn = column_getFilterFn(column)\n\n if (shouldAutoRemoveFilter(filterFn, filter.value, column)) {\n return false\n }\n }\n\n return true\n })\n }\n\n table.options.onColumnFiltersChange?.(updateFn)\n}\n\n/**\n * Resets `columnFilters` to the configured initial state or feature default.\n *\n * With no argument, the reset clones `table.initialState.columnFilters` when it\n * exists. Passing `true` ignores initial state and resets to `[]`.\n *\n * @example\n * ```ts\n * table_resetColumnFilters(table)\n * table_resetColumnFilters(table, true)\n * ```\n */\nexport function table_resetColumnFilters<\n TFeatures extends TableFeatures,\n TData extends RowData,\n>(table: Table_Internal<TFeatures, TData>, defaultState?: boolean) {\n table_setColumnFilters(\n table,\n defaultState ? [] : cloneState(table.initialState.columnFilters ?? []),\n )\n}\n\n/**\n * Returns whether a filter value should be removed from filter state.\n *\n * This checks the filter function's `autoRemove` hook and built-in empty-value rules.\n *\n * @example\n * ```ts\n * const removeFilter = shouldAutoRemoveFilter(filterFn, value, column)\n * ```\n */\nexport function shouldAutoRemoveFilter<\n TFeatures extends TableFeatures,\n TData extends RowData,\n TValue extends CellData = CellData,\n>(\n filterFn?: FilterFn<TFeatures, TData>,\n value?: any,\n column?: Column_Internal<TFeatures, TData, TValue>,\n) {\n return (\n (filterFn && filterFn.autoRemove\n ? filterFn.autoRemove(value, column as any)\n : false) ||\n typeof value === 'undefined' ||\n (typeof value === 'string' && !value)\n )\n}\n"],"mappings":"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"}
|
|
@@ -30,6 +30,7 @@ declare function column_getCanGlobalFilter<TFeatures extends TableFeatures, TDat
|
|
|
30
30
|
*/
|
|
31
31
|
declare function table_getGlobalAutoFilterFn(): (<TFeatures extends TableFeatures, TData extends RowData>(row: Row<TFeatures, TData>, columnId: string, filterValue: unknown) => boolean) & {
|
|
32
32
|
autoRemove: (val: any) => boolean;
|
|
33
|
+
resolveFilterValue: (val: any) => string;
|
|
33
34
|
};
|
|
34
35
|
/**
|
|
35
36
|
* Resolves the filter function used for global filtering.
|
|
@@ -30,6 +30,7 @@ declare function column_getCanGlobalFilter<TFeatures extends TableFeatures, TDat
|
|
|
30
30
|
*/
|
|
31
31
|
declare function table_getGlobalAutoFilterFn(): (<TFeatures extends TableFeatures, TData extends RowData>(row: Row<TFeatures, TData>, columnId: string, filterValue: unknown) => boolean) & {
|
|
32
32
|
autoRemove: (val: any) => boolean;
|
|
33
|
+
resolveFilterValue: (val: any) => string;
|
|
33
34
|
};
|
|
34
35
|
/**
|
|
35
36
|
* Resolves the filter function used for global filtering.
|
|
@@ -33,46 +33,53 @@ function _createSortedRowModel(table) {
|
|
|
33
33
|
const sorting = (_table$atoms$sorting2 = table.atoms.sorting) === null || _table$atoms$sorting2 === void 0 ? void 0 : _table$atoms$sorting2.get();
|
|
34
34
|
if (!preSortedRowModel.rows.length || !(sorting === null || sorting === void 0 ? void 0 : sorting.length)) return preSortedRowModel;
|
|
35
35
|
const sortedFlatRows = [];
|
|
36
|
-
const availableSorting = sorting.filter((sort) =>
|
|
37
|
-
|
|
38
|
-
|
|
36
|
+
const availableSorting = sorting.filter((sort) => {
|
|
37
|
+
const column = table.getColumn(sort.id);
|
|
38
|
+
return column ? require_rowSortingFeature_utils.column_getCanSort(column) : false;
|
|
39
|
+
});
|
|
40
|
+
const resolvedSorting = [];
|
|
41
|
+
for (let i = 0; i < availableSorting.length; i++) {
|
|
42
|
+
const sortEntry = availableSorting[i];
|
|
39
43
|
const column = table.getColumn(sortEntry.id);
|
|
40
|
-
if (!column)
|
|
41
|
-
|
|
44
|
+
if (!column) continue;
|
|
45
|
+
resolvedSorting.push({
|
|
46
|
+
id: sortEntry.id,
|
|
47
|
+
desc: sortEntry.desc,
|
|
42
48
|
sortUndefined: column.columnDef.sortUndefined,
|
|
43
49
|
invertSorting: column.columnDef.invertSorting,
|
|
44
50
|
sortFn: require_rowSortingFeature_utils.column_getSortFn(column)
|
|
45
|
-
};
|
|
46
|
-
}
|
|
47
|
-
const
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
const
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
if (
|
|
62
|
-
|
|
63
|
-
if (sortUndefined === "last") return aUndefined ? 1 : -1;
|
|
64
|
-
sortInt = aUndefined && bUndefined ? 0 : aUndefined ? sortUndefined : -sortUndefined;
|
|
65
|
-
}
|
|
66
|
-
}
|
|
67
|
-
if (sortInt === 0) sortInt = columnInfo.sortFn(rowA, rowB, sortEntry.id);
|
|
68
|
-
if (sortInt !== 0) {
|
|
69
|
-
if (isDesc) sortInt *= -1;
|
|
70
|
-
if (columnInfo.invertSorting) sortInt *= -1;
|
|
71
|
-
return sortInt;
|
|
51
|
+
});
|
|
52
|
+
}
|
|
53
|
+
const compareRows = (rowA, rowB) => {
|
|
54
|
+
for (let i = 0; i < resolvedSorting.length; i++) {
|
|
55
|
+
const sortEntry = resolvedSorting[i];
|
|
56
|
+
const sortUndefined = sortEntry.sortUndefined;
|
|
57
|
+
const isDesc = sortEntry.desc;
|
|
58
|
+
let sortInt = 0;
|
|
59
|
+
if (sortUndefined) {
|
|
60
|
+
const aValue = rowA.getValue(sortEntry.id);
|
|
61
|
+
const bValue = rowB.getValue(sortEntry.id);
|
|
62
|
+
const aUndefined = aValue === void 0;
|
|
63
|
+
const bUndefined = bValue === void 0;
|
|
64
|
+
if (aUndefined && bUndefined) continue;
|
|
65
|
+
if (aUndefined || bUndefined) {
|
|
66
|
+
if (sortUndefined === "first") return aUndefined ? -1 : 1;
|
|
67
|
+
if (sortUndefined === "last") return aUndefined ? 1 : -1;
|
|
68
|
+
sortInt = aUndefined ? sortUndefined : -sortUndefined;
|
|
72
69
|
}
|
|
73
70
|
}
|
|
74
|
-
|
|
75
|
-
|
|
71
|
+
if (sortInt === 0) sortInt = sortEntry.sortFn(rowA, rowB, sortEntry.id);
|
|
72
|
+
if (sortInt !== 0) {
|
|
73
|
+
if (isDesc) sortInt *= -1;
|
|
74
|
+
if (sortEntry.invertSorting) sortInt *= -1;
|
|
75
|
+
return sortInt;
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
return rowA.index - rowB.index;
|
|
79
|
+
};
|
|
80
|
+
const sortData = (rows) => {
|
|
81
|
+
const sortedData = rows.slice();
|
|
82
|
+
sortedData.sort(compareRows);
|
|
76
83
|
for (let i = 0; i < sortedData.length; i++) {
|
|
77
84
|
const row = sortedData[i];
|
|
78
85
|
if (row.subRows.length) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"createSortedRowModel.cjs","names":["tableMemo","table_autoResetPageIndex","column_getCanSort","
|
|
1
|
+
{"version":3,"file":"createSortedRowModel.cjs","names":["tableMemo","table_autoResetPageIndex","column_getCanSort","column_getSortFn"],"sources":["../../../src/features/row-sorting/createSortedRowModel.ts"],"sourcesContent":["import { tableMemo } from '../../utils'\nimport { table_autoResetPageIndex } from '../row-pagination/rowPaginationFeature.utils'\nimport { column_getCanSort, column_getSortFn } from './rowSortingFeature.utils'\nimport type { Column_Internal } from '../../types/Column'\nimport type { TableFeatures } from '../../types/TableFeatures'\nimport type { RowModel } from '../../core/row-models/coreRowModelsFeature.types'\nimport type { Table, Table_Internal } from '../../types/Table'\nimport type { Row } from '../../types/Row'\nimport type { SortFn } from './rowSortingFeature.types'\nimport type { RowData } from '../../types/type-utils'\n\n/**\n * Creates a memoized sorted row model factory.\n *\n * The factory reads the relevant table state atoms and options, then returns a row model function used by the table row-model pipeline.\n *\n * Register sorting functions with the `sortFns` slot on the `features` option:\n * `tableFeatures({ rowSortingFeature, sortedRowModel: createSortedRowModel(), sortFns })`.\n */\nexport function createSortedRowModel<\n TFeatures extends TableFeatures,\n TData extends RowData,\n>(): (table: Table<TFeatures, TData>) => () => RowModel<TFeatures, TData> {\n return (_table) => {\n const table = _table as unknown as Table_Internal<TFeatures, TData>\n return tableMemo({\n feature: 'rowSortingFeature',\n table,\n fnName: 'table.getSortedRowModel',\n memoDeps: () => [\n table.atoms.sorting?.get(),\n table.getPreSortedRowModel(),\n ],\n fn: () => _createSortedRowModel(table),\n onAfterUpdate: () => table_autoResetPageIndex(table),\n })\n }\n}\n\nfunction _createSortedRowModel<\n TFeatures extends TableFeatures,\n TData extends RowData = any,\n>(table: Table_Internal<TFeatures, TData>): RowModel<TFeatures, TData> {\n const preSortedRowModel = table.getPreSortedRowModel()\n const sorting = table.atoms.sorting?.get()\n\n if (!preSortedRowModel.rows.length || !sorting?.length) {\n return preSortedRowModel\n }\n\n const sortedFlatRows: Array<Row<TFeatures, TData>> = []\n\n // Filter out sortings that correspond to non existing columns\n const availableSorting = sorting.filter((sort) => {\n const column = table.getColumn(sort.id)\n return column ? column_getCanSort(column) : false\n })\n\n const resolvedSorting: Array<{\n id: string\n desc?: boolean\n sortUndefined?: false | -1 | 1 | 'first' | 'last'\n invertSorting?: boolean\n sortFn: SortFn<TFeatures, TData>\n }> = []\n\n for (let i = 0; i < availableSorting.length; i++) {\n const sortEntry = availableSorting[i]!\n const column: Column_Internal<TFeatures, TData> | undefined =\n table.getColumn(sortEntry.id)\n if (!column) {\n continue\n }\n\n resolvedSorting.push({\n id: sortEntry.id,\n desc: sortEntry.desc,\n sortUndefined: column.columnDef.sortUndefined,\n invertSorting: column.columnDef.invertSorting,\n sortFn: column_getSortFn(column),\n })\n }\n\n const compareRows = (\n rowA: Row<TFeatures, TData>,\n rowB: Row<TFeatures, TData>,\n ) => {\n for (let i = 0; i < resolvedSorting.length; i++) {\n const sortEntry = resolvedSorting[i]!\n const sortUndefined = sortEntry.sortUndefined\n const isDesc = sortEntry.desc\n\n let sortInt = 0\n\n // All sorting ints should always return in ascending order\n if (sortUndefined) {\n const aValue = rowA.getValue(sortEntry.id)\n const bValue = rowB.getValue(sortEntry.id)\n\n const aUndefined = aValue === undefined\n const bUndefined = bValue === undefined\n\n if (aUndefined && bUndefined) {\n continue\n }\n\n if (aUndefined || bUndefined) {\n if (sortUndefined === 'first') return aUndefined ? -1 : 1\n if (sortUndefined === 'last') return aUndefined ? 1 : -1\n sortInt = aUndefined ? sortUndefined : -sortUndefined\n }\n }\n\n if (sortInt === 0) {\n sortInt = sortEntry.sortFn(rowA, rowB, sortEntry.id)\n }\n\n // If sorting is non-zero, take care of desc and inversion\n if (sortInt !== 0) {\n if (isDesc) {\n sortInt *= -1\n }\n\n if (sortEntry.invertSorting) {\n sortInt *= -1\n }\n\n return sortInt\n }\n }\n\n return rowA.index - rowB.index\n }\n\n const sortData = (rows: Array<Row<TFeatures, TData>>) => {\n const sortedData = rows.slice()\n\n sortedData.sort(compareRows)\n\n // If there are sub-rows, sort them. Clone only rows that need mutation\n // (i.e. have subRows) so we don't corrupt the source row model.\n for (let i = 0; i < sortedData.length; i++) {\n const row = sortedData[i]!\n if (row.subRows.length) {\n // Preserve prototype chain so methods like getValue() remain accessible\n const cloned = Object.create(Object.getPrototypeOf(row))\n Object.assign(cloned, row)\n cloned.subRows = sortData(row.subRows)\n sortedData[i] = cloned\n sortedFlatRows.push(cloned)\n } else {\n sortedFlatRows.push(row)\n }\n }\n\n return sortedData\n }\n\n return {\n rows: sortData(preSortedRowModel.rows),\n flatRows: sortedFlatRows,\n rowsById: preSortedRowModel.rowsById,\n }\n}\n"],"mappings":";;;;;;;;;;;;;AAmBA,SAAgB,uBAG0D;CACxE,QAAQ,WAAW;EACjB,MAAM,QAAQ;EACd,OAAOA,wBAAU;GACf,SAAS;GACT;GACA,QAAQ;GACR,gBAAgB;;oCACd,MAAM,MAAM,qFAAS,IAAI,GACzB,MAAM,qBAAqB,CAC7B;;GACA,UAAU,sBAAsB,KAAK;GACrC,qBAAqBC,4DAAyB,KAAK;EACrD,CAAC;CACH;AACF;AAEA,SAAS,sBAGP,OAAqE;;CACrE,MAAM,oBAAoB,MAAM,qBAAqB;CACrD,MAAM,mCAAU,MAAM,MAAM,uFAAS,IAAI;CAEzC,IAAI,CAAC,kBAAkB,KAAK,UAAU,oDAAC,QAAS,SAC9C,OAAO;CAGT,MAAM,iBAA+C,CAAC;CAGtD,MAAM,mBAAmB,QAAQ,QAAQ,SAAS;EAChD,MAAM,SAAS,MAAM,UAAU,KAAK,EAAE;EACtC,OAAO,SAASC,kDAAkB,MAAM,IAAI;CAC9C,CAAC;CAED,MAAM,kBAMD,CAAC;CAEN,KAAK,IAAI,IAAI,GAAG,IAAI,iBAAiB,QAAQ,KAAK;EAChD,MAAM,YAAY,iBAAiB;EACnC,MAAM,SACJ,MAAM,UAAU,UAAU,EAAE;EAC9B,IAAI,CAAC,QACH;EAGF,gBAAgB,KAAK;GACnB,IAAI,UAAU;GACd,MAAM,UAAU;GAChB,eAAe,OAAO,UAAU;GAChC,eAAe,OAAO,UAAU;GAChC,QAAQC,iDAAiB,MAAM;EACjC,CAAC;CACH;CAEA,MAAM,eACJ,MACA,SACG;EACH,KAAK,IAAI,IAAI,GAAG,IAAI,gBAAgB,QAAQ,KAAK;GAC/C,MAAM,YAAY,gBAAgB;GAClC,MAAM,gBAAgB,UAAU;GAChC,MAAM,SAAS,UAAU;GAEzB,IAAI,UAAU;GAGd,IAAI,eAAe;IACjB,MAAM,SAAS,KAAK,SAAS,UAAU,EAAE;IACzC,MAAM,SAAS,KAAK,SAAS,UAAU,EAAE;IAEzC,MAAM,aAAa,WAAW;IAC9B,MAAM,aAAa,WAAW;IAE9B,IAAI,cAAc,YAChB;IAGF,IAAI,cAAc,YAAY;KAC5B,IAAI,kBAAkB,SAAS,OAAO,aAAa,KAAK;KACxD,IAAI,kBAAkB,QAAQ,OAAO,aAAa,IAAI;KACtD,UAAU,aAAa,gBAAgB,CAAC;IAC1C;GACF;GAEA,IAAI,YAAY,GACd,UAAU,UAAU,OAAO,MAAM,MAAM,UAAU,EAAE;GAIrD,IAAI,YAAY,GAAG;IACjB,IAAI,QACF,WAAW;IAGb,IAAI,UAAU,eACZ,WAAW;IAGb,OAAO;GACT;EACF;EAEA,OAAO,KAAK,QAAQ,KAAK;CAC3B;CAEA,MAAM,YAAY,SAAuC;EACvD,MAAM,aAAa,KAAK,MAAM;EAE9B,WAAW,KAAK,WAAW;EAI3B,KAAK,IAAI,IAAI,GAAG,IAAI,WAAW,QAAQ,KAAK;GAC1C,MAAM,MAAM,WAAW;GACvB,IAAI,IAAI,QAAQ,QAAQ;IAEtB,MAAM,SAAS,OAAO,OAAO,OAAO,eAAe,GAAG,CAAC;IACvD,OAAO,OAAO,QAAQ,GAAG;IACzB,OAAO,UAAU,SAAS,IAAI,OAAO;IACrC,WAAW,KAAK;IAChB,eAAe,KAAK,MAAM;GAC5B,OACE,eAAe,KAAK,GAAG;EAE3B;EAEA,OAAO;CACT;CAEA,OAAO;EACL,MAAM,SAAS,kBAAkB,IAAI;EACrC,UAAU;EACV,UAAU,kBAAkB;CAC9B;AACF"}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { tableMemo } from "../../utils.js";
|
|
2
2
|
import { table_autoResetPageIndex } from "../row-pagination/rowPaginationFeature.utils.js";
|
|
3
3
|
import { column_getCanSort, column_getSortFn } from "./rowSortingFeature.utils.js";
|
|
4
4
|
|
|
@@ -33,46 +33,53 @@ function _createSortedRowModel(table) {
|
|
|
33
33
|
const sorting = (_table$atoms$sorting2 = table.atoms.sorting) === null || _table$atoms$sorting2 === void 0 ? void 0 : _table$atoms$sorting2.get();
|
|
34
34
|
if (!preSortedRowModel.rows.length || !(sorting === null || sorting === void 0 ? void 0 : sorting.length)) return preSortedRowModel;
|
|
35
35
|
const sortedFlatRows = [];
|
|
36
|
-
const availableSorting = sorting.filter((sort) =>
|
|
37
|
-
|
|
38
|
-
|
|
36
|
+
const availableSorting = sorting.filter((sort) => {
|
|
37
|
+
const column = table.getColumn(sort.id);
|
|
38
|
+
return column ? column_getCanSort(column) : false;
|
|
39
|
+
});
|
|
40
|
+
const resolvedSorting = [];
|
|
41
|
+
for (let i = 0; i < availableSorting.length; i++) {
|
|
42
|
+
const sortEntry = availableSorting[i];
|
|
39
43
|
const column = table.getColumn(sortEntry.id);
|
|
40
|
-
if (!column)
|
|
41
|
-
|
|
44
|
+
if (!column) continue;
|
|
45
|
+
resolvedSorting.push({
|
|
46
|
+
id: sortEntry.id,
|
|
47
|
+
desc: sortEntry.desc,
|
|
42
48
|
sortUndefined: column.columnDef.sortUndefined,
|
|
43
49
|
invertSorting: column.columnDef.invertSorting,
|
|
44
50
|
sortFn: column_getSortFn(column)
|
|
45
|
-
};
|
|
46
|
-
}
|
|
47
|
-
const
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
const
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
if (
|
|
62
|
-
|
|
63
|
-
if (sortUndefined === "last") return aUndefined ? 1 : -1;
|
|
64
|
-
sortInt = aUndefined && bUndefined ? 0 : aUndefined ? sortUndefined : -sortUndefined;
|
|
65
|
-
}
|
|
66
|
-
}
|
|
67
|
-
if (sortInt === 0) sortInt = columnInfo.sortFn(rowA, rowB, sortEntry.id);
|
|
68
|
-
if (sortInt !== 0) {
|
|
69
|
-
if (isDesc) sortInt *= -1;
|
|
70
|
-
if (columnInfo.invertSorting) sortInt *= -1;
|
|
71
|
-
return sortInt;
|
|
51
|
+
});
|
|
52
|
+
}
|
|
53
|
+
const compareRows = (rowA, rowB) => {
|
|
54
|
+
for (let i = 0; i < resolvedSorting.length; i++) {
|
|
55
|
+
const sortEntry = resolvedSorting[i];
|
|
56
|
+
const sortUndefined = sortEntry.sortUndefined;
|
|
57
|
+
const isDesc = sortEntry.desc;
|
|
58
|
+
let sortInt = 0;
|
|
59
|
+
if (sortUndefined) {
|
|
60
|
+
const aValue = rowA.getValue(sortEntry.id);
|
|
61
|
+
const bValue = rowB.getValue(sortEntry.id);
|
|
62
|
+
const aUndefined = aValue === void 0;
|
|
63
|
+
const bUndefined = bValue === void 0;
|
|
64
|
+
if (aUndefined && bUndefined) continue;
|
|
65
|
+
if (aUndefined || bUndefined) {
|
|
66
|
+
if (sortUndefined === "first") return aUndefined ? -1 : 1;
|
|
67
|
+
if (sortUndefined === "last") return aUndefined ? 1 : -1;
|
|
68
|
+
sortInt = aUndefined ? sortUndefined : -sortUndefined;
|
|
72
69
|
}
|
|
73
70
|
}
|
|
74
|
-
|
|
75
|
-
|
|
71
|
+
if (sortInt === 0) sortInt = sortEntry.sortFn(rowA, rowB, sortEntry.id);
|
|
72
|
+
if (sortInt !== 0) {
|
|
73
|
+
if (isDesc) sortInt *= -1;
|
|
74
|
+
if (sortEntry.invertSorting) sortInt *= -1;
|
|
75
|
+
return sortInt;
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
return rowA.index - rowB.index;
|
|
79
|
+
};
|
|
80
|
+
const sortData = (rows) => {
|
|
81
|
+
const sortedData = rows.slice();
|
|
82
|
+
sortedData.sort(compareRows);
|
|
76
83
|
for (let i = 0; i < sortedData.length; i++) {
|
|
77
84
|
const row = sortedData[i];
|
|
78
85
|
if (row.subRows.length) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"createSortedRowModel.js","names":[],"sources":["../../../src/features/row-sorting/createSortedRowModel.ts"],"sourcesContent":["import {
|
|
1
|
+
{"version":3,"file":"createSortedRowModel.js","names":[],"sources":["../../../src/features/row-sorting/createSortedRowModel.ts"],"sourcesContent":["import { tableMemo } from '../../utils'\nimport { table_autoResetPageIndex } from '../row-pagination/rowPaginationFeature.utils'\nimport { column_getCanSort, column_getSortFn } from './rowSortingFeature.utils'\nimport type { Column_Internal } from '../../types/Column'\nimport type { TableFeatures } from '../../types/TableFeatures'\nimport type { RowModel } from '../../core/row-models/coreRowModelsFeature.types'\nimport type { Table, Table_Internal } from '../../types/Table'\nimport type { Row } from '../../types/Row'\nimport type { SortFn } from './rowSortingFeature.types'\nimport type { RowData } from '../../types/type-utils'\n\n/**\n * Creates a memoized sorted row model factory.\n *\n * The factory reads the relevant table state atoms and options, then returns a row model function used by the table row-model pipeline.\n *\n * Register sorting functions with the `sortFns` slot on the `features` option:\n * `tableFeatures({ rowSortingFeature, sortedRowModel: createSortedRowModel(), sortFns })`.\n */\nexport function createSortedRowModel<\n TFeatures extends TableFeatures,\n TData extends RowData,\n>(): (table: Table<TFeatures, TData>) => () => RowModel<TFeatures, TData> {\n return (_table) => {\n const table = _table as unknown as Table_Internal<TFeatures, TData>\n return tableMemo({\n feature: 'rowSortingFeature',\n table,\n fnName: 'table.getSortedRowModel',\n memoDeps: () => [\n table.atoms.sorting?.get(),\n table.getPreSortedRowModel(),\n ],\n fn: () => _createSortedRowModel(table),\n onAfterUpdate: () => table_autoResetPageIndex(table),\n })\n }\n}\n\nfunction _createSortedRowModel<\n TFeatures extends TableFeatures,\n TData extends RowData = any,\n>(table: Table_Internal<TFeatures, TData>): RowModel<TFeatures, TData> {\n const preSortedRowModel = table.getPreSortedRowModel()\n const sorting = table.atoms.sorting?.get()\n\n if (!preSortedRowModel.rows.length || !sorting?.length) {\n return preSortedRowModel\n }\n\n const sortedFlatRows: Array<Row<TFeatures, TData>> = []\n\n // Filter out sortings that correspond to non existing columns\n const availableSorting = sorting.filter((sort) => {\n const column = table.getColumn(sort.id)\n return column ? column_getCanSort(column) : false\n })\n\n const resolvedSorting: Array<{\n id: string\n desc?: boolean\n sortUndefined?: false | -1 | 1 | 'first' | 'last'\n invertSorting?: boolean\n sortFn: SortFn<TFeatures, TData>\n }> = []\n\n for (let i = 0; i < availableSorting.length; i++) {\n const sortEntry = availableSorting[i]!\n const column: Column_Internal<TFeatures, TData> | undefined =\n table.getColumn(sortEntry.id)\n if (!column) {\n continue\n }\n\n resolvedSorting.push({\n id: sortEntry.id,\n desc: sortEntry.desc,\n sortUndefined: column.columnDef.sortUndefined,\n invertSorting: column.columnDef.invertSorting,\n sortFn: column_getSortFn(column),\n })\n }\n\n const compareRows = (\n rowA: Row<TFeatures, TData>,\n rowB: Row<TFeatures, TData>,\n ) => {\n for (let i = 0; i < resolvedSorting.length; i++) {\n const sortEntry = resolvedSorting[i]!\n const sortUndefined = sortEntry.sortUndefined\n const isDesc = sortEntry.desc\n\n let sortInt = 0\n\n // All sorting ints should always return in ascending order\n if (sortUndefined) {\n const aValue = rowA.getValue(sortEntry.id)\n const bValue = rowB.getValue(sortEntry.id)\n\n const aUndefined = aValue === undefined\n const bUndefined = bValue === undefined\n\n if (aUndefined && bUndefined) {\n continue\n }\n\n if (aUndefined || bUndefined) {\n if (sortUndefined === 'first') return aUndefined ? -1 : 1\n if (sortUndefined === 'last') return aUndefined ? 1 : -1\n sortInt = aUndefined ? sortUndefined : -sortUndefined\n }\n }\n\n if (sortInt === 0) {\n sortInt = sortEntry.sortFn(rowA, rowB, sortEntry.id)\n }\n\n // If sorting is non-zero, take care of desc and inversion\n if (sortInt !== 0) {\n if (isDesc) {\n sortInt *= -1\n }\n\n if (sortEntry.invertSorting) {\n sortInt *= -1\n }\n\n return sortInt\n }\n }\n\n return rowA.index - rowB.index\n }\n\n const sortData = (rows: Array<Row<TFeatures, TData>>) => {\n const sortedData = rows.slice()\n\n sortedData.sort(compareRows)\n\n // If there are sub-rows, sort them. Clone only rows that need mutation\n // (i.e. have subRows) so we don't corrupt the source row model.\n for (let i = 0; i < sortedData.length; i++) {\n const row = sortedData[i]!\n if (row.subRows.length) {\n // Preserve prototype chain so methods like getValue() remain accessible\n const cloned = Object.create(Object.getPrototypeOf(row))\n Object.assign(cloned, row)\n cloned.subRows = sortData(row.subRows)\n sortedData[i] = cloned\n sortedFlatRows.push(cloned)\n } else {\n sortedFlatRows.push(row)\n }\n }\n\n return sortedData\n }\n\n return {\n rows: sortData(preSortedRowModel.rows),\n flatRows: sortedFlatRows,\n rowsById: preSortedRowModel.rowsById,\n }\n}\n"],"mappings":";;;;;;;;;;;;;AAmBA,SAAgB,uBAG0D;CACxE,QAAQ,WAAW;EACjB,MAAM,QAAQ;EACd,OAAO,UAAU;GACf,SAAS;GACT;GACA,QAAQ;GACR,gBAAgB;;oCACd,MAAM,MAAM,qFAAS,IAAI,GACzB,MAAM,qBAAqB,CAC7B;;GACA,UAAU,sBAAsB,KAAK;GACrC,qBAAqB,yBAAyB,KAAK;EACrD,CAAC;CACH;AACF;AAEA,SAAS,sBAGP,OAAqE;;CACrE,MAAM,oBAAoB,MAAM,qBAAqB;CACrD,MAAM,mCAAU,MAAM,MAAM,uFAAS,IAAI;CAEzC,IAAI,CAAC,kBAAkB,KAAK,UAAU,oDAAC,QAAS,SAC9C,OAAO;CAGT,MAAM,iBAA+C,CAAC;CAGtD,MAAM,mBAAmB,QAAQ,QAAQ,SAAS;EAChD,MAAM,SAAS,MAAM,UAAU,KAAK,EAAE;EACtC,OAAO,SAAS,kBAAkB,MAAM,IAAI;CAC9C,CAAC;CAED,MAAM,kBAMD,CAAC;CAEN,KAAK,IAAI,IAAI,GAAG,IAAI,iBAAiB,QAAQ,KAAK;EAChD,MAAM,YAAY,iBAAiB;EACnC,MAAM,SACJ,MAAM,UAAU,UAAU,EAAE;EAC9B,IAAI,CAAC,QACH;EAGF,gBAAgB,KAAK;GACnB,IAAI,UAAU;GACd,MAAM,UAAU;GAChB,eAAe,OAAO,UAAU;GAChC,eAAe,OAAO,UAAU;GAChC,QAAQ,iBAAiB,MAAM;EACjC,CAAC;CACH;CAEA,MAAM,eACJ,MACA,SACG;EACH,KAAK,IAAI,IAAI,GAAG,IAAI,gBAAgB,QAAQ,KAAK;GAC/C,MAAM,YAAY,gBAAgB;GAClC,MAAM,gBAAgB,UAAU;GAChC,MAAM,SAAS,UAAU;GAEzB,IAAI,UAAU;GAGd,IAAI,eAAe;IACjB,MAAM,SAAS,KAAK,SAAS,UAAU,EAAE;IACzC,MAAM,SAAS,KAAK,SAAS,UAAU,EAAE;IAEzC,MAAM,aAAa,WAAW;IAC9B,MAAM,aAAa,WAAW;IAE9B,IAAI,cAAc,YAChB;IAGF,IAAI,cAAc,YAAY;KAC5B,IAAI,kBAAkB,SAAS,OAAO,aAAa,KAAK;KACxD,IAAI,kBAAkB,QAAQ,OAAO,aAAa,IAAI;KACtD,UAAU,aAAa,gBAAgB,CAAC;IAC1C;GACF;GAEA,IAAI,YAAY,GACd,UAAU,UAAU,OAAO,MAAM,MAAM,UAAU,EAAE;GAIrD,IAAI,YAAY,GAAG;IACjB,IAAI,QACF,WAAW;IAGb,IAAI,UAAU,eACZ,WAAW;IAGb,OAAO;GACT;EACF;EAEA,OAAO,KAAK,QAAQ,KAAK;CAC3B;CAEA,MAAM,YAAY,SAAuC;EACvD,MAAM,aAAa,KAAK,MAAM;EAE9B,WAAW,KAAK,WAAW;EAI3B,KAAK,IAAI,IAAI,GAAG,IAAI,WAAW,QAAQ,KAAK;GAC1C,MAAM,MAAM,WAAW;GACvB,IAAI,IAAI,QAAQ,QAAQ;IAEtB,MAAM,SAAS,OAAO,OAAO,OAAO,eAAe,GAAG,CAAC;IACvD,OAAO,OAAO,QAAQ,GAAG;IACzB,OAAO,UAAU,SAAS,IAAI,OAAO;IACrC,WAAW,KAAK;IAChB,eAAe,KAAK,MAAM;GAC5B,OACE,eAAe,KAAK,GAAG;EAE3B;EAEA,OAAO;CACT;CAEA,OAAO;EACL,MAAM,SAAS,kBAAkB,IAAI;EACrC,UAAU;EACV,UAAU,kBAAkB;CAC9B;AACF"}
|
|
@@ -7,10 +7,12 @@
|
|
|
7
7
|
* can reuse already aggregated values.
|
|
8
8
|
*/
|
|
9
9
|
function aggregationFn_sum(columnId, _leafRows, childRows) {
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
10
|
+
let sumValue = 0;
|
|
11
|
+
for (let i = 0; i < childRows.length; i++) {
|
|
12
|
+
const nextValue = childRows[i].getValue(columnId);
|
|
13
|
+
sumValue += typeof nextValue === "number" ? nextValue : 0;
|
|
14
|
+
}
|
|
15
|
+
return sumValue;
|
|
14
16
|
}
|
|
15
17
|
/**
|
|
16
18
|
* Finds the minimum numeric child-row value for a grouped column.
|
|
@@ -20,10 +22,10 @@ function aggregationFn_sum(columnId, _leafRows, childRows) {
|
|
|
20
22
|
*/
|
|
21
23
|
function aggregationFn_min(columnId, _leafRows, childRows) {
|
|
22
24
|
let minValue;
|
|
23
|
-
childRows.
|
|
24
|
-
const value =
|
|
25
|
-
if (
|
|
26
|
-
}
|
|
25
|
+
for (let i = 0; i < childRows.length; i++) {
|
|
26
|
+
const value = childRows[i].getValue(columnId);
|
|
27
|
+
if (typeof value === "number" && (minValue === void 0 || value < minValue)) minValue = value;
|
|
28
|
+
}
|
|
27
29
|
return minValue;
|
|
28
30
|
}
|
|
29
31
|
/**
|
|
@@ -34,10 +36,10 @@ function aggregationFn_min(columnId, _leafRows, childRows) {
|
|
|
34
36
|
*/
|
|
35
37
|
function aggregationFn_max(columnId, _leafRows, childRows) {
|
|
36
38
|
let maxValue;
|
|
37
|
-
childRows.
|
|
38
|
-
const value =
|
|
39
|
-
if (
|
|
40
|
-
}
|
|
39
|
+
for (let i = 0; i < childRows.length; i++) {
|
|
40
|
+
const value = childRows[i].getValue(columnId);
|
|
41
|
+
if (typeof value === "number" && (maxValue === void 0 || value > maxValue)) maxValue = value;
|
|
42
|
+
}
|
|
41
43
|
return maxValue;
|
|
42
44
|
}
|
|
43
45
|
/**
|
|
@@ -49,14 +51,14 @@ function aggregationFn_max(columnId, _leafRows, childRows) {
|
|
|
49
51
|
function aggregationFn_extent(columnId, _leafRows, childRows) {
|
|
50
52
|
let minValue;
|
|
51
53
|
let maxValue;
|
|
52
|
-
childRows.
|
|
53
|
-
const value =
|
|
54
|
-
if (
|
|
54
|
+
for (let i = 0; i < childRows.length; i++) {
|
|
55
|
+
const value = childRows[i].getValue(columnId);
|
|
56
|
+
if (typeof value === "number") if (minValue === void 0) minValue = maxValue = value;
|
|
55
57
|
else {
|
|
56
58
|
if (minValue > value) minValue = value;
|
|
57
59
|
if (maxValue < value) maxValue = value;
|
|
58
60
|
}
|
|
59
|
-
}
|
|
61
|
+
}
|
|
60
62
|
return [minValue, maxValue];
|
|
61
63
|
}
|
|
62
64
|
/**
|
|
@@ -68,8 +70,8 @@ function aggregationFn_extent(columnId, _leafRows, childRows) {
|
|
|
68
70
|
function aggregationFn_mean(columnId, leafRows) {
|
|
69
71
|
let count = 0;
|
|
70
72
|
let sumValue = 0;
|
|
71
|
-
leafRows.
|
|
72
|
-
const value =
|
|
73
|
+
for (let i = 0; i < leafRows.length; i++) {
|
|
74
|
+
const value = leafRows[i].getValue(columnId);
|
|
73
75
|
if (value != null && typeof value === "number") {
|
|
74
76
|
++count;
|
|
75
77
|
sumValue += value;
|
|
@@ -80,7 +82,7 @@ function aggregationFn_mean(columnId, leafRows) {
|
|
|
80
82
|
sumValue += numValue;
|
|
81
83
|
}
|
|
82
84
|
}
|
|
83
|
-
}
|
|
85
|
+
}
|
|
84
86
|
if (count) return sumValue / count;
|
|
85
87
|
}
|
|
86
88
|
/**
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"aggregationFns.cjs","names":[],"sources":["../../src/fns/aggregationFns.ts"],"sourcesContent":["import type { RowData } from '../types/type-utils'\nimport type { TableFeatures } from '../types/TableFeatures'\nimport type { Row } from '../types/Row'\n\n/**\n * Sums numeric child-row values for a grouped column.\n *\n * Non-number values contribute `0`. Child rows are used so nested group totals\n * can reuse already aggregated values.\n */\nexport function aggregationFn_sum<\n TFeatures extends TableFeatures,\n TData extends RowData,\n>(\n columnId: string,\n _leafRows: Array<Row<TFeatures, TData>>,\n childRows: Array<Row<TFeatures, TData>>,\n) {\n // It's faster to just add the aggregations together instead of\n // process leaf nodes individually\n
|
|
1
|
+
{"version":3,"file":"aggregationFns.cjs","names":[],"sources":["../../src/fns/aggregationFns.ts"],"sourcesContent":["import type { RowData } from '../types/type-utils'\nimport type { TableFeatures } from '../types/TableFeatures'\nimport type { Row } from '../types/Row'\n\n/**\n * Sums numeric child-row values for a grouped column.\n *\n * Non-number values contribute `0`. Child rows are used so nested group totals\n * can reuse already aggregated values.\n */\nexport function aggregationFn_sum<\n TFeatures extends TableFeatures,\n TData extends RowData,\n>(\n columnId: string,\n _leafRows: Array<Row<TFeatures, TData>>,\n childRows: Array<Row<TFeatures, TData>>,\n) {\n // It's faster to just add the aggregations together instead of\n // process leaf nodes individually\n let sumValue = 0\n for (let i = 0; i < childRows.length; i++) {\n const nextValue = childRows[i]!.getValue(columnId)\n sumValue += typeof nextValue === 'number' ? nextValue : 0\n }\n return sumValue\n}\n\n/**\n * Finds the minimum numeric child-row value for a grouped column.\n *\n * Nullish and non-number values are ignored. Returns `undefined` when no\n * numeric value is found.\n */\nexport function aggregationFn_min<\n TFeatures extends TableFeatures,\n TData extends RowData,\n>(\n columnId: string,\n _leafRows: Array<Row<TFeatures, TData>>,\n childRows: Array<Row<TFeatures, TData>>,\n) {\n let minValue: number | undefined\n\n for (let i = 0; i < childRows.length; i++) {\n const value = childRows[i]!.getValue(columnId)\n\n if (\n typeof value === 'number' &&\n (minValue === undefined || value < minValue)\n ) {\n minValue = value\n }\n }\n\n return minValue\n}\n\n/**\n * Finds the maximum numeric child-row value for a grouped column.\n *\n * Nullish and non-number values are ignored. Returns `undefined` when no\n * numeric value is found.\n */\nexport function aggregationFn_max<\n TFeatures extends TableFeatures,\n TData extends RowData,\n>(\n columnId: string,\n _leafRows: Array<Row<TFeatures, TData>>,\n childRows: Array<Row<TFeatures, TData>>,\n) {\n let maxValue: number | undefined\n\n for (let i = 0; i < childRows.length; i++) {\n const value = childRows[i]!.getValue(columnId)\n if (\n typeof value === 'number' &&\n (maxValue === undefined || value > maxValue)\n ) {\n maxValue = value\n }\n }\n\n return maxValue\n}\n\n/**\n * Finds the numeric extent for a grouped column.\n *\n * Returns `[min, max]`, where each entry is `undefined` when no numeric value is\n * present.\n */\nexport function aggregationFn_extent<\n TFeatures extends TableFeatures,\n TData extends RowData,\n>(\n columnId: string,\n _leafRows: Array<Row<TFeatures, TData>>,\n childRows: Array<Row<TFeatures, TData>>,\n) {\n let minValue: number | undefined\n let maxValue: number | undefined\n\n for (let i = 0; i < childRows.length; i++) {\n const value = childRows[i]!.getValue(columnId)\n if (typeof value === 'number') {\n if (minValue === undefined) {\n minValue = maxValue = value\n } else {\n if (minValue > value) minValue = value\n if (maxValue! < value) maxValue = value\n }\n }\n }\n\n return [minValue, maxValue]\n}\n\n/**\n * Averages numeric leaf-row values for a grouped column.\n *\n * Number-like values are coerced with unary `+`; nullish and non-numeric values\n * are ignored.\n */\nexport function aggregationFn_mean<\n TFeatures extends TableFeatures,\n TData extends RowData,\n>(columnId: string, leafRows: Array<Row<TFeatures, TData>>) {\n let count = 0\n let sumValue = 0\n\n for (let i = 0; i < leafRows.length; i++) {\n const value = leafRows[i]!.getValue(columnId)\n if (value != null && typeof value === 'number') {\n ++count\n sumValue += value\n } else if (value != null) {\n const numValue = +value\n if (!Number.isNaN(numValue)) {\n ++count\n sumValue += numValue\n }\n }\n }\n\n if (count) return sumValue / count\n\n return\n}\n\n/**\n * Computes the median of numeric leaf-row values for a grouped column.\n *\n * All values must be numbers. If any value is non-numeric, or no leaf rows are\n * present, the result is `undefined`.\n */\nexport function aggregationFn_median<\n TFeatures extends TableFeatures,\n TData extends RowData,\n>(columnId: string, leafRows: Array<Row<TFeatures, TData>>) {\n if (!leafRows.length) {\n return\n }\n\n const values: Array<number> = new Array(leafRows.length)\n for (let i = 0; i < leafRows.length; i++) {\n const v = leafRows[i]!.getValue(columnId)\n if (typeof v !== 'number') return\n values[i] = v\n }\n\n if (values.length === 1) {\n return values[0]\n }\n\n const mid = Math.floor(values.length / 2)\n values.sort((a, b) => a - b)\n return values.length % 2 !== 0\n ? values[mid]\n : (values[mid - 1]! + values[mid]!) / 2\n}\n\n/**\n * Collects unique leaf-row values for a grouped column.\n *\n * Values are compared with JavaScript `Set` semantics.\n */\nexport function aggregationFn_unique<\n TFeatures extends TableFeatures,\n TData extends RowData,\n>(columnId: string, leafRows: Array<Row<TFeatures, TData>>) {\n const set = new Set<unknown>()\n for (let i = 0; i < leafRows.length; i++) {\n set.add(leafRows[i]!.getValue(columnId))\n }\n return Array.from(set.values())\n}\n\n/**\n * Counts unique leaf-row values for a grouped column.\n *\n * Values are compared with JavaScript `Set` semantics.\n */\nexport function aggregationFn_uniqueCount<\n TFeatures extends TableFeatures,\n TData extends RowData,\n>(columnId: string, leafRows: Array<Row<TFeatures, TData>>) {\n const set = new Set<unknown>()\n for (let i = 0; i < leafRows.length; i++) {\n set.add(leafRows[i]!.getValue(columnId))\n }\n return set.size\n}\n\n/**\n * Counts the number of leaf rows in the group.\n *\n * The column id is ignored because the result is based only on group size.\n */\nexport function aggregationFn_count<\n TFeatures extends TableFeatures,\n TData extends RowData,\n>(_columnId: string, leafRows: Array<Row<TFeatures, TData>>) {\n return leafRows.length\n}\n\n/**\n * The built-in aggregation function registry.\n *\n * Pass this object to grouped row model creation or extend it with custom aggregation functions for grouped columns.\n */\nexport const aggregationFns = {\n sum: aggregationFn_sum,\n min: aggregationFn_min,\n max: aggregationFn_max,\n extent: aggregationFn_extent,\n mean: aggregationFn_mean,\n median: aggregationFn_median,\n unique: aggregationFn_unique,\n uniqueCount: aggregationFn_uniqueCount,\n count: aggregationFn_count,\n}\n\nexport type BuiltInAggregationFn = keyof typeof aggregationFns\n"],"mappings":"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"}
|