Files
hyungi_document_server/frontend/src/lib/components/SourceTextPanel.svelte
T
Hyungi Ahn 475a542ea3 feat(study): iPad 손글씨 학습 세션 frontend (Phase 1)
PR-2: 자격증/어학 학습 세션 UI. iPad Safari + Apple Pencil 지원.

신규 컴포넌트:
- HandwriteCanvas — perfect-freehand + PointerEvents (압력/tilt) +
  palm rejection (pointerType==='pen') + DPR + touch-action:none +
  stroke 단위 undo/redo + 5초 idle / 5 stroke 자동 저장 +
  localStorage 백업 + PNG snapshot export
- StudyMetaEditor — study_type(certification/language) 토글, 자격증/어학
  분기 메타 입력, 어학 metadata.reading/meaning/unit_type
- SourceTextPanel — 원문 + 어학 메타 read-only 표시
- AssetList — 연결된 audio/video/scan/handwriting 표시 + 재생 + 연결/해제

라우트:
- /study → /study/write 리다이렉트
- /study/write — 도메인 토글 + 빠른 시작 폼 + 세션 목록
- /study/write/[id] — 좌측 메타/원문/asset, 우측 캔버스 (md+ 분할,
  모바일 위/아래)

Layout/Sidebar:
- 상단 nav 에 "공부" 추가 (메모와 뉴스 사이)
- Sidebar 메모/Inbox 섹션에 GraduationCap 아이콘 항목 추가

기타:
- frontend/package.json: perfect-freehand ^1.2.3 (MIT)
- THIRD_PARTY_LICENSES.md 신규 — perfect-freehand MIT 고지

플랜: ~/.claude/plans/scalable-chasing-stonebraker.md (PR-2)
신규 파일 lint:tokens 회귀 0 (기존 잔존 130 그대로).
2026-04-27 08:30:28 +09:00

63 lines
2.3 KiB
Svelte

<script lang="ts">
/**
* SourceTextPanel — 학습 세션의 원문/어학 메타 표시 (read-only).
*
* 캔버스 옆 또는 위쪽에 깔린다. 트레이싱 모드(mode='trace')에선 캔버스가 직접
* traceText 를 배경으로 그리므로 여기선 별도 표시 안 해도 되지만, 표시 보존.
*/
type Mode = 'copy' | 'trace' | 'blank-repeat' | 'dictation' | 'shadowing' | 'quiz' | 'flashcard';
interface Props {
sourceText?: string | null;
sourcePage?: number | null;
metadata?: Record<string, unknown> | null;
mode?: Mode;
studyType?: 'certification' | 'language';
}
let { sourceText, sourcePage, metadata, mode, studyType }: Props = $props();
let m = $derived((metadata ?? {}) as Record<string, string>);
</script>
<div class="flex flex-col gap-2 p-3 border-b border-default bg-surface">
{#if sourceText}
<div>
<div class="text-xs text-dim mb-1">
원문 {sourcePage ? `(p.${sourcePage})` : ''}
</div>
<div class="text-sm text-text whitespace-pre-wrap break-words">{sourceText}</div>
</div>
{:else}
<div class="text-xs text-dim">원문 미설정 — 메타 편집기에서 입력</div>
{/if}
{#if studyType === 'language' && metadata}
<div class="grid grid-cols-2 gap-x-3 gap-y-1 text-xs mt-1 pt-2 border-t border-default">
{#if m.reading}
<div><span class="text-dim">reading:</span> <span class="text-text">{m.reading}</span></div>
{/if}
{#if m.meaning}
<div><span class="text-dim">meaning:</span> <span class="text-text">{m.meaning}</span></div>
{/if}
{#if m.unit_type}
<div><span class="text-dim">unit:</span> <span class="text-text">{m.unit_type}</span></div>
{/if}
{#if m.romaji}
<div><span class="text-dim">romaji:</span> <span class="text-text">{m.romaji}</span></div>
{/if}
{#if m.example_sentence}
<div class="col-span-2">
<span class="text-dim">example:</span> <span class="text-text">{m.example_sentence}</span>
</div>
{/if}
</div>
{/if}
{#if mode === 'trace' && sourceText}
<div class="text-[10px] text-dim mt-1">
트레이싱 모드 — 캔버스 배경에 회색으로 깔린 원문 위에 펜으로 덮어쓰세요.
</div>
{/if}
</div>