vectis-ui 0.10.0 → 0.10.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (334) hide show
  1. package/dist/components/VAccordion/VAccordion.js.map +1 -1
  2. package/dist/components/VAccordion/VAccordion.vue_vue_type_script_setup_true_lang.js.map +1 -1
  3. package/dist/components/VAccordion/VAccordionItem.d.ts +6 -21
  4. package/dist/components/VAccordion/VAccordionItem.js.map +1 -1
  5. package/dist/components/VAccordion/VAccordionItem.vue_vue_type_script_setup_true_lang.js.map +1 -1
  6. package/dist/components/VAccordion/context.js.map +1 -1
  7. package/dist/components/VAvatar/VAvatar.d.ts +2 -12
  8. package/dist/components/VAvatar/VAvatar.js.map +1 -1
  9. package/dist/components/VAvatar/VAvatar.vue_vue_type_script_setup_true_lang.js.map +1 -1
  10. package/dist/components/VAvatar/VAvatarGroup.d.ts +2 -2
  11. package/dist/components/VAvatar/VAvatarGroup.js.map +1 -1
  12. package/dist/components/VAvatar/VAvatarGroup.vue_vue_type_script_setup_true_lang.js +6 -6
  13. package/dist/components/VAvatar/VAvatarGroup.vue_vue_type_script_setup_true_lang.js.map +1 -1
  14. package/dist/components/VAvatar/context.d.ts +1 -5
  15. package/dist/components/VAvatar/context.js.map +1 -1
  16. package/dist/components/VBadge/VBadge.d.ts +13 -27
  17. package/dist/components/VBadge/VBadge.js.map +1 -1
  18. package/dist/components/VBadge/VBadge.vue_vue_type_script_setup_true_lang.js.map +1 -1
  19. package/dist/components/VBreadcrumb/VBreadcrumb.d.ts +3 -9
  20. package/dist/components/VBreadcrumb/VBreadcrumb.js.map +1 -1
  21. package/dist/components/VBreadcrumb/VBreadcrumb.vue_vue_type_script_setup_true_lang.js.map +1 -1
  22. package/dist/components/VButton/VButton.d.ts +10 -17
  23. package/dist/components/VButton/VButton.js.map +1 -1
  24. package/dist/components/VButton/VButton.vue_vue_type_script_setup_true_lang.js.map +1 -1
  25. package/dist/components/VButton/VButtonGroup.d.ts +6 -15
  26. package/dist/components/VButton/VButtonGroup.js.map +1 -1
  27. package/dist/components/VButton/VButtonGroup.vue_vue_type_script_setup_true_lang.js.map +1 -1
  28. package/dist/components/VButton/context.d.ts +1 -9
  29. package/dist/components/VButton/context.js.map +1 -1
  30. package/dist/components/VCalendar/VCalendar.d.ts +9 -24
  31. package/dist/components/VCalendar/VCalendar.js.map +1 -1
  32. package/dist/components/VCalendar/VCalendar.vue_vue_type_script_setup_true_lang.js.map +1 -1
  33. package/dist/components/VCalendar/VCalendarEvent.d.ts +4 -13
  34. package/dist/components/VCalendar/VCalendarEvent.js.map +1 -1
  35. package/dist/components/VCalendar/VCalendarEvent.vue_vue_type_script_setup_true_lang.js.map +1 -1
  36. package/dist/components/VCalendar/VCalendarMonth.js.map +1 -1
  37. package/dist/components/VCalendar/VCalendarMonth.vue_vue_type_script_setup_true_lang.js.map +1 -1
  38. package/dist/components/VCalendar/VCalendarTimeGrid.d.ts +1 -5
  39. package/dist/components/VCalendar/VCalendarTimeGrid.js.map +1 -1
  40. package/dist/components/VCalendar/VCalendarTimeGrid.vue_vue_type_script_setup_true_lang.js.map +1 -1
  41. package/dist/components/VCalendar/VCalendarYear.js.map +1 -1
  42. package/dist/components/VCalendar/VCalendarYear.vue_vue_type_script_setup_true_lang.js.map +1 -1
  43. package/dist/components/VCalendar/color.d.ts +1 -7
  44. package/dist/components/VCalendar/color.js.map +1 -1
  45. package/dist/components/VCalendar/edgeStep.d.ts +5 -15
  46. package/dist/components/VCalendar/edgeStep.js.map +1 -1
  47. package/dist/components/VCalendar/gesture.d.ts +12 -36
  48. package/dist/components/VCalendar/gesture.js.map +1 -1
  49. package/dist/components/VCalendar/keyboard.d.ts +5 -42
  50. package/dist/components/VCalendar/keyboard.js.map +1 -1
  51. package/dist/components/VCalendar/layout.d.ts +38 -199
  52. package/dist/components/VCalendar/layout.js.map +1 -1
  53. package/dist/components/VCalendar/timeGrid.d.ts +3 -25
  54. package/dist/components/VCalendar/timeGrid.js.map +1 -1
  55. package/dist/components/VCalendar/types.d.ts +6 -23
  56. package/dist/components/VCarousel/VCarousel.d.ts +25 -96
  57. package/dist/components/VCarousel/VCarousel.js.map +1 -1
  58. package/dist/components/VCarousel/VCarousel.vue_vue_type_script_setup_true_lang.js +6 -6
  59. package/dist/components/VCarousel/VCarousel.vue_vue_type_script_setup_true_lang.js.map +1 -1
  60. package/dist/components/VCarousel/VCarouselItem.d.ts +1 -6
  61. package/dist/components/VCarousel/VCarouselItem.js.map +1 -1
  62. package/dist/components/VCarousel/VCarouselItem.vue_vue_type_script_setup_true_lang.js.map +1 -1
  63. package/dist/components/VCarousel/context.js.map +1 -1
  64. package/dist/components/VCheckbox/VCheckbox.d.ts +1 -5
  65. package/dist/components/VCheckbox/VCheckbox.js.map +1 -1
  66. package/dist/components/VCheckbox/VCheckbox.vue_vue_type_script_setup_true_lang.js.map +1 -1
  67. package/dist/components/VChip/VChip.d.ts +2 -8
  68. package/dist/components/VChip/VChip.js.map +1 -1
  69. package/dist/components/VChip/VChip.vue_vue_type_script_setup_true_lang.js.map +1 -1
  70. package/dist/components/VCombobox/VCombobox.d.ts +21 -59
  71. package/dist/components/VCombobox/VCombobox.js.map +1 -1
  72. package/dist/components/VCombobox/VCombobox.vue_vue_type_script_setup_true_lang.js +117 -119
  73. package/dist/components/VCombobox/VCombobox.vue_vue_type_script_setup_true_lang.js.map +1 -1
  74. package/dist/components/VCombobox/VComboboxGroup.js.map +1 -1
  75. package/dist/components/VCombobox/VComboboxGroup.vue_vue_type_script_setup_true_lang.js.map +1 -1
  76. package/dist/components/VCombobox/VComboboxOption.js.map +1 -1
  77. package/dist/components/VCombobox/VComboboxOption.vue_vue_type_script_setup_true_lang.js.map +1 -1
  78. package/dist/components/VCombobox/VComboboxSeparator.js.map +1 -1
  79. package/dist/components/VCombobox/VComboboxSeparator.vue_vue_type_script_setup_true_lang.js.map +1 -1
  80. package/dist/components/VCombobox/infiniteScroll.d.ts +4 -10
  81. package/dist/components/VCombobox/infiniteScroll.js.map +1 -1
  82. package/dist/components/VDataTable/VDataTable.d.ts +11 -36
  83. package/dist/components/VDataTable/VDataTable.js.map +1 -1
  84. package/dist/components/VDataTable/VDataTable.vue_vue_type_script_setup_true_lang.js +23 -20
  85. package/dist/components/VDataTable/VDataTable.vue_vue_type_script_setup_true_lang.js.map +1 -1
  86. package/dist/components/VDateInput/VDateInput.d.ts +12 -21
  87. package/dist/components/VDateInput/VDateInput.js.map +1 -1
  88. package/dist/components/VDateInput/VDateInput.vue_vue_type_script_setup_true_lang.js.map +1 -1
  89. package/dist/components/VDateInput/mask.d.ts +14 -59
  90. package/dist/components/VDateInput/mask.js.map +1 -1
  91. package/dist/components/VDatePicker/VDatePicker.d.ts +6 -12
  92. package/dist/components/VDatePicker/VDatePicker.js.map +1 -1
  93. package/dist/components/VDatePicker/VDatePicker.vue_vue_type_script_setup_true_lang.js.map +1 -1
  94. package/dist/components/VDatePicker/keyboard.d.ts +10 -42
  95. package/dist/components/VDatePicker/keyboard.js.map +1 -1
  96. package/dist/components/VDatePicker/names.d.ts +8 -22
  97. package/dist/components/VDatePicker/names.js.map +1 -1
  98. package/dist/components/VDialog/VDialog.d.ts +5 -10
  99. package/dist/components/VDialog/VDialog.js.map +1 -1
  100. package/dist/components/VDialog/VDialog.vue_vue_type_script_setup_true_lang.js +51 -53
  101. package/dist/components/VDialog/VDialog.vue_vue_type_script_setup_true_lang.js.map +1 -1
  102. package/dist/components/VDialog/VDialogAlert.d.ts +2 -3
  103. package/dist/components/VDialog/VDialogAlert.js.map +1 -1
  104. package/dist/components/VDialog/VDialogAlert.vue_vue_type_script_setup_true_lang.js.map +1 -1
  105. package/dist/components/VFileInput/VFileInput.d.ts +11 -37
  106. package/dist/components/VFileInput/VFileInput.js.map +1 -1
  107. package/dist/components/VFileInput/VFileInput.vue_vue_type_script_setup_true_lang.js.map +1 -1
  108. package/dist/components/VFileInput/truncate.d.ts +3 -23
  109. package/dist/components/VFileInput/truncate.js.map +1 -1
  110. package/dist/components/VFilePicker/VFilePicker.d.ts +15 -65
  111. package/dist/components/VFilePicker/VFilePicker.js.map +1 -1
  112. package/dist/components/VFilePicker/VFilePicker.vue_vue_type_script_setup_true_lang.js.map +1 -1
  113. package/dist/components/VFilePicker/fileKind.js.map +1 -1
  114. package/dist/components/VHotkeys/VHotkeys.d.ts +6 -15
  115. package/dist/components/VHotkeys/VHotkeys.js.map +1 -1
  116. package/dist/components/VHotkeys/VHotkeys.vue_vue_type_script_setup_true_lang.js.map +1 -1
  117. package/dist/components/VHotkeys/platform.d.ts +10 -49
  118. package/dist/components/VHotkeys/platform.js.map +1 -1
  119. package/dist/components/VIcon/VIcon.d.ts +7 -19
  120. package/dist/components/VIcon/VIcon.js.map +1 -1
  121. package/dist/components/VIcon/VIcon.vue_vue_type_script_setup_true_lang.js.map +1 -1
  122. package/dist/components/VIcon/iconProps.d.ts +5 -19
  123. package/dist/components/VIcon/iconProps.js.map +1 -1
  124. package/dist/components/VIcon/resolver.d.ts +15 -43
  125. package/dist/components/VIcon/resolver.js.map +1 -1
  126. package/dist/components/VIcon/types.d.ts +7 -34
  127. package/dist/components/VIconButton/VIconButton.d.ts +2 -3
  128. package/dist/components/VIconButton/VIconButton.js.map +1 -1
  129. package/dist/components/VIconButton/VIconButton.vue_vue_type_script_setup_true_lang.js.map +1 -1
  130. package/dist/components/VInput/VInput.d.ts +14 -29
  131. package/dist/components/VInput/VInput.js.map +1 -1
  132. package/dist/components/VInput/VInput.vue_vue_type_script_setup_true_lang.js.map +1 -1
  133. package/dist/components/VInput/VInputGroup.js.map +1 -1
  134. package/dist/components/VInput/VInputGroup.vue_vue_type_script_setup_true_lang.js +34 -50
  135. package/dist/components/VInput/VInputGroup.vue_vue_type_script_setup_true_lang.js.map +1 -1
  136. package/dist/components/VInput/context.js.map +1 -1
  137. package/dist/components/VInputOTP/VInputOTP.d.ts +8 -16
  138. package/dist/components/VInputOTP/VInputOTP.js.map +1 -1
  139. package/dist/components/VInputOTP/VInputOTP.vue_vue_type_script_setup_true_lang.js +55 -63
  140. package/dist/components/VInputOTP/VInputOTP.vue_vue_type_script_setup_true_lang.js.map +1 -1
  141. package/dist/components/VMenu/VMenu.js.map +1 -1
  142. package/dist/components/VMenu/VMenu.vue_vue_type_script_setup_true_lang.js.map +1 -1
  143. package/dist/components/VMenu/VMenuGroup.d.ts +1 -6
  144. package/dist/components/VMenu/VMenuGroup.js.map +1 -1
  145. package/dist/components/VMenu/VMenuGroup.vue_vue_type_script_setup_true_lang.js.map +1 -1
  146. package/dist/components/VMenu/VMenuItem.d.ts +0 -5
  147. package/dist/components/VMenu/VMenuItem.js.map +1 -1
  148. package/dist/components/VMenu/VMenuItem.vue_vue_type_script_setup_true_lang.js.map +1 -1
  149. package/dist/components/VMenu/VMenuPanel.d.ts +1 -6
  150. package/dist/components/VMenu/VMenuPanel.js.map +1 -1
  151. package/dist/components/VMenu/VMenuPanel.vue_vue_type_script_setup_true_lang.js +2 -2
  152. package/dist/components/VMenu/VMenuPanel.vue_vue_type_script_setup_true_lang.js.map +1 -1
  153. package/dist/components/VMenu/VMenuSeparator.js.map +1 -1
  154. package/dist/components/VMenu/VMenuSeparator.vue_vue_type_script_setup_true_lang.js.map +1 -1
  155. package/dist/components/VMenu/context.d.ts +3 -11
  156. package/dist/components/VMenu/context.js.map +1 -1
  157. package/dist/components/VPagination/VPagination.d.ts +9 -20
  158. package/dist/components/VPagination/VPagination.js.map +1 -1
  159. package/dist/components/VPagination/VPagination.vue_vue_type_script_setup_true_lang.js.map +1 -1
  160. package/dist/components/VPopover/VPopover.d.ts +7 -18
  161. package/dist/components/VPopover/VPopover.js.map +1 -1
  162. package/dist/components/VPopover/VPopover.vue_vue_type_script_setup_true_lang.js +23 -27
  163. package/dist/components/VPopover/VPopover.vue_vue_type_script_setup_true_lang.js.map +1 -1
  164. package/dist/components/VProgressCircular/VProgressCircular.d.ts +2 -6
  165. package/dist/components/VProgressCircular/VProgressCircular.js.map +1 -1
  166. package/dist/components/VProgressCircular/VProgressCircular.vue_vue_type_script_setup_true_lang.js.map +1 -1
  167. package/dist/components/VProgressLinear/VProgressLinear.d.ts +4 -15
  168. package/dist/components/VProgressLinear/VProgressLinear.js.map +1 -1
  169. package/dist/components/VProgressLinear/VProgressLinear.vue_vue_type_script_setup_true_lang.js.map +1 -1
  170. package/dist/components/VRadio/VRadio.d.ts +1 -5
  171. package/dist/components/VRadio/VRadio.js.map +1 -1
  172. package/dist/components/VRadio/VRadio.vue_vue_type_script_setup_true_lang.js.map +1 -1
  173. package/dist/components/VSeparator/VSeparator.d.ts +2 -15
  174. package/dist/components/VSeparator/VSeparator.js.map +1 -1
  175. package/dist/components/VSeparator/VSeparator.vue_vue_type_script_setup_true_lang.js.map +1 -1
  176. package/dist/components/VSideNavigation/VSideNavigation.d.ts +1 -1
  177. package/dist/components/VSideNavigation/VSideNavigation.js.map +1 -1
  178. package/dist/components/VSideNavigation/VSideNavigation.vue_vue_type_script_setup_true_lang.js.map +1 -1
  179. package/dist/components/VSideNavigation/VSideNavigationGroup.d.ts +1 -5
  180. package/dist/components/VSideNavigation/VSideNavigationGroup.js.map +1 -1
  181. package/dist/components/VSideNavigation/VSideNavigationGroup.vue_vue_type_script_setup_true_lang.js.map +1 -1
  182. package/dist/components/VSideNavigation/VSideNavigationItem.d.ts +1 -5
  183. package/dist/components/VSideNavigation/VSideNavigationItem.js.map +1 -1
  184. package/dist/components/VSideNavigation/VSideNavigationItem.vue_vue_type_script_setup_true_lang.js +80 -75
  185. package/dist/components/VSideNavigation/VSideNavigationItem.vue_vue_type_script_setup_true_lang.js.map +1 -1
  186. package/dist/components/VSideNavigation/VSideNavigationSeparator.js.map +1 -1
  187. package/dist/components/VSideNavigation/context.js.map +1 -1
  188. package/dist/components/VSkeletonLoader/VSkeletonLoader.d.ts +6 -19
  189. package/dist/components/VSkeletonLoader/VSkeletonLoader.js.map +1 -1
  190. package/dist/components/VSkeletonLoader/VSkeletonLoader.vue_vue_type_script_setup_true_lang.js.map +1 -1
  191. package/dist/components/VSlider/VSlider.d.ts +5 -13
  192. package/dist/components/VSlider/VSlider.js.map +1 -1
  193. package/dist/components/VSlider/VSlider.vue_vue_type_script_setup_true_lang.js.map +1 -1
  194. package/dist/components/VSnackbar/VSnackbar.js.map +1 -1
  195. package/dist/components/VSnackbar/VSnackbar.vue_vue_type_script_setup_true_lang.js.map +1 -1
  196. package/dist/components/VSnackbar/state.d.ts +4 -17
  197. package/dist/components/VSnackbar/state.js.map +1 -1
  198. package/dist/components/VSpinner/VSpinner.d.ts +3 -5
  199. package/dist/components/VSpinner/VSpinner.js.map +1 -1
  200. package/dist/components/VSpinner/VSpinner.vue_vue_type_script_setup_true_lang.js.map +1 -1
  201. package/dist/components/VSwitch/VSwitch.js.map +1 -1
  202. package/dist/components/VSwitch/VSwitch.vue_vue_type_script_setup_true_lang.js.map +1 -1
  203. package/dist/components/VTabs/VTab.d.ts +1 -5
  204. package/dist/components/VTabs/VTab.js.map +1 -1
  205. package/dist/components/VTabs/VTab.vue_vue_type_script_setup_true_lang.js.map +1 -1
  206. package/dist/components/VTabs/VTabPanel.js.map +1 -1
  207. package/dist/components/VTabs/VTabPanel.vue_vue_type_script_setup_true_lang.js.map +1 -1
  208. package/dist/components/VTabs/VTabs.d.ts +5 -17
  209. package/dist/components/VTabs/VTabs.js.map +1 -1
  210. package/dist/components/VTabs/VTabs.vue_vue_type_script_setup_true_lang.js.map +1 -1
  211. package/dist/components/VTabs/context.js.map +1 -1
  212. package/dist/components/VTextarea/VTextarea.d.ts +13 -20
  213. package/dist/components/VTextarea/VTextarea.js.map +1 -1
  214. package/dist/components/VTextarea/VTextarea.vue_vue_type_script_setup_true_lang.js.map +1 -1
  215. package/dist/components/VTimeInput/VTimeInput.d.ts +8 -21
  216. package/dist/components/VTimeInput/VTimeInput.js.map +1 -1
  217. package/dist/components/VTimeInput/VTimeInput.vue_vue_type_script_setup_true_lang.js.map +1 -1
  218. package/dist/components/VTimeInput/search.d.ts +3 -34
  219. package/dist/components/VTimeInput/search.js.map +1 -1
  220. package/dist/components/VTimePicker/VTimePicker.d.ts +9 -31
  221. package/dist/components/VTimePicker/VTimePicker.js.map +1 -1
  222. package/dist/components/VTimePicker/VTimePicker.vue_vue_type_script_setup_true_lang.js.map +1 -1
  223. package/dist/components/VTimePicker/limits.d.ts +18 -45
  224. package/dist/components/VTimePicker/limits.js.map +1 -1
  225. package/dist/components/VToast/VToast.js.map +1 -1
  226. package/dist/components/VToast/VToast.vue_vue_type_script_setup_true_lang.js.map +1 -1
  227. package/dist/components/VToast/VToaster.js.map +1 -1
  228. package/dist/components/VToast/VToaster.vue_vue_type_script_setup_true_lang.js.map +1 -1
  229. package/dist/components/VToast/state.d.ts +2 -7
  230. package/dist/components/VToast/state.js.map +1 -1
  231. package/dist/components/VToggle/VToggle.d.ts +5 -9
  232. package/dist/components/VToggle/VToggle.js.map +1 -1
  233. package/dist/components/VToggle/VToggle.vue_vue_type_script_setup_true_lang.js.map +1 -1
  234. package/dist/components/VToggle/VToggleItem.d.ts +1 -9
  235. package/dist/components/VToggle/VToggleItem.js.map +1 -1
  236. package/dist/components/VToggle/VToggleItem.vue_vue_type_script_setup_true_lang.js.map +1 -1
  237. package/dist/components/VToggle/context.js.map +1 -1
  238. package/dist/components/VTooltip/VTooltip.d.ts +3 -16
  239. package/dist/components/VTooltip/VTooltip.js.map +1 -1
  240. package/dist/components/VTooltip/VTooltip.vue_vue_type_script_setup_true_lang.js +2 -2
  241. package/dist/components/VTooltip/VTooltip.vue_vue_type_script_setup_true_lang.js.map +1 -1
  242. package/dist/components/VTypography/VTypography.d.ts +4 -8
  243. package/dist/components/VTypography/VTypography.js.map +1 -1
  244. package/dist/components/VTypography/VTypography.vue_vue_type_script_setup_true_lang.js.map +1 -1
  245. package/dist/composables/useAriaLabel.js.map +1 -1
  246. package/dist/composables/useClearable.d.ts +2 -8
  247. package/dist/composables/useClearable.js.map +1 -1
  248. package/dist/composables/useControlShape.js.map +1 -1
  249. package/dist/composables/useDetailsOpen.d.ts +2 -10
  250. package/dist/composables/useDetailsOpen.js.map +1 -1
  251. package/dist/composables/useFieldIds.js.map +1 -1
  252. package/dist/composables/useFieldPanel.d.ts +4 -17
  253. package/dist/composables/useFieldPanel.js.map +1 -1
  254. package/dist/composables/useFileDrop.js.map +1 -1
  255. package/dist/composables/useFileField.d.ts +1 -5
  256. package/dist/composables/useFileField.js.map +1 -1
  257. package/dist/composables/useFocusoutDismiss.js.map +1 -1
  258. package/dist/composables/useIconClickHandlers.d.ts +4 -19
  259. package/dist/composables/useIconClickHandlers.js.map +1 -1
  260. package/dist/composables/useInertLink.d.ts +1 -1
  261. package/dist/composables/useInertLink.js.map +1 -1
  262. package/dist/composables/useLiveAnnouncer.js.map +1 -1
  263. package/dist/composables/useMaskedField.d.ts +12 -27
  264. package/dist/composables/useMaskedField.js.map +1 -1
  265. package/dist/composables/usePopover.d.ts +3 -11
  266. package/dist/composables/usePopover.js.map +1 -1
  267. package/dist/composables/useProgressValue.js.map +1 -1
  268. package/dist/composables/useRootAttrs.d.ts +0 -9
  269. package/dist/composables/useRootAttrs.js +11 -4
  270. package/dist/composables/useRootAttrs.js.map +1 -1
  271. package/dist/composables/useSlotNodes.d.ts +3 -14
  272. package/dist/composables/useSlotNodes.js.map +1 -1
  273. package/dist/composables/useTextLimit.d.ts +4 -16
  274. package/dist/composables/useTextLimit.js.map +1 -1
  275. package/dist/composables/useTimer.d.ts +2 -15
  276. package/dist/composables/useTimer.js.map +1 -1
  277. package/dist/i18n/en.js.map +1 -1
  278. package/dist/i18n/fr.js.map +1 -1
  279. package/dist/i18n/state.d.ts +9 -38
  280. package/dist/i18n/state.js.map +1 -1
  281. package/dist/i18n/types.d.ts +19 -81
  282. package/dist/icons.d.ts +2 -12
  283. package/dist/styles.css +1 -1
  284. package/dist/tokens/css.d.ts +3 -16
  285. package/dist/tokens/css.js.map +1 -1
  286. package/dist/tokens/index.d.ts +5 -0
  287. package/dist/tokens/index.js.map +1 -1
  288. package/dist/tokens/primitives.js.map +1 -1
  289. package/dist/tokens/semantic.d.ts +6 -23
  290. package/dist/tokens/semantic.js +5 -0
  291. package/dist/tokens/semantic.js.map +1 -1
  292. package/dist/tokens/themes/dark.js.map +1 -1
  293. package/dist/tokens/types.d.ts +2 -12
  294. package/dist/tokens/types.js.map +1 -1
  295. package/dist/tokens.json +14 -0
  296. package/dist/types.d.ts +3 -21
  297. package/dist/utils/array.d.ts +2 -4
  298. package/dist/utils/array.js.map +1 -1
  299. package/dist/utils/arrowNav.d.ts +2 -26
  300. package/dist/utils/arrowNav.js.map +1 -1
  301. package/dist/utils/chip.d.ts +1 -8
  302. package/dist/utils/chip.js.map +1 -1
  303. package/dist/utils/clock.d.ts +16 -39
  304. package/dist/utils/clock.js.map +1 -1
  305. package/dist/utils/css.d.ts +5 -16
  306. package/dist/utils/css.js.map +1 -1
  307. package/dist/utils/date.d.ts +17 -60
  308. package/dist/utils/date.js.map +1 -1
  309. package/dist/utils/direction.d.ts +2 -9
  310. package/dist/utils/direction.js.map +1 -1
  311. package/dist/utils/env.d.ts +2 -15
  312. package/dist/utils/env.js.map +1 -1
  313. package/dist/utils/file.d.ts +8 -46
  314. package/dist/utils/file.js.map +1 -1
  315. package/dist/utils/focus.d.ts +1 -14
  316. package/dist/utils/focus.js +1 -6
  317. package/dist/utils/focus.js.map +1 -1
  318. package/dist/utils/hostWarns.d.ts +3 -8
  319. package/dist/utils/hostWarns.js.map +1 -1
  320. package/dist/utils/ids.d.ts +2 -7
  321. package/dist/utils/ids.js.map +1 -1
  322. package/dist/utils/matcher.d.ts +1 -8
  323. package/dist/utils/matcher.js.map +1 -1
  324. package/dist/utils/memo.d.ts +1 -11
  325. package/dist/utils/memo.js.map +1 -1
  326. package/dist/utils/number.d.ts +1 -7
  327. package/dist/utils/number.js.map +1 -1
  328. package/dist/utils/text.d.ts +4 -23
  329. package/dist/utils/text.js.map +1 -1
  330. package/dist/utils/time.d.ts +4 -12
  331. package/dist/utils/time.js.map +1 -1
  332. package/dist/utils/vnode.d.ts +0 -10
  333. package/dist/utils/vnode.js.map +1 -1
  334. package/package.json +1 -1
