@refraction-ui/astro 0.4.2 → 0.4.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (334) hide show
  1. package/dist/accordion/index.ts +1 -0
  2. package/dist/ai/ai-manager.ts +121 -0
  3. package/dist/ai/index.ts +23 -0
  4. package/dist/ai/mock-providers.ts +68 -0
  5. package/dist/ai/sanitizer.ts +174 -0
  6. package/dist/ai/tts-manager.ts +80 -0
  7. package/dist/ai/types.ts +72 -0
  8. package/dist/animated-text/animated-text.styles.ts +28 -0
  9. package/dist/animated-text/animated-text.ts +83 -0
  10. package/dist/animated-text/index.ts +15 -0
  11. package/dist/app-shell/app-shell.ts +252 -0
  12. package/dist/app-shell/auth-shell.ts +84 -0
  13. package/dist/app-shell/index.ts +22 -0
  14. package/dist/app-shell/page-shell.ts +125 -0
  15. package/dist/astro-accordion/Button.astro +1 -1
  16. package/dist/astro-ai/index.ts +1 -1
  17. package/dist/astro-animated-text/AnimatedText.astro +1 -1
  18. package/dist/astro-animated-text/TypewriterText.astro +1 -1
  19. package/dist/astro-app-shell/AppShell.astro +1 -1
  20. package/dist/astro-app-shell/AuthShell.astro +1 -1
  21. package/dist/astro-app-shell/AuthShellCard.astro +1 -1
  22. package/dist/astro-app-shell/PageShell.astro +1 -1
  23. package/dist/astro-app-shell/PageShellSection.astro +1 -1
  24. package/dist/astro-app-shell/index.ts +1 -1
  25. package/dist/astro-auth/index.ts +2 -2
  26. package/dist/astro-avatar/Avatar.astro +1 -1
  27. package/dist/astro-avatar/AvatarFallback.astro +1 -1
  28. package/dist/astro-avatar/AvatarImage.astro +1 -1
  29. package/dist/astro-avatar-group/AvatarGroup.astro +1 -1
  30. package/dist/astro-badge/Badge.astro +1 -1
  31. package/dist/astro-bottom-nav/BottomNav.astro +1 -1
  32. package/dist/astro-breadcrumbs/Breadcrumbs.astro +1 -1
  33. package/dist/astro-button/Button.astro +1 -1
  34. package/dist/astro-calendar/Calendar.astro +1 -1
  35. package/dist/astro-card/Card.astro +1 -1
  36. package/dist/astro-card/CardContent.astro +1 -1
  37. package/dist/astro-card/CardDescription.astro +1 -1
  38. package/dist/astro-card/CardFooter.astro +1 -1
  39. package/dist/astro-card/CardHeader.astro +1 -1
  40. package/dist/astro-card/CardTitle.astro +1 -1
  41. package/dist/astro-card-grid/CardGrid.astro +1 -1
  42. package/dist/astro-carousel/Button.astro +1 -1
  43. package/dist/astro-charts/Bars.astro +1 -1
  44. package/dist/astro-charts/Chart.astro +1 -1
  45. package/dist/astro-charts/Circles.astro +1 -1
  46. package/dist/astro-charts/Histogram.astro +1 -1
  47. package/dist/astro-charts/Line.astro +1 -1
  48. package/dist/astro-charts/PieChart.astro +1 -1
  49. package/dist/astro-charts/ScatterPlot.astro +1 -1
  50. package/dist/astro-charts/index.ts +1 -1
  51. package/dist/astro-checkbox/Checkbox.astro +1 -1
  52. package/dist/astro-code-editor/CodeEditor.astro +1 -1
  53. package/dist/astro-collapsible/Collapsible.astro +1 -1
  54. package/dist/astro-collapsible/CollapsibleContent.astro +1 -1
  55. package/dist/astro-command/Command.astro +1 -1
  56. package/dist/astro-command/CommandGroup.astro +1 -1
  57. package/dist/astro-command/CommandInput.astro +1 -1
  58. package/dist/astro-command/CommandItem.astro +1 -1
  59. package/dist/astro-command-input/CommandInput.astro +1 -1
  60. package/dist/astro-content-protection/ContentProtection.astro +1 -1
  61. package/dist/astro-data-table/DataTable.astro +1 -1
  62. package/dist/astro-date-picker/DatePicker.astro +1 -1
  63. package/dist/astro-device-frame/DeviceFrame.astro +1 -1
  64. package/dist/astro-dialog/DialogContent.astro +1 -1
  65. package/dist/astro-dialog/DialogOverlay.astro +1 -1
  66. package/dist/astro-diff-viewer/DiffViewer.astro +1 -1
  67. package/dist/astro-dropdown-menu/DropdownMenuContent.astro +1 -1
  68. package/dist/astro-dropdown-menu/DropdownMenuItem.astro +1 -1
  69. package/dist/astro-emoji-picker/EmojiPicker.astro +1 -1
  70. package/dist/astro-feedback-dialog/FeedbackDialog.astro +1 -1
  71. package/dist/astro-file-upload/FileUpload.astro +1 -1
  72. package/dist/astro-footer/Footer.astro +1 -1
  73. package/dist/astro-inline-editor/InlineEditor.astro +1 -1
  74. package/dist/astro-input/Input.astro +1 -1
  75. package/dist/astro-input-group/InputGroup.astro +1 -1
  76. package/dist/astro-input-group/InputGroupAddon.astro +1 -1
  77. package/dist/astro-input-group/InputGroupButton.astro +1 -1
  78. package/dist/astro-install-prompt/InstallPrompt.astro +1 -1
  79. package/dist/astro-keyboard-shortcut/ShortcutBadge.astro +1 -1
  80. package/dist/astro-language-selector/LanguageSelector.astro +1 -1
  81. package/dist/astro-link-card/LinkCard.astro +1 -1
  82. package/dist/astro-markdown-renderer/MarkdownRenderer.astro +1 -1
  83. package/dist/astro-mobile-nav/MobileNav.astro +1 -1
  84. package/dist/astro-mobile-nav/MobileNavLink.astro +1 -1
  85. package/dist/astro-mobile-nav/MobileNavTrigger.astro +1 -1
  86. package/dist/astro-navbar/Navbar.astro +1 -1
  87. package/dist/astro-otp-input/OtpInput.astro +1 -1
  88. package/dist/astro-payment/Payment.astro +1 -1
  89. package/dist/astro-popover/PopoverContent.astro +1 -1
  90. package/dist/astro-presence-indicator/PresenceIndicator.astro +1 -1
  91. package/dist/astro-progress-display/BadgeDisplay.astro +1 -1
  92. package/dist/astro-progress-display/ProgressBar.astro +1 -1
  93. package/dist/astro-progress-display/StatsGrid.astro +1 -1
  94. package/dist/astro-radio/RadioGroup.astro +1 -1
  95. package/dist/astro-radio/RadioItem.astro +1 -1
  96. package/dist/astro-reaction-bar/ReactionBar.astro +1 -1
  97. package/dist/astro-resizable-layout/ResizableDivider.astro +1 -1
  98. package/dist/astro-resizable-layout/ResizableLayout.astro +1 -1
  99. package/dist/astro-resizable-layout/ResizablePane.astro +1 -1
  100. package/dist/astro-resizable-layout/index.ts +1 -1
  101. package/dist/astro-rich-editor/index.ts +2 -2
  102. package/dist/astro-search-bar/SearchBar.astro +1 -1
  103. package/dist/astro-search-bar/SearchResults.astro +1 -1
  104. package/dist/astro-select/Select.astro +1 -1
  105. package/dist/astro-select/SelectContent.astro +1 -1
  106. package/dist/astro-select/SelectItem.astro +1 -1
  107. package/dist/astro-select/SelectTrigger.astro +1 -1
  108. package/dist/astro-sidebar/Sidebar.astro +1 -1
  109. package/dist/astro-skeleton/Skeleton.astro +1 -1
  110. package/dist/astro-slide-viewer/SlideViewer.astro +1 -1
  111. package/dist/astro-status-indicator/StatusIndicator.astro +1 -1
  112. package/dist/astro-switch/Switch.astro +1 -1
  113. package/dist/astro-table-of-contents/TableOfContents.astro +1 -1
  114. package/dist/astro-tabs/Tabs.astro +1 -1
  115. package/dist/astro-tabs/TabsList.astro +1 -1
  116. package/dist/astro-tabs/TabsTrigger.astro +1 -1
  117. package/dist/astro-textarea/Textarea.astro +1 -1
  118. package/dist/astro-theme/ThemeScript.astro +1 -1
  119. package/dist/astro-thread-view/ThreadView.astro +1 -1
  120. package/dist/astro-toast/Toast.astro +1 -1
  121. package/dist/astro-tooltip/TooltipContent.astro +1 -1
  122. package/dist/astro-version-selector/VersionSelector.astro +1 -1
  123. package/dist/astro-video-player/VideoPlayer.astro +1 -1
  124. package/dist/auth/adapters/mock.ts +74 -0
  125. package/dist/auth/auth-machine.ts +120 -0
  126. package/dist/auth/index.ts +22 -0
  127. package/dist/auth/rbac.ts +44 -0
  128. package/dist/auth/types.ts +44 -0
  129. package/dist/avatar/avatar.styles.ts +47 -0
  130. package/dist/avatar/avatar.ts +73 -0
  131. package/dist/avatar/index.ts +15 -0
  132. package/dist/avatar-group/avatar-group.styles.ts +63 -0
  133. package/dist/avatar-group/avatar-group.ts +106 -0
  134. package/dist/avatar-group/index.ts +18 -0
  135. package/dist/badge/badge.styles.ts +24 -0
  136. package/dist/badge/badge.ts +48 -0
  137. package/dist/badge/index.ts +10 -0
  138. package/dist/bottom-nav/bottom-nav.styles.ts +18 -0
  139. package/dist/bottom-nav/bottom-nav.ts +33 -0
  140. package/dist/bottom-nav/index.ts +2 -0
  141. package/dist/breadcrumbs/breadcrumbs.styles.ts +20 -0
  142. package/dist/breadcrumbs/breadcrumbs.ts +72 -0
  143. package/dist/breadcrumbs/index.ts +8 -0
  144. package/dist/button/button.styles.ts +38 -0
  145. package/dist/button/button.ts +64 -0
  146. package/dist/button/index.ts +10 -0
  147. package/dist/calendar/calendar.styles.ts +21 -0
  148. package/dist/calendar/calendar.ts +202 -0
  149. package/dist/calendar/index.ts +9 -0
  150. package/dist/callout/callout.ts +1 -0
  151. package/dist/callout/index.ts +1 -0
  152. package/dist/card/card.styles.ts +55 -0
  153. package/dist/card/card.ts +45 -0
  154. package/dist/card/index.ts +20 -0
  155. package/dist/card-grid/card-grid.ts +9 -0
  156. package/dist/card-grid/index.ts +1 -0
  157. package/dist/carousel/index.ts +1 -0
  158. package/dist/charts/axis.ts +50 -0
  159. package/dist/charts/chart.ts +73 -0
  160. package/dist/charts/colorblind.ts +100 -0
  161. package/dist/charts/data.ts +72 -0
  162. package/dist/charts/geometry.ts +54 -0
  163. package/dist/charts/index.ts +61 -0
  164. package/dist/charts/scales.ts +151 -0
  165. package/dist/checkbox/checkbox.styles.ts +33 -0
  166. package/dist/checkbox/checkbox.ts +73 -0
  167. package/dist/checkbox/index.ts +10 -0
  168. package/dist/code-block/code-block.ts +1 -0
  169. package/dist/code-block/index.ts +1 -0
  170. package/dist/code-editor/code-editor.styles.ts +32 -0
  171. package/dist/code-editor/code-editor.ts +140 -0
  172. package/dist/code-editor/index.ts +9 -0
  173. package/dist/collapsible/collapsible.styles.ts +14 -0
  174. package/dist/collapsible/collapsible.ts +93 -0
  175. package/dist/collapsible/index.ts +7 -0
  176. package/dist/command/command.styles.ts +27 -0
  177. package/dist/command/command.ts +179 -0
  178. package/dist/command/index.ts +14 -0
  179. package/dist/command-input/command-input.ts +176 -0
  180. package/dist/command-input/index.ts +1 -0
  181. package/dist/content-protection/content-protection.styles.ts +9 -0
  182. package/dist/content-protection/content-protection.ts +68 -0
  183. package/dist/content-protection/index.ts +8 -0
  184. package/dist/data-table/data-table.styles.ts +55 -0
  185. package/dist/data-table/data-table.ts +183 -0
  186. package/dist/data-table/index.ts +15 -0
  187. package/dist/date-picker/date-picker.styles.ts +31 -0
  188. package/dist/date-picker/date-picker.ts +333 -0
  189. package/dist/date-picker/index.ts +18 -0
  190. package/dist/device-frame/device-frame.styles.ts +21 -0
  191. package/dist/device-frame/device-frame.ts +112 -0
  192. package/dist/device-frame/index.ts +10 -0
  193. package/dist/dialog/dialog.styles.ts +8 -0
  194. package/dist/dialog/dialog.ts +133 -0
  195. package/dist/dialog/index.ts +8 -0
  196. package/dist/diff-viewer/diff-viewer.styles.ts +124 -0
  197. package/dist/diff-viewer/diff-viewer.ts +255 -0
  198. package/dist/diff-viewer/index.ts +20 -0
  199. package/dist/dropdown-menu/dropdown-menu.styles.ts +9 -0
  200. package/dist/dropdown-menu/dropdown-menu.ts +139 -0
  201. package/dist/dropdown-menu/index.ts +9 -0
  202. package/dist/emoji-picker/emoji-data.ts +282 -0
  203. package/dist/emoji-picker/emoji-picker.styles.ts +32 -0
  204. package/dist/emoji-picker/emoji-picker.ts +165 -0
  205. package/dist/emoji-picker/index.ts +25 -0
  206. package/dist/feedback-dialog/feedback-dialog.styles.ts +15 -0
  207. package/dist/feedback-dialog/feedback-dialog.ts +147 -0
  208. package/dist/feedback-dialog/index.ts +11 -0
  209. package/dist/file-upload/file-upload.styles.ts +30 -0
  210. package/dist/file-upload/file-upload.ts +260 -0
  211. package/dist/file-upload/index.ts +19 -0
  212. package/dist/footer/footer.styles.ts +5 -0
  213. package/dist/footer/footer.ts +32 -0
  214. package/dist/footer/index.ts +9 -0
  215. package/dist/index.ts +1 -1
  216. package/dist/inline-editor/index.ts +13 -0
  217. package/dist/inline-editor/inline-editor.styles.ts +42 -0
  218. package/dist/inline-editor/inline-editor.ts +96 -0
  219. package/dist/input/index.ts +9 -0
  220. package/dist/input/input.styles.ts +15 -0
  221. package/dist/input/input.ts +84 -0
  222. package/dist/input-group/index.ts +13 -0
  223. package/dist/input-group/input-group.styles.ts +50 -0
  224. package/dist/input-group/input-group.ts +44 -0
  225. package/dist/install-prompt/index.ts +9 -0
  226. package/dist/install-prompt/install-prompt.styles.ts +5 -0
  227. package/dist/install-prompt/install-prompt.ts +68 -0
  228. package/dist/keyboard-shortcut/index.ts +12 -0
  229. package/dist/keyboard-shortcut/keyboard-shortcut.styles.ts +8 -0
  230. package/dist/keyboard-shortcut/keyboard-shortcut.ts +153 -0
  231. package/dist/language-selector/index.ts +8 -0
  232. package/dist/language-selector/language-selector.styles.ts +28 -0
  233. package/dist/language-selector/language-selector.ts +149 -0
  234. package/dist/link-card/index.ts +1 -0
  235. package/dist/link-card/link-card.ts +9 -0
  236. package/dist/markdown-renderer/index.ts +8 -0
  237. package/dist/markdown-renderer/markdown-renderer.styles.ts +31 -0
  238. package/dist/markdown-renderer/markdown-renderer.ts +251 -0
  239. package/dist/mobile-nav/index.ts +14 -0
  240. package/dist/mobile-nav/mobile-nav.styles.ts +39 -0
  241. package/dist/mobile-nav/mobile-nav.ts +74 -0
  242. package/dist/navbar/index.ts +9 -0
  243. package/dist/navbar/navbar.styles.ts +29 -0
  244. package/dist/navbar/navbar.ts +39 -0
  245. package/dist/otp-input/index.ts +13 -0
  246. package/dist/otp-input/otp-input.styles.ts +51 -0
  247. package/dist/otp-input/otp-input.ts +198 -0
  248. package/dist/pagination/index.ts +1 -0
  249. package/dist/payment/index.ts +1 -0
  250. package/dist/payment/payment.ts +16 -0
  251. package/dist/popover/index.ts +7 -0
  252. package/dist/popover/popover.styles.ts +16 -0
  253. package/dist/popover/popover.ts +89 -0
  254. package/dist/presence-indicator/index.ts +14 -0
  255. package/dist/presence-indicator/presence-indicator.styles.ts +29 -0
  256. package/dist/presence-indicator/presence-indicator.ts +63 -0
  257. package/dist/progress-display/index.ts +15 -0
  258. package/dist/progress-display/progress-display.styles.ts +72 -0
  259. package/dist/progress-display/progress-display.ts +60 -0
  260. package/dist/radio/index.ts +8 -0
  261. package/dist/radio/radio.styles.ts +34 -0
  262. package/dist/radio/radio.ts +70 -0
  263. package/dist/reaction-bar/index.ts +14 -0
  264. package/dist/reaction-bar/reaction-bar.styles.ts +23 -0
  265. package/dist/reaction-bar/reaction-bar.ts +87 -0
  266. package/dist/resizable-layout/index.ts +12 -0
  267. package/dist/resizable-layout/resizable-layout.styles.ts +50 -0
  268. package/dist/resizable-layout/resizable-layout.ts +139 -0
  269. package/dist/rich-editor/editor.ts +342 -0
  270. package/dist/rich-editor/emoji.ts +175 -0
  271. package/dist/rich-editor/history.ts +79 -0
  272. package/dist/rich-editor/index.ts +106 -0
  273. package/dist/rich-editor/markdown-shortcuts.ts +248 -0
  274. package/dist/rich-editor/mentions.ts +162 -0
  275. package/dist/rich-editor/model.ts +206 -0
  276. package/dist/rich-editor/operations.ts +772 -0
  277. package/dist/rich-editor/selection.ts +157 -0
  278. package/dist/rich-editor/serialization.ts +711 -0
  279. package/dist/rich-editor/slash-commands.ts +212 -0
  280. package/dist/search-bar/index.ts +7 -0
  281. package/dist/search-bar/search-bar.styles.ts +29 -0
  282. package/dist/search-bar/search-bar.ts +130 -0
  283. package/dist/select/index.ts +13 -0
  284. package/dist/select/select.styles.ts +52 -0
  285. package/dist/select/select.ts +152 -0
  286. package/dist/sidebar/index.ts +9 -0
  287. package/dist/sidebar/sidebar.styles.ts +27 -0
  288. package/dist/sidebar/sidebar.ts +59 -0
  289. package/dist/skeleton/index.ts +8 -0
  290. package/dist/skeleton/skeleton.styles.ts +16 -0
  291. package/dist/skeleton/skeleton.ts +39 -0
  292. package/dist/skip-to-content/index.ts +1 -0
  293. package/dist/skip-to-content/skip-to-content.ts +1 -0
  294. package/dist/slide-viewer/index.ts +16 -0
  295. package/dist/slide-viewer/slide-viewer.styles.ts +57 -0
  296. package/dist/slide-viewer/slide-viewer.ts +152 -0
  297. package/dist/slider/index.ts +1 -0
  298. package/dist/slider/slider.ts +2 -0
  299. package/dist/status-indicator/index.ts +15 -0
  300. package/dist/status-indicator/status-indicator.styles.ts +41 -0
  301. package/dist/status-indicator/status-indicator.ts +66 -0
  302. package/dist/steps/index.ts +1 -0
  303. package/dist/steps/steps.ts +1 -0
  304. package/dist/switch/index.ts +7 -0
  305. package/dist/switch/switch.styles.ts +55 -0
  306. package/dist/switch/switch.ts +63 -0
  307. package/dist/table-of-contents/index.ts +1 -0
  308. package/dist/table-of-contents/table-of-contents.ts +37 -0
  309. package/dist/tabs/index.ts +8 -0
  310. package/dist/tabs/tabs.styles.ts +9 -0
  311. package/dist/tabs/tabs.ts +133 -0
  312. package/dist/textarea/index.ts +7 -0
  313. package/dist/textarea/textarea.styles.ts +15 -0
  314. package/dist/textarea/textarea.ts +59 -0
  315. package/dist/theme/dom-adapters.ts +60 -0
  316. package/dist/theme/index.ts +18 -0
  317. package/dist/theme/theme-machine.ts +130 -0
  318. package/dist/theme/theme-script.ts +18 -0
  319. package/dist/thread-view/index.ts +26 -0
  320. package/dist/thread-view/thread-view.styles.ts +35 -0
  321. package/dist/thread-view/thread-view.ts +176 -0
  322. package/dist/toast/index.ts +13 -0
  323. package/dist/toast/toast.styles.ts +19 -0
  324. package/dist/toast/toast.ts +203 -0
  325. package/dist/tooltip/index.ts +7 -0
  326. package/dist/tooltip/tooltip.styles.ts +16 -0
  327. package/dist/tooltip/tooltip.ts +109 -0
  328. package/dist/version-selector/index.ts +12 -0
  329. package/dist/version-selector/version-selector.styles.ts +41 -0
  330. package/dist/version-selector/version-selector.ts +136 -0
  331. package/dist/video-player/index.ts +12 -0
  332. package/dist/video-player/video-player.styles.ts +42 -0
  333. package/dist/video-player/video-player.ts +100 -0
  334. package/package.json +1 -1
