@aplus-frontend/antdv
Version:
Vue basic component library maintained based on ant-design-vue
594 lines (593 loc) • 18.6 kB
JavaScript
"use strict";
var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.default = void 0;
var _vue = require("vue");
var _extends2 = _interopRequireDefault(require("@babel/runtime/helpers/extends"));
var _classNames = _interopRequireDefault(require("../../_util/classNames"));
var _vueTypes = _interopRequireWildcard(require("../../_util/vue-types"));
var _BaseMixin = _interopRequireDefault(require("../../_util/BaseMixin"));
var _propsUtil = require("../../_util/props-util");
var _Track = _interopRequireDefault(require("./common/Track"));
var _createSlider = _interopRequireDefault(require("./common/createSlider"));
var utils = _interopRequireWildcard(require("./utils"));
var _initDefaultProps = _interopRequireDefault(require("../../_util/props-util/initDefaultProps"));
function _getRequireWildcardCache(e) { if ("function" != typeof WeakMap) return null; var r = new WeakMap(), t = new WeakMap(); return (_getRequireWildcardCache = function (e) { return e ? t : r; })(e); }
function _interopRequireWildcard(e, r) { if (!r && e && e.__esModule) return e; if (null === e || "object" != typeof e && "function" != typeof e) return { default: e }; var t = _getRequireWildcardCache(r); if (t && t.has(e)) return t.get(e); var n = { __proto__: null }, a = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var u in e) if ("default" !== u && {}.hasOwnProperty.call(e, u)) { var i = a ? Object.getOwnPropertyDescriptor(e, u) : null; i && (i.get || i.set) ? Object.defineProperty(n, u, i) : n[u] = e[u]; } return n.default = e, t && t.set(e, n), n; }
const trimAlignValue = _ref => {
let {
value,
handle,
bounds,
props
} = _ref;
const {
allowCross,
pushable
} = props;
const thershold = Number(pushable);
const valInRange = utils.ensureValueInRange(value, props);
let valNotConflict = valInRange;
if (!allowCross && handle != null && bounds !== undefined) {
if (handle > 0 && valInRange <= bounds[handle - 1] + thershold) {
valNotConflict = bounds[handle - 1] + thershold;
}
if (handle < bounds.length - 1 && valInRange >= bounds[handle + 1] - thershold) {
valNotConflict = bounds[handle + 1] - thershold;
}
}
return utils.ensureValuePrecision(valNotConflict, props);
};
const rangeProps = {
defaultValue: _vueTypes.default.arrayOf(_vueTypes.default.number),
value: _vueTypes.default.arrayOf(_vueTypes.default.number),
count: Number,
pushable: (0, _vueTypes.withUndefined)(_vueTypes.default.oneOfType([_vueTypes.default.looseBool, _vueTypes.default.number])),
allowCross: {
type: Boolean,
default: undefined
},
disabled: {
type: Boolean,
default: undefined
},
reverse: {
type: Boolean,
default: undefined
},
tabindex: _vueTypes.default.arrayOf(_vueTypes.default.number),
prefixCls: String,
min: Number,
max: Number,
autofocus: {
type: Boolean,
default: undefined
},
ariaLabelGroupForHandles: Array,
ariaLabelledByGroupForHandles: Array,
ariaValueTextFormatterGroupForHandles: Array,
draggableTrack: {
type: Boolean,
default: undefined
}
};
const Range = (0, _vue.defineComponent)({
compatConfig: {
MODE: 3
},
name: 'Range',
mixins: [_BaseMixin.default],
inheritAttrs: false,
props: (0, _initDefaultProps.default)(rangeProps, {
count: 1,
allowCross: true,
pushable: false,
tabindex: [],
draggableTrack: false,
ariaLabelGroupForHandles: [],
ariaLabelledByGroupForHandles: [],
ariaValueTextFormatterGroupForHandles: []
}),
emits: ['beforeChange', 'afterChange', 'change'],
displayName: 'Range',
data() {
const {
count,
min,
max
} = this;
const initialValue = Array(...Array(count + 1)).map(() => min);
const defaultValue = (0, _propsUtil.hasProp)(this, 'defaultValue') ? this.defaultValue : initialValue;
let {
value
} = this;
if (value === undefined) {
value = defaultValue;
}
const bounds = value.map((v, i) => trimAlignValue({
value: v,
handle: i,
props: this.$props
}));
const recent = bounds[0] === max ? 0 : bounds.length - 1;
return {
sHandle: null,
recent,
bounds
};
},
watch: {
value: {
handler(val) {
const {
bounds
} = this;
this.setChangeValue(val || bounds);
},
deep: true
},
min() {
const {
value
} = this;
this.setChangeValue(value || this.bounds);
},
max() {
const {
value
} = this;
this.setChangeValue(value || this.bounds);
}
},
methods: {
setChangeValue(value) {
const {
bounds
} = this;
let nextBounds = value.map((v, i) => trimAlignValue({
value: v,
handle: i,
bounds,
props: this.$props
}));
if (bounds.length === nextBounds.length) {
if (nextBounds.every((v, i) => v === bounds[i])) {
return null;
}
} else {
nextBounds = value.map((v, i) => trimAlignValue({
value: v,
handle: i,
props: this.$props
}));
}
this.setState({
bounds: nextBounds
});
if (value.some(v => utils.isValueOutOfRange(v, this.$props))) {
const newValues = value.map(v => {
return utils.ensureValueInRange(v, this.$props);
});
this.$emit('change', newValues);
}
},
onChange(state) {
const isNotControlled = !(0, _propsUtil.hasProp)(this, 'value');
if (isNotControlled) {
this.setState(state);
} else {
const controlledState = {};
['sHandle', 'recent'].forEach(item => {
if (state[item] !== undefined) {
controlledState[item] = state[item];
}
});
if (Object.keys(controlledState).length) {
this.setState(controlledState);
}
}
const data = (0, _extends2.default)((0, _extends2.default)({}, this.$data), state);
const changedValue = data.bounds;
this.$emit('change', changedValue);
},
positionGetValue(position) {
const bounds = this.getValue();
const value = this.calcValueByPos(position);
const closestBound = this.getClosestBound(value);
const index = this.getBoundNeedMoving(value, closestBound);
const prevValue = bounds[index];
if (value === prevValue) return null;
const nextBounds = [...bounds];
nextBounds[index] = value;
return nextBounds;
},
onStart(position) {
const {
bounds
} = this;
this.$emit('beforeChange', bounds);
const value = this.calcValueByPos(position);
this.startValue = value;
this.startPosition = position;
const closestBound = this.getClosestBound(value);
this.prevMovedHandleIndex = this.getBoundNeedMoving(value, closestBound);
this.setState({
sHandle: this.prevMovedHandleIndex,
recent: this.prevMovedHandleIndex
});
const prevValue = bounds[this.prevMovedHandleIndex];
if (value === prevValue) return;
const nextBounds = [...bounds];
nextBounds[this.prevMovedHandleIndex] = value;
this.onChange({
bounds: nextBounds
});
},
onEnd(force) {
const {
sHandle
} = this;
this.removeDocumentEvents();
if (!sHandle) {
this.dragTrack = false;
}
if (sHandle !== null || force) {
this.$emit('afterChange', this.bounds);
}
this.setState({
sHandle: null
});
},
onMove(e, position, dragTrack, startBounds) {
utils.pauseEvent(e);
const {
$data: state,
$props: props
} = this;
const maxValue = props.max || 100;
const minValue = props.min || 0;
if (dragTrack) {
let pos = props.vertical ? -position : position;
pos = props.reverse ? -pos : pos;
const max = maxValue - Math.max(...startBounds);
const min = minValue - Math.min(...startBounds);
const ratio = Math.min(Math.max(pos / (this.getSliderLength() / 100), min), max);
const nextBounds = startBounds.map(v => Math.floor(Math.max(Math.min(v + ratio, maxValue), minValue)));
if (state.bounds.map((c, i) => c === nextBounds[i]).some(c => !c)) {
this.onChange({
bounds: nextBounds
});
}
return;
}
const {
bounds,
sHandle
} = this;
const value = this.calcValueByPos(position);
const oldValue = bounds[sHandle];
if (value === oldValue) return;
this.moveTo(value);
},
onKeyboard(e) {
const {
reverse,
vertical
} = this.$props;
const valueMutator = utils.getKeyboardValueMutator(e, vertical, reverse);
if (valueMutator) {
utils.pauseEvent(e);
const {
bounds,
sHandle
} = this;
const oldValue = bounds[sHandle === null ? this.recent : sHandle];
const mutatedValue = valueMutator(oldValue, this.$props);
const value = trimAlignValue({
value: mutatedValue,
handle: sHandle,
bounds,
props: this.$props
});
if (value === oldValue) return;
const isFromKeyboardEvent = true;
this.moveTo(value, isFromKeyboardEvent);
}
},
getClosestBound(value) {
const {
bounds
} = this;
let closestBound = 0;
for (let i = 1; i < bounds.length - 1; i += 1) {
if (value >= bounds[i]) {
closestBound = i;
}
}
if (Math.abs(bounds[closestBound + 1] - value) < Math.abs(bounds[closestBound] - value)) {
closestBound += 1;
}
return closestBound;
},
getBoundNeedMoving(value, closestBound) {
const {
bounds,
recent
} = this;
let boundNeedMoving = closestBound;
const isAtTheSamePoint = bounds[closestBound + 1] === bounds[closestBound];
if (isAtTheSamePoint && bounds[recent] === bounds[closestBound]) {
boundNeedMoving = recent;
}
if (isAtTheSamePoint && value !== bounds[closestBound + 1]) {
boundNeedMoving = value < bounds[closestBound + 1] ? closestBound : closestBound + 1;
}
return boundNeedMoving;
},
getLowerBound() {
return this.bounds[0];
},
getUpperBound() {
const {
bounds
} = this;
return bounds[bounds.length - 1];
},
/**
* Returns an array of possible slider points, taking into account both
* `marks` and `step`. The result is cached.
*/
getPoints() {
const {
marks,
step,
min,
max
} = this;
const cache = this.internalPointsCache;
if (!cache || cache.marks !== marks || cache.step !== step) {
const pointsObject = (0, _extends2.default)({}, marks);
if (step !== null) {
for (let point = min; point <= max; point += step) {
pointsObject[point] = point;
}
}
const points = Object.keys(pointsObject).map(parseFloat);
points.sort((a, b) => a - b);
this.internalPointsCache = {
marks,
step,
points
};
}
return this.internalPointsCache.points;
},
moveTo(value, isFromKeyboardEvent) {
const nextBounds = [...this.bounds];
const {
sHandle,
recent
} = this;
const handle = sHandle === null ? recent : sHandle;
nextBounds[handle] = value;
let nextHandle = handle;
if (this.$props.pushable !== false) {
this.pushSurroundingHandles(nextBounds, nextHandle);
} else if (this.$props.allowCross) {
nextBounds.sort((a, b) => a - b);
nextHandle = nextBounds.indexOf(value);
}
this.onChange({
recent: nextHandle,
sHandle: nextHandle,
bounds: nextBounds
});
if (isFromKeyboardEvent) {
// known problem: because setState is async,
// so trigger focus will invoke handler's onEnd and another handler's onStart too early,
// cause onBeforeChange and onAfterChange receive wrong value.
// here use setState callback to hack,but not elegant
this.$emit('afterChange', nextBounds);
this.setState({}, () => {
this.handlesRefs[nextHandle].focus();
});
this.onEnd();
}
},
pushSurroundingHandles(bounds, handle) {
const value = bounds[handle];
const {
pushable
} = this;
const threshold = Number(pushable);
let direction = 0;
if (bounds[handle + 1] - value < threshold) {
direction = +1; // push to right
}
if (value - bounds[handle - 1] < threshold) {
direction = -1; // push to left
}
if (direction === 0) {
return;
}
const nextHandle = handle + direction;
const diffToNext = direction * (bounds[nextHandle] - value);
if (!this.pushHandle(bounds, nextHandle, direction, threshold - diffToNext)) {
// revert to original value if pushing is impossible
bounds[handle] = bounds[nextHandle] - direction * threshold;
}
},
pushHandle(bounds, handle, direction, amount) {
const originalValue = bounds[handle];
let currentValue = bounds[handle];
while (direction * (currentValue - originalValue) < amount) {
if (!this.pushHandleOnePoint(bounds, handle, direction)) {
// can't push handle enough to create the needed `amount` gap, so we
// revert its position to the original value
bounds[handle] = originalValue;
return false;
}
currentValue = bounds[handle];
}
// the handle was pushed enough to create the needed `amount` gap
return true;
},
pushHandleOnePoint(bounds, handle, direction) {
const points = this.getPoints();
const pointIndex = points.indexOf(bounds[handle]);
const nextPointIndex = pointIndex + direction;
if (nextPointIndex >= points.length || nextPointIndex < 0) {
// reached the minimum or maximum available point, can't push anymore
return false;
}
const nextHandle = handle + direction;
const nextValue = points[nextPointIndex];
const {
pushable
} = this;
const threshold = Number(pushable);
const diffToNext = direction * (bounds[nextHandle] - nextValue);
if (!this.pushHandle(bounds, nextHandle, direction, threshold - diffToNext)) {
// couldn't push next handle, so we won't push this one either
return false;
}
// push the handle
bounds[handle] = nextValue;
return true;
},
trimAlignValue(value) {
const {
sHandle,
bounds
} = this;
return trimAlignValue({
value,
handle: sHandle,
bounds,
props: this.$props
});
},
ensureValueNotConflict(handle, val, _ref2) {
let {
allowCross,
pushable: thershold
} = _ref2;
const state = this.$data || {};
const {
bounds
} = state;
handle = handle === undefined ? state.sHandle : handle;
thershold = Number(thershold);
/* eslint-disable eqeqeq */
if (!allowCross && handle != null && bounds !== undefined) {
if (handle > 0 && val <= bounds[handle - 1] + thershold) {
return bounds[handle - 1] + thershold;
}
if (handle < bounds.length - 1 && val >= bounds[handle + 1] - thershold) {
return bounds[handle + 1] - thershold;
}
}
/* eslint-enable eqeqeq */
return val;
},
getTrack(_ref3) {
let {
bounds,
prefixCls,
reverse,
vertical,
included,
offsets,
trackStyle
} = _ref3;
return bounds.slice(0, -1).map((_, index) => {
const i = index + 1;
const trackClassName = (0, _classNames.default)({
[`${prefixCls}-track`]: true,
[`${prefixCls}-track-${i}`]: true
});
return (0, _vue.createVNode)(_Track.default, {
"class": trackClassName,
"vertical": vertical,
"reverse": reverse,
"included": included,
"offset": offsets[i - 1],
"length": offsets[i] - offsets[i - 1],
"style": trackStyle[index],
"key": i
}, null);
});
},
renderSlider() {
const {
sHandle,
bounds,
prefixCls,
vertical,
included,
disabled,
min,
max,
reverse,
handle,
defaultHandle,
trackStyle,
handleStyle,
tabindex,
ariaLabelGroupForHandles,
ariaLabelledByGroupForHandles,
ariaValueTextFormatterGroupForHandles
} = this;
const handleGenerator = handle || defaultHandle;
const offsets = bounds.map(v => this.calcOffset(v));
const handleClassName = `${prefixCls}-handle`;
const handles = bounds.map((v, i) => {
let mergedTabIndex = tabindex[i] || 0;
if (disabled || tabindex[i] === null) {
mergedTabIndex = null;
}
const dragging = sHandle === i;
return handleGenerator({
class: (0, _classNames.default)({
[handleClassName]: true,
[`${handleClassName}-${i + 1}`]: true,
[`${handleClassName}-dragging`]: dragging
}),
prefixCls,
vertical,
dragging,
offset: offsets[i],
value: v,
index: i,
tabindex: mergedTabIndex,
min,
max,
reverse,
disabled,
style: handleStyle[i],
ref: h => this.saveHandle(i, h),
onFocus: this.onFocus,
onBlur: this.onBlur,
ariaLabel: ariaLabelGroupForHandles[i],
ariaLabelledBy: ariaLabelledByGroupForHandles[i],
ariaValueTextFormatter: ariaValueTextFormatterGroupForHandles[i]
});
});
return {
tracks: this.getTrack({
bounds,
prefixCls,
reverse,
vertical,
included,
offsets,
trackStyle
}),
handles
};
}
}
});
var _default = exports.default = (0, _createSlider.default)(Range);