@mieweb/ui 0.6.1 → 0.7.0-dev.178

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.
Files changed (450) hide show
  1. package/README.md +90 -53
  2. package/dist/CsvBlock-2A5VEDD3.cjs +15 -0
  3. package/dist/CsvBlock-2A5VEDD3.cjs.map +1 -0
  4. package/dist/CsvBlock-D6PWAJ5X.js +6 -0
  5. package/dist/CsvBlock-D6PWAJ5X.js.map +1 -0
  6. package/dist/HtmlPreviewBlock-PEHTJ6C3.js +6 -0
  7. package/dist/HtmlPreviewBlock-PEHTJ6C3.js.map +1 -0
  8. package/dist/HtmlPreviewBlock-SYXCV5RH.cjs +15 -0
  9. package/dist/HtmlPreviewBlock-SYXCV5RH.cjs.map +1 -0
  10. package/dist/MedicationEditor-Bp4NLy7y.d.cts +352 -0
  11. package/dist/MedicationEditor-Bp4NLy7y.d.ts +352 -0
  12. package/dist/MermaidBlock-7NK3AVK2.js +6 -0
  13. package/dist/MermaidBlock-7NK3AVK2.js.map +1 -0
  14. package/dist/MermaidBlock-AFXNP5NK.cjs +15 -0
  15. package/dist/MermaidBlock-AFXNP5NK.cjs.map +1 -0
  16. package/dist/SurveyBlock-6KRNKFH5.cjs +15 -0
  17. package/dist/SurveyBlock-6KRNKFH5.cjs.map +1 -0
  18. package/dist/SurveyBlock-NNDGXGG4.js +6 -0
  19. package/dist/SurveyBlock-NNDGXGG4.js.map +1 -0
  20. package/dist/ag-grid.cjs +6 -6
  21. package/dist/ag-grid.cjs.map +1 -1
  22. package/dist/ag-grid.js +2 -2
  23. package/dist/ag-grid.js.map +1 -1
  24. package/dist/brands/index.cjs +17 -17
  25. package/dist/brands/index.js +4 -4
  26. package/dist/chunk-372IIHUA.cjs +2017 -0
  27. package/dist/chunk-372IIHUA.cjs.map +1 -0
  28. package/dist/{chunk-2DS3RJ2D.js → chunk-3TERETXH.js} +112 -3
  29. package/dist/chunk-3TERETXH.js.map +1 -0
  30. package/dist/chunk-44CK4CT2.cjs +336 -0
  31. package/dist/chunk-44CK4CT2.cjs.map +1 -0
  32. package/dist/{chunk-FSBFQBNE.cjs → chunk-4GXECTPS.cjs} +2 -2
  33. package/dist/{chunk-FSBFQBNE.cjs.map → chunk-4GXECTPS.cjs.map} +1 -1
  34. package/dist/chunk-4LVPQ44A.js +228 -0
  35. package/dist/chunk-4LVPQ44A.js.map +1 -0
  36. package/dist/{chunk-6555OYRU.js → chunk-5BQE6BEL.js} +2 -2
  37. package/dist/{chunk-6555OYRU.js.map → chunk-5BQE6BEL.js.map} +1 -1
  38. package/dist/chunk-62ZOA6PX.js +31 -0
  39. package/dist/chunk-62ZOA6PX.js.map +1 -0
  40. package/dist/chunk-63KVQHGQ.cjs +1802 -0
  41. package/dist/chunk-63KVQHGQ.cjs.map +1 -0
  42. package/dist/chunk-6AHYYWVB.js +78 -0
  43. package/dist/chunk-6AHYYWVB.js.map +1 -0
  44. package/dist/chunk-6I7IDZ4A.js +51 -0
  45. package/dist/chunk-6I7IDZ4A.js.map +1 -0
  46. package/dist/chunk-6ZYE6JUK.cjs +80 -0
  47. package/dist/chunk-6ZYE6JUK.cjs.map +1 -0
  48. package/dist/chunk-7QXG5BBB.cjs +164 -0
  49. package/dist/chunk-7QXG5BBB.cjs.map +1 -0
  50. package/dist/chunk-7WMSUXOQ.js +182 -0
  51. package/dist/chunk-7WMSUXOQ.js.map +1 -0
  52. package/dist/chunk-7XUN3OQT.js +3 -0
  53. package/dist/{chunk-V2DF2GUE.js.map → chunk-7XUN3OQT.js.map} +1 -1
  54. package/dist/chunk-7ZVTLTJF.js +109 -0
  55. package/dist/chunk-7ZVTLTJF.js.map +1 -0
  56. package/dist/chunk-AES2BKEW.cjs +229 -0
  57. package/dist/chunk-AES2BKEW.cjs.map +1 -0
  58. package/dist/chunk-AFKKJEV5.cjs +72 -0
  59. package/dist/chunk-AFKKJEV5.cjs.map +1 -0
  60. package/dist/chunk-AT732HC6.cjs +4 -0
  61. package/dist/{chunk-74K3RRU7.cjs.map → chunk-AT732HC6.cjs.map} +1 -1
  62. package/dist/chunk-BB4WQ4LV.cjs +137 -0
  63. package/dist/chunk-BB4WQ4LV.cjs.map +1 -0
  64. package/dist/chunk-BIT27PPD.js +49 -0
  65. package/dist/chunk-BIT27PPD.js.map +1 -0
  66. package/dist/chunk-BLPCYP4D.cjs +537 -0
  67. package/dist/chunk-BLPCYP4D.cjs.map +1 -0
  68. package/dist/chunk-BT3ZQJGT.cjs +130 -0
  69. package/dist/chunk-BT3ZQJGT.cjs.map +1 -0
  70. package/dist/chunk-BX6BTDTR.js +34 -0
  71. package/dist/chunk-BX6BTDTR.js.map +1 -0
  72. package/dist/chunk-C2544GKZ.js +313 -0
  73. package/dist/chunk-C2544GKZ.js.map +1 -0
  74. package/dist/chunk-C7RVKV25.cjs +25 -0
  75. package/dist/chunk-C7RVKV25.cjs.map +1 -0
  76. package/dist/chunk-CKD554XR.cjs +100 -0
  77. package/dist/chunk-CKD554XR.cjs.map +1 -0
  78. package/dist/chunk-CVC4NWFA.cjs +154 -0
  79. package/dist/chunk-CVC4NWFA.cjs.map +1 -0
  80. package/dist/{chunk-K3IVCUPP.js → chunk-CYMZ2QS5.js} +2 -2
  81. package/dist/{chunk-K3IVCUPP.js.map → chunk-CYMZ2QS5.js.map} +1 -1
  82. package/dist/{chunk-FRT6RQND.cjs → chunk-DAPZPT5N.cjs} +92 -56
  83. package/dist/chunk-DAPZPT5N.cjs.map +1 -0
  84. package/dist/chunk-DHKYGVP7.js +3 -0
  85. package/dist/{chunk-LEMY57MI.js.map → chunk-DHKYGVP7.js.map} +1 -1
  86. package/dist/chunk-DLNJLCNO.cjs +101 -0
  87. package/dist/chunk-DLNJLCNO.cjs.map +1 -0
  88. package/dist/chunk-DUPR6FEL.js +43 -0
  89. package/dist/chunk-DUPR6FEL.js.map +1 -0
  90. package/dist/{chunk-4FALCEJI.cjs → chunk-EL2RSQTJ.cjs} +2 -2
  91. package/dist/{chunk-4FALCEJI.cjs.map → chunk-EL2RSQTJ.cjs.map} +1 -1
  92. package/dist/chunk-ERLPVXOV.js +22 -0
  93. package/dist/chunk-ERLPVXOV.js.map +1 -0
  94. package/dist/chunk-FIWKHLWY.js +197 -0
  95. package/dist/chunk-FIWKHLWY.js.map +1 -0
  96. package/dist/chunk-FJH7P5WG.js +513 -0
  97. package/dist/chunk-FJH7P5WG.js.map +1 -0
  98. package/dist/chunk-FSGEDDF2.cjs +33 -0
  99. package/dist/chunk-FSGEDDF2.cjs.map +1 -0
  100. package/dist/chunk-GLXTVCHN.cjs +4 -0
  101. package/dist/{chunk-4ZU53GNR.cjs.map → chunk-GLXTVCHN.cjs.map} +1 -1
  102. package/dist/chunk-HRS6W74P.js +1568 -0
  103. package/dist/chunk-HRS6W74P.js.map +1 -0
  104. package/dist/chunk-I2W24RHW.js +196 -0
  105. package/dist/chunk-I2W24RHW.js.map +1 -0
  106. package/dist/chunk-I6CY5C6A.js +12 -0
  107. package/dist/chunk-I6CY5C6A.js.map +1 -0
  108. package/dist/chunk-IQ4KQJAO.js +3 -0
  109. package/dist/chunk-IQ4KQJAO.js.map +1 -0
  110. package/dist/chunk-IWDQPSJN.cjs +1452 -0
  111. package/dist/chunk-IWDQPSJN.cjs.map +1 -0
  112. package/dist/chunk-J7KWQJOB.js +14 -0
  113. package/dist/chunk-J7KWQJOB.js.map +1 -0
  114. package/dist/{chunk-R25H4N4Z.js → chunk-J7Z7467B.js} +92 -56
  115. package/dist/chunk-J7Z7467B.js.map +1 -0
  116. package/dist/{chunk-NINI4WVS.cjs → chunk-JC6Y3LGF.cjs} +297 -84
  117. package/dist/chunk-JC6Y3LGF.cjs.map +1 -0
  118. package/dist/chunk-JCNPVK74.cjs +347 -0
  119. package/dist/chunk-JCNPVK74.cjs.map +1 -0
  120. package/dist/chunk-JFLC7SHM.cjs +35 -0
  121. package/dist/chunk-JFLC7SHM.cjs.map +1 -0
  122. package/dist/chunk-JHYFHEHS.js +1967 -0
  123. package/dist/chunk-JHYFHEHS.js.map +1 -0
  124. package/dist/{chunk-IBZXDX4L.cjs → chunk-JQEY53SH.cjs} +112 -3
  125. package/dist/chunk-JQEY53SH.cjs.map +1 -0
  126. package/dist/chunk-JTBQNOSL.cjs +1605 -0
  127. package/dist/chunk-JTBQNOSL.cjs.map +1 -0
  128. package/dist/chunk-JYZW2PZS.cjs +166 -0
  129. package/dist/chunk-JYZW2PZS.cjs.map +1 -0
  130. package/dist/chunk-KBEKQMVY.cjs +198 -0
  131. package/dist/chunk-KBEKQMVY.cjs.map +1 -0
  132. package/dist/chunk-KJ5BSGEO.cjs +258 -0
  133. package/dist/chunk-KJ5BSGEO.cjs.map +1 -0
  134. package/dist/{chunk-DNPRRYPQ.js → chunk-KL2S36FM.js} +2 -2
  135. package/dist/chunk-KL2S36FM.js.map +1 -0
  136. package/dist/chunk-LIH3IZYK.js +689 -0
  137. package/dist/chunk-LIH3IZYK.js.map +1 -0
  138. package/dist/chunk-MAMY5HTT.cjs +1177 -0
  139. package/dist/chunk-MAMY5HTT.cjs.map +1 -0
  140. package/dist/{chunk-WFS6R2F5.js → chunk-MKWGKASO.js} +114 -101
  141. package/dist/chunk-MKWGKASO.js.map +1 -0
  142. package/dist/{chunk-CV4CVGLO.cjs → chunk-MZPF2QGM.cjs} +95 -74
  143. package/dist/chunk-MZPF2QGM.cjs.map +1 -0
  144. package/dist/chunk-NQME7MCK.js +1416 -0
  145. package/dist/chunk-NQME7MCK.js.map +1 -0
  146. package/dist/chunk-NTYGCBCL.js +543 -0
  147. package/dist/chunk-NTYGCBCL.js.map +1 -0
  148. package/dist/chunk-OF7NTZ2I.js +3 -0
  149. package/dist/chunk-OF7NTZ2I.js.map +1 -0
  150. package/dist/chunk-OXYFTCRW.cjs +57 -0
  151. package/dist/chunk-OXYFTCRW.cjs.map +1 -0
  152. package/dist/chunk-QA6ZDHFP.js +117 -0
  153. package/dist/chunk-QA6ZDHFP.js.map +1 -0
  154. package/dist/chunk-RHNPILZQ.cjs +4 -0
  155. package/dist/chunk-RHNPILZQ.cjs.map +1 -0
  156. package/dist/chunk-RHYIFIT5.js +98 -0
  157. package/dist/chunk-RHYIFIT5.js.map +1 -0
  158. package/dist/chunk-RI56YPED.cjs +201 -0
  159. package/dist/chunk-RI56YPED.cjs.map +1 -0
  160. package/dist/chunk-RISZWWEQ.js +3 -0
  161. package/dist/chunk-RISZWWEQ.js.map +1 -0
  162. package/dist/chunk-S6Z3KDEM.js +140 -0
  163. package/dist/chunk-S6Z3KDEM.js.map +1 -0
  164. package/dist/chunk-S7JQ3FV5.cjs +16 -0
  165. package/dist/chunk-S7JQ3FV5.cjs.map +1 -0
  166. package/dist/{chunk-OXGUG57G.cjs → chunk-SNEQXSC5.cjs} +2 -2
  167. package/dist/{chunk-OXGUG57G.cjs.map → chunk-SNEQXSC5.cjs.map} +1 -1
  168. package/dist/chunk-SQHMGT4W.js +164 -0
  169. package/dist/chunk-SQHMGT4W.js.map +1 -0
  170. package/dist/{chunk-JHPFOG2N.cjs → chunk-ST2RE5UB.cjs} +30 -18
  171. package/dist/chunk-ST2RE5UB.cjs.map +1 -0
  172. package/dist/{chunk-QVJBUWJQ.js → chunk-STPK44AU.js} +46 -12
  173. package/dist/chunk-STPK44AU.js.map +1 -0
  174. package/dist/chunk-T3C4RNJ4.js +106 -0
  175. package/dist/chunk-T3C4RNJ4.js.map +1 -0
  176. package/dist/chunk-T3RWXOCM.js +148 -0
  177. package/dist/chunk-T3RWXOCM.js.map +1 -0
  178. package/dist/{chunk-DCER2QQB.js → chunk-T42BCIUA.js} +2 -2
  179. package/dist/{chunk-DCER2QQB.js.map → chunk-T42BCIUA.js.map} +1 -1
  180. package/dist/{chunk-OYKS2JBB.cjs → chunk-TN33E2VN.cjs} +2 -2
  181. package/dist/chunk-TN33E2VN.cjs.map +1 -0
  182. package/dist/{chunk-K7IGBNZA.cjs → chunk-TR2OJKQ4.cjs} +46 -12
  183. package/dist/chunk-TR2OJKQ4.cjs.map +1 -0
  184. package/dist/chunk-UFYXU7KV.js +135 -0
  185. package/dist/chunk-UFYXU7KV.js.map +1 -0
  186. package/dist/chunk-UM6NA7HL.js +1145 -0
  187. package/dist/chunk-UM6NA7HL.js.map +1 -0
  188. package/dist/chunk-UO3KEUYK.cjs +220 -0
  189. package/dist/chunk-UO3KEUYK.cjs.map +1 -0
  190. package/dist/chunk-UOOH356R.cjs +66 -0
  191. package/dist/chunk-UOOH356R.cjs.map +1 -0
  192. package/dist/{chunk-4ZU53GNR.cjs → chunk-UTYUT5YY.cjs} +62 -2
  193. package/dist/chunk-UTYUT5YY.cjs.map +1 -0
  194. package/dist/chunk-UVSODK6V.cjs +53 -0
  195. package/dist/chunk-UVSODK6V.cjs.map +1 -0
  196. package/dist/chunk-V25Z5GR6.cjs +184 -0
  197. package/dist/chunk-V25Z5GR6.cjs.map +1 -0
  198. package/dist/chunk-VBWRH4UW.cjs +4 -0
  199. package/dist/chunk-VBWRH4UW.cjs.map +1 -0
  200. package/dist/chunk-VJOVJTFP.cjs +370 -0
  201. package/dist/chunk-VJOVJTFP.cjs.map +1 -0
  202. package/dist/{chunk-7BARESXI.cjs → chunk-VPNURIAY.cjs} +114 -101
  203. package/dist/chunk-VPNURIAY.cjs.map +1 -0
  204. package/dist/{chunk-I56VBDSC.js → chunk-XDFDVF2O.js} +30 -18
  205. package/dist/chunk-XDFDVF2O.js.map +1 -0
  206. package/dist/chunk-XL7TTKHP.js +327 -0
  207. package/dist/chunk-XL7TTKHP.js.map +1 -0
  208. package/dist/chunk-Y2S6QMKU.js +78 -0
  209. package/dist/chunk-Y2S6QMKU.js.map +1 -0
  210. package/dist/chunk-Y4ESBDQ5.cjs +552 -0
  211. package/dist/chunk-Y4ESBDQ5.cjs.map +1 -0
  212. package/dist/chunk-Y5KEFV5O.js +192 -0
  213. package/dist/chunk-Y5KEFV5O.js.map +1 -0
  214. package/dist/chunk-YBLIDESO.js +365 -0
  215. package/dist/chunk-YBLIDESO.js.map +1 -0
  216. package/dist/chunk-YVLP3ATI.js +1776 -0
  217. package/dist/chunk-YVLP3ATI.js.map +1 -0
  218. package/dist/chunk-YVPC65ZJ.cjs +134 -0
  219. package/dist/chunk-YVPC65ZJ.cjs.map +1 -0
  220. package/dist/{chunk-MPOWJVV4.js → chunk-YZT62IMX.js} +95 -74
  221. package/dist/chunk-YZT62IMX.js.map +1 -0
  222. package/dist/chunk-ZAIEQWRA.js +207 -0
  223. package/dist/chunk-ZAIEQWRA.js.map +1 -0
  224. package/dist/chunk-ZDEYV373.cjs +139 -0
  225. package/dist/chunk-ZDEYV373.cjs.map +1 -0
  226. package/dist/{chunk-Q7NBJFEB.js → chunk-ZGSC2CB2.js} +2 -2
  227. package/dist/{chunk-Q7NBJFEB.js.map → chunk-ZGSC2CB2.js.map} +1 -1
  228. package/dist/{chunk-3M4P2KMG.cjs → chunk-ZHBANUBI.cjs} +2 -2
  229. package/dist/{chunk-3M4P2KMG.cjs.map → chunk-ZHBANUBI.cjs.map} +1 -1
  230. package/dist/components/AlertDialog/index.cjs +18 -0
  231. package/dist/components/AlertDialog/index.cjs.map +1 -0
  232. package/dist/components/AlertDialog/index.d.cts +56 -0
  233. package/dist/components/AlertDialog/index.d.ts +56 -0
  234. package/dist/components/AlertDialog/index.js +9 -0
  235. package/dist/components/AlertDialog/index.js.map +1 -0
  236. package/dist/components/AudioRecorder/index.d.cts +1 -1
  237. package/dist/components/AudioRecorder/index.d.ts +1 -1
  238. package/dist/components/Autocomplete/index.cjs +16 -0
  239. package/dist/components/Autocomplete/index.cjs.map +1 -0
  240. package/dist/components/Autocomplete/index.d.cts +77 -0
  241. package/dist/components/Autocomplete/index.d.ts +77 -0
  242. package/dist/components/Autocomplete/index.js +7 -0
  243. package/dist/components/Autocomplete/index.js.map +1 -0
  244. package/dist/components/Badge/index.cjs +4 -3
  245. package/dist/components/Badge/index.js +2 -1
  246. package/dist/components/Card/index.cjs +16 -15
  247. package/dist/components/Card/index.js +2 -1
  248. package/dist/components/Collapsible/index.cjs +21 -0
  249. package/dist/components/Collapsible/index.cjs.map +1 -0
  250. package/dist/components/Collapsible/index.d.cts +33 -0
  251. package/dist/components/Collapsible/index.d.ts +33 -0
  252. package/dist/components/Collapsible/index.js +4 -0
  253. package/dist/components/Collapsible/index.js.map +1 -0
  254. package/dist/components/CountryCodeDropdown/index.cjs +6 -5
  255. package/dist/components/CountryCodeDropdown/index.js +3 -2
  256. package/dist/components/DateInput/index.cjs +2 -2
  257. package/dist/components/DateInput/index.d.cts +8 -2
  258. package/dist/components/DateInput/index.d.ts +8 -2
  259. package/dist/components/DateInput/index.js +1 -1
  260. package/dist/components/Dropdown/index.cjs +9 -8
  261. package/dist/components/Dropdown/index.d.cts +2 -1
  262. package/dist/components/Dropdown/index.d.ts +2 -1
  263. package/dist/components/Dropdown/index.js +3 -2
  264. package/dist/components/FloatingWindow/index.cjs +18 -0
  265. package/dist/components/FloatingWindow/index.cjs.map +1 -0
  266. package/dist/components/FloatingWindow/index.d.cts +64 -0
  267. package/dist/components/FloatingWindow/index.d.ts +64 -0
  268. package/dist/components/FloatingWindow/index.js +5 -0
  269. package/dist/components/FloatingWindow/index.js.map +1 -0
  270. package/dist/components/Label/index.cjs +17 -0
  271. package/dist/components/Label/index.cjs.map +1 -0
  272. package/dist/components/Label/index.d.cts +23 -0
  273. package/dist/components/Label/index.d.ts +23 -0
  274. package/dist/components/Label/index.js +4 -0
  275. package/dist/components/Label/index.js.map +1 -0
  276. package/dist/components/Markdown/index.cjs +51 -0
  277. package/dist/components/Markdown/index.cjs.map +1 -0
  278. package/dist/components/Markdown/index.css +331 -0
  279. package/dist/components/Markdown/index.css.map +1 -0
  280. package/dist/components/Markdown/index.d.cts +82 -0
  281. package/dist/components/Markdown/index.d.ts +82 -0
  282. package/dist/components/Markdown/index.js +10 -0
  283. package/dist/components/Markdown/index.js.map +1 -0
  284. package/dist/components/Markdown/styles.css +354 -0
  285. package/dist/components/MediaEditor/index.cjs +44 -0
  286. package/dist/components/MediaEditor/index.cjs.map +1 -0
  287. package/dist/components/MediaEditor/index.d.cts +151 -0
  288. package/dist/components/MediaEditor/index.d.ts +151 -0
  289. package/dist/components/MediaEditor/index.js +19 -0
  290. package/dist/components/MediaEditor/index.js.map +1 -0
  291. package/dist/components/MediaPlayer/index.cjs +24 -0
  292. package/dist/components/MediaPlayer/index.cjs.map +1 -0
  293. package/dist/components/MediaPlayer/index.d.cts +71 -0
  294. package/dist/components/MediaPlayer/index.d.ts +71 -0
  295. package/dist/components/MediaPlayer/index.js +7 -0
  296. package/dist/components/MediaPlayer/index.js.map +1 -0
  297. package/dist/components/RecordButton/index.cjs +4 -4
  298. package/dist/components/RecordButton/index.js +1 -1
  299. package/dist/components/RichTextEditor/index.cjs +33 -0
  300. package/dist/components/RichTextEditor/index.cjs.map +1 -0
  301. package/dist/components/RichTextEditor/index.d.cts +62 -0
  302. package/dist/components/RichTextEditor/index.d.ts +62 -0
  303. package/dist/components/RichTextEditor/index.js +12 -0
  304. package/dist/components/RichTextEditor/index.js.map +1 -0
  305. package/dist/components/ScrollArea/index.cjs +17 -0
  306. package/dist/components/ScrollArea/index.cjs.map +1 -0
  307. package/dist/components/ScrollArea/index.d.cts +22 -0
  308. package/dist/components/ScrollArea/index.d.ts +22 -0
  309. package/dist/components/ScrollArea/index.js +4 -0
  310. package/dist/components/ScrollArea/index.js.map +1 -0
  311. package/dist/components/Select/index.cjs +5 -3
  312. package/dist/components/Select/index.js +3 -1
  313. package/dist/components/Separator/index.cjs +17 -0
  314. package/dist/components/Separator/index.cjs.map +1 -0
  315. package/dist/components/Separator/index.d.cts +27 -0
  316. package/dist/components/Separator/index.d.ts +27 -0
  317. package/dist/components/Separator/index.js +4 -0
  318. package/dist/components/Separator/index.js.map +1 -0
  319. package/dist/components/Sheet/index.cjs +48 -0
  320. package/dist/components/Sheet/index.cjs.map +1 -0
  321. package/dist/components/Sheet/index.d.cts +62 -0
  322. package/dist/components/Sheet/index.d.ts +62 -0
  323. package/dist/components/Sheet/index.js +7 -0
  324. package/dist/components/Sheet/index.js.map +1 -0
  325. package/dist/components/SuperChat/index.cjs +1373 -0
  326. package/dist/components/SuperChat/index.cjs.map +1 -0
  327. package/dist/components/SuperChat/index.d.cts +189 -0
  328. package/dist/components/SuperChat/index.d.ts +189 -0
  329. package/dist/components/SuperChat/index.js +1336 -0
  330. package/dist/components/SuperChat/index.js.map +1 -0
  331. package/dist/components/SuperChat/plugins/index.cjs +1292 -0
  332. package/dist/components/SuperChat/plugins/index.cjs.map +1 -0
  333. package/dist/components/SuperChat/plugins/index.d.cts +233 -0
  334. package/dist/components/SuperChat/plugins/index.d.ts +233 -0
  335. package/dist/components/SuperChat/plugins/index.js +1252 -0
  336. package/dist/components/SuperChat/plugins/index.js.map +1 -0
  337. package/dist/components/Table/index.cjs +9 -9
  338. package/dist/components/Table/index.d.cts +4 -0
  339. package/dist/components/Table/index.d.ts +4 -0
  340. package/dist/components/Table/index.js +1 -1
  341. package/dist/components/ThemeProvider/index.cjs +7 -7
  342. package/dist/components/ThemeProvider/index.js +1 -1
  343. package/dist/components/Toggle/index.cjs +17 -0
  344. package/dist/components/Toggle/index.cjs.map +1 -0
  345. package/dist/components/Toggle/index.d.cts +28 -0
  346. package/dist/components/Toggle/index.d.ts +28 -0
  347. package/dist/components/Toggle/index.js +4 -0
  348. package/dist/components/Toggle/index.js.map +1 -0
  349. package/dist/components/TranscriptView/index.cjs +21 -0
  350. package/dist/components/TranscriptView/index.cjs.map +1 -0
  351. package/dist/components/TranscriptView/index.d.cts +55 -0
  352. package/dist/components/TranscriptView/index.d.ts +55 -0
  353. package/dist/components/TranscriptView/index.js +4 -0
  354. package/dist/components/TranscriptView/index.js.map +1 -0
  355. package/dist/datavis.cjs +268 -227
  356. package/dist/datavis.cjs.map +1 -1
  357. package/dist/datavis.d.cts +83 -9
  358. package/dist/datavis.d.ts +83 -9
  359. package/dist/datavis.js +235 -229
  360. package/dist/datavis.js.map +1 -1
  361. package/dist/esheet.cjs +184 -0
  362. package/dist/esheet.cjs.map +1 -1
  363. package/dist/esheet.d.cts +117 -0
  364. package/dist/esheet.d.ts +117 -0
  365. package/dist/esheet.js +163 -0
  366. package/dist/esheet.js.map +1 -1
  367. package/dist/hey-buddy-CLUVAY2X.cjs +1133 -0
  368. package/dist/hey-buddy-CLUVAY2X.cjs.map +1 -0
  369. package/dist/hey-buddy-NMSWZ4TN.js +1131 -0
  370. package/dist/hey-buddy-NMSWZ4TN.js.map +1 -0
  371. package/dist/hooks/index.cjs +76 -16
  372. package/dist/hooks/index.d.cts +151 -2
  373. package/dist/hooks/index.d.ts +151 -2
  374. package/dist/hooks/index.js +6 -2
  375. package/dist/html-MdxqSzjD.d.cts +13 -0
  376. package/dist/html-MdxqSzjD.d.ts +13 -0
  377. package/dist/index.cjs +10394 -6565
  378. package/dist/index.cjs.map +1 -1
  379. package/dist/index.css +331 -0
  380. package/dist/index.css.map +1 -0
  381. package/dist/index.d.cts +2020 -249
  382. package/dist/index.d.ts +2020 -249
  383. package/dist/index.js +9223 -5969
  384. package/dist/index.js.map +1 -1
  385. package/dist/kerebron.cjs +119 -0
  386. package/dist/kerebron.cjs.map +1 -0
  387. package/dist/kerebron.css +11 -0
  388. package/dist/kerebron.d.cts +23 -0
  389. package/dist/kerebron.d.ts +23 -0
  390. package/dist/kerebron.js +116 -0
  391. package/dist/kerebron.js.map +1 -0
  392. package/dist/nitroTableGrid-3J2GY6CK.cjs +47 -0
  393. package/dist/nitroTableGrid-3J2GY6CK.cjs.map +1 -0
  394. package/dist/nitroTableGrid-SIMT7635.js +25 -0
  395. package/dist/nitroTableGrid-SIMT7635.js.map +1 -0
  396. package/dist/orderRows-BUJYgSc7.d.cts +221 -0
  397. package/dist/orderRows-BUJYgSc7.d.ts +221 -0
  398. package/dist/speaker-verify-5GTWAN5Y.cjs +357 -0
  399. package/dist/speaker-verify-5GTWAN5Y.cjs.map +1 -0
  400. package/dist/speaker-verify-R67P433H.js +355 -0
  401. package/dist/speaker-verify-R67P433H.js.map +1 -0
  402. package/dist/styles/init.css +5 -0
  403. package/dist/styles.css +1 -1
  404. package/dist/tailwind-preset.cjs +4 -4
  405. package/dist/tailwind-preset.js +1 -1
  406. package/dist/transcript-oaWqY3yr.d.cts +81 -0
  407. package/dist/transcript-oaWqY3yr.d.ts +81 -0
  408. package/dist/types-BYnLjEFg.d.cts +248 -0
  409. package/dist/types-BYnLjEFg.d.ts +248 -0
  410. package/dist/types-CBh8Zlje.d.cts +240 -0
  411. package/dist/types-CyCwYBlr.d.ts +240 -0
  412. package/dist/useAnchoredPosition-nXdSFKHf.d.cts +65 -0
  413. package/dist/useAnchoredPosition-nXdSFKHf.d.ts +65 -0
  414. package/dist/useTranscriptEdits-BUylQFg0.d.cts +168 -0
  415. package/dist/useTranscriptEdits-CWYnjbGP.d.ts +168 -0
  416. package/dist/utils/index.cjs +27 -18
  417. package/dist/utils/index.d.cts +1 -0
  418. package/dist/utils/index.d.ts +1 -0
  419. package/dist/utils/index.js +3 -2
  420. package/package.json +180 -55
  421. package/dist/chunk-2DS3RJ2D.js.map +0 -1
  422. package/dist/chunk-74K3RRU7.cjs +0 -4
  423. package/dist/chunk-7BARESXI.cjs.map +0 -1
  424. package/dist/chunk-CV4CVGLO.cjs.map +0 -1
  425. package/dist/chunk-DNPRRYPQ.js.map +0 -1
  426. package/dist/chunk-FRT6RQND.cjs.map +0 -1
  427. package/dist/chunk-HYEJLKXI.js +0 -476
  428. package/dist/chunk-HYEJLKXI.js.map +0 -1
  429. package/dist/chunk-I56VBDSC.js.map +0 -1
  430. package/dist/chunk-IBZXDX4L.cjs.map +0 -1
  431. package/dist/chunk-IKMR2ADM.cjs +0 -25
  432. package/dist/chunk-IKMR2ADM.cjs.map +0 -1
  433. package/dist/chunk-JHPFOG2N.cjs.map +0 -1
  434. package/dist/chunk-K7IGBNZA.cjs.map +0 -1
  435. package/dist/chunk-LEMY57MI.js +0 -3
  436. package/dist/chunk-MPOWJVV4.js.map +0 -1
  437. package/dist/chunk-NINI4WVS.cjs.map +0 -1
  438. package/dist/chunk-OKBR6PX4.js +0 -23
  439. package/dist/chunk-OKBR6PX4.js.map +0 -1
  440. package/dist/chunk-OYKS2JBB.cjs.map +0 -1
  441. package/dist/chunk-QVJBUWJQ.js.map +0 -1
  442. package/dist/chunk-R25H4N4Z.js.map +0 -1
  443. package/dist/chunk-V2DF2GUE.js +0 -3
  444. package/dist/chunk-WFS6R2F5.js.map +0 -1
  445. package/dist/ozwell.cjs +0 -385
  446. package/dist/ozwell.cjs.map +0 -1
  447. package/dist/ozwell.d.cts +0 -15
  448. package/dist/ozwell.d.ts +0 -15
  449. package/dist/ozwell.js +0 -360
  450. package/dist/ozwell.js.map +0 -1