@@ -7,36 +7,21 @@ import { CalendarEvent, CalendarEventId, CalendarEventTimes } from './types.js';
7
7
  * two would collide in every map the layout keys by id and only one would ever be drawn.
8
8
  */
9
9
  export declare const ghostIdOf: (id: CalendarEventId) => string;
10
- /**
11
- * The dragged event's own id, read back off its ghost's. It is what the card is handed as
12
- * `ghostOf`: an event's colour is derived from its id, so a ghost coloured from its own
13
- * would not match the card it belongs to. `hueOf` reads a number and its digits as the same
14
- * event, so the string form returned here is enough.
15
- */
10
+ /** The dragged event's own id, read back off its ghost's. */
16
11
  export declare const originalIdOf: (id: CalendarEventId) => string;
17
12
  export declare const isGhostId: (id: CalendarEventId) => boolean;
18
- /**
19
- * The id a card belongs to, read back off the DOM.
20
- *
21
- * An id may be a NUMBER and an attribute is always text, so a numeric one has to be turned
22
- * back into one: otherwise every card of a numerically-keyed calendar would look up as a
23
- * miss and nothing would drag. Which of the two it is, is settled by asking the map that
24
- * holds the originals rather than by guessing from the text.
25
- */
13
+ /** The id a card belongs to, read back off the DOM. */
26
14
  export declare function cardIdOf(card: HTMLElement, has: (id: CalendarEventId) => boolean): string | number;
