@getontime/cli 4.0.0 → 4.0.2

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 (331) hide show
  1. package/client/assets/{Backstage-ZSqb8OU6.js → Backstage-CAjkmeJm.js} +2 -2
  2. package/client/assets/Backstage-CAjkmeJm.js.br +0 -0
  3. package/client/assets/Backstage-CAjkmeJm.js.gz +0 -0
  4. package/client/assets/{Backstage-ZSqb8OU6.js.map → Backstage-CAjkmeJm.js.map} +1 -1
  5. package/client/assets/{Countdown-DVRZbeRP.js → Countdown-ChuA9az_.js} +2 -2
  6. package/client/assets/Countdown-ChuA9az_.js.br +0 -0
  7. package/client/assets/Countdown-ChuA9az_.js.gz +0 -0
  8. package/client/assets/{Countdown-DVRZbeRP.js.map → Countdown-ChuA9az_.js.map} +1 -1
  9. package/client/assets/{CustomTranslationModal-D_Cy0d_H.js → CustomTranslationModal-C3R_2T5s.js} +2 -2
  10. package/client/assets/CustomTranslationModal-C3R_2T5s.js.br +0 -0
  11. package/client/assets/CustomTranslationModal-C3R_2T5s.js.gz +0 -0
  12. package/client/assets/{CustomTranslationModal-D_Cy0d_H.js.map → CustomTranslationModal-C3R_2T5s.js.map} +1 -1
  13. package/client/assets/{DelayIndicator-B_JKLKYW.js → DelayIndicator-vT7n8ypf.js} +2 -2
  14. package/client/assets/DelayIndicator-vT7n8ypf.js.br +0 -0
  15. package/client/assets/DelayIndicator-vT7n8ypf.js.gz +0 -0
  16. package/client/assets/{DelayIndicator-B_JKLKYW.js.map → DelayIndicator-vT7n8ypf.js.map} +1 -1
  17. package/client/assets/{EditorFeatureWrapper-DzBxDvRn.js → EditorFeatureWrapper-DHfuO3EA.js} +2 -2
  18. package/client/assets/EditorFeatureWrapper-DHfuO3EA.js.br +0 -0
  19. package/client/assets/EditorFeatureWrapper-DHfuO3EA.js.gz +0 -0
  20. package/client/assets/{EditorFeatureWrapper-DzBxDvRn.js.map → EditorFeatureWrapper-DHfuO3EA.js.map} +1 -1
  21. package/client/assets/{EditorUtils-De0umjb-.js → EditorUtils-Da5ALK1P.js} +2 -2
  22. package/client/assets/EditorUtils-Da5ALK1P.js.br +0 -0
  23. package/client/assets/EditorUtils-Da5ALK1P.js.gz +0 -0
  24. package/client/assets/{EditorUtils-De0umjb-.js.map → EditorUtils-Da5ALK1P.js.map} +1 -1
  25. package/client/assets/{Empty-BYF0tVRk.js → Empty-gWT_HMeu.js} +2 -2
  26. package/client/assets/Empty-gWT_HMeu.js.br +0 -0
  27. package/client/assets/Empty-gWT_HMeu.js.gz +0 -0
  28. package/client/assets/{Empty-BYF0tVRk.js.map → Empty-gWT_HMeu.js.map} +1 -1
  29. package/client/assets/{EmptyPage-DYH2bswA.js → EmptyPage-Dcbg6rmF.js} +2 -2
  30. package/client/assets/EmptyPage-Dcbg6rmF.js.br +0 -0
  31. package/client/assets/EmptyPage-Dcbg6rmF.js.gz +0 -0
  32. package/client/assets/{EmptyPage-DYH2bswA.js.map → EmptyPage-Dcbg6rmF.js.map} +1 -1
  33. package/client/assets/{FollowButton-DyWsvyFF.js → FollowButton-CSqJSvix.js} +2 -2
  34. package/client/assets/FollowButton-CSqJSvix.js.br +0 -0
  35. package/client/assets/FollowButton-CSqJSvix.js.gz +0 -0
  36. package/client/assets/{FollowButton-DyWsvyFF.js.map → FollowButton-CSqJSvix.js.map} +1 -1
  37. package/client/assets/{MessageControlExport-yLGU2dMq.js → MessageControlExport-lXK21piH.js} +2 -2
  38. package/client/assets/MessageControlExport-lXK21piH.js.br +0 -0
  39. package/client/assets/MessageControlExport-lXK21piH.js.gz +0 -0
  40. package/client/assets/{MessageControlExport-yLGU2dMq.js.map → MessageControlExport-lXK21piH.js.map} +1 -1
  41. package/client/assets/{MilestoneEditor-GkzJ-h1C.js → MilestoneEditor-Bge8xLrV.js} +2 -2
  42. package/client/assets/MilestoneEditor-Bge8xLrV.js.br +0 -0
  43. package/client/assets/MilestoneEditor-Bge8xLrV.js.gz +0 -0
  44. package/client/assets/{MilestoneEditor-GkzJ-h1C.js.map → MilestoneEditor-Bge8xLrV.js.map} +1 -1
  45. package/client/assets/{Modal-BKL-5GzU.js → Modal-C2sFA0zf.js} +2 -2
  46. package/client/assets/Modal-C2sFA0zf.js.br +0 -0
  47. package/client/assets/Modal-C2sFA0zf.js.gz +0 -0
  48. package/client/assets/{Modal-BKL-5GzU.js.map → Modal-C2sFA0zf.js.map} +1 -1
  49. package/client/assets/{MultiPartProgressBar-BITERKS0.js → MultiPartProgressBar-D3jJZjb5.js} +2 -2
  50. package/client/assets/MultiPartProgressBar-D3jJZjb5.js.br +0 -0
  51. package/client/assets/MultiPartProgressBar-D3jJZjb5.js.gz +0 -0
  52. package/client/assets/{MultiPartProgressBar-BITERKS0.js.map → MultiPartProgressBar-D3jJZjb5.js.map} +1 -1
  53. package/client/assets/{OperatorExport-DMZ6eQfT.js → OperatorExport-BUhxjLUx.js} +2 -2
  54. package/client/assets/OperatorExport-BUhxjLUx.js.br +0 -0
  55. package/client/assets/OperatorExport-BUhxjLUx.js.gz +0 -0
  56. package/client/assets/{OperatorExport-DMZ6eQfT.js.map → OperatorExport-BUhxjLUx.js.map} +1 -1
  57. package/client/assets/{OverviewWrapper-riM6vPno.js → OverviewWrapper-BveJ6GjK.js} +2 -2
  58. package/client/assets/OverviewWrapper-BveJ6GjK.js.br +0 -0
  59. package/client/assets/OverviewWrapper-BveJ6GjK.js.gz +0 -0
  60. package/client/assets/{OverviewWrapper-riM6vPno.js.map → OverviewWrapper-BveJ6GjK.js.map} +1 -1
  61. package/client/assets/{ProjectInfo-DxtMq70a.js → ProjectInfo-z4k3cipS.js} +2 -2
  62. package/client/assets/ProjectInfo-z4k3cipS.js.br +0 -0
  63. package/client/assets/ProjectInfo-z4k3cipS.js.gz +0 -0
  64. package/client/assets/{ProjectInfo-DxtMq70a.js.map → ProjectInfo-z4k3cipS.js.map} +1 -1
  65. package/client/assets/{ProtectRoute-p1fmtLeu.js → ProtectRoute-CrcWfOlG.js} +2 -2
  66. package/client/assets/ProtectRoute-CrcWfOlG.js.br +0 -0
  67. package/client/assets/ProtectRoute-CrcWfOlG.js.gz +0 -0
  68. package/client/assets/{ProtectRoute-p1fmtLeu.js.map → ProtectRoute-CrcWfOlG.js.map} +1 -1
  69. package/client/assets/{ProtectedCuesheet-CvRnqT0z.js → ProtectedCuesheet-Deo4Aw6f.js} +2 -2
  70. package/client/assets/ProtectedCuesheet-Deo4Aw6f.js.br +0 -0
  71. package/client/assets/ProtectedCuesheet-Deo4Aw6f.js.gz +0 -0
  72. package/client/assets/{ProtectedCuesheet-CvRnqT0z.js.map → ProtectedCuesheet-Deo4Aw6f.js.map} +1 -1
  73. package/client/assets/{ProtectedEditor-D4UXj1xL.js → ProtectedEditor-C_SYWpL2.js} +3 -3
  74. package/client/assets/ProtectedEditor-C_SYWpL2.js.br +0 -0
  75. package/client/assets/ProtectedEditor-C_SYWpL2.js.gz +0 -0
  76. package/client/assets/{ProtectedEditor-D4UXj1xL.js.map → ProtectedEditor-C_SYWpL2.js.map} +1 -1
  77. package/client/assets/{RundownEntry-B1dSz1wu.js → RundownEntry-D61IqkXb.js} +2 -2
  78. package/client/assets/RundownEntry-D61IqkXb.js.br +0 -0
  79. package/client/assets/RundownEntry-D61IqkXb.js.gz +0 -0
  80. package/client/assets/{RundownEntry-B1dSz1wu.js.map → RundownEntry-D61IqkXb.js.map} +1 -1
  81. package/client/assets/RundownExport-1zBZurIG.css +1 -0
  82. package/client/assets/RundownExport-1zBZurIG.css.br +0 -0
  83. package/client/assets/RundownExport-1zBZurIG.css.gz +0 -0
  84. package/client/assets/{RundownExport-WjLpncYT.js → RundownExport-C6YhMGOC.js} +3 -3
  85. package/client/assets/RundownExport-C6YhMGOC.js.br +0 -0
  86. package/client/assets/RundownExport-C6YhMGOC.js.gz +0 -0
  87. package/client/assets/{RundownExport-WjLpncYT.js.map → RundownExport-C6YhMGOC.js.map} +1 -1
  88. package/client/assets/{Select-niU9Razm.js → Select-CedN80WS.js} +2 -2
  89. package/client/assets/Select-CedN80WS.js.br +0 -0
  90. package/client/assets/Select-CedN80WS.js.gz +0 -0
  91. package/client/assets/{Select-niU9Razm.js.map → Select-CedN80WS.js.map} +1 -1
  92. package/client/assets/{Studio-CWdJq4bx.js → Studio-DUzPBS6P.js} +2 -2
  93. package/client/assets/Studio-DUzPBS6P.js.br +0 -0
  94. package/client/assets/Studio-DUzPBS6P.js.gz +0 -0
  95. package/client/assets/{Studio-CWdJq4bx.js.map → Studio-DUzPBS6P.js.map} +1 -1
  96. package/client/assets/{StyleEditor-BIFjHsgD.js → StyleEditor-D2z65PB7.js} +2 -2
  97. package/client/assets/StyleEditor-D2z65PB7.js.br +0 -0
  98. package/client/assets/StyleEditor-D2z65PB7.js.gz +0 -0
  99. package/client/assets/{StyleEditor-BIFjHsgD.js.map → StyleEditor-D2z65PB7.js.map} +1 -1
  100. package/client/assets/{SuperscriptTime-DCTyUARx.js → SuperscriptTime-CIrcMcyg.js} +2 -2
  101. package/client/assets/SuperscriptTime-CIrcMcyg.js.br +0 -0
  102. package/client/assets/SuperscriptTime-CIrcMcyg.js.gz +0 -0
  103. package/client/assets/{SuperscriptTime-DCTyUARx.js.map → SuperscriptTime-CIrcMcyg.js.map} +1 -1
  104. package/client/assets/{TimeElements-DBVGVx71.js → TimeElements-CALNfv6u.js} +2 -2
  105. package/client/assets/TimeElements-CALNfv6u.js.br +0 -0
  106. package/client/assets/TimeElements-CALNfv6u.js.gz +0 -0
  107. package/client/assets/{TimeElements-DBVGVx71.js.map → TimeElements-CALNfv6u.js.map} +1 -1
  108. package/client/assets/{TimeInput-wQ67FbW6.js → TimeInput-Dg1naiy3.js} +2 -2
  109. package/client/assets/TimeInput-Dg1naiy3.js.br +0 -0
  110. package/client/assets/TimeInput-Dg1naiy3.js.gz +0 -0
  111. package/client/assets/{TimeInput-wQ67FbW6.js.map → TimeInput-Dg1naiy3.js.map} +1 -1
  112. package/client/assets/{TimelinePage-DZefE2vQ.js → TimelinePage-Cwm0svjN.js} +2 -2
  113. package/client/assets/TimelinePage-Cwm0svjN.js.br +0 -0
  114. package/client/assets/TimelinePage-Cwm0svjN.js.gz +0 -0
  115. package/client/assets/{TimelinePage-DZefE2vQ.js.map → TimelinePage-Cwm0svjN.js.map} +1 -1
  116. package/client/assets/Timer-BVXskRjc.js +2 -0
  117. package/client/assets/Timer-BVXskRjc.js.br +0 -0
  118. package/client/assets/Timer-BVXskRjc.js.gz +0 -0
  119. package/client/assets/Timer-BVXskRjc.js.map +1 -0
  120. package/client/assets/Timer-BvEmZbmF.css +1 -0
  121. package/client/assets/Timer-BvEmZbmF.css.br +0 -0
  122. package/client/assets/Timer-BvEmZbmF.css.gz +0 -0
  123. package/client/assets/{TimerControlExport-C1C_vBX4.js → TimerControlExport-C8ECtLBd.js} +2 -2
  124. package/client/assets/TimerControlExport-C8ECtLBd.js.br +0 -0
  125. package/client/assets/TimerControlExport-C8ECtLBd.js.gz +0 -0
  126. package/client/assets/{TimerControlExport-C1C_vBX4.js.map → TimerControlExport-C8ECtLBd.js.map} +1 -1
  127. package/client/assets/{TitleCard-B4N-kCM3.js → TitleCard-CZl9wSHS.js} +2 -2
  128. package/client/assets/TitleCard-CZl9wSHS.js.br +0 -0
  129. package/client/assets/TitleCard-CZl9wSHS.js.gz +0 -0
  130. package/client/assets/{TitleCard-B4N-kCM3.js.map → TitleCard-CZl9wSHS.js.map} +1 -1
  131. package/client/assets/{Tooltip-DJ8Y4CO4.js → Tooltip-D9XRnwOW.js} +2 -2
  132. package/client/assets/Tooltip-D9XRnwOW.js.br +4 -0
  133. package/client/assets/Tooltip-D9XRnwOW.js.gz +0 -0
  134. package/client/assets/{Tooltip-DJ8Y4CO4.js.map → Tooltip-D9XRnwOW.js.map} +1 -1
  135. package/client/assets/{ViewLogo-Dd60EREE.js → ViewLogo-_3Z1hIHi.js} +2 -2
  136. package/client/assets/ViewLogo-_3Z1hIHi.js.br +0 -0
  137. package/client/assets/ViewLogo-_3Z1hIHi.js.gz +0 -0
  138. package/client/assets/{ViewLogo-Dd60EREE.js.map → ViewLogo-_3Z1hIHi.js.map} +1 -1
  139. package/client/assets/{ViewParamsEditor-BWEYbq_S.js → ViewParamsEditor-Bca1TIDW.js} +2 -2
  140. package/client/assets/ViewParamsEditor-Bca1TIDW.js.br +0 -0
  141. package/client/assets/ViewParamsEditor-Bca1TIDW.js.gz +0 -0
  142. package/client/assets/{ViewParamsEditor-BWEYbq_S.js.map → ViewParamsEditor-Bca1TIDW.js.map} +1 -1
  143. package/client/assets/{dateConfig-8rhb0Dbh.js → dateConfig-DRQGMWDF.js} +2 -2
  144. package/client/assets/dateConfig-DRQGMWDF.js.br +0 -0
  145. package/client/assets/dateConfig-DRQGMWDF.js.gz +0 -0
  146. package/client/assets/{dateConfig-8rhb0Dbh.js.map → dateConfig-DRQGMWDF.js.map} +1 -1
  147. package/client/assets/{editorSettings-LMnfWux6.js → editorSettings-BU0pTMSY.js} +2 -2
  148. package/client/assets/editorSettings-BU0pTMSY.js.br +0 -0
  149. package/client/assets/editorSettings-BU0pTMSY.js.gz +0 -0
  150. package/client/assets/{editorSettings-LMnfWux6.js.map → editorSettings-BU0pTMSY.js.map} +1 -1
  151. package/client/assets/{getProgress-CyJTu6f5.js → getProgress-Cw79NL_O.js} +2 -2
  152. package/client/assets/getProgress-Cw79NL_O.js.br +0 -0
  153. package/client/assets/getProgress-Cw79NL_O.js.gz +0 -0
  154. package/client/assets/{getProgress-CyJTu6f5.js.map → getProgress-Cw79NL_O.js.map} +1 -1
  155. package/client/assets/{index-5QAOtSTh.js → index-BQEUaoAf.js} +3 -3
  156. package/client/assets/index-BQEUaoAf.js.br +0 -0
  157. package/client/assets/index-BQEUaoAf.js.gz +0 -0
  158. package/client/assets/{index-5QAOtSTh.js.map → index-BQEUaoAf.js.map} +1 -1
  159. package/client/assets/{offset-CLDSqOP5.js → offset-DJAHqjFW.js} +2 -2
  160. package/client/assets/offset-DJAHqjFW.js.br +0 -0
  161. package/client/assets/offset-DJAHqjFW.js.gz +0 -0
  162. package/client/assets/{offset-CLDSqOP5.js.map → offset-DJAHqjFW.js.map} +1 -1
  163. package/client/assets/{parseUserTime-CCDHpp7D.js → parseUserTime-BeTKj08M.js} +2 -2
  164. package/client/assets/parseUserTime-BeTKj08M.js.br +0 -0
  165. package/client/assets/parseUserTime-BeTKj08M.js.gz +0 -0
  166. package/client/assets/{parseUserTime-CCDHpp7D.js.map → parseUserTime-BeTKj08M.js.map} +1 -1
  167. package/client/assets/{playbackstate-6lBh6omZ.js → playbackstate-B_khF6xU.js} +2 -2
  168. package/client/assets/playbackstate-B_khF6xU.js.br +0 -0
  169. package/client/assets/playbackstate-B_khF6xU.js.gz +0 -0
  170. package/client/assets/{playbackstate-6lBh6omZ.js.map → playbackstate-B_khF6xU.js.map} +1 -1
  171. package/client/assets/{presentation.utils-BUIuV_2e.js → presentation.utils-KwY-ACf7.js} +2 -2
  172. package/client/assets/presentation.utils-KwY-ACf7.js.br +0 -0
  173. package/client/assets/presentation.utils-KwY-ACf7.js.gz +0 -0
  174. package/client/assets/{presentation.utils-BUIuV_2e.js.map → presentation.utils-KwY-ACf7.js.map} +1 -1
  175. package/client/assets/{rundownUtils-Cnd2prRX.js → rundownUtils-BZHazkXR.js} +2 -2
  176. package/client/assets/rundownUtils-BZHazkXR.js.br +0 -0
  177. package/client/assets/rundownUtils-BZHazkXR.js.gz +0 -0
  178. package/client/assets/{rundownUtils-Cnd2prRX.js.map → rundownUtils-BZHazkXR.js.map} +1 -1
  179. package/client/assets/{useCustomFields-BuxKsqGS.js → useCustomFields-DqCYz8Kt.js} +2 -2
  180. package/client/assets/useCustomFields-DqCYz8Kt.js.br +0 -0
  181. package/client/assets/useCustomFields-DqCYz8Kt.js.gz +0 -0
  182. package/client/assets/{useCustomFields-BuxKsqGS.js.map → useCustomFields-DqCYz8Kt.js.map} +1 -1
  183. package/client/assets/{useFollowComponent-iGQv4zoS.js → useFollowComponent-Ctfhf2or.js} +2 -2
  184. package/client/assets/useFollowComponent-Ctfhf2or.js.br +0 -0
  185. package/client/assets/useFollowComponent-Ctfhf2or.js.gz +0 -0
  186. package/client/assets/{useFollowComponent-iGQv4zoS.js.map → useFollowComponent-Ctfhf2or.js.map} +1 -1
  187. package/client/assets/{useProjectData-CetvEK9E.js → useProjectData-C1hVamxc.js} +2 -2
  188. package/client/assets/useProjectData-C1hVamxc.js.br +0 -0
  189. package/client/assets/useProjectData-C1hVamxc.js.gz +0 -0
  190. package/client/assets/{useProjectData-CetvEK9E.js.map → useProjectData-C1hVamxc.js.map} +1 -1
  191. package/client/assets/{useReport-PEFRsOhF.js → useReport-B4dMYcNL.js} +2 -2
  192. package/client/assets/useReport-B4dMYcNL.js.br +0 -0
  193. package/client/assets/useReport-B4dMYcNL.js.gz +0 -0
  194. package/client/assets/{useReport-PEFRsOhF.js.map → useReport-B4dMYcNL.js.map} +1 -1
  195. package/client/assets/useRundown-BfpjcCEJ.js +2 -0
  196. package/client/assets/useRundown-BfpjcCEJ.js.br +0 -0
  197. package/client/assets/useRundown-BfpjcCEJ.js.gz +0 -0
  198. package/client/assets/{useRundown-D8CYATNi.js.map → useRundown-BfpjcCEJ.js.map} +1 -1
  199. package/client/assets/{useWindowTitle-b5fN0StF.js → useWindowTitle-DqdFTWns.js} +2 -2
  200. package/client/assets/useWindowTitle-DqdFTWns.js.br +0 -0
  201. package/client/assets/useWindowTitle-DqdFTWns.js.gz +0 -0
  202. package/client/assets/{useWindowTitle-b5fN0StF.js.map → useWindowTitle-DqdFTWns.js.map} +1 -1
  203. package/client/assets/{validateEvent-Bvgk1E-Y.js → validateEvent-P9sf7C10.js} +2 -2
  204. package/client/assets/validateEvent-P9sf7C10.js.br +3 -0
  205. package/client/assets/validateEvent-P9sf7C10.js.gz +0 -0
  206. package/client/assets/{validateEvent-Bvgk1E-Y.js.map → validateEvent-P9sf7C10.js.map} +1 -1
  207. package/client/assets/{vendor-Cu5xgv5K.js → vendor-CCiSQ9k9.js} +2 -2
  208. package/client/assets/vendor-CCiSQ9k9.js.br +0 -0
  209. package/client/assets/vendor-CCiSQ9k9.js.gz +0 -0
  210. package/client/assets/{vendor-Cu5xgv5K.js.map → vendor-CCiSQ9k9.js.map} +1 -1
  211. package/client/assets/{viewLoader.utils-BPhACxyG.js → viewLoader.utils-CmM-4-pk.js} +2 -2
  212. package/client/assets/viewLoader.utils-CmM-4-pk.js.br +0 -0
  213. package/client/assets/viewLoader.utils-CmM-4-pk.js.gz +0 -0
  214. package/client/assets/{viewLoader.utils-BPhACxyG.js.map → viewLoader.utils-CmM-4-pk.js.map} +1 -1
  215. package/client/index.html +2 -2
  216. package/external/demo/app.js +2 -2
  217. package/package.json +1 -1
  218. package/server/index.cjs +66 -57
  219. package/client/assets/Backstage-ZSqb8OU6.js.br +0 -0
  220. package/client/assets/Backstage-ZSqb8OU6.js.gz +0 -0
  221. package/client/assets/Countdown-DVRZbeRP.js.br +0 -0
  222. package/client/assets/Countdown-DVRZbeRP.js.gz +0 -0
  223. package/client/assets/CustomTranslationModal-D_Cy0d_H.js.br +0 -0
  224. package/client/assets/CustomTranslationModal-D_Cy0d_H.js.gz +0 -0
  225. package/client/assets/DelayIndicator-B_JKLKYW.js.br +0 -0
  226. package/client/assets/DelayIndicator-B_JKLKYW.js.gz +0 -0
  227. package/client/assets/EditorFeatureWrapper-DzBxDvRn.js.br +0 -0
  228. package/client/assets/EditorFeatureWrapper-DzBxDvRn.js.gz +0 -0
  229. package/client/assets/EditorUtils-De0umjb-.js.br +0 -0
  230. package/client/assets/EditorUtils-De0umjb-.js.gz +0 -0
  231. package/client/assets/Empty-BYF0tVRk.js.br +0 -2
  232. package/client/assets/Empty-BYF0tVRk.js.gz +0 -0
  233. package/client/assets/EmptyPage-DYH2bswA.js.br +0 -0
  234. package/client/assets/EmptyPage-DYH2bswA.js.gz +0 -0
  235. package/client/assets/FollowButton-DyWsvyFF.js.br +0 -0
  236. package/client/assets/FollowButton-DyWsvyFF.js.gz +0 -0
  237. package/client/assets/MessageControlExport-yLGU2dMq.js.br +0 -0
  238. package/client/assets/MessageControlExport-yLGU2dMq.js.gz +0 -0
  239. package/client/assets/MilestoneEditor-GkzJ-h1C.js.br +0 -0
  240. package/client/assets/MilestoneEditor-GkzJ-h1C.js.gz +0 -0
  241. package/client/assets/Modal-BKL-5GzU.js.br +0 -0
  242. package/client/assets/Modal-BKL-5GzU.js.gz +0 -0
  243. package/client/assets/MultiPartProgressBar-BITERKS0.js.br +0 -0
  244. package/client/assets/MultiPartProgressBar-BITERKS0.js.gz +0 -0
  245. package/client/assets/OperatorExport-DMZ6eQfT.js.br +0 -0
  246. package/client/assets/OperatorExport-DMZ6eQfT.js.gz +0 -0
  247. package/client/assets/OverviewWrapper-riM6vPno.js.br +0 -0
  248. package/client/assets/OverviewWrapper-riM6vPno.js.gz +0 -0
  249. package/client/assets/ProjectInfo-DxtMq70a.js.br +0 -0
  250. package/client/assets/ProjectInfo-DxtMq70a.js.gz +0 -0
  251. package/client/assets/ProtectRoute-p1fmtLeu.js.br +0 -0
  252. package/client/assets/ProtectRoute-p1fmtLeu.js.gz +0 -0
  253. package/client/assets/ProtectedCuesheet-CvRnqT0z.js.br +0 -0
  254. package/client/assets/ProtectedCuesheet-CvRnqT0z.js.gz +0 -0
  255. package/client/assets/ProtectedEditor-D4UXj1xL.js.br +0 -0
  256. package/client/assets/ProtectedEditor-D4UXj1xL.js.gz +0 -0
  257. package/client/assets/RundownEntry-B1dSz1wu.js.br +0 -0
  258. package/client/assets/RundownEntry-B1dSz1wu.js.gz +0 -0
  259. package/client/assets/RundownExport-CUtaG16H.css +0 -1
  260. package/client/assets/RundownExport-CUtaG16H.css.br +0 -0
  261. package/client/assets/RundownExport-CUtaG16H.css.gz +0 -0
  262. package/client/assets/RundownExport-WjLpncYT.js.br +0 -0
  263. package/client/assets/RundownExport-WjLpncYT.js.gz +0 -0
  264. package/client/assets/Select-niU9Razm.js.br +0 -0
  265. package/client/assets/Select-niU9Razm.js.gz +0 -0
  266. package/client/assets/Studio-CWdJq4bx.js.br +0 -0
  267. package/client/assets/Studio-CWdJq4bx.js.gz +0 -0
  268. package/client/assets/StyleEditor-BIFjHsgD.js.br +0 -0
  269. package/client/assets/StyleEditor-BIFjHsgD.js.gz +0 -0
  270. package/client/assets/SuperscriptTime-DCTyUARx.js.br +0 -0
  271. package/client/assets/SuperscriptTime-DCTyUARx.js.gz +0 -0
  272. package/client/assets/TimeElements-DBVGVx71.js.br +0 -0
  273. package/client/assets/TimeElements-DBVGVx71.js.gz +0 -0
  274. package/client/assets/TimeInput-wQ67FbW6.js.br +0 -0
  275. package/client/assets/TimeInput-wQ67FbW6.js.gz +0 -0
  276. package/client/assets/TimelinePage-DZefE2vQ.js.br +0 -0
  277. package/client/assets/TimelinePage-DZefE2vQ.js.gz +0 -0
  278. package/client/assets/Timer-Bs450x86.js +0 -2
  279. package/client/assets/Timer-Bs450x86.js.br +0 -0
  280. package/client/assets/Timer-Bs450x86.js.gz +0 -0
  281. package/client/assets/Timer-Bs450x86.js.map +0 -1
  282. package/client/assets/Timer-DGNfbBKM.css +0 -1
  283. package/client/assets/Timer-DGNfbBKM.css.br +0 -0
  284. package/client/assets/Timer-DGNfbBKM.css.gz +0 -0
  285. package/client/assets/TimerControlExport-C1C_vBX4.js.br +0 -0
  286. package/client/assets/TimerControlExport-C1C_vBX4.js.gz +0 -0
  287. package/client/assets/TitleCard-B4N-kCM3.js.br +0 -0
  288. package/client/assets/TitleCard-B4N-kCM3.js.gz +0 -0
  289. package/client/assets/Tooltip-DJ8Y4CO4.js.br +0 -0
  290. package/client/assets/Tooltip-DJ8Y4CO4.js.gz +0 -0
  291. package/client/assets/ViewLogo-Dd60EREE.js.br +0 -0
  292. package/client/assets/ViewLogo-Dd60EREE.js.gz +0 -0
  293. package/client/assets/ViewParamsEditor-BWEYbq_S.js.br +0 -0
  294. package/client/assets/ViewParamsEditor-BWEYbq_S.js.gz +0 -0
  295. package/client/assets/dateConfig-8rhb0Dbh.js.br +0 -0
  296. package/client/assets/dateConfig-8rhb0Dbh.js.gz +0 -0
  297. package/client/assets/editorSettings-LMnfWux6.js.br +0 -0
  298. package/client/assets/editorSettings-LMnfWux6.js.gz +0 -0
  299. package/client/assets/getProgress-CyJTu6f5.js.br +0 -0
  300. package/client/assets/getProgress-CyJTu6f5.js.gz +0 -0
  301. package/client/assets/index-5QAOtSTh.js.br +0 -0
  302. package/client/assets/index-5QAOtSTh.js.gz +0 -0
  303. package/client/assets/offset-CLDSqOP5.js.br +0 -0
  304. package/client/assets/offset-CLDSqOP5.js.gz +0 -0
  305. package/client/assets/parseUserTime-CCDHpp7D.js.br +0 -0
  306. package/client/assets/parseUserTime-CCDHpp7D.js.gz +0 -0
  307. package/client/assets/playbackstate-6lBh6omZ.js.br +0 -0
  308. package/client/assets/playbackstate-6lBh6omZ.js.gz +0 -0
  309. package/client/assets/presentation.utils-BUIuV_2e.js.br +0 -0
  310. package/client/assets/presentation.utils-BUIuV_2e.js.gz +0 -0
  311. package/client/assets/rundownUtils-Cnd2prRX.js.br +0 -0
  312. package/client/assets/rundownUtils-Cnd2prRX.js.gz +0 -0
  313. package/client/assets/useCustomFields-BuxKsqGS.js.br +0 -0
  314. package/client/assets/useCustomFields-BuxKsqGS.js.gz +0 -0
  315. package/client/assets/useFollowComponent-iGQv4zoS.js.br +0 -0
  316. package/client/assets/useFollowComponent-iGQv4zoS.js.gz +0 -0
  317. package/client/assets/useProjectData-CetvEK9E.js.br +0 -0
  318. package/client/assets/useProjectData-CetvEK9E.js.gz +0 -0
  319. package/client/assets/useReport-PEFRsOhF.js.br +0 -0
  320. package/client/assets/useReport-PEFRsOhF.js.gz +0 -0
  321. package/client/assets/useRundown-D8CYATNi.js +0 -2
  322. package/client/assets/useRundown-D8CYATNi.js.br +0 -0
  323. package/client/assets/useRundown-D8CYATNi.js.gz +0 -0
  324. package/client/assets/useWindowTitle-b5fN0StF.js.br +0 -0
  325. package/client/assets/useWindowTitle-b5fN0StF.js.gz +0 -0
  326. package/client/assets/validateEvent-Bvgk1E-Y.js.br +0 -0
  327. package/client/assets/validateEvent-Bvgk1E-Y.js.gz +0 -0
  328. package/client/assets/vendor-Cu5xgv5K.js.br +0 -0
  329. package/client/assets/vendor-Cu5xgv5K.js.gz +0 -0
  330. package/client/assets/viewLoader.utils-BPhACxyG.js.br +0 -0
  331. package/client/assets/viewLoader.utils-BPhACxyG.js.gz +0 -0
