vectis-ui 0.14.0 → 0.15.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (375) hide show
  1. package/dist/components/VAccordion/VAccordion.js.map +1 -1
  2. package/dist/components/VAccordion/VAccordion.vue_vue_type_script_setup_true_lang.js.map +1 -1
  3. package/dist/components/VAccordion/VAccordionItem.js.map +1 -1
  4. package/dist/components/VAccordion/VAccordionItem.vue_vue_type_script_setup_true_lang.js.map +1 -1
  5. package/dist/components/VAccordion/context.js.map +1 -1
  6. package/dist/components/VAlert/VAlert.js.map +1 -1
  7. package/dist/components/VAlert/VAlert.vue_vue_type_script_setup_true_lang.js.map +1 -1
  8. package/dist/components/VAvatar/VAvatar.js.map +1 -1
  9. package/dist/components/VAvatar/VAvatar.vue_vue_type_script_setup_true_lang.js.map +1 -1
  10. package/dist/components/VAvatar/VAvatarGroup.js.map +1 -1
  11. package/dist/components/VAvatar/VAvatarGroup.vue_vue_type_script_setup_true_lang.js.map +1 -1
  12. package/dist/components/VAvatar/context.js.map +1 -1
  13. package/dist/components/VBadge/VBadge.js.map +1 -1
  14. package/dist/components/VBadge/VBadge.vue_vue_type_script_setup_true_lang.js +1 -1
  15. package/dist/components/VBadge/VBadge.vue_vue_type_script_setup_true_lang.js.map +1 -1
  16. package/dist/components/VBreadcrumb/VBreadcrumb.js.map +1 -1
  17. package/dist/components/VBreadcrumb/VBreadcrumb.vue_vue_type_script_setup_true_lang.js.map +1 -1
  18. package/dist/components/VButton/VButton.js.map +1 -1
  19. package/dist/components/VButton/VButton.vue_vue_type_script_setup_true_lang.js.map +1 -1
  20. package/dist/components/VButton/VButtonGroup.js.map +1 -1
  21. package/dist/components/VButton/VButtonGroup.vue_vue_type_script_setup_true_lang.js.map +1 -1
  22. package/dist/components/VButton/context.js.map +1 -1
  23. package/dist/components/VCalendar/VCalendar.js.map +1 -1
  24. package/dist/components/VCalendar/VCalendar.vue_vue_type_script_setup_true_lang.js.map +1 -1
  25. package/dist/components/VCalendar/VCalendarEvent.js.map +1 -1
  26. package/dist/components/VCalendar/VCalendarEvent.vue_vue_type_script_setup_true_lang.js.map +1 -1
  27. package/dist/components/VCalendar/VCalendarMonth.js.map +1 -1
  28. package/dist/components/VCalendar/VCalendarMonth.vue_vue_type_script_setup_true_lang.js +5 -17
  29. package/dist/components/VCalendar/VCalendarMonth.vue_vue_type_script_setup_true_lang.js.map +1 -1
  30. package/dist/components/VCalendar/VCalendarTimeGrid.js.map +1 -1
  31. package/dist/components/VCalendar/VCalendarTimeGrid.vue_vue_type_script_setup_true_lang.js +19 -31
  32. package/dist/components/VCalendar/VCalendarTimeGrid.vue_vue_type_script_setup_true_lang.js.map +1 -1
  33. package/dist/components/VCalendar/VCalendarYear.js.map +1 -1
  34. package/dist/components/VCalendar/VCalendarYear.vue_vue_type_script_setup_true_lang.js.map +1 -1
  35. package/dist/components/VCalendar/color.js.map +1 -1
  36. package/dist/components/VCalendar/edgeStep.js +1 -5
  37. package/dist/components/VCalendar/edgeStep.js.map +1 -1
  38. package/dist/components/VCalendar/gesture.js +4 -12
  39. package/dist/components/VCalendar/gesture.js.map +1 -1
  40. package/dist/components/VCalendar/keyboard.js.map +1 -1
  41. package/dist/components/VCalendar/layout.js +8 -12
  42. package/dist/components/VCalendar/layout.js.map +1 -1
  43. package/dist/components/VCalendar/timeGrid.js +5 -5
  44. package/dist/components/VCalendar/timeGrid.js.map +1 -1
  45. package/dist/components/VCard/VCard.js.map +1 -1
  46. package/dist/components/VCard/VCard.vue_vue_type_script_setup_true_lang.js.map +1 -1
  47. package/dist/components/VCarousel/VCarousel.js.map +1 -1
  48. package/dist/components/VCarousel/VCarousel.vue_vue_type_script_setup_true_lang.js.map +1 -1
  49. package/dist/components/VCarousel/VCarouselItem.js.map +1 -1
  50. package/dist/components/VCarousel/VCarouselItem.vue_vue_type_script_setup_true_lang.js.map +1 -1
  51. package/dist/components/VCarousel/context.js.map +1 -1
  52. package/dist/components/VCheckbox/VCheckMark.js.map +1 -1
  53. package/dist/components/VCheckbox/VCheckMark.vue_vue_type_script_setup_true_lang.js.map +1 -1
  54. package/dist/components/VCheckbox/VCheckbox.js.map +1 -1
  55. package/dist/components/VCheckbox/VCheckbox.vue_vue_type_script_setup_true_lang.js.map +1 -1
  56. package/dist/components/VChip/VChip.js.map +1 -1
  57. package/dist/components/VChip/VChip.vue_vue_type_script_setup_true_lang.js.map +1 -1
  58. package/dist/components/VColorInput/VColorInput.js.map +1 -1
  59. package/dist/components/VColorInput/VColorInput.vue_vue_type_script_setup_true_lang.js +62 -62
  60. package/dist/components/VColorInput/VColorInput.vue_vue_type_script_setup_true_lang.js.map +1 -1
  61. package/dist/components/VColorPicker/VColorPicker.js.map +1 -1
  62. package/dist/components/VColorPicker/VColorPicker.vue_vue_type_script_setup_true_lang.js +1 -5
  63. package/dist/components/VColorPicker/VColorPicker.vue_vue_type_script_setup_true_lang.js.map +1 -1
  64. package/dist/components/VColorPicker/color.js.map +1 -1
  65. package/dist/components/VCombobox/VCombobox.js.map +1 -1
  66. package/dist/components/VCombobox/VCombobox.vue_vue_type_script_setup_true_lang.js +114 -122
  67. package/dist/components/VCombobox/VCombobox.vue_vue_type_script_setup_true_lang.js.map +1 -1
  68. package/dist/components/VCommandPalette/VCommandPalette.js.map +1 -1
  69. package/dist/components/VCommandPalette/VCommandPalette.vue_vue_type_script_setup_true_lang.js +0 -1
  70. package/dist/components/VCommandPalette/VCommandPalette.vue_vue_type_script_setup_true_lang.js.map +1 -1
  71. package/dist/components/VCommandPalette/VCommandPaletteItem.js.map +1 -1
  72. package/dist/components/VCommandPalette/VCommandPaletteItem.vue_vue_type_script_setup_true_lang.js +1 -5
  73. package/dist/components/VCommandPalette/VCommandPaletteItem.vue_vue_type_script_setup_true_lang.js.map +1 -1
  74. package/dist/components/VContextMenu/VContextMenu.js.map +1 -1
  75. package/dist/components/VContextMenu/VContextMenu.vue_vue_type_script_setup_true_lang.js +3 -5
  76. package/dist/components/VContextMenu/VContextMenu.vue_vue_type_script_setup_true_lang.js.map +1 -1
  77. package/dist/components/VDataTable/VDataTable.js.map +1 -1
  78. package/dist/components/VDataTable/VDataTable.vue_vue_type_script_setup_true_lang.js +1 -5
  79. package/dist/components/VDataTable/VDataTable.vue_vue_type_script_setup_true_lang.js.map +1 -1
  80. package/dist/components/VDateInput/VDateInput.js.map +1 -1
  81. package/dist/components/VDateInput/VDateInput.vue_vue_type_script_setup_true_lang.js +35 -35
  82. package/dist/components/VDateInput/VDateInput.vue_vue_type_script_setup_true_lang.js.map +1 -1
  83. package/dist/components/VDateInput/mask.js.map +1 -1
  84. package/dist/components/VDatePicker/VDatePicker.js.map +1 -1
  85. package/dist/components/VDatePicker/VDatePicker.vue_vue_type_script_setup_true_lang.js +2 -1
  86. package/dist/components/VDatePicker/VDatePicker.vue_vue_type_script_setup_true_lang.js.map +1 -1
  87. package/dist/components/VDatePicker/keyboard.js.map +1 -1
  88. package/dist/components/VDatePicker/names.js.map +1 -1
  89. package/dist/components/VDialog/VDialog.js.map +1 -1
  90. package/dist/components/VDialog/VDialog.vue_vue_type_script_setup_true_lang.js.map +1 -1
  91. package/dist/components/VDialog/VDialogAlert.js.map +1 -1
  92. package/dist/components/VDialog/VDialogAlert.vue_vue_type_script_setup_true_lang.js.map +1 -1
  93. package/dist/components/VDrawer/VDrawer.js.map +1 -1
  94. package/dist/components/VDrawer/VDrawer.vue_vue_type_script_setup_true_lang.js.map +1 -1
  95. package/dist/components/VEmptyState/VEmptyState.js.map +1 -1
  96. package/dist/components/VEmptyState/VEmptyState.vue_vue_type_script_setup_true_lang.js.map +1 -1
  97. package/dist/components/VField/VField.js.map +1 -1
  98. package/dist/components/VField/VField.vue_vue_type_script_setup_true_lang.js.map +1 -1
  99. package/dist/components/VField/VFieldAnnouncer.js.map +1 -1
  100. package/dist/components/VField/VFieldAnnouncer.vue_vue_type_script_setup_true_lang.js.map +1 -1
  101. package/dist/components/VField/VFieldMessage.js.map +1 -1
  102. package/dist/components/VField/VFieldMessage.vue_vue_type_script_setup_true_lang.js.map +1 -1
  103. package/dist/components/VFieldset/VFieldset.js.map +1 -1
  104. package/dist/components/VFieldset/VFieldset.vue_vue_type_script_setup_true_lang.js.map +1 -1
  105. package/dist/components/VFileInput/VFileInput.js.map +1 -1
  106. package/dist/components/VFileInput/VFileInput.vue_vue_type_script_setup_true_lang.js +85 -85
  107. package/dist/components/VFileInput/VFileInput.vue_vue_type_script_setup_true_lang.js.map +1 -1
  108. package/dist/components/VFileInput/truncate.js.map +1 -1
  109. package/dist/components/VFilePicker/VFilePicker.js.map +1 -1
  110. package/dist/components/VFilePicker/VFilePicker.vue_vue_type_script_setup_true_lang.js +1 -1
  111. package/dist/components/VFilePicker/VFilePicker.vue_vue_type_script_setup_true_lang.js.map +1 -1
  112. package/dist/components/VFilePicker/fileKind.js.map +1 -1
  113. package/dist/components/VHotkeys/VHotkeys.js.map +1 -1
  114. package/dist/components/VHotkeys/VHotkeys.vue_vue_type_script_setup_true_lang.js.map +1 -1
  115. package/dist/components/VHotkeys/platform.js +1 -1
  116. package/dist/components/VHotkeys/platform.js.map +1 -1
  117. package/dist/components/VHoverCard/VHoverCard.js.map +1 -1
  118. package/dist/components/VHoverCard/VHoverCard.vue_vue_type_script_setup_true_lang.js +2 -12
  119. package/dist/components/VHoverCard/VHoverCard.vue_vue_type_script_setup_true_lang.js.map +1 -1
  120. package/dist/components/VIcon/VIcon.js.map +1 -1
  121. package/dist/components/VIcon/VIcon.vue_vue_type_script_setup_true_lang.js.map +1 -1
  122. package/dist/components/VIcon/iconProps.js.map +1 -1
  123. package/dist/components/VIcon/icons/add.js.map +1 -1
  124. package/dist/components/VIcon/icons/arrow_downward.js.map +1 -1
  125. package/dist/components/VIcon/icons/arrow_downward_alt.js.map +1 -1
  126. package/dist/components/VIcon/icons/arrow_drop_down.js.map +1 -1
  127. package/dist/components/VIcon/icons/arrow_drop_up.js.map +1 -1
  128. package/dist/components/VIcon/icons/arrow_left_alt.js.map +1 -1
  129. package/dist/components/VIcon/icons/arrow_right_alt.js.map +1 -1
  130. package/dist/components/VIcon/icons/arrow_upward.js.map +1 -1
  131. package/dist/components/VIcon/icons/arrow_upward_alt.js.map +1 -1
  132. package/dist/components/VIcon/icons/attach_file.js.map +1 -1
  133. package/dist/components/VIcon/icons/audio_file.js.map +1 -1
  134. package/dist/components/VIcon/icons/calendar_today.js.map +1 -1
  135. package/dist/components/VIcon/icons/check.js.map +1 -1
  136. package/dist/components/VIcon/icons/check_circle.js.map +1 -1
  137. package/dist/components/VIcon/icons/chevron_left.js.map +1 -1
  138. package/dist/components/VIcon/icons/chevron_right.js.map +1 -1
  139. package/dist/components/VIcon/icons/close.js.map +1 -1
  140. package/dist/components/VIcon/icons/cloud_upload.js.map +1 -1
  141. package/dist/components/VIcon/icons/code.js.map +1 -1
  142. package/dist/components/VIcon/icons/colorize.js.map +1 -1
  143. package/dist/components/VIcon/icons/description.js.map +1 -1
  144. package/dist/components/VIcon/icons/error.js.map +1 -1
  145. package/dist/components/VIcon/icons/expand_less.js.map +1 -1
  146. package/dist/components/VIcon/icons/expand_more.js.map +1 -1
  147. package/dist/components/VIcon/icons/first_page.js.map +1 -1
  148. package/dist/components/VIcon/icons/folder_zip.js.map +1 -1
  149. package/dist/components/VIcon/icons/image.js.map +1 -1
  150. package/dist/components/VIcon/icons/inbox.js.map +1 -1
  151. package/dist/components/VIcon/icons/index.js.map +1 -1
  152. package/dist/components/VIcon/icons/info.js.map +1 -1
  153. package/dist/components/VIcon/icons/last_page.js.map +1 -1
  154. package/dist/components/VIcon/icons/more_horiz.js.map +1 -1
  155. package/dist/components/VIcon/icons/names.js.map +1 -1
  156. package/dist/components/VIcon/icons/notifications.js.map +1 -1
  157. package/dist/components/VIcon/icons/open_in_new.js.map +1 -1
  158. package/dist/components/VIcon/icons/picture_as_pdf.js.map +1 -1
  159. package/dist/components/VIcon/icons/priority_high.js.map +1 -1
  160. package/dist/components/VIcon/icons/remove.js.map +1 -1
  161. package/dist/components/VIcon/icons/schedule.js.map +1 -1
  162. package/dist/components/VIcon/icons/search.js.map +1 -1
  163. package/dist/components/VIcon/icons/search_off.js.map +1 -1
  164. package/dist/components/VIcon/icons/star.js.map +1 -1
  165. package/dist/components/VIcon/icons/swap_vert.js.map +1 -1
  166. package/dist/components/VIcon/icons/table_chart.js.map +1 -1
  167. package/dist/components/VIcon/icons/video_file.js.map +1 -1
  168. package/dist/components/VIcon/icons/viewBox.js.map +1 -1
  169. package/dist/components/VIcon/icons/warning.js.map +1 -1
  170. package/dist/components/VIcon/resolver.js.map +1 -1
  171. package/dist/components/VIconButton/VIconButton.js.map +1 -1
  172. package/dist/components/VIconButton/VIconButton.vue_vue_type_script_setup_true_lang.js.map +1 -1
  173. package/dist/components/VInput/VInput.js.map +1 -1
  174. package/dist/components/VInput/VInput.vue_vue_type_script_setup_true_lang.js +20 -20
  175. package/dist/components/VInput/VInput.vue_vue_type_script_setup_true_lang.js.map +1 -1
  176. package/dist/components/VInput/VInputGroup.js.map +1 -1
  177. package/dist/components/VInput/VInputGroup.vue_vue_type_script_setup_true_lang.js.map +1 -1
  178. package/dist/components/VInput/context.js.map +1 -1
  179. package/dist/components/VInputOTP/VInputOTP.js.map +1 -1
  180. package/dist/components/VInputOTP/VInputOTP.vue_vue_type_script_setup_true_lang.js +2 -8
  181. package/dist/components/VInputOTP/VInputOTP.vue_vue_type_script_setup_true_lang.js.map +1 -1
  182. package/dist/components/VLink/VLink.js.map +1 -1
  183. package/dist/components/VLink/VLink.vue_vue_type_script_setup_true_lang.js.map +1 -1
  184. package/dist/components/VListbox/VListboxChevron.js.map +1 -1
  185. package/dist/components/VListbox/VListboxChevron.vue_vue_type_script_setup_true_lang.js.map +1 -1
  186. package/dist/components/VListbox/VListboxGroup.js.map +1 -1
  187. package/dist/components/VListbox/VListboxGroup.vue_vue_type_script_setup_true_lang.js.map +1 -1
  188. package/dist/components/VListbox/VListboxOption.js.map +1 -1
  189. package/dist/components/VListbox/VListboxOption.vue_vue_type_script_setup_true_lang.js.map +1 -1
  190. package/dist/components/VListbox/VListboxPanel.js.map +1 -1
  191. package/dist/components/VListbox/VListboxPanel.vue_vue_type_script_setup_true_lang.js.map +1 -1
  192. package/dist/components/VListbox/VListboxSeparator.js.map +1 -1
  193. package/dist/components/VListbox/VListboxSeparator.vue_vue_type_script_setup_true_lang.js.map +1 -1
  194. package/dist/components/VListbox/VListboxValues.js.map +1 -1
  195. package/dist/components/VListbox/VListboxValues.vue_vue_type_script_setup_true_lang.js.map +1 -1
  196. package/dist/components/VMenu/VMenu.js.map +1 -1
  197. package/dist/components/VMenu/VMenu.vue_vue_type_script_setup_true_lang.js.map +1 -1
  198. package/dist/components/VMenu/VMenuGroup.js.map +1 -1
  199. package/dist/components/VMenu/VMenuGroup.vue_vue_type_script_setup_true_lang.js.map +1 -1
  200. package/dist/components/VMenu/VMenuItem.js.map +1 -1
  201. package/dist/components/VMenu/VMenuItem.vue_vue_type_script_setup_true_lang.js +6 -12
  202. package/dist/components/VMenu/VMenuItem.vue_vue_type_script_setup_true_lang.js.map +1 -1
  203. package/dist/components/VMenu/VMenuPanel.js.map +1 -1
  204. package/dist/components/VMenu/VMenuPanel.vue_vue_type_script_setup_true_lang.js +9 -10
  205. package/dist/components/VMenu/VMenuPanel.vue_vue_type_script_setup_true_lang.js.map +1 -1
  206. package/dist/components/VMenu/VMenuSeparator.js.map +1 -1
  207. package/dist/components/VMenu/VMenuSeparator.vue_vue_type_script_setup_true_lang.js.map +1 -1
  208. package/dist/components/VMenu/context.js.map +1 -1
  209. package/dist/components/VMeter/VMeter.js.map +1 -1
  210. package/dist/components/VMeter/VMeter.vue_vue_type_script_setup_true_lang.js.map +1 -1
  211. package/dist/components/VNumberInput/VNumberInput.js.map +1 -1
  212. package/dist/components/VNumberInput/VNumberInput.vue_vue_type_script_setup_true_lang.js +86 -85
  213. package/dist/components/VNumberInput/VNumberInput.vue_vue_type_script_setup_true_lang.js.map +1 -1
  214. package/dist/components/VNumberInput/number.js.map +1 -1
  215. package/dist/components/VPagination/VPagination.js.map +1 -1
  216. package/dist/components/VPagination/VPagination.vue_vue_type_script_setup_true_lang.js.map +1 -1
  217. package/dist/components/VPopover/VPopover.js.map +1 -1
  218. package/dist/components/VPopover/VPopover.vue_vue_type_script_setup_true_lang.js.map +1 -1
  219. package/dist/components/VProgressCircular/VProgressCircular.js.map +1 -1
  220. package/dist/components/VProgressCircular/VProgressCircular.vue_vue_type_script_setup_true_lang.js.map +1 -1
  221. package/dist/components/VProgressLinear/VProgressLinear.js.map +1 -1
  222. package/dist/components/VProgressLinear/VProgressLinear.vue_vue_type_script_setup_true_lang.js.map +1 -1
  223. package/dist/components/VRadio/VRadio.js.map +1 -1
  224. package/dist/components/VRadio/VRadio.vue_vue_type_script_setup_true_lang.js.map +1 -1
  225. package/dist/components/VRating/VRating.js.map +1 -1
  226. package/dist/components/VRating/VRating.vue_vue_type_script_setup_true_lang.js.map +1 -1
  227. package/dist/components/VResizable/VResizable.js.map +1 -1
  228. package/dist/components/VResizable/VResizable.vue_vue_type_script_setup_true_lang.js +8 -6
  229. package/dist/components/VResizable/VResizable.vue_vue_type_script_setup_true_lang.js.map +1 -1
  230. package/dist/components/VResizable/VResizablePanel.js.map +1 -1
  231. package/dist/components/VResizable/VResizablePanel.vue_vue_type_script_setup_true_lang.js.map +1 -1
  232. package/dist/components/VResizable/context.js.map +1 -1
  233. package/dist/components/VResizable/layout.js.map +1 -1
  234. package/dist/components/VSelect/VSelect.js.map +1 -1
  235. package/dist/components/VSelect/VSelect.vue_vue_type_script_setup_true_lang.js +124 -125
  236. package/dist/components/VSelect/VSelect.vue_vue_type_script_setup_true_lang.js.map +1 -1
  237. package/dist/components/VSeparator/VSeparator.js.map +1 -1
  238. package/dist/components/VSeparator/VSeparator.vue_vue_type_script_setup_true_lang.js.map +1 -1
  239. package/dist/components/VSideNavigation/VSideNavigation.js.map +1 -1
  240. package/dist/components/VSideNavigation/VSideNavigation.vue_vue_type_script_setup_true_lang.js +1 -1
  241. package/dist/components/VSideNavigation/VSideNavigation.vue_vue_type_script_setup_true_lang.js.map +1 -1
  242. package/dist/components/VSideNavigation/VSideNavigationGroup.js.map +1 -1
  243. package/dist/components/VSideNavigation/VSideNavigationGroup.vue_vue_type_script_setup_true_lang.js.map +1 -1
  244. package/dist/components/VSideNavigation/VSideNavigationItem.js.map +1 -1
  245. package/dist/components/VSideNavigation/VSideNavigationItem.vue_vue_type_script_setup_true_lang.js +1 -5
  246. package/dist/components/VSideNavigation/VSideNavigationItem.vue_vue_type_script_setup_true_lang.js.map +1 -1
  247. package/dist/components/VSideNavigation/VSideNavigationSeparator.js.map +1 -1
  248. package/dist/components/VSideNavigation/context.js.map +1 -1
  249. package/dist/components/VSkeletonLoader/VSkeletonLoader.js.map +1 -1
  250. package/dist/components/VSkeletonLoader/VSkeletonLoader.vue_vue_type_script_setup_true_lang.js.map +1 -1
  251. package/dist/components/VSlider/VSlider.js.map +1 -1
  252. package/dist/components/VSlider/VSlider.vue_vue_type_script_setup_true_lang.js +22 -22
  253. package/dist/components/VSlider/VSlider.vue_vue_type_script_setup_true_lang.js.map +1 -1
  254. package/dist/components/VSnackbar/VSnackbar.js.map +1 -1
  255. package/dist/components/VSnackbar/VSnackbar.vue_vue_type_script_setup_true_lang.js.map +1 -1
  256. package/dist/components/VSnackbar/state.js.map +1 -1
  257. package/dist/components/VSpinner/VSpinner.js.map +1 -1
  258. package/dist/components/VSpinner/VSpinner.vue_vue_type_script_setup_true_lang.js.map +1 -1
  259. package/dist/components/VSplitButton/VSplitButton.js.map +1 -1
  260. package/dist/components/VSplitButton/VSplitButton.vue_vue_type_script_setup_true_lang.js.map +1 -1
  261. package/dist/components/VStepper/VStepper.js.map +1 -1
  262. package/dist/components/VStepper/VStepper.vue_vue_type_script_setup_true_lang.js.map +1 -1
  263. package/dist/components/VSwitch/VSwitch.js.map +1 -1
  264. package/dist/components/VSwitch/VSwitch.vue_vue_type_script_setup_true_lang.js.map +1 -1
  265. package/dist/components/VTabs/VTab.js.map +1 -1
  266. package/dist/components/VTabs/VTab.vue_vue_type_script_setup_true_lang.js.map +1 -1
  267. package/dist/components/VTabs/VTabPanel.js.map +1 -1
  268. package/dist/components/VTabs/VTabPanel.vue_vue_type_script_setup_true_lang.js.map +1 -1
  269. package/dist/components/VTabs/VTabs.js.map +1 -1
  270. package/dist/components/VTabs/VTabs.vue_vue_type_script_setup_true_lang.js.map +1 -1
  271. package/dist/components/VTabs/context.js.map +1 -1
  272. package/dist/components/VTextarea/VTextarea.js.map +1 -1
  273. package/dist/components/VTextarea/VTextarea.vue_vue_type_script_setup_true_lang.js.map +1 -1
  274. package/dist/components/VTimeInput/VTimeInput.js.map +1 -1
  275. package/dist/components/VTimeInput/VTimeInput.vue_vue_type_script_setup_true_lang.js +45 -45
  276. package/dist/components/VTimeInput/VTimeInput.vue_vue_type_script_setup_true_lang.js.map +1 -1
  277. package/dist/components/VTimeInput/search.js.map +1 -1
  278. package/dist/components/VTimePicker/VTimePicker.js.map +1 -1
  279. package/dist/components/VTimePicker/VTimePicker.vue_vue_type_script_setup_true_lang.js +9 -9
  280. package/dist/components/VTimePicker/VTimePicker.vue_vue_type_script_setup_true_lang.js.map +1 -1
  281. package/dist/components/VTimePicker/limits.js.map +1 -1
  282. package/dist/components/VTimeline/VTimeline.js.map +1 -1
  283. package/dist/components/VTimeline/VTimeline.vue_vue_type_script_setup_true_lang.js.map +1 -1
  284. package/dist/components/VTimeline/VTimelineItem.js.map +1 -1
  285. package/dist/components/VTimeline/VTimelineItem.vue_vue_type_script_setup_true_lang.js.map +1 -1
  286. package/dist/components/VTimeline/context.js.map +1 -1
  287. package/dist/components/VTimeline/datetime.js.map +1 -1
  288. package/dist/components/VToast/VToast.js.map +1 -1
  289. package/dist/components/VToast/VToast.vue_vue_type_script_setup_true_lang.js.map +1 -1
  290. package/dist/components/VToast/VToaster.js.map +1 -1
  291. package/dist/components/VToast/VToaster.vue_vue_type_script_setup_true_lang.js +1 -1
  292. package/dist/components/VToast/VToaster.vue_vue_type_script_setup_true_lang.js.map +1 -1
  293. package/dist/components/VToast/state.js.map +1 -1
  294. package/dist/components/VToggle/VToggle.js.map +1 -1
  295. package/dist/components/VToggle/VToggle.vue_vue_type_script_setup_true_lang.js +1 -7
  296. package/dist/components/VToggle/VToggle.vue_vue_type_script_setup_true_lang.js.map +1 -1
  297. package/dist/components/VToggle/VToggleItem.js.map +1 -1
  298. package/dist/components/VToggle/VToggleItem.vue_vue_type_script_setup_true_lang.js.map +1 -1
  299. package/dist/components/VToggle/context.js.map +1 -1
  300. package/dist/components/VTooltip/VTooltip.js.map +1 -1
  301. package/dist/components/VTooltip/VTooltip.vue_vue_type_script_setup_true_lang.js.map +1 -1
  302. package/dist/components/VTreeView/VTreeView.js.map +1 -1
  303. package/dist/components/VTreeView/VTreeView.vue_vue_type_script_setup_true_lang.js +1 -5
  304. package/dist/components/VTreeView/VTreeView.vue_vue_type_script_setup_true_lang.js.map +1 -1
  305. package/dist/components/VTypography/VTypography.js.map +1 -1
  306. package/dist/components/VTypography/VTypography.vue_vue_type_script_setup_true_lang.js.map +1 -1
  307. package/dist/components/VVirtualList/VVirtualList.js.map +1 -1
  308. package/dist/components/VVirtualList/VVirtualList.vue_vue_type_script_setup_true_lang.js.map +1 -1
  309. package/dist/composables/useAriaLabel.js.map +1 -1
  310. package/dist/composables/useChoice.js.map +1 -1
  311. package/dist/composables/useClearable.js.map +1 -1
  312. package/dist/composables/useControlShape.js.map +1 -1
  313. package/dist/composables/useDebouncedSearch.js.map +1 -1
  314. package/dist/composables/useDetailsOpen.js.map +1 -1
  315. package/dist/composables/useEscapeDismiss.js.map +1 -1
  316. package/dist/composables/useFieldIds.js.map +1 -1
  317. package/dist/composables/useFieldPanel.js +3 -7
  318. package/dist/composables/useFieldPanel.js.map +1 -1
  319. package/dist/composables/useFileDrop.js.map +1 -1
  320. package/dist/composables/useFileField.js +2 -2
  321. package/dist/composables/useFileField.js.map +1 -1
  322. package/dist/composables/useFocusoutDismiss.js.map +1 -1
  323. package/dist/composables/useHotkeyListener.js.map +1 -1
  324. package/dist/composables/useIconClickHandlers.js.map +1 -1
  325. package/dist/composables/useInertLink.js.map +1 -1
  326. package/dist/composables/useInfiniteScroll.js +2 -2
  327. package/dist/composables/useInfiniteScroll.js.map +1 -1
  328. package/dist/composables/useListbox.js +3 -9
  329. package/dist/composables/useListbox.js.map +1 -1
  330. package/dist/composables/useLiveAnnouncer.js.map +1 -1
  331. package/dist/composables/useMaskedField.js +28 -48
  332. package/dist/composables/useMaskedField.js.map +1 -1
  333. package/dist/composables/useModalDialog.js +1 -1
  334. package/dist/composables/useModalDialog.js.map +1 -1
  335. package/dist/composables/usePopover.js +1 -1
  336. package/dist/composables/usePopover.js.map +1 -1
  337. package/dist/composables/useProgressValue.js.map +1 -1
  338. package/dist/composables/useRootAttrs.js.map +1 -1
  339. package/dist/composables/useSlotNodes.js.map +1 -1
  340. package/dist/composables/useTextLimit.js.map +1 -1
  341. package/dist/composables/useTimer.js.map +1 -1
  342. package/dist/composables/useTypeahead.js.map +1 -1
  343. package/dist/composables/useVirtualList.js.map +1 -1
  344. package/dist/i18n/en.js.map +1 -1
  345. package/dist/i18n/fr.js.map +1 -1
  346. package/dist/i18n/state.js.map +1 -1
  347. package/dist/tokens/css.js.map +1 -1
  348. package/dist/tokens/index.js.map +1 -1
  349. package/dist/tokens/primitives.js.map +1 -1
  350. package/dist/tokens/semantic.js.map +1 -1
  351. package/dist/tokens/themes/dark.js.map +1 -1
  352. package/dist/tokens/types.js.map +1 -1
  353. package/dist/utils/array.js.map +1 -1
  354. package/dist/utils/arrowNav.js.map +1 -1
  355. package/dist/utils/attrs.js.map +1 -1
  356. package/dist/utils/chip.js.map +1 -1
  357. package/dist/utils/clock.js +3 -1
  358. package/dist/utils/clock.js.map +1 -1
  359. package/dist/utils/css.js +1 -1
  360. package/dist/utils/css.js.map +1 -1
  361. package/dist/utils/date.js.map +1 -1
  362. package/dist/utils/direction.js.map +1 -1
  363. package/dist/utils/env.js.map +1 -1
  364. package/dist/utils/file.js +13 -31
  365. package/dist/utils/file.js.map +1 -1
  366. package/dist/utils/focus.js.map +1 -1
  367. package/dist/utils/hostWarns.js.map +1 -1
  368. package/dist/utils/ids.js.map +1 -1
  369. package/dist/utils/matcher.js.map +1 -1
  370. package/dist/utils/memo.js.map +1 -1
  371. package/dist/utils/number.js.map +1 -1
  372. package/dist/utils/text.js.map +1 -1
  373. package/dist/utils/time.js.map +1 -1
  374. package/dist/utils/vnode.js.map +1 -1
  375. package/package.json +19 -19
