/**
 * Copyright 2020 Google Inc. All Rights Reserved.
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *     http://www.apache.org/licenses/LICENSE-2.0
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */ import type PinchZoom from 'pinch-zoom-element' ; import { Component , h , createRef , VNode } from 'preact' ; import 'two-up-element' ; import 'pinch-zoom-element' ; interface Props { left : VNode ; right : VNode ; } interface State { desktopMode : boolean ; } const desktopMedia = matchMedia ( '(min-width: 550px)' ) ; export default class ZoomableTwoUp extends Component < Props , State > { state : State = { desktopMode : desktopMedia . matches , } ; private _retargetedEvents = new WeakSet < Event > ( ) ; private _pinchZoomLeft = createRef < PinchZoom > ( ) ; private _pinchZoomRight = createRef < PinchZoom > ( ) ; param event private _onRetargetableEvent = ( event ) => { const targetEl = event . target as HTMLElement ; if ( ! this . _pinchZoomLeft . current ) throw Error ( 'Missing pinch-zoom element' ) ; if ( event . type !== 'wheel' && ! targetEl . closest ( `pinch-zoom` ) ) return ; if ( this . _retargetedEvents . has ( event ) ) return ; event . stopImmediatePropagation ( ) ; event . preventDefault ( ) ; const clonedEvent = new ( event . constructor as typeof Event ) ( event . type , event ) ; this . _retargetedEvents . add ( clonedEvent ) ; this . _pinchZoomLeft . current . dispatchEvent ( clonedEvent ) ; if ( event . type === 'touchend' && document . activeElement && document . activeElement instanceof HTMLElement ) { document . activeElement . blur ( ) ; } } ; private _onPinchZoomLeftChange = ( ) => { if ( ! this . _pinchZoomRight . current || ! this . _pinchZoomLeft . current ) { throw Error ( 'Missing pinch-zoom element' ) ; } this . _pinchZoomRight . current . setTransform ( { scale : this . _pinchZoomLeft . current . scale , x : this . _pinchZoomLeft . current . x , y : this . _pinchZoomLeft . current . y , } ) ; } ; private _onMediaChange = ( ) => { this . setState ( { desktopMode : desktopMedia . matches } ) ; } ; componentDidMount ( ) { desktopMedia . addListener ( this . _onMediaChange ) ; } componentWillUnmount ( ) { desktopMedia . removeListener ( this . _onMediaChange ) ; } render ( { left , right } , { desktopMode } ) { return ( < two - up orientation = { desktopMode ? 'horizontal' : 'vertical' } class = "two-up" onTouchStartCapture = { this . _onRetargetableEvent } onTouchEndCapture = { this . _onRetargetableEvent } onTouchMoveCapture = { this . _onRetargetableEvent } onPointerDownCapture = { this . _onRetargetableEvent } onMouseDownCapture = { this . _onRetargetableEvent } onWheelCapture = { this . _onRetargetableEvent } > < pinch - zoom class = "pinch-zoom" ref = { this . _pinchZoomLeft } onChange = { this . _onPinchZoomLeftChange } > < div > { left } < /div> < /pinch-zoom> < pinch - zoom class = "pinch-zoom" ref = { this . _pinchZoomRight } > < div > { right } < /div> < /pinch-zoom> < /two-up>); } }