Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: add horizontal mode #199

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
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
36 changes: 23 additions & 13 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ open http://localhost:9001/
```js
import List from 'rc-virtual-list';

<List data={[0, 1, 2]} height={200} itemHeight={30} itemKey="id">
<List data={[0, 1, 2]} containerSize={200} itemSize={30} itemKey="id">
{index => <div>{index}</div>}
</List>;
```
Expand All @@ -51,15 +51,25 @@ import List from 'rc-virtual-list';

## List

| Prop | Description | Type | Default |
| ---------- | ------------------------------------------------------- | ------------------------------------ | ------- |
| children | Render props of item | (item, index, props) => ReactElement | - |
| component | Customize List dom element | string \| Component | div |
| data | Data list | Array | - |
| disabled | Disable scroll check. Usually used on animation control | boolean | false |
| height | List height | number | - |
| itemHeight | Item minium height | number | - |
| itemKey | Match key with item | string | - |

`children` provides additional `props` argument to support IE 11 scroll shaking.
It will set `style` to `visibility: hidden` when measuring. You can ignore this if no requirement on IE.
| Prop | Description | Type | Default |
| --------------- | -------------------------------------------------------------------------------------------------------------------- | ----------------------------------------- | ------------------- |
| prefixCls | prefix of list element and children class | string | rc-virtual-list |
| className | wrapper className of list element | string | - |
| style | wrapper style of list element | React.CSSProperties | - |
| children | Render props of item | (item, index, props) => ReactElement | - |
| component | Customize List dom element | string \| Component | div |
| data | Data list | Array | - |
| disabled | Disable scroll check. Usually used on animation control | boolean | false |
| containerSize | List width or height. If string is passed, it's must be a valid size or it's parent has a valid size | number \| string | - |
| isStaticItem | Whether width or height of item is fixed. The `itemSize` properity is required when It set to true | boolean | false |
| itemSize | Item minium width or height. It's required when item is fixed size or you want to enable virtual mode | number | - |
| itemKey | Match key with item | string \| (\<T\>(item: T) => React.Key) | - |
| direction | list direction: IDirection.Horizontal or IDirection.Vertical | IDirection | IDirection.Vertical |
| isFullSize | always enable container size even if children's size not reach | boolean | true |
| isEnableVirtual | enable or disable virtual mode. The properity `containerSize` and `itemSize` is required to enable virtual list mode | boolean | false |
| onScroll | callback when list is scroll | React.UIEventHandler<React.HTMLElement> | - |
| onVisibleChange | trigger when render list item changed | (visibleList: T[], fullList: T[]) => void | - |
| innerProps | Inject to inner container props. Only use when you need pass aria related data | React.CSSProperties | - |

> `children` provides additional `props` argument to support IE 11 scroll shaking.
> It will set `style` to `visibility: hidden` when measuring. You can ignore this if no requirement on IE.
3 changes: 0 additions & 3 deletions docs/demo/no-virtual.md

This file was deleted.

3 changes: 3 additions & 0 deletions docs/demo/noVirtual.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
## no virtual

<code src="../../examples/noVirtual.tsx">
3 changes: 3 additions & 0 deletions docs/demo/staticItem.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
## static item

<code src="../../examples/staticItem.tsx">
3 changes: 3 additions & 0 deletions docs/demo/stringContainerSize.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
## string type containerSize

<code src="../../examples/stringContainerSize.tsx">
18 changes: 18 additions & 0 deletions examples/Item/index.less
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
.fixed-item {
display: inline-block;
box-sizing: border-box;
height: 32px;
padding: 0 16px;
line-height: 30px;
border-bottom: 1px solid gray;

&.fixed-item-horizontal {
width: 150px;
height: 120px;
border-right: 1px solid gray;
}
}

.item-horizontal {
height: 120px;
}
36 changes: 36 additions & 0 deletions examples/Item/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
import { forwardRef } from 'react';
import { useIsHorizontalMode } from '../../src/hooks';
import type { CSSProperties, ForwardRefRenderFunction } from 'react';
import type { IDirection } from '../../src/types';
import './index.less';

export interface IItem extends Omit<CSSProperties, 'direction' | 'translate'> {
id: number;
size: number;
direction?: IDirection;
style?: CSSProperties;
}

const Item: ForwardRefRenderFunction<any, IItem> = (
{ id, direction, size, style = {}, ...restProps },
ref,
) => {
const isHorizontalMode = useIsHorizontalMode(direction);
return (
<span
{...restProps}
ref={ref}
className={`fixed-item ${isHorizontalMode ? 'fixed-item-horizontal' : ''}`}
style={{
...style,
// ...(size ? { [isHorizontalMode ? 'width' : 'height']: size } : {}),
}}
>
{id}
</span>
);
};

export const ForwardMyItem = forwardRef(Item);

export default Item;
20 changes: 15 additions & 5 deletions examples/animate.less
Original file line number Diff line number Diff line change
Expand Up @@ -3,29 +3,39 @@
}

