mirror of
https://github.com/streamich/react-use.git
synced 2026-01-18 14:06:52 +00:00
feat: 🎸 add [vertical] flag to useSlider() hook
This commit is contained in:
parent
1980d46199
commit
777865c3ac
@ -15,6 +15,7 @@ export interface Options {
|
||||
onScrubStop: () => void;
|
||||
reverse: boolean;
|
||||
styles: boolean | CSSProperties;
|
||||
vertical?: boolean;
|
||||
}
|
||||
|
||||
const noop = () => {};
|
||||
@ -59,13 +60,17 @@ const useSlider = (ref: RefObject<HTMLElement>, options: Partial<Options> = {}):
|
||||
startScrubbing();
|
||||
onMouseMove(event);
|
||||
};
|
||||
const onMouseMove = (event: MouseEvent) => onScrub(event.clientX);
|
||||
const onMouseMove = options.vertical
|
||||
? (event: MouseEvent) => onScrub(event.clientY)
|
||||
: (event: MouseEvent) => onScrub(event.clientX);
|
||||
|
||||
const onTouchStart = (event: TouchEvent) => {
|
||||
startScrubbing();
|
||||
onTouchMove(event);
|
||||
};
|
||||
const onTouchMove = (event: TouchEvent) => onScrub(event.changedTouches[0].clientX);
|
||||
const onTouchMove = options.vertical
|
||||
? (event: TouchEvent) => onScrub(event.changedTouches[0].clientY)
|
||||
: (event: TouchEvent) => onScrub(event.changedTouches[0].clientX);
|
||||
|
||||
const bindEvents = () => {
|
||||
on(document, 'mousemove', onMouseMove);
|
||||
@ -83,19 +88,21 @@ const useSlider = (ref: RefObject<HTMLElement>, options: Partial<Options> = {}):
|
||||
off(document, 'touchend', stopScrubbing);
|
||||
};
|
||||
|
||||
const onScrub = (clientX: number) => {
|
||||
const onScrub = (clientXY: number) => {
|
||||
cancelAnimationFrame(frame.current);
|
||||
|
||||
frame.current = requestAnimationFrame(() => {
|
||||
if (isMounted() && ref.current) {
|
||||
const { left: pos, width: length } = ref.current.getBoundingClientRect();
|
||||
const rect = ref.current.getBoundingClientRect();
|
||||
const pos = options.vertical ? rect.top : rect.left;
|
||||
const length = options.vertical ? rect.height : rect.width;
|
||||
|
||||
// Prevent returning 0 when element is hidden by CSS
|
||||
if (!length) {
|
||||
return;
|
||||
}
|
||||
|
||||
let value = (clientX - pos) / length;
|
||||
let value = (clientXY - pos) / length;
|
||||
|
||||
if (value > 1) {
|
||||
value = 1;
|
||||
@ -126,7 +133,7 @@ const useSlider = (ref: RefObject<HTMLElement>, options: Partial<Options> = {}):
|
||||
} else {
|
||||
return undefined;
|
||||
}
|
||||
}, [ref]);
|
||||
}, [ref, options.vertical]);
|
||||
|
||||
return state;
|
||||
};
|
||||
|
||||
@ -20,6 +20,24 @@ const Demo = () => {
|
||||
);
|
||||
};
|
||||
|
||||
const DemoVertical = () => {
|
||||
const ref = React.useRef(null);
|
||||
const state = useSlider(ref, { vertical: true });
|
||||
|
||||
return (
|
||||
<div>
|
||||
<div ref={ref} style={{ position: 'relative', background: 'yellow', padding: 4, width: 30, height: 400 }}>
|
||||
<p style={{ margin: 0, textAlign: 'center' }}>Slide me</p>
|
||||
<div style={{ position: 'absolute', left: 0, top: (100 * state.value) + '%', transform: 'scale(2)' }}>
|
||||
{state.isSliding ? '🏂' : '🎿'}
|
||||
</div>
|
||||
</div>
|
||||
<pre>{JSON.stringify(state, null, 2)}</pre>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
storiesOf('UI|useSlider', module)
|
||||
.add('Docs', () => <ShowDocs md={require('../docs/useSlider.md')} />)
|
||||
.add('Demo', () => <Demo />);
|
||||
.add('Horizontal', () => <Demo />)
|
||||
.add('Vertical', () => <DemoVertical />);
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user