diff --git a/.yalc/react-map-interaction/.yalcignore b/.yalc/react-map-interaction/.yalcignore new file mode 100644 index 0000000..218e8ba --- /dev/null +++ b/.yalc/react-map-interaction/.yalcignore @@ -0,0 +1,13 @@ +/.storybook +/example +/src +/stories +.babelrc +.gitignore +.mocharc.json +.nvmrc +*.md +*.sh +example.gif +mochaTestSetup.js +webpack.config.js \ No newline at end of file diff --git a/.yalc/react-map-interaction/dist/react-map-interaction.js b/.yalc/react-map-interaction/dist/react-map-interaction.js new file mode 100644 index 0000000..61e2318 --- /dev/null +++ b/.yalc/react-map-interaction/dist/react-map-interaction.js @@ -0,0 +1,1037 @@ +(function webpackUniversalModuleDefinition(root, factory) { + if(typeof exports === 'object' && typeof module === 'object') + module.exports = factory(require("prop-types"), require("react")); + else if(typeof define === 'function' && define.amd) + define(["prop-types", "React"], factory); + else if(typeof exports === 'object') + exports["ReactMapInteraction"] = factory(require("prop-types"), require("react")); + else + root["ReactMapInteraction"] = factory(root["PropTypes"], root["React"]); +})(this, function(__WEBPACK_EXTERNAL_MODULE__0__, __WEBPACK_EXTERNAL_MODULE__1__) { +return /******/ (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 = 2); +/******/ }) +/************************************************************************/ +/******/ ([ +/* 0 */ +/***/ (function(module, exports) { + +module.exports = __WEBPACK_EXTERNAL_MODULE__0__; + +/***/ }), +/* 1 */ +/***/ (function(module, exports) { + +module.exports = __WEBPACK_EXTERNAL_MODULE__1__; + +/***/ }), +/* 2 */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +// ESM COMPAT FLAG +__webpack_require__.r(__webpack_exports__); + +// EXPORTS +__webpack_require__.d(__webpack_exports__, "MapInteractionCSS", function() { return /* reexport */ src_MapInteractionCSS; }); +__webpack_require__.d(__webpack_exports__, "MapInteraction", function() { return /* reexport */ MapInteraction; }); + +// EXTERNAL MODULE: external {"commonjs":"react","commonjs2":"react","amd":"React","root":"React"} +var external_commonjs_react_commonjs2_react_amd_React_root_React_ = __webpack_require__(1); +var external_commonjs_react_commonjs2_react_amd_React_root_React_default = /*#__PURE__*/__webpack_require__.n(external_commonjs_react_commonjs2_react_amd_React_root_React_); + +// EXTERNAL MODULE: external {"commonjs":"prop-types","commonjs2":"prop-types","commonj2s":"prop-types","amd":"prop-types","root":"PropTypes"} +var external_commonjs_prop_types_commonjs2_prop_types_commonj2s_prop_types_amd_prop_types_root_PropTypes_ = __webpack_require__(0); +var external_commonjs_prop_types_commonjs2_prop_types_commonj2s_prop_types_amd_prop_types_root_PropTypes_default = /*#__PURE__*/__webpack_require__.n(external_commonjs_prop_types_commonjs2_prop_types_commonj2s_prop_types_amd_prop_types_root_PropTypes_); + +// CONCATENATED MODULE: ./src/Controls.jsx +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 _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function"); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, writable: true, configurable: true } }); if (superClass) _setPrototypeOf(subClass, superClass); } + +function _setPrototypeOf(o, p) { _setPrototypeOf = Object.setPrototypeOf || function _setPrototypeOf(o, p) { o.__proto__ = p; return o; }; return _setPrototypeOf(o, p); } + +function _createSuper(Derived) { var hasNativeReflectConstruct = _isNativeReflectConstruct(); return function _createSuperInternal() { var Super = _getPrototypeOf(Derived), result; if (hasNativeReflectConstruct) { var NewTarget = _getPrototypeOf(this).constructor; result = Reflect.construct(Super, arguments, NewTarget); } else { result = Super.apply(this, arguments); } return _possibleConstructorReturn(this, result); }; } + +function _possibleConstructorReturn(self, call) { if (call && (_typeof(call) === "object" || typeof call === "function")) { return call; } return _assertThisInitialized(self); } + +function _assertThisInitialized(self) { if (self === void 0) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return self; } + +function _isNativeReflectConstruct() { if (typeof Reflect === "undefined" || !Reflect.construct) return false; if (Reflect.construct.sham) return false; if (typeof Proxy === "function") return true; try { Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function () {})); return true; } catch (e) { return false; } } + +function _getPrototypeOf(o) { _getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf : function _getPrototypeOf(o) { return o.__proto__ || Object.getPrototypeOf(o); }; return _getPrototypeOf(o); } + + + + +var Controls_Controls = /*#__PURE__*/function (_Component) { + _inherits(Controls, _Component); + + var _super = _createSuper(Controls); + + function Controls() { + _classCallCheck(this, Controls); + + return _super.apply(this, arguments); + } + + _createClass(Controls, [{ + key: "render", + value: function render() { + var _this = this; + + var _this$props = this.props, + plusBtnContents = _this$props.plusBtnContents, + minusBtnContents = _this$props.minusBtnContents, + btnClass = _this$props.btnClass, + plusBtnClass = _this$props.plusBtnClass, + minusBtnClass = _this$props.minusBtnClass, + controlsClass = _this$props.controlsClass, + scale = _this$props.scale, + minScale = _this$props.minScale, + maxScale = _this$props.maxScale, + onClickPlus = _this$props.onClickPlus, + onClickMinus = _this$props.onClickMinus, + disableZoom = _this$props.disableZoom; + var btnStyle = { + width: 30, + paddingTop: 5, + marginBottom: 5 + }; + var controlsStyle = controlsClass ? undefined : { + position: 'absolute', + right: 10, + top: 10 + }; + + function plusHandler(e) { + e.preventDefault(); + e.target.blur(); + if (disableZoom) return; + onClickPlus(); + } + + function minusHandler(e) { + e.preventDefault(); + e.target.blur(); + if (disableZoom) return; + onClickMinus(); + } + + return /*#__PURE__*/external_commonjs_react_commonjs2_react_amd_React_root_React_default.a.createElement("div", { + style: controlsStyle, + className: controlsClass + }, /*#__PURE__*/external_commonjs_react_commonjs2_react_amd_React_root_React_default.a.createElement("div", null, /*#__PURE__*/external_commonjs_react_commonjs2_react_amd_React_root_React_default.a.createElement("button", { + ref: function ref(node) { + _this.plusNode = node; + }, + onClick: plusHandler, + onTouchEnd: plusHandler, + className: [btnClass ? btnClass : '', plusBtnClass ? plusBtnClass : ''].join(' '), + type: "button", + style: btnClass || plusBtnClass ? undefined : btnStyle, + disabled: disableZoom || scale >= maxScale + }, plusBtnContents)), /*#__PURE__*/external_commonjs_react_commonjs2_react_amd_React_root_React_default.a.createElement("div", null, /*#__PURE__*/external_commonjs_react_commonjs2_react_amd_React_root_React_default.a.createElement("button", { + ref: function ref(node) { + _this.minusNode = node; + }, + onClick: minusHandler, + onTouchEnd: minusHandler, + className: [btnClass ? btnClass : '', minusBtnClass ? minusBtnClass : ''].join(' '), + type: "button", + style: btnClass || minusBtnClass ? undefined : btnStyle, + disabled: disableZoom || scale <= minScale + }, minusBtnContents))); + } + }]); + + return Controls; +}(external_commonjs_react_commonjs2_react_amd_React_root_React_["Component"]); + +Controls_Controls.propTypes = { + onClickPlus: external_commonjs_prop_types_commonjs2_prop_types_commonj2s_prop_types_amd_prop_types_root_PropTypes_default.a.func.isRequired, + onClickMinus: external_commonjs_prop_types_commonjs2_prop_types_commonj2s_prop_types_amd_prop_types_root_PropTypes_default.a.func.isRequired, + plusBtnContents: external_commonjs_prop_types_commonjs2_prop_types_commonj2s_prop_types_amd_prop_types_root_PropTypes_default.a.node, + minusBtnContents: external_commonjs_prop_types_commonjs2_prop_types_commonj2s_prop_types_amd_prop_types_root_PropTypes_default.a.node, + btnClass: external_commonjs_prop_types_commonjs2_prop_types_commonj2s_prop_types_amd_prop_types_root_PropTypes_default.a.string, + plusBtnClass: external_commonjs_prop_types_commonjs2_prop_types_commonj2s_prop_types_amd_prop_types_root_PropTypes_default.a.string, + minusBtnClass: external_commonjs_prop_types_commonjs2_prop_types_commonj2s_prop_types_amd_prop_types_root_PropTypes_default.a.string, + controlsClass: external_commonjs_prop_types_commonjs2_prop_types_commonj2s_prop_types_amd_prop_types_root_PropTypes_default.a.string, + scale: external_commonjs_prop_types_commonjs2_prop_types_commonj2s_prop_types_amd_prop_types_root_PropTypes_default.a.number, + minScale: external_commonjs_prop_types_commonjs2_prop_types_commonj2s_prop_types_amd_prop_types_root_PropTypes_default.a.number, + maxScale: external_commonjs_prop_types_commonjs2_prop_types_commonj2s_prop_types_amd_prop_types_root_PropTypes_default.a.number, + disableZoom: external_commonjs_prop_types_commonjs2_prop_types_commonj2s_prop_types_amd_prop_types_root_PropTypes_default.a.bool +}; +Controls_Controls.defaultProps = { + plusBtnContents: '+', + minusBtnContents: '-', + disableZoom: false +}; +/* harmony default export */ var src_Controls = (Controls_Controls); +// CONCATENATED MODULE: ./src/geometry.js +function clamp(min, value, max) { + return Math.max(min, Math.min(value, max)); +} + +function distance(p1, p2) { + var dx = p1.x - p2.x; + var dy = p1.y - p2.y; + return Math.sqrt(Math.pow(dx, 2) + Math.pow(dy, 2)); +} + +function midpoint(p1, p2) { + return { + x: (p1.x + p2.x) / 2, + y: (p1.y + p2.y) / 2 + }; +} + +function touchPt(touch) { + return { + x: touch.clientX, + y: touch.clientY + }; +} + +function touchDistance(t0, t1) { + var p0 = touchPt(t0); + var p1 = touchPt(t1); + return distance(p0, p1); +} + + +// CONCATENATED MODULE: ./src/makePassiveEventOption.js +// We want to make event listeners non-passive, and to do so have to check +// that browsers support EventListenerOptions in the first place. +// https://developer.mozilla.org/en-US/docs/Web/API/EventTarget/addEventListener#Safely_detecting_option_support +var passiveSupported = false; + +try { + var options = { + get passive() { + passiveSupported = true; + } + + }; + window.addEventListener("test", options, options); + window.removeEventListener("test", options, options); +} catch (_unused) { + passiveSupported = false; +} + +function makePassiveEventOption(passive) { + return passiveSupported ? { + passive: passive + } : passive; +} + +/* harmony default export */ var src_makePassiveEventOption = (makePassiveEventOption); +// CONCATENATED MODULE: ./src/MapInteraction.jsx +function MapInteraction_typeof(obj) { "@babel/helpers - typeof"; if (typeof Symbol === "function" && typeof Symbol.iterator === "symbol") { MapInteraction_typeof = function _typeof(obj) { return typeof obj; }; } else { MapInteraction_typeof = function _typeof(obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }; } return MapInteraction_typeof(obj); } + +function _extends() { _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; }; return _extends.apply(this, arguments); } + +function _objectWithoutProperties(source, excluded) { if (source == null) return {}; var target = _objectWithoutPropertiesLoose(source, excluded); var key, i; if (Object.getOwnPropertySymbols) { var sourceSymbolKeys = Object.getOwnPropertySymbols(source); for (i = 0; i < sourceSymbolKeys.length; i++) { key = sourceSymbolKeys[i]; if (excluded.indexOf(key) >= 0) continue; if (!Object.prototype.propertyIsEnumerable.call(source, key)) continue; target[key] = source[key]; } } return target; } + +function _objectWithoutPropertiesLoose(source, excluded) { if (source == null) return {}; var target = {}; var sourceKeys = Object.keys(source); var key, i; for (i = 0; i < sourceKeys.length; i++) { key = sourceKeys[i]; if (excluded.indexOf(key) >= 0) continue; target[key] = source[key]; } return target; } + +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 MapInteraction_classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } + +function MapInteraction_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 MapInteraction_createClass(Constructor, protoProps, staticProps) { if (protoProps) MapInteraction_defineProperties(Constructor.prototype, protoProps); if (staticProps) MapInteraction_defineProperties(Constructor, staticProps); return Constructor; } + +function MapInteraction_inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function"); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, writable: true, configurable: true } }); if (superClass) MapInteraction_setPrototypeOf(subClass, superClass); } + +function MapInteraction_setPrototypeOf(o, p) { MapInteraction_setPrototypeOf = Object.setPrototypeOf || function _setPrototypeOf(o, p) { o.__proto__ = p; return o; }; return MapInteraction_setPrototypeOf(o, p); } + +function MapInteraction_createSuper(Derived) { var hasNativeReflectConstruct = MapInteraction_isNativeReflectConstruct(); return function _createSuperInternal() { var Super = MapInteraction_getPrototypeOf(Derived), result; if (hasNativeReflectConstruct) { var NewTarget = MapInteraction_getPrototypeOf(this).constructor; result = Reflect.construct(Super, arguments, NewTarget); } else { result = Super.apply(this, arguments); } return MapInteraction_possibleConstructorReturn(this, result); }; } + +function MapInteraction_possibleConstructorReturn(self, call) { if (call && (MapInteraction_typeof(call) === "object" || typeof call === "function")) { return call; } return MapInteraction_assertThisInitialized(self); } + +function MapInteraction_assertThisInitialized(self) { if (self === void 0) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return self; } + +function MapInteraction_isNativeReflectConstruct() { if (typeof Reflect === "undefined" || !Reflect.construct) return false; if (Reflect.construct.sham) return false; if (typeof Proxy === "function") return true; try { Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function () {})); return true; } catch (e) { return false; } } + +function MapInteraction_getPrototypeOf(o) { MapInteraction_getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf : function _getPrototypeOf(o) { return o.__proto__ || Object.getPrototypeOf(o); }; return MapInteraction_getPrototypeOf(o); } + + + + + + // The amount that a value of a dimension will change given a new scale + +var coordChange = function coordChange(coordinate, scaleRatio) { + return scaleRatio * coordinate - coordinate; +}; + +var translationShape = external_commonjs_prop_types_commonjs2_prop_types_commonj2s_prop_types_amd_prop_types_root_PropTypes_default.a.shape({ + x: external_commonjs_prop_types_commonjs2_prop_types_commonj2s_prop_types_amd_prop_types_root_PropTypes_default.a.number, + y: external_commonjs_prop_types_commonjs2_prop_types_commonj2s_prop_types_amd_prop_types_root_PropTypes_default.a.number +}); +/* + This contains logic for providing a map-like interaction to any DOM node. + It allows a user to pinch, zoom, translate, etc, as they would an interactive map. + It renders its children with the current state of the translation and does not do any scaling + or translating on its own. This works on both desktop, and mobile. +*/ + +var MapInteraction_MapInteractionControlled = /*#__PURE__*/function (_Component) { + MapInteraction_inherits(MapInteractionControlled, _Component); + + var _super = MapInteraction_createSuper(MapInteractionControlled); + + function MapInteractionControlled(props) { + var _this; + + MapInteraction_classCallCheck(this, MapInteractionControlled); + + _this = _super.call(this, props); + _this.state = { + shouldPreventTouchEndDefault: false + }; + _this.startPointerInfo = undefined; + _this.onMouseDown = _this.onMouseDown.bind(MapInteraction_assertThisInitialized(_this)); + _this.onTouchStart = _this.onTouchStart.bind(MapInteraction_assertThisInitialized(_this)); + _this.onMouseMove = _this.onMouseMove.bind(MapInteraction_assertThisInitialized(_this)); + _this.onTouchMove = _this.onTouchMove.bind(MapInteraction_assertThisInitialized(_this)); + _this.onMouseUp = _this.onMouseUp.bind(MapInteraction_assertThisInitialized(_this)); + _this.onTouchEnd = _this.onTouchEnd.bind(MapInteraction_assertThisInitialized(_this)); + _this.onWheel = _this.onWheel.bind(MapInteraction_assertThisInitialized(_this)); + return _this; + } + + MapInteraction_createClass(MapInteractionControlled, [{ + key: "componentDidMount", + value: function componentDidMount() { + var passiveOption = src_makePassiveEventOption(false); + this.getContainerNode().addEventListener('wheel', this.onWheel, passiveOption); + /* + Setup events for the gesture lifecycle: start, move, end touch + */ + // start gesture + + this.getContainerNode().addEventListener('touchstart', this.onTouchStart, passiveOption); + this.getContainerNode().addEventListener('mousedown', this.onMouseDown, passiveOption); // move gesture + + window.addEventListener('touchmove', this.onTouchMove, passiveOption); + window.addEventListener('mousemove', this.onMouseMove, passiveOption); // end gesture + + var touchAndMouseEndOptions = _objectSpread({ + capture: true + }, passiveOption); + + window.addEventListener('touchend', this.onTouchEnd, touchAndMouseEndOptions); + window.addEventListener('mouseup', this.onMouseUp, touchAndMouseEndOptions); + } + }, { + key: "componentWillUnmount", + value: function componentWillUnmount() { + this.getContainerNode().removeEventListener('wheel', this.onWheel); // Remove touch events + + this.getContainerNode().removeEventListener('touchstart', this.onTouchStart); + window.removeEventListener('touchmove', this.onTouchMove); + window.removeEventListener('touchend', this.onTouchEnd); // Remove mouse events + + this.getContainerNode().removeEventListener('mousedown', this.onMouseDown); + window.removeEventListener('mousemove', this.onMouseMove); + window.removeEventListener('mouseup', this.onMouseUp); + } + /* + Event handlers + All touch/mouse handlers preventDefault because we add + both touch and mouse handlers in the same session to support devicse + with both touch screen and mouse inputs. The browser may fire both + a touch and mouse event for a *single* user action, so we have to ensure + that only one handler is used by canceling the event in the first handler. + https://developer.mozilla.org/en-US/docs/Web/API/Touch_events/Supporting_both_TouchEvent_and_MouseEvent + */ + + }, { + key: "onMouseDown", + value: function onMouseDown(e) { + e.preventDefault(); + this.setPointerState([e]); + } + }, { + key: "onTouchStart", + value: function onTouchStart(e) { + e.preventDefault(); + this.setPointerState(e.touches); + } + }, { + key: "onMouseUp", + value: function onMouseUp(e) { + this.setPointerState(); + } + }, { + key: "onTouchEnd", + value: function onTouchEnd(e) { + this.setPointerState(e.touches); + } + }, { + key: "onMouseMove", + value: function onMouseMove(e) { + if (!this.startPointerInfo || this.props.disablePan) { + return; + } + + e.preventDefault(); + this.onDrag(e); + } + }, { + key: "onTouchMove", + value: function onTouchMove(e) { + if (!this.startPointerInfo) { + return; + } + + e.preventDefault(); + var _this$props = this.props, + disablePan = _this$props.disablePan, + disableZoom = _this$props.disableZoom; + var isPinchAction = e.touches.length == 2 && this.startPointerInfo.pointers.length > 1; + + if (isPinchAction && !disableZoom) { + this.scaleFromMultiTouch(e); + } else if (e.touches.length === 1 && this.startPointerInfo && !disablePan) { + this.onDrag(e.touches[0]); + } + } // handles both touch and mouse drags + + }, { + key: "onDrag", + value: function onDrag(pointer) { + var _this2 = this; + + var _this$startPointerInf = this.startPointerInfo, + translation = _this$startPointerInf.translation, + pointers = _this$startPointerInf.pointers; + var startPointer = pointers[0]; + var dragX = pointer.clientX - startPointer.clientX; + var dragY = pointer.clientY - startPointer.clientY; + var newTranslation = { + x: translation.x + dragX, + y: translation.y + dragY + }; + var shouldPreventTouchEndDefault = Math.abs(dragX) > 1 || Math.abs(dragY) > 1; + this.setState({ + shouldPreventTouchEndDefault: shouldPreventTouchEndDefault + }, function () { + _this2.props.onChange({ + scale: _this2.props.value.scale, + translation: _this2.clampTranslation(newTranslation) + }); + }); + } + }, { + key: "onWheel", + value: function onWheel(e) { + if (this.props.disableZoom) { + return; + } + + e.preventDefault(); + e.stopPropagation(); + var scaleChange = Math.pow(2, e.deltaY * 0.010); + var newScale = clamp(this.props.minScale, this.props.value.scale + (1 - scaleChange), this.props.maxScale); + var mousePos = this.clientPosToTranslatedPos({ + x: e.clientX, + y: e.clientY + }); + this.scaleFromPoint(newScale, mousePos); + } + }, { + key: "setPointerState", + value: function setPointerState(pointers) { + if (!pointers || pointers.length === 0) { + this.startPointerInfo = undefined; + return; + } + + this.startPointerInfo = { + pointers: pointers, + scale: this.props.value.scale, + translation: this.props.value.translation + }; + } + }, { + key: "clampTranslation", + value: function clampTranslation(desiredTranslation) { + var props = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : this.props; + var x = desiredTranslation.x, + y = desiredTranslation.y; + var _props$translationBou = props.translationBounds, + xMax = _props$translationBou.xMax, + xMin = _props$translationBou.xMin, + yMax = _props$translationBou.yMax, + yMin = _props$translationBou.yMin; + xMin = xMin != undefined ? xMin : -Infinity; + yMin = yMin != undefined ? yMin : -Infinity; + xMax = xMax != undefined ? xMax : Infinity; + yMax = yMax != undefined ? yMax : Infinity; + return { + x: clamp(xMin, x, xMax), + y: clamp(yMin, y, yMax) + }; + } + }, { + key: "translatedOrigin", + value: function translatedOrigin() { + var translation = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : this.props.value.translation; + var clientOffset = this.getContainerBoundingClientRect(); + return { + x: clientOffset.left + translation.x, + y: clientOffset.top + translation.y + }; + } // From a given screen point return it as a point + // in the coordinate system of the given translation + + }, { + key: "clientPosToTranslatedPos", + value: function clientPosToTranslatedPos(_ref) { + var x = _ref.x, + y = _ref.y; + var translation = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : this.props.value.translation; + var origin = this.translatedOrigin(translation); + return { + x: x - origin.x, + y: y - origin.y + }; + } + }, { + key: "scaleFromPoint", + value: function scaleFromPoint(newScale, focalPt) { + var _this$props$value = this.props.value, + translation = _this$props$value.translation, + scale = _this$props$value.scale; + var scaleRatio = newScale / (scale != 0 ? scale : 1); + var focalPtDelta = { + x: coordChange(focalPt.x, scaleRatio), + y: coordChange(focalPt.y, scaleRatio) + }; + var newTranslation = { + x: translation.x - focalPtDelta.x, + y: translation.y - focalPtDelta.y + }; + this.props.onChange({ + scale: newScale, + translation: this.clampTranslation(newTranslation) + }); + } // Given the start touches and new e.touches, scale and translate + // such that the initial midpoint remains as the new midpoint. This is + // to achieve the effect of keeping the content that was directly + // in the middle of the two fingers as the focal point throughout the zoom. + + }, { + key: "scaleFromMultiTouch", + value: function scaleFromMultiTouch(e) { + var startTouches = this.startPointerInfo.pointers; + var newTouches = e.touches; // calculate new scale + + var dist0 = touchDistance(startTouches[0], startTouches[1]); + var dist1 = touchDistance(newTouches[0], newTouches[1]); + var scaleChange = dist1 / dist0; + var startScale = this.startPointerInfo.scale; + var targetScale = startScale + (scaleChange - 1) * startScale; + var newScale = clamp(this.props.minScale, targetScale, this.props.maxScale); // calculate mid points + + var startMidpoint = midpoint(touchPt(startTouches[0]), touchPt(startTouches[1])); + var newMidPoint = midpoint(touchPt(newTouches[0]), touchPt(newTouches[1])); // The amount we need to translate by in order for + // the mid point to stay in the middle (before thinking about scaling factor) + + var dragDelta = { + x: newMidPoint.x - startMidpoint.x, + y: newMidPoint.y - startMidpoint.y + }; + var scaleRatio = newScale / startScale; // The point originally in the middle of the fingers on the initial zoom start + + var focalPt = this.clientPosToTranslatedPos(startMidpoint, this.startPointerInfo.translation); // The amount that the middle point has changed from this scaling + + var focalPtDelta = { + x: coordChange(focalPt.x, scaleRatio), + y: coordChange(focalPt.y, scaleRatio) + }; // Translation is the original translation, plus the amount we dragged, + // minus what the scaling will do to the focal point. Subtracting the + // scaling factor keeps the midpoint in the middle of the touch points. + + var newTranslation = { + x: this.startPointerInfo.translation.x - focalPtDelta.x + dragDelta.x, + y: this.startPointerInfo.translation.y - focalPtDelta.y + dragDelta.y + }; + this.props.onChange({ + scale: newScale, + translation: this.clampTranslation(newTranslation) + }); + } + }, { + key: "discreteScaleStepSize", + value: function discreteScaleStepSize() { + var _this$props2 = this.props, + minScale = _this$props2.minScale, + maxScale = _this$props2.maxScale; + var delta = Math.abs(maxScale - minScale); + return delta / 10; + } // Scale using the center of the content as a focal point + + }, { + key: "changeScale", + value: function changeScale(delta) { + var targetScale = this.props.value.scale + delta; + var _this$props3 = this.props, + minScale = _this$props3.minScale, + maxScale = _this$props3.maxScale; + var scale = clamp(minScale, targetScale, maxScale); + var rect = this.getContainerBoundingClientRect(); + var x = rect.left + rect.width / 2; + var y = rect.top + rect.height / 2; + var focalPoint = this.clientPosToTranslatedPos({ + x: x, + y: y + }); + this.scaleFromPoint(scale, focalPoint); + } // Done like this so it is mockable + + }, { + key: "getContainerNode", + value: function getContainerNode() { + return this.containerNode; + } + }, { + key: "getContainerBoundingClientRect", + value: function getContainerBoundingClientRect() { + return this.getContainerNode().getBoundingClientRect(); + } + }, { + key: "renderControls", + value: function renderControls() { + var _this3 = this; + + var step = this.discreteScaleStepSize(); + return /*#__PURE__*/external_commonjs_react_commonjs2_react_amd_React_root_React_default.a.createElement(src_Controls, { + onClickPlus: function onClickPlus() { + return _this3.changeScale(step); + }, + onClickMinus: function onClickMinus() { + return _this3.changeScale(-step); + }, + plusBtnContents: this.props.plusBtnContents, + minusBtnContents: this.props.minusBtnContents, + btnClass: this.props.btnClass, + plusBtnClass: this.props.plusBtnClass, + minusBtnClass: this.props.minusBtnClass, + controlsClass: this.props.controlsClass, + scale: this.props.value.scale, + minScale: this.props.minScale, + maxScale: this.props.maxScale, + disableZoom: this.props.disableZoom + }); + } + }, { + key: "render", + value: function render() { + var _this4 = this; + + var _this$props4 = this.props, + showControls = _this$props4.showControls, + children = _this$props4.children; + var scale = this.props.value.scale; // Defensively clamp the translation. This should not be necessary if we properly set state elsewhere. + + var translation = this.clampTranslation(this.props.value.translation); + /* + This is a little trick to allow the following ux: We want the parent of this + component to decide if elements inside the map are clickable. Normally, you wouldn't + want to trigger a click event when the user *drags* on an element (only if they click + and then release w/o dragging at all). However we don't want to assume this + behavior here, so we call `preventDefault` and then let the parent check + `e.defaultPrevented`. That value being true means that we are signalling that + a drag event ended, not a click. + */ + + var handleEventCapture = function handleEventCapture(e) { + if (_this4.state.shouldPreventTouchEndDefault) { + e.preventDefault(); + + _this4.setState({ + shouldPreventTouchEndDefault: false + }); + } + }; + + return /*#__PURE__*/external_commonjs_react_commonjs2_react_amd_React_root_React_default.a.createElement("div", { + ref: function ref(node) { + _this4.containerNode = node; + }, + style: { + height: '100%', + width: '100%', + position: 'relative', + // for absolutely positioned children + touchAction: 'none' + }, + onClickCapture: handleEventCapture, + onTouchEndCapture: handleEventCapture + }, (children || undefined) && children({ + translation: translation, + scale: scale + }), (showControls || undefined) && this.renderControls()); + } + }], [{ + key: "propTypes", + get: function get() { + return { + // The content that will be transformed + children: external_commonjs_prop_types_commonjs2_prop_types_commonj2s_prop_types_amd_prop_types_root_PropTypes_default.a.func, + // This is a controlled component + value: external_commonjs_prop_types_commonjs2_prop_types_commonj2s_prop_types_amd_prop_types_root_PropTypes_default.a.shape({ + scale: external_commonjs_prop_types_commonjs2_prop_types_commonj2s_prop_types_amd_prop_types_root_PropTypes_default.a.number.isRequired, + translation: translationShape.isRequired + }).isRequired, + onChange: external_commonjs_prop_types_commonjs2_prop_types_commonj2s_prop_types_amd_prop_types_root_PropTypes_default.a.func.isRequired, + disableZoom: external_commonjs_prop_types_commonjs2_prop_types_commonj2s_prop_types_amd_prop_types_root_PropTypes_default.a.bool, + disablePan: external_commonjs_prop_types_commonjs2_prop_types_commonj2s_prop_types_amd_prop_types_root_PropTypes_default.a.bool, + translationBounds: external_commonjs_prop_types_commonjs2_prop_types_commonj2s_prop_types_amd_prop_types_root_PropTypes_default.a.shape({ + xMin: external_commonjs_prop_types_commonjs2_prop_types_commonj2s_prop_types_amd_prop_types_root_PropTypes_default.a.number, + xMax: external_commonjs_prop_types_commonjs2_prop_types_commonj2s_prop_types_amd_prop_types_root_PropTypes_default.a.number, + yMin: external_commonjs_prop_types_commonjs2_prop_types_commonj2s_prop_types_amd_prop_types_root_PropTypes_default.a.number, + yMax: external_commonjs_prop_types_commonjs2_prop_types_commonj2s_prop_types_amd_prop_types_root_PropTypes_default.a.number + }), + minScale: external_commonjs_prop_types_commonjs2_prop_types_commonj2s_prop_types_amd_prop_types_root_PropTypes_default.a.number, + maxScale: external_commonjs_prop_types_commonjs2_prop_types_commonj2s_prop_types_amd_prop_types_root_PropTypes_default.a.number, + showControls: external_commonjs_prop_types_commonjs2_prop_types_commonj2s_prop_types_amd_prop_types_root_PropTypes_default.a.bool, + plusBtnContents: external_commonjs_prop_types_commonjs2_prop_types_commonj2s_prop_types_amd_prop_types_root_PropTypes_default.a.node, + minusBtnContents: external_commonjs_prop_types_commonjs2_prop_types_commonj2s_prop_types_amd_prop_types_root_PropTypes_default.a.node, + btnClass: external_commonjs_prop_types_commonjs2_prop_types_commonj2s_prop_types_amd_prop_types_root_PropTypes_default.a.string, + plusBtnClass: external_commonjs_prop_types_commonjs2_prop_types_commonj2s_prop_types_amd_prop_types_root_PropTypes_default.a.string, + minusBtnClass: external_commonjs_prop_types_commonjs2_prop_types_commonj2s_prop_types_amd_prop_types_root_PropTypes_default.a.string, + controlsClass: external_commonjs_prop_types_commonjs2_prop_types_commonj2s_prop_types_amd_prop_types_root_PropTypes_default.a.string + }; + } + }, { + key: "defaultProps", + get: function get() { + return { + minScale: 0.05, + maxScale: 3, + showControls: false, + translationBounds: {}, + disableZoom: false, + disablePan: false + }; + } + }]); + + return MapInteractionControlled; +}(external_commonjs_react_commonjs2_react_amd_React_root_React_["Component"]); +/* + Main entry point component. + Determines if it's parent is controlling (eg it manages state) or leaving us uncontrolled + (eg we manage our own internal state) +*/ + +var MapInteraction_MapInteractionController = /*#__PURE__*/function (_Component2) { + MapInteraction_inherits(MapInteractionController, _Component2); + + var _super2 = MapInteraction_createSuper(MapInteractionController); + + function MapInteractionController(props) { + var _this5; + + MapInteraction_classCallCheck(this, MapInteractionController); + + _this5 = _super2.call(this, props); + var controlled = MapInteractionController.isControlled(props); + + if (controlled) { + _this5.state = { + lastKnownValueFromProps: props.value + }; + } else { + // Set the necessary state for controlling map interaction ourselves + _this5.state = { + value: props.defaultValue || { + scale: 1, + translation: { + x: 0, + y: 0 + } + }, + lastKnownValueFromProps: undefined + }; + } + + return _this5; + } + /* + Handle the parent switchg form controlled to uncontrolled or vice versa. + This is at most a best-effort attempt. It is not gauranteed by our API + but it will do its best to maintain the state such that if the parent + accidentally switches between controlled/uncontrolled there won't be + any jankiness or jumpiness. + This tries to mimick how the React component behaves. + */ + + + MapInteraction_createClass(MapInteractionController, [{ + key: "innerProps", + value: // The subset of this component's props that need to be passed + // down to the core RMI component + function innerProps() { + var _this$props5 = this.props, + value = _this$props5.value, + defaultValue = _this$props5.defaultValue, + onChange = _this$props5.onChange, + innerProps = _objectWithoutProperties(_this$props5, ["value", "defaultValue", "onChange"]); + + return innerProps; + } + }, { + key: "getValue", + value: function getValue() { + var controlled = MapInteractionController.isControlled(this.props); + return controlled ? this.props.value : this.state.value; + } + }, { + key: "render", + value: function render() { + var _this6 = this; + + var _this$props6 = this.props, + _onChange = _this$props6.onChange, + children = _this$props6.children; + var controlled = MapInteractionController.isControlled(this.props); + var value = controlled ? this.props.value : this.state.value; + return /*#__PURE__*/external_commonjs_react_commonjs2_react_amd_React_root_React_default.a.createElement(MapInteraction_MapInteractionControlled, _extends({ + onChange: function onChange(value) { + controlled ? _onChange(value) : _this6.setState({ + value: value + }); + }, + value: value + }, this.innerProps()), children); + } + }], [{ + key: "propTypes", + get: function get() { + return { + children: external_commonjs_prop_types_commonjs2_prop_types_commonj2s_prop_types_amd_prop_types_root_PropTypes_default.a.func, + value: external_commonjs_prop_types_commonjs2_prop_types_commonj2s_prop_types_amd_prop_types_root_PropTypes_default.a.shape({ + scale: external_commonjs_prop_types_commonjs2_prop_types_commonj2s_prop_types_amd_prop_types_root_PropTypes_default.a.number.isRequired, + translation: translationShape.isRequired + }), + defaultValue: external_commonjs_prop_types_commonjs2_prop_types_commonj2s_prop_types_amd_prop_types_root_PropTypes_default.a.shape({ + scale: external_commonjs_prop_types_commonjs2_prop_types_commonj2s_prop_types_amd_prop_types_root_PropTypes_default.a.number.isRequired, + translation: translationShape.isRequired + }), + disableZoom: external_commonjs_prop_types_commonjs2_prop_types_commonj2s_prop_types_amd_prop_types_root_PropTypes_default.a.bool, + disablePan: external_commonjs_prop_types_commonjs2_prop_types_commonj2s_prop_types_amd_prop_types_root_PropTypes_default.a.bool, + onChange: external_commonjs_prop_types_commonjs2_prop_types_commonj2s_prop_types_amd_prop_types_root_PropTypes_default.a.func, + translationBounds: external_commonjs_prop_types_commonjs2_prop_types_commonj2s_prop_types_amd_prop_types_root_PropTypes_default.a.shape({ + xMin: external_commonjs_prop_types_commonjs2_prop_types_commonj2s_prop_types_amd_prop_types_root_PropTypes_default.a.number, + xMax: external_commonjs_prop_types_commonjs2_prop_types_commonj2s_prop_types_amd_prop_types_root_PropTypes_default.a.number, + yMin: external_commonjs_prop_types_commonjs2_prop_types_commonj2s_prop_types_amd_prop_types_root_PropTypes_default.a.number, + yMax: external_commonjs_prop_types_commonjs2_prop_types_commonj2s_prop_types_amd_prop_types_root_PropTypes_default.a.number + }), + minScale: external_commonjs_prop_types_commonjs2_prop_types_commonj2s_prop_types_amd_prop_types_root_PropTypes_default.a.number, + maxScale: external_commonjs_prop_types_commonjs2_prop_types_commonj2s_prop_types_amd_prop_types_root_PropTypes_default.a.number, + showControls: external_commonjs_prop_types_commonjs2_prop_types_commonj2s_prop_types_amd_prop_types_root_PropTypes_default.a.bool, + plusBtnContents: external_commonjs_prop_types_commonjs2_prop_types_commonj2s_prop_types_amd_prop_types_root_PropTypes_default.a.node, + minusBtnContents: external_commonjs_prop_types_commonjs2_prop_types_commonj2s_prop_types_amd_prop_types_root_PropTypes_default.a.node, + btnClass: external_commonjs_prop_types_commonjs2_prop_types_commonj2s_prop_types_amd_prop_types_root_PropTypes_default.a.string, + plusBtnClass: external_commonjs_prop_types_commonjs2_prop_types_commonj2s_prop_types_amd_prop_types_root_PropTypes_default.a.string, + minusBtnClass: external_commonjs_prop_types_commonjs2_prop_types_commonj2s_prop_types_amd_prop_types_root_PropTypes_default.a.string, + controlsClass: external_commonjs_prop_types_commonjs2_prop_types_commonj2s_prop_types_amd_prop_types_root_PropTypes_default.a.string + }; + } + }, { + key: "getDerivedStateFromProps", + value: function getDerivedStateFromProps(props, state) { + var nowControlled = MapInteractionController.isControlled(props); + var wasControlled = state.lastKnownValueFromProps && MapInteractionController.isControlled({ + value: state.lastKnownValueFromProps + }); + /* + State transitions: + uncontrolled --> controlled (unset internal state, set last props from parent) + controlled --> uncontrolled (set internal state to last props from parent) + controlled --> controlled (update last props from parent) + uncontrolled --> uncontrolled (do nothing) + Note that the second two (no change in control) will also happen on the + initial render because we set lastKnownValueFromProps in the constructor. + */ + + if (!wasControlled && nowControlled) { + return { + value: undefined, + lastKnownValueFromProps: props.value + }; + } else if (wasControlled && !nowControlled) { + return { + value: state.lastKnownValueFromProps, + lastKnownValueFromProps: undefined + }; + } else if (wasControlled && nowControlled) { + return { + lastKnownValueFromProps: props.value + }; + } else if (!wasControlled && !nowControlled) { + return null; + } + } + }, { + key: "isControlled", + value: function isControlled(props) { + // Similar to React's API, setting a value declares + // that you want to control this component. + return props.value != undefined; + } + }]); + + return MapInteractionController; +}(external_commonjs_react_commonjs2_react_amd_React_root_React_["Component"]); + +/* harmony default export */ var MapInteraction = (MapInteraction_MapInteractionController); +// CONCATENATED MODULE: ./src/MapInteractionCSS.jsx + + +/* + This component provides a map like interaction to any content that you place in it. It will let + the user zoom and pan the children by scaling and translating props.children using css. +*/ + +var MapInteractionCSS_MapInteractionCSS = function MapInteractionCSS(props) { + return /*#__PURE__*/external_commonjs_react_commonjs2_react_amd_React_root_React_default.a.createElement(MapInteraction, props, function (_ref) { + var translation = _ref.translation, + scale = _ref.scale; + // Translate first and then scale. Otherwise, the scale would affect the translation. + var transform = "translate(".concat(translation.x, "px, ").concat(translation.y, "px) scale(").concat(scale, ")"); + return /*#__PURE__*/external_commonjs_react_commonjs2_react_amd_React_root_React_default.a.createElement("div", { + style: { + height: '100%', + width: '100%', + position: 'relative', + // for absolutely positioned children + overflow: 'hidden', + touchAction: 'none', + // Not supported in Safari :( + msTouchAction: 'none', + cursor: 'all-scroll', + WebkitUserSelect: 'none', + MozUserSelect: 'none', + msUserSelect: 'none' + } + }, /*#__PURE__*/external_commonjs_react_commonjs2_react_amd_React_root_React_default.a.createElement("div", { + style: { + display: 'inline-block', + // size to content + transform: transform, + transformOrigin: '0 0 ' + } + }, props.children)); + }); +}; + +/* harmony default export */ var src_MapInteractionCSS = (MapInteractionCSS_MapInteractionCSS); +// CONCATENATED MODULE: ./src/index.js + + + +/* harmony default export */ var src = __webpack_exports__["default"] = (MapInteraction); + +/***/ }) +/******/ ]); +}); \ No newline at end of file diff --git a/.yalc/react-map-interaction/package.json b/.yalc/react-map-interaction/package.json new file mode 100644 index 0000000..16664e9 --- /dev/null +++ b/.yalc/react-map-interaction/package.json @@ -0,0 +1,36 @@ +{ + "name": "react-map-interaction", + "version": "2.0.0+760fcdb2", + "description": "'Add map like zooming and dragging to any element'", + "main": "dist/react-map-interaction.js", + "scripts": { + "test": "./node_modules/mocha/bin/mocha", + "test:watch": "./node_modules/mocha/bin/mocha --watch", + "test:cover": "nyc ./node_modules/mocha/bin/mocha", + "dist": "webpack --config webpack.config.js --mode production", + "dist:dev": "npm run dist && ./copy-to-example.sh", + "storybook": "start-storybook -p 6006", + "build-storybook": "build-storybook" + }, + "keywords": [ + "react", + "zoom", + "pan", + "pinch", + "data visualization", + "map" + ], + "author": "Transcriptic", + "private": false, + "license": "MIT", + "peerDependencies": { + "react": "^16.3.0", + "prop-types": "^15.0.0" + }, + "repository": { + "type": "git", + "url": "https://github.com/transcriptic/react-map-interaction" + }, + "dependencies": {}, + "yalcSig": "760fcdb2b8c4ce14979304df32411d35" +} diff --git a/.yalc/react-map-interaction/yalc.sig b/.yalc/react-map-interaction/yalc.sig new file mode 100644 index 0000000..6e41f85 --- /dev/null +++ b/.yalc/react-map-interaction/yalc.sig @@ -0,0 +1 @@ +760fcdb2b8c4ce14979304df32411d35 \ No newline at end of file diff --git a/apps/blueprints/src/components/FullscreenImage.tsx b/apps/blueprints/src/components/FullscreenImage.tsx index 5dcf084..50d16e5 100644 --- a/apps/blueprints/src/components/FullscreenImage.tsx +++ b/apps/blueprints/src/components/FullscreenImage.tsx @@ -1,4 +1,4 @@ -import React, { useState } from "react"; +import React, { useEffect, useState } from "react"; import { css } from "@emotion/react"; import { MapInteractionCSS } from "react-map-interaction"; import { Image } from "@chakra-ui/image"; @@ -51,6 +51,13 @@ export const FullscreenImage: React.FC = ({ alt, src }) => translation: { x: window.innerWidth * 0.05, y: 30 }, }); + useEffect(() => { + setState({ + scale: 0.9, + translation: { x: window.innerWidth * 0.05, y: 30 }, + }); + }, [src]); + return ( <> diff --git a/package.json b/package.json index eb48265..37fa306 100644 --- a/package.json +++ b/package.json @@ -57,7 +57,7 @@ "react-cookie": "4.0.3", "react-dom": "17.0.1", "react-icons": "4.2.0", - "react-map-interaction": "2.0.0", + "react-map-interaction": "file:.yalc/react-map-interaction", "react-markdown": "5.0.3", "react-multi-select-component": "3.1.6", "sharp": "0.27.2", diff --git a/yalc.lock b/yalc.lock index 985843c..15e3a9d 100644 --- a/yalc.lock +++ b/yalc.lock @@ -5,6 +5,11 @@ "signature": "4db8c378010b5990474548640c7c809e", "file": true, "replaced": "./fbe-editor-v1.0.0.tgz" + }, + "react-map-interaction": { + "signature": "760fcdb2b8c4ce14979304df32411d35", + "file": true, + "replaced": "2.0.0" } } } \ No newline at end of file