vuetify
Version:
Vue Material Component Framework
173 lines (172 loc) • 6.06 kB
JavaScript
import { normalizeClass as _normalizeClass, createElementVNode as _createElementVNode, normalizeStyle as _normalizeStyle, withDirectives as _withDirectives, vShow as _vShow, createVNode as _createVNode } from "vue";
// Styles
import "./VSliderThumb.css";
// Components
import { VSliderSymbol } from "./slider.js";
import { VScaleTransition } from "../transitions/index.js"; // Composables
import { useTextColor } from "../../composables/color.js";
import { makeComponentProps } from "../../composables/component.js";
import { useElevation } from "../../composables/elevation.js";
import { useRtl } from "../../composables/locale.js"; // Directives
import vRipple from "../../directives/ripple/index.js"; // Utilities
import { computed, inject } from 'vue';
import { convertToUnit, genericComponent, keyValues, propsFactory, useRender } from "../../util/index.js"; // Types
export const makeVSliderThumbProps = propsFactory({
focused: Boolean,
max: {
type: Number,
required: true
},
min: {
type: Number,
required: true
},
modelValue: {
type: Number,
required: true
},
position: {
type: Number,
required: true
},
ripple: {
type: [Boolean, Object],
default: true
},
name: String,
...makeComponentProps()
}, 'VSliderThumb');
export const VSliderThumb = genericComponent()({
name: 'VSliderThumb',
directives: {
vRipple
},
props: makeVSliderThumbProps(),
emits: {
'update:modelValue': v => true
},
setup(props, _ref) {
let {
slots,
emit
} = _ref;
const slider = inject(VSliderSymbol);
const {
isRtl,
rtlClasses
} = useRtl();
if (!slider) throw new Error('[Vuetify] v-slider-thumb must be used inside v-slider or v-range-slider');
const {
min,
max,
thumbColor,
step,
disabled,
thumbSize,
thumbLabel,
direction,
isReversed,
vertical,
readonly,
elevation,
mousePressed,
decimals,
indexFromEnd
} = slider;
const elevationProps = computed(() => !disabled.value ? elevation.value : undefined);
const {
elevationClasses
} = useElevation(elevationProps);
const {
textColorClasses,
textColorStyles
} = useTextColor(thumbColor);
const {
pageup,
pagedown,
end,
home,
left,
right,
down,
up
} = keyValues;
const relevantKeys = [pageup, pagedown, end, home, left, right, down, up];
const multipliers = computed(() => {
if (step.value) return [1, 2, 3];else return [1, 5, 10];
});
function parseKeydown(e, value) {
if (!relevantKeys.includes(e.key)) return;
e.preventDefault();
const _step = step.value || 0.1;
const steps = (max.value - min.value) / _step;
if ([left, right, down, up].includes(e.key)) {
const increase = vertical.value ? [isRtl.value ? left : right, isReversed.value ? down : up] : indexFromEnd.value !== isRtl.value ? [left, up] : [right, up];
const direction = increase.includes(e.key) ? 1 : -1;
const multiplier = e.shiftKey ? 2 : e.ctrlKey ? 1 : 0;
if (direction === -1 && value === max.value && !multiplier && !Number.isInteger(steps)) {
value = value - steps % 1 * _step;
} else {
value = value + direction * _step * multipliers.value[multiplier];
}
} else if (e.key === home) {
value = min.value;
} else if (e.key === end) {
value = max.value;
} else {
const direction = e.key === pagedown ? 1 : -1;
value = value - direction * _step * (steps > 100 ? steps / 10 : 10);
}
return Math.max(props.min, Math.min(props.max, value));
}
function onKeydown(e) {
const newValue = parseKeydown(e, props.modelValue);
newValue != null && emit('update:modelValue', newValue);
}
useRender(() => {
const positionPercentage = convertToUnit(indexFromEnd.value ? 100 - props.position : props.position, '%');
return _createElementVNode("div", {
"class": _normalizeClass(['v-slider-thumb', {
'v-slider-thumb--focused': props.focused,
'v-slider-thumb--pressed': props.focused && mousePressed.value
}, props.class, rtlClasses.value]),
"style": _normalizeStyle([{
'--v-slider-thumb-position': positionPercentage,
'--v-slider-thumb-size': convertToUnit(thumbSize.value)
}, props.style]),
"role": "slider",
"tabindex": disabled.value ? -1 : 0,
"aria-label": props.name,
"aria-valuemin": min.value,
"aria-valuemax": max.value,
"aria-valuenow": props.modelValue,
"aria-readonly": !!readonly.value,
"aria-orientation": direction.value,
"onKeydown": !readonly.value ? onKeydown : undefined
}, [_createElementVNode("div", {
"class": _normalizeClass(['v-slider-thumb__surface', textColorClasses.value, elevationClasses.value]),
"style": {
...textColorStyles.value
}
}, null), _withDirectives(_createElementVNode("div", {
"class": _normalizeClass(['v-slider-thumb__ripple', textColorClasses.value]),
"style": _normalizeStyle(textColorStyles.value)
}, null), [[vRipple, props.ripple, null, {
circle: true,
center: true
}]]), _createVNode(VScaleTransition, {
"origin": "bottom center"
}, {
default: () => [_withDirectives(_createElementVNode("div", {
"class": "v-slider-thumb__label-container"
}, [_createElementVNode("div", {
"class": _normalizeClass(['v-slider-thumb__label', textColorClasses.value])
}, [_createElementVNode("div", null, [slots['thumb-label']?.({
modelValue: props.modelValue
}) ?? props.modelValue.toFixed(step.value ? decimals.value : 1)])])]), [[_vShow, thumbLabel.value && props.focused || thumbLabel.value === 'always']])]
})]);
});
return {};
}
});
//# sourceMappingURL=VSliderThumb.js.map