love-ui 1.2.12 → 1.2.14

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 (988) hide show
  1. package/dist/index.js +8 -7
  2. package/dist/mcp-server.js +1 -1
  3. package/package.json +3 -2
  4. package/packages/loveui-skills/SKILL.md +99 -0
  5. package/packages/loveui-skills/agents/openai.yaml +11 -0
  6. package/packages/loveui-skills/references/design-directions.md +60 -0
  7. package/packages/loveui-skills/references/mcp-catalog-workflow.md +68 -0
  8. package/packages/loveui-skills/references/page-blueprints.md +76 -0
  9. package/packages/loveui-skills/references/quality-gates.md +51 -0
  10. package/public/r/accordion-controlled.json +1 -1
  11. package/public/r/accordion-demo.json +1 -1
  12. package/public/r/accordion-multiple.json +1 -1
  13. package/public/r/accordion-single.json +1 -1
  14. package/public/r/alert-demo.json +1 -1
  15. package/public/r/alert-dialog-demo.json +1 -1
  16. package/public/r/alert-error.json +1 -1
  17. package/public/r/alert-info.json +1 -1
  18. package/public/r/alert-success.json +1 -1
  19. package/public/r/alert-warning.json +1 -1
  20. package/public/r/alert-with-icon-action.json +1 -1
  21. package/public/r/alert-with-icon.json +1 -1
  22. package/public/r/announcement-tagless.json +1 -1
  23. package/public/r/announcement-themes.json +1 -1
  24. package/public/r/announcement.json +1 -1
  25. package/public/r/autocomplete-async.json +1 -1
  26. package/public/r/autocomplete-autohighlight.json +1 -1
  27. package/public/r/autocomplete-demo.json +1 -1
  28. package/public/r/autocomplete-disabled.json +1 -1
  29. package/public/r/autocomplete-form.json +1 -1
  30. package/public/r/autocomplete-grouped.json +1 -1
  31. package/public/r/autocomplete-inline.json +1 -1
  32. package/public/r/autocomplete-lg.json +1 -1
  33. package/public/r/autocomplete-limit.json +1 -1
  34. package/public/r/autocomplete-sm.json +1 -1
  35. package/public/r/autocomplete-with-clear.json +1 -1
  36. package/public/r/autocomplete-with-label.json +1 -1
  37. package/public/r/autocomplete-with-trigger-clear.json +1 -1
  38. package/public/r/avatar-demo.json +1 -1
  39. package/public/r/avatar-fallback.json +1 -1
  40. package/public/r/avatar-group.json +1 -1
  41. package/public/r/avatar-radius.json +1 -1
  42. package/public/r/avatar-size.json +1 -1
  43. package/public/r/avatar-stack-hover.json +1 -1
  44. package/public/r/avatar-stack.json +1 -1
  45. package/public/r/badge-demo.json +1 -1
  46. package/public/r/badge-destructive.json +1 -1
  47. package/public/r/badge-error.json +1 -1
  48. package/public/r/badge-info.json +1 -1
  49. package/public/r/badge-lg.json +1 -1
  50. package/public/r/badge-outline.json +1 -1
  51. package/public/r/badge-secondary.json +1 -1
  52. package/public/r/badge-sm.json +1 -1
  53. package/public/r/badge-success.json +1 -1
  54. package/public/r/badge-warning.json +1 -1
  55. package/public/r/badge-with-icon.json +1 -1
  56. package/public/r/badge-with-link.json +1 -1
  57. package/public/r/banner-inset.json +1 -1
  58. package/public/r/banner-themes.json +1 -1
  59. package/public/r/banner.json +1 -1
  60. package/public/r/bookmarks.json +206 -0
  61. package/public/r/breadcrumb-custom-separator.json +1 -1
  62. package/public/r/breadcrumb-demo.json +1 -1
  63. package/public/r/button-demo.json +1 -1
  64. package/public/r/button-destructive-outline.json +1 -1
  65. package/public/r/button-destructive.json +1 -1
  66. package/public/r/button-disabled.json +1 -1
  67. package/public/r/button-ghost.json +1 -1
  68. package/public/r/button-lg.json +1 -1
  69. package/public/r/button-link.json +1 -1
  70. package/public/r/button-loading.json +1 -1
  71. package/public/r/button-outline.json +1 -1
  72. package/public/r/button-secondary.json +1 -1
  73. package/public/r/button-sm.json +1 -1
  74. package/public/r/button-with-icon.json +1 -1
  75. package/public/r/button-with-link.json +1 -1
  76. package/public/r/button-xl.json +1 -1
  77. package/public/r/button-xs.json +1 -1
  78. package/public/r/calendar-headless.json +1 -1
  79. package/public/r/calendar-rac.json +16 -0
  80. package/public/r/calendar.json +1 -1
  81. package/public/r/card-demo.json +1 -1
  82. package/public/r/chart.json +15 -0
  83. package/public/r/checkbox-card.json +1 -1
  84. package/public/r/checkbox-demo.json +1 -1
  85. package/public/r/checkbox-disabled.json +1 -1
  86. package/public/r/checkbox-form.json +1 -1
  87. package/public/r/checkbox-group-demo.json +1 -1
  88. package/public/r/checkbox-group-disabled.json +1 -1
  89. package/public/r/checkbox-group-form.json +1 -1
  90. package/public/r/checkbox-group-nested-parent.json +1 -1
  91. package/public/r/checkbox-group-parent.json +1 -1
  92. package/public/r/checkbox-tree.json +12 -0
  93. package/public/r/checkbox-with-description.json +1 -1
  94. package/public/r/choicebox-inline.json +1 -1
  95. package/public/r/choicebox.json +1 -1
  96. package/public/r/codebase.json +1 -1
  97. package/public/r/collaborative-canvas.json +1 -1
  98. package/public/r/collapsible-demo.json +1 -1
  99. package/public/r/combobox-autohighlight.json +1 -1
  100. package/public/r/combobox-controlled.json +1 -1
  101. package/public/r/combobox-create-new.json +1 -1
  102. package/public/r/combobox-demo.json +1 -1
  103. package/public/r/combobox-disabled.json +1 -1
  104. package/public/r/combobox-fixed-width.json +1 -1
  105. package/public/r/combobox-form.json +1 -1
  106. package/public/r/combobox-grouped.json +1 -1
  107. package/public/r/combobox-lg.json +1 -1
  108. package/public/r/combobox-multiple-form.json +1 -1
  109. package/public/r/combobox-multiple.json +1 -1
  110. package/public/r/combobox-sm.json +1 -1
  111. package/public/r/combobox-with-clear.json +1 -1
  112. package/public/r/combobox-with-inner-input.json +1 -1
  113. package/public/r/combobox-with-label.json +1 -1
  114. package/public/r/command.json +18 -0
  115. package/public/r/comp-01.json +22 -0
  116. package/public/r/comp-02.json +23 -0
  117. package/public/r/comp-03.json +23 -0
  118. package/public/r/comp-04.json +23 -0
  119. package/public/r/comp-05.json +22 -0
  120. package/public/r/comp-06.json +23 -0
  121. package/public/r/comp-07.json +22 -0
  122. package/public/r/comp-08.json +23 -0
  123. package/public/r/comp-09.json +22 -0
  124. package/public/r/comp-10.json +22 -0
  125. package/public/r/comp-100.json +23 -0
  126. package/public/r/comp-101.json +23 -0
  127. package/public/r/comp-102.json +23 -0
  128. package/public/r/comp-103.json +23 -0
  129. package/public/r/comp-104.json +23 -0
  130. package/public/r/comp-105.json +23 -0
  131. package/public/r/comp-106.json +22 -0
  132. package/public/r/comp-107.json +22 -0
  133. package/public/r/comp-108.json +23 -0
  134. package/public/r/comp-109.json +22 -0
  135. package/public/r/comp-11.json +22 -0
  136. package/public/r/comp-110.json +22 -0
  137. package/public/r/comp-111.json +21 -0
  138. package/public/r/comp-112.json +21 -0
  139. package/public/r/comp-113.json +22 -0
  140. package/public/r/comp-114.json +23 -0
  141. package/public/r/comp-115.json +22 -0
  142. package/public/r/comp-116.json +22 -0
  143. package/public/r/comp-117.json +23 -0
  144. package/public/r/comp-118.json +23 -0
  145. package/public/r/comp-119.json +27 -0
  146. package/public/r/comp-12.json +22 -0
  147. package/public/r/comp-120.json +27 -0
  148. package/public/r/comp-121.json +27 -0
  149. package/public/r/comp-122.json +27 -0
  150. package/public/r/comp-123.json +22 -0
  151. package/public/r/comp-124.json +22 -0
  152. package/public/r/comp-125.json +31 -0
  153. package/public/r/comp-126.json +31 -0
  154. package/public/r/comp-127.json +21 -0
  155. package/public/r/comp-128.json +21 -0
  156. package/public/r/comp-129.json +24 -0
  157. package/public/r/comp-13.json +22 -0
  158. package/public/r/comp-130.json +23 -0
  159. package/public/r/comp-131.json +23 -0
  160. package/public/r/comp-132.json +23 -0
  161. package/public/r/comp-133.json +23 -0
  162. package/public/r/comp-134.json +23 -0
  163. package/public/r/comp-135.json +24 -0
  164. package/public/r/comp-136.json +23 -0
  165. package/public/r/comp-137.json +23 -0
  166. package/public/r/comp-138.json +25 -0
  167. package/public/r/comp-139.json +23 -0
  168. package/public/r/comp-14.json +22 -0
  169. package/public/r/comp-140.json +23 -0
  170. package/public/r/comp-141.json +23 -0
  171. package/public/r/comp-142.json +25 -0
  172. package/public/r/comp-143.json +23 -0
  173. package/public/r/comp-144.json +24 -0
  174. package/public/r/comp-145.json +24 -0
  175. package/public/r/comp-146.json +24 -0
  176. package/public/r/comp-147.json +24 -0
  177. package/public/r/comp-148.json +25 -0
  178. package/public/r/comp-149.json +24 -0
  179. package/public/r/comp-15.json +22 -0
  180. package/public/r/comp-150.json +21 -0
  181. package/public/r/comp-151.json +23 -0
  182. package/public/r/comp-152.json +23 -0
  183. package/public/r/comp-153.json +23 -0
  184. package/public/r/comp-154.json +23 -0
  185. package/public/r/comp-155.json +23 -0
  186. package/public/r/comp-156.json +25 -0
  187. package/public/r/comp-157.json +27 -0
  188. package/public/r/comp-158.json +24 -0
  189. package/public/r/comp-159.json +24 -0
  190. package/public/r/comp-16.json +22 -0
  191. package/public/r/comp-160.json +24 -0
  192. package/public/r/comp-161.json +24 -0
  193. package/public/r/comp-162.json +24 -0
  194. package/public/r/comp-163.json +28 -0
  195. package/public/r/comp-164.json +24 -0
  196. package/public/r/comp-165.json +24 -0
  197. package/public/r/comp-166.json +25 -0
  198. package/public/r/comp-167.json +24 -0
  199. package/public/r/comp-168.json +24 -0
  200. package/public/r/comp-169.json +23 -0
  201. package/public/r/comp-17.json +25 -0
  202. package/public/r/comp-170.json +25 -0
  203. package/public/r/comp-171.json +28 -0
  204. package/public/r/comp-172.json +23 -0
  205. package/public/r/comp-173.json +23 -0
  206. package/public/r/comp-174.json +23 -0
  207. package/public/r/comp-175.json +23 -0
  208. package/public/r/comp-176.json +23 -0
  209. package/public/r/comp-177.json +23 -0
  210. package/public/r/comp-178.json +23 -0
  211. package/public/r/comp-179.json +24 -0
  212. package/public/r/comp-18.json +25 -0
  213. package/public/r/comp-180.json +23 -0
  214. package/public/r/comp-181.json +25 -0
  215. package/public/r/comp-182.json +24 -0
  216. package/public/r/comp-183.json +25 -0
  217. package/public/r/comp-184.json +25 -0
  218. package/public/r/comp-185.json +24 -0
  219. package/public/r/comp-186.json +25 -0
  220. package/public/r/comp-187.json +25 -0
  221. package/public/r/comp-188.json +25 -0
  222. package/public/r/comp-189.json +23 -0
  223. package/public/r/comp-19.json +23 -0
  224. package/public/r/comp-190.json +23 -0
  225. package/public/r/comp-191.json +24 -0
  226. package/public/r/comp-192.json +23 -0
  227. package/public/r/comp-193.json +23 -0
  228. package/public/r/comp-194.json +24 -0
  229. package/public/r/comp-195.json +23 -0
  230. package/public/r/comp-196.json +24 -0
  231. package/public/r/comp-197.json +23 -0
  232. package/public/r/comp-198.json +23 -0
  233. package/public/r/comp-199.json +23 -0
  234. package/public/r/comp-20.json +23 -0
  235. package/public/r/comp-200.json +25 -0
  236. package/public/r/comp-201.json +22 -0
  237. package/public/r/comp-202.json +22 -0
  238. package/public/r/comp-203.json +23 -0
  239. package/public/r/comp-204.json +23 -0
  240. package/public/r/comp-205.json +23 -0
  241. package/public/r/comp-206.json +24 -0
  242. package/public/r/comp-207.json +23 -0
  243. package/public/r/comp-208.json +23 -0
  244. package/public/r/comp-209.json +23 -0
  245. package/public/r/comp-21.json +23 -0
  246. package/public/r/comp-210.json +24 -0
  247. package/public/r/comp-211.json +24 -0
  248. package/public/r/comp-212.json +23 -0
  249. package/public/r/comp-213.json +23 -0
  250. package/public/r/comp-214.json +23 -0
  251. package/public/r/comp-215.json +24 -0
  252. package/public/r/comp-216.json +22 -0
  253. package/public/r/comp-217.json +22 -0
  254. package/public/r/comp-218.json +25 -0
  255. package/public/r/comp-219.json +23 -0
  256. package/public/r/comp-22.json +23 -0
  257. package/public/r/comp-220.json +24 -0
  258. package/public/r/comp-221.json +23 -0
  259. package/public/r/comp-222.json +26 -0
  260. package/public/r/comp-223.json +26 -0
  261. package/public/r/comp-224.json +23 -0
  262. package/public/r/comp-225.json +24 -0
  263. package/public/r/comp-226.json +26 -0
  264. package/public/r/comp-227.json +26 -0
  265. package/public/r/comp-228.json +26 -0
  266. package/public/r/comp-229.json +30 -0
  267. package/public/r/comp-23.json +24 -0
  268. package/public/r/comp-230.json +30 -0
  269. package/public/r/comp-231.json +32 -0
  270. package/public/r/comp-232.json +31 -0
  271. package/public/r/comp-233.json +30 -0
  272. package/public/r/comp-234.json +28 -0
  273. package/public/r/comp-235.json +28 -0
  274. package/public/r/comp-236.json +24 -0
  275. package/public/r/comp-237.json +26 -0
  276. package/public/r/comp-238.json +26 -0
  277. package/public/r/comp-239.json +26 -0
  278. package/public/r/comp-24.json +23 -0
  279. package/public/r/comp-240.json +23 -0
  280. package/public/r/comp-241.json +24 -0
  281. package/public/r/comp-242.json +23 -0
  282. package/public/r/comp-243.json +23 -0
  283. package/public/r/comp-244.json +23 -0
  284. package/public/r/comp-245.json +23 -0
  285. package/public/r/comp-246.json +23 -0
  286. package/public/r/comp-247.json +23 -0
  287. package/public/r/comp-248.json +23 -0
  288. package/public/r/comp-249.json +24 -0
  289. package/public/r/comp-25.json +24 -0
  290. package/public/r/comp-250.json +25 -0
  291. package/public/r/comp-251.json +25 -0
  292. package/public/r/comp-252.json +25 -0
  293. package/public/r/comp-253.json +25 -0
  294. package/public/r/comp-254.json +35 -0
  295. package/public/r/comp-255.json +30 -0
  296. package/public/r/comp-256.json +25 -0
  297. package/public/r/comp-257.json +25 -0
  298. package/public/r/comp-258.json +32 -0
  299. package/public/r/comp-259.json +26 -0
  300. package/public/r/comp-26.json +24 -0
  301. package/public/r/comp-260.json +26 -0
  302. package/public/r/comp-261.json +24 -0
  303. package/public/r/comp-262.json +31 -0
  304. package/public/r/comp-263.json +25 -0
  305. package/public/r/comp-264.json +33 -0
  306. package/public/r/comp-265.json +32 -0
  307. package/public/r/comp-266.json +24 -0
  308. package/public/r/comp-267.json +19 -0
  309. package/public/r/comp-268.json +19 -0
  310. package/public/r/comp-269.json +19 -0
  311. package/public/r/comp-27.json +24 -0
  312. package/public/r/comp-270.json +19 -0
  313. package/public/r/comp-271.json +19 -0
  314. package/public/r/comp-272.json +19 -0
  315. package/public/r/comp-273.json +19 -0
  316. package/public/r/comp-274.json +19 -0
  317. package/public/r/comp-275.json +19 -0
  318. package/public/r/comp-276.json +19 -0
  319. package/public/r/comp-277.json +21 -0
  320. package/public/r/comp-278.json +21 -0
  321. package/public/r/comp-279.json +23 -0
  322. package/public/r/comp-28.json +24 -0
  323. package/public/r/comp-280.json +23 -0
  324. package/public/r/comp-281.json +23 -0
  325. package/public/r/comp-282.json +23 -0
  326. package/public/r/comp-283.json +23 -0
  327. package/public/r/comp-284.json +23 -0
  328. package/public/r/comp-285.json +23 -0
  329. package/public/r/comp-286.json +23 -0
  330. package/public/r/comp-287.json +24 -0
  331. package/public/r/comp-288.json +23 -0
  332. package/public/r/comp-289.json +24 -0
  333. package/public/r/comp-29.json +24 -0
  334. package/public/r/comp-290.json +24 -0
  335. package/public/r/comp-291.json +24 -0
  336. package/public/r/comp-292.json +24 -0
  337. package/public/r/comp-293.json +26 -0
  338. package/public/r/comp-294.json +24 -0
  339. package/public/r/comp-295.json +23 -0
  340. package/public/r/comp-296.json +23 -0
  341. package/public/r/comp-297.json +30 -0
  342. package/public/r/comp-298.json +26 -0
  343. package/public/r/comp-299.json +28 -0
  344. package/public/r/comp-30.json +23 -0
  345. package/public/r/comp-300.json +29 -0
  346. package/public/r/comp-301.json +24 -0
  347. package/public/r/comp-302.json +18 -0
  348. package/public/r/comp-303.json +18 -0
  349. package/public/r/comp-304.json +18 -0
  350. package/public/r/comp-305.json +21 -0
  351. package/public/r/comp-306.json +21 -0
  352. package/public/r/comp-307.json +21 -0
  353. package/public/r/comp-308.json +21 -0
  354. package/public/r/comp-309.json +21 -0
  355. package/public/r/comp-31.json +21 -0
  356. package/public/r/comp-310.json +23 -0
  357. package/public/r/comp-311.json +20 -0
  358. package/public/r/comp-312.json +21 -0
  359. package/public/r/comp-313.json +26 -0
  360. package/public/r/comp-314.json +26 -0
  361. package/public/r/comp-315.json +24 -0
  362. package/public/r/comp-316.json +25 -0
  363. package/public/r/comp-317.json +24 -0
  364. package/public/r/comp-318.json +24 -0
  365. package/public/r/comp-319.json +24 -0
  366. package/public/r/comp-32.json +21 -0
  367. package/public/r/comp-320.json +27 -0
  368. package/public/r/comp-321.json +28 -0
  369. package/public/r/comp-322.json +27 -0
  370. package/public/r/comp-323.json +30 -0
  371. package/public/r/comp-324.json +28 -0
  372. package/public/r/comp-325.json +29 -0
  373. package/public/r/comp-326.json +30 -0
  374. package/public/r/comp-327.json +30 -0
  375. package/public/r/comp-328.json +37 -0
  376. package/public/r/comp-329.json +38 -0
  377. package/public/r/comp-33.json +18 -0
  378. package/public/r/comp-330.json +27 -0
  379. package/public/r/comp-331.json +42 -0
  380. package/public/r/comp-332.json +25 -0
  381. package/public/r/comp-333.json +29 -0
  382. package/public/r/comp-334.json +22 -0
  383. package/public/r/comp-335.json +22 -0
  384. package/public/r/comp-336.json +22 -0
  385. package/public/r/comp-337.json +22 -0
  386. package/public/r/comp-338.json +22 -0
  387. package/public/r/comp-339.json +22 -0
  388. package/public/r/comp-34.json +27 -0
  389. package/public/r/comp-340.json +22 -0
  390. package/public/r/comp-341.json +22 -0
  391. package/public/r/comp-342.json +22 -0
  392. package/public/r/comp-343.json +22 -0
  393. package/public/r/comp-344.json +22 -0
  394. package/public/r/comp-345.json +22 -0
  395. package/public/r/comp-346.json +22 -0
  396. package/public/r/comp-347.json +22 -0
  397. package/public/r/comp-348.json +22 -0
  398. package/public/r/comp-349.json +22 -0
  399. package/public/r/comp-35.json +27 -0
  400. package/public/r/comp-350.json +22 -0
  401. package/public/r/comp-351.json +22 -0
  402. package/public/r/comp-352.json +24 -0
  403. package/public/r/comp-353.json +24 -0
  404. package/public/r/comp-354.json +23 -0
  405. package/public/r/comp-355.json +23 -0
  406. package/public/r/comp-356.json +23 -0
  407. package/public/r/comp-357.json +23 -0
  408. package/public/r/comp-358.json +23 -0
  409. package/public/r/comp-359.json +24 -0
  410. package/public/r/comp-36.json +26 -0
  411. package/public/r/comp-360.json +25 -0
  412. package/public/r/comp-361.json +23 -0
  413. package/public/r/comp-362.json +24 -0
  414. package/public/r/comp-363.json +27 -0
  415. package/public/r/comp-364.json +26 -0
  416. package/public/r/comp-365.json +24 -0
  417. package/public/r/comp-366.json +23 -0
  418. package/public/r/comp-367.json +23 -0
  419. package/public/r/comp-368.json +23 -0
  420. package/public/r/comp-369.json +23 -0
  421. package/public/r/comp-37.json +23 -0
  422. package/public/r/comp-370.json +23 -0
  423. package/public/r/comp-371.json +24 -0
  424. package/public/r/comp-372.json +24 -0
  425. package/public/r/comp-373.json +25 -0
  426. package/public/r/comp-374.json +26 -0
  427. package/public/r/comp-375.json +25 -0
  428. package/public/r/comp-376.json +26 -0
  429. package/public/r/comp-377.json +27 -0
  430. package/public/r/comp-378.json +24 -0
  431. package/public/r/comp-379.json +24 -0
  432. package/public/r/comp-38.json +23 -0
  433. package/public/r/comp-380.json +24 -0
  434. package/public/r/comp-381.json +26 -0
  435. package/public/r/comp-382.json +25 -0
  436. package/public/r/comp-383.json +26 -0
  437. package/public/r/comp-384.json +24 -0
  438. package/public/r/comp-385.json +24 -0
  439. package/public/r/comp-386.json +24 -0
  440. package/public/r/comp-387.json +28 -0
  441. package/public/r/comp-388.json +26 -0
  442. package/public/r/comp-389.json +24 -0
  443. package/public/r/comp-39.json +23 -0
  444. package/public/r/comp-390.json +23 -0
  445. package/public/r/comp-391.json +23 -0
  446. package/public/r/comp-392.json +23 -0
  447. package/public/r/comp-393.json +23 -0
  448. package/public/r/comp-394.json +24 -0
  449. package/public/r/comp-395.json +24 -0
  450. package/public/r/comp-396.json +24 -0
  451. package/public/r/comp-397.json +25 -0
  452. package/public/r/comp-398.json +26 -0
  453. package/public/r/comp-399.json +26 -0
  454. package/public/r/comp-40.json +23 -0
  455. package/public/r/comp-400.json +20 -0
  456. package/public/r/comp-401.json +19 -0
  457. package/public/r/comp-402.json +19 -0
  458. package/public/r/comp-403.json +19 -0
  459. package/public/r/comp-404.json +19 -0
  460. package/public/r/comp-405.json +19 -0
  461. package/public/r/comp-406.json +19 -0
  462. package/public/r/comp-407.json +19 -0
  463. package/public/r/comp-408.json +19 -0
  464. package/public/r/comp-409.json +22 -0
  465. package/public/r/comp-41.json +29 -0
  466. package/public/r/comp-410.json +22 -0
  467. package/public/r/comp-411.json +22 -0
  468. package/public/r/comp-412.json +19 -0
  469. package/public/r/comp-413.json +22 -0
  470. package/public/r/comp-414.json +22 -0
  471. package/public/r/comp-415.json +22 -0
  472. package/public/r/comp-416.json +23 -0
  473. package/public/r/comp-417.json +22 -0
  474. package/public/r/comp-418.json +23 -0
  475. package/public/r/comp-419.json +23 -0
  476. package/public/r/comp-42.json +30 -0
  477. package/public/r/comp-420.json +23 -0
  478. package/public/r/comp-421.json +23 -0
  479. package/public/r/comp-422.json +23 -0
  480. package/public/r/comp-423.json +24 -0
  481. package/public/r/comp-424.json +22 -0
  482. package/public/r/comp-425.json +23 -0
  483. package/public/r/comp-426.json +23 -0
  484. package/public/r/comp-427.json +23 -0
  485. package/public/r/comp-428.json +23 -0
  486. package/public/r/comp-429.json +23 -0
  487. package/public/r/comp-43.json +32 -0
  488. package/public/r/comp-430.json +23 -0
  489. package/public/r/comp-431.json +23 -0
  490. package/public/r/comp-432.json +23 -0
  491. package/public/r/comp-433.json +24 -0
  492. package/public/r/comp-434.json +24 -0
  493. package/public/r/comp-435.json +24 -0
  494. package/public/r/comp-436.json +24 -0
  495. package/public/r/comp-437.json +25 -0
  496. package/public/r/comp-438.json +23 -0
  497. package/public/r/comp-439.json +24 -0
  498. package/public/r/comp-44.json +25 -0
  499. package/public/r/comp-440.json +25 -0
  500. package/public/r/comp-441.json +25 -0
  501. package/public/r/comp-442.json +24 -0
  502. package/public/r/comp-443.json +24 -0
  503. package/public/r/comp-444.json +24 -0
  504. package/public/r/comp-445.json +24 -0
  505. package/public/r/comp-446.json +24 -0
  506. package/public/r/comp-447.json +25 -0
  507. package/public/r/comp-448.json +23 -0
  508. package/public/r/comp-449.json +23 -0
  509. package/public/r/comp-45.json +25 -0
  510. package/public/r/comp-450.json +23 -0
  511. package/public/r/comp-451.json +23 -0
  512. package/public/r/comp-452.json +23 -0
  513. package/public/r/comp-453.json +25 -0
  514. package/public/r/comp-454.json +22 -0
  515. package/public/r/comp-455.json +22 -0
  516. package/public/r/comp-456.json +22 -0
  517. package/public/r/comp-457.json +21 -0
  518. package/public/r/comp-458.json +22 -0
  519. package/public/r/comp-459.json +26 -0
  520. package/public/r/comp-46.json +26 -0
  521. package/public/r/comp-460.json +26 -0
  522. package/public/r/comp-461.json +27 -0
  523. package/public/r/comp-462.json +27 -0
  524. package/public/r/comp-463.json +30 -0
  525. package/public/r/comp-464.json +29 -0
  526. package/public/r/comp-465.json +29 -0
  527. package/public/r/comp-466.json +21 -0
  528. package/public/r/comp-467.json +23 -0
  529. package/public/r/comp-468.json +21 -0
  530. package/public/r/comp-469.json +21 -0
  531. package/public/r/comp-47.json +32 -0
  532. package/public/r/comp-470.json +21 -0
  533. package/public/r/comp-471.json +21 -0
  534. package/public/r/comp-472.json +23 -0
  535. package/public/r/comp-473.json +24 -0
  536. package/public/r/comp-474.json +22 -0
  537. package/public/r/comp-475.json +22 -0
  538. package/public/r/comp-476.json +21 -0
  539. package/public/r/comp-477.json +31 -0
  540. package/public/r/comp-478.json +36 -0
  541. package/public/r/comp-479.json +28 -0
  542. package/public/r/comp-48.json +32 -0
  543. package/public/r/comp-480.json +30 -0
  544. package/public/r/comp-481.json +34 -0
  545. package/public/r/comp-482.json +33 -0
  546. package/public/r/comp-483.json +37 -0
  547. package/public/r/comp-484.json +41 -0
  548. package/public/r/comp-485.json +43 -0
  549. package/public/r/comp-486.json +23 -0
  550. package/public/r/comp-487.json +26 -0
  551. package/public/r/comp-488.json +27 -0
  552. package/public/r/comp-489.json +28 -0
  553. package/public/r/comp-49.json +32 -0
  554. package/public/r/comp-490.json +23 -0
  555. package/public/r/comp-491.json +24 -0
  556. package/public/r/comp-492.json +25 -0
  557. package/public/r/comp-493.json +23 -0
  558. package/public/r/comp-494.json +23 -0
  559. package/public/r/comp-495.json +24 -0
  560. package/public/r/comp-496.json +23 -0
  561. package/public/r/comp-497.json +24 -0
  562. package/public/r/comp-498.json +24 -0
  563. package/public/r/comp-499.json +24 -0
  564. package/public/r/comp-50.json +32 -0
  565. package/public/r/comp-500.json +25 -0
  566. package/public/r/comp-501.json +25 -0
  567. package/public/r/comp-502.json +26 -0
  568. package/public/r/comp-503.json +27 -0
  569. package/public/r/comp-504.json +28 -0
  570. package/public/r/comp-505.json +28 -0
  571. package/public/r/comp-506.json +26 -0
  572. package/public/r/comp-507.json +27 -0
  573. package/public/r/comp-508.json +25 -0
  574. package/public/r/comp-509.json +25 -0
  575. package/public/r/comp-51.json +23 -0
  576. package/public/r/comp-510.json +24 -0
  577. package/public/r/comp-511.json +27 -0
  578. package/public/r/comp-512.json +27 -0
  579. package/public/r/comp-513.json +21 -0
  580. package/public/r/comp-514.json +21 -0
  581. package/public/r/comp-515.json +21 -0
  582. package/public/r/comp-516.json +22 -0
  583. package/public/r/comp-517.json +22 -0
  584. package/public/r/comp-518.json +21 -0
  585. package/public/r/comp-519.json +21 -0
  586. package/public/r/comp-52.json +23 -0
  587. package/public/r/comp-520.json +22 -0
  588. package/public/r/comp-521.json +22 -0
  589. package/public/r/comp-522.json +21 -0
  590. package/public/r/comp-523.json +21 -0
  591. package/public/r/comp-524.json +21 -0
  592. package/public/r/comp-525.json +21 -0
  593. package/public/r/comp-526.json +22 -0
  594. package/public/r/comp-527.json +23 -0
  595. package/public/r/comp-528.json +22 -0
  596. package/public/r/comp-529.json +22 -0
  597. package/public/r/comp-53.json +24 -0
  598. package/public/r/comp-530.json +22 -0
  599. package/public/r/comp-531.json +22 -0
  600. package/public/r/comp-532.json +22 -0
  601. package/public/r/comp-533.json +22 -0
  602. package/public/r/comp-534.json +22 -0
  603. package/public/r/comp-535.json +22 -0
  604. package/public/r/comp-536.json +22 -0
  605. package/public/r/comp-537.json +22 -0
  606. package/public/r/comp-538.json +22 -0
  607. package/public/r/comp-539.json +22 -0
  608. package/public/r/comp-54.json +26 -0
  609. package/public/r/comp-540.json +21 -0
  610. package/public/r/comp-541.json +21 -0
  611. package/public/r/comp-542.json +124 -0
  612. package/public/r/comp-543.json +29 -0
  613. package/public/r/comp-544.json +26 -0
  614. package/public/r/comp-545.json +29 -0
  615. package/public/r/comp-546.json +29 -0
  616. package/public/r/comp-547.json +29 -0
  617. package/public/r/comp-548.json +29 -0
  618. package/public/r/comp-549.json +29 -0
  619. package/public/r/comp-55.json +27 -0
  620. package/public/r/comp-550.json +29 -0
  621. package/public/r/comp-551.json +30 -0
  622. package/public/r/comp-552.json +29 -0
  623. package/public/r/comp-553.json +29 -0
  624. package/public/r/comp-554.json +36 -0
  625. package/public/r/comp-555.json +23 -0
  626. package/public/r/comp-556.json +23 -0
  627. package/public/r/comp-557.json +23 -0
  628. package/public/r/comp-558.json +23 -0
  629. package/public/r/comp-559.json +23 -0
  630. package/public/r/comp-56.json +26 -0
  631. package/public/r/comp-560.json +23 -0
  632. package/public/r/comp-561.json +25 -0
  633. package/public/r/comp-562.json +23 -0
  634. package/public/r/comp-563.json +23 -0
  635. package/public/r/comp-564.json +24 -0
  636. package/public/r/comp-565.json +20 -0
  637. package/public/r/comp-566.json +20 -0
  638. package/public/r/comp-567.json +20 -0
  639. package/public/r/comp-568.json +20 -0
  640. package/public/r/comp-569.json +20 -0
  641. package/public/r/comp-57.json +26 -0
  642. package/public/r/comp-570.json +20 -0
  643. package/public/r/comp-571.json +23 -0
  644. package/public/r/comp-572.json +23 -0
  645. package/public/r/comp-573.json +20 -0
  646. package/public/r/comp-574.json +22 -0
  647. package/public/r/comp-575.json +20 -0
  648. package/public/r/comp-576.json +21 -0
  649. package/public/r/comp-577.json +23 -0
  650. package/public/r/comp-578.json +28 -0
  651. package/public/r/comp-579.json +28 -0
  652. package/public/r/comp-58.json +25 -0
  653. package/public/r/comp-580.json +29 -0
  654. package/public/r/comp-581.json +45 -0
  655. package/public/r/comp-582.json +42 -0
  656. package/public/r/comp-583.json +41 -0
  657. package/public/r/comp-584.json +41 -0
  658. package/public/r/comp-585.json +41 -0
  659. package/public/r/comp-586.json +34 -0
  660. package/public/r/comp-587.json +29 -0
  661. package/public/r/comp-588.json +33 -0
  662. package/public/r/comp-589.json +37 -0
  663. package/public/r/comp-59.json +22 -0
  664. package/public/r/comp-590.json +40 -0
  665. package/public/r/comp-591.json +29 -0
  666. package/public/r/comp-592.json +41 -0
  667. package/public/r/comp-593.json +36 -0
  668. package/public/r/comp-594.json +33 -0
  669. package/public/r/comp-595.json +22 -0
  670. package/public/r/comp-596.json +26 -0
  671. package/public/r/comp-597.json +22 -0
  672. package/public/r/comp-598.json +22 -0
  673. package/public/r/comp-599.json +22 -0
  674. package/public/r/comp-60.json +23 -0
  675. package/public/r/comp-600.json +17 -0
  676. package/public/r/comp-601.json +20 -0
  677. package/public/r/comp-602.json +17 -0
  678. package/public/r/comp-603.json +20 -0
  679. package/public/r/comp-604.json +17 -0
  680. package/public/r/comp-605.json +17 -0
  681. package/public/r/comp-606.json +20 -0
  682. package/public/r/comp-607.json +20 -0
  683. package/public/r/comp-608.json +20 -0
  684. package/public/r/comp-609.json +20 -0
  685. package/public/r/comp-61.json +23 -0
  686. package/public/r/comp-610.json +23 -0
  687. package/public/r/comp-611.json +23 -0
  688. package/public/r/comp-612.json +17 -0
  689. package/public/r/comp-613.json +20 -0
  690. package/public/r/comp-614.json +17 -0
  691. package/public/r/comp-615.json +26 -0
  692. package/public/r/comp-616.json +26 -0
  693. package/public/r/comp-617.json +26 -0
  694. package/public/r/comp-62.json +23 -0
  695. package/public/r/comp-63.json +22 -0
  696. package/public/r/comp-64.json +23 -0
  697. package/public/r/comp-65.json +22 -0
  698. package/public/r/comp-66.json +22 -0
  699. package/public/r/comp-67.json +23 -0
  700. package/public/r/comp-68.json +24 -0
  701. package/public/r/comp-69.json +24 -0
  702. package/public/r/comp-70.json +24 -0
  703. package/public/r/comp-71.json +22 -0
  704. package/public/r/comp-72.json +21 -0
  705. package/public/r/comp-73.json +18 -0
  706. package/public/r/comp-74.json +27 -0
  707. package/public/r/comp-75.json +22 -0
  708. package/public/r/comp-76.json +23 -0
  709. package/public/r/comp-77.json +22 -0
  710. package/public/r/comp-78.json +21 -0
  711. package/public/r/comp-79.json +22 -0
  712. package/public/r/comp-80.json +21 -0
  713. package/public/r/comp-81.json +21 -0
  714. package/public/r/comp-82.json +22 -0
  715. package/public/r/comp-83.json +21 -0
  716. package/public/r/comp-84.json +21 -0
  717. package/public/r/comp-85.json +22 -0
  718. package/public/r/comp-86.json +22 -0
  719. package/public/r/comp-87.json +21 -0
  720. package/public/r/comp-88.json +22 -0
  721. package/public/r/comp-89.json +21 -0
  722. package/public/r/comp-90.json +22 -0
  723. package/public/r/comp-91.json +22 -0
  724. package/public/r/comp-92.json +22 -0
  725. package/public/r/comp-93.json +22 -0
  726. package/public/r/comp-94.json +24 -0
  727. package/public/r/comp-95.json +26 -0
  728. package/public/r/comp-96.json +21 -0
  729. package/public/r/comp-97.json +21 -0
  730. package/public/r/comp-98.json +22 -0
  731. package/public/r/comp-99.json +23 -0
  732. package/public/r/comparison-event-handlers.json +1 -1
  733. package/public/r/comparison-hover.json +1 -1
  734. package/public/r/comparison.json +1 -1
  735. package/public/r/context-menu.json +16 -0
  736. package/public/r/contribution-graph-custom-footer.json +1 -1
  737. package/public/r/credit-card-apple.json +1 -1
  738. package/public/r/credit-card-back.json +1 -1
  739. package/public/r/credit-card.json +1 -1
  740. package/public/r/cropper.json +15 -0
  741. package/public/r/cursor-color.json +1 -1
  742. package/public/r/cursor-message.json +1 -1
  743. package/public/r/cursor-name-message.json +1 -1
  744. package/public/r/cursor-name.json +1 -1
  745. package/public/r/cursor.json +1 -1
  746. package/public/r/dashboard-1.json +263 -0
  747. package/public/r/dashboard-2.json +264 -0
  748. package/public/r/dashboard-3.json +225 -0
  749. package/public/r/datefield-rac.json +15 -0
  750. package/public/r/deck-controlled.json +1 -1
  751. package/public/r/deck-product-cards.json +1 -1
  752. package/public/r/deck.json +1 -1
  753. package/public/r/dialog-close-confirmation.json +1 -1
  754. package/public/r/dialog-demo.json +1 -1
  755. package/public/r/dialog-from-menu.json +1 -1
  756. package/public/r/dialog-nested.json +1 -1
  757. package/public/r/dialog-stack-controlled.json +1 -1
  758. package/public/r/dialog-stack-navigation.json +1 -1
  759. package/public/r/dialog-stack-six.json +1 -1
  760. package/public/r/dialog-stack.json +1 -1
  761. package/public/r/dropdown-menu.json +15 -0
  762. package/public/r/dropzone-custom-empty-state.json +1 -1
  763. package/public/r/dropzone-image-preview.json +1 -1
  764. package/public/r/editor.json +1 -1
  765. package/public/r/emails.json +243 -0
  766. package/public/r/empty-demo.json +1 -1
  767. package/public/r/example-app-calendar.json +323 -0
  768. package/public/r/field-2.json +19 -0
  769. package/public/r/field-autocomplete.json +1 -1
  770. package/public/r/field-checkbox-group.json +1 -1
  771. package/public/r/field-checkbox.json +1 -1
  772. package/public/r/field-combobox-multiple.json +1 -1
  773. package/public/r/field-combobox.json +1 -1
  774. package/public/r/field-complete-form.json +1 -1
  775. package/public/r/field-demo.json +1 -1
  776. package/public/r/field-disabled.json +1 -1
  777. package/public/r/field-error.json +1 -1
  778. package/public/r/field-number-field.json +1 -1
  779. package/public/r/field-radio.json +1 -1
  780. package/public/r/field-required.json +1 -1
  781. package/public/r/field-select.json +1 -1
  782. package/public/r/field-slider.json +1 -1
  783. package/public/r/field-switch.json +1 -1
  784. package/public/r/field-textarea.json +1 -1
  785. package/public/r/field-validity.json +1 -1
  786. package/public/r/fieldset-demo.json +1 -1
  787. package/public/r/files.json +195 -0
  788. package/public/r/form-demo.json +1 -1
  789. package/public/r/form-zod.json +1 -1
  790. package/public/r/form.json +1 -1
  791. package/public/r/frame-demo.json +1 -1
  792. package/public/r/gantt-lanes.json +1 -1
  793. package/public/r/gantt-no-sidebar.json +1 -1
  794. package/public/r/gantt-read-only.json +1 -1
  795. package/public/r/gantt.json +1 -1
  796. package/public/r/glimpse-custom.json +1 -1
  797. package/public/r/glimpse.json +1 -1
  798. package/public/r/gooey-toast-demo.json +1 -1
  799. package/public/r/gooey-toast-promise.json +1 -1
  800. package/public/r/gooey-toast-states.json +1 -1
  801. package/public/r/gooey-toast-with-button.json +1 -1
  802. package/public/r/group-demo.json +1 -1
  803. package/public/r/group-with-input.json +1 -1
  804. package/public/r/hero.json +1 -1
  805. package/public/r/hover-card.json +15 -0
  806. package/public/r/image-crop-circular.json +1 -1
  807. package/public/r/image-crop-custom.json +1 -1
  808. package/public/r/image-crop.json +1 -1
  809. package/public/r/image-zoom-background.json +1 -1
  810. package/public/r/image-zoom-margin.json +1 -1
  811. package/public/r/image-zoom.json +1 -1
  812. package/public/r/input-demo.json +1 -1
  813. package/public/r/input-disabled.json +1 -1
  814. package/public/r/input-file.json +1 -1
  815. package/public/r/input-group.json +20 -0
  816. package/public/r/input-lg.json +1 -1
  817. package/public/r/input-sm.json +1 -1
  818. package/public/r/input-with-button.json +1 -1
  819. package/public/r/input-with-label.json +1 -1
  820. package/public/r/kanban-simple.json +1 -1
  821. package/public/r/kanban.json +1 -1
  822. package/public/r/kbd.json +12 -0
  823. package/public/r/leads.json +271 -0
  824. package/public/r/list-simple.json +1 -1
  825. package/public/r/list.json +1 -1
  826. package/public/r/maps.json +188 -0
  827. package/public/r/menu-checkbox.json +1 -1
  828. package/public/r/menu-close-on-click.json +1 -1
  829. package/public/r/menu-demo.json +1 -1
  830. package/public/r/menu-group-labels.json +1 -1
  831. package/public/r/menu-hover.json +1 -1
  832. package/public/r/menu-link.json +1 -1
  833. package/public/r/menu-nested.json +1 -1
  834. package/public/r/menu-radio-group.json +1 -1
  835. package/public/r/meter-demo.json +1 -1
  836. package/public/r/meter-with-formatted-value.json +1 -1
  837. package/public/r/meter-with-range.json +1 -1
  838. package/public/r/mini-calendar-controlled.json +1 -1
  839. package/public/r/multiselect.json +15 -0
  840. package/public/r/navigation-menu.json +12 -0
  841. package/public/r/number-field-form.json +1 -1
  842. package/public/r/number-field-with-label.json +1 -1
  843. package/public/r/number-field-with-scrub.json +1 -1
  844. package/public/r/number-field-with-step.json +1 -1
  845. package/public/r/pill-avatar-group.json +1 -1
  846. package/public/r/pill-delta.json +1 -1
  847. package/public/r/pill-icon.json +1 -1
  848. package/public/r/pill-indicator.json +1 -1
  849. package/public/r/pill-status.json +1 -1
  850. package/public/r/pill.json +1 -1
  851. package/public/r/popover-demo.json +1 -1
  852. package/public/r/popover-with-close.json +1 -1
  853. package/public/r/preview-card-demo.json +1 -1
  854. package/public/r/pricing.json +1 -1
  855. package/public/r/progress-with-formatted-value.json +1 -1
  856. package/public/r/progress-with-label-value.json +1 -1
  857. package/public/r/radio-group-card.json +1 -1
  858. package/public/r/radio-group-demo.json +1 -1
  859. package/public/r/radio-group-disabled.json +1 -1
  860. package/public/r/radio-group-form.json +1 -1
  861. package/public/r/radio-group-with-description.json +1 -1
  862. package/public/r/reel-custom.json +1 -1
  863. package/public/r/reel-images.json +1 -1
  864. package/public/r/reel-minimal.json +1 -1
  865. package/public/r/reel.json +1 -1
  866. package/public/r/registry.json +18217 -0
  867. package/public/r/relative-time-controlled.json +1 -1
  868. package/public/r/relative-time-format-date.json +1 -1
  869. package/public/r/relative-time-format-time.json +1 -1
  870. package/public/r/relative-time.json +1 -1
  871. package/public/r/rentals.json +187 -0
  872. package/public/r/roadmap.json +1 -1
  873. package/public/r/sandbox-no-file-explorer.json +1 -1
  874. package/public/r/sandbox.json +1 -1
  875. package/public/r/scroll-area-both.json +1 -1
  876. package/public/r/scroll-area-demo.json +1 -1
  877. package/public/r/scroll-area-horizontal.json +1 -1
  878. package/public/r/select-demo.json +1 -1
  879. package/public/r/select-disabled.json +1 -1
  880. package/public/r/select-form.json +1 -1
  881. package/public/r/select-lg.json +1 -1
  882. package/public/r/select-native.json +12 -0
  883. package/public/r/select-sm.json +1 -1
  884. package/public/r/select-with-groups.json +1 -1
  885. package/public/r/select-without-alignment.json +1 -1
  886. package/public/r/select.json +1 -1
  887. package/public/r/separator-demo.json +1 -1
  888. package/public/r/sheet-demo.json +1 -1
  889. package/public/r/sheet-position.json +1 -1
  890. package/public/r/sidebar-nav.json +22 -0
  891. package/public/r/skeleton-demo.json +1 -1
  892. package/public/r/skeleton.json +1 -1
  893. package/public/r/slider-form.json +1 -1
  894. package/public/r/slider-with-label-value.json +1 -1
  895. package/public/r/sonner.json +16 -0
  896. package/public/r/stats-card.json +22 -0
  897. package/public/r/status-custom.json +1 -1
  898. package/public/r/stepper.json +15 -0
  899. package/public/r/stories-images.json +1 -1
  900. package/public/r/switch-card.json +1 -1
  901. package/public/r/switch-demo.json +1 -1
  902. package/public/r/switch-disabled.json +1 -1
  903. package/public/r/switch-form.json +1 -1
  904. package/public/r/switch-with-description.json +1 -1
  905. package/public/r/table-demo.json +1 -1
  906. package/public/r/table-framed.json +1 -1
  907. package/public/r/table-simple.json +1 -1
  908. package/public/r/table.json +1 -1
  909. package/public/r/tabs-demo.json +1 -1
  910. package/public/r/tabs-underline-vertical.json +1 -1
  911. package/public/r/tabs-underline.json +1 -1
  912. package/public/r/tabs-vertical.json +1 -1
  913. package/public/r/tags-create.json +1 -1
  914. package/public/r/tags-filter.json +1 -1
  915. package/public/r/tags.json +1 -1
  916. package/public/r/template-auth-eight.json +28 -0
  917. package/public/r/template-auth-five.json +28 -0
  918. package/public/r/template-auth-four.json +29 -0
  919. package/public/r/template-auth-nine.json +28 -0
  920. package/public/r/template-auth-one.json +49 -0
  921. package/public/r/template-auth-seven.json +29 -0
  922. package/public/r/template-auth-six.json +28 -0
  923. package/public/r/template-auth-three.json +49 -0
  924. package/public/r/template-auth-two.json +44 -0
  925. package/public/r/template-hero-eight.json +83 -0
  926. package/public/r/template-hero-eleven.json +29 -0
  927. package/public/r/template-hero-five.json +35 -0
  928. package/public/r/template-hero-four.json +35 -0
  929. package/public/r/template-hero-fourteen.json +101 -0
  930. package/public/r/template-hero-nine.json +74 -0
  931. package/public/r/template-hero-one.json +90 -0
  932. package/public/r/template-hero-seven.json +83 -0
  933. package/public/r/template-hero-six.json +83 -0
  934. package/public/r/template-hero-ten.json +77 -0
  935. package/public/r/template-hero-thirteen.json +101 -0
  936. package/public/r/template-hero-three.json +35 -0
  937. package/public/r/template-hero-twelve.json +30 -0
  938. package/public/r/template-hero-two.json +96 -0
  939. package/public/r/template-logo-cloud-five.json +68 -0
  940. package/public/r/template-logo-cloud-four.json +71 -0
  941. package/public/r/template-logo-cloud-one.json +89 -0
  942. package/public/r/template-logo-cloud-three.json +71 -0
  943. package/public/r/template-logo-cloud-two.json +74 -0
  944. package/public/r/textarea-demo.json +1 -1
  945. package/public/r/textarea-disabled.json +1 -1
  946. package/public/r/textarea-form.json +1 -1
  947. package/public/r/textarea-lg.json +1 -1
  948. package/public/r/textarea-sm.json +1 -1
  949. package/public/r/textarea-with-label.json +1 -1
  950. package/public/r/ticker-inline.json +1 -1
  951. package/public/r/timeline.json +15 -0
  952. package/public/r/toast-demo.json +1 -1
  953. package/public/r/toast-heights.json +1 -1
  954. package/public/r/toast-loading.json +1 -1
  955. package/public/r/toast-promise.json +1 -1
  956. package/public/r/toast-with-action.json +1 -1
  957. package/public/r/toast-with-status.json +1 -1
  958. package/public/r/toggle-demo.json +1 -1
  959. package/public/r/toggle-disabled.json +1 -1
  960. package/public/r/toggle-group-demo.json +1 -1
  961. package/public/r/toggle-group-disabled.json +1 -1
  962. package/public/r/toggle-group-lg.json +1 -1
  963. package/public/r/toggle-group-multiple.json +1 -1
  964. package/public/r/toggle-group-outline-with-separator.json +1 -1
  965. package/public/r/toggle-group-outline.json +1 -1
  966. package/public/r/toggle-group-sm.json +1 -1
  967. package/public/r/toggle-group-with-disabled-item.json +1 -1
  968. package/public/r/toggle-icon-group.json +1 -1
  969. package/public/r/toggle-lg.json +1 -1
  970. package/public/r/toggle-outline.json +1 -1
  971. package/public/r/toggle-sm.json +1 -1
  972. package/public/r/toggle-with-icon.json +1 -1
  973. package/public/r/toolbar-demo.json +1 -1
  974. package/public/r/tooltip-demo.json +1 -1
  975. package/public/r/tooltip-grouped.json +1 -1
  976. package/public/r/tree-controlled.json +1 -1
  977. package/public/r/tree-custom-icons.json +1 -1
  978. package/public/r/tree-no-lines.json +1 -1
  979. package/public/r/tree-simple.json +1 -1
  980. package/public/r/tree.json +1 -1
  981. package/public/r/typography.json +1 -1
  982. package/public/r/ui.json +5 -0
  983. package/public/r/use-character-limit.json +12 -0
  984. package/public/r/use-file-upload.json +12 -0
  985. package/public/r/use-pagination.json +12 -0
  986. package/public/r/use-slider-with-input.json +12 -0
  987. package/public/r/use-toast.json +12 -0
  988. package/public/r/utils.json +16 -0
