<template>
	<div class="slider" :disabled="disabled">
		<div
			class="input-range"
			:style="{
				'--progress': (value - props.min) / (props.max - props.min)
			}"
		>
			<span class="tip">{{ props.tipFormatter(value) }}</span>
			<input
				type="range"
				v-model="value"
				v-bind="$attrs"
				@input="onInput"
				@change="onChange"
				:disabled="disabled"
				:min="props.min"
				:max="props.max"
			/>
		</div>
		<div class="input" v-show="isInput">
			<my-input
				type="number"
				v-model="value"
				v-bind="$attrs"
				@input="onInput"
				@change="onChange"
				:disabled="disabled"
				:min="props.min"
				:max="props.max"
			/>
		</div>
	</div>
</template>

<script setup lang="ts">
	import { ref, defineProps, defineEmits, watch } from 'vue'
	import MyInput from './my-input.vue'
	const props = defineProps({
		modelValue: { type: Number },
		disabled: {
			type: Boolean,
			default: false
		},
		min: {
			type: Number,
			default: 0
		},
		max: {
			type: Number,
			default: 100
		},
		tipFormatter: {
			type: Function,
			default: (v) => v
		},
		isInput: {
			type: Boolean,
			default: true
		}
	})
	const emit = defineEmits(['update:modelValue', 'change', 'input'])
	watch(
		() => props.modelValue,
		(v) => {
			value.value = v
		}
	)
	const value = ref(props.modelValue)
	const onInput = () => {
		if (props.disabled) return
		const v = Number(value.value)
		emit('update:modelValue', v)
		emit('input', v)
	}
	const onChange = () => {
		if (props.disabled) return
		const v = Number(value.value)
		emit('update:modelValue', v)
		emit('change', v)
	}
</script>

<style scoped lang="less">
	.slider {
		position: relative;
		display: flex;
		align-items: center;
		--input-thumb-size: 0.8rem;
		--backcolor1: var(--slider-thumb-color1, #4285f4);
		--backcolor2: var(--slider-thumb-color2, rgba(0, 0, 0, 0.1));
		&:hover {
			> .input-range > .tip {
				display: block;
			}
		}
		> .input-range {
			position: relative;
			flex: 2;
			display: flex;
			> input {
				width: 100%;
				-webkit-appearance: none;
				appearance: none;
				height: 0.339rem;
				border-radius: 0.3rem;
				outline: none;
				background: linear-gradient(
					to right,
					var(--backcolor1) 0%,
					var(--backcolor1) calc(var(--progress) * 100%),
					var(--backcolor2) calc(var(--progress) * 100%),
					var(--backcolor2) 100%
				);
				&::-webkit-slider-thumb {
					-webkit-appearance: none;
					appearance: none;
					width: var(--input-thumb-size);
					height: var(--input-thumb-size);
					border-radius: 50%;
					background: var(--backcolor1); /* 蓝色滑块 */
					cursor: pointer;
					transition: all 0.2s;
					box-shadow: 0 0.1rem 0.2rem rgba(0, 0, 0, 0.1);
				}
				&::-webkit-slider-thumb:hover {
					transform: scale(1.1);
				}
			}
			> .tip {
				position: absolute;
				font-size: 1rem;
				pointer-events: none;
				user-select: none;
				color: #666;
				top: calc(var(--input-thumb-size) / -2 - 0.35rem);
				left: calc(
					(100% - var(--input-thumb-size)) * var(--progress) + var(--input-thumb-size) / 2
				);
				transform: translate(-50%, -100%);
				background-color: rgba(0, 0, 0, 0.7);
				color: white;
				padding: 0.3rem 0.5rem;
				border-radius: 0.4rem;
				font-size: 1rem;
				white-space: nowrap;
				pointer-events: none;
				display: none;
				&::after {
					content: '';
					position: absolute;
					top: 97%;
					left: 50%;
					transform: translateX(-50%);
					width: 0;
					height: 0;
					border-left: 0.5rem solid transparent;
					border-right: 0.5rem solid transparent;
					border-top: 0.5rem solid rgba(0, 0, 0, 0.8);
				}
			}
		}
		> .input {
			flex: 1;
			margin-left: 1rem;
			> input {
				border-radius: 0.3rem;
				width: 100%;
			}
		}
	}
</style>
