├── .vscode └── settings.json ├── .babelrc ├── gh-deploy.sh ├── .prettierrc ├── CHANGELOG.md ├── tsconfig.json ├── demo ├── index.html └── src │ ├── demo.less │ └── entry.tsx ├── site ├── index.html └── index.js ├── webpack.config.prod.js ├── LICENSE ├── .gitignore ├── webpack.config.dev.js ├── package.json ├── dist ├── index.d.ts ├── index.js.map └── index.js ├── README.md └── src └── index.tsx /.vscode/settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "editor.tabSize": 2 3 | } -------------------------------------------------------------------------------- /.babelrc: -------------------------------------------------------------------------------- 1 | { 2 | "presets": ["@babel/preset-env", "@babel/react"] 3 | } -------------------------------------------------------------------------------- /gh-deploy.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | git push origin `git subtree split --prefix site master`:gh-pages --force -------------------------------------------------------------------------------- /.prettierrc: -------------------------------------------------------------------------------- 1 | { 2 | "printWidth": 100, 3 | "tabWidth": 2, 4 | "useTabs": false, 5 | "semi": true, 6 | "singleQuote": true, 7 | "trailingComma": "es5", 8 | "bracketSpacing": true, 9 | "jsxBracketSameLine": true, 10 | "arrowParens": "always" 11 | } -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | ## [0.3.4] - 2019-04-12 2 | 3 | - Fixed window resizing messing up scroll bar. 4 | 5 | ## [0.3.3] - 2019-04-09 6 | 7 | Fixed 8 | - Hanlder automatically hide too early when clicking happens 9 | 10 | Added 11 | - TypeScript typings 12 | - `start` Prop now accept specific numbers 13 | - Add `setPosition` method to update the scrolling position manually -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "baseUrl": "./src", 4 | "outDir": "./dist/", 5 | "sourceMap": true, 6 | "noImplicitAny": true, 7 | "module": "commonjs", 8 | "target": "es5", 9 | "jsx": "react", 10 | "experimentalDecorators": true, 11 | "noUnusedLocals": true, 12 | "noUnusedParameters": true, 13 | "moduleResolution": "node", 14 | "lib": ["es2015", "dom"], 15 | "declaration": true 16 | }, 17 | "files": [ 18 | "src/index.tsx" 19 | ], 20 | "exclude": ["node_modules", "**/*.spec.ts", "lib", "build", "dist"] 21 | } -------------------------------------------------------------------------------- /demo/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | React Free Scrollbar 7 | 8 | 9 | 10 | 11 | 12 | 13 |
14 | 15 | 16 | 17 | -------------------------------------------------------------------------------- /site/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | React Free Scrollbar 7 | 8 | 9 | 10 | 11 | 12 | 13 |
14 | 15 | 16 | 17 | -------------------------------------------------------------------------------- /webpack.config.prod.js: -------------------------------------------------------------------------------- 1 | /* global __dirname */ 2 | const webpack = require('webpack'); 3 | 4 | module.exports = { 5 | entry: ['./demo/src/entry.tsx'], 6 | output: { 7 | path: __dirname + '/site', 8 | filename: 'index.js', 9 | }, 10 | module: { 11 | rules: [ 12 | { 13 | test: /\.tsx?$/, 14 | use: 'ts-loader', 15 | exclude: /node_modules/, 16 | }, 17 | { 18 | test: /\.jsx$/, 19 | loaders: ['babel-loader'], 20 | exclude: /node_modules/, 21 | }, 22 | { 23 | test: /\.js$/, 24 | exclude: /node_modules/, 25 | loader: 'babel-loader', 26 | }, 27 | { 28 | test: /\.less$/, 29 | loader: 'style-loader!css-loader!less-loader', 30 | }, 31 | { 32 | test: /\.(css)$/, 33 | loader: 'style-loader!css-loader', 34 | }, 35 | { 36 | test: /\.(png|jpg|jpeg|svg)$/, 37 | loader: 'file-loader', 38 | }, 39 | ], 40 | }, 41 | plugins: [new webpack.NoEmitOnErrorsPlugin()], 42 | }; 43 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2015-2018 Hao Liu http://liuhao.im 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | #### joe made this: https://goel.io/joe 2 | 3 | #####=== Node ===##### 4 | 5 | # Logs 6 | logs 7 | *.log 8 | 9 | # Runtime data 10 | pids 11 | *.pid 12 | *.seed 13 | 14 | # Directory for instrumented libs generated by jscoverage/JSCover 15 | lib-cov 16 | 17 | # Coverage directory used by tools like istanbul 18 | coverage 19 | 20 | # Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files) 21 | .grunt 22 | 23 | # node-waf configuration 24 | .lock-wscript 25 | 26 | # Compiled binary addons (http://nodejs.org/api/addons.html) 27 | build/Release 28 | 29 | # Dependency directory 30 | # https://www.npmjs.org/doc/misc/npm-faq.html#should-i-check-my-node_modules-folder-into-git- 31 | node_modules 32 | 33 | # Debug log from npm 34 | npm-debug.log 35 | 36 | #### joe made this: https://goel.io/joe 37 | 38 | #####=== OSX ===##### 39 | .DS_Store 40 | .AppleDouble 41 | .LSOverride 42 | 43 | # Icon must end with two \r 44 | Icon 45 | 46 | # Thumbnails 47 | ._* 48 | 49 | # Files that might appear on external disk 50 | .Spotlight-V100 51 | .Trashes 52 | 53 | # Directories potentially created on remote AFP share 54 | .AppleDB 55 | .AppleDesktop 56 | Network Trash Folder 57 | Temporary Items 58 | .apdisk 59 | 60 | # Dev 61 | dev.js -------------------------------------------------------------------------------- /webpack.config.dev.js: -------------------------------------------------------------------------------- 1 | /* global __dirname */ 2 | const webpack = require('webpack'); 3 | const path = require('path'); 4 | 5 | module.exports = { 6 | mode: 'development', 7 | entry: ['./demo/src/entry.tsx'], 8 | devtool: 'inline-source-map', 9 | devServer: { 10 | contentBase: path.join(__dirname, 'demo'), 11 | compress: true, 12 | port: 8080, 13 | }, 14 | output: { 15 | filename: 'dev.js', 16 | path: path.resolve(__dirname, 'demo'), 17 | }, 18 | module: { 19 | rules: [ 20 | { 21 | test: /\.tsx?$/, 22 | use: 'ts-loader', 23 | exclude: /node_modules/, 24 | }, 25 | { 26 | test: /\.jsx$/, 27 | loaders: ['babel-loader'], 28 | exclude: /node_modules/, 29 | }, 30 | { 31 | test: /\.js$/, 32 | exclude: /node_modules/, 33 | loader: 'babel-loader', 34 | }, 35 | { 36 | test: /\.less$/, 37 | loader: 'style-loader!css-loader!less-loader', 38 | }, 39 | { 40 | test: /\.(css)$/, 41 | loader: 'style-loader!css-loader', 42 | }, 43 | { 44 | test: /\.(png|jpg|jpeg|svg)$/, 45 | loader: 'file-loader', 46 | }, 47 | ], 48 | }, 49 | plugins: [new webpack.HotModuleReplacementPlugin(), new webpack.NoEmitOnErrorsPlugin()], 50 | }; 51 | -------------------------------------------------------------------------------- /demo/src/demo.less: -------------------------------------------------------------------------------- 1 | .footer { 2 | color: #D4D4D4; 3 | margin-bottom: 80px; 4 | padding-top: 20px; 5 | } 6 | 7 | .github-corner { 8 | position: fixed; 9 | top: 0; 10 | right: 0; 11 | color: #FAFAFA; 12 | } 13 | 14 | .inner { 15 | padding: 10px; 16 | } 17 | 18 | .quick-start { 19 | width: 100%; 20 | height: 300px; 21 | border: 2px solid #E7E9EC; 22 | } 23 | 24 | .horizontal { 25 | width: 100%; 26 | height: 300px; 27 | border: 2px solid #E7E9EC; 28 | } 29 | 30 | .auto-hide { 31 | width: 100%; 32 | height: 300px; 33 | border: 2px solid #E7E9EC; 34 | .inner { 35 | width: 1200px; 36 | } 37 | } 38 | 39 | .custom-styles { 40 | width: 100%; 41 | height: 300px; 42 | border: 2px solid #E7E9EC; 43 | } 44 | 45 | .example-vertical-track { 46 | background-color: transparent; 47 | width: 10px; 48 | transition: opacity 0.3s; 49 | } 50 | 51 | .example-horizontal-track { 52 | background-color: transparent; 53 | height: 10px; 54 | transition: opacity 0.3s; 55 | } 56 | 57 | .example-vertical-handler { 58 | width: 8px; 59 | right: 1px; 60 | border-radius: 4px; 61 | background-color: rgba(0, 0, 0, 0.5); 62 | transition: opacity 0.3s; 63 | &:hover { 64 | background-color: rgba(0, 0, 0, 0.8); 65 | } 66 | } 67 | 68 | .example-horizontal-handler { 69 | height: 8px; 70 | bottom: 1px; 71 | border-radius: 4px; 72 | background-color: rgba(0, 0, 0, 0.5); 73 | transition: opacity 0.3s; 74 | &:hover { 75 | background-color: rgba(0, 0, 0, 0.8); 76 | } 77 | } 78 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "react-free-scrollbar", 3 | "version": "0.3.4", 4 | "description": "A react module for creating customizable scroll area", 5 | "main": "dist/index.js", 6 | "types": "dist/index.d.ts", 7 | "scripts": { 8 | "dev": "webpack-dev-server --env=dev --config webpack.config.dev.js", 9 | "build-demo": "webpack --mode=production --env=prod --config webpack.config.prod.js --progress --colors", 10 | "dist": "tsc" 11 | }, 12 | "repository": { 13 | "type": "git", 14 | "url": "https://github.com/fuermosi777/react-free-scrollbar.git" 15 | }, 16 | "keywords": [ 17 | "react" 18 | ], 19 | "author": "Hao Liu (http://liuhao.im)", 20 | "license": "MIT", 21 | "bugs": { 22 | "url": "https://github.com/fuermosi777/react-free-scrollbar/issues" 23 | }, 24 | "homepage": "https://github.com/fuermosi777/react-free-scrollbar#readme", 25 | "devDependencies": { 26 | "@babel/core": "^7.4.3", 27 | "@babel/plugin-proposal-class-properties": "^7.4.0", 28 | "@babel/preset-env": "^7.4.3", 29 | "@babel/preset-react": "^7.0.0", 30 | "@types/react": "^16.8.13", 31 | "@types/react-dom": "^16.8.3", 32 | "babel-cli": "^6.4.5", 33 | "babel-loader": "^8.0.5", 34 | "css-loader": "^2.1.1", 35 | "file-loader": "^3.0.1", 36 | "less": "^3.9.0", 37 | "less-loader": "^4.1.0", 38 | "react-hot-loader": "^4.8.3", 39 | "style-loader": "^0.23.1", 40 | "ts-loader": "^5.3.3", 41 | "typescript": "^3.4.2", 42 | "webpack": "^4.29.6", 43 | "webpack-cli": "^3.3.0", 44 | "webpack-dev-server": "^3.3.1" 45 | }, 46 | "dependencies": { 47 | "react": "^16.1.1", 48 | "react-dom": "^16.1.1" 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /dist/index.d.ts: -------------------------------------------------------------------------------- 1 | import * as React from 'react'; 2 | export declare type Pos = { 3 | top: number; 4 | left: number; 5 | bottom: number; 6 | right: number; 7 | }; 8 | interface State { 9 | showVeriticalTrack: boolean; 10 | showHorizontalTrack: boolean; 11 | noselect: boolean; 12 | handlerPos: Pos; 13 | hideHandler: boolean; 14 | } 15 | export declare type StartOption = '' | 'bottom' | 'right' | 'bottom right' | { 16 | top: number; 17 | left: number; 18 | }; 19 | export interface Props { 20 | className?: string; 21 | style?: object; 22 | fixed?: boolean; 23 | autohide?: boolean; 24 | timeout?: number; 25 | tracksize?: string; 26 | start?: StartOption; 27 | browserOffset?: string; 28 | onScrollbarScroll?: () => void; 29 | onScrollbarScrollTimeout?: number; 30 | } 31 | export default class FreeScrollbar extends React.PureComponent { 32 | protected static displayName: string; 33 | static defaultProps: Props; 34 | private el; 35 | private offsetHeight; 36 | private offsetWidth; 37 | private lastScrollHeight; 38 | private lastScrollWidth; 39 | private activeHandler; 40 | private lastMousePos; 41 | private lastContainerScrollTop; 42 | private lastContainerScrollLeft; 43 | private handlerHider; 44 | constructor(props: Props); 45 | private throttle; 46 | scrollbarScrollThrottle: () => void; 47 | componentDidMount(): void; 48 | componentWillUnmount(): void; 49 | componentDidUpdate(): void; 50 | private handleReadyStateChange; 51 | private prepareScrollbar; 52 | private prepareScrollbarStartPos; 53 | private collectInfo; 54 | private updateTrackVisibilities; 55 | private resetHandlerHider; 56 | private handlerContainerScroll; 57 | private handleHandlerMouseDown; 58 | private handleHandlerMouseMove; 59 | private handleHandlerMouseUp; 60 | /** 61 | * Set the scrolling position manually. 62 | */ 63 | setPosition: (pos: { 64 | top?: number; 65 | left?: number; 66 | }) => void; 67 | render(): JSX.Element; 68 | } 69 | export {}; 70 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # React-free-scrollbar 2 | 3 | [![npm version](https://badge.fury.io/js/react-free-scrollbar.svg)](https://badge.fury.io/js/react-free-scrollbar) 4 | 5 | A react module for creating customizable scroll area. 6 | 7 | Visit [http://fuermosi777.github.io/react-free-scrollbar/](http://fuermosi777.github.io/react-free-scrollbar/) to see [demo](http://fuermosi777.github.io/react-free-scrollbar/). 8 | 9 | ## Install 10 | 11 | $ npm install --save react-free-scrollbar 12 | 13 | or 14 | 15 | $ yarn add react-free-scrollbar 16 | 17 | ## Usage 18 | 19 | ### Quick start 20 | 21 | import FreeScrollBar from 'react-free-scrollbar'; 22 | 23 | // must have a wrapper with a certain size 24 | 25 |
26 | 27 |

