@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
@@ -33,6 +33,7 @@ ComponentRegistry.register('image',
33
33
  );
34
34
  },
35
35
  {
36
+ namespace: 'ui',
36
37
  label: 'Image',
37
38
  icon: 'image',
38
39
  category: 'basic',
@@ -66,6 +66,7 @@ ComponentRegistry.register('navigation-menu',
66
66
  );
67
67
  },
68
68
  {
69
+ namespace: 'ui',
69
70
  label: 'Navigation Menu',
70
71
  inputs: [
71
72
  { name: 'className', type: 'string', label: 'CSS Class' }
@@ -9,6 +9,7 @@
9
9
  import { ComponentRegistry } from '@object-ui/core';
10
10
  import type { PaginationSchema } from '@object-ui/types';
11
11
  import { Pagination, PaginationContent, PaginationEllipsis, PaginationItem, PaginationLink, PaginationNext, PaginationPrevious } from '../../ui/pagination';
12
+ import React from 'react';
12
13
 
13
14
  ComponentRegistry.register('pagination',
14
15
  ({ schema, ...props }: { schema: PaginationSchema; [key: string]: any }) => {
@@ -16,13 +17,23 @@ ComponentRegistry.register('pagination',
16
17
  'data-obj-id': dataObjId,
17
18
  'data-obj-type': dataObjType,
18
19
  style,
20
+ onPageChange,
19
21
  ...paginationProps
20
22
  } = props;
21
23
 
22
24
  const currentPage = schema.currentPage || schema.page || 1;
23
25
  const totalPages = schema.totalPages || 1;
24
- const showEllipsis = totalPages > 7;
25
26
 
27
+ const handlePageChange = (page: number, e: React.MouseEvent) => {
28
+ e.preventDefault();
29
+ if (page === currentPage) return;
30
+ if (page < 1 || page > totalPages) return;
31
+
32
+ if (onPageChange) {
33
+ onPageChange(page);
34
+ }
35
+ };
36
+
26
37
  const getPageNumbers = () => {
27
38
  if (totalPages <= 7) {
28
39
  return Array.from({ length: totalPages }, (_, i) => i + 1);
@@ -47,27 +58,43 @@ ComponentRegistry.register('pagination',
47
58
  >
48
59
  <PaginationContent>
49
60
  <PaginationItem>
50
- <PaginationPrevious href="#" />
61
+ <PaginationPrevious
62
+ href="#"
63
+ onClick={(e) => handlePageChange(currentPage - 1, e)}
64
+ className={currentPage <= 1 ? "pointer-events-none opacity-50" : "cursor-pointer"}
65
+ aria-disabled={currentPage <= 1}
66
+ />
51
67
  </PaginationItem>
52
68
  {getPageNumbers().map((page, idx) => (
53
69
  <PaginationItem key={idx}>
54
70
  {page === -1 ? (
55
71
  <PaginationEllipsis />
56
72
  ) : (
57
- <PaginationLink href="#" isActive={page === currentPage}>
73
+ <PaginationLink
74
+ href="#"
75
+ isActive={page === currentPage}
76
+ onClick={(e) => handlePageChange(page, e)}
77
+ className="cursor-pointer"
78
+ >
58
79
  {page}
59
80
  </PaginationLink>
60
81
  )}
61
82
  </PaginationItem>
62
83
  ))}
63
84
  <PaginationItem>
64
- <PaginationNext href="#" />
85
+ <PaginationNext
86
+ href="#"
87
+ onClick={(e) => handlePageChange(currentPage + 1, e)}
88
+ className={currentPage >= totalPages ? "pointer-events-none opacity-50" : "cursor-pointer"}
89
+ aria-disabled={currentPage >= totalPages}
90
+ />
65
91
  </PaginationItem>
66
92
  </PaginationContent>
67
93
  </Pagination>
68
94
  );
69
95
  },
70
96
  {
97
+ namespace: 'ui',
71
98
  label: 'Pagination',
72
99
  inputs: [
73
100
  { name: 'currentPage', type: 'number', label: 'Current Page', defaultValue: 1 },
@@ -37,6 +37,7 @@ const SeparatorRenderer = forwardRef<HTMLDivElement, { schema: SeparatorSchema;
37
37
  ComponentRegistry.register('separator',
38
38
  SeparatorRenderer,
39
39
  {
40
+ namespace: 'ui',
40
41
  label: 'Separator',
41
42
  inputs: [
42
43
  {
@@ -13,6 +13,16 @@ import { forwardRef } from 'react';
13
13
 
14
14
  const SpanRenderer = forwardRef<HTMLSpanElement, { schema: SpanSchema; className?: string; [key: string]: any }>(
15
15
  ({ schema, className, ...props }, ref) => {
16
+ // Deprecation warning
17
+ if (process.env.NODE_ENV !== 'production') {
18
+ console.warn(
19
+ '[ObjectUI] The "span" component is deprecated. Please use Shadcn components instead:\n' +
20
+ ' - For badges/labels: use "badge" component\n' +
21
+ ' - For inline text emphasis: use "text" component with appropriate className\n' +
22
+ 'See documentation at https://www.objectui.org/docs/components for alternatives.'
23
+ );
24
+ }
25
+
16
26
  // Extract designer-related props
17
27
  const {
18
28
  'data-obj-id': dataObjId,
@@ -38,7 +48,8 @@ const SpanRenderer = forwardRef<HTMLSpanElement, { schema: SpanSchema; className
38
48
  ComponentRegistry.register('span',
39
49
  SpanRenderer,
40
50
  {
41
- label: 'Inline Container',
51
+ namespace: 'ui',
52
+ label: 'Inline Container (Deprecated)',
42
53
  inputs: [
43
54
  { name: 'className', type: 'string', label: 'CSS Class' }
44
55
  ],
@@ -22,13 +22,14 @@ ComponentRegistry.register('text',
22
22
  ...rest
23
23
  } = props;
24
24
 
25
- // If we have designer props, we must wrap it to make it selectable
26
- if (dataObjId) {
25
+ // If we have designer props or className, we must wrap it to make it selectable and styleable
26
+ if (dataObjId || schema.className || rest.className) {
27
27
  return (
28
28
  <span
29
29
  data-obj-id={dataObjId}
30
30
  data-obj-type={dataObjType}
31
31
  style={style}
32
+ className={schema.className || rest.className}
32
33
  {...rest}
33
34
  >
34
35
  {schema.content || schema.value}
@@ -39,6 +40,7 @@ ComponentRegistry.register('text',
39
40
  return <>{schema.content || schema.value}</>;
40
41
  },
41
42
  {
43
+ namespace: 'ui',
42
44
  label: 'Text',
43
45
  inputs: [
44
46
  { name: 'content', type: 'string', label: 'Content', required: true }
@@ -41,6 +41,7 @@ ComponentRegistry.register('carousel',
41
41
  </Carousel>
42
42
  ),
43
43
  {
44
+ namespace: 'ui',
44
45
  label: 'Carousel',
45
46
  inputs: [
46
47
  { name: 'orientation', type: 'enum', enum: ['horizontal', 'vertical'], defaultValue: 'horizontal', label: 'Orientation' },
@@ -8,6 +8,7 @@
8
8
 
9
9
  // Enterprise-level DataTable Component (Airtable-like)
10
10
  import React, { useState, useMemo, useRef, useEffect } from 'react';
11
+ import { cn } from '../../lib/utils';
11
12
  import { ComponentRegistry } from '@object-ui/core';
12
13
  import type { DataTableSchema } from '@object-ui/types';
13
14
  import {
@@ -360,55 +361,60 @@ const DataTableRenderer = ({ schema }: { schema: DataTableSchema }) => {
360
361
  return selectedRowIds.has(rowId);
361
362
  }) && !allPageRowsSelected;
362
363
 
364
+ const showToolbar = searchable || exportable || (selectable && selectedRowIds.size > 0);
365
+
363
366
  return (
364
- <div className={`space-y-4 ${className || ''}`}>
367
+ <div className={`flex flex-col h-full gap-4 ${className || ''}`}>
365
368
  {/* Toolbar */}
366
- <div className="flex items-center justify-between gap-4">
367
- <div className="flex items-center gap-2 flex-1">
368
- {searchable && (
369
- <div className="relative max-w-sm flex-1">
370
- <Search className="absolute left-2 top-1/2 transform -translate-y-1/2 h-4 w-4 text-muted-foreground" />
371
- <Input
372
- placeholder="Search..."
373
- value={searchQuery}
374
- onChange={(e) => {
375
- setSearchQuery(e.target.value);
376
- setCurrentPage(1);
377
- }}
378
- className="pl-8"
379
- />
380
- </div>
381
- )}
382
- </div>
383
-
384
- <div className="flex items-center gap-2">
385
- {exportable && (
386
- <Button
387
- variant="outline"
388
- size="sm"
389
- onClick={handleExport}
390
- disabled={sortedData.length === 0}
391
- >
392
- <Download className="h-4 w-4 mr-2" />
393
- Export CSV
394
- </Button>
395
- )}
369
+ {showToolbar && (
370
+ <div className="flex items-center justify-between gap-4 flex-none">
371
+ <div className="flex items-center gap-2 flex-1">
372
+ {searchable && (
373
+ <div className="relative max-w-sm flex-1">
374
+ <Search className="absolute left-2 top-1/2 transform -translate-y-1/2 h-4 w-4 text-muted-foreground" />
375
+ <Input
376
+ placeholder="Search..."
377
+ value={searchQuery}
378
+ onChange={(e) => {
379
+ setSearchQuery(e.target.value);
380
+ setCurrentPage(1);
381
+ }}
382
+ className="pl-8"
383
+ />
384
+ </div>
385
+ )}
386
+ </div>
396
387
 
397
- {selectable && selectedRowIds.size > 0 && (
398
- <div className="text-sm text-muted-foreground">
399
- {selectedRowIds.size} selected
400
- </div>
401
- )}
388
+ <div className="flex items-center gap-2">
389
+ {exportable && (
390
+ <Button
391
+ variant="outline"
392
+ size="sm"
393
+ onClick={handleExport}
394
+ disabled={sortedData.length === 0}
395
+ >
396
+ <Download className="h-4 w-4 mr-2" />
397
+ Export CSV
398
+ </Button>
399
+ )}
400
+
401
+ {selectable && selectedRowIds.size > 0 && (
402
+ <div className="text-sm text-muted-foreground">
403
+ {selectedRowIds.size} selected
404
+ </div>
405
+ )}
406
+ </div>
402
407
  </div>
403
- </div>
408
+ )}
404
409
 
405
410
  {/* Table */}
406
- <Table>
411
+ <div className="rounded-md border flex-1 min-h-0 overflow-auto relative bg-background">
412
+ <Table>
407
413
  {caption && <TableCaption>{caption}</TableCaption>}
408
- <TableHeader>
414
+ <TableHeader className="sticky top-0 bg-background z-10 shadow-sm">
409
415
  <TableRow>
410
416
  {selectable && (
411
- <TableHead className="w-12">
417
+ <TableHead className="w-12 bg-background">
412
418
  <Checkbox
413
419
  checked={allPageRowsSelected ? true : somePageRowsSelected ? 'indeterminate' : false}
414
420
  onCheckedChange={handleSelectAll}
@@ -423,7 +429,7 @@ const DataTableRenderer = ({ schema }: { schema: DataTableSchema }) => {
423
429
  return (
424
430
  <TableHead
425
431
  key={col.accessorKey}
426
- className={`${col.className || ''} ${sortable && col.sortable !== false ? 'cursor-pointer select-none' : ''} ${isDragging ? 'opacity-50' : ''} ${isDragOver ? 'border-l-2 border-primary' : ''} relative group`}
432
+ className={`${col.className || ''} ${sortable && col.sortable !== false ? 'cursor-pointer select-none' : ''} ${isDragging ? 'opacity-50' : ''} ${isDragOver ? 'border-l-2 border-primary' : ''} relative group bg-background`}
427
433
  style={{
428
434
  width: columnWidth,
429
435
  minWidth: columnWidth
@@ -455,7 +461,7 @@ const DataTableRenderer = ({ schema }: { schema: DataTableSchema }) => {
455
461
  );
456
462
  })}
457
463
  {rowActions && (
458
- <TableHead className="w-24 text-right">Actions</TableHead>
464
+ <TableHead className="w-24 text-right bg-background">Actions</TableHead>
459
465
  )}
460
466
  </TableRow>
461
467
  </TableHeader>
@@ -464,69 +470,101 @@ const DataTableRenderer = ({ schema }: { schema: DataTableSchema }) => {
464
470
  <TableRow>
465
471
  <TableCell
466
472
  colSpan={columns.length + (selectable ? 1 : 0) + (rowActions ? 1 : 0)}
467
- className="h-24 text-center text-muted-foreground"
473
+ className="h-96 text-center text-muted-foreground"
468
474
  >
469
- No data available
475
+ <div className="flex flex-col items-center justify-center gap-2">
476
+ <Search className="h-8 w-8 text-muted-foreground/50" />
477
+ <p>No results found</p>
478
+ <p className="text-xs text-muted-foreground/50">Try adjusting your filters or search query.</p>
479
+ </div>
470
480
  </TableCell>
471
481
  </TableRow>
472
482
  ) : (
473
- paginatedData.map((row, rowIndex) => {
474
- const globalIndex = (currentPage - 1) * pageSize + rowIndex;
475
- const rowId = getRowId(row, globalIndex);
476
- const isSelected = selectedRowIds.has(rowId);
477
-
478
- return (
479
- <TableRow key={rowId} data-state={isSelected ? 'selected' : undefined}>
480
- {selectable && (
481
- <TableCell>
482
- <Checkbox
483
- checked={isSelected}
484
- onCheckedChange={(checked) => handleSelectRow(rowId, checked as boolean)}
485
- />
486
- </TableCell>
487
- )}
488
- {columns.map((col, colIndex) => {
489
- const columnWidth = columnWidths[col.accessorKey] || col.width;
490
- return (
491
- <TableCell
492
- key={colIndex}
493
- className={col.cellClassName}
494
- style={{
495
- width: columnWidth,
496
- minWidth: columnWidth,
497
- maxWidth: columnWidth
498
- }}
499
- >
500
- {row[col.accessorKey]}
483
+ <>
484
+ {paginatedData.map((row, rowIndex) => {
485
+ const globalIndex = (currentPage - 1) * pageSize + rowIndex;
486
+ const rowId = getRowId(row, globalIndex);
487
+ const isSelected = selectedRowIds.has(rowId);
488
+
489
+ return (
490
+ <TableRow
491
+ key={rowId}
492
+ data-state={isSelected ? 'selected' : undefined}
493
+ className={cn(
494
+ // @ts-expect-error - onRowClick might not be in schema type definition
495
+ schema.onRowClick && "cursor-pointer"
496
+ )}
497
+ onClick={(e) => {
498
+ // @ts-expect-error - onRowClick might not be in schema type definition
499
+ if (schema.onRowClick && !e.defaultPrevented) {
500
+ // Simple heuristic to avoid triggering on interactive elements if they didn't stop propagation
501
+ const target = e.target as HTMLElement;
502
+ if (target.closest('button') || target.closest('[role="checkbox"]') || target.closest('a')) {
503
+ return;
504
+ }
505
+ // @ts-expect-error - onRowClick might not be in schema type definition
506
+ schema.onRowClick(row);
507
+ }
508
+ }}
509
+ >
510
+ {selectable && (
511
+ <TableCell>
512
+ <Checkbox
513
+ checked={isSelected}
514
+ onCheckedChange={(checked) => handleSelectRow(rowId, checked as boolean)}
515
+ />
501
516
  </TableCell>
502
- );
503
- })}
504
- {rowActions && (
505
- <TableCell className="text-right">
506
- <div className="flex items-center justify-end gap-1">
507
- <Button
508
- variant="ghost"
509
- size="icon-sm"
510
- onClick={() => schema.onRowEdit?.(row)}
511
- >
512
- <Edit className="h-4 w-4" />
513
- </Button>
514
- <Button
515
- variant="ghost"
516
- size="icon-sm"
517
- onClick={() => schema.onRowDelete?.(row)}
517
+ )}
518
+ {columns.map((col, colIndex) => {
519
+ const columnWidth = columnWidths[col.accessorKey] || col.width;
520
+ return (
521
+ <TableCell
522
+ key={colIndex}
523
+ className={col.cellClassName}
524
+ style={{
525
+ width: columnWidth,
526
+ minWidth: columnWidth,
527
+ maxWidth: columnWidth
528
+ }}
518
529
  >
519
- <Trash2 className="h-4 w-4 text-destructive" />
520
- </Button>
521
- </div>
522
- </TableCell>
523
- )}
530
+ {row[col.accessorKey]}
531
+ </TableCell>
532
+ );
533
+ })}
534
+ {rowActions && (
535
+ <TableCell className="text-right">
536
+ <div className="flex items-center justify-end gap-1">
537
+ <Button
538
+ variant="ghost"
539
+ size="icon-sm"
540
+ onClick={() => schema.onRowEdit?.(row)}
541
+ >
542
+ <Edit className="h-4 w-4" />
543
+ </Button>
544
+ <Button
545
+ variant="ghost"
546
+ size="icon-sm"
547
+ onClick={() => schema.onRowDelete?.(row)}
548
+ >
549
+ <Trash2 className="h-4 w-4 text-destructive" />
550
+ </Button>
551
+ </div>
552
+ </TableCell>
553
+ )}
554
+ </TableRow>
555
+ );
556
+ })}
557
+ {/* Filler rows to maintain height consistency */}
558
+ {paginatedData.length > 0 && Array.from({ length: Math.max(0, pageSize - paginatedData.length) }).map((_, i) => (
559
+ <TableRow key={`empty-${i}`} className="hover:bg-transparent">
560
+ <TableCell colSpan={columns.length + (selectable ? 1 : 0) + (rowActions ? 1 : 0)} className="h-[52px] p-0" />
524
561
  </TableRow>
525
- );
526
- })
562
+ ))}
563
+ </>
527
564
  )}
528
565
  </TableBody>
529
566
  </Table>
567
+ </div>
530
568
 
531
569
  {/* Pagination */}
532
570
  {pagination && sortedData.length > 0 && (
@@ -600,6 +638,7 @@ const DataTableRenderer = ({ schema }: { schema: DataTableSchema }) => {
600
638
 
601
639
  // Register the component
602
640
  ComponentRegistry.register('data-table', DataTableRenderer, {
641
+ namespace: 'ui',
603
642
  label: 'Data Table',
604
643
  icon: 'table',
605
644
  inputs: [
@@ -8,7 +8,7 @@
8
8
 
9
9
  import { ComponentRegistry } from '@object-ui/core';
10
10
  import type { FilterBuilderSchema, FilterGroup } from '@object-ui/types';
11
- import { FilterBuilder } from '../../ui/filter-builder';
11
+ import { FilterBuilder } from '../../custom/filter-builder';
12
12
 
13
13
  ComponentRegistry.register('filter-builder',
14
14
  ({ schema, className, onChange, ...props }: { schema: FilterBuilderSchema; className?: string; onChange?: (event: any) => void; [key: string]: any }) => {
@@ -39,6 +39,7 @@ ComponentRegistry.register('filter-builder',
39
39
  );
40
40
  },
41
41
  {
42
+ namespace: 'ui',
42
43
  label: 'Filter Builder',
43
44
  inputs: [
44
45
  { name: 'label', type: 'string', label: 'Label' },
@@ -19,7 +19,7 @@ import { renderChildren } from '../../lib/utils';
19
19
  ComponentRegistry.register('resizable',
20
20
  ({ schema, className, ...props }: { schema: ResizableSchema; className?: string; [key: string]: any }) => (
21
21
  <ResizablePanelGroup
22
- direction={schema.direction || 'horizontal'}
22
+ orientation={(schema.direction || 'horizontal') as "horizontal" | "vertical"}
23
23
  className={className}
24
24
  {...props}
25
25
  style={{ minHeight: schema.minHeight || '200px' }}
@@ -35,6 +35,7 @@ ComponentRegistry.register('resizable',
35
35
  </ResizablePanelGroup>
36
36
  ),
37
37
  {
38
+ namespace: 'ui',
38
39
  label: 'Resizable Panel Group',
39
40
  inputs: [
40
41
  { name: 'direction', type: 'enum', enum: ['horizontal', 'vertical'], defaultValue: 'horizontal', label: 'Direction' },
@@ -12,26 +12,44 @@ import { ScrollArea, ScrollBar } from '../../ui';
12
12
  import { renderChildren } from '../../lib/utils';
13
13
 
14
14
  ComponentRegistry.register('scroll-area',
15
- ({ schema, className, ...props }: { schema: ScrollAreaSchema; className?: string; [key: string]: any }) => (
16
- <ScrollArea className={className} style={{ height: schema.height, width: schema.width }} {...props}>
17
- {renderChildren(schema.content || schema.children)}
18
- {schema.orientation === 'horizontal' && <ScrollBar orientation="horizontal" />}
15
+ ({ schema, className, ...props }: { schema: ScrollAreaSchema; className?: string; [key: string]: any }) => {
16
+ // Extract designer-related props
17
+ const {
18
+ 'data-obj-id': dataObjId,
19
+ 'data-obj-type': dataObjType,
20
+ style,
21
+ ...scrollAreaProps
22
+ } = props;
23
+
24
+ const orientation = schema.orientation || 'vertical';
25
+
26
+ return (
27
+ <ScrollArea
28
+ className={className}
29
+ style={{ height: schema.height, width: schema.width, ...style }}
30
+ {...scrollAreaProps}
31
+ data-obj-id={dataObjId}
32
+ data-obj-type={dataObjType}
33
+ >
34
+ {renderChildren(schema.children)}
35
+ {(orientation === 'horizontal' || orientation === 'both') && <ScrollBar orientation="horizontal" />}
36
+ {(orientation === 'vertical' || orientation === 'both') && <ScrollBar orientation="vertical" />}
19
37
  </ScrollArea>
20
- ),
38
+ )},
21
39
  {
40
+ namespace: 'ui',
22
41
  label: 'Scroll Area',
23
42
  inputs: [
24
43
  { name: 'height', type: 'string', label: 'Height (e.g. 200px)' },
25
44
  { name: 'width', type: 'string', label: 'Width' },
26
45
  { name: 'orientation', type: 'enum', enum: ['vertical', 'horizontal', 'both'], defaultValue: 'vertical', label: 'Orientation' },
27
- { name: 'content', type: 'slot', label: 'Content' },
28
46
  { name: 'className', type: 'string', label: 'CSS Class' }
29
47
  ],
30
48
  defaultProps: {
31
49
  height: '200px',
32
50
  width: '100%',
33
51
  orientation: 'vertical',
34
- content: [
52
+ children: [
35
53
  { type: 'div', className: 'p-4', body: [{ type: 'text', content: 'Scrollable content goes here. Add more content to see scrolling behavior.' }] }
36
54
  ],
37
55
  className: 'rounded-md border'
@@ -59,6 +59,7 @@ ComponentRegistry.register('table',
59
59
  </Table>
60
60
  ),
61
61
  {
62
+ namespace: 'ui',
62
63
  label: 'Table',
63
64
  inputs: [
64
65
  { name: 'caption', type: 'string', label: 'Caption' },
@@ -23,6 +23,7 @@ ComponentRegistry.register('alert',
23
23
  </Alert>
24
24
  ),
25
25
  {
26
+ namespace: 'ui',
26
27
  label: 'Alert',
27
28
  inputs: [
28
29
  { name: 'title', type: 'string', label: 'Title', required: true },
@@ -22,6 +22,7 @@ ComponentRegistry.register('avatar',
22
22
  </Avatar>
23
23
  ),
24
24
  {
25
+ namespace: 'ui',
25
26
  label: 'Avatar',
26
27
  inputs: [
27
28
  { name: 'src', type: 'string', label: 'Image URL' },
@@ -34,6 +34,7 @@ ComponentRegistry.register('badge',
34
34
  );
35
35
  },
36
36
  {
37
+ namespace: 'ui',
37
38
  label: 'Badge',
38
39
  inputs: [
39
40
  { name: 'label', type: 'string', label: 'Label' },
@@ -44,6 +44,7 @@ ComponentRegistry.register('breadcrumb',
44
44
  );
45
45
  },
46
46
  {
47
+ namespace: 'ui',
47
48
  label: 'Breadcrumb',
48
49
  inputs: [
49
50
  { name: 'className', type: 'string', label: 'CSS Class' }
@@ -37,6 +37,7 @@ ComponentRegistry.register('kbd',
37
37
  );
38
38
  },
39
39
  {
40
+ namespace: 'ui',
40
41
  label: 'Keyboard Key',
41
42
  inputs: [
42
43
  { name: 'label', type: 'string', label: 'Label' },