// Generated by scripts/generate-manifest.mjs. Do not edit by hand. import type { AddOnCompiled } from '../../../../../types.js' type TemplateRecord = Record type TemplateAddOn = TemplateRecord & { integrations?: Array routes?: Array } type TemplateRenderContext = { [key: string]: any packageManager: any projectName: any typescript: any tailwind: any blank: any js: any jsx: any fileRouter: any codeRouter: any routerOnly: any includeExamples: any addOnEnabled: Record addOnOption: Record addOns: Array integrations: Array routes: Array getPackageManagerAddScript: (...args: Array) => string getPackageManagerRunScript: (...args: Array) => string getPackageManagerExecuteScript: (...args: Array) => string relativePath: (...args: Array) => string integrationImportContent: (...args: Array) => string integrationImportCode: (...args: Array) => string | undefined renderTemplate: (content: string) => string ignoreFile: () => never } type TemplateRenderer = (context: TemplateRenderContext) => string | undefined function __escapeXML(value: unknown) { if (value === undefined || value === null) { return '' } return String(value).replace(/[&<>'"]/g, (character) => { switch (character) { case '&': return '&' case '<': return '<' case '>': return '>' case '"': return '"' case "'": return ''' default: return character } }) } export function getManifestTemplateKey(template: string) { let hash = 0x811c9dc5 for (let i = 0; i < template.length; i++) { hash ^= template.charCodeAt(i) hash = Math.imul(hash, 0x01000193) >>> 0 } return `${hash.toString(16).padStart(8, '0')}:${template.length}` } function __render_cfd368cd_11500(context: TemplateRenderContext) { const { packageManager, projectName, typescript, tailwind, blank, js, jsx, fileRouter, codeRouter, routerOnly, includeExamples, addOnEnabled, addOnOption, addOns, integrations, routes, getPackageManagerAddScript, getPackageManagerRunScript, getPackageManagerExecuteScript, relativePath, integrationImportContent, integrationImportCode, renderTemplate, ignoreFile, } = context let __output = '' const __append = (value: unknown) => { if (value !== undefined && value !== null) { __output += String(value) } } __append("import React from 'react'\nimport { ") if (fileRouter) { __append("createFileRoute") } else { __append("createRoute") } __append(" } from '@tanstack/react-router'\nimport {\n flexRender,\n getCoreRowModel,\n getFilteredRowModel,\n getPaginationRowModel,\n getSortedRowModel,\n sortingFns,\n useReactTable,\n} from '@tanstack/react-table'\nimport { compareItems, rankItem } from '@tanstack/match-sorter-utils'\n\nimport { makeData } from '#/data/demo-table-data'\n\nimport type {\n Column,\n ColumnDef,\n ColumnFiltersState,\n FilterFn,\n SortingFn,\n} from '@tanstack/react-table'\nimport type { RankingInfo } from '@tanstack/match-sorter-utils'\n") if (codeRouter) { __append("\nimport type { RootRoute } from '@tanstack/react-router'\n") } __append("\nimport type { Person } from '#/data/demo-table-data'\n") if (fileRouter) { __append("\nexport const Route = createFileRoute('/demo/table')({\n component: TableDemo,\n})\n") } __append("\n\ndeclare module '@tanstack/react-table' {\n interface FilterFns {\n fuzzy: FilterFn\n }\n interface FilterMeta {\n itemRank: RankingInfo\n }\n}\n\n// Define a custom fuzzy filter function that will apply ranking info to rows (using match-sorter utils)\nconst fuzzyFilter: FilterFn = (row, columnId, value, addMeta) => {\n // Rank the item\n const itemRank = rankItem(row.getValue(columnId), value)\n\n // Store the itemRank info\n addMeta({\n itemRank,\n })\n\n // Return if the item should be filtered in/out\n return itemRank.passed\n}\n\n// Define a custom fuzzy sort function that will sort by rank if the row has ranking information\nconst fuzzySort: SortingFn = (rowA, rowB, columnId) => {\n let dir = 0\n\n // Only sort by rank if the column has ranking information\n if (rowA.columnFiltersMeta[columnId]) {\n dir = compareItems(\n rowA.columnFiltersMeta[columnId]?.itemRank!,\n rowB.columnFiltersMeta[columnId]?.itemRank!,\n )\n }\n\n // Provide an alphanumeric fallback for when the item ranks are equal\n return dir === 0 ? sortingFns.alphanumeric(rowA, rowB, columnId) : dir\n}\n\nfunction TableDemo() {\n const rerender = React.useReducer(() => ({}), {})[1]\n\n const [columnFilters, setColumnFilters] = React.useState(\n [],\n )\n const [globalFilter, setGlobalFilter] = React.useState('')\n\n const columns = React.useMemo[]>(\n () => [\n {\n accessorKey: 'id',\n filterFn: 'equalsString', //note: normal non-fuzzy filter column - exact match required\n },\n {\n accessorKey: 'firstName',\n cell: (info) => info.getValue(),\n filterFn: 'includesStringSensitive', //note: normal non-fuzzy filter column - case sensitive\n },\n {\n accessorFn: (row) => row.lastName,\n id: 'lastName',\n cell: (info) => info.getValue(),\n header: () => Last Name,\n filterFn: 'includesString', //note: normal non-fuzzy filter column - case insensitive\n },\n {\n accessorFn: (row) => `${row.firstName} ${row.lastName}`,\n id: 'fullName',\n header: 'Full Name',\n cell: (info) => info.getValue(),\n filterFn: 'fuzzy', //using our custom fuzzy filter function\n // filterFn: fuzzyFilter, //or just define with the function\n sortingFn: fuzzySort, //sort by fuzzy rank (falls back to alphanumeric)\n },\n ],\n [],\n )\n\n const [data, setData] = React.useState(() => makeData(5_000))\n const refreshData = () => setData((_old) => makeData(50_000)) //stress test\n\n const table = useReactTable({\n data,\n columns,\n filterFns: {\n fuzzy: fuzzyFilter, //define as a filter function that can be used in column definitions\n },\n state: {\n columnFilters,\n globalFilter,\n },\n onColumnFiltersChange: setColumnFilters,\n onGlobalFilterChange: setGlobalFilter,\n globalFilterFn: 'fuzzy', //apply fuzzy filter to the global filter (most common use case for fuzzy filter)\n getCoreRowModel: getCoreRowModel(),\n getFilteredRowModel: getFilteredRowModel(), //client side filtering\n getSortedRowModel: getSortedRowModel(),\n getPaginationRowModel: getPaginationRowModel(),\n debugTable: true,\n debugHeaders: true,\n debugColumns: false,\n })\n\n //apply the fuzzy sort if the fullName column is being filtered\n React.useEffect(() => {\n if (table.getState().columnFilters[0]?.id === 'fullName') {\n if (table.getState().sorting[0]?.id !== 'fullName') {\n table.setSorting([{ id: 'fullName', desc: false }])\n }\n }\n }, [table.getState().columnFilters[0]?.id])\n\n return (\n
\n
\n

