Skip to content

Commit 521dce1

Browse files
committed
wip: add og react-virtuoso
1 parent a45dcbc commit 521dce1

File tree

198 files changed

+16943
-0
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

198 files changed

+16943
-0
lines changed

.gitmodules

+1
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
11
[submodule "packages/message-list"]
22
path = packages/message-list
33
url = git@github.com:virtuoso-dev/message-list.git
4+
branch = monorepo

common/config/rush/pnpm-lock.yaml

+125
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

packages/react-virtuoso/LICENSE

+21
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
MIT License
2+
3+
Copyright (c) 2020 Petyo Ivanov
4+
5+
Permission is hereby granted, free of charge, to any person obtaining a copy
6+
of this software and associated documentation files (the "Software"), to deal
7+
in the Software without restriction, including without limitation the rights
8+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9+
copies of the Software, and to permit persons to whom the Software is
10+
furnished to do so, subject to the following conditions:
11+
12+
The above copyright notice and this permission notice shall be included in all
13+
copies or substantial portions of the Software.
14+
15+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21+
SOFTWARE.

packages/react-virtuoso/README.md

+102
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,102 @@
1+
<img src="https://user-images.githubusercontent.com/13347/101237112-ec4c6000-36de-11eb-936d-4b6b7ec94976.png" width="229" />
2+
3+
[![npm version](https://img.shields.io/npm/v/react-virtuoso.svg?style=flat)](//badge.fury.io/js/react-virtuoso)
4+
5+
**React Virtuoso** - the most complete React virtualization rendering list/table/grid family of components.
6+
7+
- Variable sized items out of the box; no manual measurements or hard-coding item heights is necessary;
8+
- [Chat message list UI](https://virtuoso.dev/virtuoso-message-list/) **NEW**;
9+
- [Grouped mode with sticky headers](https://virtuoso.dev/grouped-by-first-letter/);
10+
- [Responsive grid layout](https://virtuoso.dev/grid-responsive-columns/);
11+
- [Table Support](https://virtuoso.dev/hello-table/);
12+
- [Automatic handling of content resize](https://virtuoso.dev/auto-resizing/);
13+
- [Custom Header, Footer, and empty list components](https://virtuoso.dev/customize-structure/);
14+
- [Pinned top items](https://virtuoso.dev/top-items/);
15+
- [Endless scrolling](https://virtuoso.dev/endless-scrolling/), [press to load more](https://virtuoso.dev/press-to-load-more/);
16+
- [Initial top most item index](https://virtuoso.dev/initial-index/);
17+
- [Scroll to index method](https://virtuoso.dev/scroll-to-index/).
18+
19+
For live examples and documentation, check the [documentation website](https://virtuoso.dev).
20+
21+
## Sponsors
22+
23+
If you are using Virtuoso for work, [sponsor it](https://github.com/sponsors/petyosi). Any donation helps a lot with the project development and maintenance.
24+
25+
## Get Started
26+
27+
```sh
28+
npm install react-virtuoso
29+
```
30+
31+
```jsx
32+
import * as React from 'react'
33+
import * as ReactDOM from 'react-dom'
34+
import { Virtuoso } from 'react-virtuoso'
35+
36+
const App = () => {
37+
return <Virtuoso style={{ height: '400px' }} totalCount={200} itemContent={index => <div>Item {index}</div>} />
38+
}
39+
40+
ReactDOM.render(<App />, document.getElementById('root'))
41+
```
42+
43+
## [Message List](https://virtuoso.dev/virtuoso-message-list/)
44+
45+
The Virtuoso message list component is built specifically for human/chatbot conversations. In addition to the virtualized rendering, the component exposes an imperative data management
46+
API that gives you the necessary control over the scroll position when older messages are loaded, new messages arrive, and when the user submits a message. The scroll position can update instantly or with a smooth scroll animation.
47+
48+
## [Grouped Mode](https://virtuoso.dev/grouped-by-first-letter/)
49+
50+
The `GroupedVirtuoso` component is a variant of the "flat" `Virtuoso`, with the following differences:
51+
52+
- Instead of `totalCount`, the component exposes `groupCounts: number[]` property, which specifies the amount of items in each group.
53+
For example, passing `[20, 30]` will render two groups with 20 and 30 items each;
54+
- In addition the `itemContent` property, the component requires an additional `groupContent` property,
55+
which renders the **group header**. The `groupContent` callback receives the zero-based group index as a parameter.
56+
57+
## [Grid](https://virtuoso.dev/grid-responsive-columns/)
58+
59+
The `VirtuosoGrid` component displays **same sized items** in multiple columns.
60+
The layout and item sizing is controlled through CSS class properties, which allows you to use media queries, min-width, percentage, etc.
61+
62+
## [Table](https://virtuoso.dev/hello-table/)
63+
64+
The `TableVirtuoso` component works just like `Virtuoso`, but with HTML tables.
65+
It supports window scrolling, sticky headers, sticky columns, and works with React Table and MUI Table.
66+
67+
## Works With Your UI Library of Choice
68+
69+
You can customize the markup up to your requirements - check [the Material UI list demo](https://virtuoso.dev/material-ui-endless-scrolling/).
70+
If you need to support reordering, [check the React Sortable HOC example](https://virtuoso.dev/react-sortable-hoc/).
71+
72+
## Documentation and Demos
73+
74+
For in-depth documentation and live examples of the supported features and live demos, check the [documentation website](https://virtuoso.dev).
75+
76+
## Browser support
77+
78+
To support [legacy browsers](https://caniuse.com/resizeobserver), you might have to load a [ResizeObserver Polyfill](https://www.npmjs.com/package/resize-observer-polyfill) before using `react-virtuoso`:
79+
80+
```
81+
import ResizeObserver from 'resize-observer-polyfill'
82+
if (!window.ResizeObserver)
83+
window.ResizeObserver = ResizeObserver
84+
```
85+
86+
## Author
87+
88+
Petyo Ivanov [@petyosi](//twitter.com/petyosi).
89+
90+
## Contributing
91+
92+
### Fixes and new Features
93+
94+
To run the tests, use `npm run test`.
95+
An end-to-end browser-based test suite is runnable with `npm run e2e`, with the pages being `e2e/*.tsx` and the tests `e2e/*.test.ts`.
96+
97+
A convenient way to debug something is to preview the test cases in the browser.
98+
To do that, run `npm run dev` - it will launch a Ladle server that lets you browse the components in the `examples` folder.
99+
100+
## License
101+
102+
MIT License.

packages/react-virtuoso/biome.jsonc

+14
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
{
2+
"$schema": "https://biomejs.dev/schemas/1.9.4/schema.json",
3+
"extends": ["../../biome.jsonc"],
4+
"linter": {
5+
"rules": {
6+
"style": {
7+
"noNonNullAssertion": "off"
8+
},
9+
"suspicious": {
10+
"noExplicitAny": "info"
11+
}
12+
}
13+
}
14+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
import { test, expect } from '@playwright/test'
2+
//@ts-expect-error - type module and playwright
3+
import { navigateToExample } from './utils.ts'
4+
5+
test.describe('list with collapsible long items', () => {
6+
test.beforeEach(async ({ page, baseURL }) => {
7+
await navigateToExample(page, baseURL, 'collapsible-long-item')
8+
await page.waitForSelector('[data-testid=virtuoso-scroller]')
9+
await page.waitForTimeout(200)
10+
})
11+
12+
test('compensates correctly when collapsing an item', async ({ page }) => {
13+
await page.evaluate(() => {
14+
const scroller = document.querySelector('[data-testid=virtuoso-scroller]')!
15+
scroller.scrollBy({ top: -400 })
16+
})
17+
18+
await page.waitForTimeout(500)
19+
20+
await page.evaluate(() => {
21+
const button = document.querySelector('[data-index="90"] button') as HTMLButtonElement
22+
button.click()
23+
})
24+
25+
await page.waitForTimeout(200)
26+
27+
const scrollTop = await page.evaluate(() => {
28+
const scroller = document.querySelector('[data-testid=virtuoso-scroller]')!
29+
return scroller.scrollTop
30+
})
31+
32+
expect(scrollTop).toBe(9200)
33+
})
34+
})
+40
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
import { test, expect } from '@playwright/test'
2+
//@ts-expect-error - type module and playwright
3+
import { navigateToExample } from './utils.ts'
4+
5+
test.describe('list with hundred items', () => {
6+
test.beforeEach(async ({ page, baseURL }) => {
7+
await navigateToExample(page, baseURL, 'data')
8+
await page.waitForSelector('[data-testid=virtuoso-scroller]')
9+
await page.waitForTimeout(100)
10+
})
11+
12+
test('renders 10 items', async ({ page }) => {
13+
const itemCount = await page.evaluate(() => {
14+
const listContainer = document.querySelector('[data-testid=virtuoso-item-list]')!
15+
return listContainer.childElementCount
16+
})
17+
expect(itemCount).toBe(10)
18+
})
19+
20+
test('fills in the scroller', async ({ page }) => {
21+
const scrollHeight = await page.evaluate(() => {
22+
const scroller = document.querySelector('[data-testid=virtuoso-scroller]')!
23+
return scroller.scrollHeight
24+
})
25+
expect(scrollHeight).toBe(100 * 30)
26+
})
27+
28+
test('increases the items', async ({ page }) => {
29+
await page.evaluate(() => {
30+
document.querySelector('button')!.click()
31+
})
32+
33+
const scrollHeight = await page.evaluate(() => {
34+
const scroller = document.querySelector('[data-testid=virtuoso-scroller]')!
35+
return scroller.scrollHeight
36+
})
37+
38+
expect(scrollHeight).toBe(120 * 30)
39+
})
40+
})
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
import { test, expect } from '@playwright/test'
2+
//@ts-expect-error - type module and playwright
3+
import { navigateToExample } from './utils.ts'
4+
5+
test.describe('list with hundred items', () => {
6+
test.beforeEach(async ({ page, baseURL }) => {
7+
await navigateToExample(page, baseURL, 'follow-output-loading-image')
8+
await page.waitForTimeout(100)
9+
})
10+
11+
test('scrolls to bottom when image is loaded', async ({ page }) => {
12+
await page.locator('data-testid=add-image').click()
13+
await page.waitForTimeout(800)
14+
const scrollTop = await page.locator('data-testid=virtuoso-scroller').evaluate((el) => el.scrollTop)
15+
expect(scrollTop).toBe(2800)
16+
})
17+
})

0 commit comments

Comments
 (0)