@@ -0,0 +1,195 @@
1
+ {
2
+ "$schema": "https://ui.shadcn.com/schema/registry-item.json",
3
+ "name": "files",
4
+ "type": "registry:block",
5
+ "title": "Documentary Asset Vault",
6
+ "description": "A production asset manager with storage insights, collection navigation, and crew activity.",
7
+ "files": [
8
+ {
9
+ "path": "registry/example-apps/default/files/components/files/breadcrumb.tsx",
10
+ "type": "registry:component",
11
+ "target": "components/example-apps/files/components/files/breadcrumb.tsx",
12
+ "content": "\"use client\"\n\nimport Link from \"next/link\"\nimport { usePathname } from \"next/navigation\"\nimport { ArrowRight01Icon, Home01Icon } from \"@hugeicons/core-free-icons\"\nimport { HugeiconsIcon } from \"@hugeicons/react\"\n\nimport { cn } from \"../../lib/utils\"\nimport { useFilesStore } from \"../../store/files-store\"\n\nexport function Breadcrumb() {\n const pathname = usePathname()\n const { folders } = useFilesStore()\n\n const getViewName = () => {\n if (pathname === \"/starred\") return \"Starred\"\n if (pathname === \"/recent\") return \"Recent\"\n if (pathname === \"/shared\") return \"Shared\"\n if (pathname === \"/trash\") return \"Trash\"\n if (pathname.startsWith(\"/folder/\")) {\n const folderId = pathname.split(\"/folder/\")[1]\n const folder = folders.find((f) => f.id === folderId)\n return folder?.name || \"Folder\"\n }\n return null\n }\n\n const viewName = getViewName()\n\n return (\n <nav className=\"flex items-center gap-1 text-sm\">\n <Link\n href=\"/\"\n className={cn(\n \"flex items-center gap-1.5 rounded-md px-2 py-1 transition-colors\",\n pathname === \"/\"\n ? \"font-medium text-foreground\"\n : \"text-muted-foreground hover:bg-muted hover:text-foreground\"\n )}\n >\n <HugeiconsIcon icon={Home01Icon} className=\"size-4\" />\n <span>Asset Vault</span>\n </Link>\n {viewName && (\n <>\n <HugeiconsIcon\n icon={ArrowRight01Icon}\n className=\"size-4 text-muted-foreground\"\n />\n <span className=\"px-2 py-1 font-medium\">{viewName}</span>\n </>\n )}\n </nav>\n )\n}\n"
13
+ },
14
+ {
15
+ "path": "registry/example-apps/default/files/components/files/content.tsx",
16
+ "type": "registry:component",
17
+ "target": "components/example-apps/files/components/files/content.tsx",
18
+ "content": "\"use client\"\n\nimport { FileList } from \"./file-list\"\nimport { FolderGrid } from \"./folder-grid\"\nimport { RecentActivity } from \"./recent-activity\"\nimport { SharedWithMe } from \"./shared-with-me\"\nimport { StorageCards } from \"./storage-cards\"\nimport { StorageOverview } from \"./storage-overview\"\n\nexport type ViewType =\n | \"all\"\n | \"starred\"\n | \"recent\"\n | \"shared\"\n | \"trash\"\n | \"folder\"\n\ninterface FilesContentProps {\n view: ViewType\n folderId?: string\n}\n\nexport function FilesContent({ view, folderId }: FilesContentProps) {\n const showStorageCards = view === \"all\" || view === \"recent\"\n const showSidePanels = view === \"all\"\n const showFolders = view === \"all\"\n\n return (\n <div className=\"w-full flex-1 overflow-auto\">\n <div className=\"flex flex-col gap-6 p-4 md:p-6 xl:flex-row\">\n <div className=\"min-w-0 flex-1 space-y-6\">\n {showStorageCards && <StorageCards />}\n {showFolders && <FolderGrid />}\n <FileList view={view} folderId={folderId} />\n </div>\n\n {showSidePanels && (\n <div className=\"w-full shrink-0 space-y-4 xl:w-80\">\n <StorageOverview />\n <SharedWithMe />\n <RecentActivity />\n </div>\n )}\n </div>\n </div>\n )\n}\n"
19
+ },
20
+ {
21
+ "path": "registry/example-apps/default/files/components/files/file-icon.tsx",
22
+ "type": "registry:component",
23
+ "target": "components/example-apps/files/components/files/file-icon.tsx",
24
+ "content": "\"use client\"\n\nimport {\n File01Icon,\n FileAttachmentIcon,\n FolderZipIcon,\n Image01Icon,\n MusicNote01Icon,\n SourceCodeIcon,\n Video01Icon,\n} from \"@hugeicons/core-free-icons\"\nimport { HugeiconsIcon } from \"@hugeicons/react\"\n\nimport { cn } from \"../../lib/utils\"\nimport { FileType } from \"../../mock-data/files\"\n\ninterface FileIconProps {\n type: FileType\n className?: string\n}\n\nconst iconMap = {\n image: { icon: Image01Icon, color: \"text-violet-500\" },\n video: { icon: Video01Icon, color: \"text-pink-500\" },\n document: { icon: File01Icon, color: \"text-amber-500\" },\n archive: { icon: FolderZipIcon, color: \"text-emerald-500\" },\n audio: { icon: MusicNote01Icon, color: \"text-cyan-500\" },\n code: { icon: SourceCodeIcon, color: \"text-blue-500\" },\n other: { icon: FileAttachmentIcon, color: \"text-muted-foreground\" },\n}\n\nexport function FileIcon({ type, className }: FileIconProps) {\n const { icon, color } = iconMap[type] || iconMap.other\n\n return (\n <HugeiconsIcon icon={icon} className={cn(\"size-5\", color, className)} />\n )\n}\n"
25
+ },
26
+ {
27
+ "path": "registry/example-apps/default/files/components/files/file-list.tsx",
28
+ "type": "registry:component",
29
+ "target": "components/example-apps/files/components/files/file-list.tsx",
30
+ "content": "\"use client\"\n\nimport {\n Clock01Icon,\n Delete01Icon,\n FavouriteIcon,\n FolderOpenIcon,\n MoreVerticalIcon,\n Share01Icon,\n UserGroupIcon,\n} from \"@hugeicons/core-free-icons\"\nimport { HugeiconsIcon } from \"@hugeicons/react\"\n\nimport { Button } from \"@loveui/ui/ui/button\"\nimport {\n DropdownMenu,\n DropdownMenuContent,\n DropdownMenuGroup,\n DropdownMenuItem,\n DropdownMenuSeparator,\n DropdownMenuTrigger,\n} from \"@loveui/ui/ui/menu\"\nimport { Tooltip, TooltipContent, TooltipTrigger } from \"@loveui/ui/ui/tooltip\"\n\nimport { cn } from \"../../lib/utils\"\nimport { useFilesStore } from \"../../store/files-store\"\nimport { ViewType } from \"./content\"\nimport { FileIcon } from \"./file-icon\"\n\ninterface FileListProps {\n view: ViewType\n folderId?: string\n}\n\nexport function FileList({ view, folderId }: FileListProps) {\n const {\n viewMode,\n toggleStarred,\n getFilteredFiles,\n getStarredFiles,\n getRecentFiles,\n getSharedFiles,\n getFilesByFolder,\n } = useFilesStore()\n\n let files = getFilteredFiles()\n let title = \"All Assets\"\n\n if (view === \"starred\") {\n files = getStarredFiles()\n title = \"Pinned Assets\"\n } else if (view === \"recent\") {\n files = getRecentFiles()\n title = \"Latest Assets\"\n } else if (view === \"shared\") {\n files = getSharedFiles()\n title = \"Shared Assets\"\n } else if (view === \"trash\") {\n files = []\n title = \"Archive Bin\"\n } else if (view === \"folder\" && folderId) {\n files = getFilesByFolder(folderId)\n title = \"Collection\"\n }\n\n if (files.length === 0) {\n const emptyStates = {\n starred: {\n icon: FavouriteIcon,\n title: \"No pinned assets\",\n description: \"Pin important assets to keep them on top\",\n },\n recent: {\n icon: Clock01Icon,\n title: \"No recent assets\",\n description: \"Assets you open will appear here\",\n },\n shared: {\n icon: UserGroupIcon,\n title: \"No shared assets\",\n description: \"Assets shared with you will appear here\",\n },\n trash: {\n icon: Delete01Icon,\n title: \"Archive bin is empty\",\n description: \"Removed assets will appear here for 30 days\",\n },\n default: {\n icon: FolderOpenIcon,\n title: \"This collection is empty\",\n description: \"Upload assets or drag and drop them here\",\n },\n }\n\n const state =\n emptyStates[view as keyof typeof emptyStates] || emptyStates.default\n const Icon = state.icon\n\n return (\n <div className=\"flex flex-col items-center justify-center py-16 text-center\">\n <div className=\"mb-4 flex size-16 items-center justify-center rounded-2xl bg-muted\">\n <HugeiconsIcon icon={Icon} className=\"size-7 text-muted-foreground\" />\n </div>\n <h3 className=\"mb-1 text-lg font-medium\">{state.title}</h3>\n <p className=\"max-w-xs text-sm text-muted-foreground\">\n {state.description}\n </p>\n </div>\n )\n }\n\n if (viewMode === \"grid\") {\n return (\n <div className=\"space-y-4\">\n <h2 className=\"text-sm font-medium text-muted-foreground\">{title}</h2>\n <div className=\"grid grid-cols-2 gap-3 sm:grid-cols-3 lg:grid-cols-4\">\n {files.map((file) => (\n <div\n key={file.id}\n className=\"group cursor-pointer rounded-xl border bg-card p-4 transition-all hover:bg-accent/50\"\n >\n <div className=\"mb-3 flex items-start justify-between\">\n <FileIcon type={file.type} />\n <div className=\"flex items-center gap-1\">\n <Tooltip>\n <TooltipTrigger\n render={\n <Button\n variant=\"ghost\"\n size=\"icon\"\n className={cn(\n \"size-7 transition-opacity\",\n file.starred\n ? \"opacity-100\"\n : \"opacity-0 group-hover:opacity-100\"\n )}\n onClick={(e) => {\n e.stopPropagation()\n toggleStarred(file.id)\n }}\n >\n <HugeiconsIcon\n icon={FavouriteIcon}\n className={cn(\n \"size-4\",\n file.starred && \"fill-amber-400 text-amber-400\"\n )}\n />\n </Button>\n }\n />\n <TooltipContent>\n {file.starred ? \"Remove from starred\" : \"Add to starred\"}\n </TooltipContent>\n </Tooltip>\n <DropdownMenu>\n <DropdownMenuTrigger\n render={\n <Button\n variant=\"ghost\"\n size=\"icon\"\n className=\"size-7\"\n onClick={(e) => e.stopPropagation()}\n >\n <HugeiconsIcon\n icon={MoreVerticalIcon}\n className=\"size-4\"\n />\n </Button>\n }\n />\n <DropdownMenuContent align=\"end\">\n <DropdownMenuGroup>\n <DropdownMenuItem>Download</DropdownMenuItem>\n <DropdownMenuItem>Rename</DropdownMenuItem>\n <DropdownMenuItem>Share</DropdownMenuItem>\n </DropdownMenuGroup>\n <DropdownMenuSeparator />\n <DropdownMenuItem variant=\"destructive\">\n Delete\n </DropdownMenuItem>\n </DropdownMenuContent>\n </DropdownMenu>\n </div>\n </div>\n <p className=\"mb-0.5 truncate text-sm font-medium\">{file.name}</p>\n <div className=\"flex items-center gap-2 text-xs text-muted-foreground\">\n <span>{file.size}</span>\n {file.shared && (\n <HugeiconsIcon icon={Share01Icon} className=\"size-3\" />\n )}\n </div>\n </div>\n ))}\n </div>\n </div>\n )\n }\n\n return (\n <div className=\"space-y-4\">\n <h2 className=\"text-sm font-medium text-muted-foreground\">{title}</h2>\n <div className=\"overflow-hidden rounded-xl border bg-card\">\n <div className=\"hidden grid-cols-[1fr_100px_100px_100px_70px] gap-4 border-b bg-muted/50 px-4 py-3 text-xs font-medium text-muted-foreground sm:grid\">\n <span>Name</span>\n <span>Size</span>\n <span>Modified</span>\n <span>Created</span>\n <span></span>\n </div>\n <div className=\"divide-y\">\n {files.map((file) => (\n <div\n key={file.id}\n className=\"group grid cursor-pointer grid-cols-[1fr_auto] items-center gap-2 px-4 py-3 transition-colors hover:bg-accent/50 sm:grid-cols-[1fr_100px_100px_100px_70px] sm:gap-4\"\n >\n <div className=\"flex min-w-0 items-center gap-3\">\n <FileIcon type={file.type} />\n <div className=\"min-w-0\">\n <p className=\"truncate text-sm font-medium\">{file.name}</p>\n <p className=\"text-xs text-muted-foreground sm:hidden\">\n {file.size} · {file.modifiedAt}\n </p>\n </div>\n {file.shared && (\n <HugeiconsIcon\n icon={Share01Icon}\n className=\"hidden size-3.5 shrink-0 text-muted-foreground sm:block\"\n />\n )}\n </div>\n <span className=\"hidden text-sm text-muted-foreground sm:block\">\n {file.size}\n </span>\n <span className=\"hidden text-sm text-muted-foreground sm:block\">\n {file.modifiedAt}\n </span>\n <span className=\"hidden text-sm text-muted-foreground sm:block\">\n {file.createdAt}\n </span>\n <div className=\"flex items-center gap-1\">\n <Tooltip>\n <TooltipTrigger\n render={\n <Button\n variant=\"ghost\"\n size=\"icon\"\n className={cn(\n \"size-7 transition-opacity\",\n file.starred\n ? \"opacity-100\"\n : \"opacity-0 group-hover:opacity-100\"\n )}\n onClick={(e) => {\n e.stopPropagation()\n toggleStarred(file.id)\n }}\n >\n <HugeiconsIcon\n icon={FavouriteIcon}\n className={cn(\n \"size-4\",\n file.starred && \"fill-amber-400 text-amber-400\"\n )}\n />\n </Button>\n }\n />\n <TooltipContent>\n {file.starred ? \"Remove from starred\" : \"Add to starred\"}\n </TooltipContent>\n </Tooltip>\n <DropdownMenu>\n <DropdownMenuTrigger\n render={\n <Button\n variant=\"ghost\"\n size=\"icon\"\n className=\"size-7\"\n onClick={(e) => e.stopPropagation()}\n >\n <HugeiconsIcon\n icon={MoreVerticalIcon}\n className=\"size-4\"\n />\n </Button>\n }\n />\n <DropdownMenuContent align=\"end\">\n <DropdownMenuGroup>\n <DropdownMenuItem>Download</DropdownMenuItem>\n <DropdownMenuItem>Rename</DropdownMenuItem>\n <DropdownMenuItem>Share</DropdownMenuItem>\n </DropdownMenuGroup>\n <DropdownMenuSeparator />\n <DropdownMenuItem variant=\"destructive\">\n Delete\n </DropdownMenuItem>\n </DropdownMenuContent>\n </DropdownMenu>\n </div>\n </div>\n ))}\n </div>\n </div>\n </div>\n )\n}\n"
31
+ },
32
+ {
33
+ "path": "registry/example-apps/default/files/components/files/folder-grid.tsx",
34
+ "type": "registry:component",
35
+ "target": "components/example-apps/files/components/files/folder-grid.tsx",
36
+ "content": "\"use client\"\n\nimport Link from \"next/link\"\nimport { usePathname } from \"next/navigation\"\nimport { Folder01Icon, MoreVerticalIcon } from \"@hugeicons/core-free-icons\"\nimport { HugeiconsIcon } from \"@hugeicons/react\"\n\nimport { Button } from \"@loveui/ui/ui/button\"\nimport {\n DropdownMenu,\n DropdownMenuContent,\n DropdownMenuGroup,\n DropdownMenuItem,\n DropdownMenuSeparator,\n DropdownMenuTrigger,\n} from \"@loveui/ui/ui/menu\"\n\nimport { cn } from \"../../lib/utils\"\nimport { useFilesStore } from \"../../store/files-store\"\n\nexport function FolderGrid() {\n const { folders } = useFilesStore()\n const pathname = usePathname()\n\n if (pathname !== \"/\") {\n return null\n }\n\n return (\n <div className=\"space-y-4\">\n <div className=\"flex items-center justify-between\">\n <h2 className=\"text-sm font-medium text-muted-foreground\">Folders</h2>\n </div>\n <div className=\"grid grid-cols-2 gap-3 sm:grid-cols-3 lg:grid-cols-5\">\n {folders.map((folder) => (\n <Link\n key={folder.id}\n href={`/folder/${folder.id}`}\n className={cn(\n \"group block cursor-pointer rounded-xl border bg-card p-4 transition-all hover:bg-accent/50\"\n )}\n >\n <div className=\"mb-3 flex items-start justify-between\">\n <div\n className=\"flex size-10 items-center justify-center rounded-lg\"\n style={{ backgroundColor: `${folder.color}15` }}\n >\n <HugeiconsIcon\n icon={Folder01Icon}\n className=\"size-5\"\n style={{ color: folder.color }}\n />\n </div>\n <DropdownMenu>\n <DropdownMenuTrigger\n render={\n <Button\n variant=\"ghost\"\n size=\"icon\"\n className=\"size-7\"\n onClick={(e) => e.preventDefault()}\n >\n <HugeiconsIcon\n icon={MoreVerticalIcon}\n className=\"size-4\"\n />\n </Button>\n }\n />\n <DropdownMenuContent align=\"end\">\n <DropdownMenuGroup>\n <DropdownMenuItem>Open</DropdownMenuItem>\n <DropdownMenuItem>Rename</DropdownMenuItem>\n <DropdownMenuItem>Share</DropdownMenuItem>\n </DropdownMenuGroup>\n <DropdownMenuSeparator />\n <DropdownMenuItem variant=\"destructive\">\n Delete\n </DropdownMenuItem>\n </DropdownMenuContent>\n </DropdownMenu>\n </div>\n <p className=\"mb-0.5 truncate text-sm font-medium\">{folder.name}</p>\n <p className=\"text-xs text-muted-foreground\">\n {folder.filesCount} files · {folder.size}\n </p>\n </Link>\n ))}\n </div>\n </div>\n )\n}\n"
37
+ },
38
+ {
39
+ "path": "registry/example-apps/default/files/components/files/header.tsx",
40
+ "type": "registry:component",
41
+ "target": "components/example-apps/files/components/files/header.tsx",
42
+ "content": "\"use client\"\n\nimport {\n GridViewIcon,\n Menu01Icon,\n MoreVerticalIcon,\n Notification01Icon,\n Search01Icon,\n} from \"@hugeicons/core-free-icons\"\nimport { HugeiconsIcon } from \"@hugeicons/react\"\n\nimport { Button } from \"@loveui/ui/ui/button\"\nimport { Input } from \"@loveui/ui/ui/input\"\nimport {\n DropdownMenu,\n DropdownMenuContent,\n DropdownMenuGroup,\n DropdownMenuItem,\n DropdownMenuTrigger,\n} from \"@loveui/ui/ui/menu\"\n\nimport { SidebarTrigger } from \"@/components/ui/sidebar\"\n\nimport { cn } from \"../../lib/utils\"\nimport { useFilesStore } from \"../../store/files-store\"\nimport { ThemeToggle } from \"../theme-toggle\"\nimport { Breadcrumb } from \"./breadcrumb\"\nimport { QuickActions } from \"./quick-actions\"\n\nexport function FilesHeader() {\n const { searchQuery, setSearchQuery, viewMode, setViewMode } = useFilesStore()\n\n return (\n <header className=\"sticky top-0 z-10 flex w-full items-center gap-2 border-b bg-card px-3 py-2 sm:gap-3 sm:px-6 sm:py-3\">\n <SidebarTrigger className=\"-ml-1 sm:-ml-2\" />\n\n <div className=\"hidden lg:block\">\n <Breadcrumb />\n </div>\n\n <div className=\"flex-1 lg:hidden\">\n <Breadcrumb />\n </div>\n\n <div className=\"hidden flex-1 items-center justify-center gap-2 lg:flex\">\n <QuickActions />\n </div>\n\n <div className=\"relative hidden max-w-xs md:block\">\n <HugeiconsIcon\n icon={Search01Icon}\n className=\"pointer-events-none absolute top-1/2 left-3 z-10 size-4 -translate-y-1/2 text-muted-foreground\"\n />\n <Input\n placeholder=\"Search assets...\"\n value={searchQuery}\n onChange={(e) => setSearchQuery(e.target.value)}\n className=\"h-9 border bg-card pl-9\"\n />\n </div>\n\n <div className=\"hidden items-center gap-1 rounded-lg border p-0.5 sm:flex\">\n <Button\n variant=\"ghost\"\n size=\"icon-sm\"\n onClick={() => setViewMode(\"grid\")}\n className={cn(\"size-7.5\", viewMode === \"grid\" && \"bg-muted\")}\n >\n <HugeiconsIcon icon={GridViewIcon} className=\"size-4\" />\n </Button>\n <Button\n variant=\"ghost\"\n size=\"icon-sm\"\n onClick={() => setViewMode(\"list\")}\n className={cn(\"size-7.5\", viewMode === \"list\" && \"bg-muted\")}\n >\n <HugeiconsIcon icon={Menu01Icon} className=\"size-4\" />\n </Button>\n </div>\n\n <ThemeToggle />\n\n <DropdownMenu>\n <DropdownMenuTrigger\n render={\n <Button variant=\"ghost\" size=\"icon\" className=\"h-8 w-8 sm:hidden\">\n <HugeiconsIcon icon={MoreVerticalIcon} className=\"size-4\" />\n </Button>\n }\n />\n <DropdownMenuContent className=\"w-40\" align=\"end\">\n <DropdownMenuGroup>\n <DropdownMenuItem>\n <HugeiconsIcon icon={Search01Icon} className=\"mr-2 size-4\" />\n Search\n </DropdownMenuItem>\n <DropdownMenuItem\n onClick={() => setViewMode(viewMode === \"grid\" ? \"list\" : \"grid\")}\n >\n {viewMode === \"grid\" ? (\n <HugeiconsIcon icon={Menu01Icon} className=\"mr-2 size-4\" />\n ) : (\n <HugeiconsIcon icon={GridViewIcon} className=\"mr-2 size-4\" />\n )}\n {viewMode === \"grid\" ? \"List View\" : \"Grid View\"}\n </DropdownMenuItem>\n <DropdownMenuItem>\n <HugeiconsIcon\n icon={Notification01Icon}\n className=\"mr-2 size-4\"\n />\n Notifications\n </DropdownMenuItem>\n </DropdownMenuGroup>\n </DropdownMenuContent>\n </DropdownMenu>\n </header>\n )\n}\n"
43
+ },
44
+ {
45
+ "path": "registry/example-apps/default/files/components/files/quick-actions.tsx",
46
+ "type": "registry:component",
47
+ "target": "components/example-apps/files/components/files/quick-actions.tsx",
48
+ "content": "\"use client\"\n\nimport {\n FileImportIcon,\n FolderAddIcon,\n Link01Icon,\n Upload01Icon,\n} from \"@hugeicons/core-free-icons\"\nimport { HugeiconsIcon } from \"@hugeicons/react\"\n\nimport { Button } from \"@loveui/ui/ui/button\"\nimport { Tooltip, TooltipContent, TooltipTrigger } from \"@loveui/ui/ui/tooltip\"\n\nconst actions = [\n { icon: Upload01Icon, label: \"Upload Clip\", shortcut: \"⌘U\" },\n { icon: FolderAddIcon, label: \"New Collection\", shortcut: \"⌘N\" },\n { icon: Link01Icon, label: \"Share Review Link\", shortcut: \"⌘L\" },\n { icon: FileImportIcon, label: \"Import Dailies\", shortcut: \"⌘I\" },\n]\n\nexport function QuickActions() {\n return (\n <div className=\"flex items-center gap-1 rounded-xl border bg-card p-1\">\n {actions.map((action) => (\n <Tooltip key={action.label}>\n <TooltipTrigger\n render={\n <Button variant=\"ghost\" size=\"icon\" className=\"size-9 rounded-lg\">\n <HugeiconsIcon icon={action.icon} className=\"size-4\" />\n </Button>\n }\n />\n <TooltipContent side=\"bottom\" className=\"flex items-center gap-2\">\n <span>{action.label}</span>\n <kbd className=\"rounded border border-muted-foreground/50 px-1.5 py-0.5 text-[10px]\">\n {action.shortcut}\n </kbd>\n </TooltipContent>\n </Tooltip>\n ))}\n </div>\n )\n}\n"
49
+ },
50
+ {
51
+ "path": "registry/example-apps/default/files/components/files/recent-activity.tsx",
52
+ "type": "registry:component",
53
+ "target": "components/example-apps/files/components/files/recent-activity.tsx",
54
+ "content": "\"use client\"\n\nimport {\n Comment01Icon,\n Delete01Icon,\n Download01Icon,\n Edit01Icon,\n FolderTransferIcon,\n Share01Icon,\n Upload01Icon,\n} from \"@hugeicons/core-free-icons\"\nimport { HugeiconsIcon } from \"@hugeicons/react\"\n\nimport { Avatar, AvatarFallback, AvatarImage } from \"@loveui/ui/ui/avatar\"\n\nimport { cn } from \"../../lib/utils\"\n\nconst activities = [\n {\n id: \"1\",\n user: { name: \"Ava Patel\", avatar: \"ava\", initials: \"AP\" },\n action: \"uploaded\",\n file: \"Kenya_Savannah_Day03_Acam_4K.mov\",\n time: \"2 min ago\",\n icon: Upload01Icon,\n iconColor: \"text-emerald-500\",\n iconBg: \"bg-emerald-500/10\",\n },\n {\n id: \"2\",\n user: { name: \"Nora Singh\", avatar: \"nora\", initials: \"NS\" },\n action: \"shared\",\n file: \"Narrative_BeatBoard.pdf\",\n time: \"15 min ago\",\n icon: Share01Icon,\n iconColor: \"text-blue-500\",\n iconBg: \"bg-blue-500/10\",\n },\n {\n id: \"3\",\n user: { name: \"Theo Bennett\", avatar: \"theo\", initials: \"TB\" },\n action: \"edited\",\n file: \"Episode02_Edit_v14.prproj\",\n time: \"1 hour ago\",\n icon: Edit01Icon,\n iconColor: \"text-amber-500\",\n iconBg: \"bg-amber-500/10\",\n },\n {\n id: \"4\",\n user: { name: \"Liam Carter\", avatar: \"liam\", initials: \"LC\" },\n action: \"downloaded\",\n file: \"Festival_Submission_Package.zip\",\n time: \"3 hours ago\",\n icon: Download01Icon,\n iconColor: \"text-violet-500\",\n iconBg: \"bg-violet-500/10\",\n },\n {\n id: \"5\",\n user: { name: \"Maya Ortiz\", avatar: \"maya\", initials: \"MO\" },\n action: \"moved\",\n file: \"Camp_Ambience_Master.wav\",\n time: \"5 hours ago\",\n icon: FolderTransferIcon,\n iconColor: \"text-cyan-500\",\n iconBg: \"bg-cyan-500/10\",\n },\n {\n id: \"6\",\n user: { name: \"Ari Kim\", avatar: \"ari\", initials: \"AK\" },\n action: \"commented on\",\n file: \"Interview_Transcript_DrSafi.pdf\",\n time: \"Yesterday\",\n icon: Comment01Icon,\n iconColor: \"text-pink-500\",\n iconBg: \"bg-pink-500/10\",\n },\n {\n id: \"7\",\n user: { name: \"Noah Reid\", avatar: \"noah\", initials: \"NR\" },\n action: \"deleted\",\n file: \"RoughCut_Archive_2025.zip\",\n time: \"Yesterday\",\n icon: Delete01Icon,\n iconColor: \"text-red-500\",\n iconBg: \"bg-red-500/10\",\n },\n]\n\nexport function RecentActivity() {\n return (\n <div className=\"rounded-xl border bg-card p-4\">\n <div className=\"mb-4 flex items-center justify-between\">\n <h3 className=\"text-sm font-medium\">Recent Activity</h3>\n <button className=\"text-xs text-muted-foreground transition-colors hover:text-foreground\">\n View all\n </button>\n </div>\n <div className=\"space-y-3\">\n {activities.map((activity) => (\n <div key={activity.id} className=\"flex items-start gap-3\">\n <Avatar className=\"size-8\">\n <AvatarImage\n src={`https://api.dicebear.com/9.x/glass/svg?seed=${activity.user.avatar}`}\n />\n <AvatarFallback className=\"text-[10px]\">\n {activity.user.initials}\n </AvatarFallback>\n </Avatar>\n <div className=\"min-w-0 flex-1\">\n <p className=\"text-sm\">\n <span className=\"font-medium\">{activity.user.name}</span>{\" \"}\n <span className=\"text-muted-foreground\">{activity.action}</span>\n </p>\n <p className=\"truncate text-xs text-muted-foreground\">\n {activity.file}\n </p>\n </div>\n <div className=\"flex shrink-0 items-center gap-2\">\n <div\n className={cn(\n \"flex size-6 items-center justify-center rounded-md\",\n activity.iconBg\n )}\n >\n <HugeiconsIcon\n icon={activity.icon}\n className={cn(\"size-3\", activity.iconColor)}\n />\n </div>\n <span className=\"text-[10px] whitespace-nowrap text-muted-foreground\">\n {activity.time}\n </span>\n </div>\n </div>\n ))}\n </div>\n </div>\n )\n}\n"
55
+ },
56
+ {
57
+ "path": "registry/example-apps/default/files/components/files/shared-with-me.tsx",
58
+ "type": "registry:component",
59
+ "target": "components/example-apps/files/components/files/shared-with-me.tsx",
60
+ "content": "\"use client\"\n\nimport { Add01Icon } from \"@hugeicons/core-free-icons\"\nimport { HugeiconsIcon } from \"@hugeicons/react\"\n\nimport { Avatar, AvatarFallback, AvatarImage } from \"@loveui/ui/ui/avatar\"\nimport { Button } from \"@loveui/ui/ui/button\"\nimport { Tooltip, TooltipContent, TooltipTrigger } from \"@loveui/ui/ui/tooltip\"\n\nconst sharedUsers = [\n { name: \"Maya Ortiz\", avatar: \"maya\", initials: \"MO\" },\n { name: \"Liam Carter\", avatar: \"liam\", initials: \"LC\" },\n { name: \"Nora Singh\", avatar: \"nora\", initials: \"NS\" },\n { name: \"Theo Bennett\", avatar: \"theo\", initials: \"TB\" },\n { name: \"Ari Kim\", avatar: \"ari\", initials: \"AK\" },\n]\n\nexport function SharedWithMe() {\n return (\n <div className=\"rounded-xl border bg-card p-4\">\n <div className=\"mb-3 flex items-center justify-between\">\n <h3 className=\"text-sm font-medium\">Field Crew</h3>\n <span className=\"text-xs text-muted-foreground\">\n {sharedUsers.length} collaborators\n </span>\n </div>\n <div className=\"flex items-center\">\n <div className=\"flex -space-x-2\">\n {sharedUsers.slice(0, 4).map((user) => (\n <Tooltip key={user.name}>\n <TooltipTrigger\n render={\n <Avatar className=\"size-8 cursor-pointer border-2 border-card transition-transform hover:z-10 hover:scale-110\">\n <AvatarImage\n src={`https://api.dicebear.com/9.x/glass/svg?seed=${user.avatar}`}\n />\n <AvatarFallback className=\"text-[10px]\">\n {user.initials}\n </AvatarFallback>\n </Avatar>\n }\n />\n <TooltipContent>{user.name}</TooltipContent>\n </Tooltip>\n ))}\n {sharedUsers.length > 4 && (\n <Tooltip>\n <TooltipTrigger\n render={\n <div className=\"flex size-8 cursor-pointer items-center justify-center rounded-full border-2 border-card bg-muted transition-colors hover:bg-muted/80\">\n <span className=\"text-xs font-medium text-muted-foreground\">\n +{sharedUsers.length - 4}\n </span>\n </div>\n }\n />\n <TooltipContent>\n {sharedUsers\n .slice(4)\n .map((u) => u.name)\n .join(\", \")}\n </TooltipContent>\n </Tooltip>\n )}\n </div>\n <Button variant=\"outline\" size=\"icon\" className=\"ml-2 size-8\">\n <HugeiconsIcon icon={Add01Icon} className=\"size-4\" />\n </Button>\n </div>\n </div>\n )\n}\n"
61
+ },
62
+ {
63
+ "path": "registry/example-apps/default/files/components/files/sidebar.tsx",
64
+ "type": "registry:component",
65
+ "target": "components/example-apps/files/components/files/sidebar.tsx",
66
+ "content": "\"use client\"\n\nimport * as React from \"react\"\nimport Link from \"next/link\"\nimport { usePathname } from \"next/navigation\"\nimport {\n Add01Icon,\n ArrowDown01Icon,\n Clock01Icon,\n Delete01Icon,\n FavouriteIcon,\n File01Icon,\n Folder01Icon,\n FolderAddIcon,\n Globe02Icon,\n HardDriveIcon,\n Home01Icon,\n Image01Icon,\n Link01Icon,\n Logout01Icon,\n Settings01Icon,\n Share01Icon,\n UnfoldMoreIcon,\n Upload01Icon,\n UserCircle02Icon,\n} from \"@hugeicons/core-free-icons\"\nimport { HugeiconsIcon } from \"@hugeicons/react\"\n\nimport { Avatar, AvatarFallback, AvatarImage } from \"@loveui/ui/ui/avatar\"\nimport { Button } from \"@loveui/ui/ui/button\"\nimport {\n Collapsible,\n CollapsibleContent,\n CollapsibleTrigger,\n} from \"@loveui/ui/ui/collapsible\"\nimport {\n DropdownMenu,\n DropdownMenuContent,\n DropdownMenuGroup,\n DropdownMenuItem,\n DropdownMenuSeparator,\n DropdownMenuTrigger,\n} from \"@loveui/ui/ui/menu\"\nimport { Progress } from \"@loveui/ui/ui/progress\"\n\nimport {\n Sidebar,\n SidebarContent,\n SidebarFooter,\n SidebarGroup,\n SidebarGroupContent,\n SidebarGroupLabel,\n SidebarHeader,\n SidebarMenu,\n SidebarMenuButton,\n SidebarMenuItem,\n} from \"@/components/ui/sidebar\"\n\nimport { cn } from \"../../lib/utils\"\nimport { storageData } from \"../../mock-data/files\"\nimport { useFilesStore } from \"../../store/files-store\"\n\nconst menuItems = [\n { icon: Home01Icon, label: \"All Assets\", href: \"/\" },\n { icon: FavouriteIcon, label: \"Pinned\", href: \"/starred\" },\n { icon: Clock01Icon, label: \"Latest\", href: \"/recent\" },\n { icon: Share01Icon, label: \"Shared\", href: \"/shared\" },\n { icon: Delete01Icon, label: \"Archive Bin\", href: \"/trash\" },\n]\n\nexport function FilesSidebar({\n ...props\n}: React.ComponentProps<typeof Sidebar>) {\n const { folders } = useFilesStore()\n const pathname = usePathname()\n const [foldersOpen, setFoldersOpen] = React.useState(true)\n\n const storagePercentage = (storageData.used / storageData.total) * 100\n\n return (\n <Sidebar className=\"lg:border-r-0!\" collapsible=\"offExamples\" {...props}>\n <SidebarHeader className=\"p-4 pb-0\">\n <div className=\"flex items-center gap-2.5\">\n <div className=\"flex size-8 items-center justify-center rounded-lg bg-linear-to-br from-violet-500 to-fuchsia-500\">\n <HugeiconsIcon icon={HardDriveIcon} className=\"size-4 text-white\" />\n </div>\n <span className=\"text-base font-semibold\">DocuVault</span>\n </div>\n </SidebarHeader>\n\n <SidebarContent className=\"px-4 pt-6\">\n <DropdownMenu>\n <DropdownMenuTrigger\n render={\n <Button className=\"mb-4 w-full gap-2\">\n <HugeiconsIcon icon={Add01Icon} className=\"size-4\" />\n Add Asset\n </Button>\n }\n />\n <DropdownMenuContent align=\"start\" className=\"w-48\">\n <DropdownMenuGroup>\n <DropdownMenuItem>\n <HugeiconsIcon icon={Upload01Icon} className=\"mr-2 size-4\" />\n Upload Clip\n </DropdownMenuItem>\n <DropdownMenuItem>\n <HugeiconsIcon icon={FolderAddIcon} className=\"mr-2 size-4\" />\n New Collection\n </DropdownMenuItem>\n </DropdownMenuGroup>\n <DropdownMenuSeparator />\n <DropdownMenuGroup>\n <DropdownMenuItem>\n <HugeiconsIcon icon={File01Icon} className=\"mr-2 size-4\" />\n New Log\n </DropdownMenuItem>\n <DropdownMenuItem>\n <HugeiconsIcon icon={Image01Icon} className=\"mr-2 size-4\" />\n New Still\n </DropdownMenuItem>\n </DropdownMenuGroup>\n <DropdownMenuSeparator />\n <DropdownMenuGroup>\n <DropdownMenuItem>\n <HugeiconsIcon icon={Link01Icon} className=\"mr-2 size-4\" />\n Add Reference Link\n </DropdownMenuItem>\n </DropdownMenuGroup>\n </DropdownMenuContent>\n </DropdownMenu>\n\n <SidebarGroup className=\"p-0\">\n <SidebarGroupContent>\n <SidebarMenu>\n {menuItems.map((item) => (\n <SidebarMenuItem key={item.label}>\n <SidebarMenuButton\n render={<Link href={item.href} />}\n isActive={pathname === item.href}\n className=\"h-9\"\n >\n <HugeiconsIcon icon={item.icon} className=\"size-4\" />\n <span className=\"text-sm\">{item.label}</span>\n </SidebarMenuButton>\n </SidebarMenuItem>\n ))}\n </SidebarMenu>\n </SidebarGroupContent>\n </SidebarGroup>\n\n <Collapsible open={foldersOpen} onOpenChange={setFoldersOpen}>\n <SidebarGroup className=\"mt-4 p-0\">\n <CollapsibleTrigger\n nativeButton={false}\n render={\n <SidebarGroupLabel className=\"flex h-4 cursor-pointer items-center justify-between pt-2 pb-4 text-[10px] tracking-widest text-muted-foreground uppercase hover:bg-transparent hover:text-foreground\">\n <div className=\"flex items-center gap-1\">\n <HugeiconsIcon\n icon={ArrowDown01Icon}\n className={cn(\n \"size-3 transition-transform\",\n !foldersOpen && \"-rotate-90\"\n )}\n />\n <span>Folders</span>\n </div>\n <Button\n variant=\"ghost\"\n size=\"icon\"\n className=\"size-5 hover:bg-muted\"\n onClick={(e) => e.stopPropagation()}\n >\n <HugeiconsIcon icon={Add01Icon} className=\"size-3\" />\n </Button>\n </SidebarGroupLabel>\n }\n />\n <CollapsibleContent>\n <SidebarGroupContent>\n <SidebarMenu>\n {folders.map((folder) => (\n <SidebarMenuItem key={folder.id}>\n <SidebarMenuButton\n render={<Link href={`/folder/${folder.id}`} />}\n isActive={pathname === `/folder/${folder.id}`}\n className=\"h-9\"\n >\n <HugeiconsIcon\n icon={Folder01Icon}\n className=\"size-4\"\n style={{ color: folder.color }}\n />\n <span className=\"flex-1 truncate text-sm\">\n {folder.name}\n </span>\n <span className=\"text-xs text-muted-foreground\">\n {folder.filesCount}\n </span>\n </SidebarMenuButton>\n </SidebarMenuItem>\n ))}\n </SidebarMenu>\n </SidebarGroupContent>\n </CollapsibleContent>\n </SidebarGroup>\n </Collapsible>\n\n <div className=\"mt-6 rounded-xl border bg-card p-3\">\n <div className=\"mb-2 flex items-center justify-between\">\n <span className=\"text-sm font-medium\">Vault Storage</span>\n <span className=\"text-xs text-muted-foreground\">\n {storageData.used} GB / {storageData.total} GB\n </span>\n </div>\n <Progress value={storagePercentage} className=\"h-2\" />\n <div className=\"mt-3 flex flex-wrap gap-2\">\n {storageData.breakdown.slice(0, 3).map((item) => (\n <div key={item.type} className=\"flex items-center gap-1.5\">\n <div\n className=\"size-2 rounded-full\"\n style={{ backgroundColor: item.color }}\n />\n <span className=\"text-[10px] text-muted-foreground\">\n {item.type}\n </span>\n </div>\n ))}\n </div>\n </div>\n </SidebarContent>\n\n <SidebarFooter className=\"p-4\">\n <DropdownMenu>\n <DropdownMenuTrigger\n render={\n <div className=\"mt-2 flex cursor-pointer items-center gap-3 rounded-lg p-2 transition-colors hover:bg-accent\">\n <Avatar className=\"size-8\">\n <AvatarImage src=\"/ln.png\" />\n <AvatarFallback className=\"text-xs\">AP</AvatarFallback>\n </Avatar>\n <div className=\"min-w-0 flex-1\">\n <p className=\"text-sm font-medium\">Ava Patel</p>\n <p className=\"truncate text-xs text-muted-foreground\">\n archive@docuvault.studio\n </p>\n </div>\n <HugeiconsIcon\n icon={UnfoldMoreIcon}\n className=\"size-4 shrink-0 text-muted-foreground\"\n />\n </div>\n }\n />\n <DropdownMenuContent align=\"end\" className=\"w-[200px]\">\n <DropdownMenuGroup>\n <DropdownMenuItem>\n <HugeiconsIcon\n icon={UserCircle02Icon}\n className=\"mr-2 size-4\"\n />\n Profile\n </DropdownMenuItem>\n <DropdownMenuItem>\n <HugeiconsIcon icon={Settings01Icon} className=\"mr-2 size-4\" />\n Settings\n </DropdownMenuItem>\n </DropdownMenuGroup>\n <DropdownMenuSeparator />\n <DropdownMenuItem variant=\"destructive\">\n <HugeiconsIcon icon={Logout01Icon} className=\"mr-2 size-4\" />\n Log out\n </DropdownMenuItem>\n </DropdownMenuContent>\n </DropdownMenu>\n </SidebarFooter>\n </Sidebar>\n )\n}\n"
67
+ },
68
+ {
69
+ "path": "registry/example-apps/default/files/components/files/storage-cards.tsx",
70
+ "type": "registry:component",
71
+ "target": "components/example-apps/files/components/files/storage-cards.tsx",
72
+ "content": "\"use client\"\n\nimport {\n File01Icon,\n FileAttachmentIcon,\n FolderZipIcon,\n Image01Icon,\n Video01Icon,\n} from \"@hugeicons/core-free-icons\"\nimport { HugeiconsIcon } from \"@hugeicons/react\"\n\nimport { storageData } from \"../../mock-data/files\"\n\nconst iconMap = {\n Images: Image01Icon,\n Videos: Video01Icon,\n Documents: File01Icon,\n Archives: FolderZipIcon,\n Other: FileAttachmentIcon,\n}\n\nexport function StorageCards() {\n return (\n <div className=\"grid grid-cols-2 gap-3 sm:grid-cols-3 lg:grid-cols-5\">\n {storageData.breakdown.map((item) => {\n const Icon =\n iconMap[item.type as keyof typeof iconMap] || FileAttachmentIcon\n const percentage = ((item.size / storageData.total) * 100).toFixed(0)\n\n return (\n <div\n key={item.type}\n className=\"group cursor-pointer rounded-xl border bg-card p-4 transition-colors hover:bg-accent/50\"\n >\n <div\n className=\"mb-3 flex size-10 items-center justify-center rounded-lg\"\n style={{ backgroundColor: `${item.color}15` }}\n >\n <HugeiconsIcon\n icon={Icon}\n className=\"size-5\"\n style={{ color: item.color }}\n />\n </div>\n <p className=\"mb-0.5 text-sm font-medium\">{item.type}</p>\n <div className=\"flex items-center justify-between\">\n <span className=\"text-xs text-muted-foreground\">\n {item.size} GB\n </span>\n <span className=\"text-xs text-muted-foreground\">\n {percentage}%\n </span>\n </div>\n </div>\n )\n })}\n </div>\n )\n}\n"
73
+ },
74
+ {
75
+ "path": "registry/example-apps/default/files/components/files/storage-overview.tsx",
76
+ "type": "registry:component",
77
+ "target": "components/example-apps/files/components/files/storage-overview.tsx",
78
+ "content": "\"use client\"\n\nimport { storageData } from \"../../mock-data/files\"\n\nexport function StorageOverview() {\n const usedPercentage = (storageData.used / storageData.total) * 100\n\n return (\n <div className=\"rounded-xl border bg-card p-4\">\n <div className=\"mb-4 flex items-center justify-between\">\n <h3 className=\"text-sm font-medium\">Storage Overview</h3>\n <button className=\"text-xs font-medium text-violet-500 transition-colors hover:text-violet-600\">\n Upgrade\n </button>\n </div>\n\n <div className=\"relative mb-3 h-3 overflow-hidden rounded-full bg-muted\">\n <div className=\"absolute inset-0 flex overflow-hidden rounded-full\">\n {storageData.breakdown.map((item, index) => {\n const width = (item.size / storageData.used) * usedPercentage\n const isFirst = index === 0\n const isLast = index === storageData.breakdown.length - 1\n return (\n <div\n key={item.type}\n className={`h-full ${isFirst ? \"rounded-l-full\" : \"\"} ${isLast ? \"rounded-r-full\" : \"\"}`}\n style={{\n width: `${width}%`,\n backgroundColor: item.color,\n }}\n />\n )\n })}\n </div>\n </div>\n\n <div className=\"mb-4 flex items-center justify-between text-sm\">\n <span className=\"text-muted-foreground\">\n {storageData.used} GB of {storageData.total} GB used\n </span>\n <span className=\"font-medium\">{usedPercentage.toFixed(0)}%</span>\n </div>\n\n <div className=\"grid grid-cols-2 gap-2\">\n {storageData.breakdown.map((item) => (\n <div\n key={item.type}\n className=\"flex items-center gap-2 rounded-lg bg-muted/50 p-2\"\n >\n <div\n className=\"size-2.5 shrink-0 rounded-full\"\n style={{ backgroundColor: item.color }}\n />\n <span className=\"truncate text-xs text-muted-foreground\">\n {item.type}\n </span>\n <span className=\"ml-auto text-xs font-medium\">{item.size} GB</span>\n </div>\n ))}\n </div>\n </div>\n )\n}\n"
79
+ },
80
+ {
81
+ "path": "registry/example-apps/default/files/components/theme-provider.tsx",
82
+ "type": "registry:component",
83
+ "target": "components/example-apps/files/components/theme-provider.tsx",
84
+ "content": "\"use client\"\n\nimport * as React from \"react\"\nimport { ThemeProvider as NextThemesProvider } from \"next-themes\"\n\nexport function ThemeProvider({\n children,\n ...props\n}: React.ComponentProps<typeof NextThemesProvider>) {\n return <NextThemesProvider {...props}>{children}</NextThemesProvider>\n}\n"
85
+ },
86
+ {
87
+ "path": "registry/example-apps/default/files/components/theme-toggle.tsx",
88
+ "type": "registry:component",
89
+ "target": "components/example-apps/files/components/theme-toggle.tsx",
90
+ "content": "\"use client\"\n\nimport * as React from \"react\"\nimport { Moon01Icon, Sun01Icon } from \"@hugeicons/core-free-icons\"\nimport { HugeiconsIcon } from \"@hugeicons/react\"\nimport { useTheme } from \"next-themes\"\n\nimport { Button } from \"@loveui/ui/ui/button\"\n\nexport function ThemeToggle() {\n const { setTheme, theme } = useTheme()\n\n return (\n <Button\n variant=\"ghost\"\n size=\"icon\"\n onClick={() => setTheme(theme === \"light\" ? \"dark\" : \"light\")}\n >\n <HugeiconsIcon\n icon={Sun01Icon}\n className=\"h-[1.2rem] w-[1.2rem] scale-100 rotate-0 transition-all dark:scale-0 dark:-rotate-90\"\n />\n <HugeiconsIcon\n icon={Moon01Icon}\n className=\"absolute h-[1.2rem] w-[1.2rem] scale-0 rotate-90 transition-all dark:scale-100 dark:rotate-0\"\n />\n <span className=\"sr-only\">Toggle theme</span>\n </Button>\n )\n}\n"
91
+ },
92
+ {
93
+ "path": "registry/example-apps/default/files/components/ui/sidebar.tsx",
94
+ "type": "registry:ui",
95
+ "target": "components/example-apps/files/components/ui/sidebar.tsx",
96
+ "content": "\"use client\"\n\nimport * as React from \"react\"\nimport { mergeProps } from \"@base-ui/react/merge-props\"\nimport { useRender } from \"@base-ui/react/use-render\"\nimport { SidebarLeftIcon } from \"@hugeicons/core-free-icons\"\nimport { HugeiconsIcon } from \"@hugeicons/react\"\nimport { cva, type VariantProps } from \"class-variance-authority\"\n\nimport { Button } from \"@loveui/ui/ui/button\"\nimport { Input } from \"@loveui/ui/ui/input\"\nimport { Separator } from \"@loveui/ui/ui/separator\"\nimport {\n Sheet,\n SheetContent,\n SheetDescription,\n SheetHeader,\n SheetTitle,\n} from \"@loveui/ui/ui/sheet\"\nimport { Skeleton } from \"@loveui/ui/ui/skeleton\"\nimport { Tooltip, TooltipContent, TooltipTrigger } from \"@loveui/ui/ui/tooltip\"\n\nimport { useIsMobile } from \"../../hooks/use-mobile\"\nimport { cn } from \"../../lib/utils\"\n\nconst SIDEBAR_COOKIE_NAME = \"sidebar_state\"\nconst SIDEBAR_COOKIE_MAX_AGE = 60 * 60 * 24 * 7\nconst SIDEBAR_WIDTH = \"16rem\"\nconst SIDEBAR_WIDTH_MOBILE = \"18rem\"\nconst SIDEBAR_WIDTH_ICON = \"3rem\"\nconst SIDEBAR_KEYBOARD_SHORTCUT = \"b\"\n\ntype SidebarContextProps = {\n state: \"expanded\" | \"collapsed\"\n open: boolean\n setOpen: (open: boolean) => void\n openMobile: boolean\n setOpenMobile: (open: boolean) => void\n isMobile: boolean\n toggleSidebar: () => void\n}\n\nconst SidebarContext = React.createContext<SidebarContextProps | null>(null)\n\nfunction useSidebar() {\n const context = React.useContext(SidebarContext)\n if (!context) {\n throw new Error(\"useSidebar must be used within a SidebarProvider.\")\n }\n\n return context\n}\n\nfunction SidebarProvider({\n defaultOpen = true,\n open: openProp,\n onOpenChange: setOpenProp,\n className,\n style,\n children,\n ...props\n}: React.ComponentProps<\"div\"> & {\n defaultOpen?: boolean\n open?: boolean\n onOpenChange?: (open: boolean) => void\n}) {\n const isMobile = useIsMobile()\n const [openMobile, setOpenMobile] = React.useState(false)\n\n // This is the internal state of the sidebar.\n // We use openProp and setOpenProp for control from outside the component.\n const [_open, _setOpen] = React.useState(defaultOpen)\n const open = openProp ?? _open\n const setOpen = React.useCallback(\n (value: boolean | ((value: boolean) => boolean)) => {\n const openState = typeof value === \"function\" ? value(open) : value\n if (setOpenProp) {\n setOpenProp(openState)\n } else {\n _setOpen(openState)\n }\n\n // This sets the cookie to keep the sidebar state.\n document.cookie = `${SIDEBAR_COOKIE_NAME}=${openState}; path=/; max-age=${SIDEBAR_COOKIE_MAX_AGE}`\n },\n [setOpenProp, open]\n )\n\n // Helper to toggle the sidebar.\n const toggleSidebar = React.useCallback(() => {\n return isMobile ? setOpenMobile((open) => !open) : setOpen((open) => !open)\n }, [isMobile, setOpen, setOpenMobile])\n\n // Adds a keyboard shortcut to toggle the sidebar.\n React.useEffect(() => {\n const handleKeyDown = (event: KeyboardEvent) => {\n if (\n event.key === SIDEBAR_KEYBOARD_SHORTCUT &&\n (event.metaKey || event.ctrlKey)\n ) {\n event.preventDefault()\n toggleSidebar()\n }\n }\n\n window.addEventListener(\"keydown\", handleKeyDown)\n return () => window.removeEventListener(\"keydown\", handleKeyDown)\n }, [toggleSidebar])\n\n // We add a state so that we can do data-state=\"expanded\" or \"collapsed\".\n // This makes it easier to style the sidebar with Tailwind classes.\n const state = open ? \"expanded\" : \"collapsed\"\n\n const contextValue = React.useMemo<SidebarContextProps>(\n () => ({\n state,\n open,\n setOpen,\n isMobile,\n openMobile,\n setOpenMobile,\n toggleSidebar,\n }),\n [state, open, setOpen, isMobile, openMobile, setOpenMobile, toggleSidebar]\n )\n\n return (\n <SidebarContext.Provider value={contextValue}>\n <div\n data-slot=\"sidebar-wrapper\"\n style={\n {\n \"--sidebar-width\": SIDEBAR_WIDTH,\n \"--sidebar-width-icon\": SIDEBAR_WIDTH_ICON,\n ...style,\n } as any\n }\n className={cn(\n \"group/sidebar-wrapper flex min-h-svh w-full has-data-[variant=inset]:bg-sidebar\",\n className\n )}\n {...props}\n >\n {children}\n </div>\n </SidebarContext.Provider>\n )\n}\n\nfunction Sidebar({\n side = \"left\",\n variant = \"sidebar\",\n collapsible = \"offExamples\",\n className,\n children,\n ...props\n}: React.ComponentProps<\"div\"> & {\n side?: \"left\" | \"right\"\n variant?: \"sidebar\" | \"floating\" | \"inset\"\n collapsible?: \"offExamples\" | \"icon\" | \"none\"\n}) {\n const { isMobile, state, openMobile, setOpenMobile } = useSidebar()\n\n if (collapsible === \"none\") {\n return (\n <div\n data-slot=\"sidebar\"\n className={cn(\n \"flex h-full w-(--sidebar-width) flex-col bg-sidebar text-sidebar-foreground\",\n className\n )}\n {...props}\n >\n {children}\n </div>\n )\n }\n\n if (isMobile) {\n return (\n <Sheet open={openMobile} onOpenChange={setOpenMobile} {...props}>\n <SheetContent\n data-sidebar=\"sidebar\"\n data-slot=\"sidebar\"\n data-mobile=\"true\"\n className=\"top-[var(--sidebar-top-offset,0px)] h-[calc(100svh-var(--sidebar-top-offset,0px))] w-(--sidebar-width) bg-sidebar p-0 text-sidebar-foreground [&>button]:hidden\"\n style={\n {\n \"--sidebar-width\": SIDEBAR_WIDTH_MOBILE,\n } as any\n }\n side={side}\n >\n <SheetHeader className=\"sr-only\">\n <SheetTitle>Sidebar</SheetTitle>\n <SheetDescription>Displays the mobile sidebar.</SheetDescription>\n </SheetHeader>\n <div className=\"flex h-full w-full flex-col\">{children}</div>\n </SheetContent>\n </Sheet>\n )\n }\n\n return (\n <div\n className=\"group peer hidden text-sidebar-foreground md:block\"\n data-state={state}\n data-collapsible={state === \"collapsed\" ? collapsible : \"\"}\n data-variant={variant}\n data-side={side}\n data-slot=\"sidebar\"\n >\n {/* This is what handles the sidebar gap on desktop */}\n <div\n data-slot=\"sidebar-gap\"\n className={cn(\n \"relative w-(--sidebar-width) bg-transparent transition-[width] duration-200 ease-linear\",\n \"group-data-[collapsible=offExamples]:w-0\",\n \"group-data-[side=right]:rotate-180\",\n variant === \"floating\" || variant === \"inset\"\n ? \"group-data-[collapsible=icon]:w-[calc(var(--sidebar-width-icon)+(--spacing(4)))]\"\n : \"group-data-[collapsible=icon]:w-(--sidebar-width-icon)\"\n )}\n />\n <div\n data-slot=\"sidebar-container\"\n className={cn(\n \"fixed top-[var(--sidebar-top-offset,0px)] bottom-0 z-10 hidden h-[calc(100svh-var(--sidebar-top-offset,0px))] w-(--sidebar-width) transition-[left,right,width] duration-200 ease-linear md:flex\",\n side === \"left\"\n ? \"left-0 group-data-[collapsible=offExamples]:left-[calc(var(--sidebar-width)*-1)]\"\n : \"right-0 group-data-[collapsible=offExamples]:right-[calc(var(--sidebar-width)*-1)]\",\n // Adjust the padding for floating and inset variants.\n variant === \"floating\" || variant === \"inset\"\n ? \"p-2 group-data-[collapsible=icon]:w-[calc(var(--sidebar-width-icon)+(--spacing(4))+2px)]\"\n : \"group-data-[collapsible=icon]:w-(--sidebar-width-icon) group-data-[side=left]:border-r group-data-[side=right]:border-l\",\n className\n )}\n {...props}\n >\n <div\n data-sidebar=\"sidebar\"\n data-slot=\"sidebar-inner\"\n className=\"flex size-full flex-col bg-sidebar group-data-[variant=floating]:rounded-lg group-data-[variant=floating]:shadow-sm group-data-[variant=floating]:ring-1 group-data-[variant=floating]:ring-sidebar-border\"\n >\n {children}\n </div>\n </div>\n </div>\n )\n}\n\nfunction SidebarTrigger({\n className,\n onClick,\n ...props\n}: React.ComponentProps<typeof Button>) {\n const { toggleSidebar } = useSidebar()\n\n return (\n <Button\n data-sidebar=\"trigger\"\n data-slot=\"sidebar-trigger\"\n variant=\"ghost\"\n size=\"icon-sm\"\n className={cn(className)}\n onClick={(event) => {\n onClick?.(event)\n toggleSidebar()\n }}\n {...props}\n >\n <HugeiconsIcon icon={SidebarLeftIcon} strokeWidth={2} />\n <span className=\"sr-only\">Toggle Sidebar</span>\n </Button>\n )\n}\n\nfunction SidebarRail({ className, ...props }: React.ComponentProps<\"button\">) {\n const { toggleSidebar } = useSidebar()\n\n return (\n <button\n data-sidebar=\"rail\"\n data-slot=\"sidebar-rail\"\n aria-label=\"Toggle Sidebar\"\n tabIndex={-1}\n onClick={toggleSidebar}\n title=\"Toggle Sidebar\"\n className={cn(\n \"absolute inset-y-0 z-20 hidden w-4 -translate-x-1/2 transition-all ease-linear group-data-[side=left]:-right-4 group-data-[side=right]:left-0 after:absolute after:inset-y-0 after:left-1/2 after:w-[2px] hover:after:bg-sidebar-border sm:flex\",\n \"in-data-[side=left]:cursor-w-resize in-data-[side=right]:cursor-e-resize\",\n \"[[data-side=left][data-state=collapsed]_&]:cursor-e-resize [[data-side=right][data-state=collapsed]_&]:cursor-w-resize\",\n \"group-data-[collapsible=offExamples]:translate-x-0 group-data-[collapsible=offExamples]:after:left-full hover:group-data-[collapsible=offExamples]:bg-sidebar\",\n \"[[data-side=left][data-collapsible=offExamples]_&]:-right-2\",\n \"[[data-side=right][data-collapsible=offExamples]_&]:-left-2\",\n className\n )}\n {...props}\n />\n )\n}\n\nfunction SidebarInset({ className, ...props }: React.ComponentProps<\"main\">) {\n return (\n <main\n data-slot=\"sidebar-inset\"\n className={cn(\n \"relative flex w-full flex-1 flex-col bg-background md:peer-data-[variant=inset]:m-2 md:peer-data-[variant=inset]:ml-0 md:peer-data-[variant=inset]:rounded-xl md:peer-data-[variant=inset]:shadow-sm md:peer-data-[variant=inset]:peer-data-[state=collapsed]:ml-2\",\n className\n )}\n {...props}\n />\n )\n}\n\nfunction SidebarInput({\n className,\n ...props\n}: React.ComponentProps<typeof Input>) {\n return (\n <Input\n data-slot=\"sidebar-input\"\n data-sidebar=\"input\"\n className={cn(\"h-8 w-full bg-background shadow-none\", className)}\n {...props}\n />\n )\n}\n\nfunction SidebarHeader({ className, ...props }: React.ComponentProps<\"div\">) {\n return (\n <div\n data-slot=\"sidebar-header\"\n data-sidebar=\"header\"\n className={cn(\"flex flex-col gap-2 p-2\", className)}\n {...props}\n />\n )\n}\n\nfunction SidebarFooter({ className, ...props }: React.ComponentProps<\"div\">) {\n return (\n <div\n data-slot=\"sidebar-footer\"\n data-sidebar=\"footer\"\n className={cn(\"flex flex-col gap-2 p-2\", className)}\n {...props}\n />\n )\n}\n\nfunction SidebarSeparator({\n className,\n ...props\n}: React.ComponentProps<typeof Separator>) {\n return (\n <Separator\n data-slot=\"sidebar-separator\"\n data-sidebar=\"separator\"\n className={cn(\"mx-2 w-auto bg-sidebar-border\", className)}\n {...props}\n />\n )\n}\n\nfunction SidebarContent({ className, ...props }: React.ComponentProps<\"div\">) {\n return (\n <div\n data-slot=\"sidebar-content\"\n data-sidebar=\"content\"\n className={cn(\n \"no-scrollbar flex min-h-0 flex-1 flex-col gap-2 overflow-auto group-data-[collapsible=icon]:overflow-hidden\",\n className\n )}\n {...props}\n />\n )\n}\n\nfunction SidebarGroup({ className, ...props }: React.ComponentProps<\"div\">) {\n return (\n <div\n data-slot=\"sidebar-group\"\n data-sidebar=\"group\"\n className={cn(\"relative flex w-full min-w-0 flex-col p-2\", className)}\n {...props}\n />\n )\n}\n\nfunction SidebarGroupLabel({\n className,\n render,\n ...props\n}: useRender.ComponentProps<\"div\"> & React.ComponentProps<\"div\">) {\n return useRender({\n defaultTagName: \"div\",\n props: mergeProps<\"div\">(\n {\n className: cn(\n \"flex h-8 shrink-0 items-center rounded-md px-2 text-xs font-medium text-sidebar-foreground/70 ring-sidebar-ring outline-hidden transition-[margin,opacity] duration-200 ease-linear group-data-[collapsible=icon]:-mt-8 group-data-[collapsible=icon]:opacity-0 focus-visible:ring-2 [&>svg]:size-4 [&>svg]:shrink-0\",\n className\n ),\n },\n props\n ),\n render,\n state: {\n slot: \"sidebar-group-label\",\n sidebar: \"group-label\",\n },\n })\n}\n\nfunction SidebarGroupAction({\n className,\n render,\n ...props\n}: useRender.ComponentProps<\"button\"> & React.ComponentProps<\"button\">) {\n return useRender({\n defaultTagName: \"button\",\n props: mergeProps<\"button\">(\n {\n className: cn(\n \"absolute top-3.5 right-3 flex aspect-square w-5 items-center justify-center rounded-md p-0 text-sidebar-foreground ring-sidebar-ring outline-hidden transition-transform group-data-[collapsible=icon]:hidden after:absolute after:-inset-2 hover:bg-sidebar-accent hover:text-sidebar-accent-foreground focus-visible:ring-2 md:after:hidden [&>svg]:size-4 [&>svg]:shrink-0\",\n className\n ),\n },\n props\n ),\n render,\n state: {\n slot: \"sidebar-group-action\",\n sidebar: \"group-action\",\n },\n })\n}\n\nfunction SidebarGroupContent({\n className,\n ...props\n}: React.ComponentProps<\"div\">) {\n return (\n <div\n data-slot=\"sidebar-group-content\"\n data-sidebar=\"group-content\"\n className={cn(\"w-full text-sm\", className)}\n {...props}\n />\n )\n}\n\nfunction SidebarMenu({ className, ...props }: React.ComponentProps<\"ul\">) {\n return (\n <ul\n data-slot=\"sidebar-menu\"\n data-sidebar=\"menu\"\n className={cn(\"flex w-full min-w-0 flex-col gap-1\", className)}\n {...props}\n />\n )\n}\n\nfunction SidebarMenuItem({ className, ...props }: React.ComponentProps<\"li\">) {\n return (\n <li\n data-slot=\"sidebar-menu-item\"\n data-sidebar=\"menu-item\"\n className={cn(\"group/menu-item relative\", className)}\n {...props}\n />\n )\n}\n\nconst sidebarMenuButtonVariants = cva(\n \"peer/menu-button group/menu-button flex w-full items-center gap-2 overflow-hidden rounded-md p-2 text-left text-sm ring-sidebar-ring outline-hidden transition-[width,height,padding] group-has-data-[sidebar=menu-action]/menu-item:pr-8 group-data-[collapsible=icon]:size-8! group-data-[collapsible=icon]:p-2! hover:bg-sidebar-accent hover:text-sidebar-accent-foreground focus-visible:ring-2 active:bg-sidebar-accent active:text-sidebar-accent-foreground disabled:pointer-events-none disabled:opacity-50 aria-disabled:pointer-events-none aria-disabled:opacity-50 data-active:bg-sidebar-accent data-active:font-medium data-active:text-sidebar-accent-foreground data-open:hover:bg-sidebar-accent data-open:hover:text-sidebar-accent-foreground [&_svg]:size-4 [&_svg]:shrink-0 [&>span:last-child]:truncate\",\n {\n variants: {\n variant: {\n default: \"hover:bg-sidebar-accent hover:text-sidebar-accent-foreground\",\n outline:\n \"bg-background shadow-[0_0_0_1px_hsl(var(--sidebar-border))] hover:bg-sidebar-accent hover:text-sidebar-accent-foreground hover:shadow-[0_0_0_1px_hsl(var(--sidebar-accent))]\",\n },\n size: {\n default: \"h-8 text-sm\",\n sm: \"h-7 text-xs\",\n lg: \"h-12 text-sm group-data-[collapsible=icon]:p-0!\",\n },\n },\n defaultVariants: {\n variant: \"default\",\n size: \"default\",\n },\n }\n)\n\nfunction SidebarMenuButton({\n render,\n isActive = false,\n variant = \"default\",\n size = \"default\",\n tooltip,\n className,\n ...props\n}: useRender.ComponentProps<\"button\"> &\n React.ComponentProps<\"button\"> & {\n isActive?: boolean\n tooltip?: string | React.ComponentProps<typeof TooltipContent>\n } & VariantProps<typeof sidebarMenuButtonVariants>) {\n const { isMobile, state } = useSidebar()\n const comp = useRender({\n defaultTagName: \"button\",\n props: mergeProps<\"button\">(\n {\n className: cn(sidebarMenuButtonVariants({ variant, size }), className),\n },\n props\n ),\n render: (!tooltip ? render : TooltipTrigger) as any,\n state: {\n slot: \"sidebar-menu-button\",\n sidebar: \"menu-button\",\n size,\n active: isActive,\n },\n })\n\n if (!tooltip) {\n return comp\n }\n\n if (typeof tooltip === \"string\") {\n tooltip = {\n children: tooltip,\n }\n }\n\n return (\n <Tooltip>\n {comp}\n <TooltipContent\n side=\"right\"\n align=\"center\"\n hidden={state !== \"collapsed\" || isMobile}\n {...tooltip}\n />\n </Tooltip>\n )\n}\n\nfunction SidebarMenuAction({\n className,\n render,\n showOnHover = false,\n ...props\n}: useRender.ComponentProps<\"button\"> &\n React.ComponentProps<\"button\"> & {\n showOnHover?: boolean\n }) {\n return useRender({\n defaultTagName: \"button\",\n props: mergeProps<\"button\">(\n {\n className: cn(\n \"absolute top-1.5 right-1 flex aspect-square w-5 items-center justify-center rounded-md p-0 text-sidebar-foreground ring-sidebar-ring outline-hidden transition-transform group-data-[collapsible=icon]:hidden peer-hover/menu-button:text-sidebar-accent-foreground peer-data-[size=default]/menu-button:top-1.5 peer-data-[size=lg]/menu-button:top-2.5 peer-data-[size=sm]/menu-button:top-1 after:absolute after:-inset-2 hover:bg-sidebar-accent hover:text-sidebar-accent-foreground focus-visible:ring-2 md:after:hidden [&>svg]:size-4 [&>svg]:shrink-0\",\n showOnHover &&\n \"group-focus-within/menu-item:opacity-100 group-hover/menu-item:opacity-100 peer-data-active/menu-button:text-sidebar-accent-foreground data-open:opacity-100 md:opacity-0\",\n className\n ),\n },\n props\n ),\n render,\n state: {\n slot: \"sidebar-menu-action\",\n sidebar: \"menu-action\",\n },\n })\n}\n\nfunction SidebarMenuBadge({\n className,\n ...props\n}: React.ComponentProps<\"div\">) {\n return (\n <div\n data-slot=\"sidebar-menu-badge\"\n data-sidebar=\"menu-badge\"\n className={cn(\n \"pointer-events-none absolute right-1 flex h-5 min-w-5 items-center justify-center rounded-md px-1 text-xs font-medium text-sidebar-foreground tabular-nums select-none group-data-[collapsible=icon]:hidden peer-hover/menu-button:text-sidebar-accent-foreground peer-data-active/menu-button:text-sidebar-accent-foreground peer-data-[size=default]/menu-button:top-1.5 peer-data-[size=lg]/menu-button:top-2.5 peer-data-[size=sm]/menu-button:top-1\",\n className\n )}\n {...props}\n />\n )\n}\n\nfunction SidebarMenuSkeleton({\n className,\n showIcon = false,\n ...props\n}: React.ComponentProps<\"div\"> & {\n showIcon?: boolean\n}) {\n // Random width between 50 to 90%.\n const [width] = React.useState(() => {\n return `${Math.floor(Math.random() * 40) + 50}%`\n })\n\n return (\n <div\n data-slot=\"sidebar-menu-skeleton\"\n data-sidebar=\"menu-skeleton\"\n className={cn(\"flex h-8 items-center gap-2 rounded-md px-2\", className)}\n {...props}\n >\n {showIcon && (\n <Skeleton\n className=\"size-4 rounded-md\"\n data-sidebar=\"menu-skeleton-icon\"\n />\n )}\n <Skeleton\n className=\"h-4 max-w-(--skeleton-width) flex-1\"\n data-sidebar=\"menu-skeleton-text\"\n style={\n {\n \"--skeleton-width\": width,\n } as any\n }\n />\n </div>\n )\n}\n\nfunction SidebarMenuSub({ className, ...props }: React.ComponentProps<\"ul\">) {\n return (\n <ul\n data-slot=\"sidebar-menu-sub\"\n data-sidebar=\"menu-sub\"\n className={cn(\n \"mx-3.5 flex min-w-0 translate-x-px flex-col gap-1 border-l border-sidebar-border px-2.5 py-0.5 group-data-[collapsible=icon]:hidden\",\n className\n )}\n {...props}\n />\n )\n}\n\nfunction SidebarMenuSubItem({\n className,\n ...props\n}: React.ComponentProps<\"li\">) {\n return (\n <li\n data-slot=\"sidebar-menu-sub-item\"\n data-sidebar=\"menu-sub-item\"\n className={cn(\"group/menu-sub-item relative\", className)}\n {...props}\n />\n )\n}\n\nfunction SidebarMenuSubButton({\n render,\n size = \"md\",\n isActive = false,\n className,\n ...props\n}: useRender.ComponentProps<\"a\"> &\n React.ComponentProps<\"a\"> & {\n size?: \"sm\" | \"md\"\n isActive?: boolean\n }) {\n return useRender({\n defaultTagName: \"a\",\n props: mergeProps<\"a\">(\n {\n className: cn(\n \"flex h-7 min-w-0 -translate-x-px items-center gap-2 overflow-hidden rounded-md px-2 text-sidebar-foreground ring-sidebar-ring outline-hidden group-data-[collapsible=icon]:hidden hover:bg-sidebar-accent hover:text-sidebar-accent-foreground focus-visible:ring-2 active:bg-sidebar-accent active:text-sidebar-accent-foreground disabled:pointer-events-none disabled:opacity-50 aria-disabled:pointer-events-none aria-disabled:opacity-50 data-active:bg-sidebar-accent data-active:text-sidebar-accent-foreground data-[size=md]:text-sm data-[size=sm]:text-xs [&>span:last-child]:truncate [&>svg]:size-4 [&>svg]:shrink-0 [&>svg]:text-sidebar-accent-foreground\",\n className\n ),\n },\n props\n ),\n render,\n state: {\n slot: \"sidebar-menu-sub-button\",\n sidebar: \"menu-sub-button\",\n size,\n active: isActive,\n },\n })\n}\n\nexport {\n Sidebar,\n SidebarContent,\n SidebarFooter,\n SidebarGroup,\n SidebarGroupAction,\n SidebarGroupContent,\n SidebarGroupLabel,\n SidebarHeader,\n SidebarInput,\n SidebarInset,\n SidebarMenu,\n SidebarMenuAction,\n SidebarMenuBadge,\n SidebarMenuButton,\n SidebarMenuItem,\n SidebarMenuSkeleton,\n SidebarMenuSub,\n SidebarMenuSubButton,\n SidebarMenuSubItem,\n SidebarProvider,\n SidebarRail,\n SidebarSeparator,\n SidebarTrigger,\n useSidebar,\n}\n"
97
+ },
98
+ {
99
+ "path": "registry/example-apps/default/files/hooks/use-mobile.ts",
100
+ "type": "registry:hook",
101
+ "target": "components/example-apps/files/hooks/use-mobile.ts",
102
+ "content": "import * as React from \"react\"\n\nconst MOBILE_BREAKPOINT = 768\n\nexport function useIsMobile() {\n const [isMobile, setIsMobile] = React.useState<boolean | undefined>(undefined)\n\n React.useEffect(() => {\n const mql = window.matchMedia(`(max-width: ${MOBILE_BREAKPOINT - 1}px)`)\n const onChange = () => {\n setIsMobile(window.innerWidth < MOBILE_BREAKPOINT)\n }\n mql.addEventListener(\"change\", onChange)\n setIsMobile(window.innerWidth < MOBILE_BREAKPOINT)\n return () => mql.removeEventListener(\"change\", onChange)\n }, [])\n\n return !!isMobile\n}\n"
103
+ },
104
+ {
105
+ "path": "registry/example-apps/default/files/index.tsx",
106
+ "type": "registry:file",
107
+ "target": "components/example-apps/files/index.tsx",
108
+ "content": "/**\n * Wrapper export for embedding the app in the docs app\n */\n\"use client\"\n\nimport { SidebarProvider } from \"@/components/ui/sidebar\"\n\nimport { FilesContent } from \"./components/files/content\"\nimport { FilesHeader } from \"./components/files/header\"\nimport { FilesSidebar } from \"./components/files/sidebar\"\n\nexport default function FilesWrapper() {\n return (\n <SidebarProvider className=\"bg-sidebar\">\n <FilesSidebar />\n <div className=\"h-full min-h-0 w-full overflow-hidden lg:p-2\">\n <div className=\"flex h-full min-h-0 w-full flex-col items-center justify-start overflow-hidden bg-background lg:rounded-xl lg:border\">\n <FilesHeader />\n <FilesContent view=\"all\" />\n </div>\n </div>\n </SidebarProvider>\n )\n}\n"
109
+ },
110
+ {
111
+ "path": "registry/example-apps/default/files/lib/utils.ts",
112
+ "type": "registry:lib",
113
+ "target": "components/example-apps/files/lib/utils.ts",
114
+ "content": "import { clsx, type ClassValue } from \"clsx\"\nimport { twMerge } from \"tailwind-merge\"\n\nexport function cn(...inputs: ClassValue[]) {\n return twMerge(clsx(inputs))\n}\n"
115
+ },
116
+ {
117
+ "path": "registry/example-apps/default/files/mock-data/files.ts",
118
+ "type": "registry:lib",
119
+ "target": "components/example-apps/files/mock-data/files.ts",
120
+ "content": "export type FileType =\n | \"image\"\n | \"video\"\n | \"document\"\n | \"archive\"\n | \"audio\"\n | \"code\"\n | \"other\"\n\nexport interface FileItem {\n id: string\n name: string\n type: FileType\n size: string\n sizeBytes: number\n modifiedAt: string\n createdAt: string\n starred: boolean\n shared: boolean\n folderId: string | null\n}\n\nexport interface Folder {\n id: string\n name: string\n color: string\n filesCount: number\n size: string\n parentId: string | null\n}\n\nexport const folders: Folder[] = [\n {\n id: \"1\",\n name: \"Raw Footage\",\n color: \"#8B5CF6\",\n filesCount: 32,\n size: \"5.8 GB\",\n parentId: null,\n },\n {\n id: \"2\",\n name: \"Field Audio\",\n color: \"#06B6D4\",\n filesCount: 18,\n size: \"1.9 GB\",\n parentId: null,\n },\n {\n id: \"3\",\n name: \"Research Docs\",\n color: \"#F59E0B\",\n filesCount: 27,\n size: \"410 MB\",\n parentId: null,\n },\n {\n id: \"4\",\n name: \"Edit Projects\",\n color: \"#EC4899\",\n filesCount: 21,\n size: \"3.2 GB\",\n parentId: null,\n },\n {\n id: \"5\",\n name: \"Deliverables\",\n color: \"#10B981\",\n filesCount: 9,\n size: \"1.3 GB\",\n parentId: null,\n },\n]\n\nexport const files: FileItem[] = [\n {\n id: \"f1\",\n name: \"Kenya_Savannah_Day03_Acam_4K.mov\",\n type: \"video\",\n size: \"1.4 GB\",\n sizeBytes: 1503238553,\n modifiedAt: \"20 min ago\",\n createdAt: \"Jan 12, 2026\",\n starred: true,\n shared: true,\n folderId: \"1\",\n },\n {\n id: \"f2\",\n name: \"Night_Vision_Hyena_CutB.mp4\",\n type: \"video\",\n size: \"842 MB\",\n sizeBytes: 882900000,\n modifiedAt: \"2 hours ago\",\n createdAt: \"Jan 11, 2026\",\n starred: false,\n shared: true,\n folderId: \"1\",\n },\n {\n id: \"f3\",\n name: \"Camp_Ambience_Master.wav\",\n type: \"audio\",\n size: \"188 MB\",\n sizeBytes: 197132288,\n modifiedAt: \"1 hour ago\",\n createdAt: \"Jan 10, 2026\",\n starred: true,\n shared: false,\n folderId: \"2\",\n },\n {\n id: \"f4\",\n name: \"Narration_Pass_V3.wav\",\n type: \"audio\",\n size: \"96 MB\",\n sizeBytes: 100663296,\n modifiedAt: \"Yesterday\",\n createdAt: \"Jan 9, 2026\",\n starred: false,\n shared: true,\n folderId: \"2\",\n },\n {\n id: \"f5\",\n name: \"Species_Timeline_Outline.docx\",\n type: \"document\",\n size: \"2.1 MB\",\n sizeBytes: 2202009,\n modifiedAt: \"3 hours ago\",\n createdAt: \"Jan 8, 2026\",\n starred: true,\n shared: true,\n folderId: \"3\",\n },\n {\n id: \"f6\",\n name: \"Permit_Log_Q1_2026.xlsx\",\n type: \"document\",\n size: \"640 KB\",\n sizeBytes: 655360,\n modifiedAt: \"Yesterday\",\n createdAt: \"Jan 6, 2026\",\n starred: false,\n shared: false,\n folderId: \"3\",\n },\n {\n id: \"f7\",\n name: \"Episode02_Edit_v14.prproj\",\n type: \"code\",\n size: \"75 MB\",\n sizeBytes: 78643200,\n modifiedAt: \"30 min ago\",\n createdAt: \"Jan 14, 2026\",\n starred: true,\n shared: false,\n folderId: \"4\",\n },\n {\n id: \"f8\",\n name: \"LowerThirds_StyleGuide.fig\",\n type: \"image\",\n size: \"18 MB\",\n sizeBytes: 18874368,\n modifiedAt: \"4 hours ago\",\n createdAt: \"Jan 5, 2026\",\n starred: false,\n shared: true,\n folderId: \"4\",\n },\n {\n id: \"f9\",\n name: \"Episode02_Master_ProRes.mov\",\n type: \"video\",\n size: \"2.0 GB\",\n sizeBytes: 2147483648,\n modifiedAt: \"2 days ago\",\n createdAt: \"Jan 4, 2026\",\n starred: true,\n shared: false,\n folderId: \"5\",\n },\n {\n id: \"f10\",\n name: \"Festival_Submission_Package.zip\",\n type: \"archive\",\n size: \"426 MB\",\n sizeBytes: 446693376,\n modifiedAt: \"2 days ago\",\n createdAt: \"Jan 3, 2026\",\n starred: true,\n shared: true,\n folderId: \"5\",\n },\n {\n id: \"f11\",\n name: \"Map_Overlays_SetA.png\",\n type: \"image\",\n size: \"14 MB\",\n sizeBytes: 14680064,\n modifiedAt: \"5 hours ago\",\n createdAt: \"Jan 2, 2026\",\n starred: false,\n shared: true,\n folderId: \"4\",\n },\n {\n id: \"f12\",\n name: \"Drone_Path_Metadata.json\",\n type: \"code\",\n size: \"340 KB\",\n sizeBytes: 348160,\n modifiedAt: \"6 hours ago\",\n createdAt: \"Jan 13, 2026\",\n starred: false,\n shared: false,\n folderId: \"3\",\n },\n {\n id: \"f13\",\n name: \"Lion_Pride_Closeup_FrameGrab.jpg\",\n type: \"image\",\n size: \"9.8 MB\",\n sizeBytes: 10276044,\n modifiedAt: \"1 day ago\",\n createdAt: \"Jan 1, 2026\",\n starred: true,\n shared: true,\n folderId: \"1\",\n },\n {\n id: \"f14\",\n name: \"Interview_Transcript_DrSafi.pdf\",\n type: \"document\",\n size: \"3.4 MB\",\n sizeBytes: 3565158,\n modifiedAt: \"3 days ago\",\n createdAt: \"Dec 30, 2025\",\n starred: false,\n shared: true,\n folderId: \"3\",\n },\n {\n id: \"f15\",\n name: \"Color_Grade_LUTs.cube\",\n type: \"other\",\n size: \"12 KB\",\n sizeBytes: 12288,\n modifiedAt: \"2 hours ago\",\n createdAt: \"Dec 29, 2025\",\n starred: false,\n shared: false,\n folderId: \"4\",\n },\n {\n id: \"f16\",\n name: \"Episode03_RoughAssembly_v05.prproj\",\n type: \"code\",\n size: \"62 MB\",\n sizeBytes: 65011712,\n modifiedAt: \"8 hours ago\",\n createdAt: \"Dec 28, 2025\",\n starred: false,\n shared: false,\n folderId: \"4\",\n },\n {\n id: \"f17\",\n name: \"Backup_FieldCards_Week2.7z\",\n type: \"archive\",\n size: \"970 MB\",\n sizeBytes: 1017118720,\n modifiedAt: \"4 days ago\",\n createdAt: \"Dec 27, 2025\",\n starred: false,\n shared: false,\n folderId: \"5\",\n },\n {\n id: \"f18\",\n name: \"WindNoise_Reduction_Profile.xml\",\n type: \"code\",\n size: \"86 KB\",\n sizeBytes: 88064,\n modifiedAt: \"Yesterday\",\n createdAt: \"Dec 26, 2025\",\n starred: true,\n shared: false,\n folderId: \"2\",\n },\n {\n id: \"f19\",\n name: \"Narrative_BeatBoard.pdf\",\n type: \"document\",\n size: \"1.8 MB\",\n sizeBytes: 1887436,\n modifiedAt: \"5 days ago\",\n createdAt: \"Dec 24, 2025\",\n starred: true,\n shared: true,\n folderId: \"3\",\n },\n {\n id: \"f20\",\n name: \"Streaming_Delivery_H264.mp4\",\n type: \"video\",\n size: \"612 MB\",\n sizeBytes: 641728512,\n modifiedAt: \"1 week ago\",\n createdAt: \"Dec 22, 2025\",\n starred: false,\n shared: true,\n folderId: \"5\",\n },\n]\n\nexport const storageData = {\n used: 12.6,\n total: 20,\n breakdown: [\n { type: \"Images\", size: 1.9, color: \"#8B5CF6\" },\n { type: \"Videos\", size: 7.2, color: \"#EC4899\" },\n { type: \"Documents\", size: 1.3, color: \"#F59E0B\" },\n { type: \"Archives\", size: 1.5, color: \"#10B981\" },\n { type: \"Other\", size: 0.7, color: \"#6B7280\" },\n ],\n}\n"
121
+ },
122
+ {
123
+ "path": "registry/example-apps/default/files/store/files-store.ts",
124
+ "type": "registry:lib",
125
+ "target": "components/example-apps/files/store/files-store.ts",
126
+ "content": "import { create } from \"zustand\"\n\nimport {\n FileItem,\n Folder,\n files as initialFiles,\n folders as initialFolders,\n} from \"../mock-data/files\"\n\ntype ViewMode = \"grid\" | \"list\"\n\ninterface FilesStore {\n files: FileItem[]\n folders: Folder[]\n searchQuery: string\n viewMode: ViewMode\n setSearchQuery: (query: string) => void\n setViewMode: (mode: ViewMode) => void\n toggleStarred: (fileId: string) => void\n getFilteredFiles: () => FileItem[]\n getStarredFiles: () => FileItem[]\n getRecentFiles: () => FileItem[]\n getSharedFiles: () => FileItem[]\n getFilesByFolder: (folderId: string) => FileItem[]\n}\n\nexport const useFilesStore = create<FilesStore>((set, get) => ({\n files: initialFiles,\n folders: initialFolders,\n searchQuery: \"\",\n viewMode: \"list\",\n\n setSearchQuery: (query) => set({ searchQuery: query }),\n\n setViewMode: (mode) => set({ viewMode: mode }),\n\n toggleStarred: (fileId) =>\n set((state) => ({\n files: state.files.map((file) =>\n file.id === fileId ? { ...file, starred: !file.starred } : file\n ),\n })),\n\n getFilteredFiles: () => {\n const { files, searchQuery } = get()\n let filtered = files\n\n if (searchQuery) {\n const query = searchQuery.toLowerCase()\n filtered = filtered.filter((file) =>\n file.name.toLowerCase().includes(query)\n )\n }\n\n return filtered\n },\n\n getStarredFiles: () => {\n const { files } = get()\n return files.filter((file) => file.starred)\n },\n\n getRecentFiles: () => {\n const { files } = get()\n return files.slice(0, 5)\n },\n\n getSharedFiles: () => {\n const { files } = get()\n return files.filter((file) => file.shared)\n },\n\n getFilesByFolder: (folderId: string) => {\n const { files } = get()\n return files.filter((file) => file.folderId === folderId)\n },\n}))\n"
127
+ }
128
+ ],
129
+ "categories": [
130
+ "example-app",
131
+ "productivity",
132
+ "assets",
133
+ "documentary",
134
+ "storage",
135
+ "collections"
136
+ ],
137
+ "dependencies": [
138
+ "@base-ui/react",
139
+ "@hugeicons/core-free-icons",
140
+ "@hugeicons/react",
141
+ "class-variance-authority",
142
+ "clsx",
143
+ "next-themes",
144
+ "tailwind-merge",
145
+ "zustand"
146
+ ],
147
+ "registryDependencies": [
148
+ "https://www.loveui.dev/r/avatar.json",
149
+ "https://www.loveui.dev/r/button.json",
150
+ "https://www.loveui.dev/r/collapsible.json",
151
+ "https://www.loveui.dev/r/input.json",
152
+ "https://www.loveui.dev/r/menu.json",
153
+ "https://www.loveui.dev/r/progress.json",
154
+ "https://www.loveui.dev/r/separator.json",
155
+ "https://www.loveui.dev/r/sheet.json",
156
+ "https://www.loveui.dev/r/skeleton.json",
157
+ "https://www.loveui.dev/r/tooltip.json"
158
+ ],
159
+ "meta": {
160
+ "source": "example-app",
161
+ "appName": "files",
162
+ "routes": [
163
+ {
164
+ "path": "/",
165
+ "title": "All Assets",
166
+ "description": "Main production asset explorer"
167
+ },
168
+ {
169
+ "path": "/recent",
170
+ "title": "Latest",
171
+ "description": "Recently accessed assets"
172
+ },
173
+ {
174
+ "path": "/shared",
175
+ "title": "Shared",
176
+ "description": "Shared assets and collections"
177
+ },
178
+ {
179
+ "path": "/starred",
180
+ "title": "Pinned",
181
+ "description": "Pinned assets"
182
+ },
183
+ {
184
+ "path": "/trash",
185
+ "title": "Archive Bin",
186
+ "description": "Removed assets"
187
+ },
188
+ {
189
+ "path": "/folder/[id]",
190
+ "title": "Collection",
191
+ "description": "Dynamic collection view"
192
+ }
193
+ ]
194
+ }
195
+ }
@@ -10,7 +10,7 @@
10
10
  "files": [
11
11
  {
12
12
  "path": "registry/default/examples/form-demo.tsx",
13
- "content": "\"use client\"\n\nimport * as React from \"react\"\n\nimport { Button } from \"@/registry/default/ui/button\"\nimport {\n Field,\n FieldControl,\n FieldError,\n FieldLabel,\n} from \"@/registry/default/ui/field\"\nimport { Form } from \"@/registry/default/ui/form\"\n\nexport default function FormDemo() {\n const [loading, setLoading] = React.useState(false)\n const onSubmit = async (e: React.FormEvent<HTMLFormElement>) => {\n e.preventDefault()\n const formData = new FormData(e.currentTarget)\n setLoading(true)\n await new Promise((r) => setTimeout(r, 800))\n setLoading(false)\n alert(`Email: ${formData.get(\"email\") || \"\"}`)\n }\n\n return (\n <Form onSubmit={onSubmit} className=\"max-w-64\">\n <Field>\n <FieldLabel>Email</FieldLabel>\n <FieldControl\n name=\"email\"\n type=\"email\"\n placeholder=\"you@example.com\"\n disabled={loading}\n required\n />\n <FieldError>Please enter a valid email.</FieldError>\n </Field>\n <Button type=\"submit\" disabled={loading}>\n Submit\n </Button>\n </Form>\n )\n}\n",
13
+ "content": "\"use client\"\n\nimport * as React from \"react\"\n\nimport { Button } from \"@/registry/default/ui/button\"\nimport {\n Field,\n FieldControl,\n FieldError,\n FieldLabel,\n} from \"@/registry/default/ui/field\"\nimport { Form } from \"@/registry/default/ui/form\"\n\nexport default function FormDemo() {\n const [loading, setLoading] = React.useState(false)\n const onSubmit = async (e: React.FormEvent<HTMLFormElement>) => {\n e.preventDefault()\n const formData = new FormData(e.currentTarget)\n setLoading(true)\n await new Promise((r) => setTimeout(r, 800))\n setLoading(false)\n alert(`Email: ${formData.get(\"email\") || \"\"}`)\n }\n\n return (\n <Form onSubmit={onSubmit} className=\"max-w-64\">\n <Field>\n <FieldLabel>Updated Email</FieldLabel>\n <FieldControl\n name=\"email\"\n type=\"email\"\n placeholder=\"you@example.com\"\n disabled={loading}\n required\n />\n <FieldError>Updated Please enter a valid email.</FieldError>\n </Field>\n <Button type=\"submit\" disabled={loading}>\n Updated Submit\n </Button>\n </Form>\n )\n}\n",
14
14
  "type": "registry:example"
15
15
  }
16
16
  ],