@@ -1 +1 @@
1
- {"version":3,"file":"VCalendarYear.vue_vue_type_script_setup_true_lang.js","names":[],"sources":["../../../src/components/VCalendar/VCalendarYear.vue"],"sourcesContent":["<script setup lang=\"ts\" generic=\"E extends CalendarEvent\">\n// @a11y @core\n/**\n * Use one roving date across the year so arrows cross month boundaries without adding hundreds\n * of Tab stops.\n */\nimport { computed, ref } from 'vue'\n\nimport { addDays, addMonths, compareISO, formatDateDisplay, parseISO } from '../../utils/date'\n\nimport { lastDayOf, monthWeeks, type MonthCell } from './layout'\nimport type { CalendarEvent } from './types'\n\nexport interface CalendarYearProps<T> {\n /** The first day of each month of the year on show. */\n months: string[]\n events: T[]\n locale: string\n /** Which weekdays are on show, so a mini-month drops the same columns as the others. */\n weekdays: number[]\n today: string | null\n label: string\n /** Turns the twelve month headings into disabled buttons, out of the tab order. */\n disabled?: boolean\n}\n\nconst props = defineProps<CalendarYearProps<E>>()\n\nconst emit = defineEmits<{\n /** A month was chosen, and is where the calendar should go next. */\n 'month-activate': [iso: string]\n}>()\n\n/** The days of the year on show that have something on them, worked out once for all twelve. */\nconst busyDays = computed(() => {\n const days = new Set<string>()\n const first = props.months[0]\n const lastMonth = props.months.at(-1)\n if (!first || !lastMonth) return days\n const last = addDays(addMonths(lastMonth, 1), -1)\n\n for (const event of props.events) {\n if (!parseISO(event.start) || !parseISO(event.end)) continue\n const from = compareISO(event.start, first) > 0 ? event.start : first\n const end = lastDayOf(event)\n const to = compareISO(end, last) < 0 ? end : last\n for (let iso = from; compareISO(iso, to) <= 0; iso = addDays(iso, 1)) days.add(iso)\n }\n return days\n})\n\n/*\n * The twelve grids, built once per change of anchor or weekdays, and their day numbers once per\n * locale: the adjacent days repeat across neighbouring months, and none of it depends on the\n * events. The busy marks are laid over both in `yearMonths` below.\n */\nconst grids = computed(() => props.months.map((month) => monthWeeks(month, props.weekdays)))\n\nconst dayNumbers = computed(() => {\n const map = new Map<string, string>()\n for (const weeks of grids.value) {\n for (const week of weeks) {\n for (const cell of week) {\n if (!map.has(cell.iso))\n map.set(cell.iso, formatDateDisplay(cell.iso, props.locale, { day: 'numeric' }))\n }\n }\n }\n return map\n})\n\n/** One square of a mini-month, with everything the template writes on it already settled. */\ninterface YearDay {\n iso: string\n adjacent: MonthCell['adjacent']\n number: string\n /** Only a day of the month itself is marked: a neighbour's day belongs to its own month. */\n busy: boolean\n}\n\n/** What the template draws, each month with its name, its squares and how many of them are busy. */\nconst yearMonths = computed(() => {\n const busy = busyDays.value\n const numbers = dayNumbers.value\n return props.months.map((month, index) => {\n let busyCount = 0\n const weeks: YearDay[][] = (grids.value[index] ?? []).map((week) =>\n week.map((cell) => {\n const isBusy = cell.adjacent === null && busy.has(cell.iso)\n if (isBusy) busyCount++\n return {\n iso: cell.iso,\n adjacent: cell.adjacent,\n number: numbers.get(cell.iso) ?? '',\n busy: isBusy,\n }\n }),\n )\n return {\n month,\n name: formatDateDisplay(month, props.locale, { month: 'long' }),\n weeks,\n busyCount,\n }\n })\n})\n\nconst rootEl = ref<HTMLElement | null>(null)\n\ndefineExpose({\n /** Brings the focus onto the first month, the view's first control. */\n focus: (options?: FocusOptions) =>\n rootEl.value?.querySelector<HTMLButtonElement>('.v-calendar-year-title')?.focus(options),\n /** Nothing to scroll to in a year view. */\n scrollToMinutes: () => {},\n})\n</script>\n\n<template>\n <div ref=\"rootEl\" class=\"v-calendar-year\" role=\"group\" :aria-label=\"label\">\n <section v-for=\"entry in yearMonths\" :key=\"entry.month\" class=\"v-calendar-year-month\">\n <button\n type=\"button\"\n class=\"v-calendar-button v-calendar-year-title\"\n :disabled=\"disabled\"\n @click=\"emit('month-activate', entry.month)\"\n >\n {{ entry.name }}\n <!--\n The count is part of the button's own text, so a month that has something on it says\n so in its accessible name; which makes the days below safe to hide from the\n accessibility tree.\n -->\n <span v-if=\"entry.busyCount > 0\" class=\"v-calendar-year-count\">\n {{ entry.busyCount }}\n </span>\n </button>\n\n <div\n class=\"v-calendar-year-grid\"\n aria-hidden=\"true\"\n :style=\"{ '--calendar-columns': String(weekdays.length) }\"\n >\n <template v-for=\"(week, row) in entry.weeks\" :key=\"row\">\n <span\n v-for=\"day in week\"\n :key=\"day.iso\"\n class=\"v-calendar-year-day\"\n :class=\"{ 'v-calendar-today': day.iso === today }\"\n :data-adjacent=\"day.adjacent ?? undefined\"\n :data-busy=\"day.busy ? '' : undefined\"\n >\n {{ day.number }}\n </span>\n </template>\n </div>\n </section>\n </div>\n</template>\n\n<style>\n@layer vectis.components {\n .v-calendar-year {\n display: grid;\n grid-template-columns: repeat(\n auto-fill,\n minmax(var(--vectis-control-size-calendar-year-month), 1fr)\n );\n gap: var(--vectis-space-4);\n padding: var(--vectis-space-3);\n }\n\n .v-calendar-year-month {\n display: flex;\n flex-direction: column;\n gap: var(--vectis-space-2);\n }\n\n .v-calendar-year-title {\n display: flex;\n align-items: center;\n justify-content: space-between;\n gap: var(--vectis-space-2);\n padding: var(--vectis-space-1) var(--vectis-space-2);\n border-radius: var(--vectis-radius-interactive);\n color: var(--vectis-color-text);\n font-size: var(--vectis-text-heading-4-size);\n font-weight: var(--vectis-text-heading-4-weight);\n text-align: start;\n text-transform: capitalize;\n }\n\n .v-calendar-year-title:hover {\n background: var(--calendar-hover-bg);\n }\n\n .v-calendar-year-count {\n display: flex;\n align-items: center;\n justify-content: center;\n flex: none;\n min-inline-size: var(--vectis-control-size-calendar-year-cell);\n padding-inline: var(--vectis-space-1);\n border-radius: var(--vectis-radius-pill);\n background: var(--vectis-color-accent-surface);\n color: var(--vectis-color-accent-text);\n font-size: var(--vectis-text-caption-size);\n font-weight: var(--vectis-font-weight-medium);\n }\n\n /* As many columns as weekdays on show, set inline by the template exactly as the month\n view does. Written as a literal 7, a calendar showing the working week alone wrapped\n every five-day row of `monthWeeks` onto the next line. */\n .v-calendar-year-grid {\n display: grid;\n grid-template-columns: repeat(var(--calendar-columns), 1fr);\n gap: 1px;\n }\n\n .v-calendar-year-day {\n display: flex;\n align-items: center;\n justify-content: center;\n aspect-ratio: 1;\n min-inline-size: var(--vectis-control-size-calendar-year-cell);\n border-radius: var(--vectis-radius-pill);\n font-size: var(--vectis-text-caption-size);\n }\n\n /*\n * Both states are written DISJOINT from today rather than below it. Today is very often also\n * busy, and its paint is `.v-calendar-today`, in VCalendar's sheet: at equal specificity the\n * winner between two sheets is whichever the consumer's bundler emitted last, and losing that\n * draw paints today as an ordinary busy day; the one square a reader looks for first, quietly\n * indistinguishable.\n */\n .v-calendar-year-day[data-adjacent]:not(.v-calendar-today) {\n color: var(--vectis-color-text-subtle);\n }\n\n /*\n * A busy day is RINGED rather than dotted: at this size a dot would be about one pixel, and\n * it would be drawn as a background, which Windows forced-colors flattens away; where a\n * border keeps a colour of its own. The tint is a second, redundant signal for anyone the\n * ring alone is too fine for; and the ring alone is what today keeps, being painted over the\n * tint.\n */\n .v-calendar-year-day[data-busy] {\n border: 1px solid var(--vectis-color-accent-border);\n }\n\n .v-calendar-year-day[data-busy]:not(.v-calendar-today) {\n background: var(--vectis-color-accent-surface);\n color: var(--vectis-color-accent-text);\n }\n}\n</style>\n"],"mappings":"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"}
1
+ {"version":3,"file":"VCalendarYear.vue_vue_type_script_setup_true_lang.js","names":["_openBlock","_createElementBlock","_Fragment","_renderList","_createElementVNode","_createTextVNode","_toDisplayString","_createCommentVNode","_normalizeStyle","_normalizeClass","_hoisted_1","_hoisted_2","_hoisted_3","_hoisted_4","VCalendarYear_vue_vue_type_script_setup_true_lang_default","__expose","__emit","props","__props","emit","busyDays","computed","days","first","lastMonth","last","addDays","addMonths","event","parseISO","from","compareISO","end","lastDayOf","to","iso","grids","monthWeeks","month","dayNumbers","map","weeks","week","cell","formatDateDisplay","yearMonths","busy","numbers","busyCount","index","isBusy","rootEl","ref","options","openBlock","createElementBlock","Fragment","renderList","entry","createElementVNode","createTextVNode","toDisplayString","createCommentVNode","normalizeStyle","row","day","normalizeClass"],"sources":["../../../src/components/VCalendar/VCalendarYear.vue"],"sourcesContent":["<script setup lang=\"ts\" generic=\"E extends CalendarEvent\">\n// @a11y @core\n/**\n * Use one roving date across the year so arrows cross month boundaries without adding hundreds\n * of Tab stops.\n */\nimport { computed, ref } from 'vue'\n\nimport { addDays, addMonths, compareISO, formatDateDisplay, parseISO } from '../../utils/date'\n\nimport { lastDayOf, monthWeeks, type MonthCell } from './layout'\nimport type { CalendarEvent } from './types'\n\nexport interface CalendarYearProps<T> {\n /** The first day of each month of the year on show. */\n months: string[]\n events: T[]\n locale: string\n /** Which weekdays are on show, so a mini-month drops the same columns as the others. */\n weekdays: number[]\n today: string | null\n label: string\n /** Turns the twelve month headings into disabled buttons, out of the tab order. */\n disabled?: boolean\n}\n\nconst props = defineProps<CalendarYearProps<E>>()\n\nconst emit = defineEmits<{\n /** A month was chosen, and is where the calendar should go next. */\n 'month-activate': [iso: string]\n}>()\n\n/** The days of the year on show that have something on them, worked out once for all twelve. */\nconst busyDays = computed(() => {\n const days = new Set<string>()\n const first = props.months[0]\n const lastMonth = props.months.at(-1)\n if (!first || !lastMonth) return days\n const last = addDays(addMonths(lastMonth, 1), -1)\n\n for (const event of props.events) {\n if (!parseISO(event.start) || !parseISO(event.end)) continue\n const from = compareISO(event.start, first) > 0 ? event.start : first\n const end = lastDayOf(event)\n const to = compareISO(end, last) < 0 ? end : last\n for (let iso = from; compareISO(iso, to) <= 0; iso = addDays(iso, 1)) days.add(iso)\n }\n return days\n})\n\n/*\n * The twelve grids, built once per change of anchor or weekdays, and their day numbers once per\n * locale: the adjacent days repeat across neighbouring months, and none of it depends on the\n * events. The busy marks are laid over both in `yearMonths` below.\n */\nconst grids = computed(() => props.months.map((month) => monthWeeks(month, props.weekdays)))\n\nconst dayNumbers = computed(() => {\n const map = new Map<string, string>()\n for (const weeks of grids.value) {\n for (const week of weeks) {\n for (const cell of week) {\n if (!map.has(cell.iso))\n map.set(cell.iso, formatDateDisplay(cell.iso, props.locale, { day: 'numeric' }))\n }\n }\n }\n return map\n})\n\n/** One square of a mini-month, with everything the template writes on it already settled. */\ninterface YearDay {\n iso: string\n adjacent: MonthCell['adjacent']\n number: string\n /** Only a day of the month itself is marked: a neighbour's day belongs to its own month. */\n busy: boolean\n}\n\n/** What the template draws, each month with its name, its squares and how many of them are busy. */\nconst yearMonths = computed(() => {\n const busy = busyDays.value\n const numbers = dayNumbers.value\n return props.months.map((month, index) => {\n let busyCount = 0\n const weeks: YearDay[][] = (grids.value[index] ?? []).map((week) =>\n week.map((cell) => {\n const isBusy = cell.adjacent === null && busy.has(cell.iso)\n if (isBusy) busyCount++\n return {\n iso: cell.iso,\n adjacent: cell.adjacent,\n number: numbers.get(cell.iso) ?? '',\n busy: isBusy,\n }\n }),\n )\n return {\n month,\n name: formatDateDisplay(month, props.locale, { month: 'long' }),\n weeks,\n busyCount,\n }\n })\n})\n\nconst rootEl = ref<HTMLElement | null>(null)\n\ndefineExpose({\n /** Brings the focus onto the first month, the view's first control. */\n focus: (options?: FocusOptions) =>\n rootEl.value?.querySelector<HTMLButtonElement>('.v-calendar-year-title')?.focus(options),\n /** Nothing to scroll to in a year view. */\n scrollToMinutes: () => {},\n})\n</script>\n\n<template>\n <div ref=\"rootEl\" class=\"v-calendar-year\" role=\"group\" :aria-label=\"label\">\n <section v-for=\"entry in yearMonths\" :key=\"entry.month\" class=\"v-calendar-year-month\">\n <button\n type=\"button\"\n class=\"v-calendar-button v-calendar-year-title\"\n :disabled=\"disabled\"\n @click=\"emit('month-activate', entry.month)\"\n >\n {{ entry.name }}\n <!--\n The count is part of the button's own text, so a month that has something on it says\n so in its accessible name; which makes the days below safe to hide from the\n accessibility tree.\n -->\n <span v-if=\"entry.busyCount > 0\" class=\"v-calendar-year-count\">\n {{ entry.busyCount }}\n </span>\n </button>\n\n <div\n class=\"v-calendar-year-grid\"\n aria-hidden=\"true\"\n :style=\"{ '--calendar-columns': String(weekdays.length) }\"\n >\n <template v-for=\"(week, row) in entry.weeks\" :key=\"row\">\n <span\n v-for=\"day in week\"\n :key=\"day.iso\"\n class=\"v-calendar-year-day\"\n :class=\"{ 'v-calendar-today': day.iso === today }\"\n :data-adjacent=\"day.adjacent ?? undefined\"\n :data-busy=\"day.busy ? '' : undefined\"\n >\n {{ day.number }}\n </span>\n </template>\n </div>\n </section>\n </div>\n</template>\n\n<style>\n@layer vectis.components {\n .v-calendar-year {\n display: grid;\n grid-template-columns: repeat(\n auto-fill,\n minmax(var(--vectis-control-size-calendar-year-month), 1fr)\n );\n gap: var(--vectis-space-4);\n padding: var(--vectis-space-3);\n }\n\n .v-calendar-year-month {\n display: flex;\n flex-direction: column;\n gap: var(--vectis-space-2);\n }\n\n .v-calendar-year-title {\n display: flex;\n align-items: center;\n justify-content: space-between;\n gap: var(--vectis-space-2);\n padding: var(--vectis-space-1) var(--vectis-space-2);\n border-radius: var(--vectis-radius-interactive);\n color: var(--vectis-color-text);\n font-size: var(--vectis-text-heading-4-size);\n font-weight: var(--vectis-text-heading-4-weight);\n text-align: start;\n text-transform: capitalize;\n }\n\n .v-calendar-year-title:hover {\n background: var(--calendar-hover-bg);\n }\n\n .v-calendar-year-count {\n display: flex;\n align-items: center;\n justify-content: center;\n flex: none;\n min-inline-size: var(--vectis-control-size-calendar-year-cell);\n padding-inline: var(--vectis-space-1);\n border-radius: var(--vectis-radius-pill);\n background: var(--vectis-color-accent-surface);\n color: var(--vectis-color-accent-text);\n font-size: var(--vectis-text-caption-size);\n font-weight: var(--vectis-font-weight-medium);\n }\n\n /* As many columns as weekdays on show, set inline by the template exactly as the month\n view does. Written as a literal 7, a calendar showing the working week alone wrapped\n every five-day row of `monthWeeks` onto the next line. */\n .v-calendar-year-grid {\n display: grid;\n grid-template-columns: repeat(var(--calendar-columns), 1fr);\n gap: 1px;\n }\n\n .v-calendar-year-day {\n display: flex;\n align-items: center;\n justify-content: center;\n aspect-ratio: 1;\n min-inline-size: var(--vectis-control-size-calendar-year-cell);\n border-radius: var(--vectis-radius-pill);\n font-size: var(--vectis-text-caption-size);\n }\n\n /*\n * Both states are written DISJOINT from today rather than below it. Today is very often also\n * busy, and its paint is `.v-calendar-today`, in VCalendar's sheet: at equal specificity the\n * winner between two sheets is whichever the consumer's bundler emitted last, and losing that\n * draw paints today as an ordinary busy day; the one square a reader looks for first, quietly\n * indistinguishable.\n */\n .v-calendar-year-day[data-adjacent]:not(.v-calendar-today) {\n color: var(--vectis-color-text-subtle);\n }\n\n /*\n * A busy day is RINGED rather than dotted: at this size a dot would be about one pixel, and\n * it would be drawn as a background, which Windows forced-colors flattens away; where a\n * border keeps a colour of its own. The tint is a second, redundant signal for anyone the\n * ring alone is too fine for; and the ring alone is what today keeps, being painted over the\n * tint.\n */\n .v-calendar-year-day[data-busy] {\n border: 1px solid var(--vectis-color-accent-border);\n }\n\n .v-calendar-year-day[data-busy]:not(.v-calendar-today) {\n background: var(--vectis-color-accent-surface);\n color: var(--vectis-color-accent-text);\n }\n}\n</style>\n"],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"color.js","names":[],"sources":["../../../src/components/VCalendar/color.ts"],"sourcesContent":["// @core\n/** Derive event hues deterministically so server and browser render the same colours. */\nimport type { CalendarEventId } from './types'\n\n/**\n * It is not decoration, and removing it makes the palette collapse without any error to show\n * for it. A plain string hash of `\"1\"`, `\"2\"`, `\"3\"` produces three CONSECUTIVE numbers, so\n * taking them modulo 360 directly would give three hues one degree apart: a calendar whose\n * events are numbered in order would come out entirely one colour.\n */\nconst GOLDEN = 2654435761\n\n/** How many degrees the colour wheel has. */\nconst HUES = 360\n\n/** A stable hue, 0 to 359, for an event that carries no colour of its own. */\nexport function hueOf(id: CalendarEventId): number {\n const text = String(id)\n let hash = 5381\n for (let i = 0; i < text.length; i++) {\n // `| 0` keeps the running value a 32-bit integer, so the result cannot depend on how\n // far a double drifts once the multiplications exceed the exactly representable range.\n hash = ((hash << 5) + hash + text.charCodeAt(i)) | 0\n }\n return Math.abs(Math.imul(hash, GOLDEN) >>> 0) % HUES\n}\n"],"mappings":"AAgBA,SAAgB,EAAM,GAA6B;CACjD,IAAM,IAAO,OAAO,CAAE,GAClB,IAAO;CACX,KAAK,IAAI,IAAI,GAAG,IAAI,EAAK,QAAQ,KAG/B,KAAS,KAAQ,KAAK,IAAO,EAAK,WAAW,CAAC,IAAK;CAErD,OAAO,KAAK,IAAI,KAAK,KAAK,GAAM,UAAM,MAAM,CAAC,IAAI;AACnD"}
1
+ {"version":3,"file":"color.js","names":["hueOf","text","id","hash","i"],"sources":["../../../src/components/VCalendar/color.ts"],"sourcesContent":["// @core\n/** Derive event hues deterministically so server and browser render the same colours. */\nimport type { CalendarEventId } from './types'\n\n/**\n * It is not decoration, and removing it makes the palette collapse without any error to show\n * for it. A plain string hash of `\"1\"`, `\"2\"`, `\"3\"` produces three CONSECUTIVE numbers, so\n * taking them modulo 360 directly would give three hues one degree apart: a calendar whose\n * events are numbered in order would come out entirely one colour.\n */\nconst GOLDEN = 2654435761\n\n/** How many degrees the colour wheel has. */\nconst HUES = 360\n\n/** A stable hue, 0 to 359, for an event that carries no colour of its own. */\nexport function hueOf(id: CalendarEventId): number {\n const text = String(id)\n let hash = 5381\n for (let i = 0; i < text.length; i++) {\n // `| 0` keeps the running value a 32-bit integer, so the result cannot depend on how\n // far a double drifts once the multiplications exceed the exactly representable range.\n hash = ((hash << 5) + hash + text.charCodeAt(i)) | 0\n }\n return Math.abs(Math.imul(hash, GOLDEN) >>> 0) % HUES\n}\n"],"mappings":"AAgBA,SAAgBA,EAAM,GAA6B;CACjD,IAAMC,IAAO,OAAOC,CAAE,GAClBC,IAAO;CACX,KAAK,IAAIC,IAAI,GAAGA,IAAIH,EAAK,QAAQ,KAG/B,KAASE,KAAQ,KAAKA,IAAOF,EAAK,WAAWG,CAAC,IAAK;CAErD,OAAO,KAAK,IAAI,KAAK,KAAKD,GAAM,UAAM,MAAM,CAAC,IAAI;AACnD"}
@@ -13,11 +13,7 @@ function r(r, i) {
13
13
  o.value = e;
14
14
  let n = () => {
15
15
  let t = i();
16
- if (t <= 0) {
17
- o.value = null;
18
- return;
19
- }
20
- r(e), a.start(n, t);
16
+ t <= 0 ? o.value = null : (r(e), a.start(n, t));
21
17
  };
22
18
  a.start(n, t);
23
19
  }
