@opencosmos/ui 1.3.1

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 (260) hide show
  1. package/.claude/CLAUDE.md +239 -0
  2. package/README.md +161 -0
  3. package/dist/cli.mjs +151 -0
  4. package/dist/dates.d.mts +20 -0
  5. package/dist/dates.d.ts +20 -0
  6. package/dist/dates.js +240 -0
  7. package/dist/dates.js.map +1 -0
  8. package/dist/dates.mjs +203 -0
  9. package/dist/dates.mjs.map +1 -0
  10. package/dist/dnd.d.mts +126 -0
  11. package/dist/dnd.d.ts +126 -0
  12. package/dist/dnd.js +274 -0
  13. package/dist/dnd.js.map +1 -0
  14. package/dist/dnd.mjs +250 -0
  15. package/dist/dnd.mjs.map +1 -0
  16. package/dist/fontThemes-Dh8mtXES.d.mts +868 -0
  17. package/dist/fontThemes-Dh8mtXES.d.ts +868 -0
  18. package/dist/forms.d.mts +38 -0
  19. package/dist/forms.d.ts +38 -0
  20. package/dist/forms.js +198 -0
  21. package/dist/forms.js.map +1 -0
  22. package/dist/forms.mjs +159 -0
  23. package/dist/forms.mjs.map +1 -0
  24. package/dist/hooks-1b8WaQf1.d.mts +225 -0
  25. package/dist/hooks-CKW8vE9H.d.ts +225 -0
  26. package/dist/hooks.d.mts +3 -0
  27. package/dist/hooks.d.ts +3 -0
  28. package/dist/hooks.js +971 -0
  29. package/dist/hooks.js.map +1 -0
  30. package/dist/hooks.mjs +943 -0
  31. package/dist/hooks.mjs.map +1 -0
  32. package/dist/index-DscTIrZ2.d.mts +29 -0
  33. package/dist/index-DscTIrZ2.d.ts +29 -0
  34. package/dist/index.d.mts +3382 -0
  35. package/dist/index.d.ts +3382 -0
  36. package/dist/index.js +15146 -0
  37. package/dist/index.js.map +1 -0
  38. package/dist/index.mjs +14802 -0
  39. package/dist/index.mjs.map +1 -0
  40. package/dist/providers-CXPDMsl7.d.mts +30 -0
  41. package/dist/providers-Dn_Msjvz.d.ts +30 -0
  42. package/dist/providers.d.mts +3 -0
  43. package/dist/providers.d.ts +3 -0
  44. package/dist/providers.js +1885 -0
  45. package/dist/providers.js.map +1 -0
  46. package/dist/providers.mjs +1859 -0
  47. package/dist/providers.mjs.map +1 -0
  48. package/dist/tables.d.mts +10 -0
  49. package/dist/tables.d.ts +10 -0
  50. package/dist/tables.js +248 -0
  51. package/dist/tables.js.map +1 -0
  52. package/dist/tables.mjs +218 -0
  53. package/dist/tables.mjs.map +1 -0
  54. package/dist/tokens.d.mts +1065 -0
  55. package/dist/tokens.d.ts +1065 -0
  56. package/dist/tokens.js +2637 -0
  57. package/dist/tokens.js.map +1 -0
  58. package/dist/tokens.mjs +2555 -0
  59. package/dist/tokens.mjs.map +1 -0
  60. package/dist/utils-CIIM7dAC.d.ts +986 -0
  61. package/dist/utils-Cs04sxth.d.mts +986 -0
  62. package/dist/utils.d.mts +4 -0
  63. package/dist/utils.d.ts +4 -0
  64. package/dist/utils.js +874 -0
  65. package/dist/utils.js.map +1 -0
  66. package/dist/utils.mjs +806 -0
  67. package/dist/utils.mjs.map +1 -0
  68. package/dist/validation-Bj1ye-v_.d.mts +114 -0
  69. package/dist/validation-Bj1ye-v_.d.ts +114 -0
  70. package/dist/webgl.d.mts +104 -0
  71. package/dist/webgl.d.ts +104 -0
  72. package/dist/webgl.js +226 -0
  73. package/dist/webgl.js.map +1 -0
  74. package/dist/webgl.mjs +195 -0
  75. package/dist/webgl.mjs.map +1 -0
  76. package/package.json +267 -0
  77. package/src/cli.ts +206 -0
  78. package/src/component-registry.ts +183 -0
  79. package/src/components/actions/Button.test.tsx +61 -0
  80. package/src/components/actions/Button.tsx +70 -0
  81. package/src/components/actions/Link.tsx +78 -0
  82. package/src/components/actions/Magnetic.tsx +68 -0
  83. package/src/components/actions/Toggle.test.tsx +40 -0
  84. package/src/components/actions/Toggle.tsx +47 -0
  85. package/src/components/actions/ToggleGroup.tsx +70 -0
  86. package/src/components/actions/index.ts +5 -0
  87. package/src/components/backgrounds/FaultyTerminal.tsx +426 -0
  88. package/src/components/backgrounds/OrbBackground.tsx +424 -0
  89. package/src/components/backgrounds/WarpBackground.tsx +358 -0
  90. package/src/components/backgrounds/index.ts +3 -0
  91. package/src/components/blocks/Hero.tsx +142 -0
  92. package/src/components/blocks/social/OpenGraphCard.tsx +243 -0
  93. package/src/components/cursor/SplashCursor.tsx +1315 -0
  94. package/src/components/cursor/TargetCursor.tsx +187 -0
  95. package/src/components/cursor/index.ts +2 -0
  96. package/src/components/data-display/AspectImage.tsx +73 -0
  97. package/src/components/data-display/Avatar.test.tsx +35 -0
  98. package/src/components/data-display/Avatar.tsx +55 -0
  99. package/src/components/data-display/Badge.test.tsx +43 -0
  100. package/src/components/data-display/Badge.tsx +84 -0
  101. package/src/components/data-display/Brand.tsx +123 -0
  102. package/src/components/data-display/Calendar.tsx +70 -0
  103. package/src/components/data-display/Card.test.tsx +92 -0
  104. package/src/components/data-display/Card.tsx +115 -0
  105. package/src/components/data-display/Code.tsx +210 -0
  106. package/src/components/data-display/CollapsibleCodeBlock.tsx +238 -0
  107. package/src/components/data-display/DataTable.tsx +119 -0
  108. package/src/components/data-display/DescriptionList.tsx +41 -0
  109. package/src/components/data-display/GitHubIcon.tsx +44 -0
  110. package/src/components/data-display/Heading.test.tsx +36 -0
  111. package/src/components/data-display/Heading.tsx +83 -0
  112. package/src/components/data-display/StatCard.tsx +195 -0
  113. package/src/components/data-display/Table.tsx +133 -0
  114. package/src/components/data-display/Text.test.tsx +48 -0
  115. package/src/components/data-display/Text.tsx +144 -0
  116. package/src/components/data-display/Timeline.tsx +194 -0
  117. package/src/components/data-display/TreeView.tsx +226 -0
  118. package/src/components/data-display/Typewriter.tsx +119 -0
  119. package/src/components/data-display/VariableWeightText.tsx +130 -0
  120. package/src/components/data-display/index.ts +19 -0
  121. package/src/components/feedback/Alert.test.tsx +44 -0
  122. package/src/components/feedback/Alert.tsx +65 -0
  123. package/src/components/feedback/EmptyState.tsx +113 -0
  124. package/src/components/feedback/Progress.test.tsx +60 -0
  125. package/src/components/feedback/Progress.tsx +30 -0
  126. package/src/components/feedback/ProgressBar.tsx +158 -0
  127. package/src/components/feedback/Skeleton.test.tsx +39 -0
  128. package/src/components/feedback/Skeleton.tsx +45 -0
  129. package/src/components/feedback/Sonner.tsx +28 -0
  130. package/src/components/feedback/Spinner.test.tsx +33 -0
  131. package/src/components/feedback/Spinner.tsx +99 -0
  132. package/src/components/feedback/Stepper.tsx +307 -0
  133. package/src/components/feedback/Toast/Toast.tsx +243 -0
  134. package/src/components/feedback/Toast/index.ts +2 -0
  135. package/src/components/feedback/index.ts +9 -0
  136. package/src/components/forms/Checkbox.test.tsx +40 -0
  137. package/src/components/forms/Checkbox.tsx +31 -0
  138. package/src/components/forms/ColorPicker.tsx +118 -0
  139. package/src/components/forms/Combobox.tsx +96 -0
  140. package/src/components/forms/DragDrop.tsx +440 -0
  141. package/src/components/forms/FileUpload.tsx +252 -0
  142. package/src/components/forms/FilterButton.tsx +65 -0
  143. package/src/components/forms/Form.tsx +197 -0
  144. package/src/components/forms/Input.test.tsx +46 -0
  145. package/src/components/forms/Input.tsx +43 -0
  146. package/src/components/forms/InputOTP.tsx +81 -0
  147. package/src/components/forms/Label.test.tsx +20 -0
  148. package/src/components/forms/Label.tsx +25 -0
  149. package/src/components/forms/RadioGroup.tsx +51 -0
  150. package/src/components/forms/SearchBar.tsx +215 -0
  151. package/src/components/forms/Select.test.tsx +118 -0
  152. package/src/components/forms/Select.tsx +274 -0
  153. package/src/components/forms/Slider.tsx +29 -0
  154. package/src/components/forms/Switch.test.tsx +76 -0
  155. package/src/components/forms/Switch.tsx +30 -0
  156. package/src/components/forms/TextField.tsx +152 -0
  157. package/src/components/forms/Textarea.test.tsx +41 -0
  158. package/src/components/forms/Textarea.tsx +29 -0
  159. package/src/components/forms/ThemeSwitcher.tsx +290 -0
  160. package/src/components/forms/ThemeToggle.tsx +151 -0
  161. package/src/components/forms/index.ts +19 -0
  162. package/src/components/layout/Accordion.test.tsx +66 -0
  163. package/src/components/layout/Accordion.tsx +64 -0
  164. package/src/components/layout/AspectRatio.tsx +7 -0
  165. package/src/components/layout/Carousel.tsx +277 -0
  166. package/src/components/layout/Collapsible.test.tsx +40 -0
  167. package/src/components/layout/Collapsible.tsx +31 -0
  168. package/src/components/layout/Container.test.tsx +45 -0
  169. package/src/components/layout/Container.tsx +99 -0
  170. package/src/components/layout/CustomizerPanel.tsx +400 -0
  171. package/src/components/layout/DatePicker.tsx +57 -0
  172. package/src/components/layout/Footer/Footer.tsx +175 -0
  173. package/src/components/layout/Footer/index.ts +2 -0
  174. package/src/components/layout/GlassSurface.tsx +82 -0
  175. package/src/components/layout/Grid.test.tsx +31 -0
  176. package/src/components/layout/Grid.tsx +130 -0
  177. package/src/components/layout/Header/Header.tsx +450 -0
  178. package/src/components/layout/Header/index.ts +2 -0
  179. package/src/components/layout/PageLayout.tsx +180 -0
  180. package/src/components/layout/PageTemplate.tsx +158 -0
  181. package/src/components/layout/Resizable.tsx +48 -0
  182. package/src/components/layout/ScrollArea.tsx +53 -0
  183. package/src/components/layout/Separator.test.tsx +28 -0
  184. package/src/components/layout/Separator.tsx +29 -0
  185. package/src/components/layout/Sidebar.tsx +171 -0
  186. package/src/components/layout/Stack.test.tsx +41 -0
  187. package/src/components/layout/Stack.tsx +89 -0
  188. package/src/components/layout/glass-surface.css +60 -0
  189. package/src/components/layout/index.ts +18 -0
  190. package/src/components/motion/AnimatedBeam.tsx +159 -0
  191. package/src/components/navigation/Breadcrumb.test.tsx +57 -0
  192. package/src/components/navigation/Breadcrumb.tsx +119 -0
  193. package/src/components/navigation/Breadcrumbs.tsx +221 -0
  194. package/src/components/navigation/Command.tsx +159 -0
  195. package/src/components/navigation/Menubar.tsx +115 -0
  196. package/src/components/navigation/NavLink.tsx +55 -0
  197. package/src/components/navigation/NavigationMenu.tsx +125 -0
  198. package/src/components/navigation/Pagination.tsx +121 -0
  199. package/src/components/navigation/SecondaryNav.tsx +100 -0
  200. package/src/components/navigation/Tabs.test.tsx +47 -0
  201. package/src/components/navigation/Tabs.tsx +60 -0
  202. package/src/components/navigation/TertiaryNav.tsx +90 -0
  203. package/src/components/navigation/index.ts +10 -0
  204. package/src/components/overlays/AlertDialog.test.tsx +69 -0
  205. package/src/components/overlays/AlertDialog.tsx +166 -0
  206. package/src/components/overlays/ContextMenu.tsx +243 -0
  207. package/src/components/overlays/Dialog.test.tsx +79 -0
  208. package/src/components/overlays/Dialog.tsx +158 -0
  209. package/src/components/overlays/Drawer.tsx +128 -0
  210. package/src/components/overlays/Dropdown.tsx +253 -0
  211. package/src/components/overlays/DropdownMenu.tsx +242 -0
  212. package/src/components/overlays/HoverCard.tsx +32 -0
  213. package/src/components/overlays/Modal.tsx +250 -0
  214. package/src/components/overlays/NotificationCenter.tsx +364 -0
  215. package/src/components/overlays/Popover.test.tsx +40 -0
  216. package/src/components/overlays/Popover.tsx +46 -0
  217. package/src/components/overlays/Sheet.tsx +163 -0
  218. package/src/components/overlays/Tooltip.test.tsx +33 -0
  219. package/src/components/overlays/Tooltip.tsx +32 -0
  220. package/src/components/overlays/index.ts +12 -0
  221. package/src/dates.ts +2 -0
  222. package/src/dnd.ts +1 -0
  223. package/src/forms.ts +1 -0
  224. package/src/globals.css +187 -0
  225. package/src/hooks/index.ts +6 -0
  226. package/src/hooks/useForm.ts +247 -0
  227. package/src/hooks/useMotionPreference.test.ts +102 -0
  228. package/src/hooks/useMotionPreference.ts +78 -0
  229. package/src/hooks/useTheme.ts +58 -0
  230. package/src/hooks.ts +9 -0
  231. package/src/index.ts +168 -0
  232. package/src/lib/animations.ts +356 -0
  233. package/src/lib/breadcrumbs.ts +94 -0
  234. package/src/lib/colors.ts +493 -0
  235. package/src/lib/store/customizer.ts +482 -0
  236. package/src/lib/store/index.ts +3 -0
  237. package/src/lib/store/theme.ts +55 -0
  238. package/src/lib/syntax-parser/index.ts +50 -0
  239. package/src/lib/syntax-parser/patterns.ts +64 -0
  240. package/src/lib/syntax-parser/tokenizer.ts +117 -0
  241. package/src/lib/syntax-parser/types.ts +27 -0
  242. package/src/lib/utils.ts +6 -0
  243. package/src/lib/validation.ts +204 -0
  244. package/src/lib/webgl/Color.ts +11 -0
  245. package/src/lib/webgl/Mesh.ts +41 -0
  246. package/src/lib/webgl/Program.ts +118 -0
  247. package/src/lib/webgl/Renderer.ts +51 -0
  248. package/src/lib/webgl/Triangle.ts +27 -0
  249. package/src/lib/webgl/Vec3.ts +18 -0
  250. package/src/lib/webgl/index.ts +13 -0
  251. package/src/nativewind-env.d.ts +1 -0
  252. package/src/providers/ThemeProvider.tsx +461 -0
  253. package/src/providers/index.ts +1 -0
  254. package/src/providers.ts +7 -0
  255. package/src/tables.ts +1 -0
  256. package/src/test/setup.ts +39 -0
  257. package/src/theme.css +158 -0
  258. package/src/tokens.ts +7 -0
  259. package/src/utils.ts +12 -0
  260. package/src/webgl.ts +1 -0
