From 4938b25d12610ae119d7bb60e194b1685c1124c6 Mon Sep 17 00:00:00 2001 From: Hyungi Ahn Date: Wed, 8 Apr 2026 12:51:10 +0900 Subject: [PATCH] =?UTF-8?q?feat(ui):=20Phase=20E=20=E2=80=94=20PreviewPane?= =?UTF-8?q?l=20=EB=B6=84=ED=95=A0=20+=20detail=20inline=20+=20viewer=20Tab?= =?UTF-8?q?s?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit E.1 PreviewPanel 7개 editors/* 분할: - frontend/src/lib/components/editors/ 신설 (7개 컴포넌트): * NoteEditor — 사용자 메모 편집 * EditUrlEditor — 외부 편집 URL (Synology Drive 등) * TagsEditor — 태그 추가/삭제 * AIClassificationEditor — AI 분류 read-only 표시 (breadcrumb + document_type + confidence tone Badge + importance) * FileInfoView — 파일 메타 dl * ProcessingStatusView — 파이프라인 단계 status dl * DocumentDangerZone — 삭제 (ConfirmDialog 프리미티브 + id 고유화) - PreviewPanel.svelte 344줄 → 60줄 얇은 wrapper로 축소 (header + 7개 editors 조합만) - DocumentMetaRail (D.1)과 detail 페이지(E.2)가 동일 editors 재사용 E.2 detail 페이지 inline 편집: - documents/[id]/+page.svelte: 기존 read-only 메타 패널 전면 교체 - 오른쪽 aside = 7개 editors 스택 (Card 프리미티브로 감쌈) - 왼쪽 affordance row: Synology 편집 / 다운로드 / 링크 복사 - 삭제는 DocumentDangerZone이 담당 (ondelete → goto /documents) - loading/error 상태도 EmptyState 프리미티브로 교체 - marked/DOMPurify renderer 유지, viewer 분기 그대로 E.3 관련 문서 stub: - detail 페이지 오른쪽 aside에 "관련 문서" Card - EmptyState "추후 지원" + TODO(backend) GET /documents/{id}/related E.4 DocumentViewer Tabs 프리미티브: - Markdown 편집 모드의 편집/미리보기 토글 → Tabs 프리미티브 - 키보드 nav (←→/Home/End), ARIA tablist/tab/tabpanel 자동 적용 검증: - npm run build 통과 (editors/* 7개 모두 clean, $state 초기값 warning은 빈 문자열로 초기화하고 $effect로 doc 동기화해 해결) - npm run lint:tokens 204 → 168 (detail 페이지 + PreviewPanel 전면 token 기반 재작성으로 -36) Co-Authored-By: Claude Opus 4.6 (1M context) --- .../src/lib/components/DocumentViewer.svelte | 47 +-- .../src/lib/components/PreviewPanel.svelte | 356 ++---------------- .../editors/AIClassificationEditor.svelte | 43 +++ .../editors/DocumentDangerZone.svelte | 53 +++ .../components/editors/EditUrlEditor.svelte | 84 +++++ .../components/editors/FileInfoView.svelte | 52 +++ .../lib/components/editors/NoteEditor.svelte | 70 ++++ .../editors/ProcessingStatusView.svelte | 34 ++ .../lib/components/editors/TagsEditor.svelte | 101 +++++ .../src/routes/documents/[id]/+page.svelte | 326 +++++++++------- 10 files changed, 690 insertions(+), 476 deletions(-) create mode 100644 frontend/src/lib/components/editors/AIClassificationEditor.svelte create mode 100644 frontend/src/lib/components/editors/DocumentDangerZone.svelte create mode 100644 frontend/src/lib/components/editors/EditUrlEditor.svelte create mode 100644 frontend/src/lib/components/editors/FileInfoView.svelte create mode 100644 frontend/src/lib/components/editors/NoteEditor.svelte create mode 100644 frontend/src/lib/components/editors/ProcessingStatusView.svelte create mode 100644 frontend/src/lib/components/editors/TagsEditor.svelte diff --git a/frontend/src/lib/components/DocumentViewer.svelte b/frontend/src/lib/components/DocumentViewer.svelte index aaa60b9..1bc32e8 100644 --- a/frontend/src/lib/components/DocumentViewer.svelte +++ b/frontend/src/lib/components/DocumentViewer.svelte @@ -4,6 +4,7 @@ import { marked } from 'marked'; import DOMPurify from 'dompurify'; import { ExternalLink, Save, RefreshCw } from 'lucide-svelte'; + import Tabs from '$lib/components/ui/Tabs.svelte'; // marked + sanitize marked.use({ mangle: false, headerIds: false }); @@ -169,29 +170,31 @@ {:else if fullDoc} {#if viewerType === 'markdown'} {#if editMode} - +
-
- - -
- {#if editTab === 'edit'} - - {:else} -
- {@html renderMd(editContent)} -
- {/if} + + {#snippet children(activeId)} + {#if activeId === 'edit'} + + {:else} +
+ {@html renderMd(editContent)} +
+ {/if} + {/snippet} +
{:else}
diff --git a/frontend/src/lib/components/PreviewPanel.svelte b/frontend/src/lib/components/PreviewPanel.svelte index af5118c..14b30c9 100644 --- a/frontend/src/lib/components/PreviewPanel.svelte +++ b/frontend/src/lib/components/PreviewPanel.svelte @@ -1,344 +1,58 @@ -
{/if}