UNPKG

@kiwicom/orbit-components

Version:

Orbit-components is a React component library which provides developers with the easiest possible way of building Kiwi.com’s products.

340 lines (339 loc) 13.9 kB
"use strict"; "use client"; var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault").default; var _interopRequireWildcard = require("@babel/runtime/helpers/interopRequireWildcard").default; exports.__esModule = true; exports.default = void 0; var React = _interopRequireWildcard(require("react")); var _styledComponents = _interopRequireWildcard(require("styled-components")); var _transition = _interopRequireDefault(require("../utils/transition")); var _Text = _interopRequireDefault(require("../Text")); var _Heading = _interopRequireDefault(require("../Heading")); var _Stack = _interopRequireDefault(require("../Stack")); var _Hide = _interopRequireDefault(require("../Hide")); var _Handle = _interopRequireDefault(require("./components/Handle")); var _Bar = _interopRequireDefault(require("./components/Bar")); var _keyMaps = _interopRequireDefault(require("../common/keyMaps")); var _consts = _interopRequireDefault(require("./consts")); var _Histogram = _interopRequireDefault(require("./components/Histogram")); var _defaultTheme = _interopRequireDefault(require("../defaultTheme")); var _mediaQuery = _interopRequireDefault(require("../utils/mediaQuery")); var _utils = require("./utils"); const StyledSlider = _styledComponents.default.div.withConfig({ displayName: "Slider__StyledSlider", componentId: "sc-a8zzil-0" })(["position:relative;"]); StyledSlider.defaultProps = { theme: _defaultTheme.default }; const StyledSliderContent = _styledComponents.default.div.withConfig({ displayName: "Slider__StyledSliderContent", componentId: "sc-a8zzil-1" })(["", ""], ({ theme, focused }) => (0, _styledComponents.css)(["display:block;width:100%;box-sizing:border-box;padding-bottom:", ";", ";"], theme.orbit.spaceXSmall, _mediaQuery.default.tablet((0, _styledComponents.css)(["width:calc(100% + 48px);position:absolute;bottom:-16px;left:-24px;right:-24px;opacity:0;visibility:hidden;padding:12px 24px 48px 24px;border-radius:", ";transition:", ";background:transparent;", ";"], theme.orbit.borderRadiusNormal, (0, _transition.default)(["all"], "fast", "ease-in-out"), focused && (0, _styledComponents.css)(["visibility:visible;opacity:1;background:", ";box-shadow:", ";"], theme.orbit.paletteWhite, theme.orbit.boxShadowRaised))))); StyledSliderContent.defaultProps = { theme: _defaultTheme.default }; const StyledSliderInput = _styledComponents.default.div.withConfig({ displayName: "Slider__StyledSliderInput", componentId: "sc-a8zzil-2" })(["display:flex;align-items:center;width:100%;height:24px;"]); const PureSlider = ({ defaultValue = _consts.default.VALUE, maxValue = _consts.default.MAX, minValue = _consts.default.MIN, step = _consts.default.STEP, theme, onChange, onChangeAfter, onChangeBefore, ariaValueText, ariaLabel, label, histogramData, histogramLoading, histogramDescription, histogramLoadingText, valueDescription, id, dataTest }) => { const bar = React.useRef(null); const [value, setValue] = React.useState(defaultValue); const valueRef = React.useRef(value); const defaultRef = React.useRef(defaultValue); const handleIndex = React.useRef(null); const [focused, setFocused] = React.useState(false); const { rtl } = theme; const updateValue = newValue => { valueRef.current = newValue; setValue(newValue); }; React.useEffect(() => { const newValue = Array.isArray(defaultValue) ? defaultValue.map(item => Number(item)) : Number(defaultValue); if ((0, _utils.isNotEqual)(defaultValue, defaultRef.current)) { defaultRef.current = newValue; updateValue(newValue); } }, [defaultValue]); const handleKeyDown = event => { if (event.ctrlKey || event.shiftKey || event.altKey) return; const eventCode = Number(event.code); if (eventCode === _keyMaps.default.ARROW_UP) { (0, _utils.pauseEvent)(event); if (onChange) { (0, _utils.injectCallbackAndSetState)(updateValue, onChange, (0, _utils.moveValueByExtraStep)(value, maxValue, minValue, step, handleIndex.current, step)); } } if (eventCode === _keyMaps.default.ARROW_DOWN) { (0, _utils.pauseEvent)(event); if (onChange) { (0, _utils.injectCallbackAndSetState)(updateValue, onChange, (0, _utils.moveValueByExtraStep)(value, maxValue, minValue, step, handleIndex.current, -step)); } } if (eventCode === _keyMaps.default.ARROW_RIGHT) { const switchStep = rtl ? -step : step; (0, _utils.pauseEvent)(event); if (onChange) { (0, _utils.injectCallbackAndSetState)(updateValue, onChange, (0, _utils.moveValueByExtraStep)(value, maxValue, minValue, step, handleIndex.current, switchStep)); } } if (eventCode === _keyMaps.default.ARROW_LEFT) { const switchStep = rtl ? step : -step; (0, _utils.pauseEvent)(event); if (onChange) { (0, _utils.injectCallbackAndSetState)(updateValue, onChange, (0, _utils.moveValueByExtraStep)(value, maxValue, minValue, step, handleIndex.current, switchStep)); } } if (eventCode === _keyMaps.default.HOME) { (0, _utils.pauseEvent)(event); if (onChange) { (0, _utils.injectCallbackAndSetState)(updateValue, onChange, (0, _utils.moveValueByExtraStep)(value, maxValue, minValue, step, handleIndex.current, 0, minValue)); } } if (eventCode === _keyMaps.default.END) { (0, _utils.pauseEvent)(event); if (onChange) { (0, _utils.injectCallbackAndSetState)(updateValue, onChange, (0, _utils.moveValueByExtraStep)(value, maxValue, minValue, step, handleIndex.current, 0, maxValue)); } } }; const handleBlur = () => { setFocused(false); window.removeEventListener("keydown", handleKeyDown); window.removeEventListener("focusout", handleBlur); if (onChangeAfter) { (0, _utils.injectCallbackAndSetState)(updateValue, onChangeAfter, value); } }; const handleOnFocus = i => event => { handleIndex.current = i; setFocused(true); (0, _utils.pauseEvent)(event); window.addEventListener("keydown", handleKeyDown); window.addEventListener("focusout", handleBlur); if (onChangeBefore) { (0, _utils.injectCallbackAndSetState)(updateValue, onChangeBefore, value); } }; const handleMove = newValue => { if (newValue != null) { if (Array.isArray(value)) { return (0, _utils.replaceValue)(valueRef.current, (0, _utils.alignValue)(maxValue, minValue, step, newValue), Number(handleIndex.current)); } return (0, _utils.alignValue)(maxValue, minValue, step, newValue); } return null; }; const handleBarMouseDown = event => { handleIndex.current = null; const newValue = (0, _utils.calculateValueFromPosition)({ histogramData, histogramLoading, maxValue, minValue, handleIndex: handleIndex.current, bar, rtl, value, pageX: event.pageX, throughClick: true }); if (newValue) { if (Array.isArray(value)) { const index = (0, _utils.findClosestKey)(newValue, value); const replacedValue = (0, _utils.replaceValue)(value, (0, _utils.alignValue)(maxValue, minValue, step, newValue), index || 0); if (onChangeBefore) (0, _utils.injectCallbackAndSetState)(updateValue, onChangeBefore, value); if (onChange) (0, _utils.injectCallbackAndSetState)(updateValue, onChange, replacedValue); if (onChangeAfter) (0, _utils.injectCallbackAndSetState)(updateValue, onChangeAfter, replacedValue); } else { const alignedValue = (0, _utils.alignValue)(maxValue, minValue, step, newValue); if (onChangeBefore) (0, _utils.injectCallbackAndSetState)(updateValue, onChangeBefore, value); if (onChange) (0, _utils.injectCallbackAndSetState)(updateValue, onChange, alignedValue); if (onChangeAfter) (0, _utils.injectCallbackAndSetState)(updateValue, onChangeAfter, alignedValue); } } }; const handleMouseMove = event => { const newValue = (0, _utils.calculateValueFromPosition)({ histogramData, histogramLoading, maxValue, minValue, handleIndex: handleIndex.current, bar, rtl, value, pageX: event.pageX }); (0, _utils.pauseEvent)(event); (0, _utils.injectCallbackAndSetState)(updateValue, onChange, handleMove(newValue)); }; const handleMouseUp = () => { setFocused(false); window.removeEventListener("mousemove", handleMouseMove); window.removeEventListener("mouseup", handleMouseUp); if (onChangeAfter) { (0, _utils.injectCallbackAndSetState)(updateValue, onChangeAfter, valueRef.current); } }; const handleMouseDown = i => event => { // just allow left-click if (event.button === 0 && event.buttons !== 2) { setFocused(true); handleIndex.current = i; window.addEventListener("mousemove", handleMouseMove); window.addEventListener("mouseup", handleMouseUp); (0, _utils.pauseEvent)(event); if (onChangeBefore) { (0, _utils.injectCallbackAndSetState)(updateValue, onChangeBefore, value); } } }; const handleOnTouchMove = event => { if (event.touches.length > 1) return; const newValue = (0, _utils.calculateValueFromPosition)({ histogramData, histogramLoading, maxValue, minValue, handleIndex: handleIndex.current, bar, rtl, value, pageX: event.touches[0]?.pageX || 0 }); (0, _utils.pauseEvent)(event); (0, _utils.injectCallbackAndSetState)(updateValue, onChange, handleMove(newValue)); }; const handleTouchEnd = () => { setFocused(false); window.removeEventListener("touchmove", handleOnTouchMove); window.removeEventListener("touchend", handleTouchEnd); if (onChangeAfter) { (0, _utils.injectCallbackAndSetState)(updateValue, onChangeAfter, valueRef.current); } }; const handleOnTouchStart = i => event => { if (event.touches.length <= 1) { setFocused(true); handleIndex.current = i; window.addEventListener("touchmove", handleOnTouchMove, { passive: false }); window.addEventListener("touchend", handleTouchEnd); (0, _utils.stopPropagation)(event); if (onChangeBefore) { (0, _utils.injectCallbackAndSetState)(updateValue, onChangeBefore, value); } } }; const renderHandle = i => { const key = i && encodeURIComponent(i.toString()); const index = i || 0; return /*#__PURE__*/React.createElement(_Handle.default, { tabIndex: "0", onTop: handleIndex.current === i, valueMax: maxValue, valueMin: minValue, onMouseDown: handleMouseDown(index), onFocus: handleOnFocus(index), onTouchStart: handleOnTouchStart(index), value: valueRef.current, ariaValueText: ariaValueText, ariaLabel: ariaLabel, hasHistogram: histogramLoading || !!histogramData, index: index, key: key, dataTest: `SliderHandle-${index}` }); }; const renderHandles = () => Array.isArray(value) ? value.map((_valueNow, index) => renderHandle(index)) : renderHandle(); const renderSliderTexts = React.useCallback(biggerSpace => { if (!(label || valueDescription || histogramDescription)) return null; return /*#__PURE__*/React.createElement(_Stack.default, { direction: "row", spacing: "none", spaceAfter: biggerSpace ? "medium" : "small" }, (label || histogramDescription) && /*#__PURE__*/React.createElement(_Stack.default, { direction: "column", spacing: "none", basis: "60%", grow: true }, label && /*#__PURE__*/React.createElement(_Heading.default, { type: "title4" }, label), valueDescription && /*#__PURE__*/React.createElement(_Text.default, { type: "secondary", size: "small" }, valueDescription)), histogramDescription && /*#__PURE__*/React.createElement(_Stack.default, { shrink: true, justify: "end", grow: false }, /*#__PURE__*/React.createElement(_Text.default, { type: "primary", size: "small" }, histogramDescription))); }, [histogramDescription, label, valueDescription]); if (histogramData) { const properHistogramLength = (maxValue - minValue + step) / step; if (histogramData.length !== properHistogramLength) { console.warn(`Warning: Length of histogramData array is ${histogramData.length}, but should be ${properHistogramLength}. This will cause broken visuals of the whole Histogram.`); } } const sortedValue = (0, _utils.sortArray)(valueRef.current); const hasHistogram = histogramLoading || !!histogramData; return /*#__PURE__*/React.createElement(StyledSlider, { "data-test": dataTest, id: id }, hasHistogram ? /*#__PURE__*/React.createElement(React.Fragment, null, /*#__PURE__*/React.createElement(_Hide.default, { on: ["smallMobile", "mediumMobile", "largeMobile"], block: true }, renderSliderTexts(true)), /*#__PURE__*/React.createElement(StyledSliderContent, { focused: focused }, renderSliderTexts(false), /*#__PURE__*/React.createElement(_Histogram.default, { data: histogramData, value: sortedValue, min: minValue, step: step, loading: histogramLoading, loadingText: histogramLoadingText }))) : renderSliderTexts(true), /*#__PURE__*/React.createElement(StyledSliderInput, null, /*#__PURE__*/React.createElement(_Bar.default, { ref: bar, onMouseDown: handleBarMouseDown, value: sortedValue, max: maxValue, min: minValue, hasHistogram: hasHistogram }), renderHandles())); }; PureSlider.defaultProps = { theme: _defaultTheme.default }; const ThemedSlider = (0, _styledComponents.withTheme)(PureSlider); ThemedSlider.displayName = "Slider"; var _default = ThemedSlider; exports.default = _default;