@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,18 +1,15 @@
1
- import RuiIcon_default from "../icons/RuiIcon.js";
2
- import RuiButton_default from "../buttons/button/RuiButton.js";
3
1
  import RuiTextField_default from "../forms/text-field/RuiTextField.js";
4
- import { Fragment, createBlock, createElementBlock, createElementVNode, createVNode, defineComponent, mergeProps, openBlock, reactive, ref, renderList, toDisplayString, unref, useModel, watch, withCtx } from "vue";
2
+ import RuiTab_default from "../tabs/tab/RuiTab.js";
3
+ import RuiTabs_default from "../tabs/tabs/RuiTabs.js";
4
+ import { Fragment, createBlock, createElementBlock, createElementVNode, createTextVNode, createVNode, defineComponent, mergeProps, openBlock, reactive, ref, renderList, unref, useModel, watch, withCtx } from "vue";
5
5
  import { useDebounceFn } from "@vueuse/core";
6
6
  import { clamp, get as get$1, set as set$1 } from "@vueuse/shared";
7
7
  import tinycolor from "tinycolor2";
8
8
  //#region src/components/color-picker/RuiColorInput.vue?vue&type=script&setup=true&lang.ts
9
- var _hoisted_1 = { class: "flex flex-col items-center gap-1 w-[16rem]" };
10
- var _hoisted_2 = { class: "w-full" };
11
- var _hoisted_3 = {
9
+ var _hoisted_1 = {
12
10
  key: 1,
13
- class: "flex flex-1 gap-1"
11
+ class: "flex gap-1"
14
12
  };
15
- var _hoisted_4 = { class: "uppercase text-rui-text-secondary text-sm" };
16
13
  var MAX_RGB = 255;
17
14
  var DEFAULT_HEX = "000000";
18
15
  var RuiColorInput_vue_vue_type_script_setup_true_lang_default = /*@__PURE__*/ defineComponent({
@@ -31,6 +28,11 @@ var RuiColorInput_vue_vue_type_script_setup_true_lang_default = /*@__PURE__*/ de
31
28
  4,
32
29
  6
33
30
  ];
31
+ const RGB_CHANNELS = [
32
+ "Red",
33
+ "Green",
34
+ "Blue"
35
+ ];
34
36
  const inputType = ref("hex");
35
37
  const state = reactive({
36
38
  color: get$1(modelValue),
@@ -68,8 +70,8 @@ var RuiColorInput_vue_vue_type_script_setup_true_lang_default = /*@__PURE__*/ de
68
70
  } else if (key !== void 0) applyRgbValue(value, key);
69
71
  set$1(modelValue, state.color);
70
72
  }, 300);
71
- function onInputTypeChange() {
72
- set$1(inputType, get$1(inputType) === "rgb" ? "hex" : "rgb");
73
+ function onInputTypeChange(value) {
74
+ if (value === "hex" || value === "rgb") set$1(inputType, value);
73
75
  }
74
76
  watch(() => {
75
77
  const color = get$1(modelValue);
@@ -83,46 +85,55 @@ var RuiColorInput_vue_vue_type_script_setup_true_lang_default = /*@__PURE__*/ de
83
85
  return (_ctx, _cache) => {
84
86
  return openBlock(), createElementBlock("div", mergeProps({
85
87
  "data-id": "color-input",
86
- class: "flex justify-center gap-2"
87
- }, _ctx.$attrs), [createElementVNode("div", _hoisted_1, [createElementVNode("div", _hoisted_2, [unref(inputType) === "hex" ? (openBlock(), createBlock(RuiTextField_default, {
88
+ class: "flex flex-col gap-2 w-full"
89
+ }, _ctx.$attrs), [createVNode(RuiTabs_default, {
90
+ "model-value": unref(inputType),
91
+ variant: "segmented",
92
+ grow: "",
93
+ "data-id": "color-format",
94
+ "onUpdate:modelValue": _cache[0] || (_cache[0] = ($event) => onInputTypeChange($event))
95
+ }, {
96
+ default: withCtx(() => [createVNode(RuiTab_default, { value: "hex" }, {
97
+ default: withCtx(() => [..._cache[4] || (_cache[4] = [createTextVNode(" Hex ", -1)])]),
98
+ _: 1
99
+ }), createVNode(RuiTab_default, { value: "rgb" }, {
100
+ default: withCtx(() => [..._cache[5] || (_cache[5] = [createTextVNode(" RGB ", -1)])]),
101
+ _: 1
102
+ })]),
103
+ _: 1
104
+ }, 8, ["model-value"]), unref(inputType) === "hex" ? (openBlock(), createBlock(RuiTextField_default, {
88
105
  key: 0,
89
106
  modelValue: unref(state).hex,
90
- "onUpdate:modelValue": [_cache[0] || (_cache[0] = ($event) => unref(state).hex = $event), _cache[1] || (_cache[1] = ($event) => unref(onInputChange)(unref(inputType), $event))],
91
- variant: "outlined",
92
- class: "flex-1 w-full [&_input]:uppercase",
107
+ "onUpdate:modelValue": [_cache[1] || (_cache[1] = ($event) => unref(state).hex = $event), _cache[2] || (_cache[2] = ($event) => unref(onInputChange)(unref(inputType), $event))],
108
+ class: "w-full [&_input]:uppercase",
93
109
  maxlength: "6",
94
110
  color: "primary",
111
+ "aria-label": "Hex color",
95
112
  dense: "",
96
113
  "hide-details": "",
97
- onBlur: _cache[2] || (_cache[2] = ($event) => unref(onBlurChange)(unref(inputType), $event))
114
+ onBlur: _cache[3] || (_cache[3] = ($event) => unref(onBlurChange)(unref(inputType), $event))
98
115
  }, {
99
- prepend: withCtx(() => [..._cache[4] || (_cache[4] = [createElementVNode("span", { class: "text-rui-text" }, " # ", -1)])]),
116
+ prepend: withCtx(() => [..._cache[6] || (_cache[6] = [createElementVNode("span", { class: "text-rui-text-secondary" }, "#", -1)])]),
100
117
  _: 1
101
- }, 8, ["modelValue"])) : (openBlock(), createElementBlock("div", _hoisted_3, [(openBlock(true), createElementBlock(Fragment, null, renderList(unref(state).rgb, (v, i) => {
118
+ }, 8, ["modelValue"])) : (openBlock(), createElementBlock("div", _hoisted_1, [(openBlock(true), createElementBlock(Fragment, null, renderList(unref(state).rgb, (v, i) => {
102
119
  return openBlock(), createBlock(RuiTextField_default, {
103
120
  key: i,
104
121
  "model-value": v.toString(),
105
- variant: "outlined",
106
122
  class: "[&_input]:text-center w-full",
107
123
  maxlength: "3",
108
124
  color: "primary",
125
+ "aria-label": RGB_CHANNELS[i],
109
126
  dense: "",
110
127
  "hide-details": "",
111
128
  "onUpdate:modelValue": ($event) => unref(onInputChange)(unref(inputType), $event, i),
112
129
  onBlur: ($event) => unref(onBlurChange)(unref(inputType), $event, i)
113
130
  }, null, 8, [
114
131
  "model-value",
132
+ "aria-label",
115
133
  "onUpdate:modelValue",
116
134
  "onBlur"
117
135
  ]);
118
- }), 128))]))]), createElementVNode("div", _hoisted_4, toDisplayString(unref(inputType)), 1)]), createVNode(RuiButton_default, {
119
- class: "h-10",
120
- variant: "text",
121
- onClick: _cache[3] || (_cache[3] = ($event) => onInputTypeChange())
122
- }, {
123
- default: withCtx(() => [createVNode(RuiIcon_default, { name: "lu-chevrons-up-down" })]),
124
- _: 1
125
- })], 16);
136
+ }), 128))]))], 16);
126
137
  };
127
138
  }
128
139
  });
