import { useEffect, useMemo, useState } from 'react'; import { Dialog, DialogContent, DialogDescription, DialogFooter, DialogHeader, DialogTitle, } from '@/components/ui/dialog'; import { Input } from '@/components/ui/input'; import { Button } from '@/components/ui/button'; import { Label } from '@/components/ui/label'; import { Switch } from '@/components/ui/switch'; import { CODE_BLOCK_LANGUAGES, DEFAULT_CODE_BLOCK_OPTIONS, loadCodeBlockPrefs, saveCodeBlockPrefs, type CodeBlockInsertOptions, } from '../../utils/codeBlockOptions'; interface Props { open: boolean; onOpenChange: (open: boolean) => void; /** 编辑已有代码块时的初始值;新建时用偏好 */ initial?: Partial | null; /** 是否处于已有代码块(显示「移除」) */ editing?: boolean; onConfirm: (opts: CodeBlockInsertOptions) => void; onRemove?: () => void; } /** 文章编辑器:插入 / 配置代码块 */ export function ArticleCodeBlockDialog({ open, onOpenChange, initial, editing = false, onConfirm, onRemove, }: Props) { const [language, setLanguage] = useState(DEFAULT_CODE_BLOCK_OPTIONS.language); const [lineNumbers, setLineNumbers] = useState(DEFAULT_CODE_BLOCK_OPTIONS.lineNumbers); const [collapsed, setCollapsed] = useState(DEFAULT_CODE_BLOCK_OPTIONS.collapsed); const [langQuery, setLangQuery] = useState(''); useEffect(() => { if (!open) return; const prefs = loadCodeBlockPrefs(); setLanguage(initial?.language ?? ''); setLineNumbers(initial?.lineNumbers ?? prefs.lineNumbers); setCollapsed(initial?.collapsed ?? prefs.collapsed); setLangQuery(''); }, [open, initial]); const filteredLangs = useMemo(() => { const q = langQuery.trim().toLowerCase(); if (!q) return CODE_BLOCK_LANGUAGES; return CODE_BLOCK_LANGUAGES.filter( l => l.id.includes(q) || l.label.toLowerCase().includes(q), ); }, [langQuery]); const handleConfirm = () => { const opts: CodeBlockInsertOptions = { language: language.trim().toLowerCase(), lineNumbers, collapsed, }; saveCodeBlockPrefs(opts); onConfirm(opts); onOpenChange(false); }; return ( {editing ? '代码块设置' : '插入代码块'} 选择语言与阅读展示。外观随站点亮/暗主题自动切换。源码模式会写成{' '} {'```js lines collapsed'} {' '}这类围栏,可直接手改。
setLangQuery(e.target.value)} autoFocus />
{filteredLangs.map(lang => { const active = language === lang.id; return ( ); })} {filteredLangs.length === 0 ? (

无匹配项。可直接使用下方自定义标识。

) : null}
setLanguage(e.target.value.trim().toLowerCase())} onKeyDown={e => { if (e.key === 'Enter') { e.preventDefault(); handleConfirm(); } }} />

阅读态在左侧标注行号

阅读时先收起;不足 5 行不显示折叠按钮

{editing && onRemove ? ( ) : null}
); }