@mieweb/ui 0.8.0-dev.9 → 0.9.0-dev.0

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 (311) hide show
  1. package/dist/Animated-Cs-naa2g.d.cts +175 -0
  2. package/dist/Animated-Cs-naa2g.d.ts +175 -0
  3. package/dist/CsvBlock-D7Z6ZCRP.js +6 -0
  4. package/dist/{CsvBlock-RPGHFTVD.js.map → CsvBlock-D7Z6ZCRP.js.map} +1 -1
  5. package/dist/CsvBlock-QXXZ7ZUM.cjs +15 -0
  6. package/dist/{CsvBlock-HMAZ7YK5.cjs.map → CsvBlock-QXXZ7ZUM.cjs.map} +1 -1
  7. package/dist/HtmlPreviewBlock-AADG7MVB.cjs +15 -0
  8. package/dist/{HtmlPreviewBlock-QHLSIMWJ.cjs.map → HtmlPreviewBlock-AADG7MVB.cjs.map} +1 -1
  9. package/dist/HtmlPreviewBlock-F5VDM2EN.js +6 -0
  10. package/dist/{HtmlPreviewBlock-YF2YVKKX.js.map → HtmlPreviewBlock-F5VDM2EN.js.map} +1 -1
  11. package/dist/MermaidBlock-6PLITRBZ.js +6 -0
  12. package/dist/{MermaidBlock-H3TWNC4D.js.map → MermaidBlock-6PLITRBZ.js.map} +1 -1
  13. package/dist/MermaidBlock-TQ2O5CLV.cjs +15 -0
  14. package/dist/{MermaidBlock-ZLLBO3VY.cjs.map → MermaidBlock-TQ2O5CLV.cjs.map} +1 -1
  15. package/dist/SurveyBlock-OYL3VNU5.cjs +15 -0
  16. package/dist/{SurveyBlock-K6HKI7AD.cjs.map → SurveyBlock-OYL3VNU5.cjs.map} +1 -1
  17. package/dist/SurveyBlock-W5PSQ62F.js +6 -0
  18. package/dist/{SurveyBlock-ID55AT3R.js.map → SurveyBlock-W5PSQ62F.js.map} +1 -1
  19. package/dist/ag-grid.cjs +5 -5
  20. package/dist/ag-grid.js +1 -1
  21. package/dist/brands/index.cjs +7 -7
  22. package/dist/brands/index.js +2 -2
  23. package/dist/{chunk-5JZIDILK.cjs → chunk-3LHICE4I.cjs} +6 -6
  24. package/dist/chunk-3LHICE4I.cjs.map +1 -0
  25. package/dist/{chunk-JHZW3Y62.js → chunk-3RB35GYK.js} +5 -5
  26. package/dist/chunk-3RB35GYK.js.map +1 -0
  27. package/dist/{chunk-JMZF7ZHF.cjs → chunk-4SM3I7WE.cjs} +4 -4
  28. package/dist/{chunk-JMZF7ZHF.cjs.map → chunk-4SM3I7WE.cjs.map} +1 -1
  29. package/dist/{chunk-ZONEAWPR.cjs → chunk-5BVFVXHN.cjs} +218 -151
  30. package/dist/chunk-5BVFVXHN.cjs.map +1 -0
  31. package/dist/{chunk-CAN3A3DC.js → chunk-5H7SAEQO.js} +4 -4
  32. package/dist/{chunk-CAN3A3DC.js.map → chunk-5H7SAEQO.js.map} +1 -1
  33. package/dist/{chunk-EMMYFHOT.js → chunk-5WOB4UBD.js} +3 -3
  34. package/dist/{chunk-EMMYFHOT.js.map → chunk-5WOB4UBD.js.map} +1 -1
  35. package/dist/{chunk-JIU6CVPF.cjs → chunk-5Z6UPVGC.cjs} +5 -5
  36. package/dist/{chunk-JIU6CVPF.cjs.map → chunk-5Z6UPVGC.cjs.map} +1 -1
  37. package/dist/{chunk-YIXTGWT4.cjs → chunk-6QKMMKRY.cjs} +5 -5
  38. package/dist/{chunk-YIXTGWT4.cjs.map → chunk-6QKMMKRY.cjs.map} +1 -1
  39. package/dist/{chunk-F57VRLKP.js → chunk-6SAYPXHX.js} +4 -4
  40. package/dist/{chunk-F57VRLKP.js.map → chunk-6SAYPXHX.js.map} +1 -1
  41. package/dist/{chunk-5EKRH4KE.cjs → chunk-6XDPJWSC.cjs} +93 -77
  42. package/dist/chunk-6XDPJWSC.cjs.map +1 -0
  43. package/dist/{chunk-4AE2L6AO.cjs → chunk-7FTBPLA6.cjs} +8 -8
  44. package/dist/chunk-7FTBPLA6.cjs.map +1 -0
  45. package/dist/{chunk-AGYNCPJ2.cjs → chunk-7KN6J7XV.cjs} +19 -19
  46. package/dist/{chunk-AGYNCPJ2.cjs.map → chunk-7KN6J7XV.cjs.map} +1 -1
  47. package/dist/{chunk-SNSA6NWD.cjs → chunk-AHINB2TP.cjs} +9 -9
  48. package/dist/{chunk-SNSA6NWD.cjs.map → chunk-AHINB2TP.cjs.map} +1 -1
  49. package/dist/chunk-BKSPDTX4.js +3 -0
  50. package/dist/{chunk-3PXOIAF6.js.map → chunk-BKSPDTX4.js.map} +1 -1
  51. package/dist/chunk-BN75TLUN.cjs +163 -0
  52. package/dist/chunk-BN75TLUN.cjs.map +1 -0
  53. package/dist/{chunk-WWJIW2IH.cjs → chunk-BVMABVC4.cjs} +3 -3
  54. package/dist/{chunk-WWJIW2IH.cjs.map → chunk-BVMABVC4.cjs.map} +1 -1
  55. package/dist/{chunk-VKNCQIVN.cjs → chunk-BZAGP5W6.cjs} +8 -8
  56. package/dist/{chunk-VKNCQIVN.cjs.map → chunk-BZAGP5W6.cjs.map} +1 -1
  57. package/dist/{chunk-RS5VA6QU.cjs → chunk-C3DUS2VE.cjs} +3 -3
  58. package/dist/{chunk-RS5VA6QU.cjs.map → chunk-C3DUS2VE.cjs.map} +1 -1
  59. package/dist/{chunk-NLBT5O2X.js → chunk-CK3KLRNF.js} +3 -3
  60. package/dist/{chunk-NLBT5O2X.js.map → chunk-CK3KLRNF.js.map} +1 -1
  61. package/dist/{chunk-4J4FDVPS.cjs → chunk-CXDMZT45.cjs} +36 -3
  62. package/dist/chunk-CXDMZT45.cjs.map +1 -0
  63. package/dist/{chunk-TXRQQMG5.js → chunk-CYMZ2QS5.js} +2 -2
  64. package/dist/{chunk-TXRQQMG5.js.map → chunk-CYMZ2QS5.js.map} +1 -1
  65. package/dist/{chunk-CLQUCPV6.js → chunk-D25WH7MH.js} +7 -7
  66. package/dist/{chunk-CLQUCPV6.js.map → chunk-D25WH7MH.js.map} +1 -1
  67. package/dist/{chunk-ATOWMVZH.js → chunk-DFYMIRMW.js} +3 -3
  68. package/dist/{chunk-ATOWMVZH.js.map → chunk-DFYMIRMW.js.map} +1 -1
  69. package/dist/{chunk-ZJ5KAZLW.js → chunk-DGRXAIWK.js} +36 -3
  70. package/dist/chunk-DGRXAIWK.js.map +1 -0
  71. package/dist/{chunk-UZ5NGGMI.js → chunk-EG7XFZ3W.js} +4 -4
  72. package/dist/{chunk-UZ5NGGMI.js.map → chunk-EG7XFZ3W.js.map} +1 -1
  73. package/dist/{chunk-D6UXVOPS.cjs → chunk-FQBTGS3E.cjs} +5 -5
  74. package/dist/{chunk-D6UXVOPS.cjs.map → chunk-FQBTGS3E.cjs.map} +1 -1
  75. package/dist/{chunk-7SFGEE4M.cjs → chunk-FUFBRKOG.cjs} +48 -48
  76. package/dist/{chunk-7SFGEE4M.cjs.map → chunk-FUFBRKOG.cjs.map} +1 -1
  77. package/dist/{chunk-VA3WQ5KJ.cjs → chunk-FYAKUU2A.cjs} +37 -20
  78. package/dist/chunk-FYAKUU2A.cjs.map +1 -0
  79. package/dist/{chunk-JR4QIU54.cjs → chunk-H4AVMUOC.cjs} +10 -4
  80. package/dist/chunk-H4AVMUOC.cjs.map +1 -0
  81. package/dist/{chunk-I2ECTLON.cjs → chunk-HXSA6QC5.cjs} +3 -3
  82. package/dist/{chunk-I2ECTLON.cjs.map → chunk-HXSA6QC5.cjs.map} +1 -1
  83. package/dist/{chunk-X5ZPYYMS.js → chunk-I3DQXUSC.js} +3 -3
  84. package/dist/{chunk-X5ZPYYMS.js.map → chunk-I3DQXUSC.js.map} +1 -1
  85. package/dist/{chunk-FN6VHMLM.cjs → chunk-IB54SKWB.cjs} +8 -8
  86. package/dist/{chunk-FN6VHMLM.cjs.map → chunk-IB54SKWB.cjs.map} +1 -1
  87. package/dist/{chunk-JP5SGIXA.cjs → chunk-IFDC4TXM.cjs} +4 -4
  88. package/dist/{chunk-JP5SGIXA.cjs.map → chunk-IFDC4TXM.cjs.map} +1 -1
  89. package/dist/{chunk-RDGRKYQ5.cjs → chunk-IINZWUGK.cjs} +58 -6
  90. package/dist/chunk-IINZWUGK.cjs.map +1 -0
  91. package/dist/{chunk-D2GID3YK.js → chunk-KREUYVMZ.js} +58 -6
  92. package/dist/chunk-KREUYVMZ.js.map +1 -0
  93. package/dist/{chunk-Y6YSJPVC.js → chunk-KRU6IGV7.js} +11 -3
  94. package/dist/chunk-KRU6IGV7.js.map +1 -0
  95. package/dist/{chunk-K52C5UBS.js → chunk-KU3XRHWA.js} +4 -4
  96. package/dist/{chunk-K52C5UBS.js.map → chunk-KU3XRHWA.js.map} +1 -1
  97. package/dist/{chunk-P2VTQ5AR.cjs → chunk-L52N6BEN.cjs} +39 -23
  98. package/dist/chunk-L52N6BEN.cjs.map +1 -0
  99. package/dist/{chunk-6GKX36JX.js → chunk-L5W7TJQ5.js} +10 -4
  100. package/dist/chunk-L5W7TJQ5.js.map +1 -0
  101. package/dist/{chunk-PAM5UUBL.cjs → chunk-L7L5S2HO.cjs} +18 -2
  102. package/dist/{chunk-PAM5UUBL.cjs.map → chunk-L7L5S2HO.cjs.map} +1 -1
  103. package/dist/{chunk-RVGTI4F6.js → chunk-LAEIVOIY.js} +37 -20
  104. package/dist/chunk-LAEIVOIY.js.map +1 -0
  105. package/dist/{chunk-Z5KFXHDP.cjs → chunk-MM7QKUE3.cjs} +5 -5
  106. package/dist/{chunk-Z5KFXHDP.cjs.map → chunk-MM7QKUE3.cjs.map} +1 -1
  107. package/dist/{chunk-FJ7YPVKV.js → chunk-MUIDWFYJ.js} +3 -3
  108. package/dist/{chunk-FJ7YPVKV.js.map → chunk-MUIDWFYJ.js.map} +1 -1
  109. package/dist/{chunk-GPZDP2IA.js → chunk-MXQ7J4BB.js} +3 -3
  110. package/dist/{chunk-GPZDP2IA.js.map → chunk-MXQ7J4BB.js.map} +1 -1
  111. package/dist/{chunk-4KFVGIY6.js → chunk-NHN6A3ZO.js} +4 -4
  112. package/dist/{chunk-4KFVGIY6.js.map → chunk-NHN6A3ZO.js.map} +1 -1
  113. package/dist/{chunk-KLLRTTC5.js → chunk-O6GJ4IYS.js} +216 -151
  114. package/dist/chunk-O6GJ4IYS.js.map +1 -0
  115. package/dist/{chunk-4SIGL6QC.cjs → chunk-O7XHHTTP.cjs} +8 -8
  116. package/dist/{chunk-4SIGL6QC.cjs.map → chunk-O7XHHTTP.cjs.map} +1 -1
  117. package/dist/{chunk-7L4SY5YY.js → chunk-OAZUDUGX.js} +6 -4
  118. package/dist/chunk-OAZUDUGX.js.map +1 -0
  119. package/dist/{chunk-NFKX6QJP.cjs → chunk-OCV33S5Q.cjs} +3 -3
  120. package/dist/{chunk-NFKX6QJP.cjs.map → chunk-OCV33S5Q.cjs.map} +1 -1
  121. package/dist/{chunk-MUUB35XB.js → chunk-ODYQYLO2.js} +27 -11
  122. package/dist/chunk-ODYQYLO2.js.map +1 -0
  123. package/dist/{chunk-FPVRQCCL.js → chunk-OHDIJOGG.js} +4 -4
  124. package/dist/{chunk-FPVRQCCL.js.map → chunk-OHDIJOGG.js.map} +1 -1
  125. package/dist/{chunk-GQVL2JKQ.cjs → chunk-OHKO5THF.cjs} +3 -3
  126. package/dist/{chunk-GQVL2JKQ.cjs.map → chunk-OHKO5THF.cjs.map} +1 -1
  127. package/dist/{chunk-LMBXJZLG.js → chunk-ON4JULCA.js} +3 -3
  128. package/dist/{chunk-LMBXJZLG.js.map → chunk-ON4JULCA.js.map} +1 -1
  129. package/dist/{chunk-4KZIXV2J.js → chunk-ONNY7UO4.js} +6 -6
  130. package/dist/{chunk-4KZIXV2J.js.map → chunk-ONNY7UO4.js.map} +1 -1
  131. package/dist/{chunk-XNU4NTVE.js → chunk-OSPTA4UR.js} +3 -3
  132. package/dist/{chunk-XNU4NTVE.js.map → chunk-OSPTA4UR.js.map} +1 -1
  133. package/dist/{chunk-FDUA6OGN.js → chunk-PFKRHNYV.js} +8 -8
  134. package/dist/chunk-PFKRHNYV.js.map +1 -0
  135. package/dist/{chunk-KFEN2SRZ.js → chunk-PHK4XBO5.js} +3 -3
  136. package/dist/{chunk-KFEN2SRZ.js.map → chunk-PHK4XBO5.js.map} +1 -1
  137. package/dist/{chunk-Q4NRKKIW.js → chunk-PYHFVYVZ.js} +3 -3
  138. package/dist/{chunk-Q4NRKKIW.js.map → chunk-PYHFVYVZ.js.map} +1 -1
  139. package/dist/{chunk-XMCIXHGH.js → chunk-Q7G56ZIO.js} +39 -23
  140. package/dist/chunk-Q7G56ZIO.js.map +1 -0
  141. package/dist/{chunk-CLRWVJOD.js → chunk-QAKASRE6.js} +32 -24
  142. package/dist/chunk-QAKASRE6.js.map +1 -0
  143. package/dist/{chunk-UBOVDAD7.js → chunk-QAQOCS2J.js} +3 -3
  144. package/dist/{chunk-UBOVDAD7.js.map → chunk-QAQOCS2J.js.map} +1 -1
  145. package/dist/{chunk-YVIH26FG.cjs → chunk-QKAYRHWP.cjs} +12 -12
  146. package/dist/{chunk-YVIH26FG.cjs.map → chunk-QKAYRHWP.cjs.map} +1 -1
  147. package/dist/{chunk-P3JEMF6E.cjs → chunk-RSCA5AZW.cjs} +4 -4
  148. package/dist/{chunk-P3JEMF6E.cjs.map → chunk-RSCA5AZW.cjs.map} +1 -1
  149. package/dist/{chunk-5Y5FSR4N.js → chunk-SCXELRRZ.js} +3 -3
  150. package/dist/{chunk-5Y5FSR4N.js.map → chunk-SCXELRRZ.js.map} +1 -1
  151. package/dist/{chunk-JWTCEWQ4.cjs → chunk-SNEQXSC5.cjs} +2 -2
  152. package/dist/{chunk-JWTCEWQ4.cjs.map → chunk-SNEQXSC5.cjs.map} +1 -1
  153. package/dist/{chunk-ZPZAZQW4.cjs → chunk-SRA2L3SQ.cjs} +6 -4
  154. package/dist/chunk-SRA2L3SQ.cjs.map +1 -0
  155. package/dist/{chunk-HK3AMH3Q.cjs → chunk-VROIMIHB.cjs} +11 -3
  156. package/dist/chunk-VROIMIHB.cjs.map +1 -0
  157. package/dist/{chunk-3SHLOF4V.cjs → chunk-VTR2KGLY.cjs} +9 -9
  158. package/dist/{chunk-3SHLOF4V.cjs.map → chunk-VTR2KGLY.cjs.map} +1 -1
  159. package/dist/chunk-WYMO3IIK.js +136 -0
  160. package/dist/chunk-WYMO3IIK.js.map +1 -0
  161. package/dist/{chunk-ABTO4RD6.cjs → chunk-X5QRRMGB.cjs} +32 -24
  162. package/dist/chunk-X5QRRMGB.cjs.map +1 -0
  163. package/dist/{chunk-SH6B4MG5.js → chunk-XBXDUAIM.js} +4 -4
  164. package/dist/{chunk-SH6B4MG5.js.map → chunk-XBXDUAIM.js.map} +1 -1
  165. package/dist/{chunk-K5GQPTTA.cjs → chunk-XEEVDZDK.cjs} +3 -3
  166. package/dist/{chunk-K5GQPTTA.cjs.map → chunk-XEEVDZDK.cjs.map} +1 -1
  167. package/dist/{chunk-GXODR6V4.js → chunk-XOIIUO6O.js} +3 -3
  168. package/dist/{chunk-GXODR6V4.js.map → chunk-XOIIUO6O.js.map} +1 -1
  169. package/dist/{chunk-AHHFFXJR.cjs → chunk-XTHMC76F.cjs} +3 -3
  170. package/dist/{chunk-AHHFFXJR.cjs.map → chunk-XTHMC76F.cjs.map} +1 -1
  171. package/dist/{chunk-TVLZZI5Q.cjs → chunk-YJP6DUFO.cjs} +9 -9
  172. package/dist/{chunk-TVLZZI5Q.cjs.map → chunk-YJP6DUFO.cjs.map} +1 -1
  173. package/dist/{chunk-EHQ77LL5.js → chunk-ZB54MTMQ.js} +3 -3
  174. package/dist/{chunk-EHQ77LL5.js.map → chunk-ZB54MTMQ.js.map} +1 -1
  175. package/dist/components/Accordion/index.cjs +2 -2
  176. package/dist/components/Accordion/index.js +1 -1
  177. package/dist/components/Alert/index.d.cts +1 -1
  178. package/dist/components/Alert/index.d.ts +1 -1
  179. package/dist/components/AlertDialog/index.cjs +6 -5
  180. package/dist/components/AlertDialog/index.js +5 -4
  181. package/dist/components/Autocomplete/index.cjs +3 -3
  182. package/dist/components/Autocomplete/index.js +2 -2
  183. package/dist/components/Badge/index.d.cts +1 -1
  184. package/dist/components/Badge/index.d.ts +1 -1
  185. package/dist/components/Breadcrumb/index.cjs +3 -3
  186. package/dist/components/Breadcrumb/index.js +1 -1
  187. package/dist/components/Button/index.cjs +3 -3
  188. package/dist/components/Button/index.js +1 -1
  189. package/dist/components/Card/index.d.cts +2 -2
  190. package/dist/components/Card/index.d.ts +2 -2
  191. package/dist/components/CountryCodeDropdown/index.cjs +5 -5
  192. package/dist/components/CountryCodeDropdown/index.d.cts +11 -1
  193. package/dist/components/CountryCodeDropdown/index.d.ts +11 -1
  194. package/dist/components/CountryCodeDropdown/index.js +2 -2
  195. package/dist/components/CustomizableDashboard/index.cjs +11 -11
  196. package/dist/components/CustomizableDashboard/index.js +4 -4
  197. package/dist/components/DateInput/index.cjs +4 -4
  198. package/dist/components/DateInput/index.js +3 -3
  199. package/dist/components/Dropdown/index.cjs +9 -9
  200. package/dist/components/Dropdown/index.js +2 -2
  201. package/dist/components/FloatingWindow/index.cjs +4 -4
  202. package/dist/components/FloatingWindow/index.js +2 -2
  203. package/dist/components/GlossaryTooltip/index.cjs +3 -3
  204. package/dist/components/GlossaryTooltip/index.js +2 -2
  205. package/dist/components/KeyboardShortcutsOverlay/index.cjs +6 -5
  206. package/dist/components/KeyboardShortcutsOverlay/index.js +4 -3
  207. package/dist/components/Markdown/index.cjs +19 -19
  208. package/dist/components/Markdown/index.js +7 -7
  209. package/dist/components/MediaEditor/index.cjs +13 -12
  210. package/dist/components/MediaEditor/index.js +8 -7
  211. package/dist/components/MediaPlayer/index.cjs +6 -6
  212. package/dist/components/MediaPlayer/index.js +3 -3
  213. package/dist/components/Modal/index.cjs +11 -10
  214. package/dist/components/Modal/index.d.cts +1 -1
  215. package/dist/components/Modal/index.d.ts +1 -1
  216. package/dist/components/Modal/index.js +3 -2
  217. package/dist/components/Pagination/index.cjs +4 -4
  218. package/dist/components/Pagination/index.d.cts +1 -1
  219. package/dist/components/Pagination/index.d.ts +1 -1
  220. package/dist/components/Pagination/index.js +1 -1
  221. package/dist/components/PhoneInput/index.cjs +4 -4
  222. package/dist/components/PhoneInput/index.js +2 -2
  223. package/dist/components/Progress/index.d.cts +1 -1
  224. package/dist/components/Progress/index.d.ts +1 -1
  225. package/dist/components/RecordButton/index.d.cts +1 -1
  226. package/dist/components/RecordButton/index.d.ts +1 -1
  227. package/dist/components/RichTextEditor/index.cjs +8 -8
  228. package/dist/components/RichTextEditor/index.js +5 -5
  229. package/dist/components/SectionSpyNav/index.cjs +4 -4
  230. package/dist/components/SectionSpyNav/index.js +3 -3
  231. package/dist/components/Select/index.cjs +4 -4
  232. package/dist/components/Select/index.js +2 -2
  233. package/dist/components/Sheet/index.cjs +11 -11
  234. package/dist/components/Sheet/index.js +2 -2
  235. package/dist/components/Slider/index.d.cts +2 -2
  236. package/dist/components/Slider/index.d.ts +2 -2
  237. package/dist/components/SourceTip/index.cjs +3 -3
  238. package/dist/components/SourceTip/index.js +2 -2
  239. package/dist/components/SuperChat/index.cjs +10 -10
  240. package/dist/components/SuperChat/index.js +4 -4
  241. package/dist/components/SuperChat/plugins/index.cjs +4 -4
  242. package/dist/components/SuperChat/plugins/index.js +3 -3
  243. package/dist/components/Text/index.d.cts +1 -1
  244. package/dist/components/Text/index.d.ts +1 -1
  245. package/dist/components/ThemeProvider/index.cjs +9 -9
  246. package/dist/components/ThemeProvider/index.d.cts +1 -1
  247. package/dist/components/ThemeProvider/index.d.ts +1 -1
  248. package/dist/components/ThemeProvider/index.js +3 -3
  249. package/dist/components/Toggle/index.d.cts +1 -1
  250. package/dist/components/Toggle/index.d.ts +1 -1
  251. package/dist/components/Tooltip/index.cjs +3 -3
  252. package/dist/components/Tooltip/index.js +2 -2
  253. package/dist/components/TranscriptView/index.cjs +3 -3
  254. package/dist/components/TranscriptView/index.js +1 -1
  255. package/dist/datavis.cjs +2 -2
  256. package/dist/datavis.js +1 -1
  257. package/dist/esheet.cjs +14 -13
  258. package/dist/esheet.cjs.map +1 -1
  259. package/dist/esheet.js +11 -10
  260. package/dist/esheet.js.map +1 -1
  261. package/dist/hooks/index.cjs +1 -1
  262. package/dist/hooks/index.js +1 -1
  263. package/dist/index.cjs +1850 -1123
  264. package/dist/index.cjs.map +1 -1
  265. package/dist/index.d.cts +227 -29
  266. package/dist/index.d.ts +227 -29
  267. package/dist/index.js +826 -131
  268. package/dist/index.js.map +1 -1
  269. package/dist/motion.cjs +87 -0
  270. package/dist/motion.cjs.map +1 -0
  271. package/dist/motion.d.cts +52 -0
  272. package/dist/motion.d.ts +52 -0
  273. package/dist/motion.js +50 -0
  274. package/dist/motion.js.map +1 -0
  275. package/dist/styles.css +1 -1
  276. package/dist/tailwind-preset.cjs +4 -4
  277. package/dist/tailwind-preset.js +1 -1
  278. package/package.json +17 -1
  279. package/dist/CsvBlock-HMAZ7YK5.cjs +0 -15
  280. package/dist/CsvBlock-RPGHFTVD.js +0 -6
  281. package/dist/HtmlPreviewBlock-QHLSIMWJ.cjs +0 -15
  282. package/dist/HtmlPreviewBlock-YF2YVKKX.js +0 -6
  283. package/dist/MermaidBlock-H3TWNC4D.js +0 -6
  284. package/dist/MermaidBlock-ZLLBO3VY.cjs +0 -15
  285. package/dist/SurveyBlock-ID55AT3R.js +0 -6
  286. package/dist/SurveyBlock-K6HKI7AD.cjs +0 -15
  287. package/dist/chunk-3PXOIAF6.js +0 -3
  288. package/dist/chunk-4AE2L6AO.cjs.map +0 -1
  289. package/dist/chunk-4J4FDVPS.cjs.map +0 -1
  290. package/dist/chunk-5EKRH4KE.cjs.map +0 -1
  291. package/dist/chunk-5JZIDILK.cjs.map +0 -1
  292. package/dist/chunk-6GKX36JX.js.map +0 -1
  293. package/dist/chunk-7L4SY5YY.js.map +0 -1
  294. package/dist/chunk-ABTO4RD6.cjs.map +0 -1
  295. package/dist/chunk-CLRWVJOD.js.map +0 -1
  296. package/dist/chunk-D2GID3YK.js.map +0 -1
  297. package/dist/chunk-FDUA6OGN.js.map +0 -1
  298. package/dist/chunk-HK3AMH3Q.cjs.map +0 -1
  299. package/dist/chunk-JHZW3Y62.js.map +0 -1
  300. package/dist/chunk-JR4QIU54.cjs.map +0 -1
  301. package/dist/chunk-KLLRTTC5.js.map +0 -1
  302. package/dist/chunk-MUUB35XB.js.map +0 -1
  303. package/dist/chunk-P2VTQ5AR.cjs.map +0 -1
  304. package/dist/chunk-RDGRKYQ5.cjs.map +0 -1
  305. package/dist/chunk-RVGTI4F6.js.map +0 -1
  306. package/dist/chunk-VA3WQ5KJ.cjs.map +0 -1
  307. package/dist/chunk-XMCIXHGH.js.map +0 -1
  308. package/dist/chunk-Y6YSJPVC.js.map +0 -1
  309. package/dist/chunk-ZJ5KAZLW.js.map +0 -1
  310. package/dist/chunk-ZONEAWPR.cjs.map +0 -1
  311. package/dist/chunk-ZPZAZQW4.cjs.map +0 -1
