123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121 |
- import React, { useEffect, useState, useRef } from 'react';
- import { fromEvent, Subscription } from 'rxjs';
- import { throttleTime } from 'rxjs/operators';
- import { OuterWrapper, Wrapper, Rail, Track } from './styled';
- type Props = {
- color?: 'primary' | 'secondary';
- minimum?: number;
- maximum?: number;
- defaultValue?: number;
- value?: number;
- disabled?: boolean;
- onChange?: (value: number) => void;
- };
- const Sliders: React.FC<Props> = ({
- defaultValue = 0,
- value = 0,
- onChange,
- // minimum = 0,
- maximum = 100,
- }: Props) => {
- const sliderRef = useRef<HTMLDivElement>(null);
- const [valueState, setValueState] = useState(defaultValue);
- const [isActive, setActive] = useState(false);
- let mouseSubscription: Subscription | null = null;
- let touchSubscription: Subscription | null = null;
- const parseValueToPercent = (val: number): number => Math.floor(val * 100);
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
- const getFingerMoveValue = (event: any): void => {
- const { current: slider } = sliderRef;
- let clientX = 0;
- if (event.touches) {
- const touches = event.touches[0];
- ({ clientX } = touches);
- } else {
- ({ clientX } = event);
- }
- if (slider) {
- const { width, left } = slider.getBoundingClientRect();
- const moveDistance = clientX - left;
- const moveRate = moveDistance / width;
- let percent = parseValueToPercent(moveRate);
- if (percent <= 0) {
- percent = 0;
- } else if (percent >= 100) {
- percent = 100;
- }
- if (onChange) {
- const val = Math.floor(percent * (maximum * 0.01));
- onChange(val);
- }
- }
- };
- const handleTouchMove = (event: Event): void => {
- event.preventDefault();
- getFingerMoveValue(event);
- };
- const handleTouchEnd = (event: MouseEvent): void => {
- event.preventDefault();
- setActive(false);
- if (mouseSubscription) mouseSubscription.unsubscribe();
- if (touchSubscription) touchSubscription.unsubscribe();
- };
- const handleMouseDown = (
- event: React.MouseEvent<HTMLElement> | React.TouchEvent<HTMLElement>,
- ): void => {
- event.preventDefault();
- getFingerMoveValue(event);
- setActive(true);
- mouseSubscription = fromEvent(document.body, 'mousemove')
- .pipe(throttleTime(35))
- .subscribe(handleTouchMove);
- touchSubscription = fromEvent(document.body, 'touchmove')
- .pipe(throttleTime(35))
- .subscribe(handleTouchMove);
- document.body.addEventListener('mouseup', handleTouchEnd);
- };
- const setPercent = (): void => {
- const percent = parseValueToPercent((defaultValue || value) / maximum);
- setValueState(percent);
- };
- useEffect(() => {
- setPercent();
- }, []);
- useEffect(() => {
- setPercent();
- }, [value]);
- return (
- <OuterWrapper>
- <Wrapper
- ref={sliderRef}
- data-testid="sliders"
- onMouseDown={handleMouseDown}
- onTouchStart={handleMouseDown}
- >
- <Rail track={valueState} />
- <Track data-testid="track" track={valueState} isActive={isActive} />
- </Wrapper>
- </OuterWrapper>
- );
- };
- export default Sliders;
|