@rotki/ui-library 3.0.0-beta.3 → 3.0.0-beta.5

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 (248) hide show
  1. package/README.md +27 -14
  2. package/dist/components/accordions/accordion/RuiAccordion.js.map +1 -1
  3. package/dist/components/accordions/accordion/RuiAccordion.vue.d.ts +1 -1
  4. package/dist/components/accordions/accordion/RuiAccordion.vue_vue_type_script_setup_true_lang.js.map +1 -1
  5. package/dist/components/accordions/accordions/RuiAccordions.js.map +1 -1
  6. package/dist/components/accordions/accordions/RuiAccordions.vue_vue_type_script_setup_true_lang.js.map +1 -1
  7. package/dist/components/alerts/RuiAlert.js.map +1 -1
  8. package/dist/components/alerts/RuiAlert.vue_vue_type_script_setup_true_lang.js.map +1 -1
  9. package/dist/components/avatars/RuiAvatar.js.map +1 -1
  10. package/dist/components/avatars/RuiAvatar.vue_vue_type_script_setup_true_lang.js.map +1 -1
  11. package/dist/components/avatars/RuiAvatarGroup.js.map +1 -1
  12. package/dist/components/avatars/RuiAvatarGroup.vue_vue_type_script_setup_true_lang.js.map +1 -1
  13. package/dist/components/buttons/button/RuiButton.js.map +1 -1
  14. package/dist/components/buttons/button/RuiButton.vue_vue_type_script_setup_true_lang.js.map +1 -1
  15. package/dist/components/buttons/button-group/RuiButtonGroup.js.map +1 -1
  16. package/dist/components/buttons/button-group/RuiButtonGroup.vue_vue_type_script_setup_true_lang.js.map +1 -1
  17. package/dist/components/calendar/RuiCalendar.js.map +1 -1
  18. package/dist/components/calendar/RuiCalendar.vue_vue_type_script_setup_true_lang.js.map +1 -1
  19. package/dist/components/calendar/RuiCalendarGrid.js.map +1 -1
  20. package/dist/components/calendar/RuiCalendarGrid.vue_vue_type_script_setup_true_lang.js.map +1 -1
  21. package/dist/components/calendar/RuiCalendarHeader.js.map +1 -1
  22. package/dist/components/calendar/RuiCalendarHeader.vue_vue_type_script_setup_true_lang.js.map +1 -1
  23. package/dist/components/calendar/RuiCalendarMenu.js.map +1 -1
  24. package/dist/components/calendar/RuiCalendarMenu.vue_vue_type_script_setup_true_lang.js.map +1 -1
  25. package/dist/components/cards/RuiCard.js.map +1 -1
  26. package/dist/components/cards/RuiCard.vue.d.ts +1 -1
  27. package/dist/components/cards/RuiCard.vue_vue_type_script_setup_true_lang.js.map +1 -1
  28. package/dist/components/cards/RuiCardHeader.js.map +1 -1
  29. package/dist/components/cards/RuiCardHeader.vue_vue_type_script_setup_true_lang.js.map +1 -1
  30. package/dist/components/chips/RuiChip.js.map +1 -1
  31. package/dist/components/chips/RuiChip.vue.d.ts +1 -1
  32. package/dist/components/chips/RuiChip.vue_vue_type_script_setup_true_lang.js.map +1 -1
  33. package/dist/components/color-picker/RuiColorBoard.js.map +1 -1
  34. package/dist/components/color-picker/RuiColorBoard.vue_vue_type_script_setup_true_lang.js.map +1 -1
  35. package/dist/components/color-picker/RuiColorDisplay.js.map +1 -1
  36. package/dist/components/color-picker/RuiColorDisplay.vue_vue_type_script_setup_true_lang.js.map +1 -1
  37. package/dist/components/color-picker/RuiColorHue.js.map +1 -1
  38. package/dist/components/color-picker/RuiColorHue.vue_vue_type_script_setup_true_lang.js.map +1 -1
  39. package/dist/components/color-picker/RuiColorInput.js.map +1 -1
  40. package/dist/components/color-picker/RuiColorInput.vue_vue_type_script_setup_true_lang.js.map +1 -1
  41. package/dist/components/color-picker/RuiColorPicker.js.map +1 -1
  42. package/dist/components/color-picker/RuiColorPicker.vue_vue_type_script_setup_true_lang.js.map +1 -1
  43. package/dist/components/date-time-picker/RuiDateTimePicker.js.map +1 -1
  44. package/dist/components/date-time-picker/RuiDateTimePicker.vue_vue_type_script_setup_true_lang.js.map +1 -1
  45. package/dist/components/date-time-picker/RuiDateTimePickerMenu.js.map +1 -1
  46. package/dist/components/date-time-picker/RuiDateTimePickerMenu.vue.d.ts +1 -1
  47. package/dist/components/date-time-picker/RuiDateTimePickerMenu.vue_vue_type_script_setup_true_lang.js.map +1 -1
  48. package/dist/components/date-time-picker/RuiTimezoneSelect.js.map +1 -1
  49. package/dist/components/date-time-picker/RuiTimezoneSelect.vue.d.ts +2 -2
  50. package/dist/components/date-time-picker/RuiTimezoneSelect.vue_vue_type_script_setup_true_lang.js.map +1 -1
  51. package/dist/components/divider/RuiDivider.js.map +1 -1
  52. package/dist/components/divider/RuiDivider.vue_vue_type_script_setup_true_lang.js.map +1 -1
  53. package/dist/components/forms/auto-complete/RuiAutoComplete.js.map +1 -1
  54. package/dist/components/forms/auto-complete/RuiAutoComplete.vue.d.ts +1 -1
  55. package/dist/components/forms/auto-complete/RuiAutoComplete.vue_vue_type_script_setup_true_lang.js.map +1 -1
  56. package/dist/components/forms/auto-complete/RuiAutoCompleteOption.js.map +1 -1
  57. package/dist/components/forms/auto-complete/RuiAutoCompleteOption.vue_vue_type_script_setup_true_lang.js.map +1 -1
  58. package/dist/components/forms/auto-complete/RuiAutoCompleteOptionList.js.map +1 -1
  59. package/dist/components/forms/auto-complete/RuiAutoCompleteOptionList.vue.d.ts +1 -1
  60. package/dist/components/forms/auto-complete/RuiAutoCompleteOptionList.vue_vue_type_script_setup_true_lang.js.map +1 -1
  61. package/dist/components/forms/auto-complete/RuiAutoCompleteSelection.js.map +1 -1
  62. package/dist/components/forms/auto-complete/RuiAutoCompleteSelection.vue_vue_type_script_setup_true_lang.js.map +1 -1
  63. package/dist/components/forms/auto-complete/auto-complete-props.d.ts +2 -2
  64. package/dist/components/forms/category-picker/RuiCategoryPicker.js.map +1 -1
  65. package/dist/components/forms/category-picker/RuiCategoryPicker.vue.d.ts +2 -2
  66. package/dist/components/forms/category-picker/RuiCategoryPicker.vue_vue_type_script_setup_true_lang.js +6 -2
  67. package/dist/components/forms/category-picker/RuiCategoryPicker.vue_vue_type_script_setup_true_lang.js.map +1 -1
  68. package/dist/components/forms/checkbox/RuiCheckbox.js.map +1 -1
  69. package/dist/components/forms/checkbox/RuiCheckbox.vue_vue_type_script_setup_true_lang.js.map +1 -1
  70. package/dist/components/forms/checkbox/checkbox-group/RuiCheckboxGroup.js.map +1 -1
  71. package/dist/components/forms/checkbox/checkbox-group/RuiCheckboxGroup.vue_vue_type_script_setup_true_lang.js.map +1 -1
  72. package/dist/components/forms/field-defaults/RuiFieldDefaults.js.map +1 -1
  73. package/dist/components/forms/field-defaults/RuiFieldDefaults.vue_vue_type_script_setup_true_lang.js.map +1 -1
  74. package/dist/components/forms/field-label/RuiFieldLabel.js.map +1 -1
  75. package/dist/components/forms/field-label/RuiFieldLabel.vue_vue_type_script_setup_true_lang.js.map +1 -1
  76. package/dist/components/forms/file-upload/RuiFileUpload.js.map +1 -1
  77. package/dist/components/forms/file-upload/RuiFileUpload.vue.d.ts +4 -1
  78. package/dist/components/forms/file-upload/RuiFileUpload.vue_vue_type_script_setup_true_lang.js +17 -8
  79. package/dist/components/forms/file-upload/RuiFileUpload.vue_vue_type_script_setup_true_lang.js.map +1 -1
  80. package/dist/components/forms/radio-button/radio/RuiRadio.js.map +1 -1
  81. package/dist/components/forms/radio-button/radio/RuiRadio.vue_vue_type_script_setup_true_lang.js.map +1 -1
  82. package/dist/components/forms/radio-button/radio-group/RuiRadioGroup.js.map +1 -1
  83. package/dist/components/forms/radio-button/radio-group/RuiRadioGroup.vue_vue_type_script_setup_true_lang.js.map +1 -1
  84. package/dist/components/forms/revealable-text-field/RuiRevealableTextField.js.map +1 -1
  85. package/dist/components/forms/revealable-text-field/RuiRevealableTextField.vue.d.ts +1 -1
  86. package/dist/components/forms/revealable-text-field/RuiRevealableTextField.vue_vue_type_script_setup_true_lang.js.map +1 -1
  87. package/dist/components/forms/select/RuiMenuSelect.js.map +1 -1
  88. package/dist/components/forms/select/RuiMenuSelect.vue.d.ts +2 -2
  89. package/dist/components/forms/select/RuiMenuSelect.vue_vue_type_script_setup_true_lang.js.map +1 -1
  90. package/dist/components/forms/select/RuiSimpleSelect.js.map +1 -1
  91. package/dist/components/forms/select/RuiSimpleSelect.vue_vue_type_script_setup_true_lang.js.map +1 -1
  92. package/dist/components/forms/slider/RuiSlider.js.map +1 -1
  93. package/dist/components/forms/slider/RuiSlider.vue.d.ts +1 -1
  94. package/dist/components/forms/slider/RuiSlider.vue_vue_type_script_setup_true_lang.js.map +1 -1
  95. package/dist/components/forms/slider/RuiSliderTicks.js.map +1 -1
  96. package/dist/components/forms/slider/RuiSliderTicks.vue_vue_type_script_setup_true_lang.js.map +1 -1
  97. package/dist/components/forms/switch/RuiSwitch.js.map +1 -1
  98. package/dist/components/forms/switch/RuiSwitch.vue_vue_type_script_setup_true_lang.js.map +1 -1
  99. package/dist/components/forms/text-area/RuiTextArea.js.map +1 -1
  100. package/dist/components/forms/text-area/RuiTextArea.vue_vue_type_script_setup_true_lang.js.map +1 -1
  101. package/dist/components/forms/text-field/RuiTextField.js.map +1 -1
  102. package/dist/components/forms/text-field/RuiTextField.vue_vue_type_script_setup_true_lang.js.map +1 -1
  103. package/dist/components/helpers/RuiFormTextDetail.js.map +1 -1
  104. package/dist/components/helpers/RuiFormTextDetail.vue_vue_type_script_setup_true_lang.js +1 -2
  105. package/dist/components/helpers/RuiFormTextDetail.vue_vue_type_script_setup_true_lang.js.map +1 -1
  106. package/dist/components/icons/RuiIcon.js.map +1 -1
  107. package/dist/components/icons/RuiIcon.vue_vue_type_script_setup_true_lang.js +11 -10
  108. package/dist/components/icons/RuiIcon.vue_vue_type_script_setup_true_lang.js.map +1 -1
  109. package/dist/components/index.d.ts +57 -57
  110. package/dist/components/loaders/RuiSkeletonBase.js.map +1 -1
  111. package/dist/components/loaders/RuiSkeletonBase.vue_vue_type_script_setup_true_lang.js.map +1 -1
  112. package/dist/components/loaders/RuiSkeletonLoader.js.map +1 -1
  113. package/dist/components/loaders/RuiSkeletonLoader.vue.d.ts +1 -1
  114. package/dist/components/loaders/RuiSkeletonLoader.vue_vue_type_script_setup_true_lang.js.map +1 -1
  115. package/dist/components/logos/RuiLogo.js.map +1 -1
  116. package/dist/components/logos/RuiLogo.vue_vue_type_script_setup_true_lang.js.map +1 -1
  117. package/dist/components/overlays/badge/RuiBadge.js.map +1 -1
  118. package/dist/components/overlays/badge/RuiBadge.vue_vue_type_script_setup_true_lang.js.map +1 -1
  119. package/dist/components/overlays/bottom-sheet/RuiBottomSheet.js.map +1 -1
  120. package/dist/components/overlays/bottom-sheet/RuiBottomSheet.vue_vue_type_script_setup_true_lang.js.map +1 -1
  121. package/dist/components/overlays/dialog/RuiDialog.js.map +1 -1
  122. package/dist/components/overlays/dialog/RuiDialog.vue.d.ts +1 -1
  123. package/dist/components/overlays/dialog/RuiDialog.vue_vue_type_script_setup_true_lang.js.map +1 -1
  124. package/dist/components/overlays/menu/RuiMenu.js.map +1 -1
  125. package/dist/components/overlays/menu/RuiMenu.vue.d.ts +1 -1
  126. package/dist/components/overlays/menu/RuiMenu.vue_vue_type_script_setup_true_lang.js.map +1 -1
  127. package/dist/components/overlays/navigation-drawer/RuiNavigationDrawer.js.map +1 -1
  128. package/dist/components/overlays/navigation-drawer/RuiNavigationDrawer.vue.d.ts +1 -1
  129. package/dist/components/overlays/navigation-drawer/RuiNavigationDrawer.vue_vue_type_script_setup_true_lang.js.map +1 -1
  130. package/dist/components/overlays/notification/RuiNotification.js.map +1 -1
  131. package/dist/components/overlays/notification/RuiNotification.vue_vue_type_script_setup_true_lang.js.map +1 -1
  132. package/dist/components/overlays/tooltip/RuiTooltip.js.map +1 -1
  133. package/dist/components/overlays/tooltip/RuiTooltip.vue.d.ts +1 -1
  134. package/dist/components/overlays/tooltip/RuiTooltip.vue_vue_type_script_setup_true_lang.js.map +1 -1
  135. package/dist/components/progress/RuiProgress.js.map +1 -1
  136. package/dist/components/progress/RuiProgress.vue_vue_type_script_setup_true_lang.js.map +1 -1
  137. package/dist/components/steppers/RuiFooterStepper.js.map +1 -1
  138. package/dist/components/steppers/RuiFooterStepper.vue_vue_type_script_setup_true_lang.js +6 -2
  139. package/dist/components/steppers/RuiFooterStepper.vue_vue_type_script_setup_true_lang.js.map +1 -1
  140. package/dist/components/steppers/RuiStepper.js.map +1 -1
  141. package/dist/components/steppers/RuiStepper.vue.d.ts +1 -1
  142. package/dist/components/steppers/RuiStepper.vue_vue_type_script_setup_true_lang.js.map +1 -1
  143. package/dist/components/steppers/RuiStepperIcon.js.map +1 -1
  144. package/dist/components/steppers/RuiStepperIcon.vue_vue_type_script_setup_true_lang.js.map +1 -1
  145. package/dist/components/tables/RuiDataTable.js.map +1 -1
  146. package/dist/components/tables/RuiDataTable.vue.d.ts +11 -2
  147. package/dist/components/tables/RuiDataTable.vue_vue_type_script_setup_true_lang.js +8 -3
  148. package/dist/components/tables/RuiDataTable.vue_vue_type_script_setup_true_lang.js.map +1 -1
  149. package/dist/components/tables/RuiExpandButton.js.map +1 -1
  150. package/dist/components/tables/RuiExpandButton.vue_vue_type_script_setup_true_lang.js.map +1 -1
  151. package/dist/components/tables/RuiTable.js.map +1 -1
  152. package/dist/components/tables/RuiTable.vue_vue_type_script_setup_true_lang.js.map +1 -1
  153. package/dist/components/tables/RuiTableEmptyState.js.map +1 -1
  154. package/dist/components/tables/RuiTableEmptyState.vue_vue_type_script_setup_true_lang.js.map +1 -1
  155. package/dist/components/tables/RuiTableErrorState.js.map +1 -1
  156. package/dist/components/tables/RuiTableErrorState.vue_vue_type_script_setup_true_lang.js.map +1 -1
  157. package/dist/components/tables/RuiTableHead.js.map +1 -1
  158. package/dist/components/tables/RuiTableHead.vue_vue_type_script_setup_true_lang.js.map +1 -1
  159. package/dist/components/tables/RuiTableLoadingState.js.map +1 -1
  160. package/dist/components/tables/RuiTableLoadingState.vue_vue_type_script_setup_true_lang.js.map +1 -1
  161. package/dist/components/tables/RuiTablePagination.js.map +1 -1
  162. package/dist/components/tables/RuiTablePagination.vue_vue_type_script_setup_true_lang.js.map +1 -1
  163. package/dist/components/tables/data-table/RuiDataTableAppendRow.js +7 -0
  164. package/dist/components/tables/data-table/RuiDataTableAppendRow.js.map +1 -0
  165. package/dist/components/tables/data-table/RuiDataTableAppendRow.vue.d.ts +26 -0
  166. package/dist/components/tables/data-table/RuiDataTableAppendRow.vue_vue_type_script_setup_true_lang.js +29 -0
  167. package/dist/components/tables/data-table/RuiDataTableAppendRow.vue_vue_type_script_setup_true_lang.js.map +1 -0
  168. package/dist/components/tables/data-table/RuiDataTableBody.js.map +1 -1
  169. package/dist/components/tables/data-table/RuiDataTableBody.vue.d.ts +5 -1
  170. package/dist/components/tables/data-table/RuiDataTableBody.vue_vue_type_script_setup_true_lang.js +18 -10
  171. package/dist/components/tables/data-table/RuiDataTableBody.vue_vue_type_script_setup_true_lang.js.map +1 -1
  172. package/dist/components/tables/data-table/RuiDataTableCell.js.map +1 -1
  173. package/dist/components/tables/data-table/RuiDataTableCell.vue.d.ts +1 -1
  174. package/dist/components/tables/data-table/RuiDataTableCell.vue_vue_type_script_setup_true_lang.js.map +1 -1
  175. package/dist/components/tables/data-table/RuiDataTableEmptyRow.js.map +1 -1
  176. package/dist/components/tables/data-table/RuiDataTableEmptyRow.vue_vue_type_script_setup_true_lang.js.map +1 -1
  177. package/dist/components/tables/data-table/RuiDataTableErrorRow.js.map +1 -1
  178. package/dist/components/tables/data-table/RuiDataTableErrorRow.vue_vue_type_script_setup_true_lang.js.map +1 -1
  179. package/dist/components/tables/data-table/RuiDataTableExpandedRow.js.map +1 -1
  180. package/dist/components/tables/data-table/RuiDataTableExpandedRow.vue_vue_type_script_setup_true_lang.js.map +1 -1
  181. package/dist/components/tables/data-table/RuiDataTableGroupRow.js.map +1 -1
  182. package/dist/components/tables/data-table/RuiDataTableGroupRow.vue_vue_type_script_setup_true_lang.js.map +1 -1
  183. package/dist/components/tables/data-table/RuiDataTableLoadingRow.js.map +1 -1
  184. package/dist/components/tables/data-table/RuiDataTableLoadingRow.vue_vue_type_script_setup_true_lang.js.map +1 -1
  185. package/dist/components/tables/data-table/RuiDataTableMobileSort.js.map +1 -1
  186. package/dist/components/tables/data-table/RuiDataTableMobileSort.vue.d.ts +1 -1
  187. package/dist/components/tables/data-table/RuiDataTableMobileSort.vue_vue_type_script_setup_true_lang.js.map +1 -1
  188. package/dist/components/tables/data-table/RuiDataTableRow.js.map +1 -1
  189. package/dist/components/tables/data-table/RuiDataTableRow.vue.d.ts +5 -1
  190. package/dist/components/tables/data-table/RuiDataTableRow.vue_vue_type_script_setup_true_lang.js +144 -88
  191. package/dist/components/tables/data-table/RuiDataTableRow.vue_vue_type_script_setup_true_lang.js.map +1 -1
  192. package/dist/components/tables/data-table/context.d.ts +1 -1
  193. package/dist/components/tables/data-table-styles.js +1 -1
  194. package/dist/components/tables/data-table-styles.js.map +1 -1
  195. package/dist/components/tabs/tab/RuiTab.js.map +1 -1
  196. package/dist/components/tabs/tab/RuiTab.vue.d.ts +1 -1
  197. package/dist/components/tabs/tab/RuiTab.vue_vue_type_script_setup_true_lang.js.map +1 -1
  198. package/dist/components/tabs/tab-item/RuiTabItem.js.map +1 -1
  199. package/dist/components/tabs/tab-item/RuiTabItem.vue_vue_type_script_setup_true_lang.js.map +1 -1
  200. package/dist/components/tabs/tab-items/RuiTabItems.js.map +1 -1
  201. package/dist/components/tabs/tab-items/RuiTabItems.vue_vue_type_script_setup_true_lang.js.map +1 -1
  202. package/dist/components/tabs/tabs/RuiTabs.js.map +1 -1
  203. package/dist/components/tabs/tabs/RuiTabs.vue_vue_type_script_setup_true_lang.js.map +1 -1
  204. package/dist/components/time-picker/RuiTimePicker.js.map +1 -1
  205. package/dist/components/time-picker/RuiTimePicker.vue_vue_type_script_setup_true_lang.js +12 -8
  206. package/dist/components/time-picker/RuiTimePicker.vue_vue_type_script_setup_true_lang.js.map +1 -1
  207. package/dist/composables/floating.d.ts +1 -1
  208. package/dist/composables/icons.d.ts +1 -1
  209. package/dist/composables/icons.js +1 -7
  210. package/dist/composables/icons.js.map +1 -1
  211. package/dist/composables/tables/data-table/columns.d.ts +1 -1
  212. package/dist/composables/tables/data-table/grouping.d.ts +1 -1
  213. package/dist/composables/tables/data-table/page-scroll.d.ts +1 -1
  214. package/dist/composables/tables/data-table/pagination.d.ts +2 -2
  215. package/dist/composables/tables/data-table/sort.d.ts +2 -2
  216. package/dist/composables/tables/data-table/types.d.ts +2 -2
  217. package/dist/i18n/keys.d.ts +9 -0
  218. package/dist/i18n/keys.js +9 -0
  219. package/dist/i18n/keys.js.map +1 -1
  220. package/dist/icons/icons_1.d.ts +26 -26
  221. package/dist/icons/icons_1.js +348 -365
  222. package/dist/icons/icons_1.js.map +1 -1
  223. package/dist/icons/icons_2.d.ts +28 -28
  224. package/dist/icons/icons_2.js +434 -323
  225. package/dist/icons/icons_2.js.map +1 -1
  226. package/dist/icons/icons_3.d.ts +32 -32
  227. package/dist/icons/icons_3.js +334 -364
  228. package/dist/icons/icons_3.js.map +1 -1
  229. package/dist/icons/icons_4.d.ts +64 -64
  230. package/dist/icons/icons_4.js +769 -669
  231. package/dist/icons/icons_4.js.map +1 -1
  232. package/dist/icons/icons_5.d.ts +66 -9
  233. package/dist/icons/icons_5.js +693 -83
  234. package/dist/icons/icons_5.js.map +1 -1
  235. package/dist/icons/index.d.ts +1 -1
  236. package/dist/icons/index.js +108 -51
  237. package/dist/icons/index.js.map +1 -1
  238. package/dist/index.d.ts +1 -1
  239. package/dist/index.js +6 -6
  240. package/dist/style.css +22 -4
  241. package/dist/types/theme.d.ts +1 -1
  242. package/dist/utils/tv.d.ts +1 -1
  243. package/dist/vendor/@vueuse/core/dist/index.js +63 -55
  244. package/dist/vendor/@vueuse/core/dist/index.js.map +1 -1
  245. package/dist/vendor/@vueuse/shared/dist/index.js +4 -4
  246. package/dist/vendor/@vueuse/shared/dist/index.js.map +1 -1
  247. package/dist/web-types.json +88 -4
  248. package/package.json +26 -26
