cupertino-pane
Advanced tools
Comparing version 1.1.7 to 1.1.8
# Change Log | ||
All notable changes to this project will be documented in this file. | ||
## 1.1.8 - 2020-08-29 | ||
### BREAKING CHANGES | ||
- Property `offset` for breaks are not more under support. Renamed with `height` | ||
```javascript | ||
breaks: { | ||
... | ||
middle: { | ||
enabled: true, | ||
height: 400 | ||
} | ||
} | ||
``` | ||
### Features | ||
- Added `upperThanTop` settings property | ||
- Added `touchMoveStopPropagation` settings property. Set `true` to prevent all move events behind pane and backdrop [#55](https://github.com/roman-rr/cupertino-pane/issues/55) | ||
- Added `bounce` property for breakpoints (transition in apple stocks style) | ||
```javascript | ||
breaks: { | ||
... | ||
middle: { | ||
enabled: true, | ||
height: 400, | ||
bounce: true | ||
} | ||
} | ||
``` | ||
- Added `touchAngle` settings property which allow user set possible pane move angle. Helps to handle horizontal slider elements inside pane such as `ion-item-sliding` [#23](https://github.com/roman-rr/cupertino-pane/issues/23) | ||
- Added **3d push effect** within `pushElement` and `pushMinHeight` properties | ||
```javascript | ||
const settings = { | ||
... | ||
parentElement: 'ion-tabs', | ||
pushElement: 'app-home', | ||
pushMinHeight: 350 | ||
} | ||
``` | ||
### Bug Fixes | ||
- Improved drag top gesture | ||
- Auto-preventing accidental unwanted clicks events during pane move gestures by `preventClicks` parameter | ||
- Close button touch area fixed | ||
## 1.1.7 - 2020-07-22 | ||
@@ -6,0 +50,0 @@ |
@@ -9,3 +9,4 @@ import { Settings } from './models'; | ||
private steps; | ||
private startP; | ||
private startY; | ||
private startX; | ||
private pointerDown; | ||
@@ -16,5 +17,6 @@ private topper; | ||
private contentScrollTop; | ||
private draggableScrollOffset; | ||
private disableDragEvents; | ||
private disableDragAngle; | ||
private rendered; | ||
private allowClick; | ||
private breaks; | ||
@@ -42,3 +44,7 @@ private brs; | ||
*/ | ||
private attachAllEvents; | ||
private detachAllEvents; | ||
private resetEvents; | ||
private scrollElementInit; | ||
private getTimingFunction; | ||
private checkOpacityAttr; | ||
@@ -61,2 +67,8 @@ private checkOverflowAttr; | ||
*/ | ||
private touchMoveBackdropCb; | ||
private touchMoveBackdrop; | ||
/** | ||
* Touch Move Event | ||
* @param t | ||
*/ | ||
private touchMoveCb; | ||
@@ -70,2 +82,8 @@ private touchMove; | ||
private touchEnd; | ||
/** | ||
* Click Event | ||
* @param t | ||
*/ | ||
private onClickCb; | ||
private onClick; | ||
private swipeNextPoint; | ||
@@ -106,2 +124,3 @@ private isBackdropPresented; | ||
}): any; | ||
private pushTransition; | ||
/*********************************** | ||
@@ -108,0 +127,0 @@ * Transitions handler |
/** | ||
* Cupertino Pane 1.1.7 | ||
* Cupertino Pane 1.1.8 | ||
* Multiplatform slide-over pane | ||
@@ -10,3 +10,3 @@ * https://github.com/roman-rr/cupertino-pane/ | ||
* | ||
* Released on: July 22, 2020 | ||
* Released on: August 28, 2020 | ||
*/ | ||
@@ -158,2 +158,4 @@ | ||
followerElement: null, | ||
pushElement: null, | ||
pushMinHeight: null, | ||
backdrop: false, | ||
@@ -172,7 +174,11 @@ backdropOpacity: 0.4, | ||
lowerThanBottom: true, | ||
upperThanTop: false, | ||
showDraggable: true, | ||
draggableOver: false, | ||
clickBottomOpen: true, | ||
preventClicks: true, | ||
simulateTouch: true, | ||
passiveListeners: true, | ||
touchMoveStopPropagation: false, | ||
touchAngle: null, | ||
breaks: {}, | ||
@@ -199,5 +205,6 @@ onDidDismiss: () => { }, | ||
this.contentScrollTop = 0; | ||
this.draggableScrollOffset = 0; | ||
this.disableDragEvents = false; | ||
this.disableDragAngle = false; | ||
this.rendered = false; | ||
this.allowClick = true; | ||
this.breaks = {}; | ||
@@ -215,2 +222,7 @@ this.brs = []; | ||
*/ | ||
this.touchMoveBackdropCb = (t) => this.touchMoveBackdrop(t); | ||
/** | ||
* Touch Move Event | ||
* @param t | ||
*/ | ||
this.touchMoveCb = (t) => this.touchMove(t); | ||
@@ -222,2 +234,7 @@ /** | ||
this.touchEndCb = (t) => this.touchEnd(t); | ||
/** | ||
* Click Event | ||
* @param t | ||
*/ | ||
this.onClickCb = (t) => this.onClick(t); | ||
this.swipeNextPoint = (diff, maxDiff, closest) => { | ||
@@ -378,2 +395,3 @@ if (this.currentBreakpoint === this.breaks['top']) { | ||
this.closeEl.style.right = '20px'; | ||
this.closeEl.style.zIndex = '14'; | ||
this.closeEl.style.borderRadius = '100%'; | ||
@@ -411,4 +429,4 @@ } | ||
&& this.settings.breaks[val].enabled | ||
&& (this.settings.breaks[val].offset || this.settings.breaks[val].height)) { | ||
this.breaks[val] -= (this.settings.breaks[val].offset || this.settings.breaks[val].height); | ||
&& this.settings.breaks[val].height) { | ||
this.breaks[val] -= this.settings.breaks[val].height; | ||
} | ||
@@ -457,4 +475,7 @@ }); | ||
this.followerEl.style.transform = `translateY(0px) translateZ(0px)`; | ||
this.followerEl.style.transition = `all ${this.settings.animationDuration}ms ${this.settings.animationType} 0s`; | ||
this.followerEl.style.transition = `all ${this.settings.animationDuration}ms ${this.getTimingFunction(this.settings.breaks[this.currentBreak()].bounce)} 0s`; | ||
} | ||
if (this.settings.pushElement) { | ||
this.settings.pushElement = document.querySelector(this.settings.pushElement); | ||
} | ||
if (!this.settings.showDraggable) { | ||
@@ -531,2 +552,19 @@ this.draggableEl.style.opacity = '0'; | ||
/****** Attach Events *******/ | ||
this.attachAllEvents(); | ||
/****** Animation & Transition ******/ | ||
if (conf.animate) { | ||
this.doTransition({ type: 'present', translateY: this.breaks[this.settings.initialBreak] }); | ||
} | ||
else { | ||
// Emit event | ||
if (this.settings.pushElement) { | ||
this.pushTransition(this.breaks[this.settings.initialBreak], 'unset'); | ||
} | ||
this.settings.onDidPresent(); | ||
} | ||
} | ||
/** | ||
* Private Utils methods | ||
*/ | ||
attachAllEvents() { | ||
if (!this.settings.dragBy) { | ||
@@ -542,14 +580,19 @@ this.attachEvents(this.paneEl); | ||
} | ||
/****** Animation & Transition ******/ | ||
if (conf.animate) { | ||
this.doTransition({ type: 'present', translateY: this.breaks[this.settings.initialBreak] }); | ||
} | ||
detachAllEvents() { | ||
if (!this.settings.dragBy) { | ||
this.detachEvents(this.paneEl); | ||
} | ||
else { | ||
// Emit event | ||
this.settings.onDidPresent(); | ||
this.settings.dragBy.forEach((selector) => { | ||
const el = document.querySelector(selector); | ||
if (el) | ||
this.detachEvents(el); | ||
}); | ||
} | ||
} | ||
/** | ||
* Private Utils methods | ||
*/ | ||
resetEvents() { | ||
this.detachAllEvents(); | ||
this.attachAllEvents(); | ||
} | ||
scrollElementInit() { | ||
@@ -575,2 +618,5 @@ let attrElements = this.el.querySelectorAll('[overflow-y]'); | ||
} | ||
getTimingFunction(bounce) { | ||
return bounce ? 'cubic-bezier(0.175, 0.885, 0.370, 1.120)' : this.settings.animationType; | ||
} | ||
checkOpacityAttr(val) { | ||
@@ -608,14 +654,25 @@ let attrElements = this.el.querySelectorAll('[hide-on-bottom]'); | ||
return; | ||
// Allow clicks by default, disallow on move | ||
this.allowClick = true; | ||
// Allow touch angle by default, disallow no move with condition | ||
this.disableDragAngle = false; | ||
const targetTouch = t.type === 'touchstart' && t.targetTouches && (t.targetTouches[0] || t.changedTouches[0]); | ||
const screenY = t.type === 'touchstart' ? targetTouch.screenY : t.screenY; | ||
const screenX = t.type === 'touchstart' ? targetTouch.screenX : t.screenX; | ||
if (t.type === 'mousedown') | ||
this.pointerDown = true; | ||
this.startP = screenY; | ||
this.startY = screenY; | ||
this.startX = screenX; | ||
// if overflow content was scrolled | ||
// increase to scrolled value | ||
if (this.isDragScrollabe(t.path || t.composedPath())) { | ||
this.startP += this.contentScrollTop; | ||
this.startY += this.contentScrollTop; | ||
} | ||
this.steps.push(this.startP); | ||
this.steps.push(this.startY); | ||
} | ||
touchMoveBackdrop(t) { | ||
if (this.settings.touchMoveStopPropagation) { | ||
t.stopPropagation(); | ||
} | ||
} | ||
touchMove(t) { | ||
@@ -626,5 +683,11 @@ // Event emitter | ||
return; | ||
if (this.disableDragAngle) | ||
return; | ||
if (this.settings.touchMoveStopPropagation) { | ||
t.stopPropagation(); | ||
} | ||
// Handle desktop/mobile events | ||
const targetTouch = t.type === 'touchmove' && t.targetTouches && (t.targetTouches[0] || t.changedTouches[0]); | ||
const screenY = t.type === 'touchmove' ? targetTouch.screenY : t.screenY; | ||
const screenX = t.type === 'touchmove' ? targetTouch.screenX : t.screenX; | ||
if (t.type === 'mousemove' && !this.pointerDown) | ||
@@ -634,4 +697,17 @@ return; | ||
let n = screenY; | ||
const diff = n - this.steps[this.steps.length - 1]; | ||
const newVal = this.getPanelTransformY() + diff; | ||
let v = screenX; | ||
const diffY = n - this.steps[this.steps.length - 1]; | ||
let newVal = this.getPanelTransformY() + diffY; | ||
// Touch angle | ||
if (this.settings.touchAngle) { | ||
let touchAngle; | ||
const diffX = v - this.startX; | ||
const diffY = n - this.startY; | ||
touchAngle = (Math.atan2(Math.abs(diffY), Math.abs(diffX)) * 180) / Math.PI; | ||
if (diffX * diffX + diffY * diffY >= 25 | ||
&& (90 - touchAngle > this.settings.touchAngle)) { | ||
this.disableDragAngle = true; | ||
return; | ||
} | ||
} | ||
// Not allow move panel with positive overflow scroll | ||
@@ -649,6 +725,14 @@ if (this.isDragScrollabe(t.path || t.composedPath()) | ||
} | ||
// Not allow drag upper than topper point | ||
// Not allow drag topper than top point | ||
if (newVal <= this.topper && !this.settings.upperThanTop) { | ||
this.paneEl.style.transform = `translateY(${this.topper}px) translateZ(0px)`; | ||
return; | ||
} | ||
// Allow drag topper than top point | ||
if (newVal <= this.topper && this.settings.upperThanTop) { | ||
const differKoef = ((-this.topper + this.topper - this.getPanelTransformY()) / this.topper) / -8; | ||
newVal = this.getPanelTransformY() + (diffY * differKoef); | ||
} | ||
// Not allow drag lower than bottom if free mode | ||
if ((newVal <= this.topper) | ||
|| (this.settings.freeMode && !this.settings.bottomClose && (newVal >= this.bottomer))) { | ||
if (this.settings.freeMode && !this.settings.bottomClose && (newVal >= this.bottomer)) { | ||
return; | ||
@@ -662,2 +746,4 @@ } | ||
} | ||
// Disallow accidentaly clicks while slide gestures | ||
this.allowClick = false; | ||
this.checkOpacityAttr(newVal); | ||
@@ -707,2 +793,12 @@ this.checkOverflowAttr(newVal); | ||
} | ||
onClick(t) { | ||
// Prevent accidental unwanted clicks events during swiping | ||
if (!this.allowClick) { | ||
if (this.settings.preventClicks) { | ||
t.preventDefault(); | ||
t.stopPropagation(); | ||
t.stopImmediatePropagation(); | ||
} | ||
} | ||
} | ||
isBackdropPresented() { | ||
@@ -729,2 +825,4 @@ return document.querySelector(`.cupertino-pane-wrapper .backdrop`) | ||
this.backdropEl.addEventListener('click', (t) => this.settings.onBackdropTap()); | ||
// Reset events to attach backdrop stop propagation | ||
this.resetEvents(); | ||
} | ||
@@ -764,2 +862,3 @@ /** | ||
attachEvents(el) { | ||
var _a, _b, _c; | ||
// Touch Events | ||
@@ -770,2 +869,4 @@ if (!Support.touch && Support.pointerEvents) { | ||
el.addEventListener(this.touchEvents.end, this.touchEndCb, false); | ||
// Backdrop propagation fix | ||
(_a = this.backdropEl) === null || _a === void 0 ? void 0 : _a.addEventListener(this.touchEvents.move, this.touchMoveBackdropCb, false); | ||
} | ||
@@ -778,2 +879,4 @@ else { | ||
el.addEventListener(this.touchEvents.end, this.touchEndCb, passiveListener); | ||
// Backdrop propagation fix | ||
(_b = this.backdropEl) === null || _b === void 0 ? void 0 : _b.addEventListener(this.touchEvents.move, this.touchMoveBackdropCb, Support.passiveListener ? { passive: false, capture: false } : false); | ||
if (this.touchEvents['cancel']) { | ||
@@ -787,6 +890,13 @@ el.addEventListener(this.touchEvents['cancel'], this.touchEndCb, passiveListener); | ||
el.addEventListener('mouseup', this.touchEndCb, false); | ||
// Backdrop propagation fix | ||
(_c = this.backdropEl) === null || _c === void 0 ? void 0 : _c.addEventListener('mousemove', this.touchMoveBackdropCb, false); | ||
} | ||
} | ||
// Prevent accidental unwanted clicks events during swiping | ||
if (this.settings.preventClicks) { | ||
el.addEventListener('click', this.onClickCb, true); | ||
} | ||
} | ||
detachEvents(el) { | ||
var _a, _b, _c; | ||
// Touch Events | ||
@@ -797,2 +907,4 @@ if (!Support.touch && Support.pointerEvents) { | ||
el.removeEventListener(this.touchEvents.end, this.touchEndCb, false); | ||
// Backdrop propagation fix | ||
(_a = this.backdropEl) === null || _a === void 0 ? void 0 : _a.removeEventListener(this.touchEvents.move, this.touchMoveBackdropCb, false); | ||
} | ||
@@ -805,2 +917,4 @@ else { | ||
el.removeEventListener(this.touchEvents.end, this.touchEndCb, passiveListener); | ||
// Backdrop propagation fix | ||
(_b = this.backdropEl) === null || _b === void 0 ? void 0 : _b.removeEventListener(this.touchEvents.move, this.touchMoveBackdropCb, false); | ||
if (this.touchEvents['cancel']) { | ||
@@ -814,4 +928,10 @@ el.removeEventListener(this.touchEvents['cancel'], this.touchEndCb, passiveListener); | ||
el.removeEventListener('mouseup', this.touchEndCb, false); | ||
// Backdrop propagation fix | ||
(_c = this.backdropEl) === null || _c === void 0 ? void 0 : _c.removeEventListener('mousemove', this.touchMoveBackdropCb, false); | ||
} | ||
} | ||
// Prevent accidental unwanted clicks events during swiping | ||
if (this.settings.preventClicks) { | ||
el.removeEventListener('click', this.onClickCb, true); | ||
} | ||
} | ||
@@ -887,12 +1007,3 @@ getPanelTransformY() { | ||
/****** Detach Events *******/ | ||
if (!this.settings.dragBy) { | ||
this.detachEvents(this.paneEl); | ||
} | ||
else { | ||
this.settings.dragBy.forEach((selector) => { | ||
const el = document.querySelector(selector); | ||
if (el) | ||
this.detachEvents(el); | ||
}); | ||
} | ||
this.detachAllEvents(); | ||
// Reset vars | ||
@@ -920,2 +1031,28 @@ this.currentBreakpoint = this.breaks[this.settings.initialBreak]; | ||
} | ||
pushTransition(newPaneY, transition) { | ||
newPaneY = this.screen_height - newPaneY; | ||
const topHeight = this.settings.pushMinHeight ? this.settings.pushMinHeight : this.screen_height - this.bottomer; | ||
const minHeight = this.screen_height - this.topper; | ||
this.settings.pushElement.style.transition = transition; | ||
const setStyles = (scale, y, border, contrast) => { | ||
this.settings.pushElement.style.transform = `translateY(${y}px) scale(${scale})`; | ||
this.settings.pushElement.style.borderRadius = `${border}px`; | ||
this.settings.pushElement.style.filter = `contrast(${contrast})`; | ||
}; | ||
if (newPaneY <= topHeight) { | ||
setStyles(1, 0, 0, 1); | ||
return; | ||
} | ||
const getXbyY = (min, max) => { | ||
let val = (minHeight * max - topHeight * min) * -1; | ||
val -= (min - max) * newPaneY; | ||
val /= (topHeight - minHeight); | ||
if (val > max) | ||
val = max; | ||
if (val < min) | ||
val = min; | ||
return val; | ||
}; | ||
setStyles(getXbyY(0.93, 1), getXbyY(-6, 0) * -1, getXbyY(-10, 0) * -1, getXbyY(0.85, 1)); | ||
} | ||
/*********************************** | ||
@@ -934,2 +1071,6 @@ * Transitions handler | ||
} | ||
// Push transition | ||
if (this.settings.pushElement) { | ||
this.pushTransition(this.getPanelTransformY(), 'all 0ms linear 0ms'); | ||
} | ||
return; | ||
@@ -990,8 +1131,16 @@ } | ||
return; | ||
// Get timing function && push for next | ||
// TODO: getBreakByHeight or by translateY() | ||
const nextBreak = Object.entries(this.settings.breaks).find(val => val[1].height === (this.screen_height - params.translateY)); | ||
const timingForNext = this.getTimingFunction(nextBreak && nextBreak[1].bounce ? true : false); | ||
// style | ||
this.paneEl.style.transition = `transform ${this.settings.animationDuration}ms ${this.settings.animationType} 0s`; | ||
this.paneEl.style.transition = `transform ${this.settings.animationDuration}ms ${timingForNext} 0s`; | ||
// Bind for follower same transitions | ||
if (this.followerEl) { | ||
this.followerEl.style.transition = `transform ${this.settings.animationDuration}ms ${this.settings.animationType} 0s`; | ||
this.followerEl.style.transition = `transform ${this.settings.animationDuration}ms ${timingForNext} 0s`; | ||
} | ||
// Push transition | ||
if (this.settings.pushElement) { | ||
this.pushTransition(params.translateY, `all ${this.settings.animationDuration}ms ${this.settings.animationType} 0s`); | ||
} | ||
// Main transitions | ||
@@ -1002,4 +1151,4 @@ if (params.type === 'present') { | ||
// Emit event | ||
this.settings.onTransitionStart({ translateY: { new: this.breaks[this.settings.initialBreak] } }); | ||
this.paneEl.style.transform = `translateY(${this.breaks[this.settings.initialBreak]}px) translateZ(0px)`; | ||
this.settings.onTransitionStart({ translateY: { new: params.translateY } }); | ||
this.paneEl.style.transform = `translateY(${params.translateY}px) translateZ(0px)`; | ||
// Bind for follower same transitions | ||
@@ -1006,0 +1155,0 @@ if (this.followerEl) { |
/** | ||
* Cupertino Pane 1.1.7 | ||
* Cupertino Pane 1.1.8 | ||
* Multiplatform slide-over pane | ||
@@ -10,3 +10,3 @@ * https://github.com/roman-rr/cupertino-pane/ | ||
* | ||
* Released on: July 22, 2020 | ||
* Released on: August 28, 2020 | ||
*/ | ||
@@ -162,2 +162,4 @@ | ||
followerElement: null, | ||
pushElement: null, | ||
pushMinHeight: null, | ||
backdrop: false, | ||
@@ -176,7 +178,11 @@ backdropOpacity: 0.4, | ||
lowerThanBottom: true, | ||
upperThanTop: false, | ||
showDraggable: true, | ||
draggableOver: false, | ||
clickBottomOpen: true, | ||
preventClicks: true, | ||
simulateTouch: true, | ||
passiveListeners: true, | ||
touchMoveStopPropagation: false, | ||
touchAngle: null, | ||
breaks: {}, | ||
@@ -203,5 +209,6 @@ onDidDismiss: () => { }, | ||
this.contentScrollTop = 0; | ||
this.draggableScrollOffset = 0; | ||
this.disableDragEvents = false; | ||
this.disableDragAngle = false; | ||
this.rendered = false; | ||
this.allowClick = true; | ||
this.breaks = {}; | ||
@@ -219,2 +226,7 @@ this.brs = []; | ||
*/ | ||
this.touchMoveBackdropCb = (t) => this.touchMoveBackdrop(t); | ||
/** | ||
* Touch Move Event | ||
* @param t | ||
*/ | ||
this.touchMoveCb = (t) => this.touchMove(t); | ||
@@ -226,2 +238,7 @@ /** | ||
this.touchEndCb = (t) => this.touchEnd(t); | ||
/** | ||
* Click Event | ||
* @param t | ||
*/ | ||
this.onClickCb = (t) => this.onClick(t); | ||
this.swipeNextPoint = (diff, maxDiff, closest) => { | ||
@@ -382,2 +399,3 @@ if (this.currentBreakpoint === this.breaks['top']) { | ||
this.closeEl.style.right = '20px'; | ||
this.closeEl.style.zIndex = '14'; | ||
this.closeEl.style.borderRadius = '100%'; | ||
@@ -415,4 +433,4 @@ } | ||
&& this.settings.breaks[val].enabled | ||
&& (this.settings.breaks[val].offset || this.settings.breaks[val].height)) { | ||
this.breaks[val] -= (this.settings.breaks[val].offset || this.settings.breaks[val].height); | ||
&& this.settings.breaks[val].height) { | ||
this.breaks[val] -= this.settings.breaks[val].height; | ||
} | ||
@@ -461,4 +479,7 @@ }); | ||
this.followerEl.style.transform = `translateY(0px) translateZ(0px)`; | ||
this.followerEl.style.transition = `all ${this.settings.animationDuration}ms ${this.settings.animationType} 0s`; | ||
this.followerEl.style.transition = `all ${this.settings.animationDuration}ms ${this.getTimingFunction(this.settings.breaks[this.currentBreak()].bounce)} 0s`; | ||
} | ||
if (this.settings.pushElement) { | ||
this.settings.pushElement = document.querySelector(this.settings.pushElement); | ||
} | ||
if (!this.settings.showDraggable) { | ||
@@ -535,2 +556,19 @@ this.draggableEl.style.opacity = '0'; | ||
/****** Attach Events *******/ | ||
this.attachAllEvents(); | ||
/****** Animation & Transition ******/ | ||
if (conf.animate) { | ||
this.doTransition({ type: 'present', translateY: this.breaks[this.settings.initialBreak] }); | ||
} | ||
else { | ||
// Emit event | ||
if (this.settings.pushElement) { | ||
this.pushTransition(this.breaks[this.settings.initialBreak], 'unset'); | ||
} | ||
this.settings.onDidPresent(); | ||
} | ||
} | ||
/** | ||
* Private Utils methods | ||
*/ | ||
attachAllEvents() { | ||
if (!this.settings.dragBy) { | ||
@@ -546,14 +584,19 @@ this.attachEvents(this.paneEl); | ||
} | ||
/****** Animation & Transition ******/ | ||
if (conf.animate) { | ||
this.doTransition({ type: 'present', translateY: this.breaks[this.settings.initialBreak] }); | ||
} | ||
detachAllEvents() { | ||
if (!this.settings.dragBy) { | ||
this.detachEvents(this.paneEl); | ||
} | ||
else { | ||
// Emit event | ||
this.settings.onDidPresent(); | ||
this.settings.dragBy.forEach((selector) => { | ||
const el = document.querySelector(selector); | ||
if (el) | ||
this.detachEvents(el); | ||
}); | ||
} | ||
} | ||
/** | ||
* Private Utils methods | ||
*/ | ||
resetEvents() { | ||
this.detachAllEvents(); | ||
this.attachAllEvents(); | ||
} | ||
scrollElementInit() { | ||
@@ -579,2 +622,5 @@ let attrElements = this.el.querySelectorAll('[overflow-y]'); | ||
} | ||
getTimingFunction(bounce) { | ||
return bounce ? 'cubic-bezier(0.175, 0.885, 0.370, 1.120)' : this.settings.animationType; | ||
} | ||
checkOpacityAttr(val) { | ||
@@ -612,14 +658,25 @@ let attrElements = this.el.querySelectorAll('[hide-on-bottom]'); | ||
return; | ||
// Allow clicks by default, disallow on move | ||
this.allowClick = true; | ||
// Allow touch angle by default, disallow no move with condition | ||
this.disableDragAngle = false; | ||
const targetTouch = t.type === 'touchstart' && t.targetTouches && (t.targetTouches[0] || t.changedTouches[0]); | ||
const screenY = t.type === 'touchstart' ? targetTouch.screenY : t.screenY; | ||
const screenX = t.type === 'touchstart' ? targetTouch.screenX : t.screenX; | ||
if (t.type === 'mousedown') | ||
this.pointerDown = true; | ||
this.startP = screenY; | ||
this.startY = screenY; | ||
this.startX = screenX; | ||
// if overflow content was scrolled | ||
// increase to scrolled value | ||
if (this.isDragScrollabe(t.path || t.composedPath())) { | ||
this.startP += this.contentScrollTop; | ||
this.startY += this.contentScrollTop; | ||
} | ||
this.steps.push(this.startP); | ||
this.steps.push(this.startY); | ||
} | ||
touchMoveBackdrop(t) { | ||
if (this.settings.touchMoveStopPropagation) { | ||
t.stopPropagation(); | ||
} | ||
} | ||
touchMove(t) { | ||
@@ -630,5 +687,11 @@ // Event emitter | ||
return; | ||
if (this.disableDragAngle) | ||
return; | ||
if (this.settings.touchMoveStopPropagation) { | ||
t.stopPropagation(); | ||
} | ||
// Handle desktop/mobile events | ||
const targetTouch = t.type === 'touchmove' && t.targetTouches && (t.targetTouches[0] || t.changedTouches[0]); | ||
const screenY = t.type === 'touchmove' ? targetTouch.screenY : t.screenY; | ||
const screenX = t.type === 'touchmove' ? targetTouch.screenX : t.screenX; | ||
if (t.type === 'mousemove' && !this.pointerDown) | ||
@@ -638,4 +701,17 @@ return; | ||
let n = screenY; | ||
const diff = n - this.steps[this.steps.length - 1]; | ||
const newVal = this.getPanelTransformY() + diff; | ||
let v = screenX; | ||
const diffY = n - this.steps[this.steps.length - 1]; | ||
let newVal = this.getPanelTransformY() + diffY; | ||
// Touch angle | ||
if (this.settings.touchAngle) { | ||
let touchAngle; | ||
const diffX = v - this.startX; | ||
const diffY = n - this.startY; | ||
touchAngle = (Math.atan2(Math.abs(diffY), Math.abs(diffX)) * 180) / Math.PI; | ||
if (diffX * diffX + diffY * diffY >= 25 | ||
&& (90 - touchAngle > this.settings.touchAngle)) { | ||
this.disableDragAngle = true; | ||
return; | ||
} | ||
} | ||
// Not allow move panel with positive overflow scroll | ||
@@ -653,6 +729,14 @@ if (this.isDragScrollabe(t.path || t.composedPath()) | ||
} | ||
// Not allow drag upper than topper point | ||
// Not allow drag topper than top point | ||
if (newVal <= this.topper && !this.settings.upperThanTop) { | ||
this.paneEl.style.transform = `translateY(${this.topper}px) translateZ(0px)`; | ||
return; | ||
} | ||
// Allow drag topper than top point | ||
if (newVal <= this.topper && this.settings.upperThanTop) { | ||
const differKoef = ((-this.topper + this.topper - this.getPanelTransformY()) / this.topper) / -8; | ||
newVal = this.getPanelTransformY() + (diffY * differKoef); | ||
} | ||
// Not allow drag lower than bottom if free mode | ||
if ((newVal <= this.topper) | ||
|| (this.settings.freeMode && !this.settings.bottomClose && (newVal >= this.bottomer))) { | ||
if (this.settings.freeMode && !this.settings.bottomClose && (newVal >= this.bottomer)) { | ||
return; | ||
@@ -666,2 +750,4 @@ } | ||
} | ||
// Disallow accidentaly clicks while slide gestures | ||
this.allowClick = false; | ||
this.checkOpacityAttr(newVal); | ||
@@ -711,2 +797,12 @@ this.checkOverflowAttr(newVal); | ||
} | ||
onClick(t) { | ||
// Prevent accidental unwanted clicks events during swiping | ||
if (!this.allowClick) { | ||
if (this.settings.preventClicks) { | ||
t.preventDefault(); | ||
t.stopPropagation(); | ||
t.stopImmediatePropagation(); | ||
} | ||
} | ||
} | ||
isBackdropPresented() { | ||
@@ -733,2 +829,4 @@ return document.querySelector(`.cupertino-pane-wrapper .backdrop`) | ||
this.backdropEl.addEventListener('click', (t) => this.settings.onBackdropTap()); | ||
// Reset events to attach backdrop stop propagation | ||
this.resetEvents(); | ||
} | ||
@@ -768,2 +866,3 @@ /** | ||
attachEvents(el) { | ||
var _a, _b, _c; | ||
// Touch Events | ||
@@ -774,2 +873,4 @@ if (!Support.touch && Support.pointerEvents) { | ||
el.addEventListener(this.touchEvents.end, this.touchEndCb, false); | ||
// Backdrop propagation fix | ||
(_a = this.backdropEl) === null || _a === void 0 ? void 0 : _a.addEventListener(this.touchEvents.move, this.touchMoveBackdropCb, false); | ||
} | ||
@@ -782,2 +883,4 @@ else { | ||
el.addEventListener(this.touchEvents.end, this.touchEndCb, passiveListener); | ||
// Backdrop propagation fix | ||
(_b = this.backdropEl) === null || _b === void 0 ? void 0 : _b.addEventListener(this.touchEvents.move, this.touchMoveBackdropCb, Support.passiveListener ? { passive: false, capture: false } : false); | ||
if (this.touchEvents['cancel']) { | ||
@@ -791,6 +894,13 @@ el.addEventListener(this.touchEvents['cancel'], this.touchEndCb, passiveListener); | ||
el.addEventListener('mouseup', this.touchEndCb, false); | ||
// Backdrop propagation fix | ||
(_c = this.backdropEl) === null || _c === void 0 ? void 0 : _c.addEventListener('mousemove', this.touchMoveBackdropCb, false); | ||
} | ||
} | ||
// Prevent accidental unwanted clicks events during swiping | ||
if (this.settings.preventClicks) { | ||
el.addEventListener('click', this.onClickCb, true); | ||
} | ||
} | ||
detachEvents(el) { | ||
var _a, _b, _c; | ||
// Touch Events | ||
@@ -801,2 +911,4 @@ if (!Support.touch && Support.pointerEvents) { | ||
el.removeEventListener(this.touchEvents.end, this.touchEndCb, false); | ||
// Backdrop propagation fix | ||
(_a = this.backdropEl) === null || _a === void 0 ? void 0 : _a.removeEventListener(this.touchEvents.move, this.touchMoveBackdropCb, false); | ||
} | ||
@@ -809,2 +921,4 @@ else { | ||
el.removeEventListener(this.touchEvents.end, this.touchEndCb, passiveListener); | ||
// Backdrop propagation fix | ||
(_b = this.backdropEl) === null || _b === void 0 ? void 0 : _b.removeEventListener(this.touchEvents.move, this.touchMoveBackdropCb, false); | ||
if (this.touchEvents['cancel']) { | ||
@@ -818,4 +932,10 @@ el.removeEventListener(this.touchEvents['cancel'], this.touchEndCb, passiveListener); | ||
el.removeEventListener('mouseup', this.touchEndCb, false); | ||
// Backdrop propagation fix | ||
(_c = this.backdropEl) === null || _c === void 0 ? void 0 : _c.removeEventListener('mousemove', this.touchMoveBackdropCb, false); | ||
} | ||
} | ||
// Prevent accidental unwanted clicks events during swiping | ||
if (this.settings.preventClicks) { | ||
el.removeEventListener('click', this.onClickCb, true); | ||
} | ||
} | ||
@@ -891,12 +1011,3 @@ getPanelTransformY() { | ||
/****** Detach Events *******/ | ||
if (!this.settings.dragBy) { | ||
this.detachEvents(this.paneEl); | ||
} | ||
else { | ||
this.settings.dragBy.forEach((selector) => { | ||
const el = document.querySelector(selector); | ||
if (el) | ||
this.detachEvents(el); | ||
}); | ||
} | ||
this.detachAllEvents(); | ||
// Reset vars | ||
@@ -924,2 +1035,28 @@ this.currentBreakpoint = this.breaks[this.settings.initialBreak]; | ||
} | ||
pushTransition(newPaneY, transition) { | ||
newPaneY = this.screen_height - newPaneY; | ||
const topHeight = this.settings.pushMinHeight ? this.settings.pushMinHeight : this.screen_height - this.bottomer; | ||
const minHeight = this.screen_height - this.topper; | ||
this.settings.pushElement.style.transition = transition; | ||
const setStyles = (scale, y, border, contrast) => { | ||
this.settings.pushElement.style.transform = `translateY(${y}px) scale(${scale})`; | ||
this.settings.pushElement.style.borderRadius = `${border}px`; | ||
this.settings.pushElement.style.filter = `contrast(${contrast})`; | ||
}; | ||
if (newPaneY <= topHeight) { | ||
setStyles(1, 0, 0, 1); | ||
return; | ||
} | ||
const getXbyY = (min, max) => { | ||
let val = (minHeight * max - topHeight * min) * -1; | ||
val -= (min - max) * newPaneY; | ||
val /= (topHeight - minHeight); | ||
if (val > max) | ||
val = max; | ||
if (val < min) | ||
val = min; | ||
return val; | ||
}; | ||
setStyles(getXbyY(0.93, 1), getXbyY(-6, 0) * -1, getXbyY(-10, 0) * -1, getXbyY(0.85, 1)); | ||
} | ||
/*********************************** | ||
@@ -938,2 +1075,6 @@ * Transitions handler | ||
} | ||
// Push transition | ||
if (this.settings.pushElement) { | ||
this.pushTransition(this.getPanelTransformY(), 'all 0ms linear 0ms'); | ||
} | ||
return; | ||
@@ -994,8 +1135,16 @@ } | ||
return; | ||
// Get timing function && push for next | ||
// TODO: getBreakByHeight or by translateY() | ||
const nextBreak = Object.entries(this.settings.breaks).find(val => val[1].height === (this.screen_height - params.translateY)); | ||
const timingForNext = this.getTimingFunction(nextBreak && nextBreak[1].bounce ? true : false); | ||
// style | ||
this.paneEl.style.transition = `transform ${this.settings.animationDuration}ms ${this.settings.animationType} 0s`; | ||
this.paneEl.style.transition = `transform ${this.settings.animationDuration}ms ${timingForNext} 0s`; | ||
// Bind for follower same transitions | ||
if (this.followerEl) { | ||
this.followerEl.style.transition = `transform ${this.settings.animationDuration}ms ${this.settings.animationType} 0s`; | ||
this.followerEl.style.transition = `transform ${this.settings.animationDuration}ms ${timingForNext} 0s`; | ||
} | ||
// Push transition | ||
if (this.settings.pushElement) { | ||
this.pushTransition(params.translateY, `all ${this.settings.animationDuration}ms ${this.settings.animationType} 0s`); | ||
} | ||
// Main transitions | ||
@@ -1006,4 +1155,4 @@ if (params.type === 'present') { | ||
// Emit event | ||
this.settings.onTransitionStart({ translateY: { new: this.breaks[this.settings.initialBreak] } }); | ||
this.paneEl.style.transform = `translateY(${this.breaks[this.settings.initialBreak]}px) translateZ(0px)`; | ||
this.settings.onTransitionStart({ translateY: { new: params.translateY } }); | ||
this.paneEl.style.transform = `translateY(${params.translateY}px) translateZ(0px)`; | ||
// Bind for follower same transitions | ||
@@ -1010,0 +1159,0 @@ if (this.followerEl) { |
/** | ||
* Cupertino Pane 1.1.7 | ||
* Cupertino Pane 1.1.8 | ||
* Multiplatform slide-over pane | ||
@@ -10,6 +10,6 @@ * https://github.com/roman-rr/cupertino-pane/ | ||
* | ||
* Released on: July 22, 2020 | ||
* Released on: August 28, 2020 | ||
*/ | ||
"use strict";Object.defineProperty(exports,"__esModule",{value:!0});class Support{static get touch(){return window.Modernizr&&!0===window.Modernizr.touch||!!(window.navigator.maxTouchPoints>0||"ontouchstart"in window||window.DocumentTouch&&document instanceof window.DocumentTouch)}static get observer(){return"MutationObserver"in window||"WebkitMutationObserver"in window}static get backdropFilter(){return CSS.supports("backdrop-filter","blur(0px)")||CSS.supports("-webkit-backdrop-filter","blur(0px)")}static get passiveListener(){let t=!1;try{const e=Object.defineProperty({},"passive",{get(){t=!0}});window.addEventListener("testPassiveListener",null,e)}catch(t){}return t}static get gestures(){return"ongesturestart"in window}static get pointerEvents(){return!!window.PointerEvent&&"maxTouchPoints"in window.navigator&&window.navigator.maxTouchPoints>0}}class Device{constructor(){this.ios=!1,this.android=!1,this.androidChrome=!1,this.desktop=!1,this.iphone=!1,this.ipod=!1,this.ipad=!1,this.edge=!1,this.ie=!1,this.firefox=!1,this.macos=!1,this.windows=!1,this.cordova=!(!window.cordova&&!window.phonegap),this.phonegap=!(!window.cordova&&!window.phonegap),this.electron=!1,this.ionic=!!document.querySelector("ion-app");const t=window.navigator.platform,e=window.navigator.userAgent,s=window.screen.width,i=window.screen.height;let n=e.match(/(Android);?[\s\/]+([\d.]+)?/),o=e.match(/(iPad).*OS\s([\d_]+)/),r=e.match(/(iPod)(.*OS\s([\d_]+))?/),a=!this.ipad&&e.match(/(iPhone\sOS|iOS)\s([\d_]+)/),h=e.indexOf("MSIE ")>=0||e.indexOf("Trident/")>=0,l=e.indexOf("Edge/")>=0,d=e.indexOf("Gecko/")>=0&&e.indexOf("Firefox/")>=0,p="Win32"===t,c=e.toLowerCase().indexOf("electron")>=0,u="MacIntel"===t;!o&&u&&Support.touch&&(1024===s&&1366===i||834===s&&1194===i||834===s&&1112===i||768===s&&1024===i)&&(o=e.match(/(Version)\/([\d.]+)/),u=!1),this.ie=h,this.edge=l,this.firefox=d,n&&!p&&(this.os="android",this.osVersion=n[2],this.android=!0,this.androidChrome=e.toLowerCase().indexOf("chrome")>=0),(o||a||r)&&(this.os="ios",this.ios=!0),a&&!r&&(this.osVersion=a[2].replace(/_/g,"."),this.iphone=!0),o&&(this.osVersion=o[2].replace(/_/g,"."),this.ipad=!0),r&&(this.osVersion=r[3]?r[3].replace(/_/g,"."):null,this.ipod=!0),this.ios&&this.osVersion&&e.indexOf("Version/")>=0&&"10"===this.osVersion.split(".")[0]&&(this.osVersion=e.toLowerCase().split("version/")[1].split(" ")[0]),this.webView=!(!(a||o||r)||!e.match(/.*AppleWebKit(?!.*Safari)/i)&&!window.navigator.standalone)||window.matchMedia&&window.matchMedia("(display-mode: standalone)").matches,this.webview=this.webView,this.standalone=this.webView,this.desktop=!(this.ios||this.android)||c,this.desktop&&(this.electron=c,this.macos=u,this.windows=p,this.macos&&(this.os="macos"),this.windows&&(this.os="windows")),this.pixelRatio=window.devicePixelRatio||1}}class CupertinoPane{constructor(t,e={}){this.selector=t,this.settings={initialBreak:"middle",parentElement:null,followerElement:null,backdrop:!1,backdropOpacity:.4,animationType:"ease",animationDuration:300,dragBy:null,bottomOffset:0,darkMode:!1,bottomClose:!1,freeMode:!1,buttonClose:!0,topperOverflow:!0,topperOverflowOffset:0,lowerThanBottom:!0,showDraggable:!0,draggableOver:!1,clickBottomOpen:!0,simulateTouch:!0,passiveListeners:!0,breaks:{},onDidDismiss:()=>{},onWillDismiss:()=>{},onDidPresent:()=>{},onWillPresent:()=>{},onDragStart:()=>{},onDrag:()=>{},onDragEnd:()=>{},onBackdropTap:()=>{},onTransitionStart:()=>{},onTransitionEnd:()=>{}},this.defaultBreaksConf={top:{enabled:!0,height:window.innerHeight-47.25},middle:{enabled:!0,height:300},bottom:{enabled:!0,height:100}},this.screen_height=window.innerHeight,this.steps=[],this.pointerDown=!1,this.contentScrollTop=0,this.draggableScrollOffset=0,this.disableDragEvents=!1,this.rendered=!1,this.breaks={},this.brs=[],this.device=new Device,this.touchStartCb=t=>this.touchStart(t),this.touchMoveCb=t=>this.touchMove(t),this.touchEndCb=t=>this.touchEnd(t),this.swipeNextPoint=(t,e,s)=>{if(this.currentBreakpoint===this.breaks.top){if(t>e){if(this.settings.breaks.middle.enabled)return this.breaks.middle;if(this.settings.breaks.bottom.enabled)return this.breaks.middle<s?s:this.breaks.bottom}return this.breaks.top}if(this.currentBreakpoint===this.breaks.middle)return t<-e&&this.settings.breaks.top.enabled?this.breaks.top:t>e&&this.settings.breaks.bottom.enabled?this.breaks.bottom:this.breaks.middle;if(this.currentBreakpoint===this.breaks.bottom){if(t<-e){if(this.settings.breaks.middle.enabled)return this.breaks.middle>s?s:this.breaks.middle;if(this.settings.breaks.top.enabled)return this.breaks.top}return this.breaks.bottom}return s},this.touchEvents=(()=>{const t=["touchstart","touchmove","touchend","touchcancel"];let e=["mousedown","mousemove","mouseup"];Support.pointerEvents&&(e=["pointerdown","pointermove","pointerup"]);const s={start:t[0],move:t[1],end:t[2],cancel:t[3]},i={start:e[0],move:e[1],end:e[2]};return Support.touch||!this.settings.simulateTouch?s:i})(),t instanceof HTMLElement?this.selector=t:this.selector=document.querySelector(t),this.selector?this.isPanePresented()?console.warn("Cupertino Pane: specified selector or DOM element already in use",this.selector):(this.el=this.selector,this.el.style.display="none",this.settings=Object.assign(Object.assign({},this.settings),e),this.settings.parentElement?this.settings.parentElement=document.querySelector(this.settings.parentElement):this.settings.parentElement=this.el.parentElement):console.warn("Cupertino Pane: wrong selector or DOM element specified",this.selector)}drawElements(){this.parentEl=this.settings.parentElement,this.wrapperEl=document.createElement("div"),this.wrapperEl.className="cupertino-pane-wrapper "+this.el.className,this.wrapperEl.style.position="absolute",this.wrapperEl.style.top="0",this.wrapperEl.style.left="0",this.paneEl=document.createElement("div"),this.paneEl.className="pane",this.paneEl.style.position="fixed",this.paneEl.style.zIndex="11",this.paneEl.style.paddingTop="15px",this.paneEl.style.width="100%",this.paneEl.style.maxWidth="500px",this.paneEl.style.left="0px",this.paneEl.style.right="0px",this.paneEl.style.marginLeft="auto",this.paneEl.style.marginRight="auto",this.paneEl.style.height=this.screen_height-this.topper-this.settings.bottomOffset+"px",this.paneEl.style.background="#ffffff",this.paneEl.style.borderTopLeftRadius="20px",this.paneEl.style.borderTopRightRadius="20px",this.paneEl.style.boxShadow="0 4px 16px rgba(0,0,0,.12)",this.paneEl.style.overflow="hidden",this.paneEl.style.willChange="transform",this.paneEl.style.transform=`translateY(${this.breaks[this.settings.initialBreak]}px) translateZ(0px)`,this.draggableEl=document.createElement("div"),this.draggableEl.className="draggable",this.draggableEl.style.padding="5px",this.draggableEl.style.position="absolute",this.draggableEl.style.top="0",this.draggableEl.style.left="0",this.draggableEl.style.right="0",this.draggableEl.style.marginLeft="auto",this.draggableEl.style.marginRight="auto",this.draggableEl.style.height="30px",this.draggableEl.style.zIndex="12",this.moveEl=document.createElement("div"),this.moveEl.className="move",this.moveEl.style.margin="0 auto",this.moveEl.style.height="5px",this.moveEl.style.background="#c0c0c0",this.moveEl.style.width="36px",this.moveEl.style.borderRadius="4px",this.contentEl=this.el,this.contentEl.style.display="block",this.contentEl.style.transition=`opacity ${this.settings.animationDuration}ms ${this.settings.animationType} 0s`,this.contentEl.style.overflowX="hidden",this.closeEl=document.createElement("div"),this.closeEl.className="close-button",this.closeEl.style.width="26px",this.closeEl.style.height="26px",this.closeEl.style.position="absolute",this.closeEl.style.background="#ebebeb",this.closeEl.style.top="16px",this.closeEl.style.right="20px",this.closeEl.style.borderRadius="100%"}present(t={animate:!1}){if(this.el)if(this.isPanePresented()&&this.rendered)this.moveToBreak(this.settings.initialBreak);else if(!this.isPanePresented()||this.rendered){if(this.settings.onWillPresent(),this.breaks={top:this.screen_height,middle:this.screen_height,bottom:this.screen_height},["top","middle","bottom"].forEach(t=>{this.breaks[t]-=this.settings.bottomOffset,this.settings.breaks[t]||(this.settings.breaks[t]=this.defaultBreaksConf[t]),this.settings.breaks[t]&&this.settings.breaks[t].enabled&&(this.settings.breaks[t].offset||this.settings.breaks[t].height)&&(this.breaks[t]-=this.settings.breaks[t].offset||this.settings.breaks[t].height)}),this.settings.breaks[this.settings.initialBreak].enabled||console.warn("Cupertino Pane: Please set initialBreak for enabled breakpoint"),this.settings.breaks.middle.height>=this.settings.breaks.top.height&&console.warn("Cupertino Pane: Please set middle height lower than top height"),this.settings.breaks.middle.height<=this.settings.breaks.bottom.height&&console.warn("Cupertino Pane: Please set bottom height lower than middle height"),this.brs=[],["top","middle","bottom"].forEach(t=>{this.settings.breaks[t].enabled&&this.brs.push(this.breaks[t])}),this.topper=this.brs.reduce((t,e)=>Math.abs(e)<Math.abs(t)?e:t),this.bottomer=this.brs.reduce((t,e)=>Math.abs(e)>Math.abs(t)?e:t),this.currentBreakpoint=this.breaks[this.settings.initialBreak],this.drawElements(),this.parentEl.appendChild(this.wrapperEl),this.wrapperEl.appendChild(this.paneEl),this.paneEl.appendChild(this.draggableEl),this.paneEl.appendChild(this.contentEl),this.draggableEl.appendChild(this.moveEl),this.rendered=!0,this.settings.followerElement){if(!document.querySelector(this.settings.followerElement))return void console.warn("Cupertino Pane: wrong follower element selector specified",this.settings.followerElement);this.followerEl=document.querySelector(this.settings.followerElement),this.followerEl.style.willChange="transform, border-radius",this.followerEl.style.transform="translateY(0px) translateZ(0px)",this.followerEl.style.transition=`all ${this.settings.animationDuration}ms ${this.settings.animationType} 0s`}if(this.settings.showDraggable||(this.draggableEl.style.opacity="0"),this.settings.draggableOver&&(this.paneEl.style.background="transparent",this.paneEl.style.boxShadow="none",this.paneEl.style.paddingTop="30px",this.contentEl.style.background="#ffffff",this.contentEl.style.display="block",this.contentEl.style.borderTopLeftRadius="20px",this.contentEl.style.borderTopRightRadius="20px",this.contentEl.style.boxShadow="0 4px 16px rgba(0,0,0,.12)",this.closeEl.style.top="45px",this.draggableEl.style.padding="15px",this.moveEl.style.width="45px",this.moveEl.style.background="rgba(225, 225, 225, 0.6)",Support.backdropFilter&&(this.moveEl.style.backdropFilter="saturate(180%) blur(20px)",this.moveEl.style.webkitBackdropFilter="saturate(180%) blur(20px)")),this.settings.darkMode&&(this.paneEl.style.background="#1c1c1d",this.paneEl.style.color="#ffffff",this.moveEl.style.background="#5a5a5e"),this.settings.buttonClose){this.paneEl.appendChild(this.closeEl),this.closeEl.addEventListener("click",t=>this.destroy({animate:!0}));let t="#7a7a7e";this.settings.darkMode&&(this.closeEl.style.background="#424246",t="#a8a7ae"),this.closeEl.innerHTML=`<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512">\n <path fill="${t}" d="M278.6 256l68.2-68.2c6.2-6.2 6.2-16.4 0-22.6-6.2-6.2-16.4-6.2-22.6 0L256 233.4l-68.2-68.2c-6.2-6.2-16.4-6.2-22.6 0-3.1 3.1-4.7 7.2-4.7 11.3 0 4.1 1.6 8.2 4.7 11.3l68.2 68.2-68.2 68.2c-3.1 3.1-4.7 7.2-4.7 11.3 0 4.1 1.6 8.2 4.7 11.3 6.2 6.2 16.4 6.2 22.6 0l68.2-68.2 68.2 68.2c6.2 6.2 16.4 6.2 22.6 0 6.2-6.2 6.2-16.4 0-22.6L278.6 256z"/>\n </svg>`}this.settings.bottomClose&&(this.settings.breaks.bottom.enabled=!0),this.settings.backdrop&&this.renderBackdrop(),this.scrollElementInit(),this.checkOpacityAttr(this.currentBreakpoint),this.checkOverflowAttr(this.currentBreakpoint),this.device.android&&(document.body.style.overscrollBehaviorY="none",this.device.ionic&&this.device.cordova&&window.addEventListener("keyboardWillHide",()=>{this.paneEl&&window.requestAnimationFrame(()=>{this.wrapperEl.style.width="100%",this.paneEl.style.position="absolute",window.requestAnimationFrame(()=>{this.wrapperEl.style.width="unset",this.paneEl.style.position="fixed"})})})),this.settings.dragBy?this.settings.dragBy.forEach(t=>{const e=document.querySelector(t);e&&this.attachEvents(e)}):this.attachEvents(this.paneEl),t.animate?this.doTransition({type:"present",translateY:this.breaks[this.settings.initialBreak]}):this.settings.onDidPresent()}else console.warn("Cupertino Pane: specified selector or DOM element already in use",this.selector)}scrollElementInit(){let t=this.el.querySelectorAll("[overflow-y]");!t.length||t.length>1?this.overflowEl=this.contentEl:this.overflowEl=t[0],this.settings.topperOverflow&&setTimeout(()=>{this.overflowEl.style.height=this.screen_height-this.topper-this.settings.bottomOffset-this.settings.topperOverflowOffset-this.overflowEl.offsetTop+"px"},150)}checkOpacityAttr(t){let e=this.el.querySelectorAll("[hide-on-bottom]");e.length&&e.forEach(e=>{e.style.transition=`opacity ${this.settings.animationDuration}ms ${this.settings.animationType} 0s`,e.style.opacity=t>=this.breaks.bottom?"0":"1"})}checkOverflowAttr(t){this.settings.topperOverflow&&(this.overflowEl.style.overflowY=t<=this.topper?"auto":"hidden")}isPanePresented(){let t=Array.from(document.querySelectorAll(".cupertino-pane-wrapper"));return!!t.length&&!!t.find(t=>t.contains(this.selector))}isDragScrollabe(t){return!!t.find(t=>t===this.overflowEl)}touchStart(t){if(this.settings.onDragStart(t),this.disableDragEvents)return;const e="touchstart"===t.type&&t.targetTouches&&(t.targetTouches[0]||t.changedTouches[0]),s="touchstart"===t.type?e.screenY:t.screenY;"mousedown"===t.type&&(this.pointerDown=!0),this.startP=s,this.isDragScrollabe(t.path||t.composedPath())&&(this.startP+=this.contentScrollTop),this.steps.push(this.startP)}touchMove(t){if(this.settings.onDrag(t),this.disableDragEvents)return;const e="touchmove"===t.type&&t.targetTouches&&(t.targetTouches[0]||t.changedTouches[0]),s="touchmove"===t.type?e.screenY:t.screenY;if("mousemove"===t.type&&!this.pointerDown)return;let i=s;const n=i-this.steps[this.steps.length-1],o=this.getPanelTransformY()+n;this.isDragScrollabe(t.path||t.composedPath())&&"auto"===this.overflowEl.style.overflowY&&(this.overflowEl.addEventListener("scroll",t=>{this.contentScrollTop=t.target.scrollTop}),o>this.topper&&this.contentScrollTop>0||o<=this.topper)||o<=this.topper||this.settings.freeMode&&!this.settings.bottomClose&&o>=this.bottomer||(!this.settings.lowerThanBottom&&o>=this.bottomer?this.destroy({animate:!0}):(this.checkOpacityAttr(o),this.checkOverflowAttr(o),this.doTransition({type:"move",translateY:o}),this.steps.push(i)))}touchEnd(t){if(this.settings.onDragEnd(t),this.disableDragEvents)return;const e="touchmove"===t.type&&t.targetTouches&&(t.targetTouches[0]||t.changedTouches[0]);"touchmove"===t.type?e.screenY:t.screenY;"mouseup"===t.type&&(this.pointerDown=!1);let s=this.brs.reduce((t,e)=>Math.abs(e-this.getPanelTransformY())<Math.abs(t-this.getPanelTransformY())?e:t);const i=this.steps[this.steps.length-1]-this.steps[this.steps.length-2],n=window.hasOwnProperty("cordova")?4:3;Math.abs(i)>=n&&(s=this.swipeNextPoint(i,n,s)),this.settings.clickBottomOpen&&this.currentBreakpoint===this.breaks.bottom&&isNaN(i)&&(s=this.settings.breaks.middle.enabled?this.breaks.middle:this.settings.breaks.top.enabled?this.breaks.top:this.breaks.bottom),this.steps=[],this.currentBreakpoint=s,this.checkOpacityAttr(this.currentBreakpoint),this.checkOverflowAttr(this.currentBreakpoint),this.settings.bottomClose&&s===this.breaks.bottom?this.destroy({animate:!0}):this.doTransition({type:"end",translateY:s})}isBackdropPresented(){return!!document.querySelector(".cupertino-pane-wrapper .backdrop")}renderBackdrop(){this.backdropEl=document.createElement("div"),this.backdropEl.className="backdrop",this.backdropEl.style.overflow="hidden",this.backdropEl.style.position="fixed",this.backdropEl.style.width="100%",this.backdropEl.style.bottom="0",this.backdropEl.style.right="0",this.backdropEl.style.left="0",this.backdropEl.style.top="0",this.backdropEl.style.transition=`all ${this.settings.animationDuration}ms ${this.settings.animationType} 0s`,this.backdropEl.style.backgroundColor=`rgba(0,0,0, ${this.settings.backdropOpacity})`,this.backdropEl.style.display="none",this.backdropEl.style.zIndex="10",this.wrapperEl.appendChild(this.backdropEl),this.backdropEl.style.display="block",this.backdropEl.addEventListener("click",t=>this.settings.onBackdropTap())}backdrop(t={show:!0}){if(!this.isPanePresented())return console.warn("Cupertino Pane: Present pane before call backdrop()"),null;this.isBackdropPresented()||this.renderBackdrop();const e=()=>{this.backdropEl.style.transition="initial",this.backdropEl.style.display="none",this.backdropEl.removeEventListener("transitionend",e)};if(this.backdropEl.style.transition=`all ${this.settings.animationDuration}ms ${this.settings.animationType} 0s`,this.backdropEl.style.backgroundColor="rgba(0,0,0,.0)",t.show)this.backdropEl.style.display="block",setTimeout(()=>{this.backdropEl.style.backgroundColor=`rgba(0,0,0, ${this.settings.backdropOpacity})`},50);else{if("none"===this.backdropEl.style.display)return;this.backdropEl.addEventListener("transitionend",e)}}attachEvents(t){if(!Support.touch&&Support.pointerEvents)t.addEventListener(this.touchEvents.start,this.touchStartCb,!1),t.addEventListener(this.touchEvents.move,this.touchMoveCb,!1),t.addEventListener(this.touchEvents.end,this.touchEndCb,!1);else{if(Support.touch){const e=!("touchstart"!==this.touchEvents.start||!Support.passiveListener||!this.settings.passiveListeners)&&{passive:!0,capture:!1};t.addEventListener(this.touchEvents.start,this.touchStartCb,e),t.addEventListener(this.touchEvents.move,this.touchMoveCb,!!Support.passiveListener&&{passive:!1,capture:!1}),t.addEventListener(this.touchEvents.end,this.touchEndCb,e),this.touchEvents.cancel&&t.addEventListener(this.touchEvents.cancel,this.touchEndCb,e)}(this.settings.simulateTouch&&!this.device.ios&&!this.device.android||this.settings.simulateTouch&&!Support.touch&&this.device.ios)&&(t.addEventListener("mousedown",this.touchStartCb,!1),t.addEventListener("mousemove",this.touchMoveCb,!1),t.addEventListener("mouseup",this.touchEndCb,!1))}}detachEvents(t){if(!Support.touch&&Support.pointerEvents)t.removeEventListener(this.touchEvents.start,this.touchStartCb,!1),t.removeEventListener(this.touchEvents.move,this.touchMoveCb,!1),t.removeEventListener(this.touchEvents.end,this.touchEndCb,!1);else{if(Support.touch){const e=!("onTouchStart"!==this.touchEvents.start||!Support.passiveListener||!this.settings.passiveListeners)&&{passive:!0,capture:!1};t.removeEventListener(this.touchEvents.start,this.touchStartCb,e),t.removeEventListener(this.touchEvents.move,this.touchMoveCb,!1),t.removeEventListener(this.touchEvents.end,this.touchEndCb,e),this.touchEvents.cancel&&t.removeEventListener(this.touchEvents.cancel,this.touchEndCb,e)}(this.settings.simulateTouch&&!this.device.ios&&!this.device.android||this.settings.simulateTouch&&!Support.touch&&this.device.ios)&&(t.removeEventListener("mousedown",this.touchStartCb,!1),t.removeEventListener("mousemove",this.touchMoveCb,!1),t.removeEventListener("mouseup",this.touchEndCb,!1))}}getPanelTransformY(){return parseFloat(/\.*translateY\((.*)px\)/i.exec(this.paneEl.style.transform)[1])}disableDrag(){this.disableDragEvents=!0}enableDrag(){this.disableDragEvents=!1}moveToBreak(t){if(!this.isPanePresented())return console.warn("Cupertino Pane: Present pane before call moveToBreak()"),null;this.settings.breaks[t].enabled?(this.checkOpacityAttr(this.breaks[t]),this.checkOverflowAttr(this.breaks[t]),this.doTransition({type:"breakpoint",translateY:this.breaks[t]}),this.currentBreakpoint=this.breaks[t]):console.warn("Cupertino Pane: %s breakpoint disabled",t)}hide(){return this.isPanePresented()?this.isHidden()?(console.warn("Cupertino Pane: Pane already hidden"),null):void this.doTransition({type:"hide",translateY:this.screen_height}):(console.warn("Cupertino Pane: Present pane before call hide()"),null)}isHidden(){return this.isPanePresented()?this.paneEl.style.transform===`translateY(${this.screen_height}px) translateZ(0px)`:(console.warn("Cupertino Pane: Present pane before call isHidden()"),null)}currentBreak(){return this.isPanePresented()?this.breaks.top===this.currentBreakpoint?"top":this.breaks.middle===this.currentBreakpoint?"middle":this.breaks.bottom===this.currentBreakpoint?"bottom":null:(console.warn("Cupertino Pane: Present pane before call currentBreak()"),null)}destroyResets(){this.parentEl.appendChild(this.contentEl),this.wrapperEl.remove(),this.settings.dragBy?this.settings.dragBy.forEach(t=>{const e=document.querySelector(t);e&&this.detachEvents(e)}):this.detachEvents(this.paneEl),this.currentBreakpoint=this.breaks[this.settings.initialBreak],this.contentEl.style.display="none"}destroy(t={animate:!1}){if(!this.isPanePresented())return console.warn("Cupertino Pane: Present pane before call destroy()"),null;this.settings.onWillDismiss(),t.animate?this.doTransition({type:"destroy",translateY:this.screen_height}):(this.destroyResets(),this.settings.onDidDismiss())}doTransition(t={}){if("move"===t.type)return this.paneEl.style.transition="all 0ms linear 0ms",this.paneEl.style.transform=`translateY(${t.translateY}px) translateZ(0px)`,void(this.followerEl&&(this.followerEl.style.transition="all 0ms linear 0ms",this.followerEl.style.transform=`translateY(${t.translateY-this.breaks[this.settings.initialBreak]}px) translateZ(0px)`));const e=()=>{"destroy"===t.type&&this.destroyResets(),this.paneEl.style.transition="initial",this.followerEl&&(this.followerEl.style.transition="initial"),this.settings.backdrop&&("destroy"!==t.type&&"hide"!==t.type||(this.backdropEl.style.transition="initial",this.backdropEl.style.display="none")),"present"===t.type&&this.settings.onDidPresent(),"destroy"===t.type&&this.settings.onDidDismiss(),this.settings.onTransitionEnd(),this.paneEl.removeEventListener("transitionend",e)};if("breakpoint"===t.type||"end"===t.type||"present"===t.type||"hide"===t.type||"destroy"===t.type){if(this.settings.backdrop&&(this.isHidden()||"hide"===t.type||"destroy"===t.type||"present"===t.type)&&(this.backdropEl.style.backgroundColor="rgba(0,0,0,.0)",this.backdropEl.style.transition=`all ${this.settings.animationDuration}ms ${this.settings.animationType} 0s`,"hide"!==t.type&&"destroy"!==t.type&&(this.backdropEl.style.display="block",setTimeout(()=>{this.backdropEl.style.backgroundColor=`rgba(0,0,0, ${this.settings.backdropOpacity})`},50))),"end"===t.type&&this.settings.freeMode)return;return this.paneEl.style.transition=`transform ${this.settings.animationDuration}ms ${this.settings.animationType} 0s`,this.followerEl&&(this.followerEl.style.transition=`transform ${this.settings.animationDuration}ms ${this.settings.animationType} 0s`),"present"===t.type?(this.paneEl.style.transform=`translateY(${this.screen_height}px) translateZ(0px)`,setTimeout(()=>{this.settings.onTransitionStart({translateY:{new:this.breaks[this.settings.initialBreak]}}),this.paneEl.style.transform=`translateY(${this.breaks[this.settings.initialBreak]}px) translateZ(0px)`,this.followerEl&&(this.followerEl.style.transform="translateY(0px) translateZ(0px)")},50)):(this.settings.onTransitionStart({translateY:{new:t.translateY}}),this.paneEl.style.transform=`translateY(${t.translateY}px) translateZ(0px)`,this.followerEl&&(this.followerEl.style.transform=`translateY(${t.translateY-this.breaks[this.settings.initialBreak]}px) translateZ(0px)`)),void this.paneEl.addEventListener("transitionend",e)}}}exports.CupertinoPane=CupertinoPane; | ||
"use strict";Object.defineProperty(exports,"__esModule",{value:!0});class Support{static get touch(){return window.Modernizr&&!0===window.Modernizr.touch||!!(window.navigator.maxTouchPoints>0||"ontouchstart"in window||window.DocumentTouch&&document instanceof window.DocumentTouch)}static get observer(){return"MutationObserver"in window||"WebkitMutationObserver"in window}static get backdropFilter(){return CSS.supports("backdrop-filter","blur(0px)")||CSS.supports("-webkit-backdrop-filter","blur(0px)")}static get passiveListener(){let t=!1;try{const e=Object.defineProperty({},"passive",{get(){t=!0}});window.addEventListener("testPassiveListener",null,e)}catch(t){}return t}static get gestures(){return"ongesturestart"in window}static get pointerEvents(){return!!window.PointerEvent&&"maxTouchPoints"in window.navigator&&window.navigator.maxTouchPoints>0}}class Device{constructor(){this.ios=!1,this.android=!1,this.androidChrome=!1,this.desktop=!1,this.iphone=!1,this.ipod=!1,this.ipad=!1,this.edge=!1,this.ie=!1,this.firefox=!1,this.macos=!1,this.windows=!1,this.cordova=!(!window.cordova&&!window.phonegap),this.phonegap=!(!window.cordova&&!window.phonegap),this.electron=!1,this.ionic=!!document.querySelector("ion-app");const t=window.navigator.platform,e=window.navigator.userAgent,s=window.screen.width,i=window.screen.height;let n=e.match(/(Android);?[\s\/]+([\d.]+)?/),o=e.match(/(iPad).*OS\s([\d_]+)/),r=e.match(/(iPod)(.*OS\s([\d_]+))?/),a=!this.ipad&&e.match(/(iPhone\sOS|iOS)\s([\d_]+)/),h=e.indexOf("MSIE ")>=0||e.indexOf("Trident/")>=0,l=e.indexOf("Edge/")>=0,p=e.indexOf("Gecko/")>=0&&e.indexOf("Firefox/")>=0,d="Win32"===t,c=e.toLowerCase().indexOf("electron")>=0,u="MacIntel"===t;!o&&u&&Support.touch&&(1024===s&&1366===i||834===s&&1194===i||834===s&&1112===i||768===s&&1024===i)&&(o=e.match(/(Version)\/([\d.]+)/),u=!1),this.ie=h,this.edge=l,this.firefox=p,n&&!d&&(this.os="android",this.osVersion=n[2],this.android=!0,this.androidChrome=e.toLowerCase().indexOf("chrome")>=0),(o||a||r)&&(this.os="ios",this.ios=!0),a&&!r&&(this.osVersion=a[2].replace(/_/g,"."),this.iphone=!0),o&&(this.osVersion=o[2].replace(/_/g,"."),this.ipad=!0),r&&(this.osVersion=r[3]?r[3].replace(/_/g,"."):null,this.ipod=!0),this.ios&&this.osVersion&&e.indexOf("Version/")>=0&&"10"===this.osVersion.split(".")[0]&&(this.osVersion=e.toLowerCase().split("version/")[1].split(" ")[0]),this.webView=!(!(a||o||r)||!e.match(/.*AppleWebKit(?!.*Safari)/i)&&!window.navigator.standalone)||window.matchMedia&&window.matchMedia("(display-mode: standalone)").matches,this.webview=this.webView,this.standalone=this.webView,this.desktop=!(this.ios||this.android)||c,this.desktop&&(this.electron=c,this.macos=u,this.windows=d,this.macos&&(this.os="macos"),this.windows&&(this.os="windows")),this.pixelRatio=window.devicePixelRatio||1}}class CupertinoPane{constructor(t,e={}){this.selector=t,this.settings={initialBreak:"middle",parentElement:null,followerElement:null,pushElement:null,pushMinHeight:null,backdrop:!1,backdropOpacity:.4,animationType:"ease",animationDuration:300,dragBy:null,bottomOffset:0,darkMode:!1,bottomClose:!1,freeMode:!1,buttonClose:!0,topperOverflow:!0,topperOverflowOffset:0,lowerThanBottom:!0,upperThanTop:!1,showDraggable:!0,draggableOver:!1,clickBottomOpen:!0,preventClicks:!0,simulateTouch:!0,passiveListeners:!0,touchMoveStopPropagation:!1,touchAngle:null,breaks:{},onDidDismiss:()=>{},onWillDismiss:()=>{},onDidPresent:()=>{},onWillPresent:()=>{},onDragStart:()=>{},onDrag:()=>{},onDragEnd:()=>{},onBackdropTap:()=>{},onTransitionStart:()=>{},onTransitionEnd:()=>{}},this.defaultBreaksConf={top:{enabled:!0,height:window.innerHeight-47.25},middle:{enabled:!0,height:300},bottom:{enabled:!0,height:100}},this.screen_height=window.innerHeight,this.steps=[],this.pointerDown=!1,this.contentScrollTop=0,this.disableDragEvents=!1,this.disableDragAngle=!1,this.rendered=!1,this.allowClick=!0,this.breaks={},this.brs=[],this.device=new Device,this.touchStartCb=t=>this.touchStart(t),this.touchMoveBackdropCb=t=>this.touchMoveBackdrop(t),this.touchMoveCb=t=>this.touchMove(t),this.touchEndCb=t=>this.touchEnd(t),this.onClickCb=t=>this.onClick(t),this.swipeNextPoint=(t,e,s)=>{if(this.currentBreakpoint===this.breaks.top){if(t>e){if(this.settings.breaks.middle.enabled)return this.breaks.middle;if(this.settings.breaks.bottom.enabled)return this.breaks.middle<s?s:this.breaks.bottom}return this.breaks.top}if(this.currentBreakpoint===this.breaks.middle)return t<-e&&this.settings.breaks.top.enabled?this.breaks.top:t>e&&this.settings.breaks.bottom.enabled?this.breaks.bottom:this.breaks.middle;if(this.currentBreakpoint===this.breaks.bottom){if(t<-e){if(this.settings.breaks.middle.enabled)return this.breaks.middle>s?s:this.breaks.middle;if(this.settings.breaks.top.enabled)return this.breaks.top}return this.breaks.bottom}return s},this.touchEvents=(()=>{const t=["touchstart","touchmove","touchend","touchcancel"];let e=["mousedown","mousemove","mouseup"];Support.pointerEvents&&(e=["pointerdown","pointermove","pointerup"]);const s={start:t[0],move:t[1],end:t[2],cancel:t[3]},i={start:e[0],move:e[1],end:e[2]};return Support.touch||!this.settings.simulateTouch?s:i})(),t instanceof HTMLElement?this.selector=t:this.selector=document.querySelector(t),this.selector?this.isPanePresented()?console.warn("Cupertino Pane: specified selector or DOM element already in use",this.selector):(this.el=this.selector,this.el.style.display="none",this.settings=Object.assign(Object.assign({},this.settings),e),this.settings.parentElement?this.settings.parentElement=document.querySelector(this.settings.parentElement):this.settings.parentElement=this.el.parentElement):console.warn("Cupertino Pane: wrong selector or DOM element specified",this.selector)}drawElements(){this.parentEl=this.settings.parentElement,this.wrapperEl=document.createElement("div"),this.wrapperEl.className="cupertino-pane-wrapper "+this.el.className,this.wrapperEl.style.position="absolute",this.wrapperEl.style.top="0",this.wrapperEl.style.left="0",this.paneEl=document.createElement("div"),this.paneEl.className="pane",this.paneEl.style.position="fixed",this.paneEl.style.zIndex="11",this.paneEl.style.paddingTop="15px",this.paneEl.style.width="100%",this.paneEl.style.maxWidth="500px",this.paneEl.style.left="0px",this.paneEl.style.right="0px",this.paneEl.style.marginLeft="auto",this.paneEl.style.marginRight="auto",this.paneEl.style.height=this.screen_height-this.topper-this.settings.bottomOffset+"px",this.paneEl.style.background="#ffffff",this.paneEl.style.borderTopLeftRadius="20px",this.paneEl.style.borderTopRightRadius="20px",this.paneEl.style.boxShadow="0 4px 16px rgba(0,0,0,.12)",this.paneEl.style.overflow="hidden",this.paneEl.style.willChange="transform",this.paneEl.style.transform=`translateY(${this.breaks[this.settings.initialBreak]}px) translateZ(0px)`,this.draggableEl=document.createElement("div"),this.draggableEl.className="draggable",this.draggableEl.style.padding="5px",this.draggableEl.style.position="absolute",this.draggableEl.style.top="0",this.draggableEl.style.left="0",this.draggableEl.style.right="0",this.draggableEl.style.marginLeft="auto",this.draggableEl.style.marginRight="auto",this.draggableEl.style.height="30px",this.draggableEl.style.zIndex="12",this.moveEl=document.createElement("div"),this.moveEl.className="move",this.moveEl.style.margin="0 auto",this.moveEl.style.height="5px",this.moveEl.style.background="#c0c0c0",this.moveEl.style.width="36px",this.moveEl.style.borderRadius="4px",this.contentEl=this.el,this.contentEl.style.display="block",this.contentEl.style.transition=`opacity ${this.settings.animationDuration}ms ${this.settings.animationType} 0s`,this.contentEl.style.overflowX="hidden",this.closeEl=document.createElement("div"),this.closeEl.className="close-button",this.closeEl.style.width="26px",this.closeEl.style.height="26px",this.closeEl.style.position="absolute",this.closeEl.style.background="#ebebeb",this.closeEl.style.top="16px",this.closeEl.style.right="20px",this.closeEl.style.zIndex="14",this.closeEl.style.borderRadius="100%"}present(t={animate:!1}){if(this.el)if(this.isPanePresented()&&this.rendered)this.moveToBreak(this.settings.initialBreak);else if(!this.isPanePresented()||this.rendered){if(this.settings.onWillPresent(),this.breaks={top:this.screen_height,middle:this.screen_height,bottom:this.screen_height},["top","middle","bottom"].forEach(t=>{this.breaks[t]-=this.settings.bottomOffset,this.settings.breaks[t]||(this.settings.breaks[t]=this.defaultBreaksConf[t]),this.settings.breaks[t]&&this.settings.breaks[t].enabled&&this.settings.breaks[t].height&&(this.breaks[t]-=this.settings.breaks[t].height)}),this.settings.breaks[this.settings.initialBreak].enabled||console.warn("Cupertino Pane: Please set initialBreak for enabled breakpoint"),this.settings.breaks.middle.height>=this.settings.breaks.top.height&&console.warn("Cupertino Pane: Please set middle height lower than top height"),this.settings.breaks.middle.height<=this.settings.breaks.bottom.height&&console.warn("Cupertino Pane: Please set bottom height lower than middle height"),this.brs=[],["top","middle","bottom"].forEach(t=>{this.settings.breaks[t].enabled&&this.brs.push(this.breaks[t])}),this.topper=this.brs.reduce((t,e)=>Math.abs(e)<Math.abs(t)?e:t),this.bottomer=this.brs.reduce((t,e)=>Math.abs(e)>Math.abs(t)?e:t),this.currentBreakpoint=this.breaks[this.settings.initialBreak],this.drawElements(),this.parentEl.appendChild(this.wrapperEl),this.wrapperEl.appendChild(this.paneEl),this.paneEl.appendChild(this.draggableEl),this.paneEl.appendChild(this.contentEl),this.draggableEl.appendChild(this.moveEl),this.rendered=!0,this.settings.followerElement){if(!document.querySelector(this.settings.followerElement))return void console.warn("Cupertino Pane: wrong follower element selector specified",this.settings.followerElement);this.followerEl=document.querySelector(this.settings.followerElement),this.followerEl.style.willChange="transform, border-radius",this.followerEl.style.transform="translateY(0px) translateZ(0px)",this.followerEl.style.transition=`all ${this.settings.animationDuration}ms ${this.getTimingFunction(this.settings.breaks[this.currentBreak()].bounce)} 0s`}if(this.settings.pushElement&&(this.settings.pushElement=document.querySelector(this.settings.pushElement)),this.settings.showDraggable||(this.draggableEl.style.opacity="0"),this.settings.draggableOver&&(this.paneEl.style.background="transparent",this.paneEl.style.boxShadow="none",this.paneEl.style.paddingTop="30px",this.contentEl.style.background="#ffffff",this.contentEl.style.display="block",this.contentEl.style.borderTopLeftRadius="20px",this.contentEl.style.borderTopRightRadius="20px",this.contentEl.style.boxShadow="0 4px 16px rgba(0,0,0,.12)",this.closeEl.style.top="45px",this.draggableEl.style.padding="15px",this.moveEl.style.width="45px",this.moveEl.style.background="rgba(225, 225, 225, 0.6)",Support.backdropFilter&&(this.moveEl.style.backdropFilter="saturate(180%) blur(20px)",this.moveEl.style.webkitBackdropFilter="saturate(180%) blur(20px)")),this.settings.darkMode&&(this.paneEl.style.background="#1c1c1d",this.paneEl.style.color="#ffffff",this.moveEl.style.background="#5a5a5e"),this.settings.buttonClose){this.paneEl.appendChild(this.closeEl),this.closeEl.addEventListener("click",t=>this.destroy({animate:!0}));let t="#7a7a7e";this.settings.darkMode&&(this.closeEl.style.background="#424246",t="#a8a7ae"),this.closeEl.innerHTML=`<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512">\n <path fill="${t}" d="M278.6 256l68.2-68.2c6.2-6.2 6.2-16.4 0-22.6-6.2-6.2-16.4-6.2-22.6 0L256 233.4l-68.2-68.2c-6.2-6.2-16.4-6.2-22.6 0-3.1 3.1-4.7 7.2-4.7 11.3 0 4.1 1.6 8.2 4.7 11.3l68.2 68.2-68.2 68.2c-3.1 3.1-4.7 7.2-4.7 11.3 0 4.1 1.6 8.2 4.7 11.3 6.2 6.2 16.4 6.2 22.6 0l68.2-68.2 68.2 68.2c6.2 6.2 16.4 6.2 22.6 0 6.2-6.2 6.2-16.4 0-22.6L278.6 256z"/>\n </svg>`}this.settings.bottomClose&&(this.settings.breaks.bottom.enabled=!0),this.settings.backdrop&&this.renderBackdrop(),this.scrollElementInit(),this.checkOpacityAttr(this.currentBreakpoint),this.checkOverflowAttr(this.currentBreakpoint),this.device.android&&(document.body.style.overscrollBehaviorY="none",this.device.ionic&&this.device.cordova&&window.addEventListener("keyboardWillHide",()=>{this.paneEl&&window.requestAnimationFrame(()=>{this.wrapperEl.style.width="100%",this.paneEl.style.position="absolute",window.requestAnimationFrame(()=>{this.wrapperEl.style.width="unset",this.paneEl.style.position="fixed"})})})),this.attachAllEvents(),t.animate?this.doTransition({type:"present",translateY:this.breaks[this.settings.initialBreak]}):(this.settings.pushElement&&this.pushTransition(this.breaks[this.settings.initialBreak],"unset"),this.settings.onDidPresent())}else console.warn("Cupertino Pane: specified selector or DOM element already in use",this.selector)}attachAllEvents(){this.settings.dragBy?this.settings.dragBy.forEach(t=>{const e=document.querySelector(t);e&&this.attachEvents(e)}):this.attachEvents(this.paneEl)}detachAllEvents(){this.settings.dragBy?this.settings.dragBy.forEach(t=>{const e=document.querySelector(t);e&&this.detachEvents(e)}):this.detachEvents(this.paneEl)}resetEvents(){this.detachAllEvents(),this.attachAllEvents()}scrollElementInit(){let t=this.el.querySelectorAll("[overflow-y]");!t.length||t.length>1?this.overflowEl=this.contentEl:this.overflowEl=t[0],this.settings.topperOverflow&&setTimeout(()=>{this.overflowEl.style.height=this.screen_height-this.topper-this.settings.bottomOffset-this.settings.topperOverflowOffset-this.overflowEl.offsetTop+"px"},150)}getTimingFunction(t){return t?"cubic-bezier(0.175, 0.885, 0.370, 1.120)":this.settings.animationType}checkOpacityAttr(t){let e=this.el.querySelectorAll("[hide-on-bottom]");e.length&&e.forEach(e=>{e.style.transition=`opacity ${this.settings.animationDuration}ms ${this.settings.animationType} 0s`,e.style.opacity=t>=this.breaks.bottom?"0":"1"})}checkOverflowAttr(t){this.settings.topperOverflow&&(this.overflowEl.style.overflowY=t<=this.topper?"auto":"hidden")}isPanePresented(){let t=Array.from(document.querySelectorAll(".cupertino-pane-wrapper"));return!!t.length&&!!t.find(t=>t.contains(this.selector))}isDragScrollabe(t){return!!t.find(t=>t===this.overflowEl)}touchStart(t){if(this.settings.onDragStart(t),this.disableDragEvents)return;this.allowClick=!0,this.disableDragAngle=!1;const e="touchstart"===t.type&&t.targetTouches&&(t.targetTouches[0]||t.changedTouches[0]),s="touchstart"===t.type?e.screenY:t.screenY,i="touchstart"===t.type?e.screenX:t.screenX;"mousedown"===t.type&&(this.pointerDown=!0),this.startY=s,this.startX=i,this.isDragScrollabe(t.path||t.composedPath())&&(this.startY+=this.contentScrollTop),this.steps.push(this.startY)}touchMoveBackdrop(t){this.settings.touchMoveStopPropagation&&t.stopPropagation()}touchMove(t){if(this.settings.onDrag(t),this.disableDragEvents)return;if(this.disableDragAngle)return;this.settings.touchMoveStopPropagation&&t.stopPropagation();const e="touchmove"===t.type&&t.targetTouches&&(t.targetTouches[0]||t.changedTouches[0]),s="touchmove"===t.type?e.screenY:t.screenY,i="touchmove"===t.type?e.screenX:t.screenX;if("mousemove"===t.type&&!this.pointerDown)return;let n=s,o=i;const r=n-this.steps[this.steps.length-1];let a=this.getPanelTransformY()+r;if(this.settings.touchAngle){let t;const e=o-this.startX,s=n-this.startY;if(t=180*Math.atan2(Math.abs(s),Math.abs(e))/Math.PI,e*e+s*s>=25&&90-t>this.settings.touchAngle)return void(this.disableDragAngle=!0)}if(!(this.isDragScrollabe(t.path||t.composedPath())&&"auto"===this.overflowEl.style.overflowY&&(this.overflowEl.addEventListener("scroll",t=>{this.contentScrollTop=t.target.scrollTop}),a>this.topper&&this.contentScrollTop>0||a<=this.topper)))if(a<=this.topper&&!this.settings.upperThanTop)this.paneEl.style.transform=`translateY(${this.topper}px) translateZ(0px)`;else{if(a<=this.topper&&this.settings.upperThanTop){const t=(-this.topper+this.topper-this.getPanelTransformY())/this.topper/-8;a=this.getPanelTransformY()+r*t}this.settings.freeMode&&!this.settings.bottomClose&&a>=this.bottomer||(!this.settings.lowerThanBottom&&a>=this.bottomer?this.destroy({animate:!0}):(this.allowClick=!1,this.checkOpacityAttr(a),this.checkOverflowAttr(a),this.doTransition({type:"move",translateY:a}),this.steps.push(n)))}}touchEnd(t){if(this.settings.onDragEnd(t),this.disableDragEvents)return;const e="touchmove"===t.type&&t.targetTouches&&(t.targetTouches[0]||t.changedTouches[0]);"touchmove"===t.type?e.screenY:t.screenY;"mouseup"===t.type&&(this.pointerDown=!1);let s=this.brs.reduce((t,e)=>Math.abs(e-this.getPanelTransformY())<Math.abs(t-this.getPanelTransformY())?e:t);const i=this.steps[this.steps.length-1]-this.steps[this.steps.length-2],n=window.hasOwnProperty("cordova")?4:3;Math.abs(i)>=n&&(s=this.swipeNextPoint(i,n,s)),this.settings.clickBottomOpen&&this.currentBreakpoint===this.breaks.bottom&&isNaN(i)&&(s=this.settings.breaks.middle.enabled?this.breaks.middle:this.settings.breaks.top.enabled?this.breaks.top:this.breaks.bottom),this.steps=[],this.currentBreakpoint=s,this.checkOpacityAttr(this.currentBreakpoint),this.checkOverflowAttr(this.currentBreakpoint),this.settings.bottomClose&&s===this.breaks.bottom?this.destroy({animate:!0}):this.doTransition({type:"end",translateY:s})}onClick(t){this.allowClick||this.settings.preventClicks&&(t.preventDefault(),t.stopPropagation(),t.stopImmediatePropagation())}isBackdropPresented(){return!!document.querySelector(".cupertino-pane-wrapper .backdrop")}renderBackdrop(){this.backdropEl=document.createElement("div"),this.backdropEl.className="backdrop",this.backdropEl.style.overflow="hidden",this.backdropEl.style.position="fixed",this.backdropEl.style.width="100%",this.backdropEl.style.bottom="0",this.backdropEl.style.right="0",this.backdropEl.style.left="0",this.backdropEl.style.top="0",this.backdropEl.style.transition=`all ${this.settings.animationDuration}ms ${this.settings.animationType} 0s`,this.backdropEl.style.backgroundColor=`rgba(0,0,0, ${this.settings.backdropOpacity})`,this.backdropEl.style.display="none",this.backdropEl.style.zIndex="10",this.wrapperEl.appendChild(this.backdropEl),this.backdropEl.style.display="block",this.backdropEl.addEventListener("click",t=>this.settings.onBackdropTap()),this.resetEvents()}backdrop(t={show:!0}){if(!this.isPanePresented())return console.warn("Cupertino Pane: Present pane before call backdrop()"),null;this.isBackdropPresented()||this.renderBackdrop();const e=()=>{this.backdropEl.style.transition="initial",this.backdropEl.style.display="none",this.backdropEl.removeEventListener("transitionend",e)};if(this.backdropEl.style.transition=`all ${this.settings.animationDuration}ms ${this.settings.animationType} 0s`,this.backdropEl.style.backgroundColor="rgba(0,0,0,.0)",t.show)this.backdropEl.style.display="block",setTimeout(()=>{this.backdropEl.style.backgroundColor=`rgba(0,0,0, ${this.settings.backdropOpacity})`},50);else{if("none"===this.backdropEl.style.display)return;this.backdropEl.addEventListener("transitionend",e)}}attachEvents(t){var e,s,i;if(!Support.touch&&Support.pointerEvents)t.addEventListener(this.touchEvents.start,this.touchStartCb,!1),t.addEventListener(this.touchEvents.move,this.touchMoveCb,!1),t.addEventListener(this.touchEvents.end,this.touchEndCb,!1),null===(e=this.backdropEl)||void 0===e||e.addEventListener(this.touchEvents.move,this.touchMoveBackdropCb,!1);else{if(Support.touch){const e=!("touchstart"!==this.touchEvents.start||!Support.passiveListener||!this.settings.passiveListeners)&&{passive:!0,capture:!1};t.addEventListener(this.touchEvents.start,this.touchStartCb,e),t.addEventListener(this.touchEvents.move,this.touchMoveCb,!!Support.passiveListener&&{passive:!1,capture:!1}),t.addEventListener(this.touchEvents.end,this.touchEndCb,e),null===(s=this.backdropEl)||void 0===s||s.addEventListener(this.touchEvents.move,this.touchMoveBackdropCb,!!Support.passiveListener&&{passive:!1,capture:!1}),this.touchEvents.cancel&&t.addEventListener(this.touchEvents.cancel,this.touchEndCb,e)}(this.settings.simulateTouch&&!this.device.ios&&!this.device.android||this.settings.simulateTouch&&!Support.touch&&this.device.ios)&&(t.addEventListener("mousedown",this.touchStartCb,!1),t.addEventListener("mousemove",this.touchMoveCb,!1),t.addEventListener("mouseup",this.touchEndCb,!1),null===(i=this.backdropEl)||void 0===i||i.addEventListener("mousemove",this.touchMoveBackdropCb,!1))}this.settings.preventClicks&&t.addEventListener("click",this.onClickCb,!0)}detachEvents(t){var e,s,i;if(!Support.touch&&Support.pointerEvents)t.removeEventListener(this.touchEvents.start,this.touchStartCb,!1),t.removeEventListener(this.touchEvents.move,this.touchMoveCb,!1),t.removeEventListener(this.touchEvents.end,this.touchEndCb,!1),null===(e=this.backdropEl)||void 0===e||e.removeEventListener(this.touchEvents.move,this.touchMoveBackdropCb,!1);else{if(Support.touch){const e=!("onTouchStart"!==this.touchEvents.start||!Support.passiveListener||!this.settings.passiveListeners)&&{passive:!0,capture:!1};t.removeEventListener(this.touchEvents.start,this.touchStartCb,e),t.removeEventListener(this.touchEvents.move,this.touchMoveCb,!1),t.removeEventListener(this.touchEvents.end,this.touchEndCb,e),null===(s=this.backdropEl)||void 0===s||s.removeEventListener(this.touchEvents.move,this.touchMoveBackdropCb,!1),this.touchEvents.cancel&&t.removeEventListener(this.touchEvents.cancel,this.touchEndCb,e)}(this.settings.simulateTouch&&!this.device.ios&&!this.device.android||this.settings.simulateTouch&&!Support.touch&&this.device.ios)&&(t.removeEventListener("mousedown",this.touchStartCb,!1),t.removeEventListener("mousemove",this.touchMoveCb,!1),t.removeEventListener("mouseup",this.touchEndCb,!1),null===(i=this.backdropEl)||void 0===i||i.removeEventListener("mousemove",this.touchMoveBackdropCb,!1))}this.settings.preventClicks&&t.removeEventListener("click",this.onClickCb,!0)}getPanelTransformY(){return parseFloat(/\.*translateY\((.*)px\)/i.exec(this.paneEl.style.transform)[1])}disableDrag(){this.disableDragEvents=!0}enableDrag(){this.disableDragEvents=!1}moveToBreak(t){if(!this.isPanePresented())return console.warn("Cupertino Pane: Present pane before call moveToBreak()"),null;this.settings.breaks[t].enabled?(this.checkOpacityAttr(this.breaks[t]),this.checkOverflowAttr(this.breaks[t]),this.doTransition({type:"breakpoint",translateY:this.breaks[t]}),this.currentBreakpoint=this.breaks[t]):console.warn("Cupertino Pane: %s breakpoint disabled",t)}hide(){return this.isPanePresented()?this.isHidden()?(console.warn("Cupertino Pane: Pane already hidden"),null):void this.doTransition({type:"hide",translateY:this.screen_height}):(console.warn("Cupertino Pane: Present pane before call hide()"),null)}isHidden(){return this.isPanePresented()?this.paneEl.style.transform===`translateY(${this.screen_height}px) translateZ(0px)`:(console.warn("Cupertino Pane: Present pane before call isHidden()"),null)}currentBreak(){return this.isPanePresented()?this.breaks.top===this.currentBreakpoint?"top":this.breaks.middle===this.currentBreakpoint?"middle":this.breaks.bottom===this.currentBreakpoint?"bottom":null:(console.warn("Cupertino Pane: Present pane before call currentBreak()"),null)}destroyResets(){this.parentEl.appendChild(this.contentEl),this.wrapperEl.remove(),this.detachAllEvents(),this.currentBreakpoint=this.breaks[this.settings.initialBreak],this.contentEl.style.display="none"}destroy(t={animate:!1}){if(!this.isPanePresented())return console.warn("Cupertino Pane: Present pane before call destroy()"),null;this.settings.onWillDismiss(),t.animate?this.doTransition({type:"destroy",translateY:this.screen_height}):(this.destroyResets(),this.settings.onDidDismiss())}pushTransition(t,e){t=this.screen_height-t;const s=this.settings.pushMinHeight?this.settings.pushMinHeight:this.screen_height-this.bottomer,i=this.screen_height-this.topper;this.settings.pushElement.style.transition=e;const n=(t,e,s,i)=>{this.settings.pushElement.style.transform=`translateY(${e}px) scale(${t})`,this.settings.pushElement.style.borderRadius=s+"px",this.settings.pushElement.style.filter=`contrast(${i})`};if(t<=s)return void n(1,0,0,1);const o=(e,n)=>{let o=-1*(i*n-s*e);return o-=(e-n)*t,o/=s-i,o>n&&(o=n),o<e&&(o=e),o};n(o(.93,1),-1*o(-6,0),-1*o(-10,0),o(.85,1))}doTransition(t={}){if("move"===t.type)return this.paneEl.style.transition="all 0ms linear 0ms",this.paneEl.style.transform=`translateY(${t.translateY}px) translateZ(0px)`,this.followerEl&&(this.followerEl.style.transition="all 0ms linear 0ms",this.followerEl.style.transform=`translateY(${t.translateY-this.breaks[this.settings.initialBreak]}px) translateZ(0px)`),void(this.settings.pushElement&&this.pushTransition(this.getPanelTransformY(),"all 0ms linear 0ms"));const e=()=>{"destroy"===t.type&&this.destroyResets(),this.paneEl.style.transition="initial",this.followerEl&&(this.followerEl.style.transition="initial"),this.settings.backdrop&&("destroy"!==t.type&&"hide"!==t.type||(this.backdropEl.style.transition="initial",this.backdropEl.style.display="none")),"present"===t.type&&this.settings.onDidPresent(),"destroy"===t.type&&this.settings.onDidDismiss(),this.settings.onTransitionEnd(),this.paneEl.removeEventListener("transitionend",e)};if("breakpoint"===t.type||"end"===t.type||"present"===t.type||"hide"===t.type||"destroy"===t.type){if(this.settings.backdrop&&(this.isHidden()||"hide"===t.type||"destroy"===t.type||"present"===t.type)&&(this.backdropEl.style.backgroundColor="rgba(0,0,0,.0)",this.backdropEl.style.transition=`all ${this.settings.animationDuration}ms ${this.settings.animationType} 0s`,"hide"!==t.type&&"destroy"!==t.type&&(this.backdropEl.style.display="block",setTimeout(()=>{this.backdropEl.style.backgroundColor=`rgba(0,0,0, ${this.settings.backdropOpacity})`},50))),"end"===t.type&&this.settings.freeMode)return;const s=Object.entries(this.settings.breaks).find(e=>e[1].height===this.screen_height-t.translateY),i=this.getTimingFunction(!(!s||!s[1].bounce));return this.paneEl.style.transition=`transform ${this.settings.animationDuration}ms ${i} 0s`,this.followerEl&&(this.followerEl.style.transition=`transform ${this.settings.animationDuration}ms ${i} 0s`),this.settings.pushElement&&this.pushTransition(t.translateY,`all ${this.settings.animationDuration}ms ${this.settings.animationType} 0s`),"present"===t.type?(this.paneEl.style.transform=`translateY(${this.screen_height}px) translateZ(0px)`,setTimeout(()=>{this.settings.onTransitionStart({translateY:{new:t.translateY}}),this.paneEl.style.transform=`translateY(${t.translateY}px) translateZ(0px)`,this.followerEl&&(this.followerEl.style.transform="translateY(0px) translateZ(0px)")},50)):(this.settings.onTransitionStart({translateY:{new:t.translateY}}),this.paneEl.style.transform=`translateY(${t.translateY}px) translateZ(0px)`,this.followerEl&&(this.followerEl.style.transform=`translateY(${t.translateY-this.breaks[this.settings.initialBreak]}px) translateZ(0px)`)),void this.paneEl.addEventListener("transitionend",e)}}}exports.CupertinoPane=CupertinoPane; | ||
//# sourceMappingURL=cupertino-pane.min.js.map |
@@ -0,17 +1,10 @@ | ||
export interface PaneBreak { | ||
enabled: boolean; | ||
height?: number; | ||
bounce?: boolean; | ||
} | ||
export interface PaneBreaks { | ||
top?: { | ||
enabled: boolean; | ||
height?: number; | ||
offset?: number; | ||
}; | ||
middle?: { | ||
enabled: boolean; | ||
height?: number; | ||
offset?: number; | ||
}; | ||
bottom?: { | ||
enabled: boolean; | ||
height?: number; | ||
offset?: number; | ||
}; | ||
top?: PaneBreak; | ||
middle?: PaneBreak; | ||
bottom?: PaneBreak; | ||
} | ||
@@ -27,5 +20,7 @@ export interface TransitionStartEvent { | ||
followerElement: string; | ||
pushElement: any; | ||
pushMinHeight: number; | ||
backdrop: boolean; | ||
backdropOpacity: number; | ||
animationType: ('ease' | 'ease-in' | 'ease-out' | 'ease-in-out' | 'cubic-bezier'); | ||
animationType: string; | ||
animationDuration: number; | ||
@@ -40,2 +35,3 @@ bottomOffset: number; | ||
lowerThanBottom: boolean; | ||
upperThanTop: boolean; | ||
showDraggable: boolean; | ||
@@ -45,4 +41,7 @@ draggableOver: boolean; | ||
dragBy: string[]; | ||
preventClicks: boolean; | ||
simulateTouch: boolean; | ||
passiveListeners: boolean; | ||
touchMoveStopPropagation: boolean; | ||
touchAngle: number; | ||
breaks: PaneBreaks; | ||
@@ -49,0 +48,0 @@ onDidDismiss: (event?: CustomEvent) => void; |
{ | ||
"name": "cupertino-pane", | ||
"description": "Multiplatform slide-over pane", | ||
"version": "1.1.7", | ||
"version": "1.1.8", | ||
"author": "Roman Antonov (roman-rr)", | ||
@@ -6,0 +6,0 @@ "homepage": "https://github.com/roman-rr/cupertino-pane/", |
@@ -64,3 +64,3 @@ <!-- https://github.com/ai/nanoid - cover --> | ||
- [Apple Clips live](https://output.jsbin.com/luqaxud) | ||
- [Bulletin live](https://output.jsbin.com/fonavuy) | ||
- [Bulletin live](https://output.jsbin.com/tafahupihe) | ||
- [Starbucks live](https://output.jsbin.com/jayicip) | ||
@@ -131,3 +131,3 @@ - [Backdrop drag-opacity live](https://output.jsbin.com/riwahab) | ||
breaks: { | ||
middle: { enabled: true, height: 300 }, | ||
middle: { enabled: true, height: 300, bounce: true }, | ||
bottom: { enabled: true, height: 80 }, | ||
@@ -148,3 +148,3 @@ }, | ||
var myPane = new CupertinoPane('.cupertino-pane', { /* ... */ }); | ||
myPane.present(); | ||
myPane.present({animate: true}); | ||
}); | ||
@@ -159,3 +159,3 @@ ``` | ||
let myPane = new CupertinoPane('.cupertino-pane', CupertinoSettings); | ||
myPane.present(); | ||
myPane.present({animate: true}); | ||
``` | ||
@@ -180,2 +180,4 @@ | ||
| **followerElement** | `string` | Follower element selector | Element with selector will following pane transitions | | ||
| **pushElement** | `string` | Push element selector | DOM Element will be pushed and scaled | | ||
| **pushMinHeight** | `number` | Most bottom available point | Height from which 3d push effect will be started | | ||
| **initialBreak** | `'top' \| 'middle' \| 'bottom'` | 'middle' | Initial pane position | | ||
@@ -185,3 +187,3 @@ | **darkMode** | `boolean` | false | Initial pane styles | | ||
| **backdropOpacity** | `number` | 0.4 | Dimmed overlay opacity value | | ||
| **animationType** | `'ease' \| 'ease-in' \| 'ease-out' \| 'ease-in-out' \| 'cubic-bezier'` | 'ease' | Transition property animation type | | ||
| **animationType** | `string` | 'ease' | Base transition timing function | | ||
| **animationDuration** | `number` | 300 | Transition property duration | | ||
@@ -191,2 +193,4 @@ | **bottomClose** | `boolean` | false | Close pane with drag to bottom breakpoint | | ||
| **lowerThanBottom** | `boolean` | true | By default allow user to drag pane lower than bottom position. On `false` will automatically place pane to bottom position on lower than bottom attemption | | ||
| **upperThanTop** | `boolean` | false | Allow user to drag pane upper than maximum top position. Useful with bulletin style without overflow-y | | ||
| **touchAngle** | `number` | null | Allowable angle (in degrees) to trigger touch move | | ||
| **buttonClose** | `boolean` | true | Determinate whetever close button will render or not | | ||
@@ -200,2 +204,4 @@ | **bottomOffset** | `number` | 0 | Margin bottom for pane from screen bottom point | | ||
| **dragBy** | `string[]` | null | Array of selectors for whom elements drag events will be attached. By default drag events attached to pane element. If you are about to drag only with draggable component set option to ['.pane .draggable'] | | ||
| **preventClicks** | `boolean` | true | Prevent accidental unwanted clicks events during move gestures | | ||
| **touchMoveStopPropagation** | `boolean` | false | If enabled, then propagation of "touchmove" will be stopped | | ||
| **simulateTouch** | `boolean` | true | Simulate touch events for Desktop | | ||
@@ -210,3 +216,4 @@ | **passiveListeners** | `boolean` | true | (Indicates that the function specified by listener will never call preventDefault()) | | ||
enabled: true, // Enable or disable breakpoint | ||
height: 0 // Pane breakpoint height | ||
height: 700, // Pane breakpoint height | ||
bounce: true // Bounce pane on transition | ||
}, | ||
@@ -218,5 +225,8 @@ middle: { ... }, | ||
``` | ||
Bottom and middle heights normalized accross devices by default | ||
Default top height: `window.screen.height - (135 * 0.35)` | ||
Bottom and middle heights normalized accross devices by default | ||
Add property `bounce` to break and enjoy transitions in apple stocks style with `cubic-bezier(0.175, 0.885, 0.370, 1.120)` | ||
### Callbacks | ||
@@ -232,3 +242,3 @@ The function that executes when the event fires. | ||
| **onDrag** | `void: () => {}` | Call executes on each new position of pane | | ||
| **onDragEng** | `void: () => {}` | Executes when drag event complete | | ||
| **onDragEnd** | `void: () => {}` | Executes when drag event complete | | ||
| **onBackdropTap** | `void: () => {}` | Call when user tap backdrop overlay | | ||
@@ -311,14 +321,6 @@ | **onTransitionStart** | `void: () => {}` | Executes before auto transition and animation start | | ||
## Future Goals | ||
- [Code] Divide elements by classes | ||
- [Quality] Touch angle 45 | ||
- [Quality] Topper than top (allow mode/if scroll - overflow enable else 10px-20px) | ||
- [Quality] Click item/drag pane precision on device (threshold) | ||
- [Quality] Transition timing: easeOutElastic | ||
- [UI] 3D effect (ion-modal example) + release | ||
- [Showcase] Apple Music F7 | ||
- [Accurance] Draw experiment application (Normal/TimeStamp/Native) | ||
- [Accurance] Native Touch Plugin | ||
- [Quality] Keyboard manual control | ||
- [Docs] Docs engine (F7) | ||
- [Docs] Live example hosted in pages | ||
- [Platforms] React Native version | ||
@@ -325,0 +327,0 @@ - [Platforms] C++ QT version |
import { Support } from './support'; | ||
import { Device } from './device'; | ||
import { Settings } from './models'; | ||
import { Settings, PaneBreaks } from './models'; | ||
export type CupertinoSettings = Partial<Settings>; | ||
@@ -12,4 +12,6 @@ | ||
followerElement: null, | ||
pushElement: null, | ||
pushMinHeight: null, | ||
backdrop: false, | ||
backdropOpacity: 0.4, | ||
backdropOpacity: 0.4, | ||
animationType: 'ease', | ||
@@ -26,7 +28,11 @@ animationDuration: 300, | ||
lowerThanBottom: true, | ||
upperThanTop: false, | ||
showDraggable: true, | ||
draggableOver: false, | ||
clickBottomOpen: true, | ||
preventClicks: true, | ||
simulateTouch: true, | ||
passiveListeners: true, | ||
touchMoveStopPropagation: false, | ||
touchAngle: null, | ||
breaks: {}, | ||
@@ -45,10 +51,12 @@ onDidDismiss: () => {}, | ||
private defaultBreaksConf = { | ||
top: { enabled: true, height: window.innerHeight - (135 * 0.35)}, | ||
middle: { enabled: true, height: 300}, | ||
bottom: { enabled: true, height: 100}, | ||
private defaultBreaksConf: PaneBreaks = { | ||
top: { enabled: true, height: window.innerHeight - (135 * 0.35) }, | ||
middle: { enabled: true, height: 300 }, | ||
bottom: { enabled: true, height: 100 }, | ||
}; | ||
private screen_height: number = window.innerHeight; | ||
private steps: any[] = []; | ||
private startP: any; | ||
private startY: number; | ||
private startX: number; | ||
private pointerDown: boolean = false; | ||
@@ -59,5 +67,6 @@ private topper: number; | ||
private contentScrollTop: number = 0; | ||
private draggableScrollOffset: number = 0; | ||
private disableDragEvents: boolean = false; | ||
private disableDragAngle: boolean = false; | ||
private rendered: boolean = false; | ||
private allowClick: boolean = true; | ||
@@ -184,2 +193,3 @@ private breaks: {} = {} | ||
this.closeEl.style.right = '20px'; | ||
this.closeEl.style.zIndex = '14'; | ||
this.closeEl.style.borderRadius = '100%'; | ||
@@ -220,8 +230,8 @@ } | ||
} | ||
// Add offsets (offset or height, later need remove ofsfset) | ||
if (this.settings.breaks[val] | ||
&& this.settings.breaks[val].enabled | ||
&& (this.settings.breaks[val].offset || this.settings.breaks[val].height)) { | ||
this.breaks[val] -= (this.settings.breaks[val].offset || this.settings.breaks[val].height); | ||
&& this.settings.breaks[val].height) { | ||
this.breaks[val] -= this.settings.breaks[val].height; | ||
} | ||
@@ -279,5 +289,9 @@ }); | ||
this.followerEl.style.transform = `translateY(0px) translateZ(0px)`; | ||
this.followerEl.style.transition = `all ${this.settings.animationDuration}ms ${this.settings.animationType} 0s`; | ||
this.followerEl.style.transition = `all ${this.settings.animationDuration}ms ${this.getTimingFunction(this.settings.breaks[this.currentBreak()].bounce)} 0s`; | ||
} | ||
if (this.settings.pushElement) { | ||
this.settings.pushElement = document.querySelector(this.settings.pushElement); | ||
} | ||
if (!this.settings.showDraggable) { | ||
@@ -366,10 +380,3 @@ this.draggableEl.style.opacity = '0'; | ||
/****** Attach Events *******/ | ||
if (!this.settings.dragBy) { | ||
this.attachEvents(this.paneEl); | ||
} else { | ||
this.settings.dragBy.forEach((selector) => { | ||
const el = document.querySelector(selector); | ||
if (el) this.attachEvents(el); | ||
}); | ||
} | ||
this.attachAllEvents(); | ||
@@ -381,2 +388,5 @@ /****** Animation & Transition ******/ | ||
// Emit event | ||
if (this.settings.pushElement) { | ||
this.pushTransition(this.breaks[this.settings.initialBreak], 'unset'); | ||
} | ||
this.settings.onDidPresent(); | ||
@@ -390,2 +400,29 @@ } | ||
private attachAllEvents() { | ||
if (!this.settings.dragBy) { | ||
this.attachEvents(this.paneEl); | ||
} else { | ||
this.settings.dragBy.forEach((selector) => { | ||
const el = document.querySelector(selector); | ||
if (el) this.attachEvents(el); | ||
}); | ||
} | ||
} | ||
private detachAllEvents() { | ||
if (!this.settings.dragBy) { | ||
this.detachEvents(this.paneEl); | ||
} else { | ||
this.settings.dragBy.forEach((selector) => { | ||
const el = document.querySelector(selector); | ||
if (el) this.detachEvents(el); | ||
}); | ||
} | ||
} | ||
private resetEvents() { | ||
this.detachAllEvents(); | ||
this.attachAllEvents(); | ||
} | ||
private scrollElementInit() { | ||
@@ -412,2 +449,6 @@ let attrElements = this.el.querySelectorAll('[overflow-y]'); | ||
private getTimingFunction(bounce) { | ||
return bounce ? 'cubic-bezier(0.175, 0.885, 0.370, 1.120)' : this.settings.animationType; | ||
} | ||
private checkOpacityAttr(val) { | ||
@@ -452,7 +493,15 @@ let attrElements = this.el.querySelectorAll('[hide-on-bottom]'); | ||
// Allow clicks by default, disallow on move | ||
this.allowClick = true; | ||
// Allow touch angle by default, disallow no move with condition | ||
this.disableDragAngle = false; | ||
const targetTouch = t.type === 'touchstart' && t.targetTouches && (t.targetTouches[0] || t.changedTouches[0]); | ||
const screenY = t.type === 'touchstart' ? targetTouch.screenY : t.screenY; | ||
const screenX = t.type === 'touchstart' ? targetTouch.screenX : t.screenX; | ||
if (t.type === 'mousedown') this.pointerDown = true; | ||
this.startP = screenY; | ||
this.startY = screenY; | ||
this.startX = screenX; | ||
@@ -462,5 +511,5 @@ // if overflow content was scrolled | ||
if (this.isDragScrollabe(t.path || t.composedPath())) { | ||
this.startP += this.contentScrollTop; | ||
this.startY += this.contentScrollTop; | ||
} | ||
this.steps.push(this.startP); | ||
this.steps.push(this.startY); | ||
} | ||
@@ -472,2 +521,13 @@ | ||
*/ | ||
private touchMoveBackdropCb = (t) => this.touchMoveBackdrop(t); | ||
private touchMoveBackdrop(t) { | ||
if (this.settings.touchMoveStopPropagation) { | ||
t.stopPropagation(); | ||
} | ||
} | ||
/** | ||
* Touch Move Event | ||
* @param t | ||
*/ | ||
private touchMoveCb = (t) => this.touchMove(t); | ||
@@ -479,6 +539,12 @@ private touchMove(t) { | ||
if (this.disableDragEvents) return; | ||
if (this.disableDragAngle) return; | ||
if (this.settings.touchMoveStopPropagation) { | ||
t.stopPropagation(); | ||
} | ||
// Handle desktop/mobile events | ||
const targetTouch = t.type === 'touchmove' && t.targetTouches && (t.targetTouches[0] || t.changedTouches[0]); | ||
const screenY = t.type === 'touchmove' ? targetTouch.screenY : t.screenY; | ||
const screenX = t.type === 'touchmove' ? targetTouch.screenX : t.screenX; | ||
if(t.type === 'mousemove' && !this.pointerDown) return; | ||
@@ -488,5 +554,19 @@ | ||
let n = screenY; | ||
const diff = n - this.steps[this.steps.length - 1]; | ||
const newVal = this.getPanelTransformY() + diff; | ||
let v = screenX; | ||
const diffY = n - this.steps[this.steps.length - 1]; | ||
let newVal = this.getPanelTransformY() + diffY; | ||
// Touch angle | ||
if (this.settings.touchAngle) { | ||
let touchAngle; | ||
const diffX = v - this.startX; | ||
const diffY = n - this.startY; | ||
touchAngle = (Math.atan2(Math.abs(diffY), Math.abs(diffX)) * 180) / Math.PI; | ||
if (diffX * diffX + diffY * diffY >= 25 | ||
&& (90 - touchAngle > this.settings.touchAngle)) { | ||
this.disableDragAngle = true; | ||
return; | ||
} | ||
} | ||
// Not allow move panel with positive overflow scroll | ||
@@ -505,6 +585,16 @@ if (this.isDragScrollabe(t.path || t.composedPath()) | ||
// Not allow drag upper than topper point | ||
// Not allow drag topper than top point | ||
if (newVal <= this.topper && !this.settings.upperThanTop) { | ||
this.paneEl.style.transform = `translateY(${this.topper}px) translateZ(0px)`; | ||
return; | ||
} | ||
// Allow drag topper than top point | ||
if (newVal <= this.topper && this.settings.upperThanTop) { | ||
const differKoef = ((-this.topper + this.topper - this.getPanelTransformY()) / this.topper) / -8; | ||
newVal = this.getPanelTransformY() + (diffY * differKoef); | ||
} | ||
// Not allow drag lower than bottom if free mode | ||
if ((newVal <= this.topper) | ||
|| (this.settings.freeMode && !this.settings.bottomClose && (newVal >= this.bottomer))) { | ||
if (this.settings.freeMode && !this.settings.bottomClose && (newVal >= this.bottomer)) { | ||
return; | ||
@@ -520,2 +610,5 @@ } | ||
// Disallow accidentaly clicks while slide gestures | ||
this.allowClick = false; | ||
this.checkOpacityAttr(newVal); | ||
@@ -580,2 +673,18 @@ this.checkOverflowAttr(newVal); | ||
/** | ||
* Click Event | ||
* @param t | ||
*/ | ||
private onClickCb = (t) => this.onClick(t); | ||
private onClick(t) { | ||
// Prevent accidental unwanted clicks events during swiping | ||
if (!this.allowClick) { | ||
if (this.settings.preventClicks) { | ||
t.preventDefault(); | ||
t.stopPropagation(); | ||
t.stopImmediatePropagation(); | ||
} | ||
} | ||
} | ||
private swipeNextPoint = (diff, maxDiff, closest) => { | ||
@@ -644,2 +753,5 @@ if (this.currentBreakpoint === this.breaks['top']) { | ||
this.backdropEl.addEventListener('click', (t) => this.settings.onBackdropTap()); | ||
// Reset events to attach backdrop stop propagation | ||
this.resetEvents(); | ||
} | ||
@@ -712,2 +824,5 @@ | ||
el.addEventListener(this.touchEvents.end, this.touchEndCb, false); | ||
// Backdrop propagation fix | ||
this.backdropEl?.addEventListener(this.touchEvents.move, this.touchMoveBackdropCb, false); | ||
} else { | ||
@@ -720,2 +835,5 @@ | ||
el.addEventListener(this.touchEvents.end, this.touchEndCb, passiveListener); | ||
// Backdrop propagation fix | ||
this.backdropEl?.addEventListener(this.touchEvents.move, this.touchMoveBackdropCb, Support.passiveListener ? { passive: false, capture: false } : false); | ||
if (this.touchEvents['cancel']) { | ||
@@ -730,4 +848,12 @@ el.addEventListener(this.touchEvents['cancel'], this.touchEndCb, passiveListener); | ||
el.addEventListener('mouseup', this.touchEndCb, false); | ||
// Backdrop propagation fix | ||
this.backdropEl?.addEventListener('mousemove', this.touchMoveBackdropCb, false); | ||
} | ||
} | ||
// Prevent accidental unwanted clicks events during swiping | ||
if (this.settings.preventClicks) { | ||
el.addEventListener('click', this.onClickCb, true); | ||
} | ||
} | ||
@@ -741,2 +867,5 @@ | ||
el.removeEventListener(this.touchEvents.end, this.touchEndCb, false); | ||
// Backdrop propagation fix | ||
this.backdropEl?.removeEventListener(this.touchEvents.move, this.touchMoveBackdropCb, false); | ||
} else { | ||
@@ -748,2 +877,5 @@ if (Support.touch) { | ||
el.removeEventListener(this.touchEvents.end, this.touchEndCb, passiveListener); | ||
// Backdrop propagation fix | ||
this.backdropEl?.removeEventListener(this.touchEvents.move, this.touchMoveBackdropCb, false); | ||
if (this.touchEvents['cancel']) { | ||
@@ -757,4 +889,12 @@ el.removeEventListener(this.touchEvents['cancel'], this.touchEndCb, passiveListener); | ||
el.removeEventListener('mouseup', this.touchEndCb, false); | ||
// Backdrop propagation fix | ||
this.backdropEl?.removeEventListener('mousemove', this.touchMoveBackdropCb, false); | ||
} | ||
} | ||
// Prevent accidental unwanted clicks events during swiping | ||
if (this.settings.preventClicks) { | ||
el.removeEventListener('click', this.onClickCb, true); | ||
} | ||
} | ||
@@ -842,10 +982,3 @@ | ||
/****** Detach Events *******/ | ||
if (!this.settings.dragBy) { | ||
this.detachEvents(this.paneEl); | ||
} else { | ||
this.settings.dragBy.forEach((selector) => { | ||
const el = document.querySelector(selector); | ||
if (el) this.detachEvents(el); | ||
}); | ||
} | ||
this.detachAllEvents(); | ||
@@ -878,2 +1011,36 @@ // Reset vars | ||
private pushTransition(newPaneY: number, transition: string) { | ||
newPaneY = this.screen_height - newPaneY; | ||
const topHeight = this.settings.pushMinHeight ? this.settings.pushMinHeight : this.screen_height - this.bottomer; | ||
const minHeight = this.screen_height - this.topper; | ||
this.settings.pushElement.style.transition = transition; | ||
const setStyles = (scale, y, border, contrast) => { | ||
this.settings.pushElement.style.transform = `translateY(${y}px) scale(${scale})`; | ||
this.settings.pushElement.style.borderRadius = `${border}px`; | ||
this.settings.pushElement.style.filter = `contrast(${contrast})`; | ||
}; | ||
if (newPaneY <= topHeight) { | ||
setStyles(1, 0, 0, 1); | ||
return; | ||
} | ||
const getXbyY = (min, max) => { | ||
let val = (minHeight * max - topHeight * min) * -1; | ||
val -= (min - max) * newPaneY; | ||
val /= (topHeight - minHeight); | ||
if (val > max) val = max; | ||
if (val < min) val = min; | ||
return val; | ||
}; | ||
setStyles( | ||
getXbyY(0.93, 1), | ||
getXbyY(-6, 0) * -1, | ||
getXbyY(-10, 0) * -1, | ||
getXbyY(0.85, 1) | ||
); | ||
} | ||
/*********************************** | ||
@@ -883,2 +1050,3 @@ * Transitions handler | ||
private doTransition(params:any = {}): void { | ||
// touchmove simple event | ||
@@ -893,2 +1061,7 @@ if (params.type === 'move') { | ||
} | ||
// Push transition | ||
if (this.settings.pushElement) { | ||
this.pushTransition(this.getPanelTransformY(), 'all 0ms linear 0ms'); | ||
} | ||
@@ -915,3 +1088,3 @@ return; | ||
} | ||
} | ||
} | ||
@@ -959,9 +1132,21 @@ // Emit event | ||
// Get timing function && push for next | ||
// TODO: getBreakByHeight or by translateY() | ||
const nextBreak = Object.entries(this.settings.breaks).find( | ||
val => val[1].height === (this.screen_height - params.translateY) | ||
); | ||
const timingForNext = this.getTimingFunction(nextBreak && nextBreak[1].bounce ? true : false); | ||
// style | ||
this.paneEl.style.transition = `transform ${this.settings.animationDuration}ms ${this.settings.animationType} 0s`; | ||
this.paneEl.style.transition = `transform ${this.settings.animationDuration}ms ${timingForNext} 0s`; | ||
// Bind for follower same transitions | ||
if (this.followerEl) { | ||
this.followerEl.style.transition = `transform ${this.settings.animationDuration}ms ${this.settings.animationType} 0s`; | ||
this.followerEl.style.transition = `transform ${this.settings.animationDuration}ms ${timingForNext} 0s`; | ||
} | ||
// Push transition | ||
if (this.settings.pushElement) { | ||
this.pushTransition(params.translateY, `all ${this.settings.animationDuration}ms ${this.settings.animationType} 0s`); | ||
} | ||
// Main transitions | ||
@@ -972,5 +1157,5 @@ if (params.type === 'present') { | ||
// Emit event | ||
this.settings.onTransitionStart({translateY: {new: this.breaks[this.settings.initialBreak]}}); | ||
this.settings.onTransitionStart({translateY: {new: params.translateY}}); | ||
this.paneEl.style.transform = `translateY(${this.breaks[this.settings.initialBreak]}px) translateZ(0px)`; | ||
this.paneEl.style.transform = `translateY(${params.translateY}px) translateZ(0px)`; | ||
// Bind for follower same transitions | ||
@@ -977,0 +1162,0 @@ if (this.followerEl) { |
@@ -0,5 +1,11 @@ | ||
export interface PaneBreak { | ||
enabled: boolean, | ||
height?: number, | ||
bounce?: boolean | ||
} | ||
export interface PaneBreaks { | ||
top?: {enabled: boolean, height?: number, offset?: number}; | ||
middle?: {enabled: boolean, height?: number, offset?: number}; | ||
bottom?: {enabled: boolean, height?: number, offset?: number}; | ||
top?: PaneBreak; | ||
middle?: PaneBreak; | ||
bottom?: PaneBreak; | ||
} | ||
@@ -15,5 +21,7 @@ | ||
followerElement: string; | ||
pushElement: any; | ||
pushMinHeight: number; | ||
backdrop: boolean; | ||
backdropOpacity: number; | ||
animationType: ('ease'|'ease-in'|'ease-out'|'ease-in-out'|'cubic-bezier'); | ||
animationType: string; | ||
animationDuration: number; | ||
@@ -28,2 +36,3 @@ bottomOffset: number, | ||
lowerThanBottom: boolean; | ||
upperThanTop: boolean; | ||
showDraggable: boolean; | ||
@@ -33,4 +42,7 @@ draggableOver: boolean; | ||
dragBy: string[]; | ||
preventClicks: boolean; | ||
simulateTouch: boolean; | ||
passiveListeners: boolean; | ||
touchMoveStopPropagation: boolean; | ||
touchAngle: number; | ||
breaks: PaneBreaks; | ||
@@ -37,0 +49,0 @@ onDidDismiss: (event?: CustomEvent) => void, |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
11975803
4099
323