native dropdown

This commit is contained in:
Pete Matsyburka committed 2026-09-23 11:00:17 +03:00
1 parent be533e492e
commit 930445258d
6 files changed
+177 -56

No files matched your search

+2
View File
@@ -10,6 +10,7 @@ import ToggleCookies from './elements/toggle_cookies'
import DisableHidden from './elements/disable_hidden'
import TurboModal from './elements/turbo_modal'
import NativeAction from './elements/native_action'
import NativeMenu from './elements/native_menu'
import NativeSearch from './elements/native_search'
import NativeModal from './elements/native_modal'
import NativeEvent from './elements/native_event'
@@ -181,6 +182,7 @@ safeRegisterElement('toggle-visible', ToggleVisible)
safeRegisterElement('disable-hidden', DisableHidden)
safeRegisterElement('turbo-modal', TurboModal)
safeRegisterElement('native-action', NativeAction)
safeRegisterElement('native-menu', NativeMenu)
safeRegisterElement('native-search', NativeSearch)
safeRegisterElement('native-modal', NativeModal)
safeRegisterElement('native-event', NativeEvent)
+48
View File
@@ -0,0 +1,48 @@
let counter = 0
export default class extends HTMLElement {
connectedCallback () {
if (window.webkit?.messageHandlers?.native) {
this.addEventListener('click', this.onClick)
} else {
document.addEventListener('pointerdown', this.onPointerDown)
}
}
disconnectedCallback () {
this.removeEventListener('click', this.onClick)
document.removeEventListener('pointerdown', this.onPointerDown)
}
onPointerDown = (event) => {
if (this.contains(document.activeElement) && !this.contains(event.target)) {
document.activeElement.blur()
}
}
onClick = (event) => {
if (event.target.closest('native-menu-action')) return
const rect = this.firstElementChild.getBoundingClientRect()
const items = [...this.querySelectorAll('native-menu-action')].map((action) => {
const target = action.querySelector('a, button, [role="button"]') || action.firstElementChild
target.dataset.nativeId ||= `native-menu-${++counter}`
return {
id: target.dataset.nativeId,
title: action.dataset.label || target.textContent.trim(),
icon: action.dataset.icon,
destructive: action.dataset.destructive === 'true',
selected: action.dataset.selected === 'true'
}
})
window.webkit.messageHandlers.native.postMessage({
type: 'menu',
rect: { x: rect.left + window.scrollX, y: rect.top + window.scrollY, width: rect.width, height: rect.height },
items
})
}
}