@@ -177,6 +177,7 @@ var TranscriptView = React__namespace.forwardRef(
177
177
  "button",
178
178
  {
179
179
  type: "button",
180
+ "data-slot": "transcript-row",
180
181
  "data-transcript-index": index,
181
182
  "aria-current": isActive ? "true" : void 0,
182
183
  className: `hover:bg-muted focus-visible:ring-ring flex w-full cursor-pointer gap-3 rounded px-2 py-1 text-start text-sm transition-colors focus-visible:ring-2 focus-visible:outline-none ${isActive ? "bg-primary-500/20" : ""}`,
@@ -192,29 +193,45 @@ var TranscriptView = React__namespace.forwardRef(
192
193
  }
193
194
  ) }, index);
194
195
  };
195
- return /* @__PURE__ */ jsxRuntime.jsxs("div", { ref, className: transcriptViewVariants({ variant, className }), children: [
196
- actions && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "border-border mb-2 flex items-center justify-end gap-2 border-b pb-2", children: actions }),
197
- /* @__PURE__ */ jsxRuntime.jsx(
198
- "div",
199
- {
200
- ref: contentRef,
201
- "aria-label": ariaLabel,
202
- onMouseEnter: () => {
203
- isHoveringRef.current = true;
204
- },
205
- onMouseLeave: () => {
206
- isHoveringRef.current = false;
207
- },
208
- ...resolvedGranularity === "segment" ? { role: "list", className: "space-y-2" } : { className: "text-sm leading-relaxed" },
209
- children: resolvedGranularity === "segment" ? segmentRows.map(renderSegmentRow) : transcript.words.map(renderWord)
210
- }
211
- )
212
- ] });
196
+ return /* @__PURE__ */ jsxRuntime.jsxs(
197
+ "div",
198
+ {
199
+ ref,
200
+ "data-slot": "transcript-view",
201
+ className: transcriptViewVariants({ variant, className }),
202
+ children: [
203
+ actions && /* @__PURE__ */ jsxRuntime.jsx(
204
+ "div",
205
+ {
206
+ "data-slot": "transcript-actions",
207
+ className: "border-border mb-2 flex items-center justify-end gap-2 border-b pb-2",
208
+ children: actions
209
+ }
210
+ ),
211
+ /* @__PURE__ */ jsxRuntime.jsx(
212
+ "div",
213
+ {
214
+ ref: contentRef,
215
+ "data-slot": "transcript-content",
216
+ "aria-label": ariaLabel,
217
+ onMouseEnter: () => {
218
+ isHoveringRef.current = true;
219
+ },
220
+ onMouseLeave: () => {
221
+ isHoveringRef.current = false;
222
+ },
223
+ ...resolvedGranularity === "segment" ? { role: "list", className: "space-y-2" } : { className: "text-sm leading-relaxed" },
224
+ children: resolvedGranularity === "segment" ? segmentRows.map(renderSegmentRow) : transcript.words.map(renderWord)
225
+ }
226
+ )
227
+ ]
228
+ }
229
+ );
213
230
  }
