@rotki/ui-library 2.26.1 → 3.0.0-beta.1

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 (420) hide show
  1. package/README.md +36 -15
  2. package/dist/components/accordions/accordion/RuiAccordion.js.map +1 -1
  3. package/dist/components/accordions/accordion/RuiAccordion.vue.d.ts +0 -4
  4. package/dist/components/accordions/accordion/RuiAccordion.vue_vue_type_script_setup_true_lang.js +6 -7
  5. package/dist/components/accordions/accordion/RuiAccordion.vue_vue_type_script_setup_true_lang.js.map +1 -1
  6. package/dist/components/accordions/accordions/RuiAccordions.js.map +1 -1
  7. package/dist/components/accordions/accordions/RuiAccordions.vue_vue_type_script_setup_true_lang.js +15 -2
  8. package/dist/components/accordions/accordions/RuiAccordions.vue_vue_type_script_setup_true_lang.js.map +1 -1
  9. package/dist/components/alerts/RuiAlert.js.map +1 -1
  10. package/dist/components/alerts/RuiAlert.vue_vue_type_script_setup_true_lang.js +43 -212
  11. package/dist/components/alerts/RuiAlert.vue_vue_type_script_setup_true_lang.js.map +1 -1
  12. package/dist/components/avatars/RuiAvatar.js.map +1 -1
  13. package/dist/components/avatars/RuiAvatar.vue_vue_type_script_setup_true_lang.js +21 -31
  14. package/dist/components/avatars/RuiAvatar.vue_vue_type_script_setup_true_lang.js.map +1 -1
  15. package/dist/components/avatars/RuiAvatarGroup.js.map +1 -1
  16. package/dist/components/avatars/RuiAvatarGroup.vue.d.ts +6 -0
  17. package/dist/components/avatars/RuiAvatarGroup.vue_vue_type_script_setup_true_lang.js +16 -12
  18. package/dist/components/avatars/RuiAvatarGroup.vue_vue_type_script_setup_true_lang.js.map +1 -1
  19. package/dist/components/avatars/avatar-props.d.ts +16 -3
  20. package/dist/components/avatars/avatar-props.js +42 -5
  21. package/dist/components/avatars/avatar-props.js.map +1 -1
  22. package/dist/components/buttons/button/RuiButton.js.map +1 -1
  23. package/dist/components/buttons/button/RuiButton.vue.d.ts +0 -1
  24. package/dist/components/buttons/button/RuiButton.vue_vue_type_script_setup_true_lang.js +29 -16
  25. package/dist/components/buttons/button/RuiButton.vue_vue_type_script_setup_true_lang.js.map +1 -1
  26. package/dist/components/buttons/button/button-props.d.ts +0 -2
  27. package/dist/components/buttons/button/button-props.js +5 -5
  28. package/dist/components/buttons/button/button-props.js.map +1 -1
  29. package/dist/components/buttons/button/button-styles.d.ts +4 -1
  30. package/dist/components/buttons/button/button-styles.js +127 -54
  31. package/dist/components/buttons/button/button-styles.js.map +1 -1
  32. package/dist/components/buttons/button-group/RuiButtonGroup.js.map +1 -1
  33. package/dist/components/buttons/button-group/RuiButtonGroup.vue.d.ts +8 -2
  34. package/dist/components/buttons/button-group/RuiButtonGroup.vue_vue_type_script_setup_true_lang.js +65 -96
  35. package/dist/components/buttons/button-group/RuiButtonGroup.vue_vue_type_script_setup_true_lang.js.map +1 -1
  36. package/dist/components/buttons/button-group/button-group-context.d.ts +28 -0
  37. package/dist/components/buttons/button-group/button-group-context.js +22 -0
  38. package/dist/components/buttons/button-group/button-group-context.js.map +1 -0
  39. package/dist/components/calendar/RuiCalendar.js.map +1 -1
  40. package/dist/components/calendar/RuiCalendar.vue_vue_type_script_setup_true_lang.js +5 -2
  41. package/dist/components/calendar/RuiCalendar.vue_vue_type_script_setup_true_lang.js.map +1 -1
  42. package/dist/components/calendar/RuiCalendarGrid.js.map +1 -1
  43. package/dist/components/calendar/RuiCalendarGrid.vue_vue_type_script_setup_true_lang.js +11 -7
  44. package/dist/components/calendar/RuiCalendarGrid.vue_vue_type_script_setup_true_lang.js.map +1 -1
  45. package/dist/components/calendar/RuiCalendarHeader.js.map +1 -1
  46. package/dist/components/calendar/RuiCalendarHeader.vue_vue_type_script_setup_true_lang.js +20 -21
  47. package/dist/components/calendar/RuiCalendarHeader.vue_vue_type_script_setup_true_lang.js.map +1 -1
  48. package/dist/components/calendar/RuiCalendarMenu.js.map +1 -1
  49. package/dist/components/calendar/RuiCalendarMenu.vue_vue_type_script_setup_true_lang.js +16 -20
  50. package/dist/components/calendar/RuiCalendarMenu.vue_vue_type_script_setup_true_lang.js.map +1 -1
  51. package/dist/components/cards/RuiCard.js.map +1 -1
  52. package/dist/components/cards/RuiCard.vue.d.ts +0 -3
  53. package/dist/components/cards/RuiCard.vue_vue_type_script_setup_true_lang.js +31 -19
  54. package/dist/components/cards/RuiCard.vue_vue_type_script_setup_true_lang.js.map +1 -1
  55. package/dist/components/cards/RuiCardHeader.js.map +1 -1
  56. package/dist/components/cards/RuiCardHeader.vue_vue_type_script_setup_true_lang.js +13 -25
  57. package/dist/components/cards/RuiCardHeader.vue_vue_type_script_setup_true_lang.js.map +1 -1
  58. package/dist/components/chips/RuiChip.js.map +1 -1
  59. package/dist/components/chips/RuiChip.vue.d.ts +5 -2
  60. package/dist/components/chips/RuiChip.vue_vue_type_script_setup_true_lang.js +127 -78
  61. package/dist/components/chips/RuiChip.vue_vue_type_script_setup_true_lang.js.map +1 -1
  62. package/dist/components/chips/chip-props.d.ts +2 -0
  63. package/dist/components/chips/chip-props.js +5 -3
  64. package/dist/components/chips/chip-props.js.map +1 -1
  65. package/dist/components/color-picker/RuiColorBoard.js.map +1 -1
  66. package/dist/components/color-picker/RuiColorBoard.vue_vue_type_script_setup_true_lang.js +4 -4
  67. package/dist/components/color-picker/RuiColorBoard.vue_vue_type_script_setup_true_lang.js.map +1 -1
  68. package/dist/components/color-picker/RuiColorHue.js.map +1 -1
  69. package/dist/components/color-picker/RuiColorHue.vue_vue_type_script_setup_true_lang.js +1 -1
  70. package/dist/components/color-picker/RuiColorHue.vue_vue_type_script_setup_true_lang.js.map +1 -1
  71. package/dist/components/color-picker/RuiColorInput.js.map +1 -1
  72. package/dist/components/color-picker/RuiColorInput.vue_vue_type_script_setup_true_lang.js +38 -27
  73. package/dist/components/color-picker/RuiColorInput.vue_vue_type_script_setup_true_lang.js.map +1 -1
  74. package/dist/components/color-picker/RuiColorPicker.js.map +1 -1
  75. package/dist/components/color-picker/RuiColorPicker.vue_vue_type_script_setup_true_lang.js +1 -1
  76. package/dist/components/color-picker/RuiColorPicker.vue_vue_type_script_setup_true_lang.js.map +1 -1
  77. package/dist/components/date-time-picker/RuiDateTimePicker.js.map +1 -1
  78. package/dist/components/date-time-picker/RuiDateTimePicker.vue.d.ts +3 -2
  79. package/dist/components/date-time-picker/RuiDateTimePicker.vue_vue_type_script_setup_true_lang.js +49 -47
  80. package/dist/components/date-time-picker/RuiDateTimePicker.vue_vue_type_script_setup_true_lang.js.map +1 -1
  81. package/dist/components/date-time-picker/RuiDateTimePickerMenu.js.map +1 -1
  82. package/dist/components/date-time-picker/RuiDateTimePickerMenu.vue_vue_type_script_setup_true_lang.js +2 -2
  83. package/dist/components/date-time-picker/RuiDateTimePickerMenu.vue_vue_type_script_setup_true_lang.js.map +1 -1
  84. package/dist/components/date-time-picker/RuiTimezoneSelect.js.map +1 -1
  85. package/dist/components/date-time-picker/RuiTimezoneSelect.vue.d.ts +4 -3
  86. package/dist/components/date-time-picker/RuiTimezoneSelect.vue_vue_type_script_setup_true_lang.js +3 -3
  87. package/dist/components/date-time-picker/RuiTimezoneSelect.vue_vue_type_script_setup_true_lang.js.map +1 -1
  88. package/dist/components/date-time-picker/date-time-picker-styles.d.ts +128 -219
  89. package/dist/components/date-time-picker/date-time-picker-styles.js +1 -2
  90. package/dist/components/date-time-picker/date-time-picker-styles.js.map +1 -1
  91. package/dist/components/date-time-picker/dayjs-setup.d.ts +12 -1
  92. package/dist/components/date-time-picker/dayjs-setup.js +19 -4
  93. package/dist/components/date-time-picker/dayjs-setup.js.map +1 -1
  94. package/dist/components/date-time-picker/segment-utils.d.ts +1 -2
  95. package/dist/components/date-time-picker/segment-utils.js +1 -2
  96. package/dist/components/date-time-picker/segment-utils.js.map +1 -1
  97. package/dist/components/date-time-picker/use-date-bounds.d.ts +1 -1
  98. package/dist/components/date-time-picker/use-date-bounds.js +1 -1
  99. package/dist/components/date-time-picker/use-date-bounds.js.map +1 -1
  100. package/dist/components/date-time-picker/use-date-time-selection.d.ts +1 -2
  101. package/dist/components/date-time-picker/use-date-time-selection.js +1 -2
  102. package/dist/components/date-time-picker/use-date-time-selection.js.map +1 -1
  103. package/dist/components/date-time-picker/utils.d.ts +0 -1
  104. package/dist/components/date-time-picker/utils.js +1 -2
  105. package/dist/components/date-time-picker/utils.js.map +1 -1
  106. package/dist/components/forms/auto-complete/RuiAutoComplete.js.map +1 -1
  107. package/dist/components/forms/auto-complete/RuiAutoComplete.vue.d.ts +1 -68
  108. package/dist/components/forms/auto-complete/RuiAutoComplete.vue_vue_type_script_setup_true_lang.js +184 -180
  109. package/dist/components/forms/auto-complete/RuiAutoComplete.vue_vue_type_script_setup_true_lang.js.map +1 -1
  110. package/dist/components/forms/auto-complete/RuiAutoCompleteOption.js.map +1 -1
  111. package/dist/components/forms/auto-complete/RuiAutoCompleteOption.vue_vue_type_script_setup_true_lang.js +1 -0
  112. package/dist/components/forms/auto-complete/RuiAutoCompleteOption.vue_vue_type_script_setup_true_lang.js.map +1 -1
  113. package/dist/components/forms/auto-complete/RuiAutoCompleteOptionList.js.map +1 -1
  114. package/dist/components/forms/auto-complete/RuiAutoCompleteOptionList.vue.d.ts +2 -0
  115. package/dist/components/forms/auto-complete/RuiAutoCompleteOptionList.vue_vue_type_script_setup_true_lang.js +8 -3
  116. package/dist/components/forms/auto-complete/RuiAutoCompleteOptionList.vue_vue_type_script_setup_true_lang.js.map +1 -1
  117. package/dist/components/forms/auto-complete/RuiAutoCompleteSelection.js.map +1 -1
  118. package/dist/components/forms/auto-complete/RuiAutoCompleteSelection.vue.d.ts +4 -0
  119. package/dist/components/forms/auto-complete/RuiAutoCompleteSelection.vue_vue_type_script_setup_true_lang.js +24 -10
  120. package/dist/components/forms/auto-complete/RuiAutoCompleteSelection.vue_vue_type_script_setup_true_lang.js.map +1 -1
  121. package/dist/components/forms/auto-complete/auto-complete-props.d.ts +66 -0
  122. package/dist/components/forms/auto-complete/auto-complete-styles.d.ts +128 -218
  123. package/dist/components/forms/auto-complete/auto-complete-styles.js +4 -2
  124. package/dist/components/forms/auto-complete/auto-complete-styles.js.map +1 -1
  125. package/dist/components/forms/category-picker/RuiCategoryPicker.js.map +1 -1
  126. package/dist/components/forms/category-picker/RuiCategoryPicker.vue.d.ts +3 -6
  127. package/dist/components/forms/category-picker/RuiCategoryPicker.vue_vue_type_script_setup_true_lang.js +106 -105
  128. package/dist/components/forms/category-picker/RuiCategoryPicker.vue_vue_type_script_setup_true_lang.js.map +1 -1
  129. package/dist/components/forms/category-picker/category-picker-styles.d.ts +83 -232
  130. package/dist/components/forms/category-picker/category-picker-styles.js +20 -26
  131. package/dist/components/forms/category-picker/category-picker-styles.js.map +1 -1
  132. package/dist/components/forms/check-control-styles.d.ts +61 -2
  133. package/dist/components/forms/check-control-styles.js +53 -46
  134. package/dist/components/forms/check-control-styles.js.map +1 -1
  135. package/dist/components/forms/checkbox/RuiCheckbox.js.map +1 -1
  136. package/dist/components/forms/checkbox/RuiCheckbox.vue_vue_type_script_setup_true_lang.js +31 -18
  137. package/dist/components/forms/checkbox/RuiCheckbox.vue_vue_type_script_setup_true_lang.js.map +1 -1
  138. package/dist/components/forms/checkbox/checkbox-group/RuiCheckboxGroup.js.map +1 -1
  139. package/dist/components/forms/checkbox/checkbox-group/RuiCheckboxGroup.vue_vue_type_script_setup_true_lang.js +3 -3
  140. package/dist/components/forms/checkbox/checkbox-group/RuiCheckboxGroup.vue_vue_type_script_setup_true_lang.js.map +1 -1
  141. package/dist/components/forms/field-defaults/RuiFieldDefaults.js +7 -0
  142. package/dist/components/forms/field-defaults/RuiFieldDefaults.js.map +1 -0
  143. package/dist/components/forms/field-defaults/RuiFieldDefaults.vue.d.ts +16 -0
  144. package/dist/components/forms/field-defaults/RuiFieldDefaults.vue_vue_type_script_setup_true_lang.js +18 -0
  145. package/dist/components/forms/field-defaults/RuiFieldDefaults.vue_vue_type_script_setup_true_lang.js.map +1 -0
  146. package/dist/components/forms/field-label/RuiFieldLabel.js +7 -0
  147. package/dist/components/forms/field-label/RuiFieldLabel.js.map +1 -0
  148. package/dist/components/forms/field-label/RuiFieldLabel.vue.d.ts +17 -0
  149. package/dist/components/forms/field-label/RuiFieldLabel.vue_vue_type_script_setup_true_lang.js +57 -0
  150. package/dist/components/forms/field-label/RuiFieldLabel.vue_vue_type_script_setup_true_lang.js.map +1 -0
  151. package/dist/components/forms/file-upload/RuiFileUpload.js.map +1 -1
  152. package/dist/components/forms/file-upload/RuiFileUpload.vue.d.ts +1 -1
  153. package/dist/components/forms/file-upload/RuiFileUpload.vue_vue_type_script_setup_true_lang.js +39 -20
  154. package/dist/components/forms/file-upload/RuiFileUpload.vue_vue_type_script_setup_true_lang.js.map +1 -1
  155. package/dist/components/forms/radio-button/radio/RuiRadio.js.map +1 -1
  156. package/dist/components/forms/radio-button/radio/RuiRadio.vue_vue_type_script_setup_true_lang.js +13 -14
  157. package/dist/components/forms/radio-button/radio/RuiRadio.vue_vue_type_script_setup_true_lang.js.map +1 -1
  158. package/dist/components/forms/radio-button/radio-group/RuiRadioGroup.js.map +1 -1
  159. package/dist/components/forms/radio-button/radio-group/RuiRadioGroup.vue_vue_type_script_setup_true_lang.js +3 -3
  160. package/dist/components/forms/radio-button/radio-group/RuiRadioGroup.vue_vue_type_script_setup_true_lang.js.map +1 -1
  161. package/dist/components/forms/revealable-text-field/RuiRevealableTextField.js.map +1 -1
  162. package/dist/components/forms/revealable-text-field/RuiRevealableTextField.vue_vue_type_script_setup_true_lang.js +6 -6
  163. package/dist/components/forms/revealable-text-field/RuiRevealableTextField.vue_vue_type_script_setup_true_lang.js.map +1 -1
  164. package/dist/components/forms/select/RuiMenuSelect.js.map +1 -1
  165. package/dist/components/forms/select/RuiMenuSelect.vue.d.ts +3 -12
  166. package/dist/components/forms/select/RuiMenuSelect.vue_vue_type_script_setup_true_lang.js +50 -45
  167. package/dist/components/forms/select/RuiMenuSelect.vue_vue_type_script_setup_true_lang.js.map +1 -1
  168. package/dist/components/forms/select/RuiSimpleSelect.js.map +1 -1
  169. package/dist/components/forms/select/RuiSimpleSelect.vue.d.ts +0 -1
  170. package/dist/components/forms/select/RuiSimpleSelect.vue_vue_type_script_setup_true_lang.js +13 -20
  171. package/dist/components/forms/select/RuiSimpleSelect.vue_vue_type_script_setup_true_lang.js.map +1 -1
  172. package/dist/components/forms/select/menu-select-styles.d.ts +99 -221
  173. package/dist/components/forms/select/menu-select-styles.js +1 -4
  174. package/dist/components/forms/select/menu-select-styles.js.map +1 -1
  175. package/dist/components/forms/slider/RuiSlider.js.map +1 -1
  176. package/dist/components/forms/slider/RuiSlider.vue.d.ts +0 -4
  177. package/dist/components/forms/slider/RuiSlider.vue_vue_type_script_setup_true_lang.js +113 -90
  178. package/dist/components/forms/slider/RuiSlider.vue_vue_type_script_setup_true_lang.js.map +1 -1
  179. package/dist/components/forms/slider/slider-styles.d.ts +40 -40
  180. package/dist/components/forms/slider/slider-styles.js +67 -109
  181. package/dist/components/forms/slider/slider-styles.js.map +1 -1
  182. package/dist/components/forms/switch/RuiSwitch.js.map +1 -1
  183. package/dist/components/forms/switch/RuiSwitch.vue_vue_type_script_setup_true_lang.js +32 -44
  184. package/dist/components/forms/switch/RuiSwitch.vue_vue_type_script_setup_true_lang.js.map +1 -1
  185. package/dist/components/forms/text-area/RuiTextArea.js.map +1 -1
  186. package/dist/components/forms/text-area/RuiTextArea.vue.d.ts +3 -2
  187. package/dist/components/forms/text-area/RuiTextArea.vue_vue_type_script_setup_true_lang.js +120 -99
  188. package/dist/components/forms/text-area/RuiTextArea.vue_vue_type_script_setup_true_lang.js.map +1 -1
  189. package/dist/components/forms/text-area/text-area-styles.d.ts +41 -115
  190. package/dist/components/forms/text-area/text-area-styles.js +34 -194
  191. package/dist/components/forms/text-area/text-area-styles.js.map +1 -1
  192. package/dist/components/forms/text-field/RuiTextField.js.map +1 -1
  193. package/dist/components/forms/text-field/RuiTextField.vue.d.ts +3 -2
  194. package/dist/components/forms/text-field/RuiTextField.vue_vue_type_script_setup_true_lang.js +93 -90
  195. package/dist/components/forms/text-field/RuiTextField.vue_vue_type_script_setup_true_lang.js.map +1 -1
  196. package/dist/components/forms/text-field/text-field-styles.d.ts +37 -145
  197. package/dist/components/forms/text-field/text-field-styles.js +24 -267
  198. package/dist/components/forms/text-field/text-field-styles.js.map +1 -1
  199. package/dist/components/forms/text-input-styles.d.ts +98 -229
  200. package/dist/components/forms/text-input-styles.js +63 -193
  201. package/dist/components/forms/text-input-styles.js.map +1 -1
  202. package/dist/components/helpers/RuiFormTextDetail.js.map +1 -1
  203. package/dist/components/helpers/RuiFormTextDetail.vue_vue_type_script_setup_true_lang.js +2 -2
  204. package/dist/components/helpers/RuiFormTextDetail.vue_vue_type_script_setup_true_lang.js.map +1 -1
  205. package/dist/components/icons/RuiIcon.js.map +1 -1
  206. package/dist/components/icons/RuiIcon.vue_vue_type_script_setup_true_lang.js +6 -3
  207. package/dist/components/icons/RuiIcon.vue_vue_type_script_setup_true_lang.js.map +1 -1
  208. package/dist/components/index.d.ts +5 -3
  209. package/dist/components/index.js +4 -3
  210. package/dist/components/loaders/RuiSkeletonBase.js.map +1 -1
  211. package/dist/components/loaders/RuiSkeletonBase.vue_vue_type_script_setup_true_lang.js +6 -5
  212. package/dist/components/loaders/RuiSkeletonBase.vue_vue_type_script_setup_true_lang.js.map +1 -1
  213. package/dist/components/loaders/RuiSkeletonLoader.js.map +1 -1
  214. package/dist/components/loaders/RuiSkeletonLoader.vue_vue_type_script_setup_true_lang.js +8 -8
  215. package/dist/components/loaders/RuiSkeletonLoader.vue_vue_type_script_setup_true_lang.js.map +1 -1
  216. package/dist/components/logos/RuiLogo.js.map +1 -1
  217. package/dist/components/logos/RuiLogo.vue.d.ts +8 -10
  218. package/dist/components/logos/RuiLogo.vue_vue_type_script_setup_true_lang.js +42 -43
  219. package/dist/components/logos/RuiLogo.vue_vue_type_script_setup_true_lang.js.map +1 -1
  220. package/dist/components/logos/verified-logo.d.ts +17 -0
  221. package/dist/components/logos/verified-logo.js +36 -0
  222. package/dist/components/logos/verified-logo.js.map +1 -0
  223. package/dist/components/overlays/badge/RuiBadge.js.map +1 -1
  224. package/dist/components/overlays/badge/RuiBadge.vue_vue_type_script_setup_true_lang.js +75 -47
  225. package/dist/components/overlays/badge/RuiBadge.vue_vue_type_script_setup_true_lang.js.map +1 -1
  226. package/dist/components/overlays/dialog/RuiDialog.js.map +1 -1
  227. package/dist/components/overlays/dialog/RuiDialog.vue.d.ts +3 -2
  228. package/dist/components/overlays/dialog/RuiDialog.vue_vue_type_script_setup_true_lang.js +16 -12
  229. package/dist/components/overlays/dialog/RuiDialog.vue_vue_type_script_setup_true_lang.js.map +1 -1
  230. package/dist/components/overlays/menu/RuiMenu.js.map +1 -1
  231. package/dist/components/overlays/menu/RuiMenu.vue.d.ts +15 -10
  232. package/dist/components/overlays/menu/RuiMenu.vue_vue_type_script_setup_true_lang.js +29 -22
  233. package/dist/components/overlays/menu/RuiMenu.vue_vue_type_script_setup_true_lang.js.map +1 -1
  234. package/dist/components/overlays/menu/activator-handlers.d.ts +11 -0
  235. package/dist/components/overlays/menu/activator-handlers.js +18 -0
  236. package/dist/components/overlays/menu/activator-handlers.js.map +1 -0
  237. package/dist/components/overlays/navigation-drawer/RuiNavigationDrawer.js.map +1 -1
  238. package/dist/components/overlays/navigation-drawer/RuiNavigationDrawer.vue.d.ts +6 -2
  239. package/dist/components/overlays/navigation-drawer/RuiNavigationDrawer.vue_vue_type_script_setup_true_lang.js +40 -16
  240. package/dist/components/overlays/navigation-drawer/RuiNavigationDrawer.vue_vue_type_script_setup_true_lang.js.map +1 -1
  241. package/dist/components/overlays/notification/RuiNotification.js.map +1 -1
  242. package/dist/components/overlays/notification/RuiNotification.vue_vue_type_script_setup_true_lang.js +4 -4
  243. package/dist/components/overlays/notification/RuiNotification.vue_vue_type_script_setup_true_lang.js.map +1 -1
  244. package/dist/components/overlays/tooltip/RuiTooltip.js.map +1 -1
  245. package/dist/components/overlays/tooltip/RuiTooltip.vue.d.ts +0 -5
  246. package/dist/components/overlays/tooltip/RuiTooltip.vue_vue_type_script_setup_true_lang.js +16 -10
  247. package/dist/components/overlays/tooltip/RuiTooltip.vue_vue_type_script_setup_true_lang.js.map +1 -1
  248. package/dist/components/overlays/tooltip/tooltip-styles.d.ts +5 -12
  249. package/dist/components/overlays/tooltip/tooltip-styles.js +11 -18
  250. package/dist/components/overlays/tooltip/tooltip-styles.js.map +1 -1
  251. package/dist/components/progress/RuiProgress.js.map +1 -1
  252. package/dist/components/progress/RuiProgress.vue.d.ts +4 -0
  253. package/dist/components/progress/RuiProgress.vue_vue_type_script_setup_true_lang.js +72 -46
  254. package/dist/components/progress/RuiProgress.vue_vue_type_script_setup_true_lang.js.map +1 -1
  255. package/dist/components/steppers/RuiFooterStepper.js.map +1 -1
  256. package/dist/components/steppers/RuiFooterStepper.vue_vue_type_script_setup_true_lang.js +27 -28
  257. package/dist/components/steppers/RuiFooterStepper.vue_vue_type_script_setup_true_lang.js.map +1 -1
  258. package/dist/components/steppers/RuiStepper.js.map +1 -1
  259. package/dist/components/steppers/RuiStepper.vue.d.ts +0 -4
  260. package/dist/components/steppers/RuiStepper.vue_vue_type_script_setup_true_lang.js +25 -23
  261. package/dist/components/steppers/RuiStepper.vue_vue_type_script_setup_true_lang.js.map +1 -1
  262. package/dist/components/steppers/RuiStepperIcon.js.map +1 -1
  263. package/dist/components/steppers/RuiStepperIcon.vue.d.ts +2 -0
  264. package/dist/components/steppers/RuiStepperIcon.vue_vue_type_script_setup_true_lang.js +47 -47
  265. package/dist/components/steppers/RuiStepperIcon.vue_vue_type_script_setup_true_lang.js.map +1 -1
  266. package/dist/components/tables/RuiDataTable.js.map +1 -1
  267. package/dist/components/tables/RuiDataTable.vue.d.ts +3 -6
  268. package/dist/components/tables/RuiDataTable.vue_vue_type_script_setup_true_lang.js +65 -47
  269. package/dist/components/tables/RuiDataTable.vue_vue_type_script_setup_true_lang.js.map +1 -1
  270. package/dist/components/tables/RuiExpandButton.js.map +1 -1
  271. package/dist/components/tables/RuiExpandButton.vue_vue_type_script_setup_true_lang.js +1 -0
  272. package/dist/components/tables/RuiExpandButton.vue_vue_type_script_setup_true_lang.js.map +1 -1
  273. package/dist/components/tables/RuiTable.js.map +1 -1
  274. package/dist/components/tables/RuiTable.vue_vue_type_script_setup_true_lang.js +8 -5
  275. package/dist/components/tables/RuiTable.vue_vue_type_script_setup_true_lang.js.map +1 -1
  276. package/dist/components/tables/RuiTableEmptyState.js.map +1 -1
  277. package/dist/components/tables/RuiTableEmptyState.vue_vue_type_script_setup_true_lang.js +1 -1
  278. package/dist/components/tables/RuiTableEmptyState.vue_vue_type_script_setup_true_lang.js.map +1 -1
  279. package/dist/components/tables/RuiTableHead.js.map +1 -1
  280. package/dist/components/tables/RuiTableHead.vue_vue_type_script_setup_true_lang.js +88 -66
  281. package/dist/components/tables/RuiTableHead.vue_vue_type_script_setup_true_lang.js.map +1 -1
  282. package/dist/components/tables/RuiTablePagination.js.map +1 -1
  283. package/dist/components/tables/RuiTablePagination.vue_vue_type_script_setup_true_lang.js +8 -11
  284. package/dist/components/tables/RuiTablePagination.vue_vue_type_script_setup_true_lang.js.map +1 -1
  285. package/dist/components/tables/data-table/RuiDataTableExpandedRow.js.map +1 -1
  286. package/dist/components/tables/data-table/RuiDataTableExpandedRow.vue_vue_type_script_setup_true_lang.js +3 -3
  287. package/dist/components/tables/data-table/RuiDataTableExpandedRow.vue_vue_type_script_setup_true_lang.js.map +1 -1
  288. package/dist/components/tables/data-table/RuiDataTableGroupRow.js.map +1 -1
  289. package/dist/components/tables/data-table/RuiDataTableGroupRow.vue_vue_type_script_setup_true_lang.js +7 -3
  290. package/dist/components/tables/data-table/RuiDataTableGroupRow.vue_vue_type_script_setup_true_lang.js.map +1 -1
  291. package/dist/components/tables/data-table/RuiDataTableMobileSort.js.map +1 -1
  292. package/dist/components/tables/data-table/RuiDataTableMobileSort.vue_vue_type_script_setup_true_lang.js +1 -1
  293. package/dist/components/tables/data-table/RuiDataTableMobileSort.vue_vue_type_script_setup_true_lang.js.map +1 -1
  294. package/dist/components/tables/data-table/RuiDataTableRow.js.map +1 -1
  295. package/dist/components/tables/data-table/RuiDataTableRow.vue_vue_type_script_setup_true_lang.js +58 -19
  296. package/dist/components/tables/data-table/RuiDataTableRow.vue_vue_type_script_setup_true_lang.js.map +1 -1
  297. package/dist/components/tables/data-table-styles.d.ts +24 -0
  298. package/dist/components/tables/data-table-styles.js +35 -20
  299. package/dist/components/tables/data-table-styles.js.map +1 -1
  300. package/dist/components/tables/table_no_data_placeholder.js +1 -1
  301. package/dist/components/tables/table_no_data_placeholder.js.map +1 -1
  302. package/dist/components/tables/table_no_data_placeholder_dark.js +1 -1
  303. package/dist/components/tables/table_no_data_placeholder_dark.js.map +1 -1
  304. package/dist/components/tabs/tab/RuiTab.js.map +1 -1
  305. package/dist/components/tabs/tab/RuiTab.vue.d.ts +2 -5
  306. package/dist/components/tabs/tab/RuiTab.vue_vue_type_script_setup_true_lang.js +94 -68
  307. package/dist/components/tabs/tab/RuiTab.vue_vue_type_script_setup_true_lang.js.map +1 -1
  308. package/dist/components/tabs/tab-item/RuiTabItem.js.map +1 -1
  309. package/dist/components/tabs/tab-item/RuiTabItem.vue.d.ts +0 -1
  310. package/dist/components/tabs/tab-item/RuiTabItem.vue_vue_type_script_setup_true_lang.js +5 -11
  311. package/dist/components/tabs/tab-item/RuiTabItem.vue_vue_type_script_setup_true_lang.js.map +1 -1
  312. package/dist/components/tabs/tab-items/RuiTabItems.js.map +1 -1
  313. package/dist/components/tabs/tab-items/RuiTabItems.vue_vue_type_script_setup_true_lang.js +3 -8
  314. package/dist/components/tabs/tab-items/RuiTabItems.vue_vue_type_script_setup_true_lang.js.map +1 -1
  315. package/dist/components/tabs/tab-props.d.ts +7 -1
  316. package/dist/components/tabs/tab-props.js +7 -1
  317. package/dist/components/tabs/tab-props.js.map +1 -1
  318. package/dist/components/tabs/tabs/RuiTabs.js.map +1 -1
  319. package/dist/components/tabs/tabs/RuiTabs.vue.d.ts +2 -1
  320. package/dist/components/tabs/tabs/RuiTabs.vue_vue_type_script_setup_true_lang.js +178 -32
  321. package/dist/components/tabs/tabs/RuiTabs.vue_vue_type_script_setup_true_lang.js.map +1 -1
  322. package/dist/components/tabs/tabs/use-tab-indicator.d.ts +27 -0
  323. package/dist/components/tabs/tabs/use-tab-indicator.js +67 -0
  324. package/dist/components/tabs/tabs/use-tab-indicator.js.map +1 -0
  325. package/dist/components/tabs/tabs/use-tab-keyboard.d.ts +17 -0
  326. package/dist/components/tabs/tabs/use-tab-keyboard.js +57 -0
  327. package/dist/components/tabs/tabs/use-tab-keyboard.js.map +1 -0
  328. package/dist/components/tabs/tabs/use-tab-routing.js +1 -2
  329. package/dist/components/tabs/tabs/use-tab-routing.js.map +1 -1
  330. package/dist/components/time-picker/RuiTimePicker.js.map +1 -1
  331. package/dist/components/time-picker/RuiTimePicker.vue_vue_type_script_setup_true_lang.js +35 -32
  332. package/dist/components/time-picker/RuiTimePicker.vue_vue_type_script_setup_true_lang.js.map +1 -1
  333. package/dist/components/time-picker/time-picker-styles.d.ts +18 -0
  334. package/dist/components/time-picker/time-picker-styles.js +16 -10
  335. package/dist/components/time-picker/time-picker-styles.js.map +1 -1
  336. package/dist/composables/defaults/field.d.ts +22 -0
  337. package/dist/composables/defaults/field.js +29 -0
  338. package/dist/composables/defaults/field.js.map +1 -0
  339. package/dist/composables/defaults/logo.d.ts +18 -0
  340. package/dist/composables/defaults/logo.js +13 -0
  341. package/dist/composables/defaults/logo.js.map +1 -0
  342. package/dist/composables/dropdown-menu.d.ts +14 -2
  343. package/dist/composables/dropdown-menu.js +12 -2
  344. package/dist/composables/dropdown-menu.js.map +1 -1
  345. package/dist/composables/floating.d.ts +0 -2
  346. package/dist/composables/floating.js +5 -2
  347. package/dist/composables/floating.js.map +1 -1
  348. package/dist/composables/forms/auto-complete/chips.d.ts +22 -0
  349. package/dist/composables/forms/auto-complete/chips.js +42 -0
  350. package/dist/composables/forms/auto-complete/chips.js.map +1 -0
  351. package/dist/composables/forms/auto-complete/combobox.d.ts +25 -0
  352. package/dist/composables/forms/auto-complete/combobox.js +35 -0
  353. package/dist/composables/forms/auto-complete/combobox.js.map +1 -0
  354. package/dist/composables/forms/auto-complete/focus.d.ts +5 -2
  355. package/dist/composables/forms/auto-complete/focus.js +36 -10
  356. package/dist/composables/forms/auto-complete/focus.js.map +1 -1
  357. package/dist/composables/forms/auto-complete/index.d.ts +3 -0
  358. package/dist/composables/forms/auto-complete/keyboard-navigation.d.ts +8 -1
  359. package/dist/composables/forms/auto-complete/keyboard-navigation.js +48 -20
  360. package/dist/composables/forms/auto-complete/keyboard-navigation.js.map +1 -1
  361. package/dist/composables/forms/auto-complete/selection.d.ts +37 -0
  362. package/dist/composables/forms/auto-complete/selection.js +60 -0
  363. package/dist/composables/forms/auto-complete/selection.js.map +1 -0
  364. package/dist/composables/forms/auto-complete/value.js +19 -0
  365. package/dist/composables/forms/auto-complete/value.js.map +1 -1
  366. package/dist/composables/keyboard-scroll.d.ts +17 -0
  367. package/dist/composables/keyboard-scroll.js +58 -0
  368. package/dist/composables/keyboard-scroll.js.map +1 -0
  369. package/dist/composables/sticky-header.d.ts +8 -0
  370. package/dist/composables/sticky-header.js +13 -2
  371. package/dist/composables/sticky-header.js.map +1 -1
  372. package/dist/composables/tables/data-table/page-scroll.d.ts +30 -0
  373. package/dist/composables/tables/data-table/page-scroll.js +113 -0
  374. package/dist/composables/tables/data-table/page-scroll.js.map +1 -0
  375. package/dist/consts/colors.d.ts +4 -0
  376. package/dist/consts/colors.js +1 -37
  377. package/dist/consts/colors.js.map +1 -1
  378. package/dist/consts/tokens.d.ts +56 -0
  379. package/dist/consts/tokens.js +46 -0
  380. package/dist/consts/tokens.js.map +1 -0
  381. package/dist/consts/typography.d.ts +51 -18
  382. package/dist/index.d.ts +13 -0
  383. package/dist/index.js +12 -7
  384. package/dist/index.js.map +1 -1
  385. package/dist/library-icons.json +0 -10
  386. package/dist/style.css +5644 -4677
  387. package/dist/styles/colors.css +315 -0
  388. package/dist/styles/tokens.css +50 -0
  389. package/dist/tailwind.css +145 -0
  390. package/dist/theme/theme.css +403 -0
  391. package/dist/theme.css +403 -0
  392. package/dist/utils/helpers.d.ts +0 -8
  393. package/dist/utils/helpers.js +1 -17
  394. package/dist/utils/helpers.js.map +1 -1
  395. package/dist/utils/tv.js +13 -21
  396. package/dist/utils/tv.js.map +1 -1
  397. package/dist/web-types.json +271 -413
  398. package/package.json +17 -16
  399. package/dist/components/icons/LazyIcon.vue.d.ts +0 -8
  400. package/dist/components/logos/use-logo-sources.d.ts +0 -29
  401. package/dist/components/logos/use-logo-sources.js +0 -90
  402. package/dist/components/logos/use-logo-sources.js.map +0 -1
  403. package/dist/components/steppers/RuiStepperCustomIcon.js +0 -7
  404. package/dist/components/steppers/RuiStepperCustomIcon.js.map +0 -1
  405. package/dist/components/steppers/RuiStepperCustomIcon.vue.d.ts +0 -8
  406. package/dist/components/steppers/RuiStepperCustomIcon.vue_vue_type_script_setup_true_lang.js +0 -43
  407. package/dist/components/steppers/RuiStepperCustomIcon.vue_vue_type_script_setup_true_lang.js.map +0 -1
  408. package/dist/composables/colors/common.d.ts +0 -20
  409. package/dist/composables/colors/index.d.ts +0 -3
  410. package/dist/composables/colors/text-input.d.ts +0 -27
  411. package/dist/composables/forms/auto-complete/index.js +0 -5
  412. package/dist/composables/forms/use-label-with-quote.d.ts +0 -2
  413. package/dist/composables/popper.d.ts +0 -16
  414. package/dist/composables/popper.js +0 -23
  415. package/dist/composables/popper.js.map +0 -1
  416. package/dist/consts/forms/auto-complete/index.d.ts +0 -4
  417. package/dist/theme/index.d.ts +0 -5
  418. package/dist/theme/index.js +0 -162
  419. package/dist/theme/index.js.map +0 -1
  420. package/dist/utils/forms/auto-complete/index.d.ts +0 -2
