@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
package/src/index.ts ADDED
@@ -0,0 +1,10 @@
1
+ import './index.css';
2
+
3
+ // Register all ObjectUI renderers (side-effects)
4
+ import './renderers';
5
+
6
+ // Export utils
7
+ export * from './lib/utils';
8
+
9
+ // Export raw Shadcn UI components
10
+ export * from './ui';
@@ -0,0 +1,27 @@
1
+ import { clsx, type ClassValue } from "clsx"
2
+ import { twMerge } from "tailwind-merge"
3
+ import { SchemaRenderer } from "@object-ui/react"
4
+ import React from "react"
5
+
6
+ export function cn(...inputs: ClassValue[]) {
7
+ return twMerge(clsx(inputs))
8
+ }
9
+
10
+ export function renderChildren(children: any): React.ReactNode {
11
+ if (!children) return null;
12
+ if (typeof children === 'string' || typeof children === 'number') {
13
+ return children;
14
+ }
15
+ if (Array.isArray(children)) {
16
+ if (children.length === 0) return null;
17
+ // Unwrap single child to support Radix UI 'asChild' pattern which expects a single ReactElement, not an array
18
+ if (children.length === 1) {
19
+ return <SchemaRenderer schema={children[0]} />;
20
+ }
21
+ return children.map((child, index) => (
22
+ <SchemaRenderer key={child.id || index} schema={child} />
23
+ ));
24
+ }
25
+ return <SchemaRenderer schema={children} />;
26
+ }
27
+
@@ -0,0 +1,74 @@
1
+ import { describe, it, expect, beforeAll } from 'vitest';
2
+ import { ComponentRegistry } from '@object-ui/core';
3
+
4
+ describe('New Components Registration', () => {
5
+ // Import all renderers to register them
6
+ beforeAll(async () => {
7
+ await import('./renderers');
8
+ });
9
+
10
+ describe('Form Components', () => {
11
+ it('should register date-picker component', () => {
12
+ const component = ComponentRegistry.getConfig('date-picker');
13
+ expect(component).toBeDefined();
14
+ expect(component?.label).toBe('Date Picker');
15
+ });
16
+
17
+ it('should register file-upload component', () => {
18
+ const component = ComponentRegistry.getConfig('file-upload');
19
+ expect(component).toBeDefined();
20
+ expect(component?.label).toBe('File Upload');
21
+ });
22
+ });
23
+
24
+ describe('Data Display Components', () => {
25
+ it('should register list component', () => {
26
+ const component = ComponentRegistry.getConfig('list');
27
+ expect(component).toBeDefined();
28
+ expect(component?.label).toBe('List');
29
+ });
30
+
31
+ it('should register tree-view component', () => {
32
+ const component = ComponentRegistry.getConfig('tree-view');
33
+ expect(component).toBeDefined();
34
+ expect(component?.label).toBe('Tree View');
35
+ });
36
+ });
37
+
38
+ describe('Layout Components', () => {
39
+ it('should register grid component', () => {
40
+ const component = ComponentRegistry.getConfig('grid');
41
+ expect(component).toBeDefined();
42
+ expect(component?.label).toBe('Grid Layout');
43
+ });
44
+
45
+ it('should register flex component', () => {
46
+ const component = ComponentRegistry.getConfig('flex');
47
+ expect(component).toBeDefined();
48
+ expect(component?.label).toBe('Flex Layout');
49
+ });
50
+
51
+ it('should register container component', () => {
52
+ const component = ComponentRegistry.getConfig('container');
53
+ expect(component).toBeDefined();
54
+ expect(component?.label).toBe('Container');
55
+ });
56
+ });
57
+
58
+ describe('Feedback Components', () => {
59
+ it('should register loading component', () => {
60
+ const component = ComponentRegistry.getConfig('loading');
61
+ expect(component).toBeDefined();
62
+ expect(component?.label).toBe('Loading');
63
+ });
64
+ });
65
+
66
+ describe('Complex Components', () => {
67
+ it('should register timeline component', () => {
68
+ const component = ComponentRegistry.getConfig('timeline');
69
+ expect(component).toBeDefined();
70
+ expect(component?.label).toBe('Timeline');
71
+ expect(component?.category).toBe('data-display');
72
+ });
73
+ });
74
+ });
@@ -0,0 +1,41 @@
1
+ import { ComponentRegistry } from '@object-ui/core';
2
+ import type { DivSchema } from '@object-ui/types';
3
+ import { renderChildren } from '../../lib/utils';
4
+ import { forwardRef } from 'react';
5
+
6
+ const DivRenderer = forwardRef<HTMLDivElement, { schema: DivSchema; className?: string; [key: string]: any }>(
7
+ ({ schema, className, ...props }, ref) => {
8
+ // Extract designer-related props
9
+ const {
10
+ 'data-obj-id': dataObjId,
11
+ 'data-obj-type': dataObjType,
12
+ style,
13
+ ...divProps
14
+ } = props;
15
+
16
+ return (
17
+ <div
18
+ ref={ref}
19
+ className={className}
20
+ {...divProps}
21
+ // Apply designer props
22
+ {...{ 'data-obj-id': dataObjId, 'data-obj-type': dataObjType, style }}
23
+ >
24
+ {renderChildren(schema.children || schema.body)}
25
+ </div>
26
+ );
27
+ }
28
+ );
29
+
30
+ ComponentRegistry.register('div',
31
+ DivRenderer,
32
+ {
33
+ label: 'Container',
34
+ inputs: [
35
+ { name: 'className', type: 'string', label: 'CSS Class' }
36
+ ],
37
+ defaultProps: {
38
+ className: 'p-4 border border-dashed border-gray-300 rounded min-h-[100px]'
39
+ }
40
+ }
41
+ );
@@ -0,0 +1,34 @@
1
+ import React from 'react';
2
+ import { ComponentRegistry } from '@object-ui/core';
3
+ import type { HtmlSchema } from '@object-ui/types';
4
+ import { cn } from '../../lib/utils';
5
+
6
+ ComponentRegistry.register('html',
7
+ ({ schema, className, ...props }: { schema: HtmlSchema; className?: string; [key: string]: any }) => {
8
+ // Extract designer-related props
9
+ const {
10
+ 'data-obj-id': dataObjId,
11
+ 'data-obj-type': dataObjType,
12
+ style,
13
+ ...htmlProps
14
+ } = props;
15
+
16
+ return (
17
+ <div
18
+ className={cn("prose prose-sm max-w-none dark:prose-invert", className)}
19
+ dangerouslySetInnerHTML={{ __html: schema.html }}
20
+ {...htmlProps}
21
+ // Apply designer props
22
+ data-obj-id={dataObjId}
23
+ data-obj-type={dataObjType}
24
+ style={style}
25
+ />
26
+ );
27
+ },
28
+ {
29
+ label: 'HTML Content',
30
+ inputs: [
31
+ { name: 'html', type: 'string', label: 'HTML', description: 'Raw HTML content' }
32
+ ]
33
+ }
34
+ );
@@ -0,0 +1,25 @@
1
+ import { ComponentRegistry } from '@object-ui/core';
2
+ import type { IconSchema } from '@object-ui/types';
3
+ import { icons } from 'lucide-react';
4
+ import React, { forwardRef } from 'react';
5
+
6
+ const IconRenderer = forwardRef<SVGSVGElement, { schema: IconSchema; className?: string; [key: string]: any }>(
7
+ ({ schema, className, ...props }, ref) => {
8
+ const Icon = (icons as any)[schema.name || schema.icon];
9
+ if (!Icon) return null;
10
+ return <Icon ref={ref} className={className} {...props} />;
11
+ }
12
+ );
13
+
14
+ ComponentRegistry.register('icon',
15
+ IconRenderer,
16
+ {
17
+ label: 'Icon',
18
+ icon: 'smile',
19
+ category: 'basic',
20
+ inputs: [
21
+ { name: 'name', type: 'string', label: 'Icon Name', defaultValue: 'smile' },
22
+ { name: 'className', type: 'string', label: 'CSS Class' }
23
+ ]
24
+ }
25
+ );
@@ -0,0 +1,37 @@
1
+ import { ComponentRegistry } from '@object-ui/core';
2
+ import type { ImageSchema } from '@object-ui/types';
3
+
4
+ ComponentRegistry.register('image',
5
+ ({ schema, className, ...props }: { schema: ImageSchema; className?: string; [key: string]: any }) => {
6
+ // Extract designer-related props
7
+ const {
8
+ 'data-obj-id': dataObjId,
9
+ 'data-obj-type': dataObjType,
10
+ style,
11
+ ...imgProps
12
+ } = props;
13
+
14
+ return (
15
+ <img
16
+ src={schema.src}
17
+ alt={schema.alt || ''}
18
+ className={className}
19
+ {...imgProps}
20
+ // Apply designer props
21
+ data-obj-id={dataObjId}
22
+ data-obj-type={dataObjType}
23
+ style={style}
24
+ />
25
+ );
26
+ },
27
+ {
28
+ label: 'Image',
29
+ icon: 'image',
30
+ category: 'basic',
31
+ inputs: [
32
+ { name: 'src', type: 'string', label: 'Source URL' },
33
+ { name: 'alt', type: 'string', label: 'Alt Text' },
34
+ { name: 'className', type: 'string', label: 'Classes' }
35
+ ]
36
+ }
37
+ );
@@ -0,0 +1,7 @@
1
+ import './div';
2
+ import './text';
3
+ import './span';
4
+ import './separator';
5
+ import './image';
6
+ import './icon';
7
+ import './html';
@@ -0,0 +1,48 @@
1
+ import { ComponentRegistry } from '@object-ui/core';
2
+ import type { SeparatorSchema } from '@object-ui/types';
3
+ import { Separator } from '../../ui';
4
+ import { forwardRef } from 'react';
5
+
6
+ const SeparatorRenderer = forwardRef<HTMLDivElement, { schema: SeparatorSchema; className?: string; [key: string]: any }>(
7
+ ({ schema, className, ...props }, ref) => {
8
+ // Extract designer-related props
9
+ const {
10
+ 'data-obj-id': dataObjId,
11
+ 'data-obj-type': dataObjType,
12
+ style,
13
+ ...separatorProps
14
+ } = props;
15
+
16
+ return (
17
+ <Separator
18
+ ref={ref}
19
+ orientation={schema.orientation}
20
+ className={className}
21
+ {...separatorProps}
22
+ // Apply designer props
23
+ {...{ 'data-obj-id': dataObjId, 'data-obj-type': dataObjType, style }}
24
+ />
25
+ );
26
+ }
27
+ );
28
+
29
+ ComponentRegistry.register('separator',
30
+ SeparatorRenderer,
31
+ {
32
+ label: 'Separator',
33
+ inputs: [
34
+ {
35
+ name: 'orientation',
36
+ type: 'enum',
37
+ enum: ['horizontal', 'vertical'],
38
+ defaultValue: 'horizontal',
39
+ label: 'Orientation'
40
+ },
41
+ { name: 'className', type: 'string', label: 'CSS Class' }
42
+ ],
43
+ defaultProps: {
44
+ orientation: 'horizontal',
45
+ className: 'my-4'
46
+ }
47
+ }
48
+ );
@@ -0,0 +1,44 @@
1
+ import { ComponentRegistry } from '@object-ui/core';
2
+ import type { SpanSchema } from '@object-ui/types';
3
+ import { renderChildren } from '../../lib/utils';
4
+ import { forwardRef } from 'react';
5
+
6
+ const SpanRenderer = forwardRef<HTMLSpanElement, { schema: SpanSchema; className?: string; [key: string]: any }>(
7
+ ({ schema, className, ...props }, ref) => {
8
+ // Extract designer-related props
9
+ const {
10
+ 'data-obj-id': dataObjId,
11
+ 'data-obj-type': dataObjType,
12
+ style,
13
+ ...spanProps
14
+ } = props;
15
+
16
+ return (
17
+ <span
18
+ ref={ref}
19
+ className={className}
20
+ {...spanProps}
21
+ // Apply designer props
22
+ {...{ 'data-obj-id': dataObjId, 'data-obj-type': dataObjType, style }}
23
+ >
24
+ {renderChildren(schema.body)}
25
+ </span>
26
+ );
27
+ }
28
+ );
29
+
30
+ ComponentRegistry.register('span',
31
+ SpanRenderer,
32
+ {
33
+ label: 'Inline Container',
34
+ inputs: [
35
+ { name: 'className', type: 'string', label: 'CSS Class' }
36
+ ],
37
+ defaultProps: {
38
+ className: 'px-2 py-1'
39
+ },
40
+ defaultChildren: [
41
+ { type: 'text', content: 'Inline text' }
42
+ ]
43
+ }
44
+ );
@@ -0,0 +1,42 @@
1
+ import { ComponentRegistry } from '@object-ui/core';
2
+ import type { TextSchema } from '@object-ui/types';
3
+
4
+ ComponentRegistry.register('text',
5
+ ({ schema, ...props }: { schema: TextSchema; [key: string]: any }) => {
6
+ // Text is a special case as it might be rendered as a fragment or span depending on usage.
7
+ // However, to support drag and drop in designer, it MUST be wrapped in an element if props are passed.
8
+
9
+ // Extract designer-related props
10
+ const {
11
+ 'data-obj-id': dataObjId,
12
+ 'data-obj-type': dataObjType,
13
+ style,
14
+ ...rest
15
+ } = props;
16
+
17
+ // If we have designer props, we must wrap it to make it selectable
18
+ if (dataObjId) {
19
+ return (
20
+ <span
21
+ data-obj-id={dataObjId}
22
+ data-obj-type={dataObjType}
23
+ style={style}
24
+ {...rest}
25
+ >
26
+ {schema.content || schema.value}
27
+ </span>
28
+ );
29
+ }
30
+
31
+ return <>{schema.content || schema.value}</>;
32
+ },
33
+ {
34
+ label: 'Text',
35
+ inputs: [
36
+ { name: 'content', type: 'string', label: 'Content', required: true }
37
+ ],
38
+ defaultProps: {
39
+ content: 'Text content'
40
+ }
41
+ }
42
+ );
@@ -0,0 +1,208 @@
1
+ # Kanban Board Component
2
+
3
+ A fully functional, schema-driven Kanban board component for Object UI with drag-and-drop support.
4
+
5
+ ## Features
6
+
7
+ - **Multiple Columns**: Create unlimited columns with customizable titles
8
+ - **Rich Cards**: Cards support title, description, and multiple badges
9
+ - **Drag & Drop**: Smooth drag-and-drop functionality powered by @dnd-kit
10
+ - **Reordering**: Reorder cards within the same column
11
+ - **Cross-Column Moves**: Move cards between different columns
12
+ - **Column Limits**: Optional capacity limits with visual indicators
13
+ - **Card Counters**: Shows current count and limit per column
14
+ - **Schema-Driven**: Configure entirely through JSON/YAML
15
+ - **Event Callbacks**: Custom event handling for card movements
16
+
17
+ ## Usage
18
+
19
+ ### Basic Example
20
+
21
+ ```json
22
+ {
23
+ "type": "kanban",
24
+ "className": "w-full h-[600px]",
25
+ "columns": [
26
+ {
27
+ "id": "todo",
28
+ "title": "To Do",
29
+ "cards": [
30
+ {
31
+ "id": "card-1",
32
+ "title": "Task Title",
33
+ "description": "Task description",
34
+ "badges": [
35
+ { "label": "High Priority", "variant": "destructive" }
36
+ ]
37
+ }
38
+ ]
39
+ },
40
+ {
41
+ "id": "in-progress",
42
+ "title": "In Progress",
43
+ "limit": 3,
44
+ "cards": []
45
+ },
46
+ {
47
+ "id": "done",
48
+ "title": "Done",
49
+ "cards": []
50
+ }
51
+ ]
52
+ }
53
+ ```
54
+
55
+ ### With Event Handling
56
+
57
+ ```json
58
+ {
59
+ "type": "kanban",
60
+ "columns": [...],
61
+ "onCardMove": "(event) => { console.log('Card moved:', event); }"
62
+ }
63
+ ```
64
+
65
+ ## Schema Reference
66
+
67
+ ### Kanban Props
68
+
69
+ | Property | Type | Required | Description |
70
+ |----------|------|----------|-------------|
71
+ | `type` | `"kanban"` | Yes | Component type identifier |
72
+ | `columns` | `KanbanColumn[]` | Yes | Array of column configurations |
73
+ | `className` | `string` | No | Custom CSS classes |
74
+ | `onCardMove` | `function` | No | Callback when a card is moved |
75
+
76
+ ### KanbanColumn
77
+
78
+ | Property | Type | Required | Description |
79
+ |----------|------|----------|-------------|
80
+ | `id` | `string` | Yes | Unique column identifier |
81
+ | `title` | `string` | Yes | Column header title |
82
+ | `cards` | `KanbanCard[]` | Yes | Array of cards in this column |
83
+ | `limit` | `number` | No | Maximum number of cards allowed |
84
+ | `className` | `string` | No | Custom CSS classes for column |
85
+
86
+ ### KanbanCard
87
+
88
+ | Property | Type | Required | Description |
89
+ |----------|------|----------|-------------|
90
+ | `id` | `string` | Yes | Unique card identifier |
91
+ | `title` | `string` | Yes | Card title |
92
+ | `description` | `string` | No | Card description text |
93
+ | `badges` | `Badge[]` | No | Array of badge objects |
94
+
95
+ ### Badge
96
+
97
+ | Property | Type | Required | Description |
98
+ |----------|------|----------|-------------|
99
+ | `label` | `string` | Yes | Badge text |
100
+ | `variant` | `"default" \| "secondary" \| "destructive" \| "outline"` | No | Badge color variant |
101
+
102
+ ## Examples
103
+
104
+ ### Simple Task Board
105
+
106
+ ```json
107
+ {
108
+ "type": "kanban",
109
+ "columns": [
110
+ {
111
+ "id": "backlog",
112
+ "title": "📋 Backlog",
113
+ "cards": [
114
+ {
115
+ "id": "1",
116
+ "title": "Setup project",
117
+ "badges": [{ "label": "Setup" }]
118
+ }
119
+ ]
120
+ },
121
+ {
122
+ "id": "doing",
123
+ "title": "🚀 Doing",
124
+ "limit": 2,
125
+ "cards": []
126
+ },
127
+ {
128
+ "id": "done",
129
+ "title": "✅ Done",
130
+ "cards": []
131
+ }
132
+ ]
133
+ }
134
+ ```
135
+
136
+ ### Issue Tracking Board
137
+
138
+ ```json
139
+ {
140
+ "type": "kanban",
141
+ "columns": [
142
+ {
143
+ "id": "new",
144
+ "title": "New Issues",
145
+ "cards": [
146
+ {
147
+ "id": "issue-1",
148
+ "title": "Bug: Login fails on Safari",
149
+ "description": "Users can't login using Safari browser",
150
+ "badges": [
151
+ { "label": "Bug", "variant": "destructive" },
152
+ { "label": "P0", "variant": "destructive" }
153
+ ]
154
+ }
155
+ ]
156
+ },
157
+ {
158
+ "id": "investigating",
159
+ "title": "Investigating",
160
+ "limit": 3,
161
+ "cards": []
162
+ },
163
+ {
164
+ "id": "fixed",
165
+ "title": "Fixed",
166
+ "cards": []
167
+ }
168
+ ]
169
+ }
170
+ ```
171
+
172
+ ## Styling
173
+
174
+ The Kanban component uses Tailwind CSS and can be customized using the `className` prop:
175
+
176
+ ```json
177
+ {
178
+ "type": "kanban",
179
+ "className": "w-full h-[800px] bg-gray-50 p-4 rounded-lg",
180
+ "columns": [...]
181
+ }
182
+ ```
183
+
184
+ Individual columns can also be styled:
185
+
186
+ ```json
187
+ {
188
+ "id": "urgent",
189
+ "title": "🔥 Urgent",
190
+ "className": "bg-red-50",
191
+ "cards": [...]
192
+ }
193
+ ```
194
+
195
+ ## Technical Details
196
+
197
+ - Built with React 18+ and TypeScript
198
+ - Uses @dnd-kit for drag-and-drop functionality
199
+ - Integrates with Shadcn UI components (Card, Badge, ScrollArea)
200
+ - Supports both pointer and touch interactions
201
+ - Accessible keyboard navigation (via @dnd-kit)
202
+
203
+ ## Browser Support
204
+
205
+ - Chrome/Edge: Full support
206
+ - Firefox: Full support
207
+ - Safari: Full support
208
+ - Mobile browsers: Full support with touch gestures