d3ro-voice/apps/desktop/src/renderer/components/meeting/DocumentTab.tsx
Yun Chan 082ed2ef02 feat(ui): Midnight Glass v2 마감 — lucide 아이콘 통일 + 몰입 패널 웨이브 + 팝업 정합
- @mui/icons-material → lucide-react 전환 (23파일, 잔여 0)
- VoiceRecordingPanel: 9바 DOM 웨이브 → GradientWave (canvas)
- Vanilla 팝업 5종 style.css v2 정합 (글래스 네이비/헤어라인/블루,
  CSS 변수 주입 구조 유지 — 테마 반응형 보존)
2026-07-21 20:20:32 +09:00

89 lines
2.3 KiB
TypeScript

// src/renderer/components/meeting/DocumentTab.tsx
// Phase 14.5: 문서 탭 — MarkdownEditor + 자동저장 + 내보내기
import { useCallback, useRef } from 'react'
import { Box } from '@mui/material'
import { Trash2 } from 'lucide-react'
import { MarkdownEditor } from './MarkdownEditor'
import { ExportMenu } from './ExportMenu'
import { PhysicalButton } from '@d3ro/ui/components/ds'
import { d3roPalette, d3roTypo } from '@d3ro/ui/theme'
import { useI18n } from '@d3ro/i18n'
import type { MeetingExportFormat } from '@d3ro/core/types'
interface DocumentTabDoc {
id: string
title: string
content: string
templateType: string
}
interface DocumentTabProps {
document: DocumentTabDoc
onContentChange: (content: string) => void
onExport: (format: MeetingExportFormat) => void
onDelete: () => void
}
const AUTOSAVE_DELAY = 500
export function DocumentTab({
document: doc,
onContentChange,
onExport,
onDelete,
}: DocumentTabProps): React.ReactElement {
const { t } = useI18n()
const timerRef = useRef<ReturnType<typeof setTimeout> | null>(null)
const handleChange = useCallback(
(content: string) => {
if (timerRef.current) clearTimeout(timerRef.current)
timerRef.current = setTimeout(() => {
onContentChange(content)
}, AUTOSAVE_DELAY)
},
[onContentChange],
)
return (
<Box
sx={{
display: 'flex',
flexDirection: 'column',
height: '100%',
}}
>
{/* 콘텐츠 편집기 */}
<Box sx={{ flex: 1, overflow: 'hidden', minHeight: 0 }}>
<MarkdownEditor
content={doc.content}
onChange={handleChange}
/>
</Box>
{/* 하단 액션 바 */}
<Box
sx={{
display: 'flex',
justifyContent: 'space-between',
alignItems: 'center',
mt: 1.5,
pt: 1.5,
borderTop: `1px solid ${d3roPalette.border.subtle}`,
}}
>
<ExportMenu onExport={onExport} />
<PhysicalButton
size="small"
color="error"
onClick={onDelete}
sx={{ height: 32, fontSize: d3roTypo.engrave.size }}
>
<Trash2 size={14} style={{ marginRight: 4 }} />
{t('common.delete')}
</PhysicalButton>
</Box>
</Box>
)
}