rsb
Version:
ScrollArea component for react
1,409 lines (1,241 loc) • 400 kB
JavaScript
(function webpackUniversalModuleDefinition(root, factory) {
if(typeof exports === 'object' && typeof module === 'object')
module.exports = factory(require("react"));
else if(typeof define === 'function' && define.amd)
define(["react"], factory);
else if(typeof exports === 'object')
exports["rsb"] = factory(require("react"));
else
root["rsb"] = factory(root["React"]);
})(this, function(__WEBPACK_EXTERNAL_MODULE_6__) {
return /******/ (function(modules) { // webpackBootstrap
/******/ // The module cache
/******/ var installedModules = {};
/******/
/******/ // The require function
/******/ function __webpack_require__(moduleId) {
/******/
/******/ // Check if module is in cache
/******/ if(installedModules[moduleId])
/******/ return installedModules[moduleId].exports;
/******/
/******/ // Create a new module (and put it into the cache)
/******/ var module = installedModules[moduleId] = {
/******/ exports: {},
/******/ id: moduleId,
/******/ loaded: false
/******/ };
/******/
/******/ // Execute the module function
/******/ modules[moduleId].call(module.exports, module, module.exports, __webpack_require__);
/******/
/******/ // Flag the module as loaded
/******/ module.loaded = true;
/******/
/******/ // Return the exports of the module
/******/ return module.exports;
/******/ }
/******/
/******/
/******/ // expose the modules object (__webpack_modules__)
/******/ __webpack_require__.m = modules;
/******/
/******/ // expose the module cache
/******/ __webpack_require__.c = installedModules;
/******/
/******/ // __webpack_public_path__
/******/ __webpack_require__.p = "";
/******/
/******/ // Load entry module and return exports
/******/ return __webpack_require__(0);
/******/ })
/************************************************************************/
/******/ ([
/* 0 */
/***/ (function(module, exports, __webpack_require__) {
'use strict';
Object.defineProperty(exports, "__esModule", {
value: true
});
__webpack_require__(1);
var _ScrollArea = __webpack_require__(5);
var _ScrollArea2 = _interopRequireDefault(_ScrollArea);
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
exports.default = _ScrollArea2.default;
/***/ }),
/* 1 */
/***/ (function(module, exports, __webpack_require__) {
// style-loader: Adds some css to the DOM by adding a <style> tag
// load the styles
var content = __webpack_require__(2);
if(typeof content === 'string') content = [[module.id, content, '']];
// add the styles to the DOM
var update = __webpack_require__(4)(content, {});
if(content.locals) module.exports = content.locals;
// Hot Module Replacement
if(false) {
// When the styles change, update the <style> tags
if(!content.locals) {
module.hot.accept("!!../../node_modules/css-loader/index.js!../../node_modules/less-loader/index.js!./scrollArea.less", function() {
var newContent = require("!!../../node_modules/css-loader/index.js!../../node_modules/less-loader/index.js!./scrollArea.less");
if(typeof newContent === 'string') newContent = [[module.id, newContent, '']];
update(newContent);
});
}
// When the module is disposed, remove the <style> tags
module.hot.dispose(function() { update(); });
}
/***/ }),
/* 2 */
/***/ (function(module, exports, __webpack_require__) {
exports = module.exports = __webpack_require__(3)();
// imports
// module
exports.push([module.id, ".scrollarea-content {\n margin: 0;\n padding: 0;\n overflow: hidden;\n position: relative;\n}\n.scrollarea-content:focus {\n outline: 0;\n}\n.scrollarea {\n position: relative;\n overflow: hidden;\n}\n.scrollarea .scrollbar-container {\n position: absolute;\n background: none;\n opacity: .1;\n z-index: 9999;\n -webkit-transition: all .4s;\n -moz-transition: all .4s;\n -ms-transition: all .4s;\n -o-transition: all .4s;\n transition: all .4s;\n}\n.scrollarea .scrollbar-container.horizontal {\n width: 100%;\n height: 10px;\n left: 0;\n bottom: 0;\n}\n.scrollarea .scrollbar-container.horizontal .scrollbar {\n width: 20px;\n height: 8px;\n background: black;\n margin-top: 1px;\n}\n.scrollarea .scrollbar-container.vertical {\n width: 10px;\n height: 100%;\n right: 0;\n top: 0;\n}\n.scrollarea .scrollbar-container.vertical .scrollbar {\n width: 8px;\n height: 20px;\n background: black;\n margin-left: 1px;\n}\n.scrollarea .scrollbar-container:hover {\n background: gray;\n opacity: .6 !important;\n}\n.scrollarea .scrollbar-container.active {\n background: gray;\n opacity: .6 !important;\n}\n.scrollarea:hover .scrollbar-container {\n opacity: .3;\n}\n", ""]);
// exports
/***/ }),
/* 3 */
/***/ (function(module, exports) {
/*
MIT License http://www.opensource.org/licenses/mit-license.php
Author Tobias Koppers @sokra
*/
// css base code, injected by the css-loader
module.exports = function() {
var list = [];
// return the list of modules as css string
list.toString = function toString() {
var result = [];
for(var i = 0; i < this.length; i++) {
var item = this[i];
if(item[2]) {
result.push("@media " + item[2] + "{" + item[1] + "}");
} else {
result.push(item[1]);
}
}
return result.join("");
};
// import a list of modules into the list
list.i = function(modules, mediaQuery) {
if(typeof modules === "string")
modules = [[null, modules, ""]];
var alreadyImportedModules = {};
for(var i = 0; i < this.length; i++) {
var id = this[i][0];
if(typeof id === "number")
alreadyImportedModules[id] = true;
}
for(i = 0; i < modules.length; i++) {
var item = modules[i];
// skip already imported module
// this implementation is not 100% perfect for weird media query combinations
// when a module is imported multiple times with different media queries.
// I hope this will never occur (Hey this way we have smaller bundles)
if(typeof item[0] !== "number" || !alreadyImportedModules[item[0]]) {
if(mediaQuery && !item[2]) {
item[2] = mediaQuery;
} else if(mediaQuery) {
item[2] = "(" + item[2] + ") and (" + mediaQuery + ")";
}
list.push(item);
}
}
};
return list;
};
/***/ }),
/* 4 */
/***/ (function(module, exports, __webpack_require__) {
/*
MIT License http://www.opensource.org/licenses/mit-license.php
Author Tobias Koppers @sokra
*/
var stylesInDom = {},
memoize = function(fn) {
var memo;
return function () {
if (typeof memo === "undefined") memo = fn.apply(this, arguments);
return memo;
};
},
isOldIE = memoize(function() {
return /msie [6-9]\b/.test(self.navigator.userAgent.toLowerCase());
}),
getHeadElement = memoize(function () {
return document.head || document.getElementsByTagName("head")[0];
}),
singletonElement = null,
singletonCounter = 0,
styleElementsInsertedAtTop = [];
module.exports = function(list, options) {
if(false) {
if(typeof document !== "object") throw new Error("The style-loader cannot be used in a non-browser environment");
}
options = options || {};
// Force single-tag solution on IE6-9, which has a hard limit on the # of <style>
// tags it will allow on a page
if (typeof options.singleton === "undefined") options.singleton = isOldIE();
// By default, add <style> tags to the bottom of <head>.
if (typeof options.insertAt === "undefined") options.insertAt = "bottom";
var styles = listToStyles(list);
addStylesToDom(styles, options);
return function update(newList) {
var mayRemove = [];
for(var i = 0; i < styles.length; i++) {
var item = styles[i];
var domStyle = stylesInDom[item.id];
domStyle.refs--;
mayRemove.push(domStyle);
}
if(newList) {
var newStyles = listToStyles(newList);
addStylesToDom(newStyles, options);
}
for(var i = 0; i < mayRemove.length; i++) {
var domStyle = mayRemove[i];
if(domStyle.refs === 0) {
for(var j = 0; j < domStyle.parts.length; j++)
domStyle.parts[j]();
delete stylesInDom[domStyle.id];
}
}
};
}
function addStylesToDom(styles, options) {
for(var i = 0; i < styles.length; i++) {
var item = styles[i];
var domStyle = stylesInDom[item.id];
if(domStyle) {
domStyle.refs++;
for(var j = 0; j < domStyle.parts.length; j++) {
domStyle.parts[j](item.parts[j]);
}
for(; j < item.parts.length; j++) {
domStyle.parts.push(addStyle(item.parts[j], options));
}
} else {
var parts = [];
for(var j = 0; j < item.parts.length; j++) {
parts.push(addStyle(item.parts[j], options));
}
stylesInDom[item.id] = {id: item.id, refs: 1, parts: parts};
}
}
}
function listToStyles(list) {
var styles = [];
var newStyles = {};
for(var i = 0; i < list.length; i++) {
var item = list[i];
var id = item[0];
var css = item[1];
var media = item[2];
var sourceMap = item[3];
var part = {css: css, media: media, sourceMap: sourceMap};
if(!newStyles[id])
styles.push(newStyles[id] = {id: id, parts: [part]});
else
newStyles[id].parts.push(part);
}
return styles;
}
function insertStyleElement(options, styleElement) {
var head = getHeadElement();
var lastStyleElementInsertedAtTop = styleElementsInsertedAtTop[styleElementsInsertedAtTop.length - 1];
if (options.insertAt === "top") {
if(!lastStyleElementInsertedAtTop) {
head.insertBefore(styleElement, head.firstChild);
} else if(lastStyleElementInsertedAtTop.nextSibling) {
head.insertBefore(styleElement, lastStyleElementInsertedAtTop.nextSibling);
} else {
head.appendChild(styleElement);
}
styleElementsInsertedAtTop.push(styleElement);
} else if (options.insertAt === "bottom") {
head.appendChild(styleElement);
} else {
throw new Error("Invalid value for parameter 'insertAt'. Must be 'top' or 'bottom'.");
}
}
function removeStyleElement(styleElement) {
styleElement.parentNode.removeChild(styleElement);
var idx = styleElementsInsertedAtTop.indexOf(styleElement);
if(idx >= 0) {
styleElementsInsertedAtTop.splice(idx, 1);
}
}
function createStyleElement(options) {
var styleElement = document.createElement("style");
styleElement.type = "text/css";
insertStyleElement(options, styleElement);
return styleElement;
}
function createLinkElement(options) {
var linkElement = document.createElement("link");
linkElement.rel = "stylesheet";
insertStyleElement(options, linkElement);
return linkElement;
}
function addStyle(obj, options) {
var styleElement, update, remove;
if (options.singleton) {
var styleIndex = singletonCounter++;
styleElement = singletonElement || (singletonElement = createStyleElement(options));
update = applyToSingletonTag.bind(null, styleElement, styleIndex, false);
remove = applyToSingletonTag.bind(null, styleElement, styleIndex, true);
} else if(obj.sourceMap &&
typeof URL === "function" &&
typeof URL.createObjectURL === "function" &&
typeof URL.revokeObjectURL === "function" &&
typeof Blob === "function" &&
typeof btoa === "function") {
styleElement = createLinkElement(options);
update = updateLink.bind(null, styleElement);
remove = function() {
removeStyleElement(styleElement);
if(styleElement.href)
URL.revokeObjectURL(styleElement.href);
};
} else {
styleElement = createStyleElement(options);
update = applyToTag.bind(null, styleElement);
remove = function() {
removeStyleElement(styleElement);
};
}
update(obj);
return function updateStyle(newObj) {
if(newObj) {
if(newObj.css === obj.css && newObj.media === obj.media && newObj.sourceMap === obj.sourceMap)
return;
update(obj = newObj);
} else {
remove();
}
};
}
var replaceText = (function () {
var textStore = [];
return function (index, replacement) {
textStore[index] = replacement;
return textStore.filter(Boolean).join('\n');
};
})();
function applyToSingletonTag(styleElement, index, remove, obj) {
var css = remove ? "" : obj.css;
if (styleElement.styleSheet) {
styleElement.styleSheet.cssText = replaceText(index, css);
} else {
var cssNode = document.createTextNode(css);
var childNodes = styleElement.childNodes;
if (childNodes[index]) styleElement.removeChild(childNodes[index]);
if (childNodes.length) {
styleElement.insertBefore(cssNode, childNodes[index]);
} else {
styleElement.appendChild(cssNode);
}
}
}
function applyToTag(styleElement, obj) {
var css = obj.css;
var media = obj.media;
if(media) {
styleElement.setAttribute("media", media)
}
if(styleElement.styleSheet) {
styleElement.styleSheet.cssText = css;
} else {
while(styleElement.firstChild) {
styleElement.removeChild(styleElement.firstChild);
}
styleElement.appendChild(document.createTextNode(css));
}
}
function updateLink(linkElement, obj) {
var css = obj.css;
var sourceMap = obj.sourceMap;
if(sourceMap) {
// http://stackoverflow.com/a/26603875
css += "\n/*# sourceMappingURL=data:application/json;base64," + btoa(unescape(encodeURIComponent(JSON.stringify(sourceMap)))) + " */";
}
var blob = new Blob([css], { type: "text/css" });
var oldSrc = linkElement.href;
linkElement.href = URL.createObjectURL(blob);
if(oldSrc)
URL.revokeObjectURL(oldSrc);
}
/***/ }),
/* 5 */
/***/ (function(module, exports, __webpack_require__) {
'use strict';
Object.defineProperty(exports, "__esModule", {
value: true
});
var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function (obj) { return typeof obj; } : function (obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; };
var _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; };
var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }();
var _react = __webpack_require__(6);
var _react2 = _interopRequireDefault(_react);
var _propTypes = __webpack_require__(7);
var _propTypes2 = _interopRequireDefault(_propTypes);
var _lineHeight2 = __webpack_require__(17);
var _lineHeight3 = _interopRequireDefault(_lineHeight2);
var _reactMotion = __webpack_require__(19);
var _utils = __webpack_require__(34);
var _Scrollbar = __webpack_require__(35);
var _Scrollbar2 = _interopRequireDefault(_Scrollbar);
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; }
function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; }
var eventTypes = {
wheel: 'wheel',
api: 'api',
touch: 'touch',
touchEnd: 'touchEnd',
mousemove: 'mousemove',
keyPress: 'keypress'
};
var ScrollArea = function (_React$Component) {
_inherits(ScrollArea, _React$Component);
function ScrollArea(props) {
_classCallCheck(this, ScrollArea);
var _this = _possibleConstructorReturn(this, (ScrollArea.__proto__ || Object.getPrototypeOf(ScrollArea)).call(this, props));
_this.state = {
topPosition: 0,
leftPosition: 0,
realHeight: 0,
containerHeight: 0,
realWidth: 0,
containerWidth: 0
};
_this.scrollArea = {
refresh: function refresh() {
_this.setSizesToState();
},
scrollTop: function scrollTop() {
_this.scrollTop();
},
scrollBottom: function scrollBottom() {
_this.scrollBottom();
},
scrollYTo: function scrollYTo(position) {
_this.scrollYTo(position);
},
scrollLeft: function scrollLeft() {
_this.scrollLeft();
},
scrollRight: function scrollRight() {
_this.scrollRight();
},
scrollXTo: function scrollXTo(position) {
_this.scrollXTo(position);
}
};
_this.evntsPreviousValues = {
clientX: 0,
clientY: 0,
deltaX: 0,
deltaY: 0
};
_this.bindedHandleWindowResize = _this.handleWindowResize.bind(_this);
return _this;
}
_createClass(ScrollArea, [{
key: 'getChildContext',
value: function getChildContext() {
return {
scrollArea: this.scrollArea
};
}
}, {
key: 'componentDidMount',
value: function componentDidMount() {
if (this.props.contentWindow) {
this.props.contentWindow.addEventListener("resize", this.bindedHandleWindowResize);
}
this.lineHeightPx = (0, _lineHeight3.default)((0, _utils.findDOMNode)(this.content));
this.setSizesToState();
}
}, {
key: 'componentWillUnmount',
value: function componentWillUnmount() {
if (this.props.contentWindow) {
this.props.contentWindow.removeEventListener("resize", this.bindedHandleWindowResize);
}
}
}, {
key: 'componentDidUpdate',
value: function componentDidUpdate() {
this.setSizesToState();
}
}, {
key: 'render',
value: function render() {
var _this2 = this;
var _props = this.props,
children = _props.children,
className = _props.className,
contentClassName = _props.contentClassName,
ownerDocument = _props.ownerDocument;
var withMotion = this.props.smoothScrolling && (this.state.eventType === eventTypes.wheel || this.state.eventType === eventTypes.api || this.state.eventType === eventTypes.touchEnd || this.state.eventType === eventTypes.keyPress);
var scrollbarY = this.canScrollY() ? _react2.default.createElement(_Scrollbar2.default, {
ownerDocument: ownerDocument,
realSize: this.state.realHeight,
containerSize: this.state.containerHeight,
position: this.state.topPosition,
onMove: this.handleScrollbarMove.bind(this),
onPositionChange: this.handleScrollbarYPositionChange.bind(this),
containerStyle: this.props.verticalContainerStyle,
scrollbarStyle: this.props.verticalScrollbarStyle,
smoothScrolling: withMotion,
minScrollSize: this.props.minScrollSize,
onFocus: this.focusContent.bind(this),
type: 'vertical' }) : null;
var scrollbarX = this.canScrollX() ? _react2.default.createElement(_Scrollbar2.default, {
ownerDocument: ownerDocument,
realSize: this.state.realWidth,
containerSize: this.state.containerWidth,
position: this.state.leftPosition,
onMove: this.handleScrollbarMove.bind(this),
onPositionChange: this.handleScrollbarXPositionChange.bind(this),
containerStyle: this.props.horizontalContainerStyle,
scrollbarStyle: this.props.horizontalScrollbarStyle,
smoothScrolling: withMotion,
minScrollSize: this.props.minScrollSize,
onFocus: this.focusContent.bind(this),
type: 'horizontal' }) : null;
if (typeof children === 'function') {
(0, _utils.warnAboutFunctionChild)();
children = children();
} else {
(0, _utils.warnAboutElementChild)();
}
var classes = 'scrollarea ' + (className || '');
var contentClasses = 'scrollarea-content ' + (contentClassName || '');
var contentStyle = {
marginTop: -this.state.topPosition,
marginLeft: -this.state.leftPosition
};
var springifiedContentStyle = withMotion ? (0, _utils.modifyObjValues)(contentStyle, function (x) {
return (0, _reactMotion.spring)(x);
}) : contentStyle;
return _react2.default.createElement(
_reactMotion.Motion,
{ style: springifiedContentStyle },
function (style) {
return _react2.default.createElement(
'div',
{
ref: function ref(x) {
return _this2.wrapper = x;
},
className: classes,
style: _this2.props.style,
onWheel: _this2.handleWheel.bind(_this2)
},
_react2.default.createElement(
'div',
{
ref: function ref(x) {
return _this2.content = x;
},
style: _extends({}, _this2.props.contentStyle, style),
className: contentClasses,
onTouchStart: _this2.handleTouchStart.bind(_this2),
onTouchMove: _this2.handleTouchMove.bind(_this2),
onTouchEnd: _this2.handleTouchEnd.bind(_this2),
onKeyDown: _this2.handleKeyDown.bind(_this2),
tabIndex: _this2.props.focusableTabIndex
},
children
),
scrollbarY,
scrollbarX
);
}
);
}
}, {
key: 'setStateFromEvent',
value: function setStateFromEvent(newState, eventType) {
if (this.props.onScroll) {
this.props.onScroll(newState);
}
this.setState(_extends({}, newState, { eventType: eventType }));
}
}, {
key: 'handleTouchStart',
value: function handleTouchStart(e) {
var touches = e.touches;
if (touches.length === 1) {
var _touches$ = touches[0],
clientX = _touches$.clientX,
clientY = _touches$.clientY;
this.eventPreviousValues = _extends({}, this.eventPreviousValues, {
clientY: clientY,
clientX: clientX,
timestamp: Date.now()
});
}
}
}, {
key: 'handleTouchMove',
value: function handleTouchMove(e) {
e.preventDefault();
e.stopPropagation();
var touches = e.touches;
if (touches.length === 1) {
var _touches$2 = touches[0],
clientX = _touches$2.clientX,
clientY = _touches$2.clientY;
var deltaY = this.eventPreviousValues.clientY - clientY;
var deltaX = this.eventPreviousValues.clientX - clientX;
this.eventPreviousValues = _extends({}, this.eventPreviousValues, {
deltaY: deltaY,
deltaX: deltaX,
clientY: clientY,
clientX: clientX,
timestamp: Date.now()
});
this.setStateFromEvent(this.composeNewState(-deltaX, -deltaY));
}
}
}, {
key: 'handleTouchEnd',
value: function handleTouchEnd(e) {
var _eventPreviousValues = this.eventPreviousValues,
deltaX = _eventPreviousValues.deltaX,
deltaY = _eventPreviousValues.deltaY,
timestamp = _eventPreviousValues.timestamp;
if (typeof deltaX === 'undefined') deltaX = 0;
if (typeof deltaY === 'undefined') deltaY = 0;
if (Date.now() - timestamp < 200) {
this.setStateFromEvent(this.composeNewState(-deltaX * 10, -deltaY * 10), eventTypes.touchEnd);
}
this.eventPreviousValues = _extends({}, this.eventPreviousValues, {
deltaY: 0,
deltaX: 0
});
}
}, {
key: 'handleScrollbarMove',
value: function handleScrollbarMove(deltaY, deltaX) {
this.setStateFromEvent(this.composeNewState(deltaX, deltaY));
}
}, {
key: 'handleScrollbarXPositionChange',
value: function handleScrollbarXPositionChange(position) {
this.scrollXTo(position);
}
}, {
key: 'handleScrollbarYPositionChange',
value: function handleScrollbarYPositionChange(position) {
this.scrollYTo(position);
}
}, {
key: 'handleWheel',
value: function handleWheel(e) {
var deltaY = e.deltaY;
var deltaX = e.deltaX;
if (this.props.swapWheelAxes) {
var _ref = [deltaX, deltaY];
deltaY = _ref[0];
deltaX = _ref[1];
}
/*
* WheelEvent.deltaMode can differ between browsers and must be normalized
* e.deltaMode === 0: The delta values are specified in pixels
* e.deltaMode === 1: The delta values are specified in lines
* https://developer.mozilla.org/en-US/docs/Web/API/WheelEvent/deltaMode
*/
if (e.deltaMode === 1) {
deltaY = deltaY * this.lineHeightPx;
deltaX = deltaX * this.lineHeightPx;
}
deltaY = deltaY * this.props.speed;
deltaX = deltaX * this.props.speed;
var newState = this.composeNewState(-deltaX, -deltaY);
if (newState.topPosition && this.state.topPosition !== newState.topPosition || newState.leftPosition && this.state.leftPosition !== newState.leftPosition || this.props.stopScrollPropagation) {
e.preventDefault();
e.stopPropagation();
}
this.setStateFromEvent(newState, eventTypes.wheel);
this.focusContent();
}
}, {
key: 'handleKeyDown',
value: function handleKeyDown(e) {
// only handle if scroll area is in focus
if (e.target.tagName.toLowerCase() !== 'input') {
var deltaY = 0;
var deltaX = 0;
var _lineHeight = this.lineHeightPx ? this.lineHeightPx : 10;
switch (e.keyCode) {
case 33:
// page up
deltaY = this.state.containerHeight - _lineHeight;
break;
case 34:
// page down
deltaY = -this.state.containerHeight + _lineHeight;
break;
case 37:
// left
deltaX = _lineHeight;
break;
case 38:
// up
deltaY = _lineHeight;
break;
case 39:
// right
deltaX = -_lineHeight;
break;
case 40:
// down
deltaY = -_lineHeight;
break;
}
// only compose new state if key code matches those above
if (deltaY !== 0 || deltaX !== 0) {
var newState = this.composeNewState(deltaX, deltaY);
e.preventDefault();
e.stopPropagation();
this.setStateFromEvent(newState, eventTypes.keyPress);
}
}
}
}, {
key: 'handleWindowResize',
value: function handleWindowResize() {
var newState = this.computeSizes();
newState = this.getModifiedPositionsIfNeeded(newState);
this.setStateFromEvent(newState);
}
}, {
key: 'composeNewState',
value: function composeNewState(deltaX, deltaY) {
var newState = this.computeSizes();
if (this.canScrollY(newState)) {
newState.topPosition = this.computeTopPosition(deltaY, newState);
} else {
newState.topPosition = 0;
}
if (this.canScrollX(newState)) {
newState.leftPosition = this.computeLeftPosition(deltaX, newState);
}
return newState;
}
}, {
key: 'computeTopPosition',
value: function computeTopPosition(deltaY, sizes) {
var newTopPosition = this.state.topPosition - deltaY;
return this.normalizeTopPosition(newTopPosition, sizes);
}
}, {
key: 'computeLeftPosition',
value: function computeLeftPosition(deltaX, sizes) {
var newLeftPosition = this.state.leftPosition - deltaX;
return this.normalizeLeftPosition(newLeftPosition, sizes);
}
}, {
key: 'normalizeTopPosition',
value: function normalizeTopPosition(newTopPosition, sizes) {
if (newTopPosition > sizes.realHeight - sizes.containerHeight) {
newTopPosition = sizes.realHeight - sizes.containerHeight;
}
if (newTopPosition < 0) {
newTopPosition = 0;
}
return newTopPosition;
}
}, {
key: 'normalizeLeftPosition',
value: function normalizeLeftPosition(newLeftPosition, sizes) {
if (newLeftPosition > sizes.realWidth - sizes.containerWidth) {
newLeftPosition = sizes.realWidth - sizes.containerWidth;
} else if (newLeftPosition < 0) {
newLeftPosition = 0;
}
return newLeftPosition;
}
}, {
key: 'computeSizes',
value: function computeSizes() {
var realHeight = this.content.offsetHeight;
var containerHeight = this.wrapper.offsetHeight;
var realWidth = this.content.offsetWidth;
var containerWidth = this.wrapper.offsetWidth;
return {
realHeight: realHeight,
containerHeight: containerHeight,
realWidth: realWidth,
containerWidth: containerWidth
};
}
}, {
key: 'setSizesToState',
value: function setSizesToState() {
var sizes = this.computeSizes();
if (sizes.realHeight !== this.state.realHeight || sizes.realWidth !== this.state.realWidth) {
this.setStateFromEvent(this.getModifiedPositionsIfNeeded(sizes));
}
}
}, {
key: 'scrollTop',
value: function scrollTop() {
this.scrollYTo(0);
}
}, {
key: 'scrollBottom',
value: function scrollBottom() {
this.scrollYTo(this.state.realHeight - this.state.containerHeight);
}
}, {
key: 'scrollLeft',
value: function scrollLeft() {
this.scrollXTo(0);
}
}, {
key: 'scrollRight',
value: function scrollRight() {
this.scrollXTo(this.state.realWidth - this.state.containerWidth);
}
}, {
key: 'scrollYTo',
value: function scrollYTo(topPosition) {
if (this.canScrollY()) {
var position = this.normalizeTopPosition(topPosition, this.computeSizes());
this.setStateFromEvent({ topPosition: position }, eventTypes.api);
}
}
}, {
key: 'scrollXTo',
value: function scrollXTo(leftPosition) {
if (this.canScrollX()) {
var position = this.normalizeLeftPosition(leftPosition, this.computeSizes());
this.setStateFromEvent({ leftPosition: position }, eventTypes.api);
}
}
}, {
key: 'canScrollY',
value: function canScrollY() {
var state = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : this.state;
var scrollableY = state.realHeight > state.containerHeight;
return scrollableY && this.props.vertical;
}
}, {
key: 'canScrollX',
value: function canScrollX() {
var state = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : this.state;
var scrollableX = state.realWidth > state.containerWidth;
return scrollableX && this.props.horizontal;
}
}, {
key: 'getModifiedPositionsIfNeeded',
value: function getModifiedPositionsIfNeeded(newState) {
var bottomPosition = newState.realHeight - newState.containerHeight;
if (this.state.topPosition >= bottomPosition) {
newState.topPosition = this.canScrollY(newState) ? (0, _utils.positiveOrZero)(bottomPosition) : 0;
}
var rightPosition = newState.realWidth - newState.containerWidth;
if (this.state.leftPosition >= rightPosition) {
newState.leftPosition = this.canScrollX(newState) ? (0, _utils.positiveOrZero)(rightPosition) : 0;
}
return newState;
}
}, {
key: 'focusContent',
value: function focusContent() {
if (this.content) {
(0, _utils.findDOMNode)(this.content).focus();
}
}
}]);
return ScrollArea;
}(_react2.default.Component);
exports.default = ScrollArea;
ScrollArea.childContextTypes = {
scrollArea: _propTypes2.default.object
};
ScrollArea.propTypes = {
className: _propTypes2.default.string,
style: _propTypes2.default.object,
speed: _propTypes2.default.number,
contentClassName: _propTypes2.default.string,
contentStyle: _propTypes2.default.object,
vertical: _propTypes2.default.bool,
verticalContainerStyle: _propTypes2.default.object,
verticalScrollbarStyle: _propTypes2.default.object,
horizontal: _propTypes2.default.bool,
horizontalContainerStyle: _propTypes2.default.object,
horizontalScrollbarStyle: _propTypes2.default.object,
onScroll: _propTypes2.default.func,
contentWindow: _propTypes2.default.any,
ownerDocument: _propTypes2.default.any,
smoothScrolling: _propTypes2.default.bool,
minScrollSize: _propTypes2.default.number,
swapWheelAxes: _propTypes2.default.bool,
stopScrollPropagation: _propTypes2.default.bool,
focusableTabIndex: _propTypes2.default.number
};
ScrollArea.defaultProps = {
speed: 1,
vertical: true,
horizontal: true,
smoothScrolling: false,
swapWheelAxes: false,
contentWindow: (typeof window === 'undefined' ? 'undefined' : _typeof(window)) === "object" ? window : undefined,
ownerDocument: (typeof document === 'undefined' ? 'undefined' : _typeof(document)) === "object" ? document : undefined,
focusableTabIndex: 1
};
/***/ }),
/* 6 */
/***/ (function(module, exports) {
module.exports = __WEBPACK_EXTERNAL_MODULE_6__;
/***/ }),
/* 7 */
/***/ (function(module, exports, __webpack_require__) {
/* WEBPACK VAR INJECTION */(function(process) {/**
* Copyright (c) 2013-present, Facebook, Inc.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
if (process.env.NODE_ENV !== 'production') {
var REACT_ELEMENT_TYPE = (typeof Symbol === 'function' &&
Symbol.for &&
Symbol.for('react.element')) ||
0xeac7;
var isValidElement = function(object) {
return typeof object === 'object' &&
object !== null &&
object.$$typeof === REACT_ELEMENT_TYPE;
};
// By explicitly using `prop-types` you are opting into new development behavior.
// http://fb.me/prop-types-in-prod
var throwOnDirectAccess = true;
module.exports = __webpack_require__(9)(isValidElement, throwOnDirectAccess);
} else {
// By explicitly using `prop-types` you are opting into new production behavior.
// http://fb.me/prop-types-in-prod
module.exports = __webpack_require__(16)();
}
/* WEBPACK VAR INJECTION */}.call(exports, __webpack_require__(8)))
/***/ }),
/* 8 */
/***/ (function(module, exports) {
// shim for using process in browser
var process = module.exports = {};
// cached from whatever global is present so that test runners that stub it
// don't break things. But we need to wrap it in a try catch in case it is
// wrapped in strict mode code which doesn't define any globals. It's inside a
// function because try/catches deoptimize in certain engines.
var cachedSetTimeout;
var cachedClearTimeout;
function defaultSetTimout() {
throw new Error('setTimeout has not been defined');
}
function defaultClearTimeout () {
throw new Error('clearTimeout has not been defined');
}
(function () {
try {
if (typeof setTimeout === 'function') {
cachedSetTimeout = setTimeout;
} else {
cachedSetTimeout = defaultSetTimout;
}
} catch (e) {
cachedSetTimeout = defaultSetTimout;
}
try {
if (typeof clearTimeout === 'function') {
cachedClearTimeout = clearTimeout;
} else {
cachedClearTimeout = defaultClearTimeout;
}
} catch (e) {
cachedClearTimeout = defaultClearTimeout;
}
} ())
function runTimeout(fun) {
if (cachedSetTimeout === setTimeout) {
//normal enviroments in sane situations
return setTimeout(fun, 0);
}
// if setTimeout wasn't available but was latter defined
if ((cachedSetTimeout === defaultSetTimout || !cachedSetTimeout) && setTimeout) {
cachedSetTimeout = setTimeout;
return setTimeout(fun, 0);
}
try {
// when when somebody has screwed with setTimeout but no I.E. maddness
return cachedSetTimeout(fun, 0);
} catch(e){
try {
// When we are in I.E. but the script has been evaled so I.E. doesn't trust the global object when called normally
return cachedSetTimeout.call(null, fun, 0);
} catch(e){
// same as above but when it's a version of I.E. that must have the global object for 'this', hopfully our context correct otherwise it will throw a global error
return cachedSetTimeout.call(this, fun, 0);
}
}
}
function runClearTimeout(marker) {
if (cachedClearTimeout === clearTimeout) {
//normal enviroments in sane situations
return clearTimeout(marker);
}
// if clearTimeout wasn't available but was latter defined
if ((cachedClearTimeout === defaultClearTimeout || !cachedClearTimeout) && clearTimeout) {
cachedClearTimeout = clearTimeout;
return clearTimeout(marker);
}
try {
// when when somebody has screwed with setTimeout but no I.E. maddness
return cachedClearTimeout(marker);
} catch (e){
try {
// When we are in I.E. but the script has been evaled so I.E. doesn't trust the global object when called normally
return cachedClearTimeout.call(null, marker);
} catch (e){
// same as above but when it's a version of I.E. that must have the global object for 'this', hopfully our context correct otherwise it will throw a global error.
// Some versions of I.E. have different rules for clearTimeout vs setTimeout
return cachedClearTimeout.call(this, marker);
}
}
}
var queue = [];
var draining = false;
var currentQueue;
var queueIndex = -1;
function cleanUpNextTick() {
if (!draining || !currentQueue) {
return;
}
draining = false;
if (currentQueue.length) {
queue = currentQueue.concat(queue);
} else {
queueIndex = -1;
}
if (queue.length) {
drainQueue();
}
}
function drainQueue() {
if (draining) {
return;
}
var timeout = runTimeout(cleanUpNextTick);
draining = true;
var len = queue.length;
while(len) {
currentQueue = queue;
queue = [];
while (++queueIndex < len) {
if (currentQueue) {
currentQueue[queueIndex].run();
}
}
queueIndex = -1;
len = queue.length;
}
currentQueue = null;
draining = false;
runClearTimeout(timeout);
}
process.nextTick = function (fun) {
var args = new Array(arguments.length - 1);
if (arguments.length > 1) {
for (var i = 1; i < arguments.length; i++) {
args[i - 1] = arguments[i];
}
}
queue.push(new Item(fun, args));
if (queue.length === 1 && !draining) {
runTimeout(drainQueue);
}
};
// v8 likes predictible objects
function Item(fun, array) {
this.fun = fun;
this.array = array;
}
Item.prototype.run = function () {
this.fun.apply(null, this.array);
};
process.title = 'browser';
process.browser = true;
process.env = {};
process.argv = [];
process.version = ''; // empty string to avoid regexp issues
process.versions = {};
function noop() {}
process.on = noop;
process.addListener = noop;
process.once = noop;
process.off = noop;
process.removeListener = noop;
process.removeAllListeners = noop;
process.emit = noop;
process.prependListener = noop;
process.prependOnceListener = noop;
process.listeners = function (name) { return [] }
process.binding = function (name) {
throw new Error('process.binding is not supported');
};
process.cwd = function () { return '/' };
process.chdir = function (dir) {
throw new Error('process.chdir is not supported');
};
process.umask = function() { return 0; };
/***/ }),
/* 9 */
/***/ (function(module, exports, __webpack_require__) {
/* WEBPACK VAR INJECTION */(function(process) {/**
* Copyright (c) 2013-present, Facebook, Inc.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
'use strict';
var emptyFunction = __webpack_require__(10);
var invariant = __webpack_require__(11);
var warning = __webpack_require__(12);
var assign = __webpack_require__(13);
var ReactPropTypesSecret = __webpack_require__(14);
var checkPropTypes = __webpack_require__(15);
module.exports = function(isValidElement, throwOnDirectAccess) {
/* global Symbol */
var ITERATOR_SYMBOL = typeof Symbol === 'function' && Symbol.iterator;
var FAUX_ITERATOR_SYMBOL = '@@iterator'; // Before Symbol spec.
/**
* Returns the iterator method function contained on the iterable object.
*
* Be sure to invoke the function with the iterable as context:
*
* var iteratorFn = getIteratorFn(myIterable);
* if (iteratorFn) {
* var iterator = iteratorFn.call(myIterable);
* ...
* }
*
* @param {?object} maybeIterable
* @return {?function}
*/
function getIteratorFn(maybeIterable) {
var iteratorFn = maybeIterable && (ITERATOR_SYMBOL && maybeIterable[ITERATOR_SYMBOL] || maybeIterable[FAUX_ITERATOR_SYMBOL]);
if (typeof iteratorFn === 'function') {
return iteratorFn;
}
}
/**
* Collection of methods that allow declaration and validation of props that are
* supplied to React components. Example usage:
*
* var Props = require('ReactPropTypes');
* var MyArticle = React.createClass({
* propTypes: {
* // An optional string prop named "description".
* description: Props.string,
*
* // A required enum prop named "category".
* category: Props.oneOf(['News','Photos']).isRequired,
*
* // A prop named "dialog" that requires an instance of Dialog.
* dialog: Props.instanceOf(Dialog).isRequired
* },
* render: function() { ... }
* });
*
* A more formal specification of how these methods are used:
*
* type := array|bool|func|object|number|string|oneOf([...])|instanceOf(...)
* decl := ReactPropTypes.{type}(.isRequired)?
*
* Each and every declaration produces a function with the same signature. This
* allows the creation of custom validation functions. For example:
*
* var MyLink = React.createClass({
* propTypes: {
* // An optional string or URI prop named "href".
* href: function(props, propName, componentName) {
* var propValue = props[propName];
* if (propValue != null && typeof propValue !== 'string' &&
* !(propValue instanceof URI)) {
* return new Error(
* 'Expected a string or an URI for ' + propName + ' in ' +
* componentName
* );
* }
* }
* },
* render: function() {...}
* });
*
* @internal
*/
var ANONYMOUS = '<<anonymous>>';
// Important!
// Keep this list in sync with production version in `./factoryWithThrowingShims.js`.
var ReactPropTypes = {
array: createPrimitiveTypeChecker('array'),
bool: createPrimitiveTypeChecker('boolean'),
func: createPrimitiveTypeChecker('function'),
number: createPrimitiveTypeChecker('number'),
object: createPrimitiveTypeChecker('object'),
string: createPrimitiveTypeChecker('string'),
symbol: createPrimitiveTypeChecker('symbol'),
any: createAnyTypeChecker(),
arrayOf: createArrayOfTypeChecker,
element: createElementTypeChecker(),
instanceOf: createInstanceTypeChecker,
node: createNodeChecker(),
objectOf: createObjectOfTypeChecker,
oneOf: createEnumTypeChecker,
oneOfType: createUnionTypeChecker,
shape: createShapeTypeChecker,
exact: createStrictShapeTypeChecker,
};
/**
* inlined Object.is polyfill to avoid requiring consumers ship their own
* https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/is
*/
/*eslint-disable no-self-compare*/
function is(x, y) {
// SameValue algorithm
if (x === y) {
// Steps 1-5, 7-10
// Steps 6.b-6.e: +0 != -0
return x !== 0 || 1 / x === 1 / y;
} else {
// Step 6.a: NaN == NaN
return x !== x && y !== y;
}
}
/*eslint-enable no-self-compare*/
/**
* We use an Error-like object for backward compatibility as people may call
* PropTypes directly and inspect their output. However, we don't use real
* Errors anymore. We don't inspect their stack anyway, and creating them
* is prohibitively expensive if they are created too often, such as what
* happens in oneOfType() for any type before the one that matched.
*/
function PropTypeError(message) {
this.message = message;
this.stack = '';
}
// Make `instanceof Error` still work for returned errors.
PropTypeError.prototype = Error.prototype;
function createChainableTypeChecker(validate) {
if (process.env.NODE_ENV !== 'production') {
var manualPropTypeCallCache = {};
var manualPropTypeWarningCount = 0;
}
function checkType(isRequired, props, propName, componentName, location, propFullName, secret) {
componentName = componentName || ANONYMOUS;
propFullName = propFullName || propName;