@refraction-ui/astro 0.4.2 → 0.4.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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,27 @@
1
+ import { cva } from '../shared/index.ts'
2
+
3
+ export const commandVariants = cva({
4
+ base: 'flex h-full w-full flex-col overflow-hidden rounded-md bg-popover text-popover-foreground',
5
+ })
6
+
7
+ export const commandInputVariants = cva({
8
+ base: 'flex h-11 w-full rounded-md bg-transparent py-3 text-sm outline-none placeholder:text-muted-foreground disabled:cursor-not-allowed disabled:opacity-50',
9
+ })
10
+
11
+ export const commandItemVariants = cva({
12
+ base: 'relative flex cursor-default select-none items-center rounded-sm px-2 py-1.5 text-sm outline-none',
13
+ variants: {
14
+ state: {
15
+ default: '',
16
+ selected: 'bg-accent text-accent-foreground',
17
+ disabled: 'pointer-events-none opacity-50',
18
+ },
19
+ },
20
+ defaultVariants: {
21
+ state: 'default',
22
+ },
23
+ })
24
+
25
+ export const commandGroupVariants = cva({
26
+ base: 'overflow-hidden p-1 text-foreground',
27
+ })
@@ -0,0 +1,179 @@
1
+ import type { KeyboardHandlerMap } from '../shared/index.ts'
2
+ import { Keys, generateId } from '../shared/index.ts'
3
+
4
+ export interface CommandProps {
5
+ /** Whether the command palette is open (controlled) */
6
+ open?: boolean
7
+ /** Callback when open state changes */
8
+ onOpenChange?: (open: boolean) => void
9
+ /** Custom filter function — receives item value and search query, returns true to include */
10
+ filter?: (value: string, search: string) => boolean
11
+ }
12
+
13
+ export interface CommandItemData {
14
+ /** Unique identifier for the item */
15
+ id: string
16
+ /** Display label */
17
+ label: string
18
+ /** Searchable value */
19
+ value: string
20
+ /** Whether the item is disabled */
21
+ disabled?: boolean
22
+ /** Optional group the item belongs to */
23
+ group?: string
24
+ }
25
+
26
+ export interface CommandState {
27
+ /** Current search query */
28
+ search: string
29
+ /** Items after filtering */
30
+ filteredItems: CommandItemData[]
31
+ /** Index of the currently highlighted item in filteredItems */
32
+ selectedIndex: number
33
+ /** Whether the palette is open */
34
+ open: boolean
35
+ }
36
+
37
+ export interface CommandAPI {
38
+ /** Current command state */
39
+ state: CommandState
40
+ /** Update the search query and re-filter items */
41
+ search(query: string): void
42
+ /** Select the item at the given index (or the currently highlighted item) */
43
+ select(index?: number): CommandItemData | undefined
44
+ /** Keyboard handlers for the command palette */
45
+ keyboardHandlers: KeyboardHandlerMap
46
+ /** ARIA attributes for the command root */
47
+ ariaProps: Record<string, unknown>
48
+ /** ARIA attributes for the input */
49
+ inputAriaProps: Record<string, unknown>
50
+ /** ARIA attributes for the list */
51
+ listAriaProps: Record<string, unknown>
52
+ /** Get ARIA attributes for a specific item */
53
+ getItemAriaProps(item: CommandItemData, index: number): Record<string, unknown>
54
+ /** Generated IDs */
55
+ ids: {
56
+ root: string
57
+ input: string
58
+ list: string
59
+ }
60
+ }
61
+
62
+ /** Default filter: case-insensitive includes */
63
+ function defaultFilter(value: string, search: string): boolean {
64
+ return value.toLowerCase().includes(search.toLowerCase())
65
+ }
66
+
67
+ export function createCommand(
68
+ props: CommandProps = {},
69
+ items: CommandItemData[] = [],
70
+ ): CommandAPI {
71
+ const {
72
+ open: controlledOpen,
73
+ onOpenChange,
74
+ filter = defaultFilter,
75
+ } = props
76
+
77
+ const rootId = generateId('rfr-cmd')
78
+ const inputId = generateId('rfr-cmd-input')
79
+ const listId = generateId('rfr-cmd-list')
80
+
81
+ let searchQuery = ''
82
+ let selectedIndex = 0
83
+ let filteredItems = [...items]
84
+ const isOpen = controlledOpen ?? true
85
+
86
+ function applyFilter(query: string): CommandItemData[] {
87
+ if (!query) return [...items]
88
+ return items.filter((item) => filter(item.value, query))
89
+ }
90
+
91
+ function doSearch(query: string): void {
92
+ searchQuery = query
93
+ filteredItems = applyFilter(query)
94
+ selectedIndex = 0
95
+ }
96
+
97
+ function doSelect(index?: number): CommandItemData | undefined {
98
+ const idx = index ?? selectedIndex
99
+ const item = filteredItems[idx]
100
+ if (!item || item.disabled) return undefined
101
+ return item
102
+ }
103
+
104
+ const keyboardHandlers: KeyboardHandlerMap = {
105
+ [Keys.ArrowDown]: (e) => {
106
+ e.preventDefault()
107
+ if (filteredItems.length > 0) {
108
+ selectedIndex = (selectedIndex + 1) % filteredItems.length
109
+ }
110
+ },
111
+ [Keys.ArrowUp]: (e) => {
112
+ e.preventDefault()
113
+ if (filteredItems.length > 0) {
114
+ selectedIndex = (selectedIndex - 1 + filteredItems.length) % filteredItems.length
115
+ }
116
+ },
117
+ [Keys.Enter]: (e) => {
118
+ e.preventDefault()
119
+ doSelect()
120
+ },
121
+ [Keys.Escape]: (e) => {
122
+ e.preventDefault()
123
+ onOpenChange?.(false)
124
+ },
125
+ }
126
+
127
+ const ariaProps: Record<string, unknown> = {
128
+ role: 'combobox',
129
+ 'aria-expanded': isOpen,
130
+ 'aria-haspopup': 'listbox',
131
+ 'aria-owns': listId,
132
+ id: rootId,
133
+ }
134
+
135
+ const inputAriaProps: Record<string, unknown> = {
136
+ role: 'searchbox',
137
+ 'aria-autocomplete': 'list',
138
+ 'aria-controls': listId,
139
+ id: inputId,
140
+ }
141
+
142
+ const listAriaProps: Record<string, unknown> = {
143
+ role: 'listbox',
144
+ id: listId,
145
+ 'aria-label': 'Command suggestions',
146
+ }
147
+
148
+ function getItemAriaProps(item: CommandItemData, index: number): Record<string, unknown> {
149
+ return {
150
+ role: 'option',
151
+ 'aria-selected': index === selectedIndex,
152
+ 'aria-disabled': item.disabled ?? false,
153
+ id: `${listId}-item-${item.id}`,
154
+ }
155
+ }
156
+
157
+ return {
158
+ get state(): CommandState {
159
+ return {
160
+ search: searchQuery,
161
+ filteredItems,
162
+ selectedIndex,
163
+ open: isOpen,
164
+ }
165
+ },
166
+ search: doSearch,
167
+ select: doSelect,
168
+ keyboardHandlers,
169
+ ariaProps,
170
+ inputAriaProps,
171
+ listAriaProps,
172
+ getItemAriaProps,
173
+ ids: {
174
+ root: rootId,
175
+ input: inputId,
176
+ list: listId,
177
+ },
178
+ }
179
+ }
@@ -0,0 +1,14 @@
1
+ export {
2
+ createCommand,
3
+ type CommandProps,
4
+ type CommandItemData,
5
+ type CommandState,
6
+ type CommandAPI,
7
+ } from './command.js'
8
+
9
+ export {
10
+ commandVariants,
11
+ commandInputVariants,
12
+ commandItemVariants,
13
+ commandGroupVariants,
14
+ } from './command.styles.js'
@@ -0,0 +1,176 @@
1
+ export interface Trigger {
2
+ char: string;
3
+ pattern?: RegExp;
4
+ }
5
+
6
+ export interface CommandNode {
7
+ type: 'command';
8
+ trigger: string;
9
+ text: string;
10
+ }
11
+
12
+ export interface TextNode {
13
+ type: 'text';
14
+ text: string;
15
+ }
16
+
17
+ export type InputNode = TextNode | CommandNode;
18
+
19
+ export interface CommandInputState {
20
+ nodes: InputNode[];
21
+ rawText: string;
22
+ cursorPosition: number;
23
+ activeTrigger: Trigger | null;
24
+ activeCommandText: string | null;
25
+ }
26
+
27
+ export interface CommandInputOptions {
28
+ triggers: Trigger[];
29
+ onCommandTriggered?: (trigger: Trigger, text: string) => void;
30
+ onStateChange?: (state: CommandInputState) => void;
31
+ onCommandCommit?: (trigger: Trigger, text: string) => void;
32
+ onCommandCancel?: () => void;
33
+ }
34
+
35
+ export class CommandInput {
36
+ private state: CommandInputState = {
37
+ nodes: [],
38
+ rawText: '',
39
+ cursorPosition: 0,
40
+ activeTrigger: null,
41
+ activeCommandText: null,
42
+ };
43
+
44
+ private options: CommandInputOptions;
45
+
46
+ constructor(options: CommandInputOptions) {
47
+ this.options = { ...options };
48
+ }
49
+
50
+ public handleInput(text: string, cursorPosition: number): void {
51
+ this.state.rawText = text;
52
+ this.state.cursorPosition = cursorPosition;
53
+ this.parseInput();
54
+ this.notifyStateChange();
55
+ }
56
+
57
+ public handleKeyDown(key: string, event?: Event): void {
58
+ if (this.state.activeTrigger) {
59
+ if (key === 'Escape') {
60
+ if (event) event.preventDefault();
61
+ this.state.activeTrigger = null;
62
+ this.state.activeCommandText = null;
63
+ if (this.options.onCommandCancel) {
64
+ this.options.onCommandCancel();
65
+ }
66
+ this.notifyStateChange();
67
+ } else if (key === 'Enter') {
68
+ if (event) event.preventDefault();
69
+ const trigger = this.state.activeTrigger;
70
+ const text = this.state.activeCommandText || '';
71
+ this.state.activeTrigger = null;
72
+ this.state.activeCommandText = null;
73
+ if (this.options.onCommandCommit) {
74
+ this.options.onCommandCommit(trigger, text);
75
+ }
76
+ this.notifyStateChange();
77
+ }
78
+ }
79
+ }
80
+
81
+ public get value(): InputNode[] {
82
+ return this.state.nodes;
83
+ }
84
+
85
+ public getState(): CommandInputState {
86
+ return { ...this.state };
87
+ }
88
+
89
+ private parseInput() {
90
+ const { rawText, cursorPosition } = this.state;
91
+
92
+ this.state.activeTrigger = null;
93
+ this.state.activeCommandText = null;
94
+
95
+ for (let i = cursorPosition - 1; i >= 0; i--) {
96
+ const char = rawText[i];
97
+ const matchedTrigger = this.options.triggers.find((t) => t.char === char);
98
+
99
+ if (matchedTrigger) {
100
+ const isStartOfWord = i === 0 || /\\s/.test(rawText[i - 1]);
101
+ if (isStartOfWord) {
102
+ const commandText = rawText.slice(i + 1, cursorPosition);
103
+ if (!/\\s/.test(commandText)) {
104
+ let isValid = true;
105
+ if (matchedTrigger.pattern) {
106
+ isValid = matchedTrigger.pattern.test(commandText);
107
+ }
108
+ if (isValid) {
109
+ this.state.activeTrigger = matchedTrigger;
110
+ this.state.activeCommandText = commandText;
111
+
112
+ if (this.options.onCommandTriggered) {
113
+ this.options.onCommandTriggered(matchedTrigger, commandText);
114
+ }
115
+ }
116
+ }
117
+ }
118
+ break;
119
+ }
120
+
121
+ if (/\\s/.test(char)) {
122
+ break;
123
+ }
124
+ }
125
+
126
+ const nodes: InputNode[] = [];
127
+ if (this.options.triggers.length === 0) {
128
+ nodes.push({ type: 'text', text: rawText });
129
+ this.state.nodes = nodes;
130
+ return;
131
+ }
132
+
133
+ const triggerChars = this.options.triggers.map((t) => t.char.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\$&'));
134
+ const patternStr = `(^|\\\\s)(${triggerChars.join('|')})([^\\\\s]*)`;
135
+ const regex = new RegExp(patternStr, 'g');
136
+
137
+ let currentIndex = 0;
138
+ let match;
139
+
140
+ while ((match = regex.exec(rawText)) !== null) {
141
+ const precedingWhitespace = match[1];
142
+ const triggerChar = match[2];
143
+ const commandText = match[3];
144
+
145
+ const matchStart = match.index;
146
+ const triggerStart = matchStart + precedingWhitespace.length;
147
+
148
+ const triggerConfig = this.options.triggers.find(t => t.char === triggerChar);
149
+ let isValid = true;
150
+ if (triggerConfig?.pattern && commandText.length > 0) {
151
+ isValid = triggerConfig.pattern.test(commandText);
152
+ }
153
+
154
+ if (isValid) {
155
+ if (triggerStart > currentIndex) {
156
+ nodes.push({ type: 'text', text: rawText.slice(currentIndex, triggerStart) });
157
+ }
158
+
159
+ nodes.push({ type: 'command', trigger: triggerChar, text: commandText });
160
+ currentIndex = regex.lastIndex;
161
+ }
162
+ }
163
+
164
+ if (currentIndex < rawText.length) {
165
+ nodes.push({ type: 'text', text: rawText.slice(currentIndex) });
166
+ }
167
+
168
+ this.state.nodes = nodes;
169
+ }
170
+
171
+ private notifyStateChange() {
172
+ if (this.options.onStateChange) {
173
+ this.options.onStateChange({ ...this.state });
174
+ }
175
+ }
176
+ }
@@ -0,0 +1 @@
1
+ export * from './command-input'
@@ -0,0 +1,9 @@
1
+ import { cva } from '../shared/index.ts'
2
+
3
+ export const contentProtectionVariants = cva({
4
+ base: 'relative select-none',
5
+ })
6
+
7
+ export const watermarkVariants = cva({
8
+ base: 'pointer-events-none absolute inset-0 z-50 overflow-hidden',
9
+ })
@@ -0,0 +1,68 @@
1
+ export interface ContentProtectionProps {
2
+ /** Enable content protection. Default: true */
3
+ enabled?: boolean
4
+ /** Disable copy/cut. Default: true */
5
+ disableCopy?: boolean
6
+ /** Disable right-click context menu. Default: true */
7
+ disableContextMenu?: boolean
8
+ /** Watermark text overlay */
9
+ watermarkText?: string
10
+ }
11
+
12
+ export interface WatermarkConfig {
13
+ text: string
14
+ opacity: number
15
+ angle: number
16
+ }
17
+
18
+ export interface ContentProtectionAPI {
19
+ eventHandlers: {
20
+ onCopy?: (e: { preventDefault(): void }) => void
21
+ onCut?: (e: { preventDefault(): void }) => void
22
+ onContextMenu?: (e: { preventDefault(): void }) => void
23
+ onSelectStart?: (e: { preventDefault(): void }) => void
24
+ }
25
+ watermarkConfig: WatermarkConfig | null
26
+ dataAttributes: Record<string, string>
27
+ }
28
+
29
+ export function createContentProtection(
30
+ props: ContentProtectionProps = {},
31
+ ): ContentProtectionAPI {
32
+ const {
33
+ enabled = true,
34
+ disableCopy = true,
35
+ disableContextMenu = true,
36
+ watermarkText,
37
+ } = props
38
+
39
+ const eventHandlers: ContentProtectionAPI['eventHandlers'] = {}
40
+
41
+ if (enabled) {
42
+ if (disableCopy) {
43
+ const prevent = (e: { preventDefault(): void }) => e.preventDefault()
44
+ eventHandlers.onCopy = prevent
45
+ eventHandlers.onCut = prevent
46
+ eventHandlers.onSelectStart = prevent
47
+ }
48
+ if (disableContextMenu) {
49
+ eventHandlers.onContextMenu = (e: { preventDefault(): void }) =>
50
+ e.preventDefault()
51
+ }
52
+ }
53
+
54
+ const watermarkConfig: WatermarkConfig | null = watermarkText
55
+ ? { text: watermarkText, opacity: 0.08, angle: -45 }
56
+ : null
57
+
58
+ const dataAttributes: Record<string, string> = {}
59
+ if (enabled) {
60
+ dataAttributes['data-protected'] = 'true'
61
+ }
62
+
63
+ return {
64
+ eventHandlers,
65
+ watermarkConfig,
66
+ dataAttributes,
67
+ }
68
+ }
@@ -0,0 +1,8 @@
1
+ export {
2
+ createContentProtection,
3
+ type ContentProtectionProps,
4
+ type ContentProtectionAPI,
5
+ type WatermarkConfig,
6
+ } from './content-protection.js'
7
+
8
+ export { contentProtectionVariants, watermarkVariants } from './content-protection.styles.js'
@@ -0,0 +1,55 @@
1
+ import { cva } from '../shared/index.ts'
2
+
3
+ export const tableVariants = cva({
4
+ base: 'w-full caption-bottom text-sm border-collapse',
5
+ variants: {
6
+ size: {
7
+ sm: 'text-xs',
8
+ md: 'text-sm',
9
+ lg: 'text-base',
10
+ },
11
+ },
12
+ defaultVariants: {
13
+ size: 'md',
14
+ },
15
+ })
16
+
17
+ export const headerVariants = cva({
18
+ base: 'h-10 px-2 text-left align-middle font-medium text-muted-foreground border-b',
19
+ variants: {
20
+ sortable: {
21
+ true: 'cursor-pointer select-none hover:text-foreground',
22
+ false: '',
23
+ },
24
+ },
25
+ defaultVariants: {
26
+ sortable: 'false',
27
+ },
28
+ })
29
+
30
+ export const cellVariants = cva({
31
+ base: 'p-2 align-middle border-b',
32
+ variants: {
33
+ size: {
34
+ sm: 'p-1',
35
+ md: 'p-2',
36
+ lg: 'p-3',
37
+ },
38
+ },
39
+ defaultVariants: {
40
+ size: 'md',
41
+ },
42
+ })
43
+
44
+ export const rowVariants = cva({
45
+ base: 'border-b transition-colors hover:bg-muted/50',
46
+ variants: {
47
+ selected: {
48
+ true: 'bg-muted',
49
+ false: '',
50
+ },
51
+ },
52
+ defaultVariants: {
53
+ selected: 'false',
54
+ },
55
+ })