@tanstack/react-table 9.0.0-alpha.46 → 9.0.0-alpha.48

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -49,6 +49,16 @@ A headless table library for building powerful datagrids with full control over
49
49
 
50
50
  ### <a href="https://tanstack.com/table">Read the Docs →</a>
51
51
 
52
+ ## Using an AI Coding Agent?
53
+
54
+ TanStack Table ships [TanStack Intent](https://github.com/TanStack/intent) skills inside each adapter package. After installing the library, run:
55
+
56
+ ```sh
57
+ npx @tanstack/intent@latest install
58
+ ```
59
+
60
+ to add skill-loading guidance for your agent (Claude Code, Cursor, Copilot, etc.). The same CLI also exposes `intent list` to browse available skills and `intent load <skill>` to print one for inspection. Skills version with the library — your agent gets guidance that matches the version of `@tanstack/<framework>-table` you installed. Only available for v9 and above.
61
+
52
62
  ## Get Involved
53
63
 
54
64
  - We welcome issues and pull requests!
@@ -1 +1 @@
1
- {"version":3,"file":"FlexRender.cjs","names":[],"sources":["../src/FlexRender.tsx"],"sourcesContent":["import React from 'react'\nimport type {\n Cell,\n CellData,\n Header,\n RowData,\n TableFeatures,\n} from '@tanstack/table-core'\nimport type { ComponentType, JSX, ReactNode } from 'react'\n\nexport type Renderable<TProps> = ReactNode | ComponentType<TProps>\n\nfunction isReactComponent<TProps>(\n component: unknown,\n): component is ComponentType<TProps> {\n return (\n isClassComponent(component) ||\n typeof component === 'function' ||\n isExoticComponent(component)\n )\n}\n\nfunction isClassComponent(component: any) {\n return (\n typeof component === 'function' &&\n (() => {\n const proto = Object.getPrototypeOf(component)\n return proto.prototype && proto.prototype.isReactComponent\n })()\n )\n}\n\nfunction isExoticComponent(component: any) {\n return (\n typeof component === 'object' &&\n typeof component.$$typeof === 'symbol' &&\n ['react.memo', 'react.forward_ref'].includes(component.$$typeof.description)\n )\n}\n\n/**\n * If rendering headers, cells, or footers with custom markup, use flexRender instead of `cell.getValue()` or `cell.renderValue()`.\n * @example flexRender(cell.column.columnDef.cell, cell.getContext())\n */\nexport function flexRender<TProps extends object>(\n Comp: Renderable<TProps>,\n props: TProps,\n): ReactNode | JSX.Element {\n return !Comp ? null : isReactComponent<TProps>(Comp) ? (\n <Comp {...props} />\n ) : (\n Comp\n )\n}\n\n/**\n * Simplified component wrapper of `flexRender`. Use this utility component to render headers, cells, or footers with custom markup.\n * Only one prop (`cell`, `header`, or `footer`) may be passed.\n * @example <FlexRender cell={cell} />\n * @example <FlexRender header={header} />\n * @example <FlexRender footer={footer} />\n */\nexport type FlexRenderProps<\n TFeatures extends TableFeatures,\n TData extends RowData,\n TValue extends CellData = CellData,\n> =\n | { cell: Cell<TFeatures, TData, TValue>; header?: never; footer?: never }\n | {\n header: Header<TFeatures, TData, TValue>\n cell?: never\n footer?: never\n }\n | {\n footer: Header<TFeatures, TData, TValue>\n cell?: never\n header?: never\n }\n\n/**\n * Simplified component wrapper of `flexRender`. Use this utility component to render headers, cells, or footers with custom markup.\n * Only one prop (`cell`, `header`, or `footer`) may be passed.\n * @example\n * ```tsx\n * <FlexRender cell={cell} />\n * <FlexRender header={header} />\n * <FlexRender footer={footer} />\n * ```\n *\n * This replaces calling `flexRender` directly like this:\n * ```tsx\n * flexRender(cell.column.columnDef.cell, cell.getContext())\n * flexRender(header.column.columnDef.header, header.getContext())\n * flexRender(footer.column.columnDef.footer, footer.getContext())\n * ```\n */\nexport function FlexRender<\n TFeatures extends TableFeatures,\n TData extends RowData,\n TValue extends CellData = CellData,\n>(props: FlexRenderProps<TFeatures, TData, TValue>) {\n if ('cell' in props && props.cell) {\n const cell = props.cell\n const def = cell.column.columnDef\n // When the column-grouping feature is registered, a cell can be in one of\n // three special modes that should not render `columnDef.cell` directly:\n // - aggregated: render `columnDef.aggregatedCell` (falling back to\n // `columnDef.cell` if the column did not define one)\n // - placeholder: a duplicate value within a group — render nothing\n // - grouped: the group header cell — let the consumer render this; we\n // fall through to `columnDef.cell` so the existing behavior is\n // preserved (consumers that want a custom group header typically\n // branch on `cell.getIsGrouped()` themselves before calling FlexRender)\n // The optional-chaining + cast keeps this safe when the grouping feature\n // is not registered (the methods are absent at the type level then).\n const groupingCell = cell as typeof cell & {\n getIsAggregated?: () => boolean\n getIsPlaceholder?: () => boolean\n }\n const groupingDef = def as typeof def & {\n aggregatedCell?: typeof def.cell\n }\n if (groupingCell.getIsAggregated?.()) {\n return flexRender(\n groupingDef.aggregatedCell ?? def.cell,\n cell.getContext(),\n )\n }\n if (groupingCell.getIsPlaceholder?.()) {\n return null\n }\n return flexRender(def.cell, cell.getContext())\n }\n if ('header' in props && props.header) {\n return flexRender(\n props.header.column.columnDef.header,\n props.header.getContext(),\n )\n }\n if ('footer' in props && props.footer) {\n return flexRender(\n props.footer.column.columnDef.footer,\n props.footer.getContext(),\n )\n }\n return null\n}\n"],"mappings":";;;;;AAYA,SAAS,iBACP,WACoC;CACpC,OACE,iBAAiB,UAAU,IAC3B,OAAO,cAAc,cACrB,kBAAkB,UAAU;;AAIhC,SAAS,iBAAiB,WAAgB;CACxC,OACE,OAAO,cAAc,qBACd;EACL,MAAM,QAAQ,OAAO,eAAe,UAAU;EAC9C,OAAO,MAAM,aAAa,MAAM,UAAU;KACxC;;AAIR,SAAS,kBAAkB,WAAgB;CACzC,OACE,OAAO,cAAc,YACrB,OAAO,UAAU,aAAa,YAC9B,CAAC,cAAc,oBAAoB,CAAC,SAAS,UAAU,SAAS,YAAY;;;;;;AAQhF,SAAgB,WACd,MACA,OACyB;CACzB,OAAO,CAAC,OAAO,OAAO,iBAAyB,KAAK,GAClD,4CAAC,MAAS,MAAS,GAEnB;;;;;;;;;;;;;;;;;;;AA6CJ,SAAgB,WAId,OAAkD;CAClD,IAAI,UAAU,SAAS,MAAM,MAAM;;EACjC,MAAM,OAAO,MAAM;EACnB,MAAM,MAAM,KAAK,OAAO;EAYxB,MAAM,eAAe;EAIrB,MAAM,cAAc;EAGpB,6BAAI,aAAa,iHAAmB,EAClC,OAAO,WACL,YAAY,kBAAkB,IAAI,MAClC,KAAK,YAAY,CAClB;EAEH,6BAAI,aAAa,kHAAoB,EACnC,OAAO;EAET,OAAO,WAAW,IAAI,MAAM,KAAK,YAAY,CAAC;;CAEhD,IAAI,YAAY,SAAS,MAAM,QAC7B,OAAO,WACL,MAAM,OAAO,OAAO,UAAU,QAC9B,MAAM,OAAO,YAAY,CAC1B;CAEH,IAAI,YAAY,SAAS,MAAM,QAC7B,OAAO,WACL,MAAM,OAAO,OAAO,UAAU,QAC9B,MAAM,OAAO,YAAY,CAC1B;CAEH,OAAO"}
1
+ {"version":3,"file":"FlexRender.cjs","names":[],"sources":["../src/FlexRender.tsx"],"sourcesContent":["import React from 'react'\nimport type {\n Cell,\n CellData,\n Header,\n RowData,\n TableFeatures,\n} from '@tanstack/table-core'\nimport type { ComponentType, JSX, ReactNode } from 'react'\n\nexport type Renderable<TProps> = ReactNode | ComponentType<TProps>\n\nfunction isReactComponent<TProps>(\n component: unknown,\n): component is ComponentType<TProps> {\n return (\n isClassComponent(component) ||\n typeof component === 'function' ||\n isExoticComponent(component)\n )\n}\n\nfunction isClassComponent(component: any) {\n return (\n typeof component === 'function' &&\n (() => {\n const proto = Object.getPrototypeOf(component)\n return proto.prototype && proto.prototype.isReactComponent\n })()\n )\n}\n\nfunction isExoticComponent(component: any) {\n return (\n typeof component === 'object' &&\n typeof component.$$typeof === 'symbol' &&\n ['react.memo', 'react.forward_ref'].includes(component.$$typeof.description)\n )\n}\n\n/**\n * If rendering headers, cells, or footers with custom markup, use flexRender instead of `cell.getValue()` or `cell.renderValue()`.\n * @example flexRender(cell.column.columnDef.cell, cell.getContext())\n */\nexport function flexRender<TProps extends object>(\n Comp: Renderable<TProps>,\n props: TProps,\n): ReactNode | JSX.Element {\n return !Comp ? null : isReactComponent<TProps>(Comp) ? (\n <Comp {...props} />\n ) : (\n Comp\n )\n}\n\n/**\n * Simplified component wrapper of `flexRender`. Use this utility component to render headers, cells, or footers with custom markup.\n * Only one prop (`cell`, `header`, or `footer`) may be passed.\n * @example <FlexRender cell={cell} />\n * @example <FlexRender header={header} />\n * @example <FlexRender footer={footer} />\n */\nexport type FlexRenderProps<\n TFeatures extends TableFeatures,\n TData extends RowData,\n TValue extends CellData = CellData,\n> =\n | { cell: Cell<TFeatures, TData, TValue>; header?: never; footer?: never }\n | {\n header: Header<TFeatures, TData, TValue>\n cell?: never\n footer?: never\n }\n | {\n footer: Header<TFeatures, TData, TValue>\n cell?: never\n header?: never\n }\n\n/**\n * Simplified component wrapper of `flexRender`. Use this utility component to render headers, cells, or footers with custom markup.\n * Only one prop (`cell`, `header`, or `footer`) may be passed.\n * @example\n * ```tsx\n * <FlexRender cell={cell} />\n * <FlexRender header={header} />\n * <FlexRender footer={footer} />\n * ```\n *\n * This replaces calling `flexRender` directly like this:\n * ```tsx\n * flexRender(cell.column.columnDef.cell, cell.getContext())\n * flexRender(header.column.columnDef.header, header.getContext())\n * flexRender(footer.column.columnDef.footer, footer.getContext())\n * ```\n */\nexport function FlexRender<\n TFeatures extends TableFeatures,\n TData extends RowData,\n TValue extends CellData = CellData,\n>(props: FlexRenderProps<TFeatures, TData, TValue>) {\n if ('cell' in props && props.cell) {\n const cell = props.cell\n const def = cell.column.columnDef\n const groupingCell = cell as typeof cell & {\n getIsAggregated?: () => boolean\n getIsPlaceholder?: () => boolean\n }\n const groupingDef = def as typeof def & {\n aggregatedCell?: typeof def.cell\n }\n if (groupingCell.getIsAggregated?.()) {\n return flexRender(\n groupingDef.aggregatedCell ?? def.cell,\n cell.getContext(),\n )\n }\n if (groupingCell.getIsPlaceholder?.()) {\n return null\n }\n return flexRender(def.cell, cell.getContext())\n }\n if ('header' in props && props.header) {\n return flexRender(\n props.header.column.columnDef.header,\n props.header.getContext(),\n )\n }\n if ('footer' in props && props.footer) {\n return flexRender(\n props.footer.column.columnDef.footer,\n props.footer.getContext(),\n )\n }\n return null\n}\n"],"mappings":";;;;;AAYA,SAAS,iBACP,WACoC;CACpC,OACE,iBAAiB,UAAU,IAC3B,OAAO,cAAc,cACrB,kBAAkB,UAAU;;AAIhC,SAAS,iBAAiB,WAAgB;CACxC,OACE,OAAO,cAAc,qBACd;EACL,MAAM,QAAQ,OAAO,eAAe,UAAU;EAC9C,OAAO,MAAM,aAAa,MAAM,UAAU;KACxC;;AAIR,SAAS,kBAAkB,WAAgB;CACzC,OACE,OAAO,cAAc,YACrB,OAAO,UAAU,aAAa,YAC9B,CAAC,cAAc,oBAAoB,CAAC,SAAS,UAAU,SAAS,YAAY;;;;;;AAQhF,SAAgB,WACd,MACA,OACyB;CACzB,OAAO,CAAC,OAAO,OAAO,iBAAyB,KAAK,GAClD,4CAAC,MAAS,MAAS,GAEnB;;;;;;;;;;;;;;;;;;;AA6CJ,SAAgB,WAId,OAAkD;CAClD,IAAI,UAAU,SAAS,MAAM,MAAM;;EACjC,MAAM,OAAO,MAAM;EACnB,MAAM,MAAM,KAAK,OAAO;EACxB,MAAM,eAAe;EAIrB,MAAM,cAAc;EAGpB,6BAAI,aAAa,iHAAmB,EAClC,OAAO,WACL,YAAY,kBAAkB,IAAI,MAClC,KAAK,YAAY,CAClB;EAEH,6BAAI,aAAa,kHAAoB,EACnC,OAAO;EAET,OAAO,WAAW,IAAI,MAAM,KAAK,YAAY,CAAC;;CAEhD,IAAI,YAAY,SAAS,MAAM,QAC7B,OAAO,WACL,MAAM,OAAO,OAAO,UAAU,QAC9B,MAAM,OAAO,YAAY,CAC1B;CAEH,IAAI,YAAY,SAAS,MAAM,QAC7B,OAAO,WACL,MAAM,OAAO,OAAO,UAAU,QAC9B,MAAM,OAAO,YAAY,CAC1B;CAEH,OAAO"}
@@ -1 +1 @@
1
- {"version":3,"file":"FlexRender.js","names":[],"sources":["../src/FlexRender.tsx"],"sourcesContent":["import React from 'react'\nimport type {\n Cell,\n CellData,\n Header,\n RowData,\n TableFeatures,\n} from '@tanstack/table-core'\nimport type { ComponentType, JSX, ReactNode } from 'react'\n\nexport type Renderable<TProps> = ReactNode | ComponentType<TProps>\n\nfunction isReactComponent<TProps>(\n component: unknown,\n): component is ComponentType<TProps> {\n return (\n isClassComponent(component) ||\n typeof component === 'function' ||\n isExoticComponent(component)\n )\n}\n\nfunction isClassComponent(component: any) {\n return (\n typeof component === 'function' &&\n (() => {\n const proto = Object.getPrototypeOf(component)\n return proto.prototype && proto.prototype.isReactComponent\n })()\n )\n}\n\nfunction isExoticComponent(component: any) {\n return (\n typeof component === 'object' &&\n typeof component.$$typeof === 'symbol' &&\n ['react.memo', 'react.forward_ref'].includes(component.$$typeof.description)\n )\n}\n\n/**\n * If rendering headers, cells, or footers with custom markup, use flexRender instead of `cell.getValue()` or `cell.renderValue()`.\n * @example flexRender(cell.column.columnDef.cell, cell.getContext())\n */\nexport function flexRender<TProps extends object>(\n Comp: Renderable<TProps>,\n props: TProps,\n): ReactNode | JSX.Element {\n return !Comp ? null : isReactComponent<TProps>(Comp) ? (\n <Comp {...props} />\n ) : (\n Comp\n )\n}\n\n/**\n * Simplified component wrapper of `flexRender`. Use this utility component to render headers, cells, or footers with custom markup.\n * Only one prop (`cell`, `header`, or `footer`) may be passed.\n * @example <FlexRender cell={cell} />\n * @example <FlexRender header={header} />\n * @example <FlexRender footer={footer} />\n */\nexport type FlexRenderProps<\n TFeatures extends TableFeatures,\n TData extends RowData,\n TValue extends CellData = CellData,\n> =\n | { cell: Cell<TFeatures, TData, TValue>; header?: never; footer?: never }\n | {\n header: Header<TFeatures, TData, TValue>\n cell?: never\n footer?: never\n }\n | {\n footer: Header<TFeatures, TData, TValue>\n cell?: never\n header?: never\n }\n\n/**\n * Simplified component wrapper of `flexRender`. Use this utility component to render headers, cells, or footers with custom markup.\n * Only one prop (`cell`, `header`, or `footer`) may be passed.\n * @example\n * ```tsx\n * <FlexRender cell={cell} />\n * <FlexRender header={header} />\n * <FlexRender footer={footer} />\n * ```\n *\n * This replaces calling `flexRender` directly like this:\n * ```tsx\n * flexRender(cell.column.columnDef.cell, cell.getContext())\n * flexRender(header.column.columnDef.header, header.getContext())\n * flexRender(footer.column.columnDef.footer, footer.getContext())\n * ```\n */\nexport function FlexRender<\n TFeatures extends TableFeatures,\n TData extends RowData,\n TValue extends CellData = CellData,\n>(props: FlexRenderProps<TFeatures, TData, TValue>) {\n if ('cell' in props && props.cell) {\n const cell = props.cell\n const def = cell.column.columnDef\n // When the column-grouping feature is registered, a cell can be in one of\n // three special modes that should not render `columnDef.cell` directly:\n // - aggregated: render `columnDef.aggregatedCell` (falling back to\n // `columnDef.cell` if the column did not define one)\n // - placeholder: a duplicate value within a group — render nothing\n // - grouped: the group header cell — let the consumer render this; we\n // fall through to `columnDef.cell` so the existing behavior is\n // preserved (consumers that want a custom group header typically\n // branch on `cell.getIsGrouped()` themselves before calling FlexRender)\n // The optional-chaining + cast keeps this safe when the grouping feature\n // is not registered (the methods are absent at the type level then).\n const groupingCell = cell as typeof cell & {\n getIsAggregated?: () => boolean\n getIsPlaceholder?: () => boolean\n }\n const groupingDef = def as typeof def & {\n aggregatedCell?: typeof def.cell\n }\n if (groupingCell.getIsAggregated?.()) {\n return flexRender(\n groupingDef.aggregatedCell ?? def.cell,\n cell.getContext(),\n )\n }\n if (groupingCell.getIsPlaceholder?.()) {\n return null\n }\n return flexRender(def.cell, cell.getContext())\n }\n if ('header' in props && props.header) {\n return flexRender(\n props.header.column.columnDef.header,\n props.header.getContext(),\n )\n }\n if ('footer' in props && props.footer) {\n return flexRender(\n props.footer.column.columnDef.footer,\n props.footer.getContext(),\n )\n }\n return null\n}\n"],"mappings":";;;AAYA,SAAS,iBACP,WACoC;CACpC,OACE,iBAAiB,UAAU,IAC3B,OAAO,cAAc,cACrB,kBAAkB,UAAU;;AAIhC,SAAS,iBAAiB,WAAgB;CACxC,OACE,OAAO,cAAc,qBACd;EACL,MAAM,QAAQ,OAAO,eAAe,UAAU;EAC9C,OAAO,MAAM,aAAa,MAAM,UAAU;KACxC;;AAIR,SAAS,kBAAkB,WAAgB;CACzC,OACE,OAAO,cAAc,YACrB,OAAO,UAAU,aAAa,YAC9B,CAAC,cAAc,oBAAoB,CAAC,SAAS,UAAU,SAAS,YAAY;;;;;;AAQhF,SAAgB,WACd,MACA,OACyB;CACzB,OAAO,CAAC,OAAO,OAAO,iBAAyB,KAAK,GAClD,oCAAC,MAAS,MAAS,GAEnB;;;;;;;;;;;;;;;;;;;AA6CJ,SAAgB,WAId,OAAkD;CAClD,IAAI,UAAU,SAAS,MAAM,MAAM;;EACjC,MAAM,OAAO,MAAM;EACnB,MAAM,MAAM,KAAK,OAAO;EAYxB,MAAM,eAAe;EAIrB,MAAM,cAAc;EAGpB,6BAAI,aAAa,iHAAmB,EAClC,OAAO,WACL,YAAY,kBAAkB,IAAI,MAClC,KAAK,YAAY,CAClB;EAEH,6BAAI,aAAa,kHAAoB,EACnC,OAAO;EAET,OAAO,WAAW,IAAI,MAAM,KAAK,YAAY,CAAC;;CAEhD,IAAI,YAAY,SAAS,MAAM,QAC7B,OAAO,WACL,MAAM,OAAO,OAAO,UAAU,QAC9B,MAAM,OAAO,YAAY,CAC1B;CAEH,IAAI,YAAY,SAAS,MAAM,QAC7B,OAAO,WACL,MAAM,OAAO,OAAO,UAAU,QAC9B,MAAM,OAAO,YAAY,CAC1B;CAEH,OAAO"}
1
+ {"version":3,"file":"FlexRender.js","names":[],"sources":["../src/FlexRender.tsx"],"sourcesContent":["import React from 'react'\nimport type {\n Cell,\n CellData,\n Header,\n RowData,\n TableFeatures,\n} from '@tanstack/table-core'\nimport type { ComponentType, JSX, ReactNode } from 'react'\n\nexport type Renderable<TProps> = ReactNode | ComponentType<TProps>\n\nfunction isReactComponent<TProps>(\n component: unknown,\n): component is ComponentType<TProps> {\n return (\n isClassComponent(component) ||\n typeof component === 'function' ||\n isExoticComponent(component)\n )\n}\n\nfunction isClassComponent(component: any) {\n return (\n typeof component === 'function' &&\n (() => {\n const proto = Object.getPrototypeOf(component)\n return proto.prototype && proto.prototype.isReactComponent\n })()\n )\n}\n\nfunction isExoticComponent(component: any) {\n return (\n typeof component === 'object' &&\n typeof component.$$typeof === 'symbol' &&\n ['react.memo', 'react.forward_ref'].includes(component.$$typeof.description)\n )\n}\n\n/**\n * If rendering headers, cells, or footers with custom markup, use flexRender instead of `cell.getValue()` or `cell.renderValue()`.\n * @example flexRender(cell.column.columnDef.cell, cell.getContext())\n */\nexport function flexRender<TProps extends object>(\n Comp: Renderable<TProps>,\n props: TProps,\n): ReactNode | JSX.Element {\n return !Comp ? null : isReactComponent<TProps>(Comp) ? (\n <Comp {...props} />\n ) : (\n Comp\n )\n}\n\n/**\n * Simplified component wrapper of `flexRender`. Use this utility component to render headers, cells, or footers with custom markup.\n * Only one prop (`cell`, `header`, or `footer`) may be passed.\n * @example <FlexRender cell={cell} />\n * @example <FlexRender header={header} />\n * @example <FlexRender footer={footer} />\n */\nexport type FlexRenderProps<\n TFeatures extends TableFeatures,\n TData extends RowData,\n TValue extends CellData = CellData,\n> =\n | { cell: Cell<TFeatures, TData, TValue>; header?: never; footer?: never }\n | {\n header: Header<TFeatures, TData, TValue>\n cell?: never\n footer?: never\n }\n | {\n footer: Header<TFeatures, TData, TValue>\n cell?: never\n header?: never\n }\n\n/**\n * Simplified component wrapper of `flexRender`. Use this utility component to render headers, cells, or footers with custom markup.\n * Only one prop (`cell`, `header`, or `footer`) may be passed.\n * @example\n * ```tsx\n * <FlexRender cell={cell} />\n * <FlexRender header={header} />\n * <FlexRender footer={footer} />\n * ```\n *\n * This replaces calling `flexRender` directly like this:\n * ```tsx\n * flexRender(cell.column.columnDef.cell, cell.getContext())\n * flexRender(header.column.columnDef.header, header.getContext())\n * flexRender(footer.column.columnDef.footer, footer.getContext())\n * ```\n */\nexport function FlexRender<\n TFeatures extends TableFeatures,\n TData extends RowData,\n TValue extends CellData = CellData,\n>(props: FlexRenderProps<TFeatures, TData, TValue>) {\n if ('cell' in props && props.cell) {\n const cell = props.cell\n const def = cell.column.columnDef\n const groupingCell = cell as typeof cell & {\n getIsAggregated?: () => boolean\n getIsPlaceholder?: () => boolean\n }\n const groupingDef = def as typeof def & {\n aggregatedCell?: typeof def.cell\n }\n if (groupingCell.getIsAggregated?.()) {\n return flexRender(\n groupingDef.aggregatedCell ?? def.cell,\n cell.getContext(),\n )\n }\n if (groupingCell.getIsPlaceholder?.()) {\n return null\n }\n return flexRender(def.cell, cell.getContext())\n }\n if ('header' in props && props.header) {\n return flexRender(\n props.header.column.columnDef.header,\n props.header.getContext(),\n )\n }\n if ('footer' in props && props.footer) {\n return flexRender(\n props.footer.column.columnDef.footer,\n props.footer.getContext(),\n )\n }\n return null\n}\n"],"mappings":";;;AAYA,SAAS,iBACP,WACoC;CACpC,OACE,iBAAiB,UAAU,IAC3B,OAAO,cAAc,cACrB,kBAAkB,UAAU;;AAIhC,SAAS,iBAAiB,WAAgB;CACxC,OACE,OAAO,cAAc,qBACd;EACL,MAAM,QAAQ,OAAO,eAAe,UAAU;EAC9C,OAAO,MAAM,aAAa,MAAM,UAAU;KACxC;;AAIR,SAAS,kBAAkB,WAAgB;CACzC,OACE,OAAO,cAAc,YACrB,OAAO,UAAU,aAAa,YAC9B,CAAC,cAAc,oBAAoB,CAAC,SAAS,UAAU,SAAS,YAAY;;;;;;AAQhF,SAAgB,WACd,MACA,OACyB;CACzB,OAAO,CAAC,OAAO,OAAO,iBAAyB,KAAK,GAClD,oCAAC,MAAS,MAAS,GAEnB;;;;;;;;;;;;;;;;;;;AA6CJ,SAAgB,WAId,OAAkD;CAClD,IAAI,UAAU,SAAS,MAAM,MAAM;;EACjC,MAAM,OAAO,MAAM;EACnB,MAAM,MAAM,KAAK,OAAO;EACxB,MAAM,eAAe;EAIrB,MAAM,cAAc;EAGpB,6BAAI,aAAa,iHAAmB,EAClC,OAAO,WACL,YAAY,kBAAkB,IAAI,MAClC,KAAK,YAAY,CAClB;EAEH,6BAAI,aAAa,kHAAoB,EACnC,OAAO;EAET,OAAO,WAAW,IAAI,MAAM,KAAK,YAAY,CAAC;;CAEhD,IAAI,YAAY,SAAS,MAAM,QAC7B,OAAO,WACL,MAAM,OAAO,OAAO,UAAU,QAC9B,MAAM,OAAO,YAAY,CAC1B;CAEH,IAAI,YAAY,SAAS,MAAM,QAC7B,OAAO,WACL,MAAM,OAAO,OAAO,UAAU,QAC9B,MAAM,OAAO,YAAY,CAC1B;CAEH,OAAO"}
@@ -11,6 +11,7 @@ let _tanstack_react_store = require("@tanstack/react-store");
11
11
  function reactReactivity() {
12
12
  return {
13
13
  createOptionsStore: false,
14
+ schedule: (fn) => queueMicrotask(fn),
14
15
  batch: _tanstack_react_store.batch,
15
16
  untrack: (fn) => fn(),
16
17
  createReadonlyAtom: (fn, options) => {
@@ -1 +1 @@
1
- {"version":3,"file":"reactivity.cjs","names":[],"sources":["../src/reactivity.ts"],"sourcesContent":["import { batch, createAtom } from '@tanstack/react-store'\nimport type {\n TableAtomOptions,\n TableReactivityBindings,\n} from '@tanstack/table-core/reactivity'\n\n/**\n * Creates the table-core reactivity bindings used by the React adapter.\n *\n * React stores table state in TanStack Store atoms and leaves options as plain\n * resolved data because `useTable` synchronizes options during render.\n */\nexport function reactReactivity(): TableReactivityBindings {\n return {\n createOptionsStore: false,\n batch,\n untrack: (fn) => fn(),\n createReadonlyAtom: <T>(fn: () => T, options?: TableAtomOptions<T>) => {\n return createAtom(() => fn(), {\n compare: options?.compare,\n })\n },\n createWritableAtom: <T>(value: T, options?: TableAtomOptions<T>) => {\n return createAtom(value, {\n compare: options?.compare,\n })\n },\n }\n}\n"],"mappings":";;;;;;;;;;AAYA,SAAgB,kBAA2C;CACzD,OAAO;EACL,oBAAoB;EACpB;EACA,UAAU,OAAO,IAAI;EACrB,qBAAwB,IAAa,YAAkC;GACrE,mDAAwB,IAAI,EAAE,EAC5B,2DAAS,QAAS,SACnB,CAAC;;EAEJ,qBAAwB,OAAU,YAAkC;GAClE,6CAAkB,OAAO,EACvB,2DAAS,QAAS,SACnB,CAAC;;EAEL"}
1
+ {"version":3,"file":"reactivity.cjs","names":[],"sources":["../src/reactivity.ts"],"sourcesContent":["import { batch, createAtom } from '@tanstack/react-store'\nimport type {\n TableAtomOptions,\n TableReactivityBindings,\n} from '@tanstack/table-core/reactivity'\n\n/**\n * Creates the table-core reactivity bindings used by the React adapter.\n *\n * React stores table state in TanStack Store atoms and leaves options as plain\n * resolved data because `useTable` synchronizes options during render.\n */\nexport function reactReactivity(): TableReactivityBindings {\n return {\n createOptionsStore: false,\n schedule: (fn) => queueMicrotask(fn),\n batch,\n untrack: (fn) => fn(),\n createReadonlyAtom: <T>(fn: () => T, options?: TableAtomOptions<T>) => {\n return createAtom(() => fn(), {\n compare: options?.compare,\n })\n },\n createWritableAtom: <T>(value: T, options?: TableAtomOptions<T>) => {\n return createAtom(value, {\n compare: options?.compare,\n })\n },\n }\n}\n"],"mappings":";;;;;;;;;;AAYA,SAAgB,kBAA2C;CACzD,OAAO;EACL,oBAAoB;EACpB,WAAW,OAAO,eAAe,GAAG;EACpC;EACA,UAAU,OAAO,IAAI;EACrB,qBAAwB,IAAa,YAAkC;GACrE,mDAAwB,IAAI,EAAE,EAC5B,2DAAS,QAAS,SACnB,CAAC;;EAEJ,qBAAwB,OAAU,YAAkC;GAClE,6CAAkB,OAAO,EACvB,2DAAS,QAAS,SACnB,CAAC;;EAEL"}
@@ -10,6 +10,7 @@ import { batch, createAtom } from "@tanstack/react-store";
10
10
  function reactReactivity() {
11
11
  return {
12
12
  createOptionsStore: false,
13
+ schedule: (fn) => queueMicrotask(fn),
13
14
  batch,
14
15
  untrack: (fn) => fn(),
15
16
  createReadonlyAtom: (fn, options) => {
@@ -1 +1 @@
1
- {"version":3,"file":"reactivity.js","names":[],"sources":["../src/reactivity.ts"],"sourcesContent":["import { batch, createAtom } from '@tanstack/react-store'\nimport type {\n TableAtomOptions,\n TableReactivityBindings,\n} from '@tanstack/table-core/reactivity'\n\n/**\n * Creates the table-core reactivity bindings used by the React adapter.\n *\n * React stores table state in TanStack Store atoms and leaves options as plain\n * resolved data because `useTable` synchronizes options during render.\n */\nexport function reactReactivity(): TableReactivityBindings {\n return {\n createOptionsStore: false,\n batch,\n untrack: (fn) => fn(),\n createReadonlyAtom: <T>(fn: () => T, options?: TableAtomOptions<T>) => {\n return createAtom(() => fn(), {\n compare: options?.compare,\n })\n },\n createWritableAtom: <T>(value: T, options?: TableAtomOptions<T>) => {\n return createAtom(value, {\n compare: options?.compare,\n })\n },\n }\n}\n"],"mappings":";;;;;;;;;AAYA,SAAgB,kBAA2C;CACzD,OAAO;EACL,oBAAoB;EACpB;EACA,UAAU,OAAO,IAAI;EACrB,qBAAwB,IAAa,YAAkC;GACrE,OAAO,iBAAiB,IAAI,EAAE,EAC5B,2DAAS,QAAS,SACnB,CAAC;;EAEJ,qBAAwB,OAAU,YAAkC;GAClE,OAAO,WAAW,OAAO,EACvB,2DAAS,QAAS,SACnB,CAAC;;EAEL"}
1
+ {"version":3,"file":"reactivity.js","names":[],"sources":["../src/reactivity.ts"],"sourcesContent":["import { batch, createAtom } from '@tanstack/react-store'\nimport type {\n TableAtomOptions,\n TableReactivityBindings,\n} from '@tanstack/table-core/reactivity'\n\n/**\n * Creates the table-core reactivity bindings used by the React adapter.\n *\n * React stores table state in TanStack Store atoms and leaves options as plain\n * resolved data because `useTable` synchronizes options during render.\n */\nexport function reactReactivity(): TableReactivityBindings {\n return {\n createOptionsStore: false,\n schedule: (fn) => queueMicrotask(fn),\n batch,\n untrack: (fn) => fn(),\n createReadonlyAtom: <T>(fn: () => T, options?: TableAtomOptions<T>) => {\n return createAtom(() => fn(), {\n compare: options?.compare,\n })\n },\n createWritableAtom: <T>(value: T, options?: TableAtomOptions<T>) => {\n return createAtom(value, {\n compare: options?.compare,\n })\n },\n }\n}\n"],"mappings":";;;;;;;;;AAYA,SAAgB,kBAA2C;CACzD,OAAO;EACL,oBAAoB;EACpB,WAAW,OAAO,eAAe,GAAG;EACpC;EACA,UAAU,OAAO,IAAI;EACrB,qBAAwB,IAAa,YAAkC;GACrE,OAAO,iBAAiB,IAAI,EAAE,EAC5B,2DAAS,QAAS,SACnB,CAAC;;EAEJ,qBAAwB,OAAU,YAAkC;GAClE,OAAO,WAAW,OAAO,EACvB,2DAAS,QAAS,SACnB,CAAC;;EAEL"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tanstack/react-table",
3
- "version": "9.0.0-alpha.46",
3
+ "version": "9.0.0-alpha.48",
4
4
  "description": "Headless UI for building powerful tables & datagrids for React.",
5
5
  "author": "Tanner Linsley",
6
6
  "license": "MIT",
@@ -18,7 +18,8 @@
18
18
  "react",
19
19
  "table",
20
20
  "react-table",
21
- "datagrid"
21
+ "datagrid",
22
+ "tanstack-intent"
22
23
  ],
23
24
  "type": "module",
24
25
  "types": "./dist/index.d.cts",
@@ -49,11 +50,12 @@
49
50
  },
50
51
  "files": [
51
52
  "dist",
52
- "src"
53
+ "src",
54
+ "skills"
53
55
  ],
54
56
  "dependencies": {
55
57
  "@tanstack/react-store": "^0.11.0",
56
- "@tanstack/table-core": "9.0.0-alpha.46"
58
+ "@tanstack/table-core": "9.0.0-alpha.48"
57
59
  },
58
60
  "devDependencies": {
59
61
  "@eslint-react/eslint-plugin": "^5.7.7",
@@ -0,0 +1,377 @@
1
+ ---
2
+ name: react/client-to-server
3
+ description: >
4
+ Convert a client-side `@tanstack/react-table` v9 table to server-side
5
+ (manual modes). Pass server-paginated/sorted/filtered rows as `data`, set
6
+ `manualPagination` / `manualSorting` / `manualFiltering` / `manualGrouping` /
7
+ `manualExpanding` for whatever the server now owns, supply `rowCount` so
8
+ `getPageCount()` works, and DROP the matching `_rowModels` entry (no
9
+ `paginatedRowModel` if the server paginates). Own the relevant state slices
10
+ via external atoms (`useCreateAtom` + `options.atoms`) so a query can key on
11
+ the slice and refetch automatically — OR via classic `state` + `on*Change`
12
+ controlled state.
13
+ type: lifecycle
14
+ library: tanstack-table
15
+ framework: react
16
+ library_version: '9.0.0-alpha.47'
17
+ requires:
18
+ - state-management
19
+ - pagination
20
+ - filtering
21
+ - sorting
22
+ - react/table-state
23
+ sources:
24
+ - TanStack/table:examples/react/basic-external-atoms/src/main.tsx
25
+ - TanStack/table:examples/react/with-tanstack-query/src/main.tsx
26
+ - TanStack/table:examples/react/with-tanstack-query/src/fetchData.ts
27
+ ---
28
+
29
+ This skill builds on `tanstack-table/state-management` and `tanstack-table/react/table-state`. Read those first — the atom model is what makes the cleanest server-side wiring possible.
30
+
31
+ ## Why "client-to-server"
32
+
33
+ A client-side table sees every row, sorts/filters/paginates them locally, and renders a slice. A server-side table sees only the slice the server returned for the current request; the table must be told "don't try to slice this again — and here's the total row count so you can render a pager".
34
+
35
+ Four moves convert any client table to a server table:
36
+
37
+ 1. **`manualX: true`** for whichever operations the server owns.
38
+ 2. **Drop the matching factory** from `_rowModels` so it doesn't ship in your bundle.
39
+ 3. **Provide `rowCount`** so `table.getPageCount()` / `getCanNextPage()` work.
40
+ 4. **Own the slice state externally** so your data fetcher can key on it.
41
+
42
+ ## Setup
43
+
44
+ Two state-ownership patterns work; pick one per slice.
45
+
46
+ ### Pattern A — external atom (cleanest with Query/SWR)
47
+
48
+ ```tsx
49
+ import * as React from 'react'
50
+ import { useCreateAtom, useSelector } from '@tanstack/react-store'
51
+ import {
52
+ useTable,
53
+ tableFeatures,
54
+ rowPaginationFeature,
55
+ createColumnHelper,
56
+ } from '@tanstack/react-table'
57
+ import type { PaginationState } from '@tanstack/react-table'
58
+
59
+ const _features = tableFeatures({ rowPaginationFeature })
60
+ const columnHelper = createColumnHelper<typeof _features, Person>()
61
+ const columns = columnHelper.columns([
62
+ columnHelper.accessor('firstName', { header: 'First' }),
63
+ columnHelper.accessor('age', { header: 'Age' }),
64
+ ])
65
+
66
+ const EMPTY: Person[] = []
67
+
68
+ function ServerTable() {
69
+ // 1) Own pagination in an external atom.
70
+ const paginationAtom = useCreateAtom<PaginationState>({
71
+ pageIndex: 0,
72
+ pageSize: 10,
73
+ })
74
+ const pagination = useSelector(paginationAtom)
75
+
76
+ // 2) Fetch keyed on the atom value.
77
+ const [serverPage, setServerPage] = React.useState<{
78
+ rows: Person[]
79
+ rowCount: number
80
+ } | null>(null)
81
+ React.useEffect(() => {
82
+ let cancelled = false
83
+ fetchPeople(pagination).then((page) => {
84
+ if (!cancelled) setServerPage(page)
85
+ })
86
+ return () => {
87
+ cancelled = true
88
+ }
89
+ }, [pagination])
90
+
91
+ // 3) Manual pagination + rowCount. No paginatedRowModel in _rowModels.
92
+ const table = useTable({
93
+ _features,
94
+ _rowModels: {}, // core only — server slices
95
+ columns,
96
+ data: serverPage?.rows ?? EMPTY, // EMPTY at module scope
97
+ rowCount: serverPage?.rowCount,
98
+ atoms: { pagination: paginationAtom }, // table writes here directly
99
+ manualPagination: true,
100
+ })
101
+ // No onPaginationChange — table.setPageIndex(...) writes through the atom.
102
+ }
103
+ ```
104
+
105
+ Source: `examples/react/basic-external-atoms/src/main.tsx` (atoms wiring); `examples/react/with-tanstack-query/src/main.tsx` (rowCount + manualPagination).
106
+
107
+ ### Pattern B — classic `state` + `on*Change`
108
+
109
+ ```tsx
110
+ const [pagination, setPagination] = React.useState<PaginationState>({
111
+ pageIndex: 0,
112
+ pageSize: 10,
113
+ })
114
+
115
+ const table = useTable({
116
+ _features,
117
+ _rowModels: {},
118
+ columns,
119
+ data: serverPage?.rows ?? EMPTY,
120
+ rowCount: serverPage?.rowCount,
121
+ state: { pagination },
122
+ onPaginationChange: setPagination, // REQUIRED with state.pagination
123
+ manualPagination: true,
124
+ })
125
+ ```
126
+
127
+ Both work. `state` + `on*Change` is familiar from v8; atoms compose more cleanly with Query (the table writes to the atom, the query key includes the atom value, the query refetches automatically).
128
+
129
+ ## Core Patterns
130
+
131
+ ### Combining server-side sort + filter + pagination
132
+
133
+ Add the matching `manual*` flags for each operation the server now owns. Local features (column visibility, ordering, pinning) still work because they don't depend on the row model.
134
+
135
+ ```tsx
136
+ const _features = tableFeatures({
137
+ rowSortingFeature,
138
+ rowPaginationFeature,
139
+ columnFilteringFeature,
140
+ columnVisibilityFeature, // still local
141
+ columnPinningFeature, // still local
142
+ })
143
+
144
+ const sortingAtom = useCreateAtom<SortingState>([])
145
+ const paginationAtom = useCreateAtom<PaginationState>({
146
+ pageIndex: 0,
147
+ pageSize: 10,
148
+ })
149
+ const columnFiltersAtom = useCreateAtom<ColumnFiltersState>([])
150
+
151
+ const sorting = useSelector(sortingAtom)
152
+ const pagination = useSelector(paginationAtom)
153
+ const columnFilters = useSelector(columnFiltersAtom)
154
+
155
+ const serverArgs = { sorting, pagination, columnFilters }
156
+ // ... fetch keyed on serverArgs
157
+
158
+ const table = useTable({
159
+ _features,
160
+ _rowModels: {}, // no sorted/filtered/paginated factories — server owns them
161
+ columns,
162
+ data: serverPage?.rows ?? EMPTY,
163
+ rowCount: serverPage?.rowCount,
164
+ atoms: {
165
+ sorting: sortingAtom,
166
+ pagination: paginationAtom,
167
+ columnFilters: columnFiltersAtom,
168
+ },
169
+ manualSorting: true,
170
+ manualFiltering: true,
171
+ manualPagination: true,
172
+ })
173
+ ```
174
+
175
+ Source: `examples/react/basic-external-atoms/src/main.tsx`.
176
+
177
+ ### When NOT to manual-mode a slice
178
+
179
+ If the server returns the **entire** dataset, leave the table client-side. Manual mode is for slices the server has already trimmed.
180
+
181
+ ## Common Mistakes
182
+
183
+ ### CRITICAL Forgetting `manualPagination` / `manualSorting` / `manualFiltering`
184
+
185
+ Wrong:
186
+
187
+ ```tsx
188
+ const table = useTable({
189
+ _features,
190
+ _rowModels: { paginatedRowModel: createPaginatedRowModel() },
191
+ columns,
192
+ data: serverPage.rows,
193
+ // missing manualPagination
194
+ })
195
+ ```
196
+
197
+ Correct:
198
+
199
+ ```tsx
200
+ const table = useTable({
201
+ _features,
202
+ _rowModels: {}, // dropped — server paginates
203
+ columns,
204
+ data: serverPage.rows,
205
+ rowCount: serverPage.rowCount,
206
+ manualPagination: true,
207
+ })
208
+ ```
209
+
210
+ Without `manualPagination: true`, the table tries to slice the already-server-sliced page a second time, producing rows that don't exist (or visibly wrong pagination).
211
+ Source: `examples/react/with-tanstack-query/src/main.tsx`.
212
+
213
+ ### CRITICAL Missing `rowCount`
214
+
215
+ Wrong:
216
+
217
+ ```tsx
218
+ const table = useTable({
219
+ _features,
220
+ _rowModels: {},
221
+ columns,
222
+ data: serverPage.rows,
223
+ manualPagination: true,
224
+ // missing rowCount: serverPage.totalRowCount
225
+ })
226
+ // table.getPageCount() → 1, pager locks at "Page 1 of 1"
227
+ ```
228
+
229
+ Correct:
230
+
231
+ ```tsx
232
+ const table = useTable({
233
+ _features,
234
+ _rowModels: {},
235
+ columns,
236
+ data: serverPage.rows,
237
+ rowCount: serverPage.rowCount, // ← required for accurate pager
238
+ manualPagination: true,
239
+ })
240
+ ```
241
+
242
+ Without `rowCount`, `getPageCount()` falls back to `Math.ceil(data.length / pageSize)` — which is 1 if the server returned a single page.
243
+ Source: `examples/react/with-tanstack-query/src/main.tsx`.
244
+
245
+ ### HIGH `state.pagination` without `onPaginationChange`
246
+
247
+ Wrong:
248
+
249
+ ```tsx
250
+ const [pagination] = React.useState<PaginationState>({
251
+ pageIndex: 0,
252
+ pageSize: 10,
253
+ })
254
+ useTable({
255
+ _features,
256
+ _rowModels: {},
257
+ columns,
258
+ data,
259
+ state: { pagination },
260
+ // missing onPaginationChange — table.setPageIndex is a no-op
261
+ manualPagination: true,
262
+ })
263
+ ```
264
+
265
+ Correct:
266
+
267
+ ```tsx
268
+ const [pagination, setPagination] = React.useState<PaginationState>({
269
+ pageIndex: 0,
270
+ pageSize: 10,
271
+ })
272
+ useTable({
273
+ _features,
274
+ _rowModels: {},
275
+ columns,
276
+ data,
277
+ state: { pagination },
278
+ onPaginationChange: setPagination, // ← required
279
+ manualPagination: true,
280
+ })
281
+ // OR — use atoms.pagination instead, which doesn't need a writeback handler.
282
+ ```
283
+
284
+ The library treats `state` as controlled; without a writeback handler, `table.setPageIndex(...)` writes nowhere.
285
+ Source: `docs/framework/react/guide/table-state.md`.
286
+
287
+ ### HIGH Leaving `paginatedRowModel` registered for a server-paginated table
288
+
289
+ Wrong:
290
+
291
+ ```tsx
292
+ useTable({
293
+ _features,
294
+ _rowModels: { paginatedRowModel: createPaginatedRowModel() }, // ships for nothing
295
+ columns,
296
+ data: serverPage.rows,
297
+ manualPagination: true,
298
+ })
299
+ ```
300
+
301
+ Correct:
302
+
303
+ ```tsx
304
+ useTable({
305
+ _features,
306
+ _rowModels: {}, // drop it — server owns pagination
307
+ columns,
308
+ data: serverPage.rows,
309
+ rowCount: serverPage.rowCount,
310
+ manualPagination: true,
311
+ })
312
+ ```
313
+
314
+ The factory ships in your bundle for no reason. Manual mode + the factory will also let the factory re-slice your already-sliced server page if `manualPagination` is ever flipped off.
315
+ Source: maintainer guidance.
316
+
317
+ ### HIGH Mixing `state.X` and `atoms.X` for the same slice
318
+
319
+ Wrong:
320
+
321
+ ```tsx
322
+ useTable({
323
+ _features,
324
+ _rowModels: {},
325
+ columns,
326
+ data,
327
+ state: { pagination }, // silently ignored
328
+ onPaginationChange: setPagination, // silently ignored
329
+ atoms: { pagination: paginationAtom }, // wins
330
+ manualPagination: true,
331
+ })
332
+ ```
333
+
334
+ Correct:
335
+
336
+ ```tsx
337
+ // Pick one ownership mechanism per slice.
338
+ useTable({
339
+ _features,
340
+ _rowModels: {},
341
+ columns,
342
+ data,
343
+ atoms: { pagination: paginationAtom },
344
+ manualPagination: true,
345
+ })
346
+ ```
347
+
348
+ Precedence is `options.atoms[key]` > `options.state[key]` > internal. The `state` plumbing is dead code in this configuration.
349
+ Source: `examples/react/basic-external-atoms/src/main.tsx`.
350
+
351
+ ### MEDIUM Recreating `data` array identity in JSX
352
+
353
+ Wrong:
354
+
355
+ ```tsx
356
+ <MyTable data={query.data?.rows ?? []} columns={columns} />
357
+ // `?? []` produces a new array reference each render → internal memos bust
358
+ ```
359
+
360
+ Correct:
361
+
362
+ ```tsx
363
+ const EMPTY: Person[] = [] // module scope
364
+
365
+ <MyTable data={query.data?.rows ?? EMPTY} columns={columns} />
366
+ // or wrap in useMemo
367
+ ```
368
+
369
+ Internal memoization keys off identity. A fresh `[]` each render bypasses memos and may force re-computation.
370
+ Source: maintainer guidance; `examples/react/with-tanstack-query/src/main.tsx`.
371
+
372
+ ## See Also
373
+
374
+ - `tanstack-table/react/compose-with-tanstack-query` — the canonical Query + server-side pattern.
375
+ - `tanstack-table/react/compose-with-tanstack-store` — sharing slice atoms across components.
376
+ - `tanstack-table/react/table-state` — selectors, `<Subscribe>`, external atoms.
377
+ - `tanstack-table/react/production-readiness` — when to narrow selectors as the table grows.