supercharged-slider
Version:
A super modular tiny slider library.
110 lines (79 loc) • 3.24 kB
text/typescript
import { Middleware } from '~/types';
import { getElements } from '~/utils/getElement';
// TODO: TOUCH HALA PROBLEMLİ, MOBİLDE!
const touch = (): Middleware => ({
name: 'touch',
callback: (slider) => {
slider.element.classList.add('s-slider-touchable');
const isVertical = () => slider.direction === 'vertical';
const isTargetValid = (e: MouseEvent) => e.composedPath().includes(slider.wrapper);
let isDragging = false;
let isSelectionDisabled = false;
let wrapperPositionBeforeDrag = 0;
let lastCursorPosition = 0;
let lastWrapperPosition = 0;
const onMouseMove = (e: MouseEvent) => {
const mousePosition = isVertical() ? e.clientY : e.clientX;
const scrollKey = isVertical() ? 'scrollHeight' : 'scrollWidth';
const clientKey = isVertical() ? 'clientHeight' : 'clientWidth';
if (lastCursorPosition === 0) {
lastCursorPosition = mousePosition;
return;
}
const threshold = slider.wrapper[scrollKey] - slider.element[clientKey];
const distance = (mousePosition - lastCursorPosition) * -1;
const newPosition = slider.wrapperPosition + distance;
lastCursorPosition = mousePosition;
lastWrapperPosition = Math.max(Math.min(newPosition, threshold), 0);
slider.scrollWrapperTo(lastWrapperPosition);
if (isSelectionDisabled) return;
slider.wrapper.style.pointerEvents = 'none';
slider.wrapper.style.transitionDuration = '0ms';
slider.slides.forEach((slide) => {
slide.style.pointerEvents = 'none';
});
isSelectionDisabled = true;
};
const onMouseDown = (e: MouseEvent) => {
if (!isTargetValid(e)) return;
isDragging = true;
wrapperPositionBeforeDrag = slider.wrapperPosition;
document.addEventListener('mousemove', onMouseMove);
};
const onMouseUp = () => {
if (!isDragging) return;
isSelectionDisabled = false;
const rectKey = isVertical() ? 'slideHeight' : 'slideWidth';
const newIndex = Math.round(lastWrapperPosition / (slider[rectKey] || 0));
if (slider.activeView !== newIndex) {
slider.slideTo(newIndex);
} else {
slider.scrollWrapperTo(wrapperPositionBeforeDrag);
}
lastCursorPosition = 0;
isDragging = false;
slider.wrapper.style.pointerEvents = 'all';
slider.slides.forEach((slide) => { slide.style.pointerEvents = 'all'; });
slider.wrapper.style.transitionDuration = '';
document.removeEventListener('mousemove', onMouseMove);
};
document.addEventListener('mousedown', onMouseDown);
document.addEventListener('mouseup', onMouseUp);
slider.slides.forEach((slide) => {
getElements(slide.querySelectorAll('img')).forEach((img) => {
img.setAttribute('draggable', 'false');
});
});
const onCleanUp = () => {
isDragging = false;
wrapperPositionBeforeDrag = 0;
lastCursorPosition = 0;
lastWrapperPosition = 0;
document.removeEventListener('mousedown', onMouseDown);
document.removeEventListener('mouseup', onMouseUp);
slider.removeCleanUpHook(onCleanUp);
};
slider.onCleanUp(onCleanUp);
},
});
export default touch;