react-csv-importer
Version:
React CSV import widget with user-customizable mapping
1,736 lines (1,474 loc) • 158 kB
JavaScript
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 = 25);
/******/ })
/************************************************************************/
/******/ ([
/* 0 */
/***/ (function(module, exports) {
module.exports = require("react");
/***/ }),
/* 1 */
/***/ (function(module, __webpack_exports__, __webpack_require__) {
"use strict";
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "a", function() { return ConfigResolverMap; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "b", function() { return EngineMap; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "c", function() { return SUPPORT; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "d", function() { return _objectSpread2; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "e", function() { return _defineProperty; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "f", function() { return touchIds; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "g", function() { return chain; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "h", function() { return toHandlerProp; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "i", function() { return dragAction; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "j", function() { return pinchAction; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "k", function() { return hoverAction; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "l", function() { return isTouch; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "m", function() { return moveAction; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "n", function() { return parseProp; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "o", function() { return registerAction; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "p", function() { return scrollAction; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "q", function() { return toDomEventType; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "r", function() { return wheelAction; });
/* harmony import */ var _maths_b2a210f4_esm_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(2);
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 ownKeys(object, enumerableOnly) {
var keys = Object.keys(object);
if (Object.getOwnPropertySymbols) {
var symbols = Object.getOwnPropertySymbols(object);
enumerableOnly && (symbols = symbols.filter(function (sym) {
return Object.getOwnPropertyDescriptor(object, sym).enumerable;
})), keys.push.apply(keys, symbols);
}
return keys;
}
function _objectSpread2(target) {
for (var i = 1; i < arguments.length; i++) {
var source = null != arguments[i] ? arguments[i] : {};
i % 2 ? ownKeys(Object(source), !0).forEach(function (key) {
_defineProperty(target, key, source[key]);
}) : Object.getOwnPropertyDescriptors ? Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)) : ownKeys(Object(source)).forEach(function (key) {
Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key));
});
}
return target;
}
const EVENT_TYPE_MAP = {
pointer: {
start: 'down',
change: 'move',
end: 'up'
},
mouse: {
start: 'down',
change: 'move',
end: 'up'
},
touch: {
start: 'start',
change: 'move',
end: 'end'
},
gesture: {
start: 'start',
change: 'change',
end: 'end'
}
};
function capitalize(string) {
if (!string) return '';
return string[0].toUpperCase() + string.slice(1);
}
function toHandlerProp(device, action = '', capture = false) {
const deviceProps = EVENT_TYPE_MAP[device];
const actionKey = deviceProps ? deviceProps[action] || action : action;
return 'on' + capitalize(device) + capitalize(actionKey) + (capture ? 'Capture' : '');
}
const pointerCaptureEvents = ['gotpointercapture', 'lostpointercapture'];
function parseProp(prop) {
let eventKey = prop.substring(2).toLowerCase();
const passive = !!~eventKey.indexOf('passive');
if (passive) eventKey = eventKey.replace('passive', '');
const captureKey = pointerCaptureEvents.includes(eventKey) ? 'capturecapture' : 'capture';
const capture = !!~eventKey.indexOf(captureKey);
if (capture) eventKey = eventKey.replace('capture', '');
return {
device: eventKey,
capture,
passive
};
}
function toDomEventType(device, action = '') {
const deviceProps = EVENT_TYPE_MAP[device];
const actionKey = deviceProps ? deviceProps[action] || action : action;
return device + actionKey;
}
function isTouch(event) {
return 'touches' in event;
}
function getPointerType(event) {
if (isTouch(event)) return 'touch';
if ('pointerType' in event) return event.pointerType;
return 'mouse';
}
function getCurrentTargetTouchList(event) {
return Array.from(event.touches).filter(e => {
var _event$currentTarget, _event$currentTarget$;
return e.target === event.currentTarget || ((_event$currentTarget = event.currentTarget) === null || _event$currentTarget === void 0 ? void 0 : (_event$currentTarget$ = _event$currentTarget.contains) === null || _event$currentTarget$ === void 0 ? void 0 : _event$currentTarget$.call(_event$currentTarget, e.target));
});
}
function getTouchList(event) {
return event.type === 'touchend' || event.type === 'touchcancel' ? event.changedTouches : event.targetTouches;
}
function getValueEvent(event) {
return isTouch(event) ? getTouchList(event)[0] : event;
}
function distanceAngle(P1, P2) {
const dx = P2.clientX - P1.clientX;
const dy = P2.clientY - P1.clientY;
const cx = (P2.clientX + P1.clientX) / 2;
const cy = (P2.clientY + P1.clientY) / 2;
const distance = Math.hypot(dx, dy);
const angle = -(Math.atan2(dx, dy) * 180) / Math.PI;
const origin = [cx, cy];
return {
angle,
distance,
origin
};
}
function touchIds(event) {
return getCurrentTargetTouchList(event).map(touch => touch.identifier);
}
function touchDistanceAngle(event, ids) {
const [P1, P2] = Array.from(event.touches).filter(touch => ids.includes(touch.identifier));
return distanceAngle(P1, P2);
}
function pointerId(event) {
const valueEvent = getValueEvent(event);
return isTouch(event) ? valueEvent.identifier : valueEvent.pointerId;
}
function pointerValues(event) {
const valueEvent = getValueEvent(event);
return [valueEvent.clientX, valueEvent.clientY];
}
const LINE_HEIGHT = 40;
const PAGE_HEIGHT = 800;
function wheelValues(event) {
let {
deltaX,
deltaY,
deltaMode
} = event;
if (deltaMode === 1) {
deltaX *= LINE_HEIGHT;
deltaY *= LINE_HEIGHT;
} else if (deltaMode === 2) {
deltaX *= PAGE_HEIGHT;
deltaY *= PAGE_HEIGHT;
}
return [deltaX, deltaY];
}
function scrollValues(event) {
var _ref, _ref2;
const {
scrollX,
scrollY,
scrollLeft,
scrollTop
} = event.currentTarget;
return [(_ref = scrollX !== null && scrollX !== void 0 ? scrollX : scrollLeft) !== null && _ref !== void 0 ? _ref : 0, (_ref2 = scrollY !== null && scrollY !== void 0 ? scrollY : scrollTop) !== null && _ref2 !== void 0 ? _ref2 : 0];
}
function getEventDetails(event) {
const payload = {};
if ('buttons' in event) payload.buttons = event.buttons;
if ('shiftKey' in event) {
const {
shiftKey,
altKey,
metaKey,
ctrlKey
} = event;
Object.assign(payload, {
shiftKey,
altKey,
metaKey,
ctrlKey
});
}
return payload;
}
function call(v, ...args) {
if (typeof v === 'function') {
return v(...args);
} else {
return v;
}
}
function noop() {}
function chain(...fns) {
if (fns.length === 0) return noop;
if (fns.length === 1) return fns[0];
return function () {
let result;
for (const fn of fns) {
result = fn.apply(this, arguments) || result;
}
return result;
};
}
function assignDefault(value, fallback) {
return Object.assign({}, fallback, value || {});
}
const BEFORE_LAST_KINEMATICS_DELAY = 32;
class Engine {
constructor(ctrl, args, key) {
this.ctrl = ctrl;
this.args = args;
this.key = key;
if (!this.state) {
this.state = {};
this.computeValues([0, 0]);
this.computeInitial();
if (this.init) this.init();
this.reset();
}
}
get state() {
return this.ctrl.state[this.key];
}
set state(state) {
this.ctrl.state[this.key] = state;
}
get shared() {
return this.ctrl.state.shared;
}
get eventStore() {
return this.ctrl.gestureEventStores[this.key];
}
get timeoutStore() {
return this.ctrl.gestureTimeoutStores[this.key];
}
get config() {
return this.ctrl.config[this.key];
}
get sharedConfig() {
return this.ctrl.config.shared;
}
get handler() {
return this.ctrl.handlers[this.key];
}
reset() {
const {
state,
shared,
ingKey,
args
} = this;
shared[ingKey] = state._active = state.active = state._blocked = state._force = false;
state._step = [false, false];
state.intentional = false;
state._movement = [0, 0];
state._distance = [0, 0];
state._direction = [0, 0];
state._delta = [0, 0];
state._bounds = [[-Infinity, Infinity], [-Infinity, Infinity]];
state.args = args;
state.axis = undefined;
state.memo = undefined;
state.elapsedTime = 0;
state.direction = [0, 0];
state.distance = [0, 0];
state.overflow = [0, 0];
state._movementBound = [false, false];
state.velocity = [0, 0];
state.movement = [0, 0];
state.delta = [0, 0];
state.timeStamp = 0;
}
start(event) {
const state = this.state;
const config = this.config;
if (!state._active) {
this.reset();
this.computeInitial();
state._active = true;
state.target = event.target;
state.currentTarget = event.currentTarget;
state.lastOffset = config.from ? call(config.from, state) : state.offset;
state.offset = state.lastOffset;
}
state.startTime = state.timeStamp = event.timeStamp;
}
computeValues(values) {
const state = this.state;
state._values = values;
state.values = this.config.transform(values);
}
computeInitial() {
const state = this.state;
state._initial = state._values;
state.initial = state.values;
}
compute(event) {
const {
state,
config,
shared
} = this;
state.args = this.args;
let dt = 0;
if (event) {
state.event = event;
if (config.preventDefault && event.cancelable) state.event.preventDefault();
state.type = event.type;
shared.touches = this.ctrl.pointerIds.size || this.ctrl.touchIds.size;
shared.locked = !!document.pointerLockElement;
Object.assign(shared, getEventDetails(event));
shared.down = shared.pressed = shared.buttons % 2 === 1 || shared.touches > 0;
dt = event.timeStamp - state.timeStamp;
state.timeStamp = event.timeStamp;
state.elapsedTime = state.timeStamp - state.startTime;
}
if (state._active) {
const _absoluteDelta = state._delta.map(Math.abs);
_maths_b2a210f4_esm_js__WEBPACK_IMPORTED_MODULE_0__[/* V */ "a"].addTo(state._distance, _absoluteDelta);
}
if (this.axisIntent) this.axisIntent(event);
const [_m0, _m1] = state._movement;
const [t0, t1] = config.threshold;
const {
_step,
values
} = state;
if (config.hasCustomTransform) {
if (_step[0] === false) _step[0] = Math.abs(_m0) >= t0 && values[0];
if (_step[1] === false) _step[1] = Math.abs(_m1) >= t1 && values[1];
} else {
if (_step[0] === false) _step[0] = Math.abs(_m0) >= t0 && Math.sign(_m0) * t0;
if (_step[1] === false) _step[1] = Math.abs(_m1) >= t1 && Math.sign(_m1) * t1;
}
state.intentional = _step[0] !== false || _step[1] !== false;
if (!state.intentional) return;
const movement = [0, 0];
if (config.hasCustomTransform) {
const [v0, v1] = values;
movement[0] = _step[0] !== false ? v0 - _step[0] : 0;
movement[1] = _step[1] !== false ? v1 - _step[1] : 0;
} else {
movement[0] = _step[0] !== false ? _m0 - _step[0] : 0;
movement[1] = _step[1] !== false ? _m1 - _step[1] : 0;
}
if (this.restrictToAxis && !state._blocked) this.restrictToAxis(movement);
const previousOffset = state.offset;
const gestureIsActive = state._active && !state._blocked || state.active;
if (gestureIsActive) {
state.first = state._active && !state.active;
state.last = !state._active && state.active;
state.active = shared[this.ingKey] = state._active;
if (event) {
if (state.first) {
if ('bounds' in config) state._bounds = call(config.bounds, state);
if (this.setup) this.setup();
}
state.movement = movement;
this.computeOffset();
}
}
const [ox, oy] = state.offset;
const [[x0, x1], [y0, y1]] = state._bounds;
state.overflow = [ox < x0 ? -1 : ox > x1 ? 1 : 0, oy < y0 ? -1 : oy > y1 ? 1 : 0];
state._movementBound[0] = state.overflow[0] ? state._movementBound[0] === false ? state._movement[0] : state._movementBound[0] : false;
state._movementBound[1] = state.overflow[1] ? state._movementBound[1] === false ? state._movement[1] : state._movementBound[1] : false;
const rubberband = state._active ? config.rubberband || [0, 0] : [0, 0];
state.offset = Object(_maths_b2a210f4_esm_js__WEBPACK_IMPORTED_MODULE_0__[/* c */ "b"])(state._bounds, state.offset, rubberband);
state.delta = _maths_b2a210f4_esm_js__WEBPACK_IMPORTED_MODULE_0__[/* V */ "a"].sub(state.offset, previousOffset);
this.computeMovement();
if (gestureIsActive && (!state.last || dt > BEFORE_LAST_KINEMATICS_DELAY)) {
state.delta = _maths_b2a210f4_esm_js__WEBPACK_IMPORTED_MODULE_0__[/* V */ "a"].sub(state.offset, previousOffset);
const absoluteDelta = state.delta.map(Math.abs);
_maths_b2a210f4_esm_js__WEBPACK_IMPORTED_MODULE_0__[/* V */ "a"].addTo(state.distance, absoluteDelta);
state.direction = state.delta.map(Math.sign);
state._direction = state._delta.map(Math.sign);
if (!state.first && dt > 0) {
state.velocity = [absoluteDelta[0] / dt, absoluteDelta[1] / dt];
}
}
}
emit() {
const state = this.state;
const shared = this.shared;
const config = this.config;
if (!state._active) this.clean();
if ((state._blocked || !state.intentional) && !state._force && !config.triggerAllEvents) return;
const memo = this.handler(_objectSpread2(_objectSpread2(_objectSpread2({}, shared), state), {}, {
[this.aliasKey]: state.values
}));
if (memo !== undefined) state.memo = memo;
}
clean() {
this.eventStore.clean();
this.timeoutStore.clean();
}
}
function selectAxis([dx, dy], threshold) {
const absDx = Math.abs(dx);
const absDy = Math.abs(dy);
if (absDx > absDy && absDx > threshold) {
return 'x';
}
if (absDy > absDx && absDy > threshold) {
return 'y';
}
return undefined;
}
class CoordinatesEngine extends Engine {
constructor(...args) {
super(...args);
_defineProperty(this, "aliasKey", 'xy');
}
reset() {
super.reset();
this.state.axis = undefined;
}
init() {
this.state.offset = [0, 0];
this.state.lastOffset = [0, 0];
}
computeOffset() {
this.state.offset = _maths_b2a210f4_esm_js__WEBPACK_IMPORTED_MODULE_0__[/* V */ "a"].add(this.state.lastOffset, this.state.movement);
}
computeMovement() {
this.state.movement = _maths_b2a210f4_esm_js__WEBPACK_IMPORTED_MODULE_0__[/* V */ "a"].sub(this.state.offset, this.state.lastOffset);
}
axisIntent(event) {
const state = this.state;
const config = this.config;
if (!state.axis && event) {
const threshold = typeof config.axisThreshold === 'object' ? config.axisThreshold[getPointerType(event)] : config.axisThreshold;
state.axis = selectAxis(state._movement, threshold);
}
state._blocked = (config.lockDirection || !!config.axis) && !state.axis || !!config.axis && config.axis !== state.axis;
}
restrictToAxis(v) {
if (this.config.axis || this.config.lockDirection) {
switch (this.state.axis) {
case 'x':
v[1] = 0;
break;
case 'y':
v[0] = 0;
break;
}
}
}
}
const identity = v => v;
const DEFAULT_RUBBERBAND = 0.15;
const commonConfigResolver = {
enabled(value = true) {
return value;
},
preventDefault(value = false) {
return value;
},
triggerAllEvents(value = false) {
return value;
},
rubberband(value = 0) {
switch (value) {
case true:
return [DEFAULT_RUBBERBAND, DEFAULT_RUBBERBAND];
case false:
return [0, 0];
default:
return _maths_b2a210f4_esm_js__WEBPACK_IMPORTED_MODULE_0__[/* V */ "a"].toVector(value);
}
},
from(value) {
if (typeof value === 'function') return value;
if (value != null) return _maths_b2a210f4_esm_js__WEBPACK_IMPORTED_MODULE_0__[/* V */ "a"].toVector(value);
},
transform(value, _k, config) {
const transform = value || config.shared.transform;
this.hasCustomTransform = !!transform;
if (false) {}
return transform || identity;
},
threshold(value) {
return _maths_b2a210f4_esm_js__WEBPACK_IMPORTED_MODULE_0__[/* V */ "a"].toVector(value, 0);
}
};
if (false) {}
const DEFAULT_AXIS_THRESHOLD = 0;
const coordinatesConfigResolver = _objectSpread2(_objectSpread2({}, commonConfigResolver), {}, {
axis(_v, _k, {
axis
}) {
this.lockDirection = axis === 'lock';
if (!this.lockDirection) return axis;
},
axisThreshold(value = DEFAULT_AXIS_THRESHOLD) {
return value;
},
bounds(value = {}) {
if (typeof value === 'function') {
return state => coordinatesConfigResolver.bounds(value(state));
}
if ('current' in value) {
return () => value.current;
}
if (typeof HTMLElement === 'function' && value instanceof HTMLElement) {
return value;
}
const {
left = -Infinity,
right = Infinity,
top = -Infinity,
bottom = Infinity
} = value;
return [[left, right], [top, bottom]];
}
});
const DISPLACEMENT = 10;
const KEYS_DELTA_MAP = {
ArrowRight: (factor = 1) => [DISPLACEMENT * factor, 0],
ArrowLeft: (factor = 1) => [-DISPLACEMENT * factor, 0],
ArrowUp: (factor = 1) => [0, -DISPLACEMENT * factor],
ArrowDown: (factor = 1) => [0, DISPLACEMENT * factor]
};
class DragEngine extends CoordinatesEngine {
constructor(...args) {
super(...args);
_defineProperty(this, "ingKey", 'dragging');
}
reset() {
super.reset();
const state = this.state;
state._pointerId = undefined;
state._pointerActive = false;
state._keyboardActive = false;
state._preventScroll = false;
state._delayed = false;
state.swipe = [0, 0];
state.tap = false;
state.canceled = false;
state.cancel = this.cancel.bind(this);
}
setup() {
const state = this.state;
if (state._bounds instanceof HTMLElement) {
const boundRect = state._bounds.getBoundingClientRect();
const targetRect = state.currentTarget.getBoundingClientRect();
const _bounds = {
left: boundRect.left - targetRect.left + state.offset[0],
right: boundRect.right - targetRect.right + state.offset[0],
top: boundRect.top - targetRect.top + state.offset[1],
bottom: boundRect.bottom - targetRect.bottom + state.offset[1]
};
state._bounds = coordinatesConfigResolver.bounds(_bounds);
}
}
cancel() {
const state = this.state;
if (state.canceled) return;
state.canceled = true;
state._active = false;
setTimeout(() => {
this.compute();
this.emit();
}, 0);
}
setActive() {
this.state._active = this.state._pointerActive || this.state._keyboardActive;
}
clean() {
this.pointerClean();
this.state._pointerActive = false;
this.state._keyboardActive = false;
super.clean();
}
pointerDown(event) {
const config = this.config;
const state = this.state;
if (event.buttons != null && (Array.isArray(config.pointerButtons) ? !config.pointerButtons.includes(event.buttons) : config.pointerButtons !== -1 && config.pointerButtons !== event.buttons)) return;
this.ctrl.setEventIds(event);
if (config.pointerCapture) {
event.target.setPointerCapture(event.pointerId);
}
if (state._pointerActive) return;
this.start(event);
this.setupPointer(event);
state._pointerId = pointerId(event);
state._pointerActive = true;
this.computeValues(pointerValues(event));
this.computeInitial();
if (config.preventScrollAxis && getPointerType(event) !== 'mouse') {
state._active = false;
this.setupScrollPrevention(event);
} else if (config.delay > 0) {
this.setupDelayTrigger(event);
if (config.triggerAllEvents) {
this.compute(event);
this.emit();
}
} else {
this.startPointerDrag(event);
}
}
startPointerDrag(event) {
const state = this.state;
state._active = true;
state._preventScroll = true;
state._delayed = false;
this.compute(event);
this.emit();
}
pointerMove(event) {
const state = this.state;
const config = this.config;
if (!state._pointerActive) return;
if (state.type === event.type && event.timeStamp === state.timeStamp) return;
const id = pointerId(event);
if (state._pointerId !== undefined && id !== state._pointerId) return;
const _values = pointerValues(event);
if (document.pointerLockElement === event.target) {
state._delta = [event.movementX, event.movementY];
} else {
state._delta = _maths_b2a210f4_esm_js__WEBPACK_IMPORTED_MODULE_0__[/* V */ "a"].sub(_values, state._values);
this.computeValues(_values);
}
_maths_b2a210f4_esm_js__WEBPACK_IMPORTED_MODULE_0__[/* V */ "a"].addTo(state._movement, state._delta);
this.compute(event);
if (state._delayed && state.intentional) {
this.timeoutStore.remove('dragDelay');
state.active = false;
this.startPointerDrag(event);
return;
}
if (config.preventScrollAxis && !state._preventScroll) {
if (state.axis) {
if (state.axis === config.preventScrollAxis || config.preventScrollAxis === 'xy') {
state._active = false;
this.clean();
return;
} else {
this.timeoutStore.remove('startPointerDrag');
this.startPointerDrag(event);
return;
}
} else {
return;
}
}
this.emit();
}
pointerUp(event) {
this.ctrl.setEventIds(event);
try {
if (this.config.pointerCapture && event.target.hasPointerCapture(event.pointerId)) {
;
event.target.releasePointerCapture(event.pointerId);
}
} catch (_unused) {
if (false) {}
}
const state = this.state;
const config = this.config;
if (!state._active || !state._pointerActive) return;
const id = pointerId(event);
if (state._pointerId !== undefined && id !== state._pointerId) return;
this.state._pointerActive = false;
this.setActive();
this.compute(event);
const [dx, dy] = state._distance;
state.tap = dx <= config.tapsThreshold && dy <= config.tapsThreshold;
if (state.tap && config.filterTaps) {
state._force = true;
} else {
const [dirx, diry] = state.direction;
const [vx, vy] = state.velocity;
const [mx, my] = state.movement;
const [svx, svy] = config.swipe.velocity;
const [sx, sy] = config.swipe.distance;
const sdt = config.swipe.duration;
if (state.elapsedTime < sdt) {
if (Math.abs(vx) > svx && Math.abs(mx) > sx) state.swipe[0] = dirx;
if (Math.abs(vy) > svy && Math.abs(my) > sy) state.swipe[1] = diry;
}
}
this.emit();
}
pointerClick(event) {
if (!this.state.tap) {
event.preventDefault();
event.stopPropagation();
}
}
setupPointer(event) {
const config = this.config;
const device = config.device;
if (false) {}
if (config.pointerLock) {
event.currentTarget.requestPointerLock();
}
if (!config.pointerCapture) {
this.eventStore.add(this.sharedConfig.window, device, 'change', this.pointerMove.bind(this));
this.eventStore.add(this.sharedConfig.window, device, 'end', this.pointerUp.bind(this));
this.eventStore.add(this.sharedConfig.window, device, 'cancel', this.pointerUp.bind(this));
}
}
pointerClean() {
if (this.config.pointerLock && document.pointerLockElement === this.state.currentTarget) {
document.exitPointerLock();
}
}
preventScroll(event) {
if (this.state._preventScroll && event.cancelable) {
event.preventDefault();
}
}
setupScrollPrevention(event) {
persistEvent(event);
this.eventStore.add(this.sharedConfig.window, 'touch', 'change', this.preventScroll.bind(this), {
passive: false
});
this.eventStore.add(this.sharedConfig.window, 'touch', 'end', this.clean.bind(this));
this.eventStore.add(this.sharedConfig.window, 'touch', 'cancel', this.clean.bind(this));
this.timeoutStore.add('startPointerDrag', this.startPointerDrag.bind(this), this.config.preventScrollDelay, event);
}
setupDelayTrigger(event) {
this.state._delayed = true;
this.timeoutStore.add('dragDelay', () => {
this.state._step = [0, 0];
this.startPointerDrag(event);
}, this.config.delay);
}
keyDown(event) {
const deltaFn = KEYS_DELTA_MAP[event.key];
if (deltaFn) {
const state = this.state;
const factor = event.shiftKey ? 10 : event.altKey ? 0.1 : 1;
state._delta = deltaFn(factor);
this.start(event);
state._keyboardActive = true;
_maths_b2a210f4_esm_js__WEBPACK_IMPORTED_MODULE_0__[/* V */ "a"].addTo(state._movement, state._delta);
this.compute(event);
this.emit();
}
}
keyUp(event) {
if (!(event.key in KEYS_DELTA_MAP)) return;
this.state._keyboardActive = false;
this.setActive();
this.compute(event);
this.emit();
}
bind(bindFunction) {
const device = this.config.device;
bindFunction(device, 'start', this.pointerDown.bind(this));
if (this.config.pointerCapture) {
bindFunction(device, 'change', this.pointerMove.bind(this));
bindFunction(device, 'end', this.pointerUp.bind(this));
bindFunction(device, 'cancel', this.pointerUp.bind(this));
bindFunction('lostPointerCapture', '', this.pointerUp.bind(this));
}
bindFunction('key', 'down', this.keyDown.bind(this));
bindFunction('key', 'up', this.keyUp.bind(this));
if (this.config.filterTaps) {
bindFunction('click', '', this.pointerClick.bind(this), {
capture: true,
passive: false
});
}
}
}
function persistEvent(event) {
'persist' in event && typeof event.persist === 'function' && event.persist();
}
const isBrowser = typeof window !== 'undefined' && window.document && window.document.createElement;
function supportsTouchEvents() {
return isBrowser && 'ontouchstart' in window;
}
function isTouchScreen() {
return supportsTouchEvents() || isBrowser && window.navigator.maxTouchPoints > 1;
}
function supportsPointerEvents() {
return isBrowser && 'onpointerdown' in window;
}
function supportsPointerLock() {
return isBrowser && 'exitPointerLock' in window.document;
}
function supportsGestureEvents() {
try {
return 'constructor' in GestureEvent;
} catch (e) {
return false;
}
}
const SUPPORT = {
isBrowser,
gesture: supportsGestureEvents(),
touch: isTouchScreen(),
touchscreen: isTouchScreen(),
pointer: supportsPointerEvents(),
pointerLock: supportsPointerLock()
};
const DEFAULT_PREVENT_SCROLL_DELAY = 250;
const DEFAULT_DRAG_DELAY = 180;
const DEFAULT_SWIPE_VELOCITY = 0.5;
const DEFAULT_SWIPE_DISTANCE = 50;
const DEFAULT_SWIPE_DURATION = 250;
const DEFAULT_DRAG_AXIS_THRESHOLD = {
mouse: 0,
touch: 0,
pen: 8
};
const dragConfigResolver = _objectSpread2(_objectSpread2({}, coordinatesConfigResolver), {}, {
device(_v, _k, {
pointer: {
touch = false,
lock = false,
mouse = false
} = {}
}) {
this.pointerLock = lock && SUPPORT.pointerLock;
if (SUPPORT.touch && touch) return 'touch';
if (this.pointerLock) return 'mouse';
if (SUPPORT.pointer && !mouse) return 'pointer';
if (SUPPORT.touch) return 'touch';
return 'mouse';
},
preventScrollAxis(value, _k, {
preventScroll
}) {
this.preventScrollDelay = typeof preventScroll === 'number' ? preventScroll : preventScroll || preventScroll === undefined && value ? DEFAULT_PREVENT_SCROLL_DELAY : undefined;
if (!SUPPORT.touchscreen || preventScroll === false) return undefined;
return value ? value : preventScroll !== undefined ? 'y' : undefined;
},
pointerCapture(_v, _k, {
pointer: {
capture = true,
buttons = 1
} = {}
}) {
this.pointerButtons = buttons;
return !this.pointerLock && this.device === 'pointer' && capture;
},
threshold(value, _k, {
filterTaps = false,
tapsThreshold = 3,
axis = undefined
}) {
const threshold = _maths_b2a210f4_esm_js__WEBPACK_IMPORTED_MODULE_0__[/* V */ "a"].toVector(value, filterTaps ? tapsThreshold : axis ? 1 : 0);
this.filterTaps = filterTaps;
this.tapsThreshold = tapsThreshold;
return threshold;
},
swipe({
velocity = DEFAULT_SWIPE_VELOCITY,
distance = DEFAULT_SWIPE_DISTANCE,
duration = DEFAULT_SWIPE_DURATION
} = {}) {
return {
velocity: this.transform(_maths_b2a210f4_esm_js__WEBPACK_IMPORTED_MODULE_0__[/* V */ "a"].toVector(velocity)),
distance: this.transform(_maths_b2a210f4_esm_js__WEBPACK_IMPORTED_MODULE_0__[/* V */ "a"].toVector(distance)),
duration
};
},
delay(value = 0) {
switch (value) {
case true:
return DEFAULT_DRAG_DELAY;
case false:
return 0;
default:
return value;
}
},
axisThreshold(value) {
if (!value) return DEFAULT_DRAG_AXIS_THRESHOLD;
return _objectSpread2(_objectSpread2({}, DEFAULT_DRAG_AXIS_THRESHOLD), value);
}
});
if (false) {}
const SCALE_ANGLE_RATIO_INTENT_DEG = 30;
const PINCH_WHEEL_RATIO = 100;
class PinchEngine extends Engine {
constructor(...args) {
super(...args);
_defineProperty(this, "ingKey", 'pinching');
_defineProperty(this, "aliasKey", 'da');
}
init() {
this.state.offset = [1, 0];
this.state.lastOffset = [1, 0];
this.state._pointerEvents = new Map();
}
reset() {
super.reset();
const state = this.state;
state._touchIds = [];
state.canceled = false;
state.cancel = this.cancel.bind(this);
state.turns = 0;
}
computeOffset() {
const {
type,
movement,
lastOffset
} = this.state;
if (type === 'wheel') {
this.state.offset = _maths_b2a210f4_esm_js__WEBPACK_IMPORTED_MODULE_0__[/* V */ "a"].add(movement, lastOffset);
} else {
this.state.offset = [(1 + movement[0]) * lastOffset[0], movement[1] + lastOffset[1]];
}
}
computeMovement() {
const {
offset,
lastOffset
} = this.state;
this.state.movement = [offset[0] / lastOffset[0], offset[1] - lastOffset[1]];
}
axisIntent() {
const state = this.state;
const [_m0, _m1] = state._movement;
if (!state.axis) {
const axisMovementDifference = Math.abs(_m0) * SCALE_ANGLE_RATIO_INTENT_DEG - Math.abs(_m1);
if (axisMovementDifference < 0) state.axis = 'angle';else if (axisMovementDifference > 0) state.axis = 'scale';
}
}
restrictToAxis(v) {
if (this.config.lockDirection) {
if (this.state.axis === 'scale') v[1] = 0;else if (this.state.axis === 'angle') v[0] = 0;
}
}
cancel() {
const state = this.state;
if (state.canceled) return;
setTimeout(() => {
state.canceled = true;
state._active = false;
this.compute();
this.emit();
}, 0);
}
touchStart(event) {
this.ctrl.setEventIds(event);
const state = this.state;
const ctrlTouchIds = this.ctrl.touchIds;
if (state._active) {
if (state._touchIds.every(id => ctrlTouchIds.has(id))) return;
}
if (ctrlTouchIds.size < 2) return;
this.start(event);
state._touchIds = Array.from(ctrlTouchIds).slice(0, 2);
const payload = touchDistanceAngle(event, state._touchIds);
this.pinchStart(event, payload);
}
pointerStart(event) {
if (event.buttons != null && event.buttons % 2 !== 1) return;
this.ctrl.setEventIds(event);
event.target.setPointerCapture(event.pointerId);
const state = this.state;
const _pointerEvents = state._pointerEvents;
const ctrlPointerIds = this.ctrl.pointerIds;
if (state._active) {
if (Array.from(_pointerEvents.keys()).every(id => ctrlPointerIds.has(id))) return;
}
if (_pointerEvents.size < 2) {
_pointerEvents.set(event.pointerId, event);
}
if (state._pointerEvents.size < 2) return;
this.start(event);
const payload = distanceAngle(...Array.from(_pointerEvents.values()));
this.pinchStart(event, payload);
}
pinchStart(event, payload) {
const state = this.state;
state.origin = payload.origin;
this.computeValues([payload.distance, payload.angle]);
this.computeInitial();
this.compute(event);
this.emit();
}
touchMove(event) {
if (!this.state._active) return;
const payload = touchDistanceAngle(event, this.state._touchIds);
this.pinchMove(event, payload);
}
pointerMove(event) {
const _pointerEvents = this.state._pointerEvents;
if (_pointerEvents.has(event.pointerId)) {
_pointerEvents.set(event.pointerId, event);
}
if (!this.state._active) return;
const payload = distanceAngle(...Array.from(_pointerEvents.values()));
this.pinchMove(event, payload);
}
pinchMove(event, payload) {
const state = this.state;
const prev_a = state._values[1];
const delta_a = payload.angle - prev_a;
let delta_turns = 0;
if (Math.abs(delta_a) > 270) delta_turns += Math.sign(delta_a);
this.computeValues([payload.distance, payload.angle - 360 * delta_turns]);
state.origin = payload.origin;
state.turns = delta_turns;
state._movement = [state._values[0] / state._initial[0] - 1, state._values[1] - state._initial[1]];
this.compute(event);
this.emit();
}
touchEnd(event) {
this.ctrl.setEventIds(event);
if (!this.state._active) return;
if (this.state._touchIds.some(id => !this.ctrl.touchIds.has(id))) {
this.state._active = false;
this.compute(event);
this.emit();
}
}
pointerEnd(event) {
const state = this.state;
this.ctrl.setEventIds(event);
try {
event.target.releasePointerCapture(event.pointerId);
} catch (_unused) {}
if (state._pointerEvents.has(event.pointerId)) {
state._pointerEvents.delete(event.pointerId);
}
if (!state._active) return;
if (state._pointerEvents.size < 2) {
state._active = false;
this.compute(event);
this.emit();
}
}
gestureStart(event) {
if (event.cancelable) event.preventDefault();
const state = this.state;
if (state._active) return;
this.start(event);
this.computeValues([event.scale, event.rotation]);
state.origin = [event.clientX, event.clientY];
this.compute(event);
this.emit();
}
gestureMove(event) {
if (event.cancelable) event.preventDefault();
if (!this.state._active) return;
const state = this.state;
this.computeValues([event.scale, event.rotation]);
state.origin = [event.clientX, event.clientY];
const _previousMovement = state._movement;
state._movement = [event.scale - 1, event.rotation];
state._delta = _maths_b2a210f4_esm_js__WEBPACK_IMPORTED_MODULE_0__[/* V */ "a"].sub(state._movement, _previousMovement);
this.compute(event);
this.emit();
}
gestureEnd(event) {
if (!this.state._active) return;
this.state._active = false;
this.compute(event);
this.emit();
}
wheel(event) {
const modifierKey = this.config.modifierKey;
if (modifierKey && !event[modifierKey]) return;
if (!this.state._active) this.wheelStart(event);else this.wheelChange(event);
this.timeoutStore.add('wheelEnd', this.wheelEnd.bind(this));
}
wheelStart(event) {
this.start(event);
this.wheelChange(event);
}
wheelChange(event) {
const isR3f = ('uv' in event);
if (!isR3f) {
if (event.cancelable) {
event.preventDefault();
}
if (false) {}
}
const state = this.state;
state._delta = [-wheelValues(event)[1] / PINCH_WHEEL_RATIO * state.offset[0], 0];
_maths_b2a210f4_esm_js__WEBPACK_IMPORTED_MODULE_0__[/* V */ "a"].addTo(state._movement, state._delta);
this.state.origin = [event.clientX, event.clientY];
this.compute(event);
this.emit();
}
wheelEnd() {
if (!this.state._active) return;
this.state._active = false;
this.compute();
this.emit();
}
bind(bindFunction) {
const device = this.config.device;
if (!!device) {
bindFunction(device, 'start', this[device + 'Start'].bind(this));
bindFunction(device, 'change', this[device + 'Move'].bind(this));
bindFunction(device, 'end', this[device + 'End'].bind(this));
bindFunction(device, 'cancel', this[device + 'End'].bind(this));
} else {
bindFunction('wheel', '', this.wheel.bind(this), {
passive: false
});
}
}
}
const pinchConfigResolver = _objectSpread2(_objectSpread2({}, commonConfigResolver), {}, {
device(_v, _k, {
shared,
pointer: {
touch = false
} = {}
}) {
const sharedConfig = shared;
if (sharedConfig.target && !SUPPORT.touch && SUPPORT.gesture) return 'gesture';
if (SUPPORT.touch && touch) return 'touch';
if (SUPPORT.touchscreen) {
if (SUPPORT.pointer) return 'pointer';
if (SUPPORT.touch) return 'touch';
}
},
bounds(_v, _k, {
scaleBounds = {},
angleBounds = {}
}) {
const _scaleBounds = state => {
const D = assignDefault(call(scaleBounds, state), {
min: -Infinity,
max: Infinity
});
return [D.min, D.max];
};
const _angleBounds = state => {
const A = assignDefault(call(angleBounds, state), {
min: -Infinity,
max: Infinity
});
return [A.min, A.max];
};
if (typeof scaleBounds !== 'function' && typeof angleBounds !== 'function') return [_scaleBounds(), _angleBounds()];
return state => [_scaleBounds(state), _angleBounds(state)];
},
threshold(value, _k, config) {
this.lockDirection = config.axis === 'lock';
const threshold = _maths_b2a210f4_esm_js__WEBPACK_IMPORTED_MODULE_0__[/* V */ "a"].toVector(value, this.lockDirection ? [0.1, 3] : 0);
return threshold;
},
modifierKey(value) {
if (value === undefined) return 'ctrlKey';
return value;
}
});
class MoveEngine extends CoordinatesEngine {
constructor(...args) {
super(...args);
_defineProperty(this, "ingKey", 'moving');
}
move(event) {
if (this.config.mouseOnly && event.pointerType !== 'mouse') return;
if (!this.state._active) this.moveStart(event);else this.moveChange(event);
this.timeoutStore.add('moveEnd', this.moveEnd.bind(this));
}
moveStart(event) {
this.start(event);
this.computeValues(pointerValues(event));
this.compute(event);
this.computeInitial();
this.emit();
}
moveChange(event) {
if (!this.state._active) return;
const values = pointerValues(event);
const state = this.state;
state._delta = _maths_b2a210f4_esm_js__WEBPACK_IMPORTED_MODULE_0__[/* V */ "a"].sub(values, state._values);
_maths_b2a210f4_esm_js__WEBPACK_IMPORTED_MODULE_0__[/* V */ "a"].addTo(state._movement, state._delta);
this.computeValues(values);
this.compute(event);
this.emit();
}
moveEnd(event) {
if (!this.state._active) return;
this.state._active = false;
this.compute(event);
this.emit();
}
bind(bindFunction) {
bindFunction('pointer', 'change', this.move.bind(this));
bindFunction('pointer', 'leave', this.moveEnd.bind(this));
}
}
const moveConfigResolver = _objectSpread2(_objectSpread2({}, coordinatesConfigResolver), {}, {
mouseOnly: (value = true) => value
});
class ScrollEngine extends CoordinatesEngine {
constructor(...args) {
super(...args);
_defineProperty(this, "ingKey", 'scrolling');
}
scroll(event) {
if (!this.state._active) this.start(event);
this.scrollChange(event);
this.timeoutStore.add('scrollEnd', this.scrollEnd.bind(this));
}
scrollChange(event) {
if (event.cancelable) event.preventDefault();
const state = this.state;
const values = scrollValues(event);
state._delta = _maths_b2a210f4_esm_js__WEBPACK_IMPORTED_MODULE_0__[/* V */ "a"].sub(values, state._values);
_maths_b2a210f4_esm_js__WEBPACK_IMPORTED_MODULE_0__[/* V */ "a"].addTo(state._movement, state._delta);
this.computeValues(values);
this.compute(event);
this.emit();
}
scrollEnd() {
if (!this.state._active) return;
this.state._active = false;
this.compute();
this.emit();
}
bind(bindFunction) {
bindFunction('scroll', '', this.scroll.bind(this));
}
}
const scrollConfigResolver = coordinatesConfigResolver;
class WheelEngine extends CoordinatesEngine {
constructor(...args) {
super(...args);
_defineProperty(this, "ingKey", 'wheeling');
}
wheel(event) {
if (!this.state._active) this.start(event);
this.wheelChange(event);
this.timeoutStore.add('wheelEnd', this.wheelEnd.bind(this));
}
wheelChange(event) {
const state = this.state;
state._delta = wheelValues(event);
_maths_b2a210f4_esm_js__WEBPACK_IMPORTED_MODULE_0__[/* V */ "a"].addTo(state._movement, state._delta);
const [ox, oy] = state.overflow;
const [dx, dy] = state._delta;
const [dirx, diry] = state._direction;
if (ox < 0 && dx > 0 && dirx < 0 || ox > 0 && dx < 0 && dirx > 0) {
state._movement[0] = state._movementBound[0];
}
if (oy < 0 && dy > 0 && diry < 0 || oy > 0 && dy < 0 && diry > 0) {
state._movement[1] = state._movementBound[1];
}
this.compute(event);
this.emit();
}
wheelEnd() {
if (!this.state._active) return;
this.state._active = false;
this.compute();
this.emit();
}
bind(bindFunction) {
bindFunction('wheel', '', this.wheel.bind(this));
}
}
const wheelConfigResolver = coordinatesConfigResolver;
class HoverEngine extends CoordinatesEngine {
constructor(...args) {
super(...args);
_defineProperty(this, "ingKey", 'hovering');
}
enter(event) {
if (this.config.mouseOnly && event.pointerType !== 'mouse') return;
this.start(event);
this.computeValues(pointerValues(event));
this.compute(event);
this.emit();
}
leave(event) {
if (this.config.mouseOnly && event.pointerType !== 'mouse') return;
const state = this.state;
if (!state._active) return;
state._active = false;
const values = pointerValues(event);
state._movement = state._delta = _maths_b2a210f4_esm_js__WEBPACK_IMPORTED_MODULE_0__[/* V */ "a"].sub(values, state._values);
this.computeValues(values);
this.compute(event);
state.delta = state.movement;
this.emit();
}
bind(bindFunction) {
bindFunction('pointer', 'enter', this.enter.bind(this));
bindFunction('pointer', 'leave', this.leave.bind(this));
}
}
const hoverConfigResolver = _objectSpread2(_objectSpread2({}, coordinatesConfigResolver), {}, {
mouseOnly: (value = true) => value
});
const EngineMap = new Map();
const ConfigResolverMap = new Map();
function registerAction(action) {
EngineMap.set(action.key, action.engine);
ConfigResolverMap.set(action.key, action.resolver);
}
const dragAction = {
key: 'drag',
engine: DragEngine,
resolver: dragConfigResolver
};
const hoverAction = {
key: 'hover',
engine: HoverEngine,
resolver: hoverConfigResolver
};
const moveAction = {
key: 'move',
engine: MoveEngine,
resolver: moveConfigResolver
};
const pinchAction = {
key: 'pinch',
engine: PinchEngine,
resolver: pinchConfigResolver
};
const scrollAction = {
key: 'scroll',
engine: ScrollEngine,
resolver: scrollConfigResolver
};
const wheelAction = {
key: 'wheel',
engine: WheelEngine,
resolver: wheelConfigResolver
};
/***/ }),
/* 2 */
/***/ (function(module, __webpack_exports__, __webpack_require__) {
"use strict";
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "a", function() { return V; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "b", function() { return computeRubberband; });
/* unused harmony export r */
function clamp(v, min, max) {
return Math.max(min, Math.min(v, max));
}
const V = {
toVector(v, fallback) {
if (v === undefined) v = fallback;
return Array.isArray(v) ? v : [v, v];
},
add(v1, v2) {
return [v1[0] + v2[0], v1[1] + v2[1]];
},
sub(v1, v2) {
return [v1[0] - v2[0], v1[1] - v2[1]];
},
addTo(v1, v2) {
v1[0] += v2[0];
v1[1] += v2[1];
},
subTo(v1, v2) {
v1[0] -= v2[0];
v1[1] -= v2[1];
}
};
function rubberband(distance, dimension, constant) {
if (dimension === 0 || Math.abs(dimension) === Infinity) return Math.pow(distance, constant * 5);
return distance * dimension * constant / (dimension + constant * distance);
}
function rubberbandIfOutOfBounds(position, min, max, constant = 0.15) {
if (constant === 0) return clamp(position, min, max);
if (position < min) return -rubberband(min - position, max - min, constant)