@once-ui-system/core 1.7.11 → 1.7.13

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 (392) hide show
  1. package/AGENTS.md +53 -0
  2. package/README.md +27 -0
  3. package/agent/once-ui-codegen.mdc +27 -0
  4. package/ai/catalog.json +1650 -0
  5. package/ai/catalog.seed.json +411 -0
  6. package/ai/components/Accordion.json +136 -0
  7. package/ai/components/AccordionGroup.json +128 -0
  8. package/ai/components/Animation.json +146 -0
  9. package/ai/components/Arrow.json +128 -0
  10. package/ai/components/AutoScroll.json +130 -0
  11. package/ai/components/Avatar.json +133 -0
  12. package/ai/components/AvatarGroup.json +129 -0
  13. package/ai/components/Background.json +131 -0
  14. package/ai/components/Badge.json +132 -0
  15. package/ai/components/Banner.json +122 -0
  16. package/ai/components/BarChart.json +123 -0
  17. package/ai/components/BlobFx.json +125 -0
  18. package/ai/components/BlockQuote.json +132 -0
  19. package/ai/components/Button.json +26 -0
  20. package/ai/components/Card.json +129 -0
  21. package/ai/components/Carousel.json +134 -0
  22. package/ai/components/CelebrationFx.json +132 -0
  23. package/ai/components/ChartHeader.json +130 -0
  24. package/ai/components/ChartStatus.json +12 -0
  25. package/ai/components/Checkbox.json +13 -0
  26. package/ai/components/Chip.json +132 -0
  27. package/ai/components/CodeBlock.json +122 -0
  28. package/ai/components/ColorInput.json +13 -0
  29. package/ai/components/Column.json +128 -0
  30. package/ai/components/CompareImage.json +126 -0
  31. package/ai/components/ContextMenu.json +22 -0
  32. package/ai/components/CountFx.json +82 -0
  33. package/ai/components/CountdownFx.json +11 -0
  34. package/ai/components/Cursor.json +9 -0
  35. package/ai/components/CursorCard.json +128 -0
  36. package/ai/components/DataTooltip.json +15 -0
  37. package/ai/components/DateInput.json +21 -0
  38. package/ai/components/DatePicker.json +143 -0
  39. package/ai/components/DateRangeInput.json +18 -0
  40. package/ai/components/DateRangePicker.json +129 -0
  41. package/ai/components/Dialog.json +134 -0
  42. package/ai/components/DialogProvider.json +8 -0
  43. package/ai/components/Dropdown.json +128 -0
  44. package/ai/components/DropdownWrapper.json +28 -0
  45. package/ai/components/EmojiPicker.json +129 -0
  46. package/ai/components/EmojiPickerDropdown.json +13 -0
  47. package/ai/components/Fade.json +130 -0
  48. package/ai/components/FadingLettersFx.json +77 -0
  49. package/ai/components/Feedback.json +132 -0
  50. package/ai/components/Flex.json +125 -0
  51. package/ai/components/FlipFx.json +133 -0
  52. package/ai/components/GlitchFx.json +128 -0
  53. package/ai/components/Grid.json +121 -0
  54. package/ai/components/Heading.json +75 -0
  55. package/ai/components/HeadingLink.json +127 -0
  56. package/ai/components/HeadingNav.json +124 -0
  57. package/ai/components/HoloFx.json +128 -0
  58. package/ai/components/Hover.json +130 -0
  59. package/ai/components/HoverCard.json +122 -0
  60. package/ai/components/Icon.json +132 -0
  61. package/ai/components/IconButton.json +22 -0
  62. package/ai/components/InfiniteScroll.json +130 -0
  63. package/ai/components/InlineCode.json +126 -0
  64. package/ai/components/Input.json +24 -0
  65. package/ai/components/InteractiveDetails.json +14 -0
  66. package/ai/components/Kbar.json +10 -0
  67. package/ai/components/Kbd.json +127 -0
  68. package/ai/components/Legend.json +14 -0
  69. package/ai/components/LetterFx.json +14 -0
  70. package/ai/components/Line.json +125 -0
  71. package/ai/components/LineBarChart.json +123 -0
  72. package/ai/components/LineChart.json +123 -0
  73. package/ai/components/LinearGauge.json +130 -0
  74. package/ai/components/LinearGradient.json +15 -0
  75. package/ai/components/List.json +127 -0
  76. package/ai/components/ListItem.json +77 -0
  77. package/ai/components/Logo.json +16 -0
  78. package/ai/components/LogoCloud.json +124 -0
  79. package/ai/components/Mask.json +131 -0
  80. package/ai/components/MasonryGrid.json +132 -0
  81. package/ai/components/MatrixFx.json +135 -0
  82. package/ai/components/Media.json +142 -0
  83. package/ai/components/MediaUpload.json +122 -0
  84. package/ai/components/MegaMenu.json +125 -0
  85. package/ai/components/MobileMegaMenu.json +125 -0
  86. package/ai/components/Modal.json +12 -0
  87. package/ai/components/NavIcon.json +127 -0
  88. package/ai/components/NumberInput.json +16 -0
  89. package/ai/components/OTPInput.json +13 -0
  90. package/ai/components/OgCard.json +135 -0
  91. package/ai/components/Option.json +137 -0
  92. package/ai/components/Particle.json +135 -0
  93. package/ai/components/PasswordInput.json +8 -0
  94. package/ai/components/PieChart.json +123 -0
  95. package/ai/components/ProgressBar.json +131 -0
  96. package/ai/components/Pulse.json +129 -0
  97. package/ai/components/RadialGauge.json +134 -0
  98. package/ai/components/RadialGradient.json +16 -0
  99. package/ai/components/RadioButton.json +17 -0
  100. package/ai/components/RevealFx.json +131 -0
  101. package/ai/components/Row.json +128 -0
  102. package/ai/components/Schema.json +17 -0
  103. package/ai/components/ScrollContainer.json +126 -0
  104. package/ai/components/ScrollToTop.json +124 -0
  105. package/ai/components/Scroller.json +128 -0
  106. package/ai/components/SegmentedControl.json +132 -0
  107. package/ai/components/Select.json +21 -0
  108. package/ai/components/ShineFx.json +80 -0
  109. package/ai/components/Skeleton.json +129 -0
  110. package/ai/components/Slider.json +17 -0
  111. package/ai/components/SmartLink.json +17 -0
  112. package/ai/components/Spinner.json +127 -0
  113. package/ai/components/SplitView.json +129 -0
  114. package/ai/components/StatusIndicator.json +128 -0
  115. package/ai/components/StyleOverlay.json +126 -0
  116. package/ai/components/StylePanel.json +125 -0
  117. package/ai/components/Swiper.json +130 -0
  118. package/ai/components/Switch.json +20 -0
  119. package/ai/components/Table.json +140 -0
  120. package/ai/components/Tag.json +129 -0
  121. package/ai/components/TagInput.json +12 -0
  122. package/ai/components/Text.json +72 -0
  123. package/ai/components/Textarea.json +24 -0
  124. package/ai/components/ThemeSwitcher.json +122 -0
  125. package/ai/components/TiltFx.json +126 -0
  126. package/ai/components/Timeline.json +126 -0
  127. package/ai/components/Toast.json +13 -0
  128. package/ai/components/Toaster.json +14 -0
  129. package/ai/components/ToggleButton.json +24 -0
  130. package/ai/components/Tooltip.json +129 -0
  131. package/ai/components/TypeFx.json +15 -0
  132. package/ai/components/User.json +15 -0
  133. package/ai/components/UserMenu.json +16 -0
  134. package/ai/components/WeatherFx.json +133 -0
  135. package/ai/examples/auth.tsx +105 -0
  136. package/ai/examples/blocks/Background6.tsx +25 -0
  137. package/ai/examples/blocks/Chat1.tsx +70 -0
  138. package/ai/examples/blocks/Dashboard1.tsx +404 -0
  139. package/ai/examples/blocks/Feed3.tsx +151 -0
  140. package/ai/examples/blocks/Footer1.tsx +30 -0
  141. package/ai/examples/blocks/Footer2.tsx +96 -0
  142. package/ai/examples/blocks/Footer3.tsx +127 -0
  143. package/ai/examples/blocks/Footer4.tsx +406 -0
  144. package/ai/examples/blocks/Header1.tsx +370 -0
  145. package/ai/examples/blocks/Header2.tsx +98 -0
  146. package/ai/examples/blocks/Header3.tsx +133 -0
  147. package/ai/examples/blocks/Header4.tsx +123 -0
  148. package/ai/examples/blocks/Productivity1.tsx +318 -0
  149. package/ai/examples/blocks/Roadmap1.tsx +133 -0
  150. package/ai/examples/blocks/Sidebar1.tsx +34 -0
  151. package/ai/examples/blocks/Sidebar2.tsx +17 -0
  152. package/ai/examples/blocks/Sidebar4.tsx +92 -0
  153. package/ai/examples/blocks/Sidebar5.tsx +73 -0
  154. package/ai/examples/blocks/Streaming1.tsx +353 -0
  155. package/ai/examples/blocks/Table1.tsx +303 -0
  156. package/ai/examples/blocks/Waitlist1.tsx +141 -0
  157. package/ai/examples/blocks/content/chat1content.ts +65 -0
  158. package/ai/examples/blocks/content/resources.ts +5 -0
  159. package/ai/examples/blocks/content/roadmap1content.ts +51 -0
  160. package/ai/examples/blocks/manifest.json +191 -0
  161. package/ai/examples/dashboard.tsx +150 -0
  162. package/ai/examples/marketing-hero.tsx +152 -0
  163. package/ai/examples/pricing.tsx +219 -0
  164. package/ai/examples/settings.tsx +140 -0
  165. package/ai/gotchas.json +85 -0
  166. package/ai/manifest.json +21 -0
  167. package/ai/rules.compact.md +73 -0
  168. package/ai/spec.json +2694 -2701
  169. package/ai/tasks/auth.json +23 -0
  170. package/ai/tasks/chat.json +28 -0
  171. package/ai/tasks/dashboard.json +39 -0
  172. package/ai/tasks/index.json +12 -0
  173. package/ai/tasks/marketing-hero.json +38 -0
  174. package/ai/tasks/pricing.json +42 -0
  175. package/ai/tasks/roadmap.json +22 -0
  176. package/ai/tasks/settings.json +34 -0
  177. package/dist/AGENTS.md +53 -0
  178. package/dist/README.md +27 -0
  179. package/dist/agent/once-ui-codegen.mdc +27 -0
  180. package/dist/ai/catalog.json +1650 -0
  181. package/dist/ai/catalog.seed.json +411 -0
  182. package/dist/ai/components/Accordion.json +136 -0
  183. package/dist/ai/components/AccordionGroup.json +128 -0
  184. package/dist/ai/components/Animation.json +146 -0
  185. package/dist/ai/components/Arrow.json +128 -0
  186. package/dist/ai/components/AutoScroll.json +130 -0
  187. package/dist/ai/components/Avatar.json +133 -0
  188. package/dist/ai/components/AvatarGroup.json +129 -0
  189. package/dist/ai/components/Background.json +131 -0
  190. package/dist/ai/components/Badge.json +132 -0
  191. package/dist/ai/components/Banner.json +122 -0
  192. package/dist/ai/components/BarChart.json +123 -0
  193. package/dist/ai/components/BlobFx.json +125 -0
  194. package/dist/ai/components/BlockQuote.json +132 -0
  195. package/dist/ai/components/Button.json +26 -0
  196. package/dist/ai/components/Card.json +129 -0
  197. package/dist/ai/components/Carousel.json +134 -0
  198. package/dist/ai/components/CelebrationFx.json +132 -0
  199. package/dist/ai/components/ChartHeader.json +130 -0
  200. package/dist/ai/components/ChartStatus.json +12 -0
  201. package/dist/ai/components/Checkbox.json +13 -0
  202. package/dist/ai/components/Chip.json +132 -0
  203. package/dist/ai/components/CodeBlock.json +122 -0
  204. package/dist/ai/components/ColorInput.json +13 -0
  205. package/dist/ai/components/Column.json +128 -0
  206. package/dist/ai/components/CompareImage.json +126 -0
  207. package/dist/ai/components/ContextMenu.json +22 -0
  208. package/dist/ai/components/CountFx.json +82 -0
  209. package/dist/ai/components/CountdownFx.json +11 -0
  210. package/dist/ai/components/Cursor.json +9 -0
  211. package/dist/ai/components/CursorCard.json +128 -0
  212. package/dist/ai/components/DataTooltip.json +15 -0
  213. package/dist/ai/components/DateInput.json +21 -0
  214. package/dist/ai/components/DatePicker.json +143 -0
  215. package/dist/ai/components/DateRangeInput.json +18 -0
  216. package/dist/ai/components/DateRangePicker.json +129 -0
  217. package/dist/ai/components/Dialog.json +134 -0
  218. package/dist/ai/components/DialogProvider.json +8 -0
  219. package/dist/ai/components/Dropdown.json +128 -0
  220. package/dist/ai/components/DropdownWrapper.json +28 -0
  221. package/dist/ai/components/EmojiPicker.json +129 -0
  222. package/dist/ai/components/EmojiPickerDropdown.json +13 -0
  223. package/dist/ai/components/Fade.json +130 -0
  224. package/dist/ai/components/FadingLettersFx.json +77 -0
  225. package/dist/ai/components/Feedback.json +132 -0
  226. package/dist/ai/components/Flex.json +125 -0
  227. package/dist/ai/components/FlipFx.json +133 -0
  228. package/dist/ai/components/GlitchFx.json +128 -0
  229. package/dist/ai/components/Grid.json +121 -0
  230. package/dist/ai/components/Heading.json +75 -0
  231. package/dist/ai/components/HeadingLink.json +127 -0
  232. package/dist/ai/components/HeadingNav.json +124 -0
  233. package/dist/ai/components/HoloFx.json +128 -0
  234. package/dist/ai/components/Hover.json +130 -0
  235. package/dist/ai/components/HoverCard.json +122 -0
  236. package/dist/ai/components/Icon.json +132 -0
  237. package/dist/ai/components/IconButton.json +22 -0
  238. package/dist/ai/components/InfiniteScroll.json +130 -0
  239. package/dist/ai/components/InlineCode.json +126 -0
  240. package/dist/ai/components/Input.json +24 -0
  241. package/dist/ai/components/InteractiveDetails.json +14 -0
  242. package/dist/ai/components/Kbar.json +10 -0
  243. package/dist/ai/components/Kbd.json +127 -0
  244. package/dist/ai/components/Legend.json +14 -0
  245. package/dist/ai/components/LetterFx.json +14 -0
  246. package/dist/ai/components/Line.json +125 -0
  247. package/dist/ai/components/LineBarChart.json +123 -0
  248. package/dist/ai/components/LineChart.json +123 -0
  249. package/dist/ai/components/LinearGauge.json +130 -0
  250. package/dist/ai/components/LinearGradient.json +15 -0
  251. package/dist/ai/components/List.json +127 -0
  252. package/dist/ai/components/ListItem.json +77 -0
  253. package/dist/ai/components/Logo.json +16 -0
  254. package/dist/ai/components/LogoCloud.json +124 -0
  255. package/dist/ai/components/Mask.json +131 -0
  256. package/dist/ai/components/MasonryGrid.json +132 -0
  257. package/dist/ai/components/MatrixFx.json +135 -0
  258. package/dist/ai/components/Media.json +142 -0
  259. package/dist/ai/components/MediaUpload.json +122 -0
  260. package/dist/ai/components/MegaMenu.json +125 -0
  261. package/dist/ai/components/MobileMegaMenu.json +125 -0
  262. package/dist/ai/components/Modal.json +12 -0
  263. package/dist/ai/components/NavIcon.json +127 -0
  264. package/dist/ai/components/NumberInput.json +16 -0
  265. package/dist/ai/components/OTPInput.json +13 -0
  266. package/dist/ai/components/OgCard.json +135 -0
  267. package/dist/ai/components/Option.json +137 -0
  268. package/dist/ai/components/Particle.json +135 -0
  269. package/dist/ai/components/PasswordInput.json +8 -0
  270. package/dist/ai/components/PieChart.json +123 -0
  271. package/dist/ai/components/ProgressBar.json +131 -0
  272. package/dist/ai/components/Pulse.json +129 -0
  273. package/dist/ai/components/RadialGauge.json +134 -0
  274. package/dist/ai/components/RadialGradient.json +16 -0
  275. package/dist/ai/components/RadioButton.json +17 -0
  276. package/dist/ai/components/RevealFx.json +131 -0
  277. package/dist/ai/components/Row.json +128 -0
  278. package/dist/ai/components/Schema.json +17 -0
  279. package/dist/ai/components/ScrollContainer.json +126 -0
  280. package/dist/ai/components/ScrollToTop.json +124 -0
  281. package/dist/ai/components/Scroller.json +128 -0
  282. package/dist/ai/components/SegmentedControl.json +132 -0
  283. package/dist/ai/components/Select.json +21 -0
  284. package/dist/ai/components/ShineFx.json +80 -0
  285. package/dist/ai/components/Skeleton.json +129 -0
  286. package/dist/ai/components/Slider.json +17 -0
  287. package/dist/ai/components/SmartLink.json +17 -0
  288. package/dist/ai/components/Spinner.json +127 -0
  289. package/dist/ai/components/SplitView.json +129 -0
  290. package/dist/ai/components/StatusIndicator.json +128 -0
  291. package/dist/ai/components/StyleOverlay.json +126 -0
  292. package/dist/ai/components/StylePanel.json +125 -0
  293. package/dist/ai/components/Swiper.json +130 -0
  294. package/dist/ai/components/Switch.json +20 -0
  295. package/dist/ai/components/Table.json +140 -0
  296. package/dist/ai/components/Tag.json +129 -0
  297. package/dist/ai/components/TagInput.json +12 -0
  298. package/dist/ai/components/Text.json +72 -0
  299. package/dist/ai/components/Textarea.json +24 -0
  300. package/dist/ai/components/ThemeSwitcher.json +122 -0
  301. package/dist/ai/components/TiltFx.json +126 -0
  302. package/dist/ai/components/Timeline.json +126 -0
  303. package/dist/ai/components/Toast.json +13 -0
  304. package/dist/ai/components/Toaster.json +14 -0
  305. package/dist/ai/components/ToggleButton.json +24 -0
  306. package/dist/ai/components/Tooltip.json +129 -0
  307. package/dist/ai/components/TypeFx.json +15 -0
  308. package/dist/ai/components/User.json +15 -0
  309. package/dist/ai/components/UserMenu.json +16 -0
  310. package/dist/ai/components/WeatherFx.json +133 -0
  311. package/dist/ai/eval-tasks.md +71 -0
  312. package/dist/ai/examples/blocks/manifest.json +191 -0
  313. package/dist/ai/gotchas.json +85 -0
  314. package/dist/ai/manifest.json +21 -0
  315. package/dist/ai/recipes.md +149 -0
  316. package/dist/ai/rules.compact.md +73 -0
  317. package/dist/ai/rules.md +217 -0
  318. package/dist/ai/spec.json +2695 -0
  319. package/dist/ai/tasks/auth.json +23 -0
  320. package/dist/ai/tasks/chat.json +28 -0
  321. package/dist/ai/tasks/dashboard.json +39 -0
  322. package/dist/ai/tasks/index.json +12 -0
  323. package/dist/ai/tasks/marketing-hero.json +38 -0
  324. package/dist/ai/tasks/pricing.json +42 -0
  325. package/dist/ai/tasks/roadmap.json +22 -0
  326. package/dist/ai/tasks/settings.json +34 -0
  327. package/dist/components/ContextMenu.d.ts +2 -2
  328. package/dist/components/ContextMenu.d.ts.map +1 -1
  329. package/dist/components/ContextMenu.js +3 -3
  330. package/dist/components/ContextMenu.js.map +1 -1
  331. package/dist/components/ElementType.d.ts.map +1 -1
  332. package/dist/components/ElementType.js +6 -4
  333. package/dist/components/ElementType.js.map +1 -1
  334. package/dist/components/Media.d.ts.map +1 -1
  335. package/dist/components/Media.js +6 -3
  336. package/dist/components/Media.js.map +1 -1
  337. package/dist/components/MediaVideoPlayer.d.ts +12 -0
  338. package/dist/components/MediaVideoPlayer.d.ts.map +1 -0
  339. package/dist/components/MediaVideoPlayer.js +246 -0
  340. package/dist/components/MediaVideoPlayer.js.map +1 -0
  341. package/dist/components/MediaVideoPlayer.module.scss +90 -0
  342. package/dist/components/Table.d.ts +34 -6
  343. package/dist/components/Table.d.ts.map +1 -1
  344. package/dist/components/Table.js +114 -30
  345. package/dist/components/Table.js.map +1 -1
  346. package/dist/components/Table.module.scss +174 -3
  347. package/dist/components/ThemeInit.d.ts.map +1 -1
  348. package/dist/components/ThemeInit.js +2 -1
  349. package/dist/components/ThemeInit.js.map +1 -1
  350. package/dist/components/Timeline.d.ts +1 -1
  351. package/dist/components/Timeline.d.ts.map +1 -1
  352. package/dist/components/Timeline.js +16 -52
  353. package/dist/components/Timeline.js.map +1 -1
  354. package/dist/data/emoji-data.json +0 -10
  355. package/dist/icons.d.ts.map +1 -1
  356. package/dist/icons.js +7 -2
  357. package/dist/icons.js.map +1 -1
  358. package/dist/index.d.ts +0 -1
  359. package/dist/index.d.ts.map +1 -1
  360. package/dist/index.js +0 -1
  361. package/dist/index.js.map +1 -1
  362. package/dist/modules/code/CodeBlock.impl.d.ts.map +1 -1
  363. package/dist/modules/code/CodeBlock.impl.js +11 -5
  364. package/dist/modules/code/CodeBlock.impl.js.map +1 -1
  365. package/dist/modules/seo/Schema.d.ts.map +1 -1
  366. package/dist/modules/seo/Schema.js +3 -4
  367. package/dist/modules/seo/Schema.js.map +1 -1
  368. package/dist/package.json +33 -3
  369. package/dist/server/og-url-validation.d.ts +10 -0
  370. package/dist/server/og-url-validation.d.ts.map +1 -0
  371. package/dist/server/og-url-validation.js +234 -0
  372. package/dist/server/og-url-validation.js.map +1 -0
  373. package/dist/server/og-utils.d.ts +5 -2
  374. package/dist/server/og-utils.d.ts.map +1 -1
  375. package/dist/server/og-utils.js +39 -14
  376. package/dist/server/og-utils.js.map +1 -1
  377. package/dist/utils/index.d.ts +1 -0
  378. package/dist/utils/index.d.ts.map +1 -1
  379. package/dist/utils/index.js +1 -0
  380. package/dist/utils/index.js.map +1 -1
  381. package/dist/utils/safe-html.d.ts +19 -0
  382. package/dist/utils/safe-html.d.ts.map +1 -0
  383. package/dist/utils/safe-html.js +43 -0
  384. package/dist/utils/safe-html.js.map +1 -0
  385. package/package.json +159 -127
  386. package/scripts/copy-files.js +103 -0
  387. package/scripts/generate-ai-spec.js +464 -0
  388. package/scripts/generate-emoji-data.js +128 -0
  389. package/scripts/init-agent.js +156 -0
  390. package/scripts/validate-ai-code.js +149 -0
  391. package/LICENSE.md +0 -21
  392. package/next-env.d.ts +0 -5
