123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287 |
- /* 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
|