Changing front

This commit is contained in:
ewandor committed 2023-01-16 17:49:38 +01:00
1 parent 0b8a93b256
commit 4fe4be7730
48586 files changed
+4725790 -17464

No files matched your search

+16
View File
@@ -0,0 +1,16 @@
# Changelog
## [1.5.0] - 2020-01-16
### Notable changes:
- Recreated build tools using Rollup
- Updated all dependencies to its latest versions
- Switched from Travis CI to GitHub Actions
- Added Dependabot to keep our dependencies up-to-date
- Fixed RTL support (#744, #689, #750)
- Fixed `shouldBeConsumedByChild` logic in `mouse-wheel.js` (#841)
- Improved compatibility with parent class (#839)
- Added missing properties in types definition (#808)
- Added support for fractional size of scrolled element (#837)
- Added support for touch devices (#829, #867)
- Added dragging support for mobile devices (#811)
+19
View File
@@ -0,0 +1,19 @@
The MIT License (MIT) Copyright (c) 2012-2019 Hyunje Jun, MDBootstrap.com and other contributors
Permission is hereby granted, free of charge, to any person obtaining a copy of
this software and associated documentation files (the "Software"), to deal in
the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
of the Software, and to permit persons to whom the Software is furnished to do
so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
+392
View File
@@ -0,0 +1,392 @@
<p align="center">
<a href="https://mdbootstrap.com/docs/jquery/getting-started/download/?utm_source=GitHub&utm_medium=PerfectScrollbar">
<img src="https://mdbootstrap.com/img/Marketing/general/logo/medium/mdb-r.png">
</a>
</p>
<h1 align="center">perfect-scrollbar</h1>
<p align="center">Minimalistic but perfect custom scrollbar plugin<p>
<p align="center">
<a href="https://npmcharts.com/compare/perfect-scrollbar?minimal=true"><img src="https://img.shields.io/npm/dm/perfect-scrollbar.svg" alt="Downloads"></a>
<a href="https://github.com/mdbootstrap/bootstrap-material-design/blob/master/License.pdf"><img src="https://img.shields.io/badge/license-MIT-green.svg" alt="License"></a>
<a href="https://badge.fury.io/js/perfect-scrollbar"><img src="https://badge.fury.io/js/perfect-scrollbar.svg" alt="npm"></a>
<a href="https://twitter.com/intent/tweet/?text=Thanks+@mdbootstrap+for+maintaining+amazing+and+free+Perfect+Scrollbar+Plugin%20https://mdbootstrap.com/freebies/perfect-scrollbar/&hashtags=javascript,code,webdesign,github"><img src="https://img.shields.io/twitter/url/http/shields.io.svg?style=social"></a>
</p>
## [Official documentation](https://mdbootstrap.com/freebies/perfect-scrollbar/?utm_source=GitHub&utm_medium=PerfectScrollbar)
***The official documentation can be found [here](https://mdbootstrap.com/freebies/perfect-scrollbar/?utm_source=GitHub&utm_medium=PerfectScrollbar).***
***To read documentation for versions < 1.0, please visit [`v0.8.1`](https://github.com/mdbootstrap/perfect-scrollbar/tree/0.8.1).***
________
## Why perfect-scrollbar?
perfect-scrollbar is minimalistic but *perfect* (for us, and maybe for most
developers) scrollbar plugin.
* No change on design layout
* No manipulation on DOM tree
* Use plain `scrollTop` and `scrollLeft`
* Scrollbar style is fully customizable
* Efficient update on layout change
We hope you will love it!
## Live preview
Check out the [Live Preview](https://mdbootstrap.com/snippets/jquery/filipkapusta/765760/?utm_source=GitHub&utm_medium=PerfectScrollbar) snippet. You can fork it right away for testing and experimenting purposes.
## More useful plugins
***You'll find some example plugins below, you can explore all of them [here](https://mdbootstrap.com/plugins/jquery/?utm_source=GitHub&utm_medium=PerfectScrollbar)***
[Datatable Plugin](https://mdbootstrap.com/docs/jquery/tables/datatables/?utm_source=GitHub&utm_medium=PerfectScrollbar)| [Treeview Plugin](https://mdbootstrap.com/plugins/jquery/treeview/?utm_source=GitHub&utm_medium=PerfectScrollbar)| [Filter Plugin](https://mdbootstrap.com/plugins/jquery/filter/?utm_source=GitHub&utm_medium=PerfectScrollbar)
------------ | ------------- | -------------
<a href="https://mdbootstrap.com/docs/jquery/tables/datatables/?utm_source=GitHub&utm_medium=PerfectScrollbar"><img src="https://mdbootstrap.com/img/Marketing/products/jquery/plugins/datatable.jpg" alt="Filter Plugin"></a> | <a href="https://mdbootstrap.com/plugins/jquery/treeview/?utm_source=GitHub&utm_medium=PerfectScrollbar"><img src="https://mdbootstrap.com/img/Marketing/products/jquery/plugins/treeview.jpg" alt="Filter Plugin"></a> | <a href="https://mdbootstrap.com/plugins/jquery/filter/?utm_source=GitHub&utm_medium=PerfectScrollbar"><img src="https://mdbootstrap.com/img/Marketing/products/jquery/plugins/filter.jpg" alt="Filter Plugin"></a>
_________
## Table of Contents
* [Install](#install)
* [Before using perfect-scrollbar](#before-using-perfect-scrollbar)
* [Caveats](#caveats)
* [How to use](#how-to-use)
* [Options](#options)
* [Events](#events)
* [Helpdesk](#helpdesk)
* [IE Support](#ie-support)
* [License](#license)
* [Related resources](#related-resources)
* [Social media](#social-media)
## Install
#### Download now
You can manually download perfect-scrollbar [here](https://mdbootstrap.com/freebies/perfect-scrollbar/?utm_source=GitHub&utm_medium=PerfectScrollbar).
#### npm
You can install and use perfect-scrollbar with npm. It's registered
as [perfect-scrollbar](https://www.npmjs.com/package/perfect-scrollbar).
```
$ npm install perfect-scrollbar
```
#### From sources
If you want to use the development version of the plugin, build from source
manually. The development version may be unstable.
```
$ git clone https://github.com/mdbootstrap/perfect-scrollbar.git
$ cd perfect-scrollbar
$ npm install
$ npm run build
```
#### Unofficial sources
Sources not mentioned above are not maintained officially. If there are issues
of the following sources, please ask and resolve in each repository.
## Before using perfect-scrollbar
The following requirements should meet.
* the container must have a `position` style.
* the container must be a normal container element.
The following requirements are included in the basic CSS, but please keep in
mind when you'd like to change the CSS files.
* the container must have an `overflow: hidden` css style.
* the scrollbar's position must be `absolute`.
* the scrollbar-x must have `bottom` or `top`, and the scrollbar-y must have
`right` or `left`.
Finally, scroll hooking is generally considered as a bad practice, and
perfect-scrollbar should be used carefully. Unless custom scroll is really
needed, using browser-native scroll is always recommended.
## Caveats
perfect-scrollbar emulates some scrolls, but not all of the kinds. It also *does not* work
in some situations. You can find these cases in [Caveats](https://github.com/mdbootstrap/perfect-scrollbar/wiki/Caveats).
Basically, items listed in the caveats are hacky to implement and may not be
implemented in the future. If the features are really needed, please consider
using browser-native scroll.
## How to use
First of all, please check if the container element meets the requirements and
the main CSS is imported.
```html
<style>
#container {
position: relative;
width: 600px;
height: 400px;
}
</style>
<link rel="stylesheet" href="css/perfect-scrollbar.css">
```
Import via ES modules:
```js
import PerfectScrollbar from 'perfect-scrollbar';
```
Or in browser:
```html
<script src="dist/perfect-scrollbar.js"></script>
```
To initialise:
```js
const container = document.querySelector('#container');
const ps = new PerfectScrollbar(container);
// or just with selector string
const ps = new PerfectScrollbar('#container');
```
It can be initialised with [options](#options).
```js
const ps = new PerfectScrollbar('#container', {
wheelSpeed: 2,
wheelPropagation: true,
minScrollbarLength: 20
});
```
If the size of your container or content changes, call `update`.
```js
ps.update();
```
If you want to destroy the scrollbar, use `destroy`.
```js
ps.destroy();
ps = null; // to make sure garbages are collected
```
If you want to scroll to somewhere, just update `scrollTop`.
```js
const container = document.querySelector('#container');
container.scrollTop = 0;
```
You can also get information about how to use the plugin from code in [`examples/`](examples).
## Options
### `handlers {String[]}`
It is a list of handlers to scroll the element.
**Default**: `['click-rail', 'drag-thumb', 'keyboard', 'wheel', 'touch']`
### `wheelSpeed {Number}`
The scroll speed applied to mousewheel event.
**Default**: `1`
### `wheelPropagation {Boolean}`
If this option is true, when the scroll reaches the end of the side, mousewheel
event will be propagated to parent element.
**Default**: `false`
### `swipeEasing {Boolean}`
If this option is true, swipe scrolling will be eased.
**Default**: `true`
### `minScrollbarLength {Number?}`
When set to an integer value, the thumb part of the scrollbar will not shrink
below that number of pixels.
**Default**: `null`
### `maxScrollbarLength {Number?}`
When set to an integer value, the thumb part of the scrollbar will not expand
over that number of pixels.
**Default**: `null`
### `scrollingThreshold {Number}`
This sets threshold for `ps--scrolling-x` and `ps--scrolling-y` classes to
remain. In the default CSS, they make scrollbars shown regardless of hover
state. The unit is millisecond.
**Default**: `1000`
### `useBothWheelAxes {Boolean}`
When set to true, and only one (vertical or horizontal) scrollbar is visible
then both vertical and horizontal scrolling will affect the scrollbar.
**Default**: `false`
### `suppressScrollX {Boolean}`
When set to true, the scrollbar in X-axis will not be available, regardless of
the content width.
**Default**: `false`
### `suppressScrollY {Boolean}`
When set to true, the scroll bar in Y-axis will not be available, regardless of
the content height.
**Default**: `false`
### `scrollXMarginOffset {Number}`
The number of pixels the content width can surpass the container width without
enabling the X-axis scroll bar. Allows some "wiggle room" or "offset break", so
that X-axis scroll bar is not enabled just because of a few pixels.
**Default**: `0`
### `scrollYMarginOffset {Number}`
The number of pixels the content height can surpass the container height without
enabling the Y-axis scroll bar. Allows some "wiggle room" or "offset break", so
that Y-axis scroll bar is not enabled just because of a few pixels.
**Default**: `0`
## Events
perfect-scrollbar dispatches custom events.
```js
container.addEventListener('ps-scroll-x', () => ...);
```
### `ps-scroll-y`
This event fires when the y-axis is scrolled in either direction.
### `ps-scroll-x`
This event fires when the x-axis is scrolled in either direction.
### `ps-scroll-up`
This event fires when scrolling upwards.
### `ps-scroll-down`
This event fires when scrolling downwards.
### `ps-scroll-left`
This event fires when scrolling to the left.
### `ps-scroll-right`
This event fires when scrolling to the right.
### `ps-y-reach-start`
This event fires when scrolling reaches the start of the y-axis.
### `ps-y-reach-end`
This event fires when scrolling reaches the end of the y-axis (useful for
infinite scroll).
### `ps-x-reach-start`
This event fires when scrolling reaches the start of the x-axis.
### `ps-x-reach-end`
This event fires when scrolling reaches the end of the x-axis.
You can also watch the reach state via the `reach` property.
```js
const ps = new PerfectScrollbar(...);
console.log(ps.reach.x); // => 'start' or 'end' or null
console.log(ps.reach.y); // => 'start' or 'end' or null
```
## Helpdesk
If you have any idea to improve this project or any problem using this, please
feel free to upload an [issue](https://github.com/mdbootstrap/perfect-scrollbar/issues).
For common problems, there is a [FAQ](https://github.com/mdbootstrap/perfect-scrollbar/wiki/FAQ) wiki
page. Please check the page before uploading an issue.
Also, the project is not actively maintained. No maintainer is paid, and most of
us are busy on our professional or personal works. Please understand that it may
take a while for an issue to be resolved. Uploading a PR would be the fastest
way to fix an issue.
## IE Support
The plugin is developed to work in modern MS browsers including Edge and IE11,
but may have some issues in IE11 mainly because of IE rendering bug concerning
sync update on scroll properties. The problem is mentioned in
[Caveats](https://github.com/mdbootstrap/perfect-scrollbar/wiki/Caveats) too.
IE<11 is not supported, and patches to fix problems in IE<=10 will not be
accepted. When old IEs should be supported, please fork the project and make
modification locally.
## License
[MIT](LICENSE)
## Related resources
- [Material Scrollbar](https://mdbootstrap.com/docs/jquery/javascript/scroll/?utm_source=GitHub&utm_medium=PerfectScrollbar)
- [Table scroll](https://mdbootstrap.com/docs/jquery/tables/scroll/?utm_source=GitHub&utm_medium=PerfectScrollbar)
- [Full screen scroller](https://mdbootstrap.com/plugins/jquery/screen-scroller/?utm_source=GitHub&utm_medium=PerfectScrollbar)
- [Scrollspy](https://mdbootstrap.com/docs/jquery/navigation/scrollspy/?utm_source=GitHub&utm_medium=PerfectScrollbar)
## Social Media
- [Twitter](https://twitter.com/MDBootstrap)
- [Facebook](https://www.facebook.com/mdbootstrap)
- [Pinterest](https://pl.pinterest.com/mdbootstrap)
- [Dribbble](https://dribbble.com/mdbootstrap)
- [LinkedIn](https://www.linkedin.com/company/material-design-for-bootstrap)
- [YouTube](https://www.youtube.com/channel/UC5CF7mLQZhvx8O5GODZAhdA)
## MDB PRO
- [Material Design for Bootstrap PRO](https://mdbootstrap.com/products/jquery-ui-kit/?utm_source=GitHub&utm_medium=PerfectScrollbar)
+116
View File
@@ -0,0 +1,116 @@
/*
* Container style
*/
.ps {
overflow: hidden !important;
overflow-anchor: none;
-ms-overflow-style: none;
touch-action: auto;
-ms-touch-action: auto;
}
/*
* Scrollbar rail styles
*/
.ps__rail-x {
display: none;
opacity: 0;
transition: background-color .2s linear, opacity .2s linear;
-webkit-transition: background-color .2s linear, opacity .2s linear;
height: 15px;
/* there must be 'bottom' or 'top' for ps__rail-x */
bottom: 0px;
/* please don't change 'position' */
position: absolute;
}
.ps__rail-y {
display: none;
opacity: 0;
transition: background-color .2s linear, opacity .2s linear;
-webkit-transition: background-color .2s linear, opacity .2s linear;
width: 15px;
/* there must be 'right' or 'left' for ps__rail-y */
right: 0;
/* please don't change 'position' */
position: absolute;
}
.ps--active-x > .ps__rail-x,
.ps--active-y > .ps__rail-y {
display: block;
background-color: transparent;
}
.ps:hover > .ps__rail-x,
.ps:hover > .ps__rail-y,
.ps--focus > .ps__rail-x,
.ps--focus > .ps__rail-y,
.ps--scrolling-x > .ps__rail-x,
.ps--scrolling-y > .ps__rail-y {
opacity: 0.6;
}
.ps .ps__rail-x:hover,
.ps .ps__rail-y:hover,
.ps .ps__rail-x:focus,
.ps .ps__rail-y:focus,
.ps .ps__rail-x.ps--clicking,
.ps .ps__rail-y.ps--clicking {
background-color: #eee;
opacity: 0.9;
}
/*
* Scrollbar thumb styles
*/
.ps__thumb-x {
background-color: #aaa;
border-radius: 6px;
transition: background-color .2s linear, height .2s ease-in-out;
-webkit-transition: background-color .2s linear, height .2s ease-in-out;
height: 6px;
/* there must be 'bottom' for ps__thumb-x */
bottom: 2px;
/* please don't change 'position' */
position: absolute;
}
.ps__thumb-y {
background-color: #aaa;
border-radius: 6px;
transition: background-color .2s linear, width .2s ease-in-out;
-webkit-transition: background-color .2s linear, width .2s ease-in-out;
width: 6px;
/* there must be 'right' for ps__thumb-y */
right: 2px;
/* please don't change 'position' */
position: absolute;
}
.ps__rail-x:hover > .ps__thumb-x,
.ps__rail-x:focus > .ps__thumb-x,
.ps__rail-x.ps--clicking .ps__thumb-x {
background-color: #999;
height: 11px;
}
.ps__rail-y:hover > .ps__thumb-y,
.ps__rail-y:focus > .ps__thumb-y,
.ps__rail-y.ps--clicking .ps__thumb-y {
background-color: #999;
width: 11px;
}
/* MS supports */
@supports (-ms-overflow-style: none) {
.ps {
overflow: auto !important;
}
}
@media screen and (-ms-high-contrast: active), (-ms-high-contrast: none) {
.ps {
overflow: auto !important;
}
}
File diff suppressed because it is too large. Load diff
@@ -0,0 +1 @@
{"version":3,"file":"perfect-scrollbar.common.js","sources":["../src/lib/css.js","../src/lib/dom.js","../src/lib/class-names.js","../src/lib/event-manager.js","../src/process-scroll-diff.js","../src/lib/util.js","../src/update-geometry.js","../src/handlers/click-rail.js","../src/handlers/drag-thumb.js","../src/handlers/keyboard.js","../src/handlers/mouse-wheel.js","../src/handlers/touch.js","../src/index.js"],"sourcesContent":["export function get(element) {\n return getComputedStyle(element);\n}\n\nexport function set(element, obj) {\n for (const key in obj) {\n let val = obj[key];\n if (typeof val === 'number') {\n val = `${val}px`;\n }\n element.style[key] = val;\n }\n return element;\n}\n","export function div(className) {\n const div = document.createElement('div');\n div.className = className;\n return div;\n}\n\nconst elMatches =\n typeof Element !== 'undefined' &&\n (Element.prototype.matches ||\n Element.prototype.webkitMatchesSelector ||\n Element.prototype.mozMatchesSelector ||\n Element.prototype.msMatchesSelector);\n\nexport function matches(element, query) {\n if (!elMatches) {\n throw new Error('No element matching method supported');\n }\n\n return elMatches.call(element, query);\n}\n\nexport function remove(element) {\n if (element.remove) {\n element.remove();\n } else {\n if (element.parentNode) {\n element.parentNode.removeChild(element);\n }\n }\n}\n\nexport function queryChildren(element, selector) {\n return Array.prototype.filter.call(element.children, child =>\n matches(child, selector)\n );\n}\n","const cls = {\n main: 'ps',\n rtl: 'ps__rtl',\n element: {\n thumb: x => `ps__thumb-${x}`,\n rail: x => `ps__rail-${x}`,\n consuming: 'ps__child--consume',\n },\n state: {\n focus: 'ps--focus',\n clicking: 'ps--clicking',\n active: x => `ps--active-${x}`,\n scrolling: x => `ps--scrolling-${x}`,\n },\n};\n\nexport default cls;\n\n/*\n * Helper methods\n */\nconst scrollingClassTimeout = { x: null, y: null };\n\nexport function addScrollingClass(i, x) {\n const classList = i.element.classList;\n const className = cls.state.scrolling(x);\n\n if (classList.contains(className)) {\n clearTimeout(scrollingClassTimeout[x]);\n } else {\n classList.add(className);\n }\n}\n\nexport function removeScrollingClass(i, x) {\n scrollingClassTimeout[x] = setTimeout(\n () => i.isAlive && i.element.classList.remove(cls.state.scrolling(x)),\n i.settings.scrollingThreshold\n );\n}\n\nexport function setScrollingClassInstantly(i, x) {\n addScrollingClass(i, x);\n removeScrollingClass(i, x);\n}\n","class EventElement {\n constructor(element) {\n this.element = element;\n this.handlers = {};\n }\n\n bind(eventName, handler) {\n if (typeof this.handlers[eventName] === 'undefined') {\n this.handlers[eventName] = [];\n }\n this.handlers[eventName].push(handler);\n this.element.addEventListener(eventName, handler, false);\n }\n\n unbind(eventName, target) {\n this.handlers[eventName] = this.handlers[eventName].filter(handler => {\n if (target && handler !== target) {\n return true;\n }\n this.element.removeEventListener(eventName, handler, false);\n return false;\n });\n }\n\n unbindAll() {\n for (const name in this.handlers) {\n this.unbind(name);\n }\n }\n\n get isEmpty() {\n return Object.keys(this.handlers).every(\n key => this.handlers[key].length === 0\n );\n }\n}\n\nexport default class EventManager {\n constructor() {\n this.eventElements = [];\n }\n\n eventElement(element) {\n let ee = this.eventElements.filter(ee => ee.element === element)[0];\n if (!ee) {\n ee = new EventElement(element);\n this.eventElements.push(ee);\n }\n return ee;\n }\n\n bind(element, eventName, handler) {\n this.eventElement(element).bind(eventName, handler);\n }\n\n unbind(element, eventName, handler) {\n const ee = this.eventElement(element);\n ee.unbind(eventName, handler);\n\n if (ee.isEmpty) {\n // remove\n this.eventElements.splice(this.eventElements.indexOf(ee), 1);\n }\n }\n\n unbindAll() {\n this.eventElements.forEach(e => e.unbindAll());\n this.eventElements = [];\n }\n\n once(element, eventName, handler) {\n const ee = this.eventElement(element);\n const onceHandler = evt => {\n ee.unbind(eventName, onceHandler);\n handler(evt);\n };\n ee.bind(eventName, onceHandler);\n }\n}\n","import { setScrollingClassInstantly } from './lib/class-names';\n\nfunction createEvent(name) {\n if (typeof window.CustomEvent === 'function') {\n return new CustomEvent(name);\n } else {\n const evt = document.createEvent('CustomEvent');\n evt.initCustomEvent(name, false, false, undefined);\n return evt;\n }\n}\n\nexport default function(\n i,\n axis,\n diff,\n useScrollingClass = true,\n forceFireReachEvent = false\n) {\n let fields;\n ifLine truncated
File diff suppressed because it is too large. Load diff
@@ -0,0 +1 @@
{"version":3,"file":"perfect-scrollbar.esm.js","sources":["../src/lib/css.js","../src/lib/dom.js","../src/lib/class-names.js","../src/lib/event-manager.js","../src/process-scroll-diff.js","../src/lib/util.js","../src/update-geometry.js","../src/handlers/click-rail.js","../src/handlers/drag-thumb.js","../src/handlers/keyboard.js","../src/handlers/mouse-wheel.js","../src/handlers/touch.js","../src/index.js"],"sourcesContent":["export function get(element) {\n return getComputedStyle(element);\n}\n\nexport function set(element, obj) {\n for (const key in obj) {\n let val = obj[key];\n if (typeof val === 'number') {\n val = `${val}px`;\n }\n element.style[key] = val;\n }\n return element;\n}\n","export function div(className) {\n const div = document.createElement('div');\n div.className = className;\n return div;\n}\n\nconst elMatches =\n typeof Element !== 'undefined' &&\n (Element.prototype.matches ||\n Element.prototype.webkitMatchesSelector ||\n Element.prototype.mozMatchesSelector ||\n Element.prototype.msMatchesSelector);\n\nexport function matches(element, query) {\n if (!elMatches) {\n throw new Error('No element matching method supported');\n }\n\n return elMatches.call(element, query);\n}\n\nexport function remove(element) {\n if (element.remove) {\n element.remove();\n } else {\n if (element.parentNode) {\n element.parentNode.removeChild(element);\n }\n }\n}\n\nexport function queryChildren(element, selector) {\n return Array.prototype.filter.call(element.children, child =>\n matches(child, selector)\n );\n}\n","const cls = {\n main: 'ps',\n rtl: 'ps__rtl',\n element: {\n thumb: x => `ps__thumb-${x}`,\n rail: x => `ps__rail-${x}`,\n consuming: 'ps__child--consume',\n },\n state: {\n focus: 'ps--focus',\n clicking: 'ps--clicking',\n active: x => `ps--active-${x}`,\n scrolling: x => `ps--scrolling-${x}`,\n },\n};\n\nexport default cls;\n\n/*\n * Helper methods\n */\nconst scrollingClassTimeout = { x: null, y: null };\n\nexport function addScrollingClass(i, x) {\n const classList = i.element.classList;\n const className = cls.state.scrolling(x);\n\n if (classList.contains(className)) {\n clearTimeout(scrollingClassTimeout[x]);\n } else {\n classList.add(className);\n }\n}\n\nexport function removeScrollingClass(i, x) {\n scrollingClassTimeout[x] = setTimeout(\n () => i.isAlive && i.element.classList.remove(cls.state.scrolling(x)),\n i.settings.scrollingThreshold\n );\n}\n\nexport function setScrollingClassInstantly(i, x) {\n addScrollingClass(i, x);\n removeScrollingClass(i, x);\n}\n","class EventElement {\n constructor(element) {\n this.element = element;\n this.handlers = {};\n }\n\n bind(eventName, handler) {\n if (typeof this.handlers[eventName] === 'undefined') {\n this.handlers[eventName] = [];\n }\n this.handlers[eventName].push(handler);\n this.element.addEventListener(eventName, handler, false);\n }\n\n unbind(eventName, target) {\n this.handlers[eventName] = this.handlers[eventName].filter(handler => {\n if (target && handler !== target) {\n return true;\n }\n this.element.removeEventListener(eventName, handler, false);\n return false;\n });\n }\n\n unbindAll() {\n for (const name in this.handlers) {\n this.unbind(name);\n }\n }\n\n get isEmpty() {\n return Object.keys(this.handlers).every(\n key => this.handlers[key].length === 0\n );\n }\n}\n\nexport default class EventManager {\n constructor() {\n this.eventElements = [];\n }\n\n eventElement(element) {\n let ee = this.eventElements.filter(ee => ee.element === element)[0];\n if (!ee) {\n ee = new EventElement(element);\n this.eventElements.push(ee);\n }\n return ee;\n }\n\n bind(element, eventName, handler) {\n this.eventElement(element).bind(eventName, handler);\n }\n\n unbind(element, eventName, handler) {\n const ee = this.eventElement(element);\n ee.unbind(eventName, handler);\n\n if (ee.isEmpty) {\n // remove\n this.eventElements.splice(this.eventElements.indexOf(ee), 1);\n }\n }\n\n unbindAll() {\n this.eventElements.forEach(e => e.unbindAll());\n this.eventElements = [];\n }\n\n once(element, eventName, handler) {\n const ee = this.eventElement(element);\n const onceHandler = evt => {\n ee.unbind(eventName, onceHandler);\n handler(evt);\n };\n ee.bind(eventName, onceHandler);\n }\n}\n","import { setScrollingClassInstantly } from './lib/class-names';\n\nfunction createEvent(name) {\n if (typeof window.CustomEvent === 'function') {\n return new CustomEvent(name);\n } else {\n const evt = document.createEvent('CustomEvent');\n evt.initCustomEvent(name, false, false, undefined);\n return evt;\n }\n}\n\nexport default function(\n i,\n axis,\n diff,\n useScrollingClass = true,\n forceFireReachEvent = false\n) {\n let fields;\n if (aLine truncated
File diff suppressed because it is too large. Load diff
@@ -0,0 +1 @@
{"version":3,"file":"perfect-scrollbar.js","sources":["../src/lib/css.js","../src/lib/dom.js","../src/lib/class-names.js","../src/lib/event-manager.js","../src/process-scroll-diff.js","../src/lib/util.js","../src/update-geometry.js","../src/handlers/click-rail.js","../src/handlers/drag-thumb.js","../src/handlers/keyboard.js","../src/handlers/mouse-wheel.js","../src/handlers/touch.js","../src/index.js"],"sourcesContent":["export function get(element) {\n return getComputedStyle(element);\n}\n\nexport function set(element, obj) {\n for (const key in obj) {\n let val = obj[key];\n if (typeof val === 'number') {\n val = `${val}px`;\n }\n element.style[key] = val;\n }\n return element;\n}\n","export function div(className) {\n const div = document.createElement('div');\n div.className = className;\n return div;\n}\n\nconst elMatches =\n typeof Element !== 'undefined' &&\n (Element.prototype.matches ||\n Element.prototype.webkitMatchesSelector ||\n Element.prototype.mozMatchesSelector ||\n Element.prototype.msMatchesSelector);\n\nexport function matches(element, query) {\n if (!elMatches) {\n throw new Error('No element matching method supported');\n }\n\n return elMatches.call(element, query);\n}\n\nexport function remove(element) {\n if (element.remove) {\n element.remove();\n } else {\n if (element.parentNode) {\n element.parentNode.removeChild(element);\n }\n }\n}\n\nexport function queryChildren(element, selector) {\n return Array.prototype.filter.call(element.children, child =>\n matches(child, selector)\n );\n}\n","const cls = {\n main: 'ps',\n rtl: 'ps__rtl',\n element: {\n thumb: x => `ps__thumb-${x}`,\n rail: x => `ps__rail-${x}`,\n consuming: 'ps__child--consume',\n },\n state: {\n focus: 'ps--focus',\n clicking: 'ps--clicking',\n active: x => `ps--active-${x}`,\n scrolling: x => `ps--scrolling-${x}`,\n },\n};\n\nexport default cls;\n\n/*\n * Helper methods\n */\nconst scrollingClassTimeout = { x: null, y: null };\n\nexport function addScrollingClass(i, x) {\n const classList = i.element.classList;\n const className = cls.state.scrolling(x);\n\n if (classList.contains(className)) {\n clearTimeout(scrollingClassTimeout[x]);\n } else {\n classList.add(className);\n }\n}\n\nexport function removeScrollingClass(i, x) {\n scrollingClassTimeout[x] = setTimeout(\n () => i.isAlive && i.element.classList.remove(cls.state.scrolling(x)),\n i.settings.scrollingThreshold\n );\n}\n\nexport function setScrollingClassInstantly(i, x) {\n addScrollingClass(i, x);\n removeScrollingClass(i, x);\n}\n","class EventElement {\n constructor(element) {\n this.element = element;\n this.handlers = {};\n }\n\n bind(eventName, handler) {\n if (typeof this.handlers[eventName] === 'undefined') {\n this.handlers[eventName] = [];\n }\n this.handlers[eventName].push(handler);\n this.element.addEventListener(eventName, handler, false);\n }\n\n unbind(eventName, target) {\n this.handlers[eventName] = this.handlers[eventName].filter(handler => {\n if (target && handler !== target) {\n return true;\n }\n this.element.removeEventListener(eventName, handler, false);\n return false;\n });\n }\n\n unbindAll() {\n for (const name in this.handlers) {\n this.unbind(name);\n }\n }\n\n get isEmpty() {\n return Object.keys(this.handlers).every(\n key => this.handlers[key].length === 0\n );\n }\n}\n\nexport default class EventManager {\n constructor() {\n this.eventElements = [];\n }\n\n eventElement(element) {\n let ee = this.eventElements.filter(ee => ee.element === element)[0];\n if (!ee) {\n ee = new EventElement(element);\n this.eventElements.push(ee);\n }\n return ee;\n }\n\n bind(element, eventName, handler) {\n this.eventElement(element).bind(eventName, handler);\n }\n\n unbind(element, eventName, handler) {\n const ee = this.eventElement(element);\n ee.unbind(eventName, handler);\n\n if (ee.isEmpty) {\n // remove\n this.eventElements.splice(this.eventElements.indexOf(ee), 1);\n }\n }\n\n unbindAll() {\n this.eventElements.forEach(e => e.unbindAll());\n this.eventElements = [];\n }\n\n once(element, eventName, handler) {\n const ee = this.eventElement(element);\n const onceHandler = evt => {\n ee.unbind(eventName, onceHandler);\n handler(evt);\n };\n ee.bind(eventName, onceHandler);\n }\n}\n","import { setScrollingClassInstantly } from './lib/class-names';\n\nfunction createEvent(name) {\n if (typeof window.CustomEvent === 'function') {\n return new CustomEvent(name);\n } else {\n const evt = document.createEvent('CustomEvent');\n evt.initCustomEvent(name, false, false, undefined);\n return evt;\n }\n}\n\nexport default function(\n i,\n axis,\n diff,\n useScrollingClass = true,\n forceFireReachEvent = false\n) {\n let fields;\n if (axis Line truncated
+20
View File
@@ -0,0 +1,20 @@
/*!
* perfect-scrollbar v1.5.0
* Copyright 2020 Hyunje Jun, MDBootstrap and Contributors
* Licensed under MIT
*/(function(a,b){"object"==typeof exports&&"undefined"!=typeof module?module.exports=b():"function"==typeof define&&define.amd?define(b):(a=a||self,a.PerfectScrollbar=b())})(this,function(){'use strict';var u=Math.abs,v=Math.floor;function a(a){return getComputedStyle(a)}function b(a,b){for(var c in b){var d=b[c];"number"==typeof d&&(d+="px"),a.style[c]=d}return a}function c(a){var b=document.createElement("div");return b.className=a,b}function d(a,b){if(!w)throw new Error("No element matching method supported");return w.call(a,b)}function e(a){a.remove?a.remove():a.parentNode&&a.parentNode.removeChild(a)}function f(a,b){return Array.prototype.filter.call(a.children,function(a){return d(a,b)})}function g(a,b){var c=a.element.classList,d=z.state.scrolling(b);c.contains(d)?clearTimeout(A[b]):c.add(d)}function h(a,b){A[b]=setTimeout(function(){return a.isAlive&&a.element.classList.remove(z.state.scrolling(b))},a.settings.scrollingThreshold)}function j(a,b){g(a,b),h(a,b)}function k(a){if("function"==typeof window.CustomEvent)return new CustomEvent(a);var b=document.createEvent("CustomEvent");return b.initCustomEvent(a,!1,!1,void 0),b}function l(a,b,c,d,e){void 0===d&&(d=!0),void 0===e&&(e=!1);var f;if("top"===b)f=["contentHeight","containerHeight","scrollTop","y","up","down"];else if("left"===b)f=["contentWidth","containerWidth","scrollLeft","x","left","right"];else throw new Error("A proper axis should be provided");m(a,c,f,d,e)}function m(a,b,c,d,e){var f=c[0],g=c[1],h=c[2],i=c[3],l=c[4],m=c[5];void 0===d&&(d=!0),void 0===e&&(e=!1);var n=a.element;// reset reach
a.reach[i]=null,1>n[h]&&(a.reach[i]="start"),n[h]>a[f]-a[g]-1&&(a.reach[i]="end"),b&&(n.dispatchEvent(k("ps-scroll-"+i)),0>b?n.dispatchEvent(k("ps-scroll-"+l)):0<b&&n.dispatchEvent(k("ps-scroll-"+m)),d&&j(a,i)),a.reach[i]&&(b||e)&&n.dispatchEvent(k("ps-"+i+"-reach-"+a.reach[i]))}function n(a){return parseInt(a,10)||0}function o(a){return d(a,"input,[contenteditable]")||d(a,"select,[contenteditable]")||d(a,"textarea,[contenteditable]")||d(a,"button,[contenteditable]")}function p(b){var c=a(b);return n(c.width)+n(c.paddingLeft)+n(c.paddingRight)+n(c.borderLeftWidth)+n(c.borderRightWidth)}function q(a){var b=Math.ceil,c=a.element,d=v(c.scrollTop),g=c.getBoundingClientRect();a.containerWidth=b(g.width),a.containerHeight=b(g.height),a.contentWidth=c.scrollWidth,a.contentHeight=c.scrollHeight,c.contains(a.scrollbarXRail)||(f(c,z.element.rail("x")).forEach(function(a){return e(a)}),c.appendChild(a.scrollbarXRail)),c.contains(a.scrollbarYRail)||(f(c,z.element.rail("y")).forEach(function(a){return e(a)}),c.appendChild(a.scrollbarYRail)),!a.settings.suppressScrollX&&a.containerWidth+a.settings.scrollXMarginOffset<a.contentWidth?(a.scrollbarXActive=!0,a.railXWidth=a.containerWidth-a.railXMarginWidth,a.railXRatio=a.containerWidth/a.railXWidth,a.scrollbarXWidth=r(a,n(a.railXWidth*a.containerWidth/a.contentWidth)),a.scrollbarXLeft=n((a.negativeScrollAdjustment+c.scrollLeft)*(a.railXWidth-a.scrollbarXWidth)/(a.contentWidth-a.containerWidth))):a.scrollbarXActive=!1,!a.settings.suppressScrollY&&a.containerHeight+a.settings.scrollYMarginOffset<a.contentHeight?(a.scrollbarYActive=!0,a.railYHeight=a.containerHeight-a.railYMarginHeight,a.railYRatio=a.containerHeight/a.railYHeight,a.scrollbarYHeight=r(a,n(a.railYHeight*a.containerHeight/a.contentHeight)),a.scrollbarYTop=n(d*(a.railYHeight-a.scrollbarYHeight)/(a.contentHeight-a.containerHeight))):a.scrollbarYActive=!1,a.scrollbarXLeft>=a.railXWidth-a.scrollbarXWidth&&(a.scrollbarXLeft=a.railXWidth-a.scrollbarXWidth),a.scrollbarYTop>=a.railYHeight-a.scrollbarYHeight&&(a.scrollbarYTop=a.railYHeight-a.scrollbarYHeight),s(c,a),a.scrollbarXActive?c.classList.add(z.state.active("x")):(c.classList.remove(z.state.active("x")),a.scrollbarXWidth=0,a.scrollbarXLeft=0,c.scrollLeft=!0===a.isRtl?a.contentWidth:0),a.scrollbarYActive?c.classList.add(z.state.active("y")):(c.classList.remove(z.state.active("y")),a.scrollbarYHeight=0,a.scrollbarYTop=0,c.scrollTop=0)}function r(a,b){var c=Math.min,d=Math.max;return a.settings.minScrollbarLength&&(b=d(b,a.settings.minScrollbarLength)),a.settings.maxScrollbarLength&&(b=c(b,a.settings.maxScrollbarLength)),b}function s(a,c){var d={width:c.railXWidth},e=v(a.scrollTop);d.left=c.isRtl?c.negativeScrollAdjustment+a.scrollLeft+c.containerWidth-c.contentWidth:a.scrollLeft,c.isScrollbarXUsingBottom?d.bottom=c.scrollbarXBottom-e:d.top=c.scrollbarXTop+e,b(c.scrollbarXRail,d);var f={top:e,height:c.railYHeight};c.isScrollbarYUsingRight?c.isRtl?f.right=c.contentWidth-(c.negativeScrollAdjustment+a.scrollLeft)-c.scrollbarYRight-c.scrollbarYOuterWidth-9:f.right=c.scrollbarYRight-a.scrollLeft:c.isRtl?f.left=c.negativeScrollAdjustment+a.scrollLeft+2*c.containerWidth-c.contentWidth-c.scrollbarYLeft-c.scrollbarYOuterWidth:f.left=c.scrollbarYLeft+a.scrollLeft,b(c.scrollbarYRail,f),b(c.scrollbarX,{left:c.scrollbarXLeft,width:c.scrollbarXWidth-c.railBorderXWidth}),b(c.scrollbarY,{top:c.scrollbarYTop,height:c.scrollbarYHeight-c.railBorderYWidth})}function t(a,b){function c(b){b.touches&&b.touches[0]&&(b[k]=b.touches[0].pageY),s[o]=t+v*(b[k]-u),g(a,p),q(a),b.stopPropagation(),b.preventDefault()}function d(){h(a,p),a[r].classList.remove(z.state.clicking),a.event.unbind(a.ownerDocument,"mousemove",c)}function f(b,e){t=s[o],e&&b.touches&&(b[k]=b.touches[0].pageY),u=b[k],v=(a[j]-a[i])/(a[l]-a[n]),e?a.event.bind(a.ownerDocument,"touchmove",c):(a.event.bind(a.ownerDocument,"mousemove",c),a.event.once(a.ownerDocument,"mouseup",d),b.preventDefault()),a[r].classList.add(z.state.clicking),b.stopPropagation()}var i=b[0],j=b[1],k=b[2],l=b[3],m=b[4],n=b[5],o=b[6],p=b[7],r=b[8],s=a.element,t=null,u=null,v=null;a.event.bind(a[m],"mousedown",function(a){f(a)}),a.event.bind(a[m],"touchstart",function(a){f(a,!0)})}var w="undefined"!=typeof Element&&(Element.prototype.matches||Element.prototype.webkitMatchesSelector||Element.prototype.mozMatchesSelector||Element.prototype.msMatchesSelector),z={main:"ps",rtl:"ps__rtl",element:{thumb:function(a){return"ps__thumb-"+a},rail:function(a){return"ps__rail-"+a},consuming:"ps__child--consume"},state:{focus:"ps--focus",clicking:"ps--clicking",active:function(a){return"ps--active-"+a},scrolling:function(a){return"ps--scrolling-"+a}}},A={x:null,y:null},B=function(a){this.element=a,this.handlers={}},C={isEmpty:{configurable:!0}};B.prototype.bind=function(a,b){"undefined"==typeof this.handlers[a]&&(this.handlers[a]=[]),this.handlers[a].push(b),this.element.addEventListener(a,b,!1)},B.prototype.unbind=function(a,b){var c=this;this.handlers[a]=this.handlers[a].fLine truncated
for(;e.shadowRoot;)e=e.shadowRoot.activeElement;if(o(e))return}var h=0,i=0;switch(d.which){case 37:h=d.metaKey?-a.contentWidth:d.altKey?-a.containerWidth:-30;break;case 38:i=d.metaKey?a.contentHeight:d.altKey?a.containerHeight:30;break;case 39:h=d.metaKey?a.contentWidth:d.altKey?a.containerWidth:30;break;case 40:i=d.metaKey?-a.contentHeight:d.altKey?-a.containerHeight:-30;break;case 32:i=d.shiftKey?a.containerHeight:-a.containerHeight;break;case 33:i=a.containerHeight;break;case 34:i=-a.containerHeight;break;case 36:i=a.contentHeight;break;case 35:i=-a.contentHeight;break;default:return;}a.settings.suppressScrollX&&0!==h||a.settings.suppressScrollY&&0!==i||(c.scrollTop-=i,c.scrollLeft+=h,q(a),b(h,i)&&d.preventDefault())}})},wheel:function(b){function c(a,c){var d,e=v(h.scrollTop),f=0===h.scrollTop,g=e+h.offsetHeight===h.scrollHeight,i=0===h.scrollLeft,j=h.scrollLeft+h.offsetWidth===h.scrollWidth;return d=u(c)>u(a)?f||g:i||j,!d||!b.settings.wheelPropagation}function d(a){var b=a.deltaX,c=-1*a.deltaY;return("undefined"==typeof b||"undefined"==typeof c)&&(b=-1*a.wheelDeltaX/6,c=a.wheelDeltaY/6),a.deltaMode&&1===a.deltaMode&&(b*=10,c*=10),b!==b&&c!==c/* NaN checks */&&(b=0,c=a.wheelDelta),a.shiftKey?[-c,-b]:[b,c]}function f(b,c,d){// FIXME: this is a workaround for <select> issue in FF and IE #571
if(!E.isWebKit&&h.querySelector("select:focus"))return!0;if(!h.contains(b))return!1;for(var e=b;e&&e!==h;){if(e.classList.contains(z.element.consuming))return!0;var f=a(e);// if deltaY && vertical scrollable
if(d&&f.overflowY.match(/(scroll|auto)/)){var g=e.scrollHeight-e.clientHeight;if(0<g&&(0<e.scrollTop&&0>d||e.scrollTop<g&&0<d))return!0}// if deltaX && horizontal scrollable
if(c&&f.overflowX.match(/(scroll|auto)/)){var i=e.scrollWidth-e.clientWidth;if(0<i&&(0<e.scrollLeft&&0>c||e.scrollLeft<i&&0<c))return!0}e=e.parentNode}return!1}function g(a){var e=d(a),g=e[0],i=e[1];if(!f(a.target,g,i)){var j=!1;b.settings.useBothWheelAxes?b.scrollbarYActive&&!b.scrollbarXActive?(i?h.scrollTop-=i*b.settings.wheelSpeed:h.scrollTop+=g*b.settings.wheelSpeed,j=!0):b.scrollbarXActive&&!b.scrollbarYActive&&(g?h.scrollLeft+=g*b.settings.wheelSpeed:h.scrollLeft-=i*b.settings.wheelSpeed,j=!0):(h.scrollTop-=i*b.settings.wheelSpeed,h.scrollLeft+=g*b.settings.wheelSpeed),q(b),j=j||c(g,i),j&&!a.ctrlKey&&(a.stopPropagation(),a.preventDefault())}}var h=b.element;"undefined"==typeof window.onwheel?"undefined"!=typeof window.onmousewheel&&b.event.bind(h,"mousewheel",g):b.event.bind(h,"wheel",g)},touch:function(b){function c(a,c){var d=v(l.scrollTop),e=l.scrollLeft,f=u(a),g=u(c);if(g>f){// user is perhaps trying to swipe up/down the page
if(0>c&&d===b.contentHeight-b.containerHeight||0<c&&0===d)// set prevent for mobile Chrome refresh
return 0===window.scrollY&&0<c&&E.isChrome;}else if(f>g&&(0>a&&e===b.contentWidth-b.containerWidth||0<a&&0===e))// user is perhaps trying to swipe left/right across the page
return!0;return!0}function d(a,c){l.scrollTop-=c,l.scrollLeft-=a,q(b)}function f(a){return a.targetTouches?a.targetTouches[0]:a}function g(a){return!(a.pointerType&&"pen"===a.pointerType&&0===a.buttons)&&(!!(a.targetTouches&&1===a.targetTouches.length)||!!(a.pointerType&&"mouse"!==a.pointerType&&a.pointerType!==a.MSPOINTER_TYPE_MOUSE))}function h(a){if(g(a)){var b=f(a);m.pageX=b.pageX,m.pageY=b.pageY,n=new Date().getTime(),null!==p&&clearInterval(p)}}function i(b,c,d){if(!l.contains(b))return!1;for(var e=b;e&&e!==l;){if(e.classList.contains(z.element.consuming))return!0;var f=a(e);// if deltaY && vertical scrollable
if(d&&f.overflowY.match(/(scroll|auto)/)){var g=e.scrollHeight-e.clientHeight;if(0<g&&(0<e.scrollTop&&0>d||e.scrollTop<g&&0<d))return!0}// if deltaX && horizontal scrollable
if(c&&f.overflowX.match(/(scroll|auto)/)){var h=e.scrollWidth-e.clientWidth;if(0<h&&(0<e.scrollLeft&&0>c||e.scrollLeft<h&&0<c))return!0}e=e.parentNode}return!1}function j(a){if(g(a)){var b=f(a),e={pageX:b.pageX,pageY:b.pageY},h=e.pageX-m.pageX,j=e.pageY-m.pageY;if(i(a.target,h,j))return;d(h,j),m=e;var k=new Date().getTime(),l=k-n;0<l&&(o.x=h/l,o.y=j/l,n=k),c(h,j)&&a.preventDefault()}}function k(){b.settings.swipeEasing&&(clearInterval(p),p=setInterval(function(){return b.isInitialized?void clearInterval(p):o.x||o.y?.01>u(o.x)&&.01>u(o.y)?void clearInterval(p):void(d(30*o.x,30*o.y),o.x*=.8,o.y*=.8):void clearInterval(p)},10))}if(E.supportsTouch||E.supportsIePointer){var l=b.element,m={},n=0,o={},p=null;E.supportsTouch?(b.event.bind(l,"touchstart",h),b.event.bind(l,"touchmove",j),b.event.bind(l,"touchend",k)):E.supportsIePointer&&(window.PointerEvent?(b.event.bind(l,"pointerdown",h),b.event.bind(l,"pointermove",j),b.event.bind(l,"pointerup",k)):window.MSPointerEvent&&(b.event.bind(l,"MSPointerDown",h),b.event.bind(l,"MSPointerMove",j),b.event.bind(l,"MSPointerUp",k)))}}},H=function(d,e){var f=this;if(void 0===e&&(e={}),"string"==typeof d&&(d=document.querySelector(d)),!d||!d.nodeName)throw new Error("no element is specified to initialize PerfectScrollbar");for(var g in this.element=d,d.classList.add(z.main),this.settings=F(),e)this.settings[g]=e[g];this.containerWidth=null,this.containerHeight=null,this.contentWidth=null,this.contentHeight=null;var h=function(){return d.classList.add(z.state.focus)},i=function(){return d.classList.remove(z.state.focus)};this.isRtl="rtl"===a(d).direction,!0===this.isRtl&&d.classList.add(z.rtl),this.isNegativeScroll=function(){var a=d.scrollLeft,b=null;return d.scrollLeft=-1,b=0>d.scrollLeft,d.scrollLeft=a,b}(),this.negativeScrollAdjustment=this.isNegativeScroll?d.scrollWidth-d.clientWidth:0,this.event=new D,this.ownerDocument=d.ownerDocument||document,this.scrollbarXRail=c(z.element.rail("x")),d.appendChild(this.scrollbarXRail),this.scrollbarX=c(z.element.thumb("x")),this.scrollbarXRail.appendChild(this.scrollbarX),this.scrollbarX.setAttribute("tabindex",0),this.event.bind(this.scrollbarX,"focus",h),this.event.bind(this.scrollbarX,"blur",i),this.scrollbarXActive=null,this.scrollbarXWidth=null,this.scrollbarXLeft=null;var j=a(this.scrollbarXRail);this.scrollbarXBottom=parseInt(j.bottom,10),isNaN(this.scrollbarXBottom)?(this.isScrollbarXUsingBottom=!1,this.scrollbarXTop=n(j.top)):this.isScrollbarXUsingBottom=!0,this.railBorderXWidth=n(j.borderLeftWidth)+n(j.borderRightWidth),b(this.scrollbarXRail,{display:"block"}),this.railXMarginWidth=n(j.marginLeft)+n(j.marginRight),b(this.scrollbarXRail,{display:""}),this.railXWidth=null,this.railXRatio=null,this.scrollbarYRail=c(z.element.rail("y")),d.appendChild(this.scrollbarYRail),this.scrollbarY=c(z.element.thumb("y")),this.scrollbarYRail.appendChild(this.scrollbarY),this.scrollbarY.setAttribute("tabindex",0),this.event.bind(this.scrollbarY,"focus",h),this.event.bind(this.scrollbarY,"blur",i),this.scrollbarYActive=null,this.scrollbarYHeight=null,this.scrollbarYTop=null;var k=a(this.scrollbarYRail);this.scrollbarYRight=parseInt(k.right,10),isNaN(this.scrollbarYRight)?(this.isScrollbarYUsingRight=!1,this.scrollbarYLeft=n(k.left)):this.isScrollbarYUsingRight=!0,this.scrollbarYOuterWidth=this.isRtl?p(this.scrollbarY):null,this.railBorderYWidth=n(k.borderTopWidth)+n(k.borderBottomWidth),b(this.scrollbarYRail,{display:"block"}),this.railYMarginHeight=n(k.marginTop)+n(k.marginBottom),b(this.scrollbarYRail,{display:""}),this.railYHeight=null,this.railYRatio=null,this.reach={x:0>=d.scrollLeft?"start":d.scrollLeft>=this.contentWidth-this.containerWidth?"end":null,y:0>=d.scrollTop?"start":d.scrollTop>=this.contentHeight-this.containerHeight?"end":null},this.isAlive=!0,this.settings.handlers.forEach(function(a){return G[a](f)}),this.lastScrollTop=v(d.scrollTop),this.lastScrollLeft=d.scrollLeft,this.event.bind(this.element,"scroll",function(a){return f.onScroll(a)}),q(this)};return H.prototype.update=function(){this.isAlive&&(// Recalcuate negative scrollLeft adjustment
// Recalculate rail margins
// Hide scrollbars not to affect scrollWidth and scrollHeight
this.negativeScrollAdjustment=this.isNegativeScroll?this.element.scrollWidth-this.element.clientWidth:0,b(this.scrollbarXRail,{display:"block"}),b(this.scrollbarYRail,{display:"block"}),this.railXMarginWidth=n(a(this.scrollbarXRail).marginLeft)+n(a(this.scrollbarXRail).marginRight),this.railYMarginHeight=n(a(this.scrollbarYRail).marginTop)+n(a(this.scrollbarYRail).marginBottom),b(this.scrollbarXRail,{display:"none"}),b(this.scrollbarYRail,{display:"none"}),q(this),l(this,"top",0,!1,!0),l(this,"left",0,!1,!0),b(this.scrollbarXRail,{display:""}),b(this.scrollbarYRail,{display:""}))},H.prototype.onScroll=function(){this.isAlive&&(q(this),l(this,"top",this.element.scrollTop-this.lastScrollTop),l(this,"left",this.element.scrollLeft-this.lastScrollLeft),this.lastScrollTop=v(this.element.scrollTop),this.lastScrollLeft=this.element.scrollLeft)},H.prototype.destroy=function(){this.isAlive&&(// unset elements
this.event.unbindAll(),e(this.scrollbarX),e(this.scrollbarY),e(this.scrollbarXRail),e(this.scrollbarYRail),this.removePsClasses(),this.element=null,this.scrollbarX=null,this.scrollbarY=null,this.scrollbarXRail=null,this.scrollbarYRail=null,this.isAlive=!1)},H.prototype.removePsClasses=function(){this.element.className=this.element.className.split(" ").filter(function(a){return!a.match(/^ps([-_].+|)$/)}).join(" ")},H});
//# sourceMappingURL=perfect-scrollbar.min.js.map
@@ -0,0 +1 @@
{"version":3,"file":"perfect-scrollbar.min.js","sources":["../src/handlers/mouse-wheel.js","../src/update-geometry.js","../src/lib/css.js","../src/lib/dom.js","../src/lib/class-names.js","../src/process-scroll-diff.js","../src/lib/util.js","../src/handlers/drag-thumb.js","../src/lib/event-manager.js","../src/index.js","../src/handlers/click-rail.js","../src/handlers/keyboard.js","../src/handlers/touch.js"],"sourcesContent":["import * as CSS from '../lib/css';\nimport cls from '../lib/class-names';\nimport updateGeometry from '../update-geometry';\nimport { env } from '../lib/util';\n\nexport default function(i) {\n const element = i.element;\n\n let shouldPrevent = false;\n\n function shouldPreventDefault(deltaX, deltaY) {\n const roundedScrollTop = Math.floor(element.scrollTop);\n const isTop = element.scrollTop === 0;\n const isBottom =\n roundedScrollTop + element.offsetHeight === element.scrollHeight;\n const isLeft = element.scrollLeft === 0;\n const isRight =\n element.scrollLeft + element.offsetWidth === element.scrollWidth;\n\n let hitsBound;\n\n // pick axis with primary direction\n if (Math.abs(deltaY) > Math.abs(deltaX)) {\n hitsBound = isTop || isBottom;\n } else {\n hitsBound = isLeft || isRight;\n }\n\n return hitsBound ? !i.settings.wheelPropagation : true;\n }\n\n function getDeltaFromEvent(e) {\n let deltaX = e.deltaX;\n let deltaY = -1 * e.deltaY;\n\n if (typeof deltaX === 'undefined' || typeof deltaY === 'undefined') {\n // OS X Safari\n deltaX = (-1 * e.wheelDeltaX) / 6;\n deltaY = e.wheelDeltaY / 6;\n }\n\n if (e.deltaMode && e.deltaMode === 1) {\n // Firefox in deltaMode 1: Line scrolling\n deltaX *= 10;\n deltaY *= 10;\n }\n\n if (deltaX !== deltaX && deltaY !== deltaY /* NaN checks */) {\n // IE in some mouse drivers\n deltaX = 0;\n deltaY = e.wheelDelta;\n }\n\n if (e.shiftKey) {\n // reverse axis with shift key\n return [-deltaY, -deltaX];\n }\n return [deltaX, deltaY];\n }\n\n function shouldBeConsumedByChild(target, deltaX, deltaY) {\n // FIXME: this is a workaround for <select> issue in FF and IE #571\n if (!env.isWebKit && element.querySelector('select:focus')) {\n return true;\n }\n\n if (!element.contains(target)) {\n return false;\n }\n\n let cursor = target;\n\n while (cursor && cursor !== element) {\n if (cursor.classList.contains(cls.element.consuming)) {\n return true;\n }\n\n const style = CSS.get(cursor);\n\n // if deltaY && vertical scrollable\n if (deltaY && style.overflowY.match(/(scroll|auto)/)) {\n const maxScrollTop = cursor.scrollHeight - cursor.clientHeight;\n if (maxScrollTop > 0) {\n if (\n (cursor.scrollTop > 0 && deltaY < 0) ||\n (cursor.scrollTop < maxScrollTop && deltaY > 0)\n ) {\n return true;\n }\n }\n }\n // if deltaX && horizontal scrollable\n if (deltaX && style.overflowX.match(/(scroll|auto)/)) {\n const maxScrollLeft = cursor.scrollWidth - cursor.clientWidth;\n if (maxScrollLeft > 0) {\n if (\n (cursor.scrollLeft > 0 && deltaX < 0) ||\n (cursor.scrollLeft < maxScrollLeft && deltaX > 0)\n ) {\n return true;\n }\n }\n }\n\n cursor = cursor.parentNode;\n }\n\n return false;\n }\n\n function mousewheelHandler(e) {\n const [deltaX, deltaY] = getDeltaFromEvent(e);\n\n if (shouldBeConsumedByChild(e.target, deltaX, deltaY)) {\n return;\n }\n\n let shouldPrevent = false;\n if (!i.settings.useBothWheelAxes) {\n // deltaX will only be used for horizontal scrolling and deltaY will\n // only be used for vertical scrolling - this is the default\n element.scrollTop -= deltaY * i.settings.wheelSpeed;\n element.scrollLeft += deltaX * i.settings.wheelSpeed;\n } else if (i.scrollbarYActive && !i.scrollbarXActive) {\n // only vertical scrollbar is active and useBothWheelAxes option is\n // active, so let's scroll vertical bar using both mouse wheel axes\n if (deltaY) {\n element.scrollTop -= deltaY * i.settings.wheelSpeed;\n } else {\n element.scrollTop += deltaX * i.settings.wheelSpeed;\n }\n shouldPrevent = true;\n } else if (i.scrollbarXActive && !i.scrollbarYActive) {\n // useBothWheelAxes and only horizontal bar is active, so use both\n // wheel axes for horizontal bar\n if (deltaX) {\n element.scrollLeft += deltaX * i.settings.wheelSpeed;\n } else {\n element.scrollLeft -= deltaY * i.settings.wheelSpeed;\n }\n shouldPrevent = true;\n }\n\n updateGeometry(i);\n\n shouldPrevent = shouldPrevent || shouldPreventDefault(deltaX, deltaY);\n if (shouldPrevent && !e.ctrlKey) {\n e.stopPropagation();\n e.preventDefaultLine truncated
+51
View File
@@ -0,0 +1,51 @@
{
"name": "perfect-scrollbar",
"version": "1.5.0",
"description": "Minimalistic but perfect custom scrollbar plugin",
"author": "Hyunje Jun <me@noraesae.net>",
"keywords": [
"frontend",
"scroll",
"scrollbar"
],
"repository": {
"type": "git",
"url": "https://github.com/mdbootstrap/perfect-scrollbar"
},
"bugs": {
"url": "https://github.com/mdbootstrap/perfect-scrollbar/issues"
},
"jspm": {
"main": "dist/perfect-scrollbar.common.js",
"registry": "jspm"
},
"main": "dist/perfect-scrollbar.common.js",
"module": "dist/perfect-scrollbar.esm.js",
"typings": "types/perfect-scrollbar.d.ts",
"style": "css/perfect-scrollbar.css",
"files": [
"css",
"dist",
"src",
"types"
],
"devDependencies": {
"chokidar-cli": "^2.1.0",
"prettier": "^1.19.1",
"rollup": "^1.27.8",
"rollup-plugin-babel": "^4.3.3",
"rollup-plugin-babel-minify": "^9.1.1",
"rollup-plugin-buble": "^0.19.8"
},
"scripts": {
"test": "npm run format:lint && npm run build",
"rollup": "rollup --config rollup.config.js --sourcemap",
"build": "npm run clean && npm run rollup",
"clean": "rm -rf dist",
"watch": "npm run build && SHELL=/bin/bash chokidar 'src/**/*.js' -c 'npm run format && npm run build'",
"format": "prettier --write --single-quote --trailing-comma es5 'src/**/*.js'",
"format:lint": "prettier -l --single-quote --trailing-comma es5 'src/**/*.js'",
"release": "./release"
},
"license": "MIT"
}
+33
View File
@@ -0,0 +1,33 @@
import updateGeometry from '../update-geometry';
export default function(i) {
const element = i.element;
i.event.bind(i.scrollbarY, 'mousedown', e => e.stopPropagation());
i.event.bind(i.scrollbarYRail, 'mousedown', e => {
const positionTop =
e.pageY -
window.pageYOffset -
i.scrollbarYRail.getBoundingClientRect().top;
const direction = positionTop > i.scrollbarYTop ? 1 : -1;
i.element.scrollTop += direction * i.containerHeight;
updateGeometry(i);
e.stopPropagation();
});
i.event.bind(i.scrollbarX, 'mousedown', e => e.stopPropagation());
i.event.bind(i.scrollbarXRail, 'mousedown', e => {
const positionLeft =
e.pageX -
window.pageXOffset -
i.scrollbarXRail.getBoundingClientRect().left;
const direction = positionLeft > i.scrollbarXLeft ? 1 : -1;
i.element.scrollLeft += direction * i.containerWidth;
updateGeometry(i);
e.stopPropagation();
});
}
+102
View File
@@ -0,0 +1,102 @@
import * as CSS from '../lib/css';
import * as DOM from '../lib/dom';
import cls, {
addScrollingClass,
removeScrollingClass,
} from '../lib/class-names';
import updateGeometry from '../update-geometry';
import { toInt } from '../lib/util';
export default function(i) {
bindMouseScrollHandler(i, [
'containerWidth',
'contentWidth',
'pageX',
'railXWidth',
'scrollbarX',
'scrollbarXWidth',
'scrollLeft',
'x',
'scrollbarXRail',
]);
bindMouseScrollHandler(i, [
'containerHeight',
'contentHeight',
'pageY',
'railYHeight',
'scrollbarY',
'scrollbarYHeight',
'scrollTop',
'y',
'scrollbarYRail',
]);
}
function bindMouseScrollHandler(
i,
[
containerHeight,
contentHeight,
pageY,
railYHeight,
scrollbarY,
scrollbarYHeight,
scrollTop,
y,
scrollbarYRail,
]
) {
const element = i.element;
let startingScrollTop = null;
let startingMousePageY = null;
let scrollBy = null;
function mouseMoveHandler(e) {
if (e.touches && e.touches[0]) {
e[pageY] = e.touches[0].pageY;
}
element[scrollTop] =
startingScrollTop + scrollBy * (e[pageY] - startingMousePageY);
addScrollingClass(i, y);
updateGeometry(i);
e.stopPropagation();
e.preventDefault();
}
function mouseUpHandler() {
removeScrollingClass(i, y);
i[scrollbarYRail].classList.remove(cls.state.clicking);
i.event.unbind(i.ownerDocument, 'mousemove', mouseMoveHandler);
}
function bindMoves(e, touchMode) {
startingScrollTop = element[scrollTop];
if (touchMode && e.touches) {
e[pageY] = e.touches[0].pageY;
}
startingMousePageY = e[pageY];
scrollBy =
(i[contentHeight] - i[containerHeight]) /
(i[railYHeight] - i[scrollbarYHeight]);
if (!touchMode) {
i.event.bind(i.ownerDocument, 'mousemove', mouseMoveHandler);
i.event.once(i.ownerDocument, 'mouseup', mouseUpHandler);
e.preventDefault();
} else {
i.event.bind(i.ownerDocument, 'touchmove', mouseMoveHandler);
}
i[scrollbarYRail].classList.add(cls.state.clicking);
e.stopPropagation();
}
i.event.bind(i[scrollbarY], 'mousedown', e => {
bindMoves(e);
});
i.event.bind(i[scrollbarY], 'touchstart', e => {
bindMoves(e, true);
});
}
+148
View File
@@ -0,0 +1,148 @@
import * as DOM from '../lib/dom';
import updateGeometry from '../update-geometry';
import { isEditable } from '../lib/util';
export default function(i) {
const element = i.element;
const elementHovered = () => DOM.matches(element, ':hover');
const scrollbarFocused = () =>
DOM.matches(i.scrollbarX, ':focus') || DOM.matches(i.scrollbarY, ':focus');
function shouldPreventDefault(deltaX, deltaY) {
const scrollTop = Math.floor(element.scrollTop);
if (deltaX === 0) {
if (!i.scrollbarYActive) {
return false;
}
if (
(scrollTop === 0 && deltaY > 0) ||
(scrollTop >= i.contentHeight - i.containerHeight && deltaY < 0)
) {
return !i.settings.wheelPropagation;
}
}
const scrollLeft = element.scrollLeft;
if (deltaY === 0) {
if (!i.scrollbarXActive) {
return false;
}
if (
(scrollLeft === 0 && deltaX < 0) ||
(scrollLeft >= i.contentWidth - i.containerWidth && deltaX > 0)
) {
return !i.settings.wheelPropagation;
}
}
return true;
}
i.event.bind(i.ownerDocument, 'keydown', e => {
if (
(e.isDefaultPrevented && e.isDefaultPrevented()) ||
e.defaultPrevented
) {
return;
}
if (!elementHovered() && !scrollbarFocused()) {
return;
}
let activeElement = document.activeElement
? document.activeElement
: i.ownerDocument.activeElement;
if (activeElement) {
if (activeElement.tagName === 'IFRAME') {
activeElement = activeElement.contentDocument.activeElement;
} else {
// go deeper if element is a webcomponent
while (activeElement.shadowRoot) {
activeElement = activeElement.shadowRoot.activeElement;
}
}
if (isEditable(activeElement)) {
return;
}
}
let deltaX = 0;
let deltaY = 0;
switch (e.which) {
case 37: // left
if (e.metaKey) {
deltaX = -i.contentWidth;
} else if (e.altKey) {
deltaX = -i.containerWidth;
} else {
deltaX = -30;
}
break;
case 38: // up
if (e.metaKey) {
deltaY = i.contentHeight;
} else if (e.altKey) {
deltaY = i.containerHeight;
} else {
deltaY = 30;
}
break;
case 39: // right
if (e.metaKey) {
deltaX = i.contentWidth;
} else if (e.altKey) {
deltaX = i.containerWidth;
} else {
deltaX = 30;
}
break;
case 40: // down
if (e.metaKey) {
deltaY = -i.contentHeight;
} else if (e.altKey) {
deltaY = -i.containerHeight;
} else {
deltaY = -30;
}
break;
case 32: // space bar
if (e.shiftKey) {
deltaY = i.containerHeight;
} else {
deltaY = -i.containerHeight;
}
break;
case 33: // page up
deltaY = i.containerHeight;
break;
case 34: // page down
deltaY = -i.containerHeight;
break;
case 36: // home
deltaY = i.contentHeight;
break;
case 35: // end
deltaY = -i.contentHeight;
break;
default:
return;
}
if (i.settings.suppressScrollX && deltaX !== 0) {
return;
}
if (i.settings.suppressScrollY && deltaY !== 0) {
return;
}
element.scrollTop -= deltaY;
element.scrollLeft += deltaX;
updateGeometry(i);
if (shouldPreventDefault(deltaX, deltaY)) {
e.preventDefault();
}
});
}
+158
View File
@@ -0,0 +1,158 @@
import * as CSS from '../lib/css';
import cls from '../lib/class-names';
import updateGeometry from '../update-geometry';
import { env } from '../lib/util';
export default function(i) {
const element = i.element;
let shouldPrevent = false;
function shouldPreventDefault(deltaX, deltaY) {
const roundedScrollTop = Math.floor(element.scrollTop);
const isTop = element.scrollTop === 0;
const isBottom =
roundedScrollTop + element.offsetHeight === element.scrollHeight;
const isLeft = element.scrollLeft === 0;
const isRight =
element.scrollLeft + element.offsetWidth === element.scrollWidth;
let hitsBound;
// pick axis with primary direction
if (Math.abs(deltaY) > Math.abs(deltaX)) {
hitsBound = isTop || isBottom;
} else {
hitsBound = isLeft || isRight;
}
return hitsBound ? !i.settings.wheelPropagation : true;
}
function getDeltaFromEvent(e) {
let deltaX = e.deltaX;
let deltaY = -1 * e.deltaY;
if (typeof deltaX === 'undefined' || typeof deltaY === 'undefined') {
// OS X Safari
deltaX = (-1 * e.wheelDeltaX) / 6;
deltaY = e.wheelDeltaY / 6;
}
if (e.deltaMode && e.deltaMode === 1) {
// Firefox in deltaMode 1: Line scrolling
deltaX *= 10;
deltaY *= 10;
}
if (deltaX !== deltaX && deltaY !== deltaY /* NaN checks */) {
// IE in some mouse drivers
deltaX = 0;
deltaY = e.wheelDelta;
}
if (e.shiftKey) {
// reverse axis with shift key
return [-deltaY, -deltaX];
}
return [deltaX, deltaY];
}
function shouldBeConsumedByChild(target, deltaX, deltaY) {
// FIXME: this is a workaround for <select> issue in FF and IE #571
if (!env.isWebKit && element.querySelector('select:focus')) {
return true;
}
if (!element.contains(target)) {
return false;
}
let cursor = target;
while (cursor && cursor !== element) {
if (cursor.classList.contains(cls.element.consuming)) {
return true;
}
const style = CSS.get(cursor);
// if deltaY && vertical scrollable
if (deltaY && style.overflowY.match(/(scroll|auto)/)) {
const maxScrollTop = cursor.scrollHeight - cursor.clientHeight;
if (maxScrollTop > 0) {
if (
(cursor.scrollTop > 0 && deltaY < 0) ||
(cursor.scrollTop < maxScrollTop && deltaY > 0)
) {
return true;
}
}
}
// if deltaX && horizontal scrollable
if (deltaX && style.overflowX.match(/(scroll|auto)/)) {
const maxScrollLeft = cursor.scrollWidth - cursor.clientWidth;
if (maxScrollLeft > 0) {
if (
(cursor.scrollLeft > 0 && deltaX < 0) ||
(cursor.scrollLeft < maxScrollLeft && deltaX > 0)
) {
return true;
}
}
}
cursor = cursor.parentNode;
}
return false;
}
function mousewheelHandler(e) {
const [deltaX, deltaY] = getDeltaFromEvent(e);
if (shouldBeConsumedByChild(e.target, deltaX, deltaY)) {
return;
}
let shouldPrevent = false;
if (!i.settings.useBothWheelAxes) {
// deltaX will only be used for horizontal scrolling and deltaY will
// only be used for vertical scrolling - this is the default
element.scrollTop -= deltaY * i.settings.wheelSpeed;
element.scrollLeft += deltaX * i.settings.wheelSpeed;
} else if (i.scrollbarYActive && !i.scrollbarXActive) {
// only vertical scrollbar is active and useBothWheelAxes option is
// active, so let's scroll vertical bar using both mouse wheel axes
if (deltaY) {
element.scrollTop -= deltaY * i.settings.wheelSpeed;
} else {
element.scrollTop += deltaX * i.settings.wheelSpeed;
}
shouldPrevent = true;
} else if (i.scrollbarXActive && !i.scrollbarYActive) {
// useBothWheelAxes and only horizontal bar is active, so use both
// wheel axes for horizontal bar
if (deltaX) {
element.scrollLeft += deltaX * i.settings.wheelSpeed;
} else {
element.scrollLeft -= deltaY * i.settings.wheelSpeed;
}
shouldPrevent = true;
}
updateGeometry(i);
shouldPrevent = shouldPrevent || shouldPreventDefault(deltaX, deltaY);
if (shouldPrevent && !e.ctrlKey) {
e.stopPropagation();
e.preventDefault();
}
}
if (typeof window.onwheel !== 'undefined') {
i.event.bind(element, 'wheel', mousewheelHandler);
} else if (typeof window.onmousewheel !== 'undefined') {
i.event.bind(element, 'mousewheel', mousewheelHandler);
}
}
+215
View File
@@ -0,0 +1,215 @@
import updateGeometry from '../update-geometry';
import cls from '../lib/class-names';
import * as CSS from '../lib/css';
import { env } from '../lib/util';
export default function(i) {
if (!env.supportsTouch && !env.supportsIePointer) {
return;
}
const element = i.element;
function shouldPrevent(deltaX, deltaY) {
const scrollTop = Math.floor(element.scrollTop);
const scrollLeft = element.scrollLeft;
const magnitudeX = Math.abs(deltaX);
const magnitudeY = Math.abs(deltaY);
if (magnitudeY > magnitudeX) {
// user is perhaps trying to swipe up/down the page
if (
(deltaY < 0 && scrollTop === i.contentHeight - i.containerHeight) ||
(deltaY > 0 && scrollTop === 0)
) {
// set prevent for mobile Chrome refresh
return window.scrollY === 0 && deltaY > 0 && env.isChrome;
}
} else if (magnitudeX > magnitudeY) {
// user is perhaps trying to swipe left/right across the page
if (
(deltaX < 0 && scrollLeft === i.contentWidth - i.containerWidth) ||
(deltaX > 0 && scrollLeft === 0)
) {
return true;
}
}
return true;
}
function applyTouchMove(differenceX, differenceY) {
element.scrollTop -= differenceY;
element.scrollLeft -= differenceX;
updateGeometry(i);
}
let startOffset = {};
let startTime = 0;
let speed = {};
let easingLoop = null;
function getTouch(e) {
if (e.targetTouches) {
return e.targetTouches[0];
} else {
// Maybe IE pointer
return e;
}
}
function shouldHandle(e) {
if (e.pointerType && e.pointerType === 'pen' && e.buttons === 0) {
return false;
}
if (e.targetTouches && e.targetTouches.length === 1) {
return true;
}
if (
e.pointerType &&
e.pointerType !== 'mouse' &&
e.pointerType !== e.MSPOINTER_TYPE_MOUSE
) {
return true;
}
return false;
}
function touchStart(e) {
if (!shouldHandle(e)) {
return;
}
const touch = getTouch(e);
startOffset.pageX = touch.pageX;
startOffset.pageY = touch.pageY;
startTime = new Date().getTime();
if (easingLoop !== null) {
clearInterval(easingLoop);
}
}
function shouldBeConsumedByChild(target, deltaX, deltaY) {
if (!element.contains(target)) {
return false;
}
let cursor = target;
while (cursor && cursor !== element) {
if (cursor.classList.contains(cls.element.consuming)) {
return true;
}
const style = CSS.get(cursor);
// if deltaY && vertical scrollable
if (deltaY && style.overflowY.match(/(scroll|auto)/)) {
const maxScrollTop = cursor.scrollHeight - cursor.clientHeight;
if (maxScrollTop > 0) {
if (
(cursor.scrollTop > 0 && deltaY < 0) ||
(cursor.scrollTop < maxScrollTop && deltaY > 0)
) {
return true;
}
}
}
// if deltaX && horizontal scrollable
if (deltaX && style.overflowX.match(/(scroll|auto)/)) {
const maxScrollLeft = cursor.scrollWidth - cursor.clientWidth;
if (maxScrollLeft > 0) {
if (
(cursor.scrollLeft > 0 && deltaX < 0) ||
(cursor.scrollLeft < maxScrollLeft && deltaX > 0)
) {
return true;
}
}
}
cursor = cursor.parentNode;
}
return false;
}
function touchMove(e) {
if (shouldHandle(e)) {
const touch = getTouch(e);
const currentOffset = { pageX: touch.pageX, pageY: touch.pageY };
const differenceX = currentOffset.pageX - startOffset.pageX;
const differenceY = currentOffset.pageY - startOffset.pageY;
if (shouldBeConsumedByChild(e.target, differenceX, differenceY)) {
return;
}
applyTouchMove(differenceX, differenceY);
startOffset = currentOffset;
const currentTime = new Date().getTime();
const timeGap = currentTime - startTime;
if (timeGap > 0) {
speed.x = differenceX / timeGap;
speed.y = differenceY / timeGap;
startTime = currentTime;
}
if (shouldPrevent(differenceX, differenceY)) {
e.preventDefault();
}
}
}
function touchEnd() {
if (i.settings.swipeEasing) {
clearInterval(easingLoop);
easingLoop = setInterval(function() {
if (i.isInitialized) {
clearInterval(easingLoop);
return;
}
if (!speed.x && !speed.y) {
clearInterval(easingLoop);
return;
}
if (Math.abs(speed.x) < 0.01 && Math.abs(speed.y) < 0.01) {
clearInterval(easingLoop);
return;
}
applyTouchMove(speed.x * 30, speed.y * 30);
speed.x *= 0.8;
speed.y *= 0.8;
}, 10);
}
}
if (env.supportsTouch) {
i.event.bind(element, 'touchstart', touchStart);
i.event.bind(element, 'touchmove', touchMove);
i.event.bind(element, 'touchend', touchEnd);
} else if (env.supportsIePointer) {
if (window.PointerEvent) {
i.event.bind(element, 'pointerdown', touchStart);
i.event.bind(element, 'pointermove', touchMove);
i.event.bind(element, 'pointerup', touchEnd);
} else if (window.MSPointerEvent) {
i.event.bind(element, 'MSPointerDown', touchStart);
i.event.bind(element, 'MSPointerMove', touchMove);
i.event.bind(element, 'MSPointerUp', touchEnd);
}
}
}
+242
View File
@@ -0,0 +1,242 @@
import * as CSS from './lib/css';
import * as DOM from './lib/dom';
import cls from './lib/class-names';
import EventManager from './lib/event-manager';
import processScrollDiff from './process-scroll-diff';
import updateGeometry from './update-geometry';
import { toInt, outerWidth } from './lib/util';
import clickRail from './handlers/click-rail';
import dragThumb from './handlers/drag-thumb';
import keyboard from './handlers/keyboard';
import wheel from './handlers/mouse-wheel';
import touch from './handlers/touch';
const defaultSettings = () => ({
handlers: ['click-rail', 'drag-thumb', 'keyboard', 'wheel', 'touch'],
maxScrollbarLength: null,
minScrollbarLength: null,
scrollingThreshold: 1000,
scrollXMarginOffset: 0,
scrollYMarginOffset: 0,
suppressScrollX: false,
suppressScrollY: false,
swipeEasing: true,
useBothWheelAxes: false,
wheelPropagation: true,
wheelSpeed: 1,
});
const handlers = {
'click-rail': clickRail,
'drag-thumb': dragThumb,
keyboard,
wheel,
touch,
};
export default class PerfectScrollbar {
constructor(element, userSettings = {}) {
if (typeof element === 'string') {
element = document.querySelector(element);
}
if (!element || !element.nodeName) {
throw new Error('no element is specified to initialize PerfectScrollbar');
}
this.element = element;
element.classList.add(cls.main);
this.settings = defaultSettings();
for (const key in userSettings) {
this.settings[key] = userSettings[key];
}
this.containerWidth = null;
this.containerHeight = null;
this.contentWidth = null;
this.contentHeight = null;
const focus = () => element.classList.add(cls.state.focus);
const blur = () => element.classList.remove(cls.state.focus);
this.isRtl = CSS.get(element).direction === 'rtl';
if (this.isRtl === true) {
element.classList.add(cls.rtl);
}
this.isNegativeScroll = (() => {
const originalScrollLeft = element.scrollLeft;
let result = null;
element.scrollLeft = -1;
result = element.scrollLeft < 0;
element.scrollLeft = originalScrollLeft;
return result;
})();
this.negativeScrollAdjustment = this.isNegativeScroll
? element.scrollWidth - element.clientWidth
: 0;
this.event = new EventManager();
this.ownerDocument = element.ownerDocument || document;
this.scrollbarXRail = DOM.div(cls.element.rail('x'));
element.appendChild(this.scrollbarXRail);
this.scrollbarX = DOM.div(cls.element.thumb('x'));
this.scrollbarXRail.appendChild(this.scrollbarX);
this.scrollbarX.setAttribute('tabindex', 0);
this.event.bind(this.scrollbarX, 'focus', focus);
this.event.bind(this.scrollbarX, 'blur', blur);
this.scrollbarXActive = null;
this.scrollbarXWidth = null;
this.scrollbarXLeft = null;
const railXStyle = CSS.get(this.scrollbarXRail);
this.scrollbarXBottom = parseInt(railXStyle.bottom, 10);
if (isNaN(this.scrollbarXBottom)) {
this.isScrollbarXUsingBottom = false;
this.scrollbarXTop = toInt(railXStyle.top);
} else {
this.isScrollbarXUsingBottom = true;
}
this.railBorderXWidth =
toInt(railXStyle.borderLeftWidth) + toInt(railXStyle.borderRightWidth);
// Set rail to display:block to calculate margins
CSS.set(this.scrollbarXRail, { display: 'block' });
this.railXMarginWidth =
toInt(railXStyle.marginLeft) + toInt(railXStyle.marginRight);
CSS.set(this.scrollbarXRail, { display: '' });
this.railXWidth = null;
this.railXRatio = null;
this.scrollbarYRail = DOM.div(cls.element.rail('y'));
element.appendChild(this.scrollbarYRail);
this.scrollbarY = DOM.div(cls.element.thumb('y'));
this.scrollbarYRail.appendChild(this.scrollbarY);
this.scrollbarY.setAttribute('tabindex', 0);
this.event.bind(this.scrollbarY, 'focus', focus);
this.event.bind(this.scrollbarY, 'blur', blur);
this.scrollbarYActive = null;
this.scrollbarYHeight = null;
this.scrollbarYTop = null;
const railYStyle = CSS.get(this.scrollbarYRail);
this.scrollbarYRight = parseInt(railYStyle.right, 10);
if (isNaN(this.scrollbarYRight)) {
this.isScrollbarYUsingRight = false;
this.scrollbarYLeft = toInt(railYStyle.left);
} else {
this.isScrollbarYUsingRight = true;
}
this.scrollbarYOuterWidth = this.isRtl ? outerWidth(this.scrollbarY) : null;
this.railBorderYWidth =
toInt(railYStyle.borderTopWidth) + toInt(railYStyle.borderBottomWidth);
CSS.set(this.scrollbarYRail, { display: 'block' });
this.railYMarginHeight =
toInt(railYStyle.marginTop) + toInt(railYStyle.marginBottom);
CSS.set(this.scrollbarYRail, { display: '' });
this.railYHeight = null;
this.railYRatio = null;
this.reach = {
x:
element.scrollLeft <= 0
? 'start'
: element.scrollLeft >= this.contentWidth - this.containerWidth
? 'end'
: null,
y:
element.scrollTop <= 0
? 'start'
: element.scrollTop >= this.contentHeight - this.containerHeight
? 'end'
: null,
};
this.isAlive = true;
this.settings.handlers.forEach(handlerName => handlers[handlerName](this));
this.lastScrollTop = Math.floor(element.scrollTop); // for onScroll only
this.lastScrollLeft = element.scrollLeft; // for onScroll only
this.event.bind(this.element, 'scroll', e => this.onScroll(e));
updateGeometry(this);
}
update() {
if (!this.isAlive) {
return;
}
// Recalcuate negative scrollLeft adjustment
this.negativeScrollAdjustment = this.isNegativeScroll
? this.element.scrollWidth - this.element.clientWidth
: 0;
// Recalculate rail margins
CSS.set(this.scrollbarXRail, { display: 'block' });
CSS.set(this.scrollbarYRail, { display: 'block' });
this.railXMarginWidth =
toInt(CSS.get(this.scrollbarXRail).marginLeft) +
toInt(CSS.get(this.scrollbarXRail).marginRight);
this.railYMarginHeight =
toInt(CSS.get(this.scrollbarYRail).marginTop) +
toInt(CSS.get(this.scrollbarYRail).marginBottom);
// Hide scrollbars not to affect scrollWidth and scrollHeight
CSS.set(this.scrollbarXRail, { display: 'none' });
CSS.set(this.scrollbarYRail, { display: 'none' });
updateGeometry(this);
processScrollDiff(this, 'top', 0, false, true);
processScrollDiff(this, 'left', 0, false, true);
CSS.set(this.scrollbarXRail, { display: '' });
CSS.set(this.scrollbarYRail, { display: '' });
}
onScroll(e) {
if (!this.isAlive) {
return;
}
updateGeometry(this);
processScrollDiff(this, 'top', this.element.scrollTop - this.lastScrollTop);
processScrollDiff(
this,
'left',
this.element.scrollLeft - this.lastScrollLeft
);
this.lastScrollTop = Math.floor(this.element.scrollTop);
this.lastScrollLeft = this.element.scrollLeft;
}
destroy() {
if (!this.isAlive) {
return;
}
this.event.unbindAll();
DOM.remove(this.scrollbarX);
DOM.remove(this.scrollbarY);
DOM.remove(this.scrollbarXRail);
DOM.remove(this.scrollbarYRail);
this.removePsClasses();
// unset elements
this.element = null;
this.scrollbarX = null;
this.scrollbarY = null;
this.scrollbarXRail = null;
this.scrollbarYRail = null;
this.isAlive = false;
}
removePsClasses() {
this.element.className = this.element.className
.split(' ')
.filter(name => !name.match(/^ps([-_].+|)$/))
.join(' ');
}
}
+45
View File
@@ -0,0 +1,45 @@
const cls = {
main: 'ps',
rtl: 'ps__rtl',
element: {
thumb: x => `ps__thumb-${x}`,
rail: x => `ps__rail-${x}`,
consuming: 'ps__child--consume',
},
state: {
focus: 'ps--focus',
clicking: 'ps--clicking',
active: x => `ps--active-${x}`,
scrolling: x => `ps--scrolling-${x}`,
},
};
export default cls;
/*
* Helper methods
*/
const scrollingClassTimeout = { x: null, y: null };
export function addScrollingClass(i, x) {
const classList = i.element.classList;
const className = cls.state.scrolling(x);
if (classList.contains(className)) {
clearTimeout(scrollingClassTimeout[x]);
} else {
classList.add(className);
}
}
export function removeScrollingClass(i, x) {
scrollingClassTimeout[x] = setTimeout(
() => i.isAlive && i.element.classList.remove(cls.state.scrolling(x)),
i.settings.scrollingThreshold
);
}
export function setScrollingClassInstantly(i, x) {
addScrollingClass(i, x);
removeScrollingClass(i, x);
}
+14
View File
@@ -0,0 +1,14 @@
export function get(element) {
return getComputedStyle(element);
}
export function set(element, obj) {
for (const key in obj) {
let val = obj[key];
if (typeof val === 'number') {
val = `${val}px`;
}
element.style[key] = val;
}
return element;
}
+36
View File
@@ -0,0 +1,36 @@
export function div(className) {
const div = document.createElement('div');
div.className = className;
return div;
}
const elMatches =
typeof Element !== 'undefined' &&
(Element.prototype.matches ||
Element.prototype.webkitMatchesSelector ||
Element.prototype.mozMatchesSelector ||
Element.prototype.msMatchesSelector);
export function matches(element, query) {
if (!elMatches) {
throw new Error('No element matching method supported');
}
return elMatches.call(element, query);
}
export function remove(element) {
if (element.remove) {
element.remove();
} else {
if (element.parentNode) {
element.parentNode.removeChild(element);
}
}
}
export function queryChildren(element, selector) {
return Array.prototype.filter.call(element.children, child =>
matches(child, selector)
);
}
+79
View File
@@ -0,0 +1,79 @@
class EventElement {
constructor(element) {
this.element = element;
this.handlers = {};
}
bind(eventName, handler) {
if (typeof this.handlers[eventName] === 'undefined') {
this.handlers[eventName] = [];
}
this.handlers[eventName].push(handler);
this.element.addEventListener(eventName, handler, false);
}
unbind(eventName, target) {
this.handlers[eventName] = this.handlers[eventName].filter(handler => {
if (target && handler !== target) {
return true;
}
this.element.removeEventListener(eventName, handler, false);
return false;
});
}
unbindAll() {
for (const name in this.handlers) {
this.unbind(name);
}
}
get isEmpty() {
return Object.keys(this.handlers).every(
key => this.handlers[key].length === 0
);
}
}
export default class EventManager {
constructor() {
this.eventElements = [];
}
eventElement(element) {
let ee = this.eventElements.filter(ee => ee.element === element)[0];
if (!ee) {
ee = new EventElement(element);
this.eventElements.push(ee);
}
return ee;
}
bind(element, eventName, handler) {
this.eventElement(element).bind(eventName, handler);
}
unbind(element, eventName, handler) {
const ee = this.eventElement(element);
ee.unbind(eventName, handler);
if (ee.isEmpty) {
// remove
this.eventElements.splice(this.eventElements.indexOf(ee), 1);
}
}
unbindAll() {
this.eventElements.forEach(e => e.unbindAll());
this.eventElements = [];
}
once(element, eventName, handler) {
const ee = this.eventElement(element);
const onceHandler = evt => {
ee.unbind(eventName, onceHandler);
handler(evt);
};
ee.bind(eventName, onceHandler);
}
}
+43
View File
@@ -0,0 +1,43 @@
import * as CSS from './css';
import * as DOM from './dom';
export function toInt(x) {
return parseInt(x, 10) || 0;
}
export function isEditable(el) {
return (
DOM.matches(el, 'input,[contenteditable]') ||
DOM.matches(el, 'select,[contenteditable]') ||
DOM.matches(el, 'textarea,[contenteditable]') ||
DOM.matches(el, 'button,[contenteditable]')
);
}
export function outerWidth(element) {
const styles = CSS.get(element);
return (
toInt(styles.width) +
toInt(styles.paddingLeft) +
toInt(styles.paddingRight) +
toInt(styles.borderLeftWidth) +
toInt(styles.borderRightWidth)
);
}
export const env = {
isWebKit:
typeof document !== 'undefined' &&
'WebkitAppearance' in document.documentElement.style,
supportsTouch:
typeof window !== 'undefined' &&
('ontouchstart' in window ||
('maxTouchPoints' in window.navigator &&
window.navigator.maxTouchPoints > 0) ||
(window.DocumentTouch && document instanceof window.DocumentTouch)),
supportsIePointer:
typeof navigator !== 'undefined' && navigator.msMaxTouchPoints,
isChrome:
typeof navigator !== 'undefined' &&
/Chrome/i.test(navigator && navigator.userAgent),
};
+85
View File
@@ -0,0 +1,85 @@
import { setScrollingClassInstantly } from './lib/class-names';
function createEvent(name) {
if (typeof window.CustomEvent === 'function') {
return new CustomEvent(name);
} else {
const evt = document.createEvent('CustomEvent');
evt.initCustomEvent(name, false, false, undefined);
return evt;
}
}
export default function(
i,
axis,
diff,
useScrollingClass = true,
forceFireReachEvent = false
) {
let fields;
if (axis === 'top') {
fields = [
'contentHeight',
'containerHeight',
'scrollTop',
'y',
'up',
'down',
];
} else if (axis === 'left') {
fields = [
'contentWidth',
'containerWidth',
'scrollLeft',
'x',
'left',
'right',
];
} else {
throw new Error('A proper axis should be provided');
}
processScrollDiff(i, diff, fields, useScrollingClass, forceFireReachEvent);
}
function processScrollDiff(
i,
diff,
[contentHeight, containerHeight, scrollTop, y, up, down],
useScrollingClass = true,
forceFireReachEvent = false
) {
const element = i.element;
// reset reach
i.reach[y] = null;
// 1 for subpixel rounding
if (element[scrollTop] < 1) {
i.reach[y] = 'start';
}
// 1 for subpixel rounding
if (element[scrollTop] > i[contentHeight] - i[containerHeight] - 1) {
i.reach[y] = 'end';
}
if (diff) {
element.dispatchEvent(createEvent(`ps-scroll-${y}`));
if (diff < 0) {
element.dispatchEvent(createEvent(`ps-scroll-${up}`));
} else if (diff > 0) {
element.dispatchEvent(createEvent(`ps-scroll-${down}`));
}
if (useScrollingClass) {
setScrollingClassInstantly(i, y);
}
}
if (i.reach[y] && (diff || forceFireReachEvent)) {
element.dispatchEvent(createEvent(`ps-${y}-reach-${i.reach[y]}`));
}
}
+162
View File
@@ -0,0 +1,162 @@
import * as CSS from './lib/css';
import * as DOM from './lib/dom';
import cls from './lib/class-names';
import { toInt } from './lib/util';
export default function(i) {
const element = i.element;
const roundedScrollTop = Math.floor(element.scrollTop);
const rect = element.getBoundingClientRect();
i.containerWidth = Math.ceil(rect.width);
i.containerHeight = Math.ceil(rect.height);
i.contentWidth = element.scrollWidth;
i.contentHeight = element.scrollHeight;
if (!element.contains(i.scrollbarXRail)) {
// clean up and append
DOM.queryChildren(element, cls.element.rail('x')).forEach(el =>
DOM.remove(el)
);
element.appendChild(i.scrollbarXRail);
}
if (!element.contains(i.scrollbarYRail)) {
// clean up and append
DOM.queryChildren(element, cls.element.rail('y')).forEach(el =>
DOM.remove(el)
);
element.appendChild(i.scrollbarYRail);
}
if (
!i.settings.suppressScrollX &&
i.containerWidth + i.settings.scrollXMarginOffset < i.contentWidth
) {
i.scrollbarXActive = true;
i.railXWidth = i.containerWidth - i.railXMarginWidth;
i.railXRatio = i.containerWidth / i.railXWidth;
i.scrollbarXWidth = getThumbSize(
i,
toInt((i.railXWidth * i.containerWidth) / i.contentWidth)
);
i.scrollbarXLeft = toInt(
((i.negativeScrollAdjustment + element.scrollLeft) *
(i.railXWidth - i.scrollbarXWidth)) /
(i.contentWidth - i.containerWidth)
);
} else {
i.scrollbarXActive = false;
}
if (
!i.settings.suppressScrollY &&
i.containerHeight + i.settings.scrollYMarginOffset < i.contentHeight
) {
i.scrollbarYActive = true;
i.railYHeight = i.containerHeight - i.railYMarginHeight;
i.railYRatio = i.containerHeight / i.railYHeight;
i.scrollbarYHeight = getThumbSize(
i,
toInt((i.railYHeight * i.containerHeight) / i.contentHeight)
);
i.scrollbarYTop = toInt(
(roundedScrollTop * (i.railYHeight - i.scrollbarYHeight)) /
(i.contentHeight - i.containerHeight)
);
} else {
i.scrollbarYActive = false;
}
if (i.scrollbarXLeft >= i.railXWidth - i.scrollbarXWidth) {
i.scrollbarXLeft = i.railXWidth - i.scrollbarXWidth;
}
if (i.scrollbarYTop >= i.railYHeight - i.scrollbarYHeight) {
i.scrollbarYTop = i.railYHeight - i.scrollbarYHeight;
}
updateCss(element, i);
if (i.scrollbarXActive) {
element.classList.add(cls.state.active('x'));
} else {
element.classList.remove(cls.state.active('x'));
i.scrollbarXWidth = 0;
i.scrollbarXLeft = 0;
element.scrollLeft = i.isRtl === true ? i.contentWidth : 0;
}
if (i.scrollbarYActive) {
element.classList.add(cls.state.active('y'));
} else {
element.classList.remove(cls.state.active('y'));
i.scrollbarYHeight = 0;
i.scrollbarYTop = 0;
element.scrollTop = 0;
}
}
function getThumbSize(i, thumbSize) {
if (i.settings.minScrollbarLength) {
thumbSize = Math.max(thumbSize, i.settings.minScrollbarLength);
}
if (i.settings.maxScrollbarLength) {
thumbSize = Math.min(thumbSize, i.settings.maxScrollbarLength);
}
return thumbSize;
}
function updateCss(element, i) {
const xRailOffset = { width: i.railXWidth };
const roundedScrollTop = Math.floor(element.scrollTop);
if (i.isRtl) {
xRailOffset.left =
i.negativeScrollAdjustment +
element.scrollLeft +
i.containerWidth -
i.contentWidth;
} else {
xRailOffset.left = element.scrollLeft;
}
if (i.isScrollbarXUsingBottom) {
xRailOffset.bottom = i.scrollbarXBottom - roundedScrollTop;
} else {
xRailOffset.top = i.scrollbarXTop + roundedScrollTop;
}
CSS.set(i.scrollbarXRail, xRailOffset);
const yRailOffset = { top: roundedScrollTop, height: i.railYHeight };
if (i.isScrollbarYUsingRight) {
if (i.isRtl) {
yRailOffset.right =
i.contentWidth -
(i.negativeScrollAdjustment + element.scrollLeft) -
i.scrollbarYRight -
i.scrollbarYOuterWidth -
9;
} else {
yRailOffset.right = i.scrollbarYRight - element.scrollLeft;
}
} else {
if (i.isRtl) {
yRailOffset.left =
i.negativeScrollAdjustment +
element.scrollLeft +
i.containerWidth * 2 -
i.contentWidth -
i.scrollbarYLeft -
i.scrollbarYOuterWidth;
} else {
yRailOffset.left = i.scrollbarYLeft + element.scrollLeft;
}
}
CSS.set(i.scrollbarYRail, yRailOffset);
CSS.set(i.scrollbarX, {
left: i.scrollbarXLeft,
width: i.scrollbarXWidth - i.railBorderXWidth,
});
CSS.set(i.scrollbarY, {
top: i.scrollbarYTop,
height: i.scrollbarYHeight - i.railBorderYWidth,
});
}
+62
View File
@@ -0,0 +1,62 @@
declare namespace PerfectScrollbar {
export interface Options {
handlers?: string[];
maxScrollbarLength?: number;
minScrollbarLength?: number;
scrollingThreshold?: number;
scrollXMarginOffset?: number;
scrollYMarginOffset?: number;
suppressScrollX?: boolean;
suppressScrollY?: boolean;
swipeEasing?: boolean;
useBothWheelAxes?: boolean;
wheelPropagation?: boolean;
wheelSpeed?: number;
}
}
declare class PerfectScrollbar {
constructor(element: string | Element, options?: PerfectScrollbar.Options);
update(): void;
destroy(): void;
containerHeight: number;
containerWidth: number;
contentHeight: number;
contentWidth: number;
element: HTMLElement;
isAlive: boolean;
isNegativeScroll: boolean;
isRtl: boolean;
isScrollbarXUsingBottom: boolean;
isScrollbarYUsingBottom: boolean;
lastScrollLeft: boolean;
lastScrollTop: boolean;
negativeScrollAdjustment: number;
railBorderXWidth: number;
railBorderYWidth: number;
railXMarginWidth: number;
railXRatio: number;
railXWidth: number;
railYHeight: number;
railYMarginHeight: number;
railYRatio: number;
scrollbarX: HTMLElement;
scrollbarXActive: boolean;
scrollbarXBottom: number;
scrollbarXLeft: number;
scrollbarXRail: HTMLElement;
scrollbarXWidth: number;
scrollbarY: HTMLElement;
scrollbarYActive: boolean;
scrollbarYHeight: number;
scrollbarYOuterWidth?: number;
scrollbarYRail: HTMLElement;
scrollbarYRight: number;
scrollbarYTop: number;
settings: PerfectScrollbar.Options;
reach: { x: 'start' | 'end' | null, y: 'start' | 'end' | null };
}
export default PerfectScrollbar;