@@ -0,0 +1,464 @@
1
+ /**
2
+ * Generates ai/spec.json — a compressed, machine-readable description of every
3
+ * exported component: own props (with types and defaults), shared prop mixins
4
+ * (encoded once), and token aliases.
5
+ *
6
+ * Compression strategy:
7
+ * - Props declared in src/interfaces.ts are grouped into "mixins" and emitted
8
+ * once; components only reference mixin names.
9
+ * - Props inherited from React/DOM typings (node_modules) are omitted.
10
+ * - Wrapper components (e.g. Row extends ComponentProps<typeof Flex>) get an
11
+ * "extends" reference instead of repeating the base component's props.
12
+ * - Each prop is a single string: "type", "type = default", or "!type" (required).
13
+ */
14
+
15
+ const fs = require("fs");
16
+ const path = require("path");
17
+ const ts = require("typescript");
18
+
19
+ const ROOT = path.join(__dirname, "..");
20
+ const SRC = path.join(ROOT, "src");
21
+ const OUT_DIR = path.join(ROOT, "ai");
22
+ const OUT_FILE = path.join(OUT_DIR, "spec.json");
23
+
24
+ const BARRELS = [
25
+ { file: path.join(SRC, "components", "index.ts"), group: "components" },
26
+ { file: path.join(SRC, "modules", "index.ts"), group: "modules" },
27
+ ];
28
+
29
+ // Internal/low-level exports that AI should not use directly
30
+ const EXCLUDE = new Set([
31
+ "ServerFlex",
32
+ "ClientFlex",
33
+ "ServerGrid",
34
+ "ClientGrid",
35
+ "ElementType",
36
+ "FocusTrap",
37
+ "ScrollLock",
38
+ "ThemeInit",
39
+ "ArrowNavigation",
40
+ "Meta",
41
+ ]);
42
+
43
+ // Token aliases worth defining once in the spec (read from types.ts source)
44
+ const TOKEN_ALIASES = [
45
+ "SpacingToken",
46
+ "StaticSpacingToken",
47
+ "ResponsiveSpacingToken",
48
+ "TShirtSizes",
49
+ "ColorScheme",
50
+ "ColorWeight",
51
+ "Colors",
52
+ "RadiusSize",
53
+ "ShadowSize",
54
+ "TextVariant",
55
+ "TextType",
56
+ "TextWeight",
57
+ "TextSize",
58
+ "gridSize",
59
+ "opacity",
60
+ "flex",
61
+ "CSSUnit",
62
+ ];
63
+
64
+ function loadTsConfig() {
65
+ const configPath = path.join(ROOT, "tsconfig.json");
66
+ const configFile = ts.readConfigFile(configPath, ts.sys.readFile);
67
+ const parsed = ts.parseJsonConfigFileContent(configFile.config, ts.sys, ROOT);
68
+ return parsed.options;
69
+ }
70
+
71
+ function isInNodeModules(decl) {
72
+ return decl.getSourceFile().fileName.includes("node_modules");
73
+ }
74
+
75
+ function normalize(p) {
76
+ return p.replace(/\\/g, "/");
77
+ }
78
+
79
+ /** Strip quotes from string literal default values */
80
+ function cleanDefault(text) {
81
+ const t = text.trim();
82
+ if (/^["'].*["']$/.test(t)) return t.slice(1, -1);
83
+ return t;
84
+ }
85
+
86
+ /** Compact a type-node source text: collapse whitespace, strip leading pipe */
87
+ function typeText(node) {
88
+ if (!node) return "unknown";
89
+ return node
90
+ .getText()
91
+ .replace(/\s*\n\s*/g, " ")
92
+ .replace(/\s{2,}/g, " ")
93
+ .replace(/^\|\s*/, "");
94
+ }
95
+
96
+ function main() {
97
+ const options = loadTsConfig();
98
+ const rootNames = BARRELS.map((b) => b.file).filter(fs.existsSync);
99
+ const program = ts.createProgram(rootNames, options);
100
+ const checker = program.getTypeChecker();
101
+
102
+ const interfacesFile = normalize(path.join(SRC, "interfaces.ts"));
103
+
104
+ const mixinsUsed = new Map(); // mixinName -> Map<propName, propString>
105
+ const components = {};
106
+ const warnings = [];
107
+
108
+ /** Resolve the function node (arrow/function expr) implementing a component */
109
+ function getComponentFunction(decl) {
110
+ if (ts.isFunctionDeclaration(decl)) return decl;
111
+ if (ts.isVariableDeclaration(decl) && decl.initializer) {
112
+ let init = decl.initializer;
113
+ // unwrap forwardRef(...) / memo(forwardRef(...))
114
+ while (ts.isCallExpression(init)) {
115
+ const arg = init.arguments[0];
116
+ if (!arg) return undefined;
117
+ init = arg;
118
+ }
119
+ if (ts.isArrowFunction(init) || ts.isFunctionExpression(init)) return init;
120
+ }
121
+ return undefined;
122
+ }
123
+
124
+ /** Extract destructuring defaults from a component function's first param */
125
+ function getDefaults(fn) {
126
+ const defaults = {};
127
+ if (!fn || !fn.parameters.length) return defaults;
128
+ const param = fn.parameters[0];
129
+ if (!ts.isObjectBindingPattern(param.name)) return defaults;
130
+ for (const el of param.name.elements) {
131
+ if (el.initializer && ts.isIdentifier(el.propertyName ?? el.name)) {
132
+ const key = (el.propertyName ?? el.name).getText();
133
+ defaults[key] = cleanDefault(el.initializer.getText());
134
+ }
135
+ }
136
+ return defaults;
137
+ }
138
+
139
+ /** Get the props type for a component declaration */
140
+ function getPropsType(decl) {
141
+ // forwardRef<Ref, Props>(...)
142
+ if (ts.isVariableDeclaration(decl) && decl.initializer && ts.isCallExpression(decl.initializer)) {
143
+ const call = decl.initializer;
144
+ if (call.typeArguments && call.typeArguments.length >= 2) {
145
+ return checker.getTypeFromTypeNode(call.typeArguments[1]);
146
+ }
147
+ }
148
+ // const X: React.FC<Props> = ...
149
+ if (ts.isVariableDeclaration(decl) && decl.type && ts.isTypeReferenceNode(decl.type)) {
150
+ const typeName = decl.type.typeName.getText();
151
+ if (
152
+ /(^|\.)(FC|FunctionComponent)$/.test(typeName) &&
153
+ decl.type.typeArguments &&
154
+ decl.type.typeArguments.length >= 1
155
+ ) {
156
+ return checker.getTypeFromTypeNode(decl.type.typeArguments[0]);
157
+ }
158
+ }
159
+ const fn = getComponentFunction(decl);
160
+ if (fn && fn.parameters.length && fn.parameters[0].type) {
161
+ return checker.getTypeFromTypeNode(fn.parameters[0].type);
162
+ }
163
+ return undefined;
164
+ }
165
+
166
+ /** Build the prop string: "type", "type = default", "!type" (required) */
167
+ function propString(propSymbol, decl, defaults) {
168
+ const name = propSymbol.getName();
169
+ let type = "unknown";
170
+ if (
171
+ (ts.isPropertySignature(decl) || ts.isPropertyDeclaration(decl)) &&
172
+ decl.type
173
+ ) {
174
+ type = typeText(decl.type);
175
+ } else {
176
+ type = checker.typeToString(checker.getTypeOfSymbol(propSymbol));
177
+ }
178
+ const optional = (propSymbol.flags & ts.SymbolFlags.Optional) !== 0;
179
+ let out = optional ? type : `!${type}`;
180
+ if (defaults && defaults[name] !== undefined) {
181
+ out += ` = ${defaults[name]}`;
182
+ }
183
+ return out;
184
+ }
185
+
186
+ function processExport(name, symbol, group) {
187
+ if (EXCLUDE.has(name)) return;
188
+ if (!/^[A-Z]/.test(name)) return; // components only
189
+
190
+ let target = symbol;
191
+ if (target.flags & ts.SymbolFlags.Alias) {
192
+ target = checker.getAliasedSymbol(target);
193
+ }
194
+ const decl = target.valueDeclaration ?? (target.declarations && target.declarations[0]);
195
+ if (!decl) return;
196
+ if (!ts.isVariableDeclaration(decl) && !ts.isFunctionDeclaration(decl)) return;
197
+
198
+ const propsType = getPropsType(decl);
199
+ if (!propsType) {
200
+ warnings.push(`No props type resolved for ${name}; skipped`);
201
+ return;
202
+ }
203
+
204
+ // For union props (e.g. ButtonProps | AnchorProps) merge member properties
205
+ const typesToScan = propsType.isUnion() ? propsType.types : [propsType];
206
+ const seen = new Map(); // propName -> symbol
207
+ for (const t of typesToScan) {
208
+ for (const p of checker.getPropertiesOfType(t)) {
209
+ if (!seen.has(p.getName())) seen.set(p.getName(), p);
210
+ }
211
+ }
212
+
213
+ const fn = getComponentFunction(decl);
214
+ const defaults = getDefaults(fn);
215
+
216
+ const ownFile = normalize(decl.getSourceFile().fileName);
217
+ const mixins = new Set();
218
+ const extendsComponents = new Set();
219
+ const props = {};
220
+
221
+ for (const [propName, propSym] of seen) {
222
+ const pDecl = propSym.valueDeclaration ?? (propSym.declarations && propSym.declarations[0]);
223
+ if (!pDecl) continue;
224
+ if (isInNodeModules(pDecl)) continue; // React/DOM inherited noise
225
+
226
+ const declFile = normalize(pDecl.getSourceFile().fileName);
227
+
228
+ if (declFile === interfacesFile) {
229
+ // shared mixin prop: attribute to parent interface, emit once globally
230
+ const parent = pDecl.parent && ts.isInterfaceDeclaration(pDecl.parent) ? pDecl.parent.name.getText() : null;
231
+ if (parent) {
232
+ mixins.add(parent);
233
+ if (!mixinsUsed.has(parent)) mixinsUsed.set(parent, new Map());
234
+ if (!mixinsUsed.get(parent).has(propName)) {
235
+ mixinsUsed.get(parent).set(propName, propString(propSym, pDecl, {}));
236
+ }
237
+ // keep component-level default override visible
238
+ if (defaults[propName] !== undefined) {
239
+ props[propName] = propString(propSym, pDecl, defaults);
240
+ }
241
+ continue;
242
+ }
243
+ }
244
+
245
+ if (declFile !== ownFile && declFile.includes("/src/")) {
246
+ // declared in another component's file → wrapper relationship
247
+ const base = path.basename(declFile).replace(/\.(tsx|ts)$/, "");
248
+ extendsComponents.add(base);
249
+ continue;
250
+ }
251
+
252
+ props[propName] = propString(propSym, pDecl, defaults);
253
+ }
254
+
255
+ const entry = { group };
256
+ if (extendsComponents.size) entry.extends = [...extendsComponents];
257
+ if (mixins.size) entry.mixins = [...mixins].sort();
258
+ if (Object.keys(props).length) entry.props = props;
259
+ components[name] = entry;
260
+ }
261
+
262
+ for (const barrel of BARRELS) {
263
+ if (!fs.existsSync(barrel.file)) continue;
264
+ const sf = program.getSourceFile(barrel.file);
265
+ if (!sf) continue;
266
+ const moduleSymbol = checker.getSymbolAtLocation(sf);
267
+ if (!moduleSymbol) continue;
268
+ for (const exp of checker.getExportsOfModule(moduleSymbol)) {
269
+ processExport(exp.getName(), exp, barrel.group);
270
+ }
271
+ }
272
+
273
+ // Emit interfaces.ts types referenced by name in prop strings (e.g. FlexBreakpointProps)
274
+ const interfacesSf = program.getSourceFile(path.join(SRC, "interfaces.ts"));
275
+ if (interfacesSf) {
276
+ const declared = new Map();
277
+ interfacesSf.forEachChild((node) => {
278
+ if (ts.isInterfaceDeclaration(node)) declared.set(node.name.getText(), node);
279
+ });
280
+ const allPropStrings = [];
281
+ for (const c of Object.values(components)) {
282
+ if (c.props) allPropStrings.push(...Object.values(c.props));
283
+ }
284
+ for (const m of mixinsUsed.values()) {
285
+ allPropStrings.push(...m.values());
286
+ }
287
+ const blob = allPropStrings.join("\n");
288
+ for (const [ifaceName, node] of declared) {
289
+ if (mixinsUsed.has(ifaceName)) continue;
290
+ if (!new RegExp(`\\b${ifaceName}\\b`).test(blob)) continue;
291
+ const propsMap = new Map();
292
+ for (const member of node.members) {
293
+ if (!ts.isPropertySignature(member) || !member.name) continue;
294
+ const pName = member.name.getText();
295
+ const optional = !!member.questionToken;
296
+ const t = typeText(member.type);
297
+ propsMap.set(pName, optional ? t : `!${t}`);
298
+ }
299
+ mixinsUsed.set(ifaceName, propsMap);
300
+ }
301
+ }
302
+
303
+ // Token aliases from types.ts (compact source text)
304
+ const tokens = {};
305
+ const typesSf = program.getSourceFile(path.join(SRC, "types.ts"));
306
+ if (typesSf) {
307
+ typesSf.forEachChild((node) => {
308
+ if (ts.isTypeAliasDeclaration(node) && TOKEN_ALIASES.includes(node.name.getText())) {
309
+ tokens[node.name.getText()] = typeText(node.type);
310
+ }
311
+ });
312
+ }
313
+
314
+ // IconName erases to string (Record<string, IconType>) — emit actual keys from icons.ts
315
+ const iconsSf = program.getSourceFile(path.join(SRC, "icons.ts"));
316
+ if (iconsSf) {
317
+ iconsSf.forEachChild((node) => {
318
+ if (!ts.isVariableStatement(node)) return;
319
+ for (const decl of node.declarationList.declarations) {
320
+ if (decl.name.getText() !== "iconLibrary" || !decl.initializer) continue;
321
+ if (!ts.isObjectLiteralExpression(decl.initializer)) continue;
322
+ const names = decl.initializer.properties
323
+ .map((p) => (p.name ? p.name.getText() : null))
324
+ .filter(Boolean);
325
+ tokens.IconName = names.map((n) => `"${n}"`).join(" | ");
326
+ }
327
+ });
328
+ }
329
+
330
+ const mixins = {};
331
+ for (const [name, propsMap] of [...mixinsUsed.entries()].sort()) {
332
+ mixins[name] = Object.fromEntries(propsMap);
333
+ }
334
+
335
+ const pkg = JSON.parse(fs.readFileSync(path.join(ROOT, "package.json"), "utf8"));
336
+ const spec = {
337
+ name: pkg.name,
338
+ version: pkg.version,
339
+ generated: new Date().toISOString().split("T")[0],
340
+ format:
341
+ "props are 'type', 'type = default', or '!type' (required). Components with 'mixins' also accept all props of those mixins. 'extends' means all props of that component are accepted.",
342
+ tokens,
343
+ mixins,
344
+ components,
345
+ };
346
+
347
+ fs.mkdirSync(OUT_DIR, { recursive: true });
348
+ fs.writeFileSync(OUT_FILE, JSON.stringify(spec, null, 1));
349
+
350
+ emitArtifacts(spec, pkg.version);
351
+
352
+ const count = Object.keys(components).length;
353
+ console.log(`AI spec generated: ${count} components -> ${path.relative(ROOT, OUT_FILE)}`);
354
+ if (warnings.length) {
355
+ console.log(`Warnings (${warnings.length}):`);
356
+ for (const w of warnings) console.log(` - ${w}`);
357
+ }
358
+ }
359
+
360
+ /** Post-process Row/Column and emit sliced agent artifacts */
361
+ function emitArtifacts(spec, version) {
362
+ const shorthands = {
363
+ fill: { replaces: "fillWidth fillHeight", on: ["Row", "Column", "Flex", "Grid"] },
364
+ fit: { replaces: "fitWidth fitHeight", on: ["Row", "Column", "Flex", "Grid"] },
365
+ center: { replaces: 'horizontal="center" vertical="center"', on: ["Row", "Column", "Flex"] },
366
+ layout: {
367
+ Column: { preferOver: 'Flex direction="column"' },
368
+ Row: { preferOver: 'Flex direction="row"' },
369
+ Flex: { useWhen: "direction changes at breakpoints only" },
370
+ },
371
+ };
372
+
373
+ if (spec.components.Row) {
374
+ spec.components.Row.preset = { direction: "row" };
375
+ spec.components.Row.preferOver = 'Flex with direction="row"';
376
+ }
377
+ if (spec.components.Column) {
378
+ spec.components.Column.preset = { direction: "column" };
379
+ spec.components.Column.preferOver = 'Flex with direction="column"';
380
+ }
381
+ spec.shorthands = shorthands;
382
+
383
+ fs.writeFileSync(OUT_FILE, JSON.stringify(spec, null, 1));
384
+
385
+ const seedPath = path.join(OUT_DIR, "catalog.seed.json");
386
+ const seed = fs.existsSync(seedPath)
387
+ ? JSON.parse(fs.readFileSync(seedPath, "utf8"))
388
+ : {};
389
+
390
+ const catalog = { version, generated: spec.generated, components: {} };
391
+ for (const [name, entry] of Object.entries(spec.components)) {
392
+ const meta = seed[name] || {};
393
+ catalog.components[name] = {
394
+ group: entry.group,
395
+ extends: entry.extends,
396
+ purpose: meta.purpose || `${name} component`,
397
+ tags: meta.tags || [entry.group],
398
+ ...(meta.avoid ? { avoid: meta.avoid } : {}),
399
+ ...(meta.preferOver ? { preferOver: meta.preferOver } : {}),
400
+ ...(meta.pairsWith ? { pairsWith: meta.pairsWith } : {}),
401
+ };
402
+ }
403
+ fs.writeFileSync(path.join(OUT_DIR, "catalog.json"), JSON.stringify(catalog, null, 1));
404
+
405
+ const componentsDir = path.join(OUT_DIR, "components");
406
+ fs.mkdirSync(componentsDir, { recursive: true });
407
+ for (const [name, entry] of Object.entries(spec.components)) {
408
+ const slice = {
409
+ name,
410
+ ...entry,
411
+ mixinsRef: entry.mixins || [],
412
+ tokensRef: Object.keys(entry.mixins || []).length ? "see spec.json mixins" : undefined,
413
+ };
414
+ if (slice.mixins) {
415
+ slice.resolvedMixins = {};
416
+ for (const mixin of slice.mixins) {
417
+ if (spec.mixins[mixin]) slice.resolvedMixins[mixin] = spec.mixins[mixin];
418
+ }
419
+ }
420
+ fs.writeFileSync(path.join(componentsDir, `${name}.json`), JSON.stringify(slice, null, 1));
421
+ }
422
+
423
+ const manifest = {
424
+ version,
425
+ generated: spec.generated,
426
+ files: {
427
+ spec: "spec.json",
428
+ catalog: "catalog.json",
429
+ rules: "rules.compact.md",
430
+ rulesFull: "rules.md",
431
+ recipes: "recipes.md",
432
+ gotchas: "gotchas.json",
433
+ tasks: "tasks/index.json",
434
+ examples: "examples/",
435
+ blocks: "examples/blocks/manifest.json",
436
+ components: "components/",
437
+ },
438
+ bootstrap: ["rules.compact.md", "catalog.json"],
439
+ resolve: "tasks/index.json",
440
+ };
441
+ fs.writeFileSync(path.join(OUT_DIR, "manifest.json"), JSON.stringify(manifest, null, 1));
442
+
443
+ syncDocsPublic();
444
+ console.log(`AI artifacts: catalog + ${Object.keys(spec.components).length} component slices`);
445
+ }
446
+
447
+ function syncDocsPublic() {
448
+ const docsAi = path.join(ROOT, "../../apps/docs/public/ai");
449
+ if (!fs.existsSync(path.dirname(docsAi))) return;
450
+ copyDir(OUT_DIR, docsAi);
451
+ console.log(`Synced AI artifacts -> ${path.relative(ROOT, docsAi)}`);
452
+ }
453
+
454
+ function copyDir(src, dest) {
455
+ if (!fs.existsSync(dest)) fs.mkdirSync(dest, { recursive: true });
456
+ for (const entry of fs.readdirSync(src, { withFileTypes: true })) {
457
+ const srcPath = path.join(src, entry.name);
458
+ const destPath = path.join(dest, entry.name);
459
+ if (entry.isDirectory()) copyDir(srcPath, destPath);
460
+ else fs.copyFileSync(srcPath, destPath);
461
+ }
462
+ }
463
+
464
+ main();
@@ -0,0 +1,128 @@
1
+ const fs = require("fs");
2
+ const path = require("path");
3
+ const https = require("https");
4
+
5
+ const categories = {
6
+ smileys: ["face", "emotion", "person", "smile", "laugh", "sad", "angry", "love", "heart"],
7
+ animals: ["animal", "creature", "pet", "bug", "insect", "bird", "fish", "reptile", "mammal"],
8
+ food: ["food", "drink", "fruit", "vegetable", "meal", "breakfast", "lunch", "dinner"],
9
+ activities: ["sport", "game", "hobby", "activity", "exercise", "play"],
10
+ travel: [
11
+ "travel",
12
+ "place",
13
+ "building",
14
+ "location",
15
+ "transport",
16
+ "vehicle",
17
+ "car",
18
+ "plane",
19
+ "ship",
20
+ ],
21
+ objects: ["object", "tool", "device", "book", "money", "office", "clothing"],
22
+ symbols: ["symbol", "sign", "arrow", "shape", "math", "punctuation", "currency", "religion"],
23
+ flags: ["flag", "country", "nation"],
24
+ };
25
+
26
+ function fetchEmojiData() {
27
+ return new Promise((resolve, reject) => {
28
+ https
29
+ .get("https://raw.githubusercontent.com/github/gemoji/master/db/emoji.json", (res) => {
30
+ let data = "";
31
+ res.on("data", (chunk) => {
32
+ data += chunk;
33
+ });
34
+ res.on("end", () => {
35
+ try {
36
+ const emojiData = JSON.parse(data);
37
+ resolve(emojiData);
38
+ } catch (e) {
39
+ reject(e);
40
+ }
41
+ });
42
+ })
43
+ .on("error", (err) => {
44
+ reject(err);
45
+ });
46
+ });
47
+ }
48
+
49
+ function categorizeEmoji(emoji) {
50
+ let bestCategory = "objects";
51
+ let bestScore = 0;
52
+
53
+ const textToCheck = [emoji.description || "", ...(emoji.aliases || []), ...(emoji.tags || [])]
54
+ .join(" ")
55
+ .toLowerCase();
56
+
57
+ for (const [category, keywords] of Object.entries(categories)) {
58
+ const score = keywords.reduce((count, keyword) => {
59
+ return count + (textToCheck.includes(keyword) ? 1 : 0);
60
+ }, 0);
61
+
62
+ if (score > bestScore) {
63
+ bestScore = score;
64
+ bestCategory = category;
65
+ }
66
+ }
67
+
68
+ return bestCategory;
69
+ }
70
+
71
+ async function generateEmojiData() {
72
+ try {
73
+ console.log("Fetching emoji data...");
74
+ const rawEmojiData = await fetchEmojiData();
75
+
76
+ const categorizedEmojis = {};
77
+
78
+ Object.keys(categories).forEach((category) => {
79
+ categorizedEmojis[category] = [];
80
+ });
81
+
82
+ // Helper function to check if a string contains valid emoji characters
83
+ function isValidEmoji(str) {
84
+ // Check if the string exists and isn't just whitespace
85
+ if (!str || str.trim() === "") return false;
86
+
87
+ // Check for replacement characters or known broken sequences
88
+ if (str.includes("�")) return false;
89
+
90
+ // Simple length check - emoji shouldn't be too long
91
+ if (str.length > 10) return false;
92
+
93
+ return true;
94
+ }
95
+
96
+ rawEmojiData.forEach((emoji) => {
97
+ if (emoji.emoji && isValidEmoji(emoji.emoji)) {
98
+ const category = categorizeEmoji(emoji);
99
+ categorizedEmojis[category].push({
100
+ char: emoji.emoji,
101
+ description: emoji.description || "",
102
+ aliases: emoji.aliases || [],
103
+ tags: emoji.tags || [],
104
+ });
105
+ }
106
+ });
107
+
108
+ const outputPath = path.join(__dirname, "../src/data/emoji-data.json");
109
+
110
+ const dir = path.dirname(outputPath);
111
+ if (!fs.existsSync(dir)) {
112
+ fs.mkdirSync(dir, { recursive: true });
113
+ }
114
+
115
+ fs.writeFileSync(outputPath, JSON.stringify(categorizedEmojis, null, 2), { encoding: "utf8" });
116
+
117
+ console.log(`Emoji data generated successfully at ${outputPath}`);
118
+ console.log(`Total emojis: ${rawEmojiData.length}`);
119
+ Object.keys(categorizedEmojis).forEach((category) => {
120
+ console.log(`${category}: ${categorizedEmojis[category].length} emojis`);
121
+ });
122
+ } catch (error) {
123
+ console.error("Error generating emoji data:", error);
124
+ process.exit(1);
125
+ }
126
+ }
127
+
128
+ generateEmojiData();