@@ -0,0 +1,25 @@
1
+ export {
2
+ createEmojiPicker,
3
+ type EmojiPickerProps,
4
+ type EmojiPickerState,
5
+ type EmojiPickerAPI,
6
+ } from './emoji-picker.js'
7
+
8
+ export {
9
+ EMOJI_DATA,
10
+ EMOJI_CATEGORIES,
11
+ CATEGORY_LABELS,
12
+ getAllEmojis,
13
+ type EmojiCategory,
14
+ type EmojiEntry,
15
+ } from './emoji-data.js'
16
+
17
+ export {
18
+ emojiPickerContainerStyles,
19
+ emojiPickerSearchStyles,
20
+ emojiPickerCategoryBarStyles,
21
+ emojiPickerCategoryTabVariants,
22
+ emojiPickerGridStyles,
23
+ emojiPickerEmojiButtonStyles,
24
+ emojiPickerSectionLabelStyles,
25
+ } from './emoji-picker.styles.js'
@@ -0,0 +1,15 @@
1
+ import { cva } from '../shared/index.ts'
2
+
3
+ export const feedbackDialogVariants = cva({
4
+ base: 'fixed left-1/2 top-1/2 z-50 w-full max-w-md -translate-x-1/2 -translate-y-1/2 rounded-lg border bg-background p-6 shadow-lg',
5
+ variants: {
6
+ type: {
7
+ text: 'max-w-md',
8
+ video: 'max-w-lg',
9
+ general: 'max-w-md',
10
+ },
11
+ },
12
+ defaultVariants: {
13
+ type: 'general',
14
+ },
15
+ })
@@ -0,0 +1,147 @@
1
+ import type { AccessibilityProps } from '../shared/index.ts'
2
+ import { createDialog, type DialogAPI } from '../dialog/index.ts'
3
+ import { generateId } from '../shared/index.ts'
4
+
5
+ export type FeedbackType = 'text' | 'video' | 'general'
6
+
7
+ export interface FeedbackDialogProps {
8
+ /** Whether the dialog is open (controlled) */
9
+ open?: boolean
10
+ /** Callback when open state changes */
11
+ onOpenChange?: (open: boolean) => void
12
+ /** Callback when feedback is submitted */
13
+ onSubmit?: (data: FeedbackData) => void | Promise<void>
14
+ /** Feedback type */
15
+ type?: FeedbackType
16
+ }
17
+
18
+ export interface FeedbackData {
19
+ comment: string
20
+ email?: string
21
+ type: FeedbackType
22
+ selectedText?: string
23
+ }
24
+
25
+ export interface FeedbackFormState {
26
+ comment: string
27
+ email: string
28
+ honeypot: string
29
+ }
30
+
31
+ export interface FeedbackDialogState {
32
+ open: boolean
33
+ isSubmitting: boolean
34
+ isSubmitted: boolean
35
+ }
36
+
37
+ export interface FeedbackDialogAPI {
38
+ /** Current state */
39
+ state: FeedbackDialogState
40
+ /** Dialog props from the underlying createDialog */
41
+ dialogProps: DialogAPI
42
+ /** Form field values */
43
+ formState: FeedbackFormState
44
+ /** Set a form field value */
45
+ setField(field: keyof FeedbackFormState, value: string): void
46
+ /** Submit the feedback form */
47
+ submit(): Promise<void>
48
+ /** Reset form to initial state */
49
+ reset(): void
50
+ /** ARIA props for the feedback dialog */
51
+ ariaProps: Partial<AccessibilityProps> & Record<string, unknown>
52
+ }
53
+
54
+ export function createFeedbackDialog(props: FeedbackDialogProps = {}): FeedbackDialogAPI {
55
+ const {
56
+ open: controlledOpen,
57
+ onOpenChange,
58
+ onSubmit,
59
+ type = 'general',
60
+ } = props
61
+
62
+ const dialog = createDialog({
63
+ open: controlledOpen,
64
+ onOpenChange,
65
+ modal: true,
66
+ })
67
+
68
+ let isSubmitting = false
69
+ let isSubmitted = false
70
+
71
+ const formState: FeedbackFormState = {
72
+ comment: '',
73
+ email: '',
74
+ honeypot: '',
75
+ }
76
+
77
+ const feedbackId = generateId('rfr-feedback')
78
+
79
+ function setField(field: keyof FeedbackFormState, value: string): void {
80
+ formState[field] = value
81
+ }
82
+
83
+ async function submit(): Promise<void> {
84
+ // Honeypot check — bots fill this hidden field
85
+ if (formState.honeypot) {
86
+ return
87
+ }
88
+
89
+ if (!formState.comment.trim()) {
90
+ return
91
+ }
92
+
93
+ isSubmitting = true
94
+
95
+ const data: FeedbackData = {
96
+ comment: formState.comment,
97
+ type,
98
+ ...(formState.email ? { email: formState.email } : {}),
99
+ }
100
+
101
+ try {
102
+ await onSubmit?.(data)
103
+ isSubmitting = false
104
+ isSubmitted = true
105
+ } catch {
106
+ isSubmitting = false
107
+ }
108
+ }
109
+
110
+ function reset(): void {
111
+ formState.comment = ''
112
+ formState.email = ''
113
+ formState.honeypot = ''
114
+ isSubmitting = false
115
+ isSubmitted = false
116
+ }
117
+
118
+ const ariaProps: Partial<AccessibilityProps> & Record<string, unknown> = {
119
+ role: 'dialog',
120
+ 'aria-modal': true,
121
+ 'aria-labelledby': `${feedbackId}-title`,
122
+ 'aria-describedby': `${feedbackId}-desc`,
123
+ id: feedbackId,
124
+ }
125
+
126
+ return {
127
+ get state() {
128
+ return {
129
+ get open() {
130
+ return dialog.state.open
131
+ },
132
+ get isSubmitting() {
133
+ return isSubmitting
134
+ },
135
+ get isSubmitted() {
136
+ return isSubmitted
137
+ },
138
+ }
139
+ },
140
+ dialogProps: dialog,
141
+ formState,
142
+ setField,
143
+ submit,
144
+ reset,
145
+ ariaProps,
146
+ }
147
+ }
@@ -0,0 +1,11 @@
1
+ export {
2
+ createFeedbackDialog,
3
+ type FeedbackType,
4
+ type FeedbackDialogProps,
5
+ type FeedbackData,
6
+ type FeedbackFormState,
7
+ type FeedbackDialogState,
8
+ type FeedbackDialogAPI,
9
+ } from './feedback-dialog.js'
10
+
11
+ export { feedbackDialogVariants } from './feedback-dialog.styles.js'
@@ -0,0 +1,30 @@
1
+ import { cva } from '../shared/index.ts'
2
+
3
+ export const fileUploadDropZoneVariants = cva({
4
+ base: 'flex flex-col items-center justify-center rounded-lg border-2 border-dashed p-8 text-center transition-colors cursor-pointer',
5
+ variants: {
6
+ state: {
7
+ idle: 'border-muted-foreground/25 hover:border-muted-foreground/50',
8
+ dragging: 'border-primary bg-primary/5',
9
+ disabled: 'opacity-50 cursor-not-allowed',
10
+ },
11
+ },
12
+ defaultVariants: {
13
+ state: 'idle',
14
+ },
15
+ })
16
+
17
+ export const fileUploadFileListStyles =
18
+ 'mt-4 space-y-2'
19
+
20
+ export const fileUploadFileItemStyles =
21
+ 'flex items-center gap-3 rounded-md border p-3 text-sm'
22
+
23
+ export const fileUploadProgressStyles =
24
+ 'h-1.5 w-full rounded-full bg-secondary overflow-hidden'
25
+
26
+ export const fileUploadProgressBarStyles =
27
+ 'h-full rounded-full bg-primary transition-all duration-300'
28
+
29
+ export const fileUploadRemoveButtonStyles =
30
+ 'ml-auto text-muted-foreground hover:text-foreground cursor-pointer'
@@ -0,0 +1,260 @@
1
+ import type { AccessibilityProps } from '../shared/index.ts'
2
+ import { generateId } from '../shared/index.ts'
3
+
4
+ export type FileStatus = 'pending' | 'uploading' | 'complete' | 'error'
5
+
6
+ export interface FileEntry {
7
+ /** Unique ID for this file entry */
8
+ id: string
9
+ /** Original file name */
10
+ name: string
11
+ /** File size in bytes */
12
+ size: number
13
+ /** MIME type */
14
+ type: string
15
+ /** Upload progress 0-100 */
16
+ progress: number
17
+ /** Current status */
18
+ status: FileStatus
19
+ /** Error message if status is 'error' */
20
+ error?: string
21
+ }
22
+
23
+ export interface FileUploadProps {
24
+ /** Accepted file types (e.g., 'image/*,.pdf') */
25
+ accept?: string
26
+ /** Max file size in bytes */
27
+ maxSize?: number
28
+ /** Max number of files */
29
+ maxFiles?: number
30
+ /** Allow multiple file selection */
31
+ multiple?: boolean
32
+ /** Callback when files are selected/added */
33
+ onFilesSelected?: (files: FileEntry[]) => void
34
+ /** Callback when a validation error occurs */
35
+ onError?: (errors: FileUploadError[]) => void
36
+ }
37
+
38
+ export interface FileUploadError {
39
+ file: string
40
+ code: 'type' | 'size' | 'count'
41
+ message: string
42
+ }
43
+
44
+ export interface FileUploadState {
45
+ files: FileEntry[]
46
+ isDragging: boolean
47
+ }
48
+
49
+ export interface FileUploadAPI {
50
+ /** Current state */
51
+ state: FileUploadState
52
+ /** Add files (validates type, size, count) */
53
+ addFiles(files: Array<{ name: string; size: number; type: string }>): void
54
+ /** Remove a file by ID */
55
+ removeFile(id: string): void
56
+ /** Update a file's progress */
57
+ updateProgress(id: string, progress: number): void
58
+ /** Set a file's status */
59
+ setStatus(id: string, status: FileStatus, error?: string): void
60
+ /** ARIA props for the drop zone */
61
+ dropZoneProps: Partial<AccessibilityProps> & Record<string, unknown>
62
+ /** ARIA props for the file input */
63
+ inputProps: Record<string, unknown>
64
+ /** Drag event handlers (for headless use) */
65
+ dragHandlers: {
66
+ onDragEnter(): void
67
+ onDragLeave(): void
68
+ onDragOver(): void
69
+ onDrop(): void
70
+ }
71
+ /** Generated IDs */
72
+ ids: {
73
+ dropZone: string
74
+ input: string
75
+ label: string
76
+ fileList: string
77
+ }
78
+ }
79
+
80
+ function matchesAccept(fileType: string, fileName: string, accept: string): boolean {
81
+ if (!accept) return true
82
+ const acceptedTypes = accept.split(',').map((t) => t.trim())
83
+ for (const accepted of acceptedTypes) {
84
+ if (accepted.startsWith('.')) {
85
+ // Extension match
86
+ if (fileName.toLowerCase().endsWith(accepted.toLowerCase())) return true
87
+ } else if (accepted.endsWith('/*')) {
88
+ // Wildcard MIME match (e.g., 'image/*')
89
+ const prefix = accepted.slice(0, -2)
90
+ if (fileType.startsWith(prefix)) return true
91
+ } else {
92
+ // Exact MIME match
93
+ if (fileType === accepted) return true
94
+ }
95
+ }
96
+ return false
97
+ }
98
+
99
+ export function formatFileSize(bytes: number): string {
100
+ if (bytes === 0) return '0 B'
101
+ const units = ['B', 'KB', 'MB', 'GB']
102
+ const i = Math.floor(Math.log(bytes) / Math.log(1024))
103
+ const size = bytes / Math.pow(1024, i)
104
+ return `${size.toFixed(i === 0 ? 0 : 1)} ${units[i]}`
105
+ }
106
+
107
+ export function createFileUpload(props: FileUploadProps = {}): FileUploadAPI {
108
+ const {
109
+ accept,
110
+ maxSize,
111
+ maxFiles,
112
+ multiple = false,
113
+ onFilesSelected,
114
+ onError,
115
+ } = props
116
+
117
+ let files: FileEntry[] = []
118
+ let isDragging = false
119
+
120
+ const dropZoneId = generateId('rfr-file-upload-zone')
121
+ const inputId = generateId('rfr-file-upload-input')
122
+ const labelId = generateId('rfr-file-upload-label')
123
+ const fileListId = generateId('rfr-file-upload-list')
124
+
125
+ function addFiles(incoming: Array<{ name: string; size: number; type: string }>): void {
126
+ const errors: FileUploadError[] = []
127
+ const validFiles: FileEntry[] = []
128
+
129
+ // Check count limit
130
+ const availableSlots = maxFiles ? maxFiles - files.length : Infinity
131
+ if (!multiple && incoming.length > 1) {
132
+ // Only take the first file if not multiple
133
+ incoming = [incoming[0]]
134
+ }
135
+
136
+ for (let i = 0; i < incoming.length; i++) {
137
+ const file = incoming[i]
138
+
139
+ if (validFiles.length >= availableSlots) {
140
+ errors.push({
141
+ file: file.name,
142
+ code: 'count',
143
+ message: `Maximum of ${maxFiles} files allowed`,
144
+ })
145
+ continue
146
+ }
147
+
148
+ // Validate type
149
+ if (accept && !matchesAccept(file.type, file.name, accept)) {
150
+ errors.push({
151
+ file: file.name,
152
+ code: 'type',
153
+ message: `File type "${file.type || 'unknown'}" is not accepted`,
154
+ })
155
+ continue
156
+ }
157
+
158
+ // Validate size
159
+ if (maxSize && file.size > maxSize) {
160
+ errors.push({
161
+ file: file.name,
162
+ code: 'size',
163
+ message: `File size ${formatFileSize(file.size)} exceeds limit of ${formatFileSize(maxSize)}`,
164
+ })
165
+ continue
166
+ }
167
+
168
+ validFiles.push({
169
+ id: generateId('rfr-file'),
170
+ name: file.name,
171
+ size: file.size,
172
+ type: file.type,
173
+ progress: 0,
174
+ status: 'pending',
175
+ })
176
+ }
177
+
178
+ if (errors.length > 0) {
179
+ onError?.(errors)
180
+ }
181
+
182
+ if (validFiles.length > 0) {
183
+ if (!multiple) {
184
+ files = validFiles.slice(0, 1)
185
+ } else {
186
+ files = [...files, ...validFiles]
187
+ }
188
+ onFilesSelected?.(files)
189
+ }
190
+ }
191
+
192
+ function removeFile(id: string): void {
193
+ files = files.filter((f) => f.id !== id)
194
+ }
195
+
196
+ function updateProgress(id: string, progress: number): void {
197
+ files = files.map((f) =>
198
+ f.id === id ? { ...f, progress: Math.min(100, Math.max(0, progress)) } : f,
199
+ )
200
+ }
201
+
202
+ function setStatus(id: string, status: FileStatus, error?: string): void {
203
+ files = files.map((f) =>
204
+ f.id === id ? { ...f, status, error, progress: status === 'complete' ? 100 : f.progress } : f,
205
+ )
206
+ }
207
+
208
+ const dropZoneProps: Partial<AccessibilityProps> & Record<string, unknown> = {
209
+ role: 'button',
210
+ 'aria-label': 'Drop files here or click to upload',
211
+ 'aria-describedby': labelId,
212
+ id: dropZoneId,
213
+ tabIndex: 0,
214
+ }
215
+
216
+ const inputProps: Record<string, unknown> = {
217
+ type: 'file',
218
+ id: inputId,
219
+ accept: accept ?? undefined,
220
+ multiple,
221
+ 'aria-hidden': true,
222
+ tabIndex: -1,
223
+ style: { display: 'none' },
224
+ }
225
+
226
+ const dragHandlers = {
227
+ onDragEnter() {
228
+ isDragging = true
229
+ },
230
+ onDragLeave() {
231
+ isDragging = false
232
+ },
233
+ onDragOver() {
234
+ isDragging = true
235
+ },
236
+ onDrop() {
237
+ isDragging = false
238
+ },
239
+ }
240
+
241
+ return {
242
+ state: {
243
+ get files() { return files },
244
+ get isDragging() { return isDragging },
245
+ },
246
+ addFiles,
247
+ removeFile,
248
+ updateProgress,
249
+ setStatus,
250
+ dropZoneProps,
251
+ inputProps,
252
+ dragHandlers,
253
+ ids: {
254
+ dropZone: dropZoneId,
255
+ input: inputId,
256
+ label: labelId,
257
+ fileList: fileListId,
258
+ },
259
+ }
260
+ }
@@ -0,0 +1,19 @@
1
+ export {
2
+ createFileUpload,
3
+ formatFileSize,
4
+ type FileUploadProps,
5
+ type FileUploadState,
6
+ type FileUploadAPI,
7
+ type FileUploadError,
8
+ type FileEntry,
9
+ type FileStatus,
10
+ } from './file-upload.js'
11
+
12
+ export {
13
+ fileUploadDropZoneVariants,
14
+ fileUploadFileListStyles,
15
+ fileUploadFileItemStyles,
16
+ fileUploadProgressStyles,
17
+ fileUploadProgressBarStyles,
18
+ fileUploadRemoveButtonStyles,
19
+ } from './file-upload.styles.js'
@@ -0,0 +1,5 @@
1
+ import { cva } from '../shared/index.ts'
2
+
3
+ export const footerVariants = cva({
4
+ base: 'border-t bg-background py-8',
5
+ })
@@ -0,0 +1,32 @@
1
+ export interface SocialLink {
2
+ label: string
3
+ href: string
4
+ icon?: string
5
+ }
6
+
7
+ export interface FooterColumn {
8
+ title: string
9
+ links: { label: string; href: string }[]
10
+ }
11
+
12
+ export interface FooterProps {
13
+ copyright?: string
14
+ socialLinks?: SocialLink[]
15
+ columns?: FooterColumn[]
16
+ }
17
+
18
+ export interface FooterAPI {
19
+ ariaProps: Record<string, string>
20
+ copyrightText: string
21
+ }
22
+
23
+ export function createFooter(props: FooterProps = {}): FooterAPI {
24
+ const { copyright } = props
25
+ const year = new Date().getFullYear()
26
+ const copyrightText = copyright ?? `© ${year} All rights reserved.`
27
+
28
+ return {
29
+ ariaProps: { role: 'contentinfo' },
30
+ copyrightText,
31
+ }
32
+ }
@@ -0,0 +1,9 @@
1
+ export {
2
+ createFooter,
3
+ type SocialLink,
4
+ type FooterColumn,
5
+ type FooterProps,
6
+ type FooterAPI,
7
+ } from './footer.js'
8
+
9
+ export { footerVariants } from './footer.styles.js'
package/dist/index.ts CHANGED
@@ -1,5 +1,6 @@
1
1
  // Auto-generated meta-package index
