UNPKG

react-resizable-box

Version:

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

418 lines (374 loc) 15.6 kB
'use strict'; Object.defineProperty(exports, "__esModule", { value: true }); 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 = require('react'); var _react2 = _interopRequireDefault(_react); var _resizer = require('./resizer'); var _resizer2 = _interopRequireDefault(_resizer); 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; } /* eslint-disable import/no-extraneous-dependencies */ /* eslint-disable react/no-unused-prop-types */ /* eslint-disable react/require-default-props */ /* eslint-disable react/jsx-filename-extension */ /* eslint-disable react/sort-comp */ /* eslint-disable jsx-a11y/no-static-element-interactions */ /* eslint-disable max-len */ /* eslint-disable no-bitwise */ /* eslint-disable react/no-did-mount-set-state */ 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 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); 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: 'componentDidMount', value: function componentDidMount() { var size = this.size; // 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 }); } }, { 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); } } }, { 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 _props = this.props, lockAspectRatio = _props.lockAspectRatio, minWidth = _props.minWidth, minHeight = _props.minHeight; var _props2 = this.props, maxWidth = _props2.maxWidth, maxHeight = _props2.maxHeight; 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.resizable.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]); } this.setState({ width: width !== 'auto' ? newWidth : 'auto', height: height !== 'auto' ? newHeight : 'auto' }); var delta = { width: newWidth - original.width, height: newHeight - original.height }; 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: 'setSize', value: function setSize(size) { this.setState({ width: this.state.width || size.width, height: this.state.height || size.height }); } }, { key: 'updateSize', value: function updateSize(size) { this.setState({ width: size.width, height: size.height }); } }, { key: 'renderResizer', value: function renderResizer() { var _this2 = this; var _props3 = this.props, enable = _props3.enable, handlerStyles = _props3.handlerStyles, handlerClasses = _props3.handlerClasses; if (!enable) return null; var content = Object.keys(enable).map(function (dir) { if (enable[dir] !== false) { return _react2.default.createElement(_resizer2.default, { key: dir, direction: dir, onResizeStart: _this2.onResizeStart, replaceStyles: handlerStyles && handlerStyles[dir], className: handlerClasses && handlerClasses[dir] }); } return null; }); var wrapperClass = handlerClasses && handlerClasses['wrapper']; var wrapperStyle = handlerStyles && handlerStyles['wrapper']; // #93 Wrap the resize box in span (will not break 100% width/height) if (wrapperClass || wrapperStyle) { return _react2.default.createElement( 'span', { className: wrapperClass, style: wrapperStyle }, content ); } return content; } }, { key: 'render', value: function render() { var _this3 = this; var userSelect = this.state.isResizing ? userSelectNone : userSelectAuto; var _props4 = this.props, style = _props4.style, className = _props4.className; return _react2.default.createElement( 'div', _extends({ ref: function ref(c) { _this3.resizable = c; }, style: _extends({ position: 'relative' }, userSelect, style, this.style, { boxSizing: 'border-box' }), className: className }, this.props.extendsProps), this.props.children, this.renderResizer() ); } }, { key: 'size', get: function get() { 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 }; } }, { key: 'style', get: function get() { var _this4 = this; var size = function size(key) { if (typeof _this4.state[key] === 'undefined' || _this4.state[key] === 'auto') return 'auto';else if (/px$/.test(_this4.state[key].toString())) return _this4.state[key].toString();else if (/%$/.test(_this4.state[key].toString())) 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 }; exports.default = Resizable;