@@ -1,59 +1,59 @@
1
- import type { AutoCompleteProps, RuiAutoCompleteClassNames } from './forms/auto-complete/auto-complete-props';
2
- import type { TableColumn as DataTableColumn, GroupKeys as DataTableGroupKeys, SortColumn as DataTableSortColumn, TableSortData as DataTableSortData, GroupData } from './tables/RuiTableHead.vue';
3
- import RuiAccordion, { type AccordionProps, type RuiAccordionClassNames } from './accordions/accordion/RuiAccordion.vue';
4
- import RuiAccordions, { type Props as AccordionsProps } from './accordions/accordions/RuiAccordions.vue';
5
- import RuiAlert, { type Props as AlertProps } from './alerts/RuiAlert.vue';
6
- import RuiAvatar, { type Props as AvatarProps } from './avatars/RuiAvatar.vue';
7
- import RuiAvatarGroup, { type Props as AvatarGroupProps } from './avatars/RuiAvatarGroup.vue';
8
- import RuiButtonGroup, { type Props as ButtonGroupProps } from './buttons/button-group/RuiButtonGroup.vue';
9
- import RuiButton, { type Props as ButtonProps } from './buttons/button/RuiButton.vue';
10
- import RuiCalendar, { type CalendarProps } from './calendar/RuiCalendar.vue';
11
- import RuiCard, { type Props as CardProps, type RuiCardClassNames } from './cards/RuiCard.vue';
12
- import RuiCardHeader, { type Props as CardHeaderProps } from './cards/RuiCardHeader.vue';
13
- import RuiChip, { type Props as ChipProps, type RuiChipClassNames } from './chips/RuiChip.vue';
14
- import RuiColorPicker from './color-picker/RuiColorPicker.vue';
15
- import RuiDateTimePicker, { type RuiDateTimePickerProps } from './date-time-picker/RuiDateTimePicker.vue';
16
- import RuiTimezoneSelect, { type RuiTimezoneSelectProps } from './date-time-picker/RuiTimezoneSelect.vue';
17
- import RuiDivider, { type Props as DividerProps } from './divider/RuiDivider.vue';
18
- import RuiAutoComplete from './forms/auto-complete/RuiAutoComplete.vue';
19
- import RuiCategoryPicker, { type RuiCategoryPickerClassNames, type RuiCategoryPickerProps } from './forms/category-picker/RuiCategoryPicker.vue';
20
- import RuiCheckboxGroup, { type Props as CheckboxGroupProps } from './forms/checkbox/checkbox-group/RuiCheckboxGroup.vue';
21
- import RuiCheckbox, { type Props as CheckboxProps } from './forms/checkbox/RuiCheckbox.vue';
22
- import RuiFieldDefaults, { type FieldDefaultsProps } from './forms/field-defaults/RuiFieldDefaults.vue';
23
- import RuiFileUpload, { type FileUploadProps } from './forms/file-upload/RuiFileUpload.vue';
24
- import RuiRadioGroup, { type Props as RadioGroupProps } from './forms/radio-button/radio-group/RuiRadioGroup.vue';
25
- import RuiRadio, { type RadioProps } from './forms/radio-button/radio/RuiRadio.vue';
26
- import RuiRevealableTextField, { type Props as RevealableTextFieldProps } from './forms/revealable-text-field/RuiRevealableTextField.vue';
27
- import RuiMenuSelect, { type MenuSelectProps, type RuiMenuSelectClassNames } from './forms/select/RuiMenuSelect.vue';
28
- import RuiSimpleSelect, { type Props as SimpleSelectProps } from './forms/select/RuiSimpleSelect.vue';
29
- import RuiSlider, { type RuiSliderClassNames, type Props as SliderProps } from './forms/slider/RuiSlider.vue';
30
- import RuiSwitch, { type Props as SwitchProps } from './forms/switch/RuiSwitch.vue';
31
- import RuiTextArea, { type TextAreaProps } from './forms/text-area/RuiTextArea.vue';
32
- import RuiTextField, { type TextFieldProps } from './forms/text-field/RuiTextField.vue';
33
- import RuiIcon, { type Props as IconProps } from './icons/RuiIcon.vue';
34
- import RuiSkeletonLoader, { type Props as SkeletonLoaderProps } from './loaders/RuiSkeletonLoader.vue';
35
- import RuiLogo, { type Props as LogoProps } from './logos/RuiLogo.vue';
36
- import RuiBadge, { type Props as BadgeProps } from './overlays/badge/RuiBadge.vue';
37
- import RuiBottomSheet, { type BottomSheetProps } from './overlays/bottom-sheet/RuiBottomSheet.vue';
38
- import RuiDialog, { type DialogProps, type RuiDialogClassNames } from './overlays/dialog/RuiDialog.vue';
39
- import RuiMenu, { type MenuProps, type RuiMenuClassNames, type RuiMenuRole } from './overlays/menu/RuiMenu.vue';
40
- import RuiNavigationDrawer, { type NavigationDrawerProps, type RuiNavigationDrawerClassNames } from './overlays/navigation-drawer/RuiNavigationDrawer.vue';
41
- import RuiNotification, { type NotificationProps } from './overlays/notification/RuiNotification.vue';
42
- import RuiTooltip, { type RuiTooltipClassNames, type Props as TooltipProps } from './overlays/tooltip/RuiTooltip.vue';
43
- import RuiProgress, { type Props as ProgressProps } from './progress/RuiProgress.vue';
44
- import RuiFooterStepper, { type Props as FooterStepperProps } from './steppers/RuiFooterStepper.vue';
45
- import RuiStepper, { type RuiStepperClassNames, type Props as StepperProps } from './steppers/RuiStepper.vue';
46
- import RuiDataTable, { type TableOptions as DataTableOptions, type Props as DataTableProps } from './tables/RuiDataTable.vue';
47
- import RuiTableRowExpander, { type Props as ExpandButtonProps } from './tables/RuiExpandButton.vue';
48
- import RuiTable, { type TableEmpty, type Props as TableProps } from './tables/RuiTable.vue';
49
- import RuiTableEmptyState, { type TableEmptyStateProps } from './tables/RuiTableEmptyState.vue';
50
- import RuiTableErrorState, { type TableErrorStateProps } from './tables/RuiTableErrorState.vue';
51
- import RuiTableLoadingState, { type TableLoadingStateProps } from './tables/RuiTableLoadingState.vue';
52
- import RuiTablePagination, { type TablePaginationData, type Props as TablePaginationProps } from './tables/RuiTablePagination.vue';
53
- import RuiTabItem, { type Props as TabItemProps } from './tabs/tab-item/RuiTabItem.vue';
54
- import RuiTabItems from './tabs/tab-items/RuiTabItems.vue';
55
- import RuiTab, { type RuiTabClassNames, type Props as TabProps } from './tabs/tab/RuiTab.vue';
56
- import RuiTabs, { type Props as TabsProps } from './tabs/tabs/RuiTabs.vue';
57
- import RuiTimePicker, { type RuiTimePickerProps } from './time-picker/RuiTimePicker.vue';
1
+ import type { AutoCompleteProps, RuiAutoCompleteClassNames } from './forms/auto-complete/auto-complete-props.js';
2
+ import type { TableColumn as DataTableColumn, GroupKeys as DataTableGroupKeys, SortColumn as DataTableSortColumn, TableSortData as DataTableSortData, GroupData } from './tables/RuiTableHead.vue.js';
3
+ import RuiAccordion, { type AccordionProps, type RuiAccordionClassNames } from './accordions/accordion/RuiAccordion.vue.js';
4
+ import RuiAccordions, { type Props as AccordionsProps } from './accordions/accordions/RuiAccordions.vue.js';
5
+ import RuiAlert, { type Props as AlertProps } from './alerts/RuiAlert.vue.js';
6
+ import RuiAvatar, { type Props as AvatarProps } from './avatars/RuiAvatar.vue.js';
7
+ import RuiAvatarGroup, { type Props as AvatarGroupProps } from './avatars/RuiAvatarGroup.vue.js';
8
+ import RuiButtonGroup, { type Props as ButtonGroupProps } from './buttons/button-group/RuiButtonGroup.vue.js';
9
+ import RuiButton, { type Props as ButtonProps } from './buttons/button/RuiButton.vue.js';
10
+ import RuiCalendar, { type CalendarProps } from './calendar/RuiCalendar.vue.js';
11
+ import RuiCard, { type Props as CardProps, type RuiCardClassNames } from './cards/RuiCard.vue.js';
12
+ import RuiCardHeader, { type Props as CardHeaderProps } from './cards/RuiCardHeader.vue.js';
13
+ import RuiChip, { type Props as ChipProps, type RuiChipClassNames } from './chips/RuiChip.vue.js';
14
+ import RuiColorPicker from './color-picker/RuiColorPicker.vue.js';
15
+ import RuiDateTimePicker, { type RuiDateTimePickerProps } from './date-time-picker/RuiDateTimePicker.vue.js';
16
+ import RuiTimezoneSelect, { type RuiTimezoneSelectProps } from './date-time-picker/RuiTimezoneSelect.vue.js';
17
+ import RuiDivider, { type Props as DividerProps } from './divider/RuiDivider.vue.js';
18
+ import RuiAutoComplete from './forms/auto-complete/RuiAutoComplete.vue.js';
19
+ import RuiCategoryPicker, { type RuiCategoryPickerClassNames, type RuiCategoryPickerProps } from './forms/category-picker/RuiCategoryPicker.vue.js';
20
+ import RuiCheckboxGroup, { type Props as CheckboxGroupProps } from './forms/checkbox/checkbox-group/RuiCheckboxGroup.vue.js';
21
+ import RuiCheckbox, { type Props as CheckboxProps } from './forms/checkbox/RuiCheckbox.vue.js';
22
+ import RuiFieldDefaults, { type FieldDefaultsProps } from './forms/field-defaults/RuiFieldDefaults.vue.js';
23
+ import RuiFileUpload, { type FileUploadProps } from './forms/file-upload/RuiFileUpload.vue.js';
24
+ import RuiRadioGroup, { type Props as RadioGroupProps } from './forms/radio-button/radio-group/RuiRadioGroup.vue.js';
25
+ import RuiRadio, { type RadioProps } from './forms/radio-button/radio/RuiRadio.vue.js';
26
+ import RuiRevealableTextField, { type Props as RevealableTextFieldProps } from './forms/revealable-text-field/RuiRevealableTextField.vue.js';
27
+ import RuiMenuSelect, { type MenuSelectProps, type RuiMenuSelectClassNames } from './forms/select/RuiMenuSelect.vue.js';
28
+ import RuiSimpleSelect, { type Props as SimpleSelectProps } from './forms/select/RuiSimpleSelect.vue.js';
29
+ import RuiSlider, { type RuiSliderClassNames, type Props as SliderProps } from './forms/slider/RuiSlider.vue.js';
30
+ import RuiSwitch, { type Props as SwitchProps } from './forms/switch/RuiSwitch.vue.js';
31
+ import RuiTextArea, { type TextAreaProps } from './forms/text-area/RuiTextArea.vue.js';
32
+ import RuiTextField, { type TextFieldProps } from './forms/text-field/RuiTextField.vue.js';
33
+ import RuiIcon, { type Props as IconProps } from './icons/RuiIcon.vue.js';
34
+ import RuiSkeletonLoader, { type Props as SkeletonLoaderProps } from './loaders/RuiSkeletonLoader.vue.js';
35
+ import RuiLogo, { type Props as LogoProps } from './logos/RuiLogo.vue.js';
36
+ import RuiBadge, { type Props as BadgeProps } from './overlays/badge/RuiBadge.vue.js';
37
+ import RuiBottomSheet, { type BottomSheetProps } from './overlays/bottom-sheet/RuiBottomSheet.vue.js';
38
+ import RuiDialog, { type DialogProps, type RuiDialogClassNames } from './overlays/dialog/RuiDialog.vue.js';
39
+ import RuiMenu, { type MenuProps, type RuiMenuClassNames, type RuiMenuRole } from './overlays/menu/RuiMenu.vue.js';
40
+ import RuiNavigationDrawer, { type NavigationDrawerProps, type RuiNavigationDrawerClassNames } from './overlays/navigation-drawer/RuiNavigationDrawer.vue.js';
41
+ import RuiNotification, { type NotificationProps } from './overlays/notification/RuiNotification.vue.js';
42
+ import RuiTooltip, { type RuiTooltipClassNames, type Props as TooltipProps } from './overlays/tooltip/RuiTooltip.vue.js';
43
+ import RuiProgress, { type Props as ProgressProps } from './progress/RuiProgress.vue.js';
44
+ import RuiFooterStepper, { type Props as FooterStepperProps } from './steppers/RuiFooterStepper.vue.js';
45
+ import RuiStepper, { type RuiStepperClassNames, type Props as StepperProps } from './steppers/RuiStepper.vue.js';
46
+ import RuiDataTable, { type TableOptions as DataTableOptions, type Props as DataTableProps } from './tables/RuiDataTable.vue.js';
47
+ import RuiTableRowExpander, { type Props as ExpandButtonProps } from './tables/RuiExpandButton.vue.js';
48
+ import RuiTable, { type TableEmpty, type Props as TableProps } from './tables/RuiTable.vue.js';
49
+ import RuiTableEmptyState, { type TableEmptyStateProps } from './tables/RuiTableEmptyState.vue.js';
50
+ import RuiTableErrorState, { type TableErrorStateProps } from './tables/RuiTableErrorState.vue.js';
51
+ import RuiTableLoadingState, { type TableLoadingStateProps } from './tables/RuiTableLoadingState.vue.js';
52
+ import RuiTablePagination, { type TablePaginationData, type Props as TablePaginationProps } from './tables/RuiTablePagination.vue.js';
53
+ import RuiTabItem, { type Props as TabItemProps } from './tabs/tab-item/RuiTabItem.vue.js';
54
+ import RuiTabItems from './tabs/tab-items/RuiTabItems.vue.js';
55
+ import RuiTab, { type RuiTabClassNames, type Props as TabProps } from './tabs/tab/RuiTab.vue.js';
56
+ import RuiTabs, { type Props as TabsProps } from './tabs/tabs/RuiTabs.vue.js';
57
+ import RuiTimePicker, { type RuiTimePickerProps } from './time-picker/RuiTimePicker.vue.js';
58
58
  export type { AccordionProps, AccordionsProps, AlertProps, AutoCompleteProps, AvatarGroupProps, AvatarProps, BadgeProps, BottomSheetProps, ButtonGroupProps, ButtonProps, CalendarProps, CardHeaderProps, CardProps, CheckboxGroupProps, CheckboxProps, ChipProps, DataTableColumn, DataTableGroupKeys, DataTableOptions, DataTableProps, DataTableSortColumn, DataTableSortData, DialogProps, DividerProps, ExpandButtonProps, FieldDefaultsProps, FileUploadProps, FooterStepperProps, GroupData, IconProps, LogoProps, MenuProps, MenuSelectProps, NavigationDrawerProps, NotificationProps, ProgressProps, RadioGroupProps, RadioProps, RevealableTextFieldProps, RuiAccordionClassNames, RuiAutoCompleteClassNames, RuiCardClassNames, RuiCategoryPickerClassNames, RuiCategoryPickerProps, RuiChipClassNames, RuiDateTimePickerProps, RuiDialogClassNames, RuiMenuClassNames, RuiMenuRole, RuiMenuSelectClassNames, RuiNavigationDrawerClassNames, RuiSliderClassNames, RuiStepperClassNames, RuiTabClassNames, RuiTimePickerProps, RuiTimezoneSelectProps, RuiTooltipClassNames, SimpleSelectProps, SkeletonLoaderProps, SliderProps, StepperProps, SwitchProps, TabItemProps, TableEmpty, TableEmptyStateProps, TableErrorStateProps, TableLoadingStateProps, TablePaginationData, TablePaginationProps, TableProps, TabProps, TabsProps, TextAreaProps, TextFieldProps, TooltipProps, };