27
15
  /**
28
- * A grid's measured box as the pure geometry wants it: plain numbers, no element.
29
- *
30
16
  * `inlineStart` is the edge the first column starts at, which is the RIGHT one in a
31
- * right-to-left page. This is also why containment never goes through this, see
32
- * `pointWithin`.
17
+ * right-to-left page.
33
18
  */
34
19
  export declare function gridGeometryOf(rect: DOMRect, columns: number, rtl: boolean): GridGeometry;
35
20
  /** The state every gesture carries, whatever each grid adds to it. */
36
21
  export interface GestureBase {
37
22
  id: CalendarEventId;
38
23
  /**
39
- * Where the event was when the gesture began. Every pointer frame is computed from THIS and
24
+ * Where the event was when the gesture began. Every pointer frame is computed from this and
40
25
  * never from the frame before it, so a long drag cannot accumulate rounding drift.
41
26
  */
42
27
  origin: CalendarEventTimes;
@@ -52,19 +37,17 @@ export interface GestureBase {
52
37
  */
53
38
  lastX: number;
54
39
  lastY: number;
55
- /** Whether it moved past the threshold, which is what separates a drag from a click. */
40
+ /** Whether it moved past the threshold, which separates a drag from a click. */
56
41
  moved: boolean;
57
42
  /**
58
43
  * Whether the pointer is off the calendar altogether: over the toolbar, or over the page
59
- * beside it. Letting go there abandons the gesture whole and writes nothing.
60
- *
61
- * A KEYBOARD grab can never set it, and structurally rather than by a guard: `onPointermove`
62
- * is the only writer, and it returns on the id mismatch first: a grab's `pointerId` is null,
63
- * which no real pointer's id ever equals.
44
+ * beside it. A KEYBOARD grab can never set it, and structurally rather than by a guard:
45
+ * `onPointermove` is the only writer, and it returns on the id mismatch first: a grab's
46
+ * `pointerId` is null, which no real pointer's id ever equals.
64
47
  */
65
48
  outside: boolean;
66
49
  /**
67
- * The reading direction, read ONCE when the gesture begins. It cannot change under a live
50
+ * The reading direction, read once when the gesture begins. It cannot change under a live
68
51
  * drag, and asking the document on every frame costs a style resolution each time.
69
52
  */
70
53
  rtl: boolean;
@@ -72,9 +55,8 @@ export interface GestureBase {
72
55
  /** What a grid hands over to start a gesture; the rest is filled in here. */
73
56
  export type GestureInit<G extends GestureBase> = Omit<G, 'preview' | 'lastX' | 'lastY' | 'moved' | 'outside' | 'rtl'>;
74
57
  /**
75
- * A gesture held by the KEYBOARD rather than by a pointer: grabbed with Space, and waiting
76
- * for the arrows to move it. Both grids draw the card differently in that state, which is
77
- * what makes it worth a name.
58
+ * A gesture held by the KEYBOARD rather than by a pointer: grabbed with Space, and waiting for
59
+ * the arrows to move it.
78
60
  */
79
61
  export declare const isGrabbed: (state: GestureBase | null) => boolean;
80
62
  /** The two intents that move a grabbed event, which only a grid can turn into times. */
@@ -86,14 +68,8 @@ export interface CalendarGestureOptions<E extends CalendarEvent, G extends Gestu
86
68
  events: () => readonly E[];
87
69
  /** The event drawn under an id, for the handlers. */
88
70
  eventOf: (id: CalendarEventId) => E | undefined;
89
- /** The view's own box: what "outside the calendar" is measured against. */
90
71
  rootEl: Ref<HTMLElement | null>;
91
- /**
92
- * The element the pointer is captured on once a press travels. It must contain every surface
93
- * a gesture can start on, and carry the move, up, cancel and leave bindings: capture retargets
94
- * every later pointer event to it, which is what makes one set of bindings serve every kind of
95
- * gesture.
96
- */
72
+ /** The element the pointer is captured on once a press travels. */
97
73
  captureEl: Ref<HTMLElement | null>;
98
74
  /** The box the cells occupy, which points and edges are read against. */
99
75
  measureEl: Ref<HTMLElement | null>;
@@ -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. 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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"}
1
+ {"version":3,"file":"gesture.js","names":[],"sources":["../../../src/components/VCalendar/gesture.ts"],"sourcesContent":["// @keyboard @a11y @core\n/**\n * Share pointer and keyboard editing gestures across month and time-grid views; each view\n * supplies its own cell geometry.\n */\nimport { computed, nextTick, ref, watch } from 'vue'\nimport type { Ref } from 'vue'\n\nimport { isRtl as isElementRtl } from '../../utils/direction'\n\nimport { useMessages } from '../../i18n/state'\n\nimport { EDGE_BAND, useEdgeStep } from './edgeStep'\nimport { calendarIntent, type CalendarIntent } from './keyboard'\nimport { DRAG_THRESHOLD, inlineEdgeAt, pointWithin, type GridGeometry } from './layout'\nimport type { CalendarEvent, CalendarEventId, CalendarEventTimes } from './types'\n\n/**\n * The prefix marking the copy an event leaves behind at its old place while it is being\n * dragged.\n */\nconst GHOST_PREFIX = '__vectis-calendar-ghost__'\n\n/**\n * The id the ghost of a dragged event carries. It has to DIFFER from the event's own, or the\n * two would collide in every map the layout keys by id and only one would ever be drawn.\n */\nexport const ghostIdOf = (id: CalendarEventId) => `${GHOST_PREFIX}${id}`\n/** The dragged event's own id, read back off its ghost's. */\nexport const originalIdOf = (id: CalendarEventId) => String(id).slice(GHOST_PREFIX.length)\nexport const isGhostId = (id: CalendarEventId) => String(id).startsWith(GHOST_PREFIX)\n\n/** The id a card belongs to, read back off the DOM. */\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 * `inlineStart` is the edge the first column starts at, which is the RIGHT one in a\n * right-to-left page.\n */\nexport function gridGeometryOf(rect: DOMRect, columns: number, rtl: boolean): GridGeometry {\n return {\n top: rect.top,\n height: rect.height,\n inlineStart: rtl ? rect.right : rect.left,\n inlineSize: rect.width,\n columns,\n }\n}\n\n/** The state every gesture carries, whatever each grid adds to it. */\nexport interface GestureBase {\n id: CalendarEventId\n /**\n * Where the event was when the gesture began. Every pointer frame is computed from this and\n * never from the frame before it, so a long drag cannot accumulate rounding drift.\n */\n origin: CalendarEventTimes\n /** What the card shows right now. The model is not touched until the gesture ends. */\n preview: CalendarEventTimes\n /** The pointer holding the gesture, or null for a keyboard grab. */\n pointerId: number | null\n originX: number\n originY: number\n /**\n * Where the pointer last was. Two things move the calendar UNDER a still pointer: paging at\n * an edge, and auto-scrolling. Each has to work out afresh what the pointer is now over.\n */\n lastX: number\n lastY: number\n /** Whether it moved past the threshold, which separates a drag from a click. */\n moved: boolean\n /**\n * Whether the pointer is off the calendar altogether: over the toolbar, or over the page\n * beside it. A KEYBOARD grab can never set it, and structurally rather than by a guard:\n * `onPointermove` is the only writer, and it returns on the id mismatch first: a grab's\n * `pointerId` is null, which no real pointer's id ever equals.\n */\n outside: boolean\n /**\n * The reading direction, read once when the gesture begins. It cannot change under a live\n * drag, and asking the document on every frame costs a style resolution each time.\n */\n rtl: boolean\n}\n\n/** What a grid hands over to start a gesture; the rest is filled in here. */\nexport type GestureInit<G extends GestureBase> = Omit<\n G,\n 'preview' | 'lastX' | 'lastY' | 'moved' | 'outside' | 'rtl'\n>\n\n/**\n * A gesture held by the KEYBOARD rather than by a pointer: grabbed with Space, and waiting for\n * the arrows to move it.\n */\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 rootEl: Ref<HTMLElement | null>\n /** The element the pointer is captured on once a press travels. */\n captureEl: Ref<HTMLElement | null>\n /** The box the cells occupy, which points and edges are read against. */\n measureEl: Ref<HTMLElement | null>\n /** How many columns that box is divided into. */\n columns: () => number\n /** Whether events may be moved at all. */\n editable: () => boolean\n /** The node every card points at to say how it can be moved. */\n hintId: () => string\n /** The step a grabbed event moves by, handed to the keyboard table. */\n slotMinutes: () => number\n edgeStepDelay: () => number\n /** Whatever the grid's cells are made of, so paging under a still pointer re-places the card. */\n layout: () => unknown\n /** Works out where the gesture's event belongs from the pointer's last position. */\n applyPoint: (state: G, rect: DOMRect) => void\n /** Called on every pointer move past the threshold, after the edge watch, with both rects. */\n onEdges?: (state: G, rootRect: DOMRect | undefined) => void\n /** Everything else a gesture leaves running, dropped on every path out of one. */\n onRelease?: () => void\n /**\n * A pointer gesture let go inside the calendar. Returns true when the grid has answered it\n * itself, such as a slot drawn out, and nothing is left to drop.\n */\n onLetGo?: (state: G) => boolean\n /** A gesture that moved, committed: the grid reports the new times. */\n onDrop: (state: G) => void\n /** What a keyboard grab of this event starts, or null when it cannot be grabbed. */\n grab: (item: E) => GestureInit<G> | null\n /** Applies one arrow step to a grabbed event. Returns false when the step means nothing here. */\n onGrabStep: (state: G, step: GrabStep, item: E) => boolean\n step: (direction: -1 | 1) => void\n announce: (message: string) => void\n}\n\nexport function useCalendarGesture<E extends CalendarEvent, G extends GestureBase>(\n options: CalendarGestureOptions<E, G>,\n) {\n const m = useMessages()\n const gesture = ref<G | null>(null) as Ref<G | null>\n\n /** True while a card is being held by the keyboard rather than dragged by a pointer. */\n const grabbing = computed(() => isGrabbed(gesture.value))\n\n const isRtl = () => isElementRtl(options.measureEl.value)\n\n /**\n * The echo of where the gestured event began, so the reader can see what they are moving it\n * FROM. A press that has not travelled yet produces none, or a click would flash a second\n * card over the first.\n */\n const ghostEvent = computed<E | null>(() => {\n const state = gesture.value\n if (!state?.moved) return null\n const original = options.events().find((event) => event.id === state.id)\n return original ? ({ ...original, ...state.origin, id: ghostIdOf(state.id) } as E) : null\n })\n\n /** A list with the gestured event moved to wherever it is now, plus its echo. */\n function withPreview(events: readonly E[]): E[] {\n const state = gesture.value\n if (!state) return [...events]\n const moving = events.map((event) =>\n event.id === state.id ? ({ ...event, ...state.preview } as E) : event,\n )\n return ghostEvent.value ? [...moving, ghostEvent.value] : moving\n }\n\n /**\n * Set click suppression on pointerup, not pointercancel; clear it before every press guard\n * and keyboard activation. Captured releases may never send their click to an event card.\n */\n let dragged = false\n\n /** Closes the books on the previous gesture. */\n function endLastGesture() {\n dragged = false\n if (grabbing.value) revertGrab()\n }\n\n /** Puts a keyboard grab back where it was taken from, writing nothing, and says so. */\n function revertGrab() {\n const state = gesture.value\n if (!state) return\n gesture.value = null\n options.announce(m.value.calendar.reverted)\n return state\n }\n\n /**\n * A keyboard grab ends when the focus moves on to something else, the toolbar or another\n * control.\n */\n function onFocusout(event: FocusEvent) {\n const state = gesture.value\n const next = event.relatedTarget as HTMLElement | null\n if (!grabbing.value || !state || !next) return\n const card = next.closest<HTMLElement>('.v-calendar-event')\n if (card && card.dataset.eventId === String(state.id)) return\n revertGrab()\n }\n\n /** Whether the gesture that just ended actually moved; asking lowers the flag. */\n function consumeDrag() {\n const was = dragged\n dragged = false\n return was\n }\n\n const edge = useEdgeStep(options.step, options.edgeStepDelay)\n\n /** Which edge is counting down, as the attribute the stylesheet reads. */\n const edgeCue = computed(() =>\n edge.pending.value === -1 ? 'start' : edge.pending.value === 1 ? 'end' : undefined,\n )\n\n function release() {\n edge.cancel()\n options.onRelease?.()\n }\n\n /** Starts a gesture. */\n function start(init: GestureInit<G>, rtl = isRtl()) {\n gesture.value = {\n ...init,\n preview: { ...init.origin },\n lastX: init.originX,\n lastY: init.originY,\n moved: false,\n outside: false,\n rtl,\n } as G\n }\n\n /**\n * Called when the press crosses the drag threshold, never at the press. The browser sends the\n * `click` that follows a captured `pointerup` to the CAPTURE element, so a press captured at\n * once reaches the scroller instead of the card or the cell under it: clicking an event would\n * open nothing and clicking an empty slot would report nothing, on every calendar whose\n * events can be moved or drawn.\n */\n function capture(pointerId: number) {\n // @fallback\n /*\n * Synthetic pointer events may not have a capturable pointer; allow the gesture to continue\n * within the element if capture fails.\n */\n try {\n options.captureEl.value?.setPointerCapture(pointerId)\n } catch {\n /* Synthetic pointers cannot be captured. */\n }\n }\n\n function reapply(state: G) {\n const rect = options.measureEl.value?.getBoundingClientRect()\n if (rect) options.applyPoint(state, rect)\n }\n\n function onPointermove(event: PointerEvent) {\n const state = gesture.value\n if (!state || state.pointerId !== event.pointerId) return\n\n state.lastX = event.clientX\n state.lastY = event.clientY\n\n // Below the threshold nothing has happened yet. That is what keeps a click a click: the\n // hand's tremor during a press would otherwise register as a one-pixel drag.\n if (\n !state.moved &&\n Math.abs(event.clientX - state.originX) < DRAG_THRESHOLD &&\n Math.abs(event.clientY - state.originY) < DRAG_THRESHOLD\n ) {\n return\n }\n\n if (!state.moved) capture(event.pointerId)\n state.moved = true\n const rootRect = options.rootEl.value?.getBoundingClientRect()\n const rect = options.measureEl.value?.getBoundingClientRect()\n\n /*\n * Neither the placement nor the edge watch below is gated on it, and neither may become so.\n * The card must keep following the pointer while it is out, which makes coming back in\n * seamless, and paging must keep running, pushing past the edge being how one crosses into\n * the next period.\n */\n state.outside = rootRect ? !pointWithin({ x: state.lastX, y: state.lastY }, rootRect) : false\n\n if (!rect) return\n options.applyPoint(state, rect)\n edge.watchEdge(\n inlineEdgeAt(\n state.lastX,\n gridGeometryOf(rect, options.columns(), state.rtl),\n EDGE_BAND,\n state.rtl,\n ),\n )\n options.onEdges?.(state, rootRect)\n }\n\n function onPointerup(event: PointerEvent) {\n const state = gesture.value\n if (!state || state.pointerId !== event.pointerId) return\n gesture.value = null\n dragged = state.moved\n release()\n\n /*\n * Nothing is announced: the pointer says nothing on a SUCCESSFUL drop either; `grabbed`,\n * `dropped` and `reverted` belong to the keyboard grab, which has no pointer to show where\n * the event went.\n */\n if (state.outside) return\n if (options.onLetGo?.(state)) return\n // A press that never travelled is an ordinary click, which the button's own click event is\n // about to report. Writing anything here would move an event nobody dragged.\n if (state.moved) options.onDrop(state)\n }\n\n /*\n * The gesture was taken away; a system gesture, a context menu, the page starting to scroll.\n * Nothing is written and nothing is announced: the card goes back to where the model still\n * says it is.\n */\n function onPointercancel(event: PointerEvent) {\n // Another pointer's cancel, a second finger starting to pan, is not this gesture's. A\n // keyboard grab carries no pointer id, so no cancel can end it either.\n if (gesture.value?.pointerId !== event.pointerId) return\n abandon()\n }\n\n function abandon() {\n gesture.value = null\n release()\n }\n\n /*\n * Its `pointerup` then lands outside and never reaches the bindings, so without this the\n * gesture would outlive the press: a mouse keeps the same pointer id, and bringing it back\n * over the calendar with the button up would pick the event up and carry it. A captured\n * pointer never leaves, so a real drag is untouched.\n */\n function onPointerleave(event: PointerEvent) {\n const state = gesture.value\n if (!state || state.pointerId !== event.pointerId || state.moved) return\n abandon()\n }\n\n /*\n * Paging swaps the cells out from under a live drag, and the dragged event's day is then off\n * screen; the card would vanish until the next pointer move, which never comes if the hand is\n * holding still against the edge. Re-applying the last position once the new cells are\n * rendered is what keeps the card under the pointer across the boundary.\n */\n watch(\n options.layout,\n () => {\n const state = gesture.value\n if (state?.moved) reapply(state)\n },\n { flush: 'post' },\n )\n\n /**\n * The card is found by WALKING the cards rather than by building an attribute selector. An id\n * belongs to the consumer, so it may hold a quote or a backslash a selector would need\n * escaped, and `CSS.escape` cannot do that escaping here: jsdom defines no `CSS` object at\n * all, so the call threw on every keyboard grab, from inside a `nextTick` where nothing could\n * catch it; an unhandled rejection, which fails the run while every assertion still passes.\n */\n function refocusCard(id: CalendarEventId) {\n void nextTick(() => {\n // Searched from the view's root: the time grid's all-day bars sit in its sticky header,\n // outside the box the cells occupy.\n const cards = options.rootEl.value?.querySelectorAll<HTMLElement>('.v-calendar-event')\n Array.from(cards ?? [])\n .find((card) => card.dataset.eventId === String(id))\n ?.focus()\n })\n }\n\n /** Puts the focus on a cell by its id, once the render that made it tabbable has run. */\n function focusCell(id: string, deferred = false, focusOptions?: FocusOptions) {\n const move = () => document.getElementById(id)?.focus(focusOptions)\n if (deferred) void nextTick(move)\n else move()\n }\n\n /** The event a card stands for, read back off the attribute the card publishes. */\n const idOfCard = (card: HTMLElement) => cardIdOf(card, (id) => options.eventOf(id) !== undefined)\n\n /**\n * A card answers a different table from the grid it sits in; that is what a grab mode IS.\n * Without it the grid would offer a gesture the pointer alone could reach (WCAG 2.1.1).\n */\n function onCardKeydown(event: KeyboardEvent, card: HTMLElement) {\n // Whatever click follows is this key's, never the end of an earlier drag.\n dragged = false\n const item = options.eventOf(idOfCard(card))\n if (!item) return\n\n const held = grabbing.value && gesture.value?.id === item.id\n const state = held ? gesture.value! : null\n const intent = calendarIntent(\n event,\n held ? 'grabbed' : 'event',\n options.slotMinutes(),\n state?.rtl ?? isRtl(),\n )\n if (!intent) return\n\n if (!state) {\n // An event that cannot be moved keeps a button's ordinary behaviour: Space presses it,\n // which the card's click handler reports.\n const init = intent.kind === 'grab' ? options.grab(item) : null\n if (!init) return\n /*\n * Cancelling the keydown is what stops that press, so the keystroke that takes hold of\n * the event does not open it too: without it every attempt to move something would fire\n * the consumer's editor over it.\n */\n event.preventDefault()\n start(init)\n options.announce(m.value.calendar.grabbed)\n return\n }\n\n event.preventDefault()\n\n if (intent.kind === 'grabMove' || intent.kind === 'grabResize') {\n if (!options.onGrabStep(state, intent, item)) return\n state.moved = true\n refocusCard(state.id)\n return\n }\n\n if (intent.kind === 'activate') {\n gesture.value = null\n if (state.moved) options.onDrop(state)\n options.announce(m.value.calendar.dropped)\n refocusCard(state.id)\n return\n }\n\n if (intent.kind === 'cancel') {\n revertGrab()\n refocusCard(state.id)\n }\n }\n\n /**\n * The five things every card is told about the gesture, bound with `v-bind` so the two grids\n * cannot describe the same state in two different ways.\n */\n function cardState(id: CalendarEventId) {\n const state = gesture.value\n const mine = state !== null && state.id === id\n return {\n /*\n * Only once the press has travelled. A dragged card takes no pointer events, so marked at\n * the press it lets the release land on the cell beneath it: the click then goes to that\n * cell, and clicking an event reports an empty slot instead of opening it.\n */\n dragging: mine && state.pointerId !== null && state.moved,\n rejected: mine && state.outside,\n grabbed: mine && state.pointerId === null,\n hintId: options.editable() && !isGhostId(id) ? options.hintId() : undefined,\n ghostOf: isGhostId(id) ? originalIdOf(id) : undefined,\n }\n }\n\n return {\n gesture,\n grabbing,\n ghostEvent,\n withPreview,\n edgeCue,\n isRtl,\n start,\n reapply,\n release,\n endLastGesture,\n consumeDrag,\n onPointermove,\n onPointerup,\n onPointercancel,\n onPointerleave,\n onFocusout,\n onCardKeydown,\n refocusCard,\n focusCell,\n idOfCard,\n cardState,\n }\n}\n"],"mappings":"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"}
@@ -1,25 +1,6 @@
1
1
  /**
2
- * The pure half of VCalendar's keyboard: it answers the single question "what does this
3
- * key mean here?", and does nothing else. Moving the focus, writing to the model, calling
4
- * `preventDefault` and announcing the result all stay in the component, where the reactive
5
- * state lives.
6
- *
7
- * It sits in VCalendar's own folder rather than in `utils/` because it has exactly one
8
- * consumer, which fails the admission rule for shared code (the same reasoning as
9
- * `VDatePicker/keyboard.ts` and `VHotkeys/platform.ts`). Being pure is also what makes the
10
- * whole keyboard testable without mounting anything, since the environment the tests run
11
- * in lays nothing out and the handlers in the component only ever move DOM focus.
12
- *
13
- * `utils/arrowNav` is deliberately not used. It navigates a flat DOM list of controls; this
14
- * navigates a two-dimensional space of DATES AND TIMES whose edges are a domain clamp, not
15
- * a list end — the same reason VDatePicker, VCombobox and VTimePicker stay out of it.
16
- *
17
- * WHY A GRAB MODE, and not arrows that move an event outright. Every gesture the pointer
18
- * offers has to have a keyboard equivalent (WCAG 2.1.1), and a card is reached by the
19
- * arrows in the first place — so if the arrows also moved it, arriving at an event and
20
- * nudging it would be the same keystroke, and there would be no way to pass over one
21
- * without dragging it. Entering a mode separates the two, and Escape gives back the one
22
- * thing a pointer drag has that a keypress does not: the chance to change your mind.
2
+ * Decode calendar keys without side effects; focus, model updates and announcements remain with
3
+ * the view.
23
4
  */
24
5
  /** What one key means, given where the focus is. */
25
6
  export type CalendarIntent =
@@ -67,15 +48,8 @@ export type CalendarIntent =
67
48
  minutes: number;
68
49
  };
69
50
  /**
70
- * Where the focus is when the key arrives, which is what decides the answer:
71
- *
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,
75
- * Enter included, which presses the card as a button and so opens the event. Enter is the
76
- * one a reader tries first on a button, and `event-activate` has no other keyboard route.
77
- * - `grabbed`: a card being moved. The arrows now move the EVENT, Enter commits, Escape
78
- * puts it back where it was.
51
+ * Where the focus is when the key arrives, which decides the answer: - `cell`: an empty part of
52
+ * the grid.
79
53
  */
80
54
  export type CalendarFocus = 'cell' | 'event' | 'grabbed';
81
55
  /** The part of a keyboard event the table reads; a `KeyboardEvent` is one. */
@@ -86,16 +60,5 @@ export interface KeyChord {
86
60
  ctrlKey?: boolean;
87
61
  metaKey?: boolean;
88
62
  }
89
- /**
90
- * What a key means. Returning nothing says the key is none of this table's business and
91
- * the event must be left entirely alone. That keeps keeps Tab, the browser's own
92
- * shortcuts and anything a consumer has bound working.
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
- *
98
- * `rtl` is passed in rather than read here: which way is "forward" is a property of the
99
- * document, and a pure table has no business consulting one.
100
- */
63
+ /** What a key means. */
101
64
  export declare function calendarIntent(chord: KeyChord, focus: CalendarFocus, slotMinutes: number, rtl: boolean): CalendarIntent | undefined;
@@ -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 /** 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"}
1
+ {"version":3,"file":"keyboard.js","names":[],"sources":["../../../src/components/VCalendar/keyboard.ts"],"sourcesContent":["// @keyboard @a11y\n/**\n * Decode calendar keys without side effects; focus, model updates and announcements remain with\n * the view.\n */\n\nimport { MINUTES_PER_HOUR } from './layout'\n\n/** What one key means, given where the focus is. */\nexport type CalendarIntent =\n /** Move the focused cell by whole days and whole hours. */\n | { kind: 'moveFocus'; days: number; minutes: number }\n /** Jump to the first or last day of the row. */\n | { kind: 'rowEdge'; edge: 'start' | 'end' }\n /** Show the previous or next period, as the toolbar's buttons do. */\n | { kind: 'period'; delta: -1 | 1 }\n /** Take up what is focused: report an empty cell, or commit a move under way. */\n | { kind: 'activate' }\n /** Open the focused day, which only a month square offers. */\n | { kind: 'openDay' }\n /** Take hold of a card, so the arrows move it. */\n | { kind: 'grab' }\n /** Abandon a move under way and put the event back. */\n | { kind: 'cancel' }\n /** Move the grabbed event. */\n | { kind: 'grabMove'; days: number; minutes: number }\n /** Change how long the grabbed event lasts. */\n | { kind: 'grabResize'; minutes: number }\n\n/**\n * Where the focus is when the key arrives, which decides the answer: - `cell`: an empty part of\n * the grid.\n */\nexport type CalendarFocus = 'cell' | 'event' | 'grabbed'\n\n/** The part of a keyboard event the table reads; a `KeyboardEvent` is one. */\nexport interface KeyChord {\n key: string\n shiftKey?: boolean\n altKey?: boolean\n ctrlKey?: boolean\n metaKey?: boolean\n}\n\n/** What a key means. */\nexport function calendarIntent(\n chord: KeyChord,\n focus: CalendarFocus,\n slotMinutes: number,\n rtl: boolean,\n): CalendarIntent | undefined {\n if (chord.altKey || chord.ctrlKey || chord.metaKey) return undefined\n const { key } = chord\n const shiftKey = chord.shiftKey === true\n const step = slotMinutes > 0 ? slotMinutes : 1\n // The inline arrows follow the reading direction; the block ones never do, because down\n // is later in the day in every script.\n const inline = rtl ? -1 : 1\n\n if (focus === 'grabbed') {\n switch (key) {\n case 'ArrowLeft':\n return { kind: 'grabMove', days: -inline, minutes: 0 }\n case 'ArrowRight':\n return { kind: 'grabMove', days: inline, minutes: 0 }\n case 'ArrowUp':\n return shiftKey\n ? { kind: 'grabResize', minutes: -step }\n : { kind: 'grabMove', days: 0, minutes: -step }\n case 'ArrowDown':\n return shiftKey\n ? { kind: 'grabResize', minutes: step }\n : { kind: 'grabMove', days: 0, minutes: step }\n case 'Enter':\n case ' ':\n return { kind: 'activate' }\n case 'Escape':\n return { kind: 'cancel' }\n default:\n return undefined\n }\n }\n\n if (focus === 'event') return key === ' ' ? { kind: 'grab' } : undefined\n\n switch (key) {\n case 'ArrowLeft':\n return { kind: 'moveFocus', days: -inline, minutes: 0 }\n case 'ArrowRight':\n return { kind: 'moveFocus', days: inline, minutes: 0 }\n case 'ArrowUp':\n return { kind: 'moveFocus', days: 0, minutes: -MINUTES_PER_HOUR }\n case 'ArrowDown':\n return { kind: 'moveFocus', days: 0, minutes: MINUTES_PER_HOUR }\n case 'Home':\n return { kind: 'rowEdge', edge: 'start' }\n case 'End':\n return { kind: 'rowEdge', edge: 'end' }\n case 'PageUp':\n return { kind: 'period', delta: -1 }\n case 'PageDown':\n return { kind: 'period', delta: 1 }\n case 'Enter':\n return shiftKey ? { kind: 'openDay' } : { kind: 'activate' }\n case ' ':\n return { kind: 'activate' }\n default:\n return undefined\n }\n}\n"],"mappings":";AA6CA,SAAgB,EACd,GACA,GACA,GACA,GAC4B;CAC5B,IAAI,EAAM,UAAU,EAAM,WAAW,EAAM,SAAS;CACpD,IAAM,EAAE,WAAQ,GACV,IAAW,EAAM,aAAa,IAC9B,IAAO,IAAc,IAAI,IAAc,GAGvC,IAAS,IAAM,KAAK;CAE1B,IAAI,MAAU,WACZ,QAAQ,GAAR;EACE,KAAK,aACH,OAAO;GAAE,MAAM;GAAY,MAAM,CAAC;GAAQ,SAAS;EAAE;EACvD,KAAK,cACH,OAAO;GAAE,MAAM;GAAY,MAAM;GAAQ,SAAS;EAAE;EACtD,KAAK,WACH,OAAO,IACH;GAAE,MAAM;GAAc,SAAS,CAAC;EAAK,IACrC;GAAE,MAAM;GAAY,MAAM;GAAG,SAAS,CAAC;EAAK;EAClD,KAAK,aACH,OAAO,IACH;GAAE,MAAM;GAAc,SAAS;EAAK,IACpC;GAAE,MAAM;GAAY,MAAM;GAAG,SAAS;EAAK;EACjD,KAAK;EACL,KAAK,KACH,OAAO,EAAE,MAAM,WAAW;EAC5B,KAAK,UACH,OAAO,EAAE,MAAM,SAAS;EAC1B,SACE;CACJ;CAGF,IAAI,MAAU,SAAS,OAAO,MAAQ,MAAM,EAAE,MAAM,OAAO,IAAI,KAAA;CAE/D,QAAQ,GAAR;EACE,KAAK,aACH,OAAO;GAAE,MAAM;GAAa,MAAM,CAAC;GAAQ,SAAS;EAAE;EACxD,KAAK,cACH,OAAO;GAAE,MAAM;GAAa,MAAM;GAAQ,SAAS;EAAE;EACvD,KAAK,WACH,OAAO;GAAE,MAAM;GAAa,MAAM;GAAG,SAAS;EAAkB;EAClE,KAAK,aACH,OAAO;GAAE,MAAM;GAAa,MAAM;GAAG,SAAA;EAA0B;EACjE,KAAK,QACH,OAAO;GAAE,MAAM;GAAW,MAAM;EAAQ;EAC1C,KAAK,OACH,OAAO;GAAE,MAAM;GAAW,MAAM;EAAM;EACxC,KAAK,UACH,OAAO;GAAE,MAAM;GAAU,OAAO;EAAG;EACrC,KAAK,YACH,OAAO;GAAE,MAAM;GAAU,OAAO;EAAE;EACpC,KAAK,SACH,OAAO,IAAW,EAAE,MAAM,UAAU,IAAI,EAAE,MAAM,WAAW;EAC7D,KAAK,KACH,OAAO,EAAE,MAAM,WAAW;EAC5B,SACE;CACJ;AACF"}