@@ -13,7 +13,7 @@
13
13
  "files": [
14
14
  {
15
15
  "path": "registry/default/examples/form-zod.tsx",
16
- "content": "\"use client\"\n\nimport * as React from \"react\"\nimport { z } from \"zod\"\n\nimport { Button } from \"@/registry/default/ui/button\"\nimport {\n Field,\n FieldControl,\n FieldError,\n FieldLabel,\n} from \"@/registry/default/ui/field\"\nimport { Form } from \"@/registry/default/ui/form\"\n\nconst schema = z.object({\n name: z.string().min(1, { message: \"Please enter a name.\" }),\n age: z.coerce\n .number({ message: \"Please enter a number.\" })\n .positive({ message: \"Number must be positive.\" }),\n})\n\ntype Errors = Record<string, string | string[]>\n\nasync function submitForm(event: React.FormEvent<HTMLFormElement>) {\n event.preventDefault()\n\n const formData = new FormData(event.currentTarget)\n const result = schema.safeParse(Object.fromEntries(formData as any))\n\n if (!result.success) {\n const { fieldErrors } = z.flattenError(result.error)\n return { errors: fieldErrors as Errors }\n }\n\n return {\n errors: {} as Errors,\n }\n}\n\nexport default function FormZodDemo() {\n const [loading, setLoading] = React.useState(false)\n const [errors, setErrors] = React.useState<Errors>({})\n const handleClearErrors = (next: Errors) => setErrors(next)\n\n const onSubmit = async (event: React.FormEvent<HTMLFormElement>) => {\n const formEl = event.currentTarget\n setLoading(true)\n const response = await submitForm(event)\n await new Promise((r) => setTimeout(r, 800))\n setErrors(response.errors)\n setLoading(false)\n if (Object.keys(response.errors).length === 0) {\n const formData = new FormData(formEl)\n alert(\n `Name: ${String(formData.get(\"name\") || \"\")}\\nAge: ${String(\n formData.get(\"age\") || \"\"\n )}`\n )\n }\n }\n\n return (\n <Form\n className=\"max-w-64\"\n errors={errors}\n onClearErrors={handleClearErrors}\n onSubmit={onSubmit}\n >\n <Field name=\"name\">\n <FieldLabel>Name</FieldLabel>\n <FieldControl placeholder=\"Enter name\" disabled={loading} />\n <FieldError />\n </Field>\n <Field name=\"age\">\n <FieldLabel>Age</FieldLabel>\n <FieldControl placeholder=\"Enter age\" disabled={loading} />\n <FieldError />\n </Field>\n <Button type=\"submit\" disabled={loading}>\n Submit\n </Button>\n </Form>\n )\n}\n",
16
+ "content": "\"use client\"\n\nimport * as React from \"react\"\nimport { z } from \"zod\"\n\nimport { Button } from \"@/registry/default/ui/button\"\nimport {\n Field,\n FieldControl,\n FieldError,\n FieldLabel,\n} from \"@/registry/default/ui/field\"\nimport { Form } from \"@/registry/default/ui/form\"\n\nconst schema = z.object({\n name: z.string().min(1, { message: \"Updated Please enter a name.\" }),\n age: z.coerce\n .number({ message: \"Updated Please enter a number.\" })\n .positive({ message: \"Updated Number must be positive.\" }),\n})\n\ntype Errors = Record<string, string | string[]>\n\nasync function submitForm(event: React.FormEvent<HTMLFormElement>) {\n event.preventDefault()\n\n const formData = new FormData(event.currentTarget)\n const result = schema.safeParse(Object.fromEntries(formData as any))\n\n if (!result.success) {\n const { fieldErrors } = z.flattenError(result.error)\n return { errors: fieldErrors as Errors }\n }\n\n return {\n errors: {} as Errors,\n }\n}\n\nexport default function FormZodDemo() {\n const [loading, setLoading] = React.useState(false)\n const [errors, setErrors] = React.useState<Errors>({})\n const handleClearErrors = (next: Errors) => setErrors(next)\n\n const onSubmit = async (event: React.FormEvent<HTMLFormElement>) => {\n const formEl = event.currentTarget\n setLoading(true)\n const response = await submitForm(event)\n await new Promise((r) => setTimeout(r, 800))\n setErrors(response.errors)\n setLoading(false)\n if (Object.keys(response.errors).length === 0) {\n const formData = new FormData(formEl)\n alert(\n `Name: ${String(formData.get(\"name\") || \"\")}\\nAge: ${String(\n formData.get(\"age\") || \"\"\n )}`\n )\n }\n }\n\n return (\n <Form\n className=\"max-w-64\"\n errors={errors}\n onClearErrors={handleClearErrors}\n onSubmit={onSubmit}\n >\n <Field name=\"name\">\n <FieldLabel>Updated Name</FieldLabel>\n <FieldControl placeholder=\"Updated Enter name\" disabled={loading} />\n <FieldError />\n </Field>\n <Field name=\"age\">\n <FieldLabel>Updated Age</FieldLabel>\n <FieldControl placeholder=\"Updated Enter age\" disabled={loading} />\n <FieldError />\n </Field>\n <Button type=\"submit\" disabled={loading}>\n Updated Submit\n </Button>\n </Form>\n )\n}\n",
17
17
  "type": "registry:example"
18
18
  }
19
19
  ],
