UNPKG

@vnmfify/core

Version:

```shell npm i @vnmfify/core -S ```

291 lines (246 loc) 10.2 kB
import _clamp from "lodash/clamp"; var _excluded = ["className", "style", "defaultValue", "value", "min", "max", "step", "range", "size", "orientation", "disabled", "children", "onClick", "onChange"]; function ownKeys(object, enumerableOnly) { var keys = Object.keys(object); if (Object.getOwnPropertySymbols) { var symbols = Object.getOwnPropertySymbols(object); if (enumerableOnly) { symbols = symbols.filter(function (sym) { return Object.getOwnPropertyDescriptor(object, sym).enumerable; }); } keys.push.apply(keys, symbols); } return keys; } function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i] != null ? arguments[i] : {}; if (i % 2) { ownKeys(Object(source), true).forEach(function (key) { _defineProperty(target, key, source[key]); }); } else if (Object.getOwnPropertyDescriptors) { Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)); } else { ownKeys(Object(source)).forEach(function (key) { Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key)); }); } } return target; } function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; } function _objectWithoutProperties(source, excluded) { if (source == null) return {}; var target = _objectWithoutPropertiesLoose(source, excluded); var key, i; if (Object.getOwnPropertySymbols) { var sourceSymbolKeys = Object.getOwnPropertySymbols(source); for (i = 0; i < sourceSymbolKeys.length; i++) { key = sourceSymbolKeys[i]; if (excluded.indexOf(key) >= 0) continue; if (!Object.prototype.propertyIsEnumerable.call(source, key)) continue; target[key] = source[key]; } } return target; } function _objectWithoutPropertiesLoose(source, excluded) { if (source == null) return {}; var target = {}; var sourceKeys = Object.keys(source); var key, i; for (i = 0; i < sourceKeys.length; i++) { key = sourceKeys[i]; if (excluded.indexOf(key) >= 0) continue; target[key] = source[key]; } return target; } import { useUncontrolled } from "@vnmfify/hooks"; import { View } from "@vnxjs/components"; import classNames from "classnames"; import * as React from "react"; import { Children, cloneElement, isValidElement, useCallback, useMemo, useRef } from "react"; import { prefixClassname } from "../styles"; import { getClientCoordinates, preventDefault, stopPropagation } from "../utils/dom/event"; import { getRect } from "../utils/dom/rect"; import { addNumber } from "../utils/format/number"; import { addUnitPx } from "../utils/format/unit"; import { useTouch } from "../utils/touch"; import SliderThumb from "./slider-thumb"; import SliderContext from "./slider.context"; var SliderDragStatus; (function (SliderDragStatus) { SliderDragStatus["Start"] = "start"; SliderDragStatus["Dragging"] = "dragging"; SliderDragStatus["End"] = "end"; })(SliderDragStatus || (SliderDragStatus = {})); function useSliderChildren(children, range) { return useMemo(() => { var _children__$thumb; var __children__ = { thumb1: undefined, thumb2: undefined }; Children.forEach(children, child => { if (! /*#__PURE__*/isValidElement(child)) { return; } var element = child; if (__children__.thumb1 === undefined) { __children__.thumb1 = element; } else if (__children__.thumb2 === undefined) { __children__.thumb2 = element; } }); __children__.thumb1 = (_children__$thumb = __children__.thumb1) !== null && _children__$thumb !== void 0 ? _children__$thumb : /*#__PURE__*/React.createElement(SliderThumb, null); if (range) { var _children__$thumb2; __children__.thumb1 = /*#__PURE__*/cloneElement(__children__.thumb1, { key: 0, index: 0 }); __children__.thumb2 = (_children__$thumb2 = __children__.thumb2) !== null && _children__$thumb2 !== void 0 ? _children__$thumb2 : /*#__PURE__*/React.createElement(SliderThumb, null); __children__.thumb2 = /*#__PURE__*/cloneElement(__children__.thumb2, { key: 1, index: 1 }); } else { __children__.thumb1 = /*#__PURE__*/cloneElement(__children__.thumb1, { index: undefined }); } return __children__; }, [children, range]); } function Slider(props) { var { className, style = {}, defaultValue, value: valueProp = undefined, min = 0, max = 100, step = 1, range = false, size, orientation = "horizontal", disabled = false, children, onClick, onChange: onChangeProp } = props, restProps = _objectWithoutProperties(props, _excluded); var { value = 0, setValue } = useUncontrolled({ defaultValue, value: valueProp, onChange: onChangeProp }); var { thumb1, thumb2 } = useSliderChildren(children, range); var vertical = orientation === "vertical"; var rootRef = useRef(); var dragStatusRef = useRef(); var startValueRef = useRef(0); var currentValueRef = useRef(0); var buttonIndexRef = useRef(); var touch = useTouch(); var scope = useMemo(() => Number(max) - Number(min), [max, min]); var isRange = useCallback(val => range && Array.isArray(val), [range]); var calcMainAxis = useCallback(() => { if (isRange(value)) { return "".concat((value[1] - value[0]) * 100 / scope, "%"); } return "".concat((value - Number(min)) * 100 / scope, "%"); }, [isRange, min, scope, value]); var calcOffset = useCallback(() => { if (isRange(value)) { return "".concat((value[0] - Number(min)) * 100 / scope, "%"); } return "0%"; }, [isRange, min, scope, value]); var wrapperStyle = useMemo(() => { var _addUnitPx; var crossAxis = vertical ? "width" : "height"; return _objectSpread(_objectSpread({}, style), {}, { [crossAxis]: (_addUnitPx = addUnitPx(size)) !== null && _addUnitPx !== void 0 ? _addUnitPx : "" }); }, [size, style, vertical]); var trackStyle = useMemo(() => { var mainAxis = vertical ? "height" : "width"; return { [mainAxis]: calcMainAxis(), left: vertical ? "" : calcOffset(), top: vertical ? calcOffset() : "", transition: dragStatusRef.current ? "none" : "" }; }, [calcMainAxis, calcOffset, vertical]); var formatValue = value => { value = _clamp(value, min, max); var diff = Math.round((value - min) / step) * step; return addNumber(min, diff); }; var isSameValue = (newValue, oldValue) => JSON.stringify(newValue) === JSON.stringify(oldValue); var handleOverlap = value => { if (value[0] > value[1]) { return value.slice(0).reverse(); } return value; }; var updateValue = newValue => { if (isRange(newValue)) { newValue = handleOverlap(newValue).map(formatValue); } else { newValue = formatValue(newValue); } if (!isSameValue(newValue, value)) { setValue(newValue); } }; var handleClick = event => { onClick === null || onClick === void 0 ? void 0 : onClick(event); stopPropagation(event); if (disabled) { return; } getRect(rootRef).then(rect => { var { clientX, clientY } = getClientCoordinates(event); var delta = vertical ? clientY - rect.top : clientX - rect.left; var total = vertical ? rect.height : rect.width; var newValue = Number(min) + delta / total * scope; if (isRange(value)) { var [left, right] = value; var middle = (left + right) / 2; if (newValue <= middle) { updateValue([newValue, right]); } else { updateValue([left, newValue]); } } else { updateValue(newValue); } }); }; var onTouchStart = (event, index) => { if (typeof index === "number") { buttonIndexRef.current = index; } if (disabled) { return; } touch.start(event); currentValueRef.current = value; if (isRange(currentValueRef.current)) { startValueRef.current = currentValueRef.current.map(formatValue); } else { startValueRef.current = formatValue(currentValueRef.current); } dragStatusRef.current = SliderDragStatus.Start; }; var onTouchMove = event => { if (disabled) { return; } preventDefault(event, true); touch.move(event); dragStatusRef.current = SliderDragStatus.Dragging; getRect(rootRef).then(rect => { var delta = vertical ? touch.deltaY : touch.deltaX; var total = vertical ? rect.height : rect.width; var diff = delta / total * scope; if (isRange(startValueRef.current)) { ; currentValueRef.current[buttonIndexRef.current] = startValueRef.current[buttonIndexRef.current] + diff; } else { currentValueRef.current = startValueRef.current + diff; } updateValue(currentValueRef.current); }); }; var onTouchEnd = () => { if (disabled) { return; } if (dragStatusRef.current === SliderDragStatus.Dragging) { updateValue(currentValueRef.current); } dragStatusRef.current = SliderDragStatus.End; }; return /*#__PURE__*/React.createElement(View, _objectSpread({ ref: rootRef, className: classNames(classNames(prefixClassname("slider"), { [prefixClassname("slider--vertical")]: vertical, [prefixClassname("slider--disabled")]: disabled }), className), style: wrapperStyle, onClick: handleClick }, restProps), /*#__PURE__*/React.createElement(SliderContext.Provider, { value: { onTouchStart, onTouchMove, onTouchEnd } }, /*#__PURE__*/React.createElement(View, { className: prefixClassname("slider__track"), style: trackStyle }, range ? [thumb1, thumb2] : thumb1))); } export default Slider; //# sourceMappingURL=slider.js.map