Skip to content

Commit

Permalink
Merge pull request #9 from faceless-ui/fix/drag-snap
Browse files Browse the repository at this point in the history
Fix/drag snap
  • Loading branch information
jacobsfletch authored Sep 9, 2022
2 parents 6bceb82 + 2c02661 commit dc1bba6
Show file tree
Hide file tree
Showing 8 changed files with 53 additions and 26 deletions.
14 changes: 7 additions & 7 deletions demo/App.tsx
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import React from 'react';
import MarqueeSliderDemo from './MarqueeSliderDemo';
// import MarqueeSliderDemo from './MarqueeSliderDemo';
// import FreeScrollSliderDemo from './FreeScrollSliderDemo';
// import ThumbnailSliderDemo from './ThumbnailSliderDemo';
// import ScrollSnapSliderDemo from './ScrollSnapSliderDemo';
import ScrollSnapSliderDemo from './ScrollSnapSliderDemo';

const App: React.FC = () => (
<div
Expand All @@ -15,18 +15,18 @@ const App: React.FC = () => (
Free Scroll Slider:
</h1> */}
{/* <FreeScrollSliderDemo /> */}
{/* <h1>
<h1>
Scroll Snap Slider:
</h1> */}
{/* <ScrollSnapSliderDemo /> */}
</h1>
<ScrollSnapSliderDemo />
{/* <h1>
Thumbnail Slider Demo:
</h1>
<ThumbnailSliderDemo /> */}
<h1>
{/* <h1>
Marquee Slider Demo
</h1>
<MarqueeSliderDemo />
<MarqueeSliderDemo /> */}
</div>
);