@@ -1 +1 @@
1
- {"version":3,"file":"edgeStep.js","names":[],"sources":["../../../src/components/VCalendar/edgeStep.ts"],"sourcesContent":["// @core\n/** Page while a drag rests at a view edge, allowing moves beyond the currently visible period. */\nimport { readonly, ref, type Ref } from 'vue'\n\nimport { useTimer } from '../../composables/useTimer'\n\n/** How long a dragged event rests against an edge before the calendar pages, in milliseconds. */\nexport const EDGE_STEP_DELAY = 800\n\n/**\n * This number is the twin of `--vectis-control-size-calendar-edge`, the width of the band the\n * stylesheet lights up to show that paging is coming. They describe the same strip: moving one\n * without the other leaves the calendar paging from somewhere other than where it said it\n * would, with nothing anywhere to point at it.\n */\nexport const EDGE_BAND = 48\n\n/** Which way the calendar is being asked to go: back a period, or on to the next. */\nexport type EdgeDirection = -1 | 1\n\nexport interface EdgeStep {\n /**\n * Told on every pointer move which edge the drag is now against, or nothing when it is\n * back in the middle.\n */\n watchEdge(edge: EdgeDirection | null): void\n /** Drops whatever is armed, without stepping. */\n cancel(): void\n /** The edge currently counting down, for the stylesheet to show. */\n pending: Readonly<Ref<EdgeDirection | null>>\n}\n\n/**\n * `delay` is a getter rather than a number so a consumer can turn paging off mid-drag by\n * binding it to zero: the reactive-prop-as-switch shape VCarousel's `autoplay` uses.\n */\nexport function useEdgeStep(\n onStep: (direction: EdgeDirection) => void,\n delay: () => number,\n): EdgeStep {\n const timer = useTimer()\n const pending = ref<EdgeDirection | null>(null)\n\n function cancel() {\n timer.cancel()\n pending.value = null\n }\n\n function watchEdge(edge: EdgeDirection | null) {\n // Staying on the same edge must leave the armed timer alone. Re-arming on every move would\n // mean a pointer trembling by a pixel never reached the delay at all, and the calendar\n // would simply never page for anyone with an unsteady hand.\n if (edge === pending.value) return\n\n cancel()\n if (edge === null) return\n\n /*\n * The guard is what stops this recursing, not a convenience. `useTimer` runs a delay of\n * zero or less synchronously by design, and the callback below re-arms itself, so arming at\n * zero would call it again and again until the stack gave out.\n */\n const wait = delay()\n if (wait <= 0) return\n\n pending.value = edge\n\n const fire = () => {\n // The delay is asked again on every step: bound to zero while the drag is held against\n // the edge, paging stops before the next page rather than after it.\n const next = delay()\n if (next <= 0) {\n pending.value = null\n return\n }\n onStep(edge)\n timer.start(fire, next)\n }\n timer.start(fire, wait)\n }\n\n return { watchEdge, cancel, pending: readonly(pending) }\n}\n"],"mappings":";;;AAoCA,SAAgB,EACd,GACA,GACU;CACV,IAAM,IAAQ,EAAS,GACjB,IAAU,EAA0B,IAAI;CAE9C,SAAS,IAAS;EAEhB,AADA,EAAM,OAAO,GACb,EAAQ,QAAQ;CAClB;CAEA,SAAS,EAAU,GAA4B;EAO7C,IAHI,MAAS,EAAQ,UAErB,EAAO,GACH,MAAS,OAAM;EAOnB,IAAM,IAAO,EAAM;EACnB,IAAI,KAAQ,GAAG;EAEf,EAAQ,QAAQ;EAEhB,IAAM,UAAa;GAGjB,IAAM,IAAO,EAAM;GACnB,IAAI,KAAQ,GAAG;IACb,EAAQ,QAAQ;IAChB;GACF;GAEA,AADA,EAAO,CAAI,GACX,EAAM,MAAM,GAAM,CAAI;EACxB;EACA,EAAM,MAAM,GAAM,CAAI;CACxB;CAEA,OAAO;EAAE;EAAW;EAAQ,SAAS,EAAS,CAAO;CAAE;AACzD"}
1
+ {"version":3,"file":"edgeStep.js","names":["useEdgeStep","timer","useTimer","pending","ref","cancel","watchEdge","edge","wait","delay","fire","next","onStep","readonly"],"sources":["../../../src/components/VCalendar/edgeStep.ts"],"sourcesContent":["// @core\n/** Page while a drag rests at a view edge, allowing moves beyond the currently visible period. */\nimport { readonly, ref, type Ref } from 'vue'\n\nimport { useTimer } from '../../composables/useTimer'\n\n/** How long a dragged event rests against an edge before the calendar pages, in milliseconds. */\nexport const EDGE_STEP_DELAY = 800\n\n/**\n * This number is the twin of `--vectis-control-size-calendar-edge`, the width of the band the\n * stylesheet lights up to show that paging is coming. They describe the same strip: moving one\n * without the other leaves the calendar paging from somewhere other than where it said it\n * would, with nothing anywhere to point at it.\n */\nexport const EDGE_BAND = 48\n\n/** Which way the calendar is being asked to go: back a period, or on to the next. */\nexport type EdgeDirection = -1 | 1\n\nexport interface EdgeStep {\n /**\n * Told on every pointer move which edge the drag is now against, or nothing when it is\n * back in the middle.\n */\n watchEdge(edge: EdgeDirection | null): void\n /** Drops whatever is armed, without stepping. */\n cancel(): void\n /** The edge currently counting down, for the stylesheet to show. */\n pending: Readonly<Ref<EdgeDirection | null>>\n}\n\n/**\n * `delay` is a getter rather than a number so a consumer can turn paging off mid-drag by\n * binding it to zero: the reactive-prop-as-switch shape VCarousel's `autoplay` uses.\n */\nexport function useEdgeStep(\n onStep: (direction: EdgeDirection) => void,\n delay: () => number,\n): EdgeStep {\n const timer = useTimer()\n const pending = ref<EdgeDirection | null>(null)\n\n function cancel() {\n timer.cancel()\n pending.value = null\n }\n\n function watchEdge(edge: EdgeDirection | null) {\n // Staying on the same edge must leave the armed timer alone. Re-arming on every move would\n // mean a pointer trembling by a pixel never reached the delay at all, and the calendar\n // would simply never page for anyone with an unsteady hand.\n if (edge === pending.value) return\n\n cancel()\n if (edge === null) return\n\n /*\n * The guard is what stops this recursing, not a convenience. `useTimer` runs a delay of\n * zero or less synchronously by design, and the callback below re-arms itself, so arming at\n * zero would call it again and again until the stack gave out.\n */\n const wait = delay()\n if (wait <= 0) return\n\n pending.value = edge\n\n const fire = () => {\n // The delay is asked again on every step: bound to zero while the drag is held against\n // the edge, paging stops before the next page rather than after it.\n const next = delay()\n if (next <= 0) {\n pending.value = null\n return\n }\n onStep(edge)\n timer.start(fire, next)\n }\n timer.start(fire, wait)\n }\n\n return { watchEdge, cancel, pending: readonly(pending) }\n}\n"],"mappings":";;;AAoCA,SAAgBA,EACd,GACA,GACU;CACV,IAAMC,IAAQC,EAAS,GACjBC,IAAUC,EAA0B,IAAI;CAE9C,SAASC,IAAS;EAEhB,AADAJ,EAAM,OAAO,GACb,EAAQ,QAAQ;CAClB;CAEA,SAASK,EAAU,GAA4B;EAO7C,IAHIC,MAASJ,EAAQ,UAErBE,EAAO,GACHE,MAAS,OAAM;EAOnB,IAAMC,IAAOC,EAAM;EACnB,IAAID,KAAQ,GAAG;EAEf,EAAQ,QAAQD;EAEhB,IAAMG,UAAa;GAGjB,IAAMC,IAAOF,EAAM;GACnB,AAAIE,KAAQ,IACV,EAAQ,QAAQ,QAGlBC,EAAOL,CAAI,GACXN,EAAM,MAAMS,GAAMC,CAAI;EACxB;EACA,EAAM,MAAMD,GAAMF,CAAI;CACxB;CAEA,OAAO;EAAE;EAAW;EAAQ,SAASK,EAASV,CAAO;CAAE;AACzD"}
@@ -94,7 +94,7 @@ function _(u) {
94
94
  }
95
95
  function F(e) {
96
96
  let t = v.value;
97
- !t || t.pointerId !== e.pointerId || (v.value = null, C = t.moved, A(), !t.outside && (u.onLetGo?.(t) || t.moved && u.onDrop(t)));
97
+ t && t.pointerId === e.pointerId && (v.value = null, C = t.moved, A(), !t.outside && (u.onLetGo?.(t) || t.moved && u.onDrop(t)));
98
98
  }
99
99
  function I(e) {
100
100
  v.value?.pointerId === e.pointerId && L();
@@ -104,7 +104,7 @@ function _(u) {
104
104
  }
105
105
  function R(e) {
106
106
  let t = v.value;
107
- !t || t.pointerId !== e.pointerId || t.moved || L();
107
+ t && t.pointerId === e.pointerId && !t.moved && L();
108
108
  }
109
109
  l(u.layout, () => {
110
110
  let e = v.value;
@@ -131,18 +131,10 @@ function _(u) {
131
131
  let t = o.kind === "grab" ? u.grab(n) : null;
132
132
  if (!t) return;
133
133
  e.preventDefault(), j(t), u.announce(_.value.calendar.grabbed);
134
- return;
135
- }
136
- if (e.preventDefault(), o.kind === "grabMove" || o.kind === "grabResize") {
134
+ } else if (e.preventDefault(), o.kind === "grabMove" || o.kind === "grabResize") {
137
135
  if (!u.onGrabStep(i, o, n)) return;
138
136
  i.moved = !0, z(i.id);
139
- return;
140
- }
141
- if (o.kind === "activate") {
142
- v.value = null, i.moved && u.onDrop(i), u.announce(_.value.calendar.dropped), z(i.id);
143
- return;
144
- }
145
- o.kind === "cancel" && (T(), z(i.id));
137
+ } else o.kind === "activate" ? (v.value = null, i.moved && u.onDrop(i), u.announce(_.value.calendar.dropped), z(i.id)) : o.kind === "cancel" && (T(), z(i.id));
146
138
  }
147
139
  }
