New Research: Supply Chain Attack on Axios Pulls Malicious Dependency from npm.Details →
Socket
Book a DemoSign in
Socket

react-scroll-box

Package Overview
Dependencies
Maintainers
1
Versions
22
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

react-scroll-box - npm Package Compare versions

Comparing version
0.2.9
to
0.3.4
+1
target/out/index.css.map
{"version":3,"sources":[],"names":[],"mappings":"","file":"index.css","sourceRoot":""}

Sorry, the diff of this file is too big to display

{
"name": "react-scroll-box",
"version": "3.0.0",
"author": "Savva Mikhalevski",
"description": "Charged cross-browser and cross-platform scrollable container implementation with no external dependencies but React 15+",
"license": "MIT",
"repository": {
"type": "git",
"url": "https://github.com/smikhalevski/react-scroll-box.git"
},
"main": "index.js",
"homepage": "https://github.com/smikhalevski/react-scroll-box",
"keywords": [
"react",
"component",
"scroll",
"scrollbox",
"scrollbar"
],
"scripts": {
"start": "webpack-dev-server -d --progress --config webpack.gh-pages.config.js",
"build": "rm -rf target/out; webpack -p --devtool source-map",
"build:gh-pages": "rm -rf target/gh-pages; webpack -p --config webpack.gh-pages.config.js"
},
"devDependencies": {
"webpack": "2.6.1",
"webpack-dev-server": "2.4.5",
"babel-loader": "^6.2.10",
"hson-loader": "^2.0.0",
"less-loader": "^4.0.3",
"style-loader": "^0.18.0",
"css-loader": "^0.28.3",
"file-loader": "^0.11.1",
"extract-text-webpack-plugin": "2.1.0",
"babel-core": "^6.24.1",
"babel-preset-es2015": "^6.24.1",
"babel-preset-react": "^6.24.1",
"babel-preset-stage-0": "^6.24.1",
"babel-plugin-transform-runtime": "^6.23.0",
"babel-plugin-transform-regenerator": "^6.24.1",
"less": "^2.7.2",
"classnames": "^2.2.5",
"lodash": "^4.17.4",
"classlist-polyfill": "^1.2.0"
},
"dependencies": {
"react": "^15.0.0",
"prop-types": "^15.5.10",
"react-dom": "^15.0.0"
}
}
import React from 'react';
import {findDOMNode} from 'react-dom';
import {bool, element, func, node, number, object, oneOf, string} from 'prop-types';
export const FastTrackMode = {
PAGING: 'paging',
GOTO: 'goto'
};
export const ScrollCause = {
HANDLE_DRAG: 0,
MOUSE_WHEEL: 1,
FAST_TRACK: 2,
KEYBOARD: 3,
TOUCH: 4
};
export const ScrollEasing = {
easeQuadOut(percent, elapsed, min, max, duration) {
percent -= 1;
return min + max * Math.sqrt(1 - Math.pow(percent, 2));
}
};
export class AbstractScrollBox extends React.Component {
static propTypes = {
// Viewport element.
children: element.isRequired,
// Use native client scroll bars.
nativeScrollBars: bool,
className: string,
style: object,
disabled: bool,
// Events
onScroll: func,
onScrollX: func,
onScrollY: func,
onScrollStart: func,
onScrollStartX: func,
onScrollStartY: func,
onScrollEnd: func,
onScrollEndX: func,
onScrollEndY: func,
// Disable scrolling in corresponding direction.
disableScrollX: bool,
disableScrollY: bool,
// Toggle scroll bar visibility for corresponding direction.
hideScrollBarX: bool,
hideScrollBarY: bool,
// Toggle show scroll bars outside of scroll box rectangle.
// This has no effect when native scroll bars are enabled on mobile device.
outsetScrollBarX: bool,
outsetScrollBarY: bool,
// Minimum number of pixels when scroll bars are required.
scrollMinX: number,
scrollMinY: number,
// Distance from cursor to edge of the scroll track when scroll bar is considered to be hovered.
trackHoverProximityX: number,
trackHoverProximityY: number,
// Default easing functions applied when scroll with non-zero duration is requested.
easingX: func,
easingY: func,
// Handle drag
captureHandleDragX: bool,
captureHandleDragY: bool,
// Interrupt handle drag when programmatic scrolling requested.
interruptibleHandleDrag: bool,
// Fast tracking occurs when user clicks on scroll track.
captureFastTrackX: bool,
captureFastTrackY: bool,
fastTrackModeX: oneOf(Object.values(FastTrackMode)),
fastTrackModeY: oneOf(Object.values(FastTrackMode)),
fastTrackScrollDurationX: number,
fastTrackScrollDurationY: number,
// Keyboard
captureKeyboard: bool,
keyboardStepX: number,
keyboardStepY: number,
keyboardScrollDurationX: number,
keyboardScrollDurationY: number,
// Wheel
captureWheel: bool,
wheelLineHeight: number,
wheelStepX: number,
wheelStepY: number,
propagateWheelScrollX: bool,
propagateWheelScrollY: bool,
swapWheelAxes: bool,
wheelScrollDurationX: number,
wheelScrollDurationY: number,
// Touch
captureTouch: bool,
propagateTouchScrollX: bool,
propagateTouchScrollY: bool,
touchSingleAxis: bool,
touchStartDistance: number,
continuousTouchScrollX: bool,
continuousTouchScrollY: bool,
inertiaEasingX: func,
inertiaEasingY: func,
inertiaDistanceX: func,
inertiaDistanceY: func,
inertiaDurationX: func,
inertiaDurationY: func,
// Layout
trackChildrenX: node,
trackChildrenY: node,
handleChildrenX: node,
handleChildrenY: node
};
static defaultProps = {
nativeScrollBars: false,
className: 'scroll-box--wrapped',
style: null,
disabled: false,
onScroll(target, dx, dy, causeX, causeY) {},
onScrollX(target, dx, causeX) {},
onScrollY(target, dy, causeY) {},
onScrollStart(target, causeX, causeY) {},
onScrollStartX(target, causeX) {},
onScrollStartY(target, causeY) {},
onScrollEnd(target, causeX, causeY) {},
onScrollEndX(target, causeX) {},
onScrollEndY(target, causeY) {},
disableScrollX: false,
disableScrollY: false,
hideScrollBarX: false,
hideScrollBarY: false,
outsetScrollBarX: false,
outsetScrollBarY: false,
scrollMinX: 2,
scrollMinY: 2,
trackHoverProximityX: 50,
trackHoverProximityY: 50,
easingX: ScrollEasing.easeQuadOut,
easingY: ScrollEasing.easeQuadOut,
// Handle drag
captureHandleDragX: true,
captureHandleDragY: true,
interruptibleHandleDrag: true,
// Fast track
captureFastTrackX: true,
captureFastTrackY: true,
fastTrackModeX: FastTrackMode.GOTO,
fastTrackModeY: FastTrackMode.GOTO,
fastTrackScrollDurationX: 500,
fastTrackScrollDurationY: 500,
// Keyboard
captureKeyboard: true,
keyboardStepX: 30,
keyboardStepY: 30,
keyboardScrollDurationX: 200,
keyboardScrollDurationY: 200,
// Wheel
captureWheel: true,
// Used when scroll by line-height is requested.
wheelLineHeight: 24,
wheelStepX: 100,
wheelStepY: 100,
propagateWheelScrollX: false,
propagateWheelScrollY: true,
swapWheelAxes: false,
wheelScrollDurationX: 100,
wheelScrollDurationY: 100,
// Touch
captureTouch: true,
propagateTouchScrollX: true,
propagateTouchScrollY: true,
touchSingleAxis: true,
touchStartDistance: 10,
continuousTouchScrollX: false,
continuousTouchScrollY: false,
inertiaEasingX: ScrollEasing.easeQuadOut,
inertiaEasingY: ScrollEasing.easeQuadOut,
inertiaDistanceX: (dx, dt) => dx / dt * 100,
inertiaDistanceY: (dy, dt) => dy / dt * 100,
inertiaDurationX: (dx, dt) => dx / dt * 100,
inertiaDurationY: (dy, dt) => dy / dt * 100,
// Layout
trackChildrenX: null,
trackChildrenY: null,
handleChildrenX: null,
handleChildrenY: null
};
constructor(props) {
super(props);
let _scrollX = 0,
_scrollY = 0,
_prevX = 0,
_prevY = 0,
_targetX = 0,
_targetY = 0,
_durationX = 0,
_durationY = 0,
_easingX,
_easingY,
_timestampX = 0,
_timestampY = 0,
_dispatchPrevented = false,
_scrollMaxX = 0,
_scrollMaxY = 0,
_trackMaxX = 0,
_trackMaxY = 0,
_requiresScrollBarX = false,
_requiresScrollBarY = false,
_requestId,
_scrollingX = false,
_scrollingY = false,
_causeX = null,
_causeY = null,
_tickX = 0,
_tickY = 0,
// Refs
_root,
_viewport,
_handleX,
_handleY,
_trackX,
_trackY;
const setHandleX = ref => _handleX = ref;
const setHandleY = ref => _handleY = ref;
const setTrackX = ref => _trackX = ref;
const setTrackY = ref => _trackY = ref;
this.componentDidMount = () => {
_root = findDOMNode(this);
_viewport = _root.firstChild;
const requestPropagateChanges = () => {
if (window.cancelAnimationFrame) {
_requestId = requestAnimationFrame(requestPropagateChanges);
} else {
_requestId = setTimeout(requestPropagateChanges, 1000 / 30);
}
propagateChanges();
};
requestPropagateChanges();
addEventListener('mousemove', handleTrackHover);
// Fix https://github.com/facebook/react/issues/8968
_root.addEventListener('touchstart', handleTouchStart);
};
this.componentWillUnmount = () => {
_root = null;
if (window.cancelAnimationFrame) {
cancelAnimationFrame(_requestId);
} else {
clearTimeout(_requestId);
}
removeEventListener('mousemove', handleTrackHover);
};
this.componentDidUpdate = () => {
_viewport = _root.firstChild;
propagateChanges();
};
this.render = () => {
const {
className,
style,
disabled,
outsetScrollBarX,
outsetScrollBarY,
nativeScrollBars,
disableScrollX,
disableScrollY,
hideScrollBarX,
hideScrollBarY,
children,
trackChildrenX,
trackChildrenY,
handleChildrenX,
handleChildrenY
} = this.props;
let classNames = ['scroll-box'];
if (className) {
classNames.push(className);
}
if (disabled) {
classNames.push('scroll-box--disabled');
}
if (outsetScrollBarX) {
classNames.push('scroll-box--outset-x');
}
if (outsetScrollBarY) {
classNames.push('scroll-box--outset-y');
}
if (!disableScrollX && !hideScrollBarX) {
classNames.push('scroll-box--enable-x');
}
if (!disableScrollY && !hideScrollBarY) {
classNames.push('scroll-box--enable-y');
}
if (nativeScrollBars) {
classNames.push('scroll-box--native-scroll-bars');
}
return (
<div style={style}
className={classNames.join(' ')}
onWheel={handleWheel}
onKeyDown={handleKeyDown}
tabIndex="-1">
{children}
<div className="scroll-box__track scroll-box__track--x"
onMouseDown={handleFastTrackX}
ref={setTrackX}>
<div className="scroll-box__handle scroll-box__handle--x"
onMouseDown={handleDragStartX}
ref={setHandleX}>
{handleChildrenX}
</div>
{trackChildrenX}
</div>
<div className="scroll-box__track scroll-box__track--y"
onMouseDown={handleFastTrackY}
ref={setTrackY}>
<div className="scroll-box__handle scroll-box__handle--y"
onMouseDown={handleDragStartY}
ref={setHandleY}>
{handleChildrenY}
</div>
{trackChildrenY}
</div>
</div>
);
};
this.scrollTo = ({
x, y,
easing,
easingX = easing || this.props.easingX,
easingY = easing || this.props.easingY,
duration = 0,
durationX = duration,
durationY = duration,
dispatchPrevented = false
} = {}) => {
if (!isNaN(x) && x !== null) {
_prevX = _scrollX;
_targetX = x | 0;
_easingX = easingX;
_durationX = durationX;
_timestampX = Date.now();
_dispatchPrevented = dispatchPrevented;
_tickX++;
}
if (!isNaN(y) && y !== null) {
_prevY = _scrollY;
_targetY = y | 0;
_easingY = easingY;
_durationY = durationY;
_timestampY = Date.now();
_dispatchPrevented = dispatchPrevented;
_tickY++;
}
propagateChanges();
};
this.scrollToX = (x, options = {}) => this.scrollTo({...options, x});
this.scrollToY = (y, options = {}) => this.scrollTo({...options, y});
this.scrollBy = ({dx, dy, ...options} = {}) => {
this.scrollTo({
...options,
x: _targetX + dx,
y: _targetY + dy
});
};
this.scrollByX = (dx, options = {}) => this.scrollBy({...options, dx});
this.scrollByY = (dy, options = {}) => this.scrollBy({...options, dy});
this.scrollToPage = ({
x, y,
...options
} = {}) => {
x *= this.getPageWidth();
y *= this.getPageHeight();
this.scrollTo({...options, x, y});
};
this.scrollToPageX = (x, options = {}) => this.scrollToPage({...options, x});
this.scrollToPageY = (y, options = {}) => this.scrollToPage({...options, y});
this.scrollByPage = ({
dx, dy,
...options
} = {}) => {
dx *= this.getPageWidth();
dy *= this.getPageHeight();
this.scrollBy({...options, dx, dy});
};
this.scrollByPageX = (dx, options = {}) => this.scrollByPage({...options, dx});
this.scrollByPageY = (dy, options = {}) => this.scrollByPage({...options, dy});
this.getPageWidth = () => _viewport.clientWidth;
this.getPageHeight = () => _viewport.clientHeight;
Object.defineProperties(this, {
targetX: {
get: () => _targetX,
set: x => this.scrollToX(x)
},
targetY: {
get: () => _targetY,
set: y => this.scrollToY(y)
},
scrollX: {
get: () => _scrollX,
set: x => this.scrollToX(x)
},
scrollY: {
get: () => _scrollY,
set: y => this.scrollToY(y)
},
scrollMaxX: {
get: () => _scrollMaxX
},
scrollMaxY: {
get: () => _scrollMaxY
}
});
const isTargetIgnored = target => /textarea|input/i.test(target.tagName);
const propagateChanges = () => {
const {
disableScrollX,
disableScrollY,
scrollMinX,
scrollMinY,
nativeScrollBars,
outsetScrollBarX,
outsetScrollBarY,
onScroll,
onScrollX,
onScrollY,
onScrollStart,
onScrollStartX,
onScrollStartY,
onScrollEnd,
onScrollEndX,
onScrollEndY
} = this.props;
const {
clientWidth,
clientHeight,
offsetWidth,
offsetHeight,
scrollWidth,
scrollHeight,
scrollTop,
scrollLeft
} = _viewport;
_scrollMaxX = scrollWidth - clientWidth;
_scrollMaxY = scrollHeight - clientHeight;
_requiresScrollBarX = !disableScrollX && _scrollMaxX >= scrollMinX;
_requiresScrollBarY = !disableScrollY && _scrollMaxY >= scrollMinY;
_root.classList.toggle('scroll-box--requires-x', _requiresScrollBarX);
_root.classList.toggle('scroll-box--requires-y', _requiresScrollBarY);
_viewport.style.height = do {
if (nativeScrollBars && outsetScrollBarX) {
`calc(100% + ${offsetHeight - clientHeight}px)`;
} else {
'100%';
}
};
_viewport.style.width = do {
if (nativeScrollBars && outsetScrollBarY) {
`calc(100% + ${offsetWidth - clientWidth}px)`;
} else {
'100%';
}
};
_targetX = Math.max(0, Math.min(_targetX, _scrollMaxX));
_targetY = Math.max(0, Math.min(_targetY, _scrollMaxY));
let nextScrollX = _scrollX,
nextScrollY = _scrollY;
if (_scrollX === scrollLeft && _scrollY === scrollTop) {
// Controlled scroll position coincides with viewport position.
if (nextScrollX !== _targetX) {
const elapsedX = Date.now() - _timestampX;
if (elapsedX < _durationX) {
nextScrollX = _prevX + _easingX(elapsedX / _durationX, elapsedX, 0, 1, _durationX) * (_targetX - _prevX) | 0;
} else {
nextScrollX = _targetX;
}
}
if (nextScrollY !== _targetY) {
const elapsedY = Date.now() - _timestampY;
if (elapsedY < _durationY) {
nextScrollY = _prevY + _easingY(elapsedY / _durationY, elapsedY, 0, 1, _durationY) * (_targetY - _prevY) | 0;
} else {
nextScrollY = _targetY;
}
}
}
const clientScrollingX = _scrollX !== scrollLeft,
clientScrollingY = _scrollY !== scrollTop;
if (clientScrollingX) {
_targetX = nextScrollX = scrollLeft;
}
if (clientScrollingY) {
_targetY = nextScrollY = scrollTop;
}
const nextScrollingX = nextScrollX !== _targetX,
nextScrollingY = nextScrollY !== _targetY;
const dx = _scrollX - nextScrollX,
dy = _scrollY - nextScrollY;
const tickX = _tickX,
tickY = _tickY;
if (!_dispatchPrevented) {
// Events can be triggered.
// Checking ticks after each event callback invocation to ensure that any scroll
// methods were not called inside those callbacks.
if (
(nextScrollingX || nextScrollingY || clientScrollingX || clientScrollingY) &&
!_scrollingX && !_scrollingY
) {
onScrollStart(this, _causeX, _causeY);
}
if (tickX === _tickX && nextScrollingX && !_scrollingX) {
onScrollStartX(this, _causeX);
}
if (tickY === _tickY && nextScrollingY && !_scrollingY) {
onScrollStartY(this, _causeY);
}
if (
tickX === _tickX && tickY === _tickY &&
(dx || dy)
) {
onScroll(this, dx, dy, _causeX, _causeY);
}
if (tickX === _tickX && dx) {
onScrollX(this, dx, _causeX);
}
if (tickY === _tickY && dy) {
onScrollY(this, dy, _causeY);
}
if (
tickX === _tickX && tickY === _tickY &&
!nextScrollingX && !nextScrollingY &&
(_scrollingX || _scrollingY || clientScrollingX || clientScrollingY)
) {
onScrollEnd(this, _causeX, _causeY);
}
if (tickX === _tickX && !nextScrollingX && _scrollingX) {
onScrollEndX(this, _causeX);
}
if (tickY === _tickY && !nextScrollingY && _scrollingY) {
onScrollEndY(this, _causeY);
}
if (tickX === _tickX && (_causeX !== ScrollCause.TOUCH || _causeX !== ScrollCause.HANDLE_DRAG)) {
_causeX = null;
}
if (tickY === _tickY && (_causeY !== ScrollCause.TOUCH || _causeY !== ScrollCause.HANDLE_DRAG)) {
_causeY = null;
}
}
if (dx && tickX === _tickX) {
_viewport.scrollLeft = _scrollX = nextScrollX;
}
if (dy && tickY === _tickY) {
_viewport.scrollTop = _scrollY = nextScrollY;
}
if (!nativeScrollBars) {
_trackMaxX = _trackX.clientWidth - _handleX.offsetWidth;
_handleX.style.width = clientWidth / scrollWidth * 100 + '%';
_handleX.style.left = _trackMaxX * nextScrollX / _scrollMaxX + 'px';
_trackMaxY = _trackY.clientHeight - _handleY.offsetHeight;
_handleY.style.height = clientHeight / scrollHeight * 100 + '%';
_handleY.style.top = _trackMaxY * nextScrollY / _scrollMaxY + 'px';
}
};
const handleKeyDown = event => {
const {target, keyCode, shiftKey} = event;
const {
disabled,
captureKeyboard,
keyboardStepX,
keyboardStepY,
keyboardScrollDurationX,
keyboardScrollDurationY
} = this.props;
if (disabled || !captureKeyboard || isTargetIgnored(target)) {
// Do not handle any keyboard events when text-related controls are focused.
return;
}
const optionsX = {duration: keyboardScrollDurationX},
optionsY = {duration: keyboardScrollDurationY};
switch (keyCode) {
case 36: // Home
event.preventDefault();
_causeY = ScrollCause.KEYBOARD;
this.scrollToY(0, optionsY);
break;
case 35: // End
event.preventDefault();
_causeY = ScrollCause.KEYBOARD;
this.scrollToY(_scrollMaxY, optionsY);
break;
case 33: // Page Up
case 34: // Page Down
event.preventDefault();
let dy = this.getPageHeight(),
dx = this.getPageWidth();
if (keyCode === 33) { // Page Up
dy *= -1;
dx *= -1;
}
if (shiftKey) {
_causeX = ScrollCause.KEYBOARD;
this.scrollByX(dx, optionsX);
} else {
_causeY = ScrollCause.KEYBOARD;
this.scrollByY(dy, optionsY);
}
break;
case 38: // Up
event.preventDefault();
_causeY = ScrollCause.KEYBOARD;
this.scrollByY(-keyboardStepY, optionsY);
break;
case 40: // Down
event.preventDefault();
_causeY = ScrollCause.KEYBOARD;
this.scrollByY(keyboardStepY, optionsY);
break;
case 37: // Left
event.preventDefault();
_causeX = ScrollCause.KEYBOARD;
this.scrollByX(-keyboardStepX, optionsX);
break;
case 39: // Right
event.preventDefault();
_causeX = ScrollCause.KEYBOARD;
this.scrollByX(keyboardStepX, optionsX);
break;
}
};
const handleFastTrack = (event, horizontal) => {
const {
disabled,
captureFastTrackX,
captureFastTrackY,
fastTrackModeX,
fastTrackModeY,
fastTrackScrollDurationX,
fastTrackScrollDurationY
} = this.props;
if (disabled || !(captureFastTrackX || captureFastTrackY) || event.button) {
// Component is disabled or secondary mouse button is being pressed.
return;
}
const {
clientWidth,
clientHeight,
scrollWidth,
scrollHeight
} = _viewport;
if (horizontal) {
if (!captureFastTrackX) {
return;
}
_causeX = ScrollCause.FAST_TRACK;
const pointerX = event.clientX - _trackX.getBoundingClientRect().left,
optionsX = {duration: fastTrackScrollDurationX};
switch (fastTrackModeX) {
case FastTrackMode.PAGING:
this.scrollToX(_targetX + (1 - 2 * (pointerX < _handleX.offsetLeft)) * this.getPageWidth(), optionsX);
break;
case FastTrackMode.GOTO:
this.scrollToX(pointerX / _trackX.clientWidth * scrollWidth - clientWidth / 2, optionsX);
break;
}
} else {
if (!captureFastTrackY) {
return;
}
_causeY = ScrollCause.FAST_TRACK;
const pointerY = event.clientY - _trackY.getBoundingClientRect().top,
optionsY = {duration: fastTrackScrollDurationY};
switch (fastTrackModeY) {
case FastTrackMode.PAGING:
this.scrollToY(_targetY + (1 - 2 * (pointerY < _handleY.offsetTop)) * this.getPageHeight(), optionsY);
break;
case FastTrackMode.GOTO:
this.scrollToY(pointerY / _trackY.clientHeight * scrollHeight - clientHeight / 2, optionsY);
break;
}
}
};
const handleFastTrackX = event => handleFastTrack(event, true);
const handleFastTrackY = event => handleFastTrack(event, false);
const handleDragStart = (event, horizontal) => {
const {
disabled,
captureHandleDragX,
captureHandleDragY,
interruptibleHandleDrag
} = this.props;
// Handle can be dragged with left mouse button only.
if (disabled || !(captureHandleDragX || captureHandleDragY) || event.button) {
return;
}
event.preventDefault();
event.stopPropagation();
let track;
if (horizontal) {
_causeX = ScrollCause.HANDLE_DRAG;
track = _trackX;
} else {
_causeY = ScrollCause.HANDLE_DRAG;
track = _trackY;
}
const offsetX = event.clientX - _handleX.offsetLeft,
offsetY = event.clientY - _handleY.offsetTop;
const handleDrag = event => {
const cause = horizontal ? _causeX : _causeY;
if (!_root || event.button || (interruptibleHandleDrag && cause !== ScrollCause.HANDLE_DRAG)) {
stopDrag();
return;
}
if (horizontal) {
_causeX = ScrollCause.HANDLE_DRAG;
this.scrollToX(_scrollMaxX * (event.clientX - offsetX) / _trackMaxX);
} else {
_causeY = ScrollCause.HANDLE_DRAG;
this.scrollToY(_scrollMaxY * (event.clientY - offsetY) / _trackMaxY);
}
};
const handleDragEnd = () => {
if (horizontal) {
_causeX = null;
} else {
_causeY = null;
}
stopDrag();
};
const stopDrag = () => {
removeEventListener('mousemove', handleDrag);
removeEventListener('mouseup', handleDragEnd);
track.classList.remove('scroll-box__track--dragged');
};
addEventListener('mousemove', handleDrag);
addEventListener('mouseup', handleDragEnd);
track.classList.add('scroll-box__track--dragged');
};
const handleDragStartX = event => handleDragStart(event, true);
const handleDragStartY = event => handleDragStart(event, false);
const handleWheel = event => {
let {target, deltaMode, deltaX, deltaY, shiftKey, nativeEvent} = event;
const {
wheelStepX,
wheelStepY,
disabled,
nativeScrollBars,
captureWheel,
wheelLineHeight,
propagateWheelScrollX,
propagateWheelScrollY,
swapWheelAxes,
wheelScrollDurationX,
wheelScrollDurationY
} = this.props;
if (nativeScrollBars && !captureWheel) {
event.preventDefault();
}
if (disabled || nativeScrollBars || (target !== _viewport && isTargetIgnored(target))) {
return;
}
// By default, Google Chrome changes scrolling orientation if shift key is pressed,
// so propagate this behavior to other browsers as well.
if (shiftKey && !deltaX) {
deltaX = deltaY;
deltaY = 0;
}
if (swapWheelAxes) {
const buffer = deltaX;
deltaX = deltaY;
deltaY = buffer;
}
const stopPropagationX = !deltaX || (_requiresScrollBarX && ((deltaX < 0 && _targetX > 0) || (deltaX > 0 && _targetX !== _scrollMaxX))),
stopPropagationY = !deltaY || (_requiresScrollBarY && ((deltaY < 0 && _targetY > 0) || (deltaY > 0 && _targetY !== _scrollMaxY)));
const propagateX = deltaX * !stopPropagationX * propagateWheelScrollX,
propagateY = deltaY * !stopPropagationY * propagateWheelScrollY;
if (propagateX || propagateY) {
if (propagateX === deltaX && propagateY === deltaY) {
return;
} else {
event.stopPropagation();
event.preventDefault();
target.dispatchEvent(new WheelEvent(nativeEvent.type, {deltaX: propagateX, deltaY: propagateY}));
}
}
let dx = deltaX * _requiresScrollBarX,
dy = deltaY * _requiresScrollBarY;
if (!dx && !dy) {
return;
}
event.stopPropagation();
event.preventDefault();
// Converts received delta values into pixels.
switch (deltaMode) {
case 0x01: // Delta values are specified in lines.
dx *= wheelLineHeight;
dy *= wheelLineHeight;
break;
case 0x02: // Delta values are specified in pages.
dx *= this.getPageWidth();
dy *= this.getPageHeight();
break;
default:
// Delta values are specified in pixels.
break;
}
dx *= wheelStepX / 100;
dy *= wheelStepY / 100;
let nextTargetX = _targetX + dx,
nextTargetY = _targetY + dy;
// Prevent jumping to target position when animated scrolling is in progress,
// but preserve scroll speed when mouse wheel events arrive frequently.
if (Date.now() - _timestampX > wheelScrollDurationX) {
nextTargetX = _scrollX + dx;
}
if (Date.now() - _timestampX > wheelScrollDurationY) {
nextTargetY = _scrollY + dy;
}
if (dx) {
_causeX = ScrollCause.MOUSE_WHEEL;
this.scrollToX(nextTargetX, {duration: wheelScrollDurationX});
}
if (dy) {
_causeY = ScrollCause.MOUSE_WHEEL;
this.scrollToY(nextTargetY, {duration: wheelScrollDurationY});
}
};
const toggleTrackHover = (track, status) => track.classList.toggle('scroll-box__track--hover', status);
const isTrackHovered = (event, track, proximity) => {
const {clientX, clientY} = event,
{width, left, top, height} = track.getBoundingClientRect();
return proximity > clientY - height - top &&
proximity > clientX - width - left &&
proximity > left - clientX &&
proximity > top - clientY;
};
const handleTrackHover = event => {
const {
disabled,
nativeScrollBars,
captureHandleDragX,
captureHandleDragY,
captureFastTrackX,
captureFastTrackY,
trackHoverProximityX,
trackHoverProximityY
} = this.props;
if ('orientation' in window || nativeScrollBars || disabled) {
return;
}
if (_requiresScrollBarX && (captureHandleDragX || captureFastTrackX)) {
const statusX = (!event.buttons || _causeX === ScrollCause.HANDLE_DRAG) && isTrackHovered(event, _trackX, trackHoverProximityX);
toggleTrackHover(_trackX, statusX);
}
if (_requiresScrollBarY && (captureHandleDragY || captureFastTrackY)) {
const statusY = (!event.buttons || _causeY === ScrollCause.HANDLE_DRAG) && isTrackHovered(event, _trackY, trackHoverProximityY);
toggleTrackHover(_trackY, statusY);
}
};
const isIgnoredChangeX = dx => (dx < 0 && !_targetX) || (dx > 0 && _targetX === _scrollMaxX);
const isIgnoredChangeY = dy => (dy < 0 && !_targetY) || (dy > 0 && _targetY === _scrollMaxY);
const preventDefault = event => {
if (event.cancelable) {
event.preventDefault();
}
};
const handleTouchStart = event => {
const {target, touches} = event;
const {
disabled,
nativeScrollBars,
captureTouch,
propagateTouchScrollX,
propagateTouchScrollY,
touchSingleAxis,
touchStartDistance,
continuousTouchScrollX,
continuousTouchScrollY,
inertiaEasingX,
inertiaEasingY,
inertiaDistanceX,
inertiaDistanceY,
inertiaDurationX,
inertiaDurationY
} = this.props;
if (nativeScrollBars && !captureTouch) {
preventDefault(event);
}
if (disabled || nativeScrollBars || touches.length > 1 || (target !== _viewport && isTargetIgnored(target))) {
return;
}
const {
clientX: initialClientX,
clientY: initialClientY
} = touches[0];
const initialScrollX = _scrollX,
initialScrollY = _scrollY;
let prevClientX,
prevClientY,
lastClientX,
lastClientY,
prevTimestamp,
lastTimestamp,
horizontal,
stopPropagationX,
stopPropagationY;
const handleTouchMove = event => {
const {clientX, clientY} = event.touches[0];
const dx = initialClientX - clientX,
dy = initialClientY - clientY,
pending = isNaN(lastClientX);
if (pending && Math.sqrt(dx * dx + dy * dy) < touchStartDistance) {
preventDefault(event);
return;
}
if (pending && touchSingleAxis) {
horizontal = Math.abs(dx) > Math.abs(dy);
}
if (pending || continuousTouchScrollX) {
stopPropagationX = _requiresScrollBarX && !isIgnoredChangeX(dx);
}
if (pending || continuousTouchScrollY) {
stopPropagationY = _requiresScrollBarY && !isIgnoredChangeY(dy);
}
prevClientX = lastClientX;
prevClientY = lastClientY;
lastClientX = clientX;
lastClientY = clientY;
prevTimestamp = lastTimestamp;
lastTimestamp = Date.now();
const targetX = initialScrollX + dx,
targetY = initialScrollY + dy;
if (touchSingleAxis) {
if (horizontal) {
if (stopPropagationX || !propagateTouchScrollX) {
preventDefault(event);
this.scrollToX(targetX);
}
} else {
if (stopPropagationY || !propagateTouchScrollY) {
preventDefault(event);
this.scrollToY(targetY);
}
}
} else {
if (stopPropagationX || stopPropagationY || (!propagateTouchScrollX && !propagateTouchScrollY)) {
preventDefault(event);
this.scrollTo({x: targetX, y: targetY});
}
}
};
const handleTouchEnd = () => {
if (!isNaN(prevClientX)) {
const dt = lastTimestamp - prevTimestamp,
dx = prevClientX - lastClientX,
dy = prevClientY - lastClientY,
distanceX = inertiaDistanceX(dx, dt),
distanceY = inertiaDistanceY(dy, dt),
durationX = Math.abs(inertiaDurationX(dx, dt)),
durationY = Math.abs(inertiaDurationY(dy, dt));
const targetX = _targetX + distanceX,
targetY = _targetY + distanceY;
if (touchSingleAxis) {
if (horizontal) {
this.scrollToX(targetX, {easingX: inertiaEasingX, durationX});
} else {
this.scrollToY(targetY, {easingY: inertiaEasingY, durationY: 100});
}
} else {
this.scrollTo({
x: targetX,
y: targetY,
easingX: inertiaEasingX,
easingY: inertiaEasingY,
durationX,
durationY
});
}
}
removeEventListener('touchmove', handleTouchMove);
removeEventListener('touchend', handleTouchEnd);
removeEventListener('touchcancel', handleTouchEnd);
};
addEventListener('touchmove', handleTouchMove, {passive: false});
addEventListener('touchend', handleTouchEnd);
addEventListener('touchcancel', handleTouchEnd);
};
}
}
export {ScrollBox} from './ScrollBox';
export {AbstractScrollBox, FastTrackMode, ScrollCause} from './AbstractScrollBox';
@scroll-box: scroll-box; // Namespace class
@scroll-bar-border-radius: @scroll-bar-hover-weight; // Rounded caps.
@scroll-bar-weight: 6px; // Height of width for horizontal or vertical scroll bar respectively.
@scroll-bar-hover-weight: (@scroll-bar-weight * 1.7);
@scroll-bar-offset: 4px; // Distance from scroll box container border to scroll bar.
@scroll-bar-min-size: 30px;
@scroll-bar-max-size: 100%;
@scroll-bar-y-width: @scroll-bar-weight;
@scroll-bar-y-hover-width: @scroll-bar-hover-weight;
@scroll-bar-y-top: @scroll-bar-offset;
@scroll-bar-y-bottom: @scroll-bar-offset;
@scroll-bar-y-right: @scroll-bar-offset;
@scroll-bar-y-min-height: @scroll-bar-min-size;
@scroll-bar-y-max-height: @scroll-bar-max-size;
@scroll-bar-x-height: @scroll-bar-weight;
@scroll-bar-x-hover-height: @scroll-bar-hover-weight;
@scroll-bar-x-left: @scroll-bar-offset;
@scroll-bar-x-right: @scroll-bar-offset;
@scroll-bar-x-bottom: @scroll-bar-offset;
@scroll-bar-x-min-width: @scroll-bar-min-size;
@scroll-bar-x-max-width: @scroll-bar-max-size;
@scroll-cursor-handle: default;
@scroll-cursor-track: default;
.@{scroll-box} {
position: relative;
&:focus {
outline: none;
}
&--disabled {
> .@{scroll-box}__viewport {
// Hide client scrollbars.
overflow: hidden !important;
}
> .@{scroll-box}__track {
// Hide custom scrollbars.
visibility: hidden !important;
}
}
// By default scroll box looks like an unwrapped container.
&--wrapped {
> .@{scroll-box}__viewport {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
overflow: hidden;
padding: inherit;
border-radius: inherit;
}
> .@{scroll-box}__track {
display: block;
}
}
// Used if fallback to client system scrolling should occur.
&--native-scroll-bars {
&.@{scroll-box}--enable-y.@{scroll-box}--requires-y > .@{scroll-box}__viewport {
overflow-y: auto;
}
&.@{scroll-box}--enable-x.@{scroll-box}--requires-x > .@{scroll-box}__viewport {
overflow-x: auto;
}
> .@{scroll-box}__viewport {
-webkit-overflow-scrolling: touch;
}
}
&:not(.@{scroll-box}--native-scroll-bars) {
&.@{scroll-box}--enable-y.@{scroll-box}--requires-y > .@{scroll-box}__track--y {
visibility: visible;
}
&.@{scroll-box}--enable-x.@{scroll-box}--requires-x > .@{scroll-box}__track--x {
visibility: visible;
}
// Both non-client scrollbars are visible and they are inside
// scrollable are, we should prevent their intersection in the
// shared corner.
&.@{scroll-box}--enable-x.@{scroll-box}--requires-x.@{scroll-box}--enable-y.@{scroll-box}--requires-y:not(.@{scroll-box}--outset) {
> .@{scroll-box}__track {
&--y {
margin-bottom: (2 * @scroll-bar-y-bottom + @scroll-bar-x-height);
}
&--x {
margin-right: (2 * @scroll-bar-x-right + @scroll-bar-y-width);
}
}
}
}
&__handle,
&__track {
position: absolute;
border-radius: @scroll-bar-border-radius;
transition: .2s ease-in-out;
}
&__handle {
transition-property: background;
cursor: @scroll-cursor-handle;
&--y {
width: 100%;
min-height: @scroll-bar-y-min-height;
max-height: @scroll-bar-y-max-height;
top: 0;
}
&--x {
height: 100%;
min-width: @scroll-bar-x-min-width;
max-width: @scroll-bar-x-max-width;
left: 0;
}
}
&__track {
display: none; // Scroll not used by default.
visibility: hidden;
transition-property: background, width, height;
cursor: @scroll-cursor-track;
&--y {
top: 0;
bottom: 0;
right: 0;
width: @scroll-bar-y-width;
margin: @scroll-bar-y-top @scroll-bar-y-right @scroll-bar-y-bottom 0;
&.@{scroll-box}__track {
&--hover,
&--dragged {
width: @scroll-bar-y-hover-width;
}
}
.@{scroll-box}--outset > & {
left: 100%;
margin-left: @scroll-bar-y-right;
}
}
&--x {
left: 0;
right: 0;
bottom: 0;
height: @scroll-bar-x-height;
margin: 0 @scroll-bar-x-right @scroll-bar-x-bottom @scroll-bar-x-left;
&.@{scroll-box}__track {
&--hover,
&--dragged {
height: @scroll-bar-x-hover-height;
}
}
.@{scroll-box}--outset > & {
top: 100%;
margin-top: @scroll-bar-x-bottom;
}
}
}
// Apply default coloring.
.scroll-box-color();
}
.scroll-box-color(
@handle-bg: rgba(0,0,0,.4);
@track-bg: transparent;
@hover-handle-bg: rgba(0,0,0,.6);
@hover-track-bg: rgba(0,0,0,.2);
) {
> .@{scroll-box}__track {
background: @track-bg;
> .@{scroll-box}__handle {
background: @handle-bg;
}
&--hover,
&--dragged {
background: @hover-track-bg;
> .@{scroll-box}__handle {
background: @hover-handle-bg;
}
}
}
}
import React from 'react';
import {AbstractScrollBox} from './AbstractScrollBox';
export class ScrollBox extends React.Component {
render() {
return (
<AbstractScrollBox {...this.props}>
<div className="scroll-box__viewport">
{this.props.children}
</div>
</AbstractScrollBox>
);
}
}
+3
-2
{
"name": "react-scroll-box",
"version": "0.2.9",
"version": "0.3.4",
"author": "Savva Mikhalevski",

@@ -55,4 +55,5 @@ "description": "Charged cross-browser and cross-platform scrollable container implementation with no external dependencies but React 0.13+",

"react": ">=0.13.0",
"react-dom": ">=0.13.0"
"react-dom": ">=0.13.0",
"prop-types": ">=15.5.10"
}
}
+3
-1

