Public Access
feat: add ShortAnswer and MathInput renderers
This commit is contained in:
1 parent
2a59f13870
commit
82ba53da0e
2 files changed
+75
No files matched your search
@@ -0,0 +1,45 @@
|
|||||||
|
import { useState, useEffect } from 'react'
|
||||||
|
import katex from 'katex'
|
||||||
|
import type { Question } from '../../types'
|
||||||
|
|
||||||
|
interface Props {
|
||||||
|
q: Question
|
||||||
|
value: string | null | undefined
|
||||||
|
onChange: (val: string) => void
|
||||||
|
locked?: boolean
|
||||||
|
}
|
||||||
|
|
||||||
|
// The KaTeX preview uses innerHTML: KaTeX controls all output, making this safe.
|
||||||
|
export default function MathInput({ value = '', onChange, locked }: Props) {
|
||||||
|
const [preview, setPreview] = useState('')
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (!value) { setPreview(''); return }
|
||||||
|
try {
|
||||||
|
setPreview(katex.renderToString(value, { throwOnError: false, displayMode: false }))
|
||||||
|
} catch {
|
||||||
|
setPreview('')
|
||||||
|
}
|
||||||
|
}, [value])
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className="answer-input-wrap">
|
||||||
|
<input
|
||||||
|
className="input mono"
|
||||||
|
type="text"
|
||||||
|
value={value ?? ''}
|
||||||
|
onChange={(e) => onChange(e.target.value)}
|
||||||
|
placeholder="LaTeX, e.g. 2x\ln x + x"
|
||||||
|
disabled={locked}
|
||||||
|
autoComplete="off"
|
||||||
|
spellCheck={false}
|
||||||
|
/>
|
||||||
|
<div className="math-preview">
|
||||||
|
<span className="math-preview-label">Preview</span>
|
||||||
|
{preview
|
||||||
|
? <span dangerouslySetInnerHTML={{ __html: preview }} />
|
||||||
|
: <span className="faint" style={{ fontSize: 13 }}>Live LaTeX preview appears here</span>}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
@@ -0,0 +1,30 @@
|
|||||||
|
import type { Question } from '../../types'
|
||||||
|
|
||||||
|
interface Props {
|
||||||
|
q: Question
|
||||||
|
value: string | null | undefined
|
||||||
|
onChange: (val: string) => void
|
||||||
|
locked?: boolean
|
||||||
|
}
|
||||||
|
|
||||||
|
export default function ShortAnswer({ q, value = '', onChange, locked }: Props) {
|
||||||
|
return (
|
||||||
|
<div className="answer-input-wrap">
|
||||||
|
<input
|
||||||
|
className="input"
|
||||||
|
type="text"
|
||||||
|
value={value ?? ''}
|
||||||
|
onChange={(e) => onChange(e.target.value)}
|
||||||
|
placeholder="Type your answer…"
|
||||||
|
disabled={locked}
|
||||||
|
autoComplete="off"
|
||||||
|
spellCheck={q.type === 'translation'}
|
||||||
|
/>
|
||||||
|
{q.type === 'translation' && q.targetLanguage && (
|
||||||
|
<div className="faint mono" style={{ fontSize: 11 }}>
|
||||||
|
Answer in {q.targetLanguage}
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
Reference in new issue
Block a user