master d3e82595ed87 cached
40 files
71.6 KB
28.9k tokens
6 symbols
1 requests
Download .txt
Repository: DavidWong9785/react-virtualized-scroll
Branch: master
Commit: d3e82595ed87
Files: 40
Total size: 71.6 KB

Directory structure:
gitextract_0u698uid/

├── .babelrc
├── .editorconfig
├── .gitattributes
├── .gitignore
├── .npmignore
├── .prettierrc
├── .travis.yml
├── LICENSE
├── README.md
├── example/
│   └── src/
│       ├── app.tsx
│       ├── index.html
│       ├── index.tsx
│       └── utils.ts
├── jestconfig.json
├── lib/
│   ├── README.md
│   ├── __tests__/
│   │   └── demo.test.js
│   ├── assets/
│   │   ├── iconfont.css
│   │   ├── iconfont.js
│   │   └── iconfont.ts
│   ├── component/
│   │   └── ReactVirtualizedScroll/
│   │       ├── ReactVirtualizedScroll.js
│   │       ├── Row.js
│   │       ├── index.d.ts
│   │       ├── index.js
│   │       ├── style.css
│   │       ├── svg.js
│   │       └── utils.js
│   └── package.json
├── package.json
├── src/
│   ├── __tests__/
│   │   └── demo.test.tsx
│   ├── assets/
│   │   ├── iconfont.css
│   │   └── iconfont.js
│   ├── component/
│   │   └── ReactVirtualizedScroll/
│   │       ├── ReactVirtualizedScroll.tsx
│   │       ├── index.tsx
│   │       ├── style.css
│   │       └── svg.ts
│   └── types/
│       ├── demo/
│       │   └── index.d.ts
│       └── global.d.ts
├── tsconfig.json
├── tslint.json
└── webpack.config.js

================================================
FILE CONTENTS
================================================

================================================
FILE: .babelrc
================================================
{
    "presets": [
      ["env", {
        "modules": false,
        "targets": {
          "browsers": ["> 1%", "last 2 versions", "not ie <= 8"]
        }
      }],
      "stage-2"
    ],
    "plugins": ["transform-vue-jsx", "transform-runtime"]
  }
  

================================================
FILE: .editorconfig
================================================
# EditorConfig is awesome: https://EditorConfig.org

# top-most EditorConfig file
root = true

# Unix-style newlines with a newline ending every file
[*]
end_of_line = lf
insert_final_newline = true
charset = utf-8
indent_style = space
indent_size = 4

[{*.json,*.md,*.yml,*.*rc}]
indent_style = space
indent_size = 2

================================================
FILE: .gitattributes
================================================
*.html linguist-language=JavaScript

================================================
FILE: .gitignore
================================================
/node_modules/
/dist/
/coverage/
*.log


================================================
FILE: .npmignore
================================================
/.git/
/.vscode/
/node_modules/
.gitignore
.npmignore
.prettierrc
.editorconfig
tslint.json
tsconfig.json
note.md
*.log


================================================
FILE: .prettierrc
================================================
{
  "trailingComma": "all",
  "tabWidth": 4,
  "semi": false,
  "singleQuote": true,
  "endOfLine": "lf",
  "printWidth": 120,
  "overrides": [
    {
      "files": ["*.md", "*.json", "*.yml", "*.yaml"],
      "options": {
        "tabWidth": 2
      }
    }
  ]
}


================================================
FILE: .travis.yml
================================================
language: node_js
node_js:
    - '12'
install:
    - npm install
script:
    - npm run test
    - npm run lint


================================================
FILE: LICENSE
================================================
MIT License

Copyright (c) 2013-present, DavidWong9785(Zhaokang Huang)

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.


================================================
FILE: README.md
================================================
# react-virtualized-scroll
虚拟滚动搭配上拉下滑加载的scroll组件

