@refraction-ui/astro 0.4.2 → 0.4.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 (334) hide show
  1. package/dist/accordion/index.ts +1 -0
  2. package/dist/ai/ai-manager.ts +121 -0
  3. package/dist/ai/index.ts +23 -0
  4. package/dist/ai/mock-providers.ts +68 -0
  5. package/dist/ai/sanitizer.ts +174 -0
  6. package/dist/ai/tts-manager.ts +80 -0
  7. package/dist/ai/types.ts +72 -0
  8. package/dist/animated-text/animated-text.styles.ts +28 -0
  9. package/dist/animated-text/animated-text.ts +83 -0
  10. package/dist/animated-text/index.ts +15 -0
  11. package/dist/app-shell/app-shell.ts +252 -0
  12. package/dist/app-shell/auth-shell.ts +84 -0
  13. package/dist/app-shell/index.ts +22 -0
  14. package/dist/app-shell/page-shell.ts +125 -0
  15. package/dist/astro-accordion/Button.astro +1 -1
  16. package/dist/astro-ai/index.ts +1 -1
  17. package/dist/astro-animated-text/AnimatedText.astro +1 -1
  18. package/dist/astro-animated-text/TypewriterText.astro +1 -1
  19. package/dist/astro-app-shell/AppShell.astro +1 -1
  20. package/dist/astro-app-shell/AuthShell.astro +1 -1
  21. package/dist/astro-app-shell/AuthShellCard.astro +1 -1
  22. package/dist/astro-app-shell/PageShell.astro +1 -1
  23. package/dist/astro-app-shell/PageShellSection.astro +1 -1
  24. package/dist/astro-app-shell/index.ts +1 -1
  25. package/dist/astro-auth/index.ts +2 -2
  26. package/dist/astro-avatar/Avatar.astro +1 -1
  27. package/dist/astro-avatar/AvatarFallback.astro +1 -1
  28. package/dist/astro-avatar/AvatarImage.astro +1 -1
  29. package/dist/astro-avatar-group/AvatarGroup.astro +1 -1
  30. package/dist/astro-badge/Badge.astro +1 -1
  31. package/dist/astro-bottom-nav/BottomNav.astro +1 -1
  32. package/dist/astro-breadcrumbs/Breadcrumbs.astro +1 -1
  33. package/dist/astro-button/Button.astro +1 -1
  34. package/dist/astro-calendar/Calendar.astro +1 -1
  35. package/dist/astro-card/Card.astro +1 -1
  36. package/dist/astro-card/CardContent.astro +1 -1
  37. package/dist/astro-card/CardDescription.astro +1 -1
  38. package/dist/astro-card/CardFooter.astro +1 -1
  39. package/dist/astro-card/CardHeader.astro +1 -1
  40. package/dist/astro-card/CardTitle.astro +1 -1
  41. package/dist/astro-card-grid/CardGrid.astro +1 -1
  42. package/dist/astro-carousel/Button.astro +1 -1
  43. package/dist/astro-charts/Bars.astro +1 -1
  44. package/dist/astro-charts/Chart.astro +1 -1
  45. package/dist/astro-charts/Circles.astro +1 -1
  46. package/dist/astro-charts/Histogram.astro +1 -1
  47. package/dist/astro-charts/Line.astro +1 -1
  48. package/dist/astro-charts/PieChart.astro +1 -1
  49. package/dist/astro-charts/ScatterPlot.astro +1 -1
  50. package/dist/astro-charts/index.ts +1 -1
  51. package/dist/astro-checkbox/Checkbox.astro +1 -1
  52. package/dist/astro-code-editor/CodeEditor.astro +1 -1
  53. package/dist/astro-collapsible/Collapsible.astro +1 -1
  54. package/dist/astro-collapsible/CollapsibleContent.astro +1 -1
  55. package/dist/astro-command/Command.astro +1 -1
  56. package/dist/astro-command/CommandGroup.astro +1 -1
  57. package/dist/astro-command/CommandInput.astro +1 -1
  58. package/dist/astro-command/CommandItem.astro +1 -1
  59. package/dist/astro-command-input/CommandInput.astro +1 -1
  60. package/dist/astro-content-protection/ContentProtection.astro +1 -1
  61. package/dist/astro-data-table/DataTable.astro +1 -1
  62. package/dist/astro-date-picker/DatePicker.astro +1 -1
  63. package/dist/astro-device-frame/DeviceFrame.astro +1 -1
  64. package/dist/astro-dialog/DialogContent.astro +1 -1
  65. package/dist/astro-dialog/DialogOverlay.astro +1 -1
  66. package/dist/astro-diff-viewer/DiffViewer.astro +1 -1
  67. package/dist/astro-dropdown-menu/DropdownMenuContent.astro +1 -1
  68. package/dist/astro-dropdown-menu/DropdownMenuItem.astro +1 -1
  69. package/dist/astro-emoji-picker/EmojiPicker.astro +1 -1
  70. package/dist/astro-feedback-dialog/FeedbackDialog.astro +1 -1
  71. package/dist/astro-file-upload/FileUpload.astro +1 -1
  72. package/dist/astro-footer/Footer.astro +1 -1
  73. package/dist/astro-inline-editor/InlineEditor.astro +1 -1
  74. package/dist/astro-input/Input.astro +1 -1
  75. package/dist/astro-input-group/InputGroup.astro +1 -1
  76. package/dist/astro-input-group/InputGroupAddon.astro +1 -1
  77. package/dist/astro-input-group/InputGroupButton.astro +1 -1
  78. package/dist/astro-install-prompt/InstallPrompt.astro +1 -1
  79. package/dist/astro-keyboard-shortcut/ShortcutBadge.astro +1 -1
  80. package/dist/astro-language-selector/LanguageSelector.astro +1 -1
  81. package/dist/astro-link-card/LinkCard.astro +1 -1
  82. package/dist/astro-markdown-renderer/MarkdownRenderer.astro +1 -1
  83. package/dist/astro-mobile-nav/MobileNav.astro +1 -1
  84. package/dist/astro-mobile-nav/MobileNavLink.astro +1 -1
  85. package/dist/astro-mobile-nav/MobileNavTrigger.astro +1 -1
  86. package/dist/astro-navbar/Navbar.astro +1 -1
  87. package/dist/astro-otp-input/OtpInput.astro +1 -1
  88. package/dist/astro-payment/Payment.astro +1 -1
  89. package/dist/astro-popover/PopoverContent.astro +1 -1
  90. package/dist/astro-presence-indicator/PresenceIndicator.astro +1 -1
  91. package/dist/astro-progress-display/BadgeDisplay.astro +1 -1
  92. package/dist/astro-progress-display/ProgressBar.astro +1 -1
  93. package/dist/astro-progress-display/StatsGrid.astro +1 -1
  94. package/dist/astro-radio/RadioGroup.astro +1 -1
  95. package/dist/astro-radio/RadioItem.astro +1 -1
  96. package/dist/astro-reaction-bar/ReactionBar.astro +1 -1
  97. package/dist/astro-resizable-layout/ResizableDivider.astro +1 -1
  98. package/dist/astro-resizable-layout/ResizableLayout.astro +1 -1
  99. package/dist/astro-resizable-layout/ResizablePane.astro +1 -1
  100. package/dist/astro-resizable-layout/index.ts +1 -1
  101. package/dist/astro-rich-editor/index.ts +2 -2
  102. package/dist/astro-search-bar/SearchBar.astro +1 -1
  103. package/dist/astro-search-bar/SearchResults.astro +1 -1
  104. package/dist/astro-select/Select.astro +1 -1
  105. package/dist/astro-select/SelectContent.astro +1 -1
  106. package/dist/astro-select/SelectItem.astro +1 -1
  107. package/dist/astro-select/SelectTrigger.astro +1 -1
  108. package/dist/astro-sidebar/Sidebar.astro +1 -1
  109. package/dist/astro-skeleton/Skeleton.astro +1 -1
  110. package/dist/astro-slide-viewer/SlideViewer.astro +1 -1
  111. package/dist/astro-status-indicator/StatusIndicator.astro +1 -1
  112. package/dist/astro-switch/Switch.astro +1 -1
  113. package/dist/astro-table-of-contents/TableOfContents.astro +1 -1
  114. package/dist/astro-tabs/Tabs.astro +1 -1
  115. package/dist/astro-tabs/TabsList.astro +1 -1
  116. package/dist/astro-tabs/TabsTrigger.astro +1 -1
  117. package/dist/astro-textarea/Textarea.astro +1 -1
  118. package/dist/astro-theme/ThemeScript.astro +1 -1
  119. package/dist/astro-thread-view/ThreadView.astro +1 -1
  120. package/dist/astro-toast/Toast.astro +1 -1
  121. package/dist/astro-tooltip/TooltipContent.astro +1 -1
  122. package/dist/astro-version-selector/VersionSelector.astro +1 -1
  123. package/dist/astro-video-player/VideoPlayer.astro +1 -1
  124. package/dist/auth/adapters/mock.ts +74 -0
  125. package/dist/auth/auth-machine.ts +120 -0
  126. package/dist/auth/index.ts +22 -0
  127. package/dist/auth/rbac.ts +44 -0
  128. package/dist/auth/types.ts +44 -0
  129. package/dist/avatar/avatar.styles.ts +47 -0
  130. package/dist/avatar/avatar.ts +73 -0
  131. package/dist/avatar/index.ts +15 -0
  132. package/dist/avatar-group/avatar-group.styles.ts +63 -0
  133. package/dist/avatar-group/avatar-group.ts +106 -0
  134. package/dist/avatar-group/index.ts +18 -0
  135. package/dist/badge/badge.styles.ts +24 -0
  136. package/dist/badge/badge.ts +48 -0
  137. package/dist/badge/index.ts +10 -0
  138. package/dist/bottom-nav/bottom-nav.styles.ts +18 -0
  139. package/dist/bottom-nav/bottom-nav.ts +33 -0
  140. package/dist/bottom-nav/index.ts +2 -0
  141. package/dist/breadcrumbs/breadcrumbs.styles.ts +20 -0
  142. package/dist/breadcrumbs/breadcrumbs.ts +72 -0
  143. package/dist/breadcrumbs/index.ts +8 -0
  144. package/dist/button/button.styles.ts +38 -0
  145. package/dist/button/button.ts +64 -0
  146. package/dist/button/index.ts +10 -0
  147. package/dist/calendar/calendar.styles.ts +21 -0
  148. package/dist/calendar/calendar.ts +202 -0
  149. package/dist/calendar/index.ts +9 -0
  150. package/dist/callout/callout.ts +1 -0
  151. package/dist/callout/index.ts +1 -0
  152. package/dist/card/card.styles.ts +55 -0
  153. package/dist/card/card.ts +45 -0
  154. package/dist/card/index.ts +20 -0
  155. package/dist/card-grid/card-grid.ts +9 -0
  156. package/dist/card-grid/index.ts +1 -0
  157. package/dist/carousel/index.ts +1 -0
  158. package/dist/charts/axis.ts +50 -0
  159. package/dist/charts/chart.ts +73 -0
  160. package/dist/charts/colorblind.ts +100 -0
  161. package/dist/charts/data.ts +72 -0
  162. package/dist/charts/geometry.ts +54 -0
  163. package/dist/charts/index.ts +61 -0
  164. package/dist/charts/scales.ts +151 -0
  165. package/dist/checkbox/checkbox.styles.ts +33 -0
  166. package/dist/checkbox/checkbox.ts +73 -0
  167. package/dist/checkbox/index.ts +10 -0
  168. package/dist/code-block/code-block.ts +1 -0
  169. package/dist/code-block/index.ts +1 -0
  170. package/dist/code-editor/code-editor.styles.ts +32 -0
  171. package/dist/code-editor/code-editor.ts +140 -0
  172. package/dist/code-editor/index.ts +9 -0
  173. package/dist/collapsible/collapsible.styles.ts +14 -0
  174. package/dist/collapsible/collapsible.ts +93 -0
  175. package/dist/collapsible/index.ts +7 -0
  176. package/dist/command/command.styles.ts +27 -0
  177. package/dist/command/command.ts +179 -0
  178. package/dist/command/index.ts +14 -0
  179. package/dist/command-input/command-input.ts +176 -0
  180. package/dist/command-input/index.ts +1 -0
  181. package/dist/content-protection/content-protection.styles.ts +9 -0
  182. package/dist/content-protection/content-protection.ts +68 -0
  183. package/dist/content-protection/index.ts +8 -0
  184. package/dist/data-table/data-table.styles.ts +55 -0
  185. package/dist/data-table/data-table.ts +183 -0
  186. package/dist/data-table/index.ts +15 -0
  187. package/dist/date-picker/date-picker.styles.ts +31 -0
  188. package/dist/date-picker/date-picker.ts +333 -0
  189. package/dist/date-picker/index.ts +18 -0
  190. package/dist/device-frame/device-frame.styles.ts +21 -0
  191. package/dist/device-frame/device-frame.ts +112 -0
  192. package/dist/device-frame/index.ts +10 -0
  193. package/dist/dialog/dialog.styles.ts +8 -0
  194. package/dist/dialog/dialog.ts +133 -0
  195. package/dist/dialog/index.ts +8 -0
  196. package/dist/diff-viewer/diff-viewer.styles.ts +124 -0
  197. package/dist/diff-viewer/diff-viewer.ts +255 -0
  198. package/dist/diff-viewer/index.ts +20 -0
  199. package/dist/dropdown-menu/dropdown-menu.styles.ts +9 -0
  200. package/dist/dropdown-menu/dropdown-menu.ts +139 -0
  201. package/dist/dropdown-menu/index.ts +9 -0
  202. package/dist/emoji-picker/emoji-data.ts +282 -0
  203. package/dist/emoji-picker/emoji-picker.styles.ts +32 -0
  204. package/dist/emoji-picker/emoji-picker.ts +165 -0
  205. package/dist/emoji-picker/index.ts +25 -0
  206. package/dist/feedback-dialog/feedback-dialog.styles.ts +15 -0
  207. package/dist/feedback-dialog/feedback-dialog.ts +147 -0
  208. package/dist/feedback-dialog/index.ts +11 -0
  209. package/dist/file-upload/file-upload.styles.ts +30 -0
  210. package/dist/file-upload/file-upload.ts +260 -0
  211. package/dist/file-upload/index.ts +19 -0
  212. package/dist/footer/footer.styles.ts +5 -0
  213. package/dist/footer/footer.ts +32 -0
  214. package/dist/footer/index.ts +9 -0
  215. package/dist/index.ts +1 -1
  216. package/dist/inline-editor/index.ts +13 -0
  217. package/dist/inline-editor/inline-editor.styles.ts +42 -0
  218. package/dist/inline-editor/inline-editor.ts +96 -0
  219. package/dist/input/index.ts +9 -0
  220. package/dist/input/input.styles.ts +15 -0
  221. package/dist/input/input.ts +84 -0
  222. package/dist/input-group/index.ts +13 -0
  223. package/dist/input-group/input-group.styles.ts +50 -0
  224. package/dist/input-group/input-group.ts +44 -0
  225. package/dist/install-prompt/index.ts +9 -0
  226. package/dist/install-prompt/install-prompt.styles.ts +5 -0
  227. package/dist/install-prompt/install-prompt.ts +68 -0
  228. package/dist/keyboard-shortcut/index.ts +12 -0
  229. package/dist/keyboard-shortcut/keyboard-shortcut.styles.ts +8 -0
  230. package/dist/keyboard-shortcut/keyboard-shortcut.ts +153 -0
  231. package/dist/language-selector/index.ts +8 -0
  232. package/dist/language-selector/language-selector.styles.ts +28 -0
  233. package/dist/language-selector/language-selector.ts +149 -0
  234. package/dist/link-card/index.ts +1 -0
  235. package/dist/link-card/link-card.ts +9 -0
  236. package/dist/markdown-renderer/index.ts +8 -0
  237. package/dist/markdown-renderer/markdown-renderer.styles.ts +31 -0
  238. package/dist/markdown-renderer/markdown-renderer.ts +251 -0
  239. package/dist/mobile-nav/index.ts +14 -0
  240. package/dist/mobile-nav/mobile-nav.styles.ts +39 -0
  241. package/dist/mobile-nav/mobile-nav.ts +74 -0
  242. package/dist/navbar/index.ts +9 -0
  243. package/dist/navbar/navbar.styles.ts +29 -0
  244. package/dist/navbar/navbar.ts +39 -0
  245. package/dist/otp-input/index.ts +13 -0
  246. package/dist/otp-input/otp-input.styles.ts +51 -0
  247. package/dist/otp-input/otp-input.ts +198 -0
  248. package/dist/pagination/index.ts +1 -0
  249. package/dist/payment/index.ts +1 -0
  250. package/dist/payment/payment.ts +16 -0
  251. package/dist/popover/index.ts +7 -0
  252. package/dist/popover/popover.styles.ts +16 -0
  253. package/dist/popover/popover.ts +89 -0
  254. package/dist/presence-indicator/index.ts +14 -0
  255. package/dist/presence-indicator/presence-indicator.styles.ts +29 -0
  256. package/dist/presence-indicator/presence-indicator.ts +63 -0
  257. package/dist/progress-display/index.ts +15 -0
  258. package/dist/progress-display/progress-display.styles.ts +72 -0
  259. package/dist/progress-display/progress-display.ts +60 -0
  260. package/dist/radio/index.ts +8 -0
  261. package/dist/radio/radio.styles.ts +34 -0
  262. package/dist/radio/radio.ts +70 -0
  263. package/dist/reaction-bar/index.ts +14 -0
  264. package/dist/reaction-bar/reaction-bar.styles.ts +23 -0
  265. package/dist/reaction-bar/reaction-bar.ts +87 -0
  266. package/dist/resizable-layout/index.ts +12 -0
  267. package/dist/resizable-layout/resizable-layout.styles.ts +50 -0
  268. package/dist/resizable-layout/resizable-layout.ts +139 -0
  269. package/dist/rich-editor/editor.ts +342 -0
  270. package/dist/rich-editor/emoji.ts +175 -0
  271. package/dist/rich-editor/history.ts +79 -0
  272. package/dist/rich-editor/index.ts +106 -0
  273. package/dist/rich-editor/markdown-shortcuts.ts +248 -0
  274. package/dist/rich-editor/mentions.ts +162 -0
  275. package/dist/rich-editor/model.ts +206 -0
  276. package/dist/rich-editor/operations.ts +772 -0
  277. package/dist/rich-editor/selection.ts +157 -0
  278. package/dist/rich-editor/serialization.ts +711 -0
  279. package/dist/rich-editor/slash-commands.ts +212 -0
  280. package/dist/search-bar/index.ts +7 -0
  281. package/dist/search-bar/search-bar.styles.ts +29 -0
  282. package/dist/search-bar/search-bar.ts +130 -0
  283. package/dist/select/index.ts +13 -0
  284. package/dist/select/select.styles.ts +52 -0
  285. package/dist/select/select.ts +152 -0
  286. package/dist/sidebar/index.ts +9 -0
  287. package/dist/sidebar/sidebar.styles.ts +27 -0
  288. package/dist/sidebar/sidebar.ts +59 -0
  289. package/dist/skeleton/index.ts +8 -0
  290. package/dist/skeleton/skeleton.styles.ts +16 -0
  291. package/dist/skeleton/skeleton.ts +39 -0
  292. package/dist/skip-to-content/index.ts +1 -0
  293. package/dist/skip-to-content/skip-to-content.ts +1 -0
  294. package/dist/slide-viewer/index.ts +16 -0
  295. package/dist/slide-viewer/slide-viewer.styles.ts +57 -0
  296. package/dist/slide-viewer/slide-viewer.ts +152 -0
  297. package/dist/slider/index.ts +1 -0
  298. package/dist/slider/slider.ts +2 -0
  299. package/dist/status-indicator/index.ts +15 -0
  300. package/dist/status-indicator/status-indicator.styles.ts +41 -0
  301. package/dist/status-indicator/status-indicator.ts +66 -0
  302. package/dist/steps/index.ts +1 -0
  303. package/dist/steps/steps.ts +1 -0
  304. package/dist/switch/index.ts +7 -0
  305. package/dist/switch/switch.styles.ts +55 -0
  306. package/dist/switch/switch.ts +63 -0
  307. package/dist/table-of-contents/index.ts +1 -0
  308. package/dist/table-of-contents/table-of-contents.ts +37 -0
  309. package/dist/tabs/index.ts +8 -0
  310. package/dist/tabs/tabs.styles.ts +9 -0
  311. package/dist/tabs/tabs.ts +133 -0
  312. package/dist/textarea/index.ts +7 -0
  313. package/dist/textarea/textarea.styles.ts +15 -0
  314. package/dist/textarea/textarea.ts +59 -0
  315. package/dist/theme/dom-adapters.ts +60 -0
  316. package/dist/theme/index.ts +18 -0
  317. package/dist/theme/theme-machine.ts +130 -0
  318. package/dist/theme/theme-script.ts +18 -0
  319. package/dist/thread-view/index.ts +26 -0
  320. package/dist/thread-view/thread-view.styles.ts +35 -0
  321. package/dist/thread-view/thread-view.ts +176 -0
  322. package/dist/toast/index.ts +13 -0
  323. package/dist/toast/toast.styles.ts +19 -0
  324. package/dist/toast/toast.ts +203 -0
  325. package/dist/tooltip/index.ts +7 -0
  326. package/dist/tooltip/tooltip.styles.ts +16 -0
  327. package/dist/tooltip/tooltip.ts +109 -0
  328. package/dist/version-selector/index.ts +12 -0
  329. package/dist/version-selector/version-selector.styles.ts +41 -0
  330. package/dist/version-selector/version-selector.ts +136 -0
  331. package/dist/video-player/index.ts +12 -0
  332. package/dist/video-player/video-player.styles.ts +42 -0
  333. package/dist/video-player/video-player.ts +100 -0
  334. package/package.json +1 -1