@@ -1 +1 @@
1
- {"version":3,"file":"RuiColorInput.vue_vue_type_script_setup_true_lang.js","names":["$attrs"],"sources":["../../../src/components/color-picker/RuiColorInput.vue"],"sourcesContent":["<script lang=\"ts\" setup>\nimport type { Color, ColorFormat } from './utils';\nimport { clamp } from '@vueuse/shared';\nimport tinycolor from 'tinycolor2';\nimport RuiButton from '@/components/buttons/button/RuiButton.vue';\nimport RuiTextField from '@/components/forms/text-field/RuiTextField.vue';\nimport RuiIcon from '@/components/icons/RuiIcon.vue';\n\ndefineOptions({\n name: 'RuiColorInput',\n inheritAttrs: false,\n});\n\nconst modelValue = defineModel<Color>({ required: true });\n\nconst MAX_RGB = 255;\nconst VALID_HEX_LENGTHS = [3, 4, 6];\nconst DEFAULT_HEX = '000000';\n\nconst inputType = ref<ColorFormat>('hex');\nconst state = reactive({\n color: get(modelValue),\n hex: get(modelValue).hex,\n rgb: get(modelValue).rgb,\n});\n\nfunction applyRgbValue(value: string, key: number): void {\n if (!state.rgb || !state.color)\n return;\n\n const clamped = clamp(Number(value), 0, MAX_RGB);\n state.rgb[key] = clamped;\n const [r, g, b] = state.rgb;\n state.color.hex = tinycolor({ r, g, b }).toHex();\n}\n\nconst onBlurChange = useDebounceFn((format: ColorFormat, event: Event, key?: number) => {\n if (!state.color)\n return;\n\n const target = event.target;\n if (!(target instanceof HTMLInputElement))\n return;\n\n const value = target.value;\n if (format === 'hex') {\n const hex = value.replace('#', '');\n if (tinycolor(hex).isValid() && VALID_HEX_LENGTHS.includes(hex.length))\n state.color.hex = hex;\n else state.color.hex = DEFAULT_HEX;\n }\n else if (key !== undefined) {\n applyRgbValue(value, key);\n }\n\n set(modelValue, state.color);\n}, 100);\n\nconst onInputChange = useDebounceFn((format: ColorFormat, value: string, key?: number) => {\n if (!value)\n return;\n\n if (format === 'hex') {\n const hex = value.replace('#', '');\n if (tinycolor(hex).isValid() && state.color && hex.length === 6)\n state.color.hex = hex;\n }\n else if (key !== undefined) {\n applyRgbValue(value, key);\n }\n\n set(modelValue, state.color);\n}, 300);\n\nfunction onInputTypeChange(): void {\n set(inputType, get(inputType) === 'rgb' ? 'hex' : 'rgb');\n}\n\nwatch(\n () => {\n const color = get(modelValue);\n return [color.hex, ...color.rgb] as const;\n },\n () => {\n const color = get(modelValue);\n state.color = color;\n state.hex = color.hex;\n state.rgb = color.rgb;\n },\n);\n</script>\n\n<template>\n <div\n data-id=\"color-input\"\n class=\"flex justify-center gap-2\"\n v-bind=\"$attrs\"\n >\n <div class=\"flex flex-col items-center gap-1 w-[16rem]\">\n <div class=\"w-full\">\n <RuiTextField\n v-if=\"inputType === 'hex'\"\n v-model=\"state.hex\"\n variant=\"outlined\"\n class=\"flex-1 w-full [&_input]:uppercase\"\n maxlength=\"6\"\n color=\"primary\"\n dense\n hide-details\n @update:model-value=\"onInputChange(inputType, $event)\"\n @blur=\"onBlurChange(inputType, $event)\"\n >\n <template #prepend>\n <span class=\"text-rui-text\"> # </span>\n </template>\n </RuiTextField>\n <div\n v-else\n class=\"flex flex-1 gap-1\"\n >\n <RuiTextField\n v-for=\"(v, i) in state.rgb\"\n :key=\"i\"\n :model-value=\"v.toString()\"\n variant=\"outlined\"\n class=\"[&_input]:text-center w-full\"\n maxlength=\"3\"\n color=\"primary\"\n dense\n hide-details\n @update:model-value=\"onInputChange(inputType, $event, i)\"\n @blur=\"onBlurChange(inputType, $event, i)\"\n />\n </div>\n </div>\n\n <div class=\"uppercase text-rui-text-secondary text-sm\">\n {{ inputType }}\n </div>\n </div>\n <RuiButton\n class=\"h-10\"\n variant=\"text\"\n @click=\"onInputTypeChange()\"\n >\n <RuiIcon name=\"lu-chevrons-up-down\" />\n </RuiButton>\n </div>\n</template>\n"],"mappings":"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"}
1
+ {"version":3,"file":"RuiColorInput.vue_vue_type_script_setup_true_lang.js","names":["$attrs"],"sources":["../../../src/components/color-picker/RuiColorInput.vue"],"sourcesContent":["<script lang=\"ts\" setup>\nimport type { Color, ColorFormat } from './utils';\nimport { clamp } from '@vueuse/shared';\nimport tinycolor from 'tinycolor2';\nimport RuiTextField from '@/components/forms/text-field/RuiTextField.vue';\nimport RuiTab from '@/components/tabs/tab/RuiTab.vue';\nimport RuiTabs from '@/components/tabs/tabs/RuiTabs.vue';\n\ndefineOptions({\n name: 'RuiColorInput',\n inheritAttrs: false,\n});\n\nconst modelValue = defineModel<Color>({ required: true });\n\nconst MAX_RGB = 255;\nconst VALID_HEX_LENGTHS = [3, 4, 6];\nconst DEFAULT_HEX = '000000';\nconst RGB_CHANNELS = ['Red', 'Green', 'Blue'];\n\nconst inputType = ref<ColorFormat>('hex');\nconst state = reactive({\n color: get(modelValue),\n hex: get(modelValue).hex,\n rgb: get(modelValue).rgb,\n});\n\nfunction applyRgbValue(value: string, key: number): void {\n if (!state.rgb || !state.color)\n return;\n\n const clamped = clamp(Number(value), 0, MAX_RGB);\n state.rgb[key] = clamped;\n const [r, g, b] = state.rgb;\n state.color.hex = tinycolor({ r, g, b }).toHex();\n}\n\nconst onBlurChange = useDebounceFn((format: ColorFormat, event: Event, key?: number) => {\n if (!state.color)\n return;\n\n const target = event.target;\n if (!(target instanceof HTMLInputElement))\n return;\n\n const value = target.value;\n if (format === 'hex') {\n const hex = value.replace('#', '');\n if (tinycolor(hex).isValid() && VALID_HEX_LENGTHS.includes(hex.length))\n state.color.hex = hex;\n else state.color.hex = DEFAULT_HEX;\n }\n else if (key !== undefined) {\n applyRgbValue(value, key);\n }\n\n set(modelValue, state.color);\n}, 100);\n\nconst onInputChange = useDebounceFn((format: ColorFormat, value: string, key?: number) => {\n if (!value)\n return;\n\n if (format === 'hex') {\n const hex = value.replace('#', '');\n if (tinycolor(hex).isValid() && state.color && hex.length === 6)\n state.color.hex = hex;\n }\n else if (key !== undefined) {\n applyRgbValue(value, key);\n }\n\n set(modelValue, state.color);\n}, 300);\n\nfunction onInputTypeChange(value: string | number): void {\n if (value === 'hex' || value === 'rgb')\n set(inputType, value);\n}\n\nwatch(\n () => {\n const color = get(modelValue);\n return [color.hex, ...color.rgb] as const;\n },\n () => {\n const color = get(modelValue);\n state.color = color;\n state.hex = color.hex;\n state.rgb = color.rgb;\n },\n);\n</script>\n\n<template>\n <div\n data-id=\"color-input\"\n class=\"flex flex-col gap-2 w-full\"\n v-bind=\"$attrs\"\n >\n <!-- the format is a choice between two views of one value, which is what a segmented control is for -->\n <RuiTabs\n :model-value=\"inputType\"\n variant=\"segmented\"\n grow\n data-id=\"color-format\"\n @update:model-value=\"onInputTypeChange($event)\"\n >\n <RuiTab value=\"hex\">\n Hex\n </RuiTab>\n <RuiTab value=\"rgb\">\n RGB\n </RuiTab>\n </RuiTabs>\n <RuiTextField\n v-if=\"inputType === 'hex'\"\n v-model=\"state.hex\"\n class=\"w-full [&_input]:uppercase\"\n maxlength=\"6\"\n color=\"primary\"\n aria-label=\"Hex color\"\n dense\n hide-details\n @update:model-value=\"onInputChange(inputType, $event)\"\n @blur=\"onBlurChange(inputType, $event)\"\n >\n <template #prepend>\n <span class=\"text-rui-text-secondary\">#</span>\n </template>\n </RuiTextField>\n <div\n v-else\n class=\"flex gap-1\"\n >\n <RuiTextField\n v-for=\"(v, i) in state.rgb\"\n :key=\"i\"\n :model-value=\"v.toString()\"\n class=\"[&_input]:text-center w-full\"\n maxlength=\"3\"\n color=\"primary\"\n :aria-label=\"RGB_CHANNELS[i]\"\n dense\n hide-details\n @update:model-value=\"onInputChange(inputType, $event, i)\"\n @blur=\"onBlurChange(inputType, $event, i)\"\n />\n </div>\n </div>\n</template>\n"],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"RuiColorPicker.js","names":[],"sources":["../../../src/components/color-picker/RuiColorPicker.vue"],"sourcesContent":["<script lang=\"ts\" setup>\n// Inspired by https://github.com/aesoper101/vue3-colorpicker/\nimport RuiColorBoard from '@/components/color-picker/RuiColorBoard.vue';\nimport RuiColorDisplay from '@/components/color-picker/RuiColorDisplay.vue';\nimport RuiColorHue from '@/components/color-picker/RuiColorHue.vue';\nimport RuiColorInput from '@/components/color-picker/RuiColorInput.vue';\nimport { cn, tv } from '@/utils/tv';\nimport { Color } from './utils';\n\ndefineOptions({\n name: 'RuiColorPicker',\n inheritAttrs: false,\n});\n\nconst modelValue = defineModel<string>({ default: '' });\n\nconst state = reactive({\n color: new Color(get(modelValue)),\n});\n\nfunction onBoardChange({\n saturation,\n brightness,\n}: {\n saturation: number;\n brightness: number;\n}): void {\n state.color.saturation = saturation;\n state.color.brightness = brightness;\n}\n\nwhenever(\n modelValue,\n (value: string) => {\n if (state.color.hex !== value)\n state.color = new Color(value);\n },\n);\n\nwatch(\n () => state.color.hex,\n (hex: string) => {\n set(modelValue, hex);\n },\n { immediate: true },\n);\n\nconst rootStyle = tv({ base: 'relative select-none bg-initial' });\n</script>\n\n<template>\n <div\n role=\"application\"\n aria-label=\"Color picker\"\n data-id=\"color-picker\"\n :class=\"rootStyle({ class: cn($attrs.class) })\"\n v-bind=\"{ ...$attrs, class: undefined }\"\n >\n <RuiColorBoard\n :color=\"state.color\"\n @update:board=\"onBoardChange($event)\"\n />\n <div class=\"flex flex-col gap-5 p-4\">\n <div class=\"flex items-center gap-4\">\n <RuiColorDisplay :color=\"state.color.hexString\" />\n <RuiColorHue\n v-model=\"state.color.hue\"\n class=\"flex-1\"\n />\n </div>\n\n <RuiColorInput v-model=\"state.color\" />\n </div>\n </div>\n</template>\n"],"mappings":""}
1
+ {"version":3,"file":"RuiColorPicker.js","names":[],"sources":["../../../src/components/color-picker/RuiColorPicker.vue"],"sourcesContent":["<script lang=\"ts\" setup>\n// Inspired by https://github.com/aesoper101/vue3-colorpicker/\nimport RuiColorBoard from '@/components/color-picker/RuiColorBoard.vue';\nimport RuiColorDisplay from '@/components/color-picker/RuiColorDisplay.vue';\nimport RuiColorHue from '@/components/color-picker/RuiColorHue.vue';\nimport RuiColorInput from '@/components/color-picker/RuiColorInput.vue';\nimport { cn, tv } from '@/utils/tv';\nimport { Color } from './utils';\n\ndefineOptions({\n name: 'RuiColorPicker',\n inheritAttrs: false,\n});\n\nconst modelValue = defineModel<string>({ default: '' });\n\nconst state = reactive({\n color: new Color(get(modelValue)),\n});\n\nfunction onBoardChange({\n saturation,\n brightness,\n}: {\n saturation: number;\n brightness: number;\n}): void {\n state.color.saturation = saturation;\n state.color.brightness = brightness;\n}\n\nwhenever(\n modelValue,\n (value: string) => {\n if (state.color.hex !== value)\n state.color = new Color(value);\n },\n);\n\nwatch(\n () => state.color.hex,\n (hex: string) => {\n set(modelValue, hex);\n },\n { immediate: true },\n);\n\nconst rootStyle = tv({ base: 'relative select-none' });\n</script>\n\n<template>\n <div\n role=\"application\"\n aria-label=\"Color picker\"\n data-id=\"color-picker\"\n :class=\"rootStyle({ class: cn($attrs.class) })\"\n v-bind=\"{ ...$attrs, class: undefined }\"\n >\n <RuiColorBoard\n :color=\"state.color\"\n @update:board=\"onBoardChange($event)\"\n />\n <div class=\"flex flex-col gap-5 p-4\">\n <div class=\"flex items-center gap-4\">\n <RuiColorDisplay :color=\"state.color.hexString\" />\n <RuiColorHue\n v-model=\"state.color.hue\"\n class=\"flex-1\"\n />\n </div>\n\n <RuiColorInput v-model=\"state.color\" />\n </div>\n </div>\n</template>\n"],"mappings":""}
@@ -32,7 +32,7 @@ var RuiColorPicker_vue_vue_type_script_setup_true_lang_default = /*@__PURE__*/ d
32
32
  watch(() => state.color.hex, (hex) => {
33
33
  set$1(modelValue, hex);
34
34
  }, { immediate: true });