2
2
  export * from './astro-accordion/index.ts';
3
+ export * from './shared/index.ts';
3
4
  export * from './astro-ai/index.ts';
4
5
  export * from './astro-animated-text/index.ts';
5
6
  export * from './astro-app-shell/index.ts';
@@ -60,7 +61,6 @@ export * from './astro-toast/index.ts';
60
61
  export * from './astro-tooltip/index.ts';
61
62
  export * from './astro-version-selector/index.ts';
62
63
  export * from './astro-video-player/index.ts';
63
- export * from './shared/index.ts';
64
64
  export * from './astro-table-of-contents/index.ts';
65
65
  export * from './astro-carousel/index.ts';
66
66
  export * from './astro-slider/index.ts';
@@ -0,0 +1,13 @@
1
+ export {
2
+ createInlineEditor,
3
+ type InlineEditorProps,
4
+ type InlineEditorState,
5
+ type InlineEditorAPI,
6
+ type ToolbarAction,
7
+ } from './inline-editor.js'
8
+
9
+ export {
10
+ editorVariants,
11
+ toolbarVariants,
12
+ previewVariants,
13
+ } from './inline-editor.styles.js'
@@ -0,0 +1,42 @@
1
+ import { cva } from '../shared/index.ts'
2
+
3
+ export const editorVariants = cva({
4
+ base: 'w-full rounded-md border bg-background',
5
+ variants: {
6
+ state: {
7
+ viewing: 'cursor-pointer hover:bg-muted/50 p-3',
8
+ editing: 'p-0',
9
+ },
10
+ },
11
+ defaultVariants: {
12
+ state: 'viewing',
13
+ },
14
+ })
15
+
16
+ export const toolbarVariants = cva({
17
+ base: 'flex items-center gap-1 border-b px-2 py-1',
18
+ variants: {
19
+ size: {
20
+ sm: 'gap-0.5 px-1 py-0.5',
21
+ md: 'gap-1 px-2 py-1',
22
+ lg: 'gap-2 px-3 py-2',
23
+ },
24
+ },
25
+ defaultVariants: {
26
+ size: 'md',
27
+ },
28
+ })
29
+
30
+ export const previewVariants = cva({
31
+ base: 'prose prose-sm max-w-none p-3',
32
+ variants: {
33
+ size: {
34
+ sm: 'prose-xs p-2',
35
+ md: 'prose-sm p-3',
36
+ lg: 'prose-base p-4',
37
+ },
38
+ },
39
+ defaultVariants: {
40
+ size: 'md',
41
+ },
42
+ })