Extract 7 sub-modules under components/note-list/: - PinnedCard.tsx, RelationshipGroupSection.tsx, TrashWarningBanner.tsx - NoteListHeader.tsx, NoteListViews.tsx - noteListHooks.ts, noteListUtils.ts NoteList.tsx reduced from 579 → 95 lines. No behavior changes. All 2152 unit tests pass, 80%+ coverage, lint + typecheck clean. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
69 lines
3.1 KiB
TypeScript
69 lines
3.1 KiB
TypeScript
import { MagnifyingGlass, Plus, Trash } from '@phosphor-icons/react'
|
|
import type { VaultEntry } from '../../types'
|
|
import type { SortOption, SortDirection } from '../../utils/noteListHelpers'
|
|
import { Input } from '@/components/ui/input'
|
|
import { useDragRegion } from '../../hooks/useDragRegion'
|
|
import { SortDropdown } from '../SortDropdown'
|
|
|
|
export function NoteListHeader({ title, typeDocument, isEntityView, isTrashView, trashCount, listSort, listDirection, customProperties, sidebarCollapsed, searchVisible, search, onSortChange, onCreateNote, onOpenType, onToggleSearch, onSearchChange, onEmptyTrash }: {
|
|
title: string
|
|
typeDocument: VaultEntry | null
|
|
isEntityView: boolean
|
|
isTrashView: boolean
|
|
trashCount: number
|
|
listSort: SortOption
|
|
listDirection: SortDirection
|
|
customProperties: string[]
|
|
sidebarCollapsed?: boolean
|
|
searchVisible: boolean
|
|
search: string
|
|
onSortChange: (groupLabel: string, option: SortOption, direction: SortDirection) => void
|
|
onCreateNote: () => void
|
|
onOpenType: (entry: VaultEntry) => void
|
|
onToggleSearch: () => void
|
|
onSearchChange: (value: string) => void
|
|
onEmptyTrash?: () => void
|
|
}) {
|
|
const { onMouseDown: onDragMouseDown } = useDragRegion()
|
|
return (
|
|
<>
|
|
<div className="flex h-[52px] shrink-0 items-center justify-between border-b border-border px-4" onMouseDown={onDragMouseDown} style={{ cursor: 'default', paddingLeft: sidebarCollapsed ? 80 : undefined }}>
|
|
<h3
|
|
className="m-0 min-w-0 flex-1 truncate text-[14px] font-semibold"
|
|
style={typeDocument ? { cursor: 'pointer' } : undefined}
|
|
onClick={typeDocument ? () => onOpenType(typeDocument) : undefined}
|
|
data-testid={typeDocument ? 'type-header-link' : undefined}
|
|
>
|
|
{title}
|
|
</h3>
|
|
<div className="flex items-center gap-3" style={{ WebkitAppRegion: 'no-drag' } as React.CSSProperties}>
|
|
{!isEntityView && <SortDropdown groupLabel="__list__" current={listSort} direction={listDirection} customProperties={customProperties} onChange={onSortChange} />}
|
|
<button className="flex items-center text-muted-foreground transition-colors hover:text-foreground" onClick={onToggleSearch} title="Search notes">
|
|
<MagnifyingGlass size={16} />
|
|
</button>
|
|
{isTrashView && trashCount > 0 && (
|
|
<button
|
|
className="flex items-center text-destructive transition-colors hover:text-destructive/80"
|
|
onClick={onEmptyTrash}
|
|
title="Empty Trash"
|
|
data-testid="empty-trash-btn"
|
|
>
|
|
<Trash size={16} />
|
|
</button>
|
|
)}
|
|
{!isTrashView && (
|
|
<button className="flex items-center text-muted-foreground transition-colors hover:text-foreground" onClick={() => onCreateNote()} title="Create new note">
|
|
<Plus size={16} />
|
|
</button>
|
|
)}
|
|
</div>
|
|
</div>
|
|
{searchVisible && (
|
|
<div className="border-b border-border px-3 py-2">
|
|
<Input placeholder="Search notes..." value={search} onChange={(e) => onSearchChange(e.target.value)} className="h-8 text-[13px]" autoFocus />
|
|
</div>
|
|
)}
|
|
</>
|
|
)
|
|
}
|