UNPKG

@vimeo/iris

Version:
220 lines (213 loc) 11.8 kB
'use strict'; Object.defineProperty(exports, '__esModule', { value: true }); var tslib_es6 = require('../../../tslib.es6-3ec409b7.js'); var React = require('react'); var components_inputs_Slider_Slider_state = require('./Slider.state.js'); var components_inputs_Slider_Slider_style = require('./Slider.style.js'); var components_inputs_Slider_Handle = require('./Handle.js'); var utils_events_KeyCodes = require('../../../utils/events/KeyCodes.js'); var components_inputs_Slider_SliderEditableInput = require('./SliderEditableInput.js'); var utils_hooks_useOutsideClick = require('../../../utils/hooks/useOutsideClick.js'); var utils_DOM_geometry = require('../../../utils/DOM/geometry.js'); require('styled-components'); require('polished'); require('./SliderInputArrow.js'); require('../../../color/colors.js'); require('../../../tokens/core.js'); require('../../../tokens/color/index.js'); require('../../../tokens/color/background/background.js'); require('../../../tokens/util/readToken.js'); require('../../../tokens/util/clamp.js'); require('../../../tokens/color/format/format.js'); require('../../../tokens/color/format/primary.js'); require('../../../tokens/color/format/secondary.js'); require('../../../tokens/color/format/tertiary.js'); require('../../../tokens/color/rainbow/rainbow.js'); require('../../../tokens/color/rainbow/conic/index.js'); require('../../../tokens/color/rainbow/conic/sm.js'); require('../../../tokens/color/rainbow/conic/xl.js'); require('../../../tokens/color/rainbow/linear/index.js'); require('../../../tokens/color/rainbow/linear/sm.js'); require('../../../tokens/color/rainbow/linear/xl.js'); require('../../../tokens/color/livestream/livestream.js'); require('../../../tokens/color/status/status.js'); require('../../../tokens/color/status/caution.js'); require('../../../tokens/color/status/negative.js'); require('../../../tokens/color/status/positive.js'); require('../../../tokens/color/stroke/stroke.js'); require('../../../tokens/color/surface/surface.js'); require('../../../tokens/color/text/text.js'); require('../../../tokens/util/round.js'); require('../../../tokens/color/upsell/upsell.js'); require('../../../tokens/color/upsell/sm.js'); require('../../../tokens/color/upsell/xl.js'); require('../../../tokens/color/upsell/new.js'); require('../../../tokens/edge/edge.js'); require('../../../tokens/space/space.js'); require('../../../tokens/typography/index.js'); require('../../../tokens/typography/size/size.js'); require('../../../utils/css.js'); function _interopDefaultLegacy (e) { return e && typeof e === 'object' && 'default' in e ? e : { 'default': e }; } var React__default = /*#__PURE__*/_interopDefaultLegacy(React); function Slider(_a) { var disabled = _a.disabled, editableLabel = _a.editableLabel, _b = _a.formatter, formatter = _b === void 0 ? function (value) { return value; } : _b, _c = _a.initialValues, initialValues = _c === void 0 ? [0, 100] : _c, _d = _a.max, max = _d === void 0 ? 100 : _d, _e = _a.min, min = _e === void 0 ? 0 : _e, onChange = _a.onChange, onDragEnd = _a.onDragEnd, range = _a.range, props = tslib_es6.__rest(_a, ["disabled", "editableLabel", "formatter", "initialValues", "max", "min", "onChange", "onDragEnd", "range"]); var isFirstRender = React.useRef(true); var trackRef = React.useRef(null); var startHandleRef = React.useRef(null); var endHandleRef = React.useRef(null); utils_hooks_useOutsideClick.useOutsideClick([trackRef], function () { setFocus(null); }); var _f = tslib_es6.__read(React.useReducer(components_inputs_Slider_Slider_state.reducer, components_inputs_Slider_Slider_state.initialState(initialValues)), 2), state = _f[0], dispatch = _f[1]; var values = state.values, trackRect = state.trackRect, focused = state.focused, dragging = state.dragging; var dispatchChangeEvent = React.useCallback(function (callback) { var _a; var currentInput = focused === 'startHandle' || focused === 'startInput' ? startHandleRef : endHandleRef; if (!currentInput.current) currentInput = startHandleRef; var event = new Event('change', { bubbles: true }); (_a = currentInput.current) === null || _a === void 0 ? void 0 : _a.dispatchEvent(event); callback && callback(event); }, [focused]); function setDragging(payload) { if (payload) setFocus(payload); return dispatch({ type: 'SET_DRAGGING', payload: payload }); } function setValue(payload) { return dispatch({ type: 'SET_VALUES', payload: payload }); } function setFocus(payload) { return dispatch({ type: 'SET_FOCUS', payload: payload }); } function setStartValue(value) { var newValue = constrain(min, range ? values[1] - 1 : max)(value); setValue([newValue, values[1]]); } function setEndValue(value) { var newValue = constrain(values[0] + 1, max)(value); setValue([values[0], newValue]); } function handleArrowClick(direction, handle) { var action = handle === 'startInput' ? setStartValue : setEndValue; var currentValue = handle === 'startInput' ? values[0] : values[1]; if (direction === 'up') action(currentValue + 1); else action(currentValue - 1); } React.useLayoutEffect(function () { var _a = utils_DOM_geometry.geometry(trackRef.current), left = _a.left, width = _a.width; dispatch({ type: 'SET_TRACK_RECT', payload: { left: left, width: width } }); }, [dragging]); React.useEffect(function () { if (!isFirstRender.current) { dispatchChangeEvent(onChange); } else { isFirstRender.current = false; } // dispatchChangeEvent is updated on focus change and we want this flow to fire only on values / onChange updates // eslint-disable-next-line react-hooks/exhaustive-deps }, [onChange, values]); React.useEffect(function () { var mouseup = function () { if (dragging) { setDragging(false); dispatchChangeEvent(onDragEnd); } }; var keydown = function (event) { if (!focused || !isHandleFocused(focused)) return; var action = focused === 'startHandle' ? setStartValue : setEndValue; var currentValue = focused === 'startHandle' ? values[0] : values[1]; switch (event.keyCode) { case utils_events_KeyCodes.arrowDown: case utils_events_KeyCodes.arrowLeft: action(currentValue - 1); break; case utils_events_KeyCodes.arrowUp: case utils_events_KeyCodes.arrowRight: action(currentValue + 1); break; case utils_events_KeyCodes.home: action(min); break; case utils_events_KeyCodes.end: action(max); break; } }; document && document.addEventListener('mouseup', mouseup); document && document.addEventListener('keydown', keydown); return function () { document && document.removeEventListener('mouseup', mouseup); document && document.removeEventListener('keydown', keydown); }; }); React.useEffect(function () { function mousemove(event) { if (dragging) { var pos = constrainedPosition(event, trackRect, min, max); if (dragging === 'startHandle') setStartValue(pos); if (dragging === 'endHandle') setEndValue(pos); } } document && document.addEventListener('mousemove', mousemove); return function () { return document && document.removeEventListener('mousemove', mousemove); }; }); return (React__default["default"].createElement(components_inputs_Slider_Slider_style.SliderContainer, tslib_es6.__assign({}, props, { range: range, "aria-label": "slider", role: "slider", "aria-valuemin": min, "aria-valuemax": max, "aria-valuenow": dragging === 'startHandle' ? values[0] : values[1] }), range && (React__default["default"].createElement(components_inputs_Slider_Slider_style.Label, { focused: focused === 'startInput' }, editableLabel ? (React__default["default"].createElement(components_inputs_Slider_SliderEditableInput.SliderEditableInput, { value: values[0], disabled: disabled, onFocus: function () { return setFocus('startInput'); }, onChange: function (e) { return !e.button && setStartValue(parseInt(e.target.value)); }, role: "start-input", onArrowUpClick: function () { return handleArrowClick('up', range ? 'endInput' : 'startInput'); }, onArrowDownClick: function () { return handleArrowClick('down', range ? 'endInput' : 'startInput'); } })) : (formatter(values[0])))), React__default["default"].createElement(Track, { ref: trackRef, values: values, id: "track-1", max: max, range: range, "aria-label": "track" }, React__default["default"].createElement(components_inputs_Slider_Handle.Handle, { disabled: disabled, handle: "startHandle", min: min, max: max, setFocus: setFocus, setDragging: setDragging, value: values[0], ref: startHandleRef }), range && (React__default["default"].createElement(components_inputs_Slider_Handle.Handle, { disabled: disabled, handle: "endHandle", min: min, max: max, setFocus: setFocus, setDragging: setDragging, value: values[1], ref: endHandleRef }))), React__default["default"].createElement(components_inputs_Slider_Slider_style.Label, { focused: focused === (range ? 'endInput' : 'startInput') }, editableLabel ? (React__default["default"].createElement(components_inputs_Slider_SliderEditableInput.SliderEditableInput, { disabled: disabled, value: range ? values[1] : values[0], onFocus: function () { return setFocus(range ? 'endInput' : 'startInput'); }, onChange: function (e) { range ? setEndValue(parseInt(e.target.value)) : setStartValue(parseInt(e.target.value)); }, role: range ? 'end-input' : 'start-input', onArrowUpClick: function () { return handleArrowClick('up', range ? 'endInput' : 'startInput'); }, onArrowDownClick: function () { return handleArrowClick('down', range ? 'endInput' : 'startInput'); } })) : (formatter(range ? values[1] : values[0]))))); } var Track = React.forwardRef(function (_a, ref) { var children = _a.children, values = _a.values, max = _a.max, range = _a.range, props = tslib_es6.__rest(_a, ["children", "values", "max", "range"]); return (React__default["default"].createElement(components_inputs_Slider_Slider_style.Background, tslib_es6.__assign({ ref: ref }, props), children, React__default["default"].createElement(components_inputs_Slider_Slider_style.ActiveRange, { values: values, max: max, range: range }))); }); function isHandleFocused(focusedElement) { return focusedElement.includes('Handle'); } function constrainedPosition(event, element, min, max) { var left = event.clientX - element.left; var pos = Math.round((left / element.width) * max); return constrain(min, max)(pos); } function constrain(min, max) { return function (val) { if (val > max) return max; if (val < min) return min; return val; }; } exports.Slider = Slider;