@object-ui/components 0.3.1 → 0.5.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 (299) hide show
  1. package/.turbo/turbo-build.log +47 -0
  2. package/README.md +13 -0
  3. package/dist/index.css +1 -1
  4. package/dist/index.js +34610 -24854
  5. package/dist/index.umd.cjs +53 -32
  6. package/dist/src/SchemaRenderer.d.ts +3 -0
  7. package/dist/src/{ui → custom}/button-group.d.ts +1 -1
  8. package/dist/src/custom/field.d.ts +19 -0
  9. package/dist/src/custom/index.d.ts +12 -0
  10. package/dist/src/custom/input-group.d.ts +14 -0
  11. package/dist/src/{ui → custom}/item.d.ts +1 -1
  12. package/dist/src/custom/native-select.d.ts +12 -0
  13. package/dist/src/custom/sort-builder.d.ts +22 -0
  14. package/dist/src/index.d.ts +1 -0
  15. package/dist/src/renderers/data-display/table.d.ts +1 -1
  16. package/dist/src/renderers/layout/page.d.ts +1 -1
  17. package/dist/src/renderers/placeholders.d.ts +1 -1
  18. package/dist/src/ui/accordion.d.ts +4 -4
  19. package/dist/src/ui/alert-dialog.d.ts +17 -11
  20. package/dist/src/ui/alert.d.ts +4 -5
  21. package/dist/src/ui/aspect-ratio.d.ts +1 -1
  22. package/dist/src/ui/avatar.d.ts +3 -3
  23. package/dist/src/ui/badge.d.ts +3 -3
  24. package/dist/src/ui/breadcrumb.d.ts +16 -8
  25. package/dist/src/ui/calendar.d.ts +7 -7
  26. package/dist/src/ui/card.d.ts +7 -8
  27. package/dist/src/ui/carousel.d.ts +5 -6
  28. package/dist/src/ui/chart.d.ts +62 -0
  29. package/dist/src/ui/checkbox.d.ts +1 -1
  30. package/dist/src/ui/collapsible.d.ts +3 -3
  31. package/dist/src/ui/command.d.ts +78 -16
  32. package/dist/src/ui/context-menu.d.ts +14 -12
  33. package/dist/src/ui/dialog.d.ts +17 -13
  34. package/dist/src/ui/drawer.d.ts +19 -10
  35. package/dist/src/ui/dropdown-menu.d.ts +20 -18
  36. package/dist/src/ui/form.d.ts +6 -7
  37. package/dist/src/ui/hover-card.d.ts +3 -3
  38. package/dist/src/ui/index.d.ts +2 -8
  39. package/dist/src/ui/input-otp.d.ts +30 -7
  40. package/dist/src/ui/label.d.ts +2 -1
  41. package/dist/src/ui/menubar.d.ts +19 -17
  42. package/dist/src/ui/navigation-menu.d.ts +9 -11
  43. package/dist/src/ui/pagination.d.ts +25 -10
  44. package/dist/src/ui/popover.d.ts +4 -5
  45. package/dist/src/ui/progress.d.ts +1 -1
  46. package/dist/src/ui/radio-group.d.ts +2 -2
  47. package/dist/src/ui/resizable.d.ts +5 -8
  48. package/dist/src/ui/scroll-area.d.ts +2 -2
  49. package/dist/src/ui/select.d.ts +11 -13
  50. package/dist/src/ui/sheet.d.ts +23 -11
  51. package/dist/src/ui/sidebar.d.ts +27 -29
  52. package/dist/src/ui/skeleton.d.ts +1 -1
  53. package/dist/src/ui/slider.d.ts +1 -1
  54. package/dist/src/ui/sonner.d.ts +2 -1
  55. package/dist/src/ui/switch.d.ts +2 -2
  56. package/dist/src/ui/tabs.d.ts +1 -1
  57. package/dist/src/ui/textarea.d.ts +1 -1
  58. package/dist/src/ui/toast.d.ts +22 -0
  59. package/dist/src/ui/toggle-group.d.ts +8 -3
  60. package/dist/src/ui/toggle.d.ts +4 -1
  61. package/dist/src/ui/tooltip.d.ts +4 -4
  62. package/dist/src/ui/typography.d.ts +21 -0
  63. package/package.json +17 -7
  64. package/shadcn-components.json +52 -47
  65. package/src/SchemaRenderer.tsx +28 -0
  66. package/src/__tests__/PageRendererRegions.test.tsx +59 -0
  67. package/src/__tests__/Registry.test.ts +21 -0
  68. package/src/__tests__/basic-renderers.test.tsx +1 -1
  69. package/src/__tests__/complex-disclosure-renderers.test.tsx +3 -2
  70. package/src/__tests__/feedback-overlay-renderers.test.tsx +1 -1
  71. package/src/__tests__/form-renderers.test.tsx +1 -1
  72. package/src/__tests__/layout-data-renderers.test.tsx +1 -1
  73. package/src/{ui → custom}/button-group.tsx +1 -1
  74. package/src/{ui → custom}/combobox.tsx +3 -3
  75. package/src/{ui → custom}/date-picker.tsx +3 -3
  76. package/src/custom/field.tsx +81 -0
  77. package/src/{ui → custom}/filter-builder.tsx +3 -3
  78. package/src/custom/index.ts +12 -0
  79. package/src/custom/input-group.tsx +53 -0
  80. package/src/{ui → custom}/item.tsx +1 -1
  81. package/src/custom/native-select.tsx +33 -0
  82. package/src/custom/sort-builder.tsx +129 -0
  83. package/src/index.css +20 -1
  84. package/src/index.ts +1 -0
  85. package/src/renderers/basic/button-group.tsx +1 -0
  86. package/src/renderers/basic/div.tsx +12 -1
  87. package/src/renderers/basic/html.tsx +1 -0
  88. package/src/renderers/basic/icon.tsx +1 -0
  89. package/src/renderers/basic/image.tsx +1 -0
  90. package/src/renderers/basic/navigation-menu.tsx +1 -0
  91. package/src/renderers/basic/pagination.tsx +31 -4
  92. package/src/renderers/basic/separator.tsx +1 -0
  93. package/src/renderers/basic/span.tsx +12 -1
  94. package/src/renderers/basic/text.tsx +4 -2
  95. package/src/renderers/complex/carousel.tsx +1 -0
  96. package/src/renderers/complex/data-table.tsx +134 -95
  97. package/src/renderers/complex/filter-builder.tsx +2 -1
  98. package/src/renderers/complex/resizable.tsx +2 -1
  99. package/src/renderers/complex/scroll-area.tsx +25 -7
  100. package/src/renderers/complex/table.tsx +1 -0
  101. package/src/renderers/data-display/alert.tsx +1 -0
  102. package/src/renderers/data-display/avatar.tsx +1 -0
  103. package/src/renderers/data-display/badge.tsx +1 -0
  104. package/src/renderers/data-display/breadcrumb.tsx +1 -0
  105. package/src/renderers/data-display/kbd.tsx +1 -0
  106. package/src/renderers/data-display/list.tsx +21 -49
  107. package/src/renderers/data-display/statistic.tsx +21 -5
  108. package/src/renderers/data-display/table.tsx +21 -11
  109. package/src/renderers/data-display/tree-view.tsx +7 -1
  110. package/src/renderers/disclosure/accordion.tsx +1 -0
  111. package/src/renderers/disclosure/collapsible.tsx +1 -0
  112. package/src/renderers/disclosure/toggle-group.tsx +2 -0
  113. package/src/renderers/feedback/empty.tsx +1 -0
  114. package/src/renderers/feedback/loading.tsx +2 -1
  115. package/src/renderers/feedback/progress.tsx +1 -0
  116. package/src/renderers/feedback/skeleton.tsx +1 -0
  117. package/src/renderers/feedback/sonner.tsx +1 -0
  118. package/src/renderers/feedback/spinner.tsx +1 -0
  119. package/src/renderers/feedback/toast.tsx +1 -0
  120. package/src/renderers/feedback/toaster.tsx +1 -0
  121. package/src/renderers/form/button.tsx +35 -1
  122. package/src/renderers/form/calendar.tsx +1 -0
  123. package/src/renderers/form/checkbox.tsx +38 -16
  124. package/src/renderers/form/combobox.tsx +2 -1
  125. package/src/renderers/form/command.tsx +1 -0
  126. package/src/renderers/form/date-picker.tsx +1 -0
  127. package/src/renderers/form/file-upload.tsx +1 -0
  128. package/src/renderers/form/form.tsx +92 -15
  129. package/src/renderers/form/input-otp.tsx +1 -0
  130. package/src/renderers/form/input.tsx +3 -0
  131. package/src/renderers/form/label.tsx +1 -0
  132. package/src/renderers/form/radio-group.tsx +1 -0
  133. package/src/renderers/form/select.tsx +35 -15
  134. package/src/renderers/form/slider.tsx +1 -0
  135. package/src/renderers/form/switch.tsx +1 -0
  136. package/src/renderers/form/textarea.tsx +50 -27
  137. package/src/renderers/form/toggle.tsx +3 -45
  138. package/src/renderers/layout/aspect-ratio.tsx +2 -1
  139. package/src/renderers/layout/card.tsx +10 -2
  140. package/src/renderers/layout/container.tsx +1 -0
  141. package/src/renderers/layout/flex.tsx +1 -0
  142. package/src/renderers/layout/grid.tsx +23 -8
  143. package/src/renderers/layout/page.tsx +35 -23
  144. package/src/renderers/layout/semantic.tsx +1 -0
  145. package/src/renderers/layout/stack.tsx +2 -1
  146. package/src/renderers/layout/tabs.tsx +43 -17
  147. package/src/renderers/navigation/header-bar.tsx +1 -0
  148. package/src/renderers/navigation/sidebar.tsx +5 -0
  149. package/src/renderers/overlay/alert-dialog.tsx +1 -0
  150. package/src/renderers/overlay/context-menu.tsx +1 -0
  151. package/src/renderers/overlay/dialog.tsx +1 -0
  152. package/src/renderers/overlay/drawer.tsx +1 -0
  153. package/src/renderers/overlay/dropdown-menu.tsx +1 -0
  154. package/src/renderers/overlay/hover-card.tsx +1 -0
  155. package/src/renderers/overlay/menubar.tsx +1 -0
  156. package/src/renderers/overlay/popover.tsx +1 -0
  157. package/src/renderers/overlay/sheet.tsx +1 -0
  158. package/src/renderers/overlay/tooltip.tsx +1 -0
  159. package/src/renderers/placeholders.tsx +2 -2
  160. package/src/stories/CRMApp.stories.tsx +706 -0
  161. package/src/stories/Guide.mdx +55 -0
  162. package/src/stories/Introduction.mdx +34 -0
  163. package/src/stories/MockedData.stories.tsx +71 -0
  164. package/src/stories/assets/accessibility.png +0 -0
  165. package/src/stories/assets/accessibility.svg +1 -0
  166. package/src/stories/assets/addon-library.png +0 -0
  167. package/src/stories/assets/assets.png +0 -0
  168. package/src/stories/assets/avif-test-image.avif +0 -0
  169. package/src/stories/assets/context.png +0 -0
  170. package/src/stories/assets/discord.svg +1 -0
  171. package/src/stories/assets/docs.png +0 -0
  172. package/src/stories/assets/figma-plugin.png +0 -0
  173. package/src/stories/assets/github.svg +1 -0
  174. package/src/stories/assets/share.png +0 -0
  175. package/src/stories/assets/styling.png +0 -0
  176. package/src/stories/assets/testing.png +0 -0
  177. package/src/stories/assets/theming.png +0 -0
  178. package/src/stories/assets/tutorials.svg +1 -0
  179. package/src/stories/assets/youtube.svg +1 -0
  180. package/src/stories/button.css +30 -0
  181. package/src/stories/header.css +32 -0
  182. package/src/stories/page.css +68 -0
  183. package/src/stories-json/accordion.stories.tsx +43 -0
  184. package/src/stories-json/aggrid.stories.tsx +103 -0
  185. package/src/stories-json/alert.stories.tsx +39 -0
  186. package/src/stories-json/aspect-ratio.stories.tsx +34 -0
  187. package/src/stories-json/avatar.stories.tsx +38 -0
  188. package/src/stories-json/badge.stories.tsx +53 -0
  189. package/src/stories-json/breadcrumb.stories.tsx +30 -0
  190. package/src/stories-json/button-group.stories.tsx +43 -0
  191. package/src/stories-json/button.stories.tsx +73 -0
  192. package/src/stories-json/calendar.stories.tsx +85 -0
  193. package/src/stories-json/card.stories.tsx +48 -0
  194. package/src/stories-json/carousel.stories.tsx +33 -0
  195. package/src/stories-json/charts.stories.tsx +195 -0
  196. package/src/stories-json/chatbot.stories.tsx +248 -0
  197. package/src/stories-json/code-editor.stories.tsx +92 -0
  198. package/src/stories-json/collapsible.stories.tsx +40 -0
  199. package/src/stories-json/controls.stories.tsx +36 -0
  200. package/src/stories-json/dashboard.stories.tsx +318 -0
  201. package/src/stories-json/data-table.stories.tsx +60 -0
  202. package/src/stories-json/data_display_extras.stories.tsx +102 -0
  203. package/src/stories-json/date-picker.stories.tsx +28 -0
  204. package/src/stories-json/detail-view.stories.tsx +258 -0
  205. package/src/stories-json/dialog.stories.tsx +43 -0
  206. package/src/stories-json/feedback_extras.stories.tsx +40 -0
  207. package/src/stories-json/feedback_others.stories.tsx +46 -0
  208. package/src/stories-json/form_advanced.stories.tsx +117 -0
  209. package/src/stories-json/form_extras.stories.tsx +123 -0
  210. package/src/stories-json/grid.stories.tsx +56 -0
  211. package/src/stories-json/icon.stories.tsx +36 -0
  212. package/src/stories-json/input.stories.tsx +52 -0
  213. package/src/stories-json/kanban.stories.tsx +295 -0
  214. package/src/stories-json/layout_extended.stories.tsx +76 -0
  215. package/src/stories-json/layout_flex.stories.tsx +107 -0
  216. package/src/stories-json/list-view.stories.tsx +97 -0
  217. package/src/stories-json/markdown.stories.tsx +129 -0
  218. package/src/stories-json/menus.stories.tsx +63 -0
  219. package/src/stories-json/metric-card.stories.tsx +143 -0
  220. package/src/stories-json/navigation-menu.stories.tsx +37 -0
  221. package/src/stories-json/object-aggrid.stories.tsx +252 -0
  222. package/src/stories-json/object-form.stories.tsx +130 -0
  223. package/src/stories-json/object-gantt.stories.tsx +114 -0
  224. package/src/stories-json/object-grid.stories.tsx +157 -0
  225. package/src/stories-json/object-map.stories.tsx +116 -0
  226. package/src/stories-json/object-view.stories.tsx +118 -0
  227. package/src/stories-json/overlay_extras.stories.tsx +113 -0
  228. package/src/stories-json/overlay_others.stories.tsx +76 -0
  229. package/src/stories-json/page.stories.tsx +55 -0
  230. package/src/stories-json/reports.stories.tsx +163 -0
  231. package/src/stories-json/resizable.stories.tsx +44 -0
  232. package/src/stories-json/select.stories.tsx +34 -0
  233. package/src/stories-json/separator.stories.tsx +41 -0
  234. package/src/stories-json/sidebar.stories.tsx +147 -0
  235. package/src/stories-json/statistic.stories.tsx +44 -0
  236. package/src/stories-json/tabs.stories.tsx +51 -0
  237. package/src/stories-json/timeline.stories.tsx +188 -0
  238. package/src/stories-json/typography.stories.tsx +45 -0
  239. package/src/ui/accordion.tsx +47 -53
  240. package/src/ui/alert-dialog.tsx +103 -117
  241. package/src/ui/alert.tsx +35 -36
  242. package/src/ui/aspect-ratio.tsx +1 -5
  243. package/src/ui/avatar.tsx +41 -42
  244. package/src/ui/badge.tsx +6 -15
  245. package/src/ui/breadcrumb.tsx +81 -75
  246. package/src/ui/button.tsx +10 -11
  247. package/src/ui/calendar.tsx +178 -51
  248. package/src/ui/card.tsx +51 -110
  249. package/src/ui/carousel.tsx +136 -113
  250. package/src/ui/chart.tsx +367 -0
  251. package/src/ui/checkbox.tsx +20 -22
  252. package/src/ui/collapsible.tsx +5 -25
  253. package/src/ui/command.tsx +106 -135
  254. package/src/ui/context-menu.tsx +69 -116
  255. package/src/ui/dialog.tsx +94 -113
  256. package/src/ui/drawer.tsx +82 -99
  257. package/src/ui/dropdown-menu.tsx +134 -188
  258. package/src/ui/form.tsx +51 -40
  259. package/src/ui/hover-card.tsx +18 -33
  260. package/src/ui/index.ts +2 -8
  261. package/src/ui/input-otp.tsx +42 -52
  262. package/src/ui/input.tsx +13 -15
  263. package/src/ui/label.tsx +17 -15
  264. package/src/ui/menubar.tsx +188 -206
  265. package/src/ui/navigation-menu.tsx +96 -136
  266. package/src/ui/pagination.tsx +86 -96
  267. package/src/ui/popover.tsx +24 -41
  268. package/src/ui/progress.tsx +21 -22
  269. package/src/ui/radio-group.tsx +19 -20
  270. package/src/ui/resizable.tsx +32 -42
  271. package/src/ui/scroll-area.tsx +38 -48
  272. package/src/ui/select.tsx +129 -157
  273. package/src/ui/separator.tsx +2 -2
  274. package/src/ui/sheet.tsx +110 -107
  275. package/src/ui/sidebar.tsx +442 -408
  276. package/src/ui/skeleton.tsx +6 -11
  277. package/src/ui/slider.tsx +19 -54
  278. package/src/ui/sonner.tsx +19 -1
  279. package/src/ui/switch.tsx +19 -21
  280. package/src/ui/tabs.tsx +6 -37
  281. package/src/ui/textarea.tsx +8 -4
  282. package/src/ui/toast.tsx +137 -0
  283. package/src/ui/toggle-group.tsx +28 -37
  284. package/src/ui/toggle.tsx +19 -19
  285. package/src/ui/tooltip.tsx +21 -52
  286. package/src/ui/typography.tsx +85 -0
  287. package/tsconfig.json +1 -1
  288. package/vite.config.ts +9 -1
  289. package/vitest.config.ts +5 -0
  290. package/ISSUES_FOUND.md +0 -128
  291. /package/dist/src/{ui → custom}/combobox.d.ts +0 -0
  292. /package/dist/src/{ui → custom}/date-picker.d.ts +0 -0
  293. /package/dist/src/{ui → custom}/empty.d.ts +0 -0
  294. /package/dist/src/{ui → custom}/filter-builder.d.ts +0 -0
  295. /package/dist/src/{ui → custom}/kbd.d.ts +0 -0
  296. /package/dist/src/{ui → custom}/spinner.d.ts +0 -0
  297. /package/src/{ui → custom}/empty.tsx +0 -0
  298. /package/src/{ui → custom}/kbd.tsx +0 -0
  299. /package/src/{ui → custom}/spinner.tsx +0 -0
