Skip to content

Commit

Permalink
Merge pull request #2 from bvaughn/master
Browse files Browse the repository at this point in the history
Merge in latest
  • Loading branch information
MarkFalconbridge authored Apr 15, 2019
2 parents ec3d396 + f2b2106 commit f79698e
Show file tree
Hide file tree
Showing 21 changed files with 540 additions and 7 deletions.
6 changes: 6 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,12 @@
Changelog
------------

### 1.8.1
* 🐛 Replaced an incorrect empty-string value for `pointer-events` with `undefined` ([oliviertassinari](https://github.com/oliviertassinari) - [#210](https://github.com/bvaughn/react-window/pull/210))

### 1.8.0
* 🎉 Added new "smart" align option for grid and list scroll-to-item methods ([gaearon](https://github.com/gaearon) - [#209](https://github.com/bvaughn/react-window/pull/209))

### 1.7.2
* 🐛 Add guards to avoid invalid scroll offsets when `scrollTo()` is called with a negative offset or when `scrollToItem` is called with invalid indices (negative or too large).

Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "react-window",
"version": "1.7.2",
"version": "1.8.1",
"description":
"React components for efficiently rendering large, scrollable lists and tabular data",
"author":
Expand Down
16 changes: 16 additions & 0 deletions src/FixedSizeGrid.js
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,14 @@ const FixedSizeGrid = createGridComponent({
((columnWidth: any): number)
);

if (align === 'smart') {
if (scrollLeft >= minOffset - width && scrollLeft <= maxOffset + width) {
align = 'auto';
} else {
align = 'center';
}
}

switch (align) {
case 'start':
return maxOffset;
Expand Down Expand Up @@ -88,6 +96,14 @@ const FixedSizeGrid = createGridComponent({
((rowHeight: any): number)
);

if (align === 'smart') {
if (scrollTop >= minOffset - height && scrollTop <= maxOffset + height) {
align = 'auto';
} else {
align = 'center';
}
}

switch (align) {
case 'start':
return maxOffset;
Expand Down
11 changes: 11 additions & 0 deletions src/FixedSizeList.js
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,17 @@ const FixedSizeList = createListComponent({
index * ((itemSize: any): number) - size + ((itemSize: any): number)
);

if (align === 'smart') {
if (
scrollOffset >= minOffset - size &&
scrollOffset <= maxOffset + size
) {
align = 'auto';
} else {
align = 'center';
}
}

switch (align) {
case 'start':
return maxOffset;
Expand Down
8 changes: 8 additions & 0 deletions src/VariableSizeGrid.js
Original file line number Diff line number Diff line change
Expand Up @@ -255,6 +255,14 @@ const getOffsetForIndexAndAlignment = (
itemMetadata.offset - size + scrollbarSize + itemMetadata.size
);

if (align === 'smart') {
if (scrollOffset >= minOffset - size && scrollOffset <= maxOffset + size) {
align = 'auto';
} else {
align = 'center';
}
}

switch (align) {
case 'start':
return maxOffset;
Expand Down
11 changes: 11 additions & 0 deletions src/VariableSizeList.js
Original file line number Diff line number Diff line change
Expand Up @@ -205,6 +205,17 @@ const VariableSizeList = createListComponent({
itemMetadata.offset - size + itemMetadata.size
);

if (align === 'smart') {
if (
scrollOffset >= minOffset - size &&
scrollOffset <= maxOffset + size
) {
align = 'auto';
} else {
align = 'center';
}
}

switch (align) {
case 'start':
return maxOffset;
Expand Down
37 changes: 36 additions & 1 deletion src/__tests__/FixedSizeGrid.js
Original file line number Diff line number Diff line change
Expand Up @@ -155,7 +155,7 @@ describe('FixedSizeGrid', () => {
<FixedSizeGrid {...defaultProps} />
);
const scrollContainer = findScrollContainer(rendered);
expect(scrollContainer.props.style.pointerEvents).toBe('');
expect(scrollContainer.props.style.pointerEvents).toBe(undefined);
rendered.getInstance().setState({ isScrolling: true });
expect(scrollContainer.props.style.pointerEvents).toBe('none');
});
Expand Down Expand Up @@ -565,6 +565,41 @@ describe('FixedSizeGrid', () => {
expect(onItemsRendered.mock.calls).toMatchSnapshot();
});

it('should scroll to the correct item for align = "smart"', () => {
const rendered = ReactTestRenderer.create(
<FixedSizeGrid {...defaultProps} />
);

// Scroll down enough to show item 10 at the center.
// It was further than one screen away, so it gets centered.
rendered
.getInstance()
.scrollToItem({ columnIndex: 10, rowIndex: 10, align: 'smart' });
// No need to scroll again; item 9 is already visible.
// Overscan indices will change though, since direction changes.
rendered
.getInstance()
.scrollToItem({ columnIndex: 9, rowIndex: 9, align: 'smart' });
// Scroll up enough to show item 2 as close to the center as we can.
rendered
.getInstance()
.scrollToItem({ columnIndex: 2, rowIndex: 2, align: 'smart' });
// Scroll down to row 10, without changing scrollLeft
rendered.getInstance().scrollToItem({ rowIndex: 10, align: 'smart' });
// Scroll left to column 0, without changing scrollTop
rendered.getInstance().scrollToItem({ columnIndex: 0, align: 'smart' });

// Scrolling within a distance of a single screen from viewport
// should have the 'auto' behavior of scrolling as little as possible.
rendered
.getInstance()
.scrollToItem({ columnIndex: 5, rowIndex: 5, align: 'smart' });
rendered
.getInstance()
.scrollToItem({ columnIndex: 10, rowIndex: 10, align: 'smart' });
expect(onItemsRendered.mock.calls).toMatchSnapshot();
});

it('should not report isScrolling', () => {
// Use ReactDOM renderer so the container ref and "onScroll" event work correctly.
const instance = ReactDOM.render(
Expand Down
30 changes: 29 additions & 1 deletion src/__tests__/FixedSizeList.js
Original file line number Diff line number Diff line change
Expand Up @@ -200,7 +200,7 @@ describe('FixedSizeList', () => {
<FixedSizeList {...defaultProps} />
);
const scrollContainer = findScrollContainer(rendered);
expect(scrollContainer.props.style.pointerEvents).toBe('');
expect(scrollContainer.props.style.pointerEvents).toBe(undefined);
rendered.getInstance().setState({ isScrolling: true });
expect(scrollContainer.props.style.pointerEvents).toBe('none');
});
Expand Down Expand Up @@ -455,6 +455,34 @@ describe('FixedSizeList', () => {
expect(onItemsRendered.mock.calls).toMatchSnapshot();
});

it('should scroll to the correct item for align = "smart"', () => {
const rendered = ReactTestRenderer.create(
<FixedSizeList {...defaultProps} />
);
// Scroll down enough to show item 10 in the middle.
rendered.getInstance().scrollToItem(10, 'smart');
// Scrolldn't scroll at all because it's close enough.
rendered.getInstance().scrollToItem(9, 'smart');
// Should scroll but not center because it's close enough.
rendered.getInstance().scrollToItem(6, 'smart');
// Item 1 can't align in the middle because it's too close to the beginning.
// Scroll up as far as possible though.
rendered.getInstance().scrollToItem(1, 'smart');
// Item 99 can't align in the middle because it's too close to the end.
// Scroll down as far as possible though.
rendered.getInstance().scrollToItem(99, 'smart');
// This shouldn't scroll at all because it's close enough.
rendered.getInstance().scrollToItem(95, 'smart');
rendered.getInstance().scrollToItem(99, 'smart');
// This should scroll with the 'auto' behavior because it's within a screen.
rendered.getInstance().scrollToItem(94, 'smart');
rendered.getInstance().scrollToItem(99, 'smart');
// This should scroll with the 'center' behavior because it's too far.
rendered.getInstance().scrollToItem(90, 'smart');
rendered.getInstance().scrollToItem(99, 'smart');
expect(onItemsRendered.mock.calls).toMatchSnapshot();
});

it('should not report isScrolling', () => {
// Use ReactDOM renderer so the container ref and "onScroll" work correctly.
const instance = ReactDOM.render(
Expand Down
35 changes: 35 additions & 0 deletions src/__tests__/VariableSizeGrid.js
Original file line number Diff line number Diff line change
Expand Up @@ -273,6 +273,41 @@ describe('VariableSizeGrid', () => {
expect(onItemsRendered.mock.calls).toMatchSnapshot();
});

it('should scroll to the correct item for align = "smart"', () => {
const rendered = ReactTestRenderer.create(
<VariableSizeGrid {...defaultProps} />
);

// Scroll down enough to show item 10 at the center.
// It was further than one screen away, so it gets centered.
rendered
.getInstance()
.scrollToItem({ columnIndex: 10, rowIndex: 10, align: 'smart' });
// No need to scroll again; item 9 is already visible.
// Overscan indices will change though, since direction changes.
rendered
.getInstance()
.scrollToItem({ columnIndex: 9, rowIndex: 9, align: 'smart' });
// Scroll up enough to show item 2 as close to the center as we can.
rendered
.getInstance()
.scrollToItem({ columnIndex: 2, rowIndex: 2, align: 'smart' });
// Scroll down to row 10, without changing scrollLeft
rendered.getInstance().scrollToItem({ rowIndex: 10, align: 'smart' });
// Scroll left to column 0, without changing scrollTop
rendered.getInstance().scrollToItem({ columnIndex: 0, align: 'smart' });

// Scrolling within a distance of a single screen from viewport
// should have the 'auto' behavior of scrolling as little as possible.
rendered
.getInstance()
.scrollToItem({ columnIndex: 5, rowIndex: 5, align: 'smart' });
rendered
.getInstance()
.scrollToItem({ columnIndex: 10, rowIndex: 10, align: 'smart' });
expect(onItemsRendered.mock.calls).toMatchSnapshot();
});

it('should account for scrollbar size', () => {
const onScroll = jest.fn();
const rendered = ReactTestRenderer.create(
Expand Down
17 changes: 17 additions & 0 deletions src/__tests__/VariableSizeList.js
Original file line number Diff line number Diff line change
Expand Up @@ -197,6 +197,23 @@ describe('VariableSizeList', () => {
rendered.getInstance().scrollToItem(19, 'center');
expect(onItemsRendered.mock.calls).toMatchSnapshot();
});

it('should scroll to the correct item for align = "smart"', () => {
const onItemsRendered = jest.fn();
const rendered = ReactTestRenderer.create(
<VariableSizeList {...defaultProps} onItemsRendered={onItemsRendered} />
);
// Scroll down enough to show item 10 in the middle.
rendered.getInstance().scrollToItem(10, 'smart');
// Scrolldn't scroll at all because it's close enough.
rendered.getInstance().scrollToItem(9, 'smart');
// Should scroll but not center because it's close enough.
rendered.getInstance().scrollToItem(6, 'smart');
// Item 1 can't align in the middle because it's too close to the beginning.
// Scroll up as far as possible though.
rendered.getInstance().scrollToItem(1, 'smart');
expect(onItemsRendered.mock.calls).toMatchSnapshot();
});
});

describe('resetAfterIndex method', () => {
Expand Down
89 changes: 89 additions & 0 deletions src/__tests__/__snapshots__/FixedSizeGrid.js.snap
Original file line number Diff line number Diff line change
Expand Up @@ -540,6 +540,95 @@ Array [
]
`;

exports[`FixedSizeGrid scrollToItem method should scroll to the correct item for align = "smart" 1`] = `
Array [
Array [
Object {
"overscanColumnStartIndex": 0,
"overscanColumnStopIndex": 3,
"overscanRowStartIndex": 0,
"overscanRowStopIndex": 5,
"visibleColumnStartIndex": 0,
"visibleColumnStopIndex": 2,
"visibleRowStartIndex": 0,
"visibleRowStopIndex": 4,
},
],
Array [
Object {
"overscanColumnStartIndex": 8,
"overscanColumnStopIndex": 12,
"overscanRowStartIndex": 7,
"overscanRowStopIndex": 13,
"visibleColumnStartIndex": 9,
"visibleColumnStopIndex": 11,
"visibleRowStartIndex": 8,
"visibleRowStopIndex": 12,
},
],
Array [
Object {
"overscanColumnStartIndex": 0,
"overscanColumnStopIndex": 4,
"overscanRowStartIndex": 0,
"overscanRowStopIndex": 6,
"visibleColumnStartIndex": 1,
"visibleColumnStopIndex": 3,
"visibleRowStartIndex": 1,
"visibleRowStopIndex": 5,
},
],
Array [
Object {
"overscanColumnStartIndex": 0,
"overscanColumnStopIndex": 4,
"overscanRowStartIndex": 7,
"overscanRowStopIndex": 13,
"visibleColumnStartIndex": 1,
"visibleColumnStopIndex": 3,
"visibleRowStartIndex": 8,
"visibleRowStopIndex": 12,
},
],
Array [
Object {
"overscanColumnStartIndex": 0,
"overscanColumnStopIndex": 3,
"overscanRowStartIndex": 7,
"overscanRowStopIndex": 13,
"visibleColumnStartIndex": 0,
"visibleColumnStopIndex": 2,
"visibleRowStartIndex": 8,
"visibleRowStopIndex": 12,
},
],
Array [
Object {
"overscanColumnStartIndex": 3,
"overscanColumnStopIndex": 7,
"overscanRowStartIndex": 4,
"overscanRowStopIndex": 10,
"visibleColumnStartIndex": 4,
"visibleColumnStopIndex": 6,
"visibleRowStartIndex": 5,
"visibleRowStopIndex": 9,
},
],
Array [
Object {
"overscanColumnStartIndex": 8,
"overscanColumnStopIndex": 12,
"overscanRowStartIndex": 6,
"overscanRowStopIndex": 12,
"visibleColumnStartIndex": 9,
"visibleColumnStopIndex": 11,
"visibleRowStartIndex": 7,
"visibleRowStopIndex": 11,
},
],
]
`;

exports[`FixedSizeGrid scrollToItem method should scroll to the correct item for align = "start" 1`] = `
Array [
Array [
Expand Down
Loading

0 comments on commit f79698e

Please sign in to comment.