@rotki/ui-library 3.2.0 → 3.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (235) hide show
  1. package/dist/components/accordions/accordion/RuiAccordion.js.map +1 -1
  2. package/dist/components/accordions/accordion/RuiAccordion.vue.d.ts +4 -2
  3. package/dist/components/accordions/accordion/RuiAccordion.vue_vue_type_script_setup_true_lang.js.map +1 -1
  4. package/dist/components/accordions/accordions/RuiAccordions.js.map +1 -1
  5. package/dist/components/accordions/accordions/RuiAccordions.vue.d.ts +26 -9
  6. package/dist/components/accordions/accordions/RuiAccordions.vue_vue_type_script_setup_true_lang.js +11 -10
  7. package/dist/components/accordions/accordions/RuiAccordions.vue_vue_type_script_setup_true_lang.js.map +1 -1
  8. package/dist/components/alerts/RuiAlert.js.map +1 -1
  9. package/dist/components/alerts/RuiAlert.vue.d.ts +4 -2
  10. package/dist/components/alerts/RuiAlert.vue_vue_type_script_setup_true_lang.js.map +1 -1
  11. package/dist/components/avatars/RuiAvatar.js.map +1 -1
  12. package/dist/components/avatars/RuiAvatar.vue.d.ts +4 -2
  13. package/dist/components/avatars/RuiAvatar.vue_vue_type_script_setup_true_lang.js.map +1 -1
  14. package/dist/components/avatars/RuiAvatarGroup.js.map +1 -1
  15. package/dist/components/avatars/RuiAvatarGroup.vue.d.ts +3 -2
  16. package/dist/components/avatars/RuiAvatarGroup.vue_vue_type_script_setup_true_lang.js.map +1 -1
  17. package/dist/components/buttons/button/RuiButton.js.map +1 -1
  18. package/dist/components/buttons/button/RuiButton.vue.d.ts +2 -1
  19. package/dist/components/buttons/button/RuiButton.vue_vue_type_script_setup_true_lang.js.map +1 -1
  20. package/dist/components/buttons/button-group/RuiButtonGroup.js.map +1 -1
  21. package/dist/components/buttons/button-group/RuiButtonGroup.vue.d.ts +10 -4
  22. package/dist/components/buttons/button-group/RuiButtonGroup.vue_vue_type_script_setup_true_lang.js +7 -8
  23. package/dist/components/buttons/button-group/RuiButtonGroup.vue_vue_type_script_setup_true_lang.js.map +1 -1
  24. package/dist/components/calendar/RuiCalendarGrid.js.map +1 -1
  25. package/dist/components/calendar/RuiCalendarGrid.vue_vue_type_script_setup_true_lang.js +3 -3
  26. package/dist/components/calendar/RuiCalendarGrid.vue_vue_type_script_setup_true_lang.js.map +1 -1
  27. package/dist/components/calendar/RuiCalendarHeader.js.map +1 -1
  28. package/dist/components/calendar/RuiCalendarHeader.vue_vue_type_script_setup_true_lang.js +3 -3
  29. package/dist/components/calendar/RuiCalendarHeader.vue_vue_type_script_setup_true_lang.js.map +1 -1
  30. package/dist/components/calendar/RuiCalendarMenu.js.map +1 -1
  31. package/dist/components/calendar/RuiCalendarMenu.vue.d.ts +3 -3
  32. package/dist/components/calendar/RuiCalendarMenu.vue_vue_type_script_setup_true_lang.js +7 -4
  33. package/dist/components/calendar/RuiCalendarMenu.vue_vue_type_script_setup_true_lang.js.map +1 -1
  34. package/dist/components/calendar/state.d.ts +8 -1
  35. package/dist/components/calendar/state.js +13 -1
  36. package/dist/components/calendar/state.js.map +1 -1
  37. package/dist/components/cards/RuiCard.js.map +1 -1
  38. package/dist/components/cards/RuiCard.vue.d.ts +3 -1
  39. package/dist/components/cards/RuiCard.vue_vue_type_script_setup_true_lang.js.map +1 -1
  40. package/dist/components/cards/RuiCardHeader.js.map +1 -1
  41. package/dist/components/cards/RuiCardHeader.vue.d.ts +3 -1
  42. package/dist/components/cards/RuiCardHeader.vue_vue_type_script_setup_true_lang.js.map +1 -1
  43. package/dist/components/chips/RuiChip.js.map +1 -1
  44. package/dist/components/chips/RuiChip.vue.d.ts +4 -2
  45. package/dist/components/chips/RuiChip.vue_vue_type_script_setup_true_lang.js.map +1 -1
  46. package/dist/components/color-picker/RuiColorPicker.js.map +1 -1
  47. package/dist/components/color-picker/RuiColorPicker.vue.d.ts +5 -2
  48. package/dist/components/color-picker/RuiColorPicker.vue_vue_type_script_setup_true_lang.js.map +1 -1
  49. package/dist/components/date-time-picker/RuiDateTimePicker.js.map +1 -1
  50. package/dist/components/date-time-picker/RuiDateTimePicker.vue.d.ts +39 -30
  51. package/dist/components/date-time-picker/RuiDateTimePicker.vue_vue_type_script_setup_true_lang.js +8 -3
  52. package/dist/components/date-time-picker/RuiDateTimePicker.vue_vue_type_script_setup_true_lang.js.map +1 -1
  53. package/dist/components/date-time-picker/RuiDateTimePickerMenu.js.map +1 -1
  54. package/dist/components/date-time-picker/RuiDateTimePickerMenu.vue.d.ts +2 -1
  55. package/dist/components/date-time-picker/RuiDateTimePickerMenu.vue_vue_type_script_setup_true_lang.js.map +1 -1
  56. package/dist/components/date-time-picker/RuiTimezoneSelect.js.map +1 -1
  57. package/dist/components/date-time-picker/RuiTimezoneSelect.vue.d.ts +2 -1
  58. package/dist/components/date-time-picker/RuiTimezoneSelect.vue_vue_type_script_setup_true_lang.js.map +1 -1
  59. package/dist/components/divider/RuiDivider.js.map +1 -1
  60. package/dist/components/divider/RuiDivider.vue.d.ts +3 -1
  61. package/dist/components/divider/RuiDivider.vue_vue_type_script_setup_true_lang.js.map +1 -1
  62. package/dist/components/forms/auto-complete/RuiAutoComplete.js.map +1 -1
  63. package/dist/components/forms/auto-complete/RuiAutoComplete.vue.d.ts +11 -5
  64. package/dist/components/forms/auto-complete/RuiAutoComplete.vue_vue_type_script_setup_true_lang.js +5 -0
  65. package/dist/components/forms/auto-complete/RuiAutoComplete.vue_vue_type_script_setup_true_lang.js.map +1 -1
  66. package/dist/components/forms/auto-complete/RuiAutoCompleteOption.js.map +1 -1
  67. package/dist/components/forms/auto-complete/RuiAutoCompleteOption.vue.d.ts +2 -1
  68. package/dist/components/forms/auto-complete/RuiAutoCompleteOption.vue_vue_type_script_setup_true_lang.js.map +1 -1
  69. package/dist/components/forms/auto-complete/RuiAutoCompleteOptionList.js.map +1 -1
  70. package/dist/components/forms/auto-complete/RuiAutoCompleteOptionList.vue.d.ts +2 -2
  71. package/dist/components/forms/auto-complete/RuiAutoCompleteOptionList.vue_vue_type_script_setup_true_lang.js.map +1 -1
  72. package/dist/components/forms/auto-complete/auto-complete-props.d.ts +0 -1
  73. package/dist/components/forms/category-picker/RuiCategoryPicker.js.map +1 -1
  74. package/dist/components/forms/category-picker/RuiCategoryPicker.vue.d.ts +2 -1
  75. package/dist/components/forms/category-picker/RuiCategoryPicker.vue_vue_type_script_setup_true_lang.js.map +1 -1
  76. package/dist/components/forms/checkbox/RuiCheckbox.js.map +1 -1
  77. package/dist/components/forms/checkbox/RuiCheckbox.vue.d.ts +2 -1
  78. package/dist/components/forms/checkbox/RuiCheckbox.vue_vue_type_script_setup_true_lang.js +4 -1
  79. package/dist/components/forms/checkbox/RuiCheckbox.vue_vue_type_script_setup_true_lang.js.map +1 -1
  80. package/dist/components/forms/checkbox/checkbox-group/RuiCheckboxGroup.js.map +1 -1
  81. package/dist/components/forms/checkbox/checkbox-group/RuiCheckboxGroup.vue.d.ts +2 -1
  82. package/dist/components/forms/checkbox/checkbox-group/RuiCheckboxGroup.vue_vue_type_script_setup_true_lang.js.map +1 -1
  83. package/dist/components/forms/file-upload/RuiFileUpload.js.map +1 -1
  84. package/dist/components/forms/file-upload/RuiFileUpload.vue.d.ts +36 -29
  85. package/dist/components/forms/file-upload/RuiFileUpload.vue_vue_type_script_setup_true_lang.js +5 -0
  86. package/dist/components/forms/file-upload/RuiFileUpload.vue_vue_type_script_setup_true_lang.js.map +1 -1
  87. package/dist/components/forms/radio-button/radio/RuiRadio.js.map +1 -1
  88. package/dist/components/forms/radio-button/radio/RuiRadio.vue.d.ts +5 -3
  89. package/dist/components/forms/radio-button/radio/RuiRadio.vue_vue_type_script_setup_true_lang.js +7 -8
  90. package/dist/components/forms/radio-button/radio/RuiRadio.vue_vue_type_script_setup_true_lang.js.map +1 -1
  91. package/dist/components/forms/radio-button/radio-group/RuiRadioGroup.js.map +1 -1
  92. package/dist/components/forms/radio-button/radio-group/RuiRadioGroup.vue.d.ts +5 -3
  93. package/dist/components/forms/radio-button/radio-group/RuiRadioGroup.vue_vue_type_script_setup_true_lang.js +9 -10
  94. package/dist/components/forms/radio-button/radio-group/RuiRadioGroup.vue_vue_type_script_setup_true_lang.js.map +1 -1
  95. package/dist/components/forms/revealable-text-field/RuiRevealableTextField.js.map +1 -1
  96. package/dist/components/forms/revealable-text-field/RuiRevealableTextField.vue.d.ts +9 -2
  97. package/dist/components/forms/revealable-text-field/RuiRevealableTextField.vue_vue_type_script_setup_true_lang.js.map +1 -1
  98. package/dist/components/forms/select/RuiMenuSelect.js.map +1 -1
  99. package/dist/components/forms/select/RuiMenuSelect.vue.d.ts +10 -4
  100. package/dist/components/forms/select/RuiMenuSelect.vue_vue_type_script_setup_true_lang.js +5 -0
  101. package/dist/components/forms/select/RuiMenuSelect.vue_vue_type_script_setup_true_lang.js.map +1 -1
  102. package/dist/components/forms/select/RuiSimpleSelect.js.map +1 -1
  103. package/dist/components/forms/select/RuiSimpleSelect.vue.d.ts +22 -11
  104. package/dist/components/forms/select/RuiSimpleSelect.vue_vue_type_script_setup_true_lang.js.map +1 -1
  105. package/dist/components/forms/slider/RuiSlider.js.map +1 -1
  106. package/dist/components/forms/slider/RuiSlider.vue.d.ts +2 -1
  107. package/dist/components/forms/slider/RuiSlider.vue_vue_type_script_setup_true_lang.js.map +1 -1
  108. package/dist/components/forms/switch/RuiSwitch.js.map +1 -1
  109. package/dist/components/forms/switch/RuiSwitch.vue.d.ts +2 -1
  110. package/dist/components/forms/switch/RuiSwitch.vue_vue_type_script_setup_true_lang.js.map +1 -1
  111. package/dist/components/forms/text-area/RuiTextArea.js.map +1 -1
  112. package/dist/components/forms/text-area/RuiTextArea.vue.d.ts +3 -1
  113. package/dist/components/forms/text-area/RuiTextArea.vue_vue_type_script_setup_true_lang.js.map +1 -1
  114. package/dist/components/forms/text-field/RuiTextField.js.map +1 -1
  115. package/dist/components/forms/text-field/RuiTextField.vue.d.ts +3 -1
  116. package/dist/components/forms/text-field/RuiTextField.vue_vue_type_script_setup_true_lang.js.map +1 -1
  117. package/dist/components/icons/RuiIcon.js.map +1 -1
  118. package/dist/components/icons/RuiIcon.vue.d.ts +3 -1
  119. package/dist/components/icons/RuiIcon.vue_vue_type_script_setup_true_lang.js.map +1 -1
  120. package/dist/components/index.d.ts +2 -2
  121. package/dist/components/loaders/RuiSkeletonLoader.js.map +1 -1
  122. package/dist/components/loaders/RuiSkeletonLoader.vue.d.ts +3 -1
  123. package/dist/components/loaders/RuiSkeletonLoader.vue_vue_type_script_setup_true_lang.js.map +1 -1
  124. package/dist/components/logos/RuiLogo.js.map +1 -1
  125. package/dist/components/logos/RuiLogo.vue.d.ts +3 -1
  126. package/dist/components/logos/RuiLogo.vue_vue_type_script_setup_true_lang.js.map +1 -1
  127. package/dist/components/overlays/badge/RuiBadge.js.map +1 -1
  128. package/dist/components/overlays/badge/RuiBadge.vue.d.ts +3 -1
  129. package/dist/components/overlays/badge/RuiBadge.vue_vue_type_script_setup_true_lang.js.map +1 -1
  130. package/dist/components/overlays/bottom-sheet/RuiBottomSheet.js.map +1 -1
  131. package/dist/components/overlays/bottom-sheet/RuiBottomSheet.vue.d.ts +11 -5
  132. package/dist/components/overlays/bottom-sheet/RuiBottomSheet.vue_vue_type_script_setup_true_lang.js +6 -7
  133. package/dist/components/overlays/bottom-sheet/RuiBottomSheet.vue_vue_type_script_setup_true_lang.js.map +1 -1
  134. package/dist/components/overlays/dialog/RuiDialog.js.map +1 -1
  135. package/dist/components/overlays/dialog/RuiDialog.vue.d.ts +5 -3
  136. package/dist/components/overlays/dialog/RuiDialog.vue_vue_type_script_setup_true_lang.js.map +1 -1
  137. package/dist/components/overlays/menu/RuiMenu.js.map +1 -1
  138. package/dist/components/overlays/menu/RuiMenu.vue.d.ts +2 -1
  139. package/dist/components/overlays/menu/RuiMenu.vue_vue_type_script_setup_true_lang.js.map +1 -1
  140. package/dist/components/overlays/navigation-drawer/RuiNavigationDrawer.js.map +1 -1
  141. package/dist/components/overlays/navigation-drawer/RuiNavigationDrawer.vue.d.ts +2 -1
  142. package/dist/components/overlays/navigation-drawer/RuiNavigationDrawer.vue_vue_type_script_setup_true_lang.js.map +1 -1
  143. package/dist/components/overlays/notification/RuiNotification.js.map +1 -1
  144. package/dist/components/overlays/notification/RuiNotification.vue.d.ts +2 -1
  145. package/dist/components/overlays/notification/RuiNotification.vue_vue_type_script_setup_true_lang.js.map +1 -1
  146. package/dist/components/overlays/tooltip/RuiTooltip.js.map +1 -1
  147. package/dist/components/overlays/tooltip/RuiTooltip.vue.d.ts +4 -2
  148. package/dist/components/overlays/tooltip/RuiTooltip.vue_vue_type_script_setup_true_lang.js.map +1 -1
  149. package/dist/components/progress/RuiProgress.js.map +1 -1
  150. package/dist/components/progress/RuiProgress.vue.d.ts +3 -1
  151. package/dist/components/progress/RuiProgress.vue_vue_type_script_setup_true_lang.js.map +1 -1
  152. package/dist/components/steppers/RuiFooterStepper.js.map +1 -1
  153. package/dist/components/steppers/RuiFooterStepper.vue.d.ts +2 -1
  154. package/dist/components/steppers/RuiFooterStepper.vue_vue_type_script_setup_true_lang.js.map +1 -1
  155. package/dist/components/steppers/RuiStepper.js.map +1 -1
  156. package/dist/components/steppers/RuiStepper.vue.d.ts +3 -1
  157. package/dist/components/steppers/RuiStepper.vue_vue_type_script_setup_true_lang.js.map +1 -1
  158. package/dist/components/tables/RuiDataTable.js.map +1 -1
  159. package/dist/components/tables/RuiDataTable.vue.d.ts +14 -19
  160. package/dist/components/tables/RuiDataTable.vue_vue_type_script_setup_true_lang.js +25 -29
  161. package/dist/components/tables/RuiDataTable.vue_vue_type_script_setup_true_lang.js.map +1 -1
  162. package/dist/components/tables/RuiExpandButton.js.map +1 -1
  163. package/dist/components/tables/RuiExpandButton.vue.d.ts +3 -1
  164. package/dist/components/tables/RuiExpandButton.vue_vue_type_script_setup_true_lang.js.map +1 -1
  165. package/dist/components/tables/RuiTable.js.map +1 -1
  166. package/dist/components/tables/RuiTable.vue.d.ts +4 -2
  167. package/dist/components/tables/RuiTable.vue_vue_type_script_setup_true_lang.js.map +1 -1
  168. package/dist/components/tables/RuiTableEmptyState.js.map +1 -1
  169. package/dist/components/tables/RuiTableEmptyState.vue.d.ts +3 -1
  170. package/dist/components/tables/RuiTableEmptyState.vue_vue_type_script_setup_true_lang.js.map +1 -1
  171. package/dist/components/tables/RuiTableErrorState.js.map +1 -1
  172. package/dist/components/tables/RuiTableErrorState.vue.d.ts +4 -2
  173. package/dist/components/tables/RuiTableErrorState.vue_vue_type_script_setup_true_lang.js.map +1 -1
  174. package/dist/components/tables/RuiTableHead.js.map +1 -1
  175. package/dist/components/tables/RuiTableHead.vue.d.ts +3 -2
  176. package/dist/components/tables/RuiTableHead.vue_vue_type_script_setup_true_lang.js +3 -3
  177. package/dist/components/tables/RuiTableHead.vue_vue_type_script_setup_true_lang.js.map +1 -1
  178. package/dist/components/tables/RuiTableLoadingState.js.map +1 -1
  179. package/dist/components/tables/RuiTableLoadingState.vue.d.ts +3 -1
  180. package/dist/components/tables/RuiTableLoadingState.vue_vue_type_script_setup_true_lang.js.map +1 -1
  181. package/dist/components/tables/RuiTablePagination.js.map +1 -1
  182. package/dist/components/tables/RuiTablePagination.vue.d.ts +2 -1
  183. package/dist/components/tables/RuiTablePagination.vue_vue_type_script_setup_true_lang.js.map +1 -1
  184. package/dist/components/tables/data-table/RuiDataTableCell.js.map +1 -1
  185. package/dist/components/tables/data-table/RuiDataTableCell.vue_vue_type_script_setup_true_lang.js +2 -4
  186. package/dist/components/tables/data-table/RuiDataTableCell.vue_vue_type_script_setup_true_lang.js.map +1 -1
  187. package/dist/components/tables/data-table/RuiDataTableMobileSort.js.map +1 -1
  188. package/dist/components/tables/data-table/RuiDataTableMobileSort.vue.d.ts +1 -1
  189. package/dist/components/tables/data-table/RuiDataTableMobileSort.vue_vue_type_script_setup_true_lang.js +2 -3
  190. package/dist/components/tables/data-table/RuiDataTableMobileSort.vue_vue_type_script_setup_true_lang.js.map +1 -1
  191. package/dist/components/tables/data-table/context.d.ts +6 -6
  192. package/dist/components/tables/data-table/context.js +1 -1
  193. package/dist/components/tables/data-table/context.js.map +1 -1
  194. package/dist/components/tables/table-props.d.ts +9 -0
  195. package/dist/components/tables/table-props.js +13 -1
  196. package/dist/components/tables/table-props.js.map +1 -1
  197. package/dist/components/tabs/tab/RuiTab.js.map +1 -1
  198. package/dist/components/tabs/tab/RuiTab.vue.d.ts +4 -2
  199. package/dist/components/tabs/tab/RuiTab.vue_vue_type_script_setup_true_lang.js.map +1 -1
  200. package/dist/components/tabs/tab-item/RuiTabItem.js.map +1 -1
  201. package/dist/components/tabs/tab-item/RuiTabItem.vue.d.ts +3 -1
  202. package/dist/components/tabs/tab-item/RuiTabItem.vue_vue_type_script_setup_true_lang.js.map +1 -1
  203. package/dist/components/tabs/tab-items/RuiTabItems.js.map +1 -1
  204. package/dist/components/tabs/tab-items/RuiTabItems.vue.d.ts +5 -12
  205. package/dist/components/tabs/tab-items/RuiTabItems.vue_vue_type_script_setup_true_lang.js +8 -14
  206. package/dist/components/tabs/tab-items/RuiTabItems.vue_vue_type_script_setup_true_lang.js.map +1 -1
  207. package/dist/components/tabs/tabs/RuiTabs.js.map +1 -1
  208. package/dist/components/tabs/tabs/RuiTabs.vue.d.ts +26 -14
  209. package/dist/components/tabs/tabs/RuiTabs.vue_vue_type_script_setup_true_lang.js +11 -13
  210. package/dist/components/tabs/tabs/RuiTabs.vue_vue_type_script_setup_true_lang.js.map +1 -1
  211. package/dist/components/time-picker/RuiTimePicker.js.map +1 -1
  212. package/dist/components/time-picker/RuiTimePicker.vue.d.ts +2 -1
  213. package/dist/components/time-picker/RuiTimePicker.vue_vue_type_script_setup_true_lang.js.map +1 -1
  214. package/dist/composables/dropdown-menu.js.map +1 -1
  215. package/dist/composables/forms/auto-complete/search.js.map +1 -1
  216. package/dist/composables/forms/auto-complete/value.d.ts +1 -1
  217. package/dist/composables/forms/auto-complete/value.js.map +1 -1
  218. package/dist/composables/prop-model.d.ts +21 -0
  219. package/dist/composables/prop-model.js +33 -0
  220. package/dist/composables/prop-model.js.map +1 -0
  221. package/dist/composables/tables/data-table/columns.d.ts +2 -1
  222. package/dist/composables/tables/data-table/columns.js.map +1 -1
  223. package/dist/composables/tables/data-table/types.d.ts +35 -0
  224. package/dist/composables/tables/data-table/types.js.map +1 -1
  225. package/dist/composables/use-rui-i18n.d.ts +6 -3
  226. package/dist/composables/use-rui-i18n.js +1 -1
  227. package/dist/composables/use-rui-i18n.js.map +1 -1
  228. package/dist/index.d.ts +7 -1
  229. package/dist/index.js +14 -6
  230. package/dist/index.js.map +1 -1
  231. package/dist/types/attributes.d.ts +9 -0
  232. package/dist/utils/blockie.js +10 -9
  233. package/dist/utils/blockie.js.map +1 -1
  234. package/dist/web-types.json +280 -110
  235. package/package.json +3 -3
