platypush/platypush/backend/http/webapp/src/components/elements/RangeSlider.vue

144 lines
2.9 KiB
Vue

<template>
<div class="range-slider">
<label>
<input class="slider" type="range" :value="v" :min="range[0]" :max="range[1]"
:disabled="disabled" @input="input" @change="changed" @mouseup="mouseup" @mousedown="mousedown"
@touchstart="mouseup" @touchend="mousedown" :ref="`input_${i}`" v-for="(v, i) in value" :key="i">
</label>
</div>
</template>
<script>
export default {
name: "RangeSlider",
emits: ['input', 'change', 'mouseup', 'mousedown'],
props: {
disabled: {
type: Boolean,
default: false,
},
range: {
type: Array,
default: () => [0, 100],
},
value: {
type: Array,
default: () => [0, 100],
},
},
methods: {
getEvent(event) {
return {
...event,
target: {
...event.target,
value: Object.values(this.$refs).map((input) => parseFloat(input.value)).sort(),
}
}
},
input(event) {
this.$emit('input', this.getEvent(event))
},
changed(event) {
this.$emit('change', this.getEvent(event))
},
mouseup(event) {
this.$emit('mouseup', this.getEvent(event))
},
mousedown(event) {
this.$emit('mousedown', this.getEvent(event))
},
},
mounted() {
if (this.value) {
const self = this
this.value.forEach((v, i) => {
self.$refs[`input_${i}`].value = v
})
}
},
}
</script>
<style lang="scss" scoped>
.range-slider {
position: relative;
display: flex;
label {
height: 2em;
}
.slider {
@include appearance(none);
@include transition(opacity .2s);
background: none;
width: 100%;
height: 2em;
position: absolute;
left: 0;
top: 0;
margin: 0;
padding: 0;
border-radius: 1em;
outline: none;
pointer-events: none;
overflow: hidden;
z-index: 20;
@mixin slider-thumb {
@include appearance(none);
position: relative;
width: 1.5em;
height: 1.5em;
pointer-events: all;
border-radius: 50%;
border: 0;
background: $slider-thumb-bg;
cursor: pointer;
z-index: 10;
outline: 0;
}
&::-webkit-slider-thumb { @include slider-thumb }
&::-moz-range-thumb { @include slider-thumb}
&::-moz-range-track {
@include appearance(none);
position: relative;
border: 0;
}
&::-moz-range-progress { height: 1em; }
&:first-child {
z-index: 21;
&::-moz-range-progress { background: $slider-bg; }
}
&:last-child {
background: $slider-bg;
&::-moz-range-progress { background: $slider-progress-bg; }
}
&[disabled] {
@mixin no-thumb {
display: none;
width: 0;
}
&::-moz-range-progress { background: none; }
&::-webkit-slider-runnable-track { background: none; }
&::-moz-range-thumb { @include no-thumb; }
&::-webkit-slider-thumb { @include no-thumb; }
}
}
}
</style>