feat: add basic file actions
This commit is contained in:
@@ -1,5 +1,5 @@
|
||||
import type { RefObject } from 'react'
|
||||
import { PencilSimple, Trash } from '@phosphor-icons/react'
|
||||
import { ClipboardText, FolderOpen, PencilSimple, Trash } from '@phosphor-icons/react'
|
||||
import { Button } from '@/components/ui/button'
|
||||
import { translate, type AppLocale } from '../../lib/i18n'
|
||||
|
||||
@@ -13,6 +13,8 @@ interface FolderContextMenuProps {
|
||||
menu: FolderContextMenuState | null
|
||||
menuRef: RefObject<HTMLDivElement | null>
|
||||
onDelete?: (folderPath: string) => void
|
||||
onReveal?: (folderPath: string) => void
|
||||
onCopyPath?: (folderPath: string) => void
|
||||
onRename: (folderPath: string) => void
|
||||
locale?: AppLocale
|
||||
}
|
||||
@@ -21,6 +23,8 @@ export function FolderContextMenu({
|
||||
menu,
|
||||
menuRef,
|
||||
onDelete,
|
||||
onReveal,
|
||||
onCopyPath,
|
||||
onRename,
|
||||
locale = 'en',
|
||||
}: FolderContextMenuProps) {
|
||||
@@ -33,6 +37,30 @@ export function FolderContextMenu({
|
||||
style={{ left: menu.x, top: menu.y, minWidth: 180 }}
|
||||
data-testid="folder-context-menu"
|
||||
>
|
||||
{onReveal && (
|
||||
<Button
|
||||
type="button"
|
||||
variant="ghost"
|
||||
className="h-auto w-full justify-start gap-2 px-2 py-1.5 text-sm"
|
||||
onClick={() => onReveal(menu.path)}
|
||||
data-testid="reveal-folder-menu-item"
|
||||
>
|
||||
<FolderOpen size={14} />
|
||||
{translate(locale, 'sidebar.action.revealFolderMenu')}
|
||||
</Button>
|
||||
)}
|
||||
{onCopyPath && (
|
||||
<Button
|
||||
type="button"
|
||||
variant="ghost"
|
||||
className="h-auto w-full justify-start gap-2 px-2 py-1.5 text-sm"
|
||||
onClick={() => onCopyPath(menu.path)}
|
||||
data-testid="copy-folder-path-menu-item"
|
||||
>
|
||||
<ClipboardText size={14} />
|
||||
{translate(locale, 'sidebar.action.copyFolderPathMenu')}
|
||||
</Button>
|
||||
)}
|
||||
<Button
|
||||
type="button"
|
||||
variant="ghost"
|
||||
|
||||
@@ -1,21 +1,19 @@
|
||||
import { useCallback, useEffect, useRef, useState, type MouseEvent as ReactMouseEvent } from 'react'
|
||||
import { useCallback, useEffect, useRef, useState, type MouseEvent as ReactMouseEvent, type RefObject } from 'react'
|
||||
import type { FolderNode } from '../../types'
|
||||
import type { FolderFileActions } from '../../hooks/useFileActions'
|
||||
import type { FolderContextMenuState } from './FolderContextMenu'
|
||||
|
||||
interface UseFolderContextMenuInput {
|
||||
onDeleteFolder?: (folderPath: string) => void
|
||||
folderFileActions?: FolderFileActions
|
||||
onStartRenameFolder?: (folderPath: string) => void
|
||||
}
|
||||
|
||||
export function useFolderContextMenu({
|
||||
onDeleteFolder,
|
||||
onStartRenameFolder,
|
||||
}: UseFolderContextMenuInput) {
|
||||
const [contextMenu, setContextMenu] = useState<FolderContextMenuState | null>(null)
|
||||
const menuRef = useRef<HTMLDivElement>(null)
|
||||
|
||||
const closeContextMenu = useCallback(() => setContextMenu(null), [])
|
||||
|
||||
function useContextMenuDismiss(
|
||||
contextMenu: FolderContextMenuState | null,
|
||||
menuRef: RefObject<HTMLDivElement | null>,
|
||||
closeContextMenu: () => void,
|
||||
) {
|
||||
useEffect(() => {
|
||||
if (!contextMenu) return
|
||||
|
||||
@@ -32,7 +30,19 @@ export function useFolderContextMenu({
|
||||
document.removeEventListener('mousedown', handleOutsideClick)
|
||||
document.removeEventListener('keydown', handleEscape)
|
||||
}
|
||||
}, [closeContextMenu, contextMenu])
|
||||
}, [closeContextMenu, contextMenu, menuRef])
|
||||
}
|
||||
|
||||
export function useFolderContextMenu({
|
||||
onDeleteFolder,
|
||||
folderFileActions,
|
||||
onStartRenameFolder,
|
||||
}: UseFolderContextMenuInput) {
|
||||
const [contextMenu, setContextMenu] = useState<FolderContextMenuState | null>(null)
|
||||
const menuRef = useRef<HTMLDivElement>(null)
|
||||
|
||||
const closeContextMenu = useCallback(() => setContextMenu(null), [])
|
||||
useContextMenuDismiss(contextMenu, menuRef, closeContextMenu)
|
||||
|
||||
const handleOpenMenu = useCallback((node: FolderNode, event: ReactMouseEvent<HTMLDivElement>) => {
|
||||
event.preventDefault()
|
||||
@@ -54,11 +64,23 @@ export function useFolderContextMenu({
|
||||
onDeleteFolder?.(folderPath)
|
||||
}, [closeContextMenu, onDeleteFolder])
|
||||
|
||||
const handleRevealFromMenu = useCallback((folderPath: string) => {
|
||||
closeContextMenu()
|
||||
folderFileActions?.revealFolder(folderPath)
|
||||
}, [closeContextMenu, folderFileActions])
|
||||
|
||||
const handleCopyPathFromMenu = useCallback((folderPath: string) => {
|
||||
closeContextMenu()
|
||||
folderFileActions?.copyFolderPath(folderPath)
|
||||
}, [closeContextMenu, folderFileActions])
|
||||
|
||||
return {
|
||||
closeContextMenu,
|
||||
contextMenu,
|
||||
handleCopyPathFromMenu,
|
||||
handleDeleteFromMenu,
|
||||
handleOpenMenu,
|
||||
handleRevealFromMenu,
|
||||
handleRenameFromMenu,
|
||||
menuRef,
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user