@object-ui/components 0.3.0

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 (295) hide show
  1. package/CHANGELOG.md +46 -0
  2. package/LICENSE +21 -0
  3. package/README.md +170 -0
  4. package/dist/index.css +1 -0
  5. package/dist/index.d.ts +2 -0
  6. package/dist/index.js +46186 -0
  7. package/dist/index.umd.cjs +92 -0
  8. package/dist/src/hooks/use-mobile.d.ts +1 -0
  9. package/dist/src/index.d.ts +2 -0
  10. package/dist/src/index.test.d.ts +1 -0
  11. package/dist/src/lib/utils.d.ts +4 -0
  12. package/dist/src/new-components.test.d.ts +1 -0
  13. package/dist/src/renderers/basic/div.d.ts +1 -0
  14. package/dist/src/renderers/basic/html.d.ts +1 -0
  15. package/dist/src/renderers/basic/icon.d.ts +1 -0
  16. package/dist/src/renderers/basic/image.d.ts +1 -0
  17. package/dist/src/renderers/basic/index.d.ts +0 -0
  18. package/dist/src/renderers/basic/separator.d.ts +1 -0
  19. package/dist/src/renderers/basic/span.d.ts +1 -0
  20. package/dist/src/renderers/basic/text.d.ts +1 -0
  21. package/dist/src/renderers/complex/__tests__/data-table.test.d.ts +0 -0
  22. package/dist/src/renderers/complex/calendar-view.d.ts +1 -0
  23. package/dist/src/renderers/complex/carousel.d.ts +1 -0
  24. package/dist/src/renderers/complex/chatbot.d.ts +1 -0
  25. package/dist/src/renderers/complex/chatbot.test.d.ts +1 -0
  26. package/dist/src/renderers/complex/data-table.d.ts +1 -0
  27. package/dist/src/renderers/complex/filter-builder.d.ts +1 -0
  28. package/dist/src/renderers/complex/index.d.ts +0 -0
  29. package/dist/src/renderers/complex/resizable.d.ts +1 -0
  30. package/dist/src/renderers/complex/scroll-area.d.ts +1 -0
  31. package/dist/src/renderers/complex/table.d.ts +1 -0
  32. package/dist/src/renderers/complex/timeline.d.ts +1 -0
  33. package/dist/src/renderers/data-display/alert.d.ts +1 -0
  34. package/dist/src/renderers/data-display/avatar.d.ts +1 -0
  35. package/dist/src/renderers/data-display/badge.d.ts +1 -0
  36. package/dist/src/renderers/data-display/index.d.ts +0 -0
  37. package/dist/src/renderers/data-display/list.d.ts +1 -0
  38. package/dist/src/renderers/data-display/statistic.d.ts +1 -0
  39. package/dist/src/renderers/data-display/tree-view.d.ts +1 -0
  40. package/dist/src/renderers/disclosure/accordion.d.ts +1 -0
  41. package/dist/src/renderers/disclosure/collapsible.d.ts +1 -0
  42. package/dist/src/renderers/disclosure/index.d.ts +0 -0
  43. package/dist/src/renderers/feedback/index.d.ts +0 -0
  44. package/dist/src/renderers/feedback/loading.d.ts +1 -0
  45. package/dist/src/renderers/feedback/progress.d.ts +1 -0
  46. package/dist/src/renderers/feedback/skeleton.d.ts +1 -0
  47. package/dist/src/renderers/feedback/toaster.d.ts +1 -0
  48. package/dist/src/renderers/form/button.d.ts +1 -0
  49. package/dist/src/renderers/form/calendar.d.ts +1 -0
  50. package/dist/src/renderers/form/checkbox.d.ts +1 -0
  51. package/dist/src/renderers/form/date-picker.d.ts +1 -0
  52. package/dist/src/renderers/form/file-upload.d.ts +1 -0
  53. package/dist/src/renderers/form/form.d.ts +1 -0
  54. package/dist/src/renderers/form/index.d.ts +0 -0
  55. package/dist/src/renderers/form/input-otp.d.ts +1 -0
  56. package/dist/src/renderers/form/input.d.ts +1 -0
  57. package/dist/src/renderers/form/label.d.ts +1 -0
  58. package/dist/src/renderers/form/radio-group.d.ts +1 -0
  59. package/dist/src/renderers/form/select.d.ts +1 -0
  60. package/dist/src/renderers/form/slider.d.ts +1 -0
  61. package/dist/src/renderers/form/switch.d.ts +1 -0
  62. package/dist/src/renderers/form/textarea.d.ts +1 -0
  63. package/dist/src/renderers/form/toggle.d.ts +1 -0
  64. package/dist/src/renderers/index.d.ts +0 -0
  65. package/dist/src/renderers/layout/card.d.ts +1 -0
  66. package/dist/src/renderers/layout/container.d.ts +1 -0
  67. package/dist/src/renderers/layout/flex.d.ts +1 -0
  68. package/dist/src/renderers/layout/grid.d.ts +1 -0
  69. package/dist/src/renderers/layout/index.d.ts +0 -0
  70. package/dist/src/renderers/layout/page.d.ts +7 -0
  71. package/dist/src/renderers/layout/semantic.d.ts +1 -0
  72. package/dist/src/renderers/layout/stack.d.ts +1 -0
  73. package/dist/src/renderers/layout/tabs.d.ts +1 -0
  74. package/dist/src/renderers/navigation/header-bar.d.ts +1 -0
  75. package/dist/src/renderers/navigation/index.d.ts +0 -0
  76. package/dist/src/renderers/navigation/sidebar.d.ts +1 -0
  77. package/dist/src/renderers/overlay/alert-dialog.d.ts +1 -0
  78. package/dist/src/renderers/overlay/context-menu.d.ts +1 -0
  79. package/dist/src/renderers/overlay/dialog.d.ts +1 -0
  80. package/dist/src/renderers/overlay/drawer.d.ts +1 -0
  81. package/dist/src/renderers/overlay/dropdown-menu.d.ts +1 -0
  82. package/dist/src/renderers/overlay/hover-card.d.ts +1 -0
  83. package/dist/src/renderers/overlay/index.d.ts +0 -0
  84. package/dist/src/renderers/overlay/popover.d.ts +1 -0
  85. package/dist/src/renderers/overlay/sheet.d.ts +1 -0
  86. package/dist/src/renderers/overlay/tooltip.d.ts +1 -0
  87. package/dist/src/ui/accordion.d.ts +7 -0
  88. package/dist/src/ui/alert-dialog.d.ts +14 -0
  89. package/dist/src/ui/alert.d.ts +9 -0
  90. package/dist/src/ui/aspect-ratio.d.ts +3 -0
  91. package/dist/src/ui/avatar.d.ts +6 -0
  92. package/dist/src/ui/badge.d.ts +9 -0
  93. package/dist/src/ui/breadcrumb.d.ts +11 -0
  94. package/dist/src/ui/button-group.d.ts +11 -0
  95. package/dist/src/ui/button.d.ts +13 -0
  96. package/dist/src/ui/calendar-view.d.ts +21 -0
  97. package/dist/src/ui/calendar.d.ts +8 -0
  98. package/dist/src/ui/card.d.ts +9 -0
  99. package/dist/src/ui/carousel.d.ts +19 -0
  100. package/dist/src/ui/chatbot.d.ts +36 -0
  101. package/dist/src/ui/checkbox.d.ts +4 -0
  102. package/dist/src/ui/collapsible.d.ts +5 -0
  103. package/dist/src/ui/command.d.ts +18 -0
  104. package/dist/src/ui/context-menu.d.ts +25 -0
  105. package/dist/src/ui/dialog.d.ts +15 -0
  106. package/dist/src/ui/drawer.d.ts +13 -0
  107. package/dist/src/ui/dropdown-menu.d.ts +25 -0
  108. package/dist/src/ui/empty.d.ts +11 -0
  109. package/dist/src/ui/field.d.ts +24 -0
  110. package/dist/src/ui/filter-builder.d.ts +31 -0
  111. package/dist/src/ui/form.d.ts +24 -0
  112. package/dist/src/ui/hover-card.d.ts +6 -0
  113. package/dist/src/ui/index.d.ts +56 -0
  114. package/dist/src/ui/input-group.d.ts +16 -0
  115. package/dist/src/ui/input-otp.d.ts +11 -0
  116. package/dist/src/ui/input.d.ts +3 -0
  117. package/dist/src/ui/item.d.ts +23 -0
  118. package/dist/src/ui/kbd.d.ts +3 -0
  119. package/dist/src/ui/label.d.ts +4 -0
  120. package/dist/src/ui/menubar.d.ts +26 -0
  121. package/dist/src/ui/navigation-menu.d.ts +14 -0
  122. package/dist/src/ui/pagination.d.ts +13 -0
  123. package/dist/src/ui/popover.d.ts +7 -0
  124. package/dist/src/ui/progress.d.ts +4 -0
  125. package/dist/src/ui/radio-group.d.ts +5 -0
  126. package/dist/src/ui/resizable.d.ts +10 -0
  127. package/dist/src/ui/scroll-area.d.ts +5 -0
  128. package/dist/src/ui/select.d.ts +15 -0
  129. package/dist/src/ui/separator.d.ts +4 -0
  130. package/dist/src/ui/sheet.d.ts +13 -0
  131. package/dist/src/ui/sidebar.d.ts +69 -0
  132. package/dist/src/ui/skeleton.d.ts +2 -0
  133. package/dist/src/ui/slider.d.ts +4 -0
  134. package/dist/src/ui/sonner.d.ts +3 -0
  135. package/dist/src/ui/spinner.d.ts +3 -0
  136. package/dist/src/ui/switch.d.ts +4 -0
  137. package/dist/src/ui/table.d.ts +10 -0
  138. package/dist/src/ui/tabs.d.ts +7 -0
  139. package/dist/src/ui/textarea.d.ts +3 -0
  140. package/dist/src/ui/timeline.d.ts +25 -0
  141. package/dist/src/ui/toggle-group.d.ts +9 -0
  142. package/dist/src/ui/toggle.d.ts +9 -0
  143. package/dist/src/ui/tooltip.d.ts +7 -0
  144. package/docs/FilterBuilder.md +268 -0
  145. package/metadata/Chart.component.yml +30 -0
  146. package/metadata/FilterBuilder.component.yml +39 -0
  147. package/metadata/GridLayout.component.yml +27 -0
  148. package/metadata/Menu.component.yml +31 -0
  149. package/metadata/ObjectForm.component.yml +34 -0
  150. package/metadata/ObjectTable.component.yml +41 -0
  151. package/metadata/Page.component.yml +24 -0
  152. package/package.json +87 -0
  153. package/postcss.config.js +6 -0
  154. package/src/hooks/use-mobile.tsx +19 -0
  155. package/src/index.css +76 -0
  156. package/src/index.test.ts +7 -0
  157. package/src/index.ts +10 -0
  158. package/src/lib/utils.tsx +27 -0
  159. package/src/new-components.test.ts +74 -0
  160. package/src/renderers/basic/div.tsx +41 -0
  161. package/src/renderers/basic/html.tsx +34 -0
  162. package/src/renderers/basic/icon.tsx +25 -0
  163. package/src/renderers/basic/image.tsx +37 -0
  164. package/src/renderers/basic/index.ts +7 -0
  165. package/src/renderers/basic/separator.tsx +48 -0
  166. package/src/renderers/basic/span.tsx +44 -0
  167. package/src/renderers/basic/text.tsx +42 -0
  168. package/src/renderers/complex/README-KANBAN.md +208 -0
  169. package/src/renderers/complex/TIMELINE.md +353 -0
  170. package/src/renderers/complex/__tests__/data-table.test.ts +52 -0
  171. package/src/renderers/complex/calendar-view.tsx +219 -0
  172. package/src/renderers/complex/carousel.tsx +60 -0
  173. package/src/renderers/complex/chatbot.test.ts +44 -0
  174. package/src/renderers/complex/chatbot.tsx +185 -0
  175. package/src/renderers/complex/data-table.tsx +650 -0
  176. package/src/renderers/complex/filter-builder.tsx +68 -0
  177. package/src/renderers/complex/index.ts +10 -0
  178. package/src/renderers/complex/resizable.tsx +54 -0
  179. package/src/renderers/complex/scroll-area.tsx +32 -0
  180. package/src/renderers/complex/table.tsx +86 -0
  181. package/src/renderers/complex/timeline.tsx +466 -0
  182. package/src/renderers/data-display/alert.tsx +37 -0
  183. package/src/renderers/data-display/avatar.tsx +29 -0
  184. package/src/renderers/data-display/badge.tsx +46 -0
  185. package/src/renderers/data-display/index.ts +6 -0
  186. package/src/renderers/data-display/list.tsx +95 -0
  187. package/src/renderers/data-display/statistic.tsx +98 -0
  188. package/src/renderers/data-display/tree-view.tsx +180 -0
  189. package/src/renderers/disclosure/accordion.tsx +60 -0
  190. package/src/renderers/disclosure/collapsible.tsx +44 -0
  191. package/src/renderers/disclosure/index.ts +2 -0
  192. package/src/renderers/feedback/index.ts +4 -0
  193. package/src/renderers/feedback/loading.tsx +69 -0
  194. package/src/renderers/feedback/progress.tsx +20 -0
  195. package/src/renderers/feedback/skeleton.tsx +22 -0
  196. package/src/renderers/feedback/toaster.tsx +26 -0
  197. package/src/renderers/form/button.tsx +61 -0
  198. package/src/renderers/form/calendar.tsx +25 -0
  199. package/src/renderers/form/checkbox.tsx +41 -0
  200. package/src/renderers/form/date-picker.tsx +75 -0
  201. package/src/renderers/form/file-upload.tsx +175 -0
  202. package/src/renderers/form/form.tsx +417 -0
  203. package/src/renderers/form/index.ts +16 -0
  204. package/src/renderers/form/input-otp.tsx +31 -0
  205. package/src/renderers/form/input.tsx +79 -0
  206. package/src/renderers/form/label.tsx +36 -0
  207. package/src/renderers/form/radio-group.tsx +54 -0
  208. package/src/renderers/form/select.tsx +66 -0
  209. package/src/renderers/form/slider.tsx +45 -0
  210. package/src/renderers/form/switch.tsx +39 -0
  211. package/src/renderers/form/textarea.tsx +45 -0
  212. package/src/renderers/form/toggle.tsx +76 -0
  213. package/src/renderers/index.ts +9 -0
  214. package/src/renderers/layout/card.tsx +69 -0
  215. package/src/renderers/layout/container.tsx +113 -0
  216. package/src/renderers/layout/flex.tsx +123 -0
  217. package/src/renderers/layout/grid.tsx +155 -0
  218. package/src/renderers/layout/index.ts +10 -0
  219. package/src/renderers/layout/page.tsx +82 -0
  220. package/src/renderers/layout/semantic.tsx +39 -0
  221. package/src/renderers/layout/stack.tsx +123 -0
  222. package/src/renderers/layout/tabs.tsx +63 -0
  223. package/src/renderers/navigation/header-bar.tsx +50 -0
  224. package/src/renderers/navigation/index.ts +2 -0
  225. package/src/renderers/navigation/sidebar.tsx +189 -0
  226. package/src/renderers/overlay/alert-dialog.tsx +63 -0
  227. package/src/renderers/overlay/context-menu.tsx +91 -0
  228. package/src/renderers/overlay/dialog.tsx +68 -0
  229. package/src/renderers/overlay/drawer.tsx +68 -0
  230. package/src/renderers/overlay/dropdown-menu.tsx +90 -0
  231. package/src/renderers/overlay/hover-card.tsx +46 -0
  232. package/src/renderers/overlay/index.ts +9 -0
  233. package/src/renderers/overlay/popover.tsx +47 -0
  234. package/src/renderers/overlay/sheet.tsx +68 -0
  235. package/src/renderers/overlay/tooltip.tsx +58 -0
  236. package/src/ui/accordion.tsx +64 -0
  237. package/src/ui/alert-dialog.tsx +155 -0
  238. package/src/ui/alert.tsx +78 -0
  239. package/src/ui/aspect-ratio.tsx +11 -0
  240. package/src/ui/avatar.tsx +51 -0
  241. package/src/ui/badge.tsx +46 -0
  242. package/src/ui/breadcrumb.tsx +109 -0
  243. package/src/ui/button-group.tsx +83 -0
  244. package/src/ui/button.tsx +65 -0
  245. package/src/ui/calendar-view.tsx +503 -0
  246. package/src/ui/calendar.tsx +237 -0
  247. package/src/ui/card.tsx +138 -0
  248. package/src/ui/carousel.tsx +239 -0
  249. package/src/ui/chatbot.tsx +240 -0
  250. package/src/ui/checkbox.tsx +32 -0
  251. package/src/ui/collapsible.tsx +31 -0
  252. package/src/ui/command.tsx +182 -0
  253. package/src/ui/context-menu.tsx +247 -0
  254. package/src/ui/dialog.tsx +141 -0
  255. package/src/ui/drawer.tsx +135 -0
  256. package/src/ui/dropdown-menu.tsx +254 -0
  257. package/src/ui/empty.tsx +104 -0
  258. package/src/ui/field.tsx +246 -0
  259. package/src/ui/filter-builder.tsx +359 -0
  260. package/src/ui/form.tsx +167 -0
  261. package/src/ui/hover-card.tsx +44 -0
  262. package/src/ui/index.ts +56 -0
  263. package/src/ui/input-group.tsx +170 -0
  264. package/src/ui/input-otp.tsx +81 -0
  265. package/src/ui/input.tsx +24 -0
  266. package/src/ui/item.tsx +193 -0
  267. package/src/ui/kbd.tsx +28 -0
  268. package/src/ui/label.tsx +24 -0
  269. package/src/ui/menubar.tsx +274 -0
  270. package/src/ui/navigation-menu.tsx +168 -0
  271. package/src/ui/pagination.tsx +127 -0
  272. package/src/ui/popover.tsx +48 -0
  273. package/src/ui/progress.tsx +41 -0
  274. package/src/ui/radio-group.tsx +45 -0
  275. package/src/ui/resizable.tsx +55 -0
  276. package/src/ui/scroll-area.tsx +58 -0
  277. package/src/ui/select.tsx +188 -0
  278. package/src/ui/separator.tsx +31 -0
  279. package/src/ui/sheet.tsx +137 -0
  280. package/src/ui/sidebar.tsx +726 -0
  281. package/src/ui/skeleton.tsx +20 -0
  282. package/src/ui/slider.tsx +63 -0
  283. package/src/ui/sonner.tsx +43 -0
  284. package/src/ui/spinner.tsx +38 -0
  285. package/src/ui/switch.tsx +31 -0
  286. package/src/ui/table.tsx +120 -0
  287. package/src/ui/tabs.tsx +86 -0
  288. package/src/ui/textarea.tsx +18 -0
  289. package/src/ui/timeline.tsx +266 -0
  290. package/src/ui/toggle-group.tsx +87 -0
  291. package/src/ui/toggle.tsx +50 -0
  292. package/src/ui/tooltip.tsx +61 -0
  293. package/tailwind.config.js +75 -0
  294. package/tsconfig.json +18 -0
  295. package/vite.config.ts +44 -0
