@leavepulse/ui 0.82.0 → 0.83.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (263) hide show
  1. package/dist/assets/LpVideoTrim-BcGs3Sh0.css +8 -0
  2. package/dist/assets/VideoFlash-VuPkC7QV.css +23 -0
  3. package/dist/chunks/{ContextMenuItems-kRVTuSZd.js → ContextMenuItems-h-apPY2d.js} +1 -1
  4. package/dist/chunks/{DropzoneLinkField-CvMUu8HQ.js → DropzoneLinkField-_Op8b_ee.js} +1 -1
  5. package/dist/chunks/{FieldLeading-CNN_5Dp1.js → FieldLeading-mOMcwNqi.js} +1 -1
  6. package/dist/chunks/{FieldWrapper-BBJPEVHr.js → FieldWrapper-DtT-AIcn.js} +1 -1
  7. package/dist/chunks/{IconCloseButton-C59_etp2.js → IconCloseButton-YmisskyZ.js} +1 -1
  8. package/dist/chunks/{LayoutCanvas-BIY74SUe.js → LayoutCanvas-BrISZEBr.js} +1 -1
  9. package/dist/chunks/{LayoutNode-CTlKlhb-.js → LayoutNode-CwMQ8ACa.js} +1 -1
  10. package/dist/chunks/{LpActionBar-Cowb-28D.js → LpActionBar-CVVC6YbC.js} +1 -1
  11. package/dist/chunks/{LpAddressInput-nTJlUQ6K.js → LpAddressInput-tiuJ-bru.js} +7 -7
  12. package/dist/chunks/{LpAlert-DhZdjekN.js → LpAlert-8-x4H_Nk.js} +1 -1
  13. package/dist/chunks/{LpAppShell-CK9hTgQ1.js → LpAppShell-BW2YMq-A.js} +4 -4
  14. package/dist/chunks/{LpAutocomplete--PaZkQoU.js → LpAutocomplete-BZODIops.js} +4 -4
  15. package/dist/chunks/{LpAvatar-DVCld_L2.js → LpAvatar-BZq4nH53.js} +1 -1
  16. package/dist/chunks/{LpBadge-DXvpxk6z.js → LpBadge-Cz0pSSUu.js} +1 -1
  17. package/dist/chunks/{LpBottomNav-COQiBNUN.js → LpBottomNav-DVdR5Mry.js} +1 -1
  18. package/dist/chunks/{LpBreadcrumbs-Dt1O5G4O.js → LpBreadcrumbs-B2jphAel.js} +1 -1
  19. package/dist/chunks/{LpCalendar-C8Xlukd2.js → LpCalendar-C0_N5LVT.js} +1 -1
  20. package/dist/chunks/{LpCheckbox-Dpybd3oV.js → LpCheckbox-CwqLNdw4.js} +2 -2
  21. package/dist/chunks/{LpCodeBlock-C1Hu5RyT.js → LpCodeBlock-Dcss6bnl.js} +2 -2
  22. package/dist/chunks/{LpCodeDisplay-BVruT3-A.js → LpCodeDisplay-CLms1zDY.js} +4 -4
  23. package/dist/chunks/{LpColorPicker-BK-NRaGK.js → LpColorPicker-CbIY450X.js} +3 -3
  24. package/dist/chunks/{LpConfirmDialog-2CQFKtqU.js → LpConfirmDialog-RmP4z6va.js} +2 -2
  25. package/dist/chunks/{LpConfirmHost-CTkSytVl.js → LpConfirmHost-DheBgRMB.js} +1 -1
  26. package/dist/chunks/{LpContextMenu-DcHPdW-t.js → LpContextMenu-DIYhlap8.js} +2 -2
  27. package/dist/chunks/{LpContextSwitcher-C_nnDbeI.js → LpContextSwitcher-fDA6ERl-.js} +2 -2
  28. package/dist/chunks/{LpCopyButton-De7_elaO.js → LpCopyButton-DSqKFGEb.js} +1 -1
  29. package/dist/chunks/{LpDataList-BjZPfQjO.js → LpDataList-f9UjSx9m.js} +2 -2
  30. package/dist/chunks/{LpDatePicker-wOrHd0fg.js → LpDatePicker-3kDQLVbg.js} +5 -5
  31. package/dist/chunks/{LpDateRangePicker-CVMvvo5t.js → LpDateRangePicker-DUPiTt0_.js} +3 -3
  32. package/dist/chunks/{LpDisclosure-CtQ63LeO.js → LpDisclosure-C5WZjhbQ.js} +1 -1
  33. package/dist/chunks/{LpDrawer-TZBPzyOM.js → LpDrawer-CkYvIGIa.js} +1 -1
  34. package/dist/chunks/{LpDropdownMenu-DL9LgkS8.js → LpDropdownMenu-zSsK2Xra.js} +6 -3
  35. package/dist/chunks/{LpEditable-DuPE2tkl.js → LpEditable-CP7Y_lKg.js} +2 -2
  36. package/dist/chunks/{LpEmptyState-W1U_tKg-.js → LpEmptyState-dsc5x-ya.js} +1 -1
  37. package/dist/chunks/{LpFieldNotice-BLKlYLwu.js → LpFieldNotice-TOTbWvgv.js} +1 -1
  38. package/dist/chunks/{LpFileTree-CEiRIpj1.js → LpFileTree-BPjnOTln.js} +4 -4
  39. package/dist/chunks/{LpFileTreeNode-C0292AU2.js → LpFileTreeNode-_-MiWmie.js} +4 -4
  40. package/dist/chunks/{LpFormField-Bhgi0idH.js → LpFormField-BJwD1iEF.js} +1 -1
  41. package/dist/chunks/{LpHintLayer-D8ZKsvsT.js → LpHintLayer-CmfGnxYu.js} +1 -1
  42. package/dist/chunks/{LpHints-DbIV-wk4.js → LpHints-C2Xvc1Fd.js} +3 -3
  43. package/dist/chunks/{LpIcon-CytpcLmS.js → LpIcon-CoOLz1oJ.js} +1 -1
  44. package/dist/chunks/{LpInfraNode-8cGoY87Q.js → LpInfraNode-CW3qsM-U.js} +2 -2
  45. package/dist/chunks/{LpInput-P2C12X7s.js → LpInput-BVWhkPuN.js} +3 -3
  46. package/dist/chunks/{LpInspector-DjfMa4tD.js → LpInspector-REmoX_es.js} +4 -4
  47. package/dist/chunks/{LpLightbox-BEQtCz0m.js → LpLightbox-C3FFTYP5.js} +65 -20
  48. package/dist/chunks/{LpLogInspector-CyxK1d-V.js → LpLogInspector-Cs8Z_fM0.js} +2 -2
  49. package/dist/chunks/{LpLogViewer-CZrc_HG7.js → LpLogViewer-DQRGe-ZK.js} +6 -6
  50. package/dist/chunks/{LpMapPicker-CbTfFcEu.js → LpMapPicker-CQnQPgKm.js} +1 -1
  51. package/dist/chunks/{LpMediaGallery-C_SwNR4y.js → LpMediaGallery-DkKqTy9P.js} +20 -8
  52. package/dist/chunks/{LpModal-B6Yt0G7E.js → LpModal-DwejR7VP.js} +1 -1
  53. package/dist/chunks/{LpModalNav-CMYWEiUs.js → LpModalNav-D1-dSe6f.js} +3 -3
  54. package/dist/chunks/{LpNotificationBell-BJKPx0X1.js → LpNotificationBell-EKLkN0sp.js} +4 -4
  55. package/dist/chunks/{LpNotificationFeed-orWISVez.js → LpNotificationFeed-Dc-yQ4NH.js} +4 -4
  56. package/dist/chunks/{LpNumberField-C5MeLsoE.js → LpNumberField-DvUjEMp-.js} +3 -3
  57. package/dist/chunks/{LpOtpInput-6SCQ64uK.js → LpOtpInput-xvDO14f4.js} +1 -1
  58. package/dist/chunks/{LpPagination-CkwbdFa9.js → LpPagination-BFZY8dFn.js} +1 -1
  59. package/dist/chunks/{LpPaletteTheme-RWgbWFOz.js → LpPaletteTheme-EBJv0Bwz.js} +2 -2
  60. package/dist/chunks/{LpPasswordInput-DJBRo5lt.js → LpPasswordInput-DRJR3fF1.js} +2 -2
  61. package/dist/chunks/{LpPhoneInput-DcmcJwos.js → LpPhoneInput-BGOOtUoW.js} +3 -3
  62. package/dist/chunks/{LpPie-DmMlhgo2.js → LpPie-Deyn8h5J.js} +2 -2
  63. package/dist/chunks/{LpPipeline-BXcp2shV.js → LpPipeline-9ChjeNh5.js} +2 -2
  64. package/dist/chunks/{LpQuota-CtEiqRg4.js → LpQuota-CNh5eF_p.js} +1 -1
  65. package/dist/chunks/{LpRadioGroup-Ubkk_eSq.js → LpRadioGroup-Br2Nl9Gr.js} +2 -2
  66. package/dist/chunks/{LpRangeCalendar-DCswVYbU.js → LpRangeCalendar-D66Y3U_w.js} +1 -1
  67. package/dist/chunks/{LpRangeSlider-DM1qy5Tp.js → LpRangeSlider-eX-fIlOw.js} +1 -1
  68. package/dist/chunks/{LpRepeater-BMo2Eabn.js → LpRepeater-0XvnlVd_.js} +2 -2
  69. package/dist/chunks/{LpSecretField-SSRGVqRc.js → LpSecretField-1RCooChq.js} +5 -5
  70. package/dist/chunks/{LpSection-C3bTxD7t.js → LpSection-B9gbJJcP.js} +1 -1
  71. package/dist/chunks/{LpSegmented-C1DF6m6A.js → LpSegmented-hIjGzGTo.js} +2 -2
  72. package/dist/chunks/{LpSelect-DvDr1VPn.js → LpSelect-DugubwTc.js} +4 -4
  73. package/dist/chunks/{LpSidebar-Bql881r6.js → LpSidebar-DevSoN8W.js} +4 -4
  74. package/dist/chunks/{LpSidebarNav-CKx2KJvr.js → LpSidebarNav-DwQQ3KXe.js} +3 -3
  75. package/dist/chunks/{LpSidebarRow-BMOL9kOG.js → LpSidebarRow-CAGgtJCS.js} +3 -3
  76. package/dist/chunks/{LpSlider-DsSMe4b5.js → LpSlider-1fHpVxpB.js} +1 -1
  77. package/dist/chunks/{LpStat-CQYYDMS6.js → LpStat-Cm9-FaWQ.js} +2 -2
  78. package/dist/chunks/{LpStatus-g5nSJfU3.js → LpStatus-CE8FSAT1.js} +1 -1
  79. package/dist/chunks/{LpStepMark-seVNOuNJ.js → LpStepMark-BWSlV69R.js} +1 -1
  80. package/dist/chunks/{LpStepper-D6qEXihZ.js → LpStepper-1D0ZA7Nx.js} +1 -1
  81. package/dist/chunks/{LpSwitch-DM5CVm31.js → LpSwitch-D_kvE0oQ.js} +1 -1
  82. package/dist/chunks/{LpTabFace-ZWwelqRU.js → LpTabFace-CpbFKi-N.js} +2 -2
  83. package/dist/chunks/{LpTableFilter-CWU9Dmk-.js → LpTableFilter-BYHyCu38.js} +2 -2
  84. package/dist/chunks/{LpTagsInput-C2qVF2ax.js → LpTagsInput-Cqm38t5N.js} +5 -5
  85. package/dist/chunks/{LpTextarea-C3EoV_xv.js → LpTextarea-DaSKBkiV.js} +1 -1
  86. package/dist/chunks/{LpThemeStudio-BIBahaIs.js → LpThemeStudio-BNdfi-Ds.js} +5 -5
  87. package/dist/chunks/{LpThemeSwitcher-D4MqFLGS.js → LpThemeSwitcher-CbC1nqBP.js} +3 -3
  88. package/dist/chunks/{LpTimeField-DPOkbvyP.js → LpTimeField-CCfPCWPT.js} +2 -2
  89. package/dist/chunks/{LpToaster-Dj1VKxFv.js → LpToaster-BhlI7h-h.js} +2 -2
  90. package/dist/chunks/{LpTopologyCanvas-Bspzwm7x.js → LpTopologyCanvas-DlKbu7E5.js} +4 -4
  91. package/dist/chunks/{LpTour-CwpVdVN-.js → LpTour-CSLerA1B.js} +1 -1
  92. package/dist/chunks/{LpTruncate-JSaIW25q.js → LpTruncate-Ct26BSYB.js} +1 -1
  93. package/dist/chunks/{LpVideoBackdrop-Ct4St4ZL.js → LpVideoBackdrop-57i8RY8g.js} +1 -2
  94. package/dist/chunks/LpVideoPlayer-DcWd9DDW.js +813 -0
  95. package/dist/chunks/{LpWindow-RVcP436Z.js → LpWindow-YnF_knSj.js} +2 -2
  96. package/dist/chunks/{LpWorkspaceSwitcher-D0WOz1Fg.js → LpWorkspaceSwitcher-B-5UU6o4.js} +3 -3
  97. package/dist/chunks/{MenuTitle-D8Umab23.js → MenuTitle-BnZbFSwq.js} +1 -1
  98. package/dist/chunks/{OptionContent-DCnX_KRK.js → OptionContent-D5e_eklA.js} +1 -1
  99. package/dist/chunks/{PickerField-ChjY27bm.js → PickerField-KpHiowNI.js} +1 -1
  100. package/dist/chunks/{RevealToggle-MaL7PEjr.js → RevealToggle-CE1hAIJB.js} +1 -1
  101. package/dist/chunks/SteadyText-CwH-kduj.js +25 -0
  102. package/dist/chunks/{TourCard-oXZSpHKb.js → TourCard-t2csiTDS.js} +1 -1
  103. package/dist/chunks/VideoThumb-Csf9bUz3.js +67 -0
  104. package/dist/chunks/VideoVolume-B4_DNmNi.js +68 -0
  105. package/dist/chunks/icons-CdSlCrle.js +59 -0
  106. package/dist/component-names.d.ts +1 -1
  107. package/dist/components/ContextMenuItems.vue.js +1 -1
  108. package/dist/components/DropzoneLinkField.vue.js +1 -1
  109. package/dist/components/FieldLeading.vue.js +1 -1
  110. package/dist/components/FieldWrapper.vue.js +1 -1
  111. package/dist/components/IconCloseButton.vue.js +1 -1
  112. package/dist/components/LayoutCanvas.vue.js +1 -1
  113. package/dist/components/LayoutNode.vue.js +1 -1
  114. package/dist/components/LpActionBar.vue.js +1 -1
  115. package/dist/components/LpAddressInput.vue.js +1 -1
  116. package/dist/components/LpAlert.vue.js +1 -1
  117. package/dist/components/LpAppShell.vue.js +1 -1
  118. package/dist/components/LpAutocomplete.vue.js +1 -1
  119. package/dist/components/LpAvatar.vue.js +1 -1
  120. package/dist/components/LpBadge.vue.js +1 -1
  121. package/dist/components/LpBottomNav.vue.js +1 -1
  122. package/dist/components/LpBreadcrumbs.vue.js +1 -1
  123. package/dist/components/LpCalendar.vue.js +1 -1
  124. package/dist/components/LpChart.vue.js +2 -2
  125. package/dist/components/LpCheckbox.vue.js +1 -1
  126. package/dist/components/LpCodeBlock.vue.js +1 -1
  127. package/dist/components/LpCodeDisplay.vue.js +1 -1
  128. package/dist/components/LpColorPicker.vue.js +1 -1
  129. package/dist/components/LpCommandPalette.vue.js +2 -2
  130. package/dist/components/LpConfirmDialog.vue.js +1 -1
  131. package/dist/components/LpConfirmHost.vue.js +1 -1
  132. package/dist/components/LpContextMenu.vue.js +1 -1
  133. package/dist/components/LpContextSwitcher.vue.js +1 -1
  134. package/dist/components/LpCopyButton.vue.js +1 -1
  135. package/dist/components/LpDataList.vue.js +1 -1
  136. package/dist/components/LpDatePicker.vue.js +1 -1
  137. package/dist/components/LpDateRangePicker.vue.js +1 -1
  138. package/dist/components/LpDisclosure.vue.js +1 -1
  139. package/dist/components/LpDock.vue.js +1 -1
  140. package/dist/components/LpDrawer.vue.js +1 -1
  141. package/dist/components/LpDropdownMenu.vue.d.ts +5 -1
  142. package/dist/components/LpDropdownMenu.vue.js +1 -1
  143. package/dist/components/LpDropzone.vue.js +2 -2
  144. package/dist/components/LpEditable.vue.js +1 -1
  145. package/dist/components/LpEmptyState.vue.js +1 -1
  146. package/dist/components/LpFieldNotice.vue.js +1 -1
  147. package/dist/components/LpFileTree.vue.js +1 -1
  148. package/dist/components/LpFileTreeNode.vue.js +1 -1
  149. package/dist/components/LpFormField.vue.js +1 -1
  150. package/dist/components/LpHintLayer.vue.js +1 -1
  151. package/dist/components/LpHints.vue.js +1 -1
  152. package/dist/components/LpIcon.vue.js +1 -1
  153. package/dist/components/LpImageEditor.vue.js +1 -1
  154. package/dist/components/LpInfraNode.vue.js +1 -1
  155. package/dist/components/LpInput.vue.js +1 -1
  156. package/dist/components/LpInspector.vue.js +1 -1
  157. package/dist/components/LpLightbox.vue.js +1 -1
  158. package/dist/components/LpLogInspector.vue.js +1 -1
  159. package/dist/components/LpLogViewer.vue.js +1 -1
  160. package/dist/components/LpMapPicker.vue.js +1 -1
  161. package/dist/components/LpMediaGallery.vue.d.ts +1 -1
  162. package/dist/components/LpMediaGallery.vue.js +1 -1
  163. package/dist/components/LpModal.vue.js +1 -1
  164. package/dist/components/LpModalNav.vue.js +1 -1
  165. package/dist/components/LpNotificationBell.vue.js +1 -1
  166. package/dist/components/LpNotificationFeed.vue.js +1 -1
  167. package/dist/components/LpNumberField.vue.js +1 -1
  168. package/dist/components/LpOtpInput.vue.js +1 -1
  169. package/dist/components/LpPagination.vue.js +1 -1
  170. package/dist/components/LpPaletteFacts.vue.js +1 -1
  171. package/dist/components/LpPaletteHeader.vue.js +2 -2
  172. package/dist/components/LpPaletteTheme.vue.js +1 -1
  173. package/dist/components/LpPasswordInput.vue.js +1 -1
  174. package/dist/components/LpPhoneInput.vue.js +1 -1
  175. package/dist/components/LpPie.vue.js +1 -1
  176. package/dist/components/LpPipeline.vue.js +1 -1
  177. package/dist/components/LpQuota.vue.js +1 -1
  178. package/dist/components/LpRadioGroup.vue.js +1 -1
  179. package/dist/components/LpRangeCalendar.vue.js +1 -1
  180. package/dist/components/LpRangeSlider.vue.js +1 -1
  181. package/dist/components/LpRepeater.vue.js +1 -1
  182. package/dist/components/LpSecretField.vue.js +1 -1
  183. package/dist/components/LpSection.vue.js +1 -1
  184. package/dist/components/LpSegmented.vue.js +1 -1
  185. package/dist/components/LpSelect.vue.js +1 -1
  186. package/dist/components/LpShortcutsDialog.vue.js +1 -1
  187. package/dist/components/LpSidebar.vue.js +1 -1
  188. package/dist/components/LpSidebarNav.vue.js +1 -1
  189. package/dist/components/LpSidebarRow.vue.js +1 -1
  190. package/dist/components/LpSlider.vue.js +1 -1
  191. package/dist/components/LpStat.vue.js +1 -1
  192. package/dist/components/LpStatus.vue.js +1 -1
  193. package/dist/components/LpStepMark.vue.js +1 -1
  194. package/dist/components/LpStepper.vue.js +1 -1
  195. package/dist/components/LpSwitch.vue.js +1 -1
  196. package/dist/components/LpTabFace.vue.js +1 -1
  197. package/dist/components/LpTable.vue.js +9 -9
  198. package/dist/components/LpTableFilter.vue.js +1 -1
  199. package/dist/components/LpTabs.vue.js +2 -2
  200. package/dist/components/LpTagsInput.vue.js +1 -1
  201. package/dist/components/LpTextarea.vue.js +1 -1
  202. package/dist/components/LpThemeStudio.vue.js +1 -1
  203. package/dist/components/LpThemeSwitcher.vue.js +1 -1
  204. package/dist/components/LpTimeField.vue.js +1 -1
  205. package/dist/components/LpToaster.vue.js +1 -1
  206. package/dist/components/LpTopologyCanvas.vue.js +1 -1
  207. package/dist/components/LpTour.vue.js +1 -1
  208. package/dist/components/LpTruncate.vue.js +1 -1
  209. package/dist/components/LpVideoBackdrop.vue.js +1 -1
  210. package/dist/components/LpVideoPlayer.vue.d.ts +111 -0
  211. package/dist/components/LpVideoPlayer.vue.js +4 -0
  212. package/dist/components/LpVideoTrim.vue.d.ts +19 -5
  213. package/dist/components/LpVideoTrim.vue.js +596 -445
  214. package/dist/components/LpWindow.vue.js +1 -1
  215. package/dist/components/LpWorkspaceSwitcher.vue.js +1 -1
  216. package/dist/components/MenuTitle.vue.js +1 -1
  217. package/dist/components/OptionContent.vue.js +1 -1
  218. package/dist/components/PickerField.vue.js +1 -1
  219. package/dist/components/RevealToggle.vue.js +1 -1
  220. package/dist/components/SteadyText.vue.d.ts +7 -0
  221. package/dist/components/SteadyText.vue.js +4 -0
  222. package/dist/components/TourCard.vue.js +1 -1
  223. package/dist/components/VideoFlash.vue.d.ts +10 -0
  224. package/dist/components/VideoFlash.vue.js +33 -0
  225. package/dist/components/VideoThumb.vue.d.ts +12 -0
  226. package/dist/components/VideoThumb.vue.js +4 -0
  227. package/dist/components/VideoVolume.vue.d.ts +15 -0
  228. package/dist/components/VideoVolume.vue.js +4 -0
  229. package/dist/components/lightbox.d.ts +13 -0
  230. package/dist/components/lightbox.js +11 -1
  231. package/dist/components/menuWhen.js +1 -1
  232. package/dist/components/videoBackdrop.d.ts +15 -2
  233. package/dist/components/videoBackdrop.js +8 -2
  234. package/dist/components/videoMotion.d.ts +28 -0
  235. package/dist/components/videoMotion.js +26 -0
  236. package/dist/components/videoTrim.d.ts +2 -9
  237. package/dist/components/videoTrim.js +0 -6
  238. package/dist/composables/useVideoMedia.d.ts +74 -0
  239. package/dist/composables/useVideoMedia.js +291 -0
  240. package/dist/icons-all.js +1 -1
  241. package/dist/index.d.ts +4 -1
  242. package/dist/index.js +173 -168
  243. package/package.json +5 -2
  244. package/src/component-names.ts +1 -0
  245. package/src/components/LpDropdownMenu.vue +4 -0
  246. package/src/components/LpLightbox.vue +61 -8
  247. package/src/components/LpMediaGallery.vue +19 -2
  248. package/src/components/LpVideoBackdrop.vue +1 -7
  249. package/src/components/LpVideoPlayer.vue +774 -0
  250. package/src/components/LpVideoTrim.vue +437 -295
  251. package/src/components/SteadyText.vue +21 -0
  252. package/src/components/VideoFlash.vue +52 -0
  253. package/src/components/VideoThumb.vue +66 -0
  254. package/src/components/VideoVolume.vue +63 -0
  255. package/src/components/lightbox.ts +23 -0
  256. package/src/components/videoBackdrop.ts +20 -3
  257. package/src/components/videoMotion.ts +38 -0
  258. package/src/components/videoTrim.ts +2 -14
  259. package/src/composables/useVideoMedia.ts +411 -0
  260. package/src/index.ts +4 -1
  261. package/src/kit-icons.ts +1 -1
  262. package/dist/assets/LpVideoTrim-Ci6IIHW0.css +0 -8
  263. package/dist/chunks/icons-BOdqDUii.js +0 -59
