fix(key): Allow Esc and Any other input event (#173)

* fix(key): Allow Esc and input handler

* chore: set search autoFocus on shortcut component

* fix: allow enter, arrow and disable list if keyboard
This commit is contained in:
Aslam
2024-09-19 22:15:58 +07:00
committed by GitHub
parent 1a6c2ab420
commit bf5ae100ab
3 changed files with 58 additions and 50 deletions

View File

@@ -131,6 +131,7 @@ export function Shortcut() {
<form className="relative flex items-center"> <form className="relative flex items-center">
<LaIcon name="Search" className="text-muted-foreground absolute left-3 size-4" /> <LaIcon name="Search" className="text-muted-foreground absolute left-3 size-4" />
<Input <Input
autoFocus
placeholder="Search shortcuts" placeholder="Search shortcuts"
className="border-muted-foreground/50 focus-visible:border-muted-foreground h-10 pl-10 focus-visible:ring-0" className="border-muted-foreground/50 focus-visible:border-muted-foreground h-10 pl-10 focus-visible:ring-0"
value={searchQuery} value={searchQuery}

View File

@@ -25,6 +25,8 @@ import { useConfirm } from "@omit/react-confirm-dialog"
import { useLinkActions } from "./hooks/use-link-actions" import { useLinkActions } from "./hooks/use-link-actions"
import { isDeleteConfirmShownAtom } from "./LinkRoute" import { isDeleteConfirmShownAtom } from "./LinkRoute"
import { useActiveItemScroll } from "@/hooks/use-active-item-scroll" import { useActiveItemScroll } from "@/hooks/use-active-item-scroll"
import { useKeyboardManager } from "@/hooks/use-keyboard-manager"
import { useKeydownListener } from "@/hooks/use-keydown-listener"
interface LinkListProps { interface LinkListProps {
activeItemIndex: number | null activeItemIndex: number | null
@@ -131,59 +133,52 @@ const LinkList: React.FC<LinkListProps> = ({ activeItemIndex, setActiveItemIndex
}) })
}, []) }, [])
useEffect(() => { const { isKeyboardDisabled } = useKeyboardManager("XComponent")
const handleKeyDown = (e: KeyboardEvent) => {
if (isCommandPalettePpen || !me?.root?.personalLinks || sortedLinks.length === 0 || editId !== null) return
if (e.key === "ArrowUp" || e.key === "ArrowDown") { useKeydownListener((e: KeyboardEvent) => {
e.preventDefault() if (
setActiveItemIndex(prevIndex => { isKeyboardDisabled ||
if (prevIndex === null) return 0 isCommandPalettePpen ||
const newIndex = !me?.root?.personalLinks ||
e.key === "ArrowUp" ? Math.max(0, prevIndex - 1) : Math.min(sortedLinks.length - 1, prevIndex + 1) sortedLinks.length === 0 ||
editId !== null
)
return
if (e.metaKey && sort === "manual") { if (e.key === "ArrowUp" || e.key === "ArrowDown") {
const linksArray = [...me.root.personalLinks] e.preventDefault()
const newLinks = arrayMove(linksArray, prevIndex, newIndex) setActiveItemIndex(prevIndex => {
if (prevIndex === null) return 0
const newIndex =
e.key === "ArrowUp" ? Math.max(0, prevIndex - 1) : Math.min(sortedLinks.length - 1, prevIndex + 1)
while (me.root.personalLinks.length > 0) { if (e.metaKey && sort === "manual") {
me.root.personalLinks.pop() const linksArray = [...me.root.personalLinks]
} const newLinks = arrayMove(linksArray, prevIndex, newIndex)
newLinks.forEach(link => { while (me.root.personalLinks.length > 0) {
if (link) { me.root.personalLinks.pop()
me.root.personalLinks.push(link)
}
})
updateSequences(me.root.personalLinks)
} }
return newIndex newLinks.forEach(link => {
}) if (link) {
} else if (e.key === "Enter" && !disableEnterKey && activeItemIndex !== null) { me.root.personalLinks.push(link)
e.preventDefault() }
const activeLink = sortedLinks[activeItemIndex] })
if (activeLink) {
setEditId(activeLink.id) updateSequences(me.root.personalLinks)
} }
return newIndex
})
} else if (e.key === "Enter" && !disableEnterKey && activeItemIndex !== null) {
e.preventDefault()
const activeLink = sortedLinks[activeItemIndex]
if (activeLink) {
setEditId(activeLink.id)
} }
} }
})
window.addEventListener("keydown", handleKeyDown)
return () => window.removeEventListener("keydown", handleKeyDown)
}, [
me?.root?.personalLinks,
sortedLinks,
editId,
sort,
updateSequences,
isCommandPalettePpen,
activeItemIndex,
setEditId,
setActiveItemIndex,
disableEnterKey
])
const handleDragStart = useCallback( const handleDragStart = useCallback(
(event: DragStartEvent) => { (event: DragStartEvent) => {

View File

@@ -2,19 +2,31 @@ import { useAtom } from "jotai"
import { useEffect, useCallback } from "react" import { useEffect, useCallback } from "react"
import { keyboardDisableSourcesAtom } from "@/store/keydown-manager" import { keyboardDisableSourcesAtom } from "@/store/keydown-manager"
const allowedKeys = ["Escape", "ArrowUp", "ArrowDown", "ArrowLeft", "ArrowRight", "Enter"]
export function useKeyboardManager(sourceId: string) { export function useKeyboardManager(sourceId: string) {
const [disableSources, setDisableSources] = useAtom(keyboardDisableSourcesAtom) const [disableSources, setDisableSources] = useAtom(keyboardDisableSourcesAtom)
useEffect(() => { useEffect(() => {
const handleKeyDown = (event: KeyboardEvent) => { const handleKeyDown = (event: KeyboardEvent) => {
if (disableSources.size > 0) { if (disableSources.has(sourceId)) {
event.preventDefault() if (allowedKeys.includes(event.key)) {
if (event.key === "Escape") {
setDisableSources(prev => {
const next = new Set(prev)
next.delete(sourceId)
return next
})
}
} else {
event.stopPropagation()
}
} }
} }
window.addEventListener("keydown", handleKeyDown) window.addEventListener("keydown", handleKeyDown, true)
return () => window.removeEventListener("keydown", handleKeyDown) return () => window.removeEventListener("keydown", handleKeyDown, true)
}, [disableSources]) }, [disableSources, sourceId, setDisableSources])
const disableKeydown = useCallback( const disableKeydown = useCallback(
(disable: boolean) => { (disable: boolean) => {
@@ -32,7 +44,7 @@ export function useKeyboardManager(sourceId: string) {
[setDisableSources, sourceId] [setDisableSources, sourceId]
) )
const isKeyboardDisabled = disableSources.size > 0 const isKeyboardDisabled = disableSources.has(sourceId)
return { disableKeydown, isKeyboardDisabled } return { disableKeydown, isKeyboardDisabled }
} }