@vimeo/iris
Version:
Vimeo Design System
220 lines (213 loc) • 11.8 kB
JavaScript
;
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;