@@ -8,69 +8,40 @@
8
8
 
9
9
  import { ComponentRegistry } from '@object-ui/core';
10
10
  import type { ListSchema } from '@object-ui/types';
11
- import { renderChildren } from '../../lib/utils';
12
- import { cn } from '../../lib/utils';
13
- import { ChevronRight, Hexagon, Terminal } from 'lucide-react';
11
+ import { useDataScope } from '@object-ui/react';
12
+ import { renderChildren, cn } from '../../lib/utils';
14
13
 
15
14
  ComponentRegistry.register('list',
16
15
  ({ schema, className, ...props }: { schema: ListSchema; className?: string; [key: string]: any }) => {
17
- // We use 'ul' for both to control semantics manually with visuals
18
- const ListTag = 'ul';
16
+ // Support data binding
17
+ const boundData = useDataScope(schema.bind);
18
+ const items = boundData || schema.items || [];
19
19
 
20
- return (
21
- <div className={cn("relative p-4 rounded-lg bg-slate-950/30 border border-slate-800/50 backdrop-blur-sm", schema.wrapperClass)}>
22
- {/* Decorative corner accents for container */}
23
- <div className="absolute top-0 left-0 w-2 h-2 border-l-2 border-t-2 border-cyan-500/50 rounded-tl-sm" />
24
- <div className="absolute top-0 right-0 w-2 h-2 border-r-2 border-t-2 border-cyan-500/50 rounded-tr-sm" />
25
- <div className="absolute bottom-0 left-0 w-2 h-2 border-l-2 border-b-2 border-cyan-500/50 rounded-bl-sm" />
26
- <div className="absolute bottom-0 right-0 w-2 h-2 border-r-2 border-b-2 border-cyan-500/50 rounded-br-sm" />
20
+ // We use 'ol' or 'ul' based on ordered prop
21
+ const ListTag = schema.ordered ? 'ol' : 'ul';
22
+
23
+ // Default styles for ordered/unordered
24
+ const listStyle = schema.ordered ? "list-decimal" : "list-disc";
27
25
 
26
+ return (
27
+ <div className={cn("space-y-2", schema.wrapperClass)}>
28
28
  {schema.title && (
29
- <div className="flex items-center gap-2 mb-4 pb-2 border-b border-cyan-900/30">
30
- <Terminal className="w-4 h-4 text-cyan-500" />
31
- <h3 className="text-sm font-bold uppercase tracking-widest text-cyan-400 drop-shadow-[0_0_5px_rgba(6,182,212,0.5)]">
32
- {schema.title}
33
- </h3>
34
- </div>
29
+ <h3 className="text-lg font-semibold tracking-tight">
30
+ {schema.title}
31
+ </h3>
35
32
  )}
36
33
 
37
34
  <ListTag
38
35
  className={cn(
39
- "space-y-1",
36
+ "ml-6 [&>li]:mt-2",
37
+ listStyle,
40
38
  className
41
39
  )}
42
40
  {...props}
43
41
  >
44
- {schema.items?.map((item: any, index: number) => (
45
- <li
46
- key={index}
47
- className={cn(
48
- "group flex items-start gap-3 p-2 rounded-sm transition-all duration-300",
49
- "hover:bg-cyan-950/20 hover:pl-3",
50
- typeof item === 'object' && item.className
51
- )}
52
- >
53
- {/* Marker Area */}
54
- <div className="flex-shrink-0 mt-0.5">
55
- {schema.ordered ? (
56
- <span className="flex items-center justify-center w-5 h-5 text-[10px] font-mono font-bold text-slate-950 bg-cyan-600 rounded-sm shadow-[0_0_8px_cyan] group-hover:bg-cyan-400 group-hover:scale-110 transition-all">
57
- {String(index + 1).padStart(2, '0')}
58
- </span>
59
- ) : (
60
- <div className="relative flex items-center justify-center w-5 h-5">
61
- <Hexagon className="w-3 h-3 text-cyan-600 group-hover:text-cyan-400 group-hover:rotate-90 transition-transform duration-500" />
62
- <div className="absolute inset-0 bg-cyan-500/20 blur-[2px] rounded-full opacity-0 group-hover:opacity-100 transition-opacity" />
63
- </div>
64
- )}
65
- </div>
66
-
67
- {/* Content Area */}
68
- <div className="flex-1 text-sm text-slate-400 group-hover:text-cyan-100 font-medium font-sans leading-tight transition-colors">
69
- {typeof item === 'string' ? item : item.content || renderChildren(item.body)}
70
- </div>
71
-
72
- {/* Hover Indicator */}
73
- <ChevronRight className="w-4 h-4 text-cyan-500/0 -translate-x-2 group-hover:text-cyan-500 group-hover:translate-x-0 transition-all duration-300 opacity-0 group-hover:opacity-100" />
42
+ {items.map((item: any, index: number) => (
43
+ <li key={index} className={cn(typeof item === 'object' && item.className)}>
44
+ {typeof item === 'string' ? item : item.content || renderChildren(item.body)}
74
45
  </li>
75
46
  ))}
76
47
  </ListTag>
@@ -78,6 +49,7 @@ ComponentRegistry.register('list',
78
49
  );
79
50
  },
80
51
  {
52
+ namespace: 'ui',
81
53
  label: 'List',
82
54
  inputs: [
83
55
  { name: 'title', type: 'string', label: 'Title' },
@@ -10,21 +10,36 @@ import { ComponentRegistry } from '@object-ui/core';
10
10
  import type { StatisticSchema } from '@object-ui/types';
11
11
  import { cn } from '../../lib/utils';
12
12
  import { TrendingUp, TrendingDown, Minus } from 'lucide-react';
13
+ import * as LucideIcons from 'lucide-react';
14
+
15
+ // Helper to resolve icon
16
+ const getIcon = (name: string) => {
17
+ if (!name) return null;
18
+ const pascalName = name.split('-').map(part => part.charAt(0).toUpperCase() + part.slice(1)).join('');
19
+ // Dynamic icon lookup from Lucide
20
+ const Icon = LucideIcons[pascalName] || LucideIcons[name];
21
+ return Icon;
22
+ };
13
23
 
14
24
  const StatisticRenderer = ({ schema }: { schema: StatisticSchema }) => {
25
+ const Icon = schema.icon ? getIcon(schema.icon) : null;
26
+
15
27
  return (
16
28
  <div className={cn(
17
29
  "group relative flex flex-col p-4 sm:p-5 md:p-6 rounded-xl border bg-card text-card-foreground shadow-sm",
18
30
  schema.className
19
31
  )}>
20
- {/* Label */}
21
- {schema.label && (
22
- <div className="flex items-center gap-2 mb-2">
32
+ {/* Label & Header Icon */}
33
+ <div className="flex items-center justify-between mb-2">
34
+ {schema.label && (
23
35
  <p className="text-sm font-medium text-muted-foreground">
24
36
  {schema.label}
25
37
  </p>
26
- </div>
27
- )}
38
+ )}
39
+ {/* Dynamic icon resolution from Lucide, not component creation during render */}
40
+ {/* eslint-disable-next-line */}
41
+ {Icon && <Icon className="h-4 w-4 text-muted-foreground" />}
42
+ </div>
28
43
 
29
44
  {/* Value Area */}
30
45
  <div className="flex items-baseline gap-2">
@@ -52,6 +67,7 @@ const StatisticRenderer = ({ schema }: { schema: StatisticSchema }) => {
52
67
  };
53
68
 
54
69
  ComponentRegistry.register('statistic', StatisticRenderer, {
70
+ namespace: 'ui',
55
71
  label: 'Statistic',
56
72
  category: 'data-display',
57
73
  icon: 'Activity',
@@ -19,9 +19,11 @@ import {
19
19
  } from '../../ui/table';
20
20
  import { cn } from '../../lib/utils';
21
21
 
22
- export const SimpleTableRenderer = ({ schema, className, ..._props }: any) => {
23
- const data = useDataScope(schema.bind);
24
- const columns = schema.props?.columns || [];
22
+ export const SimpleTableRenderer = ({ schema, className }: any) => {
23
+ // Try to get data from binding first, then fall back to inline data
24
+ const boundData = useDataScope(schema.bind);
25
+ const data = boundData || schema.data || schema.props?.data || [];
26
+ const columns = schema.columns || schema.props?.columns || [];
25
27
 
26
28
  // If we have data but it's not an array, show error.
27
29
  // If data is undefined, we might just be loading or empty.
@@ -36,8 +38,10 @@ export const SimpleTableRenderer = ({ schema, className, ..._props }: any) => {
36
38
  <Table>
37
39
  <TableHeader>
38
40
  <TableRow>
39
- {columns.map((col: any) => (
40
- <TableHead key={col.key}>{col.label}</TableHead>
41
+ {columns.map((col: any, index: number) => (
42
+ <TableHead key={col.key || col.accessorKey || index}>
43
+ {col.label || col.header}
44
+ </TableHead>
41
45
  ))}
42
46
  </TableRow>
43
47
  </TableHeader>
@@ -51,11 +55,15 @@ export const SimpleTableRenderer = ({ schema, className, ..._props }: any) => {
51
55
  ) : (
52
56
  displayData.map((row: any, i: number) => (
53
57
  <TableRow key={row.id || i}>
54
- {columns.map((col: any) => (
55
- <TableCell key={col.key}>
56
- {row[col.key]}
57
- </TableCell>
58
- ))}
58
+ {columns.map((col: any, index: number) => {
59
+ const accessor = col.key || col.accessorKey || '';
60
+ const value = accessor ? row[accessor] : '';
61
+ return (
62
+ <TableCell key={col.key || col.accessorKey || index}>
63
+ {value}
64
+ </TableCell>
65
+ );
66
+ })}
59
67
  </TableRow>
60
68
  ))
61
69
  )}
@@ -65,4 +73,6 @@ export const SimpleTableRenderer = ({ schema, className, ..._props }: any) => {
65
73
  );
66
74
  };
67
75
 
68
- ComponentRegistry.register('table', SimpleTableRenderer);
76
+ ComponentRegistry.register('table', SimpleTableRenderer, {
77
+ namespace: 'ui'
78
+ });
@@ -11,6 +11,7 @@ import type { TreeViewSchema, TreeNode } from '@object-ui/types';
11
11
  import { ChevronRight, ChevronDown, Folder, File, FolderOpen, CircuitBoard } from 'lucide-react';
12
12
  import { useState } from 'react';
13
13
  import { cn } from '../../lib/utils';
14
+ import { useDataScope } from '@object-ui/react';
14
15
 
15
16
  const TreeNodeComponent = ({
16
17
  node,
@@ -99,6 +100,10 @@ ComponentRegistry.register('tree-view',
99
100
  }
100
101
  };
101
102
 
103
+ // Support data binding
104
+ const boundData = useDataScope(schema.bind);
105
+ const nodes = boundData || schema.nodes || schema.data || [];
106
+
102
107
  return (
103
108
  <div className={cn(
104
109
  'relative border rounded-lg p-3 bg-card text-card-foreground',
@@ -112,7 +117,7 @@ ComponentRegistry.register('tree-view',
112
117
  </div>
113
118
  )}
114
119
  <div className="space-y-1">
115
- {(schema.nodes || schema.data)?.map((node: TreeNode) => (
120
+ {nodes.map((node: TreeNode) => (
116
121
  <TreeNodeComponent
117
122
  key={node.id}
118
123
  node={node}
@@ -124,6 +129,7 @@ ComponentRegistry.register('tree-view',
124
129
  );
125
130
  },
126
131
  {
132
+ namespace: 'ui',
127
133
  label: 'Tree View',
128
134
  inputs: [
129
135
  { name: 'title', type: 'string', label: 'Title' },
@@ -30,6 +30,7 @@ ComponentRegistry.register('accordion',
30
30
  </Accordion>
31
31
  ),
32
32
  {
33
+ namespace: 'ui',
33
34
  label: 'Accordion',
34
35
  inputs: [
35
36
  { name: 'accordionType', type: 'enum', enum: ['single', 'multiple'], defaultValue: 'single', label: 'Type' },
@@ -27,6 +27,7 @@ ComponentRegistry.register('collapsible',
27
27
  </Collapsible>
28
28
  ),
29
29
  {
30
+ namespace: 'ui',
30
31
  label: 'Collapsible',
31
32
  inputs: [
32
33
  { name: 'defaultOpen', type: 'boolean', label: 'Default Open' },
@@ -16,6 +16,7 @@ ComponentRegistry.register('toggle-group',
16
16
  'data-obj-id': dataObjId,
17
17
  'data-obj-type': dataObjType,
18
18
  style,
19
+ type, // Extract type to prevent overriding the one we set below
19
20
  ...toggleGroupProps
20
21
  } = props;
21
22
 
@@ -38,6 +39,7 @@ ComponentRegistry.register('toggle-group',
38
39
  );
39
40
  },
40
41
  {
42
+ namespace: 'ui',
41
43
  label: 'Toggle Group',
42
44
  inputs: [
43
45
  {
@@ -35,6 +35,7 @@ ComponentRegistry.register('empty',
35
35
  );
36
36
  },
37
37
  {
38
+ namespace: 'ui',
38
39
  label: 'Empty',
39
40
  inputs: [
40
41
  { name: 'title', type: 'string', label: 'Title', defaultValue: 'No data' },
@@ -8,7 +8,7 @@
8
8
 
9
9
  import { ComponentRegistry } from '@object-ui/core';
10
10
  import type { LoadingSchema } from '@object-ui/types';
11
- import { Spinner } from '../../ui';
11
+ import { Spinner } from '../../custom';
12
12
  import { cn } from '../../lib/utils';
13
13
 
14
14
  ComponentRegistry.register('loading',
@@ -50,6 +50,7 @@ ComponentRegistry.register('loading',
50
50
  );
51
51
  },
52
52
  {
53
+ namespace: 'ui',
53
54
  label: 'Loading',
54
55
  inputs: [
55
56
  { name: 'text', type: 'string', label: 'Loading Text' },
@@ -15,6 +15,7 @@ ComponentRegistry.register('progress',
15
15
  <Progress value={schema.value} className={className} {...props} />
16
16
  ),
17
17
  {
18
+ namespace: 'ui',
18
19
  label: 'Progress',
19
20
  inputs: [
20
21
  { name: 'value', type: 'number', label: 'Value', defaultValue: 0 },
@@ -15,6 +15,7 @@ ComponentRegistry.register('skeleton',
15
15
  <Skeleton className={className} {...props} style={{ width: schema.width, height: schema.height }} />
16
16
  ),
17
17
  {
18
+ namespace: 'ui',
18
19
  label: 'Skeleton',
19
20
  inputs: [
20
21
  { name: 'width', type: 'string', label: 'Width' },
@@ -32,6 +32,7 @@ ComponentRegistry.register('sonner',
32
32
  );
33
33
  },
34
34
  {
35
+ namespace: 'ui',
35
36
  label: 'Sonner Toast',
36
37
  inputs: [
37
38
  { name: 'message', type: 'string', label: 'Message' },
@@ -36,6 +36,7 @@ ComponentRegistry.register('spinner',
36
36
  );
37
37
  },
38
38
  {
39
+ namespace: 'ui',
39
40
  label: 'Spinner',
40
41
  inputs: [
41
42
  {
@@ -33,6 +33,7 @@ ComponentRegistry.register('toast',
33
33
  );
34
34
  },
35
35
  {
36
+ namespace: 'ui',
36
37
  label: 'Toast',
37
38
  inputs: [
38
39
  { name: 'title', type: 'string', label: 'Title' },
@@ -15,6 +15,7 @@ ComponentRegistry.register('toaster',
15
15
  return <SonnerToaster />;
16
16
  },
17
17
  {
18
+ namespace: 'ui',
18
19
  label: 'Toaster',
19
20
  inputs: [],
20
21
  defaultProps: {}
@@ -11,6 +11,20 @@ import type { ButtonSchema } from '@object-ui/types';
11
11
  import { Button } from '../../ui';
12
12
  import { renderChildren } from '../../lib/utils';
13
13
  import { forwardRef } from 'react';
14
+ import { Loader2, icons, type LucideIcon } from 'lucide-react';
15
+
16
+ // Helper to convert icon names to PascalCase (e.g., "arrow-right" -> "ArrowRight")
17
+ function toPascalCase(str: string): string {
18
+ return str
19
+ .split('-')
20
+ .map(word => word.charAt(0).toUpperCase() + word.slice(1))
21
+ .join('');
22
+ }
23
+
24
+ // Map of renamed icons in lucide-react
25
+ const iconNameMap: Record<string, string> = {
26
+ 'Home': 'House',
27
+ };
14
28
 
15
29
  const ButtonRenderer = forwardRef<HTMLButtonElement, { schema: ButtonSchema; [key: string]: any }>(
16
30
  ({ schema, ...props }, ref) => {
@@ -22,17 +36,36 @@ const ButtonRenderer = forwardRef<HTMLButtonElement, { schema: ButtonSchema; [ke
22
36
  ...buttonProps
23
37
  } = props;
24
38
 
39
+ // Resolve icon
40
+ let Icon: LucideIcon | null = null;
41
+ if (schema.icon) {
42
+ const iconName = toPascalCase(schema.icon);
43
+ const mappedIconName = iconNameMap[iconName] || iconName;
44
+ Icon = (icons as any)[mappedIconName] as LucideIcon;
45
+ }
46
+
47
+ // Determine loading state
48
+ const isLoading = schema.loading || props.loading;
49
+
50
+ // Determine disabled state
51
+ const isDisabled = schema.disabled || props.disabled || isLoading;
52
+
25
53
  return (
26
54
  <Button
27
55
  ref={ref}
56
+ type={schema.buttonType || "button"}
28
57
  variant={schema.variant}
29
58
  size={schema.size}
30
59
  className={schema.className}
60
+ disabled={isDisabled}
31
61
  {...buttonProps}
32
62
  // Apply designer props
33
63
  {...{ 'data-obj-id': dataObjId, 'data-obj-type': dataObjType, style }}
34
64
  >
35
- {schema.label || renderChildren(schema.body)}
65
+ {isLoading && <Loader2 className="mr-2 h-4 w-4 animate-spin" />}
66
+ {!isLoading && Icon && schema.iconPosition !== 'right' && <Icon className="mr-2 h-4 w-4" />}
67
+ {schema.label || renderChildren(schema.body || schema.children)}
68
+ {!isLoading && Icon && schema.iconPosition === 'right' && <Icon className="ml-2 h-4 w-4" />}
36
69
  </Button>
37
70
  );
38
71
  }
@@ -41,6 +74,7 @@ ButtonRenderer.displayName = 'ButtonRenderer';
41
74
 
42
75
  ComponentRegistry.register('button', ButtonRenderer,
43
76
  {
77
+ namespace: 'ui',
44
78
  label: 'Button',
45
79
  inputs: [
46
80
  { name: 'label', type: 'string', label: 'Label', defaultValue: 'Button' },
@@ -20,6 +20,7 @@ ComponentRegistry.register('calendar',
20
20
  />
21
21
  ),
22
22
  {
23
+ namespace: 'ui',
23
24
  label: 'Calendar',
24
25
  inputs: [
25
26
  { name: 'mode', type: 'enum', enum: ['default', 'single', 'multiple', 'range'], defaultValue: 'single', label: 'Mode' },
@@ -9,41 +9,63 @@
9
9
  import { ComponentRegistry } from '@object-ui/core';
10
10
  import type { CheckboxSchema } from '@object-ui/types';
11
11
  import { Checkbox, Label } from '../../ui';
12
+ import { cn } from '../../lib/utils';
13
+ import React from 'react';
12
14
 
13
- ComponentRegistry.register('checkbox',
14
- ({ schema, className, ...props }: { schema: CheckboxSchema; className?: string; [key: string]: any }) => {
15
- // Extract designer-related props
16
- const {
17
- 'data-obj-id': dataObjId,
18
- 'data-obj-type': dataObjType,
19
- style,
20
- ...checkboxProps
21
- } = props;
15
+ const CheckboxRenderer = ({ schema, className, onChange, value, ...props }: { schema: CheckboxSchema; className?: string; onChange?: (val: any) => void; value?: any; [key: string]: any }) => {
16
+ // Extract designer-related props
17
+ const {
18
+ 'data-obj-id': dataObjId,
19
+ 'data-obj-type': dataObjType,
20
+ style,
21
+ ...checkboxProps
22
+ } = props;
22
23
 
23
- return (
24
+ const handleCheckedChange = (checked: boolean) => {
25
+ if (onChange) {
26
+ onChange(checked);
27
+ }
28
+ };
29
+
30
+ return (
24
31
  <div
25
- className={`flex items-center space-x-2 ${schema.wrapperClass || ''}`}
32
+ className={cn("flex items-center space-x-2", schema.wrapperClass)}
26
33
  data-obj-id={dataObjId}
27
34
  data-obj-type={dataObjType}
28
35
  style={style}
29
36
  >
30
- <Checkbox id={schema.id} className={className} {...checkboxProps} />
31
- <Label htmlFor={schema.id} className="text-sm font-medium leading-none peer-disabled:cursor-not-allowed peer-disabled:opacity-70">
37
+ <Checkbox
38
+ id={schema.id}
39
+ className={className}
40
+ checked={value ?? schema.checked ?? false}
41
+ defaultChecked={value === undefined ? schema.defaultChecked : undefined}
42
+ onCheckedChange={handleCheckedChange}
43
+ disabled={schema.disabled}
44
+ required={schema.required}
45
+ name={schema.name}
46
+ {...checkboxProps}
47
+ />
48
+ <Label htmlFor={schema.id} className={cn("text-sm font-medium leading-none peer-disabled:cursor-not-allowed peer-disabled:opacity-70", schema.required && "text-destructive after:content-['*'] after:ml-0.5")}>
32
49
  {schema.label}
33
50
  </Label>
34
51
  </div>
35
52
  );
36
- },
53
+ };
54
+
55
+ ComponentRegistry.register('checkbox', CheckboxRenderer,
37
56
  {
57
+ namespace: 'ui',
38
58
  label: 'Checkbox',
39
59
  inputs: [
40
60
  { name: 'label', type: 'string', label: 'Label', required: true },
41
61
  { name: 'id', type: 'string', label: 'ID', required: true },
42
- { name: 'checked', type: 'boolean', label: 'Checked' }
62
+ { name: 'checked', type: 'boolean', label: 'Checked' },
63
+ { name: 'required', type: 'boolean', label: 'Required' },
64
+ { name: 'disabled', type: 'boolean', label: 'Disabled' }
43
65
  ],
44
66
  defaultProps: {
45
67
  label: 'Checkbox label',
46
- id: 'checkbox-field' // Will be made unique by designer's ensureNodeIds
68
+ id: 'checkbox-field'
47
69
  }
48
70
  }
49
71
  );
@@ -8,7 +8,7 @@
8
8
 
9
9
  import { ComponentRegistry } from '@object-ui/core';
10
10
  import type { ComboboxSchema } from '@object-ui/types';
11
- import { Combobox } from '../../ui';
11
+ import { Combobox } from '../../custom';
12
12
 
13
13
  ComponentRegistry.register('combobox',
14
14
  ({ schema, ...props }: { schema: ComboboxSchema; [key: string]: any }) => {
@@ -32,6 +32,7 @@ ComponentRegistry.register('combobox',
32
32
  );
33
33
  },
34
34
  {
35
+ namespace: 'ui',
35
36
  label: 'Combobox',
36
37
  inputs: [
37
38
  { name: 'placeholder', type: 'string', label: 'Placeholder' },
@@ -42,6 +42,7 @@ ComponentRegistry.register('command',
42
42
  );
43
43
  },
44
44
  {
45
+ namespace: 'ui',
45
46
  label: 'Command',
46
47
  inputs: [
47
48
  { name: 'placeholder', type: 'string', label: 'Placeholder' },
@@ -66,6 +66,7 @@ ComponentRegistry.register('date-picker',
66
66
  );
67
67
  },
68
68
  {
69
+ namespace: 'ui',
69
70
  label: 'Date Picker',
70
71
  inputs: [
71
72
  { name: 'label', type: 'string', label: 'Label' },
@@ -165,6 +165,7 @@ ComponentRegistry.register('file-upload',
165
165
  );
166
166
  },
167
167
  {
168
+ namespace: 'ui',
168
169
  label: 'File Upload',
169
170
  inputs: [
170
171
  { name: 'label', type: 'string', label: 'Label' },