import styled from '@emotion/styled';
import type { CSSProperties, ReactElement } from 'react';
import { Children, useLayoutEffect, useRef, useState } from 'react';
import { FaAngleLeft } from 'react-icons/fa';
type Direction = 'right' | 'left';
interface ArrowProps {
direction: Direction;
onClick: () => void;
style?: CSSProperties;
}
const ArrowButton = styled.div<{
direction: Direction;
}>`
align-items: center;
background-color: #f7f7f7;
border: none;
border-radius: 50%;
cursor: pointer;
display: inline-flex;
height: 40px;
justify-content: center;
pointer-events: auto;
transition: transform ease-in 0.1s;
width: 40px;
:hover {
background-color: #607d8b !important;
color: white;
transform: scale(1.1);
}
img {
transform: translateX(
${(props) => (props.direction === 'left' ? '-2' : '2')}px
);
&:focus {
outline: 0;
}
}
`;
function Arrow({ direction, onClick, style = {} }: ArrowProps) {
return (
);
}
const Container = styled.div`
position: relative;
display: block;
height: 100%;
margin: 0 auto;
overflow: hidden;
width: 100%;
`;
const TransformController = styled.div<{
translation: number;
slidersWidth: number;
}>(
({ translation, slidersWidth }) => `
display: flex;
height: 100%;transform: translateX(-${translation}px);
transition: transform ease-out ${transition}s;
width: ${slidersWidth}px;
`,
);
const Content = styled.div<{ width: number }>`
flex: 1;
width: ${(props) => props.width}px;
`;
const transition = 0.45;
interface NextPrevProps {
children: ReactElement | ReactElement[];
index: number;
onChange: (element: number) => void;
style?: { arrowContainer?: CSSProperties };
}
export function NextPrev(props: NextPrevProps) {
const { children, index = 0, onChange = () => null, style = {} } = props;
const slidersCount = Children.count(children);
const lastIndex = slidersCount > 0 ? slidersCount - 1 : 0;
const activeIndex = Math.min(index, lastIndex);
const containerRef = useRef(null);
const [width, setWidth] = useState(0);
useLayoutEffect(() => {
const container = containerRef.current;
if (!container) return;
const observer = new ResizeObserver((entries) => {
for (const entry of entries) {
const newWidth = entry.contentRect.width;
if (newWidth > 0) {
setWidth(newWidth);
}
}
});
observer.observe(container);
const rect = container.getBoundingClientRect();
if (rect.width > 0) {
setWidth(rect.width);
}
return () => observer.disconnect();
}, []);
function nextHandler() {
if (index < lastIndex) {
onChange(index + 1);
}
}
function prevHandler() {
if (index > 0) {
onChange(index - 1);
}
}
if (!width && slidersCount === 0) return null;
const translation = width * activeIndex;
const slidersWidth = width * slidersCount;
return (
{Children.map(children, (child: ReactElement) => {
return (
{child}
);
})}
);
}
interface SliderControllersProps {
onNext: ArrowProps['onClick'];
onPrevious: ArrowProps['onClick'];
activeIndex: number;
lastIndex: number;
style?: CSSProperties;
}
function SliderControllers(props: SliderControllersProps) {
const { onNext, onPrevious, activeIndex, lastIndex, style } = props;
return (
);
}