Skip to content
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
16 changes: 0 additions & 16 deletions .eslintrc.js

This file was deleted.

8 changes: 8 additions & 0 deletions .github/dependabot.yml
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,10 @@ updates:
time: '21:00'
timezone: Asia/Shanghai
open-pull-requests-limit: 10
groups:
npm-dependencies:
patterns:
- '*'

- package-ecosystem: github-actions
directory: '/'
Expand All @@ -17,3 +21,7 @@ updates:
time: '21:00'
timezone: Asia/Shanghai
open-pull-requests-limit: 10
groups:
github-actions:
patterns:
- '*'
3 changes: 1 addition & 2 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
<div align="center">
<h1>@rc-component/virtual-list</h1>
<p><sub><img alt="Ant Design" height="14" src="https://gw.alipayobjects.com/zos/rmsportal/KDpgvguMpGfqaHPjicRK.svg" style="vertical-align: -0.125em;" /> Part of the Ant Design ecosystem.</sub></p>
<p><sub><a href="https://ant.design"><img alt="Ant Design" height="14" src="https://gw.alipayobjects.com/zos/rmsportal/KDpgvguMpGfqaHPjicRK.svg" style="vertical-align: -0.125em;" /></a> Part of the Ant Design ecosystem.</sub></p>
<p>📜 Virtual scrolling list component for React.</p>

<p>
Expand All @@ -15,7 +15,6 @@

<p align="center">English | <a href="./README.zh-CN.md">简体中文</a></p>


## Highlights

- Built for React and maintained by the rc-component team.
Expand Down
27 changes: 13 additions & 14 deletions README.zh-CN.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
<div align="center">
<h1>@rc-component/virtual-list</h1>
<p><sub><img alt="Ant Design" height="14" src="https://gw.alipayobjects.com/zos/rmsportal/KDpgvguMpGfqaHPjicRK.svg" style="vertical-align: -0.125em;" /> Ant Design 生态的一部分。</sub></p>
<p><sub><a href="https://ant.design"><img alt="Ant Design" height="14" src="https://gw.alipayobjects.com/zos/rmsportal/KDpgvguMpGfqaHPjicRK.svg" style="vertical-align: -0.125em;" /></a> Ant Design 生态的一部分。</sub></p>
<p>📜 React 虚拟列表组件,用于高性能渲染长列表。</p>

<p>
Expand All @@ -15,7 +15,6 @@

<p align="center"><a href="./README.md">English</a> | 简体中文</p>


## 特性

- 面向 React 构建,并由 rc-component 团队维护。
Expand Down Expand Up @@ -61,19 +60,19 @@ npm start

### List

| 属性 | 说明 | 类型 | 默认值 |
| ---------- | ---------------------------------------------------------------------------------------------------------------------- | -------------------------------------- | ------- |
| 属性 | 说明 | 类型 | 默认值 |
| ---------- | ------------------------------------------------------------------ | -------------------------------------- | ------- |
| children | 每一项的渲染函数。第三个参数包含旧浏览器兼容路径使用的测量 props。 | `(item, index, props) => ReactElement` | - |
| component | 自定义列表容器元素。 | `string` \| `ComponentType` | `div` |
| data | 虚拟列表渲染的数据项。 | `T[]` | - |
| disabled | 禁用滚动位置检查,通常用于配合动画。 | `boolean` | `false` |
| fullHeight | holder 是否保持完整高度。 | `boolean` | `true` |
| height | 可视列表高度。 | `number` | - |
| itemHeight | 用于计算虚拟范围的最小项高度。 | `number` | - |
| itemKey | 数据项 key 字段或 key 获取函数。 | `string` \| `(item) => React.Key` | - |
| onScroll | 列表滚动时调用。 | `React.UIEventHandler<HTMLElement>` | - |
| styles | 自定义滚动条部位样式。 | `object` | - |
| virtual | 启用虚拟渲染。 | `boolean` | `true` |
| component | 自定义列表容器元素。 | `string` \| `ComponentType` | `div` |
| data | 虚拟列表渲染的数据项。 | `T[]` | - |
| disabled | 禁用滚动位置检查,通常用于配合动画。 | `boolean` | `false` |
| fullHeight | holder 是否保持完整高度。 | `boolean` | `true` |
| height | 可视列表高度。 | `number` | - |
| itemHeight | 用于计算虚拟范围的最小项高度。 | `number` | - |
| itemKey | 数据项 key 字段或 key 获取函数。 | `string` \| `(item) => React.Key` | - |
| onScroll | 列表滚动时调用。 | `React.UIEventHandler<HTMLElement>` | - |
| styles | 自定义滚动条部位样式。 | `object` | - |
| virtual | 启用虚拟渲染。 | `boolean` | `true` |