59
59
  export { RuiAccordion, RuiAccordions, RuiAlert, RuiAutoComplete, RuiAvatar, RuiAvatarGroup, RuiBadge, RuiBottomSheet, RuiButton, RuiButtonGroup, RuiCalendar, RuiCard, RuiCardHeader, RuiCategoryPicker, RuiCheckbox, RuiCheckboxGroup, RuiChip, RuiColorPicker, RuiDataTable, RuiDateTimePicker, RuiDialog, RuiDivider, RuiFieldDefaults, RuiFileUpload, RuiFooterStepper, RuiIcon, RuiLogo, RuiMenu, RuiMenuSelect, RuiNavigationDrawer, RuiNotification, RuiProgress, RuiRadio, RuiRadioGroup, RuiRevealableTextField, RuiSimpleSelect, RuiSkeletonLoader, RuiSlider, RuiStepper, RuiSwitch, RuiTab, RuiTabItem, RuiTabItems, RuiTable, RuiTableEmptyState, RuiTableErrorState, RuiTableLoadingState, RuiTablePagination, RuiTableRowExpander, RuiTabs, RuiTextArea, RuiTextField, RuiTimePicker, RuiTimezoneSelect, RuiTooltip, };
@@ -1 +1 @@
1
- {"version":3,"file":"RuiSkeletonBase.js","names":[],"sources":["../../../src/components/loaders/RuiSkeletonBase.vue"],"sourcesContent":["<script lang=\"ts\" setup>\nimport { tv } from '@/utils/tv';\n\nexport interface Props {\n rounded?: 'none' | 'sm' | 'md' | 'lg' | 'full';\n}\n\ndefineOptions({\n name: 'RuiSkeletonLoaderBase',\n});\n\nconst { rounded } = defineProps<Props>();\n\nconst skeleton = tv({\n // zinc steps rather than translucent black and white, which in dark came out lighter than any surface\n base: 'animate-pulse bg-rui-neutral-200 dark:bg-rui-neutral-800',\n variants: {\n rounded: {\n none: 'rounded-none',\n sm: 'rounded-xs',\n md: 'rounded-rui-control',\n lg: 'rounded-rui-card',\n full: 'rounded-full',\n },\n },\n});\n\nconst ui = computed<string>(() => skeleton({ rounded }));\n</script>\n\n<template>\n <!-- decoration only: an alert role made a screen reader announce every bar -->\n <div\n :class=\"ui\"\n data-id=\"skeleton\"\n aria-hidden=\"true\"\n />\n</template>\n"],"mappings":""}
1
+ {"version":3,"file":"RuiSkeletonBase.js","names":["_sfc_main"],"sources":["../../../src/components/loaders/RuiSkeletonBase.vue"],"sourcesContent":["<script lang=\"ts\" setup>\nimport { tv } from '@/utils/tv';\n\nexport interface Props {\n rounded?: 'none' | 'sm' | 'md' | 'lg' | 'full';\n}\n\ndefineOptions({\n name: 'RuiSkeletonLoaderBase',\n});\n\nconst { rounded } = defineProps<Props>();\n\nconst skeleton = tv({\n // zinc steps rather than translucent black and white, which in dark came out lighter than any surface\n base: 'animate-pulse bg-rui-neutral-200 dark:bg-rui-neutral-800',\n variants: {\n rounded: {\n none: 'rounded-none',\n sm: 'rounded-xs',\n md: 'rounded-rui-control',\n lg: 'rounded-rui-card',\n full: 'rounded-full',\n },\n },\n});\n\nconst ui = computed<string>(() => skeleton({ rounded }));\n</script>\n\n<template>\n <!-- decoration only: an alert role made a screen reader announce every bar -->\n <div\n :class=\"ui\"\n data-id=\"skeleton\"\n aria-hidden=\"true\"\n />\n</template>\n"],"mappings":""}
@@ -1 +1 @@
1
- {"version":3,"file":"RuiSkeletonBase.vue_vue_type_script_setup_true_lang.js","names":[],"sources":["../../../src/components/loaders/RuiSkeletonBase.vue"],"sourcesContent":["<script lang=\"ts\" setup>\nimport { tv } from '@/utils/tv';\n\nexport interface Props {\n rounded?: 'none' | 'sm' | 'md' | 'lg' | 'full';\n}\n\ndefineOptions({\n name: 'RuiSkeletonLoaderBase',\n});\n\nconst { rounded } = defineProps<Props>();\n\nconst skeleton = tv({\n // zinc steps rather than translucent black and white, which in dark came out lighter than any surface\n base: 'animate-pulse bg-rui-neutral-200 dark:bg-rui-neutral-800',\n variants: {\n rounded: {\n none: 'rounded-none',\n sm: 'rounded-xs',\n md: 'rounded-rui-control',\n lg: 'rounded-rui-card',\n full: 'rounded-full',\n },\n },\n});\n\nconst ui = computed<string>(() => skeleton({ rounded }));\n</script>\n\n<template>\n <!-- decoration only: an alert role made a screen reader announce every bar -->\n <div\n :class=\"ui\"\n data-id=\"skeleton\"\n aria-hidden=\"true\"\n />\n</template>\n"],"mappings":";;;;;;;;EAaA,MAAM,WAAW,GAAG;GAElB,MAAM;GACN,UAAU,EACR,SAAS;IACP,MAAM;IACN,IAAI;IACJ,IAAI;IACJ,IAAI;IACJ,MAAM;GACR,EACF;EACF,CAAC;EAED,MAAM,KAAK,eAAuB,SAAS,EAAE,SAAM,QAAA,QAAE,CAAC,CAAC;;GAKrD,OAAA,UAAA,GAAA,mBAIE,OAAA;IAHC,OAAK,eAAE,MAAA,EAAA,CAAE;IACV,WAAQ;IACR,eAAY"}
1
+ {"version":3,"file":"RuiSkeletonBase.vue_vue_type_script_setup_true_lang.js","names":["_openBlock","_createElementBlock","_normalizeClass","_unref"],"sources":["../../../src/components/loaders/RuiSkeletonBase.vue"],"sourcesContent":["<script lang=\"ts\" setup>\nimport { tv } from '@/utils/tv';\n\nexport interface Props {\n rounded?: 'none' | 'sm' | 'md' | 'lg' | 'full';\n}\n\ndefineOptions({\n name: 'RuiSkeletonLoaderBase',\n});\n\nconst { rounded } = defineProps<Props>();\n\nconst skeleton = tv({\n // zinc steps rather than translucent black and white, which in dark came out lighter than any surface\n base: 'animate-pulse bg-rui-neutral-200 dark:bg-rui-neutral-800',\n variants: {\n rounded: {\n none: 'rounded-none',\n sm: 'rounded-xs',\n md: 'rounded-rui-control',\n lg: 'rounded-rui-card',\n full: 'rounded-full',\n },\n },\n});\n\nconst ui = computed<string>(() => skeleton({ rounded }));\n</script>\n\n<template>\n <!-- decoration only: an alert role made a screen reader announce every bar -->\n <div\n :class=\"ui\"\n data-id=\"skeleton\"\n aria-hidden=\"true\"\n />\n</template>\n"],"mappings":";;;;;;;;EAaA,MAAM,WAAW,GAAG;GAElB,MAAM;GACN,UAAU,EACR,SAAS;IACP,MAAM;IACN,IAAI;IACJ,IAAI;IACJ,IAAI;IACJ,MAAM;GACR,EACF;EACF,CAAC;EAED,MAAM,KAAK,eAAuB,SAAS,EAAE,SAAM,QAAA,QAAE,CAAC,CAAC;;GAKrD,OAAAA,UAAA,GAAAC,mBAIE,OAAA;IAHC,OAAKC,eAAEC,MAAA,EAAA,CAAE;IACV,WAAQ;IACR,eAAY"}
@@ -1 +1 @@
1
- {"version":3,"file":"RuiSkeletonLoader.js","names":[],"sources":["../../../src/components/loaders/RuiSkeletonLoader.vue"],"sourcesContent":["<script lang=\"ts\" setup>\nimport RuiSkeletonBase, {\n type Props as SkeletonBaseProps,\n} from '@/components/loaders/RuiSkeletonBase.vue';\nimport { SkeletonType } from '@/components/loaders/skeleton-type';\nimport { cn, tv } from '@/utils/tv';\n\nexport interface Props extends SkeletonBaseProps {\n type?: SkeletonType;\n}\n\ndefineOptions({\n name: 'RuiSkeletonLoader',\n inheritAttrs: false,\n});\n\nconst { type = SkeletonType.TEXT, rounded } = defineProps<Props>();\n\nconst multiLineTypes: SkeletonType[] = [SkeletonType.PARAGRAPH, SkeletonType.ARTICLE];\n\nconst skeletonType = tv({\n variants: {\n type: {\n [SkeletonType.CUSTOM]: 'box-border',\n [SkeletonType.TEXT]: 'w-full h-4 rounded-rui-control',\n [SkeletonType.HEADING]: 'w-full h-6 rounded-rui-control',\n [SkeletonType.BUTTON]: 'w-full max-w-24 h-9 rounded-rui-control',\n [SkeletonType.ICON]: 'w-6 h-6 rounded-full',\n [SkeletonType.AVATAR]: 'w-10 h-10 rounded-full',\n [SkeletonType.THUMBNAIL]: 'w-14 h-14 rounded-xs',\n [SkeletonType.PARAGRAPH]: 'flex flex-col gap-2',\n [SkeletonType.ARTICLE]: 'flex flex-col gap-2',\n },\n },\n});\n\nconst attrs = useAttrs();\nconst ui = computed<string>(() => skeletonType({ type, class: cn(attrs.class) }));\nconst isMultiLine = computed<boolean>(() => multiLineTypes.includes(type));\n</script>\n\n<template>\n <RuiSkeletonBase\n v-if=\"!isMultiLine\"\n :class=\"ui\"\n :rounded=\"rounded\"\n v-bind=\"{ ...attrs, class: undefined }\"\n />\n <div\n v-else\n :class=\"ui\"\n v-bind=\"{ ...attrs, class: undefined }\"\n >\n <RuiSkeletonBase\n v-if=\"type === SkeletonType.ARTICLE\"\n class=\"w-full h-6 rounded-rui-control mb-1\"\n :rounded=\"rounded\"\n />\n <RuiSkeletonBase\n class=\"w-full h-3 rounded-rui-control\"\n :rounded=\"rounded\"\n />\n <RuiSkeletonBase\n class=\"w-full h-3 rounded-rui-control max-w-[80%]\"\n :rounded=\"rounded\"\n />\n <RuiSkeletonBase\n class=\"w-full h-3 rounded-rui-control max-w-[90%]\"\n :rounded=\"rounded\"\n />\n </div>\n</template>\n"],"mappings":""}
1
+ {"version":3,"file":"RuiSkeletonLoader.js","names":["_sfc_main"],"sources":["../../../src/components/loaders/RuiSkeletonLoader.vue"],"sourcesContent":["<script lang=\"ts\" setup>\nimport RuiSkeletonBase, {\n type Props as SkeletonBaseProps,\n} from '@/components/loaders/RuiSkeletonBase.vue';\nimport { SkeletonType } from '@/components/loaders/skeleton-type';\nimport { cn, tv } from '@/utils/tv';\n\nexport interface Props extends SkeletonBaseProps {\n type?: SkeletonType;\n}\n\ndefineOptions({\n name: 'RuiSkeletonLoader',\n inheritAttrs: false,\n});\n\nconst { type = SkeletonType.TEXT, rounded } = defineProps<Props>();\n\nconst multiLineTypes: SkeletonType[] = [SkeletonType.PARAGRAPH, SkeletonType.ARTICLE];\n\nconst skeletonType = tv({\n variants: {\n type: {\n [SkeletonType.CUSTOM]: 'box-border',\n [SkeletonType.TEXT]: 'w-full h-4 rounded-rui-control',\n [SkeletonType.HEADING]: 'w-full h-6 rounded-rui-control',\n [SkeletonType.BUTTON]: 'w-full max-w-24 h-9 rounded-rui-control',\n [SkeletonType.ICON]: 'w-6 h-6 rounded-full',\n [SkeletonType.AVATAR]: 'w-10 h-10 rounded-full',\n [SkeletonType.THUMBNAIL]: 'w-14 h-14 rounded-xs',\n [SkeletonType.PARAGRAPH]: 'flex flex-col gap-2',\n [SkeletonType.ARTICLE]: 'flex flex-col gap-2',\n },\n },\n});\n\nconst attrs = useAttrs();\nconst ui = computed<string>(() => skeletonType({ type, class: cn(attrs.class) }));\nconst isMultiLine = computed<boolean>(() => multiLineTypes.includes(type));\n</script>\n\n<template>\n <RuiSkeletonBase\n v-if=\"!isMultiLine\"\n :class=\"ui\"\n :rounded=\"rounded\"\n v-bind=\"{ ...attrs, class: undefined }\"\n />\n <div\n v-else\n :class=\"ui\"\n v-bind=\"{ ...attrs, class: undefined }\"\n >\n <RuiSkeletonBase\n v-if=\"type === SkeletonType.ARTICLE\"\n class=\"w-full h-6 rounded-rui-control mb-1\"\n :rounded=\"rounded\"\n />\n <RuiSkeletonBase\n class=\"w-full h-3 rounded-rui-control\"\n :rounded=\"rounded\"\n />\n <RuiSkeletonBase\n class=\"w-full h-3 rounded-rui-control max-w-[80%]\"\n :rounded=\"rounded\"\n />\n <RuiSkeletonBase\n class=\"w-full h-3 rounded-rui-control max-w-[90%]\"\n :rounded=\"rounded\"\n />\n </div>\n</template>\n"],"mappings":""}
@@ -1,4 +1,4 @@
1
- import { type Props as SkeletonBaseProps } from './RuiSkeletonBase.vue';
1
+ import { type Props as SkeletonBaseProps } from './RuiSkeletonBase.vue.js';
2
2
  import { SkeletonType } from './skeleton-type.js';