35
- const rootStyle = tv({ base: "relative select-none bg-initial" });
35
+ const rootStyle = tv({ base: "relative select-none" });
36
36
  return (_ctx, _cache) => {
37
37
  return openBlock(), createElementBlock("div", mergeProps({
38
38
  role: "application",
@@ -1 +1 @@
1
- {"version":3,"file":"RuiColorPicker.vue_vue_type_script_setup_true_lang.js","names":["$attrs"],"sources":["../../../src/components/color-picker/RuiColorPicker.vue"],"sourcesContent":["<script lang=\"ts\" setup>\n// Inspired by https://github.com/aesoper101/vue3-colorpicker/\nimport RuiColorBoard from '@/components/color-picker/RuiColorBoard.vue';\nimport RuiColorDisplay from '@/components/color-picker/RuiColorDisplay.vue';\nimport RuiColorHue from '@/components/color-picker/RuiColorHue.vue';\nimport RuiColorInput from '@/components/color-picker/RuiColorInput.vue';\nimport { cn, tv } from '@/utils/tv';\nimport { Color } from './utils';\n\ndefineOptions({\n name: 'RuiColorPicker',\n inheritAttrs: false,\n});\n\nconst modelValue = defineModel<string>({ default: '' });\n\nconst state = reactive({\n color: new Color(get(modelValue)),\n});\n\nfunction onBoardChange({\n saturation,\n brightness,\n}: {\n saturation: number;\n brightness: number;\n}): void {\n state.color.saturation = saturation;\n state.color.brightness = brightness;\n}\n\nwhenever(\n modelValue,\n (value: string) => {\n if (state.color.hex !== value)\n state.color = new Color(value);\n },\n);\n\nwatch(\n () => state.color.hex,\n (hex: string) => {\n set(modelValue, hex);\n },\n { immediate: true },\n);\n\nconst rootStyle = tv({ base: 'relative select-none bg-initial' });\n</script>\n\n<template>\n <div\n role=\"application\"\n aria-label=\"Color picker\"\n data-id=\"color-picker\"\n :class=\"rootStyle({ class: cn($attrs.class) })\"\n v-bind=\"{ ...$attrs, class: undefined }\"\n >\n <RuiColorBoard\n :color=\"state.color\"\n @update:board=\"onBoardChange($event)\"\n />\n <div class=\"flex flex-col gap-5 p-4\">\n <div class=\"flex items-center gap-4\">\n <RuiColorDisplay :color=\"state.color.hexString\" />\n <RuiColorHue\n v-model=\"state.color.hue\"\n class=\"flex-1\"\n />\n </div>\n\n <RuiColorInput v-model=\"state.color\" />\n </div>\n </div>\n</template>\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;EAcA,MAAM,aAAa,SAAmB,SAAA,YAAgB;EAEtD,MAAM,QAAQ,SAAS,EACrB,OAAO,IAAI,MAAM,MAAI,UAAU,CAAC,EAClC,CAAC;EAED,SAAS,cAAc,EACrB,YACA,cAIO;GACP,MAAM,MAAM,aAAa;GACzB,MAAM,MAAM,aAAa;EAC3B;EAEA,SACE,aACC,UAAkB;GACjB,IAAI,MAAM,MAAM,QAAQ,OACtB,MAAM,QAAQ,IAAI,MAAM,KAAK;EACjC,CACF;EAEA,YACQ,MAAM,MAAM,MACjB,QAAgB;GACf,MAAI,YAAY,GAAG;EACrB,GACA,EAAE,WAAW,KAAK,CACpB;EAEA,MAAM,YAAY,GAAG,EAAE,MAAM,kCAAkC,CAAC;;GAI9D,OAAA,UAAA,GAAA,mBAsBM,OAtBN,WAsBM;IArBJ,MAAK;IACL,cAAW;IACX,WAAQ;IACP,OAAO,MAAA,SAAA,CAAS,CAAA,EAAA,OAAU,MAAA,EAAA,CAAE,CAACA,KAAAA,OAAO,KAAK,EAAA,CAAA;GAC7BA,GAAAA;IAAAA,GAAAA,KAAAA;IAAM,OAAS,KAAA;GAAS,CAAA,GAAA,CAErC,YAGE,uBAAA;IAFC,OAAO,MAAA,KAAA,CAAK,CAAC;IACb,kBAAY,OAAA,OAAA,OAAA,MAAA,WAAE,cAAc,MAAM;GAErC,GAAA,MAAA,GAAA,CAAA,OAAA,CAAA,GAAA,mBAUM,OAVN,YAUM,CATJ,mBAMM,OANN,YAMM,CALJ,YAAkD,yBAAA,EAAhC,OAAO,MAAA,KAAA,CAAK,CAAC,MAAM,UAAA,GAAA,MAAA,GAAA,CAAA,OAAA,CAAA,GACrC,YAGE,qBAAA;IAFS,YAAA,MAAA,KAAA,CAAK,CAAC,MAAM;IAAZ,uBAAA,OAAA,OAAA,OAAA,MAAA,WAAA,MAAA,KAAA,CAAK,CAAC,MAAM,MAAG;IACxB,OAAM;GAIV,GAAA,MAAA,GAAA,CAAA,YAAA,CAAA,CAAA,CAAA,GAAA,YAAuC,uBAAA;IAAf,YAAA,MAAA,KAAA,CAAK,CAAC;IAAN,uBAAA,OAAA,OAAA,OAAA,MAAA,WAAA,MAAA,KAAA,CAAK,CAAC,QAAK"}
1
+ {"version":3,"file":"RuiColorPicker.vue_vue_type_script_setup_true_lang.js","names":["$attrs"],"sources":["../../../src/components/color-picker/RuiColorPicker.vue"],"sourcesContent":["<script lang=\"ts\" setup>\n// Inspired by https://github.com/aesoper101/vue3-colorpicker/\nimport RuiColorBoard from '@/components/color-picker/RuiColorBoard.vue';\nimport RuiColorDisplay from '@/components/color-picker/RuiColorDisplay.vue';\nimport RuiColorHue from '@/components/color-picker/RuiColorHue.vue';\nimport RuiColorInput from '@/components/color-picker/RuiColorInput.vue';\nimport { cn, tv } from '@/utils/tv';\nimport { Color } from './utils';\n\ndefineOptions({\n name: 'RuiColorPicker',\n inheritAttrs: false,\n});\n\nconst modelValue = defineModel<string>({ default: '' });\n\nconst state = reactive({\n color: new Color(get(modelValue)),\n});\n\nfunction onBoardChange({\n saturation,\n brightness,\n}: {\n saturation: number;\n brightness: number;\n}): void {\n state.color.saturation = saturation;\n state.color.brightness = brightness;\n}\n\nwhenever(\n modelValue,\n (value: string) => {\n if (state.color.hex !== value)\n state.color = new Color(value);\n },\n);\n\nwatch(\n () => state.color.hex,\n (hex: string) => {\n set(modelValue, hex);\n },\n { immediate: true },\n);\n\nconst rootStyle = tv({ base: 'relative select-none' });\n</script>\n\n<template>\n <div\n role=\"application\"\n aria-label=\"Color picker\"\n data-id=\"color-picker\"\n :class=\"rootStyle({ class: cn($attrs.class) })\"\n v-bind=\"{ ...$attrs, class: undefined }\"\n >\n <RuiColorBoard\n :color=\"state.color\"\n @update:board=\"onBoardChange($event)\"\n />\n <div class=\"flex flex-col gap-5 p-4\">\n <div class=\"flex items-center gap-4\">\n <RuiColorDisplay :color=\"state.color.hexString\" />\n <RuiColorHue\n v-model=\"state.color.hue\"\n class=\"flex-1\"\n />\n </div>\n\n <RuiColorInput v-model=\"state.color\" />\n </div>\n </div>\n</template>\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;EAcA,MAAM,aAAa,SAAmB,SAAA,YAAgB;EAEtD,MAAM,QAAQ,SAAS,EACrB,OAAO,IAAI,MAAM,MAAI,UAAU,CAAC,EAClC,CAAC;EAED,SAAS,cAAc,EACrB,YACA,cAIO;GACP,MAAM,MAAM,aAAa;GACzB,MAAM,MAAM,aAAa;EAC3B;EAEA,SACE,aACC,UAAkB;GACjB,IAAI,MAAM,MAAM,QAAQ,OACtB,MAAM,QAAQ,IAAI,MAAM,KAAK;EACjC,CACF;EAEA,YACQ,MAAM,MAAM,MACjB,QAAgB;GACf,MAAI,YAAY,GAAG;EACrB,GACA,EAAE,WAAW,KAAK,CACpB;EAEA,MAAM,YAAY,GAAG,EAAE,MAAM,uBAAuB,CAAC;;GAInD,OAAA,UAAA,GAAA,mBAsBM,OAtBN,WAsBM;IArBJ,MAAK;IACL,cAAW;IACX,WAAQ;IACP,OAAO,MAAA,SAAA,CAAS,CAAA,EAAA,OAAU,MAAA,EAAA,CAAE,CAACA,KAAAA,OAAO,KAAK,EAAA,CAAA;GAC7BA,GAAAA;IAAAA,GAAAA,KAAAA;IAAM,OAAS,KAAA;GAAS,CAAA,GAAA,CAErC,YAGE,uBAAA;IAFC,OAAO,MAAA,KAAA,CAAK,CAAC;IACb,kBAAY,OAAA,OAAA,OAAA,MAAA,WAAE,cAAc,MAAM;GAErC,GAAA,MAAA,GAAA,CAAA,OAAA,CAAA,GAAA,mBAUM,OAVN,YAUM,CATJ,mBAMM,OANN,YAMM,CALJ,YAAkD,yBAAA,EAAhC,OAAO,MAAA,KAAA,CAAK,CAAC,MAAM,UAAA,GAAA,MAAA,GAAA,CAAA,OAAA,CAAA,GACrC,YAGE,qBAAA;IAFS,YAAA,MAAA,KAAA,CAAK,CAAC,MAAM;IAAZ,uBAAA,OAAA,OAAA,OAAA,MAAA,WAAA,MAAA,KAAA,CAAK,CAAC,MAAM,MAAG;IACxB,OAAM;GAIV,GAAA,MAAA,GAAA,CAAA,YAAA,CAAA,CAAA,CAAA,GAAA,YAAuC,uBAAA;IAAf,YAAA,MAAA,KAAA,CAAK,CAAC;IAAN,uBAAA,OAAA,OAAA,OAAA,MAAA,WAAA,MAAA,KAAA,CAAK,CAAC,QAAK"}
@@ -1 +1 @@
1
- {"version":3,"file":"RuiDateTimePicker.js","names":[],"sources":["../../../src/components/date-time-picker/RuiDateTimePicker.vue"],"sourcesContent":["<script lang=\"ts\" setup>\nimport type { ComponentPublicInstance } from 'vue';\nimport type { DateTimePickerAction, DateTimeSegmentType } from '@/components/date-time-picker/types';\nimport type { TimePickerSelection } from '@/components/time-picker/RuiTimePicker.vue';\nimport RuiButton from '@/components/buttons/button/RuiButton.vue';\nimport { dateTimePickerStyles, type DateTimePickerVariant } from '@/components/date-time-picker/date-time-picker-styles';\nimport RuiDateTimePickerMenu from '@/components/date-time-picker/RuiDateTimePickerMenu.vue';\nimport { useDateTimeSelection } from '@/components/date-time-picker/use-date-time-selection';\nimport { useInputHandler } from '@/components/date-time-picker/use-input-handler';\nimport { useKeyboardHandler } from '@/components/date-time-picker/use-keyboard-handler';\nimport RuiIcon from '@/components/icons/RuiIcon.vue';\nimport RuiMenu from '@/components/overlays/menu/RuiMenu.vue';\nimport { type FloatingOptions, Placement } from '@/composables/floating';\nimport { useRuiI8n } from '@/composables/use-rui-i18n';\nimport { RUI_I18N_KEYS } from '@/i18n/keys';\nimport { useFormTextDetail } from '@/utils/form-text-detail';\nimport { getNonRootAttrs, getRootAttrs } from '@/utils/helpers';\nimport { cn } from '@/utils/tv';\n\ntype DateFormat = 'year-first' | 'month-first' | 'day-first';\n\ntype DateTimeModelType = 'date' | 'epoch-ms' | 'epoch';\n\ntype ModelValueType<T extends DateTimeModelType> = T extends 'date'\n ? Date | undefined\n : T extends 'epoch-ms'\n ? number | undefined\n : T extends 'epoch'\n ? number | undefined\n : Date | number | undefined;\n\nexport interface RuiDateTimePickerProps {\n minDate?: Date | number;\n maxDate?: Date | number | 'now';\n format?: DateFormat;\n type?: DateTimeModelType;\n accuracy?: 'minute' | 'second' | 'millisecond';\n disabled?: boolean;\n allowEmpty?: boolean;\n readonly?: boolean;\n dense?: boolean;\n label?: string;\n variant?: DateTimePickerVariant;\n hint?: string;\n errorMessages?: string | string[];\n successMessages?: string | string[];\n hideDetails?: boolean;\n required?: boolean;\n /**\n * Renders the timezone selector in the menu. Off by default: the value is\n * emitted as a date or an epoch, so the picked timezone does not survive a\n * round trip and most consumers work in local time.\n */\n showTimezone?: boolean;\n /**\n * Actions rendered in the menu footer. `clear` is only rendered when the\n * picker is `allowEmpty`. Pass an empty array to drop the footer entirely.\n */\n actions?: DateTimePickerAction[];\n /**\n * Focuses the field once it is mounted. The native attribute is ignored for\n * an input inserted into an already loaded document, which is the usual case\n * for a picker revealed by an editor or a dialog.\n */\n autofocus?: boolean;\n /**\n * Accepts an entry that stops short of the full format, filling the segments\n * it never reached from one end of the day: `start` gives a bare date\n * 00:00:00.000 and `end` gives it 23:59:59.999. Meant for a range, where the\n * two bounds want opposite ends. Left unset, an entry missing its time is not\n * a value and nothing is emitted.\n *\n * The fill runs when the user is done with the field - leaving it, pressing\n * enter, or closing the calendar - and is written back into the segments, so\n * what it decided on is on screen.\n *\n * Spelled out rather than written as `PartialTimeMode`: a consumer that hands\n * this whole interface to its own `defineProps` needs every member resolvable\n * by the SFC compiler, which does not follow the type into the package.\n */\n partialTime?: 'start' | 'end';\n}\n\ndefineOptions({\n name: 'RuiDateTimePicker',\n inheritAttrs: false,\n});\n\nconst modelValue = defineModel<ModelValueType<DateTimeModelType>>({ required: true });\nconst menuOpen = defineModel<boolean>('menuOpen', { default: false });\n\nconst {\n disabled = false,\n readonly = false,\n allowEmpty = false,\n dense = false,\n type = 'epoch-ms',\n hideDetails = false,\n label,\n variant = 'default',\n hint,\n maxDate,\n minDate,\n format = 'day-first',\n accuracy = 'minute',\n errorMessages = [],\n successMessages = [],\n required = false,\n showTimezone = false,\n actions = ['now'],\n autofocus = false,\n partialTime,\n} = defineProps<RuiDateTimePickerProps>();\n\ndefineSlots<{\n 'menu-content': () => any;\n}>();\n\nconst MENU_OPTIONS: FloatingOptions = { placement: Placement.bottomStart };\n\nconst baseFormats: Record<DateFormat, string> = {\n 'day-first': 'DD/MM/YYYY HH:mm',\n 'month-first': 'MM/DD/YYYY HH:mm',\n 'year-first': 'YYYY/MM/DD HH:mm',\n};\n\nconst isOpen = ref<boolean>(false);\nconst isHovered = ref<boolean>(false);\nconst cursorPosition = ref<number>(0);\nconst currentValue = ref<number>();\n\nconst { t } = useRuiI8n();\n\nconst keys = RUI_I18N_KEYS.dateTimePicker;\n\nconst fieldLabel = computed<string>(() => label ?? t(keys.label, 'Pick a date'));\nconst clearLabel = computed<string>(() => t(keys.clearValue, 'Clear the date'));\nconst toggleLabel = computed<string>(() => (get(isOpen)\n ? t(keys.closeCalendar, 'Close the calendar')\n : t(keys.openCalendar, 'Open the calendar')));\n\nconst textInput = useTemplateRef<HTMLInputElement>('textInput');\nconst activator = useTemplateRef<HTMLDivElement>('activator');\nconst menuWrapperRef = useTemplateRef<ComponentPublicInstance>('menuWrapperRef');\nconst calendarMenuOpen = ref<boolean>(false);\n\nconst { focused: activatorFocusedWithin } = useFocusWithin(activator);\nconst { focused: menuWrapperFocusedWithin } = useFocusWithin(menuWrapperRef);\nconst { focused: searchInputFocused } = useFocus(textInput);\n\nconst anyFocused = computed<boolean>(() => get(activatorFocusedWithin) || get(menuWrapperFocusedWithin));\n\nconst dateFormat = computed<string>(() => {\n const fmt = baseFormats[format];\n if (accuracy === 'second') {\n return fmt.replace('HH:mm', 'HH:mm:ss');\n }\n else if (accuracy === 'millisecond') {\n return fmt.replace('HH:mm', 'HH:mm:ss.SSS');\n }\n return fmt;\n});\n\nconst {\n clear: clearSelection,\n commitPartialTime,\n getDateTime,\n internalErrorMessages,\n maxAllowedDate,\n minAllowedDate,\n segmentData,\n selectedDate,\n modelDay,\n modelHour,\n modelMillisecond,\n modelMinute,\n modelMonth,\n modelSecond,\n selectedTime,\n modelTimezone,\n modelYear,\n setNow,\n setToday,\n valueSet,\n} = useDateTimeSelection({\n accuracy,\n allowEmpty,\n dateFormat,\n maxDate,\n minDate,\n modelValue,\n partialTime,\n type,\n});\n\nconst { setValue, getCurrent } = useInputHandler(segmentData, currentValue);\n\nconst {\n clear: clearSegment,\n getCurrentSegment,\n handleBlur,\n handleClick,\n handleFocus,\n handleInput,\n handleInputSelection,\n handleKeyDown,\n handleMouseDown,\n handlePaste,\n pasteRejected,\n selectFirstSegment,\n setSegment,\n} = useKeyboardHandler({\n accuracy,\n currentValue,\n cursorPosition,\n dateFormat,\n disabled,\n getCurrent,\n getDateTime,\n readonly,\n setValue,\n textInput,\n timezone: modelTimezone,\n});\n\nconst { hasError, hasSuccess } = useFormTextDetail(\n () => errorMessages,\n () => successMessages,\n);\n\nconst isOutlined = computed<boolean>(() => variant === 'outlined');\n\n/** True once any segment holds a digit, even a partially typed date. */\nconst anySegmentSet = computed<boolean>(() => [\n modelYear,\n modelMonth,\n modelDay,\n modelHour,\n modelMinute,\n modelSecond,\n modelMillisecond,\n].some(segment => isDefined(segment)));\n\n/**\n * The field's text.\n *\n * An untouched field shows its format through the placeholder rather than\n * holding the tokens as its value, where a screen reader reads them as content\n * and select-all copies them. The tokens stay while the field is focused: that\n * is when the segment machinery highlights them, and collapsing the value\n * mid-edit would blank the field under the cursor. The guard is \"no segment\n * set\" rather than `valueSet`, so blurring a half-typed date keeps what was\n * entered on screen.\n */\nconst formattedDisplay = computed<string>(() => {\n if (!get(anySegmentSet) && !get(searchInputFocused)) {\n return '';\n }\n\n let result = get(dateFormat);\n\n const replacements = [\n { pattern: 'YYYY', value: getDisplayValue(modelYear, 4) },\n { pattern: 'MM', value: getDisplayValue(modelMonth, 2) },\n { pattern: 'DD', value: getDisplayValue(modelDay, 2) },\n { pattern: 'HH', value: getDisplayValue(modelHour, 2) },\n { pattern: 'mm', value: getDisplayValue(modelMinute, 2) },\n { pattern: 'ss', value: getDisplayValue(modelSecond, 2) },\n { pattern: 'SSS', value: getDisplayValue(modelMillisecond, 3) },\n ];\n\n for (const { pattern, value } of replacements) {\n if (value !== undefined) {\n result = result.replace(pattern, value);\n }\n }\n\n return result;\n});\n\n/**\n * An untouched field holds no value until focus expands the format tokens into\n * it. That patch overwrites the input's value, and writing a value drops any\n * selection with it, so the highlight `handleFocus` just set is gone by the\n * time the tokens are on screen and the caret ends up after them. Re-select\n * the first segment once the tokens have actually landed.\n */\nwatch(formattedDisplay, (value, previous) => {\n if (previous === '' && value !== '' && get(searchInputFocused))\n selectFirstSegment();\n}, { flush: 'post' });\n\nconst timeSelection = computed<TimePickerSelection>({\n get() {\n const type = getCurrentSegment()?.type;\n\n if (type === 'mm') {\n return 'minute';\n }\n else if (type === 'ss') {\n return 'second';\n }\n else if (type === 'SSS') {\n return 'millisecond';\n }\n return 'hour';\n },\n set(value: TimePickerSelection) {\n let segmentType: DateTimeSegmentType = 'HH';\n if (value === 'minute') {\n segmentType = 'mm';\n }\n else if (value === 'second') {\n segmentType = 'ss';\n }\n else if (value === 'millisecond') {\n segmentType = 'SSS';\n }\n\n setSegment(segmentType);\n },\n});\n\nconst float = computed<boolean>(() => (get(isOpen) || get(valueSet) || get(searchInputFocused)) && get(isOutlined));\n\nconst legendText = computed<string>(() => {\n if (!get(float))\n return '';\n const resolved = get(fieldLabel);\n return required ? `${resolved} ﹡` : resolved;\n});\n\nconst ui = computed<ReturnType<typeof dateTimePickerStyles>>(() => dateTimePickerStyles({\n filled: variant === 'filled',\n outlined: get(isOutlined),\n float: get(float),\n showLabel: !!get(legendText),\n opened: get(isOpen),\n hovered: get(isHovered),\n dense,\n disabled,\n readonly,\n hasError: get(hasError),\n hasSuccess: get(hasSuccess) && !get(hasError),\n}));\n\nconst pasteMessage = computed<string>(() => (get(pasteRejected)\n ? t(keys.pasteUnreadable, 'Could not read a date from the pasted text')\n : ''));\n\n/**\n * The paste message goes first: the details show one message, and it answers\n * what the user just did, which a standing validation error does not.\n */\nconst combinedErrorMessages = computed<string[]>(() => {\n const paste = get(pasteMessage) ? [get(pasteMessage)] : [];\n if (!errorMessages)\n return [...paste, ...get(internalErrorMessages)];\n\n const propErrors = Array.isArray(errorMessages) ? errorMessages : [errorMessages];\n return [...paste, ...propErrors, ...get(internalErrorMessages)];\n});\n\nfunction getDisplayValue(digit: Ref<number | undefined>, padding: number): string | undefined {\n return isDefined(digit) ? get(digit).toString().padStart(padding, '0') : undefined;\n}\n\nasync function setInputFocus(): Promise<void> {\n await nextTick(() => {\n set(searchInputFocused, true);\n });\n}\n\nfunction clear(segmentType?: string): void {\n if (!segmentType) {\n clearSelection();\n set(currentValue, undefined);\n return;\n }\n\n clearSegment(segmentType);\n}\n\n/**\n * An entry left incomplete is completed once the user is done with the field,\n * never while they are still filling it in: a half typed hour is not a segment\n * they left out. Leaving the field counts, unless the calendar is open, since\n * then the focus is only moving into it and the menu closing covers that.\n */\nfunction onBlur(): void {\n handleBlur();\n if (!get(isOpen))\n commitPartialTime();\n}\n\nwatch(isOpen, (open) => {\n if (!open && !get(searchInputFocused))\n commitPartialTime();\n});\n\n/**\n * Selects the clicked segment before opening the menu, so the selection is not\n * lost to the DOM changes that opening brings.\n */\nfunction handleInputClick(event: MouseEvent): void {\n handleClick(event);\n if (!get(isOpen)) {\n set(isOpen, true);\n }\n}\n\n/**\n * The menu is teleported to the body, so it never sits next to the field in\n * the tab sequence. Opening it from the keyboard therefore moves focus into\n * the calendar; opening it with the mouse leaves focus in the field, which is\n * what `disable-auto-focus` on the menu is there for.\n */\nconst focusCalendarOnOpen = ref<boolean>(false);\n\n/**\n * Asks for focus to move into the calendar. The menu is teleported and mounts\n * a frame later, so the watcher below waits for the wrapper to appear rather\n * than guessing at a number of ticks.\n */\nfunction focusCalendar(): void {\n set(focusCalendarOnOpen, true);\n}\n\nwatch(menuWrapperRef, (menu) => {\n if (!menu || !get(focusCalendarOnOpen))\n return;\n\n set(focusCalendarOnOpen, false);\n nextTick(() => {\n const el = menu.$el as HTMLElement | undefined;\n el?.querySelector<HTMLButtonElement>('[role=\"gridcell\"][tabindex=\"0\"]')?.focus({ preventScroll: true });\n });\n});\n\n/** Moves focus to the field. Exposed so a consumer can drive it from a ref. */\nfunction focus(): void {\n get(textInput)?.focus({ preventScroll: true });\n}\n\nfunction focusField(): void {\n nextTick(focus);\n}\n\nonMounted(() => {\n if (autofocus && !disabled)\n focusField();\n});\n\n/** Escape inside the calendar closes it and hands focus back to the field. */\nfunction closeFromMenu(): void {\n set(isOpen, false);\n focusField();\n}\n\n/**\n * The menu used to be mouse-only: the activator carried no key handlers, so\n * there was no way to reach the calendar from the keyboard. Alt+ArrowDown\n * opens it and Escape closes it, following the combobox convention, and the\n * append chevron is a real button for anyone who tabs to it instead.\n *\n * Enter and Escape are the other ways to be done with the field, and the keys\n * a consumer tends to close its editor on. Escape reaches that point only once\n * the calendar is already shut, and discards nothing, since the segments stay\n * on screen either way, so it commits what was entered rather than dropping it\n * when the field goes. Both write the value before the key carries on\n * bubbling, so it survives that close.\n */\nfunction onKeyDown(event: KeyboardEvent): void {\n if (disabled || readonly)\n return;\n\n if (event.altKey && event.key === 'ArrowDown') {\n event.preventDefault();\n set(isOpen, true);\n focusCalendar();\n return;\n }\n\n if (event.key === 'Escape' && get(isOpen)) {\n set(isOpen, false);\n return;\n }\n\n if (event.key === 'Enter' || event.key === 'Escape')\n commitPartialTime();\n\n handleKeyDown(event);\n}\n\nfunction arrowClicked(event: MouseEvent): void {\n if (get(isOpen)) {\n set(isOpen, false);\n event.stopPropagation();\n }\n}\n\nconst menuActions = computed<DateTimePickerAction[]>(\n () => actions.filter(action => action !== 'clear' || allowEmpty),\n);\n\nconst anyMenuOpen = computed<boolean>(() => get(isOpen) || get(calendarMenuOpen));\n\nwatch(anyMenuOpen, (value) => {\n set(menuOpen, value);\n});\n\ndefineExpose({\n focus,\n});\n</script>\n\n<template>\n <RuiMenu\n v-model=\"isOpen\"\n v-bind=\"getRootAttrs($attrs, [])\"\n :class=\"ui.wrapper({ class: cn($attrs.class) })\"\n :options=\"MENU_OPTIONS\"\n :dense=\"dense\"\n :hint=\"hint\"\n :disabled=\"disabled\"\n :success-messages=\"successMessages\"\n :error-messages=\"combinedErrorMessages\"\n :close-on-content-click=\"false\"\n :show-details=\"!hideDetails\"\n :persistent=\"calendarMenuOpen\"\n full-width\n disable-auto-focus\n >\n <template #activator=\"{ attrs, open }\">\n <div\n ref=\"activator\"\n :class=\"ui.activator()\"\n v-bind=\"{\n ...getNonRootAttrs($attrs, ['onClick', 'class']),\n ...(readonly ? {} : attrs),\n }\"\n data-id=\"activator\"\n :aria-invalid=\"hasError\"\n @mouseenter=\"isHovered = true\"\n @mouseleave=\"isHovered = false\"\n @click=\"setInputFocus()\"\n >\n <span\n v-if=\"isOutlined && (searchInputFocused || open || valueSet)\"\n data-id=\"label\"\n :class=\"[\n ui.label(),\n { 'pr-2': !valueSet && !open && isOutlined },\n ]\"\n >\n {{ fieldLabel }}\n <span\n v-if=\"required\"\n data-id=\"required-indicator\"\n :class=\"ui.required()\"\n >\n ﹡\n </span>\n </span>\n\n <span :class=\"ui.iconPrepend()\">\n <RuiIcon\n class=\"text-rui-text-secondary transition\"\n :size=\"dense ? 16 : 24\"\n name=\"lu-calendar-days\"\n />\n </span>\n\n <div :class=\"ui.value()\">\n <input\n ref=\"textInput\"\n :disabled=\"disabled\"\n :value=\"formattedDisplay\"\n class=\"bg-transparent outline-none flex-1 min-w-0\"\n type=\"text\"\n inputmode=\"numeric\"\n spellcheck=\"false\"\n autocomplete=\"off\"\n autocorrect=\"off\"\n autocapitalize=\"off\"\n :placeholder=\"dateFormat\"\n :readonly=\"readonly\"\n :aria-invalid=\"hasError\"\n :aria-label=\"fieldLabel\"\n :aria-required=\"required || undefined\"\n @mousedown=\"handleMouseDown($event)\"\n @focus=\"handleFocus()\"\n @blur=\"onBlur()\"\n @select=\"handleInputSelection($event)\"\n @click.stop=\"handleInputClick($event)\"\n @keydown=\"onKeyDown($event)\"\n @paste=\"handlePaste($event)\"\n @input=\"handleInput($event)\"\n />\n <!-- The details line is not a live region, so a rejected paste is announced from here -->\n <span\n class=\"sr-only\"\n aria-live=\"polite\"\n data-id=\"paste-status\"\n >\n {{ pasteMessage }}\n </span>\n </div>\n\n <RuiButton\n v-if=\"allowEmpty && valueSet && !disabled\"\n variant=\"text\"\n icon\n data-id=\"clear-button\"\n size=\"sm\"\n color=\"error\"\n :aria-label=\"clearLabel\"\n :class=\"[\n ui.clear(),\n anyFocused && '!visible',\n { 'mr-2': !dense },\n ]\"\n @click.stop.prevent=\"clear()\"\n >\n <RuiIcon\n name=\"lu-x\"\n size=\"18\"\n />\n </RuiButton>\n\n <!-- Out of the tab sequence, following the combobox pattern: the button only duplicates\n Alt+ArrowDown on the field, so leaving it in cost two stops to cross one date field\n and four to cross a from/to pair, for nothing a keyboard user could not already do.\n It stays a real button, so it keeps its label and its expanded state for anyone\n reaching it by any other means. -->\n <button\n v-if=\"!disabled && !readonly\"\n type=\"button\"\n tabindex=\"-1\"\n :class=\"ui.iconWrapper()\"\n data-id=\"append\"\n :aria-label=\"toggleLabel\"\n :aria-expanded=\"isOpen\"\n aria-haspopup=\"dialog\"\n @click=\"arrowClicked($event)\"\n >\n <RuiIcon\n :class=\"ui.icon()\"\n :size=\"dense ? 16 : 24\"\n name=\"lu-chevron-down\"\n />\n </button>\n <span\n v-else\n :class=\"ui.iconWrapper()\"\n data-id=\"append\"\n >\n <RuiIcon\n :class=\"ui.icon()\"\n :size=\"dense ? 16 : 24\"\n name=\"lu-chevron-down\"\n />\n </span>\n </div>\n <fieldset\n v-if=\"isOutlined\"\n :class=\"ui.fieldset()\"\n >\n <legend :class=\"ui.legend()\">\n {{ legendText }}\n </legend>\n </fieldset>\n </template>\n <template #default>\n <RuiDateTimePickerMenu\n ref=\"menuWrapperRef\"\n v-model:selected-date=\"selectedDate\"\n v-model:selected-time=\"selectedTime\"\n v-model:selected-hour=\"modelHour\"\n v-model:selected-minute=\"modelMinute\"\n v-model:selected-second=\"modelSecond\"\n v-model:selected-millisecond=\"modelMillisecond\"\n v-model:time-selection=\"timeSelection\"\n v-model:selected-timezone=\"modelTimezone\"\n v-model:calendar-menu-open=\"calendarMenuOpen\"\n :accuracy=\"accuracy\"\n :max-date=\"maxAllowedDate\"\n :min-date=\"minAllowedDate\"\n :show-timezone=\"showTimezone\"\n :actions=\"menuActions\"\n @keydown.escape=\"closeFromMenu()\"\n @set-now=\"setNow()\"\n @set-today=\"setToday()\"\n @clear=\"clear()\"\n >\n <slot name=\"menu-content\" />\n </RuiDateTimePickerMenu>\n </template>\n </RuiMenu>\n</template>\n"],"mappings":""}
1
+ {"version":3,"file":"RuiDateTimePicker.js","names":[],"sources":["../../../src/components/date-time-picker/RuiDateTimePicker.vue"],"sourcesContent":["<script lang=\"ts\" setup>\nimport type { ComponentPublicInstance } from 'vue';\nimport type { DateTimePickerAction, DateTimeSegmentType } from '@/components/date-time-picker/types';\nimport type { TimePickerSelection } from '@/components/time-picker/RuiTimePicker.vue';\nimport RuiButton from '@/components/buttons/button/RuiButton.vue';\nimport { dateTimePickerStyles } from '@/components/date-time-picker/date-time-picker-styles';\nimport RuiDateTimePickerMenu from '@/components/date-time-picker/RuiDateTimePickerMenu.vue';\nimport { useDateTimeSelection } from '@/components/date-time-picker/use-date-time-selection';\nimport { useInputHandler } from '@/components/date-time-picker/use-input-handler';\nimport { useKeyboardHandler } from '@/components/date-time-picker/use-keyboard-handler';\nimport RuiFieldLabel from '@/components/forms/field-label/RuiFieldLabel.vue';\nimport RuiIcon from '@/components/icons/RuiIcon.vue';\nimport { activatorHandlers } from '@/components/overlays/menu/activator-handlers';\nimport RuiMenu from '@/components/overlays/menu/RuiMenu.vue';\nimport { type LabelPlacement, useLabelPlacement } from '@/composables/defaults/field';\nimport { type FloatingOptions, Placement } from '@/composables/floating';\nimport { useRuiI8n } from '@/composables/use-rui-i18n';\nimport { RUI_I18N_KEYS } from '@/i18n/keys';\nimport { useFormTextDetail } from '@/utils/form-text-detail';\nimport { getNonRootAttrs, getRootAttrs } from '@/utils/helpers';\nimport { cn } from '@/utils/tv';\n\ntype DateFormat = 'year-first' | 'month-first' | 'day-first';\n\ntype DateTimeModelType = 'date' | 'epoch-ms' | 'epoch';\n\ntype ModelValueType<T extends DateTimeModelType> = T extends 'date'\n ? Date | undefined\n : T extends 'epoch-ms'\n ? number | undefined\n : T extends 'epoch'\n ? number | undefined\n : Date | number | undefined;\n\nexport interface RuiDateTimePickerProps {\n minDate?: Date | number;\n maxDate?: Date | number | 'now';\n format?: DateFormat;\n type?: DateTimeModelType;\n accuracy?: 'minute' | 'second' | 'millisecond';\n disabled?: boolean;\n allowEmpty?: boolean;\n readonly?: boolean;\n dense?: boolean;\n label?: string;\n /** Where the label shows; falls back to the nearest `RuiFieldDefaults`, then the app default, then `top`. */\n labelPlacement?: LabelPlacement;\n hint?: string;\n errorMessages?: string | string[];\n successMessages?: string | string[];\n hideDetails?: boolean;\n required?: boolean;\n /**\n * Renders the timezone selector in the menu. Off by default: the value is\n * emitted as a date or an epoch, so the picked timezone does not survive a\n * round trip and most consumers work in local time.\n */\n showTimezone?: boolean;\n /**\n * Actions rendered in the menu footer. `clear` is only rendered when the\n * picker is `allowEmpty`. Pass an empty array to drop the footer entirely.\n */\n actions?: DateTimePickerAction[];\n /**\n * Focuses the field once it is mounted. The native attribute is ignored for\n * an input inserted into an already loaded document, which is the usual case\n * for a picker revealed by an editor or a dialog.\n */\n autofocus?: boolean;\n /**\n * Accepts an entry that stops short of the full format, filling the segments\n * it never reached from one end of the day: `start` gives a bare date\n * 00:00:00.000 and `end` gives it 23:59:59.999. Meant for a range, where the\n * two bounds want opposite ends. Left unset, an entry missing its time is not\n * a value and nothing is emitted.\n *\n * The fill runs when the user is done with the field - leaving it, pressing\n * enter, or closing the calendar - and is written back into the segments, so\n * what it decided on is on screen.\n *\n * Spelled out rather than written as `PartialTimeMode`: a consumer that hands\n * this whole interface to its own `defineProps` needs every member resolvable\n * by the SFC compiler, which does not follow the type into the package.\n */\n partialTime?: 'start' | 'end';\n}\n\ndefineOptions({\n name: 'RuiDateTimePicker',\n inheritAttrs: false,\n});\n\nconst modelValue = defineModel<ModelValueType<DateTimeModelType>>({ required: true });\nconst menuOpen = defineModel<boolean>('menuOpen', { default: false });\n\nconst {\n disabled = false,\n readonly = false,\n allowEmpty = false,\n dense = false,\n type = 'epoch-ms',\n hideDetails = false,\n label,\n labelPlacement = undefined,\n hint,\n maxDate,\n minDate,\n format = 'day-first',\n accuracy = 'minute',\n errorMessages = [],\n successMessages = [],\n required = false,\n showTimezone = false,\n actions = ['now'],\n autofocus = false,\n partialTime,\n} = defineProps<RuiDateTimePickerProps>();\n\ndefineSlots<{\n 'menu-content': () => any;\n}>();\n\nconst MENU_OPTIONS: FloatingOptions = { placement: Placement.bottomStart };\n\nconst baseFormats: Record<DateFormat, string> = {\n 'day-first': 'DD/MM/YYYY HH:mm',\n 'month-first': 'MM/DD/YYYY HH:mm',\n 'year-first': 'YYYY/MM/DD HH:mm',\n};\n\nconst isOpen = ref<boolean>(false);\nconst isHovered = ref<boolean>(false);\nconst cursorPosition = ref<number>(0);\nconst currentValue = ref<number>();\n\nconst { t } = useRuiI8n();\n\nconst keys = RUI_I18N_KEYS.dateTimePicker;\n\nconst fieldLabel = computed<string>(() => label ?? t(keys.label, 'Pick a date'));\nconst inputId = useId();\nconst placement = useLabelPlacement(() => labelPlacement);\nconst clearLabel = computed<string>(() => t(keys.clearValue, 'Clear the date'));\nconst toggleLabel = computed<string>(() => (get(isOpen)\n ? t(keys.closeCalendar, 'Close the calendar')\n : t(keys.openCalendar, 'Open the calendar')));\n\nconst textInput = useTemplateRef<HTMLInputElement>('textInput');\nconst activator = useTemplateRef<HTMLDivElement>('activator');\nconst menuWrapperRef = useTemplateRef<ComponentPublicInstance>('menuWrapperRef');\nconst calendarMenuOpen = ref<boolean>(false);\n\nconst { focused: activatorFocusedWithin } = useFocusWithin(activator);\nconst { focused: menuWrapperFocusedWithin } = useFocusWithin(menuWrapperRef);\nconst { focused: searchInputFocused } = useFocus(textInput);\n\nconst anyFocused = computed<boolean>(() => get(activatorFocusedWithin) || get(menuWrapperFocusedWithin));\n\nconst dateFormat = computed<string>(() => {\n const fmt = baseFormats[format];\n if (accuracy === 'second') {\n return fmt.replace('HH:mm', 'HH:mm:ss');\n }\n else if (accuracy === 'millisecond') {\n return fmt.replace('HH:mm', 'HH:mm:ss.SSS');\n }\n return fmt;\n});\n\nconst {\n clear: clearSelection,\n commitPartialTime,\n getDateTime,\n internalErrorMessages,\n maxAllowedDate,\n minAllowedDate,\n segmentData,\n selectedDate,\n modelDay,\n modelHour,\n modelMillisecond,\n modelMinute,\n modelMonth,\n modelSecond,\n selectedTime,\n modelTimezone,\n modelYear,\n setNow,\n setToday,\n valueSet,\n} = useDateTimeSelection({\n accuracy,\n allowEmpty,\n dateFormat,\n maxDate,\n minDate,\n modelValue,\n partialTime,\n type,\n});\n\nconst { setValue, getCurrent } = useInputHandler(segmentData, currentValue);\n\nconst {\n clear: clearSegment,\n getCurrentSegment,\n handleBlur,\n handleClick,\n handleFocus,\n handleInput,\n handleInputSelection,\n handleKeyDown,\n handleMouseDown,\n handlePaste,\n pasteRejected,\n selectFirstSegment,\n setSegment,\n} = useKeyboardHandler({\n accuracy,\n currentValue,\n cursorPosition,\n dateFormat,\n disabled,\n getCurrent,\n getDateTime,\n readonly,\n setValue,\n textInput,\n timezone: modelTimezone,\n});\n\nconst { hasError, hasSuccess } = useFormTextDetail(\n () => errorMessages,\n () => successMessages,\n);\n\n/** True once any segment holds a digit, even a partially typed date. */\nconst anySegmentSet = computed<boolean>(() => [\n modelYear,\n modelMonth,\n modelDay,\n modelHour,\n modelMinute,\n modelSecond,\n modelMillisecond,\n].some(segment => isDefined(segment)));\n\n/**\n * The field's text.\n *\n * An untouched field shows its format through the placeholder rather than\n * holding the tokens as its value, where a screen reader reads them as content\n * and select-all copies them. The tokens stay while the field is focused: that\n * is when the segment machinery highlights them, and collapsing the value\n * mid-edit would blank the field under the cursor. The guard is \"no segment\n * set\" rather than `valueSet`, so blurring a half-typed date keeps what was\n * entered on screen.\n */\nconst formattedDisplay = computed<string>(() => {\n if (!get(anySegmentSet) && !get(searchInputFocused)) {\n return '';\n }\n\n let result = get(dateFormat);\n\n const replacements = [\n { pattern: 'YYYY', value: getDisplayValue(modelYear, 4) },\n { pattern: 'MM', value: getDisplayValue(modelMonth, 2) },\n { pattern: 'DD', value: getDisplayValue(modelDay, 2) },\n { pattern: 'HH', value: getDisplayValue(modelHour, 2) },\n { pattern: 'mm', value: getDisplayValue(modelMinute, 2) },\n { pattern: 'ss', value: getDisplayValue(modelSecond, 2) },\n { pattern: 'SSS', value: getDisplayValue(modelMillisecond, 3) },\n ];\n\n for (const { pattern, value } of replacements) {\n if (value !== undefined) {\n result = result.replace(pattern, value);\n }\n }\n\n return result;\n});\n\n/**\n * An untouched field holds no value until focus expands the format tokens into\n * it. That patch overwrites the input's value, and writing a value drops any\n * selection with it, so the highlight `handleFocus` just set is gone by the\n * time the tokens are on screen and the caret ends up after them. Re-select\n * the first segment once the tokens have actually landed.\n */\nwatch(formattedDisplay, (value, previous) => {\n if (previous === '' && value !== '' && get(searchInputFocused))\n selectFirstSegment();\n}, { flush: 'post' });\n\nconst timeSelection = computed<TimePickerSelection>({\n get() {\n const type = getCurrentSegment()?.type;\n\n if (type === 'mm') {\n return 'minute';\n }\n else if (type === 'ss') {\n return 'second';\n }\n else if (type === 'SSS') {\n return 'millisecond';\n }\n return 'hour';\n },\n set(value: TimePickerSelection) {\n let segmentType: DateTimeSegmentType = 'HH';\n if (value === 'minute') {\n segmentType = 'mm';\n }\n else if (value === 'second') {\n segmentType = 'ss';\n }\n else if (value === 'millisecond') {\n segmentType = 'SSS';\n }\n\n setSegment(segmentType);\n },\n});\n\nconst ui = computed<ReturnType<typeof dateTimePickerStyles>>(() => dateTimePickerStyles({\n opened: get(isOpen),\n hovered: get(isHovered),\n dense,\n disabled,\n readonly,\n hasError: get(hasError),\n hasSuccess: get(hasSuccess) && !get(hasError),\n}));\n\nconst pasteMessage = computed<string>(() => (get(pasteRejected)\n ? t(keys.pasteUnreadable, 'Could not read a date from the pasted text')\n : ''));\n\n/**\n * The paste message goes first: the details show one message, and it answers\n * what the user just did, which a standing validation error does not.\n */\nconst combinedErrorMessages = computed<string[]>(() => {\n const paste = get(pasteMessage) ? [get(pasteMessage)] : [];\n if (!errorMessages)\n return [...paste, ...get(internalErrorMessages)];\n\n const propErrors = Array.isArray(errorMessages) ? errorMessages : [errorMessages];\n return [...paste, ...propErrors, ...get(internalErrorMessages)];\n});\n\nfunction getDisplayValue(digit: Ref<number | undefined>, padding: number): string | undefined {\n return isDefined(digit) ? get(digit).toString().padStart(padding, '0') : undefined;\n}\n\nasync function setInputFocus(): Promise<void> {\n await nextTick(() => {\n set(searchInputFocused, true);\n });\n}\n\nfunction clear(segmentType?: string): void {\n if (!segmentType) {\n clearSelection();\n set(currentValue, undefined);\n return;\n }\n\n clearSegment(segmentType);\n}\n\n/**\n * An entry left incomplete is completed once the user is done with the field,\n * never while they are still filling it in: a half typed hour is not a segment\n * they left out. Leaving the field counts, unless the calendar is open, since\n * then the focus is only moving into it and the menu closing covers that.\n */\nfunction onBlur(): void {\n handleBlur();\n if (!get(isOpen))\n commitPartialTime();\n}\n\nwatch(isOpen, (open) => {\n if (!open && !get(searchInputFocused))\n commitPartialTime();\n});\n\n/**\n * Selects the clicked segment before opening the menu, so the selection is not\n * lost to the DOM changes that opening brings.\n */\nfunction handleInputClick(event: MouseEvent): void {\n handleClick(event);\n if (!get(isOpen)) {\n set(isOpen, true);\n }\n}\n\n/**\n * The menu is teleported to the body, so it never sits next to the field in\n * the tab sequence. Opening it from the keyboard therefore moves focus into\n * the calendar; opening it with the mouse leaves focus in the field, which is\n * what `disable-auto-focus` on the menu is there for.\n */\nconst focusCalendarOnOpen = ref<boolean>(false);\n\n/**\n * Asks for focus to move into the calendar. The menu is teleported and mounts\n * a frame later, so the watcher below waits for the wrapper to appear rather\n * than guessing at a number of ticks.\n */\nfunction focusCalendar(): void {\n set(focusCalendarOnOpen, true);\n}\n\nwatch(menuWrapperRef, (menu) => {\n if (!menu || !get(focusCalendarOnOpen))\n return;\n\n set(focusCalendarOnOpen, false);\n nextTick(() => {\n const el = menu.$el as HTMLElement | undefined;\n el?.querySelector<HTMLButtonElement>('[role=\"gridcell\"][tabindex=\"0\"]')?.focus({ preventScroll: true });\n });\n});\n\n/** Moves focus to the field. Exposed so a consumer can drive it from a ref. */\nfunction focus(): void {\n get(textInput)?.focus({ preventScroll: true });\n}\n\nfunction focusField(): void {\n nextTick(focus);\n}\n\nonMounted(() => {\n if (autofocus && !disabled)\n focusField();\n});\n\n/** Escape inside the calendar closes it and hands focus back to the field. */\nfunction closeFromMenu(): void {\n set(isOpen, false);\n focusField();\n}\n\n/**\n * The menu used to be mouse-only: the activator carried no key handlers, so\n * there was no way to reach the calendar from the keyboard. Alt+ArrowDown\n * opens it and Escape closes it, following the combobox convention, and the\n * append chevron is a real button for anyone who tabs to it instead.\n *\n * Enter and Escape are the other ways to be done with the field, and the keys\n * a consumer tends to close its editor on. Escape reaches that point only once\n * the calendar is already shut, and discards nothing, since the segments stay\n * on screen either way, so it commits what was entered rather than dropping it\n * when the field goes. Both write the value before the key carries on\n * bubbling, so it survives that close.\n */\nfunction onKeyDown(event: KeyboardEvent): void {\n if (disabled || readonly)\n return;\n\n if (event.altKey && event.key === 'ArrowDown') {\n event.preventDefault();\n set(isOpen, true);\n focusCalendar();\n return;\n }\n\n if (event.key === 'Escape' && get(isOpen)) {\n set(isOpen, false);\n return;\n }\n\n if (event.key === 'Enter' || event.key === 'Escape')\n commitPartialTime();\n\n handleKeyDown(event);\n}\n\nfunction arrowClicked(event: MouseEvent): void {\n if (get(isOpen)) {\n set(isOpen, false);\n event.stopPropagation();\n }\n}\n\nconst menuActions = computed<DateTimePickerAction[]>(\n () => actions.filter(action => action !== 'clear' || allowEmpty),\n);\n\nconst anyMenuOpen = computed<boolean>(() => get(isOpen) || get(calendarMenuOpen));\n\nwatch(anyMenuOpen, (value) => {\n set(menuOpen, value);\n});\n\ndefineExpose({\n focus,\n});\n</script>\n\n<template>\n <RuiMenu\n v-model=\"isOpen\"\n v-bind=\"getRootAttrs($attrs, [])\"\n :class=\"ui.wrapper({ class: cn($attrs.class) })\"\n :class-names=\"{ details: 'px-0', content: 'p-0' }\"\n :options=\"MENU_OPTIONS\"\n :dense=\"dense\"\n :hint=\"hint\"\n :disabled=\"disabled\"\n :success-messages=\"successMessages\"\n :error-messages=\"combinedErrorMessages\"\n :close-on-content-click=\"false\"\n :show-details=\"!hideDetails\"\n :persistent=\"calendarMenuOpen\"\n :menu-label=\"fieldLabel\"\n role=\"dialog\"\n full-width\n disable-auto-focus\n >\n <template #label>\n <RuiFieldLabel\n :for=\"inputId\"\n :text=\"fieldLabel\"\n :hidden=\"placement === 'hidden'\"\n :required=\"required\"\n :disabled=\"disabled\"\n />\n </template>\n <template #activator=\"{ attrs }\">\n <div\n ref=\"activator\"\n :class=\"ui.activator()\"\n v-bind=\"{\n ...getNonRootAttrs($attrs, ['onClick', 'class']),\n ...(readonly ? {} : activatorHandlers(attrs)),\n }\"\n data-id=\"activator\"\n :aria-invalid=\"hasError\"\n @mouseenter=\"isHovered = true\"\n @mouseleave=\"isHovered = false\"\n @click=\"setInputFocus()\"\n >\n <span :class=\"ui.iconPrepend()\">\n <RuiIcon\n class=\"text-rui-neutral-500 dark:text-rui-neutral-400 transition\"\n :size=\"dense ? 16 : 20\"\n name=\"lu-calendar-days\"\n />\n </span>\n\n <div :class=\"ui.value()\">\n <input\n :id=\"inputId\"\n ref=\"textInput\"\n :disabled=\"disabled\"\n :value=\"formattedDisplay\"\n class=\"bg-transparent outline-hidden flex-1 min-w-0\"\n type=\"text\"\n inputmode=\"numeric\"\n spellcheck=\"false\"\n autocomplete=\"off\"\n autocorrect=\"off\"\n autocapitalize=\"off\"\n :placeholder=\"dateFormat\"\n :readonly=\"readonly\"\n :aria-invalid=\"hasError\"\n :aria-required=\"required || undefined\"\n @mousedown=\"handleMouseDown($event)\"\n @focus=\"handleFocus()\"\n @blur=\"onBlur()\"\n @select=\"handleInputSelection($event)\"\n @click.stop=\"handleInputClick($event)\"\n @keydown=\"onKeyDown($event)\"\n @paste=\"handlePaste($event)\"\n @input=\"handleInput($event)\"\n />\n <!-- The details line is not a live region, so a rejected paste is announced from here -->\n <span\n class=\"sr-only\"\n aria-live=\"polite\"\n data-id=\"paste-status\"\n >\n {{ pasteMessage }}\n </span>\n </div>\n\n <RuiButton\n v-if=\"allowEmpty && valueSet && !disabled && !readonly\"\n variant=\"text\"\n icon\n data-id=\"clear-button\"\n size=\"sm\"\n :aria-label=\"clearLabel\"\n :class=\"[\n ui.clear(),\n anyFocused && 'visible!',\n { 'mr-2': !dense },\n ]\"\n @click.stop.prevent=\"clear()\"\n >\n <RuiIcon\n name=\"lu-x\"\n size=\"16\"\n />\n </RuiButton>\n\n <!-- Out of the tab sequence, following the combobox pattern: the button only duplicates\n Alt+ArrowDown on the field, so leaving it in cost two stops to cross one date field\n and four to cross a from/to pair, for nothing a keyboard user could not already do.\n It stays a real button, so it keeps its label and its expanded state for anyone\n reaching it by any other means. -->\n <button\n v-if=\"!disabled && !readonly\"\n type=\"button\"\n tabindex=\"-1\"\n :class=\"ui.iconWrapper()\"\n data-id=\"append\"\n :aria-label=\"toggleLabel\"\n :aria-expanded=\"isOpen\"\n aria-haspopup=\"dialog\"\n @click=\"arrowClicked($event)\"\n >\n <RuiIcon\n :class=\"ui.icon()\"\n :size=\"dense ? 16 : 20\"\n name=\"lu-chevron-down\"\n />\n </button>\n <span\n v-else\n :class=\"ui.iconWrapper()\"\n data-id=\"append\"\n >\n <RuiIcon\n :class=\"ui.icon()\"\n :size=\"dense ? 16 : 20\"\n name=\"lu-chevron-down\"\n />\n </span>\n </div>\n <fieldset :class=\"ui.fieldset()\" />\n </template>\n <template #default>\n <RuiDateTimePickerMenu\n ref=\"menuWrapperRef\"\n v-model:selected-date=\"selectedDate\"\n v-model:selected-time=\"selectedTime\"\n v-model:selected-hour=\"modelHour\"\n v-model:selected-minute=\"modelMinute\"\n v-model:selected-second=\"modelSecond\"\n v-model:selected-millisecond=\"modelMillisecond\"\n v-model:time-selection=\"timeSelection\"\n v-model:selected-timezone=\"modelTimezone\"\n v-model:calendar-menu-open=\"calendarMenuOpen\"\n :accuracy=\"accuracy\"\n :max-date=\"maxAllowedDate\"\n :min-date=\"minAllowedDate\"\n :show-timezone=\"showTimezone\"\n :actions=\"menuActions\"\n @keydown.escape=\"closeFromMenu()\"\n @set-now=\"setNow()\"\n @set-today=\"setToday()\"\n @clear=\"clear()\"\n >\n <!-- only when given, or the panel draws an empty third column with its divider -->\n <template\n v-if=\"$slots['menu-content']\"\n #default\n >\n <slot name=\"menu-content\" />\n </template>\n </RuiDateTimePickerMenu>\n </template>\n </RuiMenu>\n</template>\n"],"mappings":""}
@@ -1,5 +1,5 @@
1
1
  import type { DateTimePickerAction } from './types.js';
2
- import { type DateTimePickerVariant } from './date-time-picker-styles.js';
2
+ import { type LabelPlacement } from '../../composables/defaults/field.js';
3
3
  type DateFormat = 'year-first' | 'month-first' | 'day-first';
4
4
  type DateTimeModelType = 'date' | 'epoch-ms' | 'epoch';
5
5
  type ModelValueType<T extends DateTimeModelType> = T extends 'date' ? Date | undefined : T extends 'epoch-ms' ? number | undefined : T extends 'epoch' ? number | undefined : Date | number | undefined;
@@ -14,7 +14,8 @@ export interface RuiDateTimePickerProps {
14
14
  readonly?: boolean;
15
15
  dense?: boolean;
16
16
  label?: string;
17
- variant?: DateTimePickerVariant;
17
+ /** Where the label shows; falls back to the nearest `RuiFieldDefaults`, then the app default, then `top`. */
18
+ labelPlacement?: LabelPlacement;
18
19
  hint?: string;
19
20
  errorMessages?: string | string[];
20
21
  successMessages?: string | string[];
@@ -1,3 +1,4 @@
1
+ import { useLabelPlacement } from "../../composables/defaults/field.js";
1
2
  import { useRuiI8n } from "../../composables/use-rui-i18n.js";
2
3
  import { cn } from "../../utils/tv.js";
3
4
  import RuiIcon_default from "../icons/RuiIcon.js";
@@ -5,25 +6,27 @@ import RuiButton_default from "../buttons/button/RuiButton.js";
5
6
  import { useFormTextDetail } from "../../utils/form-text-detail.js";
6
7
  import { Placement } from "../../composables/floating.js";
7
8
  import RuiMenu_default from "../overlays/menu/RuiMenu.js";
9
+ import RuiFieldLabel_default from "../forms/field-label/RuiFieldLabel.js";
8
10
  import { getNonRootAttrs, getRootAttrs } from "../../utils/helpers.js";
9
11
  import { dateTimePickerStyles } from "./date-time-picker-styles.js";
12
+ import { activatorHandlers } from "../overlays/menu/activator-handlers.js";
10
13
  import { RUI_I18N_KEYS } from "../../i18n/keys.js";
11
14
  import RuiDateTimePickerMenu_default from "./RuiDateTimePickerMenu.js";
12
15
  import { useDateTimeSelection } from "./use-date-time-selection.js";
13
16
  import { useInputHandler } from "./use-input-handler.js";
14
17
  import { useKeyboardHandler } from "./use-keyboard-handler.js";
15
- import { computed, createBlock, createCommentVNode, createElementBlock, createElementVNode, createTextVNode, createVNode, defineComponent, isRef, mergeModels, mergeProps, nextTick, normalizeClass, onMounted, openBlock, ref, renderSlot, toDisplayString, unref, useModel, useTemplateRef, watch, withCtx, withKeys, withModifiers } from "vue";
18
+ import { computed, createBlock, createCommentVNode, createElementBlock, createElementVNode, createSlots, createVNode, defineComponent, isRef, mergeModels, mergeProps, nextTick, normalizeClass, onMounted, openBlock, ref, renderSlot, toDisplayString, unref, useId, useModel, useTemplateRef, watch, withCtx, withKeys, withModifiers } from "vue";
16
19
  import { isDefined, useFocus, useFocusWithin } from "@vueuse/core";
17
20
  import { get as get$1, set as set$1 } from "@vueuse/shared";
18
21
  //#region src/components/date-time-picker/RuiDateTimePicker.vue?vue&type=script&setup=true&lang.ts
19
22
  var _hoisted_1 = ["aria-invalid"];
20
23
  var _hoisted_2 = [
24
+ "id",
21
25
  "disabled",
22
26
  "value",
23
27
  "placeholder",
24
28
  "readonly",
25
29
  "aria-invalid",
26
- "aria-label",
27
30
  "aria-required"
28
31
  ];
29
32
  var _hoisted_3 = {
@@ -59,7 +62,7 @@ var RuiDateTimePicker_vue_vue_type_script_setup_true_lang_default = /*@__PURE__*
59
62
  default: false
60
63
  },
61
64
  label: {},
62
- variant: { default: "default" },
65
+ labelPlacement: { default: () => void 0 },
63
66
  hint: {},
64
67
  errorMessages: { default: () => [] },
65
68
  successMessages: { default: () => [] },
@@ -107,6 +110,8 @@ var RuiDateTimePicker_vue_vue_type_script_setup_true_lang_default = /*@__PURE__*
107
110
  const { t } = useRuiI8n();
108
111
  const keys = RUI_I18N_KEYS.dateTimePicker;
109
112
  const fieldLabel = computed(() => __props.label ?? t(keys.label, "Pick a date"));
113
+ const inputId = useId();
114
+ const placement = useLabelPlacement(() => __props.labelPlacement);
110
115
  const clearLabel = computed(() => t(keys.clearValue, "Clear the date"));
111
116
  const toggleLabel = computed(() => get$1(isOpen) ? t(keys.closeCalendar, "Close the calendar") : t(keys.openCalendar, "Open the calendar"));
112
117
  const textInput = useTemplateRef("textInput");
@@ -148,7 +153,6 @@ var RuiDateTimePicker_vue_vue_type_script_setup_true_lang_default = /*@__PURE__*
148
153
  timezone: modelTimezone
149
154
  });
150
155
  const { hasError, hasSuccess } = useFormTextDetail(() => __props.errorMessages, () => __props.successMessages);
151
- const isOutlined = computed(() => __props.variant === "outlined");
152
156
  /** True once any segment holds a digit, even a partially typed date. */
153
157
  const anySegmentSet = computed(() => [
154
158
  modelYear,
@@ -232,17 +236,7 @@ var RuiDateTimePicker_vue_vue_type_script_setup_true_lang_default = /*@__PURE__*
232
236
  setSegment(segmentType);
233
237
  }
234
238
  });
235
- const float = computed(() => (get$1(isOpen) || get$1(valueSet) || get$1(searchInputFocused)) && get$1(isOutlined));
236
- const legendText = computed(() => {
237
- if (!get$1(float)) return "";
238
- const resolved = get$1(fieldLabel);
239
- return __props.required ? `${resolved} ﹡` : resolved;
240
- });
241
239
  const ui = computed(() => dateTimePickerStyles({
242
- filled: __props.variant === "filled",
243
- outlined: get$1(isOutlined),
244
- float: get$1(float),
245
- showLabel: !!get$1(legendText),
246
240
  opened: get$1(isOpen),
247
241
  hovered: get$1(isHovered),
248
242
  dense: __props.dense,
@@ -386,6 +380,10 @@ var RuiDateTimePicker_vue_vue_type_script_setup_true_lang_default = /*@__PURE__*
386
380
  "onUpdate:modelValue": _cache[26] || (_cache[26] = ($event) => isRef(isOpen) ? isOpen.value = $event : null)
387
381
  }, unref(getRootAttrs)(_ctx.$attrs, []), {
388
382
  class: unref(ui).wrapper({ class: unref(cn)(_ctx.$attrs.class) }),
383
+ "class-names": {
384
+ details: "px-0",
385
+ content: "p-0"
386
+ },
389
387
  options: MENU_OPTIONS,
390
388
  dense: __props.dense,
391
389
  hint: __props.hint,
@@ -395,16 +393,31 @@ var RuiDateTimePicker_vue_vue_type_script_setup_true_lang_default = /*@__PURE__*
395
393
  "close-on-content-click": false,
396
394
  "show-details": !__props.hideDetails,
397
395
  persistent: unref(calendarMenuOpen),
396
+ "menu-label": unref(fieldLabel),
397
+ role: "dialog",
398
398
  "full-width": "",
399
399
  "disable-auto-focus": ""
400
400
  }), {
401
- activator: withCtx(({ attrs, open }) => [createElementVNode("div", mergeProps({
401
+ label: withCtx(() => [createVNode(RuiFieldLabel_default, {
402
+ for: unref(inputId),
403
+ text: unref(fieldLabel),
404
+ hidden: unref(placement) === "hidden",
405
+ required: __props.required,
406
+ disabled: __props.disabled
407
+ }, null, 8, [
408
+ "for",
409
+ "text",
410
+ "hidden",
411
+ "required",
412
+ "disabled"
413
+ ])]),
414
+ activator: withCtx(({ attrs }) => [createElementVNode("div", mergeProps({
402
415
  ref_key: "activator",
403
416
  ref: activator,
404
417
  class: unref(ui).activator()
405
418
  }, {
406
419
  ...unref(getNonRootAttrs)(_ctx.$attrs, ["onClick", "class"]),
407
- ...__props.readonly ? {} : attrs
420
+ ...__props.readonly ? {} : unref(activatorHandlers)(attrs)
408
421
  }, {
409
422
  "data-id": "activator",
410
423
  "aria-invalid": unref(hasError),
@@ -412,26 +425,18 @@ var RuiDateTimePicker_vue_vue_type_script_setup_true_lang_default = /*@__PURE__*
412
425
  onMouseleave: _cache[11] || (_cache[11] = ($event) => isHovered.value = false),
413
426
  onClick: _cache[12] || (_cache[12] = ($event) => setInputFocus())
414
427
  }), [
415
- unref(isOutlined) && (unref(searchInputFocused) || open || unref(valueSet)) ? (openBlock(), createElementBlock("span", {
416
- key: 0,
417
- "data-id": "label",
418
- class: normalizeClass([unref(ui).label(), { "pr-2": !unref(valueSet) && !open && unref(isOutlined) }])
419
- }, [createTextVNode(toDisplayString(unref(fieldLabel)) + " ", 1), __props.required ? (openBlock(), createElementBlock("span", {
420
- key: 0,
421
- "data-id": "required-indicator",
422
- class: normalizeClass(unref(ui).required())
423
- }, " ﹡ ", 2)) : createCommentVNode("", true)], 2)) : createCommentVNode("", true),
424
428
  createElementVNode("span", { class: normalizeClass(unref(ui).iconPrepend()) }, [createVNode(RuiIcon_default, {
425
- class: "text-rui-text-secondary transition",
426
- size: __props.dense ? 16 : 24,
429
+ class: "text-rui-neutral-500 dark:text-rui-neutral-400 transition",
430
+ size: __props.dense ? 16 : 20,
427
431
  name: "lu-calendar-days"
428
432
  }, null, 8, ["size"])], 2),
429
433
  createElementVNode("div", { class: normalizeClass(unref(ui).value()) }, [createElementVNode("input", {
434
+ id: unref(inputId),
430
435
  ref_key: "textInput",
431
436
  ref: textInput,
432
437
  disabled: __props.disabled,
433
438
  value: unref(formattedDisplay),
434
- class: "bg-transparent outline-none flex-1 min-w-0",
439
+ class: "bg-transparent outline-hidden flex-1 min-w-0",
435
440
  type: "text",
436
441
  inputmode: "numeric",
437
442
  spellcheck: "false",
@@ -441,7 +446,6 @@ var RuiDateTimePicker_vue_vue_type_script_setup_true_lang_default = /*@__PURE__*
441
446
  placeholder: unref(dateFormat),
442
447
  readonly: __props.readonly,
443
448
  "aria-invalid": unref(hasError),
444
- "aria-label": unref(fieldLabel),
445
449
  "aria-required": __props.required || void 0,
446
450
  onMousedown: _cache[0] || (_cache[0] = ($event) => unref(handleMouseDown)($event)),
447
451
  onFocus: _cache[1] || (_cache[1] = ($event) => unref(handleFocus)()),
@@ -452,29 +456,28 @@ var RuiDateTimePicker_vue_vue_type_script_setup_true_lang_default = /*@__PURE__*
452
456
  onPaste: _cache[6] || (_cache[6] = ($event) => unref(handlePaste)($event)),
453
457
  onInput: _cache[7] || (_cache[7] = ($event) => unref(handleInput)($event))
454
458
  }, null, 40, _hoisted_2), createElementVNode("span", _hoisted_3, toDisplayString(unref(pasteMessage)), 1)], 2),
455
- __props.allowEmpty && unref(valueSet) && !__props.disabled ? (openBlock(), createBlock(RuiButton_default, {
456
- key: 1,
459
+ __props.allowEmpty && unref(valueSet) && !__props.disabled && !__props.readonly ? (openBlock(), createBlock(RuiButton_default, {
460
+ key: 0,
457
461
  variant: "text",
458
462
  icon: "",
459
463
  "data-id": "clear-button",
460
464
  size: "sm",
461
- color: "error",
462
465
  "aria-label": unref(clearLabel),
463
466
  class: normalizeClass([
464
467
  unref(ui).clear(),
465
- unref(anyFocused) && "!visible",
468
+ unref(anyFocused) && "visible!",
466
469
  { "mr-2": !__props.dense }
467
470
  ]),
468
471
  onClick: _cache[8] || (_cache[8] = withModifiers(($event) => clear(), ["stop", "prevent"]))
469
472
  }, {
470
473
  default: withCtx(() => [createVNode(RuiIcon_default, {
471
474
  name: "lu-x",
472
- size: "18"
475
+ size: "16"
473
476
  })]),
474
477
  _: 1
475
478
  }, 8, ["aria-label", "class"])) : createCommentVNode("", true),
476
479
  !__props.disabled && !__props.readonly ? (openBlock(), createElementBlock("button", {
477
- key: 2,
480
+ key: 1,
478
481
  type: "button",
479
482
  tabindex: "-1",
480
483
  class: normalizeClass(unref(ui).iconWrapper()),
@@ -485,21 +488,18 @@ var RuiDateTimePicker_vue_vue_type_script_setup_true_lang_default = /*@__PURE__*
485
488
  onClick: _cache[9] || (_cache[9] = ($event) => arrowClicked($event))
486
489
  }, [createVNode(RuiIcon_default, {
487
490
  class: normalizeClass(unref(ui).icon()),
488
- size: __props.dense ? 16 : 24,
491
+ size: __props.dense ? 16 : 20,
489
492
  name: "lu-chevron-down"
490
493
  }, null, 8, ["class", "size"])], 10, _hoisted_4)) : (openBlock(), createElementBlock("span", {
491
- key: 3,
494
+ key: 2,
492
495
  class: normalizeClass(unref(ui).iconWrapper()),
493
496
  "data-id": "append"
494
497
  }, [createVNode(RuiIcon_default, {
495
498
  class: normalizeClass(unref(ui).icon()),
496
- size: __props.dense ? 16 : 24,
499
+ size: __props.dense ? 16 : 20,
497
500
  name: "lu-chevron-down"
498
501
  }, null, 8, ["class", "size"])], 2))
499
- ], 16, _hoisted_1), unref(isOutlined) ? (openBlock(), createElementBlock("fieldset", {
500
- key: 0,
501
- class: normalizeClass(unref(ui).fieldset())
502
- }, [createElementVNode("legend", { class: normalizeClass(unref(ui).legend()) }, toDisplayString(unref(legendText)), 3)], 2)) : createCommentVNode("", true)]),
502
+ ], 16, _hoisted_1), createElementVNode("fieldset", { class: normalizeClass(unref(ui).fieldset()) }, null, 2)]),
503
503
  default: withCtx(() => [createVNode(RuiDateTimePickerMenu_default, {
504
504
  ref_key: "menuWrapperRef",
505
505
  ref: menuWrapperRef,
@@ -530,10 +530,11 @@ var RuiDateTimePicker_vue_vue_type_script_setup_true_lang_default = /*@__PURE__*
530
530
  onSetNow: _cache[23] || (_cache[23] = ($event) => unref(setNow)()),
531
531
  onSetToday: _cache[24] || (_cache[24] = ($event) => unref(setToday)()),
532
532
  onClear: _cache[25] || (_cache[25] = ($event) => clear())
533
- }, {
534
- default: withCtx(() => [renderSlot(_ctx.$slots, "menu-content")]),
535
- _: 3
536
- }, 8, [
533
+ }, createSlots({ _: 2 }, [_ctx.$slots["menu-content"] ? {
534
+ name: "default",
535
+ fn: withCtx(() => [renderSlot(_ctx.$slots, "menu-content")]),
536
+ key: "0"
537
+ } : void 0]), 1032, [
537
538
  "selected-date",
538
539
  "selected-time",
539
540
  "selected-hour",
@@ -559,7 +560,8 @@ var RuiDateTimePicker_vue_vue_type_script_setup_true_lang_default = /*@__PURE__*
559
560
  "success-messages",
560
561
  "error-messages",
561
562
  "show-details",
562
- "persistent"
563
+ "persistent",
564
+ "menu-label"
563
565
  ]);
564
566
  };
565
567
  }