@@ -5,2 +5,4 @@ # React Scroll Box

_Note_ I'm currently working on `resct-scroll-box@0.3`. It would contain [50+ configurable paramters](https://github.com/smikhalevski/react-scroll-box/blob/master/src/main/GenericScrollBox.js#L32) and would provide fine grained tracking of scrolling events and [their causes](https://github.com/smikhalevski/react-scroll-box/blob/master/src/main/GenericScrollBox.js#L15).
Charged cross-browser and cross-platform scrollable container implementation with no external dependencies but React 0.13+.

@@ -47,3 +49,3 @@

In most cases you should use `ScrollBox` to create a scrollable area, but in cause you need more control over viewport use [`GenericScrollBox`](#genericscrollbox).
In most cases you should use `ScrollBox` to create a scrollable area, but in case you need more control over viewport use [`GenericScrollBox`](#genericscrollbox).

@@ -50,0 +52,0 @@ By default, `ScrollBox` has no decoration and behaves as a regular `div` container. Specify height for scroll box in your styles, otherwise container would contract to zero height.

import React from 'react';
import {findDOMNode} from 'react-dom';
import {any, bool, element, func, node, number, object, oneOf, string} from 'prop-types';
const {number, bool, func, oneOf, any} = React.PropTypes;
function isCoordinate(value) {
return value != null && !isNaN(value);
}
export const ScrollAxes = {
X: 'x',
Y: 'y',
XY: 'xy'
export const FastTrackMode = {
PAGING: 'paging',
GOTO: 'goto'
};
export const FastTrack = {
PAGING: 'paging',
GOTO: 'goto',
OFF: null
export const ScrollCause = {
HANDLE_DRAG: 0,
MOUSE_WHEEL: 1,
FAST_TRACK: 2,
KEYBOARD: 3,
TOUCH: 4
};
export const FastTrackModeShape = oneOf([FastTrackMode.GOTO, FastTrackMode.PAGING]);
export function easeQuadOut(percent, elapsed, min, max, duration) {
percent -= 1;
return min + max * Math.sqrt(1 - Math.pow(percent, 2));
}
export class GenericScrollBox extends React.Component {
static defaultProps = {
className: 'scroll-box--wrapped',
axes: ScrollAxes.XY,
hoverProximity: 50,
disabled: false,
outset: false,
scrollMinX: 2,
scrollMinY: 2,
defaultEasing: (percent, elapsed, min, max, duration) => max * Math.sqrt(1 - --percent * percent) + min,
static propTypes = {
// Viewport element.
children: element.isRequired,
// Drag
captureHandleDrag: true,
// Use client scroll bars.
clientScrollBars: bool,
className: any,
style: object,
disabled: bool,
// Events
onViewportScroll: target => {},
onScroll: func,
onScrollX: func,
onScrollY: func,
// Fast tracking
fastTrack: FastTrack.GOTO,
fastTrackDuration: 500,
onScrollStart: func,
onScrollStartX: func,
onScrollStartY: func,
// Keyboard
captureKeyboard: true,
keyboardStepX: 30,
keyboardStepY: 30,
keyboardScrollDuration: 200,
onScrollEnd: func,
onScrollEndX: func,
onScrollEndY: func,
// Wheel
captureWheel: true,
wheelStepX: 30,
wheelStepY: 30,
propagateWheelScroll: false,
swapWheelAxes: false,
wheelScrollDuration: 100,
// Allow scrolling in corresponding direction.
disableScrollX: bool,
disableScrollY: bool,
// Touch
propagateTouchScroll: false
};
// Toggle scroll bar visibility for corresponding direction.
hideScrollBarX: bool,
hideScrollBarY: bool,
static propTypes = {
nativeScroll: bool,
className: any,
axes: oneOf([ScrollAxes.X, ScrollAxes.Y, ScrollAxes.XY]),
hoverProximity: number,
disabled: bool,
outset: bool,
// Toggle show scroll bars outside of scroll box rectangle.
// This has no effect when client scroll bars are enabled and they are shown above content.
outsetScrollBarX: bool,
outsetScrollBarY: bool,
// Minimum number of pixels when scroll bars are required.
scrollMinX: number,
scrollMinY: number,
defaultEasing: func,
// Drag
captureHandleDrag: bool,
// Distance from cursor to edge of the scroll track when scroll bar is considered to be hovered.
trackHoverProximityX: number,
trackHoverProximityY: number,
// Events
onViewportScroll: func,
// Default easing functions applied when scroll with non-zero duration is requested.
easingX: func,
easingY: func,
// Fast tracking
fastTrack: oneOf([FastTrack.GOTO, FastTrack.PAGING, FastTrack.OFF]),
fastTrackDuration: number,
// Handle drag
captureHandleDragX: bool,
captureHandleDragY: bool,
permitHandleDragInterruption: bool,
// Fast tracking occurs when user clicks on scroll track.
captureFastTrackX: bool,
captureFastTrackY: bool,
fastTrackModeX: FastTrackModeShape,
fastTrackModeY: FastTrackModeShape,
fastTrackScrollDurationX: number,
fastTrackScrollDurationY: number,
// Keyboard

@@ -83,587 +100,983 @@ captureKeyboard: bool,

keyboardStepY: number,
keyboardScrollDuration: number,
keyboardScrollDurationX: number,
keyboardScrollDurationY: number,
// Wheel
captureWheel: bool,
lineHeight: number,
wheelStepX: number,
wheelStepY: number,
propagateWheelScroll: bool,
propagateWheelScrollX: bool,
propagateWheelScrollY: bool,
swapWheelAxes: bool,
wheelScrollDuration: number,
wheelScrollDurationX: number,
wheelScrollDurationY: number,
// Touch
propagateTouchScroll: bool,
captureTouch: bool,
propagateTouchScrollX: bool,
propagateTouchScrollY: bool,
// Layout
trackXChildren: any,
trackYChildren: any,
handleXChildren: any,
handleYChildren: any
trackChildrenX: node,
trackChildrenY: node,
handleChildrenX: node,
handleChildrenY: node
};
// Handle elements.
// Set to `null` when component is unmounted.
handleX = null;
handleY = null;
static defaultProps = {
clientScrollBars: false,
className: 'scroll-box--wrapped',
// Track elements.
// Set to `null` when component is unmounted.
trackX = null;
trackY = null;
disabled: false,
// Viewport element.
// Set to `null` when component is unmounted.
viewport = null;
onScroll: (target, dx, dy, causeX, causeY) => {},
onScrollX: (target, dx, causeX) => {},
onScrollY: (target, dy, causeY) => {},
// Scroll position in pixels that was last requested.
targetX = 0;
targetY = 0;
onScrollStart: (target, causeX, causeY) => {},
onScrollStartX: (target, causeX) => {},
onScrollStartY: (target, causeY) => {},
// Previously requested scroll position.
previousX = 0;
previousY = 0;
onScrollEnd: (target, causeX, causeY) => {},
onScrollEndX: (target, causeX) => {},
onScrollEndY: (target, causeY) => {},
// Actual scroll position that user observes.
// This changes repeatedly during animation, while is static these
// values are equal to `x` and `y`.
scrollX = 0;
scrollY = 0;
disableScrollX: false,
disableScrollY: false,
// Maximum values for horizontal and vertical scroll positions.
scrollMaxX = 0;
scrollMaxY = 0;
hideScrollBarX: false,
hideScrollBarY: false,
// Maximum values for horizontal and vertical handle positions. If native scroll is used then equals to 0.
trackMaxX = 0;
trackMaxY = 0;
outsetScrollBarX: false,
outsetScrollBarY: false,
// Does scroll box require actual presence of horizontal or vertical scroll bars.
// If set to `true`, then axis is permitted via `props.axes` and corresponding `scrollMax >= scrollMin`.
exposesX = false;
exposesY = false;
scrollMinX: 2,
scrollMinY: 2,
// Id of request animation frame that keeps scroll box in sync.
_forceSyncId = 0;
trackHoverProximityX: 50,
trackHoverProximityY: 50,
// Timestamp when scroll position started to change last time.
_easingBeginTimestamp = 0;
easingX: easeQuadOut,
easingY: easeQuadOut,
// Duration of currently running animation. In case no animation is in progress `_easingDuration` equals to 0.
_easingDuration = 0;
// Handle drag
captureHandleDragX: true,
captureHandleDragY: true,
permitHandleDragInterruption: true,
_easing = null;
// Fast track
captureFastTrackX: true,
captureFastTrackY: true,
// If set to `true` prevents triggering `onViewportScroll` if any scrolling occurs.
// Automatically reset to `false` then scroll animation finishes.
_silent = false;
fastTrackModeX: FastTrackMode.GOTO,
fastTrackModeY: FastTrackMode.GOTO,
_touchOffsetX = 0;
_touchOffsetY = 0;
_touchStart = null;
_touchEnd = null;
fastTrackScrollDurationX: 500,
fastTrackScrollDurationY: 500,
scrollBy(dx, dy, duration, easing, silent) {
this.scrollTo(this.targetX + dx, this.targetY + dy, duration, easing, silent);
}
// Keyboard
captureKeyboard: true,
keyboardStepX: 30,
keyboardStepY: 30,
keyboardScrollDuration: 200,
scrollTo(x, y, duration = 0, easing = this.props.defaultEasing, silent = false) {
// Consider actual scroll position to be a starting point.
this._easingDuration = duration;
this._easingBeginTimestamp = Date.now();
this.previousX = this.scrollX;
this.previousY = this.scrollY;
if (!isNaN(x)) {
this.targetX = x;
}
if (!isNaN(y)) {
this.targetY = y;
}
this._easing = easing;
this._silent = Boolean(silent);
this._forceSync();
}
// Wheel
captureWheel: true,
lineHeight: 24,
wheelStepX: 100,
wheelStepY: 100,
propagateWheelScrollX: true,
propagateWheelScrollY: true,
swapWheelAxes: false,
wheelScrollDurationX: 100,
wheelScrollDurationY: 100,
// Synchronize scrollbar positions immediately without waiting for animation frame.
_forceSync() {
const {handleX, handleY, viewport, scrollY, scrollX, previousX, previousY, _silent, _easingBeginTimestamp, _easing, _easingDuration} = this,
{axes, nativeScroll, outset, onViewportScroll, scrollMinX, scrollMinY} = this.props,
{clientWidth, clientHeight, offsetWidth, offsetHeight, scrollWidth, scrollHeight, scrollTop, scrollLeft} = viewport;
// Touch
captureTouch: true,
propagateTouchScrollX: true,
propagateTouchScrollY: true,
};
const SCROLL_MAX_X = Math.max(0, scrollWidth - clientWidth),
SCROLL_MAX_Y = Math.max(0, scrollHeight - clientHeight);
constructor(props) {
super(props);
this.exposesX = axes.indexOf(ScrollAxes.X) > -1 && SCROLL_MAX_X >= scrollMinX;
this.exposesY = axes.indexOf(ScrollAxes.Y) > -1 && SCROLL_MAX_Y >= scrollMinY;
let _scrollX = 0,
_scrollY = 0,
_previousX = 0,
_previousY = 0,
_targetX = 0,
_targetY = 0,
_durationX = 0,
_durationY = 0,
_easingX,
_easingY,
_timestampX = 0,
_timestampY = 0,
_dispatchPrevented = false,
this.el.classList.toggle('scroll-box--show-axis-x', this.exposesX);
this.el.classList.toggle('scroll-box--show-axis-y', this.exposesY);
_scrollMaxX = 0,
_scrollMaxY = 0,
// Scrollbars may have non-zero thickness so in case of outset positioning
// pixes cropped by scrollbar must be compensated.
let width = '100%',
height = '100%';
if (nativeScroll && outset) {
let trackYWidth = offsetWidth - clientWidth,
trackXHeight = offsetHeight - clientHeight;
if (trackYWidth) {
width = `calc(100% + ${trackYWidth}px)`;
_trackMaxX = 0,
_trackMaxY = 0,
_requiresScrollBarX = false,
_requiresScrollBarY = false,
_requestId,
_scrollingX = false,
_scrollingY = false,
_causeX = null,
_causeY = null,
_tickX = 0,
_tickY = 0,
_root,
_viewport,
_handleX,
_handleY,
_trackX,
_trackY;
this.render = () => {
const {
className,
style,
disabled,
outsetScrollBarX,
outsetScrollBarY,
clientScrollBars,
disableScrollX,
disableScrollY,
hideScrollBarX,
hideScrollBarY,
children,
trackChildrenX,
trackChildrenY,
handleChildrenX,
handleChildrenY
} = this.props;
let classNames = ['scroll-box'];
if (className) {
classNames = classNames.concat(className);
}
if (trackXHeight) {
height = `calc(100% + ${trackXHeight}px)`;
if (disabled) {
classNames.push('scroll-box--disabled');
}
}
viewport.style.width = width;
viewport.style.height = height;
if (outsetScrollBarX) {
classNames.push('scroll-box--outset-x');
}
if (outsetScrollBarY) {
classNames.push('scroll-box--outset-y');
}
if (!disableScrollX && !hideScrollBarX) {
classNames.push('scroll-box--enable-x');
}
if (!disableScrollY && !hideScrollBarY) {
classNames.push('scroll-box--enable-y');
}
if (clientScrollBars) {
classNames.push('scroll-box--client-scroll-bars');
}
let targetX = Math.max(0, Math.min(Math.round(this.targetX), SCROLL_MAX_X)) * this.exposesX,
targetY = Math.max(0, Math.min(Math.round(this.targetY), SCROLL_MAX_Y)) * this.exposesY,
x = targetX,
y = targetY;
return (
<div style={style}
className={classNames.join(' ')}
onWheel={handleWheel}
onKeyDown={handleKeyDown}
onTouchStart={handleTouchStart}
tabIndex="-1">
{children}
<div className="scroll-box__track scroll-box__track--x"
onMouseDown={handleFastTrackX}
ref="trackX">
<div className="scroll-box__handle scroll-box__handle--x"
onMouseDown={handleDragStartX}
ref="handleX">
{handleChildrenX}
</div>
{trackChildrenX}
</div>
<div className="scroll-box__track scroll-box__track--y"
onMouseDown={handleFastTrackY}
ref="trackY">
<div className="scroll-box__handle scroll-box__handle--y"
onMouseDown={handleDragStartY}
ref="handleY">
{handleChildrenY}
</div>
{trackChildrenY}
</div>
</div>
);
};
if (scrollY == scrollTop && scrollX == scrollLeft) {
let elapsed = Date.now() - _easingBeginTimestamp;
if (elapsed < _easingDuration && typeof _easing == 'function') {
let ratio = _easing(elapsed / _easingDuration, elapsed, 0, 1, _easingDuration);
this.componentDidMount = () => {
_root = findDOMNode(this);
// Compute eased scroll positions.
x = Math.round(previousX + ratio * (targetX - previousX));
y = Math.round(previousY + ratio * (targetY - previousY));
const {handleX, handleY, trackX, trackY} = this.refs;
_handleX = findDOMNode(handleX);
_handleY = findDOMNode(handleY);
_trackX = findDOMNode(trackX);
_trackY = findDOMNode(trackY);
_viewport = _root.firstElementChild;
const requestPropagateChanges = () => {
if (window.cancelAnimationFrame) {
_requestId = requestAnimationFrame(requestPropagateChanges);
} else {
_requestId = setTimeout(requestPropagateChanges, 1000 / 30);
}
propagateChanges();
};
requestPropagateChanges();
addEventListener('mousemove', handleBarHover);
};
this.componentWillUnmount = () => {
_root = null;
if (window.cancelAnimationFrame) {
cancelAnimationFrame(_requestId);
} else {
// Scroll animation completed.
this._easingDuration = 0;
clearTimeout(_requestId);
}
// Prevent native scrolling glitches, especially if native scroll is inertial or smooth.
viewport.scrollLeft = x;
viewport.scrollTop = y;
} else {
// Viewport scroll position is not synced with component state.
// This is usually caused by system scrolling, resize of element etc.
// So stop running animation and update component state with current
// viewport scroll offsets.
this._easingDuration = 0;
x = targetX = scrollLeft;
y = targetY = scrollTop;
}
this.targetX = targetX;
this.targetY = targetY;
removeEventListener('mousemove', handleBarHover);
};
if (scrollX == x && scrollY == y && this.scrollMaxX == SCROLL_MAX_X && this.scrollMaxY == SCROLL_MAX_Y) {
if (!this._easingDuration) {
// Animation has completed and geometry did not change.
this._easing = null;
this._silent = false;
this.componentDidUpdate = () => {
_viewport = _root.firstElementChild;
propagateChanges();
};
this.scrollTo = ({
x, y,
easing,
easingX = easing || this.props.easingX,
easingY = easing || this.props.easingY,
duration = 0,
durationX = duration,
durationY = duration,
dispatchPrevented = false
} = {}) => {
if (isCoordinate(x)) {
_previousX = _scrollX;
_targetX = x | 0;
_easingX = easingX;
_durationX = durationX;
_timestampX = Date.now();
_dispatchPrevented = dispatchPrevented;
_tickX++;
}
// TODO Viewport did not change its scroll parameters, so invocation of `onViewportScroll` and further altering geometry of handles and tracks may not be required.
}
this.scrollX = x;
this.scrollY = y;
this.scrollMaxX = SCROLL_MAX_X;
this.scrollMaxY = SCROLL_MAX_Y;
this.trackMaxX = 0;
this.trackMaxY = 0;
// Update custom handle positions and sizes.
// Scrollbar size represents ratio of content and viewport sizes.
if (!nativeScroll) {
this.trackMaxX = this.trackX.clientWidth - handleX.offsetWidth;
this.trackMaxY = this.trackY.clientHeight - handleY.offsetHeight;
if (isCoordinate(y)) {
_previousY = _scrollY;
_targetY = y | 0;
_easingY = easingY;
_durationY = durationY;
_timestampY = Date.now();
_dispatchPrevented = dispatchPrevented;
_tickY++;
}
handleX.style.width = clientWidth / scrollWidth * 100 + '%';
handleX.style.left = this.trackMaxX * x / SCROLL_MAX_X + 'px';
propagateChanges();
};
handleY.style.height = clientHeight / scrollHeight * 100 + '%';
handleY.style.top = this.trackMaxY * y / SCROLL_MAX_Y + 'px';
}
if (!_silent && !(scrollX == x && scrollY == y)) {
onViewportScroll(this);
}
}
this.scrollToX = (x, options = {}) => this.scrollTo({...options, x});
onTouchStart = e => {
if (this.props.nativeScroll || this.props.disabled || e.touches.length > 1 || e.isDefaultPrevented()) {
return;
}
if (!this.exposesX && !this.exposesY) {
return; // No scrolling is available.
}
e.stopPropagation();
let touch = e.touches[0],
x = this.viewport.scrollLeft,
y = this.viewport.scrollTop;
this._touchOffsetX = x + touch.screenX;
this._touchOffsetY = y + touch.screenY;
this._touchStart = {x, y};
};
this.scrollToY = (y, options = {}) => this.scrollTo({...options, y});
onTouchMove = e => {
const {propagateTouchScroll} = this.props,
{targetX, targetY, scrollMaxX, scrollMaxY, exposesX, exposesY} = this;
this.scrollBy = ({dx, dy, ...options} = {}) => {
this.scrollTo({
...options,
x: _targetX + dx,
y: _targetY + dy
});
};
this.scrollByX = (dx, options = {}) => this.scrollBy({...options, dx});
this.scrollByY = (dy, options = {}) => this.scrollBy({...options, dy});
if (!this._touchStart) {
return;
}
let touch = e.touches[0],
x = this._touchOffsetX - touch.screenX,
y = this._touchOffsetY - touch.screenY;
this.scrollToPage = ({
x, y,
...options
} = {}) => {
x *= this.getPageWidth();
y *= this.getPageHeight();
this.scrollTo({...options, x, y});
};
let prevTouch = this._touchEnd || this._touchStart,
deltaX = prevTouch.x - x,
deltaY = prevTouch.y - y;
this.scrollToPageX = (x, options = {}) => this.scrollToPage({...options, x});
let dx = deltaX * exposesX,
dy = deltaY * exposesY;
if (
(deltaX && !exposesX) || (dx < 0 && !targetX) || (dx > 0 && targetX == scrollMaxX) ||
(deltaY && !exposesY) || (dy < 0 && !targetY) || (dy > 0 && targetY == scrollMaxY)
) {
// Content is scrolled to its possible limit.
if (!propagateTouchScroll) {
e.preventDefault();
this.scrollToPageY = (y, options = {}) => this.scrollToPage({...options, y});
this.scrollByPage = ({
dx, dy,
...options
} = {}) => {
dx *= this.getPageWidth();
dy *= this.getPageHeight();
this.scrollBy({...options, dx, dy});
};
this.scrollByPageX = (dx, options = {}) => this.scrollByPage({...options, dx});
this.scrollByPageY = (dy, options = {}) => this.scrollByPage({...options, dy});
this.getPageWidth = () => _viewport.clientWidth;
this.getPageHeight = () => _viewport.clientHeight;
Object.defineProperties(this, {
targetX: {
get: () => _targetX,
set: x => this.scrollToX(x)
},
targetY: {
get: () => _targetY,
set: y => this.scrollToY(y)
},
scrollX: {
get: () => _scrollX,
set: x => this.scrollToX(x)
},
scrollY: {
get: () => _scrollY,
set: y => this.scrollToY(y)
},
scrollMaxX: {
get: () => _scrollMaxX
},
scrollMaxY: {
get: () => _scrollMaxY
}
return;
}
});
if (this._touchEnd) {
let coords = this._touchStart;
this._touchStart = this._touchEnd;
this._touchEnd = coords;
coords.x = x;
coords.y = y;
} else {
this._touchEnd = {x, y};
}
this.scrollTo(x, y, 0);
};
const propagateChanges = () => {
const {
disableScrollX,
disableScrollY,
onTouchEnd = e => {
if (!this._touchEnd) {
return;
}
const {_touchStart, _touchEnd} = this;
let dt = Date.now() - this._easingBeginTimestamp,
dx = _touchStart.x - _touchEnd.x,
dy = _touchStart.y - _touchEnd.y,
distance = Math.sqrt(dx * dx + dy * dy),
velocity = distance / dt * 100;
scrollMinX,
scrollMinY,
this._touchStart = null;
this._touchEnd = null;
this.scrollTo(_touchEnd.x - velocity * dx / distance, _touchEnd.y - velocity * dy / distance, velocity);
};
clientScrollBars,
onWheel = e => {
const {wheelStepX, wheelStepY, disabled, nativeScroll, captureWheel, propagateWheelScroll, swapWheelAxes, wheelScrollDuration} = this.props,
{targetX, targetY, scrollMaxX, scrollMaxY, exposesX, exposesY} = this,
el = e.target;
if (nativeScroll && !captureWheel) {
e.preventDefault();
}
if (
disabled || e.isDefaultPrevented() || // Event prevented.
!captureWheel || // Wheel events prevented.
(el != this.viewport && el.tagName.toLowerCase() == 'textarea') // Nested textarea is focused and its is not a viewport.
) {
return;
}
let dx = e.deltaX * exposesX,
dy = e.deltaY * exposesY;
if (
(e.deltaX && !exposesX) || (dx < 0 && !targetX) || (dx > 0 && targetX == scrollMaxX) ||
(e.deltaY && !exposesY) || (dy < 0 && !targetY) || (dy > 0 && targetY == scrollMaxY)
) {
// Content is scrolled to its possible limit.
if (!propagateWheelScroll) {
e.preventDefault();
outsetScrollBarX,
outsetScrollBarY,
onScroll,
onScrollX,
onScrollY,
onScrollStart,
onScrollStartX,
onScrollStartY,
onScrollEnd,
onScrollEndX,
onScrollEndY
} = this.props;
const {
clientWidth,
clientHeight,
offsetWidth,
offsetHeight,
scrollWidth,
scrollHeight,
scrollTop,
scrollLeft
} = _viewport;
_scrollMaxX = scrollWidth - clientWidth;
_scrollMaxY = scrollHeight - clientHeight;
_requiresScrollBarX = !disableScrollX && _scrollMaxX >= scrollMinX;
_requiresScrollBarY = !disableScrollY && _scrollMaxY >= scrollMinY;
_root.classList.toggle('scroll-box--requires-x', _requiresScrollBarX);
_root.classList.toggle('scroll-box--requires-y', _requiresScrollBarY);
if (clientScrollBars && outsetScrollBarX) {
_viewport.style.height = `calc(100% + ${offsetHeight - clientHeight}px)`;
} else {
_viewport.style.height = '100%';
}
return;
}
// By default, Google Chrome changes scrolling orientation if shift key is pressed,
// so propagate this behavior to other browsers as well.
if (e.shiftKey && !dx) {
dx = dy;
dy = 0;
}
if (swapWheelAxes) {
[dx, dy] = [dy, dx];
}
e.preventDefault();
if (typeof InstallTrigger != 'undefined') {
const FIREFOX_SPEED_FACTOR = 30;
dx *= FIREFOX_SPEED_FACTOR;
dy *= FIREFOX_SPEED_FACTOR;
}
dx *= wheelStepX / 100;
dy *= wheelStepY / 100;
if (clientScrollBars && outsetScrollBarY) {
_viewport.style.width = `calc(100% + ${offsetWidth - clientWidth}px)`;
} else {
_viewport.style.width = '100%';
}
// Prevent jumping to target position when slow animated scrolling is in progress,
// but preserve scroll speed when mouse wheel arrive frequently.
if (Date.now() - this._easingBeginTimestamp > wheelScrollDuration) {
this.scrollTo(this.scrollX + dx, this.scrollY + dy, wheelScrollDuration);
} else {
this.scrollTo(this.targetX + dx, this.targetY + dy, wheelScrollDuration);
}
};
_targetX = Math.max(0, Math.min(_targetX, _scrollMaxX));
_targetY = Math.max(0, Math.min(_targetY, _scrollMaxY));
onKeyDown = e => {
const {keyboardStepX, keyboardStepY, disabled, captureKeyboard, keyboardScrollDuration} = this.props;
let el = e.target,
tagName = el.tagName.toLowerCase();
if (
disabled || e.isDefaultPrevented() || // Event prevented.
!captureKeyboard || !/3[3456789]|40/.test(String(e.keyCode)) || // Keyboard events prevented.
tagName == 'textarea' || (tagName == 'input' && el.type == 'text') // Nested textarea or input is focused.
) {
return;
}
// Prevent page scrolling.
e.preventDefault();
switch (e.keyCode) {
case 36: // Home
this.scrollTo(0, 0, keyboardScrollDuration);
break;
case 35: // End
this.scrollTo(this.scrollMaxX, this.scrollMaxY, keyboardScrollDuration);
break;
case 33: // PgUp
case 34: // PgDn
let dy = this.viewport.clientHeight,
dx = this.viewport.clientWidth;
if (e.keyCode == 33) {
// For PageUp invert direction.
dy *= -1;
dx *= -1;
let nextScrollX = _scrollX,
nextScrollY = _scrollY;
if (_scrollX == scrollLeft && _scrollY == scrollTop) {
// Controlled scroll position coincides with viewport position.
if (nextScrollX != _targetX) {
const elapsedX = Date.now() - _timestampX;
if (elapsedX < _durationX) {
nextScrollX = _previousX + _easingX(elapsedX / _durationX, elapsedX, 0, 1, _durationX) * (_targetX - _previousX) | 0;
} else {
nextScrollX = _targetX;
}
}
if (e.shiftKey) {
this.scrollBy(dx, 0, keyboardScrollDuration);
} else {
this.scrollBy(0, dy, keyboardScrollDuration);
if (nextScrollY != _targetY) {
const elapsedY = Date.now() - _timestampY;
if (elapsedY < _durationY) {
nextScrollY = _previousY + _easingY(elapsedY / _durationY, elapsedY, 0, 1, _durationY) * (_targetY - _previousY) | 0;
} else {
nextScrollY = _targetY;
}
}
break;
case 38: // Up
this.scrollBy(0, -keyboardStepY, keyboardScrollDuration);
break;
case 40: // Down
this.scrollBy(0, keyboardStepY, keyboardScrollDuration);
break;
case 37: // Left
this.scrollBy(-keyboardStepX, 0, keyboardScrollDuration);
break;
case 39: // Right
this.scrollBy(keyboardStepX, 0, keyboardScrollDuration);
break;
}
};
}
onDragStart(e, axis) {
const {disabled, captureHandleDrag} = this.props;
if (disabled || !captureHandleDrag || e.button != 0) {
return;
}
e.preventDefault();
e.stopPropagation();
const clientScrollingX = _scrollX != scrollLeft,
clientScrollingY = _scrollY != scrollTop;
let track;
if (axis == ScrollAxes.X) {
track = this.trackX;
} else {
track = this.trackY;
}
const OFFSET_X = e.clientX - this.handleX.offsetLeft,
OFFSET_Y = e.clientY - this.handleY.offsetTop;
if (clientScrollingX) {
_targetX = nextScrollX = scrollLeft;
}
if (clientScrollingY) {
_targetY = nextScrollY = scrollTop;
}
let onDrag = e => {
if (!this._forceSyncId || e.button != 0) {
onDragEnd(); // Component was unmounted or button was released.
const nextScrollingX = nextScrollX != _targetX,
nextScrollingY = nextScrollY != _targetY;
const dx = _scrollX - nextScrollX,
dy = _scrollY - nextScrollY;
const tickX = _tickX,
tickY = _tickY;
if (!_dispatchPrevented) {
// Events can be triggered.
// Checking ticks after each event callback invocation to ensure that any scroll
// methods were not called inside those callbacks.
if (
(nextScrollingX | nextScrollingY | clientScrollingX | clientScrollingY) &&
!_scrollingX && !_scrollingY
) {
onScrollStart(this, _causeX, _causeY);
}
if (tickX == _tickX && nextScrollingX && !_scrollingX) {
onScrollStartX(this, _causeX);
}
if (tickY == _tickY && nextScrollingY && !_scrollingY) {
onScrollStartY(this, _causeY);
}
if (
tickX == _tickX && tickY == _tickY &&
(dx | dy)
) {
onScroll(this, dx, dy, _causeX, _causeY);
}
if (tickX == _tickX && dx) {
onScrollX(this, dx, _causeX);
}
if (tickY == _tickY && dy) {
onScrollY(this, dy, _causeY);
}
if (
tickX == _tickX && tickY == _tickY &&
!nextScrollingX && !nextScrollingY &&
(_scrollingX | _scrollingY | clientScrollingX | clientScrollingY)
) {
onScrollEnd(this, _causeX, _causeY);
}
if (tickX == _tickX && !nextScrollingX && _scrollingX) {
onScrollEndX(this, _causeX);
}
if (tickY == _tickY && !nextScrollingY && _scrollingY) {
onScrollEndY(this, _causeY);
}
if (tickX == _tickX && _causeX != ScrollCause.TOUCH | _causeX != ScrollCause.HANDLE_DRAG) {
_causeX = null;
}
if (tickY == _tickY && _causeY != ScrollCause.TOUCH | _causeY != ScrollCause.HANDLE_DRAG) {
_causeY = null;
}
}
if (axis == ScrollAxes.X) {
var x = this.scrollMaxX * (e.clientX - OFFSET_X) / this.trackMaxX;
} else {
var y = this.scrollMaxY * (e.clientY - OFFSET_Y) / this.trackMaxY;
if (dx && tickX == _tickX) {
_viewport.scrollLeft = _scrollX = nextScrollX;
}
this.scrollTo(x, y, 0);
if (dy && tickY == _tickY) {
_viewport.scrollTop = _scrollY = nextScrollY;
}
if (!clientScrollBars) {
_trackMaxX = _trackX.clientWidth - _handleX.offsetWidth;
_handleX.style.width = clientWidth / scrollWidth * 100 + '%';
_handleX.style.left = _trackMaxX * nextScrollX / _scrollMaxX + 'px';
_trackMaxY = _trackY.clientHeight - _handleY.offsetHeight;
_handleY.style.height = clientHeight / scrollHeight * 100 + '%';
_handleY.style.top = _trackMaxY * nextScrollY / _scrollMaxY + 'px';
}
};
let onDragEnd = e => {
removeEventListener('mousemove', onDrag);
removeEventListener('mouseup', onDragEnd);
if (this._forceSyncId) {
// Ensure component is mounted.
track.classList.remove('scroll-box__track--dragged');
const handleKeyDown = event => {
const {target: {tagName}, keyCode, shiftKey} = event;
const {
disabled,
captureKeyboard,
keyboardStepX,
keyboardStepY,
keyboardScrollDuration
} = this.props;
if (disabled | !captureKeyboard | tagName == 'TEXTAREA' | tagName == 'INPUT') {
// Do not handle any keyboard events when text-related controls are focused.
return;
}
const options = {duration: keyboardScrollDuration};
switch (keyCode) {
case 36: // Home
event.preventDefault();
_causeY = ScrollCause.KEYBOARD;
this.scrollToY(0, options);
break;
case 35: // End
event.preventDefault();
_causeY = ScrollCause.KEYBOARD;
this.scrollToY(_scrollMaxY, options);
break;
case 33: // Page Up
case 34: // Page Down
event.preventDefault();
let dy = this.getPageHeight(),
dx = this.getPageWidth();
if (keyCode == 33) { // Page Up
dy *= -1;
dx *= -1;
}
if (shiftKey) {
_causeX = ScrollCause.KEYBOARD;
this.scrollByX(dx, options);
} else {
_causeY = ScrollCause.KEYBOARD;
this.scrollByY(dy, options);
}
break;
case 38: // Up
event.preventDefault();
_causeY = ScrollCause.KEYBOARD;
this.scrollByY(-keyboardStepY, options);
break;
case 40: // Down
event.preventDefault();
_causeY = ScrollCause.KEYBOARD;
this.scrollByY(keyboardStepY, options);
break;
case 37: // Left
event.preventDefault();
_causeX = ScrollCause.KEYBOARD;
this.scrollByX(-keyboardStepX, options);
break;
case 39: // Right
event.preventDefault();
_causeX = ScrollCause.KEYBOARD;
this.scrollByX(keyboardStepX, options);
break;
}
};
addEventListener('mousemove', onDrag);
addEventListener('mouseup', onDragEnd);
track.classList.add('scroll-box__track--dragged');
};
const handleFastTrack = (event, isHorizontal) => {
const {
disabled,
onDragStartX = e => this.onDragStart(e, ScrollAxes.X);
captureFastTrackX,
captureFastTrackY,
onDragStartY = e => this.onDragStart(e, ScrollAxes.Y);
fastTrackModeX,
fastTrackModeY,
onFastTrack(e, axis) {
const {disabled, fastTrack, fastTrackDuration} = this.props;
if (disabled || e.button != 0) {
return; // Component is disabled or secondary mouse button is being pressed.
}
let x, y;
const {clientWidth, clientHeight, scrollWidth, scrollHeight} = this.viewport,
POINTER_X = e.clientX - this.trackX.getBoundingClientRect().left,
POINTER_Y = e.clientY - this.trackY.getBoundingClientRect().top;
fastTrackScrollDurationX,
fastTrackScrollDurationY
} = this.props;
switch (fastTrack) {
if (disabled | !captureFastTrackX && !captureFastTrackY | event.button) {
// Component is disabled or secondary mouse button is being pressed.
return;
}
case FastTrack.PAGING:
if (axis == ScrollAxes.X) {
x = this.targetX + (1 - 2 * (POINTER_X < this.handleX.offsetLeft)) * clientWidth;
const {
clientWidth,
clientHeight,
scrollWidth,
scrollHeight
} = _viewport;
if (isHorizontal) {
if (!captureFastTrackX) {
return;
}
_causeX = ScrollCause.FAST_TRACK;
const pointerX = event.clientX - _trackX.getBoundingClientRect().left,
optionsX = {duration: fastTrackScrollDurationX};
switch (fastTrackModeX) {
case FastTrackMode.PAGING:
this.scrollToX(_targetX + (1 - 2 * (pointerX < _handleX.offsetLeft)) * this.getPageWidth(), optionsX);
break;
case FastTrackMode.GOTO:
this.scrollToX(pointerX / _trackX.clientWidth * scrollWidth - clientWidth / 2, optionsX);
break;
}
} else {
if (!captureFastTrackY) {
return;
}
_causeY = ScrollCause.FAST_TRACK;
const pointerY = event.clientY - _trackY.getBoundingClientRect().top,
optionsY = {duration: fastTrackScrollDurationY};
switch (fastTrackModeY) {
case FastTrackMode.PAGING:
this.scrollToY(_targetY + (1 - 2 * (pointerY < _handleY.offsetTop)) * this.getPageHeight(), optionsY);
break;
case FastTrackMode.GOTO:
this.scrollToY(pointerY / _trackY.clientHeight * scrollHeight - clientHeight / 2, optionsY);
break;
}
}
};
const handleFastTrackX = event => handleFastTrack(event, true);
const handleFastTrackY = event => handleFastTrack(event, false);
const handleDragStart = (event, isHorizontal) => {
const {
disabled,
captureHandleDragX,
captureHandleDragY,
permitHandleDragInterruption
} = this.props;
// Handle can be dragged with left mouse button only.
if (disabled | !captureHandleDragX && !captureHandleDragY | event.button) {
return;
}
event.preventDefault();
event.stopPropagation();
let track;
if (isHorizontal) {
_causeX = ScrollCause.HANDLE_DRAG;
track = _trackX;
} else {
_causeY = ScrollCause.HANDLE_DRAG;
track = _trackY;
}
const offsetX = event.clientX - _handleX.offsetLeft,
offsetY = event.clientY - _handleY.offsetTop;
const handleDrag = event => {
if (!_root | event.button | permitHandleDragInterruption && (isHorizontal ? _causeX : _causeY) != ScrollCause.HANDLE_DRAG) {
stopDrag();
return;
}
if (isHorizontal) {
_causeX = ScrollCause.HANDLE_DRAG;
this.scrollToX(_scrollMaxX * (event.clientX - offsetX) / _trackMaxX);
} else {
y = this.targetY + (1 - 2 * (POINTER_Y < this.handleY.offsetTop)) * clientHeight;
_causeY = ScrollCause.HANDLE_DRAG;
this.scrollToY(_scrollMaxY * (event.clientY - offsetY) / _trackMaxY);
}
break;
};
case FastTrack.GOTO:
if (axis == ScrollAxes.X) {
x = POINTER_X / this.trackX.clientWidth * scrollWidth - clientWidth / 2;
const handleDragEnd = () => {
if (isHorizontal) {
_causeX = null;
} else {
y = POINTER_Y / this.trackY.clientHeight * scrollHeight - clientHeight / 2;
_causeY = null;
}
break;
stopDrag();
};
default: return;
}
this.scrollTo(x, y, fastTrackDuration);
};
const stopDrag = () => {
removeEventListener('mousemove', handleDrag);
removeEventListener('mouseup', handleDragEnd);
onFastTrackX = e => this.onFastTrack(e, ScrollAxes.X);
track.classList.remove('scroll-box__track--dragged');
};
onFastTrackY = e => this.onFastTrack(e, ScrollAxes.Y);
addEventListener('mousemove', handleDrag);
addEventListener('mouseup', handleDragEnd);
_updateTrackHoverStatus(e, track) {
const {clientX, clientY} = e,
{hoverProximity} = this.props,
{width, left, top, height} = track.getBoundingClientRect();
track.classList.add('scroll-box__track--dragged');
};
track.classList.toggle('scroll-box__track--hover',
clientY - height - top < hoverProximity && top - clientY < hoverProximity &&
clientX - width - left < hoverProximity && left - clientX < hoverProximity);
}
const handleDragStartX = event => handleDragStart(event, true);
onCursorApproachingTrack = e => {
let {nativeScroll, disabled, captureHandleDrag, fastTrack} = this.props;
// Do not track cursor proximity for native scroll bar, when handle is being dragged,
// when selection is in progress or when another handle is being dragged (even on another
// scroll box instance).
if (nativeScroll || disabled || (!captureHandleDrag && fastTrack == FastTrack.OFF) || e.buttons > 0) {
return;
}
// Update track hover status only if it is actually in use.
if (this.exposesX) {
this._updateTrackHoverStatus(e, this.trackX);
}
if (this.exposesY) {
this._updateTrackHoverStatus(e, this.trackY);
}
};
const handleDragStartY = event => handleDragStart(event, false);
_updateReferences() {
let {refs} = this;
for (let ref in refs) {
if (refs.hasOwnProperty(ref)) {
this[ref] = findDOMNode(refs[ref]);
const handleWheel = event => {
let {target, deltaMode, deltaX, deltaY, shiftKey} = event;
const {
wheelStepX,
wheelStepY,
disabled,
clientScrollBars,
captureWheel,
lineHeight,
propagateWheelScrollX,
propagateWheelScrollY,
swapWheelAxes,
wheelScrollDurationX,
wheelScrollDurationY
} = this.props;
if (clientScrollBars && !captureWheel) {
event.preventDefault();
}
}
this.el = findDOMNode(this);
this.viewport = this.el.firstChild;
if (disabled | event.isDefaultPrevented()) {
return;
}
if (target != _viewport && target.tagName == 'TEXTAREA') {
// Nested textarea is focused and its is not a viewport.
return;
}
const {nativeScroll} = this.props;
if (nativeScroll == null) {
if (typeof window != 'undefined' && 'orientation' in window) {
this.el.classList.add('scroll-box--native');
// By default, Google Chrome changes scrolling orientation if shift key is pressed,
// so propagate this behavior to other browsers as well.
if (shiftKey && deltaX == 0) {
deltaX = deltaY;
deltaY = 0;
}
} else {
this.el.classList.toggle('scroll-box--native', nativeScroll);
}
}
componentDidMount() {
let requestForceSync = () => {
if (window.cancelAnimationFrame) {
this._forceSyncId = requestAnimationFrame(requestForceSync);
} else {
this._forceSyncId = setTimeout(requestForceSync, 1000 / 30);
if (swapWheelAxes) {
const buffer = deltaX;
deltaX = deltaY;
deltaY = buffer;
}
this._forceSync();
let dx = deltaX * _requiresScrollBarX,
dy = deltaY * _requiresScrollBarY;
if (deltaX && !_requiresScrollBarX | dx < 0 && !_targetX | dx > 0 && _targetX == _scrollMaxX) {
// Content is scrolled to its possible limit.
if (!propagateWheelScrollX) {
event.preventDefault();
}
return;
}
if (deltaY && !_requiresScrollBarY | dy < 0 && !_targetY | dy > 0 && _targetY == _scrollMaxY) {
if (!propagateWheelScrollY) {
event.preventDefault();
}
return;
}
event.preventDefault();
// Converts received delta values into pixels.
switch (deltaMode) {
case 0x01: // Delta values are specified in lines.
dx *= lineHeight;
dy *= lineHeight;
break;
case 0x02:
dx *= this.getPageWidth();
dy *= this.getPageHeight();
break;
default:
// Delta values are specified in pixels.
break;
}
dx *= wheelStepX / 100;
dy *= wheelStepY / 100;
let nextTargetX = _targetX + dx,
nextTargetY = _targetY + dy;
// Prevent jumping to target position when animated scrolling is in progress,
// but preserve scroll speed when mouse wheel events arrive frequently.
if (Date.now() - _timestampX > wheelScrollDurationX) {
nextTargetX = _scrollX + dx;
}
if (Date.now() - _timestampX > wheelScrollDurationY) {
nextTargetY = _scrollY + dy;
}
if (dx) {
_causeX = ScrollCause.MOUSE_WHEEL;
this.scrollToX(nextTargetX, {duration: wheelScrollDurationX});
}
if (dy) {
_causeY = ScrollCause.MOUSE_WHEEL;
this.scrollToY(nextTargetY, {duration: wheelScrollDurationY});
}
};
this._updateReferences();
requestForceSync();
addEventListener('mousemove', this.onCursorApproachingTrack);
}
componentDidUpdate() {
this._updateReferences();
this._forceSync();
}
const updateTrackHoverStatus = (event, track, proximity, status) => {
if (status == null) {
const {clientX, clientY} = event,
{width, left, top, height} = track.getBoundingClientRect();
status =
proximity > clientY - height - top &&
proximity > clientX - width - left &&
proximity > left - clientX &&
proximity > top - clientY;
}
track.classList.toggle('scroll-box__track--hover', status);
};
componentWillUnmount() {
if (window.cancelAnimationFrame) {
cancelAnimationFrame(this._forceSyncId);
} else {
clearTimeout(this._forceSyncId);
}
this._forceSyncId = 0;
removeEventListener('mousemove', this.onCursorApproachingTrack);
}
const handleBarHover = event => {
const {
disabled,
clientScrollBars,
captureHandleDragX,
captureHandleDragY,
captureFastTrackX,
captureFastTrackY,
trackHoverProximityX,
trackHoverProximityY
} = this.props;
render() {
const {axes, trackXChildren, trackYChildren, handleXChildren, handleYChildren, disabled, outset, className, children, style} = this.props;
let classNames = ['scroll-box'];
if (className) {
classNames = classNames.concat(className);
}
if (disabled) {
classNames.push('scroll-box--disabled');
}
if (outset) {
classNames.push('scroll-box--outset');
}
if (axes.indexOf(ScrollAxes.X) > -1) {
classNames.push('scroll-box--has-axis-x');
}
if (axes.indexOf(ScrollAxes.Y) > -1) {
classNames.push('scroll-box--has-axis-y');
}
return (
<div style={style}
className={classNames.join(' ')}
onWheel={this.onWheel}
onKeyDown={this.onKeyDown}
onTouchStart={this.onTouchStart}
onTouchMove={this.onTouchMove}
onTouchEnd={this.onTouchEnd}
onTouchCancel={this.onTouchEnd}
tabIndex="-1">
{React.Children.only(children)}
<div className="scroll-box__track scroll-box__track--x"
onMouseDown={this.onFastTrackX}
ref="trackX">
<div className="scroll-box__handle scroll-box__handle--x"
onMouseDown={this.onDragStartX}
ref="handleX">
{handleXChildren}
</div>
{trackXChildren}
</div>
<div className="scroll-box__track scroll-box__track--y"
onMouseDown={this.onFastTrackY}
ref="trackY">
<div className="scroll-box__handle scroll-box__handle--y"
onMouseDown={this.onDragStartY}
ref="handleY">
{handleYChildren}
</div>
{trackYChildren}
</div>
</div>
);
if ('orientation' in window | clientScrollBars | disabled) {
return;
}
if (event.buttons) {
if (_causeX != ScrollCause.HANDLE_DRAG) {
var statusX = false;
}
if (_causeY != ScrollCause.HANDLE_DRAG) {
var statusY = false;
}
}
if (_requiresScrollBarX && (captureHandleDragX | captureFastTrackX)) {
updateTrackHoverStatus(event, _trackX, trackHoverProximityX, statusX);
}
if (_requiresScrollBarY && (captureHandleDragY | captureFastTrackY)) {
updateTrackHoverStatus(event, _trackY, trackHoverProximityY, statusY);
}
};
const handleTouchStart = event => {
const {target, touches} = event;
const {
disabled,
clientScrollBars,
captureTouch,
propagateTouchScrollX,
propagateTouchScrollY,
} = this.props;
if (clientScrollBars && !captureTouch) {
event.preventDefault();
}
if (clientScrollBars | disabled | touches.length > 1 | event.isDefaultPrevented()) {
return;
}
if (target != _viewport && target.tagName == 'TEXTAREA') {
// Nested textarea is focused and its is not a viewport.
return;
}
const {
clientX: initialClientX,
clientY: initialClientY
} = touches[0];
let scrolled = false;
const handleTouchMove = event => {
const {targetX, targetY, scrollMaxX, scrollMaxY} = this;
const {clientX, clientY} = event.touches[0];
const dx = initialClientX - clientX,
dy = initialClientY - clientY;
if (
(dx < 0 && !targetX) || (dx > 0 && targetX == scrollMaxX) ||
(dy < 0 && !targetY) || (dy > 0 && targetY == scrollMaxY)
) {
if (!scrolled) {
disposeTouch();
}
return;
}
scrolled = true;
event.preventDefault();
this.scrollTo({x: _scrollX + dx, y: _scrollY + dy});
};
const handleTouchEnd = event => {
disposeTouch();
};
const disposeTouch = () => {
removeEventListener('touchmove', handleTouchMove);
removeEventListener('touchend', handleTouchEnd);
removeEventListener('touchcancel', handleTouchEnd);
};
addEventListener('touchmove', handleTouchMove);
addEventListener('touchend', handleTouchEnd);
addEventListener('touchcancel', handleTouchEnd);
};
}
}
export {ScrollBox} from './ScrollBox';
export {GenericScrollBox, FastTrack, ScrollAxes} from './GenericScrollBox';
export {GenericScrollBox, FastTrackMode, ScrollCause} from './GenericScrollBox';

@@ -38,3 +38,3 @@ @scroll-box: scroll-box; // Namespace class

> .@{scroll-box}__viewport {
// Hide native scrollbars.
// Hide client scrollbars.
overflow: hidden !important;

@@ -53,9 +53,9 @@ }

// Used if fallback to native system scrolling should occur.
&--native {
// Used if fallback to client system scrolling should occur.
&--client-scroll-bars {
&.@{scroll-box}--has-axis-y.@{scroll-box}--show-axis-y > .@{scroll-box}__viewport {
&.@{scroll-box}--enable-y.@{scroll-box}--requires-y > .@{scroll-box}__viewport {
overflow-y: auto;
}
&.@{scroll-box}--has-axis-x.@{scroll-box}--show-axis-x > .@{scroll-box}__viewport {
&.@{scroll-box}--enable-x.@{scroll-box}--requires-x > .@{scroll-box}__viewport {
overflow-x: auto;

@@ -68,14 +68,14 @@ }

&:not(.@{scroll-box}--native) {
&.@{scroll-box}--has-axis-y.@{scroll-box}--show-axis-y > .@{scroll-box}__track--y {
&:not(.@{scroll-box}--client-scroll-bars) {
&.@{scroll-box}--enable-y.@{scroll-box}--requires-y > .@{scroll-box}__track--y {
visibility: visible;
}
&.@{scroll-box}--has-axis-x.@{scroll-box}--show-axis-x > .@{scroll-box}__track--x {
&.@{scroll-box}--enable-x.@{scroll-box}--requires-x > .@{scroll-box}__track--x {
visibility: visible;
}
// Both non-native scrollbars are visible and they are inside
// Both non-client scrollbars are visible and they are inside
// scrollable are, we should prevent their intersection in the
// shared corner.
&.@{scroll-box}--has-axis-x.@{scroll-box}--show-axis-x.@{scroll-box}--has-axis-y.@{scroll-box}--show-axis-y:not(.@{scroll-box}--outset) {
&.@{scroll-box}--enable-x.@{scroll-box}--requires-x.@{scroll-box}--enable-y.@{scroll-box}--requires-y:not(.@{scroll-box}--outset) {
> .@{scroll-box}__track {

@@ -82,0 +82,0 @@ &--y {

@@ -1,1 +0,1 @@

.scroll-box{position:relative}.scroll-box:focus{outline:none}.scroll-box--disabled>.scroll-box__viewport{overflow:hidden!important}.scroll-box--disabled>.scroll-box__track{visibility:hidden!important}.scroll-box--wrapped>.scroll-box__viewport{position:absolute;top:0;left:0;width:100%;height:100%;overflow:hidden;padding:inherit;border-radius:inherit}.scroll-box--wrapped>.scroll-box__track{display:block}.scroll-box--native.scroll-box--has-axis-y.scroll-box--show-axis-y>.scroll-box__viewport{overflow-y:auto}.scroll-box--native.scroll-box--has-axis-x.scroll-box--show-axis-x>.scroll-box__viewport{overflow-x:auto}.scroll-box--native>.scroll-box__viewport{-webkit-overflow-scrolling:touch}.scroll-box:not(.scroll-box--native).scroll-box--has-axis-x.scroll-box--show-axis-x>.scroll-box__track--x,.scroll-box:not(.scroll-box--native).scroll-box--has-axis-y.scroll-box--show-axis-y>.scroll-box__track--y{visibility:visible}.scroll-box:not(.scroll-box--native).scroll-box--has-axis-x.scroll-box--show-axis-x.scroll-box--has-axis-y.scroll-box--show-axis-y:not(.scroll-box--outset)>.scroll-box__track--y{margin-bottom:14px}.scroll-box:not(.scroll-box--native).scroll-box--has-axis-x.scroll-box--show-axis-x.scroll-box--has-axis-y.scroll-box--show-axis-y:not(.scroll-box--outset)>.scroll-box__track--x{margin-right:14px}.scroll-box__handle,.scroll-box__track{position:absolute;border-radius:10.2px;transition:.2s ease-in-out}.scroll-box__handle{transition-property:background;cursor:default}.scroll-box__handle--y{width:100%;min-height:30px;max-height:100%;top:0}.scroll-box__handle--x{height:100%;min-width:30px;max-width:100%;left:0}.scroll-box__track{display:none;visibility:hidden;transition-property:background,width,height;cursor:default}.scroll-box__track--y{top:0;bottom:0;right:0;width:6px;margin:4px 4px 4px 0}.scroll-box__track--y.scroll-box__track--dragged,.scroll-box__track--y.scroll-box__track--hover{width:10.2px}.scroll-box--outset>.scroll-box__track--y{left:100%;margin-left:4px}.scroll-box__track--x{left:0;right:0;bottom:0;height:6px;margin:0 4px 4px}.scroll-box__track--x.scroll-box__track--dragged,.scroll-box__track--x.scroll-box__track--hover{height:10.2px}.scroll-box--outset>.scroll-box__track--x{top:100%;margin-top:4px}.scroll-box>.scroll-box__track{background:transparent}.scroll-box>.scroll-box__track>.scroll-box__handle{background:rgba(0,0,0,.4)}.scroll-box>.scroll-box__track--dragged,.scroll-box>.scroll-box__track--hover{background:rgba(0,0,0,.2)}.scroll-box>.scroll-box__track--dragged>.scroll-box__handle,.scroll-box>.scroll-box__track--hover>.scroll-box__handle{background:rgba(0,0,0,.6)}
.scroll-box{position:relative}.scroll-box:focus{outline:none}.scroll-box--disabled>.scroll-box__viewport{overflow:hidden!important}.scroll-box--disabled>.scroll-box__track{visibility:hidden!important}.scroll-box--wrapped>.scroll-box__viewport{position:absolute;top:0;left:0;width:100%;height:100%;overflow:hidden;padding:inherit;border-radius:inherit}.scroll-box--wrapped>.scroll-box__track{display:block}.scroll-box--client-scroll-bars.scroll-box--enable-y.scroll-box--requires-y>.scroll-box__viewport{overflow-y:auto}.scroll-box--client-scroll-bars.scroll-box--enable-x.scroll-box--requires-x>.scroll-box__viewport{overflow-x:auto}.scroll-box--client-scroll-bars>.scroll-box__viewport{-webkit-overflow-scrolling:touch}.scroll-box:not(.scroll-box--client-scroll-bars).scroll-box--enable-x.scroll-box--requires-x>.scroll-box__track--x,.scroll-box:not(.scroll-box--client-scroll-bars).scroll-box--enable-y.scroll-box--requires-y>.scroll-box__track--y{visibility:visible}.scroll-box:not(.scroll-box--client-scroll-bars).scroll-box--enable-x.scroll-box--requires-x.scroll-box--enable-y.scroll-box--requires-y:not(.scroll-box--outset)>.scroll-box__track--y{margin-bottom:14px}.scroll-box:not(.scroll-box--client-scroll-bars).scroll-box--enable-x.scroll-box--requires-x.scroll-box--enable-y.scroll-box--requires-y:not(.scroll-box--outset)>.scroll-box__track--x{margin-right:14px}.scroll-box__handle,.scroll-box__track{position:absolute;border-radius:10.2px;transition:.2s ease-in-out}.scroll-box__handle{transition-property:background;cursor:default}.scroll-box__handle--y{width:100%;min-height:30px;max-height:100%;top:0}.scroll-box__handle--x{height:100%;min-width:30px;max-width:100%;left:0}.scroll-box__track{display:none;visibility:hidden;transition-property:background,width,height;cursor:default}.scroll-box__track--y{top:0;bottom:0;right:0;width:6px;margin:4px 4px 4px 0}.scroll-box__track--y.scroll-box__track--dragged,.scroll-box__track--y.scroll-box__track--hover{width:10.2px}.scroll-box--outset>.scroll-box__track--y{left:100%;margin-left:4px}.scroll-box__track--x{left:0;right:0;bottom:0;height:6px;margin:0 4px 4px}.scroll-box__track--x.scroll-box__track--dragged,.scroll-box__track--x.scroll-box__track--hover{height:10.2px}.scroll-box--outset>.scroll-box__track--x{top:100%;margin-top:4px}.scroll-box>.scroll-box__track{background:transparent}.scroll-box>.scroll-box__track>.scroll-box__handle{background:rgba(0,0,0,.4)}.scroll-box>.scroll-box__track--dragged,.scroll-box>.scroll-box__track--hover{background:rgba(0,0,0,.2)}.scroll-box>.scroll-box__track--dragged>.scroll-box__handle,.scroll-box>.scroll-box__track--hover>.scroll-box__handle{background:rgba(0,0,0,.6)}

@@ -1,1 +0,6 @@

module.exports=function(e){function t(r){if(o[r])return o[r].exports;var a=o[r]={exports:{},id:r,loaded:!1};return e[r].call(a.exports,a,a.exports,t),a.loaded=!0,a.exports}var o={};return t.m=e,t.c=o,t.p="",t(0)}([function(e,t,o){o(5),e.exports=o(4)},function(e,t,o){"use strict";function r(e){return e&&e.__esModule?e:{"default":e}}function a(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}function n(e,t){if(!e)throw new ReferenceError("this hasn't been initialised - super() hasn't been called");return!t||"object"!=typeof t&&"function"!=typeof t?e:t}function s(e,t){if("function"!=typeof t&&null!==t)throw new TypeError("Super expression must either be null or a function, not "+typeof t);e.prototype=Object.create(t&&t.prototype,{constructor:{value:e,enumerable:!1,writable:!0,configurable:!0}}),t&&(Object.setPrototypeOf?Object.setPrototypeOf(e,t):e.__proto__=t)}Object.defineProperty(t,"__esModule",{value:!0}),t.GenericScrollBox=t.FastTrack=t.ScrollAxes=void 0;var l=function(){function e(e,t){for(var o=0;o<t.length;o++){var r=t[o];r.enumerable=r.enumerable||!1,r.configurable=!0,"value"in r&&(r.writable=!0),Object.defineProperty(e,r.key,r)}}return function(t,o,r){return o&&e(t.prototype,o),r&&e(t,r),t}}(),i=o(2),c=r(i),u=o(6),h=c["default"].PropTypes,f=h.number,p=h.bool,d=h.func,v=h.oneOf,x=h.any,y=t.ScrollAxes={X:"x",Y:"y",XY:"xy"},g=t.FastTrack={PAGING:"paging",GOTO:"goto",OFF:null},b=t.GenericScrollBox=function(e){function t(){var e,o,r,s;a(this,t);for(var l=arguments.length,i=Array(l),c=0;l>c;c++)i[c]=arguments[c];return o=r=n(this,(e=Object.getPrototypeOf(t)).call.apply(e,[this].concat(i))),r.handleX=null,r.handleY=null,r.trackX=null,r.trackY=null,r.viewport=null,r.targetX=0,r.targetY=0,r.previousX=0,r.previousY=0,r.scrollX=0,r.scrollY=0,r.scrollMaxX=0,r.scrollMaxY=0,r.trackMaxX=0,r.trackMaxY=0,r.exposesX=!1,r.exposesY=!1,r._forceSyncId=0,r._easingBeginTimestamp=0,r._easingDuration=0,r._easing=null,r._silent=!1,r._touchOffsetX=0,r._touchOffsetY=0,r._touchStart=null,r._touchEnd=null,r.onTouchStart=function(e){if(!(r.props.nativeScroll||r.props.disabled||e.touches.length>1||e.isDefaultPrevented())&&(r.exposesX||r.exposesY)){e.stopPropagation();var t=e.touches[0],o=r.viewport.scrollLeft,a=r.viewport.scrollTop;r._touchOffsetX=o+t.screenX,r._touchOffsetY=a+t.screenY,r._touchStart={x:o,y:a}}},r.onTouchMove=function(e){var t=r.props.propagateTouchScroll,o=r,a=o.targetX,n=o.targetY,s=o.scrollMaxX,l=o.scrollMaxY,i=o.exposesX,c=o.exposesY;if(r._touchStart){var u=e.touches[0],h=r._touchOffsetX-u.screenX,f=r._touchOffsetY-u.screenY,p=r._touchEnd||r._touchStart,d=p.x-h,v=p.y-f,x=d*i,y=v*c;if(d&&!i||0>x&&!a||x>0&&a==s||v&&!c||0>y&&!n||y>0&&n==l)return void(t||e.preventDefault());if(r._touchEnd){var g=r._touchStart;r._touchStart=r._touchEnd,r._touchEnd=g,g.x=h,g.y=f}else r._touchEnd={x:h,y:f};r.scrollTo(h,f,0)}},r.onTouchEnd=function(e){if(r._touchEnd){var t=r,o=t._touchStart,a=t._touchEnd,n=Date.now()-r._easingBeginTimestamp,s=o.x-a.x,l=o.y-a.y,i=Math.sqrt(s*s+l*l),c=i/n*100;r._touchStart=null,r._touchEnd=null,r.scrollTo(a.x-c*s/i,a.y-c*l/i,c)}},r.onWheel=function(e){var t=r.props,o=t.wheelStepX,a=t.wheelStepY,n=t.disabled,s=t.nativeScroll,l=t.captureWheel,i=t.propagateWheelScroll,c=t.swapWheelAxes,u=t.wheelScrollDuration,h=r,f=h.targetX,p=h.targetY,d=h.scrollMaxX,v=h.scrollMaxY,x=h.exposesX,y=h.exposesY,g=e.target;if(s&&!l&&e.preventDefault(),!(n||e.isDefaultPrevented()||!l||g!=r.viewport&&"textarea"==g.tagName.toLowerCase())){var b=e.deltaX*x,_=e.deltaY*y;if(e.deltaX&&!x||0>b&&!f||b>0&&f==d||e.deltaY&&!y||0>_&&!p||_>0&&p==v)return void(i||e.preventDefault());if(e.shiftKey&&!b&&(b=_,_=0),c){var k=[_,b];b=k[0],_=k[1]}if(e.preventDefault(),"undefined"!=typeof InstallTrigger){var X=30;b*=X,_*=X}b*=o/100,_*=a/100,Date.now()-r._easingBeginTimestamp>u?r.scrollTo(r.scrollX+b,r.scrollY+_,u):r.scrollTo(r.targetX+b,r.targetY+_,u)}},r.onKeyDown=function(e){var t=r.props,o=t.keyboardStepX,a=t.keyboardStepY,n=t.disabled,s=t.captureKeyboard,l=t.keyboardScrollDuration,i=e.target,c=i.tagName.toLowerCase();if(!n&&!e.isDefaultPrevented()&&s&&/3[3456789]|40/.test(String(e.keyCode))&&"textarea"!=c&&("input"!=c||"text"!=i.type))switch(e.preventDefault(),e.keyCode){case 36:r.scrollTo(0,0,l);break;case 35:r.scrollTo(r.scrollMaxX,r.scrollMaxY,l);break;case 33:case 34:var u=r.viewport.clientHeight,h=r.viewport.clientWidth;33==e.keyCode&&(u*=-1,h*=-1),e.shiftKey?r.scrollBy(h,0,l):r.scrollBy(0,u,l);break;case 38:r.scrollBy(0,-a,l);break;case 40:r.scrollBy(0,a,l);break;case 37:r.scrollBy(-o,0,l);break;case 39:r.scrollBy(o,0,l)}},r.onDragStartX=function(e){return r.onDragStart(e,y.X)},r.onDragStartY=function(e){return r.onDragStart(e,y.Y)},r.onFastTrackX=function(e){return r.onFastTrack(e,y.X)},r.onFastTrackY=function(e){return r.onFastTrack(e,y.Y)},r.onCursorApproachingTrack=function(e){var t=r.props,o=t.nativeScroll,a=t.disabled,n=t.captureHandleDrag,s=t.fastTrack;o||a||!n&&s==g.OFF||e.buttons>0||(r.exposesX&&r._updateTrackHoverStatus(e,r.trackX),r.exposesY&&r._updateTrackHoverStatus(e,r.trackY))},s=o,n(r,s)}return s(t,e),l(t,[{key:"scrollBy",value:function(e,t,o,r,a){this.scrollTo(this.targetX+e,this.targetY+t,o,r,a)}},{key:"scrollTo",value:function(e,t){var o=arguments.length<=2||void 0===arguments[2]?0:arguments[2],r=arguments.length<=3||void 0===arguments[3]?this.props.defaultEasing:arguments[3],a=arguments.length<=4||void 0===arguments[4]?!1:arguments[4];this._easingDuration=o,this._easingBeginTimestamp=Date.now(),this.previousX=this.scrollX,this.previousY=this.scrollY,isNaN(e)||(this.targetX=e),isNaN(t)||(this.targetY=t),this._easing=r,this._silent=Boolean(a),this._forceSync()}},{key:"_forceSync",value:function(){var e=this.handleX,t=this.handleY,o=this.viewport,r=this.scrollY,a=this.scrollX,n=this.previousX,s=this.previousY,l=this._silent,i=this._easingBeginTimestamp,c=this._easing,u=this._easingDuration,h=this.props,f=h.axes,p=h.nativeScroll,d=h.outset,v=h.onViewportScroll,x=h.scrollMinX,g=h.scrollMinY,b=o.clientWidth,_=o.clientHeight,k=o.offsetWidth,X=o.offsetHeight,Y=o.scrollWidth,m=o.scrollHeight,S=o.scrollTop,w=o.scrollLeft,T=Math.max(0,Y-b),M=Math.max(0,m-_);this.exposesX=f.indexOf(y.X)>-1&&T>=x,this.exposesY=f.indexOf(y.Y)>-1&&M>=g,this.el.classList.toggle("scroll-box--show-axis-x",this.exposesX),this.el.classList.toggle("scroll-box--show-axis-y",this.exposesY);var D="100%",O="100%";if(p&&d){var E=k-b,P=X-_;E&&(D="calc(100% + "+E+"px)"),P&&(O="calc(100% + "+P+"px)")}o.style.width=D,o.style.height=O;var C=Math.max(0,Math.min(Math.round(this.targetX),T))*this.exposesX,B=Math.max(0,Math.min(Math.round(this.targetY),M))*this.exposesY,W=C,F=B;if(r==S&&a==w){var j=Date.now()-i;if(u>j&&"function"==typeof c){var L=c(j/u,j,0,1,u);W=Math.round(n+L*(C-n)),F=Math.round(s+L*(B-s))}else this._easingDuration=0;o.scrollLeft=W,o.scrollTop=F}else this._easingDuration=0,W=C=w,F=B=S;this.targetX=C,this.targetY=B,a==W&&r==F&&this.scrollMaxX==T&&this.scrollMaxY==M&&(this._easingDuration||(this._easing=null,this._silent=!1)),this.scrollX=W,this.scrollY=F,this.scrollMaxX=T,this.scrollMaxY=M,this.trackMaxX=0,this.trackMaxY=0,p||(this.trackMaxX=this.trackX.clientWidth-e.offsetWidth,this.trackMaxY=this.trackY.clientHeight-t.offsetHeight,e.style.width=b/Y*100+"%",e.style.left=this.trackMaxX*W/T+"px",t.style.height=_/m*100+"%",t.style.top=this.trackMaxY*F/M+"px"),l||a==W&&r==F||v(this)}},{key:"onDragStart",value:function(e,t){var o=this,r=this.props,a=r.disabled,n=r.captureHandleDrag;if(!a&&n&&0==e.button){e.preventDefault(),e.stopPropagation();var s=void 0;s=t==y.X?this.trackX:this.trackY;var l=e.clientX-this.handleX.offsetLeft,i=e.clientY-this.handleY.offsetTop,c=function(e){if(o._forceSyncId&&0==e.button||u(),t==y.X)var r=o.scrollMaxX*(e.clientX-l)/o.trackMaxX;else var a=o.scrollMaxY*(e.clientY-i)/o.trackMaxY;o.scrollTo(r,a,0)},u=function h(e){removeEventListener("mousemove",c),removeEventListener("mouseup",h),o._forceSyncId&&s.classList.remove("scroll-box__track--dragged")};addEventListener("mousemove",c),addEventListener("mouseup",u),s.classList.add("scroll-box__track--dragged")}}},{key:"onFastTrack",value:function(e,t){var o=this.props,r=o.disabled,a=o.fastTrack,n=o.fastTrackDuration;if(!r&&0==e.button){var s=void 0,l=void 0,i=this.viewport,c=i.clientWidth,u=i.clientHeight,h=i.scrollWidth,f=i.scrollHeight,p=e.clientX-this.trackX.getBoundingClientRect().left,d=e.clientY-this.trackY.getBoundingClientRect().top;switch(a){case g.PAGING:t==y.X?s=this.targetX+(1-2*(p<this.handleX.offsetLeft))*c:l=this.targetY+(1-2*(d<this.handleY.offsetTop))*u;break;case g.GOTO:t==y.X?s=p/this.trackX.clientWidth*h-c/2:l=d/this.trackY.clientHeight*f-u/2;break;default:return}this.scrollTo(s,l,n)}}},{key:"_updateTrackHoverStatus",value:function(e,t){var o=e.clientX,r=e.clientY,a=this.props.hoverProximity,n=t.getBoundingClientRect(),s=n.width,l=n.left,i=n.top,c=n.height;t.classList.toggle("scroll-box__track--hover",a>r-c-i&&a>i-r&&a>o-s-l&&a>l-o)}},{key:"_updateReferences",value:function(){var e=this.refs;for(var t in e)e.hasOwnProperty(t)&&(this[t]=(0,u.findDOMNode)(e[t]));this.el=(0,u.findDOMNode)(this),this.viewport=this.el.firstChild;var o=this.props.nativeScroll;null==o?"undefined"!=typeof window&&"orientation"in window&&this.el.classList.add("scroll-box--native"):this.el.classList.toggle("scroll-box--native",o)}},{key:"componentDidMount",value:function(){var e=this,t=function o(){window.cancelAnimationFrame?e._forceSyncId=requestAnimationFrame(o):e._forceSyncId=setTimeout(o,1e3/30),e._forceSync()};this._updateReferences(),t(),addEventListener("mousemove",this.onCursorApproachingTrack)}},{key:"componentDidUpdate",value:function(){this._updateReferences(),this._forceSync()}},{key:"componentWillUnmount",value:function(){window.cancelAnimationFrame?cancelAnimationFrame(this._forceSyncId):clearTimeout(this._forceSyncId),this._forceSyncId=0,removeEventListener("mousemove",this.onCursorApproachingTrack)}},{key:"render",value:function(){var e=this.props,t=e.axes,o=e.trackXChildren,r=e.trackYChildren,a=e.handleXChildren,n=e.handleYChildren,s=e.disabled,l=e.outset,i=e.className,u=e.children,h=e.style,f=["scroll-box"];return i&&(f=f.concat(i)),s&&f.push("scroll-box--disabled"),l&&f.push("scroll-box--outset"),t.indexOf(y.X)>-1&&f.push("scroll-box--has-axis-x"),t.indexOf(y.Y)>-1&&f.push("scroll-box--has-axis-y"),c["default"].createElement("div",{style:h,className:f.join(" "),onWheel:this.onWheel,onKeyDown:this.onKeyDown,onTouchStart:this.onTouchStart,onTouchMove:this.onTouchMove,onTouchEnd:this.onTouchEnd,onTouchCancel:this.onTouchEnd,tabIndex:"-1"},c["default"].Children.only(u),c["default"].createElement("div",{className:"scroll-box__track scroll-box__track--x",onMouseDown:this.onFastTrackX,ref:"trackX"},c["default"].createElement("div",{className:"scroll-box__handle scroll-box__handle--x",onMouseDown:this.onDragStartX,ref:"handleX"},a),o),c["default"].createElement("div",{className:"scroll-box__track scroll-box__track--y",onMouseDown:this.onFastTrackY,ref:"trackY"},c["default"].createElement("div",{className:"scroll-box__handle scroll-box__handle--y",onMouseDown:this.onDragStartY,ref:"handleY"},n),r))}}]),t}(c["default"].Component);b.defaultProps={className:"scroll-box--wrapped",axes:y.XY,hoverProximity:50,disabled:!1,outset:!1,scrollMinX:2,scrollMinY:2,defaultEasing:function(e,t,o,r,a){return r*Math.sqrt(1- --e*e)+o},captureHandleDrag:!0,onViewportScroll:function(e){},fastTrack:g.GOTO,fastTrackDuration:500,captureKeyboard:!0,keyboardStepX:30,keyboardStepY:30,keyboardScrollDuration:200,captureWheel:!0,wheelStepX:30,wheelStepY:30,propagateWheelScroll:!1,swapWheelAxes:!1,wheelScrollDuration:100,propagateTouchScroll:!1},b.propTypes={nativeScroll:p,className:x,axes:v([y.X,y.Y,y.XY]),hoverProximity:f,disabled:p,outset:p,scrollMinX:f,scrollMinY:f,defaultEasing:d,captureHandleDrag:p,onViewportScroll:d,fastTrack:v([g.GOTO,g.PAGING,g.OFF]),fastTrackDuration:f,captureKeyboard:p,keyboardStepX:f,keyboardStepY:f,keyboardScrollDuration:f,captureWheel:p,wheelStepX:f,wheelStepY:f,propagateWheelScroll:p,swapWheelAxes:p,wheelScrollDuration:f,propagateTouchScroll:p,trackXChildren:x,trackYChildren:x,handleXChildren:x,handleYChildren:x}},function(e,t){e.exports=require("react")},function(e,t,o){"use strict";function r(e){return e&&e.__esModule?e:{"default":e}}function a(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}function n(e,t){if(!e)throw new ReferenceError("this hasn't been initialised - super() hasn't been called");return!t||"object"!=typeof t&&"function"!=typeof t?e:t}function s(e,t){if("function"!=typeof t&&null!==t)throw new TypeError("Super expression must either be null or a function, not "+typeof t);e.prototype=Object.create(t&&t.prototype,{constructor:{value:e,enumerable:!1,writable:!0,configurable:!0}}),t&&(Object.setPrototypeOf?Object.setPrototypeOf(e,t):e.__proto__=t)}Object.defineProperty(t,"__esModule",{value:!0}),t.ScrollBox=void 0;var l=function(){function e(e,t){for(var o=0;o<t.length;o++){var r=t[o];r.enumerable=r.enumerable||!1,r.configurable=!0,"value"in r&&(r.writable=!0),Object.defineProperty(e,r.key,r)}}return function(t,o,r){return o&&e(t.prototype,o),r&&e(t,r),t}}(),i=o(2),c=r(i),u=o(1);t.ScrollBox=function(e){function t(){return a(this,t),n(this,Object.getPrototypeOf(t).apply(this,arguments))}return s(t,e),l(t,[{key:"render",value:function(){return c["default"].createElement(u.GenericScrollBox,this.props,c["default"].createElement("div",{className:"scroll-box__viewport"},this.props.children))}}]),t}(c["default"].Component)},function(e,t,o){"use strict";Object.defineProperty(t,"__esModule",{value:!0});var r=o(3);Object.defineProperty(t,"ScrollBox",{enumerable:!0,get:function(){return r.ScrollBox}});var a=o(1);Object.defineProperty(t,"GenericScrollBox",{enumerable:!0,get:function(){return a.GenericScrollBox}}),Object.defineProperty(t,"FastTrack",{enumerable:!0,get:function(){return a.FastTrack}}),Object.defineProperty(t,"ScrollAxes",{enumerable:!0,get:function(){return a.ScrollAxes}})},function(e,t){},function(e,t){e.exports=require("react-dom")}]);
module.exports=function(e){function t(n){if(r[n])return r[n].exports;var o=r[n]={exports:{},id:n,loaded:!1};return e[n].call(o.exports,o,o.exports,t),o.loaded=!0,o.exports}var r={};return t.m=e,t.c=r,t.p="",t(0)}([function(e,t,r){r(15),e.exports=r(14)},function(e,t){"use strict";function r(){throw new Error("setTimeout has not been defined")}function n(){throw new Error("clearTimeout has not been defined")}function o(e){if(s===setTimeout)return setTimeout(e,0);if((s===r||!s)&&setTimeout)return s=setTimeout,setTimeout(e,0);try{return s(e,0)}catch(t){try{return s.call(null,e,0)}catch(t){return s.call(this,e,0)}}}function l(e){if(f===clearTimeout)return clearTimeout(e);if((f===n||!f)&&clearTimeout)return f=clearTimeout,clearTimeout(e);try{return f(e)}catch(t){try{return f.call(null,e)}catch(t){return f.call(this,e)}}}function a(){h&&d&&(h=!1,d.length?y=d.concat(y):v=-1,y.length&&i())}function i(){if(!h){var e=o(a);h=!0;for(var t=y.length;t;){for(d=y,y=[];++v<t;)d&&d[v].run();v=-1,t=y.length}d=null,h=!1,l(e)}}function c(e,t){this.fun=e,this.array=t}function u(){}var s,f,p=e.exports={};!function(){try{s="function"==typeof setTimeout?setTimeout:r}catch(e){s=r}try{f="function"==typeof clearTimeout?clearTimeout:n}catch(e){f=n}}();var d,y=[],h=!1,v=-1;p.nextTick=function(e){var t=new Array(arguments.length-1);if(arguments.length>1)for(var r=1;r<arguments.length;r++)t[r-1]=arguments[r];y.push(new c(e,t)),1!==y.length||h||o(i)},c.prototype.run=function(){this.fun.apply(null,this.array)},p.title="browser",p.browser=!0,p.env={},p.argv=[],p.version="",p.versions={},p.on=u,p.addListener=u,p.once=u,p.off=u,p.removeListener=u,p.removeAllListeners=u,p.emit=u,p.prependListener=u,p.prependOnceListener=u,p.listeners=function(e){return[]},p.binding=function(e){throw new Error("process.binding is not supported")},p.cwd=function(){return"/"},p.chdir=function(e){throw new Error("process.chdir is not supported")},p.umask=function(){return 0}},function(e,t){"use strict";function r(e){return function(){return e}}var n=function(){};n.thatReturns=r,n.thatReturnsFalse=r(!1),n.thatReturnsTrue=r(!0),n.thatReturnsNull=r(null),n.thatReturnsThis=function(){return this},n.thatReturnsArgument=function(e){return e},e.exports=n},function(e,t,r){(function(t){"use strict";function r(e,t,r,o,l,a,i,c){if(n(t),!e){var u;if(void 0===t)u=new Error("Minified exception occurred; use the non-minified dev environment for the full error message and additional helpful warnings.");else{var s=[r,o,l,a,i,c],f=0;u=new Error(t.replace(/%s/g,function(){return s[f++]})),u.name="Invariant Violation"}throw u.framesToPop=1,u}}var n=function(e){};"production"!==t.env.NODE_ENV&&(n=function(e){if(void 0===e)throw new Error("invariant requires an error message argument")}),e.exports=r}).call(t,r(1))},function(e,t){"use strict";var r="SECRET_DO_NOT_PASS_THIS_OR_YOU_WILL_BE_FIRED";e.exports=r},function(e,t,r){(function(t){"use strict";var n=r(2),o=n;if("production"!==t.env.NODE_ENV){var l=function(e){for(var t=arguments.length,r=Array(t>1?t-1:0),n=1;n<t;n++)r[n-1]=arguments[n];var o=0,l="Warning: "+e.replace(/%s/g,function(){return r[o++]});"undefined"!=typeof console&&console.error(l);try{throw new Error(l)}catch(a){}};o=function(e,t){if(void 0===t)throw new Error("`warning(condition, format, ...args)` requires a warning message argument");if(0!==t.indexOf("Failed Composite propType: ")&&!e){for(var r=arguments.length,n=Array(r>2?r-2:0),o=2;o<r;o++)n[o-2]=arguments[o];l.apply(void 0,[t].concat(n))}}}e.exports=o}).call(t,r(1))},function(e,t,r){"use strict";function n(e){return e&&e.__esModule?e:{"default":e}}function o(e,t){var r={};for(var n in e)t.indexOf(n)>=0||Object.prototype.hasOwnProperty.call(e,n)&&(r[n]=e[n]);return r}function l(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}function a(e,t){if(!e)throw new ReferenceError("this hasn't been initialised - super() hasn't been called");return!t||"object"!=typeof t&&"function"!=typeof t?e:t}function i(e,t){if("function"!=typeof t&&null!==t)throw new TypeError("Super expression must either be null or a function, not "+typeof t);e.prototype=Object.create(t&&t.prototype,{constructor:{value:e,enumerable:!1,writable:!0,configurable:!0}}),t&&(Object.setPrototypeOf?Object.setPrototypeOf(e,t):e.__proto__=t)}function c(e){return null!=e&&!isNaN(e)}function u(e,t,r,n,o){return e-=1,r+n*Math.sqrt(1-Math.pow(e,2))}Object.defineProperty(t,"__esModule",{value:!0}),t.GenericScrollBox=t.FastTrackModeShape=t.ScrollCause=t.FastTrackMode=void 0;var s=Object.assign||function(e){for(var t=1;t<arguments.length;t++){var r=arguments[t];for(var n in r)Object.prototype.hasOwnProperty.call(r,n)&&(e[n]=r[n])}return e};t.easeQuadOut=u;var f=r(7),p=n(f),d=r(16),y=r(12),h=t.FastTrackMode={PAGING:"paging",GOTO:"goto"},v=t.ScrollCause={HANDLE_DRAG:0,MOUSE_WHEEL:1,FAST_TRACK:2,KEYBOARD:3,TOUCH:4},b=t.FastTrackModeShape=(0,y.oneOf)([h.GOTO,h.PAGING]),g=t.GenericScrollBox=function(e){function t(e){l(this,t);var r=a(this,(t.__proto__||Object.getPrototypeOf(t)).call(this,e)),n=0,i=0,u=0,f=0,y=0,b=0,g=0,m=0,S=void 0,T=void 0,O=0,x=0,w=!1,E=0,Y=0,D=0,X=0,k=!1,_=!1,P=void 0,A=!1,N=!1,B=null,j=null,R=0,H=0,M=void 0,L=void 0,C=void 0,W=void 0,G=void 0,I=void 0;r.render=function(){var e=r.props,t=e.className,n=e.style,o=e.disabled,l=e.outsetScrollBarX,a=e.outsetScrollBarY,i=e.clientScrollBars,c=e.disableScrollX,u=e.disableScrollY,s=e.hideScrollBarX,f=e.hideScrollBarY,d=e.children,y=e.trackChildrenX,h=e.trackChildrenY,v=e.handleChildrenX,b=e.handleChildrenY,g=["scroll-box"];return t&&(g=g.concat(t)),o&&g.push("scroll-box--disabled"),l&&g.push("scroll-box--outset-x"),a&&g.push("scroll-box--outset-y"),c||s||g.push("scroll-box--enable-x"),u||f||g.push("scroll-box--enable-y"),i&&g.push("scroll-box--client-scroll-bars"),p["default"].createElement("div",{style:n,className:g.join(" "),onWheel:z,onKeyDown:K,onTouchStart:te,tabIndex:"-1"},d,p["default"].createElement("div",{className:"scroll-box__track scroll-box__track--x",onMouseDown:U,ref:"trackX"},p["default"].createElement("div",{className:"scroll-box__handle scroll-box__handle--x",onMouseDown:$,ref:"handleX"},v),y),p["default"].createElement("div",{className:"scroll-box__track scroll-box__track--y",onMouseDown:V,ref:"trackY"},p["default"].createElement("div",{className:"scroll-box__handle scroll-box__handle--y",onMouseDown:Q,ref:"handleY"},b),h))},r.componentDidMount=function(){M=(0,d.findDOMNode)(r);var e=r.refs,t=e.handleX,n=e.handleY,o=e.trackX,l=e.trackY;C=(0,d.findDOMNode)(t),W=(0,d.findDOMNode)(n),G=(0,d.findDOMNode)(o),I=(0,d.findDOMNode)(l),L=M.firstElementChild;var a=function i(){P=window.cancelAnimationFrame?requestAnimationFrame(i):setTimeout(i,1e3/30),F()};a(),addEventListener("mousemove",ee)},r.componentWillUnmount=function(){M=null,window.cancelAnimationFrame?cancelAnimationFrame(P):clearTimeout(P),removeEventListener("mousemove",ee)},r.componentDidUpdate=function(){L=M.firstElementChild,F()},r.scrollTo=function(){var e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:{},t=e.x,o=e.y,l=e.easing,a=e.easingX,s=void 0===a?l||r.props.easingX:a,p=e.easingY,d=void 0===p?l||r.props.easingY:p,h=e.duration,v=void 0===h?0:h,E=e.durationX,Y=void 0===E?v:E,D=e.durationY,X=void 0===D?v:D,k=e.dispatchPrevented,_=void 0!==k&&k;c(t)&&(u=n,y=0|t,S=s,g=Y,O=Date.now(),w=_,R++),c(o)&&(f=i,b=0|o,T=d,m=X,x=Date.now(),w=_,H++),F()},r.scrollToX=function(e){var t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:{};return r.scrollTo(s({},t,{x:e}))},r.scrollToY=function(e){var t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:{};return r.scrollTo(s({},t,{y:e}))},r.scrollBy=function(){var e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:{},t=e.dx,n=e.dy,l=o(e,["dx","dy"]);r.scrollTo(s({},l,{x:y+t,y:b+n}))},r.scrollByX=function(e){var t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:{};return r.scrollBy(s({},t,{dx:e}))},r.scrollByY=function(e){var t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:{};return r.scrollBy(s({},t,{dy:e}))},r.scrollToPage=function(){var e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:{},t=e.x,n=e.y,l=o(e,["x","y"]);t*=r.getPageWidth(),n*=r.getPageHeight(),r.scrollTo(s({},l,{x:t,y:n}))},r.scrollToPageX=function(e){var t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:{};return r.scrollToPage(s({},t,{x:e}))},r.scrollToPageY=function(e){var t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:{};return r.scrollToPage(s({},t,{y:e}))},r.scrollByPage=function(){var e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:{},t=e.dx,n=e.dy,l=o(e,["dx","dy"]);t*=r.getPageWidth(),n*=r.getPageHeight(),r.scrollBy(s({},l,{dx:t,dy:n}))},r.scrollByPageX=function(e){var t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:{};return r.scrollByPage(s({},t,{dx:e}))},r.scrollByPageY=function(e){var t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:{};return r.scrollByPage(s({},t,{dy:e}))},r.getPageWidth=function(){return L.clientWidth},r.getPageHeight=function(){return L.clientHeight},Object.defineProperties(r,{targetX:{get:function(){return y},set:function(e){return r.scrollToX(e)}},targetY:{get:function(){return b},set:function(e){return r.scrollToY(e)}},scrollX:{get:function(){return n},set:function(e){return r.scrollToX(e)}},scrollY:{get:function(){return i},set:function(e){return r.scrollToY(e)}},scrollMaxX:{get:function(){return E}},scrollMaxY:{get:function(){return Y}}});var F=function(){var e=r.props,t=e.disableScrollX,o=e.disableScrollY,l=e.scrollMinX,a=e.scrollMinY,c=e.clientScrollBars,s=e.outsetScrollBarX,p=e.outsetScrollBarY,d=e.onScroll,h=e.onScrollX,P=e.onScrollY,F=e.onScrollStart,K=e.onScrollStartX,q=e.onScrollStartY,U=e.onScrollEnd,V=e.onScrollEndX,J=e.onScrollEndY,$=L,Q=$.clientWidth,z=$.clientHeight,Z=$.offsetWidth,ee=$.offsetHeight,te=$.scrollWidth,re=$.scrollHeight,ne=$.scrollTop,oe=$.scrollLeft;E=te-Q,Y=re-z,k=!t&&E>=l,_=!o&&Y>=a,M.classList.toggle("scroll-box--requires-x",k),M.classList.toggle("scroll-box--requires-y",_),c&&s?L.style.height="calc(100% + "+(ee-z)+"px)":L.style.height="100%",c&&p?L.style.width="calc(100% + "+(Z-Q)+"px)":L.style.width="100%",y=Math.max(0,Math.min(y,E)),b=Math.max(0,Math.min(b,Y));var le=n,ae=i;if(n==oe&&i==ne){if(le!=y){var ie=Date.now()-O;le=ie<g?u+S(ie/g,ie,0,1,g)*(y-u)|0:y}if(ae!=b){var ce=Date.now()-x;ae=ce<m?f+T(ce/m,ce,0,1,m)*(b-f)|0:b}}var ue=n!=oe,se=i!=ne;ue&&(y=le=oe),se&&(b=ae=ne);var fe=le!=y,pe=ae!=b,de=n-le,ye=i-ae,he=R,ve=H;w||(fe|pe|ue|se&&!A&&!N&&F(r,B,j),he==R&&fe&&!A&&K(r,B),ve==H&&pe&&!N&&q(r,j),he==R&&ve==H&&de|ye&&d(r,de,ye,B,j),he==R&&de&&h(r,de,B),ve==H&&ye&&P(r,ye,j),he==R&&ve==H&&!fe&&!pe&&A|N|ue|se&&U(r,B,j),he==R&&!fe&&A&&V(r,B),ve==H&&!pe&&N&&J(r,j),he==R&&B!=v.TOUCH|B!=v.HANDLE_DRAG&&(B=null),ve==H&&j!=v.TOUCH|j!=v.HANDLE_DRAG&&(j=null)),de&&he==R&&(L.scrollLeft=n=le),ye&&ve==H&&(L.scrollTop=i=ae),c||(D=G.clientWidth-C.offsetWidth,C.style.width=Q/te*100+"%",C.style.left=D*le/E+"px",X=I.clientHeight-W.offsetHeight,W.style.height=z/re*100+"%",W.style.top=X*ae/Y+"px")},K=function(e){var t=e.target.tagName,n=e.keyCode,o=e.shiftKey,l=r.props,a=l.disabled,i=l.captureKeyboard,c=l.keyboardStepX,u=l.keyboardStepY,s=l.keyboardScrollDuration;if(!(a|!i|"TEXTAREA"==t|"INPUT"==t)){var f={duration:s};switch(n){case 36:e.preventDefault(),j=v.KEYBOARD,r.scrollToY(0,f);break;case 35:e.preventDefault(),j=v.KEYBOARD,r.scrollToY(Y,f);break;case 33:case 34:e.preventDefault();var p=r.getPageHeight(),d=r.getPageWidth();33==n&&(p*=-1,d*=-1),o?(B=v.KEYBOARD,r.scrollByX(d,f)):(j=v.KEYBOARD,r.scrollByY(p,f));break;case 38:e.preventDefault(),j=v.KEYBOARD,r.scrollByY(-u,f);break;case 40:e.preventDefault(),j=v.KEYBOARD,r.scrollByY(u,f);break;case 37:e.preventDefault(),B=v.KEYBOARD,r.scrollByX(-c,f);break;case 39:e.preventDefault(),B=v.KEYBOARD,r.scrollByX(c,f)}}},q=function(e,t){var n=r.props,o=n.disabled,l=n.captureFastTrackX,a=n.captureFastTrackY,i=n.fastTrackModeX,c=n.fastTrackModeY,u=n.fastTrackScrollDurationX,s=n.fastTrackScrollDurationY;if(!(o|!l&&!a|e.button)){var f=L,p=f.clientWidth,d=f.clientHeight,g=f.scrollWidth,m=f.scrollHeight;if(t){if(!l)return;B=v.FAST_TRACK;var S=e.clientX-G.getBoundingClientRect().left,T={duration:u};switch(i){case h.PAGING:r.scrollToX(y+(1-2*(S<C.offsetLeft))*r.getPageWidth(),T);break;case h.GOTO:r.scrollToX(S/G.clientWidth*g-p/2,T)}}else{if(!a)return;j=v.FAST_TRACK;var O=e.clientY-I.getBoundingClientRect().top,x={duration:s};switch(c){case h.PAGING:r.scrollToY(b+(1-2*(O<W.offsetTop))*r.getPageHeight(),x);break;case h.GOTO:r.scrollToY(O/I.clientHeight*m-d/2,x)}}}},U=function(e){return q(e,!0)},V=function(e){return q(e,!1)},J=function(e,t){var n=r.props,o=n.disabled,l=n.captureHandleDragX,a=n.captureHandleDragY,i=n.permitHandleDragInterruption;if(!(o|!l&&!a|e.button)){e.preventDefault(),e.stopPropagation();var c=void 0;t?(B=v.HANDLE_DRAG,c=G):(j=v.HANDLE_DRAG,c=I);var u=e.clientX-C.offsetLeft,s=e.clientY-W.offsetTop,f=function(e){return!M|e.button|i&&(t?B:j)!=v.HANDLE_DRAG?void d():void(t?(B=v.HANDLE_DRAG,r.scrollToX(E*(e.clientX-u)/D)):(j=v.HANDLE_DRAG,r.scrollToY(Y*(e.clientY-s)/X)))},p=function(){t?B=null:j=null,d()},d=function(){removeEventListener("mousemove",f),removeEventListener("mouseup",p),c.classList.remove("scroll-box__track--dragged")};addEventListener("mousemove",f),addEventListener("mouseup",p),c.classList.add("scroll-box__track--dragged")}},$=function(e){return J(e,!0)},Q=function(e){return J(e,!1)},z=function(e){var t=e.target,o=e.deltaMode,l=e.deltaX,a=e.deltaY,c=e.shiftKey,u=r.props,s=u.wheelStepX,f=u.wheelStepY,p=u.disabled,d=u.clientScrollBars,h=u.captureWheel,g=u.lineHeight,m=u.propagateWheelScrollX,S=u.propagateWheelScrollY,T=u.swapWheelAxes,x=u.wheelScrollDurationX,w=u.wheelScrollDurationY;if(d&&!h&&e.preventDefault(),!(p|e.isDefaultPrevented()||t!=L&&"TEXTAREA"==t.tagName)){if(c&&0==l&&(l=a,a=0),T){var D=l;l=a,a=D}var X=l*k,P=a*_;if(l&&!k|X<0&&!y|X>0&&y==E)return void(m||e.preventDefault());if(a&&!_|P<0&&!b|P>0&&b==Y)return void(S||e.preventDefault());switch(e.preventDefault(),o){case 1:X*=g,P*=g;break;case 2:X*=r.getPageWidth(),P*=r.getPageHeight()}X*=s/100,P*=f/100;var A=y+X,N=b+P;Date.now()-O>x&&(A=n+X),Date.now()-O>w&&(N=i+P),X&&(B=v.MOUSE_WHEEL,r.scrollToX(A,{duration:x})),P&&(j=v.MOUSE_WHEEL,r.scrollToY(N,{duration:w}))}},Z=function(e,t,r,n){if(null==n){var o=e.clientX,l=e.clientY,a=t.getBoundingClientRect(),i=a.width,c=a.left,u=a.top,s=a.height;n=r>l-s-u&&r>o-i-c&&r>c-o&&r>u-l}t.classList.toggle("scroll-box__track--hover",n)},ee=function(e){var t=r.props,n=t.disabled,o=t.clientScrollBars,l=t.captureHandleDragX,a=t.captureHandleDragY,i=t.captureFastTrackX,c=t.captureFastTrackY,u=t.trackHoverProximityX,s=t.trackHoverProximityY;if(!("orientation"in window|o|n)){if(e.buttons){if(B!=v.HANDLE_DRAG)var f=!1;if(j!=v.HANDLE_DRAG)var p=!1}k&&l|i&&Z(e,G,u,f),_&&a|c&&Z(e,I,s,p)}},te=function(e){var t=e.target,o=e.touches,l=r.props,a=l.disabled,c=l.clientScrollBars,u=l.captureTouch;l.propagateTouchScrollX,l.propagateTouchScrollY;if(c&&!u&&e.preventDefault(),!(c|a|o.length>1|e.isDefaultPrevented()||t!=L&&"TEXTAREA"==t.tagName)){var s=o[0],f=s.clientX,p=s.clientY,d=!1,y=function(e){var t=r.targetX,o=r.targetY,l=r.scrollMaxX,a=r.scrollMaxY,c=e.touches[0],u=c.clientX,s=c.clientY,y=f-u,h=p-s;return y<0&&!t||y>0&&t==l||h<0&&!o||h>0&&o==a?void(d||v()):(d=!0,e.preventDefault(),void r.scrollTo({x:n+y,y:i+h}))},h=function(e){v()},v=function(){removeEventListener("touchmove",y),removeEventListener("touchend",h),removeEventListener("touchcancel",h)};addEventListener("touchmove",y),addEventListener("touchend",h),addEventListener("touchcancel",h)}};return r}return i(t,e),t}(p["default"].Component);g.propTypes={children:y.element.isRequired,clientScrollBars:y.bool,className:y.any,style:y.object,disabled:y.bool,onScroll:y.func,onScrollX:y.func,onScrollY:y.func,onScrollStart:y.func,onScrollStartX:y.func,onScrollStartY:y.func,onScrollEnd:y.func,onScrollEndX:y.func,onScrollEndY:y.func,disableScrollX:y.bool,disableScrollY:y.bool,hideScrollBarX:y.bool,hideScrollBarY:y.bool,outsetScrollBarX:y.bool,outsetScrollBarY:y.bool,scrollMinX:y.number,scrollMinY:y.number,trackHoverProximityX:y.number,trackHoverProximityY:y.number,easingX:y.func,easingY:y.func,captureHandleDragX:y.bool,captureHandleDragY:y.bool,permitHandleDragInterruption:y.bool,captureFastTrackX:y.bool,captureFastTrackY:y.bool,fastTrackModeX:b,fastTrackModeY:b,fastTrackScrollDurationX:y.number,fastTrackScrollDurationY:y.number,captureKeyboard:y.bool,keyboardStepX:y.number,keyboardStepY:y.number,keyboardScrollDurationX:y.number,keyboardScrollDurationY:y.number,captureWheel:y.bool,lineHeight:y.number,wheelStepX:y.number,wheelStepY:y.number,propagateWheelScrollX:y.bool,propagateWheelScrollY:y.bool,swapWheelAxes:y.bool,wheelScrollDurationX:y.number,wheelScrollDurationY:y.number,captureTouch:y.bool,propagateTouchScrollX:y.bool,propagateTouchScrollY:y.bool,trackChildrenX:y.node,trackChildrenY:y.node,handleChildrenX:y.node,handleChildrenY:y.node},g.defaultProps={clientScrollBars:!1,className:"scroll-box--wrapped",disabled:!1,onScroll:function(e,t,r,n,o){},onScrollX:function(e,t,r){},onScrollY:function(e,t,r){},onScrollStart:function(e,t,r){},onScrollStartX:function(e,t){},onScrollStartY:function(e,t){},onScrollEnd:function(e,t,r){},onScrollEndX:function(e,t){},onScrollEndY:function(e,t){},disableScrollX:!1,disableScrollY:!1,hideScrollBarX:!1,hideScrollBarY:!1,outsetScrollBarX:!1,outsetScrollBarY:!1,scrollMinX:2,scrollMinY:2,trackHoverProximityX:50,trackHoverProximityY:50,easingX:u,easingY:u,captureHandleDragX:!0,captureHandleDragY:!0,permitHandleDragInterruption:!0,captureFastTrackX:!0,captureFastTrackY:!0,fastTrackModeX:h.GOTO,fastTrackModeY:h.GOTO,fastTrackScrollDurationX:500,fastTrackScrollDurationY:500,captureKeyboard:!0,keyboardStepX:30,keyboardStepY:30,keyboardScrollDuration:200,captureWheel:!0,lineHeight:24,wheelStepX:100,wheelStepY:100,propagateWheelScrollX:!0,propagateWheelScrollY:!0,swapWheelAxes:!1,wheelScrollDurationX:100,wheelScrollDurationY:100,captureTouch:!0,propagateTouchScrollX:!0,propagateTouchScrollY:!0}},function(e,t){e.exports=require("react")},function(e,t){/*
object-assign
(c) Sindre Sorhus
@license MIT
*/
"use strict";function r(e){if(null===e||void 0===e)throw new TypeError("Object.assign cannot be called with null or undefined");return Object(e)}function n(){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={},r=0;r<10;r++)t["_"+String.fromCharCode(r)]=r;var n=Object.getOwnPropertyNames(t).map(function(e){return t[e]});if("0123456789"!==n.join(""))return!1;var o={};return"abcdefghijklmnopqrst".split("").forEach(function(e){o[e]=e}),"abcdefghijklmnopqrst"===Object.keys(Object.assign({},o)).join("")}catch(l){return!1}}var o=Object.getOwnPropertySymbols,l=Object.prototype.hasOwnProperty,a=Object.prototype.propertyIsEnumerable;e.exports=n()?Object.assign:function(e,t){for(var n,i,c=r(e),u=1;u<arguments.length;u++){n=Object(arguments[u]);for(var s in n)l.call(n,s)&&(c[s]=n[s]);if(o){i=o(n);for(var f=0;f<i.length;f++)a.call(n,i[f])&&(c[i[f]]=n[i[f]])}}return c}},function(e,t,r){(function(t){"use strict";function n(e,r,n,u,s){if("production"!==t.env.NODE_ENV)for(var f in e)if(e.hasOwnProperty(f)){var p;try{l("function"==typeof e[f],"%s: %s type `%s` is invalid; it must be a function, usually from the `prop-types` package, but received `%s`.",u||"React class",n,f,o(e[f])),p=e[f](r,f,u,n,null,i)}catch(d){p=d}if(a(!p||p instanceof Error,"%s: type specification of %s `%s` is invalid; the type checker function must return `null` or an `Error` but returned a %s. You may have forgotten to pass an argument to the type checker creator (arrayOf, instanceOf, objectOf, oneOf, oneOfType, and shape all require an argument).",u||"React class",n,f,"undefined"==typeof p?"undefined":o(p)),p instanceof Error&&!(p.message in c)){c[p.message]=!0;var y=s?s():"";a(!1,"Failed %s type: %s%s",n,p.message,null!=y?y:"")}}}var o="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(e){return typeof e}:function(e){return e&&"function"==typeof Symbol&&e.constructor===Symbol&&e!==Symbol.prototype?"symbol":typeof e};if("production"!==t.env.NODE_ENV)var l=r(3),a=r(5),i=r(4),c={};e.exports=n}).call(t,r(1))},function(e,t,r){"use strict";var n=r(2),o=r(3),l=r(4);e.exports=function(){function e(e,t,r,n,a,i){i!==l&&o(!1,"Calling PropTypes validators directly is not supported by the `prop-types` package. Use PropTypes.checkPropTypes() to call them. Read more at http://fb.me/use-check-prop-types")}function t(){return e}e.isRequired=e;var r={array:e,bool:e,func:e,number:e,object:e,string:e,symbol:e,any:e,arrayOf:t,element:e,instanceOf:t,node:e,objectOf:t,oneOf:t,oneOfType:t,shape:t,exact:t};return r.checkPropTypes=n,r.PropTypes=r,r}},function(e,t,r){(function(t){"use strict";var n="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(e){return typeof e}:function(e){return e&&"function"==typeof Symbol&&e.constructor===Symbol&&e!==Symbol.prototype?"symbol":typeof e},o=r(2),l=r(3),a=r(5),i=r(8),c=r(4),u=r(9);e.exports=function(e,r){function s(e){var t=e&&(P&&e[P]||e[A]);if("function"==typeof t)return t}function f(e,t){return e===t?0!==e||1/e===1/t:e!==e&&t!==t}function p(e){this.message=e,this.stack=""}function d(e){function n(n,u,s,f,d,y,h){if(f=f||N,y=y||s,h!==c)if(r)l(!1,"Calling PropTypes validators directly is not supported by the `prop-types` package. Use `PropTypes.checkPropTypes()` to call them. Read more at http://fb.me/use-check-prop-types");else if("production"!==t.env.NODE_ENV&&"undefined"!=typeof console){var v=f+":"+s;!o[v]&&i<3&&(a(!1,"You are manually calling a React.PropTypes validation function for the `%s` prop on `%s`. This is deprecated and will throw in the standalone `prop-types` package. You may be seeing this warning due to a third-party PropTypes library. See https://fb.me/react-warning-dont-call-proptypes for details.",y,f),o[v]=!0,i++)}return null==u[s]?n?new p(null===u[s]?"The "+d+" `"+y+"` is marked as required "+("in `"+f+"`, but its value is `null`."):"The "+d+" `"+y+"` is marked as required in "+("`"+f+"`, but its value is `undefined`.")):null:e(u,s,f,d,y)}if("production"!==t.env.NODE_ENV)var o={},i=0;var u=n.bind(null,!1);return u.isRequired=n.bind(null,!0),u}function y(e){function t(t,r,n,o,l,a){var i=t[r],c=D(i);if(c!==e){var u=X(i);return new p("Invalid "+o+" `"+l+"` of type "+("`"+u+"` supplied to `"+n+"`, expected ")+("`"+e+"`."))}return null}return d(t)}function h(){return d(o.thatReturnsNull)}function v(e){function t(t,r,n,o,l){if("function"!=typeof e)return new p("Property `"+l+"` of component `"+n+"` has invalid PropType notation inside arrayOf.");var a=t[r];if(!Array.isArray(a)){var i=D(a);return new p("Invalid "+o+" `"+l+"` of type "+("`"+i+"` supplied to `"+n+"`, expected an array."))}for(var u=0;u<a.length;u++){var s=e(a,u,n,o,l+"["+u+"]",c);if(s instanceof Error)return s}return null}return d(t)}function b(){function t(t,r,n,o,l){var a=t[r];if(!e(a)){var i=D(a);return new p("Invalid "+o+" `"+l+"` of type "+("`"+i+"` supplied to `"+n+"`, expected a single ReactElement."))}return null}return d(t)}function g(e){function t(t,r,n,o,l){if(!(t[r]instanceof e)){var a=e.name||N,i=_(t[r]);return new p("Invalid "+o+" `"+l+"` of type "+("`"+i+"` supplied to `"+n+"`, expected ")+("instance of `"+a+"`."))}return null}return d(t)}function m(e){function r(t,r,n,o,l){for(var a=t[r],i=0;i<e.length;i++)if(f(a,e[i]))return null;var c=JSON.stringify(e);return new p("Invalid "+o+" `"+l+"` of value `"+a+"` "+("supplied to `"+n+"`, expected one of "+c+"."))}return Array.isArray(e)?d(r):("production"!==t.env.NODE_ENV?a(!1,"Invalid argument supplied to oneOf, expected an instance of array."):void 0,o.thatReturnsNull)}function S(e){function t(t,r,n,o,l){if("function"!=typeof e)return new p("Property `"+l+"` of component `"+n+"` has invalid PropType notation inside objectOf.");var a=t[r],i=D(a);if("object"!==i)return new p("Invalid "+o+" `"+l+"` of type "+("`"+i+"` supplied to `"+n+"`, expected an object."));for(var u in a)if(a.hasOwnProperty(u)){var s=e(a,u,n,o,l+"."+u,c);if(s instanceof Error)return s}return null}return d(t)}function T(e){function r(t,r,n,o,l){for(var a=0;a<e.length;a++){var i=e[a];if(null==i(t,r,n,o,l,c))return null}return new p("Invalid "+o+" `"+l+"` supplied to "+("`"+n+"`."))}if(!Array.isArray(e))return"production"!==t.env.NODE_ENV?a(!1,"Invalid argument supplied to oneOfType, expected an instance of array."):void 0,o.thatReturnsNull;for(var n=0;n<e.length;n++){var l=e[n];if("function"!=typeof l)return a(!1,"Invalid argument supplied to oneOfType. Expected an array of check functions, but received %s at index %s.",k(l),n),o.thatReturnsNull}return d(r)}function O(){function e(e,t,r,n,o){return E(e[t])?null:new p("Invalid "+n+" `"+o+"` supplied to "+("`"+r+"`, expected a ReactNode."))}return d(e)}function x(e){function t(t,r,n,o,l){var a=t[r],i=D(a);if("object"!==i)return new p("Invalid "+o+" `"+l+"` of type `"+i+"` "+("supplied to `"+n+"`, expected `object`."));for(var u in e){var s=e[u];if(s){var f=s(a,u,n,o,l+"."+u,c);if(f)return f}}return null}return d(t)}function w(e){function t(t,r,n,o,l){var a=t[r],u=D(a);if("object"!==u)return new p("Invalid "+o+" `"+l+"` of type `"+u+"` "+("supplied to `"+n+"`, expected `object`."));var s=i({},t[r],e);for(var f in s){var d=e[f];if(!d)return new p("Invalid "+o+" `"+l+"` key `"+f+"` supplied to `"+n+"`.\nBad object: "+JSON.stringify(t[r],null," ")+"\nValid keys: "+JSON.stringify(Object.keys(e),null," "));var y=d(a,f,n,o,l+"."+f,c);if(y)return y}return null}return d(t)}function E(t){switch("undefined"==typeof t?"undefined":n(t)){case"number":case"string":case"undefined":return!0;case"boolean":return!t;case"object":if(Array.isArray(t))return t.every(E);if(null===t||e(t))return!0;var r=s(t);if(!r)return!1;var o,l=r.call(t);if(r!==t.entries){for(;!(o=l.next()).done;)if(!E(o.value))return!1}else for(;!(o=l.next()).done;){var a=o.value;if(a&&!E(a[1]))return!1}return!0;default:return!1}}function Y(e,t){return"symbol"===e||("Symbol"===t["@@toStringTag"]||"function"==typeof Symbol&&t instanceof Symbol)}function D(e){var t="undefined"==typeof e?"undefined":n(e);return Array.isArray(e)?"array":e instanceof RegExp?"object":Y(t,e)?"symbol":t}function X(e){if("undefined"==typeof e||null===e)return""+e;var t=D(e);if("object"===t){if(e instanceof Date)return"date";if(e instanceof RegExp)return"regexp"}return t}function k(e){var t=X(e);switch(t){case"array":case"object":return"an "+t;case"boolean":case"date":case"regexp":return"a "+t;default:return t}}function _(e){return e.constructor&&e.constructor.name?e.constructor.name:N}var P="function"==typeof Symbol&&Symbol.iterator,A="@@iterator",N="<<anonymous>>",B={array:y("array"),bool:y("boolean"),func:y("function"),number:y("number"),object:y("object"),string:y("string"),symbol:y("symbol"),any:h(),arrayOf:v,element:b(),instanceOf:g,node:O(),objectOf:S,oneOf:m,oneOfType:T,shape:x,exact:w};return p.prototype=Error.prototype,B.checkPropTypes=u,B.PropTypes=B,B}}).call(t,r(1))},function(e,t,r){(function(t){"use strict";var n="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(e){return typeof e}:function(e){return e&&"function"==typeof Symbol&&e.constructor===Symbol&&e!==Symbol.prototype?"symbol":typeof e};if("production"!==t.env.NODE_ENV){var o="function"==typeof Symbol&&Symbol["for"]&&Symbol["for"]("react.element")||60103,l=function(e){return"object"===("undefined"==typeof e?"undefined":n(e))&&null!==e&&e.$$typeof===o},a=!0;e.exports=r(11)(l,a)}else e.exports=r(10)()}).call(t,r(1))},function(e,t,r){"use strict";function n(e){return e&&e.__esModule?e:{"default":e}}function o(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}function l(e,t){if(!e)throw new ReferenceError("this hasn't been initialised - super() hasn't been called");return!t||"object"!=typeof t&&"function"!=typeof t?e:t}function a(e,t){if("function"!=typeof t&&null!==t)throw new TypeError("Super expression must either be null or a function, not "+typeof t);e.prototype=Object.create(t&&t.prototype,{constructor:{value:e,enumerable:!1,writable:!0,configurable:!0}}),t&&(Object.setPrototypeOf?Object.setPrototypeOf(e,t):e.__proto__=t)}Object.defineProperty(t,"__esModule",{value:!0}),t.ScrollBox=void 0;var i=function(){function e(e,t){for(var r=0;r<t.length;r++){var n=t[r];n.enumerable=n.enumerable||!1,n.configurable=!0,"value"in n&&(n.writable=!0),Object.defineProperty(e,n.key,n)}}return function(t,r,n){return r&&e(t.prototype,r),n&&e(t,n),t}}(),c=r(7),u=n(c),s=r(6);t.ScrollBox=function(e){function t(){return o(this,t),l(this,(t.__proto__||Object.getPrototypeOf(t)).apply(this,arguments))}return a(t,e),i(t,[{key:"render",value:function(){return u["default"].createElement(s.GenericScrollBox,this.props,u["default"].createElement("div",{className:"scroll-box__viewport"},this.props.children))}}]),t}(u["default"].Component)},function(e,t,r){"use strict";Object.defineProperty(t,"__esModule",{value:!0});var n=r(13);Object.defineProperty(t,"ScrollBox",{enumerable:!0,get:function(){return n.ScrollBox}});var o=r(6);Object.defineProperty(t,"GenericScrollBox",{enumerable:!0,get:function(){return o.GenericScrollBox}}),Object.defineProperty(t,"FastTrackMode",{enumerable:!0,get:function(){return o.FastTrackMode}}),Object.defineProperty(t,"ScrollCause",{enumerable:!0,get:function(){return o.ScrollCause}})},function(e,t){},function(e,t){e.exports=require("react-dom")}]);