@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,123 @@
1
+ ---
2
+ import {
3
+ createCodeEditor,
4
+ codeEditorVariants,
5
+ type CodeEditorTheme,
6
+ } from '@refraction-ui/code-editor'
7
+ import { cn } from '../shared/index.ts'
8
+
9
+ interface Props extends astroHTML.JSX.HTMLAttributes {
10
+ value?: string
11
+ language?: string
12
+ readOnly?: boolean
13
+ theme?: CodeEditorTheme
14
+ placeholder?: string
15
+ /** Action button labels — click events are dispatched as custom events */
16
+ actions?: Array<{ label: string }>
17
+ }
18
+
19
+ const {
20
+ value = '',
21
+ language = 'plaintext',
22
+ readOnly = false,
23
+ theme = 'light',
24
+ placeholder,
25
+ actions,
26
+ class: className,
27
+ ...props
28
+ } = Astro.props
29
+
30
+ const api = createCodeEditor({ value, language, readOnly, theme })
31
+ const containerClasses = cn(codeEditorVariants({ theme }), className)
32
+ ---
33
+
34
+ <div
35
+ data-rfr-code-editor
36
+ class={containerClasses}
37
+ {...api.dataAttributes}
38
+ {...props}
39
+ >
40
+ <div class="flex items-center justify-between px-3 py-2 border-b bg-muted/50 text-xs text-muted-foreground">
41
+ <span data-rfr-code-editor-lang>{api.getLanguageLabel()}</span>
42
+ {actions && actions.length > 0 && (
43
+ <div class="flex gap-1" data-rfr-code-editor-actions>
44
+ {actions.map((action) => (
45
+ <button
46
+ type="button"
47
+ data-rfr-code-editor-action={action.label}
48
+ class="px-2 py-1 rounded text-xs hover:bg-muted transition-colors"
49
+ >
50
+ {action.label}
51
+ </button>
52
+ ))}
53
+ </div>
54
+ )}
55
+ </div>
56
+ <textarea
57
+ data-rfr-code-editor-textarea
58
+ value={value}
59
+ readonly={readOnly}
60
+ placeholder={placeholder}
61
+ class="flex-1 w-full p-4 bg-transparent resize-none outline-none font-mono min-h-[200px]"
62
+ spellcheck="false"
63
+ autocapitalize="off"
64
+ autocomplete="off"
65
+ autocorrect="off"
66
+ role={api.ariaProps.role}
67
+ aria-multiline={api.ariaProps['aria-multiline']}
68
+ aria-label={api.ariaProps['aria-label']}
69
+ aria-readonly={readOnly ? true : undefined}
70
+ />
71
+ </div>
72
+
73
+ <script>
74
+ function initCodeEditors() {
75
+ document.querySelectorAll<HTMLElement>('[data-rfr-code-editor]').forEach((root) => {
76
+ if (root.hasAttribute('data-rfr-code-editor-init')) return
77
+ root.setAttribute('data-rfr-code-editor-init', '')
78
+
79
+ const textarea = root.querySelector<HTMLTextAreaElement>('[data-rfr-code-editor-textarea]')
80
+ if (!textarea) return
81
+
82
+ // Dispatch change events when textarea value changes
83
+ textarea.addEventListener('input', () => {
84
+ root.dispatchEvent(
85
+ new CustomEvent('rfr-code-editor-change', {
86
+ detail: { value: textarea.value },
87
+ bubbles: true,
88
+ }),
89
+ )
90
+ })
91
+
92
+ // Tab key support: insert tab character instead of moving focus
93
+ textarea.addEventListener('keydown', (e) => {
94
+ if (e.key === 'Tab') {
95
+ e.preventDefault()
96
+ const start = textarea.selectionStart
97
+ const end = textarea.selectionEnd
98
+ const value = textarea.value
99
+ textarea.value = value.substring(0, start) + ' ' + value.substring(end)
100
+ textarea.selectionStart = textarea.selectionEnd = start + 2
101
+ textarea.dispatchEvent(new Event('input', { bubbles: true }))
102
+ }
103
+ })
104
+
105
+ // Action button click handlers
106
+ const actionBtns = root.querySelectorAll<HTMLButtonElement>('[data-rfr-code-editor-action]')
107
+ actionBtns.forEach((btn) => {
108
+ btn.addEventListener('click', () => {
109
+ const label = btn.getAttribute('data-rfr-code-editor-action')
110
+ root.dispatchEvent(
111
+ new CustomEvent('rfr-code-editor-action', {
112
+ detail: { label },
113
+ bubbles: true,
114
+ }),
115
+ )
116
+ })
117
+ })
118
+ })
119
+ }
120
+
121
+ initCodeEditors()
122
+ document.addEventListener('astro:after-swap', initCodeEditors)
123
+ </script>
@@ -0,0 +1 @@
1
+ export {}
@@ -0,0 +1,58 @@
1
+ ---
2
+ import { createCollapsible } from '@refraction-ui/collapsible'
3
+
4
+ interface Props extends astroHTML.JSX.HTMLAttributes {
5
+ open?: boolean
6
+ disabled?: boolean
7
+ }
8
+
9
+ const { open = false, disabled = false, class: className, ...props } = Astro.props
10
+ const api = createCollapsible({ open, disabled })
11
+ ---
12
+
13
+ <div
14
+ data-state={open ? 'open' : 'closed'}
15
+ data-disabled={disabled ? '' : undefined}
16
+ data-rfr-collapsible
17
+ data-rfr-collapsible-content-id={api.contentProps.id}
18
+ class={className}
19
+ {...props}
20
+ >
21
+ <slot />
22
+ </div>
23
+
24
+ <script>
25
+ document.querySelectorAll<HTMLElement>('[data-rfr-collapsible]').forEach((root) => {
26
+ const contentId = root.getAttribute('data-rfr-collapsible-content-id') || ''
27
+
28
+ root.addEventListener('click', (e) => {
29
+ const trigger = (e.target as HTMLElement).closest<HTMLButtonElement>('[data-rfr-collapsible-trigger]')
30
+ if (!trigger) return
31
+ if (trigger.disabled) return
32
+
33
+ const isOpen = root.getAttribute('data-state') === 'open'
34
+ const newOpen = !isOpen
35
+
36
+ root.setAttribute('data-state', newOpen ? 'open' : 'closed')
37
+ trigger.setAttribute('aria-expanded', String(newOpen))
38
+ trigger.setAttribute('data-state', newOpen ? 'open' : 'closed')
39
+
40
+ const content = root.querySelector('[data-rfr-collapsible-content]') as HTMLElement | null
41
+ if (content) {
42
+ content.setAttribute('data-state', newOpen ? 'open' : 'closed')
43
+ content.hidden = !newOpen
44
+ }
45
+
46
+ root.dispatchEvent(new CustomEvent('toggle', { detail: { open: newOpen } }))
47
+ })
48
+
49
+ root.addEventListener('keydown', (e) => {
50
+ const trigger = (e.target as HTMLElement).closest<HTMLButtonElement>('[data-rfr-collapsible-trigger]')
51
+ if (!trigger) return
52
+ if (e.key === 'Enter' || e.key === ' ') {
53
+ e.preventDefault()
54
+ trigger.click()
55
+ }
56
+ })
57
+ })
58
+ </script>
@@ -0,0 +1,21 @@
1
+ ---
2
+ import { collapsibleContentVariants } from '@refraction-ui/collapsible'
3
+ import { cn } from '../shared/index.ts'
4
+
5
+ interface Props extends astroHTML.JSX.HTMLAttributes {
6
+ open?: boolean
7
+ }
8
+
9
+ const { open = false, class: className, ...props } = Astro.props
10
+ ---
11
+
12
+ <div
13
+ role="region"
14
+ data-state={open ? 'open' : 'closed'}
15
+ data-rfr-collapsible-content
16
+ hidden={!open}
17
+ class={cn(collapsibleContentVariants({ state: open ? 'open' : 'closed' }), className)}
18
+ {...props}
19
+ >
20
+ <slot />
21
+ </div>
@@ -0,0 +1,17 @@
1
+ ---
2
+ interface Props extends astroHTML.JSX.HTMLAttributes {
3
+ disabled?: boolean
4
+ }
5
+
6
+ const { disabled, class: className, ...props } = Astro.props
7
+ ---
8
+
9
+ <button
10
+ type="button"
11
+ data-rfr-collapsible-trigger
12
+ disabled={disabled || undefined}
13
+ class={className}
14
+ {...props}
15
+ >
16
+ <slot />
17
+ </button>
@@ -0,0 +1 @@
1
+ export {}
@@ -0,0 +1,170 @@
1
+ ---
2
+ import { commandVariants } from '@refraction-ui/command'
3
+ import { cn } from '../shared/index.ts'
4
+
5
+ interface Props extends astroHTML.JSX.HTMLAttributes {
6
+ /** Whether the command palette is open */
7
+ open?: boolean
8
+ }
9
+
10
+ const { open = true, class: className, ...props } = Astro.props
11
+ ---
12
+
13
+ <div
14
+ data-rfr-command
15
+ data-rfr-command-open={open}
16
+ role="combobox"
17
+ aria-expanded={open}
18
+ aria-haspopup="listbox"
19
+ class={cn(commandVariants(), className)}
20
+ {...props}
21
+ >
22
+ <slot />
23
+ </div>
24
+
25
+ <script>
26
+ function initCommands() {
27
+ document.querySelectorAll<HTMLElement>('[data-rfr-command]').forEach((root) => {
28
+ if (root.hasAttribute('data-rfr-command-init')) return
29
+ root.setAttribute('data-rfr-command-init', '')
30
+
31
+ const input = root.querySelector<HTMLInputElement>('[data-rfr-command-input]')
32
+ const list = root.querySelector<HTMLElement>('[data-rfr-command-list]')
33
+ const emptyEl = root.querySelector<HTMLElement>('[data-rfr-command-empty]')
34
+
35
+ let selectedIndex = 0
36
+
37
+ function getItems(): HTMLElement[] {
38
+ return Array.from(root.querySelectorAll<HTMLElement>('[data-rfr-command-item]:not([data-disabled])'))
39
+ }
40
+
41
+ function getAllItems(): HTMLElement[] {
42
+ return Array.from(root.querySelectorAll<HTMLElement>('[data-rfr-command-item]'))
43
+ }
44
+
45
+ function updateSelection() {
46
+ const items = getItems()
47
+ items.forEach((item, i) => {
48
+ const isSelected = i === selectedIndex
49
+ item.setAttribute('aria-selected', String(isSelected))
50
+ item.setAttribute('data-selected', isSelected ? '' : 'false')
51
+ if (isSelected) {
52
+ item.scrollIntoView({ block: 'nearest' })
53
+ }
54
+ })
55
+ }
56
+
57
+ function filterItems() {
58
+ const query = (input?.value || '').toLowerCase()
59
+ const allItems = getAllItems()
60
+ let visibleCount = 0
61
+
62
+ // Track which groups have visible items
63
+ const groupsWithVisible = new Set<HTMLElement>()
64
+
65
+ allItems.forEach((item) => {
66
+ const value = (item.getAttribute('data-value') || item.textContent || '').toLowerCase()
67
+ const matches = !query || value.includes(query)
68
+ item.hidden = !matches
69
+ if (matches && !item.hasAttribute('data-disabled')) {
70
+ visibleCount++
71
+ }
72
+ if (matches) {
73
+ const group = item.closest<HTMLElement>('[data-rfr-command-group]')
74
+ if (group) groupsWithVisible.add(group)
75
+ }
76
+ })
77
+
78
+ // Show/hide groups based on whether they have visible items
79
+ root.querySelectorAll<HTMLElement>('[data-rfr-command-group]').forEach((group) => {
80
+ group.hidden = !groupsWithVisible.has(group)
81
+ })
82
+
83
+ // Show/hide empty state
84
+ if (emptyEl) {
85
+ emptyEl.hidden = visibleCount > 0 || !query
86
+ }
87
+
88
+ // Reset selection
89
+ selectedIndex = 0
90
+ updateSelection()
91
+ }
92
+
93
+ // Input filtering
94
+ input?.addEventListener('input', () => {
95
+ filterItems()
96
+ })
97
+
98
+ // Keyboard navigation
99
+ root.addEventListener('keydown', (e) => {
100
+ const items = getItems()
101
+ if (items.length === 0 && e.key !== 'Escape') return
102
+
103
+ switch (e.key) {
104
+ case 'ArrowDown': {
105
+ e.preventDefault()
106
+ if (items.length > 0) {
107
+ selectedIndex = (selectedIndex + 1) % items.length
108
+ updateSelection()
109
+ }
110
+ break
111
+ }
112
+ case 'ArrowUp': {
113
+ e.preventDefault()
114
+ if (items.length > 0) {
115
+ selectedIndex = (selectedIndex - 1 + items.length) % items.length
116
+ updateSelection()
117
+ }
118
+ break
119
+ }
120
+ case 'Enter': {
121
+ e.preventDefault()
122
+ const items = getItems()
123
+ const selected = items[selectedIndex]
124
+ if (selected) {
125
+ selected.click()
126
+ root.dispatchEvent(
127
+ new CustomEvent('rfr-command-select', {
128
+ detail: { value: selected.getAttribute('data-value') || selected.textContent?.trim() },
129
+ bubbles: true,
130
+ })
131
+ )
132
+ }
133
+ break
134
+ }
135
+ case 'Escape': {
136
+ e.preventDefault()
137
+ root.dispatchEvent(new CustomEvent('rfr-command-close', { bubbles: true }))
138
+ break
139
+ }
140
+ }
141
+ })
142
+
143
+ // Click on items
144
+ root.addEventListener('click', (e) => {
145
+ const item = (e.target as HTMLElement).closest<HTMLElement>('[data-rfr-command-item]')
146
+ if (item && !item.hasAttribute('data-disabled')) {
147
+ const items = getItems()
148
+ const index = items.indexOf(item)
149
+ if (index >= 0) {
150
+ selectedIndex = index
151
+ updateSelection()
152
+ }
153
+ root.dispatchEvent(
154
+ new CustomEvent('rfr-command-select', {
155
+ detail: { value: item.getAttribute('data-value') || item.textContent?.trim() },
156
+ bubbles: true,
157
+ })
158
+ )
159
+ }
160
+ })
161
+
162
+ // Initial state
163
+ if (emptyEl) emptyEl.hidden = true
164
+ updateSelection()
165
+ })
166
+ }
167
+
168
+ initCommands()
169
+ document.addEventListener('astro:after-swap', initCommands)
170
+ </script>
@@ -0,0 +1,17 @@
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
+ <div
10
+ data-rfr-command-empty
11
+ role="presentation"
12
+ hidden
13
+ class={cn('py-6 text-center text-sm', className)}
14
+ {...props}
15
+ >
16
+ <slot />
17
+ </div>
@@ -0,0 +1,25 @@
1
+ ---
2
+ import { commandGroupVariants } from '@refraction-ui/command'
3
+ import { cn } from '../shared/index.ts'
4
+
5
+ interface Props extends astroHTML.JSX.HTMLAttributes {
6
+ heading?: string
7
+ }
8
+
9
+ const { heading, class: className, ...props } = Astro.props
10
+ ---
11
+
12
+ <div
13
+ data-rfr-command-group
14
+ role="group"
15
+ aria-label={heading}
16
+ class={cn(commandGroupVariants(), className)}
17
+ {...props}
18
+ >
19
+ {heading && (
20
+ <div class="px-2 py-1.5 text-xs font-medium text-muted-foreground">
21
+ {heading}
22
+ </div>
23
+ )}
24
+ <slot />
25
+ </div>
@@ -0,0 +1,21 @@
1
+ ---
2
+ import { commandInputVariants } from '@refraction-ui/command'
3
+ import { cn } from '../shared/index.ts'
4
+
5
+ interface Props extends astroHTML.JSX.HTMLAttributes {
6
+ placeholder?: string
7
+ }
8
+
9
+ const { placeholder = 'Type a command or search...', class: className, ...props } = Astro.props
10
+ ---
11
+
12
+ <input
13
+ data-rfr-command-input
14
+ type="text"
15
+ role="searchbox"
16
+ aria-autocomplete="list"
17
+ aria-label="Command input"
18
+ placeholder={placeholder}
19
+ class={cn(commandInputVariants(), className)}
20
+ {...props}
21
+ />
@@ -0,0 +1,26 @@
1
+ ---
2
+ import { commandItemVariants } from '@refraction-ui/command'
3
+ import { cn } from '../shared/index.ts'
4
+
5
+ interface Props extends astroHTML.JSX.HTMLAttributes {
6
+ value?: string
7
+ disabled?: boolean
8
+ }
9
+
10
+ const { value, disabled = false, class: className, ...props } = Astro.props
11
+ const state = disabled ? 'disabled' : 'default'
12
+ ---
13
+
14
+ <div
15
+ data-rfr-command-item
16
+ data-value={value}
17
+ data-disabled={disabled ? '' : undefined}
18
+ role="option"
19
+ aria-selected="false"
20
+ aria-disabled={disabled}
21
+ tabindex={-1}
22
+ class={cn(commandItemVariants({ state }), className)}
23
+ {...props}
24
+ >
25
+ <slot />
26
+ </div>
@@ -0,0 +1,17 @@
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
+ <div
10
+ data-rfr-command-list
11
+ role="listbox"
12
+ aria-label="Command suggestions"
13
+ class={cn('max-h-[300px] overflow-y-auto overflow-x-hidden', className)}
14
+ {...props}
15
+ >
16
+ <slot />
17
+ </div>
@@ -0,0 +1,14 @@
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
+ <div
10
+ data-rfr-command-separator
11
+ role="separator"
12
+ class={cn('-mx-1 h-px bg-border', className)}
13
+ {...props}
14
+ />
@@ -0,0 +1 @@
1
+ export {}
@@ -0,0 +1,6 @@
1
+ ---
2
+ import { CommandInputCore } from '@refraction-ui/command-input';
3
+ ---
4
+ <div class="refraction-command-input">
5
+ <slot />
6
+ </div>
@@ -0,0 +1 @@
1
+ export { default as CommandInput } from './CommandInput.astro';
@@ -0,0 +1,104 @@
1
+ ---
2
+ import {
3
+ createContentProtection,
4
+ contentProtectionVariants,
5
+ watermarkVariants,
6
+ } from '@refraction-ui/content-protection'
7
+ import { cn } from '../shared/index.ts'
8
+
9
+ interface Props extends astroHTML.JSX.HTMLAttributes {
10
+ /** Enable content protection. Default: true */
11
+ enabled?: boolean
12
+ /** Disable copy/cut. Default: true */
13
+ disableCopy?: boolean
14
+ /** Disable right-click context menu. Default: true */
15
+ disableContextMenu?: boolean
16
+ /** Watermark text overlay */
17
+ watermarkText?: string
18
+ }
19
+
20
+ const {
21
+ enabled = true,
22
+ disableCopy = true,
23
+ disableContextMenu = true,
24
+ watermarkText,
25
+ class: className,
26
+ ...props
27
+ } = Astro.props
28
+
29
+ const api = createContentProtection({ enabled, disableCopy, disableContextMenu, watermarkText })
30
+ const classes = cn(contentProtectionVariants(), className)
31
+ ---
32
+
33
+ <div
34
+ data-rfr-content-protection
35
+ data-rfr-cp-enabled={enabled}
36
+ data-rfr-cp-disable-copy={disableCopy}
37
+ data-rfr-cp-disable-context-menu={disableContextMenu}
38
+ class={classes}
39
+ {...api.dataAttributes}
40
+ {...props}
41
+ >
42
+ <slot />
43
+ {api.watermarkConfig && (
44
+ <div
45
+ class={watermarkVariants()}
46
+ aria-hidden="true"
47
+ style={`opacity: ${api.watermarkConfig.opacity}; transform: rotate(${api.watermarkConfig.angle}deg);`}
48
+ >
49
+ <svg width="100%" height="100%">
50
+ <defs>
51
+ <pattern
52
+ id="rfr-watermark"
53
+ x="0"
54
+ y="0"
55
+ width="200"
56
+ height="200"
57
+ patternUnits="userSpaceOnUse"
58
+ patternTransform={`rotate(${api.watermarkConfig.angle})`}
59
+ >
60
+ <text
61
+ x="0"
62
+ y="100"
63
+ fill="currentColor"
64
+ font-size="16"
65
+ font-family="sans-serif"
66
+ >
67
+ {api.watermarkConfig.text}
68
+ </text>
69
+ </pattern>
70
+ </defs>
71
+ <rect width="100%" height="100%" fill="url(#rfr-watermark)" />
72
+ </svg>
73
+ </div>
74
+ )}
75
+ </div>
76
+
77
+ <script>
78
+ function initContentProtection() {
79
+ document.querySelectorAll<HTMLElement>('[data-rfr-content-protection]').forEach((el) => {
80
+ if (el.hasAttribute('data-rfr-cp-init')) return
81
+ el.setAttribute('data-rfr-cp-init', '')
82
+
83
+ const enabled = el.getAttribute('data-rfr-cp-enabled') !== 'false'
84
+ const disableCopy = el.getAttribute('data-rfr-cp-disable-copy') !== 'false'
85
+ const disableContextMenu = el.getAttribute('data-rfr-cp-disable-context-menu') !== 'false'
86
+
87
+ if (!enabled) return
88
+
89
+ if (disableCopy) {
90
+ const prevent = (e: Event) => e.preventDefault()
91
+ el.addEventListener('copy', prevent)
92
+ el.addEventListener('cut', prevent)
93
+ el.addEventListener('selectstart', prevent)
94
+ }
95
+
96
+ if (disableContextMenu) {
97
+ el.addEventListener('contextmenu', (e) => e.preventDefault())
98
+ }
99
+ })
100
+ }
101
+
102
+ initContentProtection()
103
+ document.addEventListener('astro:after-swap', initContentProtection)
104
+ </script>
@@ -0,0 +1 @@
1
+ export {}