@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
package/package.json ADDED
@@ -0,0 +1,267 @@
1
+ {
2
+ "name": "@opencosmos/ui",
3
+ "version": "1.3.1",
4
+ "description": "Sage Design Engine — Make it Lovable. 100 accessible React components, three themes, user-controlled motion.",
5
+ "main": "dist/index.js",
6
+ "module": "dist/index.mjs",
7
+ "types": "dist/index.d.ts",
8
+ "sideEffects": false,
9
+ "license": "MIT",
10
+ "author": "Shalom Ormsby",
11
+ "repository": {
12
+ "type": "git",
13
+ "url": "https://github.com/shalomormsby/sage-design-engine.git",
14
+ "directory": "packages/ui"
15
+ },
16
+ "homepage": "https://thesage.dev",
17
+ "bugs": "https://github.com/shalomormsby/sage-design-engine/issues",
18
+ "keywords": [
19
+ "react",
20
+ "components",
21
+ "ui",
22
+ "design-system",
23
+ "tailwind",
24
+ "radix",
25
+ "accessible",
26
+ "themes",
27
+ "mcp",
28
+ "ai"
29
+ ],
30
+ "publishConfig": {
31
+ "access": "public"
32
+ },
33
+ "bin": {
34
+ "opencosmos-ui": "dist/cli.mjs"
35
+ },
36
+ "files": [
37
+ "dist",
38
+ "src",
39
+ ".claude",
40
+ "README.md"
41
+ ],
42
+ "exports": {
43
+ ".": {
44
+ "types": "./dist/index.d.ts",
45
+ "import": "./dist/index.mjs",
46
+ "require": "./dist/index.js"
47
+ },
48
+ "./tokens": {
49
+ "types": "./dist/tokens.d.ts",
50
+ "import": "./dist/tokens.mjs",
51
+ "require": "./dist/tokens.js"
52
+ },
53
+ "./hooks": {
54
+ "types": "./dist/hooks.d.ts",
55
+ "import": "./dist/hooks.mjs",
56
+ "require": "./dist/hooks.js"
57
+ },
58
+ "./utils": {
59
+ "types": "./dist/utils.d.ts",
60
+ "import": "./dist/utils.mjs",
61
+ "require": "./dist/utils.js"
62
+ },
63
+ "./providers": {
64
+ "types": "./dist/providers.d.ts",
65
+ "import": "./dist/providers.mjs",
66
+ "require": "./dist/providers.js"
67
+ },
68
+ "./webgl": {
69
+ "types": "./dist/webgl.d.ts",
70
+ "import": "./dist/webgl.mjs",
71
+ "require": "./dist/webgl.js"
72
+ },
73
+ "./forms": {
74
+ "types": "./dist/forms.d.ts",
75
+ "import": "./dist/forms.mjs",
76
+ "require": "./dist/forms.js"
77
+ },
78
+ "./dates": {
79
+ "types": "./dist/dates.d.ts",
80
+ "import": "./dist/dates.mjs",
81
+ "require": "./dist/dates.js"
82
+ },
83
+ "./tables": {
84
+ "types": "./dist/tables.d.ts",
85
+ "import": "./dist/tables.mjs",
86
+ "require": "./dist/tables.js"
87
+ },
88
+ "./dnd": {
89
+ "types": "./dist/dnd.d.ts",
90
+ "import": "./dist/dnd.mjs",
91
+ "require": "./dist/dnd.js"
92
+ },
93
+ "./globals.css": "./src/globals.css",
94
+ "./theme.css": "./src/theme.css"
95
+ },
96
+ "scripts": {
97
+ "build": "tsup",
98
+ "dev": "tsup --watch",
99
+ "lint": "eslint src/",
100
+ "test": "vitest run",
101
+ "test:watch": "vitest",
102
+ "typecheck": "tsc --noEmit",
103
+ "size": "size-limit",
104
+ "size:check": "size-limit --limit"
105
+ },
106
+ "size-limit": [
107
+ {
108
+ "name": "Core (index)",
109
+ "path": "dist/index.mjs",
110
+ "limit": "450 KB"
111
+ },
112
+ {
113
+ "name": "WebGL",
114
+ "path": "dist/webgl.mjs",
115
+ "limit": "10 KB"
116
+ },
117
+ {
118
+ "name": "Forms",
119
+ "path": "dist/forms.mjs",
120
+ "limit": "11 KB"
121
+ },
122
+ {
123
+ "name": "Dates",
124
+ "path": "dist/dates.mjs",
125
+ "limit": "33 KB"
126
+ },
127
+ {
128
+ "name": "Tables",
129
+ "path": "dist/tables.mjs",
130
+ "limit": "10 KB"
131
+ },
132
+ {
133
+ "name": "DnD",
134
+ "path": "dist/dnd.mjs",
135
+ "limit": "10 KB"
136
+ },
137
+ {
138
+ "name": "Hooks",
139
+ "path": "dist/hooks.mjs",
140
+ "limit": "40 KB"
141
+ },
142
+ {
143
+ "name": "Providers",
144
+ "path": "dist/providers.mjs",
145
+ "limit": "60 KB"
146
+ },
147
+ {
148
+ "name": "Tokens",
149
+ "path": "dist/tokens.mjs",
150
+ "limit": "70 KB"
151
+ },
152
+ {
153
+ "name": "Utils",
154
+ "path": "dist/utils.mjs",
155
+ "limit": "25 KB"
156
+ }
157
+ ],
158
+ "peerDependencies": {
159
+ "@dnd-kit/core": "^6.3.1",
160
+ "@dnd-kit/sortable": "^10.0.0",
161
+ "@dnd-kit/utilities": "^3.2.2",
162
+ "@hookform/resolvers": "^3.10.0",
163
+ "@tanstack/react-table": "^8.21.3",
164
+ "date-fns": "^4.1.0",
165
+ "framer-motion": "*",
166
+ "react": "*",
167
+ "react-day-picker": "^9.13.0",
168
+ "react-hook-form": "^7.70.0",
169
+ "zod": "^3.24.1"
170
+ },
171
+ "peerDependenciesMeta": {
172
+ "@dnd-kit/core": {
173
+ "optional": true
174
+ },
175
+ "@dnd-kit/sortable": {
176
+ "optional": true
177
+ },
178
+ "@dnd-kit/utilities": {
179
+ "optional": true
180
+ },
181
+ "@hookform/resolvers": {
182
+ "optional": true
183
+ },
184
+ "@tanstack/react-table": {
185
+ "optional": true
186
+ },
187
+ "date-fns": {
188
+ "optional": true
189
+ },
190
+ "react-day-picker": {
191
+ "optional": true
192
+ },
193
+ "react-hook-form": {
194
+ "optional": true
195
+ },
196
+ "zod": {
197
+ "optional": true
198
+ }
199
+ },
200
+ "dependencies": {
201
+ "@radix-ui/react-accordion": "^1.2.12",
202
+ "@radix-ui/react-alert-dialog": "^1.1.15",
203
+ "@radix-ui/react-aspect-ratio": "^1.1.8",
204
+ "@radix-ui/react-avatar": "^1.1.11",
205
+ "@radix-ui/react-checkbox": "^1.3.3",
206
+ "@radix-ui/react-collapsible": "^1.1.12",
207
+ "@radix-ui/react-context-menu": "^2.2.16",
208
+ "@radix-ui/react-dialog": "^1.1.15",
209
+ "@radix-ui/react-dropdown-menu": "^2.1.16",
210
+ "@radix-ui/react-hover-card": "^1.1.15",
211
+ "@radix-ui/react-label": "^2.1.8",
212
+ "@radix-ui/react-menubar": "^1.1.16",
213
+ "@radix-ui/react-navigation-menu": "^1.2.14",
214
+ "@radix-ui/react-popover": "^1.1.15",
215
+ "@radix-ui/react-progress": "^1.1.8",
216
+ "@radix-ui/react-radio-group": "^1.3.8",
217
+ "@radix-ui/react-scroll-area": "^1.2.10",
218
+ "@radix-ui/react-select": "^2.2.6",
219
+ "@radix-ui/react-separator": "^1.1.8",
220
+ "@radix-ui/react-slider": "^1.3.6",
221
+ "@radix-ui/react-slot": "^1.2.4",
222
+ "@radix-ui/react-switch": "^1.2.6",
223
+ "@radix-ui/react-tabs": "^1.1.13",
224
+ "@radix-ui/react-toggle": "^1.1.10",
225
+ "@radix-ui/react-toggle-group": "^1.1.11",
226
+ "@radix-ui/react-tooltip": "^1.2.8",
227
+ "class-variance-authority": "^0.7.0",
228
+ "clsx": "^2.1.0",
229
+ "cmdk": "^1.1.1",
230
+ "embla-carousel-react": "^8.6.0",
231
+ "input-otp": "^1.4.2",
232
+ "lucide-react": "^0.562.0",
233
+ "react-dropzone": "^15.0.0",
234
+ "react-resizable-panels": "^4.4.0",
235
+ "sonner": "^2.0.7",
236
+ "tailwind-merge": "^3.0.0",
237
+ "vaul": "^1.1.2",
238
+ "zustand": "^5.0.9"
239
+ },
240
+ "devDependencies": {
241
+ "@dnd-kit/core": "^6.3.1",
242
+ "@dnd-kit/sortable": "^10.0.0",
243
+ "@dnd-kit/utilities": "^3.2.2",
244
+ "@hookform/resolvers": "^3.10.0",
245
+ "@size-limit/preset-small-lib": "^12.0.0",
246
+ "@tanstack/react-table": "^8.21.3",
247
+ "@testing-library/jest-dom": "^6.9.1",
248
+ "@testing-library/react": "^16.3.2",
249
+ "@testing-library/user-event": "^14.6.1",
250
+ "@types/react": "^19",
251
+ "date-fns": "^4.1.0",
252
+ "eslint": "^9.39.2",
253
+ "eslint-plugin-react-hooks": "^5.2.0",
254
+ "framer-motion": "^12.26.2",
255
+ "jsdom": "^28.0.0",
256
+ "react-day-picker": "^9.13.0",
257
+ "react-hook-form": "^7.70.0",
258
+ "size-limit": "^12.0.0",
259
+ "tailwindcss": "^4.0.0",
260
+ "@tailwindcss/postcss": "^4.0.0",
261
+ "tsup": "^8.0.0",
262
+ "typescript": "^5.0.0",
263
+ "typescript-eslint": "^8.54.0",
264
+ "vitest": "^4.0.18",
265
+ "zod": "^3.24.1"
266
+ }
267
+ }
package/src/cli.ts ADDED
@@ -0,0 +1,206 @@
1
+ import { readFileSync, writeFileSync, mkdirSync, existsSync, readdirSync, statSync } from 'fs';
2
+ import { join, dirname, resolve } from 'path';
3
+ import { fileURLToPath } from 'url';
4
+
5
+ // ---------------------------------------------------------------------------
6
+ // Resolve package root (works from dist/cli.js → package root)
7
+ // ---------------------------------------------------------------------------
8
+ const __filename_ = typeof __filename !== 'undefined' ? __filename : fileURLToPath(import.meta.url);
9
+ const PKG_ROOT = resolve(dirname(__filename_), '..');
10
+
11
+ // ---------------------------------------------------------------------------
12
+ // Import transform
13
+ // ---------------------------------------------------------------------------
14
+ export function transformImports(source: string): string {
15
+ return source
16
+ // ../../lib/utils → ./utils (cn utility — we scaffold it alongside)
17
+ .replace(/from\s+['"]\.\.\/\.\.\/lib\/utils['"]/g, `from './utils'`)
18
+ // ../../lib/* → @opencosmos/ui/utils
19
+ .replace(/from\s+['"]\.\.\/\.\.\/lib\/[^'"]+['"]/g, `from '@opencosmos/ui/utils'`)
20
+ // ../../hooks/* → @opencosmos/ui/hooks
21
+ .replace(/from\s+['"]\.\.\/\.\.\/hooks\/[^'"]+['"]/g, `from '@opencosmos/ui/hooks'`)
22
+ // ../category/Component → @opencosmos/ui (cross-component imports)
23
+ .replace(/from\s+['"]\.\.\/[^.][^'"]*['"]/g, `from '@opencosmos/ui'`);
24
+ }
25
+
26
+ // ---------------------------------------------------------------------------
27
+ // cn() utility source (scaffolded alongside ejected components)
28
+ // ---------------------------------------------------------------------------
29
+ const CN_UTILS_SOURCE = `import { type ClassValue, clsx } from "clsx";
30
+ import { twMerge } from "tailwind-merge";
31
+
32
+ export function cn(...inputs: ClassValue[]) {
33
+ return twMerge(clsx(inputs));
34
+ }
35
+ `;
36
+
37
+ // ---------------------------------------------------------------------------
38
+ // Scan src/components to find a component file by name (case-insensitive)
39
+ // ---------------------------------------------------------------------------
40
+ function findComponent(name: string): { filePath: string; category: string } | null {
41
+ const srcDir = join(PKG_ROOT, 'src', 'components');
42
+ if (!existsSync(srcDir)) {
43
+ return null;
44
+ }
45
+
46
+ const lowerName = name.toLowerCase();
47
+
48
+ for (const category of readdirSync(srcDir)) {
49
+ const categoryPath = join(srcDir, category);
50
+ if (!statSync(categoryPath).isDirectory()) continue;
51
+
52
+ for (const file of readdirSync(categoryPath)) {
53
+ if (file.toLowerCase() === `${lowerName}.tsx` || file.toLowerCase() === `${lowerName}.ts`) {
54
+ return { filePath: join(categoryPath, file), category };
55
+ }
56
+ }
57
+ }
58
+
59
+ return null;
60
+ }
61
+
62
+ // ---------------------------------------------------------------------------
63
+ // List all available components grouped by category
64
+ // ---------------------------------------------------------------------------
65
+ function listComponents(): void {
66
+ const srcDir = join(PKG_ROOT, 'src', 'components');
67
+ if (!existsSync(srcDir)) {
68
+ console.error('Error: Could not find component source directory.');
69
+ process.exit(1);
70
+ }
71
+
72
+ console.log('\n @opencosmos/ui — Available Components\n');
73
+
74
+ for (const category of readdirSync(srcDir).sort()) {
75
+ const categoryPath = join(srcDir, category);
76
+ if (!statSync(categoryPath).isDirectory()) continue;
77
+
78
+ const components = readdirSync(categoryPath)
79
+ .filter((f) => f.endsWith('.tsx') && !f.startsWith('index') && !f.includes('.test.'))
80
+ .map((f) => f.replace(/\.tsx$/, ''));
81
+
82
+ if (components.length === 0) continue;
83
+
84
+ console.log(` ${category}/`);
85
+ for (const comp of components.sort()) {
86
+ console.log(` ${comp}`);
87
+ }
88
+ console.log();
89
+ }
90
+ }
91
+
92
+ // ---------------------------------------------------------------------------
93
+ // Eject a component
94
+ // ---------------------------------------------------------------------------
95
+ function ejectComponent(name: string, targetDir: string): void {
96
+ const found = findComponent(name);
97
+
98
+ if (!found) {
99
+ console.error(`\n Error: Component "${name}" not found.\n`);
100
+ console.error(' Run `npx @opencosmos/ui eject --list` to see available components.\n');
101
+ process.exit(1);
102
+ }
103
+
104
+ const source = readFileSync(found.filePath, 'utf-8');
105
+ const transformed = transformImports(source);
106
+
107
+ // Ensure target directory exists
108
+ const resolvedDir = resolve(process.cwd(), targetDir);
109
+ mkdirSync(resolvedDir, { recursive: true });
110
+
111
+ // Write transformed component
112
+ const fileName = found.filePath.split('/').pop()!;
113
+ const destPath = join(resolvedDir, fileName);
114
+ writeFileSync(destPath, transformed, 'utf-8');
115
+
116
+ // Scaffold utils.ts if not present
117
+ const utilsPath = join(resolvedDir, 'utils.ts');
118
+ if (!existsSync(utilsPath)) {
119
+ writeFileSync(utilsPath, CN_UTILS_SOURCE, 'utf-8');
120
+ }
121
+
122
+ // Extract external dependencies from the source for user guidance
123
+ const deps = new Set<string>();
124
+ const importRegex = /from\s+['"](@[^/'"]+\/[^'"]+|[^.@/'"][^'"]*)['"]/g;
125
+ let match;
126
+ while ((match = importRegex.exec(source)) !== null) {
127
+ const pkg = match[1];
128
+ // Skip internal @opencosmos imports and react (always present)
129
+ if (pkg.startsWith('@opencosmos/') || pkg === 'react') continue;
130
+ // Normalize scoped packages to package name
131
+ const pkgName = pkg.startsWith('@') ? pkg.split('/').slice(0, 2).join('/') : pkg.split('/')[0];
132
+ deps.add(pkgName);
133
+ }
134
+
135
+ console.log(`\n Ejected ${name} successfully!\n`);
136
+ console.log(` ${destPath}`);
137
+ if (!existsSync(join(resolvedDir, 'utils.ts'))) {
138
+ // utils was just created
139
+ }
140
+ console.log(` ${utilsPath} (cn utility)\n`);
141
+
142
+ if (deps.size > 0) {
143
+ console.log(' Required dependencies:');
144
+ console.log(` pnpm add ${[...deps].sort().join(' ')}\n`);
145
+ }
146
+
147
+ console.log(' Update your imports:');
148
+ console.log(` import { ${name} } from './${targetDir}/${name}'\n`);
149
+ console.log(' The ejected component still works with @opencosmos/ui themes and CSS variables.');
150
+ console.log(' You now own it — modify freely.\n');
151
+ }
152
+
153
+ // ---------------------------------------------------------------------------
154
+ // CLI entry point
155
+ // ---------------------------------------------------------------------------
156
+ function main(): void {
157
+ const args = process.argv.slice(2);
158
+
159
+ if (args.length === 0 || args.includes('--help') || args.includes('-h')) {
160
+ console.log(`
161
+ @opencosmos/ui eject — Copy component source into your project
162
+
163
+ Usage:
164
+ npx @opencosmos/ui eject <ComponentName> [--dir <path>]
165
+ npx @opencosmos/ui eject --list
166
+
167
+ Options:
168
+ --dir <path> Target directory (default: src/components/ui)
169
+ --list List all available components
170
+ --help Show this help message
171
+
172
+ Examples:
173
+ npx @opencosmos/ui eject Button
174
+ npx @opencosmos/ui eject Dialog --dir components/sage
175
+ `);
176
+ return;
177
+ }
178
+
179
+ if (args.includes('--list')) {
180
+ listComponents();
181
+ return;
182
+ }
183
+
184
+ // Parse: eject <name> [--dir <path>]
185
+ const command = args[0];
186
+ if (command !== 'eject') {
187
+ console.error(`\n Unknown command: ${command}\n Run with --help for usage.\n`);
188
+ process.exit(1);
189
+ }
190
+
191
+ const componentName = args[1];
192
+ if (!componentName || componentName.startsWith('--')) {
193
+ console.error('\n Error: Component name is required.\n Usage: npx @opencosmos/ui eject <ComponentName>\n');
194
+ process.exit(1);
195
+ }
196
+
197
+ let targetDir = 'src/components/ui';
198
+ const dirIdx = args.indexOf('--dir');
199
+ if (dirIdx !== -1 && args[dirIdx + 1]) {
200
+ targetDir = args[dirIdx + 1];
201
+ }
202
+
203
+ ejectComponent(componentName, targetDir);
204
+ }
205
+
206
+ main();
@@ -0,0 +1,183 @@
1
+ /**
2
+ * Component Registry - Source of Truth
3
+ *
4
+ * This file serves as the authoritative source for component counts,
5
+ * categories, and organization. Used by:
6
+ * - Documentation (Sage Studio)
7
+ * - MCP Server registry
8
+ * - Marketing materials
9
+ * - Internal tooling
10
+ *
11
+ * ⚠️ IMPORTANT: When adding a new component, follow the complete workflow:
12
+ * See: /.agent/workflows/register-new-component.md
13
+ *
14
+ * The workflow includes:
15
+ * - Creating the component in packages/ui
16
+ * - Registering in Sage Studio (apps/web)
17
+ * - Updating THIS registry file
18
+ * - Updating MCP server registry
19
+ * - Version bumping and npm publishing
20
+ *
21
+ * Last Updated: 2026-02-28
22
+ */
23
+
24
+ export const BRAND = {
25
+ productName: 'Sage Design Engine',
26
+ productNameShort: 'Sage',
27
+ themeNames: {
28
+ organic: 'Terra',
29
+ technical: 'Volt',
30
+ neutral: 'Studio',
31
+ },
32
+ tagline: "The Solopreneur's Development Stack",
33
+ mission: 'AI-Native components for velocity',
34
+ } as const;
35
+
36
+ export const COMPONENT_REGISTRY = {
37
+ /**
38
+ * Total count of all exported UI components from @thesage/ui
39
+ */
40
+ totalCount: 100,
41
+
42
+ /**
43
+ * Core categories following functional organization pattern
44
+ * (what components DO, not abstract hierarchy)
45
+ */
46
+ coreCategories: {
47
+ actions: {
48
+ count: 5,
49
+ description: 'Components that trigger behavior',
50
+ examples: ['Button', 'Link', 'Toggle', 'ToggleGroup', 'Magnetic'],
51
+ },
52
+ forms: {
53
+ count: 19,
54
+ description: 'Components that collect user input',
55
+ examples: ['Input', 'Select', 'Checkbox', 'Switch', 'Textarea', 'ColorPicker', 'SearchBar', 'FileUpload'],
56
+ },
57
+ navigation: {
58
+ count: 10,
59
+ description: 'Components that help users move through content',
60
+ examples: ['Tabs', 'Breadcrumb', 'Pagination', 'NavigationMenu', 'Command'],
61
+ },
62
+ overlays: {
63
+ count: 12,
64
+ description: 'Components that display contextual content',
65
+ examples: ['Dialog', 'Tooltip', 'Popover', 'Drawer', 'Modal', 'Sheet', 'NotificationCenter'],
66
+ },
67
+ feedback: {
68
+ count: 9,
69
+ description: 'Components that communicate system state',
70
+ examples: ['Alert', 'Toast', 'Progress', 'Spinner', 'Skeleton', 'EmptyState', 'Stepper'],
71
+ },
72
+ 'data-display': {
73
+ count: 19,
74
+ description: 'Components that present information',
75
+ examples: ['Card', 'Table', 'Badge', 'Avatar', 'Heading', 'Text', 'Code', 'Calendar', 'StatCard', 'Timeline', 'TreeView'],
76
+ },
77
+ layout: {
78
+ count: 18,
79
+ description: 'Components for spatial organization',
80
+ examples: ['Accordion', 'Separator', 'Stack', 'Grid', 'Container', 'ScrollArea', 'GlassSurface'],
81
+ },
82
+ },
83
+
84
+ /**
85
+ * Specialty categories for advanced interactions and effects
86
+ */
87
+ specialtyCategories: {
88
+ backgrounds: {
89
+ count: 2,
90
+ description: 'Animated background effects',
91
+ examples: ['WarpBackground', 'FaultyTerminal'],
92
+ },
93
+ cursor: {
94
+ count: 2,
95
+ description: 'Interactive cursor effects',
96
+ examples: ['SplashCursor', 'TargetCursor'],
97
+ },
98
+ blocks: {
99
+ count: 1,
100
+ description: 'Composed page blocks',
101
+ examples: ['Hero', 'OpenGraphCard'],
102
+ },
103
+ },
104
+
105
+ /**
106
+ * Supporting APIs (not counted as components)
107
+ */
108
+ supportingAPIs: {
109
+ providers: ['ThemeProvider'],
110
+ hooks: ['useTheme', 'useMotionPreference', 'useForm'],
111
+ utilities: ['animations', 'breadcrumbs', 'colors', 'utils', 'validation', 'syntax-parser'],
112
+ stores: ['themeStore', 'customizerStore'],
113
+ },
114
+ } as const;
115
+
116
+ /**
117
+ * Computed totals
118
+ */
119
+ export const COMPONENT_COUNTS = {
120
+ core: Object.values(COMPONENT_REGISTRY.coreCategories).reduce(
121
+ (sum, cat) => sum + cat.count,
122
+ 0
123
+ ), // 84
124
+ specialty: Object.values(COMPONENT_REGISTRY.specialtyCategories).reduce(
125
+ (sum, cat) => sum + cat.count,
126
+ 0
127
+ ), // 5
128
+ total: COMPONENT_REGISTRY.totalCount, // 89
129
+ } as const;
130
+
131
+ /**
132
+ * Marketing-friendly descriptions
133
+ */
134
+ export const MARKETING_COPY = {
135
+ short: '100 production-ready components',
136
+ medium: '100 components across 7 core categories, plus specialty backgrounds and motion effects',
137
+ long: '100 thoughtfully designed components organized by function: actions, forms, navigation, overlays, feedback, data display, and layout—plus specialty components for backgrounds, cursor interactions, and animated effects.',
138
+ } as const;
139
+
140
+ /**
141
+ * Documentation usage examples
142
+ */
143
+ export const DOC_EXAMPLES = {
144
+ // For overview sections
145
+ overview: `${COMPONENT_COUNTS.total} components across ${Object.keys(COMPONENT_REGISTRY.coreCategories).length
146
+ } core categories`,
147
+
148
+ // For detailed breakdowns
149
+ breakdown: `
150
+ - **Actions** (${COMPONENT_REGISTRY.coreCategories.actions.count}): ${COMPONENT_REGISTRY.coreCategories.actions.description}
151
+ - **Forms** (${COMPONENT_REGISTRY.coreCategories.forms.count}): ${COMPONENT_REGISTRY.coreCategories.forms.description}
152
+ - **Navigation** (${COMPONENT_REGISTRY.coreCategories.navigation.count}): ${COMPONENT_REGISTRY.coreCategories.navigation.description}
153
+ - **Overlays** (${COMPONENT_REGISTRY.coreCategories.overlays.count}): ${COMPONENT_REGISTRY.coreCategories.overlays.description}
154
+ - **Feedback** (${COMPONENT_REGISTRY.coreCategories.feedback.count}): ${COMPONENT_REGISTRY.coreCategories.feedback.description}
155
+ - **Data Display** (${COMPONENT_REGISTRY.coreCategories['data-display'].count}): ${COMPONENT_REGISTRY.coreCategories['data-display'].description}
156
+ - **Layout** (${COMPONENT_REGISTRY.coreCategories.layout.count}): ${COMPONENT_REGISTRY.coreCategories.layout.description}
157
+ `.trim(),
158
+ } as const;
159
+
160
+ /**
161
+ * Decision Documentation: Why these numbers?
162
+ *
163
+ * **What counts as a component:**
164
+ * - Any UI element exported from packages/ui/src/index.ts
165
+ * - Follows React component pattern (returns JSX)
166
+ * - Can be imported and used directly
167
+ *
168
+ * **What doesn't count:**
169
+ * - Providers (utility, not UI)
170
+ * - Hooks (utility, not UI)
171
+ * - Utility functions
172
+ * - Type definitions
173
+ *
174
+ * **Category philosophy:**
175
+ * - Functional organization (what it DOES, not what it IS)
176
+ * - Industry standard (matches Material UI, Radix patterns)
177
+ * - No arbitrary tiers - if exported, it's official
178
+ *
179
+ * **Maintenance:**
180
+ * - Update this file when adding/removing components
181
+ * - Run: grep -c "^export \* from './components/" packages/ui/src/index.ts
182
+ * - Verify count matches COMPONENT_REGISTRY.totalCount
183
+ */