vectis-ui 0.8.1 → 0.9.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (432) hide show
  1. package/README.md +3 -3
  2. package/dist/components/VAccordion/VAccordionItem.d.ts +4 -6
  3. package/dist/components/VAccordion/VAccordionItem.js.map +1 -1
  4. package/dist/components/VAccordion/VAccordionItem.vue_vue_type_script_setup_true_lang.js +21 -19
  5. package/dist/components/VAccordion/VAccordionItem.vue_vue_type_script_setup_true_lang.js.map +1 -1
  6. package/dist/components/VAccordion/context.d.ts +6 -1
  7. package/dist/components/VAccordion/context.js.map +1 -1
  8. package/dist/components/VAvatar/VAvatar.css +1 -1
  9. package/dist/components/VAvatar/VAvatar.d.ts +5 -3
  10. package/dist/components/VAvatar/VAvatar.js.map +1 -1
  11. package/dist/components/VAvatar/VAvatar.vue_vue_type_script_setup_true_lang.js +53 -39
  12. package/dist/components/VAvatar/VAvatar.vue_vue_type_script_setup_true_lang.js.map +1 -1
  13. package/dist/components/VAvatar/VAvatarGroup.d.ts +12 -3
  14. package/dist/components/VAvatar/VAvatarGroup.js.map +1 -1
  15. package/dist/components/VAvatar/VAvatarGroup.vue_vue_type_script_setup_true_lang.js +27 -20
  16. package/dist/components/VAvatar/VAvatarGroup.vue_vue_type_script_setup_true_lang.js.map +1 -1
  17. package/dist/components/VAvatar/context.d.ts +2 -2
  18. package/dist/components/VAvatar/context.js.map +1 -1
  19. package/dist/components/VBadge/VBadge.css +1 -1
  20. package/dist/components/VBadge/VBadge.d.ts +8 -4
  21. package/dist/components/VBadge/VBadge.js.map +1 -1
  22. package/dist/components/VBadge/VBadge.vue_vue_type_script_setup_true_lang.js +6 -3
  23. package/dist/components/VBadge/VBadge.vue_vue_type_script_setup_true_lang.js.map +1 -1
  24. package/dist/components/VBreadcrumb/VBreadcrumb.d.ts +5 -4
  25. package/dist/components/VBreadcrumb/VBreadcrumb.js.map +1 -1
  26. package/dist/components/VBreadcrumb/VBreadcrumb.vue_vue_type_script_setup_true_lang.js +8 -3
  27. package/dist/components/VBreadcrumb/VBreadcrumb.vue_vue_type_script_setup_true_lang.js.map +1 -1
  28. package/dist/components/VButton/VButton.css +1 -1
  29. package/dist/components/VButton/VButton.d.ts +4 -1
  30. package/dist/components/VButton/VButton.js.map +1 -1
  31. package/dist/components/VButton/VButton.vue_vue_type_script_setup_true_lang.js +8 -7
  32. package/dist/components/VButton/VButton.vue_vue_type_script_setup_true_lang.js.map +1 -1
  33. package/dist/components/VButton/VButtonGroup.js.map +1 -1
  34. package/dist/components/VButton/VButtonGroup.vue_vue_type_script_setup_true_lang.js.map +1 -1
  35. package/dist/components/VCalendar/VCalendar.css +1 -1
  36. package/dist/components/VCalendar/VCalendar.d.ts +15 -6
  37. package/dist/components/VCalendar/VCalendar.js.map +1 -1
  38. package/dist/components/VCalendar/VCalendar.vue_vue_type_script_setup_true_lang.js +144 -126
  39. package/dist/components/VCalendar/VCalendar.vue_vue_type_script_setup_true_lang.js.map +1 -1
  40. package/dist/components/VCalendar/VCalendarEvent.css +1 -1
  41. package/dist/components/VCalendar/VCalendarEvent.d.ts +1 -1
  42. package/dist/components/VCalendar/VCalendarEvent.js.map +1 -1
  43. package/dist/components/VCalendar/VCalendarEvent.vue_vue_type_script_setup_true_lang.js.map +1 -1
  44. package/dist/components/VCalendar/VCalendarMonth.css +1 -1
  45. package/dist/components/VCalendar/VCalendarMonth.d.ts +1 -1
  46. package/dist/components/VCalendar/VCalendarMonth.js.map +1 -1
  47. package/dist/components/VCalendar/VCalendarMonth.vue_vue_type_script_setup_true_lang.js +99 -90
  48. package/dist/components/VCalendar/VCalendarMonth.vue_vue_type_script_setup_true_lang.js.map +1 -1
  49. package/dist/components/VCalendar/VCalendarTimeGrid.css +1 -1
  50. package/dist/components/VCalendar/VCalendarTimeGrid.d.ts +3 -3
  51. package/dist/components/VCalendar/VCalendarTimeGrid.js.map +1 -1
  52. package/dist/components/VCalendar/VCalendarTimeGrid.vue_vue_type_script_setup_true_lang.js +256 -246
  53. package/dist/components/VCalendar/VCalendarTimeGrid.vue_vue_type_script_setup_true_lang.js.map +1 -1
  54. package/dist/components/VCalendar/VCalendarYear.css +1 -1
  55. package/dist/components/VCalendar/VCalendarYear.d.ts +8 -1
  56. package/dist/components/VCalendar/VCalendarYear.js.map +1 -1
  57. package/dist/components/VCalendar/VCalendarYear.vue_vue_type_script_setup_true_lang.js +39 -32
  58. package/dist/components/VCalendar/VCalendarYear.vue_vue_type_script_setup_true_lang.js.map +1 -1
  59. package/dist/components/VCalendar/color.d.ts +1 -1
  60. package/dist/components/VCalendar/color.js.map +1 -1
  61. package/dist/components/VCalendar/edgeStep.d.ts +3 -3
  62. package/dist/components/VCalendar/edgeStep.js +5 -0
  63. package/dist/components/VCalendar/edgeStep.js.map +1 -1
  64. package/dist/components/VCalendar/gesture.d.ts +10 -9
  65. package/dist/components/VCalendar/gesture.js +60 -45
  66. package/dist/components/VCalendar/gesture.js.map +1 -1
  67. package/dist/components/VCalendar/keyboard.d.ts +22 -5
  68. package/dist/components/VCalendar/keyboard.js +17 -16
  69. package/dist/components/VCalendar/keyboard.js.map +1 -1
  70. package/dist/components/VCalendar/layout.d.ts +47 -37
  71. package/dist/components/VCalendar/layout.js +47 -37
  72. package/dist/components/VCalendar/layout.js.map +1 -1
  73. package/dist/components/VCalendar/timeGrid.d.ts +4 -4
  74. package/dist/components/VCalendar/timeGrid.js +6 -6
  75. package/dist/components/VCalendar/timeGrid.js.map +1 -1
  76. package/dist/components/VCalendar/types.d.ts +5 -5
  77. package/dist/components/VCarousel/VCarousel.css +1 -1
  78. package/dist/components/VCarousel/VCarousel.d.ts +59 -38
  79. package/dist/components/VCarousel/VCarousel.js.map +1 -1
  80. package/dist/components/VCarousel/VCarousel.vue_vue_type_script_setup_true_lang.js +161 -132
  81. package/dist/components/VCarousel/VCarousel.vue_vue_type_script_setup_true_lang.js.map +1 -1
  82. package/dist/components/VCarousel/VCarouselItem.d.ts +1 -1
  83. package/dist/components/VCarousel/VCarouselItem.js.map +1 -1
  84. package/dist/components/VCarousel/VCarouselItem.vue_vue_type_script_setup_true_lang.js.map +1 -1
  85. package/dist/components/VCarousel/context.d.ts +1 -1
  86. package/dist/components/VCarousel/context.js.map +1 -1
  87. package/dist/components/VCheckbox/VCheckbox.css +1 -1
  88. package/dist/components/VCheckbox/VCheckbox.d.ts +2 -2
  89. package/dist/components/VCheckbox/VCheckbox.js.map +1 -1
  90. package/dist/components/VCheckbox/VCheckbox.vue_vue_type_script_setup_true_lang.js +10 -8
  91. package/dist/components/VCheckbox/VCheckbox.vue_vue_type_script_setup_true_lang.js.map +1 -1
  92. package/dist/components/VChip/VChip.css +1 -1
  93. package/dist/components/VChip/VChip.d.ts +7 -2
  94. package/dist/components/VChip/VChip.js.map +1 -1
  95. package/dist/components/VChip/VChip.vue_vue_type_script_setup_true_lang.js +69 -55
  96. package/dist/components/VChip/VChip.vue_vue_type_script_setup_true_lang.js.map +1 -1
  97. package/dist/components/VCombobox/VCombobox.css +1 -1
  98. package/dist/components/VCombobox/VCombobox.d.ts +50 -36
  99. package/dist/components/VCombobox/VCombobox.js.map +1 -1
  100. package/dist/components/VCombobox/VCombobox.vue_vue_type_script_setup_true_lang.js +167 -161
  101. package/dist/components/VCombobox/VCombobox.vue_vue_type_script_setup_true_lang.js.map +1 -1
  102. package/dist/components/VCombobox/VComboboxGroup.css +1 -1
  103. package/dist/components/VCombobox/VComboboxGroup.js.map +1 -1
  104. package/dist/components/VCombobox/VComboboxGroup.vue_vue_type_script_setup_true_lang.js +1 -1
  105. package/dist/components/VCombobox/VComboboxGroup.vue_vue_type_script_setup_true_lang.js.map +1 -1
  106. package/dist/components/VCombobox/infiniteScroll.d.ts +12 -3
  107. package/dist/components/VCombobox/infiniteScroll.js +18 -12
  108. package/dist/components/VCombobox/infiniteScroll.js.map +1 -1
  109. package/dist/components/VDataTable/VDataTable.css +1 -1
  110. package/dist/components/VDataTable/VDataTable.d.ts +55 -24
  111. package/dist/components/VDataTable/VDataTable.js.map +1 -1
  112. package/dist/components/VDataTable/VDataTable.vue_vue_type_script_setup_true_lang.js +192 -155
  113. package/dist/components/VDataTable/VDataTable.vue_vue_type_script_setup_true_lang.js.map +1 -1
  114. package/dist/components/VDateInput/VDateInput.css +1 -1
  115. package/dist/components/VDateInput/VDateInput.d.ts +15 -12
  116. package/dist/components/VDateInput/VDateInput.js.map +1 -1
  117. package/dist/components/VDateInput/VDateInput.vue_vue_type_script_setup_true_lang.js +180 -160
  118. package/dist/components/VDateInput/VDateInput.vue_vue_type_script_setup_true_lang.js.map +1 -1
  119. package/dist/components/VDateInput/mask.d.ts +95 -0
  120. package/dist/components/VDateInput/mask.js +118 -0
  121. package/dist/components/VDateInput/mask.js.map +1 -0
  122. package/dist/components/VDatePicker/VDatePicker.css +1 -1
  123. package/dist/components/VDatePicker/VDatePicker.d.ts +6 -5
  124. package/dist/components/VDatePicker/VDatePicker.js.map +1 -1
  125. package/dist/components/VDatePicker/VDatePicker.vue_vue_type_script_setup_true_lang.js +204 -173
  126. package/dist/components/VDatePicker/VDatePicker.vue_vue_type_script_setup_true_lang.js.map +1 -1
  127. package/dist/components/VDatePicker/keyboard.d.ts +3 -3
  128. package/dist/components/VDatePicker/keyboard.js.map +1 -1
  129. package/dist/components/VDatePicker/names.d.ts +34 -0
  130. package/dist/components/VDatePicker/names.js +42 -0
  131. package/dist/components/VDatePicker/names.js.map +1 -0
  132. package/dist/components/VDialog/VDialog.css +1 -1
  133. package/dist/components/VDialog/VDialog.d.ts +2 -2
  134. package/dist/components/VDialog/VDialog.js.map +1 -1
  135. package/dist/components/VDialog/VDialog.vue_vue_type_script_setup_true_lang.js +63 -41
  136. package/dist/components/VDialog/VDialog.vue_vue_type_script_setup_true_lang.js.map +1 -1
  137. package/dist/components/VFileInput/VFileInput.d.ts +38 -25
  138. package/dist/components/VFileInput/VFileInput.js.map +1 -1
  139. package/dist/components/VFileInput/VFileInput.vue_vue_type_script_setup_true_lang.js +74 -71
  140. package/dist/components/VFileInput/VFileInput.vue_vue_type_script_setup_true_lang.js.map +1 -1
  141. package/dist/components/VFileInput/truncate.d.ts +4 -4
  142. package/dist/components/VFileInput/truncate.js.map +1 -1
  143. package/dist/components/VFilePicker/VFilePicker.css +1 -1
  144. package/dist/components/VFilePicker/VFilePicker.d.ts +54 -37
  145. package/dist/components/VFilePicker/VFilePicker.js.map +1 -1
  146. package/dist/components/VFilePicker/VFilePicker.vue_vue_type_script_setup_true_lang.js +152 -135
  147. package/dist/components/VFilePicker/VFilePicker.vue_vue_type_script_setup_true_lang.js.map +1 -1
  148. package/dist/components/VFilePicker/fileKind.d.ts +2 -2
  149. package/dist/components/VFilePicker/fileKind.js.map +1 -1
  150. package/dist/components/VHotkeys/VHotkeys.css +1 -1
  151. package/dist/components/VHotkeys/VHotkeys.d.ts +10 -8
  152. package/dist/components/VHotkeys/VHotkeys.js.map +1 -1
  153. package/dist/components/VHotkeys/VHotkeys.vue_vue_type_script_setup_true_lang.js +22 -20
  154. package/dist/components/VHotkeys/VHotkeys.vue_vue_type_script_setup_true_lang.js.map +1 -1
  155. package/dist/components/VHotkeys/platform.d.ts +9 -7
  156. package/dist/components/VHotkeys/platform.js +41 -30
  157. package/dist/components/VHotkeys/platform.js.map +1 -1
  158. package/dist/components/VIcon/VIcon.css +1 -1
  159. package/dist/components/VIcon/VIcon.d.ts +6 -6
  160. package/dist/components/VIcon/VIcon.js.map +1 -1
  161. package/dist/components/VIcon/VIcon.vue_vue_type_script_setup_true_lang.js.map +1 -1
  162. package/dist/components/VIcon/iconProps.d.ts +4 -4
  163. package/dist/components/VIcon/iconProps.js.map +1 -1
  164. package/dist/components/VIcon/icons/index.d.ts +1 -1
  165. package/dist/components/VIcon/icons/index.js.map +1 -1
  166. package/dist/components/VIcon/icons/names.d.ts +1 -1
  167. package/dist/components/VIcon/icons/names.js.map +1 -1
  168. package/dist/components/VIcon/resolver.d.ts +3 -3
  169. package/dist/components/VIcon/resolver.js +23 -20
  170. package/dist/components/VIcon/resolver.js.map +1 -1
  171. package/dist/components/VIcon/types.d.ts +4 -4
  172. package/dist/components/VIconButton/VIconButton.d.ts +4 -4
  173. package/dist/components/VIconButton/VIconButton.js.map +1 -1
  174. package/dist/components/VIconButton/VIconButton.vue_vue_type_script_setup_true_lang.js.map +1 -1
  175. package/dist/components/VInput/VInput.d.ts +16 -8
  176. package/dist/components/VInput/VInput.js.map +1 -1
  177. package/dist/components/VInput/VInput.vue_vue_type_script_setup_true_lang.js +22 -16
  178. package/dist/components/VInput/VInput.vue_vue_type_script_setup_true_lang.js.map +1 -1
  179. package/dist/components/VInput/VInputGroup.css +1 -1
  180. package/dist/components/VInput/VInputGroup.js.map +1 -1
  181. package/dist/components/VInput/VInputGroup.vue_vue_type_script_setup_true_lang.js +43 -28
  182. package/dist/components/VInput/VInputGroup.vue_vue_type_script_setup_true_lang.js.map +1 -1
  183. package/dist/components/VInputOTP/VInputOTP.css +1 -1
  184. package/dist/components/VInputOTP/VInputOTP.d.ts +3 -3
  185. package/dist/components/VInputOTP/VInputOTP.js.map +1 -1
  186. package/dist/components/VInputOTP/VInputOTP.vue_vue_type_script_setup_true_lang.js +152 -85
  187. package/dist/components/VInputOTP/VInputOTP.vue_vue_type_script_setup_true_lang.js.map +1 -1
  188. package/dist/components/VMenu/VMenu.d.ts +4 -4
  189. package/dist/components/VMenu/VMenu.js.map +1 -1
  190. package/dist/components/VMenu/VMenu.vue_vue_type_script_setup_true_lang.js.map +1 -1
  191. package/dist/components/VMenu/VMenuGroup.css +1 -1
  192. package/dist/components/VMenu/VMenuGroup.js.map +1 -1
  193. package/dist/components/VMenu/VMenuGroup.vue_vue_type_script_setup_true_lang.js +18 -11
  194. package/dist/components/VMenu/VMenuGroup.vue_vue_type_script_setup_true_lang.js.map +1 -1
  195. package/dist/components/VMenu/VMenuItem.css +1 -1
  196. package/dist/components/VMenu/VMenuItem.d.ts +6 -6
  197. package/dist/components/VMenu/VMenuItem.js.map +1 -1
  198. package/dist/components/VMenu/VMenuItem.vue_vue_type_script_setup_true_lang.js +83 -69
  199. package/dist/components/VMenu/VMenuItem.vue_vue_type_script_setup_true_lang.js.map +1 -1
  200. package/dist/components/VMenu/VMenuPanel.css +1 -1
  201. package/dist/components/VMenu/VMenuPanel.d.ts +2 -2
  202. package/dist/components/VMenu/VMenuPanel.js.map +1 -1
  203. package/dist/components/VMenu/VMenuPanel.vue_vue_type_script_setup_true_lang.js +56 -55
  204. package/dist/components/VMenu/VMenuPanel.vue_vue_type_script_setup_true_lang.js.map +1 -1
  205. package/dist/components/VMenu/context.d.ts +2 -2
  206. package/dist/components/VMenu/context.js.map +1 -1
  207. package/dist/components/VPagination/VPagination.css +1 -1
  208. package/dist/components/VPagination/VPagination.d.ts +22 -9
  209. package/dist/components/VPagination/VPagination.js.map +1 -1
  210. package/dist/components/VPagination/VPagination.vue_vue_type_script_setup_true_lang.js +67 -57
  211. package/dist/components/VPagination/VPagination.vue_vue_type_script_setup_true_lang.js.map +1 -1
  212. package/dist/components/VPopover/VPopover.css +1 -1
  213. package/dist/components/VPopover/VPopover.d.ts +1 -1
  214. package/dist/components/VPopover/VPopover.js.map +1 -1
  215. package/dist/components/VPopover/VPopover.vue_vue_type_script_setup_true_lang.js.map +1 -1
  216. package/dist/components/VProgressCircular/VProgressCircular.css +1 -1
  217. package/dist/components/VProgressCircular/VProgressCircular.d.ts +12 -7
  218. package/dist/components/VProgressCircular/VProgressCircular.js.map +1 -1
  219. package/dist/components/VProgressCircular/VProgressCircular.vue_vue_type_script_setup_true_lang.js.map +1 -1
  220. package/dist/components/VProgressLinear/VProgressLinear.css +1 -1
  221. package/dist/components/VProgressLinear/VProgressLinear.d.ts +15 -10
  222. package/dist/components/VProgressLinear/VProgressLinear.js.map +1 -1
  223. package/dist/components/VProgressLinear/VProgressLinear.vue_vue_type_script_setup_true_lang.js.map +1 -1
  224. package/dist/components/VRadio/VRadio.css +1 -1
  225. package/dist/components/VRadio/VRadio.js.map +1 -1
  226. package/dist/components/VRadio/VRadio.vue_vue_type_script_setup_true_lang.js +3 -3
  227. package/dist/components/VRadio/VRadio.vue_vue_type_script_setup_true_lang.js.map +1 -1
  228. package/dist/components/VSeparator/VSeparator.d.ts +1 -1
  229. package/dist/components/VSeparator/VSeparator.js.map +1 -1
  230. package/dist/components/VSeparator/VSeparator.vue_vue_type_script_setup_true_lang.js.map +1 -1
  231. package/dist/components/VSideNavigation/VSideNavigation.d.ts +2 -2
  232. package/dist/components/VSideNavigation/VSideNavigation.js.map +1 -1
  233. package/dist/components/VSideNavigation/VSideNavigation.vue_vue_type_script_setup_true_lang.js +1 -1
  234. package/dist/components/VSideNavigation/VSideNavigation.vue_vue_type_script_setup_true_lang.js.map +1 -1
  235. package/dist/components/VSideNavigation/VSideNavigationGroup.css +1 -1
  236. package/dist/components/VSideNavigation/VSideNavigationGroup.js.map +1 -1
  237. package/dist/components/VSideNavigation/VSideNavigationGroup.vue_vue_type_script_setup_true_lang.js +1 -1
  238. package/dist/components/VSideNavigation/VSideNavigationGroup.vue_vue_type_script_setup_true_lang.js.map +1 -1
  239. package/dist/components/VSideNavigation/VSideNavigationItem.css +1 -1
  240. package/dist/components/VSideNavigation/VSideNavigationItem.d.ts +12 -13
  241. package/dist/components/VSideNavigation/VSideNavigationItem.js.map +1 -1
  242. package/dist/components/VSideNavigation/VSideNavigationItem.vue_vue_type_script_setup_true_lang.js +87 -68
  243. package/dist/components/VSideNavigation/VSideNavigationItem.vue_vue_type_script_setup_true_lang.js.map +1 -1
  244. package/dist/components/VSkeletonLoader/VSkeletonLoader.css +1 -1
  245. package/dist/components/VSkeletonLoader/VSkeletonLoader.d.ts +10 -7
  246. package/dist/components/VSkeletonLoader/VSkeletonLoader.js.map +1 -1
  247. package/dist/components/VSkeletonLoader/VSkeletonLoader.vue_vue_type_script_setup_true_lang.js +5 -5
  248. package/dist/components/VSkeletonLoader/VSkeletonLoader.vue_vue_type_script_setup_true_lang.js.map +1 -1
  249. package/dist/components/VSlider/VSlider.css +1 -1
  250. package/dist/components/VSlider/VSlider.d.ts +21 -7
  251. package/dist/components/VSlider/VSlider.js.map +1 -1
  252. package/dist/components/VSlider/VSlider.vue_vue_type_script_setup_true_lang.js +159 -140
  253. package/dist/components/VSlider/VSlider.vue_vue_type_script_setup_true_lang.js.map +1 -1
  254. package/dist/components/VSnackbar/VSnackbar.css +1 -1
  255. package/dist/components/VSnackbar/VSnackbar.d.ts +4 -4
  256. package/dist/components/VSnackbar/VSnackbar.js.map +1 -1
  257. package/dist/components/VSnackbar/VSnackbar.vue_vue_type_script_setup_true_lang.js +85 -59
  258. package/dist/components/VSnackbar/VSnackbar.vue_vue_type_script_setup_true_lang.js.map +1 -1
  259. package/dist/components/VSnackbar/state.d.ts +7 -7
  260. package/dist/components/VSnackbar/state.js +13 -11
  261. package/dist/components/VSnackbar/state.js.map +1 -1
  262. package/dist/components/VSpinner/VSpinner.css +1 -1
  263. package/dist/components/VSpinner/VSpinner.js.map +1 -1
  264. package/dist/components/VSpinner/VSpinner.vue_vue_type_script_setup_true_lang.js.map +1 -1
  265. package/dist/components/VSwitch/VSwitch.css +1 -1
  266. package/dist/components/VSwitch/VSwitch.d.ts +1 -1
  267. package/dist/components/VSwitch/VSwitch.js.map +1 -1
  268. package/dist/components/VSwitch/VSwitch.vue_vue_type_script_setup_true_lang.js +4 -4
  269. package/dist/components/VSwitch/VSwitch.vue_vue_type_script_setup_true_lang.js.map +1 -1
  270. package/dist/components/VTabs/VTab.css +1 -1
  271. package/dist/components/VTabs/VTab.d.ts +4 -0
  272. package/dist/components/VTabs/VTab.js.map +1 -1
  273. package/dist/components/VTabs/VTab.vue_vue_type_script_setup_true_lang.js +9 -8
  274. package/dist/components/VTabs/VTab.vue_vue_type_script_setup_true_lang.js.map +1 -1
  275. package/dist/components/VTabs/VTabs.css +1 -1
  276. package/dist/components/VTabs/VTabs.d.ts +17 -7
  277. package/dist/components/VTabs/VTabs.js.map +1 -1
  278. package/dist/components/VTabs/VTabs.vue_vue_type_script_setup_true_lang.js +84 -77
  279. package/dist/components/VTabs/VTabs.vue_vue_type_script_setup_true_lang.js.map +1 -1
  280. package/dist/components/VTextarea/VTextarea.d.ts +8 -8
  281. package/dist/components/VTextarea/VTextarea.js.map +1 -1
  282. package/dist/components/VTextarea/VTextarea.vue_vue_type_script_setup_true_lang.js +71 -69
  283. package/dist/components/VTextarea/VTextarea.vue_vue_type_script_setup_true_lang.js.map +1 -1
  284. package/dist/components/VTimeInput/VTimeInput.css +1 -1
  285. package/dist/components/VTimeInput/VTimeInput.d.ts +21 -12
  286. package/dist/components/VTimeInput/VTimeInput.js.map +1 -1
  287. package/dist/components/VTimeInput/VTimeInput.vue_vue_type_script_setup_true_lang.js +230 -206
  288. package/dist/components/VTimeInput/VTimeInput.vue_vue_type_script_setup_true_lang.js.map +1 -1
  289. package/dist/components/VTimeInput/search.d.ts +17 -2
  290. package/dist/components/VTimeInput/search.js +19 -9
  291. package/dist/components/VTimeInput/search.js.map +1 -1
  292. package/dist/components/VTimePicker/VTimePicker.css +1 -1
  293. package/dist/components/VTimePicker/VTimePicker.d.ts +8 -7
  294. package/dist/components/VTimePicker/VTimePicker.js.map +1 -1
  295. package/dist/components/VTimePicker/VTimePicker.vue_vue_type_script_setup_true_lang.js +128 -106
  296. package/dist/components/VTimePicker/VTimePicker.vue_vue_type_script_setup_true_lang.js.map +1 -1
  297. package/dist/components/VTimePicker/limits.d.ts +11 -4
  298. package/dist/components/VTimePicker/limits.js +3 -2
  299. package/dist/components/VTimePicker/limits.js.map +1 -1
  300. package/dist/components/VToast/VToast.css +1 -1
  301. package/dist/components/VToast/VToast.js.map +1 -1
  302. package/dist/components/VToast/VToast.vue_vue_type_script_setup_true_lang.js +33 -37
  303. package/dist/components/VToast/VToast.vue_vue_type_script_setup_true_lang.js.map +1 -1
  304. package/dist/components/VToast/VToaster.js.map +1 -1
  305. package/dist/components/VToast/VToaster.vue_vue_type_script_setup_true_lang.js +91 -61
  306. package/dist/components/VToast/VToaster.vue_vue_type_script_setup_true_lang.js.map +1 -1
  307. package/dist/components/VToast/state.d.ts +8 -6
  308. package/dist/components/VToast/state.js +15 -13
  309. package/dist/components/VToast/state.js.map +1 -1
  310. package/dist/components/VToggle/VToggle.css +1 -1
  311. package/dist/components/VToggle/VToggle.d.ts +9 -4
  312. package/dist/components/VToggle/VToggle.js.map +1 -1
  313. package/dist/components/VToggle/VToggle.vue_vue_type_script_setup_true_lang.js +2 -1
  314. package/dist/components/VToggle/VToggle.vue_vue_type_script_setup_true_lang.js.map +1 -1
  315. package/dist/components/VToggle/VToggleItem.d.ts +4 -0
  316. package/dist/components/VToggle/VToggleItem.js.map +1 -1
  317. package/dist/components/VToggle/VToggleItem.vue_vue_type_script_setup_true_lang.js +5 -5
  318. package/dist/components/VToggle/VToggleItem.vue_vue_type_script_setup_true_lang.js.map +1 -1
  319. package/dist/components/VTooltip/VTooltip.css +1 -1
  320. package/dist/components/VTooltip/VTooltip.d.ts +17 -10
  321. package/dist/components/VTooltip/VTooltip.js.map +1 -1
  322. package/dist/components/VTooltip/VTooltip.vue_vue_type_script_setup_true_lang.js +46 -26
  323. package/dist/components/VTooltip/VTooltip.vue_vue_type_script_setup_true_lang.js.map +1 -1
  324. package/dist/components/VTypography/VTypography.css +1 -1
  325. package/dist/components/VTypography/VTypography.d.ts +6 -4
  326. package/dist/components/VTypography/VTypography.js.map +1 -1
  327. package/dist/components/VTypography/VTypography.vue_vue_type_script_setup_true_lang.js.map +1 -1
  328. package/dist/composables/useAriaLabel.js +1 -1
  329. package/dist/composables/useAriaLabel.js.map +1 -1
  330. package/dist/composables/useClearable.d.ts +2 -2
  331. package/dist/composables/useClearable.js.map +1 -1
  332. package/dist/composables/useDetailsOpen.d.ts +3 -3
  333. package/dist/composables/useDetailsOpen.js +14 -12
  334. package/dist/composables/useDetailsOpen.js.map +1 -1
  335. package/dist/composables/useFieldIds.d.ts +2 -1
  336. package/dist/composables/useFieldIds.js +6 -5
  337. package/dist/composables/useFieldIds.js.map +1 -1
  338. package/dist/composables/useFieldPanel.d.ts +2 -2
  339. package/dist/composables/useFieldPanel.js +47 -37
  340. package/dist/composables/useFieldPanel.js.map +1 -1
  341. package/dist/composables/useFileDrop.js +3 -3
  342. package/dist/composables/useFileDrop.js.map +1 -1
  343. package/dist/composables/useFileField.d.ts +1 -1
  344. package/dist/composables/useFileField.js +62 -41
  345. package/dist/composables/useFileField.js.map +1 -1
  346. package/dist/composables/useIconClickHandlers.d.ts +3 -3
  347. package/dist/composables/useIconClickHandlers.js +14 -13
  348. package/dist/composables/useIconClickHandlers.js.map +1 -1
  349. package/dist/composables/useInertLink.js +12 -10
  350. package/dist/composables/useInertLink.js.map +1 -1
  351. package/dist/composables/useLiveAnnouncer.d.ts +5 -0
  352. package/dist/composables/useLiveAnnouncer.js +23 -0
  353. package/dist/composables/useLiveAnnouncer.js.map +1 -0
  354. package/dist/composables/useMaskedField.d.ts +5 -5
  355. package/dist/composables/useMaskedField.js.map +1 -1
  356. package/dist/composables/usePopover.d.ts +3 -3
  357. package/dist/composables/usePopover.js +6 -4
  358. package/dist/composables/usePopover.js.map +1 -1
  359. package/dist/composables/useProgressValue.js +11 -2
  360. package/dist/composables/useProgressValue.js.map +1 -1
  361. package/dist/composables/useRootAttrs.d.ts +1 -1
  362. package/dist/composables/useRootAttrs.js.map +1 -1
  363. package/dist/composables/useSlotNodes.d.ts +18 -0
  364. package/dist/composables/useSlotNodes.js +13 -0
  365. package/dist/composables/useSlotNodes.js.map +1 -0
  366. package/dist/composables/useTextLimit.d.ts +2 -1
  367. package/dist/composables/useTextLimit.js +2 -2
  368. package/dist/composables/useTextLimit.js.map +1 -1
  369. package/dist/composables/useTimer.d.ts +5 -0
  370. package/dist/composables/useTimer.js +22 -11
  371. package/dist/composables/useTimer.js.map +1 -1
  372. package/dist/i18n/en.js +1 -1
  373. package/dist/i18n/en.js.map +1 -1
  374. package/dist/i18n/fr.js +14 -14
  375. package/dist/i18n/fr.js.map +1 -1
  376. package/dist/i18n/state.d.ts +7 -7
  377. package/dist/i18n/state.js +37 -28
  378. package/dist/i18n/state.js.map +1 -1
  379. package/dist/i18n/types.d.ts +12 -12
  380. package/dist/icons.d.ts +2 -2
  381. package/dist/index.d.ts +12 -11
  382. package/dist/styles.css +1 -1
  383. package/dist/tokens/css.d.ts +1 -1
  384. package/dist/tokens/css.js.map +1 -1
  385. package/dist/tokens/index.d.ts +6 -0
  386. package/dist/tokens/semantic.d.ts +6 -0
  387. package/dist/tokens/semantic.js +66 -60
  388. package/dist/tokens/semantic.js.map +1 -1
  389. package/dist/tokens/themes/dark.js +3 -3
  390. package/dist/tokens/themes/dark.js.map +1 -1
  391. package/dist/tokens.json +130 -66
  392. package/dist/types.d.ts +1 -1
  393. package/dist/utils/arrowNav.d.ts +4 -1
  394. package/dist/utils/arrowNav.js +7 -7
  395. package/dist/utils/arrowNav.js.map +1 -1
  396. package/dist/utils/chip.d.ts +1 -1
  397. package/dist/utils/chip.js.map +1 -1
  398. package/dist/utils/clock.d.ts +113 -0
  399. package/dist/utils/clock.js +84 -0
  400. package/dist/utils/clock.js.map +1 -0
  401. package/dist/utils/css.d.ts +6 -4
  402. package/dist/utils/css.js +2 -2
  403. package/dist/utils/css.js.map +1 -1
  404. package/dist/utils/date.d.ts +7 -102
  405. package/dist/utils/date.js +33 -160
  406. package/dist/utils/date.js.map +1 -1
  407. package/dist/utils/direction.d.ts +1 -1
  408. package/dist/utils/direction.js.map +1 -1
  409. package/dist/utils/env.d.ts +12 -3
  410. package/dist/utils/env.js +6 -0
  411. package/dist/utils/env.js.map +1 -0
  412. package/dist/utils/file.d.ts +3 -3
  413. package/dist/utils/file.js +1 -1
  414. package/dist/utils/file.js.map +1 -1
  415. package/dist/utils/focus.d.ts +1 -1
  416. package/dist/utils/focus.js.map +1 -1
  417. package/dist/utils/hostWarns.d.ts +1 -1
  418. package/dist/utils/hostWarns.js.map +1 -1
  419. package/dist/utils/ids.d.ts +1 -1
  420. package/dist/utils/ids.js.map +1 -1
  421. package/dist/utils/matcher.d.ts +2 -2
  422. package/dist/utils/matcher.js.map +1 -1
  423. package/dist/utils/memo.d.ts +1 -1
  424. package/dist/utils/memo.js.map +1 -1
  425. package/dist/utils/text.d.ts +3 -3
  426. package/dist/utils/text.js.map +1 -1
  427. package/dist/utils/time.d.ts +2 -101
  428. package/dist/utils/time.js +22 -98
  429. package/dist/utils/time.js.map +1 -1
  430. package/dist/utils/vnode.d.ts +5 -3
  431. package/dist/utils/vnode.js.map +1 -1
  432. package/package.json +2 -2