@@ -1 +1 @@
1
- {"version":3,"file":"RuiCalendar.vue_vue_type_script_setup_true_lang.js","names":[],"sources":["../../../src/components/calendar/RuiCalendar.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport { get, isDefined, set } from '@vueuse/core';\nimport { computed, provide, ref, watch } from 'vue';\nimport {\n CalendarStateSymbol,\n type MonthYearSelection,\n type RuiCalendarState,\n} from '@/components/calendar/state';\nimport { useRotkiTheme } from '@/composables/theme';\nimport { tv } from '@/utils/tv';\nimport RuiCalendarGrid from './RuiCalendarGrid.vue';\nimport RuiCalendarHeader from './RuiCalendarHeader.vue';\n\nexport interface CalendarProps {\n maxDate?: Date | number;\n minDate?: Date | number;\n allowEmpty?: boolean;\n borderless?: boolean;\n}\n\ndefineOptions({\n name: 'RuiCalendar',\n inheritAttrs: false,\n});\n\nconst model = defineModel<Date | undefined>({ required: false });\nconst isMenuOpen = defineModel<boolean>('menu-open', { required: false, default: false });\n\nconst { maxDate, minDate, allowEmpty = false, borderless = false } = defineProps<CalendarProps>();\n\nconst emit = defineEmits<{\n 'update:pages': [{ title: string }[]];\n}>();\n\nconst currentDate = ref<Date>(isDefined(model) ? new Date(get(model)) : new Date());\nconst selectedDate = ref<Date | undefined>(isDefined(model) ? new Date(get(model)) : undefined);\nconst viewMonth = ref<number>(get(currentDate).getMonth());\nconst viewYear = ref<number>(get(currentDate).getFullYear());\n\nconst { isDark } = useRotkiTheme();\n\nconst calendarStyles = tv({\n base: 'w-[18.75rem] bg-white dark:bg-rui-grey-900 overflow-hidden',\n variants: {\n bordered: {\n true: 'rounded-md shadow-sm border border-rui-grey-200 dark:border-rui-grey-800',\n },\n },\n});\n\nconst ui = computed<string>(() => calendarStyles({ bordered: !borderless }));\n\nconst monthTitle = computed<string>(() => {\n const date = new Date(get(viewYear), get(viewMonth));\n return date.toLocaleString('default', { month: 'long', year: 'numeric' });\n});\n\nprovide(CalendarStateSymbol.valueOf(), {\n viewMonth,\n viewYear,\n selectedDate,\n maxDate: computed(() => (maxDate ? new Date(maxDate) : undefined)),\n minDate: computed(() => (minDate ? new Date(minDate) : undefined)),\n isDark,\n allowEmpty,\n} satisfies RuiCalendarState);\n\n// The grid's keyboard navigation also turns the view, so the title follows the view itself\nwatch(monthTitle, (title) => {\n emit('update:pages', [{ title }]);\n});\n\nfunction moveMonth(delta: number): void {\n let newMonth = get(viewMonth) + delta;\n let newYear = get(viewYear);\n\n if (newMonth > 11) {\n newMonth = 0;\n newYear++;\n }\n else if (newMonth < 0) {\n newMonth = 11;\n newYear--;\n }\n\n set(viewMonth, newMonth);\n set(viewYear, newYear);\n}\n\nfunction move(date: Date | number): void {\n const newDate = new Date(date);\n set(viewMonth, newDate.getMonth());\n set(viewYear, newDate.getFullYear());\n}\n\nfunction selectMonth(selection: MonthYearSelection): void {\n set(viewMonth, selection.month);\n set(viewYear, selection.year);\n\n // If there's a selected date, update it with the new year/month\n if (isDefined(selectedDate)) {\n const current = get(selectedDate);\n const currentDay = current.getDate();\n // Handle day overflow (e.g., Jan 31 -> Feb 28) by checking BEFORE setting month\n const daysInNewMonth = new Date(selection.year, selection.month + 1, 0).getDate();\n const adjustedDay = Math.min(currentDay, daysInNewMonth);\n\n const newDate = new Date(current);\n newDate.setFullYear(selection.year);\n newDate.setDate(1); // Set to 1st to avoid overflow when changing month\n newDate.setMonth(selection.month);\n newDate.setDate(adjustedDay);\n set(selectedDate, newDate);\n }\n}\n\nwatch(selectedDate, (date) => {\n if (!date && !allowEmpty)\n return;\n\n if (date) {\n set(model, new Date(date));\n\n if (get(viewMonth) !== date.getMonth()) {\n set(viewMonth, date.getMonth());\n }\n\n if (get(viewYear) !== date.getFullYear()) {\n set(viewYear, date.getFullYear());\n }\n }\n else {\n set(model, undefined);\n }\n});\n\nwatch(model, (newValue) => {\n if (newValue === undefined) {\n set(selectedDate, undefined);\n return;\n }\n\n const date = new Date(newValue);\n\n if (isDefined(selectedDate) && get(selectedDate).getTime() !== date.getTime()) {\n set(selectedDate, new Date(newValue));\n set(viewMonth, date.getMonth());\n set(viewYear, date.getFullYear());\n }\n});\n\ndefineExpose({\n move,\n});\n</script>\n\n<template>\n <div :class=\"ui\">\n <RuiCalendarHeader\n v-model:menu-open=\"isMenuOpen\"\n :title=\"monthTitle\"\n :view-month=\"viewMonth\"\n :view-year=\"viewYear\"\n @prev-month=\"moveMonth(-1)\"\n @next-month=\"moveMonth(1)\"\n @select-month=\"selectMonth($event)\"\n />\n\n <RuiCalendarGrid\n v-model=\"selectedDate\"\n :view-month=\"viewMonth\"\n :view-year=\"viewYear\"\n />\n </div>\n</template>\n"],"mappings":"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"}
1
+ {"version":3,"file":"RuiCalendar.vue_vue_type_script_setup_true_lang.js","names":[],"sources":["../../../src/components/calendar/RuiCalendar.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport { get, isDefined, set } from '@vueuse/core';\nimport { computed, provide, ref, watch } from 'vue';\nimport {\n CalendarStateSymbol,\n type MonthYearSelection,\n type RuiCalendarState,\n} from '@/components/calendar/state';\nimport { useRotkiTheme } from '@/composables/theme';\nimport { tv } from '@/utils/tv';\nimport RuiCalendarGrid from './RuiCalendarGrid.vue';\nimport RuiCalendarHeader from './RuiCalendarHeader.vue';\n\nexport interface CalendarProps {\n maxDate?: Date | number;\n minDate?: Date | number;\n allowEmpty?: boolean;\n borderless?: boolean;\n}\n\ndefineOptions({\n name: 'RuiCalendar',\n inheritAttrs: false,\n});\n\nconst model = defineModel<Date | undefined>({ required: false });\nconst isMenuOpen = defineModel<boolean>('menu-open', { required: false, default: false });\n\nconst { maxDate, minDate, allowEmpty = false, borderless = false } = defineProps<CalendarProps>();\n\nconst emit = defineEmits<{\n 'update:pages': [{ title: string }[]];\n}>();\n\nconst currentDate = ref<Date>(isDefined(model) ? new Date(get(model)) : new Date());\nconst selectedDate = ref<Date | undefined>(isDefined(model) ? new Date(get(model)) : undefined);\nconst viewMonth = ref<number>(get(currentDate).getMonth());\nconst viewYear = ref<number>(get(currentDate).getFullYear());\n\nconst { isDark } = useRotkiTheme();\n\nconst calendarStyles = tv({\n base: 'w-75 overflow-hidden',\n variants: {\n // standalone it sits on the card surface; borderless it lives inside a menu\n bordered: {\n true: 'bg-rui-surface rounded-rui-panel border border-rui-divider',\n false: 'bg-rui-menu',\n },\n },\n});\n\nconst ui = computed<string>(() => calendarStyles({ bordered: !borderless }));\n\nconst monthTitle = computed<string>(() => {\n const date = new Date(get(viewYear), get(viewMonth));\n return date.toLocaleString('default', { month: 'long', year: 'numeric' });\n});\n\nprovide(CalendarStateSymbol.valueOf(), {\n viewMonth,\n viewYear,\n selectedDate,\n maxDate: computed(() => (maxDate ? new Date(maxDate) : undefined)),\n minDate: computed(() => (minDate ? new Date(minDate) : undefined)),\n isDark,\n allowEmpty,\n} satisfies RuiCalendarState);\n\n// The grid's keyboard navigation also turns the view, so the title follows the view itself\nwatch(monthTitle, (title) => {\n emit('update:pages', [{ title }]);\n});\n\nfunction moveMonth(delta: number): void {\n let newMonth = get(viewMonth) + delta;\n let newYear = get(viewYear);\n\n if (newMonth > 11) {\n newMonth = 0;\n newYear++;\n }\n else if (newMonth < 0) {\n newMonth = 11;\n newYear--;\n }\n\n set(viewMonth, newMonth);\n set(viewYear, newYear);\n}\n\nfunction move(date: Date | number): void {\n const newDate = new Date(date);\n set(viewMonth, newDate.getMonth());\n set(viewYear, newDate.getFullYear());\n}\n\nfunction selectMonth(selection: MonthYearSelection): void {\n set(viewMonth, selection.month);\n set(viewYear, selection.year);\n\n // If there's a selected date, update it with the new year/month\n if (isDefined(selectedDate)) {\n const current = get(selectedDate);\n const currentDay = current.getDate();\n // Handle day overflow (e.g., Jan 31 -> Feb 28) by checking BEFORE setting month\n const daysInNewMonth = new Date(selection.year, selection.month + 1, 0).getDate();\n const adjustedDay = Math.min(currentDay, daysInNewMonth);\n\n const newDate = new Date(current);\n newDate.setFullYear(selection.year);\n newDate.setDate(1); // Set to 1st to avoid overflow when changing month\n newDate.setMonth(selection.month);\n newDate.setDate(adjustedDay);\n set(selectedDate, newDate);\n }\n}\n\nwatch(selectedDate, (date) => {\n if (!date && !allowEmpty)\n return;\n\n if (date) {\n set(model, new Date(date));\n\n if (get(viewMonth) !== date.getMonth()) {\n set(viewMonth, date.getMonth());\n }\n\n if (get(viewYear) !== date.getFullYear()) {\n set(viewYear, date.getFullYear());\n }\n }\n else {\n set(model, undefined);\n }\n});\n\nwatch(model, (newValue) => {\n if (newValue === undefined) {\n set(selectedDate, undefined);\n return;\n }\n\n const date = new Date(newValue);\n\n if (isDefined(selectedDate) && get(selectedDate).getTime() !== date.getTime()) {\n set(selectedDate, new Date(newValue));\n set(viewMonth, date.getMonth());\n set(viewYear, date.getFullYear());\n }\n});\n\ndefineExpose({\n move,\n});\n</script>\n\n<template>\n <div :class=\"ui\">\n <RuiCalendarHeader\n v-model:menu-open=\"isMenuOpen\"\n :title=\"monthTitle\"\n :view-month=\"viewMonth\"\n :view-year=\"viewYear\"\n @prev-month=\"moveMonth(-1)\"\n @next-month=\"moveMonth(1)\"\n @select-month=\"selectMonth($event)\"\n />\n\n <RuiCalendarGrid\n v-model=\"selectedDate\"\n :view-month=\"viewMonth\"\n :view-year=\"viewYear\"\n />\n </div>\n</template>\n"],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"RuiCalendarGrid.js","names":[],"sources":["../../../src/components/calendar/RuiCalendarGrid.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport { get, isDefined, set } from '@vueuse/core';\nimport { computed, inject, nextTick, ref, useTemplateRef, watch } from 'vue';\nimport {\n CalendarStateSymbol,\n getDaysOfWeek,\n type RuiCalendarState,\n} from '@/components/calendar/state';\nimport { tv } from '@/utils/tv';\n\ndefineOptions({\n name: 'RuiCalendarGrid',\n inheritAttrs: false,\n});\n\nconst model = defineModel<Date | undefined>();\n\nconst { viewMonth, viewYear } = defineProps<{\n viewMonth: number;\n viewYear: number;\n}>();\n\nconst calendarState = inject<RuiCalendarState>(CalendarStateSymbol) as RuiCalendarState;\n\n/**\n * The `YYYY-MM-DD` key a day is tracked and focused by.\n *\n * @param date - the day to key\n * @returns its key\n */\nfunction createDateKey(date: Date): string {\n return `${date.getFullYear()}-${(date.getMonth() + 1).toString().padStart(2, '0')}-${date.getDate().toString().padStart(2, '0')}`;\n}\n\n// Pre-calculated constants\nconst daysOfWeek = getDaysOfWeek();\nconst today = new Date();\nconst todayKey = createDateKey(today);\n\nconst dayButton = tv({\n base: 'h-9 w-full flex items-center justify-center text-sm rounded-full mx-auto max-w-[2.25rem] transition-colors duration-150 ease-in-out border-none outline-none cursor-pointer focus:ring-2 focus:ring-rui-primary focus:ring-opacity-50',\n variants: {\n selected: {\n true: 'bg-rui-primary text-white hover:bg-rui-primary/90 dark:hover:bg-rui-primary/90',\n },\n currentMonth: {\n true: 'text-gray-700 hover:bg-gray-100 dark:text-gray-300 dark:hover:bg-gray-700',\n false: 'text-gray-400 dark:text-gray-600',\n },\n inRange: {\n false: 'opacity-50 cursor-not-allowed hover:bg-transparent',\n },\n today: {\n true: `relative after:content-[''] after:absolute after:size-1 after:rounded-full after:bottom-1 after:left-1/2 after:-translate-x-1/2 after:bg-rui-primary`,\n },\n },\n compoundVariants: [\n {\n selected: true,\n class: 'text-white dark:text-white',\n },\n ],\n});\n\n// Pre-calculated arrays for performance - using refs for better control\nconst calendarDays = ref<\n Array<{\n date: Date;\n isCurrentMonth: boolean;\n isInRange: boolean;\n isSelected: boolean;\n isToday: boolean;\n key: string;\n dayNumber: number;\n }>\n>([]);\n\nfunction createDayData(\n date: Date,\n isCurrentMonth: boolean,\n modelValue: Date | null | undefined,\n maxDateValue: Date | null,\n minDateValue: Date | null,\n): {\n date: Date;\n isCurrentMonth: boolean;\n isInRange: boolean;\n isSelected: boolean;\n isToday: boolean;\n key: string;\n dayNumber: number;\n} {\n const key = createDateKey(date);\n return {\n date,\n isCurrentMonth,\n isInRange: isDateInRangeCheck(date, maxDateValue, minDateValue),\n isSelected: modelValue ? isDateSelectedCheck(date, modelValue) : false,\n isToday: key === todayKey,\n key,\n dayNumber: date.getDate(),\n };\n}\n\n/** Rebuilds the days the grid draws for the current view month. */\nfunction calculateCalendarDays(): void {\n const firstDayOfMonth = new Date(viewYear, viewMonth, 1);\n const lastDayOfMonth = new Date(viewYear, viewMonth + 1, 0);\n const daysInMonth = lastDayOfMonth.getDate();\n const startingDayOfWeek = firstDayOfMonth.getDay();\n\n const { maxDate, minDate } = calendarState;\n const modelValue = get(model);\n const maxDateValue = isDefined(maxDate) ? get(maxDate) : null;\n const minDateValue = isDefined(minDate) ? get(minDate) : null;\n\n const result = [];\n\n // Previous month days\n if (startingDayOfWeek > 0) {\n const prevMonthLastDay = new Date(viewYear, viewMonth, 0).getDate();\n for (let i = startingDayOfWeek - 1; i >= 0; i--) {\n const date = new Date(viewYear, viewMonth - 1, prevMonthLastDay - i, 12, 0, 0, 0);\n result.push(createDayData(date, false, modelValue, maxDateValue, minDateValue));\n }\n }\n\n // Current month days\n for (let i = 1; i <= daysInMonth; i++) {\n const date = new Date(viewYear, viewMonth, i, 12, 0, 0, 0);\n result.push(createDayData(date, true, modelValue, maxDateValue, minDateValue));\n }\n\n // Next month days\n const totalDaysSoFar = result.length;\n const daysToAdd = 42 - totalDaysSoFar;\n for (let i = 1; i <= daysToAdd; i++) {\n const date = new Date(viewYear, viewMonth + 1, i, 12, 0, 0, 0);\n result.push(createDayData(date, false, modelValue, maxDateValue, minDateValue));\n }\n\n set(calendarDays, result);\n}\n\nfunction isDateInRangeCheck(\n date: Date,\n maxDateValue: Date | null,\n minDateValue: Date | null,\n): boolean {\n if (maxDateValue && date > maxDateValue)\n return false;\n if (minDateValue && date < minDateValue)\n return false;\n return true;\n}\n\nfunction isDateSelectedCheck(date: Date, modelValue: Date): boolean {\n return (\n date.getFullYear() === modelValue.getFullYear() &&\n date.getMonth() === modelValue.getMonth() &&\n date.getDate() === modelValue.getDate()\n );\n}\n\nfunction selectDate(dayData: { date: Date; isInRange: boolean; isSelected: boolean }): void {\n if (!dayData.isInRange)\n return;\n\n let updateModel: Date | undefined;\n\n if (dayData.isSelected && calendarState.allowEmpty) {\n updateModel = undefined;\n }\n else if (isDefined(model)) {\n const modelValue = get(model);\n const newDate = new Date(dayData.date);\n newDate.setHours(modelValue.getHours());\n newDate.setMinutes(modelValue.getMinutes());\n newDate.setSeconds(modelValue.getSeconds());\n updateModel = newDate;\n }\n else {\n updateModel = new Date(dayData.date);\n }\n set(model, updateModel);\n}\n\n// Keyboard navigation: a roving tabindex, so crossing the calendar costs one Tab instead of 42\nconst gridRef = useTemplateRef<HTMLDivElement>('grid');\nconst activeKey = ref<string>('');\n\nconst dayLabelFormatter = new Intl.DateTimeFormat('en-US', { dateStyle: 'full' });\n\nconst KEY_DAY_OFFSETS: Record<string, number> = {\n ArrowDown: 7,\n ArrowLeft: -1,\n ArrowRight: 1,\n ArrowUp: -7,\n};\n\nconst weeks = computed<Array<typeof calendarDays.value>>(() => {\n const days = get(calendarDays);\n const result = [];\n for (let i = 0; i < days.length; i += 7)\n result.push(days.slice(i, i + 7));\n return result;\n});\n\nfunction preferredActiveKey(): string {\n const days = get(calendarDays);\n const selected = days.find(day => day.isSelected && day.isInRange);\n const todayInView = days.find(day => day.isToday && day.isCurrentMonth && day.isInRange);\n const firstSelectable = days.find(day => day.isCurrentMonth && day.isInRange);\n return (selected ?? todayInView ?? firstSelectable ?? days[0])?.key ?? '';\n}\n\nfunction syncActiveKey(): void {\n const days = get(calendarDays);\n if (!days.some(day => day.key === get(activeKey)))\n set(activeKey, preferredActiveKey());\n}\n\nfunction keyToDate(key: string): Date {\n const [year, month, day] = key.split('-').map(Number);\n return new Date(year ?? 0, (month ?? 1) - 1, day ?? 1, 12, 0, 0, 0);\n}\n\nfunction focusKey(key: string): void {\n set(activeKey, key);\n nextTick(() => {\n get(gridRef)?.querySelector<HTMLButtonElement>(`[data-id=\"${key}\"]`)?.focus();\n });\n}\n\nfunction moveTo(target: Date): void {\n const { maxDate, minDate } = calendarState;\n const maxDateValue = isDefined(maxDate) ? get(maxDate) : null;\n const minDateValue = isDefined(minDate) ? get(minDate) : null;\n\n // min/max bound a contiguous range, so a blocked step means the edge is here\n if (!isDateInRangeCheck(target, maxDateValue, minDateValue))\n return;\n\n const key = createDateKey(target);\n\n // Even a day drawn as a spill day turns the page, so header and focus agree on the month\n if (target.getMonth() === viewMonth && target.getFullYear() === viewYear) {\n focusKey(key);\n return;\n }\n\n set(calendarState.viewMonth, target.getMonth());\n set(calendarState.viewYear, target.getFullYear());\n nextTick(() => {\n focusKey(key);\n });\n}\n\nfunction onKeydown(event: KeyboardEvent): void {\n const active = get(activeKey);\n if (!active)\n return;\n\n const current = keyToDate(active);\n const dayOffset = KEY_DAY_OFFSETS[event.key];\n\n if (dayOffset !== undefined) {\n event.preventDefault();\n moveTo(new Date(current.getFullYear(), current.getMonth(), current.getDate() + dayOffset, 12, 0, 0, 0));\n }\n else if (event.key === 'Home' || event.key === 'End') {\n event.preventDefault();\n const offset = event.key === 'Home' ? -current.getDay() : 6 - current.getDay();\n moveTo(new Date(current.getFullYear(), current.getMonth(), current.getDate() + offset, 12, 0, 0, 0));\n }\n else if (event.key === 'PageUp' || event.key === 'PageDown') {\n event.preventDefault();\n const delta = event.key === 'PageUp' ? -1 : 1;\n moveTo(new Date(current.getFullYear(), current.getMonth() + delta, current.getDate(), 12, 0, 0, 0));\n }\n}\n\n// Initial calculation\ncalculateCalendarDays();\nsyncActiveKey();\n\n// Watchers for recalculation only when needed\nwatch([() => viewMonth, () => viewYear], () => {\n calculateCalendarDays();\n syncActiveKey();\n});\n\nwatch(model, () => {\n calculateCalendarDays();\n syncActiveKey();\n});\n\nwatch(\n [() => calendarState.maxDate, () => calendarState.minDate],\n () => {\n calculateCalendarDays();\n syncActiveKey();\n },\n);\n</script>\n\n<template>\n <div class=\"w-full p-2 pt-0\">\n <div\n ref=\"grid\"\n role=\"grid\"\n class=\"grid grid-cols-7 gap-0.5\"\n @keydown=\"onKeydown($event)\"\n >\n <div\n role=\"row\"\n class=\"contents\"\n >\n <span\n v-for=\"day in daysOfWeek\"\n :key=\"day\"\n role=\"columnheader\"\n class=\"py-2 pb-4 text-xs font-medium text-center text-gray-500 dark:text-gray-400\"\n >\n {{ day }}\n </span>\n </div>\n\n <div\n v-for=\"(week, index) in weeks\"\n :key=\"index\"\n role=\"row\"\n class=\"contents\"\n >\n <button\n v-for=\"dayData in week\"\n :key=\"dayData.key\"\n type=\"button\"\n role=\"gridcell\"\n :data-id=\"dayData.key\"\n :data-current-month=\"dayData.isCurrentMonth || undefined\"\n :data-selected=\"dayData.isSelected || undefined\"\n :data-today=\"(dayData.isToday && !dayData.isSelected) || undefined\"\n :class=\"dayButton({\n selected: dayData.isSelected,\n currentMonth: !dayData.isSelected && dayData.isCurrentMonth,\n inRange: dayData.isInRange,\n today: dayData.isToday && !dayData.isSelected,\n })\"\n :disabled=\"!dayData.isInRange\"\n :tabindex=\"dayData.key === activeKey ? 0 : -1\"\n :aria-label=\"dayLabelFormatter.format(dayData.date)\"\n :aria-selected=\"dayData.isSelected\"\n :aria-current=\"dayData.isToday ? 'date' : undefined\"\n @click.stop=\"selectDate(dayData)\"\n @focus=\"activeKey = dayData.key\"\n >\n {{ dayData.dayNumber }}\n </button>\n </div>\n </div>\n </div>\n</template>\n"],"mappings":""}
1
+ {"version":3,"file":"RuiCalendarGrid.js","names":[],"sources":["../../../src/components/calendar/RuiCalendarGrid.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport { get, isDefined, set } from '@vueuse/core';\nimport { computed, inject, nextTick, ref, useTemplateRef, watch } from 'vue';\nimport {\n CalendarStateSymbol,\n getDaysOfWeek,\n type RuiCalendarState,\n} from '@/components/calendar/state';\nimport { tv } from '@/utils/tv';\n\ndefineOptions({\n name: 'RuiCalendarGrid',\n inheritAttrs: false,\n});\n\nconst model = defineModel<Date | undefined>();\n\nconst { viewMonth, viewYear } = defineProps<{\n viewMonth: number;\n viewYear: number;\n}>();\n\nconst calendarState = inject<RuiCalendarState>(CalendarStateSymbol) as RuiCalendarState;\n\n/**\n * The `YYYY-MM-DD` key a day is tracked and focused by.\n *\n * @param date - the day to key\n * @returns its key\n */\nfunction createDateKey(date: Date): string {\n return `${date.getFullYear()}-${(date.getMonth() + 1).toString().padStart(2, '0')}-${date.getDate().toString().padStart(2, '0')}`;\n}\n\n// Pre-calculated constants\nconst daysOfWeek = getDaysOfWeek();\nconst today = new Date();\nconst todayKey = createDateKey(today);\n\nconst dayButton = tv({\n base: 'h-9 w-full flex items-center justify-center text-sm rounded-rui-control mx-auto max-w-9 transition-colors duration-150 ease-in-out border-none outline-hidden cursor-pointer focus-visible:focus-ring',\n variants: {\n selected: {\n true: 'bg-rui-primary-fill text-rui-primary-foreground hover:bg-rui-primary-fill hover:state-layer-pressed',\n },\n // the neighbouring months' days are a step quieter but still pickable, so they keep 4.5:1\n currentMonth: {\n true: 'text-rui-neutral-800 dark:text-rui-neutral-100',\n false: 'text-rui-neutral-500 dark:text-rui-neutral-400',\n },\n inRange: {\n false: 'opacity-50 cursor-not-allowed hover:bg-transparent',\n },\n today: {\n true: 'inset-ring inset-ring-rui-outline font-semibold',\n },\n },\n compoundVariants: [\n // restated under `dark:`, which the current-month day color uses and would otherwise win\n {\n selected: true,\n class: 'text-rui-primary-foreground dark:text-rui-primary-foreground',\n },\n // only a pickable, unselected day takes the grey hover; on the selected one it replaced the fill\n { selected: false, inRange: true, class: 'hover:bg-rui-hover' },\n ],\n});\n\n// Pre-calculated arrays for performance - using refs for better control\nconst calendarDays = ref<\n Array<{\n date: Date;\n isCurrentMonth: boolean;\n isInRange: boolean;\n isSelected: boolean;\n isToday: boolean;\n key: string;\n dayNumber: number;\n }>\n>([]);\n\nfunction createDayData(\n date: Date,\n isCurrentMonth: boolean,\n modelValue: Date | null | undefined,\n maxDateValue: Date | null,\n minDateValue: Date | null,\n): {\n date: Date;\n isCurrentMonth: boolean;\n isInRange: boolean;\n isSelected: boolean;\n isToday: boolean;\n key: string;\n dayNumber: number;\n} {\n const key = createDateKey(date);\n return {\n date,\n isCurrentMonth,\n isInRange: isDateInRangeCheck(date, maxDateValue, minDateValue),\n isSelected: modelValue ? isDateSelectedCheck(date, modelValue) : false,\n isToday: key === todayKey,\n key,\n dayNumber: date.getDate(),\n };\n}\n\n/** Rebuilds the days the grid draws for the current view month. */\nfunction calculateCalendarDays(): void {\n const firstDayOfMonth = new Date(viewYear, viewMonth, 1);\n const lastDayOfMonth = new Date(viewYear, viewMonth + 1, 0);\n const daysInMonth = lastDayOfMonth.getDate();\n const startingDayOfWeek = firstDayOfMonth.getDay();\n\n const { maxDate, minDate } = calendarState;\n const modelValue = get(model);\n const maxDateValue = isDefined(maxDate) ? get(maxDate) : null;\n const minDateValue = isDefined(minDate) ? get(minDate) : null;\n\n const result = [];\n\n // Previous month days\n if (startingDayOfWeek > 0) {\n const prevMonthLastDay = new Date(viewYear, viewMonth, 0).getDate();\n for (let i = startingDayOfWeek - 1; i >= 0; i--) {\n const date = new Date(viewYear, viewMonth - 1, prevMonthLastDay - i, 12, 0, 0, 0);\n result.push(createDayData(date, false, modelValue, maxDateValue, minDateValue));\n }\n }\n\n // Current month days\n for (let i = 1; i <= daysInMonth; i++) {\n const date = new Date(viewYear, viewMonth, i, 12, 0, 0, 0);\n result.push(createDayData(date, true, modelValue, maxDateValue, minDateValue));\n }\n\n // Next month days\n const totalDaysSoFar = result.length;\n const daysToAdd = 42 - totalDaysSoFar;\n for (let i = 1; i <= daysToAdd; i++) {\n const date = new Date(viewYear, viewMonth + 1, i, 12, 0, 0, 0);\n result.push(createDayData(date, false, modelValue, maxDateValue, minDateValue));\n }\n\n set(calendarDays, result);\n}\n\nfunction isDateInRangeCheck(\n date: Date,\n maxDateValue: Date | null,\n minDateValue: Date | null,\n): boolean {\n if (maxDateValue && date > maxDateValue)\n return false;\n if (minDateValue && date < minDateValue)\n return false;\n return true;\n}\n\nfunction isDateSelectedCheck(date: Date, modelValue: Date): boolean {\n return (\n date.getFullYear() === modelValue.getFullYear() &&\n date.getMonth() === modelValue.getMonth() &&\n date.getDate() === modelValue.getDate()\n );\n}\n\nfunction selectDate(dayData: { date: Date; isInRange: boolean; isSelected: boolean }): void {\n if (!dayData.isInRange)\n return;\n\n let updateModel: Date | undefined;\n\n if (dayData.isSelected && calendarState.allowEmpty) {\n updateModel = undefined;\n }\n else if (isDefined(model)) {\n const modelValue = get(model);\n const newDate = new Date(dayData.date);\n newDate.setHours(modelValue.getHours());\n newDate.setMinutes(modelValue.getMinutes());\n newDate.setSeconds(modelValue.getSeconds());\n updateModel = newDate;\n }\n else {\n updateModel = new Date(dayData.date);\n }\n set(model, updateModel);\n}\n\n// Keyboard navigation: a roving tabindex, so crossing the calendar costs one Tab instead of 42\nconst gridRef = useTemplateRef<HTMLDivElement>('grid');\nconst activeKey = ref<string>('');\n\nconst dayLabelFormatter = new Intl.DateTimeFormat('en-US', { dateStyle: 'full' });\n\nconst KEY_DAY_OFFSETS: Record<string, number> = {\n ArrowDown: 7,\n ArrowLeft: -1,\n ArrowRight: 1,\n ArrowUp: -7,\n};\n\nconst weeks = computed<Array<typeof calendarDays.value>>(() => {\n const days = get(calendarDays);\n const result = [];\n for (let i = 0; i < days.length; i += 7)\n result.push(days.slice(i, i + 7));\n return result;\n});\n\nfunction preferredActiveKey(): string {\n const days = get(calendarDays);\n const selected = days.find(day => day.isSelected && day.isInRange);\n const todayInView = days.find(day => day.isToday && day.isCurrentMonth && day.isInRange);\n const firstSelectable = days.find(day => day.isCurrentMonth && day.isInRange);\n return (selected ?? todayInView ?? firstSelectable ?? days[0])?.key ?? '';\n}\n\nfunction syncActiveKey(): void {\n const days = get(calendarDays);\n if (!days.some(day => day.key === get(activeKey)))\n set(activeKey, preferredActiveKey());\n}\n\nfunction keyToDate(key: string): Date {\n const [year, month, day] = key.split('-').map(Number);\n return new Date(year ?? 0, (month ?? 1) - 1, day ?? 1, 12, 0, 0, 0);\n}\n\nfunction focusKey(key: string): void {\n set(activeKey, key);\n nextTick(() => {\n get(gridRef)?.querySelector<HTMLButtonElement>(`[data-id=\"${key}\"]`)?.focus();\n });\n}\n\nfunction moveTo(target: Date): void {\n const { maxDate, minDate } = calendarState;\n const maxDateValue = isDefined(maxDate) ? get(maxDate) : null;\n const minDateValue = isDefined(minDate) ? get(minDate) : null;\n\n // min/max bound a contiguous range, so a blocked step means the edge is here\n if (!isDateInRangeCheck(target, maxDateValue, minDateValue))\n return;\n\n const key = createDateKey(target);\n\n // Even a day drawn as a spill day turns the page, so header and focus agree on the month\n if (target.getMonth() === viewMonth && target.getFullYear() === viewYear) {\n focusKey(key);\n return;\n }\n\n set(calendarState.viewMonth, target.getMonth());\n set(calendarState.viewYear, target.getFullYear());\n nextTick(() => {\n focusKey(key);\n });\n}\n\nfunction onKeydown(event: KeyboardEvent): void {\n const active = get(activeKey);\n if (!active)\n return;\n\n const current = keyToDate(active);\n const dayOffset = KEY_DAY_OFFSETS[event.key];\n\n if (dayOffset !== undefined) {\n event.preventDefault();\n moveTo(new Date(current.getFullYear(), current.getMonth(), current.getDate() + dayOffset, 12, 0, 0, 0));\n }\n else if (event.key === 'Home' || event.key === 'End') {\n event.preventDefault();\n const offset = event.key === 'Home' ? -current.getDay() : 6 - current.getDay();\n moveTo(new Date(current.getFullYear(), current.getMonth(), current.getDate() + offset, 12, 0, 0, 0));\n }\n else if (event.key === 'PageUp' || event.key === 'PageDown') {\n event.preventDefault();\n const delta = event.key === 'PageUp' ? -1 : 1;\n moveTo(new Date(current.getFullYear(), current.getMonth() + delta, current.getDate(), 12, 0, 0, 0));\n }\n}\n\n// Initial calculation\ncalculateCalendarDays();\nsyncActiveKey();\n\n// Watchers for recalculation only when needed\nwatch([() => viewMonth, () => viewYear], () => {\n calculateCalendarDays();\n syncActiveKey();\n});\n\nwatch(model, () => {\n calculateCalendarDays();\n syncActiveKey();\n});\n\nwatch(\n [() => calendarState.maxDate, () => calendarState.minDate],\n () => {\n calculateCalendarDays();\n syncActiveKey();\n },\n);\n</script>\n\n<template>\n <div class=\"w-full p-2 pt-0\">\n <div\n ref=\"grid\"\n role=\"grid\"\n class=\"grid grid-cols-7 gap-0.5\"\n @keydown=\"onKeydown($event)\"\n >\n <div\n role=\"row\"\n class=\"contents\"\n >\n <span\n v-for=\"day in daysOfWeek\"\n :key=\"day\"\n role=\"columnheader\"\n class=\"py-2 pb-4 text-xs font-medium text-center text-rui-neutral-500 dark:text-rui-neutral-400\"\n >\n {{ day }}\n </span>\n </div>\n\n <div\n v-for=\"(week, index) in weeks\"\n :key=\"index\"\n role=\"row\"\n class=\"contents\"\n >\n <button\n v-for=\"dayData in week\"\n :key=\"dayData.key\"\n type=\"button\"\n role=\"gridcell\"\n :data-id=\"dayData.key\"\n :data-current-month=\"dayData.isCurrentMonth || undefined\"\n :data-selected=\"dayData.isSelected || undefined\"\n :data-today=\"(dayData.isToday && !dayData.isSelected) || undefined\"\n :class=\"dayButton({\n selected: dayData.isSelected,\n currentMonth: !dayData.isSelected && dayData.isCurrentMonth,\n inRange: dayData.isInRange,\n today: dayData.isToday && !dayData.isSelected,\n })\"\n :disabled=\"!dayData.isInRange\"\n :tabindex=\"dayData.key === activeKey ? 0 : -1\"\n :aria-label=\"dayLabelFormatter.format(dayData.date)\"\n :aria-selected=\"dayData.isSelected\"\n :aria-current=\"dayData.isToday ? 'date' : undefined\"\n @click.stop=\"selectDate(dayData)\"\n @focus=\"activeKey = dayData.key\"\n >\n {{ dayData.dayNumber }}\n </button>\n </div>\n </div>\n </div>\n</template>\n"],"mappings":""}
@@ -48,19 +48,23 @@ var RuiCalendarGrid_vue_vue_type_script_setup_true_lang_default = /*@__PURE__*/
48
48
  const daysOfWeek = getDaysOfWeek();