@@ -1 +1 @@
1
- {"version":3,"mappings":"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","names":["reorderArray","array","fromIndex","toIndex","modifiedArray","reorderedItem","isMacOS","userAgent","deviceAlt","deviceMod","useEventSelection","create","set","get","id","index","selectMode","selectedEvents","anchoredIndex","entryMode","rundownData","ontimeQueryClient","RUNDOWN","nextIndex","eventId","i","isOntimeEvent","eventIds","event","start","end","selectedEventIds","firstSelected","getSelectionMode","memo","EventEditorFooter","cue","loadById","loadByCue","jsxs","style","jsx","CopyTag","EventEditorEmpty","Editor.Title","Kbd","AuxKey","children","RundownEntryEditor","state","data","useRundown","entry","setEntry","useState","useEffect","selectedEventId","isOntimeDelay","EventEditor","isOntimeMilestone","MilestoneEditor","isOntimeGroup","GroupEditor","maxResults","useFinder","rundownId","useFlatRundown","results","setResults","error","setError","lastSearchString","useRef","setSelectedEvents","collapsedGroups","setCollapsedGroups","useSessionStorage","find","useCallback","searchValue","searchString","searchByIndex","searchByCue","searchByTitle","searchIndex","eventIndex","SupportedEntry","remaining","select","selectedEvent","newGroups","Finder","isOpen","onClose","selected","setSelected","debouncedFind","useDebouncedCallback","navigate","prev","submit","handleMouseMoveEvent","li","Modal","Input","isSelected","displayIndex","displayCue","FinderPlacement","handler","useDisclosure","useHotkeys","useContextMenuStore","position","options","newIsOpen","RundownContextMenu","setIsOpen","Fragment","PositionedDropdownMenu","RundownMenu","handlers","clearSelectedEvents","editorMode","sessionKeys","AppMode","deleteAllEntries","useEntryActions","deleteAll","Toolbar.Button","Button","IoTrash","Dialog","RundownHeader","setEditorMode","offsetMode","useOffsetMode","toggleAppMode","mode","newValue","toggleOffsetMode","setOffsetMode","Toolbar.Root","ToggleGroup","Toggle","Editor.Separator","OffsetMode","useEntryCopy","entryCopyId","cloneEvent","QuickAddButtons","previousEventId","parentGroup","backgroundColor","addEntry","addEvent","addDelay","addMilestone","addGroup","groupColour","cx","IoAdd","QuickAddInline","referenceEntryId","placement","handleAddEntry","type","DropdownMenu","IconButton","useContextMenu","setContextMenu","contextMenuEvent","pageX","pageY","TitleEditor","title","entryId","placeholder","className","updateEntry","ref","submitCallback","text","cleanVal","value","onChange","onBlur","onKeyDown","useReactiveTextInput","classes","RundownGroup","hasCursor","collapsed","onCollapse","handleRef","clone","ungroup","deleteEntry","setSingleEntrySelection","onContextMenu","IoDuplicateOutline","IoFolderOpenOutline","dragAttributes","dragListeners","setNodeRef","transform","transition","isDragging","isOver","over","useSortable","handleFocusClick","binderColours","getAccessibleColour","isValidDrop","canDrop","_a","_b","planOffset","planOffsetLabel","offset","absOffset","formatDuration","MILLIS_PER_MINUTE","getOffsetState","dragStyle","CSS","IoReorderTwo","IoChevronUp","IoChevronDown","formatTime","RundownGroupEnd","colour","RundownEmpty","props","handleAddNew","Empty","RundownEntry","lazy","__vitePreload","Rundown","rundownMetadata","order","entries","featureData","useRundownEditor","sortableData","setSortableData","makeSortableList","metadata","setMetadata","move","reorderEntry","setEntryCopyId","cursor","cursorRef","scrollRef","useFollowComponent","sensors","useSensors","useSensor","PointerSensor","deleteAtCursor","getPreviousNormal","insertCopyAtId","atId","copyId","above","adjustedCursor","cloneEntry","newEvent","insertAtId","patch","selectGroup","direction","newCursor","getLastNormal","getFirstNormal","getPreviousGroupNormal","getNextGroupNormal","selectEntry","getNextNormal","getIsCollapsed","groupId","handleCollapseGroup","isCollapsed","moveEntry","movedIntoGroupId","maybeParent","handleOnDragEnd","active","destinationId","isDraggingGroup","group","currentEntries","_","collapseDraggedGroups","expandOverGroup","_c","_d","isEditMode","DndContext","closestCenter","SortableContext","verticalListSortingStrategy","parentId","isGroupCollapsed","parentMetadata","entryMetadata","isNext","isFirst","isLast","parentIdForBefore","parentIdForAfter","TbFlagFilled","Playback","lastMetadataKey","RundownWrapper","isSmallDevice","status","useRundownWithMetadata","styles","RundownHeaderMobile","RundownExport","isExtracted","useIsSmallDevice","ProtectRoute","ViewNavigationMenu","ErrorBoundary","hideSideBar","Corner","handleLinks"],"ignoreList":[],"sources":["../../../../packages/utils/src/common/arrayUtils.ts","../../src/common/utils/deviceUtils.ts","../../src/features/rundown/useEventSelection.ts","../../src/features/rundown/entry-editor/composite/EventEditorFooter.tsx","../../src/features/rundown/entry-editor/EventEditorEmpty.tsx","../../src/features/rundown/entry-editor/RundownEntryEditor.tsx","../../src/views/editor/finder/useFinder.tsx","../../src/views/editor/finder/Finder.tsx","../../src/features/rundown/placements/FinderPlacement.tsx","../../src/features/rundown/rundown-context-menu/RundownContextMenu.tsx","../../src/features/rundown/rundown-header/RundownMenu.tsx","../../src/features/rundown/rundown-header/RundownHeader.tsx","../../src/features/rundown/rundown-header/RundownHeaderMobile.tsx","../../src/common/stores/entryCopyStore.ts","../../src/common/utils/clone.ts","../../src/features/rundown/entry-editor/quick-add-buttons/QuickAddButtons.tsx","../../src/features/rundown/entry-editor/quick-add-cursor/QuickAddInline.tsx","../../src/common/hooks/useContextMenu.tsx","../../src/features/rundown/common/TitleEditor.tsx","../../src/features/rundown/rundown-group/RundownGroup.tsx","../../src/features/rundown/rundown-group/RundownGroupEnd.tsx","../../src/features/rundown/RundownEmpty.tsx","../../src/features/rundown/Rundown.tsx","../../src/features/rundown/RundownWrapper.tsx","../../src/features/rundown/RundownExport.tsx"],"sourcesContent":["/**\n * Inserts an item in an array at a given index\n * @param index\n * @param item\n * @param array\n */\nexport function insertAtIndex<T>(index: number, item: T, array: T[]): T[] {\n const modifiedArray = [...array];\n\n // Insert at beginning\n if (index === 0) {\n modifiedArray.unshift(item);\n }\n\n // insert at end\n else if (index >= modifiedArray.length) {\n modifiedArray.push(item);\n }\n\n // insert in the middle\n else {\n modifiedArray.splice(index, 0, item);\n }\n\n return modifiedArray;\n}\n\n/**\n * Inserts an array into another one of the same type at a given index\n */\nexport function mergeAtIndex<T>(index: number, newArray: T[], currentArray: T[]): T[] {\n // Insert at beginning\n if (index === 0) {\n return [...newArray, ...currentArray];\n }\n\n // insert at end\n else if (index >= currentArray.length) {\n return [...currentArray, ...newArray];\n }\n\n // insert in the middle\n return currentArray.toSpliced(index, 0, ...newArray);\n}\n\n/**\n * Deletes array element at a given index\n * @param index\n * @param array\n */\nexport function deleteAtIndex<T>(index: number, array: T[]) {\n return array.filter((_, i) => i !== index);\n}\n\n/**\n * Reorders two objects in an array\n */\nexport function reorderArray<T>(array: T[], fromIndex: number, toIndex: number): T[] {\n if (fromIndex === toIndex) {\n return array; // No change needed, return the original array\n }\n\n const modifiedArray = [...array];\n\n // delete in from\n const [reorderedItem] = modifiedArray.splice(fromIndex, 1);\n\n // reinsert item at to\n modifiedArray.splice(toIndex, 0, reorderedItem);\n return modifiedArray;\n}\n","export function isMacOS() {\n const userAgent = navigator.userAgent.toLowerCase();\n return userAgent.includes('macintosh') || userAgent.includes('mac os');\n}\n\nexport const deviceAlt = isMacOS() ? 'Option' : 'Alt';\n\nexport const deviceMod = isMacOS() ? 'Cmd' : 'Ctrl';\n","import { MouseEvent } from 'react';\nimport { EntryId, isOntimeEvent, MaybeNumber, MaybeString, Rundown } from 'ontime-types';\nimport { create } from 'zustand';\n\nimport { RUNDOWN } from '../../common/api/constants';\nimport { ontimeQueryClient } from '../../common/queryClient';\nimport { isMacOS } from '../../common/utils/deviceUtils';\n\ntype SelectionMode = 'shift' | 'click' | 'ctrl';\n\ninterface EventSelectionStore {\n selectedEvents: Set<EntryId>;\n anchoredIndex: MaybeNumber;\n cursor: MaybeString;\n entryMode: 'event' | 'single' | null;\n setSingleEntrySelection: (selectionArgs: { id: EntryId }) => void;\n setSelectedEvents: (selectionArgs: { id: EntryId; index: number; selectMode: SelectionMode }) => void;\n clearSelectedEvents: () => void;\n clearMultiSelect: () => void;\n unselect: (id: EntryId) => void;\n}\n\nexport const useEventSelection = create<EventSelectionStore>()((set, get) => ({\n selectedEvents: new Set(),\n anchoredIndex: null,\n cursor: null,\n entryMode: null,\n setSingleEntrySelection: ({ id }) => {\n set({ selectedEvents: new Set([id]), anchoredIndex: null, cursor: id, entryMode: 'single' });\n },\n setSelectedEvents: ({ id, index, selectMode }) => {\n const { selectedEvents, anchoredIndex, entryMode } = get();\n\n // if we are in single mode, we replace the selection and change the mode\n if (entryMode === 'single') {\n return set({ selectedEvents: new Set([id]), anchoredIndex: index, cursor: id, entryMode: 'event' });\n }\n\n // on click, we replace selection with event\n if (selectMode === 'click') {\n return set({ selectedEvents: new Set([id]), anchoredIndex: index, cursor: id, entryMode: 'event' });\n }\n\n // on ctrl + click, we toggle the selection of that event\n if (selectMode === 'ctrl') {\n const rundownData = ontimeQueryClient.getQueryData<Rundown>(RUNDOWN);\n if (!rundownData) return;\n\n // if it doesnt exist, simply add to the list and set an anchor\n if (!selectedEvents.has(id)) {\n return set({\n selectedEvents: selectedEvents.add(id),\n anchoredIndex: index,\n cursor: id,\n entryMode: 'event',\n });\n }\n\n // if event is already selected, we remove it from selection\n // and set the anchor to the event after\n selectedEvents.delete(id);\n\n const nextIndex = rundownData.order.findIndex(\n (eventId, i) => i > index && isOntimeEvent(rundownData.entries[eventId]) && selectedEvents.has(eventId),\n );\n\n // if we didnt find anything after, set the anchor to the last event\n return set({\n selectedEvents,\n anchoredIndex: nextIndex < 0 ? rundownData.order.length - 1 : nextIndex,\n entryMode: 'event',\n });\n }\n\n // on shift + click, we select a range of events up to the clicked event\n if (selectMode === 'shift') {\n const rundownData = ontimeQueryClient.getQueryData<Rundown>(RUNDOWN);\n if (!rundownData) return;\n\n // get list of rundown with only ontime events\n const eventIds: EntryId[] = [];\n rundownData.flatOrder.forEach((eventId) => {\n const event = rundownData.entries[eventId];\n if (isOntimeEvent(event)) {\n eventIds.push(event.id);\n }\n });\n\n const start = anchoredIndex === null ? 0 : Math.min(anchoredIndex, index);\n const end = anchoredIndex === null ? index : Math.max(anchoredIndex, index + 1);\n\n // create new set with range of ids from start to end\n const selectedEventIds = eventIds.slice(start, end);\n\n return set({\n selectedEvents: new Set([...selectedEvents, ...selectedEventIds]),\n anchoredIndex: index,\n entryMode: 'event',\n });\n }\n },\n clearSelectedEvents: () => set({ selectedEvents: new Set(), anchoredIndex: null, cursor: null, entryMode: null }),\n clearMultiSelect: () => {\n const { selectedEvents } = get();\n const [firstSelected] = selectedEvents;\n set({\n selectedEvents: new Set(firstSelected ? [firstSelected] : []),\n anchoredIndex: null,\n entryMode: null,\n });\n },\n unselect: (id: string) => {\n const { entryMode, selectedEvents } = get();\n selectedEvents.delete(id);\n set({\n selectedEvents,\n entryMode: selectedEvents.size === 0 ? null : entryMode,\n });\n },\n}));\n\nexport function getSelectionMode(event: MouseEvent): SelectionMode {\n if ((isMacOS() && event.metaKey) || event.ctrlKey) {\n return 'ctrl';\n }\n\n if (event.shiftKey) {\n return 'shift';\n }\n\n return 'click';\n}\n","import { memo } from 'react';\n\nimport CopyTag from '../../../../common/components/copy-tag/CopyTag';\n\nimport style from './EventEditorFooter.module.scss';\n\ninterface EventEditorFooterProps {\n id: string;\n cue: string;\n}\n\nexport default memo(EventEditorFooter);\nfunction EventEditorFooter({ id, cue }: EventEditorFooterProps) {\n const loadById = `/ontime/load/id \"${id}\"`;\n const loadByCue = `/ontime/load/cue \"${cue}\"`;\n\n return (\n <div className={style.footer}>\n <CopyTag copyValue={loadById}>{loadById}</CopyTag>\n <CopyTag copyValue={loadByCue}>{loadByCue}</CopyTag>\n </div>\n );\n}\n","import { memo, PropsWithChildren } from 'react';\n\nimport * as Editor from '../../../common/components/editor-utils/EditorUtils';\nimport { deviceAlt, deviceMod } from '../../../common/utils/deviceUtils';\n\nimport style from './EventEditorEmpty.module.scss';\n\nexport default memo(EventEditorEmpty);\n\nfunction EventEditorEmpty() {\n return (\n <div className={style.entryEditor} data-testid='editor-container'>\n <div className={style.shortcutSection}>\n <Editor.Title className={style.prompt}>Rundown shortcuts</Editor.Title>\n <table className={style.shortcuts}>\n <tbody>\n <tr>\n <td>Find in rundown</td>\n <td>\n <Kbd>{deviceMod}</Kbd>\n <AuxKey>+</AuxKey>\n <Kbd>F</Kbd>\n </td>\n </tr>\n <tr>\n <td>Open Settings</td>\n <td>\n <Kbd>{deviceMod}</Kbd>\n <AuxKey>+</AuxKey>\n <Kbd>,</Kbd>\n </td>\n </tr>\n <tr className={style.spacer} />\n <tr>\n <td>Select entry</td>\n <td>\n <Kbd>{deviceAlt}</Kbd>\n <AuxKey>+</AuxKey>\n <Kbd>↑</Kbd>\n <AuxKey>/</AuxKey>\n <Kbd>↓</Kbd>\n </td>\n </tr>\n <tr>\n <td>Select group</td>\n <td>\n <Kbd>{deviceAlt}</Kbd>\n <AuxKey>+</AuxKey>\n <Kbd>Shift</Kbd>\n <AuxKey>+</AuxKey>\n <Kbd>↑</Kbd>\n <AuxKey>/</AuxKey>\n <Kbd>↓</Kbd>\n </td>\n </tr>\n <tr>\n <td>Deselect entry</td>\n <td>\n <Kbd>Esc</Kbd>\n </td>\n </tr>\n <tr className={style.spacer} />\n <tr>\n <td>Reorder selected entry</td>\n <td>\n <Kbd>{deviceAlt}</Kbd>\n <AuxKey>+</AuxKey>\n <Kbd>{deviceMod}</Kbd>\n <AuxKey>+</AuxKey>\n <Kbd>↑</Kbd>\n <AuxKey>/</AuxKey>\n <Kbd>↓</Kbd>\n </td>\n </tr>\n <tr>\n <td>Copy selected entry</td>\n <td>\n <Kbd>{deviceMod}</Kbd>\n <AuxKey>+</AuxKey>\n <Kbd>C</Kbd>\n </td>\n </tr>\n <tr>\n <td>Paste above</td>\n <td>\n <Kbd>{deviceMod}</Kbd>\n <AuxKey>+</AuxKey>\n <Kbd>Shift</Kbd>\n <AuxKey>+</AuxKey>\n <Kbd>V</Kbd>\n </td>\n </tr>\n <tr>\n <td>Paste below</td>\n <td>\n <Kbd>{deviceMod}</Kbd>\n <AuxKey>+</AuxKey>\n <Kbd>V</Kbd>\n </td>\n </tr>\n <tr>\n <td>Delete selected entry</td>\n <td>\n <Kbd>{deviceMod}</Kbd>\n <AuxKey>+</AuxKey>\n <Kbd>Backspace</Kbd>\n </td>\n </tr>\n <tr className={style.spacer} />\n <tr>\n <td>Add event below</td>\n <td>\n <Kbd>{deviceAlt}</Kbd>\n <AuxKey>+</AuxKey>\n <Kbd>E</Kbd>\n </td>\n </tr>\n <tr>\n <td>Add event above</td>\n <td>\n <Kbd>{deviceAlt}</Kbd>\n <AuxKey>+</AuxKey>\n <Kbd>Shift</Kbd>\n <AuxKey>+</AuxKey>\n <Kbd>E</Kbd>\n </td>\n </tr>\n <tr>\n <td>Add group below</td>\n <td>\n <Kbd>{deviceAlt}</Kbd>\n <AuxKey>+</AuxKey>\n <Kbd>G</Kbd>\n </td>\n </tr>\n <tr>\n <td>Add group above</td>\n <td>\n <Kbd>{deviceAlt}</Kbd>\n <AuxKey>+</AuxKey>\n <Kbd>Shift</Kbd>\n <AuxKey>+</AuxKey>\n <Kbd>M</Kbd>\n </td>\n </tr>\n <tr>\n <td>Add milestone below</td>\n <td>\n <Kbd>{deviceAlt}</Kbd>\n <AuxKey>+</AuxKey>\n <Kbd>G</Kbd>\n </td>\n </tr>\n <tr>\n <td>Add milestone above</td>\n <td>\n <Kbd>{deviceAlt}</Kbd>\n <AuxKey>+</AuxKey>\n <Kbd>Shift</Kbd>\n <AuxKey>+</AuxKey>\n <Kbd>M</Kbd>\n </td>\n </tr>\n <tr>\n <td>Add delay below</td>\n <td>\n <Kbd>{deviceAlt}</Kbd>\n <AuxKey>+</AuxKey>\n <Kbd>D</Kbd>\n </td>\n </tr>\n <tr>\n <td>Add delay above</td>\n <td>\n <Kbd>{deviceAlt}</Kbd>\n <AuxKey>+</AuxKey>\n <Kbd>Shift</Kbd>\n <AuxKey>+</AuxKey>\n <Kbd>D</Kbd>\n </td>\n </tr>\n </tbody>\n </table>\n </div>\n </div>\n );\n}\n\nfunction AuxKey({ children }: PropsWithChildren) {\n return <span className={style.divider}>{children}</span>;\n}\n\nfunction Kbd({ children }: PropsWithChildren) {\n return <span className={style.kbd}>{children}</span>;\n}\n","import { useEffect, useState } from 'react';\nimport {\n isOntimeDelay,\n isOntimeEvent,\n isOntimeGroup,\n isOntimeMilestone,\n OntimeEvent,\n OntimeGroup,\n OntimeMilestone,\n} from 'ontime-types';\n\nimport useRundown from '../../../common/hooks-query/useRundown';\nimport { useEventSelection } from '../useEventSelection';\n\nimport EventEditorFooter from './composite/EventEditorFooter';\nimport EventEditor from './EventEditor';\nimport EventEditorEmpty from './EventEditorEmpty';\nimport GroupEditor from './GroupEditor';\nimport MilestoneEditor from './MilestoneEditor';\n\nimport style from './EntryEditor.module.scss';\n\nexport default function RundownEntryEditor() {\n const selectedEvents = useEventSelection((state) => state.selectedEvents);\n const { data } = useRundown();\n\n const [entry, setEntry] = useState<OntimeEvent | OntimeGroup | OntimeMilestone | null>(null);\n\n useEffect(() => {\n if (data.order.length === 0) {\n setEntry(null);\n return;\n }\n\n const selectedEventId = Array.from(selectedEvents).at(0);\n if (!selectedEventId) {\n setEntry(null);\n return;\n }\n const event = data.entries[selectedEventId];\n\n if (event && !isOntimeDelay(event)) {\n setEntry(event);\n } else {\n setEntry(null);\n }\n }, [data.order, data.entries, selectedEvents]);\n\n if (!entry) {\n return <EventEditorEmpty />;\n }\n\n if (isOntimeEvent(entry)) {\n return (\n <div className={style.rundownEditor} data-testid='editor-container'>\n <EventEditor event={entry} />\n <EventEditorFooter id={entry.id} cue={entry.cue} />\n </div>\n );\n }\n\n if (isOntimeMilestone(entry)) {\n return (\n <div className={style.rundownEditor} data-testid='editor-container'>\n <MilestoneEditor milestone={entry} />\n </div>\n );\n }\n\n if (isOntimeGroup(entry)) {\n return (\n <div className={style.rundownEditor} data-testid='editor-container'>\n <GroupEditor group={entry} />\n </div>\n );\n }\n\n return null;\n}\n","import { ChangeEvent, useCallback, useEffect, useRef, useState } from 'react';\nimport { useSessionStorage } from '@mantine/hooks';\nimport { EntryId, isOntimeEvent, isOntimeGroup, isOntimeMilestone, MaybeString, SupportedEntry } from 'ontime-types';\n\nimport { useFlatRundown } from '../../../common/hooks-query/useRundown';\nimport { useEventSelection } from '../../../features/rundown/useEventSelection';\n\nconst maxResults = 12;\n\ntype FilterableGroup = {\n type: SupportedEntry.Group;\n id: EntryId;\n index: number;\n title: string;\n colour: string;\n};\n\ntype FilterableEvent = {\n type: SupportedEntry.Event;\n id: EntryId;\n index: number;\n eventIndex: number;\n title: string;\n cue: string;\n colour: string;\n parent: MaybeString;\n};\n\ntype FilterableMilestone = {\n type: SupportedEntry.Milestone;\n id: EntryId;\n index: number;\n title: string;\n cue: string;\n colour: string;\n parent: MaybeString;\n};\n\ntype FilterableEntry = FilterableGroup | FilterableEvent | FilterableMilestone;\n\nexport default function useFinder() {\n const { data, rundownId } = useFlatRundown();\n const [results, setResults] = useState<FilterableEntry[]>([]);\n const [error, setError] = useState<MaybeString>(null);\n const lastSearchString = useRef('');\n\n const setSelectedEvents = useEventSelection((state) => state.setSelectedEvents);\n\n const [collapsedGroups, setCollapsedGroups] = useSessionStorage<EntryId[]>({\n // we ensure that this is unique to the rundown\n key: `rundown.${rundownId}-editor-collapsed-groups`,\n defaultValue: [],\n });\n\n /** Filters the rundown to a given evaluation */\n const find = useCallback(\n (event: ChangeEvent<HTMLInputElement>) => {\n if (!data || data.length === 0) {\n setError('No data');\n return;\n }\n setError(null);\n\n if (event.target.value === '') {\n setResults([]);\n return;\n }\n\n const searchValue = event.target.value.toLowerCase();\n lastSearchString.current = searchValue;\n\n if (searchValue.startsWith('index ')) {\n const searchString = searchValue.slice('index '.length).trim();\n const { results, error } = searchByIndex(searchString);\n setResults(results);\n setError(error);\n return;\n }\n\n if (searchValue.startsWith('cue ')) {\n const searchString = searchValue.slice('cue '.length).trim();\n const { results, error } = searchByCue(searchString);\n setResults(results);\n setError(error);\n return;\n }\n\n const searchString = searchValue.startsWith('title ') ? searchValue.slice('title '.length).trim() : searchValue;\n const { results, error } = searchByTitle(searchString);\n setResults(results);\n setError(error);\n\n /** Returns a single item with a matching index */\n function searchByIndex(searchString: string) {\n const searchIndex = Number(searchString);\n if (isNaN(searchIndex) || searchIndex < 1) {\n return { results: [], error: 'Invalid index' };\n }\n\n if (searchIndex > data.length) {\n return { results: [], error: null };\n }\n\n // indexes exposed to the UI are 1-based\n let eventIndex = 1;\n const results: FilterableEvent[] = [];\n for (let i = 0; i < data.length; i++) {\n const event = data[i];\n if (isOntimeEvent(event)) {\n if (eventIndex === searchIndex) {\n results.push({\n type: SupportedEntry.Event,\n id: event.id,\n index: i,\n eventIndex,\n title: event.title,\n cue: event.cue,\n colour: event.colour,\n parent: event.parent,\n } satisfies FilterableEvent);\n break;\n }\n eventIndex++;\n }\n }\n\n return { results, error: null };\n }\n\n /** Returns maxResults of OntimeEvents that match the cue field */\n function searchByCue(searchString: string) {\n // indexes exposed to the UI are 1-based\n let eventIndex = 1;\n // limit amount of results we show\n let remaining = maxResults;\n const results: FilterableEvent[] = [];\n\n for (let i = 0; i < data.length; i++) {\n if (remaining <= 0) {\n break;\n }\n const event = data[i];\n if (isOntimeEvent(event)) {\n if (event.cue.toLowerCase().includes(searchString)) {\n remaining--;\n results.push({\n type: SupportedEntry.Event,\n id: event.id,\n index: i,\n eventIndex,\n title: event.title,\n cue: event.cue,\n colour: event.colour,\n parent: event.parent,\n } satisfies FilterableEvent);\n }\n eventIndex++;\n }\n }\n return { results, error: null };\n }\n\n /** Returns maxResults of OntimeEvents that match the title field*/\n function searchByTitle(searchString: string) {\n // indexes exposed to the UI are 1-based\n let eventIndex = 1;\n // limit amount of results we show\n let remaining = maxResults;\n const results: FilterableEntry[] = [];\n\n for (let i = 0; i < data.length; i++) {\n if (remaining <= 0) {\n break;\n }\n\n const entry = data[i];\n if (isOntimeEvent(entry)) {\n if (entry.title.toLowerCase().includes(searchString)) {\n remaining--;\n results.push({\n type: SupportedEntry.Event,\n id: entry.id,\n index: i,\n eventIndex,\n title: entry.title,\n cue: entry.cue,\n colour: entry.colour,\n parent: entry.parent,\n } satisfies FilterableEvent);\n }\n eventIndex++;\n } else if (isOntimeGroup(entry)) {\n if (entry.title.toLowerCase().includes(searchString)) {\n remaining--;\n results.push({\n type: SupportedEntry.Group,\n id: entry.id,\n index: i,\n title: entry.title,\n colour: entry.colour,\n } satisfies FilterableGroup);\n }\n } else if (isOntimeMilestone(entry)) {\n if (entry.title.toLowerCase().includes(searchString)) {\n remaining--;\n results.push({\n type: SupportedEntry.Milestone,\n id: entry.id,\n index: i,\n title: entry.title,\n cue: entry.cue,\n colour: entry.colour,\n parent: entry.parent,\n } satisfies FilterableMilestone);\n }\n }\n }\n return { results, error: null };\n }\n },\n [data],\n );\n\n const select = useCallback(\n (selectedEvent: FilterableEntry) => {\n // First expand the parent group if this is an event inside a group\n if ('parent' in selectedEvent && selectedEvent.parent !== null) {\n // Try direct state update instead of using callback\n const currentGroups = [...new Set(collapsedGroups)];\n const newGroups = currentGroups.filter((id) => id !== selectedEvent.parent);\n // Force a direct update\n setCollapsedGroups(newGroups);\n }\n\n // Then select the event\n setSelectedEvents({ id: selectedEvent.id, index: selectedEvent.index, selectMode: 'click' });\n },\n [collapsedGroups, setCollapsedGroups, setSelectedEvents],\n );\n\n /** clear results when source data changes */\n useEffect(() => {\n setResults([]);\n setError(null);\n // fake a submit event to re-run the search\n if (lastSearchString.current) {\n find({ target: { value: lastSearchString.current } } as ChangeEvent<HTMLInputElement>);\n }\n }, [data, find]);\n\n return { find, select, results, error };\n}\n","import { KeyboardEvent, useState } from 'react';\nimport { useDebouncedCallback } from '@mantine/hooks';\nimport { SupportedEntry } from 'ontime-types';\n\nimport Input from '../../../common/components/input/input/Input';\nimport Modal from '../../../common/components/modal/Modal';\n\nimport useFinder from './useFinder';\n\nimport style from './Finder.module.scss';\n\ninterface FinderProps {\n isOpen: boolean;\n onClose: () => void;\n}\n\nexport default function Finder({ isOpen, onClose }: FinderProps) {\n const { find, select, results, error } = useFinder();\n const [selected, setSelected] = useState(0);\n\n const debouncedFind = useDebouncedCallback(find, 100);\n\n const navigate = (event: KeyboardEvent<HTMLDivElement>) => {\n // all operations need results\n if (results.length === 0) {\n return;\n }\n if (event.key === 'ArrowDown') {\n setSelected((prev) => (prev + 1) % results.length);\n }\n if (event.key === 'ArrowUp') {\n setSelected((prev) => (prev - 1 + results.length) % results.length);\n }\n if (event.key === 'Enter') {\n event.preventDefault();\n event.stopPropagation();\n submit();\n }\n };\n\n const submit = () => {\n const selectedEvent = results[selected];\n select(selectedEvent);\n onClose();\n };\n\n const handleMouseMoveEvent = (event: React.MouseEvent<HTMLUListElement>) => {\n const target = event.target as HTMLElement;\n const li = target.closest('li');\n if (li) {\n const index = Number(li.dataset.index);\n if (!isNaN(index)) {\n setSelected(index);\n }\n }\n };\n\n return (\n <Modal\n title=''\n isOpen={isOpen}\n onClose={onClose}\n showBackdrop\n bodyElements={\n <div onKeyDown={navigate}>\n <Input height='large' fluid onChange={debouncedFind} placeholder='Search...' />\n <ul className={style.scrollContainer} onMouseMove={handleMouseMoveEvent}>\n {error && <li className={style.error}>{error}</li>}\n {results.length === 0 && <li className={style.empty}>No results</li>}\n {results.length > 0 &&\n results.map((entry, index) => {\n const isSelected = selected === index;\n const displayIndex = entry.type === SupportedEntry.Event ? entry.eventIndex : '-';\n const displayCue = 'cue' in entry ? entry.cue : '';\n\n return (\n <li\n key={entry.id}\n className={style.entry}\n data-selected={isSelected}\n data-index={index}\n onClick={submit}\n >\n <div className={style.data}>\n <div className={style.index} style={{ '--color': entry.colour }}>\n {displayIndex}\n </div>\n <div className={style.cue}>{displayCue}</div>\n <div className={style.title}>{entry.title}</div>\n </div>\n {isSelected && <span>Go ⏎</span>}\n </li>\n );\n })}\n </ul>\n </div>\n }\n footerElements={\n <div className={style.footer}>\n Use the keywords <span className={style.em}>cue</span>, <span className={style.em}>index</span> or\n <span className={style.em}>title</span> to filter search.\n </div>\n }\n />\n );\n}\n","import { memo } from 'react';\nimport { useDisclosure, useHotkeys } from '@mantine/hooks';\n\nimport Finder from '../../../views/editor/finder/Finder';\n\nexport default memo(FinderPlacement);\n\nfunction FinderPlacement() {\n const [isOpen, handler] = useDisclosure();\n\n useHotkeys([\n ['mod + f', handler.toggle],\n ['Escape', handler.close],\n ]);\n\n if (isOpen) {\n return <Finder isOpen={isOpen} onClose={handler.close} />;\n }\n\n return null;\n}\n","import type { PropsWithChildren } from 'react';\nimport { create } from 'zustand';\n\nimport { DropdownMenuOption, PositionedDropdownMenu } from '../../../common/components/dropdown-menu/DropdownMenu';\n\ntype Position = {\n x: number;\n y: number;\n};\n\ntype ContextMenuStore = {\n position: Position;\n options: DropdownMenuOption[];\n isOpen: boolean;\n setContextMenu: (position: Position, options: DropdownMenuOption[]) => void;\n setIsOpen: (newIsOpen: boolean) => void;\n};\n\nexport const useContextMenuStore = create<ContextMenuStore>((set) => ({\n position: { x: 0, y: 0 },\n options: [],\n isOpen: false,\n setContextMenu: (position, options) => set(() => ({ position, options, isOpen: true })),\n setIsOpen: (newIsOpen) => set(() => ({ isOpen: newIsOpen })),\n}));\n\nexport function RundownContextMenu({ children }: PropsWithChildren) {\n const { position, options, isOpen, setIsOpen } = useContextMenuStore();\n\n const onClose = () => {\n return setIsOpen(false);\n };\n\n if (!isOpen) {\n return children;\n }\n\n return (\n <>\n {children}\n <PositionedDropdownMenu isOpen position={position} onClose={onClose} items={options} />\n </>\n );\n}\n","import { memo, useCallback } from 'react';\nimport { IoTrash } from 'react-icons/io5';\nimport { Toolbar } from '@base-ui-components/react/toolbar';\nimport { useDisclosure, useSessionStorage } from '@mantine/hooks';\n\nimport Button from '../../../common/components/buttons/Button';\nimport Dialog from '../../../common/components/dialog/Dialog';\nimport { useEntryActions } from '../../../common/hooks/useEntryAction';\nimport { AppMode, sessionKeys } from '../../../ontimeConfig';\nimport { useEventSelection } from '../useEventSelection';\n\nimport style from './RundownHeader.module.scss';\n\nexport default memo(RundownMenu);\nfunction RundownMenu() {\n const [isOpen, handlers] = useDisclosure();\n\n const clearSelectedEvents = useEventSelection((state) => state.clearSelectedEvents);\n const [editorMode] = useSessionStorage({\n key: sessionKeys.editorMode,\n defaultValue: AppMode.Edit,\n });\n const { deleteAllEntries } = useEntryActions();\n\n const deleteAll = useCallback(() => {\n deleteAllEntries();\n clearSelectedEvents();\n handlers.close();\n }, [clearSelectedEvents, deleteAllEntries, handlers]);\n\n return (\n <>\n <Toolbar.Button\n render={<Button variant='subtle-destructive' />}\n onClick={handlers.open}\n disabled={editorMode === AppMode.Run}\n className={style.apart}\n >\n <IoTrash />\n Clear all\n </Toolbar.Button>\n <Dialog\n isOpen={isOpen}\n onClose={handlers.close}\n title='Clear rundown'\n showBackdrop\n showCloseButton\n bodyElements={\n <>\n You will lose all data in your rundown. <br /> Are you sure?\n </>\n }\n footerElements={\n <>\n <Button variant='ghosted-white' size='large' onClick={handlers.close}>\n Cancel\n </Button>\n <Button variant='destructive' size='large' onClick={deleteAll}>\n Delete all\n </Button>\n </>\n }\n />\n </>\n );\n}\n","import { memo } from 'react';\nimport { Toggle } from '@base-ui-components/react/toggle';\nimport { ToggleGroup } from '@base-ui-components/react/toggle-group';\nimport { Toolbar } from '@base-ui-components/react/toolbar';\nimport { useSessionStorage } from '@mantine/hooks';\nimport { OffsetMode } from 'ontime-types';\n\nimport * as Editor from '../../../common/components/editor-utils/EditorUtils';\nimport { setOffsetMode, useOffsetMode } from '../../../common/hooks/useSocket';\nimport { AppMode, sessionKeys } from '../../../ontimeConfig';\n\nimport RundownMenu from './RundownMenu';\n\nimport style from './RundownHeader.module.scss';\n\nexport default memo(RundownHeader);\nfunction RundownHeader() {\n const [editorMode, setEditorMode] = useSessionStorage({ key: sessionKeys.editorMode, defaultValue: AppMode.Edit });\n\n const { offsetMode } = useOffsetMode();\n\n const toggleAppMode = (mode: AppMode[]) => {\n // we need to stop user from deselecting a mode\n const newValue = mode.at(0);\n if (!newValue) return;\n setEditorMode(newValue);\n };\n\n const toggleOffsetMode = (mode: OffsetMode[]) => {\n // we need to stop user from deselecting a mode\n const newValue = mode.at(0);\n if (!newValue) return;\n setOffsetMode(newValue);\n };\n\n return (\n <Toolbar.Root className={style.header}>\n <ToggleGroup value={[editorMode]} onValueChange={toggleAppMode} className={style.group}>\n <Toolbar.Button render={<Toggle />} value={AppMode.Run} className={style.radioButton}>\n Run\n </Toolbar.Button>\n <Toolbar.Button render={<Toggle />} value={AppMode.Edit} className={style.radioButton}>\n Edit\n </Toolbar.Button>\n </ToggleGroup>\n\n <Editor.Separator className={style.separator} />\n\n <ToggleGroup value={[offsetMode]} onValueChange={toggleOffsetMode} className={style.group}>\n <Toolbar.Button render={<Toggle />} value={OffsetMode.Absolute} className={style.radioButton}>\n Absolute\n </Toolbar.Button>\n <Toolbar.Button render={<Toggle />} value={OffsetMode.Relative} className={style.radioButton}>\n Relative\n </Toolbar.Button>\n </ToggleGroup>\n\n <RundownMenu />\n </Toolbar.Root>\n );\n}\n","import { memo } from 'react';\nimport { Toggle } from '@base-ui-components/react/toggle';\nimport { ToggleGroup } from '@base-ui-components/react/toggle-group';\nimport { Toolbar } from '@base-ui-components/react/toolbar';\nimport { useSessionStorage } from '@mantine/hooks';\nimport { OffsetMode } from 'ontime-types';\n\nimport * as Editor from '../../../common/components/editor-utils/EditorUtils';\nimport { setOffsetMode, useOffsetMode } from '../../../common/hooks/useSocket';\nimport { AppMode, sessionKeys } from '../../../ontimeConfig';\n\nimport style from './RundownHeader.module.scss';\n\nexport default memo(RundownHeader);\nfunction RundownHeader() {\n const [editorMode, setEditorMode] = useSessionStorage<AppMode>({\n key: sessionKeys.editorMode,\n defaultValue: AppMode.Edit,\n });\n\n const { offsetMode } = useOffsetMode();\n\n const toggleAppMode = (mode: AppMode[]) => {\n // we need to stop user from deselecting a mode\n const newValue = mode.at(0);\n if (!newValue) return;\n setEditorMode(newValue);\n };\n\n const toggleOffsetMode = (mode: OffsetMode[]) => {\n // we need to stop user from deselecting a mode\n const newValue = mode.at(0);\n if (!newValue) return;\n setOffsetMode(newValue);\n };\n\n return (\n <Toolbar.Root className={style.header}>\n <ToggleGroup value={[editorMode]} onValueChange={toggleAppMode} className={style.group}>\n <Toolbar.Button render={<Toggle />} value={AppMode.Run} className={style.radioButton}>\n Run\n </Toolbar.Button>\n <Toolbar.Button render={<Toggle />} value={AppMode.Edit} className={style.radioButton}>\n Edit\n </Toolbar.Button>\n </ToggleGroup>\n\n <Editor.Separator className={style.separator} />\n\n <ToggleGroup value={[offsetMode]} onValueChange={toggleOffsetMode} className={style.group}>\n <Toolbar.Button render={<Toggle />} value={OffsetMode.Absolute} className={style.radioButton}>\n Absolute\n </Toolbar.Button>\n <Toolbar.Button render={<Toggle />} value={OffsetMode.Relative} className={style.radioButton}>\n Relative\n </Toolbar.Button>\n </ToggleGroup>\n </Toolbar.Root>\n );\n}\n","import { create } from 'zustand';\n\ntype EntryCopyStore = {\n entryCopyId: string | null;\n setEntryCopyId: (eventId: string | null) => void;\n};\n\nexport const useEntryCopy = create<EntryCopyStore>()((set) => ({\n entryCopyId: null,\n setEntryCopyId: (entryCopyId: string | null) => set({ entryCopyId }),\n}));\n","import { OntimeEvent, SupportedEntry } from 'ontime-types';\n\n/**\n * @description Creates a safe duplicate of an event\n * @param {OntimeEvent} event\n * @param {string} [after]\n * @return {OntimeEvent} clean event\n */\ntype ClonedEvent = Omit<OntimeEvent, 'id' | 'cue'>;\nexport const cloneEvent = (event: OntimeEvent): ClonedEvent => {\n return {\n type: SupportedEntry.Event,\n flag: event.flag,\n title: event.title,\n note: event.note,\n timeStart: event.timeStart,\n duration: event.duration,\n timeEnd: event.timeEnd,\n timerType: event.timerType,\n timeStrategy: event.timeStrategy,\n countToEnd: event.countToEnd,\n linkStart: event.linkStart,\n endAction: event.endAction,\n skip: event.skip,\n colour: event.colour,\n parent: event.parent,\n revision: 0,\n delay: event.delay, // the events will be collocated, so having the same metadata is a good start\n dayOffset: event.dayOffset,\n gap: 0,\n timeWarning: event.timeWarning,\n timeDanger: event.timeDanger,\n triggers: structuredClone(event.triggers),\n custom: structuredClone(event.custom),\n };\n};\n","import { memo } from 'react';\nimport { IoAdd } from 'react-icons/io5';\nimport { Toolbar } from '@base-ui-components/react/toolbar';\nimport { MaybeString, SupportedEntry } from 'ontime-types';\n\nimport Button from '../../../../common/components/buttons/Button';\nimport { useEntryActions } from '../../../../common/hooks/useEntryAction';\nimport { cx } from '../../../../common/utils/styleUtils';\n\nimport style from './QuickAddButtons.module.scss';\n\ninterface QuickAddButtonsProps {\n previousEventId: MaybeString;\n parentGroup: MaybeString;\n backgroundColor?: string;\n}\n\nexport default memo(QuickAddButtons);\nfunction QuickAddButtons({ previousEventId, parentGroup, backgroundColor }: QuickAddButtonsProps) {\n const { addEntry } = useEntryActions();\n\n const addEvent = () => {\n addEntry(\n {\n type: SupportedEntry.Event,\n parent: parentGroup,\n },\n {\n after: previousEventId,\n lastEventId: previousEventId,\n },\n );\n };\n\n const addDelay = () => {\n addEntry(\n { type: SupportedEntry.Delay, parent: parentGroup },\n {\n lastEventId: previousEventId,\n after: previousEventId,\n },\n );\n };\n\n const addMilestone = () => {\n addEntry(\n { type: SupportedEntry.Milestone, parent: parentGroup },\n {\n lastEventId: previousEventId,\n after: previousEventId,\n },\n );\n };\n\n const addGroup = () => {\n if (parentGroup !== null) {\n return;\n }\n addEntry(\n { type: SupportedEntry.Group },\n {\n lastEventId: previousEventId,\n after: previousEventId,\n },\n );\n };\n\n /**\n * If the colour is empty string ''\n * ie: we are inside a group, but there is no defined colour\n * we default to $gray-500 #9d9d9d\n */\n const groupColour = backgroundColor === '' ? '#9d9d9d' : backgroundColor;\n\n return (\n <Toolbar.Root\n className={cx([style.quickAdd, Boolean(parentGroup) && style.indent])}\n style={groupColour ? { '--user-bg': groupColour } : {}}\n data-testid='quick-add-buttons'\n >\n <Toolbar.Button render={<Button size='small' />} onClick={addEvent}>\n <IoAdd />\n Event\n </Toolbar.Button>\n\n <Toolbar.Button render={<Button size='small' />} onClick={addDelay}>\n <IoAdd />\n Delay\n </Toolbar.Button>\n\n <Toolbar.Button render={<Button size='small' />} onClick={addMilestone}>\n <IoAdd />\n Milestone\n </Toolbar.Button>\n\n {parentGroup === null && (\n <Toolbar.Button render={<Button size='small' />} onClick={addGroup}>\n <IoAdd />\n Group\n </Toolbar.Button>\n )}\n </Toolbar.Root>\n );\n}\n","import { memo } from 'react';\nimport { IoAdd } from 'react-icons/io5';\nimport { MaybeString, SupportedEntry } from 'ontime-types';\n\nimport IconButton from '../../../../common/components/buttons/IconButton';\nimport { DropdownMenu } from '../../../../common/components/dropdown-menu/DropdownMenu';\nimport { useEntryActions } from '../../../../common/hooks/useEntryAction';\n\nimport style from './QuickAddInline.module.scss';\n\ninterface QuickAddInlineProps {\n referenceEntryId: MaybeString;\n parentGroup: MaybeString;\n placement: 'before' | 'after';\n}\n\nexport default memo(QuickAddInline);\nfunction QuickAddInline({ referenceEntryId, parentGroup, placement }: QuickAddInlineProps) {\n const { addEntry } = useEntryActions();\n\n const handleAddEntry = (type: SupportedEntry) => {\n if (placement === 'before') {\n addEntry(\n { type, parent: type !== SupportedEntry.Group ? parentGroup : null },\n {\n before: referenceEntryId,\n },\n );\n } else {\n addEntry(\n { type, parent: type !== SupportedEntry.Group ? parentGroup : null },\n {\n lastEventId: referenceEntryId,\n after: referenceEntryId,\n },\n );\n }\n };\n\n return (\n <div className={style.quickAdd} data-testid='quick-add-inline'>\n <DropdownMenu\n items={[\n { type: 'item', icon: IoAdd, label: 'Add Event', onClick: () => handleAddEntry(SupportedEntry.Event) },\n { type: 'item', icon: IoAdd, label: 'Add Delay', onClick: () => handleAddEntry(SupportedEntry.Delay) },\n {\n type: 'item',\n icon: IoAdd,\n label: 'Add Milestone',\n onClick: () => handleAddEntry(SupportedEntry.Milestone),\n },\n {\n type: 'item',\n icon: IoAdd,\n label: 'Add Group',\n onClick: () => handleAddEntry(SupportedEntry.Group),\n disabled: parentGroup !== null,\n },\n ]}\n render={<IconButton size='small' variant='primary' className={style.addButton} />}\n >\n <IoAdd />\n </DropdownMenu>\n </div>\n );\n}\n","import { MouseEvent } from 'react';\n\nimport { useContextMenuStore } from '../../features/rundown/rundown-context-menu/RundownContextMenu';\nimport { DropdownMenuOption } from '../components/dropdown-menu/DropdownMenu';\n\nexport const useContextMenu = <T extends HTMLElement>(options: DropdownMenuOption[]) => {\n const setContextMenu = useContextMenuStore((state) => state.setContextMenu);\n\n const localCreateContextMenu = (contextMenuEvent: MouseEvent<T, globalThis.MouseEvent>) => {\n // prevent browser default context menu from showing up\n contextMenuEvent.preventDefault();\n\n const { pageX, pageY } = contextMenuEvent;\n return setContextMenu({ x: pageX, y: pageY }, options);\n };\n\n return [localCreateContextMenu];\n};\n","import { useCallback, useRef } from 'react';\n\nimport Input from '../../../common/components/input/input/Input';\nimport useReactiveTextInput from '../../../common/components/input/text-input/useReactiveTextInput';\nimport { useEntryActions } from '../../../common/hooks/useEntryAction';\nimport { cx } from '../../../common/utils/styleUtils';\n\nimport style from './TitleEditor.module.scss';\n\ninterface TitleEditorProps {\n title: string;\n entryId: string;\n placeholder: string;\n className?: string;\n}\n\nexport default function TitleEditor({ title, entryId, placeholder, className }: TitleEditorProps) {\n const { updateEntry } = useEntryActions();\n const ref = useRef<HTMLInputElement | null>(null);\n const submitCallback = useCallback(\n (text: string) => {\n if (text === title) {\n return;\n }\n\n const cleanVal = text.trim();\n updateEntry({ id: entryId, title: cleanVal });\n },\n [title, updateEntry, entryId],\n );\n\n const { value, onChange, onBlur, onKeyDown } = useReactiveTextInput(title, submitCallback, ref, {\n submitOnEnter: true,\n });\n\n const classes = cx([className, style.eventTitle, !value ? style.noTitle : null]);\n\n return (\n <Input\n data-testid='entry__title'\n variant='ghosted'\n fluid\n ref={ref}\n value={value}\n className={classes}\n placeholder={placeholder}\n onChange={onChange}\n onBlur={onBlur}\n onKeyDown={onKeyDown}\n />\n );\n}\n","import { MouseEvent, useRef } from 'react';\nimport {\n IoChevronDown,\n IoChevronUp,\n IoDuplicateOutline,\n IoFolderOpenOutline,\n IoReorderTwo,\n IoTrash,\n} from 'react-icons/io5';\nimport { useSortable } from '@dnd-kit/sortable';\nimport { CSS } from '@dnd-kit/utilities';\nimport { EntryId, OntimeGroup } from 'ontime-types';\nimport { MILLIS_PER_MINUTE } from 'ontime-utils';\n\nimport IconButton from '../../../common/components/buttons/IconButton';\nimport { useContextMenu } from '../../../common/hooks/useContextMenu';\nimport { useEntryActions } from '../../../common/hooks/useEntryAction';\nimport { getOffsetState } from '../../../common/utils/offset';\nimport { cx, getAccessibleColour } from '../../../common/utils/styleUtils';\nimport { formatDuration, formatTime } from '../../../common/utils/time';\nimport TitleEditor from '../common/TitleEditor';\nimport { canDrop } from '../rundown.utils';\nimport { useEventSelection } from '../useEventSelection';\n\nimport style from './RundownGroup.module.scss';\n\ninterface RundownGroupProps {\n data: OntimeGroup;\n hasCursor: boolean;\n collapsed: boolean;\n onCollapse: (collapsed: boolean, groupId: EntryId) => void;\n}\n\n//TODO: the group should maybe include a multiple day indicator\nexport default function RundownGroup({ data, hasCursor, collapsed, onCollapse }: RundownGroupProps) {\n const handleRef = useRef<null | HTMLSpanElement>(null);\n const { clone, ungroup, deleteEntry } = useEntryActions();\n const { selectedEvents, setSingleEntrySelection } = useEventSelection();\n\n const [onContextMenu] = useContextMenu<HTMLDivElement>([\n {\n type: 'item',\n label: 'Clone Group',\n icon: IoDuplicateOutline,\n onClick: () => clone(data.id),\n },\n {\n type: 'item',\n label: 'Ungroup',\n icon: IoFolderOpenOutline,\n onClick: () => ungroup(data.id),\n disabled: data.entries.length === 0,\n },\n { type: 'divider' },\n {\n type: 'item',\n label: 'Delete Group',\n icon: IoTrash,\n onClick: () => deleteEntry([data.id]),\n },\n ]);\n\n const {\n attributes: dragAttributes,\n listeners: dragListeners,\n setNodeRef,\n transform,\n transition,\n isDragging,\n isOver,\n over,\n } = useSortable({\n id: data.id,\n data: {\n type: 'group',\n },\n animateLayoutChanges: () => false,\n });\n\n const handleFocusClick = (event: MouseEvent) => {\n event.stopPropagation();\n\n // event.button === 2 is a right-click\n // disable selection if the user selected events and right clicks\n // so the context menu shows up\n if (selectedEvents.size > 1 && event.button === 2) {\n return;\n }\n\n // UI indexes are 1 based\n setSingleEntrySelection({ id: data.id });\n };\n\n const binderColours = data.colour && getAccessibleColour(data.colour);\n const isValidDrop = isDragging && over?.id && canDrop(over.data.current?.type, over.data.current?.parent);\n\n const [planOffset, planOffsetLabel] = (() => {\n if (data.targetDuration === null) {\n return [null, null];\n }\n\n const offset = data.duration - data.targetDuration;\n if (offset === 0) {\n return [null, 'under'];\n }\n const absOffset = Math.abs(offset);\n return [\n `${offset < 0 ? '-' : '+'}${formatDuration(absOffset, absOffset > 2 * MILLIS_PER_MINUTE)}`,\n getOffsetState(offset),\n ];\n })();\n\n const dragStyle = {\n zIndex: isDragging ? 2 : 'inherit',\n transform: CSS.Translate.toString(transform),\n transition,\n cursor: isOver ? (isValidDrop ? 'grabbing' : 'no-drop') : 'inherit',\n };\n\n return (\n <div\n className={cx([style.group, hasCursor && style.hasCursor, !collapsed && style.expanded])}\n ref={setNodeRef}\n onClick={handleFocusClick}\n onContextMenu={onContextMenu}\n style={{\n ...dragStyle,\n '--user-bg': data.colour || '#929292',\n }}\n data-testid='rundown-group'\n >\n <div className={style.binder} style={{ ...binderColours }} tabIndex={-1}>\n <span\n className={cx([style.drag, isDragging && style.isDragging, isDragging && !isValidDrop && style.notAllowed])}\n ref={handleRef}\n {...dragAttributes}\n {...dragListeners}\n >\n <IoReorderTwo />\n </span>\n </div>\n <div className={style.header}>\n <div className={style.titleRow}>\n <TitleEditor title={data.title} entryId={data.id} placeholder='Group title' />\n <IconButton aria-label='Collapse' variant='subtle-white' onClick={() => onCollapse(!collapsed, data.id)}>\n {collapsed ? <IoChevronUp /> : <IoChevronDown />}\n </IconButton>\n </div>\n <div className={style.metaRow}>\n <div className={style.metaEntry}>\n <div>Start</div>\n <div>{formatTime(data.timeStart)}</div>\n </div>\n <div className={style.metaEntry}>\n <div>End</div>\n <div>{formatTime(data.timeEnd)}</div>\n </div>\n <div className={style.metaEntry}>\n <div>Duration</div>\n {planOffset === null ? (\n <div className={cx([planOffsetLabel !== null && style[planOffsetLabel]])}>\n {formatDuration(data.duration)}\n </div>\n ) : (\n <div>\n <span className={style.strike}>{formatDuration(data.duration)}</span>\n <span className={cx([planOffsetLabel !== null && style[planOffsetLabel]])}>{planOffset}</span>\n </div>\n )}\n </div>\n <div className={style.metaEntry}>\n <div>Entries</div>\n <div>{data.entries.length}</div>\n </div>\n </div>\n </div>\n </div>\n );\n}\n","import { useSortable } from '@dnd-kit/sortable';\nimport { CSS } from '@dnd-kit/utilities';\n\nimport style from './RundownGroupEnd.module.scss';\n\ninterface RundownGroupEndProps {\n id: string;\n colour?: string;\n}\n\nexport default function RundownGroupEnd({ id, colour }: RundownGroupEndProps) {\n const {\n attributes: dragAttributes,\n listeners: dragListeners,\n setNodeRef,\n transform,\n transition,\n } = useSortable({\n id,\n data: {\n type: 'end-group',\n },\n animateLayoutChanges: () => false,\n disabled: true, // we do not want to drag end groups\n });\n\n const dragStyle = {\n transform: CSS.Transform.toString(transform),\n transition,\n };\n\n return (\n <div\n className={style.groupEnd}\n ref={setNodeRef}\n {...dragAttributes}\n {...dragListeners}\n style={{\n ...dragStyle,\n ...(colour ? { '--user-bg': colour } : {}),\n }}\n tabIndex={-1}\n />\n );\n}\n","import { IoAdd } from 'react-icons/io5';\nimport { SupportedEntry } from 'ontime-types';\n\nimport Button from '../../common/components/buttons/Button';\nimport * as Editor from '../../common/components/editor-utils/EditorUtils';\nimport Empty from '../../common/components/state/Empty';\n\nimport style from './Empty.module.scss';\n\ninterface RundownEmptyProps {\n handleAddNew: (type: SupportedEntry) => void;\n}\n\nexport default function RundownEmpty(props: RundownEmptyProps) {\n const { handleAddNew } = props;\n\n return (\n <div className={style.empty}>\n <Empty injectedStyles={{ marginTop: '5vh', marginBottom: '3rem' }} />\n <div className={style.inline}>\n <Button onClick={() => handleAddNew(SupportedEntry.Event)} variant='primary' size='large'>\n <IoAdd />\n Create Event\n </Button>\n\n <Editor.Separator />\n\n <Button onClick={() => handleAddNew(SupportedEntry.Group)} variant='primary' size='large'>\n <IoAdd /> Create Group\n </Button>\n </div>\n </div>\n );\n}\n","import { Fragment, lazy, useCallback, useEffect, useRef, useState } from 'react';\nimport { TbFlagFilled } from 'react-icons/tb';\nimport {\n closestCenter,\n DndContext,\n DragEndEvent,\n DragOverEvent,\n DragStartEvent,\n PointerSensor,\n useSensor,\n useSensors,\n} from '@dnd-kit/core';\nimport { SortableContext, verticalListSortingStrategy } from '@dnd-kit/sortable';\nimport { useHotkeys, useSessionStorage } from '@mantine/hooks';\nimport {\n type EntryId,\n type MaybeString,\n type Rundown,\n isOntimeEvent,\n isOntimeGroup,\n OntimeEntry,\n Playback,\n SupportedEntry,\n} from 'ontime-types';\nimport {\n getFirstNormal,\n getLastNormal,\n getNextGroupNormal,\n getNextNormal,\n getPreviousGroupNormal,\n getPreviousNormal,\n reorderArray,\n} from 'ontime-utils';\n\nimport { useEntryActions } from '../../common/hooks/useEntryAction';\nimport useFollowComponent from '../../common/hooks/useFollowComponent';\nimport { useRundownEditor } from '../../common/hooks/useSocket';\nimport { useEntryCopy } from '../../common/stores/entryCopyStore';\nimport { cloneEvent } from '../../common/utils/clone';\nimport { lastMetadataKey, RundownMetadataObject } from '../../common/utils/rundownMetadata';\nimport { AppMode, sessionKeys } from '../../ontimeConfig';\n\nimport QuickAddButtons from './entry-editor/quick-add-buttons/QuickAddButtons';\nimport QuickAddInline from './entry-editor/quick-add-cursor/QuickAddInline';\nimport RundownGroup from './rundown-group/RundownGroup';\nimport RundownGroupEnd from './rundown-group/RundownGroupEnd';\nimport { canDrop, makeSortableList } from './rundown.utils';\nimport RundownEmpty from './RundownEmpty';\nimport { useEventSelection } from './useEventSelection';\n\nimport style from './Rundown.module.scss';\n\nconst RundownEntry = lazy(() => import('./RundownEntry'));\n\ninterface RundownProps {\n data: Rundown;\n rundownMetadata: RundownMetadataObject;\n}\n\nexport default function Rundown({ data, rundownMetadata }: RundownProps) {\n const { order, entries, id } = data;\n // we create a copy of the rundown with a data structured aligned with what dnd-kit needs\n const featureData = useRundownEditor();\n const [sortableData, setSortableData] = useState<EntryId[]>(() => makeSortableList(order, entries));\n const [metadata, setMetadata] = useState(rundownMetadata);\n const [collapsedGroups, setCollapsedGroups] = useSessionStorage<EntryId[]>({\n // we ensure that this is unique to the rundown\n key: `rundown.${id}-editor-collapsed-groups`,\n defaultValue: [],\n });\n\n const { addEntry, deleteEntry, move, reorderEntry } = useEntryActions();\n\n const { entryCopyId, setEntryCopyId } = useEntryCopy();\n\n // cursor\n const [editorMode] = useSessionStorage<AppMode>({\n key: sessionKeys.editorMode,\n defaultValue: AppMode.Edit,\n });\n const { clearSelectedEvents, setSelectedEvents, cursor } = useEventSelection();\n\n const cursorRef = useRef<HTMLDivElement | null>(null);\n const scrollRef = useRef<HTMLDivElement | null>(null);\n useFollowComponent({\n followRef: cursorRef,\n scrollRef,\n doFollow: true,\n followTrigger: editorMode === AppMode.Edit ? cursor : featureData?.selectedEventId,\n });\n\n // DND KIT\n const sensors = useSensors(useSensor(PointerSensor, { activationConstraint: { distance: 10 } }));\n\n const deleteAtCursor = useCallback(\n (cursor: string | null) => {\n if (!cursor) return;\n const { entry, index } = getPreviousNormal(entries, order, cursor);\n deleteEntry([cursor]);\n if (entry && index !== null) {\n setSelectedEvents({ id: entry.id, selectMode: 'click', index });\n }\n },\n [entries, order, deleteEntry, setSelectedEvents],\n );\n\n const insertCopyAtId = useCallback(\n (atId: string | null, copyId: string | null, above = false) => {\n const adjustedCursor = above ? getPreviousNormal(entries, order, atId ?? '').entry?.id ?? null : atId;\n if (copyId === null) {\n // we cant clone without selection\n return;\n }\n const cloneEntry = entries[copyId];\n if (cloneEntry?.type === SupportedEntry.Event) {\n //if we don't have a cursor add the new event on top\n const newEvent = cloneEvent(cloneEntry);\n addEntry(newEvent, { after: adjustedCursor ?? undefined });\n }\n },\n [addEntry, order, entries],\n );\n\n /**\n * Add a new item referring to an existing one\n */\n const insertAtId = useCallback(\n (patch: Partial<OntimeEntry> & { type: SupportedEntry }, id: MaybeString, above = false) => {\n addEntry(patch, {\n after: id && !above ? id : undefined,\n before: id && above ? id : undefined,\n lastEventId: !above && id ? id : undefined,\n });\n },\n [addEntry],\n );\n\n const selectGroup = useCallback(\n (cursor: string | null, direction: 'up' | 'down') => {\n if (order.length < 1) {\n return;\n }\n let newCursor = cursor;\n if (cursor === null) {\n // there is no cursor, we select the first or last depending on direction\n const selected = direction === 'up' ? getLastNormal(entries, order) : getFirstNormal(entries, order);\n\n if (isOntimeGroup(selected)) {\n setSelectedEvents({ id: selected.id, selectMode: 'click', index: direction === 'up' ? order.length : 0 });\n return;\n }\n newCursor = selected?.id ?? null;\n }\n\n if (newCursor === null) {\n return;\n }\n\n // otherwise we select the next or previous\n const selected =\n direction === 'up'\n ? getPreviousGroupNormal(entries, order, newCursor)\n : getNextGroupNormal(entries, order, newCursor);\n\n if (selected.entry !== null && selected.index !== null) {\n setSelectedEvents({ id: selected.entry.id, selectMode: 'click', index: selected.index });\n }\n },\n [order, entries, setSelectedEvents],\n );\n\n const selectEntry = useCallback(\n (cursor: string | null, direction: 'up' | 'down') => {\n if (order.length < 1) {\n return;\n }\n\n if (cursor === null) {\n // there is no cursor, we select the first or last depending on direction if it exists\n const selected = direction === 'up' ? getLastNormal(entries, order) : getFirstNormal(entries, order);\n if (selected !== null) {\n setSelectedEvents({ id: selected.id, selectMode: 'click', index: direction === 'up' ? order.length : 0 });\n }\n return;\n }\n\n // otherwise we select the next or previous\n const selected =\n direction === 'up' ? getPreviousNormal(entries, order, cursor) : getNextNormal(entries, order, cursor);\n\n if (selected.entry !== null && selected.index !== null) {\n setSelectedEvents({ id: selected.entry.id, selectMode: 'click', index: selected.index });\n }\n },\n [order, entries, setSelectedEvents],\n );\n\n /**\n * Checks whether a group is collapsed\n */\n const getIsCollapsed = useCallback(\n (groupId: EntryId): boolean => {\n return Boolean(collapsedGroups.find((id) => id === groupId));\n },\n [collapsedGroups],\n );\n\n /**\n * Handles logic for collapsing groups\n */\n const handleCollapseGroup = useCallback(\n (collapsed: boolean, groupId: EntryId) => {\n setCollapsedGroups((prev) => {\n const isCollapsed = getIsCollapsed(groupId);\n if (collapsed && !isCollapsed) {\n const newSet = new Set(prev).add(groupId);\n return [...newSet];\n }\n if (!collapsed && isCollapsed) {\n return [...prev].filter((id) => id !== groupId);\n }\n return prev;\n });\n },\n [getIsCollapsed, setCollapsedGroups],\n );\n\n const moveEntry = useCallback(\n async (cursor: EntryId | null, direction: 'up' | 'down') => {\n if (cursor == null) {\n return;\n }\n\n const movedIntoGroupId = await move(cursor, direction);\n // if we are moving into a group, we need to make sure it is expanded\n if (movedIntoGroupId) {\n handleCollapseGroup(false, movedIntoGroupId);\n }\n },\n [handleCollapseGroup, move],\n );\n\n // shortcuts\n useHotkeys([\n ['alt + ArrowDown', () => selectEntry(cursor, 'down'), { preventDefault: true, usePhysicalKeys: true }],\n ['alt + ArrowUp', () => selectEntry(cursor, 'up'), { preventDefault: true, usePhysicalKeys: true }],\n\n ['alt + shift + ArrowDown', () => selectGroup(cursor, 'down'), { preventDefault: true, usePhysicalKeys: true }],\n ['alt + shift + ArrowUp', () => selectGroup(cursor, 'up'), { preventDefault: true, usePhysicalKeys: true }],\n\n ['alt + mod + ArrowDown', () => moveEntry(cursor, 'down'), { preventDefault: true, usePhysicalKeys: true }],\n ['alt + mod + ArrowUp', () => moveEntry(cursor, 'up'), { preventDefault: true, usePhysicalKeys: true }],\n\n ['Escape', () => clearSelectedEvents(), { preventDefault: true, usePhysicalKeys: true }],\n\n ['mod + Backspace', () => deleteAtCursor(cursor), { preventDefault: true, usePhysicalKeys: true }],\n\n [\n 'alt + E',\n () => insertAtId({ type: SupportedEntry.Event }, cursor),\n { preventDefault: true, usePhysicalKeys: true },\n ],\n [\n 'alt + shift + E',\n () => insertAtId({ type: SupportedEntry.Event }, cursor, true),\n { preventDefault: true, usePhysicalKeys: true },\n ],\n\n [\n 'alt + G',\n () => insertAtId({ type: SupportedEntry.Group }, cursor),\n { preventDefault: true, usePhysicalKeys: true },\n ],\n [\n 'alt + shift + G',\n () => insertAtId({ type: SupportedEntry.Group }, cursor, true),\n { preventDefault: true, usePhysicalKeys: true },\n ],\n\n [\n 'alt + D',\n () => insertAtId({ type: SupportedEntry.Delay }, cursor),\n { preventDefault: true, usePhysicalKeys: true },\n ],\n [\n 'alt + shift + D',\n () => insertAtId({ type: SupportedEntry.Delay }, cursor, true),\n { preventDefault: true, usePhysicalKeys: true },\n ],\n\n [\n 'alt + M',\n () => insertAtId({ type: SupportedEntry.Milestone }, cursor),\n { preventDefault: true, usePhysicalKeys: true },\n ],\n [\n 'alt + shift + M',\n () => insertAtId({ type: SupportedEntry.Milestone }, cursor, true),\n { preventDefault: true, usePhysicalKeys: true },\n ],\n\n ['mod + C', () => setEntryCopyId(cursor)],\n ['mod + V', () => insertCopyAtId(cursor, entryCopyId)],\n [\n 'mod + shift + V',\n () => insertCopyAtId(cursor, entryCopyId, true),\n { preventDefault: true, usePhysicalKeys: true },\n ],\n\n ['alt + backspace', () => deleteAtCursor(cursor), { preventDefault: true, usePhysicalKeys: true }],\n ]);\n\n // we copy the state from the store here\n // to workaround async updates on the drag mutations\n useEffect(() => {\n setSortableData(makeSortableList(order, entries));\n setMetadata(rundownMetadata);\n }, [order, entries, rundownMetadata]);\n\n // in run mode, we follow the playback selection and open groups as needed\n useEffect(() => {\n if (editorMode !== AppMode.Run || !featureData?.selectedEventId) {\n return;\n }\n const index = order.findIndex((id) => id === featureData.selectedEventId);\n // @ts-expect-error -- but we safely check if the parent property exists\n const maybeParent = entries[featureData.selectedEventId]?.parent;\n if (maybeParent) {\n // open the group\n setCollapsedGroups((prev) => [...prev].filter((id) => id !== maybeParent));\n }\n\n setSelectedEvents({ id: featureData.selectedEventId, selectMode: 'click', index });\n }, [editorMode, entries, featureData.selectedEventId, order, setCollapsedGroups, setSelectedEvents]);\n\n /**\n * On drag end, we reorder the events\n */\n const handleOnDragEnd = (event: DragEndEvent) => {\n const { active, over } = event;\n\n if (!over?.id || active.id === over.id) {\n return;\n }\n\n if (!active.data.current || !over.data.current) {\n return;\n }\n\n const fromIndex: number = active.data.current.sortable.index;\n const toIndex: number = over.data.current.sortable.index;\n let placement: 'before' | 'after' | 'insert' = fromIndex < toIndex ? 'after' : 'before';\n\n let destinationId = over.id as EntryId;\n const isDraggingGroup = active.data.current?.type === SupportedEntry.Group;\n\n // prevent dropping a group inside another\n if (\n isDraggingGroup &&\n !canDrop(over.data.current.type, over.data.current.parent, placement, getIsCollapsed(destinationId))\n ) {\n return;\n }\n\n /**\n * We need to specially handle the end-group\n * Dragging before a end-group will add the entry to the end of the group\n * Dragging after a end-group will add the event after the group itself\n * Dragging to the top of a group either place before first entry or if no entries do insert\n */\n if (destinationId.startsWith('end-')) {\n destinationId = destinationId.replace('end-', '');\n // if we are moving before the end, we use the insert operation\n if (placement === 'before') {\n placement = 'insert';\n }\n } else {\n const group = data.entries[destinationId];\n // if dragging into a group\n if (isOntimeGroup(group) && placement === 'after') {\n if (isDraggingGroup) {\n // ... and the dragged entry is a group, we know that the group is collapsed, because of the safe check canDrop from before\n // so we can safely push the dragged event after the group\n destinationId = group.id;\n } else if (group.entries.length === 0) {\n // ... and the group is entry, we insert\n destinationId = group.id;\n placement = 'insert';\n } else {\n // otherwise we add it to before the first group child\n destinationId = group.entries[0];\n placement = 'before';\n }\n }\n }\n\n // keep copy of the current state in case we need to revert\n const currentEntries = structuredClone(sortableData);\n // we keep a copy of the state as a hack to handle inconsistencies between dnd-kit and async store updates\n setSortableData((currentEntries) => {\n return reorderArray(currentEntries, fromIndex, toIndex);\n });\n reorderEntry(active.id as EntryId, destinationId, placement).catch((_) => {\n setSortableData(currentEntries);\n });\n };\n\n /**\n * When we drag a group, we force collapse it\n * This avoids strange scenarios like dropping a group inside itself\n */\n const collapseDraggedGroups = (event: DragStartEvent) => {\n const isGroup = event.active.data.current?.type === SupportedEntry.Group;\n if (isGroup) {\n handleCollapseGroup(true, event.active.id as EntryId);\n }\n };\n\n /**\n * When we drag over a group, we expand it if it is collapsed\n */\n const expandOverGroup = (event: DragOverEvent) => {\n // if we are dragging a group, the drop operation is invalid so we dont expand\n if (event.active.data.current?.type === 'group') {\n return;\n }\n if (event.over?.data.current?.type !== 'group') {\n return;\n }\n const groupId = event.over?.id as EntryId;\n const isCollapsed = getIsCollapsed(groupId);\n if (isCollapsed) {\n handleCollapseGroup(false, groupId);\n }\n };\n\n if (sortableData.length < 1) {\n return <RundownEmpty handleAddNew={(type: SupportedEntry) => addEntry({ type })} />;\n }\n\n // 1. gather presentation options\n const isEditMode = editorMode === AppMode.Edit;\n\n return (\n <div className={style.rundownContainer} ref={scrollRef} data-testid='rundown'>\n <DndContext\n onDragEnd={handleOnDragEnd}\n onDragStart={collapseDraggedGroups}\n onDragOver={expandOverGroup}\n sensors={sensors}\n collisionDetection={closestCenter}\n >\n <SortableContext items={sortableData} strategy={verticalListSortingStrategy}>\n <div className={style.list}>\n {isEditMode && <QuickAddButtons previousEventId={null} parentGroup={null} />}\n {sortableData.map((entryId, index) => {\n // the entry might be a pseudo end-group which does not generate metadata and should not be processed\n if (entryId.startsWith('end-')) {\n const parentId = entryId.split('end-')[1];\n const isGroupCollapsed = getIsCollapsed(parentId);\n const parentMetadata = metadata[parentId];\n\n if (isGroupCollapsed) {\n return null;\n }\n\n // if the previous element is selected, it will have its own QuickAddInline\n // we use thisId instead of previousEntryId because the end-group does not process\n // and it does not cause the reassignment of the iteration id to the previous entry\n return (\n <Fragment key={entryId}>\n {isEditMode && parentMetadata?.groupEntries === 0 && (\n <QuickAddButtons\n previousEventId={null}\n parentGroup={parentId}\n backgroundColor={parentMetadata?.groupColour}\n />\n )}\n <RundownGroupEnd key={entryId} id={entryId} colour={parentMetadata?.groupColour} />\n </Fragment>\n );\n }\n\n // we iterate through a stateful copy of order to make the dnd operations smoother\n // this means that this can be out of sync with order until the useEffect runs\n // instead of writing all the logic guards, we simply short circuit rendering here\n const entry = entries[entryId];\n const entryMetadata = metadata[entryId];\n if (!entry || !entryMetadata) return null;\n\n // if the entry has a parent, and it is collapsed, render nothing\n if (\n entry.type !== SupportedEntry.Group &&\n entryMetadata.groupId !== null &&\n getIsCollapsed(entryMetadata.groupId)\n ) {\n return null;\n }\n\n const isNext = featureData?.nextEventId === entry.id;\n const hasCursor = entry.id === cursor;\n\n /**\n * Outside a group, the value will be undefined\n * If the colour is empty string ''\n * ie: we are inside a group, but there is no defined colour\n * we default to $gray-500 #9d9d9d\n */\n const groupColour = entryMetadata.groupColour === '' ? '#9d9d9d' : entryMetadata.groupColour;\n\n const isFirst = index === 0;\n const isLast = entryId === order.at(-1);\n\n /**\n * We need to provide the parent ID for the QuickAdd components\n * This should be different depending on whether we are adding before or after an element\n * - when adding before, we need to avoid a group referencing itself as the parent\n * - when adding after, we can use the group ID directly to insert at the top of the group\n */\n\n const parentIdForBefore = entryMetadata.thisId !== entryMetadata.groupId ? entryMetadata.groupId : null;\n const parentIdForAfter = entryMetadata.groupId;\n\n return (\n <Fragment key={entry.id}>\n {/**\n * Before the entry\n * - edit mode only\n * - if there is a cursor\n * - if it is not the first entry (the buttons would be there)\n */}\n {isEditMode && hasCursor && !isFirst && (\n <QuickAddInline placement='before' referenceEntryId={entry.id} parentGroup={parentIdForBefore} />\n )}\n {isOntimeGroup(entry) ? (\n <RundownGroup\n data={entry}\n hasCursor={hasCursor}\n collapsed={getIsCollapsed(entry.id)}\n onCollapse={handleCollapseGroup}\n />\n ) : (\n <div\n className={style.entryWrapper}\n data-testid={`entry-${entryMetadata.eventIndex}`}\n style={groupColour ? { '--user-bg': groupColour } : {}}\n >\n {isOntimeEvent(entry) && (\n <div className={style.entryIndex}>\n {entry.flag && <TbFlagFilled className={style.flag} />}\n <div className={style.index}>{entryMetadata.eventIndex}</div>\n </div>\n )}\n <div className={style.entry} key={entry.id} ref={hasCursor ? cursorRef : undefined}>\n <RundownEntry\n type={entry.type}\n isPast={entryMetadata.isPast}\n eventIndex={entryMetadata.eventIndex}\n data={entry}\n loaded={entryMetadata.isLoaded}\n hasCursor={hasCursor}\n isNext={isNext}\n isNextDay={entryMetadata.isNextDay}\n playback={entryMetadata.isLoaded ? featureData.playback : undefined}\n isRolling={featureData.playback === Playback.Roll}\n totalGap={entryMetadata.totalGap}\n isLinkedToLoaded={entryMetadata.isLinkedToLoaded}\n />\n </div>\n </div>\n )}\n {/**\n * After the entry\n * - edit mode only\n * - if there is a cursor\n * - if it is not the last entry (the buttons would be there)\n * - if the entry is not the group header\n */}\n {isEditMode && hasCursor && !isLast && (\n <QuickAddInline placement='after' referenceEntryId={entry.id} parentGroup={parentIdForAfter} />\n )}\n </Fragment>\n );\n })}\n {isEditMode && (\n <QuickAddButtons\n previousEventId={metadata[lastMetadataKey]?.groupId ?? metadata[lastMetadataKey].thisId}\n parentGroup={null}\n />\n )}\n <div className={style.spacer} />\n </div>\n </SortableContext>\n </DndContext>\n </div>\n );\n}\n","import Empty from '../../common/components/state/Empty';\nimport { useRundownWithMetadata } from '../../common/hooks-query/useRundown';\n\nimport RundownHeader from './rundown-header/RundownHeader';\nimport RundownHeaderMobile from './rundown-header/RundownHeaderMobile';\nimport Rundown from './Rundown';\n\nimport styles from './Rundown.module.scss';\n\ninterface RundownWrapperProps {\n isSmallDevice?: boolean;\n}\n\nexport default function RundownWrapper({ isSmallDevice }: RundownWrapperProps) {\n const { data, status, rundownMetadata } = useRundownWithMetadata();\n\n return (\n <div className={styles.rundownWrapper}>\n {isSmallDevice ? <RundownHeaderMobile /> : <RundownHeader />}\n {status === 'success' && data && rundownMetadata ? (\n <Rundown data={data} rundownMetadata={rundownMetadata} />\n ) : (\n <Empty text='Connecting to server' />\n )}\n </div>\n );\n}\n","import { memo } from 'react';\nimport { useSessionStorage } from '@mantine/hooks';\n\nimport { Corner } from '../../common/components/editor-utils/EditorUtils';\nimport ErrorBoundary from '../../common/components/error-boundary/ErrorBoundary';\nimport ViewNavigationMenu from '../../common/components/navigation-menu/ViewNavigationMenu';\nimport ProtectRoute from '../../common/components/protect-route/ProtectRoute';\nimport { useIsSmallDevice } from '../../common/hooks/useIsSmallDevice';\nimport { handleLinks } from '../../common/utils/linkUtils';\nimport { cx } from '../../common/utils/styleUtils';\nimport { AppMode, sessionKeys } from '../../ontimeConfig';\n\nimport RundownEntryEditor from './entry-editor/RundownEntryEditor';\nimport FinderPlacement from './placements/FinderPlacement';\nimport { RundownContextMenu } from './rundown-context-menu/RundownContextMenu';\nimport RundownWrapper from './RundownWrapper';\n\nimport style from './RundownExport.module.scss';\n\nexport default memo(RundownExport);\n\nfunction RundownExport() {\n const isExtracted = window.location.pathname.includes('/rundown');\n const [editorMode] = useSessionStorage({\n key: sessionKeys.editorMode,\n defaultValue: AppMode.Edit,\n });\n const isSmallDevice = useIsSmallDevice();\n\n if (isSmallDevice && isExtracted) {\n return (\n <ProtectRoute permission='editor'>\n <div\n className={cx([style.rundownExport, style.extracted])}\n data-target='small-device'\n data-testid='panel-rundown'\n >\n <FinderPlacement />\n <ViewNavigationMenu suppressSettings />\n <div className={style.rundown}>\n <ErrorBoundary>\n <RundownContextMenu>\n <RundownWrapper isSmallDevice />\n </RundownContextMenu>\n </ErrorBoundary>\n </div>\n </div>\n </ProtectRoute>\n );\n }\n\n const hideSideBar = isExtracted && editorMode === 'run';\n\n return (\n <ProtectRoute permission='editor'>\n <div className={cx([style.rundownExport, isExtracted && style.extracted])} data-testid='panel-rundown'>\n <FinderPlacement />\n {isExtracted && <ViewNavigationMenu suppressSettings />}\n <div className={style.rundown}>\n <div className={style.list}>\n <ErrorBoundary>\n {!isExtracted && <Corner onClick={(event) => handleLinks('rundown', event)} />}\n <RundownContextMenu>\n <RundownWrapper />\n </RundownContextMenu>\n </ErrorBoundary>\n </div>\n {!hideSideBar && (\n <div className={style.side}>\n <ErrorBoundary>\n <RundownEntryEditor />\n </ErrorBoundary>\n </div>\n )}\n </div>\n </div>\n </ProtectRoute>\n );\n}\n"],"file":"assets/RundownExport-WjLpncYT.js"}
1
+ {"version":3,"mappings":"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","names":["reorderArray","array","fromIndex","toIndex","modifiedArray","reorderedItem","isMacOS","userAgent","deviceAlt","deviceMod","useEventSelection","create","set","get","id","index","selectMode","selectedEvents","anchoredIndex","entryMode","rundownData","ontimeQueryClient","RUNDOWN","nextIndex","eventId","i","isOntimeEvent","eventIds","event","start","end","selectedEventIds","firstSelected","getSelectionMode","memo","EventEditorFooter","cue","loadById","loadByCue","jsxs","style","jsx","CopyTag","EventEditorEmpty","Editor.Title","Kbd","AuxKey","children","RundownEntryEditor","state","data","useRundown","entry","setEntry","useState","useEffect","selectedEventId","isOntimeDelay","EventEditor","isOntimeMilestone","MilestoneEditor","isOntimeGroup","GroupEditor","maxResults","useFinder","rundownId","useFlatRundown","results","setResults","error","setError","lastSearchString","useRef","setSelectedEvents","collapsedGroups","setCollapsedGroups","useSessionStorage","find","useCallback","searchValue","searchString","searchByIndex","searchByCue","searchByTitle","searchIndex","eventIndex","SupportedEntry","remaining","select","selectedEvent","newGroups","Finder","isOpen","onClose","selected","setSelected","debouncedFind","useDebouncedCallback","navigate","prev","submit","handleMouseMoveEvent","li","Modal","Input","isSelected","displayIndex","displayCue","FinderPlacement","handler","useDisclosure","useHotkeys","useContextMenuStore","position","options","newIsOpen","RundownContextMenu","setIsOpen","Fragment","PositionedDropdownMenu","RundownMenu","handlers","clearSelectedEvents","editorMode","sessionKeys","AppMode","deleteAllEntries","useEntryActions","deleteAll","Toolbar.Button","Button","IoTrash","Dialog","RundownHeader","setEditorMode","offsetMode","useOffsetMode","toggleAppMode","mode","newValue","toggleOffsetMode","setOffsetMode","Toolbar.Root","ToggleGroup","Toggle","Editor.Separator","OffsetMode","useEntryCopy","entryCopyId","cloneEvent","QuickAddButtons","previousEventId","parentGroup","backgroundColor","addEntry","addEvent","addDelay","addMilestone","addGroup","groupColour","cx","IoAdd","QuickAddInline","referenceEntryId","placement","handleAddEntry","type","DropdownMenu","IconButton","useContextMenu","setContextMenu","contextMenuEvent","pageX","pageY","TitleEditor","title","entryId","placeholder","className","updateEntry","ref","submitCallback","text","cleanVal","value","onChange","onBlur","onKeyDown","useReactiveTextInput","classes","RundownGroup","hasCursor","collapsed","onCollapse","handleRef","clone","ungroup","deleteEntry","setSingleEntrySelection","onContextMenu","IoDuplicateOutline","IoFolderOpenOutline","dragAttributes","dragListeners","setNodeRef","transform","transition","isDragging","isOver","over","useSortable","handleFocusClick","binderColours","getAccessibleColour","isValidDrop","canDrop","_a","_b","planOffset","planOffsetLabel","offset","absOffset","formatDuration","MILLIS_PER_MINUTE","getOffsetState","dragStyle","CSS","IoReorderTwo","IoChevronUp","IoChevronDown","formatTime","RundownGroupEnd","colour","RundownEmpty","props","handleAddNew","Empty","RundownEntry","lazy","__vitePreload","Rundown","rundownMetadata","order","entries","featureData","useRundownEditor","sortableData","setSortableData","makeSortableList","metadata","setMetadata","move","reorderEntry","setEntryCopyId","cursor","cursorRef","scrollRef","useFollowComponent","sensors","useSensors","useSensor","PointerSensor","deleteAtCursor","getPreviousNormal","insertCopyAtId","atId","copyId","above","adjustedCursor","cloneEntry","newEvent","insertAtId","patch","selectGroup","direction","newCursor","getLastNormal","getFirstNormal","getPreviousGroupNormal","getNextGroupNormal","selectEntry","getNextNormal","getIsCollapsed","groupId","handleCollapseGroup","isCollapsed","moveEntry","movedIntoGroupId","maybeParent","handleOnDragEnd","active","destinationId","isDraggingGroup","group","currentEntries","_","collapseDraggedGroups","expandOverGroup","_c","_d","isEditMode","DndContext","closestCenter","SortableContext","verticalListSortingStrategy","parentId","isGroupCollapsed","parentMetadata","entryMetadata","isNext","isFirst","isLast","parentIdForBefore","parentIdForAfter","TbFlagFilled","Playback","lastMetadataKey","RundownWrapper","isSmallDevice","status","useRundownWithMetadata","styles","RundownHeaderMobile","RundownExport","isExtracted","useIsSmallDevice","ProtectRoute","ViewNavigationMenu","ErrorBoundary","hideSideBar","Corner","handleLinks"],"ignoreList":[],"sources":["../../../../packages/utils/src/common/arrayUtils.ts","../../src/common/utils/deviceUtils.ts","../../src/features/rundown/useEventSelection.ts","../../src/features/rundown/entry-editor/composite/EventEditorFooter.tsx","../../src/features/rundown/entry-editor/EventEditorEmpty.tsx","../../src/features/rundown/entry-editor/RundownEntryEditor.tsx","../../src/views/editor/finder/useFinder.tsx","../../src/views/editor/finder/Finder.tsx","../../src/features/rundown/placements/FinderPlacement.tsx","../../src/features/rundown/rundown-context-menu/RundownContextMenu.tsx","../../src/features/rundown/rundown-header/RundownMenu.tsx","../../src/features/rundown/rundown-header/RundownHeader.tsx","../../src/features/rundown/rundown-header/RundownHeaderMobile.tsx","../../src/common/stores/entryCopyStore.ts","../../src/common/utils/clone.ts","../../src/features/rundown/entry-editor/quick-add-buttons/QuickAddButtons.tsx","../../src/features/rundown/entry-editor/quick-add-cursor/QuickAddInline.tsx","../../src/common/hooks/useContextMenu.tsx","../../src/features/rundown/common/TitleEditor.tsx","../../src/features/rundown/rundown-group/RundownGroup.tsx","../../src/features/rundown/rundown-group/RundownGroupEnd.tsx","../../src/features/rundown/RundownEmpty.tsx","../../src/features/rundown/Rundown.tsx","../../src/features/rundown/RundownWrapper.tsx","../../src/features/rundown/RundownExport.tsx"],"sourcesContent":["/**\n * Inserts an item in an array at a given index\n * @param index\n * @param item\n * @param array\n */\nexport function insertAtIndex<T>(index: number, item: T, array: T[]): T[] {\n const modifiedArray = [...array];\n\n // Insert at beginning\n if (index === 0) {\n modifiedArray.unshift(item);\n }\n\n // insert at end\n else if (index >= modifiedArray.length) {\n modifiedArray.push(item);\n }\n\n // insert in the middle\n else {\n modifiedArray.splice(index, 0, item);\n }\n\n return modifiedArray;\n}\n\n/**\n * Inserts an array into another one of the same type at a given index\n */\nexport function mergeAtIndex<T>(index: number, newArray: T[], currentArray: T[]): T[] {\n // Insert at beginning\n if (index === 0) {\n return [...newArray, ...currentArray];\n }\n\n // insert at end\n else if (index >= currentArray.length) {\n return [...currentArray, ...newArray];\n }\n\n // insert in the middle\n return currentArray.toSpliced(index, 0, ...newArray);\n}\n\n/**\n * Deletes array element at a given index\n * @param index\n * @param array\n */\nexport function deleteAtIndex<T>(index: number, array: T[]) {\n return array.filter((_, i) => i !== index);\n}\n\n/**\n * Reorders two objects in an array\n */\nexport function reorderArray<T>(array: T[], fromIndex: number, toIndex: number): T[] {\n if (fromIndex === toIndex) {\n return array; // No change needed, return the original array\n }\n\n const modifiedArray = [...array];\n\n // delete in from\n const [reorderedItem] = modifiedArray.splice(fromIndex, 1);\n\n // reinsert item at to\n modifiedArray.splice(toIndex, 0, reorderedItem);\n return modifiedArray;\n}\n","export function isMacOS() {\n const userAgent = navigator.userAgent.toLowerCase();\n return userAgent.includes('macintosh') || userAgent.includes('mac os');\n}\n\nexport const deviceAlt = isMacOS() ? 'Option' : 'Alt';\n\nexport const deviceMod = isMacOS() ? 'Cmd' : 'Ctrl';\n","import { MouseEvent } from 'react';\nimport { EntryId, isOntimeEvent, MaybeNumber, MaybeString, Rundown } from 'ontime-types';\nimport { create } from 'zustand';\n\nimport { RUNDOWN } from '../../common/api/constants';\nimport { ontimeQueryClient } from '../../common/queryClient';\nimport { isMacOS } from '../../common/utils/deviceUtils';\n\ntype SelectionMode = 'shift' | 'click' | 'ctrl';\n\ninterface EventSelectionStore {\n selectedEvents: Set<EntryId>;\n anchoredIndex: MaybeNumber;\n cursor: MaybeString;\n entryMode: 'event' | 'single' | null;\n setSingleEntrySelection: (selectionArgs: { id: EntryId }) => void;\n setSelectedEvents: (selectionArgs: { id: EntryId; index: number; selectMode: SelectionMode }) => void;\n clearSelectedEvents: () => void;\n clearMultiSelect: () => void;\n unselect: (id: EntryId) => void;\n}\n\nexport const useEventSelection = create<EventSelectionStore>()((set, get) => ({\n selectedEvents: new Set(),\n anchoredIndex: null,\n cursor: null,\n entryMode: null,\n setSingleEntrySelection: ({ id }) => {\n set({ selectedEvents: new Set([id]), anchoredIndex: null, cursor: id, entryMode: 'single' });\n },\n setSelectedEvents: ({ id, index, selectMode }) => {\n const { selectedEvents, anchoredIndex, entryMode } = get();\n\n // if we are in single mode, we replace the selection and change the mode\n if (entryMode === 'single') {\n return set({ selectedEvents: new Set([id]), anchoredIndex: index, cursor: id, entryMode: 'event' });\n }\n\n // on click, we replace selection with event\n if (selectMode === 'click') {\n return set({ selectedEvents: new Set([id]), anchoredIndex: index, cursor: id, entryMode: 'event' });\n }\n\n // on ctrl + click, we toggle the selection of that event\n if (selectMode === 'ctrl') {\n const rundownData = ontimeQueryClient.getQueryData<Rundown>(RUNDOWN);\n if (!rundownData) return;\n\n // if it doesnt exist, simply add to the list and set an anchor\n if (!selectedEvents.has(id)) {\n return set({\n selectedEvents: selectedEvents.add(id),\n anchoredIndex: index,\n cursor: id,\n entryMode: 'event',\n });\n }\n\n // if event is already selected, we remove it from selection\n // and set the anchor to the event after\n selectedEvents.delete(id);\n\n const nextIndex = rundownData.order.findIndex(\n (eventId, i) => i > index && isOntimeEvent(rundownData.entries[eventId]) && selectedEvents.has(eventId),\n );\n\n // if we didnt find anything after, set the anchor to the last event\n return set({\n selectedEvents,\n anchoredIndex: nextIndex < 0 ? rundownData.order.length - 1 : nextIndex,\n entryMode: 'event',\n });\n }\n\n // on shift + click, we select a range of events up to the clicked event\n if (selectMode === 'shift') {\n const rundownData = ontimeQueryClient.getQueryData<Rundown>(RUNDOWN);\n if (!rundownData) return;\n\n // get list of rundown with only ontime events\n const eventIds: EntryId[] = [];\n rundownData.flatOrder.forEach((eventId) => {\n const event = rundownData.entries[eventId];\n if (isOntimeEvent(event)) {\n eventIds.push(event.id);\n }\n });\n\n const start = anchoredIndex === null ? 0 : Math.min(anchoredIndex, index);\n const end = anchoredIndex === null ? index : Math.max(anchoredIndex, index + 1);\n\n // create new set with range of ids from start to end\n const selectedEventIds = eventIds.slice(start, end);\n\n return set({\n selectedEvents: new Set([...selectedEvents, ...selectedEventIds]),\n anchoredIndex: index,\n entryMode: 'event',\n });\n }\n },\n clearSelectedEvents: () => set({ selectedEvents: new Set(), anchoredIndex: null, cursor: null, entryMode: null }),\n clearMultiSelect: () => {\n const { selectedEvents } = get();\n const [firstSelected] = selectedEvents;\n set({\n selectedEvents: new Set(firstSelected ? [firstSelected] : []),\n anchoredIndex: null,\n entryMode: null,\n });\n },\n unselect: (id: string) => {\n const { entryMode, selectedEvents } = get();\n selectedEvents.delete(id);\n set({\n selectedEvents,\n entryMode: selectedEvents.size === 0 ? null : entryMode,\n });\n },\n}));\n\nexport function getSelectionMode(event: MouseEvent): SelectionMode {\n if ((isMacOS() && event.metaKey) || event.ctrlKey) {\n return 'ctrl';\n }\n\n if (event.shiftKey) {\n return 'shift';\n }\n\n return 'click';\n}\n","import { memo } from 'react';\n\nimport CopyTag from '../../../../common/components/copy-tag/CopyTag';\n\nimport style from './EventEditorFooter.module.scss';\n\ninterface EventEditorFooterProps {\n id: string;\n cue: string;\n}\n\nexport default memo(EventEditorFooter);\nfunction EventEditorFooter({ id, cue }: EventEditorFooterProps) {\n const loadById = `/ontime/load/id \"${id}\"`;\n const loadByCue = `/ontime/load/cue \"${cue}\"`;\n\n return (\n <div className={style.footer}>\n <CopyTag copyValue={loadById}>{loadById}</CopyTag>\n <CopyTag copyValue={loadByCue}>{loadByCue}</CopyTag>\n </div>\n );\n}\n","import { memo, PropsWithChildren } from 'react';\n\nimport * as Editor from '../../../common/components/editor-utils/EditorUtils';\nimport { deviceAlt, deviceMod } from '../../../common/utils/deviceUtils';\n\nimport style from './EventEditorEmpty.module.scss';\n\nexport default memo(EventEditorEmpty);\n\nfunction EventEditorEmpty() {\n return (\n <div className={style.entryEditor} data-testid='editor-container'>\n <div className={style.shortcutSection}>\n <Editor.Title className={style.prompt}>Rundown shortcuts</Editor.Title>\n <table className={style.shortcuts}>\n <tbody>\n <tr>\n <td>Find in rundown</td>\n <td>\n <Kbd>{deviceMod}</Kbd>\n <AuxKey>+</AuxKey>\n <Kbd>F</Kbd>\n </td>\n </tr>\n <tr>\n <td>Open Settings</td>\n <td>\n <Kbd>{deviceMod}</Kbd>\n <AuxKey>+</AuxKey>\n <Kbd>,</Kbd>\n </td>\n </tr>\n <tr className={style.spacer} />\n <tr>\n <td>Select entry</td>\n <td>\n <Kbd>{deviceAlt}</Kbd>\n <AuxKey>+</AuxKey>\n <Kbd>↑</Kbd>\n <AuxKey>/</AuxKey>\n <Kbd>↓</Kbd>\n </td>\n </tr>\n <tr>\n <td>Select group</td>\n <td>\n <Kbd>{deviceAlt}</Kbd>\n <AuxKey>+</AuxKey>\n <Kbd>Shift</Kbd>\n <AuxKey>+</AuxKey>\n <Kbd>↑</Kbd>\n <AuxKey>/</AuxKey>\n <Kbd>↓</Kbd>\n </td>\n </tr>\n <tr>\n <td>Deselect entry</td>\n <td>\n <Kbd>Esc</Kbd>\n </td>\n </tr>\n <tr className={style.spacer} />\n <tr>\n <td>Reorder selected entry</td>\n <td>\n <Kbd>{deviceAlt}</Kbd>\n <AuxKey>+</AuxKey>\n <Kbd>{deviceMod}</Kbd>\n <AuxKey>+</AuxKey>\n <Kbd>↑</Kbd>\n <AuxKey>/</AuxKey>\n <Kbd>↓</Kbd>\n </td>\n </tr>\n <tr>\n <td>Copy selected entry</td>\n <td>\n <Kbd>{deviceMod}</Kbd>\n <AuxKey>+</AuxKey>\n <Kbd>C</Kbd>\n </td>\n </tr>\n <tr>\n <td>Paste above</td>\n <td>\n <Kbd>{deviceMod}</Kbd>\n <AuxKey>+</AuxKey>\n <Kbd>Shift</Kbd>\n <AuxKey>+</AuxKey>\n <Kbd>V</Kbd>\n </td>\n </tr>\n <tr>\n <td>Paste below</td>\n <td>\n <Kbd>{deviceMod}</Kbd>\n <AuxKey>+</AuxKey>\n <Kbd>V</Kbd>\n </td>\n </tr>\n <tr>\n <td>Delete selected entry</td>\n <td>\n <Kbd>{deviceMod}</Kbd>\n <AuxKey>+</AuxKey>\n <Kbd>Backspace</Kbd>\n </td>\n </tr>\n <tr className={style.spacer} />\n <tr>\n <td>Add event below</td>\n <td>\n <Kbd>{deviceAlt}</Kbd>\n <AuxKey>+</AuxKey>\n <Kbd>E</Kbd>\n </td>\n </tr>\n <tr>\n <td>Add event above</td>\n <td>\n <Kbd>{deviceAlt}</Kbd>\n <AuxKey>+</AuxKey>\n <Kbd>Shift</Kbd>\n <AuxKey>+</AuxKey>\n <Kbd>E</Kbd>\n </td>\n </tr>\n <tr>\n <td>Add group below</td>\n <td>\n <Kbd>{deviceAlt}</Kbd>\n <AuxKey>+</AuxKey>\n <Kbd>G</Kbd>\n </td>\n </tr>\n <tr>\n <td>Add group above</td>\n <td>\n <Kbd>{deviceAlt}</Kbd>\n <AuxKey>+</AuxKey>\n <Kbd>Shift</Kbd>\n <AuxKey>+</AuxKey>\n <Kbd>M</Kbd>\n </td>\n </tr>\n <tr>\n <td>Add milestone below</td>\n <td>\n <Kbd>{deviceAlt}</Kbd>\n <AuxKey>+</AuxKey>\n <Kbd>G</Kbd>\n </td>\n </tr>\n <tr>\n <td>Add milestone above</td>\n <td>\n <Kbd>{deviceAlt}</Kbd>\n <AuxKey>+</AuxKey>\n <Kbd>Shift</Kbd>\n <AuxKey>+</AuxKey>\n <Kbd>M</Kbd>\n </td>\n </tr>\n <tr>\n <td>Add delay below</td>\n <td>\n <Kbd>{deviceAlt}</Kbd>\n <AuxKey>+</AuxKey>\n <Kbd>D</Kbd>\n </td>\n </tr>\n <tr>\n <td>Add delay above</td>\n <td>\n <Kbd>{deviceAlt}</Kbd>\n <AuxKey>+</AuxKey>\n <Kbd>Shift</Kbd>\n <AuxKey>+</AuxKey>\n <Kbd>D</Kbd>\n </td>\n </tr>\n </tbody>\n </table>\n </div>\n </div>\n );\n}\n\nfunction AuxKey({ children }: PropsWithChildren) {\n return <span className={style.divider}>{children}</span>;\n}\n\nfunction Kbd({ children }: PropsWithChildren) {\n return <span className={style.kbd}>{children}</span>;\n}\n","import { useEffect, useState } from 'react';\nimport {\n isOntimeDelay,\n isOntimeEvent,\n isOntimeGroup,\n isOntimeMilestone,\n OntimeEvent,\n OntimeGroup,\n OntimeMilestone,\n} from 'ontime-types';\n\nimport useRundown from '../../../common/hooks-query/useRundown';\nimport { useEventSelection } from '../useEventSelection';\n\nimport EventEditorFooter from './composite/EventEditorFooter';\nimport EventEditor from './EventEditor';\nimport EventEditorEmpty from './EventEditorEmpty';\nimport GroupEditor from './GroupEditor';\nimport MilestoneEditor from './MilestoneEditor';\n\nimport style from './EntryEditor.module.scss';\n\nexport default function RundownEntryEditor() {\n const selectedEvents = useEventSelection((state) => state.selectedEvents);\n const { data } = useRundown();\n\n const [entry, setEntry] = useState<OntimeEvent | OntimeGroup | OntimeMilestone | null>(null);\n\n useEffect(() => {\n if (data.order.length === 0) {\n setEntry(null);\n return;\n }\n\n const selectedEventId = Array.from(selectedEvents).at(0);\n if (!selectedEventId) {\n setEntry(null);\n return;\n }\n const event = data.entries[selectedEventId];\n\n if (event && !isOntimeDelay(event)) {\n setEntry(event);\n } else {\n setEntry(null);\n }\n }, [data.order, data.entries, selectedEvents]);\n\n if (!entry) {\n return <EventEditorEmpty />;\n }\n\n if (isOntimeEvent(entry)) {\n return (\n <div className={style.rundownEditor} data-testid='editor-container'>\n <EventEditor event={entry} />\n <EventEditorFooter id={entry.id} cue={entry.cue} />\n </div>\n );\n }\n\n if (isOntimeMilestone(entry)) {\n return (\n <div className={style.rundownEditor} data-testid='editor-container'>\n <MilestoneEditor milestone={entry} />\n </div>\n );\n }\n\n if (isOntimeGroup(entry)) {\n return (\n <div className={style.rundownEditor} data-testid='editor-container'>\n <GroupEditor group={entry} />\n </div>\n );\n }\n\n return null;\n}\n","import { ChangeEvent, useCallback, useEffect, useRef, useState } from 'react';\nimport { useSessionStorage } from '@mantine/hooks';\nimport { EntryId, isOntimeEvent, isOntimeGroup, isOntimeMilestone, MaybeString, SupportedEntry } from 'ontime-types';\n\nimport { useFlatRundown } from '../../../common/hooks-query/useRundown';\nimport { useEventSelection } from '../../../features/rundown/useEventSelection';\n\nconst maxResults = 12;\n\ntype FilterableGroup = {\n type: SupportedEntry.Group;\n id: EntryId;\n index: number;\n title: string;\n colour: string;\n};\n\ntype FilterableEvent = {\n type: SupportedEntry.Event;\n id: EntryId;\n index: number;\n eventIndex: number;\n title: string;\n cue: string;\n colour: string;\n parent: MaybeString;\n};\n\ntype FilterableMilestone = {\n type: SupportedEntry.Milestone;\n id: EntryId;\n index: number;\n title: string;\n cue: string;\n colour: string;\n parent: MaybeString;\n};\n\ntype FilterableEntry = FilterableGroup | FilterableEvent | FilterableMilestone;\n\nexport default function useFinder() {\n const { data, rundownId } = useFlatRundown();\n const [results, setResults] = useState<FilterableEntry[]>([]);\n const [error, setError] = useState<MaybeString>(null);\n const lastSearchString = useRef('');\n\n const setSelectedEvents = useEventSelection((state) => state.setSelectedEvents);\n\n const [collapsedGroups, setCollapsedGroups] = useSessionStorage<EntryId[]>({\n // we ensure that this is unique to the rundown\n key: `rundown.${rundownId}-editor-collapsed-groups`,\n defaultValue: [],\n });\n\n /** Filters the rundown to a given evaluation */\n const find = useCallback(\n (event: ChangeEvent<HTMLInputElement>) => {\n if (!data || data.length === 0) {\n setError('No data');\n return;\n }\n setError(null);\n\n if (event.target.value === '') {\n setResults([]);\n return;\n }\n\n const searchValue = event.target.value.toLowerCase();\n lastSearchString.current = searchValue;\n\n if (searchValue.startsWith('index ')) {\n const searchString = searchValue.slice('index '.length).trim();\n const { results, error } = searchByIndex(searchString);\n setResults(results);\n setError(error);\n return;\n }\n\n if (searchValue.startsWith('cue ')) {\n const searchString = searchValue.slice('cue '.length).trim();\n const { results, error } = searchByCue(searchString);\n setResults(results);\n setError(error);\n return;\n }\n\n const searchString = searchValue.startsWith('title ') ? searchValue.slice('title '.length).trim() : searchValue;\n const { results, error } = searchByTitle(searchString);\n setResults(results);\n setError(error);\n\n /** Returns a single item with a matching index */\n function searchByIndex(searchString: string) {\n const searchIndex = Number(searchString);\n if (isNaN(searchIndex) || searchIndex < 1) {\n return { results: [], error: 'Invalid index' };\n }\n\n if (searchIndex > data.length) {\n return { results: [], error: null };\n }\n\n // indexes exposed to the UI are 1-based\n let eventIndex = 1;\n const results: FilterableEvent[] = [];\n for (let i = 0; i < data.length; i++) {\n const event = data[i];\n if (isOntimeEvent(event)) {\n if (eventIndex === searchIndex) {\n results.push({\n type: SupportedEntry.Event,\n id: event.id,\n index: i,\n eventIndex,\n title: event.title,\n cue: event.cue,\n colour: event.colour,\n parent: event.parent,\n } satisfies FilterableEvent);\n break;\n }\n eventIndex++;\n }\n }\n\n return { results, error: null };\n }\n\n /** Returns maxResults of OntimeEvents that match the cue field */\n function searchByCue(searchString: string) {\n // indexes exposed to the UI are 1-based\n let eventIndex = 1;\n // limit amount of results we show\n let remaining = maxResults;\n const results: FilterableEvent[] = [];\n\n for (let i = 0; i < data.length; i++) {\n if (remaining <= 0) {\n break;\n }\n const event = data[i];\n if (isOntimeEvent(event)) {\n if (event.cue.toLowerCase().includes(searchString)) {\n remaining--;\n results.push({\n type: SupportedEntry.Event,\n id: event.id,\n index: i,\n eventIndex,\n title: event.title,\n cue: event.cue,\n colour: event.colour,\n parent: event.parent,\n } satisfies FilterableEvent);\n }\n eventIndex++;\n }\n }\n return { results, error: null };\n }\n\n /** Returns maxResults of OntimeEvents that match the title field*/\n function searchByTitle(searchString: string) {\n // indexes exposed to the UI are 1-based\n let eventIndex = 1;\n // limit amount of results we show\n let remaining = maxResults;\n const results: FilterableEntry[] = [];\n\n for (let i = 0; i < data.length; i++) {\n if (remaining <= 0) {\n break;\n }\n\n const entry = data[i];\n if (isOntimeEvent(entry)) {\n if (entry.title.toLowerCase().includes(searchString)) {\n remaining--;\n results.push({\n type: SupportedEntry.Event,\n id: entry.id,\n index: i,\n eventIndex,\n title: entry.title,\n cue: entry.cue,\n colour: entry.colour,\n parent: entry.parent,\n } satisfies FilterableEvent);\n }\n eventIndex++;\n } else if (isOntimeGroup(entry)) {\n if (entry.title.toLowerCase().includes(searchString)) {\n remaining--;\n results.push({\n type: SupportedEntry.Group,\n id: entry.id,\n index: i,\n title: entry.title,\n colour: entry.colour,\n } satisfies FilterableGroup);\n }\n } else if (isOntimeMilestone(entry)) {\n if (entry.title.toLowerCase().includes(searchString)) {\n remaining--;\n results.push({\n type: SupportedEntry.Milestone,\n id: entry.id,\n index: i,\n title: entry.title,\n cue: entry.cue,\n colour: entry.colour,\n parent: entry.parent,\n } satisfies FilterableMilestone);\n }\n }\n }\n return { results, error: null };\n }\n },\n [data],\n );\n\n const select = useCallback(\n (selectedEvent: FilterableEntry) => {\n // First expand the parent group if this is an event inside a group\n if ('parent' in selectedEvent && selectedEvent.parent !== null) {\n // Try direct state update instead of using callback\n const currentGroups = [...new Set(collapsedGroups)];\n const newGroups = currentGroups.filter((id) => id !== selectedEvent.parent);\n // Force a direct update\n setCollapsedGroups(newGroups);\n }\n\n // Then select the event\n setSelectedEvents({ id: selectedEvent.id, index: selectedEvent.index, selectMode: 'click' });\n },\n [collapsedGroups, setCollapsedGroups, setSelectedEvents],\n );\n\n /** clear results when source data changes */\n useEffect(() => {\n setResults([]);\n setError(null);\n // fake a submit event to re-run the search\n if (lastSearchString.current) {\n find({ target: { value: lastSearchString.current } } as ChangeEvent<HTMLInputElement>);\n }\n }, [data, find]);\n\n return { find, select, results, error };\n}\n","import { KeyboardEvent, useState } from 'react';\nimport { useDebouncedCallback } from '@mantine/hooks';\nimport { SupportedEntry } from 'ontime-types';\n\nimport Input from '../../../common/components/input/input/Input';\nimport Modal from '../../../common/components/modal/Modal';\n\nimport useFinder from './useFinder';\n\nimport style from './Finder.module.scss';\n\ninterface FinderProps {\n isOpen: boolean;\n onClose: () => void;\n}\n\nexport default function Finder({ isOpen, onClose }: FinderProps) {\n const { find, select, results, error } = useFinder();\n const [selected, setSelected] = useState(0);\n\n const debouncedFind = useDebouncedCallback(find, 100);\n\n const navigate = (event: KeyboardEvent<HTMLDivElement>) => {\n // all operations need results\n if (results.length === 0) {\n return;\n }\n if (event.key === 'ArrowDown') {\n setSelected((prev) => (prev + 1) % results.length);\n }\n if (event.key === 'ArrowUp') {\n setSelected((prev) => (prev - 1 + results.length) % results.length);\n }\n if (event.key === 'Enter') {\n event.preventDefault();\n event.stopPropagation();\n submit();\n }\n };\n\n const submit = () => {\n const selectedEvent = results[selected];\n select(selectedEvent);\n onClose();\n };\n\n const handleMouseMoveEvent = (event: React.MouseEvent<HTMLUListElement>) => {\n const target = event.target as HTMLElement;\n const li = target.closest('li');\n if (li) {\n const index = Number(li.dataset.index);\n if (!isNaN(index)) {\n setSelected(index);\n }\n }\n };\n\n return (\n <Modal\n title=''\n isOpen={isOpen}\n onClose={onClose}\n showBackdrop\n bodyElements={\n <div onKeyDown={navigate}>\n <Input height='large' fluid onChange={debouncedFind} placeholder='Search...' />\n <ul className={style.scrollContainer} onMouseMove={handleMouseMoveEvent}>\n {error && <li className={style.error}>{error}</li>}\n {results.length === 0 && <li className={style.empty}>No results</li>}\n {results.length > 0 &&\n results.map((entry, index) => {\n const isSelected = selected === index;\n const displayIndex = entry.type === SupportedEntry.Event ? entry.eventIndex : '-';\n const displayCue = 'cue' in entry ? entry.cue : '';\n\n return (\n <li\n key={entry.id}\n className={style.entry}\n data-selected={isSelected}\n data-index={index}\n onClick={submit}\n >\n <div className={style.data}>\n <div className={style.index} style={{ '--color': entry.colour }}>\n {displayIndex}\n </div>\n <div className={style.cue}>{displayCue}</div>\n <div className={style.title}>{entry.title}</div>\n </div>\n {isSelected && <span>Go ⏎</span>}\n </li>\n );\n })}\n </ul>\n </div>\n }\n footerElements={\n <div className={style.footer}>\n Use the keywords <span className={style.em}>cue</span>, <span className={style.em}>index</span> or\n <span className={style.em}>title</span> to filter search.\n </div>\n }\n />\n );\n}\n","import { memo } from 'react';\nimport { useDisclosure, useHotkeys } from '@mantine/hooks';\n\nimport Finder from '../../../views/editor/finder/Finder';\n\nexport default memo(FinderPlacement);\n\nfunction FinderPlacement() {\n const [isOpen, handler] = useDisclosure();\n\n useHotkeys([\n ['mod + f', handler.toggle],\n ['Escape', handler.close],\n ]);\n\n if (isOpen) {\n return <Finder isOpen={isOpen} onClose={handler.close} />;\n }\n\n return null;\n}\n","import type { PropsWithChildren } from 'react';\nimport { create } from 'zustand';\n\nimport { DropdownMenuOption, PositionedDropdownMenu } from '../../../common/components/dropdown-menu/DropdownMenu';\n\ntype Position = {\n x: number;\n y: number;\n};\n\ntype ContextMenuStore = {\n position: Position;\n options: DropdownMenuOption[];\n isOpen: boolean;\n setContextMenu: (position: Position, options: DropdownMenuOption[]) => void;\n setIsOpen: (newIsOpen: boolean) => void;\n};\n\nexport const useContextMenuStore = create<ContextMenuStore>((set) => ({\n position: { x: 0, y: 0 },\n options: [],\n isOpen: false,\n setContextMenu: (position, options) => set(() => ({ position, options, isOpen: true })),\n setIsOpen: (newIsOpen) => set(() => ({ isOpen: newIsOpen })),\n}));\n\nexport function RundownContextMenu({ children }: PropsWithChildren) {\n const { position, options, isOpen, setIsOpen } = useContextMenuStore();\n\n const onClose = () => {\n return setIsOpen(false);\n };\n\n if (!isOpen) {\n return children;\n }\n\n return (\n <>\n {children}\n <PositionedDropdownMenu isOpen position={position} onClose={onClose} items={options} />\n </>\n );\n}\n","import { memo, useCallback } from 'react';\nimport { IoTrash } from 'react-icons/io5';\nimport { Toolbar } from '@base-ui-components/react/toolbar';\nimport { useDisclosure, useSessionStorage } from '@mantine/hooks';\n\nimport Button from '../../../common/components/buttons/Button';\nimport Dialog from '../../../common/components/dialog/Dialog';\nimport { useEntryActions } from '../../../common/hooks/useEntryAction';\nimport { AppMode, sessionKeys } from '../../../ontimeConfig';\nimport { useEventSelection } from '../useEventSelection';\n\nimport style from './RundownHeader.module.scss';\n\nexport default memo(RundownMenu);\nfunction RundownMenu() {\n const [isOpen, handlers] = useDisclosure();\n\n const clearSelectedEvents = useEventSelection((state) => state.clearSelectedEvents);\n const [editorMode] = useSessionStorage({\n key: sessionKeys.editorMode,\n defaultValue: AppMode.Edit,\n });\n const { deleteAllEntries } = useEntryActions();\n\n const deleteAll = useCallback(() => {\n deleteAllEntries();\n clearSelectedEvents();\n handlers.close();\n }, [clearSelectedEvents, deleteAllEntries, handlers]);\n\n return (\n <>\n <Toolbar.Button\n render={<Button variant='subtle-destructive' />}\n onClick={handlers.open}\n disabled={editorMode === AppMode.Run}\n className={style.apart}\n >\n <IoTrash />\n Clear all\n </Toolbar.Button>\n <Dialog\n isOpen={isOpen}\n onClose={handlers.close}\n title='Clear rundown'\n showBackdrop\n showCloseButton\n bodyElements={\n <>\n You will lose all data in your rundown. <br /> Are you sure?\n </>\n }\n footerElements={\n <>\n <Button variant='ghosted-white' size='large' onClick={handlers.close}>\n Cancel\n </Button>\n <Button variant='destructive' size='large' onClick={deleteAll}>\n Delete all\n </Button>\n </>\n }\n />\n </>\n );\n}\n","import { memo } from 'react';\nimport { Toggle } from '@base-ui-components/react/toggle';\nimport { ToggleGroup } from '@base-ui-components/react/toggle-group';\nimport { Toolbar } from '@base-ui-components/react/toolbar';\nimport { useSessionStorage } from '@mantine/hooks';\nimport { OffsetMode } from 'ontime-types';\n\nimport * as Editor from '../../../common/components/editor-utils/EditorUtils';\nimport { setOffsetMode, useOffsetMode } from '../../../common/hooks/useSocket';\nimport { AppMode, sessionKeys } from '../../../ontimeConfig';\n\nimport RundownMenu from './RundownMenu';\n\nimport style from './RundownHeader.module.scss';\n\nexport default memo(RundownHeader);\nfunction RundownHeader() {\n const [editorMode, setEditorMode] = useSessionStorage({ key: sessionKeys.editorMode, defaultValue: AppMode.Edit });\n\n const { offsetMode } = useOffsetMode();\n\n const toggleAppMode = (mode: AppMode[]) => {\n // we need to stop user from deselecting a mode\n const newValue = mode.at(0);\n if (!newValue) return;\n setEditorMode(newValue);\n };\n\n const toggleOffsetMode = (mode: OffsetMode[]) => {\n // we need to stop user from deselecting a mode\n const newValue = mode.at(0);\n if (!newValue) return;\n setOffsetMode(newValue);\n };\n\n return (\n <Toolbar.Root className={style.header}>\n <ToggleGroup value={[editorMode]} onValueChange={toggleAppMode} className={style.group}>\n <Toolbar.Button render={<Toggle />} value={AppMode.Run} className={style.radioButton}>\n Run\n </Toolbar.Button>\n <Toolbar.Button render={<Toggle />} value={AppMode.Edit} className={style.radioButton}>\n Edit\n </Toolbar.Button>\n </ToggleGroup>\n\n <Editor.Separator className={style.separator} />\n\n <ToggleGroup value={[offsetMode]} onValueChange={toggleOffsetMode} className={style.group}>\n <Toolbar.Button render={<Toggle />} value={OffsetMode.Absolute} className={style.radioButton}>\n Absolute\n </Toolbar.Button>\n <Toolbar.Button render={<Toggle />} value={OffsetMode.Relative} className={style.radioButton}>\n Relative\n </Toolbar.Button>\n </ToggleGroup>\n\n <RundownMenu />\n </Toolbar.Root>\n );\n}\n","import { memo } from 'react';\nimport { Toggle } from '@base-ui-components/react/toggle';\nimport { ToggleGroup } from '@base-ui-components/react/toggle-group';\nimport { Toolbar } from '@base-ui-components/react/toolbar';\nimport { useSessionStorage } from '@mantine/hooks';\nimport { OffsetMode } from 'ontime-types';\n\nimport * as Editor from '../../../common/components/editor-utils/EditorUtils';\nimport { setOffsetMode, useOffsetMode } from '../../../common/hooks/useSocket';\nimport { AppMode, sessionKeys } from '../../../ontimeConfig';\n\nimport style from './RundownHeader.module.scss';\n\nexport default memo(RundownHeader);\nfunction RundownHeader() {\n const [editorMode, setEditorMode] = useSessionStorage<AppMode>({\n key: sessionKeys.editorMode,\n defaultValue: AppMode.Edit,\n });\n\n const { offsetMode } = useOffsetMode();\n\n const toggleAppMode = (mode: AppMode[]) => {\n // we need to stop user from deselecting a mode\n const newValue = mode.at(0);\n if (!newValue) return;\n setEditorMode(newValue);\n };\n\n const toggleOffsetMode = (mode: OffsetMode[]) => {\n // we need to stop user from deselecting a mode\n const newValue = mode.at(0);\n if (!newValue) return;\n setOffsetMode(newValue);\n };\n\n return (\n <Toolbar.Root className={style.header}>\n <ToggleGroup value={[editorMode]} onValueChange={toggleAppMode} className={style.group}>\n <Toolbar.Button render={<Toggle />} value={AppMode.Run} className={style.radioButton}>\n Run\n </Toolbar.Button>\n <Toolbar.Button render={<Toggle />} value={AppMode.Edit} className={style.radioButton}>\n Edit\n </Toolbar.Button>\n </ToggleGroup>\n\n <Editor.Separator className={style.separator} />\n\n <ToggleGroup value={[offsetMode]} onValueChange={toggleOffsetMode} className={style.group}>\n <Toolbar.Button render={<Toggle />} value={OffsetMode.Absolute} className={style.radioButton}>\n Absolute\n </Toolbar.Button>\n <Toolbar.Button render={<Toggle />} value={OffsetMode.Relative} className={style.radioButton}>\n Relative\n </Toolbar.Button>\n </ToggleGroup>\n </Toolbar.Root>\n );\n}\n","import { create } from 'zustand';\n\ntype EntryCopyStore = {\n entryCopyId: string | null;\n setEntryCopyId: (eventId: string | null) => void;\n};\n\nexport const useEntryCopy = create<EntryCopyStore>()((set) => ({\n entryCopyId: null,\n setEntryCopyId: (entryCopyId: string | null) => set({ entryCopyId }),\n}));\n","import { OntimeEvent, SupportedEntry } from 'ontime-types';\n\n/**\n * @description Creates a safe duplicate of an event\n * @param {OntimeEvent} event\n * @param {string} [after]\n * @return {OntimeEvent} clean event\n */\ntype ClonedEvent = Omit<OntimeEvent, 'id' | 'cue'>;\nexport const cloneEvent = (event: OntimeEvent): ClonedEvent => {\n return {\n type: SupportedEntry.Event,\n flag: event.flag,\n title: event.title,\n note: event.note,\n timeStart: event.timeStart,\n duration: event.duration,\n timeEnd: event.timeEnd,\n timerType: event.timerType,\n timeStrategy: event.timeStrategy,\n countToEnd: event.countToEnd,\n linkStart: event.linkStart,\n endAction: event.endAction,\n skip: event.skip,\n colour: event.colour,\n parent: event.parent,\n revision: 0,\n delay: event.delay, // the events will be collocated, so having the same metadata is a good start\n dayOffset: event.dayOffset,\n gap: 0,\n timeWarning: event.timeWarning,\n timeDanger: event.timeDanger,\n triggers: structuredClone(event.triggers),\n custom: structuredClone(event.custom),\n };\n};\n","import { memo } from 'react';\nimport { IoAdd } from 'react-icons/io5';\nimport { Toolbar } from '@base-ui-components/react/toolbar';\nimport { MaybeString, SupportedEntry } from 'ontime-types';\n\nimport Button from '../../../../common/components/buttons/Button';\nimport { useEntryActions } from '../../../../common/hooks/useEntryAction';\nimport { cx } from '../../../../common/utils/styleUtils';\n\nimport style from './QuickAddButtons.module.scss';\n\ninterface QuickAddButtonsProps {\n previousEventId: MaybeString;\n parentGroup: MaybeString;\n backgroundColor?: string;\n}\n\nexport default memo(QuickAddButtons);\nfunction QuickAddButtons({ previousEventId, parentGroup, backgroundColor }: QuickAddButtonsProps) {\n const { addEntry } = useEntryActions();\n\n const addEvent = () => {\n addEntry(\n {\n type: SupportedEntry.Event,\n parent: parentGroup,\n },\n {\n after: previousEventId,\n lastEventId: previousEventId,\n },\n );\n };\n\n const addDelay = () => {\n addEntry(\n { type: SupportedEntry.Delay, parent: parentGroup },\n {\n lastEventId: previousEventId,\n after: previousEventId,\n },\n );\n };\n\n const addMilestone = () => {\n addEntry(\n { type: SupportedEntry.Milestone, parent: parentGroup },\n {\n lastEventId: previousEventId,\n after: previousEventId,\n },\n );\n };\n\n const addGroup = () => {\n if (parentGroup !== null) {\n return;\n }\n addEntry(\n { type: SupportedEntry.Group },\n {\n lastEventId: previousEventId,\n after: previousEventId,\n },\n );\n };\n\n /**\n * If the colour is empty string ''\n * ie: we are inside a group, but there is no defined colour\n * we default to $gray-500 #9d9d9d\n */\n const groupColour = backgroundColor === '' ? '#9d9d9d' : backgroundColor;\n\n return (\n <Toolbar.Root\n className={cx([style.quickAdd, Boolean(parentGroup) && style.indent])}\n style={groupColour ? { '--user-bg': groupColour } : {}}\n data-testid='quick-add-buttons'\n >\n <Toolbar.Button render={<Button size='small' />} onClick={addEvent}>\n <IoAdd />\n Event\n </Toolbar.Button>\n\n <Toolbar.Button render={<Button size='small' />} onClick={addDelay}>\n <IoAdd />\n Delay\n </Toolbar.Button>\n\n <Toolbar.Button render={<Button size='small' />} onClick={addMilestone}>\n <IoAdd />\n Milestone\n </Toolbar.Button>\n\n {parentGroup === null && (\n <Toolbar.Button render={<Button size='small' />} onClick={addGroup}>\n <IoAdd />\n Group\n </Toolbar.Button>\n )}\n </Toolbar.Root>\n );\n}\n","import { memo } from 'react';\nimport { IoAdd } from 'react-icons/io5';\nimport { MaybeString, SupportedEntry } from 'ontime-types';\n\nimport IconButton from '../../../../common/components/buttons/IconButton';\nimport { DropdownMenu } from '../../../../common/components/dropdown-menu/DropdownMenu';\nimport { useEntryActions } from '../../../../common/hooks/useEntryAction';\n\nimport style from './QuickAddInline.module.scss';\n\ninterface QuickAddInlineProps {\n referenceEntryId: MaybeString;\n parentGroup: MaybeString;\n placement: 'before' | 'after';\n}\n\nexport default memo(QuickAddInline);\nfunction QuickAddInline({ referenceEntryId, parentGroup, placement }: QuickAddInlineProps) {\n const { addEntry } = useEntryActions();\n\n const handleAddEntry = (type: SupportedEntry) => {\n if (placement === 'before') {\n addEntry(\n { type, parent: type !== SupportedEntry.Group ? parentGroup : null },\n {\n before: referenceEntryId,\n },\n );\n } else {\n addEntry(\n { type, parent: type !== SupportedEntry.Group ? parentGroup : null },\n {\n lastEventId: referenceEntryId,\n after: referenceEntryId,\n },\n );\n }\n };\n\n return (\n <div className={style.quickAdd} data-testid='quick-add-inline'>\n <DropdownMenu\n items={[\n { type: 'item', icon: IoAdd, label: 'Add Event', onClick: () => handleAddEntry(SupportedEntry.Event) },\n { type: 'item', icon: IoAdd, label: 'Add Delay', onClick: () => handleAddEntry(SupportedEntry.Delay) },\n {\n type: 'item',\n icon: IoAdd,\n label: 'Add Milestone',\n onClick: () => handleAddEntry(SupportedEntry.Milestone),\n },\n {\n type: 'item',\n icon: IoAdd,\n label: 'Add Group',\n onClick: () => handleAddEntry(SupportedEntry.Group),\n disabled: parentGroup !== null,\n },\n ]}\n render={<IconButton size='small' variant='primary' className={style.addButton} />}\n >\n <IoAdd />\n </DropdownMenu>\n </div>\n );\n}\n","import { MouseEvent } from 'react';\n\nimport { useContextMenuStore } from '../../features/rundown/rundown-context-menu/RundownContextMenu';\nimport { DropdownMenuOption } from '../components/dropdown-menu/DropdownMenu';\n\nexport const useContextMenu = <T extends HTMLElement>(options: DropdownMenuOption[]) => {\n const setContextMenu = useContextMenuStore((state) => state.setContextMenu);\n\n const localCreateContextMenu = (contextMenuEvent: MouseEvent<T, globalThis.MouseEvent>) => {\n // prevent browser default context menu from showing up\n contextMenuEvent.preventDefault();\n\n const { pageX, pageY } = contextMenuEvent;\n return setContextMenu({ x: pageX, y: pageY }, options);\n };\n\n return [localCreateContextMenu];\n};\n","import { useCallback, useRef } from 'react';\n\nimport Input from '../../../common/components/input/input/Input';\nimport useReactiveTextInput from '../../../common/components/input/text-input/useReactiveTextInput';\nimport { useEntryActions } from '../../../common/hooks/useEntryAction';\nimport { cx } from '../../../common/utils/styleUtils';\n\nimport style from './TitleEditor.module.scss';\n\ninterface TitleEditorProps {\n title: string;\n entryId: string;\n placeholder: string;\n className?: string;\n}\n\nexport default function TitleEditor({ title, entryId, placeholder, className }: TitleEditorProps) {\n const { updateEntry } = useEntryActions();\n const ref = useRef<HTMLInputElement | null>(null);\n const submitCallback = useCallback(\n (text: string) => {\n if (text === title) {\n return;\n }\n\n const cleanVal = text.trim();\n updateEntry({ id: entryId, title: cleanVal });\n },\n [title, updateEntry, entryId],\n );\n\n const { value, onChange, onBlur, onKeyDown } = useReactiveTextInput(title, submitCallback, ref, {\n submitOnEnter: true,\n });\n\n const classes = cx([className, style.eventTitle, !value ? style.noTitle : null]);\n\n return (\n <Input\n data-testid='entry__title'\n variant='ghosted'\n fluid\n ref={ref}\n value={value}\n className={classes}\n placeholder={placeholder}\n onChange={onChange}\n onBlur={onBlur}\n onKeyDown={onKeyDown}\n />\n );\n}\n","import { MouseEvent, useRef } from 'react';\nimport {\n IoChevronDown,\n IoChevronUp,\n IoDuplicateOutline,\n IoFolderOpenOutline,\n IoReorderTwo,\n IoTrash,\n} from 'react-icons/io5';\nimport { useSortable } from '@dnd-kit/sortable';\nimport { CSS } from '@dnd-kit/utilities';\nimport { EntryId, OntimeGroup } from 'ontime-types';\nimport { MILLIS_PER_MINUTE } from 'ontime-utils';\n\nimport IconButton from '../../../common/components/buttons/IconButton';\nimport { useContextMenu } from '../../../common/hooks/useContextMenu';\nimport { useEntryActions } from '../../../common/hooks/useEntryAction';\nimport { getOffsetState } from '../../../common/utils/offset';\nimport { cx, getAccessibleColour } from '../../../common/utils/styleUtils';\nimport { formatDuration, formatTime } from '../../../common/utils/time';\nimport TitleEditor from '../common/TitleEditor';\nimport { canDrop } from '../rundown.utils';\nimport { useEventSelection } from '../useEventSelection';\n\nimport style from './RundownGroup.module.scss';\n\ninterface RundownGroupProps {\n data: OntimeGroup;\n hasCursor: boolean;\n collapsed: boolean;\n onCollapse: (collapsed: boolean, groupId: EntryId) => void;\n}\n\n//TODO: the group should maybe include a multiple day indicator\nexport default function RundownGroup({ data, hasCursor, collapsed, onCollapse }: RundownGroupProps) {\n const handleRef = useRef<null | HTMLSpanElement>(null);\n const { clone, ungroup, deleteEntry } = useEntryActions();\n const { selectedEvents, setSingleEntrySelection } = useEventSelection();\n\n const [onContextMenu] = useContextMenu<HTMLDivElement>([\n {\n type: 'item',\n label: 'Clone Group',\n icon: IoDuplicateOutline,\n onClick: () => clone(data.id),\n },\n {\n type: 'item',\n label: 'Ungroup',\n icon: IoFolderOpenOutline,\n onClick: () => ungroup(data.id),\n disabled: data.entries.length === 0,\n },\n { type: 'divider' },\n {\n type: 'item',\n label: 'Delete Group',\n icon: IoTrash,\n onClick: () => deleteEntry([data.id]),\n },\n ]);\n\n const {\n attributes: dragAttributes,\n listeners: dragListeners,\n setNodeRef,\n transform,\n transition,\n isDragging,\n isOver,\n over,\n } = useSortable({\n id: data.id,\n data: {\n type: 'group',\n },\n animateLayoutChanges: () => false,\n });\n\n const handleFocusClick = (event: MouseEvent) => {\n event.stopPropagation();\n\n // event.button === 2 is a right-click\n // disable selection if the user selected events and right clicks\n // so the context menu shows up\n if (selectedEvents.size > 1 && event.button === 2) {\n return;\n }\n\n // UI indexes are 1 based\n setSingleEntrySelection({ id: data.id });\n };\n\n const binderColours = data.colour && getAccessibleColour(data.colour);\n const isValidDrop = isDragging && over?.id && canDrop(over.data.current?.type, over.data.current?.parent);\n\n const [planOffset, planOffsetLabel] = (() => {\n if (data.targetDuration === null) {\n return [null, null];\n }\n\n const offset = data.duration - data.targetDuration;\n if (offset === 0) {\n return [null, 'under'];\n }\n const absOffset = Math.abs(offset);\n return [\n `${offset < 0 ? '-' : '+'}${formatDuration(absOffset, absOffset > 2 * MILLIS_PER_MINUTE)}`,\n getOffsetState(offset),\n ];\n })();\n\n const dragStyle = {\n zIndex: isDragging ? 2 : 'inherit',\n transform: CSS.Translate.toString(transform),\n transition,\n cursor: isOver ? (isValidDrop ? 'grabbing' : 'no-drop') : 'inherit',\n };\n\n return (\n <div\n className={cx([style.group, hasCursor && style.hasCursor, !collapsed && style.expanded])}\n ref={setNodeRef}\n onClick={handleFocusClick}\n onContextMenu={onContextMenu}\n style={{\n ...dragStyle,\n '--user-bg': data.colour || '#929292',\n }}\n data-testid='rundown-group'\n >\n <div className={style.binder} style={{ ...binderColours }} tabIndex={-1}>\n <span\n className={cx([style.drag, isDragging && style.isDragging, isDragging && !isValidDrop && style.notAllowed])}\n ref={handleRef}\n {...dragAttributes}\n {...dragListeners}\n >\n <IoReorderTwo />\n </span>\n </div>\n <div className={style.header}>\n <div className={style.titleRow}>\n <TitleEditor title={data.title} entryId={data.id} placeholder='Group title' />\n <IconButton aria-label='Collapse' variant='subtle-white' onClick={() => onCollapse(!collapsed, data.id)}>\n {collapsed ? <IoChevronUp /> : <IoChevronDown />}\n </IconButton>\n </div>\n <div className={style.metaRow}>\n <div className={style.metaEntry}>\n <div>Start</div>\n <div>{formatTime(data.timeStart)}</div>\n </div>\n <div className={style.metaEntry}>\n <div>End</div>\n <div>{formatTime(data.timeEnd)}</div>\n </div>\n <div className={style.metaEntry}>\n <div>Duration</div>\n {planOffset === null ? (\n <div className={cx([planOffsetLabel !== null && style[planOffsetLabel]])}>\n {formatDuration(data.duration)}\n </div>\n ) : (\n <div>\n <span className={style.strike}>{formatDuration(data.duration)}</span>\n <span className={cx([planOffsetLabel !== null && style[planOffsetLabel]])}>{planOffset}</span>\n </div>\n )}\n </div>\n <div className={style.metaEntry}>\n <div>Entries</div>\n <div>{data.entries.length}</div>\n </div>\n </div>\n </div>\n </div>\n );\n}\n","import { useSortable } from '@dnd-kit/sortable';\nimport { CSS } from '@dnd-kit/utilities';\n\nimport style from './RundownGroupEnd.module.scss';\n\ninterface RundownGroupEndProps {\n id: string;\n colour?: string;\n}\n\nexport default function RundownGroupEnd({ id, colour }: RundownGroupEndProps) {\n const {\n attributes: dragAttributes,\n listeners: dragListeners,\n setNodeRef,\n transform,\n transition,\n } = useSortable({\n id,\n data: {\n type: 'end-group',\n },\n animateLayoutChanges: () => false,\n disabled: true, // we do not want to drag end groups\n });\n\n const dragStyle = {\n transform: CSS.Transform.toString(transform),\n transition,\n };\n\n return (\n <div\n className={style.groupEnd}\n ref={setNodeRef}\n {...dragAttributes}\n {...dragListeners}\n style={{\n ...dragStyle,\n ...(colour ? { '--user-bg': colour } : {}),\n }}\n tabIndex={-1}\n />\n );\n}\n","import { IoAdd } from 'react-icons/io5';\nimport { SupportedEntry } from 'ontime-types';\n\nimport Button from '../../common/components/buttons/Button';\nimport * as Editor from '../../common/components/editor-utils/EditorUtils';\nimport Empty from '../../common/components/state/Empty';\n\nimport style from './Empty.module.scss';\n\ninterface RundownEmptyProps {\n handleAddNew: (type: SupportedEntry) => void;\n}\n\nexport default function RundownEmpty(props: RundownEmptyProps) {\n const { handleAddNew } = props;\n\n return (\n <div className={style.empty}>\n <Empty injectedStyles={{ marginTop: '5vh', marginBottom: '3rem' }} />\n <div className={style.inline}>\n <Button onClick={() => handleAddNew(SupportedEntry.Event)} variant='primary' size='large'>\n <IoAdd />\n Create Event\n </Button>\n\n <Editor.Separator />\n\n <Button onClick={() => handleAddNew(SupportedEntry.Group)} variant='primary' size='large'>\n <IoAdd /> Create Group\n </Button>\n </div>\n </div>\n );\n}\n","import { Fragment, lazy, useCallback, useEffect, useRef, useState } from 'react';\nimport { TbFlagFilled } from 'react-icons/tb';\nimport {\n closestCenter,\n DndContext,\n DragEndEvent,\n DragOverEvent,\n DragStartEvent,\n PointerSensor,\n useSensor,\n useSensors,\n} from '@dnd-kit/core';\nimport { SortableContext, verticalListSortingStrategy } from '@dnd-kit/sortable';\nimport { useHotkeys, useSessionStorage } from '@mantine/hooks';\nimport {\n type EntryId,\n type MaybeString,\n type Rundown,\n isOntimeEvent,\n isOntimeGroup,\n OntimeEntry,\n Playback,\n SupportedEntry,\n} from 'ontime-types';\nimport {\n getFirstNormal,\n getLastNormal,\n getNextGroupNormal,\n getNextNormal,\n getPreviousGroupNormal,\n getPreviousNormal,\n reorderArray,\n} from 'ontime-utils';\n\nimport { useEntryActions } from '../../common/hooks/useEntryAction';\nimport useFollowComponent from '../../common/hooks/useFollowComponent';\nimport { useRundownEditor } from '../../common/hooks/useSocket';\nimport { useEntryCopy } from '../../common/stores/entryCopyStore';\nimport { cloneEvent } from '../../common/utils/clone';\nimport { lastMetadataKey, RundownMetadataObject } from '../../common/utils/rundownMetadata';\nimport { AppMode, sessionKeys } from '../../ontimeConfig';\n\nimport QuickAddButtons from './entry-editor/quick-add-buttons/QuickAddButtons';\nimport QuickAddInline from './entry-editor/quick-add-cursor/QuickAddInline';\nimport RundownGroup from './rundown-group/RundownGroup';\nimport RundownGroupEnd from './rundown-group/RundownGroupEnd';\nimport { canDrop, makeSortableList } from './rundown.utils';\nimport RundownEmpty from './RundownEmpty';\nimport { useEventSelection } from './useEventSelection';\n\nimport style from './Rundown.module.scss';\n\nconst RundownEntry = lazy(() => import('./RundownEntry'));\n\ninterface RundownProps {\n data: Rundown;\n rundownMetadata: RundownMetadataObject;\n}\n\nexport default function Rundown({ data, rundownMetadata }: RundownProps) {\n const { order, entries, id } = data;\n // we create a copy of the rundown with a data structured aligned with what dnd-kit needs\n const featureData = useRundownEditor();\n const [sortableData, setSortableData] = useState<EntryId[]>(() => makeSortableList(order, entries));\n const [metadata, setMetadata] = useState(rundownMetadata);\n const [collapsedGroups, setCollapsedGroups] = useSessionStorage<EntryId[]>({\n // we ensure that this is unique to the rundown\n key: `rundown.${id}-editor-collapsed-groups`,\n defaultValue: [],\n });\n\n const { addEntry, deleteEntry, move, reorderEntry } = useEntryActions();\n\n const { entryCopyId, setEntryCopyId } = useEntryCopy();\n\n // cursor\n const [editorMode] = useSessionStorage<AppMode>({\n key: sessionKeys.editorMode,\n defaultValue: AppMode.Edit,\n });\n const { clearSelectedEvents, setSelectedEvents, cursor } = useEventSelection();\n\n const cursorRef = useRef<HTMLDivElement | null>(null);\n const scrollRef = useRef<HTMLDivElement | null>(null);\n useFollowComponent({\n followRef: cursorRef,\n scrollRef,\n doFollow: true,\n followTrigger: editorMode === AppMode.Edit ? cursor : featureData?.selectedEventId,\n });\n\n // DND KIT\n const sensors = useSensors(useSensor(PointerSensor, { activationConstraint: { distance: 10 } }));\n\n const deleteAtCursor = useCallback(\n (cursor: string | null) => {\n if (!cursor) return;\n const { entry, index } = getPreviousNormal(entries, order, cursor);\n deleteEntry([cursor]);\n if (entry && index !== null) {\n setSelectedEvents({ id: entry.id, selectMode: 'click', index });\n }\n },\n [entries, order, deleteEntry, setSelectedEvents],\n );\n\n const insertCopyAtId = useCallback(\n (atId: string | null, copyId: string | null, above = false) => {\n const adjustedCursor = above ? getPreviousNormal(entries, order, atId ?? '').entry?.id ?? null : atId;\n if (copyId === null) {\n // we cant clone without selection\n return;\n }\n const cloneEntry = entries[copyId];\n if (cloneEntry?.type === SupportedEntry.Event) {\n //if we don't have a cursor add the new event on top\n const newEvent = cloneEvent(cloneEntry);\n addEntry(newEvent, { after: adjustedCursor ?? undefined });\n }\n },\n [addEntry, order, entries],\n );\n\n /**\n * Add a new item referring to an existing one\n */\n const insertAtId = useCallback(\n (patch: Partial<OntimeEntry> & { type: SupportedEntry }, id: MaybeString, above = false) => {\n addEntry(patch, {\n after: id && !above ? id : undefined,\n before: id && above ? id : undefined,\n lastEventId: !above && id ? id : undefined,\n });\n },\n [addEntry],\n );\n\n const selectGroup = useCallback(\n (cursor: string | null, direction: 'up' | 'down') => {\n if (order.length < 1) {\n return;\n }\n let newCursor = cursor;\n if (cursor === null) {\n // there is no cursor, we select the first or last depending on direction\n const selected = direction === 'up' ? getLastNormal(entries, order) : getFirstNormal(entries, order);\n\n if (isOntimeGroup(selected)) {\n setSelectedEvents({ id: selected.id, selectMode: 'click', index: direction === 'up' ? order.length : 0 });\n return;\n }\n newCursor = selected?.id ?? null;\n }\n\n if (newCursor === null) {\n return;\n }\n\n // otherwise we select the next or previous\n const selected =\n direction === 'up'\n ? getPreviousGroupNormal(entries, order, newCursor)\n : getNextGroupNormal(entries, order, newCursor);\n\n if (selected.entry !== null && selected.index !== null) {\n setSelectedEvents({ id: selected.entry.id, selectMode: 'click', index: selected.index });\n }\n },\n [order, entries, setSelectedEvents],\n );\n\n const selectEntry = useCallback(\n (cursor: string | null, direction: 'up' | 'down') => {\n if (order.length < 1) {\n return;\n }\n\n if (cursor === null) {\n // there is no cursor, we select the first or last depending on direction if it exists\n const selected = direction === 'up' ? getLastNormal(entries, order) : getFirstNormal(entries, order);\n if (selected !== null) {\n setSelectedEvents({ id: selected.id, selectMode: 'click', index: direction === 'up' ? order.length : 0 });\n }\n return;\n }\n\n // otherwise we select the next or previous\n const selected =\n direction === 'up' ? getPreviousNormal(entries, order, cursor) : getNextNormal(entries, order, cursor);\n\n if (selected.entry !== null && selected.index !== null) {\n setSelectedEvents({ id: selected.entry.id, selectMode: 'click', index: selected.index });\n }\n },\n [order, entries, setSelectedEvents],\n );\n\n /**\n * Checks whether a group is collapsed\n */\n const getIsCollapsed = useCallback(\n (groupId: EntryId): boolean => {\n return Boolean(collapsedGroups.find((id) => id === groupId));\n },\n [collapsedGroups],\n );\n\n /**\n * Handles logic for collapsing groups\n */\n const handleCollapseGroup = useCallback(\n (collapsed: boolean, groupId: EntryId) => {\n setCollapsedGroups((prev) => {\n const isCollapsed = getIsCollapsed(groupId);\n if (collapsed && !isCollapsed) {\n const newSet = new Set(prev).add(groupId);\n return [...newSet];\n }\n if (!collapsed && isCollapsed) {\n return [...prev].filter((id) => id !== groupId);\n }\n return prev;\n });\n },\n [getIsCollapsed, setCollapsedGroups],\n );\n\n const moveEntry = useCallback(\n async (cursor: EntryId | null, direction: 'up' | 'down') => {\n if (cursor == null) {\n return;\n }\n\n const movedIntoGroupId = await move(cursor, direction);\n // if we are moving into a group, we need to make sure it is expanded\n if (movedIntoGroupId) {\n handleCollapseGroup(false, movedIntoGroupId);\n }\n },\n [handleCollapseGroup, move],\n );\n\n // shortcuts\n useHotkeys([\n ['alt + ArrowDown', () => selectEntry(cursor, 'down'), { preventDefault: true, usePhysicalKeys: true }],\n ['alt + ArrowUp', () => selectEntry(cursor, 'up'), { preventDefault: true, usePhysicalKeys: true }],\n\n ['alt + shift + ArrowDown', () => selectGroup(cursor, 'down'), { preventDefault: true, usePhysicalKeys: true }],\n ['alt + shift + ArrowUp', () => selectGroup(cursor, 'up'), { preventDefault: true, usePhysicalKeys: true }],\n\n ['alt + mod + ArrowDown', () => moveEntry(cursor, 'down'), { preventDefault: true, usePhysicalKeys: true }],\n ['alt + mod + ArrowUp', () => moveEntry(cursor, 'up'), { preventDefault: true, usePhysicalKeys: true }],\n\n ['Escape', () => clearSelectedEvents(), { preventDefault: true, usePhysicalKeys: true }],\n\n ['mod + Backspace', () => deleteAtCursor(cursor), { preventDefault: true, usePhysicalKeys: true }],\n\n [\n 'alt + E',\n () => insertAtId({ type: SupportedEntry.Event }, cursor),\n { preventDefault: true, usePhysicalKeys: true },\n ],\n [\n 'alt + shift + E',\n () => insertAtId({ type: SupportedEntry.Event }, cursor, true),\n { preventDefault: true, usePhysicalKeys: true },\n ],\n\n [\n 'alt + G',\n () => insertAtId({ type: SupportedEntry.Group }, cursor),\n { preventDefault: true, usePhysicalKeys: true },\n ],\n [\n 'alt + shift + G',\n () => insertAtId({ type: SupportedEntry.Group }, cursor, true),\n { preventDefault: true, usePhysicalKeys: true },\n ],\n\n [\n 'alt + D',\n () => insertAtId({ type: SupportedEntry.Delay }, cursor),\n { preventDefault: true, usePhysicalKeys: true },\n ],\n [\n 'alt + shift + D',\n () => insertAtId({ type: SupportedEntry.Delay }, cursor, true),\n { preventDefault: true, usePhysicalKeys: true },\n ],\n\n [\n 'alt + M',\n () => insertAtId({ type: SupportedEntry.Milestone }, cursor),\n { preventDefault: true, usePhysicalKeys: true },\n ],\n [\n 'alt + shift + M',\n () => insertAtId({ type: SupportedEntry.Milestone }, cursor, true),\n { preventDefault: true, usePhysicalKeys: true },\n ],\n\n ['mod + C', () => setEntryCopyId(cursor)],\n ['mod + V', () => insertCopyAtId(cursor, entryCopyId)],\n [\n 'mod + shift + V',\n () => insertCopyAtId(cursor, entryCopyId, true),\n { preventDefault: true, usePhysicalKeys: true },\n ],\n\n ['alt + backspace', () => deleteAtCursor(cursor), { preventDefault: true, usePhysicalKeys: true }],\n ]);\n\n // we copy the state from the store here\n // to workaround async updates on the drag mutations\n useEffect(() => {\n setSortableData(makeSortableList(order, entries));\n setMetadata(rundownMetadata);\n }, [order, entries, rundownMetadata]);\n\n // in run mode, we follow the playback selection and open groups as needed\n useEffect(() => {\n if (editorMode !== AppMode.Run || !featureData?.selectedEventId) {\n return;\n }\n const index = order.findIndex((id) => id === featureData.selectedEventId);\n // @ts-expect-error -- but we safely check if the parent property exists\n const maybeParent = entries[featureData.selectedEventId]?.parent;\n if (maybeParent) {\n // open the group\n setCollapsedGroups((prev) => [...prev].filter((id) => id !== maybeParent));\n }\n\n setSelectedEvents({ id: featureData.selectedEventId, selectMode: 'click', index });\n }, [editorMode, entries, featureData.selectedEventId, order, setCollapsedGroups, setSelectedEvents]);\n\n /**\n * On drag end, we reorder the events\n */\n const handleOnDragEnd = (event: DragEndEvent) => {\n const { active, over } = event;\n\n if (!over?.id || active.id === over.id) {\n return;\n }\n\n if (!active.data.current || !over.data.current) {\n return;\n }\n\n const fromIndex: number = active.data.current.sortable.index;\n const toIndex: number = over.data.current.sortable.index;\n let placement: 'before' | 'after' | 'insert' = fromIndex < toIndex ? 'after' : 'before';\n\n let destinationId = over.id as EntryId;\n const isDraggingGroup = active.data.current?.type === SupportedEntry.Group;\n\n // prevent dropping a group inside another\n if (\n isDraggingGroup &&\n !canDrop(over.data.current.type, over.data.current.parent, placement, getIsCollapsed(destinationId))\n ) {\n return;\n }\n\n /**\n * We need to specially handle the end-group\n * Dragging before a end-group will add the entry to the end of the group\n * Dragging after a end-group will add the event after the group itself\n * Dragging to the top of a group either place before first entry or if no entries do insert\n */\n if (destinationId.startsWith('end-')) {\n destinationId = destinationId.replace('end-', '');\n // if we are moving before the end, we use the insert operation\n if (placement === 'before') {\n placement = 'insert';\n }\n } else {\n const group = data.entries[destinationId];\n // if dragging into a group\n if (isOntimeGroup(group) && placement === 'after') {\n if (isDraggingGroup) {\n // ... and the dragged entry is a group, we know that the group is collapsed, because of the safe check canDrop from before\n // so we can safely push the dragged event after the group\n destinationId = group.id;\n } else if (group.entries.length === 0) {\n // ... and the group is entry, we insert\n destinationId = group.id;\n placement = 'insert';\n } else {\n // otherwise we add it to before the first group child\n destinationId = group.entries[0];\n placement = 'before';\n }\n }\n }\n\n // keep copy of the current state in case we need to revert\n const currentEntries = structuredClone(sortableData);\n // we keep a copy of the state as a hack to handle inconsistencies between dnd-kit and async store updates\n setSortableData((currentEntries) => {\n return reorderArray(currentEntries, fromIndex, toIndex);\n });\n reorderEntry(active.id as EntryId, destinationId, placement).catch((_) => {\n setSortableData(currentEntries);\n });\n };\n\n /**\n * When we drag a group, we force collapse it\n * This avoids strange scenarios like dropping a group inside itself\n */\n const collapseDraggedGroups = (event: DragStartEvent) => {\n const isGroup = event.active.data.current?.type === SupportedEntry.Group;\n if (isGroup) {\n handleCollapseGroup(true, event.active.id as EntryId);\n }\n };\n\n /**\n * When we drag over a group, we expand it if it is collapsed\n */\n const expandOverGroup = (event: DragOverEvent) => {\n // if we are dragging a group, the drop operation is invalid so we dont expand\n if (event.active.data.current?.type === 'group') {\n return;\n }\n if (event.over?.data.current?.type !== 'group') {\n return;\n }\n const groupId = event.over?.id as EntryId;\n const isCollapsed = getIsCollapsed(groupId);\n if (isCollapsed) {\n handleCollapseGroup(false, groupId);\n }\n };\n\n if (sortableData.length < 1) {\n return <RundownEmpty handleAddNew={(type: SupportedEntry) => addEntry({ type })} />;\n }\n\n // 1. gather presentation options\n const isEditMode = editorMode === AppMode.Edit;\n\n return (\n <div className={style.rundownContainer} ref={scrollRef} data-testid='rundown'>\n <DndContext\n onDragEnd={handleOnDragEnd}\n onDragStart={collapseDraggedGroups}\n onDragOver={expandOverGroup}\n sensors={sensors}\n collisionDetection={closestCenter}\n >\n <SortableContext items={sortableData} strategy={verticalListSortingStrategy}>\n <div className={style.list}>\n {isEditMode && <QuickAddButtons previousEventId={null} parentGroup={null} />}\n {sortableData.map((entryId, index) => {\n // the entry might be a pseudo end-group which does not generate metadata and should not be processed\n if (entryId.startsWith('end-')) {\n const parentId = entryId.split('end-')[1];\n const isGroupCollapsed = getIsCollapsed(parentId);\n const parentMetadata = metadata[parentId];\n\n if (isGroupCollapsed) {\n return null;\n }\n\n // if the previous element is selected, it will have its own QuickAddInline\n // we use thisId instead of previousEntryId because the end-group does not process\n // and it does not cause the reassignment of the iteration id to the previous entry\n return (\n <Fragment key={entryId}>\n {isEditMode && parentMetadata?.groupEntries === 0 && (\n <QuickAddButtons\n previousEventId={null}\n parentGroup={parentId}\n backgroundColor={parentMetadata?.groupColour}\n />\n )}\n <RundownGroupEnd key={entryId} id={entryId} colour={parentMetadata?.groupColour} />\n </Fragment>\n );\n }\n\n // we iterate through a stateful copy of order to make the dnd operations smoother\n // this means that this can be out of sync with order until the useEffect runs\n // instead of writing all the logic guards, we simply short circuit rendering here\n const entry = entries[entryId];\n const entryMetadata = metadata[entryId];\n if (!entry || !entryMetadata) return null;\n\n // if the entry has a parent, and it is collapsed, render nothing\n if (\n entry.type !== SupportedEntry.Group &&\n entryMetadata.groupId !== null &&\n getIsCollapsed(entryMetadata.groupId)\n ) {\n return null;\n }\n\n const isNext = featureData?.nextEventId === entry.id;\n const hasCursor = entry.id === cursor;\n\n /**\n * Outside a group, the value will be undefined\n * If the colour is empty string ''\n * ie: we are inside a group, but there is no defined colour\n * we default to $gray-500 #9d9d9d\n */\n const groupColour = entryMetadata.groupColour === '' ? '#9d9d9d' : entryMetadata.groupColour;\n\n const isFirst = index === 0;\n const isLast = entryId === order.at(-1);\n\n /**\n * We need to provide the parent ID for the QuickAdd components\n * This should be different depending on whether we are adding before or after an element\n * - when adding before, we need to avoid a group referencing itself as the parent\n * - when adding after, we can use the group ID directly to insert at the top of the group\n */\n\n const parentIdForBefore = entryMetadata.thisId !== entryMetadata.groupId ? entryMetadata.groupId : null;\n const parentIdForAfter = entryMetadata.groupId;\n\n return (\n <Fragment key={entry.id}>\n {/**\n * Before the entry\n * - edit mode only\n * - if there is a cursor\n * - if it is not the first entry (the buttons would be there)\n */}\n {isEditMode && hasCursor && !isFirst && (\n <QuickAddInline placement='before' referenceEntryId={entry.id} parentGroup={parentIdForBefore} />\n )}\n {isOntimeGroup(entry) ? (\n <RundownGroup\n data={entry}\n hasCursor={hasCursor}\n collapsed={getIsCollapsed(entry.id)}\n onCollapse={handleCollapseGroup}\n />\n ) : (\n <div\n className={style.entryWrapper}\n data-testid={`entry-${entryMetadata.eventIndex}`}\n style={groupColour ? { '--user-bg': groupColour } : {}}\n >\n {isOntimeEvent(entry) && (\n <div className={style.entryIndex}>\n {entry.flag && <TbFlagFilled className={style.flag} />}\n <div className={style.index}>{entryMetadata.eventIndex}</div>\n </div>\n )}\n <div className={style.entry} key={entry.id} ref={hasCursor ? cursorRef : undefined}>\n <RundownEntry\n type={entry.type}\n isPast={entryMetadata.isPast}\n eventIndex={entryMetadata.eventIndex}\n data={entry}\n loaded={entryMetadata.isLoaded}\n hasCursor={hasCursor}\n isNext={isNext}\n isNextDay={entryMetadata.isNextDay}\n playback={entryMetadata.isLoaded ? featureData.playback : undefined}\n isRolling={featureData.playback === Playback.Roll}\n totalGap={entryMetadata.totalGap}\n isLinkedToLoaded={entryMetadata.isLinkedToLoaded}\n />\n </div>\n </div>\n )}\n {/**\n * After the entry\n * - edit mode only\n * - if there is a cursor\n * - if it is not the last entry (the buttons would be there)\n * - if the entry is not the group header\n */}\n {isEditMode && hasCursor && !isLast && (\n <QuickAddInline placement='after' referenceEntryId={entry.id} parentGroup={parentIdForAfter} />\n )}\n </Fragment>\n );\n })}\n {isEditMode && (\n <QuickAddButtons\n previousEventId={metadata[lastMetadataKey]?.groupId ?? metadata[lastMetadataKey].thisId}\n parentGroup={null}\n />\n )}\n <div className={style.spacer} />\n </div>\n </SortableContext>\n </DndContext>\n </div>\n );\n}\n","import Empty from '../../common/components/state/Empty';\nimport { useRundownWithMetadata } from '../../common/hooks-query/useRundown';\n\nimport RundownHeader from './rundown-header/RundownHeader';\nimport RundownHeaderMobile from './rundown-header/RundownHeaderMobile';\nimport Rundown from './Rundown';\n\nimport styles from './Rundown.module.scss';\n\ninterface RundownWrapperProps {\n isSmallDevice?: boolean;\n}\n\nexport default function RundownWrapper({ isSmallDevice }: RundownWrapperProps) {\n const { data, status, rundownMetadata } = useRundownWithMetadata();\n\n return (\n <div className={styles.rundownWrapper}>\n {isSmallDevice ? <RundownHeaderMobile /> : <RundownHeader />}\n {status === 'success' && data && rundownMetadata ? (\n <Rundown data={data} rundownMetadata={rundownMetadata} />\n ) : (\n <Empty text='Connecting to server' />\n )}\n </div>\n );\n}\n","import { memo } from 'react';\nimport { useSessionStorage } from '@mantine/hooks';\n\nimport { Corner } from '../../common/components/editor-utils/EditorUtils';\nimport ErrorBoundary from '../../common/components/error-boundary/ErrorBoundary';\nimport ViewNavigationMenu from '../../common/components/navigation-menu/ViewNavigationMenu';\nimport ProtectRoute from '../../common/components/protect-route/ProtectRoute';\nimport { useIsSmallDevice } from '../../common/hooks/useIsSmallDevice';\nimport { handleLinks } from '../../common/utils/linkUtils';\nimport { cx } from '../../common/utils/styleUtils';\nimport { AppMode, sessionKeys } from '../../ontimeConfig';\n\nimport RundownEntryEditor from './entry-editor/RundownEntryEditor';\nimport FinderPlacement from './placements/FinderPlacement';\nimport { RundownContextMenu } from './rundown-context-menu/RundownContextMenu';\nimport RundownWrapper from './RundownWrapper';\n\nimport style from './RundownExport.module.scss';\n\nexport default memo(RundownExport);\n\nfunction RundownExport() {\n const isExtracted = window.location.pathname.includes('/rundown');\n const [editorMode] = useSessionStorage({\n key: sessionKeys.editorMode,\n defaultValue: AppMode.Edit,\n });\n const isSmallDevice = useIsSmallDevice();\n\n if (isSmallDevice && isExtracted) {\n return (\n <ProtectRoute permission='editor'>\n <div\n className={cx([style.rundownExport, style.extracted])}\n data-target='small-device'\n data-testid='panel-rundown'\n >\n <FinderPlacement />\n <ViewNavigationMenu suppressSettings />\n <div className={style.rundown}>\n <ErrorBoundary>\n <RundownContextMenu>\n <RundownWrapper isSmallDevice />\n </RundownContextMenu>\n </ErrorBoundary>\n </div>\n </div>\n </ProtectRoute>\n );\n }\n\n const hideSideBar = isExtracted && editorMode === 'run';\n\n return (\n <ProtectRoute permission='editor'>\n <div className={cx([style.rundownExport, isExtracted && style.extracted])} data-testid='panel-rundown'>\n <FinderPlacement />\n {isExtracted && <ViewNavigationMenu suppressSettings />}\n <div className={style.rundown}>\n <div className={style.list}>\n <ErrorBoundary>\n {!isExtracted && <Corner onClick={(event) => handleLinks('rundown', event)} />}\n <RundownContextMenu>\n <RundownWrapper />\n </RundownContextMenu>\n </ErrorBoundary>\n </div>\n {!hideSideBar && (\n <div className={style.side}>\n <ErrorBoundary>\n <RundownEntryEditor />\n </ErrorBoundary>\n </div>\n )}\n </div>\n </div>\n </ProtectRoute>\n );\n}\n"],"file":"assets/RundownExport-C6YhMGOC.js"}