Skip to content

Commit 005255d

Browse files
committed
Add basic preact integration
1 parent 5d6acc9 commit 005255d

File tree

14 files changed

+503
-1
lines changed

14 files changed

+503
-1
lines changed

docs/config.json

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,15 @@
2222
}
2323
]
2424
},
25+
{
26+
"label": "preact",
27+
"children": [
28+
{
29+
"label": "Preact Virtual",
30+
"to": "framework/preact/preact-virtual"
31+
}
32+
]
33+
},
2534
{
2635
"label": "angular",
2736
"children": [
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
---
2+
title: Preact Virtual
3+
---
4+
5+
The `@tanstack/preact-virtual` adapter is a wrapper around the core virtual logic.
6+
7+
## `useVirtualizer`
8+
9+
```tsx
10+
function useVirtualizer<TScrollElement, TItemElement = unknown>(
11+
options: PartialKeys<
12+
VirtualizerOptions<TScrollElement, TItemElement>,
13+
'observeElementRect' | 'observeElementOffset' | 'scrollToFn'
14+
>,
15+
): Virtualizer<TScrollElement, TItemElement>
16+
```
17+
18+
This function returns a standard `Virtualizer` instance configured to work with an HTML element as the scrollElement.
19+
20+
## `useWindowVirtualizer`
21+
22+
```tsx
23+
function useWindowVirtualizer<TItemElement = unknown>(
24+
options: PartialKeys<
25+
VirtualizerOptions<Window, TItemElement>,
26+
| 'getScrollElement'
27+
| 'observeElementRect'
28+
| 'observeElementOffset'
29+
| 'scrollToFn'
30+
>,
31+
): Virtualizer<Window, TItemElement>
32+
```
33+
34+
This function returns a window-based `Virtualizer` instance configured to work with the window as the scrollElement.

docs/installation.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,12 @@ Install your TanStack Virtual adapter as a dependency using your favorite npm pa
1212
npm install @tanstack/react-virtual
1313
```
1414

15+
## Preact Virtual
16+
17+
```bash
18+
npm install @tanstack/preact-virtual
19+
```
20+
1521
## Solid Virtual
1622

1723
```bash

docs/introduction.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
title: Introduction
33
---
44

5-
TanStack Virtual is a headless UI utility for virtualizing long lists of elements in JS/TS, React, Vue, Svelte, Solid, Lit, and Angular. It is not a component therefore does not ship with or render any markup or styles for you. While this requires a bit of markup and styles from you, you will retain 100% control over your styles, design and implementation.
5+
TanStack Virtual is a headless UI utility for virtualizing long lists of elements in JS/TS, React, Preact, Vue, Svelte, Solid, Lit, and Angular. It is not a component therefore does not ship with or render any markup or styles for you. While this requires a bit of markup and styles from you, you will retain 100% control over your styles, design and implementation.
66

77
## The Virtualizer
88

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
# @tanstack/preact-virtual
2+
3+
## 3.13.18
4+
5+
### Patch Changes
6+
7+
- Initial Preact adapter release.
8+
9+
### Dependencies
10+
11+
- Updated dependency [`@tanstack/virtual-core`](../virtual-core/CHANGELOG.md)
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
// @ts-check
2+
3+
import rootConfig from '../../eslint.config.js'
4+
5+
export default [...rootConfig]
Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
{
2+
"name": "@tanstack/preact-virtual",
3+
"version": "3.13.18",
4+
"description": "Headless UI for virtualizing scrollable elements in Preact",
5+
"author": "Tanner Linsley",
6+
"license": "MIT",
7+
"repository": {
8+
"type": "git",
9+
"url": "git+https://github.com/TanStack/virtual.git",
10+
"directory": "packages/preact-virtual"
11+
},
12+
"homepage": "https://tanstack.com/virtual",
13+
"funding": {
14+
"type": "github",
15+
"url": "https://github.com/sponsors/tannerlinsley"
16+
},
17+
"keywords": [
18+
"preact",
19+
"virtual",
20+
"virtual-core",
21+
"datagrid"
22+
],
23+
"scripts": {
24+
"clean": "premove ./dist ./coverage",
25+
"test:eslint": "eslint ./src",
26+
"test:types": "tsc",
27+
"test:lib": "vitest",
28+
"test:lib:dev": "pnpm run test:lib --watch",
29+
"test:build": "publint --strict",
30+
"build": "vite build"
31+
},
32+
"type": "module",
33+
"types": "dist/esm/index.d.ts",
34+
"main": "dist/cjs/index.cjs",
35+
"module": "dist/esm/index.js",
36+
"exports": {
37+
".": {
38+
"import": {
39+
"types": "./dist/esm/index.d.ts",
40+
"default": "./dist/esm/index.js"
41+
},
42+
"require": {
43+
"types": "./dist/cjs/index.d.cts",
44+
"default": "./dist/cjs/index.cjs"
45+
}
46+
},
47+
"./package.json": "./package.json"
48+
},
49+
"sideEffects": false,
50+
"files": [
51+
"dist",
52+
"src"
53+
],
54+
"dependencies": {
55+
"@tanstack/virtual-core": "workspace:*"
56+
},
57+
"devDependencies": {
58+
"preact": "^10.27.2"
59+
},
60+
"peerDependencies": {
61+
"preact": "^10.0.0"
62+
}
63+
}
Lines changed: 85 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,85 @@
1+
import { useEffect, useLayoutEffect, useState } from 'preact/hooks'
2+
import {
3+
Virtualizer,
4+
elementScroll,
5+
observeElementOffset,
6+
observeElementRect,
7+
observeWindowOffset,
8+
observeWindowRect,
9+
windowScroll,
10+
} from '@tanstack/virtual-core'
11+
import type { PartialKeys, VirtualizerOptions } from '@tanstack/virtual-core'
12+
13+
export * from '@tanstack/virtual-core'
14+
15+
const useIsomorphicLayoutEffect =
16+
typeof document !== 'undefined' ? useLayoutEffect : useEffect
17+
18+
function useVirtualizerBase<
19+
TScrollElement extends Element | Window,
20+
TItemElement extends Element,
21+
>(
22+
options: VirtualizerOptions<TScrollElement, TItemElement>,
23+
): Virtualizer<TScrollElement, TItemElement> {
24+
const [, rerender] = useState(0)
25+
26+
const resolvedOptions: VirtualizerOptions<TScrollElement, TItemElement> = {
27+
...options,
28+
onChange: (instance, sync) => {
29+
rerender((d) => d + 1)
30+
options.onChange?.(instance, sync)
31+
},
32+
}
33+
34+
const [instance] = useState(
35+
() => new Virtualizer<TScrollElement, TItemElement>(resolvedOptions),
36+
)
37+
38+
instance.setOptions(resolvedOptions)
39+
40+
useIsomorphicLayoutEffect(() => {
41+
return instance._didMount()
42+
}, [])
43+
44+
useIsomorphicLayoutEffect(() => {
45+
return instance._willUpdate()
46+
})
47+
48+
return instance
49+
}
50+
51+
export function useVirtualizer<
52+
TScrollElement extends Element,
53+
TItemElement extends Element,
54+
>(
55+
options: PartialKeys<
56+
VirtualizerOptions<TScrollElement, TItemElement>,
57+
'observeElementRect' | 'observeElementOffset' | 'scrollToFn'
58+
>,
59+
): Virtualizer<TScrollElement, TItemElement> {
60+
return useVirtualizerBase<TScrollElement, TItemElement>({
61+
observeElementRect: observeElementRect,
62+
observeElementOffset: observeElementOffset,
63+
scrollToFn: elementScroll,
64+
...options,
65+
})
66+
}
67+
68+
export function useWindowVirtualizer<TItemElement extends Element>(
69+
options: PartialKeys<
70+
VirtualizerOptions<Window, TItemElement>,
71+
| 'getScrollElement'
72+
| 'observeElementRect'
73+
| 'observeElementOffset'
74+
| 'scrollToFn'
75+
>,
76+
): Virtualizer<Window, TItemElement> {
77+
return useVirtualizerBase<Window, TItemElement>({
78+
getScrollElement: () => (typeof document !== 'undefined' ? window : null),
79+
observeElementRect: observeWindowRect,
80+
observeElementOffset: observeWindowOffset,
81+
scrollToFn: windowScroll,
82+
initialOffset: () => (typeof document !== 'undefined' ? window.scrollY : 0),
83+
...options,
84+
})
85+
}

0 commit comments

Comments
 (0)