react-easy-panzoom
Advanced tools
Comparing version 0.2.5 to 0.3.0
@@ -10,8 +10,16 @@ "use strict"; | ||
var _warning = _interopRequireDefault(require("warning")); | ||
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } | ||
function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) { var desc = Object.defineProperty && Object.getOwnPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : {}; if (desc.get || desc.set) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } } newObj.default = obj; return newObj; } } | ||
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 _typeof(obj) { 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 _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 _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i] != null ? arguments[i] : {}; var ownKeys = Object.keys(source); if (typeof Object.getOwnPropertySymbols === 'function') { ownKeys = ownKeys.concat(Object.getOwnPropertySymbols(source).filter(function (sym) { return Object.getOwnPropertyDescriptor(source, sym).enumerable; })); } ownKeys.forEach(function (key) { _defineProperty(target, key, source[key]); }); } return target; } | ||
@@ -84,6 +92,2 @@ | ||
return function (element) { | ||
if (!element) { | ||
return null; | ||
} | ||
var clientTop = element.clientTop, | ||
@@ -149,7 +153,10 @@ clientLeft = element.clientLeft, | ||
_defineProperty(_assertThisInitialized(_this), "container", null); | ||
_defineProperty(_assertThisInitialized(_this), "container", React.createRef()); | ||
_defineProperty(_assertThisInitialized(_this), "dragContainer", null); | ||
_defineProperty(_assertThisInitialized(_this), "dragContainer", React.createRef()); | ||
_defineProperty(_assertThisInitialized(_this), "mousePos", null); | ||
_defineProperty(_assertThisInitialized(_this), "mousePos", { | ||
x: 0, | ||
y: 0 | ||
}); | ||
@@ -173,5 +180,5 @@ _defineProperty(_assertThisInitialized(_this), "panning", false); | ||
_defineProperty(_assertThisInitialized(_this), "transformMatrixString", null); | ||
_defineProperty(_assertThisInitialized(_this), "transformMatrixString", "matrix(1, 0, 0, 1, 0, 0)"); | ||
_defineProperty(_assertThisInitialized(_this), "intermediateTransformMatrixString", null); | ||
_defineProperty(_assertThisInitialized(_this), "intermediateTransformMatrixString", "matrix(1, 0, 0, 1, 0, 0)"); | ||
@@ -186,4 +193,15 @@ _defineProperty(_assertThisInitialized(_this), "state", { | ||
_defineProperty(_assertThisInitialized(_this), "onDoubleClick", function (e) { | ||
var doubleZoomSpeed = _this.props.doubleZoomSpeed; | ||
var _this$props = _this.props, | ||
onDoubleClick = _this$props.onDoubleClick, | ||
disableDoubleClickZoom = _this$props.disableDoubleClickZoom, | ||
doubleZoomSpeed = _this$props.doubleZoomSpeed; | ||
if (typeof onDoubleClick === 'function') { | ||
onDoubleClick(e); | ||
} | ||
if (disableDoubleClickZoom) { | ||
return; | ||
} | ||
var offset = _this.getOffset(e); | ||
@@ -195,4 +213,10 @@ | ||
_defineProperty(_assertThisInitialized(_this), "onMouseDown", function (e) { | ||
var preventPan = _this.props.preventPan; | ||
var _this$props2 = _this.props, | ||
preventPan = _this$props2.preventPan, | ||
onMouseDown = _this$props2.onMouseDown; | ||
if (typeof onMouseDown === 'function') { | ||
onMouseDown(e); | ||
} | ||
if (_this.props.disabled) { | ||
@@ -218,3 +242,3 @@ return; | ||
if (preventPan(e, offset.x, offset.y)) { | ||
if (preventPan && preventPan(e, offset.x, offset.y)) { | ||
return; | ||
@@ -289,6 +313,11 @@ } | ||
_defineProperty(_assertThisInitialized(_this), "onKeyDown", function (e) { | ||
var _this$props = _this.props, | ||
keyMapping = _this$props.keyMapping, | ||
disableKeyInteraction = _this$props.disableKeyInteraction; | ||
var _this$props3 = _this.props, | ||
keyMapping = _this$props3.keyMapping, | ||
disableKeyInteraction = _this$props3.disableKeyInteraction, | ||
onKeyDown = _this$props3.onKeyDown; | ||
if (typeof onKeyDown === 'function') { | ||
onKeyDown(e); | ||
} | ||
if (disableKeyInteraction) { | ||
@@ -357,4 +386,4 @@ return; | ||
if (_x || _y) { | ||
var containerRect = _this.container.getBoundingClientRect(); | ||
if ((_x || _y) && _this.container.current) { | ||
var containerRect = _this.container.current.getBoundingClientRect(); | ||
@@ -376,4 +405,10 @@ var offset = Math.min(containerRect.width, containerRect.height); | ||
_defineProperty(_assertThisInitialized(_this), "onTouchStart", function (e) { | ||
var preventPan = _this.props.preventPan; | ||
var _this$props4 = _this.props, | ||
preventPan = _this$props4.preventPan, | ||
onTouchStart = _this$props4.onTouchStart; | ||
if (typeof onTouchStart === 'function') { | ||
onTouchStart(e); | ||
} | ||
if (e.touches.length === 1) { | ||
@@ -385,3 +420,3 @@ // Drag | ||
if (preventPan(e, offset.x, offset.y)) { | ||
if (preventPan && preventPan(e, offset.x, offset.y)) { | ||
return; | ||
@@ -412,5 +447,5 @@ } | ||
_defineProperty(_assertThisInitialized(_this), "onToucheMove", function (e) { | ||
var _this$props2 = _this.props, | ||
realPinch = _this$props2.realPinch, | ||
noStateUpdate = _this$props2.noStateUpdate; | ||
var _this$props5 = _this.props, | ||
realPinch = _this$props5.realPinch, | ||
noStateUpdate = _this$props5.noStateUpdate; | ||
@@ -598,13 +633,35 @@ if (e.touches.length === 1) { | ||
_defineProperty(_assertThisInitialized(_this), "getContainer", function () { | ||
var container = _this.container.current; | ||
if (!container) { | ||
throw new Error("Could not find container DOM element."); | ||
} | ||
return container; | ||
}); | ||
_defineProperty(_assertThisInitialized(_this), "getDragContainer", function () { | ||
var dragContainer = _this.dragContainer.current; | ||
if (!dragContainer) { | ||
throw new Error("Could not find dragContainer DOM element."); | ||
} | ||
return dragContainer; | ||
}); | ||
_defineProperty(_assertThisInitialized(_this), "autoCenter", function () { | ||
var zoomLevel = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 1; | ||
var _this$props3 = _this.props, | ||
minZoom = _this$props3.minZoom, | ||
maxZoom = _this$props3.maxZoom; | ||
var containerRect = _this.container.getBoundingClientRect(); | ||
var container = _this.getContainer(); | ||
var _this$dragContainer = _this.dragContainer, | ||
clientWidth = _this$dragContainer.clientWidth, | ||
clientHeight = _this$dragContainer.clientHeight; | ||
var dragContainer = _this.getDragContainer(); | ||
var _this$props6 = _this.props, | ||
minZoom = _this$props6.minZoom, | ||
maxZoom = _this$props6.maxZoom; | ||
var containerRect = container.getBoundingClientRect(); | ||
var clientWidth = dragContainer.clientWidth, | ||
clientHeight = dragContainer.clientHeight; | ||
var widthRatio = containerRect.width / clientWidth; | ||
@@ -636,4 +693,5 @@ var heightRatio = containerRect.height / clientHeight; | ||
var containerRect = _this.container.getBoundingClientRect(); | ||
var container = _this.getContainer(); | ||
var containerRect = container.getBoundingClientRect(); | ||
var offset = Math.min(containerRect.width, containerRect.height); | ||
@@ -646,3 +704,4 @@ var dx = offset * moveSpeedRatio * x; | ||
_defineProperty(_assertThisInitialized(_this), "moveBy", function (dx, dy, noStateUpdate) { | ||
_defineProperty(_assertThisInitialized(_this), "moveBy", function (dx, dy) { | ||
var noStateUpdate = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : true; | ||
var _this$state = _this.state, | ||
@@ -707,6 +766,8 @@ x = _this$state.x, | ||
var rotate = _this.state.rotate; | ||
var newAngle = value; | ||
var newAngle; | ||
if (typeof value === 'function') { | ||
newAngle = value(rotate); | ||
} else { | ||
newAngle = value; | ||
} | ||
@@ -724,5 +785,5 @@ | ||
_defineProperty(_assertThisInitialized(_this), "zoomTo", function (x, y, ratio) { | ||
var _this$props4 = _this.props, | ||
minZoom = _this$props4.minZoom, | ||
maxZoom = _this$props4.maxZoom; | ||
var _this$props7 = _this.props, | ||
minZoom = _this$props7.minZoom, | ||
maxZoom = _this$props7.maxZoom; | ||
var _this$state2 = _this.state, | ||
@@ -766,5 +827,7 @@ transformX = _this$state2.x, | ||
_defineProperty(_assertThisInitialized(_this), "centeredZoom", function (delta) { | ||
var container = _this.getContainer(); | ||
var scaleMultiplier = _this.getScaleMultiplier(delta); | ||
var containerRect = _this.container.getBoundingClientRect(); | ||
var containerRect = container.getBoundingClientRect(); | ||
@@ -792,3 +855,3 @@ _this.zoomTo(containerRect.width / 2, containerRect.height / 2, scaleMultiplier); | ||
_defineProperty(_assertThisInitialized(_this), "getOffset", function (e) { | ||
var containerRect = _this.container.getBoundingClientRect(); | ||
var containerRect = _this.getContainer().getBoundingClientRect(); | ||
@@ -804,3 +867,3 @@ var offsetX = e.clientX - containerRect.left; | ||
_defineProperty(_assertThisInitialized(_this), "getTransformMatrix", function (x, y, scale, rotate) { | ||
if (!_this.dragContainer) { | ||
if (!_this.dragContainer.current) { | ||
return { | ||
@@ -816,5 +879,6 @@ a: scale, | ||
var _this$dragContainer2 = _this.dragContainer, | ||
clientWidth = _this$dragContainer2.clientWidth, | ||
clientHeight = _this$dragContainer2.clientHeight; | ||
var _this$getDragContaine = _this.getDragContainer(), | ||
clientWidth = _this$getDragContaine.clientWidth, | ||
clientHeight = _this$getDragContaine.clientHeight; | ||
var centerX = clientWidth / 2; | ||
@@ -830,3 +894,3 @@ var centerY = clientHeight / 2; | ||
_defineProperty(_assertThisInitialized(_this), "applyTransform", function () { | ||
_this.dragContainer.style.transform = _this.transformMatrixString; | ||
_this.getDragContainer().style.transform = _this.transformMatrixString; | ||
_this.frameAnimation = 0; | ||
@@ -836,3 +900,3 @@ }); | ||
_defineProperty(_assertThisInitialized(_this), "applyIntermediateTransform", function () { | ||
_this.dragContainer.style.transform = _this.intermediateTransformMatrixString; | ||
_this.getDragContainer().style.transform = _this.intermediateTransformMatrixString; | ||
_this.intermediateFrameAnimation = 0; | ||
@@ -845,6 +909,6 @@ }); | ||
var offsetY = arguments.length > 5 && arguments[5] !== undefined ? arguments[5] : 0; | ||
var _this$props5 = _this.props, | ||
enableBoundingBox = _this$props5.enableBoundingBox, | ||
boundaryRatioVertical = _this$props5.boundaryRatioVertical, | ||
boundaryRatioHorizontal = _this$props5.boundaryRatioHorizontal; | ||
var _this$props8 = _this.props, | ||
enableBoundingBox = _this$props8.enableBoundingBox, | ||
boundaryRatioVertical = _this$props8.boundaryRatioVertical, | ||
boundaryRatioHorizontal = _this$props8.boundaryRatioHorizontal; | ||
@@ -860,7 +924,7 @@ if (!enableBoundingBox) { | ||
var _this$container$getBo = _this.container.getBoundingClientRect(), | ||
containerHeight = _this$container$getBo.height, | ||
containerWidth = _this$container$getBo.width; | ||
var _this$getContainer$ge = _this.getContainer().getBoundingClientRect(), | ||
containerHeight = _this$getContainer$ge.height, | ||
containerWidth = _this$getContainer$ge.width; | ||
var _getTransformedElemen = getTransformedElementCoordinates(rotate, newScale, offsetX, offsetY)(_this.dragContainer), | ||
var _getTransformedElemen = getTransformedElementCoordinates(rotate, newScale, offsetX, offsetY)(_this.getDragContainer()), | ||
top = _getTransformedElemen.top, | ||
@@ -903,11 +967,14 @@ left = _getTransformedElemen.left, | ||
value: function componentDidMount() { | ||
var _this$props6 = this.props, | ||
autoCenter = _this$props6.autoCenter, | ||
autoCenterZoomLevel = _this$props6.autoCenterZoomLevel, | ||
minZoom = _this$props6.minZoom, | ||
maxZoom = _this$props6.maxZoom; | ||
this.container.addEventListener('mousewheel', this.onWheel, { | ||
passive: false | ||
}); | ||
var _this$props9 = this.props, | ||
autoCenter = _this$props9.autoCenter, | ||
autoCenterZoomLevel = _this$props9.autoCenterZoomLevel, | ||
minZoom = _this$props9.minZoom, | ||
maxZoom = _this$props9.maxZoom; | ||
if (this.container.current) { | ||
this.container.current.addEventListener('wheel', this.onWheel, { | ||
passive: false | ||
}); | ||
} | ||
if (maxZoom < minZoom) { | ||
@@ -923,6 +990,15 @@ throw new Error('[PanZoom]: maxZoom props cannot be inferior to minZoom'); | ||
key: "componentDidUpdate", | ||
value: function componentDidUpdate(prevProps) { | ||
value: function componentDidUpdate(prevProps, prevState) { | ||
if (prevProps.autoCenter !== this.props.autoCenter && this.props.autoCenter) { | ||
this.autoCenter(this.props.autoCenterZoomLevel); | ||
} | ||
if ((prevState.x !== this.state.x || prevState.y !== this.state.y || prevState.scale !== this.state.scale || prevState.rotate !== this.state.rotate) && this.props.onStateChange) { | ||
this.props.onStateChange({ | ||
x: this.state.x, | ||
y: this.state.y, | ||
scale: this.state.scale, | ||
rotate: this.state.rotate | ||
}); | ||
} | ||
} | ||
@@ -935,5 +1011,8 @@ }, { | ||
this.releaseTextSelection(); | ||
this.container.removeEventListener('mousewheel', this.onWheel, { | ||
passive: false | ||
}); | ||
if (this.container.current) { | ||
this.container.current.removeEventListener('wheel', this.onWheel, { | ||
passive: false | ||
}); | ||
} | ||
} | ||
@@ -943,9 +1022,31 @@ }, { | ||
value: function render() { | ||
var _this2 = this; | ||
var _this$props10 = this.props, | ||
children = _this$props10.children, | ||
autoCenter = _this$props10.autoCenter, | ||
autoCenterZoomLevel = _this$props10.autoCenterZoomLevel, | ||
zoomSpeed = _this$props10.zoomSpeed, | ||
doubleZoomSpeed = _this$props10.doubleZoomSpeed, | ||
disabled = _this$props10.disabled, | ||
disableDoubleClickZoom = _this$props10.disableDoubleClickZoom, | ||
disableKeyInteraction = _this$props10.disableKeyInteraction, | ||
realPinch = _this$props10.realPinch, | ||
keyMapping = _this$props10.keyMapping, | ||
minZoom = _this$props10.minZoom, | ||
maxZoom = _this$props10.maxZoom, | ||
enableBoundingBox = _this$props10.enableBoundingBox, | ||
boundaryRatioVertical = _this$props10.boundaryRatioVertical, | ||
boundaryRatioHorizontal = _this$props10.boundaryRatioHorizontal, | ||
noStateUpdate = _this$props10.noStateUpdate, | ||
onPanStart = _this$props10.onPanStart, | ||
onPan = _this$props10.onPan, | ||
onPanEnd = _this$props10.onPanEnd, | ||
preventPan = _this$props10.preventPan, | ||
style = _this$props10.style, | ||
onDoubleClick = _this$props10.onDoubleClick, | ||
onMouseDown = _this$props10.onMouseDown, | ||
onKeyDown = _this$props10.onKeyDown, | ||
onTouchStart = _this$props10.onTouchStart, | ||
onStateChange = _this$props10.onStateChange, | ||
restPassThroughProps = _objectWithoutProperties(_this$props10, ["children", "autoCenter", "autoCenterZoomLevel", "zoomSpeed", "doubleZoomSpeed", "disabled", "disableDoubleClickZoom", "disableKeyInteraction", "realPinch", "keyMapping", "minZoom", "maxZoom", "enableBoundingBox", "boundaryRatioVertical", "boundaryRatioHorizontal", "noStateUpdate", "onPanStart", "onPan", "onPanEnd", "preventPan", "style", "onDoubleClick", "onMouseDown", "onKeyDown", "onTouchStart", "onStateChange"]); | ||
var _this$props7 = this.props, | ||
children = _this$props7.children, | ||
style = _this$props7.style, | ||
disabled = _this$props7.disabled, | ||
disableKeyInteraction = _this$props7.disableKeyInteraction; | ||
var _this$state3 = this.state, | ||
@@ -966,6 +1067,12 @@ x = _this$state3.x, | ||
var transform = this.getTransformMatrixString(a, b, c, d, transformX, transformY); | ||
if (process.env.NODE_ENV !== 'production') { | ||
(0, _warning.default)(onDoubleClick === undefined || typeof onDoubleClick === 'function', "Expected `onDoubleClick` listener to be a function, instead got a value of `%s` type.", _typeof(onDoubleClick)); | ||
(0, _warning.default)(onMouseDown === undefined || typeof onMouseDown === 'function', "Expected `onMouseDown` listener to be a function, instead got a value of `%s` type.", _typeof(onMouseDown)); | ||
(0, _warning.default)(onKeyDown === undefined || typeof onKeyDown === 'function', "Expected `onKeyDown` listener to be a function, instead got a value of `%s` type.", _typeof(onKeyDown)); | ||
(0, _warning.default)(onTouchStart === undefined || typeof onTouchStart === 'function', "Expected `onTouchStart` listener to be a function, instead got a value of `%s` type.", _typeof(onTouchStart)); | ||
} | ||
return React.createElement("div", _extends({ | ||
ref: function ref(_ref2) { | ||
return _this2.container = _ref2; | ||
} | ||
ref: this.container | ||
}, disableKeyInteraction ? {} : { | ||
@@ -989,6 +1096,4 @@ tabIndex: 0 // enable onKeyDown event | ||
}, style) | ||
}), React.createElement("div", { | ||
ref: function ref(_ref) { | ||
return _this2.dragContainer = _ref; | ||
}, | ||
}, restPassThroughProps), React.createElement("div", { | ||
ref: this.dragContainer, | ||
style: { | ||
@@ -1008,5 +1113,6 @@ display: 'inline-block', | ||
PanZoom.defaultProps = { | ||
_defineProperty(PanZoom, "defaultProps", { | ||
zoomSpeed: 1, | ||
doubleZoomSpeed: 1.75, | ||
disabled: false, | ||
minZoom: 0, | ||
@@ -1017,7 +1123,9 @@ maxZoom: Infinity, | ||
boundaryRatioHorizontal: 0.8, | ||
disableDoubleClickZoom: false, | ||
preventPan: function preventPan() { | ||
return false; | ||
} | ||
}; | ||
}); | ||
var _default = PanZoom; | ||
exports.default = _default; |
{ | ||
"name": "react-easy-panzoom", | ||
"version": "0.2.5", | ||
"version": "0.3.0", | ||
"description": "Wrapper to enable pan and zoom for any React component", | ||
@@ -18,2 +18,4 @@ "main": "./lib/index.js", | ||
"build": "webpack", | ||
"test": "jest", | ||
"flow": "flow", | ||
"build:cjs": "cross-env NODE_ENV=production babel --config-file ./babel.config.js ./src --out-dir ./lib --ignore \"**/*.test.js\"" | ||
@@ -38,3 +40,5 @@ }, | ||
}, | ||
"dependencies": {}, | ||
"dependencies": { | ||
"warning": "4.0.3" | ||
}, | ||
"devDependencies": { | ||
@@ -48,11 +52,12 @@ "@babel/cli": "^7.2.3", | ||
"@babel/preset-react": "^7.0.0", | ||
"@storybook/addon-actions": "^5.0.1", | ||
"@storybook/addon-knobs": "^5.0.1", | ||
"@storybook/addon-links": "^5.0.1", | ||
"@storybook/addons": "^5.0.1", | ||
"@storybook/react": "^5.0.1", | ||
"@storybook/theming": "^5.0.1", | ||
"@storybook/addon-actions": "^5.1.3", | ||
"@storybook/addon-knobs": "^5.1.3", | ||
"@storybook/addon-links": "^5.1.3", | ||
"@storybook/addons": "^5.1.3", | ||
"@storybook/react": "^5.1.3", | ||
"@storybook/theming": "^5.1.3", | ||
"babel-loader": "^8.0.5", | ||
"cross-env": "^5.2.0", | ||
"flow-bin": "^0.95.1", | ||
"jest": "^24.8.0", | ||
"react": "^16.8.4", | ||
@@ -59,0 +64,0 @@ "react-dom": "^16.8.4", |
@@ -6,2 +6,3 @@ # react-easy-panzoom | ||
[![Code](https://img.shields.io/npm/dt/react-easy-panzoom.svg?style=plastic)](https://www.npmjs.com/package/react-easy-panzoom) | ||
[![Code](https://travis-ci.com/mnogueron/react-easy-panzoom.svg?branch=master)](https://travis-ci.com/mnogueron/react-easy-panzoom) | ||
@@ -141,2 +142,3 @@ ![react-easy-panzoom-demo](https://user-images.githubusercontent.com/8511318/55997819-2ff98700-5cbc-11e9-99f5-67ea295f4f92.gif) | ||
|disableKeyInteraction|`bool`|false|Disable keyboard interaction| | ||
|disableDoubleClickZoom|`bool`|false|Disable zoom when performing a double click| | ||
|realPinch|`bool`|false|Enable real pinch interaction for touch events| | ||
@@ -155,3 +157,6 @@ |keyMapping|`object`|false|Define specific key mapping for keyboard interaction (e.g. `{ '<keyCode>': { x: 0, y: 1, z: 0 } }`, with `<keyCode>` being the key code to map)| | ||
|style|`object`| |Override the inline-styles of the root element| | ||
|onStateChange|`func`| |Called after the state of the component has changed| | ||
You can also pass in every other props you would pass to a `div` element. Those will be passed through to the container component. This is helpful for adding custom event handlers. | ||
## Methods | ||
@@ -158,0 +163,0 @@ By using `ref`, methods from `PanZoom` can be accessed and called to trigger manipulation functions. |
// @flow | ||
import * as React from 'react' | ||
import warning from 'warning' | ||
type OnStateChangeData = { | ||
x: number, | ||
y: number, | ||
scale: number, | ||
rotate: number | ||
} | ||
type Props = { | ||
zoomSpeed?: number, | ||
doubleZoomSpeed?: number, | ||
zoomSpeed: number, | ||
doubleZoomSpeed: number, | ||
disabled?: boolean, | ||
@@ -11,8 +19,11 @@ autoCenter?: boolean, | ||
disableKeyInteraction?: boolean, | ||
disableDoubleClickZoom?: boolean, | ||
realPinch?: boolean, | ||
keyMapping?: { [string]: { x: number, y: number, z: number }}, | ||
minZoom?: number, | ||
maxZoom?: number, | ||
preventPan?: (event: SyntheticEvent, x: number, y: number) => boolean, | ||
noStateUpdate?: boolean, | ||
minZoom: number, | ||
maxZoom: number, | ||
preventPan: (event: SyntheticTouchEvent<HTMLDivElement> | MouseEvent, x: number, y: number) => boolean, | ||
noStateUpdate: boolean, | ||
boundaryRatioVertical: number, | ||
boundaryRatioHorizontal: number, | ||
@@ -22,2 +33,10 @@ onPanStart?: (any) => void, | ||
onPanEnd?: (any) => void, | ||
onStateChange?: (data: OnStateChangeData) => void, | ||
} & React.ElementProps<'div'> | ||
type State = { | ||
x: number, | ||
y: number, | ||
scale: number, | ||
rotate: number | ||
} | ||
@@ -49,7 +68,10 @@ | ||
const getTransformedElementCoordinates = (angle, scale, offsetX, offsetY) => (element) => { | ||
if (!element) { | ||
return null | ||
} | ||
type TransformCoordinates = { | ||
top: number, | ||
left: number, | ||
width: number, | ||
height: number, | ||
} | ||
const getTransformedElementCoordinates = (angle, scale, offsetX, offsetY) => (element: HTMLElement): TransformCoordinates => { | ||
const { clientTop, clientLeft, clientWidth, clientHeight } = element | ||
@@ -78,8 +100,23 @@ const centerX = clientWidth / 2 | ||
class PanZoom extends React.Component<Props> { | ||
class PanZoom extends React.Component<Props, State> { | ||
static defaultProps = { | ||
zoomSpeed: 1, | ||
doubleZoomSpeed: 1.75, | ||
disabled: false, | ||
minZoom: 0, | ||
maxZoom: Infinity, | ||
noStateUpdate: true, | ||
boundaryRatioVertical: 0.8, | ||
boundaryRatioHorizontal: 0.8, | ||
disableDoubleClickZoom: false, | ||
preventPan: () => false, | ||
} | ||
container = null | ||
dragContainer = null | ||
container = React.createRef<HTMLDivElement>() | ||
dragContainer = React.createRef<HTMLDivElement>() | ||
mousePos = null | ||
mousePos = { | ||
x: 0, | ||
y: 0 | ||
} | ||
panning = false | ||
@@ -99,6 +136,6 @@ touchInProgress = false | ||
transformMatrixString = null | ||
intermediateTransformMatrixString = null | ||
transformMatrixString = `matrix(1, 0, 0, 1, 0, 0)` | ||
intermediateTransformMatrixString = `matrix(1, 0, 0, 1, 0, 0)` | ||
state = { | ||
state: State = { | ||
x: 0, | ||
@@ -113,3 +150,5 @@ y: 0, | ||
this.container.addEventListener('mousewheel', this.onWheel, { passive: false }) | ||
if (this.container.current) { | ||
this.container.current.addEventListener('wheel', this.onWheel, { passive: false }) | ||
} | ||
@@ -124,3 +163,3 @@ if (maxZoom < minZoom) { | ||
componentDidUpdate(prevProps): void { | ||
componentDidUpdate(prevProps: Props, prevState: State): void { | ||
if (prevProps.autoCenter !== this.props.autoCenter | ||
@@ -130,2 +169,16 @@ && this.props.autoCenter) { | ||
} | ||
if ( | ||
(prevState.x !== this.state.x | ||
|| prevState.y !== this.state.y | ||
|| prevState.scale !== this.state.scale | ||
|| prevState.rotate !== this.state.rotate) | ||
&& this.props.onStateChange | ||
) { | ||
this.props.onStateChange({ | ||
x: this.state.x, | ||
y: this.state.y, | ||
scale: this.state.scale, | ||
rotate: this.state.rotate | ||
}) | ||
} | ||
} | ||
@@ -137,8 +190,18 @@ | ||
this.releaseTextSelection() | ||
this.container.removeEventListener('mousewheel', this.onWheel, { passive: false }) | ||
if (this.container.current) { | ||
this.container.current.removeEventListener('wheel', this.onWheel, { passive: false }) | ||
} | ||
} | ||
onDoubleClick = (e) => { | ||
const { doubleZoomSpeed } = this.props | ||
onDoubleClick = (e: MouseEvent) => { | ||
const { onDoubleClick, disableDoubleClickZoom, doubleZoomSpeed } = this.props | ||
if (typeof onDoubleClick === 'function') { | ||
onDoubleClick(e) | ||
} | ||
if (disableDoubleClickZoom) { | ||
return | ||
} | ||
const offset = this.getOffset(e) | ||
@@ -148,4 +211,9 @@ this.zoomTo(offset.x, offset.y, doubleZoomSpeed) | ||
onMouseDown = (e) => { | ||
const { preventPan } = this.props | ||
onMouseDown = (e: MouseEvent) => { | ||
const { preventPan, onMouseDown } = this.props | ||
if (typeof onMouseDown === 'function') { | ||
onMouseDown(e) | ||
} | ||
if (this.props.disabled) { | ||
@@ -170,3 +238,3 @@ return | ||
// check if there is nothing preventing the pan | ||
if (preventPan(e, offset.x, offset.y)) { | ||
if (preventPan && preventPan(e, offset.x, offset.y)) { | ||
return | ||
@@ -194,3 +262,3 @@ } | ||
onMouseMove = (e) => { | ||
onMouseMove = (e: MouseEvent) => { | ||
if (this.panning) { | ||
@@ -217,3 +285,3 @@ const { noStateUpdate } = this.props | ||
onMouseUp = (e) => { | ||
onMouseUp = (e: MouseEvent) => { | ||
// if using noStateUpdate we still need to set the new values in the state | ||
@@ -228,3 +296,3 @@ this.dispatchStateUpdateIfNeeded() | ||
onWheel = (e) => { | ||
onWheel = (e: WheelEvent) => { | ||
if (this.props.disabled) { | ||
@@ -240,5 +308,9 @@ return | ||
onKeyDown = (e) => { | ||
const { keyMapping, disableKeyInteraction } = this.props | ||
onKeyDown = (e: SyntheticKeyboardEvent<HTMLDivElement>) => { | ||
const { keyMapping, disableKeyInteraction, onKeyDown } = this.props | ||
if (typeof onKeyDown === 'function') { | ||
onKeyDown(e) | ||
} | ||
if (disableKeyInteraction) { | ||
@@ -266,4 +338,4 @@ return | ||
if (x || y) { | ||
const containerRect = this.container.getBoundingClientRect() | ||
if ((x || y) && this.container.current) { | ||
const containerRect = this.container.current.getBoundingClientRect() | ||
const offset = Math.min(containerRect.width, containerRect.height) | ||
@@ -283,4 +355,8 @@ const moveSpeedRatio = 0.05 | ||
onTouchStart = (e) => { | ||
const { preventPan } = this.props | ||
onTouchStart = (e: SyntheticTouchEvent<HTMLDivElement>) => { | ||
const { preventPan, onTouchStart } = this.props | ||
if (typeof onTouchStart === 'function') { | ||
onTouchStart(e) | ||
} | ||
if (e.touches.length === 1) { | ||
@@ -291,3 +367,3 @@ // Drag | ||
if (preventPan(e, offset.x, offset.y)) { | ||
if (preventPan && preventPan(e, offset.x, offset.y)) { | ||
return | ||
@@ -317,3 +393,3 @@ } | ||
onToucheMove = (e) => { | ||
onToucheMove = (e: TouchEvent) => { | ||
const { realPinch, noStateUpdate } = this.props | ||
@@ -368,3 +444,3 @@ if (e.touches.length === 1) { | ||
onTouchEnd = (e) => { | ||
onTouchEnd = (e: TouchEvent) => { | ||
if (e.touches.length > 0) { | ||
@@ -449,3 +525,3 @@ const offset = this.getOffset(e.touches[0]) | ||
triggerOnPanStart = (e) => { | ||
triggerOnPanStart = (e: MouseEvent | TouchEvent) => { | ||
const { onPanStart } = this.props | ||
@@ -458,3 +534,3 @@ if (!this.panStartTriggered) { | ||
triggerOnPan = (e) => { | ||
triggerOnPan = (e: MouseEvent | TouchEvent) => { | ||
const { onPan } = this.props | ||
@@ -464,3 +540,3 @@ onPan && onPan(e) | ||
triggerOnPanEnd = (e) => { | ||
triggerOnPanEnd = (e: MouseEvent | TouchEvent) => { | ||
const { onPanEnd } = this.props | ||
@@ -471,3 +547,3 @@ this.panStartTriggered = false | ||
getScaleMultiplier = (delta) => { | ||
getScaleMultiplier = (delta: number) => { | ||
let speed = 0.065 * this.props.zoomSpeed | ||
@@ -484,3 +560,3 @@ let scaleMultiplier = 1 | ||
getPinchZoomLength = (finger1, finger2) => { | ||
getPinchZoomLength = (finger1: Touch, finger2: Touch) => { | ||
return Math.sqrt( | ||
@@ -492,6 +568,24 @@ (finger1.clientX - finger2.clientX) * (finger1.clientX - finger2.clientX) + | ||
autoCenter = (zoomLevel = 1) => { | ||
getContainer = (): HTMLDivElement => { | ||
const { current: container } = this.container | ||
if (!container) { | ||
throw new Error("Could not find container DOM element.") | ||
} | ||
return container | ||
} | ||
getDragContainer = (): HTMLDivElement => { | ||
const { current: dragContainer } = this.dragContainer | ||
if (!dragContainer) { | ||
throw new Error("Could not find dragContainer DOM element.") | ||
} | ||
return dragContainer | ||
} | ||
autoCenter = (zoomLevel: number = 1) => { | ||
const container = this.getContainer() | ||
const dragContainer = this.getDragContainer() | ||
const { minZoom, maxZoom } = this.props | ||
const containerRect = this.container.getBoundingClientRect() | ||
const { clientWidth, clientHeight } = this.dragContainer | ||
const containerRect = container.getBoundingClientRect() | ||
const { clientWidth, clientHeight } = dragContainer | ||
const widthRatio = containerRect.width / clientWidth | ||
@@ -515,4 +609,5 @@ const heightRatio = containerRect.height / clientHeight | ||
moveByRatio = (x, y, moveSpeedRatio = 0.05) => { | ||
const containerRect = this.container.getBoundingClientRect() | ||
moveByRatio = (x: number, y: number, moveSpeedRatio: number = 0.05) => { | ||
const container = this.getContainer() | ||
const containerRect = container.getBoundingClientRect() | ||
const offset = Math.min(containerRect.width, containerRect.height) | ||
@@ -525,3 +620,3 @@ const dx = offset * moveSpeedRatio * x | ||
moveBy = (dx, dy, noStateUpdate) => { | ||
moveBy = (dx: number, dy: number, noStateUpdate?: boolean = true) => { | ||
const { x, y, scale, rotate } = this.state | ||
@@ -567,5 +662,7 @@ | ||
const { rotate } = this.state | ||
let newAngle = value | ||
let newAngle: number | ||
if (typeof value === 'function') { | ||
newAngle = value(rotate) | ||
} else { | ||
newAngle = value | ||
} | ||
@@ -575,7 +672,7 @@ this.setState({ rotate: newAngle }) | ||
zoomAbs = (x, y, zoomLevel) => { | ||
zoomAbs = (x: number, y: number, zoomLevel: number) => { | ||
this.zoomTo(x, y, zoomLevel / this.state.scale) | ||
} | ||
zoomTo = (x, y, ratio) => { | ||
zoomTo = (x: number, y: number, ratio: number) => { | ||
const { minZoom, maxZoom } = this.props | ||
@@ -607,5 +704,6 @@ const { x: transformX, y: transformY, scale, rotate } = this.state | ||
centeredZoom = (delta) => { | ||
centeredZoom = (delta: number) => { | ||
const container = this.getContainer() | ||
const scaleMultiplier = this.getScaleMultiplier(delta) | ||
const containerRect = this.container.getBoundingClientRect() | ||
const containerRect = container.getBoundingClientRect() | ||
this.zoomTo(containerRect.width / 2, containerRect.height / 2, scaleMultiplier) | ||
@@ -626,4 +724,4 @@ } | ||
getOffset = (e) => { | ||
const containerRect = this.container.getBoundingClientRect() | ||
getOffset = (e: MouseEvent | Touch) => { | ||
const containerRect = this.getContainer().getBoundingClientRect() | ||
const offsetX = e.clientX - containerRect.left | ||
@@ -634,8 +732,8 @@ const offsetY = e.clientY - containerRect.top | ||
getTransformMatrix = (x, y, scale, rotate) => { | ||
if (!this.dragContainer) { | ||
getTransformMatrix = (x: number, y: number, scale: number, rotate: number) => { | ||
if (!this.dragContainer.current) { | ||
return { a: scale, b: 0, c: 0, d: scale, x, y } | ||
} | ||
const { clientWidth, clientHeight } = this.dragContainer | ||
const { clientWidth, clientHeight } = this.getDragContainer() | ||
const centerX = clientWidth / 2 | ||
@@ -647,3 +745,3 @@ const centerY = clientHeight / 2 | ||
getTransformMatrixString = (a, b, c, d, x, y) => { | ||
getTransformMatrixString = (a: number, b: number, c: number, d: number, x: number, y: number) => { | ||
return `matrix(${a}, ${b}, ${c}, ${d}, ${x}, ${y})` | ||
@@ -654,3 +752,3 @@ } | ||
applyTransform = () => { | ||
this.dragContainer.style.transform = this.transformMatrixString | ||
this.getDragContainer().style.transform = this.transformMatrixString | ||
this.frameAnimation = 0 | ||
@@ -661,7 +759,7 @@ } | ||
applyIntermediateTransform = () => { | ||
this.dragContainer.style.transform = this.intermediateTransformMatrixString | ||
this.getDragContainer().style.transform = this.intermediateTransformMatrixString | ||
this.intermediateFrameAnimation = 0 | ||
} | ||
getBoundCoordinates = (x, y, newScale, rotate = 0, offsetX = 0, offsetY = 0) => { | ||
getBoundCoordinates = (x: number, y: number, newScale: number, rotate?: number = 0, offsetX?: number = 0, offsetY?: number = 0) => { | ||
const { enableBoundingBox, boundaryRatioVertical, boundaryRatioHorizontal } = this.props | ||
@@ -678,4 +776,4 @@ | ||
const { height: containerHeight, width: containerWidth } = this.container.getBoundingClientRect() | ||
const { top, left, width, height } = getTransformedElementCoordinates(rotate, newScale, offsetX, offsetY)(this.dragContainer) | ||
const { height: containerHeight, width: containerWidth } = this.getContainer().getBoundingClientRect() | ||
const { top, left, width, height } = getTransformedElementCoordinates(rotate, newScale, offsetX, offsetY)(this.getDragContainer()) | ||
@@ -711,3 +809,31 @@ // check that computed are inside boundaries otherwise set to the bounding box limits | ||
render() { | ||
const { children, style, disabled, disableKeyInteraction } = this.props | ||
const { | ||
children, | ||
autoCenter, | ||
autoCenterZoomLevel, | ||
zoomSpeed, | ||
doubleZoomSpeed, | ||
disabled, | ||
disableDoubleClickZoom, | ||
disableKeyInteraction, | ||
realPinch, | ||
keyMapping, | ||
minZoom, | ||
maxZoom, | ||
enableBoundingBox, | ||
boundaryRatioVertical, | ||
boundaryRatioHorizontal, | ||
noStateUpdate, | ||
onPanStart, | ||
onPan, | ||
onPanEnd, | ||
preventPan, | ||
style, | ||
onDoubleClick, | ||
onMouseDown, | ||
onKeyDown, | ||
onTouchStart, | ||
onStateChange, | ||
...restPassThroughProps | ||
} = this.props | ||
const { x, y, scale, rotate } = this.state | ||
@@ -717,5 +843,28 @@ const { a, b, c, d, x: transformX, y: transformY} = this.getTransformMatrix(x, y, scale, rotate) | ||
if (process.env.NODE_ENV !== 'production') { | ||
warning( | ||
onDoubleClick === undefined || typeof onDoubleClick === 'function', | ||
"Expected `onDoubleClick` listener to be a function, instead got a value of `%s` type.", | ||
typeof onDoubleClick | ||
) | ||
warning( | ||
onMouseDown === undefined || typeof onMouseDown === 'function', | ||
"Expected `onMouseDown` listener to be a function, instead got a value of `%s` type.", | ||
typeof onMouseDown | ||
) | ||
warning( | ||
onKeyDown === undefined || typeof onKeyDown === 'function', | ||
"Expected `onKeyDown` listener to be a function, instead got a value of `%s` type.", | ||
typeof onKeyDown | ||
) | ||
warning( | ||
onTouchStart === undefined || typeof onTouchStart === 'function', | ||
"Expected `onTouchStart` listener to be a function, instead got a value of `%s` type.", | ||
typeof onTouchStart | ||
) | ||
} | ||
return ( | ||
<div | ||
ref={ref => this.container = ref} | ||
ref={this.container} | ||
{ | ||
@@ -738,5 +887,6 @@ ...(disableKeyInteraction ? {} : { | ||
style={{ cursor: disabled ? 'initial' : 'pointer', ...style }} | ||
{...restPassThroughProps} | ||
> | ||
<div | ||
ref={ref => this.dragContainer = ref} | ||
ref={this.dragContainer} | ||
style={{ | ||
@@ -757,14 +907,2 @@ display: 'inline-block', | ||
PanZoom.defaultProps = { | ||
zoomSpeed: 1, | ||
doubleZoomSpeed: 1.75, | ||
minZoom: 0, | ||
maxZoom: Infinity, | ||
noStateUpdate: true, | ||
boundaryRatioVertical: 0.8, | ||
boundaryRatioHorizontal: 0.8, | ||
preventPan: () => false, | ||
} | ||
export default PanZoom |
Environment variable access
Supply chain riskPackage accesses environment variables, which may be a sign of credential stuffing or data theft.
Found 1 instance in 1 package
76831
8
1631
181
2
24
2
+ Addedwarning@4.0.3
+ Addedjs-tokens@4.0.0(transitive)
+ Addedloose-envify@1.4.0(transitive)
+ Addedwarning@4.0.3(transitive)