@livestorm/ui-vue 1.1.3 → 2.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (401) hide show
  1. package/README.md +154 -32
  2. package/components-vite.js +5 -5
  3. package/components.d.ts +3 -3
  4. package/dist/UiTimelineItem.vue_vue_type_style_index_0_lang-BN5208td.mjs +5452 -0
  5. package/dist/a11y--y7uaY4j.mjs +217 -0
  6. package/dist/breakpoints.mjs +9 -0
  7. package/dist/bus.mjs +5 -0
  8. package/dist/components.mjs +215 -1663
  9. package/dist/index.mjs +85 -166
  10. package/dist/integrations.mjs +8 -0
  11. package/dist/layouts.mjs +236 -0
  12. package/dist/responsive.mjs +25 -0
  13. package/dist/slot.mjs +21 -0
  14. package/dist/toastDSV2-wMh-UMzW.mjs +74 -0
  15. package/dist/types/index.d.ts +84 -0
  16. package/dist/types/src/components/Toast/LayoutToasts.vue.d.ts +3 -0
  17. package/dist/types/src/components/Toast/ToastMessage.vue.d.ts +21 -0
  18. package/dist/types/src/components/Toast/toastDSV2.d.ts +102 -0
  19. package/dist/types/src/components/UiActionBar/UiActionBar.vue.d.ts +44 -0
  20. package/dist/types/src/components/UiActionBar/UiActionBarItem.vue.d.ts +47 -0
  21. package/dist/types/src/components/UiActionBar/UiActionBarSeparator.vue.d.ts +3 -0
  22. package/dist/types/src/components/UiActionBar/index.d.ts +4 -0
  23. package/dist/types/src/components/UiActionBar/types.d.ts +14 -0
  24. package/dist/types/src/components/UiAnimatedLogo/UiAnimatedLogo.vue.d.ts +10 -0
  25. package/dist/types/src/components/UiAnimatedLogo/animations-links.d.ts +3 -0
  26. package/dist/types/src/components/UiAvatar/UiAvatar.vue.d.ts +55 -0
  27. package/dist/types/src/components/UiAvatar/index.d.ts +1 -0
  28. package/dist/types/src/components/UiAvatarList/UiAvatarList.vue.d.ts +28 -0
  29. package/dist/types/src/components/UiAvatarList/index.d.ts +1 -0
  30. package/dist/types/src/components/UiBadge/UiBadge.vue.d.ts +47 -0
  31. package/dist/types/src/components/UiBadge/index.d.ts +1 -0
  32. package/dist/types/src/components/UiBanner/UiBanner.vue.d.ts +96 -0
  33. package/dist/types/src/components/UiBanner/index.d.ts +2 -0
  34. package/dist/types/src/components/UiBreadcrumb/UiBreadcrumb.vue.d.ts +15 -0
  35. package/dist/types/src/components/UiBreadcrumb/index.d.ts +2 -0
  36. package/dist/types/src/components/UiButton/UiButton.vue.d.ts +280 -0
  37. package/dist/types/src/components/UiButtonGroup/UiButtonGroup.vue.d.ts +42 -0
  38. package/dist/types/src/components/UiButtonGroup/UiButtonGroupItem.vue.d.ts +21 -0
  39. package/dist/types/src/components/UiButtonGroup/index.d.ts +3 -0
  40. package/dist/types/src/components/UiButtonGroup/types.d.ts +10 -0
  41. package/dist/types/src/components/UiCard/UiCard.vue.d.ts +31 -0
  42. package/dist/types/src/components/UiCarousel/UiCarousel.vue.d.ts +63 -0
  43. package/dist/types/src/components/UiCarousel/index.d.ts +2 -0
  44. package/dist/types/src/components/UiColorField/UiColorField.vue.d.ts +19 -0
  45. package/dist/types/src/components/UiColorField/index.d.ts +2 -0
  46. package/dist/types/src/components/UiColorField/types.d.ts +29 -0
  47. package/dist/types/src/components/UiColorPicker/UiColorPicker.vue.d.ts +35 -0
  48. package/dist/types/src/components/UiColorPicker/index.d.ts +2 -0
  49. package/dist/types/src/components/UiColorPicker/types.d.ts +97 -0
  50. package/dist/types/src/components/UiDialog/MarketplaceHeaderExample.vue.d.ts +28 -0
  51. package/dist/types/src/components/UiDialog/UiDialog.vue.d.ts +18 -0
  52. package/dist/types/src/components/UiDialog/UiDialogClose.vue.d.ts +10 -0
  53. package/dist/types/src/components/UiDialog/UiDialogContent.vue.d.ts +54 -0
  54. package/dist/types/src/components/UiDialog/UiDialogFooter.vue.d.ts +13 -0
  55. package/dist/types/src/components/UiDialog/UiDialogTrigger.vue.d.ts +14 -0
  56. package/dist/types/src/components/UiDialog/index.d.ts +7 -0
  57. package/dist/types/src/components/UiDropdown/UiDropdown.vue.d.ts +42 -0
  58. package/dist/types/src/components/UiDropdown/UiDropdownContent.vue.d.ts +32 -0
  59. package/dist/types/src/components/UiDropdown/UiDropdownItem.vue.d.ts +27 -0
  60. package/dist/types/src/components/UiDropdown/UiDropdownSeparator.vue.d.ts +3 -0
  61. package/dist/types/src/components/UiDropdown/UiDropdownTrigger.vue.d.ts +45 -0
  62. package/dist/types/src/components/UiDropdown/context.d.ts +7 -0
  63. package/dist/types/src/components/UiDropdown/index.d.ts +6 -0
  64. package/dist/types/src/components/UiEmptyState/UiEmptyState.vue.d.ts +29 -0
  65. package/dist/types/src/components/UiFieldWrapper/UiFieldWrapper.vue.d.ts +36 -0
  66. package/dist/types/src/components/UiFieldWrapper/index.d.ts +1 -0
  67. package/dist/types/src/components/UiForm/UiFormField.types.d.ts +22 -0
  68. package/dist/types/src/components/UiForm/UiFormField.vue.d.ts +34 -0
  69. package/dist/types/src/components/UiForm/index.d.ts +3 -0
  70. package/dist/types/src/components/UiHorizontalSeparator/UiHorizontalSeparator.vue.d.ts +6 -0
  71. package/dist/types/src/components/UiInputCheckbox/UiInputCheckbox.vue.d.ts +108 -0
  72. package/dist/types/src/components/UiInputCheckbox/index.d.ts +2 -0
  73. package/dist/types/src/components/UiInputCheckbox/types.d.ts +1 -0
  74. package/dist/types/src/components/UiInputSelect/UiInputSelect.vue.d.ts +66 -0
  75. package/dist/types/src/components/UiInputSelect/index.d.ts +2 -0
  76. package/dist/types/src/components/UiInputSelect/types.d.ts +1 -0
  77. package/dist/types/src/components/UiInputTextarea/UiInputTextarea.vue.d.ts +49 -0
  78. package/dist/types/src/components/UiInputTextarea/index.d.ts +2 -0
  79. package/dist/types/src/components/UiInputTextarea/types.d.ts +1 -0
  80. package/dist/types/src/components/UiLabel/UiLabel.vue.d.ts +17 -0
  81. package/dist/types/src/components/UiList/UiList.vue.d.ts +27 -0
  82. package/dist/types/src/components/UiListItem/UiListItem.vue.d.ts +35 -0
  83. package/dist/types/src/components/UiLoader/UiLoader.vue.d.ts +17 -0
  84. package/dist/types/src/components/UiLogo/UiLogo.vue.d.ts +20 -0
  85. package/dist/types/src/components/UiLogo/variants/PulseVariant.vue.d.ts +3 -0
  86. package/dist/types/src/components/UiLogo/variants/TornadoVariant.vue.d.ts +3 -0
  87. package/dist/types/src/components/UiMenu/UiMenu.vue.d.ts +18 -0
  88. package/dist/types/src/components/UiMenu/UiMenuContent.vue.d.ts +30 -0
  89. package/dist/types/src/components/UiMenu/UiMenuGroup.vue.d.ts +16 -0
  90. package/dist/types/src/components/UiMenu/UiMenuItem.vue.d.ts +18 -0
  91. package/dist/types/src/components/UiMenu/UiMenuLabel.vue.d.ts +13 -0
  92. package/dist/types/src/components/UiMenu/UiMenuSeparator.vue.d.ts +13 -0
  93. package/dist/types/src/components/UiMenu/UiMenuSub.vue.d.ts +18 -0
  94. package/dist/types/src/components/UiMenu/UiMenuSubContent.vue.d.ts +32 -0
  95. package/dist/types/src/components/UiMenu/UiMenuSubTrigger.vue.d.ts +14 -0
  96. package/dist/types/src/components/UiMenu/UiMenuTrigger.vue.d.ts +14 -0
  97. package/dist/types/src/components/UiMenu/index.d.ts +10 -0
  98. package/dist/types/src/components/UiPage/UiPage.vue.d.ts +37 -0
  99. package/dist/types/src/components/UiPageHeader/UiPageHeader.vue.d.ts +33 -0
  100. package/dist/types/src/components/UiPopover/UiPopover.vue.d.ts +18 -0
  101. package/dist/types/src/components/UiPopover/UiPopoverAnchor.vue.d.ts +14 -0
  102. package/dist/types/src/components/UiPopover/UiPopoverContent.vue.d.ts +28 -0
  103. package/dist/types/src/components/UiPopover/UiPopoverTrigger.vue.d.ts +14 -0
  104. package/dist/types/src/components/UiProgress/UiProgress.vue.d.ts +15 -0
  105. package/dist/types/src/components/UiProgress/index.d.ts +2 -0
  106. package/dist/types/src/components/UiProgress/types.d.ts +4 -0
  107. package/dist/types/src/components/UiRoomButton/UiRoomButton.vue.d.ts +29 -0
  108. package/dist/types/src/components/UiShell/UiShell.vue.d.ts +24 -0
  109. package/dist/types/src/components/UiSideMenu/UiSideMenu.vue.d.ts +64 -0
  110. package/dist/types/src/components/UiSideMenu/UiSideMenuBottom.vue.d.ts +7 -0
  111. package/dist/types/src/components/UiSideMenu/UiSideMenuItem.vue.d.ts +53 -0
  112. package/dist/types/src/components/UiSideMenu/UiSideMenuItemContent.vue.d.ts +43 -0
  113. package/dist/types/src/components/UiSideMenu/UiSideMenuTop.vue.d.ts +7 -0
  114. package/dist/types/src/components/UiSideMenu/injection.d.ts +7 -0
  115. package/dist/types/src/components/UiSideMenu/types.d.ts +39 -0
  116. package/dist/types/src/components/UiSideMenu/useLabelHidden.d.ts +2 -0
  117. package/dist/types/src/components/UiSideMenu/useSideMenuLayout.d.ts +7 -0
  118. package/dist/types/src/components/UiStepper/UiStepper.vue.d.ts +18 -0
  119. package/dist/types/src/components/UiStepper/UiStepperDescription.vue.d.ts +14 -0
  120. package/dist/types/src/components/UiStepper/UiStepperIndicator.vue.d.ts +20 -0
  121. package/dist/types/src/components/UiStepper/UiStepperItem.vue.d.ts +19 -0
  122. package/dist/types/src/components/UiStepper/UiStepperSeparator.vue.d.ts +10 -0
  123. package/dist/types/src/components/UiStepper/UiStepperTitle.vue.d.ts +14 -0
  124. package/dist/types/src/components/UiStepper/index.d.ts +7 -0
  125. package/dist/types/src/components/UiTable/UiTable.vue.d.ts +20 -0
  126. package/dist/types/src/components/UiTable/UiTableBody.vue.d.ts +13 -0
  127. package/dist/types/src/components/UiTable/UiTableCell.vue.d.ts +13 -0
  128. package/dist/types/src/components/UiTable/UiTableHeader.vue.d.ts +13 -0
  129. package/dist/types/src/components/UiTable/UiTableHeaderCell.vue.d.ts +13 -0
  130. package/dist/types/src/components/UiTable/UiTableRow.vue.d.ts +16 -0
  131. package/dist/types/src/components/UiTable/index.d.ts +6 -0
  132. package/dist/types/src/components/UiTabs/UiTabs.vue.d.ts +37 -0
  133. package/dist/types/src/components/UiTabs/index.d.ts +2 -0
  134. package/dist/types/src/components/UiTag/UiTag.vue.d.ts +43 -0
  135. package/dist/types/src/components/UiTag/index.d.ts +1 -0
  136. package/dist/types/src/components/UiTextField/UiTextField.vue.d.ts +65 -0
  137. package/dist/types/src/components/UiTextField/index.d.ts +2 -0
  138. package/dist/types/src/components/UiTextField/types.d.ts +2 -0
  139. package/dist/types/src/components/UiTimeline/UiTimeline.vue.d.ts +19 -0
  140. package/dist/types/src/components/UiTimeline/UiTimelineItem.vue.d.ts +28 -0
  141. package/dist/types/src/components/UiTimeline/index.d.ts +2 -0
  142. package/dist/types/src/components/UiTooltip/UiTooltip.vue.d.ts +41 -0
  143. package/dist/types/src/components/UiTooltip/UiTooltipContent.vue.d.ts +54 -0
  144. package/dist/types/src/components/UiTooltip/UiTooltipProvider.vue.d.ts +17 -0
  145. package/dist/types/src/components/UiTooltip/UiTooltipTrigger.vue.d.ts +14 -0
  146. package/dist/types/src/components/UiTooltip/index.d.ts +4 -0
  147. package/dist/types/src/composables/useButtonStyles.d.ts +20 -0
  148. package/dist/types/src/composables/useMobileMenu.d.ts +11 -0
  149. package/dist/types/src/composables/useThemeAndModes.d.ts +34 -0
  150. package/dist/types/src/constants/index.d.ts +2 -0
  151. package/dist/types/src/constants/sizes.d.ts +2 -0
  152. package/dist/types/src/constants/themes.d.ts +22 -0
  153. package/dist/types/src/integrations/index.d.ts +1 -0
  154. package/dist/types/src/layouts/index.d.ts +2 -0
  155. package/dist/types/src/mixins/DynamicAction.d.ts +30 -0
  156. package/dist/types/src/primitives.d.ts +6 -0
  157. package/dist/types/src/theme.d.ts +1 -0
  158. package/dist/types/src/utils/a11y.d.ts +2 -0
  159. package/dist/types/src/utils/breakpoints.d.ts +9 -0
  160. package/dist/types/src/utils/bus.d.ts +2 -0
  161. package/dist/types/src/utils/clipboard.d.ts +4 -0
  162. package/dist/types/src/utils/devices.d.ts +19 -0
  163. package/dist/types/src/utils/elements.d.ts +1 -0
  164. package/dist/types/src/utils/index.d.ts +9 -0
  165. package/dist/types/src/utils/numbers.d.ts +30 -0
  166. package/dist/types/src/utils/responsive.d.ts +5 -0
  167. package/dist/types/src/utils/responsive.types.d.ts +12 -0
  168. package/dist/types/src/utils/router.d.ts +1 -0
  169. package/dist/types/src/utils/slot.d.ts +8 -0
  170. package/dist/types/src/utils/stack-view.d.ts +10 -0
  171. package/dist/types/src/utils/uid.d.ts +1 -0
  172. package/dist/types/style.d.ts +1 -0
  173. package/dist/ui-vue.css +1 -0
  174. package/dist/useThemeAndModes-DY5SDC0a.mjs +109 -0
  175. package/dist/utils.mjs +146 -0
  176. package/index.d.ts +88 -2
  177. package/index.js +169 -16
  178. package/integrations.d.ts +10 -0
  179. package/package.json +130 -63
  180. package/src/components/Toast/LayoutToasts.vue +63 -0
  181. package/src/components/Toast/ToastMessage.vue +208 -0
  182. package/src/components/Toast/toastDSV2.ts +151 -0
  183. package/src/components/UiActionBar/UiActionBar.vue +86 -0
  184. package/src/components/UiActionBar/UiActionBarItem.vue +179 -0
  185. package/src/components/UiActionBar/UiActionBarSeparator.vue +18 -0
  186. package/src/components/UiActionBar/index.ts +4 -0
  187. package/src/components/UiActionBar/types.ts +24 -0
  188. package/src/components/UiAnimatedLogo/UiAnimatedLogo.vue +47 -0
  189. package/src/components/UiAnimatedLogo/animations-links.ts +6 -0
  190. package/src/components/UiAvatar/UiAvatar.vue +186 -0
  191. package/src/components/UiAvatar/index.js +1 -0
  192. package/src/components/UiAvatarList/UiAvatarList.vue +109 -0
  193. package/src/components/UiAvatarList/index.js +1 -0
  194. package/src/components/UiBadge/UiBadge.vue +161 -0
  195. package/src/components/UiBadge/index.ts +2 -0
  196. package/src/components/UiBanner/UiBanner.vue +363 -0
  197. package/src/components/UiBanner/index.ts +2 -0
  198. package/src/components/UiBreadcrumb/UiBreadcrumb.vue +93 -0
  199. package/src/components/UiBreadcrumb/index.ts +2 -0
  200. package/src/components/UiButton/UiButton.vue +322 -0
  201. package/src/components/UiButtonGroup/UiButtonGroup.vue +198 -0
  202. package/src/components/UiButtonGroup/UiButtonGroupItem.vue +123 -0
  203. package/src/components/UiButtonGroup/index.ts +3 -0
  204. package/src/components/UiButtonGroup/types.ts +24 -0
  205. package/src/components/UiCard/UiCard.vue +112 -0
  206. package/src/components/UiCarousel/UiCarousel.vue +215 -0
  207. package/src/components/UiCarousel/index.ts +2 -0
  208. package/src/components/UiColorField/UiColorField.vue +158 -0
  209. package/src/components/UiColorField/index.ts +2 -0
  210. package/src/components/UiColorField/types.ts +30 -0
  211. package/src/components/UiColorPicker/UiColorPicker.vue +487 -0
  212. package/src/components/UiColorPicker/index.ts +2 -0
  213. package/src/components/UiColorPicker/types.ts +103 -0
  214. package/src/components/UiDialog/MarketplaceHeaderExample.vue +217 -0
  215. package/src/components/UiDialog/UiDialog.md +97 -0
  216. package/src/components/UiDialog/UiDialog.vue +16 -0
  217. package/src/components/UiDialog/UiDialogClose.vue +29 -0
  218. package/src/components/UiDialog/UiDialogContent.vue +238 -0
  219. package/src/components/UiDialog/UiDialogFooter.vue +9 -0
  220. package/src/components/UiDialog/UiDialogTrigger.vue +12 -0
  221. package/src/components/UiDialog/index.ts +18 -0
  222. package/src/components/UiDropdown/UiDropdown.vue +48 -0
  223. package/src/components/UiDropdown/UiDropdownContent.vue +72 -0
  224. package/src/components/UiDropdown/UiDropdownItem.vue +75 -0
  225. package/src/components/UiDropdown/UiDropdownSeparator.vue +7 -0
  226. package/src/components/UiDropdown/UiDropdownTrigger.vue +239 -0
  227. package/src/components/UiDropdown/context.ts +9 -0
  228. package/src/components/UiDropdown/index.ts +21 -0
  229. package/src/components/UiEmptyState/UiEmptyState.vue +80 -0
  230. package/src/components/UiFieldWrapper/UiFieldWrapper.vue +81 -0
  231. package/src/components/UiFieldWrapper/index.ts +1 -0
  232. package/src/components/UiForm/UiFormField.types.ts +24 -0
  233. package/src/components/UiForm/UiFormField.vue +66 -0
  234. package/src/components/UiForm/index.ts +3 -0
  235. package/src/components/UiHorizontalSeparator/UiHorizontalSeparator.vue +28 -0
  236. package/src/components/UiInputCheckbox/UiInputCheckbox.vue +481 -0
  237. package/src/components/UiInputCheckbox/index.ts +2 -0
  238. package/src/components/UiInputCheckbox/types.ts +1 -0
  239. package/src/components/UiInputSelect/UiInputSelect.vue +166 -0
  240. package/src/components/UiInputSelect/index.ts +2 -0
  241. package/src/components/UiInputSelect/types.ts +1 -0
  242. package/src/components/UiInputTextarea/UiInputTextarea.vue +219 -0
  243. package/src/components/UiInputTextarea/index.ts +2 -0
  244. package/src/components/UiInputTextarea/types.ts +1 -0
  245. package/src/components/UiLabel/UiLabel.vue +36 -0
  246. package/src/components/UiList/UiList.vue +45 -0
  247. package/src/components/UiListItem/UiListItem.vue +108 -0
  248. package/src/components/UiLoader/UiLoader.vue +45 -0
  249. package/src/components/UiLogo/UiLogo.vue +99 -0
  250. package/src/components/UiLogo/variants/PulseVariant.vue +51 -0
  251. package/src/components/UiLogo/variants/TornadoVariant.vue +147 -0
  252. package/src/components/UiMenu/UiMenu.vue +15 -0
  253. package/src/components/UiMenu/UiMenuContent.vue +25 -0
  254. package/src/components/UiMenu/UiMenuGroup.vue +19 -0
  255. package/src/components/UiMenu/UiMenuItem.vue +18 -0
  256. package/src/components/UiMenu/UiMenuLabel.vue +9 -0
  257. package/src/components/UiMenu/UiMenuSeparator.vue +9 -0
  258. package/src/components/UiMenu/UiMenuSub.vue +15 -0
  259. package/src/components/UiMenu/UiMenuSubContent.vue +23 -0
  260. package/src/components/UiMenu/UiMenuSubTrigger.vue +17 -0
  261. package/src/components/UiMenu/UiMenuTrigger.vue +13 -0
  262. package/src/components/UiMenu/index.ts +10 -0
  263. package/src/components/UiPage/UiPage.vue +201 -0
  264. package/src/components/UiPageHeader/UiPageHeader.vue +128 -0
  265. package/src/components/UiPopover/UiPopover.vue +16 -0
  266. package/src/components/UiPopover/UiPopoverAnchor.vue +12 -0
  267. package/src/components/UiPopover/UiPopoverContent.vue +26 -0
  268. package/src/components/UiPopover/UiPopoverTrigger.vue +19 -0
  269. package/src/components/UiProgress/UiProgress.vue +92 -0
  270. package/src/components/UiProgress/index.ts +2 -0
  271. package/src/components/UiProgress/types.ts +5 -0
  272. package/src/components/UiRoomButton/UiRoomButton.vue +240 -0
  273. package/src/components/UiShell/UiShell.vue +88 -0
  274. package/src/components/UiSideMenu/UiSideMenu.vue +513 -0
  275. package/src/components/UiSideMenu/UiSideMenuBottom.vue +27 -0
  276. package/src/components/UiSideMenu/UiSideMenuItem.vue +102 -0
  277. package/src/components/UiSideMenu/UiSideMenuItemContent.vue +172 -0
  278. package/src/components/UiSideMenu/UiSideMenuTop.vue +29 -0
  279. package/src/components/UiSideMenu/injection.ts +9 -0
  280. package/src/components/UiSideMenu/types.ts +41 -0
  281. package/src/components/UiSideMenu/useLabelHidden.ts +33 -0
  282. package/src/components/UiSideMenu/useSideMenuLayout.ts +12 -0
  283. package/src/components/UiStepper/UiStepper.vue +40 -0
  284. package/src/components/UiStepper/UiStepperDescription.vue +27 -0
  285. package/src/components/UiStepper/UiStepperIndicator.vue +93 -0
  286. package/src/components/UiStepper/UiStepperItem.vue +30 -0
  287. package/src/components/UiStepper/UiStepperSeparator.vue +49 -0
  288. package/src/components/UiStepper/UiStepperTitle.vue +24 -0
  289. package/src/components/UiStepper/index.ts +17 -0
  290. package/src/components/UiTable/UiTable.vue +24 -0
  291. package/src/components/UiTable/UiTableBody.vue +5 -0
  292. package/src/components/UiTable/UiTableCell.vue +26 -0
  293. package/src/components/UiTable/UiTableHeader.vue +17 -0
  294. package/src/components/UiTable/UiTableHeaderCell.vue +19 -0
  295. package/src/components/UiTable/UiTableRow.vue +27 -0
  296. package/src/components/UiTable/index.ts +6 -0
  297. package/src/components/UiTabs/UiTabs.vue +218 -0
  298. package/src/components/UiTabs/index.ts +5 -0
  299. package/src/components/UiTag/UiTag.vue +187 -0
  300. package/src/components/UiTag/index.js +1 -0
  301. package/src/components/UiTextField/UiTextField.vue +370 -0
  302. package/src/components/UiTextField/index.ts +2 -0
  303. package/src/components/UiTextField/types.ts +2 -0
  304. package/src/components/UiTimeline/README.md +169 -0
  305. package/src/components/UiTimeline/UiTimeline.vue +58 -0
  306. package/src/components/UiTimeline/UiTimelineItem.vue +141 -0
  307. package/src/components/UiTimeline/index.ts +2 -0
  308. package/src/components/UiTooltip/UiTooltip.vue +68 -0
  309. package/src/components/UiTooltip/UiTooltipContent.vue +86 -0
  310. package/src/components/UiTooltip/UiTooltipProvider.vue +15 -0
  311. package/src/components/UiTooltip/UiTooltipTrigger.vue +19 -0
  312. package/src/components/UiTooltip/index.js +4 -0
  313. package/src/composables/useButtonStyles.ts +242 -0
  314. package/src/composables/useMobileMenu.ts +57 -0
  315. package/src/composables/useThemeAndModes.ts +225 -0
  316. package/src/constants/index.ts +2 -0
  317. package/src/constants/sizes.ts +2 -0
  318. package/src/constants/themes.ts +34 -0
  319. package/src/css/{body.postcss → body.css} +3 -2
  320. package/src/css/reka-animations.css +209 -0
  321. package/src/css/{transitions.postcss → transitions.css} +12 -5
  322. package/src/global.d.ts +181 -0
  323. package/src/integrations/index.js +1 -0
  324. package/src/layouts/index.js +5 -0
  325. package/src/mixins/DynamicAction.js +5 -3
  326. package/src/primitives.ts +6 -0
  327. package/src/theme.ts +1 -0
  328. package/src/utils/a11y.ts +8 -0
  329. package/src/utils/{breakpoints.js → breakpoints.ts} +1 -0
  330. package/src/utils/clipboard.js +81 -14
  331. package/src/utils/devices.js +0 -3
  332. package/src/utils/index.js +2 -1
  333. package/src/utils/numbers.ts +61 -0
  334. package/src/utils/responsive.types.ts +12 -0
  335. package/src/utils/{slot.js → slot.ts} +18 -1
  336. package/style.js +3 -12
  337. package/theme.d.ts +1 -0
  338. package/.env +0 -1
  339. package/.eslintignore +0 -4
  340. package/.eslintrc.js +0 -49
  341. package/.pkg +0 -11
  342. package/babel.config.js +0 -5
  343. package/build/Dockerfile +0 -31
  344. package/ci/ci.yml +0 -54
  345. package/components-webpack.js +0 -29
  346. package/dist/environment-da321c85.mjs +0 -1656
  347. package/dist/style.css +0 -1
  348. package/plugins.js +0 -17
  349. package/postcss.config.js +0 -1
  350. package/src/components/BaseAutocomplete/BaseAutocomplete.spec.js +0 -506
  351. package/src/components/BaseAutocomplete/BaseAutocomplete.stories.js +0 -184
  352. package/src/components/BaseAutocomplete/BaseAutocomplete.vue +0 -431
  353. package/src/components/BaseBanner/BaseBanner.spec.js +0 -32
  354. package/src/components/BaseBanner/BaseBanner.stories.js +0 -133
  355. package/src/components/BaseBanner/BaseBanner.vue +0 -229
  356. package/src/components/BaseButton/BaseButton.spec.js +0 -98
  357. package/src/components/BaseButton/BaseButton.stories.js +0 -300
  358. package/src/components/BaseButton/BaseButton.vue +0 -193
  359. package/src/components/BaseButton/__snapshots__/BaseButton.spec.js.snap +0 -37
  360. package/src/components/BaseButton/__snapshots__/BaseButton.spec.js.snap.old +0 -31
  361. package/src/components/BaseCheckbox/BaseCheckbox.stories.js +0 -157
  362. package/src/components/BaseCheckbox/BaseCheckbox.vue +0 -180
  363. package/src/components/BaseDropdownMenu/BaseDropdownMenu.stories.js +0 -84
  364. package/src/components/BaseDropdownMenu/BaseDropdownMenu.vue +0 -251
  365. package/src/components/BaseDropdownMenu/BaseDropdownMenuButton.vue +0 -26
  366. package/src/components/BaseDropdownMenu/BaseDropdownMenuDivider.vue +0 -10
  367. package/src/components/BaseDropdownMenu/BaseDropdownMenuItem.vue +0 -206
  368. package/src/components/BaseDropdownMenu/BaseDropdownMenuSearch.vue +0 -49
  369. package/src/components/BaseDropdownMenu/BaseDropdownMenuTitle.vue +0 -26
  370. package/src/components/BaseModal/BaseModal.stories.js +0 -155
  371. package/src/components/BaseModal/BaseModal.vue +0 -187
  372. package/src/components/BaseModal/BaseModalContent.vue +0 -166
  373. package/src/components/BaseModal/BaseModalContentOld.vue +0 -242
  374. package/src/components/BaseRadio/BaseRadio.stories.js +0 -164
  375. package/src/components/BaseRadio/BaseRadio.vue +0 -153
  376. package/src/components/BaseRating/BaseRating.spec.js +0 -46
  377. package/src/components/BaseRating/BaseRating.stories.js +0 -46
  378. package/src/components/BaseRating/BaseRating.vue +0 -119
  379. package/src/components/BaseSelect/BaseSelect.stories.js +0 -177
  380. package/src/components/BaseSelect/BaseSelect.vue +0 -443
  381. package/src/components/BaseSelect/BaseSelectGroup.vue +0 -34
  382. package/src/components/BaseSelect/BaseSelectOption.vue +0 -219
  383. package/src/components/BaseSwitch/BaseSwitch.stories.js +0 -44
  384. package/src/components/BaseSwitch/BaseSwitch.vue +0 -114
  385. package/src/components/BaseTag/BaseTag.stories.js +0 -123
  386. package/src/components/BaseTag/BaseTag.vue +0 -244
  387. package/src/css/button.postcss +0 -363
  388. package/src/css/checkbox-radio.postcss +0 -188
  389. package/src/css/icon.postcss +0 -9
  390. package/src/css/loader.postcss +0 -120
  391. package/src/css/popper.postcss +0 -161
  392. package/src/css/tailwind-utilities.postcss +0 -1
  393. package/src/css/tailwind.postcss +0 -2
  394. package/style-postcss.d.ts +0 -3
  395. package/style-postcss.js +0 -2
  396. package/tailwind.config.base.cjs +0 -88
  397. package/tailwind.config.js +0 -9
  398. package/tsconfig.check.json +0 -13
  399. package/tsconfig.json +0 -66
  400. package/vite.config.js +0 -43
  401. package/vitest.setup.js +0 -26
