Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
58 commits
Select commit Hold shift + click to select a range
84f5792
Remove Array.prototype.includes() usage from website to unbreak IE11
Jan 15, 2019
f8cf9fa
Removed use of Array.prototype.fill to unbreak IE11
Jan 15, 2019
a83c5cd
Updated getDerivedState Flow annotations to address a warning in a ne…
Jan 28, 2019
a22f3e9
1.5.0 -> 1.5.1
Jan 28, 2019
09717d8
Handle case when number of element reduces in list
iamsolankiamit Feb 18, 2019
3a398a1
Update VariableSizeList.js
iamsolankiamit Feb 18, 2019
eabe58f
Added tests and fixed same potential bug in VariableSizeGrid
Feb 19, 2019
7c3c558
1.5.2
Feb 19, 2019
a9e792b
Create LICENSE.md
ShoeIace Feb 21, 2019
44c0200
Merge pull request #142 from ShoeIace/patch-1
bvaughn Feb 21, 2019
cdf8454
Add RTL support for List component
davidgarsan Mar 1, 2019
ebdb131
Fix lint error
davidgarsan Mar 1, 2019
97bd7e0
Grid scrollToItem() takes scrollbar size into consideration
Mar 2, 2019
c747a29
Only count scrollbar size in scrollToItem() when scrolling is required
Mar 3, 2019
05df0f4
Merge branch 'issues/148' of https://github.com/davidgarsan/react-win…
Mar 3, 2019
a42c2fb
Prettier
Mar 3, 2019
112f102
Renamed FixedSizeListRtl to RTLLayout
Mar 3, 2019
98c7ea7
Deprecate list direction=horizontal|vertical in favor of direction=lt…
Mar 3, 2019
ba279dc
Upgrade memoize-one to ^5.0.0
jgoz Mar 4, 2019
7d61351
Upgrade memoize-one in website
jgoz Mar 4, 2019
e5d32f3
Prettier
jgoz Mar 4, 2019
38732dd
Added 'direction' prop to grid (including docs and tests)
Mar 4, 2019
c6fa7aa
Merge pull request #156 from bvaughn/issues/148
bvaughn Mar 4, 2019
7130e03
Shrink domHelpers. Remove unnecessary style. Better minification.
Mar 4, 2019
a724ee1
Upgrade Rollup. Add Terser plug-in.
Mar 4, 2019
9c24344
Use version range for memoize-one
jgoz Mar 4, 2019
0f24e9a
Removed Rollup terser plug-in for now because it was bloating the bundle
Mar 4, 2019
84ba74a
Merge pull request #155 from jgoz/upgrade-memoize-one
bvaughn Mar 4, 2019
b2ea9ad
1.5.2 -> 1.6.0
Mar 4, 2019
fb15909
Bugfix to account for differences between Chrome and non-Chrome brows…
Mar 4, 2019
e0d0dce
1.6.0 -> 1.6.1
Mar 4, 2019
dcb9c55
Bugfix for RTL when scrolling back towards the beginning (right) of t…
Mar 4, 2019
7b5dd7c
1.6.1 -> 1.6.2
Mar 4, 2019
e8f35e2
Use Set if WeakSet is not available
jgoz Mar 8, 2019
b48c94f
Ensure WeakSet has proper type
jgoz Mar 8, 2019
b0c5115
Only create sets if WeakSet exists
jgoz Mar 8, 2019
c14bce6
Added more examples and FAQs to the docs based on feedback
Mar 8, 2019
a669fc9
Merge pull request #167 from jgoz/weakset-ie11
bvaughn Mar 8, 2019
dc0d7d0
Added an example of attaching custom event handlers to FAQ
Mar 12, 2019
e9225f4
Make rowIndex and columnIndex optional
jgoz Mar 12, 2019
665957e
Update documentation
jgoz Mar 12, 2019
06e3eae
fix for codemirror loader test regexp not catering for windows paths
glromeo Mar 16, 2019
dc36b8c
fix for codemirror loader test regexp not catering for windows paths
glromeo Mar 16, 2019
68a2b5e
Narrowed down the Codemirror regex test
Mar 16, 2019
465f163
Merge branch '173-optional-scrollItem-index' of https://github.com/jg…
Mar 16, 2019
dec4c57
Expanded scrollToItem demo to show scrolling to just row or column
Mar 16, 2019
53c26b4
1.6.2 -> 1.7.0
Mar 16, 2019
c29625e
Check for undefined window to support SSR
Betree Mar 18, 2019
488db17
Merge pull request #185 from Betree/fix/184-undefined-window
bvaughn Mar 18, 2019
67c45a8
1.7.0 -> 1.7.1
Mar 18, 2019
4fd0fde
Fix path to LICENSE in README
isnifer Mar 18, 2019
ce2954c
Merge pull request #187 from isnifer/patch-1
bvaughn Mar 18, 2019
c53622f
Added an example of sticky items to FAQs
Mar 19, 2019
8928783
React deps bump
Mar 21, 2019
f518c66
Added gutter example to FAQs
Mar 27, 2019
0618410
Added sticky Grid to FAQ
Apr 2, 2019
e69da68
Merge master
piecyk Mar 14, 2019
070ea74
Merge branch 'master' into issues/6
piecyk Apr 2, 2019
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
23 changes: 23 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,29 @@
Changelog
------------