@@ -1 +1 @@
1
- {"version":3,"file":"gesture.js","names":[],"sources":["../../../src/components/VCalendar/gesture.ts"],"sourcesContent":["// @keyboard @a11y @core\n/**\n * What the two grids' drag engines share, written once.\n *\n * VCalendarMonth and VCalendarTimeGrid both let an event be picked up, moved and dropped —\n * with a pointer and with the keyboard. Everything that does not depend on what a CELL is\n * lives here: the gesture state and its ghost, the pointer's move, release and cancel, the\n * capture, paging at an edge, the keyboard grab, drop and cancel, the focus handed back to a\n * card, and the flag that stops a drop from also reading as a click.\n *\n * What is NOT here is what genuinely differs, which is also why the two components exist\n * separately: turning a point into a cell (a day square on one side, a day and a minute on\n * the other), working out the new times from it, and the gesture kinds each grid adds. Those\n * stay with each grid, as hooks this composable calls, and the pure half of them is already\n * in `layout.ts`.\n *\n * It lives in the component's folder rather than in `composables/`, the `edgeStep.ts` and\n * `VCombobox/infiniteScroll.ts` arrangement: both consumers are inside this component, so it\n * fails the admission rule that folder keeps.\n */\nimport { computed, nextTick, ref, watch } from 'vue'\nimport type { Ref } from 'vue'\n\nimport { isRtl as isElementRtl } from '../../utils/direction'\n\nimport { useMessages } from '../../i18n/state'\n\nimport { EDGE_BAND, useEdgeStep } from './edgeStep'\nimport { calendarIntent, type CalendarIntent } from './keyboard'\nimport { DRAG_THRESHOLD, inlineEdgeAt, pointWithin, type GridGeometry } from './layout'\nimport type { CalendarEvent, CalendarEventId, CalendarEventTimes } from './types'\n\n/**\n * The prefix marking the copy an event leaves behind at its old place while it is being\n * dragged. It is written into the id rather than held beside it so that the ghost travels\n * through the same list, the same layout and the same `v-for` key as everything else.\n */\nconst GHOST_PREFIX = '__vectis-calendar-ghost__'\n\n/**\n * The id the ghost of a dragged event carries. It has to DIFFER from the event's own, or the\n * two would collide in every map the layout keys by id and only one would ever be drawn.\n */\nexport const ghostIdOf = (id: CalendarEventId) => `${GHOST_PREFIX}${id}`\n/**\n * The dragged event's own id, read back off its ghost's. It is what the card is handed as\n * `ghostOf`: an event's colour is derived from its id, so a ghost coloured from its own\n * would not match the card it belongs to. `hueOf` reads a number and its digits as the same\n * event, so the string form returned here is enough.\n */\nexport const originalIdOf = (id: CalendarEventId) => String(id).slice(GHOST_PREFIX.length)\nexport const isGhostId = (id: CalendarEventId) => String(id).startsWith(GHOST_PREFIX)\n\n/**\n * The id a card belongs to, read back off the DOM.\n *\n * An id may be a NUMBER and an attribute is always text, so a numeric one has to be turned\n * back into one — otherwise every card of a numerically-keyed calendar would look up as a\n * miss and nothing would drag. Which of the two it is, is settled by asking the map that\n * holds the originals rather than by guessing from the text.\n */\nexport function cardIdOf(card: HTMLElement, has: (id: CalendarEventId) => boolean) {\n const raw = card.dataset.eventId ?? ''\n return has(raw) ? raw : Number(raw)\n}\n\n/**\n * A grid's measured box as the pure geometry wants it: plain numbers, no element.\n *\n * `inlineStart` is the edge the first column starts at, which is the RIGHT one in a\n * right-to-left page — which is also why containment never goes through this, see\n * `pointWithin`.\n */\nexport function gridGeometryOf(rect: DOMRect, columns: number, rtl: boolean): GridGeometry {\n return {\n top: rect.top,\n height: rect.height,\n inlineStart: rtl ? rect.right : rect.left,\n inlineSize: rect.width,\n columns,\n }\n}\n\n/** The state every gesture carries, whatever each grid adds to it. */\nexport interface GestureBase {\n id: CalendarEventId\n /**\n * Where the event was when the gesture began. Every pointer frame is computed from THIS and\n * never from the frame before it, so a long drag cannot accumulate rounding drift.\n */\n origin: CalendarEventTimes\n /** What the card shows right now. The model is not touched until the gesture ends. */\n preview: CalendarEventTimes\n /** The pointer holding the gesture, or null for a keyboard grab. */\n pointerId: number | null\n originX: number\n originY: number\n /**\n * Where the pointer last was. Two things move the calendar UNDER a still pointer — paging at\n * an edge, and auto-scrolling — and each has to work out afresh what the pointer is now over.\n */\n lastX: number\n lastY: number\n /** Whether it moved past the threshold, which is what separates a drag from a click. */\n moved: boolean\n /**\n * Whether the pointer is off the calendar altogether — over the toolbar, or over the page\n * beside it. Letting go there abandons the gesture whole and writes nothing.\n *\n * A KEYBOARD grab can never set it, and structurally rather than by a guard: `onPointermove`\n * is the only writer, and it returns on the id mismatch first — a grab's `pointerId` is null,\n * which no real pointer's id ever equals.\n */\n outside: boolean\n /**\n * The reading direction, read ONCE when the gesture begins. It cannot change under a live\n * drag, and asking the document on every frame costs a style resolution each time.\n */\n rtl: boolean\n}\n\n/** What a grid hands over to start a gesture; the rest is filled in here. */\nexport type GestureInit<G extends GestureBase> = Omit<\n G,\n 'preview' | 'lastX' | 'lastY' | 'moved' | 'outside' | 'rtl'\n>\n\n/**\n * A gesture held by the KEYBOARD rather than by a pointer: grabbed with Space, and waiting\n * for the arrows to move it. Both grids draw the card differently in that state, which is\n * what makes it worth a name.\n */\nexport const isGrabbed = (state: GestureBase | null) => state !== null && state.pointerId === null\n\n/** The two intents that move a grabbed event, which only a grid can turn into times. */\nexport type GrabStep = Extract<CalendarIntent, { kind: 'grabMove' | 'grabResize' }>\n\nexport interface CalendarGestureOptions<E extends CalendarEvent, G extends GestureBase> {\n /** Every event as it is currently drawn, the ghost's original among them. */\n events: () => readonly E[]\n /** The event drawn under an id, for the handlers. */\n eventOf: (id: CalendarEventId) => E | undefined\n /** The view's own box: what \"outside the calendar\" is measured against. */\n rootEl: Ref<HTMLElement | null>\n /**\n * The element the pointer is captured on once a press travels. It must contain every surface\n * a gesture can start on, and carry the move, up, cancel and leave bindings: capture retargets\n * every later pointer event to it, which is what makes one set of bindings serve every kind of\n * gesture.\n */\n captureEl: Ref<HTMLElement | null>\n /** The box the cells occupy, which points and edges are read against. */\n measureEl: Ref<HTMLElement | null>\n /** How many columns that box is divided into. */\n columns: () => number\n /** Whether events may be moved at all. */\n editable: () => boolean\n /** The node every card points at to say how it can be moved. */\n hintId: () => string\n /** The step a grabbed event moves by, handed to the keyboard table. */\n slotMinutes: () => number\n edgeStepDelay: () => number\n /** Whatever the grid's cells are made of, so paging under a still pointer re-places the card. */\n layout: () => unknown\n /** Works out where the gesture's event belongs from the pointer's last position. */\n applyPoint: (state: G, rect: DOMRect) => void\n /** Called on every pointer move past the threshold, after the edge watch, with both rects. */\n onEdges?: (state: G, rootRect: DOMRect | undefined) => void\n /** Everything else a gesture leaves running, dropped on every path out of one. */\n onRelease?: () => void\n /**\n * A pointer gesture let go inside the calendar. Returns true when the grid has answered it\n * itself — a slot drawn out — and nothing is left to drop.\n */\n onLetGo?: (state: G) => boolean\n /** A gesture that moved, committed: the grid reports the new times. */\n onDrop: (state: G) => void\n /** What a keyboard grab of this event starts, or null when it cannot be grabbed. */\n grab: (item: E) => GestureInit<G> | null\n /** Applies one arrow step to a grabbed event. Returns false when the step means nothing here. */\n onGrabStep: (state: G, step: GrabStep, item: E) => boolean\n step: (direction: -1 | 1) => void\n announce: (message: string) => void\n}\n\nexport function useCalendarGesture<E extends CalendarEvent, G extends GestureBase>(\n options: CalendarGestureOptions<E, G>,\n) {\n const m = useMessages()\n const gesture = ref<G | null>(null) as Ref<G | null>\n\n /** True while a card is being held by the keyboard rather than dragged by a pointer. */\n const grabbing = computed(() => isGrabbed(gesture.value))\n\n const isRtl = () => isElementRtl(options.measureEl.value)\n\n /**\n * The echo of where the gestured event began, so the reader can see what they are moving it\n * FROM. A press that has not travelled yet produces none, or a click would flash a second\n * card over the first.\n */\n const ghostEvent = computed<E | null>(() => {\n const state = gesture.value\n if (!state?.moved) return null\n const original = options.events().find((event) => event.id === state.id)\n return original ? ({ ...original, ...state.origin, id: ghostIdOf(state.id) } as E) : null\n })\n\n /**\n * A list with the gestured event moved to wherever it is now, plus its echo.\n *\n * The echo is listed whether or not it has a box to draw on, because this is what the id maps\n * are built from and the template reads a card's event back out of them. An echo whose day\n * the view has paged past simply produces no placement, as any event off show does.\n */\n function withPreview(events: readonly E[]): E[] {\n const state = gesture.value\n if (!state) return [...events]\n const moving = events.map((event) =>\n event.id === state.id ? ({ ...event, ...state.preview } as E) : event,\n )\n return ghostEvent.value ? [...moving, ghostEvent.value] : moving\n }\n\n /**\n * The flag that keeps a drop from also reading as a click.\n *\n * A pointer that moved past the threshold ends on a `click` the browser fires anyway, and\n * without this the card would be dropped AND opened. It is a plain variable rather than a\n * ref: nothing renders from it, and a reactive one would re-render the grid at the end of\n * every gesture for no visible change.\n *\n * TRAP — three writes, and each is load-bearing.\n *\n * `pointerup` SETS it, outside the calendar included, because `pointerup` fires before\n * `click`: an abandoned drag would otherwise end by opening the very event it refused to move.\n *\n * `pointercancel` does NOT, and must never share a helper with the release that does: no click\n * follows a cancel, so a `true` left behind there would swallow the next genuine one.\n *\n * Every press CLEARS it before any guard runs. The click that lowers it only reaches a card\n * when it lands on one, and drawing out a new event ends on a CELL, so the flag would stay up\n * — and a press that starts no gesture, which `creatable` without `editable` reaches every\n * time, would never overwrite it. The reader clicks an event, nothing happens, they click\n * again. Clearing at the press is what makes the flag unable to outlive its own interaction,\n * and the order is the argument: the click it exists to swallow follows its own `pointerup`\n * with no press in between.\n */\n let dragged = false\n\n /** Closes the books on the previous gesture. Every press handler calls it first. */\n function endLastGesture() {\n dragged = false\n }\n\n /** Whether the gesture that just ended actually moved; asking lowers the flag. */\n function consumeDrag() {\n const was = dragged\n dragged = false\n return was\n }\n\n const edge = useEdgeStep(options.step, options.edgeStepDelay)\n\n /** Which edge is counting down, as the attribute the stylesheet reads. */\n const edgeCue = computed(() =>\n edge.pending.value === -1 ? 'start' : edge.pending.value === 1 ? 'end' : undefined,\n )\n\n function release() {\n edge.cancel()\n options.onRelease?.()\n }\n\n /**\n * Starts a gesture. Every entry point funnels through here, so the rules that make a gesture\n * safe — one at a time, the origin captured once — are written once. The pointer itself is\n * only taken hold of once the press travels, in `onPointermove`.\n */\n function start(init: GestureInit<G>, rtl = isRtl()) {\n gesture.value = {\n ...init,\n preview: { ...init.origin },\n lastX: init.originX,\n lastY: init.originY,\n moved: false,\n outside: false,\n rtl,\n } as G\n }\n\n /**\n * Takes hold of the pointer on the capture element, so the drag keeps following it past the\n * calendar's edges.\n *\n * TRAP — called when the press crosses the drag threshold, NEVER at the press. The browser\n * sends the `click` that follows a captured `pointerup` to the CAPTURE element, so a press\n * captured at once reaches the scroller instead of the card or the cell under it: clicking an\n * event would open nothing and clicking an empty slot would report nothing, on every calendar\n * whose events can be moved or drawn. Neither jsdom nor a synthetic pointer event reproduces\n * the retargeting (a synthetic pointer cannot be captured), so the unit suite pins WHEN the\n * capture is asked for rather than where the click lands.\n */\n function capture(pointerId: number) {\n // @fallback\n /*\n * Wrapped because a pointer event fired by a TEST refers to no real pointer,\n * and the call then throws. Failing to capture merely means the drag stops at the edge of\n * the capture element, which no test is checking.\n */\n try {\n options.captureEl.value?.setPointerCapture(pointerId)\n } catch {\n /* a synthetic pointer: nothing to capture */\n }\n }\n\n /** Re-reads the measured box and works the gesture out again, for a caller outside a handler. */\n function reapply(state: G) {\n const rect = options.measureEl.value?.getBoundingClientRect()\n if (rect) options.applyPoint(state, rect)\n }\n\n function onPointermove(event: PointerEvent) {\n const state = gesture.value\n if (!state || state.pointerId !== event.pointerId) return\n\n state.lastX = event.clientX\n state.lastY = event.clientY\n\n // Below the threshold nothing has happened yet. That is what keeps a click a click: the\n // hand's tremor during a press would otherwise register as a one-pixel drag.\n if (\n !state.moved &&\n Math.abs(event.clientX - state.originX) < DRAG_THRESHOLD &&\n Math.abs(event.clientY - state.originY) < DRAG_THRESHOLD\n ) {\n return\n }\n\n if (!state.moved) capture(event.pointerId)\n state.moved = true\n // Each box is measured ONCE per move and handed to everything that reads it.\n const rootRect = options.rootEl.value?.getBoundingClientRect()\n const rect = options.measureEl.value?.getBoundingClientRect()\n\n /*\n * Outside is measured against the view's own box — never the cells' box, whose rect\n * excludes the day names, the all-day band and the hour gutter — and the rect goes in RAW:\n * containment has no reading direction, where `inlineStart` is the right edge in RTL.\n *\n * TRAP — neither the placement nor the edge watch below is gated on it, and neither may\n * become so. The card must keep following the pointer while it is out, which is what makes\n * coming back in seamless, and paging must keep running, pushing past the edge being how one\n * crosses into the next period. Being outside decides what happens on RELEASE, nothing else.\n */\n state.outside = rootRect ? !pointWithin({ x: state.lastX, y: state.lastY }, rootRect) : false\n\n if (!rect) return\n options.applyPoint(state, rect)\n edge.watchEdge(\n inlineEdgeAt(\n state.lastX,\n gridGeometryOf(rect, options.columns(), state.rtl),\n EDGE_BAND,\n state.rtl,\n ),\n )\n options.onEdges?.(state, rootRect)\n }\n\n function onPointerup(event: PointerEvent) {\n const state = gesture.value\n if (!state || state.pointerId !== event.pointerId) return\n gesture.value = null\n dragged = state.moved\n release()\n\n /*\n * Let go with the pointer off the calendar and the gesture is abandoned whole. Nothing is\n * announced: the pointer says nothing on a SUCCESSFUL drop either — `grabbed`, `dropped` and\n * `reverted` belong to the keyboard grab, which has no pointer to show where the event went.\n */\n if (state.outside) return\n if (options.onLetGo?.(state)) return\n // A press that never travelled is an ordinary click, which the button's own click event is\n // about to report. Writing anything here would move an event nobody dragged.\n if (state.moved) options.onDrop(state)\n }\n\n /*\n * The gesture was taken away — a system gesture, a context menu, the page starting to scroll.\n * Nothing is written and nothing is announced: the card goes back to where the model still\n * says it is.\n */\n function onPointercancel() {\n gesture.value = null\n release()\n }\n\n /*\n * A press that leaves the capture element before it has travelled far enough to be captured.\n * Its `pointerup` then lands outside and never reaches the bindings, so without this the\n * gesture would outlive the press: a mouse keeps the same pointer id, and bringing it back over\n * the calendar with the button up would pick the event up and carry it. A captured pointer\n * never leaves, so a real drag is untouched.\n */\n function onPointerleave(event: PointerEvent) {\n const state = gesture.value\n if (!state || state.pointerId !== event.pointerId || state.moved) return\n onPointercancel()\n }\n\n /*\n * Paging swaps the cells out from under a live drag, and the dragged event's day is then off\n * screen — the card would vanish until the next pointer move, which never comes if the hand is\n * holding still against the edge. Re-applying the last position once the new cells are\n * rendered is what keeps the card under the pointer across the boundary.\n */\n watch(\n options.layout,\n () => {\n const state = gesture.value\n if (state?.moved) reapply(state)\n },\n { flush: 'post' },\n )\n\n /**\n * Hands the focus back to a card once it has landed somewhere else, which the re-render has\n * just taken it from.\n *\n * TRAP — the card is found by WALKING the cards rather than by building an attribute\n * selector. An id belongs to the consumer, so it may hold a quote or a backslash a selector\n * would need escaped, and `CSS.escape` cannot do that escaping here: jsdom defines no `CSS`\n * object at all, so the call threw on every keyboard grab, from inside a `nextTick` where\n * nothing could catch it — an unhandled rejection, which fails the run while every assertion\n * still passes. Comparing the attribute's own text sidesteps the question, `data-event-id`\n * being written as exactly `String(event.id)`.\n */\n function refocusCard(id: CalendarEventId) {\n void nextTick(() => {\n const cards = options.measureEl.value?.querySelectorAll<HTMLElement>('.v-calendar-event')\n Array.from(cards ?? [])\n .find((card) => card.dataset.eventId === String(id))\n ?.focus()\n })\n }\n\n /** Puts the focus on a cell by its id, once the render that made it tabbable has run. */\n function focusCell(id: string, deferred = false) {\n const move = () => document.getElementById(id)?.focus()\n if (deferred) void nextTick(move)\n else move()\n }\n\n /** The event a card stands for, read back off the attribute the card publishes. */\n const idOfCard = (card: HTMLElement) => cardIdOf(card, (id) => options.eventOf(id) !== undefined)\n\n /**\n * A card answers a different table from the grid it sits in — that is what a grab mode IS.\n * Without it the grid would offer a gesture the pointer alone could reach (WCAG 2.1.1).\n */\n function onCardKeydown(event: KeyboardEvent, card: HTMLElement) {\n const item = options.eventOf(idOfCard(card))\n if (!item) return\n\n const held = grabbing.value && gesture.value?.id === item.id\n const state = held ? gesture.value! : null\n const intent = calendarIntent(\n event.key,\n event.shiftKey,\n held ? 'grabbed' : 'event',\n options.slotMinutes(),\n state?.rtl ?? isRtl(),\n )\n if (!intent) return\n\n if (!state) {\n // An event that cannot be moved keeps a button's ordinary behaviour: Space presses it,\n // which the card's click handler reports.\n const init = intent.kind === 'grab' ? options.grab(item) : null\n if (!init) return\n /*\n * Space is ALSO how a button is pressed, on its release. Cancelling the keydown is what\n * stops that press, so the keystroke that takes hold of the event does not open it too:\n * without it every attempt to move something would fire the consumer's editor over it.\n */\n event.preventDefault()\n start(init)\n options.announce(m.value.calendar.grabbed)\n return\n }\n\n event.preventDefault()\n\n if (intent.kind === 'grabMove' || intent.kind === 'grabResize') {\n if (!options.onGrabStep(state, intent, item)) return\n state.moved = true\n refocusCard(state.id)\n return\n }\n\n if (intent.kind === 'activate') {\n gesture.value = null\n if (state.moved) options.onDrop(state)\n options.announce(m.value.calendar.dropped)\n refocusCard(state.id)\n return\n }\n\n if (intent.kind === 'cancel') {\n gesture.value = null\n options.announce(m.value.calendar.reverted)\n refocusCard(state.id)\n }\n }\n\n /**\n * The five things every card is told about the gesture, bound with `v-bind` so the two grids\n * cannot describe the same state in two different ways.\n */\n function cardState(id: CalendarEventId) {\n const state = gesture.value\n const mine = state !== null && state.id === id\n return {\n /*\n * TRAP — only once the press has travelled. A dragged card takes no pointer events, so\n * marked at the press it lets the release land on the cell beneath it: the click then goes\n * to that cell, and clicking an event reports an empty slot instead of opening it.\n */\n dragging: mine && state.pointerId !== null && state.moved,\n rejected: mine && state.outside,\n grabbed: mine && state.pointerId === null,\n hintId: options.editable() && !isGhostId(id) ? options.hintId() : undefined,\n ghostOf: isGhostId(id) ? originalIdOf(id) : undefined,\n }\n }\n\n return {\n gesture,\n grabbing,\n ghostEvent,\n withPreview,\n edgeCue,\n isRtl,\n start,\n reapply,\n release,\n endLastGesture,\n consumeDrag,\n onPointermove,\n onPointerup,\n onPointercancel,\n onPointerleave,\n onCardKeydown,\n refocusCard,\n focusCell,\n idOfCard,\n cardState,\n }\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"gesture.js","names":[],"sources":["../../../src/components/VCalendar/gesture.ts"],"sourcesContent":["// @keyboard @a11y @core\n/**\n * What the two grids' drag engines share, written once.\n *\n * VCalendarMonth and VCalendarTimeGrid both let an event be picked up, moved and dropped —\n * with a pointer and with the keyboard. Everything that does not depend on what a CELL is\n * lives here: the gesture state and its ghost, the pointer's move, release and cancel, the\n * capture, paging at an edge, the keyboard grab, drop and cancel, the focus handed back to a\n * card, and the flag that stops a drop from also reading as a click.\n *\n * What is NOT here is what genuinely differs, which is also why the two components exist\n * separately: turning a point into a cell (a day square on one side, a day and a minute on\n * the other), working out the new times from it, and the gesture kinds each grid adds. Those\n * stay with each grid, as hooks this composable calls, and the pure half of them is already\n * in `layout.ts`.\n *\n * It lives in the component's folder rather than in `composables/`, the `edgeStep.ts` and\n * `VCombobox/infiniteScroll.ts` arrangement: both consumers are inside this component, so it\n * fails the admission rule that folder keeps.\n */\nimport { computed, nextTick, ref, watch } from 'vue'\nimport type { Ref } from 'vue'\n\nimport { isRtl as isElementRtl } from '../../utils/direction'\n\nimport { useMessages } from '../../i18n/state'\n\nimport { EDGE_BAND, useEdgeStep } from './edgeStep'\nimport { calendarIntent, type CalendarIntent } from './keyboard'\nimport { DRAG_THRESHOLD, inlineEdgeAt, pointWithin, type GridGeometry } from './layout'\nimport type { CalendarEvent, CalendarEventId, CalendarEventTimes } from './types'\n\n/**\n * The prefix marking the copy an event leaves behind at its old place while it is being\n * dragged. It is written into the id rather than held beside it so that the ghost travels\n * through the same list, the same layout and the same `v-for` key as everything else.\n */\nconst GHOST_PREFIX = '__vectis-calendar-ghost__'\n\n/**\n * The id the ghost of a dragged event carries. It has to DIFFER from the event's own, or the\n * two would collide in every map the layout keys by id and only one would ever be drawn.\n */\nexport const ghostIdOf = (id: CalendarEventId) => `${GHOST_PREFIX}${id}`\n/**\n * The dragged event's own id, read back off its ghost's. It is what the card is handed as\n * `ghostOf`: an event's colour is derived from its id, so a ghost coloured from its own\n * would not match the card it belongs to. `hueOf` reads a number and its digits as the same\n * event, so the string form returned here is enough.\n */\nexport const originalIdOf = (id: CalendarEventId) => String(id).slice(GHOST_PREFIX.length)\nexport const isGhostId = (id: CalendarEventId) => String(id).startsWith(GHOST_PREFIX)\n\n/**\n * The id a card belongs to, read back off the DOM.\n *\n * An id may be a NUMBER and an attribute is always text, so a numeric one has to be turned\n * back into one: otherwise every card of a numerically-keyed calendar would look up as a\n * miss and nothing would drag. Which of the two it is, is settled by asking the map that\n * holds the originals rather than by guessing from the text.\n */\nexport function cardIdOf(card: HTMLElement, has: (id: CalendarEventId) => boolean) {\n const raw = card.dataset.eventId ?? ''\n return has(raw) ? raw : Number(raw)\n}\n\n/**\n * A grid's measured box as the pure geometry wants it: plain numbers, no element.\n *\n * `inlineStart` is the edge the first column starts at, which is the RIGHT one in a\n * right-to-left page. This is also why containment never goes through this, see\n * `pointWithin`.\n */\nexport function gridGeometryOf(rect: DOMRect, columns: number, rtl: boolean): GridGeometry {\n return {\n top: rect.top,\n height: rect.height,\n inlineStart: rtl ? rect.right : rect.left,\n inlineSize: rect.width,\n columns,\n }\n}\n\n/** The state every gesture carries, whatever each grid adds to it. */\nexport interface GestureBase {\n id: CalendarEventId\n /**\n * Where the event was when the gesture began. Every pointer frame is computed from THIS and\n * never from the frame before it, so a long drag cannot accumulate rounding drift.\n */\n origin: CalendarEventTimes\n /** What the card shows right now. The model is not touched until the gesture ends. */\n preview: CalendarEventTimes\n /** The pointer holding the gesture, or null for a keyboard grab. */\n pointerId: number | null\n originX: number\n originY: number\n /**\n * Where the pointer last was. Two things move the calendar UNDER a still pointer: paging at\n * an edge, and auto-scrolling. Each has to work out afresh what the pointer is now over.\n */\n lastX: number\n lastY: number\n /** Whether it moved past the threshold, which is what separates a drag from a click. */\n moved: boolean\n /**\n * Whether the pointer is off the calendar altogether: over the toolbar, or over the page\n * beside it. Letting go there abandons the gesture whole and writes nothing.\n *\n * A KEYBOARD grab can never set it, and structurally rather than by a guard: `onPointermove`\n * is the only writer, and it returns on the id mismatch first: a grab's `pointerId` is null,\n * which no real pointer's id ever equals.\n */\n outside: boolean\n /**\n * The reading direction, read ONCE when the gesture begins. It cannot change under a live\n * drag, and asking the document on every frame costs a style resolution each time.\n */\n rtl: boolean\n}\n\n/** What a grid hands over to start a gesture; the rest is filled in here. */\nexport type GestureInit<G extends GestureBase> = Omit<\n G,\n 'preview' | 'lastX' | 'lastY' | 'moved' | 'outside' | 'rtl'\n>\n\n/**\n * A gesture held by the KEYBOARD rather than by a pointer: grabbed with Space, and waiting\n * for the arrows to move it. Both grids draw the card differently in that state, which is\n * what makes it worth a name.\n */\nexport const isGrabbed = (state: GestureBase | null) => state !== null && state.pointerId === null\n\n/** The two intents that move a grabbed event, which only a grid can turn into times. */\nexport type GrabStep = Extract<CalendarIntent, { kind: 'grabMove' | 'grabResize' }>\n\nexport interface CalendarGestureOptions<E extends CalendarEvent, G extends GestureBase> {\n /** Every event as it is currently drawn, the ghost's original among them. */\n events: () => readonly E[]\n /** The event drawn under an id, for the handlers. */\n eventOf: (id: CalendarEventId) => E | undefined\n /** The view's own box: what \"outside the calendar\" is measured against. */\n rootEl: Ref<HTMLElement | null>\n /**\n * The element the pointer is captured on once a press travels. It must contain every surface\n * a gesture can start on, and carry the move, up, cancel and leave bindings: capture retargets\n * every later pointer event to it, which is what makes one set of bindings serve every kind of\n * gesture.\n */\n captureEl: Ref<HTMLElement | null>\n /** The box the cells occupy, which points and edges are read against. */\n measureEl: Ref<HTMLElement | null>\n /** How many columns that box is divided into. */\n columns: () => number\n /** Whether events may be moved at all. */\n editable: () => boolean\n /** The node every card points at to say how it can be moved. */\n hintId: () => string\n /** The step a grabbed event moves by, handed to the keyboard table. */\n slotMinutes: () => number\n edgeStepDelay: () => number\n /** Whatever the grid's cells are made of, so paging under a still pointer re-places the card. */\n layout: () => unknown\n /** Works out where the gesture's event belongs from the pointer's last position. */\n applyPoint: (state: G, rect: DOMRect) => void\n /** Called on every pointer move past the threshold, after the edge watch, with both rects. */\n onEdges?: (state: G, rootRect: DOMRect | undefined) => void\n /** Everything else a gesture leaves running, dropped on every path out of one. */\n onRelease?: () => void\n /**\n * A pointer gesture let go inside the calendar. Returns true when the grid has answered it\n * itself, such as a slot drawn out, and nothing is left to drop.\n */\n onLetGo?: (state: G) => boolean\n /** A gesture that moved, committed: the grid reports the new times. */\n onDrop: (state: G) => void\n /** What a keyboard grab of this event starts, or null when it cannot be grabbed. */\n grab: (item: E) => GestureInit<G> | null\n /** Applies one arrow step to a grabbed event. Returns false when the step means nothing here. */\n onGrabStep: (state: G, step: GrabStep, item: E) => boolean\n step: (direction: -1 | 1) => void\n announce: (message: string) => void\n}\n\nexport function useCalendarGesture<E extends CalendarEvent, G extends GestureBase>(\n options: CalendarGestureOptions<E, G>,\n) {\n const m = useMessages()\n const gesture = ref<G | null>(null) as Ref<G | null>\n\n /** True while a card is being held by the keyboard rather than dragged by a pointer. */\n const grabbing = computed(() => isGrabbed(gesture.value))\n\n const isRtl = () => isElementRtl(options.measureEl.value)\n\n /**\n * The echo of where the gestured event began, so the reader can see what they are moving it\n * FROM. A press that has not travelled yet produces none, or a click would flash a second\n * card over the first.\n */\n const ghostEvent = computed<E | null>(() => {\n const state = gesture.value\n if (!state?.moved) return null\n const original = options.events().find((event) => event.id === state.id)\n return original ? ({ ...original, ...state.origin, id: ghostIdOf(state.id) } as E) : null\n })\n\n /**\n * A list with the gestured event moved to wherever it is now, plus its echo.\n *\n * The echo is listed whether or not it has a box to draw on, because this is what the id maps\n * are built from and the template reads a card's event back out of them. An echo whose day\n * the view has paged past simply produces no placement, as any event off show does.\n */\n function withPreview(events: readonly E[]): E[] {\n const state = gesture.value\n if (!state) return [...events]\n const moving = events.map((event) =>\n event.id === state.id ? ({ ...event, ...state.preview } as E) : event,\n )\n return ghostEvent.value ? [...moving, ghostEvent.value] : moving\n }\n\n /**\n * The flag that keeps a drop from also reading as a click.\n *\n * A pointer that moved past the threshold ends on a `click` the browser fires anyway, and\n * without this the card would be dropped AND opened. It is a plain variable rather than a\n * ref: nothing renders from it, and a reactive one would re-render the grid at the end of\n * every gesture for no visible change.\n *\n * TRAP — three writes, and each is load-bearing.\n *\n * `pointerup` SETS it, outside the calendar included, because `pointerup` fires before\n * `click`: an abandoned drag would otherwise end by opening the very event it refused to move.\n *\n * `pointercancel` does NOT, and must never share a helper with the release that does: no click\n * follows a cancel, so a `true` left behind there would swallow the next genuine one.\n *\n * Every press CLEARS it before any guard runs. The click that lowers it only reaches a card\n * when it lands on one, and drawing out a new event ends on a CELL, so the flag would stay up\n * — and a press that starts no gesture, which `creatable` without `editable` reaches every\n * time, would never overwrite it. The reader clicks an event, nothing happens, they click\n * again. Clearing at the press is what makes the flag unable to outlive its own interaction,\n * and the order is the argument: the click it exists to swallow follows its own `pointerup`\n * with no press in between.\n *\n * A key on a card clears it too, for the same reason from the other side: after a CAPTURED\n * release the browser sends its click to the capture element, which no card handler hears,\n * so the flag outlives the drag, and the next click a card receives may be the keyboard's,\n * with no press before it.\n */\n let dragged = false\n\n /**\n * Closes the books on the previous gesture. Every press handler calls it first.\n *\n * A keyboard grab still held is abandoned here, as Escape would abandon it: every press\n * handler refuses to start while a gesture is live, so a grab left behind froze every\n * pointer gesture of the grid with nothing on screen to say why.\n */\n function endLastGesture() {\n dragged = false\n if (grabbing.value) revertGrab()\n }\n\n /** Puts a keyboard grab back where it was taken from, writing nothing, and says so. */\n function revertGrab() {\n const state = gesture.value\n if (!state) return\n gesture.value = null\n options.announce(m.value.calendar.reverted)\n return state\n }\n\n /**\n * A keyboard grab ends when the focus moves on to something else, the toolbar or another\n * control. Focus that goes NOWHERE is left alone: a card redrawn in another column loses it\n * that way on every step, and `refocusCard` hands it back.\n */\n function onFocusout(event: FocusEvent) {\n const state = gesture.value\n const next = event.relatedTarget as HTMLElement | null\n if (!grabbing.value || !state || !next) return\n const card = next.closest<HTMLElement>('.v-calendar-event')\n if (card && card.dataset.eventId === String(state.id)) return\n revertGrab()\n }\n\n /** Whether the gesture that just ended actually moved; asking lowers the flag. */\n function consumeDrag() {\n const was = dragged\n dragged = false\n return was\n }\n\n const edge = useEdgeStep(options.step, options.edgeStepDelay)\n\n /** Which edge is counting down, as the attribute the stylesheet reads. */\n const edgeCue = computed(() =>\n edge.pending.value === -1 ? 'start' : edge.pending.value === 1 ? 'end' : undefined,\n )\n\n function release() {\n edge.cancel()\n options.onRelease?.()\n }\n\n /**\n * Starts a gesture. Every entry point funnels through here, so the rules that make a gesture\n * safe — one at a time, the origin captured once — are written once. The pointer itself is\n * only taken hold of once the press travels, in `onPointermove`.\n */\n function start(init: GestureInit<G>, rtl = isRtl()) {\n gesture.value = {\n ...init,\n preview: { ...init.origin },\n lastX: init.originX,\n lastY: init.originY,\n moved: false,\n outside: false,\n rtl,\n } as G\n }\n\n /**\n * Takes hold of the pointer on the capture element, so the drag keeps following it past the\n * calendar's edges.\n *\n * TRAP — called when the press crosses the drag threshold, NEVER at the press. The browser\n * sends the `click` that follows a captured `pointerup` to the CAPTURE element, so a press\n * captured at once reaches the scroller instead of the card or the cell under it: clicking an\n * event would open nothing and clicking an empty slot would report nothing, on every calendar\n * whose events can be moved or drawn. Neither jsdom nor a synthetic pointer event reproduces\n * the retargeting (a synthetic pointer cannot be captured), so the unit suite pins WHEN the\n * capture is asked for rather than where the click lands.\n */\n function capture(pointerId: number) {\n // @fallback\n /*\n * Wrapped because a pointer event fired by a TEST refers to no real pointer,\n * and the call then throws. Failing to capture merely means the drag stops at the edge of\n * the capture element, which no test is checking.\n */\n try {\n options.captureEl.value?.setPointerCapture(pointerId)\n } catch {\n /* a synthetic pointer: nothing to capture */\n }\n }\n\n /** Re-reads the measured box and works the gesture out again, for a caller outside a handler. */\n function reapply(state: G) {\n const rect = options.measureEl.value?.getBoundingClientRect()\n if (rect) options.applyPoint(state, rect)\n }\n\n function onPointermove(event: PointerEvent) {\n const state = gesture.value\n if (!state || state.pointerId !== event.pointerId) return\n\n state.lastX = event.clientX\n state.lastY = event.clientY\n\n // Below the threshold nothing has happened yet. That is what keeps a click a click: the\n // hand's tremor during a press would otherwise register as a one-pixel drag.\n if (\n !state.moved &&\n Math.abs(event.clientX - state.originX) < DRAG_THRESHOLD &&\n Math.abs(event.clientY - state.originY) < DRAG_THRESHOLD\n ) {\n return\n }\n\n if (!state.moved) capture(event.pointerId)\n state.moved = true\n // Each box is measured ONCE per move and handed to everything that reads it.\n const rootRect = options.rootEl.value?.getBoundingClientRect()\n const rect = options.measureEl.value?.getBoundingClientRect()\n\n /*\n * Outside is measured against the view's own box — never the cells' box, whose rect\n * excludes the day names, the all-day band and the hour gutter — and the rect goes in RAW:\n * containment has no reading direction, where `inlineStart` is the right edge in RTL.\n *\n * TRAP — neither the placement nor the edge watch below is gated on it, and neither may\n * become so. The card must keep following the pointer while it is out, which is what makes\n * coming back in seamless, and paging must keep running, pushing past the edge being how one\n * crosses into the next period. Being outside decides what happens on RELEASE, nothing else.\n */\n state.outside = rootRect ? !pointWithin({ x: state.lastX, y: state.lastY }, rootRect) : false\n\n if (!rect) return\n options.applyPoint(state, rect)\n edge.watchEdge(\n inlineEdgeAt(\n state.lastX,\n gridGeometryOf(rect, options.columns(), state.rtl),\n EDGE_BAND,\n state.rtl,\n ),\n )\n options.onEdges?.(state, rootRect)\n }\n\n function onPointerup(event: PointerEvent) {\n const state = gesture.value\n if (!state || state.pointerId !== event.pointerId) return\n gesture.value = null\n dragged = state.moved\n release()\n\n /*\n * Let go with the pointer off the calendar and the gesture is abandoned whole. Nothing is\n * announced: the pointer says nothing on a SUCCESSFUL drop either — `grabbed`, `dropped` and\n * `reverted` belong to the keyboard grab, which has no pointer to show where the event went.\n */\n if (state.outside) return\n if (options.onLetGo?.(state)) return\n // A press that never travelled is an ordinary click, which the button's own click event is\n // about to report. Writing anything here would move an event nobody dragged.\n if (state.moved) options.onDrop(state)\n }\n\n /*\n * The gesture was taken away — a system gesture, a context menu, the page starting to scroll.\n * Nothing is written and nothing is announced: the card goes back to where the model still\n * says it is.\n */\n function onPointercancel(event: PointerEvent) {\n // Another pointer's cancel, a second finger starting to pan, is not this gesture's. A\n // keyboard grab carries no pointer id, so no cancel can end it either.\n if (gesture.value?.pointerId !== event.pointerId) return\n abandon()\n }\n\n function abandon() {\n gesture.value = null\n release()\n }\n\n /*\n * A press that leaves the capture element before it has travelled far enough to be captured.\n * Its `pointerup` then lands outside and never reaches the bindings, so without this the\n * gesture would outlive the press: a mouse keeps the same pointer id, and bringing it back over\n * the calendar with the button up would pick the event up and carry it. A captured pointer\n * never leaves, so a real drag is untouched.\n */\n function onPointerleave(event: PointerEvent) {\n const state = gesture.value\n if (!state || state.pointerId !== event.pointerId || state.moved) return\n abandon()\n }\n\n /*\n * Paging swaps the cells out from under a live drag, and the dragged event's day is then off\n * screen — the card would vanish until the next pointer move, which never comes if the hand is\n * holding still against the edge. Re-applying the last position once the new cells are\n * rendered is what keeps the card under the pointer across the boundary.\n */\n watch(\n options.layout,\n () => {\n const state = gesture.value\n if (state?.moved) reapply(state)\n },\n { flush: 'post' },\n )\n\n /**\n * Hands the focus back to a card once it has landed somewhere else, which the re-render has\n * just taken it from.\n *\n * TRAP — the card is found by WALKING the cards rather than by building an attribute\n * selector. An id belongs to the consumer, so it may hold a quote or a backslash a selector\n * would need escaped, and `CSS.escape` cannot do that escaping here: jsdom defines no `CSS`\n * object at all, so the call threw on every keyboard grab, from inside a `nextTick` where\n * nothing could catch it — an unhandled rejection, which fails the run while every assertion\n * still passes. Comparing the attribute's own text sidesteps the question, `data-event-id`\n * being written as exactly `String(event.id)`.\n */\n function refocusCard(id: CalendarEventId) {\n void nextTick(() => {\n // Searched from the view's root: the time grid's all-day bars sit in its sticky header,\n // outside the box the cells occupy.\n const cards = options.rootEl.value?.querySelectorAll<HTMLElement>('.v-calendar-event')\n Array.from(cards ?? [])\n .find((card) => card.dataset.eventId === String(id))\n ?.focus()\n })\n }\n\n /** Puts the focus on a cell by its id, once the render that made it tabbable has run. */\n function focusCell(id: string, deferred = false, focusOptions?: FocusOptions) {\n const move = () => document.getElementById(id)?.focus(focusOptions)\n if (deferred) void nextTick(move)\n else move()\n }\n\n /** The event a card stands for, read back off the attribute the card publishes. */\n const idOfCard = (card: HTMLElement) => cardIdOf(card, (id) => options.eventOf(id) !== undefined)\n\n /**\n * A card answers a different table from the grid it sits in — that is what a grab mode IS.\n * Without it the grid would offer a gesture the pointer alone could reach (WCAG 2.1.1).\n */\n function onCardKeydown(event: KeyboardEvent, card: HTMLElement) {\n // Whatever click follows is this key's, never the end of an earlier drag.\n dragged = false\n const item = options.eventOf(idOfCard(card))\n if (!item) return\n\n const held = grabbing.value && gesture.value?.id === item.id\n const state = held ? gesture.value! : null\n const intent = calendarIntent(\n event,\n held ? 'grabbed' : 'event',\n options.slotMinutes(),\n state?.rtl ?? isRtl(),\n )\n if (!intent) return\n\n if (!state) {\n // An event that cannot be moved keeps a button's ordinary behaviour: Space presses it,\n // which the card's click handler reports.\n const init = intent.kind === 'grab' ? options.grab(item) : null\n if (!init) return\n /*\n * Space is ALSO how a button is pressed, on its release. Cancelling the keydown is what\n * stops that press, so the keystroke that takes hold of the event does not open it too:\n * without it every attempt to move something would fire the consumer's editor over it.\n */\n event.preventDefault()\n start(init)\n options.announce(m.value.calendar.grabbed)\n return\n }\n\n event.preventDefault()\n\n if (intent.kind === 'grabMove' || intent.kind === 'grabResize') {\n if (!options.onGrabStep(state, intent, item)) return\n state.moved = true\n refocusCard(state.id)\n return\n }\n\n if (intent.kind === 'activate') {\n gesture.value = null\n if (state.moved) options.onDrop(state)\n options.announce(m.value.calendar.dropped)\n refocusCard(state.id)\n return\n }\n\n if (intent.kind === 'cancel') {\n revertGrab()\n refocusCard(state.id)\n }\n }\n\n /**\n * The five things every card is told about the gesture, bound with `v-bind` so the two grids\n * cannot describe the same state in two different ways.\n */\n function cardState(id: CalendarEventId) {\n const state = gesture.value\n const mine = state !== null && state.id === id\n return {\n /*\n * TRAP — only once the press has travelled. A dragged card takes no pointer events, so\n * marked at the press it lets the release land on the cell beneath it: the click then goes\n * to that cell, and clicking an event reports an empty slot instead of opening it.\n */\n dragging: mine && state.pointerId !== null && state.moved,\n rejected: mine && state.outside,\n grabbed: mine && state.pointerId === null,\n hintId: options.editable() && !isGhostId(id) ? options.hintId() : undefined,\n ghostOf: isGhostId(id) ? originalIdOf(id) : undefined,\n }\n }\n\n return {\n gesture,\n grabbing,\n ghostEvent,\n withPreview,\n edgeCue,\n isRtl,\n start,\n reapply,\n release,\n endLastGesture,\n consumeDrag,\n onPointermove,\n onPointerup,\n onPointercancel,\n onPointerleave,\n onFocusout,\n onCardKeydown,\n refocusCard,\n focusCell,\n idOfCard,\n cardState,\n }\n}\n"],"mappings":"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"}
@@ -43,6 +43,10 @@ export type CalendarIntent =
43
43
  | {
44
44
  kind: 'activate';
45
45
  }
46
+ /** Open the focused day, which only a month square offers. */
47
+ | {
48
+ kind: 'openDay';
49
+ }
46
50
  /** Take hold of a card, so the arrows move it. */
47
51
  | {
48
52
  kind: 'grab';
@@ -65,20 +69,33 @@ export type CalendarIntent =
65
69
  /**
66
70
  * Where the focus is when the key arrives, which is what decides the answer:
67
71
  *
68
- * - `cell` — an empty part of the grid. The arrows travel, Enter creates.
69
- * - `event` — a card, at rest. Space takes hold of it; every other key is the browser's,
72
+ * - `cell`: an empty part of the grid. The arrows travel, Enter creates, Shift and Enter
73
+ * open the day (a month square's number takes no tab stop, so this is its keyboard route).
74
+ * - `event`: a card, at rest. Space takes hold of it; every other key is the browser's,
70
75
  * Enter included, which presses the card as a button and so opens the event. Enter is the
71
76
  * one a reader tries first on a button, and `event-activate` has no other keyboard route.
72
- * - `grabbed` — a card being moved. The arrows now move the EVENT, Enter commits, Escape
77
+ * - `grabbed`: a card being moved. The arrows now move the EVENT, Enter commits, Escape
73
78
  * puts it back where it was.
74
79
  */
75
80
  export type CalendarFocus = 'cell' | 'event' | 'grabbed';
81
+ /** The part of a keyboard event the table reads; a `KeyboardEvent` is one. */
82
+ export interface KeyChord {
83
+ key: string;
84
+ shiftKey?: boolean;
85
+ altKey?: boolean;
86
+ ctrlKey?: boolean;
87
+ metaKey?: boolean;
88
+ }
76
89
  /**
77
90
  * What a key means. Returning nothing says the key is none of this table's business and
78
- * the event must be left entirely alone — which is what keeps Tab, the browser's own
91
+ * the event must be left entirely alone. That keeps keeps Tab, the browser's own
79
92
  * shortcuts and anything a consumer has bound working.
80
93
  *
94
+ * A key held with Alt, Ctrl or Meta is ALWAYS left alone, whatever it is: Alt+Left is the
95
+ * browser's Back and Ctrl+Home scrolls the page, and answering them here also cancelled them.
96
+ * Shift is part of the table.
97
+ *
81
98
  * `rtl` is passed in rather than read here: which way is "forward" is a property of the
82
99
  * document, and a pure table has no business consulting one.
83
100
  */
84
- export declare function calendarIntent(key: string, shiftKey: boolean, focus: CalendarFocus, slotMinutes: number, rtl: boolean): CalendarIntent | undefined;
101
+ export declare function calendarIntent(chord: KeyChord, focus: CalendarFocus, slotMinutes: number, rtl: boolean): CalendarIntent | undefined;
@@ -1,48 +1,49 @@
1
1
  //#region src/components/VCalendar/keyboard.ts
2
- function e(e, t, n, r, i) {
3
- let a = r > 0 ? r : 1, o = i ? -1 : 1;
4
- if (n === "grabbed") switch (e) {
2
+ function e(e, t, n, r) {
3
+ if (e.altKey || e.ctrlKey || e.metaKey) return;
4
+ let { key: i } = e, a = e.shiftKey === !0, o = n > 0 ? n : 1, s = r ? -1 : 1;
5
+ if (t === "grabbed") switch (i) {
5
6
  case "ArrowLeft": return {
6
7
  kind: "grabMove",
7
- days: -o,
8
+ days: -s,
8
9
  minutes: 0
9
10
  };
10
11
  case "ArrowRight": return {
11
12
  kind: "grabMove",
12
- days: o,
13
+ days: s,
13
14
  minutes: 0
14
15
  };
15
- case "ArrowUp": return t ? {
16
+ case "ArrowUp": return a ? {
16
17
  kind: "grabResize",
17
- minutes: -a
18
+ minutes: -o
18
19
  } : {
19
20
  kind: "grabMove",
20
21
  days: 0,
21
- minutes: -a
22
+ minutes: -o
22
23
  };
23
- case "ArrowDown": return t ? {
24
+ case "ArrowDown": return a ? {
24
25
  kind: "grabResize",
25
- minutes: a
26
+ minutes: o
26
27
  } : {
27
28
  kind: "grabMove",
28
29
  days: 0,
29
- minutes: a
30
+ minutes: o
30
31
  };
31
32
  case "Enter":
32
33
  case " ": return { kind: "activate" };
33
34
  case "Escape": return { kind: "cancel" };
34
35
  default: return;
35
36
  }
36
- if (n === "event") return e === " " ? { kind: "grab" } : void 0;
37
- switch (e) {
37
+ if (t === "event") return i === " " ? { kind: "grab" } : void 0;
38
+ switch (i) {
38
39
  case "ArrowLeft": return {
39
40
  kind: "moveFocus",
40
- days: -o,
41
+ days: -s,
41
42
  minutes: 0
42
43
  };
43
44
  case "ArrowRight": return {
44
45
  kind: "moveFocus",
45
- days: o,
46
+ days: s,
46
47
  minutes: 0
47
48
  };
48
49
  case "ArrowUp": return {
@@ -71,7 +72,7 @@ function e(e, t, n, r, i) {
71
72
  kind: "period",
72
73
  delta: 1
73
74
  };
74
- case "Enter":
75
+ case "Enter": return a ? { kind: "openDay" } : { kind: "activate" };
75
76
  case " ": return { kind: "activate" };
76
77
  default: return;
77
78
  }
@@ -1 +1 @@
1
- {"version":3,"file":"keyboard.js","names":[],"sources":["../../../src/components/VCalendar/keyboard.ts"],"sourcesContent":["// @keyboard @a11y\n/**\n * The pure half of VCalendar's keyboard: it answers the single question \"what does this\n * key mean here?\", and does nothing else. Moving the focus, writing to the model, calling\n * `preventDefault` and announcing the result all stay in the component, where the reactive\n * state lives.\n *\n * It sits in VCalendar's own folder rather than in `utils/` because it has exactly one\n * consumer, which fails the admission rule for shared code (the same reasoning as\n * `VDatePicker/keyboard.ts` and `VHotkeys/platform.ts`). Being pure is also what makes the\n * whole keyboard testable without mounting anything, since the environment the tests run\n * in lays nothing out and the handlers in the component only ever move DOM focus.\n *\n * `utils/arrowNav` is deliberately not used. It navigates a flat DOM list of controls; this\n * navigates a two-dimensional space of DATES AND TIMES whose edges are a domain clamp, not\n * a list end — the same reason VDatePicker, VCombobox and VTimePicker stay out of it.\n *\n * WHY A GRAB MODE, and not arrows that move an event outright. Every gesture the pointer\n * offers has to have a keyboard equivalent (WCAG 2.1.1), and a card is reached by the\n * arrows in the first place — so if the arrows also moved it, arriving at an event and\n * nudging it would be the same keystroke, and there would be no way to pass over one\n * without dragging it. Entering a mode separates the two, and Escape gives back the one\n * thing a pointer drag has that a keypress does not: the chance to change your mind.\n */\n\nimport { MINUTES_PER_HOUR } from './layout'\n\n/** What one key means, given where the focus is. */\nexport type CalendarIntent =\n /** Move the focused cell by whole days and whole hours. */\n | { kind: 'moveFocus'; days: number; minutes: number }\n /** Jump to the first or last day of the row. */\n | { kind: 'rowEdge'; edge: 'start' | 'end' }\n /** Show the previous or next period, as the toolbar's buttons do. */\n | { kind: 'period'; delta: -1 | 1 }\n /** Take up what is focused: report an empty cell, or commit a move under way. */\n | { kind: 'activate' }\n /** Take hold of a card, so the arrows move it. */\n | { kind: 'grab' }\n /** Abandon a move under way and put the event back. */\n | { kind: 'cancel' }\n /** Move the grabbed event. */\n | { kind: 'grabMove'; days: number; minutes: number }\n /** Change how long the grabbed event lasts. */\n | { kind: 'grabResize'; minutes: number }\n\n/**\n * Where the focus is when the key arrives, which is what decides the answer:\n *\n * - `cell` — an empty part of the grid. The arrows travel, Enter creates.\n * - `event` — a card, at rest. Space takes hold of it; every other key is the browser's,\n * Enter included, which presses the card as a button and so opens the event. Enter is the\n * one a reader tries first on a button, and `event-activate` has no other keyboard route.\n * - `grabbed` — a card being moved. The arrows now move the EVENT, Enter commits, Escape\n * puts it back where it was.\n */\nexport type CalendarFocus = 'cell' | 'event' | 'grabbed'\n\n/**\n * What a key means. Returning nothing says the key is none of this table's business and\n * the event must be left entirely alone — which is what keeps Tab, the browser's own\n * shortcuts and anything a consumer has bound working.\n *\n * `rtl` is passed in rather than read here: which way is \"forward\" is a property of the\n * document, and a pure table has no business consulting one.\n */\nexport function calendarIntent(\n key: string,\n shiftKey: boolean,\n focus: CalendarFocus,\n slotMinutes: number,\n rtl: boolean,\n): CalendarIntent | undefined {\n const step = slotMinutes > 0 ? slotMinutes : 1\n // The inline arrows follow the reading direction; the block ones never do, because down\n // is later in the day in every script.\n const inline = rtl ? -1 : 1\n\n if (focus === 'grabbed') {\n switch (key) {\n case 'ArrowLeft':\n return { kind: 'grabMove', days: -inline, minutes: 0 }\n case 'ArrowRight':\n return { kind: 'grabMove', days: inline, minutes: 0 }\n case 'ArrowUp':\n return shiftKey\n ? { kind: 'grabResize', minutes: -step }\n : { kind: 'grabMove', days: 0, minutes: -step }\n case 'ArrowDown':\n return shiftKey\n ? { kind: 'grabResize', minutes: step }\n : { kind: 'grabMove', days: 0, minutes: step }\n case 'Enter':\n case ' ':\n return { kind: 'activate' }\n case 'Escape':\n return { kind: 'cancel' }\n default:\n return undefined\n }\n }\n\n if (focus === 'event') return key === ' ' ? { kind: 'grab' } : undefined\n\n switch (key) {\n case 'ArrowLeft':\n return { kind: 'moveFocus', days: -inline, minutes: 0 }\n case 'ArrowRight':\n return { kind: 'moveFocus', days: inline, minutes: 0 }\n case 'ArrowUp':\n return { kind: 'moveFocus', days: 0, minutes: -MINUTES_PER_HOUR }\n case 'ArrowDown':\n return { kind: 'moveFocus', days: 0, minutes: MINUTES_PER_HOUR }\n case 'Home':\n return { kind: 'rowEdge', edge: 'start' }\n case 'End':\n return { kind: 'rowEdge', edge: 'end' }\n case 'PageUp':\n return { kind: 'period', delta: -1 }\n case 'PageDown':\n return { kind: 'period', delta: 1 }\n case 'Enter':\n case ' ':\n return { kind: 'activate' }\n default:\n return undefined\n }\n}\n"],"mappings":";AAkEA,SAAgB,EACd,GACA,GACA,GACA,GACA,GAC4B;CAC5B,IAAM,IAAO,IAAc,IAAI,IAAc,GAGvC,IAAS,IAAM,KAAK;CAE1B,IAAI,MAAU,WACZ,QAAQ,GAAR;EACE,KAAK,aACH,OAAO;GAAE,MAAM;GAAY,MAAM,CAAC;GAAQ,SAAS;EAAE;EACvD,KAAK,cACH,OAAO;GAAE,MAAM;GAAY,MAAM;GAAQ,SAAS;EAAE;EACtD,KAAK,WACH,OAAO,IACH;GAAE,MAAM;GAAc,SAAS,CAAC;EAAK,IACrC;GAAE,MAAM;GAAY,MAAM;GAAG,SAAS,CAAC;EAAK;EAClD,KAAK,aACH,OAAO,IACH;GAAE,MAAM;GAAc,SAAS;EAAK,IACpC;GAAE,MAAM;GAAY,MAAM;GAAG,SAAS;EAAK;EACjD,KAAK;EACL,KAAK,KACH,OAAO,EAAE,MAAM,WAAW;EAC5B,KAAK,UACH,OAAO,EAAE,MAAM,SAAS;EAC1B,SACE;CACJ;CAGF,IAAI,MAAU,SAAS,OAAO,MAAQ,MAAM,EAAE,MAAM,OAAO,IAAI,KAAA;CAE/D,QAAQ,GAAR;EACE,KAAK,aACH,OAAO;GAAE,MAAM;GAAa,MAAM,CAAC;GAAQ,SAAS;EAAE;EACxD,KAAK,cACH,OAAO;GAAE,MAAM;GAAa,MAAM;GAAQ,SAAS;EAAE;EACvD,KAAK,WACH,OAAO;GAAE,MAAM;GAAa,MAAM;GAAG,SAAS;EAAkB;EAClE,KAAK,aACH,OAAO;GAAE,MAAM;GAAa,MAAM;GAAG,SAAA;EAA0B;EACjE,KAAK,QACH,OAAO;GAAE,MAAM;GAAW,MAAM;EAAQ;EAC1C,KAAK,OACH,OAAO;GAAE,MAAM;GAAW,MAAM;EAAM;EACxC,KAAK,UACH,OAAO;GAAE,MAAM;GAAU,OAAO;EAAG;EACrC,KAAK,YACH,OAAO;GAAE,MAAM;GAAU,OAAO;EAAE;EACpC,KAAK;EACL,KAAK,KACH,OAAO,EAAE,MAAM,WAAW;EAC5B,SACE;CACJ;AACF"}
1
+ {"version":3,"file":"keyboard.js","names":[],"sources":["../../../src/components/VCalendar/keyboard.ts"],"sourcesContent":["// @keyboard @a11y\n/**\n * The pure half of VCalendar's keyboard: it answers the single question \"what does this\n * key mean here?\", and does nothing else. Moving the focus, writing to the model, calling\n * `preventDefault` and announcing the result all stay in the component, where the reactive\n * state lives.\n *\n * It sits in VCalendar's own folder rather than in `utils/` because it has exactly one\n * consumer, which fails the admission rule for shared code (the same reasoning as\n * `VDatePicker/keyboard.ts` and `VHotkeys/platform.ts`). Being pure is also what makes the\n * whole keyboard testable without mounting anything, since the environment the tests run\n * in lays nothing out and the handlers in the component only ever move DOM focus.\n *\n * `utils/arrowNav` is deliberately not used. It navigates a flat DOM list of controls; this\n * navigates a two-dimensional space of DATES AND TIMES whose edges are a domain clamp, not\n * a list end — the same reason VDatePicker, VCombobox and VTimePicker stay out of it.\n *\n * WHY A GRAB MODE, and not arrows that move an event outright. Every gesture the pointer\n * offers has to have a keyboard equivalent (WCAG 2.1.1), and a card is reached by the\n * arrows in the first place — so if the arrows also moved it, arriving at an event and\n * nudging it would be the same keystroke, and there would be no way to pass over one\n * without dragging it. Entering a mode separates the two, and Escape gives back the one\n * thing a pointer drag has that a keypress does not: the chance to change your mind.\n */\n\nimport { MINUTES_PER_HOUR } from './layout'\n\n/** What one key means, given where the focus is. */\nexport type CalendarIntent =\n /** Move the focused cell by whole days and whole hours. */\n | { kind: 'moveFocus'; days: number; minutes: number }\n /** Jump to the first or last day of the row. */\n | { kind: 'rowEdge'; edge: 'start' | 'end' }\n /** Show the previous or next period, as the toolbar's buttons do. */\n | { kind: 'period'; delta: -1 | 1 }\n /** Take up what is focused: report an empty cell, or commit a move under way. */\n | { kind: 'activate' }\n /** Open the focused day, which only a month square offers. */\n | { kind: 'openDay' }\n /** Take hold of a card, so the arrows move it. */\n | { kind: 'grab' }\n /** Abandon a move under way and put the event back. */\n | { kind: 'cancel' }\n /** Move the grabbed event. */\n | { kind: 'grabMove'; days: number; minutes: number }\n /** Change how long the grabbed event lasts. */\n | { kind: 'grabResize'; minutes: number }\n\n/**\n * Where the focus is when the key arrives, which is what decides the answer:\n *\n * - `cell`: an empty part of the grid. The arrows travel, Enter creates, Shift and Enter\n * open the day (a month square's number takes no tab stop, so this is its keyboard route).\n * - `event`: a card, at rest. Space takes hold of it; every other key is the browser's,\n * Enter included, which presses the card as a button and so opens the event. Enter is the\n * one a reader tries first on a button, and `event-activate` has no other keyboard route.\n * - `grabbed`: a card being moved. The arrows now move the EVENT, Enter commits, Escape\n * puts it back where it was.\n */\nexport type CalendarFocus = 'cell' | 'event' | 'grabbed'\n\n/** The part of a keyboard event the table reads; a `KeyboardEvent` is one. */\nexport interface KeyChord {\n key: string\n shiftKey?: boolean\n altKey?: boolean\n ctrlKey?: boolean\n metaKey?: boolean\n}\n\n/**\n * What a key means. Returning nothing says the key is none of this table's business and\n * the event must be left entirely alone. That keeps keeps Tab, the browser's own\n * shortcuts and anything a consumer has bound working.\n *\n * A key held with Alt, Ctrl or Meta is ALWAYS left alone, whatever it is: Alt+Left is the\n * browser's Back and Ctrl+Home scrolls the page, and answering them here also cancelled them.\n * Shift is part of the table.\n *\n * `rtl` is passed in rather than read here: which way is \"forward\" is a property of the\n * document, and a pure table has no business consulting one.\n */\nexport function calendarIntent(\n chord: KeyChord,\n focus: CalendarFocus,\n slotMinutes: number,\n rtl: boolean,\n): CalendarIntent | undefined {\n if (chord.altKey || chord.ctrlKey || chord.metaKey) return undefined\n const { key } = chord\n const shiftKey = chord.shiftKey === true\n const step = slotMinutes > 0 ? slotMinutes : 1\n // The inline arrows follow the reading direction; the block ones never do, because down\n // is later in the day in every script.\n const inline = rtl ? -1 : 1\n\n if (focus === 'grabbed') {\n switch (key) {\n case 'ArrowLeft':\n return { kind: 'grabMove', days: -inline, minutes: 0 }\n case 'ArrowRight':\n return { kind: 'grabMove', days: inline, minutes: 0 }\n case 'ArrowUp':\n return shiftKey\n ? { kind: 'grabResize', minutes: -step }\n : { kind: 'grabMove', days: 0, minutes: -step }\n case 'ArrowDown':\n return shiftKey\n ? { kind: 'grabResize', minutes: step }\n : { kind: 'grabMove', days: 0, minutes: step }\n case 'Enter':\n case ' ':\n return { kind: 'activate' }\n case 'Escape':\n return { kind: 'cancel' }\n default:\n return undefined\n }\n }\n\n if (focus === 'event') return key === ' ' ? { kind: 'grab' } : undefined\n\n switch (key) {\n case 'ArrowLeft':\n return { kind: 'moveFocus', days: -inline, minutes: 0 }\n case 'ArrowRight':\n return { kind: 'moveFocus', days: inline, minutes: 0 }\n case 'ArrowUp':\n return { kind: 'moveFocus', days: 0, minutes: -MINUTES_PER_HOUR }\n case 'ArrowDown':\n return { kind: 'moveFocus', days: 0, minutes: MINUTES_PER_HOUR }\n case 'Home':\n return { kind: 'rowEdge', edge: 'start' }\n case 'End':\n return { kind: 'rowEdge', edge: 'end' }\n case 'PageUp':\n return { kind: 'period', delta: -1 }\n case 'PageDown':\n return { kind: 'period', delta: 1 }\n case 'Enter':\n return shiftKey ? { kind: 'openDay' } : { kind: 'activate' }\n case ' ':\n return { kind: 'activate' }\n default:\n return undefined\n }\n}\n"],"mappings":";AAkFA,SAAgB,EACd,GACA,GACA,GACA,GAC4B;CAC5B,IAAI,EAAM,UAAU,EAAM,WAAW,EAAM,SAAS;CACpD,IAAM,EAAE,WAAQ,GACV,IAAW,EAAM,aAAa,IAC9B,IAAO,IAAc,IAAI,IAAc,GAGvC,IAAS,IAAM,KAAK;CAE1B,IAAI,MAAU,WACZ,QAAQ,GAAR;EACE,KAAK,aACH,OAAO;GAAE,MAAM;GAAY,MAAM,CAAC;GAAQ,SAAS;EAAE;EACvD,KAAK,cACH,OAAO;GAAE,MAAM;GAAY,MAAM;GAAQ,SAAS;EAAE;EACtD,KAAK,WACH,OAAO,IACH;GAAE,MAAM;GAAc,SAAS,CAAC;EAAK,IACrC;GAAE,MAAM;GAAY,MAAM;GAAG,SAAS,CAAC;EAAK;EAClD,KAAK,aACH,OAAO,IACH;GAAE,MAAM;GAAc,SAAS;EAAK,IACpC;GAAE,MAAM;GAAY,MAAM;GAAG,SAAS;EAAK;EACjD,KAAK;EACL,KAAK,KACH,OAAO,EAAE,MAAM,WAAW;EAC5B,KAAK,UACH,OAAO,EAAE,MAAM,SAAS;EAC1B,SACE;CACJ;CAGF,IAAI,MAAU,SAAS,OAAO,MAAQ,MAAM,EAAE,MAAM,OAAO,IAAI,KAAA;CAE/D,QAAQ,GAAR;EACE,KAAK,aACH,OAAO;GAAE,MAAM;GAAa,MAAM,CAAC;GAAQ,SAAS;EAAE;EACxD,KAAK,cACH,OAAO;GAAE,MAAM;GAAa,MAAM;GAAQ,SAAS;EAAE;EACvD,KAAK,WACH,OAAO;GAAE,MAAM;GAAa,MAAM;GAAG,SAAS;EAAkB;EAClE,KAAK,aACH,OAAO;GAAE,MAAM;GAAa,MAAM;GAAG,SAAA;EAA0B;EACjE,KAAK,QACH,OAAO;GAAE,MAAM;GAAW,MAAM;EAAQ;EAC1C,KAAK,OACH,OAAO;GAAE,MAAM;GAAW,MAAM;EAAM;EACxC,KAAK,UACH,OAAO;GAAE,MAAM;GAAU,OAAO;EAAG;EACrC,KAAK,YACH,OAAO;GAAE,MAAM;GAAU,OAAO;EAAE;EACpC,KAAK,SACH,OAAO,IAAW,EAAE,MAAM,UAAU,IAAI,EAAE,MAAM,WAAW;EAC7D,KAAK,KACH,OAAO,EAAE,MAAM,WAAW;EAC5B,SACE;CACJ;AACF"}
@@ -23,10 +23,10 @@ export declare function windowOf(startHour: number, endHour: number): TimeWindow
23
23
  /**
24
24
  * Minutes since midnight back into an `HH:mm` string.
25
25
  *
26
- * TRAP — the value is held one minute short of midnight rather than allowed to reach it.
26
+ * TRAP: the value is held one minute short of midnight rather than allowed to reach it.
27
27
  * A day's last moment is 1440 in this arithmetic, but `24:00` is not a time any of the
28
- * design system's helpers accept (`isValidTime` rejects it), and the alternative — writing
29
- * `00:00` on the following day — would turn an ordinary evening appointment into one that
28
+ * design system's helpers accept (`isValidTime` rejects it). Writing
29
+ * `00:00` on the following day would turn an ordinary evening appointment into one that
30
30
  * runs past midnight, which every gesture then treats differently. One minute is invisible at
31
31
  * every zoom this component offers; an event that changed kind under the pointer is not.
32
32
  */
@@ -36,8 +36,8 @@ export declare function minutesAt(time: string | undefined, fallback: number): n
36
36
  /**
37
37
  * The weekdays a calendar shows, in reading order.
38
38
  *
39
- * The array does double duty: it says which days are VISIBLE — `[1,2,3,4,5]` hides the
40
- * weekend everywhere — and its first entry is the day a week starts on. Given nothing, the
39
+ * The array does double duty: it says which days are VISIBLE: `[1,2,3,4,5]` hides the
40
+ * weekend everywhere, and its first entry is the day a week starts on. Given nothing, the
41
41
  * seven days rotated to `firstDayOfWeek`, which the calendar takes from its prop of that
42
42
  * name or from the locale.
43
43
  */
@@ -48,7 +48,7 @@ export declare function isVisibleDay(iso: string, weekdays: readonly number[]):
48
48
  * The first visible day at or after `iso` (or at or before it, going backwards).
49
49
  *
50
50
  * The loop is bounded at seven because a non-empty weekday list always contains one of any
51
- * seven consecutive days — the bound is a guard against an empty list, never a real limit.
51
+ * seven consecutive days: the bound is a guard against an empty list, never a real limit.
52
52
  */
53
53
  export declare function snapToVisibleDay(iso: string, weekdays: readonly number[], direction?: -1 | 1): string;
54
54
  /** Moves `count` VISIBLE days from `iso`, skipping over the hidden ones. */
@@ -61,7 +61,7 @@ export declare function columnCount(view: CalendarView, customDays: number): num
61
61
  * `day`, `4days` and `custom` run forward from the anchor over the visible days alone, so
62
62
  * a four-day view of a Monday-to-Friday calendar shows four WORKING days rather than four
63
63
  * calendar ones. `week` shows the week the anchor falls in, starting on `weekdays[0]`.
64
- * `month` returns every day of the anchor's month that is visible — the grid that renders
64
+ * `month` returns every day of the anchor's month that is visible: the grid that renders
65
65
  * them cuts them back into weeks itself.
66
66
  *
67
67
  * `year` returns an empty list on purpose: that view is twelve month names, not a row of
@@ -71,7 +71,7 @@ export declare function visibleDays(anchor: string, view: CalendarView, weekdays
71
71
  /**
72
72
  * Where Previous and Next land.
73
73
  *
74
- * TRAP — the day-shaped views step over VISIBLE days, not calendar ones. Stepping by one
74
+ * TRAP: the day-shaped views step over VISIBLE days, not calendar ones. Stepping by one
75
75
  * calendar day from a Friday in a Monday-to-Friday calendar would land on a Saturday the
76
76
  * grid does not draw; the view would then show the same week it already showed, and the
77
77
  * button would look broken with nothing in the console to say why.
@@ -85,8 +85,8 @@ export declare function visibleRange(anchor: string, view: CalendarView, weekday
85
85
  /**
86
86
  * How long an event lasts, in minutes, counting the days between its dates.
87
87
  *
88
- * A time that is not one reads as the far end of its day — midnight for a start, the next
89
- * midnight for an end — so a malformed event errs towards being long, and towards the band.
88
+ * A time that is not one reads as the far end of its day: midnight for a start, the next
89
+ * midnight for an end, so a malformed event errs towards being long, and towards the band.
90
90
  */
91
91
  export declare function durationOf(times: CalendarEventTimes): number;
92
92
  /** Whether an event runs from one day into the next without lasting a whole day. */
@@ -95,8 +95,8 @@ export declare function spansMidnight(times: CalendarEventTimes): boolean;
95
95
  * Whether an event belongs in the band above the grid rather than in a day's column.
96
96
  *
97
97
  * A day's column holds up to twenty-four hours, so an event running past midnight for less
98
- * than that is drawn as two cards — the evening in one column, the early morning in the next —
99
- * and only one lasting a whole day or more becomes a bar. Exactly twenty-four hours is a bar:
98
+ * than that is drawn as two cards, the evening in one column and the early morning in the next.
99
+ * Only one lasting a whole day or more becomes a bar. Exactly twenty-four hours is a bar:
100
100
  * two cards covering the same hours of two columns would read as two events.
101
101
  *
102
102
  * An event whose end comes before its start has no column to go in either, so it goes to the
@@ -128,9 +128,9 @@ export interface EventSegment {
128
128
  part: SegmentPart;
129
129
  }
130
130
  /**
131
- * Cuts the timed events into the boxes the day columns draw. All-day events produce none —
132
- * they are the band's business — and so does an event whose day is not on show or whose
133
- * hours fall entirely outside the window.
131
+ * Cuts the timed events into the boxes the day columns draw. All-day events produce none;
132
+ * they belong in the band. Nor does an event whose day is not on show or whose hours fall
133
+ * entirely outside the window.
134
134
  *
135
135
  * `minDuration` is applied HERE, by stretching the end, so that `packDayColumn` below sees
136
136
  * ordinary intervals and can stay a plain interval algorithm. Were the minimum applied
@@ -142,7 +142,7 @@ export declare function timedSegments(events: readonly CalendarEvent[], days: re
142
142
  export interface PlacedSegment extends EventSegment {
143
143
  /** Which column of its cluster it sits in, counted from zero. */
144
144
  column: number;
145
- /** How many columns it takes up — more than one when the room beside it is free. */
145
+ /** How many columns it takes up: more than one when the room beside it is free. */
146
146
  span: number;
147
147
  /** How many columns its cluster has. It is what both of the above are read against. */
148
148
  columns: number;
@@ -150,7 +150,7 @@ export interface PlacedSegment extends EventSegment {
150
150
  /**
151
151
  * Shares one day's width out between the events happening at the same time.
152
152
  *
153
- * Three passes. First the segments are cut into CLUSTERS — runs joined by overlap, where an
153
+ * Three passes. First the segments are cut into CLUSTERS: runs joined by overlap, where an
154
154
  * event starting after everything before it has finished begins a new one. That is what
155
155
  * stops a crowded morning from squeezing a lone afternoon meeting into a sliver. Then,
156
156
  * inside a cluster, each event takes the first column whose last occupant has already
@@ -159,13 +159,13 @@ export interface PlacedSegment extends EventSegment {
159
159
  * nothing in the next column overlaps it, so a single event never leaves a gap it could
160
160
  * have filled.
161
161
  *
162
- * The order is fixed — by start, then longest first, then by id — so the same list always
162
+ * The order is fixed by start, then longest first, then by id, so the same list always
163
163
  * produces the same picture. Without the id to break the last tie, two events at the same
164
164
  * time for the same length would swap places whenever the array was re-sorted, and the
165
165
  * whole day would appear to shuffle for no reason.
166
166
  *
167
- * Overlap is strictly `a.start < b.end && b.start < a.end`, so events that merely touch —
168
- * one ending exactly as the next begins — share a column instead of splitting the width.
167
+ * Overlap is strictly `a.start < b.end && b.start < a.end`, so events that merely touch
168
+ * (one ending exactly as the next begins) share a column instead of splitting the width.
169
169
  */
170
170
  export declare function packDayColumn(segments: readonly EventSegment[]): PlacedSegment[];
171
171
  /**
@@ -180,8 +180,8 @@ export type { MonthCell };
180
180
  /**
181
181
  * The month view, cut into weeks.
182
182
  *
183
- * It keeps the fixed six rows `buildMonthGrid` produces — padded with the neighbouring
184
- * months — so the grid is the same height whichever month is on show and the page does not
183
+ * It keeps the fixed six rows `buildMonthGrid` produces: padded with the neighbouring
184
+ * months, so the grid is the same height whichever month is on show and the page does not
185
185
  * jump as one steps through the year. Each row is then filtered down to the visible
186
186
  * weekdays, which is what makes a Monday-to-Friday month five columns wide rather than
187
187
  * seven with two blanks.
@@ -189,6 +189,16 @@ export type { MonthCell };
189
189
  export declare function monthWeeks(anchor: string, weekdays: readonly number[]): MonthCell[][];
190
190
  /** The first day of each month of the anchor's year, which is what the year view lays out. */
191
191
  export declare function monthsOfYear(anchor: string): string[];
192
+ /**
193
+ * The last day an event puts anything on.
194
+ *
195
+ * Its `end` date, except for a timed event ending at midnight EXACTLY: it has nothing on
196
+ * that day, which is why `timedSegments` draws it whole on its first day. Every other view
197
+ * has to agree, or twenty-four hours from one midnight to the next becomes a two-day bar and
198
+ * an evening ending at 00:00 is listed on the following day too. An all-day event's dates
199
+ * are whole days, so its end is kept as it stands.
200
+ */
201
+ export declare function lastDayOf(event: CalendarEvent): string;
192
202
  /** Whether an event covers a given day at all, all-day or timed. */
193
203
  export declare function coversDay(event: CalendarEvent, iso: string): boolean;
194
204
  /**
@@ -198,12 +208,12 @@ export declare function coversDay(event: CalendarEvent, iso: string): boolean;
198
208
  *
199
209
  * WHY ONE PASS RATHER THAN A FILTER PER DAY. The month view needs all 42 squares filled, and
200
210
  * filtering and sorting the list once per square walks the whole event list 42 times and sorts
201
- * it 42 times — `cells × events`, with a sort each. Measured on the bench: 7.8 ms per render at
211
+ * it 42 times: `cells × events`, with a sort each. Measured on the bench: 7.8 ms per render at
202
212
  * 2000 events, and the month view rebuilds it every time a drag carries a chip onto another
203
213
  * day, so that is roughly half a frame spent rebuilding lists the gesture left alone.
204
214
  *
205
215
  * Here each event is placed once, into the days it actually covers, and each day is sorted
206
- * once — `events × span + cells × k log k`. The walk is bounded to the grid on both ends, so
216
+ * once: `events × span + cells × k log k`. The walk is bounded to the grid on both ends, so
207
217
  * an event running from last year costs its visible part and nothing more.
208
218
  */
209
219
  export declare function eventsByDay<T extends CalendarEvent>(events: readonly T[], days: readonly string[]): Map<string, T[]>;
@@ -229,8 +239,8 @@ export interface AllDaySpan {
229
239
  * one day on the Friday and one on the following Monday, because those are the two days it
230
240
  * actually covers on screen.
231
241
  *
232
- * The rows are the same greedy pass the day columns use — each bar takes the first row
233
- * whose last bar has already ended — and the ordering is fixed, longest first at equal
242
+ * The rows are the same greedy pass the day columns use: each bar takes the first row
243
+ * whose last bar has already ended, and the ordering is fixed, longest first at equal
234
244
  * starts, so the band cannot reshuffle when the array is re-sorted.
235
245
  */
236
246
  export declare function packAllDay(events: readonly CalendarEvent[], days: readonly string[]): AllDaySpan[];
@@ -250,7 +260,7 @@ export interface GridGeometry {
250
260
  * and what moment that height stands for.
251
261
  *
252
262
  * Both answers are brought back inside the grid, so a pointer dragged past an edge keeps
253
- * producing the nearest sensible value rather than none — which is what makes a drag that
263
+ * producing the nearest sensible value rather than none. That is what makes a drag that
254
264
  * wanders off the component behave as the user expects instead of stopping dead.
255
265
  */
256
266
  export declare function pointToCell(point: {
@@ -262,10 +272,10 @@ export declare function pointToCell(point: {
262
272
  };
263
273
  /** Rounds a moment to the nearest step the calendar allows. */
264
274
  export declare function snapToSlot(minutes: number, step: number): number;
265
- /** Rounds a moment DOWN to the step containing it — where a drawn slot begins. */
275
+ /** Rounds a moment DOWN to the step containing it: where a drawn slot begins. */
266
276
  export declare function floorToSlot(minutes: number, step: number): number;
267
277
  /**
268
- * How many whole days an event covers beyond its first — zero for one that starts and ends
278
+ * How many whole days an event covers beyond its first: zero for one that starts and ends
269
279
  * on the same day, two for a trip from Monday to Wednesday.
270
280
  */
271
281
  export declare function daySpan(times: CalendarEventTimes): number;
@@ -275,11 +285,11 @@ export declare function daySpan(times: CalendarEventTimes): number;
275
285
  * This is the counterpart of `timeGrid.ts`'s `moveEvent`, and the two must not be confused: that one is for
276
286
  * a timed move INSIDE a single day and deliberately collapses `end` onto `start`, so putting
277
287
  * a three-day trip through it would silently squash it into one Tuesday. This one is for the
278
- * whole-day gestures — an all-day bar dragged along the band, a chip dragged across a month —
288
+ * whole-day gestures (an all-day bar dragged along the band, a chip dragged across a month),
279
289
  * where the times are carried along untouched and only the dates move.
280
290
  */
281
291
  export declare function moveEventToDay(origin: CalendarEventTimes, target: string): CalendarEventTimes;
282
- /** The measurements of a month grid — the same struct, with rows where a time window was. */
292
+ /** The measurements of a month grid: the same struct, with rows where a time window was. */
283
293
  export interface MonthGeometry extends GridGeometry {
284
294
  rows: number;
285
295
  }
@@ -287,7 +297,7 @@ export interface MonthGeometry extends GridGeometry {
287
297
  * Turns a point on the screen into a square of the month.
288
298
  *
289
299
  * The block axis is a ROW here rather than a moment, which is the whole difference from
290
- * `pointToCell` — the inline half is the same arithmetic, RTL flip included. It is sound
300
+ * `pointToCell`: the inline half is the same arithmetic, RTL flip included. It is sound
291
301
  * because every week of a month is drawn the same height: the rows share what space there is
292
302
  * and a day too full for its box clips rather than growing.
293
303
  */
@@ -303,7 +313,7 @@ export declare function pointToMonthCell(point: {
303
313
  * edge, 1 for the end one, nothing in between.
304
314
  *
305
315
  * It answers in READING order, so the start edge is the left one normally and the right one
306
- * in a right-to-left page — which is what makes "hold at the edge to go back" mean the same
316
+ * in a right-to-left page. That makes "hold at the edge to go back" mean the same
307
317
  * thing in both.
308
318
  */
309
319
  export declare function inlineEdgeAt(x: number, geometry: {
@@ -323,7 +333,7 @@ export declare function blockEdgeAt(y: number, geometry: {
323
333
  height: number;
324
334
  }, band: number): number;
325
335
  /**
326
- * Whether a point falls inside a box — how a drag decides, on release, whether it is over the
336
+ * Whether a point falls inside a box: how a drag decides, on release, whether it is over the
327
337
  * calendar at all or over the toolbar, or over the page beside it.
328
338
  *
329
339
  * It takes the box as the browser MEASURED it, and never the `GridGeometry` the rest of this file
@@ -336,10 +346,10 @@ export declare function blockEdgeAt(y: number, geometry: {
336
346
  * The edges COUNT as inside: a rect is a pair of floats on a screen that may be scaled by a
337
347
  * fraction, and an exclusive boundary would refuse a drop that looked, and was, on target.
338
348
  *
339
- * TRAP — a box that measures nothing contains EVERYTHING. That is the same answer `inlineEdgeAt`
349
+ * TRAP: a box that measures nothing contains EVERYTHING. That is the same answer `inlineEdgeAt`
340
350
  * and `blockEdgeAt` give a box of no size, and for the same reason: with no measurement there is
341
351
  * no outside to be on. Take a zero-size box literally instead and the calendar refuses every drop
342
- * wherever nothing has been laid out — in a hidden tab, before the first frame, and in jsdom,
352
+ * wherever nothing has been laid out: in a hidden tab, before the first frame, and in jsdom,
343
353
  * which measures nothing at all and where all but a handful of the drag tests would go red at
344
354
  * once.
345
355
  */
@@ -359,7 +369,7 @@ export declare function timesOf(event: CalendarEvent): CalendarEventTimes;
359
369
  *
360
370
  * It is what a drag asks before it writes its preview. A slot is a quarter of an hour, some
361
371
  * sixteen pixels at the default hour height, so most pointer moves land on the times already
362
- * shown — and the gesture state is deeply reactive, so an EQUAL but new object would still
372
+ * shown, and the gesture state is deeply reactive, so an EQUAL but new object would still
363
373
  * re-run the whole layout and re-render every cell of the grid for a picture that did not
364
374
  * change.
365
375
  */