214
231
  );
215
232
  TranscriptView.displayName = "TranscriptView";
216
233
 
217
234
  exports.TranscriptView = TranscriptView;
218
235
  exports.formatTimestampMs = formatTimestampMs;
219
- //# sourceMappingURL=chunk-VA3WQ5KJ.cjs.map
220
- //# sourceMappingURL=chunk-VA3WQ5KJ.cjs.map
236
+ //# sourceMappingURL=chunk-FYAKUU2A.cjs.map
237
+ //# sourceMappingURL=chunk-FYAKUU2A.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/components/TranscriptView/TranscriptView.tsx"],"names":["cva","React","jsx","jsxs"],"mappings":"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","file":"chunk-FYAKUU2A.cjs","sourcesContent":["import * as React from 'react';\nimport { cva, type VariantProps } from 'class-variance-authority';\nimport type {\n Transcript,\n TranscriptSegment,\n TranscriptWord,\n} from './transcript';\n\n// ============================================================================\n// Types & Interfaces\n// ============================================================================\n\nexport type TranscriptGranularity = 'word' | 'segment';\n\nexport interface TranscriptViewProps extends VariantProps<\n typeof transcriptViewVariants\n> {\n /** The transcript to render */\n transcript: Transcript;\n /**\n * Rendering granularity. Defaults to 'segment' when the transcript has\n * segments, otherwise 'word'.\n */\n granularity?: TranscriptGranularity;\n /** Controlled playback position (ms); the matching word/segment is highlighted */\n currentTimeMs?: number;\n /** Called with the start time (ms) of a clicked word/segment; the host performs the seek/play */\n onSeek?: (timeMs: number) => void;\n /** Auto-scroll the active word/segment into view (default true) */\n followPlayback?: boolean;\n /**\n * Maps Speaker.id to a display label (e.g. Clinician/Patient). Falls back to\n * Speaker.name from transcript.speakers, then the raw id.\n */\n speakerLabels?: Record<string, string>;\n /** Segment mode: merge consecutive same-speaker segments into one row (default false) */\n mergeSameSpeaker?: boolean;\n /** Segment mode: show mm:ss timestamps (default true) */\n showTimestamps?: boolean;\n /** Rendered in a header row (host supplies copy/re-transcribe/remove buttons) */\n actions?: React.ReactNode;\n /** Additional class name */\n className?: string;\n /** Accessible label for the transcript container (default 'Transcript') */\n 'aria-label'?: string;\n}\n\n// ============================================================================\n// Variants\n// ============================================================================\n\nconst transcriptViewVariants = cva('flex flex-col text-foreground', {\n variants: {\n variant: {\n plain: '',\n card: 'rounded-xl border border-border bg-card text-card-foreground p-3',\n },\n },\n defaultVariants: {\n variant: 'plain',\n },\n});\n\n// ============================================================================\n// Helpers\n// ============================================================================\n\n/** Format milliseconds as m:ss (osheet timestamp style) */\nexport function formatTimestampMs(ms: number): string {\n const totalSeconds = Math.floor(ms / 1000);\n const minutes = Math.floor(totalSeconds / 60);\n const seconds = totalSeconds % 60;\n return `${minutes}:${String(seconds).padStart(2, '0')}`;\n}\n\n/** Resolve a speaker id to its display label */\nfunction resolveSpeakerLabel(\n speakerId: string | undefined,\n speakerLabels: Record<string, string> | undefined,\n transcript: Transcript\n): string | undefined {\n if (!speakerId) return undefined;\n return (\n speakerLabels?.[speakerId] ??\n transcript.speakers?.find((s) => s.id === speakerId)?.name ??\n speakerId\n );\n}\n\n/** A display row in segment mode (possibly the merge of several source segments) */\ninterface SegmentRow {\n text: string;\n startMs: number;\n endMs: number;\n speakerId?: string;\n}\n\n/**\n * Build segment display rows, optionally merging consecutive same-speaker\n * segments (osheet formatTranscriptText behavior). Empty segments are skipped.\n */\nfunction buildSegmentRows(\n segments: TranscriptSegment[],\n merge: boolean\n): SegmentRow[] {\n const rows: SegmentRow[] = [];\n for (const segment of segments) {\n const text = segment.text.trim();\n if (!text) continue;\n const prev = rows[rows.length - 1];\n if (merge && prev && prev.speakerId === segment.speakerId) {\n prev.text += ' ' + text;\n prev.endMs = segment.endMs;\n } else {\n rows.push({\n text,\n startMs: segment.startMs,\n endMs: segment.endMs,\n speakerId: segment.speakerId,\n });\n }\n }\n return rows;\n}\n\n/** Index of the item whose [startMs, endMs) range contains timeMs, or -1 */\nfunction findActiveIndex(\n items: ReadonlyArray<{ startMs: number; endMs: number }>,\n timeMs: number | undefined\n): number {\n if (timeMs === undefined) return -1;\n return items.findIndex(\n (item) => timeMs >= item.startMs && timeMs < item.endMs\n );\n}\n\n/** Run onActivate for click and Enter/Space keyboard activation */\nfunction activationProps(onActivate: () => void) {\n return {\n onClick: onActivate,\n onKeyDown: (e: React.KeyboardEvent) => {\n if (e.key === 'Enter' || e.key === ' ') {\n e.preventDefault();\n onActivate();\n }\n },\n };\n}\n\n// ============================================================================\n// Component\n// ============================================================================\n\n/**\n * Read-only transcript viewer with word-level and segment-level (diarized)\n * rendering modes.\n *\n * Controlled and persistence-agnostic: the host owns playback and passes the\n * position via `currentTimeMs`; clicking a word/segment reports the target\n * time through `onSeek`. Segment mode matches the osheet artifact-viewer row\n * UX (timestamp | speaker | text, click to seek + play). Editing lives in\n * MediaEditor, not here.\n */\nexport const TranscriptView = React.forwardRef<\n HTMLDivElement,\n TranscriptViewProps\n>(\n (\n {\n transcript,\n granularity,\n currentTimeMs,\n onSeek,\n followPlayback = true,\n speakerLabels,\n mergeSameSpeaker = false,\n showTimestamps = true,\n actions,\n variant,\n className,\n 'aria-label': ariaLabel = 'Transcript',\n },\n ref\n ) => {\n const contentRef = React.useRef<HTMLDivElement>(null);\n const isHoveringRef = React.useRef(false);\n\n const resolvedGranularity: TranscriptGranularity =\n granularity ??\n (transcript.segments && transcript.segments.length > 0\n ? 'segment'\n : 'word');\n\n const segmentRows = React.useMemo(\n () =>\n resolvedGranularity === 'segment'\n ? buildSegmentRows(transcript.segments ?? [], mergeSameSpeaker)\n : [],\n [resolvedGranularity, transcript.segments, mergeSameSpeaker]\n );\n\n const activeIndex =\n resolvedGranularity === 'segment'\n ? findActiveIndex(segmentRows, currentTimeMs)\n : findActiveIndex(transcript.words, currentTimeMs);\n\n // Auto-scroll the active item into view, unless the user is hovering\n React.useEffect(() => {\n if (!followPlayback || activeIndex < 0 || isHoveringRef.current) return;\n const el = contentRef.current?.querySelector(\n `[data-transcript-index=\"${activeIndex}\"]`\n );\n el?.scrollIntoView({ block: 'nearest', behavior: 'smooth' });\n }, [followPlayback, activeIndex]);\n\n const seekTo = (timeMs: number) => onSeek?.(timeMs);\n\n // ------------------------------------------------------------------\n // Word mode rendering\n // ------------------------------------------------------------------\n const renderWord = (word: TranscriptWord, index: number) => {\n const isActive = index === activeIndex;\n const wordType = word.wordType ?? 'word';\n const durationSec = ((word.endMs - word.startMs) / 1000).toFixed(1);\n\n if (wordType === 'silence-newline') {\n // Longer pause: force a line break (block element inside inline flow)\n return (\n <span\n key={index}\n data-transcript-index={index}\n role=\"button\"\n tabIndex={0}\n aria-current={isActive ? 'true' : undefined}\n aria-label={`Silence, ${durationSec} seconds`}\n className={`hover:bg-muted focus-visible:ring-ring block h-3 cursor-pointer rounded transition-colors focus-visible:ring-2 focus-visible:outline-none ${\n isActive ? 'bg-primary-500/20' : ''\n }`}\n {...activationProps(() => seekTo(word.startMs))}\n />\n );\n }\n\n if (wordType === 'silence') {\n // Short gap: subtle interpunct\n return (\n <span\n key={index}\n data-transcript-index={index}\n role=\"button\"\n tabIndex={0}\n aria-current={isActive ? 'true' : undefined}\n aria-label={`Silence, ${durationSec} seconds`}\n className={`text-muted-foreground/60 hover:bg-muted focus-visible:ring-ring cursor-pointer rounded px-0.5 transition-colors focus-visible:ring-2 focus-visible:outline-none ${\n isActive ? 'bg-primary-500/20' : ''\n }`}\n {...activationProps(() => seekTo(word.startMs))}\n >\n {'\\u00B7 '}\n </span>\n );\n }\n\n return (\n <span\n key={index}\n data-transcript-index={index}\n role=\"button\"\n tabIndex={0}\n aria-current={isActive ? 'true' : undefined}\n className={`hover:bg-muted focus-visible:ring-ring cursor-pointer rounded px-0.5 transition-colors focus-visible:ring-2 focus-visible:outline-none ${\n isActive ? 'bg-primary-500/20 text-foreground' : ''\n }`}\n {...activationProps(() => seekTo(word.startMs))}\n >\n {word.text}{' '}\n </span>\n );\n };\n\n // ------------------------------------------------------------------\n // Segment mode rendering (osheet artifact-viewer row parity)\n // ------------------------------------------------------------------\n const renderSegmentRow = (row: SegmentRow, index: number) => {\n const isActive = index === activeIndex;\n const speaker = resolveSpeakerLabel(\n row.speakerId,\n speakerLabels,\n transcript\n );\n\n return (\n <div key={index} role=\"listitem\">\n <button\n type=\"button\"\n data-slot=\"transcript-row\"\n data-transcript-index={index}\n aria-current={isActive ? 'true' : undefined}\n className={`hover:bg-muted focus-visible:ring-ring flex w-full cursor-pointer gap-3 rounded px-2 py-1 text-start text-sm transition-colors focus-visible:ring-2 focus-visible:outline-none ${\n isActive ? 'bg-primary-500/20' : ''\n }`}\n onClick={() => seekTo(row.startMs)}\n >\n {showTimestamps && (\n <span className=\"text-muted-foreground w-12 shrink-0 font-mono\">\n {formatTimestampMs(row.startMs)}\n </span>\n )}\n {speaker && (\n <span className=\"text-primary-900 w-24 shrink-0 font-semibold\">\n {speaker}:\n </span>\n )}\n <span className=\"text-foreground\">{row.text}</span>\n </button>\n </div>\n );\n };\n\n return (\n <div\n ref={ref}\n data-slot=\"transcript-view\"\n className={transcriptViewVariants({ variant, className })}\n >\n {actions && (\n <div\n data-slot=\"transcript-actions\"\n className=\"border-border mb-2 flex items-center justify-end gap-2 border-b pb-2\"\n >\n {actions}\n </div>\n )}\n <div\n ref={contentRef}\n data-slot=\"transcript-content\"\n aria-label={ariaLabel}\n onMouseEnter={() => {\n isHoveringRef.current = true;\n }}\n onMouseLeave={() => {\n isHoveringRef.current = false;\n }}\n {...(resolvedGranularity === 'segment'\n ? { role: 'list', className: 'space-y-2' }\n : { className: 'text-sm leading-relaxed' })}\n >\n {resolvedGranularity === 'segment'\n ? segmentRows.map(renderSegmentRow)\n : transcript.words.map(renderWord)}\n </div>\n </div>\n );\n }\n);\n\nTranscriptView.displayName = 'TranscriptView';\n"]}
@@ -1,8 +1,8 @@
1
1
  'use strict';