148
140
  function U(e) {
@@ -1 +1 @@
1
- {"version":3,"file":"gesture.js","names":[],"sources":["../../../src/components/VCalendar/gesture.ts"],"sourcesContent":["// @keyboard @a11y @core\n/**\n * Share pointer and keyboard editing gestures across month and time-grid views; each view\n * supplies its own cell geometry.\n */\nimport { computed, nextTick, ref, watch } from 'vue'\nimport type { Ref } from 'vue'\n\nimport { isRtl as isElementRtl } from '../../utils/direction'\n\nimport { useMessages } from '../../i18n/state'\n\nimport { EDGE_BAND, useEdgeStep } from './edgeStep'\nimport { calendarIntent, type CalendarIntent } from './keyboard'\nimport { DRAG_THRESHOLD, inlineEdgeAt, pointWithin, type GridGeometry } from './layout'\nimport type { CalendarEvent, CalendarEventId, CalendarEventTimes } from './types'\n\n/**\n * The prefix marking the copy an event leaves behind at its old place while it is being\n * dragged.\n */\nconst GHOST_PREFIX = '__vectis-calendar-ghost__'\n\n/**\n * The id the ghost of a dragged event carries. It has to DIFFER from the event's own, or the\n * two would collide in every map the layout keys by id and only one would ever be drawn.\n */\nconst ghostIdOf = (id: CalendarEventId) => `${GHOST_PREFIX}${id}`\n/** The dragged event's own id, read back off its ghost's. */\nconst originalIdOf = (id: CalendarEventId) => String(id).slice(GHOST_PREFIX.length)\nconst isGhostId = (id: CalendarEventId) => String(id).startsWith(GHOST_PREFIX)\n\n/** The id a card belongs to, read back off the DOM. */\nfunction cardIdOf(card: HTMLElement, has: (id: CalendarEventId) => boolean) {\n const raw = card.dataset.eventId ?? ''\n return has(raw) ? raw : Number(raw)\n}\n\n/**\n * `inlineStart` is the edge the first column starts at, which is the RIGHT one in a\n * right-to-left page.\n */\nexport function gridGeometryOf(rect: DOMRect, columns: number, rtl: boolean): GridGeometry {\n return {\n top: rect.top,\n height: rect.height,\n inlineStart: rtl ? rect.right : rect.left,\n inlineSize: rect.width,\n columns,\n }\n}\n\n/** The state every gesture carries, whatever each grid adds to it. */\nexport interface GestureBase {\n id: CalendarEventId\n /**\n * Where the event was when the gesture began. Every pointer frame is computed from this and\n * never from the frame before it, so a long drag cannot accumulate rounding drift.\n */\n origin: CalendarEventTimes\n /** What the card shows right now. The model is not touched until the gesture ends. */\n preview: CalendarEventTimes\n /** The pointer holding the gesture, or null for a keyboard grab. */\n pointerId: number | null\n originX: number\n originY: number\n /**\n * Where the pointer last was. Two things move the calendar UNDER a still pointer: paging at\n * an edge, and auto-scrolling. Each has to work out afresh what the pointer is now over.\n */\n lastX: number\n lastY: number\n /** Whether it moved past the threshold, which separates a drag from a click. */\n moved: boolean\n /**\n * Whether the pointer is off the calendar altogether: over the toolbar, or over the page\n * beside it. A KEYBOARD grab can never set it, and structurally rather than by a guard:\n * `onPointermove` is the only writer, and it returns on the id mismatch first: a grab's\n * `pointerId` is null, which no real pointer's id ever equals.\n */\n outside: boolean\n /**\n * The reading direction, read once when the gesture begins. It cannot change under a live\n * drag, and asking the document on every frame costs a style resolution each time.\n */\n rtl: boolean\n}\n\n/** What a grid hands over to start a gesture; the rest is filled in here. */\nexport type GestureInit<G extends GestureBase> = Omit<\n G,\n 'preview' | 'lastX' | 'lastY' | 'moved' | 'outside' | 'rtl'\n>\n\n/**\n * A gesture held by the KEYBOARD rather than by a pointer: grabbed with Space, and waiting for\n * the arrows to move it.\n */\nconst isGrabbed = (state: GestureBase | null) => state !== null && state.pointerId === null\n\n/** The two intents that move a grabbed event, which only a grid can turn into times. */\nexport type GrabStep = Extract<CalendarIntent, { kind: 'grabMove' | 'grabResize' }>\n\nexport interface CalendarGestureOptions<E extends CalendarEvent, G extends GestureBase> {\n /** Every event as it is currently drawn, the ghost's original among them. */\n events: () => readonly E[]\n /** The event drawn under an id, for the handlers. */\n eventOf: (id: CalendarEventId) => E | undefined\n rootEl: Ref<HTMLElement | null>\n /** The element the pointer is captured on once a press travels. */\n captureEl: Ref<HTMLElement | null>\n /** The box the cells occupy, which points and edges are read against. */\n measureEl: Ref<HTMLElement | null>\n /** How many columns that box is divided into. */\n columns: () => number\n /** Whether events may be moved at all. */\n editable: () => boolean\n /** The node every card points at to say how it can be moved. */\n hintId: () => string\n /** The step a grabbed event moves by, handed to the keyboard table. */\n slotMinutes: () => number\n edgeStepDelay: () => number\n /** Whatever the grid's cells are made of, so paging under a still pointer re-places the card. */\n layout: () => unknown\n /** Works out where the gesture's event belongs from the pointer's last position. */\n applyPoint: (state: G, rect: DOMRect) => void\n /** Called on every pointer move past the threshold, after the edge watch, with both rects. */\n onEdges?: (state: G, rootRect: DOMRect | undefined) => void\n /** Everything else a gesture leaves running, dropped on every path out of one. */\n onRelease?: () => void\n /**\n * A pointer gesture let go inside the calendar. Returns true when the grid has answered it\n * itself, such as a slot drawn out, and nothing is left to drop.\n */\n onLetGo?: (state: G) => boolean\n /** A gesture that moved, committed: the grid reports the new times. */\n onDrop: (state: G) => void\n /** What a keyboard grab of this event starts, or null when it cannot be grabbed. */\n grab: (item: E) => GestureInit<G> | null\n /** Applies one arrow step to a grabbed event. Returns false when the step means nothing here. */\n onGrabStep: (state: G, step: GrabStep, item: E) => boolean\n step: (direction: -1 | 1) => void\n announce: (message: string) => void\n}\n\nexport function useCalendarGesture<E extends CalendarEvent, G extends GestureBase>(\n options: CalendarGestureOptions<E, G>,\n) {\n const m = useMessages()\n const gesture = ref<G | null>(null) as Ref<G | null>\n\n /** True while a card is being held by the keyboard rather than dragged by a pointer. */\n const grabbing = computed(() => isGrabbed(gesture.value))\n\n const isRtl = () => isElementRtl(options.measureEl.value)\n\n /**\n * The echo of where the gestured event began, so the reader can see what they are moving it\n * FROM. A press that has not travelled yet produces none, or a click would flash a second\n * card over the first.\n */\n const ghostEvent = computed<E | null>(() => {\n const state = gesture.value\n if (!state?.moved) return null\n const original = options.events().find((event) => event.id === state.id)\n return original ? ({ ...original, ...state.origin, id: ghostIdOf(state.id) } as E) : null\n })\n\n /** A list with the gestured event moved to wherever it is now, plus its echo. */\n function withPreview(events: readonly E[]): E[] {\n const state = gesture.value\n if (!state) return [...events]\n const moving = events.map((event) =>\n event.id === state.id ? ({ ...event, ...state.preview } as E) : event,\n )\n return ghostEvent.value ? [...moving, ghostEvent.value] : moving\n }\n\n /**\n * Set click suppression on pointerup, not pointercancel; clear it before every press guard\n * and keyboard activation. Captured releases may never send their click to an event card.\n */\n let dragged = false\n\n /** Closes the books on the previous gesture. */\n function endLastGesture() {\n dragged = false\n if (grabbing.value) revertGrab()\n }\n\n /** Puts a keyboard grab back where it was taken from, writing nothing, and says so. */\n function revertGrab() {\n const state = gesture.value\n if (!state) return\n gesture.value = null\n options.announce(m.value.calendar.reverted)\n return state\n }\n\n /**\n * A keyboard grab ends when the focus moves on to something else, the toolbar or another\n * control.\n */\n function onFocusout(event: FocusEvent) {\n const state = gesture.value\n const next = event.relatedTarget as HTMLElement | null\n if (!grabbing.value || !state || !next) return\n const card = next.closest<HTMLElement>('.v-calendar-event')\n if (card && card.dataset.eventId === String(state.id)) return\n revertGrab()\n }\n\n /** Whether the gesture that just ended actually moved; asking lowers the flag. */\n function consumeDrag() {\n const was = dragged\n dragged = false\n return was\n }\n\n const edge = useEdgeStep(options.step, options.edgeStepDelay)\n\n /** Which edge is counting down, as the attribute the stylesheet reads. */\n const edgeCue = computed(() =>\n edge.pending.value === -1 ? 'start' : edge.pending.value === 1 ? 'end' : undefined,\n )\n\n function release() {\n edge.cancel()\n options.onRelease?.()\n }\n\n /** Starts a gesture. */\n function start(init: GestureInit<G>, rtl = isRtl()) {\n gesture.value = {\n ...init,\n preview: { ...init.origin },\n lastX: init.originX,\n lastY: init.originY,\n moved: false,\n outside: false,\n rtl,\n } as G\n }\n\n /**\n * Called when the press crosses the drag threshold, never at the press. The browser sends the\n * `click` that follows a captured `pointerup` to the CAPTURE element, so a press captured at\n * once reaches the scroller instead of the card or the cell under it: clicking an event would\n * open nothing and clicking an empty slot would report nothing, on every calendar whose\n * events can be moved or drawn.\n */\n function capture(pointerId: number) {\n // @fallback\n /*\n * Synthetic pointer events may not have a capturable pointer; allow the gesture to continue\n * within the element if capture fails.\n */\n try {\n options.captureEl.value?.setPointerCapture(pointerId)\n } catch {\n /* Synthetic pointers cannot be captured. */\n }\n }\n\n function reapply(state: G) {\n const rect = options.measureEl.value?.getBoundingClientRect()\n if (rect) options.applyPoint(state, rect)\n }\n\n function onPointermove(event: PointerEvent) {\n const state = gesture.value\n if (!state || state.pointerId !== event.pointerId) return\n\n state.lastX = event.clientX\n state.lastY = event.clientY\n\n // Below the threshold nothing has happened yet. That is what keeps a click a click: the\n // hand's tremor during a press would otherwise register as a one-pixel drag.\n if (\n !state.moved &&\n Math.abs(event.clientX - state.originX) < DRAG_THRESHOLD &&\n Math.abs(event.clientY - state.originY) < DRAG_THRESHOLD\n ) {\n return\n }\n\n if (!state.moved) capture(event.pointerId)\n state.moved = true\n const rootRect = options.rootEl.value?.getBoundingClientRect()\n const rect = options.measureEl.value?.getBoundingClientRect()\n\n /*\n * Neither the placement nor the edge watch below is gated on it, and neither may become so.\n * The card must keep following the pointer while it is out, which makes coming back in\n * seamless, and paging must keep running, pushing past the edge being how one crosses into\n * the next period.\n */\n state.outside = rootRect ? !pointWithin({ x: state.lastX, y: state.lastY }, rootRect) : false\n\n if (!rect) return\n options.applyPoint(state, rect)\n edge.watchEdge(\n inlineEdgeAt(\n state.lastX,\n gridGeometryOf(rect, options.columns(), state.rtl),\n EDGE_BAND,\n state.rtl,\n ),\n )\n options.onEdges?.(state, rootRect)\n }\n\n function onPointerup(event: PointerEvent) {\n const state = gesture.value\n if (!state || state.pointerId !== event.pointerId) return\n gesture.value = null\n dragged = state.moved\n release()\n\n /*\n * Nothing is announced: the pointer says nothing on a SUCCESSFUL drop either; `grabbed`,\n * `dropped` and `reverted` belong to the keyboard grab, which has no pointer to show where\n * the event went.\n */\n if (state.outside) return\n if (options.onLetGo?.(state)) return\n // A press that never travelled is an ordinary click, which the button's own click event is\n // about to report. Writing anything here would move an event nobody dragged.\n if (state.moved) options.onDrop(state)\n }\n\n /*\n * The gesture was taken away; a system gesture, a context menu, the page starting to scroll.\n * Nothing is written and nothing is announced: the card goes back to where the model still\n * says it is.\n */\n function onPointercancel(event: PointerEvent) {\n // Another pointer's cancel, a second finger starting to pan, is not this gesture's. A\n // keyboard grab carries no pointer id, so no cancel can end it either.\n if (gesture.value?.pointerId !== event.pointerId) return\n abandon()\n }\n\n function abandon() {\n gesture.value = null\n release()\n }\n\n /*\n * Its `pointerup` then lands outside and never reaches the bindings, so without this the\n * gesture would outlive the press: a mouse keeps the same pointer id, and bringing it back\n * over the calendar with the button up would pick the event up and carry it. A captured\n * pointer never leaves, so a real drag is untouched.\n */\n function onPointerleave(event: PointerEvent) {\n const state = gesture.value\n if (!state || state.pointerId !== event.pointerId || state.moved) return\n abandon()\n }\n\n /*\n * Paging swaps the cells out from under a live drag, and the dragged event's day is then off\n * screen; the card would vanish until the next pointer move, which never comes if the hand is\n * holding still against the edge. Re-applying the last position once the new cells are\n * rendered is what keeps the card under the pointer across the boundary.\n */\n watch(\n options.layout,\n () => {\n const state = gesture.value\n if (state?.moved) reapply(state)\n },\n { flush: 'post' },\n )\n\n /**\n * The card is found by WALKING the cards rather than by building an attribute selector. An id\n * belongs to the consumer, so it may hold a quote or a backslash a selector would need\n * escaped, and `CSS.escape` cannot do that escaping here: jsdom defines no `CSS` object at\n * all, so the call threw on every keyboard grab, from inside a `nextTick` where nothing could\n * catch it; an unhandled rejection, which fails the run while every assertion still passes.\n */\n function refocusCard(id: CalendarEventId) {\n void nextTick(() => {\n // Searched from the view's root: the time grid's all-day bars sit in its sticky header,\n // outside the box the cells occupy.\n const cards = options.rootEl.value?.querySelectorAll<HTMLElement>('.v-calendar-event')\n Array.from(cards ?? [])\n .find((card) => card.dataset.eventId === String(id))\n ?.focus()\n })\n }\n\n /** Puts the focus on a cell by its id, once the render that made it tabbable has run. */\n function focusCell(id: string, deferred = false, focusOptions?: FocusOptions) {\n const move = () => document.getElementById(id)?.focus(focusOptions)\n if (deferred) void nextTick(move)\n else move()\n }\n\n /** The event a card stands for, read back off the attribute the card publishes. */\n const idOfCard = (card: HTMLElement) => cardIdOf(card, (id) => options.eventOf(id) !== undefined)\n\n /**\n * A card answers a different table from the grid it sits in; that is what a grab mode IS.\n * Without it the grid would offer a gesture the pointer alone could reach (WCAG 2.1.1).\n */\n function onCardKeydown(event: KeyboardEvent, card: HTMLElement) {\n // Whatever click follows is this key's, never the end of an earlier drag.\n dragged = false\n const item = options.eventOf(idOfCard(card))\n if (!item) return\n\n const held = grabbing.value && gesture.value?.id === item.id\n const state = held ? gesture.value! : null\n const intent = calendarIntent(\n event,\n held ? 'grabbed' : 'event',\n options.slotMinutes(),\n state?.rtl ?? isRtl(),\n )\n if (!intent) return\n\n if (!state) {\n // An event that cannot be moved keeps a button's ordinary behaviour: Space presses it,\n // which the card's click handler reports.\n const init = intent.kind === 'grab' ? options.grab(item) : null\n if (!init) return\n /*\n * Cancelling the keydown is what stops that press, so the keystroke that takes hold of\n * the event does not open it too: without it every attempt to move something would fire\n * the consumer's editor over it.\n */\n event.preventDefault()\n start(init)\n options.announce(m.value.calendar.grabbed)\n return\n }\n\n event.preventDefault()\n\n if (intent.kind === 'grabMove' || intent.kind === 'grabResize') {\n if (!options.onGrabStep(state, intent, item)) return\n state.moved = true\n refocusCard(state.id)\n return\n }\n\n if (intent.kind === 'activate') {\n gesture.value = null\n if (state.moved) options.onDrop(state)\n options.announce(m.value.calendar.dropped)\n refocusCard(state.id)\n return\n }\n\n if (intent.kind === 'cancel') {\n revertGrab()\n refocusCard(state.id)\n }\n }\n\n /**\n * The five things every card is told about the gesture, bound with `v-bind` so the two grids\n * cannot describe the same state in two different ways.\n */\n function cardState(id: CalendarEventId) {\n const state = gesture.value\n const mine = state !== null && state.id === id\n return {\n /*\n * Only once the press has travelled. A dragged card takes no pointer events, so marked at\n * the press it lets the release land on the cell beneath it: the click then goes to that\n * cell, and clicking an event reports an empty slot instead of opening it.\n */\n dragging: mine && state.pointerId !== null && state.moved,\n rejected: mine && state.outside,\n grabbed: mine && state.pointerId === null,\n hintId: options.editable() && !isGhostId(id) ? options.hintId() : undefined,\n ghostOf: isGhostId(id) ? originalIdOf(id) : undefined,\n }\n }\n\n return {\n gesture,\n grabbing,\n ghostEvent,\n withPreview,\n edgeCue,\n isRtl,\n start,\n reapply,\n release,\n endLastGesture,\n consumeDrag,\n onPointermove,\n onPointerup,\n onPointercancel,\n onPointerleave,\n onFocusout,\n onCardKeydown,\n refocusCard,\n focusCell,\n idOfCard,\n cardState,\n }\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"gesture.js","names":["isRtl","isElementRtl","GHOST_PREFIX","ghostIdOf","id","originalIdOf","isGhostId","cardIdOf","raw","card","has","gridGeometryOf","rect","rtl","isGrabbed","state","useCalendarGesture","m","useMessages","gesture","ref","grabbing","computed","isRtl$1","isRtl","options","ghostEvent","original","event","withPreview","events","moving","dragged","endLastGesture","revertGrab","onFocusout","next","consumeDrag","was","edge","useEdgeStep","edgeCue","release","start","init","capture","pointerId","reapply","onPointermove","rootRect","pointWithin","inlineEdgeAt","onPointerup","onPointercancel","abandon","onPointerleave","refocusCard","cards","focusCell","move","focusOptions","deferred","nextTick","idOfCard","onCardKeydown","item","held","intent","calendarIntent","cardState","mine"],"sources":["../../../src/components/VCalendar/gesture.ts"],"sourcesContent":["// @keyboard @a11y @core\n/**\n * Share pointer and keyboard editing gestures across month and time-grid views; each view\n * supplies its own cell geometry.\n */\nimport { computed, nextTick, ref, watch } from 'vue'\nimport type { Ref } from 'vue'\n\nimport { isRtl as isElementRtl } from '../../utils/direction'\n\nimport { useMessages } from '../../i18n/state'\n\nimport { EDGE_BAND, useEdgeStep } from './edgeStep'\nimport { calendarIntent, type CalendarIntent } from './keyboard'\nimport { DRAG_THRESHOLD, inlineEdgeAt, pointWithin, type GridGeometry } from './layout'\nimport type { CalendarEvent, CalendarEventId, CalendarEventTimes } from './types'\n\n/**\n * The prefix marking the copy an event leaves behind at its old place while it is being\n * dragged.\n */\nconst GHOST_PREFIX = '__vectis-calendar-ghost__'\n\n/**\n * The id the ghost of a dragged event carries. It has to DIFFER from the event's own, or the\n * two would collide in every map the layout keys by id and only one would ever be drawn.\n */\nconst ghostIdOf = (id: CalendarEventId) => `${GHOST_PREFIX}${id}`\n/** The dragged event's own id, read back off its ghost's. */\nconst originalIdOf = (id: CalendarEventId) => String(id).slice(GHOST_PREFIX.length)\nconst isGhostId = (id: CalendarEventId) => String(id).startsWith(GHOST_PREFIX)\n\n/** The id a card belongs to, read back off the DOM. */\nfunction cardIdOf(card: HTMLElement, has: (id: CalendarEventId) => boolean) {\n const raw = card.dataset.eventId ?? ''\n return has(raw) ? raw : Number(raw)\n}\n\n/**\n * `inlineStart` is the edge the first column starts at, which is the RIGHT one in a\n * right-to-left page.\n */\nexport function gridGeometryOf(rect: DOMRect, columns: number, rtl: boolean): GridGeometry {\n return {\n top: rect.top,\n height: rect.height,\n inlineStart: rtl ? rect.right : rect.left,\n inlineSize: rect.width,\n columns,\n }\n}\n\n/** The state every gesture carries, whatever each grid adds to it. */\nexport interface GestureBase {\n id: CalendarEventId\n /**\n * Where the event was when the gesture began. Every pointer frame is computed from this and\n * never from the frame before it, so a long drag cannot accumulate rounding drift.\n */\n origin: CalendarEventTimes\n /** What the card shows right now. The model is not touched until the gesture ends. */\n preview: CalendarEventTimes\n /** The pointer holding the gesture, or null for a keyboard grab. */\n pointerId: number | null\n originX: number\n originY: number\n /**\n * Where the pointer last was. Two things move the calendar UNDER a still pointer: paging at\n * an edge, and auto-scrolling. Each has to work out afresh what the pointer is now over.\n */\n lastX: number\n lastY: number\n /** Whether it moved past the threshold, which separates a drag from a click. */\n moved: boolean\n /**\n * Whether the pointer is off the calendar altogether: over the toolbar, or over the page\n * beside it. A KEYBOARD grab can never set it, and structurally rather than by a guard:\n * `onPointermove` is the only writer, and it returns on the id mismatch first: a grab's\n * `pointerId` is null, which no real pointer's id ever equals.\n */\n outside: boolean\n /**\n * The reading direction, read once when the gesture begins. It cannot change under a live\n * drag, and asking the document on every frame costs a style resolution each time.\n */\n rtl: boolean\n}\n\n/** What a grid hands over to start a gesture; the rest is filled in here. */\nexport type GestureInit<G extends GestureBase> = Omit<\n G,\n 'preview' | 'lastX' | 'lastY' | 'moved' | 'outside' | 'rtl'\n>\n\n/**\n * A gesture held by the KEYBOARD rather than by a pointer: grabbed with Space, and waiting for\n * the arrows to move it.\n */\nconst isGrabbed = (state: GestureBase | null) => state !== null && state.pointerId === null\n\n/** The two intents that move a grabbed event, which only a grid can turn into times. */\nexport type GrabStep = Extract<CalendarIntent, { kind: 'grabMove' | 'grabResize' }>\n\nexport interface CalendarGestureOptions<E extends CalendarEvent, G extends GestureBase> {\n /** Every event as it is currently drawn, the ghost's original among them. */\n events: () => readonly E[]\n /** The event drawn under an id, for the handlers. */\n eventOf: (id: CalendarEventId) => E | undefined\n rootEl: Ref<HTMLElement | null>\n /** The element the pointer is captured on once a press travels. */\n captureEl: Ref<HTMLElement | null>\n /** The box the cells occupy, which points and edges are read against. */\n measureEl: Ref<HTMLElement | null>\n /** How many columns that box is divided into. */\n columns: () => number\n /** Whether events may be moved at all. */\n editable: () => boolean\n /** The node every card points at to say how it can be moved. */\n hintId: () => string\n /** The step a grabbed event moves by, handed to the keyboard table. */\n slotMinutes: () => number\n edgeStepDelay: () => number\n /** Whatever the grid's cells are made of, so paging under a still pointer re-places the card. */\n layout: () => unknown\n /** Works out where the gesture's event belongs from the pointer's last position. */\n applyPoint: (state: G, rect: DOMRect) => void\n /** Called on every pointer move past the threshold, after the edge watch, with both rects. */\n onEdges?: (state: G, rootRect: DOMRect | undefined) => void\n /** Everything else a gesture leaves running, dropped on every path out of one. */\n onRelease?: () => void\n /**\n * A pointer gesture let go inside the calendar. Returns true when the grid has answered it\n * itself, such as a slot drawn out, and nothing is left to drop.\n */\n onLetGo?: (state: G) => boolean\n /** A gesture that moved, committed: the grid reports the new times. */\n onDrop: (state: G) => void\n /** What a keyboard grab of this event starts, or null when it cannot be grabbed. */\n grab: (item: E) => GestureInit<G> | null\n /** Applies one arrow step to a grabbed event. Returns false when the step means nothing here. */\n onGrabStep: (state: G, step: GrabStep, item: E) => boolean\n step: (direction: -1 | 1) => void\n announce: (message: string) => void\n}\n\nexport function useCalendarGesture<E extends CalendarEvent, G extends GestureBase>(\n options: CalendarGestureOptions<E, G>,\n) {\n const m = useMessages()\n const gesture = ref<G | null>(null) as Ref<G | null>\n\n /** True while a card is being held by the keyboard rather than dragged by a pointer. */\n const grabbing = computed(() => isGrabbed(gesture.value))\n\n const isRtl = () => isElementRtl(options.measureEl.value)\n\n /**\n * The echo of where the gestured event began, so the reader can see what they are moving it\n * FROM. A press that has not travelled yet produces none, or a click would flash a second\n * card over the first.\n */\n const ghostEvent = computed<E | null>(() => {\n const state = gesture.value\n if (!state?.moved) return null\n const original = options.events().find((event) => event.id === state.id)\n return original ? ({ ...original, ...state.origin, id: ghostIdOf(state.id) } as E) : null\n })\n\n /** A list with the gestured event moved to wherever it is now, plus its echo. */\n function withPreview(events: readonly E[]): E[] {\n const state = gesture.value\n if (!state) return [...events]\n const moving = events.map((event) =>\n event.id === state.id ? ({ ...event, ...state.preview } as E) : event,\n )\n return ghostEvent.value ? [...moving, ghostEvent.value] : moving\n }\n\n /**\n * Set click suppression on pointerup, not pointercancel; clear it before every press guard\n * and keyboard activation. Captured releases may never send their click to an event card.\n */\n let dragged = false\n\n /** Closes the books on the previous gesture. */\n function endLastGesture() {\n dragged = false\n if (grabbing.value) revertGrab()\n }\n\n /** Puts a keyboard grab back where it was taken from, writing nothing, and says so. */\n function revertGrab() {\n const state = gesture.value\n if (!state) return\n gesture.value = null\n options.announce(m.value.calendar.reverted)\n return state\n }\n\n /**\n * A keyboard grab ends when the focus moves on to something else, the toolbar or another\n * control.\n */\n function onFocusout(event: FocusEvent) {\n const state = gesture.value\n const next = event.relatedTarget as HTMLElement | null\n if (!grabbing.value || !state || !next) return\n const card = next.closest<HTMLElement>('.v-calendar-event')\n if (card && card.dataset.eventId === String(state.id)) return\n revertGrab()\n }\n\n /** Whether the gesture that just ended actually moved; asking lowers the flag. */\n function consumeDrag() {\n const was = dragged\n dragged = false\n return was\n }\n\n const edge = useEdgeStep(options.step, options.edgeStepDelay)\n\n /** Which edge is counting down, as the attribute the stylesheet reads. */\n const edgeCue = computed(() =>\n edge.pending.value === -1 ? 'start' : edge.pending.value === 1 ? 'end' : undefined,\n )\n\n function release() {\n edge.cancel()\n options.onRelease?.()\n }\n\n /** Starts a gesture. */\n function start(init: GestureInit<G>, rtl = isRtl()) {\n gesture.value = {\n ...init,\n preview: { ...init.origin },\n lastX: init.originX,\n lastY: init.originY,\n moved: false,\n outside: false,\n rtl,\n } as G\n }\n\n /**\n * Called when the press crosses the drag threshold, never at the press. The browser sends the\n * `click` that follows a captured `pointerup` to the CAPTURE element, so a press captured at\n * once reaches the scroller instead of the card or the cell under it: clicking an event would\n * open nothing and clicking an empty slot would report nothing, on every calendar whose\n * events can be moved or drawn.\n */\n function capture(pointerId: number) {\n // @fallback\n /*\n * Synthetic pointer events may not have a capturable pointer; allow the gesture to continue\n * within the element if capture fails.\n */\n try {\n options.captureEl.value?.setPointerCapture(pointerId)\n } catch {\n /* Synthetic pointers cannot be captured. */\n }\n }\n\n function reapply(state: G) {\n const rect = options.measureEl.value?.getBoundingClientRect()\n if (rect) options.applyPoint(state, rect)\n }\n\n function onPointermove(event: PointerEvent) {\n const state = gesture.value\n if (!state || state.pointerId !== event.pointerId) return\n\n state.lastX = event.clientX\n state.lastY = event.clientY\n\n // Below the threshold nothing has happened yet. That is what keeps a click a click: the\n // hand's tremor during a press would otherwise register as a one-pixel drag.\n if (\n !state.moved &&\n Math.abs(event.clientX - state.originX) < DRAG_THRESHOLD &&\n Math.abs(event.clientY - state.originY) < DRAG_THRESHOLD\n ) {\n return\n }\n\n if (!state.moved) capture(event.pointerId)\n state.moved = true\n const rootRect = options.rootEl.value?.getBoundingClientRect()\n const rect = options.measureEl.value?.getBoundingClientRect()\n\n /*\n * Neither the placement nor the edge watch below is gated on it, and neither may become so.\n * The card must keep following the pointer while it is out, which makes coming back in\n * seamless, and paging must keep running, pushing past the edge being how one crosses into\n * the next period.\n */\n state.outside = rootRect ? !pointWithin({ x: state.lastX, y: state.lastY }, rootRect) : false\n\n if (!rect) return\n options.applyPoint(state, rect)\n edge.watchEdge(\n inlineEdgeAt(\n state.lastX,\n gridGeometryOf(rect, options.columns(), state.rtl),\n EDGE_BAND,\n state.rtl,\n ),\n )\n options.onEdges?.(state, rootRect)\n }\n\n function onPointerup(event: PointerEvent) {\n const state = gesture.value\n if (!state || state.pointerId !== event.pointerId) return\n gesture.value = null\n dragged = state.moved\n release()\n\n /*\n * Nothing is announced: the pointer says nothing on a SUCCESSFUL drop either; `grabbed`,\n * `dropped` and `reverted` belong to the keyboard grab, which has no pointer to show where\n * the event went.\n */\n if (state.outside) return\n if (options.onLetGo?.(state)) return\n // A press that never travelled is an ordinary click, which the button's own click event is\n // about to report. Writing anything here would move an event nobody dragged.\n if (state.moved) options.onDrop(state)\n }\n\n /*\n * The gesture was taken away; a system gesture, a context menu, the page starting to scroll.\n * Nothing is written and nothing is announced: the card goes back to where the model still\n * says it is.\n */\n function onPointercancel(event: PointerEvent) {\n // Another pointer's cancel, a second finger starting to pan, is not this gesture's. A\n // keyboard grab carries no pointer id, so no cancel can end it either.\n if (gesture.value?.pointerId !== event.pointerId) return\n abandon()\n }\n\n function abandon() {\n gesture.value = null\n release()\n }\n\n /*\n * Its `pointerup` then lands outside and never reaches the bindings, so without this the\n * gesture would outlive the press: a mouse keeps the same pointer id, and bringing it back\n * over the calendar with the button up would pick the event up and carry it. A captured\n * pointer never leaves, so a real drag is untouched.\n */\n function onPointerleave(event: PointerEvent) {\n const state = gesture.value\n if (!state || state.pointerId !== event.pointerId || state.moved) return\n abandon()\n }\n\n /*\n * Paging swaps the cells out from under a live drag, and the dragged event's day is then off\n * screen; the card would vanish until the next pointer move, which never comes if the hand is\n * holding still against the edge. Re-applying the last position once the new cells are\n * rendered is what keeps the card under the pointer across the boundary.\n */\n watch(\n options.layout,\n () => {\n const state = gesture.value\n if (state?.moved) reapply(state)\n },\n { flush: 'post' },\n )\n\n /**\n * The card is found by WALKING the cards rather than by building an attribute selector. An id\n * belongs to the consumer, so it may hold a quote or a backslash a selector would need\n * escaped, and `CSS.escape` cannot do that escaping here: jsdom defines no `CSS` object at\n * all, so the call threw on every keyboard grab, from inside a `nextTick` where nothing could\n * catch it; an unhandled rejection, which fails the run while every assertion still passes.\n */\n function refocusCard(id: CalendarEventId) {\n void nextTick(() => {\n // Searched from the view's root: the time grid's all-day bars sit in its sticky header,\n // outside the box the cells occupy.\n const cards = options.rootEl.value?.querySelectorAll<HTMLElement>('.v-calendar-event')\n Array.from(cards ?? [])\n .find((card) => card.dataset.eventId === String(id))\n ?.focus()\n })\n }\n\n /** Puts the focus on a cell by its id, once the render that made it tabbable has run. */\n function focusCell(id: string, deferred = false, focusOptions?: FocusOptions) {\n const move = () => document.getElementById(id)?.focus(focusOptions)\n if (deferred) void nextTick(move)\n else move()\n }\n\n /** The event a card stands for, read back off the attribute the card publishes. */\n const idOfCard = (card: HTMLElement) => cardIdOf(card, (id) => options.eventOf(id) !== undefined)\n\n /**\n * A card answers a different table from the grid it sits in; that is what a grab mode IS.\n * Without it the grid would offer a gesture the pointer alone could reach (WCAG 2.1.1).\n */\n function onCardKeydown(event: KeyboardEvent, card: HTMLElement) {\n // Whatever click follows is this key's, never the end of an earlier drag.\n dragged = false\n const item = options.eventOf(idOfCard(card))\n if (!item) return\n\n const held = grabbing.value && gesture.value?.id === item.id\n const state = held ? gesture.value! : null\n const intent = calendarIntent(\n event,\n held ? 'grabbed' : 'event',\n options.slotMinutes(),\n state?.rtl ?? isRtl(),\n )\n if (!intent) return\n\n if (!state) {\n // An event that cannot be moved keeps a button's ordinary behaviour: Space presses it,\n // which the card's click handler reports.\n const init = intent.kind === 'grab' ? options.grab(item) : null\n if (!init) return\n /*\n * Cancelling the keydown is what stops that press, so the keystroke that takes hold of\n * the event does not open it too: without it every attempt to move something would fire\n * the consumer's editor over it.\n */\n event.preventDefault()\n start(init)\n options.announce(m.value.calendar.grabbed)\n return\n }\n\n event.preventDefault()\n\n if (intent.kind === 'grabMove' || intent.kind === 'grabResize') {\n if (!options.onGrabStep(state, intent, item)) return\n state.moved = true\n refocusCard(state.id)\n return\n }\n\n if (intent.kind === 'activate') {\n gesture.value = null\n if (state.moved) options.onDrop(state)\n options.announce(m.value.calendar.dropped)\n refocusCard(state.id)\n return\n }\n\n if (intent.kind === 'cancel') {\n revertGrab()\n refocusCard(state.id)\n }\n }\n\n /**\n * The five things every card is told about the gesture, bound with `v-bind` so the two grids\n * cannot describe the same state in two different ways.\n */\n function cardState(id: CalendarEventId) {\n const state = gesture.value\n const mine = state !== null && state.id === id\n return {\n /*\n * Only once the press has travelled. A dragged card takes no pointer events, so marked at\n * the press it lets the release land on the cell beneath it: the click then goes to that\n * cell, and clicking an event reports an empty slot instead of opening it.\n */\n dragging: mine && state.pointerId !== null && state.moved,\n rejected: mine && state.outside,\n grabbed: mine && state.pointerId === null,\n hintId: options.editable() && !isGhostId(id) ? options.hintId() : undefined,\n ghostOf: isGhostId(id) ? originalIdOf(id) : undefined,\n }\n }\n\n return {\n gesture,\n grabbing,\n ghostEvent,\n withPreview,\n edgeCue,\n isRtl,\n start,\n reapply,\n release,\n endLastGesture,\n consumeDrag,\n onPointermove,\n onPointerup,\n onPointercancel,\n onPointerleave,\n onFocusout,\n onCardKeydown,\n refocusCard,\n focusCell,\n idOfCard,\n cardState,\n }\n}\n"],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"keyboard.js","names":[],"sources":["../../../src/components/VCalendar/keyboard.ts"],"sourcesContent":["// @keyboard @a11y\n/**\n * Decode calendar keys without side effects; focus, model updates and announcements remain with\n * the view.\n */\n\nimport { MINUTES_PER_HOUR } from './layout'\n\n/** What one key means, given where the focus is. */\nexport type CalendarIntent =\n /** Move the focused cell by whole days and whole hours. */\n | { kind: 'moveFocus'; days: number; minutes: number }\n /** Jump to the first or last day of the row. */\n | { kind: 'rowEdge'; edge: 'start' | 'end' }\n /** Show the previous or next period, as the toolbar's buttons do. */\n | { kind: 'period'; delta: -1 | 1 }\n /** Take up what is focused: report an empty cell, or commit a move under way. */\n | { kind: 'activate' }\n /** Open the focused day, which only a month square offers. */\n | { kind: 'openDay' }\n /** Take hold of a card, so the arrows move it. */\n | { kind: 'grab' }\n /** Abandon a move under way and put the event back. */\n | { kind: 'cancel' }\n /** Move the grabbed event. */\n | { kind: 'grabMove'; days: number; minutes: number }\n /** Change how long the grabbed event lasts. */\n | { kind: 'grabResize'; minutes: number }\n\n/**\n * Where the focus is when the key arrives, which decides the answer: - `cell`: an empty part of\n * the grid.\n */\nexport type CalendarFocus = 'cell' | 'event' | 'grabbed'\n\n/** The part of a keyboard event the table reads; a `KeyboardEvent` is one. */\nexport interface KeyChord {\n key: string\n shiftKey?: boolean\n altKey?: boolean\n ctrlKey?: boolean\n metaKey?: boolean\n}\n\n/** What a key means. */\nexport function calendarIntent(\n chord: KeyChord,\n focus: CalendarFocus,\n slotMinutes: number,\n rtl: boolean,\n): CalendarIntent | undefined {\n if (chord.altKey || chord.ctrlKey || chord.metaKey) return undefined\n const { key } = chord\n const shiftKey = chord.shiftKey === true\n const step = slotMinutes > 0 ? slotMinutes : 1\n // The inline arrows follow the reading direction; the block ones never do, because down\n // is later in the day in every script.\n const inline = rtl ? -1 : 1\n\n if (focus === 'grabbed') {\n switch (key) {\n case 'ArrowLeft':\n return { kind: 'grabMove', days: -inline, minutes: 0 }\n case 'ArrowRight':\n return { kind: 'grabMove', days: inline, minutes: 0 }\n case 'ArrowUp':\n return shiftKey\n ? { kind: 'grabResize', minutes: -step }\n : { kind: 'grabMove', days: 0, minutes: -step }\n case 'ArrowDown':\n return shiftKey\n ? { kind: 'grabResize', minutes: step }\n : { kind: 'grabMove', days: 0, minutes: step }\n case 'Enter':\n case ' ':\n return { kind: 'activate' }\n case 'Escape':\n return { kind: 'cancel' }\n default:\n return undefined\n }\n }\n\n if (focus === 'event') return key === ' ' ? { kind: 'grab' } : undefined\n\n switch (key) {\n case 'ArrowLeft':\n return { kind: 'moveFocus', days: -inline, minutes: 0 }\n case 'ArrowRight':\n return { kind: 'moveFocus', days: inline, minutes: 0 }\n case 'ArrowUp':\n return { kind: 'moveFocus', days: 0, minutes: -MINUTES_PER_HOUR }\n case 'ArrowDown':\n return { kind: 'moveFocus', days: 0, minutes: MINUTES_PER_HOUR }\n case 'Home':\n return { kind: 'rowEdge', edge: 'start' }\n case 'End':\n return { kind: 'rowEdge', edge: 'end' }\n case 'PageUp':\n return { kind: 'period', delta: -1 }\n case 'PageDown':\n return { kind: 'period', delta: 1 }\n case 'Enter':\n return shiftKey ? { kind: 'openDay' } : { kind: 'activate' }\n case ' ':\n return { kind: 'activate' }\n default:\n return undefined\n }\n}\n"],"mappings":";AA6CA,SAAgB,EACd,GACA,GACA,GACA,GAC4B;CAC5B,IAAI,EAAM,UAAU,EAAM,WAAW,EAAM,SAAS;CACpD,IAAM,EAAE,WAAQ,GACV,IAAW,EAAM,aAAa,IAC9B,IAAO,IAAc,IAAI,IAAc,GAGvC,IAAS,IAAM,KAAK;CAE1B,IAAI,MAAU,WACZ,QAAQ,GAAR;EACE,KAAK,aACH,OAAO;GAAE,MAAM;GAAY,MAAM,CAAC;GAAQ,SAAS;EAAE;EACvD,KAAK,cACH,OAAO;GAAE,MAAM;GAAY,MAAM;GAAQ,SAAS;EAAE;EACtD,KAAK,WACH,OAAO,IACH;GAAE,MAAM;GAAc,SAAS,CAAC;EAAK,IACrC;GAAE,MAAM;GAAY,MAAM;GAAG,SAAS,CAAC;EAAK;EAClD,KAAK,aACH,OAAO,IACH;GAAE,MAAM;GAAc,SAAS;EAAK,IACpC;GAAE,MAAM;GAAY,MAAM;GAAG,SAAS;EAAK;EACjD,KAAK;EACL,KAAK,KACH,OAAO,EAAE,MAAM,WAAW;EAC5B,KAAK,UACH,OAAO,EAAE,MAAM,SAAS;EAC1B,SACE;CACJ;CAGF,IAAI,MAAU,SAAS,OAAO,MAAQ,MAAM,EAAE,MAAM,OAAO,IAAI,KAAA;CAE/D,QAAQ,GAAR;EACE,KAAK,aACH,OAAO;GAAE,MAAM;GAAa,MAAM,CAAC;GAAQ,SAAS;EAAE;EACxD,KAAK,cACH,OAAO;GAAE,MAAM;GAAa,MAAM;GAAQ,SAAS;EAAE;EACvD,KAAK,WACH,OAAO;GAAE,MAAM;GAAa,MAAM;GAAG,SAAS;EAAkB;EAClE,KAAK,aACH,OAAO;GAAE,MAAM;GAAa,MAAM;GAAG,SAAA;EAA0B;EACjE,KAAK,QACH,OAAO;GAAE,MAAM;GAAW,MAAM;EAAQ;EAC1C,KAAK,OACH,OAAO;GAAE,MAAM;GAAW,MAAM;EAAM;EACxC,KAAK,UACH,OAAO;GAAE,MAAM;GAAU,OAAO;EAAG;EACrC,KAAK,YACH,OAAO;GAAE,MAAM;GAAU,OAAO;EAAE;EACpC,KAAK,SACH,OAAO,IAAW,EAAE,MAAM,UAAU,IAAI,EAAE,MAAM,WAAW;EAC7D,KAAK,KACH,OAAO,EAAE,MAAM,WAAW;EAC5B,SACE;CACJ;AACF"}
1
+ {"version":3,"file":"keyboard.js","names":["calendarIntent","chord","shiftKey","step","slotMinutes","inline","rtl","focus","key"],"sources":["../../../src/components/VCalendar/keyboard.ts"],"sourcesContent":["// @keyboard @a11y\n/**\n * Decode calendar keys without side effects; focus, model updates and announcements remain with\n * the view.\n */\n\nimport { MINUTES_PER_HOUR } from './layout'\n\n/** What one key means, given where the focus is. */\nexport type CalendarIntent =\n /** Move the focused cell by whole days and whole hours. */\n | { kind: 'moveFocus'; days: number; minutes: number }\n /** Jump to the first or last day of the row. */\n | { kind: 'rowEdge'; edge: 'start' | 'end' }\n /** Show the previous or next period, as the toolbar's buttons do. */\n | { kind: 'period'; delta: -1 | 1 }\n /** Take up what is focused: report an empty cell, or commit a move under way. */\n | { kind: 'activate' }\n /** Open the focused day, which only a month square offers. */\n | { kind: 'openDay' }\n /** Take hold of a card, so the arrows move it. */\n | { kind: 'grab' }\n /** Abandon a move under way and put the event back. */\n | { kind: 'cancel' }\n /** Move the grabbed event. */\n | { kind: 'grabMove'; days: number; minutes: number }\n /** Change how long the grabbed event lasts. */\n | { kind: 'grabResize'; minutes: number }\n\n/**\n * Where the focus is when the key arrives, which decides the answer: - `cell`: an empty part of\n * the grid.\n */\nexport type CalendarFocus = 'cell' | 'event' | 'grabbed'\n\n/** The part of a keyboard event the table reads; a `KeyboardEvent` is one. */\nexport interface KeyChord {\n key: string\n shiftKey?: boolean\n altKey?: boolean\n ctrlKey?: boolean\n metaKey?: boolean\n}\n\n/** What a key means. */\nexport function calendarIntent(\n chord: KeyChord,\n focus: CalendarFocus,\n slotMinutes: number,\n rtl: boolean,\n): CalendarIntent | undefined {\n if (chord.altKey || chord.ctrlKey || chord.metaKey) return undefined\n const { key } = chord\n const shiftKey = chord.shiftKey === true\n const step = slotMinutes > 0 ? slotMinutes : 1\n // The inline arrows follow the reading direction; the block ones never do, because down\n // is later in the day in every script.\n const inline = rtl ? -1 : 1\n\n if (focus === 'grabbed') {\n switch (key) {\n case 'ArrowLeft':\n return { kind: 'grabMove', days: -inline, minutes: 0 }\n case 'ArrowRight':\n return { kind: 'grabMove', days: inline, minutes: 0 }\n case 'ArrowUp':\n return shiftKey\n ? { kind: 'grabResize', minutes: -step }\n : { kind: 'grabMove', days: 0, minutes: -step }\n case 'ArrowDown':\n return shiftKey\n ? { kind: 'grabResize', minutes: step }\n : { kind: 'grabMove', days: 0, minutes: step }\n case 'Enter':\n case ' ':\n return { kind: 'activate' }\n case 'Escape':\n return { kind: 'cancel' }\n default:\n return undefined\n }\n }\n\n if (focus === 'event') return key === ' ' ? { kind: 'grab' } : undefined\n\n switch (key) {\n case 'ArrowLeft':\n return { kind: 'moveFocus', days: -inline, minutes: 0 }\n case 'ArrowRight':\n return { kind: 'moveFocus', days: inline, minutes: 0 }\n case 'ArrowUp':\n return { kind: 'moveFocus', days: 0, minutes: -MINUTES_PER_HOUR }\n case 'ArrowDown':\n return { kind: 'moveFocus', days: 0, minutes: MINUTES_PER_HOUR }\n case 'Home':\n return { kind: 'rowEdge', edge: 'start' }\n case 'End':\n return { kind: 'rowEdge', edge: 'end' }\n case 'PageUp':\n return { kind: 'period', delta: -1 }\n case 'PageDown':\n return { kind: 'period', delta: 1 }\n case 'Enter':\n return shiftKey ? { kind: 'openDay' } : { kind: 'activate' }\n case ' ':\n return { kind: 'activate' }\n default:\n return undefined\n }\n}\n"],"mappings":";AA6CA,SAAgBA,EACd,GACA,GACA,GACA,GAC4B;CAC5B,IAAIC,EAAM,UAAUA,EAAM,WAAWA,EAAM,SAAS;CACpD,IAAM,EAAE,WAAQA,GACVC,IAAWD,EAAM,aAAa,IAC9BE,IAAOC,IAAc,IAAIA,IAAc,GAGvCC,IAASC,IAAM,KAAK;CAE1B,IAAIC,MAAU,WACZ,QAAQC,GAAR;EACE,KAAK,aACH,OAAO;GAAE,MAAM;GAAY,MAAM,CAACH;GAAQ,SAAS;EAAE;EACvD,KAAK,cACH,OAAO;GAAE,MAAM;GAAY,MAAMA;GAAQ,SAAS;EAAE;EACtD,KAAK,WACH,OAAOH,IACH;GAAE,MAAM;GAAc,SAAS,CAACC;EAAK,IACrC;GAAE,MAAM;GAAY,MAAM;GAAG,SAAS,CAACA;EAAK;EAClD,KAAK,aACH,OAAOD,IACH;GAAE,MAAM;GAAc,SAASC;EAAK,IACpC;GAAE,MAAM;GAAY,MAAM;GAAG,SAASA;EAAK;EACjD,KAAK;EACL,KAAK,KACH,OAAO,EAAE,MAAM,WAAW;EAC5B,KAAK,UACH,OAAO,EAAE,MAAM,SAAS;EAC1B,SACE;CACJ;CAGF,IAAII,MAAU,SAAS,OAAOC,MAAQ,MAAM,EAAE,MAAM,OAAO,IAAI,KAAA;CAE/D,QAAQA,GAAR;EACE,KAAK,aACH,OAAO;GAAE,MAAM;GAAa,MAAM,CAACH;GAAQ,SAAS;EAAE;EACxD,KAAK,cACH,OAAO;GAAE,MAAM;GAAa,MAAMA;GAAQ,SAAS;EAAE;EACvD,KAAK,WACH,OAAO;GAAE,MAAM;GAAa,MAAM;GAAG,SAAS;EAAkB;EAClE,KAAK,aACH,OAAO;GAAE,MAAM;GAAa,MAAM;GAAG,SAAA;EAA0B;EACjE,KAAK,QACH,OAAO;GAAE,MAAM;GAAW,MAAM;EAAQ;EAC1C,KAAK,OACH,OAAO;GAAE,MAAM;GAAW,MAAM;EAAM;EACxC,KAAK,UACH,OAAO;GAAE,MAAM;GAAU,OAAO;EAAG;EACrC,KAAK,YACH,OAAO;GAAE,MAAM;GAAU,OAAO;EAAE;EACpC,KAAK,SACH,OAAOH,IAAW,EAAE,MAAM,UAAU,IAAI,EAAE,MAAM,WAAW;EAC7D,KAAK,KACH,OAAO,EAAE,MAAM,WAAW;EAC5B,SACE;CACJ;AACF"}
@@ -2,20 +2,20 @@ import { clamp as e } from "../../utils/number.js";
2
2
  import { pad2 as t } from "../../utils/text.js";
3
3
  import { addDays as n, addMonths as r, buildMonthGrid as i, compareISO as a, daysInMonth as o, formatISO as s, isoOf as c, parseISO as l } from "../../utils/date.js";
4
4
  import { minutesOf as u } from "../../utils/time.js";
5
- var d = 1440, f = 7, p = 1440 * 60 * 1e3;
5
+ var d = 1440, f = 7, p = 864e5;
6
6
  function m(e, t) {
7
7
  let n = String(e), r = String(t);
8
8
  return n < r ? -1 : +(n > r);
9
9
  }
10
10
  function h(t, n) {
11
- let r = e(Math.round(t * 60), 0, d - 60);
11
+ let r = e(Math.round(t * 60), 0, 1380);
12
12
  return {
13
13
  start: r,
14
14
  end: e(Math.round(n * 60), r + 60, d)
15
15
  };
16
16
  }
17
17
  function g(n) {
18
- let r = e(Math.round(n), 0, d - 1);
18
+ let r = e(Math.round(n), 0, 1439);
19
19
  return `${t(Math.floor(r / 60))}:${t(r % 60)}`;
20
20
  }
21
21
  function _(e, t) {
@@ -64,12 +64,12 @@ function C(e, t, r, i) {
64
64
  return a;
65
65
  }
66
66
  if (t === "week") {
67
- let t = n(e, -((l(e).getDay() - r[0] + f) % f)), i = [];
67
+ let t = (l(e).getDay() - r[0] + f) % f, i = n(e, -t), a = [];
68
68
  for (let e = 0; e < f; e++) {
69
- let a = n(t, e);
70
- y(a, r) && i.push(a);
69
+ let t = n(i, e);
70
+ y(t, r) && a.push(t);
71
71
  }
72
- return i;
72
+ return a;
73
73
  }
74
74
  let a = S(t, i), s = [b(e, r)];
75
75
  for (let e = 1; e < a; e++) s.push(x(s[e - 1], 1, r));
@@ -132,11 +132,7 @@ function k(t, n, r, i) {
132
132
  continue;
133
133
  }
134
134
  let n = _(e.endTime, 0);
135
- if (n === 0) {
136
- c(e.id, o.get(e.start), t, d, "whole");
137
- continue;
138
- }
139
- c(e.id, o.get(e.start), t, d, "head"), c(e.id, o.get(e.end), 0, n, "tail");
135
+ n === 0 ? c(e.id, o.get(e.start), t, d, "whole") : (c(e.id, o.get(e.start), t, d, "head"), c(e.id, o.get(e.end), 0, n, "tail"));
140
136
  }
141
137
  return s;
142
138
  }
@@ -1 +1 @@
1
- {"version":3,"file":"layout.js","names":[],"sources":["../../../src/components/VCalendar/layout.ts"],"sourcesContent":["// @core\n/**\n * Pure calendar layout shared by its views; component ownership keeps agenda-specific contracts\n * out of general utilities.\n */\nimport {\n addDays,\n addMonths,\n buildMonthGrid,\n compareISO,\n daysInMonth,\n formatISO,\n isoOf,\n parseISO,\n} from '../../utils/date'\nimport { clamp } from '../../utils/number'\nimport { pad2 } from '../../utils/text'\nimport { minutesOf } from '../../utils/time'\n\nimport type { MonthCell } from '../../utils/date'\nimport type { CalendarEvent, CalendarEventId, CalendarEventTimes, CalendarView } from './types'\n\n/** An hour, in the minutes every time here is counted in: one row of a time grid. */\nexport const MINUTES_PER_HOUR = 60\n\n/** How many minutes a day holds. The upper bound of every time computed here. */\nexport const MINUTES_PER_DAY = 24 * MINUTES_PER_HOUR\n\nconst DAYS_PER_WEEK = 7\n\n/** A day in milliseconds, for counting the days between two dates. */\nconst MS_PER_DAY = 24 * 60 * 60 * 1000\n\n/** How far the pointer must travel before a press becomes a drag rather than a click. */\nexport const DRAG_THRESHOLD = 3\n\n/**\n * This must not be `localeCompare`. An id is an opaque key, never user-facing text, so there is\n * nothing here to collate; and `localeCompare` with no locale resolves against the RUNTIME's\n * default, which differs between Node and the browser.\n */\nfunction compareId(a: CalendarEventId, b: CalendarEventId): number {\n const left = String(a)\n const right = String(b)\n return left < right ? -1 : left > right ? 1 : 0\n}\n\n/** The slice of the day a calendar is showing, as minutes since midnight. */\nexport interface TimeWindow {\n start: number\n end: number\n}\n\n/** Turns the `dayStart`/`dayEnd` props, given in hours, into the window the rest works in. */\nexport function windowOf(startHour: number, endHour: number): TimeWindow {\n const start = clamp(\n Math.round(startHour * MINUTES_PER_HOUR),\n 0,\n MINUTES_PER_DAY - MINUTES_PER_HOUR,\n )\n const end = clamp(\n Math.round(endHour * MINUTES_PER_HOUR),\n start + MINUTES_PER_HOUR,\n MINUTES_PER_DAY,\n )\n return { start, end }\n}\n\n/**\n * The value is held one minute short of midnight rather than allowed to reach it. A day's last\n * moment is 1440 in this arithmetic, but `24:00` is not a time any of the design system's\n * helpers accept (`isValidTime` rejects it).\n */\nexport function timeOf(minutes: number): string {\n const held = clamp(Math.round(minutes), 0, MINUTES_PER_DAY - 1)\n return `${pad2(Math.floor(held / MINUTES_PER_HOUR))}:${pad2(held % MINUTES_PER_HOUR)}`\n}\n\n/** An `HH:mm` string into minutes since midnight; `fallback` when it is not one. */\nexport function minutesAt(time: string | undefined, fallback: number): number {\n return minutesOf(time) ?? fallback\n}\n\n/** The weekdays a calendar shows, in reading order. */\nexport function normalizeWeekdays(\n weekdays: readonly number[] | undefined,\n firstDayOfWeek: number,\n): number[] {\n const seen = new Set<number>()\n const kept: number[] = []\n for (const day of weekdays ?? []) {\n const value = Math.trunc(day)\n if (value >= 0 && value <= 6 && !seen.has(value)) {\n seen.add(value)\n kept.push(value)\n }\n }\n if (kept.length > 0) return kept\n // Monday when the day given is not a number, the fallback `firstDayOfWeekFor` uses too.\n const first = Number.isFinite(firstDayOfWeek) ? ((Math.trunc(firstDayOfWeek) % 7) + 7) % 7 : 1\n return Array.from({ length: DAYS_PER_WEEK }, (_, i) => (first + i) % 7)\n}\n\n/** Whether a date falls on one of the visible weekdays. */\nexport function isVisibleDay(iso: string, weekdays: readonly number[]): boolean {\n const date = parseISO(iso)\n return date !== null && weekdays.includes(date.getDay())\n}\n\n/** The first visible day at or after `iso` (or at or before it, going backwards). */\nexport function snapToVisibleDay(\n iso: string,\n weekdays: readonly number[],\n direction: -1 | 1 = 1,\n): string {\n if (weekdays.length === 0) return iso\n let current = iso\n for (let i = 0; i < DAYS_PER_WEEK; i++) {\n if (isVisibleDay(current, weekdays)) return current\n current = addDays(current, direction)\n }\n return iso\n}\n\n/** Moves `count` VISIBLE days from `iso`, skipping over the hidden ones. */\nexport function advanceVisibleDays(\n iso: string,\n count: number,\n weekdays: readonly number[],\n): string {\n if (count === 0 || weekdays.length === 0) return iso\n const direction = count > 0 ? 1 : -1\n let current = iso\n let remaining = Math.abs(count)\n // Bounded so a malformed weekday list can never spin: at worst one visible day costs\n // seven calendar days, so this is the same walk with its worst case written down.\n let guard = Math.abs(count) * DAYS_PER_WEEK + DAYS_PER_WEEK\n while (remaining > 0 && guard-- > 0) {\n current = addDays(current, direction)\n if (isVisibleDay(current, weekdays)) remaining--\n }\n return current\n}\n\n/** How many day columns a view shows, before the visible-weekday filter applies. */\nexport function columnCount(view: CalendarView, customDays: number): number {\n if (view === 'day') return 1\n if (view === '4days') return 4\n if (view === 'custom') return clamp(Math.trunc(customDays), 1, 31)\n return DAYS_PER_WEEK\n}\n\n/** The days a view shows, in reading order. */\nexport function visibleDays(\n anchor: string,\n view: CalendarView,\n weekdays: readonly number[],\n customDays: number,\n): string[] {\n if (weekdays.length === 0 || parseISO(anchor) === null) return []\n if (view === 'year') return []\n\n if (view === 'month') {\n const date = parseISO(anchor)!\n const year = date.getFullYear()\n const month0 = date.getMonth()\n const days: string[] = []\n for (let day = 1; day <= daysInMonth(year, month0); day++) {\n const iso = isoOf(year, month0, day)\n if (isVisibleDay(iso, weekdays)) days.push(iso)\n }\n return days\n }\n\n if (view === 'week') {\n const date = parseISO(anchor)!\n const offset = (date.getDay() - weekdays[0]! + DAYS_PER_WEEK) % DAYS_PER_WEEK\n const weekStart = addDays(anchor, -offset)\n const days: string[] = []\n for (let i = 0; i < DAYS_PER_WEEK; i++) {\n const iso = addDays(weekStart, i)\n if (isVisibleDay(iso, weekdays)) days.push(iso)\n }\n return days\n }\n\n const total = columnCount(view, customDays)\n const days: string[] = [snapToVisibleDay(anchor, weekdays)]\n for (let i = 1; i < total; i++) days.push(advanceVisibleDays(days[i - 1]!, 1, weekdays))\n return days\n}\n\n/**\n * The day-shaped views step over VISIBLE days, not calendar ones. Stepping by one calendar day\n * from a Friday in a Monday-to-Friday calendar would land on a Saturday the grid does not draw;\n * the view would then show the same week it already showed, and the button would look broken\n * with nothing in the console to say why.\n */\nexport function stepAnchor(\n anchor: string,\n view: CalendarView,\n direction: -1 | 1,\n weekdays: readonly number[],\n customDays: number,\n): string {\n if (parseISO(anchor) === null) return anchor\n if (view === 'month') return addMonths(anchor, direction)\n if (view === 'year') return addMonths(anchor, direction * 12)\n if (view === 'week') return snapToVisibleDay(addDays(anchor, direction * DAYS_PER_WEEK), weekdays)\n return advanceVisibleDays(anchor, direction * columnCount(view, customDays), weekdays)\n}\n\n/** The first and last day a view covers, which names it in the toolbar. */\nexport function visibleRange(\n anchor: string,\n view: CalendarView,\n weekdays: readonly number[],\n customDays: number,\n): { start: string; end: string } {\n if (view === 'year') {\n // No clock read here: the server and the browser must name the same range.\n const date = parseISO(anchor)\n if (!date) return { start: anchor, end: anchor }\n return { start: isoOf(date.getFullYear(), 0, 1), end: isoOf(date.getFullYear(), 11, 31) }\n }\n const days = visibleDays(anchor, view, weekdays, customDays)\n if (days.length === 0) return { start: anchor, end: anchor }\n return { start: days[0]!, end: days[days.length - 1]! }\n}\n\n/** How long an event lasts, in minutes, counting the days between its dates. */\nexport function durationOf(times: CalendarEventTimes): number {\n return (\n daySpan(times) * MINUTES_PER_DAY +\n minutesAt(times.endTime, MINUTES_PER_DAY) -\n minutesAt(times.startTime, 0)\n )\n}\n\n/** Whether an event runs from one day into the next without lasting a whole day. */\nexport function spansMidnight(times: CalendarEventTimes): boolean {\n return compareISO(times.start, times.end) < 0 && durationOf(times) < MINUTES_PER_DAY\n}\n\n/** Whether an event belongs in the band above the grid rather than in a day's column. */\nexport function isAllDayEvent(event: CalendarEvent): boolean {\n if (event.allDay === true) return true\n const order = compareISO(event.start, event.end)\n if (order === 0) return false\n return order > 0 || !spansMidnight(event)\n}\n\n/**\n * Which piece of its event a box is: the whole of it, or one side of midnight for an event\n * that runs from one day into the next.\n */\nexport type SegmentPart = 'whole' | 'head' | 'tail'\n\n/** One event's box in one day column, in minutes since midnight. */\nexport interface EventSegment {\n id: CalendarEventId\n /** Which of the visible columns it belongs to. */\n dayIndex: number\n start: number\n end: number\n /**\n * Whether the card carries on past its top or bottom edge: the window cut it off, or\n * midnight did. Both are drawn the same way.\n */\n clippedStart: boolean\n clippedEnd: boolean\n /**\n * `head` is the evening of an event running past midnight and `tail` its morning. Only a\n * `whole` or a `tail` holds the event's real end, which its resize strip drags.\n */\n part: SegmentPart\n}\n\n/**\n * Cuts the timed events into the boxes the day columns draw. Were the minimum applied during\n * packing instead, two events fifteen minutes apart would be laid out as though they did not\n * overlap and then drawn as though they did.\n */\nexport function timedSegments(\n events: readonly CalendarEvent[],\n days: readonly string[],\n timeWindow: TimeWindow,\n minDuration: number,\n): EventSegment[] {\n const index = new Map(days.map((iso, i) => [iso, i]))\n const segments: EventSegment[] = []\n\n const push = (\n id: CalendarEventId,\n dayIndex: number | undefined,\n rawStart: number,\n rawEnd: number,\n part: SegmentPart,\n ) => {\n if (dayIndex === undefined) return\n if (rawEnd <= timeWindow.start || rawStart >= timeWindow.end) return\n const start = clamp(rawStart, timeWindow.start, timeWindow.end - 1)\n const end = clamp(Math.max(rawEnd, start + minDuration), start + 1, timeWindow.end)\n segments.push({\n id,\n dayIndex,\n start,\n end,\n clippedStart: part === 'tail' || rawStart < timeWindow.start,\n clippedEnd: part === 'head' || rawEnd > timeWindow.end,\n part,\n })\n }\n\n for (const event of events) {\n if (isAllDayEvent(event)) continue\n const rawStart = minutesAt(event.startTime, timeWindow.start)\n\n if (compareISO(event.start, event.end) === 0) {\n const rawEnd = Math.max(minutesAt(event.endTime, rawStart + minDuration), rawStart + 1)\n push(event.id, index.get(event.start), rawStart, rawEnd, 'whole')\n continue\n }\n\n /*\n * An event ending at midnight exactly has nothing on its second day, so it is drawn whole;\n * a tail of no length would otherwise be stretched to a slot and show as a stub at 00:00.\n */\n const rawEnd = minutesAt(event.endTime, 0)\n if (rawEnd === 0) {\n push(event.id, index.get(event.start), rawStart, MINUTES_PER_DAY, 'whole')\n continue\n }\n push(event.id, index.get(event.start), rawStart, MINUTES_PER_DAY, 'head')\n push(event.id, index.get(event.end), 0, rawEnd, 'tail')\n }\n\n return segments\n}\n\n/** A segment once it knows how much of its column's width it gets. */\nexport interface PlacedSegment extends EventSegment {\n /** Which column of its cluster it sits in, counted from zero. */\n column: number\n /** How many columns it takes up: more than one when the room beside it is free. */\n span: number\n /** How many columns its cluster has. It is what both of the above are read against. */\n columns: number\n}\n\n/**\n * Shares one day's width out between the events happening at the same time. Overlap is strictly\n * `a.start < b.end && b.start < a.end`, so events that merely touch (one ending exactly as the\n * next begins) share a column instead of splitting the width.\n */\nexport function packDayColumn(segments: readonly EventSegment[]): PlacedSegment[] {\n const sorted = [...segments].sort(\n (a, b) => a.start - b.start || b.end - b.start - (a.end - a.start) || compareId(a.id, b.id),\n )\n\n const placed: PlacedSegment[] = []\n let cluster: PlacedSegment[] = []\n let columnEnds: number[] = []\n let clusterEnd = -Infinity\n\n const flush = () => {\n const columns = columnEnds.length\n /*\n * The cluster filed by column first, so asking \"is the room beside me free?\" reads that one\n * column's occupants rather than the whole cluster: a crowded morning of k events across c\n * columns otherwise costs k squared per column crossed.\n */\n const byColumn: PlacedSegment[][] = Array.from({ length: columns }, () => [])\n for (const item of cluster) byColumn[item.column]!.push(item)\n for (const item of cluster) {\n let span = 1\n while (\n item.column + span < columns &&\n !byColumn[item.column + span]!.some(\n (other) => other.start < item.end && item.start < other.end,\n )\n ) {\n span++\n }\n item.span = span\n item.columns = columns\n }\n placed.push(...cluster)\n cluster = []\n columnEnds = []\n clusterEnd = -Infinity\n }\n\n for (const segment of sorted) {\n if (segment.start >= clusterEnd && cluster.length > 0) flush()\n\n let column = columnEnds.findIndex((end) => end <= segment.start)\n if (column === -1) {\n column = columnEnds.length\n columnEnds.push(segment.end)\n } else {\n columnEnds[column] = segment.end\n }\n\n cluster.push({ ...segment, column, span: 1, columns: 1 })\n clusterEnd = Math.max(clusterEnd, segment.end)\n }\n if (cluster.length > 0) flush()\n\n return placed\n}\n\n/** One square of the month view: a day, and whether it belongs to the month on show. */\nexport type { MonthCell }\n\n/** The month view, cut into weeks. */\nexport function monthWeeks(anchor: string, weekdays: readonly number[]): MonthCell[][] {\n const date = parseISO(anchor)\n if (!date || weekdays.length === 0) return []\n\n const cells = buildMonthGrid(date.getFullYear(), date.getMonth(), weekdays[0]!)\n const weeks: MonthCell[][] = []\n for (let i = 0; i < cells.length; i += DAYS_PER_WEEK) {\n const week = cells\n .slice(i, i + DAYS_PER_WEEK)\n .filter((cell) => isVisibleDay(cell.iso, weekdays))\n if (week.length > 0) weeks.push(week)\n }\n return weeks\n}\n\n/** The first day of each month of the anchor's year, which the year view lays out. */\nexport function monthsOfYear(anchor: string): string[] {\n const date = parseISO(anchor)\n if (!date) return []\n const year = date.getFullYear()\n return Array.from({ length: 12 }, (_, month0) => isoOf(year, month0, 1))\n}\n\n/** The last day an event puts anything on. */\nexport function lastDayOf(event: CalendarEvent): string {\n const endsAtMidnight =\n event.allDay !== true &&\n compareISO(event.start, event.end) < 0 &&\n minutesOf(event.endTime) === 0\n return endsAtMidnight ? addDays(event.end, -1) : event.end\n}\n\n/** Whether an event covers a given day at all, all-day or timed. */\nexport function coversDay(event: CalendarEvent, iso: string): boolean {\n return compareISO(iso, event.start) >= 0 && compareISO(iso, lastDayOf(event)) <= 0\n}\n\n/**\n * Every visible day's events, in the order a summary lists them: the all-day ones first, since\n * they frame the day rather than sit inside it, then the rest by when they start, the last tie\n * broken by id so the list cannot reshuffle for no reason.\n */\nexport function eventsByDay<T extends CalendarEvent>(\n events: readonly T[],\n days: readonly string[],\n): Map<string, T[]> {\n const buckets = new Map<string, Ranked<T>[]>()\n for (const iso of days) buckets.set(iso, [])\n if (days.length === 0) return new Map()\n\n // The grid's own bounds. `days` is in order, so its ends bound every walk below; which keeps\n // a long-running event from being walked outside the month on show.\n const first = days[0]!\n const last = days[days.length - 1]!\n\n for (const event of events) {\n /*\n * The walk below steps from one date to the next through `addDays`, which hands back a\n * string that is not a date unchanged. A datetime slipped into `start` would never be\n * stepped past, and the page would hang, on the server as well as in the browser.\n */\n if (!parseISO(event.start) || !parseISO(event.end)) continue\n const end = lastDayOf(event)\n const from = compareISO(event.start, first) > 0 ? event.start : first\n const to = compareISO(end, last) < 0 ? end : last\n if (compareISO(from, to) > 0) continue\n\n /*\n * Decorate-sort-undecorate, for the classic reason: the sort key is derived once per event\n * rather than once per comparison, which is where the time in this function goes.\n * `minutesAt` re-parses an `HH:mm` string on every ask, and a 42-square month holding 2000\n * events sorts some 17 000 pairs.\n */\n const ranked: Ranked<T> = {\n event,\n allDay: isAllDayEvent(event) ? 0 : 1,\n minutes: minutesAt(event.startTime, 0),\n id: String(event.id),\n }\n\n // An overnight event has been running since midnight on its second day, so it is ranked\n // from there, ahead of that morning's appointments, rather than by the evening before.\n const morning =\n ranked.allDay === 1 && compareISO(event.start, event.end) < 0\n ? { ...ranked, minutes: 0 }\n : ranked\n\n for (let iso = from; compareISO(iso, to) <= 0; iso = addDays(iso, 1)) {\n // A day the weekday filter hides has no bucket, so it is simply skipped: that is what\n // makes a Monday-to-Friday month cost nothing for the weekends it does not show.\n buckets.get(iso)?.push(iso === event.start ? ranked : morning)\n }\n }\n\n const byDay = new Map<string, T[]>()\n for (const [iso, list] of buckets) {\n list.sort(compareRanked)\n byDay.set(\n iso,\n list.map((item) => item.event),\n )\n }\n return byDay\n}\n\n/** An event with its sort key already worked out; see `eventsByDay`. */\ninterface Ranked<T> {\n event: T\n allDay: number\n minutes: number\n id: string\n}\n\n/** The order `eventsByDay` lists a day in, reading keys that are already computed. */\nfunction compareRanked<T>(a: Ranked<T>, b: Ranked<T>): number {\n return a.allDay - b.allDay || a.minutes - b.minutes || compareId(a.id, b.id)\n}\n\n/** One bar in the all-day band: the columns it covers, and the row it sits on. */\nexport interface AllDaySpan {\n id: CalendarEventId\n /** The first visible column it covers. */\n startIndex: number\n /** How many visible columns it covers, at least one. */\n span: number\n /** Whether it reaches beyond the days on show, on either side. */\n continuesBefore: boolean\n continuesAfter: boolean\n /** Which row of the band it sits on. */\n lane: number\n}\n\n/** Stacks the all-day bars into as few rows as they fit in. */\nexport function packAllDay(\n events: readonly CalendarEvent[],\n days: readonly string[],\n): AllDaySpan[] {\n const spans: AllDaySpan[] = []\n\n for (const event of events) {\n if (!isAllDayEvent(event)) continue\n\n let first = -1\n let last = -1\n for (let i = 0; i < days.length; i++) {\n if (coversDay(event, days[i]!)) {\n if (first === -1) first = i\n last = i\n }\n }\n if (first === -1) continue\n\n spans.push({\n id: event.id,\n startIndex: first,\n span: last - first + 1,\n continuesBefore: compareISO(event.start, days[first]!) < 0,\n continuesAfter: compareISO(lastDayOf(event), days[last]!) > 0,\n lane: 0,\n })\n }\n\n spans.sort((a, b) => a.startIndex - b.startIndex || b.span - a.span || compareId(a.id, b.id))\n\n const laneEnds: number[] = []\n for (const span of spans) {\n let lane = laneEnds.findIndex((end) => end < span.startIndex)\n if (lane === -1) {\n lane = laneEnds.length\n laneEnds.push(0)\n }\n laneEnds[lane] = span.startIndex + span.span - 1\n span.lane = lane\n }\n\n return spans\n}\n\n/** Where a moment sits in the visible window, as a unitless fraction the stylesheet scales. */\nexport function fractionOf(minutes: number, timeWindow: TimeWindow): number {\n const span = timeWindow.end - timeWindow.start\n return span > 0 ? clamp((minutes - timeWindow.start) / span, 0, 1) : 0\n}\n\n/** The measurements of the grid a pointer is being read against, in viewport coordinates. */\nexport interface GridGeometry {\n top: number\n height: number\n /** The edge the first column starts at: the left one normally, the right one in RTL. */\n inlineStart: number\n inlineSize: number\n columns: number\n}\n\n/**\n * Turns a point on the screen into a point on the calendar: which day column it fell in, and\n * what moment that height stands for. That is what makes a drag that wanders off the component\n * behave as the user expects instead of stopping dead.\n */\nexport function pointToCell(\n point: { x: number; y: number },\n geometry: GridGeometry,\n timeWindow: TimeWindow,\n rtl: boolean,\n): { columnIndex: number; minutes: number } {\n const columnIndex = columnAt(point.x, geometry, rtl)\n\n const fraction = geometry.height > 0 ? (point.y - geometry.top) / geometry.height : 0\n const minutes = clamp(\n timeWindow.start + fraction * (timeWindow.end - timeWindow.start),\n timeWindow.start,\n timeWindow.end,\n )\n\n return { columnIndex, minutes }\n}\n\n/** Rounds a moment to the nearest step the calendar allows. */\nexport function snapToSlot(minutes: number, step: number): number {\n const size = step > 0 ? step : 1\n return clamp(Math.round(minutes / size) * size, 0, MINUTES_PER_DAY)\n}\n\n/** Rounds a moment DOWN to the step containing it: where a drawn slot begins. */\nexport function floorToSlot(minutes: number, step: number): number {\n const size = step > 0 ? step : 1\n return clamp(Math.floor(minutes / size) * size, 0, MINUTES_PER_DAY)\n}\n\n/**\n * How many whole days an event covers beyond its first: zero for one that starts and ends\n * on the same day, two for a trip from Monday to Wednesday.\n */\nexport function daySpan(times: CalendarEventTimes): number {\n const start = parseISO(times.start)\n const end = parseISO(times.end)\n if (!start || !end) return 0\n return Math.max(0, Math.round((end.getTime() - start.getTime()) / MS_PER_DAY))\n}\n\n/** Moves an event to another day, KEEPING its length in days as well as its times. */\nexport function moveEventToDay(origin: CalendarEventTimes, target: string): CalendarEventTimes {\n if (parseISO(target) === null) return origin\n return {\n start: target,\n end: addDays(target, daySpan(origin)),\n startTime: origin.startTime,\n endTime: origin.endTime,\n }\n}\n\n/**\n * Which column a horizontal position falls in, counted in reading order and held inside the\n * grid. The inline half both grids share: the time grid's block axis is a moment, the month's\n * a row.\n */\nfunction columnAt(x: number, geometry: GridGeometry, rtl: boolean): number {\n const columns = Math.max(1, geometry.columns)\n const columnSize = geometry.inlineSize / columns\n const offset = rtl ? geometry.inlineStart - x : x - geometry.inlineStart\n return clamp(columnSize > 0 ? Math.floor(offset / columnSize) : 0, 0, columns - 1)\n}\n\n/** The measurements of a month grid: the same struct, with rows where a time window was. */\nexport interface MonthGeometry extends GridGeometry {\n rows: number\n}\n\n/** Turns a point on the screen into a square of the month. */\nexport function pointToMonthCell(\n point: { x: number; y: number },\n geometry: MonthGeometry,\n rtl: boolean,\n): { columnIndex: number; rowIndex: number } {\n const rows = Math.max(1, geometry.rows)\n const columnIndex = columnAt(point.x, geometry, rtl)\n\n const rowSize = geometry.height / rows\n const rowIndex = clamp(\n rowSize > 0 ? Math.floor((point.y - geometry.top) / rowSize) : 0,\n 0,\n rows - 1,\n )\n\n return { columnIndex, rowIndex }\n}\n\n/**\n * Which inline edge a point is resting against, as a direction to page in: -1 for the start\n * edge, 1 for the end one, nothing in between.\n */\nexport function inlineEdgeAt(\n x: number,\n geometry: { inlineStart: number; inlineSize: number },\n band: number,\n rtl: boolean,\n): -1 | 1 | null {\n if (band <= 0 || geometry.inlineSize <= 0) return null\n const offset = rtl ? geometry.inlineStart - x : x - geometry.inlineStart\n // Past the far side of the box counts as being against that edge: a pointer dragged clean\n // off the calendar is asking to keep going, not to stop.\n if (offset < band) return -1\n if (offset > geometry.inlineSize - band) return 1\n return null\n}\n\n/**\n * How hard a point near the top or bottom of a box is asking it to scroll: -1 at the very top,\n * 1 at the very bottom, 0 anywhere in the middle.\n */\nexport function blockEdgeAt(\n y: number,\n geometry: { top: number; height: number },\n band: number,\n): number {\n if (band <= 0 || geometry.height <= 0) return 0\n const fromTop = y - geometry.top\n const fromBottom = geometry.top + geometry.height - y\n if (fromTop < band) return -clamp((band - fromTop) / band, 0, 1)\n if (fromBottom < band) return clamp((band - fromBottom) / band, 0, 1)\n return 0\n}\n\n/**\n * A box that measures nothing contains EVERYTHING. That is the same answer `inlineEdgeAt` and\n * `blockEdgeAt` give a box of no size, and for the same reason: with no measurement there is no\n * outside to be on.\n */\nexport function pointWithin(\n point: { x: number; y: number },\n box: { left: number; top: number; width: number; height: number },\n): boolean {\n if (box.width <= 0 || box.height <= 0) return true\n return (\n point.x >= box.left &&\n point.x <= box.left + box.width &&\n point.y >= box.top &&\n point.y <= box.top + box.height\n )\n}\n\n/** The times of an event, as the shape the move and resize events carry. */\nexport function timesOf(event: CalendarEvent): CalendarEventTimes {\n return {\n start: event.start,\n end: event.end,\n startTime: event.startTime,\n endTime: event.endTime,\n }\n}\n\n/**\n * Whether two placements are the same, field for field. A slot is a quarter of an hour, some\n * sixteen pixels at the default hour height, so most pointer moves land on the times already\n * shown, and the gesture state is deeply reactive, so an equal but new object would still\n * re-run the whole layout and re-render every cell of the grid for a picture that did not\n * change.\n */\nexport function sameTimes(a: CalendarEventTimes, b: CalendarEventTimes): boolean {\n return (\n a.start === b.start && a.end === b.end && a.startTime === b.startTime && a.endTime === b.endTime\n )\n}\n\n/** Today, as the calendar reads it. Kept here so the component has one place to call. */\nexport function todayISO(): string {\n return formatISO(new Date())\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"layout.js","names":["MINUTES_PER_DAY","DAYS_PER_WEEK","MS_PER_DAY","compareId","left","a","right","b","windowOf","start","clamp","startHour","endHour","timeOf","held","minutes","pad2","minutesAt","minutesOf","time","fallback","normalizeWeekdays","seen","kept","day","weekdays","value","first","firstDayOfWeek","i","isVisibleDay","date","parseISO","iso","snapToVisibleDay","current","addDays","direction","advanceVisibleDays","count","remaining","guard","columnCount","view","customDays","visibleDays","anchor","year","month0","days","daysInMonth","isoOf","offset","weekStart","total","stepAnchor","addMonths","visibleRange","durationOf","daySpan","times","spansMidnight","compareISO","isAllDayEvent","event","order","timedSegments","index","segments","push","dayIndex","rawEnd","timeWindow","rawStart","end","minDuration","part","events","packDayColumn","sorted","placed","cluster","columnEnds","clusterEnd","flush","columns","byColumn","item","span","other","segment","column","monthWeeks","cells","buildMonthGrid","weeks","week","cell","monthsOfYear","lastDayOf","coversDay","eventsByDay","buckets","last","from","to","ranked","morning","byDay","list","compareRanked","packAllDay","spans","laneEnds","lane","fractionOf","pointToCell","columnIndex","columnAt","point","geometry","rtl","fraction","snapToSlot","size","step","floorToSlot","moveEventToDay","target","origin","columnSize","x","pointToMonthCell","rows","rowSize","inlineEdgeAt","band","blockEdgeAt","fromTop","y","fromBottom","pointWithin","box","timesOf","sameTimes","todayISO","formatISO"],"sources":["../../../src/components/VCalendar/layout.ts"],"sourcesContent":["// @core\n/**\n * Pure calendar layout shared by its views; component ownership keeps agenda-specific contracts\n * out of general utilities.\n */\nimport {\n addDays,\n addMonths,\n buildMonthGrid,\n compareISO,\n daysInMonth,\n formatISO,\n isoOf,\n parseISO,\n} from '../../utils/date'\nimport { clamp } from '../../utils/number'\nimport { pad2 } from '../../utils/text'\nimport { minutesOf } from '../../utils/time'\n\nimport type { MonthCell } from '../../utils/date'\nimport type { CalendarEvent, CalendarEventId, CalendarEventTimes, CalendarView } from './types'\n\n/** An hour, in the minutes every time here is counted in: one row of a time grid. */\nexport const MINUTES_PER_HOUR = 60\n\n/** How many minutes a day holds. The upper bound of every time computed here. */\nexport const MINUTES_PER_DAY = 24 * MINUTES_PER_HOUR\n\nconst DAYS_PER_WEEK = 7\n\n/** A day in milliseconds, for counting the days between two dates. */\nconst MS_PER_DAY = 24 * 60 * 60 * 1000\n\n/** How far the pointer must travel before a press becomes a drag rather than a click. */\nexport const DRAG_THRESHOLD = 3\n\n/**\n * This must not be `localeCompare`. An id is an opaque key, never user-facing text, so there is\n * nothing here to collate; and `localeCompare` with no locale resolves against the RUNTIME's\n * default, which differs between Node and the browser.\n */\nfunction compareId(a: CalendarEventId, b: CalendarEventId): number {\n const left = String(a)\n const right = String(b)\n return left < right ? -1 : left > right ? 1 : 0\n}\n\n/** The slice of the day a calendar is showing, as minutes since midnight. */\nexport interface TimeWindow {\n start: number\n end: number\n}\n\n/** Turns the `dayStart`/`dayEnd` props, given in hours, into the window the rest works in. */\nexport function windowOf(startHour: number, endHour: number): TimeWindow {\n const start = clamp(\n Math.round(startHour * MINUTES_PER_HOUR),\n 0,\n MINUTES_PER_DAY - MINUTES_PER_HOUR,\n )\n const end = clamp(\n Math.round(endHour * MINUTES_PER_HOUR),\n start + MINUTES_PER_HOUR,\n MINUTES_PER_DAY,\n )\n return { start, end }\n}\n\n/**\n * The value is held one minute short of midnight rather than allowed to reach it. A day's last\n * moment is 1440 in this arithmetic, but `24:00` is not a time any of the design system's\n * helpers accept (`isValidTime` rejects it).\n */\nexport function timeOf(minutes: number): string {\n const held = clamp(Math.round(minutes), 0, MINUTES_PER_DAY - 1)\n return `${pad2(Math.floor(held / MINUTES_PER_HOUR))}:${pad2(held % MINUTES_PER_HOUR)}`\n}\n\n/** An `HH:mm` string into minutes since midnight; `fallback` when it is not one. */\nexport function minutesAt(time: string | undefined, fallback: number): number {\n return minutesOf(time) ?? fallback\n}\n\n/** The weekdays a calendar shows, in reading order. */\nexport function normalizeWeekdays(\n weekdays: readonly number[] | undefined,\n firstDayOfWeek: number,\n): number[] {\n const seen = new Set<number>()\n const kept: number[] = []\n for (const day of weekdays ?? []) {\n const value = Math.trunc(day)\n if (value >= 0 && value <= 6 && !seen.has(value)) {\n seen.add(value)\n kept.push(value)\n }\n }\n if (kept.length > 0) return kept\n // Monday when the day given is not a number, the fallback `firstDayOfWeekFor` uses too.\n const first = Number.isFinite(firstDayOfWeek) ? ((Math.trunc(firstDayOfWeek) % 7) + 7) % 7 : 1\n return Array.from({ length: DAYS_PER_WEEK }, (_, i) => (first + i) % 7)\n}\n\n/** Whether a date falls on one of the visible weekdays. */\nexport function isVisibleDay(iso: string, weekdays: readonly number[]): boolean {\n const date = parseISO(iso)\n return date !== null && weekdays.includes(date.getDay())\n}\n\n/** The first visible day at or after `iso` (or at or before it, going backwards). */\nexport function snapToVisibleDay(\n iso: string,\n weekdays: readonly number[],\n direction: -1 | 1 = 1,\n): string {\n if (weekdays.length === 0) return iso\n let current = iso\n for (let i = 0; i < DAYS_PER_WEEK; i++) {\n if (isVisibleDay(current, weekdays)) return current\n current = addDays(current, direction)\n }\n return iso\n}\n\n/** Moves `count` VISIBLE days from `iso`, skipping over the hidden ones. */\nexport function advanceVisibleDays(\n iso: string,\n count: number,\n weekdays: readonly number[],\n): string {\n if (count === 0 || weekdays.length === 0) return iso\n const direction = count > 0 ? 1 : -1\n let current = iso\n let remaining = Math.abs(count)\n // Bounded so a malformed weekday list can never spin: at worst one visible day costs\n // seven calendar days, so this is the same walk with its worst case written down.\n let guard = Math.abs(count) * DAYS_PER_WEEK + DAYS_PER_WEEK\n while (remaining > 0 && guard-- > 0) {\n current = addDays(current, direction)\n if (isVisibleDay(current, weekdays)) remaining--\n }\n return current\n}\n\n/** How many day columns a view shows, before the visible-weekday filter applies. */\nexport function columnCount(view: CalendarView, customDays: number): number {\n if (view === 'day') return 1\n if (view === '4days') return 4\n if (view === 'custom') return clamp(Math.trunc(customDays), 1, 31)\n return DAYS_PER_WEEK\n}\n\n/** The days a view shows, in reading order. */\nexport function visibleDays(\n anchor: string,\n view: CalendarView,\n weekdays: readonly number[],\n customDays: number,\n): string[] {\n if (weekdays.length === 0 || parseISO(anchor) === null) return []\n if (view === 'year') return []\n\n if (view === 'month') {\n const date = parseISO(anchor)!\n const year = date.getFullYear()\n const month0 = date.getMonth()\n const days: string[] = []\n for (let day = 1; day <= daysInMonth(year, month0); day++) {\n const iso = isoOf(year, month0, day)\n if (isVisibleDay(iso, weekdays)) days.push(iso)\n }\n return days\n }\n\n if (view === 'week') {\n const date = parseISO(anchor)!\n const offset = (date.getDay() - weekdays[0]! + DAYS_PER_WEEK) % DAYS_PER_WEEK\n const weekStart = addDays(anchor, -offset)\n const days: string[] = []\n for (let i = 0; i < DAYS_PER_WEEK; i++) {\n const iso = addDays(weekStart, i)\n if (isVisibleDay(iso, weekdays)) days.push(iso)\n }\n return days\n }\n\n const total = columnCount(view, customDays)\n const days: string[] = [snapToVisibleDay(anchor, weekdays)]\n for (let i = 1; i < total; i++) days.push(advanceVisibleDays(days[i - 1]!, 1, weekdays))\n return days\n}\n\n/**\n * The day-shaped views step over VISIBLE days, not calendar ones. Stepping by one calendar day\n * from a Friday in a Monday-to-Friday calendar would land on a Saturday the grid does not draw;\n * the view would then show the same week it already showed, and the button would look broken\n * with nothing in the console to say why.\n */\nexport function stepAnchor(\n anchor: string,\n view: CalendarView,\n direction: -1 | 1,\n weekdays: readonly number[],\n customDays: number,\n): string {\n if (parseISO(anchor) === null) return anchor\n if (view === 'month') return addMonths(anchor, direction)\n if (view === 'year') return addMonths(anchor, direction * 12)\n if (view === 'week') return snapToVisibleDay(addDays(anchor, direction * DAYS_PER_WEEK), weekdays)\n return advanceVisibleDays(anchor, direction * columnCount(view, customDays), weekdays)\n}\n\n/** The first and last day a view covers, which names it in the toolbar. */\nexport function visibleRange(\n anchor: string,\n view: CalendarView,\n weekdays: readonly number[],\n customDays: number,\n): { start: string; end: string } {\n if (view === 'year') {\n // No clock read here: the server and the browser must name the same range.\n const date = parseISO(anchor)\n if (!date) return { start: anchor, end: anchor }\n return { start: isoOf(date.getFullYear(), 0, 1), end: isoOf(date.getFullYear(), 11, 31) }\n }\n const days = visibleDays(anchor, view, weekdays, customDays)\n if (days.length === 0) return { start: anchor, end: anchor }\n return { start: days[0]!, end: days[days.length - 1]! }\n}\n\n/** How long an event lasts, in minutes, counting the days between its dates. */\nexport function durationOf(times: CalendarEventTimes): number {\n return (\n daySpan(times) * MINUTES_PER_DAY +\n minutesAt(times.endTime, MINUTES_PER_DAY) -\n minutesAt(times.startTime, 0)\n )\n}\n\n/** Whether an event runs from one day into the next without lasting a whole day. */\nexport function spansMidnight(times: CalendarEventTimes): boolean {\n return compareISO(times.start, times.end) < 0 && durationOf(times) < MINUTES_PER_DAY\n}\n\n/** Whether an event belongs in the band above the grid rather than in a day's column. */\nexport function isAllDayEvent(event: CalendarEvent): boolean {\n if (event.allDay === true) return true\n const order = compareISO(event.start, event.end)\n if (order === 0) return false\n return order > 0 || !spansMidnight(event)\n}\n\n/**\n * Which piece of its event a box is: the whole of it, or one side of midnight for an event\n * that runs from one day into the next.\n */\nexport type SegmentPart = 'whole' | 'head' | 'tail'\n\n/** One event's box in one day column, in minutes since midnight. */\nexport interface EventSegment {\n id: CalendarEventId\n /** Which of the visible columns it belongs to. */\n dayIndex: number\n start: number\n end: number\n /**\n * Whether the card carries on past its top or bottom edge: the window cut it off, or\n * midnight did. Both are drawn the same way.\n */\n clippedStart: boolean\n clippedEnd: boolean\n /**\n * `head` is the evening of an event running past midnight and `tail` its morning. Only a\n * `whole` or a `tail` holds the event's real end, which its resize strip drags.\n */\n part: SegmentPart\n}\n\n/**\n * Cuts the timed events into the boxes the day columns draw. Were the minimum applied during\n * packing instead, two events fifteen minutes apart would be laid out as though they did not\n * overlap and then drawn as though they did.\n */\nexport function timedSegments(\n events: readonly CalendarEvent[],\n days: readonly string[],\n timeWindow: TimeWindow,\n minDuration: number,\n): EventSegment[] {\n const index = new Map(days.map((iso, i) => [iso, i]))\n const segments: EventSegment[] = []\n\n const push = (\n id: CalendarEventId,\n dayIndex: number | undefined,\n rawStart: number,\n rawEnd: number,\n part: SegmentPart,\n ) => {\n if (dayIndex === undefined) return\n if (rawEnd <= timeWindow.start || rawStart >= timeWindow.end) return\n const start = clamp(rawStart, timeWindow.start, timeWindow.end - 1)\n const end = clamp(Math.max(rawEnd, start + minDuration), start + 1, timeWindow.end)\n segments.push({\n id,\n dayIndex,\n start,\n end,\n clippedStart: part === 'tail' || rawStart < timeWindow.start,\n clippedEnd: part === 'head' || rawEnd > timeWindow.end,\n part,\n })\n }\n\n for (const event of events) {\n if (isAllDayEvent(event)) continue\n const rawStart = minutesAt(event.startTime, timeWindow.start)\n\n if (compareISO(event.start, event.end) === 0) {\n const rawEnd = Math.max(minutesAt(event.endTime, rawStart + minDuration), rawStart + 1)\n push(event.id, index.get(event.start), rawStart, rawEnd, 'whole')\n continue\n }\n\n /*\n * An event ending at midnight exactly has nothing on its second day, so it is drawn whole;\n * a tail of no length would otherwise be stretched to a slot and show as a stub at 00:00.\n */\n const rawEnd = minutesAt(event.endTime, 0)\n if (rawEnd === 0) {\n push(event.id, index.get(event.start), rawStart, MINUTES_PER_DAY, 'whole')\n continue\n }\n push(event.id, index.get(event.start), rawStart, MINUTES_PER_DAY, 'head')\n push(event.id, index.get(event.end), 0, rawEnd, 'tail')\n }\n\n return segments\n}\n\n/** A segment once it knows how much of its column's width it gets. */\nexport interface PlacedSegment extends EventSegment {\n /** Which column of its cluster it sits in, counted from zero. */\n column: number\n /** How many columns it takes up: more than one when the room beside it is free. */\n span: number\n /** How many columns its cluster has. It is what both of the above are read against. */\n columns: number\n}\n\n/**\n * Shares one day's width out between the events happening at the same time. Overlap is strictly\n * `a.start < b.end && b.start < a.end`, so events that merely touch (one ending exactly as the\n * next begins) share a column instead of splitting the width.\n */\nexport function packDayColumn(segments: readonly EventSegment[]): PlacedSegment[] {\n const sorted = [...segments].sort(\n (a, b) => a.start - b.start || b.end - b.start - (a.end - a.start) || compareId(a.id, b.id),\n )\n\n const placed: PlacedSegment[] = []\n let cluster: PlacedSegment[] = []\n let columnEnds: number[] = []\n let clusterEnd = -Infinity\n\n const flush = () => {\n const columns = columnEnds.length\n /*\n * The cluster filed by column first, so asking \"is the room beside me free?\" reads that one\n * column's occupants rather than the whole cluster: a crowded morning of k events across c\n * columns otherwise costs k squared per column crossed.\n */\n const byColumn: PlacedSegment[][] = Array.from({ length: columns }, () => [])\n for (const item of cluster) byColumn[item.column]!.push(item)\n for (const item of cluster) {\n let span = 1\n while (\n item.column + span < columns &&\n !byColumn[item.column + span]!.some(\n (other) => other.start < item.end && item.start < other.end,\n )\n ) {\n span++\n }\n item.span = span\n item.columns = columns\n }\n placed.push(...cluster)\n cluster = []\n columnEnds = []\n clusterEnd = -Infinity\n }\n\n for (const segment of sorted) {\n if (segment.start >= clusterEnd && cluster.length > 0) flush()\n\n let column = columnEnds.findIndex((end) => end <= segment.start)\n if (column === -1) {\n column = columnEnds.length\n columnEnds.push(segment.end)\n } else {\n columnEnds[column] = segment.end\n }\n\n cluster.push({ ...segment, column, span: 1, columns: 1 })\n clusterEnd = Math.max(clusterEnd, segment.end)\n }\n if (cluster.length > 0) flush()\n\n return placed\n}\n\n/** One square of the month view: a day, and whether it belongs to the month on show. */\nexport type { MonthCell }\n\n/** The month view, cut into weeks. */\nexport function monthWeeks(anchor: string, weekdays: readonly number[]): MonthCell[][] {\n const date = parseISO(anchor)\n if (!date || weekdays.length === 0) return []\n\n const cells = buildMonthGrid(date.getFullYear(), date.getMonth(), weekdays[0]!)\n const weeks: MonthCell[][] = []\n for (let i = 0; i < cells.length; i += DAYS_PER_WEEK) {\n const week = cells\n .slice(i, i + DAYS_PER_WEEK)\n .filter((cell) => isVisibleDay(cell.iso, weekdays))\n if (week.length > 0) weeks.push(week)\n }\n return weeks\n}\n\n/** The first day of each month of the anchor's year, which the year view lays out. */\nexport function monthsOfYear(anchor: string): string[] {\n const date = parseISO(anchor)\n if (!date) return []\n const year = date.getFullYear()\n return Array.from({ length: 12 }, (_, month0) => isoOf(year, month0, 1))\n}\n\n/** The last day an event puts anything on. */\nexport function lastDayOf(event: CalendarEvent): string {\n const endsAtMidnight =\n event.allDay !== true &&\n compareISO(event.start, event.end) < 0 &&\n minutesOf(event.endTime) === 0\n return endsAtMidnight ? addDays(event.end, -1) : event.end\n}\n\n/** Whether an event covers a given day at all, all-day or timed. */\nexport function coversDay(event: CalendarEvent, iso: string): boolean {\n return compareISO(iso, event.start) >= 0 && compareISO(iso, lastDayOf(event)) <= 0\n}\n\n/**\n * Every visible day's events, in the order a summary lists them: the all-day ones first, since\n * they frame the day rather than sit inside it, then the rest by when they start, the last tie\n * broken by id so the list cannot reshuffle for no reason.\n */\nexport function eventsByDay<T extends CalendarEvent>(\n events: readonly T[],\n days: readonly string[],\n): Map<string, T[]> {\n const buckets = new Map<string, Ranked<T>[]>()\n for (const iso of days) buckets.set(iso, [])\n if (days.length === 0) return new Map()\n\n // The grid's own bounds. `days` is in order, so its ends bound every walk below; which keeps\n // a long-running event from being walked outside the month on show.\n const first = days[0]!\n const last = days[days.length - 1]!\n\n for (const event of events) {\n /*\n * The walk below steps from one date to the next through `addDays`, which hands back a\n * string that is not a date unchanged. A datetime slipped into `start` would never be\n * stepped past, and the page would hang, on the server as well as in the browser.\n */\n if (!parseISO(event.start) || !parseISO(event.end)) continue\n const end = lastDayOf(event)\n const from = compareISO(event.start, first) > 0 ? event.start : first\n const to = compareISO(end, last) < 0 ? end : last\n if (compareISO(from, to) > 0) continue\n\n /*\n * Decorate-sort-undecorate, for the classic reason: the sort key is derived once per event\n * rather than once per comparison, which is where the time in this function goes.\n * `minutesAt` re-parses an `HH:mm` string on every ask, and a 42-square month holding 2000\n * events sorts some 17 000 pairs.\n */\n const ranked: Ranked<T> = {\n event,\n allDay: isAllDayEvent(event) ? 0 : 1,\n minutes: minutesAt(event.startTime, 0),\n id: String(event.id),\n }\n\n // An overnight event has been running since midnight on its second day, so it is ranked\n // from there, ahead of that morning's appointments, rather than by the evening before.\n const morning =\n ranked.allDay === 1 && compareISO(event.start, event.end) < 0\n ? { ...ranked, minutes: 0 }\n : ranked\n\n for (let iso = from; compareISO(iso, to) <= 0; iso = addDays(iso, 1)) {\n // A day the weekday filter hides has no bucket, so it is simply skipped: that is what\n // makes a Monday-to-Friday month cost nothing for the weekends it does not show.\n buckets.get(iso)?.push(iso === event.start ? ranked : morning)\n }\n }\n\n const byDay = new Map<string, T[]>()\n for (const [iso, list] of buckets) {\n list.sort(compareRanked)\n byDay.set(\n iso,\n list.map((item) => item.event),\n )\n }\n return byDay\n}\n\n/** An event with its sort key already worked out; see `eventsByDay`. */\ninterface Ranked<T> {\n event: T\n allDay: number\n minutes: number\n id: string\n}\n\n/** The order `eventsByDay` lists a day in, reading keys that are already computed. */\nfunction compareRanked<T>(a: Ranked<T>, b: Ranked<T>): number {\n return a.allDay - b.allDay || a.minutes - b.minutes || compareId(a.id, b.id)\n}\n\n/** One bar in the all-day band: the columns it covers, and the row it sits on. */\nexport interface AllDaySpan {\n id: CalendarEventId\n /** The first visible column it covers. */\n startIndex: number\n /** How many visible columns it covers, at least one. */\n span: number\n /** Whether it reaches beyond the days on show, on either side. */\n continuesBefore: boolean\n continuesAfter: boolean\n /** Which row of the band it sits on. */\n lane: number\n}\n\n/** Stacks the all-day bars into as few rows as they fit in. */\nexport function packAllDay(\n events: readonly CalendarEvent[],\n days: readonly string[],\n): AllDaySpan[] {\n const spans: AllDaySpan[] = []\n\n for (const event of events) {\n if (!isAllDayEvent(event)) continue\n\n let first = -1\n let last = -1\n for (let i = 0; i < days.length; i++) {\n if (coversDay(event, days[i]!)) {\n if (first === -1) first = i\n last = i\n }\n }\n if (first === -1) continue\n\n spans.push({\n id: event.id,\n startIndex: first,\n span: last - first + 1,\n continuesBefore: compareISO(event.start, days[first]!) < 0,\n continuesAfter: compareISO(lastDayOf(event), days[last]!) > 0,\n lane: 0,\n })\n }\n\n spans.sort((a, b) => a.startIndex - b.startIndex || b.span - a.span || compareId(a.id, b.id))\n\n const laneEnds: number[] = []\n for (const span of spans) {\n let lane = laneEnds.findIndex((end) => end < span.startIndex)\n if (lane === -1) {\n lane = laneEnds.length\n laneEnds.push(0)\n }\n laneEnds[lane] = span.startIndex + span.span - 1\n span.lane = lane\n }\n\n return spans\n}\n\n/** Where a moment sits in the visible window, as a unitless fraction the stylesheet scales. */\nexport function fractionOf(minutes: number, timeWindow: TimeWindow): number {\n const span = timeWindow.end - timeWindow.start\n return span > 0 ? clamp((minutes - timeWindow.start) / span, 0, 1) : 0\n}\n\n/** The measurements of the grid a pointer is being read against, in viewport coordinates. */\nexport interface GridGeometry {\n top: number\n height: number\n /** The edge the first column starts at: the left one normally, the right one in RTL. */\n inlineStart: number\n inlineSize: number\n columns: number\n}\n\n/**\n * Turns a point on the screen into a point on the calendar: which day column it fell in, and\n * what moment that height stands for. That is what makes a drag that wanders off the component\n * behave as the user expects instead of stopping dead.\n */\nexport function pointToCell(\n point: { x: number; y: number },\n geometry: GridGeometry,\n timeWindow: TimeWindow,\n rtl: boolean,\n): { columnIndex: number; minutes: number } {\n const columnIndex = columnAt(point.x, geometry, rtl)\n\n const fraction = geometry.height > 0 ? (point.y - geometry.top) / geometry.height : 0\n const minutes = clamp(\n timeWindow.start + fraction * (timeWindow.end - timeWindow.start),\n timeWindow.start,\n timeWindow.end,\n )\n\n return { columnIndex, minutes }\n}\n\n/** Rounds a moment to the nearest step the calendar allows. */\nexport function snapToSlot(minutes: number, step: number): number {\n const size = step > 0 ? step : 1\n return clamp(Math.round(minutes / size) * size, 0, MINUTES_PER_DAY)\n}\n\n/** Rounds a moment DOWN to the step containing it: where a drawn slot begins. */\nexport function floorToSlot(minutes: number, step: number): number {\n const size = step > 0 ? step : 1\n return clamp(Math.floor(minutes / size) * size, 0, MINUTES_PER_DAY)\n}\n\n/**\n * How many whole days an event covers beyond its first: zero for one that starts and ends\n * on the same day, two for a trip from Monday to Wednesday.\n */\nexport function daySpan(times: CalendarEventTimes): number {\n const start = parseISO(times.start)\n const end = parseISO(times.end)\n if (!start || !end) return 0\n return Math.max(0, Math.round((end.getTime() - start.getTime()) / MS_PER_DAY))\n}\n\n/** Moves an event to another day, KEEPING its length in days as well as its times. */\nexport function moveEventToDay(origin: CalendarEventTimes, target: string): CalendarEventTimes {\n if (parseISO(target) === null) return origin\n return {\n start: target,\n end: addDays(target, daySpan(origin)),\n startTime: origin.startTime,\n endTime: origin.endTime,\n }\n}\n\n/**\n * Which column a horizontal position falls in, counted in reading order and held inside the\n * grid. The inline half both grids share: the time grid's block axis is a moment, the month's\n * a row.\n */\nfunction columnAt(x: number, geometry: GridGeometry, rtl: boolean): number {\n const columns = Math.max(1, geometry.columns)\n const columnSize = geometry.inlineSize / columns\n const offset = rtl ? geometry.inlineStart - x : x - geometry.inlineStart\n return clamp(columnSize > 0 ? Math.floor(offset / columnSize) : 0, 0, columns - 1)\n}\n\n/** The measurements of a month grid: the same struct, with rows where a time window was. */\nexport interface MonthGeometry extends GridGeometry {\n rows: number\n}\n\n/** Turns a point on the screen into a square of the month. */\nexport function pointToMonthCell(\n point: { x: number; y: number },\n geometry: MonthGeometry,\n rtl: boolean,\n): { columnIndex: number; rowIndex: number } {\n const rows = Math.max(1, geometry.rows)\n const columnIndex = columnAt(point.x, geometry, rtl)\n\n const rowSize = geometry.height / rows\n const rowIndex = clamp(\n rowSize > 0 ? Math.floor((point.y - geometry.top) / rowSize) : 0,\n 0,\n rows - 1,\n )\n\n return { columnIndex, rowIndex }\n}\n\n/**\n * Which inline edge a point is resting against, as a direction to page in: -1 for the start\n * edge, 1 for the end one, nothing in between.\n */\nexport function inlineEdgeAt(\n x: number,\n geometry: { inlineStart: number; inlineSize: number },\n band: number,\n rtl: boolean,\n): -1 | 1 | null {\n if (band <= 0 || geometry.inlineSize <= 0) return null\n const offset = rtl ? geometry.inlineStart - x : x - geometry.inlineStart\n // Past the far side of the box counts as being against that edge: a pointer dragged clean\n // off the calendar is asking to keep going, not to stop.\n if (offset < band) return -1\n if (offset > geometry.inlineSize - band) return 1\n return null\n}\n\n/**\n * How hard a point near the top or bottom of a box is asking it to scroll: -1 at the very top,\n * 1 at the very bottom, 0 anywhere in the middle.\n */\nexport function blockEdgeAt(\n y: number,\n geometry: { top: number; height: number },\n band: number,\n): number {\n if (band <= 0 || geometry.height <= 0) return 0\n const fromTop = y - geometry.top\n const fromBottom = geometry.top + geometry.height - y\n if (fromTop < band) return -clamp((band - fromTop) / band, 0, 1)\n if (fromBottom < band) return clamp((band - fromBottom) / band, 0, 1)\n return 0\n}\n\n/**\n * A box that measures nothing contains EVERYTHING. That is the same answer `inlineEdgeAt` and\n * `blockEdgeAt` give a box of no size, and for the same reason: with no measurement there is no\n * outside to be on.\n */\nexport function pointWithin(\n point: { x: number; y: number },\n box: { left: number; top: number; width: number; height: number },\n): boolean {\n if (box.width <= 0 || box.height <= 0) return true\n return (\n point.x >= box.left &&\n point.x <= box.left + box.width &&\n point.y >= box.top &&\n point.y <= box.top + box.height\n )\n}\n\n/** The times of an event, as the shape the move and resize events carry. */\nexport function timesOf(event: CalendarEvent): CalendarEventTimes {\n return {\n start: event.start,\n end: event.end,\n startTime: event.startTime,\n endTime: event.endTime,\n }\n}\n\n/**\n * Whether two placements are the same, field for field. A slot is a quarter of an hour, some\n * sixteen pixels at the default hour height, so most pointer moves land on the times already\n * shown, and the gesture state is deeply reactive, so an equal but new object would still\n * re-run the whole layout and re-render every cell of the grid for a picture that did not\n * change.\n */\nexport function sameTimes(a: CalendarEventTimes, b: CalendarEventTimes): boolean {\n return (\n a.start === b.start && a.end === b.end && a.startTime === b.startTime && a.endTime === b.endTime\n )\n}\n\n/** Today, as the calendar reads it. Kept here so the component has one place to call. */\nexport function todayISO(): string {\n return formatISO(new Date())\n}\n"],"mappings":"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"}
@@ -40,20 +40,20 @@ function d(r, a, c, u, d) {
40
40
  }
41
41
  function f(i, a, c, l, d, f) {
42
42
  if (!f) return u(i, c, l, d);
43
- let p = o(i.startTime, d.start), m = e(Math.min(r({
43
+ let p = o(i.startTime, d.start), m = Math.min(r({
44
44
  ...i,
45
45
  end: a
46
- }), 1) * n + c, p + Math.max(l, 1), p + n - 1);
47
- return m <= 1440 ? {
46
+ }), 1), h = e(m * n + c, p + Math.max(l, 1), p + n - 1);
47
+ return h <= 1440 ? {
48
48
  start: i.start,
49
49
  end: i.start,
50
50
  startTime: s(p),
51
- endTime: s(Math.max(Math.min(m, d.end), p + Math.max(l, 1)))
51
+ endTime: s(Math.max(Math.min(h, d.end), p + Math.max(l, 1)))
52
52
  } : {
53
53
  start: i.start,
54
54
  end: t(i.start, 1),
55
55
  startTime: s(p),
56
- endTime: s(m - n)
56
+ endTime: s(h - n)
57
57
  };
58
58
  }
59
59
  function p(t, n, r, i, o) {