.item {
position: relative;
display: inline-block;
box-sizing: border-box;
margin: 0;
padding: 0 16px;
overflow: hidden;
line-height: 31px;
position: relative;

&:hover {
background: rgba(255, 0, 0, 0.1);
}

&::after {
content: '';
border-bottom: 1px solid gray;
position: absolute;
right: 0;
bottom: 0;
left: 0;
right: 0;
border-bottom: 1px solid gray;
content: '';
}

button {
vertical-align: text-top;
margin-right: 8px;
vertical-align: text-top;
}

&.item-horizontal {
flex-shrink: 0;
width: 150px;
border-right: 1px solid gray;

> div {
width: 100%;
}
}
}
79 changes: 60 additions & 19 deletions examples/animate.tsx
Original file line number Diff line number Diff line change
@@ -1,11 +1,10 @@
/* eslint-disable arrow-body-style */

import * as React from 'react';
// @ts-ignore
import React, { forwardRef, StrictMode, useRef, useState } from 'react';
import CSSMotion from 'rc-animate/lib/CSSMotion';
import classNames from 'classnames';
import List, { ListRef } from '../src/List';
import List from '../src/List';
import { useIsHorizontalMode } from '../src/hooks';
import useLayoutEffect from 'rc-util/lib/hooks/useLayoutEffect';
import { IDirection} from '../src/types';
import type { IListRef } from '../src/types';
import './animate.less';

let uuid = 0;
Expand All @@ -29,6 +28,7 @@ interface Item {
}

interface MyItemProps extends Item {
direction?: IDirection;
visible: boolean;
motionAppear: boolean;
onClose: (id: string) => void;
Expand All @@ -48,6 +48,7 @@ const MyItem: React.ForwardRefRenderFunction<any, MyItemProps> = (
{
id,
uuid: itemUuid,
direction = IDirection.Vertical,
visible,
onClose,
onLeave,
Expand All @@ -58,7 +59,8 @@ const MyItem: React.ForwardRefRenderFunction<any, MyItemProps> = (
},
ref,
) => {
const motionRef = React.useRef(false);
const motionRef = useRef(false);
const isHorizontalMode = useIsHorizontalMode(direction);
useLayoutEffect(() => {
return () => {
if (motionRef.current) {
Expand Down Expand Up @@ -89,7 +91,7 @@ const MyItem: React.ForwardRefRenderFunction<any, MyItemProps> = (
return (
<div
ref={passedMotionRef}
className={classNames('item', className)}
className={`item ${isHorizontalMode ? 'item-horizontal' : ''} ${className||''}`}
style={style}
data-id={id}
>
Expand Down Expand Up @@ -127,15 +129,15 @@ const MyItem: React.ForwardRefRenderFunction<any, MyItemProps> = (
);
};

const ForwardMyItem = React.forwardRef(MyItem);
const ForwardMyItem = forwardRef(MyItem);

const Demo = () => {
const [data, setData] = React.useState(originData);
const [closeMap, setCloseMap] = React.useState<{ [id: number]: boolean }>({});
const [animating, setAnimating] = React.useState(false);
const [insertIndex, setInsertIndex] = React.useState<number>();
const [data, setData] = useState(originData);
const [closeMap, setCloseMap] = useState<{ [id: number]: boolean }>({});
const [animating, setAnimating] = useState(false);
const [insertIndex, setInsertIndex] = useState<number>();

const listRef = React.useRef<ListRef>();
const listRef = useRef<IListRef>();

const onClose = (id: string) => {
setCloseMap({
Expand All @@ -150,7 +152,6 @@ const Demo = () => {
};

const onAppear = (...args: any[]) => {
console.log('Appear:', args);
setAnimating(false);
};

Expand All @@ -174,20 +175,59 @@ const Demo = () => {
};

return (
<React.StrictMode>
<StrictMode>
<div>
<h2>Animate</h2>
<p>Direction: Vertical</p>
<p>Current: {data.length} records</p>

<List<Item>
data={data}
data-id="list"
containerSize={200}
// itemSize={20}
itemKey="id"
// disabled={animating}
ref={listRef}
style={{
border: '1px solid red',
boxSizing: 'border-box',
}}
// onSkipRender={onAppear}
// onItemRemove={onAppear}
>
{(item, index) => (
<ForwardMyItem
{...item}
motionAppear={animating && insertIndex === index}
visible={!closeMap[item.id]}
onClose={onClose}
onLeave={onLeave}
onAppear={onAppear}
onInsertBefore={onInsertBefore}
onInsertAfter={onInsertAfter}
/>
)}
</List>

<br />
<br />
<br />
<br />
<p>Direction: Horizontal</p>
<p>Current: {data.length} records</p>

<List<Item>
direction={IDirection.Horizontal}
data={data}
data-id="list"
height={200}
itemHeight={20}
containerSize={1000}
// itemSize={20}
itemKey="id"
// disabled={animating}
ref={listRef}
style={{
width: 'min-content',
border: '1px solid red',
boxSizing: 'border-box',
}}
Expand All @@ -198,6 +238,7 @@ const Demo = () => {
<ForwardMyItem
{...item}
motionAppear={animating && insertIndex === index}
direction={IDirection.Horizontal}
visible={!closeMap[item.id]}
onClose={onClose}
onLeave={onLeave}
Expand All @@ -208,7 +249,7 @@ const Demo = () => {
)}
</List>
</div>
</React.StrictMode>
</StrictMode>
);
};

Expand Down
8 changes: 0 additions & 8 deletions examples/basic.less

This file was deleted.

Loading