@refraction-ui/astro 0.4.0 → 0.4.2

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 (246) hide show
  1. package/dist/astro-accordion/Button.astro +55 -0
  2. package/dist/astro-accordion/index.ts +1 -0
  3. package/dist/astro-ai/AIScript.astro +69 -0
  4. package/dist/astro-ai/TTSScript.astro +60 -0
  5. package/dist/astro-ai/index.ts +16 -0
  6. package/dist/astro-animated-text/AnimatedText.astro +81 -0
  7. package/dist/astro-animated-text/TypewriterText.astro +90 -0
  8. package/dist/astro-animated-text/index.ts +1 -0
  9. package/dist/astro-app-shell/AppShell.astro +195 -0
  10. package/dist/astro-app-shell/AppShellContent.astro +29 -0
  11. package/dist/astro-app-shell/AppShellHeader.astro +54 -0
  12. package/dist/astro-app-shell/AppShellMain.astro +18 -0
  13. package/dist/astro-app-shell/AppShellMobileNav.astro +27 -0
  14. package/dist/astro-app-shell/AppShellOverlay.astro +21 -0
  15. package/dist/astro-app-shell/AppShellSidebar.astro +26 -0
  16. package/dist/astro-app-shell/AuthShell.astro +31 -0
  17. package/dist/astro-app-shell/AuthShellCard.astro +24 -0
  18. package/dist/astro-app-shell/PageShell.astro +36 -0
  19. package/dist/astro-app-shell/PageShellFooter.astro +30 -0
  20. package/dist/astro-app-shell/PageShellNav.astro +33 -0
  21. package/dist/astro-app-shell/PageShellSection.astro +32 -0
  22. package/dist/astro-app-shell/index.ts +21 -0
  23. package/dist/astro-auth/AuthGuard.astro +133 -0
  24. package/dist/astro-auth/index.ts +5 -0
  25. package/dist/astro-avatar/Avatar.astro +22 -0
  26. package/dist/astro-avatar/AvatarFallback.astro +18 -0
  27. package/dist/astro-avatar/AvatarImage.astro +48 -0
  28. package/dist/astro-avatar/index.ts +1 -0
  29. package/dist/astro-avatar-group/AvatarGroup.astro +42 -0
  30. package/dist/astro-avatar-group/index.ts +1 -0
  31. package/dist/astro-badge/Badge.astro +27 -0
  32. package/dist/astro-badge/index.ts +1 -0
  33. package/dist/astro-bottom-nav/BottomNav.astro +40 -0
  34. package/dist/astro-bottom-nav/index.ts +1 -0
  35. package/dist/astro-breadcrumbs/Breadcrumbs.astro +56 -0
  36. package/dist/astro-breadcrumbs/index.ts +1 -0
  37. package/dist/astro-button/Button.astro +55 -0
  38. package/dist/astro-button/index.ts +1 -0
  39. package/dist/astro-calendar/Calendar.astro +259 -0
  40. package/dist/astro-calendar/index.ts +1 -0
  41. package/dist/astro-callout/Callout.astro +3 -0
  42. package/dist/astro-callout/index.ts +1 -0
  43. package/dist/astro-card/Card.astro +20 -0
  44. package/dist/astro-card/CardContent.astro +13 -0
  45. package/dist/astro-card/CardDescription.astro +13 -0
  46. package/dist/astro-card/CardFooter.astro +13 -0
  47. package/dist/astro-card/CardHeader.astro +13 -0
  48. package/dist/astro-card/CardTitle.astro +15 -0
  49. package/dist/astro-card/index.ts +1 -0
  50. package/dist/astro-card-grid/CardGrid.astro +17 -0
  51. package/dist/astro-card-grid/index.ts +1 -0
  52. package/dist/astro-carousel/Button.astro +55 -0
  53. package/dist/astro-carousel/index.ts +1 -0
  54. package/dist/astro-charts/Bars.astro +53 -0
  55. package/dist/astro-charts/Chart.astro +31 -0
  56. package/dist/astro-charts/Circles.astro +48 -0
  57. package/dist/astro-charts/Gradient.astro +34 -0
  58. package/dist/astro-charts/Histogram.astro +107 -0
  59. package/dist/astro-charts/Line.astro +55 -0
  60. package/dist/astro-charts/PieChart.astro +63 -0
  61. package/dist/astro-charts/ScatterPlot.astro +95 -0
  62. package/dist/astro-charts/XAxis.astro +46 -0
  63. package/dist/astro-charts/YAxis.astro +44 -0
  64. package/dist/astro-charts/index.ts +26 -0
  65. package/dist/astro-checkbox/Checkbox.astro +129 -0
  66. package/dist/astro-checkbox/index.ts +1 -0
  67. package/dist/astro-code-block/CodeBlock.astro +3 -0
  68. package/dist/astro-code-block/index.ts +1 -0
  69. package/dist/astro-code-editor/CodeEditor.astro +123 -0
  70. package/dist/astro-code-editor/index.ts +1 -0
  71. package/dist/astro-collapsible/Collapsible.astro +58 -0
  72. package/dist/astro-collapsible/CollapsibleContent.astro +21 -0
  73. package/dist/astro-collapsible/CollapsibleTrigger.astro +17 -0
  74. package/dist/astro-collapsible/index.ts +1 -0
  75. package/dist/astro-command/Command.astro +170 -0
  76. package/dist/astro-command/CommandEmpty.astro +17 -0
  77. package/dist/astro-command/CommandGroup.astro +25 -0
  78. package/dist/astro-command/CommandInput.astro +21 -0
  79. package/dist/astro-command/CommandItem.astro +26 -0
  80. package/dist/astro-command/CommandList.astro +17 -0
  81. package/dist/astro-command/CommandSeparator.astro +14 -0
  82. package/dist/astro-command/index.ts +1 -0
  83. package/dist/astro-command-input/CommandInput.astro +6 -0
  84. package/dist/astro-command-input/index.ts +1 -0
  85. package/dist/astro-content-protection/ContentProtection.astro +104 -0
  86. package/dist/astro-content-protection/index.ts +1 -0
  87. package/dist/astro-data-table/DataTable.astro +263 -0
  88. package/dist/astro-data-table/index.ts +1 -0
  89. package/dist/astro-date-picker/DatePicker.astro +398 -0
  90. package/dist/astro-date-picker/index.ts +1 -0
  91. package/dist/astro-device-frame/DeviceFrame.astro +44 -0
  92. package/dist/astro-device-frame/index.ts +1 -0
  93. package/dist/astro-dialog/Dialog.astro +138 -0
  94. package/dist/astro-dialog/DialogClose.astro +16 -0
  95. package/dist/astro-dialog/DialogContent.astro +24 -0
  96. package/dist/astro-dialog/DialogDescription.astro +15 -0
  97. package/dist/astro-dialog/DialogFooter.astro +14 -0
  98. package/dist/astro-dialog/DialogHeader.astro +14 -0
  99. package/dist/astro-dialog/DialogOverlay.astro +17 -0
  100. package/dist/astro-dialog/DialogTitle.astro +15 -0
  101. package/dist/astro-dialog/DialogTrigger.astro +18 -0
  102. package/dist/astro-dialog/index.ts +1 -0
  103. package/dist/astro-diff-viewer/DiffViewer.astro +371 -0
  104. package/dist/astro-diff-viewer/index.ts +1 -0
  105. package/dist/astro-dropdown-menu/DropdownMenu.astro +138 -0
  106. package/dist/astro-dropdown-menu/DropdownMenuContent.astro +20 -0
  107. package/dist/astro-dropdown-menu/DropdownMenuItem.astro +21 -0
  108. package/dist/astro-dropdown-menu/DropdownMenuLabel.astro +14 -0
  109. package/dist/astro-dropdown-menu/DropdownMenuSeparator.astro +14 -0
  110. package/dist/astro-dropdown-menu/DropdownMenuTrigger.astro +18 -0
  111. package/dist/astro-dropdown-menu/index.ts +1 -0
  112. package/dist/astro-emoji-picker/EmojiPicker.astro +255 -0
  113. package/dist/astro-emoji-picker/index.ts +1 -0
  114. package/dist/astro-feedback-dialog/FeedbackDialog.astro +152 -0
  115. package/dist/astro-feedback-dialog/index.ts +1 -0
  116. package/dist/astro-file-tree/astro-file-tree.astro +4 -0
  117. package/dist/astro-file-tree/index.ts +1 -0
  118. package/dist/astro-file-upload/FileUpload.astro +306 -0
  119. package/dist/astro-file-upload/index.ts +1 -0
  120. package/dist/astro-footer/Footer.astro +61 -0
  121. package/dist/astro-footer/index.ts +1 -0
  122. package/dist/astro-icon-system/astro-icon-system.astro +4 -0
  123. package/dist/astro-icon-system/index.ts +1 -0
  124. package/dist/astro-inline-editor/InlineEditor.astro +169 -0
  125. package/dist/astro-inline-editor/index.ts +1 -0
  126. package/dist/astro-input/Input.astro +49 -0
  127. package/dist/astro-input/index.ts +1 -0
  128. package/dist/astro-input-group/InputGroup.astro +29 -0
  129. package/dist/astro-input-group/InputGroupAddon.astro +14 -0
  130. package/dist/astro-input-group/InputGroupButton.astro +19 -0
  131. package/dist/astro-input-group/InputGroupText.astro +11 -0
  132. package/dist/astro-input-group/index.ts +1 -0
  133. package/dist/astro-install-prompt/InstallPrompt.astro +115 -0
  134. package/dist/astro-install-prompt/index.ts +1 -0
  135. package/dist/astro-keyboard-shortcut/KeyboardShortcut.astro +83 -0
  136. package/dist/astro-keyboard-shortcut/ShortcutBadge.astro +41 -0
  137. package/dist/astro-keyboard-shortcut/index.ts +1 -0
  138. package/dist/astro-language-selector/LanguageSelector.astro +247 -0
  139. package/dist/astro-language-selector/index.ts +1 -0
  140. package/dist/astro-link-card/LinkCard.astro +17 -0
  141. package/dist/astro-link-card/index.ts +1 -0
  142. package/dist/astro-markdown-renderer/MarkdownRenderer.astro +62 -0
  143. package/dist/astro-markdown-renderer/index.ts +1 -0
  144. package/dist/astro-mobile-nav/MobileNav.astro +84 -0
  145. package/dist/astro-mobile-nav/MobileNavContent.astro +29 -0
  146. package/dist/astro-mobile-nav/MobileNavLink.astro +16 -0
  147. package/dist/astro-mobile-nav/MobileNavTrigger.astro +57 -0
  148. package/dist/astro-mobile-nav/index.ts +1 -0
  149. package/dist/astro-navbar/Navbar.astro +49 -0
  150. package/dist/astro-navbar/index.ts +1 -0
  151. package/dist/astro-otp-input/OtpInput.astro +253 -0
  152. package/dist/astro-otp-input/index.ts +1 -0
  153. package/dist/astro-pagination/Pagination.astro +3 -0
  154. package/dist/astro-pagination/index.ts +1 -0
  155. package/dist/astro-payment/Payment.astro +19 -0
  156. package/dist/astro-payment/index.ts +1 -0
  157. package/dist/astro-popover/Popover.astro +87 -0
  158. package/dist/astro-popover/PopoverClose.astro +16 -0
  159. package/dist/astro-popover/PopoverContent.astro +23 -0
  160. package/dist/astro-popover/PopoverTrigger.astro +18 -0
  161. package/dist/astro-popover/index.ts +1 -0
  162. package/dist/astro-presence-indicator/PresenceIndicator.astro +26 -0
  163. package/dist/astro-presence-indicator/index.ts +1 -0
  164. package/dist/astro-progress-display/BadgeDisplay.astro +33 -0
  165. package/dist/astro-progress-display/ProgressBar.astro +27 -0
  166. package/dist/astro-progress-display/StatsGrid.astro +32 -0
  167. package/dist/astro-progress-display/index.ts +1 -0
  168. package/dist/astro-radio/RadioGroup.astro +111 -0
  169. package/dist/astro-radio/RadioItem.astro +36 -0
  170. package/dist/astro-radio/index.ts +1 -0
  171. package/dist/astro-reaction-bar/ReactionBar.astro +117 -0
  172. package/dist/astro-reaction-bar/index.ts +1 -0
  173. package/dist/astro-resizable-layout/ResizableDivider.astro +27 -0
  174. package/dist/astro-resizable-layout/ResizableLayout.astro +162 -0
  175. package/dist/astro-resizable-layout/ResizablePane.astro +28 -0
  176. package/dist/astro-resizable-layout/index.ts +11 -0
  177. package/dist/astro-rich-editor/RichEditor.astro +260 -0
  178. package/dist/astro-rich-editor/index.ts +25 -0
  179. package/dist/astro-search-bar/SearchBar.astro +140 -0
  180. package/dist/astro-search-bar/SearchResultItem.astro +16 -0
  181. package/dist/astro-search-bar/SearchResults.astro +17 -0
  182. package/dist/astro-search-bar/index.ts +1 -0
  183. package/dist/astro-select/Select.astro +165 -0
  184. package/dist/astro-select/SelectContent.astro +19 -0
  185. package/dist/astro-select/SelectItem.astro +42 -0
  186. package/dist/astro-select/SelectTrigger.astro +36 -0
  187. package/dist/astro-select/index.ts +1 -0
  188. package/dist/astro-sidebar/Sidebar.astro +64 -0
  189. package/dist/astro-sidebar/index.ts +1 -0
  190. package/dist/astro-skeleton/Skeleton.astro +39 -0
  191. package/dist/astro-skeleton/SkeletonText.astro +22 -0
  192. package/dist/astro-skeleton/index.ts +1 -0
  193. package/dist/astro-skip-to-content/SkipToContent.astro +3 -0
  194. package/dist/astro-skip-to-content/index.ts +1 -0
  195. package/dist/astro-slide-viewer/SlideViewer.astro +231 -0
  196. package/dist/astro-slide-viewer/index.ts +1 -0
  197. package/dist/astro-slider/index.ts +1 -0
  198. package/dist/astro-status-indicator/StatusIndicator.astro +31 -0
  199. package/dist/astro-status-indicator/index.ts +1 -0
  200. package/dist/astro-steps/Steps.astro +3 -0
  201. package/dist/astro-steps/index.ts +1 -0
  202. package/dist/astro-switch/Switch.astro +89 -0
  203. package/dist/astro-switch/index.ts +1 -0
  204. package/dist/astro-table-of-contents/TableOfContents.astro +53 -0
  205. package/dist/astro-table-of-contents/index.ts +1 -0
  206. package/dist/astro-tabs/Tabs.astro +96 -0
  207. package/dist/astro-tabs/TabsContent.astro +20 -0
  208. package/dist/astro-tabs/TabsList.astro +16 -0
  209. package/dist/astro-tabs/TabsTrigger.astro +24 -0
  210. package/dist/astro-tabs/index.ts +1 -0
  211. package/dist/astro-textarea/Textarea.astro +51 -0
  212. package/dist/astro-textarea/index.ts +1 -0
  213. package/dist/astro-theme/ThemeScript.astro +13 -0
  214. package/dist/astro-theme/ThemeToggle.astro +279 -0
  215. package/dist/astro-theme/index.ts +1 -0
  216. package/dist/astro-thread-view/ThreadView.astro +159 -0
  217. package/dist/astro-thread-view/index.ts +1 -0
  218. package/dist/astro-toast/Toast.astro +49 -0
  219. package/dist/astro-toast/Toaster.astro +142 -0
  220. package/dist/astro-toast/index.ts +1 -0
  221. package/dist/astro-tooltip/Tooltip.astro +95 -0
  222. package/dist/astro-tooltip/TooltipContent.astro +22 -0
  223. package/dist/astro-tooltip/TooltipTrigger.astro +16 -0
  224. package/dist/astro-tooltip/index.ts +1 -0
  225. package/dist/astro-version-selector/VersionSelector.astro +174 -0
  226. package/dist/astro-version-selector/index.ts +1 -0
  227. package/dist/astro-video-player/VideoPlayer.astro +153 -0
  228. package/dist/astro-video-player/index.ts +1 -0
  229. package/dist/index.ts +77 -0
  230. package/dist/shared/a11y.ts +33 -0
  231. package/dist/shared/aria.ts +30 -0
  232. package/dist/shared/cn.ts +35 -0
  233. package/dist/shared/cva.ts +79 -0
  234. package/dist/shared/engine-adapter.ts +10 -0
  235. package/dist/shared/focus-trap.ts +123 -0
  236. package/dist/shared/index.ts +60 -0
  237. package/dist/shared/keyboard.ts +36 -0
  238. package/dist/shared/live-region.ts +90 -0
  239. package/dist/shared/motion.ts +15 -0
  240. package/dist/shared/skip-link.ts +35 -0
  241. package/dist/shared/state-machine.ts +57 -0
  242. package/dist/shared/tokens.ts +16 -0
  243. package/dist/shared/types.ts +45 -0
  244. package/dist/shared/variants.ts +17 -0
  245. package/package.json +20 -19
  246. package/src/index.ts +0 -94
