[
  {
    "path": ".babelrc",
    "content": "{\n  \"presets\": [\"es2015\", \"stage-1\", \"react\"]\n}"
  },
  {
    "path": ".gitignore",
    "content": "# Logs\nlogs\n*.log\nnpm-debug.log*\nyarn-debug.log*\nyarn-error.log*\npackage-lock.json\n\n# Runtime data\npids\n*.pid\n*.seed\n*.pid.lock\n\n# Directory for instrumented libs generated by jscoverage/JSCover\nlib-cov\n\n# Coverage directory used by tools like istanbul\ncoverage\n\n# nyc test coverage\n.nyc_output\n\n# Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files)\n.grunt\n\n# Bower dependency directory (https://bower.io/)\nbower_components\n\n# node-waf configuration\n.lock-wscript\n\n# Compiled binary addons (http://nodejs.org/api/addons.html)\nbuild/Release\n\n# Dependency directories\nnode_modules/\njspm_packages/\n\n# Typescript v1 declaration files\ntypings/\n\n# Optional npm cache directory\n.npm\n\n# Optional eslint cache\n.eslintcache\n\n# Optional REPL history\n.node_repl_history\n\n# Output of 'npm pack'\n*.tgz\n\n# Yarn Integrity file\n.yarn-integrity\n\n# dotenv environment variables file\n.env\n\ndemo\n\ndeploy.config.json\n\ndist\n\n.publish\n"
  },
  {
    "path": "README-cn.md",
    "content": "# [English](./README.md)\n\n# [react-pullLoad](https://github.com/react-ld/react-pullLoad)\n\nReact 版本的 [pullLoad](https://github.com/lidianhao123/pullLoad) 下拉更新 上拉加载更多 组件\n\n[pullLoad](https://github.com/lidianhao123/pullLoad) 非 react 版本，支持 require.js 模块化调用\n\n#### 示例\n\n[demo1](https://react-ld.github.io/react-pullLoad/index1.html) ReactPullLoad 根节点 DOM 作为容器\n\n[demo2](https://react-ld.github.io/react-pullLoad/index2.html) ReactPullLoad 根节点 DOM 作为容器\n\n[demo3](https://react-ld.github.io/react-pullLoad/index3.html) document.body 作为容器 且自定义刷新和加载更多 UI 组件\n\n[demo4](https://react-ld.github.io/react-pullLoad/index4.html) 禁用下拉刷新功能\n\n# 当前版本 1.2.0\n\n支持 Typescript\n\n# 简介\n\n1. 只依赖 react/react-dom\n2. 样式使用 less 编写\n3. 支持 body 或者组件根 DOM 固定高度作为外部容器 contianer（即可视区域大小）\n4. 触摸事件绑定在内容块 content（即高度为 auto 的 DOM ）\n5. 纯 React 组件方式开发的\n6. 支持自定义刷新和加载更多 UI 组件\n7. 支持代码动态调起刷新和加载更多（组件将展示刷新和加载更多样式）\n8. **只支持移动触摸设备**\n\n# 功能点\n\n1. 下拉距离大于阈值触发刷新动作\n2. 滚动到距底部距离小于阈值加载更多\n3. 支持自定义刷新和加载更多 UI 组件\n\n# 使用说明\n\n```sh\nnpm install --save react-pullload\n```\n\n```js\nimport ReactPullLoad, { STATS } from \"react-pullload\";\nimport \"node_modules/react-pullload/dist/ReactPullLoad.css\";\n\nexport class App extends Component {\n  constructor() {\n    super();\n    this.state = {\n      hasMore: true,\n      data: cData,\n      action: STATS.init,\n      index: loadMoreLimitNum //loading more test time limit\n    };\n  }\n\n  handleAction = action => {\n    console.info(action, this.state.action, action === this.state.action);\n    //new action must do not equel to old action\n    if (action === this.state.action) {\n      return false;\n    }\n\n    if (action === STATS.refreshing) {\n      //刷新\n      this.handRefreshing();\n    } else if (action === STATS.loading) {\n      //加载更多\n      this.handLoadMore();\n    } else {\n      //DO NOT modify below code\n      this.setState({\n        action: action\n      });\n    }\n  };\n\n  handRefreshing = () => {\n    if (STATS.refreshing === this.state.action) {\n      return false;\n    }\n\n    setTimeout(() => {\n      //refreshing complete\n      this.setState({\n        data: cData,\n        hasMore: true,\n        action: STATS.refreshed,\n        index: loadMoreLimitNum\n      });\n    }, 3000);\n\n    this.setState({\n      action: STATS.refreshing\n    });\n  };\n\n  handLoadMore = () => {\n    if (STATS.loading === this.state.action) {\n      return false;\n    }\n    //无更多内容则不执行后面逻辑\n    if (!this.state.hasMore) {\n      return;\n    }\n\n    setTimeout(() => {\n      if (this.state.index === 0) {\n        this.setState({\n          action: STATS.reset,\n          hasMore: false\n        });\n      } else {\n        this.setState({\n          data: [...this.state.data, cData[0], cData[0]],\n          action: STATS.reset,\n          index: this.state.index - 1\n        });\n      }\n    }, 3000);\n\n    this.setState({\n      action: STATS.loading\n    });\n  };\n\n  render() {\n    const { data, hasMore } = this.state;\n\n    const fixHeaderStyle = {\n      position: \"fixed\",\n      width: \"100%\",\n      height: \"50px\",\n      color: \"#fff\",\n      lineHeight: \"50px\",\n      backgroundColor: \"#e24f37\",\n      left: 0,\n      top: 0,\n      textAlign: \"center\",\n      zIndex: 1\n    };\n\n    return (\n      <div>\n        <div style={fixHeaderStyle}>fixed header</div>\n        <ReactPullLoad\n          downEnough={150}\n          action={this.state.action}\n          handleAction={this.handleAction}\n          hasMore={hasMore}\n          style={{ paddingTop: 50 }}\n          distanceBottom={1000}\n        >\n          <ul className=\"test-ul\">\n            <button onClick={this.handRefreshing}>refreshing</button>\n            <button onClick={this.handLoadMore}>loading more</button>\n            {data.map((str, index) => {\n              return (\n                <li key={index}>\n                  <img src={str} alt=\"\" />\n                </li>\n              );\n            })}\n          </ul>\n        </ReactPullLoad>\n      </div>\n    );\n  }\n}\n```\n\n# 参数说明：\n\n| 参数             | 说明                                          | 类型   | 默认值                                           | 备注                  |\n| ---------------- | --------------------------------------------- | ------ | ------------------------------------------------ | --------------------- |\n| action           | 用于同步状态                                  | string |                                                  | isRequired            |\n| handleAction     | 用于处理状态                                  | func   |                                                  | isRequired            |\n| hasMore          | 是否还有更多内容可加载                        | bool   | false                                            |                       |\n| downEnough       | 下拉距离是否满足要求                          | num    | 100                                              |                       |\n| distanceBottom   | 距离底部距离触发加载更多                      | num    | 100                                              |                       |\n| isBlockContainer | 是否开启使用组件根 DOM 作为外部容器 contianer | bool   | false                                            |                       |\n| HeadNode         | 自定义顶部刷新 UI 组件                        | any    | [ReactPullLoad HeadNode](./src/HeadNode.jsx)     | 必须是一个 React 组件 |\n| FooterNode       | 自定义底部加载更多 UI 组件                    | any    | [ReactPullLoad FooterNode](./src/FooterNode.jsx) | 必须是一个 React 组件 |\n\n另外 ReactPullLoad 组件支持根属性扩展 例如： className\\style 等等\n\n# STATS list\n\n| 属性       | 值               | 根节点 className     | 说明                 |\n| ---------- | ---------------- | -------------------- | -------------------- |\n| init       | ''               |                      | 组件初始状态         |\n| pulling    | 'pulling'        | state-pulling        | 下拉状态             |\n| enough     | 'pulling enough' | state-pulling.enough | 下拉并且已经满足阈值 |\n| refreshing | 'refreshing'     | state-refreshing     | 刷新中（加载数据中） |\n| refreshed  | 'refreshed'      | state-refreshed      | 完成刷新动作         |\n| reset      | 'reset'          | state-reset          | 恢复默认状态         |\n| loading    | 'loading'        | state-loading        | 加载中               |\n\ninit/reset -> pulling -> enough -> refreshing -> refreshed -> reset\n\ninit/reset -> pulling -> reset\n\ninit/reset -> loading -> reset\n\n# 自定义刷新及加载组件\n\n请参考默认刷新及加载组件源码（通过 css 根节点不同 className 设置对应 UI 样式来实现）\n\n[ReactPullLoad HeadNode](./src/HeadNode.jsx)\n\n[ReactPullLoad FooterNode](./src/FooterNode.jsx)\n\n或参考 demo3 中的实现方式在组件内容通过获取的 loaderState 与 STATS 不同状态对比来现实\n\n[demo3](https://react-ld.github.io/react-pullLoad/index3.html)\n\n# License\n\nMIT\n"
  },
  {
    "path": "README.md",
    "content": "# [中文](./README-cn.md)\n\n# [react-pullLoad](https://github.com/react-ld/react-pullLoad)\n\nRefreshing and Loading more component for react.\n\n[pullLoad](https://github.com/lidianhao123/pullLoad) is another refreshing and loading more lib without react, support require.js to load lib.\n\n#### examples\n\n[demo1](https://react-ld.github.io/react-pullLoad/index1.html) use ReactPullLoad root DOM as container\n\n[demo2](https://react-ld.github.io/react-pullLoad/index2.html) use ReactPullLoad root DOM as container\n\n[demo3](https://react-ld.github.io/react-pullLoad/index3.html) use document.body as container, and config UI component (HeadNode and FooterNode).\n\n[demo4](https://react-ld.github.io/react-pullLoad/index4.html) forbidden pull refresh\n\n# version 1.2.0\n\nSupport Typescript\n\n# Description\n\n1. Only depend on react/react-dom, without any other package.\n2. Use less.\n3. Support body or root Dom as container.\n4. Bind touch event on component root Dom.\n5. It.s develop as Pure react component.\n6. Support config UI component (HeadNode and FooterNode).\n7. Can apply refreshing or loading through modify STATE.\n8. **Only support mobile device**\n\n# How to use\n\n```sh\nnpm install --save react-pullload\n```\n\n```js\nimport ReactPullLoad, { STATS } from \"react-pullload\";\nimport \"node_modules/react-pullload/dist/ReactPullLoad.css\";\n\nexport class App extends Component {\n  constructor() {\n    super();\n    this.state = {\n      hasMore: true,\n      data: cData,\n      action: STATS.init,\n      index: loadMoreLimitNum //loading more test time limit\n    };\n  }\n\n  handleAction = action => {\n    console.info(action, this.state.action, action === this.state.action);\n    //new action must do not equel to old action\n    if (action === this.state.action) {\n      return false;\n    }\n\n    if (action === STATS.refreshing) {\n      this.handRefreshing();\n    } else if (action === STATS.loading) {\n      this.handLoadMore();\n    } else {\n      //DO NOT modify below code\n      this.setState({\n        action: action\n      });\n    }\n  };\n\n  handRefreshing = () => {\n    if (STATS.refreshing === this.state.action) {\n      return false;\n    }\n\n    setTimeout(() => {\n      //refreshing complete\n      this.setState({\n        data: cData,\n        hasMore: true,\n        action: STATS.refreshed,\n        index: loadMoreLimitNum\n      });\n    }, 3000);\n\n    this.setState({\n      action: STATS.refreshing\n    });\n  };\n\n  handLoadMore = () => {\n    if (STATS.loading === this.state.action) {\n      return false;\n    }\n    //无更多内容则不执行后面逻辑\n    if (!this.state.hasMore) {\n      return;\n    }\n\n    setTimeout(() => {\n      if (this.state.index === 0) {\n        this.setState({\n          action: STATS.reset,\n          hasMore: false\n        });\n      } else {\n        this.setState({\n          data: [...this.state.data, cData[0], cData[0]],\n          action: STATS.reset,\n          index: this.state.index - 1\n        });\n      }\n    }, 3000);\n\n    this.setState({\n      action: STATS.loading\n    });\n  };\n\n  render() {\n    const { data, hasMore } = this.state;\n\n    const fixHeaderStyle = {\n      position: \"fixed\",\n      width: \"100%\",\n      height: \"50px\",\n      color: \"#fff\",\n      lineHeight: \"50px\",\n      backgroundColor: \"#e24f37\",\n      left: 0,\n      top: 0,\n      textAlign: \"center\",\n      zIndex: 1\n    };\n\n    return (\n      <div>\n        <div style={fixHeaderStyle}>fixed header</div>\n        <ReactPullLoad\n          downEnough={150}\n          action={this.state.action}\n          handleAction={this.handleAction}\n          hasMore={hasMore}\n          style={{ paddingTop: 50 }}\n          distanceBottom={1000}\n        >\n          <ul className=\"test-ul\">\n            <button onClick={this.handRefreshing}>refreshing</button>\n            <button onClick={this.handLoadMore}>loading more</button>\n            {data.map((str, index) => {\n              return (\n                <li key={index}>\n                  <img src={str} alt=\"\" />\n                </li>\n              );\n            })}\n          </ul>\n        </ReactPullLoad>\n      </div>\n    );\n  }\n}\n```\n\n# API：\n\n| Property         | Description                                 | Type   | default                                          | Remarks                   |\n| ---------------- | ------------------------------------------- | ------ | ------------------------------------------------ | ------------------------- |\n| action           | sync component status                       | string |                                                  | isRequired                |\n| handleAction     | handle status                               | func   |                                                  | isRequired                |\n| hasMore          | flag for are there any more content to load | bool   | false                                            |                           |\n| downEnough       | how long distance is enough to refreshing   | num    | 100                                              | use px as unit            |\n| distanceBottom   | current position is apart from bottom       | num    | 100                                              | use px as unit            |\n| isBlockContainer | set root dom as container                   | bool   | false                                            |                           |\n| HeadNode         | custom header UI compoent                   | any    | [ReactPullLoad HeadNode](./src/HeadNode.jsx)     | must be a react component |\n| FooterNode       | custom footer UI compoent                   | any    | [ReactPullLoad FooterNode](./src/FooterNode.jsx) | must be a react component |\n\nRemarks: ReactPullLoad support set root dom className and style.\n\n# STATS list\n\n| Property   | Value            | root className       | explain                      |\n| ---------- | ---------------- | -------------------- | ---------------------------- |\n| init       | ''               |                      | component initial status     |\n| pulling    | 'pulling'        | state-pulling        | pull status                  |\n| enough     | 'pulling enough' | state-pulling.enough | pull down enough status      |\n| refreshing | 'refreshing'     | state-refreshing     | refreshing status fetch data |\n| refreshed  | 'refreshed'      | state-refreshed      | refreshed                    |\n| reset      | 'reset'          | state-reset          | reset status                 |\n| loading    | 'loading'        | state-loading        | fetching data                |\n\ninit/reset -> pulling -> enough -> refreshing -> refreshed -> reset\n\ninit/reset -> pulling -> reset\n\ninit/reset -> loading -> reset\n\n# Custom UI components\n\nPlease refer to the default HeadNode and FooterNode components\n\n[ReactPullLoad HeadNode](./src/HeadNode.jsx)\n\n[ReactPullLoad FooterNode](./src/FooterNode.jsx)\n\nOr refer to demo3, show different dom style through compare props loaderState width STATS.\n\n[demo3](https://react-ld.github.io/react-pullLoad/index3.html)\n\n# License\n\nMIT\n"
  },
  {
    "path": "example/App.css",
    "content": "html,body{margin: 0; padding: 0;}\nli{font-size: 20px; width: 100%;list-style: none;}\nimg{width: 100%;}\ndiv, .test-ul, p{margin: 0; padding: 0;}\n.block{position: absolute; top:0; left:0; box-sizing: border-box; height: 100%;box-sizing: border-box;}\n\nbutton{\n  display: inline-block;\n  font-weight: 500;\n  text-align: center;\n  -ms-touch-action: manipulation;\n  touch-action: manipulation;\n  cursor: pointer;\n  background-image: none;\n  border: 1px solid transparent;\n  white-space: nowrap;\n  line-height: 1.5;\n  padding: 4px 15px;\n  font-size: 12px;\n  border-radius: 4px;\n  -webkit-user-select: none;\n  -moz-user-select: none;\n  -ms-user-select: none;\n  user-select: none;\n  -webkit-transition: all .3s cubic-bezier(.645,.045,.355,1);\n  transition: all .3s cubic-bezier(.645,.045,.355,1);\n  position: relative;\n  color: rgba(0,0,0,.65);\n  background-color: #fff;\n  border-color: #d9d9d9;\n  outline: 0;\n  margin-right: 8px;\n  margin-bottom: 12px;\n  margin-top: 12px;\n  -webkit-appearance: button;\n  box-sizing: border-box;\n}"
  },
  {
    "path": "example/App1.jsx",
    "content": "\nimport React, { Component, PureComponent } from 'react'\nimport PropTypes from 'prop-types';\nimport { render } from 'react-dom'\nimport ReactPullLoad,{STATS} from 'index.js'\nimport '../src/ReactPullLoad.less'\nimport './App.css'\n\n\nconst defaultStyle ={\n  width: \"100%\",\n  textAlign: \"center\",\n  fontSize: \"20px\",\n  lineHeight: \"1.5\"\n}\n\nconst loadMoreLimitNum = 2;\n\nconst cData = [\n    \"http://img1.gtimg.com/15/1580/158031/15803178_1200x1000_0.jpg\",\n    \"http://img1.gtimg.com/15/1580/158031/15803179_1200x1000_0.jpg\",\n    \"http://img1.gtimg.com/15/1580/158031/15803181_1200x1000_0.jpg\",\n    \"http://img1.gtimg.com/15/1580/158031/15803182_1200x1000_0.jpg\",\n    \"http://img1.gtimg.com/15/1580/158031/15803183_1200x1000_0.jpg\",\n    // \"http://img1.gtimg.com/15/1580/158031/15803184_1200x1000_0.jpg\",\n    // \"http://img1.gtimg.com/15/1580/158031/15803186_1200x1000_0.jpg\"\n]\n\nexport class App extends Component{\n  constructor(){\n    super();\n    this.state ={\n      hasMore: true,\n      data: cData,\n      action: STATS.init,\n      index: loadMoreLimitNum //loading more test time limit\n    }\n  }\n\n  handleAction = (action) => {\n    console.info(action, this.state.action,action === this.state.action);\n    //new action must do not equel to old action\n    if(action === this.state.action ||\n       action === STATS.refreshing && this.state.action === STATS.loading ||\n       action === STATS.loading && this.state.action === STATS.refreshing){\n      // console.info(\"It's same action or on loading or on refreshing \",action, this.state.action,action === this.state.action);\n      return false\n    }\n\n    if(action === STATS.refreshing){//刷新\n      setTimeout(()=>{\n        //refreshing complete\n        this.setState({\n          data: cData,\n          hasMore: true,\n          action: STATS.refreshed,\n          index: loadMoreLimitNum\n        });\n      }, 3000)\n    } else if(action === STATS.loading){//加载更多\n      this.setState({\n        hasMore: true\n      });\n      setTimeout(()=>{\n        if(this.state.index === 0){\n          this.setState({\n            action: STATS.reset,\n            hasMore: false\n          });\n        } else{\n          this.setState({\n            data: [...this.state.data, cData[0], cData[0]],\n            action: STATS.reset,\n            index: this.state.index - 1\n          });\n        }\n      }, 3000)\n    }\n\n    //DO NOT modify below code\n    this.setState({\n      action: action\n    })\n  }\n\n  getScrollTop = ()=>{\n    if(this.refs.reactpullload){\n      console.info(this.refs.reactpullload.getScrollTop());\n    }\n  }\n  setScrollTop = ()=>{\n    if(this.refs.reactpullload){\n      console.info(this.refs.reactpullload.setScrollTop(100));\n    }\n  }\n  \n  render(){\n    const {\n      data, \n      hasMore\n    } = this.state\n\n    const fixHeaderStyle = {\n      position: \"fixed\",\n      width: \"100%\",\n      height: \"50px\",\n      color: \"#fff\",\n      lineHeight: \"50px\",\n      backgroundColor: \"#e24f37\",\n      left: 0,\n      top: 0,\n      textAlign: \"center\",\n      zIndex: 1\n    }\n\n    const fixButtonStyle = {\n      position: \"fixed\",\n      top: 200,\n      width: \"100%\",\n    }\n\n    return (\n      <div>\n        <div style={fixHeaderStyle}>\n          fixed header    \n        </div>\n        <ReactPullLoad \n          downEnough={150}\n          ref=\"reactpullload\"\n          className=\"block\"\n          isBlockContainer={true}\n          action={this.state.action}\n          handleAction={this.handleAction}\n          hasMore={hasMore}\n          style={{paddingTop: 50}}\n          distanceBottom={1000}>\n          <ul className=\"test-ul\">\n            <button onClick={this.handleAction.bind(this, STATS.refreshing)}>refreshing</button>\n            <button onClick={this.handleAction.bind(this, STATS.loading)}>loading more</button>\n            <div style={fixButtonStyle}>\n              <button onClick={this.getScrollTop}>getScrollTop</button>\n              <button onClick={this.setScrollTop}>setScrollTop</button>\n            </div>\n            {\n              data.map( (str, index )=>{\n                return <li key={index}><img src={str} alt=\"\"/></li>\n              })\n            }\n          </ul>\n        </ReactPullLoad>\n      </div>\n    )\n  }\n}\n\nrender(\n  <App />,\n  document.getElementById('root')\n)"
  },
  {
    "path": "example/App2.jsx",
    "content": "\nimport React, { Component, PureComponent } from 'react'\nimport PropTypes from 'prop-types';\nimport { render } from 'react-dom'\nimport ReactPullLoad,{STATS} from 'index.js'\nimport '../src/ReactPullLoad.less'\nimport './App.css'\n\nconst defaultStyle ={\n  width: \"100%\",\n  textAlign: \"center\",\n  fontSize: \"20px\",\n  lineHeight: \"1.5\"\n}\n\nconst loadMoreLimitNum = 2;\n\nconst cData = [\n    \"http://img1.gtimg.com/15/1580/158031/15803178_1200x1000_0.jpg\",\n    \"http://img1.gtimg.com/15/1580/158031/15803179_1200x1000_0.jpg\",\n    \"http://img1.gtimg.com/15/1580/158031/15803181_1200x1000_0.jpg\",\n    \"http://img1.gtimg.com/15/1580/158031/15803182_1200x1000_0.jpg\",\n    \"http://img1.gtimg.com/15/1580/158031/15803183_1200x1000_0.jpg\",\n    // \"http://img1.gtimg.com/15/1580/158031/15803184_1200x1000_0.jpg\",\n    // \"http://img1.gtimg.com/15/1580/158031/15803186_1200x1000_0.jpg\"\n]\n\nexport class App extends Component{\n  constructor(){\n    super();\n    this.state ={\n      hasMore: true,\n      data: cData,\n      action: STATS.init,\n      index: loadMoreLimitNum //loading more test time limit\n    }\n  }\n\n  handleAction = (action) => {\n    console.info(action, this.state.action,action === this.state.action);\n    //new action must do not equel to old action\n    if(action === this.state.action ||\n       action === STATS.refreshing && this.state.action === STATS.loading ||\n       action === STATS.loading && this.state.action === STATS.refreshing){\n      console.info(\"It's same action or on loading or on refreshing \",action, this.state.action,action === this.state.action);\n      return false\n    }\n\n    if(action === STATS.refreshing){//刷新\n      setTimeout(()=>{\n        //refreshing complete\n        this.setState({\n          data: cData,\n          hasMore: true,\n          action: STATS.refreshed,\n          index: loadMoreLimitNum\n        });\n      }, 3000)\n    } else if(action === STATS.loading){//加载更多      \n      this.setState({\n        hasMore: true\n      });\n      setTimeout(()=>{\n        if(this.state.index === 0){\n          this.setState({\n            action: STATS.reset,\n            hasMore: false\n          });\n        } else{\n          this.setState({\n            data: [...this.state.data, cData[0], cData[0]],\n            action: STATS.reset,\n            index: this.state.index - 1\n          });\n        }\n      }, 3000)\n    }\n\n    //DO NOT modify below code\n    this.setState({\n      action: action\n    })\n  }\n  \n  render(){\n    const {\n      data,\n      hasMore\n    } = this.state\n\n    return (\n      <div>\n        <ReactPullLoad \n          className=\"block\"\n          isBlockContainer={true}\n          downEnough={150}\n          action={this.state.action}\n          handleAction={this.handleAction}\n          hasMore={hasMore}\n          distanceBottom={1000}>\n          <ul className=\"test-ul\">\n            <button onClick={this.handleAction.bind(this, STATS.refreshing)}>refreshing</button>\n            <button onClick={this.handleAction.bind(this, STATS.loading)}>loading more</button>\n            {\n              data.map( (str, index )=>{\n                return <li key={index}><img src={str} alt=\"\"/></li>\n              })\n            }\n          </ul>\n        </ReactPullLoad>\n      </div>\n    )\n  }\n}\n\nrender(\n  <App />,\n  document.getElementById('root')\n)"
  },
  {
    "path": "example/App3.jsx",
    "content": "\nimport React, { Component, PureComponent } from 'react'\nimport PropTypes from 'prop-types';\nimport { render } from 'react-dom'\nimport ReactPullLoad,{STATS} from 'index.js'\nimport '../src/ReactPullLoad.less'\nimport './App.css'\n\nconst defaultStyle ={\n  width: \"100%\",\n  textAlign: \"center\",\n  fontSize: \"20px\",\n  lineHeight: \"1.5\"\n}\n\nclass HeadNode extends PureComponent{\n\n  static propTypes = {\n    loaderState: PropTypes.string.isRequired,\n  };\n\n  static defaultProps = {\n    loaderState: STATS.init,\n  };\n\n  render(){\n    const {\n      loaderState\n    } = this.props\n\n    let content = \"\"\n    if(loaderState == STATS.pulling){\n      content = \"下拉刷新\"\n    } else if(loaderState == STATS.enough){\n      content = \"松开刷新\"\n    } else if(loaderState == STATS.refreshing){\n      content = \"正在刷新...\"\n    } else if(loaderState == STATS.refreshed){\n      content = \"刷新成功\"\n    }\n\n    return(\n      <div style={defaultStyle}>\n        {content}\n      </div>\n    )\n  }\n}\n\nclass FooterNode extends PureComponent{\n\n  static propTypes = {\n    loaderState: PropTypes.string.isRequired,\n    hasMore: PropTypes.bool.isRequired\n  };\n\n  static defaultProps = {\n    loaderState: STATS.init,\n    hasMore: true\n  };\n\n  render(){\n    const {\n      loaderState,\n      hasMore\n    } = this.props\n\n    let content = \"\"\n    // if(hasMore === false){\n    //   content = \"没有更多\"\n    // } else if(loaderState == STATS.loading && hasMore === true){\n    //   content = \"加载中\"\n    // } \n    if(loaderState == STATS.loading){\n      content = \"加载中\"\n    } else if(hasMore === false){\n      content = \"没有更多\"\n    }\n\n    return(\n      <div style={defaultStyle}>\n        {content}\n      </div>\n    )\n  }\n}\n\nconst loadMoreLimitNum = 2;\n\nconst cData = [\n    \"http://img1.gtimg.com/15/1580/158031/15803178_1200x1000_0.jpg\",\n    \"http://img1.gtimg.com/15/1580/158031/15803179_1200x1000_0.jpg\",\n    \"http://img1.gtimg.com/15/1580/158031/15803181_1200x1000_0.jpg\",\n    \"http://img1.gtimg.com/15/1580/158031/15803182_1200x1000_0.jpg\",\n    \"http://img1.gtimg.com/15/1580/158031/15803183_1200x1000_0.jpg\",\n    // \"http://img1.gtimg.com/15/1580/158031/15803184_1200x1000_0.jpg\",\n    // \"http://img1.gtimg.com/15/1580/158031/15803186_1200x1000_0.jpg\"\n]\n\nexport class App extends Component{\n  constructor(){\n    super();\n    this.state ={\n      hasMore: true,\n      data: cData,\n      action: STATS.init,\n      index: loadMoreLimitNum //loading more test time limit\n    }\n  }\n\n  handleAction = (action) => {\n    //new action must do not equel to old action\n    if(action === this.state.action ||\n       action === STATS.refreshing && this.state.action === STATS.loading ||\n       action === STATS.loading && this.state.action === STATS.refreshing){\n      console.info(\"It's same action or on loading or on refreshing \",action, this.state.action,action === this.state.action);\n      return false\n    }\n\n    if(action === STATS.refreshing){//刷新\n      setTimeout(()=>{\n        //refreshing complete\n        this.setState({\n          data: cData,\n          hasMore: true,\n          action: STATS.refreshed,\n          index: loadMoreLimitNum\n        });\n      }, 3000)\n    } else if(action === STATS.loading && this.state.hasMore){//加载更多\n      setTimeout(()=>{\n        if(this.state.index === 0){\n          this.setState({\n            action: STATS.reset,\n            hasMore: false\n          });\n        } else{\n          this.setState({\n            data: [...this.state.data, cData[0], cData[0]],\n            action: STATS.reset,\n            index: this.state.index - 1\n          });\n        }\n      }, 3000)\n    }\n\n    //无更多内容，不再加载数据\n    if(action === STATS.loading && !this.state.hasMore){\n      return;\n    }\n    //DO NOT modify below code\n    this.setState({\n      action: action\n    })\n  }\n  \n  render(){\n    const {\n      data, \n      hasMore\n    } = this.state\n\n    const fixHeaderStyle = {\n      position: \"fixed\",\n      width: \"100%\",\n      height: \"50px\",\n      color: \"#fff\",\n      lineHeight: \"50px\",\n      backgroundColor: \"#e24f37\",\n      left: 0,\n      top: 0,\n      textAlign: \"center\",\n      zIndex: 1\n    }\n\n    return (\n      <div>\n        <div style={fixHeaderStyle}>\n          fixed header    \n        </div>\n        <ReactPullLoad \n          downEnough={100}\n          action={this.state.action}\n          handleAction={this.handleAction}\n          hasMore={hasMore}\n          HeadNode={HeadNode}\n          FooterNode={FooterNode}\n          style={{paddingTop: 50}}\n          distanceBottom={1000}>\n          <ul className=\"test-ul\">\n            <button onClick={this.handleAction.bind(this, STATS.refreshing)}>refreshing</button>\n            <button onClick={this.handleAction.bind(this, STATS.loading)}>loading more</button>\n            {\n              data.map( (str, index )=>{\n                return <li key={index}><img src={str} alt=\"\"/></li>\n              })\n            }\n          </ul>\n        </ReactPullLoad>\n      </div>\n    )\n  }\n}\n\nrender(\n  <App />,\n  document.getElementById('root')\n)"
  },
  {
    "path": "example/App4.jsx",
    "content": "\nimport React, { Component, PureComponent } from 'react'\nimport PropTypes from 'prop-types';\nimport { render } from 'react-dom'\nimport ReactPullLoad,{STATS} from 'index.js'\nimport '../src/ReactPullLoad.less'\nimport './App.css'\n\nconst defaultStyle ={\n  width: \"100%\",\n  textAlign: \"center\",\n  fontSize: \"20px\",\n  lineHeight: \"1.5\"\n}\n\nconst loadMoreLimitNum = 2;\n\nconst cData = [\n    \"http://img1.gtimg.com/15/1580/158031/15803178_1200x1000_0.jpg\",\n    \"http://img1.gtimg.com/15/1580/158031/15803179_1200x1000_0.jpg\",\n    \"http://img1.gtimg.com/15/1580/158031/15803181_1200x1000_0.jpg\",\n    \"http://img1.gtimg.com/15/1580/158031/15803182_1200x1000_0.jpg\",\n    \"http://img1.gtimg.com/15/1580/158031/15803183_1200x1000_0.jpg\",\n    // \"http://img1.gtimg.com/15/1580/158031/15803184_1200x1000_0.jpg\",\n    // \"http://img1.gtimg.com/15/1580/158031/15803186_1200x1000_0.jpg\"\n]\n\nexport class App extends Component{\n  constructor(){\n    super();\n    this.state ={\n      hasMore: true,\n      data: cData,\n      action: STATS.init,\n      index: loadMoreLimitNum //loading more test time limit\n    }\n  }\n\n  handleAction = (action) => {\n    console.info(action, this.state.action,action === this.state.action);\n    if(action !== STATS.loading){\n      return false;\n    }\n\n    this.setState({\n      hasMore: true\n    });\n    setTimeout(()=>{\n      if(this.state.index === 0){\n        this.setState({\n          action: STATS.reset,\n          hasMore: false\n        });\n      } else{\n        this.setState({\n          data: [...this.state.data, cData[0], cData[0]],\n          action: STATS.reset,\n          index: this.state.index - 1\n        });\n      }\n    }, 3000)\n\n    //DO NOT modify below code\n    this.setState({\n      action: action\n    })\n  }\n\n  getScrollTop = ()=>{\n    if(this.refs.reactpullload){\n      console.info(this.refs.reactpullload.getScrollTop());\n    }\n  }\n  setScrollTop = ()=>{\n    if(this.refs.reactpullload){\n      console.info(this.refs.reactpullload.setScrollTop(100));\n    }\n  }\n  \n  render(){\n    const {\n      data, \n      hasMore\n    } = this.state\n\n    const fixHeaderStyle = {\n      position: \"fixed\",\n      width: \"100%\",\n      height: \"50px\",\n      color: \"#fff\",\n      lineHeight: \"50px\",\n      backgroundColor: \"#e24f37\",\n      left: 0,\n      top: 0,\n      textAlign: \"center\",\n      zIndex: 1\n    }\n\n    const fixButtonStyle = {\n      position: \"fixed\",\n      top: 200,\n      width: \"100%\",\n    }\n\n    return (\n      <div>\n        <div style={fixHeaderStyle}>\n          fixed header    \n        </div>\n        <ReactPullLoad \n          downEnough={150}\n          ref=\"reactpullload\"\n          className=\"block\"\n          isBlockContainer={true}\n          action={this.state.action}\n          handleAction={this.handleAction}\n          hasMore={hasMore}\n          style={{paddingTop: 50}}\n          distanceBottom={1000}>\n          <ul className=\"test-ul\">\n            <button onClick={this.handleAction.bind(this, STATS.refreshing)}>refreshing</button>\n            <button onClick={this.handleAction.bind(this, STATS.loading)}>loading more</button>\n            <div style={fixButtonStyle}>\n              <button onClick={this.getScrollTop}>getScrollTop</button>\n              <button onClick={this.setScrollTop}>setScrollTop</button>\n            </div>\n            {\n              data.map( (str, index )=>{\n                return <li key={index}><img src={str} alt=\"\"/></li>\n              })\n            }\n          </ul>\n        </ReactPullLoad>\n      </div>\n    )\n  }\n}\n\nrender(\n  <App />,\n  document.getElementById('root')\n)"
  },
  {
    "path": "example/README.md",
    "content": "# 示例\n[demo1](https://react-ld.github.io/react-pullLoad/index1.html) ReactPullLoad 根节点 DOM 作为容器\n\n[demo2](https://react-ld.github.io/react-pullLoad/index2.html) ReactPullLoad 根节点 DOM 作为容器\n\n[demo3](https://react-ld.github.io/react-pullLoad/index3.html) document.body 作为容器 且自定义刷新和加载更多 UI 组件\n\n[demo4](https://react-ld.github.io/react-pullLoad/index4.html) 禁用下拉刷新功能\n\n# 文档\n\n [react-pullLoad](https://github.com/react-ld/react-pullLoad)"
  },
  {
    "path": "example/index1.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n    <meta charset=\"UTF-8\">\n    <title>ReactPullLoad demo1</title>\n    <meta name=\"viewport\" content=\"width=device-width, initial-scale=1, maximum-scale=1, user-scalable=0\">\n</head>\n<body>\n    <div id=\"root\"></div>\n    <!-- \n        bundle1.js is demo use document as contianer \n        bundle2.js is demo use ReactPullLoad root DOM as contianer \n    -->\n    <script src=\"./bundle1.js\"></script>\n</body>\n</html>"
  },
  {
    "path": "example/index2.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n    <meta charset=\"UTF-8\">\n    <title>ReactPullLoad demo2</title>\n    <meta name=\"viewport\" content=\"width=device-width, initial-scale=1, maximum-scale=1, user-scalable=0\">\n</head>\n<body>\n    <div id=\"root\"></div>\n    <!-- \n        bundle1.js is demo use document as contianer \n        bundle2.js is demo use ReactPullLoad root DOM as contianer \n    -->\n    <script src=\"./bundle2.js\"></script>\n</body>\n</html>"
  },
  {
    "path": "example/index3.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n    <meta charset=\"UTF-8\">\n    <title>ReactPullLoad demo3</title>\n    <meta name=\"viewport\" content=\"width=device-width, initial-scale=1, maximum-scale=1, user-scalable=0\">\n</head>\n<body>\n    <div id=\"root\"></div>\n    <!-- \n        bundle1.js is demo use document as contianer \n        bundle2.js is demo use ReactPullLoad root DOM as contianer \n    -->\n    <script src=\"./bundle3.js\"></script>\n</body>\n</html>"
  },
  {
    "path": "example/index4.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n    <meta charset=\"UTF-8\">\n    <title>ReactPullLoad demo4</title>\n    <meta name=\"viewport\" content=\"width=device-width, initial-scale=1, maximum-scale=1, user-scalable=0\">\n</head>\n<body>\n    <div id=\"root\"></div>\n    <!-- \n        bundle1.js is demo use document as contianer \n        bundle2.js is demo use ReactPullLoad root DOM as contianer \n    -->\n    <script src=\"./bundle4.js\"></script>\n</body>\n</html>"
  },
  {
    "path": "gulpfile.js",
    "content": "var gulp = require('gulp');\nvar webpack = require('webpack');\nvar clean = require('gulp-clean');\nvar gutil = require('gulp-util');\n// var ftp = require( 'vinyl-ftp' );\nvar ghPages = require('gulp-gh-pages');\n// var deploy = require('./deploy.config.json');\nvar deploy_remote_path = \"/public/17zt/viewer\"\nvar webpack_config_demo = require('./webpack.config.example.js');\nvar babel = require('gulp-babel');\nvar less = require('gulp-less');\nvar path = require('path');\n\ngulp.task('demo:clean', function(){\n  return gulp.src('./demo', {read: false})\n    .pipe(clean());\n})\n\ngulp.task('demo:file', ['demo:clean'], function(){\n  return gulp.src(['example/**/*.html','example/README.md'])\n    .pipe(gulp.dest('demo/'))\n})\n\n//编译示例\ngulp.task('demo:webpack', ['demo:clean'], function(callback) {\n  webpack(webpack_config_demo, function (error,status) {\n    //gulp 异步任务必须明确执行 callback() 否则 gulp 将一直卡住\n    callback()\n  });\n});\n\ngulp.task('demo:build', ['demo:file', 'demo:webpack']);\n\n//部署示例到自己的测试服务器\n// gulp.task('deploy:demo', ['build:demo'], function () {\n//   deploy.log = gutil.log;\n\n//   var conn = ftp.create(deploy);\n\n//   return gulp.src('demo/**')\n//     .pipe(conn.dest(deploy_remote_path))\n// })\n\n//部署示例到 gh-pages\ngulp.task('deploy:gh-pages', ['demo:build'], function() {\n  return gulp.src('./demo/**')\n    .pipe(ghPages());\n});\n\ngulp.task(\"publish:clean\", function(){\n  return gulp.src('./dist', {read: false})\n    .pipe(clean());\n})\n\ngulp.task(\"publish:ts\", [\"publish:clean\"], function(){\n  return gulp.src('src/**/*.ts')\n    .pipe(gulp.dest('dist'));\n})\n\n//编译 js 文件\ngulp.task('publish:js', [\"publish:clean\"], function(){\n  return gulp.src('src/**/*.{js,jsx}')\n    .pipe(babel({\n        presets: [\"es2015\", \"stage-1\", \"react\"]\n    }))\n    .pipe(gulp.dest('dist'));\n})\n\n//编译 less 文件\ngulp.task('publish:less', [\"publish:clean\"], function () {\n  return gulp.src('src/**/*.less')\n    .pipe(less({\n      paths: [ path.join(__dirname, 'less', 'includes') ]\n    }))\n    .pipe(gulp.dest('dist'));\n});\n\n//发布 css 文件\ngulp.task('publish:css', [\"publish:clean\"], function(){\n  return gulp.src('src/**/*.css')\n    .pipe(gulp.dest('dist'))\n})\n\n//打包发布 npm\ngulp.task('publish', [\"publish:clean\", 'publish:ts', 'publish:js', 'publish:less']);\n\ngulp.task('demo', ['deploy:demo']);\n\ngulp.task('gh-pages', ['deploy:gh-pages']);"
  },
  {
    "path": "lib/FooterNode.js",
    "content": "'use strict';\n\nObject.defineProperty(exports, \"__esModule\", {\n  value: true\n});\n\nvar _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if (\"value\" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }();\n\nvar _react = require('react');\n\nvar _react2 = _interopRequireDefault(_react);\n\nvar _constants = require('./constants');\n\nfunction _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }\n\nfunction _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError(\"Cannot call a class as a function\"); } }\n\nfunction _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError(\"this hasn't been initialised - super() hasn't been called\"); } return call && (typeof call === \"object\" || typeof call === \"function\") ? call : self; }\n\nfunction _inherits(subClass, superClass) { if (typeof superClass !== \"function\" && superClass !== null) { throw new TypeError(\"Super expression must either be null or a function, not \" + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; }\n\nvar FooterNode = function (_PureComponent) {\n  _inherits(FooterNode, _PureComponent);\n\n  function FooterNode() {\n    _classCallCheck(this, FooterNode);\n\n    return _possibleConstructorReturn(this, (FooterNode.__proto__ || Object.getPrototypeOf(FooterNode)).apply(this, arguments));\n  }\n\n  _createClass(FooterNode, [{\n    key: 'render',\n    value: function render() {\n      var _props = this.props;\n      var loaderState = _props.loaderState;\n      var hasMore = _props.hasMore;\n\n\n      var className = 'pull-load-footer-default ' + (hasMore ? \"\" : \"nomore\");\n\n      return _react2.default.createElement(\n        'div',\n        { className: className },\n        loaderState === _constants.STATS.loading ? _react2.default.createElement('i', null) : \"\"\n      );\n    }\n  }]);\n\n  return FooterNode;\n}(_react.PureComponent);\n\nFooterNode.propTypes = {\n  loaderState: _react.PropTypes.string.isRequired,\n  hasMore: _react.PropTypes.bool.isRequired\n};\nFooterNode.defaultProps = {\n  loaderState: _constants.STATS.init,\n  hasMore: true\n};\nexports.default = FooterNode;"
  },
  {
    "path": "lib/HeadNode.js",
    "content": "'use strict';\n\nObject.defineProperty(exports, \"__esModule\", {\n  value: true\n});\n\nvar _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if (\"value\" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }();\n\nvar _react = require('react');\n\nvar _react2 = _interopRequireDefault(_react);\n\nvar _constants = require('./constants');\n\nfunction _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }\n\nfunction _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError(\"Cannot call a class as a function\"); } }\n\nfunction _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError(\"this hasn't been initialised - super() hasn't been called\"); } return call && (typeof call === \"object\" || typeof call === \"function\") ? call : self; }\n\nfunction _inherits(subClass, superClass) { if (typeof superClass !== \"function\" && superClass !== null) { throw new TypeError(\"Super expression must either be null or a function, not \" + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; }\n\nvar HeadNode = function (_PureComponent) {\n  _inherits(HeadNode, _PureComponent);\n\n  function HeadNode() {\n    _classCallCheck(this, HeadNode);\n\n    return _possibleConstructorReturn(this, (HeadNode.__proto__ || Object.getPrototypeOf(HeadNode)).apply(this, arguments));\n  }\n\n  _createClass(HeadNode, [{\n    key: 'render',\n    value: function render() {\n      var loaderState = this.props.loaderState;\n\n\n      return _react2.default.createElement(\n        'div',\n        { className: 'pull-load-head-default' },\n        _react2.default.createElement('i', null)\n      );\n    }\n  }]);\n\n  return HeadNode;\n}(_react.PureComponent);\n\nHeadNode.propTypes = {\n  loaderState: _react.PropTypes.string.isRequired\n};\nHeadNode.defaultProps = {\n  loaderState: _constants.STATS.init\n};\nexports.default = HeadNode;"
  },
  {
    "path": "lib/ReactPullLoad.js",
    "content": "'use strict';\n\nObject.defineProperty(exports, \"__esModule\", {\n  value: true\n});\n\nvar _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; };\n\nvar _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if (\"value\" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }();\n\nvar _react = require('react');\n\nvar _react2 = _interopRequireDefault(_react);\n\nvar _reactDom = require('react-dom');\n\nvar _constants = require('./constants');\n\nvar _HeadNode = require('./HeadNode');\n\nvar _HeadNode2 = _interopRequireDefault(_HeadNode);\n\nvar _FooterNode = require('./FooterNode');\n\nvar _FooterNode2 = _interopRequireDefault(_FooterNode);\n\nrequire('./ReactPullLoad.less');\n\nfunction _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }\n\nfunction _objectWithoutProperties(obj, keys) { var target = {}; for (var i in obj) { if (keys.indexOf(i) >= 0) continue; if (!Object.prototype.hasOwnProperty.call(obj, i)) continue; target[i] = obj[i]; } return target; }\n\nfunction _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError(\"Cannot call a class as a function\"); } }\n\nfunction _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError(\"this hasn't been initialised - super() hasn't been called\"); } return call && (typeof call === \"object\" || typeof call === \"function\") ? call : self; }\n\nfunction _inherits(subClass, superClass) { if (typeof superClass !== \"function\" && superClass !== null) { throw new TypeError(\"Super expression must either be null or a function, not \" + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; }\n\nfunction addEvent(obj, type, fn) {\n  if (obj.attachEvent) {\n    obj['e' + type + fn] = fn;\n    obj[type + fn] = function () {\n      obj['e' + type + fn](window.event);\n    };\n    obj.attachEvent('on' + type, obj[type + fn]);\n  } else obj.addEventListener(type, fn, false);\n}\nfunction removeEvent(obj, type, fn) {\n  if (obj.detachEvent) {\n    obj.detachEvent('on' + type, obj[type + fn]);\n    obj[type + fn] = null;\n  } else obj.removeEventListener(type, fn, false);\n}\n\nvar ReactPullLoad = function (_Component) {\n  _inherits(ReactPullLoad, _Component);\n\n  function ReactPullLoad() {\n    var _ref;\n\n    var _temp, _this, _ret;\n\n    _classCallCheck(this, ReactPullLoad);\n\n    for (var _len = arguments.length, args = Array(_len), _key = 0; _key < _len; _key++) {\n      args[_key] = arguments[_key];\n    }\n\n    return _ret = (_temp = (_this = _possibleConstructorReturn(this, (_ref = ReactPullLoad.__proto__ || Object.getPrototypeOf(ReactPullLoad)).call.apply(_ref, [this].concat(args))), _this), _this.state = {\n      pullHeight: 0\n    }, _this.getScrollTop = function () {\n      if (_this.defaultConfig.container) {\n        return _this.defaultConfig.container.scrollTop;\n      } else {\n        return 0;\n      }\n    }, _this.setScrollTop = function (value) {\n      if (_this.defaultConfig.container) {\n        var scrollH = _this.defaultConfig.container.scrollHeight;\n        if (value < 0) {\n          value = 0;\n        }\n        if (value > scrollH) {\n          value = scrollH;\n        }\n        return _this.defaultConfig.container.scrollTop = value;\n      } else {\n        return 0;\n      }\n    }, _this.easing = function (distance) {\n      // t: current time, b: begInnIng value, c: change In value, d: duration\n      var t = distance;\n      var b = 0;\n      var d = screen.availHeight; // 允许拖拽的最大距离\n      var c = d / 2.5; // 提示标签最大有效拖拽距离\n\n      return c * Math.sin(t / d * (Math.PI / 2)) + b;\n    }, _this.canRefresh = function () {\n      return [_constants.STATS.refreshing, _constants.STATS.loading].indexOf(_this.props.action) < 0;\n    }, _this.onPullDownMove = function (data) {\n      if (!_this.canRefresh()) return false;\n\n      var loaderState = void 0,\n          diff = data[0].touchMoveY - data[0].touchStartY;\n      if (diff < 0) {\n        diff = 0;\n      }\n      diff = _this.easing(diff);\n      if (diff > _this.defaultConfig.downEnough) {\n        loaderState = _constants.STATS.enough;\n      } else {\n        loaderState = _constants.STATS.pulling;\n      }\n      _this.setState({\n        pullHeight: diff\n      });\n      _this.props.handleAction(loaderState);\n    }, _this.onPullDownRefresh = function () {\n      if (!_this.canRefresh()) return false;\n\n      if (_this.props.action === _constants.STATS.pulling) {\n        _this.setState({ pullHeight: 0 });\n        _this.props.handleAction(_constants.STATS.reset);\n      } else {\n        _this.setState({\n          pullHeight: 0\n        });\n        _this.props.handleAction(_constants.STATS.refreshing);\n      }\n    }, _this.onPullUpMove = function (data) {\n      if (!_this.canRefresh()) return false;\n\n      // const { hasMore, onLoadMore} = this.props\n      // if (this.props.hasMore) {\n      _this.setState({\n        pullHeight: 0\n      });\n      _this.props.handleAction(_constants.STATS.loading);\n      // }\n    }, _this.onTouchStart = function (event) {\n      var targetEvent = event.changedTouches[0];\n      _this.startX = targetEvent.clientX;\n      _this.startY = targetEvent.clientY;\n    }, _this.onTouchMove = function (event) {\n      var scrollTop = _this.defaultConfig.container.scrollTop,\n          scrollH = _this.defaultConfig.container.scrollHeight,\n          conH = _this.defaultConfig.container === document.body ? document.documentElement.clientHeight : _this.defaultConfig.container.offsetHeight,\n          targetEvent = event.changedTouches[0],\n          curX = targetEvent.clientX,\n          curY = targetEvent.clientY,\n          diffX = curX - _this.startX,\n          diffY = curY - _this.startY;\n\n      //判断垂直移动距离是否大于5 && 横向移动距离小于纵向移动距离\n      if (Math.abs(diffY) > 5 && Math.abs(diffY) > Math.abs(diffX)) {\n        //滚动距离小于设定值 &&回调onPullDownMove 函数，并且回传位置值\n        if (diffY > 5 && scrollTop < _this.defaultConfig.offsetScrollTop) {\n          //阻止执行浏览器默认动作\n          event.preventDefault();\n          _this.onPullDownMove([{\n            touchStartY: _this.startY,\n            touchMoveY: curY\n          }]);\n        } //滚动距离距离底部小于设定值\n        else if (diffY < 0 && scrollH - scrollTop - conH < _this.defaultConfig.distanceBottom) {\n            //阻止执行浏览器默认动作\n            // event.preventDefault();\n            _this.onPullUpMove([{\n              touchStartY: _this.startY,\n              touchMoveY: curY\n            }]);\n          }\n      }\n    }, _this.onTouchEnd = function (event) {\n      var scrollTop = _this.defaultConfig.container.scrollTop,\n          targetEvent = event.changedTouches[0],\n          curX = targetEvent.clientX,\n          curY = targetEvent.clientY,\n          diffX = curX - _this.startX,\n          diffY = curY - _this.startY;\n\n      //判断垂直移动距离是否大于5 && 横向移动距离小于纵向移动距离\n      if (Math.abs(diffY) > 5 && Math.abs(diffY) > Math.abs(diffX)) {\n        if (diffY > 5 && scrollTop < _this.defaultConfig.offsetScrollTop) {\n          //回调onPullDownRefresh 函数，即满足刷新条件\n          _this.onPullDownRefresh();\n        }\n      }\n    }, _temp), _possibleConstructorReturn(_this, _ret);\n  }\n  //set props default values\n\n\n  _createClass(ReactPullLoad, [{\n    key: 'componentDidMount',\n\n\n    // container = null;\n\n    value: function componentDidMount() {\n      var _props = this.props;\n      var isBlockContainer = _props.isBlockContainer;\n      var offsetScrollTop = _props.offsetScrollTop;\n      var downEnough = _props.downEnough;\n      var distanceBottom = _props.distanceBottom;\n\n      this.defaultConfig = {\n        container: isBlockContainer ? (0, _reactDom.findDOMNode)(this) : document.body,\n        offsetScrollTop: offsetScrollTop,\n        downEnough: downEnough,\n        distanceBottom: distanceBottom\n      };\n      // console.info(\"downEnough = \", downEnough, this.defaultConfig.downEnough)\n      /*\n        As below reason handle touch event self ( widthout react defualt touch)\n        Unable to preventDefault inside passive event listener due to target being treated as passive. See https://www.chromestatus.com/features/5093566007214080\n      */\n      addEvent(this.refs.container, \"touchstart\", this.onTouchStart);\n      addEvent(this.refs.container, \"touchmove\", this.onTouchMove);\n      addEvent(this.refs.container, \"touchend\", this.onTouchEnd);\n    }\n\n    // 未考虑到 children 及其他 props 改变的情况\n    // shouldComponentUpdate(nextProps, nextState) {\n    //   if(this.props.action === nextProps.action && this.state.pullHeight === nextState.pullHeight){\n    //     //console.info(\"[ReactPullLoad] info new action is equal to old action\",this.state.pullHeight,nextState.pullHeight);\n    //     return false\n    //   } else{\n    //     return true\n    //   }\n    // }\n\n  }, {\n    key: 'componentWillUnmount',\n    value: function componentWillUnmount() {\n      removeEvent(this.refs.container, \"touchstart\", this.onTouchStart);\n      removeEvent(this.refs.container, \"touchmove\", this.onTouchMove);\n      removeEvent(this.refs.container, \"touchend\", this.onTouchEnd);\n    }\n  }, {\n    key: 'componentWillReceiveProps',\n    value: function componentWillReceiveProps(nextProps) {\n      var _this2 = this;\n\n      if (nextProps.action === _constants.STATS.refreshed) {\n        setTimeout(function () {\n          _this2.props.handleAction(_constants.STATS.reset);\n        }, 1000);\n      }\n    }\n\n    // 拖拽的缓动公式 - easeOutSine\n\n  }, {\n    key: 'render',\n    value: function render() {\n      var _props2 = this.props;\n      var children = _props2.children;\n      var action = _props2.action;\n      var handleAction = _props2.handleAction;\n      var hasMore = _props2.hasMore;\n      var className = _props2.className;\n      var offsetScrollTop = _props2.offsetScrollTop;\n      var downEnough = _props2.downEnough;\n      var distanceBottom = _props2.distanceBottom;\n      var isBlockContainer = _props2.isBlockContainer;\n      var HeadNode = _props2.HeadNode;\n      var FooterNode = _props2.FooterNode;\n\n      var other = _objectWithoutProperties(_props2, ['children', 'action', 'handleAction', 'hasMore', 'className', 'offsetScrollTop', 'downEnough', 'distanceBottom', 'isBlockContainer', 'HeadNode', 'FooterNode']);\n\n      var pullHeight = this.state.pullHeight;\n\n\n      var msgStyle = pullHeight ? {\n        WebkitTransform: 'translate3d(0, ' + pullHeight + 'px, 0)',\n        transform: 'translate3d(0, ' + pullHeight + 'px, 0)'\n      } : null;\n\n      var boxClassName = className + ' pull-load state-' + action;\n\n      return _react2.default.createElement(\n        'div',\n        _extends({}, other, {\n          className: boxClassName,\n          ref: 'container' }),\n        _react2.default.createElement(\n          'div',\n          { className: 'pull-load-body', style: msgStyle },\n          _react2.default.createElement(\n            'div',\n            { className: 'pull-load-head' },\n            _react2.default.createElement(HeadNode, { loaderState: action })\n          ),\n          children,\n          _react2.default.createElement(\n            'div',\n            { className: 'pull-load-footer' },\n            _react2.default.createElement(FooterNode, { loaderState: action, hasMore: hasMore })\n          )\n        )\n      );\n    }\n  }]);\n\n  return ReactPullLoad;\n}(_react.Component);\n\nReactPullLoad.propTypes = {\n  action: _react.PropTypes.string.isRequired, //用于同步状态\n  handleAction: _react.PropTypes.func.isRequired, //用于处理状态\n  hasMore: _react.PropTypes.bool, //是否还有更多内容可加载\n  offsetScrollTop: _react.PropTypes.number, //必须大于零，使触发刷新往下偏移，隐藏部分顶部内容\n  downEnough: _react.PropTypes.number, //下拉满足刷新的距离\n  distanceBottom: _react.PropTypes.number, //距离底部距离触发加载更多\n  isBlockContainer: _react.PropTypes.bool,\n\n  HeadNode: _react.PropTypes.any, //refresh message react dom\n  FooterNode: _react.PropTypes.any };\nReactPullLoad.defaultProps = {\n  hasMore: true,\n  offsetScrollTop: 1,\n  downEnough: 100,\n  distanceBottom: 100,\n  isBlockContainer: false,\n  className: \"\",\n  HeadNode: _HeadNode2.default, //refresh message react dom\n  FooterNode: _FooterNode2.default };\nexports.default = ReactPullLoad;"
  },
  {
    "path": "lib/ReactPullLoad.less",
    "content": "\n@transition-duration: .2s;\n\n//pull-load container\n.pull-load{\n    position: relative;\n    overflow-y: scroll;\n    -webkit-overflow-scrolling: touch;\n}\n//head load more msg and refreshing UI\n.pull-load-head{\n    position: absolute;\n    transform: translate3d(0px, -100%, 0px);\n    width: 100%;\n    .state-refreshing &,\n    .state-refreshed &{\n        position: relative;\n        transform: none;\n    }\n}\n//body container content\n.pull-load-body{\n    // transform: translate3d(0,0,0);// make over the msg-refreshed\n    position: relative;\n    .state-refreshing &{\n        // transform: translate3d(0,@height,0);\n        transition: transform @transition-duration;\n    }\n\n    .state-refreshed &{\n        // handle resolve within 1s\n        // animation: refreshed @transition-duration*5;\n    }\n\n    .state-reset &{\n        transition: transform @transition-duration;\n    }\n}\n\n\n/*\n * HeadNode default UI\n */\n@bg-dark: #EFEFF4;\n\n@height: 3rem;\n@fontSize: 12px;\n@fontColor: darken(@bg-dark, 40%);// state hint\n@btnColor: darken(@bg-dark, 60%);// load more\n\n@pullingMsg: '下拉刷新';\n@pullingEnoughMsg: '松开刷新';\n@refreshingMsg: '正在刷新...';\n@refreshedMsg: '刷新成功';\n@loadingMsg: '正在加载...';\n@btnLoadMore: '加载更多';\n@btnLoadNoMore: '没有更多';\n\n.ui-loading(){\n    display: inline-block;\n    vertical-align: middle;\n    font-size: 1.5rem;\n    width: 1em;\n    height: 1em;\n    border: 2px solid darken(@bg-dark, 30%);\n    border-top-color: #fff;\n    border-radius: 100%;\n    animation: circle .8s infinite linear;\n}\n\n.pull-load-head-default{\n    text-align: center; font-size: @fontSize; line-height: @height; color: @fontColor;\n    &:after{\n        .state-pulling &{\n            content: @pullingMsg\n        }\n\n        .state-pulling.enough &{\n            content: @pullingEnoughMsg;\n        }\n\n        .state-refreshing &{\n            content: @refreshingMsg;\n        }\n        .state-refreshed &{\n            content: @refreshedMsg;\n        }\n    }\n    .state-pulling &{\n        opacity: 1;\n\n        // arrow down icon\n        i{\n            display: inline-block;\n            font-size: 2em;\n            margin-right: .6em;\n            vertical-align: middle;\n            height: 1em;\n            border-left: 1px solid;\n            position: relative;\n            transition: transform .3s ease;\n\n            &:before,&:after{\n                content: '';\n                position: absolute;\n                font-size: .5em;\n                width: 1em;\n                bottom: 0px;\n                border-top: 1px solid;\n            }\n            &:before{\n                right: 1px;\n                transform: rotate(50deg);\n                transform-origin: right;\n            }\n            &:after{\n                left: 0px;\n                transform: rotate(-50deg);\n                transform-origin: left;\n            }\n        }\n    }\n    .state-pulling.enough &{\n        // arrow up\n        i{\n            transform: rotate(180deg);\n        }\n    }\n    .state-refreshing &{\n        i{\n            margin-right: 10px;\n            .ui-loading();\n        }\n    }\n    // 刷新成功提示消息\n    .state-refreshed &{\n        opacity: 1;\n        transition: opacity 1s;\n\n        // √ icon\n        i{\n            display: inline-block;\n            box-sizing: content-box;\n            vertical-align: middle;\n            margin-right: 10px;\n            font-size: 20px;\n            height: 1em;\n            width: 1em;\n            border: 1px solid;\n            border-radius: 100%;\n            position: relative;\n\n            &:before{\n                content: '';\n                position: absolute;\n                top: 3px;\n                left: 7px;\n                height: 11px;\n                width: 5px;\n                border: solid;\n                border-width: 0 1px 1px 0;\n                transform: rotate(40deg);\n            }\n        }\n    }\n}\n\n.pull-load-footer-default{\n    text-align: center; font-size: @fontSize; line-height: @height; color: @fontColor;\n    &:after{\n        .state-loading &{\n            content: @btnLoadMore;\n        }\n    }\n    &.nomore:after{\n        content: @btnLoadNoMore;\n    }\n    .state-loading &{\n        i{\n            margin-right: 10px;\n            .ui-loading();\n        }\n    }\n}\n// loading效果\n@keyframes circle {\n    100% { transform: rotate(360deg); }\n}"
  },
  {
    "path": "lib/constants.js",
    "content": "'use strict';\n\nObject.defineProperty(exports, \"__esModule\", {\n  value: true\n});\nvar STATS = exports.STATS = {\n  init: '',\n  pulling: 'pulling',\n  enough: 'pulling enough',\n  refreshing: 'refreshing',\n  refreshed: 'refreshed',\n  reset: 'reset',\n\n  loading: 'loading' // loading more\n};"
  },
  {
    "path": "lib/index.js",
    "content": "'use strict';\n\nObject.defineProperty(exports, \"__esModule\", {\n  value: true\n});\nexports.default = exports.STATS = undefined;\n\nvar _constants = require('./constants');\n\nObject.defineProperty(exports, 'STATS', {\n  enumerable: true,\n  get: function get() {\n    return _constants.STATS;\n  }\n});\n\nvar _ReactPullLoad = require('./ReactPullLoad');\n\nvar _ReactPullLoad2 = _interopRequireDefault(_ReactPullLoad);\n\nfunction _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }\n\nexports.default = _ReactPullLoad2.default;"
  },
  {
    "path": "package.json",
    "content": "{\n  \"name\": \"react-pullload\",\n  \"version\": \"1.2.0\",\n  \"description\": \"React compopnent pull down refresh and pull up load more\",\n  \"main\": \"./dist/index.js\",\n  \"scripts\": {\n    \"start\": \"webpack-dev-server --config webpack.config.js\",\n    \"example\": \"rm -rf ./demo/* & NODE_ENV=development webpack --config webpack.config.example.js\",\n    \"test\": \"echo \\\"Error: no test specified\\\" && exit 1\"\n  },\n  \"repository\": {\n    \"type\": \"git\",\n    \"url\": \"git+https://github.com/react-ld/react-pullLoad.git\"\n  },\n  \"keywords\": [\n    \"react\",\n    \"refresh\",\n    \"component\",\n    \"loadmore\"\n  ],\n  \"author\": \"lidianhao123\",\n  \"license\": \"MIT\",\n  \"bugs\": {\n    \"url\": \"https://github.com/react-ld/react-pullLoad/issues\"\n  },\n  \"files\": [\n    \"dist\",\n    \"example\",\n    \"src\"\n  ],\n  \"homepage\": \"https://github.com/react-ld/react-pullLoad#readme\",\n  \"devDependencies\": {\n    \"autoprefixer\": \"^6.5.1\",\n    \"babel-cli\": \"^6.16.0\",\n    \"babel-core\": \"^6.17.0\",\n    \"babel-loader\": \"^6.2.5\",\n    \"babel-polyfill\": \"^6.16.0\",\n    \"babel-preset-es2015\": \"^6.16.0\",\n    \"babel-preset-react\": \"^6.16.0\",\n    \"babel-preset-stage-1\": \"^6.16.0\",\n    \"css-loader\": \"^0.25.0\",\n    \"gulp\": \"^3.9.1\",\n    \"gulp-babel\": \"^7.0.0\",\n    \"gulp-clean\": \"^0.3.2\",\n    \"gulp-gh-pages\": \"git@github.com:tekd/gulp-gh-pages.git#update-dependency\",\n    \"gulp-less\": \"^3.3.2\",\n    \"gulp-util\": \"^3.0.8\",\n    \"html-webpack-plugin\": \"^2.22.0\",\n    \"less\": \"^2.7.1\",\n    \"less-loader\": \"^2.2.3\",\n    \"postcss\": \"^5.2.4\",\n    \"postcss-loader\": \"^0.13.0\",\n    \"react\": \"^16.0.0\",\n    \"react-dom\": \"^16.0.0\",\n    \"react-hot-loader\": \"^3.0.0-beta.6\",\n    \"style-loader\": \"^0.13.1\",\n    \"webpack\": \"^2.6.1\",\n    \"webpack-dev-server\": \"^2.4.5\"\n  },\n  \"dependencies\": {\n    \"prop-types\": \"^15.6.0\"\n  }\n}\n"
  },
  {
    "path": "postcss.config.js",
    "content": "module.exports = ({ file, options, env }) => ({\n  // parser: file.extname === '.sss' ? 'sugarss' : false,\n  // plugins: {\n  //   'postcss-import': { root: file.dirname },\n  //   'postcss-cssnext': options.cssnext ? options.cssnext : false,\n  //   'autoprefixer': env == 'production' ? options.autoprefixer : false,\n  //   'cssnano': env === 'production' ? options.cssnano : false\n  // }\n  plugins: [ require('autoprefixer')({ browsers: [\"Android >= 4\", \"iOS >= 7\"]}) ]\n})"
  },
  {
    "path": "src/FooterNode.jsx",
    "content": "\nimport React, { PureComponent } from 'react'\nimport PropTypes from 'prop-types';\nimport { STATS } from './constants'\n\nexport default class FooterNode extends PureComponent{\n\n  static propTypes = {\n    loaderState: PropTypes.string.isRequired,\n    hasMore: PropTypes.bool.isRequired\n  };\n\n  static defaultProps = {\n    loaderState: STATS.init,\n    hasMore: true\n  };\n\n  render(){\n    const {\n      loaderState,\n      hasMore\n    } = this.props\n\n    let className = `pull-load-footer-default ${hasMore? \"\" : \"nomore\"}`\n\n    return(\n      <div className={className}>\n        {\n          loaderState === STATS.loading ? <i/> : \"\"\n        }\n      </div>\n    )\n  }\n}"
  },
  {
    "path": "src/HeadNode.jsx",
    "content": "\nimport React, { PureComponent } from 'react'\nimport PropTypes from 'prop-types';\nimport { STATS } from './constants'\n\nexport default class HeadNode extends PureComponent{\n\n  static propTypes = {\n    loaderState: PropTypes.string.isRequired,\n  };\n\n  static defaultProps = {\n    loaderState: STATS.init,\n  };\n\n  render(){\n    const {\n      loaderState\n    } = this.props\n\n    return(\n      <div className=\"pull-load-head-default\">\n        <i/>\n      </div>\n    )\n  }\n}"
  },
  {
    "path": "src/ReactPullLoad.jsx",
    "content": "\nimport React, { Component } from 'react'\nimport PropTypes from 'prop-types';\nimport { findDOMNode } from 'react-dom'\nimport { STATS } from './constants'\nimport HeadNode from './HeadNode'\nimport FooterNode from './FooterNode'\n\nfunction addEvent(obj, type, fn) {\n  if (obj.attachEvent) {\n    obj['e' + type + fn] = fn;\n    obj[type + fn] = function () { obj['e' + type + fn](window.event); }\n    obj.attachEvent('on' + type, obj[type + fn]);\n  } else\n    obj.addEventListener(type, fn, false, {passive: false});\n}\nfunction removeEvent(obj, type, fn) {\n  if (obj.detachEvent) {\n    obj.detachEvent('on' + type, obj[type + fn]);\n    obj[type + fn] = null;\n  } else\n    obj.removeEventListener(type, fn, false);\n}\n\nexport default class ReactPullLoad extends Component {\n  static propTypes = {\n    action: PropTypes.string.isRequired,     //用于同步状态\n    handleAction: PropTypes.func.isRequired, //用于处理状态\n    hasMore: PropTypes.bool,          //是否还有更多内容可加载\n    offsetScrollTop: PropTypes.number,//必须大于零，使触发刷新往下偏移，隐藏部分顶部内容\n    downEnough: PropTypes.number,     //下拉满足刷新的距离\n    distanceBottom: PropTypes.number, //距离底部距离触发加载更多\n    isBlockContainer: PropTypes.bool,\n\n    HeadNode: PropTypes.any,     //refresh message react dom\n    FooterNode: PropTypes.any, //refresh loading react dom\n  };\n  //set props default values\n  static defaultProps = {\n    hasMore: true,\n    offsetScrollTop: 1,\n    downEnough: 100,\n    distanceBottom: 100,\n    isBlockContainer: false,\n    className: \"\",\n    HeadNode: HeadNode,     //refresh message react dom\n    FooterNode: FooterNode, //refresh loading react dom\n  };\n\n  state = {\n    pullHeight: 0\n  };\n\n  // container = null;\n\n  componentDidMount() {\n    const {isBlockContainer, offsetScrollTop, downEnough, distanceBottom} = this.props\n    this.defaultConfig = {\n      container: isBlockContainer ? findDOMNode(this) : document.body,\n      offsetScrollTop: offsetScrollTop,\n      downEnough: downEnough,\n      distanceBottom: distanceBottom\n    };\n    // console.info(\"downEnough = \", downEnough, this.defaultConfig.downEnough)\n    /*\n      As below reason handle touch event self ( widthout react defualt touch)\n      Unable to preventDefault inside passive event listener due to target being treated as passive. See https://www.chromestatus.com/features/5093566007214080\n    */\n    addEvent(this.refs.container, \"touchstart\", this.onTouchStart)\n    addEvent(this.refs.container, \"touchmove\", this.onTouchMove)\n    addEvent(this.refs.container, \"touchend\", this.onTouchEnd)\n  }\n\n  // 未考虑到 children 及其他 props 改变的情况\n  // shouldComponentUpdate(nextProps, nextState) {\n  //   if(this.props.action === nextProps.action && this.state.pullHeight === nextState.pullHeight){\n  //     //console.info(\"[ReactPullLoad] info new action is equal to old action\",this.state.pullHeight,nextState.pullHeight);\n  //     return false\n  //   } else{\n  //     return true\n  //   }\n  // }\n\n  componentWillUnmount() {\n    removeEvent(this.refs.container, \"touchstart\", this.onTouchStart)\n    removeEvent(this.refs.container, \"touchmove\", this.onTouchMove)\n    removeEvent(this.refs.container, \"touchend\", this.onTouchEnd)\n  }\n\n  componentWillReceiveProps(nextProps) {\n    if(nextProps.action === STATS.refreshed){\n      setTimeout(()=>{\n        this.props.handleAction(STATS.reset)\n      },1000)\n    }\n  }\n\n  getScrollTop = ()=>{\n    if(this.defaultConfig.container){\n      if(this.defaultConfig.container === document.body){\n        return document.documentElement.scrollTop || document.body.scrollTop;\n      }\n      return this.defaultConfig.container.scrollTop;\n    } else{\n      return 0;\n    }\n  }\n\n  setScrollTop = (value)=>{\n    if(this.defaultConfig.container){\n      let scrollH = this.defaultConfig.container.scrollHeight;\n      if(value < 0){ value = 0}\n      if(value > scrollH){ value = scrollH}\n      return this.defaultConfig.container.scrollTop = value;\n    } else{\n      return 0;\n    }\n  }\n\n  // 拖拽的缓动公式 - easeOutSine\n  easing = (distance) => {\n    // t: current time, b: begInnIng value, c: change In value, d: duration\n    var t = distance;\n    var b = 0;\n    var d = screen.availHeight; // 允许拖拽的最大距离\n    var c = d / 2.5; // 提示标签最大有效拖拽距离\n\n    return c * Math.sin(t / d * (Math.PI / 2)) + b;\n  }\n  \n  canRefresh = () => {\n    return [STATS.refreshing, STATS.loading].indexOf(this.props.action) < 0;\n  }\n\n  onPullDownMove = (data)  => {\n    if(!this.canRefresh())return false;\n\n    let loaderState, diff = data[0].touchMoveY - data[0].touchStartY;\n    if (diff < 0) {\n      diff = 0;\n    }\n    diff = this.easing(diff);\n    if (diff > this.defaultConfig.downEnough) {\n      loaderState = STATS.enough\n    } else {\n      loaderState = STATS.pulling\n    }\n    this.setState({\n      pullHeight: diff,\n    })\n    this.props.handleAction(loaderState)\n  }\n\n  onPullDownRefresh = () => {\n    if(!this.canRefresh())return false;\n\n    if (this.props.action === STATS.pulling) {\n      this.setState({pullHeight: 0})\n      this.props.handleAction(STATS.reset)\n    } else {\n      this.setState({\n        pullHeight: 0,\n      })\n      this.props.handleAction(STATS.refreshing)\n    }\n  }\n\n  onPullUpMove = (data) => {\n    if(!this.canRefresh())return false;\n\n    // const { hasMore, onLoadMore} = this.props\n    // if (this.props.hasMore) {\n    this.setState({\n      pullHeight: 0,\n    })\n    this.props.handleAction(STATS.loading)\n    // }\n  }\n\n  onTouchStart = (event) => {\n    var targetEvent = event.changedTouches[0];\n    this.startX = targetEvent.clientX;\n    this.startY = targetEvent.clientY;\n  }\n\n  onTouchMove = (event) => {\n    let scrollTop = this.getScrollTop(),\n      scrollH = this.defaultConfig.container.scrollHeight,\n      conH = this.defaultConfig.container === document.body ? document.documentElement.clientHeight : this.defaultConfig.container.offsetHeight,\n      targetEvent = event.changedTouches[0],\n      curX = targetEvent.clientX,\n      curY = targetEvent.clientY,\n      diffX = curX - this.startX,\n      diffY = curY - this.startY;\n\n    //判断垂直移动距离是否大于5 && 横向移动距离小于纵向移动距离\n    if (Math.abs(diffY) > 5 && Math.abs(diffY) > Math.abs(diffX)) {\n      //滚动距离小于设定值 &&回调onPullDownMove 函数，并且回传位置值\n      if (diffY > 5 && scrollTop < this.defaultConfig.offsetScrollTop) {\n        //阻止执行浏览器默认动作\n        event.preventDefault();\n        this.onPullDownMove([{\n          touchStartY: this.startY,\n          touchMoveY: curY\n        }]);\n      } //滚动距离距离底部小于设定值\n      else if (diffY < 0 && (scrollH - scrollTop - conH) < this.defaultConfig.distanceBottom) {\n        //阻止执行浏览器默认动作\n        // event.preventDefault();\n        this.onPullUpMove([{\n          touchStartY: this.startY,\n          touchMoveY: curY\n        }]);\n      }\n    }\n  }\n\n  onTouchEnd = (event) => {\n    let scrollTop = this.getScrollTop(),\n      targetEvent = event.changedTouches[0],\n      curX = targetEvent.clientX,\n      curY = targetEvent.clientY,\n      diffX = curX - this.startX,\n      diffY = curY - this.startY;\n\n    //判断垂直移动距离是否大于5 && 横向移动距离小于纵向移动距离\n    if (Math.abs(diffY) > 5 && Math.abs(diffY) > Math.abs(diffX)) {\n      if (diffY > 5 && scrollTop < this.defaultConfig.offsetScrollTop) {\n        //回调onPullDownRefresh 函数，即满足刷新条件\n        this.onPullDownRefresh();\n      }\n    }\n  }\n\n  render() {\n    const {\n        children,\n        action,\n        handleAction,\n        hasMore,\n        className,\n        offsetScrollTop,\n        downEnough,\n        distanceBottom,\n        isBlockContainer,\n        HeadNode,\n        FooterNode,\n        ...other\n    } = this.props\n\n    const { pullHeight } = this.state\n\n    const msgStyle = pullHeight ? {\n      WebkitTransform: `translate3d(0, ${pullHeight}px, 0)`,\n      transform: `translate3d(0, ${pullHeight}px, 0)`\n    } : null;\n\n    const boxClassName = `${className} pull-load state-${action}`;\n\n    return (\n      <div {...other}\n        className={boxClassName}\n        ref=\"container\">\n        <div className=\"pull-load-body\" style={msgStyle}>\n          <div className=\"pull-load-head\">\n            <HeadNode loaderState={action}/>\n          </div>\n          { children }\n          <div className=\"pull-load-footer\">\n            <FooterNode loaderState={action} hasMore={hasMore}/>\n          </div>\n        </div>\n      </div>\n    )\n  }\n}\n"
  },
  {
    "path": "src/ReactPullLoad.less",
    "content": "\n@transition-duration: .2s;\n\n//pull-load container\n.pull-load{\n    position: relative;\n    overflow-y: scroll;\n    -webkit-overflow-scrolling: touch;\n}\n//head load more msg and refreshing UI\n.pull-load-head{\n    position: absolute;\n    transform: translate3d(0px, -100%, 0px);\n    width: 100%;\n    .state-refreshing &,\n    .state-refreshed &{\n        position: relative;\n        transform: none;\n    }\n}\n//body container content\n.pull-load-body{\n    // transform: translate3d(0,0,0);// make over the msg-refreshed\n    position: relative;\n    .state-refreshing &{\n        // transform: translate3d(0,@height,0);\n        transition: transform @transition-duration;\n    }\n\n    .state-refreshed &{\n        // handle resolve within 1s\n        // animation: refreshed @transition-duration*5;\n    }\n\n    .state-reset &{\n        transition: transform @transition-duration;\n    }\n}\n\n\n/*\n * HeadNode default UI\n */\n@bg-dark: #EFEFF4;\n\n@height: 3rem;\n@fontSize: 12px;\n@fontColor: darken(@bg-dark, 40%);// state hint\n@btnColor: darken(@bg-dark, 60%);// load more\n\n@pullingMsg: '下拉刷新';\n@pullingEnoughMsg: '松开刷新';\n@refreshingMsg: '正在刷新...';\n@refreshedMsg: '刷新成功';\n@loadingMsg: '正在加载...';\n@btnLoadMore: '加载更多';\n@btnLoadNoMore: '没有更多';\n\n.ui-loading(){\n    display: inline-block;\n    vertical-align: middle;\n    font-size: 1.5rem;\n    width: 1em;\n    height: 1em;\n    border: 2px solid darken(@bg-dark, 30%);\n    border-top-color: #fff;\n    border-radius: 100%;\n    animation: circle .8s infinite linear;\n}\n\n.pull-load-head-default{\n    text-align: center; font-size: @fontSize; line-height: @height; color: @fontColor;\n    &:after{\n        .state-pulling &{\n            content: @pullingMsg\n        }\n\n        .state-pulling.enough &{\n            content: @pullingEnoughMsg;\n        }\n\n        .state-refreshing &{\n            content: @refreshingMsg;\n        }\n        .state-refreshed &{\n            content: @refreshedMsg;\n        }\n    }\n    .state-pulling &{\n        opacity: 1;\n\n        // arrow down icon\n        i{\n            display: inline-block;\n            font-size: 2em;\n            margin-right: .6em;\n            vertical-align: middle;\n            height: 1em;\n            border-left: 1px solid;\n            position: relative;\n            transition: transform .3s ease;\n\n            &:before,&:after{\n                content: '';\n                position: absolute;\n                font-size: .5em;\n                width: 1em;\n                bottom: 0px;\n                border-top: 1px solid;\n            }\n            &:before{\n                right: 1px;\n                transform: rotate(50deg);\n                transform-origin: right;\n            }\n            &:after{\n                left: 0px;\n                transform: rotate(-50deg);\n                transform-origin: left;\n            }\n        }\n    }\n    .state-pulling.enough &{\n        // arrow up\n        i{\n            transform: rotate(180deg);\n        }\n    }\n    .state-refreshing &{\n        i{\n            margin-right: 10px;\n            .ui-loading();\n        }\n    }\n    // 刷新成功提示消息\n    .state-refreshed &{\n        opacity: 1;\n        transition: opacity 1s;\n\n        // √ icon\n        i{\n            display: inline-block;\n            box-sizing: content-box;\n            vertical-align: middle;\n            margin-right: 10px;\n            font-size: 20px;\n            height: 1em;\n            width: 1em;\n            border: 1px solid;\n            border-radius: 100%;\n            position: relative;\n\n            &:before{\n                content: '';\n                position: absolute;\n                top: 3px;\n                left: 7px;\n                height: 11px;\n                width: 5px;\n                border: solid;\n                border-width: 0 1px 1px 0;\n                transform: rotate(40deg);\n            }\n        }\n    }\n}\n\n.pull-load-footer-default{\n    text-align: center; font-size: @fontSize; line-height: @height; color: @fontColor;\n    &:after{\n        .state-loading &{\n            content: @btnLoadMore;\n        }\n    }\n    &.nomore:after{\n        content: @btnLoadNoMore;\n    }\n    .state-loading &{\n        i{\n            margin-right: 10px;\n            .ui-loading();\n        }\n    }\n}\n// loading效果\n@keyframes circle {\n    100% { transform: rotate(360deg); }\n}"
  },
  {
    "path": "src/constants.js",
    "content": "\nexport const STATS = {\n  init: '',\n  pulling: 'pulling',\n  enough: 'pulling enough',\n  refreshing: 'refreshing',\n  refreshed: 'refreshed',\n  reset: 'reset',\n\n  loading: 'loading' // loading more\n};"
  },
  {
    "path": "src/index.d.ts",
    "content": "import * as React from \"react\";\ndeclare enum STATS {\n  init = \"\",\n  pulling = \"pulling\",\n  enough = \"pulling enough\",\n  refreshing = \"refreshing\",\n  refreshed = \"refreshed\",\n  reset = \"reset\",\n\n  loading = \"loading\" // loading more\n}\n\nexport interface PullLoadProps {\n  action: STATS; //用于同步状态\n  handleAction: (action: STATS) => void; //用于处理状态\n  hasMore: boolean; //是否还有更多内容可加载\n  offsetScrollTop?: number; //必须大于零，使触发刷新往下偏移，隐藏部分顶部内容\n  downEnough?: number; //下拉满足刷新的距离\n  distanceBottom?: number; //距离底部距离触发加载更多\n  isBlockContainer?: boolean;\n\n  HeadNode?: React.ReactNode | string; //refresh message react dom\n  FooterNode?: React.ReactNode | string; //refresh loading react dom\n  children: React.ReactChild; // 子组件\n}\nexport default class ReactPullLoad extends React.Component<\n  PullLoadProps,\n  any\n> {}\n"
  },
  {
    "path": "src/index.js",
    "content": "\n// import { STATS as _STATS } from 'constants'\n// export const STATS = _STATS\n// export default ReactPullLoad\nexport { STATS } from './constants'\nexport default from './ReactPullLoad'"
  },
  {
    "path": "webpack.config.example.js",
    "content": "var path = require(\"path\");\nvar webpack = require(\"webpack\");\nvar HtmlWebpackPlugin = require(\"html-webpack-plugin\");\n\nmodule.exports = {\n  context: path.resolve(__dirname, \"example\"), // string（绝对路径！）\n  devtool: \"eval\",\n  cache: true,\n  entry: {\n    bundle1: [\"babel-polyfill\", \"./App1.jsx\"],\n    bundle2: [\"babel-polyfill\", \"./App2.jsx\"],\n    bundle3: [\"babel-polyfill\", \"./App3.jsx\"],\n    bundle4: [\"babel-polyfill\", \"./App4.jsx\"]\n  },\n  output: {\n    path: path.join(__dirname, \"demo/\"),\n    filename: \"[name].js\"\n  },\n  plugins: [\n    // new webpack.optimize.OccurenceOrderPlugin(),\n    new webpack.DefinePlugin({\n      \"process.env\": {\n        NODE_ENV: JSON.stringify(\"production\")\n      }\n    }),\n    new webpack.NamedModulesPlugin(),\n    // 当模块热替换(HMR)时在浏览器控制台输出对用户更友好的模块名字信息\n    new webpack.optimize.UglifyJsPlugin({\n      sourceMap: true,\n      compress: {\n        warnings: true\n      }\n    })\n    // new HtmlWebpackPlugin({ template: 'index.html' })\n  ],\n  resolve: {\n    extensions: [\".js\", \".jsx\"],\n    modules: [\"node_modules\", path.resolve(__dirname, \"src\")]\n  },\n\n  module: {\n    rules: [\n      {\n        test: /\\.(js|jsx)$/,\n        loader: \"babel-loader\",\n        exclude: /node_modules/,\n        include: __dirname,\n        options: {\n          presets: [[\"es2015\", { modules: false }], \"stage-1\", \"react\"]\n        }\n      },\n      {\n        test: /\\.css$/,\n        use: [\n          \"style-loader\",\n          \"css-loader\",\n          { loader: \"postcss-loader\", options: { config: { path: \"./postcss.config.js\" } } }\n        ]\n      },\n      {\n        test: /\\.less/,\n        use: [\n          \"style-loader\",\n          \"css-loader\",\n          { loader: \"postcss-loader\", options: { config: { path: \"./postcss.config.js\" } } },\n          \"less-loader\"\n        ]\n      },\n      {\n        test: /\\.(gif|jpg|png|woff|svg|eot|ttf)$/,\n        use: [{ loader: \"file-loader\" }]\n      }\n    ]\n  }\n};\n"
  },
  {
    "path": "webpack.config.js",
    "content": "var webpack = require(\"webpack\");\nvar HtmlWebpackPlugin = require(\"html-webpack-plugin\");\nvar path = require(\"path\");\nvar port = 3010;\nvar demoNum = 3;\n\nmodule.exports = {\n  context: path.resolve(__dirname, \"example\"), // string（绝对路径！）\n  devtool: \"eval\",\n  cache: true,\n  entry: [\n    \"react-hot-loader/patch\",\n    // 开启 React 代码的模块热替换(HMR)\n    \"webpack-dev-server/client?http://0.0.0.0:\" + port,\n    \"webpack/hot/only-dev-server\",\n    \"./App\"+demoNum+\".jsx\"\n  ],\n  plugins: [\n    new webpack.HotModuleReplacementPlugin(),\n    new webpack.NamedModulesPlugin(),\n    // 当模块热替换(HMR)时在浏览器控制台输出对用户更友好的模块名字信息\n    new webpack.optimize.UglifyJsPlugin({\n      sourceMap: true,\n      compress: {\n        warnings: true\n      }\n    }),\n    new HtmlWebpackPlugin({\n      title: \"Custom template\",\n      template: \"./index\"+demoNum+\".html\", // Load a custom template (ejs by default see the FAQ for details)\n      hash: true,\n      filename: \"./index.html\"\n    })\n  ],\n  resolve: {\n    modules: [\"node_modules\", path.resolve(__dirname, \"src\")],\n    extensions: [\".js\", \".jsx\"]\n  },\n  devServer: {\n    hot: true,\n    // 开启服务器的模块热替换(HMR)\n    host: \"0.0.0.0\",\n    port: port\n  },\n  module: {\n    rules: [\n      {\n        test: /\\.(js|jsx)$/,\n        loader: \"babel-loader\",\n        exclude: /node_modules/,\n        include: __dirname,\n        options: {\n          presets: [[\"es2015\", { modules: false }], \"stage-1\", \"react\"],\n          plugins: [\n            \"react-hot-loader/babel\"\n            // 开启 React 代码的模块热替换(HMR)\n          ]\n        }\n      },\n      {\n        test: /\\.css$/,\n        use: [\n          \"style-loader\",\n          \"css-loader\",\n          { loader: \"postcss-loader\", options: { config: { path: \"./postcss.config.js\" } } }\n        ]\n      },\n      {\n        test: /\\.less/,\n        use: [\n          \"style-loader\",\n          \"css-loader\",\n          { loader: \"postcss-loader\", options: { config: { path: \"./postcss.config.js\" } } },\n          \"less-loader\"\n        ]\n      },\n      {\n        test: /\\.(gif|jpg|png|woff|svg|eot|ttf)$/,\n        use: [{ loader: \"file-loader\" }]\n      }\n    ]\n  }\n};\n"
  }
]