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.
106 lines
2.5 KiB
JavaScript
106 lines
2.5 KiB
JavaScript
export class Dropdown extends HTMLElement {
|
|
constructor() {
|
|
super()
|
|
this.attachShadow({mode: 'open'})
|
|
this.dialogEl = document.createElement('dialog')
|
|
this.dialogEl.addEventListener('click', e => {
|
|
const rect = this.dialogEl.getBoundingClientRect()
|
|
const clickedInDialog = (
|
|
rect.top <= e.clientY &&
|
|
e.clientY <= rect.top + rect.height &&
|
|
rect.left <= e.clientX &&
|
|
e.clientX <= rect.left + rect.width
|
|
)
|
|
const isDialog = e.target === this.dialogEl
|
|
if (isDialog && !clickedInDialog) {
|
|
this.close()
|
|
}
|
|
})
|
|
this.shadowRoot.appendChild(this.dialogEl)
|
|
}
|
|
|
|
connectedCallback() {
|
|
const style = document.createElement('style')
|
|
style.textContent = `
|
|
dialog {
|
|
min-width: 200px;
|
|
border: 1px solid rgba(0, 0, 0, 0.3);
|
|
border-radius: 6px;
|
|
box-shadow: 0 3px 7px rgba(0, 0, 0, 0.3);
|
|
}
|
|
dialog {
|
|
background: #222;
|
|
color: #ddd;
|
|
padding: 3px;
|
|
margin-top: var(--anchor-bottom);
|
|
margin-right: calc(
|
|
100% - var(--anchor-right)
|
|
);
|
|
margin-left: auto;
|
|
margin-bottom: auto;
|
|
position: static;
|
|
}
|
|
dialog[open] {
|
|
display: flex;
|
|
flex-direction: column;
|
|
}
|
|
dialog::backdrop {
|
|
opacity: 0;
|
|
top: 0;
|
|
left: 0;
|
|
margin: 0;
|
|
padding: 0;
|
|
height: var(--window-height);
|
|
height: var(--window-width);
|
|
}
|
|
button {
|
|
background: #222;
|
|
font-size: 16px;
|
|
border: none;
|
|
color: inherit;
|
|
padding: 8px 10px;
|
|
text-align: left;
|
|
}
|
|
`
|
|
this.shadowRoot.append(style)
|
|
}
|
|
|
|
open(anchor) {
|
|
const rect = anchor.getBoundingClientRect()
|
|
const style = this.shadowRoot.host.style
|
|
style.setProperty(
|
|
'--anchor-right', `${rect.right}px`
|
|
)
|
|
style.setProperty(
|
|
'--anchor-bottom',
|
|
`${window.scrollY + rect.bottom - 3}px`
|
|
)
|
|
style.setProperty(
|
|
'--window-height', `${window.height}px`
|
|
)
|
|
style.setProperty(
|
|
'--window-width', `${window.width}px`
|
|
)
|
|
this.dialogEl.showModal()
|
|
}
|
|
|
|
close() {
|
|
this.dialogEl.close()
|
|
}
|
|
|
|
clear() {
|
|
this.dialogEl.replaceChildren()
|
|
}
|
|
|
|
add(text, handler = undefined) {
|
|
const btn = document.createElement('button')
|
|
btn.innerText = text
|
|
this.dialogEl.appendChild(btn)
|
|
btn.addEventListener('click', () => {
|
|
this.close()
|
|
if (handler !== undefined) {
|
|
handler()
|
|
}
|
|
})
|
|
}
|
|
} |