[![github](https://img.shields.io/github/package-json/v/DavidWong9785/react-virtualized-scroll?logo=github)](https://github.com/DavidWong9785/react-virtualized-scroll)
[![issues](https://img.shields.io/github/issues/DavidWong9785/react-virtualized-scroll)](https://github.com/DavidWong9785/react-virtualized-scroll/issues)
[![forks](https://img.shields.io/github/forks/DavidWong9785/react-virtualized-scroll)](https://github.com/DavidWong9785/react-virtualized-scroll)
[![stars](https://img.shields.io/github/stars/DavidWong9785/react-virtualized-scroll)](https://github.com/DavidWong9785/react-virtualized-scroll)<br><br>
[![npm](https://img.shields.io/npm/v/react-virtualized-scroll?label=versoin&logo=npm)](https://www.npmjs.com/package/react-virtualized-scroll)
[![downloads](https://img.shields.io/npm/dm/react-virtualized-scroll?logo=npm)](https://www.npmjs.com/package/react-virtualized-scroll)
[![npm bundle size](https://img.shields.io/bundlephobia/minzip/react-virtualized-scroll)](https://www.npmjs.com/package/react-virtualized-scroll)
![license](https://img.shields.io/github/license/DavidWong9785/react-virtualized-scroll)
![github last commit](https://img.shields.io/github/last-commit/DavidWong9785/react-virtualized-scroll)

![avatar](./test.gif)

### 简介

- 搭配 <code style="color: #ff8080">typescript</code> 和 <code style="color: #ff8080">react-hooks</code> 编写的虚拟滚动组件
- 基于  <code style="color: #ff8080">react-virtualized</code> 进行再封装。
- 暴露了 <code style="color: #ff8080">react-virtualized</code> 的 ref,可调用 <code style="color: #ff8080">react-virtualized</code> 的方法
- 除了渲染列表,你还可以传入其他的子组件(如悬浮球~等),只需要把定位设为 fixed

### 安装导入

> cnpm i react-virtualized react-virtualized-scroll --save

> import ReactVirtualizedScroll from 'react-virtualized-scroll'

### 使用

```
    <ReactVirtualizedScroll
        onPullDown={handlePullDown}
        onPullUp={handlePullUp}
        hasMore={hasMore}
        data={data}
        row={Row}
        height={"100vh"}
        width={"100vw"}
        onScroll={onScroll}
        info={info}
        logo={logo}>
        <div style="position: fixed;top: 50%">fixed element</div>
    </ReactVirtualizedScroll>
```

### 属性
<table>
    <tr>
        <td>名称</td>
        <td>类型</td>
        <td>说明</td>
    </tr>
    <tr>
        <td style="width: 150px;text-align:center">width、height</td>
        <td>string</td>
        <td>列表宽高,带单位</td>
        <td style="width: 140px;text-align:center">
            <p style="margin-bottom: 10px">可选</p>
            <p style="margin-bottom: 0px">默认100vw/vh</p>
        </td>
    </tr>
    <tr>
        <td style="width: 150px;text-align:center">hasMore</td>
        <td>boolean</td>
        <td>判断是否还可以下滑加载</td>
        <td style="width: 140px;text-align:center;color: orange">必传,默认true</td>
    </tr>
    <tr>
        <td style="width: 150px;text-align:center">data</td>
        <td>array</td>
        <td>用于渲染列表的目标数</td>
        <td style="width: 140px;text-align:center;color: orange">必传,默认 []</td>
    </tr>
    <tr>
        <td style="width: 150px;text-align:center">info</td>
        <td>object</td>
        <td>需要传入 row 渲染函数作为参数的数据</td>
        <td style="width: 140px;text-align:center">可选</td>
    </tr>
    <tr>
        <td style="width: 150px;text-align:center">logo</td>
        <td>object</td>
        <td>加载时展示的 loading 图案,四个属性</td>
        <td style="width: 140px;text-align:center">
            <p style="margin-bottom: 10px">可选</p>
            <p style="margin-bottom: 0px">有默认logo</p>
        </td>
    </tr>
    <tr>
        <td style="width: 150px;text-align:center">onPullDown</td>
        <td>function</td>
        <td>
            <p style="margin-bottom: 10px;color: orange">
                下拉加载回调
            </p>
            <p style="margin-bottom: 10px">
                该方法必须返回一个 <code style="color: orange">promise</code> 对象 ( 用于控制下拉 loading 状态 )
            </p>
            <p style="margin-bottom: 10px">
                可以使用 <code style="color: orange">async</code> 方法或者直接返回 <code style="color: orange">promise</code> 对象
            </p>
            <p style="margin-bottom: 0">
                当 <code style="color: orange">promise</code> 状态完成之后 ( resolve/reject ),下拉加载状态结束
            </p>
        </td>
        <td style="width: 140px;text-align:center">可选</td>
    </tr>
    <tr>
        <td style="width: 150px;text-align:center">onPullUp</td>
        <td>function</td>
        <td>
            上滑加载回调,目的同上,该方法需要返回一个 <code style="color: orange">promise</code> 对象
        </td>
        <td style="width: 140px;text-align:center">可选</td>
    </tr>
    <tr>
        <td style="width: 150px;text-align:center">onScroll</td>
        <td>function</td>
        <td>
            <p style="margin-bottom: 10px;color: orange">滑动回调</p>
            <p style="margin-bottom: 10px">参数1: clientHeight</p>
            <p style="margin-bottom: 10px">参数2: scrollTop</p>
            <p style="margin-bottom: 0px">参数3: scrollHeight</p>
        </td>
        <td style="width: 140px;text-align:center">可选</td>
    </tr>
    <tr>
        <td style="width: 150px;text-align:center">row</td>
        <td>function</td>
        <td>
            <p style="margin-bottom: 10px;color: orange">列表每一行的渲染函数</p>
            <p style="margin-bottom: 10px">参数1:类型为object,属性包含该行索引 index 和自定义传入的 info 属性</p>
            <p style="margin-bottom: 0px">参数2:用于渲染列表的目标数组data</p>
        </td>
        <td style="width: 140px;text-align:center;color: orange">必传</td>
    </tr>
</table>

### logo属性(字符串,图片等等,只要是JSX.Element即可)

| 属性 | 说明 |
| ---------------- | --------------------- |
| pulldown_loading | 下拉加载 loading 的 logo |
| pulldown_success | 下拉加载 成功 的 logo |
| pullup_loading   | 上滑加载 loading 的 logo |
| pullup_success   | 上滑加载 成功 的 logo |

================================================
FILE: example/src/app.tsx
================================================
/* tslint:disable */
import React, { useState, useCallback } from 'react'
import ReactVirtualizedScroll from '../../lib/component/ReactVirtualizedScroll/index.js'
import useStateAndRef from './utils'
// import ReactVirtualizedScroll from '../../src/component/ReactVirtualizedScroll/index.tsx'
import { loading_pullup } from '../../src/component/ReactVirtualizedScroll/svg'

const initState = [{
    key: 1,
    value: 1
}, {
    key: 2,
    value: 2
}, {
    key: 3,
    value: 3
}, {
    key: 4,
    value: 4
}, {
    key: 5,
    value: 5
}]

const example = () => {
    const [data, setData, dataRef] = useStateAndRef(initState)

    const [hasMore, setHasMore] = useState(true)
    const info = {
        title: 'VirtualizedScroll',
        desc: '虚拟滚动搭配上拉下滑加载的scroll组件'
    }
    const requestPullDown = () => {
        return new Promise(resolve => {
            setTimeout(() => {
                setData(initState)
                setHasMore(true)
                resolve()
            }, 2000);
        })
    }
    const requestPullUp = useCallback(
        () => {
            return new Promise(resolve => {
                if (data.length === 100) {
                    setHasMore(false)
                    resolve()
                }
                else {
                    setTimeout(() => {
                        const target: any = []
                        for (let i = data.length + 1; i < data.length + 6; i++) {
                            target.push({
                                key: i,
                                value: i
                            })
                        }
                        setData(data.concat(target))
                        resolve()
                    }, 1000);
                }
            })
        },
        [data],
    )
    const handlePullDown = async () => {
        await requestPullDown()
    }
    const handlePullUp = async () => {
        await requestPullUp()
    }
    const onScroll = (clientHeight: number, scrollTop: number, scrollHeight: number) => {
        // console.log('onScroll')
    }
    const logo = {
        pulldown_loading: <i className="icon iconfont iconshuaxin"></i>,
        pulldown_success: <i className="icon iconfont iconcheck-circle"></i>,
        pullup_loading:  <img src={loading_pullup}/>,
        pullup_success: '没有更多了',
    }
    const countAdd = ((index: number) => {
        const newData = dataRef.current
        newData[index].value += 100
        setData(JSON.parse(JSON.stringify(newData)))
    })

    const Row = ((args: any) => {
        const {index, info, data} = args
        return <div style={{
            width: '100vw',
            height: '200px',
            display: 'flex',
            justifyContent: 'center',
            alignItems: 'center',
            flexDirection: 'column',
            background: '#6495ED',
            color: '#fff',
            marginBottom: '10px'
        }}
        onClick={() => countAdd(index)}>
            <p>{ info.title } - { data[index].value }</p>
            <p>{ info.desc }</p>
        </div>
    })

    return (
        <div>
            <ReactVirtualizedScroll
                onPullUp={handlePullUp}
                onPullDown={handlePullDown}
                hasMore={hasMore}
                data={data}
                row={Row}
                height={"100vh"}
                onScroll={onScroll}
                info={info}
                logo={logo}>
            </ReactVirtualizedScroll>
        </div>
    )
}

export default example


================================================
FILE: example/src/index.html
================================================
<!DOCTYPE html>
<html lang="en">
    <head>
        <meta charset="UTF-8" />
        <meta name="viewport" content="width=device-width, initial-scale=1.0" />
        <meta http-equiv="X-UA-Compatible" content="ie=edge" />
        <title>NPMPluginTemplate</title>
    </head>
    <body>
        <div id="root"></div>
    </body>
</html>


================================================
FILE: example/src/index.tsx
================================================
import React from 'react'
import { render } from 'react-dom'
import App from './app'
render(<App />, document.getElementById('root'))


================================================
FILE: example/src/utils.ts
================================================
import React, { useState, useEffect, useRef } from 'react'
export default (initState) => {
    const [data, setData] = useState(initState)
    const dataRef = useRef(data)
    useEffect(() => {
        dataRef.current = data
    }, [data])
    return [data, setData, dataRef]
}

================================================
FILE: jestconfig.json
================================================
{
  "transform": {
    "^.+\\.(t|j)sx?$": "ts-jest",
    "^.+\\.jsx?$": "babel-jest"
  },
  "testRegex": "(/__tests__/.*|(\\.|/)(test|spec))\\.(jsx?|tsx?)$",
  "moduleFileExtensions": ["tsx", "ts", "js", "jsx", "json", "node"],
  "moduleNameMapper": {
    "\\.(s?css|less)$": "identity-obj-proxy"
  }
}


================================================
FILE: lib/README.md
================================================
# react-virtualized-scroll
虚拟滚动搭配上拉下滑加载的scroll组件

[![github](https://img.shields.io/github/package-json/v/DavidWong9785/react-virtualized-scroll?logo=github)](https://github.com/DavidWong9785/react-virtualized-scroll)
[![issues](https://img.shields.io/github/issues/DavidWong9785/react-virtualized-scroll)](https://github.com/DavidWong9785/react-virtualized-scroll/issues)
[![forks](https://img.shields.io/github/forks/DavidWong9785/react-virtualized-scroll)](https://github.com/DavidWong9785/react-virtualized-scroll)
[![stars](https://img.shields.io/github/stars/DavidWong9785/react-virtualized-scroll)](https://github.com/DavidWong9785/react-virtualized-scroll)<br><br>
[![npm](https://img.shields.io/npm/v/react-virtualized-scroll?label=versoin&logo=npm)](https://www.npmjs.com/package/react-virtualized-scroll)
[![downloads](https://img.shields.io/npm/dm/react-virtualized-scroll?logo=npm)](https://www.npmjs.com/package/react-virtualized-scroll)
[![npm bundle size](https://img.shields.io/bundlephobia/minzip/react-virtualized-scroll)](https://www.npmjs.com/package/react-virtualized-scroll)
![license](https://img.shields.io/github/license/DavidWong9785/react-virtualized-scroll)
![github last commit](https://img.shields.io/github/last-commit/DavidWong9785/react-virtualized-scroll)

![avatar](./test.gif)

### 简介

- 搭配 <code style="color: #ff8080">typescript</code> 和 <code style="color: #ff8080">react-hooks</code> 编写的虚拟滚动组件
- 基于  <code style="color: #ff8080">react-virtualized</code> 进行再封装。
- 暴露了 <code style="color: #ff8080">react-virtualized</code> 的 ref,可调用 <code style="color: #ff8080">react-virtualized</code> 的方法
- 除了渲染列表,你还可以传入其他的子组件(如悬浮球~等),只需要把定位设为 fixed

### 安装导入

> cnpm i react-virtualized react-virtualized-scroll --save

> import ReactVirtualizedScroll from 'react-virtualized-scroll'

### 使用

```
    <ReactVirtualizedScroll
        onPullDown={handlePullDown}
        onPullUp={handlePullUp}
        hasMore={hasMore}
        data={data}
        row={Row}
        height={"100vh"}
        width={"100vw"}
        onScroll={onScroll}
        info={info}
        logo={logo}>
        <div style="position: fixed;top: 50%">fixed element</div>
    </ReactVirtualizedScroll>
```

### 属性
<table>
    <tr>
        <td>名称</td>
        <td>类型</td>
        <td>说明</td>
    </tr>
    <tr>
        <td style="width: 150px;text-align:center">width、height</td>
        <td>string</td>
        <td>列表宽高,带单位</td>
        <td style="width: 140px;text-align:center">
            <p style="margin-bottom: 10px">可选</p>
            <p style="margin-bottom: 0px">默认100vw/vh</p>
        </td>
    </tr>
    <tr>
        <td style="width: 150px;text-align:center">hasMore</td>
        <td>boolean</td>
        <td>判断是否还可以下滑加载</td>
        <td style="width: 140px;text-align:center;color: orange">必传,默认true</td>
    </tr>
    <tr>
        <td style="width: 150px;text-align:center">data</td>
        <td>array</td>
        <td>用于渲染列表的目标数</td>
        <td style="width: 140px;text-align:center;color: orange">必传,默认 []</td>
    </tr>
    <tr>
        <td style="width: 150px;text-align:center">info</td>
        <td>object</td>
        <td>需要传入 row 渲染函数作为参数的数据</td>
        <td style="width: 140px;text-align:center">可选</td>
    </tr>
    <tr>
        <td style="width: 150px;text-align:center">logo</td>
        <td>object</td>
        <td>加载时展示的 loading 图案,四个属性</td>
        <td style="width: 140px;text-align:center">
            <p style="margin-bottom: 10px">可选</p>
            <p style="margin-bottom: 0px">有默认logo</p>
        </td>
    </tr>
    <tr>
        <td style="width: 150px;text-align:center">onPullDown</td>
        <td>function</td>
        <td>
            <p style="margin-bottom: 10px;color: orange">
                下拉加载回调
            </p>
            <p style="margin-bottom: 10px">
                该方法必须返回一个 <code style="color: orange">promise</code> 对象 ( 用于控制下拉 loading 状态 )
            </p>
            <p style="margin-bottom: 10px">
                可以使用 <code style="color: orange">async</code> 方法或者直接返回 <code style="color: orange">promise</code> 对象
            </p>
            <p style="margin-bottom: 0">
                当 <code style="color: orange">promise</code> 状态完成之后 ( resolve/reject ),下拉加载状态结束
            </p>
        </td>
        <td style="width: 140px;text-align:center">可选</td>
    </tr>
    <tr>
        <td style="width: 150px;text-align:center">onPullUp</td>
        <td>function</td>
        <td>
            上滑加载回调,目的同上,该方法需要返回一个 <code style="color: orange">promise</code> 对象
        </td>
        <td style="width: 140px;text-align:center">可选</td>
    </tr>
    <tr>
        <td style="width: 150px;text-align:center">onScroll</td>
        <td>function</td>
        <td>
            <p style="margin-bottom: 10px;color: orange">滑动回调</p>
            <p style="margin-bottom: 10px">参数1: clientHeight</p>
            <p style="margin-bottom: 10px">参数2: scrollTop</p>
            <p style="margin-bottom: 0px">参数3: scrollHeight</p>
        </td>
        <td style="width: 140px;text-align:center">可选</td>
    </tr>
    <tr>
        <td style="width: 150px;text-align:center">row</td>
        <td>function</td>
        <td>
            <p style="margin-bottom: 10px;color: orange">列表每一行的渲染函数</p>
            <p style="margin-bottom: 10px">参数1:类型为object,属性包含该行索引 index 和自定义传入的 info 属性</p>
            <p style="margin-bottom: 0px">参数2:用于渲染列表的目标数组data</p>
        </td>
        <td style="width: 140px;text-align:center;color: orange">必传</td>
    </tr>
</table>

### logo属性(字符串,图片等等,只要是JSX.Element即可)

| 属性 | 说明 |
| ---------------- | --------------------- |
| pulldown_loading | 下拉加载 loading 的 logo |
| pulldown_success | 下拉加载 成功 的 logo |
| pullup_loading   | 上滑加载 loading 的 logo |
| pullup_success   | 上滑加载 成功 的 logo |

================================================
FILE: lib/__tests__/demo.test.js
================================================
"use strict";
var __assign = (this && this.__assign) || function () {
    __assign = Object.assign || function(t) {
        for (var s, i = 1, n = arguments.length; i < n; i++) {
            s = arguments[i];
            for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p))
                t[p] = s[p];
        }
        return t;
    };
    return __assign.apply(this, arguments);
};
var __importDefault = (this && this.__importDefault) || function (mod) {
    return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
var react_1 = __importDefault(require("react"));
var enzyme_1 = require("enzyme");
var enzyme_adapter_react_16_1 = __importDefault(require("enzyme-adapter-react-16"));
var index_1 = __importDefault(require("../component/ReactVirtualizedScroll/index"));
enzyme_1.configure({ adapter: new enzyme_adapter_react_16_1.default() });
var setup = function () {
    // 模拟 props
    var props = {
        height: '100vh',
        row: function () { },
        hasMore: true
    };
    // 通过 enzyme 提供的 shallow(浅渲染) 创建组件
    var wrapper = enzyme_1.shallow(react_1.default.createElement(index_1.default, __assign({}, props)));
    return {
        props: props,
        wrapper: wrapper,
    };
};
describe('测试height属性', function () {
    var _a = setup(), wrapper = _a.wrapper, props = _a.props;
    it('props', function () {
        expect(props.height).toEqual('100vh');
    });
});


================================================
FILE: lib/assets/iconfont.css
================================================
@font-face {font-family: "iconfont";
  src: url('iconfont.eot?t=1578637319034'); /* IE9 */
  src: url('iconfont.eot?t=1578637319034#iefix') format('embedded-opentype'), /* IE6-IE8 */
  url('data:application/x-font-woff2;charset=utf-8;base64,d09GMgABAAAAAATYAAsAAAAACVwAAASMAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHEIGVgCDSAqFRIRoATYCJAMYCw4ABCAFhG0HYhsoCFFUTppkf4U4RBYobL8q1RqS2WPnlCFBo7GKFHDAYghuPVikPTPGSvDG5xkqd+fb7TfWfzouIB7+f79v+1wblWaOScQTnliEhDdLM/2TaIXkoZHMmmfyGzjnonwDm65BowSjLG08nE1kzfkfpDGBft9vrrIERkSYRbmKUO0Rzpv+EqTpwcC6PI12AhiN9IK2NtffElXBPp0cfBcOAs798xgziFvb89w8Bzxk4ZqNpuRg+pv/wrmxywtwTVzLA0w86gIa6/PvCxzBcfCfO8BDunlbQhnWPJBEw7a29N878nqgwANVvaLX13vRdP7/905/6/gDa13Lcplj08IA44ACGmPbIiuQTpigpqLOyC4BXh0eJjBoHgM8t7/eU1fhjQrEvcAz1K1plREU+hWtZ2FZAIla+tPjNHiSvj/+ORzWJDXzJl69sXNo+XNYD+rkPcbw9jNDWUbGXoBC7PRaH2nk0b1gg9YvNJ1HhvVLys/hD/5sV8+mJvScYdj/yyNURZKJBtJhJl2MVX4Oh2phyQ6C2ye7DgaFX7tqiWU9yDy6su04YAjviL2AJ0il8Zw9Qt1PDu13ZTQHuseSdB/wVk3Qktl6ytKuH0SgiqMfxD6g973BG2xHUEQzq1UyZ4umsha6ZzKm9shpGK+WQe8YssH8DuyqW1qqirD/2ukZ090542X17dYJqd9G2u+m7g3T7ItPSqVt9H0MsHWDPjhS1Nxa0MvQ2DlhmnWlrSO6bSPkRdJK3Ql6u4RRAU3piFaDVhtdN23dPaPKG7C9SgYm8+URXWQQXlOr1yCfFVuhdYgu7IMm/qTwREjDp7bq8VDb+oqV2Mod5Psb/uAdaHYQsKIbEC6epTtzuXeVjfObxOyVJS036DgL07KOgv/I/0uIDogNIZf4pA0+O4Mh4jEbQr4p4BW5NarmYeDj4xN54e3f5zaCAs/o3GzZsNUf2cPr6bn7fWa5y4A18BKxubb53a/jQ0ku1scaTQjw1C2ge4x/+uZ3fQLascKZ5+wGl8dJD1BaTn1cQEr57y0PlNXkq+VOkNMAG1c2k8WagH18TBWQ26vD8d0AsAOgm1HCVanqhC82cdybFQ6HTPKie2qCI/9Nn/FjV76jU/5/L9Yu4POJ2lB38zyrTvSXkJnN++9UlBVR7qgC1rVi1gllz9dlaU5rcThh0HfSwTnpu5d8ZnY+od9MCUmfOcj6reIKaS9UQ45C0+8kDNpDXz5kSqohygC2lQLCuAmSUa8hG3fGFdIHqll/aMYDhkHXgtxwyHqM92WBUThs/3Nks9QNDNrPCm/wqthIVZCSHyFlEGBxPG0mDkghe0zJfrx5ri77kiWsieMQxxnHkoWwOg5V8wU/cfueNHayhPrOEmAocDDbPxaxMik3bq76rdffgKcSM2SkrsX8CEQpaJ+JOMIM3EGazqp7l+6ZH565nHJ5mE9kEkyDGWI/mmFxf78QWGosXBHOLfDUyJ8rHZ8vT17lFhjkPbJFihwlarTo03ffr8xfkA4dHzYaOYHYGO0UcWac3rN0GeUote8Hsars59IQAQ==') format('woff2'),
  url('iconfont.woff?t=1578637319034') format('woff'),
  url('iconfont.ttf?t=1578637319034') format('truetype'), /* chrome, firefox, opera, Safari, Android, iOS 4.2+ */
  url('iconfont.svg?t=1578637319034#iconfont') format('svg'); /* iOS 4.1- */
}

.iconfont {
  font-family: "iconfont" !important;
  font-size: 16px;
  font-style: normal;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
}

.iconshuaxin:before {
  content: "\e60c";
}

.iconcheck-circle:before {
  content: "\e77d";
}

.iconreload:before {
  content: "\e788";
}

.iconicon-test:before {
  content: "\e658";
}

.iconfiltration:before {
  content: "\e630";
}



================================================
FILE: lib/assets/iconfont.js
================================================
"use strict";
!function (l) { var e, c = '<svg><symbol id="iconshuaxin" viewBox="0 0 1024 1024"><path d="M875 483c-33.4 0-60.5 27.1-60.5 60.5v0.1C814.4 710.3 678.8 846 512 846S209.5 710.3 209.5 543.5 345.2 241 512 241c36.8 0 71.7 7.6 104.4 19.7-32 3-57.4 29.1-57.4 61.9 0 34.8 28.2 63 63 63h201.9c34.8 0 63-28.2 63-63V120c0-34.8-28.2-63-63-63s-63 28.2-63 63v81.4C691 150.5 605.2 120 512 120 278.1 120 88.5 309.6 88.5 543.5S278.1 967 512 967s423.5-189.6 423.5-423.5c0-33.4-27.1-60.5-60.5-60.5z"  ></path></symbol><symbol id="iconcheck-circle" viewBox="0 0 1024 1024"><path d="M699 353h-46.9c-10.2 0-19.9 4.9-25.9 13.3L469 584.3l-71.2-98.8c-6-8.3-15.6-13.3-25.9-13.3H325c-6.5 0-10.3 7.4-6.5 12.7l124.6 172.8c12.7 17.7 39 17.7 51.7 0l210.6-292c3.9-5.3 0.1-12.7-6.4-12.7z"  ></path><path d="M512 64C264.6 64 64 264.6 64 512s200.6 448 448 448 448-200.6 448-448S759.4 64 512 64z m0 820c-205.4 0-372-166.6-372-372s166.6-372 372-372 372 166.6 372 372-166.6 372-372 372z"  ></path></symbol><symbol id="iconreload" viewBox="0 0 1024 1024"><path d="M909.1 209.3l-56.4 44.1C775.8 155.1 656.2 92 521.9 92 290 92 102.3 279.5 102 511.5 101.7 743.7 289.8 932 521.9 932c181.3 0 335.8-115 394.6-276.1 1.5-4.2-0.7-8.9-4.9-10.3l-56.7-19.5c-4.1-1.4-8.6 0.7-10.1 4.8-1.8 5-3.8 10-5.9 14.9-17.3 41-42.1 77.8-73.7 109.4-31.6 31.6-68.4 56.4-109.3 73.8-42.3 17.9-87.4 27-133.8 27-46.5 0-91.5-9.1-133.8-27-40.9-17.3-77.7-42.1-109.3-73.8-31.6-31.6-56.4-68.4-73.7-109.4-17.9-42.4-27-87.4-27-133.9s9.1-91.5 27-133.9c17.3-41 42.1-77.8 73.7-109.4 31.6-31.6 68.4-56.4 109.3-73.8 42.3-17.9 87.4-27 133.8-27 46.5 0 91.5 9.1 133.8 27 40.9 17.3 77.7 42.1 109.3 73.8 9.9 9.9 19.2 20.4 27.8 31.4l-60.2 47c-5.3 4.1-3.5 12.5 3 14.1l175.6 43c5 1.2 9.9-2.6 9.9-7.7l0.8-180.9c-0.1-6.6-7.8-10.3-13-6.2z"  ></path></symbol><symbol id="iconicon-test" viewBox="0 0 1024 1024"><path d="M512 685.248l-278.624-278.624 45.248-45.248L512 594.752l233.376-233.376 45.248 45.248z" fill="#181818" ></path></symbol><symbol id="iconfiltration" viewBox="0 0 1211 1024"><path d="M131.45833333 215.12500024a37.2023811 37.2023811 0 0 1 37.2023811-37.2023811h669.6428574a37.2023811 37.2023811 0 0 1 0 74.40476221h-669.6428574a37.2023811 37.2023811 0 0 1-37.2023811-37.20238111zM131.45833333 512.74404742a37.2023811 37.2023811 0 0 1 37.2023811-37.2023811h669.6428574a37.2023811 37.2023811 0 0 1 0 74.4047622h-669.6428574a37.2023811 37.2023811 0 0 1-37.2023811-37.2023811zM131.45833333 810.36309543a37.2023811 37.2023811 0 0 1 37.2023811-37.2023811h669.6428574a37.2023811 37.2023811 0 0 1 0 74.4047622h-669.6428574a37.2023811 37.2023811 0 0 1-37.2023811-37.2023811zM987.11309541 90.125a37.2023811 37.2023811 0 0 1 37.2023811 37.2023811v769.3452378a37.2023811 37.2023811 0 0 1-74.4047622 0V127.3273811a37.2023811 37.2023811 0 0 1 37.2023811-37.2023811z"  ></path><path d="M1118.80952413 764.97619018a37.94642852 37.94642852 0 0 1 0 52.82738114l-105.65476228 104.91071402a36.83035739 36.83035739 0 0 1-52.08333287-52.08333288l104.91071401-105.65476228a37.94642852 37.94642852 0 0 1 52.82738114 0z"  ></path></symbol></svg>', t = (e = document.getElementsByTagName("script"))[e.length - 1].getAttribute("data-injectcss"); if (t && !l.__iconfont__svg__cssinject__) {
    l.__iconfont__svg__cssinject__ = !0;
    try {
        document.write("<style>.svgfont {display: inline-block;width: 1em;height: 1em;fill: currentColor;vertical-align: -0.1em;font-size:16px;}</style>");
    }
    catch (e) {
        console && console.log(e);
    }
} !function (e) { if (document.addEventListener)
    if (~["complete", "loaded", "interactive"].indexOf(document.readyState))
        setTimeout(e, 0);
    else {
        var t = function () { document.removeEventListener("DOMContentLoaded", t, !1), e(); };
        document.addEventListener("DOMContentLoaded", t, !1);
    }
else
    document.attachEvent && (o = e, i = l.document, a = !1, (c = function () { try {
        i.documentElement.doScroll("left");
    }
    catch (e) {
        return void setTimeout(c, 50);
    } n(); })(), i.onreadystatechange = function () { "complete" == i.readyState && (i.onreadystatechange = null, n()); }); function n() { a || (a = !0, o()); } var o, i, a, c; }(function () { var e, t, n, o, i, a; (e = document.createElement("div")).innerHTML = c, c = null, (t = e.getElementsByTagName("svg")[0]) && (t.setAttribute("aria-hidden", "true"), t.style.position = "absolute", t.style.width = 0, t.style.height = 0, t.style.overflow = "hidden", n = t, (o = document.body).firstChild ? (i = n, (a = o.firstChild).parentNode.insertBefore(i, a)) : o.appendChild(n)); }); }(window);


================================================
FILE: lib/assets/iconfont.ts
================================================
"use strict";
!function (l) { var e, c = '<svg><symbol id="iconshuaxin" viewBox="0 0 1024 1024"><path d="M875 483c-33.4 0-60.5 27.1-60.5 60.5v0.1C814.4 710.3 678.8 846 512 846S209.5 710.3 209.5 543.5 345.2 241 512 241c36.8 0 71.7 7.6 104.4 19.7-32 3-57.4 29.1-57.4 61.9 0 34.8 28.2 63 63 63h201.9c34.8 0 63-28.2 63-63V120c0-34.8-28.2-63-63-63s-63 28.2-63 63v81.4C691 150.5 605.2 120 512 120 278.1 120 88.5 309.6 88.5 543.5S278.1 967 512 967s423.5-189.6 423.5-423.5c0-33.4-27.1-60.5-60.5-60.5z"  ></path></symbol><symbol id="iconcheck-circle" viewBox="0 0 1024 1024"><path d="M699 353h-46.9c-10.2 0-19.9 4.9-25.9 13.3L469 584.3l-71.2-98.8c-6-8.3-15.6-13.3-25.9-13.3H325c-6.5 0-10.3 7.4-6.5 12.7l124.6 172.8c12.7 17.7 39 17.7 51.7 0l210.6-292c3.9-5.3 0.1-12.7-6.4-12.7z"  ></path><path d="M512 64C264.6 64 64 264.6 64 512s200.6 448 448 448 448-200.6 448-448S759.4 64 512 64z m0 820c-205.4 0-372-166.6-372-372s166.6-372 372-372 372 166.6 372 372-166.6 372-372 372z"  ></path></symbol><symbol id="iconreload" viewBox="0 0 1024 1024"><path d="M909.1 209.3l-56.4 44.1C775.8 155.1 656.2 92 521.9 92 290 92 102.3 279.5 102 511.5 101.7 743.7 289.8 932 521.9 932c181.3 0 335.8-115 394.6-276.1 1.5-4.2-0.7-8.9-4.9-10.3l-56.7-19.5c-4.1-1.4-8.6 0.7-10.1 4.8-1.8 5-3.8 10-5.9 14.9-17.3 41-42.1 77.8-73.7 109.4-31.6 31.6-68.4 56.4-109.3 73.8-42.3 17.9-87.4 27-133.8 27-46.5 0-91.5-9.1-133.8-27-40.9-17.3-77.7-42.1-109.3-73.8-31.6-31.6-56.4-68.4-73.7-109.4-17.9-42.4-27-87.4-27-133.9s9.1-91.5 27-133.9c17.3-41 42.1-77.8 73.7-109.4 31.6-31.6 68.4-56.4 109.3-73.8 42.3-17.9 87.4-27 133.8-27 46.5 0 91.5 9.1 133.8 27 40.9 17.3 77.7 42.1 109.3 73.8 9.9 9.9 19.2 20.4 27.8 31.4l-60.2 47c-5.3 4.1-3.5 12.5 3 14.1l175.6 43c5 1.2 9.9-2.6 9.9-7.7l0.8-180.9c-0.1-6.6-7.8-10.3-13-6.2z"  ></path></symbol><symbol id="iconicon-test" viewBox="0 0 1024 1024"><path d="M512 685.248l-278.624-278.624 45.248-45.248L512 594.752l233.376-233.376 45.248 45.248z" fill="#181818" ></path></symbol><symbol id="iconfiltration" viewBox="0 0 1211 1024"><path d="M131.45833333 215.12500024a37.2023811 37.2023811 0 0 1 37.2023811-37.2023811h669.6428574a37.2023811 37.2023811 0 0 1 0 74.40476221h-669.6428574a37.2023811 37.2023811 0 0 1-37.2023811-37.20238111zM131.45833333 512.74404742a37.2023811 37.2023811 0 0 1 37.2023811-37.2023811h669.6428574a37.2023811 37.2023811 0 0 1 0 74.4047622h-669.6428574a37.2023811 37.2023811 0 0 1-37.2023811-37.2023811zM131.45833333 810.36309543a37.2023811 37.2023811 0 0 1 37.2023811-37.2023811h669.6428574a37.2023811 37.2023811 0 0 1 0 74.4047622h-669.6428574a37.2023811 37.2023811 0 0 1-37.2023811-37.2023811zM987.11309541 90.125a37.2023811 37.2023811 0 0 1 37.2023811 37.2023811v769.3452378a37.2023811 37.2023811 0 0 1-74.4047622 0V127.3273811a37.2023811 37.2023811 0 0 1 37.2023811-37.2023811z"  ></path><path d="M1118.80952413 764.97619018a37.94642852 37.94642852 0 0 1 0 52.82738114l-105.65476228 104.91071402a36.83035739 36.83035739 0 0 1-52.08333287-52.08333288l104.91071401-105.65476228a37.94642852 37.94642852 0 0 1 52.82738114 0z"  ></path></symbol></svg>', t = (e = document.getElementsByTagName("script"))[e.length - 1].getAttribute("data-injectcss"); if (t && !l.__iconfont__svg__cssinject__) {
    l.__iconfont__svg__cssinject__ = !0;
    try {
        document.write("<style>.svgfont {display: inline-block;width: 1em;height: 1em;fill: currentColor;vertical-align: -0.1em;font-size:16px;}</style>");
    }
    catch (e) {
        console && console.log(e);
    }
} !function (e) { if (document.addEventListener)
    if (~["complete", "loaded", "interactive"].indexOf(document.readyState))
        setTimeout(e, 0);
    else {
        var t = function () { document.removeEventListener("DOMContentLoaded", t, !1), e(); };
        document.addEventListener("DOMContentLoaded", t, !1);
    }
else
    document.attachEvent && (o = e, i = l.document, a = !1, (c = function () { try {
        i.documentElement.doScroll("left");
    }
    catch (e) {
        return void setTimeout(c, 50);
    } n(); })(), i.onreadystatechange = function () { "complete" == i.readyState && (i.onreadystatechange = null, n()); }); function n() { a || (a = !0, o()); } var o, i, a, c; }(function () { var e, t, n, o, i, a; (e = document.createElement("div")).innerHTML = c, c = null, (t = e.getElementsByTagName("svg")[0]) && (t.setAttribute("aria-hidden", "true"), t.style.position = "absolute", t.style.width = 0, t.style.height = 0, t.style.overflow = "hidden", n = t, (o = document.body).firstChild ? (i = n, (a = o.firstChild).parentNode.insertBefore(i, a)) : o.appendChild(n)); }); }(window);


================================================
FILE: lib/component/ReactVirtualizedScroll/ReactVirtualizedScroll.js
================================================
"use strict";
var __assign = (this && this.__assign) || function () {
    __assign = Object.assign || function(t) {
        for (var s, i = 1, n = arguments.length; i < n; i++) {
            s = arguments[i];
            for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p))
                t[p] = s[p];
        }
        return t;
    };
    return __assign.apply(this, arguments);
};
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
    if (k2 === undefined) k2 = k;
    Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } });
}) : (function(o, m, k, k2) {
    if (k2 === undefined) k2 = k;
    o[k2] = m[k];
}));
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
    Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
    o["default"] = v;
});
var __importStar = (this && this.__importStar) || function (mod) {
    if (mod && mod.__esModule) return mod;
    var result = {};
    if (mod != null) for (var k in mod) if (Object.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
    __setModuleDefault(result, mod);
    return result;
};
Object.defineProperty(exports, "__esModule", { value: true });
var react_1 = __importStar(require("react"));
var react_virtualized_1 = require("react-virtualized");
var svg_1 = require("./svg");
require("../../assets/iconfont.css");
require("./style.css");
var Row = function (_a) {
    var row = _a.row, data = _a.data, index = _a.index, info = _a.info;
    return react_1.useMemo(function () {
        return row({ data: data, index: index, info: info });
    }, [JSON.stringify(data[index])]);
};
var VirtualizedScroll = function (_a, ref) {
    var children = _a.children, _b = _a.hasMore, hasMore = _b === void 0 ? true : _b, _c = _a.refreshDistance, refreshDistance = _c === void 0 ? 120 : _c, _d = _a.loading, loading = _d === void 0 ? false : _d, _e = _a.data, data = _e === void 0 ? [] : _e, info = _a.info, _f = _a.height, height = _f === void 0 ? '100vh' : _f, _g = _a.width, width = _g === void 0 ? '100vw' : _g, noDataRow = _a.noDataRow, _h = _a.onPullDown, onPullDown = _h === void 0 ? null : _h, _j = _a.onPullUp, onPullUp = _j === void 0 ? null : _j, _k = _a.onScroll, onScroll = _k === void 0 ? null : _k, row = _a.row, _l = _a.logo, logo = _l === void 0 ? {} : _l;
    // 下拉状态
    var _m = react_1.useState('init'), STATS = _m[0], setSTATS = _m[1];
    // touch数据
    var _o = react_1.useState(0), startY = _o[0], setStartY = _o[1];
    var _p = react_1.useState(0), offset = _p[0], setOffset = _p[1];
    // vList容器
    var vListRef = react_1.useRef();
    var timer = react_1.useRef();
    // 上滑时,scrollTop为0禁止滑动
    var scrollingDisable = react_1.useRef(false);
    var hasMoreRef = react_1.useRef(true);
    var canNotDrag = react_1.useRef(false);
    var isPullUpLoading = react_1.useRef(false);
    react_1.useEffect(function () {
        hasMoreRef.current = hasMore;
    }, [hasMore]);
    react_1.useEffect(function () {
        canNotDrag.current = STATS === 'refreshing' || STATS === 'success' || STATS == 'scroll' || !onPullDown;
    }, [STATS]);
    var initState = function () {
        setOffset(0);
        setStartY(0);
    };
    var onTouchStart = function ($event) {
        if (canNotDrag.current || scrollingDisable.current)
            return;
        setStartY($event.nativeEvent.touches[0].pageY);
    };
    var onTouchMove = react_1.useCallback(function ($event) {
        if (canNotDrag.current || scrollingDisable.current)
            return;
        var offsetComputed = $event.nativeEvent.touches[0].pageY - startY;
        if (0 < offsetComputed && offsetComputed <= refreshDistance)
            setOffset(offsetComputed);
        else if (offsetComputed < 0)
            setOffset(0);
        else if (offsetComputed > refreshDistance)
            setOffset(refreshDistance);
        if (offset < refreshDistance && STATS !== 'dragging')
            setSTATS('dragging');
        else if (offset >= refreshDistance)
            setSTATS('pre-refresh');
    }, [startY, canNotDrag, offset, STATS]);
    var onTouchEnd = react_1.useCallback(function ($event) {
        if (canNotDrag.current)
            return;
        if (scrollingDisable.current) {
            initState();
            return;
        }
        if (STATS === 'pre-refresh') {
            setSTATS('refreshing');
            if (!onPullDown)
                return;
            onPullDown().then(function () {
                setSTATS('success');
                if (vListRef.current)
                    vListRef.current.scrollToRow(0);
                if (timer.current)
                    clearTimeout(timer.current);
                timer.current = setTimeout(function () {
                    setSTATS('init');
                    initState();
                }, 500);
            });
        }
        else {
            initState();
            setSTATS('not-enough');
            if (timer.current)
                clearTimeout(timer.current);
            timer.current = setTimeout(function () {
                setSTATS('init');
            }, 500);
        }
    }, [timer, STATS, canNotDrag]);
    var onScrollCallback = function (_a) {
        var clientHeight = _a.clientHeight, scrollTop = _a.scrollTop, scrollHeight = _a.scrollHeight;
        if (scrollTop === 0)
            scrollingDisable.current = false;
        else
            scrollingDisable.current = true;
        if ((clientHeight + scrollTop === scrollHeight) && onPullUp && !isPullUpLoading.current) {
            isPullUpLoading.current = true;
            onPullUp().then(function () {
                isPullUpLoading.current = false;
                if (vListRef.current)
                    vListRef.current.scrollToRow(data.length + 1);
            }).catch(function () {
                isPullUpLoading.current = false;
            });
        }
        if (onScroll)
            onScroll(clientHeight, scrollTop, scrollHeight);
    };
    var cache = new react_virtualized_1.CellMeasurerCache({ defaultHeight: 400, fixedWidth: true });
    react_1.useImperativeHandle(ref, function () { return ({
        vListRef: vListRef.current
    }); }, [vListRef]);
    var renderRow = react_1.useCallback(function (_a) {
        var index = _a.index, key = _a.key, parent = _a.parent, style = _a.style;
        return (react_1.default.createElement(react_virtualized_1.CellMeasurer, { cache: cache, columnIndex: 0, key: key, parent: parent, rowIndex: index },
            react_1.default.createElement("div", { className: "card-content", style: __assign({}, style), key: key },
                react_1.default.createElement(Row, { row: row, data: data, index: index, info: info }),
                index === data.length - 1 ? !hasMoreRef.current ?
                    (react_1.default.createElement("div", { className: "load-item", style: { height: '50px', width: '100%' } }, logo.pullup_success ? logo.pullup_success : '没有更多了')) :
                    (react_1.default.createElement("div", { className: "load-item", style: { height: '50px', width: '100%' } }, logo.pullup_loading ? logo.pullup_loading : react_1.default.createElement("img", { src: svg_1.loading_pullup, alt: "" }))) : '')));
    }, [data, hasMoreRef]);
    var VirtualScroll = react_1.useMemo(function () {
        return (react_1.default.createElement("div", { className: "content-wrap", style: {
                width: width,
                height: height,
                position: 'relative'
            } },
            children,
            !data.length ? noDataRow ? noDataRow : '' :
                (react_1.default.createElement(react_virtualized_1.AutoSizer, null, function (_a) {
                    var height = _a.height, width = _a.width;
                    return (react_1.default.createElement(react_virtualized_1.List, { ref: function (ref) { return vListRef.current = ref; }, onScroll: onScrollCallback, height: height, width: width, rowHeight: cache.rowHeight, rowCount: data.length, rowRenderer: renderRow }));
                }))));
    }, [data]);
    return (react_1.default.createElement("div", { id: "virtualized-scroll-panel", onTouchStart: onTouchStart, onTouchMove: onTouchMove, onTouchEnd: onTouchEnd },
        react_1.default.createElement("div", { className: "list-box" },
            react_1.default.createElement("div", { className: "pull-down-box", style: {
                    top: offset - 45 + "px",
                    transition: STATS === 'dragging' ? 'none' : 'all .3s',
                    zIndex: 999
                } },
                react_1.default.createElement("div", { className: "pull-down-round" },
                    react_1.default.createElement("div", { className: "inner", style: {
                            transform: "rotate(" + (offset / refreshDistance) * 720 + "deg)",
                            transition: STATS === 'refreshing' || STATS === 'dragging' ? 'none' : 'all .3s',
                            animation: STATS === 'refreshing' ? 'self_rotate 1s infinite linear' : ''
                        } }, STATS === 'success' || STATS === 'init' ?
                        logo.pulldown_success ? logo.pulldown_success : react_1.default.createElement("i", { className: "icon iconfont iconcheck-circle" })
                        : logo.pulldown_loading ? logo.pulldown_loading : react_1.default.createElement("i", { className: "icon iconfont iconshuaxin" })))),
            VirtualScroll)));
};
exports.default = react_1.forwardRef(VirtualizedScroll);


================================================
FILE: lib/component/ReactVirtualizedScroll/Row.js
================================================
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
var react_1 = require("react");
var Row = function (_a) {
    var row = _a.row, data = _a.data, index = _a.index, info = _a.info;
    var Render = row({ data: data, index: index, info: info });
    return react_1.useMemo(function () {
        console.log('data[index].value]', index, data[index].value);
        return Render;
    }, [JSON.stringify(data[index])]);
};
exports.default = Row;


================================================
FILE: lib/component/ReactVirtualizedScroll/index.d.ts
================================================
declare module 'react-virtualized-scroll'

================================================
FILE: lib/component/ReactVirtualizedScroll/index.js
================================================
"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
    return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
var ReactVirtualizedScroll_1 = __importDefault(require("./ReactVirtualizedScroll"));
exports.default = ReactVirtualizedScroll_1.default;


================================================
FILE: lib/component/ReactVirtualizedScroll/style.css
================================================
*{
    margin: 0;
    padding: 0;
}
#virtualized-scroll-panel, .list-box{
    width: 100%;
    height: 100%;
}
#virtualized-scroll-panel .list-box{
    transition: all .3s;
    position: absolute;
}
#virtualized-scroll-panel{
    position: relative;
    background-color: #f5f5f9;
    /* overflow: hidden; */
}
#virtualized-scroll-panel .pull-down-box{
    position: absolute;
    display: flex;
    justify-content: center;
    align-items: center;
    width: 100%;
    
}
#virtualized-scroll-panel .pull-down-box .pull-down-round .iconcheck-circle{
    font-size: 28px;
    color: #43cd80;
}
#virtualized-scroll-panel .pull-down-box .pull-down-round .iconshuaxin{
    font-size: 28px;
    color: #ff8080;
}
#virtualized-scroll-panel .pull-down-box .pull-down-round{
    width: 40px;
    height: 40px;
    background: #fff;
    box-shadow: 1px 1px 5px  rgba(0,0,0,0.5);
    border-radius: 50%;
    display: flex;
    justify-content: center;
    align-items: center;
}
@keyframes self_rotate{
   0%{ transform: rotate(0deg); }
   100%{ transform: rotate(360deg); }
}
#virtualized-scroll-panel .card-content .load-item{
    height: 50px;
    text-align: center;
    line-height: 50px;
    background-color: #f5f5f9;
    width: 100%;
}

================================================
FILE: lib/component/ReactVirtualizedScroll/svg.js
================================================
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.loading_pullup = void 0;
exports.loading_pullup = 'data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHhtbG5zOnhsaW5rPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5L3hsaW5rIiBzdHlsZT0ibWFyZ2luOiBhdXRvOyBiYWNrZ3JvdW5kOiAjZjVmNWY5OyBkaXNwbGF5OiBibG9jazsiIHdpZHRoPSIxMDAlIiBoZWlnaHQ9IjUwcHgiIHZpZXdCb3g9IjAgMCAxMDAgMTAwIiBwcmVzZXJ2ZUFzcGVjdFJhdGlvPSJ4TWlkWU1pZCI+DQo8Y2lyY2xlIGN4PSI4NCIgY3k9IjUwIiByPSIxLjA2NTE3IiBmaWxsPSIjZmFjZDllIj4NCiAgICA8YW5pbWF0ZSBhdHRyaWJ1dGVOYW1lPSJyIiByZXBlYXRDb3VudD0iaW5kZWZpbml0ZSIgZHVyPSIwLjM2MjMxODg0MDU3OTcxMDFzIiBjYWxjTW9kZT0ic3BsaW5lIiBrZXlUaW1lcz0iMDsxIiB2YWx1ZXM9IjEwOzAiIGtleVNwbGluZXM9IjAgMC41IDAuNSAxIiBiZWdpbj0iMHMiPjwvYW5pbWF0ZT4NCiAgICA8YW5pbWF0ZSBhdHRyaWJ1dGVOYW1lPSJmaWxsIiByZXBlYXRDb3VudD0iaW5kZWZpbml0ZSIgZHVyPSIxLjQ0OTI3NTM2MjMxODg0MDRzIiBjYWxjTW9kZT0iZGlzY3JldGUiIGtleVRpbWVzPSIwOzAuMjU7MC41OzAuNzU7MSIgdmFsdWVzPSIjZmFjZDllOyNmMTlkM2I7IzQ1OTQ0ODsjMzg5Nzk4OyNmYWNkOWUiIGJlZ2luPSIwcyI+PC9hbmltYXRlPg0KPC9jaXJjbGU+PGNpcmNsZSBjeD0iMTYiIGN5PSI1MCIgcj0iOC45MzQ4MyIgZmlsbD0iI2ZhY2Q5ZSI+DQogIDxhbmltYXRlIGF0dHJpYnV0ZU5hbWU9InIiIHJlcGVhdENvdW50PSJpbmRlZmluaXRlIiBkdXI9IjEuNDQ5Mjc1MzYyMzE4ODQwNHMiIGNhbGNNb2RlPSJzcGxpbmUiIGtleVRpbWVzPSIwOzAuMjU7MC41OzAuNzU7MSIgdmFsdWVzPSIwOzA7MTA7MTA7MTAiIGtleVNwbGluZXM9IjAgMC41IDAuNSAxOzAgMC41IDAuNSAxOzAgMC41IDAuNSAxOzAgMC41IDAuNSAxIiBiZWdpbj0iMHMiPjwvYW5pbWF0ZT4NCiAgPGFuaW1hdGUgYXR0cmlidXRlTmFtZT0iY3giIHJlcGVhdENvdW50PSJpbmRlZmluaXRlIiBkdXI9IjEuNDQ5Mjc1MzYyMzE4ODQwNHMiIGNhbGNNb2RlPSJzcGxpbmUiIGtleVRpbWVzPSIwOzAuMjU7MC41OzAuNzU7MSIgdmFsdWVzPSIxNjsxNjsxNjs1MDs4NCIga2V5U3BsaW5lcz0iMCAwLjUgMC41IDE7MCAwLjUgMC41IDE7MCAwLjUgMC41IDE7MCAwLjUgMC41IDEiIGJlZ2luPSIwcyI+PC9hbmltYXRlPg0KPC9jaXJjbGU+PGNpcmNsZSBjeD0iNDYuMzc4NCIgY3k9IjUwIiByPSIxMCIgZmlsbD0iIzM4OTc5OCI+DQogIDxhbmltYXRlIGF0dHJpYnV0ZU5hbWU9InIiIHJlcGVhdENvdW50PSJpbmRlZmluaXRlIiBkdXI9IjEuNDQ5Mjc1MzYyMzE4ODQwNHMiIGNhbGNNb2RlPSJzcGxpbmUiIGtleVRpbWVzPSIwOzAuMjU7MC41OzAuNzU7MSIgdmFsdWVzPSIwOzA7MTA7MTA7MTAiIGtleVNwbGluZXM9IjAgMC41IDAuNSAxOzAgMC41IDAuNSAxOzAgMC41IDAuNSAxOzAgMC41IDAuNSAxIiBiZWdpbj0iLTAuMzYyMzE4ODQwNTc5NzEwMXMiPjwvYW5pbWF0ZT4NCiAgPGFuaW1hdGUgYXR0cmlidXRlTmFtZT0iY3giIHJlcGVhdENvdW50PSJpbmRlZmluaXRlIiBkdXI9IjEuNDQ5Mjc1MzYyMzE4ODQwNHMiIGNhbGNNb2RlPSJzcGxpbmUiIGtleVRpbWVzPSIwOzAuMjU7MC41OzAuNzU7MSIgdmFsdWVzPSIxNjsxNjsxNjs1MDs4NCIga2V5U3BsaW5lcz0iMCAwLjUgMC41IDE7MCAwLjUgMC41IDE7MCAwLjUgMC41IDE7MCAwLjUgMC41IDEiIGJlZ2luPSItMC4zNjIzMTg4NDA1Nzk3MTAxcyI+PC9hbmltYXRlPg0KPC9jaXJjbGU+PGNpcmNsZSBjeD0iODAuMzc4NCIgY3k9IjUwIiByPSIxMCIgZmlsbD0iIzQ1OTQ0OCI+DQogIDxhbmltYXRlIGF0dHJpYnV0ZU5hbWU9InIiIHJlcGVhdENvdW50PSJpbmRlZmluaXRlIiBkdXI9IjEuNDQ5Mjc1MzYyMzE4ODQwNHMiIGNhbGNNb2RlPSJzcGxpbmUiIGtleVRpbWVzPSIwOzAuMjU7MC41OzAuNzU7MSIgdmFsdWVzPSIwOzA7MTA7MTA7MTAiIGtleVNwbGluZXM9IjAgMC41IDAuNSAxOzAgMC41IDAuNSAxOzAgMC41IDAuNSAxOzAgMC41IDAuNSAxIiBiZWdpbj0iLTAuNzI0NjM3NjgxMTU5NDIwMnMiPjwvYW5pbWF0ZT4NCiAgPGFuaW1hdGUgYXR0cmlidXRlTmFtZT0iY3giIHJlcGVhdENvdW50PSJpbmRlZmluaXRlIiBkdXI9IjEuNDQ5Mjc1MzYyMzE4ODQwNHMiIGNhbGNNb2RlPSJzcGxpbmUiIGtleVRpbWVzPSIwOzAuMjU7MC41OzAuNzU7MSIgdmFsdWVzPSIxNjsxNjsxNjs1MDs4NCIga2V5U3BsaW5lcz0iMCAwLjUgMC41IDE7MCAwLjUgMC41IDE7MCAwLjUgMC41IDE7MCAwLjUgMC41IDEiIGJlZ2luPSItMC43MjQ2Mzc2ODExNTk0MjAycyI+PC9hbmltYXRlPg0KPC9jaXJjbGU+PGNpcmNsZSBjeD0iMTYiIGN5PSI1MCIgcj0iMCIgZmlsbD0iI2YxOWQzYiI+DQogIDxhbmltYXRlIGF0dHJpYnV0ZU5hbWU9InIiIHJlcGVhdENvdW50PSJpbmRlZmluaXRlIiBkdXI9IjEuNDQ5Mjc1MzYyMzE4ODQwNHMiIGNhbGNNb2RlPSJzcGxpbmUiIGtleVRpbWVzPSIwOzAuMjU7MC41OzAuNzU7MSIgdmFsdWVzPSIwOzA7MTA7MTA7MTAiIGtleVNwbGluZXM9IjAgMC41IDAuNSAxOzAgMC41IDAuNSAxOzAgMC41IDAuNSAxOzAgMC41IDAuNSAxIiBiZWdpbj0iLTEuMDg2OTU2NTIxNzM5MTMwNHMiPjwvYW5pbWF0ZT4NCiAgPGFuaW1hdGUgYXR0cmlidXRlTmFtZT0iY3giIHJlcGVhdENvdW50PSJpbmRlZmluaXRlIiBkdXI9IjEuNDQ5Mjc1MzYyMzE4ODQwNHMiIGNhbGNNb2RlPSJzcGxpbmUiIGtleVRpbWVzPSIwOzAuMjU7MC41OzAuNzU7MSIgdmFsdWVzPSIxNjsxNjsxNjs1MDs4NCIga2V5U3BsaW5lcz0iMCAwLjUgMC41IDE7MCAwLjUgMC41IDE7MCAwLjUgMC41IDE7MCAwLjUgMC41IDEiIGJlZ2luPSItMS4wODY5NTY1MjE3MzkxMzA0cyI+PC9hbmltYXRlPg0KPC9jaXJjbGU+DQo8L3N2Zz4=';


================================================
FILE: lib/component/ReactVirtualizedScroll/utils.js
================================================
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.useStateAndRef = void 0;
var react_1 = require("react");
exports.useStateAndRef = function (data) {
    var _a = react_1.useState(data), data = _a[0], setData = _a[1];
    var dataRef = react_1.useRef(data);
    react_1.useEffect(function () {
        dataRef.current = data;
    }, [data]);
    return [data, setData, dataRef];
};


================================================
FILE: lib/package.json
================================================
{
  "name": "react-virtualized-scroll",
  "version": "0.0.8",
  "description": "虚拟滚动搭配上拉下滑加载的scroll组件",
  "main": "./component/ReactVirtualizedScroll/index.js",
  "author": "DavidWong <park_geunhye@163.com>",
  "license": "MIT",
  "dependencies": {
    "react": "^16.8.6",
    "react-dom": "^16.8.6",
    "react-router-dom": "^5.0.1",
    "react-virtualized": "^9.21.2"
  }
}

================================================
FILE: package.json
================================================
{
  "name": "react-virtualized-scroll",
  "version": "0.0.9",
  "description": "虚拟滚动搭配上拉下滑加载的scroll组件",
  "main": "lib/index.js",
  "homepage": "https://github.com/DavidWong9785/react-virtualized-scroll",
  "scripts": {
    "start": "webpack-dev-server --open development",
    "build": "tsc",
    "format": "prettier --write \"src/**/*.ts\" \"src/**/*.js\"",
    "lint": "tslint -p tsconfig.json",
    "test": "jest --config jestconfig.json --coverage"
  },
  "keywords": [
    "typescript",
    "虚拟滚动",
    "scroll",
    "react"
  ],
  "author": "DavidWong <park_geunhye@163.com>",
  "repository": {
    "type": "git",
    "url": "git+https://github.com/DavidWong9785/react-virtualized-scroll.git"
  },
  "license": "MIT",
  "dependencies": {
    "@types/html-webpack-plugin": "^3.2.1",
    "@types/node": "^12.6.8",
    "@types/react": "^16.8.20",
    "@types/react-dom": "^16.8.4",
    "@types/react-router-dom": "^4.3.4",
    "@types/react-virtualized": "^9.21.7",
    "@types/webpack": "^4.32.1",
    "media-show-card": "^1.0.3",
    "pre-commit": "^1.2.2",
    "react": "^16.8.6",
    "react-dom": "^16.8.6",
    "react-router-dom": "^5.0.1",
    "react-virtualized": "^9.21.2",
    "ts-node": "^8.3.0"
  },
  "devDependencies": {
    "@types/enzyme": "^3.10.3",
    "@types/jest": "^24.0.16",
    "babel-jest": "^24.9.0",
    "css-loader": "^3.1.0",
    "enzyme": "^3.10.0",
    "enzyme-adapter-react-16": "^1.14.0",
    "file-loader": "^4.1.0",
    "html-webpack-plugin": "^3.2.0",
    "identity-obj-proxy": "^3.0.0",
    "jest": "^24.8.0",
    "prettier": "^1.18.2",
    "source-map-loader": "^0.2.4",
    "style-loader": "^0.23.1",
    "ts-jest": "^24.0.2",
    "ts-loader": "^6.0.3",
    "tslint": "^5.18.0",
    "tslint-config-prettier": "^1.18.0",
    "typescript": "^3.5.2",
    "url-loader": "^2.1.0",
    "webpack": "^4.34.0",
    "webpack-cli": "^3.3.4",
    "webpack-dev-server": "^3.7.2"
  }
}


================================================
FILE: src/__tests__/demo.test.tsx
================================================
import React from 'react'
import { shallow, configure } from 'enzyme'
import Adapter from 'enzyme-adapter-react-16'
import ReactVirtualizedScroll from '../component/ReactVirtualizedScroll/index'

configure({ adapter: new Adapter() })

const setup = () => {
    // 模拟 props
    const props = {
        height: '100vh',
        row: () => {},
        hasMore: true
    }
    // 通过 enzyme 提供的 shallow(浅渲染) 创建组件
    const wrapper = shallow(<ReactVirtualizedScroll {...props} />)
    return {
        props,
        wrapper,
    }
}

describe('测试height属性', () => {
    const { wrapper, props } = setup()
    it('props', () => {
        expect(props.height).toEqual('100vh')
    })
})


================================================
FILE: src/assets/iconfont.css
================================================
@font-face {font-family: "iconfont";
  src: url('iconfont.eot?t=1578637319034'); /* IE9 */
  src: url('iconfont.eot?t=1578637319034#iefix') format('embedded-opentype'), /* IE6-IE8 */
  url('data:application/x-font-woff2;charset=utf-8;base64,d09GMgABAAAAAATYAAsAAAAACVwAAASMAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHEIGVgCDSAqFRIRoATYCJAMYCw4ABCAFhG0HYhsoCFFUTppkf4U4RBYobL8q1RqS2WPnlCFBo7GKFHDAYghuPVikPTPGSvDG5xkqd+fb7TfWfzouIB7+f79v+1wblWaOScQTnliEhDdLM/2TaIXkoZHMmmfyGzjnonwDm65BowSjLG08nE1kzfkfpDGBft9vrrIERkSYRbmKUO0Rzpv+EqTpwcC6PI12AhiN9IK2NtffElXBPp0cfBcOAs798xgziFvb89w8Bzxk4ZqNpuRg+pv/wrmxywtwTVzLA0w86gIa6/PvCxzBcfCfO8BDunlbQhnWPJBEw7a29N878nqgwANVvaLX13vRdP7/905/6/gDa13Lcplj08IA44ACGmPbIiuQTpigpqLOyC4BXh0eJjBoHgM8t7/eU1fhjQrEvcAz1K1plREU+hWtZ2FZAIla+tPjNHiSvj/+ORzWJDXzJl69sXNo+XNYD+rkPcbw9jNDWUbGXoBC7PRaH2nk0b1gg9YvNJ1HhvVLys/hD/5sV8+mJvScYdj/yyNURZKJBtJhJl2MVX4Oh2phyQ6C2ye7DgaFX7tqiWU9yDy6su04YAjviL2AJ0il8Zw9Qt1PDu13ZTQHuseSdB/wVk3Qktl6ytKuH0SgiqMfxD6g973BG2xHUEQzq1UyZ4umsha6ZzKm9shpGK+WQe8YssH8DuyqW1qqirD/2ukZ090542X17dYJqd9G2u+m7g3T7ItPSqVt9H0MsHWDPjhS1Nxa0MvQ2DlhmnWlrSO6bSPkRdJK3Ql6u4RRAU3piFaDVhtdN23dPaPKG7C9SgYm8+URXWQQXlOr1yCfFVuhdYgu7IMm/qTwREjDp7bq8VDb+oqV2Mod5Psb/uAdaHYQsKIbEC6epTtzuXeVjfObxOyVJS036DgL07KOgv/I/0uIDogNIZf4pA0+O4Mh4jEbQr4p4BW5NarmYeDj4xN54e3f5zaCAs/o3GzZsNUf2cPr6bn7fWa5y4A18BKxubb53a/jQ0ku1scaTQjw1C2ge4x/+uZ3fQLascKZ5+wGl8dJD1BaTn1cQEr57y0PlNXkq+VOkNMAG1c2k8WagH18TBWQ26vD8d0AsAOgm1HCVanqhC82cdybFQ6HTPKie2qCI/9Nn/FjV76jU/5/L9Yu4POJ2lB38zyrTvSXkJnN++9UlBVR7qgC1rVi1gllz9dlaU5rcThh0HfSwTnpu5d8ZnY+od9MCUmfOcj6reIKaS9UQ45C0+8kDNpDXz5kSqohygC2lQLCuAmSUa8hG3fGFdIHqll/aMYDhkHXgtxwyHqM92WBUThs/3Nks9QNDNrPCm/wqthIVZCSHyFlEGBxPG0mDkghe0zJfrx5ri77kiWsieMQxxnHkoWwOg5V8wU/cfueNHayhPrOEmAocDDbPxaxMik3bq76rdffgKcSM2SkrsX8CEQpaJ+JOMIM3EGazqp7l+6ZH565nHJ5mE9kEkyDGWI/mmFxf78QWGosXBHOLfDUyJ8rHZ8vT17lFhjkPbJFihwlarTo03ffr8xfkA4dHzYaOYHYGO0UcWac3rN0GeUote8Hsars59IQAQ==') format('woff2'),
  url('iconfont.woff?t=1578637319034') format('woff'),
  url('iconfont.ttf?t=1578637319034') format('truetype'), /* chrome, firefox, opera, Safari, Android, iOS 4.2+ */
  url('iconfont.svg?t=1578637319034#iconfont') format('svg'); /* iOS 4.1- */
}

.iconfont {
  font-family: "iconfont" !important;
  font-size: 16px;
  font-style: normal;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
}

.iconshuaxin:before {
  content: "\e60c";
}

.iconcheck-circle:before {
  content: "\e77d";
}

.iconreload:before {
  content: "\e788";
}

.iconicon-test:before {
  content: "\e658";
}

.iconfiltration:before {
  content: "\e630";
}



================================================
FILE: src/assets/iconfont.js
================================================
!function(l){var e,c='<svg><symbol id="iconshuaxin" viewBox="0 0 1024 1024"><path d="M875 483c-33.4 0-60.5 27.1-60.5 60.5v0.1C814.4 710.3 678.8 846 512 846S209.5 710.3 209.5 543.5 345.2 241 512 241c36.8 0 71.7 7.6 104.4 19.7-32 3-57.4 29.1-57.4 61.9 0 34.8 28.2 63 63 63h201.9c34.8 0 63-28.2 63-63V120c0-34.8-28.2-63-63-63s-63 28.2-63 63v81.4C691 150.5 605.2 120 512 120 278.1 120 88.5 309.6 88.5 543.5S278.1 967 512 967s423.5-189.6 423.5-423.5c0-33.4-27.1-60.5-60.5-60.5z"  ></path></symbol><symbol id="iconcheck-circle" viewBox="0 0 1024 1024"><path d="M699 353h-46.9c-10.2 0-19.9 4.9-25.9 13.3L469 584.3l-71.2-98.8c-6-8.3-15.6-13.3-25.9-13.3H325c-6.5 0-10.3 7.4-6.5 12.7l124.6 172.8c12.7 17.7 39 17.7 51.7 0l210.6-292c3.9-5.3 0.1-12.7-6.4-12.7z"  ></path><path d="M512 64C264.6 64 64 264.6 64 512s200.6 448 448 448 448-200.6 448-448S759.4 64 512 64z m0 820c-205.4 0-372-166.6-372-372s166.6-372 372-372 372 166.6 372 372-166.6 372-372 372z"  ></path></symbol><symbol id="iconreload" viewBox="0 0 1024 1024"><path d="M909.1 209.3l-56.4 44.1C775.8 155.1 656.2 92 521.9 92 290 92 102.3 279.5 102 511.5 101.7 743.7 289.8 932 521.9 932c181.3 0 335.8-115 394.6-276.1 1.5-4.2-0.7-8.9-4.9-10.3l-56.7-19.5c-4.1-1.4-8.6 0.7-10.1 4.8-1.8 5-3.8 10-5.9 14.9-17.3 41-42.1 77.8-73.7 109.4-31.6 31.6-68.4 56.4-109.3 73.8-42.3 17.9-87.4 27-133.8 27-46.5 0-91.5-9.1-133.8-27-40.9-17.3-77.7-42.1-109.3-73.8-31.6-31.6-56.4-68.4-73.7-109.4-17.9-42.4-27-87.4-27-133.9s9.1-91.5 27-133.9c17.3-41 42.1-77.8 73.7-109.4 31.6-31.6 68.4-56.4 109.3-73.8 42.3-17.9 87.4-27 133.8-27 46.5 0 91.5 9.1 133.8 27 40.9 17.3 77.7 42.1 109.3 73.8 9.9 9.9 19.2 20.4 27.8 31.4l-60.2 47c-5.3 4.1-3.5 12.5 3 14.1l175.6 43c5 1.2 9.9-2.6 9.9-7.7l0.8-180.9c-0.1-6.6-7.8-10.3-13-6.2z"  ></path></symbol><symbol id="iconicon-test" viewBox="0 0 1024 1024"><path d="M512 685.248l-278.624-278.624 45.248-45.248L512 594.752l233.376-233.376 45.248 45.248z" fill="#181818" ></path></symbol><symbol id="iconfiltration" viewBox="0 0 1211 1024"><path d="M131.45833333 215.12500024a37.2023811 37.2023811 0 0 1 37.2023811-37.2023811h669.6428574a37.2023811 37.2023811 0 0 1 0 74.40476221h-669.6428574a37.2023811 37.2023811 0 0 1-37.2023811-37.20238111zM131.45833333 512.74404742a37.2023811 37.2023811 0 0 1 37.2023811-37.2023811h669.6428574a37.2023811 37.2023811 0 0 1 0 74.4047622h-669.6428574a37.2023811 37.2023811 0 0 1-37.2023811-37.2023811zM131.45833333 810.36309543a37.2023811 37.2023811 0 0 1 37.2023811-37.2023811h669.6428574a37.2023811 37.2023811 0 0 1 0 74.4047622h-669.6428574a37.2023811 37.2023811 0 0 1-37.2023811-37.2023811zM987.11309541 90.125a37.2023811 37.2023811 0 0 1 37.2023811 37.2023811v769.3452378a37.2023811 37.2023811 0 0 1-74.4047622 0V127.3273811a37.2023811 37.2023811 0 0 1 37.2023811-37.2023811z"  ></path><path d="M1118.80952413 764.97619018a37.94642852 37.94642852 0 0 1 0 52.82738114l-105.65476228 104.91071402a36.83035739 36.83035739 0 0 1-52.08333287-52.08333288l104.91071401-105.65476228a37.94642852 37.94642852 0 0 1 52.82738114 0z"  ></path></symbol></svg>',t=(e=document.getElementsByTagName("script"))[e.length-1].getAttribute("data-injectcss");if(t&&!l.__iconfont__svg__cssinject__){l.__iconfont__svg__cssinject__=!0;try{document.write("<style>.svgfont {display: inline-block;width: 1em;height: 1em;fill: currentColor;vertical-align: -0.1em;font-size:16px;}</style>")}catch(e){console&&console.log(e)}}!function(e){if(document.addEventListener)if(~["complete","loaded","interactive"].indexOf(document.readyState))setTimeout(e,0);else{var t=function(){document.removeEventListener("DOMContentLoaded",t,!1),e()};document.addEventListener("DOMContentLoaded",t,!1)}else document.attachEvent&&(o=e,i=l.document,a=!1,(c=function(){try{i.documentElement.doScroll("left")}catch(e){return void setTimeout(c,50)}n()})(),i.onreadystatechange=function(){"complete"==i.readyState&&(i.onreadystatechange=null,n())});function n(){a||(a=!0,o())}var o,i,a,c}(function(){var e,t,n,o,i,a;(e=document.createElement("div")).innerHTML=c,c=null,(t=e.getElementsByTagName("svg")[0])&&(t.setAttribute("aria-hidden","true"),t.style.position="absolute",t.style.width=0,t.style.height=0,t.style.overflow="hidden",n=t,(o=document.body).firstChild?(i=n,(a=o.firstChild).parentNode.insertBefore(i,a)):o.appendChild(n))})}(window);

================================================
FILE: src/component/ReactVirtualizedScroll/ReactVirtualizedScroll.tsx
================================================
import React, { useState, useMemo, TouchEvent, useRef, useCallback, forwardRef, useImperativeHandle, useEffect } from 'react';
import { List as VList, AutoSizer, CellMeasurer, CellMeasurerCache } from 'react-virtualized';
import { loading_pullup } from './svg';
import '../../assets/iconfont.css'
import './style.css'

interface ILogo {
  pulldown_loading?: JSX.Element;
  pulldown_success?: JSX.Element;
  pullup_loading?: JSX.Element;
  pullup_success?: JSX.Element;
}

interface IVirtualized {
  children? : JSX.Element;
  hasMore : boolean;
  refreshDistance? : number;
  loading? : boolean;
  data? : any;
  info? : any;
  height? : string;
  width? : string;
  noDataRow? : JSX.Element;
  logo? : ILogo;
  onPullUp? : any;
  onPullDown? : any;
  onScroll?: any;
  row({index, info}: {index: number, info: any, data: any}): any;
}

const Row = ({ row, data, index, info }:any) => {
  return useMemo(() => {
      return row({ data: data, index, info })
  }, [JSON.stringify(data[index])])
}

const VirtualizedScroll = ({
  children,
  hasMore = true,
  refreshDistance = 120,
  loading = false,
  data = [],
  info,
  height = '100vh',
  width = '100vw',
  noDataRow,
  onPullDown = null,
  onPullUp = null,
  onScroll = null,
  row,
  logo = {}
}: IVirtualized, ref: any) => {

  // 下拉状态
  const [STATS, setSTATS] = useState<string>('init')
  // touch数据
  const [startY, setStartY] = useState<number>(0)
  const [offset, setOffset] = useState<number>(0)
  // vList容器
  const vListRef = useRef<any>()
  const timer = useRef<any>()
  // 上滑时,scrollTop为0禁止滑动
  const scrollingDisable = useRef(false)
  
  const hasMoreRef = useRef(true)
  const canNotDrag = useRef(false)
  const isPullUpLoading = useRef(false)

  useEffect(() => {
    hasMoreRef.current = hasMore
  }, [hasMore])

  useEffect(() => {
    canNotDrag.current = STATS === 'refreshing' || STATS === 'success' || STATS == 'scroll' || !onPullDown
  }, [STATS])

  const initState = () => {
    setOffset(0)
    setStartY(0)
  }

  const onTouchStart = ($event: TouchEvent) => {
    if (canNotDrag.current || scrollingDisable.current) return
    setStartY($event.nativeEvent.touches[0].pageY)
  }

  const onTouchMove = useCallback(
    ($event: TouchEvent) => {
      if (canNotDrag.current || scrollingDisable.current) return

      const offsetComputed = $event.nativeEvent.touches[0].pageY - startY
      if (0 < offsetComputed && offsetComputed <= refreshDistance) setOffset(offsetComputed)
      else if (offsetComputed < 0) setOffset(0)
      else if (offsetComputed > refreshDistance) setOffset(refreshDistance)
  
      if (offset < refreshDistance && STATS !== 'dragging') setSTATS('dragging')
      else if (offset >= refreshDistance) setSTATS('pre-refresh')
    },
    [startY, canNotDrag, offset, STATS],
  )

  const onTouchEnd = useCallback(
    ($event: TouchEvent) => {
      if (canNotDrag.current) return
      if (scrollingDisable.current) {
        initState()
        return
      }
      if (STATS === 'pre-refresh') {
        setSTATS('refreshing')
        if (!onPullDown) return
        onPullDown().then(() => {
          setSTATS('success')
          if (vListRef.current) vListRef.current.scrollToRow(0)
          if (timer.current) clearTimeout(timer.current)
          timer.current = setTimeout(() => {
            setSTATS('init')
            initState()
          }, 500)
        })
      } else {
        initState()
        setSTATS('not-enough')
        if (timer.current) clearTimeout(timer.current)
        timer.current = setTimeout(() => {
          setSTATS('init')
        }, 500)
      }
  
    },
    [timer, STATS, canNotDrag],
  )

  const onScrollCallback = ({ clientHeight, scrollTop, scrollHeight }: any) => {

    if (scrollTop === 0) scrollingDisable.current = false
    else scrollingDisable.current = true

    if ((clientHeight + scrollTop === scrollHeight) && onPullUp && !isPullUpLoading.current) {
      isPullUpLoading.current = true
      onPullUp().then(() => {
        isPullUpLoading.current = false
        if (vListRef.current) vListRef.current.scrollToRow(data.length + 1)
      }).catch(() => {
        isPullUpLoading.current = false
      })
    }
    if (onScroll) onScroll(clientHeight, scrollTop, scrollHeight)
  }

  const cache = new CellMeasurerCache({ defaultHeight: 400,fixedWidth: true});

  useImperativeHandle(
    ref,
    () => ({
      vListRef: vListRef.current
    }),
    [vListRef],
  )

  const renderRow = useCallback(
    ({ index, key, parent, style }: any) => {
      return (
        <CellMeasurer
          cache={cache}
          columnIndex={0}
          key={key}
          parent={parent}
          rowIndex={index}>
          <div className="card-content" style={ { ...style } } key={key}>
            {
              <Row
                row={row}
                data={data}
                index={index}
                info={info}></Row>

            }
            {
                index === data.length - 1 ? !hasMoreRef.current ? 
                (
                  <div className="load-item" style={{ height: '50px', width: '100%' }}>
                    { logo.pullup_success ? logo.pullup_success : '没有更多了' }
                  </div>
                ) :
                (
                  <div className="load-item" style={{ height: '50px', width: '100%' }}>
                    { logo.pullup_loading ? logo.pullup_loading : <img src={loading_pullup} alt=""/> }
                  </div>
                ) : ''
            }
          </div>
        </CellMeasurer>
      )
    }, [data, hasMoreRef]
  )

  const VirtualScroll = useMemo(() => {
    return (
      <div className="content-wrap" style={{
          width,
          height,
          position: 'relative'
      }}>
          { children }
          {
            !data.length ? noDataRow ? noDataRow : '' :
            (
                <AutoSizer>
                {
                    ({ height, width }: any) => (
                    <VList
                        ref={(ref: any) => vListRef.current = ref}
                        onScroll={onScrollCallback}
                        height={height}
                        width={width}
                        rowHeight={cache.rowHeight}
                        rowCount={data.length}
                        rowRenderer={renderRow}
                    />
                    )
                }
                </AutoSizer>
            )
          }
      </div>
    )
  }, [data])

  return (
    <div id="virtualized-scroll-panel" onTouchStart={onTouchStart} onTouchMove={onTouchMove} onTouchEnd={onTouchEnd}>
      <div className="list-box">
        <div className="pull-down-box" style={{
          top: `${offset - 45}px`,
          transition: STATS === 'dragging' ? 'none' : 'all .3s',
          zIndex: 999
        }}>
          <div className="pull-down-round">
            <div className="inner" style={{
              transform: `rotate(${(offset / refreshDistance) * 720}deg)`,
              transition: STATS === 'refreshing' || STATS === 'dragging' ? 'none' : 'all .3s',
              animation: STATS === 'refreshing' ? 'self_rotate 1s infinite linear' : ''
            }}>
              {
                STATS === 'success' || STATS === 'init' ? 
                  logo.pulldown_success ? logo.pulldown_success : <i className="icon iconfont iconcheck-circle"></i> 
                 : logo.pulldown_loading ? logo.pulldown_loading : <i className="icon iconfont iconshuaxin"></i>
              }
            </div>
          </div>
        </div>
        { VirtualScroll }
      </div>
    </div>
  );
};

export default forwardRef(VirtualizedScroll);


================================================
FILE: src/component/ReactVirtualizedScroll/index.tsx
================================================
import ReactVirtualizedScroll from './ReactVirtualizedScroll'

export default ReactVirtualizedScroll


================================================
FILE: src/component/ReactVirtualizedScroll/style.css
================================================
*{
    margin: 0;
    padding: 0;
}
#virtualized-scroll-panel, .list-box{
    width: 100%;
    height: 100%;
}
#virtualized-scroll-panel .list-box{
    transition: all .3s;
    position: absolute;
}
#virtualized-scroll-panel{
    position: relative;
    background-color: #f5f5f9;
    /* overflow: hidden; */
}
#virtualized-scroll-panel .pull-down-box{
    position: absolute;
    display: flex;
    justify-content: center;
    align-items: center;
    width: 100%;
    
}
#virtualized-scroll-panel .pull-down-box .pull-down-round .iconcheck-circle{
    font-size: 28px;
    color: #43cd80;
}
#virtualized-scroll-panel .pull-down-box .pull-down-round .iconshuaxin{
    font-size: 28px;
    color: #ff8080;
}
#virtualized-scroll-panel .pull-down-box .pull-down-round{
    width: 40px;
    height: 40px;
    background: #fff;
    box-shadow: 1px 1px 5px  rgba(0,0,0,0.5);
    border-radius: 50%;
    display: flex;
    justify-content: center;
    align-items: center;
}
@keyframes self_rotate{
   0%{ transform: rotate(0deg); }
   100%{ transform: rotate(360deg); }
}
#virtualized-scroll-panel .card-content .load-item{
    height: 50px;
    text-align: center;
    line-height: 50px;
    background-color: #f5f5f9;
    width: 100%;
}

================================================
FILE: src/component/ReactVirtualizedScroll/svg.ts
================================================
export const loading_pullup = 'data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHhtbG5zOnhsaW5rPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5L3hsaW5rIiBzdHlsZT0ibWFyZ2luOiBhdXRvOyBiYWNrZ3JvdW5kOiAjZjVmNWY5OyBkaXNwbGF5OiBibG9jazsiIHdpZHRoPSIxMDAlIiBoZWlnaHQ9IjUwcHgiIHZpZXdCb3g9IjAgMCAxMDAgMTAwIiBwcmVzZXJ2ZUFzcGVjdFJhdGlvPSJ4TWlkWU1pZCI+DQo8Y2lyY2xlIGN4PSI4NCIgY3k9IjUwIiByPSIxLjA2NTE3IiBmaWxsPSIjZmFjZDllIj4NCiAgICA8YW5pbWF0ZSBhdHRyaWJ1dGVOYW1lPSJyIiByZXBlYXRDb3VudD0iaW5kZWZpbml0ZSIgZHVyPSIwLjM2MjMxODg0MDU3OTcxMDFzIiBjYWxjTW9kZT0ic3BsaW5lIiBrZXlUaW1lcz0iMDsxIiB2YWx1ZXM9IjEwOzAiIGtleVNwbGluZXM9IjAgMC41IDAuNSAxIiBiZWdpbj0iMHMiPjwvYW5pbWF0ZT4NCiAgICA8YW5pbWF0ZSBhdHRyaWJ1dGVOYW1lPSJmaWxsIiByZXBlYXRDb3VudD0iaW5kZWZpbml0ZSIgZHVyPSIxLjQ0OTI3NTM2MjMxODg0MDRzIiBjYWxjTW9kZT0iZGlzY3JldGUiIGtleVRpbWVzPSIwOzAuMjU7MC41OzAuNzU7MSIgdmFsdWVzPSIjZmFjZDllOyNmMTlkM2I7IzQ1OTQ0ODsjMzg5Nzk4OyNmYWNkOWUiIGJlZ2luPSIwcyI+PC9hbmltYXRlPg0KPC9jaXJjbGU+PGNpcmNsZSBjeD0iMTYiIGN5PSI1MCIgcj0iOC45MzQ4MyIgZmlsbD0iI2ZhY2Q5ZSI+DQogIDxhbmltYXRlIGF0dHJpYnV0ZU5hbWU9InIiIHJlcGVhdENvdW50PSJpbmRlZmluaXRlIiBkdXI9IjEuNDQ5Mjc1MzYyMzE4ODQwNHMiIGNhbGNNb2RlPSJzcGxpbmUiIGtleVRpbWVzPSIwOzAuMjU7MC41OzAuNzU7MSIgdmFsdWVzPSIwOzA7MTA7MTA7MTAiIGtleVNwbGluZXM9IjAgMC41IDAuNSAxOzAgMC41IDAuNSAxOzAgMC41IDAuNSAxOzAgMC41IDAuNSAxIiBiZWdpbj0iMHMiPjwvYW5pbWF0ZT4NCiAgPGFuaW1hdGUgYXR0cmlidXRlTmFtZT0iY3giIHJlcGVhdENvdW50PSJpbmRlZmluaXRlIiBkdXI9IjEuNDQ5Mjc1MzYyMzE4ODQwNHMiIGNhbGNNb2RlPSJzcGxpbmUiIGtleVRpbWVzPSIwOzAuMjU7MC41OzAuNzU7MSIgdmFsdWVzPSIxNjsxNjsxNjs1MDs4NCIga2V5U3BsaW5lcz0iMCAwLjUgMC41IDE7MCAwLjUgMC41IDE7MCAwLjUgMC41IDE7MCAwLjUgMC41IDEiIGJlZ2luPSIwcyI+PC9hbmltYXRlPg0KPC9jaXJjbGU+PGNpcmNsZSBjeD0iNDYuMzc4NCIgY3k9IjUwIiByPSIxMCIgZmlsbD0iIzM4OTc5OCI+DQogIDxhbmltYXRlIGF0dHJpYnV0ZU5hbWU9InIiIHJlcGVhdENvdW50PSJpbmRlZmluaXRlIiBkdXI9IjEuNDQ5Mjc1MzYyMzE4ODQwNHMiIGNhbGNNb2RlPSJzcGxpbmUiIGtleVRpbWVzPSIwOzAuMjU7MC41OzAuNzU7MSIgdmFsdWVzPSIwOzA7MTA7MTA7MTAiIGtleVNwbGluZXM9IjAgMC41IDAuNSAxOzAgMC41IDAuNSAxOzAgMC41IDAuNSAxOzAgMC41IDAuNSAxIiBiZWdpbj0iLTAuMzYyMzE4ODQwNTc5NzEwMXMiPjwvYW5pbWF0ZT4NCiAgPGFuaW1hdGUgYXR0cmlidXRlTmFtZT0iY3giIHJlcGVhdENvdW50PSJpbmRlZmluaXRlIiBkdXI9IjEuNDQ5Mjc1MzYyMzE4ODQwNHMiIGNhbGNNb2RlPSJzcGxpbmUiIGtleVRpbWVzPSIwOzAuMjU7MC41OzAuNzU7MSIgdmFsdWVzPSIxNjsxNjsxNjs1MDs4NCIga2V5U3BsaW5lcz0iMCAwLjUgMC41IDE7MCAwLjUgMC41IDE7MCAwLjUgMC41IDE7MCAwLjUgMC41IDEiIGJlZ2luPSItMC4zNjIzMTg4NDA1Nzk3MTAxcyI+PC9hbmltYXRlPg0KPC9jaXJjbGU+PGNpcmNsZSBjeD0iODAuMzc4NCIgY3k9IjUwIiByPSIxMCIgZmlsbD0iIzQ1OTQ0OCI+DQogIDxhbmltYXRlIGF0dHJpYnV0ZU5hbWU9InIiIHJlcGVhdENvdW50PSJpbmRlZmluaXRlIiBkdXI9IjEuNDQ5Mjc1MzYyMzE4ODQwNHMiIGNhbGNNb2RlPSJzcGxpbmUiIGtleVRpbWVzPSIwOzAuMjU7MC41OzAuNzU7MSIgdmFsdWVzPSIwOzA7MTA7MTA7MTAiIGtleVNwbGluZXM9IjAgMC41IDAuNSAxOzAgMC41IDAuNSAxOzAgMC41IDAuNSAxOzAgMC41IDAuNSAxIiBiZWdpbj0iLTAuNzI0NjM3NjgxMTU5NDIwMnMiPjwvYW5pbWF0ZT4NCiAgPGFuaW1hdGUgYXR0cmlidXRlTmFtZT0iY3giIHJlcGVhdENvdW50PSJpbmRlZmluaXRlIiBkdXI9IjEuNDQ5Mjc1MzYyMzE4ODQwNHMiIGNhbGNNb2RlPSJzcGxpbmUiIGtleVRpbWVzPSIwOzAuMjU7MC41OzAuNzU7MSIgdmFsdWVzPSIxNjsxNjsxNjs1MDs4NCIga2V5U3BsaW5lcz0iMCAwLjUgMC41IDE7MCAwLjUgMC41IDE7MCAwLjUgMC41IDE7MCAwLjUgMC41IDEiIGJlZ2luPSItMC43MjQ2Mzc2ODExNTk0MjAycyI+PC9hbmltYXRlPg0KPC9jaXJjbGU+PGNpcmNsZSBjeD0iMTYiIGN5PSI1MCIgcj0iMCIgZmlsbD0iI2YxOWQzYiI+DQogIDxhbmltYXRlIGF0dHJpYnV0ZU5hbWU9InIiIHJlcGVhdENvdW50PSJpbmRlZmluaXRlIiBkdXI9IjEuNDQ5Mjc1MzYyMzE4ODQwNHMiIGNhbGNNb2RlPSJzcGxpbmUiIGtleVRpbWVzPSIwOzAuMjU7MC41OzAuNzU7MSIgdmFsdWVzPSIwOzA7MTA7MTA7MTAiIGtleVNwbGluZXM9IjAgMC41IDAuNSAxOzAgMC41IDAuNSAxOzAgMC41IDAuNSAxOzAgMC41IDAuNSAxIiBiZWdpbj0iLTEuMDg2OTU2NTIxNzM5MTMwNHMiPjwvYW5pbWF0ZT4NCiAgPGFuaW1hdGUgYXR0cmlidXRlTmFtZT0iY3giIHJlcGVhdENvdW50PSJpbmRlZmluaXRlIiBkdXI9IjEuNDQ5Mjc1MzYyMzE4ODQwNHMiIGNhbGNNb2RlPSJzcGxpbmUiIGtleVRpbWVzPSIwOzAuMjU7MC41OzAuNzU7MSIgdmFsdWVzPSIxNjsxNjsxNjs1MDs4NCIga2V5U3BsaW5lcz0iMCAwLjUgMC41IDE7MCAwLjUgMC41IDE7MCAwLjUgMC41IDE7MCAwLjUgMC41IDEiIGJlZ2luPSItMS4wODY5NTY1MjE3MzkxMzA0cyI+PC9hbmltYXRlPg0KPC9jaXJjbGU+DQo8L3N2Zz4='

================================================
FILE: src/types/demo/index.d.ts
================================================
interface IDemo {
    age: number
}


================================================
FILE: src/types/global.d.ts
================================================
declare module '*.png' {
    const value: string
    export = value
}

declare module '*.mp4' {
    const content: string
    export = content
}


================================================
FILE: tsconfig.json
================================================
{
  "compilerOptions": {
    "outDir": "./lib",
    // "sourceMap": true,
    "noImplicitAny": false, //在表达式和声明上有隐含的 any类型时报错。
    "target": "es5", //指定ECMAScript目标版本 "ES3"(默认)
    "lib": ["dom", "dom.iterable", "esnext"], //    编译过程中需要引入的库文件的列表
    "allowJs": true, //允许编译javascript文件。
    "skipLibCheck": true, //忽略所有的声明文件( *.d.ts)的类型检查
    "esModuleInterop": true, //允许从没有设置默认导出的模块中默认导入。这并不影响代码的输出,仅为了类型检查
    "allowSyntheticDefaultImports": true, // 同上
    "strict": true, //启用所有严格类型检查选项
    "forceConsistentCasingInFileNames": true, //禁止对同一个文件的不一致的引用
    "module": "commonjs", //指定生成哪个模块系统代码
    "moduleResolution": "node", //决定如何处理模块。
    "resolveJsonModule": true,
    "isolatedModules": false, //将每个文件作为单独的模块(与“ts.transpileModule”类似)。
    // "noEmit": true,//不生成输出文件
    "jsx": "react",
    "baseUrl": "./",
    "paths": { "*": ["types/*"] }
    // "suppressImplicitAnyIndexErrors": true, //阻止对缺少索引签名的索引对象报错
  },
  "exclude": ["node_modules", "./lib", "./example"],
  "include": ["src/**/*"]
}


================================================
FILE: tslint.json
================================================
{
  "extends": ["tslint:recommended", "tslint-config-prettier"],
  "rules": {
    "no-console": false,
    "object-literal-sort-keys": false,
    "member-access": false,
    "ordered-imports": false
  },
  "linterOptions": {
    "exclude": ["**/*.json", "node_modules", "./lib", "./example"]
  }
}


================================================
FILE: webpack.config.js
================================================
const path = require('path')
const HtmlWebpackPlugin = require('html-webpack-plugin')
const htmlWebpackPlugin = new HtmlWebpackPlugin({
    template: path.join(__dirname, './example/src/index.html'),
    filename: './index.html',
})

module.exports = {
    entry: path.join(__dirname, './example/src/index.tsx'),
    output: {
        path: path.join(__dirname, 'example/dist'),
        filename: 'bundle.js',
    },
    module: {
        rules: [
            {
                test: /\.tsx?/,
                loader: 'ts-loader',
            },
            {
                // pre/nomal/post - loader的执行顺序 - 前/中/后
                enforce: 'pre',
                test: /\.tsx?/,
                loader: 'source-map-loader',
            },
            {
                test: /\.css$/,
                use: ['style-loader', 'css-loader'],
            },
            {
                test: /\.(gif|jpg|png|woff|svg|eot|ttf|otf|woff2)$/,
                use: {
                    loader: 'url-loader',
                    options: {
                        limit: 20,
                    },
                },
            },
        ],
    },
    //映射工具
    // devtool: 'source-map',
    //处理路径解析
    resolve: {
        //extensions 拓展名
        extensions: ['.tsx', '.ts', '.js', '.jsx', '.json'],
    },
    plugins: [htmlWebpackPlugin],
    devServer: {
        port: 3005,
    },
}
Download .txt
gitextract_0u698uid/

├── .babelrc
├── .editorconfig
├── .gitattributes
├── .gitignore
├── .npmignore
├── .prettierrc
├── .travis.yml
├── LICENSE
├── README.md
├── example/
│   └── src/
│       ├── app.tsx
│       ├── index.html
│       ├── index.tsx
│       └── utils.ts
├── jestconfig.json
├── lib/
│   ├── README.md
│   ├── __tests__/
│   │   └── demo.test.js
│   ├── assets/
│   │   ├── iconfont.css
│   │   ├── iconfont.js
│   │   └── iconfont.ts
│   ├── component/
│   │   └── ReactVirtualizedScroll/
│   │       ├── ReactVirtualizedScroll.js
│   │       ├── Row.js
│   │       ├── index.d.ts
│   │       ├── index.js
│   │       ├── style.css
│   │       ├── svg.js
│   │       └── utils.js
│   └── package.json
├── package.json
├── src/
│   ├── __tests__/
│   │   └── demo.test.tsx
│   ├── assets/
│   │   ├── iconfont.css
│   │   └── iconfont.js
│   ├── component/
│   │   └── ReactVirtualizedScroll/
│   │       ├── ReactVirtualizedScroll.tsx
│   │       ├── index.tsx
│   │       ├── style.css
│   │       └── svg.ts
│   └── types/
│       ├── demo/
│       │   └── index.d.ts
│       └── global.d.ts
├── tsconfig.json
├── tslint.json
└── webpack.config.js
Download .txt
SYMBOL INDEX (6 symbols across 5 files)

FILE: lib/assets/iconfont.js
  function n (line 23) | function n() { a || (a = !0, o()); }

FILE: lib/assets/iconfont.ts
  function n (line 23) | function n() { a || (a = !0, o()); }

FILE: src/assets/iconfont.js
  function n (line 1) | function n(){a||(a=!0,o())}

FILE: src/component/ReactVirtualizedScroll/ReactVirtualizedScroll.tsx
  type ILogo (line 7) | interface ILogo {
  type IVirtualized (line 14) | interface IVirtualized {

FILE: src/types/demo/index.d.ts
  type IDemo (line 1) | interface IDemo {
Condensed preview — 40 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (80K chars).
[
  {
    "path": ".babelrc",
    "chars": 254,
    "preview": "{\n    \"presets\": [\n      [\"env\", {\n        \"modules\": false,\n        \"targets\": {\n          \"browsers\": [\"> 1%\", \"last 2"
  },
  {
    "path": ".editorconfig",
    "chars": 317,
    "preview": "# EditorConfig is awesome: https://EditorConfig.org\n\n# top-most EditorConfig file\nroot = true\n\n# Unix-style newlines wit"
  },
  {
    "path": ".gitattributes",
    "chars": 35,
    "preview": "*.html linguist-language=JavaScript"
  },
  {
    "path": ".gitignore",
    "chars": 39,
    "preview": "/node_modules/\n/dist/\n/coverage/\n*.log\n"
  },
  {
    "path": ".npmignore",
    "chars": 120,
    "preview": "/.git/\n/.vscode/\n/node_modules/\n.gitignore\n.npmignore\n.prettierrc\n.editorconfig\ntslint.json\ntsconfig.json\nnote.md\n*.log\n"
  },
  {
    "path": ".prettierrc",
    "chars": 265,
    "preview": "{\n  \"trailingComma\": \"all\",\n  \"tabWidth\": 4,\n  \"semi\": false,\n  \"singleQuote\": true,\n  \"endOfLine\": \"lf\",\n  \"printWidth\""
  },
  {
    "path": ".travis.yml",
    "chars": 111,
    "preview": "language: node_js\nnode_js:\n    - '12'\ninstall:\n    - npm install\nscript:\n    - npm run test\n    - npm run lint\n"
  },
  {
    "path": "LICENSE",
    "chars": 1095,
    "preview": "MIT License\n\nCopyright (c) 2013-present, DavidWong9785(Zhaokang Huang)\n\nPermission is hereby granted, free of charge, to"
  },
  {
    "path": "README.md",
    "chars": 5763,
    "preview": "# react-virtualized-scroll\n虚拟滚动搭配上拉下滑加载的scroll组件\n\n[![github](https://img.shields.io/github/package-json/v/DavidWong9785/"
  },
  {
    "path": "example/src/app.tsx",
    "chars": 3536,
    "preview": "/* tslint:disable */\nimport React, { useState, useCallback } from 'react'\nimport ReactVirtualizedScroll from '../../lib/"
  },
  {
    "path": "example/src/index.html",
    "chars": 336,
    "preview": "<!DOCTYPE html>\n<html lang=\"en\">\n    <head>\n        <meta charset=\"UTF-8\" />\n        <meta name=\"viewport\" content=\"widt"
  },
  {
    "path": "example/src/index.tsx",
    "chars": 134,
    "preview": "import React from 'react'\nimport { render } from 'react-dom'\nimport App from './app'\nrender(<App />, document.getElement"
  },
  {
    "path": "example/src/utils.ts",
    "chars": 277,
    "preview": "import React, { useState, useEffect, useRef } from 'react'\nexport default (initState) => {\n    const [data, setData] = u"
  },
  {
    "path": "jestconfig.json",
    "chars": 303,
    "preview": "{\n  \"transform\": {\n    \"^.+\\\\.(t|j)sx?$\": \"ts-jest\",\n    \"^.+\\\\.jsx?$\": \"babel-jest\"\n  },\n  \"testRegex\": \"(/__tests__/.*"
  },
  {
    "path": "lib/README.md",
    "chars": 5763,
    "preview": "# react-virtualized-scroll\n虚拟滚动搭配上拉下滑加载的scroll组件\n\n[![github](https://img.shields.io/github/package-json/v/DavidWong9785/"
  },
  {
    "path": "lib/__tests__/demo.test.js",
    "chars": 1473,
    "preview": "\"use strict\";\nvar __assign = (this && this.__assign) || function () {\n    __assign = Object.assign || function(t) {\n    "
  },
  {
    "path": "lib/assets/iconfont.css",
    "chars": 2571,
    "preview": "@font-face {font-family: \"iconfont\";\n  src: url('iconfont.eot?t=1578637319034'); /* IE9 */\n  src: url('iconfont.eot?t=15"
  },
  {
    "path": "lib/assets/iconfont.js",
    "chars": 4579,
    "preview": "\"use strict\";\n!function (l) { var e, c = '<svg><symbol id=\"iconshuaxin\" viewBox=\"0 0 1024 1024\"><path d=\"M875 483c-33.4 "
  },
  {
    "path": "lib/assets/iconfont.ts",
    "chars": 4579,
    "preview": "\"use strict\";\n!function (l) { var e, c = '<svg><symbol id=\"iconshuaxin\" viewBox=\"0 0 1024 1024\"><path d=\"M875 483c-33.4 "
  },
  {
    "path": "lib/component/ReactVirtualizedScroll/ReactVirtualizedScroll.js",
    "chars": 9615,
    "preview": "\"use strict\";\nvar __assign = (this && this.__assign) || function () {\n    __assign = Object.assign || function(t) {\n    "
  },
  {
    "path": "lib/component/ReactVirtualizedScroll/Row.js",
    "chars": 469,
    "preview": "\"use strict\";\nObject.defineProperty(exports, \"__esModule\", { value: true });\nvar react_1 = require(\"react\");\nvar Row = f"
  },
  {
    "path": "lib/component/ReactVirtualizedScroll/index.d.ts",
    "chars": 41,
    "preview": "declare module 'react-virtualized-scroll'"
  },
  {
    "path": "lib/component/ReactVirtualizedScroll/index.js",
    "chars": 353,
    "preview": "\"use strict\";\nvar __importDefault = (this && this.__importDefault) || function (mod) {\n    return (mod && mod.__esModule"
  },
  {
    "path": "lib/component/ReactVirtualizedScroll/style.css",
    "chars": 1234,
    "preview": "*{\n    margin: 0;\n    padding: 0;\n}\n#virtualized-scroll-panel, .list-box{\n    width: 100%;\n    height: 100%;\n}\n#virtuali"
  },
  {
    "path": "lib/component/ReactVirtualizedScroll/svg.js",
    "chars": 4037,
    "preview": "\"use strict\";\nObject.defineProperty(exports, \"__esModule\", { value: true });\nexports.loading_pullup = void 0;\nexports.lo"
  },
  {
    "path": "lib/component/ReactVirtualizedScroll/utils.js",
    "chars": 417,
    "preview": "\"use strict\";\nObject.defineProperty(exports, \"__esModule\", { value: true });\nexports.useStateAndRef = void 0;\nvar react_"
  },
  {
    "path": "lib/package.json",
    "chars": 375,
    "preview": "{\n  \"name\": \"react-virtualized-scroll\",\n  \"version\": \"0.0.8\",\n  \"description\": \"虚拟滚动搭配上拉下滑加载的scroll组件\",\n  \"main\": \"./com"
  },
  {
    "path": "package.json",
    "chars": 1914,
    "preview": "{\n  \"name\": \"react-virtualized-scroll\",\n  \"version\": \"0.0.9\",\n  \"description\": \"虚拟滚动搭配上拉下滑加载的scroll组件\",\n  \"main\": \"lib/i"
  },
  {
    "path": "src/__tests__/demo.test.tsx",
    "chars": 679,
    "preview": "import React from 'react'\nimport { shallow, configure } from 'enzyme'\nimport Adapter from 'enzyme-adapter-react-16'\nimpo"
  },
  {
    "path": "src/assets/iconfont.css",
    "chars": 2571,
    "preview": "@font-face {font-family: \"iconfont\";\n  src: url('iconfont.eot?t=1578637319034'); /* IE9 */\n  src: url('iconfont.eot?t=15"
  },
  {
    "path": "src/assets/iconfont.js",
    "chars": 4280,
    "preview": "!function(l){var e,c='<svg><symbol id=\"iconshuaxin\" viewBox=\"0 0 1024 1024\"><path d=\"M875 483c-33.4 0-60.5 27.1-60.5 60."
  },
  {
    "path": "src/component/ReactVirtualizedScroll/ReactVirtualizedScroll.tsx",
    "chars": 7660,
    "preview": "import React, { useState, useMemo, TouchEvent, useRef, useCallback, forwardRef, useImperativeHandle, useEffect } from 'r"
  },
  {
    "path": "src/component/ReactVirtualizedScroll/index.tsx",
    "chars": 101,
    "preview": "import ReactVirtualizedScroll from './ReactVirtualizedScroll'\n\nexport default ReactVirtualizedScroll\n"
  },
  {
    "path": "src/component/ReactVirtualizedScroll/style.css",
    "chars": 1234,
    "preview": "*{\n    margin: 0;\n    padding: 0;\n}\n#virtualized-scroll-panel, .list-box{\n    width: 100%;\n    height: 100%;\n}\n#virtuali"
  },
  {
    "path": "src/component/ReactVirtualizedScroll/svg.ts",
    "chars": 3930,
    "preview": "export const loading_pullup = 'data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHhtbG5zOnh"
  },
  {
    "path": "src/types/demo/index.d.ts",
    "chars": 36,
    "preview": "interface IDemo {\n    age: number\n}\n"
  },
  {
    "path": "src/types/global.d.ts",
    "chars": 145,
    "preview": "declare module '*.png' {\n    const value: string\n    export = value\n}\n\ndeclare module '*.mp4' {\n    const content: strin"
  },
  {
    "path": "tsconfig.json",
    "chars": 1002,
    "preview": "{\n  \"compilerOptions\": {\n    \"outDir\": \"./lib\",\n    // \"sourceMap\": true,\n    \"noImplicitAny\": false, //在表达式和声明上有隐含的 any"
  },
  {
    "path": "tslint.json",
    "chars": 298,
    "preview": "{\n  \"extends\": [\"tslint:recommended\", \"tslint-config-prettier\"],\n  \"rules\": {\n    \"no-console\": false,\n    \"object-liter"
  },
  {
    "path": "webpack.config.js",
    "chars": 1385,
    "preview": "const path = require('path')\nconst HtmlWebpackPlugin = require('html-webpack-plugin')\nconst htmlWebpackPlugin = new Html"
  }
]

About this extraction

This page contains the full source code of the DavidWong9785/react-virtualized-scroll GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 40 files (71.6 KB), approximately 28.9k tokens, and a symbol index with 6 extracted functions, classes, methods, constants, and types. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.

Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.

Copied to clipboard!