mirror of
https://github.com/langgenius/dify.git
synced 2026-06-07 16:23:44 +08:00
refactor(web): manage goto anything open state with atom (#36938)
This commit is contained in:
parent
eae44cfecb
commit
696fc5c213
@ -2,6 +2,7 @@ import type { ReactNode } from 'react'
|
||||
import type { ActionItem, SearchResult } from '../actions/types'
|
||||
import { act, render, screen, waitFor } from '@testing-library/react'
|
||||
import userEvent from '@testing-library/user-event'
|
||||
import { createStore, Provider } from 'jotai'
|
||||
import * as React from 'react'
|
||||
import { GotoAnything } from '../index'
|
||||
|
||||
@ -49,7 +50,6 @@ vi.mock('@tanstack/react-hotkeys', async (importOriginal) => {
|
||||
|
||||
const HOTKEY_ALIAS: Record<string, string> = {
|
||||
'ctrl.k': 'Mod+K',
|
||||
'esc': 'Escape',
|
||||
}
|
||||
|
||||
const triggerKeyPress = (combo: string) => {
|
||||
@ -135,6 +135,16 @@ vi.mock('../../plugins/install-plugin/install-from-marketplace', () => ({
|
||||
),
|
||||
}))
|
||||
|
||||
const renderGotoAnything = (ui: React.ReactElement) => {
|
||||
const store = createStore()
|
||||
|
||||
return render(
|
||||
<Provider store={store}>
|
||||
{ui}
|
||||
</Provider>,
|
||||
)
|
||||
}
|
||||
|
||||
describe('GotoAnything', () => {
|
||||
beforeEach(() => {
|
||||
routerPush.mockClear()
|
||||
@ -147,7 +157,7 @@ describe('GotoAnything', () => {
|
||||
|
||||
describe('modal behavior', () => {
|
||||
it('should open modal via Ctrl+K shortcut', async () => {
|
||||
render(<GotoAnything />)
|
||||
renderGotoAnything(<GotoAnything />)
|
||||
|
||||
triggerKeyPress('ctrl.k')
|
||||
|
||||
@ -157,21 +167,22 @@ describe('GotoAnything', () => {
|
||||
})
|
||||
|
||||
it('should close modal via ESC key', async () => {
|
||||
render(<GotoAnything />)
|
||||
const user = userEvent.setup()
|
||||
renderGotoAnything(<GotoAnything />)
|
||||
|
||||
triggerKeyPress('ctrl.k')
|
||||
await waitFor(() => {
|
||||
expect(screen.getByPlaceholderText('app.gotoAnything.searchPlaceholder')).toBeInTheDocument()
|
||||
})
|
||||
|
||||
triggerKeyPress('esc')
|
||||
await user.keyboard('{Escape}')
|
||||
await waitFor(() => {
|
||||
expect(screen.queryByPlaceholderText('app.gotoAnything.searchPlaceholder')).not.toBeInTheDocument()
|
||||
})
|
||||
})
|
||||
|
||||
it('should toggle modal when pressing Ctrl+K twice', async () => {
|
||||
render(<GotoAnything />)
|
||||
renderGotoAnything(<GotoAnything />)
|
||||
|
||||
triggerKeyPress('ctrl.k')
|
||||
await waitFor(() => {
|
||||
@ -185,15 +196,16 @@ describe('GotoAnything', () => {
|
||||
})
|
||||
|
||||
it('should call onHide when modal closes', async () => {
|
||||
const user = userEvent.setup()
|
||||
const onHide = vi.fn()
|
||||
render(<GotoAnything onHide={onHide} />)
|
||||
renderGotoAnything(<GotoAnything onHide={onHide} />)
|
||||
|
||||
triggerKeyPress('ctrl.k')
|
||||
await waitFor(() => {
|
||||
expect(screen.getByPlaceholderText('app.gotoAnything.searchPlaceholder')).toBeInTheDocument()
|
||||
})
|
||||
|
||||
triggerKeyPress('esc')
|
||||
await user.keyboard('{Escape}')
|
||||
await waitFor(() => {
|
||||
expect(onHide).toHaveBeenCalled()
|
||||
})
|
||||
@ -201,7 +213,7 @@ describe('GotoAnything', () => {
|
||||
|
||||
it('should reset search query when modal opens', async () => {
|
||||
const user = userEvent.setup()
|
||||
render(<GotoAnything />)
|
||||
renderGotoAnything(<GotoAnything />)
|
||||
|
||||
triggerKeyPress('ctrl.k')
|
||||
await waitFor(() => {
|
||||
@ -211,7 +223,7 @@ describe('GotoAnything', () => {
|
||||
const input = screen.getByPlaceholderText('app.gotoAnything.searchPlaceholder')
|
||||
await user.type(input, 'test')
|
||||
|
||||
triggerKeyPress('esc')
|
||||
await user.keyboard('{Escape}')
|
||||
await waitFor(() => {
|
||||
expect(screen.queryByPlaceholderText('app.gotoAnything.searchPlaceholder')).not.toBeInTheDocument()
|
||||
})
|
||||
@ -242,7 +254,7 @@ describe('GotoAnything', () => {
|
||||
error: null,
|
||||
}
|
||||
|
||||
render(<GotoAnything />)
|
||||
renderGotoAnything(<GotoAnything />)
|
||||
triggerKeyPress('ctrl.k')
|
||||
|
||||
await waitFor(() => {
|
||||
@ -260,7 +272,7 @@ describe('GotoAnything', () => {
|
||||
|
||||
it('should clear selection when typing without prefix', async () => {
|
||||
const user = userEvent.setup()
|
||||
render(<GotoAnything />)
|
||||
renderGotoAnything(<GotoAnything />)
|
||||
triggerKeyPress('ctrl.k')
|
||||
|
||||
await waitFor(() => {
|
||||
@ -284,7 +296,7 @@ describe('GotoAnything', () => {
|
||||
error: null,
|
||||
}
|
||||
|
||||
render(<GotoAnything />)
|
||||
renderGotoAnything(<GotoAnything />)
|
||||
triggerKeyPress('ctrl.k')
|
||||
|
||||
await waitFor(() => {
|
||||
@ -308,7 +320,7 @@ describe('GotoAnything', () => {
|
||||
error: testError,
|
||||
}
|
||||
|
||||
render(<GotoAnything />)
|
||||
renderGotoAnything(<GotoAnything />)
|
||||
triggerKeyPress('ctrl.k')
|
||||
|
||||
await waitFor(() => {
|
||||
@ -322,7 +334,7 @@ describe('GotoAnything', () => {
|
||||
})
|
||||
|
||||
it('should show default state when no query', async () => {
|
||||
render(<GotoAnything />)
|
||||
renderGotoAnything(<GotoAnything />)
|
||||
triggerKeyPress('ctrl.k')
|
||||
|
||||
await waitFor(() => {
|
||||
@ -341,7 +353,7 @@ describe('GotoAnything', () => {
|
||||
error: null,
|
||||
}
|
||||
|
||||
render(<GotoAnything />)
|
||||
renderGotoAnything(<GotoAnything />)
|
||||
triggerKeyPress('ctrl.k')
|
||||
|
||||
await waitFor(() => {
|
||||
@ -376,7 +388,7 @@ describe('GotoAnything', () => {
|
||||
error: null,
|
||||
}
|
||||
|
||||
render(<GotoAnything />)
|
||||
renderGotoAnything(<GotoAnything />)
|
||||
triggerKeyPress('ctrl.k')
|
||||
|
||||
await waitFor(() => {
|
||||
@ -412,7 +424,7 @@ describe('GotoAnything', () => {
|
||||
error: null,
|
||||
}
|
||||
|
||||
render(<GotoAnything />)
|
||||
renderGotoAnything(<GotoAnything />)
|
||||
triggerKeyPress('ctrl.k')
|
||||
|
||||
await waitFor(() => {
|
||||
@ -453,7 +465,7 @@ describe('GotoAnything', () => {
|
||||
error: null,
|
||||
}
|
||||
|
||||
render(<GotoAnything />)
|
||||
renderGotoAnything(<GotoAnything />)
|
||||
triggerKeyPress('ctrl.k')
|
||||
|
||||
await waitFor(() => {
|
||||
@ -485,7 +497,7 @@ describe('GotoAnything', () => {
|
||||
isAvailable: () => true,
|
||||
}
|
||||
|
||||
render(<GotoAnything />)
|
||||
renderGotoAnything(<GotoAnything />)
|
||||
triggerKeyPress('ctrl.k')
|
||||
|
||||
await waitFor(() => {
|
||||
@ -508,7 +520,7 @@ describe('GotoAnything', () => {
|
||||
isAvailable: () => false,
|
||||
}
|
||||
|
||||
render(<GotoAnything />)
|
||||
renderGotoAnything(<GotoAnything />)
|
||||
triggerKeyPress('ctrl.k')
|
||||
|
||||
await waitFor(() => {
|
||||
@ -530,7 +542,7 @@ describe('GotoAnything', () => {
|
||||
execute: executeMock,
|
||||
}
|
||||
|
||||
render(<GotoAnything />)
|
||||
renderGotoAnything(<GotoAnything />)
|
||||
triggerKeyPress('ctrl.k')
|
||||
|
||||
await waitFor(() => {
|
||||
@ -552,7 +564,7 @@ describe('GotoAnything', () => {
|
||||
isAvailable: () => true,
|
||||
}
|
||||
|
||||
render(<GotoAnything />)
|
||||
renderGotoAnything(<GotoAnything />)
|
||||
triggerKeyPress('ctrl.k')
|
||||
|
||||
await waitFor(() => {
|
||||
@ -587,7 +599,7 @@ describe('GotoAnything', () => {
|
||||
error: null,
|
||||
}
|
||||
|
||||
render(<GotoAnything />)
|
||||
renderGotoAnything(<GotoAnything />)
|
||||
triggerKeyPress('ctrl.k')
|
||||
|
||||
await waitFor(() => {
|
||||
@ -620,7 +632,7 @@ describe('GotoAnything', () => {
|
||||
error: null,
|
||||
}
|
||||
|
||||
render(<GotoAnything />)
|
||||
renderGotoAnything(<GotoAnything />)
|
||||
triggerKeyPress('ctrl.k')
|
||||
|
||||
await waitFor(() => {
|
||||
|
||||
13
web/app/components/goto-anything/atoms.ts
Normal file
13
web/app/components/goto-anything/atoms.ts
Normal file
@ -0,0 +1,13 @@
|
||||
'use client'
|
||||
|
||||
import { atom, useAtomValue, useSetAtom } from 'jotai'
|
||||
|
||||
const gotoAnythingOpenAtom = atom(false)
|
||||
|
||||
export function useGotoAnythingOpen() {
|
||||
return useAtomValue(gotoAnythingOpenAtom)
|
||||
}
|
||||
|
||||
export function useSetGotoAnythingOpen() {
|
||||
return useSetAtom(gotoAnythingOpenAtom)
|
||||
}
|
||||
@ -1,4 +1,7 @@
|
||||
import type { ReactNode } from 'react'
|
||||
import { act, renderHook } from '@testing-library/react'
|
||||
import { createStore, Provider } from 'jotai'
|
||||
import { createElement } from 'react'
|
||||
import { useGotoAnythingModal } from '../use-goto-anything-modal'
|
||||
|
||||
type KeyPressEvent = {
|
||||
@ -31,6 +34,14 @@ const triggerHotkey = (hotkey: string, event: KeyPressEvent) => {
|
||||
registration?.handler(event)
|
||||
}
|
||||
|
||||
const renderGotoAnythingModalHook = () => {
|
||||
const store = createStore()
|
||||
const wrapper = ({ children }: { children: ReactNode }) =>
|
||||
createElement(Provider, { store }, children)
|
||||
|
||||
return renderHook(() => useGotoAnythingModal(), { wrapper })
|
||||
}
|
||||
|
||||
describe('useGotoAnythingModal', () => {
|
||||
beforeEach(() => {
|
||||
Object.keys(hotkeyHandlers).forEach(key => delete hotkeyHandlers[key])
|
||||
@ -42,92 +53,64 @@ describe('useGotoAnythingModal', () => {
|
||||
})
|
||||
|
||||
describe('initialization', () => {
|
||||
it('should initialize with show=false', () => {
|
||||
const { result } = renderHook(() => useGotoAnythingModal())
|
||||
expect(result.current.show).toBe(false)
|
||||
it('should initialize with open=false', () => {
|
||||
const { result } = renderGotoAnythingModalHook()
|
||||
expect(result.current.open).toBe(false)
|
||||
})
|
||||
|
||||
it('should provide inputRef initialized to null', () => {
|
||||
const { result } = renderHook(() => useGotoAnythingModal())
|
||||
const { result } = renderGotoAnythingModalHook()
|
||||
expect(result.current.inputRef).toBeDefined()
|
||||
expect(result.current.inputRef.current).toBe(null)
|
||||
})
|
||||
|
||||
it('should provide setShow function', () => {
|
||||
const { result } = renderHook(() => useGotoAnythingModal())
|
||||
expect(typeof result.current.setShow).toBe('function')
|
||||
})
|
||||
|
||||
it('should provide handleClose function', () => {
|
||||
const { result } = renderHook(() => useGotoAnythingModal())
|
||||
expect(typeof result.current.handleClose).toBe('function')
|
||||
it('should provide onOpenChange function', () => {
|
||||
const { result } = renderGotoAnythingModalHook()
|
||||
expect(typeof result.current.onOpenChange).toBe('function')
|
||||
})
|
||||
})
|
||||
|
||||
describe('keyboard shortcuts', () => {
|
||||
it('should toggle show state when Mod+K is triggered', () => {
|
||||
const { result } = renderHook(() => useGotoAnythingModal())
|
||||
it('should toggle open state when Mod+K is triggered', () => {
|
||||
const { result } = renderGotoAnythingModalHook()
|
||||
|
||||
expect(result.current.show).toBe(false)
|
||||
expect(result.current.open).toBe(false)
|
||||
|
||||
act(() => {
|
||||
triggerHotkey('Mod+K', { preventDefault: vi.fn(), target: document.body })
|
||||
})
|
||||
|
||||
expect(result.current.show).toBe(true)
|
||||
expect(result.current.open).toBe(true)
|
||||
})
|
||||
|
||||
it('should toggle back to closed when Mod+K is triggered twice', () => {
|
||||
const { result } = renderHook(() => useGotoAnythingModal())
|
||||
const { result } = renderGotoAnythingModalHook()
|
||||
|
||||
act(() => {
|
||||
triggerHotkey('Mod+K', { preventDefault: vi.fn(), target: document.body })
|
||||
})
|
||||
expect(result.current.show).toBe(true)
|
||||
expect(result.current.open).toBe(true)
|
||||
|
||||
act(() => {
|
||||
triggerHotkey('Mod+K', { preventDefault: vi.fn(), target: document.body })
|
||||
})
|
||||
expect(result.current.show).toBe(false)
|
||||
expect(result.current.open).toBe(false)
|
||||
})
|
||||
|
||||
it('should let the hotkey library ignore inputs when the modal is closed', () => {
|
||||
renderHook(() => useGotoAnythingModal())
|
||||
renderGotoAnythingModalHook()
|
||||
|
||||
expect(hotkeyHandlers['Mod+K']?.options?.ignoreInputs).toBe(true)
|
||||
})
|
||||
|
||||
it('should close modal when escape is pressed and modal is open', () => {
|
||||
const { result } = renderHook(() => useGotoAnythingModal())
|
||||
it('should not register a separate escape hotkey', () => {
|
||||
renderGotoAnythingModalHook()
|
||||
|
||||
act(() => {
|
||||
result.current.setShow(true)
|
||||
})
|
||||
expect(result.current.show).toBe(true)
|
||||
|
||||
act(() => {
|
||||
triggerHotkey('Escape', { preventDefault: vi.fn() })
|
||||
})
|
||||
|
||||
expect(result.current.show).toBe(false)
|
||||
})
|
||||
|
||||
it('should NOT do anything when escape is pressed and modal is already closed', () => {
|
||||
const { result } = renderHook(() => useGotoAnythingModal())
|
||||
|
||||
expect(result.current.show).toBe(false)
|
||||
|
||||
const preventDefaultMock = vi.fn()
|
||||
act(() => {
|
||||
triggerHotkey('Escape', { preventDefault: preventDefaultMock })
|
||||
})
|
||||
|
||||
expect(result.current.show).toBe(false)
|
||||
expect(preventDefaultMock).not.toHaveBeenCalled()
|
||||
expect(hotkeyHandlers.Escape).toBeUndefined()
|
||||
})
|
||||
|
||||
it('should call preventDefault when Mod+K is triggered', () => {
|
||||
renderHook(() => useGotoAnythingModal())
|
||||
renderGotoAnythingModalHook()
|
||||
|
||||
const preventDefaultMock = vi.fn()
|
||||
act(() => {
|
||||
@ -138,72 +121,29 @@ describe('useGotoAnythingModal', () => {
|
||||
})
|
||||
})
|
||||
|
||||
describe('handleClose', () => {
|
||||
it('should close modal when handleClose is called', () => {
|
||||
const { result } = renderHook(() => useGotoAnythingModal())
|
||||
|
||||
act(() => {
|
||||
result.current.setShow(true)
|
||||
})
|
||||
expect(result.current.show).toBe(true)
|
||||
|
||||
act(() => {
|
||||
result.current.handleClose()
|
||||
})
|
||||
|
||||
expect(result.current.show).toBe(false)
|
||||
})
|
||||
|
||||
it('should be safe to call handleClose when modal is already closed', () => {
|
||||
const { result } = renderHook(() => useGotoAnythingModal())
|
||||
|
||||
expect(result.current.show).toBe(false)
|
||||
|
||||
act(() => {
|
||||
result.current.handleClose()
|
||||
})
|
||||
|
||||
expect(result.current.show).toBe(false)
|
||||
})
|
||||
})
|
||||
|
||||
describe('setShow', () => {
|
||||
describe('onOpenChange', () => {
|
||||
it('should accept boolean value', () => {
|
||||
const { result } = renderHook(() => useGotoAnythingModal())
|
||||
const { result } = renderGotoAnythingModalHook()
|
||||
|
||||
act(() => {
|
||||
result.current.setShow(true)
|
||||
result.current.onOpenChange(true)
|
||||
})
|
||||
expect(result.current.show).toBe(true)
|
||||
expect(result.current.open).toBe(true)
|
||||
|
||||
act(() => {
|
||||
result.current.setShow(false)
|
||||
result.current.onOpenChange(false)
|
||||
})
|
||||
expect(result.current.show).toBe(false)
|
||||
})
|
||||
|
||||
it('should accept function value', () => {
|
||||
const { result } = renderHook(() => useGotoAnythingModal())
|
||||
|
||||
act(() => {
|
||||
result.current.setShow(prev => !prev)
|
||||
})
|
||||
expect(result.current.show).toBe(true)
|
||||
|
||||
act(() => {
|
||||
result.current.setShow(prev => !prev)
|
||||
})
|
||||
expect(result.current.show).toBe(false)
|
||||
expect(result.current.open).toBe(false)
|
||||
})
|
||||
})
|
||||
|
||||
describe('focus management', () => {
|
||||
it('should call requestAnimationFrame when modal opens', () => {
|
||||
const rafSpy = vi.spyOn(window, 'requestAnimationFrame')
|
||||
const { result } = renderHook(() => useGotoAnythingModal())
|
||||
const { result } = renderGotoAnythingModalHook()
|
||||
|
||||
act(() => {
|
||||
result.current.setShow(true)
|
||||
result.current.onOpenChange(true)
|
||||
})
|
||||
|
||||
expect(rafSpy).toHaveBeenCalled()
|
||||
@ -211,16 +151,16 @@ describe('useGotoAnythingModal', () => {
|
||||
})
|
||||
|
||||
it('should not call requestAnimationFrame when modal closes', () => {
|
||||
const { result } = renderHook(() => useGotoAnythingModal())
|
||||
const { result } = renderGotoAnythingModalHook()
|
||||
|
||||
act(() => {
|
||||
result.current.setShow(true)
|
||||
result.current.onOpenChange(true)
|
||||
})
|
||||
|
||||
const rafSpy = vi.spyOn(window, 'requestAnimationFrame')
|
||||
|
||||
act(() => {
|
||||
result.current.setShow(false)
|
||||
result.current.onOpenChange(false)
|
||||
})
|
||||
|
||||
expect(rafSpy).not.toHaveBeenCalled()
|
||||
@ -234,7 +174,7 @@ describe('useGotoAnythingModal', () => {
|
||||
return 0
|
||||
}
|
||||
|
||||
const { result } = renderHook(() => useGotoAnythingModal())
|
||||
const { result } = renderGotoAnythingModalHook()
|
||||
|
||||
const mockFocus = vi.fn()
|
||||
const mockInput = { focus: mockFocus } as unknown as HTMLInputElement
|
||||
@ -245,7 +185,7 @@ describe('useGotoAnythingModal', () => {
|
||||
})
|
||||
|
||||
act(() => {
|
||||
result.current.setShow(true)
|
||||
result.current.onOpenChange(true)
|
||||
})
|
||||
|
||||
expect(mockFocus).toHaveBeenCalled()
|
||||
@ -260,13 +200,13 @@ describe('useGotoAnythingModal', () => {
|
||||
return 0
|
||||
}
|
||||
|
||||
const { result } = renderHook(() => useGotoAnythingModal())
|
||||
const { result } = renderGotoAnythingModalHook()
|
||||
|
||||
act(() => {
|
||||
result.current.setShow(true)
|
||||
result.current.onOpenChange(true)
|
||||
})
|
||||
|
||||
expect(result.current.show).toBe(true)
|
||||
expect(result.current.open).toBe(true)
|
||||
|
||||
window.requestAnimationFrame = originalRAF
|
||||
})
|
||||
|
||||
@ -2,54 +2,38 @@
|
||||
|
||||
import type { RefObject } from 'react'
|
||||
import { useHotkey } from '@tanstack/react-hotkeys'
|
||||
import { useCallback, useEffect, useRef, useState } from 'react'
|
||||
import { useEffect, useRef } from 'react'
|
||||
import { useGotoAnythingOpen, useSetGotoAnythingOpen } from '../atoms'
|
||||
|
||||
type UseGotoAnythingModalReturn = {
|
||||
show: boolean
|
||||
setShow: (show: boolean | ((prev: boolean) => boolean)) => void
|
||||
open: boolean
|
||||
onOpenChange: (open: boolean) => void
|
||||
inputRef: RefObject<HTMLInputElement | null>
|
||||
handleClose: () => void
|
||||
}
|
||||
|
||||
export const useGotoAnythingModal = (): UseGotoAnythingModalReturn => {
|
||||
const [show, setShow] = useState<boolean>(false)
|
||||
const open = useGotoAnythingOpen()
|
||||
const setOpen = useSetGotoAnythingOpen()
|
||||
const inputRef = useRef<HTMLInputElement>(null)
|
||||
|
||||
// Handle keyboard shortcuts
|
||||
const handleToggleModal = useCallback((e: KeyboardEvent) => {
|
||||
useHotkey('Mod+K', (e) => {
|
||||
e.preventDefault()
|
||||
setShow(prev => !prev)
|
||||
}, [])
|
||||
|
||||
useHotkey('Mod+K', handleToggleModal, {
|
||||
ignoreInputs: !show,
|
||||
})
|
||||
|
||||
useHotkey('Escape', (e) => {
|
||||
e.preventDefault()
|
||||
setShow(false)
|
||||
setOpen(prev => !prev)
|
||||
}, {
|
||||
enabled: show,
|
||||
ignoreInputs: false,
|
||||
ignoreInputs: !open,
|
||||
})
|
||||
|
||||
const handleClose = useCallback(() => {
|
||||
setShow(false)
|
||||
}, [])
|
||||
|
||||
// Focus input when modal opens
|
||||
useEffect(() => {
|
||||
if (show) {
|
||||
if (open) {
|
||||
requestAnimationFrame(() => {
|
||||
inputRef.current?.focus()
|
||||
})
|
||||
}
|
||||
}, [show])
|
||||
}, [open])
|
||||
|
||||
return {
|
||||
show,
|
||||
setShow,
|
||||
open,
|
||||
onOpenChange: setOpen,
|
||||
inputRef,
|
||||
handleClose,
|
||||
}
|
||||
}
|
||||
|
||||
@ -44,26 +44,25 @@ const GotoAnythingDialog: FC<Props> = ({
|
||||
|
||||
// Modal state management
|
||||
const {
|
||||
show,
|
||||
setShow,
|
||||
open,
|
||||
onOpenChange,
|
||||
inputRef,
|
||||
handleClose: modalClose,
|
||||
} = useGotoAnythingModal()
|
||||
|
||||
// Reset state when modal opens/closes
|
||||
useEffect(() => {
|
||||
if (show && !prevShowRef.current) {
|
||||
if (open && !prevShowRef.current) {
|
||||
// Modal just opened - reset search
|
||||
setSearchQuery('')
|
||||
}
|
||||
else if (!show && prevShowRef.current) {
|
||||
else if (!open && prevShowRef.current) {
|
||||
// Modal just closed
|
||||
setSearchQuery('')
|
||||
clearSelection()
|
||||
onHide?.()
|
||||
}
|
||||
prevShowRef.current = show
|
||||
}, [show, setSearchQuery, clearSelection, onHide])
|
||||
prevShowRef.current = open
|
||||
}, [open, setSearchQuery, clearSelection, onHide])
|
||||
|
||||
// Results fetching and processing
|
||||
const {
|
||||
@ -94,7 +93,7 @@ const GotoAnythingDialog: FC<Props> = ({
|
||||
setSearchQuery,
|
||||
clearSelection,
|
||||
inputRef,
|
||||
onClose: () => setShow(false),
|
||||
onClose: () => onOpenChange(false),
|
||||
})
|
||||
|
||||
// Handle search input change
|
||||
@ -118,12 +117,12 @@ const GotoAnythingDialog: FC<Props> = ({
|
||||
if (handler?.mode === 'direct' && handler.execute && isAvailable) {
|
||||
e.preventDefault()
|
||||
handler.execute()
|
||||
setShow(false)
|
||||
onOpenChange(false)
|
||||
setSearchQuery('')
|
||||
}
|
||||
}
|
||||
}
|
||||
}, [searchQuery, setShow, setSearchQuery])
|
||||
}, [searchQuery, onOpenChange, setSearchQuery])
|
||||
|
||||
// Determine which empty state to show
|
||||
const emptyStateVariant = useMemo(() => {
|
||||
@ -144,11 +143,8 @@ const GotoAnythingDialog: FC<Props> = ({
|
||||
<>
|
||||
<SlashCommandProvider />
|
||||
<Dialog
|
||||
open={show}
|
||||
onOpenChange={(open) => {
|
||||
if (!open)
|
||||
modalClose()
|
||||
}}
|
||||
open={open}
|
||||
onOpenChange={onOpenChange}
|
||||
>
|
||||
<DialogContent className="w-[480px]! overflow-hidden p-0!">
|
||||
<Command
|
||||
|
||||
Loading…
Reference in New Issue
Block a user