@@ -8,7 +8,7 @@
8
8
  "files": [
9
9
  {
10
10
  "path": "registry/default/examples/form.tsx",
11
- "content": "\"use client\"\n\nimport { useState, type FormEventHandler } from \"react\"\nimport {\n CalendarIcon,\n ImageIcon,\n InfoIcon,\n MapPinIcon,\n TagIcon,\n UsersIcon,\n} from \"lucide-react\"\nimport { toast } from \"sonner\"\n\nimport {\n Choicebox,\n ChoiceboxIndicator,\n ChoiceboxItem,\n ChoiceboxItemDescription,\n ChoiceboxItemHeader,\n ChoiceboxItemTitle,\n} from \"../../../../../packages/choicebox\"\nimport {\n Combobox,\n ComboboxContent,\n ComboboxEmpty,\n ComboboxGroup,\n ComboboxInput,\n ComboboxItem,\n ComboboxList,\n ComboboxTrigger,\n} from \"../../../../../packages/combobox\"\nimport {\n Dropzone,\n DropzoneContent,\n DropzoneEmptyState,\n} from \"../../../../../packages/dropzone\"\nimport {\n MiniCalendar,\n MiniCalendarDay,\n MiniCalendarDays,\n MiniCalendarNavigation,\n} from \"../../../../../packages/mini-calendar\"\nimport {\n Tags,\n TagsContent,\n TagsEmpty,\n TagsGroup,\n TagsInput,\n TagsItem,\n TagsList,\n TagsTrigger,\n TagsValue,\n} from \"../../../../../packages/tags\"\nimport { Button } from \"../../../../../packages/ui/src/ui/button\"\nimport { Input } from \"../../../../../packages/ui/src/ui/input\"\nimport { Label } from \"../../../../../packages/ui/src/ui/label\"\nimport { Textarea } from \"../../../../../packages/ui/src/ui/textarea\"\n\nconst eventTypes = [\n {\n value: \"conference\",\n label: \"Conference\",\n description: \"Professional gathering with speakers and networking\",\n },\n {\n value: \"workshop\",\n label: \"Workshop\",\n description: \"Hands-on learning experience with practical activities\",\n },\n {\n value: \"meetup\",\n label: \"Meetup\",\n description: \"Casual gathering for like-minded individuals\",\n },\n {\n value: \"webinar\",\n label: \"Webinar\",\n description: \"Online presentation or seminar via video conference\",\n },\n]\n\nconst venues = [\n { value: \"convention-center\", label: \"Downtown Convention Center\" },\n { value: \"hotel-ballroom\", label: \"Grand Hotel Ballroom\" },\n { value: \"university-hall\", label: \"University Main Hall\" },\n { value: \"co-working-space\", label: \"Tech Hub Co-working Space\" },\n { value: \"online\", label: \"Online/Virtual\" },\n]\n\nconst availableTags = [\n \"Technology\",\n \"Business\",\n \"Marketing\",\n \"Design\",\n \"Development\",\n \"AI/ML\",\n \"Startup\",\n \"Networking\",\n \"Education\",\n \"Innovation\",\n \"Remote Work\",\n \"Leadership\",\n]\n\nconst Example = () => {\n const [eventType, setEventType] = useState(\"\")\n const [venue, setVenue] = useState(\"\")\n const [selectedDate, setSelectedDate] = useState<Date | undefined>()\n const [files, setFiles] = useState<File[]>([])\n const [selectedTags, setSelectedTags] = useState<string[]>([])\n\n const handleTagSelect = (tag: string) => {\n if (!selectedTags.includes(tag)) {\n setSelectedTags([...selectedTags, tag])\n }\n }\n\n const handleTagRemove = (tagToRemove: string) => {\n setSelectedTags(selectedTags.filter((tag) => tag !== tagToRemove))\n }\n\n const handleSubmit: FormEventHandler<HTMLFormElement> = (event) => {\n event.preventDefault()\n\n toast.success(\"Event created successfully\", {\n description: `${eventType} event created for ${selectedDate?.toLocaleDateString()} at ${venue}`,\n })\n }\n\n return (\n <div className=\"not-prose mx-auto max-w-[530px] p-8\">\n <div className=\"mb-8 text-center\">\n <h1 className=\"mb-2 text-3xl font-semibold tracking-tight\">\n Create Your Event\n </h1>\n <p className=\"text-balance text-muted-foreground\">\n Fill out the form below to create and customize your upcoming event\n </p>\n </div>\n\n <form className=\"space-y-8\" onSubmit={handleSubmit}>\n {/* Basic Information */}\n <div className=\"space-y-4\">\n <h2 className=\"flex items-center gap-2 text-xl font-semibold\">\n <InfoIcon className=\"size-5\" />\n Basic Information\n </h2>\n <div className=\"grid gap-4 md:grid-cols-2\">\n <div className=\"space-y-2\">\n <Label htmlFor=\"event-name\">Event Name</Label>\n <Input\n id=\"event-name\"\n placeholder=\"Enter your event name\"\n required\n />\n </div>\n <div className=\"space-y-2\">\n <Label htmlFor=\"organizer\">Organizer</Label>\n <Input\n id=\"organizer\"\n placeholder=\"Your name or organization\"\n required\n />\n </div>\n </div>\n <div className=\"space-y-2\">\n <Label htmlFor=\"description\">Description</Label>\n <Textarea\n id=\"description\"\n placeholder=\"Describe your event in detail...\"\n rows={3}\n />\n </div>\n </div>\n\n {/* Event Type Selection */}\n <div className=\"space-y-4\">\n <h2 className=\"flex items-center gap-2 text-xl font-semibold\">\n <UsersIcon className=\"size-5\" />\n Event Type\n </h2>\n <Choicebox onValueChange={setEventType} value={eventType}>\n {eventTypes.map((type) => (\n <ChoiceboxItem key={type.value} value={type.value}>\n <ChoiceboxItemHeader>\n <ChoiceboxItemTitle>{type.label}</ChoiceboxItemTitle>\n <ChoiceboxItemDescription>\n {type.description}\n </ChoiceboxItemDescription>\n </ChoiceboxItemHeader>\n <ChoiceboxIndicator />\n </ChoiceboxItem>\n ))}\n </Choicebox>\n </div>\n\n {/* Venue Selection */}\n <div className=\"space-y-4\">\n <h2 className=\"flex items-center gap-2 text-xl font-semibold\">\n <MapPinIcon className=\"size-5\" />\n Venue\n </h2>\n <Combobox\n data={venues}\n onValueChange={setVenue}\n type=\"venue\"\n value={venue}\n >\n <ComboboxTrigger className=\"w-full\" />\n <ComboboxContent>\n <ComboboxInput />\n <ComboboxList>\n <ComboboxEmpty />\n <ComboboxGroup>\n {venues.map((venue) => (\n <ComboboxItem key={venue.value} value={venue.value}>\n {venue.label}\n </ComboboxItem>\n ))}\n </ComboboxGroup>\n </ComboboxList>\n </ComboboxContent>\n </Combobox>\n </div>\n\n {/* Date Selection */}\n <div className=\"space-y-4\">\n <h2 className=\"flex items-center gap-2 text-xl font-semibold\">\n <CalendarIcon className=\"size-5\" />\n Select Date\n </h2>\n <MiniCalendar\n className=\"w-fit\"\n days={7}\n onValueChange={setSelectedDate}\n value={selectedDate}\n >\n <MiniCalendarNavigation direction=\"prev\" />\n <MiniCalendarDays>\n {(date) => (\n <MiniCalendarDay date={date} key={date.toISOString()} />\n )}\n </MiniCalendarDays>\n <MiniCalendarNavigation direction=\"next\" />\n </MiniCalendar>\n </div>\n\n {/* Tags Selection */}\n <div className=\"space-y-4\">\n <h2 className=\"flex items-center gap-2 text-xl font-semibold\">\n <TagIcon className=\"size-5\" />\n Event Tags\n </h2>\n <Tags>\n <TagsTrigger>\n {selectedTags.map((tag) => (\n <TagsValue key={tag} onRemove={() => handleTagRemove(tag)}>\n {tag}\n </TagsValue>\n ))}\n </TagsTrigger>\n <TagsContent>\n <TagsInput placeholder=\"Search tags...\" />\n <TagsList>\n <TagsEmpty>No tags found.</TagsEmpty>\n <TagsGroup>\n {availableTags\n .filter((tag) => !selectedTags.includes(tag))\n .map((tag) => (\n <TagsItem key={tag} onSelect={() => handleTagSelect(tag)}>\n {tag}\n </TagsItem>\n ))}\n </TagsGroup>\n </TagsList>\n </TagsContent>\n </Tags>\n </div>\n\n {/* File Upload */}\n <div className=\"space-y-4\">\n <h2 className=\"flex items-center gap-2 text-xl font-semibold\">\n <ImageIcon className=\"size-5\" />\n Event Images\n </h2>\n <Dropzone\n accept={{\n \"image/*\": [\".png\", \".jpg\", \".jpeg\", \".gif\", \".webp\"],\n }}\n maxFiles={5}\n maxSize={5 * 1024 * 1024} // 5MB\n onDrop={(acceptedFiles) => setFiles(acceptedFiles)}\n >\n <DropzoneEmptyState />\n <DropzoneContent />\n </Dropzone>\n {files.length > 0 && (\n <div className=\"text-sm text-muted-foreground\">\n {files.length} file{files.length > 1 ? \"s\" : \"\"} selected\n </div>\n )}\n </div>\n\n {/* Submit Button */}\n <div className=\"flex justify-end space-x-4\">\n <Button type=\"button\" variant=\"outline\">\n Save as Draft\n </Button>\n <Button type=\"submit\">Create Event</Button>\n </div>\n </form>\n </div>\n )\n}\n\nexport default Example\n",
11
+ "content": "\"use client\"\n\nimport { useState, type FormEventHandler } from \"react\"\nimport {\n CalendarIcon,\n ImageIcon,\n InfoIcon,\n MapPinIcon,\n TagIcon,\n UsersIcon,\n} from \"lucide-react\"\nimport { toast } from \"sonner\"\n\nimport {\n Choicebox,\n ChoiceboxIndicator,\n ChoiceboxItem,\n ChoiceboxItemDescription,\n ChoiceboxItemHeader,\n ChoiceboxItemTitle,\n} from \"../../../../../packages/choicebox\"\nimport {\n Combobox,\n ComboboxContent,\n ComboboxEmpty,\n ComboboxGroup,\n ComboboxInput,\n ComboboxItem,\n ComboboxList,\n ComboboxTrigger,\n} from \"../../../../../packages/combobox\"\nimport {\n Dropzone,\n DropzoneContent,\n DropzoneEmptyState,\n} from \"../../../../../packages/dropzone\"\nimport {\n MiniCalendar,\n MiniCalendarDay,\n MiniCalendarDays,\n MiniCalendarNavigation,\n} from \"../../../../../packages/mini-calendar\"\nimport {\n Tags,\n TagsContent,\n TagsEmpty,\n TagsGroup,\n TagsInput,\n TagsItem,\n TagsList,\n TagsTrigger,\n TagsValue,\n} from \"../../../../../packages/tags\"\nimport { Button } from \"../../../../../packages/ui/src/ui/button\"\nimport { Input } from \"../../../../../packages/ui/src/ui/input\"\nimport { Label } from \"../../../../../packages/ui/src/ui/label\"\nimport { Textarea } from \"../../../../../packages/ui/src/ui/textarea\"\n\nconst eventTypes = [\n {\n value: \"conference\",\n label: \"Updated Conference\",\n description: \"Updated Professional gathering with speakers and networking\",\n },\n {\n value: \"workshop\",\n label: \"Updated Workshop\",\n description:\n \"Updated Hands-on learning experience with practical activities\",\n },\n {\n value: \"meetup\",\n label: \"Updated Meetup\",\n description: \"Updated Casual gathering for like-minded individuals\",\n },\n {\n value: \"webinar\",\n label: \"Updated Webinar\",\n description: \"Updated Online presentation or seminar via video conference\",\n },\n]\n\nconst venues = [\n { value: \"convention-center\", label: \"Updated Downtown Convention Center\" },\n { value: \"hotel-ballroom\", label: \"Updated Grand Hotel Ballroom\" },\n { value: \"university-hall\", label: \"Updated University Main Hall\" },\n { value: \"co-working-space\", label: \"Updated Tech Hub Co-working Space\" },\n { value: \"online\", label: \"Updated Online/Virtual\" },\n]\n\nconst availableTags = [\n \"Technology\",\n \"Business\",\n \"Marketing\",\n \"Design\",\n \"Development\",\n \"AI/ML\",\n \"Startup\",\n \"Networking\",\n \"Education\",\n \"Innovation\",\n \"Remote Work\",\n \"Leadership\",\n]\n\nconst Example = () => {\n const [eventType, setEventType] = useState(\"\")\n const [venue, setVenue] = useState(\"\")\n const [selectedDate, setSelectedDate] = useState<Date | undefined>()\n const [files, setFiles] = useState<File[]>([])\n const [selectedTags, setSelectedTags] = useState<string[]>([])\n\n const handleTagSelect = (tag: string) => {\n if (!selectedTags.includes(tag)) {\n setSelectedTags([...selectedTags, tag])\n }\n }\n\n const handleTagRemove = (tagToRemove: string) => {\n setSelectedTags(selectedTags.filter((tag) => tag !== tagToRemove))\n }\n\n const handleSubmit: FormEventHandler<HTMLFormElement> = (event) => {\n event.preventDefault()\n\n toast.success(\"Event created successfully\", {\n description: `${eventType} event created for ${selectedDate?.toLocaleDateString()} at ${venue}`,\n })\n }\n\n return (\n <div className=\"not-prose mx-auto max-w-[530px] p-8\">\n <div className=\"mb-8 text-center\">\n <h1 className=\"mb-2 text-3xl font-semibold tracking-tight\">\n Updated Create Your Event\n </h1>\n <p className=\"text-balance text-muted-foreground\">\n Updated Fill out the form below to create and customize your upcoming\n event\n </p>\n </div>\n\n <form className=\"space-y-8\" onSubmit={handleSubmit}>\n {/* Basic Information */}\n <div className=\"space-y-4\">\n <h2 className=\"flex items-center gap-2 text-xl font-semibold\">\n <InfoIcon className=\"size-5\" />\n Updated Basic Information\n </h2>\n <div className=\"grid gap-4 md:grid-cols-2\">\n <div className=\"space-y-2\">\n <Label htmlFor=\"event-name\">Updated Event Name</Label>\n <Input\n id=\"event-name\"\n placeholder=\"Updated Enter your event name\"\n required\n />\n </div>\n <div className=\"space-y-2\">\n <Label htmlFor=\"organizer\">Updated Organizer</Label>\n <Input\n id=\"organizer\"\n placeholder=\"Updated Your name or organization\"\n required\n />\n </div>\n </div>\n <div className=\"space-y-2\">\n <Label htmlFor=\"description\">Updated Description</Label>\n <Textarea\n id=\"description\"\n placeholder=\"Updated Describe your event in detail...\"\n rows={3}\n />\n </div>\n </div>\n\n {/* Event Type Selection */}\n <div className=\"space-y-4\">\n <h2 className=\"flex items-center gap-2 text-xl font-semibold\">\n <UsersIcon className=\"size-5\" />\n Updated Event Type\n </h2>\n <Choicebox onValueChange={setEventType} value={eventType}>\n {eventTypes.map((type) => (\n <ChoiceboxItem key={type.value} value={type.value}>\n <ChoiceboxItemHeader>\n <ChoiceboxItemTitle>{type.label}</ChoiceboxItemTitle>\n <ChoiceboxItemDescription>\n {type.description}\n </ChoiceboxItemDescription>\n </ChoiceboxItemHeader>\n <ChoiceboxIndicator />\n </ChoiceboxItem>\n ))}\n </Choicebox>\n </div>\n\n {/* Venue Selection */}\n <div className=\"space-y-4\">\n <h2 className=\"flex items-center gap-2 text-xl font-semibold\">\n <MapPinIcon className=\"size-5\" />\n Updated Venue\n </h2>\n <Combobox\n data={venues}\n onValueChange={setVenue}\n type=\"venue\"\n value={venue}\n >\n <ComboboxTrigger className=\"w-full\" />\n <ComboboxContent>\n <ComboboxInput />\n <ComboboxList>\n <ComboboxEmpty />\n <ComboboxGroup>\n {venues.map((venue) => (\n <ComboboxItem key={venue.value} value={venue.value}>\n {venue.label}\n </ComboboxItem>\n ))}\n </ComboboxGroup>\n </ComboboxList>\n </ComboboxContent>\n </Combobox>\n </div>\n\n {/* Date Selection */}\n <div className=\"space-y-4\">\n <h2 className=\"flex items-center gap-2 text-xl font-semibold\">\n <CalendarIcon className=\"size-5\" />\n Updated Select Date\n </h2>\n <MiniCalendar\n className=\"w-fit\"\n days={7}\n onValueChange={setSelectedDate}\n value={selectedDate}\n >\n <MiniCalendarNavigation direction=\"prev\" />\n <MiniCalendarDays>\n {(date) => (\n <MiniCalendarDay date={date} key={date.toISOString()} />\n )}\n </MiniCalendarDays>\n <MiniCalendarNavigation direction=\"next\" />\n </MiniCalendar>\n </div>\n\n {/* Tags Selection */}\n <div className=\"space-y-4\">\n <h2 className=\"flex items-center gap-2 text-xl font-semibold\">\n <TagIcon className=\"size-5\" />\n Updated Event Tags\n </h2>\n <Tags>\n <TagsTrigger>\n {selectedTags.map((tag) => (\n <TagsValue key={tag} onRemove={() => handleTagRemove(tag)}>\n {tag}\n </TagsValue>\n ))}\n </TagsTrigger>\n <TagsContent>\n <TagsInput placeholder=\"Updated Search tags...\" />\n <TagsList>\n <TagsEmpty>Updated No tags found.</TagsEmpty>\n <TagsGroup>\n {availableTags\n .filter((tag) => !selectedTags.includes(tag))\n .map((tag) => (\n <TagsItem key={tag} onSelect={() => handleTagSelect(tag)}>\n {tag}\n </TagsItem>\n ))}\n </TagsGroup>\n </TagsList>\n </TagsContent>\n </Tags>\n </div>\n\n {/* File Upload */}\n <div className=\"space-y-4\">\n <h2 className=\"flex items-center gap-2 text-xl font-semibold\">\n <ImageIcon className=\"size-5\" />\n Updated Event Images\n </h2>\n <Dropzone\n accept={{\n \"image/*\": [\".png\", \".jpg\", \".jpeg\", \".gif\", \".webp\"],\n }}\n maxFiles={5}\n maxSize={5 * 1024 * 1024} // 5MB\n onDrop={(acceptedFiles) => setFiles(acceptedFiles)}\n >\n <DropzoneEmptyState />\n <DropzoneContent />\n </Dropzone>\n {files.length > 0 && (\n <div className=\"text-sm text-muted-foreground\">\n {files.length} file{files.length > 1 ? \"s\" : \"\"} selected\n </div>\n )}\n </div>\n\n {/* Submit Button */}\n <div className=\"flex justify-end space-x-4\">\n <Button type=\"button\" variant=\"outline\">\n Updated Save as Draft\n </Button>\n <Button type=\"submit\">Updated Create Event</Button>\n </div>\n </form>\n </div>\n )\n}\n\nexport default Example\n",
12
12
  "type": "registry:example"
13
13
  }
14
14
  ],
