@getontime/cli 4.0.2 → 4.1.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 (339) hide show
  1. package/client/assets/{Backstage-CAjkmeJm.js → Backstage-BhtXVpms.js} +2 -2
  2. package/client/assets/Backstage-BhtXVpms.js.br +0 -0
  3. package/client/assets/Backstage-BhtXVpms.js.gz +0 -0
  4. package/client/assets/{Backstage-CAjkmeJm.js.map → Backstage-BhtXVpms.js.map} +1 -1
  5. package/client/assets/{Countdown-ChuA9az_.js → Countdown-NmGi1KMx.js} +2 -2
  6. package/client/assets/Countdown-NmGi1KMx.js.br +0 -0
  7. package/client/assets/Countdown-NmGi1KMx.js.gz +0 -0
  8. package/client/assets/Countdown-NmGi1KMx.js.map +1 -0
  9. package/client/assets/{CustomTranslationModal-C3R_2T5s.js → CustomTranslationModal-BBNxpds0.js} +2 -2
  10. package/client/assets/CustomTranslationModal-BBNxpds0.js.br +0 -0
  11. package/client/assets/CustomTranslationModal-BBNxpds0.js.gz +0 -0
  12. package/client/assets/{CustomTranslationModal-C3R_2T5s.js.map → CustomTranslationModal-BBNxpds0.js.map} +1 -1
  13. package/client/assets/{DelayIndicator-vT7n8ypf.js → DelayIndicator-CFCDQ7FN.js} +2 -2
  14. package/client/assets/DelayIndicator-CFCDQ7FN.js.br +0 -0
  15. package/client/assets/DelayIndicator-CFCDQ7FN.js.gz +0 -0
  16. package/client/assets/{DelayIndicator-vT7n8ypf.js.map → DelayIndicator-CFCDQ7FN.js.map} +1 -1
  17. package/client/assets/{EditorFeatureWrapper-DHfuO3EA.js → EditorFeatureWrapper-D55c8JBz.js} +2 -2
  18. package/client/assets/EditorFeatureWrapper-D55c8JBz.js.br +0 -0
  19. package/client/assets/EditorFeatureWrapper-D55c8JBz.js.gz +0 -0
  20. package/client/assets/{EditorFeatureWrapper-DHfuO3EA.js.map → EditorFeatureWrapper-D55c8JBz.js.map} +1 -1
  21. package/client/assets/{EditorUtils-Da5ALK1P.js → EditorUtils-CFE106qQ.js} +2 -2
  22. package/client/assets/EditorUtils-CFE106qQ.js.br +0 -0
  23. package/client/assets/EditorUtils-CFE106qQ.js.gz +0 -0
  24. package/client/assets/{EditorUtils-Da5ALK1P.js.map → EditorUtils-CFE106qQ.js.map} +1 -1
  25. package/client/assets/{Empty-gWT_HMeu.js → Empty-C-JO_XAr.js} +2 -2
  26. package/client/assets/Empty-C-JO_XAr.js.br +2 -0
  27. package/client/assets/Empty-C-JO_XAr.js.gz +0 -0
  28. package/client/assets/{Empty-gWT_HMeu.js.map → Empty-C-JO_XAr.js.map} +1 -1
  29. package/client/assets/{EmptyPage-Dcbg6rmF.js → EmptyPage-BSzsxpGg.js} +2 -2
  30. package/client/assets/EmptyPage-BSzsxpGg.js.br +1 -0
  31. package/client/assets/EmptyPage-BSzsxpGg.js.gz +0 -0
  32. package/client/assets/{EmptyPage-Dcbg6rmF.js.map → EmptyPage-BSzsxpGg.js.map} +1 -1
  33. package/client/assets/{FollowButton-CSqJSvix.js → FollowButton-Mox6N4JW.js} +2 -2
  34. package/client/assets/FollowButton-Mox6N4JW.js.br +0 -0
  35. package/client/assets/FollowButton-Mox6N4JW.js.gz +0 -0
  36. package/client/assets/{FollowButton-CSqJSvix.js.map → FollowButton-Mox6N4JW.js.map} +1 -1
  37. package/client/assets/MessageControlExport-BL2ip9qN.js +2 -0
  38. package/client/assets/MessageControlExport-BL2ip9qN.js.br +0 -0
  39. package/client/assets/MessageControlExport-BL2ip9qN.js.gz +0 -0
  40. package/client/assets/{MessageControlExport-lXK21piH.js.map → MessageControlExport-BL2ip9qN.js.map} +1 -1
  41. package/client/assets/{MilestoneEditor-Bge8xLrV.js → MilestoneEditor-DcWPGKNK.js} +2 -2
  42. package/client/assets/MilestoneEditor-DcWPGKNK.js.br +0 -0
  43. package/client/assets/MilestoneEditor-DcWPGKNK.js.gz +0 -0
  44. package/client/assets/{MilestoneEditor-Bge8xLrV.js.map → MilestoneEditor-DcWPGKNK.js.map} +1 -1
  45. package/client/assets/Modal-D3tAPV2u.css +1 -0
  46. package/client/assets/Modal-D3tAPV2u.css.br +0 -0
  47. package/client/assets/Modal-D3tAPV2u.css.gz +0 -0
  48. package/client/assets/Modal-krcwDRb-.js +2 -0
  49. package/client/assets/Modal-krcwDRb-.js.br +0 -0
  50. package/client/assets/Modal-krcwDRb-.js.gz +0 -0
  51. package/client/assets/Modal-krcwDRb-.js.map +1 -0
  52. package/client/assets/{MultiPartProgressBar-D3jJZjb5.js → MultiPartProgressBar-BXQbpM-j.js} +2 -2
  53. package/client/assets/MultiPartProgressBar-BXQbpM-j.js.br +0 -0
  54. package/client/assets/MultiPartProgressBar-BXQbpM-j.js.gz +0 -0
  55. package/client/assets/{MultiPartProgressBar-D3jJZjb5.js.map → MultiPartProgressBar-BXQbpM-j.js.map} +1 -1
  56. package/client/assets/{OperatorExport-BUhxjLUx.js → OperatorExport-C50KHBrD.js} +2 -2
  57. package/client/assets/OperatorExport-C50KHBrD.js.br +0 -0
  58. package/client/assets/OperatorExport-C50KHBrD.js.gz +0 -0
  59. package/client/assets/{OperatorExport-BUhxjLUx.js.map → OperatorExport-C50KHBrD.js.map} +1 -1
  60. package/client/assets/OverviewWrapper-MGJ1uE5W.js +2 -0
  61. package/client/assets/OverviewWrapper-MGJ1uE5W.js.br +0 -0
  62. package/client/assets/OverviewWrapper-MGJ1uE5W.js.gz +0 -0
  63. package/client/assets/OverviewWrapper-MGJ1uE5W.js.map +1 -0
  64. package/client/assets/{ProjectInfo-z4k3cipS.js → ProjectInfo-CJ-GLvVG.js} +2 -2
  65. package/client/assets/ProjectInfo-CJ-GLvVG.js.br +0 -0
  66. package/client/assets/ProjectInfo-CJ-GLvVG.js.gz +0 -0
  67. package/client/assets/{ProjectInfo-z4k3cipS.js.map → ProjectInfo-CJ-GLvVG.js.map} +1 -1
  68. package/client/assets/{ProtectRoute-CrcWfOlG.js → ProtectRoute-DJ9xZnPI.js} +2 -2
  69. package/client/assets/ProtectRoute-DJ9xZnPI.js.br +0 -0
  70. package/client/assets/ProtectRoute-DJ9xZnPI.js.gz +0 -0
  71. package/client/assets/{ProtectRoute-CrcWfOlG.js.map → ProtectRoute-DJ9xZnPI.js.map} +1 -1
  72. package/client/assets/{ProtectedCuesheet-Deo4Aw6f.js → ProtectedCuesheet-B8tg6Mmo.js} +2 -2
  73. package/client/assets/ProtectedCuesheet-B8tg6Mmo.js.br +0 -0
  74. package/client/assets/ProtectedCuesheet-B8tg6Mmo.js.gz +0 -0
  75. package/client/assets/{ProtectedCuesheet-Deo4Aw6f.js.map → ProtectedCuesheet-B8tg6Mmo.js.map} +1 -1
  76. package/client/assets/ProtectedEditor-Bl4wV72N.js +3 -0
  77. package/client/assets/ProtectedEditor-Bl4wV72N.js.br +0 -0
  78. package/client/assets/ProtectedEditor-Bl4wV72N.js.gz +0 -0
  79. package/client/assets/ProtectedEditor-Bl4wV72N.js.map +1 -0
  80. package/client/assets/{RundownEntry-D61IqkXb.js → RundownEntry-D9tXNXPy.js} +2 -2
  81. package/client/assets/RundownEntry-D9tXNXPy.js.br +0 -0
  82. package/client/assets/RundownEntry-D9tXNXPy.js.gz +0 -0
  83. package/client/assets/{RundownEntry-D61IqkXb.js.map → RundownEntry-D9tXNXPy.js.map} +1 -1
  84. package/client/assets/RundownExport-D6uAmFbb.js +3 -0
  85. package/client/assets/RundownExport-D6uAmFbb.js.br +0 -0
  86. package/client/assets/RundownExport-D6uAmFbb.js.gz +0 -0
  87. package/client/assets/RundownExport-D6uAmFbb.js.map +1 -0
  88. package/client/assets/{Select-CedN80WS.js → Select-BLA-yQMq.js} +2 -2
  89. package/client/assets/Select-BLA-yQMq.js.br +0 -0
  90. package/client/assets/Select-BLA-yQMq.js.gz +0 -0
  91. package/client/assets/{Select-CedN80WS.js.map → Select-BLA-yQMq.js.map} +1 -1
  92. package/client/assets/{Studio-DUzPBS6P.js → Studio-DbP92DTf.js} +2 -2
  93. package/client/assets/Studio-DbP92DTf.js.br +0 -0
  94. package/client/assets/Studio-DbP92DTf.js.gz +0 -0
  95. package/client/assets/{Studio-DUzPBS6P.js.map → Studio-DbP92DTf.js.map} +1 -1
  96. package/client/assets/{StyleEditor-D2z65PB7.js → StyleEditor-DNjZ46Qf.js} +2 -2
  97. package/client/assets/StyleEditor-DNjZ46Qf.js.br +0 -0
  98. package/client/assets/StyleEditor-DNjZ46Qf.js.gz +0 -0
  99. package/client/assets/{StyleEditor-D2z65PB7.js.map → StyleEditor-DNjZ46Qf.js.map} +1 -1
  100. package/client/assets/{SuperscriptTime-CIrcMcyg.js → SuperscriptTime-C8ypTVpH.js} +2 -2
  101. package/client/assets/SuperscriptTime-C8ypTVpH.js.br +0 -0
  102. package/client/assets/SuperscriptTime-C8ypTVpH.js.gz +0 -0
  103. package/client/assets/{SuperscriptTime-CIrcMcyg.js.map → SuperscriptTime-C8ypTVpH.js.map} +1 -1
  104. package/client/assets/{TimeElements-CALNfv6u.js → TimeElements-DlEBhXe0.js} +2 -2
  105. package/client/assets/TimeElements-DlEBhXe0.js.br +0 -0
  106. package/client/assets/TimeElements-DlEBhXe0.js.gz +0 -0
  107. package/client/assets/{TimeElements-CALNfv6u.js.map → TimeElements-DlEBhXe0.js.map} +1 -1
  108. package/client/assets/{TimeInput-Dg1naiy3.js → TimeInput-DU09ewqh.js} +2 -2
  109. package/client/assets/TimeInput-DU09ewqh.js.br +0 -0
  110. package/client/assets/TimeInput-DU09ewqh.js.gz +0 -0
  111. package/client/assets/{TimeInput-Dg1naiy3.js.map → TimeInput-DU09ewqh.js.map} +1 -1
  112. package/client/assets/{TimelinePage-Cwm0svjN.js → TimelinePage-DTwqRihn.js} +2 -2
  113. package/client/assets/TimelinePage-DTwqRihn.js.br +0 -0
  114. package/client/assets/TimelinePage-DTwqRihn.js.gz +0 -0
  115. package/client/assets/{TimelinePage-Cwm0svjN.js.map → TimelinePage-DTwqRihn.js.map} +1 -1
  116. package/client/assets/{Timer-BvEmZbmF.css → Timer-B7nk3TMf.css} +1 -1
  117. package/client/assets/Timer-B7nk3TMf.css.br +0 -0
  118. package/client/assets/Timer-B7nk3TMf.css.gz +0 -0
  119. package/client/assets/{Timer-BVXskRjc.js → Timer-jjWAunJc.js} +2 -2
  120. package/client/assets/Timer-jjWAunJc.js.br +0 -0
  121. package/client/assets/Timer-jjWAunJc.js.gz +0 -0
  122. package/client/assets/{Timer-BVXskRjc.js.map → Timer-jjWAunJc.js.map} +1 -1
  123. package/client/assets/TimerControlExport-i0ZDpUx7.js +2 -0
  124. package/client/assets/TimerControlExport-i0ZDpUx7.js.br +0 -0
  125. package/client/assets/TimerControlExport-i0ZDpUx7.js.gz +0 -0
  126. package/client/assets/{TimerControlExport-C8ECtLBd.js.map → TimerControlExport-i0ZDpUx7.js.map} +1 -1
  127. package/client/assets/{TitleCard-CZl9wSHS.js → TitleCard-BgOtucv6.js} +2 -2
  128. package/client/assets/TitleCard-BgOtucv6.js.br +0 -0
  129. package/client/assets/TitleCard-BgOtucv6.js.gz +0 -0
  130. package/client/assets/{TitleCard-CZl9wSHS.js.map → TitleCard-BgOtucv6.js.map} +1 -1
  131. package/client/assets/{Tooltip-D9XRnwOW.js → Tooltip-C0rGHLsB.js} +2 -2
  132. package/client/assets/Tooltip-C0rGHLsB.js.br +0 -0
  133. package/client/assets/Tooltip-C0rGHLsB.js.gz +0 -0
  134. package/client/assets/{Tooltip-D9XRnwOW.js.map → Tooltip-C0rGHLsB.js.map} +1 -1
  135. package/client/assets/{ViewLogo-_3Z1hIHi.js → ViewLogo--9miplQv.js} +2 -2
  136. package/client/assets/ViewLogo--9miplQv.js.br +0 -0
  137. package/client/assets/ViewLogo--9miplQv.js.gz +0 -0
  138. package/client/assets/{ViewLogo-_3Z1hIHi.js.map → ViewLogo--9miplQv.js.map} +1 -1
  139. package/client/assets/{ViewParamsEditor-Bca1TIDW.js → ViewParamsEditor-BFu_0oIb.js} +2 -2
  140. package/client/assets/ViewParamsEditor-BFu_0oIb.js.br +0 -0
  141. package/client/assets/ViewParamsEditor-BFu_0oIb.js.gz +0 -0
  142. package/client/assets/{ViewParamsEditor-Bca1TIDW.js.map → ViewParamsEditor-BFu_0oIb.js.map} +1 -1
  143. package/client/assets/{dateConfig-DRQGMWDF.js → dateConfig-WYqMzV9D.js} +2 -2
  144. package/client/assets/dateConfig-WYqMzV9D.js.br +0 -0
  145. package/client/assets/dateConfig-WYqMzV9D.js.gz +0 -0
  146. package/client/assets/{dateConfig-DRQGMWDF.js.map → dateConfig-WYqMzV9D.js.map} +1 -1
  147. package/client/assets/{editorSettings-BU0pTMSY.js → editorSettings-CCHx-wCx.js} +2 -2
  148. package/client/assets/editorSettings-CCHx-wCx.js.br +0 -0
  149. package/client/assets/editorSettings-CCHx-wCx.js.gz +0 -0
  150. package/client/assets/{editorSettings-BU0pTMSY.js.map → editorSettings-CCHx-wCx.js.map} +1 -1
  151. package/client/assets/{getProgress-Cw79NL_O.js → getProgress-B94Ieskb.js} +2 -2
  152. package/client/assets/getProgress-B94Ieskb.js.br +0 -0
  153. package/client/assets/getProgress-B94Ieskb.js.gz +0 -0
  154. package/client/assets/{getProgress-Cw79NL_O.js.map → getProgress-B94Ieskb.js.map} +1 -1
  155. package/client/assets/{index-BQEUaoAf.js → index-njXwwjfn.js} +3 -3
  156. package/client/assets/index-njXwwjfn.js.br +0 -0
  157. package/client/assets/index-njXwwjfn.js.gz +0 -0
  158. package/client/assets/{index-BQEUaoAf.js.map → index-njXwwjfn.js.map} +1 -1
  159. package/client/assets/{offset-DJAHqjFW.js → offset-D1q-72D-.js} +2 -2
  160. package/client/assets/offset-D1q-72D-.js.br +0 -0
  161. package/client/assets/offset-D1q-72D-.js.gz +0 -0
  162. package/client/assets/{offset-DJAHqjFW.js.map → offset-D1q-72D-.js.map} +1 -1
  163. package/client/assets/{parseUserTime-BeTKj08M.js → parseUserTime-Bc1pSJR2.js} +2 -2
  164. package/client/assets/parseUserTime-Bc1pSJR2.js.br +0 -0
  165. package/client/assets/parseUserTime-Bc1pSJR2.js.gz +0 -0
  166. package/client/assets/{parseUserTime-BeTKj08M.js.map → parseUserTime-Bc1pSJR2.js.map} +1 -1
  167. package/client/assets/{playbackstate-B_khF6xU.js → playbackstate-BpzbtG9F.js} +2 -2
  168. package/client/assets/playbackstate-BpzbtG9F.js.br +0 -0
  169. package/client/assets/playbackstate-BpzbtG9F.js.gz +0 -0
  170. package/client/assets/{playbackstate-B_khF6xU.js.map → playbackstate-BpzbtG9F.js.map} +1 -1
  171. package/client/assets/{presentation.utils-KwY-ACf7.js → presentation.utils-B2baBe3j.js} +2 -2
  172. package/client/assets/presentation.utils-B2baBe3j.js.br +0 -0
  173. package/client/assets/presentation.utils-B2baBe3j.js.gz +0 -0
  174. package/client/assets/{presentation.utils-KwY-ACf7.js.map → presentation.utils-B2baBe3j.js.map} +1 -1
  175. package/client/assets/{rundownUtils-BZHazkXR.js → rundownUtils-H6xvQyre.js} +2 -2
  176. package/client/assets/rundownUtils-H6xvQyre.js.br +0 -0
  177. package/client/assets/rundownUtils-H6xvQyre.js.gz +0 -0
  178. package/client/assets/{rundownUtils-BZHazkXR.js.map → rundownUtils-H6xvQyre.js.map} +1 -1
  179. package/client/assets/{useCustomFields-DqCYz8Kt.js → useCustomFields-Da0Li7nQ.js} +2 -2
  180. package/client/assets/useCustomFields-Da0Li7nQ.js.br +0 -0
  181. package/client/assets/useCustomFields-Da0Li7nQ.js.gz +0 -0
  182. package/client/assets/{useCustomFields-DqCYz8Kt.js.map → useCustomFields-Da0Li7nQ.js.map} +1 -1
  183. package/client/assets/{useFollowComponent-Ctfhf2or.js → useFollowComponent-Qo3FobyV.js} +2 -2
  184. package/client/assets/useFollowComponent-Qo3FobyV.js.br +0 -0
  185. package/client/assets/useFollowComponent-Qo3FobyV.js.gz +0 -0
  186. package/client/assets/{useFollowComponent-Ctfhf2or.js.map → useFollowComponent-Qo3FobyV.js.map} +1 -1
  187. package/client/assets/{useProjectData-C1hVamxc.js → useProjectData-DW06zQvF.js} +2 -2
  188. package/client/assets/useProjectData-DW06zQvF.js.br +0 -0
  189. package/client/assets/useProjectData-DW06zQvF.js.gz +0 -0
  190. package/client/assets/{useProjectData-C1hVamxc.js.map → useProjectData-DW06zQvF.js.map} +1 -1
  191. package/client/assets/{useReport-B4dMYcNL.js → useReport-DhFY2L8v.js} +2 -2
  192. package/client/assets/useReport-DhFY2L8v.js.br +0 -0
  193. package/client/assets/useReport-DhFY2L8v.js.gz +0 -0
  194. package/client/assets/{useReport-B4dMYcNL.js.map → useReport-DhFY2L8v.js.map} +1 -1
  195. package/client/assets/useRundown-ihoU8qBi.js +2 -0
  196. package/client/assets/useRundown-ihoU8qBi.js.br +0 -0
  197. package/client/assets/useRundown-ihoU8qBi.js.gz +0 -0
  198. package/client/assets/useRundown-ihoU8qBi.js.map +1 -0
  199. package/client/assets/{useWindowTitle-DqdFTWns.js → useWindowTitle-B2UzPuki.js} +2 -2
  200. package/client/assets/useWindowTitle-B2UzPuki.js.br +0 -0
  201. package/client/assets/useWindowTitle-B2UzPuki.js.gz +0 -0
  202. package/client/assets/{useWindowTitle-DqdFTWns.js.map → useWindowTitle-B2UzPuki.js.map} +1 -1
  203. package/client/assets/{validateEvent-P9sf7C10.js → validateEvent-BJMwP_mq.js} +2 -2
  204. package/client/assets/validateEvent-BJMwP_mq.js.br +0 -0
  205. package/client/assets/validateEvent-BJMwP_mq.js.gz +0 -0
  206. package/client/assets/{validateEvent-P9sf7C10.js.map → validateEvent-BJMwP_mq.js.map} +1 -1
  207. package/client/assets/{vendor-CCiSQ9k9.js → vendor-9UkPSc5K.js} +3 -3
  208. package/client/assets/vendor-9UkPSc5K.js.br +0 -0
  209. package/client/assets/vendor-9UkPSc5K.js.gz +0 -0
  210. package/client/assets/{vendor-CCiSQ9k9.js.map → vendor-9UkPSc5K.js.map} +1 -1
  211. package/client/assets/{viewLoader.utils-CmM-4-pk.js → viewLoader.utils-DQGhrjSp.js} +2 -2
  212. package/client/assets/viewLoader.utils-DQGhrjSp.js.br +0 -0
  213. package/client/assets/viewLoader.utils-DQGhrjSp.js.gz +0 -0
  214. package/client/assets/{viewLoader.utils-CmM-4-pk.js.map → viewLoader.utils-DQGhrjSp.js.map} +1 -1
  215. package/client/index.html +2 -2
  216. package/package.json +1 -1
  217. package/server/index.cjs +82 -82
  218. package/client/assets/Backstage-CAjkmeJm.js.br +0 -0
  219. package/client/assets/Backstage-CAjkmeJm.js.gz +0 -0
  220. package/client/assets/Countdown-ChuA9az_.js.br +0 -0
  221. package/client/assets/Countdown-ChuA9az_.js.gz +0 -0
  222. package/client/assets/Countdown-ChuA9az_.js.map +0 -1
  223. package/client/assets/CustomTranslationModal-C3R_2T5s.js.br +0 -0
  224. package/client/assets/CustomTranslationModal-C3R_2T5s.js.gz +0 -0
  225. package/client/assets/DelayIndicator-vT7n8ypf.js.br +0 -0
  226. package/client/assets/DelayIndicator-vT7n8ypf.js.gz +0 -0
  227. package/client/assets/EditorFeatureWrapper-DHfuO3EA.js.br +0 -0
  228. package/client/assets/EditorFeatureWrapper-DHfuO3EA.js.gz +0 -0
  229. package/client/assets/EditorUtils-Da5ALK1P.js.br +0 -0
  230. package/client/assets/EditorUtils-Da5ALK1P.js.gz +0 -0
  231. package/client/assets/Empty-gWT_HMeu.js.br +0 -0
  232. package/client/assets/Empty-gWT_HMeu.js.gz +0 -0
  233. package/client/assets/EmptyPage-Dcbg6rmF.js.br +0 -0
  234. package/client/assets/EmptyPage-Dcbg6rmF.js.gz +0 -0
  235. package/client/assets/FollowButton-CSqJSvix.js.br +0 -0
  236. package/client/assets/FollowButton-CSqJSvix.js.gz +0 -0
  237. package/client/assets/MessageControlExport-lXK21piH.js +0 -2
  238. package/client/assets/MessageControlExport-lXK21piH.js.br +0 -0
  239. package/client/assets/MessageControlExport-lXK21piH.js.gz +0 -0
  240. package/client/assets/MilestoneEditor-Bge8xLrV.js.br +0 -0
  241. package/client/assets/MilestoneEditor-Bge8xLrV.js.gz +0 -0
  242. package/client/assets/Modal-BgJx3SNK.css +0 -1
  243. package/client/assets/Modal-BgJx3SNK.css.br +0 -0
  244. package/client/assets/Modal-BgJx3SNK.css.gz +0 -0
  245. package/client/assets/Modal-C2sFA0zf.js +0 -2
  246. package/client/assets/Modal-C2sFA0zf.js.br +0 -0
  247. package/client/assets/Modal-C2sFA0zf.js.gz +0 -0
  248. package/client/assets/Modal-C2sFA0zf.js.map +0 -1
  249. package/client/assets/MultiPartProgressBar-D3jJZjb5.js.br +0 -0
  250. package/client/assets/MultiPartProgressBar-D3jJZjb5.js.gz +0 -0
  251. package/client/assets/OperatorExport-BUhxjLUx.js.br +0 -0
  252. package/client/assets/OperatorExport-BUhxjLUx.js.gz +0 -0
  253. package/client/assets/OverviewWrapper-BveJ6GjK.js +0 -2
  254. package/client/assets/OverviewWrapper-BveJ6GjK.js.br +0 -0
  255. package/client/assets/OverviewWrapper-BveJ6GjK.js.gz +0 -0
  256. package/client/assets/OverviewWrapper-BveJ6GjK.js.map +0 -1
  257. package/client/assets/ProjectInfo-z4k3cipS.js.br +0 -0
  258. package/client/assets/ProjectInfo-z4k3cipS.js.gz +0 -0
  259. package/client/assets/ProtectRoute-CrcWfOlG.js.br +0 -0
  260. package/client/assets/ProtectRoute-CrcWfOlG.js.gz +0 -0
  261. package/client/assets/ProtectedCuesheet-Deo4Aw6f.js.br +0 -0
  262. package/client/assets/ProtectedCuesheet-Deo4Aw6f.js.gz +0 -0
  263. package/client/assets/ProtectedEditor-C_SYWpL2.js +0 -3
  264. package/client/assets/ProtectedEditor-C_SYWpL2.js.br +0 -0
  265. package/client/assets/ProtectedEditor-C_SYWpL2.js.gz +0 -0
  266. package/client/assets/ProtectedEditor-C_SYWpL2.js.map +0 -1
  267. package/client/assets/RundownEntry-D61IqkXb.js.br +0 -0
  268. package/client/assets/RundownEntry-D61IqkXb.js.gz +0 -0
  269. package/client/assets/RundownExport-C6YhMGOC.js +0 -3
  270. package/client/assets/RundownExport-C6YhMGOC.js.br +0 -0
  271. package/client/assets/RundownExport-C6YhMGOC.js.gz +0 -0
  272. package/client/assets/RundownExport-C6YhMGOC.js.map +0 -1
  273. package/client/assets/Select-CedN80WS.js.br +0 -0
  274. package/client/assets/Select-CedN80WS.js.gz +0 -0
  275. package/client/assets/Studio-DUzPBS6P.js.br +0 -0
  276. package/client/assets/Studio-DUzPBS6P.js.gz +0 -0
  277. package/client/assets/StyleEditor-D2z65PB7.js.br +0 -0
  278. package/client/assets/StyleEditor-D2z65PB7.js.gz +0 -0
  279. package/client/assets/SuperscriptTime-CIrcMcyg.js.br +0 -0
  280. package/client/assets/SuperscriptTime-CIrcMcyg.js.gz +0 -0
  281. package/client/assets/TimeElements-CALNfv6u.js.br +0 -0
  282. package/client/assets/TimeElements-CALNfv6u.js.gz +0 -0
  283. package/client/assets/TimeInput-Dg1naiy3.js.br +0 -0
  284. package/client/assets/TimeInput-Dg1naiy3.js.gz +0 -0
  285. package/client/assets/TimelinePage-Cwm0svjN.js.br +0 -0
  286. package/client/assets/TimelinePage-Cwm0svjN.js.gz +0 -0
  287. package/client/assets/Timer-BVXskRjc.js.br +0 -0
  288. package/client/assets/Timer-BVXskRjc.js.gz +0 -0
  289. package/client/assets/Timer-BvEmZbmF.css.br +0 -0
  290. package/client/assets/Timer-BvEmZbmF.css.gz +0 -0
  291. package/client/assets/TimerControlExport-C8ECtLBd.js +0 -2
  292. package/client/assets/TimerControlExport-C8ECtLBd.js.br +0 -0
  293. package/client/assets/TimerControlExport-C8ECtLBd.js.gz +0 -0
  294. package/client/assets/TitleCard-CZl9wSHS.js.br +0 -0
  295. package/client/assets/TitleCard-CZl9wSHS.js.gz +0 -0
  296. package/client/assets/Tooltip-D9XRnwOW.js.br +0 -4
  297. package/client/assets/Tooltip-D9XRnwOW.js.gz +0 -0
  298. package/client/assets/ViewLogo-_3Z1hIHi.js.br +0 -0
  299. package/client/assets/ViewLogo-_3Z1hIHi.js.gz +0 -0
  300. package/client/assets/ViewParamsEditor-Bca1TIDW.js.br +0 -0
  301. package/client/assets/ViewParamsEditor-Bca1TIDW.js.gz +0 -0
  302. package/client/assets/dateConfig-DRQGMWDF.js.br +0 -0
  303. package/client/assets/dateConfig-DRQGMWDF.js.gz +0 -0
  304. package/client/assets/editorSettings-BU0pTMSY.js.br +0 -0
  305. package/client/assets/editorSettings-BU0pTMSY.js.gz +0 -0
  306. package/client/assets/getProgress-Cw79NL_O.js.br +0 -0
  307. package/client/assets/getProgress-Cw79NL_O.js.gz +0 -0
  308. package/client/assets/index-BQEUaoAf.js.br +0 -0
  309. package/client/assets/index-BQEUaoAf.js.gz +0 -0
  310. package/client/assets/offset-DJAHqjFW.js.br +0 -0
  311. package/client/assets/offset-DJAHqjFW.js.gz +0 -0
  312. package/client/assets/parseUserTime-BeTKj08M.js.br +0 -0
  313. package/client/assets/parseUserTime-BeTKj08M.js.gz +0 -0
  314. package/client/assets/playbackstate-B_khF6xU.js.br +0 -0
  315. package/client/assets/playbackstate-B_khF6xU.js.gz +0 -0
  316. package/client/assets/presentation.utils-KwY-ACf7.js.br +0 -0
  317. package/client/assets/presentation.utils-KwY-ACf7.js.gz +0 -0
  318. package/client/assets/rundownUtils-BZHazkXR.js.br +0 -0
  319. package/client/assets/rundownUtils-BZHazkXR.js.gz +0 -0
  320. package/client/assets/useCustomFields-DqCYz8Kt.js.br +0 -0
  321. package/client/assets/useCustomFields-DqCYz8Kt.js.gz +0 -0
  322. package/client/assets/useFollowComponent-Ctfhf2or.js.br +0 -0
  323. package/client/assets/useFollowComponent-Ctfhf2or.js.gz +0 -0
  324. package/client/assets/useProjectData-C1hVamxc.js.br +0 -0
  325. package/client/assets/useProjectData-C1hVamxc.js.gz +0 -0
  326. package/client/assets/useReport-B4dMYcNL.js.br +0 -0
  327. package/client/assets/useReport-B4dMYcNL.js.gz +0 -0
  328. package/client/assets/useRundown-BfpjcCEJ.js +0 -2
  329. package/client/assets/useRundown-BfpjcCEJ.js.br +0 -0
  330. package/client/assets/useRundown-BfpjcCEJ.js.gz +0 -0
  331. package/client/assets/useRundown-BfpjcCEJ.js.map +0 -1
  332. package/client/assets/useWindowTitle-DqdFTWns.js.br +0 -0
  333. package/client/assets/useWindowTitle-DqdFTWns.js.gz +0 -0
  334. package/client/assets/validateEvent-P9sf7C10.js.br +0 -3
  335. package/client/assets/validateEvent-P9sf7C10.js.gz +0 -0
  336. package/client/assets/vendor-CCiSQ9k9.js.br +0 -0
  337. package/client/assets/vendor-CCiSQ9k9.js.gz +0 -0
  338. package/client/assets/viewLoader.utils-CmM-4-pk.js.br +0 -0
  339. package/client/assets/viewLoader.utils-CmM-4-pk.js.gz +0 -0