@@ -0,0 +1,98 @@
1
+ import { ComponentRegistry } from '@object-ui/core';
2
+ import type { StatisticSchema } from '@object-ui/types';
3
+ import { cn } from '../../lib/utils';
4
+ import { TrendingUp, TrendingDown, Minus } from 'lucide-react';
5
+
6
+ const StatisticRenderer = ({ schema }: { schema: StatisticSchema }) => {
7
+ return (
8
+ <div className={cn(
9
+ "group relative flex flex-col p-5 rounded-xl transition-all duration-300 overflow-hidden",
10
+ "bg-slate-950/40 border border-slate-800/60 backdrop-blur-sm",
11
+ "hover:bg-slate-900/60 hover:border-cyan-500/50 hover:shadow-[0_0_30px_-10px_rgba(6,182,212,0.3)]",
12
+ schema.className
13
+ )}>
14
+ {/* Decorative scanner line */}
15
+ <div className="absolute top-0 left-0 w-full h-[1px] bg-linear-to-r from-transparent via-cyan-500/50 to-transparent -translate-x-full group-hover:animate-[shimmer_1.5s_infinite]" />
16
+ <div className="absolute inset-0 bg-[url('https://grainy-gradients.vercel.app/noise.svg')] opacity-5 pointer-events-none" />
17
+
18
+ {/* Label */}
19
+ {schema.label && (
20
+ <div className="flex items-center gap-2 mb-2">
21
+ <div className="w-1 h-3 bg-cyan-500 rounded-full shadow-[0_0_8px_cyan]" />
22
+ <p className="text-[10px] font-mono font-bold uppercase tracking-[0.2em] text-cyan-600/80 group-hover:text-cyan-400 transition-colors">
23
+ {schema.label}
24
+ </p>
25
+ </div>
26
+ )}
27
+
28
+ {/* Value Area */}
29
+ <div className="flex items-baseline gap-3 my-1 relative z-10">
30
+ <h3 className={cn(
31
+ "text-4xl font-black tracking-tight text-white transition-all duration-300",
32
+ "drop-shadow-[0_0_10px_rgba(255,255,255,0.3)]",
33
+ "group-hover:scale-110 group-hover:text-cyan-100 group-hover:drop-shadow-[0_0_15px_rgba(6,182,212,0.6)] group-hover:-translate-y-1"
34
+ )}>
35
+ {schema.value}
36
+ </h3>
37
+
38
+ {/* Trend Indicator */}
39
+ {schema.trend && (
40
+ <div className={cn(
41
+ "flex items-center px-2 py-0.5 rounded-full text-[10px] font-bold border backdrop-blur-md transition-all",
42
+ schema.trend === 'up' && "text-emerald-400 border-emerald-500/30 bg-emerald-950/30 shadow-[0_0_10px_-4px_rgba(52,211,153,0.5)]",
43
+ schema.trend === 'down' && "text-rose-400 border-rose-500/30 bg-rose-950/30 shadow-[0_0_10px_-4px_rgba(251,113,133,0.5)]",
44
+ schema.trend === 'neutral' && "text-amber-400 border-amber-500/30 bg-amber-950/30 shadow-[0_0_10px_-4px_rgba(251,191,36,0.5)]",
45
+ "group-hover:scale-105"
46
+ )}>
47
+ {schema.trend === 'up' && <TrendingUp className="mr-1 h-3 w-3" />}
48
+ {schema.trend === 'down' && <TrendingDown className="mr-1 h-3 w-3" />}
49
+ {schema.trend === 'neutral' && <Minus className="mr-1 h-3 w-3" />}
50
+ {schema.description && <span className="max-w-[100px] truncate">{schema.description}</span>}
51
+ </div>
52
+ )}
53
+ </div>
54
+
55
+ {/* Footer / Description Text if needed below (optional, mostly handled by trend pill now, but keeping separate if text is long) */}
56
+ {schema.description && !schema.trend && (
57
+ <p className="text-xs text-slate-500 font-mono mt-1 group-hover:text-slate-400 transition-colors">
58
+ {schema.description}
59
+ </p>
60
+ )}
61
+
62
+ {/* Decorative accent corners */}
63
+ <div className="absolute right-0 bottom-0 w-8 h-8 opacity-20 group-hover:opacity-100 transition-opacity">
64
+ <svg viewBox="0 0 24 24" fill="none" className="w-full h-full text-cyan-500" stroke="currentColor" strokeWidth="1">
65
+ <path d="M22 22L12 22L22 12Z" fill="currentColor" fillOpacity="0.2" />
66
+ <path d="M22 17L22 22L17 22" strokeLinecap="round" strokeLinejoin="round" />
67
+ </svg>
68
+ </div>
69
+ </div>
70
+ );
71
+ };
72
+
73
+ ComponentRegistry.register('statistic', StatisticRenderer, {
74
+ label: 'Statistic',
75
+ category: 'data-display',
76
+ icon: 'Activity',
77
+ inputs: [
78
+ { name: 'label', type: 'string', label: 'Label' },
79
+ { name: 'value', type: 'string', label: 'Value' },
80
+ { name: 'description', type: 'string', label: 'Description' },
81
+ {
82
+ name: 'trend',
83
+ type: 'enum',
84
+ enum: [
85
+ { label: 'Up', value: 'up' },
86
+ { label: 'Down', value: 'down' },
87
+ { label: 'Neutral', value: 'neutral' }
88
+ ],
89
+ label: 'Trend'
90
+ }
91
+ ],
92
+ defaultProps: {
93
+ label: 'Total Revenue',
94
+ value: '$45,231.89',
95
+ trend: 'up',
96
+ description: '+20.1% from last month'
97
+ }
98
+ });
@@ -0,0 +1,180 @@
1
+ import { ComponentRegistry } from '@object-ui/core';
2
+ import type { TreeViewSchema, TreeNode } from '@object-ui/types';
3
+ import { ChevronRight, ChevronDown, Folder, File, FolderOpen, CircuitBoard } from 'lucide-react';
4
+ import { useState } from 'react';
5
+ import { cn } from '../../lib/utils';
6
+
7
+ const TreeNodeComponent = ({
8
+ node,
9
+ onNodeClick,
10
+ isChild = false
11
+ }: {
12
+ node: TreeNode;
13
+ onNodeClick?: (node: TreeNode) => void;
14
+ isChild?: boolean;
15
+ }) => {
16
+ const [isOpen, setIsOpen] = useState(false);
17
+ const hasChildren = node.children && node.children.length > 0;
18
+
19
+ const handleToggle = (e: React.MouseEvent) => {
20
+ e.stopPropagation();
21
+ setIsOpen(!isOpen);
22
+ };
23
+
24
+ const handleClick = () => {
25
+ if (onNodeClick) {
26
+ onNodeClick(node);
27
+ }
28
+ };
29
+
30
+ return (
31
+ <div className="relative">
32
+ {/* Connecting line for siblings (visual aid, tricky to do perfectly without depth context, so we focus on the left border of the container) */}
33
+
34
+ <div
35
+ className={cn(
36
+ 'group flex items-center py-1.5 px-2 rounded-sm cursor-pointer transition-all duration-200 border border-transparent',
37
+ 'hover:bg-cyan-950/30 hover:border-cyan-500/20 hover:shadow-[inset_0_0_10px_-5px_cyan]',
38
+ isOpen && hasChildren && 'bg-slate-900/40' // Active parent state
39
+ )}
40
+ onClick={handleClick}
41
+ >
42
+ {/* Indentation adjustment triggered by parent's padding/margin, not calculated prop here to allow CSS lines */}
43
+
44
+ {hasChildren ? (
45
+ <button
46
+ onClick={handleToggle}
47
+ className="mr-2 p-0.5 h-5 w-5 flex items-center justify-center rounded-sm hover:bg-cyan-500/20 text-cyan-600 transition-colors"
48
+ >
49
+ {isOpen ? (
50
+ <ChevronDown className="h-4 w-4 drop-shadow-[0_0_5px_cyan]" />
51
+ ) : (
52
+ <ChevronRight className="h-4 w-4" />
53
+ )}
54
+ </button>
55
+ ) : (
56
+ <span className="mr-2 w-5 flex justify-center">
57
+ <div className="w-1 h-1 rounded-full bg-slate-700/50 group-hover:bg-cyan-500/50" />
58
+ </span>
59
+ )}
60
+
61
+ {node.icon === 'folder' || hasChildren ? (
62
+ isOpen ?
63
+ <FolderOpen className="h-4 w-4 mr-2 text-cyan-400 drop-shadow-[0_0_5px_rgba(6,182,212,0.5)]" /> :
64
+ <Folder className="h-4 w-4 mr-2 text-cyan-600 group-hover:text-cyan-400 transition-colors" />
65
+ ) : (
66
+ <File className="h-4 w-4 mr-2 text-slate-500 group-hover:text-cyan-200 transition-colors" />
67
+ )}
68
+
69
+ <span className={cn(
70
+ "text-sm font-mono tracking-wide transition-colors",
71
+ isOpen ? "text-cyan-100 font-bold shadow-cyan-500/20" : "text-slate-400 group-hover:text-cyan-300"
72
+ )}>
73
+ {node.label}
74
+ </span>
75
+ </div>
76
+
77
+ {/* Children Container with Circuit Line */}
78
+ {hasChildren && isOpen && (
79
+ <div className="relative ml-[11px] pl-3 border-l border-cyan-800/40 animate-in slide-in-from-left-2 fade-in duration-200">
80
+ {/* Decorative little bulb at the junction */}
81
+ <div className="absolute top-0 -left-[1px] -translate-x-1/2 w-1.5 h-1.5 bg-cyan-700/50 rounded-full" />
82
+
83
+ {node.children!.map((child) => (
84
+ <TreeNodeComponent
85
+ key={child.id}
86
+ node={child}
87
+ onNodeClick={onNodeClick}
88
+ isChild={true}
89
+ />
90
+ ))}
91
+
92
+ {/* Decorative end cap */}
93
+ <div className="absolute bottom-0 -left-[1px] -translate-x-1/2 w-1 h-1 bg-cyan-800/50 rounded-full" />
94
+ </div>
95
+ )}
96
+ </div>
97
+ );
98
+ };
99
+
100
+ ComponentRegistry.register('tree-view',
101
+ ({ schema, className, ...props }) => {
102
+ const handleNodeClick = (node: TreeNode) => {
103
+ if (schema.onNodeClick) {
104
+ schema.onNodeClick(node);
105
+ }
106
+ };
107
+
108
+ return (
109
+ <div className={cn(
110
+ 'relative border border-border/60 rounded-lg p-3 bg-card/40 backdrop-blur-md overflow-hidden',
111
+ 'shadow-lg shadow-primary/5',
112
+ className
113
+ )}
114
+ {...props}
115
+ >
116
+ {/* Background Grid */}
117
+ <div className="absolute inset-0 bg-[linear-gradient(to_right,hsl(var(--border)/0.1)_1px,transparent_1px),linear-gradient(to_bottom,hsl(var(--border)/0.1)_1px,transparent_1px)] bg-[size:24px_24px] pointer-events-none" />
118
+
119
+ {schema.title && (
120
+ <div className="flex items-center gap-2 mb-3 pb-2 border-b border-primary/20 relative z-10">
121
+ <CircuitBoard className="w-4 h-4 text-primary" />
122
+ <h3 className="text-xs font-bold font-mono uppercase tracking-widest text-primary">{schema.title}</h3>
123
+ </div>
124
+ )}
125
+ <div className="space-y-1 relative z-10">
126
+ {schema.nodes?.map((node: TreeNode) => (
127
+ <TreeNodeComponent
128
+ key={node.id}
129
+ node={node}
130
+ onNodeClick={handleNodeClick}
131
+ />
132
+ ))}
133
+ </div>
134
+ </div>
135
+ );
136
+ },
137
+ {
138
+ label: 'Tree View',
139
+ inputs: [
140
+ { name: 'title', type: 'string', label: 'Title' },
141
+ {
142
+ name: 'nodes',
143
+ type: 'array',
144
+ label: 'Tree Nodes',
145
+ description: 'Array of { id, label, icon, children, data }'
146
+ },
147
+ { name: 'className', type: 'string', label: 'CSS Class' }
148
+ ],
149
+ defaultProps: {
150
+ title: 'File Explorer',
151
+ nodes: [
152
+ {
153
+ id: '1',
154
+ label: 'Documents',
155
+ icon: 'folder',
156
+ children: [
157
+ { id: '1-1', label: 'Resume.pdf', icon: 'file' },
158
+ { id: '1-2', label: 'Cover Letter.docx', icon: 'file' }
159
+ ]
160
+ },
161
+ {
162
+ id: '2',
163
+ label: 'Photos',
164
+ icon: 'folder',
165
+ children: [
166
+ { id: '2-1', label: 'Vacation', icon: 'folder', children: [
167
+ { id: '2-1-1', label: 'Beach.jpg', icon: 'file' }
168
+ ]},
169
+ { id: '2-2', label: 'Family.jpg', icon: 'file' }
170
+ ]
171
+ },
172
+ {
173
+ id: '3',
174
+ label: 'README.md',
175
+ icon: 'file'
176
+ }
177
+ ]
178
+ }
179
+ }
180
+ );
@@ -0,0 +1,60 @@
1
+ import { ComponentRegistry } from '@object-ui/core';
2
+ import type { AccordionSchema } from '@object-ui/types';
3
+ import {
4
+ Accordion,
5
+ AccordionItem,
6
+ AccordionTrigger,
7
+ AccordionContent
8
+ } from '../../ui';
9
+ import { renderChildren } from '../../lib/utils';
10
+
11
+ ComponentRegistry.register('accordion',
12
+ ({ schema, className, ...props }: { schema: AccordionSchema; className?: string; [key: string]: any }) => (
13
+ <Accordion type={schema.accordionType || 'single'} collapsible={schema.collapsible} className={className} {...props}>
14
+ {schema.items?.map((item, index: number) => (
15
+ <AccordionItem key={item.value || index} value={item.value || `item-${index}`}>
16
+ <AccordionTrigger>{item.title}</AccordionTrigger>
17
+ <AccordionContent>
18
+ {renderChildren(item.content)}
19
+ </AccordionContent>
20
+ </AccordionItem>
21
+ ))}
22
+ </Accordion>
23
+ ),
24
+ {
25
+ label: 'Accordion',
26
+ inputs: [
27
+ { name: 'accordionType', type: 'enum', enum: ['single', 'multiple'], defaultValue: 'single', label: 'Type' },
28
+ { name: 'collapsible', type: 'boolean', label: 'Collapsible (for single type)' },
29
+ {
30
+ name: 'items',
31
+ type: 'array',
32
+ label: 'Items',
33
+ description: 'Array of { trigger, content, value }'
34
+ },
35
+ { name: 'className', type: 'string', label: 'CSS Class' }
36
+ ],
37
+ defaultProps: {
38
+ accordionType: 'single',
39
+ collapsible: true,
40
+ items: [
41
+ {
42
+ label: 'Item 1',
43
+ value: 'item-1',
44
+ content: [{ type: 'text', content: 'Content for item 1' }]
45
+ },
46
+ {
47
+ label: 'Item 2',
48
+ value: 'item-2',
49
+ content: [{ type: 'text', content: 'Content for item 2' }]
50
+ },
51
+ {
52
+ label: 'Item 3',
53
+ value: 'item-3',
54
+ content: [{ type: 'text', content: 'Content for item 3' }]
55
+ }
56
+ ],
57
+ className: 'w-full'
58
+ }
59
+ }
60
+ );
@@ -0,0 +1,44 @@
1
+ import { ComponentRegistry } from '@object-ui/core';
2
+ import type { CollapsibleSchema } from '@object-ui/types';
3
+ import {
4
+ Collapsible,
5
+ CollapsibleTrigger,
6
+ CollapsibleContent
7
+ } from '../../ui';
8
+ import { renderChildren } from '../../lib/utils';
9
+
10
+ ComponentRegistry.register('collapsible',
11
+ ({ schema, className, ...props }: { schema: CollapsibleSchema; className?: string; [key: string]: any }) => (
12
+ <Collapsible defaultOpen={schema.defaultOpen} disabled={schema.disabled} className={className} {...props}>
13
+ <CollapsibleTrigger asChild>
14
+ {renderChildren(schema.trigger)}
15
+ </CollapsibleTrigger>
16
+ <CollapsibleContent>
17
+ {renderChildren(schema.content)}
18
+ </CollapsibleContent>
19
+ </Collapsible>
20
+ ),
21
+ {
22
+ label: 'Collapsible',
23
+ inputs: [
24
+ { name: 'defaultOpen', type: 'boolean', label: 'Default Open' },
25
+ { name: 'disabled', type: 'boolean', label: 'Disabled' },
26
+ {
27
+ name: 'trigger',
28
+ type: 'slot',
29
+ label: 'Trigger'
30
+ },
31
+ {
32
+ name: 'content',
33
+ type: 'slot',
34
+ label: 'Content'
35
+ },
36
+ { name: 'className', type: 'string', label: 'CSS Class' }
37
+ ],
38
+ defaultProps: {
39
+ trigger: [{ type: 'button', label: 'Toggle', variant: 'outline' }],
40
+ content: [{ type: 'text', content: 'Collapsible content goes here' }],
41
+ className: 'w-full'
42
+ }
43
+ }
44
+ );
@@ -0,0 +1,2 @@
1
+ import './accordion';
2
+ import './collapsible';
@@ -0,0 +1,4 @@
1
+ import './progress';
2
+ import './skeleton';
3
+ import './toaster';
4
+ import './loading';
@@ -0,0 +1,69 @@
1
+ import { ComponentRegistry } from '@object-ui/core';
2
+ import type { LoadingSchema } from '@object-ui/types';
3
+ import { Spinner } from '../../ui';
4
+ import { cn } from '../../lib/utils';
5
+
6
+ ComponentRegistry.register('loading',
7
+ ({ schema, className, ...props }: { schema: LoadingSchema; className?: string; [key: string]: any }) => {
8
+ const size = schema.size || 'md';
9
+ const fullscreen = schema.fullscreen || false;
10
+
11
+ const loadingContent = (
12
+ <div className={cn('flex flex-col items-center justify-center gap-2', className)}>
13
+ <Spinner
14
+ className={cn(
15
+ size === 'sm' && 'h-4 w-4',
16
+ size === 'md' && 'h-8 w-8',
17
+ size === 'lg' && 'h-12 w-12',
18
+ size === ('xl' as any) && 'h-16 w-16'
19
+ )}
20
+ />
21
+ {schema.text && (
22
+ <p className="text-sm text-muted-foreground">{schema.text}</p>
23
+ )}
24
+ </div>
25
+ );
26
+
27
+ if (fullscreen) {
28
+ return (
29
+ <div
30
+ className="fixed inset-0 z-50 flex items-center justify-center bg-background/80 backdrop-blur-sm"
31
+ {...props}
32
+ >
33
+ {loadingContent}
34
+ </div>
35
+ );
36
+ }
37
+
38
+ return (
39
+ <div className="flex items-center justify-center p-8" {...props}>
40
+ {loadingContent}
41
+ </div>
42
+ );
43
+ },
44
+ {
45
+ label: 'Loading',
46
+ inputs: [
47
+ { name: 'text', type: 'string', label: 'Loading Text' },
48
+ {
49
+ name: 'size',
50
+ type: 'enum',
51
+ enum: ['sm', 'md', 'lg', 'xl'],
52
+ label: 'Size',
53
+ defaultValue: 'md'
54
+ },
55
+ {
56
+ name: 'fullscreen',
57
+ type: 'boolean',
58
+ label: 'Fullscreen Overlay',
59
+ defaultValue: false
60
+ },
61
+ { name: 'className', type: 'string', label: 'CSS Class' }
62
+ ],
63
+ defaultProps: {
64
+ text: 'Loading...',
65
+ size: 'md',
66
+ fullscreen: false
67
+ }
68
+ }
69
+ );
@@ -0,0 +1,20 @@
1
+ import { ComponentRegistry } from '@object-ui/core';
2
+ import type { ProgressSchema } from '@object-ui/types';
3
+ import { Progress } from '../../ui';
4
+
5
+ ComponentRegistry.register('progress',
6
+ ({ schema, className, ...props }: { schema: ProgressSchema; className?: string; [key: string]: any }) => (
7
+ <Progress value={schema.value} className={className} {...props} />
8
+ ),
9
+ {
10
+ label: 'Progress',
11
+ inputs: [
12
+ { name: 'value', type: 'number', label: 'Value', defaultValue: 0 },
13
+ { name: 'className', type: 'string', label: 'CSS Class' }
14
+ ],
15
+ defaultProps: {
16
+ value: 50,
17
+ className: 'w-full'
18
+ }
19
+ }
20
+ );
@@ -0,0 +1,22 @@
1
+ import { ComponentRegistry } from '@object-ui/core';
2
+ import type { SkeletonSchema } from '@object-ui/types';
3
+ import { Skeleton } from '../../ui';
4
+
5
+ ComponentRegistry.register('skeleton',
6
+ ({ schema, className, ...props }: { schema: SkeletonSchema; className?: string; [key: string]: any }) => (
7
+ <Skeleton className={className} {...props} style={{ width: schema.width, height: schema.height }} />
8
+ ),
9
+ {
10
+ label: 'Skeleton',
11
+ inputs: [
12
+ { name: 'width', type: 'string', label: 'Width' },
13
+ { name: 'height', type: 'string', label: 'Height' },
14
+ { name: 'className', type: 'string', label: 'CSS Class' }
15
+ ],
16
+ defaultProps: {
17
+ width: '100%',
18
+ height: '20px',
19
+ className: 'rounded-md'
20
+ }
21
+ }
22
+ );
@@ -0,0 +1,26 @@
1
+ import { ComponentRegistry } from '@object-ui/core';
2
+ import type { ToasterSchema } from '@object-ui/types';
3
+ import { Toaster as SonnerToaster } from '../../ui';
4
+ import { Toaster as DefaultToaster } from '../../ui';
5
+ // Note: In shadcn/ui typical setup, Toaster is exported from 'components/ui/toaster' and 'components/ui/sonner'.
6
+ // But in @object-ui/ui index.tsx, we need to check if they are exported.
7
+ // Assuming they are exported as Toaster and Sonner (or similar).
8
+ // Let's assume standard exports.
9
+
10
+ ComponentRegistry.register('toaster',
11
+ ({ schema }: { schema: ToasterSchema }) => {
12
+ if (schema.provider === 'sonner') {
13
+ return <SonnerToaster />;
14
+ }
15
+ return <DefaultToaster />;
16
+ },
17
+ {
18
+ label: 'Toaster',
19
+ inputs: [
20
+ { name: 'provider', type: 'enum', enum: ['default', 'sonner'], defaultValue: 'default', label: 'Provider' }
21
+ ],
22
+ defaultProps: {
23
+ provider: 'default'
24
+ }
25
+ }
26
+ );
@@ -0,0 +1,61 @@
1
+ import { ComponentRegistry } from '@object-ui/core';
2
+ import type { ButtonSchema } from '@object-ui/types';
3
+ import { Button } from '../../ui';
4
+ import { renderChildren } from '../../lib/utils';
5
+ import { forwardRef } from 'react';
6
+
7
+ const ButtonRenderer = forwardRef<HTMLButtonElement, { schema: ButtonSchema; [key: string]: any }>(
8
+ ({ schema, ...props }, ref) => {
9
+ // Extract designer-related props
10
+ const {
11
+ 'data-obj-id': dataObjId,
12
+ 'data-obj-type': dataObjType,
13
+ style,
14
+ ...buttonProps
15
+ } = props;
16
+
17
+ return (
18
+ <Button
19
+ ref={ref}
20
+ variant={schema.variant}
21
+ size={schema.size}
22
+ className={schema.className}
23
+ {...buttonProps}
24
+ // Apply designer props
25
+ {...{ 'data-obj-id': dataObjId, 'data-obj-type': dataObjType, style }}
26
+ >
27
+ {schema.label || renderChildren(schema.body)}
28
+ </Button>
29
+ );
30
+ }
31
+ );
32
+ ButtonRenderer.displayName = 'ButtonRenderer';
33
+
34
+ ComponentRegistry.register('button', ButtonRenderer,
35
+ {
36
+ label: 'Button',
37
+ inputs: [
38
+ { name: 'label', type: 'string', label: 'Label', defaultValue: 'Button' },
39
+ {
40
+ name: 'variant',
41
+ type: 'enum',
42
+ label: 'Variant',
43
+ enum: ['default', 'secondary', 'destructive', 'outline', 'ghost', 'link'],
44
+ defaultValue: 'default'
45
+ },
46
+ {
47
+ name: 'size',
48
+ type: 'enum',
49
+ label: 'Size',
50
+ enum: ['default', 'sm', 'lg', 'icon'],
51
+ defaultValue: 'default'
52
+ },
53
+ { name: 'className', type: 'string', label: 'CSS Class', advanced: true }
54
+ ],
55
+ defaultProps: {
56
+ label: 'Button',
57
+ variant: 'default',
58
+ size: 'default'
59
+ }
60
+ }
61
+ );
@@ -0,0 +1,25 @@
1
+ import { ComponentRegistry } from '@object-ui/core';
2
+ import type { CalendarSchema } from '@object-ui/types';
3
+ import { Calendar } from '../../ui';
4
+
5
+ ComponentRegistry.register('calendar',
6
+ ({ schema, className, ...props }: { schema: CalendarSchema; className?: string; [key: string]: any }) => (
7
+ <Calendar
8
+ mode={(schema.mode || "single") as any}
9
+ selected={(schema.value || schema.defaultValue) as any}
10
+ className={className}
11
+ {...props}
12
+ />
13
+ ),
14
+ {
15
+ label: 'Calendar',
16
+ inputs: [
17
+ { name: 'mode', type: 'enum', enum: ['default', 'single', 'multiple', 'range'], defaultValue: 'single', label: 'Mode' },
18
+ { name: 'className', type: 'string', label: 'CSS Class' }
19
+ ],
20
+ defaultProps: {
21
+ mode: 'single',
22
+ className: 'rounded-md border'
23
+ }
24
+ }
25
+ );
@@ -0,0 +1,41 @@
1
+ import { ComponentRegistry } from '@object-ui/core';
2
+ import type { CheckboxSchema } from '@object-ui/types';
3
+ import { Checkbox, Label } from '../../ui';
4
+
5
+ ComponentRegistry.register('checkbox',
6
+ ({ schema, className, ...props }: { schema: CheckboxSchema; className?: string; [key: string]: any }) => {
7
+ // Extract designer-related props
8
+ const {
9
+ 'data-obj-id': dataObjId,
10
+ 'data-obj-type': dataObjType,
11
+ style,
12
+ ...checkboxProps
13
+ } = props;
14
+
15
+ return (
16
+ <div
17
+ className={`flex items-center space-x-2 ${schema.wrapperClass || ''}`}
18
+ data-obj-id={dataObjId}
19
+ data-obj-type={dataObjType}
20
+ style={style}
21
+ >
22
+ <Checkbox id={schema.id} className={className} {...checkboxProps} />
23
+ <Label htmlFor={schema.id} className="text-sm font-medium leading-none peer-disabled:cursor-not-allowed peer-disabled:opacity-70">
24
+ {schema.label}
25
+ </Label>
26
+ </div>
27
+ );
28
+ },
29
+ {
30
+ label: 'Checkbox',
31
+ inputs: [
32
+ { name: 'label', type: 'string', label: 'Label', required: true },
33
+ { name: 'id', type: 'string', label: 'ID', required: true },
34
+ { name: 'checked', type: 'boolean', label: 'Checked' }
35
+ ],
36
+ defaultProps: {
37
+ label: 'Checkbox label',
38
+ id: 'checkbox-field' // Will be made unique by designer's ensureNodeIds
39
+ }
40
+ }
41
+ );