3
3
  export interface Props extends SkeletonBaseProps {
4
4
  type?: SkeletonType;
@@ -1 +1 @@
1
- {"version":3,"file":"RuiSkeletonLoader.vue_vue_type_script_setup_true_lang.js","names":[],"sources":["../../../src/components/loaders/RuiSkeletonLoader.vue"],"sourcesContent":["<script lang=\"ts\" setup>\nimport RuiSkeletonBase, {\n type Props as SkeletonBaseProps,\n} from '@/components/loaders/RuiSkeletonBase.vue';\nimport { SkeletonType } from '@/components/loaders/skeleton-type';\nimport { cn, tv } from '@/utils/tv';\n\nexport interface Props extends SkeletonBaseProps {\n type?: SkeletonType;\n}\n\ndefineOptions({\n name: 'RuiSkeletonLoader',\n inheritAttrs: false,\n});\n\nconst { type = SkeletonType.TEXT, rounded } = defineProps<Props>();\n\nconst multiLineTypes: SkeletonType[] = [SkeletonType.PARAGRAPH, SkeletonType.ARTICLE];\n\nconst skeletonType = tv({\n variants: {\n type: {\n [SkeletonType.CUSTOM]: 'box-border',\n [SkeletonType.TEXT]: 'w-full h-4 rounded-rui-control',\n [SkeletonType.HEADING]: 'w-full h-6 rounded-rui-control',\n [SkeletonType.BUTTON]: 'w-full max-w-24 h-9 rounded-rui-control',\n [SkeletonType.ICON]: 'w-6 h-6 rounded-full',\n [SkeletonType.AVATAR]: 'w-10 h-10 rounded-full',\n [SkeletonType.THUMBNAIL]: 'w-14 h-14 rounded-xs',\n [SkeletonType.PARAGRAPH]: 'flex flex-col gap-2',\n [SkeletonType.ARTICLE]: 'flex flex-col gap-2',\n },\n },\n});\n\nconst attrs = useAttrs();\nconst ui = computed<string>(() => skeletonType({ type, class: cn(attrs.class) }));\nconst isMultiLine = computed<boolean>(() => multiLineTypes.includes(type));\n</script>\n\n<template>\n <RuiSkeletonBase\n v-if=\"!isMultiLine\"\n :class=\"ui\"\n :rounded=\"rounded\"\n v-bind=\"{ ...attrs, class: undefined }\"\n />\n <div\n v-else\n :class=\"ui\"\n v-bind=\"{ ...attrs, class: undefined }\"\n >\n <RuiSkeletonBase\n v-if=\"type === SkeletonType.ARTICLE\"\n class=\"w-full h-6 rounded-rui-control mb-1\"\n :rounded=\"rounded\"\n />\n <RuiSkeletonBase\n class=\"w-full h-3 rounded-rui-control\"\n :rounded=\"rounded\"\n />\n <RuiSkeletonBase\n class=\"w-full h-3 rounded-rui-control max-w-[80%]\"\n :rounded=\"rounded\"\n />\n <RuiSkeletonBase\n class=\"w-full h-3 rounded-rui-control max-w-[90%]\"\n :rounded=\"rounded\"\n />\n </div>\n</template>\n"],"mappings":";;;;;;;;;;;;;;EAkBA,MAAM,iBAAiC,CAAC,aAAa,WAAW,aAAa,OAAO;EAEpF,MAAM,eAAe,GAAG,EACtB,UAAU,EACR,MAAM;IACH,aAAa,SAAS;IACtB,aAAa,OAAO;IACpB,aAAa,UAAU;IACvB,aAAa,SAAS;IACtB,aAAa,OAAO;IACpB,aAAa,SAAS;IACtB,aAAa,YAAY;IACzB,aAAa,YAAY;IACzB,aAAa,UAAU;EAC1B,EACF,EACF,CAAC;EAED,MAAM,QAAQ,SAAS;EACvB,MAAM,KAAK,eAAuB,aAAa;GAAE,MAAG,QAAA;GAAG,OAAO,GAAG,MAAM,KAAK;EAAE,CAAC,CAAC;EAChF,MAAM,cAAc,eAAwB,eAAe,SAAS,QAAA,IAAI,CAAC;;GAK9D,OAAA,CAAA,MAAA,WAAA,KADT,UAAA,GAAA,YAKE,yBALF,WAKE;;IAHC,OAAO,MAAA,EAAA;IACP,SAAS,QAAA;GACG,GAAA;IAAA,GAAA,MAAA,KAAA;IAAK,OAAS,KAAA;GAAS,CAAA,GAAA,MAAA,IAAA,CAAA,SAAA,SAAA,CAAA,MAEtC,UAAA,GAAA,mBAsBM,OAtBN,WAsBM;;IApBH,OAAO,MAAA,EAAA;GACK,GAAA;IAAA,GAAA,MAAA,KAAA;IAAK,OAAS,KAAA;GAAS,CAAA,GAAA;IAG5B,QAAA,SAAS,MAAA,YAAA,CAAY,CAAC,WAD9B,UAAA,GAAA,YAIE,yBAAA;;KAFA,OAAM;KACL,SAAS,QAAA;;IAEZ,YAGE,yBAAA;KAFA,OAAM;KACL,SAAS,QAAA;;IAEZ,YAGE,yBAAA;KAFA,OAAM;KACL,SAAS,QAAA;;IAEZ,YAGE,yBAAA;KAFA,OAAM;KACL,SAAS,QAAA"}
1
+ {"version":3,"file":"RuiSkeletonLoader.vue_vue_type_script_setup_true_lang.js","names":["_unref","_openBlock","_createBlock","RuiSkeletonBase","_mergeProps","_createElementBlock","_createCommentVNode","_createVNode"],"sources":["../../../src/components/loaders/RuiSkeletonLoader.vue"],"sourcesContent":["<script lang=\"ts\" setup>\nimport RuiSkeletonBase, {\n type Props as SkeletonBaseProps,\n} from '@/components/loaders/RuiSkeletonBase.vue';\nimport { SkeletonType } from '@/components/loaders/skeleton-type';\nimport { cn, tv } from '@/utils/tv';\n\nexport interface Props extends SkeletonBaseProps {\n type?: SkeletonType;\n}\n\ndefineOptions({\n name: 'RuiSkeletonLoader',\n inheritAttrs: false,\n});\n\nconst { type = SkeletonType.TEXT, rounded } = defineProps<Props>();\n\nconst multiLineTypes: SkeletonType[] = [SkeletonType.PARAGRAPH, SkeletonType.ARTICLE];\n\nconst skeletonType = tv({\n variants: {\n type: {\n [SkeletonType.CUSTOM]: 'box-border',\n [SkeletonType.TEXT]: 'w-full h-4 rounded-rui-control',\n [SkeletonType.HEADING]: 'w-full h-6 rounded-rui-control',\n [SkeletonType.BUTTON]: 'w-full max-w-24 h-9 rounded-rui-control',\n [SkeletonType.ICON]: 'w-6 h-6 rounded-full',\n [SkeletonType.AVATAR]: 'w-10 h-10 rounded-full',\n [SkeletonType.THUMBNAIL]: 'w-14 h-14 rounded-xs',\n [SkeletonType.PARAGRAPH]: 'flex flex-col gap-2',\n [SkeletonType.ARTICLE]: 'flex flex-col gap-2',\n },\n },\n});\n\nconst attrs = useAttrs();\nconst ui = computed<string>(() => skeletonType({ type, class: cn(attrs.class) }));\nconst isMultiLine = computed<boolean>(() => multiLineTypes.includes(type));\n</script>\n\n<template>\n <RuiSkeletonBase\n v-if=\"!isMultiLine\"\n :class=\"ui\"\n :rounded=\"rounded\"\n v-bind=\"{ ...attrs, class: undefined }\"\n />\n <div\n v-else\n :class=\"ui\"\n v-bind=\"{ ...attrs, class: undefined }\"\n >\n <RuiSkeletonBase\n v-if=\"type === SkeletonType.ARTICLE\"\n class=\"w-full h-6 rounded-rui-control mb-1\"\n :rounded=\"rounded\"\n />\n <RuiSkeletonBase\n class=\"w-full h-3 rounded-rui-control\"\n :rounded=\"rounded\"\n />\n <RuiSkeletonBase\n class=\"w-full h-3 rounded-rui-control max-w-[80%]\"\n :rounded=\"rounded\"\n />\n <RuiSkeletonBase\n class=\"w-full h-3 rounded-rui-control max-w-[90%]\"\n :rounded=\"rounded\"\n />\n </div>\n</template>\n"],"mappings":";;;;;;;;;;;;;;EAkBA,MAAM,iBAAiC,CAAC,aAAa,WAAW,aAAa,OAAO;EAEpF,MAAM,eAAe,GAAG,EACtB,UAAU,EACR,MAAM;IACH,aAAa,SAAS;IACtB,aAAa,OAAO;IACpB,aAAa,UAAU;IACvB,aAAa,SAAS;IACtB,aAAa,OAAO;IACpB,aAAa,SAAS;IACtB,aAAa,YAAY;IACzB,aAAa,YAAY;IACzB,aAAa,UAAU;EAC1B,EACF,EACF,CAAC;EAED,MAAM,QAAQ,SAAS;EACvB,MAAM,KAAK,eAAuB,aAAa;GAAE,MAAG,QAAA;GAAG,OAAO,GAAG,MAAM,KAAK;EAAE,CAAC,CAAC;EAChF,MAAM,cAAc,eAAwB,eAAe,SAAS,QAAA,IAAI,CAAC;;GAK9D,OAAA,CAAAA,MAAA,WAAA,KADTC,UAAA,GAAAC,YAKEC,yBALFC,WAKE;;IAHC,OAAOJ,MAAA,EAAA;IACP,SAAS,QAAA;GACG,GAAA;IAAA,GAAAA,MAAA,KAAA;IAAK,OAAS,KAAA;GAAS,CAAA,GAAA,MAAA,IAAA,CAAA,SAAA,SAAA,CAAA,MAEtCC,UAAA,GAAAI,mBAsBM,OAtBND,WAsBM;;IApBH,OAAOJ,MAAA,EAAA;GACK,GAAA;IAAA,GAAAA,MAAA,KAAA;IAAK,OAAS,KAAA;GAAS,CAAA,GAAA;IAG5B,QAAA,SAASA,MAAA,YAAA,CAAY,CAAC,WAD9BC,UAAA,GAAAC,YAIEC,yBAAA;;KAFA,OAAM;KACL,SAAS,QAAA;;IAEZI,YAGEJ,yBAAA;KAFA,OAAM;KACL,SAAS,QAAA;;IAEZI,YAGEJ,yBAAA;KAFA,OAAM;KACL,SAAS,QAAA;;IAEZI,YAGEJ,yBAAA;KAFA,OAAM;KACL,SAAS,QAAA"}
@@ -1 +1 @@
1
- {"version":3,"file":"RuiLogo.js","names":[],"sources":["../../../src/components/logos/RuiLogo.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport fallback from '@/components/logos/logo.svg';\nimport { getVerifiedLogoUrl, removeVerifiedLogoUrl, setVerifiedLogoUrl } from '@/components/logos/verified-logo';\nimport { useLogoOptions } from '@/composables/defaults/logo';\n\nexport interface Props {\n text?: boolean;\n /**\n * Name handed to the `logo.resolve` option of `createRui`. Without a resolver\n * the bundled logo shows.\n */\n logo?: string;\n size?: string | number; // in rems\n /**\n * Appended to the resolved URL as `key`, so each instance loads its own copy.\n */\n uniqueKey?: string | number;\n src?: string;\n}\n\ndefineOptions({\n name: 'RuiLogo',\n});\n\nconst { text = false, logo, size = 3, uniqueKey, src } = defineProps<Props>();\n\nconst appName = 'rotki';\n\nconst resolvedUrl = ref<string>();\nconst error = ref<boolean>(false);\nconst seasonalReady = ref<boolean>(false);\n\nconst isMounted = ref<boolean>(false);\n\nconst customImageRef = useTemplateRef<HTMLImageElement>('customImageRef');\n\nconst logoOptions = useLogoOptions();\n\nconst externalSource = computed<string | undefined>(() => {\n if (src)\n return src;\n\n const url = get(resolvedUrl);\n if (!url || uniqueKey === undefined)\n return url;\n\n return `${url}${url.includes('?') ? '&' : '?'}key=${uniqueKey}`;\n});\n\nconst showCustom = computed<boolean>(() => !!src || (!!get(externalSource) && get(seasonalReady) && !get(error)));\n\nfunction preloadImage(url: string): void {\n const existing = document.head.querySelectorAll<HTMLLinkElement>('link[rel=\"preload\"][as=\"image\"]');\n for (const link of existing) {\n if (link.href === url)\n return;\n }\n\n const link = document.createElement('link');\n link.rel = 'preload';\n link.as = 'image';\n link.href = url;\n document.head.appendChild(link);\n}\n\nasync function callResolver(name: string): Promise<string | undefined> {\n try {\n return await logoOptions?.resolve(name);\n }\n catch {\n // A failing resolver leaves the bundled logo in place\n return undefined;\n }\n}\n\n/**\n * Asks the app's resolver for the logo URL. It runs only after mount, so the\n * server and the client's first render both show the bundled fallback (or\n * `src`) and hydration matches.\n */\nasync function resolveLogo(): Promise<void> {\n if (!get(isMounted))\n return;\n\n if (src || !logo || !logoOptions) {\n set(resolvedUrl, undefined);\n return;\n }\n\n const name = logo;\n const url = await callResolver(name);\n\n // The logo prop changed while the resolver ran; that newer run wins\n if (name !== logo)\n return;\n\n set(error, false);\n // A URL that already decoded in this session is shown without waiting for it again\n set(seasonalReady, !!url && getVerifiedLogoUrl(name) === url);\n set(resolvedUrl, url);\n\n const source = get(externalSource);\n if (source)\n preloadImage(source);\n}\n\nfunction onImageError(): void {\n set(error, true);\n if (logo)\n removeVerifiedLogoUrl(logo);\n}\n\nfunction onImageLoaded(): void {\n const img = get(customImageRef);\n if (!img)\n return;\n\n img.decode()\n .then(() => {\n set(seasonalReady, true);\n // Remember the decoded URL so the next page load can trust it immediately\n const url = get(resolvedUrl);\n if (url && logo)\n setVerifiedLogoUrl(logo, url);\n })\n .catch(() => set(error, true));\n}\n\nwatch(() => get(customImageRef)?.complete, (complete) => {\n if (complete)\n onImageLoaded();\n});\n\nwatchEffect(resolveLogo);\n\nonMounted(() => {\n set(isMounted, true);\n});\n</script>\n\n<template>\n <div\n class=\"gap-x-4 flex items-center relative\"\n :style=\"{ height: `${size}rem` }\"\n >\n <div\n class=\"relative\"\n :style=\"{ width: `${size}rem`, height: `${size}rem` }\"\n >\n <!-- Fallback: always in DOM, fades out when custom image is ready -->\n <img\n :src=\"fallback\"\n :alt=\"appName\"\n data-image=\"fallback\"\n class=\"absolute inset-0 h-full w-full transition ease-out duration-200\"\n :class=\"showCustom ? 'opacity-0' : 'opacity-100'\"\n />\n\n <!-- Custom/seasonal image: fades in when decoded -->\n <img\n v-if=\"externalSource && !error\"\n ref=\"customImageRef\"\n :src=\"externalSource\"\n :alt=\"appName\"\n data-image=\"custom\"\n class=\"absolute inset-0 h-full w-full transition ease-out duration-200\"\n :class=\"showCustom ? 'opacity-100' : 'opacity-0 pointer-events-none'\"\n @error=\"onImageError()\"\n @load=\"onImageLoaded()\"\n />\n </div>\n\n <div\n v-if=\"text\"\n class=\"text-h4 text-rui-primary dark:text-rui-text\"\n >\n {{ appName }}\n </div>\n </div>\n</template>\n"],"mappings":""}
1
+ {"version":3,"file":"RuiLogo.js","names":["_sfc_main"],"sources":["../../../src/components/logos/RuiLogo.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport fallback from '@/components/logos/logo.svg';\nimport { getVerifiedLogoUrl, removeVerifiedLogoUrl, setVerifiedLogoUrl } from '@/components/logos/verified-logo';\nimport { useLogoOptions } from '@/composables/defaults/logo';\n\nexport interface Props {\n text?: boolean;\n /**\n * Name handed to the `logo.resolve` option of `createRui`. Without a resolver\n * the bundled logo shows.\n */\n logo?: string;\n size?: string | number; // in rems\n /**\n * Appended to the resolved URL as `key`, so each instance loads its own copy.\n */\n uniqueKey?: string | number;\n src?: string;\n}\n\ndefineOptions({\n name: 'RuiLogo',\n});\n\nconst { text = false, logo, size = 3, uniqueKey, src } = defineProps<Props>();\n\nconst appName = 'rotki';\n\nconst resolvedUrl = ref<string>();\nconst error = ref<boolean>(false);\nconst seasonalReady = ref<boolean>(false);\n\nconst isMounted = ref<boolean>(false);\n\nconst customImageRef = useTemplateRef<HTMLImageElement>('customImageRef');\n\nconst logoOptions = useLogoOptions();\n\nconst externalSource = computed<string | undefined>(() => {\n if (src)\n return src;\n\n const url = get(resolvedUrl);\n if (!url || uniqueKey === undefined)\n return url;\n\n return `${url}${url.includes('?') ? '&' : '?'}key=${uniqueKey}`;\n});\n\nconst showCustom = computed<boolean>(() => !!src || (!!get(externalSource) && get(seasonalReady) && !get(error)));\n\nfunction preloadImage(url: string): void {\n const existing = document.head.querySelectorAll<HTMLLinkElement>('link[rel=\"preload\"][as=\"image\"]');\n for (const link of existing) {\n if (link.href === url)\n return;\n }\n\n const link = document.createElement('link');\n link.rel = 'preload';\n link.as = 'image';\n link.href = url;\n document.head.appendChild(link);\n}\n\nasync function callResolver(name: string): Promise<string | undefined> {\n try {\n return await logoOptions?.resolve(name);\n }\n catch {\n // A failing resolver leaves the bundled logo in place\n return undefined;\n }\n}\n\n/**\n * Asks the app's resolver for the logo URL. It runs only after mount, so the\n * server and the client's first render both show the bundled fallback (or\n * `src`) and hydration matches.\n */\nasync function resolveLogo(): Promise<void> {\n if (!get(isMounted))\n return;\n\n if (src || !logo || !logoOptions) {\n set(resolvedUrl, undefined);\n return;\n }\n\n const name = logo;\n const url = await callResolver(name);\n\n // The logo prop changed while the resolver ran; that newer run wins\n if (name !== logo)\n return;\n\n set(error, false);\n // A URL that already decoded in this session is shown without waiting for it again\n set(seasonalReady, !!url && getVerifiedLogoUrl(name) === url);\n set(resolvedUrl, url);\n\n const source = get(externalSource);\n if (source)\n preloadImage(source);\n}\n\nfunction onImageError(): void {\n set(error, true);\n if (logo)\n removeVerifiedLogoUrl(logo);\n}\n\nfunction onImageLoaded(): void {\n const img = get(customImageRef);\n if (!img)\n return;\n\n img.decode()\n .then(() => {\n set(seasonalReady, true);\n // Remember the decoded URL so the next page load can trust it immediately\n const url = get(resolvedUrl);\n if (url && logo)\n setVerifiedLogoUrl(logo, url);\n })\n .catch(() => set(error, true));\n}\n\nwatch(() => get(customImageRef)?.complete, (complete) => {\n if (complete)\n onImageLoaded();\n});\n\nwatchEffect(resolveLogo);\n\nonMounted(() => {\n set(isMounted, true);\n});\n</script>\n\n<template>\n <div\n class=\"gap-x-4 flex items-center relative\"\n :style=\"{ height: `${size}rem` }\"\n >\n <div\n class=\"relative\"\n :style=\"{ width: `${size}rem`, height: `${size}rem` }\"\n >\n <!-- Fallback: always in DOM, fades out when custom image is ready -->\n <img\n :src=\"fallback\"\n :alt=\"appName\"\n data-image=\"fallback\"\n class=\"absolute inset-0 h-full w-full transition ease-out duration-200\"\n :class=\"showCustom ? 'opacity-0' : 'opacity-100'\"\n />\n\n <!-- Custom/seasonal image: fades in when decoded -->\n <img\n v-if=\"externalSource && !error\"\n ref=\"customImageRef\"\n :src=\"externalSource\"\n :alt=\"appName\"\n data-image=\"custom\"\n class=\"absolute inset-0 h-full w-full transition ease-out duration-200\"\n :class=\"showCustom ? 'opacity-100' : 'opacity-0 pointer-events-none'\"\n @error=\"onImageError()\"\n @load=\"onImageLoaded()\"\n />\n </div>\n\n <div\n v-if=\"text\"\n class=\"text-h4 text-rui-primary dark:text-rui-text\"\n >\n {{ appName }}\n </div>\n </div>\n</template>\n"],"mappings":""}
@@ -1 +1 @@
1
- {"version":3,"file":"RuiLogo.vue_vue_type_script_setup_true_lang.js","names":[],"sources":["../../../src/components/logos/RuiLogo.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport fallback from '@/components/logos/logo.svg';\nimport { getVerifiedLogoUrl, removeVerifiedLogoUrl, setVerifiedLogoUrl } from '@/components/logos/verified-logo';\nimport { useLogoOptions } from '@/composables/defaults/logo';\n\nexport interface Props {\n text?: boolean;\n /**\n * Name handed to the `logo.resolve` option of `createRui`. Without a resolver\n * the bundled logo shows.\n */\n logo?: string;\n size?: string | number; // in rems\n /**\n * Appended to the resolved URL as `key`, so each instance loads its own copy.\n */\n uniqueKey?: string | number;\n src?: string;\n}\n\ndefineOptions({\n name: 'RuiLogo',\n});\n\nconst { text = false, logo, size = 3, uniqueKey, src } = defineProps<Props>();\n\nconst appName = 'rotki';\n\nconst resolvedUrl = ref<string>();\nconst error = ref<boolean>(false);\nconst seasonalReady = ref<boolean>(false);\n\nconst isMounted = ref<boolean>(false);\n\nconst customImageRef = useTemplateRef<HTMLImageElement>('customImageRef');\n\nconst logoOptions = useLogoOptions();\n\nconst externalSource = computed<string | undefined>(() => {\n if (src)\n return src;\n\n const url = get(resolvedUrl);\n if (!url || uniqueKey === undefined)\n return url;\n\n return `${url}${url.includes('?') ? '&' : '?'}key=${uniqueKey}`;\n});\n\nconst showCustom = computed<boolean>(() => !!src || (!!get(externalSource) && get(seasonalReady) && !get(error)));\n\nfunction preloadImage(url: string): void {\n const existing = document.head.querySelectorAll<HTMLLinkElement>('link[rel=\"preload\"][as=\"image\"]');\n for (const link of existing) {\n if (link.href === url)\n return;\n }\n\n const link = document.createElement('link');\n link.rel = 'preload';\n link.as = 'image';\n link.href = url;\n document.head.appendChild(link);\n}\n\nasync function callResolver(name: string): Promise<string | undefined> {\n try {\n return await logoOptions?.resolve(name);\n }\n catch {\n // A failing resolver leaves the bundled logo in place\n return undefined;\n }\n}\n\n/**\n * Asks the app's resolver for the logo URL. It runs only after mount, so the\n * server and the client's first render both show the bundled fallback (or\n * `src`) and hydration matches.\n */\nasync function resolveLogo(): Promise<void> {\n if (!get(isMounted))\n return;\n\n if (src || !logo || !logoOptions) {\n set(resolvedUrl, undefined);\n return;\n }\n\n const name = logo;\n const url = await callResolver(name);\n\n // The logo prop changed while the resolver ran; that newer run wins\n if (name !== logo)\n return;\n\n set(error, false);\n // A URL that already decoded in this session is shown without waiting for it again\n set(seasonalReady, !!url && getVerifiedLogoUrl(name) === url);\n set(resolvedUrl, url);\n\n const source = get(externalSource);\n if (source)\n preloadImage(source);\n}\n\nfunction onImageError(): void {\n set(error, true);\n if (logo)\n removeVerifiedLogoUrl(logo);\n}\n\nfunction onImageLoaded(): void {\n const img = get(customImageRef);\n if (!img)\n return;\n\n img.decode()\n .then(() => {\n set(seasonalReady, true);\n // Remember the decoded URL so the next page load can trust it immediately\n const url = get(resolvedUrl);\n if (url && logo)\n setVerifiedLogoUrl(logo, url);\n })\n .catch(() => set(error, true));\n}\n\nwatch(() => get(customImageRef)?.complete, (complete) => {\n if (complete)\n onImageLoaded();\n});\n\nwatchEffect(resolveLogo);\n\nonMounted(() => {\n set(isMounted, true);\n});\n</script>\n\n<template>\n <div\n class=\"gap-x-4 flex items-center relative\"\n :style=\"{ height: `${size}rem` }\"\n >\n <div\n class=\"relative\"\n :style=\"{ width: `${size}rem`, height: `${size}rem` }\"\n >\n <!-- Fallback: always in DOM, fades out when custom image is ready -->\n <img\n :src=\"fallback\"\n :alt=\"appName\"\n data-image=\"fallback\"\n class=\"absolute inset-0 h-full w-full transition ease-out duration-200\"\n :class=\"showCustom ? 'opacity-0' : 'opacity-100'\"\n />\n\n <!-- Custom/seasonal image: fades in when decoded -->\n <img\n v-if=\"externalSource && !error\"\n ref=\"customImageRef\"\n :src=\"externalSource\"\n :alt=\"appName\"\n data-image=\"custom\"\n class=\"absolute inset-0 h-full w-full transition ease-out duration-200\"\n :class=\"showCustom ? 'opacity-100' : 'opacity-0 pointer-events-none'\"\n @error=\"onImageError()\"\n @load=\"onImageLoaded()\"\n />\n </div>\n\n <div\n v-if=\"text\"\n class=\"text-h4 text-rui-primary dark:text-rui-text\"\n >\n {{ appName }}\n </div>\n </div>\n</template>\n"],"mappings":"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"}
1
+ {"version":3,"file":"RuiLogo.vue_vue_type_script_setup_true_lang.js","names":["_openBlock","_createElementBlock","_normalizeStyle","_createElementVNode","_unref","fallback","_normalizeClass","_createCommentVNode","_toDisplayString"],"sources":["../../../src/components/logos/RuiLogo.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport fallback from '@/components/logos/logo.svg';\nimport { getVerifiedLogoUrl, removeVerifiedLogoUrl, setVerifiedLogoUrl } from '@/components/logos/verified-logo';\nimport { useLogoOptions } from '@/composables/defaults/logo';\n\nexport interface Props {\n text?: boolean;\n /**\n * Name handed to the `logo.resolve` option of `createRui`. Without a resolver\n * the bundled logo shows.\n */\n logo?: string;\n size?: string | number; // in rems\n /**\n * Appended to the resolved URL as `key`, so each instance loads its own copy.\n */\n uniqueKey?: string | number;\n src?: string;\n}\n\ndefineOptions({\n name: 'RuiLogo',\n});\n\nconst { text = false, logo, size = 3, uniqueKey, src } = defineProps<Props>();\n\nconst appName = 'rotki';\n\nconst resolvedUrl = ref<string>();\nconst error = ref<boolean>(false);\nconst seasonalReady = ref<boolean>(false);\n\nconst isMounted = ref<boolean>(false);\n\nconst customImageRef = useTemplateRef<HTMLImageElement>('customImageRef');\n\nconst logoOptions = useLogoOptions();\n\nconst externalSource = computed<string | undefined>(() => {\n if (src)\n return src;\n\n const url = get(resolvedUrl);\n if (!url || uniqueKey === undefined)\n return url;\n\n return `${url}${url.includes('?') ? '&' : '?'}key=${uniqueKey}`;\n});\n\nconst showCustom = computed<boolean>(() => !!src || (!!get(externalSource) && get(seasonalReady) && !get(error)));\n\nfunction preloadImage(url: string): void {\n const existing = document.head.querySelectorAll<HTMLLinkElement>('link[rel=\"preload\"][as=\"image\"]');\n for (const link of existing) {\n if (link.href === url)\n return;\n }\n\n const link = document.createElement('link');\n link.rel = 'preload';\n link.as = 'image';\n link.href = url;\n document.head.appendChild(link);\n}\n\nasync function callResolver(name: string): Promise<string | undefined> {\n try {\n return await logoOptions?.resolve(name);\n }\n catch {\n // A failing resolver leaves the bundled logo in place\n return undefined;\n }\n}\n\n/**\n * Asks the app's resolver for the logo URL. It runs only after mount, so the\n * server and the client's first render both show the bundled fallback (or\n * `src`) and hydration matches.\n */\nasync function resolveLogo(): Promise<void> {\n if (!get(isMounted))\n return;\n\n if (src || !logo || !logoOptions) {\n set(resolvedUrl, undefined);\n return;\n }\n\n const name = logo;\n const url = await callResolver(name);\n\n // The logo prop changed while the resolver ran; that newer run wins\n if (name !== logo)\n return;\n\n set(error, false);\n // A URL that already decoded in this session is shown without waiting for it again\n set(seasonalReady, !!url && getVerifiedLogoUrl(name) === url);\n set(resolvedUrl, url);\n\n const source = get(externalSource);\n if (source)\n preloadImage(source);\n}\n\nfunction onImageError(): void {\n set(error, true);\n if (logo)\n removeVerifiedLogoUrl(logo);\n}\n\nfunction onImageLoaded(): void {\n const img = get(customImageRef);\n if (!img)\n return;\n\n img.decode()\n .then(() => {\n set(seasonalReady, true);\n // Remember the decoded URL so the next page load can trust it immediately\n const url = get(resolvedUrl);\n if (url && logo)\n setVerifiedLogoUrl(logo, url);\n })\n .catch(() => set(error, true));\n}\n\nwatch(() => get(customImageRef)?.complete, (complete) => {\n if (complete)\n onImageLoaded();\n});\n\nwatchEffect(resolveLogo);\n\nonMounted(() => {\n set(isMounted, true);\n});\n</script>\n\n<template>\n <div\n class=\"gap-x-4 flex items-center relative\"\n :style=\"{ height: `${size}rem` }\"\n >\n <div\n class=\"relative\"\n :style=\"{ width: `${size}rem`, height: `${size}rem` }\"\n >\n <!-- Fallback: always in DOM, fades out when custom image is ready -->\n <img\n :src=\"fallback\"\n :alt=\"appName\"\n data-image=\"fallback\"\n class=\"absolute inset-0 h-full w-full transition ease-out duration-200\"\n :class=\"showCustom ? 'opacity-0' : 'opacity-100'\"\n />\n\n <!-- Custom/seasonal image: fades in when decoded -->\n <img\n v-if=\"externalSource && !error\"\n ref=\"customImageRef\"\n :src=\"externalSource\"\n :alt=\"appName\"\n data-image=\"custom\"\n class=\"absolute inset-0 h-full w-full transition ease-out duration-200\"\n :class=\"showCustom ? 'opacity-100' : 'opacity-0 pointer-events-none'\"\n @error=\"onImageError()\"\n @load=\"onImageLoaded()\"\n />\n </div>\n\n <div\n v-if=\"text\"\n class=\"text-h4 text-rui-primary dark:text-rui-text\"\n >\n {{ appName }}\n </div>\n </div>\n</template>\n"],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"RuiBadge.js","names":[],"sources":["../../../../src/components/overlays/badge/RuiBadge.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport type { ContextColorsType } from '@/consts/colors';\nimport type { RuiIcons } from '@/icons';\nimport RuiIcon from '@/components/icons/RuiIcon.vue';\nimport { BadgePlacement, BadgeRounded, BadgeSize } from '@/components/overlays/badge/badge-props';\nimport { tv } from '@/utils/tv';\n\ntype PosConfig = [left: number, right: string, edge: string, center: number];\n\nexport interface Props {\n text?: string | null;\n icon?: RuiIcons | null;\n modelValue?: boolean;\n dot?: boolean;\n left?: boolean;\n offsetX?: string | number;\n offsetY?: string | number;\n placement?: BadgePlacement;\n size?: BadgeSize;\n rounded?: BadgeRounded;\n color?: 'default' | ContextColorsType;\n}\n\ndefineOptions({\n name: 'RuiBadge',\n});\n\nconst {\n text = null,\n icon = null,\n modelValue = true,\n dot = false,\n placement = BadgePlacement.top,\n left = false,\n size = BadgeSize.md,\n rounded = BadgeRounded.full,\n color = 'primary',\n offsetX = 0,\n offsetY = 0,\n} = defineProps<Props>();\n\nconst slots = defineSlots<{\n default?: () => any;\n badge?: () => any;\n icon?: () => any;\n}>();\n\nconst badgeStyles = tv({\n slots: {\n wrapper: 'relative inline-block',\n badge: 'flex items-center justify-center text-xs font-medium tabular-nums absolute bg-transparent text-rui-text',\n content: 'flex items-center gap-1 px-1.5',\n },\n variants: {\n // `-fill` is `main` in light and, for a status color, the deep `darker` in dark, where `main` is a text tone\n color: {\n default: { badge: 'bg-rui-neutral-200 dark:bg-rui-neutral-700' },\n primary: { badge: 'bg-rui-primary-fill text-rui-primary-foreground' },\n secondary: { badge: 'bg-rui-secondary-fill text-rui-secondary-foreground' },\n error: { badge: 'bg-rui-error-fill text-rui-error-foreground' },\n warning: { badge: 'bg-rui-warning-fill text-rui-warning-foreground' },\n info: { badge: 'bg-rui-info-fill text-rui-info-foreground' },\n success: { badge: 'bg-rui-success-fill text-rui-success-foreground' },\n },\n // the icon is 60% of the badge height, as the text is, rather than filling it\n size: {\n sm: { badge: 'min-h-4 min-w-4 text-caption-2 [--rui-icon-size:0.625rem]' },\n md: { badge: 'min-h-5 min-w-5 [--rui-icon-size:0.75rem]' },\n lg: { badge: 'min-h-6 min-w-6 [--rui-icon-size:0.875rem]' },\n },\n rounded: {\n sm: { badge: 'rounded-xs' },\n md: { badge: 'rounded-rui-control' },\n lg: { badge: 'rounded-rui-card' },\n full: { badge: 'rounded-full' },\n },\n // A surface ring keeps a dot apart from whatever it overlaps, such as an avatar edge\n dot: {\n true: { badge: 'ring-2 ring-rui-surface' },\n },\n // an icon alone needs no side padding, so the badge stays as wide as it is tall\n iconOnly: {\n true: { content: 'px-0' },\n false: {},\n },\n },\n compoundVariants: [\n // the default dot is a step lighter in dark, where neutral-500 nearly vanished against a dark control\n { dot: true, color: 'default', class: { badge: 'bg-rui-neutral-500 dark:bg-rui-neutral-400' } },\n // A dot carries no text, so it keeps the brighter `main`, which reads better as a small mark on a dark page\n { dot: true, color: 'error', class: { badge: 'dark:bg-rui-error' } },\n { dot: true, color: 'warning', class: { badge: 'dark:bg-rui-warning' } },\n { dot: true, color: 'info', class: { badge: 'dark:bg-rui-info' } },\n { dot: true, color: 'success', class: { badge: 'dark:bg-rui-success' } },\n\n // Dot sizes: 8, 10 and 12px, since half of a dot sits off the corner and reads smaller than it is\n { dot: true, size: 'sm', class: { badge: 'min-w-2 min-h-2' } },\n { dot: true, size: 'md', class: { badge: 'min-w-2.5 min-h-2.5' } },\n { dot: true, size: 'lg', class: { badge: 'min-w-3 min-h-3' } },\n ],\n defaultVariants: {\n color: 'primary',\n size: 'md',\n rounded: 'full',\n dot: false,\n },\n});\n\nconst hasText = computed<boolean>(() => !!text || !!slots.badge);\n\nconst hasIconAndText = computed<boolean>(() => (!!icon || !!slots.icon) && get(hasText));\n\nconst ui = computed<ReturnType<typeof badgeStyles>>(() => badgeStyles({\n color,\n size,\n rounded,\n dot,\n iconOnly: (!!icon || !!slots.icon) && !get(hasText),\n}));\n\n/** Dot positions as [leftOffset, rightBase, edgeBase, centerOffset]; a dot's center sits on the corner, so each size moves by half its diameter. */\nconst DOT_POS: Record<BadgeSize, PosConfig> = {\n sm: [-0.25, '100% - 0.25rem', '100% - 0.25rem', 0.25],\n md: [-0.3125, '100% - 0.3125rem', '100% - 0.3125rem', 0.3125],\n lg: [-0.375, '100% - 0.375rem', '100% - 0.375rem', 0.375],\n};\nconst BADGE_POS: Record<BadgeSize, PosConfig> = {\n sm: [-0.85, '100% - 0.375rem', '100% - 0.375rem', 0.55],\n md: [-0.95, '100% - 0.5rem', '100% - 0.5rem', 0.65],\n lg: [-1.05, '100% - 0.5rem', '100% - 0.5rem', 0.75],\n};\n\nconst positionStyle = computed<Record<string, string>>(() => {\n const ox = Number(offsetX) * 0.0625;\n const oy = Number(offsetY) * 0.0625;\n const [l, r, edge, center] = dot ? DOT_POS[size] : BADGE_POS[size];\n\n const horizontal = `calc(${left ? `${l}rem` : r} + ${ox}rem)`;\n const vertical = placement === 'center'\n ? `calc(50% - ${center}rem - ${oy}rem)`\n : `calc(${edge} - ${oy}rem)`;\n\n return {\n left: horizontal,\n [placement === 'top' ? 'bottom' : 'top']: vertical,\n };\n});\n</script>\n\n<template>\n <div :class=\"ui.wrapper()\">\n <slot />\n <!-- under reduced motion the badge appears and leaves at full size, with no scale -->\n <Transition\n appear\n enter-active-class=\"transition-[scale] ease-out duration-200 motion-reduce:transition-none\"\n enter-from-class=\"scale-0 motion-reduce:scale-100\"\n enter-to-class=\"scale-100\"\n leave-active-class=\"transition-[scale] ease-in duration-150 motion-reduce:transition-none\"\n leave-from-class=\"scale-100\"\n leave-to-class=\"scale-0 motion-reduce:scale-100\"\n >\n <div\n v-if=\"modelValue\"\n :class=\"ui.badge()\"\n :style=\"positionStyle\"\n :data-placement=\"placement\"\n :data-dot=\"dot || undefined\"\n :data-left=\"left || undefined\"\n aria-atomic=\"true\"\n aria-live=\"polite\"\n role=\"status\"\n >\n <!-- no aria-label: on a live region it replaced the count, so a reader announced \"Badge\" -->\n <span\n v-if=\"!dot\"\n :class=\"ui.content({ class: hasIconAndText ? 'px-2' : undefined })\"\n >\n <slot name=\"badge\">\n {{ text }}\n </slot>\n <slot name=\"icon\">\n <RuiIcon\n v-if=\"icon\"\n :name=\"icon\"\n />\n </slot>\n </span>\n </div>\n </Transition>\n </div>\n</template>\n"],"mappings":""}
1
+ {"version":3,"file":"RuiBadge.js","names":["_sfc_main"],"sources":["../../../../src/components/overlays/badge/RuiBadge.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport type { ContextColorsType } from '@/consts/colors';\nimport type { RuiIcons } from '@/icons';\nimport RuiIcon from '@/components/icons/RuiIcon.vue';\nimport { BadgePlacement, BadgeRounded, BadgeSize } from '@/components/overlays/badge/badge-props';\nimport { tv } from '@/utils/tv';\n\ntype PosConfig = [left: number, right: string, edge: string, center: number];\n\nexport interface Props {\n text?: string | null;\n icon?: RuiIcons | null;\n modelValue?: boolean;\n dot?: boolean;\n left?: boolean;\n offsetX?: string | number;\n offsetY?: string | number;\n placement?: BadgePlacement;\n size?: BadgeSize;\n rounded?: BadgeRounded;\n color?: 'default' | ContextColorsType;\n}\n\ndefineOptions({\n name: 'RuiBadge',\n});\n\nconst {\n text = null,\n icon = null,\n modelValue = true,\n dot = false,\n placement = BadgePlacement.top,\n left = false,\n size = BadgeSize.md,\n rounded = BadgeRounded.full,\n color = 'primary',\n offsetX = 0,\n offsetY = 0,\n} = defineProps<Props>();\n\nconst slots = defineSlots<{\n default?: () => any;\n badge?: () => any;\n icon?: () => any;\n}>();\n\nconst badgeStyles = tv({\n slots: {\n wrapper: 'relative inline-block',\n badge: 'flex items-center justify-center text-xs font-medium tabular-nums absolute bg-transparent text-rui-text',\n content: 'flex items-center gap-1 px-1.5',\n },\n variants: {\n // `-fill` is `main` in light and, for a status color, the deep `darker` in dark, where `main` is a text tone\n color: {\n default: { badge: 'bg-rui-neutral-200 dark:bg-rui-neutral-700' },\n primary: { badge: 'bg-rui-primary-fill text-rui-primary-foreground' },\n secondary: { badge: 'bg-rui-secondary-fill text-rui-secondary-foreground' },\n error: { badge: 'bg-rui-error-fill text-rui-error-foreground' },\n warning: { badge: 'bg-rui-warning-fill text-rui-warning-foreground' },\n info: { badge: 'bg-rui-info-fill text-rui-info-foreground' },\n success: { badge: 'bg-rui-success-fill text-rui-success-foreground' },\n },\n // the icon is 60% of the badge height, as the text is, rather than filling it\n size: {\n sm: { badge: 'min-h-4 min-w-4 text-caption-2 [--rui-icon-size:0.625rem]' },\n md: { badge: 'min-h-5 min-w-5 [--rui-icon-size:0.75rem]' },\n lg: { badge: 'min-h-6 min-w-6 [--rui-icon-size:0.875rem]' },\n },\n rounded: {\n sm: { badge: 'rounded-xs' },\n md: { badge: 'rounded-rui-control' },\n lg: { badge: 'rounded-rui-card' },\n full: { badge: 'rounded-full' },\n },\n // A surface ring keeps a dot apart from whatever it overlaps, such as an avatar edge\n dot: {\n true: { badge: 'ring-2 ring-rui-surface' },\n },\n // an icon alone needs no side padding, so the badge stays as wide as it is tall\n iconOnly: {\n true: { content: 'px-0' },\n false: {},\n },\n },\n compoundVariants: [\n // the default dot is a step lighter in dark, where neutral-500 nearly vanished against a dark control\n { dot: true, color: 'default', class: { badge: 'bg-rui-neutral-500 dark:bg-rui-neutral-400' } },\n // A dot carries no text, so it keeps the brighter `main`, which reads better as a small mark on a dark page\n { dot: true, color: 'error', class: { badge: 'dark:bg-rui-error' } },\n { dot: true, color: 'warning', class: { badge: 'dark:bg-rui-warning' } },\n { dot: true, color: 'info', class: { badge: 'dark:bg-rui-info' } },\n { dot: true, color: 'success', class: { badge: 'dark:bg-rui-success' } },\n\n // Dot sizes: 8, 10 and 12px, since half of a dot sits off the corner and reads smaller than it is\n { dot: true, size: 'sm', class: { badge: 'min-w-2 min-h-2' } },\n { dot: true, size: 'md', class: { badge: 'min-w-2.5 min-h-2.5' } },\n { dot: true, size: 'lg', class: { badge: 'min-w-3 min-h-3' } },\n ],\n defaultVariants: {\n color: 'primary',\n size: 'md',\n rounded: 'full',\n dot: false,\n },\n});\n\nconst hasText = computed<boolean>(() => !!text || !!slots.badge);\n\nconst hasIconAndText = computed<boolean>(() => (!!icon || !!slots.icon) && get(hasText));\n\nconst ui = computed<ReturnType<typeof badgeStyles>>(() => badgeStyles({\n color,\n size,\n rounded,\n dot,\n iconOnly: (!!icon || !!slots.icon) && !get(hasText),\n}));\n\n/** Dot positions as [leftOffset, rightBase, edgeBase, centerOffset]; a dot's center sits on the corner, so each size moves by half its diameter. */\nconst DOT_POS: Record<BadgeSize, PosConfig> = {\n sm: [-0.25, '100% - 0.25rem', '100% - 0.25rem', 0.25],\n md: [-0.3125, '100% - 0.3125rem', '100% - 0.3125rem', 0.3125],\n lg: [-0.375, '100% - 0.375rem', '100% - 0.375rem', 0.375],\n};\nconst BADGE_POS: Record<BadgeSize, PosConfig> = {\n sm: [-0.85, '100% - 0.375rem', '100% - 0.375rem', 0.55],\n md: [-0.95, '100% - 0.5rem', '100% - 0.5rem', 0.65],\n lg: [-1.05, '100% - 0.5rem', '100% - 0.5rem', 0.75],\n};\n\nconst positionStyle = computed<Record<string, string>>(() => {\n const ox = Number(offsetX) * 0.0625;\n const oy = Number(offsetY) * 0.0625;\n const [l, r, edge, center] = dot ? DOT_POS[size] : BADGE_POS[size];\n\n const horizontal = `calc(${left ? `${l}rem` : r} + ${ox}rem)`;\n const vertical = placement === 'center'\n ? `calc(50% - ${center}rem - ${oy}rem)`\n : `calc(${edge} - ${oy}rem)`;\n\n return {\n left: horizontal,\n [placement === 'top' ? 'bottom' : 'top']: vertical,\n };\n});\n</script>\n\n<template>\n <div :class=\"ui.wrapper()\">\n <slot />\n <!-- under reduced motion the badge appears and leaves at full size, with no scale -->\n <Transition\n appear\n enter-active-class=\"transition-[scale] ease-out duration-200 motion-reduce:transition-none\"\n enter-from-class=\"scale-0 motion-reduce:scale-100\"\n enter-to-class=\"scale-100\"\n leave-active-class=\"transition-[scale] ease-in duration-150 motion-reduce:transition-none\"\n leave-from-class=\"scale-100\"\n leave-to-class=\"scale-0 motion-reduce:scale-100\"\n >\n <div\n v-if=\"modelValue\"\n :class=\"ui.badge()\"\n :style=\"positionStyle\"\n :data-placement=\"placement\"\n :data-dot=\"dot || undefined\"\n :data-left=\"left || undefined\"\n aria-atomic=\"true\"\n aria-live=\"polite\"\n role=\"status\"\n >\n <!-- no aria-label: on a live region it replaced the count, so a reader announced \"Badge\" -->\n <span\n v-if=\"!dot\"\n :class=\"ui.content({ class: hasIconAndText ? 'px-2' : undefined })\"\n >\n <slot name=\"badge\">\n {{ text }}\n </slot>\n <slot name=\"icon\">\n <RuiIcon\n v-if=\"icon\"\n :name=\"icon\"\n />\n </slot>\n </span>\n </div>\n </Transition>\n </div>\n</template>\n"],"mappings":""}
@@ -1 +1 @@
1
- {"version":3,"file":"RuiBadge.vue_vue_type_script_setup_true_lang.js","names":[],"sources":["../../../../src/components/overlays/badge/RuiBadge.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport type { ContextColorsType } from '@/consts/colors';\nimport type { RuiIcons } from '@/icons';\nimport RuiIcon from '@/components/icons/RuiIcon.vue';\nimport { BadgePlacement, BadgeRounded, BadgeSize } from '@/components/overlays/badge/badge-props';\nimport { tv } from '@/utils/tv';\n\ntype PosConfig = [left: number, right: string, edge: string, center: number];\n\nexport interface Props {\n text?: string | null;\n icon?: RuiIcons | null;\n modelValue?: boolean;\n dot?: boolean;\n left?: boolean;\n offsetX?: string | number;\n offsetY?: string | number;\n placement?: BadgePlacement;\n size?: BadgeSize;\n rounded?: BadgeRounded;\n color?: 'default' | ContextColorsType;\n}\n\ndefineOptions({\n name: 'RuiBadge',\n});\n\nconst {\n text = null,\n icon = null,\n modelValue = true,\n dot = false,\n placement = BadgePlacement.top,\n left = false,\n size = BadgeSize.md,\n rounded = BadgeRounded.full,\n color = 'primary',\n offsetX = 0,\n offsetY = 0,\n} = defineProps<Props>();\n\nconst slots = defineSlots<{\n default?: () => any;\n badge?: () => any;\n icon?: () => any;\n}>();\n\nconst badgeStyles = tv({\n slots: {\n wrapper: 'relative inline-block',\n badge: 'flex items-center justify-center text-xs font-medium tabular-nums absolute bg-transparent text-rui-text',\n content: 'flex items-center gap-1 px-1.5',\n },\n variants: {\n // `-fill` is `main` in light and, for a status color, the deep `darker` in dark, where `main` is a text tone\n color: {\n default: { badge: 'bg-rui-neutral-200 dark:bg-rui-neutral-700' },\n primary: { badge: 'bg-rui-primary-fill text-rui-primary-foreground' },\n secondary: { badge: 'bg-rui-secondary-fill text-rui-secondary-foreground' },\n error: { badge: 'bg-rui-error-fill text-rui-error-foreground' },\n warning: { badge: 'bg-rui-warning-fill text-rui-warning-foreground' },\n info: { badge: 'bg-rui-info-fill text-rui-info-foreground' },\n success: { badge: 'bg-rui-success-fill text-rui-success-foreground' },\n },\n // the icon is 60% of the badge height, as the text is, rather than filling it\n size: {\n sm: { badge: 'min-h-4 min-w-4 text-caption-2 [--rui-icon-size:0.625rem]' },\n md: { badge: 'min-h-5 min-w-5 [--rui-icon-size:0.75rem]' },\n lg: { badge: 'min-h-6 min-w-6 [--rui-icon-size:0.875rem]' },\n },\n rounded: {\n sm: { badge: 'rounded-xs' },\n md: { badge: 'rounded-rui-control' },\n lg: { badge: 'rounded-rui-card' },\n full: { badge: 'rounded-full' },\n },\n // A surface ring keeps a dot apart from whatever it overlaps, such as an avatar edge\n dot: {\n true: { badge: 'ring-2 ring-rui-surface' },\n },\n // an icon alone needs no side padding, so the badge stays as wide as it is tall\n iconOnly: {\n true: { content: 'px-0' },\n false: {},\n },\n },\n compoundVariants: [\n // the default dot is a step lighter in dark, where neutral-500 nearly vanished against a dark control\n { dot: true, color: 'default', class: { badge: 'bg-rui-neutral-500 dark:bg-rui-neutral-400' } },\n // A dot carries no text, so it keeps the brighter `main`, which reads better as a small mark on a dark page\n { dot: true, color: 'error', class: { badge: 'dark:bg-rui-error' } },\n { dot: true, color: 'warning', class: { badge: 'dark:bg-rui-warning' } },\n { dot: true, color: 'info', class: { badge: 'dark:bg-rui-info' } },\n { dot: true, color: 'success', class: { badge: 'dark:bg-rui-success' } },\n\n // Dot sizes: 8, 10 and 12px, since half of a dot sits off the corner and reads smaller than it is\n { dot: true, size: 'sm', class: { badge: 'min-w-2 min-h-2' } },\n { dot: true, size: 'md', class: { badge: 'min-w-2.5 min-h-2.5' } },\n { dot: true, size: 'lg', class: { badge: 'min-w-3 min-h-3' } },\n ],\n defaultVariants: {\n color: 'primary',\n size: 'md',\n rounded: 'full',\n dot: false,\n },\n});\n\nconst hasText = computed<boolean>(() => !!text || !!slots.badge);\n\nconst hasIconAndText = computed<boolean>(() => (!!icon || !!slots.icon) && get(hasText));\n\nconst ui = computed<ReturnType<typeof badgeStyles>>(() => badgeStyles({\n color,\n size,\n rounded,\n dot,\n iconOnly: (!!icon || !!slots.icon) && !get(hasText),\n}));\n\n/** Dot positions as [leftOffset, rightBase, edgeBase, centerOffset]; a dot's center sits on the corner, so each size moves by half its diameter. */\nconst DOT_POS: Record<BadgeSize, PosConfig> = {\n sm: [-0.25, '100% - 0.25rem', '100% - 0.25rem', 0.25],\n md: [-0.3125, '100% - 0.3125rem', '100% - 0.3125rem', 0.3125],\n lg: [-0.375, '100% - 0.375rem', '100% - 0.375rem', 0.375],\n};\nconst BADGE_POS: Record<BadgeSize, PosConfig> = {\n sm: [-0.85, '100% - 0.375rem', '100% - 0.375rem', 0.55],\n md: [-0.95, '100% - 0.5rem', '100% - 0.5rem', 0.65],\n lg: [-1.05, '100% - 0.5rem', '100% - 0.5rem', 0.75],\n};\n\nconst positionStyle = computed<Record<string, string>>(() => {\n const ox = Number(offsetX) * 0.0625;\n const oy = Number(offsetY) * 0.0625;\n const [l, r, edge, center] = dot ? DOT_POS[size] : BADGE_POS[size];\n\n const horizontal = `calc(${left ? `${l}rem` : r} + ${ox}rem)`;\n const vertical = placement === 'center'\n ? `calc(50% - ${center}rem - ${oy}rem)`\n : `calc(${edge} - ${oy}rem)`;\n\n return {\n left: horizontal,\n [placement === 'top' ? 'bottom' : 'top']: vertical,\n };\n});\n</script>\n\n<template>\n <div :class=\"ui.wrapper()\">\n <slot />\n <!-- under reduced motion the badge appears and leaves at full size, with no scale -->\n <Transition\n appear\n enter-active-class=\"transition-[scale] ease-out duration-200 motion-reduce:transition-none\"\n enter-from-class=\"scale-0 motion-reduce:scale-100\"\n enter-to-class=\"scale-100\"\n leave-active-class=\"transition-[scale] ease-in duration-150 motion-reduce:transition-none\"\n leave-from-class=\"scale-100\"\n leave-to-class=\"scale-0 motion-reduce:scale-100\"\n >\n <div\n v-if=\"modelValue\"\n :class=\"ui.badge()\"\n :style=\"positionStyle\"\n :data-placement=\"placement\"\n :data-dot=\"dot || undefined\"\n :data-left=\"left || undefined\"\n aria-atomic=\"true\"\n aria-live=\"polite\"\n role=\"status\"\n >\n <!-- no aria-label: on a live region it replaced the count, so a reader announced \"Badge\" -->\n <span\n v-if=\"!dot\"\n :class=\"ui.content({ class: hasIconAndText ? 'px-2' : undefined })\"\n >\n <slot name=\"badge\">\n {{ text }}\n </slot>\n <slot name=\"icon\">\n <RuiIcon\n v-if=\"icon\"\n :name=\"icon\"\n />\n </slot>\n </span>\n </div>\n </Transition>\n </div>\n</template>\n"],"mappings":"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"}
1
+ {"version":3,"file":"RuiBadge.vue_vue_type_script_setup_true_lang.js","names":["_useSlots","_openBlock","_createElementBlock","_normalizeClass","_unref","_renderSlot","_createVNode","_Transition","_withCtx","_normalizeStyle","_createTextVNode","_toDisplayString","_createBlock","RuiIcon","_createCommentVNode"],"sources":["../../../../src/components/overlays/badge/RuiBadge.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport type { ContextColorsType } from '@/consts/colors';\nimport type { RuiIcons } from '@/icons';\nimport RuiIcon from '@/components/icons/RuiIcon.vue';\nimport { BadgePlacement, BadgeRounded, BadgeSize } from '@/components/overlays/badge/badge-props';\nimport { tv } from '@/utils/tv';\n\ntype PosConfig = [left: number, right: string, edge: string, center: number];\n\nexport interface Props {\n text?: string | null;\n icon?: RuiIcons | null;\n modelValue?: boolean;\n dot?: boolean;\n left?: boolean;\n offsetX?: string | number;\n offsetY?: string | number;\n placement?: BadgePlacement;\n size?: BadgeSize;\n rounded?: BadgeRounded;\n color?: 'default' | ContextColorsType;\n}\n\ndefineOptions({\n name: 'RuiBadge',\n});\n\nconst {\n text = null,\n icon = null,\n modelValue = true,\n dot = false,\n placement = BadgePlacement.top,\n left = false,\n size = BadgeSize.md,\n rounded = BadgeRounded.full,\n color = 'primary',\n offsetX = 0,\n offsetY = 0,\n} = defineProps<Props>();\n\nconst slots = defineSlots<{\n default?: () => any;\n badge?: () => any;\n icon?: () => any;\n}>();\n\nconst badgeStyles = tv({\n slots: {\n wrapper: 'relative inline-block',\n badge: 'flex items-center justify-center text-xs font-medium tabular-nums absolute bg-transparent text-rui-text',\n content: 'flex items-center gap-1 px-1.5',\n },\n variants: {\n // `-fill` is `main` in light and, for a status color, the deep `darker` in dark, where `main` is a text tone\n color: {\n default: { badge: 'bg-rui-neutral-200 dark:bg-rui-neutral-700' },\n primary: { badge: 'bg-rui-primary-fill text-rui-primary-foreground' },\n secondary: { badge: 'bg-rui-secondary-fill text-rui-secondary-foreground' },\n error: { badge: 'bg-rui-error-fill text-rui-error-foreground' },\n warning: { badge: 'bg-rui-warning-fill text-rui-warning-foreground' },\n info: { badge: 'bg-rui-info-fill text-rui-info-foreground' },\n success: { badge: 'bg-rui-success-fill text-rui-success-foreground' },\n },\n // the icon is 60% of the badge height, as the text is, rather than filling it\n size: {\n sm: { badge: 'min-h-4 min-w-4 text-caption-2 [--rui-icon-size:0.625rem]' },\n md: { badge: 'min-h-5 min-w-5 [--rui-icon-size:0.75rem]' },\n lg: { badge: 'min-h-6 min-w-6 [--rui-icon-size:0.875rem]' },\n },\n rounded: {\n sm: { badge: 'rounded-xs' },\n md: { badge: 'rounded-rui-control' },\n lg: { badge: 'rounded-rui-card' },\n full: { badge: 'rounded-full' },\n },\n // A surface ring keeps a dot apart from whatever it overlaps, such as an avatar edge\n dot: {\n true: { badge: 'ring-2 ring-rui-surface' },\n },\n // an icon alone needs no side padding, so the badge stays as wide as it is tall\n iconOnly: {\n true: { content: 'px-0' },\n false: {},\n },\n },\n compoundVariants: [\n // the default dot is a step lighter in dark, where neutral-500 nearly vanished against a dark control\n { dot: true, color: 'default', class: { badge: 'bg-rui-neutral-500 dark:bg-rui-neutral-400' } },\n // A dot carries no text, so it keeps the brighter `main`, which reads better as a small mark on a dark page\n { dot: true, color: 'error', class: { badge: 'dark:bg-rui-error' } },\n { dot: true, color: 'warning', class: { badge: 'dark:bg-rui-warning' } },\n { dot: true, color: 'info', class: { badge: 'dark:bg-rui-info' } },\n { dot: true, color: 'success', class: { badge: 'dark:bg-rui-success' } },\n\n // Dot sizes: 8, 10 and 12px, since half of a dot sits off the corner and reads smaller than it is\n { dot: true, size: 'sm', class: { badge: 'min-w-2 min-h-2' } },\n { dot: true, size: 'md', class: { badge: 'min-w-2.5 min-h-2.5' } },\n { dot: true, size: 'lg', class: { badge: 'min-w-3 min-h-3' } },\n ],\n defaultVariants: {\n color: 'primary',\n size: 'md',\n rounded: 'full',\n dot: false,\n },\n});\n\nconst hasText = computed<boolean>(() => !!text || !!slots.badge);\n\nconst hasIconAndText = computed<boolean>(() => (!!icon || !!slots.icon) && get(hasText));\n\nconst ui = computed<ReturnType<typeof badgeStyles>>(() => badgeStyles({\n color,\n size,\n rounded,\n dot,\n iconOnly: (!!icon || !!slots.icon) && !get(hasText),\n}));\n\n/** Dot positions as [leftOffset, rightBase, edgeBase, centerOffset]; a dot's center sits on the corner, so each size moves by half its diameter. */\nconst DOT_POS: Record<BadgeSize, PosConfig> = {\n sm: [-0.25, '100% - 0.25rem', '100% - 0.25rem', 0.25],\n md: [-0.3125, '100% - 0.3125rem', '100% - 0.3125rem', 0.3125],\n lg: [-0.375, '100% - 0.375rem', '100% - 0.375rem', 0.375],\n};\nconst BADGE_POS: Record<BadgeSize, PosConfig> = {\n sm: [-0.85, '100% - 0.375rem', '100% - 0.375rem', 0.55],\n md: [-0.95, '100% - 0.5rem', '100% - 0.5rem', 0.65],\n lg: [-1.05, '100% - 0.5rem', '100% - 0.5rem', 0.75],\n};\n\nconst positionStyle = computed<Record<string, string>>(() => {\n const ox = Number(offsetX) * 0.0625;\n const oy = Number(offsetY) * 0.0625;\n const [l, r, edge, center] = dot ? DOT_POS[size] : BADGE_POS[size];\n\n const horizontal = `calc(${left ? `${l}rem` : r} + ${ox}rem)`;\n const vertical = placement === 'center'\n ? `calc(50% - ${center}rem - ${oy}rem)`\n : `calc(${edge} - ${oy}rem)`;\n\n return {\n left: horizontal,\n [placement === 'top' ? 'bottom' : 'top']: vertical,\n };\n});\n</script>\n\n<template>\n <div :class=\"ui.wrapper()\">\n <slot />\n <!-- under reduced motion the badge appears and leaves at full size, with no scale -->\n <Transition\n appear\n enter-active-class=\"transition-[scale] ease-out duration-200 motion-reduce:transition-none\"\n enter-from-class=\"scale-0 motion-reduce:scale-100\"\n enter-to-class=\"scale-100\"\n leave-active-class=\"transition-[scale] ease-in duration-150 motion-reduce:transition-none\"\n leave-from-class=\"scale-100\"\n leave-to-class=\"scale-0 motion-reduce:scale-100\"\n >\n <div\n v-if=\"modelValue\"\n :class=\"ui.badge()\"\n :style=\"positionStyle\"\n :data-placement=\"placement\"\n :data-dot=\"dot || undefined\"\n :data-left=\"left || undefined\"\n aria-atomic=\"true\"\n aria-live=\"polite\"\n role=\"status\"\n >\n <!-- no aria-label: on a live region it replaced the count, so a reader announced \"Badge\" -->\n <span\n v-if=\"!dot\"\n :class=\"ui.content({ class: hasIconAndText ? 'px-2' : undefined })\"\n >\n <slot name=\"badge\">\n {{ text }}\n </slot>\n <slot name=\"icon\">\n <RuiIcon\n v-if=\"icon\"\n :name=\"icon\"\n />\n </slot>\n </span>\n </div>\n </Transition>\n </div>\n</template>\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAyCA,MAAM,QAAQA,SAAA;EAMd,MAAM,cAAc,GAAG;GACrB,OAAO;IACL,SAAS;IACT,OAAO;IACP,SAAS;GACX;GACA,UAAU;IAER,OAAO;KACL,SAAS,EAAE,OAAO,6CAA6C;KAC/D,SAAS,EAAE,OAAO,kDAAkD;KACpE,WAAW,EAAE,OAAO,sDAAsD;KAC1E,OAAO,EAAE,OAAO,8CAA8C;KAC9D,SAAS,EAAE,OAAO,kDAAkD;KACpE,MAAM,EAAE,OAAO,4CAA4C;KAC3D,SAAS,EAAE,OAAO,kDAAkD;IACtE;IAEA,MAAM;KACJ,IAAI,EAAE,OAAO,4DAA4D;KACzE,IAAI,EAAE,OAAO,4CAA4C;KACzD,IAAI,EAAE,OAAO,6CAA6C;IAC5D;IACA,SAAS;KACP,IAAI,EAAE,OAAO,aAAa;KAC1B,IAAI,EAAE,OAAO,sBAAsB;KACnC,IAAI,EAAE,OAAO,mBAAmB;KAChC,MAAM,EAAE,OAAO,eAAe;IAChC;IAEA,KAAK,EACH,MAAM,EAAE,OAAO,0BAA0B,EAC3C;IAEA,UAAU;KACR,MAAM,EAAE,SAAS,OAAO;KACxB,OAAO,CAAC;IACV;GACF;GACA,kBAAkB;IAEhB;KAAE,KAAK;KAAM,OAAO;KAAW,OAAO,EAAE,OAAO,6CAA6C;IAAE;IAE9F;KAAE,KAAK;KAAM,OAAO;KAAS,OAAO,EAAE,OAAO,oBAAoB;IAAE;IACnE;KAAE,KAAK;KAAM,OAAO;KAAW,OAAO,EAAE,OAAO,sBAAsB;IAAE;IACvE;KAAE,KAAK;KAAM,OAAO;KAAQ,OAAO,EAAE,OAAO,mBAAmB;IAAE;IACjE;KAAE,KAAK;KAAM,OAAO;KAAW,OAAO,EAAE,OAAO,sBAAsB;IAAE;IAGvE;KAAE,KAAK;KAAM,MAAM;KAAM,OAAO,EAAE,OAAO,kBAAkB;IAAE;IAC7D;KAAE,KAAK;KAAM,MAAM;KAAM,OAAO,EAAE,OAAO,sBAAsB;IAAE;IACjE;KAAE,KAAK;KAAM,MAAM;KAAM,OAAO,EAAE,OAAO,kBAAkB;IAAE;GAC/D;GACA,iBAAiB;IACf,OAAO;IACP,MAAM;IACN,SAAS;IACT,KAAK;GACP;EACF,CAAC;EAED,MAAM,UAAU,eAAwB,CAAC,CAAC,QAAA,QAAQ,CAAC,CAAC,MAAM,KAAK;EAE/D,MAAM,iBAAiB,gBAAyB,CAAC,CAAC,QAAA,QAAQ,CAAC,CAAC,MAAM,SAAS,IAAI,OAAO,CAAC;EAEvF,MAAM,KAAK,eAA+C,YAAY;GACpE,OAAI,QAAA;GACJ,MAAG,QAAA;GACH,SAAM,QAAA;GACN,KAAE,QAAA;GACF,WAAW,CAAC,CAAC,QAAA,QAAQ,CAAC,CAAC,MAAM,SAAS,CAAC,IAAI,OAAO;EACpD,CAAC,CAAC;;EAGF,MAAM,UAAwC;GAC5C,IAAI;IAAC;IAAO;IAAkB;IAAkB;GAAI;GACpD,IAAI;IAAC;IAAS;IAAoB;IAAoB;GAAM;GAC5D,IAAI;IAAC;IAAQ;IAAmB;IAAmB;GAAK;EAC1D;EACA,MAAM,YAA0C;GAC9C,IAAI;IAAC;IAAO;IAAmB;IAAmB;GAAI;GACtD,IAAI;IAAC;IAAO;IAAiB;IAAiB;GAAI;GAClD,IAAI;IAAC;IAAO;IAAiB;IAAiB;GAAI;EACpD;EAEA,MAAM,gBAAgB,eAAuC;GAC3D,MAAM,KAAK,OAAO,QAAA,OAAO,IAAI;GAC7B,MAAM,KAAK,OAAO,QAAA,OAAO,IAAI;GAC7B,MAAM,CAAC,GAAG,GAAG,MAAM,UAAU,QAAA,MAAM,QAAQ,QAAA,QAAQ,UAAU,QAAA;GAE7D,MAAM,aAAa,QAAQ,QAAA,OAAO,GAAG,EAAE,OAAO,EAAE,KAAK,GAAG;GACxD,MAAM,WAAW,QAAA,cAAc,WAC3B,cAAc,OAAO,QAAQ,GAAG,QAChC,QAAQ,KAAK,KAAK,GAAG;GAEzB,OAAO;IACL,MAAM;KACL,QAAA,cAAc,QAAQ,WAAW,QAAQ;GAC5C;EACF,CAAC;;GAIC,OAAAC,UAAA,GAAAC,mBAwCM,OAAA,EAxCA,OAAKC,eAAEC,MAAA,EAAA,CAAE,CAAC,QAAO,CAAA,EAAA,GAAA,CACrBC,WAAQ,KAAA,QAAA,SAAA,GAERC,YAoCaC,YAAA;IAnCX,QAAA;IACA,sBAAmB;IACnB,oBAAiB;IACjB,kBAAe;IACf,sBAAmB;IACnB,oBAAiB;IACjB,kBAAe;;IAEf,SAAAC,cA0BM,CAzBE,QAAA,cADRP,UAAA,GAAAC,mBA0BM,OAAA;;KAxBH,OAAKC,eAAEC,MAAA,EAAA,CAAE,CAAC,MAAK,CAAA;KACf,OAAKK,eAAEL,MAAA,aAAA,CAAa;KACpB,kBAAgB,QAAA;KAChB,YAAU,QAAA,OAAO,KAAA;KACjB,aAAW,QAAA,QAAQ,KAAA;KACpB,eAAY;KACZ,aAAU;KACV,MAAK;IAII,GAAA,CAAA,CAAA,QAAA,OADTH,UAAA,GAAAC,mBAaO,QAAA;;KAXJ,OAAKC,eAAEC,MAAA,EAAA,CAAE,CAAC,QAAO,EAAA,OAAUA,MAAA,cAAA,IAAc,SAAY,KAAA,EAAS,CAAA,CAAA;IAE/DC,GAAAA,CAAAA,WAEO,KAAA,QAAA,SAAA,CAAA,SAAA,CADFK,gBAAAC,gBAAA,QAAA,IAAI,GAAA,CAAA,CAAA,CAAA,GAETN,WAKO,KAAA,QAAA,QAAA,CAAA,SAAA,CAHG,QAAA,QADRJ,UAAA,GAAAW,YAGEC,iBAAA;;KADC,MAAM,QAAA"}
@@ -1 +1 @@
1
- {"version":3,"file":"RuiBottomSheet.js","names":[],"sources":["../../../../src/components/overlays/bottom-sheet/RuiBottomSheet.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport RuiDialog from '@/components/overlays/dialog/RuiDialog.vue';\n\n/** The sheet's props, which stay in step with RuiDialog's. */\nexport interface BottomSheetProps {\n persistent?: boolean;\n width?: string | number;\n maxWidth?: string | number;\n}\n\ndefineOptions({\n name: 'RuiBottomSheet',\n inheritAttrs: false,\n});\n\nconst modelValue = defineModel<boolean>({ default: false });\n\nconst { persistent = false, width, maxWidth } = defineProps<BottomSheetProps>();\n</script>\n\n<template>\n <RuiDialog\n v-model=\"modelValue\"\n bottom-sheet\n v-bind=\"$attrs\"\n :persistent=\"persistent\"\n :width=\"width\"\n :max-width=\"maxWidth\"\n >\n <template\n v-for=\"slot in Object.keys($slots)\"\n #[slot]=\"scope\"\n >\n <slot\n v-bind=\"scope\"\n :name=\"slot\"\n />\n </template>\n </RuiDialog>\n</template>\n"],"mappings":""}
1
+ {"version":3,"file":"RuiBottomSheet.js","names":["_sfc_main"],"sources":["../../../../src/components/overlays/bottom-sheet/RuiBottomSheet.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport RuiDialog from '@/components/overlays/dialog/RuiDialog.vue';\n\n/** The sheet's props, which stay in step with RuiDialog's. */\nexport interface BottomSheetProps {\n persistent?: boolean;\n width?: string | number;\n maxWidth?: string | number;\n}\n\ndefineOptions({\n name: 'RuiBottomSheet',\n inheritAttrs: false,\n});\n\nconst modelValue = defineModel<boolean>({ default: false });\n\nconst { persistent = false, width, maxWidth } = defineProps<BottomSheetProps>();\n</script>\n\n<template>\n <RuiDialog\n v-model=\"modelValue\"\n bottom-sheet\n v-bind=\"$attrs\"\n :persistent=\"persistent\"\n :width=\"width\"\n :max-width=\"maxWidth\"\n >\n <template\n v-for=\"slot in Object.keys($slots)\"\n #[slot]=\"scope\"\n >\n <slot\n v-bind=\"scope\"\n :name=\"slot\"\n />\n </template>\n </RuiDialog>\n</template>\n"],"mappings":""}
@@ -1 +1 @@
1
- {"version":3,"file":"RuiBottomSheet.vue_vue_type_script_setup_true_lang.js","names":["$attrs","$slots"],"sources":["../../../../src/components/overlays/bottom-sheet/RuiBottomSheet.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport RuiDialog from '@/components/overlays/dialog/RuiDialog.vue';\n\n/** The sheet's props, which stay in step with RuiDialog's. */\nexport interface BottomSheetProps {\n persistent?: boolean;\n width?: string | number;\n maxWidth?: string | number;\n}\n\ndefineOptions({\n name: 'RuiBottomSheet',\n inheritAttrs: false,\n});\n\nconst modelValue = defineModel<boolean>({ default: false });\n\nconst { persistent = false, width, maxWidth } = defineProps<BottomSheetProps>();\n</script>\n\n<template>\n <RuiDialog\n v-model=\"modelValue\"\n bottom-sheet\n v-bind=\"$attrs\"\n :persistent=\"persistent\"\n :width=\"width\"\n :max-width=\"maxWidth\"\n >\n <template\n v-for=\"slot in Object.keys($slots)\"\n #[slot]=\"scope\"\n >\n <slot\n v-bind=\"scope\"\n :name=\"slot\"\n />\n </template>\n </RuiDialog>\n</template>\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;EAeA,MAAM,aAAa,SAAoB,SAAA,YAAmB;;GAMxD,OAAA,UAAA,GAAA,YAiBY,mBAjBZ,WAiBY;IAhBD,YAAA,WAAA;IAAA,uBAAA,OAAA,OAAA,OAAA,MAAA,WAAA,WAAU,QAAA;IACnB,gBAAA;GACQA,GAAAA,KAAAA,QAAM;IACb,YAAY,QAAA;IACZ,OAAO,QAAA;IACP,aAAW,QAAA;GAGK,CAAA,GAAA,YAAA,EAAA,GAAA,EAAA,GAAA,CAAA,WAAA,OAAO,KAAKC,KAAAA,MAAM,IAA1B,SAAI;;KACV,MAAA;KAED,IAAA,SAFS,UAAK,CAEd,WAGE,KAAA,QADO,MAAI,eAAA,mBADH,KAAK,CAAA,CAAA,CAAA,CAAA"}
1
+ {"version":3,"file":"RuiBottomSheet.vue_vue_type_script_setup_true_lang.js","names":["$attrs","$slots","_useModel","_openBlock","_createBlock","RuiDialog","_mergeProps","_createSlots","_renderList","_withCtx","_renderSlot","_normalizeProps","_guardReactiveProps"],"sources":["../../../../src/components/overlays/bottom-sheet/RuiBottomSheet.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport RuiDialog from '@/components/overlays/dialog/RuiDialog.vue';\n\n/** The sheet's props, which stay in step with RuiDialog's. */\nexport interface BottomSheetProps {\n persistent?: boolean;\n width?: string | number;\n maxWidth?: string | number;\n}\n\ndefineOptions({\n name: 'RuiBottomSheet',\n inheritAttrs: false,\n});\n\nconst modelValue = defineModel<boolean>({ default: false });\n\nconst { persistent = false, width, maxWidth } = defineProps<BottomSheetProps>();\n</script>\n\n<template>\n <RuiDialog\n v-model=\"modelValue\"\n bottom-sheet\n v-bind=\"$attrs\"\n :persistent=\"persistent\"\n :width=\"width\"\n :max-width=\"maxWidth\"\n >\n <template\n v-for=\"slot in Object.keys($slots)\"\n #[slot]=\"scope\"\n >\n <slot\n v-bind=\"scope\"\n :name=\"slot\"\n />\n </template>\n </RuiDialog>\n</template>\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;EAeA,MAAM,aAAaE,SAAoB,SAAA,YAAmB;;GAMxD,OAAAC,UAAA,GAAAC,YAiBYC,mBAjBZC,WAiBY;IAhBD,YAAA,WAAA;IAAA,uBAAA,OAAA,OAAA,OAAA,MAAA,WAAA,WAAU,QAAA;IACnB,gBAAA;GACQN,GAAAA,KAAAA,QAAM;IACb,YAAY,QAAA;IACZ,OAAO,QAAA;IACP,aAAW,QAAA;GAGKQ,CAAAA,GAAAA,YAAAA,EAAAA,GAAAA,EAAAA,GAAAA,CAAAA,WAAA,OAAO,KAAKP,KAAAA,MAAM,IAA1B,SAAI;;KACV,MAAA;KAED,IAAAQ,SAFS,UAAK,CAEdC,WAGE,KAAA,QADO,MAAIC,eAAAC,mBADH,KAAK,CAAA,CAAA,CAAA,CAAA"}
@@ -1 +1 @@
1
- {"version":3,"file":"RuiDialog.js","names":[],"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, tv } from '@/utils/tv';\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 dialog = tv({\n slots: {\n root: 'fixed inset-0',\n overlay: 'absolute inset-0 backdrop-blur-sm bg-rui-neutral-950/40 dark:bg-black/60',\n content: 'absolute left-1/2 bottom-0 -translate-x-1/2 outline-hidden overflow-y-auto max-h-(--rui-dialog-max-height)',\n },\n variants: {\n /*\n * The corners match a RuiCard's, the usual content, which the box clips while it scrolls.\n * A sheet sits on the screen's bottom edge, so its content's bottom corners are squared.\n */\n bottomSheet: {\n true: { content: 'rounded-t-rui-card shadow-rui-drawer *:rounded-b-none' },\n false: { content: 'top-1/2 -translate-y-1/2 bottom-auto rounded-rui-card shadow-rui-menu' },\n },\n },\n defaultVariants: { bottomSheet: false },\n});\n\nconst ui = computed<ReturnType<typeof dialog>>(() => dialog({ 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\nfunction onEscClick(): void {\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.stop=\"onEscClick()\"\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":""}
1
+ {"version":3,"file":"RuiDialog.js","names":["_sfc_main"],"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, tv } from '@/utils/tv';\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 dialog = tv({\n slots: {\n root: 'fixed inset-0',\n overlay: 'absolute inset-0 backdrop-blur-sm bg-rui-neutral-950/40 dark:bg-black/60',\n content: 'absolute left-1/2 bottom-0 -translate-x-1/2 outline-hidden overflow-y-auto max-h-(--rui-dialog-max-height)',\n },\n variants: {\n /*\n * The corners match a RuiCard's, the usual content, which the box clips while it scrolls.\n * A sheet sits on the screen's bottom edge, so its content's bottom corners are squared.\n */\n bottomSheet: {\n true: { content: 'rounded-t-rui-card shadow-rui-drawer *:rounded-b-none' },\n false: { content: 'top-1/2 -translate-y-1/2 bottom-auto rounded-rui-card shadow-rui-menu' },\n },\n },\n defaultVariants: { bottomSheet: false },\n});\n\nconst ui = computed<ReturnType<typeof dialog>>(() => dialog({ 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\nfunction onEscClick(): void {\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.stop=\"onEscClick()\"\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":""}
@@ -1,5 +1,5 @@
1
1
  import type { DialogSize } from '../../../consts/tokens.js';
2
- import type { VueClassValue } from '../../../types/class-value';
2
+ import type { VueClassValue } from '../../../types/class-value.js';
3
3
  export interface RuiDialogClassNames {
4
4
  root?: VueClassValue;
5
5
  content?: VueClassValue;
@@ -1 +1 @@
1
- {"version":3,"file":"RuiDialog.vue_vue_type_script_setup_true_lang.js","names":["$attrs"],"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, tv } from '@/utils/tv';\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 dialog = tv({\n slots: {\n root: 'fixed inset-0',\n overlay: 'absolute inset-0 backdrop-blur-sm bg-rui-neutral-950/40 dark:bg-black/60',\n content: 'absolute left-1/2 bottom-0 -translate-x-1/2 outline-hidden overflow-y-auto max-h-(--rui-dialog-max-height)',\n },\n variants: {\n /*\n * The corners match a RuiCard's, the usual content, which the box clips while it scrolls.\n * A sheet sits on the screen's bottom edge, so its content's bottom corners are squared.\n */\n bottomSheet: {\n true: { content: 'rounded-t-rui-card shadow-rui-drawer *:rounded-b-none' },\n false: { content: 'top-1/2 -translate-y-1/2 bottom-auto rounded-rui-card shadow-rui-menu' },\n },\n },\n defaultVariants: { bottomSheet: false },\n});\n\nconst ui = computed<ReturnType<typeof dialog>>(() => dialog({ 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\nfunction onEscClick(): void {\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.stop=\"onEscClick()\"\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","_withModifiers","_createVNode","_Transition","_withCtx","_normalizeClass","_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, tv } from '@/utils/tv';\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 dialog = tv({\n slots: {\n root: 'fixed inset-0',\n overlay: 'absolute inset-0 backdrop-blur-sm bg-rui-neutral-950/40 dark:bg-black/60',\n content: 'absolute left-1/2 bottom-0 -translate-x-1/2 outline-hidden overflow-y-auto max-h-(--rui-dialog-max-height)',\n },\n variants: {\n /*\n * The corners match a RuiCard's, the usual content, which the box clips while it scrolls.\n * A sheet sits on the screen's bottom edge, so its content's bottom corners are squared.\n */\n bottomSheet: {\n true: { content: 'rounded-t-rui-card shadow-rui-drawer *:rounded-b-none' },\n false: { content: 'top-1/2 -translate-y-1/2 bottom-auto rounded-rui-card shadow-rui-menu' },\n },\n },\n defaultVariants: { bottomSheet: false },\n});\n\nconst ui = computed<ReturnType<typeof dialog>>(() => dialog({ 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\nfunction onEscClick(): void {\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.stop=\"onEscClick()\"\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":[],"sources":["../../../../src/components/overlays/menu/RuiMenu.vue"],"sourcesContent":["<script setup lang=\"ts\">\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 } from '@/composables/floating';\nimport { useFormTextDetail } from '@/utils/form-text-detail';\nimport { cn, tv } from '@/utils/tv';\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 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\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 dense = false,\n persistent = false,\n disableAutoFocus = false,\n anchorEl,\n role = 'menu',\n menuLabel,\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 menuContent = useTemplateRef<HTMLElement>('menuContent');\nconst menuId = useId();\n\nconst FOCUSABLE_ELEMENTS_SELECTOR =\n 'button, [href], input, select, textarea, [tabindex]:not([tabindex=\"-1\"])';\n\nconst {\n reference: activator,\n popover: menu,\n open,\n visible,\n currentPlacement,\n leavePending,\n onLeavePending,\n onOpen,\n onClose,\n onLeaveComplete,\n updatePosition,\n} = useFloating(\n () => options ?? {},\n () => disabled,\n () => openDelay,\n () => closeDelay,\n () => anchorEl,\n);\n\nconst { width } = useElementSize(activator);\n\nconst { hasError, hasSuccess } = useFormTextDetail(\n () => errorMessages,\n () => successMessages,\n);\n\nconst menuStyles = tv({\n slots: {\n wrapper: 'relative inline-flex max-w-full',\n popover: 'w-max z-rui-menu',\n // a hairline edge keeps the popup apart from a surface of nearly the same shade in dark mode\n content: 'rounded-rui-panel overflow-hidden shadow-rui-menu bg-rui-menu border border-rui-divider text-rui-text focus:outline-hidden p-1',\n details: 'pt-1',\n },\n variants: {\n fullWidth: {\n true: { wrapper: 'w-full' },\n },\n dense: {\n true: { details: 'px-2' },\n false: { details: 'px-4' },\n },\n },\n defaultVariants: { fullWidth: false, dense: false },\n});\n\nconst ui = computed<ReturnType<typeof menuStyles>>(() => menuStyles({\n fullWidth,\n dense,\n}));\n\n// `aria-haspopup=\"true\"` means `\"menu\"`, and the default keeps emitting `true` for existing callers\nconst ariaHasPopup = computed<RuiMenuRole | 'true'>(() => role === 'menu' ? 'true' : role);\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 onOpen();\n },\n onMouseleave: disabled\n ? undefined\n : () => {\n if (openOnHover && !clickVal)\n onClose();\n },\n };\n});\n\nconst menuAttrs = computed<MenuAttrs>(() => ({\n ...get(baseMenuAttrs),\n 'onClick': disabled ? undefined : checkClick,\n 'aria-haspopup': get(ariaHasPopup),\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 * 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 if (!get(open))\n return;\n 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 */\nfunction onEscape(event: KeyboardEvent): void {\n if (persistent)\n return;\n\n onLeave(event);\n}\n\nfunction checkClick(): void {\n if (get(open) && get(click)) {\n if (!persistOnActivatorClick)\n onLeave();\n }\n else {\n onOpen();\n set(click, true);\n }\n}\n\nwatch(modelValue, (value) => {\n if (get(open) === value)\n return;\n\n if (value) {\n onOpen();\n set(click, true);\n }\n else {\n onLeave();\n }\n});\n\nwatch(open, (open) => {\n set(modelValue, open);\n if (open) {\n focusMenu();\n }\n});\n\nonClickOutside(menu, () => {\n if (get(open) && !persistent)\n onLeave();\n}, { ignore: [activator] });\n</script>\n\n<template>\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.\n -->\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 >\n <slot\n name=\"activator\"\n v-bind=\"{ attrs: menuAttrs, open, disabled, hasError, hasSuccess }\"\n />\n </div>\n <Teleport\n v-if=\"!disabled\"\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=\"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=\"updatePosition()\"\n @after-leave=\"leavePending ? onLeaveComplete() : undefined\"\n @before-leave=\"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 }\" />\n </ButtonGroupBoundary>\n </div>\n </TransitionGroup>\n </div>\n </Teleport>\n <RuiFormTextDetail\n v-if=\"showDetails\"\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 { 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 } from '@/composables/floating';\nimport { useFormTextDetail } from '@/utils/form-text-detail';\nimport { cn, tv } from '@/utils/tv';\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 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\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 dense = false,\n persistent = false,\n disableAutoFocus = false,\n anchorEl,\n role = 'menu',\n menuLabel,\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 menuContent = useTemplateRef<HTMLElement>('menuContent');\nconst menuId = useId();\n\nconst FOCUSABLE_ELEMENTS_SELECTOR =\n 'button, [href], input, select, textarea, [tabindex]:not([tabindex=\"-1\"])';\n\nconst {\n reference: activator,\n popover: menu,\n open,\n visible,\n currentPlacement,\n leavePending,\n onLeavePending,\n onOpen,\n onClose,\n onLeaveComplete,\n updatePosition,\n} = useFloating(\n () => options ?? {},\n () => disabled,\n () => openDelay,\n () => closeDelay,\n () => anchorEl,\n);\n\nconst { width } = useElementSize(activator);\n\nconst { hasError, hasSuccess } = useFormTextDetail(\n () => errorMessages,\n () => successMessages,\n);\n\nconst menuStyles = tv({\n slots: {\n wrapper: 'relative inline-flex max-w-full',\n popover: 'w-max z-rui-menu',\n // a hairline edge keeps the popup apart from a surface of nearly the same shade in dark mode\n content: 'rounded-rui-panel overflow-hidden shadow-rui-menu bg-rui-menu border border-rui-divider text-rui-text focus:outline-hidden p-1',\n details: 'pt-1',\n },\n variants: {\n fullWidth: {\n true: { wrapper: 'w-full' },\n },\n dense: {\n true: { details: 'px-2' },\n false: { details: 'px-4' },\n },\n },\n defaultVariants: { fullWidth: false, dense: false },\n});\n\nconst ui = computed<ReturnType<typeof menuStyles>>(() => menuStyles({\n fullWidth,\n dense,\n}));\n\n// `aria-haspopup=\"true\"` means `\"menu\"`, and the default keeps emitting `true` for existing callers\nconst ariaHasPopup = computed<RuiMenuRole | 'true'>(() => role === 'menu' ? 'true' : role);\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 onOpen();\n },\n onMouseleave: disabled\n ? undefined\n : () => {\n if (openOnHover && !clickVal)\n onClose();\n },\n };\n});\n\nconst menuAttrs = computed<MenuAttrs>(() => ({\n ...get(baseMenuAttrs),\n 'onClick': disabled ? undefined : checkClick,\n 'aria-haspopup': get(ariaHasPopup),\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 * 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 if (!get(open))\n return;\n 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 */\nfunction onEscape(event: KeyboardEvent): void {\n if (persistent)\n return;\n\n onLeave(event);\n}\n\nfunction checkClick(): void {\n if (get(open) && get(click)) {\n if (!persistOnActivatorClick)\n onLeave();\n }\n else {\n onOpen();\n set(click, true);\n }\n}\n\nwatch(modelValue, (value) => {\n if (get(open) === value)\n return;\n\n if (value) {\n onOpen();\n set(click, true);\n }\n else {\n onLeave();\n }\n});\n\nwatch(open, (open) => {\n set(modelValue, open);\n if (open) {\n focusMenu();\n }\n});\n\nonClickOutside(menu, () => {\n if (get(open) && !persistent)\n onLeave();\n}, { ignore: [activator] });\n</script>\n\n<template>\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.\n -->\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 >\n <slot\n name=\"activator\"\n v-bind=\"{ attrs: menuAttrs, open, disabled, hasError, hasSuccess }\"\n />\n </div>\n <Teleport\n v-if=\"!disabled\"\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=\"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=\"updatePosition()\"\n @after-leave=\"leavePending ? onLeaveComplete() : undefined\"\n @before-leave=\"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 }\" />\n </ButtonGroupBoundary>\n </div>\n </TransitionGroup>\n </div>\n </Teleport>\n <RuiFormTextDetail\n v-if=\"showDetails\"\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,4 +1,4 @@
1
- import type { VueClassValue } from '../../../types/class-value';
1
+ import type { VueClassValue } from '../../../types/class-value.js';
2
2
  import { type FloatingOptions } from '../../../composables/floating.js';
3
3
  export interface RuiMenuClassNames {
4
4
  root?: VueClassValue;