<template>
	<view class="auto-width-input-container" :class="{ 'is-textarea': type === 'textarea' }">
		<!-- 测量层：用于计算宽度的影藏文本，必须保持与 input 相同的字体样式 -->
		<text v-if="type !== 'textarea'" class="measure-text" :style="[inputStyle, { visibility: 'hidden', position: 'absolute', whiteSpace: 'nowrap' }]">
			{{ modelValue || placeholder }}
		</text>

		<!-- 输入层 -->
		<template v-if="type !== 'textarea'">
			<input class="auto-input" :type="type" :value="modelValue" :placeholder="placeholder" :placeholder-style="placeholderStyle"
				:style="[inputStyle, { width: inputWidth }]" @input="onInput" :maxlength="maxlength" />
		</template>
		<template v-else>
			<textarea class="auto-textarea" :value="modelValue" :placeholder="placeholder" :placeholder-style="placeholderStyle"
				:style="[inputStyle]" @input="onInput" :maxlength="maxlength" auto-height />
		</template>
	</view>
</template>

<script setup>
import { ref, computed, watch, nextTick, getCurrentInstance, onMounted } from 'vue';

const props = defineProps({
	modelValue: {
		type: [String, Number],
		default: ''
	},
	type: {
		type: String,
		default: 'text' // 支持所有原生类型如 'number', 'tel', 'digit' 或 'textarea'
	},
	placeholder: {
		type: String,
		default: '请输入'
	},
	placeholderStyle: {
		type: String,
		default: 'color: #999;'
	},
	fontSize: {
		type: String,
		default: '28rpx'
	},
	fontWeight: {
		type: String,
		default: 'normal'
	},
	color: {
		type: String,
		default: '#1A1A1A'
	},
	maxlength: {
		type: Number,
		default: 140
	},
	minWidth: {
		type: String,
		default: '20rpx'
	},
	extraWidth: {
		type: Number,
		default: 10 // 额外的缓冲像素，防止文字抖动
	}
});

const emit = defineEmits(['update:modelValue', 'change']);
const instance = getCurrentInstance();
const inputWidth = ref(props.minWidth);

const inputStyle = computed(() => ({
	fontSize: props.fontSize,
	fontWeight: props.fontWeight,
	color: props.color,
	fontFamily: 'inherit'
}));

/**
 * 核心逻辑：测量隐藏文本的物理宽度
 */
const updateWidth = () => {
	if (props.type === 'textarea') return;
	nextTick(() => {
		const query = uni.createSelectorQuery().in(instance.proxy);
		query.select('.measure-text').boundingClientRect(data => {
			if (data && data.width) {
				heatWidth(data.width);
			}
		}).exec();
	});
};

const heatWidth = (width) => {
	// 加上一点额外的空间，避免在某些平台上因为小数点或字体渲染导致的文字换行
	inputWidth.value = (width + props.extraWidth) + 'px';
};

const onInput = (e) => {
	const val = e.detail.value;
	emit('update:modelValue', val);
	emit('change', val);
};

// 监听值的变化实时更新宽度
watch(() => props.modelValue, () => {
	updateWidth();
});

// 初始化
onMounted(() => {
	updateWidth();
});
</script>

<style lang="less" scoped>
.auto-width-input-container {
	position: relative;
	display: inline-block;
	vertical-align: middle;
	
	&.is-textarea {
		width: 100%;
	}

	.measure-text {
		left: -9999rpx;
		top: -9999rpx;
		pointer-events: none;
	}

	.auto-input {
		min-width: v-bind('props.minWidth');
		padding: 0;
		margin: 0;
		text-align: inherit; // 继承父级的对齐方式
		height: 1.4em; // 自动适应行高
		line-height: 1.4em;
	}

	.auto-textarea {
		width: 100%;
		min-height: 1.4em;
		padding: 0;
		margin: 0;
		line-height: 1.4em;
		display: block;
	}
}
</style>
