Vue.component('tt-icon-select', { props: ['options', 'label', 'value'], data() { return { selectedOption: this.options.find(option => option.value.toString() === this.value) || null, isOpen: false, observer: null, }; }, mounted() { // Dynamically add CSS to disable default dropdown caret const style = document.createElement('style'); style.innerHTML = `.tt-select .dropdown-toggle::after { display: none; }`; document.body.appendChild(style); document.addEventListener('click', this.handleClick); this.observer = new ResizeObserver(this.calculateOffset.bind(this)); this.observer.observe(this.$refs.select); this.calculateOffset(); }, beforeDestroy() { document.removeEventListener('click', this.handleClick); this.observer.disconnect(); }, watch: { value(val) { this.selectedOption = this.options.find(option => option.value.toString() === val) || null; } }, methods: { selectOption(option) { this.selectedOption = option; this.$emit('input', option ? option.value.toString() : ''); this.isOpen = false; }, calculateOffset() { const offset = (this.$refs.select.offsetWidth - 64.41) / 2; this.$refs.select.querySelector('.dropdown-menu').style.left = `${offset}px`; }, handleClick() { this.isOpen = this.$refs.selectedIcon.contains(event.target) ? !this.isOpen : false; }, }, template: `
` });