Operator-flagged (again) on the tag-merge picker: Enter on the dropdown re-opens it instead of accepting the selection. I'd already patched this twice (fandom picker + fandom set dialog) with copy-pasted capture-phase handlers, so DRY it. New composable useAcceptOnEnter(accept): tracks the menu state and, on a capture-phase Enter, lets Vuetify pick when the menu is open but calls accept() (and blocks the re-open) when it's closed. Applied to every confirm-style picker: - TagsView merge-into picker (the reported one) - AliasPickerDialog - PostSeriesMenu add-to-existing - FandomPicker + FandomSetDialog (refactored off their bespoke handlers) One behavior, one place to change it.
36 lines
1.5 KiB
JavaScript
36 lines
1.5 KiB
JavaScript
import { ref } from 'vue'
|
|
|
|
/**
|
|
* Unifies keyboard behavior for confirm-style `v-autocomplete` / `v-select`
|
|
* dropdowns — a single picker whose Enter should trigger the surrounding
|
|
* modal's primary action (Merge, Add, Save, Use…).
|
|
*
|
|
* The recurring bug (operator-flagged across the merge / fandom / series / alias
|
|
* dialogs): pressing Enter with the menu CLOSED re-opens the dropdown instead of
|
|
* accepting the chosen value, because Vuetify's own Enter handler opens the menu.
|
|
* We bind in the CAPTURE phase so this runs BEFORE Vuetify's handler:
|
|
* - menu OPEN → return; let Vuetify pick the highlighted item (it sets the
|
|
* value and closes the menu).
|
|
* - menu CLOSED → preventDefault + stopPropagation so Vuetify can't re-open the
|
|
* menu, then call `accept()` — the modal's confirm. `accept`
|
|
* should itself no-op when nothing valid is selected.
|
|
*
|
|
* Usage:
|
|
* const { menuOpen, onEnter } = useAcceptOnEnter(onConfirm)
|
|
* <v-autocomplete v-model:menu="menuOpen" @keydown.enter.capture="onEnter" … />
|
|
*
|
|
* `menuOpen` is exposed so a component that programmatically focuses the field
|
|
* can force the menu shut (so the very next Enter accepts rather than being
|
|
* swallowed as a menu interaction).
|
|
*/
|
|
export function useAcceptOnEnter(accept) {
|
|
const menuOpen = ref(false)
|
|
function onEnter(e) {
|
|
if (menuOpen.value) return
|
|
e.preventDefault()
|
|
e.stopPropagation()
|
|
accept()
|
|
}
|
|
return { menuOpen, onEnter }
|
|
}
|