NapCatQQ/static/components/SettingSelect.ts
手瓜一十雪 2f325cfe26 feat:webui-2
2024-05-05 13:01:23 +08:00

84 lines
2.8 KiB
TypeScript

import { SettingOption } from './option'
interface MouseEventExtend extends MouseEvent {
target: HTMLElement
}
// <ob-setting-select>
const SelectTemplate = document.createElement('template')
SelectTemplate.innerHTML = `<style>
.hidden { display: none !important; }
</style>
<div part="parent">
<div part="button">
<input type="text" placeholder="请选择" part="current-text" />
<svg viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg" part="button-arrow">
<path d="M12 6.0001L8.00004 10L4 6" stroke="currentColor" stroke-linejoin="round"></path>
</svg>
</div>
<ul class="hidden" part="option-list"><slot></slot></ul>
</div>`
window.customElements.define(
'ob-setting-select',
class extends HTMLElement {
readonly _button: HTMLDivElement
readonly _text: HTMLInputElement
readonly _context: HTMLUListElement
constructor() {
super()
this.attachShadow({ mode: 'open' })
this.shadowRoot.append(SelectTemplate.content.cloneNode(true))
this._button = this.shadowRoot.querySelector('div[part="button"]')
this._text = this.shadowRoot.querySelector('input[part="current-text"]')
this._context = this.shadowRoot.querySelector('ul[part="option-list"]')
const buttonClick = () => {
const isHidden = this._context.classList.toggle('hidden')
window[`${isHidden ? 'remove' : 'add'}EventListener`]('pointerdown', windowPointerDown)
}
const windowPointerDown = ({ target }) => {
if (!this.contains(target)) buttonClick()
}
this._button.addEventListener('click', buttonClick)
this._context.addEventListener('click', ({ target }: MouseEventExtend) => {
if (target.tagName !== 'SETTING-OPTION') return
buttonClick()
if (target.hasAttribute('is-selected')) return
this.querySelectorAll('setting-option[is-selected]').forEach((dom) => dom.toggleAttribute('is-selected'))
target.toggleAttribute('is-selected')
this._text.value = target.textContent
this.dispatchEvent(
new CustomEvent('selected', {
bubbles: true,
composed: true,
detail: {
name: target.textContent,
value: target.dataset.value,
},
}),
)
})
this._text.value = this.querySelector('setting-option[is-selected]').textContent
}
},
)
export const SettingSelect = (items: Array<{ text: string; value: string }>, configKey?: string, configValue?: any) => {
return `<ob-setting-select ${configKey ? `data-config-key="${configKey}"` : ''}>
${items
.map((e, i) => {
return SettingOption(e.text, e.value, configKey && configValue ? configValue === e.value : i === 0)
})
.join('')}
</ob-setting-select>`
}