From 75a41ced4d561ccea9fad6debcbfb9cfcff55f0b Mon Sep 17 00:00:00 2001 From: Lachlan Collins <1667261+lachlancollins@users.noreply.github.com> Date: Tue, 10 Feb 2026 10:39:54 +1100 Subject: [PATCH 1/2] Pull more important changes from main --- .gitattributes | 2 +- .github/ISSUE_TEMPLATE/config.yml | 7 +- .github/pull_request_template | 8 + .github/workflows/release.yml | 2 - .npmrc | 2 - docs/framework/react/guide/table-state.md | 4 +- docs/guide/cells.md | 6 +- docs/guide/column-defs.md | 8 +- docs/guide/column-faceting.md | 4 +- docs/guide/column-filtering.md | 20 +- docs/guide/column-ordering.md | 12 +- docs/guide/column-pinning.md | 28 +-- docs/guide/column-sizing.md | 8 +- docs/guide/column-visibility.md | 12 +- docs/guide/columns.md | 10 +- docs/guide/custom-features.md | 4 +- docs/guide/data.md | 8 +- docs/guide/expanding.md | 8 +- docs/guide/features.md | 30 +-- docs/guide/filters.md | 10 +- docs/guide/fuzzy-filtering.md | 4 +- docs/guide/global-faceting.md | 4 +- docs/guide/global-filtering.md | 6 +- docs/guide/grouping.md | 8 +- docs/guide/header-groups.md | 8 +- docs/guide/headers.md | 12 +- docs/guide/pagination.md | 18 +- docs/guide/pinning.md | 4 +- docs/guide/row-pinning.md | 6 +- docs/guide/row-selection.md | 8 +- docs/guide/rows.md | 6 +- docs/guide/sorting.md | 6 +- docs/guide/tables.md | 16 +- docs/guide/virtualization.md | 10 +- docs/overview.md | 52 ++--- eslint.config.js | 7 +- nx.json | 7 +- package.json | 12 +- packages/lit-table/vite.config.ts | 2 +- packages/match-sorter-utils/vite.config.ts | 2 +- packages/preact-table/vite.config.ts | 2 +- packages/react-table/vite.config.ts | 2 +- packages/table-core/vite.config.ts | 2 +- packages/vue-table/vite.config.ts | 2 +- pnpm-lock.yaml | 216 +++++++++++++++------ pnpm-workspace.yaml | 4 + scripts/generateDocs.js | 53 ++--- scripts/publish.js | 2 +- scripts/verify-links.ts | 125 ++++++++++++ tsconfig.json | 9 +- 50 files changed, 517 insertions(+), 291 deletions(-) create mode 100644 .github/pull_request_template create mode 100644 scripts/verify-links.ts diff --git a/.gitattributes b/.gitattributes index dfe0770424..5a0d5e480b 100644 --- a/.gitattributes +++ b/.gitattributes @@ -1,2 +1,2 @@ # Auto detect text files and perform LF normalization -* text=auto +* text=auto eol=lf diff --git a/.github/ISSUE_TEMPLATE/config.yml b/.github/ISSUE_TEMPLATE/config.yml index 6a5ed2d4a4..e657773eab 100644 --- a/.github/ISSUE_TEMPLATE/config.yml +++ b/.github/ISSUE_TEMPLATE/config.yml @@ -1,8 +1,11 @@ blank_issues_enabled: false contact_links: - - name: Feature Requests & Questions + - name: šŸ¤” Feature Requests & Questions url: https://github.com/TanStack/table/discussions about: Please ask and answer questions here. - - name: Community Chat + - name: šŸ’¬ Community Chat url: https://discord.gg/mQd7egN about: A dedicated discord server hosted by TanStack + - name: šŸ¦‹ TanStack Bluesky + url: https://bsky.app/profile/tanstack.com + about: Stay up to date with new releases of our libraries \ No newline at end of file diff --git a/.github/pull_request_template b/.github/pull_request_template new file mode 100644 index 0000000000..2c10bc7d7d --- /dev/null +++ b/.github/pull_request_template @@ -0,0 +1,8 @@ +## šŸŽÆ Changes + + + +## āœ… Checklist + +- [ ] I have followed the steps in the [Contributing guide](https://github.com/TanStack/table/blob/main/CONTRIBUTING.md). +- [ ] I have tested this code locally with `pnpm test:pr`. diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 571a8cda61..c44687d853 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -43,9 +43,7 @@ jobs: run: | git config --global user.name 'Tanner Linsley' git config --global user.email 'tannerlinsley@users.noreply.github.com' - npm config set '//registry.npmjs.org/:_authToken' "${NPM_TOKEN}" pnpm run cipublish env: GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} - NPM_TOKEN: ${{ secrets.NPM_TOKEN }} TAG: ${{ inputs.tag }} diff --git a/.npmrc b/.npmrc index 84aee8d998..268c392d3c 100644 --- a/.npmrc +++ b/.npmrc @@ -1,3 +1 @@ -link-workspace-packages=true -prefer-workspace-packages=true provenance=true diff --git a/docs/framework/react/guide/table-state.md b/docs/framework/react/guide/table-state.md index 405e01ec51..fa11792898 100644 --- a/docs/framework/react/guide/table-state.md +++ b/docs/framework/react/guide/table-state.md @@ -6,8 +6,8 @@ title: Table State (React) Guide Want to skip to the implementation? Check out these examples: -- [kitchen sink](../../examples/kitchen-sink) -- [fully controlled](../../examples/fully-controlled) +- [kitchen sink](../examples/kitchen-sink) +- [fully controlled](../examples/fully-controlled) ## Table State (React) Guide diff --git a/docs/guide/cells.md b/docs/guide/cells.md index 489411122e..a6e9e443c4 100644 --- a/docs/guide/cells.md +++ b/docs/guide/cells.md @@ -4,7 +4,7 @@ title: Cells Guide ## API -[Cell API](../../api/core/cell) +[Cell API](../api/core/cell) ## Cells Guide @@ -12,7 +12,7 @@ This quick guide will discuss the different ways you can retrieve and interact w ### Where to Get Cells From -Cells come from [Rows](../rows). Enough said, right? +Cells come from [Rows](./rows). Enough said, right? There are multiple `row` instance APIs you can use to retrieve the appropriate cells from a row depending on which features you are using. Most commonly, you will use the `row.getAllCells` or `row.getVisibleCells` APIs (if you are using column visibility features), but there are a handful of other similar APIs that you can use. @@ -32,7 +32,7 @@ During grouping or aggregation features, the `cell.id` will have additional stri #### Cell Parent Objects -Every cell stores a reference to its parent [row](../rows) and [column](../columns) objects. +Every cell stores a reference to its parent [row](./rows) and [column](./columns) objects. #### Access Cell Values diff --git a/docs/guide/column-defs.md b/docs/guide/column-defs.md index 4b4f997dc9..03a1f366d3 100644 --- a/docs/guide/column-defs.md +++ b/docs/guide/column-defs.md @@ -4,17 +4,17 @@ title: Columns Definitions Guide ## API -[Column Def](../../api/core/column-def) +[Column Def](../api/core/column-def) ## Column Definitions Guide -> Note: This guide is about setting up column definitions for your table and NOT about the actual [`column`](../columns) objects that are generated within the table instance. +> Note: This guide is about setting up column definitions for your table and NOT about the actual [`column`](./columns) objects that are generated within the table instance. Column defs are the single most important part of building a table. They are responsible for: - Building the underlying data model that will be used for everything including sorting, filtering, grouping, etc. - Formatting the data model into what will be displayed in the table -- Creating [header groups](../../../api/core/header-group), [headers](../../../api/core/header) and [footers](../../../api/core/column-def#footer) +- Creating [header groups](../api/core/header-group), [headers](../api/core/header) and [footers](../api/core/column-def#footer) - Creating columns for display-only purposes, eg. action buttons, checkboxes, expanders, sparklines, etc. ## Column Def Types @@ -276,7 +276,7 @@ columnHelper.accessor('firstName', { ## Aggregated Cell Formatting -For more info on aggregated cells, see [grouping](../grouping). +For more info on aggregated cells, see [grouping](./grouping). ## Header & Footer Formatting diff --git a/docs/guide/column-faceting.md b/docs/guide/column-faceting.md index f6ec1c94a6..662993a13b 100644 --- a/docs/guide/column-faceting.md +++ b/docs/guide/column-faceting.md @@ -6,11 +6,11 @@ title: Column Faceting Guide Want to skip to the implementation? Check out these examples: -- [filters-faceted](../../framework/react/examples/filters-faceted) +- [filters-faceted](../framework/react/examples/filters-faceted) ## API -[Column Faceting API](../../api/features/column-faceting) +[Column Faceting API](../api/features/column-faceting) ## Column Faceting Guide diff --git a/docs/guide/column-filtering.md b/docs/guide/column-filtering.md index bce1395afb..a0e07d89b7 100644 --- a/docs/guide/column-filtering.md +++ b/docs/guide/column-filtering.md @@ -6,18 +6,18 @@ title: Column Filtering Guide Want to skip to the implementation? Check out these examples: -- [Column Filters](../../framework/react/examples/filters) -- [Faceted Filters](../../framework/react/examples/filters-faceted) (Autocomplete and Range filters) -- [Fuzzy Search](../../framework/react/examples/filters-fuzzy) (Match Sorter) -- [Editable Data](../../framework/react/examples/editable-data) -- [Expanding](../../framework/react/examples/expanding) (Filtering from Sub-Rows) -- [Grouping](../../framework/react/examples/grouping) -- [Pagination](../../framework/react/examples/pagination) -- [Row Selection](../../framework/react/examples/row-selection) +- [Column Filters](../framework/react/examples/filters) +- [Faceted Filters](../framework/react/examples/filters-faceted) (Autocomplete and Range filters) +- [Fuzzy Search](../framework/react/examples/filters-fuzzy) (Match Sorter) +- [Editable Data](../framework/react/examples/editable-data) +- [Expanding](../framework/react/examples/expanding) (Filtering from Sub-Rows) +- [Grouping](../framework/react/examples/grouping) +- [Pagination](../framework/react/examples/pagination) +- [Row Selection](../framework/react/examples/row-selection) ## API -[Column Filtering API](../../api/features/column-filtering) +[Column Filtering API](../api/features/column-filtering) ## Column Filtering Guide @@ -31,7 +31,7 @@ TanStack table supports both client-side and manual server-side filtering. This If you have a large dataset, you may not want to load all of that data into the client's browser in order to filter it. In this case, you will most likely want to implement server-side filtering, sorting, pagination, etc. -However, as also discussed in the [Pagination Guide](../pagination#should-you-use-client-side-pagination), a lot of developers underestimate how many rows can be loaded client-side without a performance hit. The TanStack table examples are often tested to handle up to 100,000 rows or more with decent performance for client-side filtering, sorting, pagination, and grouping. This doesn't necessarily mean that your app will be able to handle that many rows, but if your table is only going to have a few thousand rows at most, you might be able to take advantage of the client-side filtering, sorting, pagination, and grouping that TanStack table provides. +However, as also discussed in the [Pagination Guide](./pagination#should-you-use-client-side-pagination), a lot of developers underestimate how many rows can be loaded client-side without a performance hit. The TanStack table examples are often tested to handle up to 100,000 rows or more with decent performance for client-side filtering, sorting, pagination, and grouping. This doesn't necessarily mean that your app will be able to handle that many rows, but if your table is only going to have a few thousand rows at most, you might be able to take advantage of the client-side filtering, sorting, pagination, and grouping that TanStack table provides. > TanStack Table can handle thousands of client-side rows with good performance. Don't rule out client-side filtering, pagination, sorting, etc. without some thought first. diff --git a/docs/guide/column-ordering.md b/docs/guide/column-ordering.md index 9c3e9df583..81e220e970 100644 --- a/docs/guide/column-ordering.md +++ b/docs/guide/column-ordering.md @@ -6,12 +6,12 @@ title: Column Ordering Guide Want to skip to the implementation? Check out these examples: -- [column-ordering](../../framework/react/examples/column-ordering) -- [column-dnd](../../framework/react/examples/column-dnd) +- [column-ordering](../framework/react/examples/column-ordering) +- [column-dnd](../framework/react/examples/column-dnd) ## API -[Column Ordering API](../../api/features/column-ordering) +[Column Ordering API](../api/features/column-ordering) ## Column Ordering Guide @@ -21,9 +21,9 @@ By default, columns are ordered in the order they are defined in the `columns` a There are 3 table features that can reorder columns, which happen in the following order: -1. [Column Pinning](../column-pinning) - If pinning, columns are split into left, center (unpinned), and right pinned columns. +1. [Column Pinning](./column-pinning) - If pinning, columns are split into left, center (unpinned), and right pinned columns. 2. Manual **Column Ordering** - A manually specified column order is applied. -3. [Grouping](../grouping) - If grouping is enabled, a grouping state is active, and `tableOptions.groupedColumnMode` is set to `'reorder' | 'remove'`, then the grouped columns are reordered to the start of the column flow. +3. [Grouping](./grouping) - If grouping is enabled, a grouping state is active, and `tableOptions.groupedColumnMode` is set to `'reorder' | 'remove'`, then the grouped columns are reordered to the start of the column flow. > **Note:** `columnOrder` state will only affect unpinned columns if used in conjunction with column pinning. @@ -104,7 +104,7 @@ There are undoubtedly many ways to implement drag and drop features along-side T 1. Do NOT try to use [`"react-dnd"`](https://react-dnd.github.io/react-dnd/docs/overview) _if you are using React 18 or newer_. React DnD was an important library for its time, but it now does not get updated very often, and it has incompatibilities with React 18, especially in React Strict Mode. It is still possible to get it to work, but there are newer alternatives that have better compatibility and are more actively maintained. React DnD's Provider may also interfere and conflict with any other DnD solutions you may want to try in your app. -2. Use [`"@dnd-kit/core"`](https://dndkit.com/). DnD Kit is a modern, modular and lightweight drag and drop library that is highly compatible with the modern React ecosystem, and it works well with semantic `` markup. Both of the official TanStack DnD examples, [Column DnD](../../framework/react/examples/column-dnd) and [Row DnD](../../framework/react/examples/row-dnd), now use DnD Kit. +2. Use [`"@dnd-kit/core"`](https://dndkit.com/). DnD Kit is a modern, modular and lightweight drag and drop library that is highly compatible with the modern React ecosystem, and it works well with semantic `
` markup. Both of the official TanStack DnD examples, [Column DnD](../framework/react/examples/column-dnd) and [Row DnD](../framework/react/examples/row-dnd), now use DnD Kit. 3. Consider other DnD libraries like [`"react-beautiful-dnd"`](https://github.com/atlassian/react-beautiful-dnd), but be aware of their potentially large bundle sizes, maintenance status, and compatibility with `
` markup. diff --git a/docs/guide/column-pinning.md b/docs/guide/column-pinning.md index 2236fc827a..95eea231cb 100644 --- a/docs/guide/column-pinning.md +++ b/docs/guide/column-pinning.md @@ -6,17 +6,17 @@ title: Column Pinning Guide Want to skip to the implementation? Check out these examples: -- [column-pinning](../../framework/react/examples/column-pinning) -- [sticky-column-pinning](../../framework/react/examples/column-pinning-sticky) +- [column-pinning](../framework/react/examples/column-pinning) +- [sticky-column-pinning](../framework/react/examples/column-pinning-sticky) ### Other Examples -- [Svelte column-pinning](../../framework/svelte/examples/column-pinning) -- [Vue column-pinning](../../framework/vue/examples/column-pinning) +- [Svelte column-pinning](../framework/svelte/examples/column-pinning) +- [Vue column-pinning](../framework/vue/examples/column-pinning) ## API -[Column Pinning API](../../api/features/column-pinning) +[Column Pinning API](../api/features/column-pinning) ## Column Pinning Guide @@ -27,8 +27,8 @@ TanStack Table offers state and APIs helpful for implementing column pinning fea There are 3 table features that can reorder columns, which happen in the following order: 1. **Column Pinning** - If pinning, columns are split into left, center (unpinned), and right pinned columns. -2. Manual [Column Ordering](../column-ordering) - A manually specified column order is applied. -3. [Grouping](../grouping) - If grouping is enabled, a grouping state is active, and `tableOptions.groupedColumnMode` is set to `'reorder' | 'remove'`, then the grouped columns are reordered to the start of the column flow. +2. Manual [Column Ordering](./column-ordering) - A manually specified column order is applied. +3. [Grouping](./grouping) - If grouping is enabled, a grouping state is active, and `tableOptions.groupedColumnMode` is set to `'reorder' | 'remove'`, then the grouped columns are reordered to the start of the column flow. The only way to change the order of the pinned columns is in the `columnPinning.left` and `columnPinning.right` state itself. `columnOrder` state will only affect the order of the unpinned ("center") columns. @@ -77,13 +77,13 @@ const table = useTable({ There are a handful of useful Column API methods to help you implement column pinning features: -- [`column.getCanPin`](../../api/features/column-pinning#getcanpin): Use to determine if a column can be pinned. -- [`column.pin`](../../api/features/column-pinning#pin): Use to pin a column to the left or right. Or use to unpin a column. -- [`column.getIsPinned`](../../api/features/column-pinning#getispinned): Use to determine where a column is pinned. -- [`column.getStart`](../../api/features/column-pinning#getstart): Use to provide the correct `left` CSS value for a pinned column. -- [`column.getAfter`](../../api/features/column-pinning#getafter): Use to provide the correct `right` CSS value for a pinned column. -- [`column.getIsLastColumn`](../../api/features/column-pinning#getislastcolumn): Use to determine if a column is the last column in its pinned group. Useful for adding a box-shadow -- [`column.getIsFirstColumn`](../../api/features/column-pinning#getisfirstcolumn): Use to determine if a column is the first column in its pinned group. Useful for adding a box-shadow +- [`column.getCanPin`](../api/features/column-pinning#getcanpin): Use to determine if a column can be pinned. +- [`column.pin`](../api/features/column-pinning#pin): Use to pin a column to the left or right. Or use to unpin a column. +- [`column.getIsPinned`](../api/features/column-pinning#getispinned): Use to determine where a column is pinned. +- [`column.getStart`](../api/features/column-pinning#getstart): Use to provide the correct `left` CSS value for a pinned column. +- [`column.getAfter`](../api/features/column-pinning#getafter): Use to provide the correct `right` CSS value for a pinned column. +- [`column.getIsLastColumn`](../api/features/column-pinning#getislastcolumn): Use to determine if a column is the last column in its pinned group. Useful for adding a box-shadow +- [`column.getIsFirstColumn`](../api/features/column-pinning#getisfirstcolumn): Use to determine if a column is the first column in its pinned group. Useful for adding a box-shadow ### Split Table Column Pinning diff --git a/docs/guide/column-sizing.md b/docs/guide/column-sizing.md index 46e304e908..5e6d05f940 100644 --- a/docs/guide/column-sizing.md +++ b/docs/guide/column-sizing.md @@ -6,12 +6,12 @@ title: Column Sizing Guide Want to skip to the implementation? Check out these examples: -- [column-sizing](../../framework/react/examples/column-sizing) -- [column-resizing-performant](../../framework/react/examples/column-resizing-performant) +- [column-sizing](../framework/react/examples/column-sizing) +- [column-resizing-performant](../framework/react/examples/column-resizing-performant) ## API -[Column Sizing API](../../api/features/column-sizing) +[Column Sizing API](../api/features/column-sizing) ## Column Sizing Guide @@ -166,7 +166,7 @@ TanStack Table keeps track of an state object called `columnSizingInfo` that you If you are creating large or complex tables (and using React šŸ˜‰), you may find that if you do not add proper memoization to your render logic, your users may experience degraded performance while resizing columns. -We have created a [performant column resizing example](../../framework/react/examples/column-resizing-performant) that demonstrates how to achieve 60 fps column resizing renders with a complex table that may otherwise have slow renders. It is recommended that you just look at that example to see how it is done, but these are the basic things to keep in mind: +We have created a [performant column resizing example](../framework/react/examples/column-resizing-performant) that demonstrates how to achieve 60 fps column resizing renders with a complex table that may otherwise have slow renders. It is recommended that you just look at that example to see how it is done, but these are the basic things to keep in mind: 1. Don't use `column.getSize()` on every header and every data cell. Instead, calculate all column widths once upfront, **memoized**! 2. Memoize your Table Body while resizing is in progress. diff --git a/docs/guide/column-visibility.md b/docs/guide/column-visibility.md index d4e3a06ff9..1f635ba39b 100644 --- a/docs/guide/column-visibility.md +++ b/docs/guide/column-visibility.md @@ -6,18 +6,18 @@ title: Column Visibility Guide Want to skip to the implementation? Check out these examples: -- [column-visibility](../../framework/react/examples/column-visibility) -- [column-ordering](../../framework/react/examples/column-ordering) -- [sticky-column-pinning](../../framework/react/examples/column-pinning-sticky) +- [column-visibility](../framework/react/examples/column-visibility) +- [column-ordering](../framework/react/examples/column-ordering) +- [sticky-column-pinning](../framework/react/examples/column-pinning-sticky) ### Other Examples -- [SolidJS column-visibility](../../framework/solid/examples/column-visibility) -- [Svelte column-visibility](../../framework/svelte/examples/column-visibility) +- [SolidJS column-visibility](../framework/solid/examples/column-visibility) +- [Svelte column-visibility](../framework/svelte/examples/column-visibility) ## API -[Column Visibility API](../../api/features/column-visibility) +[Column Visibility API](../api/features/column-visibility) ## Column Visibility Guide diff --git a/docs/guide/columns.md b/docs/guide/columns.md index b2242d6f8b..d446c3dc27 100644 --- a/docs/guide/columns.md +++ b/docs/guide/columns.md @@ -4,11 +4,11 @@ title: Columns Guide ## API -[Column API](../../api/core/column) +[Column API](../api/core/column) ## Columns Guide -> Note: This guide is about the actual `column` objects that are generated within the table instance and NOT about setting up the [column definitions](../column-defs) for your table. +> Note: This guide is about the actual `column` objects that are generated within the table instance and NOT about setting up the [column definitions](./column-defs) for your table. This quick guide will discuss the different ways you can retrieve and interact with `column` objects in TanStack Table. @@ -18,7 +18,7 @@ You can find the `column` objects in many places. They are often attached #### Header and Cell Objects -Before you reach for one of the `table` instance APIs, consider if you actually need to retrieve either [headers](../headers) or [cells](../cells) instead of `columns`. If you are rending out the markup for your table, you will most likely want to reach for the APIs that return headers or cells instead of columns. The column objects themselves are not really meant to render out the headers or cells, but the `header` and `cell` objects will contain references to these `column` objects from which they can derive the necessary information to render their UI. +Before you reach for one of the `table` instance APIs, consider if you actually need to retrieve either [headers](./headers) or [cells](./cells) instead of `columns`. If you are rending out the markup for your table, you will most likely want to reach for the APIs that return headers or cells instead of columns. The column objects themselves are not really meant to render out the headers or cells, but the `header` and `cell` objects will contain references to these `column` objects from which they can derive the necessary information to render their UI. ```js const column = cell.column; // get column from cell @@ -47,7 +47,7 @@ Column objects are not actually meant to be used to render out the table UI dire #### Column IDs -Every column must have a unique `id` defined in their associated [Column Definition](../column-defs). Usually, you define this `id` yourself, or it is derived from the `accessorKey` or `header` properties in the column definition. +Every column must have a unique `id` defined in their associated [Column Definition](./column-defs). Usually, you define this `id` yourself, or it is derived from the `accessorKey` or `header` properties in the column definition. #### ColumnDef @@ -67,6 +67,6 @@ There are dozens of Column APIs that you can use to interact with the table stat ### Column Rendering -Don't necessarily use `column` objects to render `headers` or `cells` directly. Instead, use the [`header`](../headers) and [`cell`](../cells) objects, as discussed above. +Don't necessarily use `column` objects to render `headers` or `cells` directly. Instead, use the [`header`](./headers) and [`cell`](./cells) objects, as discussed above. But if you are just rendering a list of columns somewhere else in your UI for something like a column visibility menu or something similar, you can just map over a columns array and render out the UI as you normally would. diff --git a/docs/guide/custom-features.md b/docs/guide/custom-features.md index 06ff0490d3..89ad1e6dbb 100644 --- a/docs/guide/custom-features.md +++ b/docs/guide/custom-features.md @@ -6,7 +6,7 @@ title: Custom Features Guide Want to skip to the implementation? Check out these examples: -- [custom-features](../../framework/react/examples/custom-features) +- [custom-features](../framework/react/examples/custom-features) ## Custom Features Guide @@ -108,7 +108,7 @@ The `constructCell` method in a table feature is responsible for adding methods Let's walk through making a custom table feature for a hypothetical use case. Let's say we want to add a feature to the table instance that allows the user to change the "density" (padding of cells) of the table. -Check out the full [custom-features](../../framework/react/examples/custom-features) example to see the full implementation, but here's an in-depth look at the steps to create a custom feature. +Check out the full [custom-features](../framework/react/examples/custom-features) example to see the full implementation, but here's an in-depth look at the steps to create a custom feature. #### Step 1: Set up TypeScript Types diff --git a/docs/guide/data.md b/docs/guide/data.md index df47291093..29f193b8c3 100644 --- a/docs/guide/data.md +++ b/docs/guide/data.md @@ -133,7 +133,7 @@ const columns = [ ] ``` -This is discussed in more detail in the [Column Def Guide](../column-defs). +This is discussed in more detail in the [Column Def Guide](./column-defs). > NOTE: The "keys" in your json data can usually be anything, but any periods in the keys will be interpreted as a deep key and will cause errors. @@ -179,7 +179,7 @@ type User = { } ``` -Where `subRows` is an optional array of `User` objects. This is discussed in more detail in the [Expanding Guide](../expanding). +Where `subRows` is an optional array of `User` objects. This is discussed in more detail in the [Expanding Guide](./expanding). ### Give Data a "Stable" Reference @@ -239,7 +239,7 @@ export default function MyComponent() { ### How TanStack Table Transforms Data -Later, in other parts of these docs, you will see how TanStack Table processes the `data` that you pass to the table and generates the row and cell objects that are used to create the table. The `data` that you pass to the table is never mutated by TanStack Table, but the actual values in the rows and cells may be transformed by the accessors in your column definitions, or by other features performed by [row models](../row-models) like grouping or aggregation. +Later, in other parts of these docs, you will see how TanStack Table processes the `data` that you pass to the table and generates the row and cell objects that are used to create the table. The `data` that you pass to the table is never mutated by TanStack Table, but the actual values in the rows and cells may be transformed by the accessors in your column definitions, or by other features performed by [row models](./row-models) like grouping or aggregation. ### How Much Data Can TanStack Table Handle? @@ -247,4 +247,4 @@ Believe it or not, TanStack Table was actually built to scale up to handle poten The default mindset of a developer building a data grid is to implement server-side pagination, sorting, and filtering for large datasets. This is still usually a good idea, but a lot of developers underestimate how much data can actually be handled in the client with modern browsers and the right optimizations. If your table will never have more than a few thousand rows, you can probably take advantage of the client-side features in TanStack Table instead of implementing them yourself on the server. Before committing to letting TanStack Table's client-side features handle your large dataset, you should test it with your actual data to see if it performs well enough for your needs, of course. -This is discussed in more detail in the [Pagination Guide](../pagination#should-you-use-client-side-pagination). +This is discussed in more detail in the [Pagination Guide](./pagination#should-you-use-client-side-pagination). diff --git a/docs/guide/expanding.md b/docs/guide/expanding.md index 8ca11daaf9..6088251ec9 100644 --- a/docs/guide/expanding.md +++ b/docs/guide/expanding.md @@ -6,13 +6,13 @@ title: Expanding Guide Want to skip to the implementation? Check out these examples: -- [expanding](../../framework/react/examples/expanding) -- [grouping](../../framework/react/examples/grouping) -- [sub-components](../../framework/react/examples/sub-components) +- [expanding](../framework/react/examples/expanding) +- [grouping](../framework/react/examples/grouping) +- [sub-components](../framework/react/examples/sub-components) ## API -[Expanding API](../../api/features/expanding) +[Expanding API](../api/features/expanding) ## Expanding Feature Guide diff --git a/docs/guide/features.md b/docs/guide/features.md index 83d961c5b5..cc90fa3876 100644 --- a/docs/guide/features.md +++ b/docs/guide/features.md @@ -4,18 +4,18 @@ title: Features Guide TanStack Table comes with many features, each with their own associated options and API: -- [Column Ordering](../column-ordering) -- [Column Pinning](../column-pinning) -- [Column Sizing](../column-sizing) -- [Column Visibility](../column-visibility) -- [Expanding](../expanding) -- [Column Faceting](../column-faceting) -- [Column Filtering](../column-filtering) -- [Global Faceting](../global-faceting) -- [Global Filtering](../global-filtering) -- [Grouping](../grouping) -- [Pagination](../pagination) -- [Row Pinning](../row-pinning) -- [Row Selection](../row-selection) -- [Sorting](../sorting) -- [Virtualization](../virtualization) \ No newline at end of file +- [Column Ordering](./column-ordering) +- [Column Pinning](./column-pinning) +- [Column Sizing](./column-sizing) +- [Column Visibility](./column-visibility) +- [Expanding](./expanding) +- [Column Faceting](./column-faceting) +- [Column Filtering](./column-filtering) +- [Global Faceting](./global-faceting) +- [Global Filtering](./global-filtering) +- [Grouping](./grouping) +- [Pagination](./pagination) +- [Row Pinning](./row-pinning) +- [Row Selection](./row-selection) +- [Sorting](./sorting) +- [Virtualization](./virtualization) \ No newline at end of file diff --git a/docs/guide/filters.md b/docs/guide/filters.md index 1a5dfe5211..8d10bda84e 100644 --- a/docs/guide/filters.md +++ b/docs/guide/filters.md @@ -6,8 +6,8 @@ title: Filters Guide The filter guides are now split into multiple guides: -- [Column Filtering](../column-filtering) -- [Global Filtering](../global-filtering) -- [Fuzzy Filtering](../fuzzy-filtering) -- [Column Faceting](../column-faceting) -- [Global Faceting](../global-faceting) \ No newline at end of file +- [Column Filtering](./column-filtering) +- [Global Filtering](./global-filtering) +- [Fuzzy Filtering](./fuzzy-filtering) +- [Column Faceting](./column-faceting) +- [Global Faceting](./global-faceting) \ No newline at end of file diff --git a/docs/guide/fuzzy-filtering.md b/docs/guide/fuzzy-filtering.md index 602c55c543..a6c32a7791 100644 --- a/docs/guide/fuzzy-filtering.md +++ b/docs/guide/fuzzy-filtering.md @@ -6,11 +6,11 @@ title: Fuzzy Filtering Guide Want to skip to the implementation? Check out these examples: -- [filters-fuzzy](../../framework/react/examples/filters-fuzzy) +- [filters-fuzzy](../framework/react/examples/filters-fuzzy) ## API -[Filters API](../../api/features/filters) +[Filters API](../api/features/filters) ## Fuzzy Filtering Guide diff --git a/docs/guide/global-faceting.md b/docs/guide/global-faceting.md index 708d2d53f4..76a531a98d 100644 --- a/docs/guide/global-faceting.md +++ b/docs/guide/global-faceting.md @@ -6,11 +6,11 @@ title: Global Faceting Guide Want to skip to the implementation? Check out these examples: -- [filters-faceted](../../framework/react/examples/filters) +- [filters-faceted](../framework/react/examples/filters) ## API -[Global Faceting API](../../api/features/global-faceting) +[Global Faceting API](../api/features/global-faceting) ## Global Faceting Guide diff --git a/docs/guide/global-filtering.md b/docs/guide/global-filtering.md index c49277be9d..41a1004090 100644 --- a/docs/guide/global-filtering.md +++ b/docs/guide/global-filtering.md @@ -6,11 +6,11 @@ title: Global Filtering Guide Want to skip to the implementation? Check out these examples: -- [Global Filters](../../framework/react/examples/filters-global) +- [Global Filters](../framework/react/examples/filters-global) ## API -[Global Filtering API](../../api/features/global-filtering) +[Global Filtering API](../api/features/global-filtering) ## Global Filtering Guide @@ -22,7 +22,7 @@ This guide will focus on global filtering, which is a filter that is applied acr If you have a large dataset, you may not want to load all of that data into the client's browser in order to filter it. In this case, you will most likely want to implement server-side filtering, sorting, pagination, etc. -However, as also discussed in the [Pagination Guide](../pagination#should-you-use-client-side-pagination), a lot of developers underestimate how many rows can be loaded client-side without a performance hit. The TanStack table examples are often tested to handle up to 100,000 rows or more with decent performance for client-side filtering, sorting, pagination, and grouping. This doesn't necessarily mean that your app will be able to handle that many rows, but if your table is only going to have a few thousand rows at most, you might be able to take advantage of the client-side filtering, sorting, pagination, and grouping that TanStack table provides. +However, as also discussed in the [Pagination Guide](./pagination#should-you-use-client-side-pagination), a lot of developers underestimate how many rows can be loaded client-side without a performance hit. The TanStack table examples are often tested to handle up to 100,000 rows or more with decent performance for client-side filtering, sorting, pagination, and grouping. This doesn't necessarily mean that your app will be able to handle that many rows, but if your table is only going to have a few thousand rows at most, you might be able to take advantage of the client-side filtering, sorting, pagination, and grouping that TanStack table provides. > TanStack Table can handle thousands of client-side rows with good performance. Don't rule out client-side filtering, pagination, sorting, etc. without some thought first. diff --git a/docs/guide/grouping.md b/docs/guide/grouping.md index 0bae282711..a69014708c 100644 --- a/docs/guide/grouping.md +++ b/docs/guide/grouping.md @@ -6,18 +6,18 @@ title: Grouping Guide Want to skip to the implementation? Check out these examples: -- [grouping](../../framework/react/examples/grouping) +- [grouping](../framework/react/examples/grouping) ## API -[Grouping API](../../api/features/grouping) +[Grouping API](../api/features/grouping) ## Grouping Guide There are 3 table features that can reorder columns, which happen in the following order: -1. [Column Pinning](../column-pinning) - If pinning, columns are split into left, center (unpinned), and right pinned columns. -2. Manual [Column Ordering](../column-ordering) - A manually specified column order is applied. +1. [Column Pinning](./column-pinning) - If pinning, columns are split into left, center (unpinned), and right pinned columns. +2. Manual [Column Ordering](./column-ordering) - A manually specified column order is applied. 3. **Grouping** - If grouping is enabled, a grouping state is active, and `tableOptions.groupedColumnMode` is set to `'reorder' | 'remove'`, then the grouped columns are reordered to the start of the column flow. Grouping in TanStack table is a feature that applies to columns and allows you to categorize and organize the table rows based on specific columns. This can be useful in cases where you have a large amount of data and you want to group them together based on certain criteria. diff --git a/docs/guide/header-groups.md b/docs/guide/header-groups.md index 0ea1754cf2..f98a0ff0d0 100644 --- a/docs/guide/header-groups.md +++ b/docs/guide/header-groups.md @@ -4,7 +4,7 @@ title: Header Groups Guide ## API -[Header Group API](../../api/core/header-group) +[Header Group API](../api/core/header-group) ## Header Groups Guide @@ -12,7 +12,7 @@ This quick guide will discuss the different ways you can retrieve and interact w ### What are Header Groups? -Header Groups are simply "rows" of headers. Don't let the name confuse you, it's just that simple. The large majority of tables will only have one row of headers (a single header group), but if you define your column structure with nested columns as with the [Column Groups example](../../framework/react/examples/column-groups), you can have multiple rows of headers (multiple header groups). +Header Groups are simply "rows" of headers. Don't let the name confuse you, it's just that simple. The large majority of tables will only have one row of headers (a single header group), but if you define your column structure with nested columns as with the [Column Groups example](../framework/react/examples/column-groups), you can have multiple rows of headers (multiple header groups). ### Where to Get Header Groups From @@ -20,13 +20,13 @@ There are multiple `table` instance APIs you can use to retrieve header groups f ### Header Group Objects -Header Group objects are similar to [Row](../rows) objects, though simpler since there is not as much going on in header rows as there are in the body rows. +Header Group objects are similar to [Row](./rows) objects, though simpler since there is not as much going on in header rows as there are in the body rows. By default, header groups only have three properties: - `id`: The unique identifier for the header group that is generated from its depth (index). This is useful as a key for React components. - `depth`: The depth of the header group, zero-indexed based. Think of this as the row index amongst all header rows. -- `headers`: An array of [Header](../headers) cell objects that belong to this header group (row). +- `headers`: An array of [Header](./headers) cell objects that belong to this header group (row). ### Access Header Cells diff --git a/docs/guide/headers.md b/docs/guide/headers.md index 97623c908c..9760568865 100644 --- a/docs/guide/headers.md +++ b/docs/guide/headers.md @@ -4,7 +4,7 @@ title: Headers Guide ## API -[Header API](../../api/core/header) +[Header API](../api/core/header) ## Headers Guide @@ -14,7 +14,7 @@ Headers are the equivalent of cells, but meant for the `` section of the ### Where to Get Headers From -Headers come from [Header Groups](../header-groups), which are the equivalent of rows, but meant for the `` section of the table instead of the `` section. +Headers come from [Header Groups](./header-groups), which are the equivalent of rows, but meant for the `` section of the table instead of the `` section. #### HeaderGroup Headers @@ -42,11 +42,11 @@ There are multiple `table` instance APIs that you can use to retrieve a list of ### Header Objects -Header objects are similar to [Cell](../cells) objects, but meant for the `` section of the table instead of the `` section. Every header object can be associated with a `` section of the table instead of the `` section. Every header object can be associated with a `
` or similar cell element in your UI. There are a few properties and methods on `header` objects that you can use to interact with the table state and extract cell values from the table based on the state of the table. +Header objects are similar to [Cell](./cells) objects, but meant for the `
` or similar cell element in your UI. There are a few properties and methods on `header` objects that you can use to interact with the table state and extract cell values from the table based on the state of the table. #### Header IDs -Every header object has an `id` property that makes it unique within the table instance. Usually you only need this `id` as a unique identifier for React keys or if you are following the [performant column resizing example](../../framework/react/examples/column-resizing-performant). +Every header object has an `id` property that makes it unique within the table instance. Usually you only need this `id` as a unique identifier for React keys or if you are following the [performant column resizing example](../framework/react/examples/column-resizing-performant). For simple headers with no advanced nested or grouped headers logic, the `header.id` will be the same as it's parent `column.id`. However, if the header is part group column or a placeholder cell, it will have a more complicated id that is constructed from the header family, depth/header row index, column id, and header group id. @@ -65,11 +65,11 @@ There are a few properties on `header` objects that are only useful if the heade #### Header Parent Objects -Every header stores a reference to its parent [column](../columns) object and its parent [header group](../header-groups) object. +Every header stores a reference to its parent [column](./columns) object and its parent [header group](./header-groups) object. ### More Header APIs -Headers have a few more useful APIs attached to them that are useful for interacting with the table state. Most of them relate to the Column sizing and resizing features. See the [Column Resizing Guide](../column-resizing) for more information. +Headers have a few more useful APIs attached to them that are useful for interacting with the table state. Most of them relate to the Column sizing and resizing features. See the [Column Resizing Guide](./column-resizing) for more information. ### Header Rendering diff --git a/docs/guide/pagination.md b/docs/guide/pagination.md index e5f932d94d..9cabdb0544 100644 --- a/docs/guide/pagination.md +++ b/docs/guide/pagination.md @@ -6,17 +6,17 @@ title: Pagination Guide Want to skip to the implementation? Check out these examples: -- [pagination](../../framework/react/examples/pagination) -- [pagination-controlled (React Query)](../../framework/react/examples/pagination-controlled) -- [editable-data](../../framework/react/examples/editable-data) -- [expanding](../../framework/react/examples/expanding) -- [filters](../../framework/react/examples/filters) -- [fully-controlled](../../framework/react/examples/fully-controlled) -- [row-selection](../../framework/react/examples/row-selection) +- [pagination](../framework/react/examples/pagination) +- [pagination-controlled (React Query)](../framework/react/examples/pagination-controlled) +- [editable-data](../framework/react/examples/editable-data) +- [expanding](../framework/react/examples/expanding) +- [filters](../framework/react/examples/filters) +- [fully-controlled](../framework/react/examples/fully-controlled) +- [row-selection](../framework/react/examples/row-selection) ## API -[Pagination API](../../api/features/pagination) +[Pagination API](../api/features/pagination) ## Pagination Guide @@ -30,7 +30,7 @@ Using client-side pagination means that the `data` that you fetch will contain * Client-side pagination is usually the simplest way to implement pagination when using TanStack Table, but it might not be practical for very large datasets. -However, a lot of people underestimate just how much data can be handled client-side. If your table will only ever have a few thousand rows or less, client-side pagination can still be a viable option. TanStack Table is designed to scale up to 10s of thousands of rows with decent performance for pagination, filtering, sorting, and grouping. The [official pagination example](../../framework/react/examples/pagination) loads 100,000 rows and still performs well, albeit with only handful of columns. +However, a lot of people underestimate just how much data can be handled client-side. If your table will only ever have a few thousand rows or less, client-side pagination can still be a viable option. TanStack Table is designed to scale up to 10s of thousands of rows with decent performance for pagination, filtering, sorting, and grouping. The [official pagination example](../framework/react/examples/pagination) loads 100,000 rows and still performs well, albeit with only handful of columns. Every use-case is different and will depend on the complexity of the table, how many columns you have, how large every piece of data is, etc. The main bottlenecks to pay attention to are: diff --git a/docs/guide/pinning.md b/docs/guide/pinning.md index c8951f9695..aa8c116291 100644 --- a/docs/guide/pinning.md +++ b/docs/guide/pinning.md @@ -6,5 +6,5 @@ title: Pinning Guide Pinning is split into 2 different feature guides: -- [Column Pinning](../column-pinning) -- [Row Pinning](../row-pinning) \ No newline at end of file +- [Column Pinning](./column-pinning) +- [Row Pinning](./row-pinning) \ No newline at end of file diff --git a/docs/guide/row-pinning.md b/docs/guide/row-pinning.md index e5ee91921b..bc497a3abb 100644 --- a/docs/guide/row-pinning.md +++ b/docs/guide/row-pinning.md @@ -6,15 +6,15 @@ title: Row Pinning Guide Want to skip to the implementation? Check out these examples: -- [row-pinning](../../framework/react/examples/row-pinning) +- [row-pinning](../framework/react/examples/row-pinning) ## API -[Row Pinning API](../../api/features/row-pinning) +[Row Pinning API](../api/features/row-pinning) ## Row Pinning Guide There are 2 table features that can reorder rows, which happen in the following order: 1. **Row Pinning** - If pinning, rows are split into top, center (unpinned), and bottom pinned rows. -2. [Sorting](../sorting) \ No newline at end of file +2. [Sorting](./sorting) \ No newline at end of file diff --git a/docs/guide/row-selection.md b/docs/guide/row-selection.md index 25da7e38d6..cd29793f69 100644 --- a/docs/guide/row-selection.md +++ b/docs/guide/row-selection.md @@ -6,13 +6,13 @@ title: Row Selection Guide Want to skip to the implementation? Check out these examples: -- [React row-selection](../../framework/react/examples/row-selection) -- [Vue row-selection](../../framework/vue/row-selection) -- [React expanding](../../framework/react/examples/expanding) +- [React row-selection](../framework/react/examples/row-selection) +- [Vue row-selection](../framework/vue/row-selection) +- [React expanding](../framework/react/examples/expanding) ## API -[Row Selection API](../../api/features/row-selection) +[Row Selection API](../api/features/row-selection) ## Row Selection Guide diff --git a/docs/guide/rows.md b/docs/guide/rows.md index 1616e842bb..3db467f1d0 100644 --- a/docs/guide/rows.md +++ b/docs/guide/rows.md @@ -4,7 +4,7 @@ title: Rows Guide ## API -[Row API](../../api/core/row) +[Row API](../api/core/row) ## Rows Guide @@ -24,7 +24,7 @@ const row = table.getRow(rowId) #### Row Models -The `table` instance generates `row` objects and stores them in useful arrays called ["Row Models"](../row-models). This is discussed in much more detail in the [Row Models Guide](../row-models), but here are the most common ways you may access the row models. +The `table` instance generates `row` objects and stores them in useful arrays called ["Row Models"](./row-models). This is discussed in much more detail in the [Row Models Guide](./row-models), but here are the most common ways you may access the row models. ##### Render Rows @@ -85,7 +85,7 @@ const firstName = row.original.firstName // { firstName: 'John', lastName: 'Doe' ### Sub Rows -If you are using either grouping or expanding features, your rows may contain sub-rows or parent row references. This is discussed in much more detail in the [Expanding Guide](../expanding), but here is a quick overview of useful properties and methods for working with sub-rows. +If you are using either grouping or expanding features, your rows may contain sub-rows or parent row references. This is discussed in much more detail in the [Expanding Guide](./expanding), but here is a quick overview of useful properties and methods for working with sub-rows. - `row.subRows`: An array of sub-rows for the row. - `row.depth`: The depth of the row (if nested or grouped) relative to the root row array. 0 for root level rows, 1 for child rows, 2 for grandchild rows, etc. diff --git a/docs/guide/sorting.md b/docs/guide/sorting.md index 55c8b44373..935db42b09 100644 --- a/docs/guide/sorting.md +++ b/docs/guide/sorting.md @@ -6,12 +6,12 @@ title: Sorting Guide Want to skip to the implementation? Check out these examples: -- [sorting](../../framework/react/examples/sorting) -- [filters](../../framework/react/examples/filters) +- [sorting](../framework/react/examples/sorting) +- [filters](../framework/react/examples/filters) ## API -[Sorting API](../../api/features/sorting) +[Sorting API](../api/features/sorting) ## Sorting Guide diff --git a/docs/guide/tables.md b/docs/guide/tables.md index bf8618c331..efab6664f7 100644 --- a/docs/guide/tables.md +++ b/docs/guide/tables.md @@ -4,7 +4,7 @@ title: Table Instance Guide ## API -[Table API](../../api/core/table) +[Table API](../api/core/table) ## Table Instance Guide @@ -18,11 +18,11 @@ To create a table instance, 3 `options` are required: `columns`, `data`, and a ` #### Defining Data -Define your data as an array of objects with a stable reference. `data` can come from anywhere like an API response or defined statically in your code, but it must have a stable reference to prevent infinite re-renders. If using TypeScript, the type that you give your data will be used as a `TData` generic. See the [Data Guide](../data) for more info. +Define your data as an array of objects with a stable reference. `data` can come from anywhere like an API response or defined statically in your code, but it must have a stable reference to prevent infinite re-renders. If using TypeScript, the type that you give your data will be used as a `TData` generic. See the [Data Guide](./data) for more info. #### Defining Columns -Column definitions are covered in detail in the previous section in the [Column Def Guide](../column-defs). We'll note here, however, that when you define the type of your columns, you should use the same `TData` type that you used for your data. +Column definitions are covered in detail in the previous section in the [Column Def Guide](./column-defs). We'll note here, however, that when you define the type of your columns, you should use the same `TData` type that you used for your data. ```ts const columns: ColumnDef[] = [] //Pass User type as the generic TData type @@ -30,11 +30,11 @@ const columns: ColumnDef[] = [] //Pass User type as the generic TData type const columnHelper = createColumnHelper() //Pass User type as the generic TData type ``` -The column definitions are where we will tell TanStack Table how each column should access and/or transform row data with either an `accessorKey` or `accessorFn`. See the [Column Def Guide](../column-defs#creating-accessor-columns) for more info. +The column definitions are where we will tell TanStack Table how each column should access and/or transform row data with either an `accessorKey` or `accessorFn`. See the [Column Def Guide](./column-defs#creating-accessor-columns) for more info. #### Passing in Row Models -This is explained in much more detail in the [Row Models Guide](../row-models), but for now, just import the `getCoreRowModel` function from TanStack Table and pass it in as a table option. Depending on the features you plan to use, you may need to pass in additional row models later. +This is explained in much more detail in the [Row Models Guide](./row-models), but for now, just import the `getCoreRowModel` function from TanStack Table and pass it in as a table option. Depending on the features you plan to use, you may need to pass in additional row models later. ```ts import { getCoreRowModel } from '@tanstack/[framework]-table' @@ -83,7 +83,7 @@ table.setRowSelection((old) => ({...old})) //set the row selection state table.resetRowSelection() //reset the row selection state ``` -This is covered in more detail in the [Table State Guides](../../framework/react/guide/table-state) +This is covered in more detail in the [Table State Guides](../framework/react/guide/table-state) ### Table APIs @@ -91,8 +91,8 @@ There are dozens of table APIs created by each feature to help you either read o API reference docs for the core table instance and all other feature APIs can be found throughout the API docs. -For example, you can find the core table instance API docs here: [Table API](../../api/core/table#table-api) +For example, you can find the core table instance API docs here: [Table API](../api/core/table#table-api) ### Table Row Models -There is a special set of table instance APIs for reading rows out of the table instance called row models. TanStack Table has advanced features where the rows that are generated may be very different than the array of `data` that you originally passed in. To learn more about the different row models that you can pass in as a table option, see the [Row Models Guide](../row-models). +There is a special set of table instance APIs for reading rows out of the table instance called row models. TanStack Table has advanced features where the rows that are generated may be very different than the array of `data` that you originally passed in. To learn more about the different row models that you can pass in as a table option, see the [Row Models Guide](./row-models). diff --git a/docs/guide/virtualization.md b/docs/guide/virtualization.md index 3298979908..6adc58c3ae 100644 --- a/docs/guide/virtualization.md +++ b/docs/guide/virtualization.md @@ -6,14 +6,14 @@ title: Virtualization Guide Want to skip to the implementation? Check out these examples: -- [virtualized-columns](../../framework/react/examples/virtualized-columns) -- [virtualized-rows (dynamic row height)](../../framework/react/examples/virtualized-rows) -- [virtualized-rows (fixed row height)](../../../../../virtual/v3/docs/framework/react/examples/table) -- [virtualized-infinite-scrolling](../../framework/react/examples/virtualized-infinite-scrolling) +- [virtualized-columns](../framework/react/examples/virtualized-columns) +- [virtualized-rows (dynamic row height)](../framework/react/examples/virtualized-rows) +- [virtualized-rows (fixed row height)](https://tanstack.com/virtual/latest/docs/framework/react/examples/table) +- [virtualized-infinite-scrolling](../framework/react/examples/virtualized-infinite-scrolling) ## API -[TanStack Virtual Virtualizer API](../../../../../virtual/v3/docs/api/virtualizer) +[TanStack Virtual Virtualizer API](https://tanstack.com/virtual/latest/docs/api/virtualizer) ## Virtualization Guide diff --git a/docs/overview.md b/docs/overview.md index 1b0c25e393..e3026346e9 100644 --- a/docs/overview.md +++ b/docs/overview.md @@ -12,7 +12,7 @@ If you use TypeScript, you will get top-notch type safety and editor autocomplet ## Headless -As it was mentioned extensively in the [Intro](../introduction) section, TanStack Table is **headless**. This means that it doesn't render any DOM elements, and instead relies on you, the UI/UX developer to provide the table's markup and styles. This is a great way to build a table that can be used in any UI framework, including React, Vue, Solid, Svelte, Angular, and even JS-to-native platforms like React Native! +As it was mentioned extensively in the [Intro](./introduction) section, TanStack Table is **headless**. This means that it doesn't render any DOM elements, and instead relies on you, the UI/UX developer to provide the table's markup and styles. This is a great way to build a table that can be used in any UI framework, including React, Vue, Solid, Svelte, Angular, and even JS-to-native platforms like React Native! ## Agnostic @@ -25,39 +25,39 @@ Since TanStack Table is headless and runs on a vanilla JavaScript core, it is ag The table core uses the following abstractions, commonly exposed by adapters: -- [Data](../guide/data) - The core data array you provide the table -- [Column Defs](../guide/column-defs): Objects used to configure a column and its data model, display templates, and more -- [Table Instance](../guide/tables): The core table object containing both state and API -- [Row Models](../guide/row-models): How the `data` array is transformed into useful rows depending on the features you are using -- [Rows](../guide/rows): Each row mirrors its respective row data and provides row-specific APIs -- [Cells](../guide/cells): Each cell mirrors its respective row-column intersection and provides cell-specific APIs -- [Header Groups](../guide/header-groups): Header groups are computed slices of nested header levels, each containing a group of headers -- [Headers](../guide/headers): Each header is either directly associated with or derived from its column def and provides header-specific APIs -- [Columns](../guide/columns): Each column mirrors its respective column def and also provides column-specific APIs +- [Data](./guide/data) - The core data array you provide the table +- [Column Defs](./guide/column-defs): Objects used to configure a column and its data model, display templates, and more +- [Table Instance](./guide/tables): The core table object containing both state and API +- [Row Models](./guide/row-models): How the `data` array is transformed into useful rows depending on the features you are using +- [Rows](./guide/rows): Each row mirrors its respective row data and provides row-specific APIs +- [Cells](./guide/cells): Each cell mirrors its respective row-column intersection and provides cell-specific APIs +- [Header Groups](./guide/header-groups): Header groups are computed slices of nested header levels, each containing a group of headers +- [Headers](./guide/headers): Each header is either directly associated with or derived from its column def and provides header-specific APIs +- [Columns](./guide/columns): Each column mirrors its respective column def and also provides column-specific APIs ## Features TanStack Table will help you build just about any type of table you can imagine. It has built-in state and APIs for the following features: -- [Column Faceting](../guide/column-faceting) - List unique lists of column values or min/max values for a column -- [Column Filtering](../guide/column-filtering) - Filter rows based on search values for a column -- [Column Grouping](../guide/grouping) - Group columns together, run aggregations, and more -- [Column Ordering](../guide/column-ordering) - Dynamically change the order of columns -- [Column Pinning](../guide/column-pinning) - Pin (Freeze) columns to the left or right of the table -- [Column Sizing](../guide/column-sizing) - Dynamically change the size of columns (column resizing handles) -- [Column Visibility](../guide/column-visibility) - Hide/show columns -- [Global Faceting](../guide/global-faceting) - List unique lists of column values or min/max values for the entire table -- [Global Filtering](../guide/global-filtering) - Filter rows based on search values for the entire table -- [Row Expanding](../guide/expanding) - Expand/collapse rows (sub-rows) -- [Row Pagination](../guide/pagination) - Paginate rows -- [Row Pinning](../guide/row-pinning) - Pin (Freeze) rows to the top or bottom of the table -- [Row Selection](../guide/row-selection) - Select/deselect rows (checkboxes) -- [Row Sorting](../guide/sorting) - Sort rows by column values +- [Column Faceting](./guide/column-faceting) - List unique lists of column values or min/max values for a column +- [Column Filtering](./guide/column-filtering) - Filter rows based on search values for a column +- [Column Grouping](./guide/grouping) - Group columns together, run aggregations, and more +- [Column Ordering](./guide/column-ordering) - Dynamically change the order of columns +- [Column Pinning](./guide/column-pinning) - Pin (Freeze) columns to the left or right of the table +- [Column Sizing](./guide/column-sizing) - Dynamically change the size of columns (column resizing handles) +- [Column Visibility](./guide/column-visibility) - Hide/show columns +- [Global Faceting](./guide/global-faceting) - List unique lists of column values or min/max values for the entire table +- [Global Filtering](./guide/global-filtering) - Filter rows based on search values for the entire table +- [Row Expanding](./guide/expanding) - Expand/collapse rows (sub-rows) +- [Row Pagination](./guide/pagination) - Paginate rows +- [Row Pinning](./guide/row-pinning) - Pin (Freeze) rows to the top or bottom of the table +- [Row Selection](./guide/row-selection) - Select/deselect rows (checkboxes) +- [Row Sorting](./guide/sorting) - Sort rows by column values These are just some of the capabilities that you can build with TanStack Table. There are many more features that are possible with TanStack Table that you can add along-side the built-in features. -[Virtualization](../guide/virtualization) is an example of a feature that is not built-in to TanStack Table, but can be achieved by using another library (like [TanStack Virtual](https://tanstack.com/virtual/v3)) and adding it along-side your other table rendering logic. +[Virtualization](./guide/virtualization) is an example of a feature that is not built-in to TanStack Table, but can be achieved by using another library (like [TanStack Virtual](https://tanstack.com/virtual/v3)) and adding it along-side your other table rendering logic. -TanStack Table also supports [Custom Features](../guide/custom-features) (plugins) that you can use to modify the table instance to add your own custom logic to the table in a more integrated way. +TanStack Table also supports [Custom Features](./guide/custom-features) (plugins) that you can use to modify the table instance to add your own custom logic to the table in a more integrated way. And of course, you can just write your own state and hooks to add whatever other features you want for your table. The features from the TanStack Table core are just a solid foundation to build on, with a large focus on performance and DX. diff --git a/eslint.config.js b/eslint.config.js index 86616bef42..d0bcf6bb2f 100644 --- a/eslint.config.js +++ b/eslint.config.js @@ -1,17 +1,13 @@ // @ts-check // @ts-ignore Needed due to moduleResolution Node vs Bundler -import { tanstackConfig } from '@tanstack/config/eslint' -import unusedImports from 'eslint-plugin-unused-imports' +import { tanstackConfig } from '@tanstack/eslint-config' /** @type {any} */ const config = [ ...tanstackConfig, { name: 'tanstack/temp', - plugins: { - 'unused-imports': unusedImports, - }, rules: { 'no-case-declarations': 'off', 'no-shadow': 'off', @@ -19,7 +15,6 @@ const config = [ '@typescript-eslint/no-empty-function': 'off', '@typescript-eslint/no-unnecessary-condition': 'warn', '@typescript-eslint/no-unsafe-function-type': 'off', - 'unused-imports/no-unused-imports': 'warn', }, }, ] diff --git a/nx.json b/nx.json index 2e4fdb7eaa..5f740e3e71 100644 --- a/nx.json +++ b/nx.json @@ -1,9 +1,12 @@ { "$schema": "./node_modules/nx/schemas/nx-schema.json", "defaultBase": "main", - "nxCloudAccessToken": "OWExNzViODMtZjU4Ny00MTRmLTk3ZDYtMGY5YzlkOTRhZDQ2fHJlYWQtb25seQ==", + "nxCloudId": "6435ee4cd7387c45c0e4bf4c", "useInferencePlugins": false, "parallel": 5, + "tui": { + "enabled": false + }, "namedInputs": { "sharedGlobals": [ "{workspaceRoot}/.nvmrc", @@ -57,7 +60,7 @@ }, "test:sherif": { "cache": true, - "inputs": ["{workspaceRoot}/**/*"] + "inputs": ["{workspaceRoot}/**/package.json"] } } } diff --git a/package.json b/package.json index b13224227d..66c8e4e660 100644 --- a/package.json +++ b/package.json @@ -3,7 +3,7 @@ "private": true, "repository": { "type": "git", - "url": "https://github.com/tanstack/query.git" + "url": "git+https://github.com/TanStack/table.git" }, "packageManager": "pnpm@10.28.2", "type": "module", @@ -24,6 +24,7 @@ "test": "pnpm run test:ci", "test:build": "nx affected --target=test:build --exclude='examples/{lit,solid,svelte,vanilla,vue}/**' --exclude='packages/{lit-table,solid-table,svelte-table,vue-table,match-sorter-utils}'", "test:ci": "nx run-many --targets=test:eslint,test:sherif,test:knip,test:lib,test:types,test:build,build -p @tanstack/table-core @tanstack/react-table @tanstack/preact-table @tanstack/angular-table 'examples/react/**' 'examples/preact/**' 'examples/angular/**'", + "test:docs": "node scripts/verify-links.ts", "test:eslint": "nx affected --target=test:eslint --exclude='examples/{lit,solid,svelte,vanilla,vue}/**' --exclude='packages/{lit-table,solid-table,svelte-table,vue-table,match-sorter-utils}'", "test:knip": "knip", "test:lib": "nx affected --targets=test:lib --exclude='examples/{lit,solid,svelte,vanilla,vue}/**' --exclude='packages/{lit-table,solid-table,svelte-table,vue-table,match-sorter-utils}'", @@ -35,6 +36,7 @@ }, "nx": { "includedScripts": [ + "test:docs", "test:knip", "test:sherif" ] @@ -48,13 +50,16 @@ "devDependencies": { "@faker-js/faker": "^10.2.0", "@size-limit/preset-small-lib": "^12.0.0", - "@tanstack/config": "0.22.2", + "@tanstack/eslint-config": "0.3.4", + "@tanstack/publish-config": "0.2.2", + "@tanstack/typedoc-config": "0.3.3", + "@tanstack/vite-config": "0.4.3", "@testing-library/jest-dom": "^6.9.1", "@types/node": "^25.0.10", "eslint": "^9.39.2", - "eslint-plugin-unused-imports": "^4.3.0", "jsdom": "^27.4.0", "knip": "^5.82.1", + "markdown-link-extractor": "^4.0.3", "nx": "^22.4.2", "prettier": "^3.8.1", "prettier-plugin-svelte": "^3.4.1", @@ -62,6 +67,7 @@ "rimraf": "^6.1.2", "sherif": "^1.10.0", "size-limit": "^12.0.0", + "tinyglobby": "^0.2.15", "typescript": "5.9.3", "vite": "^7.3.1", "vitest": "^4.0.18" diff --git a/packages/lit-table/vite.config.ts b/packages/lit-table/vite.config.ts index 505d2266f2..1cb9ff6324 100644 --- a/packages/lit-table/vite.config.ts +++ b/packages/lit-table/vite.config.ts @@ -1,5 +1,5 @@ import { defineConfig, mergeConfig } from 'vitest/config' -import { tanstackViteConfig } from '@tanstack/config/vite' +import { tanstackViteConfig } from '@tanstack/vite-config' const config = defineConfig({}) diff --git a/packages/match-sorter-utils/vite.config.ts b/packages/match-sorter-utils/vite.config.ts index 0276d9a2f1..ff3c712072 100644 --- a/packages/match-sorter-utils/vite.config.ts +++ b/packages/match-sorter-utils/vite.config.ts @@ -1,5 +1,5 @@ import { defineConfig, mergeConfig } from 'vitest/config' -import { tanstackViteConfig } from '@tanstack/config/vite' +import { tanstackViteConfig } from '@tanstack/vite-config' import packageJson from './package.json' const config = defineConfig({ diff --git a/packages/preact-table/vite.config.ts b/packages/preact-table/vite.config.ts index 18ca71ea22..176155d979 100644 --- a/packages/preact-table/vite.config.ts +++ b/packages/preact-table/vite.config.ts @@ -1,5 +1,5 @@ import { defineConfig, mergeConfig } from 'vitest/config' -import { tanstackViteConfig } from '@tanstack/config/vite' +import { tanstackViteConfig } from '@tanstack/vite-config' import preact from '@preact/preset-vite' import packageJson from './package.json' diff --git a/packages/react-table/vite.config.ts b/packages/react-table/vite.config.ts index 0ffb4f07e8..04e0db3818 100644 --- a/packages/react-table/vite.config.ts +++ b/packages/react-table/vite.config.ts @@ -1,5 +1,5 @@ import { defineConfig, mergeConfig } from 'vitest/config' -import { tanstackViteConfig } from '@tanstack/config/vite' +import { tanstackViteConfig } from '@tanstack/vite-config' import react from '@vitejs/plugin-react' import packageJson from './package.json' diff --git a/packages/table-core/vite.config.ts b/packages/table-core/vite.config.ts index bc0826c393..38e555eb28 100644 --- a/packages/table-core/vite.config.ts +++ b/packages/table-core/vite.config.ts @@ -1,5 +1,5 @@ import { defineConfig, mergeConfig } from 'vitest/config' -import { tanstackViteConfig } from '@tanstack/config/vite' +import { tanstackViteConfig } from '@tanstack/vite-config' import packageJson from './package.json' const config = defineConfig({ diff --git a/packages/vue-table/vite.config.ts b/packages/vue-table/vite.config.ts index 09c21a3f1f..970395edb0 100644 --- a/packages/vue-table/vite.config.ts +++ b/packages/vue-table/vite.config.ts @@ -1,5 +1,5 @@ import { defineConfig, mergeConfig } from 'vitest/config' -import { tanstackViteConfig } from '@tanstack/config/vite' +import { tanstackViteConfig } from '@tanstack/vite-config' import vue from '@vitejs/plugin-vue' const config = defineConfig({ diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index a3d1d27689..b877e1ff3f 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -14,9 +14,18 @@ importers: '@size-limit/preset-small-lib': specifier: ^12.0.0 version: 12.0.0(size-limit@12.0.0(jiti@2.6.1)) - '@tanstack/config': - specifier: 0.22.2 - version: 0.22.2(@types/node@25.0.10)(@typescript-eslint/utils@8.54.0(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3))(eslint-import-resolver-node@0.3.9)(eslint@9.39.2(jiti@2.6.1))(rollup@4.53.3)(typescript@5.9.3)(vite@7.3.1(@types/node@25.0.10)(jiti@2.6.1)(less@4.4.2)(lightningcss@1.30.2)(sass@1.97.1)(terser@5.44.1)(tsx@4.19.2)(yaml@2.8.2)) + '@tanstack/eslint-config': + specifier: 0.3.4 + version: 0.3.4(@typescript-eslint/utils@8.54.0(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3))(eslint-import-resolver-node@0.3.9)(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3) + '@tanstack/publish-config': + specifier: 0.2.2 + version: 0.2.2 + '@tanstack/typedoc-config': + specifier: 0.3.3 + version: 0.3.3(typescript@5.9.3) + '@tanstack/vite-config': + specifier: 0.4.3 + version: 0.4.3(@types/node@25.0.10)(rollup@4.53.3)(typescript@5.9.3)(vite@7.3.1(@types/node@25.0.10)(jiti@2.6.1)(less@4.4.2)(lightningcss@1.30.2)(sass@1.97.1)(terser@5.44.1)(tsx@4.19.2)(yaml@2.8.2)) '@testing-library/jest-dom': specifier: ^6.9.1 version: 6.9.1 @@ -26,15 +35,15 @@ importers: eslint: specifier: ^9.39.2 version: 9.39.2(jiti@2.6.1) - eslint-plugin-unused-imports: - specifier: ^4.3.0 - version: 4.3.0(@typescript-eslint/eslint-plugin@8.54.0(@typescript-eslint/parser@8.54.0(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3))(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3))(eslint@9.39.2(jiti@2.6.1)) jsdom: specifier: ^27.4.0 version: 27.4.0(postcss@8.5.6) knip: specifier: ^5.82.1 version: 5.82.1(@types/node@25.0.10)(typescript@5.9.3) + markdown-link-extractor: + specifier: ^4.0.3 + version: 4.0.3 nx: specifier: ^22.4.2 version: 22.4.2 @@ -56,6 +65,9 @@ importers: size-limit: specifier: ^12.0.0 version: 12.0.0(jiti@2.6.1) + tinyglobby: + specifier: ^0.2.15 + version: 0.2.15 typescript: specifier: 5.9.3 version: 5.9.3 @@ -6945,17 +6957,15 @@ packages: '@angular/common': '>=19.0.0' '@angular/core': '>=19.0.0' - '@tanstack/config@0.22.2': - resolution: {integrity: sha512-zP1b6xd864AOOJQ7u6r+kicohRc8dAyql6sBbQh2f2RjoEynAfn0GrMHGeqhl1LN8JThokCkcjfGnXbPEz3q3A==} - engines: {node: '>=18'} - '@tanstack/devtools-event-client@0.4.0': resolution: {integrity: sha512-RPfGuk2bDZgcu9bAJodvO2lnZeHuz4/71HjZ0bGb/SPg8+lyTA+RLSKQvo7fSmPSi8/vcH3aKQ8EM9ywf1olaw==} engines: {node: '>=18'} - '@tanstack/eslint-config@0.3.3': - resolution: {integrity: sha512-8VFyAaIFV9onJcfc5yVj5WWl6DmN3W4m+t0Mb+nZrQmqHy+kDndw5O5Xv2BHVWRRPTqnhlJYh6wHWGh0R81ZzQ==} + '@tanstack/eslint-config@0.3.4': + resolution: {integrity: sha512-5Ou1XWJRCTx5G8WoCbT7+6nQ4iNdsISzBAc4lXpFy2fEOO7xioOSPvcPIv+r9V0drPPETou2tr6oLGZZ909FKg==} engines: {node: '>=18'} + peerDependencies: + eslint: ^8.0.0 || ^9.0.0 '@tanstack/form-core@1.28.0': resolution: {integrity: sha512-MX3YveB6SKHAJ2yUwp+Ca/PCguub8bVEnLcLUbFLwdkSRMkP0lMGdaZl+F0JuEgZw56c6iFoRyfILhS7OQpydA==} @@ -7071,8 +7081,8 @@ packages: peerDependencies: svelte: ^5.0.0 - '@tanstack/typedoc-config@0.3.2': - resolution: {integrity: sha512-4S6vIl2JmjvSQC87py/ZS9YWb1//1RRlHQRCUNLaGAdnptZYX7qJvSJS8GmAZ6nele2eRlpmPZGSw3MpCR22Tg==} + '@tanstack/typedoc-config@0.3.3': + resolution: {integrity: sha512-wVT2YfKDSpd+4f7fk6UaPIP3a2J7LSovlyVuFF1PH2yQb7gjqehod5zdFiwFyEXgvI9XGuFvvs1OehkKNYcr6A==} engines: {node: '>=18'} '@tanstack/virtual-core@3.13.18': @@ -7082,9 +7092,11 @@ packages: resolution: {integrity: sha512-cHHDnewHozgjpI+MIVp9tcib6lYEQK5MyUr0ChHpHFGBl8Xei55rohFK0I0ve/GKoHeioaK42Smd8OixPp6CTg==} engines: {node: '>=12'} - '@tanstack/vite-config@0.4.1': - resolution: {integrity: sha512-FOl8EF6SAcljanKSm5aBeJaflFcxQAytTbxtNW8HC6D4x+UBW68IC4tBcrlrsI0wXHBmC/Gz4Ovvv8qCtiXSgQ==} + '@tanstack/vite-config@0.4.3': + resolution: {integrity: sha512-bqXfdPmD6DuAZdE08ih5bSqpcge9Im9nEym3CKcQ9OsPo0jmGW7WrJarLaoVB6qWEysh3FIwWQN1gtfeC7q8UQ==} engines: {node: '>=18'} + peerDependencies: + vite: ^6.0.0 || ^7.0.0 '@tanstack/vue-store@0.8.0': resolution: {integrity: sha512-YLsinYboBLIjNkxDpAn1ydaMS35dKq3M3a788JRCJi4/stWcN7Swp0pxxJ+p0IwKSY4tBXx7vMz22OYWQ1QsUQ==} @@ -7329,10 +7341,6 @@ packages: eslint: ^8.57.0 || ^9.0.0 typescript: '>=4.8.4 <6.0.0' - '@typescript-eslint/types@8.53.0': - resolution: {integrity: sha512-Bmh9KX31Vlxa13+PqPvt4RzKRN1XORYSLlAE+sO1i28NkisGbTtSLFVB3l7PWdHtR3E0mVMuC7JilWJ99m2HxQ==} - engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - '@typescript-eslint/types@8.54.0': resolution: {integrity: sha512-PDUI9R1BVjqu7AUDsRBbKMtwmjWcn4J3le+5LpcFgWULN3LvHC5rkc9gCVxbrsrGmO1jfPybN5s6h4Jy+OnkAA==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} @@ -7989,6 +7997,13 @@ packages: chardet@2.1.1: resolution: {integrity: sha512-PsezH1rqdV9VvyNhxxOW32/d75r01NY7TQCmOqomRo15ZSOKbpTFVsfjghxo6JloQUCGnH4k1LGu0R4yCLlWQQ==} + cheerio-select@2.1.0: + resolution: {integrity: sha512-9v9kG0LvzrlcungtnJtpGNxY+fzECQKhK4EGJX2vByejiMX84MFNQw4UxPJl3bFbTMw+Dfs37XaIkCwTZfLh4g==} + + cheerio@1.2.0: + resolution: {integrity: sha512-WDrybc/gKFpTYQutKIK6UvfcuxijIZfMfXaYm8NMsPQxSYvf+13fXUJ4rztGGbJcBQ/GF55gvrZ0Bc0bj/mqvg==} + engines: {node: '>=20.18.1'} + chokidar@3.6.0: resolution: {integrity: sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw==} engines: {node: '>= 8.10.0'} @@ -8459,6 +8474,9 @@ packages: resolution: {integrity: sha512-Q0n9HRi4m6JuGIV1eFlmvJB7ZEVxu93IrMyiMsGC0lrMJMWzRgx6WGquyfQgZVb31vhGgXnfmPNNXmxnOkRBrg==} engines: {node: '>= 0.8'} + encoding-sniffer@0.2.1: + resolution: {integrity: sha512-5gvq20T6vfpekVtqrYQsSCFZ1wEg5+wW0/QaZMWkFr6BqD3NfKs0rLCx4rrVlSWJeZb5NBJgVLswK/w2MWU+Gw==} + encoding@0.1.13: resolution: {integrity: sha512-ETBauow1T35Y/WZMkio9jiM0Z5xjHHmJ4XmjZOq1l/dXz3lr2sRn87nJy20RupqSh1F2m3HHPSp8ShIPQJrJ3A==} @@ -8497,6 +8515,10 @@ packages: resolution: {integrity: sha512-FDWG5cmEYf2Z00IkYRhbFrwIwvdFKH07uV8dvNy0omp/Qb1xcyCWp2UDtcwJF4QZZvk0sLudP6/hAu42TaqVhQ==} engines: {node: '>=0.12'} + entities@7.0.1: + resolution: {integrity: sha512-TWrgLOFUQTH994YUyl1yT4uyavY5nNB5muff+RtWaqNVCAK408b5ZnnbNAUEWLTCpum9w6arT70i1XdQ4UeOPA==} + engines: {node: '>=0.12'} + env-paths@2.2.1: resolution: {integrity: sha512-+h1lkLKhZMTYjog1VEpJNG7NZJWcuc2DDk/qsqSTRRCOXiLjeQ1d1/udrUGhqMxUgAlwKNZ0cf2uqan5GLuS2A==} engines: {node: '>=6'} @@ -8672,15 +8694,6 @@ packages: svelte: optional: true - eslint-plugin-unused-imports@4.3.0: - resolution: {integrity: sha512-ZFBmXMGBYfHttdRtOG9nFFpmUvMtbHSjsKrS20vdWdbfiVYsO3yA2SGYy9i9XmZJDfMGBflZGBCm70SEnFQtOA==} - peerDependencies: - '@typescript-eslint/eslint-plugin': ^8.0.0-0 || ^7.0.0 || ^6.0.0 || ^5.0.0 - eslint: ^9.0.0 || ^8.0.0 - peerDependenciesMeta: - '@typescript-eslint/eslint-plugin': - optional: true - eslint-plugin-vue@10.7.0: resolution: {integrity: sha512-r2XFCK4qlo1sxEoAMIoTTX0PZAdla0JJDt1fmYiworZUX67WeEGqm+JbyAg3M+pGiJ5U6Mp5WQbontXWtIW7TA==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} @@ -9084,9 +9097,15 @@ packages: html-entities@2.3.3: resolution: {integrity: sha512-DV5Ln36z34NNTDgnz0EWGBLZENelNAtkiFA4kyNOG2tDI6Mz1uSWiq1wAKdyjnJwyDiDO7Fa2SO1CTxPXL8VxA==} + html-link-extractor@1.0.5: + resolution: {integrity: sha512-ADd49pudM157uWHwHQPUSX4ssMsvR/yHIswOR5CUfBdK9g9ZYGMhVSE6KZVHJ6kCkR0gH4htsfzU6zECDNVwyw==} + htmlparser2@10.0.0: resolution: {integrity: sha512-TwAZM+zE5Tq3lrEHvOlvwgj1XLWQCtaaibSN11Q+gGBAS7Y1uZSWwXXRe4iF6OXnaq1riyQAPFOBtYc77Mxq0g==} + htmlparser2@10.1.0: + resolution: {integrity: sha512-VTZkM9GWRAtEpveh7MSF6SjjrpNVNNVJfFup7xTY3UpFtm67foy9HDVXneLtFVt4pMz5kZtgNcvCniNFb1hlEQ==} + http-cache-semantics@4.1.1: resolution: {integrity: sha512-er295DKPVsV82j5kw1Gjt+ADA/XYHsajl82cGNQG2eyoPkvgUhX+nDIyelzhIWbbsXP39EHcI6l5tYs2FYqYXQ==} @@ -9730,6 +9749,14 @@ packages: resolution: {integrity: sha512-a54IwgWPaeBCAAsv13YgmALOF1elABB08FxO9i+r4VFk5Vl4pKokRPeX8u5TCgSsPi6ec1otfLjdOpVcgbpshg==} hasBin: true + markdown-link-extractor@4.0.3: + resolution: {integrity: sha512-aEltJiQ4/oC0h6Jbw/uuATGSHZPkcH8DIunNH1A0e+GSFkvZ6BbBkdvBTVfIV8r6HapCU3yTd0eFdi3ZeM1eAQ==} + + marked@17.0.1: + resolution: {integrity: sha512-boeBdiS0ghpWcSwoNm/jJBwdpFaMnZWRzjA6SkUMYb40SVaN1x7mmfGKp0jvexGcx+7y2La5zRZsYFZI6Qpypg==} + engines: {node: '>= 20'} + hasBin: true + math-intrinsics@1.1.0: resolution: {integrity: sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==} engines: {node: '>= 0.4'} @@ -10175,9 +10202,18 @@ packages: parse5-html-rewriting-stream@8.0.0: resolution: {integrity: sha512-wzh11mj8KKkno1pZEu+l2EVeWsuKDfR5KNWZOTsslfUX8lPDZx77m9T0kIoAVkFtD1nx6YF8oh4BnPHvxMtNMw==} + parse5-htmlparser2-tree-adapter@7.1.0: + resolution: {integrity: sha512-ruw5xyKs6lrpo9x9rCZqZZnIUntICjQAd0Wsmp396Ul9lN/h+ifgVV1x1gZHi8euej6wTfpqX8j+BFQxF0NS/g==} + + parse5-parser-stream@7.1.2: + resolution: {integrity: sha512-JyeQc9iwFLn5TbvvqACIF/VXG6abODeB3Fwmv/TGdLk2LfbWkaySGY72at4+Ty7EkPZj854u4CrICqNk2qIbow==} + parse5-sax-parser@8.0.0: resolution: {integrity: sha512-/dQ8UzHZwnrzs3EvDj6IkKrD/jIZyTlB+8XrHJvcjNgRdmWruNdN9i9RK/JtxakmlUdPwKubKPTCqvbTgzGhrw==} + parse5@7.3.0: + resolution: {integrity: sha512-IInvU7fabl34qmi9gY8XOVxhYyMyuH2xUNpb2q8/Y+7552KlejkRvqvD19nMoUW/uQGGbqNpA6Tufu5FL5BZgw==} + parse5@8.0.0: resolution: {integrity: sha512-9m4m5GSgXjL4AjumKzq1Fgfp3Z8rsvjRNbnkVwfu2ImRqE5D0LnY2QfDen18FSY9C573YU5XxSapdHZTZ2WolA==} @@ -11329,6 +11365,10 @@ packages: resolution: {integrity: sha512-y+8YjDFzWdQlSE9N5nzKMT3g4a5UBX1HKowfdXh0uvAnTaqqwqB92Jt4UXBAeKekDs5IaDKyJFR4X1gYVCgXcw==} engines: {node: '>=20.18.1'} + undici@7.21.0: + resolution: {integrity: sha512-Hn2tCQpoDt1wv23a68Ctc8Cr/BHpUSfaPYrkajTXOS9IKpxVRx/X5m1K2YkbK2ipgZgxXSgsUinl3x+2YdSSfg==} + engines: {node: '>=20.18.1'} + unicode-canonical-property-names-ecmascript@2.0.1: resolution: {integrity: sha512-dA8WbNeb2a6oQzAQ55YlT5vQAWGV9WXOsi3SskE3bcCdM0P4SDd+24zS/OCacdRq5BkdsRj9q3Pg6YyQoxIGqg==} engines: {node: '>=4'} @@ -11723,6 +11763,11 @@ packages: resolution: {integrity: sha512-OqedPIGOfsDlo31UNwYbCFMSaO9m9G/0faIHj5/dZFDMFqPTcx6UwqyOy3COEaEOg/9VsGIpdqn62W5KhoKSpg==} engines: {node: '>=0.8.0'} + whatwg-encoding@3.1.1: + resolution: {integrity: sha512-6qN4hJdMwfYBtE3YBTTHhoeuUrDBPZmbQaxWAqSALV/MeEnR5z1xd8UKud2RAkFoPkmB+hli1TZSnyi84xz1vQ==} + engines: {node: '>=18'} + deprecated: Use @exodus/bytes instead for a more spec-conformant and faster implementation + whatwg-mimetype@4.0.0: resolution: {integrity: sha512-QaKxh0eNIi2mE9p2vEdzfagOKHCcj1pJ56EEHGQOVxp8r9/iszLUUV7v89x9O1p/T+NlTM5W7jW6+cz4Fq1YVg==} engines: {node: '>=18'} @@ -15201,28 +15246,13 @@ snapshots: '@tanstack/store': 0.8.0 tslib: 2.8.1 - '@tanstack/config@0.22.2(@types/node@25.0.10)(@typescript-eslint/utils@8.54.0(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3))(eslint-import-resolver-node@0.3.9)(eslint@9.39.2(jiti@2.6.1))(rollup@4.53.3)(typescript@5.9.3)(vite@7.3.1(@types/node@25.0.10)(jiti@2.6.1)(less@4.4.2)(lightningcss@1.30.2)(sass@1.97.1)(terser@5.44.1)(tsx@4.19.2)(yaml@2.8.2))': - dependencies: - '@tanstack/eslint-config': 0.3.3(@typescript-eslint/utils@8.54.0(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3))(eslint-import-resolver-node@0.3.9)(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3) - '@tanstack/publish-config': 0.2.2 - '@tanstack/typedoc-config': 0.3.2(typescript@5.9.3) - '@tanstack/vite-config': 0.4.1(@types/node@25.0.10)(rollup@4.53.3)(typescript@5.9.3)(vite@7.3.1(@types/node@25.0.10)(jiti@2.6.1)(less@4.4.2)(lightningcss@1.30.2)(sass@1.97.1)(terser@5.44.1)(tsx@4.19.2)(yaml@2.8.2)) - transitivePeerDependencies: - - '@types/node' - - '@typescript-eslint/utils' - - eslint - - eslint-import-resolver-node - - rollup - - supports-color - - typescript - - vite - '@tanstack/devtools-event-client@0.4.0': {} - '@tanstack/eslint-config@0.3.3(@typescript-eslint/utils@8.54.0(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3))(eslint-import-resolver-node@0.3.9)(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3)': + '@tanstack/eslint-config@0.3.4(@typescript-eslint/utils@8.54.0(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3))(eslint-import-resolver-node@0.3.9)(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3)': dependencies: '@eslint/js': 9.39.2 '@stylistic/eslint-plugin': 5.7.1(eslint@9.39.2(jiti@2.6.1)) + eslint: 9.39.2(jiti@2.6.1) eslint-plugin-import-x: 4.16.1(@typescript-eslint/utils@8.54.0(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3))(eslint-import-resolver-node@0.3.9)(eslint@9.39.2(jiti@2.6.1)) eslint-plugin-n: 17.23.2(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3) globals: 16.5.0 @@ -15230,7 +15260,6 @@ snapshots: vue-eslint-parser: 10.2.0(eslint@9.39.2(jiti@2.6.1)) transitivePeerDependencies: - '@typescript-eslint/utils' - - eslint - eslint-import-resolver-node - supports-color - typescript @@ -15387,7 +15416,7 @@ snapshots: '@tanstack/store': 0.8.0 svelte: 5.48.5 - '@tanstack/typedoc-config@0.3.2(typescript@5.9.3)': + '@tanstack/typedoc-config@0.3.3(typescript@5.9.3)': dependencies: typedoc: 0.28.14(typescript@5.9.3) typedoc-plugin-frontmatter: 1.3.0(typedoc-plugin-markdown@4.9.0(typedoc@0.28.14(typescript@5.9.3))) @@ -15399,9 +15428,10 @@ snapshots: '@tanstack/virtual-file-routes@1.154.7': {} - '@tanstack/vite-config@0.4.1(@types/node@25.0.10)(rollup@4.53.3)(typescript@5.9.3)(vite@7.3.1(@types/node@25.0.10)(jiti@2.6.1)(less@4.4.2)(lightningcss@1.30.2)(sass@1.97.1)(terser@5.44.1)(tsx@4.19.2)(yaml@2.8.2))': + '@tanstack/vite-config@0.4.3(@types/node@25.0.10)(rollup@4.53.3)(typescript@5.9.3)(vite@7.3.1(@types/node@25.0.10)(jiti@2.6.1)(less@4.4.2)(lightningcss@1.30.2)(sass@1.97.1)(terser@5.44.1)(tsx@4.19.2)(yaml@2.8.2))': dependencies: rollup-plugin-preserve-directives: 0.4.0(rollup@4.53.3) + vite: 7.3.1(@types/node@25.0.10)(jiti@2.6.1)(less@4.4.2)(lightningcss@1.30.2)(sass@1.97.1)(terser@5.44.1)(tsx@4.19.2)(yaml@2.8.2) vite-plugin-dts: 4.2.3(@types/node@25.0.10)(rollup@4.53.3)(typescript@5.9.3)(vite@7.3.1(@types/node@25.0.10)(jiti@2.6.1)(less@4.4.2)(lightningcss@1.30.2)(sass@1.97.1)(terser@5.44.1)(tsx@4.19.2)(yaml@2.8.2)) vite-plugin-externalize-deps: 0.10.0(vite@7.3.1(@types/node@25.0.10)(jiti@2.6.1)(less@4.4.2)(lightningcss@1.30.2)(sass@1.97.1)(terser@5.44.1)(tsx@4.19.2)(yaml@2.8.2)) vite-tsconfig-paths: 5.1.4(typescript@5.9.3)(vite@7.3.1(@types/node@25.0.10)(jiti@2.6.1)(less@4.4.2)(lightningcss@1.30.2)(sass@1.97.1)(terser@5.44.1)(tsx@4.19.2)(yaml@2.8.2)) @@ -15410,7 +15440,6 @@ snapshots: - rollup - supports-color - typescript - - vite '@tanstack/vue-store@0.8.0(vue@3.5.27(typescript@5.9.3))': dependencies: @@ -15708,8 +15737,6 @@ snapshots: transitivePeerDependencies: - supports-color - '@typescript-eslint/types@8.53.0': {} - '@typescript-eslint/types@8.54.0': {} '@typescript-eslint/typescript-estree@8.54.0(typescript@5.9.3)': @@ -15920,7 +15947,7 @@ snapshots: dependencies: '@babel/parser': 7.28.5 '@vue/shared': 3.5.26 - entities: 7.0.0 + entities: 7.0.1 estree-walker: 2.0.2 source-map-js: 1.2.1 @@ -15984,9 +16011,9 @@ snapshots: '@vue/language-core@2.1.6(typescript@5.9.3)': dependencies: '@volar/language-core': 2.4.27 - '@vue/compiler-dom': 3.5.26 + '@vue/compiler-dom': 3.5.27 '@vue/compiler-vue2': 2.7.16 - '@vue/shared': 3.5.26 + '@vue/shared': 3.5.27 computeds: 0.0.1 minimatch: 9.0.5 muggle-string: 0.4.1 @@ -16501,6 +16528,29 @@ snapshots: chardet@2.1.1: {} + cheerio-select@2.1.0: + dependencies: + boolbase: 1.0.0 + css-select: 5.1.0 + css-what: 6.1.0 + domelementtype: 2.3.0 + domhandler: 5.0.3 + domutils: 3.2.2 + + cheerio@1.2.0: + dependencies: + cheerio-select: 2.1.0 + dom-serializer: 2.0.0 + domhandler: 5.0.3 + domutils: 3.2.2 + encoding-sniffer: 0.2.1 + htmlparser2: 10.1.0 + parse5: 7.3.0 + parse5-htmlparser2-tree-adapter: 7.1.0 + parse5-parser-stream: 7.1.2 + undici: 7.21.0 + whatwg-mimetype: 4.0.0 + chokidar@3.6.0: dependencies: anymatch: 3.1.3 @@ -16930,6 +16980,11 @@ snapshots: encodeurl@2.0.0: {} + encoding-sniffer@0.2.1: + dependencies: + iconv-lite: 0.6.3 + whatwg-encoding: 3.1.1 + encoding@0.1.13: dependencies: iconv-lite: 0.6.3 @@ -16982,6 +17037,8 @@ snapshots: entities@7.0.0: {} + entities@7.0.1: {} + env-paths@2.2.1: {} environment@1.1.0: {} @@ -17135,13 +17192,13 @@ snapshots: eslint-plugin-es-x@7.8.0(eslint@9.39.2(jiti@2.6.1)): dependencies: '@eslint-community/eslint-utils': 4.9.1(eslint@9.39.2(jiti@2.6.1)) - '@eslint-community/regexpp': 4.12.1 + '@eslint-community/regexpp': 4.12.2 eslint: 9.39.2(jiti@2.6.1) eslint-compat-utils: 0.5.1(eslint@9.39.2(jiti@2.6.1)) eslint-plugin-import-x@4.16.1(@typescript-eslint/utils@8.54.0(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3))(eslint-import-resolver-node@0.3.9)(eslint@9.39.2(jiti@2.6.1)): dependencies: - '@typescript-eslint/types': 8.53.0 + '@typescript-eslint/types': 8.54.0 comment-parser: 1.4.5 debug: 4.4.3 eslint: 9.39.2(jiti@2.6.1) @@ -17163,7 +17220,7 @@ snapshots: enhanced-resolve: 5.18.4 eslint: 9.39.2(jiti@2.6.1) eslint-plugin-es-x: 7.8.0(eslint@9.39.2(jiti@2.6.1)) - get-tsconfig: 4.8.1 + get-tsconfig: 4.13.0 globals: 15.14.0 globrex: 0.1.2 ignore: 5.3.2 @@ -17306,12 +17363,6 @@ snapshots: transitivePeerDependencies: - ts-node - eslint-plugin-unused-imports@4.3.0(@typescript-eslint/eslint-plugin@8.54.0(@typescript-eslint/parser@8.54.0(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3))(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3))(eslint@9.39.2(jiti@2.6.1)): - dependencies: - eslint: 9.39.2(jiti@2.6.1) - optionalDependencies: - '@typescript-eslint/eslint-plugin': 8.54.0(@typescript-eslint/parser@8.54.0(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3))(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3) - eslint-plugin-vue@10.7.0(@stylistic/eslint-plugin@5.7.1(eslint@9.39.2(jiti@2.6.1)))(@typescript-eslint/parser@8.54.0(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3))(eslint@9.39.2(jiti@2.6.1))(vue-eslint-parser@10.2.0(eslint@9.39.2(jiti@2.6.1))): dependencies: '@eslint-community/eslint-utils': 4.9.1(eslint@9.39.2(jiti@2.6.1)) @@ -17790,6 +17841,10 @@ snapshots: html-entities@2.3.3: {} + html-link-extractor@1.0.5: + dependencies: + cheerio: 1.2.0 + htmlparser2@10.0.0: dependencies: domelementtype: 2.3.0 @@ -17797,6 +17852,13 @@ snapshots: domutils: 3.2.2 entities: 6.0.1 + htmlparser2@10.1.0: + dependencies: + domelementtype: 2.3.0 + domhandler: 5.0.3 + domutils: 3.2.2 + entities: 7.0.1 + http-cache-semantics@4.1.1: {} http-deceiver@1.2.7: {} @@ -18474,6 +18536,13 @@ snapshots: punycode.js: 2.3.1 uc.micro: 2.1.0 + markdown-link-extractor@4.0.3: + dependencies: + html-link-extractor: 1.0.5 + marked: 17.0.1 + + marked@17.0.1: {} + math-intrinsics@1.1.0: {} mdn-data@2.12.2: {} @@ -19022,10 +19091,23 @@ snapshots: parse5: 8.0.0 parse5-sax-parser: 8.0.0 + parse5-htmlparser2-tree-adapter@7.1.0: + dependencies: + domhandler: 5.0.3 + parse5: 7.3.0 + + parse5-parser-stream@7.1.2: + dependencies: + parse5: 7.3.0 + parse5-sax-parser@8.0.0: dependencies: parse5: 8.0.0 + parse5@7.3.0: + dependencies: + entities: 6.0.1 + parse5@8.0.0: dependencies: entities: 6.0.1 @@ -20228,6 +20310,8 @@ snapshots: undici@7.18.2: {} + undici@7.21.0: {} + unicode-canonical-property-names-ecmascript@2.0.1: {} unicode-match-property-ecmascript@2.0.0: @@ -20638,6 +20722,10 @@ snapshots: websocket-extensions@0.1.4: {} + whatwg-encoding@3.1.1: + dependencies: + iconv-lite: 0.6.3 + whatwg-mimetype@4.0.0: {} whatwg-url@15.1.0: diff --git a/pnpm-workspace.yaml b/pnpm-workspace.yaml index 0e62bc4c25..92a2c71de6 100644 --- a/pnpm-workspace.yaml +++ b/pnpm-workspace.yaml @@ -1,3 +1,7 @@ +cleanupUnusedCatalogs: true +linkWorkspacePackages: true +preferWorkspacePackages: true + packages: - 'packages/*' - 'examples/angular/*' diff --git a/scripts/generateDocs.js b/scripts/generateDocs.js index 3718e90f68..b1c01667c3 100644 --- a/scripts/generateDocs.js +++ b/scripts/generateDocs.js @@ -1,33 +1,36 @@ import { resolve } from 'node:path' import { fileURLToPath } from 'node:url' -import { generateReferenceDocs } from '@tanstack/config/typedoc' +import { generateReferenceDocs } from '@tanstack/typedoc-config' const __dirname = fileURLToPath(new URL('.', import.meta.url)) -/** @type {import('@tanstack/config/typedoc').Package[]} */ -const packages = [ - { - name: 'table-core', - entryPoints: [resolve(__dirname, '../packages/table-core/src/index.ts')], - tsconfig: resolve(__dirname, '../packages/table-core/tsconfig.json'), - outputDir: resolve(__dirname, '../docs/reference'), - }, - { - name: 'react-table', - entryPoints: [resolve(__dirname, '../packages/react-table/src/index.ts')], - tsconfig: resolve(__dirname, '../packages/react-table/tsconfig.json'), - outputDir: resolve(__dirname, '../docs/framework/react/reference'), - exclude: ['packages/table-core/**/*'], - }, - { - name: 'angular-table', - entryPoints: [resolve(__dirname, '../packages/angular-table/src/index.ts')], - tsconfig: resolve(__dirname, '../packages/angular-table/tsconfig.json'), - outputDir: resolve(__dirname, '../docs/framework/angular/reference'), - exclude: ['packages/table-core/**/*'], - }, -] +await generateReferenceDocs({ + packages: [ + { + name: 'table-core', + entryPoints: [resolve(__dirname, '../packages/table-core/src/index.ts')], + tsconfig: resolve(__dirname, '../packages/table-core/tsconfig.json'), + outputDir: resolve(__dirname, '../docs/reference'), + }, + { + name: 'react-table', + entryPoints: [resolve(__dirname, '../packages/react-table/src/index.ts')], + tsconfig: resolve(__dirname, '../packages/react-table/tsconfig.json'), + outputDir: resolve(__dirname, '../docs/framework/react/reference'), + exclude: ['packages/table-core/**/*'], + }, + { + name: 'angular-table', + entryPoints: [ + resolve(__dirname, '../packages/angular-table/src/index.ts'), + ], + tsconfig: resolve(__dirname, '../packages/angular-table/tsconfig.json'), + outputDir: resolve(__dirname, '../docs/framework/angular/reference'), + exclude: ['packages/table-core/**/*'], + }, + ], +}) -await generateReferenceDocs({ packages }) +console.log('\nāœ… All markdown files have been processed!') process.exit(0) diff --git a/scripts/publish.js b/scripts/publish.js index ba818b5058..0aee644073 100644 --- a/scripts/publish.js +++ b/scripts/publish.js @@ -1,6 +1,6 @@ // @ts-check -import { publish } from '@tanstack/config/publish' +import { publish } from '@tanstack/publish-config' import { branchConfigs, packages, rootDir } from './config.js' await publish({ diff --git a/scripts/verify-links.ts b/scripts/verify-links.ts new file mode 100644 index 0000000000..8a1c40ddc5 --- /dev/null +++ b/scripts/verify-links.ts @@ -0,0 +1,125 @@ +import { existsSync, readFileSync, statSync } from 'node:fs' +import { extname, resolve } from 'node:path' +import { glob } from 'tinyglobby' +// @ts-ignore Could not find a declaration file for module 'markdown-link-extractor'. +import markdownLinkExtractor from 'markdown-link-extractor' + +const errors: Array<{ + file: string + link: string + resolvedPath: string + reason: string +}> = [] + +function isRelativeLink(link: string) { + return ( + !link.startsWith('/') && + !link.startsWith('http://') && + !link.startsWith('https://') && + !link.startsWith('//') && + !link.startsWith('#') && + !link.startsWith('mailto:') + ) +} + +/** Remove any trailing .md */ +function stripExtension(p: string): string { + return p.replace(`${extname(p)}`, '') +} + +function relativeLinkExists(link: string, file: string): boolean { + // Remove hash if present + const linkWithoutHash = link.split('#')[0] + // If the link is empty after removing hash, it's not a file + if (!linkWithoutHash) return false + + // Strip the file/link extensions + const filePath = stripExtension(file) + const linkPath = stripExtension(linkWithoutHash) + + // Resolve the path relative to the markdown file's directory + // Nav up a level to simulate how links are resolved on the web + let absPath = resolve(filePath, '..', linkPath) + + // Ensure the resolved path is within /docs + const docsRoot = resolve('docs') + if (!absPath.startsWith(docsRoot)) { + errors.push({ + link, + file, + resolvedPath: absPath, + reason: 'Path outside /docs', + }) + return false + } + + // Check if this is an example path + const isExample = absPath.includes('/examples/') + + let exists = false + + if (isExample) { + // Transform /docs/framework/{framework}/examples/ to /examples/{framework}/ + absPath = absPath.replace( + /\/docs\/framework\/([^/]+)\/examples\//, + '/examples/$1/', + ) + // For examples, we want to check if the directory exists + exists = existsSync(absPath) && statSync(absPath).isDirectory() + } else { + // For non-examples, we want to check if the .md file exists + if (!absPath.endsWith('.md')) { + absPath = `${absPath}.md` + } + exists = existsSync(absPath) + } + + if (!exists) { + errors.push({ + link, + file, + resolvedPath: absPath, + reason: 'Not found', + }) + } + return exists +} + +async function verifyMarkdownLinks() { + // Find all markdown files in docs directory + const markdownFiles = await glob('docs/**/*.md', { + ignore: ['**/node_modules/**'], + }) + + console.log(`Found ${markdownFiles.length} markdown files\n`) + + // Process each file + for (const file of markdownFiles) { + const content = readFileSync(file, 'utf-8') + const links: Array = markdownLinkExtractor(content) + + const relativeLinks = links.filter((link: string) => { + return isRelativeLink(link) + }) + + if (relativeLinks.length > 0) { + relativeLinks.forEach((link) => { + relativeLinkExists(link, file) + }) + } + } + + if (errors.length > 0) { + console.log(`\nāŒ Found ${errors.length} broken links:`) + errors.forEach((err) => { + console.log( + `${err.file}\n link: ${err.link}\n resolved: ${err.resolvedPath}\n why: ${err.reason}\n`, + ) + }) + process.exit(1) + } else { + console.log('\nāœ… No broken links found!') + } +} + +verifyMarkdownLinks().catch(console.error) diff --git a/tsconfig.json b/tsconfig.json index a68a5ae20c..92bca68fba 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -11,7 +11,7 @@ "forceConsistentCasingInFileNames": true, "isolatedModules": true, "lib": ["DOM", "DOM.Iterable", "ES2022"], - "module": "ES2022", + "module": "ESNext", "moduleResolution": "Bundler", "noEmit": true, "noImplicitReturns": false, // TODO enable @@ -24,10 +24,5 @@ "target": "ES2020", "noErrorTruncation": true }, - "include": [ - "prettier.config.js", - "scripts", - "eslint.config.js", - "vitest.workspace.mjs" - ] + "include": ["*.config.*", "scripts", "vitest.workspace.mjs"] } From b1f3befc611458502bc7616a1ef82485da809085 Mon Sep 17 00:00:00 2001 From: Lachlan Collins <1667261+lachlancollins@users.noreply.github.com> Date: Tue, 10 Feb 2026 10:46:42 +1100 Subject: [PATCH 2/2] Fix prettier --- .github/ISSUE_TEMPLATE/config.yml | 2 +- nx.json | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/ISSUE_TEMPLATE/config.yml b/.github/ISSUE_TEMPLATE/config.yml index e657773eab..963fe444ec 100644 --- a/.github/ISSUE_TEMPLATE/config.yml +++ b/.github/ISSUE_TEMPLATE/config.yml @@ -8,4 +8,4 @@ contact_links: about: A dedicated discord server hosted by TanStack - name: šŸ¦‹ TanStack Bluesky url: https://bsky.app/profile/tanstack.com - about: Stay up to date with new releases of our libraries \ No newline at end of file + about: Stay up to date with new releases of our libraries diff --git a/nx.json b/nx.json index 5f740e3e71..97e78d8bb6 100644 --- a/nx.json +++ b/nx.json @@ -4,7 +4,7 @@ "nxCloudId": "6435ee4cd7387c45c0e4bf4c", "useInferencePlugins": false, "parallel": 5, - "tui": { + "tui": { "enabled": false }, "namedInputs": {