@@ -1 +1 @@
1
- {"version":3,"file":"RuiDialog.vue_vue_type_script_setup_true_lang.js","names":["$attrs","_useModel","_openBlock","_createElementBlock","_normalizeProps","_guardReactiveProps","_unref","_renderSlot","_createBlock","_Teleport","_mergeProps","_withKeys","_createVNode","_Transition","_withCtx","_normalizeClass","_withModifiers","_createCommentVNode","_normalizeStyle"],"sources":["../../../../src/components/overlays/dialog/RuiDialog.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport type { DialogSize } from '@/consts/tokens';\nimport type { VueClassValue } from '@/types/class-value';\nimport { ButtonGroupBoundary } from '@/components/buttons/button-group/button-group-context';\nimport { useDismissableOverlay } from '@/composables/overlay-stack';\nimport { useTimeoutManager } from '@/composables/timeout-manager';\nimport { getNonRootAttrs, getRootAttrs, transformPropsUnit } from '@/utils/helpers';\nimport { cn } from '@/utils/tv';\nimport { dialogStyles } from './dialog-styles';\n\nexport interface RuiDialogClassNames {\n root?: VueClassValue;\n content?: VueClassValue;\n}\n\nexport interface DialogProps {\n persistent?: boolean;\n width?: string | number;\n maxWidth?: string | number;\n /** A preset max width, `--rui-dialog-<size>`; an explicit `maxWidth` wins */\n size?: DialogSize;\n bottomSheet?: boolean;\n classNames?: RuiDialogClassNames;\n zIndex?: string | number;\n ariaLabel?: string;\n}\n\ndefineOptions({\n name: 'RuiDialog',\n inheritAttrs: false,\n});\n\nconst modelValue = defineModel<boolean>({ default: false });\n\nconst {\n persistent = false,\n width = '98%',\n maxWidth,\n size,\n bottomSheet = false,\n classNames,\n zIndex = 'var(--rui-z-dialog)',\n ariaLabel,\n} = defineProps<DialogProps>();\n\nconst emit = defineEmits<{\n 'closed': [];\n 'click:outside': [];\n 'click:esc': [];\n /**\n * The overlay stack asked this dialog to go, which is what a back gesture\n * reaches it as. Closes unless persistent, like escape does, so a dialog that\n * has to ask before discarding should bind `persistent` and answer here.\n */\n 'dismiss': [];\n}>();\n\ndefineSlots<{\n activator?: (props: { attrs: { onClick: () => void }; isOpen: boolean }) => any;\n default?: (props: { isOpen: boolean; close: () => void }) => any;\n}>();\n\nconst transitioning = ref<boolean>(false);\nconst contentRef = useTemplateRef<HTMLDivElement>('contentRef');\n\nconst leaveTimeout = useTimeoutManager();\n\nconst alive = computed<boolean>(() => get(modelValue) || get(transitioning));\n\nconst style = computed<{ width: string | undefined; maxWidth: string | undefined }>(() => ({\n width: transformPropsUnit(width),\n maxWidth: transformPropsUnit(maxWidth) ?? (size ? `var(--rui-dialog-${size})` : undefined),\n}));\n\nconst ui = computed<ReturnType<typeof dialogStyles>>(() => dialogStyles({ bottomSheet }));\n\nconst dialogAttrs: { onClick: () => void } = {\n onClick: toggle,\n};\n\nconst contentTransition = computed<Record<string, string>>(() => {\n if (!bottomSheet) {\n return {\n enterFromClass: 'opacity-0 scale-95',\n enterActiveClass: 'transition-all ease-out duration-200',\n enterToClass: 'opacity-100 scale-100',\n leaveFromClass: 'opacity-100 scale-100',\n leaveActiveClass: 'transition-all ease-in duration-150',\n leaveToClass: 'opacity-0 scale-95',\n };\n }\n\n return {\n enterFromClass: 'translate-y-full',\n enterActiveClass: 'transition-transform ease-out duration-300',\n enterToClass: 'translate-y-0',\n leaveFromClass: 'translate-y-0',\n leaveActiveClass: 'transition-transform ease-in duration-200',\n leaveToClass: 'translate-y-full',\n };\n});\n\nfunction toggle(): void {\n set(modelValue, !get(modelValue));\n}\n\nfunction close(): void {\n set(modelValue, false);\n}\n\n/**\n * Closes on Escape unless persistent, and reports the press as `click:esc`.\n *\n * @remarks\n * An Escape that arrives while an IME is composing belongs to the IME, which\n * cancels the candidate with it. The dialog leaves that key alone entirely: no\n * close, no `click:esc`, and no `stopPropagation`, so a search field inside the\n * dialog does not lose the dialog mid-word.\n */\nfunction onEscKeydown(event: KeyboardEvent): void {\n if (event.isComposing)\n return;\n\n event.stopPropagation();\n if (!persistent) {\n close();\n }\n emit('click:esc');\n}\n\nfunction onClickOutside(): void {\n if (!persistent) {\n close();\n }\n emit('click:outside');\n}\n\nfunction onDismiss(): void {\n if (!persistent) {\n close();\n }\n emit('dismiss');\n}\n\n/**\n * Registration follows `modelValue` alone, never `persistent`: a dialog that\n * turns persistent partway through its life has to stay in the stack and refuse\n * in `onDismiss`, or the gesture starts passing through exactly once there is\n * work to lose. A dialog playing its leave transition is already on its way out\n * and does not hold the stack.\n */\nuseDismissableOverlay(modelValue, onDismiss);\n\nfunction onLeaveComplete(): void {\n leaveTimeout.clear();\n if (get(transitioning)) {\n set(transitioning, false);\n emit('closed');\n }\n}\n\nwatch(modelValue, (value) => {\n if (!value) {\n set(transitioning, true);\n // Safety fallback if transitionend is not detected\n leaveTimeout.create(onLeaveComplete, 400);\n }\n});\n\nwatch(contentRef, (ref) => {\n if (ref) {\n nextTick(() => ref.focus());\n }\n else {\n onLeaveComplete();\n }\n});\n</script>\n\n<template>\n <div v-bind=\"getRootAttrs($attrs)\">\n <slot\n name=\"activator\"\n v-bind=\"{ attrs: dialogAttrs, isOpen: modelValue }\"\n />\n <Teleport to=\"body\">\n <div\n v-if=\"alive\"\n :class=\"ui.root({ class: cn(classNames?.root) })\"\n :style=\"{ zIndex }\"\n role=\"dialog\"\n aria-modal=\"true\"\n :aria-label=\"ariaLabel\"\n tabindex=\"0\"\n v-bind=\"getNonRootAttrs($attrs)\"\n @keydown.esc=\"onEscKeydown($event)\"\n >\n <Transition\n enter-from-class=\"opacity-0\"\n enter-active-class=\"transition-opacity ease-out duration-200\"\n enter-to-class=\"opacity-100\"\n leave-from-class=\"opacity-100\"\n leave-active-class=\"transition-opacity ease-in duration-150\"\n leave-to-class=\"opacity-0\"\n >\n <div\n v-if=\"modelValue\"\n data-id=\"overlay\"\n :class=\"ui.overlay()\"\n @click.stop=\"onClickOutside()\"\n />\n </Transition>\n <Transition\n v-bind=\"contentTransition\"\n @after-leave=\"onLeaveComplete()\"\n >\n <div\n v-if=\"modelValue\"\n ref=\"contentRef\"\n data-id=\"content\"\n :style=\"style\"\n tabindex=\"0\"\n :data-bottom-sheet=\"bottomSheet || undefined\"\n :class=\"ui.content({ class: cn(classNames?.content) })\"\n >\n <ButtonGroupBoundary>\n <slot v-bind=\"{ isOpen: modelValue, close }\" />\n </ButtonGroupBoundary>\n </div>\n </Transition>\n </div>\n </Teleport>\n </div>\n</template>\n"],"mappings":"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"}
1
+ {"version":3,"file":"RuiDialog.vue_vue_type_script_setup_true_lang.js","names":["$attrs","_useModel","_openBlock","_createElementBlock","_normalizeProps","_guardReactiveProps","_unref","_renderSlot","_createBlock","_Teleport","_mergeProps","_withKeys","_createVNode","_Transition","_withCtx","_normalizeClass","_withModifiers","_createCommentVNode","_normalizeStyle"],"sources":["../../../../src/components/overlays/dialog/RuiDialog.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport type { HTMLAttributes } from 'vue';\nimport type { DialogSize } from '@/consts/tokens';\nimport type { VueClassValue } from '@/types/class-value';\nimport { ButtonGroupBoundary } from '@/components/buttons/button-group/button-group-context';\nimport { useDismissableOverlay } from '@/composables/overlay-stack';\nimport { useTimeoutManager } from '@/composables/timeout-manager';\nimport { getNonRootAttrs, getRootAttrs, transformPropsUnit } from '@/utils/helpers';\nimport { cn } from '@/utils/tv';\nimport { dialogStyles } from './dialog-styles';\n\nexport interface RuiDialogClassNames {\n root?: VueClassValue;\n content?: VueClassValue;\n}\n\nexport interface DialogProps {\n persistent?: boolean;\n width?: string | number;\n maxWidth?: string | number;\n /** A preset max width, `--rui-dialog-<size>`; an explicit `maxWidth` wins */\n size?: DialogSize;\n bottomSheet?: boolean;\n classNames?: RuiDialogClassNames;\n zIndex?: string | number;\n ariaLabel?: string;\n}\n\nexport interface DialogSlots {\n activator?: (props: { attrs: { onClick: () => void }; isOpen: boolean }) => any;\n default?: (props: { isOpen: boolean; close: () => void }) => any;\n}\n\ndefineOptions({\n name: 'RuiDialog',\n inheritAttrs: false,\n});\n\nconst modelValue = defineModel<boolean>({ default: false });\n\nconst {\n persistent = false,\n width = '98%',\n maxWidth,\n size,\n bottomSheet = false,\n classNames,\n zIndex = 'var(--rui-z-dialog)',\n ariaLabel,\n} = defineProps<DialogProps & /* @vue-ignore */ Omit<HTMLAttributes, keyof DialogProps>>();\n\nconst emit = defineEmits<{\n 'closed': [];\n 'click:outside': [];\n 'click:esc': [];\n /**\n * The overlay stack asked this dialog to go, which is what a back gesture\n * reaches it as. Closes unless persistent, like escape does, so a dialog that\n * has to ask before discarding should bind `persistent` and answer here.\n */\n 'dismiss': [];\n}>();\n\ndefineSlots<DialogSlots>();\n\nconst transitioning = ref<boolean>(false);\nconst contentRef = useTemplateRef<HTMLDivElement>('contentRef');\n\nconst leaveTimeout = useTimeoutManager();\n\nconst alive = computed<boolean>(() => get(modelValue) || get(transitioning));\n\nconst style = computed<{ width: string | undefined; maxWidth: string | undefined }>(() => ({\n width: transformPropsUnit(width),\n maxWidth: transformPropsUnit(maxWidth) ?? (size ? `var(--rui-dialog-${size})` : undefined),\n}));\n\nconst ui = computed<ReturnType<typeof dialogStyles>>(() => dialogStyles({ bottomSheet }));\n\nconst dialogAttrs: { onClick: () => void } = {\n onClick: toggle,\n};\n\nconst contentTransition = computed<Record<string, string>>(() => {\n if (!bottomSheet) {\n return {\n enterFromClass: 'opacity-0 scale-95',\n enterActiveClass: 'transition-all ease-out duration-200',\n enterToClass: 'opacity-100 scale-100',\n leaveFromClass: 'opacity-100 scale-100',\n leaveActiveClass: 'transition-all ease-in duration-150',\n leaveToClass: 'opacity-0 scale-95',\n };\n }\n\n return {\n enterFromClass: 'translate-y-full',\n enterActiveClass: 'transition-transform ease-out duration-300',\n enterToClass: 'translate-y-0',\n leaveFromClass: 'translate-y-0',\n leaveActiveClass: 'transition-transform ease-in duration-200',\n leaveToClass: 'translate-y-full',\n };\n});\n\nfunction toggle(): void {\n set(modelValue, !get(modelValue));\n}\n\nfunction close(): void {\n set(modelValue, false);\n}\n\n/**\n * Closes on Escape unless persistent, and reports the press as `click:esc`.\n *\n * @remarks\n * An Escape that arrives while an IME is composing belongs to the IME, which\n * cancels the candidate with it. The dialog leaves that key alone entirely: no\n * close, no `click:esc`, and no `stopPropagation`, so a search field inside the\n * dialog does not lose the dialog mid-word.\n */\nfunction onEscKeydown(event: KeyboardEvent): void {\n if (event.isComposing)\n return;\n\n event.stopPropagation();\n if (!persistent) {\n close();\n }\n emit('click:esc');\n}\n\nfunction onClickOutside(): void {\n if (!persistent) {\n close();\n }\n emit('click:outside');\n}\n\nfunction onDismiss(): void {\n if (!persistent) {\n close();\n }\n emit('dismiss');\n}\n\n/**\n * Registration follows `modelValue` alone, never `persistent`: a dialog that\n * turns persistent partway through its life has to stay in the stack and refuse\n * in `onDismiss`, or the gesture starts passing through exactly once there is\n * work to lose. A dialog playing its leave transition is already on its way out\n * and does not hold the stack.\n */\nuseDismissableOverlay(modelValue, onDismiss);\n\nfunction onLeaveComplete(): void {\n leaveTimeout.clear();\n if (get(transitioning)) {\n set(transitioning, false);\n emit('closed');\n }\n}\n\nwatch(modelValue, (value) => {\n if (!value) {\n set(transitioning, true);\n // Safety fallback if transitionend is not detected\n leaveTimeout.create(onLeaveComplete, 400);\n }\n});\n\nwatch(contentRef, (ref) => {\n if (ref) {\n nextTick(() => ref.focus());\n }\n else {\n onLeaveComplete();\n }\n});\n</script>\n\n<template>\n <div v-bind=\"getRootAttrs($attrs)\">\n <slot\n name=\"activator\"\n v-bind=\"{ attrs: dialogAttrs, isOpen: modelValue }\"\n />\n <Teleport to=\"body\">\n <div\n v-if=\"alive\"\n :class=\"ui.root({ class: cn(classNames?.root) })\"\n :style=\"{ zIndex }\"\n role=\"dialog\"\n aria-modal=\"true\"\n :aria-label=\"ariaLabel\"\n tabindex=\"0\"\n v-bind=\"getNonRootAttrs($attrs)\"\n @keydown.esc=\"onEscKeydown($event)\"\n >\n <Transition\n enter-from-class=\"opacity-0\"\n enter-active-class=\"transition-opacity ease-out duration-200\"\n enter-to-class=\"opacity-100\"\n leave-from-class=\"opacity-100\"\n leave-active-class=\"transition-opacity ease-in duration-150\"\n leave-to-class=\"opacity-0\"\n >\n <div\n v-if=\"modelValue\"\n data-id=\"overlay\"\n :class=\"ui.overlay()\"\n @click.stop=\"onClickOutside()\"\n />\n </Transition>\n <Transition\n v-bind=\"contentTransition\"\n @after-leave=\"onLeaveComplete()\"\n >\n <div\n v-if=\"modelValue\"\n ref=\"contentRef\"\n data-id=\"content\"\n :style=\"style\"\n tabindex=\"0\"\n :data-bottom-sheet=\"bottomSheet || undefined\"\n :class=\"ui.content({ class: cn(classNames?.content) })\"\n >\n <ButtonGroupBoundary>\n <slot v-bind=\"{ isOpen: modelValue, close }\" />\n </ButtonGroupBoundary>\n </div>\n </Transition>\n </div>\n </Teleport>\n </div>\n</template>\n"],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"RuiMenu.js","names":["_sfc_main"],"sources":["../../../../src/components/overlays/menu/RuiMenu.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport type { Reactive, Ref, WatchHandle } from 'vue';\nimport type { VueClassValue } from '@/types/class-value';\nimport { ButtonGroupBoundary } from '@/components/buttons/button-group/button-group-context';\nimport RuiFormTextDetail from '@/components/helpers/RuiFormTextDetail.vue';\nimport { type FloatingOptions, useFloating, type UseFloatingReturn } from '@/composables/floating';\nimport { containsMessage, type FormDetails } from '@/utils/form-text-detail';\nimport { cn } from '@/utils/tv';\nimport { menuStyles } from './menu-styles';\n\ninterface BaseMenuAttrs { onMouseover?: () => void; onMouseleave?: () => void }\n\n/**\n * What the activator slot binds onto its trigger. The ARIA keys belong on an\n * element that can carry them (a button, link or combobox), never on a plain\n * `div`; an activator that sets its own ARIA takes `activatorHandlers(attrs)`.\n */\ninterface MenuAttrs extends BaseMenuAttrs {\n 'onClick'?: () => void;\n 'aria-haspopup': RuiMenuRole | 'true';\n 'aria-expanded': boolean;\n 'aria-controls'?: string;\n}\n\nexport interface RuiMenuClassNames {\n root?: VueClassValue;\n wrapper?: VueClassValue;\n menu?: VueClassValue;\n /** Overrides applied to the popover content box (e.g. to drop its default padding). */\n content?: VueClassValue;\n /** Overrides applied to the hint and messages under the activator. */\n details?: VueClassValue;\n}\n\n/**\n * Roles a popover container may take. These are the values `aria-haspopup`\n * accepts, which keeps the activator and the popover in agreement.\n */\nexport type RuiMenuRole = 'menu' | 'listbox' | 'tree' | 'grid' | 'dialog';\n\nexport interface MenuProps {\n openOnHover?: boolean;\n fullWidth?: boolean;\n disabled?: boolean;\n openDelay?: number;\n closeDelay?: number;\n options?: FloatingOptions;\n classNames?: RuiMenuClassNames;\n closeOnContentClick?: boolean;\n persistOnActivatorClick?: boolean;\n hint?: string;\n errorMessages?: string | string[];\n successMessages?: string | string[];\n showDetails?: boolean;\n /** With `showDetails`: `reserve` keeps the line while empty (default), `auto` takes no space until there is a message. */\n details?: Exclude<FormDetails, 'hidden'>;\n dense?: boolean;\n /**\n * Keeps the menu open through the interactions that would otherwise dismiss\n * it: a click outside and an Escape press. A programmatic close (`v-model`\n * set to `false`) still applies.\n */\n persistent?: boolean;\n disableAutoFocus?: boolean;\n /**\n * Optional external element to anchor the menu to, instead of the\n * activator slot's wrapper. When set, the menu's position is computed\n * against this element.\n */\n anchorEl?: HTMLElement;\n /**\n * Role of the teleported popover. Defaults to `menu`, which is correct when\n * the content is made of `menuitem`s. Set it to `listbox` (or `tree`, `grid`,\n * `dialog`) when the content follows a different ARIA model, e.g. a selection\n * list opened by a `combobox`. The activator's `aria-haspopup` follows it.\n */\n role?: RuiMenuRole;\n /**\n * Accessible name of the teleported popover. A `dialog` popover needs one;\n * the other roles take it from their activator or options.\n */\n menuLabel?: string;\n /**\n * Defers the popover's setup (its positioning, the activator's size\n * observer and the click-outside listeners) to first use: a click or a\n * context menu on the activator, a hover with `openOnHover`, or the model\n * turning `true`. Until then the menu renders its root, the wrapper and the\n * activator, the same elements it keeps afterwards, so a table with a menu\n * on every row pays for the menus that are opened. Read at mount.\n */\n lazy?: boolean;\n}\n\n/** What the menu sets up at mount, or on first use when `lazy`, with its refs unwrapped. */\ntype MenuSetup = Reactive<{\n floating: UseFloatingReturn;\n width: Readonly<Ref<number>>;\n}>;\n\ndefineOptions({\n name: 'RuiMenu',\n});\n\nconst modelValue = defineModel<boolean>({ default: false });\n\nconst {\n openOnHover = false,\n disabled = false,\n fullWidth = false,\n openDelay = 0,\n closeDelay = 0,\n options,\n classNames,\n closeOnContentClick = false,\n persistOnActivatorClick = false,\n hint,\n errorMessages = [],\n successMessages = [],\n showDetails = false,\n details = 'reserve',\n dense = false,\n persistent = false,\n disableAutoFocus = false,\n anchorEl,\n role = 'menu',\n menuLabel,\n lazy = false,\n} = defineProps<MenuProps>();\n\ndefineSlots<{\n activator?: (props: {\n // An inline type literal, so callers can pass it on as `Record<string, unknown>`\n attrs: {\n 'onMouseover'?: () => void;\n 'onMouseleave'?: () => void;\n 'onClick'?: () => void;\n 'aria-haspopup': RuiMenuRole | 'true';\n 'aria-expanded': boolean;\n 'aria-controls'?: string;\n };\n open: boolean;\n disabled: boolean;\n hasError: boolean;\n hasSuccess: boolean;\n }) => any;\n default?: (props: { width: number }) => any;\n /** Rendered above the activator, outside the element the menu positions against. */\n label?: () => any;\n}>();\n\nconst click = ref<boolean>(false);\nconst activator = useTemplateRef<HTMLElement>('activator');\nconst menu = useTemplateRef<HTMLElement>('menu');\nconst menuContent = useTemplateRef<HTMLElement>('menuContent');\nconst menuId = useId();\nconst instance = getCurrentInstance();\n// Owned by this component, so whatever the setup starts stops on unmount even when it ran after mount\nconst setupScope = effectScope();\nconst menuSetup = shallowRef<MenuSetup>();\nlet stopSetUpOnModel: WatchHandle | undefined;\n\nconst FOCUSABLE_ELEMENTS_SELECTOR =\n 'button, [href], input, select, textarea, [tabindex]:not([tabindex=\"-1\"])';\n\n// Only the two flags, not the formatted lists useFormTextDetail builds, since a table may hold hundreds of menus\nconst hasError = computed<boolean>(() => containsMessage(errorMessages));\nconst hasSuccess = computed<boolean>(() => containsMessage(successMessages));\n\nconst ui = computed<ReturnType<typeof menuStyles>>(() => menuStyles({\n fullWidth,\n dense,\n}));\n\nconst open = computed<boolean>(() => get(menuSetup)?.floating.open ?? false);\nconst visible = computed<boolean>(() => get(menuSetup)?.floating.visible ?? false);\n\n/**\n * The activator attributes.\n *\n * This and the computed below it must return the same object shape from every\n * branch. Otherwise vue-tsc infers the slot's `attrs` type as a discriminated\n * union where each key is either all defined or all undefined, which breaks\n * consumer code typing its own `attrs` handler with individually optional\n * keys.\n */\nconst baseMenuAttrs = computed<BaseMenuAttrs>(() => {\n const clickVal = get(click);\n return {\n onMouseover: disabled\n ? undefined\n : () => {\n if (openOnHover)\n setUp()?.onOpen();\n },\n onMouseleave: disabled\n ? undefined\n : () => {\n if (openOnHover && !clickVal)\n activeFloating()?.onClose();\n },\n };\n});\n\nconst menuAttrs = computed<MenuAttrs>(() => ({\n ...get(baseMenuAttrs),\n 'onClick': disabled ? undefined : checkClick,\n // `aria-haspopup=\"true\"` means `\"menu\"`, and the default keeps emitting `true` for existing callers\n 'aria-haspopup': role === 'menu' ? 'true' : role,\n 'aria-expanded': get(open),\n // Only while the popover is in the DOM, so the reference never points at a missing element\n 'aria-controls': get(visible) ? menuId : undefined,\n}));\n\n/**\n * Sets a lazy menu up on its first use, on the wrapper so that it covers an\n * activator that opens the menu through the model rather than through\n * `attrs`. Hover and focus are left out: a cursor resting over a scrolling\n * table or Tab moving down it would set up every row it passes. They stay\n * after setup, where `setUp` only hands back what it already made.\n */\nconst firstUseListeners = { click: setUp, contextmenu: setUp };\n\n/**\n * Sets the popover up once and hands back its floating state. It runs at\n * mount, or for a `lazy` menu on first use, which can be after mount and\n * inside another component's lifecycle hook, so what it starts must not\n * attach itself to the current instance.\n */\nfunction setUp(): MenuSetup['floating'] | undefined {\n if (setupScope.active && !get(menuSetup)) {\n set(menuSetup, setupScope.run(createSetup));\n stopSetUpOnModel?.();\n }\n return activeFloating();\n}\n\n/**\n * The floating state while the menu is alive. An event can still reach the\n * activator after unmount, and must not start timers on a stopped menu.\n */\nfunction activeFloating(): MenuSetup['floating'] | undefined {\n return setupScope.active ? get(menuSetup)?.floating : undefined;\n}\n\n/** An element's content-box width, the box its resize observer reports. */\nfunction contentWidth(element: HTMLElement | null): number {\n if (!element)\n return 0;\n\n const style = getComputedStyle(element);\n const edges = [style.paddingLeft, style.paddingRight, style.borderLeftWidth, style.borderRightWidth];\n return edges.reduce((width, edge) => width - (Number.parseFloat(edge) || 0), element.offsetWidth);\n}\n\nfunction createSetup(): MenuSetup {\n const floating = useFloating(\n () => options ?? {},\n () => disabled,\n () => openDelay,\n () => closeDelay,\n () => anchorEl ?? get(activator) ?? undefined,\n menu,\n );\n\n const width = shallowRef<number>(0);\n const readWidth = (): void => set(width, contentWidth(get(activator)));\n useResizeObserver(activator, ([entry]) => {\n if (entry)\n set(width, entry.contentRect.width);\n });\n // Only the menu's own setup waits for its mount; a later one may run inside another component's hook\n if (instance?.isMounted)\n readWidth();\n else\n onMounted(readWidth);\n\n // Immediate, so a model that is already `true` at setup opens the menu\n watch(modelValue, (value) => {\n if (get(floating.open) === value)\n return;\n\n if (value) {\n floating.onOpen();\n set(click, true);\n }\n else {\n onLeave();\n }\n }, { immediate: true });\n\n watch(floating.open, (isOpen) => {\n set(modelValue, isOpen);\n if (isOpen) {\n focusMenu();\n }\n });\n\n onClickOutside(menu, () => {\n if (get(floating.open) && !persistent)\n onLeave();\n }, { ignore: [activator] });\n\n return reactive({ floating, width });\n}\n\n/**\n * Moves focus into the open menu without scrolling the page. A menu taller than the space below its\n * activator would otherwise make the browser scroll the whole document to reveal the focused\n * container, sliding the page out from under the activator.\n */\nfunction focusOnContent() {\n const content = get(menuContent);\n if (!content)\n return;\n\n content.focus({ preventScroll: true });\n}\n\nfunction focusMenu(): void {\n if (disableAutoFocus)\n return;\n\n nextTick(() => focusOnContent());\n}\n\n/** Hands focus back to the activator on close, likewise without scrolling to it. */\nfunction focusOnActivator() {\n const activatorEl = get(activator);\n if (!activatorEl) {\n return;\n }\n const focusableEl = activatorEl.querySelector<HTMLElement>(FOCUSABLE_ELEMENTS_SELECTOR);\n if (focusableEl) {\n focusableEl.focus({ preventScroll: true });\n }\n}\n\nfunction onLeave(event?: KeyboardEvent): void {\n const floating = activeFloating();\n if (!floating?.open)\n return;\n floating.onClose();\n set(click, false);\n event?.stopPropagation();\n\n // Return focus to activator when menu closes\n if (disableAutoFocus) {\n return;\n }\n\n nextTick(() => focusOnActivator());\n}\n\n/**\n * `persistent` blocks the outside interactions that would close the menu, and\n * Escape is one of them, which is how `RuiDialog` and `RuiBottomSheet` already\n * read it. The guard sits here rather than in `onLeave`, because `onLeave`\n * also runs for a programmatic close through `v-model`, which must keep\n * working.\n *\n * A persistent menu leaves the key alone instead of swallowing it, so an inner\n * popover can close on Escape while the menu stays open, and an ancestor still\n * sees a key nothing consumed.\n *\n * Escape is swallowed only while the menu is open and not persistent\n * (`onLeave` stops the event itself); a closed or persistent menu must let it\n * through, or a consumer that closes its own editor on Escape never sees the\n * key. The root element listens for it.\n *\n * An Escape that arrives while an IME is composing belongs to the IME, which\n * cancels the candidate with it, so the menu leaves it alone the same way: a\n * search field inside the menu would otherwise lose the whole menu mid-word.\n */\nfunction onEscape(event: KeyboardEvent): void {\n if (persistent || event.isComposing)\n return;\n\n onLeave(event);\n}\n\nfunction checkClick(): void {\n const floating = setUp();\n if (!floating)\n return;\n\n if (floating.open && get(click)) {\n if (!persistOnActivatorClick)\n onLeave();\n }\n else {\n floating.onOpen();\n set(click, true);\n }\n}\n\n// The setup's own watcher opens it; a disabled menu stays closed and unset, as an eager one stays closed\nif (!lazy || (get(modelValue) && !disabled)) {\n setUp();\n}\nelse {\n stopSetUpOnModel = watch(modelValue, (value) => {\n if (value && !disabled)\n setUp();\n });\n}\n</script>\n\n<template>\n <div\n :class=\"classNames?.root\"\n @keydown.esc=\"onEscape($event)\"\n >\n <slot name=\"label\" />\n <div\n ref=\"activator\"\n :class=\"ui.wrapper({ class: cn(classNames?.wrapper) })\"\n :data-menu-disabled=\"disabled\"\n v-on=\"lazy && !disabled ? firstUseListeners : {}\"\n >\n <slot\n name=\"activator\"\n v-bind=\"{ attrs: menuAttrs, open, disabled, hasError, hasSuccess }\"\n />\n </div>\n <Teleport\n v-if=\"!disabled && menuSetup\"\n to=\"body\"\n >\n <div\n v-if=\"visible\"\n :id=\"menuId\"\n ref=\"menu\"\n :class=\"ui.popover({ class: cn(classNames?.menu) })\"\n :role=\"role\"\n :aria-label=\"menuLabel\"\n :data-placement=\"menuSetup.floating.currentPlacement\"\n @click=\"closeOnContentClick ? onLeave() : undefined\"\n @keydown.esc=\"onEscape($event)\"\n >\n <TransitionGroup\n enter-active-class=\"transition ease-out duration-200\"\n enter-from-class=\"opacity-0 translate-y-1\"\n enter-to-class=\"opacity-100 translate-y-0\"\n leave-active-class=\"transition ease-in duration-150\"\n leave-from-class=\"opacity-100 translate-y-0\"\n leave-to-class=\"opacity-0 translate-y-1\"\n @before-enter=\"menuSetup?.floating.updatePosition()\"\n @after-leave=\"menuSetup?.floating.leavePending ? menuSetup.floating.onLeaveComplete() : undefined\"\n @before-leave=\"menuSetup?.floating.onLeavePending()\"\n >\n <div\n v-if=\"open\"\n ref=\"menuContent\"\n key=\"menu\"\n data-id=\"content\"\n :class=\"ui.content({ class: cn(classNames?.content) })\"\n tabindex=\"-1\"\n v-bind=\"baseMenuAttrs\"\n >\n <ButtonGroupBoundary>\n <slot v-bind=\"{ width: menuSetup.width }\" />\n </ButtonGroupBoundary>\n </div>\n </TransitionGroup>\n </div>\n </Teleport>\n <RuiFormTextDetail\n v-if=\"showDetails\"\n :details=\"details\"\n :class=\"ui.details({ class: cn(classNames?.details) })\"\n :error-messages=\"errorMessages\"\n :success-messages=\"successMessages\"\n :hint=\"hint\"\n />\n </div>\n</template>\n"],"mappings":""}
1
+ {"version":3,"file":"RuiMenu.js","names":["_sfc_main"],"sources":["../../../../src/components/overlays/menu/RuiMenu.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport type { HTMLAttributes, Reactive, Ref, WatchHandle } from 'vue';\nimport type { VueClassValue } from '@/types/class-value';\nimport { ButtonGroupBoundary } from '@/components/buttons/button-group/button-group-context';\nimport RuiFormTextDetail from '@/components/helpers/RuiFormTextDetail.vue';\nimport { type FloatingOptions, useFloating, type UseFloatingReturn } from '@/composables/floating';\nimport { containsMessage, type FormDetails } from '@/utils/form-text-detail';\nimport { cn } from '@/utils/tv';\nimport { menuStyles } from './menu-styles';\n\ninterface BaseMenuAttrs { onMouseover?: () => void; onMouseleave?: () => void }\n\n/**\n * What the activator slot binds onto its trigger. The ARIA keys belong on an\n * element that can carry them (a button, link or combobox), never on a plain\n * `div`; an activator that sets its own ARIA takes `activatorHandlers(attrs)`.\n */\ninterface MenuAttrs extends BaseMenuAttrs {\n 'onClick'?: () => void;\n 'aria-haspopup': RuiMenuRole | 'true';\n 'aria-expanded': boolean;\n 'aria-controls'?: string;\n}\n\nexport interface RuiMenuClassNames {\n root?: VueClassValue;\n wrapper?: VueClassValue;\n menu?: VueClassValue;\n /** Overrides applied to the popover content box (e.g. to drop its default padding). */\n content?: VueClassValue;\n /** Overrides applied to the hint and messages under the activator. */\n details?: VueClassValue;\n}\n\n/**\n * Roles a popover container may take. These are the values `aria-haspopup`\n * accepts, which keeps the activator and the popover in agreement.\n */\nexport type RuiMenuRole = 'menu' | 'listbox' | 'tree' | 'grid' | 'dialog';\n\nexport interface MenuProps {\n openOnHover?: boolean;\n fullWidth?: boolean;\n disabled?: boolean;\n openDelay?: number;\n closeDelay?: number;\n options?: FloatingOptions;\n classNames?: RuiMenuClassNames;\n closeOnContentClick?: boolean;\n persistOnActivatorClick?: boolean;\n hint?: string;\n errorMessages?: string | string[];\n successMessages?: string | string[];\n showDetails?: boolean;\n /** With `showDetails`: `reserve` keeps the line while empty (default), `auto` takes no space until there is a message. */\n details?: Exclude<FormDetails, 'hidden'>;\n dense?: boolean;\n /**\n * Keeps the menu open through the interactions that would otherwise dismiss\n * it: a click outside and an Escape press. A programmatic close (`v-model`\n * set to `false`) still applies.\n */\n persistent?: boolean;\n disableAutoFocus?: boolean;\n /**\n * Optional external element to anchor the menu to, instead of the\n * activator slot's wrapper. When set, the menu's position is computed\n * against this element.\n */\n anchorEl?: HTMLElement;\n /**\n * Role of the teleported popover. Defaults to `menu`, which is correct when\n * the content is made of `menuitem`s. Set it to `listbox` (or `tree`, `grid`,\n * `dialog`) when the content follows a different ARIA model, e.g. a selection\n * list opened by a `combobox`. The activator's `aria-haspopup` follows it.\n */\n role?: RuiMenuRole;\n /**\n * Accessible name of the teleported popover. A `dialog` popover needs one;\n * the other roles take it from their activator or options.\n */\n menuLabel?: string;\n /**\n * Defers the popover's setup (its positioning, the activator's size\n * observer and the click-outside listeners) to first use: a click or a\n * context menu on the activator, a hover with `openOnHover`, or the model\n * turning `true`. Until then the menu renders its root, the wrapper and the\n * activator, the same elements it keeps afterwards, so a table with a menu\n * on every row pays for the menus that are opened. Read at mount.\n */\n lazy?: boolean;\n}\n\n/** What the menu sets up at mount, or on first use when `lazy`, with its refs unwrapped. */\ntype MenuSetup = Reactive<{\n floating: UseFloatingReturn;\n width: Readonly<Ref<number>>;\n}>;\n\ndefineOptions({\n name: 'RuiMenu',\n});\n\nconst modelValue = defineModel<boolean>({ default: false });\n\nconst {\n openOnHover = false,\n disabled = false,\n fullWidth = false,\n openDelay = 0,\n closeDelay = 0,\n options,\n classNames,\n closeOnContentClick = false,\n persistOnActivatorClick = false,\n hint,\n errorMessages = [],\n successMessages = [],\n showDetails = false,\n details = 'reserve',\n dense = false,\n persistent = false,\n disableAutoFocus = false,\n anchorEl,\n role = 'menu',\n menuLabel,\n lazy = false,\n} = defineProps<MenuProps & /* @vue-ignore */ Omit<HTMLAttributes, keyof MenuProps>>();\n\ndefineSlots<{\n activator?: (props: {\n // An inline type literal, so callers can pass it on as `Record<string, unknown>`\n attrs: {\n 'onMouseover'?: () => void;\n 'onMouseleave'?: () => void;\n 'onClick'?: () => void;\n 'aria-haspopup': RuiMenuRole | 'true';\n 'aria-expanded': boolean;\n 'aria-controls'?: string;\n };\n open: boolean;\n disabled: boolean;\n hasError: boolean;\n hasSuccess: boolean;\n }) => any;\n default?: (props: { width: number }) => any;\n /** Rendered above the activator, outside the element the menu positions against. */\n label?: () => any;\n}>();\n\nconst click = ref<boolean>(false);\nconst activator = useTemplateRef<HTMLElement>('activator');\nconst menu = useTemplateRef<HTMLElement>('menu');\nconst menuContent = useTemplateRef<HTMLElement>('menuContent');\nconst menuId = useId();\nconst instance = getCurrentInstance();\n// Owned by this component, so whatever the setup starts stops on unmount even when it ran after mount\nconst setupScope = effectScope();\nconst menuSetup = shallowRef<MenuSetup>();\nlet stopSetUpOnModel: WatchHandle | undefined;\n\nconst FOCUSABLE_ELEMENTS_SELECTOR =\n 'button, [href], input, select, textarea, [tabindex]:not([tabindex=\"-1\"])';\n\n// Only the two flags, not the formatted lists useFormTextDetail builds, since a table may hold hundreds of menus\nconst hasError = computed<boolean>(() => containsMessage(errorMessages));\nconst hasSuccess = computed<boolean>(() => containsMessage(successMessages));\n\nconst ui = computed<ReturnType<typeof menuStyles>>(() => menuStyles({\n fullWidth,\n dense,\n}));\n\nconst open = computed<boolean>(() => get(menuSetup)?.floating.open ?? false);\nconst visible = computed<boolean>(() => get(menuSetup)?.floating.visible ?? false);\n\n/**\n * The activator attributes.\n *\n * This and the computed below it must return the same object shape from every\n * branch. Otherwise vue-tsc infers the slot's `attrs` type as a discriminated\n * union where each key is either all defined or all undefined, which breaks\n * consumer code typing its own `attrs` handler with individually optional\n * keys.\n */\nconst baseMenuAttrs = computed<BaseMenuAttrs>(() => {\n const clickVal = get(click);\n return {\n onMouseover: disabled\n ? undefined\n : () => {\n if (openOnHover)\n setUp()?.onOpen();\n },\n onMouseleave: disabled\n ? undefined\n : () => {\n if (openOnHover && !clickVal)\n activeFloating()?.onClose();\n },\n };\n});\n\nconst menuAttrs = computed<MenuAttrs>(() => ({\n ...get(baseMenuAttrs),\n 'onClick': disabled ? undefined : checkClick,\n // `aria-haspopup=\"true\"` means `\"menu\"`, and the default keeps emitting `true` for existing callers\n 'aria-haspopup': role === 'menu' ? 'true' : role,\n 'aria-expanded': get(open),\n // Only while the popover is in the DOM, so the reference never points at a missing element\n 'aria-controls': get(visible) ? menuId : undefined,\n}));\n\n/**\n * Sets a lazy menu up on its first use, on the wrapper so that it covers an\n * activator that opens the menu through the model rather than through\n * `attrs`. Hover and focus are left out: a cursor resting over a scrolling\n * table or Tab moving down it would set up every row it passes. They stay\n * after setup, where `setUp` only hands back what it already made.\n */\nconst firstUseListeners = { click: setUp, contextmenu: setUp };\n\n/**\n * Sets the popover up once and hands back its floating state. It runs at\n * mount, or for a `lazy` menu on first use, which can be after mount and\n * inside another component's lifecycle hook, so what it starts must not\n * attach itself to the current instance.\n */\nfunction setUp(): MenuSetup['floating'] | undefined {\n if (setupScope.active && !get(menuSetup)) {\n set(menuSetup, setupScope.run(createSetup));\n stopSetUpOnModel?.();\n }\n return activeFloating();\n}\n\n/**\n * The floating state while the menu is alive. An event can still reach the\n * activator after unmount, and must not start timers on a stopped menu.\n */\nfunction activeFloating(): MenuSetup['floating'] | undefined {\n return setupScope.active ? get(menuSetup)?.floating : undefined;\n}\n\n/** An element's content-box width, the box its resize observer reports. */\nfunction contentWidth(element: HTMLElement | null): number {\n if (!element)\n return 0;\n\n const style = getComputedStyle(element);\n const edges = [style.paddingLeft, style.paddingRight, style.borderLeftWidth, style.borderRightWidth];\n return edges.reduce((width, edge) => width - (Number.parseFloat(edge) || 0), element.offsetWidth);\n}\n\nfunction createSetup(): MenuSetup {\n const floating = useFloating(\n () => options ?? {},\n () => disabled,\n () => openDelay,\n () => closeDelay,\n () => anchorEl ?? get(activator) ?? undefined,\n menu,\n );\n\n const width = shallowRef<number>(0);\n const readWidth = (): void => set(width, contentWidth(get(activator)));\n useResizeObserver(activator, ([entry]) => {\n if (entry)\n set(width, entry.contentRect.width);\n });\n // Only the menu's own setup waits for its mount; a later one may run inside another component's hook\n if (instance?.isMounted)\n readWidth();\n else\n onMounted(readWidth);\n\n // Immediate, so a model that is already `true` at setup opens the menu\n watch(modelValue, (value) => {\n if (get(floating.open) === value)\n return;\n\n if (value) {\n floating.onOpen();\n set(click, true);\n }\n else {\n onLeave();\n }\n }, { immediate: true });\n\n watch(floating.open, (isOpen) => {\n set(modelValue, isOpen);\n if (isOpen) {\n focusMenu();\n }\n });\n\n onClickOutside(menu, () => {\n if (get(floating.open) && !persistent)\n onLeave();\n }, { ignore: [activator] });\n\n return reactive({ floating, width });\n}\n\n/**\n * Moves focus into the open menu without scrolling the page. A menu taller than the space below its\n * activator would otherwise make the browser scroll the whole document to reveal the focused\n * container, sliding the page out from under the activator.\n */\nfunction focusOnContent() {\n const content = get(menuContent);\n if (!content)\n return;\n\n content.focus({ preventScroll: true });\n}\n\nfunction focusMenu(): void {\n if (disableAutoFocus)\n return;\n\n nextTick(() => focusOnContent());\n}\n\n/** Hands focus back to the activator on close, likewise without scrolling to it. */\nfunction focusOnActivator() {\n const activatorEl = get(activator);\n if (!activatorEl) {\n return;\n }\n const focusableEl = activatorEl.querySelector<HTMLElement>(FOCUSABLE_ELEMENTS_SELECTOR);\n if (focusableEl) {\n focusableEl.focus({ preventScroll: true });\n }\n}\n\nfunction onLeave(event?: KeyboardEvent): void {\n const floating = activeFloating();\n if (!floating?.open)\n return;\n floating.onClose();\n set(click, false);\n event?.stopPropagation();\n\n // Return focus to activator when menu closes\n if (disableAutoFocus) {\n return;\n }\n\n nextTick(() => focusOnActivator());\n}\n\n/**\n * `persistent` blocks the outside interactions that would close the menu, and\n * Escape is one of them, which is how `RuiDialog` and `RuiBottomSheet` already\n * read it. The guard sits here rather than in `onLeave`, because `onLeave`\n * also runs for a programmatic close through `v-model`, which must keep\n * working.\n *\n * A persistent menu leaves the key alone instead of swallowing it, so an inner\n * popover can close on Escape while the menu stays open, and an ancestor still\n * sees a key nothing consumed.\n *\n * Escape is swallowed only while the menu is open and not persistent\n * (`onLeave` stops the event itself); a closed or persistent menu must let it\n * through, or a consumer that closes its own editor on Escape never sees the\n * key. The root element listens for it.\n *\n * An Escape that arrives while an IME is composing belongs to the IME, which\n * cancels the candidate with it, so the menu leaves it alone the same way: a\n * search field inside the menu would otherwise lose the whole menu mid-word.\n */\nfunction onEscape(event: KeyboardEvent): void {\n if (persistent || event.isComposing)\n return;\n\n onLeave(event);\n}\n\nfunction checkClick(): void {\n const floating = setUp();\n if (!floating)\n return;\n\n if (floating.open && get(click)) {\n if (!persistOnActivatorClick)\n onLeave();\n }\n else {\n floating.onOpen();\n set(click, true);\n }\n}\n\n// The setup's own watcher opens it; a disabled menu stays closed and unset, as an eager one stays closed\nif (!lazy || (get(modelValue) && !disabled)) {\n setUp();\n}\nelse {\n stopSetUpOnModel = watch(modelValue, (value) => {\n if (value && !disabled)\n setUp();\n });\n}\n</script>\n\n<template>\n <div\n :class=\"classNames?.root\"\n @keydown.esc=\"onEscape($event)\"\n >\n <slot name=\"label\" />\n <div\n ref=\"activator\"\n :class=\"ui.wrapper({ class: cn(classNames?.wrapper) })\"\n :data-menu-disabled=\"disabled\"\n v-on=\"lazy && !disabled ? firstUseListeners : {}\"\n >\n <slot\n name=\"activator\"\n v-bind=\"{ attrs: menuAttrs, open, disabled, hasError, hasSuccess }\"\n />\n </div>\n <Teleport\n v-if=\"!disabled && menuSetup\"\n to=\"body\"\n >\n <div\n v-if=\"visible\"\n :id=\"menuId\"\n ref=\"menu\"\n :class=\"ui.popover({ class: cn(classNames?.menu) })\"\n :role=\"role\"\n :aria-label=\"menuLabel\"\n :data-placement=\"menuSetup.floating.currentPlacement\"\n @click=\"closeOnContentClick ? onLeave() : undefined\"\n @keydown.esc=\"onEscape($event)\"\n >\n <TransitionGroup\n enter-active-class=\"transition ease-out duration-200\"\n enter-from-class=\"opacity-0 translate-y-1\"\n enter-to-class=\"opacity-100 translate-y-0\"\n leave-active-class=\"transition ease-in duration-150\"\n leave-from-class=\"opacity-100 translate-y-0\"\n leave-to-class=\"opacity-0 translate-y-1\"\n @before-enter=\"menuSetup?.floating.updatePosition()\"\n @after-leave=\"menuSetup?.floating.leavePending ? menuSetup.floating.onLeaveComplete() : undefined\"\n @before-leave=\"menuSetup?.floating.onLeavePending()\"\n >\n <div\n v-if=\"open\"\n ref=\"menuContent\"\n key=\"menu\"\n data-id=\"content\"\n :class=\"ui.content({ class: cn(classNames?.content) })\"\n tabindex=\"-1\"\n v-bind=\"baseMenuAttrs\"\n >\n <ButtonGroupBoundary>\n <slot v-bind=\"{ width: menuSetup.width }\" />\n </ButtonGroupBoundary>\n </div>\n </TransitionGroup>\n </div>\n </Teleport>\n <RuiFormTextDetail\n v-if=\"showDetails\"\n :details=\"details\"\n :class=\"ui.details({ class: cn(classNames?.details) })\"\n :error-messages=\"errorMessages\"\n :success-messages=\"successMessages\"\n :hint=\"hint\"\n />\n </div>\n</template>\n"],"mappings":""}
@@ -1,3 +1,4 @@
1
+ import type { HTMLAttributes } from 'vue';
1
2
  import type { VueClassValue } from '../../../types/class-value.js';
