Something went wrong. Try again.
Browser extension: detect and subscribe to standard.site publications on ATProto
Something went wrong. Try again.
2.5 kB · 63 lines
TypeScript
12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364// Companion to the actor-typeahead web component, which keeps its state in a// closed shadow root. Two gaps are bridged here://// - Enter: the component swallows every Enter keydown (preventDefault) so// that Enter can pick the highlighted suggestion. With no highlight that// leaves Enter doing nothing, breaking implicit form submission. This// mirrors the relevant part of the component's state: whether the user has// moved the highlight since last typing.// - Click: picking a suggestion with the pointer only copies the handle into// the input, so signing in would always need a second click on the button.// Clicking an account should just sign in as it; the button stays for the// typed-by-hand path.//// Kept free of DOM globals so it can be unit-tested in node; the entry points// import 'actor-typeahead' themselves to register the element.
const NAV_KEYS = ['ArrowDown', 'ArrowUp', 'PageDown', 'PageUp']
export function wireTypeaheadSubmit( input: EventTarget & { value: string }, form: { requestSubmit(): void }, host?: EventTarget,): void { let navigating = false let typed = input.value
input.addEventListener('input', () => { navigating = false typed = input.value })
input.addEventListener('keydown', (evt) => { const key = (evt as KeyboardEvent).key if (NAV_KEYS.includes(key)) { navigating = true } else if (key === 'Escape') { navigating = false } else if (key === 'Enter') { console.debug('[substandard] typeahead enter:', navigating ? 'select suggestion' : 'submit') if (navigating) { // actor-typeahead consumes this Enter to fill in the suggestion. navigating = false } else { form.requestSubmit() } } })
// A pointer pick is visible out here as a pointerup retargeted to the host // element (clicks on the slotted input keep their own target), and the // component's shadow-root listener has already run by then, copying the // handle into the input without an 'input' event. A retargeted pointerup // that changed the value is therefore a picked account. Enter picks stay // two-step: their synthetic pointerup is not composed and never gets here. host?.addEventListener('pointerup', (evt) => { if (evt.target !== host) return if (!input.value || input.value === typed) return typed = input.value navigating = false console.debug('[substandard] typeahead click: sign in as', input.value) form.requestSubmit() })}