@tanstack/table-core 9.0.0-beta.50 → 9.0.0-beta.52
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/features/column-grouping/createGroupedRowModel.cjs +22 -14
- package/dist/features/column-grouping/createGroupedRowModel.cjs.map +1 -1
- package/dist/features/column-grouping/createGroupedRowModel.d.cts +1 -1
- package/dist/features/column-grouping/createGroupedRowModel.d.ts +1 -1
- package/dist/features/column-grouping/createGroupedRowModel.js +21 -13
- package/dist/features/column-grouping/createGroupedRowModel.js.map +1 -1
- package/dist/features/{aggregation → row-aggregation}/aggregationFns.cjs +93 -48
- package/dist/features/row-aggregation/aggregationFns.cjs.map +1 -0
- package/dist/features/{aggregation → row-aggregation}/aggregationFns.d.cts +2 -2
- package/dist/features/{aggregation → row-aggregation}/aggregationFns.d.ts +2 -2
- package/dist/features/{aggregation → row-aggregation}/aggregationFns.js +82 -37
- package/dist/features/row-aggregation/aggregationFns.js.map +1 -0
- package/dist/features/row-aggregation/rowAggregationFeature.cjs +36 -0
- package/dist/features/row-aggregation/rowAggregationFeature.cjs.map +1 -0
- package/dist/features/row-aggregation/rowAggregationFeature.d.cts +10 -0
- package/dist/features/row-aggregation/rowAggregationFeature.d.ts +10 -0
- package/dist/features/{aggregation/aggregationFeature.js → row-aggregation/rowAggregationFeature.js} +8 -11
- package/dist/features/row-aggregation/rowAggregationFeature.js.map +1 -0
- package/dist/features/{aggregation/aggregationFeature.types.cjs → row-aggregation/rowAggregationFeature.types.cjs} +2 -2
- package/dist/features/row-aggregation/rowAggregationFeature.types.cjs.map +1 -0
- package/dist/features/{aggregation/aggregationFeature.types.d.cts → row-aggregation/rowAggregationFeature.types.d.cts} +8 -8
- package/dist/features/{aggregation/aggregationFeature.types.d.ts → row-aggregation/rowAggregationFeature.types.d.ts} +8 -8
- package/dist/features/{aggregation/aggregationFeature.types.js → row-aggregation/rowAggregationFeature.types.js} +2 -2
- package/dist/features/row-aggregation/rowAggregationFeature.types.js.map +1 -0
- package/dist/features/{aggregation/aggregationFeature.utils.cjs → row-aggregation/rowAggregationFeature.utils.cjs} +37 -6
- package/dist/features/row-aggregation/rowAggregationFeature.utils.cjs.map +1 -0
- package/dist/features/{aggregation/aggregationFeature.utils.d.cts → row-aggregation/rowAggregationFeature.utils.d.cts} +18 -4
- package/dist/features/{aggregation/aggregationFeature.utils.d.ts → row-aggregation/rowAggregationFeature.utils.d.ts} +18 -4
- package/dist/features/{aggregation/aggregationFeature.utils.js → row-aggregation/rowAggregationFeature.utils.js} +37 -7
- package/dist/features/row-aggregation/rowAggregationFeature.utils.js.map +1 -0
- package/dist/features/stockFeatures.cjs +2 -2
- package/dist/features/stockFeatures.cjs.map +1 -1
- package/dist/features/stockFeatures.d.cts +2 -2
- package/dist/features/stockFeatures.d.ts +2 -2
- package/dist/features/stockFeatures.js +2 -2
- package/dist/features/stockFeatures.js.map +1 -1
- package/dist/index.cjs +5 -5
- package/dist/index.d.cts +4 -4
- package/dist/index.d.ts +4 -4
- package/dist/index.js +4 -4
- package/dist/static-functions.cjs +9 -8
- package/dist/static-functions.d.cts +2 -2
- package/dist/static-functions.d.ts +2 -2
- package/dist/static-functions.js +2 -2
- package/dist/types/Cell.d.cts +2 -2
- package/dist/types/Cell.d.ts +2 -2
- package/dist/types/Column.d.cts +2 -2
- package/dist/types/Column.d.ts +2 -2
- package/dist/types/ColumnDef.d.cts +2 -2
- package/dist/types/ColumnDef.d.ts +2 -2
- package/dist/types/Row.d.cts +2 -2
- package/dist/types/Row.d.ts +2 -2
- package/dist/types/RowModelFns.d.cts +2 -2
- package/dist/types/RowModelFns.d.ts +2 -2
- package/dist/types/TableFeatures.d.cts +2 -2
- package/dist/types/TableFeatures.d.ts +2 -2
- package/dist/types/TableOptions.d.cts +3 -3
- package/dist/types/TableOptions.d.ts +3 -3
- 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 +6 -6
- 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 +1 -1
- package/skills/migrate-v8-to-v9/SKILL.md +8 -8
- package/skills/pagination/SKILL.md +1 -1
- package/skills/row-pinning/SKILL.md +1 -1
- package/skills/row-selection/SKILL.md +1 -1
- package/skills/sorting/SKILL.md +1 -1
- package/skills/table-features/SKILL.md +5 -5
- package/skills/typescript/SKILL.md +1 -1
- package/src/features/column-grouping/createGroupedRowModel.ts +49 -12
- package/src/features/{aggregation → row-aggregation}/aggregationFns.ts +81 -43
- package/src/features/{aggregation/aggregationFeature.ts → row-aggregation/rowAggregationFeature.ts} +5 -9
- package/src/features/{aggregation/aggregationFeature.types.ts → row-aggregation/rowAggregationFeature.types.ts} +6 -6
- package/src/features/{aggregation/aggregationFeature.utils.ts → row-aggregation/rowAggregationFeature.utils.ts} +61 -4
- package/src/features/stockFeatures.ts +3 -3
- package/src/index.ts +4 -4
- package/src/static-functions.ts +1 -1
- package/src/types/Cell.ts +2 -2
- package/src/types/Column.ts +2 -2
- package/src/types/ColumnDef.ts +2 -2
- package/src/types/Row.ts +2 -2
- package/src/types/RowModelFns.ts +2 -2
- package/src/types/TableFeatures.ts +2 -2
- package/src/types/TableOptions.ts +3 -3
- package/src/worker/initTableWorker.ts +1 -1
- package/dist/features/aggregation/aggregationFeature.cjs +0 -39
- package/dist/features/aggregation/aggregationFeature.cjs.map +0 -1
- package/dist/features/aggregation/aggregationFeature.d.cts +0 -10
- package/dist/features/aggregation/aggregationFeature.d.ts +0 -10
- package/dist/features/aggregation/aggregationFeature.js.map +0 -1
- package/dist/features/aggregation/aggregationFeature.types.cjs.map +0 -1
- package/dist/features/aggregation/aggregationFeature.types.js.map +0 -1
- package/dist/features/aggregation/aggregationFeature.utils.cjs.map +0 -1
- package/dist/features/aggregation/aggregationFeature.utils.js.map +0 -1
- package/dist/features/aggregation/aggregationFns.cjs.map +0 -1
- package/dist/features/aggregation/aggregationFns.js.map +0 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"initTableWorker.cjs","names":["makeObjectMap","constructTable","storeReactivityBindings","serializeRowModel"],"sources":["../../src/worker/initTableWorker.ts"],"sourcesContent":["import { constructTable } from '../core/table/constructTable'\nimport { storeReactivityBindings } from '../store-reactivity-bindings'\nimport { makeObjectMap } from '../utils'\nimport { serializeRowModel } from './serializeRowModel'\nimport type { RowData } from '../types/type-utils'\nimport type { TableFeatures } from '../types/TableFeatures'\nimport type { TableOptions } from '../types/TableOptions'\nimport type { Table_Internal } from '../types/Table'\nimport type {\n TableWorkerRequest,\n TableWorkerResult,\n TableWorkerStage,\n TableWorkerStagePayload,\n} from './tableWorkerProtocol'\n\nexport type TableWorkerConfig<\n TFeatures extends TableFeatures,\n TData extends RowData,\n> = Omit<TableOptions<TFeatures, TData>, 'data'>\n\nfunction capitalize(stage: string) {\n return stage.charAt(0).toUpperCase() + stage.slice(1)\n}\n\n/** Flatten column-group defs to leaf defs (mirrors core's id resolution). */\nfunction flattenColumnDefs(defs: Array<any>): Array<any> {\n return defs.flatMap((def) =>\n def.columns ? flattenColumnDefs(def.columns) : [def],\n )\n}\n\n/**\n * Runs a headless \"shadow table\" inside a dedicated Web Worker.\n *\n * Call this from a user-authored worker entry file, passing the same columns\n * and processing features used on the main thread. The shadow table runs the\n * real table-core row model pipeline (real fns, real Row objects) off the\n * main thread and posts back one payload per stage the main thread requested:\n * a transferable index permutation for flat results, a serialized row tree\n * (with eagerly computed aggregates) when grouping produces synthetic rows.\n *\n * Everything passed here must be thread-portable: `accessorKey` columns or\n * accessors defined in a shared module, and fns from registries or shared\n * modules (no closures over app state).\n *\n * @example\n * ```ts\n * // table.worker.ts\n * import { initTableWorker } from '@tanstack/table-core/experimental-worker-plugin'\n * import { columns, sharedFeatures } from './tableConfig'\n *\n * initTableWorker({ features: sharedFeatures, columns })\n * ```\n */\nexport function initTableWorker<\n TFeatures extends TableFeatures,\n TData extends RowData,\n>(config: TableWorkerConfig<TFeatures, TData>): void {\n let table: Table_Internal<TFeatures, TData> | undefined\n let dataVersion = 0\n let coreIndexById: Record<string, number> = makeObjectMap()\n let aggregateColumnIds: Array<string> = []\n // Last-sent model identity per stage: the memoized getters return stable\n // objects when their inputs did not change, so identity equality is exactly\n // \"this stage's result is unchanged\".\n let lastSentModels: { [K in TableWorkerStage]?: unknown } = {}\n\n self.onmessage = (event: MessageEvent<TableWorkerRequest<TData>>) => {\n const message = event.data\n\n if (message.type === 'data') {\n dataVersion = message.dataVersion\n lastSentModels = {}\n if (!table) {\n table = constructTable<TFeatures, TData>({\n ...(config as TableOptions<TFeatures, TData>),\n features: {\n coreReactivityFeature: storeReactivityBindings(),\n ...config.features,\n },\n data: message.data,\n })\n // Only columns with an explicit aggregation get eagerly aggregated\n // per group. Sync tables aggregate lazily (visible cells only), so\n // auto-aggregating every column would explode on high-cardinality\n // grouping for values nothing renders. Read the RAW column defs:\n //
|
|
1
|
+
{"version":3,"file":"initTableWorker.cjs","names":["makeObjectMap","constructTable","storeReactivityBindings","serializeRowModel"],"sources":["../../src/worker/initTableWorker.ts"],"sourcesContent":["import { constructTable } from '../core/table/constructTable'\nimport { storeReactivityBindings } from '../store-reactivity-bindings'\nimport { makeObjectMap } from '../utils'\nimport { serializeRowModel } from './serializeRowModel'\nimport type { RowData } from '../types/type-utils'\nimport type { TableFeatures } from '../types/TableFeatures'\nimport type { TableOptions } from '../types/TableOptions'\nimport type { Table_Internal } from '../types/Table'\nimport type {\n TableWorkerRequest,\n TableWorkerResult,\n TableWorkerStage,\n TableWorkerStagePayload,\n} from './tableWorkerProtocol'\n\nexport type TableWorkerConfig<\n TFeatures extends TableFeatures,\n TData extends RowData,\n> = Omit<TableOptions<TFeatures, TData>, 'data'>\n\nfunction capitalize(stage: string) {\n return stage.charAt(0).toUpperCase() + stage.slice(1)\n}\n\n/** Flatten column-group defs to leaf defs (mirrors core's id resolution). */\nfunction flattenColumnDefs(defs: Array<any>): Array<any> {\n return defs.flatMap((def) =>\n def.columns ? flattenColumnDefs(def.columns) : [def],\n )\n}\n\n/**\n * Runs a headless \"shadow table\" inside a dedicated Web Worker.\n *\n * Call this from a user-authored worker entry file, passing the same columns\n * and processing features used on the main thread. The shadow table runs the\n * real table-core row model pipeline (real fns, real Row objects) off the\n * main thread and posts back one payload per stage the main thread requested:\n * a transferable index permutation for flat results, a serialized row tree\n * (with eagerly computed aggregates) when grouping produces synthetic rows.\n *\n * Everything passed here must be thread-portable: `accessorKey` columns or\n * accessors defined in a shared module, and fns from registries or shared\n * modules (no closures over app state).\n *\n * @example\n * ```ts\n * // table.worker.ts\n * import { initTableWorker } from '@tanstack/table-core/experimental-worker-plugin'\n * import { columns, sharedFeatures } from './tableConfig'\n *\n * initTableWorker({ features: sharedFeatures, columns })\n * ```\n */\nexport function initTableWorker<\n TFeatures extends TableFeatures,\n TData extends RowData,\n>(config: TableWorkerConfig<TFeatures, TData>): void {\n let table: Table_Internal<TFeatures, TData> | undefined\n let dataVersion = 0\n let coreIndexById: Record<string, number> = makeObjectMap()\n let aggregateColumnIds: Array<string> = []\n // Last-sent model identity per stage: the memoized getters return stable\n // objects when their inputs did not change, so identity equality is exactly\n // \"this stage's result is unchanged\".\n let lastSentModels: { [K in TableWorkerStage]?: unknown } = {}\n\n self.onmessage = (event: MessageEvent<TableWorkerRequest<TData>>) => {\n const message = event.data\n\n if (message.type === 'data') {\n dataVersion = message.dataVersion\n lastSentModels = {}\n if (!table) {\n table = constructTable<TFeatures, TData>({\n ...(config as TableOptions<TFeatures, TData>),\n features: {\n coreReactivityFeature: storeReactivityBindings(),\n ...config.features,\n },\n data: message.data,\n })\n // Only columns with an explicit aggregation get eagerly aggregated\n // per group. Sync tables aggregate lazily (visible cells only), so\n // auto-aggregating every column would explode on high-cardinality\n // grouping for values nothing renders. Read the RAW column defs:\n // rowAggregationFeature injects default aggregatedCell/aggregationFn\n // into every resolved columnDef, so the resolved defs can't tell\n // explicit from default.\n aggregateColumnIds = flattenColumnDefs(config.columns as Array<any>)\n .filter(\n (def) => def.aggregationFn != null || def.aggregatedCell != null,\n )\n .map(\n (def) =>\n def.id ??\n (typeof def.accessorKey === 'string'\n ? def.accessorKey.replaceAll('.', '_')\n : undefined),\n )\n .filter((id): id is string => id != null)\n } else {\n table.setOptions((prev) => ({ ...prev, data: message.data }))\n }\n // Map row ids to data positions once per dataset; serialization uses it\n // to express every stage result in terms of core row positions.\n const coreFlatRows = table.getCoreRowModel().flatRows\n coreIndexById = makeObjectMap()\n for (let i = 0; i < coreFlatRows.length; i++) {\n coreIndexById[coreFlatRows[i]!.id] = i\n }\n return\n }\n\n if (!table) return\n\n const start = performance.now()\n\n // Apply the serializable state slices to the shadow table's base atoms.\n table._reactivity.batch(() => {\n for (const [key, value] of Object.entries(message.state)) {\n const baseAtom = (table!.baseAtoms as Record<string, any>)[key]\n if (baseAtom && value !== undefined) {\n baseAtom.set(value)\n }\n }\n })\n\n // Compute exactly the stages the main thread requested, skipping any this\n // shadow table has no row model factory for (the main thread warns).\n const stages: { [K in TableWorkerStage]?: TableWorkerStagePayload } = {}\n const transfer: Array<Transferable> = []\n\n for (const stage of message.stages) {\n if (!(config.features as Record<string, unknown>)[`${stage}RowModel`]) {\n continue\n }\n const model = (table as any)[`get${capitalize(stage)}RowModel`]()\n // Memoized getters return the same object when inputs are unchanged;\n // skip re-serializing (and the main thread skips rebuilding). Safe under\n // single-flight: results are never dropped within a dataVersion.\n if (lastSentModels[stage] === model) {\n stages[stage] = { kind: 'unchanged' }\n continue\n }\n lastSentModels[stage] = model\n stages[stage] = serializeRowModel(\n model,\n coreIndexById,\n aggregateColumnIds,\n transfer,\n )\n }\n\n const response: TableWorkerResult = {\n type: 'result',\n requestId: message.requestId,\n dataVersion,\n stages,\n computeMs: performance.now() - start,\n }\n postMessage(response, { transfer })\n }\n}\n"],"mappings":";;;;;;AAoBA,SAAS,WAAW,OAAe;CACjC,OAAO,MAAM,OAAO,CAAC,CAAC,CAAC,YAAY,IAAI,MAAM,MAAM,CAAC;AACtD;;AAGA,SAAS,kBAAkB,MAA8B;CACvD,OAAO,KAAK,SAAS,QACnB,IAAI,UAAU,kBAAkB,IAAI,OAAO,IAAI,CAAC,GAAG,CACrD;AACF;;;;;;;;;;;;;;;;;;;;;;;;AAyBA,SAAgB,gBAGd,QAAmD;CACnD,IAAI;CACJ,IAAI,cAAc;CAClB,IAAI,gBAAwCA,4BAAc;CAC1D,IAAI,qBAAoC,CAAC;CAIzC,IAAI,iBAAwD,CAAC;CAE7D,KAAK,aAAa,UAAmD;EACnE,MAAM,UAAU,MAAM;EAEtB,IAAI,QAAQ,SAAS,QAAQ;GAC3B,cAAc,QAAQ;GACtB,iBAAiB,CAAC;GAClB,IAAI,CAAC,OAAO;IACV,QAAQC,sCAAiC;KACvC,GAAI;KACJ,UAAU;MACR,uBAAuBC,0DAAwB;MAC/C,GAAG,OAAO;KACZ;KACA,MAAM,QAAQ;IAChB,CAAC;IAQD,qBAAqB,kBAAkB,OAAO,OAAqB,CAAC,CACjE,QACE,QAAQ,IAAI,iBAAiB,QAAQ,IAAI,kBAAkB,IAC9D,CAAC,CACA,KACE,QACC,IAAI,OACH,OAAO,IAAI,gBAAgB,WACxB,IAAI,YAAY,WAAW,KAAK,GAAG,IACnC,OACR,CAAC,CACA,QAAQ,OAAqB,MAAM,IAAI;GAC5C,OACE,MAAM,YAAY,UAAU;IAAE,GAAG;IAAM,MAAM,QAAQ;GAAK,EAAE;GAI9D,MAAM,eAAe,MAAM,gBAAgB,CAAC,CAAC;GAC7C,gBAAgBF,4BAAc;GAC9B,KAAK,IAAI,IAAI,GAAG,IAAI,aAAa,QAAQ,KACvC,cAAc,aAAa,EAAE,CAAE,MAAM;GAEvC;EACF;EAEA,IAAI,CAAC,OAAO;EAEZ,MAAM,QAAQ,YAAY,IAAI;EAG9B,MAAM,YAAY,YAAY;GAC5B,KAAK,MAAM,CAAC,KAAK,UAAU,OAAO,QAAQ,QAAQ,KAAK,GAAG;IACxD,MAAM,WAAY,MAAO,UAAkC;IAC3D,IAAI,YAAY,UAAU,QACxB,SAAS,IAAI,KAAK;GAEtB;EACF,CAAC;EAID,MAAM,SAAgE,CAAC;EACvE,MAAM,WAAgC,CAAC;EAEvC,KAAK,MAAM,SAAS,QAAQ,QAAQ;GAClC,IAAI,CAAE,OAAO,SAAqC,GAAG,MAAM,YACzD;GAEF,MAAM,QAAS,MAAc,MAAM,WAAW,KAAK,EAAE,UAAU,CAAC;GAIhE,IAAI,eAAe,WAAW,OAAO;IACnC,OAAO,SAAS,EAAE,MAAM,YAAY;IACpC;GACF;GACA,eAAe,SAAS;GACxB,OAAO,SAASG,4CACd,OACA,eACA,oBACA,QACF;EACF;EAEA,MAAM,WAA8B;GAClC,MAAM;GACN,WAAW,QAAQ;GACnB;GACA;GACA,WAAW,YAAY,IAAI,IAAI;EACjC;EACA,YAAY,UAAU,EAAE,SAAS,CAAC;CACpC;AACF"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"initTableWorker.js","names":[],"sources":["../../src/worker/initTableWorker.ts"],"sourcesContent":["import { constructTable } from '../core/table/constructTable'\nimport { storeReactivityBindings } from '../store-reactivity-bindings'\nimport { makeObjectMap } from '../utils'\nimport { serializeRowModel } from './serializeRowModel'\nimport type { RowData } from '../types/type-utils'\nimport type { TableFeatures } from '../types/TableFeatures'\nimport type { TableOptions } from '../types/TableOptions'\nimport type { Table_Internal } from '../types/Table'\nimport type {\n TableWorkerRequest,\n TableWorkerResult,\n TableWorkerStage,\n TableWorkerStagePayload,\n} from './tableWorkerProtocol'\n\nexport type TableWorkerConfig<\n TFeatures extends TableFeatures,\n TData extends RowData,\n> = Omit<TableOptions<TFeatures, TData>, 'data'>\n\nfunction capitalize(stage: string) {\n return stage.charAt(0).toUpperCase() + stage.slice(1)\n}\n\n/** Flatten column-group defs to leaf defs (mirrors core's id resolution). */\nfunction flattenColumnDefs(defs: Array<any>): Array<any> {\n return defs.flatMap((def) =>\n def.columns ? flattenColumnDefs(def.columns) : [def],\n )\n}\n\n/**\n * Runs a headless \"shadow table\" inside a dedicated Web Worker.\n *\n * Call this from a user-authored worker entry file, passing the same columns\n * and processing features used on the main thread. The shadow table runs the\n * real table-core row model pipeline (real fns, real Row objects) off the\n * main thread and posts back one payload per stage the main thread requested:\n * a transferable index permutation for flat results, a serialized row tree\n * (with eagerly computed aggregates) when grouping produces synthetic rows.\n *\n * Everything passed here must be thread-portable: `accessorKey` columns or\n * accessors defined in a shared module, and fns from registries or shared\n * modules (no closures over app state).\n *\n * @example\n * ```ts\n * // table.worker.ts\n * import { initTableWorker } from '@tanstack/table-core/experimental-worker-plugin'\n * import { columns, sharedFeatures } from './tableConfig'\n *\n * initTableWorker({ features: sharedFeatures, columns })\n * ```\n */\nexport function initTableWorker<\n TFeatures extends TableFeatures,\n TData extends RowData,\n>(config: TableWorkerConfig<TFeatures, TData>): void {\n let table: Table_Internal<TFeatures, TData> | undefined\n let dataVersion = 0\n let coreIndexById: Record<string, number> = makeObjectMap()\n let aggregateColumnIds: Array<string> = []\n // Last-sent model identity per stage: the memoized getters return stable\n // objects when their inputs did not change, so identity equality is exactly\n // \"this stage's result is unchanged\".\n let lastSentModels: { [K in TableWorkerStage]?: unknown } = {}\n\n self.onmessage = (event: MessageEvent<TableWorkerRequest<TData>>) => {\n const message = event.data\n\n if (message.type === 'data') {\n dataVersion = message.dataVersion\n lastSentModels = {}\n if (!table) {\n table = constructTable<TFeatures, TData>({\n ...(config as TableOptions<TFeatures, TData>),\n features: {\n coreReactivityFeature: storeReactivityBindings(),\n ...config.features,\n },\n data: message.data,\n })\n // Only columns with an explicit aggregation get eagerly aggregated\n // per group. Sync tables aggregate lazily (visible cells only), so\n // auto-aggregating every column would explode on high-cardinality\n // grouping for values nothing renders. Read the RAW column defs:\n //
|
|
1
|
+
{"version":3,"file":"initTableWorker.js","names":[],"sources":["../../src/worker/initTableWorker.ts"],"sourcesContent":["import { constructTable } from '../core/table/constructTable'\nimport { storeReactivityBindings } from '../store-reactivity-bindings'\nimport { makeObjectMap } from '../utils'\nimport { serializeRowModel } from './serializeRowModel'\nimport type { RowData } from '../types/type-utils'\nimport type { TableFeatures } from '../types/TableFeatures'\nimport type { TableOptions } from '../types/TableOptions'\nimport type { Table_Internal } from '../types/Table'\nimport type {\n TableWorkerRequest,\n TableWorkerResult,\n TableWorkerStage,\n TableWorkerStagePayload,\n} from './tableWorkerProtocol'\n\nexport type TableWorkerConfig<\n TFeatures extends TableFeatures,\n TData extends RowData,\n> = Omit<TableOptions<TFeatures, TData>, 'data'>\n\nfunction capitalize(stage: string) {\n return stage.charAt(0).toUpperCase() + stage.slice(1)\n}\n\n/** Flatten column-group defs to leaf defs (mirrors core's id resolution). */\nfunction flattenColumnDefs(defs: Array<any>): Array<any> {\n return defs.flatMap((def) =>\n def.columns ? flattenColumnDefs(def.columns) : [def],\n )\n}\n\n/**\n * Runs a headless \"shadow table\" inside a dedicated Web Worker.\n *\n * Call this from a user-authored worker entry file, passing the same columns\n * and processing features used on the main thread. The shadow table runs the\n * real table-core row model pipeline (real fns, real Row objects) off the\n * main thread and posts back one payload per stage the main thread requested:\n * a transferable index permutation for flat results, a serialized row tree\n * (with eagerly computed aggregates) when grouping produces synthetic rows.\n *\n * Everything passed here must be thread-portable: `accessorKey` columns or\n * accessors defined in a shared module, and fns from registries or shared\n * modules (no closures over app state).\n *\n * @example\n * ```ts\n * // table.worker.ts\n * import { initTableWorker } from '@tanstack/table-core/experimental-worker-plugin'\n * import { columns, sharedFeatures } from './tableConfig'\n *\n * initTableWorker({ features: sharedFeatures, columns })\n * ```\n */\nexport function initTableWorker<\n TFeatures extends TableFeatures,\n TData extends RowData,\n>(config: TableWorkerConfig<TFeatures, TData>): void {\n let table: Table_Internal<TFeatures, TData> | undefined\n let dataVersion = 0\n let coreIndexById: Record<string, number> = makeObjectMap()\n let aggregateColumnIds: Array<string> = []\n // Last-sent model identity per stage: the memoized getters return stable\n // objects when their inputs did not change, so identity equality is exactly\n // \"this stage's result is unchanged\".\n let lastSentModels: { [K in TableWorkerStage]?: unknown } = {}\n\n self.onmessage = (event: MessageEvent<TableWorkerRequest<TData>>) => {\n const message = event.data\n\n if (message.type === 'data') {\n dataVersion = message.dataVersion\n lastSentModels = {}\n if (!table) {\n table = constructTable<TFeatures, TData>({\n ...(config as TableOptions<TFeatures, TData>),\n features: {\n coreReactivityFeature: storeReactivityBindings(),\n ...config.features,\n },\n data: message.data,\n })\n // Only columns with an explicit aggregation get eagerly aggregated\n // per group. Sync tables aggregate lazily (visible cells only), so\n // auto-aggregating every column would explode on high-cardinality\n // grouping for values nothing renders. Read the RAW column defs:\n // rowAggregationFeature injects default aggregatedCell/aggregationFn\n // into every resolved columnDef, so the resolved defs can't tell\n // explicit from default.\n aggregateColumnIds = flattenColumnDefs(config.columns as Array<any>)\n .filter(\n (def) => def.aggregationFn != null || def.aggregatedCell != null,\n )\n .map(\n (def) =>\n def.id ??\n (typeof def.accessorKey === 'string'\n ? def.accessorKey.replaceAll('.', '_')\n : undefined),\n )\n .filter((id): id is string => id != null)\n } else {\n table.setOptions((prev) => ({ ...prev, data: message.data }))\n }\n // Map row ids to data positions once per dataset; serialization uses it\n // to express every stage result in terms of core row positions.\n const coreFlatRows = table.getCoreRowModel().flatRows\n coreIndexById = makeObjectMap()\n for (let i = 0; i < coreFlatRows.length; i++) {\n coreIndexById[coreFlatRows[i]!.id] = i\n }\n return\n }\n\n if (!table) return\n\n const start = performance.now()\n\n // Apply the serializable state slices to the shadow table's base atoms.\n table._reactivity.batch(() => {\n for (const [key, value] of Object.entries(message.state)) {\n const baseAtom = (table!.baseAtoms as Record<string, any>)[key]\n if (baseAtom && value !== undefined) {\n baseAtom.set(value)\n }\n }\n })\n\n // Compute exactly the stages the main thread requested, skipping any this\n // shadow table has no row model factory for (the main thread warns).\n const stages: { [K in TableWorkerStage]?: TableWorkerStagePayload } = {}\n const transfer: Array<Transferable> = []\n\n for (const stage of message.stages) {\n if (!(config.features as Record<string, unknown>)[`${stage}RowModel`]) {\n continue\n }\n const model = (table as any)[`get${capitalize(stage)}RowModel`]()\n // Memoized getters return the same object when inputs are unchanged;\n // skip re-serializing (and the main thread skips rebuilding). Safe under\n // single-flight: results are never dropped within a dataVersion.\n if (lastSentModels[stage] === model) {\n stages[stage] = { kind: 'unchanged' }\n continue\n }\n lastSentModels[stage] = model\n stages[stage] = serializeRowModel(\n model,\n coreIndexById,\n aggregateColumnIds,\n transfer,\n )\n }\n\n const response: TableWorkerResult = {\n type: 'result',\n requestId: message.requestId,\n dataVersion,\n stages,\n computeMs: performance.now() - start,\n }\n postMessage(response, { transfer })\n }\n}\n"],"mappings":";;;;;;AAoBA,SAAS,WAAW,OAAe;CACjC,OAAO,MAAM,OAAO,CAAC,CAAC,CAAC,YAAY,IAAI,MAAM,MAAM,CAAC;AACtD;;AAGA,SAAS,kBAAkB,MAA8B;CACvD,OAAO,KAAK,SAAS,QACnB,IAAI,UAAU,kBAAkB,IAAI,OAAO,IAAI,CAAC,GAAG,CACrD;AACF;;;;;;;;;;;;;;;;;;;;;;;;AAyBA,SAAgB,gBAGd,QAAmD;CACnD,IAAI;CACJ,IAAI,cAAc;CAClB,IAAI,gBAAwC,cAAc;CAC1D,IAAI,qBAAoC,CAAC;CAIzC,IAAI,iBAAwD,CAAC;CAE7D,KAAK,aAAa,UAAmD;EACnE,MAAM,UAAU,MAAM;EAEtB,IAAI,QAAQ,SAAS,QAAQ;GAC3B,cAAc,QAAQ;GACtB,iBAAiB,CAAC;GAClB,IAAI,CAAC,OAAO;IACV,QAAQ,eAAiC;KACvC,GAAI;KACJ,UAAU;MACR,uBAAuB,wBAAwB;MAC/C,GAAG,OAAO;KACZ;KACA,MAAM,QAAQ;IAChB,CAAC;IAQD,qBAAqB,kBAAkB,OAAO,OAAqB,CAAC,CACjE,QACE,QAAQ,IAAI,iBAAiB,QAAQ,IAAI,kBAAkB,IAC9D,CAAC,CACA,KACE,QACC,IAAI,OACH,OAAO,IAAI,gBAAgB,WACxB,IAAI,YAAY,WAAW,KAAK,GAAG,IACnC,OACR,CAAC,CACA,QAAQ,OAAqB,MAAM,IAAI;GAC5C,OACE,MAAM,YAAY,UAAU;IAAE,GAAG;IAAM,MAAM,QAAQ;GAAK,EAAE;GAI9D,MAAM,eAAe,MAAM,gBAAgB,CAAC,CAAC;GAC7C,gBAAgB,cAAc;GAC9B,KAAK,IAAI,IAAI,GAAG,IAAI,aAAa,QAAQ,KACvC,cAAc,aAAa,EAAE,CAAE,MAAM;GAEvC;EACF;EAEA,IAAI,CAAC,OAAO;EAEZ,MAAM,QAAQ,YAAY,IAAI;EAG9B,MAAM,YAAY,YAAY;GAC5B,KAAK,MAAM,CAAC,KAAK,UAAU,OAAO,QAAQ,QAAQ,KAAK,GAAG;IACxD,MAAM,WAAY,MAAO,UAAkC;IAC3D,IAAI,YAAY,UAAU,QACxB,SAAS,IAAI,KAAK;GAEtB;EACF,CAAC;EAID,MAAM,SAAgE,CAAC;EACvE,MAAM,WAAgC,CAAC;EAEvC,KAAK,MAAM,SAAS,QAAQ,QAAQ;GAClC,IAAI,CAAE,OAAO,SAAqC,GAAG,MAAM,YACzD;GAEF,MAAM,QAAS,MAAc,MAAM,WAAW,KAAK,EAAE,UAAU,CAAC;GAIhE,IAAI,eAAe,WAAW,OAAO;IACnC,OAAO,SAAS,EAAE,MAAM,YAAY;IACpC;GACF;GACA,eAAe,SAAS;GACxB,OAAO,SAAS,kBACd,OACA,eACA,oBACA,QACF;EACF;EAEA,MAAM,WAA8B;GAClC,MAAM;GACN,WAAW,QAAQ;GACnB;GACA;GACA,WAAW,YAAY,IAAI,IAAI;EACjC;EACA,YAAY,UAAU,EAAE,SAAS,CAAC;CACpC;AACF"}
|
package/package.json
CHANGED
|
@@ -6,13 +6,13 @@ metadata:
|
|
|
6
6
|
{
|
|
7
7
|
type: sub-skill,
|
|
8
8
|
library: '@tanstack/table-core',
|
|
9
|
-
library_version: '9.0.0-beta.
|
|
9
|
+
library_version: '9.0.0-beta.52',
|
|
10
10
|
}
|
|
11
11
|
requires: ['core', 'table-features']
|
|
12
12
|
sources:
|
|
13
13
|
- 'TanStack/table:docs/guide/aggregation.md'
|
|
14
14
|
- 'TanStack/table:docs/framework/react/guide/aggregation.md'
|
|
15
|
-
- 'TanStack/table:packages/table-core/src/features/aggregation'
|
|
15
|
+
- 'TanStack/table:packages/table-core/src/features/row-aggregation'
|
|
16
16
|
- 'TanStack/table:examples/react/aggregation'
|
|
17
17
|
- 'TanStack/table:examples/react/grouped-aggregation'
|
|
18
18
|
---
|
|
@@ -27,14 +27,14 @@ for synthetic grouped rows.
|
|
|
27
27
|
|
|
28
28
|
```ts
|
|
29
29
|
import {
|
|
30
|
-
|
|
30
|
+
rowAggregationFeature,
|
|
31
31
|
aggregationFn_mean,
|
|
32
32
|
aggregationFn_sum,
|
|
33
33
|
tableFeatures,
|
|
34
34
|
} from '@tanstack/table-core'
|
|
35
35
|
|
|
36
36
|
export const features = tableFeatures({
|
|
37
|
-
|
|
37
|
+
rowAggregationFeature,
|
|
38
38
|
aggregationFns: {
|
|
39
39
|
mean: aggregationFn_mean,
|
|
40
40
|
sum: aggregationFn_sum,
|
|
@@ -113,7 +113,7 @@ disables that local fallback.
|
|
|
113
113
|
|
|
114
114
|
Wrong: registering `columnGroupingFeature` solely to total a column.
|
|
115
115
|
|
|
116
|
-
Correct: register `
|
|
116
|
+
Correct: register `rowAggregationFeature` and call
|
|
117
117
|
`column.getAggregationValue()`. Grouping is only required for grouped rows.
|
|
118
118
|
|
|
119
119
|
### [HIGH] Passing a scope label and rows
|
|
@@ -136,6 +136,6 @@ grouped results sent by the worker must be structured-cloneable.
|
|
|
136
136
|
|
|
137
137
|
## API Discovery
|
|
138
138
|
|
|
139
|
-
Inspect `node_modules/@tanstack/table-core/src/features/aggregation/` and the
|
|
139
|
+
Inspect `node_modules/@tanstack/table-core/src/features/row-aggregation/` and the
|
|
140
140
|
Aggregation Guide. Use `Column_Aggregation`, `AggregationFnDef`,
|
|
141
141
|
`AggregationContext`, and `AggregationResult` for the typed public surface.
|
package/skills/core/SKILL.md
CHANGED
|
@@ -5,7 +5,7 @@ description: >
|
|
|
5
5
|
metadata:
|
|
6
6
|
type: sub-skill
|
|
7
7
|
library: '@tanstack/table-core'
|
|
8
|
-
library_version: '9.0.0-beta.
|
|
8
|
+
library_version: '9.0.0-beta.52'
|
|
9
9
|
requires: ['core', 'table-features', 'typescript']
|
|
10
10
|
sources:
|
|
11
11
|
- 'TanStack/table:docs/framework/react/guide/custom-features.md'
|
package/skills/grouping/SKILL.md
CHANGED
|
@@ -5,7 +5,7 @@ description: >
|
|
|
5
5
|
metadata:
|
|
6
6
|
type: lifecycle
|
|
7
7
|
library: '@tanstack/table-core'
|
|
8
|
-
library_version: '9.0.0-beta.
|
|
8
|
+
library_version: '9.0.0-beta.52'
|
|
9
9
|
requires: ['core', 'table-features', 'typescript']
|
|
10
10
|
sources:
|
|
11
11
|
- 'TanStack/table:docs/framework/react/guide/migrating.md'
|
|
@@ -68,18 +68,18 @@ V8 bundled all stock features. V9 exposes an API only when its feature is presen
|
|
|
68
68
|
|
|
69
69
|
| Capability | V9 feature |
|
|
70
70
|
| --------------------------- | ------------------------- |
|
|
71
|
+
| Aggregation | `rowAggregationFeature` |
|
|
71
72
|
| Column faceting | `columnFacetingFeature` |
|
|
72
73
|
| Column filtering | `columnFilteringFeature` |
|
|
73
|
-
| Aggregation | `aggregationFeature` |
|
|
74
|
-
| Grouping | `columnGroupingFeature` |
|
|
75
74
|
| Column ordering | `columnOrderingFeature` |
|
|
76
75
|
| Column pinning | `columnPinningFeature` |
|
|
77
|
-
| Interactive column resizing | `columnResizingFeature` |
|
|
78
76
|
| Column sizes and offsets | `columnSizingFeature` |
|
|
79
77
|
| Column visibility | `columnVisibilityFeature` |
|
|
80
78
|
| Global filtering | `globalFilteringFeature` |
|
|
81
|
-
|
|
|
79
|
+
| Grouping | `columnGroupingFeature` |
|
|
80
|
+
| Interactive column resizing | `columnResizingFeature` |
|
|
82
81
|
| Pagination | `rowPaginationFeature` |
|
|
82
|
+
| Row expansion | `rowExpandingFeature` |
|
|
83
83
|
| Row pinning | `rowPinningFeature` |
|
|
84
84
|
| Row selection | `rowSelectionFeature` |
|
|
85
85
|
| Sorting | `rowSortingFeature` |
|
|
@@ -91,7 +91,7 @@ Honor feature prerequisites in the same `tableFeatures` call:
|
|
|
91
91
|
- `columnResizingFeature` requires `columnSizingFeature`.
|
|
92
92
|
- `globalFilteringFeature` requires `columnFilteringFeature`.
|
|
93
93
|
- Every row-model or function-registry slot requires its associated feature.
|
|
94
|
-
- `aggregationFns` requires `
|
|
94
|
+
- `aggregationFns` requires `rowAggregationFeature`; grouped aggregation uses both `rowAggregationFeature` and `columnGroupingFeature`.
|
|
95
95
|
- Put prerequisite feature properties before dependent slots so inference and diagnostics remain clear.
|
|
96
96
|
|
|
97
97
|
### 2. Move row models into feature slots and rename factories
|
|
@@ -122,7 +122,7 @@ Move registries from table options or factory arguments into these feature slots
|
|
|
122
122
|
|
|
123
123
|
Register only the built-ins the table references by string name, importing each individually (`filterFn_includesString`, `sortFn_alphanumeric`, `aggregationFn_sum`, and so on) alongside any custom functions. The full registry objects (`filterFns`, `sortFns`, `aggregationFns` exports) still work but bundle every built-in. A slot's keys become the valid string names in column definitions, and `'auto'` resolves only registered functions.
|
|
124
124
|
|
|
125
|
-
Aggregation is independent from grouping. Add `
|
|
125
|
+
Aggregation is independent from grouping. Add `rowAggregationFeature` for
|
|
126
126
|
`aggregationFn`, `aggregatedCell`, `column.getAggregationValue(options?)`, and
|
|
127
127
|
`cell.getIsAggregated`. A root total does not require grouping. Convert legacy
|
|
128
128
|
custom callables `(columnId, leafRows, childRows) => result` to
|
|
@@ -300,7 +300,7 @@ Do not confuse new capabilities with required breakages. After the table works,
|
|
|
300
300
|
- [ ] Move all remaining `get*RowModel()` options or earlier-beta `rowModels` entries to `create*RowModel()` feature slots.
|
|
301
301
|
- [ ] Register each dependent feature before its row-model slot.
|
|
302
302
|
- [ ] Move `filterFns`, `sortingFns`/`sortFns`, and `aggregationFns` into feature slots, registering individually imported built-ins; pass no registries to factories.
|
|
303
|
-
- [ ] Register `
|
|
303
|
+
- [ ] Register `rowAggregationFeature` independently and migrate custom aggregation callables to context-based `AggregationFnDef` definitions.
|
|
304
304
|
- [ ] Register `columnFilteringFeature` before global filtering and filter/facet dependencies.
|
|
305
305
|
- [ ] Register `columnSizingFeature` before `columnResizingFeature`.
|
|
306
306
|
- [ ] Replace `table.getState()` and top-level `onStateChange` according to the adapter state guide.
|
package/skills/sorting/SKILL.md
CHANGED
|
@@ -5,7 +5,7 @@ description: >
|
|
|
5
5
|
metadata:
|
|
6
6
|
type: sub-skill
|
|
7
7
|
library: '@tanstack/table-core'
|
|
8
|
-
library_version: '9.0.0-beta.
|
|
8
|
+
library_version: '9.0.0-beta.52'
|
|
9
9
|
requires: ['core']
|
|
10
10
|
sources:
|
|
11
11
|
- 'TanStack/table:docs/guide/row-models.md'
|
|
@@ -22,7 +22,7 @@ This skill builds on `core`. Read it first for the headless model and stable inp
|
|
|
22
22
|
|
|
23
23
|
```ts
|
|
24
24
|
import {
|
|
25
|
-
|
|
25
|
+
rowAggregationFeature,
|
|
26
26
|
aggregationFn_sum,
|
|
27
27
|
columnGroupingFeature,
|
|
28
28
|
createFilteredRowModel,
|
|
@@ -38,7 +38,7 @@ export const features = tableFeatures({
|
|
|
38
38
|
columnFilteringFeature,
|
|
39
39
|
filteredRowModel: createFilteredRowModel(),
|
|
40
40
|
filterFns: { includesString: filterFn_includesString },
|
|
41
|
-
|
|
41
|
+
rowAggregationFeature,
|
|
42
42
|
columnGroupingFeature,
|
|
43
43
|
aggregationFns: { sum: aggregationFn_sum },
|
|
44
44
|
rowSortingFeature,
|
|
@@ -68,7 +68,7 @@ const features = tableFeatures({
|
|
|
68
68
|
filterFns: { includesString: filterFn_includesString },
|
|
69
69
|
rowSortingFeature,
|
|
70
70
|
sortFns: { alphanumeric: sortFn_alphanumeric },
|
|
71
|
-
|
|
71
|
+
rowAggregationFeature,
|
|
72
72
|
columnGroupingFeature,
|
|
73
73
|
aggregationFns: { sum: aggregationFn_sum },
|
|
74
74
|
})
|
|
@@ -76,7 +76,7 @@ const features = tableFeatures({
|
|
|
76
76
|
|
|
77
77
|
`filterFns`, `sortFns`, and `aggregationFns` are feature slots, not table
|
|
78
78
|
options. They respectively require `columnFilteringFeature`,
|
|
79
|
-
`rowSortingFeature`, and `
|
|
79
|
+
`rowSortingFeature`, and `rowAggregationFeature`. Import individual built-ins
|
|
80
80
|
(`filterFn_*`, `sortFn_*`, `aggregationFn_*`) and register them under their
|
|
81
81
|
conventional keys; the full registry objects (`filterFns`, `sortFns`,
|
|
82
82
|
`aggregationFns` exports) still work but bundle every built-in. A registered
|
|
@@ -5,10 +5,10 @@ import { table_autoResetExpanded } from '../row-expanding/rowExpandingFeature.ut
|
|
|
5
5
|
import { table_autoResetPageIndex } from '../row-pagination/rowPaginationFeature.utils'
|
|
6
6
|
import {
|
|
7
7
|
aggregateColumnValue,
|
|
8
|
-
|
|
9
|
-
} from '../aggregation/
|
|
10
|
-
import { row_getGroupingValue } from './columnGroupingFeature.utils'
|
|
8
|
+
normalizeUniqueAggregationRows,
|
|
9
|
+
} from '../row-aggregation/rowAggregationFeature.utils'
|
|
11
10
|
import type { Row_ColumnGrouping } from './columnGroupingFeature.types'
|
|
11
|
+
import type { Column_Internal } from '../../types/Column'
|
|
12
12
|
import type { TableFeatures } from '../../types/TableFeatures'
|
|
13
13
|
import type { RowModel } from '../../core/row-models/coreRowModelsFeature.types'
|
|
14
14
|
import type { Table, Table_Internal } from '../../types/Table'
|
|
@@ -20,7 +20,7 @@ import type { RowData } from '../../types/type-utils'
|
|
|
20
20
|
*
|
|
21
21
|
* The factory reads the relevant table state atoms and options, then returns a row model function used by the table row-model pipeline.
|
|
22
22
|
*
|
|
23
|
-
* When
|
|
23
|
+
* When rowAggregationFeature is also registered, grouped rows use its shared
|
|
24
24
|
* executor for non-group values. Grouping remains useful without aggregation.
|
|
25
25
|
*/
|
|
26
26
|
export function createGroupedRowModel<
|
|
@@ -103,7 +103,7 @@ function _createGroupedRowModel<
|
|
|
103
103
|
const columnId = existingGrouping[depth] as string
|
|
104
104
|
|
|
105
105
|
// Group the rows together for this level
|
|
106
|
-
const rowGroupsMap = groupBy(rows, columnId)
|
|
106
|
+
const rowGroupsMap = groupBy(table, rows, columnId)
|
|
107
107
|
|
|
108
108
|
// Perform aggregations for each group
|
|
109
109
|
const aggregatedGroupedRows = Array.from(rowGroupsMap.entries()).map(
|
|
@@ -118,7 +118,13 @@ function _createGroupedRowModel<
|
|
|
118
118
|
subRow.parentId = id
|
|
119
119
|
})
|
|
120
120
|
|
|
121
|
-
|
|
121
|
+
// Rows produced by groupBy are disjoint members of the pre-grouped
|
|
122
|
+
// row tree, so the duplicate-id guard is unnecessary; flat groups
|
|
123
|
+
// reuse the partition array as-is.
|
|
124
|
+
const leafRows = normalizeUniqueAggregationRows(
|
|
125
|
+
groupedRows,
|
|
126
|
+
Infinity,
|
|
127
|
+
) as Array<Row<TFeatures, TData>>
|
|
122
128
|
|
|
123
129
|
const row = constructRow(
|
|
124
130
|
table,
|
|
@@ -171,6 +177,7 @@ function _createGroupedRowModel<
|
|
|
171
177
|
column,
|
|
172
178
|
groupingRow: row,
|
|
173
179
|
rows: groupedRows,
|
|
180
|
+
uniqueRows: true,
|
|
174
181
|
})
|
|
175
182
|
return cache[colId]
|
|
176
183
|
},
|
|
@@ -203,19 +210,49 @@ function _createGroupedRowModel<
|
|
|
203
210
|
}
|
|
204
211
|
|
|
205
212
|
function groupBy<TFeatures extends TableFeatures, TData extends RowData = any>(
|
|
213
|
+
table: Table_Internal<TFeatures, TData>,
|
|
206
214
|
rows: Array<Row<TFeatures, TData>>,
|
|
207
215
|
columnId: string,
|
|
208
216
|
) {
|
|
209
217
|
const groupMap = new Map<any, Array<Row<TFeatures, TData>>>()
|
|
210
218
|
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
219
|
+
// Resolve the column once instead of per row: `table.getColumn` goes
|
|
220
|
+
// through the memoized-API dispatcher, which is far too expensive to sit
|
|
221
|
+
// inside this per-row loop. The branches below mirror
|
|
222
|
+
// `row_getGroupingValue`'s caching contract exactly.
|
|
223
|
+
const column = table_getColumn(table, columnId) as
|
|
224
|
+
| Column_Internal<TFeatures, TData, unknown>
|
|
225
|
+
| undefined
|
|
226
|
+
const getGroupingValue = column?.columnDef.getGroupingValue
|
|
227
|
+
|
|
228
|
+
for (let i = 0; i < rows.length; i++) {
|
|
229
|
+
const row = rows[i]!
|
|
230
|
+
let groupingValue
|
|
231
|
+
if (getGroupingValue) {
|
|
232
|
+
const cache = (row as any)._groupingValuesCache as
|
|
233
|
+
| Record<string, unknown>
|
|
234
|
+
| undefined
|
|
235
|
+
if (cache && hasOwn(cache, columnId)) {
|
|
236
|
+
groupingValue = cache[columnId]
|
|
237
|
+
} else if (cache) {
|
|
238
|
+
groupingValue = cache[columnId] = getGroupingValue(
|
|
239
|
+
row.original,
|
|
240
|
+
row.index,
|
|
241
|
+
row,
|
|
242
|
+
)
|
|
243
|
+
}
|
|
244
|
+
} else {
|
|
245
|
+
groupingValue = row.getValue(columnId)
|
|
246
|
+
}
|
|
247
|
+
|
|
248
|
+
const resKey = `${groupingValue}`
|
|
249
|
+
const previous = groupMap.get(resKey)
|
|
214
250
|
if (!previous) {
|
|
215
|
-
|
|
251
|
+
groupMap.set(resKey, [row])
|
|
216
252
|
} else {
|
|
217
253
|
previous.push(row)
|
|
218
254
|
}
|
|
219
|
-
|
|
220
|
-
|
|
255
|
+
}
|
|
256
|
+
|
|
257
|
+
return groupMap
|
|
221
258
|
}
|