Expand Down
4 changes: 2 additions & 2 deletions demo/ScrollSnapSliderDemo/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -28,8 +28,8 @@ const ScrollSnapSliderDemo: React.FC = () => {
</button>
<SliderProvider
slidesToShow={1}
autoPlay={autoPlay}
dragScroll
autoPlay
scrollSnap
>
<div
style={{
Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@faceless-ui/slider",
"version": "1.1.12",
"version": "1.1.13",
"main": "dist/index.js",
"types": "dist/index.d.ts",
"homepage:": "https://facelessui.com/docs/slider",
Expand Down
11 changes: 6 additions & 5 deletions src/Slide/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -26,12 +26,12 @@ const Slide: React.FC<SlideProps> = (props) => {
index,
htmlElement = 'div',
children,
style: styleFromProps,
style,
onClick: onClickFromProps,
...rest
} = props;

const [style, setStyle] = useState<React.CSSProperties | undefined>();
const [snapStyles, setSnapStyles] = useState<React.CSSProperties | undefined>();
const slider = useSlider();
const slideRef = useRef<HTMLElement | null>(null);

Expand Down Expand Up @@ -70,14 +70,15 @@ const Slide: React.FC<SlideProps> = (props) => {
index,
]);

// here
useEffect(() => {
if (scrollSnap) {
setStyle({
setSnapStyles({
scrollSnapStop: 'always',
scrollSnapAlign: 'start',
})
} else {
setStyle(undefined);
setSnapStyles(undefined);
}
}, [scrollSnap]);

Expand All @@ -101,7 +102,7 @@ const Slide: React.FC<SlideProps> = (props) => {
flexShrink: 0,
width: slideWidth,
...style || {},
...styleFromProps || {},
...snapStyles || {},
}

return (
Expand Down
1 change: 1 addition & 0 deletions src/SliderProvider/context.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ export interface ISliderContext extends Omit<SliderProviderProps, 'children'> {
slideWidth?: string
isPaused?: boolean
setIsPaused: (is: boolean) => void // eslint-disable-line no-unused-vars
isDragging: boolean
}

export const SliderContext = createContext<ISliderContext>({} as ISliderContext);
Expand Down
8 changes: 6 additions & 2 deletions src/SliderProvider/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,7 @@ const SliderProvider: React.FC<SliderProviderProps> = (props) => {
const [isPaused, setIsPaused] = useState(false);
const [isFullyScrolled, setIsFullyScrolled] = useState(false);
const sliderTrackRef = useRef<HTMLDivElement>(null);
const [isDragging, setIsDragging] = useState(false);

const [sliderState, dispatchSliderState] = useReducer(reducer, {
currentSlideIndex: slideIndexFromProps,
Expand All @@ -89,7 +90,9 @@ const SliderProvider: React.FC<SliderProviderProps> = (props) => {
useDragScroll({
ref: sliderTrackRef,
scrollYAxis: false,
enable: dragScroll || (scrollable && dragScroll !== false)
enable: dragScroll || (scrollable && dragScroll !== false),
onDrag: () => { setIsDragging(true) },
onDragEnd: () => { setIsDragging(false) },
});

useMarquee({
Expand Down Expand Up @@ -206,7 +209,8 @@ const SliderProvider: React.FC<SliderProviderProps> = (props) => {
setIsPaused,
isPaused,
pauseOnHover,
alignLastSlide
alignLastSlide,
isDragging
};

return (
Expand Down
27 changes: 20 additions & 7 deletions src/SliderProvider/useDragScroll.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@ type Args = {
scrollYAxis?: boolean
enable?: boolean
ref: React.MutableRefObject<HTMLDivElement | null>
onDrag: () => void
onDragEnd: () => void
}

export type UseDraggable = (args?: Args) => null // eslint-disable-line no-unused-vars
Expand All @@ -14,7 +16,9 @@ export const useDraggable: UseDraggable = (args) => {
buttons = [1, 4, 5], // See https://developer.mozilla.org/en-US/docs/Web/API/MouseEvent/buttons
scrollYAxis,
enable,
ref
ref,
onDrag,
onDragEnd
} = args || {};

// Position of the mouse on the page on mousedown
Expand All @@ -37,6 +41,9 @@ export const useDraggable: UseDraggable = (args) => {
setStartY(e.pageY - ref.current.offsetTop);
setStartScrollLeft(ref.current.scrollLeft);
setStartScrollTop(ref.current.scrollTop);
if (typeof onDrag === 'function') {
onDrag();
}
}
};

Expand All @@ -57,15 +64,16 @@ export const useDraggable: UseDraggable = (args) => {
}

e.preventDefault();

// Position of mouse on the page
const mouseX = e.pageX - ref.current.offsetLeft;
const mouseY = e.pageY - ref.current.offsetTop;
// Distance of the mouse from the origin of the last mousedown event
const walkX = mouseX - startX;
const walkY = mouseY - startY;
// Set element scroll
ref.current.scrollLeft = startScrollLeft - walkX;
const newScrollTop = startScrollTop - walkY;
const xDisplacement = mouseX - startX;
const yDisplacement = mouseY - startY;
// Finally, set the element's scroll
ref.current.scrollLeft = startScrollLeft - xDisplacement;
const newScrollTop = startScrollTop - yDisplacement;
if (scrollYAxis !== false) {
ref.current.scrollTop = newScrollTop;
}
Expand All @@ -80,6 +88,9 @@ export const useDraggable: UseDraggable = (args) => {
const childAsElement = child as HTMLElement;
childAsElement.style.removeProperty('pointer-events');
});
if (typeof onDragEnd === 'function') {
onDragEnd();
}
}
};

Expand All @@ -101,7 +112,9 @@ export const useDraggable: UseDraggable = (args) => {
startY,
scrollYAxis,
enable,
ref
ref,
onDragEnd,
onDrag
]);

return null;
Expand Down
12 changes: 10 additions & 2 deletions src/SliderTrack/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,8 @@ const SliderTrack: React.FC<SliderTrackProps> = (props) => {
scrollSnap,
setIsPaused,
pauseOnHover,
alignLastSlide
alignLastSlide,
isDragging
} = sliderContext;

const hasAddedScrollListener = useRef(false);
Expand Down Expand Up @@ -85,6 +86,7 @@ const SliderTrack: React.FC<SliderTrackProps> = (props) => {
track.addEventListener('wheel', (e) => { e.preventDefault() })
}
}

return () => {
if (track) {
track.removeEventListener('scroll', onScroll);
Expand All @@ -98,6 +100,11 @@ const SliderTrack: React.FC<SliderTrackProps> = (props) => {

const ghostSlideWidth = getGhostSlideWidth(sliderContext);

let scrollSnapType;
if (scrollSnap && slideWidth) {
scrollSnapType = !isDragging ? 'x mandatory' : 'none';
}

return (
<Tag
{...{
Expand All @@ -107,7 +114,8 @@ const SliderTrack: React.FC<SliderTrackProps> = (props) => {
display: 'flex',
overflowX: 'scroll', // NOTE: 'WebkitOverflowScrolling: touch' does not work when 'auto'
WebkitOverflowScrolling: 'touch',
scrollSnapType: (scrollSnap && slideWidth) ? 'x mandatory' : undefined, // NOTE: only apply after slide width has populated
// NOTE: only apply after slide width has populated and while NOT dragging
scrollSnapType,
...style,
},
ref: sliderTrackRef,
Expand Down

0 comments on commit dc1bba6

Please sign in to comment.