UNPKG

react-aim

Version:

Determine the cursor aim for triggering mouse events.

299 lines (255 loc) 11.7 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 _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; }; exports.default = function (source) { var spec = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : null; if (spec === null && (typeof source === 'undefined' ? 'undefined' : _typeof(source)) === 'object') { spec = source; source = null; } return function (WrappedComponent) { var _class, _temp; return _temp = _class = function (_Component) { _inherits(_class, _Component); _createClass(_class, [{ key: 'getChildContext', value: function getChildContext() { return { target: this }; } }]); function _class() { _classCallCheck(this, _class); var _this = _possibleConstructorReturn(this, (_class.__proto__ || Object.getPrototypeOf(_class)).call(this)); _this.aiming = false; _this.skippedStops = 0; _this._isOver = false; _this.childrenSources = []; _this._isMounted = false; _this.handleMouseOut = function (e) { if (e.toElement == null && e.relatedTarget == null) { _this.handleMouseLeave(e); } else { _this.handleMouseMove(e); } }; _this.handleMouseMove = function (e) { if (_monitor2.default.mouseOver(e, _this)) _this.handleMouseEnter(e);else _this.handleMouseLeave(e); }; _this.handleMouseEnter = function () { if (!_this._isOver) { _this._isOver = true; _this.trackMouseLeave(); _this.triggerMouseEnter(); } }; _this.handleMouseLeave = function () { if (_this._isOver) { _this._isOver = false; _this.untrackMouseLeave(); _this.triggerMouseLeave(); } }; _this._source = source; _this.spec = spec; return _this; } _createClass(_class, [{ key: 'addChildrenSource', value: function addChildrenSource(source) { this.childrenSources.push(source); } }, { key: 'removeChildrenSource', value: function removeChildrenSource(source) { this.childrenSources = this.childrenSources.filter(function (item) { return item !== source; }); } }, { key: 'isOver', value: function isOver() { return this._isOver; } }, { key: 'hasChildrenOver', value: function hasChildrenOver() { for (var i = 0, len = this.childrenSources.length; i < len; ++i) { if (this.childrenSources[i].isOver() || this.childrenSources[i].hasChildrenOver()) return true; } return false; } }, { key: 'isAimed', value: function isAimed() { return this.aiming; } }, { key: 'hasChildrenAimed', value: function hasChildrenAimed() { for (var i = 0, len = this.childrenSources.length; i < len; ++i) { if (this.childrenSources[i].hasChildrenAimed()) return true; } return false; } }, { key: 'hasChildrenSource', value: function hasChildrenSource(source) { if (this.childrenSources.includes(source)) return true; var result = false; this.childrenSources.forEach(function (item) { item.childrenTargets.forEach(function (target) { if (target.hasChildrenSource(source)) result = true; }); }); return result; } }, { key: 'componentDidMount', value: function componentDidMount() { if (this.context.source) { this.context.source.addChildrenTarget(this); } this._isMounted = true; _monitor2.default.addTarget(this); var element = _reactDom2.default.findDOMNode(this); element.addEventListener('mousemove', this.handleMouseMove); } }, { key: 'componentWillUnmount', value: function componentWillUnmount() { if (this.context.source) { this.context.source.removeChildrenTarget(this); } this._isMounted = false; _monitor2.default.removeTarget(this); var element = _reactDom2.default.findDOMNode(this); element.removeEventListener('mousemove', this.handleMouseMove); document.removeEventListener('mousemove', this.handleMouseMove); document.removeEventListener('mouseout', this.handleMouseOut); clearTimeout(this.stopTimeout); } }, { key: 'trackMouseLeave', value: function trackMouseLeave() { var element = _reactDom2.default.findDOMNode(this); document.addEventListener('mousemove', this.handleMouseMove); document.addEventListener('mouseout', this.handleMouseOut); element.removeEventListener('mousemove', this.handleMouseMove); } }, { key: 'untrackMouseLeave', value: function untrackMouseLeave() { var element = _reactDom2.default.findDOMNode(this); document.removeEventListener('mousemove', this.handleMouseMove); document.removeEventListener('mouseout', this.handleMouseOut); element.addEventListener('mousemove', this.handleMouseMove); } }, { key: 'triggerAimMove', value: function triggerAimMove(distance) { var _this2 = this; if (!this.maxDistance) this.maxDistance = distance; distance = Math.round((1 - 1 / this.maxDistance * distance) * 1000) / 1000; if (this.prevDistance === null || this.prevDistance < distance || this.aiming) { if (!this.aiming) { this.aiming = true; if (_typeof(this.spec) === 'object' && this.spec && typeof this.spec.aimStart === 'function') { this.spec.aimStart(this.wrappedComponent.props, this.wrappedComponent, distance); } } this.skippedStops = 0; if (this.stopTimeout) clearTimeout(this.stopTimeout); this.stopTimeout = setTimeout(function () { _this2.triggerAimStop(true); if (!_this2._isOver) _monitor2.default.aimStopped(); }, 100); if (_typeof(this.spec) === 'object' && this.spec && typeof this.spec.aimMove === 'function') { this.spec.aimMove(this.wrappedComponent.props, this.wrappedComponent, distance); } } this.prevDistance = distance; } }, { key: 'triggerAimStop', value: function triggerAimStop() { var _this3 = this; var force = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : false; if (this.stopTimeout) clearTimeout(this.stopTimeout); if (this.aiming) { var doStop = function doStop() { _this3.prevDistance = null; _this3.skippedStops = 0; _this3.maxDistance = null; _this3.aiming = false; if (_typeof(_this3.spec) === 'object' && _this3.spec && typeof _this3.spec.aimStop === 'function') { if (_this3.wrappedComponent) { _this3.spec.aimStop(_this3.wrappedComponent.props, _this3.wrappedComponent); } } }; if (!force && this.skippedStops < 10) { this.skippedStops++; this.stopTimeout = setTimeout(function () { doStop(); if (!_this3._isOver) _monitor2.default.aimStopped(); }, 100); } else { doStop(); } } } }, { key: 'triggerMouseEnter', value: function triggerMouseEnter() { if (_typeof(this.spec) === 'object' && this.spec && typeof this.spec.mouseEnter === 'function') { this.spec.mouseEnter(this.wrappedComponent.props, this.wrappedComponent); } } }, { key: 'triggerMouseLeave', value: function triggerMouseLeave() { if (_typeof(this.spec) === 'object' && this.spec && typeof this.spec.mouseLeave === 'function') { this.spec.mouseLeave(this.wrappedComponent.props, this.wrappedComponent); } } }, { key: 'render', value: function render() { var _this4 = this; return _react2.default.createElement(WrappedComponent, _extends({ ref: function ref(_ref) { return _this4.wrappedComponent = _ref; } }, this.props)); } }, { key: 'source', get: function get() { if (typeof this._source === 'function' && this.wrappedComponent) return this._source(this.wrappedComponent.props, this.wrappedComponent); return null; } }]); return _class; }(_react.Component), _class.childContextTypes = { target: _propTypes2.default.object }, _class.contextTypes = { source: _propTypes2.default.object }, _temp; }; }; var _react = require('react'); var _react2 = _interopRequireDefault(_react); var _propTypes = require('prop-types'); var _propTypes2 = _interopRequireDefault(_propTypes); var _reactDom = require('react-dom'); var _reactDom2 = _interopRequireDefault(_reactDom); var _monitor = require('./monitor'); var _monitor2 = _interopRequireDefault(_monitor); 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; }