@@ -0,0 +1,1776 @@
1
+ import { PLAYBACK_SPEEDS } from './chunk-J7KWQJOB.js';
2
+ import { Slider } from './chunk-JBB25LFB.js';
3
+ import { MediaPlayer } from './chunk-S6Z3KDEM.js';
4
+ import { Checkbox } from './chunk-XCLQZ4FV.js';
5
+ import { Select } from './chunk-J7Z7467B.js';
6
+ import { Modal, ModalHeader, ModalTitle, ModalClose, ModalBody, ModalFooter } from './chunk-IUFDGB5O.js';
7
+ import { Input } from './chunk-PVUDXJAI.js';
8
+ import { Button } from './chunk-ZVSW2KS6.js';
9
+ import { useTranscriptEdits, DEFAULT_FILLER_WORDS } from './chunk-NTYGCBCL.js';
10
+ import * as React6 from 'react';
11
+ import { cva } from 'class-variance-authority';
12
+ import { jsxs, jsx, Fragment } from 'react/jsx-runtime';
13
+
14
+ var SILENCE_THRESHOLD_OPTIONS = [0.3, 0.4, 0.5, 0.75, 1, 1.5, 2];
15
+ function formatDuration(ms) {
16
+ const totalSeconds = Math.round(ms / 1e3);
17
+ if (totalSeconds < 90) {
18
+ return `${totalSeconds}s`;
19
+ }
20
+ const minutes = Math.floor(totalSeconds / 60);
21
+ const seconds = totalSeconds % 60;
22
+ return `${minutes}:${String(seconds).padStart(2, "0")}`;
23
+ }
24
+ var FillerWordsModal = ({
25
+ isOpen,
26
+ onClose,
27
+ onApply,
28
+ matchingCounts,
29
+ fillerDurations,
30
+ silenceCounts,
31
+ currentDurationMs
32
+ }) => {
33
+ const [searchTerm, setSearchTerm] = React6.useState("");
34
+ const [selectedFillers, setSelectedFillers] = React6.useState(
35
+ new Set(DEFAULT_FILLER_WORDS)
36
+ );
37
+ const [customWord, setCustomWord] = React6.useState("");
38
+ const [removeSilence, setRemoveSilence] = React6.useState(false);
39
+ const [silenceThreshold, setSilenceThreshold] = React6.useState(0.4);
40
+ const filteredFillers = DEFAULT_FILLER_WORDS.filter(
41
+ (word) => word.toLowerCase().includes(searchTerm.toLowerCase())
42
+ ).sort((a, b) => {
43
+ const countA = matchingCounts.get(a) || 0;
44
+ const countB = matchingCounts.get(b) || 0;
45
+ if (countB !== countA) return countB - countA;
46
+ return a.localeCompare(b);
47
+ });
48
+ const customFillers = Array.from(selectedFillers).filter((word) => !DEFAULT_FILLER_WORDS.includes(word)).filter((word) => word.toLowerCase().includes(searchTerm.toLowerCase())).sort((a, b) => {
49
+ const countA = matchingCounts.get(a) || 0;
50
+ const countB = matchingCounts.get(b) || 0;
51
+ if (countB !== countA) return countB - countA;
52
+ return a.localeCompare(b);
53
+ });
54
+ const toggleFiller = (word) => {
55
+ setSelectedFillers((prev) => {
56
+ const next = new Set(prev);
57
+ if (next.has(word)) {
58
+ next.delete(word);
59
+ } else {
60
+ next.add(word);
61
+ }
62
+ return next;
63
+ });
64
+ };
65
+ const handleAddCustom = () => {
66
+ const trimmed = customWord.trim().toLowerCase();
67
+ if (trimmed && !selectedFillers.has(trimmed)) {
68
+ setSelectedFillers((prev) => /* @__PURE__ */ new Set([...prev, trimmed]));
69
+ setCustomWord("");
70
+ }
71
+ };
72
+ const silenceData = removeSilence ? silenceCounts.find((s) => s.threshold === silenceThreshold) || {
73
+ count: 0,
74
+ durationMs: 0
75
+ } : { count: 0, durationMs: 0 };
76
+ const silenceRemovalCount = silenceData.count;
77
+ const silenceDurationMs = silenceData.durationMs;
78
+ const handleApply = () => {
79
+ onApply(
80
+ Array.from(selectedFillers),
81
+ removeSilence ? silenceThreshold : null
82
+ );
83
+ onClose();
84
+ };
85
+ const selectAll = () => {
86
+ setSelectedFillers(/* @__PURE__ */ new Set([...DEFAULT_FILLER_WORDS, ...customFillers]));
87
+ };
88
+ const selectNone = () => {
89
+ setSelectedFillers(/* @__PURE__ */ new Set());
90
+ };
91
+ const fillerMatches = Array.from(selectedFillers).reduce(
92
+ (sum, word) => sum + (matchingCounts.get(word) || 0),
93
+ 0
94
+ );
95
+ const totalMatches = fillerMatches + silenceRemovalCount;
96
+ const fillerTimeSavedMs = Array.from(selectedFillers).reduce(
97
+ (sum, word) => sum + (fillerDurations.get(word) || 0),
98
+ 0
99
+ );
100
+ const totalTimeSavedMs = fillerTimeSavedMs + silenceDurationMs;
101
+ const newDurationMs = currentDurationMs - totalTimeSavedMs;
102
+ const renderFillerItem = (word, isCustom) => {
103
+ const count = matchingCounts.get(word) || 0;
104
+ return /* @__PURE__ */ jsxs(
105
+ "label",
106
+ {
107
+ className: "hover:bg-muted flex cursor-pointer items-center gap-2 rounded-md px-1.5 py-1 text-sm transition-colors",
108
+ children: [
109
+ /* @__PURE__ */ jsx(
110
+ Checkbox,
111
+ {
112
+ size: "sm",
113
+ checked: selectedFillers.has(word),
114
+ onChange: () => toggleFiller(word),
115
+ "aria-label": `Remove "${word}"`
116
+ }
117
+ ),
118
+ /* @__PURE__ */ jsx("span", { className: "text-foreground min-w-0 flex-1 truncate", children: word }),
119
+ count > 0 && /* @__PURE__ */ jsxs("span", { className: "text-muted-foreground text-xs", children: [
120
+ "(",
121
+ count,
122
+ ")"
123
+ ] }),
124
+ isCustom && /* @__PURE__ */ jsx(
125
+ "button",
126
+ {
127
+ type: "button",
128
+ 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",
129
+ onClick: (e) => {
130
+ e.preventDefault();
131
+ setSelectedFillers((prev) => {
132
+ const next = new Set(prev);
133
+ next.delete(word);
134
+ return next;
135
+ });
136
+ },
137
+ "aria-label": `Remove ${word}`,
138
+ children: "\xD7"
139
+ }
140
+ )
141
+ ]
142
+ },
143
+ word
144
+ );
145
+ };
146
+ return /* @__PURE__ */ jsxs(
147
+ Modal,
148
+ {
149
+ open: isOpen,
150
+ onOpenChange: (open) => {
151
+ if (!open) onClose();
152
+ },
153
+ size: "lg",
154
+ children: [
155
+ /* @__PURE__ */ jsxs(ModalHeader, { children: [
156
+ /* @__PURE__ */ jsx(ModalTitle, { children: "Remove Filler Words" }),
157
+ /* @__PURE__ */ jsx(ModalClose, { "aria-label": "Close modal" })
158
+ ] }),
159
+ /* @__PURE__ */ jsxs(ModalBody, { className: "flex flex-col gap-3", children: [
160
+ /* @__PURE__ */ jsx(
161
+ Input,
162
+ {
163
+ size: "sm",
164
+ type: "text",
165
+ placeholder: "Search filler words...",
166
+ value: searchTerm,
167
+ onChange: (e) => setSearchTerm(e.target.value),
168
+ "aria-label": "Search filler words"
169
+ }
170
+ ),
171
+ /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2", children: [
172
+ /* @__PURE__ */ jsx(Button, { variant: "ghost", size: "sm", onClick: selectAll, children: "Select All" }),
173
+ /* @__PURE__ */ jsx(Button, { variant: "ghost", size: "sm", onClick: selectNone, children: "Select None" })
174
+ ] }),
175
+ /* @__PURE__ */ jsxs("div", { className: "border-border bg-muted/40 flex flex-wrap items-center gap-2 rounded-lg border px-3 py-2", children: [
176
+ /* @__PURE__ */ jsx(
177
+ Checkbox,
178
+ {
179
+ size: "sm",
180
+ label: "Remove silences greater than",
181
+ checked: removeSilence,
182
+ onChange: (e) => setRemoveSilence(e.target.checked)
183
+ }
184
+ ),
185
+ /* @__PURE__ */ jsx("div", { className: "w-24", children: /* @__PURE__ */ jsx(
186
+ Select,
187
+ {
188
+ size: "sm",
189
+ options: SILENCE_THRESHOLD_OPTIONS.map((t) => ({
190
+ value: String(t),
191
+ label: `${t}s`
192
+ })),
193
+ value: String(silenceThreshold),
194
+ onValueChange: (value) => setSilenceThreshold(parseFloat(value)),
195
+ disabled: !removeSilence,
196
+ "aria-label": "Silence threshold in seconds"
197
+ }
198
+ ) }),
199
+ removeSilence && silenceRemovalCount > 0 && /* @__PURE__ */ jsxs("span", { className: "text-muted-foreground text-xs", children: [
200
+ "(",
201
+ silenceRemovalCount,
202
+ " silences)"
203
+ ] })
204
+ ] }),
205
+ /* @__PURE__ */ jsxs("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", children: [
206
+ filteredFillers.map((word) => renderFillerItem(word, false)),
207
+ customFillers.map((word) => renderFillerItem(word, true))
208
+ ] }),
209
+ /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2", children: [
210
+ /* @__PURE__ */ jsx(
211
+ Input,
212
+ {
213
+ size: "sm",
214
+ type: "text",
215
+ placeholder: "Add custom filler word...",
216
+ value: customWord,
217
+ onChange: (e) => setCustomWord(e.target.value),
218
+ onKeyDown: (e) => {
219
+ if (e.key === "Enter") {
220
+ e.preventDefault();
221
+ handleAddCustom();
222
+ }
223
+ },
224
+ "aria-label": "Add custom filler word"
225
+ }
226
+ ),
227
+ /* @__PURE__ */ jsx(
228
+ Button,
229
+ {
230
+ variant: "secondary",
231
+ size: "sm",
232
+ onClick: handleAddCustom,
233
+ disabled: !customWord.trim(),
234
+ children: "Add"
235
+ }
236
+ )
237
+ ] })
238
+ ] }),
239
+ /* @__PURE__ */ jsxs(ModalFooter, { className: "justify-between", children: [
240
+ /* @__PURE__ */ jsxs("span", { className: "text-muted-foreground text-sm", children: [
241
+ totalMatches,
242
+ " items \u2022 saves ",
243
+ formatDuration(totalTimeSavedMs),
244
+ " \u2192",
245
+ " ",
246
+ formatDuration(newDurationMs)
247
+ ] }),
248
+ /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2", children: [
249
+ /* @__PURE__ */ jsx(Button, { variant: "secondary", size: "sm", onClick: onClose, children: "Cancel" }),
250
+ /* @__PURE__ */ jsxs(
251
+ Button,
252
+ {
253
+ variant: "primary",
254
+ size: "sm",
255
+ onClick: handleApply,
256
+ disabled: totalMatches === 0,
257
+ children: [
258
+ "Mark as Deleted (",
259
+ totalMatches,
260
+ ")"
261
+ ]
262
+ }
263
+ )
264
+ ] })
265
+ ] })
266
+ ]
267
+ }
268
+ );
269
+ };
270
+ FillerWordsModal.displayName = "FillerWordsModal";
271
+ var WordEditorModal = ({
272
+ isOpen,
273
+ editableWord,
274
+ onClose,
275
+ onSave,
276
+ onSplitSilence,
277
+ onDelete
278
+ }) => {
279
+ const [inputValue, setInputValue] = React6.useState("");
280
+ const [error, setError] = React6.useState(null);
281
+ const inputRef = React6.useRef(null);
282
+ const isSilence = editableWord?.word.wordType === "silence";
283
+ const durationMs = editableWord ? editableWord.word.endMs - editableWord.word.startMs : 0;
284
+ const durationSec = durationMs / 1e3;
285
+ React6.useEffect(() => {
286
+ if (isOpen && editableWord) {
287
+ if (isSilence) {
288
+ setInputValue("");
289
+ } else {
290
+ setInputValue(editableWord.word.text);
291
+ }
292
+ setError(null);
293
+ setTimeout(() => inputRef.current?.focus(), 50);
294
+ }
295
+ }, [isOpen, editableWord, isSilence]);
296
+ const parseSilenceSplit = (input) => {
297
+ const trimmed = input.trim();
298
+ if (!trimmed) return null;
299
+ const parts = trimmed.split(/\s+/);
300
+ const durations = [];
301
+ let total = 0;
302
+ for (const part of parts) {
303
+ const num = parseFloat(part);
304
+ if (isNaN(num) || num <= 0) {
305
+ return {
306
+ durations: [],
307
+ remainder: 0,
308
+ error: `Invalid number: "${part}"`
309
+ };
310
+ }
311
+ durations.push(num);
312
+ total += num;
313
+ }
314
+ if (total >= durationSec) {
315
+ return {
316
+ durations: [],
317
+ remainder: 0,
318
+ error: `Total (${total.toFixed(1)}s) exceeds silence duration (${durationSec.toFixed(1)}s)`
319
+ };
320
+ }
321
+ const remainder = durationSec - total;
322
+ return { durations, remainder };
323
+ };
324
+ const handleApply = () => {
325
+ if (isSilence) {
326
+ const parsed = parseSilenceSplit(inputValue);
327
+ if (parsed?.error) {
328
+ setError(parsed.error);
329
+ return;
330
+ }
331
+ if (parsed && parsed.durations.length > 0) {
332
+ const allDurations = [...parsed.durations, parsed.remainder];
333
+ onSplitSilence(allDurations);
334
+ onClose();
335
+ }
336
+ } else {
337
+ const trimmed = inputValue.trim();
338
+ if (trimmed && trimmed !== editableWord?.word.text) {
339
+ onSave(trimmed);
340
+ }
341
+ onClose();
342
+ }
343
+ };
344
+ const handleKeyDown = (e) => {
345
+ if (e.key === "Enter") {
346
+ e.preventDefault();
347
+ handleApply();
348
+ }
349
+ };
350
+ const preview = isSilence ? parseSilenceSplit(inputValue) : null;
351
+ const applyDisabled = isSilence ? !inputValue.trim() || !!preview?.error || !preview || preview.durations.length === 0 : !inputValue.trim();
352
+ return /* @__PURE__ */ jsxs(
353
+ Modal,
354
+ {
355
+ open: isOpen && editableWord !== null,
356
+ onOpenChange: (open) => {
357
+ if (!open) onClose();
358
+ },
359
+ size: "md",
360
+ children: [
361
+ /* @__PURE__ */ jsxs(ModalHeader, { children: [
362
+ /* @__PURE__ */ jsx(ModalTitle, { children: isSilence ? "Split Silence" : "Edit Word" }),
363
+ /* @__PURE__ */ jsx(ModalClose, { "aria-label": "Close editor" })
364
+ ] }),
365
+ /* @__PURE__ */ jsx(ModalBody, { className: "flex flex-col gap-2", children: isSilence ? /* @__PURE__ */ jsxs(Fragment, { children: [
366
+ /* @__PURE__ */ jsxs("p", { className: "text-foreground m-0 text-sm", children: [
367
+ "Silence duration:",
368
+ " ",
369
+ /* @__PURE__ */ jsxs("strong", { className: "font-semibold", children: [
370
+ durationSec.toFixed(1),
371
+ "s"
372
+ ] })
373
+ ] }),
374
+ /* @__PURE__ */ jsx("p", { className: "text-muted-foreground m-0 text-xs", children: 'Enter space-separated durations to split (e.g., "1 1 4 1")' }),
375
+ /* @__PURE__ */ jsx(
376
+ Input,
377
+ {
378
+ ref: inputRef,
379
+ type: "text",
380
+ value: inputValue,
381
+ onChange: (e) => {
382
+ setInputValue(e.target.value);
383
+ setError(null);
384
+ },
385
+ onKeyDown: handleKeyDown,
386
+ placeholder: "1 2 3...",
387
+ "aria-label": "Split durations"
388
+ }
389
+ ),
390
+ error && /* @__PURE__ */ jsx("p", { className: "text-destructive m-0 text-sm", role: "alert", children: error }),
391
+ preview && !preview.error && preview.durations.length > 0 && !error && /* @__PURE__ */ jsxs("p", { className: "text-muted-foreground m-0 text-sm", children: [
392
+ "Preview:",
393
+ " ",
394
+ [...preview.durations, preview.remainder].map((d) => `[${d.toFixed(1)}s]`).join(" ")
395
+ ] }),
396
+ preview?.error && !error && /* @__PURE__ */ jsx("p", { className: "text-destructive m-0 text-sm", role: "alert", children: preview.error })
397
+ ] }) : /* @__PURE__ */ jsxs(Fragment, { children: [
398
+ /* @__PURE__ */ jsx("p", { className: "text-foreground m-0 text-sm", children: "Edit the word text:" }),
399
+ /* @__PURE__ */ jsx(
400
+ Input,
401
+ {
402
+ ref: inputRef,
403
+ type: "text",
404
+ value: inputValue,
405
+ onChange: (e) => setInputValue(e.target.value),
406
+ onKeyDown: handleKeyDown,
407
+ "aria-label": "Word text"
408
+ }
409
+ )
410
+ ] }) }),
411
+ /* @__PURE__ */ jsxs(ModalFooter, { className: "justify-between", children: [
412
+ /* @__PURE__ */ jsx(
413
+ Button,
414
+ {
415
+ variant: editableWord?.deleted ? "secondary" : "danger",
416
+ size: "sm",
417
+ onClick: onDelete,
418
+ children: editableWord?.deleted ? "Restore" : "Delete"
419
+ }
420
+ ),
421
+ /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2", children: [
422
+ /* @__PURE__ */ jsx(Button, { variant: "secondary", size: "sm", onClick: onClose, children: "Cancel" }),
423
+ /* @__PURE__ */ jsx(
424
+ Button,
425
+ {
426
+ variant: "primary",
427
+ size: "sm",
428
+ onClick: handleApply,
429
+ disabled: applyDisabled,
430
+ children: isSilence ? "Split" : "Save"
431
+ }
432
+ )
433
+ ] })
434
+ ] })
435
+ ]
436
+ }
437
+ );
438
+ };
439
+ WordEditorModal.displayName = "WordEditorModal";
440
+ var SilenceSettingsModal = ({
441
+ isOpen,
442
+ onClose,
443
+ minSilenceMs,
444
+ nlSilenceMs,
445
+ onApply
446
+ }) => {
447
+ const [threshold, setThreshold] = React6.useState(minSilenceMs / 1e3);
448
+ const [nlThreshold, setNlThreshold] = React6.useState(nlSilenceMs / 1e3);
449
+ React6.useEffect(() => {
450
+ if (isOpen) {
451
+ setThreshold(minSilenceMs / 1e3);
452
+ setNlThreshold(nlSilenceMs / 1e3);
453
+ }
454
+ }, [isOpen, minSilenceMs, nlSilenceMs]);
455
+ const handleApply = () => {
456
+ const finalNlThreshold = Math.max(nlThreshold, threshold);
457
+ onApply(Math.round(threshold * 1e3), Math.round(finalNlThreshold * 1e3));
458
+ onClose();
459
+ };
460
+ const handleThresholdChange = (value) => {
461
+ setThreshold(value);
462
+ if (nlThreshold < value) {
463
+ setNlThreshold(value);
464
+ }
465
+ };
466
+ const formatSeconds = (v) => `${v.toFixed(1)}s`;
467
+ return /* @__PURE__ */ jsxs(
468
+ Modal,
469
+ {
470
+ open: isOpen,
471
+ onOpenChange: (open) => {
472
+ if (!open) onClose();
473
+ },
474
+ size: "md",
475
+ children: [
476
+ /* @__PURE__ */ jsxs(ModalHeader, { children: [
477
+ /* @__PURE__ */ jsx(ModalTitle, { children: "Silence Settings" }),
478
+ /* @__PURE__ */ jsx(ModalClose, { "aria-label": "Close modal" })
479
+ ] }),
480
+ /* @__PURE__ */ jsxs(ModalBody, { className: "flex flex-col gap-6", children: [
481
+ /* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-1", children: [
482
+ /* @__PURE__ */ jsx(
483
+ Slider,
484
+ {
485
+ label: "Minimum silence duration",
486
+ min: 0.1,
487
+ max: 2,
488
+ step: 0.1,
489
+ value: threshold,
490
+ onValueChange: handleThresholdChange,
491
+ showValue: true,
492
+ formatValue: formatSeconds,
493
+ "aria-label": "Minimum silence duration"
494
+ }
495
+ ),
496
+ /* @__PURE__ */ jsx("p", { className: "text-muted-foreground m-0 text-xs", children: "Gaps shorter than this will not be shown as silences." })
497
+ ] }),
498
+ /* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-1", children: [
499
+ /* @__PURE__ */ jsx(
500
+ Slider,
501
+ {
502
+ label: "Paragraph break threshold",
503
+ min: threshold,
504
+ max: 5,
505
+ step: 0.1,
506
+ value: nlThreshold,
507
+ onValueChange: setNlThreshold,
508
+ showValue: true,
509
+ formatValue: formatSeconds,
510
+ "aria-label": "Paragraph break threshold"
511
+ }
512
+ ),
513
+ /* @__PURE__ */ jsx("p", { className: "text-muted-foreground m-0 text-xs", children: "Silences longer than this will create paragraph breaks." })
514
+ ] })
515
+ ] }),
516
+ /* @__PURE__ */ jsxs(ModalFooter, { children: [
517
+ /* @__PURE__ */ jsx(Button, { variant: "secondary", size: "sm", onClick: onClose, children: "Cancel" }),
518
+ /* @__PURE__ */ jsx(Button, { variant: "primary", size: "sm", onClick: handleApply, children: "Apply" })
519
+ ] })
520
+ ]
521
+ }
522
+ );
523
+ };
524
+ SilenceSettingsModal.displayName = "SilenceSettingsModal";
525
+ var SpeedMarkerMenu = ({
526
+ isOpen,
527
+ position,
528
+ currentMarker,
529
+ defaultSpeed,
530
+ onSetSpeed,
531
+ onRemoveMarker,
532
+ onClose
533
+ }) => {
534
+ const menuRef = React6.useRef(null);
535
+ React6.useEffect(() => {
536
+ const handleKeyDown = (e) => {
537
+ if (e.key === "Escape") onClose();
538
+ };
539
+ const handleClickOutside = (e) => {
540
+ if (menuRef.current && !menuRef.current.contains(e.target)) {
541
+ onClose();
542
+ }
543
+ };
544
+ if (isOpen) {
545
+ document.addEventListener("keydown", handleKeyDown);
546
+ document.addEventListener("mousedown", handleClickOutside);
547
+ return () => {
548
+ document.removeEventListener("keydown", handleKeyDown);
549
+ document.removeEventListener("mousedown", handleClickOutside);
550
+ };
551
+ }
552
+ }, [isOpen, onClose]);
553
+ if (!isOpen || !position) return null;
554
+ return /* @__PURE__ */ jsxs(
555
+ "div",
556
+ {
557
+ ref: menuRef,
558
+ className: "border-border bg-card text-card-foreground fixed z-50 min-w-36 overflow-hidden rounded-lg border shadow-lg",
559
+ style: { left: position.x, top: position.y },
560
+ role: "menu",
561
+ "aria-label": "Set speed marker",
562
+ children: [
563
+ /* @__PURE__ */ jsx("div", { className: "border-border text-muted-foreground border-b px-3 py-1.5 text-xs font-semibold", children: "Set Speed Marker" }),
564
+ /* @__PURE__ */ jsx("div", { className: "flex flex-col p-1", children: PLAYBACK_SPEEDS.map((speed) => {
565
+ const isActive = currentMarker?.speed === speed;
566
+ const isDefault = speed === defaultSpeed && !currentMarker;
567
+ return /* @__PURE__ */ jsxs(
568
+ "button",
569
+ {
570
+ type: "button",
571
+ 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 ${isActive ? "bg-primary-600 font-medium text-white" : "text-foreground hover:bg-muted"}`,
572
+ onClick: () => {
573
+ onSetSpeed(speed);
574
+ onClose();
575
+ },
576
+ role: "menuitem",
577
+ children: [
578
+ speed,
579
+ "x",
580
+ isDefault && /* @__PURE__ */ jsx("span", { className: "text-muted-foreground text-xs", children: "default" })
581
+ ]
582
+ },
583
+ speed
584
+ );
585
+ }) }),
586
+ currentMarker && /* @__PURE__ */ jsx(
587
+ "button",
588
+ {
589
+ type: "button",
590
+ 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",
591
+ onClick: () => {
592
+ onRemoveMarker();
593
+ onClose();
594
+ },
595
+ role: "menuitem",
596
+ children: "Remove Marker"
597
+ }
598
+ )
599
+ ]
600
+ }
601
+ );
602
+ };
603
+ SpeedMarkerMenu.displayName = "SpeedMarkerMenu";
604
+ var yamlPromise = null;
605
+ function loadYaml() {
606
+ yamlPromise ??= import(
607
+ /* @vite-ignore */
608
+ 'js-yaml'
609
+ );
610
+ return yamlPromise;
611
+ }
612
+ async function parseScript(text, format) {
613
+ let data;
614
+ if (format === "json") {
615
+ data = JSON.parse(text);
616
+ } else {
617
+ const yaml = await loadYaml();
618
+ data = yaml.load(text);
619
+ }
620
+ if (!Array.isArray(data)) {
621
+ throw new Error("Script must be a list of word entries.");
622
+ }
623
+ return data.map((raw, i) => {
624
+ const ew = raw;
625
+ const w = ew.word;
626
+ if (!w || typeof w.text !== "string" || typeof w.startMs !== "number" || typeof w.endMs !== "number") {
627
+ throw new Error(
628
+ `Entry ${i + 1}: each entry needs word.text, word.startMs and word.endMs.`
629
+ );
630
+ }
631
+ const word = {
632
+ text: w.text,
633
+ startMs: w.startMs,
634
+ endMs: w.endMs,
635
+ ...typeof w.wordType === "string" ? { wordType: w.wordType } : {},
636
+ ...typeof w.speakerId === "string" ? { speakerId: w.speakerId } : {}
637
+ };
638
+ return {
639
+ originalIndex: typeof ew.originalIndex === "number" ? ew.originalIndex : -1,
640
+ deleted: Boolean(ew.deleted),
641
+ ...ew.inserted !== void 0 ? { inserted: Boolean(ew.inserted) } : {},
642
+ word
643
+ };
644
+ });
645
+ }
646
+ var ScriptPanel = ({
647
+ transcript,
648
+ editedWords,
649
+ onApply,
650
+ onClose,
651
+ className
652
+ }) => {
653
+ const [source, setSource] = React6.useState("editor");
654
+ const [format, setFormat] = React6.useState("yaml");
655
+ const [text, setText] = React6.useState("");
656
+ const [dirty, setDirty] = React6.useState(false);
657
+ const [error, setError] = React6.useState(null);
658
+ const readOnly = source === "original";
659
+ React6.useEffect(() => {
660
+ if (dirty) return;
661
+ let cancelled = false;
662
+ const data = source === "original" ? transcript : editedWords;
663
+ (async () => {
664
+ const serialized = format === "json" ? JSON.stringify(data, null, 2) : (await loadYaml()).dump(data, { lineWidth: 120 });
665
+ if (!cancelled) {
666
+ setText(serialized);
667
+ setError(null);
668
+ }
669
+ })();
670
+ return () => {
671
+ cancelled = true;
672
+ };
673
+ }, [source, format, transcript, editedWords, dirty]);
674
+ const handleApply = async () => {
675
+ try {
676
+ const words = await parseScript(text, format);
677
+ onApply(words);
678
+ setDirty(false);
679
+ setError(null);
680
+ } catch (err) {
681
+ setError(
682
+ err instanceof Error ? err.message : "Could not parse the script."
683
+ );
684
+ }
685
+ };
686
+ const handleReset = () => {
687
+ setDirty(false);
688
+ setError(null);
689
+ };
690
+ const sourceButton = (value, label) => /* @__PURE__ */ jsx(
691
+ "button",
692
+ {
693
+ type: "button",
694
+ onClick: () => {
695
+ setSource(value);
696
+ setDirty(false);
697
+ setError(null);
698
+ },
699
+ "aria-pressed": source === value,
700
+ className: `focus-visible:ring-ring rounded px-1.5 py-0.5 text-xs transition-colors focus-visible:ring-2 focus-visible:outline-none ${source === value ? "bg-primary-800 font-medium text-white" : "text-muted-foreground hover:bg-muted hover:text-foreground"}`,
701
+ children: label
702
+ }
703
+ );
704
+ return /* @__PURE__ */ jsxs(
705
+ "aside",
706
+ {
707
+ className: `border-border bg-card flex w-80 shrink-0 flex-col border-l lg:w-96 ${className ?? ""}`,
708
+ "aria-label": "Transcript script",
709
+ children: [
710
+ /* @__PURE__ */ jsxs("div", { className: "border-border flex shrink-0 flex-wrap items-center gap-1.5 border-b px-3 py-2", children: [
711
+ /* @__PURE__ */ jsx("span", { className: "text-foreground text-xs font-semibold", children: "Script" }),
712
+ /* @__PURE__ */ jsx("span", { className: "bg-border mx-1 h-4 w-px", "aria-hidden": "true" }),
713
+ sourceButton("editor", "Editor"),
714
+ sourceButton("original", "Original"),
715
+ /* @__PURE__ */ jsx("span", { className: "bg-border mx-1 h-4 w-px", "aria-hidden": "true" }),
716
+ /* @__PURE__ */ jsx(
717
+ "button",
718
+ {
719
+ type: "button",
720
+ onClick: () => {
721
+ setFormat(format === "yaml" ? "json" : "yaml");
722
+ setDirty(false);
723
+ setError(null);
724
+ },
725
+ 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",
726
+ title: "Toggle YAML / JSON",
727
+ children: format.toUpperCase()
728
+ }
729
+ ),
730
+ /* @__PURE__ */ jsx("span", { className: "text-muted-foreground ml-auto text-[10px]", children: readOnly ? "read-only" : dirty ? "edited" : "live" }),
731
+ /* @__PURE__ */ jsx(
732
+ Button,
733
+ {
734
+ variant: "ghost",
735
+ size: "sm",
736
+ onClick: onClose,
737
+ "aria-label": "Close script panel",
738
+ children: "\u2715"
739
+ }
740
+ )
741
+ ] }),
742
+ /* @__PURE__ */ jsx(
743
+ "textarea",
744
+ {
745
+ value: text,
746
+ readOnly,
747
+ spellCheck: false,
748
+ onChange: (e) => {
749
+ setText(e.target.value);
750
+ setDirty(true);
751
+ },
752
+ className: "text-foreground min-h-0 flex-1 resize-none bg-transparent p-3 font-mono text-xs leading-relaxed focus:outline-none",
753
+ "aria-label": `Script source (${source}, ${format.toUpperCase()})`
754
+ }
755
+ ),
756
+ error && /* @__PURE__ */ jsx(
757
+ "p",
758
+ {
759
+ className: "border-border text-destructive m-0 shrink-0 border-t px-3 py-2 text-xs",
760
+ role: "alert",
761
+ children: error
762
+ }
763
+ ),
764
+ !readOnly && /* @__PURE__ */ jsxs("div", { className: "border-border flex shrink-0 items-center gap-2 border-t px-3 py-2", children: [
765
+ /* @__PURE__ */ jsx(Button, { size: "sm", onClick: handleApply, disabled: !dirty, children: "Apply" }),
766
+ /* @__PURE__ */ jsx(
767
+ Button,
768
+ {
769
+ variant: "ghost",
770
+ size: "sm",
771
+ onClick: handleReset,
772
+ disabled: !dirty,
773
+ title: "Throw away unapplied typing and re-sync from the editor",
774
+ children: "Discard"
775
+ }
776
+ ),
777
+ /* @__PURE__ */ jsx("span", { className: "text-muted-foreground text-[10px]", children: "Apply pushes into the editor \u2014 revert an applied change with Undo" })
778
+ ] })
779
+ ]
780
+ }
781
+ );
782
+ };
783
+ var mediaEditorVariants = cva(
784
+ // Root is always a row so the ScriptPanel can dock on the right; the
785
+ // media/transcript split direction lives on the inner wrapper below.
786
+ "flex h-full min-h-0 w-full overflow-hidden rounded-xl border border-border bg-card text-card-foreground",
787
+ {
788
+ variants: {
789
+ splitLayout: {
790
+ horizontal: "",
791
+ vertical: ""
792
+ }
793
+ },
794
+ defaultVariants: {
795
+ splitLayout: "horizontal"
796
+ }
797
+ }
798
+ );
799
+ function formatDuration2(ms) {
800
+ const totalSeconds = Math.round(ms / 1e3);
801
+ if (totalSeconds < 90) {
802
+ return `${totalSeconds}s`;
803
+ }
804
+ const hours = Math.floor(totalSeconds / 3600);
805
+ const minutes = Math.floor(totalSeconds % 3600 / 60);
806
+ const seconds = totalSeconds % 60;
807
+ if (hours > 0) {
808
+ return `${hours}:${String(minutes).padStart(2, "0")}:${String(seconds).padStart(2, "0")}`;
809
+ }
810
+ return `${minutes}:${String(seconds).padStart(2, "0")}`;
811
+ }
812
+ function wordClassName(s) {
813
+ const parts = [
814
+ "relative cursor-pointer rounded-sm px-1 py-0.5 transition-colors duration-150"
815
+ ];
816
+ if (s.isSilence) {
817
+ parts.push("text-xs font-medium italic tracking-wide");
818
+ }
819
+ if (s.isSilenceNewline) {
820
+ parts.push("mt-1.5 block w-fit");
821
+ }
822
+ if (s.isAnchor) {
823
+ parts.push("bg-warning/40 outline outline-2 outline-warning");
824
+ } else if (s.isActive) {
825
+ parts.push("bg-primary-800 font-medium text-white");
826
+ } else if (s.isSelected && s.isFocused) {
827
+ parts.push("bg-primary-500/40");
828
+ } else if (s.isDeleted) {
829
+ parts.push(
830
+ "bg-destructive/10 text-destructive line-through opacity-40 hover:bg-destructive/20 hover:opacity-70"
831
+ );
832
+ } else if (s.isInserted) {
833
+ parts.push("bg-success/15 text-success hover:bg-success/25");
834
+ } else if (s.isSilenceNewline) {
835
+ parts.push("text-primary-500 hover:bg-primary-500/15");
836
+ } else if (s.isSilence) {
837
+ parts.push(
838
+ "border border-dashed border-border bg-muted text-muted-foreground hover:bg-muted/70"
839
+ );
840
+ } else {
841
+ parts.push("hover:bg-primary-500/30");
842
+ }
843
+ if (s.isDeleted && (s.isActive || s.isSelected && s.isFocused || s.isAnchor)) {
844
+ parts.push("line-through opacity-60");
845
+ }
846
+ if (s.isCursor && s.isFocused && !s.isAnchor) {
847
+ if (s.isDeleted) {
848
+ parts.push("outline outline-2 outline-offset-1 outline-destructive");
849
+ } else if (s.isActive) {
850
+ parts.push("outline outline-2 outline-offset-1 outline-background");
851
+ } else {
852
+ parts.push("outline outline-2 outline-offset-1 outline-primary-500");
853
+ }
854
+ }
855
+ if (s.hasSpeedMarker) {
856
+ parts.push("ml-0.5 border-l-[3px] border-l-warning pl-1.5");
857
+ }
858
+ return parts.join(" ");
859
+ }
860
+ var Caret = ({ side }) => /* @__PURE__ */ jsx(
861
+ "span",
862
+ {
863
+ "aria-hidden": "true",
864
+ className: `bg-primary-500 absolute top-0.5 bottom-0.5 w-0.5 motion-safe:animate-pulse ${side === "before" ? "-left-px" : "right-0.5"}`
865
+ }
866
+ );
867
+ var MediaEditor = React6.forwardRef(
868
+ ({
869
+ src,
870
+ kind,
871
+ transcript,
872
+ initialEditedWords,
873
+ initialUndoStack,
874
+ onEditorStateChange,
875
+ onHasEditsChange,
876
+ onCursorTimestampChange,
877
+ onEditedWordsRender,
878
+ playerRef: externalPlayerRef,
879
+ className,
880
+ splitLayout
881
+ }, ref) => {
882
+ const edits = useTranscriptEdits({
883
+ transcript,
884
+ initialEditedWords,
885
+ initialUndoStack,
886
+ onChange: onEditorStateChange
887
+ });
888
+ const {
889
+ editedWords,
890
+ undoStack,
891
+ clipboard,
892
+ hasEdits,
893
+ undo,
894
+ toggleWordDeleted,
895
+ deleteRange,
896
+ cut,
897
+ copy,
898
+ paste,
899
+ setWordText,
900
+ splitSilence,
901
+ deleteWord,
902
+ replaceEditedWords,
903
+ removeFillers,
904
+ setSilenceThresholds,
905
+ silenceThresholds,
906
+ speedMarkers,
907
+ defaultSpeed,
908
+ setDefaultSpeed,
909
+ toggleSpeedMarker,
910
+ removeSpeedMarker,
911
+ getSpeedAtIndex,
912
+ getSpeedMarkerAtIndex,
913
+ playbackSegments,
914
+ stats,
915
+ fillerAnalysis
916
+ } = edits;
917
+ const [activeWordIndex, setActiveWordIndex] = React6.useState(
918
+ null
919
+ );
920
+ const [cursorIndex, setCursorIndex] = React6.useState(0);
921
+ const [cursorPosition, setCursorPosition] = React6.useState("before");
922
+ const [selectionAnchor, setSelectionAnchor] = React6.useState(
923
+ null
924
+ );
925
+ const [selection, setSelection] = React6.useState(
926
+ null
927
+ );
928
+ const [doubleClickAnchor, setDoubleClickAnchor] = React6.useState(null);
929
+ const [isPlayingSequence, setIsPlayingSequence] = React6.useState(false);
930
+ const [isFocused, setIsFocused] = React6.useState(false);
931
+ const [showFillerModal, setShowFillerModal] = React6.useState(false);
932
+ const [showSilenceModal, setShowSilenceModal] = React6.useState(false);
933
+ const [showScriptPanel, setShowScriptPanel] = React6.useState(false);
934
+ const [editorWordIndex, setEditorWordIndex] = React6.useState(
935
+ null
936
+ );
937
+ const [speedMenuWordIndex, setSpeedMenuWordIndex] = React6.useState(null);
938
+ const [speedMenuPosition, setSpeedMenuPosition] = React6.useState(null);
939
+ const playerRef = React6.useRef(null);
940
+ React6.useImperativeHandle(
941
+ externalPlayerRef,
942
+ () => playerRef.current,
943
+ []
944
+ );
945
+ const contentRef = React6.useRef(null);
946
+ const userSetCursor = React6.useRef(null);
947
+ const isDragging = React6.useRef(false);
948
+ const longPressTimer = React6.useRef(
949
+ null
950
+ );
951
+ const longPressTriggered = React6.useRef(false);
952
+ const wordPlaybackStartMs = React6.useRef(null);
953
+ const wordPlaybackEndMs = React6.useRef(null);
954
+ const sequenceSegments = React6.useRef([]);
955
+ const currentSegmentIndex = React6.useRef(0);
956
+ React6.useEffect(() => {
957
+ onHasEditsChange?.(hasEdits);
958
+ }, [hasEdits, onHasEditsChange]);
959
+ React6.useEffect(() => {
960
+ onEditedWordsRender?.(editedWords);
961
+ }, [editedWords, onEditedWordsRender]);
962
+ React6.useEffect(() => {
963
+ if (onCursorTimestampChange) {
964
+ const word = editedWords[cursorIndex];
965
+ if (word && !word.deleted) {
966
+ onCursorTimestampChange(word.word.startMs);
967
+ } else {
968
+ onCursorTimestampChange(null);
969
+ }
970
+ }
971
+ }, [cursorIndex, editedWords, onCursorTimestampChange]);
972
+ const prevTranscriptRef = React6.useRef(transcript);
973
+ React6.useEffect(() => {
974
+ if (prevTranscriptRef.current === transcript) return;
975
+ prevTranscriptRef.current = transcript;
976
+ setCursorIndex(0);
977
+ setCursorPosition("before");
978
+ setSelection(null);
979
+ setSelectionAnchor(null);
980
+ setDoubleClickAnchor(null);
981
+ setActiveWordIndex(null);
982
+ setIsPlayingSequence(false);
983
+ sequenceSegments.current = [];
984
+ currentSegmentIndex.current = 0;
985
+ }, [transcript]);
986
+ React6.useEffect(() => {
987
+ if (userSetCursor.current !== null) {
988
+ return;
989
+ }
990
+ if (activeWordIndex !== null && activeWordIndex >= 0) {
991
+ setCursorIndex(activeWordIndex);
992
+ setCursorPosition("before");
993
+ setSelection(null);
994
+ setSelectionAnchor(null);
995
+ }
996
+ }, [activeWordIndex]);
997
+ React6.useEffect(() => {
998
+ if (activeWordIndex === null) return;
999
+ const el = contentRef.current?.querySelector(
1000
+ `[data-word-index="${activeWordIndex}"]`
1001
+ );
1002
+ el?.scrollIntoView({ block: "nearest", behavior: "smooth" });
1003
+ }, [activeWordIndex]);
1004
+ React6.useEffect(() => {
1005
+ contentRef.current?.focus();
1006
+ }, [transcript]);
1007
+ React6.useEffect(() => {
1008
+ const player = playerRef.current;
1009
+ if (!player) return;
1010
+ const timeMs = player.getCurrentTimeMs();
1011
+ const currentWordIndex = editedWords.findIndex(
1012
+ (ew) => !ew.deleted && timeMs >= ew.word.startMs && timeMs < ew.word.endMs
1013
+ );
1014
+ const targetSpeed = currentWordIndex >= 0 ? getSpeedAtIndex(currentWordIndex) : defaultSpeed;
1015
+ player.setPlaybackRate(targetSpeed);
1016
+ }, [defaultSpeed, speedMarkers, editedWords, getSpeedAtIndex]);
1017
+ const handleTimeUpdate = (timeMs) => {
1018
+ const player = playerRef.current;
1019
+ if (!player) return;
1020
+ if (isPlayingSequence && sequenceSegments.current.length > 0) {
1021
+ const currentSeg = sequenceSegments.current[currentSegmentIndex.current];
1022
+ if (currentSeg && timeMs >= currentSeg.endMs) {
1023
+ const nextIndex = currentSegmentIndex.current + 1;
1024
+ if (nextIndex < sequenceSegments.current.length) {
1025
+ currentSegmentIndex.current = nextIndex;
1026
+ player.seekToMs(sequenceSegments.current[nextIndex].startMs);
1027
+ } else {
1028
+ player.pause();
1029
+ setIsPlayingSequence(false);
1030
+ sequenceSegments.current = [];
1031
+ currentSegmentIndex.current = 0;
1032
+ }
1033
+ }
1034
+ } else if (hasEdits && !player.isPaused()) {
1035
+ const inDeletedWord = editedWords.some(
1036
+ (ew) => ew.deleted && timeMs >= ew.word.startMs && timeMs < ew.word.endMs
1037
+ );
1038
+ if (inDeletedWord) {
1039
+ const nextNonDeleted = editedWords.find(
1040
+ (ew) => !ew.deleted && ew.word.startMs >= timeMs
1041
+ );
1042
+ if (nextNonDeleted) {
1043
+ player.seekToMs(nextNonDeleted.word.startMs);
1044
+ }
1045
+ }
1046
+ }
1047
+ if (wordPlaybackEndMs.current !== null && timeMs >= wordPlaybackEndMs.current) {
1048
+ player.pause();
1049
+ if (wordPlaybackStartMs.current !== null) {
1050
+ player.seekToMs(wordPlaybackStartMs.current);
1051
+ wordPlaybackStartMs.current = null;
1052
+ }
1053
+ wordPlaybackEndMs.current = null;
1054
+ }
1055
+ let editedIndex = -1;
1056
+ if (isPlayingSequence && sequenceSegments.current.length > 0) {
1057
+ const currentSeg = sequenceSegments.current[currentSegmentIndex.current];
1058
+ if (currentSeg) {
1059
+ for (const idx of currentSeg.editedIndices) {
1060
+ const ew = editedWords[idx];
1061
+ if (ew && !ew.deleted && timeMs >= ew.word.startMs && timeMs < ew.word.endMs) {
1062
+ editedIndex = idx;
1063
+ break;
1064
+ }
1065
+ }
1066
+ }
1067
+ }
1068
+ if (editedIndex === -1) {
1069
+ editedIndex = editedWords.findIndex(
1070
+ (ew) => !ew.deleted && timeMs >= ew.word.startMs && timeMs < ew.word.endMs
1071
+ );
1072
+ }
1073
+ if (editedIndex !== activeWordIndex && editedIndex >= 0) {
1074
+ player.setPlaybackRate(getSpeedAtIndex(editedIndex));
1075
+ }
1076
+ setActiveWordIndex(editedIndex >= 0 ? editedIndex : null);
1077
+ userSetCursor.current = null;
1078
+ };
1079
+ const stopSequencePlayback = () => {
1080
+ setIsPlayingSequence(false);
1081
+ sequenceSegments.current = [];
1082
+ currentSegmentIndex.current = 0;
1083
+ };
1084
+ const selectionIndices = React6.useCallback(() => {
1085
+ if (selection) {
1086
+ const indices = [];
1087
+ for (let i = selection.start; i <= selection.end; i++) indices.push(i);
1088
+ return indices;
1089
+ }
1090
+ return [cursorIndex];
1091
+ }, [selection, cursorIndex]);
1092
+ const handleCut = React6.useCallback(() => {
1093
+ cut(selectionIndices());
1094
+ }, [cut, selectionIndices]);
1095
+ const handlePaste = React6.useCallback(() => {
1096
+ if (!clipboard) return;
1097
+ const pastedCount = clipboard.words.length;
1098
+ const insertIndex = paste(cursorIndex, cursorPosition !== "after");
1099
+ if (insertIndex !== null) {
1100
+ setCursorIndex(insertIndex + pastedCount - 1);
1101
+ setCursorPosition("after");
1102
+ setSelection(null);
1103
+ setSelectionAnchor(null);
1104
+ }
1105
+ }, [clipboard, paste, cursorIndex, cursorPosition]);
1106
+ const handleDeleteToggle = React6.useCallback(() => {
1107
+ if (selection) {
1108
+ const anchorIndex = selectionAnchor ?? selection.start;
1109
+ const indices = [anchorIndex];
1110
+ for (let i = selection.start; i <= selection.end; i++) {
1111
+ if (i !== anchorIndex) indices.push(i);
1112
+ }
1113
+ deleteRange(indices);
1114
+ } else {
1115
+ toggleWordDeleted(cursorIndex);
1116
+ }
1117
+ }, [
1118
+ selection,
1119
+ selectionAnchor,
1120
+ cursorIndex,
1121
+ deleteRange,
1122
+ toggleWordDeleted
1123
+ ]);
1124
+ const handleCopy = React6.useCallback(
1125
+ (e) => {
1126
+ const indices = selectionIndices();
1127
+ const selectedWords = indices.map((i) => editedWords[i]).filter((ew) => ew !== void 0 && !ew.deleted);
1128
+ if (selectedWords.length === 0) return;
1129
+ const selectedText = selectedWords.filter((ew) => ew.word.wordType !== "silence").map((ew) => ew.word.text).join(" ");
1130
+ e.preventDefault();
1131
+ e.clipboardData.setData("text/plain", selectedText);
1132
+ copy(indices);
1133
+ },
1134
+ [selectionIndices, editedWords, copy]
1135
+ );
1136
+ const openWordEditor = React6.useCallback((index) => {
1137
+ setEditorWordIndex(index);
1138
+ }, []);
1139
+ const closeWordEditor = React6.useCallback(() => {
1140
+ setEditorWordIndex(null);
1141
+ setTimeout(() => contentRef.current?.focus(), 0);
1142
+ }, []);
1143
+ const handleEditorSave = React6.useCallback(
1144
+ (newText) => {
1145
+ if (editorWordIndex === null) return;
1146
+ setWordText(editorWordIndex, newText);
1147
+ },
1148
+ [editorWordIndex, setWordText]
1149
+ );
1150
+ const handleEditorSplitSilence = React6.useCallback(
1151
+ (durations) => {
1152
+ if (editorWordIndex === null) return;
1153
+ splitSilence(editorWordIndex, durations);
1154
+ },
1155
+ [editorWordIndex, splitSilence]
1156
+ );
1157
+ const handleEditorDelete = React6.useCallback(() => {
1158
+ if (editorWordIndex !== null) {
1159
+ deleteWord(editorWordIndex);
1160
+ closeWordEditor();
1161
+ }
1162
+ }, [editorWordIndex, deleteWord, closeWordEditor]);
1163
+ const handleWordClick = (word, index, e) => {
1164
+ setCursorIndex(index);
1165
+ setCursorPosition("before");
1166
+ userSetCursor.current = index;
1167
+ if (e.shiftKey && selectionAnchor !== null) {
1168
+ setSelection({
1169
+ start: Math.min(selectionAnchor, index),
1170
+ end: Math.max(selectionAnchor, index)
1171
+ });
1172
+ } else if (doubleClickAnchor !== null && doubleClickAnchor !== index && !isDragging.current) {
1173
+ const start = Math.min(doubleClickAnchor, index);
1174
+ const end = Math.max(doubleClickAnchor, index);
1175
+ setSelection({ start, end });
1176
+ setSelectionAnchor(doubleClickAnchor);
1177
+ setDoubleClickAnchor(null);
1178
+ } else if (doubleClickAnchor === index) ; else if (!isDragging.current) {
1179
+ setSelectionAnchor(index);
1180
+ setSelection(null);
1181
+ const player = playerRef.current;
1182
+ if (player) {
1183
+ player.pause();
1184
+ player.seekToMs(word.startMs);
1185
+ wordPlaybackStartMs.current = word.startMs;
1186
+ wordPlaybackEndMs.current = word.endMs;
1187
+ player.play();
1188
+ }
1189
+ }
1190
+ };
1191
+ const handleWordDoubleClick = (index, e) => {
1192
+ e.preventDefault();
1193
+ if (longPressTriggered.current) return;
1194
+ if (doubleClickAnchor === index) {
1195
+ setDoubleClickAnchor(null);
1196
+ } else {
1197
+ setDoubleClickAnchor(index);
1198
+ setSelection(null);
1199
+ }
1200
+ };
1201
+ const handleWordMouseDown = (index, e) => {
1202
+ if (e.button !== 0) return;
1203
+ longPressTriggered.current = false;
1204
+ longPressTimer.current = setTimeout(() => {
1205
+ longPressTriggered.current = true;
1206
+ openWordEditor(index);
1207
+ }, 500);
1208
+ isDragging.current = true;
1209
+ setSelectionAnchor(index);
1210
+ setCursorIndex(index);
1211
+ setCursorPosition("before");
1212
+ setSelection(null);
1213
+ };
1214
+ const handleWordMouseEnter = (index) => {
1215
+ if (longPressTimer.current) {
1216
+ clearTimeout(longPressTimer.current);
1217
+ longPressTimer.current = null;
1218
+ }
1219
+ if (!isDragging.current || selectionAnchor === null) return;
1220
+ setSelection({
1221
+ start: Math.min(selectionAnchor, index),
1222
+ end: Math.max(selectionAnchor, index)
1223
+ });
1224
+ setCursorIndex(index);
1225
+ };
1226
+ const handleMouseUp = () => {
1227
+ if (longPressTimer.current) {
1228
+ clearTimeout(longPressTimer.current);
1229
+ longPressTimer.current = null;
1230
+ }
1231
+ if (isDragging.current) {
1232
+ isDragging.current = false;
1233
+ }
1234
+ };
1235
+ const handleWordContextMenu = (index, e) => {
1236
+ e.preventDefault();
1237
+ const rect = e.currentTarget.getBoundingClientRect();
1238
+ const menuHeight = 280;
1239
+ const menuWidth = 150;
1240
+ let x = rect.left;
1241
+ let y = rect.bottom + 4;
1242
+ if (x + menuWidth > window.innerWidth) {
1243
+ x = window.innerWidth - menuWidth - 8;
1244
+ }
1245
+ if (y + menuHeight > window.innerHeight) {
1246
+ y = rect.top - menuHeight - 4;
1247
+ if (y < 0) {
1248
+ y = 8;
1249
+ }
1250
+ }
1251
+ setSpeedMenuPosition({ x, y });
1252
+ setSpeedMenuWordIndex(index);
1253
+ };
1254
+ const handleKeyDown = React6.useCallback(
1255
+ (e) => {
1256
+ const wordCount = editedWords.length;
1257
+ if (wordCount === 0) return;
1258
+ let newIndex = cursorIndex;
1259
+ let handled = false;
1260
+ if (e.key === "Delete" || e.key === "Backspace") {
1261
+ handleDeleteToggle();
1262
+ handled = true;
1263
+ } else if ((e.metaKey || e.ctrlKey) && e.key === "x") {
1264
+ handleCut();
1265
+ handled = true;
1266
+ } else if ((e.metaKey || e.ctrlKey) && e.key === "v" && clipboard) {
1267
+ handlePaste();
1268
+ handled = true;
1269
+ } else if ((e.metaKey || e.ctrlKey) && e.key === "z" && !e.shiftKey) {
1270
+ undo();
1271
+ handled = true;
1272
+ } else if (e.key === "ArrowLeft") {
1273
+ if (cursorPosition === "after") {
1274
+ setCursorPosition("before");
1275
+ } else {
1276
+ newIndex = Math.max(0, cursorIndex - 1);
1277
+ }
1278
+ handled = true;
1279
+ } else if (e.key === "ArrowRight") {
1280
+ if (cursorIndex === wordCount - 1 && cursorPosition === "before") {
1281
+ setCursorPosition("after");
1282
+ } else if (cursorPosition !== "after") {
1283
+ newIndex = Math.min(wordCount - 1, cursorIndex + 1);
1284
+ }
1285
+ handled = true;
1286
+ } else if (e.key === "ArrowUp" || e.key === "ArrowDown") {
1287
+ const currentElement = contentRef.current?.querySelector(
1288
+ `[data-word-index="${cursorIndex}"]`
1289
+ );
1290
+ if (currentElement) {
1291
+ const currentRect = currentElement.getBoundingClientRect();
1292
+ const currentCenterX = currentRect.left + currentRect.width / 2;
1293
+ const direction = e.key === "ArrowUp" ? -1 : 1;
1294
+ let bestMatch = cursorIndex;
1295
+ let bestDistance = Infinity;
1296
+ let targetRowTop = null;
1297
+ for (let i = cursorIndex + direction; i >= 0 && i < wordCount; i += direction) {
1298
+ const el = contentRef.current?.querySelector(
1299
+ `[data-word-index="${i}"]`
1300
+ );
1301
+ if (!el) continue;
1302
+ const rect = el.getBoundingClientRect();
1303
+ const isOnDifferentRow = direction === -1 ? rect.bottom <= currentRect.top : rect.top >= currentRect.bottom;
1304
+ if (isOnDifferentRow) {
1305
+ if (targetRowTop === null) {
1306
+ targetRowTop = rect.top;
1307
+ }
1308
+ const isSameTargetRow = Math.abs(rect.top - targetRowTop) < 5;
1309
+ if (isSameTargetRow) {
1310
+ const centerX = rect.left + rect.width / 2;
1311
+ const distance = Math.abs(centerX - currentCenterX);
1312
+ if (distance < bestDistance) {
1313
+ bestDistance = distance;
1314
+ bestMatch = i;
1315
+ }
1316
+ } else {
1317
+ break;
1318
+ }
1319
+ }
1320
+ }
1321
+ newIndex = bestMatch;
1322
+ }
1323
+ handled = true;
1324
+ } else if (e.key === "Home") {
1325
+ newIndex = 0;
1326
+ handled = true;
1327
+ } else if (e.key === "End") {
1328
+ newIndex = wordCount - 1;
1329
+ handled = true;
1330
+ } else if (e.key === "Enter") {
1331
+ openWordEditor(cursorIndex);
1332
+ handled = true;
1333
+ } else if (e.key === " ") {
1334
+ const ew = editedWords[cursorIndex];
1335
+ const player = playerRef.current;
1336
+ if (player && ew && !ew.deleted) {
1337
+ if (player.isPaused()) {
1338
+ if (hasEdits) {
1339
+ const segments = playbackSegments;
1340
+ if (segments.length > 0) {
1341
+ let startSegmentIdx = 0;
1342
+ for (let i = 0; i < segments.length; i++) {
1343
+ if (segments[i].editedIndices.includes(cursorIndex)) {
1344
+ startSegmentIdx = i;
1345
+ break;
1346
+ }
1347
+ }
1348
+ sequenceSegments.current = segments;
1349
+ currentSegmentIndex.current = startSegmentIdx;
1350
+ setIsPlayingSequence(true);
1351
+ player.seekToMs(ew.word.startMs);
1352
+ player.play();
1353
+ }
1354
+ } else {
1355
+ player.seekToMs(ew.word.startMs);
1356
+ player.play();
1357
+ }
1358
+ } else {
1359
+ player.pause();
1360
+ setIsPlayingSequence(false);
1361
+ }
1362
+ }
1363
+ handled = true;
1364
+ }
1365
+ if (handled) {
1366
+ e.preventDefault();
1367
+ e.stopPropagation();
1368
+ if (newIndex !== cursorIndex) {
1369
+ setCursorIndex(newIndex);
1370
+ setCursorPosition("before");
1371
+ }
1372
+ if (e.shiftKey && e.key !== "Delete" && e.key !== "Backspace") {
1373
+ const anchor = selectionAnchor ?? cursorIndex;
1374
+ if (selectionAnchor === null) {
1375
+ setSelectionAnchor(cursorIndex);
1376
+ }
1377
+ setSelection({
1378
+ start: Math.min(anchor, newIndex),
1379
+ end: Math.max(anchor, newIndex)
1380
+ });
1381
+ } else if (!e.metaKey && !e.ctrlKey) {
1382
+ setSelection(null);
1383
+ setSelectionAnchor(null);
1384
+ }
1385
+ const wordElement = contentRef.current?.querySelector(
1386
+ `[data-word-index="${newIndex}"]`
1387
+ );
1388
+ wordElement?.scrollIntoView({ block: "nearest", behavior: "smooth" });
1389
+ }
1390
+ },
1391
+ [
1392
+ editedWords,
1393
+ cursorIndex,
1394
+ cursorPosition,
1395
+ selectionAnchor,
1396
+ clipboard,
1397
+ hasEdits,
1398
+ playbackSegments,
1399
+ handleDeleteToggle,
1400
+ handleCut,
1401
+ handlePaste,
1402
+ undo,
1403
+ openWordEditor
1404
+ ]
1405
+ );
1406
+ const isWordSelected = (index) => {
1407
+ if (!selection) return false;
1408
+ return index >= selection.start && index <= selection.end;
1409
+ };
1410
+ const renderWord = (ew, index) => {
1411
+ const isActive = index === activeWordIndex;
1412
+ const isCursor = index === cursorIndex;
1413
+ const isSelected = isWordSelected(index);
1414
+ const isDeleted = ew.deleted;
1415
+ const isInserted = ew.inserted ?? false;
1416
+ const isSilence = ew.word.wordType === "silence" || ew.word.wordType === "silence-newline";
1417
+ const isSilenceNewline = ew.word.wordType === "silence-newline";
1418
+ const isAnchor = index === doubleClickAnchor;
1419
+ const showCursorBefore = isCursor && cursorPosition === "before";
1420
+ const showCursorAfter = isCursor && cursorPosition === "after" && index === editedWords.length - 1;
1421
+ const speedMarker = getSpeedMarkerAtIndex(index);
1422
+ const hasSpeedMarker = !!speedMarker;
1423
+ const effectiveSpeed = getSpeedAtIndex(index);
1424
+ let displayText = ew.word.text;
1425
+ if (isSilence && effectiveSpeed !== 1) {
1426
+ const originalDurationMs = ew.word.endMs - ew.word.startMs;
1427
+ const adjustedDurationSec = originalDurationMs / effectiveSpeed / 1e3;
1428
+ displayText = `[${adjustedDurationSec.toFixed(1)}s]`;
1429
+ }
1430
+ const title = `${ew.word.startMs}ms - ${ew.word.endMs}ms${ew.word.confidence ? ` (${Math.round(ew.word.confidence * 100)}%)` : ""}${isSilence ? ` [SILENCE: ${((ew.word.endMs - ew.word.startMs) / 1e3).toFixed(1)}s${effectiveSpeed !== 1 ? ` \u2192 ${((ew.word.endMs - ew.word.startMs) / effectiveSpeed / 1e3).toFixed(1)}s @ ${effectiveSpeed}x` : ""}]` : ""}${isDeleted ? " [DELETED]" : ""}${isInserted ? " [INSERTED]" : ""}${hasSpeedMarker ? ` [SPEED: ${speedMarker.speed}x]` : ""}${isAnchor ? " [ANCHOR - click another word to select range, double-click to clear]" : ""}${!isAnchor && !isDeleted ? " (right-click to set speed marker)" : ""}`;
1431
+ return (
1432
+ // Keyboard interaction is owned by the parent listbox via roving focus
1433
+ // (aria-activedescendant); options are pointer affordances only.
1434
+ // eslint-disable-next-line jsx-a11y/click-events-have-key-events, jsx-a11y/interactive-supports-focus
1435
+ /* @__PURE__ */ jsxs(
1436
+ "span",
1437
+ {
1438
+ id: `word-${index}`,
1439
+ "data-word-index": index,
1440
+ className: wordClassName({
1441
+ isActive,
1442
+ isCursor,
1443
+ isSelected,
1444
+ isDeleted,
1445
+ isInserted,
1446
+ isSilence,
1447
+ isSilenceNewline,
1448
+ isAnchor,
1449
+ isFocused,
1450
+ hasSpeedMarker
1451
+ }),
1452
+ onClick: (e) => handleWordClick(ew.word, index, e),
1453
+ onDoubleClick: (e) => handleWordDoubleClick(index, e),
1454
+ onMouseDown: (e) => handleWordMouseDown(index, e),
1455
+ onMouseEnter: () => handleWordMouseEnter(index),
1456
+ onContextMenu: (e) => handleWordContextMenu(index, e),
1457
+ role: "option",
1458
+ "aria-selected": isSelected || isCursor,
1459
+ title,
1460
+ children: [
1461
+ showCursorBefore && isFocused && /* @__PURE__ */ jsx(Caret, { side: "before" }),
1462
+ hasSpeedMarker && /* @__PURE__ */ jsxs(
1463
+ "span",
1464
+ {
1465
+ 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",
1466
+ title: `Speed: ${speedMarker.speed}x from here`,
1467
+ children: [
1468
+ speedMarker.speed,
1469
+ "x"
1470
+ ]
1471
+ }
1472
+ ),
1473
+ displayText,
1474
+ " ",
1475
+ showCursorAfter && isFocused && /* @__PURE__ */ jsx(Caret, { side: "after" })
1476
+ ]
1477
+ },
1478
+ `${ew.originalIndex}-${index}`
1479
+ )
1480
+ );
1481
+ };
1482
+ const showEditBar = hasEdits || doubleClickAnchor !== null || selection !== null;
1483
+ return /* @__PURE__ */ jsxs(
1484
+ "div",
1485
+ {
1486
+ ref,
1487
+ className: mediaEditorVariants({ splitLayout, className }),
1488
+ children: [
1489
+ /* @__PURE__ */ jsxs(
1490
+ "div",
1491
+ {
1492
+ className: `flex min-h-0 min-w-0 flex-1 ${splitLayout === "vertical" ? "flex-col md:flex-row" : "flex-col"}`,
1493
+ children: [
1494
+ /* @__PURE__ */ jsx(
1495
+ "div",
1496
+ {
1497
+ className: `border-border bg-background min-h-0 shrink-0 ${splitLayout === "vertical" ? "md:w-1/2 md:border-r" : "max-h-[50%] border-b"}`,
1498
+ children: /* @__PURE__ */ jsx(
1499
+ MediaPlayer,
1500
+ {
1501
+ ref: playerRef,
1502
+ src,
1503
+ kind,
1504
+ "aria-label": "Media player",
1505
+ onTimeUpdate: handleTimeUpdate,
1506
+ onEnded: stopSequencePlayback
1507
+ }
1508
+ )
1509
+ }
1510
+ ),
1511
+ /* @__PURE__ */ jsxs(
1512
+ "div",
1513
+ {
1514
+ className: `flex min-h-0 flex-1 flex-col ${splitLayout === "vertical" ? "md:w-1/2" : ""}`,
1515
+ children: [
1516
+ /* @__PURE__ */ jsxs("div", { className: "border-border flex shrink-0 flex-wrap items-center justify-between gap-2 border-b px-3 py-2", children: [
1517
+ /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2", children: [
1518
+ hasEdits && /* @__PURE__ */ jsx("span", { className: "bg-warning/20 text-warning-foreground rounded px-1.5 py-0.5 text-xs font-semibold", children: "Edited" }),
1519
+ /* @__PURE__ */ jsx(
1520
+ "label",
1521
+ {
1522
+ className: "text-muted-foreground text-xs",
1523
+ htmlFor: "media-editor-default-speed",
1524
+ children: "Speed:"
1525
+ }
1526
+ ),
1527
+ /* @__PURE__ */ jsx("div", { className: "w-20", children: /* @__PURE__ */ jsx(
1528
+ Select,
1529
+ {
1530
+ id: "media-editor-default-speed",
1531
+ size: "sm",
1532
+ options: PLAYBACK_SPEEDS.map((speed) => ({
1533
+ value: String(speed),
1534
+ label: `${speed}x`
1535
+ })),
1536
+ value: String(defaultSpeed),
1537
+ onValueChange: (value) => setDefaultSpeed(parseFloat(value)),
1538
+ "aria-label": "Default playback speed"
1539
+ }
1540
+ ) }),
1541
+ speedMarkers.length > 0 && /* @__PURE__ */ jsxs(
1542
+ "span",
1543
+ {
1544
+ className: "text-muted-foreground text-xs",
1545
+ title: `${speedMarkers.length} speed marker(s) set. Right-click on a word to add/remove speed markers.`,
1546
+ children: [
1547
+ speedMarkers.length,
1548
+ " marker",
1549
+ speedMarkers.length !== 1 ? "s" : ""
1550
+ ]
1551
+ }
1552
+ ),
1553
+ /* @__PURE__ */ jsx(
1554
+ Button,
1555
+ {
1556
+ variant: "ghost",
1557
+ size: "sm",
1558
+ onClick: () => setShowFillerModal(true),
1559
+ "aria-label": "Remove filler words",
1560
+ title: "Remove filler words",
1561
+ children: "\u2702\uFE0F"
1562
+ }
1563
+ ),
1564
+ undoStack.length > 0 && /* @__PURE__ */ jsxs(
1565
+ Button,
1566
+ {
1567
+ variant: "ghost",
1568
+ size: "sm",
1569
+ onClick: undo,
1570
+ "aria-label": `Undo (${undoStack.length} available)`,
1571
+ title: "Undo (\u2318Z)",
1572
+ children: [
1573
+ "Undo (",
1574
+ undoStack.length,
1575
+ ")"
1576
+ ]
1577
+ }
1578
+ )
1579
+ ] }),
1580
+ /* @__PURE__ */ jsxs("div", { className: "text-muted-foreground flex items-center gap-2 text-xs", children: [
1581
+ /* @__PURE__ */ jsx(
1582
+ Button,
1583
+ {
1584
+ variant: "ghost",
1585
+ size: "sm",
1586
+ onClick: () => setShowScriptPanel((v) => !v),
1587
+ "aria-pressed": showScriptPanel,
1588
+ "aria-label": "Show script",
1589
+ title: "Show the transcript script (editable YAML/JSON)",
1590
+ children: "Script"
1591
+ }
1592
+ ),
1593
+ /* @__PURE__ */ jsxs("span", { children: [
1594
+ stats.activeWordCount,
1595
+ " words"
1596
+ ] }),
1597
+ /* @__PURE__ */ jsxs(
1598
+ "button",
1599
+ {
1600
+ type: "button",
1601
+ 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",
1602
+ onClick: () => setShowSilenceModal(true),
1603
+ title: stats.activeSilenceCount > 0 ? `Click to configure silence detection (currently \u2265${(silenceThresholds.minSilenceMs / 1e3).toFixed(1)}s)` : `No silences detected (threshold: ${(silenceThresholds.minSilenceMs / 1e3).toFixed(1)}s). Click to configure.`,
1604
+ "aria-label": "Configure silence detection",
1605
+ children: [
1606
+ stats.activeSilenceCount,
1607
+ " silences"
1608
+ ]
1609
+ }
1610
+ ),
1611
+ (stats.deletedWordCount > 0 || stats.deletedSilenceCount > 0) && /* @__PURE__ */ jsxs("span", { className: "text-destructive", children: [
1612
+ stats.deletedWordCount + stats.deletedSilenceCount,
1613
+ " deleted"
1614
+ ] }),
1615
+ transcript.speakers && /* @__PURE__ */ jsxs("span", { children: [
1616
+ transcript.speakers.length,
1617
+ " speakers"
1618
+ ] }),
1619
+ /* @__PURE__ */ jsx("span", { children: formatDuration2(stats.editedDurationMs) })
1620
+ ] })
1621
+ ] }),
1622
+ showEditBar && /* @__PURE__ */ jsxs("div", { className: "border-border bg-muted/40 flex shrink-0 items-center gap-1 border-b px-3 py-1", children: [
1623
+ /* @__PURE__ */ jsxs(
1624
+ Button,
1625
+ {
1626
+ variant: "ghost",
1627
+ size: "sm",
1628
+ onClick: () => openWordEditor(cursorIndex),
1629
+ title: "Edit selected word (Enter)",
1630
+ children: [
1631
+ "Edit ",
1632
+ /* @__PURE__ */ jsx("kbd", { className: "text-[10px] opacity-60", children: "\u21B5" })
1633
+ ]
1634
+ }
1635
+ ),
1636
+ /* @__PURE__ */ jsxs(
1637
+ Button,
1638
+ {
1639
+ variant: "ghost",
1640
+ size: "sm",
1641
+ onClick: handleDeleteToggle,
1642
+ title: "Delete selected word (Del)",
1643
+ children: [
1644
+ "Del ",
1645
+ /* @__PURE__ */ jsx("kbd", { className: "text-[10px] opacity-60", children: "\u232B" })
1646
+ ]
1647
+ }
1648
+ ),
1649
+ /* @__PURE__ */ jsxs(
1650
+ Button,
1651
+ {
1652
+ variant: "ghost",
1653
+ size: "sm",
1654
+ onClick: handleCut,
1655
+ title: "Cut selection (\u2318X)",
1656
+ children: [
1657
+ "Cut ",
1658
+ /* @__PURE__ */ jsx("kbd", { className: "text-[10px] opacity-60", children: "\u2318X" })
1659
+ ]
1660
+ }
1661
+ ),
1662
+ /* @__PURE__ */ jsxs(
1663
+ Button,
1664
+ {
1665
+ variant: "ghost",
1666
+ size: "sm",
1667
+ onClick: handlePaste,
1668
+ disabled: !clipboard,
1669
+ title: "Paste (\u2318V)",
1670
+ children: [
1671
+ "Paste ",
1672
+ /* @__PURE__ */ jsx("kbd", { className: "text-[10px] opacity-60", children: "\u2318V" })
1673
+ ]
1674
+ }
1675
+ )
1676
+ ] }),
1677
+ /* @__PURE__ */ jsx(
1678
+ "div",
1679
+ {
1680
+ ref: contentRef,
1681
+ 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 ${isFocused ? "bg-muted/20" : ""}`,
1682
+ tabIndex: 0,
1683
+ onKeyDown: handleKeyDown,
1684
+ onCopy: handleCopy,
1685
+ onFocus: () => setIsFocused(true),
1686
+ onBlur: () => setIsFocused(false),
1687
+ onMouseUp: handleMouseUp,
1688
+ onMouseLeave: handleMouseUp,
1689
+ role: "listbox",
1690
+ "aria-label": "Transcript words",
1691
+ "aria-activedescendant": `word-${cursorIndex}`,
1692
+ children: editedWords.map(renderWord)
1693
+ }
1694
+ )
1695
+ ]
1696
+ }
1697
+ )
1698
+ ]
1699
+ }
1700
+ ),
1701
+ showScriptPanel && /* @__PURE__ */ jsx(
1702
+ ScriptPanel,
1703
+ {
1704
+ transcript,
1705
+ editedWords,
1706
+ onApply: replaceEditedWords,
1707
+ onClose: () => setShowScriptPanel(false)
1708
+ }
1709
+ ),
1710
+ /* @__PURE__ */ jsx(
1711
+ FillerWordsModal,
1712
+ {
1713
+ isOpen: showFillerModal,
1714
+ onClose: () => setShowFillerModal(false),
1715
+ onApply: removeFillers,
1716
+ matchingCounts: fillerAnalysis.matchCounts,
1717
+ fillerDurations: fillerAnalysis.durations,
1718
+ silenceCounts: fillerAnalysis.silenceCounts,
1719
+ currentDurationMs: stats.editedDurationMs
1720
+ }
1721
+ ),
1722
+ /* @__PURE__ */ jsx(
1723
+ SilenceSettingsModal,
1724
+ {
1725
+ isOpen: showSilenceModal,
1726
+ onClose: () => setShowSilenceModal(false),
1727
+ minSilenceMs: silenceThresholds.minSilenceMs,
1728
+ nlSilenceMs: silenceThresholds.nlSilenceMs,
1729
+ onApply: setSilenceThresholds
1730
+ }
1731
+ ),
1732
+ /* @__PURE__ */ jsx(
1733
+ WordEditorModal,
1734
+ {
1735
+ isOpen: editorWordIndex !== null,
1736
+ editableWord: editorWordIndex !== null ? editedWords[editorWordIndex] ?? null : null,
1737
+ onClose: closeWordEditor,
1738
+ onSave: handleEditorSave,
1739
+ onSplitSilence: handleEditorSplitSilence,
1740
+ onDelete: handleEditorDelete
1741
+ }
1742
+ ),
1743
+ /* @__PURE__ */ jsx(
1744
+ SpeedMarkerMenu,
1745
+ {
1746
+ isOpen: speedMenuWordIndex !== null,
1747
+ position: speedMenuPosition,
1748
+ wordIndex: speedMenuWordIndex,
1749
+ currentMarker: speedMenuWordIndex !== null ? getSpeedMarkerAtIndex(speedMenuWordIndex) : void 0,
1750
+ defaultSpeed,
1751
+ onSetSpeed: (speed) => {
1752
+ if (speedMenuWordIndex !== null) {
1753
+ toggleSpeedMarker(speedMenuWordIndex, speed);
1754
+ }
1755
+ },
1756
+ onRemoveMarker: () => {
1757
+ if (speedMenuWordIndex !== null) {
1758
+ removeSpeedMarker(speedMenuWordIndex);
1759
+ }
1760
+ },
1761
+ onClose: () => {
1762
+ setSpeedMenuWordIndex(null);
1763
+ setSpeedMenuPosition(null);
1764
+ }
1765
+ }
1766
+ )
1767
+ ]
1768
+ }
1769
+ );
1770
+ }
1771
+ );
1772
+ MediaEditor.displayName = "MediaEditor";
1773
+
1774
+ export { FillerWordsModal, MediaEditor, SilenceSettingsModal, SpeedMarkerMenu, WordEditorModal };
1775
+ //# sourceMappingURL=chunk-YVLP3ATI.js.map
1776
+ //# sourceMappingURL=chunk-YVLP3ATI.js.map