@faceless-ui/slider
Version:
A React library for building every kind of slider
109 lines • 4.47 kB
JavaScript
var __rest = (this && this.__rest) || function (s, e) {
var t = {};
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)
t[p] = s[p];
if (s != null && typeof Object.getOwnPropertySymbols === "function")
for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {
if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i]))
t[p[i]] = s[p[i]];
}
return t;
};
import React, { useCallback, useEffect, useRef } from 'react';
import { useSlider } from '../useSlider/index.js';
import { getGhostSlideWidth } from './getGhostSlideWidth.js';
export const SliderTrack = (props) => {
const { htmlElement: Tag = 'div', children, style } = props, rest = __rest(props, ["htmlElement", "children", "style"]);
const sliderContext = useSlider();
const { sliderTrackRef, setScrollRatio, slideWidth, scrollable, scrollSnap, setIsPaused, pauseOnHover, alignLastSlide, isDragging, autoPlay, id: idFromContext, } = sliderContext;
const hasAddedScrollListener = useRef(false);
const animationFrameID = useRef(undefined);
const getScrollRatio = useCallback(() => {
const track = sliderTrackRef.current;
if (track) {
const newScrollRatio = track.scrollLeft / (track.scrollWidth - track.clientWidth);
setScrollRatio(newScrollRatio);
}
}, [
sliderTrackRef,
setScrollRatio,
]);
const onScroll = useCallback(() => {
const track = sliderTrackRef.current;
if (track) {
// prevent compounding events
if (animationFrameID.current)
cancelAnimationFrame(animationFrameID.current);
const requestID = requestAnimationFrame(getScrollRatio);
animationFrameID.current = requestID;
}
}, [
sliderTrackRef,
getScrollRatio,
]);
// NOTE: handle updates to the track's current scroll, which could originate from either the user or the program
useEffect(() => {
const track = sliderTrackRef.current;
if (track && hasAddedScrollListener.current === false) {
track.addEventListener('scroll', onScroll, false);
hasAddedScrollListener.current = true;
}
return () => {
hasAddedScrollListener.current = false;
if (track) {
track.removeEventListener('scroll', onScroll);
}
};
}, [
sliderTrackRef,
onScroll,
]);
// NOTE: if the user does not want scroll enabled, we need to remove the event listener without canceling programmatic scroll
useEffect(() => {
const track = sliderTrackRef.current;
if (track) {
if (!scrollable) {
track.addEventListener('wheel', (e) => { e.preventDefault(); });
}
}
return () => {
if (track) {
track.removeEventListener('scroll', onScroll);
}
};
}, [
scrollable,
onScroll,
sliderTrackRef
]);
const ghostSlideWidth = getGhostSlideWidth(sliderContext);
let scrollSnapType;
if (scrollSnap && slideWidth) {
scrollSnapType = !isDragging ? 'x mandatory' : 'none';
}
return (React.createElement(Tag, Object.assign({
// NOTE: the 'aria-controls' attribute of the toggler should match this ID
id: `slider-track_${idFromContext}`,
'aria-live': autoPlay ? "polite" : "off" }, rest, { style: Object.assign({ position: 'relative', display: 'flex', overflowX: 'scroll', WebkitOverflowScrolling: 'touch',
// NOTE: only apply after slide width has populated and while NOT dragging
scrollSnapType }, style),
ref: sliderTrackRef,
onMouseEnter: () => {
if (pauseOnHover)
setIsPaused(true);
// TODO: fire external methods from props, too
},
onMouseLeave: () => {
if (pauseOnHover)
setIsPaused(false);
// TODO: fire external methods from props, too
} }),
children && children,
alignLastSlide !== undefined && (React.createElement("div", { style: {
flexShrink: 0,
width: ghostSlideWidth,
pointerEvents: 'none'
} }, "\u00A0"))));
};
export default SliderTrack;
//# sourceMappingURL=index.js.map