UNPKG

react-resizable-box

Version:

<p align="center"><img src ="https://github.com/bokuweb/react-resizable-box/blob/master/logo.png?raw=true" /></p>

770 lines (651 loc) 22.3 kB
'use strict'; var React = require('react'); var React__default = React['default']; var babelHelpers = {}; var asyncGenerator = function () { function AwaitValue(value) { this.value = value; } function AsyncGenerator(gen) { var front, back; function send(key, arg) { return new Promise(function (resolve, reject) { var request = { key: key, arg: arg, resolve: resolve, reject: reject, next: null }; if (back) { back = back.next = request; } else { front = back = request; resume(key, arg); } }); } function resume(key, arg) { try { var result = gen[key](arg); var value = result.value; if (value instanceof AwaitValue) { Promise.resolve(value.value).then(function (arg) { resume("next", arg); }, function (arg) { resume("throw", arg); }); } else { settle(result.done ? "return" : "normal", result.value); } } catch (err) { settle("throw", err); } } function settle(type, value) { switch (type) { case "return": front.resolve({ value: value, done: true }); break; case "throw": front.reject(value); break; default: front.resolve({ value: value, done: false }); break; } front = front.next; if (front) { resume(front.key, front.arg); } else { back = null; } } this._invoke = send; if (typeof gen.return !== "function") { this.return = undefined; } } if (typeof Symbol === "function" && Symbol.asyncIterator) { AsyncGenerator.prototype[Symbol.asyncIterator] = function () { return this; }; } AsyncGenerator.prototype.next = function (arg) { return this._invoke("next", arg); }; AsyncGenerator.prototype.throw = function (arg) { return this._invoke("throw", arg); }; AsyncGenerator.prototype.return = function (arg) { return this._invoke("return", arg); }; return { wrap: function (fn) { return function () { return new AsyncGenerator(fn.apply(this, arguments)); }; }, await: function (value) { return new AwaitValue(value); } }; }(); var classCallCheck = function (instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }; 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 _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 inherits = function (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 possibleConstructorReturn = function (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; }; babelHelpers; var styles = { base: { position: 'absolute' }, top: { width: '100%', height: '10px', top: '-5px', left: '0px', cursor: 'row-resize' }, right: { width: '10px', height: '100%', top: '0px', right: '-5px', cursor: 'col-resize' }, bottom: { width: '100%', height: '10px', bottom: '-5px', left: '0px', cursor: 'row-resize' }, left: { width: '10px', height: '100%', top: '0px', left: '-5px', cursor: 'col-resize' }, topRight: { width: '20px', height: '20px', position: 'absolute', right: '-10px', top: '-10px', cursor: 'ne-resize' }, bottomRight: { width: '20px', height: '20px', position: 'absolute', right: '-10px', bottom: '-10px', cursor: 'se-resize' }, bottomLeft: { width: '20px', height: '20px', position: 'absolute', left: '-10px', bottom: '-10px', cursor: 'sw-resize' }, topLeft: { width: '20px', height: '20px', position: 'absolute', left: '-10px', top: '-10px', cursor: 'nw-resize' } }; var Resizer = (function (props) { return React.createElement('div', { className: props.className, style: _extends({}, styles.base, styles[props.direction], props.replaceStyles || {}), onMouseDown: function onMouseDown(e) { props.onResizeStart(e, props.direction); }, onTouchStart: function onTouchStart(e) { props.onResizeStart(e, props.direction); } }); }); var userSelectNone = { userSelect: 'none', MozUserSelect: 'none', WebkitUserSelect: 'none', MsUserSelect: 'none' }; var userSelectAuto = { userSelect: 'auto', MozUserSelect: 'auto', WebkitUserSelect: 'auto', MsUserSelect: 'auto' }; var clamp = function clamp(n, min, max) { return Math.max(Math.min(n, max), min); }; var snap = function snap(n, size) { return Math.round(n / size) * size; }; var baseSizeId = 0; var Resizable = function (_Component) { inherits(Resizable, _Component); function Resizable(props) { classCallCheck(this, Resizable); var _this = possibleConstructorReturn(this, (Resizable.__proto__ || Object.getPrototypeOf(Resizable)).call(this, props)); var width = props.width, height = props.height; _this.state = { isResizing: false, width: typeof width === 'undefined' ? 'auto' : width, height: typeof height === 'undefined' ? 'auto' : height, direction: 'right', original: { x: 0, y: 0, width: 0, height: 0 } }; _this.onResizeStart = _this.onResizeStart.bind(_this); _this.onMouseMove = _this.onMouseMove.bind(_this); _this.onMouseUp = _this.onMouseUp.bind(_this); _this.baseSizeId = '__resizable' + baseSizeId; baseSizeId += 1; if (typeof window !== 'undefined') { window.addEventListener('mouseup', _this.onMouseUp); window.addEventListener('mousemove', _this.onMouseMove); window.addEventListener('touchmove', _this.onMouseMove); window.addEventListener('touchend', _this.onMouseUp); } return _this; } createClass(Resizable, [{ key: 'getParentSize', value: function getParentSize() { var base = document.getElementById(this.baseSizeId); if (!base) return { width: window.innerWidth, height: window.innerHeight }; return { width: base.offsetWidth, height: base.offsetHeight }; } }, { key: 'componentDidMount', value: function componentDidMount() { var size = this.size; // const debounced = debounce(() => { // this.setState(this.style); // }, 0); // const ro = new ResizeObserver(debounced); // ro.observe(this.parentNode); // If props.width or height is not defined, set default size when mounted. this.setState({ width: this.state.width || size.width, height: this.state.height || size.height }); var element = document.createElement('div'); element.id = this.baseSizeId; element.style.width = '100%'; element.style.height = '100%'; element.style.position = 'relative'; element.style.left = '-99999px'; var parent = this.parentNode; if (!(parent instanceof HTMLElement)) return; parent.appendChild(element); } }, { key: 'componentWillReceiveProps', value: function componentWillReceiveProps(_ref) { var width = _ref.width, height = _ref.height; if (width !== this.props.width) { this.setState({ width: width }); } if (height !== this.props.height) { this.setState({ height: height }); } } }, { key: 'componentWillUnmount', value: function componentWillUnmount() { if (typeof window !== 'undefined') { window.removeEventListener('mouseup', this.onMouseUp); window.removeEventListener('mousemove', this.onMouseMove); window.removeEventListener('touchmove', this.onMouseMove); window.removeEventListener('touchend', this.onMouseUp); var parent = this.parentNode; var base = document.getElementById(this.baseSizeId); if (!base) return; if (!(parent instanceof HTMLElement)) return; parent.removeChild(base); } } }, { key: 'onResizeStart', value: function onResizeStart(event, direction) { var clientX = 0; var clientY = 0; if (event.nativeEvent instanceof MouseEvent) { clientX = event.nativeEvent.clientX; clientY = event.nativeEvent.clientY; } else if (event.nativeEvent instanceof TouchEvent) { clientX = event.nativeEvent.touches[0].clientX; clientY = event.nativeEvent.touches[0].clientY; } if (this.props.onResizeStart) { this.props.onResizeStart(event, direction, this.resizable); } var size = this.size; this.setState({ original: { x: clientX, y: clientY, width: size.width, height: size.height }, isResizing: true, direction: direction }); } }, { key: 'onMouseMove', value: function onMouseMove(event) { if (!this.state.isResizing) return; var clientX = event instanceof MouseEvent ? event.clientX : event.touches[0].clientX; var clientY = event instanceof MouseEvent ? event.clientY : event.touches[0].clientY; var _state = this.state, direction = _state.direction, original = _state.original, width = _state.width, height = _state.height; var lockAspectRatio = this.props.lockAspectRatio; var _props = this.props, maxWidth = _props.maxWidth, maxHeight = _props.maxHeight, minWidth = _props.minWidth, minHeight = _props.minHeight; // TODO: refactor var parentSize = this.getParentSize(); if (maxWidth && typeof maxWidth === 'string' && maxWidth.endsWith('%')) { var _ratio = Number(maxWidth.replace('%', '')) / 100; maxWidth = parentSize.width * _ratio; } if (maxHeight && typeof maxHeight === 'string' && maxHeight.endsWith('%')) { var _ratio2 = Number(maxHeight.replace('%', '')) / 100; maxHeight = parentSize.height * _ratio2; } if (minWidth && typeof minWidth === 'string' && minWidth.endsWith('%')) { var _ratio3 = Number(minWidth.replace('%', '')) / 100; minWidth = parentSize.width * _ratio3; } if (minHeight && typeof minHeight === 'string' && minHeight.endsWith('%')) { var _ratio4 = Number(minHeight.replace('%', '')) / 100; minHeight = parentSize.height * _ratio4; } maxWidth = typeof maxWidth === 'undefined' ? undefined : Number(maxWidth); maxHeight = typeof maxHeight === 'undefined' ? undefined : Number(maxHeight); minWidth = typeof minWidth === 'undefined' ? undefined : Number(minWidth); minHeight = typeof minHeight === 'undefined' ? undefined : Number(minHeight); var ratio = original.height / original.width; var newWidth = original.width; var newHeight = original.height; if (/right/i.test(direction)) { newWidth = original.width + (clientX - original.x); if (lockAspectRatio) newHeight = newWidth * ratio; } if (/left/i.test(direction)) { newWidth = original.width - (clientX - original.x); if (lockAspectRatio) newHeight = newWidth * ratio; } if (/bottom/i.test(direction)) { newHeight = original.height + (clientY - original.y); if (lockAspectRatio) newWidth = newHeight / ratio; } if (/top/i.test(direction)) { newHeight = original.height - (clientY - original.y); if (lockAspectRatio) newWidth = newHeight / ratio; } if (this.props.bounds === 'parent') { var parent = this.parentNode; if (parent instanceof HTMLElement) { var parentRect = parent.getBoundingClientRect(); var parentLeft = parentRect.left; var parentTop = parentRect.top; var _resizable$getBoundin = this.resizable.getBoundingClientRect(), _left = _resizable$getBoundin.left, _top = _resizable$getBoundin.top; var boundWidth = parent.offsetWidth + (parentLeft - _left); var boundHeight = parent.offsetHeight + (parentTop - _top); maxWidth = maxWidth && maxWidth < boundWidth ? maxWidth : boundWidth; maxHeight = maxHeight && maxHeight < boundHeight ? maxHeight : boundHeight; } } else if (this.props.bounds === 'window') { if (typeof window !== 'undefined') { var _resizable$getBoundin2 = this.resizable.getBoundingClientRect(), _left2 = _resizable$getBoundin2.left, _top2 = _resizable$getBoundin2.top; var _boundWidth = window.innerWidth - _left2; var _boundHeight = window.innerHeight - _top2; maxWidth = maxWidth && maxWidth < _boundWidth ? maxWidth : _boundWidth; maxHeight = maxHeight && maxHeight < _boundHeight ? maxHeight : _boundHeight; } } else if (this.props.bounds instanceof HTMLElement) { var targetRect = this.props.bounds.getBoundingClientRect(); var targetLeft = targetRect.left; var targetTop = targetRect.top; var _resizable$getBoundin3 = this.resizable.getBoundingClientRect(), _left3 = _resizable$getBoundin3.left, _top3 = _resizable$getBoundin3.top; if (!(this.props.bounds instanceof HTMLElement)) return; var _boundWidth2 = this.props.bounds.offsetWidth + (targetLeft - _left3); var _boundHeight2 = this.props.bounds.offsetHeight + (targetTop - _top3); maxWidth = maxWidth && maxWidth < _boundWidth2 ? maxWidth : _boundWidth2; maxHeight = maxHeight && maxHeight < _boundHeight2 ? maxHeight : _boundHeight2; } var computedMinWidth = typeof minWidth === 'undefined' || minWidth < 0 ? 0 : minWidth; var computedMaxWidth = typeof maxWidth === 'undefined' || maxWidth < 0 ? newWidth : maxWidth; var computedMinHeight = typeof minHeight === 'undefined' || minHeight < 0 ? 0 : minHeight; var computedMaxHeight = typeof maxHeight === 'undefined' || maxHeight < 0 ? newHeight : maxHeight; if (lockAspectRatio) { var lockedMinWidth = computedMinWidth > computedMinHeight / ratio ? computedMinWidth : computedMinHeight / ratio; var lockedMaxWidth = computedMaxWidth < computedMaxHeight / ratio ? computedMaxWidth : computedMaxHeight / ratio; var lockedMinHeight = computedMinHeight > computedMinWidth * ratio ? computedMinHeight : computedMinWidth * ratio; var lockedMaxHeight = computedMaxHeight < computedMaxWidth * ratio ? computedMaxHeight : computedMaxWidth * ratio; newWidth = clamp(newWidth, lockedMinWidth, lockedMaxWidth); newHeight = clamp(newHeight, lockedMinHeight, lockedMaxHeight); } else { newWidth = clamp(newWidth, computedMinWidth, computedMaxWidth); newHeight = clamp(newHeight, computedMinHeight, computedMaxHeight); } if (this.props.grid) { newWidth = snap(newWidth, this.props.grid[0]); } if (this.props.grid) { newHeight = snap(newHeight, this.props.grid[1]); } var delta = { width: newWidth - original.width, height: newHeight - original.height }; if (width && typeof width === 'string' && width.endsWith('%')) { var percent = newWidth / parentSize.width * 100; newWidth = percent + '%'; } if (height && typeof height === 'string' && height.endsWith('%')) { var _percent = newHeight / parentSize.height * 100; newHeight = _percent + '%'; } this.setState({ width: width !== 'auto' || typeof this.props.width === 'undefined' ? newWidth : 'auto', height: height !== 'auto' || typeof this.props.height === 'undefined' ? newHeight : 'auto' }); if (this.props.onResize) { this.props.onResize(event, direction, this.resizable, delta); } } }, { key: 'onMouseUp', value: function onMouseUp(event) { var _state2 = this.state, isResizing = _state2.isResizing, direction = _state2.direction, original = _state2.original; if (!isResizing) return; var delta = { width: this.size.width - original.width, height: this.size.height - original.height }; if (this.props.onResizeStop) { this.props.onResizeStop(event, direction, this.resizable, delta); } this.setState({ isResizing: false }); } }, { key: 'updateSize', value: function updateSize(size) { this.setState({ width: size.width, height: size.height }); } }, { key: 'renderResizer', value: function renderResizer() { var _this2 = this; var _props2 = this.props, enable = _props2.enable, handleStyles = _props2.handleStyles, handleClasses = _props2.handleClasses, handleWrapperStyle = _props2.handleWrapperStyle, handleWrapperClass = _props2.handleWrapperClass; if (!enable) return null; var resizers = Object.keys(enable).map(function (dir) { if (enable[dir] !== false) { return React__default.createElement(Resizer, { key: dir, direction: dir, onResizeStart: _this2.onResizeStart, replaceStyles: handleStyles && handleStyles[dir], className: handleClasses && handleClasses[dir] }); } return null; }); // #93 Wrap the resize box in span (will not break 100% width/height) return React__default.createElement( 'span', { className: handleWrapperClass, style: handleWrapperStyle }, resizers ); } }, { key: 'render', value: function render() { var _this3 = this; var userSelect = this.state.isResizing ? userSelectNone : userSelectAuto; var _props3 = this.props, style = _props3.style, className = _props3.className; return React__default.createElement( 'div', _extends({ ref: function ref(c) { _this3.resizable = c; }, style: _extends({ position: 'relative' }, userSelect, style, this.style, { maxWidth: this.props.maxWidth, maxHeight: this.props.maxHeight, minWidth: this.props.minWidth, minHeight: this.props.minHeight, boxSizing: 'border-box' }), className: className }, this.props.extendsProps), this.props.children, this.renderResizer() ); } }, { key: 'parentNode', get: function get$$1() { return this.props.parentNode || this.resizable.parentNode; } }, { key: 'size', get: function get$$1() { var width = 0; var height = 0; if (typeof window !== 'undefined') { var _style = window.getComputedStyle(this.resizable, null); width = +_style.getPropertyValue('width').replace('px', ''); height = +_style.getPropertyValue('height').replace('px', ''); } return { width: width, height: height }; } // TODO: rename }, { key: 'style', get: function get$$1() { var _this4 = this; var size = function size(key) { if (typeof _this4.state[key] === 'undefined' || _this4.state[key] === 'auto') return 'auto'; if (_this4.props[key] && _this4.props[key].toString().endsWith('%')) { if (_this4.state[key].toString().endsWith('%')) return _this4.state[key].toString(); var parentSize = _this4.getParentSize(); var value = Number(_this4.state[key].toString().replace('px', '')); var percent = value / parentSize[key] * 100; return percent + '%'; } if (_this4.state[key].toString().endsWith('px')) return _this4.state[key].toString(); if (_this4.state[key].toString().endsWith('%')) return _this4.state[key].toString(); return _this4.state[key] + 'px'; }; return { width: size('width'), height: size('height') }; } }]); return Resizable; }(React.Component); Resizable.defaultProps = { onResizeStart: function onResizeStart() {}, onResize: function onResize() {}, onResizeStop: function onResizeStop() {}, enable: { top: true, right: true, bottom: true, left: true, topRight: true, bottomRight: true, bottomLeft: true, topLeft: true }, style: {}, grid: [1, 1], lockAspectRatio: false }; module.exports = Resizable; //# sourceMappingURL=index.es5.js.map