// src/plugin/sidebar/SortMenuButton.tsx import { useCallback, type MouseEvent } from 'react' import { ArrowDownAZ, ArrowUpAZ, ArrowDown01, ArrowUp01, Clock, History, type LucideIcon, } from 'lucide-react' import { Menu } from '../obsidian-stubs' import { SORT_MODES, getSortModeMetadata, type SortMode } from './sort-mode' interface SortMenuButtonProps { currentMode: SortMode onChange: (mode: SortMode) => void } /** * Typed lookup table for the per-mode lucide icon. Direct named imports * keep tree-shaking working (no `import *` namespace retention) and * eliminate the stringly-typed `LucideIcons[name]` lookup that would * fail silently if upstream renamed a component. */ const ICON_BY_MODE: Record = { 'name-asc': ArrowDownAZ, 'name-desc': ArrowUpAZ, 'created-desc': ArrowDown01, 'created-asc': ArrowUp01, 'modified-desc': Clock, 'modified-asc': History, } /** * Header-action button that opens the Obsidian-compat Menu primitive with * the six sort modes. Used by FileTreeView and QuickAccessView via * `getHeaderActions()`. */ export function SortMenuButton({ currentMode, onChange }: SortMenuButtonProps) { const meta = getSortModeMetadata(currentMode) const Icon = ICON_BY_MODE[currentMode] const handleClick = useCallback( (e: MouseEvent) => { const menu = new Menu() for (const mode of SORT_MODES) { const m = getSortModeMetadata(mode) menu.addItem((item) => { item.setTitle(m.label) item.setIcon(m.obsidianIcon) item.setChecked(mode === currentMode) item.onClick(() => onChange(mode)) }) } menu.showAtPosition({ x: e.clientX, y: e.clientY }) }, [currentMode, onChange], ) return ( ) }