UNPKG

@react-md/form

Version:

This package is for creating all the different form input types.

367 lines 14.3 kB
var __assign = (this && this.__assign) || function () { __assign = Object.assign || function(t) { for (var s, i = 1, n = arguments.length; i < n; i++) { s = arguments[i]; for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p)) t[p] = s[p]; } return t; }; return __assign.apply(this, arguments); }; var __rest = (this && this.__rest) || function (s, e) { var t = {}; for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0) t[p] = s[p]; if (s != null && typeof Object.getOwnPropertySymbols === "function") for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) { if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i])) t[p[i]] = s[p[i]]; } return t; }; var __read = (this && this.__read) || function (o, n) { var m = typeof Symbol === "function" && o[Symbol.iterator]; if (!m) return o; var i = m.call(o), r, ar = [], e; try { while ((n === void 0 || n-- > 0) && !(r = i.next()).done) ar.push(r.value); } catch (error) { e = { error: error }; } finally { try { if (r && !r.done && (m = i["return"])) m.call(i); } finally { if (e) throw e.error; } } return ar; }; import { useCallback, useEffect, useRef, useState } from "react"; import { applyRef, useDir, useIsomorphicLayoutEffect } from "@react-md/utils"; import { DEFAULT_SLIDER_ANIMATION_TIME } from "./constants"; import { getDragPercentage, getDragValue, isMouseEvent, isRangeSlider, isTouchEvent, } from "./utils"; var VALID_KEYS = [ "ArrowDown", "ArrowUp", "ArrowLeft", "ArrowRight", "Home", "End", "PageUp", "PageDown", ]; /** * This hook provides all the logic for updating the slider's when the user * interacts with the slider. * * @internal * @remarks \@since 2.5.0 */ export function useSliderControls(_a) { var _b, _c; var ref = _a.ref, propThumb1Ref = _a.thumb1Ref, propThumb2Ref = _a.thumb2Ref, min = _a.min, max = _a.max, step = _a.step, _d = _a.disabled, disabled = _d === void 0 ? false : _d, _e = _a.vertical, vertical = _e === void 0 ? false : _e, onBlur = _a.onBlur, onKeyDown = _a.onKeyDown, onMouseDown = _a.onMouseDown, onTouchStart = _a.onTouchStart, _f = _a.animationDuration, animationDuration = _f === void 0 ? DEFAULT_SLIDER_ANIMATION_TIME : _f, controls = __rest(_a, ["ref", "thumb1Ref", "thumb2Ref", "min", "max", "step", "disabled", "vertical", "onBlur", "onKeyDown", "onMouseDown", "onTouchStart", "animationDuration"]); var trackRef = useRef(null); var thumb1Ref = useRef(null); var thumb2Ref = useRef(null); var _g = __read(useState(false), 2), dragging = _g[0], setDragging = _g[1]; var _h = __read(useState(min), 2), dragValue = _h[0], setDragValue = _h[1]; var _j = __read(useState(null), 2), draggingBy = _j[0], setDraggingBy = _j[1]; var _k = __read(useState(null), 2), draggingIndex = _k[0], setDraggingIndex = _k[1]; var controlsRef = useRef(controls); useIsomorphicLayoutEffect(function () { controlsRef.current = controls; }); var dir = useDir().dir; var isRtl = dir === "rtl"; var thumb1Value; var thumb1Percentage; var thumb2Value; var thumb2Percentage; if (isRangeSlider(controls)) { _b = __read(controls.value, 2), thumb1Value = _b[0], thumb2Value = _b[1]; (_c = getDragPercentage({ min: min, max: max, thumb1Value: thumb1Value, thumb2Value: thumb2Value, dragging: dragging, dragValue: dragValue, draggingIndex: draggingIndex, }), thumb1Percentage = _c.thumb1Percentage, thumb2Percentage = _c.thumb2Percentage); } else { thumb1Value = controls.value; (thumb1Percentage = getDragPercentage({ min: min, max: max, thumb1Value: thumb1Value, dragging: dragging, dragValue: dragValue, draggingIndex: draggingIndex, }).thumb1Percentage); } /** * The main handler for updating the value of the slider. To help keep the * drag experience smooth, some values are stored in refs to prevent the * `useEffect` from being run during renders which adds and removes the move * event handlers */ var drag = useCallback(function (event) { var track = trackRef.current; var slider1 = thumb1Ref.current; var slider2 = thumb2Ref.current; var altKey = event.altKey, ctrlKey = event.ctrlKey, metaKey = event.metaKey, shiftKey = event.shiftKey; if (altKey || ctrlKey || metaKey || shiftKey || disabled || !track || !slider1 || (isMouseEvent(event) && event.button !== 0) || (isTouchEvent(event) && event.changedTouches.length !== 1) || (!isMouseEvent(event) && !isTouchEvent(event))) { return; } // prevent text from being highlighted on desktop or the page from // scrolling on mobile while dragging if (!isTouchEvent(event) || event.type === "touchmove") { event.preventDefault(); } event.stopPropagation(); // get the current mouse/touch position to help determine hwo far the // slider is being dragged var clientX; var clientY; if (isMouseEvent(event)) { (clientX = event.clientX, clientY = event.clientY); } else { var touch = event.changedTouches[0]; (clientX = touch.clientX, clientY = touch.clientY); } var index = 0; var slider = slider1; if (slider2) { // if we aren't dragging yet, try to find the slider closest to the // mouse/touch position and use that one if (draggingIndex === null) { var x1 = slider1.getBoundingClientRect().x; var x2 = slider2.getBoundingClientRect().x; var y1 = slider1.getBoundingClientRect().y; var y2 = slider2.getBoundingClientRect().y; if (vertical) { index = Math.abs(clientY - y1) < Math.abs(clientY - y2) ? 0 : 1; } else { index = Math.abs(clientX - x1) < Math.abs(clientX - x2) ? 0 : 1; } } else { index = draggingIndex; } slider = index === 0 ? slider1 : slider2; } // if we aren't dragging yet, want to focus the slider element to make it // easier to switch between mouse dragging and keyboard "dragging" if (draggingIndex !== index) { slider.focus(); setDraggingIndex(index); } setDraggingBy(isMouseEvent(event) ? "mouse" : "touch"); var _a = track.getBoundingClientRect(), left = _a.left, top = _a.top, height = _a.height, width = _a.width; var options = { min: min, max: max, step: step, vertical: vertical, clientX: clientX, clientY: clientY, left: left, top: top, height: height, width: width, isRtl: isRtl, minValue: min, maxValue: max, }; var controls = controlsRef.current; if (isRangeSlider(controls)) { var _b = __read(controls.value, 2), thumb1Value_1 = _b[0], thumb2Value_1 = _b[1]; var _c = getDragValue(__assign(__assign({}, options), { minValue: index === 0 ? min : thumb1Value_1 + step, maxValue: index === 1 ? max : thumb2Value_1 - step })), value = _c.value, current = _c.current; setDragValue(current); controls.setValue(index === 0 ? [value, thumb2Value_1] : [thumb1Value_1, value]); } else { var _d = getDragValue(options), value = _d.value, current = _d.current; setDragValue(current); controls.setValue(value); } }, [disabled, isRtl, draggingIndex, max, min, step, vertical]); var stop = useCallback(function () { controlsRef.current.persist(); setDragging(false); setDraggingIndex(null); setDraggingBy(null); }, []); useEffect(function () { if (draggingBy === null) { return; } if (draggingBy === "mouse") { window.addEventListener("mousemove", drag); window.addEventListener("mouseup", stop); } else { window.addEventListener("touchmove", drag, { passive: false }); window.addEventListener("touchend", stop); } return function () { if (draggingBy === "mouse") { window.removeEventListener("mousemove", drag); window.removeEventListener("mouseup", stop); } else { window.removeEventListener("touchmove", drag); window.removeEventListener("touchend", stop); } }; }, [draggingBy, drag, stop]); useEffect(function () { if (draggingIndex === null && draggingBy === null) { return; } // I don't know how to reach this flow.. so maybe can be removed? /* istanbul ignore if */ if (draggingIndex === null) { setDragging(false); return; } var timeout = window.setTimeout(function () { setDragging(true); }, animationDuration); return function () { window.clearTimeout(timeout); }; }, [draggingIndex, draggingBy, animationDuration]); var handleBlur = useCallback(function (event) { if (onBlur) { onBlur(event); } controlsRef.current.persist(); }, [onBlur]); /** * Note: this should be attached to the `SliderTrack` component. */ var handleMouseDown = useCallback(function (event) { if (onMouseDown) { onMouseDown(event); } // only call drag again when the dragging by isn't null since it can cause // the "drag" events to be re-started if the mouse appears over the slider // thumb again if (draggingBy === null) { drag(event); } }, [drag, draggingBy, onMouseDown]); /** * Note: this should be attached to the `SliderTrack` component. */ var handleTouchStart = useCallback(function (event) { if (onTouchStart) { onTouchStart(event); } // only call drag again when the dragging by isn't null since it can cause // the "drag" events to be re-started if the user's finger appears over // the slider thumb again if (draggingBy === null) { drag(event); } }, [drag, draggingBy, onTouchStart]); /** * Note: this should be attached to each `SliderThumb` component. */ var handleKeyDown = useCallback(function (event) { if (onKeyDown) { onKeyDown(event); } var key = event.key, altKey = event.altKey, ctrlKey = event.ctrlKey, metaKey = event.metaKey, shiftKey = event.shiftKey; if (altKey || ctrlKey || metaKey || shiftKey || disabled || !VALID_KEYS.includes(key)) { return; } var controls; if (isRangeSlider(controlsRef.current)) { var _a = controlsRef.current, increment_1 = _a.increment, incrementJump_1 = _a.incrementJump, decrement_1 = _a.decrement, decrementJump_1 = _a.decrementJump, minimum_1 = _a.minimum, maximum_1 = _a.maximum; var index = event.currentTarget === thumb2Ref.current ? 1 : 0; controls = { increment: increment_1.bind(null, index), incrementJump: incrementJump_1.bind(null, index), decrement: decrement_1.bind(null, index), decrementJump: decrementJump_1.bind(null, index), minimum: minimum_1.bind(null, index), maximum: maximum_1.bind(null, index), }; } else { controls = controlsRef.current; } var increment = controls.increment, incrementJump = controls.incrementJump, decrement = controls.decrement, decrementJump = controls.decrementJump, minimum = controls.minimum, maximum = controls.maximum; event.preventDefault(); event.stopPropagation(); switch (key) { case "ArrowUp": case "ArrowRight": increment(); break; case "ArrowDown": case "ArrowLeft": decrement(); break; case "Home": minimum(); break; case "End": maximum(); break; case "PageUp": incrementJump(); break; case "PageDown": decrementJump(); break; } }, [onKeyDown, disabled]); var trackRefHandler = useCallback(function (instance) { applyRef(instance, ref); trackRef.current = instance; }, [ref]); var thumb1RefHandler = useCallback(function (instance) { applyRef(instance, propThumb1Ref); thumb1Ref.current = instance; }, [propThumb1Ref]); var thumb2RefHandler = useCallback(function (instance) { applyRef(instance, propThumb2Ref); thumb2Ref.current = instance; }, [propThumb2Ref]); return { thumb1Ref: thumb1RefHandler, thumb1Value: thumb1Value, thumb1Percentage: thumb1Percentage, thumb2Ref: thumb2RefHandler, thumb2Value: thumb2Value, thumb2Percentage: thumb2Percentage, dragging: dragging, draggingIndex: draggingIndex, ref: trackRefHandler, onBlur: handleBlur, onKeyDown: handleKeyDown, onMouseDown: handleMouseDown, onTouchStart: handleTouchStart, }; } //# sourceMappingURL=useSliderControls.js.map