@@ -1 +1 @@
1
- {"version":3,"file":"SuperscriptTime-CIrcMcyg.js","sources":["../../src/features/viewers/common/superscript-time/SuperscriptTime.tsx"],"sourcesContent":["import { CSSProperties } from 'react';\n\nimport './SuperscriptTime.scss';\n\ninterface SuperscriptTimeProps {\n time: string;\n className?: string;\n style?: CSSProperties;\n}\n\n/**\n * When the timer includes seconds, we want to split it from the rest\n */\nfunction getTimerParts(time: string) {\n if (time.length !== 8) {\n return [time, ''];\n }\n\n return [time.slice(0, 5), time.slice(5)];\n}\n\n/**\n * Receives a time string and formats it with a subscript or superscript\n * @example 12:00 AM -> AM becomes a superscript\n * @example 12:00:10 -> the seconds become a subscript\n */\nexport default function SuperscriptTime({ time, className, style }: SuperscriptTimeProps) {\n // we assume anything after space is a period tag\n const [timeString, period] = time.split(' ');\n const [mainTime, subscript] = getTimerParts(timeString);\n\n return (\n <div className={className} style={style}>\n {mainTime}\n {subscript && <span className='subscript'>{subscript}</span>}\n {period && <sup className='period'>{period}</sup>}\n </div>\n );\n}\n"],"names":["getTimerParts","time","SuperscriptTime","className","style","timeString","period","mainTime","subscript","jsxs","jsx"],"mappings":"mYAaA,SAASA,EAAcC,EAAc,CAC/B,OAAAA,EAAK,SAAW,EACX,CAACA,EAAM,EAAE,EAGX,CAACA,EAAK,MAAM,EAAG,CAAC,EAAGA,EAAK,MAAM,CAAC,CAAC,CACzC,CAOA,SAAwBC,EAAgB,CAAE,KAAAD,EAAM,UAAAE,EAAW,MAAAC,GAA+B,CAExF,KAAM,CAACC,EAAYC,CAAM,EAAIL,EAAK,MAAM,GAAG,EACrC,CAACM,EAAUC,CAAS,EAAIR,EAAcK,CAAU,EAGpD,OAAAI,EAAA,KAAC,MAAI,CAAA,UAAAN,EAAsB,MAAAC,EACxB,SAAA,CAAAG,EACAC,GAAaE,EAAA,IAAC,OAAK,CAAA,UAAU,YAAa,SAAUF,EAAA,EACpDF,GAAUI,EAAA,IAAC,MAAI,CAAA,UAAU,SAAU,SAAOJ,CAAA,CAAA,CAAA,EAC7C,CAEJ"}
1
+ {"version":3,"file":"SuperscriptTime-C8ypTVpH.js","sources":["../../src/features/viewers/common/superscript-time/SuperscriptTime.tsx"],"sourcesContent":["import { CSSProperties } from 'react';\n\nimport './SuperscriptTime.scss';\n\ninterface SuperscriptTimeProps {\n time: string;\n className?: string;\n style?: CSSProperties;\n}\n\n/**\n * When the timer includes seconds, we want to split it from the rest\n */\nfunction getTimerParts(time: string) {\n if (time.length !== 8) {\n return [time, ''];\n }\n\n return [time.slice(0, 5), time.slice(5)];\n}\n\n/**\n * Receives a time string and formats it with a subscript or superscript\n * @example 12:00 AM -> AM becomes a superscript\n * @example 12:00:10 -> the seconds become a subscript\n */\nexport default function SuperscriptTime({ time, className, style }: SuperscriptTimeProps) {\n // we assume anything after space is a period tag\n const [timeString, period] = time.split(' ');\n const [mainTime, subscript] = getTimerParts(timeString);\n\n return (\n <div className={className} style={style}>\n {mainTime}\n {subscript && <span className='subscript'>{subscript}</span>}\n {period && <sup className='period'>{period}</sup>}\n </div>\n );\n}\n"],"names":["getTimerParts","time","SuperscriptTime","className","style","timeString","period","mainTime","subscript","jsxs","jsx"],"mappings":"mYAaA,SAASA,EAAcC,EAAc,CAC/B,OAAAA,EAAK,SAAW,EACX,CAACA,EAAM,EAAE,EAGX,CAACA,EAAK,MAAM,EAAG,CAAC,EAAGA,EAAK,MAAM,CAAC,CAAC,CACzC,CAOA,SAAwBC,EAAgB,CAAE,KAAAD,EAAM,UAAAE,EAAW,MAAAC,GAA+B,CAExF,KAAM,CAACC,EAAYC,CAAM,EAAIL,EAAK,MAAM,GAAG,EACrC,CAACM,EAAUC,CAAS,EAAIR,EAAcK,CAAU,EAGpD,OAAAI,EAAA,KAAC,MAAI,CAAA,UAAAN,EAAsB,MAAAC,EACxB,SAAA,CAAAG,EACAC,GAAaE,EAAA,IAAC,OAAK,CAAA,UAAU,YAAa,SAAUF,EAAA,EACpDF,GAAUI,EAAA,IAAC,MAAI,CAAA,UAAU,SAAU,SAAOJ,CAAA,CAAA,CAAA,EAC7C,CAEJ"}
@@ -1,2 +1,2 @@
1
- import{j as e,h as D,b3 as P,b4 as $,b5 as M,b6 as U,b7 as A,b8 as z,b9 as V}from"./vendor-CCiSQ9k9.js";import{r as b,y as I,bg as h,A as J,i as d,bi as W,g as w,bj as q,w as g,bk as B,s as H,J as K,a as L,bl as Q,bm as X,bn as F,T as N,bo as Y,bp as Z}from"./index-BQEUaoAf.js";import{T as o}from"./Tooltip-D9XRnwOW.js";import{s as R}from"./useRundown-BfpjcCEJ.js";import{a as ee,g as te}from"./offset-DJAHqjFW.js";import{i as E}from"./playbackstate-B_khF6xU.js";(function(){try{var a=typeof window<"u"?window:typeof global<"u"?global:typeof globalThis<"u"?globalThis:typeof self<"u"?self:{},s=new a.Error().stack;s&&(a._sentryDebugIds=a._sentryDebugIds||{},a._sentryDebugIds[s]="ba6f5f2e-76f5-4606-9f3c-20a687ec7e89",a._sentryDebugIdIdentifier="sentry-dbid-ba6f5f2e-76f5-4606-9f3c-20a687ec7e89")}catch{}})();function y(a,s=3,n,r="due"){return a!==null&&a<=0?r:_(a,s,n)}function _(a,s=3,n){return I(a,{fallback:s===3?h:J,direction:n})}function G(a){return a!==null&&a>b?[a%b,Math.floor(a/b)]:[a,0]}const ae="_label_1k32k_18",se="_clock_1k32k_23",ne="_column_1k32k_35",le="_over_1k32k_50",re="_under_1k32k_56",u={label:ae,clock:se,column:ne,over:le,under:re};function S({label:a,value:s,state:n="active",className:r,testId:i}){return e.jsxs("div",{className:d([u.column,r]),"data-state":n,children:[e.jsx("span",{className:u.label,children:a}),e.jsx("span",{className:u.clock,"data-testid":i,children:s})]})}function ce({state:a,value:s,testId:n}){return e.jsxs("div",{className:u.column,"data-state":a,children:[e.jsxs("div",{className:u.label,children:[e.jsx("span",{className:u.over,children:"Over"}),e.jsx("span",{children:"/"}),e.jsx("span",{className:u.under,children:"Under"})]}),e.jsx("span",{className:u.clock,"data-testid":n,children:s})]})}const ie="_column_1x7b2_17",de="_row_1x7b2_26",oe="_metadataRow_1x7b2_33",me="_labelledElement_1x7b2_40",ue="_icon_1x7b2_46",xe="_label_1x7b2_40",pe="_time_1x7b2_57",be="_daySpan_1x7b2_64",fe="_muted_1x7b2_72",je="_labelTitle_1x7b2_76",Te="_dueTime_1x7b2_85",t={column:ie,row:de,metadataRow:oe,labelledElement:me,icon:ue,label:xe,time:pe,daySpan:be,muted:fe,labelTitle:je,dueTime:Te};function Se(){const{plannedEnd:a,plannedStart:s,actualStart:n,expectedEnd:r}=W(),i=s===null?h:w(s),[m,x]=D.useMemo(()=>G(a),[a]),[l,c]=D.useMemo(()=>G(r),[r]),p=m===null?h:w(m);return e.jsxs("div",{className:t.column,children:[e.jsxs("div",{className:t.row,children:[e.jsx("span",{className:t.label,children:"Start"}),e.jsxs("div",{className:t.labelledElement,children:[e.jsx(o,{text:"Planned start time",render:e.jsx(P,{className:t.icon})}),e.jsx("span",{className:d([t.time,s===null&&t.muted]),children:i})]}),e.jsxs("div",{className:t.labelledElement,"data-testid":"actual-start-time",children:[e.jsx(o,{text:"Actual start time",render:e.jsx($,{className:t.icon})}),e.jsx("span",{className:d([t.time,n===null&&t.muted]),children:_(n)})]})]}),e.jsxs("div",{className:t.row,children:[e.jsx("span",{className:t.label,children:"End"}),e.jsxs("div",{className:t.labelledElement,children:[e.jsx(o,{text:"Planned end time",render:e.jsx(P,{className:t.icon})}),x>0?e.jsx(o,{text:`Rundown spans over ${x+1} days`,render:e.jsx("span",{className:d([t.time,t.daySpan]),"data-day-offset":x}),children:p}):e.jsx("span",{className:d([t.time,a===null&&t.muted]),children:p})]}),e.jsxs("div",{className:t.labelledElement,children:[e.jsx(o,{text:"Expected end time",render:e.jsx(M,{className:t.icon})}),l!==null&&c>0?e.jsx(o,{text:`Rundown spans over ${c+1} days`,render:e.jsx("span",{className:d([t.time,t.daySpan]),"data-day-offset":c}),children:_(l)}):e.jsx("span",{className:d([t.time,l===null&&t.muted]),children:_(l)})]})]})]})}function ke(){return e.jsxs("div",{className:t.column,children:[e.jsx(ve,{}),e.jsx(_e,{})]})}function ve(){const{clock:a,mode:s,groupExpectedEnd:n,actualGroupStart:r,currentDay:i,playback:m}=Q(),{currentGroupId:x}=X(),l=R(x),c=E(m),p=(()=>{if(!c||!l||l.timeStart===null)return null;const j=a+i*b;return s===F.Absolute?l.timeStart+l.duration-j:r+l.duration-j})(),T=y(p,3,N.CountDown),v=n!==null?n-a:null,f=y(v,3,N.CountDown);return e.jsxs("div",{className:t.metadataRow,children:[e.jsx("span",{className:l!=null&&l.title?t.labelTitle:t.label,children:`${(l==null?void 0:l.title)||"Group"} `}),e.jsxs("div",{className:t.labelledElement,children:[e.jsx(o,{text:"Time to planned group end",render:e.jsx(U,{className:t.icon})}),e.jsx("span",{className:d([t.time,(!l||!c)&&t.muted,T==="due"&&t.dueTime]),children:T})]}),e.jsxs("div",{className:t.labelledElement,children:[e.jsx(o,{text:"Time to expected group end",render:e.jsx(A,{className:t.icon})}),e.jsx("span",{className:d([t.time,!n&&t.muted,f==="due"&&t.dueTime]),children:f})]})]})}function _e(){const{clock:a,mode:s,actualStart:n,plannedStart:r,playback:i,currentDay:m}=Y(),{id:x,expectedStart:l}=Z(),c=R(x),p=E(i),T=(()=>{if(!p||!c)return null;const O=c.timeStart+c.dayOffset*b,C=a+m*b;return s===F.Absolute?O-C:O+n-r-C})(),v=y(T,3,N.CountDown),f=l!==null?l-a:null,j=y(f,3,N.CountDown),k=(c==null?void 0:c.title)??null;return e.jsxs("div",{className:t.metadataRow,children:[e.jsx("span",{className:k?t.labelTitle:t.label,children:`${k||"Flag"} `}),e.jsxs("div",{className:t.labelledElement,children:[e.jsx(o,{text:"Time to next flag planned start",render:e.jsx(z,{className:t.icon})}),e.jsx("span",{"data-testid":"flag-plannedStart",className:d([t.time,(!c||!p)&&t.muted,v==="due"&&t.dueTime]),children:v})]}),e.jsxs("div",{className:t.labelledElement,children:[e.jsx(o,{text:"Time to next flag expected start",render:e.jsx(V,{className:t.icon})}),e.jsx("span",{"data-testid":"flag-expectedStart",className:d([t.time,f===null&&t.muted,j==="due"&&t.dueTime]),children:j})]})]})}function Oe(){const{numEvents:a,selectedEventIndex:s}=q(),n=s!==null?s+1:g,r=a?`${n} of ${a||g}`:g;return e.jsx(S,{label:"Progress",value:r,state:s===null?"muted":"active"})}function Ce(){const{offset:a,playback:s}=B(),n=E(s),r=te(n?a:null),i=ee(n?a:null);return e.jsx(ce,{state:r,value:i,testId:"offset"})}function De({className:a}){const{clock:s}=H(),n=w(s);return e.jsx(S,{label:"Time now",value:n,className:a})}function Pe({className:a}){const s=K(),n=s.phase===L.Pending,r=n?"Count to start":"Running timer",i=I(n?s.secondaryTimer:s.current,{fallback:h}),m=n?"waiting":s.current===null?"muted":"active";return e.jsx(S,{label:r,value:i,state:m,className:a})}export{De as C,ke as M,Ce as O,Oe as P,Se as S,Pe as T,_ as f};
2
- //# sourceMappingURL=TimeElements-CALNfv6u.js.map
1
+ import{j as e,h as D,b3 as P,b4 as $,b5 as M,b6 as U,b7 as A,b8 as z,b9 as V}from"./vendor-9UkPSc5K.js";import{r as b,y as I,bg as h,A as J,i as d,bi as W,g as w,bj as q,w as g,bk as B,s as H,J as K,a as L,bl as Q,bm as X,bn as F,T as N,bo as Y,bp as Z}from"./index-njXwwjfn.js";import{T as o}from"./Tooltip-C0rGHLsB.js";import{v as R}from"./useRundown-ihoU8qBi.js";import{a as ee,g as te}from"./offset-D1q-72D-.js";import{i as E}from"./playbackstate-BpzbtG9F.js";(function(){try{var a=typeof window<"u"?window:typeof global<"u"?global:typeof globalThis<"u"?globalThis:typeof self<"u"?self:{},s=new a.Error().stack;s&&(a._sentryDebugIds=a._sentryDebugIds||{},a._sentryDebugIds[s]="166f9859-aa47-4826-9a17-e9bf02e03cd8",a._sentryDebugIdIdentifier="sentry-dbid-166f9859-aa47-4826-9a17-e9bf02e03cd8")}catch{}})();function y(a,s=3,n,r="due"){return a!==null&&a<=0?r:_(a,s,n)}function _(a,s=3,n){return I(a,{fallback:s===3?h:J,direction:n})}function G(a){return a!==null&&a>b?[a%b,Math.floor(a/b)]:[a,0]}const ae="_label_1k32k_18",se="_clock_1k32k_23",ne="_column_1k32k_35",le="_over_1k32k_50",re="_under_1k32k_56",u={label:ae,clock:se,column:ne,over:le,under:re};function S({label:a,value:s,state:n="active",className:r,testId:i}){return e.jsxs("div",{className:d([u.column,r]),"data-state":n,children:[e.jsx("span",{className:u.label,children:a}),e.jsx("span",{className:u.clock,"data-testid":i,children:s})]})}function ce({state:a,value:s,testId:n}){return e.jsxs("div",{className:u.column,"data-state":a,children:[e.jsxs("div",{className:u.label,children:[e.jsx("span",{className:u.over,children:"Over"}),e.jsx("span",{children:"/"}),e.jsx("span",{className:u.under,children:"Under"})]}),e.jsx("span",{className:u.clock,"data-testid":n,children:s})]})}const ie="_column_1x7b2_17",de="_row_1x7b2_26",oe="_metadataRow_1x7b2_33",me="_labelledElement_1x7b2_40",ue="_icon_1x7b2_46",xe="_label_1x7b2_40",pe="_time_1x7b2_57",be="_daySpan_1x7b2_64",fe="_muted_1x7b2_72",je="_labelTitle_1x7b2_76",Te="_dueTime_1x7b2_85",t={column:ie,row:de,metadataRow:oe,labelledElement:me,icon:ue,label:xe,time:pe,daySpan:be,muted:fe,labelTitle:je,dueTime:Te};function Se(){const{plannedEnd:a,plannedStart:s,actualStart:n,expectedEnd:r}=W(),i=s===null?h:w(s),[m,x]=D.useMemo(()=>G(a),[a]),[l,c]=D.useMemo(()=>G(r),[r]),p=m===null?h:w(m);return e.jsxs("div",{className:t.column,children:[e.jsxs("div",{className:t.row,children:[e.jsx("span",{className:t.label,children:"Start"}),e.jsxs("div",{className:t.labelledElement,children:[e.jsx(o,{text:"Planned start time",render:e.jsx(P,{className:t.icon})}),e.jsx("span",{className:d([t.time,s===null&&t.muted]),children:i})]}),e.jsxs("div",{className:t.labelledElement,"data-testid":"actual-start-time",children:[e.jsx(o,{text:"Actual start time",render:e.jsx($,{className:t.icon})}),e.jsx("span",{className:d([t.time,n===null&&t.muted]),children:_(n)})]})]}),e.jsxs("div",{className:t.row,children:[e.jsx("span",{className:t.label,children:"End"}),e.jsxs("div",{className:t.labelledElement,children:[e.jsx(o,{text:"Planned end time",render:e.jsx(P,{className:t.icon})}),x>0?e.jsx(o,{text:`Rundown spans over ${x+1} days`,render:e.jsx("span",{className:d([t.time,t.daySpan]),"data-day-offset":x}),children:p}):e.jsx("span",{className:d([t.time,a===null&&t.muted]),children:p})]}),e.jsxs("div",{className:t.labelledElement,children:[e.jsx(o,{text:"Expected end time",render:e.jsx(M,{className:t.icon})}),l!==null&&c>0?e.jsx(o,{text:`Rundown spans over ${c+1} days`,render:e.jsx("span",{className:d([t.time,t.daySpan]),"data-day-offset":c}),children:_(l)}):e.jsx("span",{className:d([t.time,l===null&&t.muted]),children:_(l)})]})]})]})}function ke(){return e.jsxs("div",{className:t.column,children:[e.jsx(ve,{}),e.jsx(_e,{})]})}function ve(){const{clock:a,mode:s,groupExpectedEnd:n,actualGroupStart:r,currentDay:i,playback:m}=Q(),{currentGroupId:x}=X(),l=R(x),c=E(m),p=(()=>{if(!c||!l||l.timeStart===null)return null;const j=a+i*b;return s===F.Absolute?l.timeStart+l.duration-j:r+l.duration-j})(),T=y(p,3,N.CountDown),v=n!==null?n-a:null,f=y(v,3,N.CountDown);return e.jsxs("div",{className:t.metadataRow,children:[e.jsx("span",{className:l!=null&&l.title?t.labelTitle:t.label,children:`${(l==null?void 0:l.title)||"Group"} `}),e.jsxs("div",{className:t.labelledElement,children:[e.jsx(o,{text:"Time to planned group end",render:e.jsx(U,{className:t.icon})}),e.jsx("span",{className:d([t.time,(!l||!c)&&t.muted,T==="due"&&t.dueTime]),children:T})]}),e.jsxs("div",{className:t.labelledElement,children:[e.jsx(o,{text:"Time to expected group end",render:e.jsx(A,{className:t.icon})}),e.jsx("span",{className:d([t.time,!n&&t.muted,f==="due"&&t.dueTime]),children:f})]})]})}function _e(){const{clock:a,mode:s,actualStart:n,plannedStart:r,playback:i,currentDay:m}=Y(),{id:x,expectedStart:l}=Z(),c=R(x),p=E(i),T=(()=>{if(!p||!c)return null;const O=c.timeStart+c.dayOffset*b,C=a+m*b;return s===F.Absolute?O-C:O+n-r-C})(),v=y(T,3,N.CountDown),f=l!==null?l-a:null,j=y(f,3,N.CountDown),k=(c==null?void 0:c.title)??null;return e.jsxs("div",{className:t.metadataRow,children:[e.jsx("span",{className:k?t.labelTitle:t.label,children:`${k||"Flag"} `}),e.jsxs("div",{className:t.labelledElement,children:[e.jsx(o,{text:"Time to next flag planned start",render:e.jsx(z,{className:t.icon})}),e.jsx("span",{"data-testid":"flag-plannedStart",className:d([t.time,(!c||!p)&&t.muted,v==="due"&&t.dueTime]),children:v})]}),e.jsxs("div",{className:t.labelledElement,children:[e.jsx(o,{text:"Time to next flag expected start",render:e.jsx(V,{className:t.icon})}),e.jsx("span",{"data-testid":"flag-expectedStart",className:d([t.time,f===null&&t.muted,j==="due"&&t.dueTime]),children:j})]})]})}function Oe(){const{numEvents:a,selectedEventIndex:s}=q(),n=s!==null?s+1:g,r=a?`${n} of ${a||g}`:g;return e.jsx(S,{label:"Progress",value:r,state:s===null?"muted":"active"})}function Ce(){const{offset:a,playback:s}=B(),n=E(s),r=te(n?a:null),i=ee(n?a:null);return e.jsx(ce,{state:r,value:i,testId:"offset"})}function De({className:a}){const{clock:s}=H(),n=w(s);return e.jsx(S,{label:"Time now",value:n,className:a})}function Pe({className:a}){const s=K(),n=s.phase===L.Pending,r=n?"Count to start":"Running timer",i=I(n?s.secondaryTimer:s.current,{fallback:h}),m=n?"waiting":s.current===null?"muted":"active";return e.jsx(S,{label:r,value:i,state:m,className:a})}export{De as C,ke as M,Ce as O,Oe as P,Se as S,Pe as T,_ as f};
2
+ //# sourceMappingURL=TimeElements-DlEBhXe0.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"TimeElements-CALNfv6u.js","sources":["../../src/features/overview/overview.utils.ts","../../src/features/overview/composite/TimeLayout.tsx","../../src/features/overview/composite/TimeElements.tsx"],"sourcesContent":["import { MaybeNumber, TimerType } from 'ontime-types';\nimport { dayInMs, millisToString } from 'ontime-utils';\n\nimport { timerPlaceholder, timerPlaceholderMin } from '../../common/utils/styleUtils';\n\n/**\n * Composition to stop negative timers from being formatted\n * They should show a due string instead\n *\n * This is used for cases when a negative timer is unwanted\n * eg: count down to a milestone\n */\nexport function formatDueTime(\n time: MaybeNumber,\n segments: number = 3,\n direction?: TimerType.CountDown | TimerType.CountUp,\n dueString = 'due',\n): string {\n if (time !== null && time <= 0) return dueString;\n return formattedTime(time, segments, direction);\n}\n\n/**\n * Encapsulates the logic for formatting time in overview\n */\nexport function formattedTime(\n time: MaybeNumber,\n segments: number = 3,\n direction?: TimerType.CountDown | TimerType.CountUp,\n): string {\n return millisToString(time, { fallback: segments === 3 ? timerPlaceholder : timerPlaceholderMin, direction });\n}\n\n/**\n * Calculates how long a time is and how many days it spans\n */\nexport function calculateEndAndDaySpan(end: MaybeNumber): [MaybeNumber, number] {\n if (end !== null && end > dayInMs) {\n return [end % dayInMs, Math.floor(end / dayInMs)];\n }\n\n return [end, 0];\n}\n","import { cx } from '../../../common/utils/styleUtils';\n\nimport style from './TimeLayout.module.scss';\n\ninterface TimeLayoutProps {\n label: string;\n value: string;\n state?: 'muted' | 'waiting' | 'active';\n daySpan?: number;\n className?: string;\n testId?: string;\n}\n\nexport function TimeColumn({ label, value, state = 'active', className, testId }: TimeLayoutProps) {\n return (\n <div className={cx([style.column, className])} data-state={state}>\n <span className={style.label}>{label}</span>\n <span className={style.clock} data-testid={testId}>\n {value}\n </span>\n </div>\n );\n}\n\ninterface OverUnderProps {\n state: 'over' | 'under' | 'muted' | null;\n value: string;\n testId: string;\n}\n\nexport function OverUnder({ state, value, testId }: OverUnderProps) {\n return (\n <div className={style.column} data-state={state}>\n <div className={style.label}>\n <span className={style.over}>Over</span>\n <span>/</span>\n <span className={style.under}>Under</span>\n </div>\n <span className={style.clock} data-testid={testId}>\n {value}\n </span>\n </div>\n );\n}\n","import { useMemo } from 'react';\nimport {\n TbCalendarClock,\n TbCalendarPin,\n TbCalendarStar,\n TbFlagPin,\n TbFlagStar,\n TbFolderPin,\n TbFolderStar,\n} from 'react-icons/tb';\nimport { OffsetMode, OntimeEvent, OntimeGroup, TimerPhase, TimerType } from 'ontime-types';\nimport { dayInMs, isPlaybackActive, millisToString } from 'ontime-utils';\n\nimport Tooltip from '../../../common/components/tooltip/Tooltip';\nimport {\n useClock,\n useCurrentGroupId,\n useFlagTimerOverView,\n useGroupTimerOverView,\n useNextFlag,\n useOffsetOverview,\n useProgressOverview,\n useStartTimesOverview,\n useTimer,\n} from '../../../common/hooks/useSocket';\nimport { useEntry } from '../../../common/hooks-query/useRundown';\nimport { getOffsetState, getOffsetText } from '../../../common/utils/offset';\nimport { cx, enDash, timerPlaceholder } from '../../../common/utils/styleUtils';\nimport { formatTime } from '../../../common/utils/time';\nimport { calculateEndAndDaySpan, formatDueTime, formattedTime } from '../overview.utils';\n\nimport { OverUnder, TimeColumn } from './TimeLayout';\n\nimport style from './TimeElements.module.scss';\n\nexport function StartTimes() {\n const { plannedEnd, plannedStart, actualStart, expectedEnd } = useStartTimesOverview();\n\n const plannedStartText = plannedStart === null ? timerPlaceholder : formatTime(plannedStart);\n\n const [maybePlannedEnd, maybePlannedDaySpan] = useMemo(() => calculateEndAndDaySpan(plannedEnd), [plannedEnd]);\n const [maybeExpectedEnd, maybeExpectedDaySpan] = useMemo(() => calculateEndAndDaySpan(expectedEnd), [expectedEnd]);\n const plannedEndText = maybePlannedEnd === null ? timerPlaceholder : formatTime(maybePlannedEnd);\n\n return (\n <div className={style.column}>\n <div className={style.row}>\n <span className={style.label}>Start</span>\n <div className={style.labelledElement}>\n <Tooltip text='Planned start time' render={<TbCalendarPin className={style.icon} />} />\n <span className={cx([style.time, plannedStart === null && style.muted])}>{plannedStartText}</span>\n </div>\n <div className={style.labelledElement} data-testid='actual-start-time'>\n <Tooltip text='Actual start time' render={<TbCalendarClock className={style.icon} />} />\n <span className={cx([style.time, actualStart === null && style.muted])}>{formattedTime(actualStart)}</span>\n </div>\n </div>\n <div className={style.row}>\n <span className={style.label}>End</span>\n <div className={style.labelledElement}>\n <Tooltip text='Planned end time' render={<TbCalendarPin className={style.icon} />} />\n {maybePlannedDaySpan > 0 ? (\n <Tooltip\n text={`Rundown spans over ${maybePlannedDaySpan + 1} days`}\n render={<span className={cx([style.time, style.daySpan])} data-day-offset={maybePlannedDaySpan} />}\n >\n {plannedEndText}\n </Tooltip>\n ) : (\n <span className={cx([style.time, plannedEnd === null && style.muted])}>{plannedEndText}</span>\n )}\n </div>\n <div className={style.labelledElement}>\n <Tooltip text='Expected end time' render={<TbCalendarStar className={style.icon} />} />\n {maybeExpectedEnd !== null && maybeExpectedDaySpan > 0 ? (\n <Tooltip\n text={`Rundown spans over ${maybeExpectedDaySpan + 1} days`}\n render={<span className={cx([style.time, style.daySpan])} data-day-offset={maybeExpectedDaySpan} />}\n >\n {formattedTime(maybeExpectedEnd)}\n </Tooltip>\n ) : (\n <span className={cx([style.time, maybeExpectedEnd === null && style.muted])}>\n {formattedTime(maybeExpectedEnd)}\n </span>\n )}\n </div>\n </div>\n </div>\n );\n}\n\nexport function MetadataTimes() {\n return (\n <div className={style.column}>\n <GroupTimes />\n <FlagTimes />\n </div>\n );\n}\n\nfunction GroupTimes() {\n const { clock, mode, groupExpectedEnd, actualGroupStart, currentDay, playback } = useGroupTimerOverView();\n const { currentGroupId } = useCurrentGroupId();\n const group = useEntry(currentGroupId) as OntimeGroup | null;\n\n const active = isPlaybackActive(playback);\n\n // the group end time dose not encode any day offsets so it is calculated with group start time and duration\n const plannedGroupEnd = (() => {\n if (!active) return null;\n if (!group || group.timeStart === null) return null;\n const normalizedClock = clock + currentDay * dayInMs;\n\n return mode === OffsetMode.Absolute\n ? group.timeStart + group.duration - normalizedClock\n : actualGroupStart + group.duration - normalizedClock;\n })();\n\n const plannedTimeUntilGroupEnd = formatDueTime(plannedGroupEnd, 3, TimerType.CountDown);\n\n const expectedGroupEnd = groupExpectedEnd !== null ? groupExpectedEnd - clock : null;\n const expectedTimeUntilGroupEnd = formatDueTime(expectedGroupEnd, 3, TimerType.CountDown);\n\n return (\n <div className={style.metadataRow}>\n <span className={group?.title ? style.labelTitle : style.label}>{`${group?.title || 'Group'} `}</span>\n <div className={style.labelledElement}>\n <Tooltip text='Time to planned group end' render={<TbFolderPin className={style.icon} />} />\n <span\n className={cx([\n style.time,\n (!group || !active) && style.muted,\n plannedTimeUntilGroupEnd === 'due' && style.dueTime,\n ])}\n >\n {plannedTimeUntilGroupEnd}\n </span>\n </div>\n <div className={style.labelledElement}>\n <Tooltip text='Time to expected group end' render={<TbFolderStar className={style.icon} />} />\n <span\n className={cx([\n style.time,\n !groupExpectedEnd && style.muted,\n expectedTimeUntilGroupEnd === 'due' && style.dueTime,\n ])}\n >\n {expectedTimeUntilGroupEnd}\n </span>\n </div>\n </div>\n );\n}\n\nfunction FlagTimes() {\n const { clock, mode, actualStart, plannedStart, playback, currentDay } = useFlagTimerOverView();\n const { id, expectedStart } = useNextFlag();\n const entry = useEntry(id) as OntimeEvent | null;\n\n const active = isPlaybackActive(playback);\n\n const plannedFlagStart = (() => {\n if (!active) return null;\n if (!entry) return null;\n const normalizedTimeStart = entry.timeStart + entry.dayOffset * dayInMs;\n const normalizedClock = clock + currentDay * dayInMs;\n return mode === OffsetMode.Absolute\n ? normalizedTimeStart - normalizedClock\n : normalizedTimeStart + actualStart - plannedStart - normalizedClock;\n })();\n\n const plannedTimeUntilDisplay = formatDueTime(plannedFlagStart, 3, TimerType.CountDown);\n\n const expectedTimeUntil = expectedStart !== null ? expectedStart - clock : null;\n const expectedTimeUntilDisplay = formatDueTime(expectedTimeUntil, 3, TimerType.CountDown);\n\n const title = entry?.title ?? null;\n\n return (\n <div className={style.metadataRow}>\n <span className={title ? style.labelTitle : style.label}>{`${title || 'Flag'} `}</span>\n <div className={style.labelledElement}>\n <Tooltip text='Time to next flag planned start' render={<TbFlagPin className={style.icon} />} />\n <span\n data-testid='flag-plannedStart'\n className={cx([\n style.time,\n (!entry || !active) && style.muted,\n plannedTimeUntilDisplay === 'due' && style.dueTime,\n ])}\n >\n {plannedTimeUntilDisplay}\n </span>\n </div>\n <div className={style.labelledElement}>\n <Tooltip text='Time to next flag expected start' render={<TbFlagStar className={style.icon} />} />\n <span\n data-testid='flag-expectedStart'\n className={cx([\n style.time,\n expectedTimeUntil === null && style.muted,\n expectedTimeUntilDisplay === 'due' && style.dueTime,\n ])}\n >\n {expectedTimeUntilDisplay}\n </span>\n </div>\n </div>\n );\n}\n\nexport function ProgressOverview() {\n const { numEvents, selectedEventIndex } = useProgressOverview();\n\n const current = selectedEventIndex !== null ? selectedEventIndex + 1 : enDash;\n const progressText = numEvents ? `${current} of ${numEvents || enDash}` : enDash;\n\n return <TimeColumn label='Progress' value={progressText} state={selectedEventIndex === null ? 'muted' : 'active'} />;\n}\n\nexport function OffsetOverview() {\n const { offset, playback } = useOffsetOverview();\n\n const isPlaying = isPlaybackActive(playback);\n const offsetState = getOffsetState(isPlaying ? offset : null);\n const offsetText = getOffsetText(isPlaying ? offset : null);\n\n return <OverUnder state={offsetState} value={offsetText} testId='offset' />;\n}\n\nexport function ClockOverview({ className }: { className?: string }) {\n const { clock } = useClock();\n const formattedClock = formatTime(clock);\n\n return <TimeColumn label='Time now' value={formattedClock} className={className} />;\n}\n\nexport function TimerOverview({ className }: { className?: string }) {\n const timer = useTimer();\n\n const isWaiting = timer.phase === TimerPhase.Pending;\n const title = isWaiting ? 'Count to start' : 'Running timer';\n const display = millisToString(isWaiting ? timer.secondaryTimer : timer.current, { fallback: timerPlaceholder });\n const timerState = (() => {\n if (isWaiting) return 'waiting';\n if (timer.current === null) return 'muted';\n return 'active';\n })();\n\n return <TimeColumn label={title} value={display} state={timerState} className={className} />;\n}\n"],"names":["formatDueTime","time","segments","direction","dueString","formattedTime","millisToString","timerPlaceholder","timerPlaceholderMin","calculateEndAndDaySpan","end","dayInMs","TimeColumn","label","value","state","className","testId","jsxs","cx","style","jsx","OverUnder","StartTimes","plannedEnd","plannedStart","actualStart","expectedEnd","useStartTimesOverview","plannedStartText","formatTime","maybePlannedEnd","maybePlannedDaySpan","useMemo","maybeExpectedEnd","maybeExpectedDaySpan","plannedEndText","Tooltip","TbCalendarPin","TbCalendarClock","TbCalendarStar","MetadataTimes","GroupTimes","FlagTimes","clock","mode","groupExpectedEnd","actualGroupStart","currentDay","playback","useGroupTimerOverView","currentGroupId","useCurrentGroupId","group","useEntry","active","isPlaybackActive","plannedGroupEnd","normalizedClock","OffsetMode","plannedTimeUntilGroupEnd","TimerType","expectedGroupEnd","expectedTimeUntilGroupEnd","TbFolderPin","TbFolderStar","useFlagTimerOverView","id","expectedStart","useNextFlag","entry","plannedFlagStart","normalizedTimeStart","plannedTimeUntilDisplay","expectedTimeUntil","expectedTimeUntilDisplay","title","TbFlagPin","TbFlagStar","ProgressOverview","numEvents","selectedEventIndex","useProgressOverview","current","enDash","progressText","OffsetOverview","offset","useOffsetOverview","isPlaying","offsetState","getOffsetState","offsetText","getOffsetText","ClockOverview","useClock","formattedClock","TimerOverview","timer","useTimer","isWaiting","TimerPhase","display","timerState"],"mappings":"0yBAYO,SAASA,EACdC,EACAC,EAAmB,EACnBC,EACAC,EAAY,MACJ,CACR,OAAIH,IAAS,MAAQA,GAAQ,EAAUG,EAChCC,EAAcJ,EAAMC,EAAUC,CAAS,CAChD,CAKO,SAASE,EACdJ,EACAC,EAAmB,EACnBC,EACQ,CACD,OAAAG,EAAeL,EAAM,CAAE,SAAUC,IAAa,EAAIK,EAAmBC,EAAqB,UAAAL,EAAW,CAC9G,CAKO,SAASM,EAAuBC,EAAyC,CAC1E,OAAAA,IAAQ,MAAQA,EAAMC,EACjB,CAACD,EAAMC,EAAS,KAAK,MAAMD,EAAMC,CAAO,CAAC,EAG3C,CAACD,EAAK,CAAC,CAChB,iKC7BgB,SAAAE,EAAW,CAAE,MAAAC,EAAO,MAAAC,EAAO,MAAAC,EAAQ,SAAU,UAAAC,EAAW,OAAAC,GAA2B,CAE/F,OAAAC,EAAA,KAAC,MAAI,CAAA,UAAWC,EAAG,CAACC,EAAM,OAAQJ,CAAS,CAAC,EAAG,aAAYD,EACzD,SAAA,CAAAM,EAAA,IAAC,OAAK,CAAA,UAAWD,EAAM,MAAQ,SAAMP,EAAA,QACpC,OAAK,CAAA,UAAWO,EAAM,MAAO,cAAaH,EACxC,SACHH,CAAA,CAAA,CAAA,EACF,CAEJ,CAQO,SAASQ,GAAU,CAAE,MAAAP,EAAO,MAAAD,EAAO,OAAAG,GAA0B,CAClE,cACG,MAAI,CAAA,UAAWG,EAAM,OAAQ,aAAYL,EACxC,SAAA,CAACG,EAAA,KAAA,MAAA,CAAI,UAAWE,EAAM,MACpB,SAAA,CAAAC,EAAA,IAAC,OAAK,CAAA,UAAWD,EAAM,KAAM,SAAI,OAAA,EACjCC,EAAAA,IAAC,QAAK,SAAC,GAAA,CAAA,EACNA,EAAA,IAAA,OAAA,CAAK,UAAWD,EAAM,MAAO,SAAK,OAAA,CAAA,CAAA,EACrC,QACC,OAAK,CAAA,UAAWA,EAAM,MAAO,cAAaH,EACxC,SACHH,CAAA,CAAA,CAAA,EACF,CAEJ,iYCRO,SAASS,IAAa,CAC3B,KAAM,CAAE,WAAAC,EAAY,aAAAC,EAAc,YAAAC,EAAa,YAAAC,CAAA,EAAgBC,EAAsB,EAE/EC,EAAmBJ,IAAiB,KAAOlB,EAAmBuB,EAAWL,CAAY,EAErF,CAACM,EAAiBC,CAAmB,EAAIC,EAAA,QAAQ,IAAMxB,EAAuBe,CAAU,EAAG,CAACA,CAAU,CAAC,EACvG,CAACU,EAAkBC,CAAoB,EAAIF,EAAA,QAAQ,IAAMxB,EAAuBkB,CAAW,EAAG,CAACA,CAAW,CAAC,EAC3GS,EAAiBL,IAAoB,KAAOxB,EAAmBuB,EAAWC,CAAe,EAE/F,OACGb,EAAAA,KAAA,MAAA,CAAI,UAAWE,EAAM,OACpB,SAAA,CAACF,EAAA,KAAA,MAAA,CAAI,UAAWE,EAAM,IACpB,SAAA,CAAAC,EAAA,IAAC,OAAK,CAAA,UAAWD,EAAM,MAAO,SAAK,QAAA,EAClCF,EAAA,KAAA,MAAA,CAAI,UAAWE,EAAM,gBACpB,SAAA,CAACC,EAAAA,IAAAgB,EAAA,CAAQ,KAAK,qBAAqB,aAASC,EAAc,CAAA,UAAWlB,EAAM,IAAA,CAAM,CAAI,CAAA,EACpFC,EAAAA,IAAA,OAAA,CAAK,UAAWF,EAAG,CAACC,EAAM,KAAMK,IAAiB,MAAQL,EAAM,KAAK,CAAC,EAAI,SAAiBS,CAAA,CAAA,CAAA,EAC7F,SACC,MAAI,CAAA,UAAWT,EAAM,gBAAiB,cAAY,oBACjD,SAAA,CAACC,EAAAA,IAAAgB,EAAA,CAAQ,KAAK,oBAAoB,aAASE,EAAgB,CAAA,UAAWnB,EAAM,IAAA,CAAM,CAAI,CAAA,EACrFC,EAAA,IAAA,OAAA,CAAK,UAAWF,EAAG,CAACC,EAAM,KAAMM,IAAgB,MAAQN,EAAM,KAAK,CAAC,EAAI,SAAAf,EAAcqB,CAAW,CAAE,CAAA,CAAA,CACtG,CAAA,CAAA,EACF,EACCR,EAAA,KAAA,MAAA,CAAI,UAAWE,EAAM,IACpB,SAAA,CAAAC,EAAA,IAAC,OAAK,CAAA,UAAWD,EAAM,MAAO,SAAG,MAAA,EAChCF,EAAA,KAAA,MAAA,CAAI,UAAWE,EAAM,gBACpB,SAAA,CAACC,EAAAA,IAAAgB,EAAA,CAAQ,KAAK,mBAAmB,aAASC,EAAc,CAAA,UAAWlB,EAAM,IAAA,CAAM,CAAI,CAAA,EAClFY,EAAsB,EACrBX,EAAA,IAACgB,EAAA,CACC,KAAM,sBAAsBL,EAAsB,CAAC,QACnD,OAAQX,EAAAA,IAAC,OAAK,CAAA,UAAWF,EAAG,CAACC,EAAM,KAAMA,EAAM,OAAO,CAAC,EAAG,kBAAiBY,CAAqB,CAAA,EAE/F,SAAAI,CAAA,CAAA,EAGHf,EAAAA,IAAC,OAAK,CAAA,UAAWF,EAAG,CAACC,EAAM,KAAMI,IAAe,MAAQJ,EAAM,KAAK,CAAC,EAAI,SAAegB,CAAA,CAAA,CAAA,EAE3F,EACClB,EAAA,KAAA,MAAA,CAAI,UAAWE,EAAM,gBACpB,SAAA,CAACC,EAAAA,IAAAgB,EAAA,CAAQ,KAAK,oBAAoB,aAASG,EAAe,CAAA,UAAWpB,EAAM,IAAA,CAAM,CAAI,CAAA,EACpFc,IAAqB,MAAQC,EAAuB,EACnDd,EAAA,IAACgB,EAAA,CACC,KAAM,sBAAsBF,EAAuB,CAAC,QACpD,OAAQd,EAAAA,IAAC,OAAK,CAAA,UAAWF,EAAG,CAACC,EAAM,KAAMA,EAAM,OAAO,CAAC,EAAG,kBAAiBe,CAAsB,CAAA,EAEhG,WAAcD,CAAgB,CAAA,CAAA,EAGhCb,EAAAA,IAAA,OAAA,CAAK,UAAWF,EAAG,CAACC,EAAM,KAAMc,IAAqB,MAAQd,EAAM,KAAK,CAAC,EACvE,SAAAf,EAAc6B,CAAgB,CACjC,CAAA,CAAA,CAEJ,CAAA,CAAA,CACF,CAAA,CAAA,EACF,CAEJ,CAEO,SAASO,IAAgB,CAC9B,OACGvB,EAAAA,KAAA,MAAA,CAAI,UAAWE,EAAM,OACpB,SAAA,CAAAC,EAAA,IAACqB,GAAW,EAAA,QACXC,GAAU,CAAA,CAAA,CAAA,EACb,CAEJ,CAEA,SAASD,IAAa,CACd,KAAA,CAAE,MAAAE,EAAO,KAAAC,EAAM,iBAAAC,EAAkB,iBAAAC,EAAkB,WAAAC,EAAY,SAAAC,GAAaC,EAAsB,EAClG,CAAE,eAAAC,CAAe,EAAIC,EAAkB,EACvCC,EAAQC,EAASH,CAAc,EAE/BI,EAASC,EAAiBP,CAAQ,EAGlCQ,GAAmB,IAAM,CAE7B,GADI,CAACF,GACD,CAACF,GAASA,EAAM,YAAc,KAAa,OAAA,KACzC,MAAAK,EAAkBd,EAAQI,EAAarC,EAEtC,OAAAkC,IAASc,EAAW,SACvBN,EAAM,UAAYA,EAAM,SAAWK,EACnCX,EAAmBM,EAAM,SAAWK,CAAA,GACvC,EAEGE,EAA2B5D,EAAcyD,EAAiB,EAAGI,EAAU,SAAS,EAEhFC,EAAmBhB,IAAqB,KAAOA,EAAmBF,EAAQ,KAC1EmB,EAA4B/D,EAAc8D,EAAkB,EAAGD,EAAU,SAAS,EAExF,OACG3C,EAAAA,KAAA,MAAA,CAAI,UAAWE,EAAM,YACpB,SAAA,CAAAC,EAAA,IAAC,OAAK,CAAA,UAAWgC,GAAA,MAAAA,EAAO,MAAQjC,EAAM,WAAaA,EAAM,MAAQ,SAAG,IAAAiC,GAAA,YAAAA,EAAO,QAAS,OAAO,IAAI,EAC9FnC,EAAA,KAAA,MAAA,CAAI,UAAWE,EAAM,gBACpB,SAAA,CAACC,EAAAA,IAAAgB,EAAA,CAAQ,KAAK,4BAA4B,aAAS2B,EAAY,CAAA,UAAW5C,EAAM,IAAA,CAAM,CAAI,CAAA,EAC1FC,EAAA,IAAC,OAAA,CACC,UAAWF,EAAG,CACZC,EAAM,MACL,CAACiC,GAAS,CAACE,IAAWnC,EAAM,MAC7BwC,IAA6B,OAASxC,EAAM,OAAA,CAC7C,EAEA,SAAAwC,CAAA,CAAA,CACH,EACF,EACC1C,EAAA,KAAA,MAAA,CAAI,UAAWE,EAAM,gBACpB,SAAA,CAACC,EAAAA,IAAAgB,EAAA,CAAQ,KAAK,6BAA6B,aAAS4B,EAAa,CAAA,UAAW7C,EAAM,IAAA,CAAM,CAAI,CAAA,EAC5FC,EAAA,IAAC,OAAA,CACC,UAAWF,EAAG,CACZC,EAAM,KACN,CAAC0B,GAAoB1B,EAAM,MAC3B2C,IAA8B,OAAS3C,EAAM,OAAA,CAC9C,EAEA,SAAA2C,CAAA,CAAA,CACH,CACF,CAAA,CAAA,EACF,CAEJ,CAEA,SAASpB,IAAY,CACb,KAAA,CAAE,MAAAC,EAAO,KAAAC,EAAM,YAAAnB,EAAa,aAAAD,EAAc,SAAAwB,EAAU,WAAAD,GAAekB,EAAqB,EACxF,CAAE,GAAAC,EAAI,cAAAC,CAAc,EAAIC,EAAY,EACpCC,EAAQhB,EAASa,CAAE,EAEnBZ,EAASC,EAAiBP,CAAQ,EAElCsB,GAAoB,IAAM,CAE1B,GADA,CAAChB,GACD,CAACe,EAAc,OAAA,KACnB,MAAME,EAAsBF,EAAM,UAAYA,EAAM,UAAY3D,EAC1D+C,EAAkBd,EAAQI,EAAarC,EAC7C,OAAOkC,IAASc,EAAW,SACvBa,EAAsBd,EACtBc,EAAsB9C,EAAcD,EAAeiC,CAAA,GACtD,EAEGe,EAA0BzE,EAAcuE,EAAkB,EAAGV,EAAU,SAAS,EAEhFa,EAAoBN,IAAkB,KAAOA,EAAgBxB,EAAQ,KACrE+B,EAA2B3E,EAAc0E,EAAmB,EAAGb,EAAU,SAAS,EAElFe,GAAQN,GAAA,YAAAA,EAAO,QAAS,KAE9B,OACGpD,EAAAA,KAAA,MAAA,CAAI,UAAWE,EAAM,YACpB,SAAA,CAACC,EAAA,IAAA,OAAA,CAAK,UAAWuD,EAAQxD,EAAM,WAAaA,EAAM,MAAQ,SAAA,GAAGwD,GAAS,MAAM,GAAI,CAAA,EAC/E1D,EAAA,KAAA,MAAA,CAAI,UAAWE,EAAM,gBACpB,SAAA,CAACC,EAAAA,IAAAgB,EAAA,CAAQ,KAAK,kCAAkC,aAASwC,EAAU,CAAA,UAAWzD,EAAM,IAAA,CAAM,CAAI,CAAA,EAC9FC,EAAA,IAAC,OAAA,CACC,cAAY,oBACZ,UAAWF,EAAG,CACZC,EAAM,MACL,CAACkD,GAAS,CAACf,IAAWnC,EAAM,MAC7BqD,IAA4B,OAASrD,EAAM,OAAA,CAC5C,EAEA,SAAAqD,CAAA,CAAA,CACH,EACF,EACCvD,EAAA,KAAA,MAAA,CAAI,UAAWE,EAAM,gBACpB,SAAA,CAACC,EAAAA,IAAAgB,EAAA,CAAQ,KAAK,mCAAmC,aAASyC,EAAW,CAAA,UAAW1D,EAAM,IAAA,CAAM,CAAI,CAAA,EAChGC,EAAA,IAAC,OAAA,CACC,cAAY,qBACZ,UAAWF,EAAG,CACZC,EAAM,KACNsD,IAAsB,MAAQtD,EAAM,MACpCuD,IAA6B,OAASvD,EAAM,OAAA,CAC7C,EAEA,SAAAuD,CAAA,CAAA,CACH,CACF,CAAA,CAAA,EACF,CAEJ,CAEO,SAASI,IAAmB,CACjC,KAAM,CAAE,UAAAC,EAAW,mBAAAC,CAAmB,EAAIC,EAAoB,EAExDC,EAAUF,IAAuB,KAAOA,EAAqB,EAAIG,EACjEC,EAAeL,EAAY,GAAGG,CAAO,OAAOH,GAAaI,CAAM,GAAKA,EAEnE,OAAA/D,EAAA,IAACT,EAAW,CAAA,MAAM,WAAW,MAAOyE,EAAc,MAAOJ,IAAuB,KAAO,QAAU,QAAU,CAAA,CACpH,CAEO,SAASK,IAAiB,CAC/B,KAAM,CAAE,OAAAC,EAAQ,SAAAtC,CAAS,EAAIuC,EAAkB,EAEzCC,EAAYjC,EAAiBP,CAAQ,EACrCyC,EAAcC,GAAeF,EAAYF,EAAS,IAAI,EACtDK,EAAaC,GAAcJ,EAAYF,EAAS,IAAI,EAE1D,aAAQjE,GAAU,CAAA,MAAOoE,EAAa,MAAOE,EAAY,OAAO,SAAS,CAC3E,CAEgB,SAAAE,GAAc,CAAE,UAAA9E,GAAqC,CAC7D,KAAA,CAAE,MAAA4B,CAAM,EAAImD,EAAS,EACrBC,EAAiBlE,EAAWc,CAAK,EAEvC,aAAQhC,EAAW,CAAA,MAAM,WAAW,MAAOoF,EAAgB,UAAAhF,EAAsB,CACnF,CAEgB,SAAAiF,GAAc,CAAE,UAAAjF,GAAqC,CACnE,MAAMkF,EAAQC,EAAS,EAEjBC,EAAYF,EAAM,QAAUG,EAAW,QACvCzB,EAAQwB,EAAY,iBAAmB,gBACvCE,EAAUhG,EAAe8F,EAAYF,EAAM,eAAiBA,EAAM,QAAS,CAAE,SAAU3F,EAAkB,EACzGgG,EACAH,EAAkB,UAClBF,EAAM,UAAY,KAAa,QAC5B,SAGF,OAAA7E,MAACT,GAAW,MAAOgE,EAAO,MAAO0B,EAAS,MAAOC,EAAY,UAAAvF,EAAsB,CAC5F"}
1
+ {"version":3,"file":"TimeElements-DlEBhXe0.js","sources":["../../src/features/overview/overview.utils.ts","../../src/features/overview/composite/TimeLayout.tsx","../../src/features/overview/composite/TimeElements.tsx"],"sourcesContent":["import { MaybeNumber, TimerType } from 'ontime-types';\nimport { dayInMs, millisToString } from 'ontime-utils';\n\nimport { timerPlaceholder, timerPlaceholderMin } from '../../common/utils/styleUtils';\n\n/**\n * Composition to stop negative timers from being formatted\n * They should show a due string instead\n *\n * This is used for cases when a negative timer is unwanted\n * eg: count down to a milestone\n */\nexport function formatDueTime(\n time: MaybeNumber,\n segments: number = 3,\n direction?: TimerType.CountDown | TimerType.CountUp,\n dueString = 'due',\n): string {\n if (time !== null && time <= 0) return dueString;\n return formattedTime(time, segments, direction);\n}\n\n/**\n * Encapsulates the logic for formatting time in overview\n */\nexport function formattedTime(\n time: MaybeNumber,\n segments: number = 3,\n direction?: TimerType.CountDown | TimerType.CountUp,\n): string {\n return millisToString(time, { fallback: segments === 3 ? timerPlaceholder : timerPlaceholderMin, direction });\n}\n\n/**\n * Calculates how long a time is and how many days it spans\n */\nexport function calculateEndAndDaySpan(end: MaybeNumber): [MaybeNumber, number] {\n if (end !== null && end > dayInMs) {\n return [end % dayInMs, Math.floor(end / dayInMs)];\n }\n\n return [end, 0];\n}\n","import { cx } from '../../../common/utils/styleUtils';\n\nimport style from './TimeLayout.module.scss';\n\ninterface TimeLayoutProps {\n label: string;\n value: string;\n state?: 'muted' | 'waiting' | 'active';\n daySpan?: number;\n className?: string;\n testId?: string;\n}\n\nexport function TimeColumn({ label, value, state = 'active', className, testId }: TimeLayoutProps) {\n return (\n <div className={cx([style.column, className])} data-state={state}>\n <span className={style.label}>{label}</span>\n <span className={style.clock} data-testid={testId}>\n {value}\n </span>\n </div>\n );\n}\n\ninterface OverUnderProps {\n state: 'over' | 'under' | 'muted' | null;\n value: string;\n testId: string;\n}\n\nexport function OverUnder({ state, value, testId }: OverUnderProps) {\n return (\n <div className={style.column} data-state={state}>\n <div className={style.label}>\n <span className={style.over}>Over</span>\n <span>/</span>\n <span className={style.under}>Under</span>\n </div>\n <span className={style.clock} data-testid={testId}>\n {value}\n </span>\n </div>\n );\n}\n","import { useMemo } from 'react';\nimport {\n TbCalendarClock,\n TbCalendarPin,\n TbCalendarStar,\n TbFlagPin,\n TbFlagStar,\n TbFolderPin,\n TbFolderStar,\n} from 'react-icons/tb';\nimport { OffsetMode, OntimeEvent, OntimeGroup, TimerPhase, TimerType } from 'ontime-types';\nimport { dayInMs, isPlaybackActive, millisToString } from 'ontime-utils';\n\nimport Tooltip from '../../../common/components/tooltip/Tooltip';\nimport {\n useClock,\n useCurrentGroupId,\n useFlagTimerOverView,\n useGroupTimerOverView,\n useNextFlag,\n useOffsetOverview,\n useProgressOverview,\n useStartTimesOverview,\n useTimer,\n} from '../../../common/hooks/useSocket';\nimport { useEntry } from '../../../common/hooks-query/useRundown';\nimport { getOffsetState, getOffsetText } from '../../../common/utils/offset';\nimport { cx, enDash, timerPlaceholder } from '../../../common/utils/styleUtils';\nimport { formatTime } from '../../../common/utils/time';\nimport { calculateEndAndDaySpan, formatDueTime, formattedTime } from '../overview.utils';\n\nimport { OverUnder, TimeColumn } from './TimeLayout';\n\nimport style from './TimeElements.module.scss';\n\nexport function StartTimes() {\n const { plannedEnd, plannedStart, actualStart, expectedEnd } = useStartTimesOverview();\n\n const plannedStartText = plannedStart === null ? timerPlaceholder : formatTime(plannedStart);\n\n const [maybePlannedEnd, maybePlannedDaySpan] = useMemo(() => calculateEndAndDaySpan(plannedEnd), [plannedEnd]);\n const [maybeExpectedEnd, maybeExpectedDaySpan] = useMemo(() => calculateEndAndDaySpan(expectedEnd), [expectedEnd]);\n const plannedEndText = maybePlannedEnd === null ? timerPlaceholder : formatTime(maybePlannedEnd);\n\n return (\n <div className={style.column}>\n <div className={style.row}>\n <span className={style.label}>Start</span>\n <div className={style.labelledElement}>\n <Tooltip text='Planned start time' render={<TbCalendarPin className={style.icon} />} />\n <span className={cx([style.time, plannedStart === null && style.muted])}>{plannedStartText}</span>\n </div>\n <div className={style.labelledElement} data-testid='actual-start-time'>\n <Tooltip text='Actual start time' render={<TbCalendarClock className={style.icon} />} />\n <span className={cx([style.time, actualStart === null && style.muted])}>{formattedTime(actualStart)}</span>\n </div>\n </div>\n <div className={style.row}>\n <span className={style.label}>End</span>\n <div className={style.labelledElement}>\n <Tooltip text='Planned end time' render={<TbCalendarPin className={style.icon} />} />\n {maybePlannedDaySpan > 0 ? (\n <Tooltip\n text={`Rundown spans over ${maybePlannedDaySpan + 1} days`}\n render={<span className={cx([style.time, style.daySpan])} data-day-offset={maybePlannedDaySpan} />}\n >\n {plannedEndText}\n </Tooltip>\n ) : (\n <span className={cx([style.time, plannedEnd === null && style.muted])}>{plannedEndText}</span>\n )}\n </div>\n <div className={style.labelledElement}>\n <Tooltip text='Expected end time' render={<TbCalendarStar className={style.icon} />} />\n {maybeExpectedEnd !== null && maybeExpectedDaySpan > 0 ? (\n <Tooltip\n text={`Rundown spans over ${maybeExpectedDaySpan + 1} days`}\n render={<span className={cx([style.time, style.daySpan])} data-day-offset={maybeExpectedDaySpan} />}\n >\n {formattedTime(maybeExpectedEnd)}\n </Tooltip>\n ) : (\n <span className={cx([style.time, maybeExpectedEnd === null && style.muted])}>\n {formattedTime(maybeExpectedEnd)}\n </span>\n )}\n </div>\n </div>\n </div>\n );\n}\n\nexport function MetadataTimes() {\n return (\n <div className={style.column}>\n <GroupTimes />\n <FlagTimes />\n </div>\n );\n}\n\nfunction GroupTimes() {\n const { clock, mode, groupExpectedEnd, actualGroupStart, currentDay, playback } = useGroupTimerOverView();\n const { currentGroupId } = useCurrentGroupId();\n const group = useEntry(currentGroupId) as OntimeGroup | null;\n\n const active = isPlaybackActive(playback);\n\n // the group end time dose not encode any day offsets so it is calculated with group start time and duration\n const plannedGroupEnd = (() => {\n if (!active) return null;\n if (!group || group.timeStart === null) return null;\n const normalizedClock = clock + currentDay * dayInMs;\n\n return mode === OffsetMode.Absolute\n ? group.timeStart + group.duration - normalizedClock\n : actualGroupStart + group.duration - normalizedClock;\n })();\n\n const plannedTimeUntilGroupEnd = formatDueTime(plannedGroupEnd, 3, TimerType.CountDown);\n\n const expectedGroupEnd = groupExpectedEnd !== null ? groupExpectedEnd - clock : null;\n const expectedTimeUntilGroupEnd = formatDueTime(expectedGroupEnd, 3, TimerType.CountDown);\n\n return (\n <div className={style.metadataRow}>\n <span className={group?.title ? style.labelTitle : style.label}>{`${group?.title || 'Group'} `}</span>\n <div className={style.labelledElement}>\n <Tooltip text='Time to planned group end' render={<TbFolderPin className={style.icon} />} />\n <span\n className={cx([\n style.time,\n (!group || !active) && style.muted,\n plannedTimeUntilGroupEnd === 'due' && style.dueTime,\n ])}\n >\n {plannedTimeUntilGroupEnd}\n </span>\n </div>\n <div className={style.labelledElement}>\n <Tooltip text='Time to expected group end' render={<TbFolderStar className={style.icon} />} />\n <span\n className={cx([\n style.time,\n !groupExpectedEnd && style.muted,\n expectedTimeUntilGroupEnd === 'due' && style.dueTime,\n ])}\n >\n {expectedTimeUntilGroupEnd}\n </span>\n </div>\n </div>\n );\n}\n\nfunction FlagTimes() {\n const { clock, mode, actualStart, plannedStart, playback, currentDay } = useFlagTimerOverView();\n const { id, expectedStart } = useNextFlag();\n const entry = useEntry(id) as OntimeEvent | null;\n\n const active = isPlaybackActive(playback);\n\n const plannedFlagStart = (() => {\n if (!active) return null;\n if (!entry) return null;\n const normalizedTimeStart = entry.timeStart + entry.dayOffset * dayInMs;\n const normalizedClock = clock + currentDay * dayInMs;\n return mode === OffsetMode.Absolute\n ? normalizedTimeStart - normalizedClock\n : normalizedTimeStart + actualStart - plannedStart - normalizedClock;\n })();\n\n const plannedTimeUntilDisplay = formatDueTime(plannedFlagStart, 3, TimerType.CountDown);\n\n const expectedTimeUntil = expectedStart !== null ? expectedStart - clock : null;\n const expectedTimeUntilDisplay = formatDueTime(expectedTimeUntil, 3, TimerType.CountDown);\n\n const title = entry?.title ?? null;\n\n return (\n <div className={style.metadataRow}>\n <span className={title ? style.labelTitle : style.label}>{`${title || 'Flag'} `}</span>\n <div className={style.labelledElement}>\n <Tooltip text='Time to next flag planned start' render={<TbFlagPin className={style.icon} />} />\n <span\n data-testid='flag-plannedStart'\n className={cx([\n style.time,\n (!entry || !active) && style.muted,\n plannedTimeUntilDisplay === 'due' && style.dueTime,\n ])}\n >\n {plannedTimeUntilDisplay}\n </span>\n </div>\n <div className={style.labelledElement}>\n <Tooltip text='Time to next flag expected start' render={<TbFlagStar className={style.icon} />} />\n <span\n data-testid='flag-expectedStart'\n className={cx([\n style.time,\n expectedTimeUntil === null && style.muted,\n expectedTimeUntilDisplay === 'due' && style.dueTime,\n ])}\n >\n {expectedTimeUntilDisplay}\n </span>\n </div>\n </div>\n );\n}\n\nexport function ProgressOverview() {\n const { numEvents, selectedEventIndex } = useProgressOverview();\n\n const current = selectedEventIndex !== null ? selectedEventIndex + 1 : enDash;\n const progressText = numEvents ? `${current} of ${numEvents || enDash}` : enDash;\n\n return <TimeColumn label='Progress' value={progressText} state={selectedEventIndex === null ? 'muted' : 'active'} />;\n}\n\nexport function OffsetOverview() {\n const { offset, playback } = useOffsetOverview();\n\n const isPlaying = isPlaybackActive(playback);\n const offsetState = getOffsetState(isPlaying ? offset : null);\n const offsetText = getOffsetText(isPlaying ? offset : null);\n\n return <OverUnder state={offsetState} value={offsetText} testId='offset' />;\n}\n\nexport function ClockOverview({ className }: { className?: string }) {\n const { clock } = useClock();\n const formattedClock = formatTime(clock);\n\n return <TimeColumn label='Time now' value={formattedClock} className={className} />;\n}\n\nexport function TimerOverview({ className }: { className?: string }) {\n const timer = useTimer();\n\n const isWaiting = timer.phase === TimerPhase.Pending;\n const title = isWaiting ? 'Count to start' : 'Running timer';\n const display = millisToString(isWaiting ? timer.secondaryTimer : timer.current, { fallback: timerPlaceholder });\n const timerState = (() => {\n if (isWaiting) return 'waiting';\n if (timer.current === null) return 'muted';\n return 'active';\n })();\n\n return <TimeColumn label={title} value={display} state={timerState} className={className} />;\n}\n"],"names":["formatDueTime","time","segments","direction","dueString","formattedTime","millisToString","timerPlaceholder","timerPlaceholderMin","calculateEndAndDaySpan","end","dayInMs","TimeColumn","label","value","state","className","testId","jsxs","cx","style","jsx","OverUnder","StartTimes","plannedEnd","plannedStart","actualStart","expectedEnd","useStartTimesOverview","plannedStartText","formatTime","maybePlannedEnd","maybePlannedDaySpan","useMemo","maybeExpectedEnd","maybeExpectedDaySpan","plannedEndText","Tooltip","TbCalendarPin","TbCalendarClock","TbCalendarStar","MetadataTimes","GroupTimes","FlagTimes","clock","mode","groupExpectedEnd","actualGroupStart","currentDay","playback","useGroupTimerOverView","currentGroupId","useCurrentGroupId","group","useEntry","active","isPlaybackActive","plannedGroupEnd","normalizedClock","OffsetMode","plannedTimeUntilGroupEnd","TimerType","expectedGroupEnd","expectedTimeUntilGroupEnd","TbFolderPin","TbFolderStar","useFlagTimerOverView","id","expectedStart","useNextFlag","entry","plannedFlagStart","normalizedTimeStart","plannedTimeUntilDisplay","expectedTimeUntil","expectedTimeUntilDisplay","title","TbFlagPin","TbFlagStar","ProgressOverview","numEvents","selectedEventIndex","useProgressOverview","current","enDash","progressText","OffsetOverview","offset","useOffsetOverview","isPlaying","offsetState","getOffsetState","offsetText","getOffsetText","ClockOverview","useClock","formattedClock","TimerOverview","timer","useTimer","isWaiting","TimerPhase","display","timerState"],"mappings":"0yBAYO,SAASA,EACdC,EACAC,EAAmB,EACnBC,EACAC,EAAY,MACJ,CACR,OAAIH,IAAS,MAAQA,GAAQ,EAAUG,EAChCC,EAAcJ,EAAMC,EAAUC,CAAS,CAChD,CAKO,SAASE,EACdJ,EACAC,EAAmB,EACnBC,EACQ,CACD,OAAAG,EAAeL,EAAM,CAAE,SAAUC,IAAa,EAAIK,EAAmBC,EAAqB,UAAAL,EAAW,CAC9G,CAKO,SAASM,EAAuBC,EAAyC,CAC1E,OAAAA,IAAQ,MAAQA,EAAMC,EACjB,CAACD,EAAMC,EAAS,KAAK,MAAMD,EAAMC,CAAO,CAAC,EAG3C,CAACD,EAAK,CAAC,CAChB,iKC7BgB,SAAAE,EAAW,CAAE,MAAAC,EAAO,MAAAC,EAAO,MAAAC,EAAQ,SAAU,UAAAC,EAAW,OAAAC,GAA2B,CAE/F,OAAAC,EAAA,KAAC,MAAI,CAAA,UAAWC,EAAG,CAACC,EAAM,OAAQJ,CAAS,CAAC,EAAG,aAAYD,EACzD,SAAA,CAAAM,EAAA,IAAC,OAAK,CAAA,UAAWD,EAAM,MAAQ,SAAMP,EAAA,QACpC,OAAK,CAAA,UAAWO,EAAM,MAAO,cAAaH,EACxC,SACHH,CAAA,CAAA,CAAA,EACF,CAEJ,CAQO,SAASQ,GAAU,CAAE,MAAAP,EAAO,MAAAD,EAAO,OAAAG,GAA0B,CAClE,cACG,MAAI,CAAA,UAAWG,EAAM,OAAQ,aAAYL,EACxC,SAAA,CAACG,EAAA,KAAA,MAAA,CAAI,UAAWE,EAAM,MACpB,SAAA,CAAAC,EAAA,IAAC,OAAK,CAAA,UAAWD,EAAM,KAAM,SAAI,OAAA,EACjCC,EAAAA,IAAC,QAAK,SAAC,GAAA,CAAA,EACNA,EAAA,IAAA,OAAA,CAAK,UAAWD,EAAM,MAAO,SAAK,OAAA,CAAA,CAAA,EACrC,QACC,OAAK,CAAA,UAAWA,EAAM,MAAO,cAAaH,EACxC,SACHH,CAAA,CAAA,CAAA,EACF,CAEJ,iYCRO,SAASS,IAAa,CAC3B,KAAM,CAAE,WAAAC,EAAY,aAAAC,EAAc,YAAAC,EAAa,YAAAC,CAAA,EAAgBC,EAAsB,EAE/EC,EAAmBJ,IAAiB,KAAOlB,EAAmBuB,EAAWL,CAAY,EAErF,CAACM,EAAiBC,CAAmB,EAAIC,EAAA,QAAQ,IAAMxB,EAAuBe,CAAU,EAAG,CAACA,CAAU,CAAC,EACvG,CAACU,EAAkBC,CAAoB,EAAIF,EAAA,QAAQ,IAAMxB,EAAuBkB,CAAW,EAAG,CAACA,CAAW,CAAC,EAC3GS,EAAiBL,IAAoB,KAAOxB,EAAmBuB,EAAWC,CAAe,EAE/F,OACGb,EAAAA,KAAA,MAAA,CAAI,UAAWE,EAAM,OACpB,SAAA,CAACF,EAAA,KAAA,MAAA,CAAI,UAAWE,EAAM,IACpB,SAAA,CAAAC,EAAA,IAAC,OAAK,CAAA,UAAWD,EAAM,MAAO,SAAK,QAAA,EAClCF,EAAA,KAAA,MAAA,CAAI,UAAWE,EAAM,gBACpB,SAAA,CAACC,EAAAA,IAAAgB,EAAA,CAAQ,KAAK,qBAAqB,aAASC,EAAc,CAAA,UAAWlB,EAAM,IAAA,CAAM,CAAI,CAAA,EACpFC,EAAAA,IAAA,OAAA,CAAK,UAAWF,EAAG,CAACC,EAAM,KAAMK,IAAiB,MAAQL,EAAM,KAAK,CAAC,EAAI,SAAiBS,CAAA,CAAA,CAAA,EAC7F,SACC,MAAI,CAAA,UAAWT,EAAM,gBAAiB,cAAY,oBACjD,SAAA,CAACC,EAAAA,IAAAgB,EAAA,CAAQ,KAAK,oBAAoB,aAASE,EAAgB,CAAA,UAAWnB,EAAM,IAAA,CAAM,CAAI,CAAA,EACrFC,EAAA,IAAA,OAAA,CAAK,UAAWF,EAAG,CAACC,EAAM,KAAMM,IAAgB,MAAQN,EAAM,KAAK,CAAC,EAAI,SAAAf,EAAcqB,CAAW,CAAE,CAAA,CAAA,CACtG,CAAA,CAAA,EACF,EACCR,EAAA,KAAA,MAAA,CAAI,UAAWE,EAAM,IACpB,SAAA,CAAAC,EAAA,IAAC,OAAK,CAAA,UAAWD,EAAM,MAAO,SAAG,MAAA,EAChCF,EAAA,KAAA,MAAA,CAAI,UAAWE,EAAM,gBACpB,SAAA,CAACC,EAAAA,IAAAgB,EAAA,CAAQ,KAAK,mBAAmB,aAASC,EAAc,CAAA,UAAWlB,EAAM,IAAA,CAAM,CAAI,CAAA,EAClFY,EAAsB,EACrBX,EAAA,IAACgB,EAAA,CACC,KAAM,sBAAsBL,EAAsB,CAAC,QACnD,OAAQX,EAAAA,IAAC,OAAK,CAAA,UAAWF,EAAG,CAACC,EAAM,KAAMA,EAAM,OAAO,CAAC,EAAG,kBAAiBY,CAAqB,CAAA,EAE/F,SAAAI,CAAA,CAAA,EAGHf,EAAAA,IAAC,OAAK,CAAA,UAAWF,EAAG,CAACC,EAAM,KAAMI,IAAe,MAAQJ,EAAM,KAAK,CAAC,EAAI,SAAegB,CAAA,CAAA,CAAA,EAE3F,EACClB,EAAA,KAAA,MAAA,CAAI,UAAWE,EAAM,gBACpB,SAAA,CAACC,EAAAA,IAAAgB,EAAA,CAAQ,KAAK,oBAAoB,aAASG,EAAe,CAAA,UAAWpB,EAAM,IAAA,CAAM,CAAI,CAAA,EACpFc,IAAqB,MAAQC,EAAuB,EACnDd,EAAA,IAACgB,EAAA,CACC,KAAM,sBAAsBF,EAAuB,CAAC,QACpD,OAAQd,EAAAA,IAAC,OAAK,CAAA,UAAWF,EAAG,CAACC,EAAM,KAAMA,EAAM,OAAO,CAAC,EAAG,kBAAiBe,CAAsB,CAAA,EAEhG,WAAcD,CAAgB,CAAA,CAAA,EAGhCb,EAAAA,IAAA,OAAA,CAAK,UAAWF,EAAG,CAACC,EAAM,KAAMc,IAAqB,MAAQd,EAAM,KAAK,CAAC,EACvE,SAAAf,EAAc6B,CAAgB,CACjC,CAAA,CAAA,CAEJ,CAAA,CAAA,CACF,CAAA,CAAA,EACF,CAEJ,CAEO,SAASO,IAAgB,CAC9B,OACGvB,EAAAA,KAAA,MAAA,CAAI,UAAWE,EAAM,OACpB,SAAA,CAAAC,EAAA,IAACqB,GAAW,EAAA,QACXC,GAAU,CAAA,CAAA,CAAA,EACb,CAEJ,CAEA,SAASD,IAAa,CACd,KAAA,CAAE,MAAAE,EAAO,KAAAC,EAAM,iBAAAC,EAAkB,iBAAAC,EAAkB,WAAAC,EAAY,SAAAC,GAAaC,EAAsB,EAClG,CAAE,eAAAC,CAAe,EAAIC,EAAkB,EACvCC,EAAQC,EAASH,CAAc,EAE/BI,EAASC,EAAiBP,CAAQ,EAGlCQ,GAAmB,IAAM,CAE7B,GADI,CAACF,GACD,CAACF,GAASA,EAAM,YAAc,KAAa,OAAA,KACzC,MAAAK,EAAkBd,EAAQI,EAAarC,EAEtC,OAAAkC,IAASc,EAAW,SACvBN,EAAM,UAAYA,EAAM,SAAWK,EACnCX,EAAmBM,EAAM,SAAWK,CAAA,GACvC,EAEGE,EAA2B5D,EAAcyD,EAAiB,EAAGI,EAAU,SAAS,EAEhFC,EAAmBhB,IAAqB,KAAOA,EAAmBF,EAAQ,KAC1EmB,EAA4B/D,EAAc8D,EAAkB,EAAGD,EAAU,SAAS,EAExF,OACG3C,EAAAA,KAAA,MAAA,CAAI,UAAWE,EAAM,YACpB,SAAA,CAAAC,EAAA,IAAC,OAAK,CAAA,UAAWgC,GAAA,MAAAA,EAAO,MAAQjC,EAAM,WAAaA,EAAM,MAAQ,SAAG,IAAAiC,GAAA,YAAAA,EAAO,QAAS,OAAO,IAAI,EAC9FnC,EAAA,KAAA,MAAA,CAAI,UAAWE,EAAM,gBACpB,SAAA,CAACC,EAAAA,IAAAgB,EAAA,CAAQ,KAAK,4BAA4B,aAAS2B,EAAY,CAAA,UAAW5C,EAAM,IAAA,CAAM,CAAI,CAAA,EAC1FC,EAAA,IAAC,OAAA,CACC,UAAWF,EAAG,CACZC,EAAM,MACL,CAACiC,GAAS,CAACE,IAAWnC,EAAM,MAC7BwC,IAA6B,OAASxC,EAAM,OAAA,CAC7C,EAEA,SAAAwC,CAAA,CAAA,CACH,EACF,EACC1C,EAAA,KAAA,MAAA,CAAI,UAAWE,EAAM,gBACpB,SAAA,CAACC,EAAAA,IAAAgB,EAAA,CAAQ,KAAK,6BAA6B,aAAS4B,EAAa,CAAA,UAAW7C,EAAM,IAAA,CAAM,CAAI,CAAA,EAC5FC,EAAA,IAAC,OAAA,CACC,UAAWF,EAAG,CACZC,EAAM,KACN,CAAC0B,GAAoB1B,EAAM,MAC3B2C,IAA8B,OAAS3C,EAAM,OAAA,CAC9C,EAEA,SAAA2C,CAAA,CAAA,CACH,CACF,CAAA,CAAA,EACF,CAEJ,CAEA,SAASpB,IAAY,CACb,KAAA,CAAE,MAAAC,EAAO,KAAAC,EAAM,YAAAnB,EAAa,aAAAD,EAAc,SAAAwB,EAAU,WAAAD,GAAekB,EAAqB,EACxF,CAAE,GAAAC,EAAI,cAAAC,CAAc,EAAIC,EAAY,EACpCC,EAAQhB,EAASa,CAAE,EAEnBZ,EAASC,EAAiBP,CAAQ,EAElCsB,GAAoB,IAAM,CAE1B,GADA,CAAChB,GACD,CAACe,EAAc,OAAA,KACnB,MAAME,EAAsBF,EAAM,UAAYA,EAAM,UAAY3D,EAC1D+C,EAAkBd,EAAQI,EAAarC,EAC7C,OAAOkC,IAASc,EAAW,SACvBa,EAAsBd,EACtBc,EAAsB9C,EAAcD,EAAeiC,CAAA,GACtD,EAEGe,EAA0BzE,EAAcuE,EAAkB,EAAGV,EAAU,SAAS,EAEhFa,EAAoBN,IAAkB,KAAOA,EAAgBxB,EAAQ,KACrE+B,EAA2B3E,EAAc0E,EAAmB,EAAGb,EAAU,SAAS,EAElFe,GAAQN,GAAA,YAAAA,EAAO,QAAS,KAE9B,OACGpD,EAAAA,KAAA,MAAA,CAAI,UAAWE,EAAM,YACpB,SAAA,CAACC,EAAA,IAAA,OAAA,CAAK,UAAWuD,EAAQxD,EAAM,WAAaA,EAAM,MAAQ,SAAA,GAAGwD,GAAS,MAAM,GAAI,CAAA,EAC/E1D,EAAA,KAAA,MAAA,CAAI,UAAWE,EAAM,gBACpB,SAAA,CAACC,EAAAA,IAAAgB,EAAA,CAAQ,KAAK,kCAAkC,aAASwC,EAAU,CAAA,UAAWzD,EAAM,IAAA,CAAM,CAAI,CAAA,EAC9FC,EAAA,IAAC,OAAA,CACC,cAAY,oBACZ,UAAWF,EAAG,CACZC,EAAM,MACL,CAACkD,GAAS,CAACf,IAAWnC,EAAM,MAC7BqD,IAA4B,OAASrD,EAAM,OAAA,CAC5C,EAEA,SAAAqD,CAAA,CAAA,CACH,EACF,EACCvD,EAAA,KAAA,MAAA,CAAI,UAAWE,EAAM,gBACpB,SAAA,CAACC,EAAAA,IAAAgB,EAAA,CAAQ,KAAK,mCAAmC,aAASyC,EAAW,CAAA,UAAW1D,EAAM,IAAA,CAAM,CAAI,CAAA,EAChGC,EAAA,IAAC,OAAA,CACC,cAAY,qBACZ,UAAWF,EAAG,CACZC,EAAM,KACNsD,IAAsB,MAAQtD,EAAM,MACpCuD,IAA6B,OAASvD,EAAM,OAAA,CAC7C,EAEA,SAAAuD,CAAA,CAAA,CACH,CACF,CAAA,CAAA,EACF,CAEJ,CAEO,SAASI,IAAmB,CACjC,KAAM,CAAE,UAAAC,EAAW,mBAAAC,CAAmB,EAAIC,EAAoB,EAExDC,EAAUF,IAAuB,KAAOA,EAAqB,EAAIG,EACjEC,EAAeL,EAAY,GAAGG,CAAO,OAAOH,GAAaI,CAAM,GAAKA,EAEnE,OAAA/D,EAAA,IAACT,EAAW,CAAA,MAAM,WAAW,MAAOyE,EAAc,MAAOJ,IAAuB,KAAO,QAAU,QAAU,CAAA,CACpH,CAEO,SAASK,IAAiB,CAC/B,KAAM,CAAE,OAAAC,EAAQ,SAAAtC,CAAS,EAAIuC,EAAkB,EAEzCC,EAAYjC,EAAiBP,CAAQ,EACrCyC,EAAcC,GAAeF,EAAYF,EAAS,IAAI,EACtDK,EAAaC,GAAcJ,EAAYF,EAAS,IAAI,EAE1D,aAAQjE,GAAU,CAAA,MAAOoE,EAAa,MAAOE,EAAY,OAAO,SAAS,CAC3E,CAEgB,SAAAE,GAAc,CAAE,UAAA9E,GAAqC,CAC7D,KAAA,CAAE,MAAA4B,CAAM,EAAImD,EAAS,EACrBC,EAAiBlE,EAAWc,CAAK,EAEvC,aAAQhC,EAAW,CAAA,MAAM,WAAW,MAAOoF,EAAgB,UAAAhF,EAAsB,CACnF,CAEgB,SAAAiF,GAAc,CAAE,UAAAjF,GAAqC,CACnE,MAAMkF,EAAQC,EAAS,EAEjBC,EAAYF,EAAM,QAAUG,EAAW,QACvCzB,EAAQwB,EAAY,iBAAmB,gBACvCE,EAAUhG,EAAe8F,EAAYF,EAAM,eAAiBA,EAAM,QAAS,CAAE,SAAU3F,EAAkB,EACzGgG,EACAH,EAAkB,UAClBF,EAAM,UAAY,KAAa,QAC5B,SAGF,OAAA7E,MAACT,GAAW,MAAOgE,EAAO,MAAO0B,EAAS,MAAOC,EAAY,UAAAvF,EAAsB,CAC5F"}
@@ -1,2 +1,2 @@
1
- import{v as D,j as y,h as t}from"./vendor-CCiSQ9k9.js";import{y as E,af as T,i as N}from"./index-BQEUaoAf.js";import{p as j}from"./parseUserTime-BeTKj08M.js";(function(){try{var s=typeof window<"u"?window:typeof global<"u"?global:typeof globalThis<"u"?globalThis:typeof self<"u"?self:{},n=new s.Error().stack;n&&(s._sentryDebugIds=s._sentryDebugIds||{},s._sentryDebugIds[n]="9eebc2bb-beb6-4d32-9344-4a0efa77cd31",s._sentryDebugIdIdentifier="sentry-dbid-9eebc2bb-beb6-4d32-9344-4a0efa77cd31")}catch{}})();const A="_link_1myua_17",R={link:A};function L({search:s,children:n}){const r=D(),a=()=>r({search:s});return y.jsx("button",{onClick:a,className:R.link,children:n})}const S="_timeInput_1u25s_17",w="_delayed_1u25s_23",p={timeInput:S,delayed:w};function M({id:s,name:n,submitHandler:r,time:a,placeholder:g,disabled:k,align:I="center",delayed:_,className:h}){const l=t.useRef(null),[m,o]=t.useState(""),i=t.useRef(!1),u=t.useCallback(()=>{typeof a!="number"||isNaN(a)?o("00:00:00"):o(E(a))},[a]),C=t.useCallback(()=>{var e;(e=l.current)==null||e.select()},[]),f=t.useCallback(e=>e===""?!1:e.startsWith("p")||e.startsWith("+")?(r(n,e),!0):j(e)===a?!1:(r(n,e),!0),[n,r,a]),d=t.useCallback(e=>{f(e)||u()},[f,u]),v=t.useCallback(e=>{var c,b;e.key==="Enter"&&((c=l.current)==null||c.blur()),e.key==="Escape"&&(i.current=!0,(b=l.current)==null||b.blur(),u())},[u]),x=t.useCallback(e=>{if(i.current){i.current=!1;return}d(e.target.value)},[d]);return t.useEffect(()=>{u()},[u]),y.jsx(T,{id:s,disabled:k,ref:l,"data-testid":`time-input-${n}`,className:N([p.timeInput,_&&p.delayed,h]),placeholder:g,onFocus:C,onChange:e=>o(e.target.value),onBlur:x,onKeyDown:v,value:m,maxLength:8,style:{textAlign:I}})}export{L as A,M as T,p as s};
2
- //# sourceMappingURL=TimeInput-Dg1naiy3.js.map
1
+ import{v as D,j as y,h as t}from"./vendor-9UkPSc5K.js";import{y as E,af as T,i as N}from"./index-njXwwjfn.js";import{p as j}from"./parseUserTime-Bc1pSJR2.js";(function(){try{var s=typeof window<"u"?window:typeof global<"u"?global:typeof globalThis<"u"?globalThis:typeof self<"u"?self:{},n=new s.Error().stack;n&&(s._sentryDebugIds=s._sentryDebugIds||{},s._sentryDebugIds[n]="9eebc2bb-beb6-4d32-9344-4a0efa77cd31",s._sentryDebugIdIdentifier="sentry-dbid-9eebc2bb-beb6-4d32-9344-4a0efa77cd31")}catch{}})();const A="_link_1myua_17",R={link:A};function L({search:s,children:n}){const r=D(),a=()=>r({search:s});return y.jsx("button",{onClick:a,className:R.link,children:n})}const S="_timeInput_1u25s_17",w="_delayed_1u25s_23",p={timeInput:S,delayed:w};function M({id:s,name:n,submitHandler:r,time:a,placeholder:g,disabled:k,align:I="center",delayed:_,className:h}){const l=t.useRef(null),[m,o]=t.useState(""),i=t.useRef(!1),u=t.useCallback(()=>{typeof a!="number"||isNaN(a)?o("00:00:00"):o(E(a))},[a]),C=t.useCallback(()=>{var e;(e=l.current)==null||e.select()},[]),f=t.useCallback(e=>e===""?!1:e.startsWith("p")||e.startsWith("+")?(r(n,e),!0):j(e)===a?!1:(r(n,e),!0),[n,r,a]),d=t.useCallback(e=>{f(e)||u()},[f,u]),v=t.useCallback(e=>{var c,b;e.key==="Enter"&&((c=l.current)==null||c.blur()),e.key==="Escape"&&(i.current=!0,(b=l.current)==null||b.blur(),u())},[u]),x=t.useCallback(e=>{if(i.current){i.current=!1;return}d(e.target.value)},[d]);return t.useEffect(()=>{u()},[u]),y.jsx(T,{id:s,disabled:k,ref:l,"data-testid":`time-input-${n}`,className:N([p.timeInput,_&&p.delayed,h]),placeholder:g,onFocus:C,onChange:e=>o(e.target.value),onBlur:x,onKeyDown:v,value:m,maxLength:8,style:{textAlign:I}})}export{L as A,M as T,p as s};
2
+ //# sourceMappingURL=TimeInput-DU09ewqh.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"TimeInput-Dg1naiy3.js","sources":["../../src/common/components/link/app-link/AppLink.tsx","../../src/common/components/input/time-input/TimeInput.tsx"],"sourcesContent":["import { type PropsWithChildren } from 'react';\nimport { useNavigate } from 'react-router';\n\nimport style from './AppLink.module.scss';\n\ninterface AppLinkProps {\n search: string;\n}\n\n/**\n * Component used to navigate to an editor link inside the same window\n * Handles the path to respect Ontime Clouds base URL\n */\nexport default function AppLink({ search, children }: PropsWithChildren<AppLinkProps>) {\n const navigate = useNavigate();\n\n const handleClick = () => navigate({ search });\n\n return (\n <button onClick={handleClick} className={style.link}>\n {children}\n </button>\n );\n}\n","import { FocusEvent, KeyboardEvent, useCallback, useEffect, useRef, useState } from 'react';\nimport { millisToString, parseUserTime } from 'ontime-utils';\n\nimport { cx } from '../../../utils/styleUtils';\nimport Input from '../input/Input';\n\nimport style from './TimeInput.module.scss';\n\ninterface TimeInputProps<T extends string> {\n id?: T;\n name: T;\n submitHandler: (field: T, value: string) => void;\n time?: number;\n placeholder?: string;\n disabled?: boolean;\n align?: 'left' | 'center';\n delayed?: boolean;\n className?: string;\n}\n\nexport default function TimeInput<T extends string>({\n id,\n name,\n submitHandler,\n time,\n placeholder,\n disabled,\n align = 'center',\n delayed,\n className,\n}: TimeInputProps<T>) {\n const inputRef = useRef<HTMLInputElement | null>(null);\n const [value, setValue] = useState<string>('');\n const ignoreChange = useRef(false);\n\n /**\n * @description Resets input value to given\n */\n const resetValue = useCallback(() => {\n if (typeof time !== 'number' || isNaN(time)) {\n setValue('00:00:00');\n } else {\n setValue(millisToString(time));\n }\n }, [time]);\n\n /**\n * @description Selects input text on focus\n */\n const handleFocus = useCallback(() => {\n inputRef.current?.select();\n }, []);\n\n /**\n * @description Submit handler\n * @param {string} newValue\n */\n const handleSubmit = useCallback(\n (newValue: string) => {\n // Check if there is anything there\n if (newValue === '') {\n return false;\n }\n\n // we dont know the values in the rundown, escalate to handler\n if (newValue.startsWith('p') || newValue.startsWith('+')) {\n submitHandler(name, newValue);\n return true;\n }\n\n const valueInMillis = parseUserTime(newValue);\n if (valueInMillis === time) {\n return false;\n }\n\n submitHandler(name, newValue);\n return true;\n },\n [name, submitHandler, time],\n );\n\n /**\n * @description Prepare time fields\n * @param {string} value string to be parsed\n */\n const validateAndSubmit = useCallback(\n (newValue: string) => {\n const success = handleSubmit(newValue);\n if (!success) {\n resetValue();\n }\n },\n [handleSubmit, resetValue],\n );\n\n /**\n * @description Handles common keys for submit and cancel\n * @param {KeyboardEvent} event\n */\n const onKeyDownHandler = useCallback(\n (event: KeyboardEvent<HTMLInputElement>) => {\n if (event.key === 'Enter') {\n inputRef.current?.blur();\n }\n if (event.key === 'Escape') {\n ignoreChange.current = true;\n inputRef.current?.blur();\n resetValue();\n }\n },\n [resetValue],\n );\n\n const onBlurHandler = useCallback(\n (event: FocusEvent<HTMLInputElement>) => {\n if (ignoreChange.current) {\n ignoreChange.current = false;\n return;\n }\n validateAndSubmit((event.target as HTMLInputElement).value);\n },\n [validateAndSubmit],\n );\n\n useEffect(() => {\n resetValue();\n }, [resetValue]);\n\n return (\n <Input\n id={id}\n disabled={disabled}\n ref={inputRef}\n data-testid={`time-input-${name}`}\n className={cx([style.timeInput, delayed && style.delayed, className])}\n placeholder={placeholder}\n onFocus={handleFocus}\n onChange={(event) => setValue(event.target.value)}\n onBlur={onBlurHandler}\n onKeyDown={onKeyDownHandler}\n value={value}\n maxLength={8}\n style={{\n textAlign: align,\n }}\n />\n );\n}\n"],"names":["AppLink","search","children","navigate","useNavigate","handleClick","style","TimeInput","id","name","submitHandler","time","placeholder","disabled","align","delayed","className","inputRef","useRef","value","setValue","useState","ignoreChange","resetValue","useCallback","millisToString","handleFocus","_a","handleSubmit","newValue","parseUserTime","validateAndSubmit","onKeyDownHandler","event","_b","onBlurHandler","useEffect","jsx","Input","cx"],"mappings":"4hBAaA,SAAwBA,EAAQ,CAAE,OAAAC,EAAQ,SAAAC,GAA6C,CACrF,MAAMC,EAAWC,EAAY,EAEvBC,EAAc,IAAMF,EAAS,CAAE,OAAAF,EAAQ,EAE7C,aACG,SAAO,CAAA,QAASI,EAAa,UAAWC,EAAM,KAC5C,SAAAJ,EACH,CAEJ,+ECHA,SAAwBK,EAA4B,CAClD,GAAAC,EACA,KAAAC,EACA,cAAAC,EACA,KAAAC,EACA,YAAAC,EACA,SAAAC,EACA,MAAAC,EAAQ,SACR,QAAAC,EACA,UAAAC,CACF,EAAsB,CACd,MAAAC,EAAWC,SAAgC,IAAI,EAC/C,CAACC,EAAOC,CAAQ,EAAIC,EAAAA,SAAiB,EAAE,EACvCC,EAAeJ,SAAO,EAAK,EAK3BK,EAAaC,EAAAA,YAAY,IAAM,CAC/B,OAAOb,GAAS,UAAY,MAAMA,CAAI,EACxCS,EAAS,UAAU,EAEVA,EAAAK,EAAed,CAAI,CAAC,CAC/B,EACC,CAACA,CAAI,CAAC,EAKHe,EAAcF,EAAAA,YAAY,IAAM,QACpCG,EAAAV,EAAS,UAAT,MAAAU,EAAkB,QACpB,EAAG,EAAE,EAMCC,EAAeJ,EAAA,YAClBK,GAEKA,IAAa,GACR,GAILA,EAAS,WAAW,GAAG,GAAKA,EAAS,WAAW,GAAG,GACrDnB,EAAcD,EAAMoB,CAAQ,EACrB,IAGaC,EAAcD,CAAQ,IACtBlB,EACb,IAGTD,EAAcD,EAAMoB,CAAQ,EACrB,IAET,CAACpB,EAAMC,EAAeC,CAAI,CAC5B,EAMMoB,EAAoBP,EAAA,YACvBK,GAAqB,CACJD,EAAaC,CAAQ,GAExBN,EAAA,CAEf,EACA,CAACK,EAAcL,CAAU,CAC3B,EAMMS,EAAmBR,EAAA,YACtBS,GAA2C,SACtCA,EAAM,MAAQ,WAChBN,EAAAV,EAAS,UAAT,MAAAU,EAAkB,QAEhBM,EAAM,MAAQ,WAChBX,EAAa,QAAU,IACvBY,EAAAjB,EAAS,UAAT,MAAAiB,EAAkB,OACPX,EAAA,EAEf,EACA,CAACA,CAAU,CACb,EAEMY,EAAgBX,EAAA,YACnBS,GAAwC,CACvC,GAAIX,EAAa,QAAS,CACxBA,EAAa,QAAU,GACvB,MAAA,CAEiBS,EAAAE,EAAM,OAA4B,KAAK,CAC5D,EACA,CAACF,CAAiB,CACpB,EAEAK,OAAAA,EAAAA,UAAU,IAAM,CACHb,EAAA,CAAA,EACV,CAACA,CAAU,CAAC,EAGbc,EAAA,IAACC,EAAA,CACC,GAAA9B,EACA,SAAAK,EACA,IAAKI,EACL,cAAa,cAAcR,CAAI,GAC/B,UAAW8B,EAAG,CAACjC,EAAM,UAAWS,GAAWT,EAAM,QAASU,CAAS,CAAC,EACpE,YAAAJ,EACA,QAASc,EACT,SAAWO,GAAUb,EAASa,EAAM,OAAO,KAAK,EAChD,OAAQE,EACR,UAAWH,EACX,MAAAb,EACA,UAAW,EACX,MAAO,CACL,UAAWL,CAAA,CACb,CACF,CAEJ"}
1
+ {"version":3,"file":"TimeInput-DU09ewqh.js","sources":["../../src/common/components/link/app-link/AppLink.tsx","../../src/common/components/input/time-input/TimeInput.tsx"],"sourcesContent":["import { type PropsWithChildren } from 'react';\nimport { useNavigate } from 'react-router';\n\nimport style from './AppLink.module.scss';\n\ninterface AppLinkProps {\n search: string;\n}\n\n/**\n * Component used to navigate to an editor link inside the same window\n * Handles the path to respect Ontime Clouds base URL\n */\nexport default function AppLink({ search, children }: PropsWithChildren<AppLinkProps>) {\n const navigate = useNavigate();\n\n const handleClick = () => navigate({ search });\n\n return (\n <button onClick={handleClick} className={style.link}>\n {children}\n </button>\n );\n}\n","import { FocusEvent, KeyboardEvent, useCallback, useEffect, useRef, useState } from 'react';\nimport { millisToString, parseUserTime } from 'ontime-utils';\n\nimport { cx } from '../../../utils/styleUtils';\nimport Input from '../input/Input';\n\nimport style from './TimeInput.module.scss';\n\ninterface TimeInputProps<T extends string> {\n id?: T;\n name: T;\n submitHandler: (field: T, value: string) => void;\n time?: number;\n placeholder?: string;\n disabled?: boolean;\n align?: 'left' | 'center';\n delayed?: boolean;\n className?: string;\n}\n\nexport default function TimeInput<T extends string>({\n id,\n name,\n submitHandler,\n time,\n placeholder,\n disabled,\n align = 'center',\n delayed,\n className,\n}: TimeInputProps<T>) {\n const inputRef = useRef<HTMLInputElement | null>(null);\n const [value, setValue] = useState<string>('');\n const ignoreChange = useRef(false);\n\n /**\n * @description Resets input value to given\n */\n const resetValue = useCallback(() => {\n if (typeof time !== 'number' || isNaN(time)) {\n setValue('00:00:00');\n } else {\n setValue(millisToString(time));\n }\n }, [time]);\n\n /**\n * @description Selects input text on focus\n */\n const handleFocus = useCallback(() => {\n inputRef.current?.select();\n }, []);\n\n /**\n * @description Submit handler\n * @param {string} newValue\n */\n const handleSubmit = useCallback(\n (newValue: string) => {\n // Check if there is anything there\n if (newValue === '') {\n return false;\n }\n\n // we dont know the values in the rundown, escalate to handler\n if (newValue.startsWith('p') || newValue.startsWith('+')) {\n submitHandler(name, newValue);\n return true;\n }\n\n const valueInMillis = parseUserTime(newValue);\n if (valueInMillis === time) {\n return false;\n }\n\n submitHandler(name, newValue);\n return true;\n },\n [name, submitHandler, time],\n );\n\n /**\n * @description Prepare time fields\n * @param {string} value string to be parsed\n */\n const validateAndSubmit = useCallback(\n (newValue: string) => {\n const success = handleSubmit(newValue);\n if (!success) {\n resetValue();\n }\n },\n [handleSubmit, resetValue],\n );\n\n /**\n * @description Handles common keys for submit and cancel\n * @param {KeyboardEvent} event\n */\n const onKeyDownHandler = useCallback(\n (event: KeyboardEvent<HTMLInputElement>) => {\n if (event.key === 'Enter') {\n inputRef.current?.blur();\n }\n if (event.key === 'Escape') {\n ignoreChange.current = true;\n inputRef.current?.blur();\n resetValue();\n }\n },\n [resetValue],\n );\n\n const onBlurHandler = useCallback(\n (event: FocusEvent<HTMLInputElement>) => {\n if (ignoreChange.current) {\n ignoreChange.current = false;\n return;\n }\n validateAndSubmit((event.target as HTMLInputElement).value);\n },\n [validateAndSubmit],\n );\n\n useEffect(() => {\n resetValue();\n }, [resetValue]);\n\n return (\n <Input\n id={id}\n disabled={disabled}\n ref={inputRef}\n data-testid={`time-input-${name}`}\n className={cx([style.timeInput, delayed && style.delayed, className])}\n placeholder={placeholder}\n onFocus={handleFocus}\n onChange={(event) => setValue(event.target.value)}\n onBlur={onBlurHandler}\n onKeyDown={onKeyDownHandler}\n value={value}\n maxLength={8}\n style={{\n textAlign: align,\n }}\n />\n );\n}\n"],"names":["AppLink","search","children","navigate","useNavigate","handleClick","style","TimeInput","id","name","submitHandler","time","placeholder","disabled","align","delayed","className","inputRef","useRef","value","setValue","useState","ignoreChange","resetValue","useCallback","millisToString","handleFocus","_a","handleSubmit","newValue","parseUserTime","validateAndSubmit","onKeyDownHandler","event","_b","onBlurHandler","useEffect","jsx","Input","cx"],"mappings":"4hBAaA,SAAwBA,EAAQ,CAAE,OAAAC,EAAQ,SAAAC,GAA6C,CACrF,MAAMC,EAAWC,EAAY,EAEvBC,EAAc,IAAMF,EAAS,CAAE,OAAAF,EAAQ,EAE7C,aACG,SAAO,CAAA,QAASI,EAAa,UAAWC,EAAM,KAC5C,SAAAJ,EACH,CAEJ,+ECHA,SAAwBK,EAA4B,CAClD,GAAAC,EACA,KAAAC,EACA,cAAAC,EACA,KAAAC,EACA,YAAAC,EACA,SAAAC,EACA,MAAAC,EAAQ,SACR,QAAAC,EACA,UAAAC,CACF,EAAsB,CACd,MAAAC,EAAWC,SAAgC,IAAI,EAC/C,CAACC,EAAOC,CAAQ,EAAIC,EAAAA,SAAiB,EAAE,EACvCC,EAAeJ,SAAO,EAAK,EAK3BK,EAAaC,EAAAA,YAAY,IAAM,CAC/B,OAAOb,GAAS,UAAY,MAAMA,CAAI,EACxCS,EAAS,UAAU,EAEVA,EAAAK,EAAed,CAAI,CAAC,CAC/B,EACC,CAACA,CAAI,CAAC,EAKHe,EAAcF,EAAAA,YAAY,IAAM,QACpCG,EAAAV,EAAS,UAAT,MAAAU,EAAkB,QACpB,EAAG,EAAE,EAMCC,EAAeJ,EAAA,YAClBK,GAEKA,IAAa,GACR,GAILA,EAAS,WAAW,GAAG,GAAKA,EAAS,WAAW,GAAG,GACrDnB,EAAcD,EAAMoB,CAAQ,EACrB,IAGaC,EAAcD,CAAQ,IACtBlB,EACb,IAGTD,EAAcD,EAAMoB,CAAQ,EACrB,IAET,CAACpB,EAAMC,EAAeC,CAAI,CAC5B,EAMMoB,EAAoBP,EAAA,YACvBK,GAAqB,CACJD,EAAaC,CAAQ,GAExBN,EAAA,CAEf,EACA,CAACK,EAAcL,CAAU,CAC3B,EAMMS,EAAmBR,EAAA,YACtBS,GAA2C,SACtCA,EAAM,MAAQ,WAChBN,EAAAV,EAAS,UAAT,MAAAU,EAAkB,QAEhBM,EAAM,MAAQ,WAChBX,EAAa,QAAU,IACvBY,EAAAjB,EAAS,UAAT,MAAAiB,EAAkB,OACPX,EAAA,EAEf,EACA,CAACA,CAAU,CACb,EAEMY,EAAgBX,EAAA,YACnBS,GAAwC,CACvC,GAAIX,EAAa,QAAS,CACxBA,EAAa,QAAU,GACvB,MAAA,CAEiBS,EAAAE,EAAM,OAA4B,KAAK,CAC5D,EACA,CAACF,CAAiB,CACpB,EAEAK,OAAAA,EAAAA,UAAU,IAAM,CACHb,EAAA,CAAA,EACV,CAACA,CAAU,CAAC,EAGbc,EAAA,IAACC,EAAA,CACC,GAAA9B,EACA,SAAAK,EACA,IAAKI,EACL,cAAa,cAAcR,CAAI,GAC/B,UAAW8B,EAAG,CAACjC,EAAM,UAAWS,GAAWT,EAAM,QAASU,CAAS,CAAC,EACpE,YAAAJ,EACA,QAASc,EACT,SAAWO,GAAUb,EAASa,EAAM,OAAO,KAAK,EAChD,OAAQE,EACR,UAAWH,EACX,MAAAb,EACA,UAAW,EACX,MAAO,CACL,UAAWL,CAAA,CACb,CACF,CAEJ"}
@@ -1,2 +1,2 @@
1
- import{h as p,l as U,j as i,y as W}from"./vendor-CCiSQ9k9.js";import{r as w,P as q,H as E,l as N,M as C,g as O,I as F,i as b,J as G,q as $,f as B,v as M,d as J,L as Q,o as K,h as X,O as Y,s as Z}from"./index-BQEUaoAf.js";import{E as tt}from"./EmptyPage-Dcbg6rmF.js";import{V as et}from"./ViewLogo-_3Z1hIHi.js";import{O as I,i as H,V as st}from"./ViewParamsEditor-Bca1TIDW.js";import{u as nt}from"./useWindowTitle-DqdFTWns.js";import{S as it}from"./SuperscriptTime-CIrcMcyg.js";import{i as j,a as v,d as ot,u as at}from"./useRundown-BfpjcCEJ.js";import{g as rt,a as lt}from"./viewLoader.utils-CmM-4-pk.js";import{g as ct,a as z,b as ut,c as mt}from"./rundownUtils-BZHazkXR.js";import{g as dt}from"./getProgress-Cw79NL_O.js";import{u as ft}from"./useProjectData-C1hVamxc.js";import"./Empty-gWT_HMeu.js";import"./Select-CedN80WS.js";(function(){try{var e=typeof window<"u"?window:typeof global<"u"?global:typeof globalThis<"u"?globalThis:typeof self<"u"?self:{},t=new e.Error().stack;t&&(e._sentryDebugIds=e._sentryDebugIds||{},e._sentryDebugIds[t]="dfaa0d47-8699-4c7a-a83a-9e2e9fabfe7e",e._sentryDebugIdIdentifier="sentry-dbid-dfaa0d47-8699-4c7a-a83a-9e2e9fabfe7e")}catch{}})();function ht(e,t){if(!t)return 0;const s=e.timeStart+e.dayOffset*w,n=t.timeStart+t.duration+t.dayOffset*w;return s===n?0:(s>n,s-n)}function D(e,t,s){if(!t.current)return;if(!(e!=null&&e.current)){t.current.scrollTo({left:0,behavior:"smooth"});return}const n=e.current.getBoundingClientRect(),a=t.current.getBoundingClientRect(),o=n.left-a.left+t.current.scrollLeft-s;t.current.scrollTo({left:o,behavior:"smooth"})}function pt({followRef:e,scrollRef:t,doFollow:s,selectedEventId:n,leftOffset:a=0,setScrollFlag:o}){return p.useEffect(()=>{!s||!t.current||(o==null||o(!0),window.requestAnimationFrame(()=>{D(n!==null?e:null,t,a),o==null||o(!1)}))},[e,t,s,a,o,n]),p.useCallback((u=e,m=t,c=a)=>{m.current&&D(n!==null?u:null,m,c)},[e,t,a,n])}const xt=e=>[{title:I.ClockOptions,collapsible:!0,options:[rt(e)]},{title:I.ElementVisibility,collapsible:!0,options:[{id:"hidePast",title:"Hide Past Events",description:"Whether to hide events that have passed",type:"boolean",defaultValue:!1},{id:"autosize",title:"Autosize timeline",description:"Timeline will adjust sizes to help with readability and automatically scroll if necessary",type:"boolean",defaultValue:!1}]}];function gt(e,t){const s=n=>(t==null?void 0:t.get(n))??e.get(n);return{hidePast:H(s("hidePast")),autosize:H(s("autosize"))}}function R(){const[e]=U(),t=p.use(q);return p.useMemo(()=>{const n=t?new URLSearchParams(t.search):void 0;return gt(e,n)},[t,e])}function _t(e,t,s,n,a){const r=(t<e?t+w:t)-e,u=n*a/r;return{left:(s-e)*a/r,width:u}}function yt(e){return Math.floor(e/E)}function bt(e){return Math.ceil(e/E)}function Tt(e,t){const s=[];for(let n=e;n<t;n++)s.push(n);return s}function jt(e,t){return t==="done"||t==="live"?t:e<=0?"pending":N(e,e>C*2)}function wt(e,t){const{hidePast:s}=R();return p.useMemo(()=>{if(e.length===0)return{scopedRundown:[],firstStart:0,totalDuration:0};const a=[];let o=t?1/0:-1,r=null,u=0,m=null;for(let c=0;c<e.length;c++){const l=e[c];if(j(l)&&v(l)){if(l.id===t&&(o=c),s&&c<o)continue;a.push(l),r===null&&(r=l.timeStart);const d=ht(l,m);d===0?u+=l.duration:d>0?u+=d+l.duration:d<0&&(u+=Math.max(l.duration+d,0)),ot(l,m)&&(m=l)}}return{scopedRundown:a,firstStart:r??0,totalDuration:u}},[s,e,t])}function St(e,t){var o,r;if(e.length===0)return{now:null,next:null,followedBy:null};let s=t?ct(e,t):null;j(s)||(s=null);const n=s?(o=z(e,s.id))==null?void 0:o.nextEvent:ut(e).firstEvent,a=n?(r=z(e,n.id))==null?void 0:r.nextEvent:null;return{now:s,next:n,followedBy:a}}function vt(e,t,s,n,a,o=100){let r=1/0;const u=e.map(({start:l,duration:d})=>{const g=_t(t,s,l,d,n);return r=Math.min(r,g.width),g});if(!a)return{positions:u,scale:1,totalWidth:n};const m=r<o?o/r:1;return m===1?{positions:u,scale:1,totalWidth:n}:{positions:u.map(l=>({left:l.left*m,width:l.width*m})),scale:m,totalWidth:n*m}}const Et="_markers_gfywu_17",Nt={markers:Et};function Pt(e){const{startHour:t,endHour:s}=e,n=Tt(t,s);return i.jsx("div",{className:Nt.markers,children:n.map(a=>i.jsx("span",{},a))})}const Lt="_timelineContainer_4bums_21",kt="_scroll_4bums_26",Ct="_timeline_4bums_21",Ot="_column_4bums_37",Mt="_maybeInline_4bums_45",Bt="_timelineBlock_4bums_52",It="_smallArea_4bums_64",Ht="_content_4bums_64",zt="_timeOverview_4bums_68",Dt="_hide_4bums_72",At="_status_4bums_98",Vt="_delay_4bums_105",$t="_cross_4bums_115",Rt="_separeLeft_4bums_121",h={timelineContainer:Lt,scroll:kt,timeline:Ct,column:Ot,maybeInline:Mt,timelineBlock:Bt,smallArea:It,content:Ht,timeOverview:zt,hide:Dt,status:At,delay:Vt,cross:$t,separeLeft:Rt},A={format12:"hh:mm a",format24:"HH:mm"};function Ut({colour:e,delay:t,duration:s,hasLink:n,left:a,status:o,start:r,dayOffset:u,totalGap:m,isLinkedToLoaded:c,title:l,width:d,cue:g,ref:S}){const P=O(r,A),L=N(s),y=r+t,T=t>0,f=F(e,.7),x=d>25,_=d<40;return i.jsxs("div",{ref:S,className:b([h.column,_&&h.smallArea]),style:{"--color":e,"--lighter":f??"",left:`${a}px`,width:`${d}px`},"data-testid":g,children:[o==="live"?i.jsx(Wt,{}):i.jsx("div",{"data-status":o,className:h.timelineBlock}),i.jsxs("div",{className:b([h.content,d<20&&h.hide,!n&&h.separeLeft]),"data-status":o,style:{"--color":e},children:[i.jsxs("div",{className:h.maybeInline,children:[i.jsx("div",{className:b([T&&h.cross]),children:P}),T&&i.jsx("div",{className:h.delay,children:O(y,A)}),_&&i.jsx(V,{delay:t,start:r,dayOffset:u,totalGap:m,isLinkedToLoaded:c,status:o})]}),x&&i.jsxs(i.Fragment,{children:[!_&&i.jsx(V,{delay:t,start:r,dayOffset:u,totalGap:m,isLinkedToLoaded:c,status:o}),i.jsx("div",{children:l})]})]}),i.jsx("div",{className:h.timeOverview,"data-status":o,children:o!=="done"&&i.jsx("div",{className:h.duration,children:L})})]})}function V({delay:e,start:t,dayOffset:s,totalGap:n,isLinkedToLoaded:a,status:o}){const r=$(),{getLocalizedString:u}=B(),{timeToStart:m}=M({timeStart:t,delay:e,dayOffset:s,totalGap:n,isLinkedToLoaded:a,countToEnd:!1,duration:0},r);let c=jt(m,o);return c==="live"?c=u("timeline.live"):c==="pending"&&(c=u("timeline.due")),i.jsx("div",{className:h.status,children:c})}function Wt(){const{current:e,duration:t}=G(),s=dt(e,t);return i.jsx("div",{"data-status":"live",className:h.timelineBlock,style:{"--progress":`${s}%`}})}const qt=p.memo(Ft);function Ft({firstStart:e,rundown:t,selectedEventId:s,totalDuration:n}){const{width:a}=W(),{hidePast:o,autosize:r}=R(),u=p.useRef(null),m=p.useRef(null),{lastEvent:c}=mt(t),l=yt(e),d=bt(e+n+((c==null?void 0:c.delay)??0)),g=l*E,S=d*E;pt({followRef:u,scrollRef:m,doFollow:r,selectedEventId:s,leftOffset:o?0:a/6});const{positions:P,totalWidth:L}=p.useMemo(()=>{const f=t.filter(x=>j(x)&&v(x)).map(x=>({start:x.timeStart+(x.dayOffset??0)*w+(x.delay??0),duration:x.duration}));return vt(f,g,S,a,r)},[t,g,S,a,r]);if(n===0)return null;let y=s?"done":"future";const T={};return t.forEach(f=>{j(f)&&v(f)&&(y==="live"&&(y="future"),f.id===s&&(y="live"),T[f.id]=y)}),i.jsx("div",{ref:m,className:b([h.timelineContainer,r&&h.scroll]),children:i.jsxs("div",{className:h.timeline,style:{width:L},children:[i.jsx(Pt,{startHour:l,endHour:d}),t.map((f,x)=>{if(!j(f)||!v(f))return null;const _=P[x];return _?i.jsx(Ut,{ref:f.id===s?u:void 0,colour:f.colour,delay:f.delay??0,duration:f.duration,hasLink:!!f.linkStart,left:_.left,status:T[f.id],start:f.timeStart+(f.dayOffset??0)*w,totalGap:f.totalGap,isLinkedToLoaded:f.isLinkedToLoaded,dayOffset:f.dayOffset,title:f.title,cue:f.cue,width:_.width},f.id):null})]})})}const k=p.memo(Gt);function Gt({category:e,content:t,title:s,status:n}){const a=b(["section",e==="now"&&"section--now"]),o=b(["section-content",t?`section-content--${e}`:"section-content--subdue"]);return i.jsxs("div",{className:a,"data-testid":e,children:[i.jsxs("div",{className:"section-title",children:[i.jsx("span",{className:"section-title__label",children:s}),n&&i.jsx("span",{className:"section-title__status",children:n})]}),i.jsx("div",{className:o,children:t??"-"})]})}function Jt({now:e,next:t,followedBy:s}){const{getLocalizedString:n}=B(),a=$(),o=(e==null?void 0:e.title)??"-",r=n("timeline.due").toUpperCase(),u=t!==null?t.title:"-",m=s!==null?s.title:"-";let c,l;if(t!==null){const{timeToStart:d}=M(t,a);d<=0?c=r:c=N(d,d>C*2)}if(s!==null){const{timeToStart:d}=M(s,a);d<=0?l=r:l=N(d,d>C*2)}return i.jsxs("div",{className:"title-grid",children:[i.jsx(k,{title:n("timeline.live"),content:o,category:"now"}),i.jsx(k,{title:n("common.next"),status:c,content:u,category:"next"}),i.jsx(k,{title:n("timeline.followedby"),status:l,content:m,category:"followedBy"})]})}function Qt(){const{data:e,status:t}=at(),{data:s,status:n}=ft(),{data:a,status:o}=J();return{data:{events:e,projectData:s,settings:a},status:lt([t,n,o])}}function de(){const{data:e,status:t}=Qt();return nt("Timeline"),t==="pending"?i.jsx(Q,{}):t==="error"?i.jsx(tt,{text:"There was an error fetching data, please refresh the page."}):i.jsx(Kt,{...e})}function Kt({events:e,projectData:t,settings:s}){const{selectedEventId:n}=K(),{scopedRundown:a,firstStart:o,totalDuration:r}=wt(e,n),{now:u,next:m,followedBy:c}=p.useMemo(()=>St(a,n),[a,n]),l=X(s==null?void 0:s.timeFormat),d=p.useMemo(()=>xt(l),[l]);return i.jsxs("div",{className:"timeline","data-testid":"timeline-view",children:[i.jsx(st,{target:Y.Timeline,viewOptions:d}),i.jsxs("div",{className:"project-header",children:[(t==null?void 0:t.logo)&&i.jsx(et,{name:t.logo,className:"logo"}),i.jsx("div",{className:"title",children:t.title}),i.jsx(Xt,{})]}),i.jsx(Jt,{now:u,next:m,followedBy:c}),i.jsx(qt,{firstStart:o,rundown:a,selectedEventId:n,totalDuration:r})]})}function Xt(){const{getLocalizedString:e}=B(),{clock:t}=Z(),s=O(t);return i.jsxs("div",{className:"clock-container",children:[i.jsx("div",{className:"label",children:e("common.time_now")}),i.jsx(it,{time:s,className:"time"})]})}export{de as default};
2
- //# sourceMappingURL=TimelinePage-Cwm0svjN.js.map
1
+ import{h as p,l as U,j as i,y as W}from"./vendor-9UkPSc5K.js";import{r as w,P as q,H as E,l as N,M as C,g as O,I as F,i as b,J as G,q as $,f as B,v as M,d as J,L as Q,o as K,h as X,O as Y,s as Z}from"./index-njXwwjfn.js";import{E as tt}from"./EmptyPage-BSzsxpGg.js";import{V as et}from"./ViewLogo--9miplQv.js";import{O as I,i as H,V as st}from"./ViewParamsEditor-BFu_0oIb.js";import{u as nt}from"./useWindowTitle-B2UzPuki.js";import{S as it}from"./SuperscriptTime-C8ypTVpH.js";import{i as j,a as v,d as ot,u as at}from"./useRundown-ihoU8qBi.js";import{g as rt,a as lt}from"./viewLoader.utils-DQGhrjSp.js";import{g as ct,a as z,b as ut,c as mt}from"./rundownUtils-H6xvQyre.js";import{g as dt}from"./getProgress-B94Ieskb.js";import{u as ft}from"./useProjectData-DW06zQvF.js";import"./Empty-C-JO_XAr.js";import"./Select-BLA-yQMq.js";(function(){try{var e=typeof window<"u"?window:typeof global<"u"?global:typeof globalThis<"u"?globalThis:typeof self<"u"?self:{},t=new e.Error().stack;t&&(e._sentryDebugIds=e._sentryDebugIds||{},e._sentryDebugIds[t]="dfaa0d47-8699-4c7a-a83a-9e2e9fabfe7e",e._sentryDebugIdIdentifier="sentry-dbid-dfaa0d47-8699-4c7a-a83a-9e2e9fabfe7e")}catch{}})();function ht(e,t){if(!t)return 0;const s=e.timeStart+e.dayOffset*w,n=t.timeStart+t.duration+t.dayOffset*w;return s===n?0:(s>n,s-n)}function D(e,t,s){if(!t.current)return;if(!(e!=null&&e.current)){t.current.scrollTo({left:0,behavior:"smooth"});return}const n=e.current.getBoundingClientRect(),a=t.current.getBoundingClientRect(),o=n.left-a.left+t.current.scrollLeft-s;t.current.scrollTo({left:o,behavior:"smooth"})}function pt({followRef:e,scrollRef:t,doFollow:s,selectedEventId:n,leftOffset:a=0,setScrollFlag:o}){return p.useEffect(()=>{!s||!t.current||(o==null||o(!0),window.requestAnimationFrame(()=>{D(n!==null?e:null,t,a),o==null||o(!1)}))},[e,t,s,a,o,n]),p.useCallback((u=e,m=t,c=a)=>{m.current&&D(n!==null?u:null,m,c)},[e,t,a,n])}const xt=e=>[{title:I.ClockOptions,collapsible:!0,options:[rt(e)]},{title:I.ElementVisibility,collapsible:!0,options:[{id:"hidePast",title:"Hide Past Events",description:"Whether to hide events that have passed",type:"boolean",defaultValue:!1},{id:"autosize",title:"Autosize timeline",description:"Timeline will adjust sizes to help with readability and automatically scroll if necessary",type:"boolean",defaultValue:!1}]}];function gt(e,t){const s=n=>(t==null?void 0:t.get(n))??e.get(n);return{hidePast:H(s("hidePast")),autosize:H(s("autosize"))}}function R(){const[e]=U(),t=p.use(q);return p.useMemo(()=>{const n=t?new URLSearchParams(t.search):void 0;return gt(e,n)},[t,e])}function _t(e,t,s,n,a){const r=(t<e?t+w:t)-e,u=n*a/r;return{left:(s-e)*a/r,width:u}}function yt(e){return Math.floor(e/E)}function bt(e){return Math.ceil(e/E)}function Tt(e,t){const s=[];for(let n=e;n<t;n++)s.push(n);return s}function jt(e,t){return t==="done"||t==="live"?t:e<=0?"pending":N(e,e>C*2)}function wt(e,t){const{hidePast:s}=R();return p.useMemo(()=>{if(e.length===0)return{scopedRundown:[],firstStart:0,totalDuration:0};const a=[];let o=t?1/0:-1,r=null,u=0,m=null;for(let c=0;c<e.length;c++){const l=e[c];if(j(l)&&v(l)){if(l.id===t&&(o=c),s&&c<o)continue;a.push(l),r===null&&(r=l.timeStart);const d=ht(l,m);d===0?u+=l.duration:d>0?u+=d+l.duration:d<0&&(u+=Math.max(l.duration+d,0)),ot(l,m)&&(m=l)}}return{scopedRundown:a,firstStart:r??0,totalDuration:u}},[s,e,t])}function St(e,t){var o,r;if(e.length===0)return{now:null,next:null,followedBy:null};let s=t?ct(e,t):null;j(s)||(s=null);const n=s?(o=z(e,s.id))==null?void 0:o.nextEvent:ut(e).firstEvent,a=n?(r=z(e,n.id))==null?void 0:r.nextEvent:null;return{now:s,next:n,followedBy:a}}function vt(e,t,s,n,a,o=100){let r=1/0;const u=e.map(({start:l,duration:d})=>{const g=_t(t,s,l,d,n);return r=Math.min(r,g.width),g});if(!a)return{positions:u,scale:1,totalWidth:n};const m=r<o?o/r:1;return m===1?{positions:u,scale:1,totalWidth:n}:{positions:u.map(l=>({left:l.left*m,width:l.width*m})),scale:m,totalWidth:n*m}}const Et="_markers_gfywu_17",Nt={markers:Et};function Pt(e){const{startHour:t,endHour:s}=e,n=Tt(t,s);return i.jsx("div",{className:Nt.markers,children:n.map(a=>i.jsx("span",{},a))})}const Lt="_timelineContainer_4bums_21",kt="_scroll_4bums_26",Ct="_timeline_4bums_21",Ot="_column_4bums_37",Mt="_maybeInline_4bums_45",Bt="_timelineBlock_4bums_52",It="_smallArea_4bums_64",Ht="_content_4bums_64",zt="_timeOverview_4bums_68",Dt="_hide_4bums_72",At="_status_4bums_98",Vt="_delay_4bums_105",$t="_cross_4bums_115",Rt="_separeLeft_4bums_121",h={timelineContainer:Lt,scroll:kt,timeline:Ct,column:Ot,maybeInline:Mt,timelineBlock:Bt,smallArea:It,content:Ht,timeOverview:zt,hide:Dt,status:At,delay:Vt,cross:$t,separeLeft:Rt},A={format12:"hh:mm a",format24:"HH:mm"};function Ut({colour:e,delay:t,duration:s,hasLink:n,left:a,status:o,start:r,dayOffset:u,totalGap:m,isLinkedToLoaded:c,title:l,width:d,cue:g,ref:S}){const P=O(r,A),L=N(s),y=r+t,T=t>0,f=F(e,.7),x=d>25,_=d<40;return i.jsxs("div",{ref:S,className:b([h.column,_&&h.smallArea]),style:{"--color":e,"--lighter":f??"",left:`${a}px`,width:`${d}px`},"data-testid":g,children:[o==="live"?i.jsx(Wt,{}):i.jsx("div",{"data-status":o,className:h.timelineBlock}),i.jsxs("div",{className:b([h.content,d<20&&h.hide,!n&&h.separeLeft]),"data-status":o,style:{"--color":e},children:[i.jsxs("div",{className:h.maybeInline,children:[i.jsx("div",{className:b([T&&h.cross]),children:P}),T&&i.jsx("div",{className:h.delay,children:O(y,A)}),_&&i.jsx(V,{delay:t,start:r,dayOffset:u,totalGap:m,isLinkedToLoaded:c,status:o})]}),x&&i.jsxs(i.Fragment,{children:[!_&&i.jsx(V,{delay:t,start:r,dayOffset:u,totalGap:m,isLinkedToLoaded:c,status:o}),i.jsx("div",{children:l})]})]}),i.jsx("div",{className:h.timeOverview,"data-status":o,children:o!=="done"&&i.jsx("div",{className:h.duration,children:L})})]})}function V({delay:e,start:t,dayOffset:s,totalGap:n,isLinkedToLoaded:a,status:o}){const r=$(),{getLocalizedString:u}=B(),{timeToStart:m}=M({timeStart:t,delay:e,dayOffset:s,totalGap:n,isLinkedToLoaded:a,countToEnd:!1,duration:0},r);let c=jt(m,o);return c==="live"?c=u("timeline.live"):c==="pending"&&(c=u("timeline.due")),i.jsx("div",{className:h.status,children:c})}function Wt(){const{current:e,duration:t}=G(),s=dt(e,t);return i.jsx("div",{"data-status":"live",className:h.timelineBlock,style:{"--progress":`${s}%`}})}const qt=p.memo(Ft);function Ft({firstStart:e,rundown:t,selectedEventId:s,totalDuration:n}){const{width:a}=W(),{hidePast:o,autosize:r}=R(),u=p.useRef(null),m=p.useRef(null),{lastEvent:c}=mt(t),l=yt(e),d=bt(e+n+((c==null?void 0:c.delay)??0)),g=l*E,S=d*E;pt({followRef:u,scrollRef:m,doFollow:r,selectedEventId:s,leftOffset:o?0:a/6});const{positions:P,totalWidth:L}=p.useMemo(()=>{const f=t.filter(x=>j(x)&&v(x)).map(x=>({start:x.timeStart+(x.dayOffset??0)*w+(x.delay??0),duration:x.duration}));return vt(f,g,S,a,r)},[t,g,S,a,r]);if(n===0)return null;let y=s?"done":"future";const T={};return t.forEach(f=>{j(f)&&v(f)&&(y==="live"&&(y="future"),f.id===s&&(y="live"),T[f.id]=y)}),i.jsx("div",{ref:m,className:b([h.timelineContainer,r&&h.scroll]),children:i.jsxs("div",{className:h.timeline,style:{width:L},children:[i.jsx(Pt,{startHour:l,endHour:d}),t.map((f,x)=>{if(!j(f)||!v(f))return null;const _=P[x];return _?i.jsx(Ut,{ref:f.id===s?u:void 0,colour:f.colour,delay:f.delay??0,duration:f.duration,hasLink:!!f.linkStart,left:_.left,status:T[f.id],start:f.timeStart+(f.dayOffset??0)*w,totalGap:f.totalGap,isLinkedToLoaded:f.isLinkedToLoaded,dayOffset:f.dayOffset,title:f.title,cue:f.cue,width:_.width},f.id):null})]})})}const k=p.memo(Gt);function Gt({category:e,content:t,title:s,status:n}){const a=b(["section",e==="now"&&"section--now"]),o=b(["section-content",t?`section-content--${e}`:"section-content--subdue"]);return i.jsxs("div",{className:a,"data-testid":e,children:[i.jsxs("div",{className:"section-title",children:[i.jsx("span",{className:"section-title__label",children:s}),n&&i.jsx("span",{className:"section-title__status",children:n})]}),i.jsx("div",{className:o,children:t??"-"})]})}function Jt({now:e,next:t,followedBy:s}){const{getLocalizedString:n}=B(),a=$(),o=(e==null?void 0:e.title)??"-",r=n("timeline.due").toUpperCase(),u=t!==null?t.title:"-",m=s!==null?s.title:"-";let c,l;if(t!==null){const{timeToStart:d}=M(t,a);d<=0?c=r:c=N(d,d>C*2)}if(s!==null){const{timeToStart:d}=M(s,a);d<=0?l=r:l=N(d,d>C*2)}return i.jsxs("div",{className:"title-grid",children:[i.jsx(k,{title:n("timeline.live"),content:o,category:"now"}),i.jsx(k,{title:n("common.next"),status:c,content:u,category:"next"}),i.jsx(k,{title:n("timeline.followedby"),status:l,content:m,category:"followedBy"})]})}function Qt(){const{data:e,status:t}=at(),{data:s,status:n}=ft(),{data:a,status:o}=J();return{data:{events:e,projectData:s,settings:a},status:lt([t,n,o])}}function de(){const{data:e,status:t}=Qt();return nt("Timeline"),t==="pending"?i.jsx(Q,{}):t==="error"?i.jsx(tt,{text:"There was an error fetching data, please refresh the page."}):i.jsx(Kt,{...e})}function Kt({events:e,projectData:t,settings:s}){const{selectedEventId:n}=K(),{scopedRundown:a,firstStart:o,totalDuration:r}=wt(e,n),{now:u,next:m,followedBy:c}=p.useMemo(()=>St(a,n),[a,n]),l=X(s==null?void 0:s.timeFormat),d=p.useMemo(()=>xt(l),[l]);return i.jsxs("div",{className:"timeline","data-testid":"timeline-view",children:[i.jsx(st,{target:Y.Timeline,viewOptions:d}),i.jsxs("div",{className:"project-header",children:[(t==null?void 0:t.logo)&&i.jsx(et,{name:t.logo,className:"logo"}),i.jsx("div",{className:"title",children:t.title}),i.jsx(Xt,{})]}),i.jsx(Jt,{now:u,next:m,followedBy:c}),i.jsx(qt,{firstStart:o,rundown:a,selectedEventId:n,totalDuration:r})]})}function Xt(){const{getLocalizedString:e}=B(),{clock:t}=Z(),s=O(t);return i.jsxs("div",{className:"clock-container",children:[i.jsx("div",{className:"label",children:e("common.time_now")}),i.jsx(it,{time:s,className:"time"})]})}export{de as default};
2
+ //# sourceMappingURL=TimelinePage-DTwqRihn.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"TimelinePage-Cwm0svjN.js","sources":["../../../../packages/utils/src/date-utils/getTimeFrom.ts","../../src/common/hooks/useHorizontalFollowComponent.ts","../../src/views/timeline/timeline.options.ts","../../src/views/timeline/timeline.utils.ts","../../src/views/timeline/timeline-markers/TimelineMarkers.tsx","../../src/views/timeline/TimelineEntry.tsx","../../src/views/timeline/Timeline.tsx","../../src/views/timeline/timeline-section/TimelineSection.tsx","../../src/views/timeline/TimelineSections.tsx","../../src/views/timeline/useTimelineData.ts","../../src/views/timeline/TimelinePage.tsx"],"sourcesContent":["import type { OntimeEvent } from 'ontime-types';\n\nimport { dayInMs } from './conversionUtils.js';\n\n/**\n * Utility returns the gap from a previous given event\n */\nexport function getTimeFrom(\n current: Pick<OntimeEvent, 'timeStart' | 'dayOffset'>,\n previous: Pick<OntimeEvent, 'timeStart' | 'duration' | 'dayOffset'> | null,\n): number {\n // there is no previous event\n if (!previous) {\n return 0;\n }\n\n const normalisedCurrentStart = current.timeStart + current.dayOffset * dayInMs;\n const normalisedPreviousEnd = previous.timeStart + previous.duration + previous.dayOffset * dayInMs;\n\n // event is linked to previous\n if (normalisedCurrentStart === normalisedPreviousEnd) {\n return 0;\n }\n\n // event has a gap from previous\n if (normalisedCurrentStart > normalisedPreviousEnd) {\n // time from previous is difference between start and previous end\n return normalisedCurrentStart - normalisedPreviousEnd;\n }\n\n // event overlaps with previous\n return normalisedCurrentStart - normalisedPreviousEnd;\n}\n","import { RefObject, useCallback, useEffect } from 'react';\nimport { EntryId } from 'ontime-types';\n\nfunction scrollToComponent<ComponentRef extends HTMLElement, ScrollRef extends HTMLElement>(\n componentRef: RefObject<ComponentRef> | null,\n scrollRef: RefObject<ScrollRef>,\n leftOffset: number,\n) {\n if (!scrollRef.current) {\n return;\n }\n\n if (!componentRef?.current) {\n // If no target component, scroll to start\n scrollRef.current.scrollTo({ left: 0, behavior: 'smooth' });\n return;\n }\n\n const componentRect = componentRef.current.getBoundingClientRect();\n const scrollRect = scrollRef.current.getBoundingClientRect();\n const left = componentRect.left - scrollRect.left + scrollRef.current.scrollLeft - leftOffset;\n\n scrollRef.current.scrollTo({ left, behavior: 'smooth' });\n}\n\ninterface UseHorizontalFollowComponentOptions {\n followRef: RefObject<HTMLElement | null>;\n scrollRef: RefObject<HTMLElement | null>;\n doFollow: boolean;\n selectedEventId: EntryId | null;\n leftOffset?: number;\n setScrollFlag?: (newValue: boolean) => void;\n}\n\n/**\n * This is a copy of useFollowComponent, but for horizontal scrolling\n * Designed with the timeline component in mind\n */\nexport default function useHorizontalFollowComponent({\n followRef,\n scrollRef,\n doFollow,\n selectedEventId,\n leftOffset = 0,\n setScrollFlag,\n}: UseHorizontalFollowComponentOptions) {\n useEffect(() => {\n if (!doFollow || !scrollRef.current) {\n return;\n }\n\n setScrollFlag?.(true);\n // Use requestAnimationFrame to ensure the component is fully loaded\n window.requestAnimationFrame(() => {\n scrollToComponent(\n selectedEventId !== null ? (followRef as RefObject<HTMLElement>) : null,\n scrollRef as RefObject<HTMLElement>,\n leftOffset,\n );\n setScrollFlag?.(false);\n });\n }, [followRef, scrollRef, doFollow, leftOffset, setScrollFlag, selectedEventId]);\n\n const scrollToRefComponent = useCallback(\n (componentRef = followRef, containerRef = scrollRef, offset = leftOffset) => {\n if (containerRef.current) {\n scrollToComponent(\n selectedEventId !== null ? (componentRef as RefObject<HTMLElement>) : null,\n containerRef as RefObject<HTMLElement>,\n offset,\n );\n }\n },\n [followRef, scrollRef, leftOffset, selectedEventId],\n );\n\n return scrollToRefComponent;\n}\n","import { use, useMemo } from 'react';\nimport { useSearchParams } from 'react-router';\n\nimport { getTimeOption } from '../../common/components/view-params-editor/common.options';\nimport { OptionTitle } from '../../common/components/view-params-editor/constants';\nimport { ViewOption } from '../../common/components/view-params-editor/viewParams.types';\nimport { PresetContext } from '../../common/context/PresetContext';\nimport { isStringBoolean } from '../../features/viewers/common/viewUtils';\n\nexport const getTimelineOptions = (timeFormat: string): ViewOption[] => {\n return [\n { title: OptionTitle.ClockOptions, collapsible: true, options: [getTimeOption(timeFormat)] },\n {\n title: OptionTitle.ElementVisibility,\n collapsible: true,\n options: [\n {\n id: 'hidePast',\n title: 'Hide Past Events',\n description: 'Whether to hide events that have passed',\n type: 'boolean',\n defaultValue: false,\n },\n {\n id: 'autosize',\n title: 'Autosize timeline',\n description: 'Timeline will adjust sizes to help with readability and automatically scroll if necessary',\n type: 'boolean',\n defaultValue: false,\n },\n ],\n },\n ];\n};\n\ntype TimelineOptions = {\n hidePast: boolean;\n autosize: boolean;\n};\n\n/**\n * Utility extract the view options from URL Params\n * the names and fallback are manually matched with timerOptions\n */\nfunction getOptionsFromParams(searchParams: URLSearchParams, defaultValues?: URLSearchParams): TimelineOptions {\n // Helper to get value from either source, prioritizing defaultValues\n const getValue = (key: string) => defaultValues?.get(key) ?? searchParams.get(key);\n\n return {\n hidePast: isStringBoolean(getValue('hidePast')),\n autosize: isStringBoolean(getValue('autosize')),\n };\n}\n\n/**\n * Hook exposes the timeline view options\n */\nexport function useTimelineOptions(): TimelineOptions {\n const [searchParams] = useSearchParams();\n const maybePreset = use(PresetContext);\n\n const options = useMemo(() => {\n const defaultValues = maybePreset ? new URLSearchParams(maybePreset.search) : undefined;\n return getOptionsFromParams(searchParams, defaultValues);\n }, [maybePreset, searchParams]);\n\n return options;\n}\n","import { useMemo } from 'react';\nimport { isOntimeEvent, isPlayableEvent, MaybeString, OntimeEntry, OntimeEvent, PlayableEvent } from 'ontime-types';\nimport {\n dayInMs,\n getEventWithId,\n getFirstEvent,\n getNextEvent,\n getTimeFrom,\n isNewLatest,\n MILLIS_PER_HOUR,\n MILLIS_PER_MINUTE,\n} from 'ontime-utils';\n\nimport { ExtendedEntry } from '../../common/utils/rundownMetadata';\nimport { formatDuration } from '../../common/utils/time';\n\nimport { useTimelineOptions } from './timeline.options';\nimport type { ProgressStatus } from './TimelineEntry';\n\ntype CSSPosition = {\n left: number;\n width: number;\n};\n\n/**\n * Calculates the base position and width of an element based on schedule\n * The scaling of these values (if needed) is handled by calculateTimelineLayout\n */\nexport function getElementPosition(\n scheduleStart: number,\n scheduleEnd: number,\n eventStart: number,\n eventDuration: number,\n containerWidth: number,\n): CSSPosition {\n const normalEnd = scheduleEnd < scheduleStart ? scheduleEnd + dayInMs : scheduleEnd;\n const totalDuration = normalEnd - scheduleStart;\n\n // Calculate proportional width and position\n const width = (eventDuration * containerWidth) / totalDuration;\n const left = ((eventStart - scheduleStart) * containerWidth) / totalDuration;\n\n return { left, width };\n}\n\n/**\n * Gets rounded down hour for a given time\n */\nexport function getStartHour(startTime: number): number {\n const hours = Math.floor(startTime / MILLIS_PER_HOUR);\n return hours;\n}\n\n/**\n * Gets rounded up hour for a given time\n */\nexport function getEndHour(endTime: number): number {\n const hours = Math.ceil(endTime / MILLIS_PER_HOUR);\n return hours;\n}\n\n/**\n * converts a time span into an array of hours\n */\nexport function makeTimelineSections(firstHour: number, lastHour: number) {\n const timelineSections = [];\n for (let i = firstHour; i < lastHour; i++) {\n timelineSections.push(i);\n }\n return timelineSections;\n}\n\n/**\n * Returns a formatted label for a progress status\n */\nexport function getStatusLabel(timeToStart: number, status: ProgressStatus): string {\n if (status === 'done' || status === 'live') {\n return status;\n }\n\n if (timeToStart <= 0) {\n return 'pending';\n }\n\n return formatDuration(timeToStart, timeToStart > MILLIS_PER_MINUTE * 2);\n}\n\ninterface ScopedRundownData {\n scopedRundown: ExtendedEntry<PlayableEvent>[];\n firstStart: number;\n totalDuration: number;\n}\n\nexport function useScopedRundown(\n rundown: ExtendedEntry<OntimeEntry>[],\n selectedEventId: MaybeString,\n): ScopedRundownData {\n const { hidePast } = useTimelineOptions();\n\n const data = useMemo(() => {\n if (rundown.length === 0) {\n return { scopedRundown: [], firstStart: 0, totalDuration: 0 };\n }\n\n const scopedRundown: ExtendedEntry<PlayableEvent>[] = [];\n let selectedIndex = selectedEventId ? Infinity : -1;\n let firstStart = null;\n let totalDuration = 0;\n let lastEntry: ExtendedEntry<PlayableEvent> | null = null;\n\n for (let i = 0; i < rundown.length; i++) {\n const currentEntry = rundown[i];\n // we only deal with playableEvents\n if (isOntimeEvent(currentEntry) && isPlayableEvent(currentEntry)) {\n if (currentEntry.id === selectedEventId) {\n selectedIndex = i;\n }\n\n // maybe filter past\n if (hidePast && i < selectedIndex) {\n continue;\n }\n\n // add to scopedRundown\n scopedRundown.push(currentEntry);\n\n /**\n * Derive timers\n * This logic is partially from rundownCache.generate\n * With the addition of deriving the current day offset\n */\n if (firstStart === null) {\n firstStart = currentEntry.timeStart;\n }\n\n const timeFromPrevious: number = getTimeFrom(currentEntry, lastEntry);\n\n if (timeFromPrevious === 0) {\n totalDuration += currentEntry.duration;\n } else if (timeFromPrevious > 0) {\n totalDuration += timeFromPrevious + currentEntry.duration;\n } else if (timeFromPrevious < 0) {\n totalDuration += Math.max(currentEntry.duration + timeFromPrevious, 0);\n }\n if (isNewLatest(currentEntry, lastEntry)) {\n lastEntry = currentEntry;\n }\n }\n }\n\n return { scopedRundown, firstStart: firstStart ?? 0, totalDuration };\n }, [hidePast, rundown, selectedEventId]);\n\n return data;\n}\n\ntype UpcomingEvents = {\n now: ExtendedEntry<OntimeEvent> | null;\n next: ExtendedEntry<OntimeEvent> | null;\n followedBy: ExtendedEntry<OntimeEvent> | null;\n};\n\n/**\n * Returns upcoming events from current: now, next and followedBy\n */\nexport function getUpcomingEvents(events: ExtendedEntry<PlayableEvent>[], selectedId: MaybeString): UpcomingEvents {\n if (events.length === 0) {\n return { now: null, next: null, followedBy: null };\n }\n\n let now = selectedId ? (getEventWithId(events, selectedId) as ExtendedEntry<OntimeEvent>) : null;\n if (!isOntimeEvent(now)) {\n now = null;\n }\n\n const next = now\n ? (getNextEvent(events, now.id)?.nextEvent as ExtendedEntry<OntimeEvent> | null)\n : (getFirstEvent(events).firstEvent as ExtendedEntry<OntimeEvent> | null);\n const followedBy = next ? (getNextEvent(events, next.id)?.nextEvent as ExtendedEntry<OntimeEvent> | null) : null;\n\n // Return the titles, handling nulls appropriately\n return {\n now,\n next,\n followedBy,\n };\n}\n\n/**\n * Utility function calculates time to start\n */\nexport function getTimeToStart(now: number, start: number, delay: number, offset: number): number {\n return start + delay - now + offset;\n}\n\ninterface TimelineLayout {\n positions: CSSPosition[];\n scale: number;\n totalWidth: number;\n}\n\n/**\n * Calculates positions for all events and applies scaling if needed\n */\nexport function calculateTimelineLayout(\n events: Array<{ start: number; duration: number }>,\n scheduleStart: number,\n scheduleEnd: number,\n containerWidth: number,\n canScroll: boolean,\n minWidth = 100,\n): TimelineLayout {\n // Calculate positions and track minimum width\n let smallestWidth = Infinity;\n const positions = events.map(({ start, duration }) => {\n const position = getElementPosition(scheduleStart, scheduleEnd, start, duration, containerWidth);\n smallestWidth = Math.min(smallestWidth, position.width);\n return position;\n });\n\n if (!canScroll) {\n return {\n positions: positions,\n scale: 1,\n totalWidth: containerWidth,\n };\n }\n\n // Determine if scaling is needed\n const scale = smallestWidth < minWidth ? minWidth / smallestWidth : 1;\n\n // If no scaling is needed, return base positions\n if (scale === 1) {\n return {\n positions,\n scale: 1,\n totalWidth: containerWidth,\n };\n }\n\n // Apply scale to all positions\n const scaledPositions = positions.map((pos) => ({\n left: pos.left * scale,\n width: pos.width * scale,\n }));\n\n return {\n positions: scaledPositions,\n scale,\n totalWidth: containerWidth * scale,\n };\n}\n","import { makeTimelineSections } from '../timeline.utils';\n\nimport style from './TimelineMarkers.module.scss';\n\ninterface TimelineMarkersProps {\n startHour: number;\n endHour: number;\n}\n\n/** Creates a line for every hour in the timeline */\nexport default function TimelineMarkers(props: TimelineMarkersProps) {\n const { startHour, endHour } = props;\n\n const elements = makeTimelineSections(startHour, endHour);\n\n return (\n <div className={style.markers}>\n {elements.map((tag) => (\n <span key={tag} />\n ))}\n </div>\n );\n}\n","import { RefObject } from 'react';\n\nimport { useExpectedStartData, useTimer } from '../../common/hooks/useSocket';\nimport { getProgress } from '../../common/utils/getProgress';\nimport { alpha, cx } from '../../common/utils/styleUtils';\nimport { formatDuration, formatTime, getExpectedTimesFromExtendedEvent } from '../../common/utils/time';\nimport { useTranslation } from '../../translation/TranslationProvider';\n\nimport { getStatusLabel } from './timeline.utils';\n\nimport style from './Timeline.module.scss';\n\nexport type ProgressStatus = 'done' | 'live' | 'future';\n\ninterface TimelineEntryProps {\n colour: string;\n delay: number;\n duration: number;\n hasLink: boolean;\n left: number;\n status: ProgressStatus;\n start: number;\n dayOffset: number;\n totalGap: number;\n isLinkedToLoaded: boolean;\n title: string;\n width: number;\n cue: string;\n ref?: RefObject<HTMLDivElement | null>;\n}\n\nconst formatOptions = {\n format12: 'hh:mm a',\n format24: 'HH:mm',\n};\n\nexport function TimelineEntry({\n colour,\n delay,\n duration,\n hasLink,\n left,\n status,\n start,\n dayOffset,\n totalGap,\n isLinkedToLoaded,\n title,\n width,\n cue,\n ref,\n}: TimelineEntryProps) {\n const formattedStartTime = formatTime(start, formatOptions);\n const formattedDuration = formatDuration(duration);\n const delayedStart = start + delay;\n const hasDelay = delay > 0;\n\n const lighterColour = alpha(colour, 0.7);\n const showTitle = width > 25;\n const smallArea = width < 40;\n\n return (\n <div\n ref={ref}\n className={cx([style.column, smallArea && style.smallArea])}\n style={{\n '--color': colour,\n '--lighter': lighterColour ?? '',\n left: `${left}px`,\n width: `${width}px`,\n }}\n data-testid={cue}\n >\n {status === 'live' ? <ActiveBlock /> : <div data-status={status} className={style.timelineBlock} />}\n <div\n className={cx([style.content, width < 20 && style.hide, !hasLink && style.separeLeft])}\n data-status={status}\n style={{\n '--color': colour,\n }}\n >\n <div className={style.maybeInline}>\n <div className={cx([hasDelay && style.cross])}>{formattedStartTime}</div>\n {hasDelay && <div className={style.delay}>{formatTime(delayedStart, formatOptions)}</div>}\n {smallArea && (\n <TimelineEntryStatus\n delay={delay}\n start={start}\n dayOffset={dayOffset}\n totalGap={totalGap}\n isLinkedToLoaded={isLinkedToLoaded}\n status={status}\n />\n )}\n </div>\n {showTitle && (\n <>\n {!smallArea && (\n <TimelineEntryStatus\n delay={delay}\n start={start}\n dayOffset={dayOffset}\n totalGap={totalGap}\n isLinkedToLoaded={isLinkedToLoaded}\n status={status}\n />\n )}\n <div>{title}</div>\n </>\n )}\n </div>\n <div className={style.timeOverview} data-status={status}>\n {status !== 'done' && <div className={style.duration}>{formattedDuration}</div>}\n </div>\n </div>\n );\n}\n\ninterface TimelineEntryStatusProps {\n delay: number;\n start: number;\n dayOffset: number;\n totalGap: number;\n isLinkedToLoaded: boolean;\n status: ProgressStatus;\n}\n\n// extract component to isolate re-renders provoked by the clock changes\nfunction TimelineEntryStatus({\n delay,\n start,\n dayOffset,\n totalGap,\n isLinkedToLoaded,\n status,\n}: TimelineEntryStatusProps) {\n const state = useExpectedStartData();\n\n const { getLocalizedString } = useTranslation();\n\n const { timeToStart } = getExpectedTimesFromExtendedEvent(\n { timeStart: start, delay, dayOffset, totalGap, isLinkedToLoaded, countToEnd: false, duration: 0 },\n state,\n );\n\n let statusText = getStatusLabel(timeToStart, status);\n if (statusText === 'live') {\n statusText = getLocalizedString('timeline.live');\n } else if (statusText === 'pending') {\n statusText = getLocalizedString('timeline.due');\n }\n\n return <div className={style.status}>{statusText}</div>;\n}\n\n/** Generates a block level progress bar */\nfunction ActiveBlock() {\n const { current, duration } = useTimer();\n const progress = getProgress(current, duration);\n return <div data-status='live' className={style.timelineBlock} style={{ '--progress': `${progress}%` }} />;\n}\n","import { memo, useMemo, useRef } from 'react';\nimport { useViewportSize } from '@mantine/hooks';\nimport { isOntimeEvent, isPlayableEvent, OntimeEntry, PlayableEvent } from 'ontime-types';\nimport { dayInMs, getLastEvent, MILLIS_PER_HOUR } from 'ontime-utils';\n\nimport useHorizontalFollowComponent from '../../common/hooks/useHorizontalFollowComponent';\nimport { ExtendedEntry } from '../../common/utils/rundownMetadata';\nimport { cx } from '../../common/utils/styleUtils';\n\nimport TimelineMarkers from './timeline-markers/TimelineMarkers';\nimport { useTimelineOptions } from './timeline.options';\nimport { calculateTimelineLayout, getEndHour, getStartHour } from './timeline.utils';\nimport { ProgressStatus, TimelineEntry } from './TimelineEntry';\n\nimport style from './Timeline.module.scss';\n\ninterface TimelineProps {\n firstStart: number;\n rundown: ExtendedEntry<OntimeEntry>[];\n selectedEventId: string | null;\n totalDuration: number;\n}\n\nexport default memo(Timeline);\nfunction Timeline({ firstStart, rundown, selectedEventId, totalDuration }: TimelineProps) {\n const { width: screenWidth } = useViewportSize();\n const { hidePast, autosize } = useTimelineOptions();\n const selectedRef = useRef<HTMLDivElement>(null);\n const scrollContainerRef = useRef<HTMLDivElement>(null);\n\n const { lastEvent } = getLastEvent(rundown);\n const startHour = getStartHour(firstStart);\n const endHour = getEndHour(firstStart + totalDuration + (lastEvent?.delay ?? 0));\n const scheduleStart = startHour * MILLIS_PER_HOUR;\n const scheduleEnd = endHour * MILLIS_PER_HOUR;\n\n // use horizontal follow when scroll is enabled\n useHorizontalFollowComponent({\n followRef: selectedRef,\n scrollRef: scrollContainerRef,\n doFollow: autosize,\n selectedEventId: selectedEventId,\n // No offset when hiding past events to ensure content starts at 0\n leftOffset: hidePast ? 0 : screenWidth / 6,\n });\n\n const { positions, totalWidth } = useMemo(() => {\n const playableEvents = rundown\n .filter((event): event is ExtendedEntry<PlayableEvent> => isOntimeEvent(event) && isPlayableEvent(event))\n .map((event) => ({\n start: event.timeStart + (event.dayOffset ?? 0) * dayInMs + (event.delay ?? 0),\n duration: event.duration,\n }));\n\n return calculateTimelineLayout(playableEvents, scheduleStart, scheduleEnd, screenWidth, autosize);\n }, [rundown, scheduleStart, scheduleEnd, screenWidth, autosize]);\n\n if (totalDuration === 0) {\n return null;\n }\n\n // Pre-calculate event statuses\n let currentStatus: ProgressStatus = selectedEventId ? 'done' : 'future';\n const statusMap: Record<string, ProgressStatus> = {};\n rundown.forEach((event) => {\n if (isOntimeEvent(event) && isPlayableEvent(event)) {\n if (currentStatus === 'live') {\n currentStatus = 'future';\n }\n if (event.id === selectedEventId) {\n currentStatus = 'live';\n }\n statusMap[event.id] = currentStatus;\n }\n });\n\n return (\n <div ref={scrollContainerRef} className={cx([style.timelineContainer, autosize && style.scroll])}>\n <div className={style.timeline} style={{ width: totalWidth }}>\n <TimelineMarkers startHour={startHour} endHour={endHour} />\n {rundown.map((event, index) => {\n if (!isOntimeEvent(event) || !isPlayableEvent(event)) {\n return null;\n }\n\n const position = positions[index];\n if (!position) return null;\n\n return (\n <TimelineEntry\n key={event.id}\n ref={event.id === selectedEventId ? selectedRef : undefined}\n colour={event.colour}\n delay={event.delay ?? 0}\n duration={event.duration}\n hasLink={Boolean(event.linkStart)}\n left={position.left}\n status={statusMap[event.id]}\n start={event.timeStart + (event.dayOffset ?? 0) * dayInMs}\n totalGap={event.totalGap}\n isLinkedToLoaded={event.isLinkedToLoaded}\n dayOffset={event.dayOffset}\n title={event.title}\n cue={event.cue}\n width={position.width}\n />\n );\n })}\n </div>\n </div>\n );\n}\n","import { memo } from 'react';\nimport { MaybeString } from 'ontime-types';\n\nimport { cx } from '../../../common/utils/styleUtils';\n\ninterface SectionProps {\n category: 'now' | 'next' | 'followedBy';\n content: MaybeString;\n title: string;\n status?: string;\n}\n\nexport default memo(TimelineSection);\n\nfunction TimelineSection({ category, content, title, status }: SectionProps) {\n const sectionClasses = cx(['section', category === 'now' && 'section--now']);\n const contentClasses = cx(['section-content', content ? `section-content--${category}` : 'section-content--subdue']);\n return (\n <div className={sectionClasses} data-testid={category}>\n <div className='section-title'>\n <span className='section-title__label'>{title}</span>\n {status && <span className='section-title__status'>{status}</span>}\n </div>\n <div className={contentClasses}>{content ?? '-'}</div>\n </div>\n );\n}\n","import { OntimeEvent } from 'ontime-types';\nimport { MILLIS_PER_MINUTE } from 'ontime-utils';\n\nimport { useExpectedStartData } from '../../common/hooks/useSocket';\nimport { ExtendedEntry } from '../../common/utils/rundownMetadata';\nimport { formatDuration, getExpectedTimesFromExtendedEvent } from '../../common/utils/time';\nimport { useTranslation } from '../../translation/TranslationProvider';\n\nimport TimelineSection from './timeline-section/TimelineSection';\n\ninterface TimelineSectionsProps {\n now: ExtendedEntry<OntimeEvent> | null;\n next: ExtendedEntry<OntimeEvent> | null;\n followedBy: ExtendedEntry<OntimeEvent> | null;\n}\n\nexport default function TimelineSections({ now, next, followedBy }: TimelineSectionsProps) {\n const { getLocalizedString } = useTranslation();\n const state = useExpectedStartData();\n\n // gather card data\n const titleNow = now?.title ?? '-';\n const dueText = getLocalizedString('timeline.due').toUpperCase();\n const nextText = next !== null ? next.title : '-';\n const followedByText = followedBy !== null ? followedBy.title : '-';\n let nextStatus: string | undefined;\n let followedByStatus: string | undefined;\n\n if (next !== null) {\n const { timeToStart } = getExpectedTimesFromExtendedEvent(next, state);\n if (timeToStart <= 0) {\n nextStatus = dueText;\n } else {\n nextStatus = formatDuration(timeToStart, timeToStart > MILLIS_PER_MINUTE * 2);\n }\n }\n\n if (followedBy !== null) {\n const { timeToStart } = getExpectedTimesFromExtendedEvent(followedBy, state);\n if (timeToStart <= 0) {\n followedByStatus = dueText;\n } else {\n followedByStatus = formatDuration(timeToStart, timeToStart > MILLIS_PER_MINUTE * 2);\n }\n }\n\n return (\n <div className='title-grid'>\n <TimelineSection title={getLocalizedString('timeline.live')} content={titleNow} category='now' />\n <TimelineSection\n title={getLocalizedString('common.next')}\n status={nextStatus}\n content={nextText}\n category='next'\n />\n <TimelineSection\n title={getLocalizedString('timeline.followedby')}\n status={followedByStatus}\n content={followedByText}\n category='followedBy'\n />\n </div>\n );\n}\n","import { OntimeEntry, ProjectData, Settings } from 'ontime-types';\n\nimport useProjectData from '../../common/hooks-query/useProjectData';\nimport { useFlatRundownWithMetadata } from '../../common/hooks-query/useRundown';\nimport useSettings from '../../common/hooks-query/useSettings';\nimport { ExtendedEntry } from '../../common/utils/rundownMetadata';\nimport { aggregateQueryStatus, ViewData } from '../utils/viewLoader.utils';\n\nexport interface TimelineData {\n events: ExtendedEntry<OntimeEntry>[];\n projectData: ProjectData;\n settings: Settings;\n}\n\nexport function useTimelineData(): ViewData<TimelineData> {\n // HTTP API data\n const { data: rundownData, status: rundownStatus } = useFlatRundownWithMetadata();\n const { data: projectData, status: projectDataStatus } = useProjectData();\n const { data: settings, status: settingsStatus } = useSettings();\n\n return {\n data: {\n events: rundownData,\n projectData,\n settings,\n },\n status: aggregateQueryStatus([rundownStatus, projectDataStatus, settingsStatus]),\n };\n}\n","import { useMemo } from 'react';\nimport { OntimeView } from 'ontime-types';\n\nimport EmptyPage from '../../common/components/state/EmptyPage';\nimport ViewLogo from '../../common/components/view-logo/ViewLogo';\nimport ViewParamsEditor from '../../common/components/view-params-editor/ViewParamsEditor';\nimport { useClock, useSelectedEventId } from '../../common/hooks/useSocket';\nimport { useWindowTitle } from '../../common/hooks/useWindowTitle';\nimport { formatTime, getDefaultFormat } from '../../common/utils/time';\nimport SuperscriptTime from '../../features/viewers/common/superscript-time/SuperscriptTime';\nimport { useTranslation } from '../../translation/TranslationProvider';\nimport Loader from '../common/loader/Loader';\n\nimport Timeline from './Timeline';\nimport { getTimelineOptions } from './timeline.options';\nimport { getUpcomingEvents, useScopedRundown } from './timeline.utils';\nimport TimelineSections from './TimelineSections';\nimport { TimelineData, useTimelineData } from './useTimelineData';\n\nimport './TimelinePage.scss';\n\nexport default function TimelinePageLoader() {\n const { data, status } = useTimelineData();\n\n useWindowTitle('Timeline');\n\n if (status === 'pending') {\n return <Loader />;\n }\n\n if (status === 'error') {\n return <EmptyPage text='There was an error fetching data, please refresh the page.' />;\n }\n\n return <TimelinePage {...data} />;\n}\n\nfunction TimelinePage({ events, projectData, settings }: TimelineData) {\n const { selectedEventId } = useSelectedEventId();\n // holds copy of the rundown with only relevant events\n const { scopedRundown, firstStart, totalDuration } = useScopedRundown(events, selectedEventId);\n\n // gather card options\n const { now, next, followedBy } = useMemo(() => {\n return getUpcomingEvents(scopedRundown, selectedEventId);\n }, [scopedRundown, selectedEventId]);\n\n // populate options\n const defaultFormat = getDefaultFormat(settings?.timeFormat);\n const progressOptions = useMemo(() => getTimelineOptions(defaultFormat), [defaultFormat]);\n\n return (\n <div className='timeline' data-testid='timeline-view'>\n <ViewParamsEditor target={OntimeView.Timeline} viewOptions={progressOptions} />\n <div className='project-header'>\n {projectData?.logo && <ViewLogo name={projectData.logo} className='logo' />}\n <div className='title'>{projectData.title}</div>\n <TimelineClock />\n </div>\n\n <TimelineSections now={now} next={next} followedBy={followedBy} />\n\n <Timeline\n firstStart={firstStart}\n rundown={scopedRundown}\n selectedEventId={selectedEventId}\n totalDuration={totalDuration}\n />\n </div>\n );\n}\n\nfunction TimelineClock() {\n const { getLocalizedString } = useTranslation();\n const { clock } = useClock();\n\n // gather timer data\n const formattedClock = formatTime(clock);\n\n return (\n <div className='clock-container'>\n <div className='label'>{getLocalizedString('common.time_now')}</div>\n <SuperscriptTime time={formattedClock} className='time' />\n </div>\n );\n}\n"],"names":["getTimeFrom","current","previous","normalisedCurrentStart","dayInMs","normalisedPreviousEnd","scrollToComponent","componentRef","scrollRef","leftOffset","componentRect","scrollRect","left","useHorizontalFollowComponent","followRef","doFollow","selectedEventId","setScrollFlag","useEffect","useCallback","containerRef","offset","getTimelineOptions","timeFormat","OptionTitle","getTimeOption","getOptionsFromParams","searchParams","defaultValues","getValue","key","isStringBoolean","useTimelineOptions","useSearchParams","maybePreset","use","PresetContext","useMemo","getElementPosition","scheduleStart","scheduleEnd","eventStart","eventDuration","containerWidth","totalDuration","width","getStartHour","startTime","MILLIS_PER_HOUR","getEndHour","endTime","makeTimelineSections","firstHour","lastHour","timelineSections","i","getStatusLabel","timeToStart","status","formatDuration","MILLIS_PER_MINUTE","useScopedRundown","rundown","hidePast","scopedRundown","selectedIndex","firstStart","lastEntry","currentEntry","isOntimeEvent","isPlayableEvent","timeFromPrevious","isNewLatest","getUpcomingEvents","events","selectedId","now","getEventWithId","next","_a","getNextEvent","getFirstEvent","followedBy","_b","calculateTimelineLayout","canScroll","minWidth","smallestWidth","positions","start","duration","position","scale","pos","TimelineMarkers","props","startHour","endHour","elements","jsx","style","tag","formatOptions","TimelineEntry","colour","delay","hasLink","dayOffset","totalGap","isLinkedToLoaded","title","cue","ref","formattedStartTime","formatTime","formattedDuration","delayedStart","hasDelay","lighterColour","alpha","showTitle","smallArea","jsxs","cx","ActiveBlock","TimelineEntryStatus","Fragment","state","useExpectedStartData","getLocalizedString","useTranslation","getExpectedTimesFromExtendedEvent","statusText","useTimer","progress","getProgress","memo","Timeline","screenWidth","useViewportSize","autosize","selectedRef","useRef","scrollContainerRef","lastEvent","getLastEvent","totalWidth","playableEvents","event","currentStatus","statusMap","index","TimelineSection","category","content","sectionClasses","contentClasses","TimelineSections","titleNow","dueText","nextText","followedByText","nextStatus","followedByStatus","useTimelineData","rundownData","rundownStatus","useFlatRundownWithMetadata","projectData","projectDataStatus","useProjectData","settings","settingsStatus","useSettings","aggregateQueryStatus","TimelinePageLoader","data","useWindowTitle","Loader","EmptyPage","TimelinePage","useSelectedEventId","defaultFormat","getDefaultFormat","progressOptions","ViewParamsEditor","OntimeView","ViewLogo","TimelineClock","clock","useClock","formattedClock","SuperscriptTime"],"mappings":"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"}
1
+ {"version":3,"file":"TimelinePage-DTwqRihn.js","sources":["../../../../packages/utils/src/date-utils/getTimeFrom.ts","../../src/common/hooks/useHorizontalFollowComponent.ts","../../src/views/timeline/timeline.options.ts","../../src/views/timeline/timeline.utils.ts","../../src/views/timeline/timeline-markers/TimelineMarkers.tsx","../../src/views/timeline/TimelineEntry.tsx","../../src/views/timeline/Timeline.tsx","../../src/views/timeline/timeline-section/TimelineSection.tsx","../../src/views/timeline/TimelineSections.tsx","../../src/views/timeline/useTimelineData.ts","../../src/views/timeline/TimelinePage.tsx"],"sourcesContent":["import type { OntimeEvent } from 'ontime-types';\n\nimport { dayInMs } from './conversionUtils.js';\n\n/**\n * Utility returns the gap from a previous given event\n */\nexport function getTimeFrom(\n current: Pick<OntimeEvent, 'timeStart' | 'dayOffset'>,\n previous: Pick<OntimeEvent, 'timeStart' | 'duration' | 'dayOffset'> | null,\n): number {\n // there is no previous event\n if (!previous) {\n return 0;\n }\n\n const normalisedCurrentStart = current.timeStart + current.dayOffset * dayInMs;\n const normalisedPreviousEnd = previous.timeStart + previous.duration + previous.dayOffset * dayInMs;\n\n // event is linked to previous\n if (normalisedCurrentStart === normalisedPreviousEnd) {\n return 0;\n }\n\n // event has a gap from previous\n if (normalisedCurrentStart > normalisedPreviousEnd) {\n // time from previous is difference between start and previous end\n return normalisedCurrentStart - normalisedPreviousEnd;\n }\n\n // event overlaps with previous\n return normalisedCurrentStart - normalisedPreviousEnd;\n}\n","import { RefObject, useCallback, useEffect } from 'react';\nimport { EntryId } from 'ontime-types';\n\nfunction scrollToComponent<ComponentRef extends HTMLElement, ScrollRef extends HTMLElement>(\n componentRef: RefObject<ComponentRef> | null,\n scrollRef: RefObject<ScrollRef>,\n leftOffset: number,\n) {\n if (!scrollRef.current) {\n return;\n }\n\n if (!componentRef?.current) {\n // If no target component, scroll to start\n scrollRef.current.scrollTo({ left: 0, behavior: 'smooth' });\n return;\n }\n\n const componentRect = componentRef.current.getBoundingClientRect();\n const scrollRect = scrollRef.current.getBoundingClientRect();\n const left = componentRect.left - scrollRect.left + scrollRef.current.scrollLeft - leftOffset;\n\n scrollRef.current.scrollTo({ left, behavior: 'smooth' });\n}\n\ninterface UseHorizontalFollowComponentOptions {\n followRef: RefObject<HTMLElement | null>;\n scrollRef: RefObject<HTMLElement | null>;\n doFollow: boolean;\n selectedEventId: EntryId | null;\n leftOffset?: number;\n setScrollFlag?: (newValue: boolean) => void;\n}\n\n/**\n * This is a copy of useFollowComponent, but for horizontal scrolling\n * Designed with the timeline component in mind\n */\nexport default function useHorizontalFollowComponent({\n followRef,\n scrollRef,\n doFollow,\n selectedEventId,\n leftOffset = 0,\n setScrollFlag,\n}: UseHorizontalFollowComponentOptions) {\n useEffect(() => {\n if (!doFollow || !scrollRef.current) {\n return;\n }\n\n setScrollFlag?.(true);\n // Use requestAnimationFrame to ensure the component is fully loaded\n window.requestAnimationFrame(() => {\n scrollToComponent(\n selectedEventId !== null ? (followRef as RefObject<HTMLElement>) : null,\n scrollRef as RefObject<HTMLElement>,\n leftOffset,\n );\n setScrollFlag?.(false);\n });\n }, [followRef, scrollRef, doFollow, leftOffset, setScrollFlag, selectedEventId]);\n\n const scrollToRefComponent = useCallback(\n (componentRef = followRef, containerRef = scrollRef, offset = leftOffset) => {\n if (containerRef.current) {\n scrollToComponent(\n selectedEventId !== null ? (componentRef as RefObject<HTMLElement>) : null,\n containerRef as RefObject<HTMLElement>,\n offset,\n );\n }\n },\n [followRef, scrollRef, leftOffset, selectedEventId],\n );\n\n return scrollToRefComponent;\n}\n","import { use, useMemo } from 'react';\nimport { useSearchParams } from 'react-router';\n\nimport { getTimeOption } from '../../common/components/view-params-editor/common.options';\nimport { OptionTitle } from '../../common/components/view-params-editor/constants';\nimport { ViewOption } from '../../common/components/view-params-editor/viewParams.types';\nimport { PresetContext } from '../../common/context/PresetContext';\nimport { isStringBoolean } from '../../features/viewers/common/viewUtils';\n\nexport const getTimelineOptions = (timeFormat: string): ViewOption[] => {\n return [\n { title: OptionTitle.ClockOptions, collapsible: true, options: [getTimeOption(timeFormat)] },\n {\n title: OptionTitle.ElementVisibility,\n collapsible: true,\n options: [\n {\n id: 'hidePast',\n title: 'Hide Past Events',\n description: 'Whether to hide events that have passed',\n type: 'boolean',\n defaultValue: false,\n },\n {\n id: 'autosize',\n title: 'Autosize timeline',\n description: 'Timeline will adjust sizes to help with readability and automatically scroll if necessary',\n type: 'boolean',\n defaultValue: false,\n },\n ],\n },\n ];\n};\n\ntype TimelineOptions = {\n hidePast: boolean;\n autosize: boolean;\n};\n\n/**\n * Utility extract the view options from URL Params\n * the names and fallback are manually matched with timerOptions\n */\nfunction getOptionsFromParams(searchParams: URLSearchParams, defaultValues?: URLSearchParams): TimelineOptions {\n // Helper to get value from either source, prioritizing defaultValues\n const getValue = (key: string) => defaultValues?.get(key) ?? searchParams.get(key);\n\n return {\n hidePast: isStringBoolean(getValue('hidePast')),\n autosize: isStringBoolean(getValue('autosize')),\n };\n}\n\n/**\n * Hook exposes the timeline view options\n */\nexport function useTimelineOptions(): TimelineOptions {\n const [searchParams] = useSearchParams();\n const maybePreset = use(PresetContext);\n\n const options = useMemo(() => {\n const defaultValues = maybePreset ? new URLSearchParams(maybePreset.search) : undefined;\n return getOptionsFromParams(searchParams, defaultValues);\n }, [maybePreset, searchParams]);\n\n return options;\n}\n","import { useMemo } from 'react';\nimport { isOntimeEvent, isPlayableEvent, MaybeString, OntimeEntry, OntimeEvent, PlayableEvent } from 'ontime-types';\nimport {\n dayInMs,\n getEventWithId,\n getFirstEvent,\n getNextEvent,\n getTimeFrom,\n isNewLatest,\n MILLIS_PER_HOUR,\n MILLIS_PER_MINUTE,\n} from 'ontime-utils';\n\nimport { ExtendedEntry } from '../../common/utils/rundownMetadata';\nimport { formatDuration } from '../../common/utils/time';\n\nimport { useTimelineOptions } from './timeline.options';\nimport type { ProgressStatus } from './TimelineEntry';\n\ntype CSSPosition = {\n left: number;\n width: number;\n};\n\n/**\n * Calculates the base position and width of an element based on schedule\n * The scaling of these values (if needed) is handled by calculateTimelineLayout\n */\nexport function getElementPosition(\n scheduleStart: number,\n scheduleEnd: number,\n eventStart: number,\n eventDuration: number,\n containerWidth: number,\n): CSSPosition {\n const normalEnd = scheduleEnd < scheduleStart ? scheduleEnd + dayInMs : scheduleEnd;\n const totalDuration = normalEnd - scheduleStart;\n\n // Calculate proportional width and position\n const width = (eventDuration * containerWidth) / totalDuration;\n const left = ((eventStart - scheduleStart) * containerWidth) / totalDuration;\n\n return { left, width };\n}\n\n/**\n * Gets rounded down hour for a given time\n */\nexport function getStartHour(startTime: number): number {\n const hours = Math.floor(startTime / MILLIS_PER_HOUR);\n return hours;\n}\n\n/**\n * Gets rounded up hour for a given time\n */\nexport function getEndHour(endTime: number): number {\n const hours = Math.ceil(endTime / MILLIS_PER_HOUR);\n return hours;\n}\n\n/**\n * converts a time span into an array of hours\n */\nexport function makeTimelineSections(firstHour: number, lastHour: number) {\n const timelineSections = [];\n for (let i = firstHour; i < lastHour; i++) {\n timelineSections.push(i);\n }\n return timelineSections;\n}\n\n/**\n * Returns a formatted label for a progress status\n */\nexport function getStatusLabel(timeToStart: number, status: ProgressStatus): string {\n if (status === 'done' || status === 'live') {\n return status;\n }\n\n if (timeToStart <= 0) {\n return 'pending';\n }\n\n return formatDuration(timeToStart, timeToStart > MILLIS_PER_MINUTE * 2);\n}\n\ninterface ScopedRundownData {\n scopedRundown: ExtendedEntry<PlayableEvent>[];\n firstStart: number;\n totalDuration: number;\n}\n\nexport function useScopedRundown(\n rundown: ExtendedEntry<OntimeEntry>[],\n selectedEventId: MaybeString,\n): ScopedRundownData {\n const { hidePast } = useTimelineOptions();\n\n const data = useMemo(() => {\n if (rundown.length === 0) {\n return { scopedRundown: [], firstStart: 0, totalDuration: 0 };\n }\n\n const scopedRundown: ExtendedEntry<PlayableEvent>[] = [];\n let selectedIndex = selectedEventId ? Infinity : -1;\n let firstStart = null;\n let totalDuration = 0;\n let lastEntry: ExtendedEntry<PlayableEvent> | null = null;\n\n for (let i = 0; i < rundown.length; i++) {\n const currentEntry = rundown[i];\n // we only deal with playableEvents\n if (isOntimeEvent(currentEntry) && isPlayableEvent(currentEntry)) {\n if (currentEntry.id === selectedEventId) {\n selectedIndex = i;\n }\n\n // maybe filter past\n if (hidePast && i < selectedIndex) {\n continue;\n }\n\n // add to scopedRundown\n scopedRundown.push(currentEntry);\n\n /**\n * Derive timers\n * This logic is partially from rundownCache.generate\n * With the addition of deriving the current day offset\n */\n if (firstStart === null) {\n firstStart = currentEntry.timeStart;\n }\n\n const timeFromPrevious: number = getTimeFrom(currentEntry, lastEntry);\n\n if (timeFromPrevious === 0) {\n totalDuration += currentEntry.duration;\n } else if (timeFromPrevious > 0) {\n totalDuration += timeFromPrevious + currentEntry.duration;\n } else if (timeFromPrevious < 0) {\n totalDuration += Math.max(currentEntry.duration + timeFromPrevious, 0);\n }\n if (isNewLatest(currentEntry, lastEntry)) {\n lastEntry = currentEntry;\n }\n }\n }\n\n return { scopedRundown, firstStart: firstStart ?? 0, totalDuration };\n }, [hidePast, rundown, selectedEventId]);\n\n return data;\n}\n\ntype UpcomingEvents = {\n now: ExtendedEntry<OntimeEvent> | null;\n next: ExtendedEntry<OntimeEvent> | null;\n followedBy: ExtendedEntry<OntimeEvent> | null;\n};\n\n/**\n * Returns upcoming events from current: now, next and followedBy\n */\nexport function getUpcomingEvents(events: ExtendedEntry<PlayableEvent>[], selectedId: MaybeString): UpcomingEvents {\n if (events.length === 0) {\n return { now: null, next: null, followedBy: null };\n }\n\n let now = selectedId ? (getEventWithId(events, selectedId) as ExtendedEntry<OntimeEvent>) : null;\n if (!isOntimeEvent(now)) {\n now = null;\n }\n\n const next = now\n ? (getNextEvent(events, now.id)?.nextEvent as ExtendedEntry<OntimeEvent> | null)\n : (getFirstEvent(events).firstEvent as ExtendedEntry<OntimeEvent> | null);\n const followedBy = next ? (getNextEvent(events, next.id)?.nextEvent as ExtendedEntry<OntimeEvent> | null) : null;\n\n // Return the titles, handling nulls appropriately\n return {\n now,\n next,\n followedBy,\n };\n}\n\n/**\n * Utility function calculates time to start\n */\nexport function getTimeToStart(now: number, start: number, delay: number, offset: number): number {\n return start + delay - now + offset;\n}\n\ninterface TimelineLayout {\n positions: CSSPosition[];\n scale: number;\n totalWidth: number;\n}\n\n/**\n * Calculates positions for all events and applies scaling if needed\n */\nexport function calculateTimelineLayout(\n events: Array<{ start: number; duration: number }>,\n scheduleStart: number,\n scheduleEnd: number,\n containerWidth: number,\n canScroll: boolean,\n minWidth = 100,\n): TimelineLayout {\n // Calculate positions and track minimum width\n let smallestWidth = Infinity;\n const positions = events.map(({ start, duration }) => {\n const position = getElementPosition(scheduleStart, scheduleEnd, start, duration, containerWidth);\n smallestWidth = Math.min(smallestWidth, position.width);\n return position;\n });\n\n if (!canScroll) {\n return {\n positions: positions,\n scale: 1,\n totalWidth: containerWidth,\n };\n }\n\n // Determine if scaling is needed\n const scale = smallestWidth < minWidth ? minWidth / smallestWidth : 1;\n\n // If no scaling is needed, return base positions\n if (scale === 1) {\n return {\n positions,\n scale: 1,\n totalWidth: containerWidth,\n };\n }\n\n // Apply scale to all positions\n const scaledPositions = positions.map((pos) => ({\n left: pos.left * scale,\n width: pos.width * scale,\n }));\n\n return {\n positions: scaledPositions,\n scale,\n totalWidth: containerWidth * scale,\n };\n}\n","import { makeTimelineSections } from '../timeline.utils';\n\nimport style from './TimelineMarkers.module.scss';\n\ninterface TimelineMarkersProps {\n startHour: number;\n endHour: number;\n}\n\n/** Creates a line for every hour in the timeline */\nexport default function TimelineMarkers(props: TimelineMarkersProps) {\n const { startHour, endHour } = props;\n\n const elements = makeTimelineSections(startHour, endHour);\n\n return (\n <div className={style.markers}>\n {elements.map((tag) => (\n <span key={tag} />\n ))}\n </div>\n );\n}\n","import { RefObject } from 'react';\n\nimport { useExpectedStartData, useTimer } from '../../common/hooks/useSocket';\nimport { getProgress } from '../../common/utils/getProgress';\nimport { alpha, cx } from '../../common/utils/styleUtils';\nimport { formatDuration, formatTime, getExpectedTimesFromExtendedEvent } from '../../common/utils/time';\nimport { useTranslation } from '../../translation/TranslationProvider';\n\nimport { getStatusLabel } from './timeline.utils';\n\nimport style from './Timeline.module.scss';\n\nexport type ProgressStatus = 'done' | 'live' | 'future';\n\ninterface TimelineEntryProps {\n colour: string;\n delay: number;\n duration: number;\n hasLink: boolean;\n left: number;\n status: ProgressStatus;\n start: number;\n dayOffset: number;\n totalGap: number;\n isLinkedToLoaded: boolean;\n title: string;\n width: number;\n cue: string;\n ref?: RefObject<HTMLDivElement | null>;\n}\n\nconst formatOptions = {\n format12: 'hh:mm a',\n format24: 'HH:mm',\n};\n\nexport function TimelineEntry({\n colour,\n delay,\n duration,\n hasLink,\n left,\n status,\n start,\n dayOffset,\n totalGap,\n isLinkedToLoaded,\n title,\n width,\n cue,\n ref,\n}: TimelineEntryProps) {\n const formattedStartTime = formatTime(start, formatOptions);\n const formattedDuration = formatDuration(duration);\n const delayedStart = start + delay;\n const hasDelay = delay > 0;\n\n const lighterColour = alpha(colour, 0.7);\n const showTitle = width > 25;\n const smallArea = width < 40;\n\n return (\n <div\n ref={ref}\n className={cx([style.column, smallArea && style.smallArea])}\n style={{\n '--color': colour,\n '--lighter': lighterColour ?? '',\n left: `${left}px`,\n width: `${width}px`,\n }}\n data-testid={cue}\n >\n {status === 'live' ? <ActiveBlock /> : <div data-status={status} className={style.timelineBlock} />}\n <div\n className={cx([style.content, width < 20 && style.hide, !hasLink && style.separeLeft])}\n data-status={status}\n style={{\n '--color': colour,\n }}\n >\n <div className={style.maybeInline}>\n <div className={cx([hasDelay && style.cross])}>{formattedStartTime}</div>\n {hasDelay && <div className={style.delay}>{formatTime(delayedStart, formatOptions)}</div>}\n {smallArea && (\n <TimelineEntryStatus\n delay={delay}\n start={start}\n dayOffset={dayOffset}\n totalGap={totalGap}\n isLinkedToLoaded={isLinkedToLoaded}\n status={status}\n />\n )}\n </div>\n {showTitle && (\n <>\n {!smallArea && (\n <TimelineEntryStatus\n delay={delay}\n start={start}\n dayOffset={dayOffset}\n totalGap={totalGap}\n isLinkedToLoaded={isLinkedToLoaded}\n status={status}\n />\n )}\n <div>{title}</div>\n </>\n )}\n </div>\n <div className={style.timeOverview} data-status={status}>\n {status !== 'done' && <div className={style.duration}>{formattedDuration}</div>}\n </div>\n </div>\n );\n}\n\ninterface TimelineEntryStatusProps {\n delay: number;\n start: number;\n dayOffset: number;\n totalGap: number;\n isLinkedToLoaded: boolean;\n status: ProgressStatus;\n}\n\n// extract component to isolate re-renders provoked by the clock changes\nfunction TimelineEntryStatus({\n delay,\n start,\n dayOffset,\n totalGap,\n isLinkedToLoaded,\n status,\n}: TimelineEntryStatusProps) {\n const state = useExpectedStartData();\n\n const { getLocalizedString } = useTranslation();\n\n const { timeToStart } = getExpectedTimesFromExtendedEvent(\n { timeStart: start, delay, dayOffset, totalGap, isLinkedToLoaded, countToEnd: false, duration: 0 },\n state,\n );\n\n let statusText = getStatusLabel(timeToStart, status);\n if (statusText === 'live') {\n statusText = getLocalizedString('timeline.live');\n } else if (statusText === 'pending') {\n statusText = getLocalizedString('timeline.due');\n }\n\n return <div className={style.status}>{statusText}</div>;\n}\n\n/** Generates a block level progress bar */\nfunction ActiveBlock() {\n const { current, duration } = useTimer();\n const progress = getProgress(current, duration);\n return <div data-status='live' className={style.timelineBlock} style={{ '--progress': `${progress}%` }} />;\n}\n","import { memo, useMemo, useRef } from 'react';\nimport { useViewportSize } from '@mantine/hooks';\nimport { isOntimeEvent, isPlayableEvent, OntimeEntry, PlayableEvent } from 'ontime-types';\nimport { dayInMs, getLastEvent, MILLIS_PER_HOUR } from 'ontime-utils';\n\nimport useHorizontalFollowComponent from '../../common/hooks/useHorizontalFollowComponent';\nimport { ExtendedEntry } from '../../common/utils/rundownMetadata';\nimport { cx } from '../../common/utils/styleUtils';\n\nimport TimelineMarkers from './timeline-markers/TimelineMarkers';\nimport { useTimelineOptions } from './timeline.options';\nimport { calculateTimelineLayout, getEndHour, getStartHour } from './timeline.utils';\nimport { ProgressStatus, TimelineEntry } from './TimelineEntry';\n\nimport style from './Timeline.module.scss';\n\ninterface TimelineProps {\n firstStart: number;\n rundown: ExtendedEntry<OntimeEntry>[];\n selectedEventId: string | null;\n totalDuration: number;\n}\n\nexport default memo(Timeline);\nfunction Timeline({ firstStart, rundown, selectedEventId, totalDuration }: TimelineProps) {\n const { width: screenWidth } = useViewportSize();\n const { hidePast, autosize } = useTimelineOptions();\n const selectedRef = useRef<HTMLDivElement>(null);\n const scrollContainerRef = useRef<HTMLDivElement>(null);\n\n const { lastEvent } = getLastEvent(rundown);\n const startHour = getStartHour(firstStart);\n const endHour = getEndHour(firstStart + totalDuration + (lastEvent?.delay ?? 0));\n const scheduleStart = startHour * MILLIS_PER_HOUR;\n const scheduleEnd = endHour * MILLIS_PER_HOUR;\n\n // use horizontal follow when scroll is enabled\n useHorizontalFollowComponent({\n followRef: selectedRef,\n scrollRef: scrollContainerRef,\n doFollow: autosize,\n selectedEventId: selectedEventId,\n // No offset when hiding past events to ensure content starts at 0\n leftOffset: hidePast ? 0 : screenWidth / 6,\n });\n\n const { positions, totalWidth } = useMemo(() => {\n const playableEvents = rundown\n .filter((event): event is ExtendedEntry<PlayableEvent> => isOntimeEvent(event) && isPlayableEvent(event))\n .map((event) => ({\n start: event.timeStart + (event.dayOffset ?? 0) * dayInMs + (event.delay ?? 0),\n duration: event.duration,\n }));\n\n return calculateTimelineLayout(playableEvents, scheduleStart, scheduleEnd, screenWidth, autosize);\n }, [rundown, scheduleStart, scheduleEnd, screenWidth, autosize]);\n\n if (totalDuration === 0) {\n return null;\n }\n\n // Pre-calculate event statuses\n let currentStatus: ProgressStatus = selectedEventId ? 'done' : 'future';\n const statusMap: Record<string, ProgressStatus> = {};\n rundown.forEach((event) => {\n if (isOntimeEvent(event) && isPlayableEvent(event)) {\n if (currentStatus === 'live') {\n currentStatus = 'future';\n }\n if (event.id === selectedEventId) {\n currentStatus = 'live';\n }\n statusMap[event.id] = currentStatus;\n }\n });\n\n return (\n <div ref={scrollContainerRef} className={cx([style.timelineContainer, autosize && style.scroll])}>\n <div className={style.timeline} style={{ width: totalWidth }}>\n <TimelineMarkers startHour={startHour} endHour={endHour} />\n {rundown.map((event, index) => {\n if (!isOntimeEvent(event) || !isPlayableEvent(event)) {\n return null;\n }\n\n const position = positions[index];\n if (!position) return null;\n\n return (\n <TimelineEntry\n key={event.id}\n ref={event.id === selectedEventId ? selectedRef : undefined}\n colour={event.colour}\n delay={event.delay ?? 0}\n duration={event.duration}\n hasLink={Boolean(event.linkStart)}\n left={position.left}\n status={statusMap[event.id]}\n start={event.timeStart + (event.dayOffset ?? 0) * dayInMs}\n totalGap={event.totalGap}\n isLinkedToLoaded={event.isLinkedToLoaded}\n dayOffset={event.dayOffset}\n title={event.title}\n cue={event.cue}\n width={position.width}\n />\n );\n })}\n </div>\n </div>\n );\n}\n","import { memo } from 'react';\nimport { MaybeString } from 'ontime-types';\n\nimport { cx } from '../../../common/utils/styleUtils';\n\ninterface SectionProps {\n category: 'now' | 'next' | 'followedBy';\n content: MaybeString;\n title: string;\n status?: string;\n}\n\nexport default memo(TimelineSection);\n\nfunction TimelineSection({ category, content, title, status }: SectionProps) {\n const sectionClasses = cx(['section', category === 'now' && 'section--now']);\n const contentClasses = cx(['section-content', content ? `section-content--${category}` : 'section-content--subdue']);\n return (\n <div className={sectionClasses} data-testid={category}>\n <div className='section-title'>\n <span className='section-title__label'>{title}</span>\n {status && <span className='section-title__status'>{status}</span>}\n </div>\n <div className={contentClasses}>{content ?? '-'}</div>\n </div>\n );\n}\n","import { OntimeEvent } from 'ontime-types';\nimport { MILLIS_PER_MINUTE } from 'ontime-utils';\n\nimport { useExpectedStartData } from '../../common/hooks/useSocket';\nimport { ExtendedEntry } from '../../common/utils/rundownMetadata';\nimport { formatDuration, getExpectedTimesFromExtendedEvent } from '../../common/utils/time';\nimport { useTranslation } from '../../translation/TranslationProvider';\n\nimport TimelineSection from './timeline-section/TimelineSection';\n\ninterface TimelineSectionsProps {\n now: ExtendedEntry<OntimeEvent> | null;\n next: ExtendedEntry<OntimeEvent> | null;\n followedBy: ExtendedEntry<OntimeEvent> | null;\n}\n\nexport default function TimelineSections({ now, next, followedBy }: TimelineSectionsProps) {\n const { getLocalizedString } = useTranslation();\n const state = useExpectedStartData();\n\n // gather card data\n const titleNow = now?.title ?? '-';\n const dueText = getLocalizedString('timeline.due').toUpperCase();\n const nextText = next !== null ? next.title : '-';\n const followedByText = followedBy !== null ? followedBy.title : '-';\n let nextStatus: string | undefined;\n let followedByStatus: string | undefined;\n\n if (next !== null) {\n const { timeToStart } = getExpectedTimesFromExtendedEvent(next, state);\n if (timeToStart <= 0) {\n nextStatus = dueText;\n } else {\n nextStatus = formatDuration(timeToStart, timeToStart > MILLIS_PER_MINUTE * 2);\n }\n }\n\n if (followedBy !== null) {\n const { timeToStart } = getExpectedTimesFromExtendedEvent(followedBy, state);\n if (timeToStart <= 0) {\n followedByStatus = dueText;\n } else {\n followedByStatus = formatDuration(timeToStart, timeToStart > MILLIS_PER_MINUTE * 2);\n }\n }\n\n return (\n <div className='title-grid'>\n <TimelineSection title={getLocalizedString('timeline.live')} content={titleNow} category='now' />\n <TimelineSection\n title={getLocalizedString('common.next')}\n status={nextStatus}\n content={nextText}\n category='next'\n />\n <TimelineSection\n title={getLocalizedString('timeline.followedby')}\n status={followedByStatus}\n content={followedByText}\n category='followedBy'\n />\n </div>\n );\n}\n","import { OntimeEntry, ProjectData, Settings } from 'ontime-types';\n\nimport useProjectData from '../../common/hooks-query/useProjectData';\nimport { useFlatRundownWithMetadata } from '../../common/hooks-query/useRundown';\nimport useSettings from '../../common/hooks-query/useSettings';\nimport { ExtendedEntry } from '../../common/utils/rundownMetadata';\nimport { aggregateQueryStatus, ViewData } from '../utils/viewLoader.utils';\n\nexport interface TimelineData {\n events: ExtendedEntry<OntimeEntry>[];\n projectData: ProjectData;\n settings: Settings;\n}\n\nexport function useTimelineData(): ViewData<TimelineData> {\n // HTTP API data\n const { data: rundownData, status: rundownStatus } = useFlatRundownWithMetadata();\n const { data: projectData, status: projectDataStatus } = useProjectData();\n const { data: settings, status: settingsStatus } = useSettings();\n\n return {\n data: {\n events: rundownData,\n projectData,\n settings,\n },\n status: aggregateQueryStatus([rundownStatus, projectDataStatus, settingsStatus]),\n };\n}\n","import { useMemo } from 'react';\nimport { OntimeView } from 'ontime-types';\n\nimport EmptyPage from '../../common/components/state/EmptyPage';\nimport ViewLogo from '../../common/components/view-logo/ViewLogo';\nimport ViewParamsEditor from '../../common/components/view-params-editor/ViewParamsEditor';\nimport { useClock, useSelectedEventId } from '../../common/hooks/useSocket';\nimport { useWindowTitle } from '../../common/hooks/useWindowTitle';\nimport { formatTime, getDefaultFormat } from '../../common/utils/time';\nimport SuperscriptTime from '../../features/viewers/common/superscript-time/SuperscriptTime';\nimport { useTranslation } from '../../translation/TranslationProvider';\nimport Loader from '../common/loader/Loader';\n\nimport Timeline from './Timeline';\nimport { getTimelineOptions } from './timeline.options';\nimport { getUpcomingEvents, useScopedRundown } from './timeline.utils';\nimport TimelineSections from './TimelineSections';\nimport { TimelineData, useTimelineData } from './useTimelineData';\n\nimport './TimelinePage.scss';\n\nexport default function TimelinePageLoader() {\n const { data, status } = useTimelineData();\n\n useWindowTitle('Timeline');\n\n if (status === 'pending') {\n return <Loader />;\n }\n\n if (status === 'error') {\n return <EmptyPage text='There was an error fetching data, please refresh the page.' />;\n }\n\n return <TimelinePage {...data} />;\n}\n\nfunction TimelinePage({ events, projectData, settings }: TimelineData) {\n const { selectedEventId } = useSelectedEventId();\n // holds copy of the rundown with only relevant events\n const { scopedRundown, firstStart, totalDuration } = useScopedRundown(events, selectedEventId);\n\n // gather card options\n const { now, next, followedBy } = useMemo(() => {\n return getUpcomingEvents(scopedRundown, selectedEventId);\n }, [scopedRundown, selectedEventId]);\n\n // populate options\n const defaultFormat = getDefaultFormat(settings?.timeFormat);\n const progressOptions = useMemo(() => getTimelineOptions(defaultFormat), [defaultFormat]);\n\n return (\n <div className='timeline' data-testid='timeline-view'>\n <ViewParamsEditor target={OntimeView.Timeline} viewOptions={progressOptions} />\n <div className='project-header'>\n {projectData?.logo && <ViewLogo name={projectData.logo} className='logo' />}\n <div className='title'>{projectData.title}</div>\n <TimelineClock />\n </div>\n\n <TimelineSections now={now} next={next} followedBy={followedBy} />\n\n <Timeline\n firstStart={firstStart}\n rundown={scopedRundown}\n selectedEventId={selectedEventId}\n totalDuration={totalDuration}\n />\n </div>\n );\n}\n\nfunction TimelineClock() {\n const { getLocalizedString } = useTranslation();\n const { clock } = useClock();\n\n // gather timer data\n const formattedClock = formatTime(clock);\n\n return (\n <div className='clock-container'>\n <div className='label'>{getLocalizedString('common.time_now')}</div>\n <SuperscriptTime time={formattedClock} className='time' />\n </div>\n );\n}\n"],"names":["getTimeFrom","current","previous","normalisedCurrentStart","dayInMs","normalisedPreviousEnd","scrollToComponent","componentRef","scrollRef","leftOffset","componentRect","scrollRect","left","useHorizontalFollowComponent","followRef","doFollow","selectedEventId","setScrollFlag","useEffect","useCallback","containerRef","offset","getTimelineOptions","timeFormat","OptionTitle","getTimeOption","getOptionsFromParams","searchParams","defaultValues","getValue","key","isStringBoolean","useTimelineOptions","useSearchParams","maybePreset","use","PresetContext","useMemo","getElementPosition","scheduleStart","scheduleEnd","eventStart","eventDuration","containerWidth","totalDuration","width","getStartHour","startTime","MILLIS_PER_HOUR","getEndHour","endTime","makeTimelineSections","firstHour","lastHour","timelineSections","i","getStatusLabel","timeToStart","status","formatDuration","MILLIS_PER_MINUTE","useScopedRundown","rundown","hidePast","scopedRundown","selectedIndex","firstStart","lastEntry","currentEntry","isOntimeEvent","isPlayableEvent","timeFromPrevious","isNewLatest","getUpcomingEvents","events","selectedId","now","getEventWithId","next","_a","getNextEvent","getFirstEvent","followedBy","_b","calculateTimelineLayout","canScroll","minWidth","smallestWidth","positions","start","duration","position","scale","pos","TimelineMarkers","props","startHour","endHour","elements","jsx","style","tag","formatOptions","TimelineEntry","colour","delay","hasLink","dayOffset","totalGap","isLinkedToLoaded","title","cue","ref","formattedStartTime","formatTime","formattedDuration","delayedStart","hasDelay","lighterColour","alpha","showTitle","smallArea","jsxs","cx","ActiveBlock","TimelineEntryStatus","Fragment","state","useExpectedStartData","getLocalizedString","useTranslation","getExpectedTimesFromExtendedEvent","statusText","useTimer","progress","getProgress","memo","Timeline","screenWidth","useViewportSize","autosize","selectedRef","useRef","scrollContainerRef","lastEvent","getLastEvent","totalWidth","playableEvents","event","currentStatus","statusMap","index","TimelineSection","category","content","sectionClasses","contentClasses","TimelineSections","titleNow","dueText","nextText","followedByText","nextStatus","followedByStatus","useTimelineData","rundownData","rundownStatus","useFlatRundownWithMetadata","projectData","projectDataStatus","useProjectData","settings","settingsStatus","useSettings","aggregateQueryStatus","TimelinePageLoader","data","useWindowTitle","Loader","EmptyPage","TimelinePage","useSelectedEventId","defaultFormat","getDefaultFormat","progressOptions","ViewParamsEditor","OntimeView","ViewLogo","TimelineClock","clock","useClock","formattedClock","SuperscriptTime"],"mappings":"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"}
@@ -1 +1 @@
1
- .blink{animation:blink 1s step-start infinite}@keyframes blink{0%{opacity:100%}50%{opacity:20%}}.fourtyfive{transform:rotate(45deg)}.mirror{transform:rotate(180deg)}.stage-timer{margin:0;box-sizing:border-box;overflow:hidden;width:100%;height:100vh;transition:opacity .5s ease-in-out;font-family:var(--font-family-override, "Open Sans", "Segoe UI", sans-serif);background:var(--timer-bg, var(--background-color-override, #101010));color:var(--color-override, rgba(255, 255, 255, .8));gap:min(2vh,16px);padding:min(2vh,16px) clamp(16px,2vw,24px);display:flex;flex-direction:column}.stage-timer--finished{outline:clamp(4px,1vw,16px) solid var(--timer-overtime-color-override, #FA5656);outline-offset:calc(clamp(4px,1vw,16px)*-1);transition:.5s}.stage-timer .blackout{position:absolute;top:0;right:0;bottom:0;left:0;z-index:0;background-color:#000;opacity:0;transition:opacity .5s}.stage-timer .blackout--active{z-index:101;opacity:1}.stage-timer .clock-container{margin-left:auto;font-weight:600;transition:opacity .5s}.stage-timer .clock-container .label{font-size:clamp(12px,1.25vw,20px);color:var(--label-color-override, rgba(255, 255, 255, .25));text-transform:uppercase}.stage-timer .clock-container .clock{font-size:clamp(24px,2.5vw,48px);color:var(--secondary-color-override, rgba(255, 255, 255, .45));letter-spacing:.05em;line-height:.95em}.stage-timer .clock-container--hidden{opacity:0}.stage-timer .event{background-color:var(--card-background-color-override, rgba(255, 255, 255, .05));padding:min(2vh,8px) clamp(16px,2vw,24px);border-radius:4px}.stage-timer .event.now{grid-area:now}.stage-timer .event.next{grid-area:next}.stage-timer .timer-container{flex:1;align-content:center;justify-self:center;align-self:center;width:100%;overflow:hidden}.stage-timer .timer-container .end-message{text-align:center;font-size:11.5vw;font-weight:600;color:var(--timer-overtime-color-override, #FA5656);padding:0;max-height:100%}.stage-timer .timer-container .timer{opacity:1;font-family:var(--timer-font, var(--font-family-override, "Open Sans", "Segoe UI", sans-serif));color:var(--timer-colour, var(--timer-color-override, #f6f6f6));line-height:.9em;text-align:center;letter-spacing:.05em;font-weight:600;transition-property:font-size;transition-duration:.5s}.stage-timer .timer-container .timer--paused{opacity:.6;transition:.5s}.stage-timer .timer-container .timer--finished{color:var(--timer-overtime-color-override, #FA5656)}.stage-timer .timer-container .timer[data-phase=warning]{color:var(--timer-colour, var(--timer-warning-color-override))}.stage-timer .timer-container .timer[data-phase=danger]{color:var(--timer-colour, var(--timer-danger-color-override))}.stage-timer .secondary{white-space:nowrap;overflow:hidden;text-overflow:ellipsis;margin-top:.125em;padding-block:.125em;font-weight:600;text-align:center;color:var(--external-color-override, rgba(255, 255, 255, .85));letter-spacing:.5px;line-height:1em;transition-property:opacity,height;transition-duration:.5s;border-top:1px solid color-mix(in srgb,var(--external-color-override, rgba(255, 255, 255, .85)) 10%,transparent)}.stage-timer .secondary--hidden{opacity:0;height:0}.stage-timer .progress-container{width:100%;margin:0 auto;opacity:1;transition:.5s}.stage-timer .progress-container--paused{opacity:.6;transition:.5s}.stage-timer .message-overlay{position:fixed;top:0;right:0;bottom:0;left:0;padding:2vw;background:var(--background-color-override, #101010);opacity:0;transition:opacity .5s}.stage-timer .message-overlay--active{z-index:100;opacity:1}.stage-timer .message{display:grid;place-content:center;height:100%;width:100%;color:var(--color-override, rgba(255, 255, 255, .8));text-align:center;font-weight:600}.stage-timer .logo{position:absolute;top:min(2vh,16px);left:clamp(16px,2vw,24px);max-width:min(200px,20vw)}@media screen and (max-width: 768px){.stage-timer .logo img{height:min(50px,10vh)}}
1
+ .blink{animation:blink 1s step-start infinite}@keyframes blink{0%{opacity:100%}50%{opacity:20%}}.fourtyfive{transform:rotate(45deg)}.mirror{transform:rotate(180deg)}.stage-timer{margin:0;box-sizing:border-box;overflow:hidden;width:100%;height:100vh;transition:opacity .5s ease-in-out;font-family:var(--font-family-override, "Open Sans", "Segoe UI", sans-serif);background:var(--timer-bg, var(--background-color-override, #101010));color:var(--color-override, rgba(255, 255, 255, .8));gap:min(2vh,16px);padding:min(2vh,16px) clamp(16px,2vw,24px);display:flex;flex-direction:column}.stage-timer--finished{outline:clamp(4px,1vw,16px) solid var(--timer-overtime-color-override, #FA5656);outline-offset:calc(clamp(4px,1vw,16px)*-1);transition:.5s}.stage-timer .blackout{position:absolute;top:0;right:0;bottom:0;left:0;z-index:0;background-color:#000;opacity:0;transition:opacity .5s}.stage-timer .blackout--active{z-index:101;opacity:1}.stage-timer .clock-container{margin-left:auto;font-weight:600;transition:opacity .5s}.stage-timer .clock-container .label{font-size:clamp(12px,1.25vw,20px);color:var(--label-color-override, rgba(255, 255, 255, .25));text-transform:uppercase}.stage-timer .clock-container .clock{font-size:clamp(24px,2.5vw,48px);color:var(--secondary-color-override, rgba(255, 255, 255, .45));letter-spacing:.05em;line-height:.95em}.stage-timer .clock-container--hidden{opacity:0}.stage-timer .event{background-color:var(--card-background-color-override, rgba(255, 255, 255, .05));padding:min(2vh,8px) clamp(16px,2vw,24px);border-radius:4px}.stage-timer .event.now{grid-area:now}.stage-timer .event.next{grid-area:next}.stage-timer .timer-container{flex:1;align-content:center;justify-self:center;align-self:center;width:100%;overflow:hidden}.stage-timer .timer-container .end-message{text-align:center;font-size:11.5vw;font-weight:600;color:var(--timer-overtime-color-override, #FA5656);padding:0;max-height:100%}.stage-timer .timer-container .timer{opacity:1;font-family:var(--timer-font, var(--font-family-override, "Open Sans", "Segoe UI", sans-serif));color:var(--timer-colour, var(--timer-color-override, #f6f6f6));line-height:.9em;text-align:center;letter-spacing:.05em;font-weight:600;transition-property:font-size;transition-duration:.5s}.stage-timer .timer-container .timer--paused{opacity:.6;transition:.5s}.stage-timer .timer-container .timer--finished{color:var(--timer-overtime-color-override, #FA5656)}.stage-timer .timer-container .timer[data-phase=warning]{color:var(--timer-colour, var(--timer-warning-color-override))}.stage-timer .timer-container .timer[data-phase=danger]{color:var(--timer-colour, var(--timer-danger-color-override))}.stage-timer .timer-container .timer[data-type=none]{transition:1s;opacity:0}.stage-timer .secondary{white-space:nowrap;overflow:hidden;text-overflow:ellipsis;margin-top:.125em;padding-block:.125em;font-weight:600;text-align:center;color:var(--external-color-override, rgba(255, 255, 255, .85));letter-spacing:.5px;line-height:1em;transition-property:opacity,height;transition-duration:.5s;border-top:1px solid color-mix(in srgb,var(--external-color-override, rgba(255, 255, 255, .85)) 10%,transparent)}.stage-timer .secondary--hidden{opacity:0;height:0}.stage-timer .progress-container{width:100%;margin:0 auto;opacity:1;transition:.5s}.stage-timer .progress-container--paused{opacity:.6;transition:.5s}.stage-timer .message-overlay{position:fixed;top:0;right:0;bottom:0;left:0;padding:2vw;background:var(--background-color-override, #101010);opacity:0;transition:opacity .5s}.stage-timer .message-overlay--active{z-index:100;opacity:1}.stage-timer .message{display:grid;place-content:center;height:100%;width:100%;color:var(--color-override, rgba(255, 255, 255, .8));text-align:center;font-weight:600}.stage-timer .logo{position:absolute;top:min(2vh,16px);left:clamp(16px,2vw,24px);max-width:min(200px,20vw)}@media screen and (max-width: 768px){.stage-timer .logo img{height:min(50px,10vh)}}