UNPKG

@mvarble/viewport.js

Version:
860 lines (694 loc) 33 kB
module.exports = /******/ (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] = { /******/ i: moduleId, /******/ l: false, /******/ exports: {} /******/ }; /******/ /******/ // Execute the module function /******/ modules[moduleId].call(module.exports, module, module.exports, __webpack_require__); /******/ /******/ // Flag the module as loaded /******/ module.l = 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; /******/ /******/ // define getter function for harmony exports /******/ __webpack_require__.d = function(exports, name, getter) { /******/ if(!__webpack_require__.o(exports, name)) { /******/ Object.defineProperty(exports, name, { enumerable: true, get: getter }); /******/ } /******/ }; /******/ /******/ // define __esModule on exports /******/ __webpack_require__.r = function(exports) { /******/ if(typeof Symbol !== 'undefined' && Symbol.toStringTag) { /******/ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' }); /******/ } /******/ Object.defineProperty(exports, '__esModule', { value: true }); /******/ }; /******/ /******/ // create a fake namespace object /******/ // mode & 1: value is a module id, require it /******/ // mode & 2: merge all properties of value into the ns /******/ // mode & 4: return value when already ns object /******/ // mode & 8|1: behave like require /******/ __webpack_require__.t = function(value, mode) { /******/ if(mode & 1) value = __webpack_require__(value); /******/ if(mode & 8) return value; /******/ if((mode & 4) && typeof value === 'object' && value && value.__esModule) return value; /******/ var ns = Object.create(null); /******/ __webpack_require__.r(ns); /******/ Object.defineProperty(ns, 'default', { enumerable: true, value: value }); /******/ if(mode & 2 && typeof value != 'string') for(var key in value) __webpack_require__.d(ns, key, function(key) { return value[key]; }.bind(null, key)); /******/ return ns; /******/ }; /******/ /******/ // getDefaultExport function for compatibility with non-harmony modules /******/ __webpack_require__.n = function(module) { /******/ var getter = module && module.__esModule ? /******/ function getDefault() { return module['default']; } : /******/ function getModuleExports() { return module; }; /******/ __webpack_require__.d(getter, 'a', getter); /******/ return getter; /******/ }; /******/ /******/ // Object.prototype.hasOwnProperty.call /******/ __webpack_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); }; /******/ /******/ // __webpack_public_path__ /******/ __webpack_require__.p = ""; /******/ /******/ /******/ // Load entry module and return exports /******/ return __webpack_require__(__webpack_require__.s = 0); /******/ }) /************************************************************************/ /******/ ([ /* 0 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony import */ var _Viewport__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(1); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "Viewport", function() { return _Viewport__WEBPACK_IMPORTED_MODULE_0__["Viewport"]; }); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "ViewportDriver", function() { return _Viewport__WEBPACK_IMPORTED_MODULE_0__["ViewportDriver"]; }); /* harmony import */ var _clicks__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(7); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "isOver", function() { return _clicks__WEBPACK_IMPORTED_MODULE_1__["isOver"]; }); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "getOver", function() { return _clicks__WEBPACK_IMPORTED_MODULE_1__["getOver"]; }); /* harmony default export */ __webpack_exports__["default"] = ({ Viewport: _Viewport__WEBPACK_IMPORTED_MODULE_0__["Viewport"], ViewportDriver: _Viewport__WEBPACK_IMPORTED_MODULE_0__["ViewportDriver"], isOver: _clicks__WEBPACK_IMPORTED_MODULE_1__["isOver"], getOver: _clicks__WEBPACK_IMPORTED_MODULE_1__["getOver"] }); /***/ }), /* 1 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "Viewport", function() { return Viewport; }); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "ViewportDriver", function() { return ViewportDriver; }); /* harmony import */ var xstream__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(2); /* harmony import */ var xstream__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(xstream__WEBPACK_IMPORTED_MODULE_0__); /* harmony import */ var xstream_extra_sampleCombine__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(3); /* harmony import */ var xstream_extra_sampleCombine__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(xstream_extra_sampleCombine__WEBPACK_IMPORTED_MODULE_1__); /* harmony import */ var xstream_extra_dropRepeats__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(4); /* harmony import */ var xstream_extra_dropRepeats__WEBPACK_IMPORTED_MODULE_2___default = /*#__PURE__*/__webpack_require__.n(xstream_extra_dropRepeats__WEBPACK_IMPORTED_MODULE_2__); /* harmony import */ var xstream_extra_fromEvent__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(5); /* harmony import */ var xstream_extra_fromEvent__WEBPACK_IMPORTED_MODULE_3___default = /*#__PURE__*/__webpack_require__.n(xstream_extra_fromEvent__WEBPACK_IMPORTED_MODULE_3__); /* harmony import */ var _cycle_run_lib_adapt__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(6); /* harmony import */ var _cycle_run_lib_adapt__WEBPACK_IMPORTED_MODULE_4___default = /*#__PURE__*/__webpack_require__.n(_cycle_run_lib_adapt__WEBPACK_IMPORTED_MODULE_4__); /* harmony import */ var _clicks__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(7); function _toConsumableArray(arr) { return _arrayWithoutHoles(arr) || _iterableToArray(arr) || _nonIterableSpread(); } function _nonIterableSpread() { throw new TypeError("Invalid attempt to spread non-iterable instance"); } function _iterableToArray(iter) { if (Symbol.iterator in Object(iter) || Object.prototype.toString.call(iter) === "[object Arguments]") return Array.from(iter); } function _arrayWithoutHoles(arr) { if (Array.isArray(arr)) { for (var i = 0, arr2 = new Array(arr.length); i < arr.length; i++) { arr2[i] = arr[i]; } return arr2; } } function _typeof(obj) { "@babel/helpers - typeof"; if (typeof Symbol === "function" && typeof Symbol.iterator === "symbol") { _typeof = function _typeof(obj) { return typeof obj; }; } else { _typeof = function _typeof(obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }; } return _typeof(obj); } function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a 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); } } function _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); return Constructor; } function _slicedToArray(arr, i) { return _arrayWithHoles(arr) || _iterableToArrayLimit(arr, i) || _nonIterableRest(); } function _nonIterableRest() { throw new TypeError("Invalid attempt to destructure non-iterable instance"); } function _iterableToArrayLimit(arr, i) { if (!(Symbol.iterator in Object(arr) || Object.prototype.toString.call(arr) === "[object Arguments]")) { return; } var _arr = []; var _n = true; var _d = false; var _e = undefined; try { for (var _i = arr[Symbol.iterator](), _s; !(_n = (_s = _i.next()).done); _n = true) { _arr.push(_s.value); if (i && _arr.length === i) break; } } catch (err) { _d = true; _e = err; } finally { try { if (!_n && _i["return"] != null) _i["return"](); } finally { if (_d) throw _e; } } return _arr; } function _arrayWithHoles(arr) { if (Array.isArray(arr)) return arr; } function ownKeys(object, enumerableOnly) { var keys = Object.keys(object); if (Object.getOwnPropertySymbols) { var symbols = Object.getOwnPropertySymbols(object); if (enumerableOnly) symbols = symbols.filter(function (sym) { return Object.getOwnPropertyDescriptor(object, sym).enumerable; }); keys.push.apply(keys, symbols); } return keys; } function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i] != null ? arguments[i] : {}; if (i % 2) { ownKeys(Object(source), true).forEach(function (key) { _defineProperty(target, key, source[key]); }); } else if (Object.getOwnPropertyDescriptors) { Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)); } else { ownKeys(Object(source)).forEach(function (key) { Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key)); }); } } return target; } function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; } /** * Viewport.js * * This module exports the Cycle.js driver/component pair which allow for * declarative rendering on the canvas. */ // module dependencies: npm packages // module dependencies: project modules // exports // these are boolean functions that help us determine the state of a snabbdom // vdom function isRenderable(vdom) { if (typeof document === 'undefined') return false; return vdom && vdom.elm && document.body.contains(vdom.elm); } function alreadyHasHook(vdom) { return vdom.data && vdom.data.hook && vdom.data.hook.insert; } function withRenderHook(vdom, renderFunc, stateObject) { if (alreadyHasHook(vdom)) { if (!vdom.data.viewport) { var insert = function insert(vnode) { vdom.data.hook.insert(vnode); renderFunc(vnode.elm, stateObject); }; var newVdom = _objectSpread({}, vdom, { data: _objectSpread({}, vdom.data, { hook: _objectSpread({}, vdom.data.hook, { insert: insert }), viewport: { oldInsert: vdom.data.hook.insert } }) }); return newVdom; } else { var _insert = function _insert(vnode) { if (vnode.data.viewport.oldInsert) { vnode.data.viewport.oldInsert(vnode); } renderFunc(vnode.elm, stateObject); }; var _newVdom = _objectSpread({}, vdom, { data: _objectSpread({}, vdom.data, { hook: _objectSpread({}, vdom.data.hook, { insert: _insert }) }) }); return _newVdom; } } else { var _newVdom2 = _objectSpread({}, vdom); if (!_newVdom2.data) { _newVdom2.data = {}; } if (!_newVdom2.data.hook) { _newVdom2.data.hook = {}; } _newVdom2.data.viewport = { oldInsert: undefined }; vdom.data.hook.insert = function (vnode) { return renderFunc(vnode.elm, stateObject); }; return _newVdom2; } } /** * Viewport: * * This is a simple component that appends a hook to the relevant snabbdom and * prepares a stream for the ViewportDriver. */ function Viewport(_ref) { var DOM = _ref.DOM, state = _ref.state, canvas = _ref.canvas, render = _ref.render, parseDeep = _ref.parseDeep; var all$$ = xstream__WEBPACK_IMPORTED_MODULE_0___default.a.combine(state, canvas, render, parseDeep || xstream__WEBPACK_IMPORTED_MODULE_0___default.a.of(true)).map(function (_ref2) { var _ref3 = _slicedToArray(_ref2, 4), stateObject = _ref3[0], vdom = _ref3[1], renderFunc = _ref3[2], isDeep = _ref3[3]; // if there is no vdom, we cannot do anything if (!vdom) return xstream__WEBPACK_IMPORTED_MODULE_0___default.a.empty(); // if there is a ready vdom, we simply pile everything together if (isRenderable(vdom)) { return { vdom: xstream__WEBPACK_IMPORTED_MODULE_0___default.a.of(vdom), viewport: xstream__WEBPACK_IMPORTED_MODULE_0___default.a.of({ render: renderFunc, state: stateObject, elm: vdom.elm, isDeep: isDeep }) }; } // if the vdom is not ready, we need to add insert render hooks var newVdom = withRenderHook(vdom, renderFunc, stateObject); // in the chance that the vdom has been patched and the object is already // in there. In such a case, take the most recent result of the element return { vdom: xstream__WEBPACK_IMPORTED_MODULE_0___default.a.of(newVdom), viewport: DOM.select(newVdom.sel).element().take(1).map(function (elm) { return { render: renderFunc, state: stateObject, elm: elm, isDeep: isDeep }; }) }; }); // we return the adapted DOM and viewport streams return { DOM: all$$.map(function (obj) { return obj.vdom; }).flatten(), viewport: all$$.map(function (obj) { return obj.viewport; }).flatten() }; } /** * ViewportDriver: * * This is a Cycle.js driver which allows us to have a queryable collection of * streams corresponding to parsed events on a canvas DOM element. These parsed * events will correspond to click events that occured over a given frame. * This is done by leveraging the streams of a `MainDOMSource` object from the * Cycle.js factory `DOMDriver`. */ function ViewportDriver(viewport$) { // create the render callback var next = function next(_ref4) { var render = _ref4.render, elm = _ref4.elm, state = _ref4.state; if (typeof document !== 'undefined' && document.body.contains(elm)) { render(elm, state); } }; // add render callback as listener viewport$.addListener({ next: next }); // return the FrameSource var state$ = viewport$.map(function (viewport) { return { state: viewport.state, _scope: viewport._scope, isDeep: viewport.isDeep }; }); return new UnmountedFrameSource(state$); } /** * UnmountedFrameSource * * An instance of this class is returned by the ViewportDriver. */ var unmountedAncestryMessage = 'Do not isolate an `UnmountedFrameSource`' + 'instance to a specific branch. Instead, mount this source first!'; var UnmountedFrameSource = /*#__PURE__*/function () { function UnmountedFrameSource(state$, scope) { _classCallCheck(this, UnmountedFrameSource); this._state$ = state$; this._scope = scope || []; this.isolateSource = function (source, scope) { var isolation = parseIsolationScope(scope); if (isolation.type3) return source; if (isolation.type1) { return new UnmountedFrameSource(source._state$, appendScope(source._scope, isolation.type1)); } throw new Error(unmountedAncestryMessage); }; this.isolateSink = isolateSink; } _createClass(UnmountedFrameSource, [{ key: "mount", value: function mount(domSource) { return new FrameSourceMaster(domSource, this._state$, this._scope); } }, { key: "select", value: function select() { throw new Error('You need to mount a `DOMSource` before filtering streams'); } }, { key: "events", value: function events() { throw new Error('You need to mount a `DOMSource` before requesting streams'); } }]); return UnmountedFrameSource; }(); /** * FrameSourceMaster * * Each `FrameSourceMaster` is in the context of some `DOMSource` and a stream * of `frame.js` frames. It creates a wrapper of `DOMSource.events` and * some additional methods which allow us to quickly parse the frame. */ var FrameSourceMaster = /*#__PURE__*/function () { // our constructor function FrameSourceMaster(domSource, state$, scope) { _classCallCheck(this, FrameSourceMaster); this._domSource = domSource; this._state$ = state$; this._scope = scope; this._parsedStreams = {}; this.isolateSource = function (source, scope) { var isolation = parseIsolationScope(scope); if (isolation.type3) return source; if (isolation.type1) { return new FrameSourceMaster(source._domSource, source._state$, appendScope(source._scope, isolation.type1)); } return new FrameSource(source, function () { return true; }, [isolation.type2]); }; this.isolateSink = isolateSink; } /** * this is a wrapper of the `DOMSource.events` method, with the added * information of which frame `getOver(event, frame, isOver)` returned */ _createClass(FrameSourceMaster, [{ key: "events", value: function events(type) { var _this = this; if (!this._parsedStreams[type]) { // filter the state immediately var state$ = this._state$.filter(function (_ref5) { var _scope = _ref5._scope; return withinScope(_this._scope, _scope); }); // leverage the DOMSource events this._parsedStreams[type] = this._domSource.events(type).compose(xstream_extra_sampleCombine__WEBPACK_IMPORTED_MODULE_1___default()(state$)).map(function (_ref6) { var _ref7 = _slicedToArray(_ref6, 2), event = _ref7[0], _ref7$ = _ref7[1], state = _ref7$.state, isDeep = _ref7$.isDeep; var _getOver = Object(_clicks__WEBPACK_IMPORTED_MODULE_5__["getOver"])(event, state, isDeep), frame = _getOver.frame, treeKeys = _getOver.treeKeys; event.frame = frame; event.treeKeys = treeKeys; return event; }); } return Object(_cycle_run_lib_adapt__WEBPACK_IMPORTED_MODULE_4__["adapt"])(this._parsedStreams[type]); } /** * this will return a `FrameSource` with the selector in place */ }, { key: "select", value: function select(selector) { if (typeof selector !== 'function') { throw new TypeError('`FrameSource.select` needs a function obj => bool'); return; } return new FrameSource(this, selector, []); } }]); return FrameSourceMaster; }(); /** * FrameSource * * This class serves as a filtered `FrameSourceMaster`. The stream returned * by `FrameSource.parentDims` is identical, while that of `FrameSource.events` * will return only those events for which `event.frame` satisfies the * `FrameSource.selector`, which is a function `frame => bool`. */ var FrameSource = /*#__PURE__*/function () { function FrameSource(master, selector, treeKeys) { _classCallCheck(this, FrameSource); this._master = master; this._selector = selector; this._treeKeys = treeKeys; this.isolateSource = function (source, scope) { var isolation = parseIsolationScope(scope); if (isolation.type3) return source; if (isolation.type1) { var _master = new FrameSourceMaster(source._master._domSource, source._master._state, appendScope(source._master._scope, isolation.type1)); return new FrameSource(_master, source._selector, source._treeKeys); } return new FrameSource(source._master, source._selector, appendScope(source._treeKeys, isolation.type2)); }; this.isolateSink = isolateSink; } _createClass(FrameSource, [{ key: "select", value: function select(selector) { var _this2 = this; if (typeof selector !== 'function') { throw new TypeError('`FrameSource.select` needs a function obj => bool'); return; } return new FrameSource(this._master, function (frame) { return _this2._selector(frame) && selector(frame); }, this._treeKeys); } }, { key: "events", value: function events(type) { var _this3 = this; return this._master.events(type).filter(function (event) { return event && _this3._selector(event.frame) && withinScope(_this3._treeKeys, event.treeKeys); }); } }]); return FrameSource; }(); /** * isolation: * * For isolating ViewportDriver sources/sinks, we have two setups: (1) isolating * different viewports and (2) isolating frames within a single viewport. * * For (1), the source isolation is handled by having a simple string. * * isolate(SomethingWithViewport, 'someScope) * * This string is passed to the `_scope` attribute of the `FrameSource` instance * and the isolation is calculated normally. * * For (2), the source isolation is handled by the `FrameSource` object having * a single property `key`. * * isolate(SomeFrameComponent, { frameSource: { key: 'hisKey' } }) * isolate(SomeFrameComponent, { frameSource: '{"key": "hisKey"}' }) * * The intention of such isolation is that the `FrameSource` instance will store * an ancestry of all keys `[k1, k2, ..., kn]` added in its `_treeKeys` * property. From there, the ancestry keys from `getOver` on each event will * have to contain such isolation keys. * * Note that this isolation in (2) will only work if every frame in the * unist tree has a `key` property. * * Lastly, no isolation of sinks happens in (2), as frames are not responsible * for returning their own viewports. */ function isNully(object) { var type = _typeof(object); return !object && type !== 'boolean' && type !== 'number'; } var errorString = "ViewportDriver isolation requires:\n (1) a string for viewport scope,\n (2) an object with attribute 'key' for filtering clicks along the tree,\n (3) a 'null' or 'undefined' for neither.\n"; // this function will return an object corresponding to the data of (1) vs (2) function parseIsolationScope(scope) { if (isNully(scope)) return { type3: true }; if (scope && scope.key) return { type2: scope.key }; try { // if JSON.parse works and the object has a key attribute, we assume (2) var object = JSON.parse(scope); if (typeof object.key === 'undefined') { throw new Error(errorString); } return { type2: object.key }; } catch (error) { // otherwise, we are in (1), so simply pass the string if (error.name !== 'SyntaxError') { throw error; } return { type1: scope }; } } // these functions will simply control string concatenation. function prependScope(oldScope, scope) { return [scope].concat(_toConsumableArray(oldScope || [])); } function appendScope(oldScope, scope) { return [].concat(_toConsumableArray(oldScope || []), [scope]); } // we do not perform sink isolation in (2), as they should not be creating // their own viewports. function isolateSink(sink, scope) { var isolation = parseIsolationScope(scope); if (isolation.type1) { return sink.map(function (viewport) { return _objectSpread({}, viewport, { _scope: prependScope(viewport._scope, isolation.type1) }); }); } else { return sink; } } // This will see if the sourceScope array is a subset of the streamScope array. // Such an event corresponds to the stream with the associated streamScope // "belonging" to the component with the associated sourceScope. function withinScope(sourceScope, streamScope) { if (!sourceScope || !sourceScope.length) return true; if (!streamScope || !streamScope.length) return false; return streamScope.slice(0, sourceScope.length).every(function (scope, i) { return scope === sourceScope[i]; }); } /***/ }), /* 2 */ /***/ (function(module, exports) { module.exports = require("xstream"); /***/ }), /* 3 */ /***/ (function(module, exports) { module.exports = require("xstream/extra/sampleCombine"); /***/ }), /* 4 */ /***/ (function(module, exports) { module.exports = require("xstream/extra/dropRepeats"); /***/ }), /* 5 */ /***/ (function(module, exports) { module.exports = require("xstream/extra/fromEvent"); /***/ }), /* 6 */ /***/ (function(module, exports) { module.exports = require("@cycle/run/lib/adapt"); /***/ }), /* 7 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "isOver", function() { return isOver; }); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "getOver", function() { return getOver; }); /* harmony import */ var xstream__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(2); /* harmony import */ var xstream__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(xstream__WEBPACK_IMPORTED_MODULE_0__); /* harmony import */ var xstream_extra_fromEvent__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(5); /* harmony import */ var xstream_extra_fromEvent__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(xstream_extra_fromEvent__WEBPACK_IMPORTED_MODULE_1__); /* harmony import */ var unist_util_visit_parents__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(8); /* harmony import */ var unist_util_visit_parents__WEBPACK_IMPORTED_MODULE_2___default = /*#__PURE__*/__webpack_require__.n(unist_util_visit_parents__WEBPACK_IMPORTED_MODULE_2__); /* harmony import */ var _mvarble_frames_js__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(9); /* harmony import */ var _mvarble_frames_js__WEBPACK_IMPORTED_MODULE_3___default = /*#__PURE__*/__webpack_require__.n(_mvarble_frames_js__WEBPACK_IMPORTED_MODULE_3__); /* harmony import */ var _mvarble_viewport_utilities__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(10); /* harmony import */ var _mvarble_viewport_utilities__WEBPACK_IMPORTED_MODULE_4___default = /*#__PURE__*/__webpack_require__.n(_mvarble_viewport_utilities__WEBPACK_IMPORTED_MODULE_4__); function _toConsumableArray(arr) { return _arrayWithoutHoles(arr) || _iterableToArray(arr) || _nonIterableSpread(); } function _nonIterableSpread() { throw new TypeError("Invalid attempt to spread non-iterable instance"); } function _iterableToArray(iter) { if (Symbol.iterator in Object(iter) || Object.prototype.toString.call(iter) === "[object Arguments]") return Array.from(iter); } function _arrayWithoutHoles(arr) { if (Array.isArray(arr)) { for (var i = 0, arr2 = new Array(arr.length); i < arr.length; i++) { arr2[i] = arr[i]; } return arr2; } } function ownKeys(object, enumerableOnly) { var keys = Object.keys(object); if (Object.getOwnPropertySymbols) { var symbols = Object.getOwnPropertySymbols(object); if (enumerableOnly) symbols = symbols.filter(function (sym) { return Object.getOwnPropertyDescriptor(object, sym).enumerable; }); keys.push.apply(keys, symbols); } return keys; } function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i] != null ? arguments[i] : {}; if (i % 2) { ownKeys(Object(source), true).forEach(function (key) { _defineProperty(target, key, source[key]); }); } else if (Object.getOwnPropertyDescriptors) { Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)); } else { ownKeys(Object(source)).forEach(function (key) { Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key)); }); } } return target; } function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; } function _slicedToArray(arr, i) { return _arrayWithHoles(arr) || _iterableToArrayLimit(arr, i) || _nonIterableRest(); } function _nonIterableRest() { throw new TypeError("Invalid attempt to destructure non-iterable instance"); } function _iterableToArrayLimit(arr, i) { if (!(Symbol.iterator in Object(arr) || Object.prototype.toString.call(arr) === "[object Arguments]")) { return; } var _arr = []; var _n = true; var _d = false; var _e = undefined; try { for (var _i = arr[Symbol.iterator](), _s; !(_n = (_s = _i.next()).done); _n = true) { _arr.push(_s.value); if (i && _arr.length === i) break; } } catch (err) { _d = true; _e = err; } finally { try { if (!_n && _i["return"] != null) _i["return"](); } finally { if (_d) throw _e; } } return _arr; } function _arrayWithHoles(arr) { if (Array.isArray(arr)) return arr; } /** * clicks.js * * This module exports utilities that are useful for parsing click events * of a canvas. */ // module dependencies: npm packages // our exports /** * isOver * * This is a function that determines by `frame.data.clickDisk(s)` or * `frame.data.clickBox(es)` if a mouse event occured over a `frame`. * We assume that the click coordinates are those of the world frame. */ function isOver(event, frame) { if (!clickable(frame)) return false; // get the mouse position var p = Object(_mvarble_frames_js__WEBPACK_IMPORTED_MODULE_3__["locFrameTrans"])(Object(_mvarble_viewport_utilities__WEBPACK_IMPORTED_MODULE_4__["relativeMousePosition"])(event), _mvarble_frames_js__WEBPACK_IMPORTED_MODULE_3__["identityFrame"], frame); // check if in clickBox(es) or clickDisk(s) var data = frame.data; if (data.clickBoxes && data.clickBoxes.some(function (b) { return inBox(p, b); })) return true; if (data.clickDisks && data.clickDisks.some(function (d) { return inDisk(p, d); })) return true; if (data.clickDisk && inDisk(p, data.clickDisk)) return true; return data.clickBox ? inBox(p, data.clickBox) : false; } // helper functions function inBox(_ref, _ref2) { var _ref3 = _slicedToArray(_ref, 2), x = _ref3[0], y = _ref3[1]; var _ref4 = _slicedToArray(_ref2, 4), mX = _ref4[0], mY = _ref4[1], MX = _ref4[2], MY = _ref4[3]; return x >= mX && x <= MX && y >= mY && y <= MY; } function inDisk(_ref5, _ref6) { var _ref7 = _slicedToArray(_ref5, 2), x = _ref7[0], y = _ref7[1]; var _ref8 = _slicedToArray(_ref6, 3), h = _ref8[0], k = _ref8[1], r = _ref8[2]; return Math.pow(x - h, 2) + Math.pow(y - k, 2) <= Math.pow(r, 2); } function clickable(frame) { // only frames with coordinate systems and clickBoxes can receive clicks return frame.data && frame.worldMatrix && (frame.data.clickBox || frame.data.clickBoxes || frame.data.clickDisk || frame.data.clickDisks); } /** * getOver * * This is a function that searches down the depth of a tree if any frame in the * state has been clicked on. It uses `unist-util-visit` to run through the * tree, and it proceeds down any branch of which the frame has a successful * `isOver` return. It returns the node. */ function getOver(event, tree, deep) { var frame = null; var treeKeys = []; unist_util_visit_parents__WEBPACK_IMPORTED_MODULE_2___default()(tree, function (node, ancestry) { if (isOver(event, node)) { frame = node; treeKeys = ancestry.map(function (frame) { return frame.key; }).filter(function (key) { return key; }); return false; } }); if (deep && frame && frame.children && frame.children.length) { var overData = getOver(event, _objectSpread({}, frame, { data: {} }), deep); return overData.frame ? { frame: overData.frame, treeKeys: [].concat(_toConsumableArray(treeKeys), _toConsumableArray(overData.treeKeys)) } : { frame: frame, treeKeys: frame.key ? [].concat(_toConsumableArray(treeKeys), [frame.key]) : treeKeys }; } else { return { frame: frame, treeKeys: frame && frame.key ? [].concat(_toConsumableArray(treeKeys), [frame.key]) : treeKeys }; } } /***/ }), /* 8 */ /***/ (function(module, exports) { module.exports = require("unist-util-visit-parents"); /***/ }), /* 9 */ /***/ (function(module, exports) { module.exports = require("@mvarble/frames.js"); /***/ }), /* 10 */ /***/ (function(module, exports) { module.exports = require("@mvarble/viewport-utilities"); /***/ }) /******/ ]);