The title

28 |

Lorem ipsum dolor sit amet, consectetur adipisicing elit.

29 |
30 |
31 | 32 | ## Props 33 | 34 | ### `className: string` optional 35 | 36 | Add custom class to the scroller. If you add a custom className to the component, all default styles will not working. You have to also add the following styles in your CSS files: 37 | 38 | // if you add "demo" as the custom class 39 | .demo {} // optional 40 | .demo-vertical-track {} // required 41 | .demo-horizontal-track {} // required 42 | .demo-vertical-handler {} // required 43 | .demo-horizontal-handler {} // required 44 | 45 | ### `style: object` optional 46 | 47 | If you just want to add some simple styles, you can pass this prop to the component. 48 | 49 | Example: 50 | 51 | 52 | 53 | ### `fixed: boolean` optional 54 | 55 | You can pass `fixed` to decide if handler's position: fixed or static. If `fixed` equals `true`, then the handler will overlap the content inside the scroller. 56 | 57 | ### `autohide: boolean` optional 58 | 59 | Set `true` if you want a macOS style auto-hide scroller. 60 | 61 | ### `timeout: number` optional 62 | 63 | The time length of the handler disappears. Default: 2000 64 | 65 | ### `tracksize: string` 66 | 67 | The width of the vertical handler or the height of the horizontal handler. Default: 10px 68 | 69 | ### `start: string | object` 70 | 71 | The starting position of the scroll area, can be descriptive string or an object. 72 | 73 | Options: "bottom", "bottom right", "top right", "right", `{top: 20, left: 30}` 74 | 75 | ### `browserOffset: string` 76 | 77 | The browser scroll bar width. Default: "17px". [It should fit for most browsers](https://codepen.io/sambible/post/browser-scrollbar-widths). 78 | 79 | ### `onScrollbarScroll: Function` optional 80 | 81 | Fired when the scrollbar is scrolled. 82 | 83 | ### `onScrollbarScrollTimeout: Number` optional 84 | 85 | This timeout adds a throttle for `onScrollbarScroll`. Default is `300`. Set to `0` to remove throttle. 86 | 87 | ## Methods 88 | 89 | ### `setPosition(pos: {top: number, left: number})` 90 | 91 | ## Customization 92 | 93 | Adding a custom className to the component will give you power to customize the scrollbar's track and handler. Here is an example: 94 | 95 | /* the following code snippet is using Less */ 96 | .example-vertical-track { 97 | background-color: transparent; 98 | width: 10px; 99 | transition: opacity 0.3s; 100 | } 101 | 102 | .example-horizontal-track { 103 | background-color: transparent; 104 | height: 10px; 105 | transition: opacity 0.3s; 106 | } 107 | 108 | .example-vertical-handler { 109 | width: 8px; 110 | right: 1px; 111 | border-radius: 4px; 112 | background-color: rgba(0, 0, 0, 0.5); 113 | transition: opacity 0.3s; 114 | &:hover { 115 | background-color: rgba(0, 0, 0, 0.8); 116 | } 117 | } 118 | 119 | .example-horizontal-handler { 120 | height: 8px; 121 | bottom: 1px; 122 | border-radius: 4px; 123 | background-color: rgba(0, 0, 0, 0.5); 124 | transition: opacity 0.3s; 125 | &:hover { 126 | background-color: rgba(0, 0, 0, 0.8); 127 | } 128 | } 129 | 130 | For more examples, go to [http://fuermosi777.github.io/react-free-scrollbar/](http://fuermosi777.github.io/react-free-scrollbar/). 131 | 132 | ## Develop 133 | 134 | `$ yarn dev` 135 | 136 | Go to `http://localhost:8080`. 137 | 138 | ## Publish 139 | 140 | `$ yarn dist` 141 | `$ npm publish` 142 | 143 | Update changelog. 144 | -------------------------------------------------------------------------------- /demo/src/entry.tsx: -------------------------------------------------------------------------------- 1 | import * as React from 'react'; 2 | import * as ReactDOM from 'react-dom'; 3 | // @ts-ignore 4 | import FreeScrollBar from '../../src/index.tsx'; 5 | import './demo.less'; 6 | 7 | const things = [ 8 | 'Clean the room', 9 | 'Take out the ice-cream', 10 | 'Do the homework', 11 | 'Feed the cat', 12 | 'Clean the car', 13 | 'Go to dinner', 14 | 'Clean the cups', 15 | 'Throw a party', 16 | 'Repeat things above', 17 | 'Think about the trip', 18 | 'Make up a list', 19 | 'Go out with friends', 20 | "Kick neighbor's butt", 21 | ]; 22 | 23 | const List = things.map((item, key) => { 24 | return
  • {item}
  • ; 25 | }); 26 | 27 | const Text = ( 28 |

    29 | Lorem ipsum dolor sit amet, consectetur adipisicing elit. Sapiente sint quos at. Quae in 30 | voluptate, autem ipsa porro quisquam architecto eos impedit laudantium, dolorem blanditiis 31 | fugiat maxime, veritatis voluptas temporibus? 32 |
    33 |
    34 | Lorem ipsum dolor sit amet, consectetur adipisicing elit. Hic consequuntur, incidunt explicabo 35 | reiciendis, reprehenderit voluptates dolorum possimus quo consequatur ratione quasi ipsa 36 | provident, ducimus similique. Ipsum quo alias exercitationem corrupti? 37 |
    38 |
    39 | Lorem ipsum dolor sit amet, consectetur adipisicing elit. Hic consequuntur, incidunt explicabo 40 | reiciendis, reprehenderit voluptates dolorum possimus quo consequatur ratione quasi ipsa 41 | provident, ducimus similique. Ipsum quo alias exercitationem corrupti? 42 |
    43 |
    44 | Lorem ipsum dolor sit amet, consectetur adipisicing elit. Hic consequuntur, incidunt explicabo 45 | reiciendis, reprehenderit voluptates dolorum possimus quo consequatur ratione quasi ipsa 46 | provident, ducimus similique. Ipsum quo alias exercitationem corrupti? 47 |

    48 | ); 49 | 50 | class Root extends React.Component { 51 | private controlledScrollBar: FreeScrollBar | null = null; 52 | private handlePositionChanged = (pos: { top?: number; left?: number }) => { 53 | if (this.controlledScrollBar) { 54 | this.controlledScrollBar.setPosition(pos); 55 | } 56 | }; 57 | public render() { 58 | return ( 59 |
    60 |
    61 |
    62 |

    React Free Scrollbar

    63 |

    A react module for creating customizable scroll area

    64 |
    65 | 68 | Documentation on Github 69 | 70 | 71 |

    Features

    72 |
      73 |
    • Vertical and horizontal scrolling
    • 74 |
    • Auto-hide
    • 75 |
    • Fully customizable
    • 76 |
    77 | 78 |

    Install

    79 |
     80 |             $ npm install --save react-free-scrollbar
     81 |           
    82 |

    Examples

    83 |
    84 |
    85 |

    Quick start

    86 |
    87 | 88 |
    89 | {List} 90 | {List} 91 | {List} 92 | {List} 93 | {List} 94 | {List} 95 | {List} 96 |
    97 |
    98 |
    99 |
    100 |
    101 |

    Horizontal

    102 |
    103 | 104 | 105 | 106 |
    107 |
    108 |
    109 |
    110 |
    111 |

    Custom styles

    112 |
    113 | 114 |
    115 | {List} 116 | {List} 117 | {List} 118 | {List} 119 | {List} 120 | {List} 121 | {List} 122 | {List} 123 | {List} 124 | {List} 125 | {List} 126 | {List} 127 | {List} 128 | {List} 129 | {List} 130 | {List} 131 | {List} 132 | {List} 133 | {List} 134 | {List} 135 | {List} 136 | {List} 137 | {List} 138 | {List} 139 | {List} 140 | {List} 141 | {List} 142 | {List} 143 |
    144 |
    145 |
    146 |
    147 |
    148 |

    Auto hide, and the starting position is on the "bottom right".

    149 |
    150 | { 156 | console.log('scrolled'); 157 | }} 158 | onScrollbarScrollTimeout={100}> 159 |
    {Text}
    160 |
    161 |
    162 |
    163 |
    164 |
    165 |
    166 |

    Control scrolling position

    167 | this.handlePositionChanged({ top: Number(e.target.value) || 10 })} 171 | /> 172 | this.handlePositionChanged({ left: Number(e.target.value) || 10 })} 176 | /> 177 |
    178 | (this.controlledScrollBar = el)}> 182 |
    183 | {List} 184 | {List} 185 | {List} 186 | {List} 187 | {List} 188 | {List} 189 | {List} 190 |
    191 |
    192 |
    193 |
    194 |
    195 |

    196 | 199 | Documentation on Github 200 | 201 |

    © 2017 ~ 2019 Hao Liu

    202 |

    203 |
    204 | ); 205 | } 206 | } 207 | 208 | ReactDOM.render(, document.getElementById('app')); 209 | -------------------------------------------------------------------------------- /dist/index.js.map: -------------------------------------------------------------------------------- 1 | {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.tsx"],"names":[],"mappings":"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"} -------------------------------------------------------------------------------- /src/index.tsx: -------------------------------------------------------------------------------- 1 | import * as React from 'react'; 2 | 3 | enum Direction { 4 | Vertical, 5 | Horizontal, 6 | } 7 | 8 | export type Pos = { 9 | top: number; 10 | left: number; 11 | bottom: number; 12 | right: number; 13 | }; 14 | 15 | const styles = { 16 | main: { 17 | overflow: 'hidden', 18 | position: 'relative', 19 | boxSizing: 'border-box', 20 | }, 21 | container: { 22 | position: 'absolute', 23 | top: '0', 24 | left: '0', 25 | overflow: 'scroll', 26 | boxSizing: 'border-box', 27 | }, 28 | track: { 29 | vertical: { 30 | position: 'absolute', 31 | top: '0', 32 | right: '0', 33 | }, 34 | verticalCustomize: { 35 | width: '10px', 36 | backgroundColor: '#FAFAFA', 37 | borderLeft: '1px solid #E8E8E8', 38 | transition: 'opacity 0.3s', 39 | }, 40 | horizontal: { 41 | position: 'absolute', 42 | left: '0', 43 | bottom: '0', 44 | }, 45 | horizontalCustomize: { 46 | height: '10px', 47 | backgroundColor: '#FAFAFA', 48 | borderTop: '1px solid #E8E8E8', 49 | transition: 'opacity 0.3s', 50 | }, 51 | }, 52 | handler: { 53 | vertical: { 54 | position: 'absolute', 55 | }, 56 | verticalCustomize: { 57 | width: '100%', 58 | backgroundColor: '#C1C1C1', 59 | borderRadius: '5px', 60 | transition: 'opacity 0.3s', 61 | }, 62 | horizontal: { 63 | position: 'absolute', 64 | }, 65 | horizontalCustomize: { 66 | height: '100%', 67 | backgroundColor: '#C1C1C1', 68 | borderRadius: '5px', 69 | transition: 'opacity 0.3s', 70 | }, 71 | }, 72 | square: { 73 | position: 'absolute', 74 | width: '10px', 75 | height: '10px', 76 | right: 0, 77 | bottom: 0, 78 | backgroundColor: 'white', 79 | }, 80 | }; 81 | 82 | interface State { 83 | showVeriticalTrack: boolean; 84 | showHorizontalTrack: boolean; 85 | noselect: boolean; 86 | handlerPos: Pos; 87 | hideHandler: boolean; 88 | } 89 | 90 | export type StartOption = '' | 'bottom' | 'right' | 'bottom right' | { top: number; left: number }; 91 | 92 | export interface Props { 93 | className?: string; 94 | style?: object; 95 | fixed?: boolean; 96 | autohide?: boolean; 97 | timeout?: number; 98 | tracksize?: string; 99 | // Initial scroll bar position. 100 | start?: StartOption; 101 | browserOffset?: string; 102 | onScrollbarScroll?: () => void; 103 | onScrollbarScrollTimeout?: number; 104 | } 105 | 106 | export default class FreeScrollbar extends React.PureComponent { 107 | protected static displayName = 'FreeScrollbar'; 108 | 109 | public static defaultProps: Props = { 110 | className: '', 111 | style: { 112 | width: '100%', 113 | height: '100%', 114 | }, 115 | fixed: false, 116 | autohide: false, 117 | timeout: 2000, 118 | tracksize: '10px', 119 | start: '', 120 | browserOffset: '17px', 121 | onScrollbarScroll: null, 122 | onScrollbarScrollTimeout: 300, 123 | }; 124 | 125 | private el: HTMLDivElement = null; 126 | private offsetHeight = 0; 127 | private offsetWidth = 0; 128 | private lastScrollHeight = 0; 129 | private lastScrollWidth = 0; 130 | private activeHandler: Direction = null; 131 | private lastMousePos: { top: number; left: number } = null; 132 | private lastContainerScrollTop = 0; 133 | private lastContainerScrollLeft = 0; 134 | private handlerHider: number = null; 135 | 136 | public constructor(props: Props) { 137 | super(props); 138 | 139 | this.state = { 140 | showVeriticalTrack: false, 141 | showHorizontalTrack: false, 142 | noselect: false, 143 | handlerPos: { 144 | // Vertical handler. 145 | top: 0, 146 | bottom: 0, 147 | // Horizontal handler. 148 | left: 0, 149 | right: 0, 150 | }, 151 | hideHandler: props.autohide, 152 | }; 153 | } 154 | 155 | private throttle = (func: (args?: any) => void, timeout: number) => { 156 | if (!func) return null; 157 | 158 | let canRun = true; 159 | 160 | return function (...args: any) { 161 | if (canRun) { 162 | canRun = false; 163 | func(...args); 164 | 165 | setTimeout(() => { 166 | canRun = true; 167 | }, timeout); 168 | } 169 | }; 170 | }; 171 | 172 | public scrollbarScrollThrottle = 173 | this.props.onScrollbarScrollTimeout > 0 174 | ? this.throttle(this.props.onScrollbarScroll, this.props.onScrollbarScrollTimeout) 175 | : this.props.onScrollbarScroll; 176 | 177 | public componentDidMount() { 178 | window.addEventListener('resize', this.prepareScrollbar); 179 | document.addEventListener('mousemove', this.handleHandlerMouseMove); 180 | document.addEventListener('mouseup', this.handleHandlerMouseUp); 181 | document.addEventListener('readystatechange', this.handleReadyStateChange); 182 | 183 | this.prepareScrollbar(); 184 | } 185 | 186 | public componentWillUnmount() { 187 | window.removeEventListener('resize', this.prepareScrollbar); 188 | document.removeEventListener('mousemove', this.handleHandlerMouseMove); 189 | document.removeEventListener('mouseup', this.handleHandlerMouseUp); 190 | document.removeEventListener('readystatechange', this.handleReadyStateChange); 191 | 192 | clearTimeout(this.handlerHider); 193 | } 194 | 195 | public componentDidUpdate() { 196 | this.updateTrackVisibilities(); 197 | } 198 | 199 | private handleReadyStateChange = () => { 200 | if (document.readyState === 'complete') { 201 | this.prepareScrollbar(); 202 | this.prepareScrollbarStartPos(); 203 | } 204 | }; 205 | 206 | private prepareScrollbar = () => { 207 | this.collectInfo(); 208 | this.updateTrackVisibilities(); 209 | 210 | // Trigger auto hider. 211 | this.handlerContainerScroll(); 212 | }; 213 | 214 | private prepareScrollbarStartPos = () => { 215 | const { start } = this.props; 216 | if (typeof start === 'string') { 217 | if (start.includes('bottom')) { 218 | this.el.scrollTop = this.el.scrollHeight; 219 | } 220 | if (start.includes('right')) { 221 | this.el.scrollLeft = this.el.scrollWidth; 222 | } 223 | } else if (typeof start === 'object') { 224 | this.el.scrollTop = start.top; 225 | this.el.scrollLeft = start.left; 226 | } 227 | }; 228 | 229 | private collectInfo = () => { 230 | this.offsetWidth = this.el.offsetWidth; 231 | this.offsetHeight = this.el.offsetHeight; 232 | }; 233 | 234 | private updateTrackVisibilities = () => { 235 | let { el } = this; 236 | let { scrollHeight, scrollWidth } = el; 237 | 238 | if (scrollHeight === this.lastScrollHeight && scrollWidth === this.lastScrollWidth) return; 239 | this.setState({ 240 | showVeriticalTrack: scrollHeight > this.offsetHeight, 241 | showHorizontalTrack: scrollWidth > this.offsetWidth, 242 | }); 243 | this.lastScrollWidth = scrollWidth; 244 | this.lastScrollHeight = scrollHeight; 245 | }; 246 | 247 | private resetHandlerHider = () => { 248 | if (this.props.autohide) { 249 | clearTimeout(this.handlerHider); 250 | this.setState({ hideHandler: false }); 251 | this.handlerHider = setTimeout(() => { 252 | this.setState({ hideHandler: true }); 253 | }, this.props.timeout); 254 | } 255 | }; 256 | 257 | private handlerContainerScroll = () => { 258 | this.resetHandlerHider(); 259 | 260 | let el = this.el; 261 | let top = 262 | (el.scrollTop / (el.scrollHeight - this.offsetHeight)) * 263 | (1 - this.offsetHeight / this.lastScrollHeight) * 264 | 100; 265 | let bottom = 266 | (1 - 267 | ((el.scrollTop + this.offsetHeight) / (el.scrollHeight - this.offsetHeight)) * 268 | (1 - this.offsetHeight / this.lastScrollHeight)) * 269 | 100; 270 | if (bottom < 0) bottom = 0; 271 | let left = 272 | (el.scrollLeft / (el.scrollWidth - this.offsetWidth)) * 273 | (1 - this.offsetWidth / this.lastScrollWidth) * 274 | 100; 275 | let right = 276 | (1 - 277 | ((el.scrollLeft + this.offsetWidth) / (el.scrollWidth - this.offsetWidth)) * 278 | (1 - this.offsetWidth / this.lastScrollWidth)) * 279 | 100; 280 | if (right < 0) right = 0; 281 | let pos = { 282 | top: top, 283 | bottom: bottom, 284 | left: left, 285 | right: right, 286 | }; 287 | this.setState({ handlerPos: pos }); 288 | 289 | if (this.scrollbarScrollThrottle) { 290 | this.scrollbarScrollThrottle(); 291 | } 292 | }; 293 | 294 | private handleHandlerMouseDown = ( 295 | e: React.MouseEvent, 296 | d: Direction 297 | ) => { 298 | this.resetHandlerHider(); 299 | this.lastContainerScrollTop = this.el.scrollTop; 300 | this.lastContainerScrollLeft = this.el.scrollLeft; 301 | 302 | this.activeHandler = d; 303 | this.lastMousePos = { 304 | top: e.clientY, 305 | left: e.clientX, 306 | }; 307 | this.setState({ noselect: true }); 308 | }; 309 | 310 | private handleHandlerMouseMove = (event: MouseEvent) => { 311 | if (this.activeHandler === Direction.Vertical) { 312 | let delY = event.clientY - this.lastMousePos.top; 313 | this.el.scrollTop = 314 | this.lastContainerScrollTop + (delY / this.offsetHeight) * this.lastScrollHeight; 315 | } 316 | if (this.activeHandler === Direction.Horizontal) { 317 | let delX = event.clientX - this.lastMousePos.left; 318 | this.el.scrollLeft = 319 | this.lastContainerScrollLeft + (delX / this.offsetWidth) * this.lastScrollWidth; 320 | } 321 | }; 322 | 323 | private handleHandlerMouseUp = () => { 324 | this.lastMousePos = null; 325 | this.activeHandler = null; 326 | this.setState({ noselect: false }); 327 | }; 328 | 329 | /** 330 | * Set the scrolling position manually. 331 | */ 332 | public setPosition = (pos: { top?: number; left?: number }) => { 333 | if (pos.top) { 334 | this.el.scrollTop = pos.top; 335 | } 336 | if (pos.left) { 337 | this.el.scrollLeft = pos.left; 338 | } 339 | }; 340 | 341 | public render() { 342 | // Dynamic styles 343 | let containerStyles: React.CSSProperties = { 344 | paddingRight: this.props.fixed 345 | ? 0 346 | : this.state.showHorizontalTrack 347 | ? this.props.tracksize 348 | : 0, 349 | paddingBottom: this.props.fixed 350 | ? 0 351 | : this.state.showVeriticalTrack 352 | ? this.props.tracksize 353 | : 0, 354 | right: `-${this.props.browserOffset}`, 355 | bottom: `-${this.props.browserOffset}`, 356 | }; 357 | if (this.state.noselect) { 358 | containerStyles.userSelect = 'none'; 359 | containerStyles.MozUserSelect = 'none'; 360 | containerStyles.WebkitUserSelect = 'none'; 361 | containerStyles.msUserSelect = 'none'; 362 | } 363 | let verticalTrackStyles = { 364 | bottom: this.state.showHorizontalTrack ? this.props.tracksize : '0', 365 | opacity: this.state.hideHandler ? 0 : 1, 366 | }; 367 | let horizontalTrackStyles = { 368 | right: this.state.showVeriticalTrack ? this.props.tracksize : '0', 369 | opacity: this.state.hideHandler ? 0 : 1, 370 | }; 371 | // TODO: resolve the bottom issue and the horizontal handler length. 372 | // TODO: convert this into the config option. 373 | let min = 5; 374 | let verticalHandlerHeight = Math.max( 375 | 100 - this.state.handlerPos.bottom - this.state.handlerPos.top, 376 | min 377 | ); 378 | let verticalHandlerStyles = { 379 | top: this.state.handlerPos.top + '%', 380 | bottom: 100 - verticalHandlerHeight - this.state.handlerPos.top + '%', 381 | opacity: this.state.hideHandler ? 0 : 1, 382 | }; 383 | let horizontalHandlerStyles = { 384 | left: this.state.handlerPos.left + '%', 385 | right: this.state.handlerPos.right + '%', 386 | opacity: this.state.hideHandler ? 0 : 1, 387 | }; 388 | 389 | return ( 390 |
    393 |
    (this.el = container)} 397 | onScroll={this.handlerContainerScroll}> 398 | {this.props.children} 399 |
    400 | {this.state.showVeriticalTrack ? ( 401 |
    414 |
    { 419 | this.handleHandlerMouseDown(event, Direction.Vertical); 420 | }} 421 | style={ 422 | this.props.className 423 | ? Object.assign(verticalHandlerStyles, styles.handler.vertical) 424 | : Object.assign( 425 | verticalHandlerStyles, 426 | styles.handler.vertical, 427 | styles.handler.verticalCustomize 428 | ) 429 | } 430 | /> 431 |
    432 | ) : null} 433 | {this.state.showHorizontalTrack ? ( 434 |
    447 |
    { 452 | this.handleHandlerMouseDown(event, Direction.Horizontal); 453 | }} 454 | style={ 455 | this.props.className 456 | ? Object.assign(horizontalHandlerStyles, styles.handler.horizontal) 457 | : Object.assign( 458 | horizontalHandlerStyles, 459 | styles.handler.horizontal, 460 | styles.handler.horizontalCustomize 461 | ) 462 | } 463 | /> 464 |
    465 | ) : null} 466 | {this.state.showHorizontalTrack && this.state.showVeriticalTrack && !this.props.fixed ? ( 467 |
    473 | ) : null} 474 |
    475 | ); 476 | } 477 | } 478 | -------------------------------------------------------------------------------- /dist/index.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | var __extends = (this && this.__extends) || (function () { 3 | var extendStatics = function (d, b) { 4 | extendStatics = Object.setPrototypeOf || 5 | ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) || 6 | function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; }; 7 | return extendStatics(d, b); 8 | }; 9 | return function (d, b) { 10 | extendStatics(d, b); 11 | function __() { this.constructor = d; } 12 | d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); 13 | }; 14 | })(); 15 | var __assign = (this && this.__assign) || function () { 16 | __assign = Object.assign || function(t) { 17 | for (var s, i = 1, n = arguments.length; i < n; i++) { 18 | s = arguments[i]; 19 | for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p)) 20 | t[p] = s[p]; 21 | } 22 | return t; 23 | }; 24 | return __assign.apply(this, arguments); 25 | }; 26 | Object.defineProperty(exports, "__esModule", { value: true }); 27 | var React = require("react"); 28 | var Direction; 29 | (function (Direction) { 30 | Direction[Direction["Vertical"] = 0] = "Vertical"; 31 | Direction[Direction["Horizontal"] = 1] = "Horizontal"; 32 | })(Direction || (Direction = {})); 33 | var styles = { 34 | main: { 35 | overflow: 'hidden', 36 | position: 'relative', 37 | boxSizing: 'border-box', 38 | }, 39 | container: { 40 | position: 'absolute', 41 | top: '0', 42 | left: '0', 43 | overflow: 'scroll', 44 | boxSizing: 'border-box', 45 | }, 46 | track: { 47 | vertical: { 48 | position: 'absolute', 49 | top: '0', 50 | right: '0', 51 | }, 52 | verticalCustomize: { 53 | width: '10px', 54 | backgroundColor: '#FAFAFA', 55 | borderLeft: '1px solid #E8E8E8', 56 | transition: 'opacity 0.3s', 57 | }, 58 | horizontal: { 59 | position: 'absolute', 60 | left: '0', 61 | bottom: '0', 62 | }, 63 | horizontalCustomize: { 64 | height: '10px', 65 | backgroundColor: '#FAFAFA', 66 | borderTop: '1px solid #E8E8E8', 67 | transition: 'opacity 0.3s', 68 | }, 69 | }, 70 | handler: { 71 | vertical: { 72 | position: 'absolute', 73 | }, 74 | verticalCustomize: { 75 | width: '100%', 76 | backgroundColor: '#C1C1C1', 77 | borderRadius: '5px', 78 | transition: 'opacity 0.3s', 79 | }, 80 | horizontal: { 81 | position: 'absolute', 82 | }, 83 | horizontalCustomize: { 84 | height: '100%', 85 | backgroundColor: '#C1C1C1', 86 | borderRadius: '5px', 87 | transition: 'opacity 0.3s', 88 | }, 89 | }, 90 | square: { 91 | position: 'absolute', 92 | width: '10px', 93 | height: '10px', 94 | right: 0, 95 | bottom: 0, 96 | backgroundColor: 'white', 97 | }, 98 | }; 99 | var FreeScrollbar = /** @class */ (function (_super) { 100 | __extends(FreeScrollbar, _super); 101 | function FreeScrollbar(props) { 102 | var _this = _super.call(this, props) || this; 103 | _this.el = null; 104 | _this.offsetHeight = 0; 105 | _this.offsetWidth = 0; 106 | _this.lastScrollHeight = 0; 107 | _this.lastScrollWidth = 0; 108 | _this.activeHandler = null; 109 | _this.lastMousePos = null; 110 | _this.lastContainerScrollTop = 0; 111 | _this.lastContainerScrollLeft = 0; 112 | _this.handlerHider = null; 113 | _this.throttle = function (func, timeout) { 114 | if (!func) 115 | return null; 116 | var canRun = true; 117 | return function () { 118 | var args = []; 119 | for (var _i = 0; _i < arguments.length; _i++) { 120 | args[_i] = arguments[_i]; 121 | } 122 | if (canRun) { 123 | canRun = false; 124 | func.apply(void 0, args); 125 | setTimeout(function () { 126 | canRun = true; 127 | }, timeout); 128 | } 129 | }; 130 | }; 131 | _this.scrollbarScrollThrottle = _this.props.onScrollbarScrollTimeout > 0 132 | ? _this.throttle(_this.props.onScrollbarScroll, _this.props.onScrollbarScrollTimeout) 133 | : _this.props.onScrollbarScroll; 134 | _this.handleReadyStateChange = function () { 135 | if (document.readyState === 'complete') { 136 | _this.prepareScrollbar(); 137 | _this.prepareScrollbarStartPos(); 138 | } 139 | }; 140 | _this.prepareScrollbar = function () { 141 | _this.collectInfo(); 142 | _this.updateTrackVisibilities(); 143 | // Trigger auto hider. 144 | _this.handlerContainerScroll(); 145 | }; 146 | _this.prepareScrollbarStartPos = function () { 147 | var start = _this.props.start; 148 | if (typeof start === 'string') { 149 | if (start.includes('bottom')) { 150 | _this.el.scrollTop = _this.el.scrollHeight; 151 | } 152 | if (start.includes('right')) { 153 | _this.el.scrollLeft = _this.el.scrollWidth; 154 | } 155 | } 156 | else if (typeof start === 'object') { 157 | _this.el.scrollTop = start.top; 158 | _this.el.scrollLeft = start.left; 159 | } 160 | }; 161 | _this.collectInfo = function () { 162 | _this.offsetWidth = _this.el.offsetWidth; 163 | _this.offsetHeight = _this.el.offsetHeight; 164 | }; 165 | _this.updateTrackVisibilities = function () { 166 | var el = _this.el; 167 | var scrollHeight = el.scrollHeight, scrollWidth = el.scrollWidth; 168 | if (scrollHeight === _this.lastScrollHeight && scrollWidth === _this.lastScrollWidth) 169 | return; 170 | _this.setState({ 171 | showVeriticalTrack: scrollHeight > _this.offsetHeight, 172 | showHorizontalTrack: scrollWidth > _this.offsetWidth, 173 | }); 174 | _this.lastScrollWidth = scrollWidth; 175 | _this.lastScrollHeight = scrollHeight; 176 | }; 177 | _this.resetHandlerHider = function () { 178 | if (_this.props.autohide) { 179 | clearTimeout(_this.handlerHider); 180 | _this.setState({ hideHandler: false }); 181 | _this.handlerHider = setTimeout(function () { 182 | _this.setState({ hideHandler: true }); 183 | }, _this.props.timeout); 184 | } 185 | }; 186 | _this.handlerContainerScroll = function () { 187 | _this.resetHandlerHider(); 188 | var el = _this.el; 189 | var top = (el.scrollTop / (el.scrollHeight - _this.offsetHeight)) * 190 | (1 - _this.offsetHeight / _this.lastScrollHeight) * 191 | 100; 192 | var bottom = (1 - 193 | ((el.scrollTop + _this.offsetHeight) / (el.scrollHeight - _this.offsetHeight)) * 194 | (1 - _this.offsetHeight / _this.lastScrollHeight)) * 195 | 100; 196 | if (bottom < 0) 197 | bottom = 0; 198 | var left = (el.scrollLeft / (el.scrollWidth - _this.offsetWidth)) * 199 | (1 - _this.offsetWidth / _this.lastScrollWidth) * 200 | 100; 201 | var right = (1 - 202 | ((el.scrollLeft + _this.offsetWidth) / (el.scrollWidth - _this.offsetWidth)) * 203 | (1 - _this.offsetWidth / _this.lastScrollWidth)) * 204 | 100; 205 | if (right < 0) 206 | right = 0; 207 | var pos = { 208 | top: top, 209 | bottom: bottom, 210 | left: left, 211 | right: right, 212 | }; 213 | _this.setState({ handlerPos: pos }); 214 | if (_this.scrollbarScrollThrottle) { 215 | _this.scrollbarScrollThrottle(); 216 | } 217 | }; 218 | _this.handleHandlerMouseDown = function (e, d) { 219 | _this.resetHandlerHider(); 220 | _this.lastContainerScrollTop = _this.el.scrollTop; 221 | _this.lastContainerScrollLeft = _this.el.scrollLeft; 222 | _this.activeHandler = d; 223 | _this.lastMousePos = { 224 | top: e.clientY, 225 | left: e.clientX, 226 | }; 227 | _this.setState({ noselect: true }); 228 | }; 229 | _this.handleHandlerMouseMove = function (event) { 230 | if (_this.activeHandler === Direction.Vertical) { 231 | var delY = event.clientY - _this.lastMousePos.top; 232 | _this.el.scrollTop = 233 | _this.lastContainerScrollTop + (delY / _this.offsetHeight) * _this.lastScrollHeight; 234 | } 235 | if (_this.activeHandler === Direction.Horizontal) { 236 | var delX = event.clientX - _this.lastMousePos.left; 237 | _this.el.scrollLeft = 238 | _this.lastContainerScrollLeft + (delX / _this.offsetWidth) * _this.lastScrollWidth; 239 | } 240 | }; 241 | _this.handleHandlerMouseUp = function () { 242 | _this.lastMousePos = null; 243 | _this.activeHandler = null; 244 | _this.setState({ noselect: false }); 245 | }; 246 | /** 247 | * Set the scrolling position manually. 248 | */ 249 | _this.setPosition = function (pos) { 250 | if (pos.top) { 251 | _this.el.scrollTop = pos.top; 252 | } 253 | if (pos.left) { 254 | _this.el.scrollLeft = pos.left; 255 | } 256 | }; 257 | _this.state = { 258 | showVeriticalTrack: false, 259 | showHorizontalTrack: false, 260 | noselect: false, 261 | handlerPos: { 262 | // Vertical handler. 263 | top: 0, 264 | bottom: 0, 265 | // Horizontal handler. 266 | left: 0, 267 | right: 0, 268 | }, 269 | hideHandler: props.autohide, 270 | }; 271 | return _this; 272 | } 273 | FreeScrollbar.prototype.componentDidMount = function () { 274 | window.addEventListener('resize', this.prepareScrollbar); 275 | document.addEventListener('mousemove', this.handleHandlerMouseMove); 276 | document.addEventListener('mouseup', this.handleHandlerMouseUp); 277 | document.addEventListener('readystatechange', this.handleReadyStateChange); 278 | this.prepareScrollbar(); 279 | }; 280 | FreeScrollbar.prototype.componentWillUnmount = function () { 281 | window.removeEventListener('resize', this.prepareScrollbar); 282 | document.removeEventListener('mousemove', this.handleHandlerMouseMove); 283 | document.removeEventListener('mouseup', this.handleHandlerMouseUp); 284 | document.removeEventListener('readystatechange', this.handleReadyStateChange); 285 | clearTimeout(this.handlerHider); 286 | }; 287 | FreeScrollbar.prototype.componentDidUpdate = function () { 288 | this.updateTrackVisibilities(); 289 | }; 290 | FreeScrollbar.prototype.render = function () { 291 | var _this = this; 292 | // Dynamic styles 293 | var containerStyles = { 294 | paddingRight: this.props.fixed 295 | ? 0 296 | : this.state.showHorizontalTrack 297 | ? this.props.tracksize 298 | : 0, 299 | paddingBottom: this.props.fixed 300 | ? 0 301 | : this.state.showVeriticalTrack 302 | ? this.props.tracksize 303 | : 0, 304 | right: "-" + this.props.browserOffset, 305 | bottom: "-" + this.props.browserOffset, 306 | }; 307 | if (this.state.noselect) { 308 | containerStyles.userSelect = 'none'; 309 | containerStyles.MozUserSelect = 'none'; 310 | containerStyles.WebkitUserSelect = 'none'; 311 | containerStyles.msUserSelect = 'none'; 312 | } 313 | var verticalTrackStyles = { 314 | bottom: this.state.showHorizontalTrack ? this.props.tracksize : '0', 315 | opacity: this.state.hideHandler ? 0 : 1, 316 | }; 317 | var horizontalTrackStyles = { 318 | right: this.state.showVeriticalTrack ? this.props.tracksize : '0', 319 | opacity: this.state.hideHandler ? 0 : 1, 320 | }; 321 | var verticalHandlerStyles = { 322 | top: this.state.handlerPos.top + '%', 323 | bottom: this.state.handlerPos.bottom + '%', 324 | opacity: this.state.hideHandler ? 0 : 1, 325 | }; 326 | var horizontalHandlerStyles = { 327 | left: this.state.handlerPos.left + '%', 328 | right: this.state.handlerPos.right + '%', 329 | opacity: this.state.hideHandler ? 0 : 1, 330 | }; 331 | return (React.createElement("div", { className: "FreeScrollbar " + this.props.className, style: __assign({}, this.props.style, styles.main) }, 332 | React.createElement("div", { className: "FreeScrollbar-container", style: __assign({}, containerStyles, styles.container), ref: function (container) { return (_this.el = container); }, onScroll: this.handlerContainerScroll }, this.props.children), 333 | this.state.showVeriticalTrack ? (React.createElement("div", { className: "FreeScrollbar-vertical-track " + (this.props.className ? this.props.className + '-vertical-track' : ''), style: this.props.className 334 | ? Object.assign(verticalTrackStyles, styles.track.vertical) 335 | : Object.assign(verticalTrackStyles, styles.track.vertical, styles.track.verticalCustomize) }, 336 | React.createElement("div", { className: "FreeScrollbar-vertical-handler " + (this.props.className ? this.props.className + '-vertical-handler' : ''), onMouseDown: function (event) { 337 | _this.handleHandlerMouseDown(event, Direction.Vertical); 338 | }, style: this.props.className 339 | ? Object.assign(verticalHandlerStyles, styles.handler.vertical) 340 | : Object.assign(verticalHandlerStyles, styles.handler.vertical, styles.handler.verticalCustomize) }))) : null, 341 | this.state.showHorizontalTrack ? (React.createElement("div", { className: "FreeScrollbar-horizontal-track " + (this.props.className ? this.props.className + '-horizontal-track' : ''), style: this.props.className 342 | ? Object.assign(horizontalTrackStyles, styles.track.horizontal) 343 | : Object.assign(horizontalTrackStyles, styles.track.horizontal, styles.track.horizontalCustomize) }, 344 | React.createElement("div", { className: "FreeScrollbar-horizontal-handler " + (this.props.className ? this.props.className + '-horizontal-handler' : ''), onMouseDown: function (event) { 345 | _this.handleHandlerMouseDown(event, Direction.Horizontal); 346 | }, style: this.props.className 347 | ? Object.assign(horizontalHandlerStyles, styles.handler.horizontal) 348 | : Object.assign(horizontalHandlerStyles, styles.handler.horizontal, styles.handler.horizontalCustomize) }))) : null, 349 | this.state.showHorizontalTrack && this.state.showVeriticalTrack && !this.props.fixed ? (React.createElement("div", { className: "FreeScrollbar-square " + (this.props.className ? this.props.className + '-square' : ''), style: styles.square })) : null)); 350 | }; 351 | FreeScrollbar.displayName = 'FreeScrollbar'; 352 | FreeScrollbar.defaultProps = { 353 | className: '', 354 | style: { 355 | width: '100%', 356 | height: '100%', 357 | }, 358 | fixed: false, 359 | autohide: false, 360 | timeout: 2000, 361 | tracksize: '10px', 362 | start: '', 363 | browserOffset: '17px', 364 | onScrollbarScroll: null, 365 | onScrollbarScrollTimeout: 300, 366 | }; 367 | return FreeScrollbar; 368 | }(React.PureComponent)); 369 | exports.default = FreeScrollbar; 370 | //# sourceMappingURL=index.js.map -------------------------------------------------------------------------------- /site/index.js: -------------------------------------------------------------------------------- 1 | !function(e){var t={};function n(r){if(t[r])return t[r].exports;var l=t[r]={i:r,l:!1,exports:{}};return e[r].call(l.exports,l,l.exports,n),l.l=!0,l.exports}n.m=e,n.c=t,n.d=function(e,t,r){n.o(e,t)||Object.defineProperty(e,t,{enumerable:!0,get:r})},n.r=function(e){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},n.t=function(e,t){if(1&t&&(e=n(e)),8&t)return e;if(4&t&&"object"==typeof e&&e&&e.__esModule)return e;var r=Object.create(null);if(n.r(r),Object.defineProperty(r,"default",{enumerable:!0,value:e}),2&t&&"string"!=typeof e)for(var l in e)n.d(r,l,function(t){return e[t]}.bind(null,l));return r},n.n=function(e){var t=e&&e.__esModule?function(){return e.default}:function(){return e};return n.d(t,"a",t),t},n.o=function(e,t){return Object.prototype.hasOwnProperty.call(e,t)},n.p="",n(n.s=2)}([function(e,t,n){"use strict";e.exports=n(4)},function(e,t,n){"use strict"; 2 | /* 3 | object-assign 4 | (c) Sindre Sorhus 5 | @license MIT 6 | */var r=Object.getOwnPropertySymbols,l=Object.prototype.hasOwnProperty,o=Object.prototype.propertyIsEnumerable;e.exports=function(){try{if(!Object.assign)return!1;var e=new String("abc");if(e[5]="de","5"===Object.getOwnPropertyNames(e)[0])return!1;for(var t={},n=0;n<10;n++)t["_"+String.fromCharCode(n)]=n;if("0123456789"!==Object.getOwnPropertyNames(t).map(function(e){return t[e]}).join(""))return!1;var r={};return"abcdefghijklmnopqrst".split("").forEach(function(e){r[e]=e}),"abcdefghijklmnopqrst"===Object.keys(Object.assign({},r)).join("")}catch(e){return!1}}()?Object.assign:function(e,t){for(var n,i,a=function(e){if(null==e)throw new TypeError("Object.assign cannot be called with null or undefined");return Object(e)}(e),u=1;uM.length&&M.push(e)}function L(e,t,n){return null==e?0:function e(t,n,r,l){var a=typeof t;"undefined"!==a&&"boolean"!==a||(t=null);var u=!1;if(null===t)u=!0;else switch(a){case"string":case"number":u=!0;break;case"object":switch(t.$$typeof){case o:case i:u=!0}}if(u)return r(l,t,""===n?"."+I(t,0):n),1;if(u=0,n=""===n?".":n+":",Array.isArray(t))for(var c=0;cthis.eventPool.length&&this.eventPool.push(e)}function fe(e){e.eventPool=[],e.getPooled=ce,e.release=se}l(ue.prototype,{preventDefault:function(){this.defaultPrevented=!0;var e=this.nativeEvent;e&&(e.preventDefault?e.preventDefault():"unknown"!=typeof e.returnValue&&(e.returnValue=!1),this.isDefaultPrevented=ie)},stopPropagation:function(){var e=this.nativeEvent;e&&(e.stopPropagation?e.stopPropagation():"unknown"!=typeof e.cancelBubble&&(e.cancelBubble=!0),this.isPropagationStopped=ie)},persist:function(){this.isPersistent=ie},isPersistent:ae,destructor:function(){var e,t=this.constructor.Interface;for(e in t)this[e]=null;this.nativeEvent=this._targetInst=this.dispatchConfig=null,this.isPropagationStopped=this.isDefaultPrevented=ae,this._dispatchInstances=this._dispatchListeners=null}}),ue.Interface={type:null,target:null,currentTarget:function(){return null},eventPhase:null,bubbles:null,cancelable:null,timeStamp:function(e){return e.timeStamp||Date.now()},defaultPrevented:null,isTrusted:null},ue.extend=function(e){function t(){}function n(){return r.apply(this,arguments)}var r=this;t.prototype=r.prototype;var o=new t;return l(o,n.prototype),n.prototype=o,n.prototype.constructor=n,n.Interface=l({},r.Interface,e),n.extend=r.extend,fe(n),n},fe(ue);var de=ue.extend({data:null}),pe=ue.extend({data:null}),me=[9,13,27,32],he=q&&"CompositionEvent"in window,ve=null;q&&"documentMode"in document&&(ve=document.documentMode);var ye=q&&"TextEvent"in window&&!ve,ge=q&&(!he||ve&&8=ve),be=String.fromCharCode(32),ke={beforeInput:{phasedRegistrationNames:{bubbled:"onBeforeInput",captured:"onBeforeInputCapture"},dependencies:["compositionend","keypress","textInput","paste"]},compositionEnd:{phasedRegistrationNames:{bubbled:"onCompositionEnd",captured:"onCompositionEndCapture"},dependencies:"blur compositionend keydown keypress keyup mousedown".split(" ")},compositionStart:{phasedRegistrationNames:{bubbled:"onCompositionStart",captured:"onCompositionStartCapture"},dependencies:"blur compositionstart keydown keypress keyup mousedown".split(" ")},compositionUpdate:{phasedRegistrationNames:{bubbled:"onCompositionUpdate",captured:"onCompositionUpdateCapture"},dependencies:"blur compositionupdate keydown keypress keyup mousedown".split(" ")}},xe=!1;function we(e,t){switch(e){case"keyup":return-1!==me.indexOf(t.keyCode);case"keydown":return 229!==t.keyCode;case"keypress":case"mousedown":case"blur":return!0;default:return!1}}function Te(e){return"object"==typeof(e=e.detail)&&"data"in e?e.data:null}var Ee=!1;var Se={eventTypes:ke,extractEvents:function(e,t,n,r){var l=void 0,o=void 0;if(he)e:{switch(e){case"compositionstart":l=ke.compositionStart;break e;case"compositionend":l=ke.compositionEnd;break e;case"compositionupdate":l=ke.compositionUpdate;break e}l=void 0}else Ee?we(e,n)&&(l=ke.compositionEnd):"keydown"===e&&229===n.keyCode&&(l=ke.compositionStart);return l?(ge&&"ko"!==n.locale&&(Ee||l!==ke.compositionStart?l===ke.compositionEnd&&Ee&&(o=oe()):(re="value"in(ne=r)?ne.value:ne.textContent,Ee=!0)),l=de.getPooled(l,t,n,r),o?l.data=o:null!==(o=Te(n))&&(l.data=o),B(l),o=l):o=null,(e=ye?function(e,t){switch(e){case"compositionend":return Te(t);case"keypress":return 32!==t.which?null:(xe=!0,be);case"textInput":return(e=t.data)===be&&xe?null:e;default:return null}}(e,n):function(e,t){if(Ee)return"compositionend"===e||!he&&we(e,t)?(e=oe(),le=re=ne=null,Ee=!1,e):null;switch(e){case"paste":return null;case"keypress":if(!(t.ctrlKey||t.altKey||t.metaKey)||t.ctrlKey&&t.altKey){if(t.char&&1