diff --git a/docs/components/interactive-map.md b/docs/components/interactive-map.md index 8af5c188d..a624f34ac 100644 --- a/docs/components/interactive-map.md +++ b/docs/components/interactive-map.md @@ -253,7 +253,11 @@ Called when the map is hovered over with mouse (not pressed). Receives a [Pointe ##### `onClick` {Function} -Called when the map is clicked. Receives a [PointerEvent](/docs/components/pointer-event.md) object. +Called when the map is single clicked. Receives a [PointerEvent](/docs/components/pointer-event.md) object. This event is not fired on double click therefore there may be a delay between pointer up and the event. + +##### `onNativeClick` {Function} + +Called when the map is clicked. Receives a [PointerEvent](/docs/components/pointer-event.md) object. This event is fired twice on double click. ##### `onDblClick` {Function} diff --git a/package.json b/package.json index 55518220c..13dac6dce 100644 --- a/package.json +++ b/package.json @@ -45,7 +45,7 @@ "dependencies": { "@babel/runtime": "^7.0.0", "mapbox-gl": "~0.52.0", - "mjolnir.js": "^2.0.3", + "mjolnir.js": "^2.1.0", "prop-types": "^15.5.7", "react-virtualized-auto-sizer": "^1.0.2", "viewport-mercator-project": "^6.1.0" diff --git a/src/components/base-control.js b/src/components/base-control.js index 4178fc5ff..ad9f59f4d 100644 --- a/src/components/base-control.js +++ b/src/components/base-control.js @@ -74,8 +74,9 @@ export default class BaseControl extends PureComponent { this._events = { wheel: this._onScroll, panstart: this._onDragStart, + anyclick: this._onClick, click: this._onClick, - pointerup: this._onPointerUp + dblclick: this._onDblClick }; eventManager.on(this._events, ref); } @@ -104,18 +105,9 @@ export default class BaseControl extends PureComponent { } } - _onPointerUp = (evt: MjolnirEvent) => { + _onDblClick = (evt: MjolnirEvent) => { if (this.props.captureDoubleClick) { - const {eventManager} = this._context; - const {options: {enable}} = eventManager.manager.get('doubletap'); - // Temporarily disable doubletap - if (enable) { - eventManager._toggleRecognizer('doubletap', false); - /* global setTimeout */ - setTimeout(() => { - eventManager._toggleRecognizer('doubletap', true); - }, 0); - } + evt.stopPropagation(); } } diff --git a/src/components/interactive-map.js b/src/components/interactive-map.js index dd6020cf9..754ecc9f0 100644 --- a/src/components/interactive-map.js +++ b/src/components/interactive-map.js @@ -109,6 +109,7 @@ const defaultProps = Object.assign({}, onViewStateChange: null, onViewportChange: null, onClick: null, + onNativeClick: null, onHover: null, onContextMenu: event => event.preventDefault(), @@ -142,6 +143,7 @@ type InteractiveMapProps = StaticMapProps & { onInteractionStateChange: Function, onHover: Function, onClick: Function, + onNativeClick: Function, onDblClick: Function, onContextMenu: Function, onMouseDown: Function, @@ -154,6 +156,20 @@ type InteractiveMapProps = StaticMapProps & { onMouseLeave: Function, onMouseOut: Function, onWheel: Function, + + transitionDuration: number, + transitionInterpolator: any, + transitionInterruption: number, + transitionEasing: Function, + + scrollZoom: boolean, + dragPan: boolean, + dragRotate: boolean, + doubleClickZoom: boolean, + touchZoom: boolean, + touchRotate: boolean, + keyboard: boolean, + touchAction: string, clickRadius: number, interactiveLayerIds: Array, @@ -222,6 +238,7 @@ export default class InteractiveMap extends PureComponent { - if (this.props.onClick) { + const {onClick, onNativeClick, onDblClick, doubleClickZoom} = this.props; + let callbacks = []; + const isDoubleClickEnabled = onDblClick || doubleClickZoom; + + // `click` is only fired on single click. `anyclick` is fired twice if double clicking. + // `click` has a delay period after pointer up that prevents it from firing when + // double clicking. `anyclick` is always fired immediately after pointer up. + // If double click is turned off by the user, we want to immediately fire the + // onClick event. Otherwise, we wait to make sure it's a single click. + switch (event.type) { + case 'anyclick': + callbacks.push(onNativeClick); + if (!isDoubleClickEnabled) { + callbacks.push(onClick); + } + break; + + case 'click': + if (isDoubleClickEnabled) { + callbacks.push(onClick); + } + break; + + default: + } + + callbacks = callbacks.filter(Boolean); + + if (callbacks.length) { event = this._normalizeEvent(event); // backward compatibility: v3 `onClick` interface event.features = this._getFeatures({pos: event.point, radius: this.props.clickRadius}); - this.props.onClick(event); + callbacks.forEach(cb => cb(event)); } } diff --git a/yarn.lock b/yarn.lock index facc50335..c02dea34b 100644 --- a/yarn.lock +++ b/yarn.lock @@ -6087,10 +6087,10 @@ mixin-deep@^1.2.0: for-in "^1.0.2" is-extendable "^1.0.1" -mjolnir.js@^2.0.3: - version "2.0.3" - resolved "https://registry.yarnpkg.com/mjolnir.js/-/mjolnir.js-2.0.3.tgz#2354d31bc966a13f18d3bc350d5491acfb562914" - integrity sha512-3AvoMwJCR3m9QQYzsE+D+LWZ9N2uWbl7prixSJGRZNOpaagRgiXJeVvDEHTiXAGmNhdn/VAtgWrx3lpdrj2sIQ== +mjolnir.js@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/mjolnir.js/-/mjolnir.js-2.1.0.tgz#e8a4727e86d8f9352d6b6fe9cdc6faab0dcff15e" + integrity sha512-XVvwByhXGvgWJs/mFsekE1cmg3l/KrRIqaJ5oO5DFEyG//NbQssPIuFOjKrZYQ4rFkRZRq+FN4EcecUPSGR89g== dependencies: "@babel/runtime" "^7.0.0" hammerjs "^2.0.8"