@@ -0,0 +1,27 @@
1
+ ---
2
+ /**
3
+ * AppShellMobileNav — fixed bottom navigation bar, visible only on mobile.
4
+ */
5
+ import { cn } from '../shared/index.ts'
6
+
7
+ interface Props extends astroHTML.JSX.HTMLAttributes {}
8
+
9
+ const { class: className, ...props } = Astro.props
10
+ ---
11
+
12
+ <nav
13
+ role="navigation"
14
+ aria-label="Mobile navigation"
15
+ class={cn(
16
+ 'fixed bottom-0 left-0 right-0 z-30',
17
+ 'flex items-center justify-around',
18
+ 'border-t bg-background',
19
+ 'h-14',
20
+ className,
21
+ )}
22
+ style="display:none;"
23
+ data-rfr-shell-mobile-nav
24
+ {...props}
25
+ >
26
+ <slot />
27
+ </nav>
@@ -0,0 +1,21 @@
1
+ ---
2
+ /**
3
+ * AppShellOverlay — backdrop overlay shown when mobile sidebar is open.
4
+ */
5
+ import { cn } from '../shared/index.ts'
6
+
7
+ interface Props extends astroHTML.JSX.HTMLAttributes {}
8
+
9
+ const { class: className, ...props } = Astro.props
10
+ ---
11
+
12
+ <div
13
+ aria-hidden="true"
14
+ class={cn(
15
+ 'fixed inset-0 z-30 bg-black/50 transition-opacity',
16
+ className,
17
+ )}
18
+ style="display:none;"
19
+ data-rfr-shell-overlay
20
+ {...props}
21
+ />
@@ -0,0 +1,26 @@
1
+ ---
2
+ /**
3
+ * AppShellSidebar — sidebar navigation area within the AppShell.
4
+ */
5
+ import { cn } from '../shared/index.ts'
6
+
7
+ interface Props extends astroHTML.JSX.HTMLAttributes {}
8
+
9
+ const { class: className, ...props } = Astro.props
10
+ ---
11
+
12
+ <aside
13
+ role="navigation"
14
+ aria-label="Sidebar"
15
+ class={cn(
16
+ 'flex flex-col shrink-0 overflow-y-auto overflow-x-hidden',
17
+ 'bg-background border-r',
18
+ 'transition-[width,transform] duration-200 ease-in-out',
19
+ 'h-full relative w-[var(--shell-sidebar-width)]',
20
+ className,
21
+ )}
22
+ data-rfr-shell-sidebar
23
+ {...props}
24
+ >
25
+ <slot />
26
+ </aside>
@@ -0,0 +1,31 @@
1
+ ---
2
+ /**
3
+ * AuthShell — centered layout for authentication pages (sign-in, sign-up, etc.).
4
+ */
5
+ import { createAuthShell, type AuthShellConfig } from '@refraction-ui/app-shell'
6
+ import { cn } from '../shared/index.ts'
7
+
8
+ interface Props extends astroHTML.JSX.HTMLAttributes {
9
+ /** Card max-width preset (default 'sm') */
10
+ maxWidth?: 'xs' | 'sm' | 'md'
11
+ /** Card position (default 'center') */
12
+ position?: 'center' | 'left'
13
+ /** Show decorative background (default true) */
14
+ showBackground?: boolean
15
+ }
16
+
17
+ const { maxWidth, position, showBackground, class: className, ...props } = Astro.props
18
+
19
+ const config: AuthShellConfig = { maxWidth, position, showBackground }
20
+ const api = createAuthShell(config)
21
+ ---
22
+
23
+ <div
24
+ role="main"
25
+ aria-label="Authentication"
26
+ class={cn(api.containerClasses, className)}
27
+ data-rfr-auth-shell
28
+ {...props}
29
+ >
30
+ <slot />
31
+ </div>
@@ -0,0 +1,24 @@
1
+ ---
2
+ /**
3
+ * AuthShellCard — card container within AuthShell for form content.
4
+ */
5
+ import { createAuthShell, type AuthShellConfig } from '@refraction-ui/app-shell'
6
+ import { cn } from '../shared/index.ts'
7
+
8
+ interface Props extends astroHTML.JSX.HTMLAttributes {
9
+ /** Card max-width preset (default 'sm') */
10
+ maxWidth?: 'xs' | 'sm' | 'md'
11
+ }
12
+
13
+ const { maxWidth, class: className, ...props } = Astro.props
14
+
15
+ const api = createAuthShell({ maxWidth })
16
+ ---
17
+
18
+ <div
19
+ class={cn(api.cardClasses, className)}
20
+ data-rfr-auth-card
21
+ {...props}
22
+ >
23
+ <slot />
24
+ </div>
@@ -0,0 +1,36 @@
1
+ ---
2
+ /**
3
+ * PageShell — root layout for marketing/landing pages with nav, sections, footer.
4
+ */
5
+ import { createPageShell, type PageShellConfig } from '@refraction-ui/app-shell'
6
+ import { cn } from '../shared/index.ts'
7
+
8
+ interface Props extends astroHTML.JSX.HTMLAttributes {
9
+ /** Max width for contained sections (default '80rem') */
10
+ maxWidth?: string
11
+ /** Navigation bar height (default '4rem') */
12
+ navHeight?: string
13
+ /** Whether nav is transparent (default false) */
14
+ navTransparent?: boolean
15
+ /** Whether nav is sticky (default true) */
16
+ navSticky?: boolean
17
+ /** Number of footer columns (default 4) */
18
+ footerColumns?: number
19
+ }
20
+
21
+ const { maxWidth, navHeight, navTransparent, navSticky, footerColumns, class: className, ...props } = Astro.props
22
+
23
+ const config: PageShellConfig = { maxWidth, navHeight, navTransparent, navSticky, footerColumns }
24
+ const api = createPageShell(config)
25
+ const cssVars = api.getCSSVariables()
26
+ const styleStr = Object.entries(cssVars).map(([k, v]) => `${k}:${v}`).join(';')
27
+ ---
28
+
29
+ <div
30
+ class={cn('flex min-h-screen flex-col', className)}
31
+ style={styleStr}
32
+ data-rfr-page-shell
33
+ {...props}
34
+ >
35
+ <slot />
36
+ </div>
@@ -0,0 +1,30 @@
1
+ ---
2
+ /**
3
+ * PageShellFooter — footer area within PageShell.
4
+ */
5
+ import { cn } from '../shared/index.ts'
6
+
7
+ interface Props extends astroHTML.JSX.HTMLAttributes {
8
+ /** Number of grid columns (default 4) */
9
+ columns?: number
10
+ }
11
+
12
+ const { columns = 4, class: className, ...props } = Astro.props
13
+ ---
14
+
15
+ <footer
16
+ role="contentinfo"
17
+ class={cn(
18
+ 'border-t bg-muted py-12 px-4 sm:px-6 lg:px-8',
19
+ className,
20
+ )}
21
+ data-rfr-page-footer
22
+ {...props}
23
+ >
24
+ <div
25
+ class="mx-auto max-w-[var(--page-max-width)] grid gap-8"
26
+ style={`grid-template-columns: repeat(${columns}, minmax(0, 1fr));`}
27
+ >
28
+ <slot />
29
+ </div>
30
+ </footer>
@@ -0,0 +1,33 @@
1
+ ---
2
+ /**
3
+ * PageShellNav — navigation bar within PageShell.
4
+ */
5
+ import { cn } from '../shared/index.ts'
6
+
7
+ interface Props extends astroHTML.JSX.HTMLAttributes {
8
+ /** Whether nav is sticky (default true) */
9
+ sticky?: boolean
10
+ /** Whether nav is transparent (default false) */
11
+ transparent?: boolean
12
+ }
13
+
14
+ const { sticky = true, transparent = false, class: className, ...props } = Astro.props
15
+
16
+ const stickyClass = sticky ? 'sticky top-0 z-40' : ''
17
+ const transparentClass = transparent ? 'bg-transparent' : 'bg-background border-b'
18
+ ---
19
+
20
+ <nav
21
+ role="navigation"
22
+ aria-label="Main navigation"
23
+ class={cn(
24
+ 'flex items-center h-[var(--page-nav-height)] px-4 sm:px-6 lg:px-8',
25
+ stickyClass,
26
+ transparentClass,
27
+ className,
28
+ )}
29
+ data-rfr-page-nav
30
+ {...props}
31
+ >
32
+ <slot />
33
+ </nav>
@@ -0,0 +1,32 @@
1
+ ---
2
+ /**
3
+ * PageShellSection — a content section within PageShell.
4
+ */
5
+ import { createPageShell } from '@refraction-ui/app-shell'
6
+ import { cn } from '../shared/index.ts'
7
+
8
+ interface Props extends astroHTML.JSX.HTMLAttributes {
9
+ /** Whether section spans edge-to-edge (default false) */
10
+ fullWidth?: boolean
11
+ /** Override max-width for this section */
12
+ maxWidth?: string
13
+ /** Whether section has padding (default true) */
14
+ padding?: boolean
15
+ /** Background variant */
16
+ background?: 'default' | 'muted' | 'primary' | 'none'
17
+ }
18
+
19
+ const { fullWidth, maxWidth, padding, background, class: className, ...props } = Astro.props
20
+
21
+ // Use the default page shell to get section classes
22
+ const api = createPageShell()
23
+ const sectionClasses = api.getSectionClasses({ fullWidth, maxWidth, padding, background })
24
+ ---
25
+
26
+ <section
27
+ class={cn('py-12', sectionClasses, className)}
28
+ data-rfr-page-section
29
+ {...props}
30
+ >
31
+ <slot />
32
+ </section>
@@ -0,0 +1,21 @@
1
+ // AppShell compound components
2
+ export { default as AppShell } from './AppShell.astro'
3
+ export { default as AppShellSidebar } from './AppShellSidebar.astro'
4
+ export { default as AppShellHeader } from './AppShellHeader.astro'
5
+ export { default as AppShellMain } from './AppShellMain.astro'
6
+ export { default as AppShellContent } from './AppShellContent.astro'
7
+ export { default as AppShellMobileNav } from './AppShellMobileNav.astro'
8
+ export { default as AppShellOverlay } from './AppShellOverlay.astro'
9
+
10
+ // PageShell compound components
11
+ export { default as PageShell } from './PageShell.astro'
12
+ export { default as PageShellNav } from './PageShellNav.astro'
13
+ export { default as PageShellSection } from './PageShellSection.astro'
14
+ export { default as PageShellFooter } from './PageShellFooter.astro'
15
+
16
+ // AuthShell compound components
17
+ export { default as AuthShell } from './AuthShell.astro'
18
+ export { default as AuthShellCard } from './AuthShellCard.astro'
19
+
20
+ // Re-export core types
21
+ export { createAppShell, createPageShell, createAuthShell } from '@refraction-ui/app-shell'
@@ -0,0 +1,133 @@
1
+ ---
2
+ /**
3
+ * AuthGuard — server-side component that conditionally renders children
4
+ * based on auth state. Since Astro is primarily server-rendered, this
5
+ * component checks auth at SSR time and includes a client-side script
6
+ * for dynamic scenarios.
7
+ *
8
+ * Slots:
9
+ * - default: content shown when authenticated
10
+ * - fallback: shown while loading / when unauthenticated (no roles check)
11
+ * - unauthorized: shown when user lacks required roles
12
+ */
13
+ import { cn } from '../shared/index.ts'
14
+
15
+ interface Props extends astroHTML.JSX.HTMLAttributes {
16
+ /** Roles required to view the content */
17
+ roles?: string[]
18
+ /** URL to redirect to when unauthenticated (client-side) */
19
+ redirectTo?: string
20
+ /** Provider type for auto-detection */
21
+ provider?: 'firebase' | 'supabase' | 'mock' | 'none'
22
+ }
23
+
24
+ const { roles, redirectTo, provider, class: className, ...props } = Astro.props
25
+
26
+ const rolesJSON = JSON.stringify(roles ?? [])
27
+ ---
28
+
29
+ <div
30
+ class={cn('rfr-auth-guard', className)}
31
+ data-rfr-auth-guard
32
+ data-rfr-auth-roles={rolesJSON}
33
+ data-rfr-auth-redirect={redirectTo}
34
+ data-rfr-auth-provider={provider}
35
+ {...props}
36
+ >
37
+ <!-- Loading / fallback state (hidden once auth resolves) -->
38
+ <div data-rfr-auth-state="loading">
39
+ <slot name="fallback">
40
+ <div class="flex items-center justify-center p-8" aria-busy="true" aria-label="Checking authentication">
41
+ <svg
42
+ class="animate-spin h-6 w-6"
43
+ xmlns="http://www.w3.org/2000/svg"
44
+ fill="none"
45
+ viewBox="0 0 24 24"
46
+ aria-hidden="true"
47
+ >
48
+ <circle
49
+ class="opacity-25"
50
+ cx="12"
51
+ cy="12"
52
+ r="10"
53
+ stroke="currentColor"
54
+ stroke-width="4"
55
+ />
56
+ <path
57
+ class="opacity-75"
58
+ fill="currentColor"
59
+ d="M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z"
60
+ />
61
+ </svg>
62
+ </div>
63
+ </slot>
64
+ </div>
65
+
66
+ <!-- Authenticated content (hidden until auth confirmed) -->
67
+ <div data-rfr-auth-state="authenticated" style="display:none;">
68
+ <slot />
69
+ </div>
70
+
71
+ <!-- Unauthorized (hidden unless roles check fails) -->
72
+ <div data-rfr-auth-state="unauthorized" style="display:none;">
73
+ <slot name="unauthorized">
74
+ <div class="flex items-center justify-center p-8 text-muted-foreground" role="alert">
75
+ <p>You do not have permission to view this content.</p>
76
+ </div>
77
+ </slot>
78
+ </div>
79
+ </div>
80
+
81
+ <script is:inline>
82
+ ;(function () {
83
+ document.querySelectorAll('[data-rfr-auth-guard]').forEach(function (guard) {
84
+ var redirect = guard.getAttribute('data-rfr-auth-redirect')
85
+ var roles = []
86
+ try {
87
+ roles = JSON.parse(guard.getAttribute('data-rfr-auth-roles') || '[]')
88
+ } catch (_) { /* */ }
89
+
90
+ var loadingEl = guard.querySelector('[data-rfr-auth-state="loading"]')
91
+ var authedEl = guard.querySelector('[data-rfr-auth-state="authenticated"]')
92
+ var unauthEl = guard.querySelector('[data-rfr-auth-state="unauthorized"]')
93
+
94
+ function showState(state) {
95
+ if (loadingEl) loadingEl.style.display = state === 'loading' ? '' : 'none'
96
+ if (authedEl) authedEl.style.display = state === 'authenticated' ? '' : 'none'
97
+ if (unauthEl) unauthEl.style.display = state === 'unauthorized' ? '' : 'none'
98
+ }
99
+
100
+ function hasAnyRole(user, requiredRoles) {
101
+ if (!requiredRoles || requiredRoles.length === 0) return true
102
+ if (!user || !user.roles) return false
103
+ return requiredRoles.some(function (r) { return user.roles.indexOf(r) !== -1 })
104
+ }
105
+
106
+ function handleAuth(user) {
107
+ if (!user) {
108
+ if (redirect) {
109
+ window.location.href = redirect
110
+ } else {
111
+ showState('loading')
112
+ }
113
+ return
114
+ }
115
+ if (roles.length > 0 && !hasAnyRole(user, roles)) {
116
+ showState('unauthorized')
117
+ return
118
+ }
119
+ showState('authenticated')
120
+ }
121
+
122
+ // Listen for custom auth events dispatched by the auth system
123
+ window.addEventListener('rfr:auth:state', function (e) {
124
+ handleAuth(e.detail && e.detail.user)
125
+ })
126
+
127
+ // Check if auth state is already available
128
+ if (window.__rfr_auth && window.__rfr_auth._ready) {
129
+ handleAuth(window.__rfr_auth.user)
130
+ }
131
+ })
132
+ })()
133
+ </script>
@@ -0,0 +1,5 @@
1
+ export { default as AuthGuard } from './AuthGuard.astro'
2
+
3
+ // Re-export core types for convenience
4
+ export type { User, AuthState, AuthConfig } from '@refraction-ui/auth'
5
+ export { createAuth } from '@refraction-ui/auth'
@@ -0,0 +1,22 @@
1
+ ---
2
+ import { createAvatar, avatarVariants, type AvatarSize } from '@refraction-ui/avatar'
3
+ import { cn } from '../shared/index.ts'
4
+
5
+ interface Props extends astroHTML.JSX.HTMLAttributes {
6
+ size?: AvatarSize
7
+ }
8
+
9
+ const { size = 'md', class: className, ...props } = Astro.props
10
+ const api = createAvatar({ size })
11
+ ---
12
+
13
+ <span
14
+ class={cn(avatarVariants({ size }), className)}
15
+ data-rfr-avatar
16
+ data-rfr-avatar-size={size}
17
+ {...api.ariaProps}
18
+ {...api.dataAttributes}
19
+ {...props}
20
+ >
21
+ <slot />
22
+ </span>
@@ -0,0 +1,18 @@
1
+ ---
2
+ import { avatarFallbackVariants, type AvatarSize } from '@refraction-ui/avatar'
3
+ import { cn } from '../shared/index.ts'
4
+
5
+ interface Props extends astroHTML.JSX.HTMLAttributes {
6
+ size?: AvatarSize
7
+ }
8
+
9
+ const { size = 'md', class: className, ...props } = Astro.props
10
+ ---
11
+
12
+ <span
13
+ class={cn(avatarFallbackVariants({ size }), className)}
14
+ data-rfr-avatar-fallback
15
+ {...props}
16
+ >
17
+ <slot />
18
+ </span>
@@ -0,0 +1,48 @@
1
+ ---
2
+ import { avatarImageVariants } from '@refraction-ui/avatar'
3
+ import { cn } from '../shared/index.ts'
4
+
5
+ interface Props extends astroHTML.JSX.HTMLAttributes {
6
+ src?: string
7
+ alt?: string
8
+ }
9
+
10
+ const { src, alt = '', class: className, ...props } = Astro.props
11
+ ---
12
+
13
+ <img
14
+ class={cn(avatarImageVariants(), className)}
15
+ src={src}
16
+ alt={alt}
17
+ data-rfr-avatar-image
18
+ {...props}
19
+ />
20
+
21
+ <script>
22
+ document.querySelectorAll('[data-rfr-avatar-image]').forEach((img) => {
23
+ const imgEl = img as HTMLImageElement
24
+ const parent = imgEl.closest('[data-rfr-avatar]')
25
+ const fallback = parent?.querySelector('[data-rfr-avatar-fallback]') as HTMLElement | null
26
+
27
+ // Handle already-loaded images (cached)
28
+ if (imgEl.complete && imgEl.naturalWidth > 0) {
29
+ imgEl.style.display = ''
30
+ if (fallback) fallback.style.display = 'none'
31
+ return
32
+ }
33
+
34
+ // Hide image until loaded
35
+ imgEl.style.display = 'none'
36
+ if (fallback) fallback.style.display = ''
37
+
38
+ imgEl.addEventListener('load', () => {
39
+ imgEl.style.display = ''
40
+ if (fallback) fallback.style.display = 'none'
41
+ })
42
+
43
+ imgEl.addEventListener('error', () => {
44
+ imgEl.style.display = 'none'
45
+ if (fallback) fallback.style.display = ''
46
+ })
47
+ })
48
+ </script>
@@ -0,0 +1 @@
1
+ export {}
@@ -0,0 +1,42 @@
1
+ ---
2
+ import {
3
+ createAvatarGroup,
4
+ avatarGroupStyles,
5
+ avatarVariants,
6
+ avatarOverflowBadgeVariants,
7
+ avatarImageStyles,
8
+ avatarPresenceDotVariants,
9
+ type AvatarUser,
10
+ type AvatarSize,
11
+ } from '@refraction-ui/avatar-group'
12
+ import { cn } from '../shared/index.ts'
13
+
14
+ interface Props extends astroHTML.JSX.HTMLAttributes {
15
+ users: AvatarUser[]
16
+ max?: number
17
+ size?: AvatarSize
18
+ }
19
+
20
+ const { users, max, size = 'md', class: className, ...props } = Astro.props
21
+ const api = createAvatarGroup({ users, max, size })
22
+ ---
23
+
24
+ <div class={cn(avatarGroupStyles, className)} {...api.ariaProps} {...props}>
25
+ {api.visibleUsers.map((user) => (
26
+ <div class={avatarVariants({ size })} {...api.getAvatarAriaProps(user)}>
27
+ {user.src ? (
28
+ <img src={user.src} alt={user.name} class={avatarImageStyles} />
29
+ ) : (
30
+ <span>{api.getInitials(user.name)}</span>
31
+ )}
32
+ {user.status && (
33
+ <span class={avatarPresenceDotVariants({ size, status: user.status })} />
34
+ )}
35
+ </div>
36
+ ))}
37
+ {api.overflowCount > 0 && (
38
+ <div class={avatarOverflowBadgeVariants({ size })} {...api.overflowBadgeProps}>
39
+ +{api.overflowCount}
40
+ </div>
41
+ )}
42
+ </div>
@@ -0,0 +1 @@
1
+ export {}
@@ -0,0 +1,27 @@
1
+ ---
2
+ import {
3
+ createBadge,
4
+ badgeVariants,
5
+ type BadgeVariant,
6
+ type BadgeSize,
7
+ } from '@refraction-ui/badge'
8
+ import { cn } from '../shared/index.ts'
9
+
10
+ interface Props extends astroHTML.JSX.HTMLAttributes {
11
+ variant?: BadgeVariant
12
+ size?: BadgeSize
13
+ }
14
+
15
+ const { variant, size, class: className, ...props } = Astro.props
16
+ const api = createBadge({ variant, size })
17
+ const classes = cn(badgeVariants({ variant, size }), className)
18
+ ---
19
+
20
+ <div
21
+ class={classes}
22
+ {...api.ariaProps}
23
+ {...api.dataAttributes}
24
+ {...props}
25
+ >
26
+ <slot />
27
+ </div>
@@ -0,0 +1 @@
1
+ export {}
@@ -0,0 +1,40 @@
1
+ ---
2
+ import {
3
+ createBottomNav,
4
+ bottomNavVariants,
5
+ bottomNavTabVariants,
6
+ type NavTab,
7
+ } from '@refraction-ui/bottom-nav'
8
+ import { cn } from '../shared/index.ts'
9
+
10
+ interface Props extends astroHTML.JSX.HTMLAttributes {
11
+ tabs?: NavTab[]
12
+ currentPath?: string
13
+ }
14
+
15
+ const { tabs = [], currentPath, class: className, ...props } = Astro.props
16
+ const api = createBottomNav({ tabs, currentPath })
17
+ const classes = cn(bottomNavVariants(), className)
18
+ ---
19
+
20
+ <nav class={classes} {...api.ariaProps} {...props}>
21
+ <div class="flex">
22
+ {tabs.map((tab) => {
23
+ const active = api.isActive(tab.href)
24
+ return (
25
+ <a
26
+ href={tab.href}
27
+ class={bottomNavTabVariants({ active: active ? 'true' : 'false' })}
28
+ {...api.tabAriaProps(tab.href)}
29
+ >
30
+ {tab.icon && (
31
+ <span aria-hidden="true">
32
+ {active && tab.activeIcon ? tab.activeIcon : tab.icon}
33
+ </span>
34
+ )}
35
+ <span>{tab.label}</span>
36
+ </a>
37
+ )
38
+ })}
39
+ </div>
40
+ </nav>
@@ -0,0 +1 @@
1
+ export {}