@@ -0,0 +1,63 @@
1
+ import { cva } from '../shared/index.ts'
2
+
3
+ export const avatarGroupStyles =
4
+ 'flex items-center -space-x-2'
5
+
6
+ export const avatarVariants = cva({
7
+ base: 'relative inline-flex items-center justify-center rounded-full border-2 border-background bg-muted text-muted-foreground font-medium overflow-hidden ring-2 ring-background',
8
+ variants: {
9
+ size: {
10
+ xs: 'h-6 w-6 text-[10px]',
11
+ sm: 'h-8 w-8 text-xs',
12
+ md: 'h-10 w-10 text-sm',
13
+ lg: 'h-12 w-12 text-base',
14
+ xl: 'h-16 w-16 text-xl',
15
+ },
16
+ },
17
+ defaultVariants: {
18
+ size: 'md',
19
+ },
20
+ })
21
+
22
+ export const avatarOverflowBadgeVariants = cva({
23
+ base: 'relative inline-flex items-center justify-center rounded-full border-2 border-background bg-muted text-muted-foreground font-medium ring-2 ring-background',
24
+ variants: {
25
+ size: {
26
+ xs: 'h-6 w-6 text-[10px]',
27
+ sm: 'h-8 w-8 text-xs',
28
+ md: 'h-10 w-10 text-sm',
29
+ lg: 'h-12 w-12 text-base',
30
+ xl: 'h-16 w-16 text-xl',
31
+ },
32
+ },
33
+ defaultVariants: {
34
+ size: 'md',
35
+ },
36
+ })
37
+
38
+ export const avatarImageStyles =
39
+ 'h-full w-full object-cover'
40
+
41
+ export const avatarPresenceDotVariants = cva({
42
+ base: 'absolute bottom-0 right-0 rounded-full border-2 border-background',
43
+ variants: {
44
+ size: {
45
+ xs: 'h-2 w-2',
46
+ sm: 'h-2.5 w-2.5',
47
+ md: 'h-3 w-3',
48
+ lg: 'h-3.5 w-3.5',
49
+ xl: 'h-4 w-4',
50
+ },
51
+ status: {
52
+ online: 'bg-green-500',
53
+ offline: 'bg-gray-400',
54
+ away: 'bg-yellow-500',
55
+ busy: 'bg-red-500',
56
+ dnd: 'bg-red-500',
57
+ },
58
+ },
59
+ defaultVariants: {
60
+ size: 'md',
61
+ status: 'offline',
62
+ },
63
+ })
@@ -0,0 +1,106 @@
1
+ import type { AccessibilityProps } from '../shared/index.ts'
2
+ import { generateId } from '../shared/index.ts'
3
+
4
+ export type AvatarSize = 'xs' | 'sm' | 'md' | 'lg' | 'xl'
5
+ export type PresenceStatus = 'online' | 'offline' | 'away' | 'busy' | 'dnd'
6
+
7
+ export interface AvatarUser {
8
+ /** Unique identifier */
9
+ id: string
10
+ /** Display name */
11
+ name: string
12
+ /** Avatar image URL */
13
+ src?: string
14
+ /** Online presence status */
15
+ status?: PresenceStatus
16
+ }
17
+
18
+ export interface AvatarGroupProps {
19
+ /** Array of users to display */
20
+ users: AvatarUser[]
21
+ /** Maximum number of visible avatars */
22
+ max?: number
23
+ /** Avatar size */
24
+ size?: AvatarSize
25
+ }
26
+
27
+ export interface AvatarGroupAPI {
28
+ /** Users that are visible (within max limit) */
29
+ visibleUsers: AvatarUser[]
30
+ /** Number of overflow users */
31
+ overflowCount: number
32
+ /** All overflow users (for tooltip/popup) */
33
+ overflowUsers: AvatarUser[]
34
+ /** ARIA props for the group container */
35
+ ariaProps: Partial<AccessibilityProps> & Record<string, unknown>
36
+ /** Get ARIA props for an individual avatar */
37
+ getAvatarAriaProps(user: AvatarUser): Record<string, unknown>
38
+ /** Get initials from a user's name */
39
+ getInitials(name: string): string
40
+ /** Get the overflow badge ARIA props */
41
+ overflowBadgeProps: Record<string, unknown>
42
+ /** Generated IDs */
43
+ ids: {
44
+ group: string
45
+ label: string
46
+ }
47
+ }
48
+
49
+ export const AVATAR_SIZES: Record<AvatarSize, { width: number; fontSize: number }> = {
50
+ xs: { width: 24, fontSize: 10 },
51
+ sm: { width: 32, fontSize: 12 },
52
+ md: { width: 40, fontSize: 14 },
53
+ lg: { width: 48, fontSize: 16 },
54
+ xl: { width: 64, fontSize: 20 },
55
+ }
56
+
57
+ export function getInitials(name: string): string {
58
+ const parts = name.trim().split(/\s+/)
59
+ if (parts.length === 0) return ''
60
+ if (parts.length === 1) return parts[0].charAt(0).toUpperCase()
61
+ return (parts[0].charAt(0) + parts[parts.length - 1].charAt(0)).toUpperCase()
62
+ }
63
+
64
+ export function createAvatarGroup(props: AvatarGroupProps): AvatarGroupAPI {
65
+ const { users, max, size = 'md' } = props
66
+
67
+ const visibleUsers = max && max > 0 ? users.slice(0, max) : users
68
+ const overflowUsers = max && max > 0 ? users.slice(max) : []
69
+ const overflowCount = overflowUsers.length
70
+
71
+ const groupId = generateId('rfr-avatar-group')
72
+ const labelId = generateId('rfr-avatar-group-label')
73
+
74
+ const ariaProps: Partial<AccessibilityProps> & Record<string, unknown> = {
75
+ role: 'group',
76
+ 'aria-label': `${users.length} users`,
77
+ id: groupId,
78
+ }
79
+
80
+ function getAvatarAriaProps(user: AvatarUser): Record<string, unknown> {
81
+ const label = user.status ? `${user.name} (${user.status})` : user.name
82
+ return {
83
+ role: 'img',
84
+ 'aria-label': label,
85
+ }
86
+ }
87
+
88
+ const overflowBadgeProps: Record<string, unknown> = {
89
+ role: 'button',
90
+ 'aria-label': `${overflowCount} more users`,
91
+ }
92
+
93
+ return {
94
+ visibleUsers,
95
+ overflowCount,
96
+ overflowUsers,
97
+ ariaProps,
98
+ getAvatarAriaProps,
99
+ getInitials,
100
+ overflowBadgeProps,
101
+ ids: {
102
+ group: groupId,
103
+ label: labelId,
104
+ },
105
+ }
106
+ }
@@ -0,0 +1,18 @@
1
+ export {
2
+ createAvatarGroup,
3
+ getInitials,
4
+ AVATAR_SIZES,
5
+ type AvatarGroupProps,
6
+ type AvatarGroupAPI,
7
+ type AvatarUser,
8
+ type AvatarSize,
9
+ type PresenceStatus,
10
+ } from './avatar-group.js'
11
+
12
+ export {
13
+ avatarGroupStyles,
14
+ avatarVariants,
15
+ avatarOverflowBadgeVariants,
16
+ avatarImageStyles,
17
+ avatarPresenceDotVariants,
18
+ } from './avatar-group.styles.js'
@@ -0,0 +1,24 @@
1
+ import { cva } from '../shared/index.ts'
2
+
3
+ export const badgeVariants = cva({
4
+ base: 'inline-flex items-center rounded-full border px-2.5 py-0.5 text-xs font-semibold transition-colors focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2',
5
+ variants: {
6
+ variant: {
7
+ default: 'border-transparent bg-primary text-primary-foreground shadow hover:bg-primary/80',
8
+ primary: 'border-transparent bg-primary text-primary-foreground shadow hover:bg-primary/80',
9
+ secondary: 'border-transparent bg-secondary text-secondary-foreground hover:bg-secondary/80',
10
+ destructive: 'border-transparent bg-destructive text-destructive-foreground shadow hover:bg-destructive/80 font-semibold',
11
+ outline: 'text-foreground',
12
+ success: 'border-transparent bg-green-500 text-white shadow hover:bg-green-500/80 font-semibold',
13
+ warning: 'border-transparent bg-yellow-500 text-white shadow hover:bg-yellow-500/80 font-semibold',
14
+ },
15
+ size: {
16
+ sm: 'px-2 py-0 text-[10px]',
17
+ md: 'px-2.5 py-0.5 text-xs',
18
+ },
19
+ },
20
+ defaultVariants: {
21
+ variant: 'default',
22
+ size: 'md',
23
+ },
24
+ })
@@ -0,0 +1,48 @@
1
+ import type { AccessibilityProps } from '../shared/index.ts'
2
+
3
+ export type BadgeVariant = 'default' | 'primary' | 'secondary' | 'destructive' | 'outline' | 'success' | 'warning'
4
+ export type BadgeSize = 'sm' | 'md'
5
+
6
+ export interface BadgeProps {
7
+ variant?: BadgeVariant
8
+ size?: BadgeSize
9
+ }
10
+
11
+ export interface BadgeAPI {
12
+ /** ARIA attributes to spread on the element */
13
+ ariaProps: Partial<AccessibilityProps>
14
+ /** Data attributes for CSS styling hooks */
15
+ dataAttributes: Record<string, string>
16
+ }
17
+
18
+ const statusVariants: BadgeVariant[] = ['success', 'warning', 'destructive']
19
+
20
+ /** Icon name for status badge variants — non-color indicator for colorblind safety */
21
+ const BADGE_ICONS: Partial<Record<BadgeVariant, string>> = {
22
+ success: 'check',
23
+ warning: 'alert',
24
+ destructive: 'x',
25
+ }
26
+
27
+ /** Get the icon name for a badge variant (undefined for non-status variants) */
28
+ export function getBadgeIcon(variant: BadgeVariant): string | undefined {
29
+ return BADGE_ICONS[variant]
30
+ }
31
+
32
+ export function createBadge(props: BadgeProps = {}): BadgeAPI {
33
+ const { variant = 'default' } = props
34
+
35
+ const ariaProps: Partial<AccessibilityProps> = {}
36
+
37
+ if (statusVariants.includes(variant)) {
38
+ ariaProps.role = 'status'
39
+ }
40
+
41
+ const dataAttributes: Record<string, string> = {}
42
+ dataAttributes['data-variant'] = variant
43
+
44
+ return {
45
+ ariaProps,
46
+ dataAttributes,
47
+ }
48
+ }
@@ -0,0 +1,10 @@
1
+ export {
2
+ createBadge,
3
+ getBadgeIcon,
4
+ type BadgeVariant,
5
+ type BadgeSize,
6
+ type BadgeProps,
7
+ type BadgeAPI,
8
+ } from './badge.js'
9
+
10
+ export { badgeVariants } from './badge.styles.js'
@@ -0,0 +1,18 @@
1
+ import { cva } from '../shared/index.ts'
2
+
3
+ export const bottomNavVariants = cva({
4
+ base: 'fixed bottom-0 left-0 right-0 z-40 border-t bg-background md:hidden',
5
+ })
6
+
7
+ export const bottomNavTabVariants = cva({
8
+ base: 'flex flex-1 flex-col items-center justify-center gap-1 py-2 text-xs transition-colors',
9
+ variants: {
10
+ active: {
11
+ true: 'text-foreground',
12
+ false: 'text-muted-foreground',
13
+ },
14
+ },
15
+ defaultVariants: {
16
+ active: 'false',
17
+ },
18
+ })
@@ -0,0 +1,33 @@
1
+ export interface NavTab {
2
+ label: string
3
+ href: string
4
+ icon?: string
5
+ activeIcon?: string
6
+ }
7
+
8
+ export interface BottomNavProps {
9
+ tabs?: NavTab[]
10
+ currentPath?: string
11
+ }
12
+
13
+ export interface BottomNavAPI {
14
+ ariaProps: Record<string, string>
15
+ isActive: (href: string) => boolean
16
+ tabAriaProps: (href: string) => Record<string, string>
17
+ }
18
+
19
+ export function createBottomNav(props: BottomNavProps = {}): BottomNavAPI {
20
+ const { currentPath = '/' } = props
21
+
22
+ function isActive(href: string): boolean {
23
+ if (href === '/') return currentPath === '/'
24
+ return currentPath.startsWith(href)
25
+ }
26
+
27
+ return {
28
+ ariaProps: { role: 'navigation', 'aria-label': 'Main navigation' },
29
+ isActive,
30
+ tabAriaProps: (href: string): Record<string, string> =>
31
+ isActive(href) ? { 'aria-current': 'page' } : {},
32
+ }
33
+ }
@@ -0,0 +1,2 @@
1
+ export { createBottomNav, type NavTab, type BottomNavProps, type BottomNavAPI } from './bottom-nav.js'
2
+ export { bottomNavVariants, bottomNavTabVariants } from './bottom-nav.styles.js'
@@ -0,0 +1,20 @@
1
+ import { cva } from '../shared/index.ts'
2
+
3
+ export const breadcrumbsVariants = cva({
4
+ base: 'flex flex-wrap items-center gap-1.5 text-sm text-muted-foreground',
5
+ })
6
+
7
+ export const breadcrumbItemVariants = cva({
8
+ base: 'transition-colors',
9
+ variants: {
10
+ active: {
11
+ true: 'font-medium text-foreground',
12
+ false: 'hover:text-foreground',
13
+ },
14
+ },
15
+ defaultVariants: {
16
+ active: 'false',
17
+ },
18
+ })
19
+
20
+ export const breadcrumbSeparatorStyles = 'text-muted-foreground/50 select-none'
@@ -0,0 +1,72 @@
1
+ export interface BreadcrumbItem {
2
+ label: string
3
+ href?: string
4
+ }
5
+
6
+ export interface BreadcrumbsProps {
7
+ /** Current pathname to auto-generate from */
8
+ pathname?: string
9
+ /** Manual items (overrides pathname) */
10
+ items?: BreadcrumbItem[]
11
+ /** Custom label map for pathname segments */
12
+ labels?: Record<string, string>
13
+ /** Separator character */
14
+ separator?: string
15
+ /** Max items to show before truncating */
16
+ maxItems?: number
17
+ }
18
+
19
+ export interface BreadcrumbsAPI {
20
+ items: BreadcrumbItem[]
21
+ ariaProps: Record<string, string>
22
+ separator: string
23
+ isLast: (index: number) => boolean
24
+ itemAriaProps: (index: number) => Record<string, string>
25
+ }
26
+
27
+ function kebabToTitle(segment: string): string {
28
+ return segment
29
+ .split('-')
30
+ .map((word) => word.charAt(0).toUpperCase() + word.slice(1))
31
+ .join(' ')
32
+ }
33
+
34
+ function pathToItems(
35
+ pathname: string,
36
+ labels: Record<string, string> = {},
37
+ ): BreadcrumbItem[] {
38
+ const segments = pathname.split('/').filter(Boolean)
39
+ const items: BreadcrumbItem[] = [{ label: 'Home', href: '/' }]
40
+
41
+ let currentPath = ''
42
+ for (const segment of segments) {
43
+ currentPath += `/${segment}`
44
+ items.push({
45
+ label: labels[segment] ?? labels[currentPath] ?? kebabToTitle(segment),
46
+ href: currentPath,
47
+ })
48
+ }
49
+
50
+ return items
51
+ }
52
+
53
+ export function createBreadcrumbs(props: BreadcrumbsProps = {}): BreadcrumbsAPI {
54
+ const { pathname, items: manualItems, labels = {}, separator = '/', maxItems } = props
55
+
56
+ let items = manualItems ?? (pathname ? pathToItems(pathname, labels) : [])
57
+
58
+ if (maxItems && items.length > maxItems) {
59
+ const first = items[0]
60
+ const last = items.slice(-(maxItems - 1))
61
+ items = [first, { label: '...' }, ...last]
62
+ }
63
+
64
+ return {
65
+ items,
66
+ ariaProps: { 'aria-label': 'Breadcrumb' },
67
+ separator,
68
+ isLast: (index: number) => index === items.length - 1,
69
+ itemAriaProps: (index: number): Record<string, string> =>
70
+ index === items.length - 1 ? { 'aria-current': 'page' } : {},
71
+ }
72
+ }
@@ -0,0 +1,8 @@
1
+ export {
2
+ createBreadcrumbs,
3
+ type BreadcrumbItem,
4
+ type BreadcrumbsProps,
5
+ type BreadcrumbsAPI,
6
+ } from './breadcrumbs.js'
7
+
8
+ export { breadcrumbsVariants, breadcrumbItemVariants, breadcrumbSeparatorStyles } from './breadcrumbs.styles.js'
@@ -0,0 +1,38 @@
1
+ import { cva } from '../shared/index.ts'
2
+ import type { TokenContract } from '../shared/index.ts'
3
+
4
+ export const buttonTokens: TokenContract = {
5
+ name: 'button',
6
+ tokens: {
7
+ bg: { variable: '--rfr-button-bg', fallback: 'hsl(var(--primary))' },
8
+ fg: { variable: '--rfr-button-fg', fallback: 'hsl(var(--primary-foreground))' },
9
+ border: { variable: '--rfr-button-border', fallback: 'hsl(var(--border))' },
10
+ radius: { variable: '--rfr-button-radius', fallback: 'var(--radius)' },
11
+ ring: { variable: '--rfr-button-ring', fallback: 'hsl(var(--ring))' },
12
+ },
13
+ }
14
+
15
+ export const buttonVariants = cva({
16
+ base: 'inline-flex items-center justify-center gap-2 whitespace-nowrap rounded-md text-sm font-medium transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50 [&_svg]:pointer-events-none [&_svg]:shrink-0',
17
+ variants: {
18
+ variant: {
19
+ default: 'bg-primary text-primary-foreground shadow hover:bg-primary/90',
20
+ destructive: 'bg-destructive text-destructive-foreground shadow-sm hover:bg-destructive/90',
21
+ outline: 'border border-input bg-background shadow-sm hover:bg-accent hover:text-accent-foreground',
22
+ secondary: 'bg-secondary text-secondary-foreground shadow-sm hover:bg-secondary/80',
23
+ ghost: 'hover:bg-accent hover:text-accent-foreground',
24
+ link: 'text-primary underline-offset-4 hover:underline',
25
+ },
26
+ size: {
27
+ xs: 'h-7 rounded px-2 text-xs',
28
+ sm: 'h-8 rounded-md px-3 text-xs',
29
+ default: 'h-9 px-4 py-2',
30
+ lg: 'h-10 rounded-md px-8',
31
+ icon: 'h-9 w-9',
32
+ },
33
+ },
34
+ defaultVariants: {
35
+ variant: 'default',
36
+ size: 'default',
37
+ },
38
+ })
@@ -0,0 +1,64 @@
1
+ import type { AccessibilityProps, KeyboardHandlerMap } from '../shared/index.ts'
2
+ import { Keys } from '../shared/index.ts'
3
+
4
+ export type ButtonVariant = 'default' | 'destructive' | 'outline' | 'secondary' | 'ghost' | 'link'
5
+ export type ButtonSize = 'xs' | 'sm' | 'default' | 'lg' | 'icon'
6
+
7
+ export interface ButtonProps {
8
+ variant?: ButtonVariant
9
+ size?: ButtonSize
10
+ disabled?: boolean
11
+ loading?: boolean
12
+ asChild?: boolean
13
+ type?: 'button' | 'submit' | 'reset'
14
+ }
15
+
16
+ export interface ButtonAPI {
17
+ /** ARIA attributes to spread on the element */
18
+ ariaProps: Partial<AccessibilityProps>
19
+ /** Keyboard handlers to attach */
20
+ keyboardHandlers: KeyboardHandlerMap
21
+ /** Whether interaction should be blocked */
22
+ isInteractive: boolean
23
+ /** Data attributes for CSS styling hooks */
24
+ dataAttributes: Record<string, string>
25
+ }
26
+
27
+ export function createButton(props: ButtonProps = {}): ButtonAPI {
28
+ const { disabled = false, loading = false } = props
29
+ const isInteractive = !disabled && !loading
30
+
31
+ const ariaProps: Partial<AccessibilityProps> = {}
32
+ if (disabled) {
33
+ ariaProps['aria-disabled'] = true
34
+ }
35
+ if (loading) {
36
+ ariaProps['aria-disabled'] = true
37
+ ariaProps['aria-label'] = ariaProps['aria-label'] ?? undefined
38
+ }
39
+
40
+ const dataAttributes: Record<string, string> = {}
41
+ if (loading) {
42
+ dataAttributes['data-loading'] = ''
43
+ }
44
+ if (disabled) {
45
+ dataAttributes['data-disabled'] = ''
46
+ }
47
+
48
+ const keyboardHandlers: KeyboardHandlerMap = {}
49
+ if (!isInteractive) {
50
+ keyboardHandlers[Keys.Enter] = (e) => e.preventDefault()
51
+ keyboardHandlers[Keys.Space] = (e) => e.preventDefault()
52
+ }
53
+
54
+ return {
55
+ ariaProps,
56
+ keyboardHandlers,
57
+ isInteractive,
58
+ dataAttributes,
59
+ }
60
+ }
61
+
62
+ export function getButtonType(props: ButtonProps): string {
63
+ return props.type ?? 'button'
64
+ }
@@ -0,0 +1,10 @@
1
+ export {
2
+ createButton,
3
+ getButtonType,
4
+ type ButtonProps,
5
+ type ButtonAPI,
6
+ type ButtonVariant,
7
+ type ButtonSize,
8
+ } from './button.js'
9
+
10
+ export { buttonVariants, buttonTokens } from './button.styles.js'
@@ -0,0 +1,21 @@
1
+ import { cva } from '../shared/index.ts'
2
+
3
+ export const calendarVariants = cva({
4
+ base: 'p-3 rounded-md border bg-background',
5
+ })
6
+
7
+ export const dayVariants = cva({
8
+ base: 'inline-flex items-center justify-center rounded-md text-sm h-9 w-9',
9
+ variants: {
10
+ state: {
11
+ default: 'hover:bg-accent hover:text-accent-foreground',
12
+ selected: 'bg-primary text-primary-foreground hover:bg-primary/90',
13
+ today: 'bg-accent text-accent-foreground',
14
+ disabled: 'text-muted-foreground opacity-50 cursor-not-allowed',
15
+ outside: 'text-muted-foreground opacity-50',
16
+ },
17
+ },
18
+ defaultVariants: {
19
+ state: 'default',
20
+ },
21
+ })