2
3
  import { type FloatingOptions } from '../../../composables/floating.js';
3
4
  import { type FormDetails } from '../../../utils/form-text-detail.js';
@@ -67,7 +68,7 @@ export interface MenuProps {
67
68
  */
68
69
  lazy?: boolean;
69
70
  }
70
- type __VLS_Props = MenuProps;
71
+ type __VLS_Props = MenuProps & /* @vue-ignore */ Omit<HTMLAttributes, keyof MenuProps>;
71
72
  type __VLS_Slots = {
72
73
  activator?: (props: {
73
74
  attrs: {
@@ -1 +1 @@
1
- {"version":3,"file":"RuiMenu.vue_vue_type_script_setup_true_lang.js","names":["_useModel","_openBlock","_createElementBlock","_normalizeClass","_withKeys","_renderSlot","_createElementVNode","_mergeProps","_unref","_toHandlers","_normalizeProps","_guardReactiveProps","_createBlock","_Teleport","_createVNode","_TransitionGroup","_withCtx","_createCommentVNode","RuiFormTextDetail"],"sources":["../../../../src/components/overlays/menu/RuiMenu.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport type { Reactive, Ref, WatchHandle } from 'vue';\nimport type { VueClassValue } from '@/types/class-value';\nimport { ButtonGroupBoundary } from '@/components/buttons/button-group/button-group-context';\nimport RuiFormTextDetail from '@/components/helpers/RuiFormTextDetail.vue';\nimport { type FloatingOptions, useFloating, type UseFloatingReturn } from '@/composables/floating';\nimport { containsMessage, type FormDetails } from '@/utils/form-text-detail';\nimport { cn } from '@/utils/tv';\nimport { menuStyles } from './menu-styles';\n\ninterface BaseMenuAttrs { onMouseover?: () => void; onMouseleave?: () => void }\n\n/**\n * What the activator slot binds onto its trigger. The ARIA keys belong on an\n * element that can carry them (a button, link or combobox), never on a plain\n * `div`; an activator that sets its own ARIA takes `activatorHandlers(attrs)`.\n */\ninterface MenuAttrs extends BaseMenuAttrs {\n 'onClick'?: () => void;\n 'aria-haspopup': RuiMenuRole | 'true';\n 'aria-expanded': boolean;\n 'aria-controls'?: string;\n}\n\nexport interface RuiMenuClassNames {\n root?: VueClassValue;\n wrapper?: VueClassValue;\n menu?: VueClassValue;\n /** Overrides applied to the popover content box (e.g. to drop its default padding). */\n content?: VueClassValue;\n /** Overrides applied to the hint and messages under the activator. */\n details?: VueClassValue;\n}\n\n/**\n * Roles a popover container may take. These are the values `aria-haspopup`\n * accepts, which keeps the activator and the popover in agreement.\n */\nexport type RuiMenuRole = 'menu' | 'listbox' | 'tree' | 'grid' | 'dialog';\n\nexport interface MenuProps {\n openOnHover?: boolean;\n fullWidth?: boolean;\n disabled?: boolean;\n openDelay?: number;\n closeDelay?: number;\n options?: FloatingOptions;\n classNames?: RuiMenuClassNames;\n closeOnContentClick?: boolean;\n persistOnActivatorClick?: boolean;\n hint?: string;\n errorMessages?: string | string[];\n successMessages?: string | string[];\n showDetails?: boolean;\n /** With `showDetails`: `reserve` keeps the line while empty (default), `auto` takes no space until there is a message. */\n details?: Exclude<FormDetails, 'hidden'>;\n dense?: boolean;\n /**\n * Keeps the menu open through the interactions that would otherwise dismiss\n * it: a click outside and an Escape press. A programmatic close (`v-model`\n * set to `false`) still applies.\n */\n persistent?: boolean;\n disableAutoFocus?: boolean;\n /**\n * Optional external element to anchor the menu to, instead of the\n * activator slot's wrapper. When set, the menu's position is computed\n * against this element.\n */\n anchorEl?: HTMLElement;\n /**\n * Role of the teleported popover. Defaults to `menu`, which is correct when\n * the content is made of `menuitem`s. Set it to `listbox` (or `tree`, `grid`,\n * `dialog`) when the content follows a different ARIA model, e.g. a selection\n * list opened by a `combobox`. The activator's `aria-haspopup` follows it.\n */\n role?: RuiMenuRole;\n /**\n * Accessible name of the teleported popover. A `dialog` popover needs one;\n * the other roles take it from their activator or options.\n */\n menuLabel?: string;\n /**\n * Defers the popover's setup (its positioning, the activator's size\n * observer and the click-outside listeners) to first use: a click or a\n * context menu on the activator, a hover with `openOnHover`, or the model\n * turning `true`. Until then the menu renders its root, the wrapper and the\n * activator, the same elements it keeps afterwards, so a table with a menu\n * on every row pays for the menus that are opened. Read at mount.\n */\n lazy?: boolean;\n}\n\n/** What the menu sets up at mount, or on first use when `lazy`, with its refs unwrapped. */\ntype MenuSetup = Reactive<{\n floating: UseFloatingReturn;\n width: Readonly<Ref<number>>;\n}>;\n\ndefineOptions({\n name: 'RuiMenu',\n});\n\nconst modelValue = defineModel<boolean>({ default: false });\n\nconst {\n openOnHover = false,\n disabled = false,\n fullWidth = false,\n openDelay = 0,\n closeDelay = 0,\n options,\n classNames,\n closeOnContentClick = false,\n persistOnActivatorClick = false,\n hint,\n errorMessages = [],\n successMessages = [],\n showDetails = false,\n details = 'reserve',\n dense = false,\n persistent = false,\n disableAutoFocus = false,\n anchorEl,\n role = 'menu',\n menuLabel,\n lazy = false,\n} = defineProps<MenuProps>();\n\ndefineSlots<{\n activator?: (props: {\n // An inline type literal, so callers can pass it on as `Record<string, unknown>`\n attrs: {\n 'onMouseover'?: () => void;\n 'onMouseleave'?: () => void;\n 'onClick'?: () => void;\n 'aria-haspopup': RuiMenuRole | 'true';\n 'aria-expanded': boolean;\n 'aria-controls'?: string;\n };\n open: boolean;\n disabled: boolean;\n hasError: boolean;\n hasSuccess: boolean;\n }) => any;\n default?: (props: { width: number }) => any;\n /** Rendered above the activator, outside the element the menu positions against. */\n label?: () => any;\n}>();\n\nconst click = ref<boolean>(false);\nconst activator = useTemplateRef<HTMLElement>('activator');\nconst menu = useTemplateRef<HTMLElement>('menu');\nconst menuContent = useTemplateRef<HTMLElement>('menuContent');\nconst menuId = useId();\nconst instance = getCurrentInstance();\n// Owned by this component, so whatever the setup starts stops on unmount even when it ran after mount\nconst setupScope = effectScope();\nconst menuSetup = shallowRef<MenuSetup>();\nlet stopSetUpOnModel: WatchHandle | undefined;\n\nconst FOCUSABLE_ELEMENTS_SELECTOR =\n 'button, [href], input, select, textarea, [tabindex]:not([tabindex=\"-1\"])';\n\n// Only the two flags, not the formatted lists useFormTextDetail builds, since a table may hold hundreds of menus\nconst hasError = computed<boolean>(() => containsMessage(errorMessages));\nconst hasSuccess = computed<boolean>(() => containsMessage(successMessages));\n\nconst ui = computed<ReturnType<typeof menuStyles>>(() => menuStyles({\n fullWidth,\n dense,\n}));\n\nconst open = computed<boolean>(() => get(menuSetup)?.floating.open ?? false);\nconst visible = computed<boolean>(() => get(menuSetup)?.floating.visible ?? false);\n\n/**\n * The activator attributes.\n *\n * This and the computed below it must return the same object shape from every\n * branch. Otherwise vue-tsc infers the slot's `attrs` type as a discriminated\n * union where each key is either all defined or all undefined, which breaks\n * consumer code typing its own `attrs` handler with individually optional\n * keys.\n */\nconst baseMenuAttrs = computed<BaseMenuAttrs>(() => {\n const clickVal = get(click);\n return {\n onMouseover: disabled\n ? undefined\n : () => {\n if (openOnHover)\n setUp()?.onOpen();\n },\n onMouseleave: disabled\n ? undefined\n : () => {\n if (openOnHover && !clickVal)\n activeFloating()?.onClose();\n },\n };\n});\n\nconst menuAttrs = computed<MenuAttrs>(() => ({\n ...get(baseMenuAttrs),\n 'onClick': disabled ? undefined : checkClick,\n // `aria-haspopup=\"true\"` means `\"menu\"`, and the default keeps emitting `true` for existing callers\n 'aria-haspopup': role === 'menu' ? 'true' : role,\n 'aria-expanded': get(open),\n // Only while the popover is in the DOM, so the reference never points at a missing element\n 'aria-controls': get(visible) ? menuId : undefined,\n}));\n\n/**\n * Sets a lazy menu up on its first use, on the wrapper so that it covers an\n * activator that opens the menu through the model rather than through\n * `attrs`. Hover and focus are left out: a cursor resting over a scrolling\n * table or Tab moving down it would set up every row it passes. They stay\n * after setup, where `setUp` only hands back what it already made.\n */\nconst firstUseListeners = { click: setUp, contextmenu: setUp };\n\n/**\n * Sets the popover up once and hands back its floating state. It runs at\n * mount, or for a `lazy` menu on first use, which can be after mount and\n * inside another component's lifecycle hook, so what it starts must not\n * attach itself to the current instance.\n */\nfunction setUp(): MenuSetup['floating'] | undefined {\n if (setupScope.active && !get(menuSetup)) {\n set(menuSetup, setupScope.run(createSetup));\n stopSetUpOnModel?.();\n }\n return activeFloating();\n}\n\n/**\n * The floating state while the menu is alive. An event can still reach the\n * activator after unmount, and must not start timers on a stopped menu.\n */\nfunction activeFloating(): MenuSetup['floating'] | undefined {\n return setupScope.active ? get(menuSetup)?.floating : undefined;\n}\n\n/** An element's content-box width, the box its resize observer reports. */\nfunction contentWidth(element: HTMLElement | null): number {\n if (!element)\n return 0;\n\n const style = getComputedStyle(element);\n const edges = [style.paddingLeft, style.paddingRight, style.borderLeftWidth, style.borderRightWidth];\n return edges.reduce((width, edge) => width - (Number.parseFloat(edge) || 0), element.offsetWidth);\n}\n\nfunction createSetup(): MenuSetup {\n const floating = useFloating(\n () => options ?? {},\n () => disabled,\n () => openDelay,\n () => closeDelay,\n () => anchorEl ?? get(activator) ?? undefined,\n menu,\n );\n\n const width = shallowRef<number>(0);\n const readWidth = (): void => set(width, contentWidth(get(activator)));\n useResizeObserver(activator, ([entry]) => {\n if (entry)\n set(width, entry.contentRect.width);\n });\n // Only the menu's own setup waits for its mount; a later one may run inside another component's hook\n if (instance?.isMounted)\n readWidth();\n else\n onMounted(readWidth);\n\n // Immediate, so a model that is already `true` at setup opens the menu\n watch(modelValue, (value) => {\n if (get(floating.open) === value)\n return;\n\n if (value) {\n floating.onOpen();\n set(click, true);\n }\n else {\n onLeave();\n }\n }, { immediate: true });\n\n watch(floating.open, (isOpen) => {\n set(modelValue, isOpen);\n if (isOpen) {\n focusMenu();\n }\n });\n\n onClickOutside(menu, () => {\n if (get(floating.open) && !persistent)\n onLeave();\n }, { ignore: [activator] });\n\n return reactive({ floating, width });\n}\n\n/**\n * Moves focus into the open menu without scrolling the page. A menu taller than the space below its\n * activator would otherwise make the browser scroll the whole document to reveal the focused\n * container, sliding the page out from under the activator.\n */\nfunction focusOnContent() {\n const content = get(menuContent);\n if (!content)\n return;\n\n content.focus({ preventScroll: true });\n}\n\nfunction focusMenu(): void {\n if (disableAutoFocus)\n return;\n\n nextTick(() => focusOnContent());\n}\n\n/** Hands focus back to the activator on close, likewise without scrolling to it. */\nfunction focusOnActivator() {\n const activatorEl = get(activator);\n if (!activatorEl) {\n return;\n }\n const focusableEl = activatorEl.querySelector<HTMLElement>(FOCUSABLE_ELEMENTS_SELECTOR);\n if (focusableEl) {\n focusableEl.focus({ preventScroll: true });\n }\n}\n\nfunction onLeave(event?: KeyboardEvent): void {\n const floating = activeFloating();\n if (!floating?.open)\n return;\n floating.onClose();\n set(click, false);\n event?.stopPropagation();\n\n // Return focus to activator when menu closes\n if (disableAutoFocus) {\n return;\n }\n\n nextTick(() => focusOnActivator());\n}\n\n/**\n * `persistent` blocks the outside interactions that would close the menu, and\n * Escape is one of them, which is how `RuiDialog` and `RuiBottomSheet` already\n * read it. The guard sits here rather than in `onLeave`, because `onLeave`\n * also runs for a programmatic close through `v-model`, which must keep\n * working.\n *\n * A persistent menu leaves the key alone instead of swallowing it, so an inner\n * popover can close on Escape while the menu stays open, and an ancestor still\n * sees a key nothing consumed.\n *\n * Escape is swallowed only while the menu is open and not persistent\n * (`onLeave` stops the event itself); a closed or persistent menu must let it\n * through, or a consumer that closes its own editor on Escape never sees the\n * key. The root element listens for it.\n *\n * An Escape that arrives while an IME is composing belongs to the IME, which\n * cancels the candidate with it, so the menu leaves it alone the same way: a\n * search field inside the menu would otherwise lose the whole menu mid-word.\n */\nfunction onEscape(event: KeyboardEvent): void {\n if (persistent || event.isComposing)\n return;\n\n onLeave(event);\n}\n\nfunction checkClick(): void {\n const floating = setUp();\n if (!floating)\n return;\n\n if (floating.open && get(click)) {\n if (!persistOnActivatorClick)\n onLeave();\n }\n else {\n floating.onOpen();\n set(click, true);\n }\n}\n\n// The setup's own watcher opens it; a disabled menu stays closed and unset, as an eager one stays closed\nif (!lazy || (get(modelValue) && !disabled)) {\n setUp();\n}\nelse {\n stopSetUpOnModel = watch(modelValue, (value) => {\n if (value && !disabled)\n setUp();\n });\n}\n</script>\n\n<template>\n <div\n :class=\"classNames?.root\"\n @keydown.esc=\"onEscape($event)\"\n >\n <slot name=\"label\" />\n <div\n ref=\"activator\"\n :class=\"ui.wrapper({ class: cn(classNames?.wrapper) })\"\n :data-menu-disabled=\"disabled\"\n v-on=\"lazy && !disabled ? firstUseListeners : {}\"\n >\n <slot\n name=\"activator\"\n v-bind=\"{ attrs: menuAttrs, open, disabled, hasError, hasSuccess }\"\n />\n </div>\n <Teleport\n v-if=\"!disabled && menuSetup\"\n to=\"body\"\n >\n <div\n v-if=\"visible\"\n :id=\"menuId\"\n ref=\"menu\"\n :class=\"ui.popover({ class: cn(classNames?.menu) })\"\n :role=\"role\"\n :aria-label=\"menuLabel\"\n :data-placement=\"menuSetup.floating.currentPlacement\"\n @click=\"closeOnContentClick ? onLeave() : undefined\"\n @keydown.esc=\"onEscape($event)\"\n >\n <TransitionGroup\n enter-active-class=\"transition ease-out duration-200\"\n enter-from-class=\"opacity-0 translate-y-1\"\n enter-to-class=\"opacity-100 translate-y-0\"\n leave-active-class=\"transition ease-in duration-150\"\n leave-from-class=\"opacity-100 translate-y-0\"\n leave-to-class=\"opacity-0 translate-y-1\"\n @before-enter=\"menuSetup?.floating.updatePosition()\"\n @after-leave=\"menuSetup?.floating.leavePending ? menuSetup.floating.onLeaveComplete() : undefined\"\n @before-leave=\"menuSetup?.floating.onLeavePending()\"\n >\n <div\n v-if=\"open\"\n ref=\"menuContent\"\n key=\"menu\"\n data-id=\"content\"\n :class=\"ui.content({ class: cn(classNames?.content) })\"\n tabindex=\"-1\"\n v-bind=\"baseMenuAttrs\"\n >\n <ButtonGroupBoundary>\n <slot v-bind=\"{ width: menuSetup.width }\" />\n </ButtonGroupBoundary>\n </div>\n </TransitionGroup>\n </div>\n </Teleport>\n <RuiFormTextDetail\n v-if=\"showDetails\"\n :details=\"details\"\n :class=\"ui.details({ class: cn(classNames?.details) })\"\n :error-messages=\"errorMessages\"\n :success-messages=\"successMessages\"\n :hint=\"hint\"\n />\n </div>\n</template>\n"],"mappings":"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"}
1
+ {"version":3,"file":"RuiMenu.vue_vue_type_script_setup_true_lang.js","names":["_useModel","_openBlock","_createElementBlock","_normalizeClass","_withKeys","_renderSlot","_createElementVNode","_mergeProps","_unref","_toHandlers","_normalizeProps","_guardReactiveProps","_createBlock","_Teleport","_createVNode","_TransitionGroup","_withCtx","_createCommentVNode","RuiFormTextDetail"],"sources":["../../../../src/components/overlays/menu/RuiMenu.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport type { HTMLAttributes, Reactive, Ref, WatchHandle } from 'vue';\nimport type { VueClassValue } from '@/types/class-value';\nimport { ButtonGroupBoundary } from '@/components/buttons/button-group/button-group-context';\nimport RuiFormTextDetail from '@/components/helpers/RuiFormTextDetail.vue';\nimport { type FloatingOptions, useFloating, type UseFloatingReturn } from '@/composables/floating';\nimport { containsMessage, type FormDetails } from '@/utils/form-text-detail';\nimport { cn } from '@/utils/tv';\nimport { menuStyles } from './menu-styles';\n\ninterface BaseMenuAttrs { onMouseover?: () => void; onMouseleave?: () => void }\n\n/**\n * What the activator slot binds onto its trigger. The ARIA keys belong on an\n * element that can carry them (a button, link or combobox), never on a plain\n * `div`; an activator that sets its own ARIA takes `activatorHandlers(attrs)`.\n */\ninterface MenuAttrs extends BaseMenuAttrs {\n 'onClick'?: () => void;\n 'aria-haspopup': RuiMenuRole | 'true';\n 'aria-expanded': boolean;\n 'aria-controls'?: string;\n}\n\nexport interface RuiMenuClassNames {\n root?: VueClassValue;\n wrapper?: VueClassValue;\n menu?: VueClassValue;\n /** Overrides applied to the popover content box (e.g. to drop its default padding). */\n content?: VueClassValue;\n /** Overrides applied to the hint and messages under the activator. */\n details?: VueClassValue;\n}\n\n/**\n * Roles a popover container may take. These are the values `aria-haspopup`\n * accepts, which keeps the activator and the popover in agreement.\n */\nexport type RuiMenuRole = 'menu' | 'listbox' | 'tree' | 'grid' | 'dialog';\n\nexport interface MenuProps {\n openOnHover?: boolean;\n fullWidth?: boolean;\n disabled?: boolean;\n openDelay?: number;\n closeDelay?: number;\n options?: FloatingOptions;\n classNames?: RuiMenuClassNames;\n closeOnContentClick?: boolean;\n persistOnActivatorClick?: boolean;\n hint?: string;\n errorMessages?: string | string[];\n successMessages?: string | string[];\n showDetails?: boolean;\n /** With `showDetails`: `reserve` keeps the line while empty (default), `auto` takes no space until there is a message. */\n details?: Exclude<FormDetails, 'hidden'>;\n dense?: boolean;\n /**\n * Keeps the menu open through the interactions that would otherwise dismiss\n * it: a click outside and an Escape press. A programmatic close (`v-model`\n * set to `false`) still applies.\n */\n persistent?: boolean;\n disableAutoFocus?: boolean;\n /**\n * Optional external element to anchor the menu to, instead of the\n * activator slot's wrapper. When set, the menu's position is computed\n * against this element.\n */\n anchorEl?: HTMLElement;\n /**\n * Role of the teleported popover. Defaults to `menu`, which is correct when\n * the content is made of `menuitem`s. Set it to `listbox` (or `tree`, `grid`,\n * `dialog`) when the content follows a different ARIA model, e.g. a selection\n * list opened by a `combobox`. The activator's `aria-haspopup` follows it.\n */\n role?: RuiMenuRole;\n /**\n * Accessible name of the teleported popover. A `dialog` popover needs one;\n * the other roles take it from their activator or options.\n */\n menuLabel?: string;\n /**\n * Defers the popover's setup (its positioning, the activator's size\n * observer and the click-outside listeners) to first use: a click or a\n * context menu on the activator, a hover with `openOnHover`, or the model\n * turning `true`. Until then the menu renders its root, the wrapper and the\n * activator, the same elements it keeps afterwards, so a table with a menu\n * on every row pays for the menus that are opened. Read at mount.\n */\n lazy?: boolean;\n}\n\n/** What the menu sets up at mount, or on first use when `lazy`, with its refs unwrapped. */\ntype MenuSetup = Reactive<{\n floating: UseFloatingReturn;\n width: Readonly<Ref<number>>;\n}>;\n\ndefineOptions({\n name: 'RuiMenu',\n});\n\nconst modelValue = defineModel<boolean>({ default: false });\n\nconst {\n openOnHover = false,\n disabled = false,\n fullWidth = false,\n openDelay = 0,\n closeDelay = 0,\n options,\n classNames,\n closeOnContentClick = false,\n persistOnActivatorClick = false,\n hint,\n errorMessages = [],\n successMessages = [],\n showDetails = false,\n details = 'reserve',\n dense = false,\n persistent = false,\n disableAutoFocus = false,\n anchorEl,\n role = 'menu',\n menuLabel,\n lazy = false,\n} = defineProps<MenuProps & /* @vue-ignore */ Omit<HTMLAttributes, keyof MenuProps>>();\n\ndefineSlots<{\n activator?: (props: {\n // An inline type literal, so callers can pass it on as `Record<string, unknown>`\n attrs: {\n 'onMouseover'?: () => void;\n 'onMouseleave'?: () => void;\n 'onClick'?: () => void;\n 'aria-haspopup': RuiMenuRole | 'true';\n 'aria-expanded': boolean;\n 'aria-controls'?: string;\n };\n open: boolean;\n disabled: boolean;\n hasError: boolean;\n hasSuccess: boolean;\n }) => any;\n default?: (props: { width: number }) => any;\n /** Rendered above the activator, outside the element the menu positions against. */\n label?: () => any;\n}>();\n\nconst click = ref<boolean>(false);\nconst activator = useTemplateRef<HTMLElement>('activator');\nconst menu = useTemplateRef<HTMLElement>('menu');\nconst menuContent = useTemplateRef<HTMLElement>('menuContent');\nconst menuId = useId();\nconst instance = getCurrentInstance();\n// Owned by this component, so whatever the setup starts stops on unmount even when it ran after mount\nconst setupScope = effectScope();\nconst menuSetup = shallowRef<MenuSetup>();\nlet stopSetUpOnModel: WatchHandle | undefined;\n\nconst FOCUSABLE_ELEMENTS_SELECTOR =\n 'button, [href], input, select, textarea, [tabindex]:not([tabindex=\"-1\"])';\n\n// Only the two flags, not the formatted lists useFormTextDetail builds, since a table may hold hundreds of menus\nconst hasError = computed<boolean>(() => containsMessage(errorMessages));\nconst hasSuccess = computed<boolean>(() => containsMessage(successMessages));\n\nconst ui = computed<ReturnType<typeof menuStyles>>(() => menuStyles({\n fullWidth,\n dense,\n}));\n\nconst open = computed<boolean>(() => get(menuSetup)?.floating.open ?? false);\nconst visible = computed<boolean>(() => get(menuSetup)?.floating.visible ?? false);\n\n/**\n * The activator attributes.\n *\n * This and the computed below it must return the same object shape from every\n * branch. Otherwise vue-tsc infers the slot's `attrs` type as a discriminated\n * union where each key is either all defined or all undefined, which breaks\n * consumer code typing its own `attrs` handler with individually optional\n * keys.\n */\nconst baseMenuAttrs = computed<BaseMenuAttrs>(() => {\n const clickVal = get(click);\n return {\n onMouseover: disabled\n ? undefined\n : () => {\n if (openOnHover)\n setUp()?.onOpen();\n },\n onMouseleave: disabled\n ? undefined\n : () => {\n if (openOnHover && !clickVal)\n activeFloating()?.onClose();\n },\n };\n});\n\nconst menuAttrs = computed<MenuAttrs>(() => ({\n ...get(baseMenuAttrs),\n 'onClick': disabled ? undefined : checkClick,\n // `aria-haspopup=\"true\"` means `\"menu\"`, and the default keeps emitting `true` for existing callers\n 'aria-haspopup': role === 'menu' ? 'true' : role,\n 'aria-expanded': get(open),\n // Only while the popover is in the DOM, so the reference never points at a missing element\n 'aria-controls': get(visible) ? menuId : undefined,\n}));\n\n/**\n * Sets a lazy menu up on its first use, on the wrapper so that it covers an\n * activator that opens the menu through the model rather than through\n * `attrs`. Hover and focus are left out: a cursor resting over a scrolling\n * table or Tab moving down it would set up every row it passes. They stay\n * after setup, where `setUp` only hands back what it already made.\n */\nconst firstUseListeners = { click: setUp, contextmenu: setUp };\n\n/**\n * Sets the popover up once and hands back its floating state. It runs at\n * mount, or for a `lazy` menu on first use, which can be after mount and\n * inside another component's lifecycle hook, so what it starts must not\n * attach itself to the current instance.\n */\nfunction setUp(): MenuSetup['floating'] | undefined {\n if (setupScope.active && !get(menuSetup)) {\n set(menuSetup, setupScope.run(createSetup));\n stopSetUpOnModel?.();\n }\n return activeFloating();\n}\n\n/**\n * The floating state while the menu is alive. An event can still reach the\n * activator after unmount, and must not start timers on a stopped menu.\n */\nfunction activeFloating(): MenuSetup['floating'] | undefined {\n return setupScope.active ? get(menuSetup)?.floating : undefined;\n}\n\n/** An element's content-box width, the box its resize observer reports. */\nfunction contentWidth(element: HTMLElement | null): number {\n if (!element)\n return 0;\n\n const style = getComputedStyle(element);\n const edges = [style.paddingLeft, style.paddingRight, style.borderLeftWidth, style.borderRightWidth];\n return edges.reduce((width, edge) => width - (Number.parseFloat(edge) || 0), element.offsetWidth);\n}\n\nfunction createSetup(): MenuSetup {\n const floating = useFloating(\n () => options ?? {},\n () => disabled,\n () => openDelay,\n () => closeDelay,\n () => anchorEl ?? get(activator) ?? undefined,\n menu,\n );\n\n const width = shallowRef<number>(0);\n const readWidth = (): void => set(width, contentWidth(get(activator)));\n useResizeObserver(activator, ([entry]) => {\n if (entry)\n set(width, entry.contentRect.width);\n });\n // Only the menu's own setup waits for its mount; a later one may run inside another component's hook\n if (instance?.isMounted)\n readWidth();\n else\n onMounted(readWidth);\n\n // Immediate, so a model that is already `true` at setup opens the menu\n watch(modelValue, (value) => {\n if (get(floating.open) === value)\n return;\n\n if (value) {\n floating.onOpen();\n set(click, true);\n }\n else {\n onLeave();\n }\n }, { immediate: true });\n\n watch(floating.open, (isOpen) => {\n set(modelValue, isOpen);\n if (isOpen) {\n focusMenu();\n }\n });\n\n onClickOutside(menu, () => {\n if (get(floating.open) && !persistent)\n onLeave();\n }, { ignore: [activator] });\n\n return reactive({ floating, width });\n}\n\n/**\n * Moves focus into the open menu without scrolling the page. A menu taller than the space below its\n * activator would otherwise make the browser scroll the whole document to reveal the focused\n * container, sliding the page out from under the activator.\n */\nfunction focusOnContent() {\n const content = get(menuContent);\n if (!content)\n return;\n\n content.focus({ preventScroll: true });\n}\n\nfunction focusMenu(): void {\n if (disableAutoFocus)\n return;\n\n nextTick(() => focusOnContent());\n}\n\n/** Hands focus back to the activator on close, likewise without scrolling to it. */\nfunction focusOnActivator() {\n const activatorEl = get(activator);\n if (!activatorEl) {\n return;\n }\n const focusableEl = activatorEl.querySelector<HTMLElement>(FOCUSABLE_ELEMENTS_SELECTOR);\n if (focusableEl) {\n focusableEl.focus({ preventScroll: true });\n }\n}\n\nfunction onLeave(event?: KeyboardEvent): void {\n const floating = activeFloating();\n if (!floating?.open)\n return;\n floating.onClose();\n set(click, false);\n event?.stopPropagation();\n\n // Return focus to activator when menu closes\n if (disableAutoFocus) {\n return;\n }\n\n nextTick(() => focusOnActivator());\n}\n\n/**\n * `persistent` blocks the outside interactions that would close the menu, and\n * Escape is one of them, which is how `RuiDialog` and `RuiBottomSheet` already\n * read it. The guard sits here rather than in `onLeave`, because `onLeave`\n * also runs for a programmatic close through `v-model`, which must keep\n * working.\n *\n * A persistent menu leaves the key alone instead of swallowing it, so an inner\n * popover can close on Escape while the menu stays open, and an ancestor still\n * sees a key nothing consumed.\n *\n * Escape is swallowed only while the menu is open and not persistent\n * (`onLeave` stops the event itself); a closed or persistent menu must let it\n * through, or a consumer that closes its own editor on Escape never sees the\n * key. The root element listens for it.\n *\n * An Escape that arrives while an IME is composing belongs to the IME, which\n * cancels the candidate with it, so the menu leaves it alone the same way: a\n * search field inside the menu would otherwise lose the whole menu mid-word.\n */\nfunction onEscape(event: KeyboardEvent): void {\n if (persistent || event.isComposing)\n return;\n\n onLeave(event);\n}\n\nfunction checkClick(): void {\n const floating = setUp();\n if (!floating)\n return;\n\n if (floating.open && get(click)) {\n if (!persistOnActivatorClick)\n onLeave();\n }\n else {\n floating.onOpen();\n set(click, true);\n }\n}\n\n// The setup's own watcher opens it; a disabled menu stays closed and unset, as an eager one stays closed\nif (!lazy || (get(modelValue) && !disabled)) {\n setUp();\n}\nelse {\n stopSetUpOnModel = watch(modelValue, (value) => {\n if (value && !disabled)\n setUp();\n });\n}\n</script>\n\n<template>\n <div\n :class=\"classNames?.root\"\n @keydown.esc=\"onEscape($event)\"\n >\n <slot name=\"label\" />\n <div\n ref=\"activator\"\n :class=\"ui.wrapper({ class: cn(classNames?.wrapper) })\"\n :data-menu-disabled=\"disabled\"\n v-on=\"lazy && !disabled ? firstUseListeners : {}\"\n >\n <slot\n name=\"activator\"\n v-bind=\"{ attrs: menuAttrs, open, disabled, hasError, hasSuccess }\"\n />\n </div>\n <Teleport\n v-if=\"!disabled && menuSetup\"\n to=\"body\"\n >\n <div\n v-if=\"visible\"\n :id=\"menuId\"\n ref=\"menu\"\n :class=\"ui.popover({ class: cn(classNames?.menu) })\"\n :role=\"role\"\n :aria-label=\"menuLabel\"\n :data-placement=\"menuSetup.floating.currentPlacement\"\n @click=\"closeOnContentClick ? onLeave() : undefined\"\n @keydown.esc=\"onEscape($event)\"\n >\n <TransitionGroup\n enter-active-class=\"transition ease-out duration-200\"\n enter-from-class=\"opacity-0 translate-y-1\"\n enter-to-class=\"opacity-100 translate-y-0\"\n leave-active-class=\"transition ease-in duration-150\"\n leave-from-class=\"opacity-100 translate-y-0\"\n leave-to-class=\"opacity-0 translate-y-1\"\n @before-enter=\"menuSetup?.floating.updatePosition()\"\n @after-leave=\"menuSetup?.floating.leavePending ? menuSetup.floating.onLeaveComplete() : undefined\"\n @before-leave=\"menuSetup?.floating.onLeavePending()\"\n >\n <div\n v-if=\"open\"\n ref=\"menuContent\"\n key=\"menu\"\n data-id=\"content\"\n :class=\"ui.content({ class: cn(classNames?.content) })\"\n tabindex=\"-1\"\n v-bind=\"baseMenuAttrs\"\n >\n <ButtonGroupBoundary>\n <slot v-bind=\"{ width: menuSetup.width }\" />\n </ButtonGroupBoundary>\n </div>\n </TransitionGroup>\n </div>\n </Teleport>\n <RuiFormTextDetail\n v-if=\"showDetails\"\n :details=\"details\"\n :class=\"ui.details({ class: cn(classNames?.details) })\"\n :error-messages=\"errorMessages\"\n :success-messages=\"successMessages\"\n :hint=\"hint\"\n />\n </div>\n</template>\n"],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"RuiNavigationDrawer.js","names":["_sfc_main"],"sources":["../../../../src/components/overlays/navigation-drawer/RuiNavigationDrawer.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport type { ClassValue } from 'vue';\nimport type { VueClassValue } from '@/types/class-value';\nimport type { MaybeElement } from '@/types/dom';\nimport { useTimeoutManager } from '@/composables/timeout-manager';\nimport { getRootAttrs, transformPropsUnit } from '@/utils/helpers';\nimport { cn } from '@/utils/tv';\nimport { navigationDrawerStyles } from './navigation-drawer-styles';\n\nexport interface RuiNavigationDrawerClassNames {\n root?: VueClassValue;\n content?: VueClassValue;\n}\n\nexport interface NavigationDrawerProps {\n temporary?: boolean;\n stateless?: boolean;\n width?: string | number;\n miniVariant?: boolean;\n overlay?: boolean;\n position?: 'left' | 'right';\n classNames?: RuiNavigationDrawerClassNames;\n ariaLabel?: string;\n /**\n * Starts the drawer, and its overlay, below the app bar (`--rui-app-bar-height`), so the app bar\n * stays uncovered and usable while the drawer is open. Without it the drawer runs the full height and\n * a modal one covers the app bar.\n */\n belowAppBar?: boolean;\n}\n\ndefineOptions({\n name: 'RuiNavigationDrawer',\n inheritAttrs: false,\n});\n\nconst modelValue = defineModel<boolean>({ default: false });\n\nconst {\n temporary = false,\n stateless = false,\n width = 360,\n miniVariant = false,\n overlay = false,\n position = 'left',\n classNames,\n ariaLabel,\n belowAppBar = false,\n} = defineProps<NavigationDrawerProps>();\n\nconst emit = defineEmits<{\n closed: [];\n}>();\n\ndefineSlots<{\n activator?: (props: { open: boolean; attrs: { onClick: () => void } }) => any;\n default?: (props: { attrs: { onClick: () => void }; close: () => void }) => any;\n}>();\n\nconst transitioning = ref<boolean>(false);\nconst content = useTemplateRef<MaybeElement>('content');\nconst leaveTimeout = useTimeoutManager();\nconst clickOutsideTimeout = useTimeoutManager();\n\nconst alive = computed<boolean>(() => get(modelValue) || get(transitioning) || miniVariant);\n\nconst style = computed<{ width: string | undefined }>(() => ({\n width: transformPropsUnit(width),\n}));\n\nconst activatorAttrs: { onClick: () => void } = {\n onClick: toggle,\n};\n\n/**\n * Where the drawer starts its slide in: it mounts open, so the closed position has to be put on it for\n * its first frame. Important, because the open position is already on the element.\n */\nconst enterFromClass = computed<string>(() => (position === 'left' ? '-translate-x-full!' : 'translate-x-full!'));\n\n// the overlay dims what the drawer covers: the whole view, or only the part below the app bar\nconst overlayClass = computed<string>(() => cn([\n 'fixed inset-x-0 bottom-0 backdrop-blur-sm bg-rui-neutral-950/40 dark:bg-black/60 z-rui-drawer',\n belowAppBar ? 'top-rui-app-bar' : 'top-0',\n]) ?? '');\n\n/**\n * Consumer classes go through `navigationDrawerStyles()` rather than alongside it, so\n * tailwind-variants' twMerge resolves conflicts in the consumer's favour.\n * Passed as an argument instead of read off `$attrs` here, so the template\n * keeps using `$attrs` directly.\n */\nfunction rootClass(attrsClass: ClassValue): string {\n return navigationDrawerStyles({\n position,\n visible: modelValue.value,\n mini: miniVariant,\n withOverlay: overlay,\n temporary,\n belowAppBar,\n class: cn([\n temporary && modelValue.value && 'shadow-rui-drawer',\n classNames?.content,\n classNames?.root,\n attrsClass,\n ]),\n });\n}\n\nfunction toggle(): void {\n set(modelValue, !get(modelValue));\n}\n\nfunction close(): void {\n set(modelValue, false);\n}\n\nfunction onLeaveComplete(): void {\n leaveTimeout.clear();\n if (get(transitioning)) {\n set(transitioning, false);\n emit('closed');\n }\n}\n\nwatch(modelValue, (value) => {\n if (!value) {\n set(transitioning, true);\n // Match CSS transition duration (200ms) + buffer\n leaveTimeout.create(onLeaveComplete, 250);\n }\n});\n\n// Debounced, so the activator's own click, which bubbles to the body, does not close it again\nonClickOutside(content, () => {\n if (get(modelValue) && temporary && !stateless) {\n clickOutsideTimeout.create(close, 50);\n }\n});\n</script>\n\n<template>\n <div>\n <slot\n name=\"activator\"\n v-bind=\"{ open: modelValue, attrs: activatorAttrs }\"\n />\n <Teleport to=\"body\">\n <Transition\n v-if=\"overlay\"\n enter-from-class=\"opacity-0\"\n enter-active-class=\"transition-opacity ease-out duration-200\"\n enter-to-class=\"opacity-100\"\n leave-from-class=\"opacity-100\"\n leave-active-class=\"transition-opacity ease-in duration-200\"\n leave-to-class=\"opacity-0\"\n >\n <div\n v-if=\"modelValue\"\n data-id=\"overlay\"\n :class=\"overlayClass\"\n @click.stop=\"close()\"\n />\n </Transition>\n <!-- leaves with no transition: it has already slid out, and its own would hold the removal for a transitionend that never comes -->\n <Transition\n :enter-from-class=\"enterFromClass\"\n leave-active-class=\"duration-0!\"\n >\n <aside\n v-if=\"alive\"\n ref=\"content\"\n data-id=\"drawer-content\"\n :style=\"style\"\n :data-visible=\"modelValue || undefined\"\n :data-position=\"position\"\n :data-mini=\"miniVariant || undefined\"\n :class=\"rootClass($attrs.class)\"\n :aria-label=\"ariaLabel\"\n v-bind=\"getRootAttrs($attrs, [])\"\n >\n <slot v-bind=\"{ attrs: activatorAttrs, close }\" />\n </aside>\n </Transition>\n </Teleport>\n </div>\n</template>\n"],"mappings":""}
1
+ {"version":3,"file":"RuiNavigationDrawer.js","names":["_sfc_main"],"sources":["../../../../src/components/overlays/navigation-drawer/RuiNavigationDrawer.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport type { ClassValue, HTMLAttributes } from 'vue';\nimport type { VueClassValue } from '@/types/class-value';\nimport type { MaybeElement } from '@/types/dom';\nimport { useTimeoutManager } from '@/composables/timeout-manager';\nimport { getRootAttrs, transformPropsUnit } from '@/utils/helpers';\nimport { cn } from '@/utils/tv';\nimport { navigationDrawerStyles } from './navigation-drawer-styles';\n\nexport interface RuiNavigationDrawerClassNames {\n root?: VueClassValue;\n content?: VueClassValue;\n}\n\nexport interface NavigationDrawerProps {\n temporary?: boolean;\n stateless?: boolean;\n width?: string | number;\n miniVariant?: boolean;\n overlay?: boolean;\n position?: 'left' | 'right';\n classNames?: RuiNavigationDrawerClassNames;\n ariaLabel?: string;\n /**\n * Starts the drawer, and its overlay, below the app bar (`--rui-app-bar-height`), so the app bar\n * stays uncovered and usable while the drawer is open. Without it the drawer runs the full height and\n * a modal one covers the app bar.\n */\n belowAppBar?: boolean;\n}\n\ndefineOptions({\n name: 'RuiNavigationDrawer',\n inheritAttrs: false,\n});\n\nconst modelValue = defineModel<boolean>({ default: false });\n\nconst {\n temporary = false,\n stateless = false,\n width = 360,\n miniVariant = false,\n overlay = false,\n position = 'left',\n classNames,\n ariaLabel,\n belowAppBar = false,\n} = defineProps<NavigationDrawerProps & /* @vue-ignore */ Omit<HTMLAttributes, keyof NavigationDrawerProps>>();\n\nconst emit = defineEmits<{\n closed: [];\n}>();\n\ndefineSlots<{\n activator?: (props: { open: boolean; attrs: { onClick: () => void } }) => any;\n default?: (props: { attrs: { onClick: () => void }; close: () => void }) => any;\n}>();\n\nconst transitioning = ref<boolean>(false);\nconst content = useTemplateRef<MaybeElement>('content');\nconst leaveTimeout = useTimeoutManager();\nconst clickOutsideTimeout = useTimeoutManager();\n\nconst alive = computed<boolean>(() => get(modelValue) || get(transitioning) || miniVariant);\n\nconst style = computed<{ width: string | undefined }>(() => ({\n width: transformPropsUnit(width),\n}));\n\nconst activatorAttrs: { onClick: () => void } = {\n onClick: toggle,\n};\n\n/**\n * Where the drawer starts its slide in: it mounts open, so the closed position has to be put on it for\n * its first frame. Important, because the open position is already on the element.\n */\nconst enterFromClass = computed<string>(() => (position === 'left' ? '-translate-x-full!' : 'translate-x-full!'));\n\n// the overlay dims what the drawer covers: the whole view, or only the part below the app bar\nconst overlayClass = computed<string>(() => cn([\n 'fixed inset-x-0 bottom-0 backdrop-blur-sm bg-rui-neutral-950/40 dark:bg-black/60 z-rui-drawer',\n belowAppBar ? 'top-rui-app-bar' : 'top-0',\n]) ?? '');\n\n/**\n * Consumer classes go through `navigationDrawerStyles()` rather than alongside it, so\n * tailwind-variants' twMerge resolves conflicts in the consumer's favour.\n * Passed as an argument instead of read off `$attrs` here, so the template\n * keeps using `$attrs` directly.\n */\nfunction rootClass(attrsClass: ClassValue): string {\n return navigationDrawerStyles({\n position,\n visible: modelValue.value,\n mini: miniVariant,\n withOverlay: overlay,\n temporary,\n belowAppBar,\n class: cn([\n temporary && modelValue.value && 'shadow-rui-drawer',\n classNames?.content,\n classNames?.root,\n attrsClass,\n ]),\n });\n}\n\nfunction toggle(): void {\n set(modelValue, !get(modelValue));\n}\n\nfunction close(): void {\n set(modelValue, false);\n}\n\nfunction onLeaveComplete(): void {\n leaveTimeout.clear();\n if (get(transitioning)) {\n set(transitioning, false);\n emit('closed');\n }\n}\n\nwatch(modelValue, (value) => {\n if (!value) {\n set(transitioning, true);\n // Match CSS transition duration (200ms) + buffer\n leaveTimeout.create(onLeaveComplete, 250);\n }\n});\n\n// Debounced, so the activator's own click, which bubbles to the body, does not close it again\nonClickOutside(content, () => {\n if (get(modelValue) && temporary && !stateless) {\n clickOutsideTimeout.create(close, 50);\n }\n});\n</script>\n\n<template>\n <div>\n <slot\n name=\"activator\"\n v-bind=\"{ open: modelValue, attrs: activatorAttrs }\"\n />\n <Teleport to=\"body\">\n <Transition\n v-if=\"overlay\"\n enter-from-class=\"opacity-0\"\n enter-active-class=\"transition-opacity ease-out duration-200\"\n enter-to-class=\"opacity-100\"\n leave-from-class=\"opacity-100\"\n leave-active-class=\"transition-opacity ease-in duration-200\"\n leave-to-class=\"opacity-0\"\n >\n <div\n v-if=\"modelValue\"\n data-id=\"overlay\"\n :class=\"overlayClass\"\n @click.stop=\"close()\"\n />\n </Transition>\n <!-- leaves with no transition: it has already slid out, and its own would hold the removal for a transitionend that never comes -->\n <Transition\n :enter-from-class=\"enterFromClass\"\n leave-active-class=\"duration-0!\"\n >\n <aside\n v-if=\"alive\"\n ref=\"content\"\n data-id=\"drawer-content\"\n :style=\"style\"\n :data-visible=\"modelValue || undefined\"\n :data-position=\"position\"\n :data-mini=\"miniVariant || undefined\"\n :class=\"rootClass($attrs.class)\"\n :aria-label=\"ariaLabel\"\n v-bind=\"getRootAttrs($attrs, [])\"\n >\n <slot v-bind=\"{ attrs: activatorAttrs, close }\" />\n </aside>\n </Transition>\n </Teleport>\n </div>\n</template>\n"],"mappings":""}
@@ -1,3 +1,4 @@
1
+ import type { HTMLAttributes } from 'vue';
1
2
  import type { VueClassValue } from '../../../types/class-value.js';
2
3
  export interface RuiNavigationDrawerClassNames {
3
4
  root?: VueClassValue;
@@ -19,7 +20,7 @@ export interface NavigationDrawerProps {
19
20
  */
20
21
  belowAppBar?: boolean;
21
22
  }
22
- type __VLS_Props = NavigationDrawerProps;
23
+ type __VLS_Props = NavigationDrawerProps & /* @vue-ignore */ Omit<HTMLAttributes, keyof NavigationDrawerProps>;
23
24
  type __VLS_Slots = {
24
25
  activator?: (props: {
25
26
  open: boolean;
@@ -1 +1 @@
1
- {"version":3,"file":"RuiNavigationDrawer.vue_vue_type_script_setup_true_lang.js","names":["$attrs","_useModel","_openBlock","_createElementBlock","_renderSlot","_normalizeProps","_guardReactiveProps","_createBlock","_Teleport","_Transition","_withCtx","_normalizeClass","_unref","_withModifiers","_createCommentVNode","_createVNode","_mergeProps"],"sources":["../../../../src/components/overlays/navigation-drawer/RuiNavigationDrawer.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport type { ClassValue } from 'vue';\nimport type { VueClassValue } from '@/types/class-value';\nimport type { MaybeElement } from '@/types/dom';\nimport { useTimeoutManager } from '@/composables/timeout-manager';\nimport { getRootAttrs, transformPropsUnit } from '@/utils/helpers';\nimport { cn } from '@/utils/tv';\nimport { navigationDrawerStyles } from './navigation-drawer-styles';\n\nexport interface RuiNavigationDrawerClassNames {\n root?: VueClassValue;\n content?: VueClassValue;\n}\n\nexport interface NavigationDrawerProps {\n temporary?: boolean;\n stateless?: boolean;\n width?: string | number;\n miniVariant?: boolean;\n overlay?: boolean;\n position?: 'left' | 'right';\n classNames?: RuiNavigationDrawerClassNames;\n ariaLabel?: string;\n /**\n * Starts the drawer, and its overlay, below the app bar (`--rui-app-bar-height`), so the app bar\n * stays uncovered and usable while the drawer is open. Without it the drawer runs the full height and\n * a modal one covers the app bar.\n */\n belowAppBar?: boolean;\n}\n\ndefineOptions({\n name: 'RuiNavigationDrawer',\n inheritAttrs: false,\n});\n\nconst modelValue = defineModel<boolean>({ default: false });\n\nconst {\n temporary = false,\n stateless = false,\n width = 360,\n miniVariant = false,\n overlay = false,\n position = 'left',\n classNames,\n ariaLabel,\n belowAppBar = false,\n} = defineProps<NavigationDrawerProps>();\n\nconst emit = defineEmits<{\n closed: [];\n}>();\n\ndefineSlots<{\n activator?: (props: { open: boolean; attrs: { onClick: () => void } }) => any;\n default?: (props: { attrs: { onClick: () => void }; close: () => void }) => any;\n}>();\n\nconst transitioning = ref<boolean>(false);\nconst content = useTemplateRef<MaybeElement>('content');\nconst leaveTimeout = useTimeoutManager();\nconst clickOutsideTimeout = useTimeoutManager();\n\nconst alive = computed<boolean>(() => get(modelValue) || get(transitioning) || miniVariant);\n\nconst style = computed<{ width: string | undefined }>(() => ({\n width: transformPropsUnit(width),\n}));\n\nconst activatorAttrs: { onClick: () => void } = {\n onClick: toggle,\n};\n\n/**\n * Where the drawer starts its slide in: it mounts open, so the closed position has to be put on it for\n * its first frame. Important, because the open position is already on the element.\n */\nconst enterFromClass = computed<string>(() => (position === 'left' ? '-translate-x-full!' : 'translate-x-full!'));\n\n// the overlay dims what the drawer covers: the whole view, or only the part below the app bar\nconst overlayClass = computed<string>(() => cn([\n 'fixed inset-x-0 bottom-0 backdrop-blur-sm bg-rui-neutral-950/40 dark:bg-black/60 z-rui-drawer',\n belowAppBar ? 'top-rui-app-bar' : 'top-0',\n]) ?? '');\n\n/**\n * Consumer classes go through `navigationDrawerStyles()` rather than alongside it, so\n * tailwind-variants' twMerge resolves conflicts in the consumer's favour.\n * Passed as an argument instead of read off `$attrs` here, so the template\n * keeps using `$attrs` directly.\n */\nfunction rootClass(attrsClass: ClassValue): string {\n return navigationDrawerStyles({\n position,\n visible: modelValue.value,\n mini: miniVariant,\n withOverlay: overlay,\n temporary,\n belowAppBar,\n class: cn([\n temporary && modelValue.value && 'shadow-rui-drawer',\n classNames?.content,\n classNames?.root,\n attrsClass,\n ]),\n });\n}\n\nfunction toggle(): void {\n set(modelValue, !get(modelValue));\n}\n\nfunction close(): void {\n set(modelValue, false);\n}\n\nfunction onLeaveComplete(): void {\n leaveTimeout.clear();\n if (get(transitioning)) {\n set(transitioning, false);\n emit('closed');\n }\n}\n\nwatch(modelValue, (value) => {\n if (!value) {\n set(transitioning, true);\n // Match CSS transition duration (200ms) + buffer\n leaveTimeout.create(onLeaveComplete, 250);\n }\n});\n\n// Debounced, so the activator's own click, which bubbles to the body, does not close it again\nonClickOutside(content, () => {\n if (get(modelValue) && temporary && !stateless) {\n clickOutsideTimeout.create(close, 50);\n }\n});\n</script>\n\n<template>\n <div>\n <slot\n name=\"activator\"\n v-bind=\"{ open: modelValue, attrs: activatorAttrs }\"\n />\n <Teleport to=\"body\">\n <Transition\n v-if=\"overlay\"\n enter-from-class=\"opacity-0\"\n enter-active-class=\"transition-opacity ease-out duration-200\"\n enter-to-class=\"opacity-100\"\n leave-from-class=\"opacity-100\"\n leave-active-class=\"transition-opacity ease-in duration-200\"\n leave-to-class=\"opacity-0\"\n >\n <div\n v-if=\"modelValue\"\n data-id=\"overlay\"\n :class=\"overlayClass\"\n @click.stop=\"close()\"\n />\n </Transition>\n <!-- leaves with no transition: it has already slid out, and its own would hold the removal for a transitionend that never comes -->\n <Transition\n :enter-from-class=\"enterFromClass\"\n leave-active-class=\"duration-0!\"\n >\n <aside\n v-if=\"alive\"\n ref=\"content\"\n data-id=\"drawer-content\"\n :style=\"style\"\n :data-visible=\"modelValue || undefined\"\n :data-position=\"position\"\n :data-mini=\"miniVariant || undefined\"\n :class=\"rootClass($attrs.class)\"\n :aria-label=\"ariaLabel\"\n v-bind=\"getRootAttrs($attrs, [])\"\n >\n <slot v-bind=\"{ attrs: activatorAttrs, close }\" />\n </aside>\n </Transition>\n </Teleport>\n </div>\n</template>\n"],"mappings":"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"}
1
+ {"version":3,"file":"RuiNavigationDrawer.vue_vue_type_script_setup_true_lang.js","names":["$attrs","_useModel","_openBlock","_createElementBlock","_renderSlot","_normalizeProps","_guardReactiveProps","_createBlock","_Teleport","_Transition","_withCtx","_normalizeClass","_unref","_withModifiers","_createCommentVNode","_createVNode","_mergeProps"],"sources":["../../../../src/components/overlays/navigation-drawer/RuiNavigationDrawer.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport type { ClassValue, HTMLAttributes } from 'vue';\nimport type { VueClassValue } from '@/types/class-value';\nimport type { MaybeElement } from '@/types/dom';\nimport { useTimeoutManager } from '@/composables/timeout-manager';\nimport { getRootAttrs, transformPropsUnit } from '@/utils/helpers';\nimport { cn } from '@/utils/tv';\nimport { navigationDrawerStyles } from './navigation-drawer-styles';\n\nexport interface RuiNavigationDrawerClassNames {\n root?: VueClassValue;\n content?: VueClassValue;\n}\n\nexport interface NavigationDrawerProps {\n temporary?: boolean;\n stateless?: boolean;\n width?: string | number;\n miniVariant?: boolean;\n overlay?: boolean;\n position?: 'left' | 'right';\n classNames?: RuiNavigationDrawerClassNames;\n ariaLabel?: string;\n /**\n * Starts the drawer, and its overlay, below the app bar (`--rui-app-bar-height`), so the app bar\n * stays uncovered and usable while the drawer is open. Without it the drawer runs the full height and\n * a modal one covers the app bar.\n */\n belowAppBar?: boolean;\n}\n\ndefineOptions({\n name: 'RuiNavigationDrawer',\n inheritAttrs: false,\n});\n\nconst modelValue = defineModel<boolean>({ default: false });\n\nconst {\n temporary = false,\n stateless = false,\n width = 360,\n miniVariant = false,\n overlay = false,\n position = 'left',\n classNames,\n ariaLabel,\n belowAppBar = false,\n} = defineProps<NavigationDrawerProps & /* @vue-ignore */ Omit<HTMLAttributes, keyof NavigationDrawerProps>>();\n\nconst emit = defineEmits<{\n closed: [];\n}>();\n\ndefineSlots<{\n activator?: (props: { open: boolean; attrs: { onClick: () => void } }) => any;\n default?: (props: { attrs: { onClick: () => void }; close: () => void }) => any;\n}>();\n\nconst transitioning = ref<boolean>(false);\nconst content = useTemplateRef<MaybeElement>('content');\nconst leaveTimeout = useTimeoutManager();\nconst clickOutsideTimeout = useTimeoutManager();\n\nconst alive = computed<boolean>(() => get(modelValue) || get(transitioning) || miniVariant);\n\nconst style = computed<{ width: string | undefined }>(() => ({\n width: transformPropsUnit(width),\n}));\n\nconst activatorAttrs: { onClick: () => void } = {\n onClick: toggle,\n};\n\n/**\n * Where the drawer starts its slide in: it mounts open, so the closed position has to be put on it for\n * its first frame. Important, because the open position is already on the element.\n */\nconst enterFromClass = computed<string>(() => (position === 'left' ? '-translate-x-full!' : 'translate-x-full!'));\n\n// the overlay dims what the drawer covers: the whole view, or only the part below the app bar\nconst overlayClass = computed<string>(() => cn([\n 'fixed inset-x-0 bottom-0 backdrop-blur-sm bg-rui-neutral-950/40 dark:bg-black/60 z-rui-drawer',\n belowAppBar ? 'top-rui-app-bar' : 'top-0',\n]) ?? '');\n\n/**\n * Consumer classes go through `navigationDrawerStyles()` rather than alongside it, so\n * tailwind-variants' twMerge resolves conflicts in the consumer's favour.\n * Passed as an argument instead of read off `$attrs` here, so the template\n * keeps using `$attrs` directly.\n */\nfunction rootClass(attrsClass: ClassValue): string {\n return navigationDrawerStyles({\n position,\n visible: modelValue.value,\n mini: miniVariant,\n withOverlay: overlay,\n temporary,\n belowAppBar,\n class: cn([\n temporary && modelValue.value && 'shadow-rui-drawer',\n classNames?.content,\n classNames?.root,\n attrsClass,\n ]),\n });\n}\n\nfunction toggle(): void {\n set(modelValue, !get(modelValue));\n}\n\nfunction close(): void {\n set(modelValue, false);\n}\n\nfunction onLeaveComplete(): void {\n leaveTimeout.clear();\n if (get(transitioning)) {\n set(transitioning, false);\n emit('closed');\n }\n}\n\nwatch(modelValue, (value) => {\n if (!value) {\n set(transitioning, true);\n // Match CSS transition duration (200ms) + buffer\n leaveTimeout.create(onLeaveComplete, 250);\n }\n});\n\n// Debounced, so the activator's own click, which bubbles to the body, does not close it again\nonClickOutside(content, () => {\n if (get(modelValue) && temporary && !stateless) {\n clickOutsideTimeout.create(close, 50);\n }\n});\n</script>\n\n<template>\n <div>\n <slot\n name=\"activator\"\n v-bind=\"{ open: modelValue, attrs: activatorAttrs }\"\n />\n <Teleport to=\"body\">\n <Transition\n v-if=\"overlay\"\n enter-from-class=\"opacity-0\"\n enter-active-class=\"transition-opacity ease-out duration-200\"\n enter-to-class=\"opacity-100\"\n leave-from-class=\"opacity-100\"\n leave-active-class=\"transition-opacity ease-in duration-200\"\n leave-to-class=\"opacity-0\"\n >\n <div\n v-if=\"modelValue\"\n data-id=\"overlay\"\n :class=\"overlayClass\"\n @click.stop=\"close()\"\n />\n </Transition>\n <!-- leaves with no transition: it has already slid out, and its own would hold the removal for a transitionend that never comes -->\n <Transition\n :enter-from-class=\"enterFromClass\"\n leave-active-class=\"duration-0!\"\n >\n <aside\n v-if=\"alive\"\n ref=\"content\"\n data-id=\"drawer-content\"\n :style=\"style\"\n :data-visible=\"modelValue || undefined\"\n :data-position=\"position\"\n :data-mini=\"miniVariant || undefined\"\n :class=\"rootClass($attrs.class)\"\n :aria-label=\"ariaLabel\"\n v-bind=\"getRootAttrs($attrs, [])\"\n >\n <slot v-bind=\"{ attrs: activatorAttrs, close }\" />\n </aside>\n </Transition>\n </Teleport>\n </div>\n</template>\n"],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"RuiNotification.js","names":["_sfc_main"],"sources":["../../../../src/components/overlays/notification/RuiNotification.vue"],"sourcesContent":["<script lang=\"ts\" setup>\nimport { useTimeoutFn } from '@vueuse/core';\nimport { transformPropsUnit } from '@/utils/helpers';\nimport { cn } from '@/utils/tv';\nimport { notificationStyles } from './notification-styles';\n\nexport interface NotificationProps {\n timeout: number;\n width?: number | string;\n theme?: 'light' | 'dark';\n}\n\ndefineOptions({\n name: 'RuiNotification',\n inheritAttrs: false,\n});\n\nconst modelValue = defineModel<boolean>({ required: true });\n\nconst { timeout, width = 400, theme } = defineProps<NotificationProps>();\n\ndefineSlots<{\n default?: () => any;\n}>();\n\nconst style = computed<{ width: string | undefined }>(() => ({\n width: transformPropsUnit(width),\n}));\n\nconst { start, stop } = useTimeoutFn(() => {\n set(modelValue, false);\n}, timeout, { immediate: false });\n\nfunction dismiss(): void {\n if (timeout < 0)\n return;\n\n set(modelValue, false);\n}\n\nwatchImmediate(modelValue, (display) => {\n if (!display) {\n stop();\n return;\n }\n\n if (timeout > 0) {\n stop();\n start();\n }\n});\n</script>\n\n<template>\n <Teleport to=\"body\">\n <Transition\n enter-from-class=\"opacity-0\"\n enter-active-class=\"ease-out duration-150\"\n enter-to-class=\"opacity-100\"\n leave-from-class=\"opacity-100\"\n leave-active-class=\"ease-in duration-100\"\n leave-to-class=\"opacity-0\"\n >\n <div\n v-if=\"modelValue\"\n role=\"alert\"\n aria-live=\"polite\"\n :class=\"notificationStyles({ class: cn([$attrs.class, {\n 'bg-rui-overlay border-rui-divider': !theme,\n 'bg-rui-light-overlay text-rui-light-text border-rui-light-divider': theme === 'light',\n 'bg-rui-dark-overlay text-rui-dark-text border-rui-dark-divider': theme === 'dark',\n }]) })\"\n :style=\"style\"\n v-bind=\"{ ...$attrs, class: undefined }\"\n @click=\"dismiss()\"\n >\n <slot />\n </div>\n </Transition>\n </Teleport>\n</template>\n"],"mappings":""}
1
+ {"version":3,"file":"RuiNotification.js","names":["_sfc_main"],"sources":["../../../../src/components/overlays/notification/RuiNotification.vue"],"sourcesContent":["<script lang=\"ts\" setup>\nimport type { HTMLAttributes } from 'vue';\nimport { useTimeoutFn } from '@vueuse/core';\nimport { transformPropsUnit } from '@/utils/helpers';\nimport { cn } from '@/utils/tv';\nimport { notificationStyles } from './notification-styles';\n\nexport interface NotificationProps {\n timeout: number;\n width?: number | string;\n theme?: 'light' | 'dark';\n}\n\ndefineOptions({\n name: 'RuiNotification',\n inheritAttrs: false,\n});\n\nconst modelValue = defineModel<boolean>({ required: true });\n\nconst { timeout, width = 400, theme } = defineProps<NotificationProps & /* @vue-ignore */ Omit<HTMLAttributes, keyof NotificationProps>>();\n\ndefineSlots<{\n default?: () => any;\n}>();\n\nconst style = computed<{ width: string | undefined }>(() => ({\n width: transformPropsUnit(width),\n}));\n\nconst { start, stop } = useTimeoutFn(() => {\n set(modelValue, false);\n}, timeout, { immediate: false });\n\nfunction dismiss(): void {\n if (timeout < 0)\n return;\n\n set(modelValue, false);\n}\n\nwatchImmediate(modelValue, (display) => {\n if (!display) {\n stop();\n return;\n }\n\n if (timeout > 0) {\n stop();\n start();\n }\n});\n</script>\n\n<template>\n <Teleport to=\"body\">\n <Transition\n enter-from-class=\"opacity-0\"\n enter-active-class=\"ease-out duration-150\"\n enter-to-class=\"opacity-100\"\n leave-from-class=\"opacity-100\"\n leave-active-class=\"ease-in duration-100\"\n leave-to-class=\"opacity-0\"\n >\n <div\n v-if=\"modelValue\"\n role=\"alert\"\n aria-live=\"polite\"\n :class=\"notificationStyles({ class: cn([$attrs.class, {\n 'bg-rui-overlay border-rui-divider': !theme,\n 'bg-rui-light-overlay text-rui-light-text border-rui-light-divider': theme === 'light',\n 'bg-rui-dark-overlay text-rui-dark-text border-rui-dark-divider': theme === 'dark',\n }]) })\"\n :style=\"style\"\n v-bind=\"{ ...$attrs, class: undefined }\"\n @click=\"dismiss()\"\n >\n <slot />\n </div>\n </Transition>\n </Teleport>\n</template>\n"],"mappings":""}
@@ -1,9 +1,10 @@
1
+ import type { HTMLAttributes } from 'vue';
1
2
  export interface NotificationProps {
2
3
  timeout: number;
3
4
  width?: number | string;
4
5
  theme?: 'light' | 'dark';
5
6
  }
6
- type __VLS_Props = NotificationProps;
7
+ type __VLS_Props = NotificationProps & /* @vue-ignore */ Omit<HTMLAttributes, keyof NotificationProps>;
7
8
  type __VLS_Slots = {
8
9
  default?: () => any;
9
10
  };
@@ -1 +1 @@
1
- {"version":3,"file":"RuiNotification.vue_vue_type_script_setup_true_lang.js","names":["$attrs","_useModel","_openBlock","_createBlock","_Teleport","_createVNode","_Transition","_withCtx","_createElementBlock","_mergeProps","_unref","_renderSlot","_createCommentVNode"],"sources":["../../../../src/components/overlays/notification/RuiNotification.vue"],"sourcesContent":["<script lang=\"ts\" setup>\nimport { useTimeoutFn } from '@vueuse/core';\nimport { transformPropsUnit } from '@/utils/helpers';\nimport { cn } from '@/utils/tv';\nimport { notificationStyles } from './notification-styles';\n\nexport interface NotificationProps {\n timeout: number;\n width?: number | string;\n theme?: 'light' | 'dark';\n}\n\ndefineOptions({\n name: 'RuiNotification',\n inheritAttrs: false,\n});\n\nconst modelValue = defineModel<boolean>({ required: true });\n\nconst { timeout, width = 400, theme } = defineProps<NotificationProps>();\n\ndefineSlots<{\n default?: () => any;\n}>();\n\nconst style = computed<{ width: string | undefined }>(() => ({\n width: transformPropsUnit(width),\n}));\n\nconst { start, stop } = useTimeoutFn(() => {\n set(modelValue, false);\n}, timeout, { immediate: false });\n\nfunction dismiss(): void {\n if (timeout < 0)\n return;\n\n set(modelValue, false);\n}\n\nwatchImmediate(modelValue, (display) => {\n if (!display) {\n stop();\n return;\n }\n\n if (timeout > 0) {\n stop();\n start();\n }\n});\n</script>\n\n<template>\n <Teleport to=\"body\">\n <Transition\n enter-from-class=\"opacity-0\"\n enter-active-class=\"ease-out duration-150\"\n enter-to-class=\"opacity-100\"\n leave-from-class=\"opacity-100\"\n leave-active-class=\"ease-in duration-100\"\n leave-to-class=\"opacity-0\"\n >\n <div\n v-if=\"modelValue\"\n role=\"alert\"\n aria-live=\"polite\"\n :class=\"notificationStyles({ class: cn([$attrs.class, {\n 'bg-rui-overlay border-rui-divider': !theme,\n 'bg-rui-light-overlay text-rui-light-text border-rui-light-divider': theme === 'light',\n 'bg-rui-dark-overlay text-rui-dark-text border-rui-dark-divider': theme === 'dark',\n }]) })\"\n :style=\"style\"\n v-bind=\"{ ...$attrs, class: undefined }\"\n @click=\"dismiss()\"\n >\n <slot />\n </div>\n </Transition>\n </Teleport>\n</template>\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;EAiBA,MAAM,aAAaC,SAAoB,SAAA,YAAmB;EAQ1D,MAAM,QAAQ,gBAA+C,EAC3D,OAAO,mBAAmB,QAAA,KAAK,EACjC,EAAE;EAEF,MAAM,EAAE,OAAO,SAAS,mBAAmB;GACzC,IAAI,YAAY,KAAK;EACvB,GAAG,QAAA,SAAS,EAAE,WAAW,MAAM,CAAC;EAEhC,SAAS,UAAgB;GACvB,IAAI,QAAA,UAAU,GACZ;GAEF,IAAI,YAAY,KAAK;EACvB;EAEA,eAAe,aAAa,YAAY;GACtC,IAAI,CAAC,SAAS;IACZ,KAAK;IACL;GACF;GAEA,IAAI,QAAA,UAAU,GAAG;IACf,KAAK;IACL,MAAM;GACR;EACF,CAAC;;GAIC,OAAAC,UAAA,GAAAC,YAyBWC,UAAA,EAzBD,IAAG,OAAM,GAAA,CACjBC,YAuBaC,YAAA;IAtBX,oBAAiB;IACjB,sBAAmB;IACnB,kBAAe;IACf,oBAAiB;IACjB,sBAAmB;IACnB,kBAAe;;IAEf,SAAAC,cAcM,CAbE,WAAA,SADRL,UAAA,GAAAM,mBAcM,OAdNC,WAcM;;KAZJ,MAAK;KACL,aAAU;KACT,OAAOC,MAAA,kBAAA,CAAkB,CAAA,EAAA,OAAUA,MAAA,EAAA,CAAE,CAAA,CAAEV,KAAAA,OAAO,OAAK;MAAoD,qCAAA,CAAA,QAAA;MAAsF,qEAAA,QAAA,UAAK;MAA0F,kEAAA,QAAA,UAAK;;KAKjS,OAAOU,MAAA,KAAA;IACKV,GAAAA;KAAAA,GAAAA,KAAAA;KAAM,OAAS,KAAA;IAAS,GAAA,EACpC,SAAK,OAAA,OAAA,OAAA,MAAA,WAAE,QAAO,GAAA,CAAA,GAAA,CAEfW,WAAQ,KAAA,QAAA,SAAA,CAAA,GAAA,EAAA,KAAA,mBAAA,IAAA,IAAA,CAAA,CAAA"}
1
+ {"version":3,"file":"RuiNotification.vue_vue_type_script_setup_true_lang.js","names":["$attrs","_useModel","_openBlock","_createBlock","_Teleport","_createVNode","_Transition","_withCtx","_createElementBlock","_mergeProps","_unref","_renderSlot","_createCommentVNode"],"sources":["../../../../src/components/overlays/notification/RuiNotification.vue"],"sourcesContent":["<script lang=\"ts\" setup>\nimport type { HTMLAttributes } from 'vue';\nimport { useTimeoutFn } from '@vueuse/core';\nimport { transformPropsUnit } from '@/utils/helpers';\nimport { cn } from '@/utils/tv';\nimport { notificationStyles } from './notification-styles';\n\nexport interface NotificationProps {\n timeout: number;\n width?: number | string;\n theme?: 'light' | 'dark';\n}\n\ndefineOptions({\n name: 'RuiNotification',\n inheritAttrs: false,\n});\n\nconst modelValue = defineModel<boolean>({ required: true });\n\nconst { timeout, width = 400, theme } = defineProps<NotificationProps & /* @vue-ignore */ Omit<HTMLAttributes, keyof NotificationProps>>();\n\ndefineSlots<{\n default?: () => any;\n}>();\n\nconst style = computed<{ width: string | undefined }>(() => ({\n width: transformPropsUnit(width),\n}));\n\nconst { start, stop } = useTimeoutFn(() => {\n set(modelValue, false);\n}, timeout, { immediate: false });\n\nfunction dismiss(): void {\n if (timeout < 0)\n return;\n\n set(modelValue, false);\n}\n\nwatchImmediate(modelValue, (display) => {\n if (!display) {\n stop();\n return;\n }\n\n if (timeout > 0) {\n stop();\n start();\n }\n});\n</script>\n\n<template>\n <Teleport to=\"body\">\n <Transition\n enter-from-class=\"opacity-0\"\n enter-active-class=\"ease-out duration-150\"\n enter-to-class=\"opacity-100\"\n leave-from-class=\"opacity-100\"\n leave-active-class=\"ease-in duration-100\"\n leave-to-class=\"opacity-0\"\n >\n <div\n v-if=\"modelValue\"\n role=\"alert\"\n aria-live=\"polite\"\n :class=\"notificationStyles({ class: cn([$attrs.class, {\n 'bg-rui-overlay border-rui-divider': !theme,\n 'bg-rui-light-overlay text-rui-light-text border-rui-light-divider': theme === 'light',\n 'bg-rui-dark-overlay text-rui-dark-text border-rui-dark-divider': theme === 'dark',\n }]) })\"\n :style=\"style\"\n v-bind=\"{ ...$attrs, class: undefined }\"\n @click=\"dismiss()\"\n >\n <slot />\n </div>\n </Transition>\n </Teleport>\n</template>\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;EAkBA,MAAM,aAAaC,SAAoB,SAAA,YAAmB;EAQ1D,MAAM,QAAQ,gBAA+C,EAC3D,OAAO,mBAAmB,QAAA,KAAK,EACjC,EAAE;EAEF,MAAM,EAAE,OAAO,SAAS,mBAAmB;GACzC,IAAI,YAAY,KAAK;EACvB,GAAG,QAAA,SAAS,EAAE,WAAW,MAAM,CAAC;EAEhC,SAAS,UAAgB;GACvB,IAAI,QAAA,UAAU,GACZ;GAEF,IAAI,YAAY,KAAK;EACvB;EAEA,eAAe,aAAa,YAAY;GACtC,IAAI,CAAC,SAAS;IACZ,KAAK;IACL;GACF;GAEA,IAAI,QAAA,UAAU,GAAG;IACf,KAAK;IACL,MAAM;GACR;EACF,CAAC;;GAIC,OAAAC,UAAA,GAAAC,YAyBWC,UAAA,EAzBD,IAAG,OAAM,GAAA,CACjBC,YAuBaC,YAAA;IAtBX,oBAAiB;IACjB,sBAAmB;IACnB,kBAAe;IACf,oBAAiB;IACjB,sBAAmB;IACnB,kBAAe;;IAEf,SAAAC,cAcM,CAbE,WAAA,SADRL,UAAA,GAAAM,mBAcM,OAdNC,WAcM;;KAZJ,MAAK;KACL,aAAU;KACT,OAAOC,MAAA,kBAAA,CAAkB,CAAA,EAAA,OAAUA,MAAA,EAAA,CAAE,CAAA,CAAEV,KAAAA,OAAO,OAAK;MAAoD,qCAAA,CAAA,QAAA;MAAsF,qEAAA,QAAA,UAAK;MAA0F,kEAAA,QAAA,UAAK;;KAKjS,OAAOU,MAAA,KAAA;IACKV,GAAAA;KAAAA,GAAAA,KAAAA;KAAM,OAAS,KAAA;IAAS,GAAA,EACpC,SAAK,OAAA,OAAA,OAAA,MAAA,WAAE,QAAO,GAAA,CAAA,GAAA,CAEfW,WAAQ,KAAA,QAAA,SAAA,CAAA,GAAA,EAAA,KAAA,mBAAA,IAAA,IAAA,CAAA,CAAA"}
@@ -1 +1 @@
1
- {"version":3,"file":"RuiTooltip.js","names":["_sfc_main"],"sources":["../../../../src/components/overlays/tooltip/RuiTooltip.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport type { Reactive } from 'vue';\nimport type { VueClassValue } from '@/types/class-value';\nimport { ButtonGroupBoundary } from '@/components/buttons/button-group/button-group-context';\nimport { type FloatingOptions, useFloating, type UseFloatingReturn } from '@/composables/floating';\nimport { cn } from '@/utils/tv';\nimport { tooltipPopoverStyles, tooltipRootStyles, tooltipStyles } from './tooltip-styles';\n\nexport interface RuiTooltipClassNames {\n root?: VueClassValue;\n tooltip?: VueClassValue;\n}\n\nexport interface Props {\n text?: string | null;\n disabled?: boolean;\n hideArrow?: boolean;\n openDelay?: number;\n closeDelay?: number;\n persistOnTooltipHover?: boolean;\n options?: FloatingOptions;\n classNames?: RuiTooltipClassNames;\n}\n\ndefineOptions({\n name: 'RuiTooltip',\n inheritAttrs: false,\n});\n\nconst {\n text = null,\n disabled = false,\n hideArrow = false,\n openDelay = 0,\n closeDelay = 500,\n persistOnTooltipHover = false,\n options,\n classNames,\n} = defineProps<Props>();\n\ndefineSlots<{\n activator?: (props: { open: boolean; close: () => void }) => any;\n default?: () => any;\n}>();\n\nconst tooltipId = useId();\nconst activator = useTemplateRef<HTMLElement>('activator');\nconst tooltip = useTemplateRef<HTMLElement>('tooltip');\n// Owned by this component, so a setup run on first use still stops on unmount\nconst setupScope = effectScope();\nconst floating = shallowRef<Reactive<UseFloatingReturn>>();\n\nconst open = computed<boolean>(() => get(floating)?.open ?? false);\nconst visible = computed<boolean>(() => get(floating)?.visible ?? false);\n\ntype PlacementSide = 'bottom' | 'left' | 'right' | 'top';\n\n/**\n * Sets the floating state up on the first hover, focus or `onOpen`, so a\n * table with a tooltip on every row pays only for the tooltips it shows. An\n * event that reaches the activator after unmount gets nothing back.\n */\nfunction setUp(): Reactive<UseFloatingReturn> | undefined {\n if (setupScope.active && !disabled && !get(floating)) {\n set(floating, setupScope.run(() => reactive(useFloating(\n () => options ?? {},\n () => disabled,\n () => openDelay,\n () => closeDelay,\n () => get(activator) ?? undefined,\n tooltip,\n ))));\n }\n return setupScope.active ? get(floating) : undefined;\n}\n\nfunction onOpen(immediate?: boolean): void {\n setUp()?.onOpen(immediate);\n}\n\nfunction onClose(immediate?: boolean): void {\n if (setupScope.active)\n get(floating)?.onClose(immediate);\n}\n\nfunction placementSide(placement: string): PlacementSide {\n if (placement.startsWith('top'))\n return 'top';\n if (placement.startsWith('left'))\n return 'left';\n if (placement.startsWith('right'))\n return 'right';\n return 'bottom';\n}\n\ndefineExpose({\n onOpen,\n onClose,\n});\n</script>\n\n<template>\n <div\n ref=\"activator\"\n v-bind=\"{ ...$attrs, class: undefined }\"\n :class=\"tooltipRootStyles({ class: cn($attrs.class) })\"\n :data-tooltip-disabled=\"disabled\"\n :aria-describedby=\"!disabled && open ? tooltipId : undefined\"\n @mouseover=\"onOpen()\"\n @mouseleave=\"onClose()\"\n @focusin=\"onOpen()\"\n @focusout=\"onClose()\"\n >\n <slot\n name=\"activator\"\n :open=\"open\"\n :close=\"onClose\"\n />\n\n <Teleport\n v-if=\"!disabled && floating\"\n to=\"body\"\n >\n <div\n v-if=\"visible\"\n :id=\"tooltipId\"\n ref=\"tooltip\"\n :class=\"tooltipPopoverStyles({ class: cn(classNames?.tooltip) })\"\n :role=\"open ? 'tooltip' : undefined\"\n :data-placement=\"floating.currentPlacement\"\n >\n <TransitionGroup\n enter-active-class=\"transition ease-out duration-200\"\n enter-from-class=\"opacity-0 translate-y-1\"\n enter-to-class=\"opacity-100 translate-y-0\"\n leave-active-class=\"transition ease-in duration-150\"\n leave-from-class=\"opacity-100 translate-y-0\"\n leave-to-class=\"opacity-0 translate-y-1\"\n @before-enter=\"floating?.updatePosition()\"\n @after-leave=\"floating?.onLeaveComplete()\"\n >\n <div\n v-if=\"open\"\n key=\"tooltip\"\n class=\"px-2 py-1.5 text-xs font-normal wrap-break-word bg-rui-neutral-900 dark:bg-rui-neutral-700 text-white rounded-rui-control shadow-rui-tooltip\"\n data-id=\"content\"\n @mouseover=\"persistOnTooltipHover && onOpen()\"\n @mouseleave=\"persistOnTooltipHover && onClose()\"\n >\n <ButtonGroupBoundary>\n <slot>\n {{ text }}\n </slot>\n </ButtonGroupBoundary>\n </div>\n <span\n v-if=\"!hideArrow\"\n key=\"arrow\"\n :class=\"tooltipStyles({ open, side: placementSide(floating.currentPlacement) }).arrow()\"\n data-id=\"arrow\"\n >\n <span :class=\"tooltipStyles({ open, side: placementSide(floating.currentPlacement) }).diamond()\" />\n </span>\n </TransitionGroup>\n </div>\n </Teleport>\n </div>\n</template>\n"],"mappings":""}
1
+ {"version":3,"file":"RuiTooltip.js","names":["_sfc_main"],"sources":["../../../../src/components/overlays/tooltip/RuiTooltip.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport type { HTMLAttributes, Reactive } from 'vue';\nimport type { VueClassValue } from '@/types/class-value';\nimport { ButtonGroupBoundary } from '@/components/buttons/button-group/button-group-context';\nimport { type FloatingOptions, useFloating, type UseFloatingReturn } from '@/composables/floating';\nimport { cn } from '@/utils/tv';\nimport { tooltipPopoverStyles, tooltipRootStyles, tooltipStyles } from './tooltip-styles';\n\nexport interface RuiTooltipClassNames {\n root?: VueClassValue;\n tooltip?: VueClassValue;\n}\n\nexport interface Props {\n text?: string | null;\n disabled?: boolean;\n hideArrow?: boolean;\n openDelay?: number;\n closeDelay?: number;\n persistOnTooltipHover?: boolean;\n options?: FloatingOptions;\n classNames?: RuiTooltipClassNames;\n}\n\ndefineOptions({\n name: 'RuiTooltip',\n inheritAttrs: false,\n});\n\nconst {\n text = null,\n disabled = false,\n hideArrow = false,\n openDelay = 0,\n closeDelay = 500,\n persistOnTooltipHover = false,\n options,\n classNames,\n} = defineProps<Props & /* @vue-ignore */ Omit<HTMLAttributes, keyof Props>>();\n\ndefineSlots<{\n activator?: (props: { open: boolean; close: () => void }) => any;\n default?: () => any;\n}>();\n\nconst tooltipId = useId();\nconst activator = useTemplateRef<HTMLElement>('activator');\nconst tooltip = useTemplateRef<HTMLElement>('tooltip');\n// Owned by this component, so a setup run on first use still stops on unmount\nconst setupScope = effectScope();\nconst floating = shallowRef<Reactive<UseFloatingReturn>>();\n\nconst open = computed<boolean>(() => get(floating)?.open ?? false);\nconst visible = computed<boolean>(() => get(floating)?.visible ?? false);\n\ntype PlacementSide = 'bottom' | 'left' | 'right' | 'top';\n\n/**\n * Sets the floating state up on the first hover, focus or `onOpen`, so a\n * table with a tooltip on every row pays only for the tooltips it shows. An\n * event that reaches the activator after unmount gets nothing back.\n */\nfunction setUp(): Reactive<UseFloatingReturn> | undefined {\n if (setupScope.active && !disabled && !get(floating)) {\n set(floating, setupScope.run(() => reactive(useFloating(\n () => options ?? {},\n () => disabled,\n () => openDelay,\n () => closeDelay,\n () => get(activator) ?? undefined,\n tooltip,\n ))));\n }\n return setupScope.active ? get(floating) : undefined;\n}\n\nfunction onOpen(immediate?: boolean): void {\n setUp()?.onOpen(immediate);\n}\n\nfunction onClose(immediate?: boolean): void {\n if (setupScope.active)\n get(floating)?.onClose(immediate);\n}\n\nfunction placementSide(placement: string): PlacementSide {\n if (placement.startsWith('top'))\n return 'top';\n if (placement.startsWith('left'))\n return 'left';\n if (placement.startsWith('right'))\n return 'right';\n return 'bottom';\n}\n\ndefineExpose({\n onOpen,\n onClose,\n});\n</script>\n\n<template>\n <div\n ref=\"activator\"\n v-bind=\"{ ...$attrs, class: undefined }\"\n :class=\"tooltipRootStyles({ class: cn($attrs.class) })\"\n :data-tooltip-disabled=\"disabled\"\n :aria-describedby=\"!disabled && open ? tooltipId : undefined\"\n @mouseover=\"onOpen()\"\n @mouseleave=\"onClose()\"\n @focusin=\"onOpen()\"\n @focusout=\"onClose()\"\n >\n <slot\n name=\"activator\"\n :open=\"open\"\n :close=\"onClose\"\n />\n\n <Teleport\n v-if=\"!disabled && floating\"\n to=\"body\"\n >\n <div\n v-if=\"visible\"\n :id=\"tooltipId\"\n ref=\"tooltip\"\n :class=\"tooltipPopoverStyles({ class: cn(classNames?.tooltip) })\"\n :role=\"open ? 'tooltip' : undefined\"\n :data-placement=\"floating.currentPlacement\"\n >\n <TransitionGroup\n enter-active-class=\"transition ease-out duration-200\"\n enter-from-class=\"opacity-0 translate-y-1\"\n enter-to-class=\"opacity-100 translate-y-0\"\n leave-active-class=\"transition ease-in duration-150\"\n leave-from-class=\"opacity-100 translate-y-0\"\n leave-to-class=\"opacity-0 translate-y-1\"\n @before-enter=\"floating?.updatePosition()\"\n @after-leave=\"floating?.onLeaveComplete()\"\n >\n <div\n v-if=\"open\"\n key=\"tooltip\"\n class=\"px-2 py-1.5 text-xs font-normal wrap-break-word bg-rui-neutral-900 dark:bg-rui-neutral-700 text-white rounded-rui-control shadow-rui-tooltip\"\n data-id=\"content\"\n @mouseover=\"persistOnTooltipHover && onOpen()\"\n @mouseleave=\"persistOnTooltipHover && onClose()\"\n >\n <ButtonGroupBoundary>\n <slot>\n {{ text }}\n </slot>\n </ButtonGroupBoundary>\n </div>\n <span\n v-if=\"!hideArrow\"\n key=\"arrow\"\n :class=\"tooltipStyles({ open, side: placementSide(floating.currentPlacement) }).arrow()\"\n data-id=\"arrow\"\n >\n <span :class=\"tooltipStyles({ open, side: placementSide(floating.currentPlacement) }).diamond()\" />\n </span>\n </TransitionGroup>\n </div>\n </Teleport>\n </div>\n</template>\n"],"mappings":""}
@@ -1,3 +1,4 @@
1
+ import type { HTMLAttributes } from 'vue';
1
2
  import type { VueClassValue } from '../../../types/class-value.js';
2
3
  import { type FloatingOptions } from '../../../composables/floating.js';
3
4
  export interface RuiTooltipClassNames {
@@ -14,6 +15,7 @@ export interface Props {
14
15
  options?: FloatingOptions;
15
16
  classNames?: RuiTooltipClassNames;
16
17
  }
18
+ type __VLS_Props = Props & /* @vue-ignore */ Omit<HTMLAttributes, keyof Props>;
17
19
  type __VLS_Slots = {
18
20
  activator?: (props: {
19
21
  open: boolean;
@@ -23,10 +25,10 @@ type __VLS_Slots = {
23
25
  };
24
26
  declare function onOpen(immediate?: boolean): void;
25
27
  declare function onClose(immediate?: boolean): void;
26
- declare const __VLS_base: import("vue").DefineComponent<Props, {
28
+ declare const __VLS_base: import("vue").DefineComponent<__VLS_Props, {
27
29
  onOpen: typeof onOpen;
28
30
  onClose: typeof onClose;
29
- }, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<Props> & Readonly<{}>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
31
+ }, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<__VLS_Props> & Readonly<{}>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
30
32
  declare const __VLS_export: __VLS_WithSlots<typeof __VLS_base, __VLS_Slots>;
31
33
  declare const _default: typeof __VLS_export;
32
34
  export default _default;
@@ -1 +1 @@
1
- {"version":3,"file":"RuiTooltip.vue_vue_type_script_setup_true_lang.js","names":["$attrs","_openBlock","_createElementBlock","_mergeProps","_unref","_renderSlot","_createBlock","_Teleport","_normalizeClass","_createVNode","_TransitionGroup","_withCtx","_createTextVNode","_toDisplayString","_createCommentVNode","_createElementVNode"],"sources":["../../../../src/components/overlays/tooltip/RuiTooltip.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport type { Reactive } from 'vue';\nimport type { VueClassValue } from '@/types/class-value';\nimport { ButtonGroupBoundary } from '@/components/buttons/button-group/button-group-context';\nimport { type FloatingOptions, useFloating, type UseFloatingReturn } from '@/composables/floating';\nimport { cn } from '@/utils/tv';\nimport { tooltipPopoverStyles, tooltipRootStyles, tooltipStyles } from './tooltip-styles';\n\nexport interface RuiTooltipClassNames {\n root?: VueClassValue;\n tooltip?: VueClassValue;\n}\n\nexport interface Props {\n text?: string | null;\n disabled?: boolean;\n hideArrow?: boolean;\n openDelay?: number;\n closeDelay?: number;\n persistOnTooltipHover?: boolean;\n options?: FloatingOptions;\n classNames?: RuiTooltipClassNames;\n}\n\ndefineOptions({\n name: 'RuiTooltip',\n inheritAttrs: false,\n});\n\nconst {\n text = null,\n disabled = false,\n hideArrow = false,\n openDelay = 0,\n closeDelay = 500,\n persistOnTooltipHover = false,\n options,\n classNames,\n} = defineProps<Props>();\n\ndefineSlots<{\n activator?: (props: { open: boolean; close: () => void }) => any;\n default?: () => any;\n}>();\n\nconst tooltipId = useId();\nconst activator = useTemplateRef<HTMLElement>('activator');\nconst tooltip = useTemplateRef<HTMLElement>('tooltip');\n// Owned by this component, so a setup run on first use still stops on unmount\nconst setupScope = effectScope();\nconst floating = shallowRef<Reactive<UseFloatingReturn>>();\n\nconst open = computed<boolean>(() => get(floating)?.open ?? false);\nconst visible = computed<boolean>(() => get(floating)?.visible ?? false);\n\ntype PlacementSide = 'bottom' | 'left' | 'right' | 'top';\n\n/**\n * Sets the floating state up on the first hover, focus or `onOpen`, so a\n * table with a tooltip on every row pays only for the tooltips it shows. An\n * event that reaches the activator after unmount gets nothing back.\n */\nfunction setUp(): Reactive<UseFloatingReturn> | undefined {\n if (setupScope.active && !disabled && !get(floating)) {\n set(floating, setupScope.run(() => reactive(useFloating(\n () => options ?? {},\n () => disabled,\n () => openDelay,\n () => closeDelay,\n () => get(activator) ?? undefined,\n tooltip,\n ))));\n }\n return setupScope.active ? get(floating) : undefined;\n}\n\nfunction onOpen(immediate?: boolean): void {\n setUp()?.onOpen(immediate);\n}\n\nfunction onClose(immediate?: boolean): void {\n if (setupScope.active)\n get(floating)?.onClose(immediate);\n}\n\nfunction placementSide(placement: string): PlacementSide {\n if (placement.startsWith('top'))\n return 'top';\n if (placement.startsWith('left'))\n return 'left';\n if (placement.startsWith('right'))\n return 'right';\n return 'bottom';\n}\n\ndefineExpose({\n onOpen,\n onClose,\n});\n</script>\n\n<template>\n <div\n ref=\"activator\"\n v-bind=\"{ ...$attrs, class: undefined }\"\n :class=\"tooltipRootStyles({ class: cn($attrs.class) })\"\n :data-tooltip-disabled=\"disabled\"\n :aria-describedby=\"!disabled && open ? tooltipId : undefined\"\n @mouseover=\"onOpen()\"\n @mouseleave=\"onClose()\"\n @focusin=\"onOpen()\"\n @focusout=\"onClose()\"\n >\n <slot\n name=\"activator\"\n :open=\"open\"\n :close=\"onClose\"\n />\n\n <Teleport\n v-if=\"!disabled && floating\"\n to=\"body\"\n >\n <div\n v-if=\"visible\"\n :id=\"tooltipId\"\n ref=\"tooltip\"\n :class=\"tooltipPopoverStyles({ class: cn(classNames?.tooltip) })\"\n :role=\"open ? 'tooltip' : undefined\"\n :data-placement=\"floating.currentPlacement\"\n >\n <TransitionGroup\n enter-active-class=\"transition ease-out duration-200\"\n enter-from-class=\"opacity-0 translate-y-1\"\n enter-to-class=\"opacity-100 translate-y-0\"\n leave-active-class=\"transition ease-in duration-150\"\n leave-from-class=\"opacity-100 translate-y-0\"\n leave-to-class=\"opacity-0 translate-y-1\"\n @before-enter=\"floating?.updatePosition()\"\n @after-leave=\"floating?.onLeaveComplete()\"\n >\n <div\n v-if=\"open\"\n key=\"tooltip\"\n class=\"px-2 py-1.5 text-xs font-normal wrap-break-word bg-rui-neutral-900 dark:bg-rui-neutral-700 text-white rounded-rui-control shadow-rui-tooltip\"\n data-id=\"content\"\n @mouseover=\"persistOnTooltipHover && onOpen()\"\n @mouseleave=\"persistOnTooltipHover && onClose()\"\n >\n <ButtonGroupBoundary>\n <slot>\n {{ text }}\n </slot>\n </ButtonGroupBoundary>\n </div>\n <span\n v-if=\"!hideArrow\"\n key=\"arrow\"\n :class=\"tooltipStyles({ open, side: placementSide(floating.currentPlacement) }).arrow()\"\n data-id=\"arrow\"\n >\n <span :class=\"tooltipStyles({ open, side: placementSide(floating.currentPlacement) }).diamond()\" />\n </span>\n </TransitionGroup>\n </div>\n </Teleport>\n </div>\n</template>\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EA6CA,MAAM,YAAY,MAAM;EACxB,MAAM,YAAY,eAA4B,WAAW;EACzD,MAAM,UAAU,eAA4B,SAAS;EAErD,MAAM,aAAa,YAAY;EAC/B,MAAM,WAAW,WAAwC;EAEzD,MAAM,OAAO,eAAwB,IAAI,QAAQ,CAAC,EAAE,QAAQ,KAAK;EACjE,MAAM,UAAU,eAAwB,IAAI,QAAQ,CAAC,EAAE,WAAW,KAAK;EASvE,SAAS,QAAiD;GACxD,IAAI,WAAW,UAAU,CAAC,QAAA,YAAY,CAAC,IAAI,QAAQ,GACjD,IAAI,UAAU,WAAW,UAAU,SAAS,kBACpC,QAAA,WAAW,CAAC,SACZ,QAAA,gBACA,QAAA,iBACA,QAAA,kBACA,IAAI,SAAS,KAAK,KAAA,GACxB,OACF,CAAC,CAAC,CAAC;GAEL,OAAO,WAAW,SAAS,IAAI,QAAQ,IAAI,KAAA;EAC7C;EAEA,SAAS,OAAO,WAA2B;GACzC,MAAM,CAAC,EAAE,OAAO,SAAS;EAC3B;EAEA,SAAS,QAAQ,WAA2B;GAC1C,IAAI,WAAW,QACb,IAAI,QAAQ,CAAC,EAAE,QAAQ,SAAS;EACpC;EAEA,SAAS,cAAc,WAAkC;GACvD,IAAI,UAAU,WAAW,KAAK,GAC5B,OAAO;GACT,IAAI,UAAU,WAAW,MAAM,GAC7B,OAAO;GACT,IAAI,UAAU,WAAW,OAAO,GAC9B,OAAO;GACT,OAAO;EACT;EAEA,SAAa;GACX;GACA;EACF,CAAC;;GAIC,OAAAC,UAAA,GAAAC,mBAgEM,OAhENC,WAgEM;IA/DA,SAAA;IAAJ,KAAI;GACSH,GAAAA;IAAAA,GAAAA,KAAAA;IAAM,OAAS,KAAA;GAAS,GAAA;IACpC,OAAOI,MAAA,iBAAA,CAAiB,CAAA,EAAA,OAAUA,MAAA,EAAA,CAAE,CAACJ,KAAAA,OAAO,KAAK,EAAA,CAAA;IACjD,yBAAuB,QAAA;IACvB,oBAAgB,CAAG,QAAA,YAAYI,MAAA,IAAA,IAAOA,MAAA,SAAA,IAAY,KAAA;IAClD,aAAS,OAAA,OAAA,OAAA,MAAA,WAAE,OAAM;IACjB,cAAU,OAAA,OAAA,OAAA,MAAA,WAAE,QAAO;IACnB,WAAO,OAAA,OAAA,OAAA,MAAA,WAAE,OAAM;IACf,YAAQ,OAAA,OAAA,OAAA,MAAA,WAAE,QAAO;GAElBC,CAAAA,GAAAA,CAAAA,WAIE,KAAA,QAAA,aAAA;IAFC,MAAMD,MAAA,IAAA;IACN,OAAO;GAID,CAAA,GAAA,CAAA,QAAA,YAAYA,MAAA,QAAA,KADrBH,UAAA,GAAAK,YA8CWC,UAAA;;IA5CT,IAAG;GAGKH,GAAAA,CAAAA,MAAA,OAAA,KADRH,UAAA,GAAAC,mBAyCM,OAAA;;IAvCH,IAAIE,MAAA,SAAA;IACD,SAAA;IAAJ,KAAI;IACH,OAAKI,eAAEJ,MAAA,oBAAA,CAAoB,CAAA,EAAA,OAAUA,MAAA,EAAA,CAAE,CAAC,QAAA,YAAY,OAAO,EAAA,CAAA,CAAA;IAC3D,MAAMA,MAAA,IAAA,IAAI,YAAe,KAAA;IACzB,kBAAgBA,MAAA,QAAA,CAAQ,CAAC;GAE1BK,GAAAA,CAAAA,YAgCkBC,iBAAA;IA/BhB,sBAAmB;IACnB,oBAAiB;IACjB,kBAAe;IACf,sBAAmB;IACnB,oBAAiB;IACjB,kBAAe;IACd,eAAY,OAAA,OAAA,OAAA,MAAA,WAAEN,MAAA,QAAA,CAAQ,EAAE,eAAc;IACtC,cAAW,OAAA,OAAA,OAAA,MAAA,WAAEA,MAAA,QAAA,CAAQ,EAAE,gBAAe;;IAEvC,SAAAO,cAaM,CAZEP,MAAA,IAAA,KADRH,UAAA,GAAAC,mBAaM,OAAA;KAXJ,KAAI;KACJ,OAAM;KACN,WAAQ;KACP,aAAS,OAAA,OAAA,OAAA,MAAA,WAAE,QAAA,yBAAyB,OAAM;KAC1C,cAAU,OAAA,OAAA,OAAA,MAAA,WAAE,QAAA,yBAAyB,QAAO;IAE7CO,GAAAA,CAAAA,YAIsBL,MAAA,mBAAA,GAAA,MAAA;KAHpB,SAAAO,cAEO,CAFPN,WAEO,KAAA,QAAA,WAAA,CAAA,SAAA,CADFO,gBAAAC,gBAAA,QAAA,IAAI,GAAA,CAAA,CAAA,CAAA,CAAA,CAAA;;IAKJ,CAAA,CAAA,GAAA,EAAA,KAAA,mBAAA,IAAA,IAAA,GAAA,CAAA,QAAA,aADTZ,UAAA,GAAAC,mBAOO,QAAA;KALL,KAAI;KACH,OAAKM,eAAEJ,MAAA,aAAA,CAAa,CAAA;MAAA,MAAGA,MAAA,IAAA;MAAI,MAAQ,cAAcA,MAAA,QAAA,CAAQ,CAAC,gBAAgB;KAAA,CAAA,CAAA,CAAK,MAAK,CAAA;KACrF,WAAQ;IAERW,GAAAA,CAAAA,mBAAmG,QAAA,EAA5F,OAAKP,eAAEJ,MAAA,aAAA,CAAa,CAAA;KAAA,MAAGA,MAAA,IAAA;KAAI,MAAQ,cAAcA,MAAA,QAAA,CAAQ,CAAC,gBAAgB;IAAA,CAAA,CAAA,CAAK,QAAO,CAAA,EAAA,GAAA,MAAA,CAAA,CAAA,GAAA,CAAA,KAAA,mBAAA,IAAA,IAAA,CAAA,CAAA"}
1
+ {"version":3,"file":"RuiTooltip.vue_vue_type_script_setup_true_lang.js","names":["$attrs","_openBlock","_createElementBlock","_mergeProps","_unref","_renderSlot","_createBlock","_Teleport","_normalizeClass","_createVNode","_TransitionGroup","_withCtx","_createTextVNode","_toDisplayString","_createCommentVNode","_createElementVNode"],"sources":["../../../../src/components/overlays/tooltip/RuiTooltip.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport type { HTMLAttributes, Reactive } from 'vue';\nimport type { VueClassValue } from '@/types/class-value';\nimport { ButtonGroupBoundary } from '@/components/buttons/button-group/button-group-context';\nimport { type FloatingOptions, useFloating, type UseFloatingReturn } from '@/composables/floating';\nimport { cn } from '@/utils/tv';\nimport { tooltipPopoverStyles, tooltipRootStyles, tooltipStyles } from './tooltip-styles';\n\nexport interface RuiTooltipClassNames {\n root?: VueClassValue;\n tooltip?: VueClassValue;\n}\n\nexport interface Props {\n text?: string | null;\n disabled?: boolean;\n hideArrow?: boolean;\n openDelay?: number;\n closeDelay?: number;\n persistOnTooltipHover?: boolean;\n options?: FloatingOptions;\n classNames?: RuiTooltipClassNames;\n}\n\ndefineOptions({\n name: 'RuiTooltip',\n inheritAttrs: false,\n});\n\nconst {\n text = null,\n disabled = false,\n hideArrow = false,\n openDelay = 0,\n closeDelay = 500,\n persistOnTooltipHover = false,\n options,\n classNames,\n} = defineProps<Props & /* @vue-ignore */ Omit<HTMLAttributes, keyof Props>>();\n\ndefineSlots<{\n activator?: (props: { open: boolean; close: () => void }) => any;\n default?: () => any;\n}>();\n\nconst tooltipId = useId();\nconst activator = useTemplateRef<HTMLElement>('activator');\nconst tooltip = useTemplateRef<HTMLElement>('tooltip');\n// Owned by this component, so a setup run on first use still stops on unmount\nconst setupScope = effectScope();\nconst floating = shallowRef<Reactive<UseFloatingReturn>>();\n\nconst open = computed<boolean>(() => get(floating)?.open ?? false);\nconst visible = computed<boolean>(() => get(floating)?.visible ?? false);\n\ntype PlacementSide = 'bottom' | 'left' | 'right' | 'top';\n\n/**\n * Sets the floating state up on the first hover, focus or `onOpen`, so a\n * table with a tooltip on every row pays only for the tooltips it shows. An\n * event that reaches the activator after unmount gets nothing back.\n */\nfunction setUp(): Reactive<UseFloatingReturn> | undefined {\n if (setupScope.active && !disabled && !get(floating)) {\n set(floating, setupScope.run(() => reactive(useFloating(\n () => options ?? {},\n () => disabled,\n () => openDelay,\n () => closeDelay,\n () => get(activator) ?? undefined,\n tooltip,\n ))));\n }\n return setupScope.active ? get(floating) : undefined;\n}\n\nfunction onOpen(immediate?: boolean): void {\n setUp()?.onOpen(immediate);\n}\n\nfunction onClose(immediate?: boolean): void {\n if (setupScope.active)\n get(floating)?.onClose(immediate);\n}\n\nfunction placementSide(placement: string): PlacementSide {\n if (placement.startsWith('top'))\n return 'top';\n if (placement.startsWith('left'))\n return 'left';\n if (placement.startsWith('right'))\n return 'right';\n return 'bottom';\n}\n\ndefineExpose({\n onOpen,\n onClose,\n});\n</script>\n\n<template>\n <div\n ref=\"activator\"\n v-bind=\"{ ...$attrs, class: undefined }\"\n :class=\"tooltipRootStyles({ class: cn($attrs.class) })\"\n :data-tooltip-disabled=\"disabled\"\n :aria-describedby=\"!disabled && open ? tooltipId : undefined\"\n @mouseover=\"onOpen()\"\n @mouseleave=\"onClose()\"\n @focusin=\"onOpen()\"\n @focusout=\"onClose()\"\n >\n <slot\n name=\"activator\"\n :open=\"open\"\n :close=\"onClose\"\n />\n\n <Teleport\n v-if=\"!disabled && floating\"\n to=\"body\"\n >\n <div\n v-if=\"visible\"\n :id=\"tooltipId\"\n ref=\"tooltip\"\n :class=\"tooltipPopoverStyles({ class: cn(classNames?.tooltip) })\"\n :role=\"open ? 'tooltip' : undefined\"\n :data-placement=\"floating.currentPlacement\"\n >\n <TransitionGroup\n enter-active-class=\"transition ease-out duration-200\"\n enter-from-class=\"opacity-0 translate-y-1\"\n enter-to-class=\"opacity-100 translate-y-0\"\n leave-active-class=\"transition ease-in duration-150\"\n leave-from-class=\"opacity-100 translate-y-0\"\n leave-to-class=\"opacity-0 translate-y-1\"\n @before-enter=\"floating?.updatePosition()\"\n @after-leave=\"floating?.onLeaveComplete()\"\n >\n <div\n v-if=\"open\"\n key=\"tooltip\"\n class=\"px-2 py-1.5 text-xs font-normal wrap-break-word bg-rui-neutral-900 dark:bg-rui-neutral-700 text-white rounded-rui-control shadow-rui-tooltip\"\n data-id=\"content\"\n @mouseover=\"persistOnTooltipHover && onOpen()\"\n @mouseleave=\"persistOnTooltipHover && onClose()\"\n >\n <ButtonGroupBoundary>\n <slot>\n {{ text }}\n </slot>\n </ButtonGroupBoundary>\n </div>\n <span\n v-if=\"!hideArrow\"\n key=\"arrow\"\n :class=\"tooltipStyles({ open, side: placementSide(floating.currentPlacement) }).arrow()\"\n data-id=\"arrow\"\n >\n <span :class=\"tooltipStyles({ open, side: placementSide(floating.currentPlacement) }).diamond()\" />\n </span>\n </TransitionGroup>\n </div>\n </Teleport>\n </div>\n</template>\n"],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"RuiProgress.js","names":["_sfc_main"],"sources":["../../../src/components/progress/RuiProgress.vue"],"sourcesContent":["<script lang=\"ts\" setup>\nimport type { ContextColorsType } from '@/consts/colors';\nimport { ProgressVariant } from '@/components/progress/progress-props';\nimport { progressStyles } from './progress-styles';\n\nexport interface Props {\n /**\n * in percentage value, required when variant === determinate or buffer\n * Ranges from 0 to 100.\n */\n value?: number;\n /**\n * in percentage value, required when variant === buffer\n * Ranges from 0 to 100.\n */\n bufferValue?: number;\n variant?: ProgressVariant;\n color?: ContextColorsType | 'inherit';\n circular?: boolean;\n showLabel?: boolean;\n /**\n * Sets the stroke thickness in pixels\n */\n thickness?: number | string;\n /**\n * only used for circular progress\n */\n size?: number | string;\n /**\n * What is loading, as the progress bar's accessible name (\"Loading\" when not given)\n */\n ariaLabel?: string;\n}\n\ndefineOptions({\n name: 'RuiProgress',\n});\n\nconst {\n value = 0,\n bufferValue = 0,\n variant = ProgressVariant.determinate,\n color = 'inherit',\n circular = false,\n showLabel = false,\n thickness = 4,\n size = 40,\n ariaLabel = 'Loading',\n} = defineProps<Props>();\n\ndefineSlots<Record<string, never>>();\n\nconst CIRCLE_RADIUS = 20;\nconst CIRCLE_CIRCUMFERENCE = 2 * Math.PI * CIRCLE_RADIUS; // ~125.66\n/** width of `100%` in ems, measured with tabular figures */\nconst LABEL_WIDTH_EM = 2.95;\n/** keeps the label off the stroke rather than merely inside it */\nconst LABEL_BREATHING_ROOM = 0.9;\n/** below this font size a label inside the ring is unreadable, so the ring drops it rather than change its footprint */\nconst MIN_INSIDE_LABEL_PX = 9;\n\nfunction clampPercent(val: number | undefined): number {\n return Math.max(0, Math.min(val ?? 100, 100));\n}\n\nconst hasLabel = computed<boolean>(() => showLabel && variant !== ProgressVariant.indeterminate);\n\n/**\n * The font size that fits the widest label (`100%`) inside the ring, solved against the chord\n * it spans. Always computed for that widest label so the text does not resize as the value climbs.\n */\nconst insideLabelFit = computed<number>(() => {\n const innerRadius = Math.max((+size - 2 * +thickness) / 2, 0);\n return (LABEL_BREATHING_ROOM * 2 * innerRadius) / Math.sqrt(LABEL_WIDTH_EM ** 2 + 1);\n});\n\nconst labelFits = computed<boolean>(() => get(insideLabelFit) >= MIN_INSIDE_LABEL_PX);\n\nconst ui = computed<ReturnType<typeof progressStyles>>(() => progressStyles({\n color,\n variant,\n circular,\n hasLabel: get(hasLabel),\n}));\n\nconst currentValue = computed<number>(() => clampPercent(value));\n\n/** An indeterminate bar has no value to report, so it leaves `aria-valuenow` off. */\nconst ariaValueNow = computed<number | undefined>(() =>\n variant === ProgressVariant.indeterminate ? undefined : get(currentValue));\n\nconst label = computed<string>(() => `${Math.floor(get(currentValue))}%`);\n\nconst progress = computed<number>(() => -100 + get(currentValue));\n\nconst barStyle = computed<Record<string, string>>(() => ({\n transform: `translateX(${get(progress)}%)`,\n}));\n\nconst bufferRailStyle = computed<Record<string, string>>(() => ({\n transform: `translateX(${-100 + clampPercent(bufferValue)}%)`,\n}));\n\nconst linearStyle = computed<Record<string, string>>(() => ({\n height: `${+thickness}px`,\n}));\n\nconst circularSize = computed<Record<string, string>>(() => ({\n width: `${+size}px`,\n height: `${+size}px`,\n}));\n\nconst circularGeometry = computed<{ scaledThickness: number; viewSize: number }>(() => {\n const scaledThickness = (+thickness * 32) / +size;\n return { scaledThickness, viewSize: 40 + scaledThickness };\n});\n\n/**\n * The label inside the ring scales with both `size` and `thickness`. The fit is capped by\n * a sublinear curve so large rings do not end up with an oversized number in the middle.\n */\nconst circularLabelStyle = computed<Record<string, string>>(() => ({\n fontSize: `${Math.min(get(insideLabelFit), +size * 0.15 + 6)}px`,\n}));\n\nconst circularStrokeStyle = computed<Record<string, string>>(() => ({\n strokeDasharray: `${CIRCLE_CIRCUMFERENCE}`,\n strokeDashoffset: `${(get(progress) / 100) * -CIRCLE_CIRCUMFERENCE}`,\n // the library's own motion, not Material's standard curve\n transition: 'stroke-dashoffset 200ms ease-out',\n}));\n</script>\n\n<template>\n <div :class=\"ui.wrapper()\">\n <!-- Circular progress (not supported for buffer variant) -->\n <div\n v-if=\"circular && variant !== ProgressVariant.buffer\"\n :aria-valuenow=\"ariaValueNow\"\n :class=\"ui.circularContainer()\"\n :style=\"circularSize\"\n :data-variant=\"variant\"\n :data-color=\"color\"\n :aria-label=\"ariaLabel\"\n :title=\"hasLabel && !labelFits ? label : undefined\"\n aria-valuemax=\"100\"\n aria-valuemin=\"0\"\n role=\"progressbar\"\n >\n <svg\n :class=\"ui.svg()\"\n :viewBox=\"`0 0 ${circularGeometry.viewSize} ${circularGeometry.viewSize}`\"\n >\n <!-- Track behind the arc, mirroring the linear rail. Indeterminate spins, so it gets no track. -->\n <circle\n v-if=\"variant === ProgressVariant.determinate\"\n cx=\"50%\"\n cy=\"50%\"\n fill=\"none\"\n :r=\"CIRCLE_RADIUS\"\n :class=\"ui.circleTrack()\"\n :stroke-width=\"circularGeometry.scaledThickness\"\n />\n <circle\n cx=\"50%\"\n cy=\"50%\"\n fill=\"none\"\n :r=\"CIRCLE_RADIUS\"\n :class=\"ui.circle()\"\n :style=\"variant === ProgressVariant.determinate ? circularStrokeStyle : undefined\"\n :stroke-width=\"circularGeometry.scaledThickness\"\n />\n </svg>\n <div\n v-if=\"hasLabel && labelFits\"\n :class=\"ui.label()\"\n :style=\"circularLabelStyle\"\n aria-hidden=\"true\"\n >\n {{ label }}\n </div>\n </div>\n\n <!-- Linear progress (also used as fallback for circular + buffer) -->\n <div\n v-else\n :aria-valuenow=\"ariaValueNow\"\n :class=\"ui.progressbar()\"\n :style=\"linearStyle\"\n :data-variant=\"variant\"\n :data-color=\"color\"\n :aria-label=\"ariaLabel\"\n aria-valuemax=\"100\"\n aria-valuemin=\"0\"\n role=\"progressbar\"\n >\n <div\n v-if=\"variant === ProgressVariant.buffer\"\n :class=\"ui.bufferDots()\"\n />\n <div\n :class=\"variant === ProgressVariant.buffer ? [ui.rail(), ui.bufferRail()] : ui.rail()\"\n :style=\"variant === ProgressVariant.buffer ? bufferRailStyle : undefined\"\n data-id=\"progress-rail\"\n />\n <div\n v-if=\"variant === ProgressVariant.indeterminate\"\n :class=\"ui.indeterminateBar()\"\n />\n <div\n v-else\n :class=\"ui.bar()\"\n :style=\"barStyle\"\n />\n </div>\n\n <!-- Linear label -->\n <div\n v-if=\"hasLabel && !circular\"\n :class=\"ui.label()\"\n >\n {{ label }}\n </div>\n </div>\n</template>\n"],"mappings":""}
1
+ {"version":3,"file":"RuiProgress.js","names":["_sfc_main"],"sources":["../../../src/components/progress/RuiProgress.vue"],"sourcesContent":["<script lang=\"ts\" setup>\nimport type { HTMLAttributes } from 'vue';\nimport type { ContextColorsType } from '@/consts/colors';\nimport { ProgressVariant } from '@/components/progress/progress-props';\nimport { progressStyles } from './progress-styles';\n\nexport interface Props {\n /**\n * in percentage value, required when variant === determinate or buffer\n * Ranges from 0 to 100.\n */\n value?: number;\n /**\n * in percentage value, required when variant === buffer\n * Ranges from 0 to 100.\n */\n bufferValue?: number;\n variant?: ProgressVariant;\n color?: ContextColorsType | 'inherit';\n circular?: boolean;\n showLabel?: boolean;\n /**\n * Sets the stroke thickness in pixels\n */\n thickness?: number | string;\n /**\n * only used for circular progress\n */\n size?: number | string;\n /**\n * What is loading, as the progress bar's accessible name (\"Loading\" when not given)\n */\n ariaLabel?: string;\n}\n\ndefineOptions({\n name: 'RuiProgress',\n});\n\nconst {\n value = 0,\n bufferValue = 0,\n variant = ProgressVariant.determinate,\n color = 'inherit',\n circular = false,\n showLabel = false,\n thickness = 4,\n size = 40,\n ariaLabel = 'Loading',\n} = defineProps<Props & /* @vue-ignore */ Omit<HTMLAttributes, keyof Props>>();\n\ndefineSlots<Record<string, never>>();\n\nconst CIRCLE_RADIUS = 20;\nconst CIRCLE_CIRCUMFERENCE = 2 * Math.PI * CIRCLE_RADIUS; // ~125.66\n/** width of `100%` in ems, measured with tabular figures */\nconst LABEL_WIDTH_EM = 2.95;\n/** keeps the label off the stroke rather than merely inside it */\nconst LABEL_BREATHING_ROOM = 0.9;\n/** below this font size a label inside the ring is unreadable, so the ring drops it rather than change its footprint */\nconst MIN_INSIDE_LABEL_PX = 9;\n\nfunction clampPercent(val: number | undefined): number {\n return Math.max(0, Math.min(val ?? 100, 100));\n}\n\nconst hasLabel = computed<boolean>(() => showLabel && variant !== ProgressVariant.indeterminate);\n\n/**\n * The font size that fits the widest label (`100%`) inside the ring, solved against the chord\n * it spans. Always computed for that widest label so the text does not resize as the value climbs.\n */\nconst insideLabelFit = computed<number>(() => {\n const innerRadius = Math.max((+size - 2 * +thickness) / 2, 0);\n return (LABEL_BREATHING_ROOM * 2 * innerRadius) / Math.sqrt(LABEL_WIDTH_EM ** 2 + 1);\n});\n\nconst labelFits = computed<boolean>(() => get(insideLabelFit) >= MIN_INSIDE_LABEL_PX);\n\nconst ui = computed<ReturnType<typeof progressStyles>>(() => progressStyles({\n color,\n variant,\n circular,\n hasLabel: get(hasLabel),\n}));\n\nconst currentValue = computed<number>(() => clampPercent(value));\n\n/** An indeterminate bar has no value to report, so it leaves `aria-valuenow` off. */\nconst ariaValueNow = computed<number | undefined>(() =>\n variant === ProgressVariant.indeterminate ? undefined : get(currentValue));\n\nconst label = computed<string>(() => `${Math.floor(get(currentValue))}%`);\n\nconst progress = computed<number>(() => -100 + get(currentValue));\n\nconst barStyle = computed<Record<string, string>>(() => ({\n transform: `translateX(${get(progress)}%)`,\n}));\n\nconst bufferRailStyle = computed<Record<string, string>>(() => ({\n transform: `translateX(${-100 + clampPercent(bufferValue)}%)`,\n}));\n\nconst linearStyle = computed<Record<string, string>>(() => ({\n height: `${+thickness}px`,\n}));\n\nconst circularSize = computed<Record<string, string>>(() => ({\n width: `${+size}px`,\n height: `${+size}px`,\n}));\n\nconst circularGeometry = computed<{ scaledThickness: number; viewSize: number }>(() => {\n const scaledThickness = (+thickness * 32) / +size;\n return { scaledThickness, viewSize: 40 + scaledThickness };\n});\n\n/**\n * The label inside the ring scales with both `size` and `thickness`. The fit is capped by\n * a sublinear curve so large rings do not end up with an oversized number in the middle.\n */\nconst circularLabelStyle = computed<Record<string, string>>(() => ({\n fontSize: `${Math.min(get(insideLabelFit), +size * 0.15 + 6)}px`,\n}));\n\nconst circularStrokeStyle = computed<Record<string, string>>(() => ({\n strokeDasharray: `${CIRCLE_CIRCUMFERENCE}`,\n strokeDashoffset: `${(get(progress) / 100) * -CIRCLE_CIRCUMFERENCE}`,\n // the library's own motion, not Material's standard curve\n transition: 'stroke-dashoffset 200ms ease-out',\n}));\n</script>\n\n<template>\n <div :class=\"ui.wrapper()\">\n <!-- Circular progress (not supported for buffer variant) -->\n <div\n v-if=\"circular && variant !== ProgressVariant.buffer\"\n :aria-valuenow=\"ariaValueNow\"\n :class=\"ui.circularContainer()\"\n :style=\"circularSize\"\n :data-variant=\"variant\"\n :data-color=\"color\"\n :aria-label=\"ariaLabel\"\n :title=\"hasLabel && !labelFits ? label : undefined\"\n aria-valuemax=\"100\"\n aria-valuemin=\"0\"\n role=\"progressbar\"\n >\n <svg\n :class=\"ui.svg()\"\n :viewBox=\"`0 0 ${circularGeometry.viewSize} ${circularGeometry.viewSize}`\"\n >\n <!-- Track behind the arc, mirroring the linear rail. Indeterminate spins, so it gets no track. -->\n <circle\n v-if=\"variant === ProgressVariant.determinate\"\n cx=\"50%\"\n cy=\"50%\"\n fill=\"none\"\n :r=\"CIRCLE_RADIUS\"\n :class=\"ui.circleTrack()\"\n :stroke-width=\"circularGeometry.scaledThickness\"\n />\n <circle\n cx=\"50%\"\n cy=\"50%\"\n fill=\"none\"\n :r=\"CIRCLE_RADIUS\"\n :class=\"ui.circle()\"\n :style=\"variant === ProgressVariant.determinate ? circularStrokeStyle : undefined\"\n :stroke-width=\"circularGeometry.scaledThickness\"\n />\n </svg>\n <div\n v-if=\"hasLabel && labelFits\"\n :class=\"ui.label()\"\n :style=\"circularLabelStyle\"\n aria-hidden=\"true\"\n >\n {{ label }}\n </div>\n </div>\n\n <!-- Linear progress (also used as fallback for circular + buffer) -->\n <div\n v-else\n :aria-valuenow=\"ariaValueNow\"\n :class=\"ui.progressbar()\"\n :style=\"linearStyle\"\n :data-variant=\"variant\"\n :data-color=\"color\"\n :aria-label=\"ariaLabel\"\n aria-valuemax=\"100\"\n aria-valuemin=\"0\"\n role=\"progressbar\"\n >\n <div\n v-if=\"variant === ProgressVariant.buffer\"\n :class=\"ui.bufferDots()\"\n />\n <div\n :class=\"variant === ProgressVariant.buffer ? [ui.rail(), ui.bufferRail()] : ui.rail()\"\n :style=\"variant === ProgressVariant.buffer ? bufferRailStyle : undefined\"\n data-id=\"progress-rail\"\n />\n <div\n v-if=\"variant === ProgressVariant.indeterminate\"\n :class=\"ui.indeterminateBar()\"\n />\n <div\n v-else\n :class=\"ui.bar()\"\n :style=\"barStyle\"\n />\n </div>\n\n <!-- Linear label -->\n <div\n v-if=\"hasLabel && !circular\"\n :class=\"ui.label()\"\n >\n {{ label }}\n </div>\n </div>\n</template>\n"],"mappings":""}
@@ -1,3 +1,4 @@
1
+ import type { HTMLAttributes } from 'vue';
1
2
  import type { ContextColorsType } from '../../consts/colors.js';
2
3
  import { ProgressVariant } from './progress-props.js';
3
4
  export interface Props {
@@ -28,8 +29,9 @@ export interface Props {
28
29
  */
29
30
  ariaLabel?: string;
30
31
  }
32
+ type __VLS_Props = Props & /* @vue-ignore */ Omit<HTMLAttributes, keyof Props>;
31
33
  type __VLS_Slots = Record<string, never>;
32
- declare const __VLS_base: import("vue").DefineComponent<Props, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<Props> & Readonly<{}>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
34
+ declare const __VLS_base: import("vue").DefineComponent<__VLS_Props, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<__VLS_Props> & Readonly<{}>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
33
35
  declare const __VLS_export: __VLS_WithSlots<typeof __VLS_base, __VLS_Slots>;
34
36
  declare const _default: typeof __VLS_export;
35
37
  export default _default;