TanStack Table

\n

Table Demo

\n setGlobalFilter(String(value))}\n className=\"demo-input\"\n placeholder=\"Search all columns...\"\n />\n
\n
\n
\n \n \n {table.getHeaderGroups().map((headerGroup) => (\n \n {headerGroup.headers.map((header) => {\n return (\n \n {header.isPlaceholder ? null : (\n <>\n \n {flexRender(\n header.column.columnDef.header,\n header.getContext(),\n )}\n {{\n asc: ' 🔼',\n desc: ' 🔽',\n }[header.column.getIsSorted() as string] ?? null}\n \n {header.column.getCanFilter() ? (\n
\n \n
\n ) : null}\n \n )}\n \n )\n })}\n
\n ))}\n \n \n {table.getRowModel().rows.map((row) => {\n return (\n \n {row.getVisibleCells().map((cell) => {\n return (\n \n )\n })}\n \n )\n })}\n \n
\n {flexRender(\n cell.column.columnDef.cell,\n cell.getContext(),\n )}\n
\n
\n
\n
\n table.setPageIndex(0)}\n disabled={!table.getCanPreviousPage()}\n >\n {'<<'}\n \n table.previousPage()}\n disabled={!table.getCanPreviousPage()}\n >\n {'<'}\n \n table.nextPage()}\n disabled={!table.getCanNextPage()}\n >\n {'>'}\n \n table.setPageIndex(table.getPageCount() - 1)}\n disabled={!table.getCanNextPage()}\n >\n {'>>'}\n \n \n
Page
\n \n {table.getState().pagination.pageIndex + 1} of{' '}\n {table.getPageCount()}\n \n
\n \n | Go to page:\n {\n const page = e.target.value ? Number(e.target.value) - 1 : 0\n table.setPageIndex(page)\n }}\n className=\"demo-input demo-input-fit py-1\"\n />\n \n {\n table.setPageSize(Number(e.target.value))\n }}\n className=\"demo-select demo-input-fit py-1\"\n >\n {[10, 20, 30, 40, 50].map((pageSize) => (\n \n ))}\n \n
\n
\n {table.getPrePaginationRowModel().rows.length} Rows\n
\n
\n rerender()}\n className=\"demo-button\"\n >\n Force Rerender\n \n refreshData()}\n className=\"demo-button\"\n >\n Refresh Data\n \n
\n
\n        {JSON.stringify(\n          {\n            columnFilters: table.getState().columnFilters,\n            globalFilter: table.getState().globalFilter,\n          },\n          null,\n          2,\n        )}\n      
\n
\n )\n}\n\nfunction Filter({ column }: { column: Column }) {\n const columnFilterValue = column.getFilterValue()\n\n return (\n column.setFilterValue(value)}\n placeholder={`Search...`}\n className=\"demo-input py-1\"\n />\n )\n}\n\n// A typical debounced input react component\nfunction DebouncedInput({\n value: initialValue,\n onChange,\n debounce = 500,\n ...props\n}: {\n value: string | number\n onChange: (value: string | number) => void\n debounce?: number\n} & Omit, 'onChange'>) {\n const [value, setValue] = React.useState(initialValue)\n\n React.useEffect(() => {\n setValue(initialValue)\n }, [initialValue])\n\n React.useEffect(() => {\n const timeout = setTimeout(() => {\n onChange(value)\n }, debounce)\n\n return () => clearTimeout(timeout)\n }, [value])\n\n return (\n setValue(e.target.value)}\n />\n )\n}\n\n") if (codeRouter) { __append("\nexport default (parentRoute: RootRoute) => createRoute({\n path: '/demo/table',\n component: TableDemo,\n getParentRoute: () => parentRoute,\n})\n") } __append("\n") return __output } const templateRenderers: Record = { "cfd368cd:11500": __render_cfd368cd_11500, } export function hasManifestTemplate(template: string) { return getManifestTemplateKey(template) in templateRenderers } export function renderManifestTemplate( template: string, context: TemplateRenderContext, ) { const key = getManifestTemplateKey(template) const renderer = templateRenderers[key] if (!renderer) { throw new Error(`Template ${key} was not precompiled into the manifest`) } return renderer(context) ?? '' } export const addOn = { "name": "Table", "description": "Integrate TanStack Table into your application.", "phase": "add-on", "modes": [ "file-router", "code-router" ], "link": "https://tanstack.com/table/latest", "type": "add-on", "category": "tanstack", "color": "#06B6D4", "priority": 28, "routes": [ { "icon": "Table", "url": "/demo/table", "name": "TanStack Table", "path": "src/routes/demo.table.tsx", "jsName": "TableDemo" } ], "id": "table", "version": "0.0.0", "packageAdditions": { "dependencies": { "@faker-js/faker": "^10.3.0", "@tanstack/match-sorter-utils": "latest", "@tanstack/react-table": "latest" } }, "readmeIsEjs": false, "files": { "src/data/demo-table-data.ts": "import { faker } from '@faker-js/faker'\n\nexport type Person = {\n id: number\n firstName: string\n lastName: string\n age: number\n visits: number\n progress: number\n status: 'relationship' | 'complicated' | 'single'\n subRows?: Person[]\n}\n\nconst range = (len: number) => {\n const arr: number[] = []\n for (let i = 0; i < len; i++) {\n arr.push(i)\n }\n return arr\n}\n\nconst newPerson = (num: number): Person => {\n return {\n id: num,\n firstName: faker.person.firstName(),\n lastName: faker.person.lastName(),\n age: faker.number.int(40),\n visits: faker.number.int(1000),\n progress: faker.number.int(100),\n status: faker.helpers.shuffle([\n 'relationship',\n 'complicated',\n 'single',\n ])[0]!,\n }\n}\n\nexport function makeData(...lens: number[]) {\n const makeDataLevel = (depth = 0): Person[] => {\n const len = lens[depth]!\n return range(len).map((index): Person => {\n return {\n ...newPerson(index),\n subRows: lens[depth + 1] ? makeDataLevel(depth + 1) : undefined,\n }\n })\n }\n\n return makeDataLevel()\n}\n", "src/routes/demo/table.tsx.ejs": "import React from 'react'\nimport { <% if (fileRouter) { %>createFileRoute<% } else { %>createRoute<% } %> } from '@tanstack/react-router'\nimport {\n flexRender,\n getCoreRowModel,\n getFilteredRowModel,\n getPaginationRowModel,\n getSortedRowModel,\n sortingFns,\n useReactTable,\n} from '@tanstack/react-table'\nimport { compareItems, rankItem } from '@tanstack/match-sorter-utils'\n\nimport { makeData } from '#/data/demo-table-data'\n\nimport type {\n Column,\n ColumnDef,\n ColumnFiltersState,\n FilterFn,\n SortingFn,\n} from '@tanstack/react-table'\nimport type { RankingInfo } from '@tanstack/match-sorter-utils'\n<% if (codeRouter) { %>\nimport type { RootRoute } from '@tanstack/react-router'\n<% } %>\nimport type { Person } from '#/data/demo-table-data'\n<% if (fileRouter) { %>\nexport const Route = createFileRoute('/demo/table')({\n component: TableDemo,\n})\n<% } %>\n\ndeclare module '@tanstack/react-table' {\n interface FilterFns {\n fuzzy: FilterFn\n }\n interface FilterMeta {\n itemRank: RankingInfo\n }\n}\n\n// Define a custom fuzzy filter function that will apply ranking info to rows (using match-sorter utils)\nconst fuzzyFilter: FilterFn = (row, columnId, value, addMeta) => {\n // Rank the item\n const itemRank = rankItem(row.getValue(columnId), value)\n\n // Store the itemRank info\n addMeta({\n itemRank,\n })\n\n // Return if the item should be filtered in/out\n return itemRank.passed\n}\n\n// Define a custom fuzzy sort function that will sort by rank if the row has ranking information\nconst fuzzySort: SortingFn = (rowA, rowB, columnId) => {\n let dir = 0\n\n // Only sort by rank if the column has ranking information\n if (rowA.columnFiltersMeta[columnId]) {\n dir = compareItems(\n rowA.columnFiltersMeta[columnId]?.itemRank!,\n rowB.columnFiltersMeta[columnId]?.itemRank!,\n )\n }\n\n // Provide an alphanumeric fallback for when the item ranks are equal\n return dir === 0 ? sortingFns.alphanumeric(rowA, rowB, columnId) : dir\n}\n\nfunction TableDemo() {\n const rerender = React.useReducer(() => ({}), {})[1]\n\n const [columnFilters, setColumnFilters] = React.useState(\n [],\n )\n const [globalFilter, setGlobalFilter] = React.useState('')\n\n const columns = React.useMemo[]>(\n () => [\n {\n accessorKey: 'id',\n filterFn: 'equalsString', //note: normal non-fuzzy filter column - exact match required\n },\n {\n accessorKey: 'firstName',\n cell: (info) => info.getValue(),\n filterFn: 'includesStringSensitive', //note: normal non-fuzzy filter column - case sensitive\n },\n {\n accessorFn: (row) => row.lastName,\n id: 'lastName',\n cell: (info) => info.getValue(),\n header: () => Last Name,\n filterFn: 'includesString', //note: normal non-fuzzy filter column - case insensitive\n },\n {\n accessorFn: (row) => `${row.firstName} ${row.lastName}`,\n id: 'fullName',\n header: 'Full Name',\n cell: (info) => info.getValue(),\n filterFn: 'fuzzy', //using our custom fuzzy filter function\n // filterFn: fuzzyFilter, //or just define with the function\n sortingFn: fuzzySort, //sort by fuzzy rank (falls back to alphanumeric)\n },\n ],\n [],\n )\n\n const [data, setData] = React.useState(() => makeData(5_000))\n const refreshData = () => setData((_old) => makeData(50_000)) //stress test\n\n const table = useReactTable({\n data,\n columns,\n filterFns: {\n fuzzy: fuzzyFilter, //define as a filter function that can be used in column definitions\n },\n state: {\n columnFilters,\n globalFilter,\n },\n onColumnFiltersChange: setColumnFilters,\n onGlobalFilterChange: setGlobalFilter,\n globalFilterFn: 'fuzzy', //apply fuzzy filter to the global filter (most common use case for fuzzy filter)\n getCoreRowModel: getCoreRowModel(),\n getFilteredRowModel: getFilteredRowModel(), //client side filtering\n getSortedRowModel: getSortedRowModel(),\n getPaginationRowModel: getPaginationRowModel(),\n debugTable: true,\n debugHeaders: true,\n debugColumns: false,\n })\n\n //apply the fuzzy sort if the fullName column is being filtered\n React.useEffect(() => {\n if (table.getState().columnFilters[0]?.id === 'fullName') {\n if (table.getState().sorting[0]?.id !== 'fullName') {\n table.setSorting([{ id: 'fullName', desc: false }])\n }\n }\n }, [table.getState().columnFilters[0]?.id])\n\n return (\n
\n
\n

TanStack Table

\n

Table Demo

\n setGlobalFilter(String(value))}\n className=\"demo-input\"\n placeholder=\"Search all columns...\"\n />\n
\n
\n
\n \n \n {table.getHeaderGroups().map((headerGroup) => (\n \n {headerGroup.headers.map((header) => {\n return (\n \n {header.isPlaceholder ? null : (\n <>\n \n {flexRender(\n header.column.columnDef.header,\n header.getContext(),\n )}\n {{\n asc: ' 🔼',\n desc: ' 🔽',\n }[header.column.getIsSorted() as string] ?? null}\n \n {header.column.getCanFilter() ? (\n
\n \n
\n ) : null}\n \n )}\n \n )\n })}\n
\n ))}\n \n \n {table.getRowModel().rows.map((row) => {\n return (\n \n {row.getVisibleCells().map((cell) => {\n return (\n \n )\n })}\n \n )\n })}\n \n
\n {flexRender(\n cell.column.columnDef.cell,\n cell.getContext(),\n )}\n
\n
\n
\n
\n table.setPageIndex(0)}\n disabled={!table.getCanPreviousPage()}\n >\n {'<<'}\n \n table.previousPage()}\n disabled={!table.getCanPreviousPage()}\n >\n {'<'}\n \n table.nextPage()}\n disabled={!table.getCanNextPage()}\n >\n {'>'}\n \n table.setPageIndex(table.getPageCount() - 1)}\n disabled={!table.getCanNextPage()}\n >\n {'>>'}\n \n \n
Page
\n \n {table.getState().pagination.pageIndex + 1} of{' '}\n {table.getPageCount()}\n \n
\n \n | Go to page:\n {\n const page = e.target.value ? Number(e.target.value) - 1 : 0\n table.setPageIndex(page)\n }}\n className=\"demo-input demo-input-fit py-1\"\n />\n \n {\n table.setPageSize(Number(e.target.value))\n }}\n className=\"demo-select demo-input-fit py-1\"\n >\n {[10, 20, 30, 40, 50].map((pageSize) => (\n \n ))}\n \n
\n
\n {table.getPrePaginationRowModel().rows.length} Rows\n
\n
\n rerender()}\n className=\"demo-button\"\n >\n Force Rerender\n \n refreshData()}\n className=\"demo-button\"\n >\n Refresh Data\n \n
\n
\n        {JSON.stringify(\n          {\n            columnFilters: table.getState().columnFilters,\n            globalFilter: table.getState().globalFilter,\n          },\n          null,\n          2,\n        )}\n      
\n
\n )\n}\n\nfunction Filter({ column }: { column: Column }) {\n const columnFilterValue = column.getFilterValue()\n\n return (\n column.setFilterValue(value)}\n placeholder={`Search...`}\n className=\"demo-input py-1\"\n />\n )\n}\n\n// A typical debounced input react component\nfunction DebouncedInput({\n value: initialValue,\n onChange,\n debounce = 500,\n ...props\n}: {\n value: string | number\n onChange: (value: string | number) => void\n debounce?: number\n} & Omit, 'onChange'>) {\n const [value, setValue] = React.useState(initialValue)\n\n React.useEffect(() => {\n setValue(initialValue)\n }, [initialValue])\n\n React.useEffect(() => {\n const timeout = setTimeout(() => {\n onChange(value)\n }, debounce)\n\n return () => clearTimeout(timeout)\n }, [value])\n\n return (\n setValue(e.target.value)}\n />\n )\n}\n\n<% if (codeRouter) { %>\nexport default (parentRoute: RootRoute) => createRoute({\n path: '/demo/table',\n component: TableDemo,\n getParentRoute: () => parentRoute,\n})\n<% } %>\n" }, "deletedFiles": [], "smallLogo": "" } satisfies AddOnCompiled