@tanstack/table-core 9.0.0-alpha.48 → 9.0.0-alpha.51

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.
Files changed (162) hide show
  1. package/dist/core/cells/constructCell.cjs.map +1 -1
  2. package/dist/core/cells/constructCell.js.map +1 -1
  3. package/dist/core/cells/coreCellsFeature.cjs.map +1 -1
  4. package/dist/core/cells/coreCellsFeature.js.map +1 -1
  5. package/dist/core/cells/coreCellsFeature.utils.cjs.map +1 -1
  6. package/dist/core/cells/coreCellsFeature.utils.js.map +1 -1
  7. package/dist/core/columns/constructColumn.cjs.map +1 -1
  8. package/dist/core/columns/constructColumn.js.map +1 -1
  9. package/dist/core/columns/coreColumnsFeature.cjs.map +1 -1
  10. package/dist/core/columns/coreColumnsFeature.js.map +1 -1
  11. package/dist/core/columns/coreColumnsFeature.utils.cjs.map +1 -1
  12. package/dist/core/columns/coreColumnsFeature.utils.js.map +1 -1
  13. package/dist/core/coreFeatures.cjs.map +1 -1
  14. package/dist/core/coreFeatures.js.map +1 -1
  15. package/dist/core/headers/buildHeaderGroups.cjs.map +1 -1
  16. package/dist/core/headers/buildHeaderGroups.js.map +1 -1
  17. package/dist/core/headers/constructHeader.cjs.map +1 -1
  18. package/dist/core/headers/constructHeader.js.map +1 -1
  19. package/dist/core/headers/coreHeadersFeature.cjs.map +1 -1
  20. package/dist/core/headers/coreHeadersFeature.js.map +1 -1
  21. package/dist/core/headers/coreHeadersFeature.utils.cjs.map +1 -1
  22. package/dist/core/headers/coreHeadersFeature.utils.js.map +1 -1
  23. package/dist/core/reactivity/coreReactivityFeature.utils.cjs.map +1 -1
  24. package/dist/core/reactivity/coreReactivityFeature.utils.js.map +1 -1
  25. package/dist/core/row-models/coreRowModelsFeature.cjs.map +1 -1
  26. package/dist/core/row-models/coreRowModelsFeature.js.map +1 -1
  27. package/dist/core/row-models/coreRowModelsFeature.utils.cjs.map +1 -1
  28. package/dist/core/row-models/coreRowModelsFeature.utils.js.map +1 -1
  29. package/dist/core/row-models/createCoreRowModel.cjs.map +1 -1
  30. package/dist/core/row-models/createCoreRowModel.js.map +1 -1
  31. package/dist/core/rows/constructRow.cjs.map +1 -1
  32. package/dist/core/rows/constructRow.js.map +1 -1
  33. package/dist/core/rows/coreRowsFeature.cjs.map +1 -1
  34. package/dist/core/rows/coreRowsFeature.js.map +1 -1
  35. package/dist/core/rows/coreRowsFeature.utils.cjs.map +1 -1
  36. package/dist/core/rows/coreRowsFeature.utils.js.map +1 -1
  37. package/dist/core/table/constructTable.cjs.map +1 -1
  38. package/dist/core/table/constructTable.js.map +1 -1
  39. package/dist/core/table/coreTablesFeature.cjs.map +1 -1
  40. package/dist/core/table/coreTablesFeature.js.map +1 -1
  41. package/dist/core/table/coreTablesFeature.types.d.cts +7 -0
  42. package/dist/core/table/coreTablesFeature.types.d.ts +7 -0
  43. package/dist/core/table/coreTablesFeature.utils.cjs.map +1 -1
  44. package/dist/core/table/coreTablesFeature.utils.js.map +1 -1
  45. package/dist/features/column-faceting/columnFacetingFeature.cjs.map +1 -1
  46. package/dist/features/column-faceting/columnFacetingFeature.js.map +1 -1
  47. package/dist/features/column-faceting/columnFacetingFeature.utils.cjs.map +1 -1
  48. package/dist/features/column-faceting/columnFacetingFeature.utils.js.map +1 -1
  49. package/dist/features/column-faceting/createFacetedMinMaxValues.cjs.map +1 -1
  50. package/dist/features/column-faceting/createFacetedMinMaxValues.js.map +1 -1
  51. package/dist/features/column-faceting/createFacetedRowModel.cjs.map +1 -1
  52. package/dist/features/column-faceting/createFacetedRowModel.js.map +1 -1
  53. package/dist/features/column-faceting/createFacetedUniqueValues.cjs.map +1 -1
  54. package/dist/features/column-faceting/createFacetedUniqueValues.js.map +1 -1
  55. package/dist/features/column-filtering/columnFilteringFeature.cjs.map +1 -1
  56. package/dist/features/column-filtering/columnFilteringFeature.js.map +1 -1
  57. package/dist/features/column-filtering/columnFilteringFeature.utils.cjs.map +1 -1
  58. package/dist/features/column-filtering/columnFilteringFeature.utils.js.map +1 -1
  59. package/dist/features/column-filtering/createFilteredRowModel.cjs.map +1 -1
  60. package/dist/features/column-filtering/createFilteredRowModel.js.map +1 -1
  61. package/dist/features/column-filtering/filterRowsUtils.cjs.map +1 -1
  62. package/dist/features/column-filtering/filterRowsUtils.js.map +1 -1
  63. package/dist/features/column-grouping/columnGroupingFeature.cjs.map +1 -1
  64. package/dist/features/column-grouping/columnGroupingFeature.js.map +1 -1
  65. package/dist/features/column-grouping/columnGroupingFeature.utils.cjs.map +1 -1
  66. package/dist/features/column-grouping/columnGroupingFeature.utils.js.map +1 -1
  67. package/dist/features/column-grouping/createGroupedRowModel.cjs.map +1 -1
  68. package/dist/features/column-grouping/createGroupedRowModel.js.map +1 -1
  69. package/dist/features/column-ordering/columnOrderingFeature.cjs.map +1 -1
  70. package/dist/features/column-ordering/columnOrderingFeature.js.map +1 -1
  71. package/dist/features/column-ordering/columnOrderingFeature.utils.cjs.map +1 -1
  72. package/dist/features/column-ordering/columnOrderingFeature.utils.js.map +1 -1
  73. package/dist/features/column-pinning/columnPinningFeature.cjs.map +1 -1
  74. package/dist/features/column-pinning/columnPinningFeature.js.map +1 -1
  75. package/dist/features/column-pinning/columnPinningFeature.utils.cjs.map +1 -1
  76. package/dist/features/column-pinning/columnPinningFeature.utils.js.map +1 -1
  77. package/dist/features/column-resizing/columnResizingFeature.cjs.map +1 -1
  78. package/dist/features/column-resizing/columnResizingFeature.js.map +1 -1
  79. package/dist/features/column-resizing/columnResizingFeature.utils.cjs +1 -1
  80. package/dist/features/column-resizing/columnResizingFeature.utils.cjs.map +1 -1
  81. package/dist/features/column-resizing/columnResizingFeature.utils.js +1 -1
  82. package/dist/features/column-resizing/columnResizingFeature.utils.js.map +1 -1
  83. package/dist/features/column-sizing/columnSizingFeature.cjs.map +1 -1
  84. package/dist/features/column-sizing/columnSizingFeature.js.map +1 -1
  85. package/dist/features/column-sizing/columnSizingFeature.utils.cjs.map +1 -1
  86. package/dist/features/column-sizing/columnSizingFeature.utils.js.map +1 -1
  87. package/dist/features/column-visibility/columnVisibilityFeature.cjs.map +1 -1
  88. package/dist/features/column-visibility/columnVisibilityFeature.js.map +1 -1
  89. package/dist/features/column-visibility/columnVisibilityFeature.utils.cjs.map +1 -1
  90. package/dist/features/column-visibility/columnVisibilityFeature.utils.js.map +1 -1
  91. package/dist/features/global-filtering/globalFilteringFeature.cjs.map +1 -1
  92. package/dist/features/global-filtering/globalFilteringFeature.js.map +1 -1
  93. package/dist/features/global-filtering/globalFilteringFeature.utils.cjs.map +1 -1
  94. package/dist/features/global-filtering/globalFilteringFeature.utils.js.map +1 -1
  95. package/dist/features/row-expanding/createExpandedRowModel.cjs.map +1 -1
  96. package/dist/features/row-expanding/createExpandedRowModel.js.map +1 -1
  97. package/dist/features/row-expanding/rowExpandingFeature.cjs.map +1 -1
  98. package/dist/features/row-expanding/rowExpandingFeature.js.map +1 -1
  99. package/dist/features/row-expanding/rowExpandingFeature.utils.cjs.map +1 -1
  100. package/dist/features/row-expanding/rowExpandingFeature.utils.js.map +1 -1
  101. package/dist/features/row-pagination/createPaginatedRowModel.cjs.map +1 -1
  102. package/dist/features/row-pagination/createPaginatedRowModel.js.map +1 -1
  103. package/dist/features/row-pagination/rowPaginationFeature.cjs.map +1 -1
  104. package/dist/features/row-pagination/rowPaginationFeature.js.map +1 -1
  105. package/dist/features/row-pagination/rowPaginationFeature.utils.cjs.map +1 -1
  106. package/dist/features/row-pagination/rowPaginationFeature.utils.js.map +1 -1
  107. package/dist/features/row-pinning/rowPinningFeature.cjs.map +1 -1
  108. package/dist/features/row-pinning/rowPinningFeature.js.map +1 -1
  109. package/dist/features/row-pinning/rowPinningFeature.utils.cjs.map +1 -1
  110. package/dist/features/row-pinning/rowPinningFeature.utils.js.map +1 -1
  111. package/dist/features/row-selection/rowSelectionFeature.cjs.map +1 -1
  112. package/dist/features/row-selection/rowSelectionFeature.js.map +1 -1
  113. package/dist/features/row-selection/rowSelectionFeature.utils.cjs.map +1 -1
  114. package/dist/features/row-selection/rowSelectionFeature.utils.js.map +1 -1
  115. package/dist/features/row-sorting/createSortedRowModel.cjs.map +1 -1
  116. package/dist/features/row-sorting/createSortedRowModel.js.map +1 -1
  117. package/dist/features/row-sorting/rowSortingFeature.cjs.map +1 -1
  118. package/dist/features/row-sorting/rowSortingFeature.js.map +1 -1
  119. package/dist/features/row-sorting/rowSortingFeature.utils.cjs +1 -1
  120. package/dist/features/row-sorting/rowSortingFeature.utils.cjs.map +1 -1
  121. package/dist/features/row-sorting/rowSortingFeature.utils.js +1 -1
  122. package/dist/features/row-sorting/rowSortingFeature.utils.js.map +1 -1
  123. package/dist/features/stockFeatures.cjs.map +1 -1
  124. package/dist/features/stockFeatures.js.map +1 -1
  125. package/dist/flex-render.cjs.map +1 -1
  126. package/dist/flex-render.js.map +1 -1
  127. package/dist/fns/aggregationFns.cjs.map +1 -1
  128. package/dist/fns/aggregationFns.js.map +1 -1
  129. package/dist/fns/filterFns.cjs.map +1 -1
  130. package/dist/fns/filterFns.js.map +1 -1
  131. package/dist/fns/sortFns.cjs.map +1 -1
  132. package/dist/fns/sortFns.js.map +1 -1
  133. package/dist/helpers/columnHelper.cjs.map +1 -1
  134. package/dist/helpers/columnHelper.js.map +1 -1
  135. package/dist/helpers/tableFeatures.cjs.map +1 -1
  136. package/dist/helpers/tableFeatures.js.map +1 -1
  137. package/dist/helpers/tableOptions.cjs.map +1 -1
  138. package/dist/helpers/tableOptions.js.map +1 -1
  139. package/dist/store-reactivity-bindings.cjs.map +1 -1
  140. package/dist/store-reactivity-bindings.js.map +1 -1
  141. package/dist/utils.cjs +2 -1
  142. package/dist/utils.cjs.map +1 -1
  143. package/dist/utils.js +2 -1
  144. package/dist/utils.js.map +1 -1
  145. package/package.json +1 -1
  146. package/skills/column-definitions/SKILL.md +1 -1
  147. package/skills/column-layout/SKILL.md +1 -1
  148. package/skills/customizing-feature-behavior/SKILL.md +1 -1
  149. package/skills/filtering/SKILL.md +1 -1
  150. package/skills/grouping/SKILL.md +1 -1
  151. package/skills/migrate-v8-to-v9/SKILL.md +1 -1
  152. package/skills/pagination/SKILL.md +1 -1
  153. package/skills/row-expanding/SKILL.md +1 -1
  154. package/skills/row-pinning/SKILL.md +1 -1
  155. package/skills/row-selection/SKILL.md +1 -1
  156. package/skills/setup/SKILL.md +1 -1
  157. package/skills/sorting/SKILL.md +1 -1
  158. package/skills/state-management/SKILL.md +1 -1
  159. package/src/core/table/coreTablesFeature.types.ts +7 -0
  160. package/src/features/column-resizing/columnResizingFeature.utils.ts +1 -2
  161. package/src/features/row-sorting/rowSortingFeature.utils.ts +1 -1
  162. package/src/utils.ts +5 -1
