You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
xshop/resources/js/client-vue/Quantity.vue

124 lines
3.0 KiB
Vue

<template>
<div class="quantity">
<div class="val">
{{val}}
</div>
<div class="border-end-0 btns">
<i class="ri-arrow-up-s-line"
@mousedown="startIncrement"
@mouseup="stopChange"
@mouseleave="stopChange"></i>
<i class="ri-arrow-down-s-line"
@mousedown="startDecrement"
@mouseup="stopChange"
@mouseleave="stopChange"></i>
</div>
<input type="hidden" :name="xname" v-if="xname != null" :value="val">
</div>
</template>
<script>
export default {
name: "quantity",
data: () => ({
val: 1,
interval: null,
timeout: null,
changeSpeed: 100, // milliseconds between each change
startDelay: 1000, // 1 second delay before rapid change starts
}),
emits: ['update:modelValue'],
props: {
min: {
default: 1,
type: Number,
},
max: {
default: 99,
type: Number,
},
xname: {
default: null,
type: [null, String],
},
modelValue: {
type: Number,
default: 1,
},
},
methods: {
inc() {
if (this.val < this.max) {
this.val++;
this.$emit('update:modelValue', this.val);
}
},
dec() {
if (this.val > this.min) {
this.val--;
this.$emit('update:modelValue', this.val);
}
},
startIncrement() {
this.inc(); // Immediate first increment
this.timeout = setTimeout(() => {
this.interval = setInterval(this.inc, this.changeSpeed);
}, this.startDelay);
},
startDecrement() {
this.dec(); // Immediate first decrement
this.timeout = setTimeout(() => {
this.interval = setInterval(this.dec, this.changeSpeed);
}, this.startDelay);
},
stopChange() {
clearTimeout(this.timeout);
clearInterval(this.interval);
},
},
beforeUnmount() {
this.stopChange();
},
}
</script>
<style scoped>
.quantity {
direction: ltr;
border: 1px solid rgba(128, 128, 128, 0.56);
display: grid;
grid-template-columns: 2fr 1fr;
width: 90px;
height: 50px;
border-radius: var(--xshop-border-radius);
.val{
display: flex;
align-items: center;
justify-content: center;
font-size: 17px;
}
i{
display: block;
transition: 377ms;
&:first-child{
border-bottom: 1px solid rgba(128, 128, 128, 0.56);
}
&:hover{
background: var(--xshop-primary);
color: var(--xshop-diff);
}
}
.btns{
border: 1px solid rgba(128, 128, 128, 0.56);
border-bottom: 0;
border-top: 0;
text-align: center;
}
}
</style>