vectis-ui 0.10.0 → 0.10.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (334) 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.d.ts +6 -21
  4. package/dist/components/VAccordion/VAccordionItem.js.map +1 -1
  5. package/dist/components/VAccordion/VAccordionItem.vue_vue_type_script_setup_true_lang.js.map +1 -1
  6. package/dist/components/VAccordion/context.js.map +1 -1
  7. package/dist/components/VAvatar/VAvatar.d.ts +2 -12
  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.d.ts +2 -2
  11. package/dist/components/VAvatar/VAvatarGroup.js.map +1 -1
  12. package/dist/components/VAvatar/VAvatarGroup.vue_vue_type_script_setup_true_lang.js +6 -6
  13. package/dist/components/VAvatar/VAvatarGroup.vue_vue_type_script_setup_true_lang.js.map +1 -1
  14. package/dist/components/VAvatar/context.d.ts +1 -5
  15. package/dist/components/VAvatar/context.js.map +1 -1
  16. package/dist/components/VBadge/VBadge.d.ts +13 -27
  17. package/dist/components/VBadge/VBadge.js.map +1 -1
  18. package/dist/components/VBadge/VBadge.vue_vue_type_script_setup_true_lang.js.map +1 -1
  19. package/dist/components/VBreadcrumb/VBreadcrumb.d.ts +3 -9
  20. package/dist/components/VBreadcrumb/VBreadcrumb.js.map +1 -1
  21. package/dist/components/VBreadcrumb/VBreadcrumb.vue_vue_type_script_setup_true_lang.js.map +1 -1
  22. package/dist/components/VButton/VButton.d.ts +10 -17
  23. package/dist/components/VButton/VButton.js.map +1 -1
  24. package/dist/components/VButton/VButton.vue_vue_type_script_setup_true_lang.js.map +1 -1
  25. package/dist/components/VButton/VButtonGroup.d.ts +6 -15
  26. package/dist/components/VButton/VButtonGroup.js.map +1 -1
  27. package/dist/components/VButton/VButtonGroup.vue_vue_type_script_setup_true_lang.js.map +1 -1
  28. package/dist/components/VButton/context.d.ts +1 -9
  29. package/dist/components/VButton/context.js.map +1 -1
  30. package/dist/components/VCalendar/VCalendar.d.ts +9 -24
  31. package/dist/components/VCalendar/VCalendar.js.map +1 -1
  32. package/dist/components/VCalendar/VCalendar.vue_vue_type_script_setup_true_lang.js.map +1 -1
  33. package/dist/components/VCalendar/VCalendarEvent.d.ts +4 -13
  34. package/dist/components/VCalendar/VCalendarEvent.js.map +1 -1
  35. package/dist/components/VCalendar/VCalendarEvent.vue_vue_type_script_setup_true_lang.js.map +1 -1
  36. package/dist/components/VCalendar/VCalendarMonth.js.map +1 -1
  37. package/dist/components/VCalendar/VCalendarMonth.vue_vue_type_script_setup_true_lang.js.map +1 -1
  38. package/dist/components/VCalendar/VCalendarTimeGrid.d.ts +1 -5
  39. package/dist/components/VCalendar/VCalendarTimeGrid.js.map +1 -1
  40. package/dist/components/VCalendar/VCalendarTimeGrid.vue_vue_type_script_setup_true_lang.js.map +1 -1
  41. package/dist/components/VCalendar/VCalendarYear.js.map +1 -1
  42. package/dist/components/VCalendar/VCalendarYear.vue_vue_type_script_setup_true_lang.js.map +1 -1
  43. package/dist/components/VCalendar/color.d.ts +1 -7
  44. package/dist/components/VCalendar/color.js.map +1 -1
  45. package/dist/components/VCalendar/edgeStep.d.ts +5 -15
  46. package/dist/components/VCalendar/edgeStep.js.map +1 -1
  47. package/dist/components/VCalendar/gesture.d.ts +12 -36
  48. package/dist/components/VCalendar/gesture.js.map +1 -1
  49. package/dist/components/VCalendar/keyboard.d.ts +5 -42
  50. package/dist/components/VCalendar/keyboard.js.map +1 -1
  51. package/dist/components/VCalendar/layout.d.ts +38 -199
  52. package/dist/components/VCalendar/layout.js.map +1 -1
  53. package/dist/components/VCalendar/timeGrid.d.ts +3 -25
  54. package/dist/components/VCalendar/timeGrid.js.map +1 -1
  55. package/dist/components/VCalendar/types.d.ts +6 -23
  56. package/dist/components/VCarousel/VCarousel.d.ts +25 -96
  57. package/dist/components/VCarousel/VCarousel.js.map +1 -1
  58. package/dist/components/VCarousel/VCarousel.vue_vue_type_script_setup_true_lang.js +6 -6
  59. package/dist/components/VCarousel/VCarousel.vue_vue_type_script_setup_true_lang.js.map +1 -1
  60. package/dist/components/VCarousel/VCarouselItem.d.ts +1 -6
  61. package/dist/components/VCarousel/VCarouselItem.js.map +1 -1
  62. package/dist/components/VCarousel/VCarouselItem.vue_vue_type_script_setup_true_lang.js.map +1 -1
  63. package/dist/components/VCarousel/context.js.map +1 -1
  64. package/dist/components/VCheckbox/VCheckbox.d.ts +1 -5
  65. package/dist/components/VCheckbox/VCheckbox.js.map +1 -1
  66. package/dist/components/VCheckbox/VCheckbox.vue_vue_type_script_setup_true_lang.js.map +1 -1
  67. package/dist/components/VChip/VChip.d.ts +2 -8
  68. package/dist/components/VChip/VChip.js.map +1 -1
  69. package/dist/components/VChip/VChip.vue_vue_type_script_setup_true_lang.js.map +1 -1
  70. package/dist/components/VCombobox/VCombobox.d.ts +21 -59
  71. package/dist/components/VCombobox/VCombobox.js.map +1 -1
  72. package/dist/components/VCombobox/VCombobox.vue_vue_type_script_setup_true_lang.js +117 -119
  73. package/dist/components/VCombobox/VCombobox.vue_vue_type_script_setup_true_lang.js.map +1 -1
  74. package/dist/components/VCombobox/VComboboxGroup.js.map +1 -1
  75. package/dist/components/VCombobox/VComboboxGroup.vue_vue_type_script_setup_true_lang.js.map +1 -1
  76. package/dist/components/VCombobox/VComboboxOption.js.map +1 -1
  77. package/dist/components/VCombobox/VComboboxOption.vue_vue_type_script_setup_true_lang.js.map +1 -1
  78. package/dist/components/VCombobox/VComboboxSeparator.js.map +1 -1
  79. package/dist/components/VCombobox/VComboboxSeparator.vue_vue_type_script_setup_true_lang.js.map +1 -1
  80. package/dist/components/VCombobox/infiniteScroll.d.ts +4 -10
  81. package/dist/components/VCombobox/infiniteScroll.js.map +1 -1
  82. package/dist/components/VDataTable/VDataTable.d.ts +11 -36
  83. package/dist/components/VDataTable/VDataTable.js.map +1 -1
  84. package/dist/components/VDataTable/VDataTable.vue_vue_type_script_setup_true_lang.js +23 -20
  85. package/dist/components/VDataTable/VDataTable.vue_vue_type_script_setup_true_lang.js.map +1 -1
  86. package/dist/components/VDateInput/VDateInput.d.ts +12 -21
  87. package/dist/components/VDateInput/VDateInput.js.map +1 -1
  88. package/dist/components/VDateInput/VDateInput.vue_vue_type_script_setup_true_lang.js.map +1 -1
  89. package/dist/components/VDateInput/mask.d.ts +14 -59
  90. package/dist/components/VDateInput/mask.js.map +1 -1
  91. package/dist/components/VDatePicker/VDatePicker.d.ts +6 -12
  92. package/dist/components/VDatePicker/VDatePicker.js.map +1 -1
  93. package/dist/components/VDatePicker/VDatePicker.vue_vue_type_script_setup_true_lang.js.map +1 -1
  94. package/dist/components/VDatePicker/keyboard.d.ts +10 -42
  95. package/dist/components/VDatePicker/keyboard.js.map +1 -1
  96. package/dist/components/VDatePicker/names.d.ts +8 -22
  97. package/dist/components/VDatePicker/names.js.map +1 -1
  98. package/dist/components/VDialog/VDialog.d.ts +5 -10
  99. package/dist/components/VDialog/VDialog.js.map +1 -1
  100. package/dist/components/VDialog/VDialog.vue_vue_type_script_setup_true_lang.js +51 -53
  101. package/dist/components/VDialog/VDialog.vue_vue_type_script_setup_true_lang.js.map +1 -1
  102. package/dist/components/VDialog/VDialogAlert.d.ts +2 -3
  103. package/dist/components/VDialog/VDialogAlert.js.map +1 -1
  104. package/dist/components/VDialog/VDialogAlert.vue_vue_type_script_setup_true_lang.js.map +1 -1
  105. package/dist/components/VFileInput/VFileInput.d.ts +11 -37
  106. package/dist/components/VFileInput/VFileInput.js.map +1 -1
  107. package/dist/components/VFileInput/VFileInput.vue_vue_type_script_setup_true_lang.js.map +1 -1
  108. package/dist/components/VFileInput/truncate.d.ts +3 -23
  109. package/dist/components/VFileInput/truncate.js.map +1 -1
  110. package/dist/components/VFilePicker/VFilePicker.d.ts +15 -65
  111. package/dist/components/VFilePicker/VFilePicker.js.map +1 -1
  112. package/dist/components/VFilePicker/VFilePicker.vue_vue_type_script_setup_true_lang.js.map +1 -1
  113. package/dist/components/VFilePicker/fileKind.js.map +1 -1
  114. package/dist/components/VHotkeys/VHotkeys.d.ts +6 -15
  115. package/dist/components/VHotkeys/VHotkeys.js.map +1 -1
  116. package/dist/components/VHotkeys/VHotkeys.vue_vue_type_script_setup_true_lang.js.map +1 -1
  117. package/dist/components/VHotkeys/platform.d.ts +10 -49
  118. package/dist/components/VHotkeys/platform.js.map +1 -1
  119. package/dist/components/VIcon/VIcon.d.ts +7 -19
  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.d.ts +5 -19
  123. package/dist/components/VIcon/iconProps.js.map +1 -1
  124. package/dist/components/VIcon/resolver.d.ts +15 -43
  125. package/dist/components/VIcon/resolver.js.map +1 -1
  126. package/dist/components/VIcon/types.d.ts +7 -34
  127. package/dist/components/VIconButton/VIconButton.d.ts +2 -3
  128. package/dist/components/VIconButton/VIconButton.js.map +1 -1
  129. package/dist/components/VIconButton/VIconButton.vue_vue_type_script_setup_true_lang.js.map +1 -1
  130. package/dist/components/VInput/VInput.d.ts +14 -29
  131. package/dist/components/VInput/VInput.js.map +1 -1
  132. package/dist/components/VInput/VInput.vue_vue_type_script_setup_true_lang.js.map +1 -1
  133. package/dist/components/VInput/VInputGroup.js.map +1 -1
  134. package/dist/components/VInput/VInputGroup.vue_vue_type_script_setup_true_lang.js +34 -50
  135. package/dist/components/VInput/VInputGroup.vue_vue_type_script_setup_true_lang.js.map +1 -1
  136. package/dist/components/VInput/context.js.map +1 -1
  137. package/dist/components/VInputOTP/VInputOTP.d.ts +8 -16
  138. package/dist/components/VInputOTP/VInputOTP.js.map +1 -1
  139. package/dist/components/VInputOTP/VInputOTP.vue_vue_type_script_setup_true_lang.js +55 -63
  140. package/dist/components/VInputOTP/VInputOTP.vue_vue_type_script_setup_true_lang.js.map +1 -1
  141. package/dist/components/VMenu/VMenu.js.map +1 -1
  142. package/dist/components/VMenu/VMenu.vue_vue_type_script_setup_true_lang.js.map +1 -1
  143. package/dist/components/VMenu/VMenuGroup.d.ts +1 -6
  144. package/dist/components/VMenu/VMenuGroup.js.map +1 -1
  145. package/dist/components/VMenu/VMenuGroup.vue_vue_type_script_setup_true_lang.js.map +1 -1
  146. package/dist/components/VMenu/VMenuItem.d.ts +0 -5
  147. package/dist/components/VMenu/VMenuItem.js.map +1 -1
  148. package/dist/components/VMenu/VMenuItem.vue_vue_type_script_setup_true_lang.js.map +1 -1
  149. package/dist/components/VMenu/VMenuPanel.d.ts +1 -6
  150. package/dist/components/VMenu/VMenuPanel.js.map +1 -1
  151. package/dist/components/VMenu/VMenuPanel.vue_vue_type_script_setup_true_lang.js +2 -2
  152. package/dist/components/VMenu/VMenuPanel.vue_vue_type_script_setup_true_lang.js.map +1 -1
  153. package/dist/components/VMenu/VMenuSeparator.js.map +1 -1
  154. package/dist/components/VMenu/VMenuSeparator.vue_vue_type_script_setup_true_lang.js.map +1 -1
  155. package/dist/components/VMenu/context.d.ts +3 -11
  156. package/dist/components/VMenu/context.js.map +1 -1
  157. package/dist/components/VPagination/VPagination.d.ts +9 -20
  158. package/dist/components/VPagination/VPagination.js.map +1 -1
  159. package/dist/components/VPagination/VPagination.vue_vue_type_script_setup_true_lang.js.map +1 -1
  160. package/dist/components/VPopover/VPopover.d.ts +7 -18
  161. package/dist/components/VPopover/VPopover.js.map +1 -1
  162. package/dist/components/VPopover/VPopover.vue_vue_type_script_setup_true_lang.js +23 -27
  163. package/dist/components/VPopover/VPopover.vue_vue_type_script_setup_true_lang.js.map +1 -1
  164. package/dist/components/VProgressCircular/VProgressCircular.d.ts +2 -6
  165. package/dist/components/VProgressCircular/VProgressCircular.js.map +1 -1
  166. package/dist/components/VProgressCircular/VProgressCircular.vue_vue_type_script_setup_true_lang.js.map +1 -1
  167. package/dist/components/VProgressLinear/VProgressLinear.d.ts +4 -15
  168. package/dist/components/VProgressLinear/VProgressLinear.js.map +1 -1
  169. package/dist/components/VProgressLinear/VProgressLinear.vue_vue_type_script_setup_true_lang.js.map +1 -1
  170. package/dist/components/VRadio/VRadio.d.ts +1 -5
  171. package/dist/components/VRadio/VRadio.js.map +1 -1
  172. package/dist/components/VRadio/VRadio.vue_vue_type_script_setup_true_lang.js.map +1 -1
  173. package/dist/components/VSeparator/VSeparator.d.ts +2 -15
  174. package/dist/components/VSeparator/VSeparator.js.map +1 -1
  175. package/dist/components/VSeparator/VSeparator.vue_vue_type_script_setup_true_lang.js.map +1 -1
  176. package/dist/components/VSideNavigation/VSideNavigation.d.ts +1 -1
  177. package/dist/components/VSideNavigation/VSideNavigation.js.map +1 -1
  178. package/dist/components/VSideNavigation/VSideNavigation.vue_vue_type_script_setup_true_lang.js.map +1 -1
  179. package/dist/components/VSideNavigation/VSideNavigationGroup.d.ts +1 -5
  180. package/dist/components/VSideNavigation/VSideNavigationGroup.js.map +1 -1
  181. package/dist/components/VSideNavigation/VSideNavigationGroup.vue_vue_type_script_setup_true_lang.js.map +1 -1
  182. package/dist/components/VSideNavigation/VSideNavigationItem.d.ts +1 -5
  183. package/dist/components/VSideNavigation/VSideNavigationItem.js.map +1 -1
  184. package/dist/components/VSideNavigation/VSideNavigationItem.vue_vue_type_script_setup_true_lang.js +80 -75
  185. package/dist/components/VSideNavigation/VSideNavigationItem.vue_vue_type_script_setup_true_lang.js.map +1 -1
  186. package/dist/components/VSideNavigation/VSideNavigationSeparator.js.map +1 -1
  187. package/dist/components/VSideNavigation/context.js.map +1 -1
  188. package/dist/components/VSkeletonLoader/VSkeletonLoader.d.ts +6 -19
  189. package/dist/components/VSkeletonLoader/VSkeletonLoader.js.map +1 -1
  190. package/dist/components/VSkeletonLoader/VSkeletonLoader.vue_vue_type_script_setup_true_lang.js.map +1 -1
  191. package/dist/components/VSlider/VSlider.d.ts +5 -13
  192. package/dist/components/VSlider/VSlider.js.map +1 -1
  193. package/dist/components/VSlider/VSlider.vue_vue_type_script_setup_true_lang.js.map +1 -1
  194. package/dist/components/VSnackbar/VSnackbar.js.map +1 -1
  195. package/dist/components/VSnackbar/VSnackbar.vue_vue_type_script_setup_true_lang.js.map +1 -1
  196. package/dist/components/VSnackbar/state.d.ts +4 -17
  197. package/dist/components/VSnackbar/state.js.map +1 -1
  198. package/dist/components/VSpinner/VSpinner.d.ts +3 -5
  199. package/dist/components/VSpinner/VSpinner.js.map +1 -1
  200. package/dist/components/VSpinner/VSpinner.vue_vue_type_script_setup_true_lang.js.map +1 -1
  201. package/dist/components/VSwitch/VSwitch.js.map +1 -1
  202. package/dist/components/VSwitch/VSwitch.vue_vue_type_script_setup_true_lang.js.map +1 -1
  203. package/dist/components/VTabs/VTab.d.ts +1 -5
  204. package/dist/components/VTabs/VTab.js.map +1 -1
  205. package/dist/components/VTabs/VTab.vue_vue_type_script_setup_true_lang.js.map +1 -1
  206. package/dist/components/VTabs/VTabPanel.js.map +1 -1
  207. package/dist/components/VTabs/VTabPanel.vue_vue_type_script_setup_true_lang.js.map +1 -1
  208. package/dist/components/VTabs/VTabs.d.ts +5 -17
  209. package/dist/components/VTabs/VTabs.js.map +1 -1
  210. package/dist/components/VTabs/VTabs.vue_vue_type_script_setup_true_lang.js.map +1 -1
  211. package/dist/components/VTabs/context.js.map +1 -1
  212. package/dist/components/VTextarea/VTextarea.d.ts +13 -20
  213. package/dist/components/VTextarea/VTextarea.js.map +1 -1
  214. package/dist/components/VTextarea/VTextarea.vue_vue_type_script_setup_true_lang.js.map +1 -1
  215. package/dist/components/VTimeInput/VTimeInput.d.ts +8 -21
  216. package/dist/components/VTimeInput/VTimeInput.js.map +1 -1
  217. package/dist/components/VTimeInput/VTimeInput.vue_vue_type_script_setup_true_lang.js.map +1 -1
  218. package/dist/components/VTimeInput/search.d.ts +3 -34
  219. package/dist/components/VTimeInput/search.js.map +1 -1
  220. package/dist/components/VTimePicker/VTimePicker.d.ts +9 -31
  221. package/dist/components/VTimePicker/VTimePicker.js.map +1 -1
  222. package/dist/components/VTimePicker/VTimePicker.vue_vue_type_script_setup_true_lang.js.map +1 -1
  223. package/dist/components/VTimePicker/limits.d.ts +18 -45
  224. package/dist/components/VTimePicker/limits.js.map +1 -1
  225. package/dist/components/VToast/VToast.js.map +1 -1
  226. package/dist/components/VToast/VToast.vue_vue_type_script_setup_true_lang.js.map +1 -1
  227. package/dist/components/VToast/VToaster.js.map +1 -1
  228. package/dist/components/VToast/VToaster.vue_vue_type_script_setup_true_lang.js.map +1 -1
  229. package/dist/components/VToast/state.d.ts +2 -7
  230. package/dist/components/VToast/state.js.map +1 -1
  231. package/dist/components/VToggle/VToggle.d.ts +5 -9
  232. package/dist/components/VToggle/VToggle.js.map +1 -1
  233. package/dist/components/VToggle/VToggle.vue_vue_type_script_setup_true_lang.js.map +1 -1
  234. package/dist/components/VToggle/VToggleItem.d.ts +1 -9
  235. package/dist/components/VToggle/VToggleItem.js.map +1 -1
  236. package/dist/components/VToggle/VToggleItem.vue_vue_type_script_setup_true_lang.js.map +1 -1
  237. package/dist/components/VToggle/context.js.map +1 -1
  238. package/dist/components/VTooltip/VTooltip.d.ts +3 -16
  239. package/dist/components/VTooltip/VTooltip.js.map +1 -1
  240. package/dist/components/VTooltip/VTooltip.vue_vue_type_script_setup_true_lang.js +2 -2
  241. package/dist/components/VTooltip/VTooltip.vue_vue_type_script_setup_true_lang.js.map +1 -1
  242. package/dist/components/VTypography/VTypography.d.ts +4 -8
  243. package/dist/components/VTypography/VTypography.js.map +1 -1
  244. package/dist/components/VTypography/VTypography.vue_vue_type_script_setup_true_lang.js.map +1 -1
  245. package/dist/composables/useAriaLabel.js.map +1 -1
  246. package/dist/composables/useClearable.d.ts +2 -8
  247. package/dist/composables/useClearable.js.map +1 -1
  248. package/dist/composables/useControlShape.js.map +1 -1
  249. package/dist/composables/useDetailsOpen.d.ts +2 -10
  250. package/dist/composables/useDetailsOpen.js.map +1 -1
  251. package/dist/composables/useFieldIds.js.map +1 -1
  252. package/dist/composables/useFieldPanel.d.ts +4 -17
  253. package/dist/composables/useFieldPanel.js.map +1 -1
  254. package/dist/composables/useFileDrop.js.map +1 -1
  255. package/dist/composables/useFileField.d.ts +1 -5
  256. package/dist/composables/useFileField.js.map +1 -1
  257. package/dist/composables/useFocusoutDismiss.js.map +1 -1
  258. package/dist/composables/useIconClickHandlers.d.ts +4 -19
  259. package/dist/composables/useIconClickHandlers.js.map +1 -1
  260. package/dist/composables/useInertLink.d.ts +1 -1
  261. package/dist/composables/useInertLink.js.map +1 -1
  262. package/dist/composables/useLiveAnnouncer.js.map +1 -1
  263. package/dist/composables/useMaskedField.d.ts +12 -27
  264. package/dist/composables/useMaskedField.js.map +1 -1
  265. package/dist/composables/usePopover.d.ts +3 -11
  266. package/dist/composables/usePopover.js.map +1 -1
  267. package/dist/composables/useProgressValue.js.map +1 -1
  268. package/dist/composables/useRootAttrs.d.ts +0 -9
  269. package/dist/composables/useRootAttrs.js +11 -4
  270. package/dist/composables/useRootAttrs.js.map +1 -1
  271. package/dist/composables/useSlotNodes.d.ts +3 -14
  272. package/dist/composables/useSlotNodes.js.map +1 -1
  273. package/dist/composables/useTextLimit.d.ts +4 -16
  274. package/dist/composables/useTextLimit.js.map +1 -1
  275. package/dist/composables/useTimer.d.ts +2 -15
  276. package/dist/composables/useTimer.js.map +1 -1
  277. package/dist/i18n/en.js.map +1 -1
  278. package/dist/i18n/fr.js.map +1 -1
  279. package/dist/i18n/state.d.ts +9 -38
  280. package/dist/i18n/state.js.map +1 -1
  281. package/dist/i18n/types.d.ts +19 -81
  282. package/dist/icons.d.ts +2 -12
  283. package/dist/styles.css +1 -1
  284. package/dist/tokens/css.d.ts +3 -16
  285. package/dist/tokens/css.js.map +1 -1
  286. package/dist/tokens/index.d.ts +5 -0
  287. package/dist/tokens/index.js.map +1 -1
  288. package/dist/tokens/primitives.js.map +1 -1
  289. package/dist/tokens/semantic.d.ts +6 -23
  290. package/dist/tokens/semantic.js +5 -0
  291. package/dist/tokens/semantic.js.map +1 -1
  292. package/dist/tokens/themes/dark.js.map +1 -1
  293. package/dist/tokens/types.d.ts +2 -12
  294. package/dist/tokens/types.js.map +1 -1
  295. package/dist/tokens.json +14 -0
  296. package/dist/types.d.ts +3 -21
  297. package/dist/utils/array.d.ts +2 -4
  298. package/dist/utils/array.js.map +1 -1
  299. package/dist/utils/arrowNav.d.ts +2 -26
  300. package/dist/utils/arrowNav.js.map +1 -1
  301. package/dist/utils/chip.d.ts +1 -8
  302. package/dist/utils/chip.js.map +1 -1
  303. package/dist/utils/clock.d.ts +16 -39
  304. package/dist/utils/clock.js.map +1 -1
  305. package/dist/utils/css.d.ts +5 -16
  306. package/dist/utils/css.js.map +1 -1
  307. package/dist/utils/date.d.ts +17 -60
  308. package/dist/utils/date.js.map +1 -1
  309. package/dist/utils/direction.d.ts +2 -9
  310. package/dist/utils/direction.js.map +1 -1
  311. package/dist/utils/env.d.ts +2 -15
  312. package/dist/utils/env.js.map +1 -1
  313. package/dist/utils/file.d.ts +8 -46
  314. package/dist/utils/file.js.map +1 -1
  315. package/dist/utils/focus.d.ts +1 -14
  316. package/dist/utils/focus.js +1 -6
  317. package/dist/utils/focus.js.map +1 -1
  318. package/dist/utils/hostWarns.d.ts +3 -8
  319. package/dist/utils/hostWarns.js.map +1 -1
  320. package/dist/utils/ids.d.ts +2 -7
  321. package/dist/utils/ids.js.map +1 -1
  322. package/dist/utils/matcher.d.ts +1 -8
  323. package/dist/utils/matcher.js.map +1 -1
  324. package/dist/utils/memo.d.ts +1 -11
  325. package/dist/utils/memo.js.map +1 -1
  326. package/dist/utils/number.d.ts +1 -7
  327. package/dist/utils/number.js.map +1 -1
  328. package/dist/utils/text.d.ts +4 -23
  329. package/dist/utils/text.js.map +1 -1
  330. package/dist/utils/time.d.ts +4 -12
  331. package/dist/utils/time.js.map +1 -1
  332. package/dist/utils/vnode.d.ts +0 -10
  333. package/dist/utils/vnode.js.map +1 -1
  334. package/package.json +1 -1