@@ -1 +1 @@
1
- {"version":3,"file":"utils.cjs","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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"}
1
+ {"version":3,"file":"utils.cjs","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 if (!onAfterUpdate) {\n return\n }\n\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/dist/utils.js CHANGED
@@ -128,8 +128,9 @@ function tableMemo({ feature, fnName, objectId, onAfterUpdate, table, ...memoOpt
128
128
  console.groupEnd();
129
129
  }
130
130
  const onAfterUpdateHandler = () => {
131
+ if (!onAfterUpdate) return;
131
132
  const { schedule, untrack } = table._reactivity;
132
- schedule(() => untrack(() => onAfterUpdate === null || onAfterUpdate === void 0 ? void 0 : onAfterUpdate()));
133
+ schedule(() => untrack(() => onAfterUpdate()));
133
134
  };
134
135
  const debugOptions = process.env.NODE_ENV === "development" ? {
135
136
  onBeforeCompare: () => {
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 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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"}
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 if (!onAfterUpdate) {\n return\n }\n\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
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tanstack/table-core",
3
- "version": "9.0.0-alpha.48",
3
+ "version": "9.0.0-alpha.51",
4
4
  "description": "Headless UI for building powerful tables & datagrids for TS/JS.",
5
5
  "author": "Tanner Linsley",
6
6
  "license": "MIT",
@@ -9,7 +9,7 @@ description: >
9
9
  required `id` rules, and `getRowId` for stable row identity.
10
10
  type: core
11
11
  library: tanstack-table
12
- library_version: '9.0.0-alpha.47'
12
+ library_version: '9.0.0-alpha.48'
13
13
  sources:
14
14
  - TanStack/table:docs/guide/column-defs.md
15
15
  - TanStack/table:docs/guide/columns.md
@@ -14,7 +14,7 @@ description: >
14
14
  performant resize pattern). Pipeline: Column Pinning → columnOrder → Grouping.
15
15
  type: core
16
16
  library: tanstack-table
17
- library_version: '9.0.0-alpha.47'
17
+ library_version: '9.0.0-alpha.48'
18
18
  requires:
19
19
  - state-management
20
20
  sources:
@@ -12,7 +12,7 @@ description: >
12
12
  `aggregationFn` (produces value) from `aggregatedCell` (renders value).
13
13
  type: core
14
14
  library: tanstack-table
15
- library_version: '9.0.0-alpha.47'
15
+ library_version: '9.0.0-alpha.48'
16
16
  requires:
17
17
  - state-management
18
18
  sources:
@@ -15,7 +15,7 @@ description: >
15
15
  fuzzy-filtering.
16
16
  type: core
17
17
  library: tanstack-table
18
- library_version: '9.0.0-alpha.47'
18
+ library_version: '9.0.0-alpha.48'
19
19
  requires:
20
20
  - state-management
21
21
  - customizing-feature-behavior
@@ -13,7 +13,7 @@ description: >
13
13
  and the required `rowExpandingFeature` pairing for drill-down UX.
14
14
  type: core
15
15
  library: tanstack-table
16
- library_version: '9.0.0-alpha.47'
16
+ library_version: '9.0.0-alpha.48'
17
17
  requires:
18
18
  - state-management
19
19
  - customizing-feature-behavior
@@ -16,7 +16,7 @@ description: >
16
16
  on" registry.
17
17
  type: lifecycle
18
18
  library: tanstack-table
19
- library_version: '9.0.0-alpha.47'
19
+ library_version: '9.0.0-alpha.48'
20
20
  requires:
21
21
  - setup
22
22
  - state-management
@@ -11,7 +11,7 @@ description: >
11
11
  for "total filtered" counts.
12
12
  type: core
13
13
  library: tanstack-table
14
- library_version: '9.0.0-alpha.47'
14
+ library_version: '9.0.0-alpha.48'
15
15
  requires:
16
16
  - state-management
17
17
  sources:
@@ -12,7 +12,7 @@ description: >
12
12
  `maxLeafRowFilterDepth` interaction with filtering.
13
13
  type: core
14
14
  library: tanstack-table
15
- library_version: '9.0.0-alpha.47'
15
+ library_version: '9.0.0-alpha.48'
16
16
  requires:
17
17
  - state-management
18
18
  sources:
@@ -12,7 +12,7 @@ description: >
12
12
  Sorting.
13
13
  type: core
14
14
  library: tanstack-table
15
- library_version: '9.0.0-alpha.47'
15
+ library_version: '9.0.0-alpha.48'
16
16
  requires:
17
17
  - state-management
18
18
  sources:
@@ -13,7 +13,7 @@ description: >
13
13
  and why `getRowId` is essentially mandatory — especially under server pagination.
14
14
  type: core
15
15
  library: tanstack-table
16
- library_version: '9.0.0-alpha.47'
16
+ library_version: '9.0.0-alpha.48'
17
17
  requires:
18
18
  - state-management
19
19
  - column-definitions
@@ -10,7 +10,7 @@ description: >
10
10
  be module-scoped, when to reach for `stockFeatures`, and `coreFeatures`.
11
11
  type: core
12
12
  library: tanstack-table
13
- library_version: '9.0.0-alpha.47'
13
+ library_version: '9.0.0-alpha.48'
14
14
  requires:
15
15
  - state-management
16
16
  - column-definitions
@@ -13,7 +13,7 @@ description: >
13
13
  `manualSorting` for server-side, and fuzzy `compareItems` pairing.
14
14
  type: core
15
15
  library: tanstack-table
16
- library_version: '9.0.0-alpha.47'
16
+ library_version: '9.0.0-alpha.48'
17
17
  requires:
18
18
  - state-management
19
19
  - customizing-feature-behavior
@@ -12,7 +12,7 @@ description: >
12
12
  `GroupingState` shapes. Foundational for every other skill.
13
13
  type: core
14
14
  library: tanstack-table
15
- library_version: '9.0.0-alpha.47'
15
+ library_version: '9.0.0-alpha.48'
16
16
  sources:
17
17
  - TanStack/table:docs/framework/vanilla/guide/table-state.md
18
18
  - TanStack/table:docs/framework/react/guide/table-state.md
@@ -93,6 +93,13 @@ export interface TableOptions_Table<
93
93
  * The data for the table to display. When the `data` option changes reference, the table will reprocess the data.
94
94
  */
95
95
  readonly data: ReadonlyArray<TData>
96
+ /**
97
+ * Optional key used to identify this table instance.
98
+ *
99
+ * This is used by TanStack Table Devtools to register and select tables. It is
100
+ * not required unless the table is passed to devtools.
101
+ */
102
+ readonly key?: string
96
103
  /**
97
104
  * Optionally provide starting values for registered table state slices.
98
105
  * Feature reset APIs use this value by default, and many reset APIs accept
@@ -314,6 +314,7 @@ export function table_resetHeaderSizeInfo<
314
314
  )
315
315
  }
316
316
 
317
+ let passiveSupported: boolean | null = null
317
318
  /**
318
319
  * Detects whether the current environment supports passive event listeners.
319
320
  *
@@ -326,8 +327,6 @@ export function table_resetHeaderSizeInfo<
326
327
  * ```
327
328
  */
328
329
  export function passiveEventSupported() {
329
- let passiveSupported: boolean | null = null
330
-
331
330
  if (typeof passiveSupported === 'boolean') return passiveSupported
332
331
 
333
332
  let supported = false
@@ -91,7 +91,7 @@ export function column_getAutoSortFn<
91
91
 
92
92
  let sortFn: SortFn<TFeatures, TData> | undefined
93
93
 
94
- const firstRows = column.table.getFilteredRowModel().flatRows.slice(10)
94
+ const firstRows = column.table.getFilteredRowModel().flatRows.slice(0, 10)
95
95
 
96
96
  let isString = false
97
97
 
package/src/utils.ts CHANGED
@@ -254,8 +254,12 @@ export function tableMemo<
254
254
  }
255
255
 
256
256
  const onAfterUpdateHandler = () => {
257
+ if (!onAfterUpdate) {
258
+ return
259
+ }
260
+
257
261
  const { schedule, untrack } = table._reactivity
258
- schedule(() => untrack(() => onAfterUpdate?.()))
262
+ schedule(() => untrack(() => onAfterUpdate()))
259
263
  }
260
264
 
261
265
  const debugOptions =