Files
graff.training/src/components/Main/SliderControls.tsx
T
2024-09-11 16:43:26 +05:00

126 lines
3.7 KiB
TypeScript

import { forwardRef, useImperativeHandle, useRef } from 'react';
import { ArrowLeftIcon } from '../icons/ArrowLeftIcon';
import { ArrowRightIcon } from '../icons/ArrowRightIcon';
import { delay } from 'framer-motion';
export const SliderControls = forwardRef<
{ left: () => void; right: () => void },
{
slidesCount: number;
width: number;
height: number;
slide: number;
onLeftClick: () => void;
onRightClick: () => void;
className?: string;
}
>(
(
{
slidesCount,
height,
width,
slide = 0,
onLeftClick,
onRightClick,
className,
},
ref,
) => {
const length = 2 * Math.PI * (height / 2) + (width - height) * 2;
const prevBtnRef = useRef<HTMLButtonElement>(null);
const nextBtnRef = useRef<HTMLButtonElement>(null);
const rectRef = useRef<SVGRectElement>(null);
useImperativeHandle(ref, () => ({
left: () => prevBtnRef.current?.click(),
right: () => nextBtnRef.current?.click(),
}));
return (
<div className={'flex items-center gap-2 ' + className}>
<div className="relative flex justify-center max-sm:order-2">
<svg
width={width}
height={height}
viewBox={`0 0 ${width} ${height}`}
xmlns="http://www.w3.org/2000/svg"
className="bg-[#14161F] rounded-full fill-none"
>
<rect
x="1"
y="1"
width={width - 2}
height={height - 2}
rx={(height - 2) / 2}
stroke="#3D425C"
strokeLinecap="butt"
/>
<rect
className="transition-all duration-300"
ref={rectRef}
x="1"
y="1"
width={width - 2}
height={height - 2}
rx={(height - 2) / 2}
stroke="white"
strokeLinecap="butt"
strokeDasharray={`calc(${length}/${slidesCount}*${slide + 1}) ${length - (length / slidesCount) * (slide + 1)}`}
strokeDashoffset={`-${height / 2}`}
/>
</svg>
<p className="absolute self-center font-medium h4">
{Math.round(slide) + 1} из {slidesCount}
</p>
</div>
<button
ref={prevBtnRef}
onClick={() => {
if (slide === 0) {
rectRef.current!.classList.remove(
'transition-all',
'duration-300',
);
rectRef.current!.setAttribute('stroke-dasharray', `${length} 0`);
delay(() => {
rectRef.current!.classList.add(
'transition-all',
'duration-300',
);
}, 1);
}
onLeftClick();
}}
className="rounded-full sm:p-5 p-4 border border-[#3D425C] bg-[#14161F]"
>
<ArrowLeftIcon />
</button>
<button
onClick={() => {
if (slide + 1 === slidesCount) {
rectRef.current!.classList.remove(
'transition-all',
'duration-300',
);
rectRef.current!.setAttribute('stroke-dasharray', `0 ${length}`);
delay(() => {
rectRef.current!.classList.add(
'transition-all',
'duration-300',
);
}, 1);
}
onRightClick();
}}
ref={nextBtnRef}
className="rounded-full sm:p-5 p-4 border border-[#3D425C] bg-[#14161F] max-sm:order-2"
>
<ArrowRightIcon />
</button>
</div>
);
},
);