@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.
- package/dist/accordion/index.ts +1 -0
- package/dist/ai/ai-manager.ts +121 -0
- package/dist/ai/index.ts +23 -0
- package/dist/ai/mock-providers.ts +68 -0
- package/dist/ai/sanitizer.ts +174 -0
- package/dist/ai/tts-manager.ts +80 -0
- package/dist/ai/types.ts +72 -0
- package/dist/animated-text/animated-text.styles.ts +28 -0
- package/dist/animated-text/animated-text.ts +83 -0
- package/dist/animated-text/index.ts +15 -0
- package/dist/app-shell/app-shell.ts +252 -0
- package/dist/app-shell/auth-shell.ts +84 -0
- package/dist/app-shell/index.ts +22 -0
- package/dist/app-shell/page-shell.ts +125 -0
- package/dist/astro-accordion/Button.astro +1 -1
- package/dist/astro-ai/index.ts +1 -1
- package/dist/astro-animated-text/AnimatedText.astro +1 -1
- package/dist/astro-animated-text/TypewriterText.astro +1 -1
- package/dist/astro-app-shell/AppShell.astro +1 -1
- package/dist/astro-app-shell/AuthShell.astro +1 -1
- package/dist/astro-app-shell/AuthShellCard.astro +1 -1
- package/dist/astro-app-shell/PageShell.astro +1 -1
- package/dist/astro-app-shell/PageShellSection.astro +1 -1
- package/dist/astro-app-shell/index.ts +1 -1
- package/dist/astro-auth/index.ts +2 -2
- package/dist/astro-avatar/Avatar.astro +1 -1
- package/dist/astro-avatar/AvatarFallback.astro +1 -1
- package/dist/astro-avatar/AvatarImage.astro +1 -1
- package/dist/astro-avatar-group/AvatarGroup.astro +1 -1
- package/dist/astro-badge/Badge.astro +1 -1
- package/dist/astro-bottom-nav/BottomNav.astro +1 -1
- package/dist/astro-breadcrumbs/Breadcrumbs.astro +1 -1
- package/dist/astro-button/Button.astro +1 -1
- package/dist/astro-calendar/Calendar.astro +1 -1
- package/dist/astro-card/Card.astro +1 -1
- package/dist/astro-card/CardContent.astro +1 -1
- package/dist/astro-card/CardDescription.astro +1 -1
- package/dist/astro-card/CardFooter.astro +1 -1
- package/dist/astro-card/CardHeader.astro +1 -1
- package/dist/astro-card/CardTitle.astro +1 -1
- package/dist/astro-card-grid/CardGrid.astro +1 -1
- package/dist/astro-carousel/Button.astro +1 -1
- package/dist/astro-charts/Bars.astro +1 -1
- package/dist/astro-charts/Chart.astro +1 -1
- package/dist/astro-charts/Circles.astro +1 -1
- package/dist/astro-charts/Histogram.astro +1 -1
- package/dist/astro-charts/Line.astro +1 -1
- package/dist/astro-charts/PieChart.astro +1 -1
- package/dist/astro-charts/ScatterPlot.astro +1 -1
- package/dist/astro-charts/index.ts +1 -1
- package/dist/astro-checkbox/Checkbox.astro +1 -1
- package/dist/astro-code-editor/CodeEditor.astro +1 -1
- package/dist/astro-collapsible/Collapsible.astro +1 -1
- package/dist/astro-collapsible/CollapsibleContent.astro +1 -1
- package/dist/astro-command/Command.astro +1 -1
- package/dist/astro-command/CommandGroup.astro +1 -1
- package/dist/astro-command/CommandInput.astro +1 -1
- package/dist/astro-command/CommandItem.astro +1 -1
- package/dist/astro-command-input/CommandInput.astro +1 -1
- package/dist/astro-content-protection/ContentProtection.astro +1 -1
- package/dist/astro-data-table/DataTable.astro +1 -1
- package/dist/astro-date-picker/DatePicker.astro +1 -1
- package/dist/astro-device-frame/DeviceFrame.astro +1 -1
- package/dist/astro-dialog/DialogContent.astro +1 -1
- package/dist/astro-dialog/DialogOverlay.astro +1 -1
- package/dist/astro-diff-viewer/DiffViewer.astro +1 -1
- package/dist/astro-dropdown-menu/DropdownMenuContent.astro +1 -1
- package/dist/astro-dropdown-menu/DropdownMenuItem.astro +1 -1
- package/dist/astro-emoji-picker/EmojiPicker.astro +1 -1
- package/dist/astro-feedback-dialog/FeedbackDialog.astro +1 -1
- package/dist/astro-file-upload/FileUpload.astro +1 -1
- package/dist/astro-footer/Footer.astro +1 -1
- package/dist/astro-inline-editor/InlineEditor.astro +1 -1
- package/dist/astro-input/Input.astro +1 -1
- package/dist/astro-input-group/InputGroup.astro +1 -1
- package/dist/astro-input-group/InputGroupAddon.astro +1 -1
- package/dist/astro-input-group/InputGroupButton.astro +1 -1
- package/dist/astro-install-prompt/InstallPrompt.astro +1 -1
- package/dist/astro-keyboard-shortcut/ShortcutBadge.astro +1 -1
- package/dist/astro-language-selector/LanguageSelector.astro +1 -1
- package/dist/astro-link-card/LinkCard.astro +1 -1
- package/dist/astro-markdown-renderer/MarkdownRenderer.astro +1 -1
- package/dist/astro-mobile-nav/MobileNav.astro +1 -1
- package/dist/astro-mobile-nav/MobileNavLink.astro +1 -1
- package/dist/astro-mobile-nav/MobileNavTrigger.astro +1 -1
- package/dist/astro-navbar/Navbar.astro +1 -1
- package/dist/astro-otp-input/OtpInput.astro +1 -1
- package/dist/astro-payment/Payment.astro +1 -1
- package/dist/astro-popover/PopoverContent.astro +1 -1
- package/dist/astro-presence-indicator/PresenceIndicator.astro +1 -1
- package/dist/astro-progress-display/BadgeDisplay.astro +1 -1
- package/dist/astro-progress-display/ProgressBar.astro +1 -1
- package/dist/astro-progress-display/StatsGrid.astro +1 -1
- package/dist/astro-radio/RadioGroup.astro +1 -1
- package/dist/astro-radio/RadioItem.astro +1 -1
- package/dist/astro-reaction-bar/ReactionBar.astro +1 -1
- package/dist/astro-resizable-layout/ResizableDivider.astro +1 -1
- package/dist/astro-resizable-layout/ResizableLayout.astro +1 -1
- package/dist/astro-resizable-layout/ResizablePane.astro +1 -1
- package/dist/astro-resizable-layout/index.ts +1 -1
- package/dist/astro-rich-editor/index.ts +2 -2
- package/dist/astro-search-bar/SearchBar.astro +1 -1
- package/dist/astro-search-bar/SearchResults.astro +1 -1
- package/dist/astro-select/Select.astro +1 -1
- package/dist/astro-select/SelectContent.astro +1 -1
- package/dist/astro-select/SelectItem.astro +1 -1
- package/dist/astro-select/SelectTrigger.astro +1 -1
- package/dist/astro-sidebar/Sidebar.astro +1 -1
- package/dist/astro-skeleton/Skeleton.astro +1 -1
- package/dist/astro-slide-viewer/SlideViewer.astro +1 -1
- package/dist/astro-status-indicator/StatusIndicator.astro +1 -1
- package/dist/astro-switch/Switch.astro +1 -1
- package/dist/astro-table-of-contents/TableOfContents.astro +1 -1
- package/dist/astro-tabs/Tabs.astro +1 -1
- package/dist/astro-tabs/TabsList.astro +1 -1
- package/dist/astro-tabs/TabsTrigger.astro +1 -1
- package/dist/astro-textarea/Textarea.astro +1 -1
- package/dist/astro-theme/ThemeScript.astro +1 -1
- package/dist/astro-thread-view/ThreadView.astro +1 -1
- package/dist/astro-toast/Toast.astro +1 -1
- package/dist/astro-tooltip/TooltipContent.astro +1 -1
- package/dist/astro-version-selector/VersionSelector.astro +1 -1
- package/dist/astro-video-player/VideoPlayer.astro +1 -1
- package/dist/auth/adapters/mock.ts +74 -0
- package/dist/auth/auth-machine.ts +120 -0
- package/dist/auth/index.ts +22 -0
- package/dist/auth/rbac.ts +44 -0
- package/dist/auth/types.ts +44 -0
- package/dist/avatar/avatar.styles.ts +47 -0
- package/dist/avatar/avatar.ts +73 -0
- package/dist/avatar/index.ts +15 -0
- package/dist/avatar-group/avatar-group.styles.ts +63 -0
- package/dist/avatar-group/avatar-group.ts +106 -0
- package/dist/avatar-group/index.ts +18 -0
- package/dist/badge/badge.styles.ts +24 -0
- package/dist/badge/badge.ts +48 -0
- package/dist/badge/index.ts +10 -0
- package/dist/bottom-nav/bottom-nav.styles.ts +18 -0
- package/dist/bottom-nav/bottom-nav.ts +33 -0
- package/dist/bottom-nav/index.ts +2 -0
- package/dist/breadcrumbs/breadcrumbs.styles.ts +20 -0
- package/dist/breadcrumbs/breadcrumbs.ts +72 -0
- package/dist/breadcrumbs/index.ts +8 -0
- package/dist/button/button.styles.ts +38 -0
- package/dist/button/button.ts +64 -0
- package/dist/button/index.ts +10 -0
- package/dist/calendar/calendar.styles.ts +21 -0
- package/dist/calendar/calendar.ts +202 -0
- package/dist/calendar/index.ts +9 -0
- package/dist/callout/callout.ts +1 -0
- package/dist/callout/index.ts +1 -0
- package/dist/card/card.styles.ts +55 -0
- package/dist/card/card.ts +45 -0
- package/dist/card/index.ts +20 -0
- package/dist/card-grid/card-grid.ts +9 -0
- package/dist/card-grid/index.ts +1 -0
- package/dist/carousel/index.ts +1 -0
- package/dist/charts/axis.ts +50 -0
- package/dist/charts/chart.ts +73 -0
- package/dist/charts/colorblind.ts +100 -0
- package/dist/charts/data.ts +72 -0
- package/dist/charts/geometry.ts +54 -0
- package/dist/charts/index.ts +61 -0
- package/dist/charts/scales.ts +151 -0
- package/dist/checkbox/checkbox.styles.ts +33 -0
- package/dist/checkbox/checkbox.ts +73 -0
- package/dist/checkbox/index.ts +10 -0
- package/dist/code-block/code-block.ts +1 -0
- package/dist/code-block/index.ts +1 -0
- package/dist/code-editor/code-editor.styles.ts +32 -0
- package/dist/code-editor/code-editor.ts +140 -0
- package/dist/code-editor/index.ts +9 -0
- package/dist/collapsible/collapsible.styles.ts +14 -0
- package/dist/collapsible/collapsible.ts +93 -0
- package/dist/collapsible/index.ts +7 -0
- package/dist/command/command.styles.ts +27 -0
- package/dist/command/command.ts +179 -0
- package/dist/command/index.ts +14 -0
- package/dist/command-input/command-input.ts +176 -0
- package/dist/command-input/index.ts +1 -0
- package/dist/content-protection/content-protection.styles.ts +9 -0
- package/dist/content-protection/content-protection.ts +68 -0
- package/dist/content-protection/index.ts +8 -0
- package/dist/data-table/data-table.styles.ts +55 -0
- package/dist/data-table/data-table.ts +183 -0
- package/dist/data-table/index.ts +15 -0
- package/dist/date-picker/date-picker.styles.ts +31 -0
- package/dist/date-picker/date-picker.ts +333 -0
- package/dist/date-picker/index.ts +18 -0
- package/dist/device-frame/device-frame.styles.ts +21 -0
- package/dist/device-frame/device-frame.ts +112 -0
- package/dist/device-frame/index.ts +10 -0
- package/dist/dialog/dialog.styles.ts +8 -0
- package/dist/dialog/dialog.ts +133 -0
- package/dist/dialog/index.ts +8 -0
- package/dist/diff-viewer/diff-viewer.styles.ts +124 -0
- package/dist/diff-viewer/diff-viewer.ts +255 -0
- package/dist/diff-viewer/index.ts +20 -0
- package/dist/dropdown-menu/dropdown-menu.styles.ts +9 -0
- package/dist/dropdown-menu/dropdown-menu.ts +139 -0
- package/dist/dropdown-menu/index.ts +9 -0
- package/dist/emoji-picker/emoji-data.ts +282 -0
- package/dist/emoji-picker/emoji-picker.styles.ts +32 -0
- package/dist/emoji-picker/emoji-picker.ts +165 -0
- package/dist/emoji-picker/index.ts +25 -0
- package/dist/feedback-dialog/feedback-dialog.styles.ts +15 -0
- package/dist/feedback-dialog/feedback-dialog.ts +147 -0
- package/dist/feedback-dialog/index.ts +11 -0
- package/dist/file-upload/file-upload.styles.ts +30 -0
- package/dist/file-upload/file-upload.ts +260 -0
- package/dist/file-upload/index.ts +19 -0
- package/dist/footer/footer.styles.ts +5 -0
- package/dist/footer/footer.ts +32 -0
- package/dist/footer/index.ts +9 -0
- package/dist/index.ts +1 -1
- package/dist/inline-editor/index.ts +13 -0
- package/dist/inline-editor/inline-editor.styles.ts +42 -0
- package/dist/inline-editor/inline-editor.ts +96 -0
- package/dist/input/index.ts +9 -0
- package/dist/input/input.styles.ts +15 -0
- package/dist/input/input.ts +84 -0
- package/dist/input-group/index.ts +13 -0
- package/dist/input-group/input-group.styles.ts +50 -0
- package/dist/input-group/input-group.ts +44 -0
- package/dist/install-prompt/index.ts +9 -0
- package/dist/install-prompt/install-prompt.styles.ts +5 -0
- package/dist/install-prompt/install-prompt.ts +68 -0
- package/dist/keyboard-shortcut/index.ts +12 -0
- package/dist/keyboard-shortcut/keyboard-shortcut.styles.ts +8 -0
- package/dist/keyboard-shortcut/keyboard-shortcut.ts +153 -0
- package/dist/language-selector/index.ts +8 -0
- package/dist/language-selector/language-selector.styles.ts +28 -0
- package/dist/language-selector/language-selector.ts +149 -0
- package/dist/link-card/index.ts +1 -0
- package/dist/link-card/link-card.ts +9 -0
- package/dist/markdown-renderer/index.ts +8 -0
- package/dist/markdown-renderer/markdown-renderer.styles.ts +31 -0
- package/dist/markdown-renderer/markdown-renderer.ts +251 -0
- package/dist/mobile-nav/index.ts +14 -0
- package/dist/mobile-nav/mobile-nav.styles.ts +39 -0
- package/dist/mobile-nav/mobile-nav.ts +74 -0
- package/dist/navbar/index.ts +9 -0
- package/dist/navbar/navbar.styles.ts +29 -0
- package/dist/navbar/navbar.ts +39 -0
- package/dist/otp-input/index.ts +13 -0
- package/dist/otp-input/otp-input.styles.ts +51 -0
- package/dist/otp-input/otp-input.ts +198 -0
- package/dist/pagination/index.ts +1 -0
- package/dist/payment/index.ts +1 -0
- package/dist/payment/payment.ts +16 -0
- package/dist/popover/index.ts +7 -0
- package/dist/popover/popover.styles.ts +16 -0
- package/dist/popover/popover.ts +89 -0
- package/dist/presence-indicator/index.ts +14 -0
- package/dist/presence-indicator/presence-indicator.styles.ts +29 -0
- package/dist/presence-indicator/presence-indicator.ts +63 -0
- package/dist/progress-display/index.ts +15 -0
- package/dist/progress-display/progress-display.styles.ts +72 -0
- package/dist/progress-display/progress-display.ts +60 -0
- package/dist/radio/index.ts +8 -0
- package/dist/radio/radio.styles.ts +34 -0
- package/dist/radio/radio.ts +70 -0
- package/dist/reaction-bar/index.ts +14 -0
- package/dist/reaction-bar/reaction-bar.styles.ts +23 -0
- package/dist/reaction-bar/reaction-bar.ts +87 -0
- package/dist/resizable-layout/index.ts +12 -0
- package/dist/resizable-layout/resizable-layout.styles.ts +50 -0
- package/dist/resizable-layout/resizable-layout.ts +139 -0
- package/dist/rich-editor/editor.ts +342 -0
- package/dist/rich-editor/emoji.ts +175 -0
- package/dist/rich-editor/history.ts +79 -0
- package/dist/rich-editor/index.ts +106 -0
- package/dist/rich-editor/markdown-shortcuts.ts +248 -0
- package/dist/rich-editor/mentions.ts +162 -0
- package/dist/rich-editor/model.ts +206 -0
- package/dist/rich-editor/operations.ts +772 -0
- package/dist/rich-editor/selection.ts +157 -0
- package/dist/rich-editor/serialization.ts +711 -0
- package/dist/rich-editor/slash-commands.ts +212 -0
- package/dist/search-bar/index.ts +7 -0
- package/dist/search-bar/search-bar.styles.ts +29 -0
- package/dist/search-bar/search-bar.ts +130 -0
- package/dist/select/index.ts +13 -0
- package/dist/select/select.styles.ts +52 -0
- package/dist/select/select.ts +152 -0
- package/dist/sidebar/index.ts +9 -0
- package/dist/sidebar/sidebar.styles.ts +27 -0
- package/dist/sidebar/sidebar.ts +59 -0
- package/dist/skeleton/index.ts +8 -0
- package/dist/skeleton/skeleton.styles.ts +16 -0
- package/dist/skeleton/skeleton.ts +39 -0
- package/dist/skip-to-content/index.ts +1 -0
- package/dist/skip-to-content/skip-to-content.ts +1 -0
- package/dist/slide-viewer/index.ts +16 -0
- package/dist/slide-viewer/slide-viewer.styles.ts +57 -0
- package/dist/slide-viewer/slide-viewer.ts +152 -0
- package/dist/slider/index.ts +1 -0
- package/dist/slider/slider.ts +2 -0
- package/dist/status-indicator/index.ts +15 -0
- package/dist/status-indicator/status-indicator.styles.ts +41 -0
- package/dist/status-indicator/status-indicator.ts +66 -0
- package/dist/steps/index.ts +1 -0
- package/dist/steps/steps.ts +1 -0
- package/dist/switch/index.ts +7 -0
- package/dist/switch/switch.styles.ts +55 -0
- package/dist/switch/switch.ts +63 -0
- package/dist/table-of-contents/index.ts +1 -0
- package/dist/table-of-contents/table-of-contents.ts +37 -0
- package/dist/tabs/index.ts +8 -0
- package/dist/tabs/tabs.styles.ts +9 -0
- package/dist/tabs/tabs.ts +133 -0
- package/dist/textarea/index.ts +7 -0
- package/dist/textarea/textarea.styles.ts +15 -0
- package/dist/textarea/textarea.ts +59 -0
- package/dist/theme/dom-adapters.ts +60 -0
- package/dist/theme/index.ts +18 -0
- package/dist/theme/theme-machine.ts +130 -0
- package/dist/theme/theme-script.ts +18 -0
- package/dist/thread-view/index.ts +26 -0
- package/dist/thread-view/thread-view.styles.ts +35 -0
- package/dist/thread-view/thread-view.ts +176 -0
- package/dist/toast/index.ts +13 -0
- package/dist/toast/toast.styles.ts +19 -0
- package/dist/toast/toast.ts +203 -0
- package/dist/tooltip/index.ts +7 -0
- package/dist/tooltip/tooltip.styles.ts +16 -0
- package/dist/tooltip/tooltip.ts +109 -0
- package/dist/version-selector/index.ts +12 -0
- package/dist/version-selector/version-selector.styles.ts +41 -0
- package/dist/version-selector/version-selector.ts +136 -0
- package/dist/video-player/index.ts +12 -0
- package/dist/video-player/video-player.styles.ts +42 -0
- package/dist/video-player/video-player.ts +100 -0
- 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,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,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,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,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
|
+
})
|