UNPKG

quasar

Version:

Build high-performance VueJS user interfaces (SPA, PWA, SSR, Mobile and Desktop) in record time

188 lines (153 loc) 4.67 kB
import { h, ref, computed, watch, getCurrentInstance } from 'vue' import { useFormAttrs } from '../../composables/use-form/private.use-form.js' import useSlider, { useSliderProps, useSliderEmits, keyCodes } from './use-slider.js' import { createComponent } from '../../utils/private.create/create.js' import { between } from '../../utils/format/format.js' import { stopAndPrevent } from '../../utils/event/event.js' const getNodeData = () => ({}) export default createComponent({ name: 'QSlider', props: { ...useSliderProps, modelValue: { required: true, default: null, validator: v => typeof v === 'number' || v === null }, labelValue: [String, Number] }, emits: useSliderEmits, setup(props, { emit }) { const { proxy: { $q } } = getCurrentInstance() const { state, methods } = useSlider({ updateValue, updatePosition, getDragging, formAttrs: useFormAttrs(props) }) const rootRef = ref(null) const curRatio = ref(0) const model = ref(0) function normalizeModel() { model.value = props.modelValue === null ? state.innerMin.value : between( props.modelValue, state.innerMin.value, state.innerMax.value ) } watch( () => `${props.modelValue}|${state.innerMin.value}|${state.innerMax.value}`, normalizeModel ) normalizeModel() const modelRatio = computed(() => methods.convertModelToRatio(model.value)) const ratio = computed(() => state.active.value === true ? curRatio.value : modelRatio.value ) const selectionBarStyle = computed(() => { const acc = { [state.positionProp.value]: `${100 * state.innerMinRatio.value}%`, [state.sizeProp.value]: `${100 * (ratio.value - state.innerMinRatio.value)}%` } if (props.selectionImg !== void 0) { acc.backgroundImage = `url(${props.selectionImg}) !important` } return acc }) const getThumb = methods.getThumbRenderFn({ focusValue: true, getNodeData, ratio, label: computed(() => props.labelValue !== void 0 ? props.labelValue : model.value ), thumbColor: computed(() => props.thumbColor || props.color), labelColor: computed(() => props.labelColor), labelTextColor: computed(() => props.labelTextColor) }) const trackContainerEvents = computed(() => { if (state.editable.value !== true) { return {} } return $q.platform.is.mobile === true ? { onClick: methods.onMobileClick } : { onMousedown: methods.onActivate, onFocus, onBlur: methods.onBlur, onKeydown, onKeyup: methods.onKeyup } }) function updateValue(change) { if (model.value !== props.modelValue) { emit('update:modelValue', model.value) } if (change === true) emit('change', model.value) } function getDragging() { return rootRef.value.getBoundingClientRect() } function updatePosition(event, dragging = state.dragging.value) { const localRatio = methods.getDraggingRatio(event, dragging) model.value = methods.convertRatioToModel(localRatio) curRatio.value = props.snap !== true || props.step === 0 ? localRatio : methods.convertModelToRatio(model.value) } function onFocus() { state.focus.value = true } function onKeydown(evt) { if (keyCodes.includes(evt.keyCode) === false) return stopAndPrevent(evt) const stepVal = ([34, 33].includes(evt.keyCode) ? 10 : 1) * state.keyStep.value, offset = ([34, 37, 40].includes(evt.keyCode) ? -1 : 1) * (state.isReversed.value === true ? -1 : 1) * (props.vertical === true ? -1 : 1) * stepVal model.value = between( state.roundValueFn.value(model.value + offset), state.innerMin.value, state.innerMax.value ) updateValue() } return () => { const content = methods.getContent( selectionBarStyle, state.tabindex, trackContainerEvents, node => { node.push(getThumb()) } ) return h( 'div', { ref: rootRef, class: state.classes.value + (props.modelValue === null ? ' q-slider--no-value' : ''), ...state.attributes.value, 'aria-valuenow': props.modelValue }, content ) } } })