2
2
 
3
+ var chunkS5RVSXDV_cjs = require('./chunk-S5RVSXDV.cjs');
3
4
  var chunkFHY3K6PL_cjs = require('./chunk-FHY3K6PL.cjs');
4
5
  var chunkAOHJILLU_cjs = require('./chunk-AOHJILLU.cjs');
5
- var chunkS5RVSXDV_cjs = require('./chunk-S5RVSXDV.cjs');
6
6
  var React = require('react');
7
7
  var reactDom = require('react-dom');
8
8
  var lucideReact = require('lucide-react');
@@ -270,7 +270,13 @@ function GlossaryTooltip({
270
270
  className: "text-muted-foreground hover:text-foreground inline-flex shrink-0 items-center gap-0.5 text-[11px] font-medium",
271
271
  children: [
272
272
  "Full definition",
273
- /* @__PURE__ */ jsxRuntime.jsx(lucideReact.ArrowRight, { "aria-hidden": "true", className: "h-3 w-3" })
273
+ /* @__PURE__ */ jsxRuntime.jsx(
274
+ lucideReact.ArrowRight,
275
+ {
276
+ "aria-hidden": "true",
277
+ className: "h-3 w-3 rtl:-scale-x-100"
278
+ }
279
+ )
274
280
  ]
275
281
  }
276
282
  )
@@ -287,5 +293,5 @@ function GlossaryTooltip({
287
293
  }
288
294
 
289
295
  exports.GlossaryTooltip = GlossaryTooltip;
290
- //# sourceMappingURL=chunk-JR4QIU54.cjs.map
291
- //# sourceMappingURL=chunk-JR4QIU54.cjs.map
296
+ //# sourceMappingURL=chunk-H4AVMUOC.cjs.map
297
+ //# sourceMappingURL=chunk-H4AVMUOC.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/components/GlossaryTooltip/GlossaryTooltip.tsx"],"names":["React","useAnchoredPosition","useEscapeKey","cn","jsxs","jsx","createPortal","X","Diamond","ArrowRight"],"mappings":"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","file":"chunk-H4AVMUOC.cjs","sourcesContent":["'use client';\n\nimport * as React from 'react';\nimport { createPortal } from 'react-dom';\nimport { ArrowRight, Diamond, X } from 'lucide-react';\nimport { cn } from '../../utils/cn';\nimport { useAnchoredPosition } from '../../hooks/useAnchoredPosition';\nimport { useEscapeKey } from '../../hooks/useEscapeKey';\n\n// =============================================================================\n// Types\n// =============================================================================\n\n/** Authoritative source link shown in the card footer. */\nexport interface GlossarySource {\n label: string;\n url: string;\n}\n\n/** Sibling term shown as a lateral \"hop\" chip. */\nexport interface GlossaryRelatedTerm {\n term: string;\n href?: string;\n}\n\nexport interface GlossaryTooltipProps {\n /** Visible, in-flow trigger text (may be a plural or abbreviation match). */\n children: React.ReactNode;\n /** Canonical term name, shown as the card heading. */\n term: string;\n definition: string;\n /** Human-readable category label, shown as a badge in the header. */\n category?: string;\n /** Optional single key fact, shown with a diamond marker. */\n keyFact?: string;\n /** Optional authoritative source link, shown in the footer. */\n source?: GlossarySource;\n /** Optional sibling terms, shown as chips. */\n related?: GlossaryRelatedTerm[];\n /**\n * Full glossary page for the term. When set, the trigger is a real link —\n * desktop clicks navigate while hover previews; touch taps pin the card.\n */\n href?: string;\n /** Truncation limit for the in-card definition (default 190 chars). */\n maxDefinitionLength?: number;\n /** Dashed underline marking the term as hoverable (default true). */\n underline?: boolean;\n className?: string;\n}\n\nconst HIDE_GRACE_MS = 180;\n\n// =============================================================================\n// GlossaryTooltip\n// =============================================================================\n\n/**\n * A rich \"what does this term mean?\" hover card: category badge, canonical\n * term, truncated definition, optional key fact, source link, and related\n * term chips. The provenance sibling is `SourceTip` (\"what backs this\n * claim?\") — the two share the same interaction grammar.\n *\n * Trigger and card are phrasing content (`span`/`a`/`button` only), so it is\n * valid inside `<p>` prose. The card portals to `body` with fixed\n * positioning, flipping and clamping to stay in the viewport. On touch, a\n * tap pins the card instead of navigating; Escape or an outside tap closes.\n *\n * @example\n * ```tsx\n * <GlossaryTooltip\n * term=\"OSHA recordable\"\n * definition=\"A work-related injury or illness that meets OSHA reporting criteria…\"\n * category=\"Compliance\"\n * href=\"/glossary/osha-recordable\"\n * >\n * OSHA recordables\n * </GlossaryTooltip>\n * ```\n */\nexport function GlossaryTooltip({\n children,\n term,\n definition,\n category,\n keyFact,\n source,\n related,\n href,\n maxDefinitionLength = 190,\n underline = true,\n className,\n}: GlossaryTooltipProps) {\n const [open, setOpen] = React.useState(false);\n const [pinned, setPinned] = React.useState(false);\n const timer = React.useRef<ReturnType<typeof setTimeout> | null>(null);\n // True while close() restores focus to the trigger, so the trigger's\n // focus-show doesn't immediately reopen a card the user just dismissed.\n const suppressFocusShow = React.useRef(false);\n\n const { anchorRef, floatingRef, style } = useAnchoredPosition<\n HTMLSpanElement,\n HTMLSpanElement\n >({\n open,\n placement: 'top',\n offset: 10,\n viewportPadding: 8,\n allowFlip: true,\n });\n\n const clearHideTimer = () => {\n if (timer.current) {\n clearTimeout(timer.current);\n timer.current = null;\n }\n };\n\n const show = React.useCallback(() => {\n clearHideTimer();\n setOpen(true);\n }, []);\n\n const scheduleHide = React.useCallback(() => {\n if (pinned) return;\n clearHideTimer();\n timer.current = setTimeout(() => setOpen(false), HIDE_GRACE_MS);\n }, [pinned]);\n\n const close = React.useCallback(() => {\n clearHideTimer();\n setPinned(false);\n setOpen(false);\n // Return focus to the trigger if it was inside the card.\n if (floatingRef.current?.contains(document.activeElement)) {\n suppressFocusShow.current = true;\n (anchorRef.current?.querySelector('a,button') as HTMLElement)?.focus();\n }\n }, [anchorRef, floatingRef]);\n\n React.useEffect(() => () => clearHideTimer(), []);\n\n // A pinned card is a non-modal dialog: move focus into it so its links\n // and close button are reachable by keyboard.\n React.useEffect(() => {\n if (pinned) floatingRef.current?.focus();\n }, [pinned, floatingRef]);\n\n useEscapeKey(close, open);\n\n // Pinned cards close on an outside tap; hover cards close on their own.\n React.useEffect(() => {\n if (!open || !pinned) return;\n const onPointer = (e: Event) => {\n const t = e.target as Node;\n if (anchorRef.current?.contains(t) || floatingRef.current?.contains(t))\n return;\n close();\n };\n document.addEventListener('mousedown', onPointer);\n document.addEventListener('touchstart', onPointer);\n return () => {\n document.removeEventListener('mousedown', onPointer);\n document.removeEventListener('touchstart', onPointer);\n };\n }, [open, pinned, close, anchorRef, floatingRef]);\n\n const togglePin = React.useCallback(() => {\n if (pinned) close();\n else {\n setPinned(true);\n show();\n }\n }, [pinned, close, show]);\n\n // Linked terms: desktop clicks navigate, coarse pointers pin instead.\n // Unlinked (button) terms: any click toggles the pin — hover previews,\n // click holds the card open.\n const onTriggerClick = (e: React.MouseEvent) => {\n const coarse =\n typeof window !== 'undefined' &&\n window.matchMedia('(hover: none)').matches;\n if (href) {\n if (!coarse) return;\n e.preventDefault();\n }\n togglePin();\n };\n\n const onTriggerKeyDown = (e: React.KeyboardEvent) => {\n if (href) return; // links keep native Enter navigation\n if (e.key === 'Enter' || e.key === ' ') {\n e.preventDefault();\n togglePin();\n }\n };\n\n // Focus lives on the dialog container once pinned, so Enter/Space there\n // (not on a link or the close button inside) must also unpin.\n const onDialogKeyDown = (e: React.KeyboardEvent<HTMLSpanElement>) => {\n if (e.target !== e.currentTarget) return;\n if (e.key === 'Enter' || e.key === ' ') {\n e.preventDefault();\n close();\n }\n };\n\n const onTriggerFocus = () => {\n if (suppressFocusShow.current) {\n suppressFocusShow.current = false;\n return;\n }\n show();\n };\n\n const onBlurCapture = (e: React.FocusEvent<HTMLSpanElement>) => {\n const next = e.relatedTarget as Node | null;\n if (\n next &&\n (anchorRef.current?.contains(next) || floatingRef.current?.contains(next))\n )\n return;\n scheduleHide();\n };\n\n const limit = Math.max(1, maxDefinitionLength);\n const short =\n definition.length > limit\n ? `${definition.slice(0, limit - 1).trimEnd()}…`\n : definition;\n\n const triggerClasses = cn(\n 'cursor-help',\n underline &&\n 'decoration-primary-400/70 underline decoration-dashed underline-offset-4',\n className\n );\n\n const triggerProps = {\n onClick: onTriggerClick,\n className: cn(\n triggerClasses,\n href && 'text-primary-800 dark:text-primary-400 font-medium'\n ),\n };\n\n return (\n <span\n ref={anchorRef}\n className=\"relative inline\"\n onMouseEnter={show}\n onMouseLeave={scheduleHide}\n onFocus={onTriggerFocus}\n onBlur={onBlurCapture}\n >\n {href ? (\n <a\n href={href}\n aria-expanded={open}\n aria-haspopup=\"dialog\"\n {...triggerProps}\n >\n {children}\n </a>\n ) : (\n <button\n type=\"button\"\n aria-expanded={open}\n aria-haspopup=\"dialog\"\n aria-label={`${term} — show definition`}\n onKeyDown={onTriggerKeyDown}\n {...triggerProps}\n className={cn(\n 'inline appearance-none border-0 bg-transparent p-0 text-inherit [font:inherit]',\n triggerProps.className\n )}\n >\n {children}\n </button>\n )}\n {open &&\n createPortal(\n /* eslint-disable-next-line jsx-a11y/no-noninteractive-element-interactions -- keyboard dismissal on a focused non-modal dialog container is the WAI-ARIA pattern; links inside keep their own semantics */\n <span\n ref={floatingRef}\n role=\"dialog\"\n aria-label={term}\n tabIndex={-1}\n onMouseEnter={show}\n onMouseLeave={scheduleHide}\n onBlurCapture={onBlurCapture}\n onKeyDown={onDialogKeyDown}\n className=\"focus-visible:ring-ring z-50 block w-80 rounded-lg outline-none focus-visible:ring-2\"\n style={style}\n >\n <span className=\"border-border bg-card block overflow-hidden rounded-lg border text-start font-normal tracking-normal normal-case shadow-xl ring-1 ring-black/5 dark:ring-white/10\">\n <span className=\"from-primary-700 to-primary-600 block bg-gradient-to-br px-3.5 py-2.5\">\n <span className=\"flex items-start justify-between gap-2\">\n <span className=\"block min-w-0\">\n {category && (\n <span className=\"mb-1 inline-flex rounded-full bg-white/15 px-2 py-0.5 text-[10px] font-bold tracking-wide text-white uppercase\">\n {category}\n </span>\n )}\n <span className=\"block text-sm leading-snug font-semibold text-white\">\n {term}\n </span>\n </span>\n {pinned && (\n <button\n type=\"button\"\n onClick={close}\n aria-label=\"Close definition\"\n className=\"shrink-0 rounded p-0.5 text-white/70 hover:bg-white/10 hover:text-white\"\n >\n <X aria-hidden=\"true\" className=\"h-3.5 w-3.5\" />\n </button>\n )}\n </span>\n </span>\n\n <span className=\"block px-3.5 py-2.5\">\n <span className=\"text-muted-foreground block text-[13px] leading-relaxed\">\n {short}\n </span>\n {keyFact && (\n <span className=\"mt-2 flex items-start gap-1.5\">\n <Diamond\n aria-hidden=\"true\"\n className=\"text-primary-500 mt-0.5 h-3 w-3 shrink-0\"\n />\n <span className=\"text-foreground min-w-0 text-xs leading-relaxed font-medium\">\n {keyFact}\n </span>\n </span>\n )}\n </span>\n\n {(source || (related && related.length > 0) || href) && (\n <span className=\"border-border bg-muted/50 block border-t px-3.5 py-2\">\n {related && related.length > 0 && (\n <span className=\"mb-1.5 flex flex-wrap gap-1\">\n {related.map((r) =>\n r.href ? (\n <a\n key={r.term}\n href={r.href}\n className=\"border-border bg-card text-foreground hover:border-primary-400 hover:text-primary-800 dark:hover:text-primary-400 rounded-full border px-2 py-0.5 text-[11px] font-medium\"\n >\n {r.term}\n </a>\n ) : (\n <span\n key={r.term}\n className=\"border-border bg-card text-muted-foreground rounded-full border px-2 py-0.5 text-[11px] font-medium\"\n >\n {r.term}\n </span>\n )\n )}\n </span>\n )}\n <span className=\"flex items-center justify-between gap-2\">\n {source ? (\n <a\n href={source.url}\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n className=\"text-primary-800 hover:text-primary-700 dark:text-primary-400 dark:hover:text-primary-300 min-w-0 truncate text-[11px] font-semibold\"\n >\n {source.label}\n </a>\n ) : (\n <span />\n )}\n {href && (\n <a\n href={href}\n className=\"text-muted-foreground hover:text-foreground inline-flex shrink-0 items-center gap-0.5 text-[11px] font-medium\"\n >\n Full definition\n <ArrowRight\n aria-hidden=\"true\"\n className=\"h-3 w-3 rtl:-scale-x-100\"\n />\n </a>\n )}\n </span>\n </span>\n )}\n </span>\n </span>,\n document.body\n )}\n </span>\n );\n}\n"]}
@@ -43,7 +43,7 @@ function Breadcrumb({
43
43
  ...lastItems
44
44
  ];
45
45
  }, [items, maxItems]);
