import React from 'react'; import { NonEmptyArray } from '../../fp/NonEmptyArray'; const KEYBOARD_KEY = { ArrowRight: 'ArrowRight', ArrowLeft: 'ArrowLeft', ArrowUp: 'ArrowUp', ArrowDown: 'ArrowDown', PageUp: 'PageUp', PageDown: 'PageDown', Escape: 'Escape', }; const preventKeyboardScrolling = (e: React.KeyboardEvent): void => { if ( [ KEYBOARD_KEY.ArrowLeft, KEYBOARD_KEY.ArrowRight, KEYBOARD_KEY.ArrowUp, KEYBOARD_KEY.ArrowDown, KEYBOARD_KEY.PageUp, KEYBOARD_KEY.PageDown, ].includes(e.key) ) { e.stopPropagation(); e.preventDefault(); } }; interface SlidingEventData { changedTouches?: NonEmptyArray<{ pageX: number; pageY: number }>; clientX: number; clientY: number; touches?: NonEmptyArray<{ pageX: number; pageY: number }>; type: string; } const getPointerPosition = ( event: Event | SlidingEventData ): { x: number; y: number } => { const e = event as SlidingEventData; const isTouchEvent = e.type === 'touchmove'; const isMouseEvent = e.type === 'mousemove' || e.type === 'mousedown'; let x = 0; let y = 0; if ( isTouchEvent === true && e.touches !== undefined && e.changedTouches !== undefined ) { const isTouches = e.touches[0] !== null && e.touches[0] !== undefined; const touch = isTouches ? e.touches[0] : e.changedTouches[0]; x = touch.pageX; y = touch.pageY; } else if (isMouseEvent === true) { x = e.clientX; y = e.clientY; } return { x, y }; }; const normalizeValue = (min: number, max: number, value: number): number => Math.min(Math.max(value, min), max); const getValueByMouseEvent = ( e: Event | SlidingEventData, railWidth: number, railOffsetLeft: number, min: number, max: number, step: number ): number => { const draggedWidth = getPointerPosition(e).x - railOffsetLeft; const draggedPercent = (draggedWidth / railWidth) * 100; const valueFromDraggedPercent = Math.round( min + Math.round((((max - min) / 100) * draggedPercent) / step) * step ); const result = normalizeValue(min, max, valueFromDraggedPercent); return result; }; const getValueByKeyboard = ( value: number, step: number, min: number, max: number, keyboardKey: string ): number => { if ( [ KEYBOARD_KEY.ArrowLeft, KEYBOARD_KEY.ArrowDown, KEYBOARD_KEY.PageDown, ].includes(keyboardKey) ) { return Math.max(value - step, min); } if ( [ KEYBOARD_KEY.ArrowRight, KEYBOARD_KEY.ArrowUp, KEYBOARD_KEY.PageUp, ].includes(keyboardKey) ) { return Math.min(value + step, max); } return value; }; const removeListener = (onMouseMove: EventListener) => { return (): void => { document.removeEventListener('mousemove', onMouseMove); document.removeEventListener('touchmove', onMouseMove); }; }; const addListener = ( onMouseMove: EventListener, onMouseUp: EventListener ): void => { document.addEventListener('mousemove', onMouseMove); document.addEventListener('touchmove', onMouseMove); document.addEventListener('mouseup', onMouseUp); document.addEventListener('touchend', onMouseUp); }; export interface SliderData { valueInNumber: number; valueInPercent: number; } interface SliderInput { max: number; min: number; value: number; } export const useSliderData = ({ min, max, value }: SliderInput): SliderData => { const valueInNumber = value === undefined ? (min + max) / 2 : normalizeValue(min, max, value); const valueInPercent = normalizeValue( 0, 100, ((valueInNumber - min) / (max - min)) * 100 ); return { valueInNumber, valueInPercent, }; }; export { preventKeyboardScrolling, getValueByMouseEvent, getValueByKeyboard, addListener, removeListener, };