"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.shiftHeld = exports.optionHeld = exports.mouseIsDown = exports.mouseDowned = exports.mouseButton = exports.metaHeld = exports.gestureState = exports.gestureEnd = exports.dragging = exports.dragVector = exports.cursorPosition = exports.actionEvent = void 0; var _common = require("./common"); var _select = require("./select"); /* * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one * or more contributor license agreements. Licensed under the Elastic License * 2.0; you may not use this file except in compliance with the Elastic License * 2.0. */ // Only needed to shuffle some modifier keys for Apple keyboards as per vector editing software conventions, // so it's OK that user agent strings are not reliable; in case it's spoofed, it'll just work with a slightly // different modifier key map (also, there aren't a lot of alternatives for OS / hw / keyboard detection). // It shouldn't fail in testing environments (node.js) either, where it can just return false, no need for // actually getting the OS on the server side. const appleKeyboard = Boolean(window && window.navigator && window.navigator.userAgent && window.navigator.userAgent.match('Macintosh|iPhone|iPad')); /** * Selectors directly from a state object * * (we could turn gesture.js into a factory, with this state root - primaryUpdate - being passed...) */ const primaryUpdate = state => state.primaryUpdate; const gestureStatePrev = (0, _select.select)(scene => scene.gestureState)(_common.scene); /** * Gestures - derived selectors for transient state */ // dispatch the various types of actions const rawCursorPosition = (0, _select.select)(action => action.type === 'cursorPosition' ? action.payload : null)(primaryUpdate); const mouseButtonEvent = (0, _select.select)(action => action.type === 'mouseEvent' ? action.payload : null)(primaryUpdate); const keyFromMouse = (0, _select.select)(({ type, payload: { altKey, metaKey, shiftKey, ctrlKey } }) => type === 'cursorPosition' || type === 'mouseEvent' ? { altKey, metaKey, shiftKey, ctrlKey } : {})(primaryUpdate); const metaHeld = (0, _select.select)(appleKeyboard ? e => e.metaKey : e => e.altKey)(keyFromMouse); exports.metaHeld = metaHeld; const optionHeld = (0, _select.select)(appleKeyboard ? e => e.altKey : e => e.ctrlKey)(keyFromMouse); exports.optionHeld = optionHeld; const shiftHeld = (0, _select.select)(e => e.shiftKey)(keyFromMouse); exports.shiftHeld = shiftHeld; const cursorPosition = (0, _select.select)(({ cursor }, position) => position || cursor)(gestureStatePrev, rawCursorPosition); exports.cursorPosition = cursorPosition; const mouseButton = (0, _select.select)(next => { if (!next) { return { down: false, up: false, uid: null }; } const { event, uid } = next; if (event === 'mouseDown') { return { down: true, up: false, uid }; } else { return event === 'mouseUp' ? { down: false, up: true, uid } : { down: false, up: false, uid: null }; } })(mouseButtonEvent); exports.mouseButton = mouseButton; const mouseIsDown = (0, _select.select)(({ mouseIsDown }, next) => next ? next.event === 'mouseDown' : mouseIsDown)(gestureStatePrev, mouseButtonEvent); exports.mouseIsDown = mouseIsDown; const gestureEnd = (0, _select.select)(action => action && (action.type === 'actionEvent' || action.type === 'mouseEvent' && action.payload.event === 'mouseUp'))(primaryUpdate); /** * mouseButtonStateTransitions * * View: http://stable.ascii-flow.appspot.com/#567671116534197027 * Edit: http://stable.ascii-flow.appspot.com/#567671116534197027/776257435 * * * mouseNowDown * initial state: 'up' +------------> 'downed' * ^ ^ + + * | | !mouseNowDown | | * !mouseNowDown | +------------------+ | mouseNowDown && movedAlready * | | * +----+ 'dragging' <-----+ * + ^ * | | * +------+ * mouseNowDown * */ exports.gestureEnd = gestureEnd; const mouseButtonStateTransitions = (state, mouseNowDown, movedAlready) => { switch (state) { case 'up': return mouseNowDown ? 'downed' : 'up'; case 'downed': if (mouseNowDown) { return movedAlready ? 'dragging' : 'downed'; } else { return 'up'; } case 'dragging': return mouseNowDown ? 'dragging' : 'up'; } }; const mouseButtonState = (0, _select.select)(({ mouseButtonState: { buttonState, downX, downY } }, mouseNowDown, { x, y }) => { const movedAlready = x !== downX || y !== downY; const newButtonState = mouseButtonStateTransitions(buttonState, mouseNowDown, movedAlready); return { buttonState: newButtonState, downX: newButtonState === 'downed' ? x : downX, downY: newButtonState === 'downed' ? y : downY }; })(gestureStatePrev, mouseIsDown, cursorPosition); const mouseDowned = (0, _select.select)(state => state.buttonState === 'downed')(mouseButtonState); exports.mouseDowned = mouseDowned; const dragging = (0, _select.select)(state => state.buttonState === 'dragging')(mouseButtonState); exports.dragging = dragging; const dragVector = (0, _select.select)(({ buttonState, downX, downY }, { x, y }) => ({ down: buttonState !== 'up', x0: downX, y0: downY, x1: x, y1: y }))(mouseButtonState, cursorPosition); exports.dragVector = dragVector; const actionEvent = (0, _select.select)(action => action.type === 'actionEvent' ? action.payload : null)(primaryUpdate); exports.actionEvent = actionEvent; const gestureState = (0, _select.select)((cursor, mouseIsDown, mouseButtonState) => ({ cursor, mouseIsDown, mouseButtonState }))(cursorPosition, mouseIsDown, mouseButtonState); exports.gestureState = gestureState;