@refraction-ui/astro 0.3.1 → 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 +22 -20
  246. package/src/index.ts +0 -92
@@ -0,0 +1,16 @@
1
+ ---
2
+ import { mobileNavLinkVariants } from '@refraction-ui/mobile-nav'
3
+ import { cn } from '../shared/index.ts'
4
+
5
+ interface Props extends astroHTML.JSX.AnchorHTMLAttributes {}
6
+
7
+ const { class: className, ...props } = Astro.props
8
+ ---
9
+
10
+ <a
11
+ role="menuitem"
12
+ class={cn(mobileNavLinkVariants(), className)}
13
+ {...props}
14
+ >
15
+ <slot />
16
+ </a>
@@ -0,0 +1,57 @@
1
+ ---
2
+ import { mobileNavTriggerVariants } from '@refraction-ui/mobile-nav'
3
+ import { cn } from '../shared/index.ts'
4
+
5
+ interface Props extends astroHTML.JSX.HTMLAttributes {}
6
+
7
+ const { class: className, ...props } = Astro.props
8
+ const hasChildren = Astro.slots.has('default')
9
+ ---
10
+
11
+ <button
12
+ type="button"
13
+ data-rfr-mobile-nav-trigger
14
+ aria-expanded="false"
15
+ aria-label="Toggle menu"
16
+ class={cn(mobileNavTriggerVariants(), className)}
17
+ {...props}
18
+ >
19
+ {hasChildren ? (
20
+ <slot />
21
+ ) : (
22
+ <Fragment>
23
+ <svg
24
+ data-rfr-mobile-nav-icon-closed
25
+ width="24"
26
+ height="24"
27
+ viewBox="0 0 24 24"
28
+ fill="none"
29
+ stroke="currentColor"
30
+ stroke-width="2"
31
+ stroke-linecap="round"
32
+ stroke-linejoin="round"
33
+ aria-hidden="true"
34
+ >
35
+ <line x1="4" y1="6" x2="20" y2="6" />
36
+ <line x1="4" y1="12" x2="20" y2="12" />
37
+ <line x1="4" y1="18" x2="20" y2="18" />
38
+ </svg>
39
+ <svg
40
+ data-rfr-mobile-nav-icon-open
41
+ hidden
42
+ width="24"
43
+ height="24"
44
+ viewBox="0 0 24 24"
45
+ fill="none"
46
+ stroke="currentColor"
47
+ stroke-width="2"
48
+ stroke-linecap="round"
49
+ stroke-linejoin="round"
50
+ aria-hidden="true"
51
+ >
52
+ <line x1="18" y1="6" x2="6" y2="18" />
53
+ <line x1="6" y1="6" x2="18" y2="18" />
54
+ </svg>
55
+ </Fragment>
56
+ )}
57
+ </button>
@@ -0,0 +1 @@
1
+ export {}
@@ -0,0 +1,49 @@
1
+ ---
2
+ import {
3
+ createNavbar,
4
+ navbarVariants,
5
+ navLinkVariants,
6
+ type NavLink,
7
+ type NavbarVariant,
8
+ } from '@refraction-ui/navbar'
9
+ import { cn } from '../shared/index.ts'
10
+
11
+ interface Props extends astroHTML.JSX.HTMLAttributes {
12
+ links?: NavLink[]
13
+ currentPath?: string
14
+ variant?: NavbarVariant
15
+ }
16
+
17
+ const { links = [], currentPath, variant, class: className, ...props } = Astro.props
18
+ const api = createNavbar({ links, currentPath, variant })
19
+ const classes = cn(navbarVariants({ variant }), className)
20
+ ---
21
+
22
+ <header class={classes} {...props}>
23
+ <nav
24
+ class="mx-auto flex h-14 max-w-7xl items-center justify-between px-4"
25
+ {...api.ariaProps}
26
+ >
27
+ <div class="flex-shrink-0">
28
+ <slot name="logo" />
29
+ </div>
30
+ <ul class="hidden items-center gap-6 md:flex">
31
+ {links.map((link) => (
32
+ <li>
33
+ <a
34
+ href={link.href}
35
+ class={navLinkVariants({
36
+ active: api.isActive(link.href) ? 'true' : 'false',
37
+ })}
38
+ {...api.linkAriaProps(link.href)}
39
+ >
40
+ {link.label}
41
+ </a>
42
+ </li>
43
+ ))}
44
+ </ul>
45
+ <div class="flex items-center gap-2">
46
+ <slot name="actions" />
47
+ </div>
48
+ </nav>
49
+ </header>
@@ -0,0 +1 @@
1
+ export {}
@@ -0,0 +1,253 @@
1
+ ---
2
+ import {
3
+ createOtpInput,
4
+ otpInputContainerVariants,
5
+ otpInputSlotVariants,
6
+ type OtpInputType,
7
+ } from '@refraction-ui/otp-input'
8
+ import { cn } from '../shared/index.ts'
9
+
10
+ interface Props extends astroHTML.JSX.HTMLAttributes {
11
+ /** Number of OTP slots */
12
+ length?: number
13
+ /** Initial OTP value */
14
+ value?: string
15
+ /** Auto-focus first slot */
16
+ autoFocus?: boolean
17
+ /** Input type: number or text */
18
+ type?: OtpInputType
19
+ /** Whether the input is disabled */
20
+ disabled?: boolean
21
+ /** Size variant */
22
+ size?: 'sm' | 'default' | 'lg'
23
+ /** Name attribute for the hidden form input */
24
+ name?: string
25
+ }
26
+
27
+ const {
28
+ length = 6,
29
+ value = '',
30
+ autoFocus = false,
31
+ type = 'number',
32
+ disabled = false,
33
+ size = 'default',
34
+ name,
35
+ class: className,
36
+ ...props
37
+ } = Astro.props
38
+
39
+ const api = createOtpInput({ length, value, autoFocus, type, disabled })
40
+ const slots = Array.from({ length }, (_, i) => ({
41
+ index: i,
42
+ value: value.charAt(i) || '',
43
+ slotProps: api.getSlotProps(i),
44
+ }))
45
+ ---
46
+
47
+ <div
48
+ data-rfr-otp
49
+ data-rfr-otp-length={length}
50
+ data-rfr-otp-type={type}
51
+ data-rfr-otp-disabled={disabled ? 'true' : 'false'}
52
+ data-rfr-otp-size={size}
53
+ data-rfr-otp-autofocus={autoFocus ? 'true' : 'false'}
54
+ class={cn(otpInputContainerVariants({ size }), className)}
55
+ role="group"
56
+ aria-label="One-time password input"
57
+ {...props}
58
+ >
59
+ {slots.map((slot) => (
60
+ <input
61
+ type="text"
62
+ class={cn(otpInputSlotVariants({
63
+ size,
64
+ focused: 'false',
65
+ filled: slot.value ? 'true' : 'false',
66
+ }))}
67
+ value={slot.value}
68
+ maxlength="1"
69
+ inputmode={type === 'number' ? 'numeric' : 'text'}
70
+ pattern={type === 'number' ? '[0-9]*' : undefined}
71
+ autocomplete={slot.index === 0 ? 'one-time-code' : 'off'}
72
+ disabled={disabled}
73
+ aria-label={`Digit ${slot.index + 1} of ${length}`}
74
+ data-rfr-otp-slot={slot.index}
75
+ data-slot="otp-slot"
76
+ />
77
+ ))}
78
+ <input
79
+ type="hidden"
80
+ data-rfr-otp-hidden
81
+ name={name}
82
+ value={value}
83
+ />
84
+ </div>
85
+
86
+ <script>
87
+ // Style class templates for dynamic updates
88
+ const SIZE_CLASSES: Record<string, { base: string; focused: string; filled: string }> = {
89
+ sm: {
90
+ base: 'relative flex items-center justify-center rounded-md border border-input bg-background text-center font-mono shadow-sm transition-all h-8 w-8 text-sm',
91
+ focused: 'ring-2 ring-ring ring-offset-background',
92
+ filled: 'border-primary',
93
+ },
94
+ default: {
95
+ base: 'relative flex items-center justify-center rounded-md border border-input bg-background text-center font-mono shadow-sm transition-all h-10 w-10 text-base',
96
+ focused: 'ring-2 ring-ring ring-offset-background',
97
+ filled: 'border-primary',
98
+ },
99
+ lg: {
100
+ base: 'relative flex items-center justify-center rounded-md border border-input bg-background text-center font-mono shadow-sm transition-all h-12 w-12 text-lg',
101
+ focused: 'ring-2 ring-ring ring-offset-background',
102
+ filled: 'border-primary',
103
+ },
104
+ }
105
+
106
+ function initOtpInputs() {
107
+ document.querySelectorAll<HTMLElement>('[data-rfr-otp]').forEach((root) => {
108
+ if (root.hasAttribute('data-rfr-otp-init')) return
109
+ root.setAttribute('data-rfr-otp-init', '')
110
+
111
+ const length = parseInt(root.getAttribute('data-rfr-otp-length') || '6', 10)
112
+ const type = root.getAttribute('data-rfr-otp-type') || 'number'
113
+ const isDisabled = root.getAttribute('data-rfr-otp-disabled') === 'true'
114
+ const size = root.getAttribute('data-rfr-otp-size') || 'default'
115
+ const sizeClasses = SIZE_CLASSES[size] || SIZE_CLASSES.default
116
+
117
+ const slots = root.querySelectorAll<HTMLInputElement>('[data-rfr-otp-slot]')
118
+ if (slots.length === 0) return
119
+
120
+ function updateSlotClasses(slot: HTMLInputElement, focused: boolean) {
121
+ const filled = slot.value !== ''
122
+ let cls = sizeClasses.base
123
+ if (focused) cls += ' ' + sizeClasses.focused
124
+ if (filled) cls += ' ' + sizeClasses.filled
125
+ slot.className = cls
126
+ }
127
+
128
+ const hiddenInput = root.querySelector<HTMLInputElement>('[data-rfr-otp-hidden]')
129
+
130
+ function dispatchChange() {
131
+ const values = Array.from(slots).map((s) => s.value)
132
+ const combined = values.join('')
133
+
134
+ // Sync hidden input for form submission
135
+ if (hiddenInput) {
136
+ hiddenInput.value = combined
137
+ }
138
+
139
+ root.dispatchEvent(new CustomEvent('rfr-otp-change', {
140
+ detail: { value: combined },
141
+ bubbles: true,
142
+ }))
143
+
144
+ // Check if complete
145
+ if (combined.length === length && !values.includes('')) {
146
+ root.dispatchEvent(new CustomEvent('rfr-otp-complete', {
147
+ detail: { value: combined },
148
+ bubbles: true,
149
+ }))
150
+ }
151
+ }
152
+
153
+ slots.forEach((slot, index) => {
154
+ // Input handler
155
+ slot.addEventListener('input', (e) => {
156
+ if (isDisabled) return
157
+ const inputValue = slot.value
158
+ let char = inputValue.slice(-1)
159
+
160
+ // Filter for number type
161
+ if (type === 'number') {
162
+ char = char.replace(/[^0-9]/g, '')
163
+ }
164
+
165
+ slot.value = char
166
+
167
+ updateSlotClasses(slot, true)
168
+ dispatchChange()
169
+
170
+ // Auto-advance to next input
171
+ if (char && index < length - 1) {
172
+ slots[index + 1].focus()
173
+ }
174
+ })
175
+
176
+ // Keydown handler
177
+ slot.addEventListener('keydown', (e) => {
178
+ if (isDisabled) return
179
+
180
+ if (e.key === 'Backspace') {
181
+ e.preventDefault()
182
+ if (slot.value) {
183
+ slot.value = ''
184
+ updateSlotClasses(slot, true)
185
+ dispatchChange()
186
+ } else if (index > 0) {
187
+ slots[index - 1].value = ''
188
+ updateSlotClasses(slots[index - 1], false)
189
+ slots[index - 1].focus()
190
+ dispatchChange()
191
+ }
192
+ }
193
+
194
+ if (e.key === 'ArrowLeft' && index > 0) {
195
+ e.preventDefault()
196
+ slots[index - 1].focus()
197
+ }
198
+
199
+ if (e.key === 'ArrowRight' && index < length - 1) {
200
+ e.preventDefault()
201
+ slots[index + 1].focus()
202
+ }
203
+ })
204
+
205
+ // Paste handler
206
+ slot.addEventListener('paste', (e) => {
207
+ if (isDisabled) return
208
+ e.preventDefault()
209
+ const pasteData = e.clipboardData?.getData('text') || ''
210
+ let chars = pasteData
211
+ if (type === 'number') {
212
+ chars = pasteData.replace(/[^0-9]/g, '')
213
+ }
214
+
215
+ for (let i = 0; i < length; i++) {
216
+ slots[i].value = chars.charAt(i) || ''
217
+ updateSlotClasses(slots[i], false)
218
+ }
219
+
220
+ dispatchChange()
221
+
222
+ // Focus the last filled or next empty
223
+ let lastFilled = -1
224
+ for (let i = length - 1; i >= 0; i--) {
225
+ if (slots[i].value !== '') { lastFilled = i; break }
226
+ }
227
+ const nextIndex = Math.min(lastFilled + 1, length - 1)
228
+ slots[nextIndex].focus()
229
+ })
230
+
231
+ // Focus/blur classes
232
+ slot.addEventListener('focus', () => {
233
+ updateSlotClasses(slot, true)
234
+ slot.setAttribute('data-focused', '')
235
+ })
236
+
237
+ slot.addEventListener('blur', () => {
238
+ updateSlotClasses(slot, false)
239
+ slot.removeAttribute('data-focused')
240
+ })
241
+ })
242
+
243
+ // Auto-focus first slot
244
+ const shouldAutoFocus = root.getAttribute('data-rfr-otp-autofocus') === 'true'
245
+ if (shouldAutoFocus && !isDisabled && slots.length > 0) {
246
+ slots[0].focus()
247
+ }
248
+ })
249
+ }
250
+
251
+ initOtpInputs()
252
+ document.addEventListener('astro:after-swap', initOtpInputs)
253
+ </script>
@@ -0,0 +1 @@
1
+ export {}
@@ -0,0 +1,3 @@
1
+ ---
2
+ ---
3
+ <div></div>
@@ -0,0 +1 @@
1
+ export {}
@@ -0,0 +1,19 @@
1
+ ---
2
+ import type { PaymentProps } from '@refraction-ui/payment';
3
+
4
+ interface Props extends PaymentProps {
5
+ stripeKey: string;
6
+ }
7
+
8
+ const { clientSecret, stripeKey } = Astro.props;
9
+ ---
10
+
11
+ <div class="refraction-payment" data-client-secret={clientSecret} data-stripe-key={stripeKey}>
12
+ <div id="payment-element-placeholder">Payment Element Placeholder (Astro)</div>
13
+ <button id="submit-payment">Pay</button>
14
+ </div>
15
+
16
+ <script>
17
+ // Basic initialization placeholder
18
+ console.log('Stripe initialized in Astro component.');
19
+ </script>
@@ -0,0 +1 @@
1
+ export {}
@@ -0,0 +1,87 @@
1
+ ---
2
+ import { cn } from '../shared/index.ts'
3
+
4
+ interface Props extends astroHTML.JSX.HTMLAttributes {
5
+ /** Whether the popover starts open */
6
+ defaultOpen?: boolean
7
+ }
8
+
9
+ const { defaultOpen = false, class: className, ...props } = Astro.props
10
+ ---
11
+
12
+ <div
13
+ data-rfr-popover
14
+ data-rfr-popover-default-open={defaultOpen}
15
+ data-state={defaultOpen ? 'open' : 'closed'}
16
+ class={cn('relative inline-block', className)}
17
+ {...props}
18
+ >
19
+ <slot />
20
+ </div>
21
+
22
+ <script>
23
+ function initPopovers() {
24
+ document.querySelectorAll<HTMLElement>('[data-rfr-popover]').forEach((root) => {
25
+ if (root.hasAttribute('data-rfr-popover-init')) return
26
+ root.setAttribute('data-rfr-popover-init', '')
27
+
28
+ const defaultOpen = root.getAttribute('data-rfr-popover-default-open') === 'true'
29
+ let isOpen = defaultOpen
30
+
31
+ const trigger = root.querySelector<HTMLElement>('[data-rfr-popover-trigger]')
32
+ const content = root.querySelector<HTMLElement>('[data-rfr-popover-content]')
33
+ const closeBtns = root.querySelectorAll<HTMLElement>('[data-rfr-popover-close]')
34
+
35
+ function setState(open: boolean) {
36
+ isOpen = open
37
+ const state = open ? 'open' : 'closed'
38
+ root.setAttribute('data-state', state)
39
+ trigger?.setAttribute('aria-expanded', String(open))
40
+ content?.setAttribute('data-state', state)
41
+
42
+ if (open) {
43
+ content?.removeAttribute('hidden')
44
+ content?.focus()
45
+ } else {
46
+ content?.setAttribute('hidden', '')
47
+ trigger?.focus()
48
+ }
49
+
50
+ root.dispatchEvent(new CustomEvent('rfr-popover-change', { detail: { open }, bubbles: true }))
51
+ }
52
+
53
+ // Trigger click
54
+ trigger?.addEventListener('click', () => setState(!isOpen))
55
+
56
+ // Close button clicks
57
+ closeBtns.forEach((btn) => {
58
+ btn.addEventListener('click', () => setState(false))
59
+ })
60
+
61
+ // Escape key
62
+ root.addEventListener('keydown', (e) => {
63
+ if (!isOpen) return
64
+ if (e.key === 'Escape') {
65
+ e.preventDefault()
66
+ setState(false)
67
+ }
68
+ })
69
+
70
+ // Click outside to close
71
+ document.addEventListener('click', (e) => {
72
+ if (!isOpen) return
73
+ if (!root.contains(e.target as Node)) {
74
+ setState(false)
75
+ }
76
+ })
77
+
78
+ // Set initial state
79
+ if (!defaultOpen) {
80
+ content?.setAttribute('hidden', '')
81
+ }
82
+ })
83
+ }
84
+
85
+ initPopovers()
86
+ document.addEventListener('astro:after-swap', initPopovers)
87
+ </script>
@@ -0,0 +1,16 @@
1
+ ---
2
+ import { cn } from '../shared/index.ts'
3
+
4
+ interface Props extends astroHTML.JSX.HTMLAttributes {}
5
+
6
+ const { class: className, ...props } = Astro.props
7
+ ---
8
+
9
+ <button
10
+ type="button"
11
+ data-rfr-popover-close
12
+ class={cn(className)}
13
+ {...props}
14
+ >
15
+ <slot />
16
+ </button>
@@ -0,0 +1,23 @@
1
+ ---
2
+ import { popoverContentVariants } from '@refraction-ui/popover'
3
+ import { cn } from '../shared/index.ts'
4
+ import type { Side } from '../shared/index.ts'
5
+
6
+ interface Props extends astroHTML.JSX.HTMLAttributes {
7
+ side?: Side
8
+ }
9
+
10
+ const { side = 'bottom', class: className, ...props } = Astro.props
11
+ ---
12
+
13
+ <div
14
+ data-rfr-popover-content
15
+ data-state="closed"
16
+ role="dialog"
17
+ tabindex="-1"
18
+ hidden
19
+ class={cn(popoverContentVariants({ side }), className)}
20
+ {...props}
21
+ >
22
+ <slot />
23
+ </div>
@@ -0,0 +1,18 @@
1
+ ---
2
+ import { cn } from '../shared/index.ts'
3
+
4
+ interface Props extends astroHTML.JSX.HTMLAttributes {}
5
+
6
+ const { class: className, ...props } = Astro.props
7
+ ---
8
+
9
+ <button
10
+ type="button"
11
+ data-rfr-popover-trigger
12
+ aria-haspopup="dialog"
13
+ aria-expanded="false"
14
+ class={cn(className)}
15
+ {...props}
16
+ >
17
+ <slot />
18
+ </button>
@@ -0,0 +1 @@
1
+ export {}
@@ -0,0 +1,26 @@
1
+ ---
2
+ import {
3
+ createPresence,
4
+ presenceDotVariants,
5
+ presenceContainerStyles,
6
+ presenceLabelStyles,
7
+ type PresenceStatus,
8
+ } from '@refraction-ui/presence-indicator'
9
+ import { cn } from '../shared/index.ts'
10
+
11
+ interface Props extends astroHTML.JSX.HTMLAttributes {
12
+ status: PresenceStatus
13
+ showLabel?: boolean
14
+ label?: string
15
+ size?: 'sm' | 'md' | 'lg'
16
+ }
17
+
18
+ const { status, showLabel = false, label, size = 'md', class: className, ...props } = Astro.props
19
+ const api = createPresence({ status, showLabel, label })
20
+ const classes = cn(presenceContainerStyles, className)
21
+ ---
22
+
23
+ <span class={classes} {...api.ariaProps} {...props}>
24
+ <span class={presenceDotVariants({ status, size })}></span>
25
+ {api.showLabel && <span class={presenceLabelStyles}>{api.label}</span>}
26
+ </span>
@@ -0,0 +1 @@
1
+ export {}
@@ -0,0 +1,33 @@
1
+ ---
2
+ import {
3
+ createProgressDisplay,
4
+ badgeGridVariants,
5
+ badgeItemVariants,
6
+ type BadgeData,
7
+ } from '@refraction-ui/progress-display'
8
+ import { cn } from '../shared/index.ts'
9
+
10
+ interface Props extends astroHTML.JSX.HTMLAttributes {
11
+ badges: BadgeData[]
12
+ }
13
+
14
+ const { badges, class: className, ...props } = Astro.props
15
+ const api = createProgressDisplay({ stats: [], badges })
16
+ ---
17
+
18
+ <div class={cn(badgeGridVariants(), className)} {...props}>
19
+ {api.badges.map((badge) => (
20
+ <div
21
+ class={badgeItemVariants({
22
+ state: badge.isUnlocked ? 'unlocked' : 'locked',
23
+ })}
24
+ {...api.getBadgeAriaProps(badge)}
25
+ >
26
+ <span class="text-3xl">{badge.icon}</span>
27
+ <span class="font-medium">{badge.name}</span>
28
+ {!badge.isUnlocked && (
29
+ <span class="text-xs text-muted-foreground">Locked</span>
30
+ )}
31
+ </div>
32
+ ))}
33
+ </div>
@@ -0,0 +1,27 @@
1
+ ---
2
+ import { progressBarVariants } from '@refraction-ui/progress-display'
3
+ import { cn } from '../shared/index.ts'
4
+
5
+ interface Props extends astroHTML.JSX.HTMLAttributes {
6
+ value: number
7
+ max?: number
8
+ size?: 'sm' | 'md' | 'lg'
9
+ }
10
+
11
+ const { value, max = 100, size, class: className, ...props } = Astro.props
12
+ const percent = Math.min(100, Math.max(0, (value / max) * 100))
13
+ ---
14
+
15
+ <div
16
+ class={cn(progressBarVariants({ size }), className)}
17
+ role="progressbar"
18
+ aria-valuenow={value}
19
+ aria-valuemin={0}
20
+ aria-valuemax={max}
21
+ {...props}
22
+ >
23
+ <div
24
+ class="h-full rounded-full bg-primary transition-all"
25
+ style={`width: ${percent}%`}
26
+ />
27
+ </div>