@@ -1,60 +1,67 @@
1
- import { defineComponent, ref, computed, watch, shallowRef, nextTick, onMounted, onBeforeUnmount, openBlock, createElementBlock, mergeProps, unref, createElementVNode, normalizeStyle, Fragment, renderList, normalizeClass, createCommentVNode, createVNode, toDisplayString, withCtx, createTextVNode, withDirectives, vShow, withKeys, withModifiers, createBlock } from "vue";
1
+ import { defineComponent, ref, computed, watch, shallowRef, nextTick, onMounted, onBeforeUnmount, openBlock, createElementBlock, mergeProps, unref, createVNode, withCtx, createElementVNode, toHandlers, Transition, normalizeProps, guardReactiveProps, normalizeStyle, Fragment, renderList, normalizeClass, createCommentVNode, toDisplayString, renderSlot, createBlock, createTextVNode, TransitionGroup, withKeys, withModifiers } from "vue";
2
2
  import { startPointerDrag } from "../composables/pointerDrag.js";
3
- import { isHTMLElement } from "../composables/realm.js";
3
+ import { nodeWindow, isHTMLElement } from "../composables/realm.js";
4
4
  import { useLabels } from "../composables/useLpConfig.js";
5
5
  import { useMergedAttrs } from "../composables/useMergedClass.js";