@@ -8,7 +8,7 @@
8
8
  "files": [
9
9
  {
10
10
  "path": "registry/default/examples/frame-demo.tsx",
11
- "content": "import {\n Frame,\n FrameDescription,\n FrameHeader,\n FramePanel,\n FrameTitle,\n} from \"@/registry/default/ui/frame\"\n\nexport default function FrameDemo() {\n return (\n <Frame className=\"w-full\">\n <FrameHeader>\n <FrameTitle>Section header</FrameTitle>\n <FrameDescription>Brief description about the section</FrameDescription>\n </FrameHeader>\n <FramePanel>\n <h2 className=\"text-sm font-semibold\">Section title</h2>\n <p className=\"text-sm text-muted-foreground\">Section description</p>\n </FramePanel>\n </Frame>\n )\n}\n",
11
+ "content": "import {\n Frame,\n FrameDescription,\n FrameHeader,\n FramePanel,\n FrameTitle,\n} from \"@/registry/default/ui/frame\"\n\nexport default function FrameDemo() {\n return (\n <Frame className=\"w-full\">\n <FrameHeader>\n <FrameTitle>Updated Section header</FrameTitle>\n <FrameDescription>\n Updated Brief description about the section\n </FrameDescription>\n </FrameHeader>\n <FramePanel>\n <h2 className=\"text-sm font-semibold\">Updated Section title</h2>\n <p className=\"text-sm text-muted-foreground\">\n Updated Section description\n </p>\n </FramePanel>\n </Frame>\n )\n}\n",
12
12
  "type": "registry:example"
13
13
  }
14
14
  ],
