Skip to content
This repository has been archived by the owner on Sep 1, 2023. It is now read-only.

Commit

Permalink
feat: Add optionally custom setSlide function
Browse files Browse the repository at this point in the history
closes #100
  • Loading branch information
mstruebing committed May 11, 2020
1 parent 0bb3e9f commit cd404e1
Show file tree
Hide file tree
Showing 2 changed files with 148 additions and 65 deletions.
107 changes: 84 additions & 23 deletions src/index.stories.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,11 @@ storiesOf("Slider", module)
<div style={{ width: "100vw", height: "100vh" }}>
<Slider hasBullets onSlideChange={onSlideChange}>
{images.map(image => (
<div key={image} draggable="false" style={imageStyle(image)} />
<div
key={image}
draggable="false"
style={imageStyle(image)}
/>
))}
</Slider>
</div>
Expand All @@ -37,7 +41,11 @@ storiesOf("Slider", module)
<div style={{ width: "500px", height: "500px" }}>
<Slider hasBullets>
{images.map(image => (
<div key={image} draggable="false" style={imageStyle(image)} />
<div
key={image}
draggable="false"
style={imageStyle(image)}
/>
))}
</Slider>
</div>
Expand All @@ -46,7 +54,11 @@ storiesOf("Slider", module)
<div style={{ width: "100vw", height: "100vh" }}>
<Slider hasBullets auto={2000}>
{images.map(image => (
<div key={image} draggable="false" style={imageStyle(image)} />
<div
key={image}
draggable="false"
style={imageStyle(image)}
/>
))}
</Slider>
</div>
Expand All @@ -55,7 +67,11 @@ storiesOf("Slider", module)
<div style={{ width: "100vw", height: "100vh" }}>
<Slider hasBullets activeIndex={2}>
{images.map(image => (
<div key={image} draggable="false" style={imageStyle(image)} />
<div
key={image}
draggable="false"
style={imageStyle(image)}
/>
))}
</Slider>
</div>
Expand All @@ -78,39 +94,59 @@ storiesOf("Slider", module)
<div style={{ width: "100vw", height: "100vh" }}>
<Slider hasBullets activeIndex={activeIndex}>
{images.map(image => (
<div key={image} draggable="false" style={imageStyle(image)} />
<div
key={image}
draggable="false"
style={imageStyle(image)}
/>
))}
</Slider>
</div>
);
})
.add("with activeIndex change at onSlideChange", () => {
.add("With custom setSlide function", () => {
const [activeIndex, setActiveIndex] = useState(0);
const manipulateActiveIndex = (index: number) => setActiveIndex(1);

const setSlideCustom = (slide: number) => 1

return (
<div style={{ width: "100vw", height: "100vh" }}>
<Slider hasBullets activeIndex={activeIndex} onSlideChange={manipulateActiveIndex}>
{images.map(image => (
<div key={image} draggable="false" style={imageStyle(image)} />
))}
</Slider>
</div>
)
<div style={{ width: "100vw", height: "100vh" }}>
<Slider
hasBullets
activeIndex={activeIndex}
setSlideCustom={setSlideCustom}
>
{images.map(image => (
<div
key={image}
draggable="false"
style={imageStyle(image)}
/>
))}
</Slider>
</div>
);
})
.add("With different `bulletStyle`", () => {
return (
<div style={{ width: "100vw", height: "100vh" }}>
<Slider hasBullets bulletStyle={{ backgroundColor: "#fff" }}>
{images.map(image => (
<div key={image} draggable="false" style={imageStyle(image)} />
<div
key={image}
draggable="false"
style={imageStyle(image)}
/>
))}
</Slider>
</div>
);
})
.add("With custom `bullets`", () => {
const BulletComponent: BulletComponentType = ({ onClick, isActive }) => (
const BulletComponent: BulletComponentType = ({
onClick,
isActive
}) => (
<li
style={{
width: "25px",
Expand All @@ -127,7 +163,11 @@ storiesOf("Slider", module)
<div style={{ width: "100vw", height: "100vh" }}>
<Slider hasBullets BulletComponent={BulletComponent}>
{images.map(image => (
<div key={image} draggable="false" style={imageStyle(image)} />
<div
key={image}
draggable="false"
style={imageStyle(image)}
/>
))}
</Slider>
</div>
Expand All @@ -138,7 +178,11 @@ storiesOf("Slider", module)
<div style={{ width: "100vw", height: "100vh" }}>
<Slider hasArrows>
{images.map(image => (
<div key={image} draggable="false" style={imageStyle(image)} />
<div
key={image}
draggable="false"
style={imageStyle(image)}
/>
))}
</Slider>
</div>
Expand All @@ -151,7 +195,11 @@ storiesOf("Slider", module)
<div style={{ width: "100vw", height: "100vh" }}>
<Slider hasArrows arrowStyle={arrowStyle}>
{images.map(image => (
<div key={image} draggable="false" style={imageStyle(image)} />
<div
key={image}
draggable="false"
style={imageStyle(image)}
/>
))}
</Slider>
</div>
Expand All @@ -177,7 +225,11 @@ storiesOf("Slider", module)
<div style={{ width: "100vw", height: "100vh" }}>
<Slider hasArrows ArrowComponent={ArrowComponent}>
{images.map(image => (
<div key={image} draggable="false" style={imageStyle(image)} />
<div
key={image}
draggable="false"
style={imageStyle(image)}
/>
))}
</Slider>
</div>
Expand All @@ -188,7 +240,11 @@ storiesOf("Slider", module)
<div style={{ width: "100vw", height: "100vh" }}>
<Slider hasArrows hasBullets>
{images.map(image => (
<div key={image} draggable="false" style={imageStyle(image)} />
<div
key={image}
draggable="false"
style={imageStyle(image)}
/>
))}
</Slider>
</div>
Expand All @@ -198,7 +254,12 @@ storiesOf("Slider", module)
<div style={{ width: "100vw", height: "100vh" }}>
<Slider hasBullets onSlideChange={onSlideChange}>
{images.map(image => (
<div key={image} draggable="false" style={imageStyle(image)} onClick={() => console.log("click")}/>
<div
key={image}
draggable="false"
style={imageStyle(image)}
onClick={() => console.log("click")}
/>
))}
</Slider>
</div>
Expand Down
106 changes: 64 additions & 42 deletions src/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,7 @@ interface SliderProps {
hasArrows?: boolean;
hasBullets?: boolean;
onSlideChange?: (slide: number) => void;
setSlideCustom?: (slide: number) => number;
}

const clamp = (input: number, lower: number, upper: number) =>
Expand All @@ -82,59 +83,78 @@ const Slider: React.FunctionComponent<SliderProps> = ({
children = [],
hasArrows = false,
hasBullets = false,
onSlideChange = () => undefined
onSlideChange = () => undefined,
setSlideCustom = undefined
}) => {
const sliderRef = useRef<HTMLDivElement>(null);
const [slide, setSlide] = useState(0);
const [slide, setSlideOriginal] = useState(0);
const setSlide = setSlideCustom
? (index: number) => setSlideOriginal(setSlideCustom(index))
: setSlideOriginal;
const [isDragging, setDragging] = useState(false);

// Initialize slides with spring
const [springProps, setSpringProps] = useSprings(children.length, index => ({
offset: index
}));
const [springProps, setSpringProps] = useSprings(
children.length,
index => ({
offset: index
})
);

// Bindings to set on the element
const gestureBinds = useGesture({
onDrag: ({
down,
movement: [xDelta],
direction: [xDir],
distance,
cancel,
first
const gestureBinds = useGesture(
{
onDrag: ({
down,
movement: [xDelta],
direction: [xDir],
distance,
cancel,
first
}) => {
if (first) {
setDragging(true);
}
if (sliderRef && sliderRef.current && sliderRef.current.parentElement) {
const {
width
} = sliderRef.current.parentElement.getBoundingClientRect();

if (down && distance > width / 2) {
if (cancel) cancel();
setSlide(clamp(slide + (xDir > 0 ? -1 : 1), 0, children.length - 1));
if (first) {
setDragging(true);
}
if (
sliderRef &&
sliderRef.current &&
sliderRef.current.parentElement
) {
const {
width
} = sliderRef.current.parentElement.getBoundingClientRect();

if (down && distance > width / 2) {
if (cancel) cancel();
setSlide(
clamp(
slide + (xDir > 0 ? -1 : 1),
0,
children.length - 1
)
);
}
// see: https://github.com/react-spring/react-spring/issues/861
// @ts-ignore
setSpringProps(index => ({
offset: (down ? xDelta : 0) / width + (index - slide)
}));
}
// see: https://github.com/react-spring/react-spring/issues/861
// @ts-ignore
setSpringProps(index => ({
offset: (down ? xDelta : 0) / width + (index - slide)
}));
},
onClick: () => {
if (isDragging) {
setDragging(false);
return;
}
clickOnSlide(slide);
}
},
onClick: () => {
if (isDragging) {
setDragging(false);
return;
{
drag: {
delay: 200
}
clickOnSlide(slide);
}
},
{
drag: {
delay: 200
}
});
);

// Triggered on slide change
useEffect(() => {
Expand Down Expand Up @@ -172,7 +192,8 @@ const Slider: React.FunctionComponent<SliderProps> = ({

// Calls onClick on the current slide
const clickOnSlide = (slideIndex: number) => {
childs[slideIndex].props.children.props.onClick && childs[slideIndex].props.children.props.onClick();
childs[slideIndex].props.children.props.onClick &&
childs[slideIndex].props.children.props.onClick();
};

const nextSlide = () => {
Expand Down Expand Up @@ -235,7 +256,8 @@ const Slider: React.FunctionComponent<SliderProps> = ({
className="slider__slide"
style={{
transform: offset.interpolate(
offsetX => `translate3d(${offsetX * 100}%, 0, 0)`
offsetX =>
`translate3d(${offsetX * 100}%, 0, 0)`
),
position: "absolute",
width: "100%",
Expand Down

0 comments on commit cd404e1

Please sign in to comment.