6
6
  import { useResizeObserver } from "../composables/useResizeObserver.js";
7
7
  import { usePrefersReducedMotion } from "../composables/useReducedMotion.js";
8
- import { _ as _sfc_main$2 } from "../chunks/LpButton-DSHioIfD.js";
9
- import { _ as _sfc_main$1 } from "../chunks/LpIcon-CytpcLmS.js";
10
- import { _ as _sfc_main$3 } from "../chunks/LpInput-P2C12X7s.js";
11
- import { formatClipTime } from "./videoBackdrop.js";
8
+ import { useVideoMedia } from "../composables/useVideoMedia.js";
9
+ import { _ as _sfc_main$3 } from "../chunks/LpButton-DSHioIfD.js";
10
+ import { _ as _sfc_main$2 } from "../chunks/LpIcon-CoOLz1oJ.js";
11
+ import { _ as _sfc_main$1 } from "../chunks/LpContextMenu-DIYhlap8.js";
12
+ import { _ as _sfc_main$6 } from "../chunks/LpInput-BVWhkPuN.js";
13
+ import { _ as _sfc_main$4 } from "../chunks/SteadyText-CwH-kduj.js";
14
+ import VideoFlash from "./VideoFlash.vue.js";
15
+ import { _ as _sfc_main$5 } from "../chunks/VideoVolume-B4_DNmNi.js";
16
+ import { FADE, FADE_SCALE, OVERLAY_BUTTON, ICON_SWAP } from "./videoMotion.js";
17
+ import { useClipboard } from "../composables/useClipboard.js";
18
+ import { useToast } from "../composables/useToast.js";
19
+ import { formatClipTime, widestClipTime } from "./videoBackdrop.js";
12
20
  import { stillSpan, FrameSampler } from "./videoFrames.js";
13
- import { normalizeRange, ticks, tickStep, containRect, mediaErrorCause, revealTime, zoomView, shiftView, adjustRegion, dragEnd, setEnd, parseClipTime, regionBetween } from "./videoTrim.js";
21
+ import { normalizeRange, ticks, tickStep, containRect, setEnd, revealTime, zoomView, shiftView, adjustRegion, dragEnd, parseClipTime, regionBetween } from "./videoTrim.js";
14
22
  import { _ as _export_sfc } from "../chunks/_plugin-vue_export-helper-1tPrXgE0.js";
15
- import '../assets/LpVideoTrim-Ci6IIHW0.css';const _hoisted_1 = ["data-disabled"];
16
- const _hoisted_2 = ["src", "poster", "muted"];
23
+ import '../assets/LpVideoTrim-BcGs3Sh0.css';const _hoisted_1 = ["data-disabled"];
24
+ const _hoisted_2 = ["src", "poster"];
17
25
  const _hoisted_3 = ["src"];
18
- const _hoisted_4 = ["aria-label"];
26
+ const _hoisted_4 = ["data-live", "aria-label"];
19
27
  const _hoisted_5 = ["data-lp-corner", "onPointerdown"];
20
28
  const _hoisted_6 = {
21
- key: 1,
22
- role: "alert",
23
- class: "absolute inset-0 flex flex-col items-center justify-center gap-2 p-4 text-center text-sm text-white/80"
29
+ key: 0,
30
+ class: "pointer-events-none absolute bottom-3 left-1/2 -translate-x-1/2 rounded-pill bg-black/55 px-3 py-1 text-xs whitespace-nowrap text-white/85"
31
+ };
32
+ const _hoisted_7 = {
33
+ key: 0,
34
+ class: "absolute top-2 right-2 flex gap-0.5 rounded-control bg-black/45"
24
35
  };
25
- const _hoisted_7 = { class: "flex flex-wrap items-center gap-1" };
26
36
  const _hoisted_8 = {
27
- class: "px-1.5 font-mono text-xs text-muted tabular-nums",
28
- "data-lp-clock": ""
37
+ key: 0,
38
+ role: "alert",
39
+ class: "absolute inset-0 flex flex-col items-center justify-center gap-2 p-4 text-center text-sm text-white/80"
29
40
  };
30
- const _hoisted_9 = { class: "text-ink" };
41
+ const _hoisted_9 = { class: "flex items-center gap-0.5" };
31
42
  const _hoisted_10 = {
32
- class: "relative h-4 overflow-hidden text-[10px] text-muted tabular-nums",
33
- "aria-hidden": "true"
43
+ class: "min-w-0 truncate px-1.5 font-mono text-xs text-muted",
44
+ "data-lp-clock": ""
34
45
  };
35
- const _hoisted_11 = ["aria-label"];
36
- const _hoisted_12 = { class: "absolute inset-0 overflow-hidden rounded-control" };
37
- const _hoisted_13 = ["data-lp-still"];
38
- const _hoisted_14 = ["tabindex", "aria-label", "aria-valuemax", "aria-valuenow", "aria-valuetext", "aria-disabled", "data-lp-handle", "onPointerdown"];
39
- const _hoisted_15 = ["tabindex", "aria-label", "aria-valuemax", "aria-valuenow", "aria-valuetext"];
40
- const _hoisted_16 = ["aria-label"];
41
- const _hoisted_17 = { class: "flex flex-wrap items-end gap-x-3 gap-y-2 text-xs" };
42
- const _hoisted_18 = { class: "text-muted" };
43
- const _hoisted_19 = { class: "flex flex-col gap-1 pb-1.5" };
46
+ const _hoisted_11 = ["data-live"];
47
+ const _hoisted_12 = ["aria-label"];
48
+ const _hoisted_13 = { class: "absolute inset-0 overflow-hidden rounded-control" };
49
+ const _hoisted_14 = ["data-lp-still"];
50
+ const _hoisted_15 = ["tabindex", "aria-label", "aria-valuemax", "aria-valuenow", "aria-valuetext", "aria-disabled", "aria-hidden", "data-lp-handle", "data-active", "onPointerdown"];
51
+ const _hoisted_16 = ["tabindex", "aria-label", "aria-valuemax", "aria-valuenow", "aria-valuetext", "data-glide"];
52
+ const _hoisted_17 = ["aria-label"];
53
+ const _hoisted_18 = { class: "flex flex-wrap items-end gap-x-3 gap-y-2" };
54
+ const _hoisted_19 = { class: "flex flex-col gap-0.5 pb-0.5 text-xs" };
44
55
  const _hoisted_20 = { class: "text-muted" };
45
56
  const _hoisted_21 = {
46
- class: "font-mono text-sm text-ink tabular-nums",
57
+ class: "font-mono text-sm text-ink",
47
58
  "data-lp-length": ""
48
59
  };
49
60
  const _hoisted_22 = {
50
61
  key: 0,
51
- class: "pb-2 text-muted",
62
+ class: "pb-1 font-mono text-xs text-muted",
52
63
  "data-lp-left": ""
53
64
  };
54
- const _hoisted_23 = {
55
- key: 1,
56
- class: "pb-2 text-muted"
57
- };
58
65
  const __default__ = { inheritAttrs: false };
