Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions docs/config.json
Original file line number Diff line number Diff line change
Expand Up @@ -463,6 +463,10 @@
{
"to": "framework/lit/examples/sorting",
"label": "Sorting"
},
{
"to": "framework/lit/examples/virtualized-rows",
"label": "Virtualized Rows"
}
]
},
Expand Down
5 changes: 5 additions & 0 deletions examples/lit/virtualized-rows/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
node_modules
.DS_Store
dist
dist-ssr
*.local
6 changes: 6 additions & 0 deletions examples/lit/virtualized-rows/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
# Example

To run this example:

- `npm install` or `yarn`
- `npm run start` or `yarn start`
14 changes: 14 additions & 0 deletions examples/lit/virtualized-rows/index.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Vite App</title>
<script type="module" src="https://cdn.skypack.dev/twind/shim"></script>
</head>
<body>
<div id="root"></div>
<script type="module" src="/src/main.ts"></script>
<lit-table-example></lit-table-example>
</body>
</html>
22 changes: 22 additions & 0 deletions examples/lit/virtualized-rows/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
{
"name": "tanstack-lit-table-virtualized-rows",
"version": "0.0.0",
"private": true,
"scripts": {
"dev": "vite",
"build": "vite build",
"serve": "vite preview",
"start": "vite"
},
"dependencies": {
"@faker-js/faker": "^8.4.1",
"@lit-labs/virtualizer": "^2.0.13",
"@tanstack/lit-table": "^8.19.1",
"lit": "^3.1.3"
},
"devDependencies": {
"@rollup/plugin-replace": "^5.0.5",
"typescript": "5.4.5",
"vite": "^5.2.10"
}
}
211 changes: 211 additions & 0 deletions examples/lit/virtualized-rows/src/main.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,211 @@
import { customElement } from 'lit/decorators.js'
import { html, LitElement } from 'lit'
import { repeat } from 'lit/directives/repeat.js'
import {
ColumnDef,
flexRender,
getCoreRowModel,
getSortedRowModel,
TableController,
} from '@tanstack/lit-table'
import config from '../twind.config'
import { styleMap } from 'lit/directives/style-map.js'
import { virtualize, virtualizerRef } from '@lit-labs/virtualizer/virtualize.js'
import { makeData, Person } from './makeData.ts'

const columns: ColumnDef<Person>[] = [
{
accessorKey: 'id',
header: 'ID',
size: 60,
},
{
accessorKey: 'firstName',
cell: info => info.getValue(),
},
{
accessorFn: row => row.lastName,
id: 'lastName',
cell: info => info.getValue(),
header: () => html`<span>Last Name</span>`,
},
{
accessorKey: 'age',
header: () => 'Age',
size: 50,
},
{
accessorKey: 'visits',
header: () => html`<span>Visits</span>`,
size: 50,
},
{
accessorKey: 'status',
header: 'Status',
},
{
accessorKey: 'progress',
header: 'Profile Progress',
size: 80,
},
{
accessorKey: 'createdAt',
header: 'Created At',
cell: info => info.getValue<Date>().toLocaleString(),
size: 250,
},
]
const data = makeData(50_000)

