|
|
@ -7,8 +7,9 @@ import React, { |
|
|
|
} from 'react'; |
|
|
|
} from 'react'; |
|
|
|
import { Item, SlideDirection } from '../../types/carousel'; |
|
|
|
import { Item, SlideDirection } from '../../types/carousel'; |
|
|
|
import styles from '../../styles/slider/styles.module.css'; |
|
|
|
import styles from '../../styles/slider/styles.module.css'; |
|
|
|
|
|
|
|
import { getOuterWidth } from '../../helpers'; |
|
|
|
|
|
|
|
|
|
|
|
export const Slider: FunctionComponent<SliderProps> = ({ |
|
|
|
export const ScrollingCarousel: FunctionComponent<SliderProps> = ({ |
|
|
|
children, |
|
|
|
children, |
|
|
|
className, |
|
|
|
className, |
|
|
|
}: SliderProps) => { |
|
|
|
}: SliderProps) => { |
|
|
@ -31,11 +32,16 @@ export const Slider: FunctionComponent<SliderProps> = ({ |
|
|
|
}; |
|
|
|
}; |
|
|
|
const [showArrow, setShowArrow] = useState<Arrows>(showArrows()); |
|
|
|
const [showArrow, setShowArrow] = useState<Arrows>(showArrows()); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
const onScroll = (_: Event) => { |
|
|
|
|
|
|
|
setShowArrow(showArrows()); |
|
|
|
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
|
|
const ref = useCallback( |
|
|
|
const ref = useCallback( |
|
|
|
(node) => { |
|
|
|
(node) => { |
|
|
|
if (node !== null) { |
|
|
|
if (node !== null) { |
|
|
|
Object.defineProperty(slider, 'current', { value: node }); |
|
|
|
Object.defineProperty(slider, 'current', { value: node }); |
|
|
|
setShowArrow(showArrows()); |
|
|
|
setShowArrow(showArrows()); |
|
|
|
|
|
|
|
node.addEventListener('scroll', onScroll); |
|
|
|
} |
|
|
|
} |
|
|
|
}, |
|
|
|
}, |
|
|
|
[slider], |
|
|
|
[slider], |
|
|
@ -64,11 +70,36 @@ export const Slider: FunctionComponent<SliderProps> = ({ |
|
|
|
slider.current!.scrollLeft = position.scrollLeft - slide; |
|
|
|
slider.current!.scrollLeft = position.scrollLeft - slide; |
|
|
|
}; |
|
|
|
}; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
const calculateSlideAmount = (direction: SlideDirection): number => { |
|
|
|
|
|
|
|
const _slider = slider.current!; |
|
|
|
|
|
|
|
const currentView = |
|
|
|
|
|
|
|
direction === SlideDirection.Left |
|
|
|
|
|
|
|
? _slider.scrollLeft + _slider.offsetWidth |
|
|
|
|
|
|
|
: _slider.scrollLeft; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
const childNodes = Array.from(_slider.children) as HTMLElement[]; |
|
|
|
|
|
|
|
let nodeWidthSum = 0; |
|
|
|
|
|
|
|
for (const node of childNodes) { |
|
|
|
|
|
|
|
const nodeWidth = getOuterWidth(node); |
|
|
|
|
|
|
|
nodeWidthSum += nodeWidth; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (nodeWidthSum >= currentView) { |
|
|
|
|
|
|
|
const showingPart = |
|
|
|
|
|
|
|
direction === SlideDirection.Left |
|
|
|
|
|
|
|
? nodeWidthSum - currentView |
|
|
|
|
|
|
|
: nodeWidth; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
return (_slider.offsetWidth - showingPart) * direction; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
return _slider.offsetWidth; |
|
|
|
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
|
|
const slide = (direction: SlideDirection) => { |
|
|
|
const slide = (direction: SlideDirection) => { |
|
|
|
const slideAmount = -1 * direction * slider.current!.offsetWidth * 0.9; |
|
|
|
const slideAmount = calculateSlideAmount(direction); |
|
|
|
const start = slider.current!.scrollLeft; |
|
|
|
const start = slider.current!.scrollLeft; |
|
|
|
smoothHorizontalScroll(500, slideAmount, start); |
|
|
|
smoothHorizontalScroll(500, slideAmount, start); |
|
|
|
setShowArrow(showArrows()); |
|
|
|
|
|
|
|
}; |
|
|
|
}; |
|
|
|
|
|
|
|
|
|
|
|
const smoothHorizontalScroll = (time: number, amount: number, start: number) => { |
|
|
|
const smoothHorizontalScroll = (time: number, amount: number, start: number) => { |
|
|
@ -85,16 +116,19 @@ export const Slider: FunctionComponent<SliderProps> = ({ |
|
|
|
|
|
|
|
|
|
|
|
const smoothHorizontalScrollBehavior = (amount: number) => { |
|
|
|
const smoothHorizontalScrollBehavior = (amount: number) => { |
|
|
|
slider.current!.scrollLeft = amount; |
|
|
|
slider.current!.scrollLeft = amount; |
|
|
|
setShowArrow(showArrows()); |
|
|
|
|
|
|
|
}; |
|
|
|
}; |
|
|
|
|
|
|
|
|
|
|
|
return ( |
|
|
|
return ( |
|
|
|
<div className={`${styles.sliderBase} ${className}`}> |
|
|
|
<div className={`${styles.sliderBase} ${className}`}> |
|
|
|
{showArrow.left && ( |
|
|
|
{showArrow.left && ( |
|
|
|
<button onClick={() => slide(SlideDirection.Left)}>left</button> |
|
|
|
<div data-arrow="left"> |
|
|
|
|
|
|
|
<button onClick={() => slide(SlideDirection.Right)} /> |
|
|
|
|
|
|
|
</div> |
|
|
|
)} |
|
|
|
)} |
|
|
|
{showArrow.right && ( |
|
|
|
{showArrow.right && ( |
|
|
|
<button onClick={() => slide(SlideDirection.Right)}>right</button> |
|
|
|
<div data-arrow="right"> |
|
|
|
|
|
|
|
<button onClick={() => slide(SlideDirection.Left)} /> |
|
|
|
|
|
|
|
</div> |
|
|
|
)} |
|
|
|
)} |
|
|
|
<div |
|
|
|
<div |
|
|
|
ref={ref} |
|
|
|
ref={ref} |