## 本地开发

Expand Down
115 changes: 115 additions & 0 deletions eslint.config.mjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,115 @@
import js from '@eslint/js';
import { defineConfig } from 'eslint/config';
import { dirname } from 'node:path';
import { fileURLToPath } from 'node:url';
import prettier from 'eslint-config-prettier';
import jest from 'eslint-plugin-jest';
import react from 'eslint-plugin-react';
import reactHooks from 'eslint-plugin-react-hooks';
import globals from 'globals';
import tseslint from 'typescript-eslint';

const tsconfigRootDir = dirname(fileURLToPath(import.meta.url));

export default defineConfig([
{
plugins: {
'@typescript-eslint': tseslint.plugin,
},
},
{
linterOptions: {
reportUnusedDisableDirectives: 'warn',
},
},
{
ignores: [
'node_modules/',
'coverage/',
'es/',
'lib/',
'dist/',
'docs-dist/',
'.docs-dist/',
'.dumi/',
'.doc/',
'.vercel/',
],
},
{
files: ['**/*.{js,jsx,ts,tsx}'],
extends: [
js.configs.recommended,
react.configs.flat.recommended,
react.configs.flat['jsx-runtime'],
prettier,
],
plugins: {
'react-hooks': reactHooks,
},
languageOptions: {
globals: {
...globals.browser,
...globals.node,
},
},
settings: {
react: {
version: 'detect',
},
},
rules: {
'no-async-promise-executor': 'off',
'no-empty-pattern': 'off',
'no-irregular-whitespace': 'off',
'no-prototype-builtins': 'off',
'no-useless-escape': 'off',
'no-extra-boolean-cast': 'off',
'no-undef': 'off',
'no-unused-vars': 'off',
'react/no-find-dom-node': 'off',
'react/display-name': 'off',
'react/no-unknown-property': 'off',
'react/prop-types': 'off',
'react-hooks/exhaustive-deps': 'warn',
'react-hooks/rules-of-hooks': 'error',
},
},
{
files: ['**/*.{ts,tsx}'],
extends: [...tseslint.configs.recommended],
rules: {
'@typescript-eslint/ban-ts-comment': 'off',
'@typescript-eslint/no-empty-object-type': 'off',
'@typescript-eslint/no-explicit-any': 'off',
'@typescript-eslint/no-unsafe-function-type': 'off',
'@typescript-eslint/no-unnecessary-type-constraint': 'off',
'@typescript-eslint/no-unused-vars': 'off',
},
},
{
files: ['src/**/*.{ts,tsx}'],
languageOptions: {
parserOptions: {
projectService: true,
tsconfigRootDir,
},
},
},
{
files: ['tests/**/*.{js,jsx,ts,tsx}', '**/*.{test,spec}.{js,jsx,ts,tsx}'],
extends: [jest.configs['flat/recommended']],
rules: {
'jest/no-disabled-tests': 'off',
'jest/no-done-callback': 'off',
'jest/no-identical-title': 'off',
'jest/expect-expect': 'off',
'jest/no-alias-methods': 'off',
'jest/no-conditional-expect': 'off',
'jest/no-export': 'off',
'jest/no-standalone-expect': 'off',
'jest/valid-expect': 'off',
'jest/valid-title': 'off',
},
},
]);
2 changes: 1 addition & 1 deletion examples/animate.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -130,7 +130,7 @@ const Demo = () => {
const [animating, setAnimating] = React.useState(false);
const [insertIndex, setInsertIndex] = React.useState<number>();

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

const onClose = (id: string) => {
setCloseMap({
Expand Down
6 changes: 3 additions & 3 deletions examples/no-virtual.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ interface Item {
height: number;
}

const MyItem: React.FC<Item> = ({ id, height }, ref) => {
const MyItem = React.forwardRef<HTMLSpanElement, Item>(({ id, height }, ref) => {
Comment thread
afc163 marked this conversation as resolved.
return (
<span
ref={ref}
Expand All @@ -23,9 +23,9 @@ const MyItem: React.FC<Item> = ({ id, height }, ref) => {
{id}
</span>
);
};
});

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

const data: Item[] = [];
for (let i = 0; i < 100; i += 1) {
Expand Down
8 changes: 4 additions & 4 deletions examples/switch.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ interface Item {
id: number;
}

const MyItem: React.FC<Item> = ({ id }, ref) => (
const MyItem = React.forwardRef<HTMLSpanElement, Item>(({ id }, ref) => (
Comment thread
afc163 marked this conversation as resolved.
<span
ref={ref}
style={{
Expand All @@ -21,9 +21,9 @@ const MyItem: React.FC<Item> = ({ id }, ref) => (
>
{id}
</span>
);
));

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

function getData(count: number) {
const data: Item[] = [];
Expand All @@ -39,7 +39,7 @@ const Demo = () => {
const [height, setHeight] = React.useState(200);
const [data, setData] = React.useState(getData(20));
const [fullHeight, setFullHeight] = React.useState(true);
const listRef = React.useRef<ListRef>();
const listRef = React.useRef<ListRef>(null);

return (
<React.StrictMode>
Expand Down
11 changes: 11 additions & 0 deletions global.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
/// <reference types="jest" />
/// <reference types="node" />
/// <reference types="react" />
/// <reference types="react-dom" />
/// <reference types="@testing-library/jest-dom" />

declare module '*.css';
declare module '*.less';
declare module 'jsonp';

declare module 'moment/locale/zh-cn';
41 changes: 24 additions & 17 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -48,33 +48,40 @@
"react-dom": ">=18.0.0"
},
"devDependencies": {
"@eslint/js": "^9.39.4",
"@rc-component/father-plugin": "^2.2.0",
"@rc-component/np": "^1.0.4",
"@testing-library/dom": "^10.4.1",
"@testing-library/jest-dom": "^6.9.1",
"@testing-library/react": "^15.0.7",
"@types/jest": "^29.5.14",
"@testing-library/react": "^16.3.2",
"@types/jest": "^30.0.0",
"@types/node": "^26.0.1",
"@types/react": "^18.3.31",
"@types/react-dom": "^18.3.7",
"@types/react": "^19.2.17",
"@types/react-dom": "^19.2.3",
"@types/warning": "^3.0.4",
"dumi": "^2.4.35",
"eslint": "^8.57.1",
"eslint-plugin-unicorn": "^56.0.1",
"father": "^4.6.23",
"glob": "^13.0.6",
"rc-animate": "^2.9.1",
"rc-test": "^7.1.3",
"react": "^18.3.1",
"react-dom": "^18.3.1",
"typescript": "^5.9.3",
"cross-env": "^10.1.0",
"dumi": "^2.4.38",
"eslint": "^9.39.4",
"eslint-config-prettier": "^10.1.8",
"eslint-plugin-jest": "^29.15.4",
"eslint-plugin-react": "^7.37.5",
"eslint-plugin-react-hooks": "^7.1.1",
"father": "^4.6.24",
"gh-pages": "^6.3.0",
"prettier": "^3.9.0",
"glob": "^13.0.6",
"globals": "^17.7.0",
"husky": "^9.1.7",
"lint-staged": "^16.4.0"
"lint-staged": "^17.0.8",
"prettier": "^3.9.4",
"rc-animate": "^2.9.1",
"rc-test": "^7.1.3",
"react": "^19.2.7",
"react-dom": "^19.2.7",
"typescript": "^6.0.3",
"typescript-eslint": "^8.62.1"
},
"dependencies": {
"@babel/runtime": "^7.20.0",
"@babel/runtime": "^7.29.7",
"@rc-component/resize-observer": "^1.0.1",
"@rc-component/util": "^1.4.0",
"clsx": "^2.1.1"
Expand Down
13 changes: 8 additions & 5 deletions src/Item.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,15 +2,18 @@ import * as React from 'react';

export interface ItemProps {
children: React.ReactElement;
setRef: (element: HTMLElement) => void;
setRef: (element: HTMLElement | null) => void;
}

export function Item({ children, setRef }: ItemProps) {
const refFunc = React.useCallback(node => {
setRef(node);
}, []);
const refFunc = React.useCallback(
(node) => {
setRef(node);
},
[setRef],
Comment thread
coderabbitai[bot] marked this conversation as resolved.
);

return React.cloneElement(children, {
return React.cloneElement(children as React.ReactElement<any>, {
ref: refFunc,
});
}
Loading
Loading