59
66
  const _sfc_main = /* @__PURE__ */ defineComponent({
60
67
  ...__default__,
@@ -68,6 +75,7 @@ const _sfc_main = /* @__PURE__ */ defineComponent({
68
75
  regionSelect: { type: Boolean },
69
76
  region: { default: null },
70
77
  frameRate: { default: 30 },
78
+ menuItems: {},
71
79
  disabled: { type: Boolean },
72
80
  labels: { default: () => ({}) }
73
81
  },
@@ -100,22 +108,36 @@ const _sfc_main = /* @__PURE__ */ defineComponent({
100
108
  regionClear: "Remove area",
101
109
  failed: "This video couldn't be loaded.",
102
110
  unsupported: "This browser can't play this video's format.",
103
- invalidTime: "Type a time like 1:05.5"
111
+ invalidTime: "Type a time like 1:05.5",
112
+ /** `{time}` is replaced by the time the menu was opened at. */
113
+ menuAt: "At {time}",
114
+ setStart: "Start here",
115
+ setEnd: "End here",
116
+ goStart: "Go to the clip's start",
117
+ goEnd: "Go to the clip's end",
118
+ zoomHere: "Zoom in here",
119
+ volume: "Volume",
120
+ copyTime: "Copy time",
121
+ copyFrame: "Copy frame",
122
+ copiedTime: "Time copied",
123
+ copiedFrame: "Frame copied",
124
+ copyFailed: "Couldn't copy"
104
125
  },
105
126
  () => props.labels
106
127
  );
107
- const { class: rootClass, attrs: rest } = useMergedAttrs("flex flex-col gap-3 select-none");
128
+ const { class: rootClass, attrs: rest } = useMergedAttrs("flex w-full min-w-0 flex-col gap-3 select-none");
108
129
  const reduced = usePrefersReducedMotion();
109
130
  const videoEl = ref(null);
110
131
  const samplerEl = ref(null);
111
132
  const stageEl = ref(null);
112
133
  const trackEl = ref(null);
113
- const duration = ref(0);
114
- const failure = ref(null);
115
- const time = ref(0);
116
- const playing = ref(false);
117
- const muted = ref(false);
118
- const videoSize = ref({ width: 0, height: 0 });
134
+ const media = useVideoMedia(videoEl, {
135
+ src: () => props.src,
136
+ onFrame: followPlayback,
137
+ onError: (cause) => emit("error", { cause, message: cause === "unsupported" ? text.value.unsupported : text.value.failed })
138
+ });
139
+ const { duration, failure, time, playing, wantsPlay, muted, size: videoSize, seek } = media;
140
+ const pause = () => media.pause({ instant: true });
119
141
  const stageSize = ref({ width: 0, height: 0 });
120
142
  const trackWidth = ref(0);
121
143
  const ready = computed(() => duration.value > 0 && !failure.value);
@@ -145,99 +167,21 @@ const _sfc_main = /* @__PURE__ */ defineComponent({
145
167
  if (commit) emit("change", next);
146
168
  }
147
169
  const clipLength = computed(() => local.value[1] - local.value[0]);
148
- let seekTarget = null;
149
- let seekBusy = false;
150
- function seek(t) {
151
- const video = videoEl.value;
152
- const target = Math.min(Math.max(0, t), duration.value || t);
153
- time.value = target;
154
- if (!video) return;
155
- if (seekBusy) {
156
- seekTarget = target;
157
- return;
158
- }
159
- seekBusy = true;
160
- video.currentTime = target;
161
- }
162
- function onSeeked() {
163
- seekBusy = false;
164
- if (seekTarget !== null) {
165
- const next = seekTarget;
166
- seekTarget = null;
167
- seek(next);
168
- } else if (videoEl.value && !playing.value) time.value = videoEl.value.currentTime;
169
- }
170
- let probingDuration = false;
171
- function onMetadata() {
172
- const video = videoEl.value;
173
- if (!video) return;
174
- videoSize.value = { width: video.videoWidth, height: video.videoHeight };
175
- if (Number.isFinite(video.duration)) {
176
- duration.value = video.duration;
177
- return;
178
- }
179
- probingDuration = true;
180
- video.currentTime = 1e101;
181
- }
182
- function onDurationChange() {
183
- const video = videoEl.value;
184
- if (!video || !Number.isFinite(video.duration) || !video.duration) return;
185
- duration.value = video.duration;
186
- if (probingDuration) {
187
- probingDuration = false;
188
- video.currentTime = 0;
189
- }
190
- }
191
- async function onError() {
192
- const video = videoEl.value;
193
- if (!video?.error) return;
194
- const src = props.src;
195
- let cause = mediaErrorCause(video.error);
196
- if (cause === "unsupported") cause = await probeSource(src);
197
- if (src !== props.src) return;
198
- failure.value = cause;
199
- emit("error", { cause, message: cause === "unsupported" ? text.value.unsupported : text.value.failed });
200
- }
201
- async function probeSource(src) {
202
- try {
203
- const res = await fetch(src, { headers: { Range: "bytes=0-0" }, credentials: "same-origin" });
204
- void res.body?.cancel();
205
- const type = res.headers.get("content-type") ?? "";
206
- return res.ok && !/^text\/|json|xml/.test(type) ? "unsupported" : "load";
207
- } catch {
208
- return "unsupported";
209
- }
210
- }
211
170
  let stopAtEnd = false;
212
- let frame = 0;
213
- function tick() {
214
- frame = 0;
215
- const video = videoEl.value;
216
- if (!video || !playing.value) return;
217
- time.value = video.currentTime;
218
- if (stopAtEnd && video.currentTime >= local.value[1]) {
219
- video.pause();
171
+ function followPlayback() {
172
+ if (stopAtEnd && time.value >= local.value[1]) {
173
+ pause();
220
174
  seek(local.value[1]);
221
175
  return;
222
176
  }
223
177
  if (zoomed.value) view.value = revealTime(view.value, time.value, duration.value, 0.05);
224
- frame = requestAnimationFrame(tick);
225
- }
226
- function onPlay() {
227
- playing.value = true;
228
- if (!frame) frame = requestAnimationFrame(tick);
229
- }
230
- function onPause() {
231
- playing.value = false;
232
- if (frame) cancelAnimationFrame(frame);
233
- frame = 0;
234
- if (videoEl.value && !seekBusy) time.value = videoEl.value.currentTime;
235
178
  }
179
+ const flash = ref(null);
236
180
  function togglePlay() {
237
- const video = videoEl.value;
238
- if (!video || off.value) return;
239
- if (!video.paused) {
240
- video.pause();
181
+ if (!videoEl.value || off.value) return;
182
+ flash.value = { icon: wantsPlay.value ? "lucide:pause" : "lucide:play", n: (flash.value?.n ?? 0) + 1 };
183
+ if (wantsPlay.value) {
184
+ media.pause();
241
185
  return;
242
186
  }
243
187
  const [a, b] = local.value;
@@ -245,11 +189,7 @@ const _sfc_main = /* @__PURE__ */ defineComponent({
245
189
  if (from >= b - 1e-3 && from <= b + 1e-3) from = a;
246
190
  stopAtEnd = from >= a - 1e-3 && from < b;
247
191
  if (from !== time.value) seek(from);
248
- void video.play().catch(() => {
249
- });
250
- }
251
- function pause() {
252
- videoEl.value?.pause();
192
+ media.play();
253
193
  }
254
194
  function step(seconds) {
255
195
  if (off.value) return;
@@ -258,10 +198,17 @@ const _sfc_main = /* @__PURE__ */ defineComponent({
258
198
  if (zoomed.value) view.value = revealTime(view.value, time.value, duration.value);
259
199
  }
260
200
  function toggleMute() {
261
- muted.value = !muted.value;
262
- if (videoEl.value) videoEl.value.muted = muted.value;
201
+ media.setMuted(!muted.value);
263
202
  }
264
203
  const frameStep = computed(() => 1 / Math.max(1, props.frameRate));
204
+ const frameWindow = () => nodeWindow(trackEl.value ?? videoEl.value);
205
+ const TRACK_GLIDE = "[&_[data-glide]]:transition-[left,width] [&_[data-glide]]:duration-(--duration-medium) [&_[data-glide]]:ease-(--ease-emphasized) data-[live]:[&_[data-glide]]:transition-none motion-reduce:[&_[data-glide]]:transition-none";
206
+ const placed = ref(false);
207
+ watch(ready, (ok) => {
208
+ placed.value = false;
209
+ if (ok) frameWindow().requestAnimationFrame(() => frameWindow().requestAnimationFrame(() => placed.value = true));
210
+ });
211
+ const live = computed(() => !placed.value || dragging.value !== null || scrubbing.value || pinching.value || wheeling.value || playing.value);
265
212
  const MIN_SPAN = 2;
266
213
  const view = ref({ start: 0, end: 0 });
267
214
  const span = computed(() => Math.max(1e-6, view.value.end - view.value.start));
@@ -277,33 +224,49 @@ const _sfc_main = /* @__PURE__ */ defineComponent({
277
224
  if (!box || !box.width) return 0;
278
225
  return view.value.start + (clientX - box.left) / box.width * span.value;
279
226
  }
280
- function zoomBy(factor, anchor = time.value) {
227
+ function zoomAnchor() {
228
+ const { start, end } = view.value;
229
+ return time.value >= start && time.value <= end ? time.value : (start + end) / 2;
230
+ }
231
+ function zoomBy(factor, anchor = zoomAnchor()) {
281
232
  if (!duration.value) return;
282
233
  view.value = zoomView(view.value, anchor, factor, duration.value, MIN_SPAN);
283
234
  }
284
235
  function fit() {
285
236
  view.value = { start: 0, end: duration.value };
286
237
  }
238
+ const wheeling = ref(false);
239
+ let wheelTimer;
240
+ function markWheel() {
241
+ wheeling.value = true;
242
+ clearTimeout(wheelTimer);
243
+ wheelTimer = setTimeout(() => wheeling.value = false, 160);
244
+ }
287
245
  function onWheel(event) {
288
246
  if (!ready.value) return;
289
247
  const dx = event.shiftKey ? event.deltaY : event.deltaX;
290
248
  if (Math.abs(dx) > Math.abs(event.deltaY) || event.shiftKey) {
291
249
  if (!zoomed.value) return;
292
250
  event.preventDefault();
251
+ markWheel();
293
252
  view.value = shiftView(view.value, dx / Math.max(1, trackWidth.value) * span.value, duration.value);
294
253
  return;
295
254
  }
296
255
  event.preventDefault();
297
256
  const unit = event.deltaMode === 1 ? 16 : event.deltaMode === 2 ? 400 : 1;
298
- zoomBy(Math.exp(-event.deltaY * unit / (event.ctrlKey ? 100 : 300)), timeAt(event.clientX));
257
+ const delta = event.deltaY * unit;
258
+ const notch = event.deltaMode !== 0 || !event.ctrlKey && Math.abs(delta) >= 50;
259
+ if (!notch) markWheel();
260
+ zoomBy(Math.exp(-delta / (event.ctrlKey ? 100 : 300)), timeAt(event.clientX));
299
261
  }
300
262
  const marks = computed(() => ready.value ? ticks(view.value, tickStep(span.value, trackWidth.value)) : []);
301
263
  const markDigits = computed(() => tickStep(span.value, trackWidth.value) < 1);
302
264
  const pointers = /* @__PURE__ */ new Map();
303
265
  let pinch = null;
266
+ const pinching = ref(false);
304
267
  let edgeFrame = 0;
305
268
  let lastX = 0;
306
- let scrubbing = false;
269
+ const scrubbing = ref(false);
307
270
  function onHandleDown(end, event) {
308
271
  if (off.value || event.button !== 0) return;
309
272
  event.stopPropagation();
@@ -320,7 +283,7 @@ const _sfc_main = /* @__PURE__ */ defineComponent({
320
283
  },
321
284
  end: () => {
322
285
  dragging.value = null;
323
- if (edgeFrame) cancelAnimationFrame(edgeFrame);
286
+ if (edgeFrame) frameWindow().cancelAnimationFrame(edgeFrame);
324
287
  edgeFrame = 0;
325
288
  emit("change", local.value);
326
289
  }
@@ -338,8 +301,8 @@ const _sfc_main = /* @__PURE__ */ defineComponent({
338
301
  const box = trackEl.value?.getBoundingClientRect();
339
302
  if (!box) return;
340
303
  const over = lastX < box.left ? lastX - box.left : lastX > box.right ? lastX - box.right : 0;
341
- if (!over || dragging.value === null && !scrubbing) return;
342
- edgeFrame = requestAnimationFrame(() => {
304
+ if (!over || dragging.value === null && !scrubbing.value) return;
305
+ edgeFrame = frameWindow().requestAnimationFrame(() => {
343
306
  edgeFrame = 0;
344
307
  view.value = shiftView(view.value, Math.max(-60, Math.min(60, over)) / 6 / Math.max(1, box.width) * span.value, duration.value);
345
308
  if (dragging.value !== null) moveHandle();
@@ -352,16 +315,17 @@ const _sfc_main = /* @__PURE__ */ defineComponent({
352
315
  event.currentTarget.setPointerCapture(event.pointerId);
353
316
  pointers.set(event.pointerId, event.clientX);
354
317
  if (pointers.size === 2) {
355
- scrubbing = false;
318
+ scrubbing.value = false;
356
319
  const [a, b] = [...pointers.values()];
357
320
  pinch = { distance: Math.max(8, Math.abs(a - b)), anchor: timeAt((a + b) / 2) };
321
+ pinching.value = true;
358
322
  return;
359
323
  }
360
324
  if (pointers.size > 2) return;
361
325
  event.preventDefault();
362
326
  trackEl.value?.querySelector("[data-lp-playhead]")?.focus({ preventScroll: true });
363
327
  pause();
364
- scrubbing = true;
328
+ scrubbing.value = true;
365
329
  lastX = event.clientX;
366
330
  seek(timeAt(event.clientX));
367
331
  }
@@ -375,15 +339,18 @@ const _sfc_main = /* @__PURE__ */ defineComponent({
375
339
  pinch.distance = distance;
376
340
  return;
377
341
  }
378
- if (!scrubbing) return;
342
+ if (!scrubbing.value) return;
379
343
  lastX = event.clientX;
380
344
  seek(timeAt(event.clientX));
381
345
  edgeScroll();
382
346
  }
383
347
  function onTrackUp(event) {
384
348
  pointers.delete(event.pointerId);
385
- if (pointers.size < 2) pinch = null;
386
- if (!pointers.size) scrubbing = false;
349
+ if (pointers.size < 2) {
350
+ pinch = null;
351
+ pinching.value = false;
352
+ }
353
+ if (!pointers.size) scrubbing.value = false;
387
354
  }
388
355
  function onOverviewDown(event) {
389
356
  if (off.value || event.button !== 0) return;
@@ -424,10 +391,39 @@ const _sfc_main = /* @__PURE__ */ defineComponent({
424
391
  sampler.want([...list].sort((a, b) => Math.abs(a.time - centre) - Math.abs(b.time - centre)));
425
392
  }, 120);
426
393
  });
427
- function mountFrame(key, el) {
394
+ function mountFrame(still, el) {
428
395
  if (!isHTMLElement(el)) return;
429
- const canvas = frames.value.get(key) ?? sampler?.cached(key);
430
- if (canvas && canvas.parentElement !== el) el.replaceChildren(canvas);
396
+ const canvas = frames.value.get(still.key) ?? sampler?.cached(still.key);
397
+ if (canvas) {
398
+ if (canvas.parentElement === el) return;
399
+ const standIns = [...el.children];
400
+ el.append(canvas);
401
+ if (!standIns.length || reduced.value) standIns.forEach((c) => c.remove());
402
+ else canvas.addEventListener("animationend", () => standIns.forEach((c) => c.remove()), { once: true });
403
+ return;
404
+ }
405
+ if (el.children.length) return;
406
+ const near = nearestFrame(still.time);
407
+ if (!near) return;
408
+ const copy2 = el.ownerDocument.createElement("canvas");
409
+ copy2.width = near.width;
410
+ copy2.height = near.height;
411
+ copy2.getContext("2d")?.drawImage(near, 0, 0);
412
+ copy2.dataset.lpStandIn = "";
413
+ el.append(copy2);
414
+ }
415
+ const frameTimes = /* @__PURE__ */ new Map();
416
+ function nearestFrame(t) {
417
+ let best;
418
+ let gap = Infinity;
419
+ for (const [key, canvas] of frames.value) {
420
+ const d = Math.abs((frameTimes.get(key) ?? Infinity) - t);
421
+ if (d < gap) {
422
+ gap = d;
423
+ best = canvas;
424
+ }
425
+ }
426
+ return best;
431
427
  }
432
428
  const picture = computed(() => containRect(stageSize.value.width, stageSize.value.height, videoSize.value.width, videoSize.value.height));
433
429
  const draft = ref(null);
@@ -478,6 +474,13 @@ const _sfc_main = /* @__PURE__ */ defineComponent({
478
474
  if (event.defaultPrevented || event.ctrlKey || event.metaKey || target.closest("input, textarea, select, [contenteditable='true']")) return;
479
475
  const handle = target.dataset.lpHandle;
480
476
  const end = handle === "0" ? 0 : handle === "1" ? 1 : null;
477
+ if (target.getAttribute("role") === "slider" && end === null && target.dataset.lpPlayhead === void 0) return;
478
+ if ((event.key === "m" || event.key === "M") && !event.altKey) {
479
+ if (!ready.value) return;
480
+ event.preventDefault();
481
+ toggleMute();
482
+ return;
483
+ }
481
484
  const big = event.shiftKey ? 1 : frameStep.value;
482
485
  const delta = { ArrowLeft: -big, ArrowRight: big, ArrowDown: -big, ArrowUp: big, PageDown: -10, PageUp: 10 };
483
486
  if (event.key === " " && target.tagName !== "BUTTON") {
@@ -506,7 +509,7 @@ const _sfc_main = /* @__PURE__ */ defineComponent({
506
509
  }
507
510
  const drafts = ref([null, null]);
508
511
  const invalid = ref([false, false]);
509
- const fieldText = (end) => drafts.value[end] ?? formatClipTime(local.value[end], true);
512
+ const fieldText = (end) => drafts.value[end] ?? formatClipTime(local.value[end], "fixed");
510
513
  function onFieldInput(end, value) {
511
514
  drafts.value[end] = value;
512
515
  invalid.value[end] = false;
@@ -533,6 +536,8 @@ const _sfc_main = /* @__PURE__ */ defineComponent({
533
536
  function startSampler() {
534
537
  sampler?.dispose();
535
538
  sampler = samplerEl.value ? new FrameSampler(samplerEl.value, () => ({ width: stillWidth.value, height: STILL_HEIGHT }), (key, canvas) => {
539
+ const still = stills.value.find((s) => s.key === key);
540
+ if (still) frameTimes.set(key, still.time);
536
541
  const next = new Map(frames.value);
537
542
  next.set(key, canvas);
538
543
  if (next.size > 240) next.delete(next.keys().next().value);
@@ -542,12 +547,7 @@ const _sfc_main = /* @__PURE__ */ defineComponent({
542
547
  watch(
543
548
  () => props.src,
544
549
  () => {
545
- duration.value = 0;
546
- failure.value = null;
547
- time.value = 0;
548
550
  frames.value = /* @__PURE__ */ new Map();
549
- seekBusy = false;
550
- seekTarget = null;
551
551
  void nextTick(startSampler);
552
552
  }
553
553
  );
@@ -555,13 +555,11 @@ const _sfc_main = /* @__PURE__ */ defineComponent({
555
555
  onBeforeUnmount(() => {
556
556
  sampler?.dispose();
557
557
  clearTimeout(stillTimer);
558
- if (frame) cancelAnimationFrame(frame);
559
- if (edgeFrame) cancelAnimationFrame(edgeFrame);
560
- for (const el of [videoEl.value, samplerEl.value]) {
561
- if (!el) continue;
562
- el.pause();
563
- el.removeAttribute("src");
564
- el.load();
558
+ if (edgeFrame) frameWindow().cancelAnimationFrame(edgeFrame);
559
+ const stillsEl = samplerEl.value;
560
+ if (stillsEl) {
561
+ stillsEl.removeAttribute("src");
562
+ stillsEl.load();
565
563
  }
566
564
  });
567
565
  __expose({
@@ -571,109 +569,211 @@ const _sfc_main = /* @__PURE__ */ defineComponent({
571
569
  /** The playhead, in seconds. */
572
570
  currentTime: () => time.value
573
571
  });
574
- const handleText = (t) => formatClipTime(t, true);
572
+ const { copy } = useClipboard();
573
+ const { error: toastError } = useToast();
574
+ const videoMenu = computed(() => {
575
+ if (!ready.value || props.disabled) return [];
576
+ const items = [
577
+ { label: wantsPlay.value ? text.value.pause : text.value.play, icon: wantsPlay.value ? "lucide:pause" : "lucide:play", shortcut: "Space", onSelect: togglePlay },
578
+ { label: muted.value ? text.value.unmute : text.value.mute, icon: muted.value ? "lucide:volume-2" : "lucide:volume-x", shortcut: "M", onSelect: toggleMute },
579
+ { label: text.value.stepBack, icon: "lucide:step-back", shortcut: "ArrowLeft", separatorBefore: true, onSelect: () => step(-frameStep.value) },
580
+ { label: text.value.stepForward, icon: "lucide:step-forward", shortcut: "ArrowRight", onSelect: () => step(frameStep.value) },
581
+ { label: text.value.copyTime, icon: "lucide:clock", separatorBefore: true, onSelect: () => void copy(formatClipTime(time.value, "fixed"), { toast: text.value.copiedTime, errorToast: text.value.copyFailed }) },
582
+ { label: text.value.copyFrame, icon: "lucide:image", onSelect: copyFrame }
583
+ ];
584
+ if (props.regionSelect && props.region) items.push({ label: text.value.regionClear, icon: "lucide:x", separatorBefore: true, onSelect: () => emit("update:region", null) });
585
+ return items;
586
+ });
587
+ const clockTitle = computed(() => text.value.menuAt.replace("{time}", formatClipTime(time.value, "fixed")));
588
+ async function copyFrame() {
589
+ const blob = await media.captureFrame();
590
+ if (blob) void copy(blob, { toast: text.value.copiedFrame, errorToast: text.value.copyFailed });
591
+ else toastError(text.value.copyFailed);
592
+ }
593
+ const menuAt = ref(0);
594
+ function onTimeContextMenu(event) {
595
+ const overview = event.target.closest?.("[data-lp-overview]");
596
+ if (overview) {
597
+ const box = overview.getBoundingClientRect();
598
+ menuAt.value = (event.clientX - box.left) / Math.max(1, box.width) * duration.value;
599
+ } else menuAt.value = timeAt(event.clientX);
600
+ menuAt.value = Math.min(duration.value, Math.max(0, menuAt.value));
601
+ }
602
+ const timeMenu = computed(() => {
603
+ if (!ready.value || props.disabled) return [];
604
+ const at = menuAt.value;
605
+ const items = [
606
+ {
607
+ label: text.value.setStart,
608
+ icon: "lucide:arrow-left-to-line",
609
+ shortcut: "I",
610
+ onSelect: () => {
611
+ put(setEnd(local.value, 0, at, limits.value), true);
612
+ seek(at);
613
+ }
614
+ },
615
+ {
616
+ label: text.value.setEnd,
617
+ icon: "lucide:arrow-right-to-line",
618
+ shortcut: "O",
619
+ onSelect: () => {
620
+ put(setEnd(local.value, 1, at, limits.value), true);
621
+ seek(at);
622
+ }
623
+ },
624
+ { label: text.value.goStart, separatorBefore: true, onSelect: () => seek(local.value[0]) },
625
+ { label: text.value.goEnd, onSelect: () => seek(local.value[1]) },
626
+ zoomed.value ? { label: text.value.zoomFit, icon: "lucide:maximize-2", separatorBefore: true, onSelect: fit } : { label: text.value.zoomHere, icon: "lucide:zoom-in", separatorBefore: true, disabled: !canZoomIn.value, onSelect: () => zoomBy(4, at) }
627
+ ];
628
+ const extra = props.menuItems?.(at) ?? [];
629
+ return [...items, ...extra.map((item, i) => i === 0 ? { ...item, separatorBefore: true } : item)];
630
+ });
631
+ const menuTitle = computed(() => text.value.menuAt.replace("{time}", formatClipTime(menuAt.value, "fixed")));
632
+ const handleText = (t) => formatClipTime(t, "fixed");
633
+ const widest = computed(() => widestClipTime(duration.value));
634
+ const leftOf = (left, max) => text.value.left.replace("{left}", left).replace("{max}", max);
575
635
  const leftText = computed(
576
- () => Number.isFinite(limits.value.maxClip) ? text.value.left.replace("{left}", formatClipTime(Math.max(0, limits.value.maxClip - clipLength.value), true)).replace("{max}", formatClipTime(limits.value.maxClip, true)) : ""
636
+ () => Number.isFinite(limits.value.maxClip) ? leftOf(formatClipTime(Math.max(0, limits.value.maxClip - clipLength.value), "fixed"), formatClipTime(limits.value.maxClip, "fixed")) : ""
577
637
  );
638
+ const widestLeft = computed(() => leftOf(widestClipTime(limits.value.maxClip), widestClipTime(limits.value.maxClip)));
578
639
  return (_ctx, _cache) => {
579
640
  return openBlock(), createElementBlock("div", mergeProps({ class: unref(rootClass) }, unref(rest), {
580
641
  "data-disabled": __props.disabled || void 0,
581
642
  onKeydown
582
643
  }), [
583
- createElementVNode("div", {
584
- ref_key: "stageEl",
585
- ref: stageEl,
586
- class: "relative aspect-video w-full overflow-hidden rounded-card bg-black"
587
- }, [
588
- createElementVNode("video", {
589
- ref_key: "videoEl",
590
- ref: videoEl,
591
- class: "absolute inset-0 size-full object-contain",
592
- src: __props.src,
593
- poster: __props.poster,
594
- preload: "metadata",
595
- playsinline: "",
596
- muted: muted.value,
597
- onLoadedmetadata: onMetadata,
598
- onDurationchange: onDurationChange,
599
- onSeeked,
600
- onPlay,
601
- onPause,
602
- onError,
603
- onClick: _cache[0] || (_cache[0] = ($event) => !__props.regionSelect && togglePlay())
604
- }, null, 40, _hoisted_2),
605
- createElementVNode("video", {
606
- ref_key: "samplerEl",
607
- ref: samplerEl,
608
- class: "pointer-events-none absolute size-px opacity-0",
609
- src: __props.src,
610
- preload: "metadata",
611
- muted: "",
612
- playsinline: "",
613
- "aria-hidden": "true",
614
- tabindex: "-1"
615
- }, null, 8, _hoisted_3),
616
- __props.regionSelect && ready.value ? (openBlock(), createElementBlock("div", {
617
- key: 0,
618
- class: "absolute cursor-crosshair touch-none",
619
- style: normalizeStyle({ left: `${picture.value.x}px`, top: `${picture.value.y}px`, width: `${picture.value.width}px`, height: `${picture.value.height}px` }),
620
- "data-lp-region-layer": "",
621
- onPointerdown: _cache[2] || (_cache[2] = ($event) => onRegionDown("draw", $event))
622
- }, [
623
- shownRegion.value ? (openBlock(), createElementBlock("div", {
624
- key: 0,
625
- class: "absolute cursor-move rounded-inner border-2 border-dashed border-white bg-brand/25 shadow-[0_0_0_9999px_rgb(0_0_0/0.35)] outline-none focus-visible:ring-2 focus-visible:ring-ring",
626
- style: normalizeStyle({ left: `${shownRegion.value.x * 100}%`, top: `${shownRegion.value.y * 100}%`, width: `${shownRegion.value.w * 100}%`, height: `${shownRegion.value.h * 100}%` }),
627
- tabindex: "0",
628
- role: "group",
629
- "aria-label": unref(text).region,
630
- "data-lp-region": "",
631
- onPointerdown: _cache[1] || (_cache[1] = ($event) => onRegionDown("move", $event)),
632
- onKeydown: onRegionKey
633
- }, [
634
- (openBlock(), createElementBlock(Fragment, null, renderList(["nw", "ne", "sw", "se"], (corner) => {
635
- return createElementVNode("span", {
636
- key: corner,
637
- class: normalizeClass(["absolute grid size-6 place-items-center pointer-coarse:size-11", [
638
- corner[0] === "n" ? "top-0 -translate-y-1/2" : "bottom-0 translate-y-1/2",
639
- corner[1] === "w" ? "left-0 -translate-x-1/2" : "right-0 translate-x-1/2",
640
- corner === "nw" || corner === "se" ? "cursor-nwse-resize" : "cursor-nesw-resize"
641
- ]]),
642
- "data-lp-corner": corner,
643
- onPointerdown: ($event) => onRegionDown(corner, $event)
644
- }, [..._cache[8] || (_cache[8] = [
645
- createElementVNode("span", { class: "size-3 rounded-pill border-2 border-white bg-brand shadow" }, null, -1)
646
- ])], 42, _hoisted_5);
647
- }), 64))
648
- ], 44, _hoisted_4)) : createCommentVNode("", true)
649
- ], 36)) : createCommentVNode("", true),
650
- failure.value ? (openBlock(), createElementBlock("div", _hoisted_6, [
651
- createVNode(_sfc_main$1, {
652
- name: "lucide:video-off",
653
- size: 32
654
- }),
655
- createElementVNode("p", null, toDisplayString(failure.value === "unsupported" ? unref(text).unsupported : unref(text).failed), 1)
656
- ])) : createCommentVNode("", true)
657
- ], 512),
658
- createElementVNode("div", _hoisted_7, [
659
- createVNode(_sfc_main$2, {
644
+ createVNode(_sfc_main$1, {
645
+ items: videoMenu.value,
646
+ title: clockTitle.value,
647
+ always: ""
648
+ }, {
649
+ default: withCtx(() => [
650
+ createElementVNode("div", null, [
651
+ createElementVNode("div", {
652
+ ref_key: "stageEl",
653
+ ref: stageEl,
654
+ class: "relative aspect-video w-full overflow-hidden rounded-card bg-black"
655
+ }, [
656
+ createElementVNode("video", mergeProps({
657
+ ref_key: "videoEl",
658
+ ref: videoEl,
659
+ class: "absolute inset-0 size-full object-contain",
660
+ src: __props.src,
661
+ poster: __props.poster,
662
+ preload: "metadata",
663
+ playsinline: ""
664
+ }, toHandlers(unref(media).listeners, true), {
665
+ onClick: _cache[0] || (_cache[0] = ($event) => !__props.regionSelect && togglePlay())
666
+ }), null, 16, _hoisted_2),
667
+ createVNode(VideoFlash, { flash: flash.value }, null, 8, ["flash"]),
668
+ createElementVNode("video", {
669
+ ref_key: "samplerEl",
670
+ ref: samplerEl,
671
+ class: "pointer-events-none absolute size-px opacity-0",
672
+ src: __props.src,
673
+ preload: "metadata",
674
+ muted: "",
675
+ playsinline: "",
676
+ "aria-hidden": "true",
677
+ tabindex: "-1"
678
+ }, null, 8, _hoisted_3),
679
+ createVNode(Transition, normalizeProps(guardReactiveProps(unref(FADE))), {
680
+ default: withCtx(() => [
681
+ __props.regionSelect && ready.value ? (openBlock(), createElementBlock("div", {
682
+ key: 0,
683
+ class: "absolute cursor-crosshair touch-none",
684
+ style: normalizeStyle({ left: `${picture.value.x}px`, top: `${picture.value.y}px`, width: `${picture.value.width}px`, height: `${picture.value.height}px` }),
685
+ "data-lp-region-layer": "",
686
+ onPointerdown: _cache[2] || (_cache[2] = ($event) => onRegionDown("draw", $event))
687
+ }, [
688
+ createVNode(Transition, mergeProps(unref(FADE_SCALE), {
689
+ "enter-from-class": draft.value ? "opacity-0" : unref(FADE_SCALE).enterFromClass
690
+ }), {
691
+ default: withCtx(() => [
692
+ shownRegion.value ? (openBlock(), createElementBlock("div", {
693
+ key: 0,
694
+ class: "absolute cursor-move rounded-inner border-2 border-dashed border-white/90 bg-white/10 shadow-[0_0_0_9999px_rgb(0_0_0/0.35)] outline-none transition-[left,top,width,height] duration-(--duration-medium) ease-(--ease-emphasized) focus-visible:ring-2 focus-visible:ring-ring data-[live]:transition-none motion-reduce:transition-none",
695
+ "data-live": draft.value ? "" : void 0,
696
+ style: normalizeStyle({ left: `${shownRegion.value.x * 100}%`, top: `${shownRegion.value.y * 100}%`, width: `${shownRegion.value.w * 100}%`, height: `${shownRegion.value.h * 100}%` }),
697
+ tabindex: "0",
698
+ role: "group",
699
+ "aria-label": unref(text).region,
700
+ "data-lp-region": "",
701
+ onPointerdown: _cache[1] || (_cache[1] = ($event) => onRegionDown("move", $event)),
702
+ onKeydown: onRegionKey
703
+ }, [
704
+ (openBlock(), createElementBlock(Fragment, null, renderList(["nw", "ne", "sw", "se"], (corner) => {
705
+ return createElementVNode("span", {
706
+ key: corner,
707
+ class: normalizeClass(["absolute grid size-6 place-items-center pointer-coarse:size-11", [
708
+ corner[0] === "n" ? "top-0 -translate-y-1/2" : "bottom-0 translate-y-1/2",
709
+ corner[1] === "w" ? "left-0 -translate-x-1/2" : "right-0 translate-x-1/2",
710
+ corner === "nw" || corner === "se" ? "cursor-nwse-resize" : "cursor-nesw-resize"
711
+ ]]),
712
+ "data-lp-corner": corner,
713
+ onPointerdown: ($event) => onRegionDown(corner, $event)
714
+ }, [..._cache[8] || (_cache[8] = [
715
+ createElementVNode("span", { class: "size-3 rounded-full bg-white shadow-[0_0_0_1px_rgb(0_0_0/0.3),0_1px_3px_rgb(0_0_0/0.35)]" }, null, -1)
716
+ ])], 42, _hoisted_5);
717
+ }), 64))
718
+ ], 44, _hoisted_4)) : createCommentVNode("", true)
719
+ ]),
720
+ _: 1
721
+ }, 16, ["enter-from-class"])
722
+ ], 36)) : createCommentVNode("", true)
723
+ ]),
724
+ _: 1
725
+ }, 16),
726
+ createVNode(Transition, normalizeProps(guardReactiveProps(unref(FADE))), {
727
+ default: withCtx(() => [
728
+ __props.regionSelect && ready.value && !shownRegion.value && !unref(playing) && !__props.disabled ? (openBlock(), createElementBlock("span", _hoisted_6, toDisplayString(unref(text).regionHint), 1)) : createCommentVNode("", true)
729
+ ]),
730
+ _: 1
731
+ }, 16),
732
+ _ctx.$slots.actions ? (openBlock(), createElementBlock("div", _hoisted_7, [
733
+ renderSlot(_ctx.$slots, "actions", { buttonClass: unref(OVERLAY_BUTTON) }, void 0, true)
734
+ ])) : createCommentVNode("", true),
735
+ createVNode(Transition, normalizeProps(guardReactiveProps(unref(FADE))), {
736
+ default: withCtx(() => [
737
+ unref(failure) ? (openBlock(), createElementBlock("div", _hoisted_8, [
738
+ createVNode(_sfc_main$2, {
739
+ name: "lucide:video-off",
740
+ size: 32
741
+ }),
742
+ createElementVNode("p", null, toDisplayString(unref(failure) === "unsupported" ? unref(text).unsupported : unref(text).failed), 1)
743
+ ])) : createCommentVNode("", true)
744
+ ]),
745
+ _: 1
746
+ }, 16)
747
+ ], 512)
748
+ ])
749
+ ]),
750
+ _: 3
751
+ }, 8, ["items", "title"]),
752
+ createElementVNode("div", _hoisted_9, [
753
+ createVNode(_sfc_main$3, {
660
754
  size: "sm",
661
755
  variant: "ghost",
662
756
  square: "",
663
757
  disabled: off.value,
664
- "aria-label": playing.value ? unref(text).pause : unref(text).play,
665
- title: playing.value ? unref(text).pause : unref(text).play,
758
+ "aria-label": unref(wantsPlay) ? unref(text).pause : unref(text).play,
759
+ title: unref(wantsPlay) ? unref(text).pause : unref(text).play,
666
760
  onClick: togglePlay
667
761
  }, {
668
762
  default: withCtx(() => [
669
- createVNode(_sfc_main$1, {
670
- name: playing.value ? "lucide:pause" : "lucide:play",
671
- size: 16
672
- }, null, 8, ["name"])
763
+ createVNode(Transition, normalizeProps(guardReactiveProps(unref(ICON_SWAP))), {
764
+ default: withCtx(() => [
765
+ (openBlock(), createBlock(_sfc_main$2, {
766
+ key: unref(wantsPlay) ? "pause" : "play",
767
+ name: unref(wantsPlay) ? "lucide:pause" : "lucide:play",
768
+ size: 16
769
+ }, null, 8, ["name"]))
770
+ ]),
771
+ _: 1
772
+ }, 16)
673
773
  ]),
674
774
  _: 1
675
775
  }, 8, ["disabled", "aria-label", "title"]),
676
- createVNode(_sfc_main$2, {
776
+ createVNode(_sfc_main$3, {
677
777
  size: "sm",
678
778
  variant: "ghost",
679
779
  square: "",
@@ -683,14 +783,14 @@ const _sfc_main = /* @__PURE__ */ defineComponent({
683
783
  onClick: _cache[3] || (_cache[3] = ($event) => step(-frameStep.value))
684
784
  }, {
685
785
  default: withCtx(() => [
686
- createVNode(_sfc_main$1, {
786
+ createVNode(_sfc_main$2, {
687
787
  name: "lucide:step-back",
688
788
  size: 16
689
789
  })
690
790
  ]),
691
791
  _: 1
692
792
  }, 8, ["disabled", "aria-label", "title"]),
693
- createVNode(_sfc_main$2, {
793
+ createVNode(_sfc_main$3, {
694
794
  size: "sm",
695
795
  variant: "ghost",
696
796
  square: "",
@@ -700,37 +800,51 @@ const _sfc_main = /* @__PURE__ */ defineComponent({
700
800
  onClick: _cache[4] || (_cache[4] = ($event) => step(frameStep.value))
701
801
  }, {
702
802
  default: withCtx(() => [
703
- createVNode(_sfc_main$1, {
803
+ createVNode(_sfc_main$2, {
704
804
  name: "lucide:step-forward",
705
805
  size: 16
706
806
  })
707
807
  ]),
708
808
  _: 1
709
809
  }, 8, ["disabled", "aria-label", "title"]),
710
- createElementVNode("span", _hoisted_8, [
711
- createElementVNode("span", _hoisted_9, toDisplayString(unref(formatClipTime)(time.value, true)), 1),
712
- createTextVNode(" / " + toDisplayString(unref(formatClipTime)(duration.value, true)), 1)
810
+ createElementVNode("span", _hoisted_10, [
811
+ createVNode(_sfc_main$4, {
812
+ class: "text-ink",
813
+ text: unref(formatClipTime)(unref(time), "fixed"),
814
+ widest: widest.value
815
+ }, null, 8, ["text", "widest"]),
816
+ createTextVNode(" / " + toDisplayString(unref(formatClipTime)(unref(duration), "fixed")), 1)
713
817
  ]),
714
- createVNode(_sfc_main$2, {
715
- size: "sm",
716
- variant: "ghost",
717
- square: "",
718
- disabled: !ready.value,
719
- "aria-label": muted.value ? unref(text).unmute : unref(text).mute,
720
- title: muted.value ? unref(text).unmute : unref(text).mute,
721
- "aria-pressed": muted.value,
722
- onClick: toggleMute
723
- }, {
818
+ createVNode(_sfc_main$5, {
819
+ media: unref(media),
820
+ labels: unref(text),
821
+ disabled: !ready.value
822
+ }, null, 8, ["media", "labels", "disabled"]),
823
+ _cache[9] || (_cache[9] = createElementVNode("span", { class: "flex-1" }, null, -1)),
824
+ createVNode(Transition, normalizeProps(guardReactiveProps(unref(FADE_SCALE))), {
724
825
  default: withCtx(() => [
725
- createVNode(_sfc_main$1, {
726
- name: muted.value ? "lucide:volume-x" : "lucide:volume-2",
727
- size: 16
728
- }, null, 8, ["name"])
826
+ zoomed.value ? (openBlock(), createBlock(_sfc_main$3, {
827
+ key: 0,
828
+ size: "sm",
829
+ variant: "ghost",
830
+ square: "",
831
+ disabled: off.value,
832
+ "aria-label": unref(text).zoomFit,
833
+ title: unref(text).zoomFit,
834
+ onClick: fit
835
+ }, {
836
+ default: withCtx(() => [
837
+ createVNode(_sfc_main$2, {
838
+ name: "lucide:maximize-2",
839
+ size: 16
840
+ })
841
+ ]),
842
+ _: 1
843
+ }, 8, ["disabled", "aria-label", "title"])) : createCommentVNode("", true)
729
844
  ]),
730
845
  _: 1
731
- }, 8, ["disabled", "aria-label", "title", "aria-pressed"]),
732
- _cache[9] || (_cache[9] = createElementVNode("span", { class: "flex-1" }, null, -1)),
733
- createVNode(_sfc_main$2, {
846
+ }, 16),
847
+ createVNode(_sfc_main$3, {
734
848
  size: "sm",
735
849
  variant: "ghost",
736
850
  square: "",
@@ -740,14 +854,14 @@ const _sfc_main = /* @__PURE__ */ defineComponent({
740
854
  onClick: _cache[5] || (_cache[5] = ($event) => zoomBy(0.5))
741
855
  }, {
742
856
  default: withCtx(() => [
743
- createVNode(_sfc_main$1, {
857
+ createVNode(_sfc_main$2, {
744
858
  name: "lucide:zoom-out",
745
859
  size: 16
746
860
  })
747
861
  ]),
748
862
  _: 1
749
863
  }, 8, ["disabled", "aria-label", "title"]),
750
- createVNode(_sfc_main$2, {
864
+ createVNode(_sfc_main$3, {
751
865
  size: "sm",
752
866
  variant: "ghost",
753
867
  square: "",
@@ -757,199 +871,236 @@ const _sfc_main = /* @__PURE__ */ defineComponent({
757
871
  onClick: _cache[6] || (_cache[6] = ($event) => zoomBy(2))
758
872
  }, {
759
873
  default: withCtx(() => [
760
- createVNode(_sfc_main$1, {
874
+ createVNode(_sfc_main$2, {
761
875
  name: "lucide:zoom-in",
762
876
  size: 16
763
877
  })
764
878
  ]),
765
879
  _: 1
766
- }, 8, ["disabled", "aria-label", "title"]),
767
- createVNode(_sfc_main$2, {
768
- size: "sm",
769
- variant: "ghost",
770
- square: "",
771
- disabled: off.value || !zoomed.value,
772
- "aria-label": unref(text).zoomFit,
773
- title: unref(text).zoomFit,
774
- onClick: fit
775
- }, {
776
- default: withCtx(() => [
777
- createVNode(_sfc_main$1, {
778
- name: "lucide:maximize-2",
779
- size: 16
780
- })
781
- ]),
782
- _: 1
783
880
  }, 8, ["disabled", "aria-label", "title"])
784
881
  ]),
785
- createElementVNode("div", {
786
- class: "relative",
787
- onWheel
788
- }, [
789
- createElementVNode("div", _hoisted_10, [
790
- (openBlock(true), createElementBlock(Fragment, null, renderList(marks.value, (m) => {
791
- return openBlock(), createElementBlock("span", {
792
- key: m,
793
- class: normalizeClass(["absolute top-0 whitespace-nowrap", xOf(m) < 16 ? "" : xOf(m) > trackWidth.value - 16 ? "-translate-x-full" : "-translate-x-1/2"]),
794
- style: normalizeStyle({ left: pct(m) })
795
- }, toDisplayString(unref(formatClipTime)(m, markDigits.value)), 7);
796
- }), 128))
797
- ]),
798
- createElementVNode("div", {
799
- ref_key: "trackEl",
800
- ref: trackEl,
801
- class: normalizeClass(["relative h-14 touch-none rounded-control bg-surface-soft", off.value ? "opacity-60" : "cursor-text"]),
802
- "aria-label": unref(text).timeline,
803
- role: "group",
804
- onPointerdown: onTrackDown,
805
- onPointermove: onTrackMove,
806
- onPointerup: onTrackUp,
807
- onPointercancel: onTrackUp
808
- }, [
809
- createElementVNode("div", _hoisted_12, [
810
- (openBlock(true), createElementBlock(Fragment, null, renderList(stills.value, (s) => {
811
- return openBlock(), createElementBlock("div", {
812
- key: s.key,
813
- ref_for: true,
814
- ref: (el) => mountFrame(s.key, el),
815
- class: normalizeClass(["lp-trim-still absolute inset-y-0 overflow-hidden border-r border-black/20 [&>canvas]:size-full [&>canvas]:object-cover", { "lp-trim-still-in": !unref(reduced) }]),
816
- style: normalizeStyle({ left: s.left, width: s.width }),
817
- "data-lp-still": frames.value.has(s.key) ? "ready" : "pending"
818
- }, null, 14, _hoisted_13);
819
- }), 128)),
820
- createElementVNode("div", {
821
- class: "absolute inset-y-0 left-0 bg-black/55",
822
- style: normalizeStyle({ width: `${Math.max(0, xOf(local.value[0]))}px` })
823
- }, null, 4),
882
+ createVNode(_sfc_main$1, {
883
+ items: timeMenu.value,
884
+ title: menuTitle.value,
885
+ always: ""
886
+ }, {
887
+ default: withCtx(() => [
888
+ createElementVNode("div", {
889
+ class: normalizeClass(["relative", TRACK_GLIDE]),
890
+ "data-live": live.value || void 0,
891
+ onWheel,
892
+ onContextmenu: onTimeContextMenu
893
+ }, [
894
+ createVNode(TransitionGroup, mergeProps({
895
+ tag: "div",
896
+ class: "relative h-4 overflow-hidden text-[10px] text-muted tabular-nums",
897
+ "aria-hidden": "true"
898
+ }, unref(FADE)), {
899
+ default: withCtx(() => [
900
+ (openBlock(true), createElementBlock(Fragment, null, renderList(marks.value, (m) => {
901
+ return openBlock(), createElementBlock("span", {
902
+ key: m,
903
+ class: normalizeClass(["absolute top-0 whitespace-nowrap", xOf(m) < 16 ? "" : xOf(m) > trackWidth.value - 16 ? "-translate-x-full" : "-translate-x-1/2"]),
904
+ style: normalizeStyle({ left: pct(m) }),
905
+ "data-glide": ""
906
+ }, toDisplayString(unref(formatClipTime)(m, markDigits.value)), 7);
907
+ }), 128))
908
+ ]),
909
+ _: 1
910
+ }, 16),
824
911
  createElementVNode("div", {
825
- class: "absolute inset-y-0 right-0 bg-black/55",
826
- style: normalizeStyle({ left: `${Math.min(trackWidth.value, Math.max(0, xOf(local.value[1])))}px` })
827
- }, null, 4)
828
- ]),
829
- ready.value ? (openBlock(), createElementBlock("div", {
830
- key: 0,
831
- class: "pointer-events-none absolute inset-y-0 border-y-2 border-brand",
832
- style: normalizeStyle({ left: pct(local.value[0]), width: `${clipLength.value / span.value * 100}%` }),
833
- "data-lp-range": ""
834
- }, null, 4)) : createCommentVNode("", true),
835
- (openBlock(), createElementBlock(Fragment, null, renderList([0, 1], (end) => {
836
- return withDirectives(createElementVNode("div", {
837
- key: end,
838
- class: normalizeClass(["group/handle absolute inset-y-0 z-10 flex w-6 touch-none items-stretch outline-none pointer-coarse:w-11", [end === 0 ? "justify-start" : "-translate-x-full justify-end", off.value ? "" : "cursor-ew-resize"]]),
839
- style: normalizeStyle({ left: pct(local.value[end]) }),
840
- role: "slider",
841
- tabindex: off.value ? -1 : 0,
842
- "aria-label": end === 0 ? unref(text).start : unref(text).end,
843
- "aria-valuemin": 0,
844
- "aria-valuemax": Math.round(duration.value * 1e3) / 1e3,
845
- "aria-valuenow": local.value[end],
846
- "aria-valuetext": handleText(local.value[end]),
847
- "aria-disabled": off.value || void 0,
848
- "data-lp-handle": end,
849
- onPointerdown: ($event) => onHandleDown(end, $event)
912
+ ref_key: "trackEl",
913
+ ref: trackEl,
914
+ class: normalizeClass(["relative h-14 touch-none rounded-control bg-surface-soft transition-opacity duration-(--duration-fast) motion-reduce:transition-none", off.value ? "opacity-60" : "cursor-text"]),
915
+ "aria-label": unref(text).timeline,
916
+ role: "group",
917
+ onPointerdown: onTrackDown,
918
+ onPointermove: onTrackMove,
919
+ onPointerup: onTrackUp,
920
+ onPointercancel: onTrackUp
850
921
  }, [
851
- createElementVNode("span", {
852
- class: normalizeClass(["flex w-3 items-center justify-center bg-brand transition-[width] duration-(--duration-fast) group-focus-visible/handle:ring-2 group-focus-visible/handle:ring-ring motion-reduce:transition-none", end === 0 ? "rounded-l-control" : "rounded-r-control"])
853
- }, [..._cache[10] || (_cache[10] = [
854
- createElementVNode("span", { class: "h-5 w-0.5 rounded-pill bg-white/85" }, null, -1)
855
- ])], 2)
856
- ], 46, _hoisted_14), [
857
- [vShow, ready.value]
858
- ]);
859
- }), 64)),
860
- withDirectives(createElementVNode("div", {
861
- class: "absolute -top-4 bottom-0 z-20 w-0 outline-none",
862
- style: normalizeStyle({ left: pct(time.value) }),
863
- role: "slider",
864
- tabindex: off.value ? -1 : 0,
865
- "aria-label": unref(text).position,
866
- "aria-valuemin": 0,
867
- "aria-valuemax": Math.round(duration.value * 1e3) / 1e3,
868
- "aria-valuenow": Math.round(time.value * 1e3) / 1e3,
869
- "aria-valuetext": handleText(time.value),
870
- "data-lp-playhead": ""
871
- }, [..._cache[11] || (_cache[11] = [
872
- createElementVNode("span", { class: "pointer-events-none absolute inset-y-0 -left-px w-0.5 bg-white shadow-[0_0_0_1px_rgb(0_0_0/0.45)]" }, null, -1),
873
- createElementVNode("span", { class: "pointer-events-none absolute -top-0.5 -left-1.5 size-3 rounded-pill border-2 border-white bg-ink shadow [[data-lp-playhead]:focus-visible_&]:ring-2 [[data-lp-playhead]:focus-visible_&]:ring-ring" }, null, -1)
874
- ])], 12, _hoisted_15), [
875
- [vShow, ready.value && time.value >= view.value.start && time.value <= view.value.end]
876
- ])
877
- ], 42, _hoisted_11),
878
- zoomed.value ? (openBlock(), createElementBlock("div", {
879
- key: 0,
880
- class: "relative mt-1.5 h-2 cursor-pointer touch-none rounded-pill bg-surface-soft",
881
- "aria-label": unref(text).overview,
882
- role: "presentation",
883
- "data-lp-overview": "",
884
- onPointerdown: onOverviewDown
885
- }, [
886
- createElementVNode("span", {
887
- class: "absolute inset-y-0 rounded-pill bg-brand/45",
888
- style: normalizeStyle({ left: `${local.value[0] / duration.value * 100}%`, width: `${clipLength.value / duration.value * 100}%` })
889
- }, null, 4),
890
- createElementVNode("span", {
891
- class: "absolute -inset-y-0.5 rounded-pill border-2 border-ink/70",
892
- style: normalizeStyle({ left: `${view.value.start / duration.value * 100}%`, width: `${span.value / duration.value * 100}%` })
893
- }, null, 4)
894
- ], 40, _hoisted_16)) : createCommentVNode("", true)
895
- ], 32),
896
- createElementVNode("div", _hoisted_17, [
922
+ createElementVNode("div", _hoisted_13, [
923
+ createVNode(TransitionGroup, normalizeProps(guardReactiveProps(unref(FADE))), {
924
+ default: withCtx(() => [
925
+ (openBlock(true), createElementBlock(Fragment, null, renderList(stills.value, (s) => {
926
+ return openBlock(), createElementBlock("div", {
927
+ key: s.key,
928
+ ref_for: true,
929
+ ref: (el) => mountFrame(s, el),
930
+ class: normalizeClass(["absolute inset-y-0 overflow-hidden [&>canvas]:absolute [&>canvas]:inset-0 [&>canvas]:size-full [&>canvas]:object-cover", { "lp-trim-still-in": !unref(reduced) }]),
931
+ style: normalizeStyle({ left: s.left, width: s.width }),
932
+ "data-lp-still": frames.value.has(s.key) ? "ready" : "pending",
933
+ "data-glide": ""
934
+ }, null, 14, _hoisted_14);
935
+ }), 128))
936
+ ]),
937
+ _: 1
938
+ }, 16),
939
+ createElementVNode("div", {
940
+ class: "absolute inset-y-0 left-0 bg-black/55",
941
+ style: normalizeStyle({ width: pct(local.value[0]) }),
942
+ "data-glide": ""
943
+ }, null, 4),
944
+ createElementVNode("div", {
945
+ class: "absolute inset-y-0 right-0 bg-black/55",
946
+ style: normalizeStyle({ left: pct(local.value[1]) }),
947
+ "data-glide": ""
948
+ }, null, 4)
949
+ ]),
950
+ createElementVNode("div", {
951
+ class: normalizeClass(["pointer-events-none absolute inset-0 transition-opacity duration-(--duration-medium) ease-(--ease-emphasized) motion-reduce:transition-none", ready.value ? "" : "opacity-0"])
952
+ }, [
953
+ createElementVNode("div", {
954
+ class: "absolute inset-y-0 rounded-control border-y-2 border-white/85 shadow-[0_0_0_1px_rgb(0_0_0/0.25)]",
955
+ style: normalizeStyle({ left: pct(local.value[0]), width: `${clipLength.value / span.value * 100}%` }),
956
+ "data-lp-range": "",
957
+ "data-glide": ""
958
+ }, null, 4),
959
+ (openBlock(), createElementBlock(Fragment, null, renderList([0, 1], (end) => {
960
+ return createElementVNode("div", {
961
+ key: end,
962
+ class: normalizeClass(["group/handle absolute inset-y-0 z-10 flex w-6 -translate-x-1/2 touch-none justify-center outline-none pointer-coarse:w-11", [off.value ? "" : "cursor-ew-resize", ready.value ? "pointer-events-auto" : ""]]),
963
+ style: normalizeStyle({ left: pct(local.value[end]) }),
964
+ role: "slider",
965
+ tabindex: off.value ? -1 : 0,
966
+ "aria-label": end === 0 ? unref(text).start : unref(text).end,
967
+ "aria-valuemin": 0,
968
+ "aria-valuemax": Math.round(unref(duration) * 1e3) / 1e3,
969
+ "aria-valuenow": local.value[end],
970
+ "aria-valuetext": handleText(local.value[end]),
971
+ "aria-disabled": off.value || void 0,
972
+ "aria-hidden": ready.value ? void 0 : "true",
973
+ "data-lp-handle": end,
974
+ "data-active": dragging.value === end || void 0,
975
+ "data-glide": "",
976
+ onPointerdown: ($event) => onHandleDown(end, $event)
977
+ }, [..._cache[10] || (_cache[10] = [
978
+ createElementVNode("span", { class: "my-1 flex w-2 items-center justify-center rounded-inner bg-white/90 shadow-[0_0_0_1px_rgb(0_0_0/0.3),0_1px_3px_rgb(0_0_0/0.35)] transition-[background-color,scale] duration-(--duration-fast) ease-(--ease-emphasized) group-hover/handle:bg-white group-data-active/handle:scale-x-125 group-data-active/handle:bg-white group-focus-visible/handle:ring-2 group-focus-visible/handle:ring-ring motion-reduce:transition-none motion-reduce:group-data-active/handle:scale-x-100" }, [
979
+ createElementVNode("span", { class: "h-4 w-px rounded-pill bg-black/35" })
980
+ ], -1)
981
+ ])], 46, _hoisted_15);
982
+ }), 64))
983
+ ], 2),
984
+ createElementVNode("div", {
985
+ class: "group/playhead absolute -top-4 bottom-0 z-20 w-0 outline-none",
986
+ style: normalizeStyle({ left: pct(unref(time)) }),
987
+ role: "slider",
988
+ tabindex: off.value ? -1 : 0,
989
+ "aria-label": unref(text).position,
990
+ "aria-valuemin": 0,
991
+ "aria-valuemax": Math.round(unref(duration) * 1e3) / 1e3,
992
+ "aria-valuenow": Math.round(unref(time) * 1e3) / 1e3,
993
+ "aria-valuetext": handleText(unref(time)),
994
+ "data-lp-playhead": "",
995
+ "data-glide": unref(playing) ? void 0 : ""
996
+ }, [
997
+ createElementVNode("span", {
998
+ class: normalizeClass(["pointer-events-none absolute inset-0 transition-opacity duration-(--duration-fast) motion-reduce:transition-none", ready.value && unref(time) >= view.value.start && unref(time) <= view.value.end ? "" : "opacity-0"])
999
+ }, [..._cache[11] || (_cache[11] = [
1000
+ createElementVNode("span", { class: "absolute inset-y-0 -left-px w-0.5 rounded-pill bg-white shadow-[0_0_0_1px_rgb(0_0_0/0.35)]" }, null, -1),
1001
+ createElementVNode("span", { class: "absolute -top-0.5 -left-1.5 size-3 rounded-full bg-white shadow-[0_0_0_1px_rgb(0_0_0/0.3),0_1px_3px_rgb(0_0_0/0.35)] group-focus-visible/playhead:ring-2 group-focus-visible/playhead:ring-ring" }, null, -1)
1002
+ ])], 2)
1003
+ ], 12, _hoisted_16)
1004
+ ], 42, _hoisted_12),
1005
+ createVNode(Transition, normalizeProps(guardReactiveProps(unref(FADE))), {
1006
+ default: withCtx(() => [
1007
+ zoomed.value ? (openBlock(), createElementBlock("div", {
1008
+ key: 0,
1009
+ class: "relative mt-1.5 h-2.5 cursor-pointer touch-none rounded-pill bg-surface-soft",
1010
+ "aria-label": unref(text).overview,
1011
+ role: "presentation",
1012
+ "data-lp-overview": "",
1013
+ onPointerdown: onOverviewDown
1014
+ }, [
1015
+ createElementVNode("span", {
1016
+ class: "absolute inset-y-0.5 rounded-pill bg-line-strong",
1017
+ style: normalizeStyle({ left: `${local.value[0] / unref(duration) * 100}%`, width: `${clipLength.value / unref(duration) * 100}%` }),
1018
+ "data-glide": ""
1019
+ }, null, 4),
1020
+ createElementVNode("span", {
1021
+ class: "absolute inset-y-0 rounded-pill border border-ink/60",
1022
+ style: normalizeStyle({ left: `${view.value.start / unref(duration) * 100}%`, width: `${span.value / unref(duration) * 100}%` }),
1023
+ "data-glide": ""
1024
+ }, null, 4)
1025
+ ], 40, _hoisted_17)) : createCommentVNode("", true)
1026
+ ]),
1027
+ _: 1
1028
+ }, 16)
1029
+ ], 40, _hoisted_11)
1030
+ ]),
1031
+ _: 1
1032
+ }, 8, ["items", "title"]),
1033
+ createElementVNode("div", _hoisted_18, [
897
1034
  (openBlock(), createElementBlock(Fragment, null, renderList([0, 1], (end) => {
898
- return createElementVNode("label", {
1035
+ return createVNode(_sfc_main$6, {
899
1036
  key: end,
900
- class: "flex flex-col gap-1"
901
- }, [
902
- createElementVNode("span", _hoisted_18, toDisplayString(end === 0 ? unref(text).start : unref(text).end), 1),
903
- createVNode(_sfc_main$3, {
904
- size: "sm",
905
- class: "w-28 font-mono tabular-nums",
906
- "model-value": fieldText(end),
907
- disabled: off.value,
908
- invalid: invalid.value[end],
909
- title: invalid.value[end] ? unref(text).invalidTime : void 0,
910
- inputmode: "decimal",
911
- spellcheck: "false",
912
- autocomplete: "off",
913
- "data-lp-time": end,
914
- "onUpdate:modelValue": ($event) => onFieldInput(end, $event),
915
- onBlur: ($event) => commitField(end),
916
- onKeydown: [
917
- withKeys(withModifiers(($event) => commitField(end), ["prevent"]), ["enter"]),
918
- withKeys(($event) => revertField(end), ["esc"])
919
- ]
920
- }, null, 8, ["model-value", "disabled", "invalid", "title", "data-lp-time", "onUpdate:modelValue", "onBlur", "onKeydown"])
921
- ]);
1037
+ size: "sm",
1038
+ class: "w-28",
1039
+ label: end === 0 ? unref(text).start : unref(text).end,
1040
+ "model-value": fieldText(end),
1041
+ disabled: off.value,
1042
+ invalid: invalid.value[end],
1043
+ title: invalid.value[end] ? unref(text).invalidTime : void 0,
1044
+ inputmode: "decimal",
1045
+ spellcheck: "false",
1046
+ autocomplete: "off",
1047
+ "data-lp-time": end,
1048
+ "onUpdate:modelValue": ($event) => onFieldInput(end, $event),
1049
+ onBlur: ($event) => commitField(end),
1050
+ onKeydown: [
1051
+ withKeys(withModifiers(($event) => commitField(end), ["prevent"]), ["enter"]),
1052
+ withKeys(($event) => revertField(end), ["esc"])
1053
+ ]
1054
+ }, null, 8, ["label", "model-value", "disabled", "invalid", "title", "data-lp-time", "onUpdate:modelValue", "onBlur", "onKeydown"]);
922
1055
  }), 64)),
923
1056
  createElementVNode("div", _hoisted_19, [
924
1057
  createElementVNode("span", _hoisted_20, toDisplayString(unref(text).length), 1),
925
- createElementVNode("span", _hoisted_21, toDisplayString(unref(formatClipTime)(clipLength.value, true)), 1)
1058
+ createElementVNode("span", _hoisted_21, [
1059
+ createVNode(_sfc_main$4, {
1060
+ text: unref(formatClipTime)(clipLength.value, "fixed"),
1061
+ widest: widest.value
1062
+ }, null, 8, ["text", "widest"])
1063
+ ])
926
1064
  ]),
927
- leftText.value ? (openBlock(), createElementBlock("span", _hoisted_22, toDisplayString(leftText.value), 1)) : createCommentVNode("", true),
1065
+ createVNode(Transition, normalizeProps(guardReactiveProps(unref(FADE))), {
1066
+ default: withCtx(() => [
1067
+ leftText.value ? (openBlock(), createElementBlock("span", _hoisted_22, [
1068
+ createVNode(_sfc_main$4, {
1069
+ text: leftText.value,
1070
+ widest: widestLeft.value
1071
+ }, null, 8, ["text", "widest"])
1072
+ ])) : createCommentVNode("", true)
1073
+ ]),
1074
+ _: 1
1075
+ }, 16),
928
1076
  _cache[12] || (_cache[12] = createElementVNode("span", { class: "flex-1" }, null, -1)),
929
- __props.regionSelect ? (openBlock(), createElementBlock(Fragment, { key: 1 }, [
930
- __props.region ? (openBlock(), createBlock(_sfc_main$2, {
931
- key: 0,
932
- size: "sm",
933
- variant: "outline",
934
- disabled: __props.disabled,
935
- onClick: _cache[7] || (_cache[7] = ($event) => emit("update:region", null))
936
- }, {
937
- default: withCtx(() => [
938
- createVNode(_sfc_main$1, {
939
- name: "lucide:x",
940
- size: 14
941
- }),
942
- createTextVNode(toDisplayString(unref(text).regionClear), 1)
943
- ]),
944
- _: 1
945
- }, 8, ["disabled"])) : (openBlock(), createElementBlock("span", _hoisted_23, toDisplayString(unref(text).regionHint), 1))
946
- ], 64)) : createCommentVNode("", true)
1077
+ createVNode(Transition, normalizeProps(guardReactiveProps(unref(FADE_SCALE))), {
1078
+ default: withCtx(() => [
1079
+ __props.regionSelect ? (openBlock(), createBlock(_sfc_main$3, {
1080
+ key: 0,
1081
+ size: "sm",
1082
+ variant: "outline",
1083
+ disabled: __props.disabled || !__props.region,
1084
+ onClick: _cache[7] || (_cache[7] = ($event) => emit("update:region", null))
1085
+ }, {
1086
+ default: withCtx(() => [
1087
+ createVNode(_sfc_main$2, {
1088
+ name: "lucide:x",
1089
+ size: 14
1090
+ }),
1091
+ createTextVNode(toDisplayString(unref(text).regionClear), 1)
1092
+ ]),
1093
+ _: 1
1094
+ }, 8, ["disabled"])) : createCommentVNode("", true)
1095
+ ]),
1096
+ _: 1
1097
+ }, 16)
947
1098
  ])
948
1099
  ], 16, _hoisted_1);
949
1100
  };
950
1101
  }
951
1102
  });
952
- const LpVideoTrim = /* @__PURE__ */ _export_sfc(_sfc_main, [["__scopeId", "data-v-04a3a07a"]]);
1103
+ const LpVideoTrim = /* @__PURE__ */ _export_sfc(_sfc_main, [["__scopeId", "data-v-713835cc"]]);
953
1104
  export {
954
1105
  LpVideoTrim as default
955
1106
  };