返回 oh-my-ppt
FormulaInspector.tsx
根目录 / src / renderer / src / components / session-detail / element-inspector / FormulaInspector.tsx
1 import 'katex/dist/katex.min.css'
2
3 import { Sigma } from 'lucide-react'
4 import { useMemo } from 'react'
5 import { Checkbox } from '../../ui/Checkbox'
6 import { InspectorSection } from './InspectorSection'
7 import { renderFormulaToHtml } from './formulaEditUtils'
8 import type { ElementEditorProps } from './types'
9 import { useT } from '@renderer/i18n'
10
11 const FORMULA_FIELDS = ['formulaLatex', 'formulaHtml', 'formulaDisplayMode'] as const
12
13 export function FormulaInspector({ draft, onDraftChange }: ElementEditorProps): React.JSX.Element {
14 const t = useT()
15 const rendered = useMemo(
16 () => renderFormulaToHtml(draft.formulaLatex, draft.formulaDisplayMode),
17 [draft.formulaDisplayMode, draft.formulaLatex]
18 )
19
20 const updateFormula = (latex: string, displayMode: boolean, commit = false): void => {
21 const nextRendered = renderFormulaToHtml(latex, displayMode)
22 const nextDraft = {
23 ...draft,
24 formulaLatex: latex,
25 formulaDisplayMode: displayMode,
26 formulaHtml: nextRendered.html
27 }
28 onDraftChange(
29 nextDraft,
30 commit && nextRendered.html ? { commit: true, fields: [...FORMULA_FIELDS] } : undefined
31 )
32 }
33
34 return (
35 <InspectorSection
36 title={t('sessionDetail.formulaContent')}
37 icon={<Sigma className="h-3.5 w-3.5 text-[#7a875f]" />}
38 >
39 <textarea
40 value={draft.formulaLatex}
41 onChange={(event) => updateFormula(event.target.value, draft.formulaDisplayMode)}
42 onBlur={() => updateFormula(draft.formulaLatex, draft.formulaDisplayMode, true)}
43 onKeyDown={(event) => {
44 if ((event.metaKey || event.ctrlKey) && event.key === 'Enter') {
45 event.currentTarget.blur()
46 }
47 }}
48 className="min-h-[92px] w-full resize-y rounded-[9px] border border-[#d9cfbd]/72 bg-[#fffaf1]/92 px-2.5 py-2 font-mono text-[11px] leading-5 text-[#34402c] outline-none transition-colors placeholder:text-[#b1a58f] focus:border-[#9daf8a]"
49 placeholder="x = \frac{-b \pm \sqrt{b^2 - 4ac}}{2a}"
50 spellCheck={false}
51 />
52
53 <label className="mt-2 flex items-center gap-2 text-[11px] text-[#6f664f]">
54 <Checkbox
55 checked={draft.formulaDisplayMode}
56 onCheckedChange={(checked) =>
57 updateFormula(draft.formulaLatex, checked === true, true)
58 }
59 />
60 <span>{t('sessionDetail.formulaDisplayMode')}</span>
61 </label>
62
63 <div className="mt-3 rounded-[9px] border border-[#e1d6c4]/70 bg-white/64 px-2.5 py-2">
64 <div className="mb-1.5 text-[10px] font-semibold uppercase tracking-[0.12em] text-[#8a806b]">
65 {t('sessionDetail.formulaPreview')}
66 </div>
67 {rendered.html ? (
68 <div
69 className="overflow-x-auto text-[#0a0a0b]"
70 dangerouslySetInnerHTML={{ __html: rendered.html }}
71 />
72 ) : (
73 <p className="text-[11px] leading-5 text-[#a0977e]">
74 {rendered.error || t('sessionDetail.formulaPreviewEmpty')}
75 </p>
76 )}
77 </div>
78 </InspectorSection>
79 )
80 }
81
81 lines Plain Text