@customElement('lit-table-example')
class LitTableExample extends LitElement {
private tableController = new TableController<Person>(this)

protected render(): unknown {
const table = this.tableController.table({
columns,
data,
getSortedRowModel: getSortedRowModel(),
getCoreRowModel: getCoreRowModel(),
})
const { rows } = table.getRowModel()
return html`
<div class="app">
(${data.length} rows)
<div
class="container"
style="${styleMap({
overflow: 'auto', //our scrollable table container
position: 'relative', //needed for sticky header
height: '800px', //should be a fixed height
})}"
>
<table style="display: grid">
<thead
style="${styleMap({
display: 'grid',
position: 'sticky',
top: 0,
zIndex: 1,
})}"
>
${repeat(
table.getHeaderGroups(),
headerGroup => headerGroup.id,
headerGroup => html`
<tr style="${styleMap({ display: 'flex', width: '100%' })}">
${repeat(
headerGroup.headers,
header => header.id,
header => html`
<th
style="${styleMap({
display: 'flex',
width: `${header.getSize()}px`,
})}"
@click="${header.column.getToggleSortingHandler()}"
>
${flexRender(
header.column.columnDef.header,
header.getContext()
)}
${{ asc: ' 🔼', desc: ' 🔽' }[
header.column.getIsSorted() as string
] ?? null}
</th>
`
)}
</tr>
`
)}
</thead>
<tbody
style=${styleMap({
display: 'grid',
height: 500,
// height: `${rowVirtualizer.getTotalSize()}px`, //tells scrollbar how big the table is
position: 'relative', //needed for absolute positioning of rows
})}
>
${virtualize({
items: data,
renderItem: (_, index) => {
const row = rows[index]
return html`
<tr
style=${styleMap({
display: 'flex',
width: '100%',
})}
>
${repeat(
row.getVisibleCells(),
cell => cell.id,
cell => html`
<td
style=${styleMap({
display: 'flex',
width: `${cell.column.getSize()}px`,
})}
>
${flexRender(
cell.column.columnDef.cell,
cell.getContext()
)}
</td>
`
)}
</tr>
`
},
})}
</tbody>
</table>
</div>
</div>

<style>
html {
font-family: sans-serif;
font-size: 14px;
}

table {
border-collapse: collapse;
border-spacing: 0;
font-family: arial, sans-serif;
table-layout: fixed;
}

thead {
background: lightgray;
}

tr {
border-bottom: 1px solid lightgray;
}

th {
border-bottom: 1px solid lightgray;
border-right: 1px solid lightgray;
padding: 2px 4px;
text-align: left;
}

td {
padding: 6px;
}

.container {
border: 1px solid lightgray;
margin: 1rem auto;
}

.app {
margin: 1rem auto;
text-align: center;
}
</style>
`
}
}
50 changes: 50 additions & 0 deletions examples/lit/virtualized-rows/src/makeData.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
import { faker } from '@faker-js/faker'

export type Person = {
id: number
firstName: string
lastName: string
age: number
visits: number
progress: number
status: 'relationship' | 'complicated' | 'single'
createdAt: Date
}

const range = (len: number) => {
const arr: number[] = []
for (let i = 0; i < len; i++) {
arr.push(i)
}
return arr
}

const newPerson = (index: number): Person => {
return {
id: index + 1,
firstName: faker.person.firstName(),
lastName: faker.person.lastName(),
age: faker.number.int(40),
visits: faker.number.int(1000),
progress: faker.number.int(100),
createdAt: faker.date.anytime(),
status: faker.helpers.shuffle<Person['status']>([
'relationship',
'complicated',
'single',
])[0]!,
}
}

export function makeData(...lens: number[]) {
const makeDataLevel = (depth = 0): Person[] => {
const len = lens[depth]!
return range(len).map((d): Person => {
return {
...newPerson(d),
}
})
}

return makeDataLevel()
}
26 changes: 26 additions & 0 deletions examples/lit/virtualized-rows/tsconfig.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
{
"compilerOptions": {
"target": "ES2020",
"lib": ["ES2020", "DOM", "DOM.Iterable"],
"module": "ESNext",
"skipLibCheck": true,

/* Bundler mode */
"moduleResolution": "bundler",
"allowImportingTsExtensions": true,
"resolveJsonModule": true,
"isolatedModules": true,
"emitDecoratorMetadata": true,
"noEmit": true,
"jsx": "react-jsx",
"experimentalDecorators": true,
"useDefineForClassFields": false,

/* Linting */
"strict": true,
"noUnusedLocals": false,
"noUnusedParameters": true,
"noFallthroughCasesInSwitch": true
},
"include": ["src"]
}
7 changes: 7 additions & 0 deletions examples/lit/virtualized-rows/twind.config.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
import { defineConfig } from '@twind/core'
import presetAutoprefix from '@twind/preset-autoprefix'
import presetTailwind from '@twind/preset-tailwind/base'

export default defineConfig({
presets: [presetAutoprefix(), presetTailwind()],
})
15 changes: 15 additions & 0 deletions examples/lit/virtualized-rows/vite.config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
import { defineConfig } from 'vite'
import rollupReplace from '@rollup/plugin-replace'

// https://vitejs.dev/config/
export default defineConfig({
plugins: [
rollupReplace({
preventAssignment: true,
values: {
__DEV__: JSON.stringify(true),
'process.env.NODE_ENV': JSON.stringify('development'),
},
}),
],
})
Loading