@mieweb/ui 0.7.0 → 0.7.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/CsvBlock-2A5VEDD3.cjs +15 -0
- package/dist/{CsvBlock-7K6XVRYO.cjs.map → CsvBlock-2A5VEDD3.cjs.map} +1 -1
- package/dist/CsvBlock-D6PWAJ5X.js +6 -0
- package/dist/{CsvBlock-AAV4QMSF.js.map → CsvBlock-D6PWAJ5X.js.map} +1 -1
- package/dist/HtmlPreviewBlock-PEHTJ6C3.js +6 -0
- package/dist/{HtmlPreviewBlock-DNINC7RW.js.map → HtmlPreviewBlock-PEHTJ6C3.js.map} +1 -1
- package/dist/HtmlPreviewBlock-SYXCV5RH.cjs +15 -0
- package/dist/{HtmlPreviewBlock-74XQF3KT.cjs.map → HtmlPreviewBlock-SYXCV5RH.cjs.map} +1 -1
- package/dist/MermaidBlock-7NK3AVK2.js +6 -0
- package/dist/{MermaidBlock-PKXGFGU6.js.map → MermaidBlock-7NK3AVK2.js.map} +1 -1
- package/dist/MermaidBlock-AFXNP5NK.cjs +15 -0
- package/dist/{MermaidBlock-R4U7IHSZ.cjs.map → MermaidBlock-AFXNP5NK.cjs.map} +1 -1
- package/dist/SurveyBlock-6KRNKFH5.cjs +15 -0
- package/dist/{SurveyBlock-E52I4PW3.cjs.map → SurveyBlock-6KRNKFH5.cjs.map} +1 -1
- package/dist/SurveyBlock-NNDGXGG4.js +6 -0
- package/dist/{SurveyBlock-IULSBG22.js.map → SurveyBlock-NNDGXGG4.js.map} +1 -1
- package/dist/chunk-6CGM5H4J.js +17 -0
- package/dist/chunk-6CGM5H4J.js.map +1 -0
- package/dist/{chunk-HRS6W74P.js → chunk-6D5F7EDM.js} +3 -3
- package/dist/{chunk-HRS6W74P.js.map → chunk-6D5F7EDM.js.map} +1 -1
- package/dist/{chunk-NAQ3ZALI.cjs → chunk-7VF6WO7H.cjs} +32 -16
- package/dist/chunk-7VF6WO7H.cjs.map +1 -0
- package/dist/{chunk-FGIIXD37.js → chunk-7WMSUXOQ.js} +3 -3
- package/dist/{chunk-FGIIXD37.js.map → chunk-7WMSUXOQ.js.map} +1 -1
- package/dist/{chunk-74NOFB34.cjs → chunk-BB4WQ4LV.cjs} +4 -4
- package/dist/{chunk-74NOFB34.cjs.map → chunk-BB4WQ4LV.cjs.map} +1 -1
- package/dist/{chunk-YD23ZGRU.cjs → chunk-BYUV3IZV.cjs} +16 -4
- package/dist/chunk-BYUV3IZV.cjs.map +1 -0
- package/dist/{chunk-UL3PQ7HL.cjs → chunk-CKD554XR.cjs} +12 -3
- package/dist/chunk-CKD554XR.cjs.map +1 -0
- package/dist/{chunk-FZQAF3WA.cjs → chunk-CVC4NWFA.cjs} +4 -4
- package/dist/{chunk-FZQAF3WA.cjs.map → chunk-CVC4NWFA.cjs.map} +1 -1
- package/dist/{chunk-UO3KEUYK.cjs → chunk-DG7KE4YJ.cjs} +3 -3
- package/dist/chunk-DG7KE4YJ.cjs.map +1 -0
- package/dist/{chunk-Y4ESBDQ5.cjs → chunk-FCBQP2U4.cjs} +36 -38
- package/dist/chunk-FCBQP2U4.cjs.map +1 -0
- package/dist/{chunk-CPJIOOBM.js → chunk-I2W24RHW.js} +3 -3
- package/dist/{chunk-CPJIOOBM.js.map → chunk-I2W24RHW.js.map} +1 -1
- package/dist/{chunk-LIH3IZYK.js → chunk-IHTRKWBG.js} +121 -42
- package/dist/chunk-IHTRKWBG.js.map +1 -0
- package/dist/{chunk-Y65SK5Y2.cjs → chunk-JCNPVK74.cjs} +21 -12
- package/dist/chunk-JCNPVK74.cjs.map +1 -0
- package/dist/{chunk-6RV7HQ4U.cjs → chunk-KBEKQMVY.cjs} +5 -5
- package/dist/{chunk-6RV7HQ4U.cjs.map → chunk-KBEKQMVY.cjs.map} +1 -1
- package/dist/{chunk-FGP64Z24.js → chunk-KOCTIB6U.js} +16 -4
- package/dist/chunk-KOCTIB6U.js.map +1 -0
- package/dist/{chunk-3TERETXH.js → chunk-LJ2ZWIX6.js} +28 -2
- package/dist/chunk-LJ2ZWIX6.js.map +1 -0
- package/dist/{chunk-35VBGVMB.js → chunk-MCCO4A23.js} +24 -8
- package/dist/chunk-MCCO4A23.js.map +1 -0
- package/dist/chunk-NUFUV43P.cjs +20 -0
- package/dist/chunk-NUFUV43P.cjs.map +1 -0
- package/dist/{chunk-NTYGCBCL.js → chunk-OOYEHBYJ.js} +36 -38
- package/dist/chunk-OOYEHBYJ.js.map +1 -0
- package/dist/{chunk-JQEY53SH.cjs → chunk-PFWHWIXS.cjs} +28 -2
- package/dist/chunk-PFWHWIXS.cjs.map +1 -0
- package/dist/{chunk-JTBQNOSL.cjs → chunk-PWHK7SWN.cjs} +6 -6
- package/dist/{chunk-JTBQNOSL.cjs.map → chunk-PWHK7SWN.cjs.map} +1 -1
- package/dist/{chunk-JC6Y3LGF.cjs → chunk-QUUFKGDF.cjs} +120 -41
- package/dist/chunk-QUUFKGDF.cjs.map +1 -0
- package/dist/{chunk-MHJMUKLA.js → chunk-RHYIFIT5.js} +12 -3
- package/dist/chunk-RHYIFIT5.js.map +1 -0
- package/dist/{chunk-FIWKHLWY.js → chunk-SEPYBAML.js} +3 -3
- package/dist/chunk-SEPYBAML.js.map +1 -0
- package/dist/{chunk-WGC3KOP7.js → chunk-T3RWXOCM.js} +3 -3
- package/dist/{chunk-WGC3KOP7.js.map → chunk-T3RWXOCM.js.map} +1 -1
- package/dist/{chunk-NCRYCG5G.js → chunk-UFYXU7KV.js} +3 -3
- package/dist/{chunk-NCRYCG5G.js.map → chunk-UFYXU7KV.js.map} +1 -1
- package/dist/{chunk-VO3NWSCQ.cjs → chunk-V25Z5GR6.cjs} +7 -7
- package/dist/{chunk-VO3NWSCQ.cjs.map → chunk-V25Z5GR6.cjs.map} +1 -1
- package/dist/{chunk-NSLR3B7K.js → chunk-XL7TTKHP.js} +21 -12
- package/dist/chunk-XL7TTKHP.js.map +1 -0
- package/dist/components/DateInput/index.cjs +3 -2
- package/dist/components/DateInput/index.d.cts +4 -0
- package/dist/components/DateInput/index.d.ts +4 -0
- package/dist/components/DateInput/index.js +2 -1
- package/dist/components/Markdown/index.cjs +15 -15
- package/dist/components/Markdown/index.css +1 -1
- package/dist/components/Markdown/index.css.map +1 -1
- package/dist/components/Markdown/index.js +6 -6
- package/dist/components/Markdown/styles.css +4 -1
- package/dist/components/MediaEditor/index.cjs +9 -9
- package/dist/components/MediaEditor/index.d.cts +2 -2
- package/dist/components/MediaEditor/index.d.ts +2 -2
- package/dist/components/MediaEditor/index.js +4 -4
- package/dist/components/MediaPlayer/index.cjs +4 -4
- package/dist/components/MediaPlayer/index.js +1 -1
- package/dist/components/SuperChat/plugins/index.cjs +3 -0
- package/dist/components/SuperChat/plugins/index.cjs.map +1 -1
- package/dist/components/SuperChat/plugins/index.js +3 -0
- package/dist/components/SuperChat/plugins/index.js.map +1 -1
- package/dist/components/TranscriptView/index.cjs +5 -5
- package/dist/components/TranscriptView/index.d.cts +2 -2
- package/dist/components/TranscriptView/index.d.ts +2 -2
- package/dist/components/TranscriptView/index.js +2 -2
- package/dist/esheet.cjs +5 -5
- package/dist/esheet.js +2 -2
- package/dist/hooks/index.cjs +10 -9
- package/dist/hooks/index.d.cts +2 -2
- package/dist/hooks/index.d.ts +2 -2
- package/dist/hooks/index.js +2 -1
- package/dist/index.cjs +82 -82
- package/dist/index.css +1 -1
- package/dist/index.css.map +1 -1
- package/dist/index.d.cts +4 -2
- package/dist/index.d.ts +4 -2
- package/dist/index.js +16 -16
- package/dist/styles.css +1 -1
- package/dist/tailwind-preset.cjs +4 -4
- package/dist/tailwind-preset.js +1 -1
- package/dist/{transcript-oaWqY3yr.d.ts → transcript-Cg7uSW-C.d.cts} +4 -1
- package/dist/{transcript-oaWqY3yr.d.cts → transcript-Cg7uSW-C.d.ts} +4 -1
- package/dist/{useTranscriptEdits-CWYnjbGP.d.ts → useTranscriptEdits-C2BbMU37.d.ts} +3 -2
- package/dist/{useTranscriptEdits-BUylQFg0.d.cts → useTranscriptEdits-Hy0Vm-H8.d.cts} +3 -2
- package/package.json +2 -1
- package/dist/CsvBlock-7K6XVRYO.cjs +0 -15
- package/dist/CsvBlock-AAV4QMSF.js +0 -6
- package/dist/HtmlPreviewBlock-74XQF3KT.cjs +0 -15
- package/dist/HtmlPreviewBlock-DNINC7RW.js +0 -6
- package/dist/MermaidBlock-PKXGFGU6.js +0 -6
- package/dist/MermaidBlock-R4U7IHSZ.cjs +0 -15
- package/dist/SurveyBlock-E52I4PW3.cjs +0 -15
- package/dist/SurveyBlock-IULSBG22.js +0 -6
- package/dist/chunk-35VBGVMB.js.map +0 -1
- package/dist/chunk-3TERETXH.js.map +0 -1
- package/dist/chunk-FGP64Z24.js.map +0 -1
- package/dist/chunk-FIWKHLWY.js.map +0 -1
- package/dist/chunk-J7KWQJOB.js +0 -14
- package/dist/chunk-J7KWQJOB.js.map +0 -1
- package/dist/chunk-JC6Y3LGF.cjs.map +0 -1
- package/dist/chunk-JQEY53SH.cjs.map +0 -1
- package/dist/chunk-LIH3IZYK.js.map +0 -1
- package/dist/chunk-MHJMUKLA.js.map +0 -1
- package/dist/chunk-NAQ3ZALI.cjs.map +0 -1
- package/dist/chunk-NSLR3B7K.js.map +0 -1
- package/dist/chunk-NTYGCBCL.js.map +0 -1
- package/dist/chunk-S7JQ3FV5.cjs +0 -16
- package/dist/chunk-S7JQ3FV5.cjs.map +0 -1
- package/dist/chunk-UL3PQ7HL.cjs.map +0 -1
- package/dist/chunk-UO3KEUYK.cjs.map +0 -1
- package/dist/chunk-Y4ESBDQ5.cjs.map +0 -1
- package/dist/chunk-Y65SK5Y2.cjs.map +0 -1
- package/dist/chunk-YD23ZGRU.cjs.map +0 -1
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/components/MediaEditor/FillerWordsModal.tsx","../src/components/MediaEditor/WordEditorModal.tsx","../src/components/MediaEditor/SilenceSettingsModal.tsx","../src/components/MediaEditor/SpeedMarkerMenu.tsx","../src/components/MediaEditor/ScriptPanel.tsx","../src/components/MediaEditor/MediaEditor.tsx"],"names":["React","React2","jsxs","jsx","React3","React4","React5","formatDuration"],"mappings":"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","file":"chunk-MCCO4A23.js","sourcesContent":["/**\n * FillerWordsModal — select filler words (and long silences) to mark deleted.\n *\n * Ported from pulseclip's TranscriptViewer for @mieweb/ui. Pure UI: match\n * counts/durations come in via props (see useTranscriptEdits.fillerAnalysis);\n * the selection is reported through onApply.\n */\n\nimport * as React from 'react';\nimport {\n Modal,\n ModalHeader,\n ModalTitle,\n ModalClose,\n ModalBody,\n ModalFooter,\n} from '../Modal';\nimport { Button } from '../Button';\nimport { Input } from '../Input';\nimport { Checkbox } from '../Checkbox';\nimport { Select } from '../Select';\nimport { DEFAULT_FILLER_WORDS } from '../../hooks/useTranscriptEdits';\nimport type { SilenceThresholdCount } from '../../hooks/useTranscriptEdits';\n\nexport interface FillerWordsModalProps {\n isOpen: boolean;\n onClose: () => void;\n /** Apply removal: selected filler words + optional silence threshold (seconds) */\n onApply: (\n fillerWords: string[],\n removeSilenceAboveSec: number | null\n ) => void;\n /** Occurrence count per normalized word */\n matchingCounts: Map<string, number>;\n /** Total duration (ms) per filler word */\n fillerDurations: Map<string, number>;\n /** Count and total duration of silences at each threshold */\n silenceCounts: SilenceThresholdCount[];\n /** Current total edited duration in ms */\n currentDurationMs: number;\n}\n\nconst SILENCE_THRESHOLD_OPTIONS = [0.3, 0.4, 0.5, 0.75, 1.0, 1.5, 2.0];\n\n/** Format duration in seconds or m:ss */\nfunction formatDuration(ms: number): string {\n const totalSeconds = Math.round(ms / 1000);\n if (totalSeconds < 90) {\n return `${totalSeconds}s`;\n }\n const minutes = Math.floor(totalSeconds / 60);\n const seconds = totalSeconds % 60;\n return `${minutes}:${String(seconds).padStart(2, '0')}`;\n}\n\n/** Modal for selecting filler words to remove from the edited transcript */\nexport const FillerWordsModal: React.FC<FillerWordsModalProps> = ({\n isOpen,\n onClose,\n onApply,\n matchingCounts,\n fillerDurations,\n silenceCounts,\n currentDurationMs,\n}) => {\n const [searchTerm, setSearchTerm] = React.useState('');\n const [selectedFillers, setSelectedFillers] = React.useState<Set<string>>(\n new Set(DEFAULT_FILLER_WORDS)\n );\n const [customWord, setCustomWord] = React.useState('');\n const [removeSilence, setRemoveSilence] = React.useState(false);\n const [silenceThreshold, setSilenceThreshold] = React.useState(0.4);\n\n // Filter filler words based on search, then sort by count (matches first)\n const filteredFillers = DEFAULT_FILLER_WORDS.filter((word) =>\n word.toLowerCase().includes(searchTerm.toLowerCase())\n ).sort((a, b) => {\n const countA = matchingCounts.get(a) || 0;\n const countB = matchingCounts.get(b) || 0;\n if (countB !== countA) return countB - countA;\n return a.localeCompare(b);\n });\n\n // Custom words that have been added, sorted by count\n const customFillers = Array.from(selectedFillers)\n .filter((word) => !DEFAULT_FILLER_WORDS.includes(word))\n .filter((word) => word.toLowerCase().includes(searchTerm.toLowerCase()))\n .sort((a, b) => {\n const countA = matchingCounts.get(a) || 0;\n const countB = matchingCounts.get(b) || 0;\n if (countB !== countA) return countB - countA;\n return a.localeCompare(b);\n });\n\n const toggleFiller = (word: string) => {\n setSelectedFillers((prev) => {\n const next = new Set(prev);\n if (next.has(word)) {\n next.delete(word);\n } else {\n next.add(word);\n }\n return next;\n });\n };\n\n const handleAddCustom = () => {\n const trimmed = customWord.trim().toLowerCase();\n if (trimmed && !selectedFillers.has(trimmed)) {\n setSelectedFillers((prev) => new Set([...prev, trimmed]));\n setCustomWord('');\n }\n };\n\n // Count and duration of silences that would be removed at the current threshold\n const silenceData = removeSilence\n ? silenceCounts.find((s) => s.threshold === silenceThreshold) || {\n count: 0,\n durationMs: 0,\n }\n : { count: 0, durationMs: 0 };\n const silenceRemovalCount = silenceData.count;\n const silenceDurationMs = silenceData.durationMs;\n\n const handleApply = () => {\n onApply(\n Array.from(selectedFillers),\n removeSilence ? silenceThreshold : null\n );\n onClose();\n };\n\n const selectAll = () => {\n setSelectedFillers(new Set([...DEFAULT_FILLER_WORDS, ...customFillers]));\n };\n\n const selectNone = () => {\n setSelectedFillers(new Set());\n };\n\n // Total matches (filler words + silences)\n const fillerMatches = Array.from(selectedFillers).reduce(\n (sum, word) => sum + (matchingCounts.get(word) || 0),\n 0\n );\n const totalMatches = fillerMatches + silenceRemovalCount;\n\n // Time saved from filler words + silences\n const fillerTimeSavedMs = Array.from(selectedFillers).reduce(\n (sum, word) => sum + (fillerDurations.get(word) || 0),\n 0\n );\n const totalTimeSavedMs = fillerTimeSavedMs + silenceDurationMs;\n const newDurationMs = currentDurationMs - totalTimeSavedMs;\n\n const renderFillerItem = (word: string, isCustom: boolean) => {\n const count = matchingCounts.get(word) || 0;\n return (\n <label\n key={word}\n className=\"hover:bg-muted flex cursor-pointer items-center gap-2 rounded-md px-1.5 py-1 text-sm transition-colors\"\n >\n <Checkbox\n size=\"sm\"\n checked={selectedFillers.has(word)}\n onChange={() => toggleFiller(word)}\n aria-label={`Remove \"${word}\"`}\n />\n <span className=\"text-foreground min-w-0 flex-1 truncate\">{word}</span>\n {count > 0 && (\n <span className=\"text-muted-foreground text-xs\">({count})</span>\n )}\n {isCustom && (\n <button\n type=\"button\"\n className=\"text-muted-foreground hover:bg-destructive/10 hover:text-destructive focus-visible:ring-ring rounded px-1 transition-colors focus-visible:ring-2 focus-visible:outline-none\"\n onClick={(e) => {\n e.preventDefault();\n setSelectedFillers((prev) => {\n const next = new Set(prev);\n next.delete(word);\n return next;\n });\n }}\n aria-label={`Remove ${word}`}\n >\n ×\n </button>\n )}\n </label>\n );\n };\n\n return (\n <Modal\n open={isOpen}\n onOpenChange={(open) => {\n if (!open) onClose();\n }}\n size=\"lg\"\n >\n <ModalHeader>\n <ModalTitle>Remove Filler Words</ModalTitle>\n <ModalClose aria-label=\"Close modal\" />\n </ModalHeader>\n\n <ModalBody className=\"flex flex-col gap-3\">\n <Input\n size=\"sm\"\n type=\"text\"\n placeholder=\"Search filler words...\"\n value={searchTerm}\n onChange={(e) => setSearchTerm(e.target.value)}\n aria-label=\"Search filler words\"\n />\n\n <div className=\"flex items-center gap-2\">\n <Button variant=\"ghost\" size=\"sm\" onClick={selectAll}>\n Select All\n </Button>\n <Button variant=\"ghost\" size=\"sm\" onClick={selectNone}>\n Select None\n </Button>\n </div>\n\n <div className=\"border-border bg-muted/40 flex flex-wrap items-center gap-2 rounded-lg border px-3 py-2\">\n <Checkbox\n size=\"sm\"\n label=\"Remove silences greater than\"\n checked={removeSilence}\n onChange={(e) => setRemoveSilence(e.target.checked)}\n />\n <div className=\"w-24\">\n <Select\n size=\"sm\"\n options={SILENCE_THRESHOLD_OPTIONS.map((t) => ({\n value: String(t),\n label: `${t}s`,\n }))}\n value={String(silenceThreshold)}\n onValueChange={(value) => setSilenceThreshold(parseFloat(value))}\n disabled={!removeSilence}\n aria-label=\"Silence threshold in seconds\"\n />\n </div>\n {removeSilence && silenceRemovalCount > 0 && (\n <span className=\"text-muted-foreground text-xs\">\n ({silenceRemovalCount} silences)\n </span>\n )}\n </div>\n\n <div className=\"border-border grid max-h-56 grid-cols-2 gap-x-3 gap-y-0.5 overflow-y-auto rounded-lg border p-2 sm:grid-cols-3\">\n {filteredFillers.map((word) => renderFillerItem(word, false))}\n {customFillers.map((word) => renderFillerItem(word, true))}\n </div>\n\n <div className=\"flex items-center gap-2\">\n <Input\n size=\"sm\"\n type=\"text\"\n placeholder=\"Add custom filler word...\"\n value={customWord}\n onChange={(e) => setCustomWord(e.target.value)}\n onKeyDown={(e) => {\n if (e.key === 'Enter') {\n e.preventDefault();\n handleAddCustom();\n }\n }}\n aria-label=\"Add custom filler word\"\n />\n <Button\n variant=\"secondary\"\n size=\"sm\"\n onClick={handleAddCustom}\n disabled={!customWord.trim()}\n >\n Add\n </Button>\n </div>\n </ModalBody>\n\n <ModalFooter className=\"justify-between\">\n <span className=\"text-muted-foreground text-sm\">\n {totalMatches} items • saves {formatDuration(totalTimeSavedMs)} →{' '}\n {formatDuration(newDurationMs)}\n </span>\n <div className=\"flex items-center gap-2\">\n <Button variant=\"secondary\" size=\"sm\" onClick={onClose}>\n Cancel\n </Button>\n <Button\n variant=\"primary\"\n size=\"sm\"\n onClick={handleApply}\n disabled={totalMatches === 0}\n >\n Mark as Deleted ({totalMatches})\n </Button>\n </div>\n </ModalFooter>\n </Modal>\n );\n};\n\nFillerWordsModal.displayName = 'FillerWordsModal';\n","/**\n * WordEditorModal — edit a word's text or split a silence into segments.\n *\n * Ported from pulseclip's TranscriptViewer for @mieweb/ui. For silences,\n * space-separated durations (e.g. \"1 1 4 1\") split the silence; the\n * remainder becomes the final segment.\n */\n\nimport * as React from 'react';\nimport {\n Modal,\n ModalHeader,\n ModalTitle,\n ModalClose,\n ModalBody,\n ModalFooter,\n} from '../Modal';\nimport { Button } from '../Button';\nimport { Input } from '../Input';\nimport { isSilenceType } from '../TranscriptView/transcript';\nimport type { EditableWord } from '../TranscriptView/transcript';\n\nexport interface WordEditorModalProps {\n isOpen: boolean;\n editableWord: EditableWord | null;\n onClose: () => void;\n /** Save a new text for the word */\n onSave: (newText: string) => void;\n /** Split a silence into segments with the given durations (seconds) */\n onSplitSilence: (durations: number[]) => void;\n /** Toggle the word's deleted state */\n onDelete: () => void;\n}\n\ninterface SilenceSplitResult {\n durations: number[];\n remainder: number;\n error?: string;\n}\n\n/**\n * Modal for editing a word or splitting a silence.\n * For silences, enter space-separated durations (e.g., \"1 1 4 1\") to split.\n */\nexport const WordEditorModal: React.FC<WordEditorModalProps> = ({\n isOpen,\n editableWord,\n onClose,\n onSave,\n onSplitSilence,\n onDelete,\n}) => {\n const [inputValue, setInputValue] = React.useState('');\n const [error, setError] = React.useState<string | null>(null);\n const inputRef = React.useRef<HTMLInputElement>(null);\n\n const isSilence = isSilenceType(editableWord?.word.wordType);\n const durationMs = editableWord\n ? editableWord.word.endMs - editableWord.word.startMs\n : 0;\n const durationSec = durationMs / 1000;\n\n // Reset input when the modal opens\n React.useEffect(() => {\n if (isOpen && editableWord) {\n if (isSilence) {\n setInputValue('');\n } else {\n setInputValue(editableWord.word.text);\n }\n setError(null);\n // Focus input after a short delay so it wins over the modal's focus trap\n setTimeout(() => inputRef.current?.focus(), 50);\n }\n }, [isOpen, editableWord, isSilence]);\n\n // Parse silence split input (pure function, no side effects)\n const parseSilenceSplit = (input: string): SilenceSplitResult | null => {\n const trimmed = input.trim();\n if (!trimmed) return null;\n\n const parts = trimmed.split(/\\s+/);\n const durations: number[] = [];\n let total = 0;\n\n for (const part of parts) {\n const num = parseFloat(part);\n if (isNaN(num) || num <= 0) {\n return {\n durations: [],\n remainder: 0,\n error: `Invalid number: \"${part}\"`,\n };\n }\n durations.push(num);\n total += num;\n }\n\n if (total >= durationSec) {\n return {\n durations: [],\n remainder: 0,\n error: `Total (${total.toFixed(1)}s) exceeds silence duration (${durationSec.toFixed(1)}s)`,\n };\n }\n\n const remainder = durationSec - total;\n return { durations, remainder };\n };\n\n const handleApply = () => {\n if (isSilence) {\n const parsed = parseSilenceSplit(inputValue);\n if (parsed?.error) {\n setError(parsed.error);\n return;\n }\n if (parsed && parsed.durations.length > 0) {\n // Add the remainder as the final segment\n const allDurations = [...parsed.durations, parsed.remainder];\n onSplitSilence(allDurations);\n onClose();\n }\n } else {\n const trimmed = inputValue.trim();\n if (trimmed && trimmed !== editableWord?.word.text) {\n onSave(trimmed);\n }\n onClose();\n }\n };\n\n const handleKeyDown = (e: React.KeyboardEvent) => {\n if (e.key === 'Enter') {\n e.preventDefault();\n handleApply();\n }\n };\n\n // Preview for silence splitting\n const preview = isSilence ? parseSilenceSplit(inputValue) : null;\n\n const applyDisabled = isSilence\n ? !inputValue.trim() ||\n !!preview?.error ||\n !preview ||\n preview.durations.length === 0\n : !inputValue.trim();\n\n return (\n <Modal\n open={isOpen && editableWord !== null}\n onOpenChange={(open) => {\n if (!open) onClose();\n }}\n size=\"md\"\n >\n <ModalHeader>\n <ModalTitle>{isSilence ? 'Split Silence' : 'Edit Word'}</ModalTitle>\n <ModalClose aria-label=\"Close editor\" />\n </ModalHeader>\n\n <ModalBody className=\"flex flex-col gap-2\">\n {isSilence ? (\n <>\n <p className=\"text-foreground m-0 text-sm\">\n Silence duration:{' '}\n <strong className=\"font-semibold\">\n {durationSec.toFixed(1)}s\n </strong>\n </p>\n <p className=\"text-muted-foreground m-0 text-xs\">\n Enter space-separated durations to split (e.g., "1 1 4\n 1")\n </p>\n <Input\n ref={inputRef}\n type=\"text\"\n value={inputValue}\n onChange={(e) => {\n setInputValue(e.target.value);\n setError(null);\n }}\n onKeyDown={handleKeyDown}\n placeholder=\"1 2 3...\"\n aria-label=\"Split durations\"\n />\n {error && (\n <p className=\"text-destructive m-0 text-sm\" role=\"alert\">\n {error}\n </p>\n )}\n {preview &&\n !preview.error &&\n preview.durations.length > 0 &&\n !error && (\n <p className=\"text-muted-foreground m-0 text-sm\">\n Preview:{' '}\n {[...preview.durations, preview.remainder]\n .map((d) => `[${d.toFixed(1)}s]`)\n .join(' ')}\n </p>\n )}\n {preview?.error && !error && (\n <p className=\"text-destructive m-0 text-sm\" role=\"alert\">\n {preview.error}\n </p>\n )}\n </>\n ) : (\n <>\n <p className=\"text-foreground m-0 text-sm\">Edit the word text:</p>\n <Input\n ref={inputRef}\n type=\"text\"\n value={inputValue}\n onChange={(e) => setInputValue(e.target.value)}\n onKeyDown={handleKeyDown}\n aria-label=\"Word text\"\n />\n </>\n )}\n </ModalBody>\n\n <ModalFooter className=\"justify-between\">\n <Button\n variant={editableWord?.deleted ? 'secondary' : 'danger'}\n size=\"sm\"\n onClick={onDelete}\n >\n {editableWord?.deleted ? 'Restore' : 'Delete'}\n </Button>\n <div className=\"flex items-center gap-2\">\n <Button variant=\"secondary\" size=\"sm\" onClick={onClose}>\n Cancel\n </Button>\n <Button\n variant=\"primary\"\n size=\"sm\"\n onClick={handleApply}\n disabled={applyDisabled}\n >\n {isSilence ? 'Split' : 'Save'}\n </Button>\n </div>\n </ModalFooter>\n </Modal>\n );\n};\n\nWordEditorModal.displayName = 'WordEditorModal';\n","/**\n * SilenceSettingsModal — configure silence detection thresholds.\n *\n * Ported from pulseclip's TranscriptViewer for @mieweb/ui. The paragraph\n * break threshold is clamped to be >= the minimum silence duration.\n */\n\nimport * as React from 'react';\nimport {\n Modal,\n ModalHeader,\n ModalTitle,\n ModalClose,\n ModalBody,\n ModalFooter,\n} from '../Modal';\nimport { Button } from '../Button';\nimport { Slider } from '../Slider';\n\nexport interface SilenceSettingsModalProps {\n isOpen: boolean;\n onClose: () => void;\n /** Current minimum silence duration (ms) */\n minSilenceMs: number;\n /** Current paragraph break threshold (ms) */\n nlSilenceMs: number;\n /** Apply new thresholds (both in ms) */\n onApply: (minSilenceMs: number, nlSilenceMs: number) => void;\n}\n\n/** Modal for configuring silence detection settings */\nexport const SilenceSettingsModal: React.FC<SilenceSettingsModalProps> = ({\n isOpen,\n onClose,\n minSilenceMs,\n nlSilenceMs,\n onApply,\n}) => {\n const [threshold, setThreshold] = React.useState(minSilenceMs / 1000);\n const [nlThreshold, setNlThreshold] = React.useState(nlSilenceMs / 1000);\n\n // Reset when the modal opens\n React.useEffect(() => {\n if (isOpen) {\n setThreshold(minSilenceMs / 1000);\n setNlThreshold(nlSilenceMs / 1000);\n }\n }, [isOpen, minSilenceMs, nlSilenceMs]);\n\n const handleApply = () => {\n // Ensure nlThreshold is always >= threshold\n const finalNlThreshold = Math.max(nlThreshold, threshold);\n onApply(Math.round(threshold * 1000), Math.round(finalNlThreshold * 1000));\n onClose();\n };\n\n // Auto-adjust newline threshold if it would be less than the min threshold\n const handleThresholdChange = (value: number) => {\n setThreshold(value);\n if (nlThreshold < value) {\n setNlThreshold(value);\n }\n };\n\n const formatSeconds = (v: number) => `${v.toFixed(1)}s`;\n\n return (\n <Modal\n open={isOpen}\n onOpenChange={(open) => {\n if (!open) onClose();\n }}\n size=\"md\"\n >\n <ModalHeader>\n <ModalTitle>Silence Settings</ModalTitle>\n <ModalClose aria-label=\"Close modal\" />\n </ModalHeader>\n\n <ModalBody className=\"flex flex-col gap-6\">\n <div className=\"flex flex-col gap-1\">\n <Slider\n label=\"Minimum silence duration\"\n min={0.1}\n max={2}\n step={0.1}\n value={threshold}\n onValueChange={handleThresholdChange}\n showValue\n formatValue={formatSeconds}\n aria-label=\"Minimum silence duration\"\n />\n <p className=\"text-muted-foreground m-0 text-xs\">\n Gaps shorter than this will not be shown as silences.\n </p>\n </div>\n\n <div className=\"flex flex-col gap-1\">\n <Slider\n label=\"Paragraph break threshold\"\n min={threshold}\n max={5}\n step={0.1}\n value={nlThreshold}\n onValueChange={setNlThreshold}\n showValue\n formatValue={formatSeconds}\n aria-label=\"Paragraph break threshold\"\n />\n <p className=\"text-muted-foreground m-0 text-xs\">\n Silences longer than this will create paragraph breaks.\n </p>\n </div>\n </ModalBody>\n\n <ModalFooter>\n <Button variant=\"secondary\" size=\"sm\" onClick={onClose}>\n Cancel\n </Button>\n <Button variant=\"primary\" size=\"sm\" onClick={handleApply}>\n Apply\n </Button>\n </ModalFooter>\n </Modal>\n );\n};\n\nSilenceSettingsModal.displayName = 'SilenceSettingsModal';\n","/**\n * SpeedMarkerMenu — context-menu popup for setting per-word speed markers.\n *\n * Ported from pulseclip's TranscriptViewer for @mieweb/ui. Hand-built (plain\n * elements + tokens): a positioned context menu has no @mieweb/ui primitive.\n */\n\nimport * as React from 'react';\nimport type { PlaybackSpeed, SpeedMarker } from '../TranscriptView/transcript';\nimport { PLAYBACK_SPEEDS } from '../TranscriptView/transcript';\n\nexport interface SpeedMarkerMenuProps {\n isOpen: boolean;\n /** Viewport coordinates for the menu (already clamped by the caller) */\n position: { x: number; y: number } | null;\n /** The edited-word index the menu applies to */\n wordIndex: number | null;\n /** Existing marker at that word, if any */\n currentMarker: SpeedMarker | undefined;\n defaultSpeed: PlaybackSpeed;\n onSetSpeed: (speed: PlaybackSpeed) => void;\n onRemoveMarker: () => void;\n onClose: () => void;\n}\n\n/** Popup menu for setting speed markers on a word */\nexport const SpeedMarkerMenu: React.FC<SpeedMarkerMenuProps> = ({\n isOpen,\n position,\n currentMarker,\n defaultSpeed,\n onSetSpeed,\n onRemoveMarker,\n onClose,\n}) => {\n const menuRef = React.useRef<HTMLDivElement>(null);\n\n // Close on escape or click outside\n React.useEffect(() => {\n const handleKeyDown = (e: KeyboardEvent) => {\n if (e.key === 'Escape') onClose();\n };\n const handleClickOutside = (e: MouseEvent) => {\n if (menuRef.current && !menuRef.current.contains(e.target as Node)) {\n onClose();\n }\n };\n if (isOpen) {\n document.addEventListener('keydown', handleKeyDown);\n document.addEventListener('mousedown', handleClickOutside);\n return () => {\n document.removeEventListener('keydown', handleKeyDown);\n document.removeEventListener('mousedown', handleClickOutside);\n };\n }\n }, [isOpen, onClose]);\n\n if (!isOpen || !position) return null;\n\n return (\n <div\n ref={menuRef}\n className=\"border-border bg-card text-card-foreground fixed z-50 min-w-36 overflow-hidden rounded-lg border shadow-lg\"\n style={{ left: position.x, top: position.y }}\n role=\"menu\"\n aria-label=\"Set speed marker\"\n >\n <div className=\"border-border text-muted-foreground border-b px-3 py-1.5 text-xs font-semibold\">\n Set Speed Marker\n </div>\n <div className=\"flex flex-col p-1\">\n {PLAYBACK_SPEEDS.map((speed) => {\n const isActive = currentMarker?.speed === speed;\n const isDefault = speed === defaultSpeed && !currentMarker;\n return (\n <button\n key={speed}\n type=\"button\"\n className={`focus-visible:ring-ring flex items-center justify-between gap-2 rounded-md px-2.5 py-1 text-left text-sm transition-colors focus-visible:ring-2 focus-visible:outline-none ${\n isActive\n ? 'bg-primary-600 font-medium text-white'\n : 'text-foreground hover:bg-muted'\n }`}\n onClick={() => {\n onSetSpeed(speed);\n onClose();\n }}\n role=\"menuitem\"\n >\n {speed}x\n {isDefault && (\n <span className=\"text-muted-foreground text-xs\">default</span>\n )}\n </button>\n );\n })}\n </div>\n {currentMarker && (\n <button\n type=\"button\"\n className=\"border-border text-destructive hover:bg-destructive/10 focus-visible:ring-ring w-full border-t px-2.5 py-1.5 text-left text-sm transition-colors focus-visible:ring-2 focus-visible:outline-none\"\n onClick={() => {\n onRemoveMarker();\n onClose();\n }}\n role=\"menuitem\"\n >\n Remove Marker\n </button>\n )}\n </div>\n );\n};\n\nSpeedMarkerMenu.displayName = 'SpeedMarkerMenu';\n","/**\n * ScriptPanel — the transcript \"script\" as editable YAML/JSON, side by side\n * with the editor.\n *\n * Two sources: \"Editor\" is the live edit state (EditableWord[], remapped as\n * you edit) and can be edited as text and applied back; \"Original\" is the\n * canonical transcript (immutable, read-only). The panel live-follows the\n * editor until you start typing; Apply parses + validates and replaces the\n * edit state (undo-safe via useTranscriptEdits.replaceEditedWords).\n *\n * js-yaml is loaded lazily on first use (same pattern as Markdown's\n * SurveyBlock) so it stays out of the MediaEditor bundle.\n */\n\nimport * as React from 'react';\nimport { Button } from '../Button';\nimport type {\n Transcript,\n EditableWord,\n TranscriptWord,\n} from '../TranscriptView/transcript';\n\nlet yamlPromise: Promise<typeof import('js-yaml')> | null = null;\nfunction loadYaml() {\n yamlPromise ??= import(/* @vite-ignore */ 'js-yaml');\n return yamlPromise;\n}\n\nexport interface ScriptPanelProps {\n /** The canonical transcript (read-only source) */\n transcript: Transcript;\n /** The live edit state (editable source) */\n editedWords: EditableWord[];\n /** Apply parsed script back into the editor */\n onApply: (words: EditableWord[]) => void;\n /** Close the panel */\n onClose: () => void;\n className?: string;\n}\n\ntype ScriptSource = 'editor' | 'original';\ntype ScriptFormat = 'yaml' | 'json';\n\n/** Parse + validate script text into EditableWord[]; throws with a readable message. */\nasync function parseScript(\n text: string,\n format: ScriptFormat\n): Promise<EditableWord[]> {\n let data: unknown;\n if (format === 'json') {\n data = JSON.parse(text);\n } else {\n const yaml = await loadYaml();\n data = yaml.load(text);\n }\n if (!Array.isArray(data)) {\n throw new Error('Script must be a list of word entries.');\n }\n return data.map((raw, i) => {\n const ew = raw as {\n originalIndex?: unknown;\n deleted?: unknown;\n inserted?: unknown;\n word?: Record<string, unknown>;\n };\n const w = ew.word;\n if (\n !w ||\n typeof w.text !== 'string' ||\n typeof w.startMs !== 'number' ||\n typeof w.endMs !== 'number'\n ) {\n throw new Error(\n `Entry ${i + 1}: each entry needs word.text, word.startMs and word.endMs.`\n );\n }\n if (\n w.wordType !== undefined &&\n w.wordType !== 'word' &&\n w.wordType !== 'silence' &&\n w.wordType !== 'silence-newline'\n ) {\n throw new Error(\n `Entry ${i + 1}: wordType must be 'word', 'silence' or 'silence-newline'.`\n );\n }\n const word: TranscriptWord = {\n text: w.text,\n startMs: w.startMs,\n endMs: w.endMs,\n ...(typeof w.wordType === 'string'\n ? { wordType: w.wordType as TranscriptWord['wordType'] }\n : {}),\n ...(typeof w.speakerId === 'string' ? { speakerId: w.speakerId } : {}),\n };\n return {\n originalIndex:\n typeof ew.originalIndex === 'number' ? ew.originalIndex : -1,\n deleted: Boolean(ew.deleted),\n ...(ew.inserted !== undefined ? { inserted: Boolean(ew.inserted) } : {}),\n word,\n } as EditableWord;\n });\n}\n\nexport const ScriptPanel: React.FC<ScriptPanelProps> = ({\n transcript,\n editedWords,\n onApply,\n onClose,\n className,\n}) => {\n const [source, setSource] = React.useState<ScriptSource>('editor');\n const [format, setFormat] = React.useState<ScriptFormat>('yaml');\n const [text, setText] = React.useState('');\n const [dirty, setDirty] = React.useState(false);\n const [error, setError] = React.useState<string | null>(null);\n\n const readOnly = source === 'original';\n\n // Live-follow the selected source until the user starts editing.\n React.useEffect(() => {\n if (dirty) return;\n let cancelled = false;\n const data = source === 'original' ? transcript : editedWords;\n (async () => {\n const serialized =\n format === 'json'\n ? JSON.stringify(data, null, 2)\n : (await loadYaml()).dump(data, { lineWidth: 120 });\n if (!cancelled) {\n setText(serialized);\n setError(null);\n }\n })();\n return () => {\n cancelled = true;\n };\n }, [source, format, transcript, editedWords, dirty]);\n\n const handleApply = async () => {\n try {\n const words = await parseScript(text, format);\n onApply(words);\n setDirty(false);\n setError(null);\n } catch (err) {\n setError(\n err instanceof Error ? err.message : 'Could not parse the script.'\n );\n }\n };\n\n const handleReset = () => {\n setDirty(false);\n setError(null);\n };\n\n const sourceButton = (value: ScriptSource, label: string) => (\n <button\n type=\"button\"\n onClick={() => {\n setSource(value);\n setDirty(false);\n setError(null);\n }}\n aria-pressed={source === value}\n className={`focus-visible:ring-ring rounded px-1.5 py-0.5 text-xs transition-colors focus-visible:ring-2 focus-visible:outline-none ${\n source === value\n ? 'bg-primary-800 font-medium text-white'\n : 'text-muted-foreground hover:bg-muted hover:text-foreground'\n }`}\n >\n {label}\n </button>\n );\n\n return (\n <aside\n className={`border-border bg-card flex w-80 shrink-0 flex-col border-l lg:w-96 ${className ?? ''}`}\n aria-label=\"Transcript script\"\n >\n <div className=\"border-border flex shrink-0 flex-wrap items-center gap-1.5 border-b px-3 py-2\">\n <span className=\"text-foreground text-xs font-semibold\">Script</span>\n <span className=\"bg-border mx-1 h-4 w-px\" aria-hidden=\"true\" />\n {sourceButton('editor', 'Editor')}\n {sourceButton('original', 'Original')}\n <span className=\"bg-border mx-1 h-4 w-px\" aria-hidden=\"true\" />\n <button\n type=\"button\"\n onClick={() => {\n setFormat(format === 'yaml' ? 'json' : 'yaml');\n setDirty(false);\n setError(null);\n }}\n className=\"text-muted-foreground hover:bg-muted hover:text-foreground focus-visible:ring-ring rounded px-1.5 py-0.5 text-xs transition-colors focus-visible:ring-2 focus-visible:outline-none\"\n title=\"Toggle YAML / JSON\"\n >\n {format.toUpperCase()}\n </button>\n <span className=\"text-muted-foreground ml-auto text-[10px]\">\n {readOnly ? 'read-only' : dirty ? 'edited' : 'live'}\n </span>\n <Button\n variant=\"ghost\"\n size=\"sm\"\n onClick={onClose}\n aria-label=\"Close script panel\"\n >\n ✕\n </Button>\n </div>\n\n <textarea\n value={text}\n readOnly={readOnly}\n spellCheck={false}\n onChange={(e) => {\n setText(e.target.value);\n setDirty(true);\n }}\n className=\"text-foreground min-h-0 flex-1 resize-none bg-transparent p-3 font-mono text-xs leading-relaxed focus:outline-none\"\n aria-label={`Script source (${source}, ${format.toUpperCase()})`}\n />\n\n {error && (\n <p\n className=\"border-border text-destructive m-0 shrink-0 border-t px-3 py-2 text-xs\"\n role=\"alert\"\n >\n {error}\n </p>\n )}\n\n {!readOnly && (\n <div className=\"border-border flex shrink-0 items-center gap-2 border-t px-3 py-2\">\n <Button size=\"sm\" onClick={handleApply} disabled={!dirty}>\n Apply\n </Button>\n <Button\n variant=\"ghost\"\n size=\"sm\"\n onClick={handleReset}\n disabled={!dirty}\n title=\"Throw away unapplied typing and re-sync from the editor\"\n >\n Discard\n </Button>\n <span className=\"text-muted-foreground text-[10px]\">\n Apply pushes into the editor — revert an applied change with\n Undo\n </span>\n </div>\n )}\n </aside>\n );\n};\n","/**\n * MediaEditor — media playback + editable word-level transcript.\n *\n * Composition of MediaPlayer (imperative MediaPlayerRef) and an editable\n * word-mode transcript, with all edit state held by useTranscriptEdits.\n * Ported from pulseclip's TranscriptViewer; UI-only state (cursor,\n * selection, modals, sequence-playback bookkeeping) lives here.\n *\n * Controlled + persistence-agnostic: edits flow out via\n * onEditorStateChange / onEditedWordsRender and back in via\n * initialEditedWords / initialUndoStack. Timestamps in ms.\n */\n\nimport * as React from 'react';\nimport { cva, type VariantProps } from 'class-variance-authority';\nimport { Button } from '../Button';\nimport { Select } from '../Select';\nimport type {\n Transcript,\n TranscriptWord,\n EditableWord,\n PlaybackSegment,\n PlaybackSpeed,\n} from '../TranscriptView/transcript';\nimport { PLAYBACK_SPEEDS, isSilenceType } from '../TranscriptView/transcript';\nimport { useTranscriptEdits } from '../../hooks/useTranscriptEdits';\nimport {\n MediaPlayer,\n type MediaPlayerRef,\n type MediaKind,\n} from '../MediaPlayer/MediaPlayer';\nimport { FillerWordsModal } from './FillerWordsModal';\nimport { WordEditorModal } from './WordEditorModal';\nimport { SilenceSettingsModal } from './SilenceSettingsModal';\nimport { SpeedMarkerMenu } from './SpeedMarkerMenu';\nimport { ScriptPanel } from './ScriptPanel';\n\n// ============================================================================\n// Types & Interfaces\n// ============================================================================\n\nexport interface MediaEditorProps extends VariantProps<\n typeof mediaEditorVariants\n> {\n /** Media URL */\n src: string;\n /** Force the media kind; inferred from the src extension when omitted */\n kind?: MediaKind;\n /** The source transcript (canonical, immutable) */\n transcript: Transcript;\n /** Initial edited words (from saved edits) */\n initialEditedWords?: EditableWord[];\n /** Initial undo stack (from saved edits) */\n initialUndoStack?: EditableWord[][];\n /** Fired after every edit mutation (for persistence) */\n onEditorStateChange?: (\n editedWords: EditableWord[],\n undoStack: EditableWord[][]\n ) => void;\n /** Fired when the hasEdits flag changes */\n onHasEditsChange?: (hasEdits: boolean) => void;\n /** Fired when the cursor moves (start time of the cursor word in ms, or null) */\n onCursorTimestampChange?: (timestampMs: number | null) => void;\n /** Fired whenever the edited words change — lets the host build raw-data views */\n onEditedWordsRender?: (editedWords: EditableWord[]) => void;\n /** Optional ref to the internal MediaPlayer (host escape hatch, e.g. thumbnail capture) */\n playerRef?: React.Ref<MediaPlayerRef>;\n /** Additional class name */\n className?: string;\n /**\n * 'horizontal' (default): media stacked above the transcript.\n * 'vertical': media and transcript side by side.\n */\n splitLayout?: 'horizontal' | 'vertical';\n}\n\ninterface SelectionRange {\n start: number;\n end: number;\n}\n\n// ============================================================================\n// Variants\n// ============================================================================\n\nconst mediaEditorVariants = cva(\n // Root is always a row so the ScriptPanel can dock on the right; the\n // media/transcript split direction lives on the inner wrapper below.\n 'flex h-full min-h-0 w-full overflow-hidden rounded-xl border border-border bg-card text-card-foreground',\n {\n variants: {\n splitLayout: {\n horizontal: '',\n vertical: '',\n },\n },\n defaultVariants: {\n splitLayout: 'horizontal',\n },\n }\n);\n\n// ============================================================================\n// Helpers\n// ============================================================================\n\n/** Format duration: seconds only if <90s, min:sec if <60min, h:mm:ss otherwise */\nfunction formatDuration(ms: number): string {\n const totalSeconds = Math.round(ms / 1000);\n if (totalSeconds < 90) {\n return `${totalSeconds}s`;\n }\n const hours = Math.floor(totalSeconds / 3600);\n const minutes = Math.floor((totalSeconds % 3600) / 60);\n const seconds = totalSeconds % 60;\n if (hours > 0) {\n return `${hours}:${String(minutes).padStart(2, '0')}:${String(seconds).padStart(2, '0')}`;\n }\n return `${minutes}:${String(seconds).padStart(2, '0')}`;\n}\n\ninterface WordVisualState {\n isActive: boolean;\n isCursor: boolean;\n isSelected: boolean;\n isDeleted: boolean;\n isInserted: boolean;\n isSilence: boolean;\n isSilenceNewline: boolean;\n isAnchor: boolean;\n isFocused: boolean;\n hasSpeedMarker: boolean;\n}\n\n/**\n * Tailwind classes for one transcript word. Background/color states are\n * mutually exclusive (precedence: anchor > active > selected > deleted >\n * inserted > silence) so token utilities never conflict.\n */\nfunction wordClassName(s: WordVisualState): string {\n const parts = [\n 'relative cursor-pointer rounded-sm px-1 py-0.5 transition-colors duration-150',\n ];\n\n if (s.isSilence) {\n parts.push('text-xs font-medium italic tracking-wide');\n }\n if (s.isSilenceNewline) {\n parts.push('mt-1.5 block w-fit');\n }\n\n if (s.isAnchor) {\n parts.push('bg-warning/40 outline outline-2 outline-warning');\n } else if (s.isActive) {\n parts.push('bg-primary-800 font-medium text-white');\n } else if (s.isSelected && s.isFocused) {\n parts.push('bg-primary-500/40');\n } else if (s.isDeleted) {\n parts.push(\n 'bg-destructive/10 text-destructive line-through opacity-40 hover:bg-destructive/20 hover:opacity-70'\n );\n } else if (s.isInserted) {\n parts.push('bg-success/15 text-success hover:bg-success/25');\n } else if (s.isSilenceNewline) {\n parts.push('text-primary-500 hover:bg-primary-500/15');\n } else if (s.isSilence) {\n parts.push(\n 'border border-dashed border-border bg-muted text-muted-foreground hover:bg-muted/70'\n );\n } else {\n parts.push('hover:bg-primary-500/30');\n }\n\n // Keep the strikethrough visible when a deleted word is also active/selected/anchored\n if (\n s.isDeleted &&\n (s.isActive || (s.isSelected && s.isFocused) || s.isAnchor)\n ) {\n parts.push('line-through opacity-60');\n }\n\n // Cursor outline only when the transcript has focus (source behavior)\n if (s.isCursor && s.isFocused && !s.isAnchor) {\n if (s.isDeleted) {\n parts.push('outline outline-2 outline-offset-1 outline-destructive');\n } else if (s.isActive) {\n parts.push('outline outline-2 outline-offset-1 outline-background');\n } else {\n parts.push('outline outline-2 outline-offset-1 outline-primary-500');\n }\n }\n\n if (s.hasSpeedMarker) {\n parts.push('ml-0.5 border-l-[3px] border-l-warning pl-1.5');\n }\n\n return parts.join(' ');\n}\n\n/** Blinking caret rendered inside the cursor word */\nconst Caret: React.FC<{ side: 'before' | 'after' }> = ({ side }) => (\n <span\n aria-hidden=\"true\"\n className={`bg-primary-500 absolute top-0.5 bottom-0.5 w-0.5 motion-safe:animate-pulse ${\n side === 'before' ? '-left-px' : 'right-0.5'\n }`}\n />\n);\n\n// ============================================================================\n// Component\n// ============================================================================\n\n/**\n * Media editor: MediaPlayer on top, an editable word-mode transcript below,\n * and a toolbar with speed control, filler removal, and edit statistics.\n *\n * Interactions (ported from pulseclip's TranscriptViewer):\n * - Click a word: seek and play just that word\n * - Double-click: set a range anchor; click another word to select the range\n * - Mouse-down + drag: select a range; long-press (500ms) opens the editor\n * - Right-click: speed marker menu\n * - Keyboard: arrows (+Shift to select), Home/End, Backspace/Delete toggle\n * delete, Cmd/Ctrl+X/C/V cut/copy/paste, Cmd/Ctrl+Z undo, Space plays the\n * edited timeline from the cursor, Enter opens the word editor\n */\nexport const MediaEditor = React.forwardRef<HTMLDivElement, MediaEditorProps>(\n (\n {\n src,\n kind,\n transcript,\n initialEditedWords,\n initialUndoStack,\n onEditorStateChange,\n onHasEditsChange,\n onCursorTimestampChange,\n onEditedWordsRender,\n playerRef: externalPlayerRef,\n className,\n splitLayout,\n },\n ref\n ) => {\n // -- Edit state (headless hook) --\n const edits = useTranscriptEdits({\n transcript,\n initialEditedWords,\n initialUndoStack,\n onChange: onEditorStateChange,\n });\n const {\n editedWords,\n undoStack,\n clipboard,\n hasEdits,\n undo,\n toggleWordDeleted,\n deleteRange,\n cut,\n copy,\n paste,\n setWordText,\n splitSilence,\n deleteWord,\n replaceEditedWords,\n removeFillers,\n setSilenceThresholds,\n silenceThresholds,\n speedMarkers,\n defaultSpeed,\n setDefaultSpeed,\n toggleSpeedMarker,\n removeSpeedMarker,\n getSpeedAtIndex,\n getSpeedMarkerAtIndex,\n playbackSegments,\n stats,\n fillerAnalysis,\n } = edits;\n\n // -- UI state --\n const [activeWordIndex, setActiveWordIndex] = React.useState<number | null>(\n null\n );\n const [cursorIndex, setCursorIndex] = React.useState<number>(0);\n // 'before' = caret before the cursor word; 'after' = after the last word\n const [cursorPosition, setCursorPosition] = React.useState<\n 'before' | 'after'\n >('before');\n const [selectionAnchor, setSelectionAnchor] = React.useState<number | null>(\n null\n );\n const [selection, setSelection] = React.useState<SelectionRange | null>(\n null\n );\n const [doubleClickAnchor, setDoubleClickAnchor] = React.useState<\n number | null\n >(null);\n const [isPlayingSequence, setIsPlayingSequence] = React.useState(false);\n const [isFocused, setIsFocused] = React.useState(false);\n const [showFillerModal, setShowFillerModal] = React.useState(false);\n const [showSilenceModal, setShowSilenceModal] = React.useState(false);\n const [showScriptPanel, setShowScriptPanel] = React.useState(false);\n const [editorWordIndex, setEditorWordIndex] = React.useState<number | null>(\n null\n );\n const [speedMenuWordIndex, setSpeedMenuWordIndex] = React.useState<\n number | null\n >(null);\n const [speedMenuPosition, setSpeedMenuPosition] = React.useState<{\n x: number;\n y: number;\n } | null>(null);\n\n // -- Refs --\n const playerRef = React.useRef<MediaPlayerRef>(null);\n // Mirror the internal player handle to the host-provided ref via a STABLE\n // delegating proxy: every call forwards to playerRef.current at call time.\n // (Snapshotting playerRef.current with [] deps captured the first-commit\n // handle — ref assignment doesn't re-render, so hosts could hold a stale\n // handle whose mediaElement stayed null forever.)\n React.useImperativeHandle(\n externalPlayerRef,\n (): MediaPlayerRef => ({\n seekToMs: (timeMs) => playerRef.current?.seekToMs(timeMs),\n play: () => playerRef.current?.play(),\n pause: () => playerRef.current?.pause(),\n getCurrentTimeMs: () => playerRef.current?.getCurrentTimeMs() ?? 0,\n getDurationMs: () => playerRef.current?.getDurationMs() ?? 0,\n isPaused: () => playerRef.current?.isPaused() ?? true,\n setPlaybackRate: (rate) => playerRef.current?.setPlaybackRate(rate),\n get mediaElement() {\n return playerRef.current?.mediaElement ?? null;\n },\n }),\n []\n );\n const contentRef = React.useRef<HTMLDivElement>(null);\n const userSetCursor = React.useRef<number | null>(null);\n const isDragging = React.useRef<boolean>(false);\n const longPressTimer = React.useRef<ReturnType<typeof setTimeout> | null>(\n null\n );\n const longPressTriggered = React.useRef<boolean>(false);\n const wordPlaybackStartMs = React.useRef<number | null>(null);\n const wordPlaybackEndMs = React.useRef<number | null>(null);\n // Edited-timeline sequence playback\n const sequenceSegments = React.useRef<PlaybackSegment[]>([]);\n const currentSegmentIndex = React.useRef<number>(0);\n\n // ------------------------------------------------------------------\n // Parent notifications\n // ------------------------------------------------------------------\n\n React.useEffect(() => {\n onHasEditsChange?.(hasEdits);\n }, [hasEdits, onHasEditsChange]);\n\n React.useEffect(() => {\n onEditedWordsRender?.(editedWords);\n }, [editedWords, onEditedWordsRender]);\n\n // Report cursor timestamp changes to the parent\n React.useEffect(() => {\n if (onCursorTimestampChange) {\n const word = editedWords[cursorIndex];\n if (word && !word.deleted) {\n onCursorTimestampChange(word.word.startMs);\n } else {\n onCursorTimestampChange(null);\n }\n }\n }, [cursorIndex, editedWords, onCursorTimestampChange]);\n\n // ------------------------------------------------------------------\n // Transcript change / cursor sync / focus\n // ------------------------------------------------------------------\n\n // Reset UI state when the transcript changes (edit state resets in the hook)\n const prevTranscriptRef = React.useRef(transcript);\n React.useEffect(() => {\n if (prevTranscriptRef.current === transcript) return;\n prevTranscriptRef.current = transcript;\n setCursorIndex(0);\n setCursorPosition('before');\n setSelection(null);\n setSelectionAnchor(null);\n setDoubleClickAnchor(null);\n setActiveWordIndex(null);\n setIsPlayingSequence(false);\n sequenceSegments.current = [];\n currentSegmentIndex.current = 0;\n }, [transcript]);\n\n // Sync cursor with the active word while playing (unless a click-seek is pending)\n React.useEffect(() => {\n if (userSetCursor.current !== null) {\n return;\n }\n if (activeWordIndex !== null && activeWordIndex >= 0) {\n setCursorIndex(activeWordIndex);\n setCursorPosition('before');\n setSelection(null);\n setSelectionAnchor(null);\n }\n }, [activeWordIndex]);\n\n // Auto-scroll the active word into view during playback\n React.useEffect(() => {\n if (activeWordIndex === null) return;\n const el = contentRef.current?.querySelector(\n `[data-word-index=\"${activeWordIndex}\"]`\n );\n el?.scrollIntoView({ block: 'nearest', behavior: 'smooth' });\n }, [activeWordIndex]);\n\n // Auto-focus the transcript for keyboard navigation\n React.useEffect(() => {\n contentRef.current?.focus();\n }, [transcript]);\n\n // Apply the default speed when it changes (and no marker overrides it)\n React.useEffect(() => {\n const player = playerRef.current;\n if (!player) return;\n const timeMs = player.getCurrentTimeMs();\n const currentWordIndex = editedWords.findIndex(\n (ew) =>\n !ew.deleted && timeMs >= ew.word.startMs && timeMs < ew.word.endMs\n );\n const targetSpeed =\n currentWordIndex >= 0\n ? getSpeedAtIndex(currentWordIndex)\n : defaultSpeed;\n player.setPlaybackRate(targetSpeed);\n }, [defaultSpeed, speedMarkers, editedWords, getSpeedAtIndex]);\n\n // ------------------------------------------------------------------\n // Playback engine (timeupdate-driven)\n // ------------------------------------------------------------------\n\n const handleTimeUpdate = (timeMs: number) => {\n const player = playerRef.current;\n if (!player) return;\n\n // Segment-based playback of the edited timeline (jumps over deletions\n // and honors reordered/pasted words)\n if (isPlayingSequence && sequenceSegments.current.length > 0) {\n const currentSeg =\n sequenceSegments.current[currentSegmentIndex.current];\n if (currentSeg && timeMs >= currentSeg.endMs) {\n const nextIndex = currentSegmentIndex.current + 1;\n if (nextIndex < sequenceSegments.current.length) {\n currentSegmentIndex.current = nextIndex;\n player.seekToMs(sequenceSegments.current[nextIndex].startMs);\n } else {\n // End of all segments\n player.pause();\n setIsPlayingSequence(false);\n sequenceSegments.current = [];\n currentSegmentIndex.current = 0;\n }\n }\n } else if (hasEdits && !player.isPaused()) {\n // During normal playback with edits, skip over deleted words\n const inDeletedWord = editedWords.some(\n (ew) =>\n ew.deleted && timeMs >= ew.word.startMs && timeMs < ew.word.endMs\n );\n if (inDeletedWord) {\n const nextNonDeleted = editedWords.find(\n (ew) => !ew.deleted && ew.word.startMs >= timeMs\n );\n if (nextNonDeleted) {\n player.seekToMs(nextNonDeleted.word.startMs);\n }\n }\n }\n\n // Stop playback at the end of single-word playback, reseek to its start\n if (\n wordPlaybackEndMs.current !== null &&\n timeMs >= wordPlaybackEndMs.current\n ) {\n player.pause();\n if (wordPlaybackStartMs.current !== null) {\n player.seekToMs(wordPlaybackStartMs.current);\n wordPlaybackStartMs.current = null;\n }\n wordPlaybackEndMs.current = null;\n }\n\n // Find the active word. During segment playback use the current\n // segment's indices (disambiguates duplicate/pasted words that share\n // timing); otherwise fall back to a time-based lookup.\n let editedIndex = -1;\n if (isPlayingSequence && sequenceSegments.current.length > 0) {\n const currentSeg =\n sequenceSegments.current[currentSegmentIndex.current];\n if (currentSeg) {\n for (const idx of currentSeg.editedIndices) {\n const ew = editedWords[idx];\n if (\n ew &&\n !ew.deleted &&\n timeMs >= ew.word.startMs &&\n timeMs < ew.word.endMs\n ) {\n editedIndex = idx;\n break;\n }\n }\n }\n }\n if (editedIndex === -1) {\n editedIndex = editedWords.findIndex(\n (ew) =>\n !ew.deleted && timeMs >= ew.word.startMs && timeMs < ew.word.endMs\n );\n }\n\n // Update playback rate from speed markers when the word changes\n if (editedIndex !== activeWordIndex && editedIndex >= 0) {\n player.setPlaybackRate(getSpeedAtIndex(editedIndex));\n }\n setActiveWordIndex(editedIndex >= 0 ? editedIndex : null);\n\n // Playback has resumed reporting time: release the click-seek cursor lock\n userSetCursor.current = null;\n };\n\n const stopSequencePlayback = () => {\n setIsPlayingSequence(false);\n sequenceSegments.current = [];\n currentSegmentIndex.current = 0;\n };\n\n // ------------------------------------------------------------------\n // Selection / clipboard helpers\n // ------------------------------------------------------------------\n\n /** Indices covered by the selection, or the cursor word */\n const selectionIndices = React.useCallback((): number[] => {\n if (selection) {\n const indices: number[] = [];\n for (let i = selection.start; i <= selection.end; i++) indices.push(i);\n return indices;\n }\n return [cursorIndex];\n }, [selection, cursorIndex]);\n\n const handleCut = React.useCallback(() => {\n cut(selectionIndices());\n }, [cut, selectionIndices]);\n\n const handlePaste = React.useCallback(() => {\n if (!clipboard) return;\n const pastedCount = clipboard.words.length;\n const insertIndex = paste(cursorIndex, cursorPosition !== 'after');\n if (insertIndex !== null) {\n setCursorIndex(insertIndex + pastedCount - 1);\n setCursorPosition('after');\n setSelection(null);\n setSelectionAnchor(null);\n }\n }, [clipboard, paste, cursorIndex, cursorPosition]);\n\n // Toggle deleted state for the selection (anchor decides) or cursor word\n const handleDeleteToggle = React.useCallback(() => {\n if (selection) {\n const anchorIndex = selectionAnchor ?? selection.start;\n const indices: number[] = [anchorIndex];\n for (let i = selection.start; i <= selection.end; i++) {\n if (i !== anchorIndex) indices.push(i);\n }\n deleteRange(indices);\n } else {\n toggleWordDeleted(cursorIndex);\n }\n }, [\n selection,\n selectionAnchor,\n cursorIndex,\n deleteRange,\n toggleWordDeleted,\n ]);\n\n // Copy: put plain text on the system clipboard + fill the internal clipboard\n const handleCopy = React.useCallback(\n (e: React.ClipboardEvent) => {\n const indices = selectionIndices();\n const selectedWords = indices\n .map((i) => editedWords[i])\n .filter((ew): ew is EditableWord => ew !== undefined && !ew.deleted);\n if (selectedWords.length === 0) return;\n const selectedText = selectedWords\n .filter((ew) => !isSilenceType(ew.word.wordType))\n .map((ew) => ew.word.text)\n .join(' ');\n e.preventDefault();\n e.clipboardData.setData('text/plain', selectedText);\n copy(indices);\n },\n [selectionIndices, editedWords, copy]\n );\n\n // ------------------------------------------------------------------\n // Word editor modal\n // ------------------------------------------------------------------\n\n const openWordEditor = React.useCallback((index: number) => {\n setEditorWordIndex(index);\n }, []);\n\n const closeWordEditor = React.useCallback(() => {\n setEditorWordIndex(null);\n // Restore focus to the transcript after the modal closes\n setTimeout(() => contentRef.current?.focus(), 0);\n }, []);\n\n const handleEditorSave = React.useCallback(\n (newText: string) => {\n if (editorWordIndex === null) return;\n setWordText(editorWordIndex, newText);\n },\n [editorWordIndex, setWordText]\n );\n\n const handleEditorSplitSilence = React.useCallback(\n (durations: number[]) => {\n if (editorWordIndex === null) return;\n splitSilence(editorWordIndex, durations);\n },\n [editorWordIndex, splitSilence]\n );\n\n const handleEditorDelete = React.useCallback(() => {\n if (editorWordIndex !== null) {\n deleteWord(editorWordIndex);\n closeWordEditor();\n }\n }, [editorWordIndex, deleteWord, closeWordEditor]);\n\n // ------------------------------------------------------------------\n // Mouse interactions\n // ------------------------------------------------------------------\n\n const handleWordClick = (\n word: TranscriptWord,\n index: number,\n e: React.MouseEvent\n ) => {\n setCursorIndex(index);\n setCursorPosition('before');\n userSetCursor.current = index;\n\n if (e.shiftKey && selectionAnchor !== null) {\n // Extend selection with shift+click\n setSelection({\n start: Math.min(selectionAnchor, index),\n end: Math.max(selectionAnchor, index),\n });\n } else if (\n doubleClickAnchor !== null &&\n doubleClickAnchor !== index &&\n !isDragging.current\n ) {\n // A double-click anchor exists and a different word was clicked: select the range\n const start = Math.min(doubleClickAnchor, index);\n const end = Math.max(doubleClickAnchor, index);\n setSelection({ start, end });\n setSelectionAnchor(doubleClickAnchor);\n setDoubleClickAnchor(null);\n } else if (doubleClickAnchor === index) {\n // Clicking the anchor itself — wait for a potential double-click\n } else if (!isDragging.current) {\n // Clear selection, set a new anchor, and play just this word\n setSelectionAnchor(index);\n setSelection(null);\n\n const player = playerRef.current;\n if (player) {\n player.pause();\n player.seekToMs(word.startMs);\n wordPlaybackStartMs.current = word.startMs;\n wordPlaybackEndMs.current = word.endMs;\n player.play();\n }\n }\n };\n\n const handleWordDoubleClick = (index: number, e: React.MouseEvent) => {\n e.preventDefault();\n // Don't trigger if a long press already fired\n if (longPressTriggered.current) return;\n\n if (doubleClickAnchor === index) {\n setDoubleClickAnchor(null);\n } else {\n setDoubleClickAnchor(index);\n setSelection(null);\n }\n };\n\n const handleWordMouseDown = (index: number, e: React.MouseEvent) => {\n if (e.button !== 0) return;\n\n // Long press (500ms) opens the word editor\n longPressTriggered.current = false;\n longPressTimer.current = setTimeout(() => {\n longPressTriggered.current = true;\n openWordEditor(index);\n }, 500);\n\n isDragging.current = true;\n setSelectionAnchor(index);\n setCursorIndex(index);\n setCursorPosition('before');\n setSelection(null);\n };\n\n const handleWordMouseEnter = (index: number) => {\n // Cancel the long press when dragging to another word\n if (longPressTimer.current) {\n clearTimeout(longPressTimer.current);\n longPressTimer.current = null;\n }\n\n if (!isDragging.current || selectionAnchor === null) return;\n\n setSelection({\n start: Math.min(selectionAnchor, index),\n end: Math.max(selectionAnchor, index),\n });\n setCursorIndex(index);\n };\n\n const handleMouseUp = () => {\n if (longPressTimer.current) {\n clearTimeout(longPressTimer.current);\n longPressTimer.current = null;\n }\n if (isDragging.current) {\n isDragging.current = false;\n }\n };\n\n const handleWordContextMenu = (index: number, e: React.MouseEvent) => {\n e.preventDefault();\n // Position the speed menu near the word, clamped to the viewport\n const rect = e.currentTarget.getBoundingClientRect();\n const menuHeight = 280;\n const menuWidth = 150;\n\n let x = rect.left;\n let y = rect.bottom + 4;\n\n if (x + menuWidth > window.innerWidth) {\n x = window.innerWidth - menuWidth - 8;\n }\n if (y + menuHeight > window.innerHeight) {\n y = rect.top - menuHeight - 4;\n if (y < 0) {\n y = 8;\n }\n }\n\n setSpeedMenuPosition({ x, y });\n setSpeedMenuWordIndex(index);\n };\n\n // ------------------------------------------------------------------\n // Keyboard\n // ------------------------------------------------------------------\n\n const handleKeyDown = React.useCallback(\n (e: React.KeyboardEvent) => {\n const wordCount = editedWords.length;\n if (wordCount === 0) return;\n\n let newIndex = cursorIndex;\n let handled = false;\n\n if (e.key === 'Delete' || e.key === 'Backspace') {\n handleDeleteToggle();\n handled = true;\n } else if ((e.metaKey || e.ctrlKey) && e.key === 'x') {\n handleCut();\n handled = true;\n } else if ((e.metaKey || e.ctrlKey) && e.key === 'v' && clipboard) {\n handlePaste();\n handled = true;\n } else if ((e.metaKey || e.ctrlKey) && e.key === 'z' && !e.shiftKey) {\n undo();\n handled = true;\n } else if (e.key === 'ArrowLeft') {\n if (cursorPosition === 'after') {\n // Move from 'after' the last word back to 'before' it\n setCursorPosition('before');\n } else {\n newIndex = Math.max(0, cursorIndex - 1);\n }\n handled = true;\n } else if (e.key === 'ArrowRight') {\n if (cursorIndex === wordCount - 1 && cursorPosition === 'before') {\n // At the last word: move the caret after it\n setCursorPosition('after');\n } else if (cursorPosition !== 'after') {\n newIndex = Math.min(wordCount - 1, cursorIndex + 1);\n }\n handled = true;\n } else if (e.key === 'ArrowUp' || e.key === 'ArrowDown') {\n // Find the visually nearest word on the previous/next row\n const currentElement = contentRef.current?.querySelector(\n `[data-word-index=\"${cursorIndex}\"]`\n ) as HTMLElement | null;\n if (currentElement) {\n const currentRect = currentElement.getBoundingClientRect();\n const currentCenterX = currentRect.left + currentRect.width / 2;\n\n const direction = e.key === 'ArrowUp' ? -1 : 1;\n let bestMatch = cursorIndex;\n let bestDistance = Infinity;\n let targetRowTop: number | null = null;\n\n for (\n let i = cursorIndex + direction;\n i >= 0 && i < wordCount;\n i += direction\n ) {\n const el = contentRef.current?.querySelector(\n `[data-word-index=\"${i}\"]`\n ) as HTMLElement | null;\n if (!el) continue;\n\n const rect = el.getBoundingClientRect();\n const isOnDifferentRow =\n direction === -1\n ? rect.bottom <= currentRect.top\n : rect.top >= currentRect.bottom;\n\n if (isOnDifferentRow) {\n // The first word on a different row establishes the target row\n if (targetRowTop === null) {\n targetRowTop = rect.top;\n }\n const isSameTargetRow = Math.abs(rect.top - targetRowTop) < 5;\n if (isSameTargetRow) {\n const centerX = rect.left + rect.width / 2;\n const distance = Math.abs(centerX - currentCenterX);\n if (distance < bestDistance) {\n bestDistance = distance;\n bestMatch = i;\n }\n } else {\n // Moved past the target row; stop searching\n break;\n }\n }\n }\n newIndex = bestMatch;\n }\n handled = true;\n } else if (e.key === 'Home') {\n newIndex = 0;\n handled = true;\n } else if (e.key === 'End') {\n newIndex = wordCount - 1;\n handled = true;\n } else if (e.key === 'Enter') {\n openWordEditor(cursorIndex);\n handled = true;\n } else if (e.key === ' ') {\n // Toggle play/pause from the cursor position\n const ew = editedWords[cursorIndex];\n const player = playerRef.current;\n if (player && ew && !ew.deleted) {\n if (player.isPaused()) {\n if (hasEdits) {\n // Play the edited timeline as a segment sequence\n const segments = playbackSegments;\n if (segments.length > 0) {\n let startSegmentIdx = 0;\n for (let i = 0; i < segments.length; i++) {\n if (segments[i].editedIndices.includes(cursorIndex)) {\n startSegmentIdx = i;\n break;\n }\n }\n sequenceSegments.current = segments;\n currentSegmentIndex.current = startSegmentIdx;\n setIsPlayingSequence(true);\n // Start from the cursor word's time, not the segment's start\n player.seekToMs(ew.word.startMs);\n player.play();\n }\n } else {\n // Normal playback from the cursor\n player.seekToMs(ew.word.startMs);\n player.play();\n }\n } else {\n player.pause();\n setIsPlayingSequence(false);\n }\n }\n handled = true;\n }\n\n if (handled) {\n e.preventDefault();\n e.stopPropagation();\n if (newIndex !== cursorIndex) {\n setCursorIndex(newIndex);\n setCursorPosition('before');\n }\n\n if (e.shiftKey && e.key !== 'Delete' && e.key !== 'Backspace') {\n // Extend the selection (not for delete operations)\n const anchor = selectionAnchor ?? cursorIndex;\n if (selectionAnchor === null) {\n setSelectionAnchor(cursorIndex);\n }\n setSelection({\n start: Math.min(anchor, newIndex),\n end: Math.max(anchor, newIndex),\n });\n } else if (!e.metaKey && !e.ctrlKey) {\n // Clear the selection when moving without shift (not for cut/paste)\n setSelection(null);\n setSelectionAnchor(null);\n }\n\n // Scroll the cursor into view\n const wordElement = contentRef.current?.querySelector(\n `[data-word-index=\"${newIndex}\"]`\n );\n wordElement?.scrollIntoView({ block: 'nearest', behavior: 'smooth' });\n }\n },\n [\n editedWords,\n cursorIndex,\n cursorPosition,\n selectionAnchor,\n clipboard,\n hasEdits,\n playbackSegments,\n handleDeleteToggle,\n handleCut,\n handlePaste,\n undo,\n openWordEditor,\n ]\n );\n\n // ------------------------------------------------------------------\n // Rendering\n // ------------------------------------------------------------------\n\n const isWordSelected = (index: number): boolean => {\n if (!selection) return false;\n return index >= selection.start && index <= selection.end;\n };\n\n const renderWord = (ew: EditableWord, index: number) => {\n const isActive = index === activeWordIndex;\n const isCursor = index === cursorIndex;\n const isSelected = isWordSelected(index);\n const isDeleted = ew.deleted;\n const isInserted = ew.inserted ?? false;\n const isSilence =\n ew.word.wordType === 'silence' ||\n ew.word.wordType === 'silence-newline';\n const isSilenceNewline = ew.word.wordType === 'silence-newline';\n const isAnchor = index === doubleClickAnchor;\n const showCursorBefore = isCursor && cursorPosition === 'before';\n const showCursorAfter =\n isCursor &&\n cursorPosition === 'after' &&\n index === editedWords.length - 1;\n const speedMarker = getSpeedMarkerAtIndex(index);\n const hasSpeedMarker = !!speedMarker;\n\n // For silences, show the duration adjusted for the effective speed\n const effectiveSpeed = getSpeedAtIndex(index);\n let displayText = ew.word.text;\n if (isSilence && effectiveSpeed !== 1) {\n const originalDurationMs = ew.word.endMs - ew.word.startMs;\n const adjustedDurationSec = originalDurationMs / effectiveSpeed / 1000;\n displayText = `[${adjustedDurationSec.toFixed(1)}s]`;\n }\n\n const title = `${ew.word.startMs}ms - ${ew.word.endMs}ms${\n ew.word.confidence ? ` (${Math.round(ew.word.confidence * 100)}%)` : ''\n }${\n isSilence\n ? ` [SILENCE: ${((ew.word.endMs - ew.word.startMs) / 1000).toFixed(1)}s${\n effectiveSpeed !== 1\n ? ` → ${((ew.word.endMs - ew.word.startMs) / effectiveSpeed / 1000).toFixed(1)}s @ ${effectiveSpeed}x`\n : ''\n }]`\n : ''\n }${isDeleted ? ' [DELETED]' : ''}${isInserted ? ' [INSERTED]' : ''}${\n hasSpeedMarker ? ` [SPEED: ${speedMarker.speed}x]` : ''\n }${\n isAnchor\n ? ' [ANCHOR - click another word to select range, double-click to clear]'\n : ''\n }${!isAnchor && !isDeleted ? ' (right-click to set speed marker)' : ''}`;\n\n return (\n // Keyboard interaction is owned by the parent listbox via roving focus\n // (aria-activedescendant); options are pointer affordances only.\n // eslint-disable-next-line jsx-a11y/click-events-have-key-events, jsx-a11y/interactive-supports-focus\n <span\n key={`${ew.originalIndex}-${index}`}\n id={`word-${index}`}\n data-word-index={index}\n className={wordClassName({\n isActive,\n isCursor,\n isSelected,\n isDeleted,\n isInserted,\n isSilence,\n isSilenceNewline,\n isAnchor,\n isFocused,\n hasSpeedMarker,\n })}\n onClick={(e) => handleWordClick(ew.word, index, e)}\n onDoubleClick={(e) => handleWordDoubleClick(index, e)}\n onMouseDown={(e) => handleWordMouseDown(index, e)}\n onMouseEnter={() => handleWordMouseEnter(index)}\n onContextMenu={(e) => handleWordContextMenu(index, e)}\n role=\"option\"\n aria-selected={isSelected || isCursor}\n title={title}\n >\n {showCursorBefore && isFocused && <Caret side=\"before\" />}\n {hasSpeedMarker && (\n <span\n className=\"border-warning/50 bg-warning/20 text-warning-foreground mr-1 inline-block rounded-sm border px-0.5 align-middle text-[9px] leading-snug font-semibold\"\n title={`Speed: ${speedMarker.speed}x from here`}\n >\n {speedMarker.speed}x\n </span>\n )}\n {displayText} {showCursorAfter && isFocused && <Caret side=\"after\" />}\n </span>\n );\n };\n\n const showEditBar =\n hasEdits || doubleClickAnchor !== null || selection !== null;\n\n return (\n <div\n ref={ref}\n className={mediaEditorVariants({ splitLayout, className })}\n >\n <div\n className={`flex min-h-0 min-w-0 flex-1 ${\n splitLayout === 'vertical' ? 'flex-col md:flex-row' : 'flex-col'\n }`}\n >\n {/* Media surface */}\n <div\n className={`border-border bg-background min-h-0 shrink-0 ${\n splitLayout === 'vertical'\n ? 'md:w-1/2 md:border-r'\n : 'max-h-[50%] border-b'\n }`}\n >\n <MediaPlayer\n ref={playerRef}\n src={src}\n kind={kind}\n aria-label=\"Media player\"\n onTimeUpdate={handleTimeUpdate}\n onEnded={stopSequencePlayback}\n />\n </div>\n\n {/* Transcript editor */}\n <div\n className={`flex min-h-0 flex-1 flex-col ${splitLayout === 'vertical' ? 'md:w-1/2' : ''}`}\n >\n {/* Toolbar */}\n <div className=\"border-border flex shrink-0 flex-wrap items-center justify-between gap-2 border-b px-3 py-2\">\n <div className=\"flex items-center gap-2\">\n {hasEdits && (\n <span className=\"bg-warning/20 text-warning-foreground rounded px-1.5 py-0.5 text-xs font-semibold\">\n Edited\n </span>\n )}\n <label\n className=\"text-muted-foreground text-xs\"\n htmlFor=\"media-editor-default-speed\"\n >\n Speed:\n </label>\n <div className=\"w-20\">\n <Select\n id=\"media-editor-default-speed\"\n size=\"sm\"\n options={PLAYBACK_SPEEDS.map((speed) => ({\n value: String(speed),\n label: `${speed}x`,\n }))}\n value={String(defaultSpeed)}\n onValueChange={(value) =>\n setDefaultSpeed(parseFloat(value) as PlaybackSpeed)\n }\n aria-label=\"Default playback speed\"\n />\n </div>\n {speedMarkers.length > 0 && (\n <span\n className=\"text-muted-foreground text-xs\"\n title={`${speedMarkers.length} speed marker(s) set. Right-click on a word to add/remove speed markers.`}\n >\n {speedMarkers.length} marker\n {speedMarkers.length !== 1 ? 's' : ''}\n </span>\n )}\n <Button\n variant=\"ghost\"\n size=\"sm\"\n onClick={() => setShowFillerModal(true)}\n aria-label=\"Remove filler words\"\n title=\"Remove filler words\"\n >\n ✂️\n </Button>\n {undoStack.length > 0 && (\n <Button\n variant=\"ghost\"\n size=\"sm\"\n onClick={undo}\n aria-label={`Undo (${undoStack.length} available)`}\n title=\"Undo (⌘Z)\"\n >\n Undo ({undoStack.length})\n </Button>\n )}\n </div>\n\n <div className=\"text-muted-foreground flex items-center gap-2 text-xs\">\n <Button\n variant=\"ghost\"\n size=\"sm\"\n onClick={() => setShowScriptPanel((v) => !v)}\n aria-pressed={showScriptPanel}\n aria-label=\"Show script\"\n title=\"Show the transcript script (editable YAML/JSON)\"\n >\n Script\n </Button>\n <span>{stats.activeWordCount} words</span>\n <button\n type=\"button\"\n className=\"hover:bg-muted hover:text-foreground focus-visible:ring-ring rounded px-1 underline decoration-dotted transition-colors focus-visible:ring-2 focus-visible:outline-none\"\n onClick={() => setShowSilenceModal(true)}\n title={\n stats.activeSilenceCount > 0\n ? `Click to configure silence detection (currently ≥${(silenceThresholds.minSilenceMs / 1000).toFixed(1)}s)`\n : `No silences detected (threshold: ${(silenceThresholds.minSilenceMs / 1000).toFixed(1)}s). Click to configure.`\n }\n aria-label=\"Configure silence detection\"\n >\n {stats.activeSilenceCount} silences\n </button>\n {(stats.deletedWordCount > 0 ||\n stats.deletedSilenceCount > 0) && (\n <span className=\"text-destructive\">\n {stats.deletedWordCount + stats.deletedSilenceCount} deleted\n </span>\n )}\n {transcript.speakers && (\n <span>{transcript.speakers.length} speakers</span>\n )}\n <span>{formatDuration(stats.editedDurationMs)}</span>\n </div>\n </div>\n\n {/* Contextual edit actions */}\n {showEditBar && (\n <div className=\"border-border bg-muted/40 flex shrink-0 items-center gap-1 border-b px-3 py-1\">\n <Button\n variant=\"ghost\"\n size=\"sm\"\n onClick={() => openWordEditor(cursorIndex)}\n title=\"Edit selected word (Enter)\"\n >\n Edit <kbd className=\"text-[10px] opacity-60\">↵</kbd>\n </Button>\n <Button\n variant=\"ghost\"\n size=\"sm\"\n onClick={handleDeleteToggle}\n title=\"Delete selected word (Del)\"\n >\n Del <kbd className=\"text-[10px] opacity-60\">⌫</kbd>\n </Button>\n <Button\n variant=\"ghost\"\n size=\"sm\"\n onClick={handleCut}\n title=\"Cut selection (⌘X)\"\n >\n Cut <kbd className=\"text-[10px] opacity-60\">⌘X</kbd>\n </Button>\n <Button\n variant=\"ghost\"\n size=\"sm\"\n onClick={handlePaste}\n disabled={!clipboard}\n title=\"Paste (⌘V)\"\n >\n Paste <kbd className=\"text-[10px] opacity-60\">⌘V</kbd>\n </Button>\n </div>\n )}\n\n {/* Editable transcript */}\n <div\n ref={contentRef}\n className={`focus-visible:ring-ring min-h-0 flex-1 overflow-y-auto p-3 text-sm leading-relaxed select-none focus:outline-none focus-visible:ring-2 focus-visible:ring-inset ${\n isFocused ? 'bg-muted/20' : ''\n }`}\n tabIndex={0}\n onKeyDown={handleKeyDown}\n onCopy={handleCopy}\n onFocus={() => setIsFocused(true)}\n onBlur={() => setIsFocused(false)}\n onMouseUp={handleMouseUp}\n onMouseLeave={handleMouseUp}\n role=\"listbox\"\n aria-label=\"Transcript words\"\n aria-activedescendant={`word-${cursorIndex}`}\n >\n {editedWords.map(renderWord)}\n </div>\n </div>\n </div>\n\n {showScriptPanel && (\n <ScriptPanel\n transcript={transcript}\n editedWords={editedWords}\n onApply={replaceEditedWords}\n onClose={() => setShowScriptPanel(false)}\n />\n )}\n\n {/* Modals & menus */}\n <FillerWordsModal\n isOpen={showFillerModal}\n onClose={() => setShowFillerModal(false)}\n onApply={removeFillers}\n matchingCounts={fillerAnalysis.matchCounts}\n fillerDurations={fillerAnalysis.durations}\n silenceCounts={fillerAnalysis.silenceCounts}\n currentDurationMs={stats.editedDurationMs}\n />\n\n <SilenceSettingsModal\n isOpen={showSilenceModal}\n onClose={() => setShowSilenceModal(false)}\n minSilenceMs={silenceThresholds.minSilenceMs}\n nlSilenceMs={silenceThresholds.nlSilenceMs}\n onApply={setSilenceThresholds}\n />\n\n <WordEditorModal\n isOpen={editorWordIndex !== null}\n editableWord={\n editorWordIndex !== null\n ? (editedWords[editorWordIndex] ?? null)\n : null\n }\n onClose={closeWordEditor}\n onSave={handleEditorSave}\n onSplitSilence={handleEditorSplitSilence}\n onDelete={handleEditorDelete}\n />\n\n <SpeedMarkerMenu\n isOpen={speedMenuWordIndex !== null}\n position={speedMenuPosition}\n wordIndex={speedMenuWordIndex}\n currentMarker={\n speedMenuWordIndex !== null\n ? getSpeedMarkerAtIndex(speedMenuWordIndex)\n : undefined\n }\n defaultSpeed={defaultSpeed}\n onSetSpeed={(speed) => {\n if (speedMenuWordIndex !== null) {\n toggleSpeedMarker(speedMenuWordIndex, speed);\n }\n }}\n onRemoveMarker={() => {\n if (speedMenuWordIndex !== null) {\n removeSpeedMarker(speedMenuWordIndex);\n }\n }}\n onClose={() => {\n setSpeedMenuWordIndex(null);\n setSpeedMenuPosition(null);\n }}\n />\n </div>\n );\n }\n);\n\nMediaEditor.displayName = 'MediaEditor';\n"]}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
// src/components/TranscriptView/transcript.ts
|
|
4
|
+
function isSilenceType(wordType) {
|
|
5
|
+
return wordType === "silence" || wordType === "silence-newline";
|
|
6
|
+
}
|
|
7
|
+
var PLAYBACK_SPEEDS = [
|
|
8
|
+
0.5,
|
|
9
|
+
0.75,
|
|
10
|
+
1,
|
|
11
|
+
1.25,
|
|
12
|
+
1.5,
|
|
13
|
+
1.75,
|
|
14
|
+
2
|
|
15
|
+
];
|
|
16
|
+
|
|
17
|
+
exports.PLAYBACK_SPEEDS = PLAYBACK_SPEEDS;
|
|
18
|
+
exports.isSilenceType = isSilenceType;
|
|
19
|
+
//# sourceMappingURL=chunk-NUFUV43P.cjs.map
|
|
20
|
+
//# sourceMappingURL=chunk-NUFUV43P.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/components/TranscriptView/transcript.ts"],"names":[],"mappings":";;;AAiBO,SAAS,cAAc,QAAA,EAAyC;AACrE,EAAA,OAAO,QAAA,KAAa,aAAa,QAAA,KAAa,iBAAA;AAChD;AAqEO,IAAM,eAAA,GAAmC;AAAA,EAC9C,GAAA;AAAA,EAAK,IAAA;AAAA,EAAM,CAAA;AAAA,EAAG,IAAA;AAAA,EAAM,GAAA;AAAA,EAAK,IAAA;AAAA,EAAM;AACjC","file":"chunk-NUFUV43P.cjs","sourcesContent":["/**\n * Transcript schema for @mieweb/ui media components.\n *\n * Provider-agnostic and persistence-agnostic. Canonical time unit is\n * **milliseconds** (consumers with seconds-based data, e.g. osheet, adapt\n * at the boundary).\n *\n * Shared by TranscriptView, MediaEditor, and useTranscriptEdits.\n */\n\n/** Type of transcript word - 'word' for spoken content, 'silence' for detected gaps, 'silence-newline' for longer pauses */\nexport type WordType = 'word' | 'silence' | 'silence-newline';\n\n/** True for BOTH silence pseudo-word types ('silence' and 'silence-newline').\n * Use this instead of comparing against 'silence' directly — checking only one\n * of the two types is the root cause of a whole family of review findings\n * (stats, splitting, filler analysis, clipboard copy). */\nexport function isSilenceType(wordType: WordType | undefined): boolean {\n return wordType === 'silence' || wordType === 'silence-newline';\n}\n\nexport interface TranscriptWord {\n text: string;\n startMs: number;\n endMs: number;\n /** References Speaker.id when diarization is available */\n speakerId?: string;\n confidence?: number;\n /** Type of word: 'word' for spoken content, 'silence' for detected gaps. Defaults to 'word' */\n wordType?: WordType;\n}\n\n/** A diarized segment of contiguous speech (osheet-style granularity) */\nexport interface TranscriptSegment {\n text: string;\n startMs: number;\n endMs: number;\n /** References Speaker.id when diarization is available */\n speakerId?: string;\n words: TranscriptWord[];\n}\n\nexport interface Speaker {\n id: string;\n /** Display name (e.g. 'Clinician', 'Patient'). Hosts may remap via speakerLabels props. */\n name?: string;\n}\n\nexport interface Transcript {\n durationMs: number;\n speakers?: Speaker[];\n words: TranscriptWord[];\n segments?: TranscriptSegment[];\n}\n\n/**\n * An editable word that references the original transcript word.\n * Used in the edited timeline to track deletions and reordering.\n */\nexport interface EditableWord {\n /** Index into the SILENCE-INSERTED baseline timeline (transcript.words\n * with detected silence pseudo-words interleaved) — NOT into\n * transcript.words. -1 for split/inserted entries with no baseline slot.\n * Consumers persisting edits should key by this timeline. */\n originalIndex: number;\n /** The word data (from original transcript) */\n word: TranscriptWord;\n /** Whether this word is marked as deleted */\n deleted: boolean;\n /** Whether this word was inserted (pasted from clipboard) */\n inserted?: boolean;\n}\n\n/**\n * Represents a contiguous segment of playback from the original media.\n * Used when playing back an edited timeline with potentially reordered/deleted words.\n */\nexport interface PlaybackSegment {\n startMs: number;\n endMs: number;\n /** Indices into the editedWords array that this segment covers */\n editedIndices: number[];\n}\n\n/** Available playback speed multipliers */\nexport type PlaybackSpeed = 0.5 | 0.75 | 1 | 1.25 | 1.5 | 1.75 | 2;\n\n/** Array of all available speed options for dropdowns */\nexport const PLAYBACK_SPEEDS: PlaybackSpeed[] = [\n 0.5, 0.75, 1, 1.25, 1.5, 1.75, 2,\n];\n\n/**\n * A speed marker applied to a word in the transcript.\n * The speed applies from this word until the next speed marker or end of transcript.\n */\nexport interface SpeedMarker {\n /** Index in the editedWords array where the speed marker is placed */\n wordIndex: number;\n /** The playback speed multiplier */\n speed: PlaybackSpeed;\n}\n"]}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
+
import { isSilenceType } from './chunk-6CGM5H4J.js';
|
|
1
2
|
import { useRef, useState, useCallback, useEffect, useMemo } from 'react';
|
|
2
3
|
|
|
3
|
-
// src/hooks/useTranscriptEdits.ts
|
|
4
4
|
var DEFAULT_FILLER_WORDS = [
|
|
5
5
|
"um",
|
|
6
6
|
"uh",
|
|
@@ -65,15 +65,12 @@ function buildPlaybackSegments(editedWords) {
|
|
|
65
65
|
return segments;
|
|
66
66
|
}
|
|
67
67
|
function getSpeedAtIndex(wordIndex, speedMarkers, defaultSpeed) {
|
|
68
|
-
const sortedMarkers = [...speedMarkers].sort(
|
|
69
|
-
(a, b) => a.wordIndex - b.wordIndex
|
|
70
|
-
);
|
|
71
68
|
let effectiveSpeed = defaultSpeed;
|
|
72
|
-
|
|
73
|
-
|
|
69
|
+
let nearest = -1;
|
|
70
|
+
for (const marker of speedMarkers) {
|
|
71
|
+
if (marker.wordIndex <= wordIndex && marker.wordIndex > nearest) {
|
|
72
|
+
nearest = marker.wordIndex;
|
|
74
73
|
effectiveSpeed = marker.speed;
|
|
75
|
-
} else {
|
|
76
|
-
break;
|
|
77
74
|
}
|
|
78
75
|
}
|
|
79
76
|
return effectiveSpeed;
|
|
@@ -143,7 +140,14 @@ function useTranscriptEdits(options) {
|
|
|
143
140
|
const [clipboard, setClipboard] = useState(null);
|
|
144
141
|
const [hasEdits, setHasEdits] = useState(() => {
|
|
145
142
|
if (initialEditedWords) {
|
|
146
|
-
|
|
143
|
+
const baseline = initEditableWords(
|
|
144
|
+
transcript,
|
|
145
|
+
initialMinSilenceMs,
|
|
146
|
+
initialNlSilenceMs
|
|
147
|
+
);
|
|
148
|
+
return initialEditedWords.length !== baseline.length || initialEditedWords.some(
|
|
149
|
+
(ew, i) => ew.deleted || ew.inserted || ew.originalIndex !== i || ew.word.text !== baseline[i].word.text
|
|
150
|
+
);
|
|
147
151
|
}
|
|
148
152
|
return false;
|
|
149
153
|
});
|
|
@@ -181,9 +185,12 @@ function useTranscriptEdits(options) {
|
|
|
181
185
|
const previousState = undoStack[undoStack.length - 1];
|
|
182
186
|
setUndoStack((prev) => prev.slice(0, -1));
|
|
183
187
|
setEditedWords(previousState);
|
|
184
|
-
const
|
|
188
|
+
const baseline = initEditableWords(transcript, minSilenceMs, nlSilenceMs);
|
|
189
|
+
const isOriginal = previousState.length === baseline.length && previousState.every(
|
|
190
|
+
(ew, i) => ew.originalIndex === i && !ew.deleted && !ew.inserted && ew.word.text === baseline[i].word.text
|
|
191
|
+
);
|
|
185
192
|
setHasEdits(!isOriginal);
|
|
186
|
-
}, [undoStack, transcript
|
|
193
|
+
}, [undoStack, transcript, minSilenceMs, nlSilenceMs]);
|
|
187
194
|
const toggleWordDeleted = useCallback(
|
|
188
195
|
(index) => {
|
|
189
196
|
const ew = editedWords[index];
|
|
@@ -282,7 +289,7 @@ function useTranscriptEdits(options) {
|
|
|
282
289
|
const splitSilence = useCallback(
|
|
283
290
|
(index, durationsSec) => {
|
|
284
291
|
const ew = editedWords[index];
|
|
285
|
-
if (!ew || ew.word.wordType
|
|
292
|
+
if (!ew || !isSilenceType(ew.word.wordType)) return;
|
|
286
293
|
pushUndo();
|
|
287
294
|
const silenceStart = ew.word.startMs;
|
|
288
295
|
const newSilences = [];
|
|
@@ -331,14 +338,14 @@ function useTranscriptEdits(options) {
|
|
|
331
338
|
const silenceThresholdMs = removeSilenceAboveSec !== null ? removeSilenceAboveSec * 1e3 : null;
|
|
332
339
|
const newEditedWords = editedWords.map((ew) => {
|
|
333
340
|
if (ew.deleted) return ew;
|
|
334
|
-
if ((ew.word.wordType
|
|
341
|
+
if (isSilenceType(ew.word.wordType) && silenceThresholdMs !== null) {
|
|
335
342
|
const durationMs = ew.word.endMs - ew.word.startMs;
|
|
336
343
|
if (durationMs > silenceThresholdMs) {
|
|
337
344
|
return { ...ew, deleted: true };
|
|
338
345
|
}
|
|
339
346
|
return ew;
|
|
340
347
|
}
|
|
341
|
-
if (ew.word.wordType
|
|
348
|
+
if (!isSilenceType(ew.word.wordType)) {
|
|
342
349
|
const wordText = normalizeWordText(ew.word.text);
|
|
343
350
|
if (fillerSet.has(wordText)) {
|
|
344
351
|
return { ...ew, deleted: true };
|
|
@@ -362,9 +369,11 @@ function useTranscriptEdits(options) {
|
|
|
362
369
|
setMinSilenceMs(newMinSilenceMs);
|
|
363
370
|
setNlSilenceMs(newNlSilenceMs);
|
|
364
371
|
const wordDeletedStatus = /* @__PURE__ */ new Map();
|
|
372
|
+
let saveIdx = 0;
|
|
365
373
|
editedWords.forEach((ew) => {
|
|
366
|
-
if (ew.word.wordType
|
|
367
|
-
wordDeletedStatus.set(
|
|
374
|
+
if (!isSilenceType(ew.word.wordType) && ew.originalIndex >= 0 && !ew.inserted) {
|
|
375
|
+
wordDeletedStatus.set(saveIdx, ew.deleted);
|
|
376
|
+
saveIdx++;
|
|
368
377
|
}
|
|
369
378
|
});
|
|
370
379
|
const newEditedWords = initEditableWords(
|
|
@@ -374,7 +383,7 @@ function useTranscriptEdits(options) {
|
|
|
374
383
|
);
|
|
375
384
|
let wordIdx = 0;
|
|
376
385
|
const restoredWords = newEditedWords.map((ew) => {
|
|
377
|
-
if (ew.word.wordType
|
|
386
|
+
if (!isSilenceType(ew.word.wordType)) {
|
|
378
387
|
const wasDeleted = wordDeletedStatus.get(wordIdx) ?? false;
|
|
379
388
|
wordIdx++;
|
|
380
389
|
return { ...ew, deleted: wasDeleted };
|
|
@@ -382,6 +391,7 @@ function useTranscriptEdits(options) {
|
|
|
382
391
|
return ew;
|
|
383
392
|
});
|
|
384
393
|
setEditedWords(restoredWords);
|
|
394
|
+
setUndoStack([]);
|
|
385
395
|
},
|
|
386
396
|
[editedWords, transcript]
|
|
387
397
|
);
|
|
@@ -433,16 +443,16 @@ function useTranscriptEdits(options) {
|
|
|
433
443
|
);
|
|
434
444
|
const stats = useMemo(() => {
|
|
435
445
|
const activeWordCount = editedWords.filter(
|
|
436
|
-
(ew) => !ew.deleted && ew.word.wordType
|
|
446
|
+
(ew) => !ew.deleted && !isSilenceType(ew.word.wordType)
|
|
437
447
|
).length;
|
|
438
448
|
const activeSilenceCount = editedWords.filter(
|
|
439
|
-
(ew) => !ew.deleted && ew.word.wordType
|
|
449
|
+
(ew) => !ew.deleted && isSilenceType(ew.word.wordType)
|
|
440
450
|
).length;
|
|
441
451
|
const deletedWordCount = editedWords.filter(
|
|
442
|
-
(ew) => ew.deleted && ew.word.wordType
|
|
452
|
+
(ew) => ew.deleted && !isSilenceType(ew.word.wordType)
|
|
443
453
|
).length;
|
|
444
454
|
const deletedSilenceCount = editedWords.filter(
|
|
445
|
-
(ew) => ew.deleted && ew.word.wordType
|
|
455
|
+
(ew) => ew.deleted && isSilenceType(ew.word.wordType)
|
|
446
456
|
).length;
|
|
447
457
|
const editedDurationMs = editedWords.reduce((sum, ew, index) => {
|
|
448
458
|
if (ew.deleted) return sum;
|
|
@@ -461,26 +471,15 @@ function useTranscriptEdits(options) {
|
|
|
461
471
|
const fillerAnalysis = useMemo(() => {
|
|
462
472
|
const matchCounts = /* @__PURE__ */ new Map();
|
|
463
473
|
for (const ew of editedWords) {
|
|
464
|
-
if (ew.deleted || ew.word.wordType
|
|
474
|
+
if (ew.deleted || isSilenceType(ew.word.wordType)) continue;
|
|
465
475
|
const wordText = normalizeWordText(ew.word.text);
|
|
466
|
-
for (const filler of DEFAULT_FILLER_WORDS) {
|
|
467
|
-
if (wordText === filler) {
|
|
468
|
-
matchCounts.set(filler, (matchCounts.get(filler) || 0) + 1);
|
|
469
|
-
}
|
|
470
|
-
}
|
|
471
476
|
matchCounts.set(wordText, (matchCounts.get(wordText) || 0) + 1);
|
|
472
477
|
}
|
|
473
478
|
const durations = /* @__PURE__ */ new Map();
|
|
474
479
|
for (const ew of editedWords) {
|
|
475
|
-
if (ew.deleted || ew.word.wordType
|
|
476
|
-
continue;
|
|
480
|
+
if (ew.deleted || isSilenceType(ew.word.wordType)) continue;
|
|
477
481
|
const wordText = normalizeWordText(ew.word.text);
|
|
478
482
|
const wordDuration = ew.word.endMs - ew.word.startMs;
|
|
479
|
-
for (const filler of DEFAULT_FILLER_WORDS) {
|
|
480
|
-
if (wordText === filler) {
|
|
481
|
-
durations.set(filler, (durations.get(filler) || 0) + wordDuration);
|
|
482
|
-
}
|
|
483
|
-
}
|
|
484
483
|
durations.set(wordText, (durations.get(wordText) || 0) + wordDuration);
|
|
485
484
|
}
|
|
486
485
|
const silenceCounts = SILENCE_ANALYSIS_THRESHOLDS.map((threshold) => {
|
|
@@ -489,8 +488,7 @@ function useTranscriptEdits(options) {
|
|
|
489
488
|
let durationMs = 0;
|
|
490
489
|
for (const ew of editedWords) {
|
|
491
490
|
if (ew.deleted) continue;
|
|
492
|
-
if (ew.word.wordType
|
|
493
|
-
continue;
|
|
491
|
+
if (!isSilenceType(ew.word.wordType)) continue;
|
|
494
492
|
const silenceDuration = ew.word.endMs - ew.word.startMs;
|
|
495
493
|
if (silenceDuration > thresholdMs) {
|
|
496
494
|
count++;
|
|
@@ -539,5 +537,5 @@ function useTranscriptEdits(options) {
|
|
|
539
537
|
}
|
|
540
538
|
|
|
541
539
|
export { DEFAULT_FILLER_WORDS, DEFAULT_MIN_SILENCE_MS, DEFAULT_NL_SILENCE_MS, buildPlaybackSegments, getSpeedAtIndex, initEditableWords, insertSilences, useTranscriptEdits };
|
|
542
|
-
//# sourceMappingURL=chunk-
|
|
543
|
-
//# sourceMappingURL=chunk-
|
|
540
|
+
//# sourceMappingURL=chunk-OOYEHBYJ.js.map
|
|
541
|
+
//# sourceMappingURL=chunk-OOYEHBYJ.js.map
|