@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,303 @@
1
+ "use client";
2
+
3
+ import { Checkbox, Column, IconButton, Input, Row, Text, Card, Icon, DropdownWrapper, Button, ToggleButton, CountFx } from "@once-ui-system/core";
4
+ import { useEffect, useMemo, useState } from "react";
5
+
6
+ type Align = "start" | "center" | "end";
7
+
8
+ export type TableColumn<T = any> = {
9
+ key: string;
10
+ title: React.ReactNode;
11
+ render: (item: T, index: number) => React.ReactNode;
12
+ align?: Align;
13
+ width?: number; // in grid columns (optional)
14
+ };
15
+
16
+ export type Table1Props<T = any> = React.ComponentProps<typeof Column> & {
17
+ data: T[];
18
+ columns: TableColumn<T>[];
19
+ selectable?: boolean;
20
+ getId?: (item: T, index: number) => string;
21
+ itemsPerPageOptions?: number[];
22
+ initialItemsPerPage?: number;
23
+ heading?: React.ReactNode;
24
+ showSearch?: boolean;
25
+ filterFn?: (item: T, query: string) => boolean;
26
+ onSelectionChange?: (ids: Set<string>) => void;
27
+ };
28
+
29
+ export const Table1: React.FC<Table1Props> = ({
30
+ data,
31
+ columns,
32
+ selectable = false,
33
+ getId,
34
+ itemsPerPageOptions = [5, 25, 50, 100],
35
+ initialItemsPerPage = 5,
36
+ heading = "Items",
37
+ showSearch = true,
38
+ filterFn,
39
+ onSelectionChange,
40
+ ...flex
41
+ }) => {
42
+
43
+ const [itemsPerPage, setItemsPerPage] = useState(initialItemsPerPage);
44
+ const [search, setSearch] = useState("");
45
+ const [currentPage, setCurrentPage] = useState(1);
46
+ const [selectedItems, setSelectedItems] = useState(new Set<string>());
47
+
48
+ // Filter by search
49
+ const filteredContent = useMemo(() => {
50
+ const q = search.trim().toLowerCase();
51
+ if (!q) return data;
52
+ if (filterFn) return data.filter((item) => filterFn(item, q));
53
+ // Default fallback filter: stringify
54
+ return data.filter((item) => JSON.stringify(item).toLowerCase().includes(q));
55
+ }, [search, data, filterFn]);
56
+
57
+ // Pagination calculations
58
+ const totalitemsPerPage = Math.max(1, Math.ceil(filteredContent.length / itemsPerPage));
59
+ const startIndex = (currentPage - 1) * itemsPerPage;
60
+ const endIndex = startIndex + itemsPerPage;
61
+ const paginatedItems = filteredContent.slice(startIndex, endIndex);
62
+
63
+ // Reset to first page when filters or page size change
64
+ useEffect(() => {
65
+ setCurrentPage(1);
66
+ }, [search, itemsPerPage]);
67
+
68
+ // Selection helpers
69
+ const resolveId = (item: any, index: number) => (getId ? getId(item, index) : String(index));
70
+ const isSelected = (id: string) => selectedItems.has(id);
71
+ const toggleSelect = (id: string) => {
72
+ setSelectedItems((prev) => {
73
+ const next = new Set(prev);
74
+ if (next.has(id)) next.delete(id); else next.add(id);
75
+ onSelectionChange?.(next);
76
+ return next;
77
+ });
78
+ };
79
+
80
+ const currentPageIds = paginatedItems.map((i, idx) => resolveId(i, startIndex + idx));
81
+ const allCurrentSelected = currentPageIds.length > 0 && currentPageIds.every((id) => selectedItems.has(id));
82
+ const someCurrentSelected = currentPageIds.some((id) => selectedItems.has(id));
83
+ const toggleSelectAllCurrent = () => {
84
+ setSelectedItems((prev) => {
85
+ const next = new Set(prev);
86
+ if (allCurrentSelected) {
87
+ currentPageIds.forEach((id) => next.delete(id));
88
+ } else {
89
+ currentPageIds.forEach((id) => next.add(id));
90
+ }
91
+ onSelectionChange?.(next);
92
+ return next;
93
+ });
94
+ };
95
+
96
+ return (
97
+ <Column fillWidth radius="l" border="neutral-alpha-weak" {...flex}>
98
+ <Row fillWidth horizontal="between" paddingY="12" paddingRight="12" paddingLeft="24" gap="16" vertical="center" s={{direction: "column",}}>
99
+ <Row fillWidth gap="12" vertical="center" horizontal="between">
100
+ {selectable && someCurrentSelected ? (
101
+ <CountFx variant="label-default-m" paddingY="12" paddingLeft="8" value={selectedItems.size} effect="smooth" speed={250}>
102
+ <Text marginLeft="8">selected</Text>
103
+ </CountFx>
104
+ ) : (
105
+ typeof heading === "string" ? (
106
+ <Text variant="label-default-m" paddingY="12" paddingLeft="8">{heading}</Text>
107
+ ) : (
108
+ <Row paddingY="12" paddingLeft="8">{heading}</Row>
109
+ )
110
+ )}
111
+ </Row>
112
+ {showSearch && (
113
+ <Row maxWidth={16}>
114
+ <Input
115
+ height="s"
116
+ id="search"
117
+ placeholder="Search..."
118
+ value={search}
119
+ hasPrefix={<Icon name="search" size="s" onBackground="neutral-weak"/>}
120
+ hasSuffix={search.length > 0 && <IconButton tooltip="Clear" tooltipPosition="left" icon="close" size="s" variant="ghost" onClick={() => setSearch("")}/>}
121
+ onChange={(e) => setSearch(e.target.value)}
122
+ />
123
+ </Row>
124
+ )}
125
+ </Row>
126
+ <Column fillWidth overflowX="auto">
127
+ <Column fillWidth radius="l" border="neutral-alpha-weak" overflow="hidden">
128
+ <Row fillWidth gap="16" paddingX="24" paddingY="12" borderBottom="neutral-alpha-weak">
129
+ {selectable && (
130
+ <Row textVariant="label-default-s" vertical="center" gap="16">
131
+ <Checkbox
132
+ isChecked={allCurrentSelected || (someCurrentSelected && !allCurrentSelected)}
133
+ isIndeterminate={someCurrentSelected && !allCurrentSelected}
134
+ onToggle={toggleSelectAllCurrent}
135
+ />
136
+ </Row>
137
+ )}
138
+ {columns.map((col, cIdx) => (
139
+ <Row
140
+ key={`head-${col.key}-${cIdx}`}
141
+ fillWidth
142
+ minWidth={8}
143
+ textVariant="label-default-s"
144
+ vertical="center"
145
+ horizontal={col.align === "end" ? "end" : col.align === "center" ? "center" : "start"}
146
+ paddingRight={col.align === "end" ? "8" : undefined}
147
+ >
148
+ {col.title}
149
+ </Row>
150
+ ))}
151
+ </Row>
152
+ <Column fillWidth overflow="auto">
153
+ <Column fitWidth style={{minWidth: "100%"}}>
154
+ {paginatedItems.map((item, index) => {
155
+ const globalIndex = startIndex + index;
156
+ const id = resolveId(item, globalIndex);
157
+ return (
158
+ <Row key={`row-${id}`} gap="16" fillWidth borderBottom={index === paginatedItems.length - 1 ? "transparent" : "neutral-alpha-weak"}>
159
+ <Card fillWidth paddingY="8" paddingX="24" gap="16" vertical="center" border="transparent" background="transparent">
160
+ {selectable && (
161
+ <Row vertical="center" gap="16">
162
+ <Checkbox
163
+ key={`cb-${id}`}
164
+ isChecked={isSelected(id)}
165
+ onToggle={() => toggleSelect(id)}
166
+ />
167
+ </Row>
168
+ )}
169
+ {columns.map((col, cIdx) => (
170
+ <Row
171
+ key={`cell-${id}-${col.key}-${cIdx}`}
172
+ fillWidth
173
+ minWidth={8}
174
+ horizontal={col.align === "end" ? "end" : col.align === "center" ? "center" : "start"}
175
+ paddingRight={col.align === "end" ? "8" : undefined}
176
+ >
177
+ {col.render(item, globalIndex)}
178
+ </Row>
179
+ ))}
180
+ </Card>
181
+ </Row>
182
+ );
183
+ })}
184
+ </Column>
185
+ {paginatedItems.length === 0 && (
186
+ <Column fill center padding="l" gap="24">
187
+ <Text variant="label-default-s" onBackground="neutral-weak">No results{search ? ` for "${search}"` : ""}</Text>
188
+ {showSearch && <Button size="s" variant="secondary" onClick={() => setSearch("")}>Clear search</Button>}
189
+ </Column>
190
+ )}
191
+ </Column>
192
+ </Column>
193
+ </Column>
194
+
195
+ <Row fillWidth horizontal="between" vertical="center" paddingX="24">
196
+ <Row fillWidth paddingY="12" gap="12" vertical="center">
197
+ <IconButton icon="chevronLeft" size="s" variant="ghost" onClick={() => setCurrentPage(currentPage - 1)} disabled={currentPage === 1}/>
198
+ <Row gap="4" vertical="center">
199
+ {/* Page 1 */}
200
+ <IconButton
201
+ key={`page-1`}
202
+ size="m"
203
+ variant={currentPage === 1 ? "primary" : "secondary"}
204
+ onClick={() => setCurrentPage(1)}
205
+ >
206
+ <Text variant="label-strong-s">1</Text>
207
+ </IconButton>
208
+
209
+ {/* Page 2 (if exists) */}
210
+ {totalitemsPerPage >= 2 && (
211
+ <IconButton
212
+ key={`page-2`}
213
+ size="m"
214
+ variant={currentPage === 2 ? "primary" : "secondary"}
215
+ onClick={() => setCurrentPage(2)}
216
+ >
217
+ <Text variant="label-strong-s">2</Text>
218
+ </IconButton>
219
+ )}
220
+
221
+ {/* More dropdown for middle pages when > 4 total pages */}
222
+ {totalitemsPerPage > 4 && (
223
+ <DropdownWrapper
224
+ placement="bottom-end"
225
+ trigger={<IconButton icon="moreHorizontal" size="s" variant="ghost"/>}
226
+ dropdown={
227
+ <Column padding="4" gap="2" width={4}>
228
+ {Array.from({ length: totalitemsPerPage - 4 }, (_, i) => i + 3).map((pageNum) => (
229
+ <ToggleButton
230
+ key={`page-middle-${pageNum}`}
231
+ fillWidth
232
+ horizontal="start"
233
+ selected={currentPage === pageNum}
234
+ onClick={() => setCurrentPage(pageNum)}
235
+ >
236
+ {pageNum}
237
+ </ToggleButton>
238
+ ))}
239
+ </Column>
240
+ }
241
+ />
242
+ )}
243
+
244
+ {/* Last-1 and Last */}
245
+ {totalitemsPerPage >= 4 ? (
246
+ <>
247
+ <IconButton
248
+ key={`page-${totalitemsPerPage - 1}`}
249
+ size="m"
250
+ variant={currentPage === totalitemsPerPage - 1 ? "primary" : "secondary"}
251
+ onClick={() => setCurrentPage(totalitemsPerPage - 1)}
252
+ >
253
+ <Text variant="label-strong-s">{totalitemsPerPage - 1}</Text>
254
+ </IconButton>
255
+ <IconButton
256
+ key={`page-${totalitemsPerPage}`}
257
+ size="m"
258
+ variant={currentPage === totalitemsPerPage ? "primary" : "secondary"}
259
+ onClick={() => setCurrentPage(totalitemsPerPage)}
260
+ >
261
+ <Text variant="label-strong-s">{totalitemsPerPage}</Text>
262
+ </IconButton>
263
+ </>
264
+ ) : totalitemsPerPage === 3 ? (
265
+ <IconButton
266
+ key={`page-3`}
267
+ size="m"
268
+ variant={currentPage === 3 ? "primary" : "secondary"}
269
+ onClick={() => setCurrentPage(3)}
270
+ >
271
+ <Text variant="label-strong-s">3</Text>
272
+ </IconButton>
273
+ ) : null}
274
+ </Row>
275
+ <IconButton icon="chevronRight" size="s" variant="ghost" onClick={() => setCurrentPage(currentPage + 1)} disabled={currentPage === totalitemsPerPage}/>
276
+ </Row>
277
+
278
+ <DropdownWrapper
279
+ placement="bottom-end"
280
+ trigger={
281
+ <Button size="s" variant="secondary" prefixIcon="chevronDown">
282
+ <Text variant="label-strong-s">{itemsPerPage}</Text>
283
+ </Button>
284
+ }
285
+ dropdown={
286
+ <Column padding="4" gap="2" width={4}>
287
+ {itemsPerPageOptions.map((option) => (
288
+ <ToggleButton
289
+ key={option}
290
+ fillWidth
291
+ horizontal="start"
292
+ onClick={() => setItemsPerPage(option)}
293
+ >
294
+ {option}
295
+ </ToggleButton>
296
+ ))}
297
+ </Column>
298
+ }
299
+ />
300
+ </Row>
301
+ </Column>
302
+ );
303
+ };
@@ -0,0 +1,141 @@
1
+ "use client";
2
+
3
+ import {
4
+ Row,
5
+ Column,
6
+ Badge,
7
+ Heading,
8
+ Input,
9
+ IconButton,
10
+ AvatarGroup,
11
+ CountFx,
12
+ Text,
13
+ Logo,
14
+ RevealFx,
15
+ Line,
16
+ } from "@once-ui-system/core";
17
+ import { Background6 } from "./Background6";
18
+ import { useEffect, useState } from "react";
19
+
20
+ export const Waitlist1 = () => {
21
+ const [email, setEmail] = useState("");
22
+ const [subscribers, setSubscribers] = useState(0);
23
+ const [subscribed, setSubscribed] = useState(false);
24
+
25
+ useEffect(() => {
26
+ setSubscribers(1337);
27
+ });
28
+
29
+ const validateEmail = (email: any) => {
30
+ if (!email) return null;
31
+
32
+ const emailRegex = /^[^s@]+@[^s@]+.[^s@]+$/;
33
+ if (!emailRegex.test(email)) {
34
+ return "Please enter a valid email address";
35
+ }
36
+
37
+ return null;
38
+ };
39
+
40
+ const subscribe = () => {
41
+ if (validateEmail(email)) {
42
+ return;
43
+ }
44
+
45
+ setSubscribed(true);
46
+ setSubscribers(subscribers + 1);
47
+ setEmail("");
48
+ };
49
+
50
+ return (
51
+ <Row fillWidth center padding="l" minHeight="100%"
52
+ cursor={
53
+ <svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
54
+ <g>
55
+ <path d="M7.89235 19.7113L3.33378 3.71982C3.0984 2.89409 3.95602 2.18106 4.73584 2.55413L19.8385 9.7792C20.6416 10.1634 20.5812 11.3159 19.7425 11.6131L13.5312 13.8139C13.3056 13.8938 13.1164 14.0511 12.9978 14.2574L9.73178 19.9361C9.29078 20.7029 8.13473 20.5616 7.89235 19.7113Z" fill="#15D9EF"/>
56
+ <path d="M2.85075 3.8544C2.49768 2.61583 3.78362 1.54674 4.95335 2.10628L20.0564 9.3314C21.2607 9.90776 21.1699 11.6359 19.9119 12.0816L13.7012 14.2825C13.5885 14.3224 13.4939 14.4012 13.4346 14.5041L10.1679 20.1829C9.50645 21.3329 7.7731 21.1214 7.40931 19.8463L2.85075 3.8544Z" stroke="#15AAEF"/>
57
+ </g>
58
+ </svg>
59
+ }>
60
+ <Background6 />
61
+ <Column horizontal="center" gap="40" maxWidth="xs">
62
+ <RevealFx horizontal="center">
63
+ <Badge paddingX="24" background="brand-alpha-weak" pointerEvents="none" textVariant="label-default-s" onBackground="brand-medium">
64
+ <Logo size="s" dark icon="/trademarks/icon-dark.svg" wordmark="/trademarks/wordmark-dark.svg"/>
65
+ <Logo size="s" light icon="/trademarks/icon-light.svg" wordmark="/trademarks/wordmark-light.svg"/>
66
+ <Line vert marginX="16" height="20" background="brand-alpha-medium"/>
67
+ <Text paddingX="4">Arriving soon</Text>
68
+ </Badge>
69
+ </RevealFx>
70
+ <Column horizontal="center" align="center" gap="24">
71
+ <RevealFx horizontal="center" delay={0.4}>
72
+ <Heading variant="display-strong-xl" onBackground="neutral-strong">
73
+ The all-in-one course platform
74
+ </Heading>
75
+ </RevealFx>
76
+ <RevealFx horizontal="center" delay={0.6}>
77
+ <Text onBackground="neutral-medium" variant="heading-default-xl">
78
+ Launch and sell your courses with ease. We handle enrollment, payments and analytics. You focus on creating.
79
+ </Text>
80
+ </RevealFx>
81
+ </Column>
82
+ <RevealFx horizontal="center" delay={0.8}>
83
+ <AvatarGroup
84
+ reverse
85
+ size="m"
86
+ avatars={[
87
+ { src: "/images/creators/lorant.jpg" },
88
+ { src: "/images/creators/justin.jpg" },
89
+ { src: "/images/creators/light.jpg" },
90
+ { src: "/images/creators/texz.jpg" },
91
+ { src: "/images/creators/suhaib.jpg" },
92
+ ]}
93
+ />
94
+ </RevealFx>
95
+
96
+ <Column maxWidth={24} horizontal="center" align="center">
97
+ {subscribed ? (
98
+ <RevealFx key="waitlist" direction="column" horizontal="center" paddingX="64" paddingY="24" radius="l" background="brand-alpha-weak" border="brand-alpha-weak" gap="20">
99
+ <Text variant="label-default-m" onBackground="brand-medium">
100
+ You're on the list!
101
+ </Text>
102
+ <Row vertical="center" textVariant="heading-strong-l" gap="16">
103
+ That makes it <CountFx
104
+ value={subscribers}
105
+ variant="code-default-xl"
106
+ speed={4000}
107
+ effect="smooth"
108
+ easing="ease-out"
109
+ />
110
+ </Row>
111
+ </RevealFx>
112
+ ) : (
113
+ <RevealFx key="subscribed" direction="column" horizontal="center" delay={1} gap="16" data-border="rounded">
114
+ <Input
115
+ id="email"
116
+ placeholder="Enter email"
117
+ value={email}
118
+ validate={(value) => validateEmail(value as string)}
119
+ onChange={(e) => setEmail(e.target.value)}
120
+ hasSuffix={
121
+ <IconButton size="l" style={{marginRight: "-0.5rem"}} icon="send" onClick={() => subscribe()}/>
122
+ }
123
+ />
124
+ <Row vertical="center" gap="4" textVariant="label-default-s">
125
+ <Text>Join</Text>
126
+ <CountFx
127
+ value={subscribers}
128
+ variant="code-default-s"
129
+ speed={1000}
130
+ effect="smooth"
131
+ easing="ease-out"
132
+ />
133
+ <Text>others</Text>
134
+ </Row>
135
+ </RevealFx>
136
+ )}
137
+ </Column>
138
+ </Column>
139
+ </Row>
140
+ );
141
+ };
@@ -0,0 +1,65 @@
1
+ export const sidebar = [
2
+ {
3
+ items: [
4
+ { label: "Members" },
5
+ { label: "Files" },
6
+ { label: "Pins" },
7
+ ],
8
+ },
9
+ {
10
+ title: "Channels",
11
+ rooms: [
12
+ { label: "👋 ┃ intro" },
13
+ { label: "general" },
14
+ { label: "design-system" },
15
+ ],
16
+ },
17
+ ];
18
+
19
+ export const chatMembers = [
20
+ {
21
+ title: "Online",
22
+ members: [
23
+ {
24
+ name: "Jane Wong",
25
+ status: "Active now",
26
+ bio: "Design engineer",
27
+ avatar: "/images/creators/lorant.jpg",
28
+ group: "Online",
29
+ },
30
+ {
31
+ name: "Lorant K.",
32
+ status: "Coding something...",
33
+ bio: "Building Once UI",
34
+ avatar: "/images/creators/lorant.jpg",
35
+ group: "Online",
36
+ },
37
+ ],
38
+ },
39
+ ];
40
+
41
+ export const chatMessages = [
42
+ {
43
+ author: { name: "Jane Wong", avatar: "/images/creators/lorant.jpg" },
44
+ postedAt: new Date("2025-01-18T09:38:00"),
45
+ message: "Can you sanity-check the chat density before we ship?",
46
+ attachments: [],
47
+ reactions: [{ emoji: "👍", count: 2, reacted: true }],
48
+ },
49
+ {
50
+ author: { name: "Lorant K.", avatar: "/images/creators/lorant.jpg" },
51
+ postedAt: new Date("2025-01-18T09:40:00"),
52
+ message: "On it — Discord sidebar + Linear message rhythm.",
53
+ attachments: [
54
+ { media: "/images/blocks/vibe-coding-dark.jpg" },
55
+ ],
56
+ reactions: [],
57
+ },
58
+ {
59
+ author: { name: "Jane Wong", avatar: "/images/creators/lorant.jpg" },
60
+ postedAt: new Date("2025-01-18T09:42:00"),
61
+ message: "",
62
+ attachments: [{ media: "https://docs.once-ui.com" }],
63
+ reactions: [{ emoji: "🔗", count: 1, reacted: false }],
64
+ },
65
+ ];
@@ -0,0 +1,5 @@
1
+ export const social = [
2
+ { icon: "link", label: "Discord", href: "https://discord.com/invite/5EyAQ4eNdS" },
3
+ { icon: "link", label: "GitHub", href: "https://github.com/once-ui-system" },
4
+ { icon: "document", label: "Email", href: "mailto:demo@email.com" },
5
+ ];
@@ -0,0 +1,51 @@
1
+ export const task = {
2
+ planned: { label: "Planned", color: "neutral" },
3
+ progress: { label: "In progress", color: "brand" },
4
+ done: { label: "Done", color: "success" },
5
+ blocked: { label: "Blocked", color: "danger" },
6
+ } as const;
7
+
8
+ export const roadmap = [
9
+ {
10
+ product: "Once UI Core",
11
+ brand: "brand",
12
+ columns: [
13
+ {
14
+ title: "Planned",
15
+ tasks: [
16
+ {
17
+ title: "Agent-first MCP tools",
18
+ description: "resolve, get_component, validate",
19
+ type: "progress",
20
+ user: { name: "Lorant", avatar: "/images/creators/lorant.jpg" },
21
+ href: "#",
22
+ },
23
+ {
24
+ title: "Expanded block references",
25
+ description: "Pro block gold examples in harness",
26
+ type: "planned",
27
+ },
28
+ ],
29
+ },
30
+ {
31
+ title: "In progress",
32
+ tasks: [
33
+ {
34
+ title: "Codegen harness Phase 1",
35
+ type: "progress",
36
+ user: { name: "Lorant" },
37
+ },
38
+ ],
39
+ },
40
+ {
41
+ title: "Done",
42
+ tasks: [
43
+ {
44
+ title: "Component catalog slices",
45
+ type: "done",
46
+ },
47
+ ],
48
+ },
49
+ ],
50
+ },
51
+ ];