49
49
  const todayKey = createDateKey(/* @__PURE__ */ new Date());
50
50
  const dayButton = tv({
51
- base: "h-9 w-full flex items-center justify-center text-sm rounded-full mx-auto max-w-[2.25rem] transition-colors duration-150 ease-in-out border-none outline-none cursor-pointer focus:ring-2 focus:ring-rui-primary focus:ring-opacity-50",
51
+ base: "h-9 w-full flex items-center justify-center text-sm rounded-rui-control mx-auto max-w-9 transition-colors duration-150 ease-in-out border-none outline-hidden cursor-pointer focus-visible:focus-ring",
52
52
  variants: {
53
- selected: { true: "bg-rui-primary text-white hover:bg-rui-primary/90 dark:hover:bg-rui-primary/90" },
53
+ selected: { true: "bg-rui-primary-fill text-rui-primary-foreground hover:bg-rui-primary-fill hover:state-layer-pressed" },
54
54
  currentMonth: {
55
- true: "text-gray-700 hover:bg-gray-100 dark:text-gray-300 dark:hover:bg-gray-700",
56
- false: "text-gray-400 dark:text-gray-600"
55
+ true: "text-rui-neutral-800 dark:text-rui-neutral-100",
56
+ false: "text-rui-neutral-500 dark:text-rui-neutral-400"
57
57
  },
58
58
  inRange: { false: "opacity-50 cursor-not-allowed hover:bg-transparent" },
59
- today: { true: `relative after:content-[''] after:absolute after:size-1 after:rounded-full after:bottom-1 after:left-1/2 after:-translate-x-1/2 after:bg-rui-primary` }
59
+ today: { true: "inset-ring inset-ring-rui-outline font-semibold" }
60
60
  },
61
61
  compoundVariants: [{
62
62
  selected: true,
63
- class: "text-white dark:text-white"
63
+ class: "text-rui-primary-foreground dark:text-rui-primary-foreground"
64
+ }, {
65
+ selected: false,
66
+ inRange: true,
67
+ class: "hover:bg-rui-hover"
64
68
  }]
65
69
  });