@@ -10,7 +10,7 @@
10
10
  "files": [
11
11
  {
12
12
  "path": "registry/default/examples/gantt-lanes.tsx",
13
- "content": "\"use client\"\n\nimport { useState } from \"react\"\nimport { faker } from \"@faker-js/faker\"\n// @ts-ignore: No type declarations for 'lodash.groupby'\nimport groupBy from \"lodash.groupby\"\nimport { EyeIcon, LinkIcon, TrashIcon } from \"lucide-react\"\n\nimport {\n Avatar,\n AvatarFallback,\n AvatarImage,\n} from \"@/registry/default/ui/avatar\"\nimport {\n ContextMenu,\n ContextMenuContent,\n ContextMenuItem,\n ContextMenuTrigger,\n} from \"@/registry/default/ui/context-menu\"\n\nimport {\n GanttCreateMarkerTrigger,\n GanttFeatureList,\n GanttFeatureListGroup,\n GanttFeatureRow,\n GanttHeader,\n GanttMarker,\n GanttProvider,\n GanttSidebar,\n GanttSidebarGroup,\n GanttSidebarItem,\n GanttTimeline,\n GanttToday,\n} from \"../../../../../packages/gantt\"\n\n// Seed faker to ensure consistent data between server and client\nfaker.seed(123)\n\nconst capitalize = (str: string) => str.charAt(0).toUpperCase() + str.slice(1)\n\nconst statuses = [\n { id: faker.string.uuid(), name: \"Confirmed\", color: \"#10B981\" },\n { id: faker.string.uuid(), name: \"Pending\", color: \"#F59E0B\" },\n { id: faker.string.uuid(), name: \"Cancelled\", color: \"#EF4444\" },\n]\n\nconst guests = Array.from({ length: 8 })\n .fill(null)\n .map(() => ({\n id: faker.string.uuid(),\n name: faker.person.fullName(),\n image: faker.image.avatar(),\n }))\n\n// Hotel rooms\nconst hotelRooms = Array.from({ length: 5 })\n .fill(null)\n .map((_, index) => ({\n id: faker.string.uuid(),\n name: `Room ${101 + index}`,\n }))\n\n// Generate hotel reservations - multiple guests can book the same room for different periods\nconst hotelReservations = Array.from({ length: 12 })\n .fill(null)\n .map(() => {\n const startDate = faker.date.future({ years: 0.3, refDate: new Date() })\n const endDate = faker.date.future({ years: 0.1, refDate: startDate })\n const room = faker.helpers.arrayElement(hotelRooms)\n const guest = faker.helpers.arrayElement(guests)\n\n return {\n id: faker.string.uuid(),\n name: `${guest.name} - ${faker.helpers.arrayElement([\"Business Trip\", \"Vacation\", \"Conference\", \"Weekend Getaway\"])}`,\n startAt: startDate,\n endAt: endDate,\n status: faker.helpers.arrayElement(statuses),\n lane: room.id, // This groups reservations by room\n // Store additional data that's not part of core GanttFeature\n metadata: {\n guest,\n room,\n group: { name: \"Hotel Reservations\" },\n },\n }\n })\n\nconst exampleMarkers = Array.from({ length: 3 })\n .fill(null)\n .map(() => ({\n id: faker.string.uuid(),\n date: faker.date.future({ years: 0.2, refDate: new Date() }),\n label: faker.helpers.arrayElement([\n \"Holiday Period\",\n \"Conference Week\",\n \"Peak Season\",\n ]),\n className: faker.helpers.arrayElement([\n \"bg-blue-100 text-blue-900\",\n \"bg-green-100 text-green-900\",\n \"bg-purple-100 text-purple-900\",\n ]),\n }))\n\nconst Example = () => {\n const [reservations, setReservations] = useState(hotelReservations)\n\n // Group reservations by room (lane), then by group\n const groupedReservations = groupBy(reservations, \"metadata.group.name\")\n const roomGroupedReservations = Object.fromEntries(\n Object.entries(groupedReservations).map(\n ([groupName, groupReservations]) => [\n groupName,\n groupBy(groupReservations, \"lane\"),\n ]\n )\n )\n\n const handleViewReservation = (id: string) =>\n console.log(`Reservation selected: ${id}`)\n\n const handleCopyLink = (id: string) => console.log(`Copy link: ${id}`)\n\n const handleRemoveReservation = (id: string) =>\n setReservations((prev) =>\n prev.filter((reservation) => reservation.id !== id)\n )\n\n const handleRemoveMarker = (id: string) => console.log(`Remove marker: ${id}`)\n\n const handleCreateMarker = (date: Date) =>\n console.log(`Create marker: ${date.toISOString()}`)\n\n const handleMoveReservation = (\n id: string,\n startAt: Date,\n endAt: Date | null\n ) => {\n if (!endAt) {\n return\n }\n\n setReservations((prev) =>\n prev.map((reservation) =>\n reservation.id === id ? { ...reservation, startAt, endAt } : reservation\n )\n )\n\n console.log(`Move reservation: ${id} from ${startAt} to ${endAt}`)\n }\n\n const handleAddReservation = (date: Date) =>\n console.log(`Add reservation: ${date.toISOString()}`)\n\n return (\n <GanttProvider\n className=\"border\"\n onAddItem={handleAddReservation}\n range=\"monthly\"\n zoom={100}\n >\n <GanttSidebar>\n {Object.entries(roomGroupedReservations).map(\n ([groupName, roomReservations]) => (\n <GanttSidebarGroup key={groupName} name={groupName}>\n {Object.entries(roomReservations).map(\n ([roomId, roomReservationList]) => {\n const room = hotelRooms.find((r) => r.id === roomId)\n // Create a representative feature for the sidebar\n const representativeReservation = {\n id: roomId,\n name: room?.name || \"Unknown Room\",\n startAt: new Date(\n Math.min(\n ...roomReservationList.map((r) => r.startAt.getTime())\n )\n ),\n endAt: new Date(\n Math.max(\n ...roomReservationList.map((r) => r.endAt.getTime())\n )\n ),\n status: roomReservationList[0].status,\n }\n\n return (\n <GanttSidebarItem\n feature={representativeReservation}\n key={roomId}\n onSelectItem={() => handleViewReservation(roomId)}\n />\n )\n }\n )}\n </GanttSidebarGroup>\n )\n )}\n </GanttSidebar>\n <GanttTimeline>\n <GanttHeader />\n <GanttFeatureList>\n {Object.entries(roomGroupedReservations).map(\n ([groupName, roomReservations]) => (\n <GanttFeatureListGroup key={groupName}>\n {Object.entries(roomReservations).map(\n ([roomId, roomReservationList]) => (\n <div key={roomId}>\n <GanttFeatureRow\n features={roomReservationList}\n onMove={handleMoveReservation}\n >\n {(reservation) => (\n <ContextMenu>\n <ContextMenuTrigger asChild>\n <div className=\"flex w-full items-center gap-2\">\n <p className=\"flex-1 truncate text-xs\">\n {reservation.name}\n </p>\n {(reservation as any).metadata?.guest && (\n <Avatar className=\"h-4 w-4\">\n <AvatarImage\n src={\n (reservation as any).metadata.guest\n .image\n }\n />\n <AvatarFallback>\n {(\n reservation as any\n ).metadata.guest.name?.slice(0, 2)}\n </AvatarFallback>\n </Avatar>\n )}\n </div>\n </ContextMenuTrigger>\n <ContextMenuContent>\n <ContextMenuItem\n className=\"flex items-center gap-2\"\n onClick={() =>\n handleViewReservation(reservation.id)\n }\n >\n <EyeIcon\n className=\"text-muted-foreground\"\n size={16}\n />\n View reservation\n </ContextMenuItem>\n <ContextMenuItem\n className=\"flex items-center gap-2\"\n onClick={() => handleCopyLink(reservation.id)}\n >\n <LinkIcon\n className=\"text-muted-foreground\"\n size={16}\n />\n Copy link\n </ContextMenuItem>\n <ContextMenuItem\n className=\"flex items-center gap-2 text-destructive\"\n onClick={() =>\n handleRemoveReservation(reservation.id)\n }\n >\n <TrashIcon size={16} />\n Cancel reservation\n </ContextMenuItem>\n </ContextMenuContent>\n </ContextMenu>\n )}\n </GanttFeatureRow>\n </div>\n )\n )}\n </GanttFeatureListGroup>\n )\n )}\n </GanttFeatureList>\n {exampleMarkers.map((marker) => (\n <GanttMarker\n key={marker.id}\n {...marker}\n onRemove={handleRemoveMarker}\n />\n ))}\n <GanttToday />\n <GanttCreateMarkerTrigger onCreateMarker={handleCreateMarker} />\n </GanttTimeline>\n </GanttProvider>\n )\n}\n\nexport default Example\n",
13
+ "content": "\"use client\"\n\nimport { useState } from \"react\"\nimport { faker } from \"@faker-js/faker\"\n// @ts-ignore: No type declarations for 'lodash.groupby'\nimport groupBy from \"lodash.groupby\"\nimport { EyeIcon, LinkIcon, TrashIcon } from \"lucide-react\"\n\nimport {\n Avatar,\n AvatarFallback,\n AvatarImage,\n} from \"@/registry/default/ui/avatar\"\nimport {\n ContextMenu,\n ContextMenuContent,\n ContextMenuItem,\n ContextMenuTrigger,\n} from \"@/registry/default/ui/context-menu\"\n\nimport {\n GanttCreateMarkerTrigger,\n GanttFeatureList,\n GanttFeatureListGroup,\n GanttFeatureRow,\n GanttHeader,\n GanttMarker,\n GanttProvider,\n GanttSidebar,\n GanttSidebarGroup,\n GanttSidebarItem,\n GanttTimeline,\n GanttToday,\n} from \"../../../../../packages/gantt\"\n\n// Seed faker to ensure consistent data between server and client\nfaker.seed(123)\n\nconst capitalize = (str: string) => str.charAt(0).toUpperCase() + str.slice(1)\n\nconst statuses = [\n { id: faker.string.uuid(), name: \"Updated Confirmed\", color: \"#10B981\" },\n { id: faker.string.uuid(), name: \"Updated Pending\", color: \"#F59E0B\" },\n { id: faker.string.uuid(), name: \"Updated Cancelled\", color: \"#EF4444\" },\n]\n\nconst guests = Array.from({ length: 8 })\n .fill(null)\n .map(() => ({\n id: faker.string.uuid(),\n name: faker.person.fullName(),\n image: faker.image.avatar(),\n }))\n\n// Hotel rooms\nconst hotelRooms = Array.from({ length: 5 })\n .fill(null)\n .map((_, index) => ({\n id: faker.string.uuid(),\n name: `Room ${101 + index}`,\n }))\n\n// Generate hotel reservations - multiple guests can book the same room for different periods\nconst hotelReservations = Array.from({ length: 12 })\n .fill(null)\n .map(() => {\n const startDate = faker.date.future({ years: 0.3, refDate: new Date() })\n const endDate = faker.date.future({ years: 0.1, refDate: startDate })\n const room = faker.helpers.arrayElement(hotelRooms)\n const guest = faker.helpers.arrayElement(guests)\n\n return {\n id: faker.string.uuid(),\n name: `${guest.name} - ${faker.helpers.arrayElement([\"Business Trip\", \"Vacation\", \"Conference\", \"Weekend Getaway\"])}`,\n startAt: startDate,\n endAt: endDate,\n status: faker.helpers.arrayElement(statuses),\n lane: room.id, // This groups reservations by room\n // Store additional data that's not part of core GanttFeature\n metadata: {\n guest,\n room,\n group: { name: \"Updated Hotel Reservations\" },\n },\n }\n })\n\nconst exampleMarkers = Array.from({ length: 3 })\n .fill(null)\n .map(() => ({\n id: faker.string.uuid(),\n date: faker.date.future({ years: 0.2, refDate: new Date() }),\n label: faker.helpers.arrayElement([\n \"Holiday Period\",\n \"Conference Week\",\n \"Peak Season\",\n ]),\n className: faker.helpers.arrayElement([\n \"bg-blue-100 text-blue-900\",\n \"bg-green-100 text-green-900\",\n \"bg-purple-100 text-purple-900\",\n ]),\n }))\n\nconst Example = () => {\n const [reservations, setReservations] = useState(hotelReservations)\n\n // Group reservations by room (lane), then by group\n const groupedReservations = groupBy(reservations, \"metadata.group.name\")\n const roomGroupedReservations = Object.fromEntries(\n Object.entries(groupedReservations).map(\n ([groupName, groupReservations]) => [\n groupName,\n groupBy(groupReservations, \"lane\"),\n ]\n )\n )\n\n const handleViewReservation = (id: string) =>\n console.log(`Reservation selected: ${id}`)\n\n const handleCopyLink = (id: string) => console.log(`Copy link: ${id}`)\n\n const handleRemoveReservation = (id: string) =>\n setReservations((prev) =>\n prev.filter((reservation) => reservation.id !== id)\n )\n\n const handleRemoveMarker = (id: string) => console.log(`Remove marker: ${id}`)\n\n const handleCreateMarker = (date: Date) =>\n console.log(`Create marker: ${date.toISOString()}`)\n\n const handleMoveReservation = (\n id: string,\n startAt: Date,\n endAt: Date | null\n ) => {\n if (!endAt) {\n return\n }\n\n setReservations((prev) =>\n prev.map((reservation) =>\n reservation.id === id ? { ...reservation, startAt, endAt } : reservation\n )\n )\n\n console.log(`Move reservation: ${id} from ${startAt} to ${endAt}`)\n }\n\n const handleAddReservation = (date: Date) =>\n console.log(`Add reservation: ${date.toISOString()}`)\n\n return (\n <GanttProvider\n className=\"border\"\n onAddItem={handleAddReservation}\n range=\"monthly\"\n zoom={100}\n >\n <GanttSidebar>\n {Object.entries(roomGroupedReservations).map(\n ([groupName, roomReservations]) => (\n <GanttSidebarGroup key={groupName} name={groupName}>\n {Object.entries(roomReservations).map(\n ([roomId, roomReservationList]) => {\n const room = hotelRooms.find((r) => r.id === roomId)\n // Create a representative feature for the sidebar\n const representativeReservation = {\n id: roomId,\n name: room?.name || \"Unknown Room\",\n startAt: new Date(\n Math.min(\n ...roomReservationList.map((r) => r.startAt.getTime())\n )\n ),\n endAt: new Date(\n Math.max(\n ...roomReservationList.map((r) => r.endAt.getTime())\n )\n ),\n status: roomReservationList[0].status,\n }\n\n return (\n <GanttSidebarItem\n feature={representativeReservation}\n key={roomId}\n onSelectItem={() => handleViewReservation(roomId)}\n />\n )\n }\n )}\n </GanttSidebarGroup>\n )\n )}\n </GanttSidebar>\n <GanttTimeline>\n <GanttHeader />\n <GanttFeatureList>\n {Object.entries(roomGroupedReservations).map(\n ([groupName, roomReservations]) => (\n <GanttFeatureListGroup key={groupName}>\n {Object.entries(roomReservations).map(\n ([roomId, roomReservationList]) => (\n <div key={roomId}>\n <GanttFeatureRow\n features={roomReservationList}\n onMove={handleMoveReservation}\n >\n {(reservation) => (\n <ContextMenu>\n <ContextMenuTrigger asChild>\n <div className=\"flex w-full items-center gap-2\">\n <p className=\"flex-1 truncate text-xs\">\n {reservation.name}\n </p>\n {(reservation as any).metadata?.guest && (\n <Avatar className=\"h-4 w-4\">\n <AvatarImage\n src={\n (reservation as any).metadata.guest\n .image\n }\n />\n <AvatarFallback>\n {(\n reservation as any\n ).metadata.guest.name?.slice(0, 2)}\n </AvatarFallback>\n </Avatar>\n )}\n </div>\n </ContextMenuTrigger>\n <ContextMenuContent>\n <ContextMenuItem\n className=\"flex items-center gap-2\"\n onClick={() =>\n handleViewReservation(reservation.id)\n }\n >\n <EyeIcon\n className=\"text-muted-foreground\"\n size={16}\n />\n Updated View reservation\n </ContextMenuItem>\n <ContextMenuItem\n className=\"flex items-center gap-2\"\n onClick={() => handleCopyLink(reservation.id)}\n >\n <LinkIcon\n className=\"text-muted-foreground\"\n size={16}\n />\n Updated Copy link\n </ContextMenuItem>\n <ContextMenuItem\n className=\"flex items-center gap-2 text-destructive\"\n onClick={() =>\n handleRemoveReservation(reservation.id)\n }\n >\n <TrashIcon size={16} />\n Updated Cancel reservation\n </ContextMenuItem>\n </ContextMenuContent>\n </ContextMenu>\n )}\n </GanttFeatureRow>\n </div>\n )\n )}\n </GanttFeatureListGroup>\n )\n )}\n </GanttFeatureList>\n {exampleMarkers.map((marker) => (\n <GanttMarker\n key={marker.id}\n {...marker}\n onRemove={handleRemoveMarker}\n />\n ))}\n <GanttToday />\n <GanttCreateMarkerTrigger onCreateMarker={handleCreateMarker} />\n </GanttTimeline>\n </GanttProvider>\n )\n}\n\nexport default Example\n",
14
14
  "type": "registry:example"
15
15
  }
16
16
  ],