@@ -0,0 +1,322 @@
1
+ <template>
2
+ <component
3
+ :is="component.is"
4
+ v-bind="component.props"
5
+ :aria-label="!isLink ? labelFinal : undefined"
6
+ class="ui-button group align-center flex justify-center rounded-lg relative transition-all duration-150 focus-indicator-none"
7
+ :class="[
8
+ buttonClasses,
9
+ textClasses,
10
+ borderClasses,
11
+ { 'cursor-pointer': !finalDisabled },
12
+ { 'opacity-50 cursor-not-allowed': finalDisabled }
13
+ ]"
14
+ data-testid="ui-button"
15
+ @click="onClick"
16
+ @mouseenter="$emit('mouseenter')"
17
+ @mouseleave="$emit('mouseleave')"
18
+ >
19
+ <div
20
+ class="absolute h-full top-0 left-0 z-0 rounded-md w-full"
21
+ :class="[bgClasses, focusRingClasses]"
22
+ />
23
+ <div
24
+ class="button-overlay absolute h-full top-0 left-0 z-10 rounded-md w-full"
25
+ :class="overlayClasses"
26
+ />
27
+ <UiTooltip :content="typeof tooltip === 'string' ? tooltip : tooltip?.content">
28
+ <div
29
+ class="button-wrapper flex items-center whitespace-nowrap h-full relative z-20"
30
+ >
31
+ <!-- Loader -->
32
+ <UiLoader
33
+ v-if="loading"
34
+ :size="size"
35
+ :class="{ 'mr-2': hasLabel }"
36
+ />
37
+
38
+ <!-- Content -->
39
+ <template
40
+ v-else-if="showIconLeft"
41
+ >
42
+ <div
43
+ v-if="iconSlot"
44
+ :class="[iconSizeClasses, { 'mr-2': hasLabel }]"
45
+ class="shrink-0"
46
+ >
47
+ <RenderSlot
48
+ :vnodes="iconSlot"
49
+ />
50
+ </div>
51
+ <div
52
+ v-else-if="imageSource"
53
+ :class="[iconSizeClasses, { 'mr-2': hasLabel }]"
54
+ class="shrink-0"
55
+ >
56
+ <img
57
+ :src="imageSource"
58
+ :alt="`${labelFinal} button image`"
59
+ >
60
+ </div>
61
+ <div
62
+ v-else-if="icon"
63
+ :class="[icon, iconSizeClasses, { 'mr-2': hasLabel }]"
64
+ class="shrink-0"
65
+ />
66
+ </template>
67
+ <span
68
+ class="content w-full"
69
+ >
70
+ <RenderSlot
71
+ :vnodes="defaultSlot"
72
+ />
73
+ </span>
74
+ <div
75
+ v-if="iconRight"
76
+ :class="[iconRight, iconSizeClasses, { 'ml-2': hasLabel }]"
77
+ class="shrink-0"
78
+ />
79
+ </div>
80
+ </UiTooltip>
81
+ </component>
82
+ </template>
83
+
84
+ <script lang="ts">
85
+ import { computed, getCurrentInstance, watch } from 'vue'
86
+ import { useSlotsAsComponents, RenderSlot } from '../../utils/slot'
87
+ import { SIZES, type Size } from '../../constants'
88
+ import { useButtonStyles, BUTTON_COLORS, type ButtonVariant, type ButtonColor } from '../../composables/useButtonStyles'
89
+ import UiLoader from '../UiLoader/UiLoader.vue'
90
+ import UiTooltip from '../UiTooltip/UiTooltip.vue'
91
+ import type { RouteLocationRaw } from 'vue-router'
92
+
93
+ export type Variant = ButtonVariant
94
+ const COLORS = BUTTON_COLORS
95
+ export type Color = ButtonColor
96
+
97
+ export default {
98
+ components: {
99
+ RenderSlot,
100
+ UiLoader,
101
+ UiTooltip,
102
+ },
103
+
104
+ props: {
105
+ variant: {
106
+ type: String as () => Variant,
107
+ default: 'cta',
108
+ },
109
+ size: {
110
+ type: String,
111
+ default: 'md',
112
+ validator: (value: Size) => SIZES.includes(value),
113
+ },
114
+ color: {
115
+ type: String as () => Color,
116
+ default: 'primary',
117
+ validator: (value: Color) => COLORS.includes(value),
118
+ },
119
+ disabled: {
120
+ type: Boolean,
121
+ default: false,
122
+ },
123
+ showIconLeft: {
124
+ type: Boolean,
125
+ default: true,
126
+ },
127
+ icon: {
128
+ type: [String, Boolean],
129
+ default: undefined,
130
+ },
131
+ label: {
132
+ type: String,
133
+ default: undefined,
134
+ },
135
+ iconRight: {
136
+ type: [String, Boolean],
137
+ default: undefined,
138
+ },
139
+ loading: {
140
+ type: Boolean,
141
+ default: false,
142
+ },
143
+ imageSource: {
144
+ type: String,
145
+ default: undefined,
146
+ },
147
+ tooltip: {
148
+ type: [String, Object],
149
+ default: undefined,
150
+ },
151
+ type: {
152
+ type: String,
153
+ default: 'button',
154
+ },
155
+ href: {
156
+ type: String,
157
+ default: undefined,
158
+ },
159
+ to: {
160
+ type: Object as () => RouteLocationRaw,
161
+ default: undefined,
162
+ },
163
+ },
164
+
165
+ emits: [
166
+ 'click',
167
+ 'mouseenter',
168
+ 'mouseleave',
169
+ ],
170
+
171
+ // * The script setup syntax would be the better way to have good typing of the props argument.
172
+ setup (props: any) {
173
+ const slots = useSlotsAsComponents()
174
+ const defaultSlot = computed(() => slots.default && slots.default())
175
+ const iconSlot = computed(() => slots.icon && slots.icon())
176
+ const hasLabel = computed<boolean>(() => !!defaultSlot.value)
177
+ const isSquare = computed(() => !hasLabel.value && !defaultSlot.value && (!!props.icon || !!props.iconRight))
178
+
179
+ // Disabled status
180
+ const finalDisabled = computed(() => props.disabled || props.loading)
181
+
182
+ // Can be "<router-link", "<button>" or "<a>"
183
+ const component = computed(() => {
184
+ const isDisabled = finalDisabled.value
185
+
186
+ // Disabled links should render as buttons for accessibility
187
+ if (isDisabled && (props.to || props.href)) {
188
+ return {
189
+ is: 'button',
190
+ props: {
191
+ type: 'button',
192
+ disabled: true,
193
+ },
194
+ }
195
+ }
196
+
197
+ if (props.to) {
198
+ return {
199
+ is: 'router-link',
200
+ props: {
201
+ to: props.to,
202
+ },
203
+ }
204
+ } else if (props.href) {
205
+ return {
206
+ is: 'a',
207
+ props: {
208
+ href: props.href,
209
+ },
210
+ }
211
+ } else {
212
+ return {
213
+ is: 'button',
214
+ props: {
215
+ type: props.type,
216
+ disabled: isDisabled,
217
+ },
218
+ }
219
+ }
220
+ })
221
+
222
+ // Check if component is a link (to apply inline-block) - only when not disabled
223
+ const isLink = computed(() => !finalDisabled.value && (!!props.href || !!props.to))
224
+
225
+ // Icon size classes
226
+ const iconSizeClasses = computed(() => ({
227
+ 'size-3': props.size === 'sm',
228
+ 'size-4': props.size === 'md',
229
+ 'size-5': props.size === 'lg',
230
+ }))
231
+
232
+ // Label value
233
+ const labelFinal = computed(() => {
234
+ // Try to get label from slot or prop
235
+ const explicitLabel = ((defaultSlot.value && typeof defaultSlot.value[0].children === 'string' && defaultSlot.value[0].children) || props.label)?.trim()
236
+ if (explicitLabel) return explicitLabel
237
+
238
+ // Fallback: generate label from icon for icon-only buttons
239
+ if (isSquare.value && props.icon && typeof props.icon === 'string') {
240
+ // Extract readable name from icon class (e.g. "i-ls-settings" -> "settings")
241
+ const iconName = props.icon.replace(/^i-ls-/, '').replace(/-/g, ' ')
242
+ return iconName ? `${iconName} icon` : 'icon'
243
+ }
244
+
245
+ return undefined
246
+ })
247
+
248
+ // Handle click
249
+ const instance = getCurrentInstance()
250
+ function onClick (event: Event) {
251
+ if (finalDisabled.value) {
252
+ event.preventDefault()
253
+ } else {
254
+ instance?.emit('click', event)
255
+ }
256
+ }
257
+
258
+ // Style: Dynamic button classes
259
+ const buttonClasses = computed(() => [
260
+ {
261
+ 'size-8': isSquare.value && props.size === 'sm',
262
+ 'size-10': isSquare.value && props.size === 'md',
263
+ 'size-12': isSquare.value && props.size === 'lg',
264
+ },
265
+ { 'grid place-items-center': isSquare.value },
266
+ {
267
+ 'h-8 text-action-button-sm': props.size === 'sm',
268
+ 'h-10 text-action-button-md': props.size === 'md',
269
+ 'h-12 text-action-button-lg': props.size === 'lg',
270
+ },
271
+ props.size === 'sm' ? 'px-2.5' : props.size === 'lg' ? 'px-4' : 'px-3',
272
+ // Links should be inline-flex to prevent full width while maintaining flex centering
273
+ { 'inline-flex': isLink.value },
274
+ ])
275
+
276
+ // Style: variant × color visual language — shared with `UiDropdownTrigger`
277
+ // via `useButtonStyles` so both stay pixel-identical.
278
+ const {
279
+ bgClass,
280
+ textClass,
281
+ borderClasses,
282
+ overlayClasses,
283
+ } = useButtonStyles({
284
+ variant: () => props.variant,
285
+ color: () => props.color,
286
+ disabled: finalDisabled,
287
+ })
288
+
289
+ const bgClasses = bgClass
290
+ const textClasses = computed(() => textClass.value ? [textClass.value] : [])
291
+
292
+ // Style: Focus ring color
293
+ const focusRingClasses = 'group-focus-visible:ring-2 group-focus-visible:ring-inset group-focus-visible:ring-focus-ring'
294
+
295
+ // Validation: warn if no label or icon provided
296
+ watch(() => !props.label && !props.icon && !props.iconRight && !defaultSlot.value, (isEmpty) => {
297
+ if (isEmpty) {
298
+ console.warn('UiButton: You must provide a label or an icon to the button')
299
+ }
300
+ }, { immediate: true })
301
+
302
+ return {
303
+ component,
304
+ defaultSlot,
305
+ iconSlot,
306
+ hasLabel,
307
+ isLink,
308
+ iconSizeClasses,
309
+ buttonClasses,
310
+ bgClasses,
311
+ focusRingClasses,
312
+ textClasses,
313
+ borderClasses,
314
+ overlayClasses,
315
+ isSquare,
316
+ finalDisabled,
317
+ labelFinal,
318
+ onClick,
319
+ }
320
+ },
321
+ }
322
+ </script>
@@ -0,0 +1,198 @@
1
+ <script setup lang="ts">
2
+ import { ToggleGroupRoot } from 'reka-ui'
3
+ import type { AcceptableValue } from 'reka-ui'
4
+ import { useDebounceFn, useResizeObserver } from '@vueuse/core'
5
+ import { computed, nextTick, onMounted, provide, ref, watch } from 'vue'
6
+ import type { ButtonGroupColor, ButtonGroupSize } from './types'
7
+ import {
8
+ BUTTON_GROUP_COLOR_KEY,
9
+ BUTTON_GROUP_REGISTER_KEY,
10
+ BUTTON_GROUP_SIZE_KEY,
11
+ } from './types'
12
+
13
+ interface UiButtonGroupProps {
14
+ modelValue?: string
15
+ defaultValue?: string
16
+ disabled?: boolean
17
+ size?: ButtonGroupSize
18
+ color?: ButtonGroupColor
19
+ name?: string
20
+ orientation?: 'horizontal' | 'vertical'
21
+ /**
22
+ * When false (default), clicking the selected item is a no-op — matches
23
+ * radio-group semantics where exactly one option is always selected.
24
+ * Set to true to allow clearing the selection by clicking the active item.
25
+ */
26
+ allowDeselect?: boolean
27
+ }
28
+
29
+ const props = withDefaults(defineProps<UiButtonGroupProps>(), {
30
+ size: 'md',
31
+ color: 'neutral',
32
+ orientation: 'horizontal',
33
+ disabled: false,
34
+ allowDeselect: false,
35
+ modelValue: undefined,
36
+ defaultValue: undefined,
37
+ name: undefined,
38
+ })
39
+
40
+ const emit = defineEmits<{
41
+ 'update:modelValue': [value: string | undefined]
42
+ }>()
43
+
44
+ provide(BUTTON_GROUP_SIZE_KEY, computed(() => props.size))
45
+ provide(BUTTON_GROUP_COLOR_KEY, computed(() => props.color))
46
+
47
+ // --- Sliding indicator -----------------------------------------------------
48
+ // Each item registers its DOM node on mount. When the selected value or
49
+ // layout changes, we measure the active item and reposition a single absolute
50
+ // <div> whose transform + width + height transition smoothly.
51
+
52
+ const itemEls = new Map<string, HTMLElement>()
53
+ const rootRef = ref<InstanceType<typeof ToggleGroupRoot> | null>(null)
54
+
55
+ // Shadowed selection state — mirrors modelValue when controlled, falls back
56
+ // to defaultValue/emitted updates when uncontrolled, so the indicator works
57
+ // either way. Undefined is forwarded too, so external form resets that clear
58
+ // v-model correctly hide the indicator.
59
+ const selectedValue = ref<string | undefined>(props.modelValue ?? props.defaultValue)
60
+ watch(() => props.modelValue, (v) => {
61
+ selectedValue.value = v
62
+ })
63
+
64
+ const indicatorStyle = ref<Record<string, string>>({
65
+ transform: 'translate(0px, 0px)',
66
+ width: '0px',
67
+ height: '0px',
68
+ })
69
+ const indicatorVisible = ref(false)
70
+
71
+ function getRootEl (): HTMLElement | null {
72
+ const el = (rootRef.value as unknown as { $el?: unknown })?.$el
73
+ return el instanceof HTMLElement ? el : null
74
+ }
75
+
76
+ function updateIndicator () {
77
+ const rootEl = getRootEl()
78
+ if (!rootEl) return
79
+
80
+ const activeEl = selectedValue.value ? itemEls.get(selectedValue.value) : null
81
+ if (!activeEl) {
82
+ indicatorVisible.value = false
83
+ return
84
+ }
85
+
86
+ const rootRect = rootEl.getBoundingClientRect()
87
+ const itemRect = activeEl.getBoundingClientRect()
88
+ indicatorStyle.value = {
89
+ transform: `translate(${itemRect.left - rootRect.left}px, ${itemRect.top - rootRect.top}px)`,
90
+ width: `${itemRect.width}px`,
91
+ height: `${itemRect.height}px`,
92
+ }
93
+ indicatorVisible.value = true
94
+ }
95
+
96
+ const debouncedUpdate = useDebounceFn(updateIndicator, 100)
97
+
98
+ provide(BUTTON_GROUP_REGISTER_KEY, {
99
+ register (value, el) {
100
+ itemEls.set(value, el)
101
+ updateIndicator()
102
+ },
103
+ unregister (value) {
104
+ itemEls.delete(value)
105
+ },
106
+ })
107
+
108
+ watch([selectedValue, () => props.orientation, () => props.size], async () => {
109
+ await nextTick()
110
+ updateIndicator()
111
+ })
112
+
113
+ onMounted(async () => {
114
+ await nextTick()
115
+ updateIndicator()
116
+ })
117
+
118
+ const resizeTarget = computed(() => getRootEl())
119
+ useResizeObserver(resizeTarget, debouncedUpdate)
120
+
121
+ // --- Classes ---------------------------------------------------------------
122
+
123
+ const sizeClasses = computed(() => {
124
+ switch (props.size) {
125
+ case 'sm': return 'h-8 p-0.5 gap-0.5'
126
+ case 'lg': return 'h-12 p-1 gap-1'
127
+ case 'md':
128
+ default: return 'h-10 p-0.5 gap-1'
129
+ }
130
+ })
131
+
132
+ const RAIL_BG: Record<ButtonGroupColor, string> = {
133
+ 'neutral': 'bg-actions-neutral-idle-alpha-light',
134
+ 'neutral-invert': 'bg-actions-neutral-invert-idle-alpha-light',
135
+ 'primary': 'bg-actions-primary-idle-alpha-light',
136
+ 'success': 'bg-actions-success-idle-alpha-light',
137
+ 'warning': 'bg-actions-warning-idle-alpha-light',
138
+ 'error': 'bg-actions-danger-idle-alpha-light',
139
+ }
140
+
141
+ const INDICATOR_BG: Record<ButtonGroupColor, string> = {
142
+ 'neutral': 'bg-actions-neutral-idle',
143
+ 'neutral-invert': 'bg-actions-neutral-invert-idle',
144
+ 'primary': 'bg-actions-primary-idle',
145
+ 'success': 'bg-actions-success-idle',
146
+ 'warning': 'bg-actions-warning-idle',
147
+ 'error': 'bg-actions-danger-idle',
148
+ }
149
+
150
+ const INDICATOR_RADIUS: Record<ButtonGroupSize, string> = {
151
+ sm: 'rounded-md',
152
+ md: 'rounded-lg',
153
+ lg: 'rounded-lg',
154
+ }
155
+
156
+ const railBgClass = computed(() => RAIL_BG[props.color])
157
+ const indicatorBgClass = computed(() => INDICATOR_BG[props.color])
158
+ const indicatorRadiusClass = computed(() => INDICATOR_RADIUS[props.size])
159
+
160
+ function handleUpdate (value: AcceptableValue | AcceptableValue[]) {
161
+ const next = Array.isArray(value) ? value[0] : value
162
+ const resolved = typeof next === 'string' ? next : undefined
163
+
164
+ // Reka-ui's single-select emits `undefined` when the user clicks the already
165
+ // selected item. Suppress that unless the consumer opts into deselection —
166
+ // driving ToggleGroupRoot from `selectedValue` means the visible state
167
+ // reverts cleanly on the next render.
168
+ if (resolved === undefined && !props.allowDeselect) return
169
+
170
+ selectedValue.value = resolved
171
+ emit('update:modelValue', resolved)
172
+ }
173
+ </script>
174
+
175
+ <template>
176
+ <ToggleGroupRoot
177
+ ref="rootRef"
178
+ :model-value="selectedValue"
179
+ :disabled="disabled"
180
+ :orientation="orientation"
181
+ :name="name"
182
+ :roving-focus="true"
183
+ type="single"
184
+ class="relative inline-flex w-full items-stretch rounded-lg"
185
+ :class="[sizeClasses, railBgClass, { 'flex-col h-auto': orientation === 'vertical' }]"
186
+ @update:model-value="handleUpdate"
187
+ >
188
+ <div
189
+ v-show="indicatorVisible"
190
+ data-testid="button-group-indicator"
191
+ aria-hidden="true"
192
+ class="absolute top-0 left-0 pointer-events-none transition-[transform,width,height] duration-200 ease-out will-change-transform"
193
+ :class="[indicatorBgClass, indicatorRadiusClass]"
194
+ :style="indicatorStyle"
195
+ />
196
+ <slot />
197
+ </ToggleGroupRoot>
198
+ </template>
@@ -0,0 +1,123 @@
1
+ <script setup lang="ts">
2
+ import { ToggleGroupItem } from 'reka-ui'
3
+ import { computed, inject, onBeforeUnmount, onMounted, ref, watch } from 'vue'
4
+ import type { ButtonGroupColor } from './types'
5
+ import {
6
+ BUTTON_GROUP_COLOR_KEY,
7
+ BUTTON_GROUP_REGISTER_KEY,
8
+ BUTTON_GROUP_SIZE_KEY,
9
+ } from './types'
10
+
11
+ interface UiButtonGroupItemProps {
12
+ value: string
13
+ disabled?: boolean
14
+ ariaLabel?: string
15
+ }
16
+
17
+ const props = withDefaults(defineProps<UiButtonGroupItemProps>(), {
18
+ disabled: false,
19
+ ariaLabel: undefined,
20
+ })
21
+
22
+ const size = inject(BUTTON_GROUP_SIZE_KEY, computed(() => 'md' as const))
23
+ const color = inject(BUTTON_GROUP_COLOR_KEY, computed<ButtonGroupColor>(() => 'neutral'))
24
+ const registry = inject(BUTTON_GROUP_REGISTER_KEY, null)
25
+
26
+ const itemRef = ref<InstanceType<typeof ToggleGroupItem> | null>(null)
27
+
28
+ function resolveEl (): HTMLElement | null {
29
+ const el = (itemRef.value as unknown as { $el?: unknown })?.$el
30
+ return el instanceof HTMLElement ? el : null
31
+ }
32
+
33
+ onMounted(() => {
34
+ const el = resolveEl()
35
+ if (el && registry) registry.register(props.value, el)
36
+ })
37
+
38
+ // Re-register under the new key if the `value` prop changes dynamically
39
+ // (e.g. iterating over a reactive list), so the indicator keeps tracking
40
+ // this item instead of looking for a stale key.
41
+ watch(() => props.value, (next, prev) => {
42
+ if (next === prev || !registry) return
43
+ registry.unregister(prev)
44
+ const el = resolveEl()
45
+ if (el) registry.register(next, el)
46
+ })
47
+
48
+ onBeforeUnmount(() => {
49
+ registry?.unregister(props.value)
50
+ })
51
+
52
+ // Vertical padding is sized so the item content box matches the rail's inner height
53
+ // (rail height − rail padding) in horizontal mode, and drives height in vertical mode.
54
+ const sizeClasses = computed(() => {
55
+ switch (size.value) {
56
+ case 'sm': return 'px-2.5 py-1.5 gap-1 rounded-md text-action-button-sm'
57
+ case 'lg': return 'px-6 py-2.5 gap-2 rounded-lg text-action-button-lg'
58
+ case 'md':
59
+ default: return 'px-4 py-2.5 gap-1.5 rounded-lg text-action-button-md'
60
+ }
61
+ })
62
+
63
+ // Per-color state classes. The selected fill is drawn by the parent's sliding
64
+ // indicator <div>, so items only set text color per state. Hover bg/text apply
65
+ // only to unselected items (data-[state=off]) so the hover tint never stacks
66
+ // on top of the indicator.
67
+ const COLOR_CLASSES: Record<ButtonGroupColor, string> = {
68
+ 'neutral': [
69
+ 'text-actions-neutral-idle-alpha-strong',
70
+ 'data-[state=off]:hover:bg-actions-neutral-hover-overlay',
71
+ 'data-[state=off]:hover:text-actions-neutral-idle',
72
+ 'data-[state=on]:text-actions-neutral-invert-idle',
73
+ ].join(' '),
74
+ 'neutral-invert': [
75
+ 'text-actions-neutral-invert-idle-alpha-strong',
76
+ 'data-[state=off]:hover:bg-actions-neutral-invert-hover-overlay',
77
+ 'data-[state=off]:hover:text-actions-neutral-invert-idle',
78
+ 'data-[state=on]:text-actions-neutral-idle',
79
+ ].join(' '),
80
+ 'primary': [
81
+ 'text-actions-primary-idle-alpha-strong',
82
+ 'data-[state=off]:hover:bg-actions-primary-hover-overlay',
83
+ 'data-[state=off]:hover:text-actions-primary-idle',
84
+ 'data-[state=on]:text-actions-neutral-invert-idle',
85
+ ].join(' '),
86
+ 'success': [
87
+ 'text-actions-success-idle-alpha-strong',
88
+ 'data-[state=off]:hover:bg-actions-success-hover-overlay',
89
+ 'data-[state=off]:hover:text-actions-success-idle',
90
+ 'data-[state=on]:text-actions-neutral-invert-idle',
91
+ ].join(' '),
92
+ 'warning': [
93
+ 'text-actions-warning-idle-alpha-strong',
94
+ 'data-[state=off]:hover:bg-actions-warning-hover-overlay',
95
+ 'data-[state=off]:hover:text-actions-warning-idle',
96
+ 'data-[state=on]:text-actions-neutral-invert-idle',
97
+ ].join(' '),
98
+ 'error': [
99
+ 'text-actions-danger-idle-alpha-strong',
100
+ 'data-[state=off]:hover:bg-actions-danger-hover-overlay',
101
+ 'data-[state=off]:hover:text-actions-danger-idle',
102
+ 'data-[state=on]:text-actions-neutral-invert-idle',
103
+ ].join(' '),
104
+ }
105
+
106
+ const colorClasses = computed(() => COLOR_CLASSES[color.value])
107
+ </script>
108
+
109
+ <template>
110
+ <ToggleGroupItem
111
+ ref="itemRef"
112
+ :value="value"
113
+ :disabled="disabled"
114
+ :aria-label="ariaLabel"
115
+ class="relative z-10 flex-1 inline-flex items-center justify-center transition-colors cursor-pointer outline-none
116
+ focus-visible:ring-2 focus-visible:ring-inset focus-visible:ring-focus-ring
117
+ data-[disabled]:opacity-50 data-[disabled]:cursor-not-allowed
118
+ data-[state=off]:data-[disabled]:hover:bg-transparent"
119
+ :class="[sizeClasses, colorClasses]"
120
+ >
121
+ <slot />
122
+ </ToggleGroupItem>
123
+ </template>
@@ -0,0 +1,3 @@
1
+ export { default as UiButtonGroup } from './UiButtonGroup.vue'
2
+ export { default as UiButtonGroupItem } from './UiButtonGroupItem.vue'
3
+ export type { ButtonGroupColor, ButtonGroupSize } from './types'
@@ -0,0 +1,24 @@
1
+ import type { ComputedRef, InjectionKey } from 'vue'
2
+
3
+ export type ButtonGroupSize = 'sm' | 'md' | 'lg'
4
+ export type ButtonGroupColor =
5
+ | 'neutral'
6
+ | 'neutral-invert'
7
+ | 'primary'
8
+ | 'success'
9
+ | 'warning'
10
+ | 'error'
11
+
12
+ export interface ButtonGroupRegister {
13
+ register(value: string, el: HTMLElement): void
14
+ unregister(value: string): void
15
+ }
16
+
17
+ export const BUTTON_GROUP_SIZE_KEY: InjectionKey<ComputedRef<ButtonGroupSize>> =
18
+ Symbol('ui-button-group-size')
19
+
20
+ export const BUTTON_GROUP_COLOR_KEY: InjectionKey<ComputedRef<ButtonGroupColor>> =
21
+ Symbol('ui-button-group-color')
22
+
23
+ export const BUTTON_GROUP_REGISTER_KEY: InjectionKey<ButtonGroupRegister> =
24
+ Symbol('ui-button-group-register')