UNPKG

@nativescript-community/ui-drawer

Version:

Easily add a side drawer (side menu) to your projects.

959 lines 37.7 kB
import { GestureHandlerStateEvent, GestureHandlerTouchEvent, GestureState, HandlerType, Manager, install as installGestures } from '@nativescript-community/gesturehandler'; import { Animation, Application, CSSType, Color, CoreTypes, GridLayout, Property, Utils, booleanConverter } from '@nativescript/core'; installGestures(false); const OPEN_DURATION = 200; const CLOSE_DURATION = 200; export const PAN_GESTURE_TAG = 12431; const DEFAULT_TRIGGER_WIDTH = 20; const DEFAULT_TRIGGER_HEIGHT = 20; function transformAnimationValues(values) { values.translate = { x: values.translateX || 0, y: values.translateY || 0 }; values.scale = { x: values.scaleX || 1, y: values.scaleY || 1 }; delete values.translateX; delete values.translateY; delete values.scaleX; delete values.scaleY; return values; } export const leftDrawerContentProperty = new Property({ name: 'leftDrawer', defaultValue: undefined, valueChanged: (target, oldValue, newValue) => target._onDrawerContentChanged('left', oldValue, newValue) }); export const rightDrawerContentProperty = new Property({ name: 'rightDrawer', defaultValue: undefined, valueChanged: (target, oldValue, newValue) => target._onDrawerContentChanged('right', oldValue, newValue) }); export const topDrawerContentProperty = new Property({ name: 'topDrawer', defaultValue: undefined, valueChanged: (target, oldValue, newValue) => target._onDrawerContentChanged('top', oldValue, newValue) }); export const bottomDrawerContentProperty = new Property({ name: 'bottomDrawer', defaultValue: undefined, valueChanged: (target, oldValue, newValue) => target._onDrawerContentChanged('bottom', oldValue, newValue) }); export const gestureEnabledProperty = new Property({ name: 'gestureEnabled', defaultValue: true, valueConverter: booleanConverter }); export const backdropColorProperty = new Property({ name: 'backdropColor', valueConverter: (c) => (c ? new Color(c) : null) }); export const backdropPropertiesProperty = new Property({ name: 'backdropProperties' }); export const leftDrawerModeProperty = new Property({ name: 'leftDrawerMode' }); export const rightDrawerModeProperty = new Property({ name: 'rightDrawerMode' }); export const topDrawerModeProperty = new Property({ name: 'topDrawerMode' }); export const bottomDrawerModeProperty = new Property({ name: 'bottomDrawerMode' }); export const translationFunctionProperty = new Property({ name: 'translationFunction' }); export const animationFunctionProperty = new Property({ name: 'animationFunction' }); export const backDropEnabledProperty = new Property({ defaultValue: true, valueConverter: booleanConverter, name: 'backDropEnabled' }); export const startingSideProperty = new Property({ name: 'startingSide', defaultValue: null }); export const gestureHandlerOptionsProperty = new Property({ name: 'gestureHandlerOptions' }); const SIDES = ['left', 'right', 'top', 'bottom']; let Drawer = class Drawer extends GridLayout { constructor() { super(); this.gestureTag = PAN_GESTURE_TAG; this.gestureMinDist = 10; this.waitFor = []; this.simultaneousHandlers = []; this.leftSwipeDistance = 40; this.rightSwipeDistance = 40; this.bottomSwipeDistance = 40; this.topSwipeDistance = 40; this.backdropColor = new Color('rgba(0, 0, 0, 0.7)'); this.backdropProperties = {}; this.leftOpenedDrawerAllowDraging = true; this.rightOpenedDrawerAllowDraging = true; this.bottomOpenedDrawerAllowDraging = true; this.topOpenedDrawerAllowDraging = true; this.leftClosedDrawerAllowDraging = true; this.rightClosedDrawerAllowDraging = true; this.bottomClosedDrawerAllowDraging = true; this.topClosedDrawerAllowDraging = true; this.gestureEnabled = true; this.backdropTapGestureEnabled = true; this.openAnimationDuration = OPEN_DURATION; this.closeAnimationDuration = CLOSE_DURATION; this.mIsPanning = false; this.mIsAnimating = false; this.mPrevDeltaX = 0; this.mPrevDeltaY = 0; this.mViewWidth = { left: undefined, right: undefined }; this.mViewHeight = { bottom: undefined, top: undefined }; this.mTranslationX = { left: 0, right: 0 }; this.mTranslationY = { bottom: 0, top: 0 }; this.mShowingSide = null; // private mNeedToSetSide: Side | VerticalSide; this.mModes = {}; this.backDropEnabled = true; this.mViewByIdCache = {}; this.isPassThroughParentEnabled = true; } _onBackDropEnabledValueChanged() { if (this.backDropEnabled && !this.backDrop) { this.backDrop = new GridLayout(); this.backDrop.ignoreTouchAnimation = true; this.backDrop.backgroundColor = this.backdropColor; Object.assign(this.backDrop, this.backdropProperties); this.backDrop.opacity = 0; this.backDrop.visibility = 'hidden'; this.insertChild(this.backDrop, 0); } else if (!this.backDropEnabled && this.backDrop) { this.removeChild(this.backDrop); this.backDrop = null; } } [backDropEnabledProperty.setNative](value) { this._onBackDropEnabledValueChanged(); } getActualSide(side) { return SIDES.indexOf(side) >= 0 ? side : null; } updateStartingSide(side) { startingSideProperty.nativeValueChange(this, side); } [startingSideProperty.setNative](value) { value = this.getActualSide(value); if (value === this.mShowingSide) { return; } if (value && !this.mViewWidth[value] && !this.mViewHeight[value]) { this.mShowingSide = value; const drawer = this[value + 'Drawer']; if (drawer) { drawer.visibility = this.mShowingSide === value ? 'visible' : 'hidden'; } } else if (value) { this.open(value, 0); } else { this.close(value, 0); } } onBackdropTap() { this.close(); } initGestures() { const manager = Manager.getInstance(); const gestureHandler = manager.createGestureHandler(HandlerType.PAN, this.gestureTag, { shouldStartGesture: this.shouldStartGesture.bind(this), simultaneousHandlers: this.simultaneousHandlers, waitFor: this.waitFor, minDist: this.gestureMinDist, ...(this.gestureHandlerOptions || {}) }); gestureHandler.on(GestureHandlerTouchEvent, this.onGestureTouch, this); gestureHandler.on(GestureHandlerStateEvent, this.onGestureState, this); gestureHandler.attachToView(this); this.panGestureHandler = gestureHandler; } initNativeView() { if (this.backDropEnabled && !this.backDrop) { this[backDropEnabledProperty.setNative](this.backDropEnabled); } super.initNativeView(); if (this.backDrop && this.backdropTapGestureEnabled) { this.backDrop.on('tap', this.onBackdropTap, this); } if (this.gestureEnabled) { this.initGestures(); } } disposeNativeView() { super.disposeNativeView(); if (this.backDrop) { this.backDrop.off('tap', this.onBackdropTap, this); } if (this.panGestureHandler) { this.panGestureHandler.off(GestureHandlerTouchEvent, this.onGestureTouch, this); this.panGestureHandler.off(GestureHandlerStateEvent, this.onGestureState, this); this.panGestureHandler.detachFromView(); this.panGestureHandler = null; } } shouldStartSheetDraggingInternal(side) { let result = this[side + 'OpenedDrawerAllowDraging']; if (result && this.shouldStartSheetDragging) { result = this.shouldStartSheetDragging(side); } return result; } shouldStartGesture(data) { // const landscape = Application.orientation() === 'landscape'; const width = Utils.layout.toDeviceIndependentPixels(this.getMeasuredWidth()); const height = Utils.layout.toDeviceIndependentPixels(this.getMeasuredHeight()); const side = this.mShowingSide; if (side) { if (side === 'left' || side === 'right') { const viewWidth = this.mViewWidth[side]; if ((side === 'left' && data.x <= viewWidth) || (side === 'right' && data.x >= width - viewWidth)) { return this.shouldStartSheetDraggingInternal(side); } } else { const viewHeight = this.mViewHeight[side]; if ((side === 'top' && data.y <= viewHeight) || (side === 'bottom' && data.y >= height - viewHeight)) { return this.shouldStartSheetDraggingInternal(side); } } // for now without backDrop we force allow gesture return !this.backDrop || this.backDrop.opacity !== 0; } else { let needToSetSide; if (this.leftDrawer && (!this.leftSwipeDistance || data.x <= this.leftSwipeDistance)) { needToSetSide = 'left'; } else if (this.rightDrawer && (!this.rightSwipeDistance || data.x >= width - this.rightSwipeDistance)) { needToSetSide = 'right'; } else if (this.bottomDrawer && (!this.bottomSwipeDistance || data.y >= height - this.bottomSwipeDistance)) { needToSetSide = 'bottom'; } else if (this.topDrawer && (!this.topSwipeDistance || data.y <= this.topSwipeDistance)) { needToSetSide = 'top'; } if (needToSetSide && this[needToSetSide + 'ClosedDrawerAllowDraging']) { // this.mNeedToSetSide = needToSetSide; return true; } } return false; } getDrawerToOpen(extraData) { if (extraData.translationX < 0 && this.rightDrawer) { return 'right'; } else if (extraData.translationX > 0 && this.leftDrawer) { return 'left'; } else if (extraData.translationY < 0 && this.bottomDrawer) { return 'bottom'; } else if (extraData.translationY > 0 && this.topDrawer) { return 'top'; } return null; } onGestureState(args) { const { state, prevState, extraData, view } = args.data; if (state === GestureState.ACTIVE) { if (!this.mShowingSide) { const shouldShowSide = this.getDrawerToOpen(extraData); if (shouldShowSide && shouldShowSide !== this.mShowingSide) { this[shouldShowSide + 'Drawer'].visibility = 'visible'; this.mShowingSide = shouldShowSide; this.notify({ eventName: 'start', side: this.mShowingSide }); } // if (this.mNeedToSetSide === 'left') { // this.leftDrawer.visibility = 'visible'; // } else if (this.mNeedToSetSide === 'right') { // this.rightDrawer.visibility = 'visible'; // } else if (this.mNeedToSetSide === 'bottom') { // this.bottomDrawer.visibility = 'visible'; // } else if (this.mNeedToSetSide === 'top') { // this.topDrawer.visibility = 'visible'; // } } } this.updateIsPanning(state); if (prevState === GestureState.ACTIVE) { const side = this.mShowingSide; // const side = this.mShowingSide || this.mNeedToSetSide; // this.mNeedToSetSide = null; if (!side || (this.shouldPan && !this.shouldPan(side))) { return; } const { velocityX, velocityY, translationX, translationY } = extraData; const dragToss = 0.05; let destSnapPoint = 0; if (side === 'left' || side === 'right') { const viewWidth = this.mViewWidth[side]; const viewX = this.mTranslationX[side] - viewWidth; const x = translationX - this.mPrevDeltaX; this.mPrevDeltaX = 0; const totalDelta = x + dragToss * velocityX; if (side === 'left') { if (totalDelta < -DEFAULT_TRIGGER_WIDTH) { destSnapPoint = 0; } else if (totalDelta > DEFAULT_TRIGGER_WIDTH) { destSnapPoint = viewWidth; } else { const endOffsetX = viewX + totalDelta; const progress = Math.abs(endOffsetX / viewWidth); destSnapPoint = progress > 0.5 ? viewWidth : 0; } } else if (side === 'right') { if (-totalDelta < -DEFAULT_TRIGGER_WIDTH) { destSnapPoint = 0; } else if (-totalDelta > DEFAULT_TRIGGER_WIDTH) { destSnapPoint = viewWidth; } else { const endOffsetX = viewX + totalDelta; const progress = Math.abs(endOffsetX / viewWidth); destSnapPoint = progress > 0.5 ? viewWidth : 0; } } } else { const viewHeight = this.mViewHeight[side]; const viewY = this.mTranslationY[side] - viewHeight; const y = translationY - this.mPrevDeltaY; this.mPrevDeltaY = 0; const totalDelta = y + dragToss * velocityY; if (side === 'top') { if (totalDelta < -DEFAULT_TRIGGER_HEIGHT) { destSnapPoint = 0; } else if (totalDelta > DEFAULT_TRIGGER_HEIGHT) { destSnapPoint = viewHeight; } else { const endOffsetY = viewY + totalDelta; const progress = Math.abs(endOffsetY / viewHeight); destSnapPoint = progress > 0.5 ? viewHeight : 0; } } else if (side === 'bottom') { if (-totalDelta < -DEFAULT_TRIGGER_HEIGHT) { destSnapPoint = 0; } else if (-totalDelta > DEFAULT_TRIGGER_HEIGHT) { destSnapPoint = viewHeight; } else { const endOffsetY = viewY + totalDelta; const progress = Math.abs(endOffsetY / viewHeight); destSnapPoint = progress > 0.5 ? viewHeight : 0; } } } this.animateToPosition(side, destSnapPoint); } } isSideVisible(side) { if (side === 'left' || side === 'right') { return this.mViewWidth[side] - this.mTranslationX[side]; } else { return this.mViewHeight[side] - this.mTranslationY[side]; } } onGestureTouch(args) { const data = args.data; const { state, extraData, view } = args.data; // const side = this.mShowingSide || this.mNeedToSetSide; if (data.state !== GestureState.ACTIVE || this.mIsAnimating) { return; } const shouldShowSide = this.getDrawerToOpen(extraData); if (shouldShowSide && (!this.mShowingSide || (shouldShowSide !== this.mShowingSide && !this.isSideVisible(this.mShowingSide)))) { if (this.mShowingSide) { this[this.mShowingSide + 'Drawer'].visibility = 'hidden'; this.notify({ eventName: 'end', side: this.mShowingSide }); } this[shouldShowSide + 'Drawer'].visibility = 'visible'; this.mShowingSide = shouldShowSide; this.notify({ eventName: 'start', side: this.mShowingSide }); } const side = this.mShowingSide; if (!side || this.mIsAnimating) { return; } if (side === 'left' || side === 'right') { const deltaX = extraData.translationX; if (this.mIsAnimating || !this.mIsPanning || deltaX === 0 || (this.shouldPan && !this.shouldPan(side))) { this.mPrevDeltaX = deltaX; return; } // if (this.mNeedToSetSide) { // this.mShowingSide = this.mNeedToSetSide; // this.mNeedToSetSide = null; // } const width = this.mViewWidth[side]; const viewX = this.mTranslationX[side] - width; let x = deltaX - this.mPrevDeltaX; if (side === 'left') { x = -x; } const trX = this.constrainX(side, viewX + x); this.mTranslationX[side] = width + trX; const trData = this.computeTranslationData(side, width + trX); if (this.backDrop) { this.backDrop.visibility = trData.backDrop && trData.backDrop.opacity > 0 ? 'visible' : 'hidden'; } this.applyTrData(trData, side); this.updateIsPanning(state); this.mPrevDeltaX = deltaX; } else { const deltaY = extraData.translationY; if (this.mIsAnimating || !this.mIsPanning || deltaY === 0 || (this.shouldPan && !this.shouldPan(side))) { this.mPrevDeltaY = deltaY; return; } // if (this.mNeedToSetSide) { // this.mShowingSide = this.mNeedToSetSide; // this.mNeedToSetSide = null; // } const height = this.mViewHeight[side]; const viewY = this.mTranslationY[side] - height; let y = deltaY - this.mPrevDeltaY; if (side === 'top') { y = -y; } const trY = this.constrainY(side, viewY + y); this.mTranslationY[side] = height + trY; const trData = this.computeTranslationData(side, height + trY); if (this.backDrop) { this.backDrop.visibility = trData.backDrop && trData.backDrop.opacity > 0 ? 'visible' : 'hidden'; } this.applyTrData(trData, side); this.updateIsPanning(state); this.mPrevDeltaY = deltaY; } } [gestureEnabledProperty.setNative](value) { if (this.panGestureHandler) { this.panGestureHandler.enabled = value; } else if (value && !this.panGestureHandler) { this.initGestures(); } } [backdropColorProperty.setNative](value) { if (this.backDrop) { this.backDrop.backgroundColor = value; } } [backdropPropertiesProperty.setNative](value) { if (this.backDrop) { Object.assign(this.backDrop, this.backdropProperties || {}); } } [leftDrawerModeProperty.setNative](value) { this.onSideModeChanged('left', value); } [rightDrawerModeProperty.setNative](value) { this.onSideModeChanged('right', value); } [topDrawerModeProperty.setNative](value) { this.onSideModeChanged('top', value); } [bottomDrawerModeProperty.setNative](value) { this.onSideModeChanged('bottom', value); } [gestureHandlerOptionsProperty.setNative](value) { if (this.panGestureHandler) { Object.assign(this.panGestureHandler, value || {}); } } _onMainContentChanged(oldValue, newValue) { this._onBackDropEnabledValueChanged(); if (oldValue) { this.removeChild(oldValue); } if (newValue) { const indexBack = this.backDrop ? this.getChildIndex(this.backDrop) : 0; const index = this.getChildIndex(newValue); if (index !== indexBack - 1 && newValue.parent === this) { this.removeChild(newValue); this.insertChild(newValue, indexBack); } else { this.insertChild(newValue, indexBack); } } } leftLayoutChanged(event) { return this.onLayoutChange('left', event); } rightLayoutChanged(event) { return this.onLayoutChange('right', event); } topLayoutChanged(event) { return this.onLayoutChange('top', event); } bottomLayoutChanged(event) { return this.onLayoutChange('bottom', event); } addChild(child) { // for now we ignore this // to make sure we add the view in the property change // this is to make sure the view does not get "visible" too quickly // before we apply the translation // super.addChild(child); } _onDrawerContentChanged(side, oldValue, newValue) { if (oldValue === newValue) { return; } this._onBackDropEnabledValueChanged(); if (oldValue) { oldValue.off('layoutChanged', this[side + 'LayoutChanged'], this); this.removeChild(oldValue); } if (newValue) { // newValue.columns = "auto" if (side === 'left' || side === 'right') { newValue.horizontalAlignment = side; } else { newValue.verticalAlignment = side; } newValue.on('layoutChanged', this[side + 'LayoutChanged'], this); this.onSideModeChanged(side, this.mModes[side]); } } onSideModeChanged(side, mode, oldMode = this.mModes[side]) { if ((oldMode && oldMode === mode) || (oldMode && oldMode !== 'under' && mode !== 'under')) { return; } const drawer = this[side + 'Drawer']; if (!drawer) { return; } const indexBack = this.backDrop ? this.getChildIndex(this.backDrop) : 0; const index = this.getChildIndex(drawer); drawer.visibility = this.mShowingSide === side ? 'visible' : 'hidden'; if (mode === 'under') { if (index > indexBack - 1 && drawer.parent === this) { drawer.reusable = true; this.removeChild(drawer); this.insertChild(drawer, Math.max(indexBack - 1, 0)); } else if (drawer.parent !== this) { // initial addition // this.backDrop.visibility = trData.backDrop && trData.backDrop.opacity > 0 ? 'visible' : 'hidden'; this.insertChild(drawer, 0); } } else { if (index <= indexBack && drawer.parent === this) { drawer.reusable = true; this.removeChild(drawer); this.insertChild(drawer, indexBack + 1); } else if (drawer.parent !== this) { // initial addition this.insertChild(drawer, indexBack + 1); } } } computeTranslationData(side, value) { if (side === 'left' || side === 'right') { const width = this.mViewWidth[side]; const delta = Math.max(width - value, 0); const progress = delta / width; if (this.translationFunction) { return this.translationFunction(side, width, value, delta, progress, this); } if (this.mModes[side] === 'under') { return { mainContent: { translateX: side === 'right' ? -delta : delta }, [side + 'Drawer']: { translateX: 0 }, backDrop: { translateX: side === 'right' ? -delta : delta, opacity: progress } }; } else { return { mainContent: { // translateX: 0 }, [side + 'Drawer']: { translateX: side === 'left' ? -value : value }, backDrop: { // translateX: 0, opacity: progress } }; } } else { const height = this.mViewHeight[side]; const delta = Math.max(height - value, 0); const progress = delta / height; if (this.translationFunction) { return this.translationFunction(side, height, value, delta, progress, this); } if (this.mModes[side] === 'under') { return { mainContent: { translateY: side === 'bottom' ? -delta : delta }, [side + 'Drawer']: { translateY: 0 }, backDrop: { translateY: side === 'bottom' ? -delta : delta, opacity: progress } }; } else { return { mainContent: { translateY: 0 }, [side + 'Drawer']: { translateY: side === 'top' ? -value : value }, backDrop: { translateY: 0, opacity: progress } }; } } } onLayoutChange(side, event) { const contentView = event.object; let data; let safeAreaOffset = 0; let changed = false; const viewWidth = Utils.layout.toDeviceIndependentPixels(contentView.getMeasuredWidth()); const viewHeight = Utils.layout.toDeviceIndependentPixels(contentView.getMeasuredHeight()); if (side === 'left' || side === 'right') { if (__IOS__ && !this.iosIgnoreSafeArea) { const deviceOrientation = UIDevice.currentDevice.orientation; if (deviceOrientation === 3 /* UIDeviceOrientation.LandscapeLeft */) { safeAreaOffset = Application.ios.window.safeAreaInsets.left; } else if (deviceOrientation === 4 /* UIDeviceOrientation.LandscapeRight */) { safeAreaOffset = Application.ios.window.safeAreaInsets.right; } } const width = Math.ceil(Utils.layout.toDeviceIndependentPixels(contentView.getMeasuredWidth()) + safeAreaOffset); const firstSet = this.mViewWidth[side] === undefined; changed = width !== this.mViewWidth[side]; this.mViewWidth[side] = width; if (firstSet) { const offset = this.mShowingSide === side ? 0 : width; data = this.computeTranslationData(side, offset); const shown = this.mViewWidth[side] - offset; this.mTranslationX[side] = width - shown; } else { this.mTranslationX[side] = this.mTranslationX[side] === 0 ? 0 : width; } } else { safeAreaOffset = __IOS__ && !this.iosIgnoreSafeArea && Application.ios.window.safeAreaInsets ? Application.ios.window.safeAreaInsets.bottom : 0; const height = Math.ceil(viewHeight + safeAreaOffset); const firstSet = this.mViewHeight[side] === undefined; changed = height !== this.mViewHeight[side]; this.mViewHeight[side] = height; if (firstSet) { const offset = this.mShowingSide === side ? 0 : height; data = this.computeTranslationData(side, offset); const shown = this.mViewHeight[side] - offset; this.mTranslationY[side] = height - shown; } else { this.mTranslationY[side] = this.mTranslationY[side] === 0 ? 0 : height; } } if (changed && data) { // delay applyTrData or it will create a layout issue on iOS setTimeout(() => { this.applyTrData(data, side); if (this.backDrop) { this.backDrop.visibility = data.backDrop && data.backDrop.opacity > 0 ? 'visible' : 'hidden'; } }, 0); } } forceEnsureSize(side) { const contentView = this[side + 'Drawer']; let data; let safeAreaOffset = 0; if (side === 'left' || side === 'right') { if (__IOS__ && !this.iosIgnoreSafeArea) { const deviceOrientation = UIDevice.currentDevice.orientation; if (deviceOrientation === 3) { safeAreaOffset = Application.ios.window.safeAreaInsets.left; } else if (deviceOrientation === 4) { safeAreaOffset = Application.ios.window.safeAreaInsets.right; } } const width = Math.ceil(Utils.layout.toDeviceIndependentPixels(contentView.getMeasuredWidth()) + safeAreaOffset); this.mViewWidth[side] = width; } else { safeAreaOffset = __IOS__ && !this.iosIgnoreSafeArea && Application.ios.window.safeAreaInsets ? Application.ios.window.safeAreaInsets.bottom : 0; const height = Math.ceil(Utils.layout.toDeviceIndependentPixels(contentView.getMeasuredHeight()) + safeAreaOffset); this.mViewHeight[side] = height; } } onTapGestureState(args) { const { state } = args.data; if (state === GestureState.BEGAN) { this.close(); } } updateIsPanning(state) { this.mIsPanning = state === GestureState.ACTIVE || state === GestureState.BEGAN; } applyTrData(trData, side) { const cache = this.mViewByIdCache; Object.keys(trData).forEach((k) => { let target = this[k] || cache[k]; if (!target) { target = this.getViewById(k); if (target) { cache[k] = target; } } if (target) { Object.assign(target, trData[k]); } }); } constrainX(side, x) { const width = this.mViewWidth[side]; if (x > 0) { return 0; } else if (x < -width) { return -width; } return x; } constrainY(side, y) { const height = this.mViewHeight[side]; if (y > 0) { return 0; } else if (y < -height) { return -height; } return y; } async animateToPosition(side, position, duration = this.openAnimationDuration) { if (this.mShowingSide && side !== this.mShowingSide) { this.animateToPosition(this.mShowingSide, 0, duration); } // const shouldSendEvent = side !== this.mShowingSide || (this.mShowingSide === side && position === 0); // TODO: why did we not send event every time? const shouldSendEvent = true; let trData; if (side === 'left' || side === 'right') { const width = this.mViewWidth[side]; trData = this.computeTranslationData(side, width - position); this.mTranslationX[side] = width - position; } else { const height = this.mViewHeight[side]; trData = this.computeTranslationData(side, height - position); this.mTranslationY[side] = height - position; } if (position !== 0) { this.mShowingSide = side; const drawer = this[side + 'Drawer']; if (drawer) { drawer.visibility = 'visible'; } if (this.backDrop && trData.backDrop && trData.backDrop.opacity > 0 && this.backDrop.visibility !== 'visible') { this.backDrop.opacity = 0; this.backDrop.visibility = 'visible'; } } else { this.mShowingSide = null; } // TODO: custom animation curve + apply curve on gesture const params = []; Object.keys(trData).forEach((k) => { if (this[k]) { const animatedParams = duration ? transformAnimationValues(trData[k]) : trData[k]; if (Object.keys(animatedParams).length) { const animParam = Object.assign({ target: this[k], curve: CoreTypes.AnimationCurve.easeInOut, duration }, animatedParams); params.push(animParam); } } }); try { if (duration) { if (this.animationFunction) { await this.animationFunction(side, duration, trData, params, this); } await new Animation(params).play(); } } catch (err) { console.error('animateToPosition', this, err, err.stack); throw err; } finally { // apply tr data to prevent hickups on iOS // and handle animation cancelled errors if ((position !== 0 && this.mShowingSide === side) || (position === 0 && !this.mShowingSide)) { this.applyTrData(trData, this.mShowingSide); if (position !== 0) { // if (trData.backDrop) { // this.backDrop.opacity = 1; // } } else { const drawer = this[side + 'Drawer']; if (drawer) { drawer.visibility = 'hidden'; } if (this.backDrop) { this.backDrop.visibility = 'hidden'; } } } if (shouldSendEvent) { if (position === 0) { this.notify({ eventName: 'close', side, duration }); } else { this.notify({ eventName: 'open', side, duration }); } } } } isSideOpened() { return !!this.mShowingSide; } isOpened(side) { if (side) { return this.mShowingSide === side; } return !!this.mShowingSide; } getDefaultSide() { if (this.leftDrawer) { return 'left'; } else if (this.rightDrawer) { return 'right'; } else if (this.bottomDrawer) { return 'bottom'; } else if (this.topDrawer) { return 'top'; } return null; } async toggle(side) { side = this.getActualSide(side) || this.getDefaultSide(); if (!side) { return; } if (this.isOpened(side)) { this.close(side); } else { this.open(side); } } async open(side, duration = this.openAnimationDuration) { side = this.getActualSide(side) || this.getDefaultSide(); if (!side) { return; } if (this.mShowingSide && this.mShowingSide !== side) { this.close(); } if (!this.isOpened(side)) { this.forceEnsureSize(side); } if (side === 'left' || side === 'right') { this.animateToPosition(side, this.mViewWidth[side], duration); } else { this.animateToPosition(side, this.mViewHeight[side], duration); } } async close(side, duration = this.closeAnimationDuration) { side = this.getActualSide(side) || this.mShowingSide; if (!side) { return; } // this.mShowingSide = null; return this.animateToPosition(side, 0, duration); } }; Drawer = __decorate([ CSSType('Drawer') ], Drawer); export { Drawer }; export const mainContentProperty = new Property({ name: 'mainContent', defaultValue: undefined, valueChanged: (target, oldValue, newValue) => { target._onMainContentChanged(oldValue, newValue); } }); mainContentProperty.register(Drawer); backdropColorProperty.register(Drawer); leftDrawerContentProperty.register(Drawer); rightDrawerContentProperty.register(Drawer); topDrawerContentProperty.register(Drawer); bottomDrawerContentProperty.register(Drawer); gestureEnabledProperty.register(Drawer); leftDrawerModeProperty.register(Drawer); rightDrawerModeProperty.register(Drawer); bottomDrawerModeProperty.register(Drawer); topDrawerModeProperty.register(Drawer); translationFunctionProperty.register(Drawer); animationFunctionProperty.register(Drawer); backDropEnabledProperty.register(Drawer); startingSideProperty.register(Drawer); gestureHandlerOptionsProperty.register(Drawer); export function install() { installGestures(); } //# sourceMappingURL=index.js.map