@tanstack/table-core 9.0.0-alpha.46 → 9.0.0-alpha.47
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/cells/constructCell.cjs +4 -3
- package/dist/core/cells/constructCell.cjs.map +1 -1
- package/dist/core/cells/constructCell.js +4 -3
- package/dist/core/cells/constructCell.js.map +1 -1
- package/dist/core/columns/constructColumn.cjs +6 -4
- package/dist/core/columns/constructColumn.cjs.map +1 -1
- package/dist/core/columns/constructColumn.js +6 -4
- package/dist/core/columns/constructColumn.js.map +1 -1
- package/dist/core/columns/coreColumnsFeature.utils.cjs +10 -2
- package/dist/core/columns/coreColumnsFeature.utils.cjs.map +1 -1
- package/dist/core/columns/coreColumnsFeature.utils.js +10 -2
- package/dist/core/columns/coreColumnsFeature.utils.js.map +1 -1
- package/dist/core/headers/buildHeaderGroups.cjs +27 -19
- package/dist/core/headers/buildHeaderGroups.cjs.map +1 -1
- package/dist/core/headers/buildHeaderGroups.js +27 -19
- package/dist/core/headers/buildHeaderGroups.js.map +1 -1
- package/dist/core/headers/constructHeader.cjs +4 -3
- package/dist/core/headers/constructHeader.cjs.map +1 -1
- package/dist/core/headers/constructHeader.js +4 -3
- package/dist/core/headers/constructHeader.js.map +1 -1
- package/dist/core/headers/coreHeadersFeature.cjs +1 -6
- package/dist/core/headers/coreHeadersFeature.cjs.map +1 -1
- package/dist/core/headers/coreHeadersFeature.js +2 -7
- package/dist/core/headers/coreHeadersFeature.js.map +1 -1
- package/dist/core/headers/coreHeadersFeature.utils.cjs +20 -18
- package/dist/core/headers/coreHeadersFeature.utils.cjs.map +1 -1
- package/dist/core/headers/coreHeadersFeature.utils.d.cts +1 -1
- package/dist/core/headers/coreHeadersFeature.utils.d.ts +1 -1
- package/dist/core/headers/coreHeadersFeature.utils.js +21 -19
- package/dist/core/headers/coreHeadersFeature.utils.js.map +1 -1
- package/dist/core/reactivity/coreReactivityFeature.types.d.cts +4 -0
- package/dist/core/reactivity/coreReactivityFeature.types.d.ts +4 -0
- package/dist/core/rows/constructRow.cjs +8 -6
- package/dist/core/rows/constructRow.cjs.map +1 -1
- package/dist/core/rows/constructRow.js +8 -6
- package/dist/core/rows/constructRow.js.map +1 -1
- package/dist/core/rows/coreRowsFeature.utils.cjs +9 -4
- package/dist/core/rows/coreRowsFeature.utils.cjs.map +1 -1
- package/dist/core/rows/coreRowsFeature.utils.js +9 -4
- package/dist/core/rows/coreRowsFeature.utils.js.map +1 -1
- package/dist/core/table/constructTable.cjs +9 -5
- package/dist/core/table/constructTable.cjs.map +1 -1
- package/dist/core/table/constructTable.js +9 -5
- package/dist/core/table/constructTable.js.map +1 -1
- package/dist/core/table/coreTablesFeature.utils.cjs +5 -1
- package/dist/core/table/coreTablesFeature.utils.cjs.map +1 -1
- package/dist/core/table/coreTablesFeature.utils.js +5 -1
- package/dist/core/table/coreTablesFeature.utils.js.map +1 -1
- package/dist/features/column-faceting/createFacetedMinMaxValues.cjs +8 -5
- package/dist/features/column-faceting/createFacetedMinMaxValues.cjs.map +1 -1
- package/dist/features/column-faceting/createFacetedMinMaxValues.js +8 -5
- package/dist/features/column-faceting/createFacetedMinMaxValues.js.map +1 -1
- package/dist/features/column-faceting/createFacetedRowModel.cjs +8 -3
- package/dist/features/column-faceting/createFacetedRowModel.cjs.map +1 -1
- package/dist/features/column-faceting/createFacetedRowModel.js +8 -3
- package/dist/features/column-faceting/createFacetedRowModel.js.map +1 -1
- package/dist/features/column-faceting/createFacetedUniqueValues.cjs +7 -4
- package/dist/features/column-faceting/createFacetedUniqueValues.cjs.map +1 -1
- package/dist/features/column-faceting/createFacetedUniqueValues.js +7 -4
- package/dist/features/column-faceting/createFacetedUniqueValues.js.map +1 -1
- package/dist/features/column-filtering/createFilteredRowModel.cjs +11 -5
- package/dist/features/column-filtering/createFilteredRowModel.cjs.map +1 -1
- package/dist/features/column-filtering/createFilteredRowModel.js +11 -5
- package/dist/features/column-filtering/createFilteredRowModel.js.map +1 -1
- package/dist/features/column-ordering/columnOrderingFeature.utils.cjs +16 -6
- package/dist/features/column-ordering/columnOrderingFeature.utils.cjs.map +1 -1
- package/dist/features/column-ordering/columnOrderingFeature.utils.js +16 -6
- package/dist/features/column-ordering/columnOrderingFeature.utils.js.map +1 -1
- package/dist/features/column-pinning/columnPinningFeature.utils.cjs +41 -24
- package/dist/features/column-pinning/columnPinningFeature.utils.cjs.map +1 -1
- package/dist/features/column-pinning/columnPinningFeature.utils.d.cts +5 -4
- package/dist/features/column-pinning/columnPinningFeature.utils.d.ts +5 -4
- package/dist/features/column-pinning/columnPinningFeature.utils.js +42 -25
- package/dist/features/column-pinning/columnPinningFeature.utils.js.map +1 -1
- package/dist/features/column-sizing/columnSizingFeature.cjs +28 -4
- package/dist/features/column-sizing/columnSizingFeature.cjs.map +1 -1
- package/dist/features/column-sizing/columnSizingFeature.js +28 -4
- package/dist/features/column-sizing/columnSizingFeature.js.map +1 -1
- package/dist/features/column-visibility/columnVisibilityFeature.cjs +23 -14
- package/dist/features/column-visibility/columnVisibilityFeature.cjs.map +1 -1
- package/dist/features/column-visibility/columnVisibilityFeature.js +24 -15
- package/dist/features/column-visibility/columnVisibilityFeature.js.map +1 -1
- package/dist/features/column-visibility/columnVisibilityFeature.types.d.cts +4 -0
- package/dist/features/column-visibility/columnVisibilityFeature.types.d.ts +4 -0
- package/dist/features/column-visibility/columnVisibilityFeature.utils.cjs +40 -13
- package/dist/features/column-visibility/columnVisibilityFeature.utils.cjs.map +1 -1
- package/dist/features/column-visibility/columnVisibilityFeature.utils.d.cts +12 -1
- package/dist/features/column-visibility/columnVisibilityFeature.utils.d.ts +12 -1
- package/dist/features/column-visibility/columnVisibilityFeature.utils.js +40 -14
- package/dist/features/column-visibility/columnVisibilityFeature.utils.js.map +1 -1
- package/dist/features/row-expanding/rowExpandingFeature.utils.cjs +2 -2
- package/dist/features/row-expanding/rowExpandingFeature.utils.cjs.map +1 -1
- package/dist/features/row-expanding/rowExpandingFeature.utils.js +2 -2
- package/dist/features/row-expanding/rowExpandingFeature.utils.js.map +1 -1
- package/dist/features/row-pinning/rowPinningFeature.utils.cjs +13 -7
- package/dist/features/row-pinning/rowPinningFeature.utils.cjs.map +1 -1
- package/dist/features/row-pinning/rowPinningFeature.utils.js +13 -7
- package/dist/features/row-pinning/rowPinningFeature.utils.js.map +1 -1
- package/dist/features/row-selection/rowSelectionFeature.utils.cjs +6 -3
- package/dist/features/row-selection/rowSelectionFeature.utils.cjs.map +1 -1
- package/dist/features/row-selection/rowSelectionFeature.utils.js +6 -3
- package/dist/features/row-selection/rowSelectionFeature.utils.js.map +1 -1
- package/dist/features/row-sorting/createSortedRowModel.cjs +13 -8
- package/dist/features/row-sorting/createSortedRowModel.cjs.map +1 -1
- package/dist/features/row-sorting/createSortedRowModel.js +13 -8
- package/dist/features/row-sorting/createSortedRowModel.js.map +1 -1
- package/dist/features/row-sorting/rowSortingFeature.utils.cjs +2 -2
- package/dist/features/row-sorting/rowSortingFeature.utils.cjs.map +1 -1
- package/dist/features/row-sorting/rowSortingFeature.utils.js +2 -2
- package/dist/features/row-sorting/rowSortingFeature.utils.js.map +1 -1
- package/dist/fns/aggregationFns.cjs +14 -7
- package/dist/fns/aggregationFns.cjs.map +1 -1
- package/dist/fns/aggregationFns.js +14 -8
- package/dist/fns/aggregationFns.js.map +1 -1
- package/dist/index.cjs +0 -4
- package/dist/index.d.cts +2 -2
- package/dist/index.d.ts +2 -2
- package/dist/index.js +2 -2
- package/dist/static-functions.cjs +1 -0
- 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/store-reactivity-bindings.cjs +1 -0
- package/dist/store-reactivity-bindings.cjs.map +1 -1
- package/dist/store-reactivity-bindings.js +1 -0
- package/dist/store-reactivity-bindings.js.map +1 -1
- package/dist/utils.cjs +18 -39
- package/dist/utils.cjs.map +1 -1
- package/dist/utils.d.cts +1 -23
- package/dist/utils.d.ts +1 -23
- package/dist/utils.js +19 -36
- package/dist/utils.js.map +1 -1
- package/package.json +1 -1
- package/src/core/cells/constructCell.ts +3 -2
- package/src/core/columns/constructColumn.ts +5 -3
- package/src/core/columns/coreColumnsFeature.utils.ts +6 -2
- package/src/core/headers/buildHeaderGroups.ts +29 -30
- package/src/core/headers/constructHeader.ts +3 -2
- package/src/core/headers/coreHeadersFeature.ts +2 -27
- package/src/core/headers/coreHeadersFeature.utils.ts +29 -43
- package/src/core/reactivity/coreReactivityFeature.types.ts +4 -0
- package/src/core/rows/constructRow.ts +6 -4
- package/src/core/rows/coreRowsFeature.utils.ts +11 -4
- package/src/core/table/constructTable.ts +6 -4
- package/src/core/table/coreTablesFeature.utils.ts +3 -1
- package/src/features/column-faceting/createFacetedMinMaxValues.ts +8 -10
- package/src/features/column-faceting/createFacetedRowModel.ts +10 -6
- package/src/features/column-faceting/createFacetedUniqueValues.ts +4 -3
- package/src/features/column-filtering/createFilteredRowModel.ts +14 -8
- package/src/features/column-ordering/columnOrderingFeature.utils.ts +14 -6
- package/src/features/column-pinning/columnPinningFeature.utils.ts +53 -37
- package/src/features/column-sizing/columnSizingFeature.ts +16 -0
- package/src/features/column-visibility/columnVisibilityFeature.ts +8 -0
- package/src/features/column-visibility/columnVisibilityFeature.types.ts +7 -0
- package/src/features/column-visibility/columnVisibilityFeature.utils.ts +50 -17
- package/src/features/row-expanding/rowExpandingFeature.utils.ts +2 -2
- package/src/features/row-pinning/rowPinningFeature.utils.ts +20 -18
- package/src/features/row-selection/rowSelectionFeature.utils.ts +20 -19
- package/src/features/row-sorting/createSortedRowModel.ts +16 -13
- package/src/features/row-sorting/rowSortingFeature.utils.ts +2 -2
- package/src/fns/aggregationFns.ts +20 -8
- package/src/store-reactivity-bindings.ts +1 -0
- package/src/utils.ts +19 -46
package/dist/utils.js
CHANGED
|
@@ -18,16 +18,16 @@ function cloneState(value) {
|
|
|
18
18
|
const proto = Object.getPrototypeOf(value);
|
|
19
19
|
if (proto !== Object.prototype && proto !== null) return value;
|
|
20
20
|
const copy = {};
|
|
21
|
-
|
|
21
|
+
const keys = Object.keys(value);
|
|
22
|
+
for (let i = 0; i < keys.length; i++) {
|
|
23
|
+
const key = keys[i];
|
|
24
|
+
copy[key] = cloneState(value[key]);
|
|
25
|
+
}
|
|
22
26
|
return copy;
|
|
23
27
|
}
|
|
24
28
|
return value;
|
|
25
29
|
}
|
|
26
30
|
/**
|
|
27
|
-
* A no-operation function used as a safe default callback.
|
|
28
|
-
*/
|
|
29
|
-
function noop() {}
|
|
30
|
-
/**
|
|
31
31
|
* Creates a table state updater for a single state slice.
|
|
32
32
|
*
|
|
33
33
|
* The updater writes through the table base atom for the slice and supports both value and functional updater forms.
|
|
@@ -45,12 +45,6 @@ function isFunction(d) {
|
|
|
45
45
|
return d instanceof Function;
|
|
46
46
|
}
|
|
47
47
|
/**
|
|
48
|
-
* Returns whether a value is an array containing only numbers.
|
|
49
|
-
*/
|
|
50
|
-
function isNumberArray(d) {
|
|
51
|
-
return Array.isArray(d) && d.every((val) => typeof val === "number");
|
|
52
|
-
}
|
|
53
|
-
/**
|
|
54
48
|
* Flattens a tree of nodes by recursively reading child nodes.
|
|
55
49
|
*
|
|
56
50
|
* The original nodes are preserved in depth-first order.
|
|
@@ -68,25 +62,6 @@ function flattenBy(arr, getChildren) {
|
|
|
68
62
|
return flat;
|
|
69
63
|
}
|
|
70
64
|
/**
|
|
71
|
-
* Symbol used to attach internal memo metadata to wrapped functions.
|
|
72
|
-
*
|
|
73
|
-
* This is exported so diagnostics can recognize memoized functions without
|
|
74
|
-
* depending on a string property name.
|
|
75
|
-
*/
|
|
76
|
-
const $internalMemoFnMeta = Symbol("memoFnMeta");
|
|
77
|
-
/**
|
|
78
|
-
* @internal
|
|
79
|
-
*/
|
|
80
|
-
function setMemoFnMeta(fn, meta) {
|
|
81
|
-
Object.defineProperty(fn, $internalMemoFnMeta, { value: meta });
|
|
82
|
-
}
|
|
83
|
-
/**
|
|
84
|
-
* @internal
|
|
85
|
-
*/
|
|
86
|
-
function getMemoFnMeta(fn) {
|
|
87
|
-
return (typeof fn === "function" && fn[$internalMemoFnMeta]) ?? null;
|
|
88
|
-
}
|
|
89
|
-
/**
|
|
90
65
|
* Creates a dependency-tracked memoized function for table internals.
|
|
91
66
|
*
|
|
92
67
|
* The memo recomputes only when its dependency tuple changes and can emit debug timing information.
|
|
@@ -97,7 +72,13 @@ const memo = ({ fn, memoDeps, onAfterCompare, onAfterUpdate, onBeforeCompare, on
|
|
|
97
72
|
const memoizedFn = (depArgs) => {
|
|
98
73
|
onBeforeCompare === null || onBeforeCompare === void 0 || onBeforeCompare();
|
|
99
74
|
const newDeps = memoDeps === null || memoDeps === void 0 ? void 0 : memoDeps(depArgs);
|
|
100
|
-
|
|
75
|
+
let depsChanged = !newDeps || newDeps.length !== (deps === null || deps === void 0 ? void 0 : deps.length);
|
|
76
|
+
if (!depsChanged && newDeps) {
|
|
77
|
+
for (let i = 0; i < newDeps.length; i++) if (newDeps[i] !== deps[i]) {
|
|
78
|
+
depsChanged = true;
|
|
79
|
+
break;
|
|
80
|
+
}
|
|
81
|
+
}
|
|
101
82
|
onAfterCompare === null || onAfterCompare === void 0 || onAfterCompare(depsChanged);
|
|
102
83
|
if (!depsChanged) return result;
|
|
103
84
|
deps = newDeps;
|
|
@@ -106,7 +87,6 @@ const memo = ({ fn, memoDeps, onAfterCompare, onAfterUpdate, onBeforeCompare, on
|
|
|
106
87
|
onAfterUpdate === null || onAfterUpdate === void 0 || onAfterUpdate(result);
|
|
107
88
|
return result;
|
|
108
89
|
};
|
|
109
|
-
setMemoFnMeta(memoizedFn, { originalArgsLength: fn.length });
|
|
110
90
|
return memoizedFn;
|
|
111
91
|
};
|
|
112
92
|
const pad = (str, num) => {
|
|
@@ -147,6 +127,10 @@ function tableMemo({ feature, fnName, objectId, onAfterUpdate, table, ...memoOpt
|
|
|
147
127
|
console.trace();
|
|
148
128
|
console.groupEnd();
|
|
149
129
|
}
|
|
130
|
+
const onAfterUpdateHandler = () => {
|
|
131
|
+
const { schedule, untrack } = table._reactivity;
|
|
132
|
+
schedule(() => untrack(() => onAfterUpdate === null || onAfterUpdate === void 0 ? void 0 : onAfterUpdate()));
|
|
133
|
+
};
|
|
150
134
|
const debugOptions = process.env.NODE_ENV === "development" ? {
|
|
151
135
|
onBeforeCompare: () => {
|
|
152
136
|
if (debugCache) beforeCompareTime = performance.now();
|
|
@@ -166,10 +150,10 @@ function tableMemo({ feature, fnName, objectId, onAfterUpdate, table, ...memoOpt
|
|
|
166
150
|
endCalcTime = performance.now();
|
|
167
151
|
logTime(Math.round((endCalcTime - startCalcTime) * 100) / 100, true);
|
|
168
152
|
}
|
|
169
|
-
|
|
153
|
+
onAfterUpdateHandler();
|
|
170
154
|
}
|
|
171
155
|
} : { onAfterUpdate: () => {
|
|
172
|
-
|
|
156
|
+
onAfterUpdateHandler();
|
|
173
157
|
} };
|
|
174
158
|
return memo({
|
|
175
159
|
...memoOptions,
|
|
@@ -232,7 +216,6 @@ function assignPrototypeAPIs(feature, prototype, table, apis) {
|
|
|
232
216
|
} else prototype[fnKey] = function(...args) {
|
|
233
217
|
return fn(this, ...args);
|
|
234
218
|
};
|
|
235
|
-
setMemoFnMeta(prototype[fnKey], { originalArgsLength: fn.length });
|
|
236
219
|
}
|
|
237
220
|
}
|
|
238
221
|
/**
|
|
@@ -244,5 +227,5 @@ function callMemoOrStaticFn(obj, fnKey, staticFn, ...args) {
|
|
|
244
227
|
}
|
|
245
228
|
|
|
246
229
|
//#endregion
|
|
247
|
-
export {
|
|
230
|
+
export { assignPrototypeAPIs, assignTableAPIs, callMemoOrStaticFn, cloneState, flattenBy, functionalUpdate, getFunctionNameInfo, isFunction, makeStateUpdater, memo, tableMemo };
|
|
248
231
|
//# sourceMappingURL=utils.js.map
|
package/dist/utils.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"utils.js","names":[],"sources":["../src/utils.ts"],"sourcesContent":["import type { Table, Table_Internal } from './types/Table'\nimport type { NoInfer, RowData, Updater } from './types/type-utils'\nimport type { TableFeatures } from './types/TableFeatures'\nimport type { TableState, TableState_All } from './types/TableState'\n\n/**\n * Applies a TanStack updater to a value.\n *\n * If the updater is a function it is called with the previous value; otherwise the updater value is returned directly.\n */\nexport function functionalUpdate<T>(updater: Updater<T>, input: T): T {\n return typeof updater === 'function'\n ? (updater as (i: T) => T)(input)\n : updater\n}\n\n/**\n * Clones table state values while preserving non-plain objects.\n *\n * Plain objects and arrays are copied recursively so state updates can avoid mutating existing references.\n */\nexport function cloneState<T>(value: T): T {\n if (Array.isArray(value)) {\n return value.map(cloneState) as T\n }\n\n if (value && typeof value === 'object') {\n const proto = Object.getPrototypeOf(value)\n\n if (proto !== Object.prototype && proto !== null) {\n return value\n }\n\n const copy: Record<string, unknown> = {}\n\n for (const key of Object.keys(value)) {\n copy[key] = cloneState((value as Record<string, unknown>)[key])\n }\n\n return copy as T\n }\n\n return value\n}\n\n/**\n * A no-operation function used as a safe default callback.\n */\nexport function noop() {}\n\n/**\n * Creates a table state updater for a single state slice.\n *\n * The updater writes through the table base atom for the slice and supports both value and functional updater forms.\n */\nexport function makeStateUpdater<\n TFeatures extends TableFeatures,\n K extends (string & {}) | keyof TableState_All | keyof TableState<TFeatures>,\n>(key: K, instance: Table<TFeatures, any>) {\n return (updater: Updater<TableState<any>[K & keyof TableState<any>]>) => {\n const externalAtom = (instance.options as any).atoms?.[key]\n const targetAtom = externalAtom ?? (instance.baseAtoms as any)[key]\n targetAtom.set((old: any) => functionalUpdate(updater, old))\n }\n}\n\ntype AnyFunction = (...args: any) => any\n\n/**\n * Returns whether a value is a function.\n */\nexport function isFunction<T extends AnyFunction>(d: any): d is T {\n return d instanceof Function\n}\n\n/**\n * Returns whether a value is an array containing only numbers.\n */\nexport function isNumberArray(d: any): d is Array<number> {\n return Array.isArray(d) && d.every((val) => typeof val === 'number')\n}\n\n/**\n * Flattens a tree of nodes by recursively reading child nodes.\n *\n * The original nodes are preserved in depth-first order.\n */\nexport function flattenBy<TNode>(\n arr: Array<TNode>,\n getChildren: (item: TNode) => Array<TNode>,\n) {\n const flat: Array<TNode> = []\n\n const recurse = (subArr: Array<TNode>) => {\n subArr.forEach((item) => {\n flat.push(item)\n const children = getChildren(item)\n if (children.length) {\n recurse(children)\n }\n })\n }\n\n recurse(arr)\n\n return flat\n}\n\n/**\n * Symbol used to attach internal memo metadata to wrapped functions.\n *\n * This is exported so diagnostics can recognize memoized functions without\n * depending on a string property name.\n */\nexport const $internalMemoFnMeta = Symbol('memoFnMeta')\nexport type MemoFnMeta = { originalArgsLength?: number }\n\n/**\n * @internal\n */\nfunction setMemoFnMeta(fn: Function, meta: MemoFnMeta) {\n Object.defineProperty(fn, $internalMemoFnMeta, { value: meta })\n}\n\n/**\n * @internal\n */\nexport function getMemoFnMeta(fn: any): MemoFnMeta | null {\n return (typeof fn === 'function' && fn[$internalMemoFnMeta]) ?? null\n}\n\ninterface MemoOptions<TDeps extends ReadonlyArray<any>, TDepArgs, TResult> {\n fn: (...args: NoInfer<TDeps>) => TResult\n memoDeps?: (depArgs?: TDepArgs) => [...TDeps] | undefined\n onAfterCompare?: (depsChanged: boolean) => void\n onAfterUpdate?: (result: TResult) => void\n onBeforeCompare?: () => void\n onBeforeUpdate?: () => void\n}\n\n/**\n * Creates a dependency-tracked memoized function for table internals.\n *\n * The memo recomputes only when its dependency tuple changes and can emit debug timing information.\n */\nexport const memo = <TDeps extends ReadonlyArray<any>, TDepArgs, TResult>({\n fn,\n memoDeps,\n onAfterCompare,\n onAfterUpdate,\n onBeforeCompare,\n onBeforeUpdate,\n}: MemoOptions<TDeps, TDepArgs, TResult>): ((\n depArgs?: TDepArgs,\n) => TResult) => {\n let deps: Array<any> | undefined = []\n let result: TResult | undefined\n\n const memoizedFn = (depArgs?: TDepArgs): TResult => {\n onBeforeCompare?.()\n const newDeps = memoDeps?.(depArgs)\n const depsChanged =\n !newDeps ||\n newDeps.length !== deps?.length ||\n newDeps.some((dep: any, index: number) => deps?.[index] !== dep)\n onAfterCompare?.(depsChanged)\n\n if (!depsChanged) {\n return result!\n }\n\n deps = newDeps\n\n onBeforeUpdate?.()\n result = fn(...(newDeps ?? ([] as any)))\n onAfterUpdate?.(result)\n\n return result\n }\n\n setMemoFnMeta(memoizedFn, { originalArgsLength: fn.length })\n\n return memoizedFn\n}\n\ninterface TableMemoOptions<\n TFeatures extends TableFeatures,\n TDeps extends ReadonlyArray<any>,\n TDepArgs,\n TResult,\n> extends MemoOptions<TDeps, TDepArgs, TResult> {\n feature?: keyof TFeatures & string\n fnName: string\n objectId?: string\n onAfterUpdate?: () => void\n table: Table_Internal<TFeatures, any>\n}\n\nconst pad = (str: number | string, num: number) => {\n str = String(str)\n while (str.length < num) {\n str = ' ' + str\n }\n return str\n}\n\n/**\n * Creates a table-aware memoized function.\n *\n * This wraps `memo` with table debug options and feature metadata so row models and derived APIs can share consistent diagnostics.\n */\nexport function tableMemo<\n TFeatures extends TableFeatures,\n TDeps extends ReadonlyArray<any>,\n TDepArgs,\n TResult,\n>({\n feature,\n fnName,\n objectId,\n onAfterUpdate,\n table,\n ...memoOptions\n}: TableMemoOptions<TFeatures, TDeps, TDepArgs, TResult>) {\n let beforeCompareTime: number\n let afterCompareTime: number\n let startCalcTime: number\n let endCalcTime: number\n let runCount = 0\n let debug: boolean | undefined\n let debugCache: boolean | undefined\n\n if (process.env.NODE_ENV === 'development') {\n const { debugCache: _debugCache, debugAll } = table.options\n debugCache = _debugCache\n const { parentName } = getFunctionNameInfo(fnName, '.')\n\n const debugByParent =\n // @ts-expect-error\n table.options[\n `debug${(parentName != 'table' ? parentName + 's' : parentName).replace(\n parentName,\n parentName.charAt(0).toUpperCase() + parentName.slice(1),\n )}`\n ]\n const debugByFeature = feature\n ? // @ts-expect-error\n table.options[\n `debug${feature.charAt(0).toUpperCase() + feature.slice(1)}`\n ]\n : false\n\n debug = debugAll || debugByParent || debugByFeature\n }\n\n function logTime(time: number, depsChanged: boolean) {\n const runType =\n runCount === 0\n ? '(1st run)'\n : depsChanged\n ? '(rerun #' + runCount + ')'\n : '(cache)'\n runCount++\n\n console.groupCollapsed(\n `%c⏱ ${pad(`${time.toFixed(1)} ms`, 12)} %c${runType}%c ${fnName}%c ${objectId ? `(${fnName.split('.')[0]}Id: ${objectId})` : ''}`,\n `font-size: .6rem; font-weight: bold; ${\n depsChanged\n ? `color: hsl(\n ${Math.max(0, Math.min(120 - Math.log10(time) * 60, 120))}deg 100% 31%);`\n : ''\n } `,\n `color: ${runCount < 2 ? '#FF00FF' : '#FF1493'}`,\n 'color: #666',\n 'color: #87CEEB',\n )\n console.info({\n feature,\n state: table.store.state,\n deps: memoOptions.memoDeps?.toString(),\n })\n console.trace()\n console.groupEnd()\n }\n\n const debugOptions =\n process.env.NODE_ENV === 'development'\n ? {\n onBeforeCompare: () => {\n if (debugCache) {\n beforeCompareTime = performance.now()\n }\n },\n onAfterCompare: (depsChanged: boolean) => {\n if (debugCache) {\n afterCompareTime = performance.now()\n const compareTime =\n Math.round((afterCompareTime - beforeCompareTime) * 100) / 100\n if (!depsChanged) {\n logTime(compareTime, depsChanged)\n }\n }\n },\n onBeforeUpdate: () => {\n if (debug) {\n startCalcTime = performance.now()\n }\n },\n onAfterUpdate: () => {\n if (debug) {\n endCalcTime = performance.now()\n const executionTime =\n Math.round((endCalcTime - startCalcTime) * 100) / 100\n logTime(executionTime, true)\n }\n queueMicrotask(() => onAfterUpdate?.())\n },\n }\n : {\n onAfterUpdate: () => {\n queueMicrotask(() => onAfterUpdate?.())\n },\n }\n\n return memo({\n ...memoOptions,\n ...debugOptions,\n })\n}\n\nexport interface API<TDeps extends ReadonlyArray<any>, TDepArgs> {\n fn: (...args: any) => any\n memoDeps?: (depArgs?: any) => [...any] | undefined\n}\n\nexport type APIObject<TDeps extends ReadonlyArray<any>, TDepArgs> = Record<\n string,\n API<TDeps, TDepArgs>\n>\n\n/**\n * Assumes that a function name is in the format of `parentName_fnKey` and returns the `fnKey` and `fnName` in the format of `parentName.fnKey`.\n */\nexport function getFunctionNameInfo(\n staticFnName: string,\n splitBy: '_' | '.' = '_',\n) {\n const [parentName, fnKey] = staticFnName.split(splitBy)\n const fnName = `${parentName}.${fnKey}`\n return { fnKey, fnName, parentName } as {\n fnKey: string\n fnName: string\n parentName: string\n }\n}\n\n/**\n * Assigns Table API methods directly to the table instance.\n * Unlike row/cell/column/header, the table is a singleton so methods are assigned directly.\n */\nexport function assignTableAPIs<\n TFeatures extends TableFeatures,\n TData extends RowData,\n TDeps extends ReadonlyArray<any>,\n TDepArgs,\n>(\n feature: keyof TFeatures & string,\n table: Table_Internal<TFeatures, TData>,\n apis: APIObject<TDeps, NoInfer<TDepArgs>>,\n): void {\n for (const [staticFnName, { fn, memoDeps }] of Object.entries(apis)) {\n const { fnKey, fnName } = getFunctionNameInfo(staticFnName)\n\n ;(table as Record<string, any>)[fnKey] = memoDeps\n ? tableMemo({\n memoDeps,\n fn,\n fnName,\n table,\n feature,\n })\n : fn\n }\n}\n\nexport interface PrototypeAPI<TDeps extends ReadonlyArray<any>, TDepArgs> {\n fn: (self: any, ...args: any) => any\n memoDeps?: (self: any, depArgs?: any) => [...any] | undefined\n}\n\nexport type PrototypeAPIObject<\n TDeps extends ReadonlyArray<any>,\n TDepArgs,\n> = Record<string, PrototypeAPI<TDeps, TDepArgs>>\n\n/**\n * Assigns API methods to a prototype object for memory-efficient method sharing.\n * All instances created with this prototype will share the same method references.\n *\n * For memoized methods, the memo state is lazily created and stored on each instance.\n * This provides the best of both worlds: shared method code + per-instance caching.\n */\nexport function assignPrototypeAPIs<\n TFeatures extends TableFeatures,\n TData extends RowData,\n TDeps extends ReadonlyArray<any>,\n TDepArgs,\n>(\n feature: keyof TFeatures & string,\n prototype: Record<string, any>,\n table: Table_Internal<TFeatures, TData>,\n apis: PrototypeAPIObject<TDeps, NoInfer<TDepArgs>>,\n): void {\n for (const [staticFnName, { fn, memoDeps }] of Object.entries(apis)) {\n const { fnKey, fnName } = getFunctionNameInfo(staticFnName)\n\n if (memoDeps) {\n // For memoized methods, create a function that lazily initializes\n // the memo on first access and stores it on the instance\n const memoKey = `_memo_${fnKey}`\n\n prototype[fnKey] = function (this: any, ...args: Array<any>) {\n // Lazily create memo on first access for this instance\n if (!this[memoKey]) {\n const self = this\n this[memoKey] = tableMemo({\n memoDeps: (depArgs) => memoDeps(self, depArgs),\n fn: (...deps) => fn(self, ...deps),\n fnName,\n objectId: self.id,\n table,\n feature,\n })\n }\n return this[memoKey](...args)\n }\n } else {\n // Non-memoized methods just call the static function with `this`\n prototype[fnKey] = function (this: any, ...args: Array<any>) {\n return fn(this, ...args)\n }\n }\n\n setMemoFnMeta(prototype[fnKey], { originalArgsLength: fn.length })\n }\n}\n\n/**\n * Looks to run the memoized function with the builder pattern on the object if it exists, otherwise fallback to the static method passed in.\n */\nexport function callMemoOrStaticFn<\n TObject extends Record<string, any>,\n TStaticFn extends AnyFunction,\n>(\n obj: TObject,\n fnKey: string,\n staticFn: TStaticFn,\n ...args: Parameters<TStaticFn> extends [any, ...infer Rest] ? Rest : never\n): ReturnType<TStaticFn> {\n return (\n (obj[fnKey] as Function | undefined)?.(...args) ?? staticFn(obj, ...args)\n )\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"utils.js","names":[],"sources":["../src/utils.ts"],"sourcesContent":["import type { Table, Table_Internal } from './types/Table'\nimport type { NoInfer, RowData, Updater } from './types/type-utils'\nimport type { TableFeatures } from './types/TableFeatures'\nimport type { TableState, TableState_All } from './types/TableState'\n\n/**\n * Applies a TanStack updater to a value.\n *\n * If the updater is a function it is called with the previous value; otherwise the updater value is returned directly.\n */\nexport function functionalUpdate<T>(updater: Updater<T>, input: T): T {\n return typeof updater === 'function'\n ? (updater as (i: T) => T)(input)\n : updater\n}\n\n/**\n * Clones table state values while preserving non-plain objects.\n *\n * Plain objects and arrays are copied recursively so state updates can avoid mutating existing references.\n */\nexport function cloneState<T>(value: T): T {\n if (Array.isArray(value)) {\n return value.map(cloneState) as T\n }\n\n if (value && typeof value === 'object') {\n const proto = Object.getPrototypeOf(value)\n\n if (proto !== Object.prototype && proto !== null) {\n return value\n }\n\n const copy: Record<string, unknown> = {}\n const keys = Object.keys(value)\n\n for (let i = 0; i < keys.length; i++) {\n const key = keys[i]!\n copy[key] = cloneState((value as Record<string, unknown>)[key])\n }\n\n return copy as T\n }\n\n return value\n}\n\n/**\n * Creates a table state updater for a single state slice.\n *\n * The updater writes through the table base atom for the slice and supports both value and functional updater forms.\n */\nexport function makeStateUpdater<\n TFeatures extends TableFeatures,\n K extends (string & {}) | keyof TableState_All | keyof TableState<TFeatures>,\n>(key: K, instance: Table<TFeatures, any>) {\n return (updater: Updater<TableState<any>[K & keyof TableState<any>]>) => {\n const externalAtom = (instance.options as any).atoms?.[key]\n const targetAtom = externalAtom ?? (instance.baseAtoms as any)[key]\n targetAtom.set((old: any) => functionalUpdate(updater, old))\n }\n}\n\ntype AnyFunction = (...args: any) => any\n\n/**\n * Returns whether a value is a function.\n */\nexport function isFunction<T extends AnyFunction>(d: any): d is T {\n return d instanceof Function\n}\n\n/**\n * Flattens a tree of nodes by recursively reading child nodes.\n *\n * The original nodes are preserved in depth-first order.\n */\nexport function flattenBy<TNode>(\n arr: Array<TNode>,\n getChildren: (item: TNode) => Array<TNode>,\n) {\n const flat: Array<TNode> = []\n\n const recurse = (subArr: Array<TNode>) => {\n subArr.forEach((item) => {\n flat.push(item)\n const children = getChildren(item)\n if (children.length) {\n recurse(children)\n }\n })\n }\n\n recurse(arr)\n\n return flat\n}\n\ninterface MemoOptions<TDeps extends ReadonlyArray<any>, TDepArgs, TResult> {\n fn: (...args: NoInfer<TDeps>) => TResult\n memoDeps?: (depArgs?: TDepArgs) => [...TDeps] | undefined\n onAfterCompare?: (depsChanged: boolean) => void\n onAfterUpdate?: (result: TResult) => void\n onBeforeCompare?: () => void\n onBeforeUpdate?: () => void\n}\n\n/**\n * Creates a dependency-tracked memoized function for table internals.\n *\n * The memo recomputes only when its dependency tuple changes and can emit debug timing information.\n */\nexport const memo = <TDeps extends ReadonlyArray<any>, TDepArgs, TResult>({\n fn,\n memoDeps,\n onAfterCompare,\n onAfterUpdate,\n onBeforeCompare,\n onBeforeUpdate,\n}: MemoOptions<TDeps, TDepArgs, TResult>): ((\n depArgs?: TDepArgs,\n) => TResult) => {\n let deps: Array<any> | undefined = []\n let result: TResult | undefined\n\n const memoizedFn = (depArgs?: TDepArgs): TResult => {\n onBeforeCompare?.()\n const newDeps = memoDeps?.(depArgs)\n let depsChanged = !newDeps || newDeps.length !== deps?.length\n if (!depsChanged && newDeps) {\n for (let i = 0; i < newDeps.length; i++) {\n if (newDeps[i] !== deps![i]) {\n depsChanged = true\n break\n }\n }\n }\n onAfterCompare?.(depsChanged)\n\n if (!depsChanged) {\n return result!\n }\n\n deps = newDeps\n\n onBeforeUpdate?.()\n result = fn(...(newDeps ?? ([] as any)))\n onAfterUpdate?.(result)\n\n return result\n }\n\n return memoizedFn\n}\n\ninterface TableMemoOptions<\n TFeatures extends TableFeatures,\n TDeps extends ReadonlyArray<any>,\n TDepArgs,\n TResult,\n> extends MemoOptions<TDeps, TDepArgs, TResult> {\n feature?: keyof TFeatures & string\n fnName: string\n objectId?: string\n onAfterUpdate?: () => void\n table: Table_Internal<TFeatures, any>\n}\n\nconst pad = (str: number | string, num: number) => {\n str = String(str)\n while (str.length < num) {\n str = ' ' + str\n }\n return str\n}\n\n/**\n * Creates a table-aware memoized function.\n *\n * This wraps `memo` with table debug options and feature metadata so row models and derived APIs can share consistent diagnostics.\n */\nexport function tableMemo<\n TFeatures extends TableFeatures,\n TDeps extends ReadonlyArray<any>,\n TDepArgs,\n TResult,\n>({\n feature,\n fnName,\n objectId,\n onAfterUpdate,\n table,\n ...memoOptions\n}: TableMemoOptions<TFeatures, TDeps, TDepArgs, TResult>) {\n let beforeCompareTime: number\n let afterCompareTime: number\n let startCalcTime: number\n let endCalcTime: number\n let runCount = 0\n let debug: boolean | undefined\n let debugCache: boolean | undefined\n\n if (process.env.NODE_ENV === 'development') {\n const { debugCache: _debugCache, debugAll } = table.options\n debugCache = _debugCache\n const { parentName } = getFunctionNameInfo(fnName, '.')\n\n const debugByParent =\n // @ts-expect-error\n table.options[\n `debug${(parentName != 'table' ? parentName + 's' : parentName).replace(\n parentName,\n parentName.charAt(0).toUpperCase() + parentName.slice(1),\n )}`\n ]\n const debugByFeature = feature\n ? // @ts-expect-error\n table.options[\n `debug${feature.charAt(0).toUpperCase() + feature.slice(1)}`\n ]\n : false\n\n debug = debugAll || debugByParent || debugByFeature\n }\n\n function logTime(time: number, depsChanged: boolean) {\n const runType =\n runCount === 0\n ? '(1st run)'\n : depsChanged\n ? '(rerun #' + runCount + ')'\n : '(cache)'\n runCount++\n\n console.groupCollapsed(\n `%c⏱ ${pad(`${time.toFixed(1)} ms`, 12)} %c${runType}%c ${fnName}%c ${objectId ? `(${fnName.split('.')[0]}Id: ${objectId})` : ''}`,\n `font-size: .6rem; font-weight: bold; ${\n depsChanged\n ? `color: hsl(\n ${Math.max(0, Math.min(120 - Math.log10(time) * 60, 120))}deg 100% 31%);`\n : ''\n } `,\n `color: ${runCount < 2 ? '#FF00FF' : '#FF1493'}`,\n 'color: #666',\n 'color: #87CEEB',\n )\n console.info({\n feature,\n state: table.store.state,\n deps: memoOptions.memoDeps?.toString(),\n })\n console.trace()\n console.groupEnd()\n }\n\n const onAfterUpdateHandler = () => {\n const { schedule, untrack } = table._reactivity\n schedule(() => untrack(() => onAfterUpdate?.()))\n }\n\n const debugOptions =\n process.env.NODE_ENV === 'development'\n ? {\n onBeforeCompare: () => {\n if (debugCache) {\n beforeCompareTime = performance.now()\n }\n },\n onAfterCompare: (depsChanged: boolean) => {\n if (debugCache) {\n afterCompareTime = performance.now()\n const compareTime =\n Math.round((afterCompareTime - beforeCompareTime) * 100) / 100\n if (!depsChanged) {\n logTime(compareTime, depsChanged)\n }\n }\n },\n onBeforeUpdate: () => {\n if (debug) {\n startCalcTime = performance.now()\n }\n },\n onAfterUpdate: () => {\n if (debug) {\n endCalcTime = performance.now()\n const executionTime =\n Math.round((endCalcTime - startCalcTime) * 100) / 100\n logTime(executionTime, true)\n }\n onAfterUpdateHandler()\n },\n }\n : {\n onAfterUpdate: () => {\n onAfterUpdateHandler()\n },\n }\n\n return memo({\n ...memoOptions,\n ...debugOptions,\n })\n}\n\nexport interface API<TDeps extends ReadonlyArray<any>, TDepArgs> {\n fn: (...args: any) => any\n memoDeps?: (depArgs?: any) => [...any] | undefined\n}\n\nexport type APIObject<TDeps extends ReadonlyArray<any>, TDepArgs> = Record<\n string,\n API<TDeps, TDepArgs>\n>\n\n/**\n * Assumes that a function name is in the format of `parentName_fnKey` and returns the `fnKey` and `fnName` in the format of `parentName.fnKey`.\n */\nexport function getFunctionNameInfo(\n staticFnName: string,\n splitBy: '_' | '.' = '_',\n) {\n const [parentName, fnKey] = staticFnName.split(splitBy)\n const fnName = `${parentName}.${fnKey}`\n return { fnKey, fnName, parentName } as {\n fnKey: string\n fnName: string\n parentName: string\n }\n}\n\n/**\n * Assigns Table API methods directly to the table instance.\n * Unlike row/cell/column/header, the table is a singleton so methods are assigned directly.\n */\nexport function assignTableAPIs<\n TFeatures extends TableFeatures,\n TData extends RowData,\n TDeps extends ReadonlyArray<any>,\n TDepArgs,\n>(\n feature: keyof TFeatures & string,\n table: Table_Internal<TFeatures, TData>,\n apis: APIObject<TDeps, NoInfer<TDepArgs>>,\n): void {\n for (const [staticFnName, { fn, memoDeps }] of Object.entries(apis)) {\n const { fnKey, fnName } = getFunctionNameInfo(staticFnName)\n\n ;(table as Record<string, any>)[fnKey] = memoDeps\n ? tableMemo({\n memoDeps,\n fn,\n fnName,\n table,\n feature,\n })\n : fn\n }\n}\n\nexport interface PrototypeAPI<TDeps extends ReadonlyArray<any>, TDepArgs> {\n fn: (self: any, ...args: any) => any\n memoDeps?: (self: any, depArgs?: any) => [...any] | undefined\n}\n\nexport type PrototypeAPIObject<\n TDeps extends ReadonlyArray<any>,\n TDepArgs,\n> = Record<string, PrototypeAPI<TDeps, TDepArgs>>\n\n/**\n * Assigns API methods to a prototype object for memory-efficient method sharing.\n * All instances created with this prototype will share the same method references.\n *\n * For memoized methods, the memo state is lazily created and stored on each instance.\n * This provides the best of both worlds: shared method code + per-instance caching.\n */\nexport function assignPrototypeAPIs<\n TFeatures extends TableFeatures,\n TData extends RowData,\n TDeps extends ReadonlyArray<any>,\n TDepArgs,\n>(\n feature: keyof TFeatures & string,\n prototype: Record<string, any>,\n table: Table_Internal<TFeatures, TData>,\n apis: PrototypeAPIObject<TDeps, NoInfer<TDepArgs>>,\n): void {\n for (const [staticFnName, { fn, memoDeps }] of Object.entries(apis)) {\n const { fnKey, fnName } = getFunctionNameInfo(staticFnName)\n\n if (memoDeps) {\n // For memoized methods, create a function that lazily initializes\n // the memo on first access and stores it on the instance\n const memoKey = `_memo_${fnKey}`\n\n prototype[fnKey] = function (this: any, ...args: Array<any>) {\n // Lazily create memo on first access for this instance\n if (!this[memoKey]) {\n const self = this\n this[memoKey] = tableMemo({\n memoDeps: (depArgs) => memoDeps(self, depArgs),\n fn: (...deps) => fn(self, ...deps),\n fnName,\n objectId: self.id,\n table,\n feature,\n })\n }\n return this[memoKey](...args)\n }\n } else {\n // Non-memoized methods just call the static function with `this`\n prototype[fnKey] = function (this: any, ...args: Array<any>) {\n return fn(this, ...args)\n }\n }\n }\n}\n\n/**\n * Looks to run the memoized function with the builder pattern on the object if it exists, otherwise fallback to the static method passed in.\n */\nexport function callMemoOrStaticFn<\n TObject extends Record<string, any>,\n TStaticFn extends AnyFunction,\n>(\n obj: TObject,\n fnKey: string,\n staticFn: TStaticFn,\n ...args: Parameters<TStaticFn> extends [any, ...infer Rest] ? Rest : never\n): ReturnType<TStaticFn> {\n return (\n (obj[fnKey] as Function | undefined)?.(...args) ?? staticFn(obj, ...args)\n )\n}\n"],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -16,8 +16,9 @@ function getCellPrototype<
|
|
|
16
16
|
>(table: Table_Internal<TFeatures, TData>): object {
|
|
17
17
|
if (!table._cellPrototype) {
|
|
18
18
|
table._cellPrototype = { table }
|
|
19
|
-
|
|
20
|
-
|
|
19
|
+
const features = Object.values(table._features)
|
|
20
|
+
for (let i = 0; i < features.length; i++) {
|
|
21
|
+
features[i]!.assignCellPrototype?.(table._cellPrototype, table)
|
|
21
22
|
}
|
|
22
23
|
}
|
|
23
24
|
return table._cellPrototype
|
|
@@ -20,8 +20,9 @@ function getColumnPrototype<
|
|
|
20
20
|
>(table: Table_Internal<TFeatures, TData>): object {
|
|
21
21
|
if (!table._columnPrototype) {
|
|
22
22
|
table._columnPrototype = { table }
|
|
23
|
-
|
|
24
|
-
|
|
23
|
+
const features = Object.values(table._features)
|
|
24
|
+
for (let i = 0; i < features.length; i++) {
|
|
25
|
+
features[i]!.assignColumnPrototype?.(table._columnPrototype, table)
|
|
25
26
|
}
|
|
26
27
|
}
|
|
27
28
|
return table._columnPrototype
|
|
@@ -69,7 +70,8 @@ export function constructColumn<
|
|
|
69
70
|
accessorFn = (originalRow: TData) => {
|
|
70
71
|
let result = originalRow as Record<string, any> | undefined
|
|
71
72
|
|
|
72
|
-
for (
|
|
73
|
+
for (let i = 0; i < keys.length; i++) {
|
|
74
|
+
const key = keys[i]!
|
|
73
75
|
result = result?.[key]
|
|
74
76
|
if (process.env.NODE_ENV === 'development' && result === undefined) {
|
|
75
77
|
console.warn(
|
|
@@ -179,7 +179,9 @@ export function table_getAllFlatColumnsById<
|
|
|
179
179
|
table: Table_Internal<TFeatures, TData>,
|
|
180
180
|
): Record<string, Column<TFeatures, TData, unknown>> {
|
|
181
181
|
const result: Record<string, Column<TFeatures, TData, unknown>> = {}
|
|
182
|
-
|
|
182
|
+
const flatColumns = table.getAllFlatColumns()
|
|
183
|
+
for (let i = 0; i < flatColumns.length; i++) {
|
|
184
|
+
const column = flatColumns[i]!
|
|
183
185
|
result[column.id] = column
|
|
184
186
|
}
|
|
185
187
|
return result
|
|
@@ -228,7 +230,9 @@ export function table_getAllLeafColumnsById<
|
|
|
228
230
|
table: Table_Internal<TFeatures, TData>,
|
|
229
231
|
): Record<string, Column<TFeatures, TData, unknown>> {
|
|
230
232
|
const result: Record<string, Column<TFeatures, TData, unknown>> = {}
|
|
231
|
-
|
|
233
|
+
const leafColumns = table.getAllLeafColumns()
|
|
234
|
+
for (let i = 0; i < leafColumns.length; i++) {
|
|
235
|
+
const column = leafColumns[i]!
|
|
232
236
|
result[column.id] = column
|
|
233
237
|
}
|
|
234
238
|
return result
|
|
@@ -37,15 +37,14 @@ export function buildHeaderGroups<
|
|
|
37
37
|
) => {
|
|
38
38
|
maxDepth = Math.max(maxDepth, depth)
|
|
39
39
|
|
|
40
|
-
columns
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
)
|
|
44
|
-
.forEach((column) => {
|
|
40
|
+
for (let i = 0; i < columns.length; i++) {
|
|
41
|
+
const column = columns[i]!
|
|
42
|
+
if (callMemoOrStaticFn(column, 'getIsVisible', column_getIsVisible)) {
|
|
45
43
|
if (column.columns.length) {
|
|
46
44
|
findMaxDepth(column.columns, depth + 1)
|
|
47
45
|
}
|
|
48
|
-
}
|
|
46
|
+
}
|
|
47
|
+
}
|
|
49
48
|
}
|
|
50
49
|
|
|
51
50
|
findMaxDepth(allColumns)
|
|
@@ -136,43 +135,43 @@ export function buildHeaderGroups<
|
|
|
136
135
|
|
|
137
136
|
headerGroups.reverse()
|
|
138
137
|
|
|
139
|
-
// headerGroups = headerGroups.filter(headerGroup => {
|
|
140
|
-
// return !headerGroup.headers.every(header => header.isPlaceholder)
|
|
141
|
-
// })
|
|
142
|
-
|
|
143
138
|
const recurseHeadersForSpans = (
|
|
144
139
|
headers: Array<Header<TFeatures, TData, TValue>>,
|
|
145
140
|
): Array<{ colSpan: number; rowSpan: number }> => {
|
|
146
|
-
const
|
|
147
|
-
|
|
148
|
-
)
|
|
141
|
+
const results: Array<{ colSpan: number; rowSpan: number }> = []
|
|
142
|
+
|
|
143
|
+
for (let i = 0; i < headers.length; i++) {
|
|
144
|
+
const header = headers[i]!
|
|
145
|
+
if (
|
|
146
|
+
!callMemoOrStaticFn(header.column, 'getIsVisible', column_getIsVisible)
|
|
147
|
+
) {
|
|
148
|
+
continue
|
|
149
|
+
}
|
|
149
150
|
|
|
150
|
-
return filteredHeaders.map((header) => {
|
|
151
151
|
let colSpan = 0
|
|
152
|
-
let
|
|
153
|
-
let childRowSpans = [0]
|
|
152
|
+
let minChildRowSpan = Infinity
|
|
154
153
|
|
|
155
154
|
if (header.subHeaders.length) {
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
}
|
|
163
|
-
|
|
155
|
+
const childSpans = recurseHeadersForSpans(header.subHeaders)
|
|
156
|
+
for (let j = 0; j < childSpans.length; j++) {
|
|
157
|
+
const child = childSpans[j]!
|
|
158
|
+
colSpan += child.colSpan
|
|
159
|
+
if (child.rowSpan < minChildRowSpan) {
|
|
160
|
+
minChildRowSpan = child.rowSpan
|
|
161
|
+
}
|
|
162
|
+
}
|
|
164
163
|
} else {
|
|
165
164
|
colSpan = 1
|
|
165
|
+
minChildRowSpan = 0
|
|
166
166
|
}
|
|
167
167
|
|
|
168
|
-
const minChildRowSpan = Math.min(...childRowSpans)
|
|
169
|
-
rowSpan = rowSpan + minChildRowSpan
|
|
170
|
-
|
|
171
168
|
header.colSpan = colSpan
|
|
172
|
-
header.rowSpan =
|
|
169
|
+
header.rowSpan = minChildRowSpan
|
|
173
170
|
|
|
174
|
-
|
|
175
|
-
}
|
|
171
|
+
results.push({ colSpan, rowSpan: header.rowSpan })
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
return results
|
|
176
175
|
}
|
|
177
176
|
|
|
178
177
|
recurseHeadersForSpans(
|
|
@@ -15,8 +15,9 @@ function getHeaderPrototype<
|
|
|
15
15
|
>(table: Table_Internal<TFeatures, TData>): object {
|
|
16
16
|
if (!table._headerPrototype) {
|
|
17
17
|
table._headerPrototype = { table }
|
|
18
|
-
|
|
19
|
-
|
|
18
|
+
const features = Object.values(table._features)
|
|
19
|
+
for (let i = 0; i < features.length; i++) {
|
|
20
|
+
features[i]!.assignHeaderPrototype?.(table._headerPrototype, table)
|
|
20
21
|
}
|
|
21
22
|
}
|
|
22
23
|
return table._headerPrototype
|
|
@@ -1,13 +1,4 @@
|
|
|
1
|
-
import {
|
|
2
|
-
assignPrototypeAPIs,
|
|
3
|
-
assignTableAPIs,
|
|
4
|
-
callMemoOrStaticFn,
|
|
5
|
-
} from '../../utils'
|
|
6
|
-
import {
|
|
7
|
-
table_getCenterHeaderGroups,
|
|
8
|
-
table_getLeftHeaderGroups,
|
|
9
|
-
table_getRightHeaderGroups,
|
|
10
|
-
} from '../../features/column-pinning/columnPinningFeature.utils'
|
|
1
|
+
import { assignPrototypeAPIs, assignTableAPIs } from '../../utils'
|
|
11
2
|
import {
|
|
12
3
|
header_getContext,
|
|
13
4
|
header_getLeafHeaders,
|
|
@@ -74,23 +65,7 @@ export function constructCoreHeadersFeature<
|
|
|
74
65
|
},
|
|
75
66
|
table_getLeafHeaders: {
|
|
76
67
|
fn: () => table_getLeafHeaders(table),
|
|
77
|
-
memoDeps: () => [
|
|
78
|
-
callMemoOrStaticFn(
|
|
79
|
-
table,
|
|
80
|
-
'getLeftHeaderGroups',
|
|
81
|
-
table_getLeftHeaderGroups,
|
|
82
|
-
),
|
|
83
|
-
callMemoOrStaticFn(
|
|
84
|
-
table,
|
|
85
|
-
'getCenterHeaderGroups',
|
|
86
|
-
table_getCenterHeaderGroups,
|
|
87
|
-
),
|
|
88
|
-
callMemoOrStaticFn(
|
|
89
|
-
table,
|
|
90
|
-
'getRightHeaderGroups',
|
|
91
|
-
table_getRightHeaderGroups,
|
|
92
|
-
),
|
|
93
|
-
],
|
|
68
|
+
memoDeps: () => [table.getHeaderGroups()],
|
|
94
69
|
},
|
|
95
70
|
})
|
|
96
71
|
},
|
|
@@ -1,9 +1,4 @@
|
|
|
1
|
-
import {
|
|
2
|
-
getDefaultColumnPinningState,
|
|
3
|
-
table_getCenterHeaderGroups,
|
|
4
|
-
table_getLeftHeaderGroups,
|
|
5
|
-
table_getRightHeaderGroups,
|
|
6
|
-
} from '../../features/column-pinning/columnPinningFeature.utils'
|
|
1
|
+
import { getDefaultColumnPinningState } from '../../features/column-pinning/columnPinningFeature.utils'
|
|
7
2
|
import {
|
|
8
3
|
column_getIsVisible,
|
|
9
4
|
table_getVisibleLeafColumns,
|
|
@@ -90,11 +85,17 @@ export function table_getHeaderGroups<
|
|
|
90
85
|
'getVisibleLeafColumns',
|
|
91
86
|
table_getVisibleLeafColumns,
|
|
92
87
|
) as Array<Column<TFeatures, TData, unknown>>
|
|
88
|
+
|
|
89
|
+
// Fast path: no columns are pinned — skip per-side lookups, partition, and spread.
|
|
90
|
+
if (!left.length && !right.length) {
|
|
91
|
+
return buildHeaderGroups(allColumns, leafColumns, table)
|
|
92
|
+
}
|
|
93
|
+
|
|
93
94
|
const leafColumnsById = table.getAllLeafColumnsById()
|
|
94
95
|
|
|
95
96
|
const leftColumns: typeof leafColumns = []
|
|
96
|
-
for (
|
|
97
|
-
const column = leafColumnsById[
|
|
97
|
+
for (let i = 0; i < left.length; i++) {
|
|
98
|
+
const column = leafColumnsById[left[i]!]
|
|
98
99
|
if (
|
|
99
100
|
column &&
|
|
100
101
|
callMemoOrStaticFn(column, 'getIsVisible', column_getIsVisible)
|
|
@@ -104,8 +105,8 @@ export function table_getHeaderGroups<
|
|
|
104
105
|
}
|
|
105
106
|
|
|
106
107
|
const rightColumns: typeof leafColumns = []
|
|
107
|
-
for (
|
|
108
|
-
const column = leafColumnsById[
|
|
108
|
+
for (let i = 0; i < right.length; i++) {
|
|
109
|
+
const column = leafColumnsById[right[i]!]
|
|
109
110
|
if (
|
|
110
111
|
column &&
|
|
111
112
|
callMemoOrStaticFn(column, 'getIsVisible', column_getIsVisible)
|
|
@@ -118,13 +119,11 @@ export function table_getHeaderGroups<
|
|
|
118
119
|
(column) => !left.includes(column.id) && !right.includes(column.id),
|
|
119
120
|
)
|
|
120
121
|
|
|
121
|
-
|
|
122
|
+
return buildHeaderGroups(
|
|
122
123
|
allColumns,
|
|
123
124
|
[...leftColumns, ...centerColumns, ...rightColumns],
|
|
124
125
|
table,
|
|
125
126
|
)
|
|
126
|
-
|
|
127
|
-
return headerGroups
|
|
128
127
|
}
|
|
129
128
|
|
|
130
129
|
/**
|
|
@@ -160,11 +159,14 @@ export function table_getFlatHeaders<
|
|
|
160
159
|
TData extends RowData,
|
|
161
160
|
>(table: Table_Internal<TFeatures, TData>) {
|
|
162
161
|
const headerGroups = table.getHeaderGroups()
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
162
|
+
const result: Array<Header<TFeatures, TData, unknown>> = []
|
|
163
|
+
for (let i = 0; i < headerGroups.length; i++) {
|
|
164
|
+
const headers = headerGroups[i]!.headers
|
|
165
|
+
for (let j = 0; j < headers.length; j++) {
|
|
166
|
+
result.push(headers[j]!)
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
return result
|
|
168
170
|
}
|
|
169
171
|
|
|
170
172
|
/**
|
|
@@ -181,29 +183,13 @@ export function table_getLeafHeaders<
|
|
|
181
183
|
TFeatures extends TableFeatures,
|
|
182
184
|
TData extends RowData,
|
|
183
185
|
>(table: Table_Internal<TFeatures, TData>) {
|
|
184
|
-
const
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
)
|
|
194
|
-
const right = callMemoOrStaticFn(
|
|
195
|
-
table,
|
|
196
|
-
'getRightHeaderGroups',
|
|
197
|
-
table_getRightHeaderGroups,
|
|
198
|
-
)
|
|
199
|
-
|
|
200
|
-
return [
|
|
201
|
-
...(left[0]?.headers ?? []),
|
|
202
|
-
...(center[0]?.headers ?? []),
|
|
203
|
-
...(right[0]?.headers ?? []),
|
|
204
|
-
]
|
|
205
|
-
.map((header) => {
|
|
206
|
-
return header.getLeafHeaders()
|
|
207
|
-
})
|
|
208
|
-
.flat()
|
|
186
|
+
const topHeaders = table.getHeaderGroups()[0]?.headers ?? []
|
|
187
|
+
const result: Array<Header<TFeatures, TData, unknown>> = []
|
|
188
|
+
for (let i = 0; i < topHeaders.length; i++) {
|
|
189
|
+
const leafHeaders = topHeaders[i]!.getLeafHeaders()
|
|
190
|
+
for (let j = 0; j < leafHeaders.length; j++) {
|
|
191
|
+
result.push(leafHeaders[j]!)
|
|
192
|
+
}
|
|
193
|
+
}
|
|
194
|
+
return result
|
|
209
195
|
}
|
|
@@ -38,4 +38,8 @@ export interface TableReactivityBindings {
|
|
|
38
38
|
* Batches reactive updates to avoid intermediate recomputation.
|
|
39
39
|
*/
|
|
40
40
|
batch: (fn: () => void) => void
|
|
41
|
+
/**
|
|
42
|
+
* Schedules a function to run. This is used to defer updates after the current call stack (render, etc.) has finished
|
|
43
|
+
*/
|
|
44
|
+
schedule: (fn: () => void) => void
|
|
41
45
|
}
|
|
@@ -14,8 +14,9 @@ function getRowPrototype<
|
|
|
14
14
|
>(table: Table_Internal<TFeatures, TData>): object {
|
|
15
15
|
if (!table._rowPrototype) {
|
|
16
16
|
table._rowPrototype = { table }
|
|
17
|
-
|
|
18
|
-
|
|
17
|
+
const features = Object.values(table._features)
|
|
18
|
+
for (let i = 0; i < features.length; i++) {
|
|
19
|
+
features[i]!.assignRowPrototype?.(table._rowPrototype, table)
|
|
19
20
|
}
|
|
20
21
|
}
|
|
21
22
|
return table._rowPrototype
|
|
@@ -56,8 +57,9 @@ export const constructRow = <
|
|
|
56
57
|
row.subRows = subRows ?? []
|
|
57
58
|
|
|
58
59
|
// Initialize instance-specific data (e.g., caches) for features that need it
|
|
59
|
-
|
|
60
|
-
|
|
60
|
+
const features = Object.values(table._features)
|
|
61
|
+
for (let i = 0; i < features.length; i++) {
|
|
62
|
+
features[i]!.initRowInstanceData?.(row)
|
|
61
63
|
}
|
|
62
64
|
|
|
63
65
|
return row as Row<TFeatures, TData>
|
|
@@ -164,9 +164,14 @@ export function row_getAllCells<
|
|
|
164
164
|
TFeatures extends TableFeatures,
|
|
165
165
|
TData extends RowData,
|
|
166
166
|
>(row: Row<TFeatures, TData>): Array<Cell<TFeatures, TData, unknown>> {
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
167
|
+
const columns = row.table.getAllLeafColumns()
|
|
168
|
+
const cells: Array<Cell<TFeatures, TData, unknown>> = new Array(
|
|
169
|
+
columns.length,
|
|
170
|
+
)
|
|
171
|
+
for (let i = 0; i < columns.length; i++) {
|
|
172
|
+
cells[i] = constructCell(columns[i]!, row, row.table)
|
|
173
|
+
}
|
|
174
|
+
return cells
|
|
170
175
|
}
|
|
171
176
|
|
|
172
177
|
/**
|
|
@@ -184,7 +189,9 @@ export function row_getAllCellsByColumnId<
|
|
|
184
189
|
TData extends RowData,
|
|
185
190
|
>(row: Row<TFeatures, TData>) {
|
|
186
191
|
const result: Record<string, Cell<TFeatures, TData, unknown>> = {}
|
|
187
|
-
|
|
192
|
+
const cells = row.getAllCells()
|
|
193
|
+
for (let i = 0; i < cells.length; i++) {
|
|
194
|
+
const cell = cells[i]!
|
|
188
195
|
result[cell.column.id] = cell
|
|
189
196
|
}
|
|
190
197
|
return result
|
|
@@ -79,7 +79,8 @@ export function constructTable<
|
|
|
79
79
|
string & keyof TableState<TFeatures>
|
|
80
80
|
>
|
|
81
81
|
|
|
82
|
-
for (
|
|
82
|
+
for (let i = 0; i < stateKeys.length; i++) {
|
|
83
|
+
const key = stateKeys[i]!
|
|
83
84
|
// create writable base atom
|
|
84
85
|
table.baseAtoms[key] = _reactivity.createWritableAtom(
|
|
85
86
|
table.initialState[key],
|
|
@@ -107,7 +108,8 @@ export function constructTable<
|
|
|
107
108
|
_reactivity.createReadonlyAtom(
|
|
108
109
|
() => {
|
|
109
110
|
const snapshot = {} as TableState<TFeatures>
|
|
110
|
-
for (
|
|
111
|
+
for (let i = 0; i < stateKeys.length; i++) {
|
|
112
|
+
const key = stateKeys[i]!
|
|
111
113
|
snapshot[key] = table.atoms[key].get()
|
|
112
114
|
}
|
|
113
115
|
return snapshot
|
|
@@ -136,8 +138,8 @@ export function constructTable<
|
|
|
136
138
|
)
|
|
137
139
|
}
|
|
138
140
|
|
|
139
|
-
for (
|
|
140
|
-
|
|
141
|
+
for (let i = 0; i < featuresList.length; i++) {
|
|
142
|
+
featuresList[i]!.constructTableAPIs?.(table)
|
|
141
143
|
}
|
|
142
144
|
|
|
143
145
|
return table
|
|
@@ -56,7 +56,9 @@ export function table_reset<
|
|
|
56
56
|
>(table: Table_Internal<TFeatures, TData>): void {
|
|
57
57
|
const snap = cloneState(table.initialState)
|
|
58
58
|
table._reactivity.batch(() => {
|
|
59
|
-
|
|
59
|
+
const keys = Object.keys(snap) as Array<keyof typeof snap>
|
|
60
|
+
for (let i = 0; i < keys.length; i++) {
|
|
61
|
+
const key = keys[i]!
|
|
60
62
|
;(table.baseAtoms as any)[key].set(snap[key] as any)
|
|
61
63
|
}
|
|
62
64
|
})
|