@@ -1 +1 @@
1
- {"version":3,"file":"VCalendar.vue_vue_type_script_setup_true_lang.js","names":["$slots"],"sources":["../../../src/components/VCalendar/VCalendar.vue"],"sourcesContent":["<script setup lang=\"ts\" generic=\"E extends CalendarEvent\">\n// @a11y @ssr @core\n/**\n * An agenda: the days side by side, the hours running down them, the events drawn where they\n * fall.\n *\n * A place to READ and REARRANGE a schedule, never to write one. Opening an event for editing\n * stays with the consumer — this reports what was asked for and leaves the form to them.\n *\n * Everything is local ISO `YYYY-MM-DD` and 24-hour `HH:mm`, which is what keeps the server\n * and the browser in agreement. An event may name a `timezone`, and that name is SHOWN\n * beside its times but never applied: converting would move the card depending on where the\n * page was rendered, the one thing a calendar must not do.\n *\n * The JS is what the platform leaves no way round — there is no accessible time grid to\n * build on and no way to say \"these three meetings overlap, share the width\" in CSS, so the\n * ARIA grid pattern and the overlap layout are written by hand. Every geometric and\n * calendrical decision lives in `layout.ts`, pure, because jsdom lays nothing out and that is\n * the only place any of it can be tested.\n */\nimport { computed, onMounted, ref, useId, watch } from 'vue'\n\nimport VButton from '../VButton/VButton.vue'\nimport VIcon from '../VIcon/VIcon.vue'\nimport { arrow_drop_down as arrowDropDownIcon } from '../VIcon/icons/arrow_drop_down'\nimport { chevron_left as chevronLeftIcon } from '../VIcon/icons/chevron_left'\nimport { chevron_right as chevronRightIcon } from '../VIcon/icons/chevron_right'\nimport VIconButton from '../VIconButton/VIconButton.vue'\nimport VMenu from '../VMenu/VMenu.vue'\nimport VMenuItem from '../VMenu/VMenuItem.vue'\nimport VTypography from '../VTypography/VTypography.vue'\n\nimport { useAriaLabel } from '../../composables/useAriaLabel'\nimport { useLiveAnnouncer } from '../../composables/useLiveAnnouncer'\nimport { useRootAttrs } from '../../composables/useRootAttrs'\nimport { useTimer } from '../../composables/useTimer'\nimport { firstDayOfWeekFor, formatDateDisplay, formatDisplayRange } from '../../utils/date'\nimport { hourCycleFor, minutesOf } from '../../utils/time'\n\nimport { useMessages, useResolvedLocale } from '../../i18n/state'\n\nimport VCalendarMonth from './VCalendarMonth.vue'\nimport VCalendarTimeGrid, { type FocusedCell } from './VCalendarTimeGrid.vue'\nimport VCalendarYear from './VCalendarYear.vue'\nimport { EDGE_STEP_DELAY } from './edgeStep'\nimport {\n monthWeeks,\n monthsOfYear,\n normalizeWeekdays,\n stepAnchor,\n sameTimes,\n timeOf,\n timesOf,\n todayISO,\n visibleDays,\n visibleRange,\n windowOf,\n} from './layout'\nimport type {\n ActivatedCell,\n CalendarCell,\n CalendarEvent,\n CalendarEventId,\n CalendarEventSlotProps,\n CalendarEventTimes,\n CalendarFormat,\n CalendarView,\n} from './types'\n\nexport interface CalendarProps {\n /**\n * Which views the menu offers, in the order it lists them. Narrowing it is how a\n * calendar that only ever shows weeks stops offering anything else.\n */\n views?: CalendarView[]\n /** How many days the custom view shows, and how far Previous and Next step in it. */\n customDays?: number\n /**\n * Which weekdays are on show, as numbers from 0 for Sunday. `[1,2,3,4,5]` hides the\n * weekend everywhere. The ORDER matters as well: the first entry is the day a week\n * starts on, and it wins over `firstDayOfWeek`. Left out, the seven days starting on\n * `firstDayOfWeek`.\n */\n weekdays?: number[]\n /**\n * The day a week starts on, from 0 for Sunday, when `weekdays` is not given. Left out,\n * the locale decides.\n */\n firstDayOfWeek?: number\n /** The language the days, months and times are written in. Falls back to the global one. */\n locale?: string\n /**\n * Whether times are shown on a twelve or twenty-four hour clock. Left out, the reader's\n * language decides. It is the same prop, under the same name, as VTimePicker's.\n */\n format?: CalendarFormat\n /** The hour the grid starts at, from 0. */\n dayStart?: number\n /** The hour it ends at, up to 24. */\n dayEnd?: number\n /**\n * The step everything snaps to, in minutes: how far a nudge moves an event, and the unit a\n * slot is drawn out in.\n */\n slotDuration?: number\n /** Where the grid is scrolled to when it first appears, so the working day is in view. */\n scrollTime?: string\n /**\n * Leaves out the line drawn across today's column at the time it is now, and the dot on\n * its leading edge. Left in, it ticks once a minute while the calendar is on screen.\n */\n hideCurrentTime?: boolean\n /** How many events a day of the month view shows before it starts counting the rest. */\n monthEventLimit?: number\n /**\n * Stops events being moved and stretched, by dragging or with the keyboard. They\n * stay readable and clickable, and nothing else.\n */\n readonly?: boolean\n /**\n * Freezes the whole calendar: nothing can be moved, created or opened, no other period\n * can be reached, and everything greys out through the colour tokens. The cards leave the\n * tab order, the grid keeps its own so the agenda can still be read. That is what\n * separates this from `readonly`, where only the editing stops.\n */\n disabled?: boolean\n /**\n * Lets an empty stretch of a time grid be drawn out with the pointer, up or down from the\n * slot pressed. On release its times are reported through `event-create`, and nothing is\n * added to `events`: putting the event on the calendar is yours to do. A click, or Enter on a\n * focused cell, reports `cell-activate` with or without this.\n */\n creatable?: boolean\n /**\n * How long a dragged event has to rest against the side of the calendar before the view\n * turns to the previous or next period, in milliseconds. `0` turns that off.\n *\n * The wait is the point of it: paging the instant the pointer touched the edge would make\n * the last day of a week impossible to aim at.\n */\n edgeStepDelay?: number\n /** Stops dragging near the top or bottom of a time grid from scrolling it. */\n noEdgeScroll?: boolean\n /** What the calendar is called, for anyone who cannot see it. */\n label?: string\n}\n\nconst props = withDefaults(defineProps<CalendarProps>(), {\n views: () => ['day', '4days', 'week'],\n customDays: 4,\n weekdays: undefined,\n firstDayOfWeek: undefined,\n locale: undefined,\n format: undefined,\n dayStart: 0,\n dayEnd: 24,\n slotDuration: 15,\n scrollTime: '08:00',\n hideCurrentTime: false,\n monthEventLimit: 3,\n readonly: false,\n disabled: false,\n creatable: false,\n edgeStepDelay: EDGE_STEP_DELAY,\n noEdgeScroll: false,\n label: undefined,\n})\n\n/*\n * The wrapper-root pattern: the consumer's class and style stay on the outer box, and\n * everything else — their `id`, their `aria-*` — goes on the region, which is the part\n * that carries the role and is therefore the part they mean.\n */\ndefineOptions({ inheritAttrs: false })\n\n/** Which span the calendar is showing. It opens on the week. */\nconst view = defineModel<CalendarView>('view', { default: 'week' })\n\n// @ssr\n/*\n * The anchor is read from the clock at setup, so the server and the client can in\n * principle disagree across a midnight boundary. That is the trade VDatePicker already\n * makes for the month it opens on, and it is a safer one here: what the anchor decides is\n * a whole WEEK or month, which is the same on both sides for all but a few seconds a day.\n * Today's date, which marks a single column, is a different matter and is read below in\n * `onMounted` where the server cannot see it at all.\n */\n/**\n * The day the calendar is anchored on, as `YYYY-MM-DD`: the view shows the week, month or\n * year holding it. It opens on today.\n */\nconst date = defineModel<string>('date', { default: () => todayISO() })\n/**\n * What is on the calendar, empty to begin with. It is a MODEL rather than a plain prop\n * because dragging and resizing write back to it: the calendar rearranges what it is given\n * and hands the new list back, never mutating the one it received.\n *\n * Opening an event for editing stays with the consumer: this component reads and\n * rearranges, and never creates or deletes: a slot drawn out is reported, not added.\n */\nconst events = defineModel<E[]>('events', { default: () => [] })\n\nconst emit = defineEmits<{\n /** A card was clicked or activated: the cue to open an editor of your own. */\n 'event-activate': [event: E]\n /**\n * An empty part of the grid was activated, at this day and this time. A day of the month\n * view has no hour of its own, and reports the one the time grids start at.\n */\n 'cell-activate': [cell: CalendarCell]\n /**\n * An event was dragged or nudged somewhere else. It carries the event as it now stands and\n * where it came from, so undoing it needs no copy of your own. A gesture that ends where it\n * began reports nothing.\n */\n 'event-move': [event: E, previous: CalendarEventTimes]\n /** An event's end was dragged or nudged, in the same two parts. */\n 'event-resize': [event: E, previous: CalendarEventTimes]\n /**\n * An empty stretch of a day was drawn out, and these are its times. Nothing has been added\n * to `events`: this is the cue to make the event, in your own model or through your own form.\n */\n 'event-create': [times: CalendarEventTimes]\n}>()\n\ndefineSlots<{\n /** Extra controls in the toolbar, between the range and the view menu. */\n actions?(): unknown\n /** The content of one event's card, replacing the title and times. */\n event?(props: CalendarEventSlotProps<E>): unknown\n /** The head of one day column, replacing the weekday and the number. */\n 'day-header'?(props: { iso: string; weekday: string; dayText: string; today: boolean }): unknown\n /** The label beside the band of all-day events. */\n 'all-day-label'?(): unknown\n}>()\n\nconst m = useMessages()\nconst { rootClass, rootStyle, forwardedAttrs } = useRootAttrs()\n\nconst resolvedLocale = useResolvedLocale(() => props.locale)\nconst resolvedFormat = computed(() => props.format ?? hourCycleFor(resolvedLocale.value))\nconst resolvedWeekdays = computed(() =>\n normalizeWeekdays(\n props.weekdays,\n props.firstDayOfWeek ?? firstDayOfWeekFor(resolvedLocale.value),\n ),\n)\n\nconst timeWindow = computed(() => windowOf(props.dayStart, props.dayEnd))\n\nconst days = computed(() =>\n visibleDays(date.value, view.value, resolvedWeekdays.value, props.customDays),\n)\n\n/** Which view is a time grid, and which is a summary. Several things below turn on this. */\nconst isTimeGrid = computed(() => view.value !== 'month' && view.value !== 'year')\n\nconst weeks = computed(() =>\n view.value === 'month' ? monthWeeks(date.value, resolvedWeekdays.value) : [],\n)\n\nconst months = computed(() => (view.value === 'year' ? monthsOfYear(date.value) : []))\n\n// @ssr — today and the time it is now can only be known on the client: the server has no\n// way to tell either where the reader is, and rendering a guess would make the two markups\n// differ. Both stay null until then, and every rule that draws them is written to expect it.\nconst today = ref<string | null>(null)\nconst now = ref<number | null>(null)\n\nconst clock = useTimer()\n\n/**\n * Re-reads the clock, then arms itself for the top of the next minute — so the line moves\n * when the minute does rather than drifting by however long the interval was.\n *\n * TRAP — the floor on the delay is not a nicety. `useTimer` runs a delay of zero or less\n * SYNCHRONOUSLY, by design, so a tick that ever computed one would call itself straight back\n * and go on doing so until the stack gave out. A second is well below the resolution\n * anything here needs and comfortably above the point where that could happen.\n */\nfunction tick() {\n const at = new Date()\n now.value = at.getHours() * 60 + at.getMinutes()\n clock.start(tick, Math.max(1000, (60 - at.getSeconds()) * 1000))\n}\n\n/** Scrolls the time grid on show to `scrollTime`. */\nfunction scrollToStart() {\n const at = minutesOf(props.scrollTime)\n if (at !== null) gridRef.value?.scrollToMinutes(at)\n}\n\nonMounted(() => {\n today.value = todayISO()\n if (!props.hideCurrentTime) tick()\n scrollToStart()\n})\n\n// @core\n// The prop is a switch a consumer may flip after mount: the clock read at mount alone never\n// started when it was turned on later, and went on ticking when it was turned off.\nwatch(\n () => props.hideCurrentTime,\n (hidden) => {\n if (!hidden) return tick()\n clock.cancel()\n now.value = null\n },\n)\n\n/**\n * The grid, named by what it exposes rather than by `InstanceType<typeof …>`.\n *\n * TRAP — the usual form does not work here and the error it gives says nothing useful about\n * why. A generic `<script setup>` compiles to a FUNCTION, not to a class, so it has no\n * construct signature for `InstanceType` to read: the message complains that the component\n * \"provides no match for the signature `new (...args: any)`\", pointing at the template.\n * Writing the contract out is also the more honest of the two, since these two methods are\n * the whole of what this component asks of that one.\n */\nconst gridRef = ref<{\n focus(options?: FocusOptions): void\n scrollToMinutes(minutes: number): void\n} | null>(null)\n\n// @core\n// A time grid that appears after mount, a month switched to a week, opens at `scrollTime`\n// too. Post-flush, so the new grid is rendered and measurable when it is asked to scroll.\nwatch(gridRef, scrollToStart, { flush: 'post' })\n\n/** The region, the element a consumer's attributes land on. */\nconst regionEl = ref<HTMLElement | null>(null)\n\n/*\n * Which cell holds the tab stop, kept as two refs because the two kinds of view mean\n * different things by it: a time grid needs a day AND an hour, a month only a day. One ref\n * carrying an hour the month ignores would leave that hour to go stale, and the grid would\n * then reopen on whatever the month happened to leave behind.\n */\nconst focused = ref<FocusedCell>({ iso: date.value, minutes: timeWindow.value.start })\nconst focusedDay = ref(date.value)\n\nconst range = computed(() =>\n visibleRange(date.value, view.value, resolvedWeekdays.value, props.customDays),\n)\n\n/**\n * What the toolbar says the calendar is showing. Each view names itself at the coarsest\n * granularity that still identifies it: a single day says its weekday, a year says nothing\n * but the number.\n */\nconst rangeText = computed(() => {\n const locale = resolvedLocale.value\n if (view.value === 'year')\n return formatDateDisplay(range.value.start, locale, { year: 'numeric' })\n if (view.value === 'month') {\n return formatDateDisplay(range.value.start, locale, { month: 'long', year: 'numeric' })\n }\n if (view.value === 'day') {\n return formatDateDisplay(range.value.start, locale, {\n weekday: 'long',\n day: 'numeric',\n month: 'long',\n year: 'numeric',\n })\n }\n return formatDisplayRange(range.value.start, range.value.end, locale, {\n day: 'numeric',\n month: 'long',\n year: 'numeric',\n })\n})\n\nconst viewLabel = (value: CalendarView) => {\n const words = m.value.calendar\n if (value === 'day') return words.viewDay\n if (value === '4days') return words.view4Days\n if (value === 'week') return words.viewWeek\n if (value === 'month') return words.viewMonth\n if (value === 'year') return words.viewYear\n return words.viewCustom(props.customDays)\n}\n\n/**\n * What the two navigation buttons are called. They name the step rather than saying\n * \"previous\" alone, because the step is what changes from one view to the next and a bare\n * \"previous\" leaves a reader to guess whether it is a day or a year they are about to lose.\n */\nconst stepLabels = computed(() => {\n const words = m.value.calendar\n if (view.value === 'day') return { previous: words.previousDay, next: words.nextDay }\n if (view.value === 'week') return { previous: words.previousWeek, next: words.nextWeek }\n if (view.value === 'month') return { previous: words.previousMonth, next: words.nextMonth }\n if (view.value === 'year') return { previous: words.previousYear, next: words.nextYear }\n return { previous: words.previousPeriod, next: words.nextPeriod }\n})\n\nconst ariaLabel = useAriaLabel(() => props.label ?? m.value.calendar.label)\n\n/*\n * The four ways of reaching another period all pass through here, and `disabled` is refused\n * in every one of them rather than on the controls alone: the edge step pages the view from a\n * drag, and the year grid opens a month from a cell, neither of which is a button this\n * component disabled. It is the VDatePicker arrangement, where the guard sits on `goTo`.\n * `onCellActivate` below takes the same guard, for the same reason.\n */\nfunction step(delta: -1 | 1) {\n if (props.disabled) return\n date.value = stepAnchor(date.value, view.value, delta, resolvedWeekdays.value, props.customDays)\n}\n\nfunction goToToday() {\n if (props.disabled) return\n date.value = todayISO()\n}\n\nfunction setView(value: CalendarView) {\n if (props.disabled) return\n view.value = value\n}\n\n/**\n * An empty cell taken up, from either grid. The one place the time a month day stands for is\n * decided: the hour the time grids start at.\n *\n * TRAP — `disabled` is refused HERE, and not by the stylesheet's `pointer-events: none`\n * alone. That rule stops a click, but the grid keeps its tab stop so the agenda stays\n * readable, and Enter on a focused cell reaches this with nothing in its way — a frozen\n * calendar would go on reporting cells to a consumer's form.\n */\nfunction onCellActivate(cell: ActivatedCell) {\n if (props.disabled) return\n emit('cell-activate', {\n date: cell.date,\n time: timeOf(cell.minutes ?? timeWindow.value.start),\n })\n}\n\n/**\n * Going from a summary to the thing it summarises: opening a day from the month view, or a\n * month from the year view.\n *\n * The view only changes if the calendar was offering that one in the first place. A consumer\n * who narrowed `views` to a week and a year has said what their calendar is for, and jumping\n * it into a day view they deliberately left out would be the component overruling them —\n * so the date moves and the view stays, which is still a step towards what was asked for.\n */\nfunction openIn(iso: string, target: CalendarView) {\n if (props.disabled) return\n date.value = iso\n if (props.views.includes(target)) view.value = target\n}\n\n/**\n * What a reader who cannot see the grid is told: the range after every step of a move, and\n * whether the move was taken or given up.\n *\n * The node is rendered from the FIRST paint and left empty, never inserted along with its\n * first message — a live region that appears at the same moment as its text is not announced\n * at all, which is the trap VDataTable's selection count already documents.\n */\nconst { polite: announcement, announce: say } = useLiveAnnouncer()\nconst uid = useId()\nconst hintId = `${uid}-hint`\n\n/*\n * Through the shared announcer, which empties the region and writes on the next tick: the\n * same words twice in a row are no change to a live region, and would not be read again.\n */\nfunction announce(message: string) {\n say(message, false)\n}\n\n/**\n * Writes one event's new times into the model and says what happened.\n *\n * The array is replaced rather than edited in place: a new reference is what wakes a\n * consumer's own watchers, and it is the design system's rule for every v-model holding a\n * list. This runs ONCE, when a gesture ends — never per frame of a drag, which would fill an\n * undo stack with sixty entries a second and send each one back as a render fighting the\n * finger.\n */\nfunction onEventDrop(id: CalendarEventId, times: CalendarEventTimes, kind: 'move' | 'resize') {\n const current = events.value.find((item) => item.id === id)\n if (!current) return\n\n const previous = timesOf(current)\n // A gesture that ends where it began moved nothing, and a consumer's undo stack must not\n // gain an entry for it, nor its watchers a new array.\n if (sameTimes(previous, times)) return\n const next = { ...current, ...times }\n events.value = events.value.map((item) => (item.id === id ? next : item))\n // Written out rather than picking the name with a conditional: the emit signatures are an\n // overload set, and TypeScript resolves one only against a literal.\n if (kind === 'resize') emit('event-resize', next, previous)\n else emit('event-move', next, previous)\n}\n\n/*\n * A drawn slot is REPORTED and never added. What an event is called, what else it carries and\n * whether it exists at all are the consumer's decisions, so the calendar hands over the times\n * and draws nothing once the pointer is let go. The grid only asks when it was told it could\n * create, so `creatable` is not checked a second time here.\n */\nfunction onSlotCreate(times: CalendarEventTimes) {\n emit('event-create', times)\n}\n\ndefineExpose({\n /**\n * Brings the focus into the view: the cell the grid is showing, or the first month heading\n * in the year view.\n */\n focus: (options?: FocusOptions) => gridRef.value?.focus(options),\n /** The region, which is where your `id` and `aria-*` attributes land. */\n el: regionEl,\n /** Goes back to the current day, exactly as the Today button does. */\n today: goToToday,\n /** Moves back one view (a week, a month or a year), exactly as the toolbar's arrow does. */\n previous: () => step(-1),\n /** Moves forward one view. */\n next: () => step(1),\n /** Scrolls the grid so a given `HH:mm` sits at the top of the visible area. */\n scrollTo: (time: string) => {\n const at = minutesOf(time)\n if (at !== null) gridRef.value?.scrollToMinutes(at)\n },\n})\n</script>\n\n<template>\n <div\n class=\"v-calendar\"\n :class=\"rootClass\"\n :style=\"rootStyle\"\n :data-disabled=\"disabled ? '' : undefined\"\n >\n <section\n ref=\"regionEl\"\n :aria-roledescription=\"m.calendar.roleDescription\"\n v-bind=\"forwardedAttrs\"\n class=\"v-calendar-region\"\n :aria-label=\"ariaLabel\"\n >\n <div class=\"v-calendar-toolbar\">\n <div class=\"v-calendar-nav\">\n <VIconButton\n :label=\"stepLabels.previous\"\n size=\"sm\"\n :disabled=\"disabled\"\n @click=\"step(-1)\"\n >\n <VIcon :name=\"chevronLeftIcon\" mirrored />\n </VIconButton>\n <VIconButton :label=\"stepLabels.next\" size=\"sm\" :disabled=\"disabled\" @click=\"step(1)\">\n <VIcon :name=\"chevronRightIcon\" mirrored />\n </VIconButton>\n </div>\n\n <VButton variant=\"outline\" tone=\"neutral\" size=\"sm\" :disabled=\"disabled\" @click=\"goToToday\">\n {{ m.calendar.today }}\n </VButton>\n\n <VTypography variant=\"heading-4\" as=\"h2\" class=\"v-calendar-title\">\n {{ rangeText }}\n </VTypography>\n\n <div class=\"v-calendar-actions\">\n <slot name=\"actions\" />\n\n <VMenu v-if=\"views.length > 1\" size=\"sm\" placement=\"bottom-end\" match-trigger>\n <template #trigger=\"{ triggerProps }\">\n <VButton\n variant=\"outline\"\n tone=\"neutral\"\n size=\"sm\"\n :disabled=\"disabled\"\n v-bind=\"triggerProps\"\n :aria-label=\"`${m.calendar.view}: ${viewLabel(view)}`\"\n >\n {{ viewLabel(view) }}\n <VIcon :name=\"arrowDropDownIcon\" />\n </VButton>\n </template>\n <VMenuItem\n v-for=\"value in views\"\n :key=\"value\"\n :label=\"viewLabel(value)\"\n :selected=\"value === view\"\n @select=\"setView(value)\"\n />\n </VMenu>\n </div>\n </div>\n\n <!--\n The public props say what is REFUSED — `readonly`, `hideCurrentTime`,\n `noEdgeScroll` — so that none of them has to be turned off with a binding. The two\n internal grids keep the positive sense they read a dozen times each, and the whole\n of the inversion lives here, at the boundary: flip a sign on one of these lines and\n the grid quietly does the opposite of what was asked, since nothing downstream\n knows which way round the prop was written.\n -->\n <VCalendarTimeGrid\n v-if=\"isTimeGrid\"\n ref=\"gridRef\"\n v-model:focused=\"focused\"\n class=\"v-calendar-view\"\n :days=\"days\"\n :events=\"events\"\n :time-window=\"timeWindow\"\n :slot-duration=\"slotDuration\"\n :locale=\"resolvedLocale\"\n :format=\"resolvedFormat\"\n :today=\"today\"\n :now=\"hideCurrentTime ? null : now\"\n :editable=\"!readonly && !disabled\"\n :disabled=\"disabled\"\n :creatable=\"creatable && !disabled\"\n :hint-id=\"hintId\"\n :edge-step-delay=\"edgeStepDelay\"\n :auto-scroll=\"!noEdgeScroll\"\n :label=\"rangeText\"\n @cell-activate=\"onCellActivate\"\n @event-activate=\"emit('event-activate', $event)\"\n @event-drop=\"onEventDrop\"\n @slot-create=\"onSlotCreate\"\n @announce=\"announce\"\n @step=\"step\"\n >\n <template v-if=\"$slots.event\" #event=\"slotProps\">\n <slot name=\"event\" v-bind=\"slotProps\" />\n </template>\n <template v-if=\"$slots['day-header']\" #day-header=\"slotProps\">\n <slot name=\"day-header\" v-bind=\"slotProps\" />\n </template>\n <template v-if=\"$slots['all-day-label']\" #all-day-label>\n <slot name=\"all-day-label\" />\n </template>\n </VCalendarTimeGrid>\n\n <VCalendarMonth\n v-else-if=\"view === 'month'\"\n ref=\"gridRef\"\n v-model:focused=\"focusedDay\"\n class=\"v-calendar-view\"\n :weeks=\"weeks\"\n :events=\"events\"\n :locale=\"resolvedLocale\"\n :format=\"resolvedFormat\"\n :today=\"today\"\n :month-event-limit=\"monthEventLimit\"\n :editable=\"!readonly && !disabled\"\n :disabled=\"disabled\"\n :hint-id=\"hintId\"\n :edge-step-delay=\"edgeStepDelay\"\n :label=\"rangeText\"\n @day-activate=\"openIn($event, 'day')\"\n @cell-activate=\"onCellActivate\"\n @event-activate=\"emit('event-activate', $event)\"\n @event-drop=\"onEventDrop\"\n @announce=\"announce\"\n @step=\"step\"\n >\n <template v-if=\"$slots.event\" #event=\"slotProps\">\n <slot name=\"event\" v-bind=\"slotProps\" />\n </template>\n </VCalendarMonth>\n\n <VCalendarYear\n v-else\n ref=\"gridRef\"\n class=\"v-calendar-view\"\n :disabled=\"disabled\"\n :months=\"months\"\n :events=\"events\"\n :locale=\"resolvedLocale\"\n :weekdays=\"resolvedWeekdays\"\n :today=\"today\"\n :label=\"rangeText\"\n @month-activate=\"openIn($event, 'month')\"\n />\n\n <!--\n Both of these are rendered from the first paint and never conditionally.\n\n The live region has to EXIST before it has anything to say: one inserted along with\n its first message is not announced at all. And the hint is what every card points at\n with `aria-describedby`, so one node serves the whole calendar rather than repeating\n the same sentence on each of a hundred events.\n -->\n <div class=\"v-visually-hidden\" role=\"status\" aria-live=\"polite\">{{ announcement }}</div>\n <span :id=\"hintId\" class=\"v-visually-hidden\">{{ m.calendar.eventHint }}</span>\n </section>\n </div>\n</template>\n\n<style>\n@layer vectis.components {\n .v-calendar {\n display: flex;\n block-size: 100%;\n min-block-size: 0;\n font-family: var(--vectis-text-family);\n color: var(--vectis-color-text);\n }\n\n /* A frozen calendar greys out through the colour tokens and never through opacity, the\n design system rule: what a reader keeps here is the agenda itself, which has to stay\n readable. The cards are real disabled buttons, so they grey themselves. */\n .v-calendar[data-disabled] {\n color: var(--vectis-color-text-subtle);\n cursor: not-allowed;\n }\n\n .v-calendar[data-disabled] .v-calendar-view {\n pointer-events: none;\n }\n\n /*\n * The height is settled in CSS rather than measured, the VDataTable idiom: the region is\n * a flex column at full height, the toolbar refuses to grow and the grid takes what is\n * left. `min-block-size: 0` on the grid is what lets it shrink below its content and\n * therefore scroll — without it the automatic minimum of a flex item would hold it at its\n * full 24-hour height and the whole page would scroll instead.\n *\n * All of it is a no-op when the parent's height is auto, where the percentage falls back\n * to auto and the calendar is simply as tall as its content. That is what makes an opt-in\n * prop unnecessary.\n */\n .v-calendar-region {\n display: flex;\n flex: 1;\n flex-direction: column;\n min-inline-size: 0;\n min-block-size: 0;\n }\n\n .v-calendar-toolbar {\n display: flex;\n flex: none;\n flex-wrap: wrap;\n align-items: center;\n gap: var(--vectis-space-2);\n padding-block-end: var(--vectis-space-3);\n }\n\n .v-calendar-nav {\n display: flex;\n align-items: center;\n gap: var(--vectis-space-1);\n }\n\n .v-calendar-title {\n /* It may be long — a full weekday and month in the day view — so it is the part that\n gives way first, and the controls keep their size. */\n min-inline-size: 0;\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n }\n\n .v-calendar-actions {\n display: flex;\n align-items: center;\n gap: var(--vectis-space-2);\n /* The two siblings are pushed apart from here rather than by a `justify-content` on the\n toolbar, which would space every control equally instead of grouping them. */\n margin-inline-start: auto;\n }\n\n /*\n * The view on show, whichever it is: the one box that scrolls. The views inherit the family\n * and the colour from `.v-calendar` and declare neither again.\n */\n .v-calendar-view {\n flex: 1;\n overflow: auto;\n block-size: 100%;\n min-block-size: 0;\n border: 1px solid var(--vectis-color-border);\n border-radius: var(--vectis-radius-surface);\n }\n\n /*\n * What the three views share lives HERE rather than in each of their sheets. They are only\n * ever rendered by this component, so this sheet ships wherever they do — the\n * VCarousel/VCarouselItem arrangement. Every rule a view writes against one of these classes\n * is either disjoint from it or more specific, never tied: a tie between two sheets would be\n * settled by the consumer's bundler.\n */\n\n /*\n * A drag currently held off the calendar. `not-allowed` is the word the library already uses\n * for \"you cannot do this\", on every disabled control.\n *\n * BEST-EFFORT, and never the signal: while a pointer is captured the cursor is resolved\n * against the capture target rather than against whatever sits under the pointer, and engines\n * differ on it. What carries the message is the card's own paint.\n */\n .v-calendar-view[data-outside] {\n cursor: not-allowed;\n }\n\n .v-calendar-weekday {\n color: var(--vectis-color-text-muted);\n font-size: var(--vectis-text-overline-size);\n font-weight: var(--vectis-text-overline-weight);\n letter-spacing: var(--vectis-text-overline-tracking);\n text-transform: uppercase;\n }\n\n /*\n * Today's date, marked on the number the way a calendar marks a date rather than a column.\n * Semibold here marks a state, not a type role. Written at (0,2,0) so it wins over each view's\n * own (0,1,0) rule for the element it lands on.\n */\n .v-calendar-view .v-calendar-today {\n background: var(--vectis-color-accent);\n color: var(--vectis-color-text-on-accent);\n font-weight: var(--vectis-font-weight-semibold);\n }\n\n /*\n * A cell of either grid: ruled on two sides, the other two drawn by its neighbours. It keeps\n * the default cursor: the pointer hand belongs to what can be opened, the events, and a grid\n * of hands would say every square of the week is a link.\n */\n .v-calendar-cell {\n border-block-start: 1px solid var(--vectis-color-border);\n border-inline-start: 1px solid var(--vectis-color-border);\n }\n\n .v-calendar-cell:first-child {\n border-inline-start: none;\n }\n\n .v-calendar-cell:focus-visible {\n outline: var(--vectis-focus-ring-width) solid var(--vectis-focus-ring-color);\n /* Drawn inwards: the view is a scrolling box, and an outward ring on a cell at the edge\n would be cropped by it. */\n outline-offset: calc(-1 * var(--vectis-focus-ring-width));\n }\n\n /* The plain buttons the month and year views draw: a day number, the \"+2 more\", a month. */\n .v-calendar-button {\n /* A button carries a border and a background from the browser, which around a round day\n number read as a stray ring. Neither is optional. */\n border: none;\n background: none;\n font-family: inherit;\n cursor: pointer;\n transition: background-color var(--vectis-duration-fast) var(--vectis-ease-default);\n }\n\n .v-calendar-button:focus-visible {\n outline: var(--vectis-focus-ring-width) solid var(--vectis-focus-ring-color);\n outline-offset: var(--vectis-focus-ring-offset);\n }\n\n /*\n * The strip that lights up while a drag rests against an edge, counting down to turn the\n * page. It is what stops the paging being a surprise.\n *\n * Drawn INSIDE the box the cells occupy rather than on the scroller, because a scroller's\n * absolutely positioned child is placed against its content and scrolls away with it. That\n * box has to be positioned, which each view's own sheet sees to. An absolutely positioned\n * pseudo-element is not a grid item, so it disturbs no column.\n *\n * Its width is `--vectis-control-size-calendar-edge`, whose twin is `EDGE_BAND` in\n * `edgeStep.ts` — the JavaScript that decides where the countdown actually starts. Neither\n * may move without the other. The layer, 2, is the time grid's stacking table.\n */\n .v-calendar-edge-cue[data-edge]::after {\n content: '';\n position: absolute;\n inset-block: 0;\n inline-size: var(--vectis-control-size-calendar-edge);\n background: var(--vectis-color-accent-surface);\n z-index: 2;\n pointer-events: none;\n }\n\n .v-calendar-edge-cue[data-edge='start']::after {\n inset-inline-start: 0;\n }\n\n .v-calendar-edge-cue[data-edge='end']::after {\n inset-inline-end: 0;\n }\n\n @media (prefers-reduced-motion: reduce) {\n .v-calendar-button {\n transition: none;\n }\n }\n\n /*\n * Windows forced colors flattens every background to Canvas, and today and the paging strip\n * are drawn with nothing else. Today takes the system selection pair, the one every other\n * \"current\" mark in the library takes, and the strip takes Highlight.\n */\n @media (forced-colors: active) {\n .v-calendar-view .v-calendar-today {\n forced-color-adjust: none;\n background: Highlight;\n color: HighlightText;\n }\n\n .v-calendar-edge-cue[data-edge]::after {\n forced-color-adjust: none;\n background: Highlight;\n }\n }\n}\n</style>\n"],"mappings":"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"}
1
+ {"version":3,"file":"VCalendar.vue_vue_type_script_setup_true_lang.js","names":["$slots"],"sources":["../../../src/components/VCalendar/VCalendar.vue"],"sourcesContent":["<script setup lang=\"ts\" generic=\"E extends CalendarEvent\">\n// @a11y @ssr @core\n/**\n * Calendar layout is pure; JavaScript supplies grid navigation, editing gestures and\n * announcements because HTML has no native agenda widget. Editing forms remain consumer-owned.\n */\nimport { computed, onMounted, ref, useId, watch } from 'vue'\n\nimport VButton from '../VButton/VButton.vue'\nimport VIcon from '../VIcon/VIcon.vue'\nimport { arrow_drop_down as arrowDropDownIcon } from '../VIcon/icons/arrow_drop_down'\nimport { chevron_left as chevronLeftIcon } from '../VIcon/icons/chevron_left'\nimport { chevron_right as chevronRightIcon } from '../VIcon/icons/chevron_right'\nimport VIconButton from '../VIconButton/VIconButton.vue'\nimport VMenu from '../VMenu/VMenu.vue'\nimport VMenuItem from '../VMenu/VMenuItem.vue'\nimport VTypography from '../VTypography/VTypography.vue'\n\nimport { useAriaLabel } from '../../composables/useAriaLabel'\nimport { useLiveAnnouncer } from '../../composables/useLiveAnnouncer'\nimport { useRootAttrs } from '../../composables/useRootAttrs'\nimport { useTimer } from '../../composables/useTimer'\nimport { firstDayOfWeekFor, formatDateDisplay, formatDisplayRange } from '../../utils/date'\nimport { hourCycleFor, minutesOf } from '../../utils/time'\n\nimport { useMessages, useResolvedLocale } from '../../i18n/state'\n\nimport VCalendarMonth from './VCalendarMonth.vue'\nimport VCalendarTimeGrid, { type FocusedCell } from './VCalendarTimeGrid.vue'\nimport VCalendarYear from './VCalendarYear.vue'\nimport { EDGE_STEP_DELAY } from './edgeStep'\nimport {\n monthWeeks,\n monthsOfYear,\n normalizeWeekdays,\n stepAnchor,\n sameTimes,\n timeOf,\n timesOf,\n todayISO,\n visibleDays,\n visibleRange,\n windowOf,\n} from './layout'\nimport type {\n ActivatedCell,\n CalendarCell,\n CalendarEvent,\n CalendarEventId,\n CalendarEventSlotProps,\n CalendarEventTimes,\n CalendarFormat,\n CalendarView,\n} from './types'\n\nexport interface CalendarProps {\n /**\n * Which views the menu offers, in the order it lists them. Narrowing it is how a\n * calendar that only ever shows weeks stops offering anything else.\n */\n views?: CalendarView[]\n /** How many days the custom view shows, and how far Previous and Next step in it. */\n customDays?: number\n /**\n * Which weekdays are on show, as numbers from 0 for Sunday. The ORDER matters as well: the\n * first entry is the day a week starts on, and it wins over `firstDayOfWeek`.\n */\n weekdays?: number[]\n /**\n * The day a week starts on, from 0 for Sunday, when `weekdays` is not given. Left out,\n * the locale decides.\n */\n firstDayOfWeek?: number\n /** The language the days, months and times are written in. Falls back to the global one. */\n locale?: string\n /**\n * Whether times are shown on a twelve or twenty-four hour clock. Left out, the reader's\n * language decides. It is the same prop, under the same name, as VTimePicker's.\n */\n format?: CalendarFormat\n /** The hour the grid starts at, from 0. */\n dayStart?: number\n /** The hour it ends at, up to 24. */\n dayEnd?: number\n /**\n * The step everything snaps to, in minutes: how far a nudge moves an event, and the unit a\n * slot is drawn out in.\n */\n slotDuration?: number\n /** Where the grid is scrolled to when it first appears, so the working day is in view. */\n scrollTime?: string\n /**\n * Leaves out the line drawn across today's column at the time it is now, and the dot on\n * its leading edge. Left in, it ticks once a minute while the calendar is on screen.\n */\n hideCurrentTime?: boolean\n /** How many events a day of the month view shows before it starts counting the rest. */\n monthEventLimit?: number\n /**\n * Stops events being moved and stretched, by dragging or with the keyboard. They\n * stay readable and clickable, and nothing else.\n */\n readonly?: boolean\n /**\n * Freezes the whole calendar: nothing can be moved, created or opened, no other period can be\n * reached, and everything greys out through the colour tokens. That is what separates this\n * from `readonly`, where only the editing stops.\n */\n disabled?: boolean\n /**\n * Lets an empty stretch of a time grid be drawn out with the pointer, up or down from the\n * slot pressed.\n */\n creatable?: boolean\n /**\n * How long a dragged event has to rest against the side of the calendar before the view turns\n * to the previous or next period, in milliseconds.\n */\n edgeStepDelay?: number\n /** Stops dragging near the top or bottom of a time grid from scrolling it. */\n noEdgeScroll?: boolean\n /** What the calendar is called, for anyone who cannot see it. */\n label?: string\n}\n\nconst props = withDefaults(defineProps<CalendarProps>(), {\n views: () => ['day', '4days', 'week'],\n customDays: 4,\n weekdays: undefined,\n firstDayOfWeek: undefined,\n locale: undefined,\n format: undefined,\n dayStart: 0,\n dayEnd: 24,\n slotDuration: 15,\n scrollTime: '08:00',\n hideCurrentTime: false,\n monthEventLimit: 3,\n readonly: false,\n disabled: false,\n creatable: false,\n edgeStepDelay: EDGE_STEP_DELAY,\n noEdgeScroll: false,\n label: undefined,\n})\n\n/*\n * The wrapper-root pattern: the consumer's class and style stay on the outer box, and\n * everything else; their `id`, their `aria-*`; goes on the region, which is the part that\n * carries the role and is therefore the part they mean.\n */\ndefineOptions({ inheritAttrs: false })\n\n/** Which span the calendar is showing. It opens on the week. */\nconst view = defineModel<CalendarView>('view', { default: 'week' })\n\n// @ssr\n/*\n * Today's date, which marks a single column, is a different matter and is read below in\n * `onMounted` where the server cannot see it at all.\n */\n/**\n * The day the calendar is anchored on, as `YYYY-MM-DD`: the view shows the week, month or\n * year holding it. It opens on today.\n */\nconst date = defineModel<string>('date', { default: () => todayISO() })\n/** What is on the calendar, empty to begin with. */\nconst events = defineModel<E[]>('events', { default: () => [] })\n\nconst emit = defineEmits<{\n /** A card was clicked or activated: the cue to open an editor of your own. */\n 'event-activate': [event: E]\n /**\n * An empty part of the grid was activated, at this day and this time. A day of the month\n * view has no hour of its own, and reports the one the time grids start at.\n */\n 'cell-activate': [cell: CalendarCell]\n /** An event was dragged or nudged somewhere else. */\n 'event-move': [event: E, previous: CalendarEventTimes]\n /** An event's end was dragged or nudged, in the same two parts. */\n 'event-resize': [event: E, previous: CalendarEventTimes]\n /**\n * An empty stretch of a day was drawn out, and these are its times. Nothing has been added\n * to `events`: this is the cue to make the event, in your own model or through your own form.\n */\n 'event-create': [times: CalendarEventTimes]\n}>()\n\ndefineSlots<{\n /** Extra controls in the toolbar, between the range and the view menu. */\n actions?(): unknown\n /** The content of one event's card, replacing the title and times. */\n event?(props: CalendarEventSlotProps<E>): unknown\n /** The head of one day column, replacing the weekday and the number. */\n 'day-header'?(props: { iso: string; weekday: string; dayText: string; today: boolean }): unknown\n /** The label beside the band of all-day events. */\n 'all-day-label'?(): unknown\n}>()\n\nconst m = useMessages()\nconst { rootClass, rootStyle, forwardedAttrs } = useRootAttrs()\n\nconst resolvedLocale = useResolvedLocale(() => props.locale)\nconst resolvedFormat = computed(() => props.format ?? hourCycleFor(resolvedLocale.value))\nconst resolvedWeekdays = computed(() =>\n normalizeWeekdays(\n props.weekdays,\n props.firstDayOfWeek ?? firstDayOfWeekFor(resolvedLocale.value),\n ),\n)\n\nconst timeWindow = computed(() => windowOf(props.dayStart, props.dayEnd))\n\nconst days = computed(() =>\n visibleDays(date.value, view.value, resolvedWeekdays.value, props.customDays),\n)\n\n/** Which view is a time grid, and which is a summary. Several things below turn on this. */\nconst isTimeGrid = computed(() => view.value !== 'month' && view.value !== 'year')\n\nconst weeks = computed(() =>\n view.value === 'month' ? monthWeeks(date.value, resolvedWeekdays.value) : [],\n)\n\nconst months = computed(() => (view.value === 'year' ? monthsOfYear(date.value) : []))\n\n// @ssr\n// Way to tell either where the reader is, and rendering a guess would make the two markups\n// differ. Both stay null until then, and every rule that draws them is written to expect it.\nconst today = ref<string | null>(null)\nconst now = ref<number | null>(null)\n\nconst clock = useTimer()\n\n/**\n * The floor on the delay is not a nicety. `useTimer` runs a delay of zero or less\n * synchronously, by design, so a tick that ever computed one would call itself straight back\n * and go on doing so until the stack gave out.\n */\nfunction tick() {\n const at = new Date()\n now.value = at.getHours() * 60 + at.getMinutes()\n clock.start(tick, Math.max(1000, (60 - at.getSeconds()) * 1000))\n}\n\n/** Scrolls the time grid on show to `scrollTime`. */\nfunction scrollToStart() {\n const at = minutesOf(props.scrollTime)\n if (at !== null) gridRef.value?.scrollToMinutes(at)\n}\n\nonMounted(() => {\n today.value = todayISO()\n if (!props.hideCurrentTime) tick()\n scrollToStart()\n})\n\n// @core\n// Watch the visibility prop so toggling the current-time line starts or stops its timer after\n// mount.\nwatch(\n () => props.hideCurrentTime,\n (hidden) => {\n if (!hidden) return tick()\n clock.cancel()\n now.value = null\n },\n)\n\n/**\n * The usual form does not work here and the error it gives says nothing useful about why. A\n * generic `<script setup>` compiles to a FUNCTION, not to a class, so it has no construct\n * signature for `InstanceType` to read: the message complains that the component \"provides no\n * match for the signature `new (...args: any)`\", pointing at the template.\n */\nconst gridRef = ref<{\n focus(options?: FocusOptions): void\n scrollToMinutes(minutes: number): void\n} | null>(null)\n\n// @core\n// A time grid that appears after mount, a month switched to a week, opens at `scrollTime`\n// too. Post-flush, so the new grid is rendered and measurable when it is asked to scroll.\nwatch(gridRef, scrollToStart, { flush: 'post' })\n\n/** The region, the element a consumer's attributes land on. */\nconst regionEl = ref<HTMLElement | null>(null)\n\n/*\n * Which cell holds the tab stop, kept as two refs because the two kinds of view mean different\n * things by it: a time grid needs a day and an hour, a month only a day. One ref carrying an\n * hour the month ignores would leave that hour to go stale, and the grid would then reopen on\n * whatever the month happened to leave behind.\n */\nconst focused = ref<FocusedCell>({ iso: date.value, minutes: timeWindow.value.start })\nconst focusedDay = ref(date.value)\n\nconst range = computed(() =>\n visibleRange(date.value, view.value, resolvedWeekdays.value, props.customDays),\n)\n\n/**\n * What the toolbar says the calendar is showing. Each view names itself at the coarsest\n * granularity that still identifies it: a single day says its weekday, a year says nothing\n * but the number.\n */\nconst rangeText = computed(() => {\n const locale = resolvedLocale.value\n if (view.value === 'year')\n return formatDateDisplay(range.value.start, locale, { year: 'numeric' })\n if (view.value === 'month') {\n return formatDateDisplay(range.value.start, locale, { month: 'long', year: 'numeric' })\n }\n if (view.value === 'day') {\n return formatDateDisplay(range.value.start, locale, {\n weekday: 'long',\n day: 'numeric',\n month: 'long',\n year: 'numeric',\n })\n }\n return formatDisplayRange(range.value.start, range.value.end, locale, {\n day: 'numeric',\n month: 'long',\n year: 'numeric',\n })\n})\n\nconst viewLabel = (value: CalendarView) => {\n const words = m.value.calendar\n if (value === 'day') return words.viewDay\n if (value === '4days') return words.view4Days\n if (value === 'week') return words.viewWeek\n if (value === 'month') return words.viewMonth\n if (value === 'year') return words.viewYear\n return words.viewCustom(props.customDays)\n}\n\n/** What the two navigation buttons are called. */\nconst stepLabels = computed(() => {\n const words = m.value.calendar\n if (view.value === 'day') return { previous: words.previousDay, next: words.nextDay }\n if (view.value === 'week') return { previous: words.previousWeek, next: words.nextWeek }\n if (view.value === 'month') return { previous: words.previousMonth, next: words.nextMonth }\n if (view.value === 'year') return { previous: words.previousYear, next: words.nextYear }\n return { previous: words.previousPeriod, next: words.nextPeriod }\n})\n\nconst ariaLabel = useAriaLabel(() => props.label ?? m.value.calendar.label)\n\n/*\n * The four ways of reaching another period all pass through here, and `disabled` is refused in\n * every one of them rather than on the controls alone: the edge step pages the view from a\n * drag, and the year grid opens a month from a cell, neither of which is a button this\n * component disabled. It is the VDatePicker arrangement, where the guard sits on `goTo`.\n */\nfunction step(delta: -1 | 1) {\n if (props.disabled) return\n date.value = stepAnchor(date.value, view.value, delta, resolvedWeekdays.value, props.customDays)\n}\n\nfunction goToToday() {\n if (props.disabled) return\n date.value = todayISO()\n}\n\nfunction setView(value: CalendarView) {\n if (props.disabled) return\n view.value = value\n}\n\n/**\n * `disabled` is refused here, and not by the stylesheet's `pointer-events: none` alone. That\n * rule stops a click, but the grid keeps its tab stop so the agenda stays readable, and Enter\n * on a focused cell reaches this with nothing in its way; a frozen calendar would go on\n * reporting cells to a consumer's form.\n */\nfunction onCellActivate(cell: ActivatedCell) {\n if (props.disabled) return\n emit('cell-activate', {\n date: cell.date,\n time: timeOf(cell.minutes ?? timeWindow.value.start),\n })\n}\n\n/**\n * Drill into an allowed detail view; if views excludes it, update the date while preserving the\n * current view.\n */\nfunction openIn(iso: string, target: CalendarView) {\n if (props.disabled) return\n date.value = iso\n if (props.views.includes(target)) view.value = target\n}\n\n/**\n * What a reader who cannot see the grid is told: the range after every step of a move, and\n * whether the move was taken or given up.\n */\nconst { polite: announcement, announce: say } = useLiveAnnouncer()\nconst uid = useId()\nconst hintId = `${uid}-hint`\n\n/*\n * Through the shared announcer, which empties the region and writes on the next tick: the\n * same words twice in a row are no change to a live region, and would not be read again.\n */\nfunction announce(message: string) {\n say(message, false)\n}\n\n/** Writes one event's new times into the model and says what happened. */\nfunction onEventDrop(id: CalendarEventId, times: CalendarEventTimes, kind: 'move' | 'resize') {\n const current = events.value.find((item) => item.id === id)\n if (!current) return\n\n const previous = timesOf(current)\n // A gesture that ends where it began moved nothing, and a consumer's undo stack must not\n // gain an entry for it, nor its watchers a new array.\n if (sameTimes(previous, times)) return\n const next = { ...current, ...times }\n events.value = events.value.map((item) => (item.id === id ? next : item))\n // Written out rather than picking the name with a conditional: the emit signatures are an\n // overload set, and TypeScript resolves one only against a literal.\n if (kind === 'resize') emit('event-resize', next, previous)\n else emit('event-move', next, previous)\n}\n\n/*\n * A drawn slot is REPORTED and never added. What an event is called, what else it carries and\n * whether it exists at all are the consumer's decisions, so the calendar hands over the times\n * and draws nothing once the pointer is let go.\n */\nfunction onSlotCreate(times: CalendarEventTimes) {\n emit('event-create', times)\n}\n\ndefineExpose({\n /**\n * Brings the focus into the view: the cell the grid is showing, or the first month heading\n * in the year view.\n */\n focus: (options?: FocusOptions) => gridRef.value?.focus(options),\n /** The region, which is where your `id` and `aria-*` attributes land. */\n el: regionEl,\n /** Goes back to the current day, exactly as the Today button does. */\n today: goToToday,\n /** Moves back one view (a week, a month or a year), exactly as the toolbar's arrow does. */\n previous: () => step(-1),\n /** Moves forward one view. */\n next: () => step(1),\n /** Scrolls the grid so a given `HH:mm` sits at the top of the visible area. */\n scrollTo: (time: string) => {\n const at = minutesOf(time)\n if (at !== null) gridRef.value?.scrollToMinutes(at)\n },\n})\n</script>\n\n<template>\n <div\n class=\"v-calendar\"\n :class=\"rootClass\"\n :style=\"rootStyle\"\n :data-disabled=\"disabled ? '' : undefined\"\n >\n <section\n ref=\"regionEl\"\n :aria-roledescription=\"m.calendar.roleDescription\"\n v-bind=\"forwardedAttrs\"\n class=\"v-calendar-region\"\n :aria-label=\"ariaLabel\"\n >\n <div class=\"v-calendar-toolbar\">\n <div class=\"v-calendar-nav\">\n <VIconButton\n :label=\"stepLabels.previous\"\n size=\"sm\"\n :disabled=\"disabled\"\n @click=\"step(-1)\"\n >\n <VIcon :name=\"chevronLeftIcon\" mirrored />\n </VIconButton>\n <VIconButton :label=\"stepLabels.next\" size=\"sm\" :disabled=\"disabled\" @click=\"step(1)\">\n <VIcon :name=\"chevronRightIcon\" mirrored />\n </VIconButton>\n </div>\n\n <VButton variant=\"outline\" tone=\"neutral\" size=\"sm\" :disabled=\"disabled\" @click=\"goToToday\">\n {{ m.calendar.today }}\n </VButton>\n\n <VTypography variant=\"heading-4\" as=\"h2\" class=\"v-calendar-title\">\n {{ rangeText }}\n </VTypography>\n\n <div class=\"v-calendar-actions\">\n <slot name=\"actions\" />\n\n <VMenu v-if=\"views.length > 1\" size=\"sm\" placement=\"bottom-end\" match-trigger>\n <template #trigger=\"{ triggerProps }\">\n <VButton\n variant=\"outline\"\n tone=\"neutral\"\n size=\"sm\"\n :disabled=\"disabled\"\n v-bind=\"triggerProps\"\n :aria-label=\"`${m.calendar.view}: ${viewLabel(view)}`\"\n >\n {{ viewLabel(view) }}\n <VIcon :name=\"arrowDropDownIcon\" />\n </VButton>\n </template>\n <VMenuItem\n v-for=\"value in views\"\n :key=\"value\"\n :label=\"viewLabel(value)\"\n :selected=\"value === view\"\n @select=\"setView(value)\"\n />\n </VMenu>\n </div>\n </div>\n\n <!--\n Invert opt-out public props once at the internal-grid boundary; internal view contracts\n use positive booleans.\n -->\n <VCalendarTimeGrid\n v-if=\"isTimeGrid\"\n ref=\"gridRef\"\n v-model:focused=\"focused\"\n class=\"v-calendar-view\"\n :days=\"days\"\n :events=\"events\"\n :time-window=\"timeWindow\"\n :slot-duration=\"slotDuration\"\n :locale=\"resolvedLocale\"\n :format=\"resolvedFormat\"\n :today=\"today\"\n :now=\"hideCurrentTime ? null : now\"\n :editable=\"!readonly && !disabled\"\n :disabled=\"disabled\"\n :creatable=\"creatable && !disabled\"\n :hint-id=\"hintId\"\n :edge-step-delay=\"edgeStepDelay\"\n :auto-scroll=\"!noEdgeScroll\"\n :label=\"rangeText\"\n @cell-activate=\"onCellActivate\"\n @event-activate=\"emit('event-activate', $event)\"\n @event-drop=\"onEventDrop\"\n @slot-create=\"onSlotCreate\"\n @announce=\"announce\"\n @step=\"step\"\n >\n <template v-if=\"$slots.event\" #event=\"slotProps\">\n <slot name=\"event\" v-bind=\"slotProps\" />\n </template>\n <template v-if=\"$slots['day-header']\" #day-header=\"slotProps\">\n <slot name=\"day-header\" v-bind=\"slotProps\" />\n </template>\n <template v-if=\"$slots['all-day-label']\" #all-day-label>\n <slot name=\"all-day-label\" />\n </template>\n </VCalendarTimeGrid>\n\n <VCalendarMonth\n v-else-if=\"view === 'month'\"\n ref=\"gridRef\"\n v-model:focused=\"focusedDay\"\n class=\"v-calendar-view\"\n :weeks=\"weeks\"\n :events=\"events\"\n :locale=\"resolvedLocale\"\n :format=\"resolvedFormat\"\n :today=\"today\"\n :month-event-limit=\"monthEventLimit\"\n :editable=\"!readonly && !disabled\"\n :disabled=\"disabled\"\n :hint-id=\"hintId\"\n :edge-step-delay=\"edgeStepDelay\"\n :label=\"rangeText\"\n @day-activate=\"openIn($event, 'day')\"\n @cell-activate=\"onCellActivate\"\n @event-activate=\"emit('event-activate', $event)\"\n @event-drop=\"onEventDrop\"\n @announce=\"announce\"\n @step=\"step\"\n >\n <template v-if=\"$slots.event\" #event=\"slotProps\">\n <slot name=\"event\" v-bind=\"slotProps\" />\n </template>\n </VCalendarMonth>\n\n <VCalendarYear\n v-else\n ref=\"gridRef\"\n class=\"v-calendar-view\"\n :disabled=\"disabled\"\n :months=\"months\"\n :events=\"events\"\n :locale=\"resolvedLocale\"\n :weekdays=\"resolvedWeekdays\"\n :today=\"today\"\n :label=\"rangeText\"\n @month-activate=\"openIn($event, 'month')\"\n />\n\n <!--\n Both of these are rendered from the first paint and never conditionally. The live region\n has to EXIST before it has anything to say: one inserted along with its first message is\n not announced at all.\n -->\n <div class=\"v-visually-hidden\" role=\"status\" aria-live=\"polite\">{{ announcement }}</div>\n <span :id=\"hintId\" class=\"v-visually-hidden\">{{ m.calendar.eventHint }}</span>\n </section>\n </div>\n</template>\n\n<style>\n@layer vectis.components {\n .v-calendar {\n display: flex;\n block-size: 100%;\n min-block-size: 0;\n font-family: var(--vectis-text-family);\n color: var(--vectis-color-text);\n }\n\n /* A frozen calendar greys out through the colour tokens and never through opacity, the\n design system rule: what a reader keeps here is the agenda itself, which has to stay\n readable. The cards are real disabled buttons, so they grey themselves. */\n .v-calendar[data-disabled] {\n color: var(--vectis-color-text-subtle);\n cursor: not-allowed;\n }\n\n .v-calendar[data-disabled] .v-calendar-view {\n pointer-events: none;\n }\n\n /*\n * `min-block-size: 0` on the grid is what lets it shrink below its content and therefore\n * scroll; without it the automatic minimum of a flex item would hold it at its full 24-hour\n * height and the whole page would scroll instead. All of it is a no-op when the parent's\n * height is auto, where the percentage falls back to auto and the calendar is simply as tall\n * as its content.\n */\n .v-calendar-region {\n display: flex;\n flex: 1;\n flex-direction: column;\n min-inline-size: 0;\n min-block-size: 0;\n }\n\n .v-calendar-toolbar {\n display: flex;\n flex: none;\n flex-wrap: wrap;\n align-items: center;\n gap: var(--vectis-space-2);\n padding-block-end: var(--vectis-space-3);\n }\n\n .v-calendar-nav {\n display: flex;\n align-items: center;\n gap: var(--vectis-space-1);\n }\n\n .v-calendar-title {\n /*\n * It may be long; a full weekday and month in the day view; so it is the part that gives\n * way first, and the controls keep their size.\n */\n min-inline-size: 0;\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n }\n\n .v-calendar-actions {\n display: flex;\n align-items: center;\n gap: var(--vectis-space-2);\n /* The two siblings are pushed apart from here rather than by a `justify-content` on the\n toolbar, which would space every control equally instead of grouping them. */\n margin-inline-start: auto;\n }\n\n /*\n * The view on show, whichever it is: the one box that scrolls. The views inherit the family\n * and the colour from `.v-calendar` and declare neither again.\n */\n .v-calendar-view {\n flex: 1;\n overflow: auto;\n block-size: 100%;\n min-block-size: 0;\n border: 1px solid var(--vectis-color-border);\n border-radius: var(--vectis-radius-surface);\n }\n\n /*\n * Every rule a view writes against one of these classes is either disjoint from it or more\n * specific, never tied: a tie between two sheets would be settled by the consumer's bundler.\n */\n\n /*\n * `not-allowed` is the word the library already uses for \"you cannot do this\", on every\n * disabled control. BEST-EFFORT, and never the signal: while a pointer is captured the cursor\n * is resolved against the capture target rather than against whatever sits under the pointer,\n * and engines differ on it.\n */\n .v-calendar-view[data-outside] {\n cursor: not-allowed;\n }\n\n .v-calendar-weekday {\n color: var(--vectis-color-text-muted);\n font-size: var(--vectis-text-overline-size);\n font-weight: var(--vectis-text-overline-weight);\n letter-spacing: var(--vectis-text-overline-tracking);\n text-transform: uppercase;\n }\n\n /*\n * Today's date, marked on the number the way a calendar marks a date rather than a column.\n * Semibold here marks a state, not a type role.\n */\n .v-calendar-view .v-calendar-today {\n background: var(--vectis-color-accent);\n color: var(--vectis-color-text-on-accent);\n font-weight: var(--vectis-font-weight-semibold);\n }\n\n /*\n * A cell of either grid: ruled on two sides, the other two drawn by its neighbours. It keeps\n * the default cursor: the pointer hand belongs to what can be opened, the events, and a grid\n * of hands would say every square of the week is a link.\n */\n .v-calendar-cell {\n border-block-start: 1px solid var(--vectis-color-border);\n border-inline-start: 1px solid var(--vectis-color-border);\n }\n\n .v-calendar-cell:first-child {\n border-inline-start: none;\n }\n\n .v-calendar-cell:focus-visible {\n outline: var(--vectis-focus-ring-width) solid var(--vectis-focus-ring-color);\n /* Drawn inwards: the view is a scrolling box, and an outward ring on a cell at the edge\n would be cropped by it. */\n outline-offset: calc(-1 * var(--vectis-focus-ring-width));\n }\n\n .v-calendar-button {\n /* A button carries a border and a background from the browser, which around a round day\n number read as a stray ring. Neither is optional. */\n border: none;\n background: none;\n font-family: inherit;\n cursor: pointer;\n transition: background-color var(--vectis-duration-fast) var(--vectis-ease-default);\n }\n\n .v-calendar-button:focus-visible {\n outline: var(--vectis-focus-ring-width) solid var(--vectis-focus-ring-color);\n outline-offset: var(--vectis-focus-ring-offset);\n }\n\n /*\n * Drawn INSIDE the box the cells occupy rather than on the scroller, because a scroller's\n * absolutely positioned child is placed against its content and scrolls away with it. That\n * box has to be positioned, which each view's own sheet sees to.\n */\n .v-calendar-edge-cue[data-edge]::after {\n content: '';\n position: absolute;\n inset-block: 0;\n inline-size: var(--vectis-control-size-calendar-edge);\n background: var(--vectis-color-accent-surface);\n z-index: 2;\n pointer-events: none;\n }\n\n .v-calendar-edge-cue[data-edge='start']::after {\n inset-inline-start: 0;\n }\n\n .v-calendar-edge-cue[data-edge='end']::after {\n inset-inline-end: 0;\n }\n\n @media (prefers-reduced-motion: reduce) {\n .v-calendar-button {\n transition: none;\n }\n }\n\n /*\n * Windows forced colors flattens every background to Canvas, and today and the paging strip\n * are drawn with nothing else. Today takes the system selection pair, the one every other\n * \"current\" mark in the library takes, and the strip takes Highlight.\n */\n @media (forced-colors: active) {\n .v-calendar-view .v-calendar-today {\n forced-color-adjust: none;\n background: Highlight;\n color: HighlightText;\n }\n\n .v-calendar-edge-cue[data-edge]::after {\n forced-color-adjust: none;\n background: Highlight;\n }\n }\n}\n</style>\n"],"mappings":"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"}
@@ -17,13 +17,8 @@ export interface CalendarEventProps<T> {
17
17
  /** Whether the card is being dragged with a pointer right now. */
18
18
  dragging?: boolean;
19
19
  /**
20
- * Whether letting go now would write nothing: the pointer has left the calendar, and the event
21
- * is about to return to where the faded echo shows it started.
22
- *
23
- * It is separate from `dragging` rather than folded into it because a refused card is ALSO
24
- * being dragged: the two are orthogonal, and the stylesheet reads both. Named for what the
25
- * card knows, which is that its drop will not be taken; a card knows nothing of a view it
26
- * might be outside of.
20
+ * Whether letting go now would write nothing: the pointer has left the calendar, and the
21
+ * event is about to return to where the faded echo shows it started.
27
22
  */
28
23
  rejected?: boolean;
29
24
  /** Whether the card has been taken hold of with the keyboard. */
@@ -31,12 +26,8 @@ export interface CalendarEventProps<T> {
31
26
  /** How the card says it can be moved, read from a node the calendar shares between them. */
32
27
  hintId?: string;
33
28
  /**
34
- * Marks this card as the faded echo left behind where a dragged event STARTED, and names
35
- * the event it echoes.
36
- *
37
- * It carries the original id rather than a bare boolean because the colour is derived from
38
- * an id: a ghost has to be given a distinct one so the layout can tell the two apart, and
39
- * without this the echo would come out a different colour from the card it belongs to.
29
+ * Marks this card as the faded echo left behind where a dragged event STARTED, and names the
30
+ * event it echoes.
40
31
  */
41
32
  ghostOf?: CalendarEventId;
42
33
  /** Whether the whole calendar is disabled, which makes the card a real disabled button. */
@@ -1 +1 @@
1
- {"version":3,"file":"VCalendarEvent.js","names":[],"sources":["../../../src/components/VCalendar/VCalendarEvent.vue"],"sourcesContent":["<script setup lang=\"ts\" generic=\"E extends CalendarEvent\">\n// @a11y @core\n/**\n * One event as it is drawn on the calendar. Internal to VCalendar, whose documentation\n * covers it.\n *\n * It exists because the same card is drawn from three places in two shapes — a block in a\n * day column, a chip in the all-day band or a month cell — and writing it three times would\n * triplicate the accessible name, the colour table and the slot.\n *\n * A real `<button>`, which is what makes an event reachable and activatable with no JS of its\n * own. The only script here derives the colour; where the card goes and what a drag does\n * belong to the calendar, the thing that knows about the grid.\n */\nimport { computed } from 'vue'\n\nimport VTypography from '../VTypography/VTypography.vue'\n\nimport { useMessages } from '../../i18n/state'\n\nimport { hueOf } from './color'\nimport type {\n CalendarEvent,\n CalendarEventId,\n CalendarEventLayout,\n CalendarEventSlotProps,\n} from './types'\n\nexport interface CalendarEventProps<T> {\n /** The event this card stands for. */\n event: T\n /**\n * Which shape to take: a block, which fills the box the calendar gives it and can show a\n * second line, or a chip, which is one line high and sits in a row of others.\n */\n layout?: CalendarEventLayout\n /** The event's times, already written out for the reader by the calendar. */\n timeText?: string\n /** Whether the event carries on past the start or the end of what is on show. */\n continuesBefore?: boolean\n continuesAfter?: boolean\n /** Shows the strip along the bottom edge that the event's end is dragged by. */\n resizable?: boolean\n /** Whether the card is being dragged with a pointer right now. */\n dragging?: boolean\n /**\n * Whether letting go now would write nothing: the pointer has left the calendar, and the event\n * is about to return to where the faded echo shows it started.\n *\n * It is separate from `dragging` rather than folded into it because a refused card is ALSO\n * being dragged: the two are orthogonal, and the stylesheet reads both. Named for what the\n * card knows, which is that its drop will not be taken; a card knows nothing of a view it\n * might be outside of.\n */\n rejected?: boolean\n /** Whether the card has been taken hold of with the keyboard. */\n grabbed?: boolean\n /** How the card says it can be moved, read from a node the calendar shares between them. */\n hintId?: string\n /**\n * Marks this card as the faded echo left behind where a dragged event STARTED, and names\n * the event it echoes.\n *\n * It carries the original id rather than a bare boolean because the colour is derived from\n * an id: a ghost has to be given a distinct one so the layout can tell the two apart, and\n * without this the echo would come out a different colour from the card it belongs to.\n */\n ghostOf?: CalendarEventId\n /** Whether the whole calendar is disabled, which makes the card a real disabled button. */\n disabled?: boolean\n}\n\nconst props = withDefaults(defineProps<CalendarEventProps<E>>(), {\n layout: 'block',\n timeText: '',\n continuesBefore: false,\n continuesAfter: false,\n resizable: false,\n dragging: false,\n rejected: false,\n grabbed: false,\n hintId: undefined,\n ghostOf: undefined,\n disabled: false,\n})\n\ndefineSlots<{\n /** The whole content of the card, replacing the title and the times. */\n default?(props: CalendarEventSlotProps<E>): unknown\n}>()\n\nconst m = useMessages()\n\n/*\n * A colour given by the consumer is used as it stands; otherwise a hue is derived from the\n * event's id and the token layer supplies the lightness and the chroma that go with it.\n * The two are kept apart by an attribute rather than by a fallback chain, because the\n * custom case needs a DIFFERENT recipe and not merely a different value — see the\n * stylesheet below.\n */\nconst hue = computed(() => hueOf(props.ghostOf ?? props.event.id))\n\nconst style = computed(() =>\n props.event.color\n ? { '--calendar-event-color': props.event.color }\n : { '--vectis-calendar-event-hue': String(hue.value) },\n)\n\n/**\n * What a screen reader hears: the title, then when it happens. The visible card may hide\n * the times when it is too short to hold them, so the name has to carry them itself —\n * \"Standup\" alone would leave a reader unable to tell two days of it apart.\n */\nconst accessibleName = computed(() =>\n props.timeText ? `${props.event.title}, ${props.timeText}` : props.event.title,\n)\n</script>\n\n<template>\n <button\n type=\"button\"\n class=\"v-calendar-event\"\n :data-event-id=\"String(event.id)\"\n :data-layout=\"layout\"\n :data-custom=\"event.color ? '' : undefined\"\n :data-continues-before=\"continuesBefore ? '' : undefined\"\n :data-continues-after=\"continuesAfter ? '' : undefined\"\n :data-dragging=\"dragging ? '' : undefined\"\n :data-rejected=\"rejected ? '' : undefined\"\n :data-grabbed=\"grabbed ? '' : undefined\"\n :data-ghost=\"ghostOf !== undefined ? '' : undefined\"\n :style=\"style\"\n :aria-label=\"accessibleName\"\n :aria-roledescription=\"m.calendar.eventRoleDescription\"\n :aria-describedby=\"hintId\"\n :disabled=\"disabled || undefined\"\n :inert=\"ghostOf !== undefined ? true : undefined\"\n >\n <!--\n The content sits in a box of its own because the CARD is the container the stylesheet\n queries, and an element cannot be styled by its own container query. The layout that\n has to change when a card gets short — a column of two lines becoming one row — must\n therefore live on a descendant. It is also why the padding belongs here rather than on\n the button: a card cannot zero its own.\n -->\n <span class=\"v-calendar-event-body\">\n <slot\n :event=\"event\"\n :layout=\"layout\"\n :time-text=\"timeText\"\n :continues-before=\"continuesBefore\"\n :continues-after=\"continuesAfter\"\n :dragging=\"dragging\"\n :grabbed=\"grabbed\"\n >\n <span class=\"v-calendar-event-title\">{{ event.title }}</span>\n <span v-if=\"layout === 'block' && timeText\" class=\"v-calendar-event-time\">\n {{ timeText }}\n </span>\n <VTypography\n v-if=\"layout === 'block' && event.description\"\n as=\"span\"\n variant=\"caption\"\n class=\"v-calendar-event-description\"\n >\n {{ event.description }}\n </VTypography>\n </slot>\n </span>\n\n <!--\n The strip the event's end is dragged by.\n\n It is a `span` and NOT a control, which is what keeps it out of the accessibility tree\n and away from `nested-interactive`: a button inside a button is invalid HTML and a\n blocking accessibility failure at once. It is a pointer affordance and nothing else,\n and its keyboard equivalent lives on the card itself as Shift with the arrow keys —\n which is why hiding it costs a reader nothing.\n -->\n <span\n v-if=\"resizable && layout === 'block'\"\n class=\"v-calendar-event-handle\"\n data-calendar-handle\n aria-hidden=\"true\"\n />\n </button>\n</template>\n\n<style>\n@layer vectis.components {\n .v-calendar-event {\n /*\n * The three colours of a card, named by what they paint rather than by where they come\n * from — which is what lets the custom block below swap the SOURCE of all three without\n * touching a single rule that consumes them.\n */\n /*\n * TRAP — the hue is turned HERE, on the card, and never in the tokens. A token carrying\n * `var(--vectis-calendar-event-hue)` is resolved on `:root`, where no card has set one,\n * and every event came out in the fallback hue. Relative colour syntax keeps the token's\n * lightness and chroma, which are what hold the title's contrast, and takes the hue the\n * card sets inline, or the token's own (`h`) when none is set.\n */\n --calendar-event-face: oklch(\n from var(--vectis-color-event-surface) l c var(--vectis-calendar-event-hue, h)\n );\n --calendar-event-edge: oklch(\n from var(--vectis-color-event-border) l c var(--vectis-calendar-event-hue, h)\n );\n --calendar-event-ink: oklch(\n from var(--vectis-color-event-text) l c var(--vectis-calendar-event-hue, h)\n );\n\n /* The handle is placed against this box, so the card has to establish one. */\n position: relative;\n display: flex;\n overflow: hidden;\n /*\n * The card is what the body below is measured against.\n *\n * `size` and not `inline-size`, which is what the library's other four containers use:\n * the question being asked here is about HEIGHT, since that is what a short event runs\n * out of. It is safe because a card's two dimensions are both set outright by\n * `.v-calendar-block` — size containment therefore removes an influence nothing was\n * exercising. Asking in minutes instead would have meant calibrating against\n * `--vectis-control-size-calendar-hour`, and being silently wrong for anyone who\n * overrode it.\n */\n container-type: size;\n border: 1px solid var(--calendar-event-edge);\n /* The leading edge is what carries the colour at a glance, so it is drawn thicker. It\n is a border and not a background stripe: under Windows forced-colors a background is\n forced to Canvas and vanishes, where a border keeps a colour of its own. */\n border-inline-start: var(--vectis-control-size-calendar-event-edge) solid\n var(--calendar-event-edge);\n /* TRAP — the cap is measured against the all-day LANE, the shortest thing this same\n class ever renders, and against nothing else. A browser scales down any radius it\n cannot fit, so a chip already paints half a lane under a large\n --vectis-radius-interactive; min() applies that same reduction to a timed block,\n whose height is the event's DURATION. Written bare, a pill theme paints half of a\n three-hour block instead: 96px corners on one card and 12px on the chip beside it.\n Never take the unit from --vectis-control-size-calendar-hour, for the reason the\n `container-type` comment above already gives — the radius has nothing to do with how\n tall an hour is, and anyone retuning that token would move it by accident. */\n border-radius: min(\n var(--vectis-radius-interactive),\n calc(var(--vectis-control-size-calendar-allday-lane) / 2)\n );\n background: var(--calendar-event-face);\n color: var(--calendar-event-ink);\n font-family: var(--vectis-text-family);\n text-align: start;\n cursor: pointer;\n transition:\n box-shadow var(--vectis-duration-fast) var(--vectis-ease-default),\n filter var(--vectis-duration-fast) var(--vectis-ease-default);\n }\n\n /*\n * A colour the consumer chose is an arbitrary value, so the card is built so that NOTHING\n * is ever written on top of it: it paints the edge, and the face is a faint wash of it\n * over the page's own surface — which also makes it follow the theme with no second\n * setting. The text stays the page's text colour, whose contrast against that surface is\n * already guaranteed. This is the deliberate difference from VChip, where a fully\n * coloured chip leaves the check to whoever chose the colour.\n */\n .v-calendar-event[data-custom] {\n --calendar-event-edge: var(--calendar-event-color);\n --calendar-event-face: color-mix(\n in oklab,\n var(--calendar-event-color) 14%,\n var(--vectis-color-surface)\n );\n --calendar-event-ink: var(--vectis-color-text);\n }\n\n .v-calendar-event-body {\n display: flex;\n flex: 1;\n flex-direction: column;\n gap: 1px;\n /* Without this a flex item refuses to shrink past its content, and a card too short for\n its own text would push its title out of the clip instead of cropping it. */\n min-block-size: 0;\n min-inline-size: 0;\n overflow: hidden;\n padding: var(--vectis-space-1) var(--vectis-space-2);\n }\n\n /*\n * A card too short for two lines puts them on ONE: the title first, the time after it, and\n * the description dropped — which is the only way a quarter of an hour shows anything at\n * all. Three rem is where a title line, a time line, the gap and the padding stop fitting;\n * below it there is room for exactly one line.\n *\n * The TITLE keeps that line. It is what identifies the event, where the times are already in\n * the card's accessible name and readable from its height. Both items shrink, but the time's\n * shrink factor is large enough that it gives up its whole width, down to an ellipsis and then\n * to nothing, before the title loses a character: flex shrinking is weighted by factor times\n * basis, so a factor a thousand times the title's leaves the title a rounding error.\n *\n * The threshold is a literal because a container query takes no custom properties — the\n * same constraint VPagination's steps are written under.\n */\n @container (max-block-size: 3rem) {\n .v-calendar-event[data-layout='block'] .v-calendar-event-body {\n flex-direction: row;\n align-items: center;\n gap: var(--vectis-space-1);\n padding-block: 0;\n }\n\n .v-calendar-event[data-layout='block'] .v-calendar-event-title {\n flex: 0 1 auto;\n min-inline-size: 0;\n }\n\n .v-calendar-event[data-layout='block'] .v-calendar-event-time {\n flex: 0 1000 auto;\n min-inline-size: 0;\n }\n\n /* There is no room for a third thing, and the title is what identifies the event. */\n .v-calendar-event[data-layout='block'] .v-calendar-event-description {\n display: none;\n }\n }\n\n /*\n * The shortest card there is: one slot, which at the default hour height is sixteen pixels,\n * leaving fourteen once the border is taken. A line of the title at its normal leading is\n * eighteen — so the leading is what gives, down to the glyphs themselves. Nothing smaller\n * is available: twelve pixels is already the smallest type role the library has.\n *\n * This tier exists because a card may no longer grow past its own length: it is the price\n * of a quarter of an hour that stays inside its slot, and it is paid in leading rather than\n * in a card that covers the next one.\n */\n @container (max-block-size: 1.5rem) {\n .v-calendar-event[data-layout='block'] .v-calendar-event-title,\n .v-calendar-event[data-layout='block'] .v-calendar-event-time {\n line-height: 1;\n }\n\n /* Half the strip, or half of a sixteen-pixel card would resize rather than move it. */\n .v-calendar-event[data-layout='block'] .v-calendar-event-handle {\n block-size: calc(var(--vectis-control-size-calendar-handle) / 2);\n }\n }\n\n .v-calendar-event:hover {\n filter: brightness(0.97);\n }\n\n /*\n * A card being moved is lifted off the grid and made slightly transparent, so the hours\n * underneath stay readable while it travels — a solid card would hide the very rules the\n * reader is aiming at. `pointer-events: none` matters as much: the pointer is captured by\n * the grid, and a card under the cursor would otherwise take the hover of every cell it\n * passed over.\n */\n .v-calendar-event[data-dragging] {\n opacity: 0.75;\n box-shadow: var(--vectis-shadow-md);\n pointer-events: none;\n z-index: 3;\n }\n\n /*\n * A card whose drop will not be taken: the pointer has left the calendar, and letting go here\n * puts the event back where the echo shows it started.\n *\n * THREE channels, because one is never enough. The colour is the danger role, reached through\n * the same three local variables `[data-custom]` swaps — which is also what repaints a card the\n * consumer coloured, that rule sitting higher up this sheet. The LIFT is taken away, so a card\n * that will not land visibly stops being carried: the one cue that costs no colour at all. And\n * the border goes DOTTED, the only one of the three surviving Windows forced-colors, where the\n * face is forced to Canvas and every card would otherwise look identical — dotted rather than\n * dashed because dashed is already the echo's language, and a refused drop must not read as a\n * memory of one.\n *\n * `opacity: 0.75` is deliberately left in place: it is what keeps the hours under the card\n * readable, and the reader is still aiming with it.\n *\n * TRAP — this rule must stay BELOW `[data-dragging]`. Both are (0,2,0) and a refused card is\n * always also a dragged one, so the later rule is the whole of the arbitration. That is\n * legitimate here and only here: these two live in the SAME sheet, where the internal order is\n * ours to decide — between two component sheets it would be the consumer's bundler deciding.\n */\n .v-calendar-event[data-rejected] {\n --calendar-event-face: var(--vectis-color-danger-surface);\n --calendar-event-edge: var(--vectis-color-danger-border);\n --calendar-event-ink: var(--vectis-color-danger-text);\n\n border-style: dotted;\n box-shadow: none;\n }\n\n /*\n * The echo left where a dragged event started, so the reader can see what they are moving\n * it FROM — without it a long drag ends with no idea what has just been given up.\n *\n * Faded rather than outlined, and dashed rather than solid, so that it reads as a memory\n * and not as a second event: at a glance the only card that looks real is the one under the\n * pointer. It sits UNDER everything (`z-index: 0`), since it is the one thing on the grid\n * that nothing should ever be hidden behind.\n *\n * `inert` in the template is what keeps it out of the accessibility tree and out of reach\n * of the pointer, in one attribute — a duplicate announced a second time would be noise,\n * and a focusable copy inside a hidden subtree is an axe violation of its own.\n */\n .v-calendar-event[data-ghost] {\n opacity: 0.4;\n border-style: dashed;\n z-index: 0;\n }\n\n /* Held by the keyboard: the same lift, but marked with the focus ring's own colour, since\n there is no pointer to show where it is going. */\n .v-calendar-event[data-grabbed] {\n outline: var(--vectis-focus-ring-width) solid var(--vectis-focus-ring-color);\n outline-offset: var(--vectis-focus-ring-offset);\n box-shadow: var(--vectis-shadow-md);\n z-index: 3;\n }\n\n .v-calendar-event-handle {\n position: absolute;\n inset-block-end: 0;\n inset-inline: 0;\n block-size: var(--vectis-control-size-calendar-handle);\n /* Dragging here IS how the end is set, so it must do nothing else: no scrolling under a\n finger, and no selecting the text it sits over. */\n touch-action: none;\n cursor: ns-resize;\n }\n\n /* The grip appears on hover and while the card is being resized, never permanently: a\n short card is mostly handle, and a line across every event all the time reads as a\n border nobody asked for. */\n .v-calendar-event-handle::after {\n content: '';\n position: absolute;\n inset-block-end: var(--vectis-control-size-calendar-grip-thickness);\n inset-inline-start: 50%;\n inline-size: var(--vectis-control-size-calendar-grip);\n block-size: var(--vectis-control-size-calendar-grip-thickness);\n translate: -50% 0;\n border-radius: var(--vectis-radius-pill);\n background: var(--calendar-event-ink);\n opacity: 0;\n transition: opacity var(--vectis-duration-fast) var(--vectis-ease-default);\n }\n\n .v-calendar-event:hover .v-calendar-event-handle::after,\n .v-calendar-event[data-dragging] .v-calendar-event-handle::after {\n opacity: 0.6;\n }\n\n .v-calendar-event:focus-visible {\n outline: var(--vectis-focus-ring-width) solid var(--vectis-focus-ring-color);\n outline-offset: calc(-1 * var(--vectis-focus-ring-width));\n }\n\n /* An event running past what is on show loses the corner on that side, so the card reads\n as cut off rather than as merely small. */\n .v-calendar-event[data-continues-before] {\n border-start-start-radius: 0;\n border-start-end-radius: 0;\n border-block-start-style: dashed;\n }\n\n .v-calendar-event[data-continues-after] {\n border-end-start-radius: 0;\n border-end-end-radius: 0;\n border-block-end-style: dashed;\n }\n\n /*\n * A chip fills the box it was put in — a lane of the all-day band, whose grid row is\n * already the right height — unless the consumer of this class names a height instead.\n *\n * TRAP — that indirection is not a nicety, it is the only correct shape. This selector is\n * (0,2,0) and `.v-calendar-month-chip`, which needs a different height, is (0,1,0) in\n * ANOTHER SHEET: matching specificity would hand the winner to whichever order the\n * consumer's bundler happens to emit, and beating it would need a three-class compound.\n * Routing through a property this rule already reads is the library's documented way out,\n * the one `.v-data-table-title` takes on `--typography-color`.\n */\n .v-calendar-event[data-layout='chip'] {\n block-size: var(--calendar-chip-height, 100%);\n }\n\n .v-calendar-event[data-layout='chip'] .v-calendar-event-body {\n flex-direction: row;\n align-items: center;\n gap: var(--vectis-space-1);\n padding-block: 0;\n }\n\n .v-calendar-event-title {\n overflow: hidden;\n font-size: var(--vectis-text-body-sm-size);\n font-weight: var(--vectis-font-weight-medium);\n line-height: var(--vectis-text-body-sm-leading);\n text-overflow: ellipsis;\n white-space: nowrap;\n }\n\n .v-calendar-event-time {\n overflow: hidden;\n font-size: var(--vectis-text-caption-size);\n line-height: var(--vectis-text-caption-leading);\n text-overflow: ellipsis;\n white-space: nowrap;\n /* The times are secondary to the title, but the card's colour is already doing the\n quiet work — a muted token here would fight it, so the same ink at less weight. */\n opacity: 0.85;\n }\n\n .v-calendar-event-description {\n overflow: hidden;\n /* The card's height is the event's length, so a description shows only where there is\n genuinely room for it: it takes whatever is left and disappears when that is nothing. */\n min-block-size: 0;\n color: inherit;\n text-overflow: ellipsis;\n opacity: 0.85;\n }\n\n @media (prefers-reduced-motion: reduce) {\n .v-calendar-event,\n .v-calendar-event-handle::after {\n transition: none;\n }\n }\n\n /* The resize grip is a background, which forced colors would flatten to Canvas. */\n @media (forced-colors: active) {\n .v-calendar-event-handle::after {\n forced-color-adjust: none;\n background: CanvasText;\n }\n }\n}\n</style>\n"],"mappings":""}
1
+ {"version":3,"file":"VCalendarEvent.js","names":[],"sources":["../../../src/components/VCalendar/VCalendarEvent.vue"],"sourcesContent":["<script setup lang=\"ts\" generic=\"E extends CalendarEvent\">\n// @a11y @core\n/**\n * Share the native event button across calendar views so accessible naming and event-slot\n * rendering remain consistent.\n */\nimport { computed } from 'vue'\n\nimport VTypography from '../VTypography/VTypography.vue'\n\nimport { useMessages } from '../../i18n/state'\n\nimport { hueOf } from './color'\nimport type {\n CalendarEvent,\n CalendarEventId,\n CalendarEventLayout,\n CalendarEventSlotProps,\n} from './types'\n\nexport interface CalendarEventProps<T> {\n /** The event this card stands for. */\n event: T\n /**\n * Which shape to take: a block, which fills the box the calendar gives it and can show a\n * second line, or a chip, which is one line high and sits in a row of others.\n */\n layout?: CalendarEventLayout\n /** The event's times, already written out for the reader by the calendar. */\n timeText?: string\n /** Whether the event carries on past the start or the end of what is on show. */\n continuesBefore?: boolean\n continuesAfter?: boolean\n /** Shows the strip along the bottom edge that the event's end is dragged by. */\n resizable?: boolean\n /** Whether the card is being dragged with a pointer right now. */\n dragging?: boolean\n /**\n * Whether letting go now would write nothing: the pointer has left the calendar, and the\n * event is about to return to where the faded echo shows it started.\n */\n rejected?: boolean\n /** Whether the card has been taken hold of with the keyboard. */\n grabbed?: boolean\n /** How the card says it can be moved, read from a node the calendar shares between them. */\n hintId?: string\n /**\n * Marks this card as the faded echo left behind where a dragged event STARTED, and names the\n * event it echoes.\n */\n ghostOf?: CalendarEventId\n /** Whether the whole calendar is disabled, which makes the card a real disabled button. */\n disabled?: boolean\n}\n\nconst props = withDefaults(defineProps<CalendarEventProps<E>>(), {\n layout: 'block',\n timeText: '',\n continuesBefore: false,\n continuesAfter: false,\n resizable: false,\n dragging: false,\n rejected: false,\n grabbed: false,\n hintId: undefined,\n ghostOf: undefined,\n disabled: false,\n})\n\ndefineSlots<{\n /** The whole content of the card, replacing the title and the times. */\n default?(props: CalendarEventSlotProps<E>): unknown\n}>()\n\nconst m = useMessages()\n\n/*\n * A colour given by the consumer is used as it stands; otherwise a hue is derived from the\n * event's id and the token layer supplies the lightness and the chroma that go with it. The two\n * are kept apart by an attribute rather than by a fallback chain, because the custom case needs\n * a DIFFERENT recipe and not merely a different value; see the stylesheet below.\n */\nconst hue = computed(() => hueOf(props.ghostOf ?? props.event.id))\n\nconst style = computed(() =>\n props.event.color\n ? { '--calendar-event-color': props.event.color }\n : { '--vectis-calendar-event-hue': String(hue.value) },\n)\n\n/** What a screen reader hears: the title, then when it happens. */\nconst accessibleName = computed(() =>\n props.timeText ? `${props.event.title}, ${props.timeText}` : props.event.title,\n)\n</script>\n\n<template>\n <button\n type=\"button\"\n class=\"v-calendar-event\"\n :data-event-id=\"String(event.id)\"\n :data-layout=\"layout\"\n :data-custom=\"event.color ? '' : undefined\"\n :data-continues-before=\"continuesBefore ? '' : undefined\"\n :data-continues-after=\"continuesAfter ? '' : undefined\"\n :data-dragging=\"dragging ? '' : undefined\"\n :data-rejected=\"rejected ? '' : undefined\"\n :data-grabbed=\"grabbed ? '' : undefined\"\n :data-ghost=\"ghostOf !== undefined ? '' : undefined\"\n :style=\"style\"\n :aria-label=\"accessibleName\"\n :aria-roledescription=\"m.calendar.eventRoleDescription\"\n :aria-describedby=\"hintId\"\n :disabled=\"disabled || undefined\"\n :inert=\"ghostOf !== undefined ? true : undefined\"\n >\n <!--\n The content sits in a box of its own because the CARD is the container the stylesheet\n queries, and an element cannot be styled by its own container query. The layout that has\n to change when a card gets short; a column of two lines becoming one row; must therefore\n live on a descendant.\n -->\n <span class=\"v-calendar-event-body\">\n <slot\n :event=\"event\"\n :layout=\"layout\"\n :time-text=\"timeText\"\n :continues-before=\"continuesBefore\"\n :continues-after=\"continuesAfter\"\n :dragging=\"dragging\"\n :grabbed=\"grabbed\"\n >\n <span class=\"v-calendar-event-title\">{{ event.title }}</span>\n <span v-if=\"layout === 'block' && timeText\" class=\"v-calendar-event-time\">\n {{ timeText }}\n </span>\n <VTypography\n v-if=\"layout === 'block' && event.description\"\n as=\"span\"\n variant=\"caption\"\n class=\"v-calendar-event-description\"\n >\n {{ event.description }}\n </VTypography>\n </slot>\n </span>\n\n <!--\n It is a pointer affordance and nothing else, and its keyboard equivalent lives on the card\n itself as Shift with the arrow keys; which is why hiding it costs a reader nothing.\n -->\n <span\n v-if=\"resizable && layout === 'block'\"\n class=\"v-calendar-event-handle\"\n data-calendar-handle\n aria-hidden=\"true\"\n />\n </button>\n</template>\n\n<style>\n@layer vectis.components {\n .v-calendar-event {\n /*\n * The three colours of a card, named by what they paint rather than by where they come\n * from; which lets the custom block below swap the source of all three without touching a\n * single rule that consumes them.\n */\n /*\n * The hue is turned here, on the card, and never in the tokens. Relative colour syntax\n * keeps the token's lightness and chroma, which are what hold the title's contrast, and\n * takes the hue the card sets inline, or the token's own (`h`) when none is set.\n */\n --calendar-event-face: oklch(\n from var(--vectis-color-event-surface) l c var(--vectis-calendar-event-hue, h)\n );\n --calendar-event-edge: oklch(\n from var(--vectis-color-event-border) l c var(--vectis-calendar-event-hue, h)\n );\n --calendar-event-ink: oklch(\n from var(--vectis-color-event-text) l c var(--vectis-calendar-event-hue, h)\n );\n\n position: relative;\n display: flex;\n overflow: hidden;\n /*\n * It is safe because a card's two dimensions are both set outright by `.v-calendar-block`;\n * size containment therefore removes an influence nothing was exercising. Asking in minutes\n * instead would have meant calibrating against `--vectis-control-size-calendar-hour`, and\n * being silently wrong for anyone who overrode it.\n */\n container-type: size;\n border: 1px solid var(--calendar-event-edge);\n /* The leading edge is what carries the colour at a glance, so it is drawn thicker. It\n is a border and not a background stripe: under Windows forced-colors a background is\n forced to Canvas and vanishes, where a border keeps a colour of its own. */\n border-inline-start: var(--vectis-control-size-calendar-event-edge) solid\n var(--calendar-event-edge);\n /*\n * A browser scales down any radius it cannot fit, so a chip already paints half a lane\n * under a large --vectis-radius-interactive; min() applies that same reduction to a timed\n * block, whose height is the event's DURATION. Written bare, a pill theme paints half of a\n * three-hour block instead: 96px corners on one card and 12px on the chip beside it.\n */\n border-radius: min(\n var(--vectis-radius-interactive),\n calc(var(--vectis-control-size-calendar-allday-lane) / 2)\n );\n background: var(--calendar-event-face);\n color: var(--calendar-event-ink);\n font-family: var(--vectis-text-family);\n text-align: start;\n cursor: pointer;\n transition:\n box-shadow var(--vectis-duration-fast) var(--vectis-ease-default),\n filter var(--vectis-duration-fast) var(--vectis-ease-default);\n }\n\n /*\n * A colour the consumer chose is an arbitrary value, so the card is built so that NOTHING is\n * ever written on top of it: it paints the edge, and the face is a faint wash of it over the\n * page's own surface; which also makes it follow the theme with no second setting. The text\n * stays the page's text colour, whose contrast against that surface is already guaranteed.\n */\n .v-calendar-event[data-custom] {\n --calendar-event-edge: var(--calendar-event-color);\n --calendar-event-face: color-mix(\n in oklab,\n var(--calendar-event-color) 14%,\n var(--vectis-color-surface)\n );\n --calendar-event-ink: var(--vectis-color-text);\n }\n\n .v-calendar-event-body {\n display: flex;\n flex: 1;\n flex-direction: column;\n gap: 1px;\n /* Without this a flex item refuses to shrink past its content, and a card too short for\n its own text would push its title out of the clip instead of cropping it. */\n min-block-size: 0;\n min-inline-size: 0;\n overflow: hidden;\n padding: var(--vectis-space-1) var(--vectis-space-2);\n }\n\n /*\n * Give the time a larger weighted flex-shrink so it disappears before truncating the event\n * title.\n */\n @container (max-block-size: 3rem) {\n .v-calendar-event[data-layout='block'] .v-calendar-event-body {\n flex-direction: row;\n align-items: center;\n gap: var(--vectis-space-1);\n padding-block: 0;\n }\n\n .v-calendar-event[data-layout='block'] .v-calendar-event-title {\n flex: 0 1 auto;\n min-inline-size: 0;\n }\n\n .v-calendar-event[data-layout='block'] .v-calendar-event-time {\n flex: 0 1000 auto;\n min-inline-size: 0;\n }\n\n .v-calendar-event[data-layout='block'] .v-calendar-event-description {\n display: none;\n }\n }\n\n /*\n * The shortest card there is: one slot, which at the default hour height is sixteen pixels,\n * leaving fourteen once the border is taken. A line of the title at its normal leading is\n * eighteen; so the leading is what gives, down to the glyphs themselves.\n */\n @container (max-block-size: 1.5rem) {\n .v-calendar-event[data-layout='block'] .v-calendar-event-title,\n .v-calendar-event[data-layout='block'] .v-calendar-event-time {\n line-height: 1;\n }\n\n .v-calendar-event[data-layout='block'] .v-calendar-event-handle {\n block-size: calc(var(--vectis-control-size-calendar-handle) / 2);\n }\n }\n\n .v-calendar-event:hover {\n filter: brightness(0.97);\n }\n\n /*\n * `pointer-events: none` matters as much: the pointer is captured by the grid, and a card\n * under the cursor would otherwise take the hover of every cell it passed over.\n */\n .v-calendar-event[data-dragging] {\n opacity: 0.75;\n box-shadow: var(--vectis-shadow-md);\n pointer-events: none;\n z-index: 3;\n }\n\n /*\n * This rule must stay BELOW `[data-dragging]`. Both are (0,2,0) and a refused card is always\n * also a dragged one, so the later rule is the whole of the arbitration.\n */\n .v-calendar-event[data-rejected] {\n --calendar-event-face: var(--vectis-color-danger-surface);\n --calendar-event-edge: var(--vectis-color-danger-border);\n --calendar-event-ink: var(--vectis-color-danger-text);\n\n border-style: dotted;\n box-shadow: none;\n }\n\n /*\n * The echo left where a dragged event started, so the reader can see what they are moving it\n * FROM; without it a long drag ends with no idea what has just been given up. Faded rather\n * than outlined, and dashed rather than solid, so that it reads as a memory and not as a\n * second event: at a glance the only card that looks real is the one under the pointer.\n */\n .v-calendar-event[data-ghost] {\n opacity: 0.4;\n border-style: dashed;\n z-index: 0;\n }\n\n /* Held by the keyboard: the same lift, but marked with the focus ring's own colour, since\n there is no pointer to show where it is going. */\n .v-calendar-event[data-grabbed] {\n outline: var(--vectis-focus-ring-width) solid var(--vectis-focus-ring-color);\n outline-offset: var(--vectis-focus-ring-offset);\n box-shadow: var(--vectis-shadow-md);\n z-index: 3;\n }\n\n .v-calendar-event-handle {\n position: absolute;\n inset-block-end: 0;\n inset-inline: 0;\n block-size: var(--vectis-control-size-calendar-handle);\n /* Dragging here IS how the end is set, so it must do nothing else: no scrolling under a\n finger, and no selecting the text it sits over. */\n touch-action: none;\n cursor: ns-resize;\n }\n\n /* The grip appears on hover and while the card is being resized, never permanently: a\n short card is mostly handle, and a line across every event all the time reads as a\n border nobody asked for. */\n .v-calendar-event-handle::after {\n content: '';\n position: absolute;\n inset-block-end: var(--vectis-control-size-calendar-grip-thickness);\n inset-inline-start: 50%;\n inline-size: var(--vectis-control-size-calendar-grip);\n block-size: var(--vectis-control-size-calendar-grip-thickness);\n translate: -50% 0;\n border-radius: var(--vectis-radius-pill);\n background: var(--calendar-event-ink);\n opacity: 0;\n transition: opacity var(--vectis-duration-fast) var(--vectis-ease-default);\n }\n\n .v-calendar-event:hover .v-calendar-event-handle::after,\n .v-calendar-event[data-dragging] .v-calendar-event-handle::after {\n opacity: 0.6;\n }\n\n .v-calendar-event:focus-visible {\n outline: var(--vectis-focus-ring-width) solid var(--vectis-focus-ring-color);\n outline-offset: calc(-1 * var(--vectis-focus-ring-width));\n }\n\n /* An event running past what is on show loses the corner on that side, so the card reads\n as cut off rather than as merely small. */\n .v-calendar-event[data-continues-before] {\n border-start-start-radius: 0;\n border-start-end-radius: 0;\n border-block-start-style: dashed;\n }\n\n .v-calendar-event[data-continues-after] {\n border-end-start-radius: 0;\n border-end-end-radius: 0;\n border-block-end-style: dashed;\n }\n\n /*\n * That indirection is not a nicety, it is the only correct shape. This selector is (0,2,0)\n * and `.v-calendar-month-chip`, which needs a different height, is (0,1,0) in ANOTHER SHEET:\n * matching specificity would hand the winner to whichever order the consumer's bundler\n * happens to emit, and beating it would need a three-class compound.\n */\n .v-calendar-event[data-layout='chip'] {\n block-size: var(--calendar-chip-height, 100%);\n }\n\n .v-calendar-event[data-layout='chip'] .v-calendar-event-body {\n flex-direction: row;\n align-items: center;\n gap: var(--vectis-space-1);\n padding-block: 0;\n }\n\n .v-calendar-event-title {\n overflow: hidden;\n font-size: var(--vectis-text-body-sm-size);\n font-weight: var(--vectis-font-weight-medium);\n line-height: var(--vectis-text-body-sm-leading);\n text-overflow: ellipsis;\n white-space: nowrap;\n }\n\n .v-calendar-event-time {\n overflow: hidden;\n font-size: var(--vectis-text-caption-size);\n line-height: var(--vectis-text-caption-leading);\n text-overflow: ellipsis;\n white-space: nowrap;\n /*\n * The times are secondary to the title, but the card's colour is already doing the quiet\n * work; a muted token here would fight it, so the same ink at less weight.\n */\n opacity: 0.85;\n }\n\n .v-calendar-event-description {\n overflow: hidden;\n /* The card's height is the event's length, so a description shows only where there is\n genuinely room for it: it takes whatever is left and disappears when that is nothing. */\n min-block-size: 0;\n color: inherit;\n text-overflow: ellipsis;\n opacity: 0.85;\n }\n\n @media (prefers-reduced-motion: reduce) {\n .v-calendar-event,\n .v-calendar-event-handle::after {\n transition: none;\n }\n }\n\n @media (forced-colors: active) {\n .v-calendar-event-handle::after {\n forced-color-adjust: none;\n background: CanvasText;\n }\n }\n}\n</style>\n"],"mappings":""}
@@ -1 +1 @@
1
- {"version":3,"file":"VCalendarEvent.vue_vue_type_script_setup_true_lang.js","names":[],"sources":["../../../src/components/VCalendar/VCalendarEvent.vue"],"sourcesContent":["<script setup lang=\"ts\" generic=\"E extends CalendarEvent\">\n// @a11y @core\n/**\n * One event as it is drawn on the calendar. Internal to VCalendar, whose documentation\n * covers it.\n *\n * It exists because the same card is drawn from three places in two shapes — a block in a\n * day column, a chip in the all-day band or a month cell — and writing it three times would\n * triplicate the accessible name, the colour table and the slot.\n *\n * A real `<button>`, which is what makes an event reachable and activatable with no JS of its\n * own. The only script here derives the colour; where the card goes and what a drag does\n * belong to the calendar, the thing that knows about the grid.\n */\nimport { computed } from 'vue'\n\nimport VTypography from '../VTypography/VTypography.vue'\n\nimport { useMessages } from '../../i18n/state'\n\nimport { hueOf } from './color'\nimport type {\n CalendarEvent,\n CalendarEventId,\n CalendarEventLayout,\n CalendarEventSlotProps,\n} from './types'\n\nexport interface CalendarEventProps<T> {\n /** The event this card stands for. */\n event: T\n /**\n * Which shape to take: a block, which fills the box the calendar gives it and can show a\n * second line, or a chip, which is one line high and sits in a row of others.\n */\n layout?: CalendarEventLayout\n /** The event's times, already written out for the reader by the calendar. */\n timeText?: string\n /** Whether the event carries on past the start or the end of what is on show. */\n continuesBefore?: boolean\n continuesAfter?: boolean\n /** Shows the strip along the bottom edge that the event's end is dragged by. */\n resizable?: boolean\n /** Whether the card is being dragged with a pointer right now. */\n dragging?: boolean\n /**\n * Whether letting go now would write nothing: the pointer has left the calendar, and the event\n * is about to return to where the faded echo shows it started.\n *\n * It is separate from `dragging` rather than folded into it because a refused card is ALSO\n * being dragged: the two are orthogonal, and the stylesheet reads both. Named for what the\n * card knows, which is that its drop will not be taken; a card knows nothing of a view it\n * might be outside of.\n */\n rejected?: boolean\n /** Whether the card has been taken hold of with the keyboard. */\n grabbed?: boolean\n /** How the card says it can be moved, read from a node the calendar shares between them. */\n hintId?: string\n /**\n * Marks this card as the faded echo left behind where a dragged event STARTED, and names\n * the event it echoes.\n *\n * It carries the original id rather than a bare boolean because the colour is derived from\n * an id: a ghost has to be given a distinct one so the layout can tell the two apart, and\n * without this the echo would come out a different colour from the card it belongs to.\n */\n ghostOf?: CalendarEventId\n /** Whether the whole calendar is disabled, which makes the card a real disabled button. */\n disabled?: boolean\n}\n\nconst props = withDefaults(defineProps<CalendarEventProps<E>>(), {\n layout: 'block',\n timeText: '',\n continuesBefore: false,\n continuesAfter: false,\n resizable: false,\n dragging: false,\n rejected: false,\n grabbed: false,\n hintId: undefined,\n ghostOf: undefined,\n disabled: false,\n})\n\ndefineSlots<{\n /** The whole content of the card, replacing the title and the times. */\n default?(props: CalendarEventSlotProps<E>): unknown\n}>()\n\nconst m = useMessages()\n\n/*\n * A colour given by the consumer is used as it stands; otherwise a hue is derived from the\n * event's id and the token layer supplies the lightness and the chroma that go with it.\n * The two are kept apart by an attribute rather than by a fallback chain, because the\n * custom case needs a DIFFERENT recipe and not merely a different value — see the\n * stylesheet below.\n */\nconst hue = computed(() => hueOf(props.ghostOf ?? props.event.id))\n\nconst style = computed(() =>\n props.event.color\n ? { '--calendar-event-color': props.event.color }\n : { '--vectis-calendar-event-hue': String(hue.value) },\n)\n\n/**\n * What a screen reader hears: the title, then when it happens. The visible card may hide\n * the times when it is too short to hold them, so the name has to carry them itself —\n * \"Standup\" alone would leave a reader unable to tell two days of it apart.\n */\nconst accessibleName = computed(() =>\n props.timeText ? `${props.event.title}, ${props.timeText}` : props.event.title,\n)\n</script>\n\n<template>\n <button\n type=\"button\"\n class=\"v-calendar-event\"\n :data-event-id=\"String(event.id)\"\n :data-layout=\"layout\"\n :data-custom=\"event.color ? '' : undefined\"\n :data-continues-before=\"continuesBefore ? '' : undefined\"\n :data-continues-after=\"continuesAfter ? '' : undefined\"\n :data-dragging=\"dragging ? '' : undefined\"\n :data-rejected=\"rejected ? '' : undefined\"\n :data-grabbed=\"grabbed ? '' : undefined\"\n :data-ghost=\"ghostOf !== undefined ? '' : undefined\"\n :style=\"style\"\n :aria-label=\"accessibleName\"\n :aria-roledescription=\"m.calendar.eventRoleDescription\"\n :aria-describedby=\"hintId\"\n :disabled=\"disabled || undefined\"\n :inert=\"ghostOf !== undefined ? true : undefined\"\n >\n <!--\n The content sits in a box of its own because the CARD is the container the stylesheet\n queries, and an element cannot be styled by its own container query. The layout that\n has to change when a card gets short — a column of two lines becoming one row — must\n therefore live on a descendant. It is also why the padding belongs here rather than on\n the button: a card cannot zero its own.\n -->\n <span class=\"v-calendar-event-body\">\n <slot\n :event=\"event\"\n :layout=\"layout\"\n :time-text=\"timeText\"\n :continues-before=\"continuesBefore\"\n :continues-after=\"continuesAfter\"\n :dragging=\"dragging\"\n :grabbed=\"grabbed\"\n >\n <span class=\"v-calendar-event-title\">{{ event.title }}</span>\n <span v-if=\"layout === 'block' && timeText\" class=\"v-calendar-event-time\">\n {{ timeText }}\n </span>\n <VTypography\n v-if=\"layout === 'block' && event.description\"\n as=\"span\"\n variant=\"caption\"\n class=\"v-calendar-event-description\"\n >\n {{ event.description }}\n </VTypography>\n </slot>\n </span>\n\n <!--\n The strip the event's end is dragged by.\n\n It is a `span` and NOT a control, which is what keeps it out of the accessibility tree\n and away from `nested-interactive`: a button inside a button is invalid HTML and a\n blocking accessibility failure at once. It is a pointer affordance and nothing else,\n and its keyboard equivalent lives on the card itself as Shift with the arrow keys —\n which is why hiding it costs a reader nothing.\n -->\n <span\n v-if=\"resizable && layout === 'block'\"\n class=\"v-calendar-event-handle\"\n data-calendar-handle\n aria-hidden=\"true\"\n />\n </button>\n</template>\n\n<style>\n@layer vectis.components {\n .v-calendar-event {\n /*\n * The three colours of a card, named by what they paint rather than by where they come\n * from — which is what lets the custom block below swap the SOURCE of all three without\n * touching a single rule that consumes them.\n */\n /*\n * TRAP — the hue is turned HERE, on the card, and never in the tokens. A token carrying\n * `var(--vectis-calendar-event-hue)` is resolved on `:root`, where no card has set one,\n * and every event came out in the fallback hue. Relative colour syntax keeps the token's\n * lightness and chroma, which are what hold the title's contrast, and takes the hue the\n * card sets inline, or the token's own (`h`) when none is set.\n */\n --calendar-event-face: oklch(\n from var(--vectis-color-event-surface) l c var(--vectis-calendar-event-hue, h)\n );\n --calendar-event-edge: oklch(\n from var(--vectis-color-event-border) l c var(--vectis-calendar-event-hue, h)\n );\n --calendar-event-ink: oklch(\n from var(--vectis-color-event-text) l c var(--vectis-calendar-event-hue, h)\n );\n\n /* The handle is placed against this box, so the card has to establish one. */\n position: relative;\n display: flex;\n overflow: hidden;\n /*\n * The card is what the body below is measured against.\n *\n * `size` and not `inline-size`, which is what the library's other four containers use:\n * the question being asked here is about HEIGHT, since that is what a short event runs\n * out of. It is safe because a card's two dimensions are both set outright by\n * `.v-calendar-block` — size containment therefore removes an influence nothing was\n * exercising. Asking in minutes instead would have meant calibrating against\n * `--vectis-control-size-calendar-hour`, and being silently wrong for anyone who\n * overrode it.\n */\n container-type: size;\n border: 1px solid var(--calendar-event-edge);\n /* The leading edge is what carries the colour at a glance, so it is drawn thicker. It\n is a border and not a background stripe: under Windows forced-colors a background is\n forced to Canvas and vanishes, where a border keeps a colour of its own. */\n border-inline-start: var(--vectis-control-size-calendar-event-edge) solid\n var(--calendar-event-edge);\n /* TRAP — the cap is measured against the all-day LANE, the shortest thing this same\n class ever renders, and against nothing else. A browser scales down any radius it\n cannot fit, so a chip already paints half a lane under a large\n --vectis-radius-interactive; min() applies that same reduction to a timed block,\n whose height is the event's DURATION. Written bare, a pill theme paints half of a\n three-hour block instead: 96px corners on one card and 12px on the chip beside it.\n Never take the unit from --vectis-control-size-calendar-hour, for the reason the\n `container-type` comment above already gives — the radius has nothing to do with how\n tall an hour is, and anyone retuning that token would move it by accident. */\n border-radius: min(\n var(--vectis-radius-interactive),\n calc(var(--vectis-control-size-calendar-allday-lane) / 2)\n );\n background: var(--calendar-event-face);\n color: var(--calendar-event-ink);\n font-family: var(--vectis-text-family);\n text-align: start;\n cursor: pointer;\n transition:\n box-shadow var(--vectis-duration-fast) var(--vectis-ease-default),\n filter var(--vectis-duration-fast) var(--vectis-ease-default);\n }\n\n /*\n * A colour the consumer chose is an arbitrary value, so the card is built so that NOTHING\n * is ever written on top of it: it paints the edge, and the face is a faint wash of it\n * over the page's own surface — which also makes it follow the theme with no second\n * setting. The text stays the page's text colour, whose contrast against that surface is\n * already guaranteed. This is the deliberate difference from VChip, where a fully\n * coloured chip leaves the check to whoever chose the colour.\n */\n .v-calendar-event[data-custom] {\n --calendar-event-edge: var(--calendar-event-color);\n --calendar-event-face: color-mix(\n in oklab,\n var(--calendar-event-color) 14%,\n var(--vectis-color-surface)\n );\n --calendar-event-ink: var(--vectis-color-text);\n }\n\n .v-calendar-event-body {\n display: flex;\n flex: 1;\n flex-direction: column;\n gap: 1px;\n /* Without this a flex item refuses to shrink past its content, and a card too short for\n its own text would push its title out of the clip instead of cropping it. */\n min-block-size: 0;\n min-inline-size: 0;\n overflow: hidden;\n padding: var(--vectis-space-1) var(--vectis-space-2);\n }\n\n /*\n * A card too short for two lines puts them on ONE: the title first, the time after it, and\n * the description dropped — which is the only way a quarter of an hour shows anything at\n * all. Three rem is where a title line, a time line, the gap and the padding stop fitting;\n * below it there is room for exactly one line.\n *\n * The TITLE keeps that line. It is what identifies the event, where the times are already in\n * the card's accessible name and readable from its height. Both items shrink, but the time's\n * shrink factor is large enough that it gives up its whole width, down to an ellipsis and then\n * to nothing, before the title loses a character: flex shrinking is weighted by factor times\n * basis, so a factor a thousand times the title's leaves the title a rounding error.\n *\n * The threshold is a literal because a container query takes no custom properties — the\n * same constraint VPagination's steps are written under.\n */\n @container (max-block-size: 3rem) {\n .v-calendar-event[data-layout='block'] .v-calendar-event-body {\n flex-direction: row;\n align-items: center;\n gap: var(--vectis-space-1);\n padding-block: 0;\n }\n\n .v-calendar-event[data-layout='block'] .v-calendar-event-title {\n flex: 0 1 auto;\n min-inline-size: 0;\n }\n\n .v-calendar-event[data-layout='block'] .v-calendar-event-time {\n flex: 0 1000 auto;\n min-inline-size: 0;\n }\n\n /* There is no room for a third thing, and the title is what identifies the event. */\n .v-calendar-event[data-layout='block'] .v-calendar-event-description {\n display: none;\n }\n }\n\n /*\n * The shortest card there is: one slot, which at the default hour height is sixteen pixels,\n * leaving fourteen once the border is taken. A line of the title at its normal leading is\n * eighteen — so the leading is what gives, down to the glyphs themselves. Nothing smaller\n * is available: twelve pixels is already the smallest type role the library has.\n *\n * This tier exists because a card may no longer grow past its own length: it is the price\n * of a quarter of an hour that stays inside its slot, and it is paid in leading rather than\n * in a card that covers the next one.\n */\n @container (max-block-size: 1.5rem) {\n .v-calendar-event[data-layout='block'] .v-calendar-event-title,\n .v-calendar-event[data-layout='block'] .v-calendar-event-time {\n line-height: 1;\n }\n\n /* Half the strip, or half of a sixteen-pixel card would resize rather than move it. */\n .v-calendar-event[data-layout='block'] .v-calendar-event-handle {\n block-size: calc(var(--vectis-control-size-calendar-handle) / 2);\n }\n }\n\n .v-calendar-event:hover {\n filter: brightness(0.97);\n }\n\n /*\n * A card being moved is lifted off the grid and made slightly transparent, so the hours\n * underneath stay readable while it travels — a solid card would hide the very rules the\n * reader is aiming at. `pointer-events: none` matters as much: the pointer is captured by\n * the grid, and a card under the cursor would otherwise take the hover of every cell it\n * passed over.\n */\n .v-calendar-event[data-dragging] {\n opacity: 0.75;\n box-shadow: var(--vectis-shadow-md);\n pointer-events: none;\n z-index: 3;\n }\n\n /*\n * A card whose drop will not be taken: the pointer has left the calendar, and letting go here\n * puts the event back where the echo shows it started.\n *\n * THREE channels, because one is never enough. The colour is the danger role, reached through\n * the same three local variables `[data-custom]` swaps — which is also what repaints a card the\n * consumer coloured, that rule sitting higher up this sheet. The LIFT is taken away, so a card\n * that will not land visibly stops being carried: the one cue that costs no colour at all. And\n * the border goes DOTTED, the only one of the three surviving Windows forced-colors, where the\n * face is forced to Canvas and every card would otherwise look identical — dotted rather than\n * dashed because dashed is already the echo's language, and a refused drop must not read as a\n * memory of one.\n *\n * `opacity: 0.75` is deliberately left in place: it is what keeps the hours under the card\n * readable, and the reader is still aiming with it.\n *\n * TRAP — this rule must stay BELOW `[data-dragging]`. Both are (0,2,0) and a refused card is\n * always also a dragged one, so the later rule is the whole of the arbitration. That is\n * legitimate here and only here: these two live in the SAME sheet, where the internal order is\n * ours to decide — between two component sheets it would be the consumer's bundler deciding.\n */\n .v-calendar-event[data-rejected] {\n --calendar-event-face: var(--vectis-color-danger-surface);\n --calendar-event-edge: var(--vectis-color-danger-border);\n --calendar-event-ink: var(--vectis-color-danger-text);\n\n border-style: dotted;\n box-shadow: none;\n }\n\n /*\n * The echo left where a dragged event started, so the reader can see what they are moving\n * it FROM — without it a long drag ends with no idea what has just been given up.\n *\n * Faded rather than outlined, and dashed rather than solid, so that it reads as a memory\n * and not as a second event: at a glance the only card that looks real is the one under the\n * pointer. It sits UNDER everything (`z-index: 0`), since it is the one thing on the grid\n * that nothing should ever be hidden behind.\n *\n * `inert` in the template is what keeps it out of the accessibility tree and out of reach\n * of the pointer, in one attribute — a duplicate announced a second time would be noise,\n * and a focusable copy inside a hidden subtree is an axe violation of its own.\n */\n .v-calendar-event[data-ghost] {\n opacity: 0.4;\n border-style: dashed;\n z-index: 0;\n }\n\n /* Held by the keyboard: the same lift, but marked with the focus ring's own colour, since\n there is no pointer to show where it is going. */\n .v-calendar-event[data-grabbed] {\n outline: var(--vectis-focus-ring-width) solid var(--vectis-focus-ring-color);\n outline-offset: var(--vectis-focus-ring-offset);\n box-shadow: var(--vectis-shadow-md);\n z-index: 3;\n }\n\n .v-calendar-event-handle {\n position: absolute;\n inset-block-end: 0;\n inset-inline: 0;\n block-size: var(--vectis-control-size-calendar-handle);\n /* Dragging here IS how the end is set, so it must do nothing else: no scrolling under a\n finger, and no selecting the text it sits over. */\n touch-action: none;\n cursor: ns-resize;\n }\n\n /* The grip appears on hover and while the card is being resized, never permanently: a\n short card is mostly handle, and a line across every event all the time reads as a\n border nobody asked for. */\n .v-calendar-event-handle::after {\n content: '';\n position: absolute;\n inset-block-end: var(--vectis-control-size-calendar-grip-thickness);\n inset-inline-start: 50%;\n inline-size: var(--vectis-control-size-calendar-grip);\n block-size: var(--vectis-control-size-calendar-grip-thickness);\n translate: -50% 0;\n border-radius: var(--vectis-radius-pill);\n background: var(--calendar-event-ink);\n opacity: 0;\n transition: opacity var(--vectis-duration-fast) var(--vectis-ease-default);\n }\n\n .v-calendar-event:hover .v-calendar-event-handle::after,\n .v-calendar-event[data-dragging] .v-calendar-event-handle::after {\n opacity: 0.6;\n }\n\n .v-calendar-event:focus-visible {\n outline: var(--vectis-focus-ring-width) solid var(--vectis-focus-ring-color);\n outline-offset: calc(-1 * var(--vectis-focus-ring-width));\n }\n\n /* An event running past what is on show loses the corner on that side, so the card reads\n as cut off rather than as merely small. */\n .v-calendar-event[data-continues-before] {\n border-start-start-radius: 0;\n border-start-end-radius: 0;\n border-block-start-style: dashed;\n }\n\n .v-calendar-event[data-continues-after] {\n border-end-start-radius: 0;\n border-end-end-radius: 0;\n border-block-end-style: dashed;\n }\n\n /*\n * A chip fills the box it was put in — a lane of the all-day band, whose grid row is\n * already the right height — unless the consumer of this class names a height instead.\n *\n * TRAP — that indirection is not a nicety, it is the only correct shape. This selector is\n * (0,2,0) and `.v-calendar-month-chip`, which needs a different height, is (0,1,0) in\n * ANOTHER SHEET: matching specificity would hand the winner to whichever order the\n * consumer's bundler happens to emit, and beating it would need a three-class compound.\n * Routing through a property this rule already reads is the library's documented way out,\n * the one `.v-data-table-title` takes on `--typography-color`.\n */\n .v-calendar-event[data-layout='chip'] {\n block-size: var(--calendar-chip-height, 100%);\n }\n\n .v-calendar-event[data-layout='chip'] .v-calendar-event-body {\n flex-direction: row;\n align-items: center;\n gap: var(--vectis-space-1);\n padding-block: 0;\n }\n\n .v-calendar-event-title {\n overflow: hidden;\n font-size: var(--vectis-text-body-sm-size);\n font-weight: var(--vectis-font-weight-medium);\n line-height: var(--vectis-text-body-sm-leading);\n text-overflow: ellipsis;\n white-space: nowrap;\n }\n\n .v-calendar-event-time {\n overflow: hidden;\n font-size: var(--vectis-text-caption-size);\n line-height: var(--vectis-text-caption-leading);\n text-overflow: ellipsis;\n white-space: nowrap;\n /* The times are secondary to the title, but the card's colour is already doing the\n quiet work — a muted token here would fight it, so the same ink at less weight. */\n opacity: 0.85;\n }\n\n .v-calendar-event-description {\n overflow: hidden;\n /* The card's height is the event's length, so a description shows only where there is\n genuinely room for it: it takes whatever is left and disappears when that is nothing. */\n min-block-size: 0;\n color: inherit;\n text-overflow: ellipsis;\n opacity: 0.85;\n }\n\n @media (prefers-reduced-motion: reduce) {\n .v-calendar-event,\n .v-calendar-event-handle::after {\n transition: none;\n }\n }\n\n /* The resize grip is a background, which forced colors would flatten to Canvas. */\n @media (forced-colors: active) {\n .v-calendar-event-handle::after {\n forced-color-adjust: none;\n background: CanvasText;\n }\n }\n}\n</style>\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAwEA,IAAM,IAAQ,GAmBR,IAAI,EAAY,GAShB,IAAM,QAAe,EAAM,EAAM,WAAW,EAAM,MAAM,EAAE,CAAC,GAE3D,IAAQ,QACZ,EAAM,MAAM,QACR,EAAE,0BAA0B,EAAM,MAAM,MAAM,IAC9C,EAAE,+BAA+B,OAAO,EAAI,KAAK,EAAE,CACzD,GAOM,IAAiB,QACrB,EAAM,WAAW,GAAG,EAAM,MAAM,MAAM,IAAI,EAAM,aAAa,EAAM,MAAM,KAC3E;yBAIE,EAkES,UAAA;GAjEP,MAAK;GACL,OAAM;GACL,iBAAe,OAAO,EAAA,MAAM,EAAE;GAC9B,eAAa,EAAA;GACb,eAAa,EAAA,MAAM,QAAK,KAAQ,KAAA;GAChC,yBAAuB,EAAA,kBAAe,KAAQ,KAAA;GAC9C,wBAAsB,EAAA,iBAAc,KAAQ,KAAA;GAC5C,iBAAe,EAAA,WAAQ,KAAQ,KAAA;GAC/B,iBAAe,EAAA,WAAQ,KAAQ,KAAA;GAC/B,gBAAc,EAAA,UAAO,KAAQ,KAAA;GAC7B,cAAY,EAAA,YAAY,KAAA,IAAiB,KAAA,IAAR;GACjC,OAAK,EAAE,EAAA,KAAK;GACZ,cAAY,EAAA;GACZ,wBAAsB,EAAA,CAAA,CAAC,CAAC,SAAS;GACjC,oBAAkB,EAAA;GAClB,UAAU,EAAA,YAAY,KAAA;GACtB,OAAO,EAAA,YAAY,KAAA,KAAmB,KAAA;MASvC,EAuBO,QAvBP,GAuBO,CAtBL,EAqBO,EAAA,QAAA,WAAA;GApBJ,OAAO,EAAA;GACP,QAAQ,EAAA;GACR,UAAW,EAAA;GACX,iBAAkB,EAAA;GAClB,gBAAiB,EAAA;GACjB,UAAU,EAAA;GACV,SAAS,EAAA;WAcL;GAZL,EAA6D,QAA7D,GAA6D,EAArB,EAAA,MAAM,KAAK,GAAA,CAAA;GACvC,EAAA,WAAM,WAAgB,EAAA,YAAA,EAAA,GAAlC,EAEO,QAFP,GAEO,EADF,EAAA,QAAQ,GAAA,CAAA,KAAA,EAAA,IAAA,EAAA;GAGL,EAAA,WAAM,WAAgB,EAAA,MAAM,eAAA,EAAA,GADpC,EAOc,GAAA;;IALZ,IAAG;IACH,SAAQ;IACR,OAAM;;qBAEiB,CAAA,EAAA,EAApB,EAAA,MAAM,WAAW,GAAA,CAAA,CAAA,CAAA;;;QAelB,EAAA,aAAa,EAAA,WAAM,WAAA,EAAA,GAD3B,EAKE,QALF,CAKE,KAAA,EAAA,IAAA,EAAA,CAAA,GAAA,IAAA,CAAA"}
1
+ {"version":3,"file":"VCalendarEvent.vue_vue_type_script_setup_true_lang.js","names":[],"sources":["../../../src/components/VCalendar/VCalendarEvent.vue"],"sourcesContent":["<script setup lang=\"ts\" generic=\"E extends CalendarEvent\">\n// @a11y @core\n/**\n * Share the native event button across calendar views so accessible naming and event-slot\n * rendering remain consistent.\n */\nimport { computed } from 'vue'\n\nimport VTypography from '../VTypography/VTypography.vue'\n\nimport { useMessages } from '../../i18n/state'\n\nimport { hueOf } from './color'\nimport type {\n CalendarEvent,\n CalendarEventId,\n CalendarEventLayout,\n CalendarEventSlotProps,\n} from './types'\n\nexport interface CalendarEventProps<T> {\n /** The event this card stands for. */\n event: T\n /**\n * Which shape to take: a block, which fills the box the calendar gives it and can show a\n * second line, or a chip, which is one line high and sits in a row of others.\n */\n layout?: CalendarEventLayout\n /** The event's times, already written out for the reader by the calendar. */\n timeText?: string\n /** Whether the event carries on past the start or the end of what is on show. */\n continuesBefore?: boolean\n continuesAfter?: boolean\n /** Shows the strip along the bottom edge that the event's end is dragged by. */\n resizable?: boolean\n /** Whether the card is being dragged with a pointer right now. */\n dragging?: boolean\n /**\n * Whether letting go now would write nothing: the pointer has left the calendar, and the\n * event is about to return to where the faded echo shows it started.\n */\n rejected?: boolean\n /** Whether the card has been taken hold of with the keyboard. */\n grabbed?: boolean\n /** How the card says it can be moved, read from a node the calendar shares between them. */\n hintId?: string\n /**\n * Marks this card as the faded echo left behind where a dragged event STARTED, and names the\n * event it echoes.\n */\n ghostOf?: CalendarEventId\n /** Whether the whole calendar is disabled, which makes the card a real disabled button. */\n disabled?: boolean\n}\n\nconst props = withDefaults(defineProps<CalendarEventProps<E>>(), {\n layout: 'block',\n timeText: '',\n continuesBefore: false,\n continuesAfter: false,\n resizable: false,\n dragging: false,\n rejected: false,\n grabbed: false,\n hintId: undefined,\n ghostOf: undefined,\n disabled: false,\n})\n\ndefineSlots<{\n /** The whole content of the card, replacing the title and the times. */\n default?(props: CalendarEventSlotProps<E>): unknown\n}>()\n\nconst m = useMessages()\n\n/*\n * A colour given by the consumer is used as it stands; otherwise a hue is derived from the\n * event's id and the token layer supplies the lightness and the chroma that go with it. The two\n * are kept apart by an attribute rather than by a fallback chain, because the custom case needs\n * a DIFFERENT recipe and not merely a different value; see the stylesheet below.\n */\nconst hue = computed(() => hueOf(props.ghostOf ?? props.event.id))\n\nconst style = computed(() =>\n props.event.color\n ? { '--calendar-event-color': props.event.color }\n : { '--vectis-calendar-event-hue': String(hue.value) },\n)\n\n/** What a screen reader hears: the title, then when it happens. */\nconst accessibleName = computed(() =>\n props.timeText ? `${props.event.title}, ${props.timeText}` : props.event.title,\n)\n</script>\n\n<template>\n <button\n type=\"button\"\n class=\"v-calendar-event\"\n :data-event-id=\"String(event.id)\"\n :data-layout=\"layout\"\n :data-custom=\"event.color ? '' : undefined\"\n :data-continues-before=\"continuesBefore ? '' : undefined\"\n :data-continues-after=\"continuesAfter ? '' : undefined\"\n :data-dragging=\"dragging ? '' : undefined\"\n :data-rejected=\"rejected ? '' : undefined\"\n :data-grabbed=\"grabbed ? '' : undefined\"\n :data-ghost=\"ghostOf !== undefined ? '' : undefined\"\n :style=\"style\"\n :aria-label=\"accessibleName\"\n :aria-roledescription=\"m.calendar.eventRoleDescription\"\n :aria-describedby=\"hintId\"\n :disabled=\"disabled || undefined\"\n :inert=\"ghostOf !== undefined ? true : undefined\"\n >\n <!--\n The content sits in a box of its own because the CARD is the container the stylesheet\n queries, and an element cannot be styled by its own container query. The layout that has\n to change when a card gets short; a column of two lines becoming one row; must therefore\n live on a descendant.\n -->\n <span class=\"v-calendar-event-body\">\n <slot\n :event=\"event\"\n :layout=\"layout\"\n :time-text=\"timeText\"\n :continues-before=\"continuesBefore\"\n :continues-after=\"continuesAfter\"\n :dragging=\"dragging\"\n :grabbed=\"grabbed\"\n >\n <span class=\"v-calendar-event-title\">{{ event.title }}</span>\n <span v-if=\"layout === 'block' && timeText\" class=\"v-calendar-event-time\">\n {{ timeText }}\n </span>\n <VTypography\n v-if=\"layout === 'block' && event.description\"\n as=\"span\"\n variant=\"caption\"\n class=\"v-calendar-event-description\"\n >\n {{ event.description }}\n </VTypography>\n </slot>\n </span>\n\n <!--\n It is a pointer affordance and nothing else, and its keyboard equivalent lives on the card\n itself as Shift with the arrow keys; which is why hiding it costs a reader nothing.\n -->\n <span\n v-if=\"resizable && layout === 'block'\"\n class=\"v-calendar-event-handle\"\n data-calendar-handle\n aria-hidden=\"true\"\n />\n </button>\n</template>\n\n<style>\n@layer vectis.components {\n .v-calendar-event {\n /*\n * The three colours of a card, named by what they paint rather than by where they come\n * from; which lets the custom block below swap the source of all three without touching a\n * single rule that consumes them.\n */\n /*\n * The hue is turned here, on the card, and never in the tokens. Relative colour syntax\n * keeps the token's lightness and chroma, which are what hold the title's contrast, and\n * takes the hue the card sets inline, or the token's own (`h`) when none is set.\n */\n --calendar-event-face: oklch(\n from var(--vectis-color-event-surface) l c var(--vectis-calendar-event-hue, h)\n );\n --calendar-event-edge: oklch(\n from var(--vectis-color-event-border) l c var(--vectis-calendar-event-hue, h)\n );\n --calendar-event-ink: oklch(\n from var(--vectis-color-event-text) l c var(--vectis-calendar-event-hue, h)\n );\n\n position: relative;\n display: flex;\n overflow: hidden;\n /*\n * It is safe because a card's two dimensions are both set outright by `.v-calendar-block`;\n * size containment therefore removes an influence nothing was exercising. Asking in minutes\n * instead would have meant calibrating against `--vectis-control-size-calendar-hour`, and\n * being silently wrong for anyone who overrode it.\n */\n container-type: size;\n border: 1px solid var(--calendar-event-edge);\n /* The leading edge is what carries the colour at a glance, so it is drawn thicker. It\n is a border and not a background stripe: under Windows forced-colors a background is\n forced to Canvas and vanishes, where a border keeps a colour of its own. */\n border-inline-start: var(--vectis-control-size-calendar-event-edge) solid\n var(--calendar-event-edge);\n /*\n * A browser scales down any radius it cannot fit, so a chip already paints half a lane\n * under a large --vectis-radius-interactive; min() applies that same reduction to a timed\n * block, whose height is the event's DURATION. Written bare, a pill theme paints half of a\n * three-hour block instead: 96px corners on one card and 12px on the chip beside it.\n */\n border-radius: min(\n var(--vectis-radius-interactive),\n calc(var(--vectis-control-size-calendar-allday-lane) / 2)\n );\n background: var(--calendar-event-face);\n color: var(--calendar-event-ink);\n font-family: var(--vectis-text-family);\n text-align: start;\n cursor: pointer;\n transition:\n box-shadow var(--vectis-duration-fast) var(--vectis-ease-default),\n filter var(--vectis-duration-fast) var(--vectis-ease-default);\n }\n\n /*\n * A colour the consumer chose is an arbitrary value, so the card is built so that NOTHING is\n * ever written on top of it: it paints the edge, and the face is a faint wash of it over the\n * page's own surface; which also makes it follow the theme with no second setting. The text\n * stays the page's text colour, whose contrast against that surface is already guaranteed.\n */\n .v-calendar-event[data-custom] {\n --calendar-event-edge: var(--calendar-event-color);\n --calendar-event-face: color-mix(\n in oklab,\n var(--calendar-event-color) 14%,\n var(--vectis-color-surface)\n );\n --calendar-event-ink: var(--vectis-color-text);\n }\n\n .v-calendar-event-body {\n display: flex;\n flex: 1;\n flex-direction: column;\n gap: 1px;\n /* Without this a flex item refuses to shrink past its content, and a card too short for\n its own text would push its title out of the clip instead of cropping it. */\n min-block-size: 0;\n min-inline-size: 0;\n overflow: hidden;\n padding: var(--vectis-space-1) var(--vectis-space-2);\n }\n\n /*\n * Give the time a larger weighted flex-shrink so it disappears before truncating the event\n * title.\n */\n @container (max-block-size: 3rem) {\n .v-calendar-event[data-layout='block'] .v-calendar-event-body {\n flex-direction: row;\n align-items: center;\n gap: var(--vectis-space-1);\n padding-block: 0;\n }\n\n .v-calendar-event[data-layout='block'] .v-calendar-event-title {\n flex: 0 1 auto;\n min-inline-size: 0;\n }\n\n .v-calendar-event[data-layout='block'] .v-calendar-event-time {\n flex: 0 1000 auto;\n min-inline-size: 0;\n }\n\n .v-calendar-event[data-layout='block'] .v-calendar-event-description {\n display: none;\n }\n }\n\n /*\n * The shortest card there is: one slot, which at the default hour height is sixteen pixels,\n * leaving fourteen once the border is taken. A line of the title at its normal leading is\n * eighteen; so the leading is what gives, down to the glyphs themselves.\n */\n @container (max-block-size: 1.5rem) {\n .v-calendar-event[data-layout='block'] .v-calendar-event-title,\n .v-calendar-event[data-layout='block'] .v-calendar-event-time {\n line-height: 1;\n }\n\n .v-calendar-event[data-layout='block'] .v-calendar-event-handle {\n block-size: calc(var(--vectis-control-size-calendar-handle) / 2);\n }\n }\n\n .v-calendar-event:hover {\n filter: brightness(0.97);\n }\n\n /*\n * `pointer-events: none` matters as much: the pointer is captured by the grid, and a card\n * under the cursor would otherwise take the hover of every cell it passed over.\n */\n .v-calendar-event[data-dragging] {\n opacity: 0.75;\n box-shadow: var(--vectis-shadow-md);\n pointer-events: none;\n z-index: 3;\n }\n\n /*\n * This rule must stay BELOW `[data-dragging]`. Both are (0,2,0) and a refused card is always\n * also a dragged one, so the later rule is the whole of the arbitration.\n */\n .v-calendar-event[data-rejected] {\n --calendar-event-face: var(--vectis-color-danger-surface);\n --calendar-event-edge: var(--vectis-color-danger-border);\n --calendar-event-ink: var(--vectis-color-danger-text);\n\n border-style: dotted;\n box-shadow: none;\n }\n\n /*\n * The echo left where a dragged event started, so the reader can see what they are moving it\n * FROM; without it a long drag ends with no idea what has just been given up. Faded rather\n * than outlined, and dashed rather than solid, so that it reads as a memory and not as a\n * second event: at a glance the only card that looks real is the one under the pointer.\n */\n .v-calendar-event[data-ghost] {\n opacity: 0.4;\n border-style: dashed;\n z-index: 0;\n }\n\n /* Held by the keyboard: the same lift, but marked with the focus ring's own colour, since\n there is no pointer to show where it is going. */\n .v-calendar-event[data-grabbed] {\n outline: var(--vectis-focus-ring-width) solid var(--vectis-focus-ring-color);\n outline-offset: var(--vectis-focus-ring-offset);\n box-shadow: var(--vectis-shadow-md);\n z-index: 3;\n }\n\n .v-calendar-event-handle {\n position: absolute;\n inset-block-end: 0;\n inset-inline: 0;\n block-size: var(--vectis-control-size-calendar-handle);\n /* Dragging here IS how the end is set, so it must do nothing else: no scrolling under a\n finger, and no selecting the text it sits over. */\n touch-action: none;\n cursor: ns-resize;\n }\n\n /* The grip appears on hover and while the card is being resized, never permanently: a\n short card is mostly handle, and a line across every event all the time reads as a\n border nobody asked for. */\n .v-calendar-event-handle::after {\n content: '';\n position: absolute;\n inset-block-end: var(--vectis-control-size-calendar-grip-thickness);\n inset-inline-start: 50%;\n inline-size: var(--vectis-control-size-calendar-grip);\n block-size: var(--vectis-control-size-calendar-grip-thickness);\n translate: -50% 0;\n border-radius: var(--vectis-radius-pill);\n background: var(--calendar-event-ink);\n opacity: 0;\n transition: opacity var(--vectis-duration-fast) var(--vectis-ease-default);\n }\n\n .v-calendar-event:hover .v-calendar-event-handle::after,\n .v-calendar-event[data-dragging] .v-calendar-event-handle::after {\n opacity: 0.6;\n }\n\n .v-calendar-event:focus-visible {\n outline: var(--vectis-focus-ring-width) solid var(--vectis-focus-ring-color);\n outline-offset: calc(-1 * var(--vectis-focus-ring-width));\n }\n\n /* An event running past what is on show loses the corner on that side, so the card reads\n as cut off rather than as merely small. */\n .v-calendar-event[data-continues-before] {\n border-start-start-radius: 0;\n border-start-end-radius: 0;\n border-block-start-style: dashed;\n }\n\n .v-calendar-event[data-continues-after] {\n border-end-start-radius: 0;\n border-end-end-radius: 0;\n border-block-end-style: dashed;\n }\n\n /*\n * That indirection is not a nicety, it is the only correct shape. This selector is (0,2,0)\n * and `.v-calendar-month-chip`, which needs a different height, is (0,1,0) in ANOTHER SHEET:\n * matching specificity would hand the winner to whichever order the consumer's bundler\n * happens to emit, and beating it would need a three-class compound.\n */\n .v-calendar-event[data-layout='chip'] {\n block-size: var(--calendar-chip-height, 100%);\n }\n\n .v-calendar-event[data-layout='chip'] .v-calendar-event-body {\n flex-direction: row;\n align-items: center;\n gap: var(--vectis-space-1);\n padding-block: 0;\n }\n\n .v-calendar-event-title {\n overflow: hidden;\n font-size: var(--vectis-text-body-sm-size);\n font-weight: var(--vectis-font-weight-medium);\n line-height: var(--vectis-text-body-sm-leading);\n text-overflow: ellipsis;\n white-space: nowrap;\n }\n\n .v-calendar-event-time {\n overflow: hidden;\n font-size: var(--vectis-text-caption-size);\n line-height: var(--vectis-text-caption-leading);\n text-overflow: ellipsis;\n white-space: nowrap;\n /*\n * The times are secondary to the title, but the card's colour is already doing the quiet\n * work; a muted token here would fight it, so the same ink at less weight.\n */\n opacity: 0.85;\n }\n\n .v-calendar-event-description {\n overflow: hidden;\n /* The card's height is the event's length, so a description shows only where there is\n genuinely room for it: it takes whatever is left and disappears when that is nothing. */\n min-block-size: 0;\n color: inherit;\n text-overflow: ellipsis;\n opacity: 0.85;\n }\n\n @media (prefers-reduced-motion: reduce) {\n .v-calendar-event,\n .v-calendar-event-handle::after {\n transition: none;\n }\n }\n\n @media (forced-colors: active) {\n .v-calendar-event-handle::after {\n forced-color-adjust: none;\n background: CanvasText;\n }\n }\n}\n</style>\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAuDA,IAAM,IAAQ,GAmBR,IAAI,EAAY,GAQhB,IAAM,QAAe,EAAM,EAAM,WAAW,EAAM,MAAM,EAAE,CAAC,GAE3D,IAAQ,QACZ,EAAM,MAAM,QACR,EAAE,0BAA0B,EAAM,MAAM,MAAM,IAC9C,EAAE,+BAA+B,OAAO,EAAI,KAAK,EAAE,CACzD,GAGM,IAAiB,QACrB,EAAM,WAAW,GAAG,EAAM,MAAM,MAAM,IAAI,EAAM,aAAa,EAAM,MAAM,KAC3E;yBAIE,EA4DS,UAAA;GA3DP,MAAK;GACL,OAAM;GACL,iBAAe,OAAO,EAAA,MAAM,EAAE;GAC9B,eAAa,EAAA;GACb,eAAa,EAAA,MAAM,QAAK,KAAQ,KAAA;GAChC,yBAAuB,EAAA,kBAAe,KAAQ,KAAA;GAC9C,wBAAsB,EAAA,iBAAc,KAAQ,KAAA;GAC5C,iBAAe,EAAA,WAAQ,KAAQ,KAAA;GAC/B,iBAAe,EAAA,WAAQ,KAAQ,KAAA;GAC/B,gBAAc,EAAA,UAAO,KAAQ,KAAA;GAC7B,cAAY,EAAA,YAAY,KAAA,IAAiB,KAAA,IAAR;GACjC,OAAK,EAAE,EAAA,KAAK;GACZ,cAAY,EAAA;GACZ,wBAAsB,EAAA,CAAA,CAAC,CAAC,SAAS;GACjC,oBAAkB,EAAA;GAClB,UAAU,EAAA,YAAY,KAAA;GACtB,OAAO,EAAA,YAAY,KAAA,KAAmB,KAAA;MAQvC,EAuBO,QAvBP,GAuBO,CAtBL,EAqBO,EAAA,QAAA,WAAA;GApBJ,OAAO,EAAA;GACP,QAAQ,EAAA;GACR,UAAW,EAAA;GACX,iBAAkB,EAAA;GAClB,gBAAiB,EAAA;GACjB,UAAU,EAAA;GACV,SAAS,EAAA;WAcL;GAZL,EAA6D,QAA7D,GAA6D,EAArB,EAAA,MAAM,KAAK,GAAA,CAAA;GACvC,EAAA,WAAM,WAAgB,EAAA,YAAA,EAAA,GAAlC,EAEO,QAFP,GAEO,EADF,EAAA,QAAQ,GAAA,CAAA,KAAA,EAAA,IAAA,EAAA;GAGL,EAAA,WAAM,WAAgB,EAAA,MAAM,eAAA,EAAA,GADpC,EAOc,GAAA;;IALZ,IAAG;IACH,SAAQ;IACR,OAAM;;qBAEiB,CAAA,EAAA,EAApB,EAAA,MAAM,WAAW,GAAA,CAAA,CAAA,CAAA;;;QAUlB,EAAA,aAAa,EAAA,WAAM,WAAA,EAAA,GAD3B,EAKE,QALF,CAKE,KAAA,EAAA,IAAA,EAAA,CAAA,GAAA,IAAA,CAAA"}
@@ -1 +1 @@
1
- {"version":3,"file":"VCalendarMonth.js","names":[],"sources":["../../../src/components/VCalendar/VCalendarMonth.vue"],"sourcesContent":["<script setup lang=\"ts\" generic=\"E extends CalendarEvent\">\n// @a11y @keyboard @core\n/**\n * The month view: the weeks stacked one under another, each day a square holding as many of\n * its events as will fit.\n *\n * It is internal to VCalendar and has no story of its own — its documentation lives with\n * the component that renders it. Like the time grid it computes nothing about dates: it is\n * handed the weeks already cut and filtered, and turns them into boxes.\n *\n * A day here is not a column of hours but a SUMMARY, so the events are drawn as chips in\n * the order the day would be read out — the all-day ones first, then the rest by when they\n * start — and a day with more than it can show says how many are left rather than silently\n * dropping them.\n *\n * The drag and the keyboard grab are `gesture.ts`'s. What stays here is what a square means:\n * the point under the pointer turned into a day, and a vertical step read as a whole week.\n */\nimport { computed, ref, useId } from 'vue'\n\nimport { formatDateDisplay } from '../../utils/date'\nimport { clamp } from '../../utils/number'\nimport { formatTimeDisplay } from '../../utils/time'\n\nimport { useMessages } from '../../i18n/state'\n\nimport VCalendarEvent from './VCalendarEvent.vue'\nimport { gridGeometryOf, useCalendarGesture, type GestureBase, type GrabStep } from './gesture'\nimport { calendarIntent } from './keyboard'\nimport {\n eventsByDay,\n isAllDayEvent,\n moveEventToDay,\n pointToMonthCell,\n sameTimes,\n timesOf,\n type MonthCell,\n} from './layout'\nimport type {\n ActivatedCell,\n CalendarEvent,\n CalendarEventId,\n CalendarEventSlotProps,\n CalendarEventTimes,\n CalendarFormat,\n} from './types'\n\nexport interface CalendarMonthProps<T> {\n /** The weeks, already padded to a fixed height and filtered to the visible weekdays. */\n weeks: MonthCell[][]\n events: T[]\n locale: string\n format: CalendarFormat\n today: string | null\n /** How many events a day shows before it starts counting the rest. */\n monthEventLimit: number\n /** Whether events can be moved from one day to another. */\n editable: boolean\n /** Whether the whole calendar is frozen, which also takes its cards out of the tab order. */\n disabled: boolean\n /** The node telling a reader how a chip can be moved, shared by every one of them. */\n hintId: string\n /** How long a drag rests against an edge before the month turns. Zero turns paging off. */\n edgeStepDelay: number\n label: string\n}\n\nconst props = defineProps<CalendarMonthProps<E>>()\n\nconst emit = defineEmits<{\n /** A day was asked to be opened on its own. */\n 'day-activate': [iso: string]\n /** An empty part of a day was activated. A month has no hours, so the time is left to the calendar. */\n 'cell-activate': [cell: ActivatedCell]\n 'event-activate': [event: E]\n /** An event was dropped on another day. A month has no hours, so it is only ever a move. */\n 'event-drop': [id: CalendarEventId, times: CalendarEventTimes, kind: 'move']\n /** Something happened that a reader who cannot see the grid needs told. */\n announce: [message: string]\n step: [delta: -1 | 1]\n}>()\n\n/** Which day holds the tab stop. Only the date matters here; the hour is the grid's affair. */\nconst focused = defineModel<string>('focused', { required: true })\n\ndefineSlots<{\n event?(props: CalendarEventSlotProps<E>): unknown\n}>()\n\nconst m = useMessages()\nconst uid = useId()\n\nconst cellId = (iso: string) => `${uid}-m-${iso}`\n\n/** The flattened list of days: what the arrows travel along, and what the events are filed by. */\nconst flat = computed(() => props.weeks.flat().map((cell) => cell.iso))\nconst columnCount = computed(() => props.weeks[0]?.length ?? 1)\n\n/** The column headings, taken from the first week so they always match the columns drawn. */\nconst weekdayNames = computed(() =>\n (props.weeks[0] ?? []).map((cell) =>\n formatDateDisplay(cell.iso, props.locale, { weekday: 'short' }),\n ),\n)\n\n/*\n * The two labels every square carries, worked out once per cell rather than once per USE.\n *\n * `longDay` is asked for twice in the template — the square's own `aria-label`, then the\n * name of the button that opens the day — so the 42 cells cost 126 `Intl` formats a render,\n * and a drag re-renders the whole grid each time it carries a chip onto another day. The map\n * depends on the weeks and the locale alone, so it survives every frame of a drag.\n */\nconst dayLabels = computed(() => {\n const map = new Map<string, { number: string; long: string }>()\n for (const iso of flat.value) {\n map.set(iso, {\n number: formatDateDisplay(iso, props.locale, { day: 'numeric' }),\n long: formatDateDisplay(iso, props.locale, {\n weekday: 'long',\n day: 'numeric',\n month: 'long',\n }),\n })\n }\n return map\n})\n\nconst dayNumber = (iso: string) => dayLabels.value.get(iso)?.number ?? ''\n\n/*\n * A day outside the grid can reach this — the announcement after a move names the day the\n * event landed on, which may be the next month — so it falls back to formatting rather than\n * assuming the map holds it.\n */\nconst longDay = (iso: string) =>\n dayLabels.value.get(iso)?.long ??\n formatDateDisplay(iso, props.locale, { weekday: 'long', day: 'numeric', month: 'long' })\n\n/**\n * A chip being carried from one day to another, by pointer or by keyboard.\n *\n * A month has no hours, so there is one kind and no resize: only which day an event starts\n * on moves, and its length in days and its times come along untouched.\n */\ninterface Gesture extends GestureBase {\n /** Which square the pointer took hold in, so a long bar does not jump under it. */\n grabIndex: number\n}\n\nconst gridEl = ref<HTMLElement | null>(null)\n/** The view's own box, which a drag is measured against to know whether it has left it. */\nconst rootEl = ref<HTMLElement | null>(null)\n\nconst {\n gesture,\n withPreview,\n edgeCue,\n isRtl,\n start,\n endLastGesture,\n consumeDrag,\n onPointermove,\n onPointerup,\n onPointercancel,\n onPointerleave,\n onFocusout,\n onCardKeydown,\n focusCell,\n idOfCard,\n cardState,\n} = useCalendarGesture<E, Gesture>({\n events: () => props.events,\n // The finished gesture and the weeks it was measured against are not kept past it.\n onRelease: () => {\n lastApplied = null\n },\n eventOf: (id): E | undefined => eventsById.value.get(id),\n // Measured against the ROOT and not against `gridEl`, whose rect leaves out the row of\n // weekday names above it.\n rootEl,\n // Captured on the GRID rather than on the chip, because a chip is redrawn on another day the\n // moment the drag starts and a captured element that moves takes the pointer with it.\n captureEl: gridEl,\n measureEl: gridEl,\n columns: () => columnCount.value,\n editable: () => props.editable,\n hintId: () => props.hintId,\n // The step is irrelevant to a month, which has no hours: 1 keeps the table honest without\n // asking the calendar for a number this view never uses.\n slotMinutes: () => 1,\n edgeStepDelay: () => props.edgeStepDelay,\n layout: () => props.weeks,\n applyPoint,\n onDrop: (state) => emit('event-drop', state.id, state.preview, 'move'),\n grab: (item) =>\n props.editable\n ? {\n id: item.id,\n origin: timesOf(item),\n pointerId: null,\n originX: 0,\n originY: 0,\n // There is no pointer to remember; the arrows work off the preview, not a position.\n grabIndex: 0,\n }\n : null,\n onGrabStep,\n step: (delta) => emit('step', delta),\n announce: (message) => emit('announce', message),\n})\n\n/**\n * The events as the month should currently DRAW them — the model, with the one being carried\n * put wherever it now is. Running the preview through the same grouping as everything else is\n * what makes the day it leaves and the day it arrives at both redraw with no special case.\n *\n * Nothing has to be held out of a layout for the echo, unlike the time grid: a month cell\n * simply stacks its chips, so the echo takes its own line in the day it came from and disturbs\n * nothing.\n */\nconst drawnEvents = computed<E[]>(() => (gesture.value ? withPreview(props.events) : props.events))\n\n/** Every day's events, worked out once rather than once per chip. */\nconst byDay = computed(() => eventsByDay(drawnEvents.value, flat.value))\n\nconst eventsById = computed(\n () => new Map<CalendarEventId, E>(drawnEvents.value.map((item) => [item.id, item])),\n)\n\n/**\n * A chip says when it happens only when that is not obvious: an all-day event has no time\n * to give, and the day it sits in already says which day it is.\n *\n * Memoized by start time inside the computed, so a change of locale or hour format throws the\n * cache away whole — the twin in VCalendarTimeGrid.vue carries the trap that makes reading\n * the computed, and not a cache beside it, the only correct shape.\n */\nconst timeTextOf = computed(() => {\n const { locale, format } = props\n const cache = new Map<string, string>()\n return (event: E): string => {\n if (isAllDayEvent(event)) return ''\n let text = cache.get(event.startTime)\n if (text === undefined) {\n text = formatTimeDisplay(event.startTime, locale, format)\n cache.set(event.startTime, text)\n }\n return text\n }\n})\n\n/** One chip as the template draws it, its time already written out. */\ninterface Chip {\n event: E\n timeText: string\n}\n\n/**\n * What each square draws, and how many it had to leave out — one Map, built in a single pass.\n *\n * It is the `dayLabels` treatment. Written as template functions these returned a NEW array\n * per square per render, and since one of them is the source of a `v-for`, Vue rediffed all\n * 42 lists each time; each chip also formatted its own time. The map is rebuilt with `byDay`,\n * which a drag changes only when it carries its chip onto another day (`applyPoint` writes\n * nothing otherwise), and survives every other render.\n */\nconst dayEvents = computed(() => {\n const map = new Map<string, { shown: Chip[]; hidden: number }>()\n const textOf = timeTextOf.value\n // Below zero, a limit would count hidden events on every empty square.\n const limit = Math.max(0, props.monthEventLimit)\n for (const [iso, all] of byDay.value) {\n const shown = all.length > limit ? all.slice(0, limit) : all\n map.set(iso, {\n shown: shown.map((event) => ({ event, timeText: textOf(event) })),\n hidden: Math.max(0, all.length - limit),\n })\n }\n return map\n})\n\n/** A square with nothing on it, shared rather than allocated per empty cell. */\nconst NO_EVENTS: { shown: Chip[]; hidden: number } = Object.freeze({ shown: [], hidden: 0 })\nconst dayEventsOf = (iso: string) => dayEvents.value.get(iso) ?? NO_EVENTS\n\nfunction moveFocusTo(iso: string) {\n focused.value = iso\n // @a11y — the model decides which cell is tabbable, so the focus can only follow once the\n // render that applied it has run.\n focusCell(cellId(iso), true)\n}\n\nconst tabbable = computed(() =>\n flat.value.includes(focused.value) ? focused.value : (flat.value[0] ?? null),\n)\n\n/**\n * The same table serves both views, so its two axes are read differently here: a sideways step\n * is one day, and a vertical one is a whole week rather than an hour. That is the only place the\n * month reinterprets it, and it is why the table returns a direction rather than a date.\n */\nconst dayStep = (days: number, minutes: number) =>\n days !== 0 ? days : Math.sign(minutes) * columnCount.value\n\nfunction onKeydown(event: KeyboardEvent) {\n const target = event.target as HTMLElement | null\n\n // A chip answers its own table, delegated here on the same element as the pointer so the\n // two input paths cannot drift apart.\n const card = target?.closest<HTMLElement>('.v-calendar-event')\n if (card) {\n onCardKeydown(event, card)\n return\n }\n\n const cell = target?.closest<HTMLElement>('.v-calendar-month-cell')\n if (!cell) return\n\n const intent = calendarIntent(event, 'cell', 1, isRtl())\n if (!intent) return\n\n const iso = cell.dataset.iso!\n const index = flat.value.indexOf(iso)\n const columns = columnCount.value\n\n if (intent.kind === 'moveFocus') {\n const next =\n flat.value[clamp(index + dayStep(intent.days, intent.minutes), 0, flat.value.length - 1)]\n if (!next) return\n event.preventDefault()\n moveFocusTo(next)\n return\n }\n\n if (intent.kind === 'rowEdge') {\n const row = Math.floor(index / columns)\n const edge = intent.edge === 'start' ? row * columns : row * columns + columns - 1\n const next = flat.value[clamp(edge, 0, flat.value.length - 1)]\n if (!next) return\n event.preventDefault()\n moveFocusTo(next)\n return\n }\n\n if (intent.kind === 'period') {\n event.preventDefault()\n emit('step', intent.delta)\n return\n }\n\n if (intent.kind === 'openDay') {\n event.preventDefault()\n emit('day-activate', iso)\n return\n }\n\n if (intent.kind === 'activate') {\n event.preventDefault()\n emit('cell-activate', { date: iso, minutes: null })\n }\n}\n\n/** Which of the flattened squares a point falls on. */\nfunction indexAt(x: number, y: number, rect: DOMRect, rtl: boolean): number {\n const cell = pointToMonthCell(\n { x, y },\n { ...gridGeometryOf(rect, columnCount.value, rtl), rows: props.weeks.length || 1 },\n rtl,\n )\n return cell.rowIndex * columnCount.value + cell.columnIndex\n}\n\nfunction onGridPointerdown(event: PointerEvent) {\n endLastGesture()\n if (gesture.value || !props.editable || event.button !== 0) return\n\n const card = (event.target as HTMLElement | null)?.closest<HTMLElement>('.v-calendar-event')\n const item = card ? eventsById.value.get(idOfCard(card)) : undefined\n const rect = gridEl.value?.getBoundingClientRect()\n if (!item || !rect) return\n const rtl = isRtl()\n\n start(\n {\n id: item.id,\n origin: timesOf(item),\n pointerId: event.pointerId,\n originX: event.clientX,\n originY: event.clientY,\n grabIndex: indexAt(event.clientX, event.clientY, rect, rtl),\n },\n rtl,\n )\n}\n\n/**\n * Works out which day the chip now belongs to, from wherever the pointer last was.\n *\n * Separate from the handler because the month turning calls it too: the squares change under\n * a hand that has not moved, and the chip has to be placed against the new ones.\n */\nfunction applyPoint(state: Gesture, rect: DOMRect) {\n const index = indexAt(state.lastX, state.lastY, rect, state.rtl)\n const last = lastApplied\n if (last?.state === state && last.weeks === props.weeks && last.index === index) return\n lastApplied = { state, weeks: props.weeks, index }\n\n /*\n * The target is the event's START shifted by however many squares the pointer has crossed,\n * not the square it is over — so a bar grabbed by its third day keeps its third day under\n * the finger. The days come out of the flattened grid, which is already filtered to the\n * weekdays on show, so a hidden weekend is not counted.\n */\n const days = flat.value\n const from = days.indexOf(state.origin.start)\n const target =\n days[\n clamp((from === -1 ? state.grabIndex : from) + index - state.grabIndex, 0, days.length - 1)\n ]\n if (!target) return\n /*\n * TRAP — written only when the day changes. The gesture is a deep ref, so an equal but new\n * preview would still re-bucket and re-sort every event and re-render all 42 squares.\n */\n const next = moveEventToDay(state.origin, target)\n if (!sameTimes(state.preview, next)) state.preview = next\n}\n\n/**\n * The square `applyPoint` last placed the chip from, so the many `pointermove`s that fire\n * inside one square return before any date arithmetic. The weeks belong to what the index\n * MEANS: the month turning under a still pointer reads as a new square at the same index.\n * A plain variable, since nothing renders it; the gesture's identity says a new press began.\n */\nlet lastApplied: { state: Gesture; weeks: MonthCell[][]; index: number } | null = null\n\n/** One arrow press on a chip held by the keyboard: a day sideways, a week vertically. */\nfunction onGrabStep(state: Gesture, step: GrabStep, item: E): boolean {\n // A month has no hours to stretch, so Shift with an arrow is simply not a gesture here.\n if (step.kind !== 'grabMove') return false\n const days = flat.value\n const from = days.indexOf(state.preview.start)\n const target = days[clamp(from + dayStep(step.days, step.minutes), 0, days.length - 1)]\n // Held against the grid's edge, the press goes nowhere: nothing to announce or to drop.\n if (!target || target === state.preview.start) return false\n state.preview = moveEventToDay(state.preview, target)\n emit('announce', m.value.calendar.movedTo(item.title, longDay(state.preview.start)))\n return true\n}\n\nfunction onCardClick(item: E) {\n // `pointerup` fires before `click`, so letting go at the end of a drag would ALSO open the\n // event — the consumer's editor over every chip the reader had just moved.\n if (consumeDrag()) return\n emit('event-activate', item)\n}\n\n/**\n * A click on the empty part of a day: the pointer's side of the Enter that activates a cell,\n * so a square drawn with a pointer cursor answers a click as it answers the key.\n *\n * The chips and the two buttons a square holds answer their own clicks, so a click that came\n * from one of them is theirs alone. And a click ending a drag is swallowed like the one a chip\n * would have received: the drop has already said what the gesture meant.\n */\nfunction onGridClick(event: MouseEvent) {\n const target = event.target as HTMLElement | null\n if (target?.closest('.v-calendar-event, button')) return\n const cell = target?.closest<HTMLElement>('.v-calendar-month-cell')\n if (!cell || consumeDrag()) return\n emit('cell-activate', { date: cell.dataset.iso!, minutes: null })\n}\n\n// The same two members VCalendarTimeGrid exposes, so VCalendar drives either view without\n// asking which is on screen. A month has no hours, hence the empty `scrollToMinutes`.\ndefineExpose({\n /** Brings the focus onto the day the grid is currently pointing at. */\n focus: (options?: FocusOptions) => {\n if (tabbable.value) focusCell(cellId(tabbable.value), false, options)\n },\n /** Nothing to scroll to in a month view. */\n scrollToMinutes: () => {},\n})\n</script>\n\n<template>\n <div\n ref=\"rootEl\"\n class=\"v-calendar-month\"\n :data-outside=\"gesture?.outside ? '' : undefined\"\n :style=\"{ '--calendar-columns': String(weekdayNames.length) }\"\n @focusout=\"onFocusout\"\n >\n <div class=\"v-calendar-month-head\" aria-hidden=\"true\">\n <span\n v-for=\"(name, index) in weekdayNames\"\n :key=\"index\"\n class=\"v-calendar-weekday v-calendar-month-weekday\"\n >\n {{ name }}\n </span>\n </div>\n\n <div\n ref=\"gridEl\"\n class=\"v-calendar-month-grid v-calendar-edge-cue\"\n role=\"grid\"\n :aria-label=\"label\"\n :data-edge=\"edgeCue\"\n @keydown=\"onKeydown\"\n @pointerdown=\"onGridPointerdown\"\n @pointermove=\"onPointermove\"\n @pointerup=\"onPointerup\"\n @pointercancel=\"onPointercancel\"\n @pointerleave=\"onPointerleave\"\n @click=\"onGridClick\"\n >\n <div\n v-for=\"(week, row) in weeks\"\n :key=\"week[0]?.iso ?? row\"\n role=\"row\"\n class=\"v-calendar-month-week\"\n >\n <div\n v-for=\"cell in week\"\n :id=\"cellId(cell.iso)\"\n :key=\"cell.iso\"\n role=\"gridcell\"\n class=\"v-calendar-cell v-calendar-month-cell\"\n :data-iso=\"cell.iso\"\n :data-adjacent=\"cell.adjacent ?? undefined\"\n :tabindex=\"tabbable === cell.iso ? 0 : -1\"\n :aria-label=\"longDay(cell.iso)\"\n aria-keyshortcuts=\"Shift+Enter\"\n >\n <button\n type=\"button\"\n class=\"v-calendar-button v-calendar-month-day\"\n :class=\"{ 'v-calendar-today': cell.iso === today }\"\n tabindex=\"-1\"\n :aria-label=\"m.calendar.openDay(longDay(cell.iso))\"\n @click=\"emit('day-activate', cell.iso)\"\n >\n {{ dayNumber(cell.iso) }}\n </button>\n\n <VCalendarEvent\n v-for=\"chip in dayEventsOf(cell.iso).shown\"\n :key=\"chip.event.id\"\n class=\"v-calendar-month-chip\"\n :event=\"chip.event\"\n layout=\"chip\"\n :disabled=\"disabled\"\n :time-text=\"chip.timeText\"\n v-bind=\"cardState(chip.event.id)\"\n @click=\"onCardClick(chip.event)\"\n >\n <template v-if=\"$slots.event\" #default=\"slotProps\">\n <slot name=\"event\" v-bind=\"slotProps\" />\n </template>\n </VCalendarEvent>\n\n <button\n v-if=\"dayEventsOf(cell.iso).hidden > 0\"\n type=\"button\"\n class=\"v-calendar-button v-calendar-month-more\"\n tabindex=\"-1\"\n @click=\"emit('day-activate', cell.iso)\"\n >\n {{ m.calendar.moreEvents(dayEventsOf(cell.iso).hidden) }}\n </button>\n </div>\n </div>\n </div>\n </div>\n</template>\n\n<style>\n@layer vectis.components {\n .v-calendar-month {\n display: flex;\n flex-direction: column;\n }\n\n .v-calendar-month-head,\n .v-calendar-month-week {\n display: grid;\n grid-template-columns: repeat(var(--calendar-columns), minmax(0, 1fr));\n }\n\n /* 4, the time grid's header layer: a dragged chip (3) and the edge strip (2) pass under the\n sticky names as the month scrolls, rather than over them. */\n .v-calendar-month-head {\n position: sticky;\n inset-block-start: 0;\n z-index: 4;\n background: var(--vectis-color-surface);\n border-block-end: 1px solid var(--vectis-color-border);\n }\n\n .v-calendar-month-weekday {\n padding-block: var(--vectis-space-2);\n text-align: center;\n }\n\n .v-calendar-month-grid {\n /* The edge strip is placed against this box. */\n position: relative;\n display: flex;\n /* The rows share what height there is, so a month fills the box it was given instead of\n leaving a band of nothing under the last week. The floor keeps a day readable when\n that box is short. */\n flex: 1;\n flex-direction: column;\n min-block-size: 0;\n }\n\n .v-calendar-month-week {\n flex: 1;\n min-block-size: var(--vectis-control-size-calendar-month-cell);\n }\n\n .v-calendar-month-cell {\n display: flex;\n flex-direction: column;\n gap: var(--vectis-control-size-calendar-gap);\n overflow: hidden;\n padding: var(--vectis-space-1);\n }\n\n /* The days of the neighbouring months are kept — the grid is a fixed six rows, so the\n page never jumps — but pushed back, since they are context rather than content. */\n .v-calendar-month-cell[data-adjacent] {\n background: var(--vectis-color-surface-sunken);\n color: var(--vectis-color-text-subtle);\n }\n\n .v-calendar-month-day {\n align-self: center;\n display: flex;\n align-items: center;\n justify-content: center;\n flex: none;\n inline-size: var(--vectis-control-height-sm);\n block-size: var(--vectis-control-height-sm);\n border-radius: var(--vectis-radius-pill);\n color: inherit;\n font-size: var(--vectis-text-body-md-size);\n }\n\n /* Disjoint from today rather than less specific: the two live in different sheets, where a\n tie would be settled by whichever one the consumer's bundler emitted last. */\n .v-calendar-month-day:hover:not(.v-calendar-today) {\n background: var(--vectis-color-surface-muted);\n }\n\n /*\n * A day in the month view is a summary, so a chip is capped at one lane however long the\n * event really is — an all-day bar and a two-hour meeting look the same here, and several\n * have to fit under the date.\n *\n * The height is SET AS A PROPERTY rather than as `block-size`. The chip rule in\n * VCalendarEvent's own sheet is (0,2,0) against this (0,1,0), so declaring the size\n * directly would lose — and matching its specificity would only hand the decision to\n * whichever sheet the consumer's bundler emitted last, which is the failure the library's\n * one-sheet-per-component rule exists to prevent.\n */\n .v-calendar-month-chip {\n --calendar-chip-height: var(--vectis-control-size-calendar-allday-lane);\n\n flex: none;\n }\n\n .v-calendar-month-more {\n flex: none;\n padding-inline: var(--vectis-space-1);\n color: var(--vectis-color-text-muted);\n font-size: var(--vectis-text-caption-size);\n text-align: start;\n }\n\n .v-calendar-month-more:hover {\n color: var(--vectis-color-text);\n text-decoration: underline;\n }\n\n /* The neighbouring months' days are told apart by a tint forced colors removes: grey text\n keeps them apart. */\n @media (forced-colors: active) {\n .v-calendar-month-cell[data-adjacent] {\n forced-color-adjust: none;\n background: Canvas;\n color: GrayText;\n }\n }\n}\n</style>\n"],"mappings":""}
1
+ {"version":3,"file":"VCalendarMonth.js","names":[],"sources":["../../../src/components/VCalendar/VCalendarMonth.vue"],"sourcesContent":["<script setup lang=\"ts\" generic=\"E extends CalendarEvent\">\n// @a11y @keyboard @core\n/**\n * Month cells summarize events and overflow counts. Shared gesture logic supplies dragging and\n * keyboard grabs; grid focus remains in this view.\n */\nimport { computed, ref, useId } from 'vue'\n\nimport { formatDateDisplay } from '../../utils/date'\nimport { clamp } from '../../utils/number'\nimport { formatTimeDisplay } from '../../utils/time'\n\nimport { useMessages } from '../../i18n/state'\n\nimport VCalendarEvent from './VCalendarEvent.vue'\nimport { gridGeometryOf, useCalendarGesture, type GestureBase, type GrabStep } from './gesture'\nimport { calendarIntent } from './keyboard'\nimport {\n eventsByDay,\n isAllDayEvent,\n moveEventToDay,\n pointToMonthCell,\n sameTimes,\n timesOf,\n type MonthCell,\n} from './layout'\nimport type {\n ActivatedCell,\n CalendarEvent,\n CalendarEventId,\n CalendarEventSlotProps,\n CalendarEventTimes,\n CalendarFormat,\n} from './types'\n\nexport interface CalendarMonthProps<T> {\n /** The weeks, already padded to a fixed height and filtered to the visible weekdays. */\n weeks: MonthCell[][]\n events: T[]\n locale: string\n format: CalendarFormat\n today: string | null\n /** How many events a day shows before it starts counting the rest. */\n monthEventLimit: number\n /** Whether events can be moved from one day to another. */\n editable: boolean\n /** Whether the whole calendar is frozen, which also takes its cards out of the tab order. */\n disabled: boolean\n /** The node telling a reader how a chip can be moved, shared by every one of them. */\n hintId: string\n /** How long a drag rests against an edge before the month turns. Zero turns paging off. */\n edgeStepDelay: number\n label: string\n}\n\nconst props = defineProps<CalendarMonthProps<E>>()\n\nconst emit = defineEmits<{\n /** A day was asked to be opened on its own. */\n 'day-activate': [iso: string]\n /** An empty part of a day was activated. A month has no hours, so the time is left to the calendar. */\n 'cell-activate': [cell: ActivatedCell]\n 'event-activate': [event: E]\n /** An event was dropped on another day. A month has no hours, so it is only ever a move. */\n 'event-drop': [id: CalendarEventId, times: CalendarEventTimes, kind: 'move']\n /** Something happened that a reader who cannot see the grid needs told. */\n announce: [message: string]\n step: [delta: -1 | 1]\n}>()\n\n/** Which day holds the tab stop. Only the date matters here; the hour is the grid's affair. */\nconst focused = defineModel<string>('focused', { required: true })\n\ndefineSlots<{\n event?(props: CalendarEventSlotProps<E>): unknown\n}>()\n\nconst m = useMessages()\nconst uid = useId()\n\nconst cellId = (iso: string) => `${uid}-m-${iso}`\n\n/** The flattened list of days: what the arrows travel along, and what the events are filed by. */\nconst flat = computed(() => props.weeks.flat().map((cell) => cell.iso))\nconst columnCount = computed(() => props.weeks[0]?.length ?? 1)\n\n/** The column headings, taken from the first week so they always match the columns drawn. */\nconst weekdayNames = computed(() =>\n (props.weeks[0] ?? []).map((cell) =>\n formatDateDisplay(cell.iso, props.locale, { weekday: 'short' }),\n ),\n)\n\n/*\n * `longDay` is asked for twice in the template; the square's own `aria-label`, then the name of\n * the button that opens the day; so the 42 cells cost 126 `Intl` formats a render, and a drag\n * re-renders the whole grid each time it carries a chip onto another day. The map depends on\n * the weeks and the locale alone, so it survives every frame of a drag.\n */\nconst dayLabels = computed(() => {\n const map = new Map<string, { number: string; long: string }>()\n for (const iso of flat.value) {\n map.set(iso, {\n number: formatDateDisplay(iso, props.locale, { day: 'numeric' }),\n long: formatDateDisplay(iso, props.locale, {\n weekday: 'long',\n day: 'numeric',\n month: 'long',\n }),\n })\n }\n return map\n})\n\nconst dayNumber = (iso: string) => dayLabels.value.get(iso)?.number ?? ''\n\n/*\n * A day outside the grid can reach this; the announcement after a move names the day the event\n * landed on, which may be the next month; so it falls back to formatting rather than assuming\n * the map holds it.\n */\nconst longDay = (iso: string) =>\n dayLabels.value.get(iso)?.long ??\n formatDateDisplay(iso, props.locale, { weekday: 'long', day: 'numeric', month: 'long' })\n\n/** A chip being carried from one day to another, by pointer or by keyboard. */\ninterface Gesture extends GestureBase {\n /** Which square the pointer took hold in, so a long bar does not jump under it. */\n grabIndex: number\n}\n\nconst gridEl = ref<HTMLElement | null>(null)\nconst rootEl = ref<HTMLElement | null>(null)\n\nconst {\n gesture,\n withPreview,\n edgeCue,\n isRtl,\n start,\n endLastGesture,\n consumeDrag,\n onPointermove,\n onPointerup,\n onPointercancel,\n onPointerleave,\n onFocusout,\n onCardKeydown,\n focusCell,\n idOfCard,\n cardState,\n} = useCalendarGesture<E, Gesture>({\n events: () => props.events,\n onRelease: () => {\n lastApplied = null\n },\n eventOf: (id): E | undefined => eventsById.value.get(id),\n rootEl,\n // Captured on the GRID rather than on the chip, because a chip is redrawn on another day the\n // moment the drag starts and a captured element that moves takes the pointer with it.\n captureEl: gridEl,\n measureEl: gridEl,\n columns: () => columnCount.value,\n editable: () => props.editable,\n hintId: () => props.hintId,\n // The step is irrelevant to a month, which has no hours: 1 keeps the table honest without\n // asking the calendar for a number this view never uses.\n slotMinutes: () => 1,\n edgeStepDelay: () => props.edgeStepDelay,\n layout: () => props.weeks,\n applyPoint,\n onDrop: (state) => emit('event-drop', state.id, state.preview, 'move'),\n grab: (item) =>\n props.editable\n ? {\n id: item.id,\n origin: timesOf(item),\n pointerId: null,\n originX: 0,\n originY: 0,\n grabIndex: 0,\n }\n : null,\n onGrabStep,\n step: (delta) => emit('step', delta),\n announce: (message) => emit('announce', message),\n})\n\n/**\n * The events as the month should currently DRAW them; the model, with the one being carried put\n * wherever it now is.\n */\nconst drawnEvents = computed<E[]>(() => (gesture.value ? withPreview(props.events) : props.events))\n\n/** Every day's events, worked out once rather than once per chip. */\nconst byDay = computed(() => eventsByDay(drawnEvents.value, flat.value))\n\nconst eventsById = computed(\n () => new Map<CalendarEventId, E>(drawnEvents.value.map((item) => [item.id, item])),\n)\n\n/**\n * A chip says when it happens only when that is not obvious: an all-day event has no time to\n * give, and the day it sits in already says which day it is.\n */\nconst timeTextOf = computed(() => {\n const { locale, format } = props\n const cache = new Map<string, string>()\n return (event: E): string => {\n if (isAllDayEvent(event)) return ''\n let text = cache.get(event.startTime)\n if (text === undefined) {\n text = formatTimeDisplay(event.startTime, locale, format)\n cache.set(event.startTime, text)\n }\n return text\n }\n})\n\n/** One chip as the template draws it, its time already written out. */\ninterface Chip {\n event: E\n timeText: string\n}\n\n/** What each square draws, and how many it had to leave out; one Map, built in a single pass. */\nconst dayEvents = computed(() => {\n const map = new Map<string, { shown: Chip[]; hidden: number }>()\n const textOf = timeTextOf.value\n const limit = Math.max(0, props.monthEventLimit)\n for (const [iso, all] of byDay.value) {\n const shown = all.length > limit ? all.slice(0, limit) : all\n map.set(iso, {\n shown: shown.map((event) => ({ event, timeText: textOf(event) })),\n hidden: Math.max(0, all.length - limit),\n })\n }\n return map\n})\n\n/** A square with nothing on it, shared rather than allocated per empty cell. */\nconst NO_EVENTS: { shown: Chip[]; hidden: number } = Object.freeze({ shown: [], hidden: 0 })\nconst dayEventsOf = (iso: string) => dayEvents.value.get(iso) ?? NO_EVENTS\n\nfunction moveFocusTo(iso: string) {\n focused.value = iso\n // @a11y\n focusCell(cellId(iso), true)\n}\n\nconst tabbable = computed(() =>\n flat.value.includes(focused.value) ? focused.value : (flat.value[0] ?? null),\n)\n\n/**\n * The same table serves both views, so its two axes are read differently here: a sideways step\n * is one day, and a vertical one is a whole week rather than an hour.\n */\nconst dayStep = (days: number, minutes: number) =>\n days !== 0 ? days : Math.sign(minutes) * columnCount.value\n\nfunction onKeydown(event: KeyboardEvent) {\n const target = event.target as HTMLElement | null\n\n // A chip answers its own table, delegated here on the same element as the pointer so the\n // two input paths cannot drift apart.\n const card = target?.closest<HTMLElement>('.v-calendar-event')\n if (card) {\n onCardKeydown(event, card)\n return\n }\n\n const cell = target?.closest<HTMLElement>('.v-calendar-month-cell')\n if (!cell) return\n\n const intent = calendarIntent(event, 'cell', 1, isRtl())\n if (!intent) return\n\n const iso = cell.dataset.iso!\n const index = flat.value.indexOf(iso)\n const columns = columnCount.value\n\n if (intent.kind === 'moveFocus') {\n const next =\n flat.value[clamp(index + dayStep(intent.days, intent.minutes), 0, flat.value.length - 1)]\n if (!next) return\n event.preventDefault()\n moveFocusTo(next)\n return\n }\n\n if (intent.kind === 'rowEdge') {\n const row = Math.floor(index / columns)\n const edge = intent.edge === 'start' ? row * columns : row * columns + columns - 1\n const next = flat.value[clamp(edge, 0, flat.value.length - 1)]\n if (!next) return\n event.preventDefault()\n moveFocusTo(next)\n return\n }\n\n if (intent.kind === 'period') {\n event.preventDefault()\n emit('step', intent.delta)\n return\n }\n\n if (intent.kind === 'openDay') {\n event.preventDefault()\n emit('day-activate', iso)\n return\n }\n\n if (intent.kind === 'activate') {\n event.preventDefault()\n emit('cell-activate', { date: iso, minutes: null })\n }\n}\n\n/** Which of the flattened squares a point falls on. */\nfunction indexAt(x: number, y: number, rect: DOMRect, rtl: boolean): number {\n const cell = pointToMonthCell(\n { x, y },\n { ...gridGeometryOf(rect, columnCount.value, rtl), rows: props.weeks.length || 1 },\n rtl,\n )\n return cell.rowIndex * columnCount.value + cell.columnIndex\n}\n\nfunction onGridPointerdown(event: PointerEvent) {\n endLastGesture()\n if (gesture.value || !props.editable || event.button !== 0) return\n\n const card = (event.target as HTMLElement | null)?.closest<HTMLElement>('.v-calendar-event')\n const item = card ? eventsById.value.get(idOfCard(card)) : undefined\n const rect = gridEl.value?.getBoundingClientRect()\n if (!item || !rect) return\n const rtl = isRtl()\n\n start(\n {\n id: item.id,\n origin: timesOf(item),\n pointerId: event.pointerId,\n originX: event.clientX,\n originY: event.clientY,\n grabIndex: indexAt(event.clientX, event.clientY, rect, rtl),\n },\n rtl,\n )\n}\n\n/** Works out which day the chip now belongs to, from wherever the pointer last was. */\nfunction applyPoint(state: Gesture, rect: DOMRect) {\n const index = indexAt(state.lastX, state.lastY, rect, state.rtl)\n const last = lastApplied\n if (last?.state === state && last.weeks === props.weeks && last.index === index) return\n lastApplied = { state, weeks: props.weeks, index }\n\n /*\n * The target is the event's START shifted by however many squares the pointer has crossed,\n * not the square it is over; so a bar grabbed by its third day keeps its third day under the\n * finger. The days come out of the flattened grid, which is already filtered to the weekdays\n * on show, so a hidden weekend is not counted.\n */\n const days = flat.value\n const from = days.indexOf(state.origin.start)\n const target =\n days[\n clamp((from === -1 ? state.grabIndex : from) + index - state.grabIndex, 0, days.length - 1)\n ]\n if (!target) return\n /*\n * Written only when the day changes. The gesture is a deep ref, so an equal but new preview\n * would still re-bucket and re-sort every event and re-render all 42 squares.\n */\n const next = moveEventToDay(state.origin, target)\n if (!sameTimes(state.preview, next)) state.preview = next\n}\n\n/**\n * The square `applyPoint` last placed the chip from, so the many `pointermove`s that fire\n * inside one square return before any date arithmetic.\n */\nlet lastApplied: { state: Gesture; weeks: MonthCell[][]; index: number } | null = null\n\n/** One arrow press on a chip held by the keyboard: a day sideways, a week vertically. */\nfunction onGrabStep(state: Gesture, step: GrabStep, item: E): boolean {\n if (step.kind !== 'grabMove') return false\n const days = flat.value\n const from = days.indexOf(state.preview.start)\n const target = days[clamp(from + dayStep(step.days, step.minutes), 0, days.length - 1)]\n if (!target || target === state.preview.start) return false\n state.preview = moveEventToDay(state.preview, target)\n emit('announce', m.value.calendar.movedTo(item.title, longDay(state.preview.start)))\n return true\n}\n\nfunction onCardClick(item: E) {\n // `pointerup` fires before `click`, so letting go at the end of a drag would ALSO open the\n // event; the consumer's editor over every chip the reader had just moved.\n if (consumeDrag()) return\n emit('event-activate', item)\n}\n\n/**\n * A click on the empty part of a day: the pointer's side of the Enter that activates a cell, so\n * a square drawn with a pointer cursor answers a click as it answers the key.\n */\nfunction onGridClick(event: MouseEvent) {\n const target = event.target as HTMLElement | null\n if (target?.closest('.v-calendar-event, button')) return\n const cell = target?.closest<HTMLElement>('.v-calendar-month-cell')\n if (!cell || consumeDrag()) return\n emit('cell-activate', { date: cell.dataset.iso!, minutes: null })\n}\n\n// The same two members VCalendarTimeGrid exposes, so VCalendar drives either view without\n// asking which is on screen. A month has no hours, hence the empty `scrollToMinutes`.\ndefineExpose({\n /** Brings the focus onto the day the grid is currently pointing at. */\n focus: (options?: FocusOptions) => {\n if (tabbable.value) focusCell(cellId(tabbable.value), false, options)\n },\n /** Nothing to scroll to in a month view. */\n scrollToMinutes: () => {},\n})\n</script>\n\n<template>\n <div\n ref=\"rootEl\"\n class=\"v-calendar-month\"\n :data-outside=\"gesture?.outside ? '' : undefined\"\n :style=\"{ '--calendar-columns': String(weekdayNames.length) }\"\n @focusout=\"onFocusout\"\n >\n <div class=\"v-calendar-month-head\" aria-hidden=\"true\">\n <span\n v-for=\"(name, index) in weekdayNames\"\n :key=\"index\"\n class=\"v-calendar-weekday v-calendar-month-weekday\"\n >\n {{ name }}\n </span>\n </div>\n\n <div\n ref=\"gridEl\"\n class=\"v-calendar-month-grid v-calendar-edge-cue\"\n role=\"grid\"\n :aria-label=\"label\"\n :data-edge=\"edgeCue\"\n @keydown=\"onKeydown\"\n @pointerdown=\"onGridPointerdown\"\n @pointermove=\"onPointermove\"\n @pointerup=\"onPointerup\"\n @pointercancel=\"onPointercancel\"\n @pointerleave=\"onPointerleave\"\n @click=\"onGridClick\"\n >\n <div\n v-for=\"(week, row) in weeks\"\n :key=\"week[0]?.iso ?? row\"\n role=\"row\"\n class=\"v-calendar-month-week\"\n >\n <div\n v-for=\"cell in week\"\n :id=\"cellId(cell.iso)\"\n :key=\"cell.iso\"\n role=\"gridcell\"\n class=\"v-calendar-cell v-calendar-month-cell\"\n :data-iso=\"cell.iso\"\n :data-adjacent=\"cell.adjacent ?? undefined\"\n :tabindex=\"tabbable === cell.iso ? 0 : -1\"\n :aria-label=\"longDay(cell.iso)\"\n aria-keyshortcuts=\"Shift+Enter\"\n >\n <button\n type=\"button\"\n class=\"v-calendar-button v-calendar-month-day\"\n :class=\"{ 'v-calendar-today': cell.iso === today }\"\n tabindex=\"-1\"\n :aria-label=\"m.calendar.openDay(longDay(cell.iso))\"\n @click=\"emit('day-activate', cell.iso)\"\n >\n {{ dayNumber(cell.iso) }}\n </button>\n\n <VCalendarEvent\n v-for=\"chip in dayEventsOf(cell.iso).shown\"\n :key=\"chip.event.id\"\n class=\"v-calendar-month-chip\"\n :event=\"chip.event\"\n layout=\"chip\"\n :disabled=\"disabled\"\n :time-text=\"chip.timeText\"\n v-bind=\"cardState(chip.event.id)\"\n @click=\"onCardClick(chip.event)\"\n >\n <template v-if=\"$slots.event\" #default=\"slotProps\">\n <slot name=\"event\" v-bind=\"slotProps\" />\n </template>\n </VCalendarEvent>\n\n <button\n v-if=\"dayEventsOf(cell.iso).hidden > 0\"\n type=\"button\"\n class=\"v-calendar-button v-calendar-month-more\"\n tabindex=\"-1\"\n @click=\"emit('day-activate', cell.iso)\"\n >\n {{ m.calendar.moreEvents(dayEventsOf(cell.iso).hidden) }}\n </button>\n </div>\n </div>\n </div>\n </div>\n</template>\n\n<style>\n@layer vectis.components {\n .v-calendar-month {\n display: flex;\n flex-direction: column;\n }\n\n .v-calendar-month-head,\n .v-calendar-month-week {\n display: grid;\n grid-template-columns: repeat(var(--calendar-columns), minmax(0, 1fr));\n }\n\n /* 4, the time grid's header layer: a dragged chip (3) and the edge strip (2) pass under the\n sticky names as the month scrolls, rather than over them. */\n .v-calendar-month-head {\n position: sticky;\n inset-block-start: 0;\n z-index: 4;\n background: var(--vectis-color-surface);\n border-block-end: 1px solid var(--vectis-color-border);\n }\n\n .v-calendar-month-weekday {\n padding-block: var(--vectis-space-2);\n text-align: center;\n }\n\n .v-calendar-month-grid {\n position: relative;\n display: flex;\n /* The rows share what height there is, so a month fills the box it was given instead of\n leaving a band of nothing under the last week. The floor keeps a day readable when\n that box is short. */\n flex: 1;\n flex-direction: column;\n min-block-size: 0;\n }\n\n .v-calendar-month-week {\n flex: 1;\n min-block-size: var(--vectis-control-size-calendar-month-cell);\n }\n\n .v-calendar-month-cell {\n display: flex;\n flex-direction: column;\n gap: var(--vectis-control-size-calendar-gap);\n overflow: hidden;\n padding: var(--vectis-space-1);\n }\n\n /*\n * The days of the neighbouring months are kept; the grid is a fixed six rows, so the page\n * never jumps; but pushed back, since they are context rather than content.\n */\n .v-calendar-month-cell[data-adjacent] {\n background: var(--vectis-color-surface-sunken);\n color: var(--vectis-color-text-subtle);\n }\n\n .v-calendar-month-day {\n align-self: center;\n display: flex;\n align-items: center;\n justify-content: center;\n flex: none;\n inline-size: var(--vectis-control-height-sm);\n block-size: var(--vectis-control-height-sm);\n border-radius: var(--vectis-radius-pill);\n color: inherit;\n font-size: var(--vectis-text-body-md-size);\n }\n\n /* Disjoint from today rather than less specific: the two live in different sheets, where a\n tie would be settled by whichever one the consumer's bundler emitted last. */\n .v-calendar-month-day:hover:not(.v-calendar-today) {\n background: var(--vectis-color-surface-muted);\n }\n\n /*\n * The chip rule in VCalendarEvent's own sheet is (0,2,0) against this (0,1,0), so declaring\n * the size directly would lose; and matching its specificity would only hand the decision to\n * whichever sheet the consumer's bundler emitted last, which is the failure the library's\n * one-sheet-per-component rule exists to prevent.\n */\n .v-calendar-month-chip {\n --calendar-chip-height: var(--vectis-control-size-calendar-allday-lane);\n\n flex: none;\n }\n\n .v-calendar-month-more {\n flex: none;\n padding-inline: var(--vectis-space-1);\n color: var(--vectis-color-text-muted);\n font-size: var(--vectis-text-caption-size);\n text-align: start;\n }\n\n .v-calendar-month-more:hover {\n color: var(--vectis-color-text);\n text-decoration: underline;\n }\n\n /* The neighbouring months' days are told apart by a tint forced colors removes: grey text\n keeps them apart. */\n @media (forced-colors: active) {\n .v-calendar-month-cell[data-adjacent] {\n forced-color-adjust: none;\n background: Canvas;\n color: GrayText;\n }\n }\n}\n</style>\n"],"mappings":""}