@@ -0,0 +1,239 @@
1
+ # @thesage/ui — AI Context
2
+
3
+ > 100 accessible React components | Radix UI + Tailwind CSS | 3 themes | TypeScript strict mode | MIT
4
+
5
+ ## Install
6
+
7
+ ```bash
8
+ pnpm add @thesage/ui
9
+ ```
10
+
11
+ ## Provider Hierarchy (Required)
12
+
13
+ Wrap your app root in this exact order:
14
+
15
+ ```tsx
16
+ import { ThemeProvider, TooltipProvider } from '@thesage/ui/providers'
17
+ import { Toaster } from '@thesage/ui'
18
+ import '@thesage/ui/globals.css'
19
+
20
+ export default function RootLayout({ children }) {
21
+ return (
22
+ <ThemeProvider defaultTheme="studio" defaultMode="system">
23
+ <TooltipProvider>
24
+ {children}
25
+ <Toaster />
26
+ </TooltipProvider>
27
+ </ThemeProvider>
28
+ )
29
+ }
30
+ ```
31
+
32
+ ## Import Patterns
33
+
34
+ ```tsx
35
+ // Main exports (most common)
36
+ import { Button, Card, Input, Dialog, Badge } from '@thesage/ui'
37
+
38
+ // Subpath exports
39
+ import { useMotionPreference, useTheme } from '@thesage/ui/hooks'
40
+ import { ThemeProvider, TooltipProvider } from '@thesage/ui/providers'
41
+ import { cn } from '@thesage/ui/utils'
42
+ import { spacing, typography } from '@thesage/ui/tokens'
43
+
44
+ // Heavy/optional features (require peer dependencies)
45
+ import { Form, FormField, FormItem } from '@thesage/ui/forms' // react-hook-form + zod
46
+ import { Calendar, DatePicker } from '@thesage/ui/dates' // date-fns + react-day-picker
47
+ import { DataTable } from '@thesage/ui/tables' // @tanstack/react-table
48
+ import { DragDrop } from '@thesage/ui/dnd' // @dnd-kit/*
49
+ ```
50
+
51
+ ## Themes
52
+
53
+ Three themes, each with light and dark modes:
54
+ - **Studio** — Professional, balanced (default)
55
+ - **Terra** — Calm, organic, warm earth tones
56
+ - **Volt** — Bold, electric, cyberpunk neon
57
+
58
+ ```tsx
59
+ import { useTheme } from '@thesage/ui/hooks'
60
+ const { theme, setTheme, mode, setMode } = useTheme()
61
+ setTheme('volt')
62
+ setMode('dark')
63
+ ```
64
+
65
+ ## Styling Rules
66
+
67
+ - Use CSS variables: `bg-background`, `text-foreground`, `border-border`
68
+ - NEVER hardcode colors: no `bg-white`, `text-black`, `bg-neutral-100`
69
+ - All components accept `className` for Tailwind overrides
70
+ - Merge classes with `cn()`: `import { cn } from '@thesage/ui/utils'`
71
+
72
+ ## Motion
73
+
74
+ Every animation MUST respect user preferences:
75
+ ```tsx
76
+ import { useMotionPreference } from '@thesage/ui/hooks'
77
+ const { shouldAnimate, scale } = useMotionPreference()
78
+ ```
79
+
80
+ ## Component Categories
81
+
82
+ | Category | Count | Import | Examples |
83
+ |----------|-------|--------|----------|
84
+ | Actions | 5 | `@thesage/ui` | Button, Toggle, ToggleGroup, Link, Magnetic |
85
+ | Forms | 18 | `@thesage/ui` | Input, Textarea, Select, Checkbox, Switch, Slider, Combobox, RadioGroup, Label, SearchBar |
86
+ | Navigation | 7 | `@thesage/ui` | Tabs, Breadcrumb, Pagination, NavigationMenu, Menubar, Command |
87
+ | Overlays | 8 | `@thesage/ui` | Dialog, AlertDialog, Popover, Tooltip, HoverCard, ContextMenu, DropdownMenu, Drawer |
88
+ | Feedback | 6 | `@thesage/ui` | Alert, Toaster/toast, Progress, Skeleton, Spinner |
89
+ | Data Display | 14 | `@thesage/ui` | Card, Badge, Avatar, Table, Carousel, AspectRatio, Collapsible, CodeBlock |
90
+ | Layout | 8 | `@thesage/ui` | Accordion, Separator, ScrollArea, ResizablePanel, Sheet |
91
+ | Features | 3 | `@thesage/ui` | CustomizerPanel, ThemeSwitcher |
92
+
93
+ ## High-Frequency Component Quick Reference
94
+
95
+ ### Button
96
+ ```tsx
97
+ <Button variant="default|destructive|outline|secondary|ghost|link" size="sm|default|lg|icon">
98
+ Label
99
+ </Button>
100
+ ```
101
+
102
+ ### Card
103
+ ```tsx
104
+ <Card>
105
+ <CardHeader><CardTitle>Title</CardTitle><CardDescription>Desc</CardDescription></CardHeader>
106
+ <CardContent>Body</CardContent>
107
+ <CardFooter>Actions</CardFooter>
108
+ </Card>
109
+ ```
110
+
111
+ ### Dialog
112
+ ```tsx
113
+ <Dialog>
114
+ <DialogTrigger asChild><Button>Open</Button></DialogTrigger>
115
+ <DialogContent>
116
+ <DialogHeader><DialogTitle>Title</DialogTitle><DialogDescription>Desc</DialogDescription></DialogHeader>
117
+ Body
118
+ <DialogFooter><Button>Confirm</Button></DialogFooter>
119
+ </DialogContent>
120
+ </Dialog>
121
+ ```
122
+
123
+ ### Input
124
+ ```tsx
125
+ <Input type="email" placeholder="Enter email" disabled={false} />
126
+ ```
127
+
128
+ ### Select
129
+ ```tsx
130
+ <Select value={val} onValueChange={setVal}>
131
+ <SelectTrigger><SelectValue placeholder="Pick one" /></SelectTrigger>
132
+ <SelectContent>
133
+ <SelectItem value="a">Option A</SelectItem>
134
+ <SelectItem value="b">Option B</SelectItem>
135
+ </SelectContent>
136
+ </Select>
137
+ ```
138
+
139
+ ### Tabs
140
+ ```tsx
141
+ <Tabs defaultValue="tab1">
142
+ <TabsList>
143
+ <TabsTrigger value="tab1">Tab 1</TabsTrigger>
144
+ <TabsTrigger value="tab2">Tab 2</TabsTrigger>
145
+ </TabsList>
146
+ <TabsContent value="tab1">Content 1</TabsContent>
147
+ <TabsContent value="tab2">Content 2</TabsContent>
148
+ </Tabs>
149
+ ```
150
+
151
+ ### Badge
152
+ ```tsx
153
+ <Badge variant="default|secondary|destructive|outline">Label</Badge>
154
+ ```
155
+
156
+ ### Alert
157
+ ```tsx
158
+ <Alert variant="default|destructive">
159
+ <AlertTitle>Heading</AlertTitle>
160
+ <AlertDescription>Message</AlertDescription>
161
+ </Alert>
162
+ ```
163
+
164
+ ### Form (react-hook-form integration)
165
+ ```tsx
166
+ import { Form, FormField, FormItem, FormLabel, FormControl, FormMessage } from '@thesage/ui/forms'
167
+
168
+ <Form {...form}>
169
+ <FormField control={form.control} name="email" render={({ field }) => (
170
+ <FormItem>
171
+ <FormLabel>Email</FormLabel>
172
+ <FormControl><Input {...field} /></FormControl>
173
+ <FormMessage />
174
+ </FormItem>
175
+ )} />
176
+ </Form>
177
+ ```
178
+
179
+ ## Bundle Size (minified + brotli)
180
+
181
+ | Entrypoint | Size | Peer Deps Required |
182
+ |------------|------|--------------------|
183
+ | `@thesage/ui` (core) | 146 KB | None |
184
+ | `@thesage/ui/dates` | 29 KB | date-fns, react-day-picker |
185
+ | `@thesage/ui/tokens` | 11 KB | None |
186
+ | `@thesage/ui/utils` | 10 KB | None |
187
+ | `@thesage/ui/forms` | 9 KB | react-hook-form, zod |
188
+ | `@thesage/ui/tables` | 8 KB | @tanstack/react-table |
189
+ | `@thesage/ui/dnd` | 8 KB | @dnd-kit/* |
190
+ | `@thesage/ui/providers` | 8 KB | None |
191
+ | `@thesage/ui/hooks` | 6 KB | None |
192
+ | `@thesage/ui/webgl` | 1 KB | framer-motion |
193
+
194
+ `sideEffects: false` enables tree-shaking. Heavy features isolated behind subpath exports.
195
+
196
+ ## Third-Party Pairings
197
+
198
+ For gaps SDE doesn't cover, these libraries integrate well:
199
+
200
+ | Need | Library | Install |
201
+ |------|---------|---------|
202
+ | Rich Text Editor | Tiptap | `@tiptap/react @tiptap/starter-kit` |
203
+ | File Upload | react-dropzone | `react-dropzone` |
204
+ | Charts | Recharts | `recharts` |
205
+ | Color Picker | react-colorful | `react-colorful` |
206
+ | Markdown | react-markdown | `react-markdown remark-gfm` |
207
+ | Virtualized Lists | @tanstack/react-virtual | `@tanstack/react-virtual` |
208
+ | State Machines | XState | `xstate @xstate/react` |
209
+
210
+ **Already integrated as optional peer deps:** @tanstack/react-table (`/tables`), react-hook-form + zod (`/forms`), date-fns + react-day-picker (`/dates`), @dnd-kit (`/dnd`), framer-motion, lucide-react.
211
+
212
+ **Integration pattern:** Wrap in SDE Card/Dialog, use `cn()` for class merging, pull colors from CSS variables (`var(--color-primary)`) to stay theme-aware.
213
+
214
+ ## Eject (Full Customization)
215
+
216
+ ```bash
217
+ npx @thesage/ui eject Button # copies to src/components/ui/Button.tsx
218
+ npx @thesage/ui eject Dialog --dir my/dir # custom target
219
+ npx @thesage/ui eject --list # list all components
220
+ ```
221
+
222
+ Imports are automatically rewritten:
223
+ - `../../lib/utils` → `./utils` (auto-scaffolded)
224
+ - `../../hooks/*` → `@thesage/ui/hooks`
225
+ - `../category/*` → `@thesage/ui`
226
+
227
+ Ejected components keep working with SDE themes and CSS variables. Also available via MCP tool `eject_component` and web UI at thesage.dev.
228
+
229
+ ## Full API Reference
230
+
231
+ For complete props, variants, and examples for all 100 components:
232
+ - Web: https://thesage.dev/llms-full.txt
233
+ - MCP Server: `npx @thesage/mcp` (tools: list_components, search_components, get_component)
234
+
235
+ ## Resources
236
+
237
+ - Docs: https://thesage.dev/docs
238
+ - GitHub: https://github.com/shalomormsby/sage-design-engine
239
+ - NPM: https://www.npmjs.com/package/@thesage/ui
package/README.md ADDED
@@ -0,0 +1,161 @@
1
+ # Sage Design Engine (@thesage/ui)
2
+
3
+ <div align="center">
4
+
5
+ [![npm version](https://img.shields.io/npm/v/@thesage/ui?color=indigo&style=flat-square)](https://www.npmjs.com/package/@thesage/ui)
6
+ [![License](https://img.shields.io/npm/l/@thesage/ui?color=blue&style=flat-square)](https://github.com/shalomormsby/sage-design-engine/blob/main/LICENSE)
7
+ [![Downloads](https://img.shields.io/npm/dt/@thesage/ui?color=teal&style=flat-square)](https://www.npmjs.com/package/@thesage/ui)
8
+
9
+ **Sage — Make it Lovable.**
10
+
11
+ Components that feel alive. Themes with real personality. Motion your users control. Designed for humans. Fluent with AI.
12
+
13
+ [Documentation](https://thesage.dev) | [Components](https://thesage.dev/components) | [GitHub](https://github.com/shalomormsby/sage-design-engine)
14
+
15
+ </div>
16
+
17
+ ---
18
+
19
+ **Sage Design Engine** is a component library and design system built on **Radix UI** primitives and **Tailwind CSS**. 100 accessible components across 11 functional categories, three distinct themes with runtime switching, and a user-controlled motion system — all wired through a 4-layer design token architecture.
20
+
21
+ ## Features
22
+
23
+ - **Accessible by default** — Built on WAI-ARIA standards via Radix UI. Keyboard navigable, screen reader compatible, WCAG AA contrast.
24
+ - **Three themes, real personality** — Studio (professional), Terra (organic), Volt (electric). Runtime switching via CSS variables, light and dark modes each.
25
+ - **User-controlled motion** — A 0–10 intensity scale that respects `prefers-reduced-motion`. Intensity 0 works perfectly — no degraded experience.
26
+ - **Modular imports** — Core stays lean. Heavy features (forms, dates, tables, drag-and-drop, WebGL) ship as optional subpath exports — install only what you use.
27
+ - **Type safe** — Written in TypeScript with full type inference. React 19 ref-as-prop pattern throughout.
28
+ - **Design token system** — Colors, typography, spacing, motion, and syntax tokens. Change one primary color, everything updates.
29
+
30
+ ## Installation
31
+
32
+ ```bash
33
+ pnpm add @thesage/ui
34
+ ```
35
+
36
+ Sage requires **Tailwind CSS** as a styling engine:
37
+
38
+ ```bash
39
+ pnpm add -D tailwindcss@^3.4 postcss autoprefixer
40
+ ```
41
+
42
+ ### Optional subpath exports
43
+
44
+ Install peer dependencies only for the features you need:
45
+
46
+ ```bash
47
+ # Forms (react-hook-form + zod validation)
48
+ pnpm add react-hook-form @hookform/resolvers zod
49
+
50
+ # Date picker
51
+ pnpm add react-day-picker date-fns
52
+
53
+ # Data tables
54
+ pnpm add @tanstack/react-table
55
+
56
+ # Drag and drop
57
+ pnpm add @dnd-kit/core @dnd-kit/sortable @dnd-kit/utilities
58
+ ```
59
+
60
+ ### Configure Tailwind
61
+
62
+ ```js
63
+ /** @type {import('tailwindcss').Config} */
64
+ module.exports = {
65
+ content: [
66
+ "./src/**/*.{ts,tsx}",
67
+ "./node_modules/@thesage/ui/dist/**/*.{js,ts,jsx,tsx}"
68
+ ],
69
+ }
70
+ ```
71
+
72
+ ### Import styles
73
+
74
+ ```tsx
75
+ import '@thesage/ui/globals.css';
76
+ ```
77
+
78
+ ## Usage
79
+
80
+ ```tsx
81
+ import { Button, Card, ThemeProvider } from '@thesage/ui';
82
+
83
+ export default function App() {
84
+ return (
85
+ <ThemeProvider theme="studio" defaultMode="system">
86
+ <Card className="max-w-md p-6">
87
+ <h3 className="mb-2 text-lg font-semibold">Welcome to Sage</h3>
88
+ <p className="mb-4 text-muted-foreground">
89
+ Build beautifully with components that feel premium out of the box.
90
+ </p>
91
+ <div className="flex gap-2">
92
+ <Button>Get Started</Button>
93
+ <Button variant="ghost">Documentation</Button>
94
+ </div>
95
+ </Card>
96
+ </ThemeProvider>
97
+ );
98
+ }
99
+ ```
100
+
101
+ ### Subpath imports
102
+
103
+ ```tsx
104
+ import { useMotionPreference, useTheme } from '@thesage/ui/hooks'
105
+ import { ThemeProvider } from '@thesage/ui/providers'
106
+ import { cn } from '@thesage/ui/utils'
107
+
108
+ // Optional feature imports
109
+ import { Form, FormField } from '@thesage/ui/forms'
110
+ import { DatePicker } from '@thesage/ui/dates'
111
+ import { DataTable } from '@thesage/ui/tables'
112
+ import { SortableList } from '@thesage/ui/dnd'
113
+ ```
114
+
115
+ ## Component categories
116
+
117
+ | Category | Examples |
118
+ |----------|----------|
119
+ | **Actions** | Button, Toggle, ToggleGroup |
120
+ | **Forms** | Input, Select, Checkbox, Switch, Slider, SearchBar |
121
+ | **Navigation** | Tabs, Menubar, Breadcrumb, Pagination, NavigationMenu |
122
+ | **Overlays** | Dialog, Sheet, Popover, Tooltip, ContextMenu, HoverCard |
123
+ | **Data Display** | Card, Avatar, Badge, Table, ScrollArea, Carousel |
124
+ | **Feedback** | Alert, Progress, Skeleton, Toast (Sonner) |
125
+ | **Layout** | Accordion, Separator, ResizablePanels, Collapsible |
126
+ | **Features** | Customizer, ThemeSwitcher |
127
+
128
+ ## Eject — full customization
129
+
130
+ Need to deeply customize a component? Eject it into your project for full ownership:
131
+
132
+ ```bash
133
+ npx @thesage/ui eject Button
134
+ npx @thesage/ui eject Dialog --dir components/sage
135
+ npx @thesage/ui eject --list # see all available components
136
+ ```
137
+
138
+ This copies the component source into your project with imports automatically rewritten. The ejected component still works with Sage themes and CSS variables — you just own the code now.
139
+
140
+ You can also eject from [thesage.dev](https://thesage.dev) — every component page has an **Eject** button that lets you copy or download the source directly.
141
+
142
+ ## Bundle size
143
+
144
+ Core and optional entry points are independently tracked via [size-limit](https://github.com/ai/size-limit):
145
+
146
+ | Entry point | Brotli size |
147
+ |-------------|-------------|
148
+ | Core | ~146 KB |
149
+ | Hooks | ~40 KB |
150
+ | Providers | ~60 KB |
151
+ | Tokens | ~70 KB |
152
+ | Utils | ~25 KB |
153
+ | Forms | ~9.4 KB |
154
+ | Dates | ~29 KB |
155
+ | Tables | ~8.3 KB |
156
+ | DnD | ~8.3 KB |
157
+ | WebGL | ~1.1 KB |
158
+
159
+ ## License
160
+
161
+ MIT &copy; [Shalom Ormsby](https://github.com/shalomormsby)
package/dist/cli.mjs ADDED
@@ -0,0 +1,151 @@
1
+ #!/usr/bin/env node
2
+
3
+ // src/cli.ts
4
+ import { readFileSync, writeFileSync, mkdirSync, existsSync, readdirSync, statSync } from "fs";
5
+ import { join, dirname, resolve } from "path";
6
+ import { fileURLToPath } from "url";
7
+ var __filename_ = typeof __filename !== "undefined" ? __filename : fileURLToPath(import.meta.url);
8
+ var PKG_ROOT = resolve(dirname(__filename_), "..");
9
+ function transformImports(source) {
10
+ return source.replace(/from\s+['"]\.\.\/\.\.\/lib\/utils['"]/g, `from './utils'`).replace(/from\s+['"]\.\.\/\.\.\/lib\/[^'"]+['"]/g, `from '@opencosmos/ui/utils'`).replace(/from\s+['"]\.\.\/\.\.\/hooks\/[^'"]+['"]/g, `from '@opencosmos/ui/hooks'`).replace(/from\s+['"]\.\.\/[^.][^'"]*['"]/g, `from '@opencosmos/ui'`);
11
+ }
12
+ var CN_UTILS_SOURCE = `import { type ClassValue, clsx } from "clsx";
13
+ import { twMerge } from "tailwind-merge";
14
+
15
+ export function cn(...inputs: ClassValue[]) {
16
+ return twMerge(clsx(inputs));
17
+ }
18
+ `;
19
+ function findComponent(name) {
20
+ const srcDir = join(PKG_ROOT, "src", "components");
21
+ if (!existsSync(srcDir)) {
22
+ return null;
23
+ }
24
+ const lowerName = name.toLowerCase();
25
+ for (const category of readdirSync(srcDir)) {
26
+ const categoryPath = join(srcDir, category);
27
+ if (!statSync(categoryPath).isDirectory()) continue;
28
+ for (const file of readdirSync(categoryPath)) {
29
+ if (file.toLowerCase() === `${lowerName}.tsx` || file.toLowerCase() === `${lowerName}.ts`) {
30
+ return { filePath: join(categoryPath, file), category };
31
+ }
32
+ }
33
+ }
34
+ return null;
35
+ }
36
+ function listComponents() {
37
+ const srcDir = join(PKG_ROOT, "src", "components");
38
+ if (!existsSync(srcDir)) {
39
+ console.error("Error: Could not find component source directory.");
40
+ process.exit(1);
41
+ }
42
+ console.log("\n @opencosmos/ui \u2014 Available Components\n");
43
+ for (const category of readdirSync(srcDir).sort()) {
44
+ const categoryPath = join(srcDir, category);
45
+ if (!statSync(categoryPath).isDirectory()) continue;
46
+ const components = readdirSync(categoryPath).filter((f) => f.endsWith(".tsx") && !f.startsWith("index") && !f.includes(".test.")).map((f) => f.replace(/\.tsx$/, ""));
47
+ if (components.length === 0) continue;
48
+ console.log(` ${category}/`);
49
+ for (const comp of components.sort()) {
50
+ console.log(` ${comp}`);
51
+ }
52
+ console.log();
53
+ }
54
+ }
55
+ function ejectComponent(name, targetDir) {
56
+ const found = findComponent(name);
57
+ if (!found) {
58
+ console.error(`
59
+ Error: Component "${name}" not found.
60
+ `);
61
+ console.error(" Run `npx @opencosmos/ui eject --list` to see available components.\n");
62
+ process.exit(1);
63
+ }
64
+ const source = readFileSync(found.filePath, "utf-8");
65
+ const transformed = transformImports(source);
66
+ const resolvedDir = resolve(process.cwd(), targetDir);
67
+ mkdirSync(resolvedDir, { recursive: true });
68
+ const fileName = found.filePath.split("/").pop();
69
+ const destPath = join(resolvedDir, fileName);
70
+ writeFileSync(destPath, transformed, "utf-8");
71
+ const utilsPath = join(resolvedDir, "utils.ts");
72
+ if (!existsSync(utilsPath)) {
73
+ writeFileSync(utilsPath, CN_UTILS_SOURCE, "utf-8");
74
+ }
75
+ const deps = /* @__PURE__ */ new Set();
76
+ const importRegex = /from\s+['"](@[^/'"]+\/[^'"]+|[^.@/'"][^'"]*)['"]/g;
77
+ let match;
78
+ while ((match = importRegex.exec(source)) !== null) {
79
+ const pkg = match[1];
80
+ if (pkg.startsWith("@opencosmos/") || pkg === "react") continue;
81
+ const pkgName = pkg.startsWith("@") ? pkg.split("/").slice(0, 2).join("/") : pkg.split("/")[0];
82
+ deps.add(pkgName);
83
+ }
84
+ console.log(`
85
+ Ejected ${name} successfully!
86
+ `);
87
+ console.log(` ${destPath}`);
88
+ if (!existsSync(join(resolvedDir, "utils.ts"))) {
89
+ }
90
+ console.log(` ${utilsPath} (cn utility)
91
+ `);
92
+ if (deps.size > 0) {
93
+ console.log(" Required dependencies:");
94
+ console.log(` pnpm add ${[...deps].sort().join(" ")}
95
+ `);
96
+ }
97
+ console.log(" Update your imports:");
98
+ console.log(` import { ${name} } from './${targetDir}/${name}'
99
+ `);
100
+ console.log(" The ejected component still works with @opencosmos/ui themes and CSS variables.");
101
+ console.log(" You now own it \u2014 modify freely.\n");
102
+ }
103
+ function main() {
104
+ const args = process.argv.slice(2);
105
+ if (args.length === 0 || args.includes("--help") || args.includes("-h")) {
106
+ console.log(`
107
+ @opencosmos/ui eject \u2014 Copy component source into your project
108
+
109
+ Usage:
110
+ npx @opencosmos/ui eject <ComponentName> [--dir <path>]
111
+ npx @opencosmos/ui eject --list
112
+
113
+ Options:
114
+ --dir <path> Target directory (default: src/components/ui)
115
+ --list List all available components
116
+ --help Show this help message
117
+
118
+ Examples:
119
+ npx @opencosmos/ui eject Button
120
+ npx @opencosmos/ui eject Dialog --dir components/sage
121
+ `);
122
+ return;
123
+ }
124
+ if (args.includes("--list")) {
125
+ listComponents();
126
+ return;
127
+ }
128
+ const command = args[0];
129
+ if (command !== "eject") {
130
+ console.error(`
131
+ Unknown command: ${command}
132
+ Run with --help for usage.
133
+ `);
134
+ process.exit(1);
135
+ }
136
+ const componentName = args[1];
137
+ if (!componentName || componentName.startsWith("--")) {
138
+ console.error("\n Error: Component name is required.\n Usage: npx @opencosmos/ui eject <ComponentName>\n");
139
+ process.exit(1);
140
+ }
141
+ let targetDir = "src/components/ui";
142
+ const dirIdx = args.indexOf("--dir");
143
+ if (dirIdx !== -1 && args[dirIdx + 1]) {
144
+ targetDir = args[dirIdx + 1];
145
+ }
146
+ ejectComponent(componentName, targetDir);
147
+ }
148
+ main();
149
+ export {
150
+ transformImports
151
+ };
@@ -0,0 +1,20 @@
1
+ import * as react_jsx_runtime from 'react/jsx-runtime';
2
+ import * as React from 'react';
3
+ import { DayPicker } from 'react-day-picker';
4
+
5
+ type CalendarProps = React.ComponentProps<typeof DayPicker>;
6
+ declare function Calendar({ className, classNames, showOutsideDays, ...props }: CalendarProps): react_jsx_runtime.JSX.Element;
7
+ declare namespace Calendar {
8
+ var displayName: string;
9
+ }
10
+
11
+ interface DatePickerProps {
12
+ date?: Date;
13
+ onDateChange?: (date: Date | undefined) => void;
14
+ placeholder?: string;
15
+ className?: string;
16
+ disabled?: boolean;
17
+ }
18
+ declare function DatePicker({ date, onDateChange, placeholder, className, disabled, }: DatePickerProps): react_jsx_runtime.JSX.Element;
19
+
20
+ export { Calendar, type CalendarProps, DatePicker, type DatePickerProps };
@@ -0,0 +1,20 @@
1
+ import * as react_jsx_runtime from 'react/jsx-runtime';
2
+ import * as React from 'react';
3
+ import { DayPicker } from 'react-day-picker';
4
+
5
+ type CalendarProps = React.ComponentProps<typeof DayPicker>;
6
+ declare function Calendar({ className, classNames, showOutsideDays, ...props }: CalendarProps): react_jsx_runtime.JSX.Element;
7
+ declare namespace Calendar {
8
+ var displayName: string;
9
+ }
10
+
11
+ interface DatePickerProps {
12
+ date?: Date;
13
+ onDateChange?: (date: Date | undefined) => void;
14
+ placeholder?: string;
15
+ className?: string;
16
+ disabled?: boolean;
17
+ }
18
+ declare function DatePicker({ date, onDateChange, placeholder, className, disabled, }: DatePickerProps): react_jsx_runtime.JSX.Element;
19
+
20
+ export { Calendar, type CalendarProps, DatePicker, type DatePickerProps };