@tanstack/table-core 9.0.0-beta.47 → 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 +1 -1
- package/dist/features/column-filtering/columnFilteringFeature.types.d.ts +1 -1
- package/dist/{fns → features/column-filtering}/filterFns.cjs +1 -1
- package/dist/features/column-filtering/filterFns.cjs.map +1 -0
- package/dist/{fns → features/column-filtering}/filterFns.d.cts +4 -4
- package/dist/{fns → features/column-filtering}/filterFns.d.ts +4 -4
- package/dist/{fns → features/column-filtering}/filterFns.js +1 -1
- 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 -87
- package/dist/features/column-grouping/columnGroupingFeature.types.d.ts +6 -87
- package/dist/features/column-grouping/columnGroupingFeature.utils.cjs +0 -64
- package/dist/features/column-grouping/columnGroupingFeature.utils.cjs.map +1 -1
- package/dist/features/column-grouping/columnGroupingFeature.utils.d.cts +2 -44
- package/dist/features/column-grouping/columnGroupingFeature.utils.d.ts +2 -44
- package/dist/features/column-grouping/columnGroupingFeature.utils.js +2 -63
- package/dist/features/column-grouping/columnGroupingFeature.utils.js.map +1 -1
- package/dist/features/column-grouping/createGroupedRowModel.cjs +23 -16
- package/dist/features/column-grouping/createGroupedRowModel.cjs.map +1 -1
- package/dist/features/column-grouping/createGroupedRowModel.d.cts +2 -6
- package/dist/features/column-grouping/createGroupedRowModel.d.ts +2 -6
- package/dist/features/column-grouping/createGroupedRowModel.js +25 -18
- package/dist/features/column-grouping/createGroupedRowModel.js.map +1 -1
- package/dist/features/global-filtering/globalFilteringFeature.utils.cjs +1 -1
- package/dist/features/global-filtering/globalFilteringFeature.utils.cjs.map +1 -1
- package/dist/features/global-filtering/globalFilteringFeature.utils.js +1 -1
- package/dist/features/global-filtering/globalFilteringFeature.utils.js.map +1 -1
- package/dist/features/row-sorting/rowSortingFeature.types.d.cts +1 -1
- package/dist/features/row-sorting/rowSortingFeature.types.d.ts +1 -1
- package/dist/features/row-sorting/rowSortingFeature.utils.cjs +1 -1
- package/dist/features/row-sorting/rowSortingFeature.utils.cjs.map +1 -1
- package/dist/features/row-sorting/rowSortingFeature.utils.js +1 -1
- package/dist/features/row-sorting/rowSortingFeature.utils.js.map +1 -1
- package/dist/{fns → features/row-sorting}/sortFns.cjs +1 -1
- package/dist/{fns/sortFns.js.map → features/row-sorting/sortFns.cjs.map} +1 -1
- package/dist/{fns → features/row-sorting}/sortFns.d.cts +4 -4
- package/dist/{fns → features/row-sorting}/sortFns.d.ts +4 -4
- package/dist/{fns → features/row-sorting}/sortFns.js +1 -1
- 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/index.cjs +7 -4
- package/dist/index.d.cts +7 -5
- package/dist/index.d.ts +7 -5
- 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 +4 -4
- package/dist/types/TableFeatures.d.ts +4 -4
- 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/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 +1 -1
- package/skills/column-filtering/SKILL.md +1 -1
- 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 +1 -1
- package/skills/grouping/SKILL.md +12 -18
- package/skills/migrate-v8-to-v9/SKILL.md +15 -2
- 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 +1 -1
- package/skills/table-features/SKILL.md +5 -2
- 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 +1 -1
- package/src/{fns → features/column-filtering}/filterFns.ts +4 -4
- package/src/features/column-grouping/columnGroupingFeature.ts +1 -20
- package/src/features/column-grouping/columnGroupingFeature.types.ts +4 -141
- package/src/features/column-grouping/columnGroupingFeature.utils.ts +1 -122
- package/src/features/column-grouping/createGroupedRowModel.ts +32 -41
- package/src/features/global-filtering/globalFilteringFeature.utils.ts +1 -1
- package/src/features/row-sorting/rowSortingFeature.types.ts +1 -1
- package/src/features/row-sorting/rowSortingFeature.utils.ts +1 -1
- package/src/{fns → features/row-sorting}/sortFns.ts +4 -7
- package/src/features/stockFeatures.ts +3 -0
- 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 +4 -4
- package/src/types/TableOptions.ts +5 -1
- package/src/worker/initTableWorker.ts +1 -1
- package/dist/fns/aggregationFns.cjs +0 -234
- package/dist/fns/aggregationFns.cjs.map +0 -1
- package/dist/fns/aggregationFns.d.cts +0 -139
- package/dist/fns/aggregationFns.d.ts +0 -139
- package/dist/fns/aggregationFns.js +0 -221
- package/dist/fns/aggregationFns.js.map +0 -1
- package/dist/fns/filterFns.cjs.map +0 -1
- package/dist/fns/filterFns.js.map +0 -1
- package/dist/fns/sortFns.cjs.map +0 -1
- package/src/fns/aggregationFns.ts +0 -303
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"columnGroupingFeature.utils.js","names":[],"sources":["../../../src/features/column-grouping/columnGroupingFeature.utils.ts"],"sourcesContent":["import { cloneState, hasOwn, isFunction } from '../../utils'\nimport type { Column_Internal } from '../../types/Column'\nimport type { CellData, RowData, Updater } from '../../types/type-utils'\nimport type { TableFeatures } from '../../types/TableFeatures'\nimport type { Table_Internal } from '../../types/Table'\nimport type { Row } from '../../types/Row'\nimport type { Cell } from '../../types/Cell'\nimport type {\n AggregationFn,\n GroupingState,\n Row_ColumnGrouping,\n} from './columnGroupingFeature.types'\n\n/**\n * Creates the default grouping state.\n *\n * The feature default is an empty array, meaning no columns are grouped. Reset\n * APIs use this value when `defaultState` is `true`.\n *\n * @example\n * ```ts\n * const grouping = getDefaultGroupingState()\n * ```\n */\nexport function getDefaultGroupingState(): GroupingState {\n return []\n}\n\n/**\n * Adds or removes this column id from the grouping state.\n *\n * Existing grouped columns keep their order. A column already present in\n * `state.grouping` is removed; otherwise it is appended.\n *\n * @example\n * ```ts\n * column_toggleGrouping(column)\n * ```\n */\nexport function column_toggleGrouping<\n TFeatures extends TableFeatures,\n TData extends RowData,\n TValue extends CellData = CellData,\n>(column: Column_Internal<TFeatures, TData, TValue>) {\n table_setGrouping(column.table, (old) => {\n // Find any existing grouping for this column\n if (old.includes(column.id)) {\n return old.filter((d) => d !== column.id)\n }\n\n return [...old, column.id]\n })\n}\n\n/**\n * Checks whether this column can be used for grouping.\n *\n * Grouping must be enabled at the column and table level, and the column must\n * either have an accessor or provide `getGroupingValue`.\n *\n * @example\n * ```ts\n * const canGroup = column_getCanGroup(column)\n * ```\n */\nexport function column_getCanGroup<\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.enableGrouping ?? true) &&\n (column.table.options.enableGrouping ?? true) &&\n (!!column.accessorFn || !!column.columnDef.getGroupingValue)\n )\n}\n\n/**\n * Checks whether this column id is present in `state.grouping`.\n *\n * The result only reflects grouping state, not whether the grouped row model has\n * been calculated yet.\n *\n * @example\n * ```ts\n * const isGrouped = column_getIsGrouped(column)\n * ```\n */\nexport function column_getIsGrouped<\n TFeatures extends TableFeatures,\n TData extends RowData,\n TValue extends CellData = CellData,\n>(column: Column_Internal<TFeatures, TData, TValue>): boolean {\n return !!column.table.atoms.grouping?.get()?.includes(column.id)\n}\n\n/**\n * Finds this column's position in the ordered grouping state.\n *\n * The result is `-1` when the column is not grouped.\n *\n * @example\n * ```ts\n * const index = column_getGroupedIndex(column)\n * ```\n */\nexport function column_getGroupedIndex<\n TFeatures extends TableFeatures,\n TData extends RowData,\n TValue extends CellData = CellData,\n>(column: Column_Internal<TFeatures, TData, TValue>): number {\n return column.table.atoms.grouping?.get()?.indexOf(column.id) ?? -1\n}\n\n/**\n * Creates a header/control handler that toggles grouping for this column.\n *\n * The handler is a no-op when `column_getCanGroup(column)` is false.\n *\n * @example\n * ```ts\n * const onClick = column_getToggleGroupingHandler(column)\n * ```\n */\nexport function column_getToggleGroupingHandler<\n TFeatures extends TableFeatures,\n TData extends RowData,\n TValue extends CellData = CellData,\n>(column: Column_Internal<TFeatures, TData, TValue>) {\n const canGroup = column_getCanGroup(column)\n\n return () => {\n if (!canGroup) return\n column_toggleGrouping(column)\n }\n}\n\n/**\n * Chooses a built-in aggregation function from the first core row value.\n *\n * Numeric columns default to `sum`, date-like values default to `extent`, and\n * other value types leave aggregation unspecified.\n *\n * The chosen aggregation function is looked up in the table's\n * `aggregationFns` registry. When it is not registered there, this returns\n * `undefined` and warns in development instead of substituting a different\n * aggregation function.\n *\n * @example\n * ```ts\n * const aggregationFn = column_getAutoAggregationFn(column)\n * ```\n */\nexport function column_getAutoAggregationFn<\n TFeatures extends TableFeatures,\n TData extends RowData,\n TValue extends CellData = CellData,\n>(column: Column_Internal<TFeatures, TData, TValue>) {\n const aggregationFns:\n | Record<string, AggregationFn<TFeatures, TData>>\n | undefined = column.table._rowModelFns.aggregationFns\n\n const firstRow = column.table.getCoreRowModel().flatRows[0]\n\n const value = firstRow?.getValue(column.id)\n\n let aggregationFnName: string | undefined\n\n if (typeof value === 'number') {\n aggregationFnName = 'sum'\n } else if (Object.prototype.toString.call(value) === '[object Date]') {\n aggregationFnName = 'extent'\n }\n\n if (!aggregationFnName) {\n return undefined\n }\n\n const aggregationFn = aggregationFns?.[aggregationFnName]\n\n if (process.env.NODE_ENV === 'development' && !aggregationFn) {\n console.warn(\n `aggregationFn '${aggregationFnName}' (auto) for column '${column.id}' is not registered`,\n )\n }\n\n return aggregationFn\n}\n\n/**\n * Resolves the aggregation function configured for a column.\n *\n * Function-valued `columnDef.aggregationFn` is returned directly, `'auto'`\n * delegates to `column_getAutoAggregationFn`, and string values are looked up in\n * the table's aggregation function registry.\n *\n * @example\n * ```ts\n * const aggregationFn = column_getAggregationFn(column)\n * ```\n */\nexport function column_getAggregationFn<\n TFeatures extends TableFeatures,\n TData extends RowData,\n TValue extends CellData = CellData,\n>(column: Column_Internal<TFeatures, TData, TValue>) {\n const aggregationFns:\n | Record<string, AggregationFn<TFeatures, TData>>\n | undefined = column.table._rowModelFns.aggregationFns\n\n if (isFunction(column.columnDef.aggregationFn)) {\n return column.columnDef.aggregationFn\n }\n\n if (column.columnDef.aggregationFn === 'auto') {\n return column_getAutoAggregationFn(column)\n }\n\n const aggregationFn =\n aggregationFns?.[column.columnDef.aggregationFn as string]\n\n if (\n process.env.NODE_ENV === 'development' &&\n !aggregationFn &&\n column.columnDef.aggregationFn != null\n ) {\n console.warn(\n `aggregationFn '${String(column.columnDef.aggregationFn)}' for column '${column.id}' is not registered`,\n )\n }\n\n return aggregationFn\n}\n\n/**\n * Routes a grouping updater through the table's grouping change handler.\n *\n * The updater may be a next `GroupingState` array or a function of the previous\n * grouping state, matching the instance `table.setGrouping` behavior.\n *\n * @example\n * ```ts\n * table_setGrouping(table, (old) => [...old, 'status'])\n * ```\n */\nexport function table_setGrouping<\n TFeatures extends TableFeatures,\n TData extends RowData,\n>(table: Table_Internal<TFeatures, TData>, updater: Updater<GroupingState>) {\n table.options.onGroupingChange?.(updater)\n}\n\n/**\n * Resets `grouping` to the configured initial state or feature default.\n *\n * With no argument, the reset clones `table.initialState.grouping` when it\n * exists. Passing `true` ignores initial state and resets to `[]`.\n *\n * @example\n * ```ts\n * table_resetGrouping(table)\n * table_resetGrouping(table, true)\n * ```\n */\nexport function table_resetGrouping<\n TFeatures extends TableFeatures,\n TData extends RowData,\n>(table: Table_Internal<TFeatures, TData>, defaultState?: boolean) {\n table_setGrouping(\n table,\n defaultState ? [] : cloneState(table.initialState.grouping ?? []),\n )\n}\n\n/**\n * Checks whether this row was created as a grouped row.\n *\n * Grouped rows carry a `groupingColumnId`; ordinary leaf rows do not.\n *\n * @example\n * ```ts\n * const isGrouped = row_getIsGrouped(row)\n * ```\n */\nexport function row_getIsGrouped<\n TFeatures extends TableFeatures,\n TData extends RowData,\n>(row: Row<TFeatures, TData> & Partial<Row_ColumnGrouping>) {\n return !!row.groupingColumnId\n}\n\n/**\n * Reads and caches this row's grouping value for a column.\n *\n * `columnDef.getGroupingValue` wins when provided; otherwise the normal row\n * accessor value is used.\n *\n * @example\n * ```ts\n * const groupValue = row_getGroupingValue(row, 'status')\n * ```\n */\nexport function row_getGroupingValue<\n TFeatures extends TableFeatures,\n TData extends RowData,\n>(row: Row<TFeatures, TData> & Partial<Row_ColumnGrouping>, columnId: string) {\n if (row._groupingValuesCache && hasOwn(row._groupingValuesCache, columnId)) {\n return row._groupingValuesCache[columnId]\n }\n\n const column = row.table.getColumn(columnId) as Column_Internal<\n TFeatures,\n TData\n >\n\n if (!column.columnDef.getGroupingValue) {\n return row.getValue(columnId)\n }\n\n if (row._groupingValuesCache) {\n row._groupingValuesCache[columnId] = column.columnDef.getGroupingValue(\n row.original,\n row.index,\n row,\n )\n }\n\n return row._groupingValuesCache?.[columnId]\n}\n\n/**\n * Checks whether this cell represents the grouped column for a grouped row.\n *\n * This is the cell that usually renders the grouped value and expansion control.\n *\n * @example\n * ```ts\n * const isGroupedCell = cell_getIsGrouped(cell)\n * ```\n */\nexport function cell_getIsGrouped<\n TFeatures extends TableFeatures,\n TData extends RowData,\n TValue extends CellData = CellData,\n>(cell: Cell<TFeatures, TData, TValue>) {\n const row = cell.row as Row<TFeatures, TData> & Partial<Row_ColumnGrouping>\n return (\n column_getIsGrouped(cell.column) && cell.column.id === row.groupingColumnId\n )\n}\n\n/**\n * Checks whether this cell is a placeholder hidden by grouping.\n *\n * Placeholder cells belong to grouped columns other than the row's active\n * grouping column.\n *\n * @example\n * ```ts\n * const isPlaceholder = cell_getIsPlaceholder(cell)\n * ```\n */\nexport function cell_getIsPlaceholder<\n TFeatures extends TableFeatures,\n TData extends RowData,\n TValue extends CellData = CellData,\n>(cell: Cell<TFeatures, TData, TValue>) {\n return !cell_getIsGrouped(cell) && column_getIsGrouped(cell.column)\n}\n\n/**\n * Checks whether this cell should render an aggregated value.\n *\n * Aggregated cells are non-placeholder, non-grouped cells on rows that have\n * subRows.\n *\n * @example\n * ```ts\n * const isAggregated = cell_getIsAggregated(cell)\n * ```\n */\nexport function cell_getIsAggregated<\n TFeatures extends TableFeatures,\n TData extends RowData,\n TValue extends CellData = CellData,\n>(cell: Cell<TFeatures, TData, TValue>) {\n return (\n !cell_getIsGrouped(cell) &&\n !cell_getIsPlaceholder(cell) &&\n !!cell.row.subRows.length\n )\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"columnGroupingFeature.utils.js","names":[],"sources":["../../../src/features/column-grouping/columnGroupingFeature.utils.ts"],"sourcesContent":["import { cloneState, hasOwn } from '../../utils'\nimport type { Column_Internal } from '../../types/Column'\nimport type { CellData, RowData, Updater } from '../../types/type-utils'\nimport type { TableFeatures } from '../../types/TableFeatures'\nimport type { Table_Internal } from '../../types/Table'\nimport type { Row } from '../../types/Row'\nimport type { Cell } from '../../types/Cell'\nimport type {\n GroupingState,\n Row_ColumnGrouping,\n} from './columnGroupingFeature.types'\n\n/**\n * Creates the default grouping state.\n *\n * The feature default is an empty array, meaning no columns are grouped. Reset\n * APIs use this value when `defaultState` is `true`.\n *\n * @example\n * ```ts\n * const grouping = getDefaultGroupingState()\n * ```\n */\nexport function getDefaultGroupingState(): GroupingState {\n return []\n}\n\n/**\n * Adds or removes this column id from the grouping state.\n *\n * Existing grouped columns keep their order. A column already present in\n * `state.grouping` is removed; otherwise it is appended.\n *\n * @example\n * ```ts\n * column_toggleGrouping(column)\n * ```\n */\nexport function column_toggleGrouping<\n TFeatures extends TableFeatures,\n TData extends RowData,\n TValue extends CellData = CellData,\n>(column: Column_Internal<TFeatures, TData, TValue>) {\n table_setGrouping(column.table, (old) => {\n // Find any existing grouping for this column\n if (old.includes(column.id)) {\n return old.filter((d) => d !== column.id)\n }\n\n return [...old, column.id]\n })\n}\n\n/**\n * Checks whether this column can be used for grouping.\n *\n * Grouping must be enabled at the column and table level, and the column must\n * either have an accessor or provide `getGroupingValue`.\n *\n * @example\n * ```ts\n * const canGroup = column_getCanGroup(column)\n * ```\n */\nexport function column_getCanGroup<\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.enableGrouping ?? true) &&\n (column.table.options.enableGrouping ?? true) &&\n (!!column.accessorFn || !!column.columnDef.getGroupingValue)\n )\n}\n\n/**\n * Checks whether this column id is present in `state.grouping`.\n *\n * The result only reflects grouping state, not whether the grouped row model has\n * been calculated yet.\n *\n * @example\n * ```ts\n * const isGrouped = column_getIsGrouped(column)\n * ```\n */\nexport function column_getIsGrouped<\n TFeatures extends TableFeatures,\n TData extends RowData,\n TValue extends CellData = CellData,\n>(column: Column_Internal<TFeatures, TData, TValue>): boolean {\n return !!column.table.atoms.grouping?.get()?.includes(column.id)\n}\n\n/**\n * Finds this column's position in the ordered grouping state.\n *\n * The result is `-1` when the column is not grouped.\n *\n * @example\n * ```ts\n * const index = column_getGroupedIndex(column)\n * ```\n */\nexport function column_getGroupedIndex<\n TFeatures extends TableFeatures,\n TData extends RowData,\n TValue extends CellData = CellData,\n>(column: Column_Internal<TFeatures, TData, TValue>): number {\n return column.table.atoms.grouping?.get()?.indexOf(column.id) ?? -1\n}\n\n/**\n * Creates a header/control handler that toggles grouping for this column.\n *\n * The handler is a no-op when `column_getCanGroup(column)` is false.\n *\n * @example\n * ```ts\n * const onClick = column_getToggleGroupingHandler(column)\n * ```\n */\nexport function column_getToggleGroupingHandler<\n TFeatures extends TableFeatures,\n TData extends RowData,\n TValue extends CellData = CellData,\n>(column: Column_Internal<TFeatures, TData, TValue>) {\n const canGroup = column_getCanGroup(column)\n\n return () => {\n if (!canGroup) return\n column_toggleGrouping(column)\n }\n}\n\n/**\n * Routes a grouping updater through the table's grouping change handler.\n *\n * The updater may be a next `GroupingState` array or a function of the previous\n * grouping state, matching the instance `table.setGrouping` behavior.\n *\n * @example\n * ```ts\n * table_setGrouping(table, (old) => [...old, 'status'])\n * ```\n */\nexport function table_setGrouping<\n TFeatures extends TableFeatures,\n TData extends RowData,\n>(table: Table_Internal<TFeatures, TData>, updater: Updater<GroupingState>) {\n table.options.onGroupingChange?.(updater)\n}\n\n/**\n * Resets `grouping` to the configured initial state or feature default.\n *\n * With no argument, the reset clones `table.initialState.grouping` when it\n * exists. Passing `true` ignores initial state and resets to `[]`.\n *\n * @example\n * ```ts\n * table_resetGrouping(table)\n * table_resetGrouping(table, true)\n * ```\n */\nexport function table_resetGrouping<\n TFeatures extends TableFeatures,\n TData extends RowData,\n>(table: Table_Internal<TFeatures, TData>, defaultState?: boolean) {\n table_setGrouping(\n table,\n defaultState ? [] : cloneState(table.initialState.grouping ?? []),\n )\n}\n\n/**\n * Checks whether this row was created as a grouped row.\n *\n * Grouped rows carry a `groupingColumnId`; ordinary leaf rows do not.\n *\n * @example\n * ```ts\n * const isGrouped = row_getIsGrouped(row)\n * ```\n */\nexport function row_getIsGrouped<\n TFeatures extends TableFeatures,\n TData extends RowData,\n>(row: Row<TFeatures, TData> & Partial<Row_ColumnGrouping>) {\n return !!row.groupingColumnId\n}\n\n/**\n * Reads and caches this row's grouping value for a column.\n *\n * `columnDef.getGroupingValue` wins when provided; otherwise the normal row\n * accessor value is used.\n *\n * @example\n * ```ts\n * const groupValue = row_getGroupingValue(row, 'status')\n * ```\n */\nexport function row_getGroupingValue<\n TFeatures extends TableFeatures,\n TData extends RowData,\n>(row: Row<TFeatures, TData> & Partial<Row_ColumnGrouping>, columnId: string) {\n if (row._groupingValuesCache && hasOwn(row._groupingValuesCache, columnId)) {\n return row._groupingValuesCache[columnId]\n }\n\n const column = row.table.getColumn(columnId) as Column_Internal<\n TFeatures,\n TData\n >\n\n if (!column.columnDef.getGroupingValue) {\n return row.getValue(columnId)\n }\n\n if (row._groupingValuesCache) {\n row._groupingValuesCache[columnId] = column.columnDef.getGroupingValue(\n row.original,\n row.index,\n row,\n )\n }\n\n return row._groupingValuesCache?.[columnId]\n}\n\n/**\n * Checks whether this cell represents the grouped column for a grouped row.\n *\n * This is the cell that usually renders the grouped value and expansion control.\n *\n * @example\n * ```ts\n * const isGroupedCell = cell_getIsGrouped(cell)\n * ```\n */\nexport function cell_getIsGrouped<\n TFeatures extends TableFeatures,\n TData extends RowData,\n TValue extends CellData = CellData,\n>(cell: Cell<TFeatures, TData, TValue>) {\n const row = cell.row as Row<TFeatures, TData> & Partial<Row_ColumnGrouping>\n return (\n column_getIsGrouped(cell.column) && cell.column.id === row.groupingColumnId\n )\n}\n\n/**\n * Checks whether this cell is a placeholder hidden by grouping.\n *\n * Placeholder cells belong to grouped columns other than the row's active\n * grouping column.\n *\n * @example\n * ```ts\n * const isPlaceholder = cell_getIsPlaceholder(cell)\n * ```\n */\nexport function cell_getIsPlaceholder<\n TFeatures extends TableFeatures,\n TData extends RowData,\n TValue extends CellData = CellData,\n>(cell: Cell<TFeatures, TData, TValue>) {\n return !cell_getIsGrouped(cell) && column_getIsGrouped(cell.column)\n}\n"],"mappings":";;;;;;;;;;;;;;AAuBA,SAAgB,0BAAyC;CACvD,OAAO,CAAC;AACV;;;;;;;;;;;;AAaA,SAAgB,sBAId,QAAmD;CACnD,kBAAkB,OAAO,QAAQ,QAAQ;EAEvC,IAAI,IAAI,SAAS,OAAO,EAAE,GACxB,OAAO,IAAI,QAAQ,MAAM,MAAM,OAAO,EAAE;EAG1C,OAAO,CAAC,GAAG,KAAK,OAAO,EAAE;CAC3B,CAAC;AACH;;;;;;;;;;;;AAaA,SAAgB,mBAId,QAAmD;CACnD,QACG,OAAO,UAAU,kBAAkB,UACnC,OAAO,MAAM,QAAQ,kBAAkB,UACvC,CAAC,CAAC,OAAO,cAAc,CAAC,CAAC,OAAO,UAAU;AAE/C;;;;;;;;;;;;AAaA,SAAgB,oBAId,QAA4D;CAC5D,OAAO,CAAC,CAAC,OAAO,MAAM,MAAM,UAAU,IAAI,CAAC,EAAE,SAAS,OAAO,EAAE;AACjE;;;;;;;;;;;AAYA,SAAgB,uBAId,QAA2D;CAC3D,OAAO,OAAO,MAAM,MAAM,UAAU,IAAI,CAAC,EAAE,QAAQ,OAAO,EAAE,KAAK;AACnE;;;;;;;;;;;AAYA,SAAgB,gCAId,QAAmD;CACnD,MAAM,WAAW,mBAAmB,MAAM;CAE1C,aAAa;EACX,IAAI,CAAC,UAAU;EACf,sBAAsB,MAAM;CAC9B;AACF;;;;;;;;;;;;AAaA,SAAgB,kBAGd,OAAyC,SAAiC;CAC1E,MAAM,QAAQ,mBAAmB,OAAO;AAC1C;;;;;;;;;;;;;AAcA,SAAgB,oBAGd,OAAyC,cAAwB;CACjE,kBACE,OACA,eAAe,CAAC,IAAI,WAAW,MAAM,aAAa,YAAY,CAAC,CAAC,CAClE;AACF;;;;;;;;;;;AAYA,SAAgB,iBAGd,KAA0D;CAC1D,OAAO,CAAC,CAAC,IAAI;AACf;;;;;;;;;;;;AAaA,SAAgB,qBAGd,KAA0D,UAAkB;CAC5E,IAAI,IAAI,wBAAwB,OAAO,IAAI,sBAAsB,QAAQ,GACvE,OAAO,IAAI,qBAAqB;CAGlC,MAAM,SAAS,IAAI,MAAM,UAAU,QAAQ;CAK3C,IAAI,CAAC,OAAO,UAAU,kBACpB,OAAO,IAAI,SAAS,QAAQ;CAG9B,IAAI,IAAI,sBACN,IAAI,qBAAqB,YAAY,OAAO,UAAU,iBACpD,IAAI,UACJ,IAAI,OACJ,GACF;CAGF,OAAO,IAAI,uBAAuB;AACpC;;;;;;;;;;;AAYA,SAAgB,kBAId,MAAsC;CACtC,MAAM,MAAM,KAAK;CACjB,OACE,oBAAoB,KAAK,MAAM,KAAK,KAAK,OAAO,OAAO,IAAI;AAE/D;;;;;;;;;;;;AAaA,SAAgB,sBAId,MAAsC;CACtC,OAAO,CAAC,kBAAkB,IAAI,KAAK,oBAAoB,KAAK,MAAM;AACpE"}
|
|
@@ -2,6 +2,7 @@ const require_utils = require('../../utils.cjs');
|
|
|
2
2
|
const require_coreColumnsFeature_utils = require('../../core/columns/coreColumnsFeature.utils.cjs');
|
|
3
3
|
const require_constructRow = require('../../core/rows/constructRow.cjs');
|
|
4
4
|
const require_rowPaginationFeature_utils = require('../row-pagination/rowPaginationFeature.utils.cjs');
|
|
5
|
+
const require_aggregationFeature_utils = require('../aggregation/aggregationFeature.utils.cjs');
|
|
5
6
|
const require_columnGroupingFeature_utils = require('./columnGroupingFeature.utils.cjs');
|
|
6
7
|
const require_rowExpandingFeature_utils = require('../row-expanding/rowExpandingFeature.utils.cjs');
|
|
7
8
|
|
|
@@ -11,12 +12,8 @@ const require_rowExpandingFeature_utils = require('../row-expanding/rowExpanding
|
|
|
11
12
|
*
|
|
12
13
|
* The factory reads the relevant table state atoms and options, then returns a row model function used by the table row-model pipeline.
|
|
13
14
|
*
|
|
14
|
-
*
|
|
15
|
-
*
|
|
16
|
-
* `tableFeatures({ columnGroupingFeature, groupedRowModel: createGroupedRowModel(), aggregationFns: { sum: aggregationFn_sum } })`.
|
|
17
|
-
* Importing individual `aggregationFn_*` functions keeps unused built-ins out
|
|
18
|
-
* of your bundle; aggregation functions passed directly to the
|
|
19
|
-
* `aggregationFn` column option need no registration at all.
|
|
15
|
+
* When aggregationFeature is also registered, grouped rows use its shared
|
|
16
|
+
* executor for non-group values. Grouping remains useful without aggregation.
|
|
20
17
|
*/
|
|
21
18
|
function createGroupedRowModel() {
|
|
22
19
|
return (_table) => {
|
|
@@ -25,7 +22,11 @@ function createGroupedRowModel() {
|
|
|
25
22
|
feature: "columnGroupingFeature",
|
|
26
23
|
table,
|
|
27
24
|
fnName: "table.getGroupedRowModel",
|
|
28
|
-
memoDeps: () => [
|
|
25
|
+
memoDeps: () => [
|
|
26
|
+
table.atoms.grouping?.get(),
|
|
27
|
+
table.getPreGroupedRowModel(),
|
|
28
|
+
table.options.columns
|
|
29
|
+
],
|
|
29
30
|
fn: () => _createGroupedRowModel(table),
|
|
30
31
|
onAfterUpdate: () => {
|
|
31
32
|
require_rowExpandingFeature_utils.table_autoResetExpanded(table);
|
|
@@ -69,7 +70,7 @@ function _createGroupedRowModel(table) {
|
|
|
69
70
|
subRows.forEach((subRow) => {
|
|
70
71
|
subRow.parentId = id;
|
|
71
72
|
});
|
|
72
|
-
const leafRows =
|
|
73
|
+
const leafRows = require_aggregationFeature_utils.normalizeAggregationRows(groupedRows);
|
|
73
74
|
const row = require_constructRow.constructRow(table, id, leafRows[0].original, index, depth, void 0, parentId);
|
|
74
75
|
Object.assign(row, {
|
|
75
76
|
groupingColumnId: columnId,
|
|
@@ -77,18 +78,24 @@ function _createGroupedRowModel(table) {
|
|
|
77
78
|
subRows,
|
|
78
79
|
leafRows,
|
|
79
80
|
getValue: (colId) => {
|
|
80
|
-
|
|
81
|
+
const groupingIndex = existingGrouping.indexOf(colId);
|
|
82
|
+
if (groupingIndex !== -1 && groupingIndex <= depth) {
|
|
81
83
|
if (require_utils.hasOwn(row._valuesCache, colId)) return row._valuesCache[colId];
|
|
82
84
|
if (groupedRows[0]) row._valuesCache[colId] = groupedRows[0].getValue(colId) ?? void 0;
|
|
83
85
|
return row._valuesCache[colId];
|
|
84
86
|
}
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
if (
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
87
|
+
const aggregationCache = row._aggregationValuesCache;
|
|
88
|
+
if (aggregationCache && require_utils.hasOwn(aggregationCache, colId)) return aggregationCache[colId];
|
|
89
|
+
const column = table.getColumn(colId);
|
|
90
|
+
if (typeof column.getAggregationFns !== "function") return void 0;
|
|
91
|
+
const cache = row._aggregationValuesCache ??= require_utils.makeObjectMap();
|
|
92
|
+
cache[colId] = require_aggregationFeature_utils.aggregateColumnValue({
|
|
93
|
+
childRows: subRows,
|
|
94
|
+
column,
|
|
95
|
+
groupingRow: row,
|
|
96
|
+
rows: leafRows
|
|
97
|
+
});
|
|
98
|
+
return cache[colId];
|
|
92
99
|
}
|
|
93
100
|
});
|
|
94
101
|
subRows.forEach((subRow) => {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"createGroupedRowModel.cjs","names":["tableMemo","table_getColumn","makeObjectMap","flattenBy","constructRow","hasOwn","column_getAggregationFn","row_getGroupingValue"],"sources":["../../../src/features/column-grouping/createGroupedRowModel.ts"],"sourcesContent":["import { flattenBy, hasOwn, makeObjectMap, tableMemo } from '../../utils'\nimport { constructRow } from '../../core/rows/constructRow'\nimport { table_getColumn } from '../../core/columns/coreColumnsFeature.utils'\nimport { table_autoResetExpanded } from '../row-expanding/rowExpandingFeature.utils'\nimport { table_autoResetPageIndex } from '../row-pagination/rowPaginationFeature.utils'\nimport {\n column_getAggregationFn,\n row_getGroupingValue,\n} from './columnGroupingFeature.utils'\nimport type { Column } from '../../types/Column'\nimport type { Row_ColumnGrouping } from './columnGroupingFeature.types'\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 { RowData } from '../../types/type-utils'\n\n/**\n * Creates a memoized grouped 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 the aggregation functions you use with the `aggregationFns` slot\n * on the `features` option:\n * `tableFeatures({ columnGroupingFeature, groupedRowModel: createGroupedRowModel(), aggregationFns: { sum: aggregationFn_sum } })`.\n * Importing individual `aggregationFn_*` functions keeps unused built-ins out\n * of your bundle; aggregation functions passed directly to the\n * `aggregationFn` column option need no registration at all.\n */\nexport function createGroupedRowModel<\n TFeatures extends TableFeatures,\n TData extends RowData = any,\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: 'columnGroupingFeature',\n table,\n fnName: 'table.getGroupedRowModel',\n memoDeps: () => [\n table.atoms.grouping?.get(),\n table.getPreGroupedRowModel(),\n ],\n fn: () => _createGroupedRowModel(table),\n onAfterUpdate: () => {\n table_autoResetExpanded(table)\n table_autoResetPageIndex(table)\n },\n })\n }\n}\n\nfunction _createGroupedRowModel<\n TFeatures extends TableFeatures,\n TData extends RowData = any,\n>(table: Table_Internal<TFeatures, TData>): RowModel<TFeatures, TData> {\n const rowModel = table.getPreGroupedRowModel()\n const grouping = table.atoms.grouping?.get()\n\n if (!rowModel.rows.length || !grouping?.length) {\n rowModel.rows.forEach((row) => {\n row.depth = 0\n row.parentId = undefined\n })\n return rowModel\n }\n\n // Filter the grouping list down to columns that exist\n const existingGrouping = grouping.filter((columnId) =>\n table_getColumn(table, columnId),\n )\n\n const groupedFlatRows: Array<Row<TFeatures, TData>> &\n Partial<Row_ColumnGrouping> = []\n const groupedRowsById = makeObjectMap<Row<TFeatures, TData>>()\n\n // Recursively group the data\n const groupUpRecursively = (\n rows: Array<Row<TFeatures, TData>>,\n depth = 0,\n parentId?: string,\n ) => {\n // Grouping depth has been been met\n // Stop grouping and simply rewrite thd depth and row relationships\n if (depth >= existingGrouping.length) {\n return rows.map((row) => {\n row.depth = depth\n\n // Every row is pushed into flatRows/rowsById exactly once, by its\n // parent frame: rows returned here are pushed by the caller (the\n // parent group's loop or the root loop), so only descendants below\n // the terminal depth are pushed here.\n if (row.subRows.length) {\n row.subRows = groupUpRecursively(row.subRows, depth + 1, row.id)\n for (let i = 0; i < row.subRows.length; i++) {\n const subRow = row.subRows[i]!\n groupedFlatRows.push(subRow)\n groupedRowsById[subRow.id] = subRow\n }\n }\n\n return row\n })\n }\n\n const columnId = existingGrouping[depth] as string\n\n // Group the rows together for this level\n const rowGroupsMap = groupBy(rows, columnId)\n\n // Perform aggregations for each group\n const aggregatedGroupedRows = Array.from(rowGroupsMap.entries()).map(\n ([groupingValue, groupedRows], index) => {\n let id = `${columnId}:${groupingValue}`\n id = parentId ? `${parentId}>${id}` : id\n\n // First, Recurse to group sub rows before aggregation\n const subRows = groupUpRecursively(groupedRows, depth + 1, id)\n\n subRows.forEach((subRow) => {\n subRow.parentId = id\n })\n\n // Flatten the leaf rows of the rows in this group\n const leafRows = depth\n ? flattenBy(groupedRows, (row) => row.subRows)\n : groupedRows\n\n const row = constructRow(\n table,\n id,\n leafRows[0]!.original,\n index,\n depth,\n undefined,\n parentId,\n ) as Row<TFeatures, TData> & Partial<Row_ColumnGrouping>\n\n Object.assign(row, {\n groupingColumnId: columnId,\n groupingValue,\n subRows,\n leafRows,\n getValue: (colId: string) => {\n // Don't aggregate columns that are in the grouping\n if (existingGrouping.includes(colId)) {\n if (hasOwn(row._valuesCache, colId)) {\n return row._valuesCache[colId]\n }\n\n if (groupedRows[0]) {\n row._valuesCache[colId] =\n groupedRows[0].getValue(colId) ?? undefined\n }\n\n return row._valuesCache[colId]\n }\n\n if (\n row._groupingValuesCache &&\n hasOwn(row._groupingValuesCache, colId)\n ) {\n return row._groupingValuesCache[colId]\n }\n\n // Aggregate the values\n const column = table.getColumn(colId)\n const aggregateFn = column_getAggregationFn(\n column as Column<TFeatures, TData, unknown>,\n )\n\n if (!row._groupingValuesCache) {\n row._groupingValuesCache = makeObjectMap()\n }\n\n if (aggregateFn) {\n row._groupingValuesCache[colId] = aggregateFn(\n colId,\n leafRows,\n groupedRows,\n )\n\n return row._groupingValuesCache[colId]\n }\n },\n })\n\n subRows.forEach((subRow) => {\n groupedFlatRows.push(subRow)\n groupedRowsById[subRow.id] = subRow\n })\n\n return row\n },\n )\n\n return aggregatedGroupedRows\n }\n\n const groupedRows = groupUpRecursively(rowModel.rows, 0)\n\n groupedRows.forEach((subRow) => {\n groupedFlatRows.push(subRow)\n groupedRowsById[subRow.id] = subRow\n })\n\n return {\n rows: groupedRows,\n flatRows: groupedFlatRows,\n rowsById: groupedRowsById,\n }\n}\n\nfunction groupBy<TFeatures extends TableFeatures, TData extends RowData = any>(\n rows: Array<Row<TFeatures, TData>>,\n columnId: string,\n) {\n const groupMap = new Map<any, Array<Row<TFeatures, TData>>>()\n\n return rows.reduce((map, row) => {\n const resKey = `${row_getGroupingValue(row, columnId)}`\n const previous = map.get(resKey)\n if (!previous) {\n map.set(resKey, [row])\n } else {\n previous.push(row)\n }\n return map\n }, groupMap)\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"createGroupedRowModel.cjs","names":["tableMemo","table_getColumn","makeObjectMap","normalizeAggregationRows","constructRow","hasOwn","aggregateColumnValue","row_getGroupingValue"],"sources":["../../../src/features/column-grouping/createGroupedRowModel.ts"],"sourcesContent":["import { hasOwn, makeObjectMap, tableMemo } from '../../utils'\nimport { constructRow } from '../../core/rows/constructRow'\nimport { table_getColumn } from '../../core/columns/coreColumnsFeature.utils'\nimport { table_autoResetExpanded } from '../row-expanding/rowExpandingFeature.utils'\nimport { table_autoResetPageIndex } from '../row-pagination/rowPaginationFeature.utils'\nimport {\n aggregateColumnValue,\n normalizeAggregationRows,\n} from '../aggregation/aggregationFeature.utils'\nimport { row_getGroupingValue } from './columnGroupingFeature.utils'\nimport type { Row_ColumnGrouping } from './columnGroupingFeature.types'\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 { RowData } from '../../types/type-utils'\n\n/**\n * Creates a memoized grouped 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 * When aggregationFeature is also registered, grouped rows use its shared\n * executor for non-group values. Grouping remains useful without aggregation.\n */\nexport function createGroupedRowModel<\n TFeatures extends TableFeatures,\n TData extends RowData = any,\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: 'columnGroupingFeature',\n table,\n fnName: 'table.getGroupedRowModel',\n memoDeps: () => [\n table.atoms.grouping?.get(),\n table.getPreGroupedRowModel(),\n table.options.columns,\n ],\n fn: () => _createGroupedRowModel(table),\n onAfterUpdate: () => {\n table_autoResetExpanded(table)\n table_autoResetPageIndex(table)\n },\n })\n }\n}\n\nfunction _createGroupedRowModel<\n TFeatures extends TableFeatures,\n TData extends RowData = any,\n>(table: Table_Internal<TFeatures, TData>): RowModel<TFeatures, TData> {\n const rowModel = table.getPreGroupedRowModel()\n const grouping = table.atoms.grouping?.get()\n\n if (!rowModel.rows.length || !grouping?.length) {\n rowModel.rows.forEach((row) => {\n row.depth = 0\n row.parentId = undefined\n })\n return rowModel\n }\n\n // Filter the grouping list down to columns that exist\n const existingGrouping = grouping.filter((columnId) =>\n table_getColumn(table, columnId),\n )\n\n const groupedFlatRows: Array<Row<TFeatures, TData>> &\n Partial<Row_ColumnGrouping> = []\n const groupedRowsById = makeObjectMap<Row<TFeatures, TData>>()\n\n // Recursively group the data\n const groupUpRecursively = (\n rows: Array<Row<TFeatures, TData>>,\n depth = 0,\n parentId?: string,\n ) => {\n // Grouping depth has been been met\n // Stop grouping and simply rewrite thd depth and row relationships\n if (depth >= existingGrouping.length) {\n return rows.map((row) => {\n row.depth = depth\n\n // Every row is pushed into flatRows/rowsById exactly once, by its\n // parent frame: rows returned here are pushed by the caller (the\n // parent group's loop or the root loop), so only descendants below\n // the terminal depth are pushed here.\n if (row.subRows.length) {\n row.subRows = groupUpRecursively(row.subRows, depth + 1, row.id)\n for (let i = 0; i < row.subRows.length; i++) {\n const subRow = row.subRows[i]!\n groupedFlatRows.push(subRow)\n groupedRowsById[subRow.id] = subRow\n }\n }\n\n return row\n })\n }\n\n const columnId = existingGrouping[depth] as string\n\n // Group the rows together for this level\n const rowGroupsMap = groupBy(rows, columnId)\n\n // Perform aggregations for each group\n const aggregatedGroupedRows = Array.from(rowGroupsMap.entries()).map(\n ([groupingValue, groupedRows], index) => {\n let id = `${columnId}:${groupingValue}`\n id = parentId ? `${parentId}>${id}` : id\n\n // First, Recurse to group sub rows before aggregation\n const subRows = groupUpRecursively(groupedRows, depth + 1, id)\n\n subRows.forEach((subRow) => {\n subRow.parentId = id\n })\n\n const leafRows = normalizeAggregationRows(groupedRows)\n\n const row = constructRow(\n table,\n id,\n leafRows[0]!.original,\n index,\n depth,\n undefined,\n parentId,\n ) as Row<TFeatures, TData> & Partial<Row_ColumnGrouping>\n\n Object.assign(row, {\n groupingColumnId: columnId,\n groupingValue,\n subRows,\n leafRows,\n getValue: (colId: string) => {\n const groupingIndex = existingGrouping.indexOf(colId)\n\n // The active grouping column and ancestor grouping columns expose\n // their inherited grouping values. Columns grouped at deeper\n // levels are still eligible for aggregation here.\n if (groupingIndex !== -1 && groupingIndex <= depth) {\n if (hasOwn(row._valuesCache, colId)) {\n return row._valuesCache[colId]\n }\n\n if (groupedRows[0]) {\n row._valuesCache[colId] =\n groupedRows[0].getValue(colId) ?? undefined\n }\n\n return row._valuesCache[colId]\n }\n\n const aggregationCache = (row as any)._aggregationValuesCache as\n | Record<string, unknown>\n | undefined\n if (aggregationCache && hasOwn(aggregationCache, colId)) {\n return aggregationCache[colId]\n }\n\n const column = table.getColumn(colId) as any\n if (typeof column.getAggregationFns !== 'function') return undefined\n\n const cache = ((row as any)._aggregationValuesCache ??=\n makeObjectMap())\n cache[colId] = aggregateColumnValue({\n childRows: subRows,\n column,\n groupingRow: row,\n rows: leafRows,\n })\n return cache[colId]\n },\n })\n\n subRows.forEach((subRow) => {\n groupedFlatRows.push(subRow)\n groupedRowsById[subRow.id] = subRow\n })\n\n return row\n },\n )\n\n return aggregatedGroupedRows\n }\n\n const groupedRows = groupUpRecursively(rowModel.rows, 0)\n\n groupedRows.forEach((subRow) => {\n groupedFlatRows.push(subRow)\n groupedRowsById[subRow.id] = subRow\n })\n\n return {\n rows: groupedRows,\n flatRows: groupedFlatRows,\n rowsById: groupedRowsById,\n }\n}\n\nfunction groupBy<TFeatures extends TableFeatures, TData extends RowData = any>(\n rows: Array<Row<TFeatures, TData>>,\n columnId: string,\n) {\n const groupMap = new Map<any, Array<Row<TFeatures, TData>>>()\n\n return rows.reduce((map, row) => {\n const resKey = `${row_getGroupingValue(row, columnId)}`\n const previous = map.get(resKey)\n if (!previous) {\n map.set(resKey, [row])\n } else {\n previous.push(row)\n }\n return map\n }, groupMap)\n}\n"],"mappings":"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"}
|
|
@@ -9,12 +9,8 @@ import { TableFeatures } from "../../types/TableFeatures.cjs";
|
|
|
9
9
|
*
|
|
10
10
|
* The factory reads the relevant table state atoms and options, then returns a row model function used by the table row-model pipeline.
|
|
11
11
|
*
|
|
12
|
-
*
|
|
13
|
-
*
|
|
14
|
-
* `tableFeatures({ columnGroupingFeature, groupedRowModel: createGroupedRowModel(), aggregationFns: { sum: aggregationFn_sum } })`.
|
|
15
|
-
* Importing individual `aggregationFn_*` functions keeps unused built-ins out
|
|
16
|
-
* of your bundle; aggregation functions passed directly to the
|
|
17
|
-
* `aggregationFn` column option need no registration at all.
|
|
12
|
+
* When aggregationFeature is also registered, grouped rows use its shared
|
|
13
|
+
* executor for non-group values. Grouping remains useful without aggregation.
|
|
18
14
|
*/
|
|
19
15
|
declare function createGroupedRowModel<TFeatures extends TableFeatures, TData extends RowData = any>(): (table: Table<TFeatures, TData>) => () => RowModel<TFeatures, TData>;
|
|
20
16
|
//#endregion
|
|
@@ -9,12 +9,8 @@ import { TableFeatures } from "../../types/TableFeatures.js";
|
|
|
9
9
|
*
|
|
10
10
|
* The factory reads the relevant table state atoms and options, then returns a row model function used by the table row-model pipeline.
|
|
11
11
|
*
|
|
12
|
-
*
|
|
13
|
-
*
|
|
14
|
-
* `tableFeatures({ columnGroupingFeature, groupedRowModel: createGroupedRowModel(), aggregationFns: { sum: aggregationFn_sum } })`.
|
|
15
|
-
* Importing individual `aggregationFn_*` functions keeps unused built-ins out
|
|
16
|
-
* of your bundle; aggregation functions passed directly to the
|
|
17
|
-
* `aggregationFn` column option need no registration at all.
|
|
12
|
+
* When aggregationFeature is also registered, grouped rows use its shared
|
|
13
|
+
* executor for non-group values. Grouping remains useful without aggregation.
|
|
18
14
|
*/
|
|
19
15
|
declare function createGroupedRowModel<TFeatures extends TableFeatures, TData extends RowData = any>(): (table: Table<TFeatures, TData>) => () => RowModel<TFeatures, TData>;
|
|
20
16
|
//#endregion
|
|
@@ -1,8 +1,9 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { hasOwn, makeObjectMap, tableMemo } from "../../utils.js";
|
|
2
2
|
import { table_getColumn } from "../../core/columns/coreColumnsFeature.utils.js";
|
|
3
3
|
import { constructRow } from "../../core/rows/constructRow.js";
|
|
4
4
|
import { table_autoResetPageIndex } from "../row-pagination/rowPaginationFeature.utils.js";
|
|
5
|
-
import {
|
|
5
|
+
import { aggregateColumnValue, normalizeAggregationRows } from "../aggregation/aggregationFeature.utils.js";
|
|
6
|
+
import { row_getGroupingValue } from "./columnGroupingFeature.utils.js";
|
|
6
7
|
import { table_autoResetExpanded } from "../row-expanding/rowExpandingFeature.utils.js";
|
|
7
8
|
|
|
8
9
|
//#region src/features/column-grouping/createGroupedRowModel.ts
|
|
@@ -11,12 +12,8 @@ import { table_autoResetExpanded } from "../row-expanding/rowExpandingFeature.ut
|
|
|
11
12
|
*
|
|
12
13
|
* The factory reads the relevant table state atoms and options, then returns a row model function used by the table row-model pipeline.
|
|
13
14
|
*
|
|
14
|
-
*
|
|
15
|
-
*
|
|
16
|
-
* `tableFeatures({ columnGroupingFeature, groupedRowModel: createGroupedRowModel(), aggregationFns: { sum: aggregationFn_sum } })`.
|
|
17
|
-
* Importing individual `aggregationFn_*` functions keeps unused built-ins out
|
|
18
|
-
* of your bundle; aggregation functions passed directly to the
|
|
19
|
-
* `aggregationFn` column option need no registration at all.
|
|
15
|
+
* When aggregationFeature is also registered, grouped rows use its shared
|
|
16
|
+
* executor for non-group values. Grouping remains useful without aggregation.
|
|
20
17
|
*/
|
|
21
18
|
function createGroupedRowModel() {
|
|
22
19
|
return (_table) => {
|
|
@@ -25,7 +22,11 @@ function createGroupedRowModel() {
|
|
|
25
22
|
feature: "columnGroupingFeature",
|
|
26
23
|
table,
|
|
27
24
|
fnName: "table.getGroupedRowModel",
|
|
28
|
-
memoDeps: () => [
|
|
25
|
+
memoDeps: () => [
|
|
26
|
+
table.atoms.grouping?.get(),
|
|
27
|
+
table.getPreGroupedRowModel(),
|
|
28
|
+
table.options.columns
|
|
29
|
+
],
|
|
29
30
|
fn: () => _createGroupedRowModel(table),
|
|
30
31
|
onAfterUpdate: () => {
|
|
31
32
|
table_autoResetExpanded(table);
|
|
@@ -69,7 +70,7 @@ function _createGroupedRowModel(table) {
|
|
|
69
70
|
subRows.forEach((subRow) => {
|
|
70
71
|
subRow.parentId = id;
|
|
71
72
|
});
|
|
72
|
-
const leafRows =
|
|
73
|
+
const leafRows = normalizeAggregationRows(groupedRows);
|
|
73
74
|
const row = constructRow(table, id, leafRows[0].original, index, depth, void 0, parentId);
|
|
74
75
|
Object.assign(row, {
|
|
75
76
|
groupingColumnId: columnId,
|
|
@@ -77,18 +78,24 @@ function _createGroupedRowModel(table) {
|
|
|
77
78
|
subRows,
|
|
78
79
|
leafRows,
|
|
79
80
|
getValue: (colId) => {
|
|
80
|
-
|
|
81
|
+
const groupingIndex = existingGrouping.indexOf(colId);
|
|
82
|
+
if (groupingIndex !== -1 && groupingIndex <= depth) {
|
|
81
83
|
if (hasOwn(row._valuesCache, colId)) return row._valuesCache[colId];
|
|
82
84
|
if (groupedRows[0]) row._valuesCache[colId] = groupedRows[0].getValue(colId) ?? void 0;
|
|
83
85
|
return row._valuesCache[colId];
|
|
84
86
|
}
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
if (
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
87
|
+
const aggregationCache = row._aggregationValuesCache;
|
|
88
|
+
if (aggregationCache && hasOwn(aggregationCache, colId)) return aggregationCache[colId];
|
|
89
|
+
const column = table.getColumn(colId);
|
|
90
|
+
if (typeof column.getAggregationFns !== "function") return void 0;
|
|
91
|
+
const cache = row._aggregationValuesCache ??= makeObjectMap();
|
|
92
|
+
cache[colId] = aggregateColumnValue({
|
|
93
|
+
childRows: subRows,
|
|
94
|
+
column,
|
|
95
|
+
groupingRow: row,
|
|
96
|
+
rows: leafRows
|
|
97
|
+
});
|
|
98
|
+
return cache[colId];
|
|
92
99
|
}
|
|
93
100
|
});
|
|
94
101
|
subRows.forEach((subRow) => {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"createGroupedRowModel.js","names":[],"sources":["../../../src/features/column-grouping/createGroupedRowModel.ts"],"sourcesContent":["import { flattenBy, hasOwn, makeObjectMap, tableMemo } from '../../utils'\nimport { constructRow } from '../../core/rows/constructRow'\nimport { table_getColumn } from '../../core/columns/coreColumnsFeature.utils'\nimport { table_autoResetExpanded } from '../row-expanding/rowExpandingFeature.utils'\nimport { table_autoResetPageIndex } from '../row-pagination/rowPaginationFeature.utils'\nimport {\n column_getAggregationFn,\n row_getGroupingValue,\n} from './columnGroupingFeature.utils'\nimport type { Column } from '../../types/Column'\nimport type { Row_ColumnGrouping } from './columnGroupingFeature.types'\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 { RowData } from '../../types/type-utils'\n\n/**\n * Creates a memoized grouped 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 the aggregation functions you use with the `aggregationFns` slot\n * on the `features` option:\n * `tableFeatures({ columnGroupingFeature, groupedRowModel: createGroupedRowModel(), aggregationFns: { sum: aggregationFn_sum } })`.\n * Importing individual `aggregationFn_*` functions keeps unused built-ins out\n * of your bundle; aggregation functions passed directly to the\n * `aggregationFn` column option need no registration at all.\n */\nexport function createGroupedRowModel<\n TFeatures extends TableFeatures,\n TData extends RowData = any,\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: 'columnGroupingFeature',\n table,\n fnName: 'table.getGroupedRowModel',\n memoDeps: () => [\n table.atoms.grouping?.get(),\n table.getPreGroupedRowModel(),\n ],\n fn: () => _createGroupedRowModel(table),\n onAfterUpdate: () => {\n table_autoResetExpanded(table)\n table_autoResetPageIndex(table)\n },\n })\n }\n}\n\nfunction _createGroupedRowModel<\n TFeatures extends TableFeatures,\n TData extends RowData = any,\n>(table: Table_Internal<TFeatures, TData>): RowModel<TFeatures, TData> {\n const rowModel = table.getPreGroupedRowModel()\n const grouping = table.atoms.grouping?.get()\n\n if (!rowModel.rows.length || !grouping?.length) {\n rowModel.rows.forEach((row) => {\n row.depth = 0\n row.parentId = undefined\n })\n return rowModel\n }\n\n // Filter the grouping list down to columns that exist\n const existingGrouping = grouping.filter((columnId) =>\n table_getColumn(table, columnId),\n )\n\n const groupedFlatRows: Array<Row<TFeatures, TData>> &\n Partial<Row_ColumnGrouping> = []\n const groupedRowsById = makeObjectMap<Row<TFeatures, TData>>()\n\n // Recursively group the data\n const groupUpRecursively = (\n rows: Array<Row<TFeatures, TData>>,\n depth = 0,\n parentId?: string,\n ) => {\n // Grouping depth has been been met\n // Stop grouping and simply rewrite thd depth and row relationships\n if (depth >= existingGrouping.length) {\n return rows.map((row) => {\n row.depth = depth\n\n // Every row is pushed into flatRows/rowsById exactly once, by its\n // parent frame: rows returned here are pushed by the caller (the\n // parent group's loop or the root loop), so only descendants below\n // the terminal depth are pushed here.\n if (row.subRows.length) {\n row.subRows = groupUpRecursively(row.subRows, depth + 1, row.id)\n for (let i = 0; i < row.subRows.length; i++) {\n const subRow = row.subRows[i]!\n groupedFlatRows.push(subRow)\n groupedRowsById[subRow.id] = subRow\n }\n }\n\n return row\n })\n }\n\n const columnId = existingGrouping[depth] as string\n\n // Group the rows together for this level\n const rowGroupsMap = groupBy(rows, columnId)\n\n // Perform aggregations for each group\n const aggregatedGroupedRows = Array.from(rowGroupsMap.entries()).map(\n ([groupingValue, groupedRows], index) => {\n let id = `${columnId}:${groupingValue}`\n id = parentId ? `${parentId}>${id}` : id\n\n // First, Recurse to group sub rows before aggregation\n const subRows = groupUpRecursively(groupedRows, depth + 1, id)\n\n subRows.forEach((subRow) => {\n subRow.parentId = id\n })\n\n // Flatten the leaf rows of the rows in this group\n const leafRows = depth\n ? flattenBy(groupedRows, (row) => row.subRows)\n : groupedRows\n\n const row = constructRow(\n table,\n id,\n leafRows[0]!.original,\n index,\n depth,\n undefined,\n parentId,\n ) as Row<TFeatures, TData> & Partial<Row_ColumnGrouping>\n\n Object.assign(row, {\n groupingColumnId: columnId,\n groupingValue,\n subRows,\n leafRows,\n getValue: (colId: string) => {\n // Don't aggregate columns that are in the grouping\n if (existingGrouping.includes(colId)) {\n if (hasOwn(row._valuesCache, colId)) {\n return row._valuesCache[colId]\n }\n\n if (groupedRows[0]) {\n row._valuesCache[colId] =\n groupedRows[0].getValue(colId) ?? undefined\n }\n\n return row._valuesCache[colId]\n }\n\n if (\n row._groupingValuesCache &&\n hasOwn(row._groupingValuesCache, colId)\n ) {\n return row._groupingValuesCache[colId]\n }\n\n // Aggregate the values\n const column = table.getColumn(colId)\n const aggregateFn = column_getAggregationFn(\n column as Column<TFeatures, TData, unknown>,\n )\n\n if (!row._groupingValuesCache) {\n row._groupingValuesCache = makeObjectMap()\n }\n\n if (aggregateFn) {\n row._groupingValuesCache[colId] = aggregateFn(\n colId,\n leafRows,\n groupedRows,\n )\n\n return row._groupingValuesCache[colId]\n }\n },\n })\n\n subRows.forEach((subRow) => {\n groupedFlatRows.push(subRow)\n groupedRowsById[subRow.id] = subRow\n })\n\n return row\n },\n )\n\n return aggregatedGroupedRows\n }\n\n const groupedRows = groupUpRecursively(rowModel.rows, 0)\n\n groupedRows.forEach((subRow) => {\n groupedFlatRows.push(subRow)\n groupedRowsById[subRow.id] = subRow\n })\n\n return {\n rows: groupedRows,\n flatRows: groupedFlatRows,\n rowsById: groupedRowsById,\n }\n}\n\nfunction groupBy<TFeatures extends TableFeatures, TData extends RowData = any>(\n rows: Array<Row<TFeatures, TData>>,\n columnId: string,\n) {\n const groupMap = new Map<any, Array<Row<TFeatures, TData>>>()\n\n return rows.reduce((map, row) => {\n const resKey = `${row_getGroupingValue(row, columnId)}`\n const previous = map.get(resKey)\n if (!previous) {\n map.set(resKey, [row])\n } else {\n previous.push(row)\n }\n return map\n }, groupMap)\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"createGroupedRowModel.js","names":[],"sources":["../../../src/features/column-grouping/createGroupedRowModel.ts"],"sourcesContent":["import { hasOwn, makeObjectMap, tableMemo } from '../../utils'\nimport { constructRow } from '../../core/rows/constructRow'\nimport { table_getColumn } from '../../core/columns/coreColumnsFeature.utils'\nimport { table_autoResetExpanded } from '../row-expanding/rowExpandingFeature.utils'\nimport { table_autoResetPageIndex } from '../row-pagination/rowPaginationFeature.utils'\nimport {\n aggregateColumnValue,\n normalizeAggregationRows,\n} from '../aggregation/aggregationFeature.utils'\nimport { row_getGroupingValue } from './columnGroupingFeature.utils'\nimport type { Row_ColumnGrouping } from './columnGroupingFeature.types'\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 { RowData } from '../../types/type-utils'\n\n/**\n * Creates a memoized grouped 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 * When aggregationFeature is also registered, grouped rows use its shared\n * executor for non-group values. Grouping remains useful without aggregation.\n */\nexport function createGroupedRowModel<\n TFeatures extends TableFeatures,\n TData extends RowData = any,\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: 'columnGroupingFeature',\n table,\n fnName: 'table.getGroupedRowModel',\n memoDeps: () => [\n table.atoms.grouping?.get(),\n table.getPreGroupedRowModel(),\n table.options.columns,\n ],\n fn: () => _createGroupedRowModel(table),\n onAfterUpdate: () => {\n table_autoResetExpanded(table)\n table_autoResetPageIndex(table)\n },\n })\n }\n}\n\nfunction _createGroupedRowModel<\n TFeatures extends TableFeatures,\n TData extends RowData = any,\n>(table: Table_Internal<TFeatures, TData>): RowModel<TFeatures, TData> {\n const rowModel = table.getPreGroupedRowModel()\n const grouping = table.atoms.grouping?.get()\n\n if (!rowModel.rows.length || !grouping?.length) {\n rowModel.rows.forEach((row) => {\n row.depth = 0\n row.parentId = undefined\n })\n return rowModel\n }\n\n // Filter the grouping list down to columns that exist\n const existingGrouping = grouping.filter((columnId) =>\n table_getColumn(table, columnId),\n )\n\n const groupedFlatRows: Array<Row<TFeatures, TData>> &\n Partial<Row_ColumnGrouping> = []\n const groupedRowsById = makeObjectMap<Row<TFeatures, TData>>()\n\n // Recursively group the data\n const groupUpRecursively = (\n rows: Array<Row<TFeatures, TData>>,\n depth = 0,\n parentId?: string,\n ) => {\n // Grouping depth has been been met\n // Stop grouping and simply rewrite thd depth and row relationships\n if (depth >= existingGrouping.length) {\n return rows.map((row) => {\n row.depth = depth\n\n // Every row is pushed into flatRows/rowsById exactly once, by its\n // parent frame: rows returned here are pushed by the caller (the\n // parent group's loop or the root loop), so only descendants below\n // the terminal depth are pushed here.\n if (row.subRows.length) {\n row.subRows = groupUpRecursively(row.subRows, depth + 1, row.id)\n for (let i = 0; i < row.subRows.length; i++) {\n const subRow = row.subRows[i]!\n groupedFlatRows.push(subRow)\n groupedRowsById[subRow.id] = subRow\n }\n }\n\n return row\n })\n }\n\n const columnId = existingGrouping[depth] as string\n\n // Group the rows together for this level\n const rowGroupsMap = groupBy(rows, columnId)\n\n // Perform aggregations for each group\n const aggregatedGroupedRows = Array.from(rowGroupsMap.entries()).map(\n ([groupingValue, groupedRows], index) => {\n let id = `${columnId}:${groupingValue}`\n id = parentId ? `${parentId}>${id}` : id\n\n // First, Recurse to group sub rows before aggregation\n const subRows = groupUpRecursively(groupedRows, depth + 1, id)\n\n subRows.forEach((subRow) => {\n subRow.parentId = id\n })\n\n const leafRows = normalizeAggregationRows(groupedRows)\n\n const row = constructRow(\n table,\n id,\n leafRows[0]!.original,\n index,\n depth,\n undefined,\n parentId,\n ) as Row<TFeatures, TData> & Partial<Row_ColumnGrouping>\n\n Object.assign(row, {\n groupingColumnId: columnId,\n groupingValue,\n subRows,\n leafRows,\n getValue: (colId: string) => {\n const groupingIndex = existingGrouping.indexOf(colId)\n\n // The active grouping column and ancestor grouping columns expose\n // their inherited grouping values. Columns grouped at deeper\n // levels are still eligible for aggregation here.\n if (groupingIndex !== -1 && groupingIndex <= depth) {\n if (hasOwn(row._valuesCache, colId)) {\n return row._valuesCache[colId]\n }\n\n if (groupedRows[0]) {\n row._valuesCache[colId] =\n groupedRows[0].getValue(colId) ?? undefined\n }\n\n return row._valuesCache[colId]\n }\n\n const aggregationCache = (row as any)._aggregationValuesCache as\n | Record<string, unknown>\n | undefined\n if (aggregationCache && hasOwn(aggregationCache, colId)) {\n return aggregationCache[colId]\n }\n\n const column = table.getColumn(colId) as any\n if (typeof column.getAggregationFns !== 'function') return undefined\n\n const cache = ((row as any)._aggregationValuesCache ??=\n makeObjectMap())\n cache[colId] = aggregateColumnValue({\n childRows: subRows,\n column,\n groupingRow: row,\n rows: leafRows,\n })\n return cache[colId]\n },\n })\n\n subRows.forEach((subRow) => {\n groupedFlatRows.push(subRow)\n groupedRowsById[subRow.id] = subRow\n })\n\n return row\n },\n )\n\n return aggregatedGroupedRows\n }\n\n const groupedRows = groupUpRecursively(rowModel.rows, 0)\n\n groupedRows.forEach((subRow) => {\n groupedFlatRows.push(subRow)\n groupedRowsById[subRow.id] = subRow\n })\n\n return {\n rows: groupedRows,\n flatRows: groupedFlatRows,\n rowsById: groupedRowsById,\n }\n}\n\nfunction groupBy<TFeatures extends TableFeatures, TData extends RowData = any>(\n rows: Array<Row<TFeatures, TData>>,\n columnId: string,\n) {\n const groupMap = new Map<any, Array<Row<TFeatures, TData>>>()\n\n return rows.reduce((map, row) => {\n const resKey = `${row_getGroupingValue(row, columnId)}`\n const previous = map.get(resKey)\n if (!previous) {\n map.set(resKey, [row])\n } else {\n previous.push(row)\n }\n return map\n }, groupMap)\n}\n"],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"globalFilteringFeature.utils.cjs","names":["filterFn_includesString","isFunction","cloneState"],"sources":["../../../src/features/global-filtering/globalFilteringFeature.utils.ts"],"sourcesContent":["import { filterFn_includesString } from '
|
|
1
|
+
{"version":3,"file":"globalFilteringFeature.utils.cjs","names":["filterFn_includesString","isFunction","cloneState"],"sources":["../../../src/features/global-filtering/globalFilteringFeature.utils.ts"],"sourcesContent":["import { filterFn_includesString } from '../column-filtering/filterFns'\nimport { cloneState, isFunction } from '../../utils'\nimport type { Column_Internal } from '../../types/Column'\nimport type { FilterFn } from '../column-filtering/columnFilteringFeature.types'\nimport type { CellData, RowData } from '../../types/type-utils'\nimport type { TableFeatures } from '../../types/TableFeatures'\nimport type { Table_Internal } from '../../types/Table'\n\n/**\n * Checks whether this accessor column participates in global filtering.\n *\n * The column must have an accessor and pass column-level, table-level, and\n * optional `getColumnCanGlobalFilter` checks.\n *\n * @example\n * ```ts\n * const canGlobalFilter = column_getCanGlobalFilter(column)\n * ```\n */\nexport function column_getCanGlobalFilter<\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.enableGlobalFilter ?? true) &&\n (column.table.options.enableGlobalFilter ?? true) &&\n (column.table.options.enableFilters ?? true) &&\n (column.table.options.getColumnCanGlobalFilter?.(column as any) ?? true) &&\n !!column.accessorFn\n )\n}\n\n/**\n * Provides the built-in automatic global filter function.\n *\n * Global filtering defaults to `includesString`, which gives search-box style\n * matching across globally filterable columns.\n *\n * @example\n * ```ts\n * const filterFn = table_getGlobalAutoFilterFn()\n * ```\n */\nexport function table_getGlobalAutoFilterFn() {\n return filterFn_includesString\n}\n\n/**\n * Resolves the filter function used for global filtering.\n *\n * Function-valued `options.globalFilterFn` is returned directly, `'auto'`\n * delegates to `table_getGlobalAutoFilterFn`, and string values are looked up in\n * the table's filter function registry.\n *\n * @example\n * ```ts\n * const filterFn = table_getGlobalFilterFn(table)\n * ```\n */\nexport function table_getGlobalFilterFn<\n TFeatures extends TableFeatures,\n TData extends RowData,\n>(\n table: Table_Internal<TFeatures, TData>,\n): FilterFn<TFeatures, TData> | undefined {\n const { globalFilterFn: globalFilterFn } = table.options\n const filterFns: Record<string, FilterFn<TFeatures, TData>> | undefined =\n table._rowModelFns.filterFns\n\n const filterFn = isFunction(globalFilterFn)\n ? globalFilterFn\n : globalFilterFn === 'auto'\n ? table_getGlobalAutoFilterFn()\n : filterFns?.[globalFilterFn as string]\n\n if (\n process.env.NODE_ENV === 'development' &&\n !filterFn &&\n globalFilterFn != null\n ) {\n console.warn(`globalFilterFn '${String(globalFilterFn)}' is not registered`)\n }\n\n return filterFn\n}\n\n/**\n * Routes a global filter updater through the table's global filter handler.\n *\n * The updater may be a next value or a function of the previous value, matching\n * the instance `table.setGlobalFilter` behavior.\n *\n * @example\n * ```ts\n * table_setGlobalFilter(table, 'search text')\n * ```\n */\nexport function table_setGlobalFilter<\n TFeatures extends TableFeatures,\n TData extends RowData,\n>(table: Table_Internal<TFeatures, TData>, updater: any) {\n table.options.onGlobalFilterChange?.(updater)\n}\n\n/**\n * Resets `globalFilter` to the configured initial state or feature default.\n *\n * With no argument, the reset clones `table.initialState.globalFilter`. Passing\n * `true` ignores initial state and resets to `undefined`.\n *\n * @example\n * ```ts\n * table_resetGlobalFilter(table)\n * table_resetGlobalFilter(table, true)\n * ```\n */\nexport function table_resetGlobalFilter<\n TFeatures extends TableFeatures,\n TData extends RowData,\n>(table: Table_Internal<TFeatures, TData>, defaultState?: boolean) {\n table_setGlobalFilter(\n table,\n defaultState ? undefined : cloneState(table.initialState.globalFilter),\n )\n}\n"],"mappings":";;;;;;;;;;;;;;;AAmBA,SAAgB,0BAId,QAA4D;CAC5D,QACG,OAAO,UAAU,sBAAsB,UACvC,OAAO,MAAM,QAAQ,sBAAsB,UAC3C,OAAO,MAAM,QAAQ,iBAAiB,UACtC,OAAO,MAAM,QAAQ,2BAA2B,MAAa,KAAK,SACnE,CAAC,CAAC,OAAO;AAEb;;;;;;;;;;;;AAaA,SAAgB,8BAA8B;CAC5C,OAAOA;AACT;;;;;;;;;;;;;AAcA,SAAgB,wBAId,OACwC;CACxC,MAAM,EAAkB,mBAAmB,MAAM;CACjD,MAAM,YACJ,MAAM,aAAa;CAErB,MAAM,WAAWC,yBAAW,cAAc,IACtC,iBACA,mBAAmB,SACjB,4BAA4B,IAC5B,YAAY;CAElB,IACE,QAAQ,IAAI,aAAa,iBACzB,CAAC,YACD,kBAAkB,MAElB,QAAQ,KAAK,mBAAmB,OAAO,cAAc,EAAE,oBAAoB;CAG7E,OAAO;AACT;;;;;;;;;;;;AAaA,SAAgB,sBAGd,OAAyC,SAAc;CACvD,MAAM,QAAQ,uBAAuB,OAAO;AAC9C;;;;;;;;;;;;;AAcA,SAAgB,wBAGd,OAAyC,cAAwB;CACjE,sBACE,OACA,eAAe,SAAYC,yBAAW,MAAM,aAAa,YAAY,CACvE;AACF"}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { cloneState, isFunction } from "../../utils.js";
|
|
2
|
-
import { filterFn_includesString } from "
|
|
2
|
+
import { filterFn_includesString } from "../column-filtering/filterFns.js";
|
|
3
3
|
|
|
4
4
|
//#region src/features/global-filtering/globalFilteringFeature.utils.ts
|
|
5
5
|
/**
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"globalFilteringFeature.utils.js","names":[],"sources":["../../../src/features/global-filtering/globalFilteringFeature.utils.ts"],"sourcesContent":["import { filterFn_includesString } from '
|
|
1
|
+
{"version":3,"file":"globalFilteringFeature.utils.js","names":[],"sources":["../../../src/features/global-filtering/globalFilteringFeature.utils.ts"],"sourcesContent":["import { filterFn_includesString } from '../column-filtering/filterFns'\nimport { cloneState, isFunction } from '../../utils'\nimport type { Column_Internal } from '../../types/Column'\nimport type { FilterFn } from '../column-filtering/columnFilteringFeature.types'\nimport type { CellData, RowData } from '../../types/type-utils'\nimport type { TableFeatures } from '../../types/TableFeatures'\nimport type { Table_Internal } from '../../types/Table'\n\n/**\n * Checks whether this accessor column participates in global filtering.\n *\n * The column must have an accessor and pass column-level, table-level, and\n * optional `getColumnCanGlobalFilter` checks.\n *\n * @example\n * ```ts\n * const canGlobalFilter = column_getCanGlobalFilter(column)\n * ```\n */\nexport function column_getCanGlobalFilter<\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.enableGlobalFilter ?? true) &&\n (column.table.options.enableGlobalFilter ?? true) &&\n (column.table.options.enableFilters ?? true) &&\n (column.table.options.getColumnCanGlobalFilter?.(column as any) ?? true) &&\n !!column.accessorFn\n )\n}\n\n/**\n * Provides the built-in automatic global filter function.\n *\n * Global filtering defaults to `includesString`, which gives search-box style\n * matching across globally filterable columns.\n *\n * @example\n * ```ts\n * const filterFn = table_getGlobalAutoFilterFn()\n * ```\n */\nexport function table_getGlobalAutoFilterFn() {\n return filterFn_includesString\n}\n\n/**\n * Resolves the filter function used for global filtering.\n *\n * Function-valued `options.globalFilterFn` is returned directly, `'auto'`\n * delegates to `table_getGlobalAutoFilterFn`, and string values are looked up in\n * the table's filter function registry.\n *\n * @example\n * ```ts\n * const filterFn = table_getGlobalFilterFn(table)\n * ```\n */\nexport function table_getGlobalFilterFn<\n TFeatures extends TableFeatures,\n TData extends RowData,\n>(\n table: Table_Internal<TFeatures, TData>,\n): FilterFn<TFeatures, TData> | undefined {\n const { globalFilterFn: globalFilterFn } = table.options\n const filterFns: Record<string, FilterFn<TFeatures, TData>> | undefined =\n table._rowModelFns.filterFns\n\n const filterFn = isFunction(globalFilterFn)\n ? globalFilterFn\n : globalFilterFn === 'auto'\n ? table_getGlobalAutoFilterFn()\n : filterFns?.[globalFilterFn as string]\n\n if (\n process.env.NODE_ENV === 'development' &&\n !filterFn &&\n globalFilterFn != null\n ) {\n console.warn(`globalFilterFn '${String(globalFilterFn)}' is not registered`)\n }\n\n return filterFn\n}\n\n/**\n * Routes a global filter updater through the table's global filter handler.\n *\n * The updater may be a next value or a function of the previous value, matching\n * the instance `table.setGlobalFilter` behavior.\n *\n * @example\n * ```ts\n * table_setGlobalFilter(table, 'search text')\n * ```\n */\nexport function table_setGlobalFilter<\n TFeatures extends TableFeatures,\n TData extends RowData,\n>(table: Table_Internal<TFeatures, TData>, updater: any) {\n table.options.onGlobalFilterChange?.(updater)\n}\n\n/**\n * Resets `globalFilter` to the configured initial state or feature default.\n *\n * With no argument, the reset clones `table.initialState.globalFilter`. Passing\n * `true` ignores initial state and resets to `undefined`.\n *\n * @example\n * ```ts\n * table_resetGlobalFilter(table)\n * table_resetGlobalFilter(table, true)\n * ```\n */\nexport function table_resetGlobalFilter<\n TFeatures extends TableFeatures,\n TData extends RowData,\n>(table: Table_Internal<TFeatures, TData>, defaultState?: boolean) {\n table_setGlobalFilter(\n table,\n defaultState ? undefined : cloneState(table.initialState.globalFilter),\n )\n}\n"],"mappings":";;;;;;;;;;;;;;;AAmBA,SAAgB,0BAId,QAA4D;CAC5D,QACG,OAAO,UAAU,sBAAsB,UACvC,OAAO,MAAM,QAAQ,sBAAsB,UAC3C,OAAO,MAAM,QAAQ,iBAAiB,UACtC,OAAO,MAAM,QAAQ,2BAA2B,MAAa,KAAK,SACnE,CAAC,CAAC,OAAO;AAEb;;;;;;;;;;;;AAaA,SAAgB,8BAA8B;CAC5C,OAAO;AACT;;;;;;;;;;;;;AAcA,SAAgB,wBAId,OACwC;CACxC,MAAM,EAAkB,mBAAmB,MAAM;CACjD,MAAM,YACJ,MAAM,aAAa;CAErB,MAAM,WAAW,WAAW,cAAc,IACtC,iBACA,mBAAmB,SACjB,4BAA4B,IAC5B,YAAY;CAElB,IACE,QAAQ,IAAI,aAAa,iBACzB,CAAC,YACD,kBAAkB,MAElB,QAAQ,KAAK,mBAAmB,OAAO,cAAc,EAAE,oBAAoB;CAG7E,OAAO;AACT;;;;;;;;;;;;AAaA,SAAgB,sBAGd,OAAyC,SAAc;CACvD,MAAM,QAAQ,uBAAuB,OAAO;AAC9C;;;;;;;;;;;;;AAcA,SAAgB,wBAGd,OAAyC,cAAwB;CACjE,sBACE,OACA,eAAe,SAAY,WAAW,MAAM,aAAa,YAAY,CACvE;AACF"}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { OnChangeFn, RowData, TransformDataValueFn, Updater } from "../../types/type-utils.cjs";
|
|
2
|
-
import { BuiltInSortFn } from "
|
|
2
|
+
import { BuiltInSortFn } from "./sortFns.cjs";
|
|
3
3
|
import { Row } from "../../types/Row.cjs";
|
|
4
4
|
import { RowModel } from "../../core/row-models/coreRowModelsFeature.types.cjs";
|
|
5
5
|
import { IsAny, TableFeatures } from "../../types/TableFeatures.cjs";
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { OnChangeFn, RowData, TransformDataValueFn, Updater } from "../../types/type-utils.js";
|
|
2
|
-
import { BuiltInSortFn } from "
|
|
2
|
+
import { BuiltInSortFn } from "./sortFns.js";
|
|
3
3
|
import { Row } from "../../types/Row.js";
|
|
4
4
|
import { RowModel } from "../../core/row-models/coreRowModelsFeature.types.js";
|
|
5
5
|
import { IsAny, TableFeatures } from "../../types/TableFeatures.js";
|
|
@@ -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 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
|
+
{"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
|
/**
|