46
- const defaultSeparator = /* @__PURE__ */ jsxRuntime.jsx(ChevronRightIcon, { className: "text-muted-foreground h-4 w-4 shrink-0" });
46
+ const defaultSeparator = /* @__PURE__ */ jsxRuntime.jsx(ChevronRightIcon, { className: "text-muted-foreground h-4 w-4 shrink-0 rtl:-scale-x-100" });
47
47
  return /* @__PURE__ */ jsxRuntime.jsx("nav", { "data-slot": "breadcrumb", "aria-label": "Breadcrumb", className, children: /* @__PURE__ */ jsxRuntime.jsx(
48
48
  "ol",
49
49
  {
@@ -133,5 +133,5 @@ function BreadcrumbSlash({ className }) {
133
133
 
134
134
  exports.Breadcrumb = Breadcrumb;
135
135
  exports.BreadcrumbSlash = BreadcrumbSlash;
136
- //# sourceMappingURL=chunk-I2ECTLON.cjs.map
137
- //# sourceMappingURL=chunk-I2ECTLON.cjs.map
136
+ //# sourceMappingURL=chunk-HXSA6QC5.cjs.map
137
+ //# sourceMappingURL=chunk-HXSA6QC5.cjs.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/components/Breadcrumb/Breadcrumb.tsx"],"names":["React","jsx","jsxs","cn"],"mappings":"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","file":"chunk-I2ECTLON.cjs","sourcesContent":["import * as React from 'react';\nimport { cn } from '../../utils/cn';\n\n// ============================================================================\n// Breadcrumb Types\n// ============================================================================\n\nexport interface BreadcrumbItem {\n /** Label for the breadcrumb item */\n label: string;\n /** URL to navigate to (optional for the last item) */\n href?: string;\n /** Icon to display before the label */\n icon?: React.ReactNode;\n}\n\n// ============================================================================\n// Breadcrumb Component\n// ============================================================================\n\nexport interface BreadcrumbProps {\n /** Array of breadcrumb items */\n items: BreadcrumbItem[];\n /** Custom separator between items */\n separator?: React.ReactNode;\n /** Maximum items to display (collapses middle items) */\n maxItems?: number;\n /** Custom renderer for links */\n renderLink?: (item: BreadcrumbItem, index: number) => React.ReactNode;\n /** Additional class name */\n className?: string;\n}\n\n/**\n * A navigation breadcrumb component.\n *\n * @example\n * ```tsx\n * <Breadcrumb\n * items={[\n * { label: 'Home', href: '/' },\n * { label: 'Products', href: '/products' },\n * { label: 'Category', href: '/products/category' },\n * { label: 'Current Item' },\n * ]}\n * />\n * ```\n */\nfunction Breadcrumb({\n items,\n separator,\n maxItems,\n renderLink,\n className,\n}: BreadcrumbProps) {\n // Collapse items if maxItems is specified\n const displayedItems = React.useMemo(() => {\n if (!maxItems || items.length <= maxItems) {\n return items;\n }\n\n // Show first item, ellipsis, and last (maxItems - 2) items\n const firstItem = items[0];\n const lastItems = items.slice(-(maxItems - 1));\n\n return [\n firstItem,\n { label: '...', isEllipsis: true } as BreadcrumbItem & {\n isEllipsis?: boolean;\n },\n ...lastItems,\n ];\n }, [items, maxItems]);\n\n const defaultSeparator = (\n <ChevronRightIcon className=\"text-muted-foreground h-4 w-4 shrink-0\" />\n );\n\n return (\n <nav data-slot=\"breadcrumb\" aria-label=\"Breadcrumb\" className={className}>\n <ol\n data-slot=\"breadcrumb-list\"\n className=\"flex flex-wrap items-center gap-1.5\"\n >\n {displayedItems.map((item, index) => {\n const isLast = index === displayedItems.length - 1;\n const isEllipsis = (item as BreadcrumbItem & { isEllipsis?: boolean })\n .isEllipsis;\n\n return (\n <li key={index} className=\"flex items-center gap-1.5\">\n {index > 0 && (\n <span data-slot=\"breadcrumb-separator\" aria-hidden=\"true\">\n {separator || defaultSeparator}\n </span>\n )}\n {isEllipsis ? (\n <span\n data-slot=\"breadcrumb-ellipsis\"\n className=\"text-muted-foreground text-sm\"\n >\n ...\n </span>\n ) : isLast || !item.href ? (\n <BreadcrumbPage item={item} />\n ) : renderLink ? (\n <span data-slot=\"breadcrumb-link\">\n {renderLink(item, index)}\n </span>\n ) : (\n <BreadcrumbLink item={item} />\n )}\n </li>\n );\n })}\n </ol>\n </nav>\n );\n}\n\nBreadcrumb.displayName = 'Breadcrumb';\n\n// ============================================================================\n// Breadcrumb Link (Internal)\n// ============================================================================\n\ninterface BreadcrumbLinkProps {\n item: BreadcrumbItem;\n}\n\nfunction BreadcrumbLink({ item }: BreadcrumbLinkProps) {\n return (\n <a\n href={item.href}\n data-slot=\"breadcrumb-link\"\n className={cn(\n 'inline-flex items-center gap-1.5',\n 'text-muted-foreground text-sm',\n 'hover:text-foreground transition-colors',\n 'focus-visible:ring-ring rounded focus-visible:ring-2 focus-visible:outline-none'\n )}\n >\n {item.icon}\n {item.label}\n </a>\n );\n}\n\n// ============================================================================\n// Breadcrumb Page (Current Page - Internal)\n// ============================================================================\n\ninterface BreadcrumbPageProps {\n item: BreadcrumbItem;\n}\n\nfunction BreadcrumbPage({ item }: BreadcrumbPageProps) {\n return (\n <span\n data-slot=\"breadcrumb-page\"\n className=\"text-foreground inline-flex items-center gap-1.5 text-sm font-medium\"\n aria-current=\"page\"\n >\n {item.icon}\n {item.label}\n </span>\n );\n}\n\n// ============================================================================\n// Chevron Icon\n// ============================================================================\n\nfunction ChevronRightIcon({ className }: { className?: string }) {\n return (\n <svg\n xmlns=\"http://www.w3.org/2000/svg\"\n width=\"24\"\n height=\"24\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"2\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n className={className}\n aria-hidden=\"true\"\n >\n <path d=\"m9 18 6-6-6-6\" />\n </svg>\n );\n}\n\n// ============================================================================\n// Slash Separator Component\n// ============================================================================\n\nfunction BreadcrumbSlash({ className }: { className?: string }) {\n return (\n <span\n className={cn('text-muted-foreground mx-1', className)}\n aria-hidden=\"true\"\n >\n /\n </span>\n );\n}\n\nexport { Breadcrumb, BreadcrumbSlash };\n"]}
1
+ {"version":3,"sources":["../src/components/Breadcrumb/Breadcrumb.tsx"],"names":["React","jsx","jsxs","cn"],"mappings":"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","file":"chunk-HXSA6QC5.cjs","sourcesContent":["import * as React from 'react';\nimport { cn } from '../../utils/cn';\n\n// ============================================================================\n// Breadcrumb Types\n// ============================================================================\n\nexport interface BreadcrumbItem {\n /** Label for the breadcrumb item */\n label: string;\n /** URL to navigate to (optional for the last item) */\n href?: string;\n /** Icon to display before the label */\n icon?: React.ReactNode;\n}\n\n// ============================================================================\n// Breadcrumb Component\n// ============================================================================\n\nexport interface BreadcrumbProps {\n /** Array of breadcrumb items */\n items: BreadcrumbItem[];\n /** Custom separator between items */\n separator?: React.ReactNode;\n /** Maximum items to display (collapses middle items) */\n maxItems?: number;\n /** Custom renderer for links */\n renderLink?: (item: BreadcrumbItem, index: number) => React.ReactNode;\n /** Additional class name */\n className?: string;\n}\n\n/**\n * A navigation breadcrumb component.\n *\n * @example\n * ```tsx\n * <Breadcrumb\n * items={[\n * { label: 'Home', href: '/' },\n * { label: 'Products', href: '/products' },\n * { label: 'Category', href: '/products/category' },\n * { label: 'Current Item' },\n * ]}\n * />\n * ```\n */\nfunction Breadcrumb({\n items,\n separator,\n maxItems,\n renderLink,\n className,\n}: BreadcrumbProps) {\n // Collapse items if maxItems is specified\n const displayedItems = React.useMemo(() => {\n if (!maxItems || items.length <= maxItems) {\n return items;\n }\n\n // Show first item, ellipsis, and last (maxItems - 2) items\n const firstItem = items[0];\n const lastItems = items.slice(-(maxItems - 1));\n\n return [\n firstItem,\n { label: '...', isEllipsis: true } as BreadcrumbItem & {\n isEllipsis?: boolean;\n },\n ...lastItems,\n ];\n }, [items, maxItems]);\n\n const defaultSeparator = (\n <ChevronRightIcon className=\"text-muted-foreground h-4 w-4 shrink-0 rtl:-scale-x-100\" />\n );\n\n return (\n <nav data-slot=\"breadcrumb\" aria-label=\"Breadcrumb\" className={className}>\n <ol\n data-slot=\"breadcrumb-list\"\n className=\"flex flex-wrap items-center gap-1.5\"\n >\n {displayedItems.map((item, index) => {\n const isLast = index === displayedItems.length - 1;\n const isEllipsis = (item as BreadcrumbItem & { isEllipsis?: boolean })\n .isEllipsis;\n\n return (\n <li key={index} className=\"flex items-center gap-1.5\">\n {index > 0 && (\n <span data-slot=\"breadcrumb-separator\" aria-hidden=\"true\">\n {separator || defaultSeparator}\n </span>\n )}\n {isEllipsis ? (\n <span\n data-slot=\"breadcrumb-ellipsis\"\n className=\"text-muted-foreground text-sm\"\n >\n ...\n </span>\n ) : isLast || !item.href ? (\n <BreadcrumbPage item={item} />\n ) : renderLink ? (\n <span data-slot=\"breadcrumb-link\">\n {renderLink(item, index)}\n </span>\n ) : (\n <BreadcrumbLink item={item} />\n )}\n </li>\n );\n })}\n </ol>\n </nav>\n );\n}\n\nBreadcrumb.displayName = 'Breadcrumb';\n\n// ============================================================================\n// Breadcrumb Link (Internal)\n// ============================================================================\n\ninterface BreadcrumbLinkProps {\n item: BreadcrumbItem;\n}\n\nfunction BreadcrumbLink({ item }: BreadcrumbLinkProps) {\n return (\n <a\n href={item.href}\n data-slot=\"breadcrumb-link\"\n className={cn(\n 'inline-flex items-center gap-1.5',\n 'text-muted-foreground text-sm',\n 'hover:text-foreground transition-colors',\n 'focus-visible:ring-ring rounded focus-visible:ring-2 focus-visible:outline-none'\n )}\n >\n {item.icon}\n {item.label}\n </a>\n );\n}\n\n// ============================================================================\n// Breadcrumb Page (Current Page - Internal)\n// ============================================================================\n\ninterface BreadcrumbPageProps {\n item: BreadcrumbItem;\n}\n\nfunction BreadcrumbPage({ item }: BreadcrumbPageProps) {\n return (\n <span\n data-slot=\"breadcrumb-page\"\n className=\"text-foreground inline-flex items-center gap-1.5 text-sm font-medium\"\n aria-current=\"page\"\n >\n {item.icon}\n {item.label}\n </span>\n );\n}\n\n// ============================================================================\n// Chevron Icon\n// ============================================================================\n\nfunction ChevronRightIcon({ className }: { className?: string }) {\n return (\n <svg\n xmlns=\"http://www.w3.org/2000/svg\"\n width=\"24\"\n height=\"24\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"2\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n className={className}\n aria-hidden=\"true\"\n >\n <path d=\"m9 18 6-6-6-6\" />\n </svg>\n );\n}\n\n// ============================================================================\n// Slash Separator Component\n// ============================================================================\n\nfunction BreadcrumbSlash({ className }: { className?: string }) {\n return (\n <span\n className={cn('text-muted-foreground mx-1', className)}\n aria-hidden=\"true\"\n >\n /\n </span>\n );\n}\n\nexport { Breadcrumb, BreadcrumbSlash };\n"]}
@@ -1,4 +1,4 @@
1
- import { Modal, ModalHeader, ModalTitle, ModalClose, ModalBody, ModalFooter } from './chunk-XMCIXHGH.js';
1
+ import { Modal, ModalHeader, ModalTitle, ModalClose, ModalBody, ModalFooter } from './chunk-Q7G56ZIO.js';
2
2
  import { cn } from './chunk-TQONQSJO.js';
3
3
  import * as React from 'react';
4
4
  import { Keyboard } from 'lucide-react';
@@ -101,5 +101,5 @@ function KeyboardShortcutsOverlay({
101
101
  }
102
102
 
103
103
  export { Kbd, KeyboardShortcutsOverlay };
104
- //# sourceMappingURL=chunk-X5ZPYYMS.js.map
105
- //# sourceMappingURL=chunk-X5ZPYYMS.js.map
104
+ //# sourceMappingURL=chunk-I3DQXUSC.js.map
105
+ //# sourceMappingURL=chunk-I3DQXUSC.js.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/components/KeyboardShortcutsOverlay/KeyboardShortcutsOverlay.tsx"],"names":["Kbd","Fragment"],"mappings":"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","file":"chunk-X5ZPYYMS.js","sourcesContent":["'use client';\n\nimport * as React from 'react';\nimport { Keyboard } from 'lucide-react';\nimport { cn } from '../../utils/cn';\nimport {\n Modal,\n ModalHeader,\n ModalTitle,\n ModalClose,\n ModalBody,\n ModalFooter,\n} from '../Modal';\n\n// =============================================================================\n// Kbd\n// =============================================================================\n\nexport type KbdProps = React.HTMLAttributes<HTMLElement>;\n\n/** A keyboard-key chip: `<Kbd>⌘K</Kbd>`. */\nexport const Kbd = React.forwardRef<HTMLElement, KbdProps>(function Kbd(\n { className, ...props },\n ref\n) {\n return (\n <kbd\n ref={ref}\n className={cn(\n 'border-border bg-muted text-foreground rounded border px-1.5 py-0.5 font-mono text-[11px]',\n className\n )}\n {...props}\n />\n );\n});\n\n// =============================================================================\n// KeyboardShortcutsOverlay\n// =============================================================================\n\nexport interface ShortcutDef {\n /** Key or alternatives — `\"j\"`, `[\"j\", \"↓\"]`, `\"⌘K\"`. */\n keys: string | string[];\n description: string;\n}\n\nexport interface ShortcutGroup {\n title: string;\n shortcuts: ShortcutDef[];\n}\n\nexport interface KeyboardShortcutsOverlayProps {\n open: boolean;\n onClose: () => void;\n /** Flat list of shortcuts, or use `groups` for sectioned help. */\n shortcuts?: ShortcutDef[];\n /** Sectioned shortcuts with group headings. */\n groups?: ShortcutGroup[];\n title?: string;\n /** Footer hint. Pass `null` to hide it. */\n hint?: React.ReactNode | null;\n /** Joins key alternatives (default \"or\"), overridable for i18n. */\n alternativesLabel?: string;\n}\n\nfunction Keys({\n keys,\n alternativesLabel,\n}: {\n keys: string | string[];\n alternativesLabel: string;\n}) {\n const list = Array.isArray(keys) ? keys : keys.split(' / ');\n return (\n <span className=\"flex shrink-0 items-center gap-1\">\n {list.map((k, i) => (\n <React.Fragment key={`${k}-${i}`}>\n <Kbd>{k}</Kbd>\n {i < list.length - 1 && (\n <span className=\"text-muted-foreground mx-0.5 text-xs\">\n {alternativesLabel}\n </span>\n )}\n </React.Fragment>\n ))}\n </span>\n );\n}\n\nfunction ShortcutList({\n shortcuts,\n alternativesLabel,\n}: {\n shortcuts: ShortcutDef[];\n alternativesLabel: string;\n}) {\n return (\n <ul className=\"flex list-none flex-col gap-2 p-0\">\n {shortcuts.map((s) => (\n <li\n key={`${s.description}-${String(s.keys)}`}\n className=\"text-foreground flex items-center justify-between gap-4 text-sm\"\n >\n <span className=\"min-w-0\">{s.description}</span>\n <Keys keys={s.keys} alternativesLabel={alternativesLabel} />\n </li>\n ))}\n </ul>\n );\n}\n\n/**\n * The `?` keyboard-shortcuts help dialog: a list of shortcut rows\n * (optionally grouped) with `Kbd` chips for each key. Pairs with the\n * `useKeyboardShortcut` hook, which handles the binding — this component\n * only renders the help.\n *\n * @example\n * ```tsx\n * const [open, setOpen] = useState(false);\n * useKeyboardShortcut('?', () => setOpen((v) => !v), {\n * modifiers: { shift: true },\n * });\n *\n * <KeyboardShortcutsOverlay\n * open={open}\n * onClose={() => setOpen(false)}\n * shortcuts={[\n * { keys: ['j', '↓'], description: 'Next record' },\n * { keys: '⌘K', description: 'Command palette' },\n * ]}\n * />\n * ```\n */\nexport function KeyboardShortcutsOverlay({\n open,\n onClose,\n shortcuts,\n groups,\n title = 'Keyboard shortcuts',\n hint,\n alternativesLabel = 'or',\n}: KeyboardShortcutsOverlayProps) {\n const defaultHint = (\n <>\n Press <Kbd>?</Kbd> anytime to toggle this help\n </>\n );\n const footer = hint === null ? null : (hint ?? defaultHint);\n\n return (\n <Modal\n open={open}\n onOpenChange={(o) => {\n if (!o) onClose();\n }}\n size=\"sm\"\n aria-label={title}\n >\n <ModalHeader>\n <ModalTitle className=\"flex items-center gap-2 text-sm\">\n <Keyboard aria-hidden=\"true\" className=\"text-primary-500 h-4 w-4\" />\n {title}\n </ModalTitle>\n <ModalClose />\n </ModalHeader>\n <ModalBody className=\"flex flex-col gap-4\">\n {shortcuts && (\n <ShortcutList\n shortcuts={shortcuts}\n alternativesLabel={alternativesLabel}\n />\n )}\n {groups?.map((group) => (\n <div key={group.title} className=\"flex flex-col gap-2\">\n <h3 className=\"text-muted-foreground text-xs font-semibold tracking-wide uppercase\">\n {group.title}\n </h3>\n <ShortcutList\n shortcuts={group.shortcuts}\n alternativesLabel={alternativesLabel}\n />\n </div>\n ))}\n </ModalBody>\n {footer && (\n <ModalFooter className=\"text-muted-foreground justify-center text-[11px]\">\n <span>{footer}</span>\n </ModalFooter>\n )}\n </Modal>\n );\n}\n"]}
1
+ {"version":3,"sources":["../src/components/KeyboardShortcutsOverlay/KeyboardShortcutsOverlay.tsx"],"names":["Kbd","Fragment"],"mappings":"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","file":"chunk-I3DQXUSC.js","sourcesContent":["'use client';\n\nimport * as React from 'react';\nimport { Keyboard } from 'lucide-react';\nimport { cn } from '../../utils/cn';\nimport {\n Modal,\n ModalHeader,\n ModalTitle,\n ModalClose,\n ModalBody,\n ModalFooter,\n} from '../Modal';\n\n// =============================================================================\n// Kbd\n// =============================================================================\n\nexport type KbdProps = React.HTMLAttributes<HTMLElement>;\n\n/** A keyboard-key chip: `<Kbd>⌘K</Kbd>`. */\nexport const Kbd = React.forwardRef<HTMLElement, KbdProps>(function Kbd(\n { className, ...props },\n ref\n) {\n return (\n <kbd\n ref={ref}\n className={cn(\n 'border-border bg-muted text-foreground rounded border px-1.5 py-0.5 font-mono text-[11px]',\n className\n )}\n {...props}\n />\n );\n});\n\n// =============================================================================\n// KeyboardShortcutsOverlay\n// =============================================================================\n\nexport interface ShortcutDef {\n /** Key or alternatives — `\"j\"`, `[\"j\", \"↓\"]`, `\"⌘K\"`. */\n keys: string | string[];\n description: string;\n}\n\nexport interface ShortcutGroup {\n title: string;\n shortcuts: ShortcutDef[];\n}\n\nexport interface KeyboardShortcutsOverlayProps {\n open: boolean;\n onClose: () => void;\n /** Flat list of shortcuts, or use `groups` for sectioned help. */\n shortcuts?: ShortcutDef[];\n /** Sectioned shortcuts with group headings. */\n groups?: ShortcutGroup[];\n title?: string;\n /** Footer hint. Pass `null` to hide it. */\n hint?: React.ReactNode | null;\n /** Joins key alternatives (default \"or\"), overridable for i18n. */\n alternativesLabel?: string;\n}\n\nfunction Keys({\n keys,\n alternativesLabel,\n}: {\n keys: string | string[];\n alternativesLabel: string;\n}) {\n const list = Array.isArray(keys) ? keys : keys.split(' / ');\n return (\n <span className=\"flex shrink-0 items-center gap-1\">\n {list.map((k, i) => (\n <React.Fragment key={`${k}-${i}`}>\n <Kbd>{k}</Kbd>\n {i < list.length - 1 && (\n <span className=\"text-muted-foreground mx-0.5 text-xs\">\n {alternativesLabel}\n </span>\n )}\n </React.Fragment>\n ))}\n </span>\n );\n}\n\nfunction ShortcutList({\n shortcuts,\n alternativesLabel,\n}: {\n shortcuts: ShortcutDef[];\n alternativesLabel: string;\n}) {\n return (\n <ul className=\"flex list-none flex-col gap-2 p-0\">\n {shortcuts.map((s) => (\n <li\n key={`${s.description}-${String(s.keys)}`}\n className=\"text-foreground flex items-center justify-between gap-4 text-sm\"\n >\n <span className=\"min-w-0\">{s.description}</span>\n <Keys keys={s.keys} alternativesLabel={alternativesLabel} />\n </li>\n ))}\n </ul>\n );\n}\n\n/**\n * The `?` keyboard-shortcuts help dialog: a list of shortcut rows\n * (optionally grouped) with `Kbd` chips for each key. Pairs with the\n * `useKeyboardShortcut` hook, which handles the binding — this component\n * only renders the help.\n *\n * @example\n * ```tsx\n * const [open, setOpen] = useState(false);\n * useKeyboardShortcut('?', () => setOpen((v) => !v), {\n * modifiers: { shift: true },\n * });\n *\n * <KeyboardShortcutsOverlay\n * open={open}\n * onClose={() => setOpen(false)}\n * shortcuts={[\n * { keys: ['j', '↓'], description: 'Next record' },\n * { keys: '⌘K', description: 'Command palette' },\n * ]}\n * />\n * ```\n */\nexport function KeyboardShortcutsOverlay({\n open,\n onClose,\n shortcuts,\n groups,\n title = 'Keyboard shortcuts',\n hint,\n alternativesLabel = 'or',\n}: KeyboardShortcutsOverlayProps) {\n const defaultHint = (\n <>\n Press <Kbd>?</Kbd> anytime to toggle this help\n </>\n );\n const footer = hint === null ? null : (hint ?? defaultHint);\n\n return (\n <Modal\n open={open}\n onOpenChange={(o) => {\n if (!o) onClose();\n }}\n size=\"sm\"\n aria-label={title}\n >\n <ModalHeader>\n <ModalTitle className=\"flex items-center gap-2 text-sm\">\n <Keyboard aria-hidden=\"true\" className=\"text-primary-500 h-4 w-4\" />\n {title}\n </ModalTitle>\n <ModalClose />\n </ModalHeader>\n <ModalBody className=\"flex flex-col gap-4\">\n {shortcuts && (\n <ShortcutList\n shortcuts={shortcuts}\n alternativesLabel={alternativesLabel}\n />\n )}\n {groups?.map((group) => (\n <div key={group.title} className=\"flex flex-col gap-2\">\n <h3 className=\"text-muted-foreground text-xs font-semibold tracking-wide uppercase\">\n {group.title}\n </h3>\n <ShortcutList\n shortcuts={group.shortcuts}\n alternativesLabel={alternativesLabel}\n />\n </div>\n ))}\n </ModalBody>\n {footer && (\n <ModalFooter className=\"text-muted-foreground justify-center text-[11px]\">\n <span>{footer}</span>\n </ModalFooter>\n )}\n </Modal>\n );\n}\n"]}
@@ -1,7 +1,7 @@
1
1
  'use strict';
2
2
 
3
- var chunkYIXTGWT4_cjs = require('./chunk-YIXTGWT4.cjs');
4
- var chunkRDGRKYQ5_cjs = require('./chunk-RDGRKYQ5.cjs');
3
+ var chunk6QKMMKRY_cjs = require('./chunk-6QKMMKRY.cjs');
4
+ var chunkIINZWUGK_cjs = require('./chunk-IINZWUGK.cjs');
5
5
  var lucideReact = require('lucide-react');
6
6
  var react = require('react');
7
7
  var jsxRuntime = require('react/jsx-runtime');
@@ -48,7 +48,7 @@ var HtmlPreviewBlock = ({
48
48
  const togglePreview = react.useCallback(() => setShowPreview((v) => !v), []);
49
49
  const headerActions = /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
50
50
  /* @__PURE__ */ jsxRuntime.jsxs(
51
- chunkRDGRKYQ5_cjs.Button,
51
+ chunkIINZWUGK_cjs.Button,
52
52
  {
53
53
  variant: "ghost",
54
54
  size: "sm",
@@ -61,7 +61,7 @@ var HtmlPreviewBlock = ({
61
61
  }
62
62
  ),
63
63
  showPreview && /* @__PURE__ */ jsxRuntime.jsx(
64
- chunkRDGRKYQ5_cjs.Button,
64
+ chunkIINZWUGK_cjs.Button,
65
65
  {
66
66
  variant: "ghost",
67
67
  size: "sm",
@@ -73,7 +73,7 @@ var HtmlPreviewBlock = ({
73
73
  )
74
74
  ] });
75
75
  return /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
76
- /* @__PURE__ */ jsxRuntime.jsx(chunkYIXTGWT4_cjs.FenceBlock, { code, language: "html", headerActions, children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: "relative", children: showPreview ? /* @__PURE__ */ jsxRuntime.jsx(
76
+ /* @__PURE__ */ jsxRuntime.jsx(chunk6QKMMKRY_cjs.FenceBlock, { code, language: "html", headerActions, children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: "relative", children: showPreview ? /* @__PURE__ */ jsxRuntime.jsx(
77
77
  "iframe",
78
78
  {
79
79
  ref: iframeRef,
@@ -106,7 +106,7 @@ var HtmlPreviewBlock = ({
106
106
  /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center justify-between border-b border-neutral-200 px-4 py-2 dark:border-neutral-700", children: [
107
107
  /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-sm font-medium", children: "HTML Preview" }),
108
108
  /* @__PURE__ */ jsxRuntime.jsx(
109
- chunkRDGRKYQ5_cjs.Button,
109
+ chunkIINZWUGK_cjs.Button,
110
110
  {
111
111
  variant: "ghost",
112
112
  size: "sm",
@@ -133,5 +133,5 @@ var HtmlPreviewBlock = ({
133
133
  };
134
134
 
135
135
  exports.HtmlPreviewBlock = HtmlPreviewBlock;
136
- //# sourceMappingURL=chunk-FN6VHMLM.cjs.map
137
- //# sourceMappingURL=chunk-FN6VHMLM.cjs.map
136
+ //# sourceMappingURL=chunk-IB54SKWB.cjs.map
137
+ //# sourceMappingURL=chunk-IB54SKWB.cjs.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/components/Markdown/HtmlPreviewBlock.tsx"],"names":["useState","useRef","useEffect","useCallback","jsxs","Fragment","Button","jsx","Code","Eye","Maximize2","FenceBlock"],"mappings":"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","file":"chunk-FN6VHMLM.cjs","sourcesContent":["/** Sandboxed iframe preview for HTML code blocks. */\nimport { Code, Eye, Maximize2 } from 'lucide-react';\nimport React, { useCallback, useEffect, useRef, useState } from 'react';\n\nimport { Button } from '../Button';\nimport { FenceBlock } from './FenceBlock';\n\ninterface HtmlPreviewBlockProps {\n code: string;\n id: string;\n}\n\nfunction isFullDocument(html: string): boolean {\n return /<!DOCTYPE|<html/i.test(html);\n}\n\nfunction wrapFragment(html: string): string {\n return `<!DOCTYPE html>\n<html>\n<head><meta charset=\"utf-8\"><style>body{margin:0;padding:8px;font-family:system-ui,sans-serif;font-size:14px}</style></head>\n<body>${html}</body>\n</html>`;\n}\n\nexport const HtmlPreviewBlock: React.FC<HtmlPreviewBlockProps> = ({\n code,\n id,\n}) => {\n const [showPreview, setShowPreview] = useState(false);\n const [expanded, setExpanded] = useState(false);\n const iframeRef = useRef<HTMLIFrameElement>(null);\n const [iframeHeight, setIframeHeight] = useState(200);\n\n const srcdoc = isFullDocument(code) ? code : wrapFragment(code);\n\n useEffect(() => {\n function handleMessage(event: globalThis.MessageEvent) {\n // Sandboxed srcDoc iframes report origin \"null\"; validate source to prevent spoofing.\n if (event.origin !== 'null' && event.origin !== window.location.origin)\n return;\n if (event.source !== iframeRef.current?.contentWindow) return;\n if (event.data?.type === 'HTML_PREVIEW_RESIZE' && event.data?.id === id) {\n setIframeHeight(Math.min(Math.max(event.data.height, 200), 4000));\n }\n }\n window.addEventListener('message', handleMessage);\n return () => window.removeEventListener('message', handleMessage);\n }, [id]);\n\n useEffect(() => {\n if (!expanded) return;\n function handleKey(e: KeyboardEvent) {\n if (e.key === 'Escape') setExpanded(false);\n }\n document.addEventListener('keydown', handleKey);\n return () => document.removeEventListener('keydown', handleKey);\n }, [expanded]);\n\n const togglePreview = useCallback(() => setShowPreview((v) => !v), []);\n\n const headerActions = (\n <>\n <Button\n variant=\"ghost\"\n size=\"sm\"\n onClick={togglePreview}\n className=\"h-7 gap-1 px-2 text-xs\"\n >\n {showPreview ? (\n <Code className=\"h-3 w-3\" />\n ) : (\n <Eye className=\"h-3 w-3\" />\n )}\n {showPreview ? 'Code' : 'Preview'}\n </Button>\n {showPreview && (\n <Button\n variant=\"ghost\"\n size=\"sm\"\n onClick={() => setExpanded(true)}\n className=\"h-7 w-7 p-0\"\n aria-label=\"Expand preview\"\n >\n <Maximize2 className=\"h-3 w-3\" />\n </Button>\n )}\n </>\n );\n\n return (\n <>\n <FenceBlock code={code} language=\"html\" headerActions={headerActions}>\n <div className=\"relative\">\n {showPreview ? (\n <iframe\n ref={iframeRef}\n srcDoc={srcdoc}\n // `allow-scripts` lets previewed HTML run its own JS (charts, demos,\n // and the optional resize-postMessage handshake). It is intentionally\n // NOT paired with `allow-same-origin`, so the content runs in an\n // opaque (null) origin with no access to this page, cookies, or storage.\n sandbox=\"allow-scripts allow-forms\"\n referrerPolicy=\"no-referrer\"\n className=\"w-full border-0\"\n style={{ height: iframeHeight }}\n title=\"HTML Preview\"\n />\n ) : (\n <pre className=\"overflow-x-auto p-3 text-sm\">\n <code>{code}</code>\n </pre>\n )}\n </div>\n </FenceBlock>\n\n {expanded && (\n <div\n className=\"fixed inset-0 z-50 flex items-center justify-center bg-black/50\"\n role=\"dialog\"\n aria-modal=\"true\"\n aria-label=\"HTML Preview\"\n >\n <button\n type=\"button\"\n aria-label=\"Close preview\"\n className=\"absolute inset-0 h-full w-full cursor-default border-0 bg-transparent p-0\"\n onClick={() => setExpanded(false)}\n />\n <div className=\"relative h-[90vh] w-[90vw] overflow-hidden rounded-lg bg-white shadow-xl dark:bg-neutral-900\">\n <div className=\"flex items-center justify-between border-b border-neutral-200 px-4 py-2 dark:border-neutral-700\">\n <span className=\"text-sm font-medium\">HTML Preview</span>\n <Button\n variant=\"ghost\"\n size=\"sm\"\n onClick={() => setExpanded(false)}\n >\n Close\n </Button>\n </div>\n <iframe\n srcDoc={srcdoc}\n sandbox=\"allow-scripts allow-forms\"\n referrerPolicy=\"no-referrer\"\n className=\"h-full w-full border-0\"\n title=\"HTML Preview (expanded)\"\n />\n </div>\n </div>\n )}\n </>\n );\n};\n"]}
1
+ {"version":3,"sources":["../src/components/Markdown/HtmlPreviewBlock.tsx"],"names":["useState","useRef","useEffect","useCallback","jsxs","Fragment","Button","jsx","Code","Eye","Maximize2","FenceBlock"],"mappings":"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","file":"chunk-IB54SKWB.cjs","sourcesContent":["/** Sandboxed iframe preview for HTML code blocks. */\nimport { Code, Eye, Maximize2 } from 'lucide-react';\nimport React, { useCallback, useEffect, useRef, useState } from 'react';\n\nimport { Button } from '../Button';\nimport { FenceBlock } from './FenceBlock';\n\ninterface HtmlPreviewBlockProps {\n code: string;\n id: string;\n}\n\nfunction isFullDocument(html: string): boolean {\n return /<!DOCTYPE|<html/i.test(html);\n}\n\nfunction wrapFragment(html: string): string {\n return `<!DOCTYPE html>\n<html>\n<head><meta charset=\"utf-8\"><style>body{margin:0;padding:8px;font-family:system-ui,sans-serif;font-size:14px}</style></head>\n<body>${html}</body>\n</html>`;\n}\n\nexport const HtmlPreviewBlock: React.FC<HtmlPreviewBlockProps> = ({\n code,\n id,\n}) => {\n const [showPreview, setShowPreview] = useState(false);\n const [expanded, setExpanded] = useState(false);\n const iframeRef = useRef<HTMLIFrameElement>(null);\n const [iframeHeight, setIframeHeight] = useState(200);\n\n const srcdoc = isFullDocument(code) ? code : wrapFragment(code);\n\n useEffect(() => {\n function handleMessage(event: globalThis.MessageEvent) {\n // Sandboxed srcDoc iframes report origin \"null\"; validate source to prevent spoofing.\n if (event.origin !== 'null' && event.origin !== window.location.origin)\n return;\n if (event.source !== iframeRef.current?.contentWindow) return;\n if (event.data?.type === 'HTML_PREVIEW_RESIZE' && event.data?.id === id) {\n setIframeHeight(Math.min(Math.max(event.data.height, 200), 4000));\n }\n }\n window.addEventListener('message', handleMessage);\n return () => window.removeEventListener('message', handleMessage);\n }, [id]);\n\n useEffect(() => {\n if (!expanded) return;\n function handleKey(e: KeyboardEvent) {\n if (e.key === 'Escape') setExpanded(false);\n }\n document.addEventListener('keydown', handleKey);\n return () => document.removeEventListener('keydown', handleKey);\n }, [expanded]);\n\n const togglePreview = useCallback(() => setShowPreview((v) => !v), []);\n\n const headerActions = (\n <>\n <Button\n variant=\"ghost\"\n size=\"sm\"\n onClick={togglePreview}\n className=\"h-7 gap-1 px-2 text-xs\"\n >\n {showPreview ? (\n <Code className=\"h-3 w-3\" />\n ) : (\n <Eye className=\"h-3 w-3\" />\n )}\n {showPreview ? 'Code' : 'Preview'}\n </Button>\n {showPreview && (\n <Button\n variant=\"ghost\"\n size=\"sm\"\n onClick={() => setExpanded(true)}\n className=\"h-7 w-7 p-0\"\n aria-label=\"Expand preview\"\n >\n <Maximize2 className=\"h-3 w-3\" />\n </Button>\n )}\n </>\n );\n\n return (\n <>\n <FenceBlock code={code} language=\"html\" headerActions={headerActions}>\n <div className=\"relative\">\n {showPreview ? (\n <iframe\n ref={iframeRef}\n srcDoc={srcdoc}\n // `allow-scripts` lets previewed HTML run its own JS (charts, demos,\n // and the optional resize-postMessage handshake). It is intentionally\n // NOT paired with `allow-same-origin`, so the content runs in an\n // opaque (null) origin with no access to this page, cookies, or storage.\n sandbox=\"allow-scripts allow-forms\"\n referrerPolicy=\"no-referrer\"\n className=\"w-full border-0\"\n style={{ height: iframeHeight }}\n title=\"HTML Preview\"\n />\n ) : (\n <pre className=\"overflow-x-auto p-3 text-sm\">\n <code>{code}</code>\n </pre>\n )}\n </div>\n </FenceBlock>\n\n {expanded && (\n <div\n className=\"fixed inset-0 z-50 flex items-center justify-center bg-black/50\"\n role=\"dialog\"\n aria-modal=\"true\"\n aria-label=\"HTML Preview\"\n >\n <button\n type=\"button\"\n aria-label=\"Close preview\"\n className=\"absolute inset-0 h-full w-full cursor-default border-0 bg-transparent p-0\"\n onClick={() => setExpanded(false)}\n />\n <div className=\"relative h-[90vh] w-[90vw] overflow-hidden rounded-lg bg-white shadow-xl dark:bg-neutral-900\">\n <div className=\"flex items-center justify-between border-b border-neutral-200 px-4 py-2 dark:border-neutral-700\">\n <span className=\"text-sm font-medium\">HTML Preview</span>\n <Button\n variant=\"ghost\"\n size=\"sm\"\n onClick={() => setExpanded(false)}\n >\n Close\n </Button>\n </div>\n <iframe\n srcDoc={srcdoc}\n sandbox=\"allow-scripts allow-forms\"\n referrerPolicy=\"no-referrer\"\n className=\"h-full w-full border-0\"\n title=\"HTML Preview (expanded)\"\n />\n </div>\n </div>\n )}\n </>\n );\n};\n"]}
@@ -1,6 +1,6 @@
1
1
  'use strict';
2
2
 
3
- var chunkRDGRKYQ5_cjs = require('./chunk-RDGRKYQ5.cjs');
3
+ var chunkIINZWUGK_cjs = require('./chunk-IINZWUGK.cjs');
4
4
  var chunkJYZW2PZS_cjs = require('./chunk-JYZW2PZS.cjs');
5
5
  var React = require('react');
6
6
  var classVarianceAuthority = require('class-variance-authority');
@@ -119,7 +119,7 @@ var MediaPlayer = React__namespace.forwardRef(
119
119
  children: [
120
120
  /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-destructive-700 dark:text-destructive-300 m-0 text-sm", children: error }),
121
121
  /* @__PURE__ */ jsxRuntime.jsx(
122
- chunkRDGRKYQ5_cjs.Button,
122
+ chunkIINZWUGK_cjs.Button,
123
123
  {
124
124
  variant: "outline",
125
125
  size: "sm",
@@ -163,5 +163,5 @@ MediaPlayer.displayName = "MediaPlayer";
163
163
  exports.MediaPlayer = MediaPlayer;
164
164
  exports.inferMediaKind = inferMediaKind;
165
165
  exports.mediaPlayerVariants = mediaPlayerVariants;
166
- //# sourceMappingURL=chunk-JP5SGIXA.cjs.map
167
- //# sourceMappingURL=chunk-JP5SGIXA.cjs.map
166
+ //# sourceMappingURL=chunk-IFDC4TXM.cjs.map
167
+ //# sourceMappingURL=chunk-IFDC4TXM.cjs.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/components/MediaPlayer/MediaPlayer.tsx"],"names":["cva","React","useMediaTransport","jsx","jsxs","Button"],"mappings":"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","file":"chunk-JP5SGIXA.cjs","sourcesContent":["import * as React from 'react';\nimport { cva, type VariantProps } from 'class-variance-authority';\n\nimport { Button } from '../Button';\nimport { useMediaTransport } from '../../hooks/useMediaTransport';\n\n// ============================================================================\n// Types & Interfaces\n// ============================================================================\n\nexport type MediaPlayerState =\n | 'idle'\n | 'loading'\n | 'playing'\n | 'paused'\n | 'error';\n\nexport type MediaKind = 'video' | 'audio';\n\n/** Ref handle for controlling {@link MediaPlayer} programmatically. */\nexport interface MediaPlayerRef {\n /** Seek to a specific time in milliseconds. */\n seekToMs: (timeMs: number) => void;\n /** Start playback. */\n play: () => void;\n /** Pause playback. */\n pause: () => void;\n /** Get current playback time in milliseconds. */\n getCurrentTimeMs: () => number;\n /** Get total duration in milliseconds. */\n getDurationMs: () => number;\n /** Whether playback is currently paused. */\n isPaused: () => boolean;\n /** Set playback speed multiplier. */\n setPlaybackRate: (rate: number) => void;\n /**\n * The underlying media element.\n * Escape hatch for host integrations (e.g. thumbnail capture); prefer the\n * typed methods above for playback control.\n */\n mediaElement: HTMLVideoElement | HTMLAudioElement | null;\n}\n\nexport interface MediaPlayerProps extends VariantProps<\n typeof mediaPlayerVariants\n> {\n /** Media source URL. */\n src: string;\n /** Force the media kind; when omitted it is inferred from the src extension. */\n kind?: MediaKind;\n /** Whether to show native controls (default `true`). */\n controls?: boolean;\n /** Callback when playback state changes. */\n onStateChange?: (state: MediaPlayerState) => void;\n /** Callback when playback ends. */\n onEnded?: () => void;\n /** Callback when an error occurs. */\n onError?: (error: Error) => void;\n /** Callback on time updates (milliseconds). */\n onTimeUpdate?: (currentTimeMs: number, durationMs: number) => void;\n /** Additional class name. */\n className?: string;\n /** Accessible label for the media element. */\n 'aria-label'?: string;\n /**\n * Transitional: exposes the raw media element to legacy consumers.\n * Prefer {@link MediaPlayerRef} for playback control.\n */\n mediaElementRef?: React.RefObject<HTMLVideoElement | HTMLAudioElement | null>;\n}\n\n// ============================================================================\n// Variants\n// ============================================================================\n\nconst mediaPlayerVariants = cva(\n 'flex h-full w-full items-center justify-center',\n {\n variants: {\n variant: {\n plain: '',\n card: 'rounded-xl border border-border bg-card text-card-foreground p-2',\n },\n },\n defaultVariants: {\n variant: 'plain',\n },\n }\n);\n\n// ============================================================================\n// Helpers\n// ============================================================================\n\nconst VIDEO_EXTENSIONS = /\\.(mp4|mov|avi|webm|mkv|m4v)$/i;\n\n/** Infer media kind from a URL's file extension; defaults to audio. */\nexport function inferMediaKind(src: string): MediaKind {\n // Strip any query string / fragment before matching. Testing the extension\n // against the full URL required a trailing `.*`, which backtracks\n // polynomially on crafted inputs (ReDoS); splitting first is linear.\n const path = src.split(/[?#]/, 1)[0];\n return VIDEO_EXTENSIONS.test(path) ? 'video' : 'audio';\n}\n\n// ============================================================================\n// Component\n// ============================================================================\n\n/**\n * Media playback surface for audio and video with a shared imperative handle.\n *\n * Renders a native `<video>` or `<audio>` element (kind inferred from the src\n * extension unless forced) with themed error/retry handling. Playback state and\n * controls come from the shared {@link useMediaTransport} hook and are exposed\n * through {@link MediaPlayerRef} (all times in milliseconds) — consumers should\n * not reach into the DOM element directly.\n */\nexport const MediaPlayer = React.forwardRef<MediaPlayerRef, MediaPlayerProps>(\n (\n {\n src,\n kind,\n controls = true,\n variant,\n onStateChange,\n onEnded,\n onError,\n onTimeUpdate,\n className,\n 'aria-label': ariaLabel,\n mediaElementRef,\n },\n ref\n ) => {\n const [error, setError] = React.useState<string | null>(null);\n\n // A failed load must not outlive its src: clearing on change lets a host\n // swap in a corrected URL without being trapped on the error surface\n // (which unmounts the media element, so the new src would never load).\n React.useEffect(() => {\n setError(null);\n }, [src]);\n const resolvedKind = kind ?? inferMediaKind(src);\n\n const transport = useMediaTransport({\n onTimeUpdate,\n onStateChange,\n onEnded,\n onError: (err) => {\n setError('Unable to load media. The server may be unavailable.');\n onError?.(err);\n },\n endedState: 'paused',\n errorLabel: `media: ${src}`,\n });\n\n const { setMediaElement, mediaElement } = transport;\n\n const setElement = React.useCallback(\n (el: HTMLVideoElement | HTMLAudioElement | null) => {\n setMediaElement(el);\n if (mediaElementRef) {\n (mediaElementRef as React.MutableRefObject<typeof el>).current = el;\n }\n },\n [setMediaElement, mediaElementRef]\n );\n\n React.useImperativeHandle(\n ref,\n (): MediaPlayerRef => ({\n seekToMs: transport.seekToMs,\n play: transport.play,\n pause: transport.pause,\n getCurrentTimeMs: transport.getCurrentTimeMs,\n getDurationMs: transport.getDurationMs,\n isPaused: transport.isPaused,\n setPlaybackRate: transport.setPlaybackRate,\n get mediaElement() {\n return mediaElement;\n },\n }),\n [transport, mediaElement]\n );\n\n const handleRetry = React.useCallback(() => {\n setError(null);\n mediaElement?.load();\n }, [mediaElement]);\n\n const sharedMediaProps = {\n src,\n controls,\n 'aria-label': ariaLabel,\n };\n\n if (error) {\n return (\n <div className={mediaPlayerVariants({ variant, className })}>\n <div\n role=\"alert\"\n className=\"border-destructive/30 bg-destructive/10 flex min-h-36 flex-col items-center justify-center gap-3 rounded-lg border p-8 text-center\"\n >\n {/* destructive-700/300 instead of the base token: #dc2626 on the\n destructive/10 tint is 4.14:1 — below WCAG AA (axe: color-contrast). */}\n <p className=\"text-destructive-700 dark:text-destructive-300 m-0 text-sm\">\n {error}\n </p>\n {/* bg-background: the outline button is transparent, and its text on\n the destructive/10 tint sits exactly at the 4.5:1 AA boundary. */}\n <Button\n variant=\"outline\"\n size=\"sm\"\n className=\"bg-background\"\n onClick={handleRetry}\n >\n Retry\n </Button>\n </div>\n </div>\n );\n }\n\n return (\n <div className={mediaPlayerVariants({ variant, className })}>\n {resolvedKind === 'video' ? (\n // Generic media surface: caption tracks belong to the consumer's media\n // resource and are supplied via children, not this transport component.\n // eslint-disable-next-line jsx-a11y/media-has-caption\n <video\n ref={setElement as React.Ref<HTMLVideoElement>}\n playsInline\n className=\"h-auto max-h-full w-auto max-w-full object-contain\"\n {...sharedMediaProps}\n />\n ) : (\n // eslint-disable-next-line jsx-a11y/media-has-caption\n <audio\n ref={setElement as React.Ref<HTMLAudioElement>}\n className=\"my-4 w-[90%] max-w-lg\"\n {...sharedMediaProps}\n />\n )}\n </div>\n );\n }\n);\n\nMediaPlayer.displayName = 'MediaPlayer';\n\nexport { mediaPlayerVariants };\n"]}
1
+ {"version":3,"sources":["../src/components/MediaPlayer/MediaPlayer.tsx"],"names":["cva","React","useMediaTransport","jsx","jsxs","Button"],"mappings":"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","file":"chunk-IFDC4TXM.cjs","sourcesContent":["import * as React from 'react';\nimport { cva, type VariantProps } from 'class-variance-authority';\n\nimport { Button } from '../Button';\nimport { useMediaTransport } from '../../hooks/useMediaTransport';\n\n// ============================================================================\n// Types & Interfaces\n// ============================================================================\n\nexport type MediaPlayerState =\n | 'idle'\n | 'loading'\n | 'playing'\n | 'paused'\n | 'error';\n\nexport type MediaKind = 'video' | 'audio';\n\n/** Ref handle for controlling {@link MediaPlayer} programmatically. */\nexport interface MediaPlayerRef {\n /** Seek to a specific time in milliseconds. */\n seekToMs: (timeMs: number) => void;\n /** Start playback. */\n play: () => void;\n /** Pause playback. */\n pause: () => void;\n /** Get current playback time in milliseconds. */\n getCurrentTimeMs: () => number;\n /** Get total duration in milliseconds. */\n getDurationMs: () => number;\n /** Whether playback is currently paused. */\n isPaused: () => boolean;\n /** Set playback speed multiplier. */\n setPlaybackRate: (rate: number) => void;\n /**\n * The underlying media element.\n * Escape hatch for host integrations (e.g. thumbnail capture); prefer the\n * typed methods above for playback control.\n */\n mediaElement: HTMLVideoElement | HTMLAudioElement | null;\n}\n\nexport interface MediaPlayerProps extends VariantProps<\n typeof mediaPlayerVariants\n> {\n /** Media source URL. */\n src: string;\n /** Force the media kind; when omitted it is inferred from the src extension. */\n kind?: MediaKind;\n /** Whether to show native controls (default `true`). */\n controls?: boolean;\n /** Callback when playback state changes. */\n onStateChange?: (state: MediaPlayerState) => void;\n /** Callback when playback ends. */\n onEnded?: () => void;\n /** Callback when an error occurs. */\n onError?: (error: Error) => void;\n /** Callback on time updates (milliseconds). */\n onTimeUpdate?: (currentTimeMs: number, durationMs: number) => void;\n /** Additional class name. */\n className?: string;\n /** Accessible label for the media element. */\n 'aria-label'?: string;\n /**\n * Transitional: exposes the raw media element to legacy consumers.\n * Prefer {@link MediaPlayerRef} for playback control.\n */\n mediaElementRef?: React.RefObject<HTMLVideoElement | HTMLAudioElement | null>;\n}\n\n// ============================================================================\n// Variants\n// ============================================================================\n\nconst mediaPlayerVariants = cva(\n 'flex h-full w-full items-center justify-center',\n {\n variants: {\n variant: {\n plain: '',\n card: 'rounded-xl border border-border bg-card text-card-foreground p-2',\n },\n },\n defaultVariants: {\n variant: 'plain',\n },\n }\n);\n\n// ============================================================================\n// Helpers\n// ============================================================================\n\nconst VIDEO_EXTENSIONS = /\\.(mp4|mov|avi|webm|mkv|m4v)$/i;\n\n/** Infer media kind from a URL's file extension; defaults to audio. */\nexport function inferMediaKind(src: string): MediaKind {\n // Strip any query string / fragment before matching. Testing the extension\n // against the full URL required a trailing `.*`, which backtracks\n // polynomially on crafted inputs (ReDoS); splitting first is linear.\n const path = src.split(/[?#]/, 1)[0];\n return VIDEO_EXTENSIONS.test(path) ? 'video' : 'audio';\n}\n\n// ============================================================================\n// Component\n// ============================================================================\n\n/**\n * Media playback surface for audio and video with a shared imperative handle.\n *\n * Renders a native `<video>` or `<audio>` element (kind inferred from the src\n * extension unless forced) with themed error/retry handling. Playback state and\n * controls come from the shared {@link useMediaTransport} hook and are exposed\n * through {@link MediaPlayerRef} (all times in milliseconds) — consumers should\n * not reach into the DOM element directly.\n */\nexport const MediaPlayer = React.forwardRef<MediaPlayerRef, MediaPlayerProps>(\n (\n {\n src,\n kind,\n controls = true,\n variant,\n onStateChange,\n onEnded,\n onError,\n onTimeUpdate,\n className,\n 'aria-label': ariaLabel,\n mediaElementRef,\n },\n ref\n ) => {\n const [error, setError] = React.useState<string | null>(null);\n\n // A failed load must not outlive its src: clearing on change lets a host\n // swap in a corrected URL without being trapped on the error surface\n // (which unmounts the media element, so the new src would never load).\n React.useEffect(() => {\n setError(null);\n }, [src]);\n const resolvedKind = kind ?? inferMediaKind(src);\n\n const transport = useMediaTransport({\n onTimeUpdate,\n onStateChange,\n onEnded,\n onError: (err) => {\n setError('Unable to load media. The server may be unavailable.');\n onError?.(err);\n },\n endedState: 'paused',\n errorLabel: `media: ${src}`,\n });\n\n const { setMediaElement, mediaElement } = transport;\n\n const setElement = React.useCallback(\n (el: HTMLVideoElement | HTMLAudioElement | null) => {\n setMediaElement(el);\n if (mediaElementRef) {\n (mediaElementRef as React.MutableRefObject<typeof el>).current = el;\n }\n },\n [setMediaElement, mediaElementRef]\n );\n\n React.useImperativeHandle(\n ref,\n (): MediaPlayerRef => ({\n seekToMs: transport.seekToMs,\n play: transport.play,\n pause: transport.pause,\n getCurrentTimeMs: transport.getCurrentTimeMs,\n getDurationMs: transport.getDurationMs,\n isPaused: transport.isPaused,\n setPlaybackRate: transport.setPlaybackRate,\n get mediaElement() {\n return mediaElement;\n },\n }),\n [transport, mediaElement]\n );\n\n const handleRetry = React.useCallback(() => {\n setError(null);\n mediaElement?.load();\n }, [mediaElement]);\n\n const sharedMediaProps = {\n src,\n controls,\n 'aria-label': ariaLabel,\n };\n\n if (error) {\n return (\n <div className={mediaPlayerVariants({ variant, className })}>\n <div\n role=\"alert\"\n className=\"border-destructive/30 bg-destructive/10 flex min-h-36 flex-col items-center justify-center gap-3 rounded-lg border p-8 text-center\"\n >\n {/* destructive-700/300 instead of the base token: #dc2626 on the\n destructive/10 tint is 4.14:1 — below WCAG AA (axe: color-contrast). */}\n <p className=\"text-destructive-700 dark:text-destructive-300 m-0 text-sm\">\n {error}\n </p>\n {/* bg-background: the outline button is transparent, and its text on\n the destructive/10 tint sits exactly at the 4.5:1 AA boundary. */}\n <Button\n variant=\"outline\"\n size=\"sm\"\n className=\"bg-background\"\n onClick={handleRetry}\n >\n Retry\n </Button>\n </div>\n </div>\n );\n }\n\n return (\n <div className={mediaPlayerVariants({ variant, className })}>\n {resolvedKind === 'video' ? (\n // Generic media surface: caption tracks belong to the consumer's media\n // resource and are supplied via children, not this transport component.\n // eslint-disable-next-line jsx-a11y/media-has-caption\n <video\n ref={setElement as React.Ref<HTMLVideoElement>}\n playsInline\n className=\"h-auto max-h-full w-auto max-w-full object-contain\"\n {...sharedMediaProps}\n />\n ) : (\n // eslint-disable-next-line jsx-a11y/media-has-caption\n <audio\n ref={setElement as React.Ref<HTMLAudioElement>}\n className=\"my-4 w-[90%] max-w-lg\"\n {...sharedMediaProps}\n />\n )}\n </div>\n );\n }\n);\n\nMediaPlayer.displayName = 'MediaPlayer';\n\nexport { mediaPlayerVariants };\n"]}