@vnmfify/core
Version:
```shell npm i @vnmfify/core -S ```
291 lines (246 loc) • 10.2 kB
JavaScript
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