### 1.7.1
* 🐛 Fix SSR regression introduced in 1.7.0 - ([Betree](https://github.com/Betree) - [#185](https://github.com/bvaughn/react-window/pull/185))

### 1.7.0
* 🎉 Grid `scrollToItem` supports optional `rowIndex` and `columnIndex` params ([jgoz](https://github.com/jgoz) - [#174](https://github.com/bvaughn/react-window/pull/174))
* DEV mode checks for `WeakSet` support before using it to avoid requiring a polyfill for IE11 - ([jgoz](https://github.com/jgoz) - [#167](https://github.com/bvaughn/react-window/pull/167))

### 1.6.2
* 🐛 Bugfix for RTL when scrolling back towards the beginning (right) of the list.

### 1.6.1
* 🐛 Bugfix to account for differences between Chrome and non-Chrome browsers with regard to RTL and "scroll" events.

### 1.6.0
* 🎉 RTL support added for lists and grids. Special thanks to [davidgarsan](https://github.com/davidgarsan) for his support. - [#156](https://github.com/bvaughn/react-window/pull/156)
* 🐛 Grid `scrollToItem` methods take scrollbar size into account when aligning items - [#153](https://github.com/bvaughn/react-window/issues/153)

### 1.5.2
* 🐛 Edge case bug fix for `VariableSizeList` and `VariableSizeGrid` when the number of items decreases while a scroll is in progress. - ([iamsolankiamit](https://github.com/iamsolankiamit) - [#138](https://github.com/bvaughn/react-window/pull/138))

### 1.5.1
* 🐛 Updated `getDerivedState` Flow annotations to address a warning in a newer version of Flow.

### 1.5.0
* 🎉 Added advanced memoization helpers methods `areEqual` and `shouldComponentUpdate` for item renderers. - [#114](https://github.com/bvaughn/react-window/issues/114)

Expand Down
21 changes: 21 additions & 0 deletions LICENSE.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
The MIT License (MIT)

Copyright (c) 2018 Brian Vaughn

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
59 changes: 56 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

> React components for efficiently rendering large lists and tabular data

[![NPM registry](https://img.shields.io/npm/v/react-window.svg?style=for-the-badge)](https://yarnpkg.com/en/package/react-window) [![Travis](https://img.shields.io/badge/ci-travis-green.svg?style=for-the-badge)](https://travis-ci.org/bvaughn/react-window) [![NPM license](https://img.shields.io/badge/license-mit-red.svg?style=for-the-badge)](LICENSE)
[![NPM registry](https://img.shields.io/npm/v/react-window.svg?style=for-the-badge)](https://yarnpkg.com/en/package/react-window) [![Travis](https://img.shields.io/badge/ci-travis-green.svg?style=for-the-badge)](https://travis-ci.org/bvaughn/react-window) [![NPM license](https://img.shields.io/badge/license-mit-red.svg?style=for-the-badge)](LICENSE.md)

## Install

Expand All @@ -16,11 +16,16 @@ npm install --save react-window

## Usage

Learn more at [react-window.now.sh](https://react-window.now.sh/).
Learn more at [react-window.now.sh](https://react-window.now.sh/):

## Related libraries

* [`react-virtualized-auto-sizer`](https://npmjs.com/package/react-virtualized-auto-sizer): HOC that grows to fit all of the available space and passes the width and height values to its child.
* [`react-window-infinite-loader`](https://npmjs.com/package/react-window-infinite-loader): Helps break large data sets down into chunks that can be just-in-time loaded as they are scrolled into view. It can also be used to create infinite loading lists (e.g. Facebook or Twitter).

## Frequently asked questions

#### How is `react-window` different from `react-virtualized`?
### How is `react-window` different from `react-virtualized`?
I wrote `react-virtualized` several years ago. At the time, I was new to both React and the concept of windowing. Because of this, I made a few API decisions that I later came to regret. One of these was adding too many non-essential features and components. Once you add something to an open source project, removing it is pretty painful for users.

`react-window` is a complete rewrite of `react-virtualized`. I didn't try to solve as many problems or support as many use cases. Instead I focused on making the package **smaller**<sup>1</sup> and **faster**. I also put a lot of thought into making the API (and documentation) as beginner-friendly as possible (with the caveat that windowing is still kind of an advanced use case).
Expand All @@ -32,6 +37,54 @@ If `react-window` provides the functionality your project needs, I would strongl

<sup>1 - Adding a `react-virtualized` list to a CRA project increases the (gzipped) build size by ~33.5 KB. Adding a `react-window` list to a CRA project increases the (gzipped) build size by &lt;2 KB.</sup>

### Can a list or a grid fill 100% the width or height of a page?

Yes. I recommend using the [`react-virtualized-auto-sizer` package](https://npmjs.com/package/react-virtualized-auto-sizer):

<img width="336" alt="screen shot 2019-03-07 at 7 29 08 pm" src="https://user-images.githubusercontent.com/29597/54005716-50f41880-410f-11e9-864f-a65bbdf49e07.png">

Here's a [Code Sandbox demo](https://codesandbox.io/s/3vnx878jk5).

### Why is my list blank when I scroll?

If your list looks something like this...

<img src="https://user-images.githubusercontent.com/29597/54005352-eb535c80-410d-11e9-80b2-d3d02db1f599.gif" width="302" height="152">

...then you probably forgot to use the `style` parameter! Libraries like react-window work by absolutely positioning the list items (via an inline style), so don't forget to attach it to the DOM element you render!

<img width="257" alt="screen shot 2019-03-07 at 7 21 48 pm" src="https://user-images.githubusercontent.com/29597/54005433-45ecb880-410e-11e9-8721-420ff1a153da.png">

### Can I lazy load data for my list?

Yes. I recommend using the [`react-window-infinite-loader` package](https://npmjs.com/package/react-window-infinite-loader):

<img width="368" alt="screen shot 2019-03-07 at 7 32 32 pm" src="https://user-images.githubusercontent.com/29597/54006733-653a1480-4113-11e9-907b-08ca5e27b3f9.png">

Here's a [Code Sandbox demo](https://codesandbox.io/s/5wqo7z2np4).

### Can I attach custom properties or event handlers?

Yes, using the `outerElementType` prop.

<img width="412" alt="Screen Shot 2019-03-12 at 8 58 09 AM" src="https://user-images.githubusercontent.com/29597/54215333-f9ee9a80-44a4-11e9-9142-34c67026d950.png">

Here's a [Code Sandbox demo](https://codesandbox.io/s/4zqx79nww0).

### Can I add gutter or padding between items?

Yes, although it requires a bit of inline styling.

<img width="416" alt="Screen Shot 2019-03-26 at 6 33 56 PM" src="https://user-images.githubusercontent.com/29597/55043972-c14ad700-4ff5-11e9-9caa-2e9f4d85f96c.png">

Here's a [Code Sandbox demo](https://codesandbox.io/s/2w8wmlm89p).

### Does this library support "sticky" items?

Yes, although it requires a small amount of user code. Here are Code Sandbox demos for list and grids:
* [List demo](https://codesandbox.io/s/0mk3qwpl4l)
* [Grid demo](https://codesandbox.io/s/vqk32863wy)

## License

MIT © [bvaughn](https://github.com/bvaughn)
17 changes: 9 additions & 8 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "react-window",
"version": "1.6.0-alpha.1",
"version": "1.8.0-alpha.1",
"description":
"React components for efficiently rendering large, scrollable lists and tabular data",
"author":
Expand Down Expand Up @@ -61,7 +61,7 @@
},
"dependencies": {
"@babel/runtime": "^7.0.0",
"memoize-one": "^3.1.1"
"memoize-one": ">=3.1.1 <6"
},
"peerDependencies": {
"react": "^15.0.0 || ^16.0.0",
Expand Down Expand Up @@ -95,13 +95,14 @@
"gh-pages": "^1.1.0",
"lint-staged": "^7.0.5",
"prettier": "^1.12.1",
"react": "^16.7.0",
"react-dom": "^16.7.0",
"react": "^16.8.4",
"react-dom": "^16.8.4",
"react-is": "^16.8.4",
"react-scripts": "^1.1.1",
"react-test-renderer": "^16.7.0",
"rollup": "^0.65.0",
"rollup-plugin-babel": "^4.0.2",
"rollup-plugin-commonjs": "^8.2.1",
"rollup-plugin-node-resolve": "^3.0.2"
"rollup": "^1.4.1",
"rollup-plugin-babel": "^4.3.2",
"rollup-plugin-commonjs": "^9.2.1",
"rollup-plugin-node-resolve": "^4.0.1"
}
}
1 change: 1 addition & 0 deletions rollup.config.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import babel from 'rollup-plugin-babel';
import commonjs from 'rollup-plugin-commonjs';
import nodeResolve from 'rollup-plugin-node-resolve';

import pkg from './package.json';

const input = './src/index.js';
Expand Down
29 changes: 21 additions & 8 deletions src/DynamicSizeList.js
Original file line number Diff line number Diff line change
Expand Up @@ -152,7 +152,7 @@ const DynamicSizeList = createListComponent({
scrollOffset: number,
instanceProps: InstanceProps
): number => {
const { direction, height, width } = props;
const { direction, layout, height, width } = props;

if (process.env.NODE_ENV !== 'production') {
const { lastMeasuredIndex } = instanceProps;
Expand All @@ -164,7 +164,9 @@ const DynamicSizeList = createListComponent({
}
}

const size = (((direction === 'horizontal' ? width : height): any): number);
const size = (((direction === 'horizontal' || layout === 'horizontal'
? width
: height): any): number);
const itemMetadata = getItemMetadata(props, index, instanceProps);

// Get estimated total size after ItemMetadata is computed,
Expand Down Expand Up @@ -225,9 +227,11 @@ const DynamicSizeList = createListComponent({
scrollOffset: number,
instanceProps: InstanceProps
): number => {
const { direction, height, itemCount, width } = props;
const { direction, layout, height, itemCount, width } = props;

const size = (((direction === 'horizontal' ? width : height): any): number);
const size = (((direction === 'horizontal' || layout === 'horizontal'
? width
: height): any): number);
const itemMetadata = getItemMetadata(props, startIndex, instanceProps);
const maxOffset = scrollOffset + size;

Expand Down Expand Up @@ -325,7 +329,7 @@ const DynamicSizeList = createListComponent({
instance.forceUpdate();
} else {
const { scrollOffset } = instance.state;
const { direction } = instance.props;
const { direction, layout } = instance.props;

// Adjusting scroll offset directly interrupts smooth scrolling for some browsers (e.g. Firefox).
// The relative scrollBy() method doesn't interrupt (or at least it won't as of Firefox v65).
Expand All @@ -335,10 +339,17 @@ const DynamicSizeList = createListComponent({
// $FlowFixMe Property scrollBy is missing in HTMLDivElement
if (typeof element.scrollBy === 'function') {
element.scrollBy(
direction === 'horizontal' ? sizeDeltaForStateUpdate : 0,
direction === 'horizontal' ? 0 : sizeDeltaForStateUpdate
direction === 'horizontal' || layout === 'horizontal'
? sizeDeltaForStateUpdate
: 0,
direction === 'horizontal' || layout === 'horizontal'
? 0
: sizeDeltaForStateUpdate
);
} else if (direction === 'horizontal') {
} else if (
direction === 'horizontal' ||
layout === 'horizontal'
) {
element.scrollLeft = scrollOffset;
} else {
element.scrollTop = scrollOffset;
Expand Down Expand Up @@ -418,6 +429,7 @@ const DynamicSizeList = createListComponent({
const {
children,
direction,
layout,
itemCount,
itemData,
itemKey = defaultItemKey,
Expand Down Expand Up @@ -451,6 +463,7 @@ const DynamicSizeList = createListComponent({
items.push(
createElement(ItemMeasurer, {
direction,
layout,
handleNewMeasurements,
index,
item,
Expand Down
10 changes: 8 additions & 2 deletions src/FixedSizeGrid.js
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,9 @@ const FixedSizeGrid = createGridComponent({
{ columnCount, columnWidth, width }: Props<any>,
columnIndex: number,
align: ScrollToAlign,
scrollLeft: number
scrollLeft: number,
instanceProps: typeof undefined,
scrollbarSize: number
): number => {
const maxOffset = Math.max(
0,
Expand All @@ -40,6 +42,7 @@ const FixedSizeGrid = createGridComponent({
0,
columnIndex * ((columnWidth: any): number) -
width +
scrollbarSize +
((columnWidth: any): number)
);

Expand All @@ -66,7 +69,9 @@ const FixedSizeGrid = createGridComponent({
{ rowHeight, height, rowCount }: Props<any>,
rowIndex: number,
align: ScrollToAlign,
scrollTop: number
scrollTop: number,
instanceProps: typeof undefined,
scrollbarSize: number
): number => {
const maxOffset = Math.max(
0,
Expand All @@ -79,6 +84,7 @@ const FixedSizeGrid = createGridComponent({
0,
rowIndex * ((rowHeight: any): number) -
height +
scrollbarSize +
((rowHeight: any): number)
);

Expand Down
12 changes: 8 additions & 4 deletions src/FixedSizeList.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,12 +15,14 @@ const FixedSizeList = createListComponent({
((itemSize: any): number) * itemCount,

getOffsetForIndexAndAlignment: (
{ direction, height, itemCount, itemSize, width }: Props<any>,
{ direction, height, itemCount, itemSize, layout, width }: Props<any>,
index: number,
align: ScrollToAlign,
scrollOffset: number
): number => {
const size = (((direction === 'horizontal' ? width : height): any): number);
// TODO Deprecate direction "horizontal"
const isHorizontal = direction === 'horizontal' || layout === 'horizontal';
const size = (((isHorizontal ? width : height): any): number);
const maxOffset = Math.max(
0,
Math.min(
Expand Down Expand Up @@ -62,12 +64,14 @@ const FixedSizeList = createListComponent({
),

getStopIndexForStartIndex: (
{ direction, height, itemCount, itemSize, width }: Props<any>,
{ direction, height, itemCount, itemSize, layout, width }: Props<any>,
startIndex: number,
scrollOffset: number
): number => {
// TODO Deprecate direction "horizontal"
const isHorizontal = direction === 'horizontal' || layout === 'horizontal';
const offset = startIndex * ((itemSize: any): number);
const size = (((direction === 'horizontal' ? width : height): any): number);
const size = (((isHorizontal ? width : height): any): number);
return Math.max(
0,
Math.min(
Expand Down
6 changes: 4 additions & 2 deletions src/ItemMeasurer.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
import { cloneElement, Component } from 'react';
import { findDOMNode } from 'react-dom';

import type { Direction } from './createListComponent';
import type { Direction, Layout } from './createListComponent';
import type { HandleNewMeasurements } from './DynamicSizeList';

class DOMRectReadOnly {
Expand Down Expand Up @@ -38,6 +38,7 @@ declare class ResizeObserver {

type ItemMeasurerProps = {|
direction: Direction,
layout: Layout,
handleNewMeasurements: HandleNewMeasurements,
index: number,
item: React$Element<any>,
Expand Down Expand Up @@ -107,6 +108,7 @@ export default class ItemMeasurer extends Component<ItemMeasurerProps, void> {
_measureItem = (isCommitPhase: boolean) => {
const {
direction,
layout,
handleNewMeasurements,
index,
size: oldSize,
Expand All @@ -121,7 +123,7 @@ export default class ItemMeasurer extends Component<ItemMeasurerProps, void> {
node instanceof node.ownerDocument.defaultView.HTMLElement
) {
const newSize =
direction === 'horizontal'
direction === 'horizontal' || layout === 'horizontal'
? Math.ceil(node.offsetWidth)
: Math.ceil(node.offsetHeight);

Expand Down
Loading