66
70
  const calendarDays = ref([]);
@@ -217,7 +221,7 @@ var RuiCalendarGrid_vue_vue_type_script_setup_true_lang_default = /*@__PURE__*/
217
221
  return openBlock(), createElementBlock("span", {
218
222
  key: day,
219
223
  role: "columnheader",
220
- class: "py-2 pb-4 text-xs font-medium text-center text-gray-500 dark:text-gray-400"
224
+ class: "py-2 pb-4 text-xs font-medium text-center text-rui-neutral-500 dark:text-rui-neutral-400"
221
225
  }, toDisplayString(day), 1);
222
226
  }), 128))]), (openBlock(true), createElementBlock(Fragment, null, renderList(weeks.value, (week, index) => {
223
227
  return openBlock(), createElementBlock("div", {
@@ -1 +1 @@
1
- {"version":3,"file":"RuiCalendarGrid.vue_vue_type_script_setup_true_lang.js","names":[],"sources":["../../../src/components/calendar/RuiCalendarGrid.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport { get, isDefined, set } from '@vueuse/core';\nimport { computed, inject, nextTick, ref, useTemplateRef, watch } from 'vue';\nimport {\n CalendarStateSymbol,\n getDaysOfWeek,\n type RuiCalendarState,\n} from '@/components/calendar/state';\nimport { tv } from '@/utils/tv';\n\ndefineOptions({\n name: 'RuiCalendarGrid',\n inheritAttrs: false,\n});\n\nconst model = defineModel<Date | undefined>();\n\nconst { viewMonth, viewYear } = defineProps<{\n viewMonth: number;\n viewYear: number;\n}>();\n\nconst calendarState = inject<RuiCalendarState>(CalendarStateSymbol) as RuiCalendarState;\n\n/**\n * The `YYYY-MM-DD` key a day is tracked and focused by.\n *\n * @param date - the day to key\n * @returns its key\n */\nfunction createDateKey(date: Date): string {\n return `${date.getFullYear()}-${(date.getMonth() + 1).toString().padStart(2, '0')}-${date.getDate().toString().padStart(2, '0')}`;\n}\n\n// Pre-calculated constants\nconst daysOfWeek = getDaysOfWeek();\nconst today = new Date();\nconst todayKey = createDateKey(today);\n\nconst dayButton = tv({\n base: 'h-9 w-full flex items-center justify-center text-sm rounded-full mx-auto max-w-[2.25rem] transition-colors duration-150 ease-in-out border-none outline-none cursor-pointer focus:ring-2 focus:ring-rui-primary focus:ring-opacity-50',\n variants: {\n selected: {\n true: 'bg-rui-primary text-white hover:bg-rui-primary/90 dark:hover:bg-rui-primary/90',\n },\n currentMonth: {\n true: 'text-gray-700 hover:bg-gray-100 dark:text-gray-300 dark:hover:bg-gray-700',\n false: 'text-gray-400 dark:text-gray-600',\n },\n inRange: {\n false: 'opacity-50 cursor-not-allowed hover:bg-transparent',\n },\n today: {\n true: `relative after:content-[''] after:absolute after:size-1 after:rounded-full after:bottom-1 after:left-1/2 after:-translate-x-1/2 after:bg-rui-primary`,\n },\n },\n compoundVariants: [\n {\n selected: true,\n class: 'text-white dark:text-white',\n },\n ],\n});\n\n// Pre-calculated arrays for performance - using refs for better control\nconst calendarDays = ref<\n Array<{\n date: Date;\n isCurrentMonth: boolean;\n isInRange: boolean;\n isSelected: boolean;\n isToday: boolean;\n key: string;\n dayNumber: number;\n }>\n>([]);\n\nfunction createDayData(\n date: Date,\n isCurrentMonth: boolean,\n modelValue: Date | null | undefined,\n maxDateValue: Date | null,\n minDateValue: Date | null,\n): {\n date: Date;\n isCurrentMonth: boolean;\n isInRange: boolean;\n isSelected: boolean;\n isToday: boolean;\n key: string;\n dayNumber: number;\n} {\n const key = createDateKey(date);\n return {\n date,\n isCurrentMonth,\n isInRange: isDateInRangeCheck(date, maxDateValue, minDateValue),\n isSelected: modelValue ? isDateSelectedCheck(date, modelValue) : false,\n isToday: key === todayKey,\n key,\n dayNumber: date.getDate(),\n };\n}\n\n/** Rebuilds the days the grid draws for the current view month. */\nfunction calculateCalendarDays(): void {\n const firstDayOfMonth = new Date(viewYear, viewMonth, 1);\n const lastDayOfMonth = new Date(viewYear, viewMonth + 1, 0);\n const daysInMonth = lastDayOfMonth.getDate();\n const startingDayOfWeek = firstDayOfMonth.getDay();\n\n const { maxDate, minDate } = calendarState;\n const modelValue = get(model);\n const maxDateValue = isDefined(maxDate) ? get(maxDate) : null;\n const minDateValue = isDefined(minDate) ? get(minDate) : null;\n\n const result = [];\n\n // Previous month days\n if (startingDayOfWeek > 0) {\n const prevMonthLastDay = new Date(viewYear, viewMonth, 0).getDate();\n for (let i = startingDayOfWeek - 1; i >= 0; i--) {\n const date = new Date(viewYear, viewMonth - 1, prevMonthLastDay - i, 12, 0, 0, 0);\n result.push(createDayData(date, false, modelValue, maxDateValue, minDateValue));\n }\n }\n\n // Current month days\n for (let i = 1; i <= daysInMonth; i++) {\n const date = new Date(viewYear, viewMonth, i, 12, 0, 0, 0);\n result.push(createDayData(date, true, modelValue, maxDateValue, minDateValue));\n }\n\n // Next month days\n const totalDaysSoFar = result.length;\n const daysToAdd = 42 - totalDaysSoFar;\n for (let i = 1; i <= daysToAdd; i++) {\n const date = new Date(viewYear, viewMonth + 1, i, 12, 0, 0, 0);\n result.push(createDayData(date, false, modelValue, maxDateValue, minDateValue));\n }\n\n set(calendarDays, result);\n}\n\nfunction isDateInRangeCheck(\n date: Date,\n maxDateValue: Date | null,\n minDateValue: Date | null,\n): boolean {\n if (maxDateValue && date > maxDateValue)\n return false;\n if (minDateValue && date < minDateValue)\n return false;\n return true;\n}\n\nfunction isDateSelectedCheck(date: Date, modelValue: Date): boolean {\n return (\n date.getFullYear() === modelValue.getFullYear() &&\n date.getMonth() === modelValue.getMonth() &&\n date.getDate() === modelValue.getDate()\n );\n}\n\nfunction selectDate(dayData: { date: Date; isInRange: boolean; isSelected: boolean }): void {\n if (!dayData.isInRange)\n return;\n\n let updateModel: Date | undefined;\n\n if (dayData.isSelected && calendarState.allowEmpty) {\n updateModel = undefined;\n }\n else if (isDefined(model)) {\n const modelValue = get(model);\n const newDate = new Date(dayData.date);\n newDate.setHours(modelValue.getHours());\n newDate.setMinutes(modelValue.getMinutes());\n newDate.setSeconds(modelValue.getSeconds());\n updateModel = newDate;\n }\n else {\n updateModel = new Date(dayData.date);\n }\n set(model, updateModel);\n}\n\n// Keyboard navigation: a roving tabindex, so crossing the calendar costs one Tab instead of 42\nconst gridRef = useTemplateRef<HTMLDivElement>('grid');\nconst activeKey = ref<string>('');\n\nconst dayLabelFormatter = new Intl.DateTimeFormat('en-US', { dateStyle: 'full' });\n\nconst KEY_DAY_OFFSETS: Record<string, number> = {\n ArrowDown: 7,\n ArrowLeft: -1,\n ArrowRight: 1,\n ArrowUp: -7,\n};\n\nconst weeks = computed<Array<typeof calendarDays.value>>(() => {\n const days = get(calendarDays);\n const result = [];\n for (let i = 0; i < days.length; i += 7)\n result.push(days.slice(i, i + 7));\n return result;\n});\n\nfunction preferredActiveKey(): string {\n const days = get(calendarDays);\n const selected = days.find(day => day.isSelected && day.isInRange);\n const todayInView = days.find(day => day.isToday && day.isCurrentMonth && day.isInRange);\n const firstSelectable = days.find(day => day.isCurrentMonth && day.isInRange);\n return (selected ?? todayInView ?? firstSelectable ?? days[0])?.key ?? '';\n}\n\nfunction syncActiveKey(): void {\n const days = get(calendarDays);\n if (!days.some(day => day.key === get(activeKey)))\n set(activeKey, preferredActiveKey());\n}\n\nfunction keyToDate(key: string): Date {\n const [year, month, day] = key.split('-').map(Number);\n return new Date(year ?? 0, (month ?? 1) - 1, day ?? 1, 12, 0, 0, 0);\n}\n\nfunction focusKey(key: string): void {\n set(activeKey, key);\n nextTick(() => {\n get(gridRef)?.querySelector<HTMLButtonElement>(`[data-id=\"${key}\"]`)?.focus();\n });\n}\n\nfunction moveTo(target: Date): void {\n const { maxDate, minDate } = calendarState;\n const maxDateValue = isDefined(maxDate) ? get(maxDate) : null;\n const minDateValue = isDefined(minDate) ? get(minDate) : null;\n\n // min/max bound a contiguous range, so a blocked step means the edge is here\n if (!isDateInRangeCheck(target, maxDateValue, minDateValue))\n return;\n\n const key = createDateKey(target);\n\n // Even a day drawn as a spill day turns the page, so header and focus agree on the month\n if (target.getMonth() === viewMonth && target.getFullYear() === viewYear) {\n focusKey(key);\n return;\n }\n\n set(calendarState.viewMonth, target.getMonth());\n set(calendarState.viewYear, target.getFullYear());\n nextTick(() => {\n focusKey(key);\n });\n}\n\nfunction onKeydown(event: KeyboardEvent): void {\n const active = get(activeKey);\n if (!active)\n return;\n\n const current = keyToDate(active);\n const dayOffset = KEY_DAY_OFFSETS[event.key];\n\n if (dayOffset !== undefined) {\n event.preventDefault();\n moveTo(new Date(current.getFullYear(), current.getMonth(), current.getDate() + dayOffset, 12, 0, 0, 0));\n }\n else if (event.key === 'Home' || event.key === 'End') {\n event.preventDefault();\n const offset = event.key === 'Home' ? -current.getDay() : 6 - current.getDay();\n moveTo(new Date(current.getFullYear(), current.getMonth(), current.getDate() + offset, 12, 0, 0, 0));\n }\n else if (event.key === 'PageUp' || event.key === 'PageDown') {\n event.preventDefault();\n const delta = event.key === 'PageUp' ? -1 : 1;\n moveTo(new Date(current.getFullYear(), current.getMonth() + delta, current.getDate(), 12, 0, 0, 0));\n }\n}\n\n// Initial calculation\ncalculateCalendarDays();\nsyncActiveKey();\n\n// Watchers for recalculation only when needed\nwatch([() => viewMonth, () => viewYear], () => {\n calculateCalendarDays();\n syncActiveKey();\n});\n\nwatch(model, () => {\n calculateCalendarDays();\n syncActiveKey();\n});\n\nwatch(\n [() => calendarState.maxDate, () => calendarState.minDate],\n () => {\n calculateCalendarDays();\n syncActiveKey();\n },\n);\n</script>\n\n<template>\n <div class=\"w-full p-2 pt-0\">\n <div\n ref=\"grid\"\n role=\"grid\"\n class=\"grid grid-cols-7 gap-0.5\"\n @keydown=\"onKeydown($event)\"\n >\n <div\n role=\"row\"\n class=\"contents\"\n >\n <span\n v-for=\"day in daysOfWeek\"\n :key=\"day\"\n role=\"columnheader\"\n class=\"py-2 pb-4 text-xs font-medium text-center text-gray-500 dark:text-gray-400\"\n >\n {{ day }}\n </span>\n </div>\n\n <div\n v-for=\"(week, index) in weeks\"\n :key=\"index\"\n role=\"row\"\n class=\"contents\"\n >\n <button\n v-for=\"dayData in week\"\n :key=\"dayData.key\"\n type=\"button\"\n role=\"gridcell\"\n :data-id=\"dayData.key\"\n :data-current-month=\"dayData.isCurrentMonth || undefined\"\n :data-selected=\"dayData.isSelected || undefined\"\n :data-today=\"(dayData.isToday && !dayData.isSelected) || undefined\"\n :class=\"dayButton({\n selected: dayData.isSelected,\n currentMonth: !dayData.isSelected && dayData.isCurrentMonth,\n inRange: dayData.isInRange,\n today: dayData.isToday && !dayData.isSelected,\n })\"\n :disabled=\"!dayData.isInRange\"\n :tabindex=\"dayData.key === activeKey ? 0 : -1\"\n :aria-label=\"dayLabelFormatter.format(dayData.date)\"\n :aria-selected=\"dayData.isSelected\"\n :aria-current=\"dayData.isToday ? 'date' : undefined\"\n @click.stop=\"selectDate(dayData)\"\n @focus=\"activeKey = dayData.key\"\n >\n {{ dayData.dayNumber }}\n </button>\n </div>\n </div>\n </div>\n</template>\n"],"mappings":"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"}
1
+ {"version":3,"file":"RuiCalendarGrid.vue_vue_type_script_setup_true_lang.js","names":[],"sources":["../../../src/components/calendar/RuiCalendarGrid.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport { get, isDefined, set } from '@vueuse/core';\nimport { computed, inject, nextTick, ref, useTemplateRef, watch } from 'vue';\nimport {\n CalendarStateSymbol,\n getDaysOfWeek,\n type RuiCalendarState,\n} from '@/components/calendar/state';\nimport { tv } from '@/utils/tv';\n\ndefineOptions({\n name: 'RuiCalendarGrid',\n inheritAttrs: false,\n});\n\nconst model = defineModel<Date | undefined>();\n\nconst { viewMonth, viewYear } = defineProps<{\n viewMonth: number;\n viewYear: number;\n}>();\n\nconst calendarState = inject<RuiCalendarState>(CalendarStateSymbol) as RuiCalendarState;\n\n/**\n * The `YYYY-MM-DD` key a day is tracked and focused by.\n *\n * @param date - the day to key\n * @returns its key\n */\nfunction createDateKey(date: Date): string {\n return `${date.getFullYear()}-${(date.getMonth() + 1).toString().padStart(2, '0')}-${date.getDate().toString().padStart(2, '0')}`;\n}\n\n// Pre-calculated constants\nconst daysOfWeek = getDaysOfWeek();\nconst today = new Date();\nconst todayKey = createDateKey(today);\n\nconst dayButton = tv({\n base: 'h-9 w-full flex items-center justify-center text-sm rounded-rui-control mx-auto max-w-9 transition-colors duration-150 ease-in-out border-none outline-hidden cursor-pointer focus-visible:focus-ring',\n variants: {\n selected: {\n true: 'bg-rui-primary-fill text-rui-primary-foreground hover:bg-rui-primary-fill hover:state-layer-pressed',\n },\n // the neighbouring months' days are a step quieter but still pickable, so they keep 4.5:1\n currentMonth: {\n true: 'text-rui-neutral-800 dark:text-rui-neutral-100',\n false: 'text-rui-neutral-500 dark:text-rui-neutral-400',\n },\n inRange: {\n false: 'opacity-50 cursor-not-allowed hover:bg-transparent',\n },\n today: {\n true: 'inset-ring inset-ring-rui-outline font-semibold',\n },\n },\n compoundVariants: [\n // restated under `dark:`, which the current-month day color uses and would otherwise win\n {\n selected: true,\n class: 'text-rui-primary-foreground dark:text-rui-primary-foreground',\n },\n // only a pickable, unselected day takes the grey hover; on the selected one it replaced the fill\n { selected: false, inRange: true, class: 'hover:bg-rui-hover' },\n ],\n});\n\n// Pre-calculated arrays for performance - using refs for better control\nconst calendarDays = ref<\n Array<{\n date: Date;\n isCurrentMonth: boolean;\n isInRange: boolean;\n isSelected: boolean;\n isToday: boolean;\n key: string;\n dayNumber: number;\n }>\n>([]);\n\nfunction createDayData(\n date: Date,\n isCurrentMonth: boolean,\n modelValue: Date | null | undefined,\n maxDateValue: Date | null,\n minDateValue: Date | null,\n): {\n date: Date;\n isCurrentMonth: boolean;\n isInRange: boolean;\n isSelected: boolean;\n isToday: boolean;\n key: string;\n dayNumber: number;\n} {\n const key = createDateKey(date);\n return {\n date,\n isCurrentMonth,\n isInRange: isDateInRangeCheck(date, maxDateValue, minDateValue),\n isSelected: modelValue ? isDateSelectedCheck(date, modelValue) : false,\n isToday: key === todayKey,\n key,\n dayNumber: date.getDate(),\n };\n}\n\n/** Rebuilds the days the grid draws for the current view month. */\nfunction calculateCalendarDays(): void {\n const firstDayOfMonth = new Date(viewYear, viewMonth, 1);\n const lastDayOfMonth = new Date(viewYear, viewMonth + 1, 0);\n const daysInMonth = lastDayOfMonth.getDate();\n const startingDayOfWeek = firstDayOfMonth.getDay();\n\n const { maxDate, minDate } = calendarState;\n const modelValue = get(model);\n const maxDateValue = isDefined(maxDate) ? get(maxDate) : null;\n const minDateValue = isDefined(minDate) ? get(minDate) : null;\n\n const result = [];\n\n // Previous month days\n if (startingDayOfWeek > 0) {\n const prevMonthLastDay = new Date(viewYear, viewMonth, 0).getDate();\n for (let i = startingDayOfWeek - 1; i >= 0; i--) {\n const date = new Date(viewYear, viewMonth - 1, prevMonthLastDay - i, 12, 0, 0, 0);\n result.push(createDayData(date, false, modelValue, maxDateValue, minDateValue));\n }\n }\n\n // Current month days\n for (let i = 1; i <= daysInMonth; i++) {\n const date = new Date(viewYear, viewMonth, i, 12, 0, 0, 0);\n result.push(createDayData(date, true, modelValue, maxDateValue, minDateValue));\n }\n\n // Next month days\n const totalDaysSoFar = result.length;\n const daysToAdd = 42 - totalDaysSoFar;\n for (let i = 1; i <= daysToAdd; i++) {\n const date = new Date(viewYear, viewMonth + 1, i, 12, 0, 0, 0);\n result.push(createDayData(date, false, modelValue, maxDateValue, minDateValue));\n }\n\n set(calendarDays, result);\n}\n\nfunction isDateInRangeCheck(\n date: Date,\n maxDateValue: Date | null,\n minDateValue: Date | null,\n): boolean {\n if (maxDateValue && date > maxDateValue)\n return false;\n if (minDateValue && date < minDateValue)\n return false;\n return true;\n}\n\nfunction isDateSelectedCheck(date: Date, modelValue: Date): boolean {\n return (\n date.getFullYear() === modelValue.getFullYear() &&\n date.getMonth() === modelValue.getMonth() &&\n date.getDate() === modelValue.getDate()\n );\n}\n\nfunction selectDate(dayData: { date: Date; isInRange: boolean; isSelected: boolean }): void {\n if (!dayData.isInRange)\n return;\n\n let updateModel: Date | undefined;\n\n if (dayData.isSelected && calendarState.allowEmpty) {\n updateModel = undefined;\n }\n else if (isDefined(model)) {\n const modelValue = get(model);\n const newDate = new Date(dayData.date);\n newDate.setHours(modelValue.getHours());\n newDate.setMinutes(modelValue.getMinutes());\n newDate.setSeconds(modelValue.getSeconds());\n updateModel = newDate;\n }\n else {\n updateModel = new Date(dayData.date);\n }\n set(model, updateModel);\n}\n\n// Keyboard navigation: a roving tabindex, so crossing the calendar costs one Tab instead of 42\nconst gridRef = useTemplateRef<HTMLDivElement>('grid');\nconst activeKey = ref<string>('');\n\nconst dayLabelFormatter = new Intl.DateTimeFormat('en-US', { dateStyle: 'full' });\n\nconst KEY_DAY_OFFSETS: Record<string, number> = {\n ArrowDown: 7,\n ArrowLeft: -1,\n ArrowRight: 1,\n ArrowUp: -7,\n};\n\nconst weeks = computed<Array<typeof calendarDays.value>>(() => {\n const days = get(calendarDays);\n const result = [];\n for (let i = 0; i < days.length; i += 7)\n result.push(days.slice(i, i + 7));\n return result;\n});\n\nfunction preferredActiveKey(): string {\n const days = get(calendarDays);\n const selected = days.find(day => day.isSelected && day.isInRange);\n const todayInView = days.find(day => day.isToday && day.isCurrentMonth && day.isInRange);\n const firstSelectable = days.find(day => day.isCurrentMonth && day.isInRange);\n return (selected ?? todayInView ?? firstSelectable ?? days[0])?.key ?? '';\n}\n\nfunction syncActiveKey(): void {\n const days = get(calendarDays);\n if (!days.some(day => day.key === get(activeKey)))\n set(activeKey, preferredActiveKey());\n}\n\nfunction keyToDate(key: string): Date {\n const [year, month, day] = key.split('-').map(Number);\n return new Date(year ?? 0, (month ?? 1) - 1, day ?? 1, 12, 0, 0, 0);\n}\n\nfunction focusKey(key: string): void {\n set(activeKey, key);\n nextTick(() => {\n get(gridRef)?.querySelector<HTMLButtonElement>(`[data-id=\"${key}\"]`)?.focus();\n });\n}\n\nfunction moveTo(target: Date): void {\n const { maxDate, minDate } = calendarState;\n const maxDateValue = isDefined(maxDate) ? get(maxDate) : null;\n const minDateValue = isDefined(minDate) ? get(minDate) : null;\n\n // min/max bound a contiguous range, so a blocked step means the edge is here\n if (!isDateInRangeCheck(target, maxDateValue, minDateValue))\n return;\n\n const key = createDateKey(target);\n\n // Even a day drawn as a spill day turns the page, so header and focus agree on the month\n if (target.getMonth() === viewMonth && target.getFullYear() === viewYear) {\n focusKey(key);\n return;\n }\n\n set(calendarState.viewMonth, target.getMonth());\n set(calendarState.viewYear, target.getFullYear());\n nextTick(() => {\n focusKey(key);\n });\n}\n\nfunction onKeydown(event: KeyboardEvent): void {\n const active = get(activeKey);\n if (!active)\n return;\n\n const current = keyToDate(active);\n const dayOffset = KEY_DAY_OFFSETS[event.key];\n\n if (dayOffset !== undefined) {\n event.preventDefault();\n moveTo(new Date(current.getFullYear(), current.getMonth(), current.getDate() + dayOffset, 12, 0, 0, 0));\n }\n else if (event.key === 'Home' || event.key === 'End') {\n event.preventDefault();\n const offset = event.key === 'Home' ? -current.getDay() : 6 - current.getDay();\n moveTo(new Date(current.getFullYear(), current.getMonth(), current.getDate() + offset, 12, 0, 0, 0));\n }\n else if (event.key === 'PageUp' || event.key === 'PageDown') {\n event.preventDefault();\n const delta = event.key === 'PageUp' ? -1 : 1;\n moveTo(new Date(current.getFullYear(), current.getMonth() + delta, current.getDate(), 12, 0, 0, 0));\n }\n}\n\n// Initial calculation\ncalculateCalendarDays();\nsyncActiveKey();\n\n// Watchers for recalculation only when needed\nwatch([() => viewMonth, () => viewYear], () => {\n calculateCalendarDays();\n syncActiveKey();\n});\n\nwatch(model, () => {\n calculateCalendarDays();\n syncActiveKey();\n});\n\nwatch(\n [() => calendarState.maxDate, () => calendarState.minDate],\n () => {\n calculateCalendarDays();\n syncActiveKey();\n },\n);\n</script>\n\n<template>\n <div class=\"w-full p-2 pt-0\">\n <div\n ref=\"grid\"\n role=\"grid\"\n class=\"grid grid-cols-7 gap-0.5\"\n @keydown=\"onKeydown($event)\"\n >\n <div\n role=\"row\"\n class=\"contents\"\n >\n <span\n v-for=\"day in daysOfWeek\"\n :key=\"day\"\n role=\"columnheader\"\n class=\"py-2 pb-4 text-xs font-medium text-center text-rui-neutral-500 dark:text-rui-neutral-400\"\n >\n {{ day }}\n </span>\n </div>\n\n <div\n v-for=\"(week, index) in weeks\"\n :key=\"index\"\n role=\"row\"\n class=\"contents\"\n >\n <button\n v-for=\"dayData in week\"\n :key=\"dayData.key\"\n type=\"button\"\n role=\"gridcell\"\n :data-id=\"dayData.key\"\n :data-current-month=\"dayData.isCurrentMonth || undefined\"\n :data-selected=\"dayData.isSelected || undefined\"\n :data-today=\"(dayData.isToday && !dayData.isSelected) || undefined\"\n :class=\"dayButton({\n selected: dayData.isSelected,\n currentMonth: !dayData.isSelected && dayData.isCurrentMonth,\n inRange: dayData.isInRange,\n today: dayData.isToday && !dayData.isSelected,\n })\"\n :disabled=\"!dayData.isInRange\"\n :tabindex=\"dayData.key === activeKey ? 0 : -1\"\n :aria-label=\"dayLabelFormatter.format(dayData.date)\"\n :aria-selected=\"dayData.isSelected\"\n :aria-current=\"dayData.isToday ? 'date' : undefined\"\n @click.stop=\"selectDate(dayData)\"\n @focus=\"activeKey = dayData.key\"\n >\n {{ dayData.dayNumber }}\n </button>\n </div>\n </div>\n </div>\n</template>\n"],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"RuiCalendarHeader.js","names":[],"sources":["../../../src/components/calendar/RuiCalendarHeader.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport { get, isDefined, set } from '@vueuse/core';\nimport { computed, inject, ref } from 'vue';\nimport RuiButton from '@/components/buttons/button/RuiButton.vue';\nimport {\n CalendarStateSymbol,\n type MonthYearSelection,\n type RuiCalendarState,\n} from '@/components/calendar/state';\nimport RuiIcon from '@/components/icons/RuiIcon.vue';\nimport RuiCalendarMenu from './RuiCalendarMenu.vue';\n\ndefineOptions({\n name: 'RuiCalendarHeader',\n inheritAttrs: false,\n});\n\nconst isMenuOpen = defineModel<boolean>('menu-open', { required: true });\n\nconst { viewMonth, viewYear } = defineProps<{\n title: string;\n viewMonth: number;\n viewYear: number;\n}>();\n\nconst emit = defineEmits<{\n 'prev-month': [];\n 'next-month': [];\n 'select-month': [MonthYearSelection];\n}>();\n\nconst anchorEl = ref<HTMLElement>();\n\nconst calendarState = inject<RuiCalendarState>(CalendarStateSymbol) as RuiCalendarState;\n\nconst navButtonClass = 'p-1 rounded-full text-gray-500 hover:text-rui-primary hover:bg-gray-100 dark:text-gray-400 dark:hover:bg-gray-600 dark:hover:text-rui-primary';\n\nconst canGoToNext = computed<boolean>(() => {\n const { maxDate } = calendarState;\n if (!isDefined(maxDate)) {\n return true;\n }\n\n const date = new Date(viewYear, viewMonth);\n return date.getTime() < get(maxDate).getTime();\n});\n\nconst canGoToPrev = computed<boolean>(() => {\n const { minDate } = calendarState;\n if (!isDefined(minDate)) {\n return true;\n }\n\n const date = new Date(viewYear, viewMonth);\n return date.getTime() > get(minDate).getTime();\n});\n\nfunction handleTitleClick(e: Event): void {\n set(anchorEl, (e.currentTarget as HTMLElement) ?? undefined);\n set(isMenuOpen, true);\n}\n\nfunction handleDateSelection(selection: MonthYearSelection): void {\n emit('select-month', selection);\n}\n</script>\n\n<template>\n <div class=\"flex items-center justify-between px-4 py-3\">\n <RuiButton\n type=\"button\"\n :class=\"navButtonClass\"\n icon\n data-id=\"nav-prev\"\n :disabled=\"!canGoToPrev\"\n variant=\"text\"\n @click.stop=\"emit('prev-month')\"\n >\n <RuiIcon\n name=\"lu-chevron-left\"\n size=\"20\"\n />\n </RuiButton>\n\n <h3\n class=\"font-medium text-gray-800 dark:text-gray-200 flex items-center cursor-pointer pl-8\"\n data-id=\"header-title\"\n @click.stop=\"handleTitleClick($event)\"\n >\n {{ title }}\n <RuiIcon\n name=\"lu-chevron-down\"\n size=\"16\"\n class=\"ml-1\"\n />\n </h3>\n\n <RuiCalendarMenu\n v-model=\"isMenuOpen\"\n :anchor-el=\"anchorEl\"\n :view-month=\"viewMonth\"\n :view-year=\"viewYear\"\n @select=\"handleDateSelection($event)\"\n />\n\n <RuiButton\n type=\"button\"\n :class=\"navButtonClass\"\n variant=\"text\"\n icon\n data-id=\"nav-next\"\n :disabled=\"!canGoToNext\"\n @click.stop=\"emit('next-month')\"\n >\n <RuiIcon\n name=\"lu-chevron-right\"\n size=\"20\"\n />\n </RuiButton>\n </div>\n</template>\n"],"mappings":""}
1
+ {"version":3,"file":"RuiCalendarHeader.js","names":[],"sources":["../../../src/components/calendar/RuiCalendarHeader.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport { get, isDefined, set } from '@vueuse/core';\nimport { computed, inject, ref } from 'vue';\nimport RuiButton from '@/components/buttons/button/RuiButton.vue';\nimport {\n CalendarStateSymbol,\n type MonthYearSelection,\n type RuiCalendarState,\n} from '@/components/calendar/state';\nimport RuiIcon from '@/components/icons/RuiIcon.vue';\nimport RuiCalendarMenu from './RuiCalendarMenu.vue';\n\ndefineOptions({\n name: 'RuiCalendarHeader',\n inheritAttrs: false,\n});\n\nconst isMenuOpen = defineModel<boolean>('menu-open', { required: true });\n\nconst { viewMonth, viewYear } = defineProps<{\n title: string;\n viewMonth: number;\n viewYear: number;\n}>();\n\nconst emit = defineEmits<{\n 'prev-month': [];\n 'next-month': [];\n 'select-month': [MonthYearSelection];\n}>();\n\nconst anchorEl = ref<HTMLElement>();\n\nconst calendarState = inject<RuiCalendarState>(CalendarStateSymbol) as RuiCalendarState;\n\nconst canGoToNext = computed<boolean>(() => {\n const { maxDate } = calendarState;\n if (!isDefined(maxDate)) {\n return true;\n }\n\n const date = new Date(viewYear, viewMonth);\n return date.getTime() < get(maxDate).getTime();\n});\n\nconst canGoToPrev = computed<boolean>(() => {\n const { minDate } = calendarState;\n if (!isDefined(minDate)) {\n return true;\n }\n\n const date = new Date(viewYear, viewMonth);\n return date.getTime() > get(minDate).getTime();\n});\n\nfunction handleTitleClick(e: Event): void {\n set(anchorEl, e.currentTarget instanceof HTMLElement ? e.currentTarget : undefined);\n set(isMenuOpen, true);\n}\n\nfunction handleDateSelection(selection: MonthYearSelection): void {\n emit('select-month', selection);\n}\n</script>\n\n<template>\n <div class=\"flex items-center justify-between px-3 py-2\">\n <RuiButton\n type=\"button\"\n icon\n size=\"sm\"\n data-id=\"nav-prev\"\n aria-label=\"Previous month\"\n :disabled=\"!canGoToPrev\"\n variant=\"text\"\n @click.stop=\"emit('prev-month')\"\n >\n <RuiIcon name=\"lu-chevron-left\" />\n </RuiButton>\n\n <!--\n The title and its picker share the middle, so the picker's own wrapper is not a fourth flex item\n that pulls the title off center. The month and year open the picker, so they are a button.\n -->\n <div class=\"flex min-w-0 flex-1 justify-center\">\n <button\n type=\"button\"\n class=\"flex items-center gap-1 rounded-rui-control px-2 py-1 text-sm font-medium text-rui-text transition-colors hover:bg-rui-hover outline-hidden focus-visible:focus-ring\"\n data-id=\"header-title\"\n aria-haspopup=\"dialog\"\n :aria-expanded=\"isMenuOpen\"\n @click.stop=\"handleTitleClick($event)\"\n >\n {{ title }}\n <RuiIcon\n name=\"lu-chevron-down\"\n size=\"14\"\n class=\"text-rui-text-secondary\"\n />\n </button>\n\n <RuiCalendarMenu\n v-model=\"isMenuOpen\"\n :anchor-el=\"anchorEl\"\n :view-month=\"viewMonth\"\n :view-year=\"viewYear\"\n @select=\"handleDateSelection($event)\"\n />\n </div>\n\n <RuiButton\n type=\"button\"\n variant=\"text\"\n icon\n size=\"sm\"\n data-id=\"nav-next\"\n aria-label=\"Next month\"\n :disabled=\"!canGoToNext\"\n @click.stop=\"emit('next-month')\"\n >\n <RuiIcon name=\"lu-chevron-right\" />\n </RuiButton>\n </div>\n</template>\n"],"mappings":""}
@@ -2,11 +2,12 @@ import RuiIcon_default from "../icons/RuiIcon.js";
2
2
  import RuiButton_default from "../buttons/button/RuiButton.js";
3
3
  import { CalendarStateSymbol } from "./state.js";
4
4
  import RuiCalendarMenu_default from "./RuiCalendarMenu.js";
5
- import { computed, createElementBlock, createElementVNode, createTextVNode, createVNode, defineComponent, inject, mergeModels, normalizeClass, openBlock, ref, toDisplayString, useModel, withCtx, withModifiers } from "vue";
5
+ import { computed, createElementBlock, createElementVNode, createTextVNode, createVNode, defineComponent, inject, mergeModels, openBlock, ref, toDisplayString, useModel, withCtx, withModifiers } from "vue";
6
6
  import { get, isDefined, set } from "@vueuse/core";
7
7
  //#region src/components/calendar/RuiCalendarHeader.vue?vue&type=script&setup=true&lang.ts
8
- var _hoisted_1 = { class: "flex items-center justify-between px-4 py-3" };
9
- var navButtonClass = "p-1 rounded-full text-gray-500 hover:text-rui-primary hover:bg-gray-100 dark:text-gray-400 dark:hover:bg-gray-600 dark:hover:text-rui-primary";
8
+ var _hoisted_1 = { class: "flex items-center justify-between px-3 py-2" };
9
+ var _hoisted_2 = { class: "flex min-w-0 flex-1 justify-center" };
10
+ var _hoisted_3 = ["aria-expanded"];
10
11
  var RuiCalendarHeader_vue_vue_type_script_setup_true_lang_default = /*@__PURE__*/ defineComponent({
11
12
  name: "RuiCalendarHeader",
12
13
  inheritAttrs: false,
@@ -43,7 +44,7 @@ var RuiCalendarHeader_vue_vue_type_script_setup_true_lang_default = /*@__PURE__*
43
44
  return new Date(__props.viewYear, __props.viewMonth).getTime() > get(minDate).getTime();
44
45
  });
45
46
  function handleTitleClick(e) {
46
- set(anchorEl, e.currentTarget ?? void 0);
47
+ set(anchorEl, e.currentTarget instanceof HTMLElement ? e.currentTarget : void 0);
47
48
  set(isMenuOpen, true);
48
49
  }
49
50
  function handleDateSelection(selection) {
@@ -53,29 +54,29 @@ var RuiCalendarHeader_vue_vue_type_script_setup_true_lang_default = /*@__PURE__*
53
54
  return openBlock(), createElementBlock("div", _hoisted_1, [
54
55
  createVNode(RuiButton_default, {
55
56
  type: "button",
56
- class: normalizeClass(navButtonClass),
57
57
  icon: "",
58
+ size: "sm",
58
59
  "data-id": "nav-prev",
60
+ "aria-label": "Previous month",
59
61
  disabled: !canGoToPrev.value,
60
62
  variant: "text",
61
63
  onClick: _cache[0] || (_cache[0] = withModifiers(($event) => emit("prev-month"), ["stop"]))
62
64
  }, {
63
- default: withCtx(() => [createVNode(RuiIcon_default, {
64
- name: "lu-chevron-left",
65
- size: "20"
66
- })]),
65
+ default: withCtx(() => [createVNode(RuiIcon_default, { name: "lu-chevron-left" })]),
67
66
  _: 1
68
67
  }, 8, ["disabled"]),
69
- createElementVNode("h3", {
70
- class: "font-medium text-gray-800 dark:text-gray-200 flex items-center cursor-pointer pl-8",
68
+ createElementVNode("div", _hoisted_2, [createElementVNode("button", {
69
+ type: "button",
70
+ class: "flex items-center gap-1 rounded-rui-control px-2 py-1 text-sm font-medium text-rui-text transition-colors hover:bg-rui-hover outline-hidden focus-visible:focus-ring",
71
71
  "data-id": "header-title",
72
+ "aria-haspopup": "dialog",
73
+ "aria-expanded": isMenuOpen.value,
72
74
  onClick: _cache[1] || (_cache[1] = withModifiers(($event) => handleTitleClick($event), ["stop"]))
73
75
  }, [createTextVNode(toDisplayString(__props.title) + " ", 1), createVNode(RuiIcon_default, {
74
76
  name: "lu-chevron-down",
75
- size: "16",
76
- class: "ml-1"
77
- })]),
78
- createVNode(RuiCalendarMenu_default, {
77
+ size: "14",
78
+ class: "text-rui-text-secondary"
79
+ })], 8, _hoisted_3), createVNode(RuiCalendarMenu_default, {
79
80
  modelValue: isMenuOpen.value,
80
81
  "onUpdate:modelValue": _cache[2] || (_cache[2] = ($event) => isMenuOpen.value = $event),
81
82
  "anchor-el": anchorEl.value,
@@ -87,20 +88,18 @@ var RuiCalendarHeader_vue_vue_type_script_setup_true_lang_default = /*@__PURE__*
87
88
  "anchor-el",
88
89
  "view-month",
89
90
  "view-year"
90
- ]),
91
+ ])]),
91
92
  createVNode(RuiButton_default, {
92
93
  type: "button",
93
- class: normalizeClass(navButtonClass),
94
94
  variant: "text",
95
95
  icon: "",
96
+ size: "sm",
96
97
  "data-id": "nav-next",
98
+ "aria-label": "Next month",
97
99
  disabled: !canGoToNext.value,
98
100
  onClick: _cache[4] || (_cache[4] = withModifiers(($event) => emit("next-month"), ["stop"]))
99
101
  }, {
100
- default: withCtx(() => [createVNode(RuiIcon_default, {
101
- name: "lu-chevron-right",
102
- size: "20"
103
- })]),
102
+ default: withCtx(() => [createVNode(RuiIcon_default, { name: "lu-chevron-right" })]),
104
103
  _: 1
105
104
  }, 8, ["disabled"])
106
105
  ]);
@@ -1 +1 @@
1
- {"version":3,"file":"RuiCalendarHeader.vue_vue_type_script_setup_true_lang.js","names":[],"sources":["../../../src/components/calendar/RuiCalendarHeader.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport { get, isDefined, set } from '@vueuse/core';\nimport { computed, inject, ref } from 'vue';\nimport RuiButton from '@/components/buttons/button/RuiButton.vue';\nimport {\n CalendarStateSymbol,\n type MonthYearSelection,\n type RuiCalendarState,\n} from '@/components/calendar/state';\nimport RuiIcon from '@/components/icons/RuiIcon.vue';\nimport RuiCalendarMenu from './RuiCalendarMenu.vue';\n\ndefineOptions({\n name: 'RuiCalendarHeader',\n inheritAttrs: false,\n});\n\nconst isMenuOpen = defineModel<boolean>('menu-open', { required: true });\n\nconst { viewMonth, viewYear } = defineProps<{\n title: string;\n viewMonth: number;\n viewYear: number;\n}>();\n\nconst emit = defineEmits<{\n 'prev-month': [];\n 'next-month': [];\n 'select-month': [MonthYearSelection];\n}>();\n\nconst anchorEl = ref<HTMLElement>();\n\nconst calendarState = inject<RuiCalendarState>(CalendarStateSymbol) as RuiCalendarState;\n\nconst navButtonClass = 'p-1 rounded-full text-gray-500 hover:text-rui-primary hover:bg-gray-100 dark:text-gray-400 dark:hover:bg-gray-600 dark:hover:text-rui-primary';\n\nconst canGoToNext = computed<boolean>(() => {\n const { maxDate } = calendarState;\n if (!isDefined(maxDate)) {\n return true;\n }\n\n const date = new Date(viewYear, viewMonth);\n return date.getTime() < get(maxDate).getTime();\n});\n\nconst canGoToPrev = computed<boolean>(() => {\n const { minDate } = calendarState;\n if (!isDefined(minDate)) {\n return true;\n }\n\n const date = new Date(viewYear, viewMonth);\n return date.getTime() > get(minDate).getTime();\n});\n\nfunction handleTitleClick(e: Event): void {\n set(anchorEl, (e.currentTarget as HTMLElement) ?? undefined);\n set(isMenuOpen, true);\n}\n\nfunction handleDateSelection(selection: MonthYearSelection): void {\n emit('select-month', selection);\n}\n</script>\n\n<template>\n <div class=\"flex items-center justify-between px-4 py-3\">\n <RuiButton\n type=\"button\"\n :class=\"navButtonClass\"\n icon\n data-id=\"nav-prev\"\n :disabled=\"!canGoToPrev\"\n variant=\"text\"\n @click.stop=\"emit('prev-month')\"\n >\n <RuiIcon\n name=\"lu-chevron-left\"\n size=\"20\"\n />\n </RuiButton>\n\n <h3\n class=\"font-medium text-gray-800 dark:text-gray-200 flex items-center cursor-pointer pl-8\"\n data-id=\"header-title\"\n @click.stop=\"handleTitleClick($event)\"\n >\n {{ title }}\n <RuiIcon\n name=\"lu-chevron-down\"\n size=\"16\"\n class=\"ml-1\"\n />\n </h3>\n\n <RuiCalendarMenu\n v-model=\"isMenuOpen\"\n :anchor-el=\"anchorEl\"\n :view-month=\"viewMonth\"\n :view-year=\"viewYear\"\n @select=\"handleDateSelection($event)\"\n />\n\n <RuiButton\n type=\"button\"\n :class=\"navButtonClass\"\n variant=\"text\"\n icon\n data-id=\"nav-next\"\n :disabled=\"!canGoToNext\"\n @click.stop=\"emit('next-month')\"\n >\n <RuiIcon\n name=\"lu-chevron-right\"\n size=\"20\"\n />\n </RuiButton>\n </div>\n</template>\n"],"mappings":";;;;;;;;AAmCA,IAAM,iBAAiB;;;;;;;;;;;;;;;;;;;;;;EAlBvB,MAAM,aAAa,SAAoB,SAAC,WAA+B;EAQvE,MAAM,OAAO;EAMb,MAAM,WAAW,IAAiB;EAElC,MAAM,gBAAgB,OAAyB,mBAAmB;EAIlE,MAAM,cAAc,eAAwB;GAC1C,MAAM,EAAE,YAAY;GACpB,IAAI,CAAC,UAAU,OAAO,GACpB,OAAO;GAIT,OAAO,IADU,KAAK,QAAA,UAAU,QAAA,SACzB,CAAA,CAAK,QAAQ,IAAI,IAAI,OAAO,CAAC,CAAC,QAAQ;EAC/C,CAAC;EAED,MAAM,cAAc,eAAwB;GAC1C,MAAM,EAAE,YAAY;GACpB,IAAI,CAAC,UAAU,OAAO,GACpB,OAAO;GAIT,OAAO,IADU,KAAK,QAAA,UAAU,QAAA,SACzB,CAAA,CAAK,QAAQ,IAAI,IAAI,OAAO,CAAC,CAAC,QAAQ;EAC/C,CAAC;EAED,SAAS,iBAAiB,GAAgB;GACxC,IAAI,UAAW,EAAE,iBAAiC,KAAA,CAAS;GAC3D,IAAI,YAAY,IAAI;EACtB;EAEA,SAAS,oBAAoB,WAAqC;GAChE,KAAK,gBAAgB,SAAS;EAChC;;GAIE,OAAA,UAAA,GAAA,mBAmDM,OAnDN,YAmDM;IAlDJ,YAaY,mBAAA;KAZV,MAAK;KACJ,OAAK,eAAE,cAAc;KACtB,MAAA;KACA,WAAQ;KACP,UAAQ,CAAG,YAAA;KACZ,SAAQ;KACP,SAAK,OAAA,OAAA,OAAA,KAAA,eAAA,WAAO,KAAI,YAAA,GAAA,CAAA,MAAA,CAAA;;KAEjB,SAAA,cAGE,CAHF,YAGE,iBAAA;MAFA,MAAK;MACL,MAAK;;;;IAIT,mBAWK,MAAA;KAVH,OAAM;KACN,WAAQ;KACP,SAAK,OAAA,OAAA,OAAA,KAAA,eAAA,WAAO,iBAAiB,MAAM,GAAA,CAAA,MAAA,CAAA;IAEjC,GAAA,CAAA,gBAAA,gBAAA,QAAA,KAAK,IAAG,KACX,CAAA,GAAA,YAIE,iBAAA;KAHA,MAAK;KACL,MAAK;KACL,OAAM;;IAIV,YAME,yBAAA;KALS,YAAA,WAAA;KAAA,uBAAA,OAAA,OAAA,OAAA,MAAA,WAAA,WAAU,QAAA;KAClB,aAAW,SAAA;KACX,cAAY,QAAA;KACZ,aAAW,QAAA;KACX,UAAM,OAAA,OAAA,OAAA,MAAA,WAAE,oBAAoB,MAAM;;;;;;;IAGrC,YAaY,mBAAA;KAZV,MAAK;KACJ,OAAK,eAAE,cAAc;KACtB,SAAQ;KACR,MAAA;KACA,WAAQ;KACP,UAAQ,CAAG,YAAA;KACX,SAAK,OAAA,OAAA,OAAA,KAAA,eAAA,WAAO,KAAI,YAAA,GAAA,CAAA,MAAA,CAAA;;KAEjB,SAAA,cAGE,CAHF,YAGE,iBAAA;MAFA,MAAK;MACL,MAAK"}
1
+ {"version":3,"file":"RuiCalendarHeader.vue_vue_type_script_setup_true_lang.js","names":[],"sources":["../../../src/components/calendar/RuiCalendarHeader.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport { get, isDefined, set } from '@vueuse/core';\nimport { computed, inject, ref } from 'vue';\nimport RuiButton from '@/components/buttons/button/RuiButton.vue';\nimport {\n CalendarStateSymbol,\n type MonthYearSelection,\n type RuiCalendarState,\n} from '@/components/calendar/state';\nimport RuiIcon from '@/components/icons/RuiIcon.vue';\nimport RuiCalendarMenu from './RuiCalendarMenu.vue';\n\ndefineOptions({\n name: 'RuiCalendarHeader',\n inheritAttrs: false,\n});\n\nconst isMenuOpen = defineModel<boolean>('menu-open', { required: true });\n\nconst { viewMonth, viewYear } = defineProps<{\n title: string;\n viewMonth: number;\n viewYear: number;\n}>();\n\nconst emit = defineEmits<{\n 'prev-month': [];\n 'next-month': [];\n 'select-month': [MonthYearSelection];\n}>();\n\nconst anchorEl = ref<HTMLElement>();\n\nconst calendarState = inject<RuiCalendarState>(CalendarStateSymbol) as RuiCalendarState;\n\nconst canGoToNext = computed<boolean>(() => {\n const { maxDate } = calendarState;\n if (!isDefined(maxDate)) {\n return true;\n }\n\n const date = new Date(viewYear, viewMonth);\n return date.getTime() < get(maxDate).getTime();\n});\n\nconst canGoToPrev = computed<boolean>(() => {\n const { minDate } = calendarState;\n if (!isDefined(minDate)) {\n return true;\n }\n\n const date = new Date(viewYear, viewMonth);\n return date.getTime() > get(minDate).getTime();\n});\n\nfunction handleTitleClick(e: Event): void {\n set(anchorEl, e.currentTarget instanceof HTMLElement ? e.currentTarget : undefined);\n set(isMenuOpen, true);\n}\n\nfunction handleDateSelection(selection: MonthYearSelection): void {\n emit('select-month', selection);\n}\n</script>\n\n<template>\n <div class=\"flex items-center justify-between px-3 py-2\">\n <RuiButton\n type=\"button\"\n icon\n size=\"sm\"\n data-id=\"nav-prev\"\n aria-label=\"Previous month\"\n :disabled=\"!canGoToPrev\"\n variant=\"text\"\n @click.stop=\"emit('prev-month')\"\n >\n <RuiIcon name=\"lu-chevron-left\" />\n </RuiButton>\n\n <!--\n The title and its picker share the middle, so the picker's own wrapper is not a fourth flex item\n that pulls the title off center. The month and year open the picker, so they are a button.\n -->\n <div class=\"flex min-w-0 flex-1 justify-center\">\n <button\n type=\"button\"\n class=\"flex items-center gap-1 rounded-rui-control px-2 py-1 text-sm font-medium text-rui-text transition-colors hover:bg-rui-hover outline-hidden focus-visible:focus-ring\"\n data-id=\"header-title\"\n aria-haspopup=\"dialog\"\n :aria-expanded=\"isMenuOpen\"\n @click.stop=\"handleTitleClick($event)\"\n >\n {{ title }}\n <RuiIcon\n name=\"lu-chevron-down\"\n size=\"14\"\n class=\"text-rui-text-secondary\"\n />\n </button>\n\n <RuiCalendarMenu\n v-model=\"isMenuOpen\"\n :anchor-el=\"anchorEl\"\n :view-month=\"viewMonth\"\n :view-year=\"viewYear\"\n @select=\"handleDateSelection($event)\"\n />\n </div>\n\n <RuiButton\n type=\"button\"\n variant=\"text\"\n icon\n size=\"sm\"\n data-id=\"nav-next\"\n aria-label=\"Next month\"\n :disabled=\"!canGoToNext\"\n @click.stop=\"emit('next-month')\"\n >\n <RuiIcon name=\"lu-chevron-right\" />\n </RuiButton>\n </div>\n</template>\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAiBA,MAAM,aAAa,SAAoB,SAAC,WAA+B;EAQvE,MAAM,OAAO;EAMb,MAAM,WAAW,IAAiB;EAElC,MAAM,gBAAgB,OAAyB,mBAAmB;EAElE,MAAM,cAAc,eAAwB;GAC1C,MAAM,EAAE,YAAY;GACpB,IAAI,CAAC,UAAU,OAAO,GACpB,OAAO;GAIT,OAAO,IADU,KAAK,QAAA,UAAU,QAAA,SACzB,CAAA,CAAK,QAAQ,IAAI,IAAI,OAAO,CAAC,CAAC,QAAQ;EAC/C,CAAC;EAED,MAAM,cAAc,eAAwB;GAC1C,MAAM,EAAE,YAAY;GACpB,IAAI,CAAC,UAAU,OAAO,GACpB,OAAO;GAIT,OAAO,IADU,KAAK,QAAA,UAAU,QAAA,SACzB,CAAA,CAAK,QAAQ,IAAI,IAAI,OAAO,CAAC,CAAC,QAAQ;EAC/C,CAAC;EAED,SAAS,iBAAiB,GAAgB;GACxC,IAAI,UAAU,EAAE,yBAAyB,cAAc,EAAE,gBAAgB,KAAA,CAAS;GAClF,IAAI,YAAY,IAAI;EACtB;EAEA,SAAS,oBAAoB,WAAqC;GAChE,KAAK,gBAAgB,SAAS;EAChC;;GAIE,OAAA,UAAA,GAAA,mBAwDM,OAxDN,YAwDM;IAvDJ,YAWY,mBAAA;KAVV,MAAK;KACL,MAAA;KACA,MAAK;KACL,WAAQ;KACR,cAAW;KACV,UAAQ,CAAG,YAAA;KACZ,SAAQ;KACP,SAAK,OAAA,OAAA,OAAA,KAAA,eAAA,WAAO,KAAI,YAAA,GAAA,CAAA,MAAA,CAAA;;KAEjB,SAAA,cAAkC,CAAlC,YAAkC,iBAAA,EAAzB,MAAK,kBAAiB,CAAA,CAAA,CAAA;;;IAOjC,mBAwBM,OAxBN,YAwBM,CAvBJ,mBAcS,UAAA;KAbP,MAAK;KACL,OAAM;KACN,WAAQ;KACR,iBAAc;KACb,iBAAe,WAAA;KACf,SAAK,OAAA,OAAA,OAAA,KAAA,eAAA,WAAO,iBAAiB,MAAM,GAAA,CAAA,MAAA,CAAA;IAEjC,GAAA,CAAA,gBAAA,gBAAA,QAAA,KAAK,IAAG,KACX,CAAA,GAAA,YAIE,iBAAA;KAHA,MAAK;KACL,MAAK;KACL,OAAM;IAIV,CAAA,CAAA,GAAA,GAAA,UAAA,GAAA,YAME,yBAAA;KALS,YAAA,WAAA;KAAA,uBAAA,OAAA,OAAA,OAAA,MAAA,WAAA,WAAU,QAAA;KAClB,aAAW,SAAA;KACX,cAAY,QAAA;KACZ,aAAW,QAAA;KACX,UAAM,OAAA,OAAA,OAAA,MAAA,WAAE,oBAAoB,MAAM;;;;;;;IAIvC,YAWY,mBAAA;KAVV,MAAK;KACL,SAAQ;KACR,MAAA;KACA,MAAK;KACL,WAAQ;KACR,cAAW;KACV,UAAQ,CAAG,YAAA;KACX,SAAK,OAAA,OAAA,OAAA,KAAA,eAAA,WAAO,KAAI,YAAA,GAAA,CAAA,MAAA,CAAA;;KAEjB,SAAA,cAAmC,CAAnC,YAAmC,iBAAA,EAA1B,MAAK,mBAAkB,CAAA,CAAA,CAAA"}
@@ -1 +1 @@
1
- {"version":3,"file":"RuiCalendarMenu.js","names":[],"sources":["../../../src/components/calendar/RuiCalendarMenu.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport { get, isDefined, set } from '@vueuse/core';\nimport { ref, watch } from 'vue';\nimport {\n CalendarStateSymbol,\n getShortMonthNames,\n type MonthYearSelection,\n type RuiCalendarState,\n} from '@/components/calendar/state';\nimport RuiIcon from '@/components/icons/RuiIcon.vue';\nimport RuiMenu from '@/components/overlays/menu/RuiMenu.vue';\nimport { type FloatingOptions, Placement } from '@/composables/floating';\nimport { tv } from '@/utils/tv';\nimport RuiButton from '../buttons/button/RuiButton.vue';\n\ndefineOptions({\n name: 'RuiCalendarMenu',\n inheritAttrs: false,\n});\n\nconst modelValue = defineModel<boolean>();\n\nconst { viewMonth, viewYear } = defineProps<{\n anchorEl: HTMLElement | undefined;\n viewMonth: number;\n viewYear: number;\n}>();\n\nconst emit = defineEmits<{\n select: [MonthYearSelection];\n}>();\n\nconst MENU_OPTIONS: FloatingOptions = { placement: Placement.bottomStart };\n\n// Core reactive state - minimal\nconst viewMode = ref<'months' | 'years'>('months');\nconst startYear = ref<number>(viewYear - 6);\n\n// Pre-calculated constants\nconst months = getShortMonthNames();\nconst calendarState = inject<RuiCalendarState>(CalendarStateSymbol) as RuiCalendarState;\n\nconst navButtonClass = 'p-1 rounded-full text-gray-500 hover:text-rui-primary hover:bg-gray-100 dark:text-gray-400 dark:hover:bg-gray-600 dark:hover:text-rui-primary';\n\nconst cellButton = tv({\n base: 'h-9 w-full flex items-center justify-center text-sm font-medium rounded-md transition-colors duration-150 ease-in-out border-none outline-none cursor-pointer focus:ring-2 focus:ring-rui-primary focus:ring-opacity-50',\n variants: {\n selected: {\n true: 'bg-rui-primary text-white hover:bg-rui-primary-darker active:bg-rui-primary-darker dark:bg-rui-primary dark:text-white dark:hover:bg-rui-primary-darker',\n },\n inRange: {\n true: 'text-gray-700 bg-transparent hover:bg-gray-100 active:bg-gray-200 dark:text-gray-300 dark:hover:bg-gray-700 dark:active:bg-gray-600',\n false: 'opacity-50 cursor-not-allowed bg-transparent hover:bg-transparent active:bg-transparent dark:hover:bg-transparent dark:active:bg-transparent pointer-events-none text-gray-400 dark:text-gray-600',\n },\n selectedOutOfRange: {\n true: 'bg-gray-300 text-gray-500 dark:bg-gray-600 dark:text-gray-400',\n },\n },\n});\n\n// Pre-calculated arrays for performance - using refs for better control\nconst yearRange = ref<number[]>([]);\nconst monthsInRange = ref<boolean[]>([]);\nconst yearsInRange = ref<boolean[]>([]);\nconst title = ref<string>('');\nconst canGoToNext = ref<boolean>(true);\nconst canGoToPrev = ref<boolean>(true);\n\n/** Rebuilds the years the picker offers around the current start year. */\nfunction calculateYearRange(): void {\n const start = get(startYear);\n set(\n yearRange,\n Array.from({ length: 12 }, (_, i) => start + i),\n );\n}\n\nfunction calculateTitle(): void {\n if (get(viewMode) === 'months') {\n set(title, viewYear.toString());\n }\n else {\n const range = get(yearRange);\n set(title, `${range[0]} - ${range.at(-1)}`);\n }\n}\n\nfunction calculateNavigation(): void {\n const { maxDate, minDate } = calendarState;\n const mode = get(viewMode);\n\n if (mode === 'months') {\n const nextYear = viewYear + 1;\n const previousYear = viewYear - 1;\n\n set(canGoToNext, !isDefined(maxDate) || nextYear <= get(maxDate).getFullYear());\n set(canGoToPrev, !isDefined(minDate) || previousYear >= get(minDate).getFullYear());\n }\n else {\n const lastYearInRange = get(startYear) + 11;\n const firstYearInRange = get(startYear);\n\n // Check if we can navigate to the next range of years\n const nextRangeStart = lastYearInRange + 1;\n set(canGoToNext, !isDefined(maxDate) || nextRangeStart <= get(maxDate).getFullYear());\n\n // Check if we can navigate to the previous range of years\n const prevRangeEnd = firstYearInRange - 1;\n set(canGoToPrev, !isDefined(minDate) || prevRangeEnd >= get(minDate).getFullYear());\n }\n}\n\nfunction calculateMonthsInRange(): void {\n const { minDate, maxDate } = calendarState;\n const currentYear = viewYear;\n const result = new Array(12).fill(true);\n\n if (isDefined(minDate) || isDefined(maxDate)) {\n for (let month = 0; month < 12; month++) {\n const date = new Date(currentYear, month);\n if (isDefined(maxDate) && date > get(maxDate)) {\n result[month] = false;\n }\n if (isDefined(minDate) && date < get(minDate)) {\n result[month] = false;\n }\n }\n }\n\n set(monthsInRange, result);\n}\n\nfunction calculateYearsInRange(): void {\n const { minDate, maxDate } = calendarState;\n const range = get(yearRange);\n const currentMonth = viewMonth;\n\n if (!isDefined(minDate) && !isDefined(maxDate)) {\n set(yearsInRange, new Array(range.length).fill(true));\n return;\n }\n\n const result = range.map((year) => {\n const date = new Date(year, currentMonth);\n if (isDefined(maxDate) && date > get(maxDate)) {\n return false;\n }\n return !isDefined(minDate) || date >= get(minDate);\n });\n\n set(yearsInRange, result);\n}\n\nfunction toggleSelection(): void {\n set(viewMode, get(viewMode) === 'months' ? 'years' : 'months');\n}\n\nfunction selectMonth(month: number): void {\n if (!get(monthsInRange)[month])\n return;\n emit('select', { month, year: viewYear });\n set(modelValue, false);\n}\n\nfunction selectYear(year: number): void {\n const yearIndex = get(yearRange).indexOf(year);\n if (yearIndex === -1 || !get(yearsInRange)[yearIndex])\n return;\n\n emit('select', { month: viewMonth, year });\n set(viewMode, 'months');\n}\n\nfunction handleNext(): void {\n if (get(viewMode) === 'months') {\n const nextYear = viewYear + 1;\n // Emit directly - navigation is already constrained by canGoToNext\n emit('select', { month: viewMonth, year: nextYear });\n }\n else {\n const lastYearInRange = get(startYear) + 11;\n set(startYear, lastYearInRange + 1);\n }\n}\n\nfunction handlePrev(): void {\n if (get(viewMode) === 'months') {\n const previousYear = viewYear - 1;\n // Emit directly - navigation is already constrained by canGoToPrev\n emit('select', { month: viewMonth, year: previousYear });\n }\n else {\n const firstYearInRange = get(startYear);\n set(startYear, firstYearInRange - 12);\n }\n}\n\n// Initial calculations\ncalculateYearRange();\ncalculateTitle();\ncalculateNavigation();\ncalculateMonthsInRange();\ncalculateYearsInRange();\n\n// Watchers for recalculation only when needed\nwatch(startYear, () => {\n calculateYearRange();\n calculateTitle();\n calculateNavigation();\n calculateYearsInRange();\n});\n\nwatch(viewMode, () => {\n calculateTitle();\n calculateNavigation();\n});\n\nwatch(\n () => viewYear,\n () => {\n calculateTitle();\n calculateNavigation();\n calculateMonthsInRange();\n calculateYearsInRange();\n },\n);\n\nwatch(\n () => viewMonth,\n () => {\n calculateYearsInRange();\n },\n);\n</script>\n\n<template>\n <RuiMenu\n v-model=\"modelValue\"\n :anchor-el=\"anchorEl\"\n :options=\"MENU_OPTIONS\"\n >\n <div class=\"w-64 shadow-lg overflow-hidden\">\n <div class=\"flex items-center justify-center p-1 font-medium text-gray-800 dark:text-gray-200 border-b border-rui-grey-200 dark:border-rui-grey-800 cursor-pointer hover:bg-rui-grey-100 dark:hover:bg-rui-grey-800\">\n <RuiButton\n type=\"button\"\n :class=\"navButtonClass\"\n icon\n :disabled=\"!get(canGoToPrev)\"\n variant=\"text\"\n @click.stop=\"handlePrev()\"\n >\n <RuiIcon\n name=\"lu-chevron-left\"\n size=\"20\"\n />\n </RuiButton>\n\n <div\n class=\"flex-1 text-center cursor-pointer\"\n @click.stop=\"toggleSelection()\"\n >\n {{ get(title) }}\n </div>\n\n <RuiButton\n type=\"button\"\n :class=\"navButtonClass\"\n icon\n :disabled=\"!get(canGoToNext)\"\n variant=\"text\"\n @click.stop=\"handleNext()\"\n >\n <RuiIcon\n name=\"lu-chevron-right\"\n size=\"20\"\n />\n </RuiButton>\n </div>\n\n <div\n v-if=\"viewMode === 'months'\"\n class=\"grid grid-cols-3 gap-1 p-2\"\n >\n <button\n v-for=\"(month, index) in months\"\n :key=\"month\"\n type=\"button\"\n :class=\"cellButton({\n selected: index === viewMonth && get(monthsInRange)[index],\n selectedOutOfRange: index === viewMonth && !get(monthsInRange)[index],\n inRange: index !== viewMonth ? get(monthsInRange)[index] : undefined,\n })\"\n :disabled=\"!get(monthsInRange)[index]\"\n @click.stop=\"selectMonth(index)\"\n >\n {{ month.substring(0, 3) }}\n </button>\n </div>\n\n <div\n v-else-if=\"viewMode === 'years'\"\n class=\"grid grid-cols-3 gap-1 p-2\"\n >\n <button\n v-for=\"(year, index) in yearRange\"\n :key=\"year\"\n type=\"button\"\n :class=\"cellButton({\n selected: year === viewYear && get(yearsInRange)[index],\n selectedOutOfRange: year === viewYear && !get(yearsInRange)[index],\n inRange: year !== viewYear ? get(yearsInRange)[index] : undefined,\n })\"\n :disabled=\"!get(yearsInRange)[index]\"\n @click.stop=\"selectYear(year)\"\n >\n {{ year }}\n </button>\n </div>\n </div>\n </RuiMenu>\n</template>\n"],"mappings":""}
1
+ {"version":3,"file":"RuiCalendarMenu.js","names":[],"sources":["../../../src/components/calendar/RuiCalendarMenu.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport { get, isDefined, set } from '@vueuse/core';\nimport { ref, watch } from 'vue';\nimport {\n CalendarStateSymbol,\n getShortMonthNames,\n type MonthYearSelection,\n type RuiCalendarState,\n} from '@/components/calendar/state';\nimport RuiIcon from '@/components/icons/RuiIcon.vue';\nimport RuiMenu from '@/components/overlays/menu/RuiMenu.vue';\nimport { type FloatingOptions, Placement } from '@/composables/floating';\nimport { tv } from '@/utils/tv';\nimport RuiButton from '../buttons/button/RuiButton.vue';\n\ndefineOptions({\n name: 'RuiCalendarMenu',\n inheritAttrs: false,\n});\n\nconst modelValue = defineModel<boolean>();\n\nconst { viewMonth, viewYear } = defineProps<{\n anchorEl: HTMLElement | undefined;\n viewMonth: number;\n viewYear: number;\n}>();\n\nconst emit = defineEmits<{\n select: [MonthYearSelection];\n}>();\n\nconst MENU_OPTIONS: FloatingOptions = { placement: Placement.bottomStart };\n\n// Core reactive state - minimal\nconst viewMode = ref<'months' | 'years'>('months');\nconst startYear = ref<number>(viewYear - 6);\n\n// Pre-calculated constants\nconst months = getShortMonthNames();\nconst calendarState = inject<RuiCalendarState>(CalendarStateSymbol) as RuiCalendarState;\n\nconst cellButton = tv({\n base: 'h-9 w-full flex items-center justify-center text-sm font-medium rounded-rui-control transition-colors duration-150 ease-in-out border-none outline-hidden cursor-pointer focus-visible:focus-ring',\n variants: {\n selected: {\n true: 'bg-rui-primary-fill text-rui-primary-foreground hover:bg-rui-primary-darker active:bg-rui-primary-darker',\n },\n inRange: {\n true: 'text-rui-text bg-transparent hover:bg-rui-hover active:bg-rui-pressed',\n false: 'cursor-not-allowed bg-transparent pointer-events-none text-rui-text-disabled',\n },\n selectedOutOfRange: {\n true: 'bg-rui-surface-muted text-rui-text-disabled',\n },\n },\n});\n\n// Pre-calculated arrays for performance - using refs for better control\nconst yearRange = ref<number[]>([]);\nconst monthsInRange = ref<boolean[]>([]);\nconst yearsInRange = ref<boolean[]>([]);\nconst title = ref<string>('');\nconst canGoToNext = ref<boolean>(true);\nconst canGoToPrev = ref<boolean>(true);\n\n/** Rebuilds the years the picker offers around the current start year. */\nfunction calculateYearRange(): void {\n const start = get(startYear);\n set(\n yearRange,\n Array.from({ length: 12 }, (_, i) => start + i),\n );\n}\n\nfunction calculateTitle(): void {\n if (get(viewMode) === 'months') {\n set(title, viewYear.toString());\n }\n else {\n const range = get(yearRange);\n set(title, `${range[0]} - ${range.at(-1)}`);\n }\n}\n\nfunction calculateNavigation(): void {\n const { maxDate, minDate } = calendarState;\n const mode = get(viewMode);\n\n if (mode === 'months') {\n const nextYear = viewYear + 1;\n const previousYear = viewYear - 1;\n\n set(canGoToNext, !isDefined(maxDate) || nextYear <= get(maxDate).getFullYear());\n set(canGoToPrev, !isDefined(minDate) || previousYear >= get(minDate).getFullYear());\n }\n else {\n const lastYearInRange = get(startYear) + 11;\n const firstYearInRange = get(startYear);\n\n // Check if we can navigate to the next range of years\n const nextRangeStart = lastYearInRange + 1;\n set(canGoToNext, !isDefined(maxDate) || nextRangeStart <= get(maxDate).getFullYear());\n\n // Check if we can navigate to the previous range of years\n const prevRangeEnd = firstYearInRange - 1;\n set(canGoToPrev, !isDefined(minDate) || prevRangeEnd >= get(minDate).getFullYear());\n }\n}\n\nfunction calculateMonthsInRange(): void {\n const { minDate, maxDate } = calendarState;\n const currentYear = viewYear;\n const result = new Array(12).fill(true);\n\n if (isDefined(minDate) || isDefined(maxDate)) {\n for (let month = 0; month < 12; month++) {\n const date = new Date(currentYear, month);\n if (isDefined(maxDate) && date > get(maxDate)) {\n result[month] = false;\n }\n if (isDefined(minDate) && date < get(minDate)) {\n result[month] = false;\n }\n }\n }\n\n set(monthsInRange, result);\n}\n\nfunction calculateYearsInRange(): void {\n const { minDate, maxDate } = calendarState;\n const range = get(yearRange);\n const currentMonth = viewMonth;\n\n if (!isDefined(minDate) && !isDefined(maxDate)) {\n set(yearsInRange, new Array(range.length).fill(true));\n return;\n }\n\n const result = range.map((year) => {\n const date = new Date(year, currentMonth);\n if (isDefined(maxDate) && date > get(maxDate)) {\n return false;\n }\n return !isDefined(minDate) || date >= get(minDate);\n });\n\n set(yearsInRange, result);\n}\n\nfunction toggleSelection(): void {\n set(viewMode, get(viewMode) === 'months' ? 'years' : 'months');\n}\n\nfunction selectMonth(month: number): void {\n if (!get(monthsInRange)[month])\n return;\n emit('select', { month, year: viewYear });\n set(modelValue, false);\n}\n\nfunction selectYear(year: number): void {\n const yearIndex = get(yearRange).indexOf(year);\n if (yearIndex === -1 || !get(yearsInRange)[yearIndex])\n return;\n\n emit('select', { month: viewMonth, year });\n set(viewMode, 'months');\n}\n\nfunction handleNext(): void {\n if (get(viewMode) === 'months') {\n const nextYear = viewYear + 1;\n // Emit directly - navigation is already constrained by canGoToNext\n emit('select', { month: viewMonth, year: nextYear });\n }\n else {\n const lastYearInRange = get(startYear) + 11;\n set(startYear, lastYearInRange + 1);\n }\n}\n\nfunction handlePrev(): void {\n if (get(viewMode) === 'months') {\n const previousYear = viewYear - 1;\n // Emit directly - navigation is already constrained by canGoToPrev\n emit('select', { month: viewMonth, year: previousYear });\n }\n else {\n const firstYearInRange = get(startYear);\n set(startYear, firstYearInRange - 12);\n }\n}\n\n// Initial calculations\ncalculateYearRange();\ncalculateTitle();\ncalculateNavigation();\ncalculateMonthsInRange();\ncalculateYearsInRange();\n\n// Watchers for recalculation only when needed\nwatch(startYear, () => {\n calculateYearRange();\n calculateTitle();\n calculateNavigation();\n calculateYearsInRange();\n});\n\nwatch(viewMode, () => {\n calculateTitle();\n calculateNavigation();\n});\n\nwatch(\n () => viewYear,\n () => {\n calculateTitle();\n calculateNavigation();\n calculateMonthsInRange();\n calculateYearsInRange();\n },\n);\n\nwatch(\n () => viewMonth,\n () => {\n calculateYearsInRange();\n },\n);\n</script>\n\n<template>\n <RuiMenu\n v-model=\"modelValue\"\n :anchor-el=\"anchorEl\"\n :options=\"MENU_OPTIONS\"\n >\n <div class=\"w-64 overflow-hidden\">\n <div class=\"flex items-center justify-between gap-1 border-b border-rui-divider px-1 pb-1 text-sm font-medium text-rui-text\">\n <RuiButton\n type=\"button\"\n icon\n size=\"sm\"\n aria-label=\"Previous\"\n :disabled=\"!get(canGoToPrev)\"\n variant=\"text\"\n @click.stop=\"handlePrev()\"\n >\n <RuiIcon name=\"lu-chevron-left\" />\n </RuiButton>\n\n <button\n type=\"button\"\n class=\"flex-1 rounded-rui-control px-2 py-1 text-center transition-colors hover:bg-rui-hover outline-hidden focus-visible:focus-ring\"\n @click.stop=\"toggleSelection()\"\n >\n {{ get(title) }}\n </button>\n\n <RuiButton\n type=\"button\"\n icon\n size=\"sm\"\n aria-label=\"Next\"\n :disabled=\"!get(canGoToNext)\"\n variant=\"text\"\n @click.stop=\"handleNext()\"\n >\n <RuiIcon name=\"lu-chevron-right\" />\n </RuiButton>\n </div>\n\n <div\n v-if=\"viewMode === 'months'\"\n class=\"grid grid-cols-3 gap-1 p-2\"\n >\n <button\n v-for=\"(month, index) in months\"\n :key=\"month\"\n type=\"button\"\n :class=\"cellButton({\n selected: index === viewMonth && get(monthsInRange)[index],\n selectedOutOfRange: index === viewMonth && !get(monthsInRange)[index],\n inRange: index !== viewMonth ? get(monthsInRange)[index] : undefined,\n })\"\n :disabled=\"!get(monthsInRange)[index]\"\n @click.stop=\"selectMonth(index)\"\n >\n {{ month.substring(0, 3) }}\n </button>\n </div>\n\n <div\n v-else-if=\"viewMode === 'years'\"\n class=\"grid grid-cols-3 gap-1 p-2\"\n >\n <button\n v-for=\"(year, index) in yearRange\"\n :key=\"year\"\n type=\"button\"\n :class=\"cellButton({\n selected: year === viewYear && get(yearsInRange)[index],\n selectedOutOfRange: year === viewYear && !get(yearsInRange)[index],\n inRange: year !== viewYear ? get(yearsInRange)[index] : undefined,\n })\"\n :disabled=\"!get(yearsInRange)[index]\"\n @click.stop=\"selectYear(year)\"\n >\n {{ year }}\n </button>\n </div>\n </div>\n </RuiMenu>\n</template>\n"],"mappings":""}
@@ -7,8 +7,8 @@ import RuiMenu_default from "../overlays/menu/RuiMenu.js";
7
7
  import { Fragment, createBlock, createCommentVNode, createElementBlock, createElementVNode, createVNode, defineComponent, inject, mergeModels, normalizeClass, openBlock, ref, renderList, toDisplayString, unref, useModel, watch, withCtx, withModifiers } from "vue";
8
8
  import { get, isDefined, set } from "@vueuse/core";
9
9
  //#region src/components/calendar/RuiCalendarMenu.vue?vue&type=script&setup=true&lang.ts
10
- var _hoisted_1 = { class: "w-64 shadow-lg overflow-hidden" };
11
- var _hoisted_2 = { class: "flex items-center justify-center p-1 font-medium text-gray-800 dark:text-gray-200 border-b border-rui-grey-200 dark:border-rui-grey-800 cursor-pointer hover:bg-rui-grey-100 dark:hover:bg-rui-grey-800" };
10
+ var _hoisted_1 = { class: "w-64 overflow-hidden" };
11
+ var _hoisted_2 = { class: "flex items-center justify-between gap-1 border-b border-rui-divider px-1 pb-1 text-sm font-medium text-rui-text" };
12
12
  var _hoisted_3 = {
13
13
  key: 0,
14
14
  class: "grid grid-cols-3 gap-1 p-2"
@@ -19,7 +19,6 @@ var _hoisted_5 = {
19
19
  class: "grid grid-cols-3 gap-1 p-2"
20
20
  };
21
21
  var _hoisted_6 = ["disabled", "onClick"];
22
- var navButtonClass = "p-1 rounded-full text-gray-500 hover:text-rui-primary hover:bg-gray-100 dark:text-gray-400 dark:hover:bg-gray-600 dark:hover:text-rui-primary";
23
22
  var RuiCalendarMenu_vue_vue_type_script_setup_true_lang_default = /*@__PURE__*/ defineComponent({
24
23
  name: "RuiCalendarMenu",
25
24
  inheritAttrs: false,
@@ -42,14 +41,14 @@ var RuiCalendarMenu_vue_vue_type_script_setup_true_lang_default = /*@__PURE__*/
42
41
  const months = getShortMonthNames();
43
42
  const calendarState = inject(CalendarStateSymbol);
44
43
  const cellButton = tv({
45
- base: "h-9 w-full flex items-center justify-center text-sm font-medium rounded-md transition-colors duration-150 ease-in-out border-none outline-none cursor-pointer focus:ring-2 focus:ring-rui-primary focus:ring-opacity-50",
44
+ base: "h-9 w-full flex items-center justify-center text-sm font-medium rounded-rui-control transition-colors duration-150 ease-in-out border-none outline-hidden cursor-pointer focus-visible:focus-ring",
46
45
  variants: {
47
- selected: { true: "bg-rui-primary text-white hover:bg-rui-primary-darker active:bg-rui-primary-darker dark:bg-rui-primary dark:text-white dark:hover:bg-rui-primary-darker" },
46
+ selected: { true: "bg-rui-primary-fill text-rui-primary-foreground hover:bg-rui-primary-darker active:bg-rui-primary-darker" },
48
47
  inRange: {
49
- true: "text-gray-700 bg-transparent hover:bg-gray-100 active:bg-gray-200 dark:text-gray-300 dark:hover:bg-gray-700 dark:active:bg-gray-600",
50
- false: "opacity-50 cursor-not-allowed bg-transparent hover:bg-transparent active:bg-transparent dark:hover:bg-transparent dark:active:bg-transparent pointer-events-none text-gray-400 dark:text-gray-600"
48
+ true: "text-rui-text bg-transparent hover:bg-rui-hover active:bg-rui-pressed",
49
+ false: "cursor-not-allowed bg-transparent pointer-events-none text-rui-text-disabled"
51
50
  },
52
- selectedOutOfRange: { true: "bg-gray-300 text-gray-500 dark:bg-gray-600 dark:text-gray-400" }
51
+ selectedOutOfRange: { true: "bg-rui-surface-muted text-rui-text-disabled" }
53
52
  }
54
53
  });
55
54
  const yearRange = ref([]);
@@ -190,34 +189,31 @@ var RuiCalendarMenu_vue_vue_type_script_setup_true_lang_default = /*@__PURE__*/
190
189
  default: withCtx(() => [createElementVNode("div", _hoisted_1, [createElementVNode("div", _hoisted_2, [
191
190
  createVNode(RuiButton_default, {
192
191
  type: "button",
193
- class: normalizeClass(navButtonClass),
194
192
  icon: "",
193
+ size: "sm",
194
+ "aria-label": "Previous",
195
195
  disabled: !unref(get)(canGoToPrev.value),
196
196
  variant: "text",
197
197
  onClick: _cache[0] || (_cache[0] = withModifiers(($event) => handlePrev(), ["stop"]))
198
198
  }, {
199
- default: withCtx(() => [createVNode(RuiIcon_default, {
200
- name: "lu-chevron-left",
201
- size: "20"
202
- })]),
199
+ default: withCtx(() => [createVNode(RuiIcon_default, { name: "lu-chevron-left" })]),
203
200
  _: 1
204
201
  }, 8, ["disabled"]),
205
- createElementVNode("div", {
206
- class: "flex-1 text-center cursor-pointer",
202
+ createElementVNode("button", {
203
+ type: "button",
204
+ class: "flex-1 rounded-rui-control px-2 py-1 text-center transition-colors hover:bg-rui-hover outline-hidden focus-visible:focus-ring",
207
205
  onClick: _cache[1] || (_cache[1] = withModifiers(($event) => toggleSelection(), ["stop"]))
208
206
  }, toDisplayString(unref(get)(title.value)), 1),
209
207
  createVNode(RuiButton_default, {
210
208
  type: "button",
211
- class: normalizeClass(navButtonClass),
212
209
  icon: "",
210
+ size: "sm",
211
+ "aria-label": "Next",
213
212
  disabled: !unref(get)(canGoToNext.value),
214
213
  variant: "text",
215
214
  onClick: _cache[2] || (_cache[2] = withModifiers(($event) => handleNext(), ["stop"]))
216
215
  }, {
217
- default: withCtx(() => [createVNode(RuiIcon_default, {
218
- name: "lu-chevron-right",
219
- size: "20"
220
- })]),
216
+ default: withCtx(() => [createVNode(RuiIcon_default, { name: "lu-chevron-right" })]),
221
217
  _: 1
222
218
  }, 8, ["disabled"])
223
219
  ]), viewMode.value === "months" ? (openBlock(), createElementBlock("div", _hoisted_3, [(openBlock(true), createElementBlock(Fragment, null, renderList(unref(months), (month, index) => {