mirror of
https://github.com/jellyfin/jellyfin-web
synced 2025-03-30 19:56:21 +00:00
Move libraries to lib
This commit is contained in:
parent
385a01d5ad
commit
0ea5349422
9 changed files with 6 additions and 6 deletions
373
src/lib/navdrawer/navdrawer.js
Normal file
373
src/lib/navdrawer/navdrawer.js
Normal file
|
@ -0,0 +1,373 @@
|
|||
/**
|
||||
* NOTE: This file should not be modified.
|
||||
* It is a legacy library that should be replaced at some point.
|
||||
*/
|
||||
|
||||
import browser from '../../scripts/browser';
|
||||
import dom from '../../scripts/dom';
|
||||
import './navdrawer.scss';
|
||||
import '../../styles/scrollstyles.scss';
|
||||
import globalize from '../../scripts/globalize';
|
||||
|
||||
function getTouches(e) {
|
||||
return e.changedTouches || e.targetTouches || e.touches;
|
||||
}
|
||||
|
||||
function disableEvent(e) {
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
}
|
||||
|
||||
class NavDrawer {
|
||||
mask;
|
||||
newPos = 0;
|
||||
currentPos = 0;
|
||||
startPoint = 0;
|
||||
countStart = 0;
|
||||
velocity = 0;
|
||||
dragMode = 0;
|
||||
menuTouchStartX;
|
||||
menuTouchStartY;
|
||||
menuTouchStartTime;
|
||||
edgeContainer = document.querySelector('.mainDrawerHandle');
|
||||
isPeeking = false;
|
||||
backgroundTouchStartX;
|
||||
backgroundTouchStartTime;
|
||||
_edgeSwipeEnabled;
|
||||
|
||||
constructor(options) {
|
||||
this.options = options;
|
||||
this.defaults = {
|
||||
width: 260,
|
||||
handleSize: 10,
|
||||
disableMask: false,
|
||||
maxMaskOpacity: 0.5
|
||||
};
|
||||
options.target.classList.add('transition');
|
||||
this.scrollContainer = options.target.querySelector('.mainDrawer-scrollContainer');
|
||||
this.scrollContainer.classList.add('scrollY');
|
||||
this.isVisible = false;
|
||||
this.initialize();
|
||||
}
|
||||
|
||||
setVelocity(deltaX) {
|
||||
const time = new Date().getTime() - (this.menuTouchStartTime || 0);
|
||||
this.velocity = Math.abs(deltaX) / time;
|
||||
}
|
||||
|
||||
onMenuTouchStart = (e) => {
|
||||
const options = this.options;
|
||||
|
||||
options.target.classList.remove('transition');
|
||||
const touches = getTouches(e);
|
||||
const touch = touches[0] || {};
|
||||
this.menuTouchStartX = touch.clientX;
|
||||
this.menuTouchStartY = touch.clientY;
|
||||
this.menuTouchStartTime = new Date().getTime();
|
||||
};
|
||||
|
||||
onMenuTouchMove = (e) => {
|
||||
const scrollContainer = this.scrollContainer;
|
||||
|
||||
const isOpen = this.visible;
|
||||
const touches = getTouches(e);
|
||||
const touch = touches[0] || {};
|
||||
const endX = touch.clientX || 0;
|
||||
const endY = touch.clientY || 0;
|
||||
let deltaX = endX - (this.menuTouchStartX || 0);
|
||||
if (globalize.getIsRTL()) {
|
||||
deltaX *= -1;
|
||||
}
|
||||
const deltaY = endY - (this.menuTouchStartY || 0);
|
||||
this.setVelocity(deltaX);
|
||||
|
||||
if (isOpen && this.dragMode !== 1 && deltaX > 0) {
|
||||
this.dragMode = 2;
|
||||
}
|
||||
|
||||
if (this.dragMode === 0 && (!isOpen || Math.abs(deltaX) >= 10) && Math.abs(deltaY) < 5) {
|
||||
this.dragMode = 1;
|
||||
scrollContainer.addEventListener('scroll', disableEvent);
|
||||
this.showMask();
|
||||
} else if (this.dragMode === 0 && Math.abs(deltaY) >= 5) {
|
||||
this.dragMode = 2;
|
||||
}
|
||||
|
||||
if (this.dragMode === 1) {
|
||||
this.newPos = this.currentPos + deltaX;
|
||||
this.changeMenuPos();
|
||||
}
|
||||
};
|
||||
|
||||
onMenuTouchEnd = (e) => {
|
||||
const options = this.options;
|
||||
const scrollContainer = this.scrollContainer;
|
||||
|
||||
options.target.classList.add('transition');
|
||||
scrollContainer.removeEventListener('scroll', disableEvent);
|
||||
this.dragMode = 0;
|
||||
const touches = getTouches(e);
|
||||
const touch = touches[0] || {};
|
||||
const endX = touch.clientX || 0;
|
||||
const endY = touch.clientY || 0;
|
||||
let deltaX = endX - (this.menuTouchStartX || 0);
|
||||
if (globalize.getIsRTL()) {
|
||||
deltaX *= -1;
|
||||
}
|
||||
const deltaY = endY - (this.menuTouchStartY || 0);
|
||||
this.currentPos = deltaX;
|
||||
this.checkMenuState(deltaX, deltaY);
|
||||
};
|
||||
|
||||
onEdgeTouchMove = (e) => {
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
this.onEdgeTouchStart(e);
|
||||
};
|
||||
|
||||
onEdgeTouchStart = (e) => {
|
||||
const options = this.options;
|
||||
|
||||
if (this.isPeeking) {
|
||||
this.onMenuTouchMove(e);
|
||||
} else if ((getTouches(e)[0]?.clientX || 0) <= options.handleSize) {
|
||||
this.isPeeking = true;
|
||||
|
||||
if (e.type === 'touchstart') {
|
||||
dom.removeEventListener(this.edgeContainer, 'touchmove', this.onEdgeTouchMove, {});
|
||||
dom.addEventListener(this.edgeContainer, 'touchmove', this.onEdgeTouchMove, {});
|
||||
}
|
||||
|
||||
this.onMenuTouchStart(e);
|
||||
}
|
||||
};
|
||||
|
||||
onEdgeTouchEnd = (e) => {
|
||||
if (this.isPeeking) {
|
||||
this.isPeeking = false;
|
||||
dom.removeEventListener(this.edgeContainer, 'touchmove', this.onEdgeTouchMove, {});
|
||||
this.onMenuTouchEnd(e);
|
||||
}
|
||||
};
|
||||
|
||||
onBackgroundTouchStart = (e) => {
|
||||
const touches = getTouches(e);
|
||||
const touch = touches[0] || {};
|
||||
this.backgroundTouchStartX = touch.clientX;
|
||||
this.backgroundTouchStartTime = new Date().getTime();
|
||||
};
|
||||
|
||||
onBackgroundTouchMove = (e) => {
|
||||
const options = this.options;
|
||||
|
||||
const touches = getTouches(e);
|
||||
const touch = touches[0] || {};
|
||||
const endX = touch.clientX || 0;
|
||||
|
||||
if (endX <= options.width && this.isVisible) {
|
||||
this.countStart++;
|
||||
let deltaX = endX - (this.backgroundTouchStartX || 0);
|
||||
if (globalize.getIsRTL()) {
|
||||
deltaX *= -1;
|
||||
}
|
||||
|
||||
if (this.countStart == 1) {
|
||||
this.startPoint = deltaX;
|
||||
}
|
||||
if (deltaX < 0 && this.dragMode !== 2) {
|
||||
this.dragMode = 1;
|
||||
this.newPos = deltaX - this.startPoint + options.width;
|
||||
this.changeMenuPos();
|
||||
const time = new Date().getTime() - (this.backgroundTouchStartTime || 0);
|
||||
this.velocity = Math.abs(deltaX) / time;
|
||||
}
|
||||
}
|
||||
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
};
|
||||
|
||||
onBackgroundTouchEnd = (e) => {
|
||||
const touches = getTouches(e);
|
||||
const touch = touches[0] || {};
|
||||
const endX = touch.clientX || 0;
|
||||
let deltaX = endX - (this.backgroundTouchStartX || 0);
|
||||
if (globalize.getIsRTL()) {
|
||||
deltaX *= -1;
|
||||
}
|
||||
this.checkMenuState(deltaX);
|
||||
this.countStart = 0;
|
||||
};
|
||||
|
||||
initElements() {
|
||||
const options = this.options;
|
||||
|
||||
options.target.classList.add('touch-menu-la');
|
||||
options.target.style.width = options.width + 'px';
|
||||
if (globalize.getIsRTL()) {
|
||||
options.target.style.right = -options.width + 'px';
|
||||
} else {
|
||||
options.target.style.left = -options.width + 'px';
|
||||
}
|
||||
|
||||
if (!options.disableMask) {
|
||||
this.mask = document.createElement('div');
|
||||
this.mask.className = 'tmla-mask hide';
|
||||
document.body.appendChild(this.mask);
|
||||
}
|
||||
}
|
||||
|
||||
animateToPosition(pos) {
|
||||
const options = this.options;
|
||||
const languageAwarePos = globalize.getIsRTL() ? -pos : pos;
|
||||
requestAnimationFrame(function () {
|
||||
options.target.style.transform = pos ? 'translateX(' + languageAwarePos + 'px)' : 'none';
|
||||
});
|
||||
}
|
||||
|
||||
changeMenuPos() {
|
||||
const options = this.options;
|
||||
if (this.newPos <= options.width) {
|
||||
this.animateToPosition(this.newPos);
|
||||
}
|
||||
}
|
||||
|
||||
clickMaskClose() {
|
||||
this.mask.addEventListener('click', () => {
|
||||
this.close();
|
||||
});
|
||||
}
|
||||
|
||||
checkMenuState(deltaX, deltaY) {
|
||||
if (this.velocity >= 0.4) {
|
||||
if (deltaX >= 0 || Math.abs(deltaY || 0) >= 70) {
|
||||
this.open();
|
||||
} else {
|
||||
this.close();
|
||||
}
|
||||
} else if (this.newPos >= 100) {
|
||||
this.open();
|
||||
} else if (this.newPos) {
|
||||
this.close();
|
||||
}
|
||||
}
|
||||
|
||||
open() {
|
||||
const options = this.options;
|
||||
|
||||
this.animateToPosition(options.width);
|
||||
this.currentPos = options.width;
|
||||
this.isVisible = true;
|
||||
options.target.classList.add('drawer-open');
|
||||
this.showMask();
|
||||
this.invoke(options.onChange);
|
||||
}
|
||||
|
||||
close() {
|
||||
const options = this.options;
|
||||
|
||||
this.animateToPosition(0);
|
||||
this.currentPos = 0;
|
||||
this.isVisible = false;
|
||||
options.target.classList.remove('drawer-open');
|
||||
this.hideMask();
|
||||
this.invoke(options.onChange);
|
||||
}
|
||||
|
||||
toggle() {
|
||||
if (this.isVisible) {
|
||||
this.close();
|
||||
} else {
|
||||
this.open();
|
||||
}
|
||||
}
|
||||
|
||||
showMask() {
|
||||
this.mask.classList.remove('hide');
|
||||
this.mask.classList.add('backdrop');
|
||||
}
|
||||
|
||||
hideMask() {
|
||||
this.mask.classList.add('hide');
|
||||
this.mask.classList.remove('backdrop');
|
||||
}
|
||||
|
||||
invoke(fn) {
|
||||
if (fn) {
|
||||
fn.apply(this);
|
||||
}
|
||||
}
|
||||
|
||||
setEdgeSwipeEnabled(enabled) {
|
||||
const options = this.options;
|
||||
|
||||
if (!options.disableEdgeSwipe && browser.touch) {
|
||||
if (enabled) {
|
||||
if (!this._edgeSwipeEnabled) {
|
||||
this._edgeSwipeEnabled = true;
|
||||
dom.addEventListener(this.edgeContainer, 'touchstart', this.onEdgeTouchStart, {
|
||||
passive: true
|
||||
});
|
||||
dom.addEventListener(this.edgeContainer, 'touchend', this.onEdgeTouchEnd, {
|
||||
passive: true
|
||||
});
|
||||
dom.addEventListener(this.edgeContainer, 'touchcancel', this.onEdgeTouchEnd, {
|
||||
passive: true
|
||||
});
|
||||
}
|
||||
} else if (this._edgeSwipeEnabled) {
|
||||
this._edgeSwipeEnabled = false;
|
||||
dom.removeEventListener(this.edgeContainer, 'touchstart', this.onEdgeTouchStart, {
|
||||
passive: true
|
||||
});
|
||||
dom.removeEventListener(this.edgeContainer, 'touchend', this.onEdgeTouchEnd, {
|
||||
passive: true
|
||||
});
|
||||
dom.removeEventListener(this.edgeContainer, 'touchcancel', this.onEdgeTouchEnd, {
|
||||
passive: true
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
initialize() {
|
||||
const options = Object.assign({}, this.defaults, this.options || {});
|
||||
this.options = options;
|
||||
|
||||
if (browser.edge) {
|
||||
options.disableEdgeSwipe = true;
|
||||
}
|
||||
|
||||
this.initElements();
|
||||
|
||||
if (browser.touch) {
|
||||
dom.addEventListener(options.target, 'touchstart', this.onMenuTouchStart, {
|
||||
passive: true
|
||||
});
|
||||
dom.addEventListener(options.target, 'touchmove', this.onMenuTouchMove, {
|
||||
passive: true
|
||||
});
|
||||
dom.addEventListener(options.target, 'touchend', this.onMenuTouchEnd, {
|
||||
passive: true
|
||||
});
|
||||
dom.addEventListener(options.target, 'touchcancel', this.onMenuTouchEnd, {
|
||||
passive: true
|
||||
});
|
||||
dom.addEventListener(this.mask, 'touchstart', this.onBackgroundTouchStart, {
|
||||
passive: true
|
||||
});
|
||||
dom.addEventListener(this.mask, 'touchmove', this.onBackgroundTouchMove, {});
|
||||
dom.addEventListener(this.mask, 'touchend', this.onBackgroundTouchEnd, {
|
||||
passive: true
|
||||
});
|
||||
dom.addEventListener(this.mask, 'touchcancel', this.onBackgroundTouchEnd, {
|
||||
passive: true
|
||||
});
|
||||
}
|
||||
|
||||
this.clickMaskClose();
|
||||
}
|
||||
}
|
||||
|
||||
export default NavDrawer;
|
||||
|
52
src/lib/navdrawer/navdrawer.scss
Normal file
52
src/lib/navdrawer/navdrawer.scss
Normal file
|
@ -0,0 +1,52 @@
|
|||
.tmla-mask,
|
||||
.touch-menu-la {
|
||||
position: fixed;
|
||||
top: 0;
|
||||
bottom: 0;
|
||||
contain: strict;
|
||||
box-sizing: border-box;
|
||||
padding-left: env(safe-area-inset-left);
|
||||
}
|
||||
|
||||
.touch-menu-la {
|
||||
background-color: #fff;
|
||||
will-change: transform;
|
||||
display: flex;
|
||||
transition: transform ease-out 40ms, left ease-out 260ms;
|
||||
|
||||
[div="rtl"] & {
|
||||
transition: transform ease-out 40ms, right ease-out 260ms;
|
||||
}
|
||||
|
||||
z-index: 1099;
|
||||
}
|
||||
|
||||
.touch-menu-la.transition {
|
||||
transition: transform ease-out 240ms, left ease-out 260ms;
|
||||
|
||||
[div="rtl"] & {
|
||||
transition: transform ease-out 240ms, right ease-out 260ms;
|
||||
}
|
||||
}
|
||||
|
||||
.drawer-open {
|
||||
box-shadow: 2px 0 12px rgba(0, 0, 0, 0.4);
|
||||
}
|
||||
|
||||
.scrollContainer {
|
||||
flex-grow: 1;
|
||||
}
|
||||
|
||||
.tmla-mask {
|
||||
left: 0;
|
||||
right: 0;
|
||||
opacity: 0;
|
||||
z-index: 1098;
|
||||
transition: opacity ease-in-out 0.38s, visibility ease-in-out 0.38s;
|
||||
will-change: opacity;
|
||||
background-color: rgba(0, 0, 0, 0.3);
|
||||
}
|
||||
|
||||
.tmla-mask.backdrop {
|
||||
opacity: 1;
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue