index.tsx 2.2 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394
  1. import React, {
  2. useEffect, useState, useRef, useCallback,
  3. } from 'react';
  4. import { fromEvent } from 'rxjs';
  5. import {
  6. throttleTime,
  7. } from 'rxjs/operators';
  8. import {
  9. Container, Wrapper, Rail, Track,
  10. } from './styled';
  11. type Props = {
  12. color?: 'primary' | 'secondary';
  13. max?: number;
  14. min?: number;
  15. defaultValue?: number;
  16. disabled?: boolean;
  17. onChange?: (value: number) => void;
  18. };
  19. const Sliders: React.FunctionComponent<Props> = ({
  20. defaultValue = 0,
  21. onChange,
  22. }: Props) => {
  23. const sliderRef = useRef<HTMLDivElement>(null);
  24. const [valueState, setValueState] = useState(defaultValue);
  25. const [isActive, setActive] = useState(false);
  26. let subscription: any = null;
  27. const parseValueToPercent = (value: number): number => Math.floor(value * 100);
  28. const getFingerMoveValue = (event: MouseEvent | React.MouseEvent<HTMLElement>): void => {
  29. const { current: slider } = sliderRef;
  30. if (slider) {
  31. const { width, left } = slider.getBoundingClientRect();
  32. const value = (event.clientX - left) / width;
  33. let percent = parseValueToPercent(value);
  34. if (percent <= 0) {
  35. percent = 0;
  36. } else if (percent >= 100) {
  37. percent = 100;
  38. }
  39. setValueState(percent);
  40. if (onChange) onChange(percent);
  41. }
  42. };
  43. const handleTouchMove = useCallback((event: any) => {
  44. event.preventDefault();
  45. getFingerMoveValue(event);
  46. }, []);
  47. const handleTouchEnd = useCallback((event: MouseEvent) => {
  48. event.preventDefault();
  49. setActive(false);
  50. subscription.unsubscribe();
  51. }, []);
  52. const handleMouseDown = useCallback((event: React.MouseEvent<HTMLElement>) => {
  53. event.preventDefault();
  54. getFingerMoveValue(event);
  55. setActive(true);
  56. subscription = fromEvent(document.body, 'mousemove').pipe(throttleTime(35)).subscribe(handleTouchMove);
  57. document.body.addEventListener('mouseup', handleTouchEnd);
  58. }, []);
  59. useEffect(() => {
  60. setValueState(defaultValue);
  61. }, []);
  62. return (
  63. <Container>
  64. <Wrapper
  65. ref={sliderRef}
  66. onMouseDown={handleMouseDown}
  67. >
  68. <Rail track={valueState} />
  69. <Track
  70. track={valueState}
  71. isActive={isActive}
  72. />
  73. </Wrapper>
  74. </Container>
  75. );
  76. };
  77. export default Sliders;