Vulture/VApp/node_modules/vuetify/lib/components/VSlider/slider.mjs

287 lines
8.3 KiB
JavaScript

/* eslint-disable max-statements */
// Composables
import { makeElevationProps } from "../../composables/elevation.mjs";
import { useRtl } from "../../composables/locale.mjs";
import { makeRoundedProps } from "../../composables/rounded.mjs"; // Utilities
import { computed, provide, ref, shallowRef, toRef } from 'vue';
import { clamp, createRange, getDecimals, propsFactory } from "../../util/index.mjs"; // Types
export const VSliderSymbol = Symbol.for('vuetify:v-slider');
export function getOffset(e, el, direction) {
const vertical = direction === 'vertical';
const rect = el.getBoundingClientRect();
const touch = 'touches' in e ? e.touches[0] : e;
return vertical ? touch.clientY - (rect.top + rect.height / 2) : touch.clientX - (rect.left + rect.width / 2);
}
function getPosition(e, position) {
if ('touches' in e && e.touches.length) return e.touches[0][position];else if ('changedTouches' in e && e.changedTouches.length) return e.changedTouches[0][position];else return e[position];
}
export const makeSliderProps = propsFactory({
disabled: {
type: Boolean,
default: null
},
error: Boolean,
readonly: {
type: Boolean,
default: null
},
max: {
type: [Number, String],
default: 100
},
min: {
type: [Number, String],
default: 0
},
step: {
type: [Number, String],
default: 0
},
thumbColor: String,
thumbLabel: {
type: [Boolean, String],
default: undefined,
validator: v => typeof v === 'boolean' || v === 'always'
},
thumbSize: {
type: [Number, String],
default: 20
},
showTicks: {
type: [Boolean, String],
default: false,
validator: v => typeof v === 'boolean' || v === 'always'
},
ticks: {
type: [Array, Object]
},
tickSize: {
type: [Number, String],
default: 2
},
color: String,
trackColor: String,
trackFillColor: String,
trackSize: {
type: [Number, String],
default: 4
},
direction: {
type: String,
default: 'horizontal',
validator: v => ['vertical', 'horizontal'].includes(v)
},
reverse: Boolean,
...makeRoundedProps(),
...makeElevationProps({
elevation: 2
}),
ripple: {
type: Boolean,
default: true
}
}, 'Slider');
export const useSteps = props => {
const min = computed(() => parseFloat(props.min));
const max = computed(() => parseFloat(props.max));
const step = computed(() => +props.step > 0 ? parseFloat(props.step) : 0);
const decimals = computed(() => Math.max(getDecimals(step.value), getDecimals(min.value)));
function roundValue(value) {
value = parseFloat(value);
if (step.value <= 0) return value;
const clamped = clamp(value, min.value, max.value);
const offset = min.value % step.value;
const newValue = Math.round((clamped - offset) / step.value) * step.value + offset;
return parseFloat(Math.min(newValue, max.value).toFixed(decimals.value));
}
return {
min,
max,
step,
decimals,
roundValue
};
};
export const useSlider = _ref => {
let {
props,
steps,
onSliderStart,
onSliderMove,
onSliderEnd,
getActiveThumb
} = _ref;
const {
isRtl
} = useRtl();
const isReversed = toRef(props, 'reverse');
const vertical = computed(() => props.direction === 'vertical');
const indexFromEnd = computed(() => vertical.value !== isReversed.value);
const {
min,
max,
step,
decimals,
roundValue
} = steps;
const thumbSize = computed(() => parseInt(props.thumbSize, 10));
const tickSize = computed(() => parseInt(props.tickSize, 10));
const trackSize = computed(() => parseInt(props.trackSize, 10));
const numTicks = computed(() => (max.value - min.value) / step.value);
const disabled = toRef(props, 'disabled');
const thumbColor = computed(() => props.error || props.disabled ? undefined : props.thumbColor ?? props.color);
const trackColor = computed(() => props.error || props.disabled ? undefined : props.trackColor ?? props.color);
const trackFillColor = computed(() => props.error || props.disabled ? undefined : props.trackFillColor ?? props.color);
const mousePressed = shallowRef(false);
const startOffset = shallowRef(0);
const trackContainerRef = ref();
const activeThumbRef = ref();
function parseMouseMove(e) {
const vertical = props.direction === 'vertical';
const start = vertical ? 'top' : 'left';
const length = vertical ? 'height' : 'width';
const position = vertical ? 'clientY' : 'clientX';
const {
[start]: trackStart,
[length]: trackLength
} = trackContainerRef.value?.$el.getBoundingClientRect();
const clickOffset = getPosition(e, position);
// It is possible for left to be NaN, force to number
let clickPos = Math.min(Math.max((clickOffset - trackStart - startOffset.value) / trackLength, 0), 1) || 0;
if (vertical ? indexFromEnd.value : indexFromEnd.value !== isRtl.value) clickPos = 1 - clickPos;
return roundValue(min.value + clickPos * (max.value - min.value));
}
const handleStop = e => {
onSliderEnd({
value: parseMouseMove(e)
});
mousePressed.value = false;
startOffset.value = 0;
};
const handleStart = e => {
activeThumbRef.value = getActiveThumb(e);
if (!activeThumbRef.value) return;
activeThumbRef.value.focus();
mousePressed.value = true;
if (activeThumbRef.value.contains(e.target)) {
startOffset.value = getOffset(e, activeThumbRef.value, props.direction);
} else {
startOffset.value = 0;
onSliderMove({
value: parseMouseMove(e)
});
}
onSliderStart({
value: parseMouseMove(e)
});
};
const moveListenerOptions = {
passive: true,
capture: true
};
function onMouseMove(e) {
onSliderMove({
value: parseMouseMove(e)
});
}
function onSliderMouseUp(e) {
e.stopPropagation();
e.preventDefault();
handleStop(e);
window.removeEventListener('mousemove', onMouseMove, moveListenerOptions);
window.removeEventListener('mouseup', onSliderMouseUp);
}
function onSliderTouchend(e) {
handleStop(e);
window.removeEventListener('touchmove', onMouseMove, moveListenerOptions);
e.target?.removeEventListener('touchend', onSliderTouchend);
}
function onSliderTouchstart(e) {
handleStart(e);
window.addEventListener('touchmove', onMouseMove, moveListenerOptions);
e.target?.addEventListener('touchend', onSliderTouchend, {
passive: false
});
}
function onSliderMousedown(e) {
e.preventDefault();
handleStart(e);
window.addEventListener('mousemove', onMouseMove, moveListenerOptions);
window.addEventListener('mouseup', onSliderMouseUp, {
passive: false
});
}
const position = val => {
const percentage = (val - min.value) / (max.value - min.value) * 100;
return clamp(isNaN(percentage) ? 0 : percentage, 0, 100);
};
const showTicks = toRef(props, 'showTicks');
const parsedTicks = computed(() => {
if (!showTicks.value) return [];
if (!props.ticks) {
return numTicks.value !== Infinity ? createRange(numTicks.value + 1).map(t => {
const value = min.value + t * step.value;
return {
value,
position: position(value)
};
}) : [];
}
if (Array.isArray(props.ticks)) return props.ticks.map(t => ({
value: t,
position: position(t),
label: t.toString()
}));
return Object.keys(props.ticks).map(key => ({
value: parseFloat(key),
position: position(parseFloat(key)),
label: props.ticks[key]
}));
});
const hasLabels = computed(() => parsedTicks.value.some(_ref2 => {
let {
label
} = _ref2;
return !!label;
}));
const data = {
activeThumbRef,
color: toRef(props, 'color'),
decimals,
disabled,
direction: toRef(props, 'direction'),
elevation: toRef(props, 'elevation'),
hasLabels,
isReversed,
indexFromEnd,
min,
max,
mousePressed,
numTicks,
onSliderMousedown,
onSliderTouchstart,
parsedTicks,
parseMouseMove,
position,
readonly: toRef(props, 'readonly'),
rounded: toRef(props, 'rounded'),
roundValue,
showTicks,
startOffset,
step,
thumbSize,
thumbColor,
thumbLabel: toRef(props, 'thumbLabel'),
ticks: toRef(props, 'ticks'),
tickSize,
trackColor,
trackContainerRef,
trackFillColor,
trackSize,
vertical
};
provide(VSliderSymbol, data);
return data;
};
//# sourceMappingURL=slider.mjs.map