@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
@@ -0,0 +1,28 @@
1
+ import React from 'react';
2
+ import { ComponentRegistry } from '@object-ui/core';
3
+
4
+ export const SchemaRenderer = ({ schema }: { schema: any }) => {
5
+ if (!schema) return null;
6
+ if (Array.isArray(schema)) {
7
+ return <>{schema.map((s, i) => <SchemaRenderer key={s.id || i} schema={s} />)}</>;
8
+ }
9
+
10
+ const { type, hidden } = schema;
11
+ if (hidden) return null; // Simple hidden check
12
+
13
+ if (!type) {
14
+ if (typeof schema === 'string') return <>{schema}</>;
15
+ return null;
16
+ }
17
+
18
+ const Component = ComponentRegistry.get(type);
19
+
20
+ if (!Component) {
21
+ console.warn(`Renderer not found for type: ${type}`);
22
+ return <div className="p-2 text-xs text-red-500 border border-red-200 bg-red-50 rounded">Unknown: {type}</div>;
23
+ }
24
+
25
+ // This is dynamic component resolution from registry, not component creation during render
26
+ // eslint-disable-next-line
27
+ return <Component schema={schema} {...schema} />;
28
+ };
@@ -0,0 +1,59 @@
1
+
2
+ import { describe, it, expect } from 'vitest';
3
+ import { render, screen } from '@testing-library/react';
4
+ import React from 'react';
5
+ import { PageRenderer } from '../renderers/layout/page'; // Direct import to test logic
6
+ import { ComponentRegistry } from '@object-ui/core';
7
+
8
+ // Mock SchemaRenderer to verify it's called
9
+ import { SchemaRenderer } from '@object-ui/react';
10
+ import { vi } from 'vitest';
11
+
12
+ // Mock the SchemaRenderer to avoid full tree recursion deps
13
+ vi.mock('@object-ui/react', () => ({
14
+ SchemaRenderer: ({ schema }: any) => <div data-testid="child-node">{schema.type}:{schema.value || schema.name}</div>
15
+ }));
16
+
17
+ describe('PageRenderer Regions', () => {
18
+ it('should render components from regions', () => {
19
+ const schema: any = {
20
+ type: 'page',
21
+ title: 'Test Page',
22
+ regions: [
23
+ {
24
+ name: 'main',
25
+ components: [
26
+ { type: 'text', value: 'Region Content 1' },
27
+ { type: 'button', label: 'Region Button' }
28
+ ]
29
+ }
30
+ ]
31
+ };
32
+
33
+ render(<PageRenderer schema={schema} />);
34
+
35
+ // Check if title is rendered
36
+ expect(screen.getByText('Test Page')).toBeDefined();
37
+
38
+ // Check real content (since mock didn't take effect, we verify real render)
39
+ // The text component renders the value directly
40
+ expect(screen.getByText('Region Content 1')).toBeDefined();
41
+
42
+ // The button component renders the label
43
+ expect(screen.getByText('Region Button')).toBeDefined();
44
+ });
45
+
46
+ it('should render legacy body', () => {
47
+ const schema: any = {
48
+ type: 'page',
49
+ title: 'Legacy Page',
50
+ body: [
51
+ { type: 'text', value: 'Body Content' }
52
+ ]
53
+ };
54
+
55
+ render(<PageRenderer schema={schema} />);
56
+
57
+ expect(screen.getByText('Body Content')).toBeDefined();
58
+ });
59
+ });
@@ -0,0 +1,21 @@
1
+
2
+ import { describe, it, expect } from 'vitest';
3
+ import { ComponentRegistry } from '@object-ui/core';
4
+ import '../renderers'; // Ensure side-effects are run
5
+
6
+ describe('Component Registry', () => {
7
+ it('should register standard page types', () => {
8
+ expect(ComponentRegistry.get('page')).toBeDefined();
9
+ expect(ComponentRegistry.get('app')).toBeDefined();
10
+ expect(ComponentRegistry.get('utility')).toBeDefined();
11
+ expect(ComponentRegistry.get('home')).toBeDefined();
12
+ expect(ComponentRegistry.get('record')).toBeDefined();
13
+ });
14
+
15
+ it('should register standard layout components', () => {
16
+ expect(ComponentRegistry.get('container')).toBeDefined();
17
+ expect(ComponentRegistry.get('grid')).toBeDefined();
18
+ expect(ComponentRegistry.get('stack')).toBeDefined();
19
+ expect(ComponentRegistry.get('card')).toBeDefined();
20
+ });
21
+ });
@@ -17,7 +17,7 @@ import {
17
17
  // Import renderers to ensure registration
18
18
  beforeAll(async () => {
19
19
  await import('../renderers');
20
- });
20
+ }, 30000); // Increase timeout to 30 seconds for heavy renderer imports
21
21
 
22
22
  /**
23
23
  * Comprehensive tests for basic renderer components
@@ -17,7 +17,7 @@ import {
17
17
  // Import renderers to ensure registration
18
18
  beforeAll(async () => {
19
19
  await import('../renderers');
20
- });
20
+ }, 30000); // Increase timeout to 30 seconds for heavy renderer imports
21
21
 
22
22
  /**
23
23
  * Comprehensive tests for disclosure renderer components
@@ -178,10 +178,11 @@ describe('Complex Renderers - Display Issue Detection', () => {
178
178
  it('should render scrollable area', () => {
179
179
  const { container } = renderComponent({
180
180
  type: 'scroll-area',
181
- content: [{ type: 'text', content: 'Scrollable content' }],
181
+ children: [{ type: 'text', content: 'Scrollable content' }],
182
182
  });
183
183
 
184
184
  // ScrollArea renders content
185
+
185
186
  expect(container.textContent).toContain('Scrollable content');
186
187
  });
187
188
  });
@@ -16,7 +16,7 @@ import {
16
16
  // Import renderers to ensure registration
17
17
  beforeAll(async () => {
18
18
  await import('../renderers');
19
- });
19
+ }, 30000); // Increase timeout to 30 seconds for heavy renderer imports
20
20
 
21
21
  /**
22
22
  * Comprehensive tests for feedback renderer components
@@ -17,7 +17,7 @@ import {
17
17
  // Import renderers to ensure registration
18
18
  beforeAll(async () => {
19
19
  await import('../renderers');
20
- });
20
+ }, 30000); // Increase timeout to 30 seconds for heavy renderer imports
21
21
 
22
22
  /**
23
23
  * Comprehensive tests for form renderer components
@@ -16,7 +16,7 @@ import {
16
16
  // Import renderers to ensure registration
17
17
  beforeAll(async () => {
18
18
  await import('../renderers');
19
- });
19
+ }, 30000); // Increase timeout to 30 seconds for heavy renderer imports
20
20
 
21
21
  /**
22
22
  * Comprehensive tests for layout renderer components
@@ -10,7 +10,7 @@ import { Slot } from "@radix-ui/react-slot"
10
10
  import { cva, type VariantProps } from "class-variance-authority"
11
11
 
12
12
  import { cn } from "../lib/utils"
13
- import { Separator } from "./separator"
13
+ import { Separator } from "../ui/separator"
14
14
 
15
15
  const buttonGroupVariants = cva(
16
16
  "flex w-fit items-stretch [&>*]:focus-visible:z-10 [&>*]:focus-visible:relative [&>[data-slot=select-trigger]:not([class*='w-'])]:w-fit [&>input]:flex-1 has-[select[aria-hidden=true]:last-child]:[&>[data-slot=select-trigger]:last-of-type]:rounded-r-md has-[>[data-slot=button-group]]:gap-2",
@@ -12,7 +12,7 @@ import * as React from "react"
12
12
  import { Check, ChevronsUpDown } from "lucide-react"
13
13
 
14
14
  import { cn } from "../lib/utils"
15
- import { Button } from "./button"
15
+ import { Button } from "../ui/button"
16
16
  import {
17
17
  Command,
18
18
  CommandEmpty,
@@ -20,12 +20,12 @@ import {
20
20
  CommandInput,
21
21
  CommandItem,
22
22
  CommandList,
23
- } from "./command"
23
+ } from "../ui/command"
24
24
  import {
25
25
  Popover,
26
26
  PopoverContent,
27
27
  PopoverTrigger,
28
- } from "./popover"
28
+ } from "../ui/popover"
29
29
 
30
30
  export interface ComboboxOption {
31
31
  value: string
@@ -13,9 +13,9 @@ import { CalendarIcon } from "lucide-react"
13
13
  import { format } from "date-fns"
14
14
 
15
15
  import { cn } from "../lib/utils"
16
- import { Button } from "./button"
17
- import { Calendar } from "./calendar"
18
- import { Popover, PopoverContent, PopoverTrigger } from "./popover"
16
+ import { Button } from "../ui/button"
17
+ import { Calendar } from "../ui/calendar"
18
+ import { Popover, PopoverContent, PopoverTrigger } from "../ui/popover"
19
19
 
20
20
  export interface DatePickerProps {
21
21
  date?: Date
@@ -0,0 +1,81 @@
1
+ /**
2
+ * ObjectUI
3
+ * Copyright (c) 2024-present ObjectStack Inc.
4
+ *
5
+ * This source code is licensed under the MIT license found in the
6
+ * LICENSE file in the root directory of this source tree.
7
+ */
8
+
9
+ import * as React from "react"
10
+ import { Slot } from "@radix-ui/react-slot"
11
+ import { cva, type VariantProps } from "class-variance-authority"
12
+
13
+ import { cn } from "../lib/utils"
14
+ import { Label } from "../ui/label"
15
+
16
+ const fieldVariants = cva("space-y-2")
17
+
18
+ export interface FieldProps
19
+ extends React.HTMLAttributes<HTMLDivElement>,
20
+ VariantProps<typeof fieldVariants> {
21
+ label?: React.ReactNode
22
+ description?: React.ReactNode
23
+ error?: React.ReactNode
24
+ required?: boolean
25
+ htmlFor?: string
26
+ }
27
+
28
+ const Field = React.forwardRef<HTMLDivElement, FieldProps>(
29
+ ({ className, label, description, error, required, htmlFor, children, ...props }, ref) => {
30
+ const id = React.useId()
31
+ const fieldId = htmlFor || id
32
+ const descriptionId = `${fieldId}-description`
33
+ const errorId = `${fieldId}-error`
34
+
35
+ return (
36
+ <div ref={ref} className={cn(fieldVariants(), className)} {...props}>
37
+ {label && (
38
+ <Label
39
+ htmlFor={fieldId}
40
+ className={cn(error && "text-destructive", required && "after:content-['*'] after:ml-0.5 after:text-destructive")}
41
+ >
42
+ {label}
43
+ </Label>
44
+ )}
45
+
46
+ <Slot
47
+ id={fieldId}
48
+ aria-describedby={
49
+ [description && descriptionId, error && errorId]
50
+ .filter(Boolean)
51
+ .join(" ") || undefined
52
+ }
53
+ aria-invalid={!!error}
54
+ >
55
+ {children}
56
+ </Slot>
57
+
58
+ {description && !error && (
59
+ <p
60
+ id={descriptionId}
61
+ className="text-[0.8rem] text-muted-foreground"
62
+ >
63
+ {description}
64
+ </p>
65
+ )}
66
+
67
+ {error && (
68
+ <p
69
+ id={errorId}
70
+ className="text-[0.8rem] font-medium text-destructive"
71
+ >
72
+ {error}
73
+ </p>
74
+ )}
75
+ </div>
76
+ )
77
+ }
78
+ )
79
+ Field.displayName = "Field"
80
+
81
+ export { Field }
@@ -12,9 +12,9 @@ import * as React from "react"
12
12
  import { X, Plus, Trash2 } from "lucide-react"
13
13
 
14
14
  import { cn } from "../lib/utils"
15
- import { Button } from "./button"
16
- import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from "./select"
17
- import { Input } from "./input"
15
+ import { Button } from "../ui/button"
16
+ import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from "../ui/select"
17
+ import { Input } from "../ui/input"
18
18
 
19
19
  export interface FilterCondition {
20
20
  id: string
@@ -0,0 +1,12 @@
1
+ export * from './button-group';
2
+ export * from './combobox';
3
+ export * from './date-picker';
4
+ export * from './empty';
5
+ export * from './field';
6
+ export * from './filter-builder';
7
+ export * from './input-group';
8
+ export * from './item';
9
+ export * from './kbd';
10
+ export * from './native-select';
11
+ export * from './spinner';
12
+ export * from './sort-builder';
@@ -0,0 +1,53 @@
1
+ /**
2
+ * ObjectUI
3
+ * Copyright (c) 2024-present ObjectStack Inc.
4
+ *
5
+ * This source code is licensed under the MIT license found in the
6
+ * LICENSE file in the root directory of this source tree.
7
+ */
8
+
9
+ import * as React from "react"
10
+ import { cn } from "../lib/utils"
11
+ import { Input } from "../ui/input"
12
+ import { Button } from "../ui/button"
13
+
14
+ export interface InputGroupProps extends React.ComponentProps<"div"> {
15
+ startContent?: React.ReactNode
16
+ endContent?: React.ReactNode
17
+ }
18
+
19
+ const InputGroup = React.forwardRef<HTMLDivElement, InputGroupProps>(
20
+ ({ className, startContent, endContent, children, ...props }, ref) => {
21
+ return (
22
+ <div
23
+ ref={ref}
24
+ className={cn(
25
+ "flex w-full items-center rounded-md border border-input bg-transparent ring-offset-background focus-within:ring-2 focus-within:ring-ring focus-within:ring-offset-2",
26
+ "has-[[data-invalid]]:border-destructive",
27
+ className
28
+ )}
29
+ {...props}
30
+ >
31
+ {startContent && (
32
+ <div className="flex items-center px-3 text-muted-foreground bg-muted/50 border-r h-full self-stretch rounded-l-md">
33
+ {startContent}
34
+ </div>
35
+ )}
36
+
37
+ {/* We need to process children to remove their default borders/rings if they are Inputs */}
38
+ <div className="flex-1 relative [&_input]:border-0 [&_input]:shadow-none [&_input]:focus-visible:ring-0 [&_input]:bg-transparent">
39
+ {children}
40
+ </div>
41
+
42
+ {endContent && (
43
+ <div className="flex items-center px-3 text-muted-foreground bg-muted/50 border-l h-full self-stretch rounded-r-md">
44
+ {endContent}
45
+ </div>
46
+ )}
47
+ </div>
48
+ )
49
+ }
50
+ )
51
+ InputGroup.displayName = "InputGroup"
52
+
53
+ export { InputGroup }
@@ -11,7 +11,7 @@ import { Slot } from "@radix-ui/react-slot"
11
11
  import { cva, type VariantProps } from "class-variance-authority"
12
12
 
13
13
  import { cn } from "../lib/utils"
14
- import { Separator } from "./separator"
14
+ import { Separator } from "../ui/separator"
15
15
 
16
16
  function ItemGroup({ className, ...props }: React.ComponentProps<"div">) {
17
17
  return (
@@ -0,0 +1,33 @@
1
+ /**
2
+ * ObjectUI
3
+ * Copyright (c) 2024-present ObjectStack Inc.
4
+ *
5
+ * This source code is licensed under the MIT license found in the
6
+ * LICENSE file in the root directory of this source tree.
7
+ */
8
+
9
+ import * as React from "react"
10
+ import { cn } from "../lib/utils"
11
+
12
+ // eslint-disable-next-line @typescript-eslint/no-empty-object-type
13
+ export interface NativeSelectProps extends React.SelectHTMLAttributes<HTMLSelectElement> {}
14
+
15
+ const NativeSelect = React.forwardRef<HTMLSelectElement, NativeSelectProps>(
16
+ ({ className, children, ...props }, ref) => {
17
+ return (
18
+ <select
19
+ className={cn(
20
+ "flex h-10 w-full items-center justify-between rounded-md border border-input bg-background px-3 py-2 text-sm ring-offset-background placeholder:text-muted-foreground focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50",
21
+ className
22
+ )}
23
+ ref={ref}
24
+ {...props}
25
+ >
26
+ {children}
27
+ </select>
28
+ )
29
+ }
30
+ )
31
+ NativeSelect.displayName = "NativeSelect"
32
+
33
+ export { NativeSelect }
@@ -0,0 +1,129 @@
1
+ /**
2
+ * ObjectUI
3
+ * Copyright (c) 2024-present ObjectStack Inc.
4
+ *
5
+ * This source code is licensed under the MIT license found in the
6
+ * LICENSE file in the root directory of this source tree.
7
+ */
8
+
9
+ import * as React from "react"
10
+ import { X, Plus, Trash2 } from "lucide-react"
11
+
12
+ import { cn } from "../lib/utils"
13
+ import { Button } from "../ui/button"
14
+ import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from "../ui/select"
15
+
16
+ export interface SortItem {
17
+ id: string;
18
+ field: string;
19
+ order: 'asc' | 'desc';
20
+ }
21
+
22
+ export interface SortBuilderProps {
23
+ fields?: Array<{
24
+ value: string
25
+ label: string
26
+ }>;
27
+ value?: SortItem[];
28
+ onChange?: (value: SortItem[]) => void;
29
+ className?: string;
30
+ }
31
+
32
+ export function SortBuilder({
33
+ fields = [],
34
+ value = [],
35
+ onChange,
36
+ className,
37
+ }: SortBuilderProps) {
38
+ // Use internal state initialization prop changes
39
+ const [items, setItems] = React.useState<SortItem[]>(value || []);
40
+
41
+ React.useEffect(() => {
42
+ if (value && JSON.stringify(value) !== JSON.stringify(items)) {
43
+ setItems(value);
44
+ }
45
+ }, [value]);
46
+
47
+ const handleChange = (newItems: SortItem[]) => {
48
+ setItems(newItems);
49
+ onChange?.(newItems);
50
+ };
51
+
52
+ const addItem = () => {
53
+ const newItem: SortItem = {
54
+ id: crypto.randomUUID(),
55
+ field: fields[0]?.value || "",
56
+ order: 'asc',
57
+ };
58
+ handleChange([...items, newItem]);
59
+ };
60
+
61
+ const updateItem = (id: string, updates: Partial<SortItem>) => {
62
+ handleChange(items.map(item => item.id === id ? { ...item, ...updates } : item));
63
+ };
64
+
65
+ const removeItem = (id: string) => {
66
+ handleChange(items.filter(item => item.id !== id));
67
+ };
68
+
69
+ return (
70
+ <div className={cn("space-y-3", className)}>
71
+ <div className="space-y-2">
72
+ {items.map((item, index) => (
73
+ <div key={item.id} className="flex items-center gap-2">
74
+ <span className="text-sm font-medium w-16 text-muted-foreground">
75
+ {index === 0 ? "Sort by" : "Then by"}
76
+ </span>
77
+ <div className="flex-1">
78
+ <Select
79
+ value={item.field}
80
+ onValueChange={(val) => updateItem(item.id, { field: val })}
81
+ >
82
+ <SelectTrigger className="h-9">
83
+ <SelectValue placeholder="Select field" />
84
+ </SelectTrigger>
85
+ <SelectContent>
86
+ {fields.map(f => (
87
+ <SelectItem key={f.value} value={f.value}>{f.label}</SelectItem>
88
+ ))}
89
+ </SelectContent>
90
+ </Select>
91
+ </div>
92
+ <div className="w-28">
93
+ <Select
94
+ value={item.order}
95
+ onValueChange={(val) => updateItem(item.id, { order: val as 'asc' | 'desc' })}
96
+ >
97
+ <SelectTrigger className="h-9">
98
+ <SelectValue />
99
+ </SelectTrigger>
100
+ <SelectContent>
101
+ <SelectItem value="asc">A -&gt; Z</SelectItem>
102
+ <SelectItem value="desc">Z -&gt; A</SelectItem>
103
+ </SelectContent>
104
+ </Select>
105
+ </div>
106
+ <Button
107
+ variant="ghost"
108
+ size="icon-sm"
109
+ className="h-9 w-9 shrink-0"
110
+ onClick={() => removeItem(item.id)}
111
+ >
112
+ <X className="h-4 w-4" />
113
+ </Button>
114
+ </div>
115
+ ))}
116
+ </div>
117
+ <Button
118
+ variant="outline"
119
+ size="sm"
120
+ onClick={addItem}
121
+ className="h-8"
122
+ disabled={fields.length === 0}
123
+ >
124
+ <Plus className="h-3 w-3 mr-2" />
125
+ Add sort
126
+ </Button>
127
+ </div>
128
+ );
129
+ }
package/src/index.css CHANGED
@@ -1,7 +1,7 @@
1
1
  @import 'tailwindcss';
2
2
 
3
3
  /* Scan sources for Tailwind classes */
4
- @source './src/**/*.{ts,tsx}';
4
+ @source '../src/**/*.{ts,tsx}';
5
5
 
6
6
  /* Tailwind plugin for animations */
7
7
  @plugin 'tailwindcss-animate';
@@ -33,6 +33,13 @@
33
33
  --color-popover-foreground: hsl(var(--popover-foreground));
34
34
  --color-card: hsl(var(--card));
35
35
  --color-card-foreground: hsl(var(--card-foreground));
36
+
37
+ /* Chart colors */
38
+ --color-chart-1: hsl(var(--chart-1));
39
+ --color-chart-2: hsl(var(--chart-2));
40
+ --color-chart-3: hsl(var(--chart-3));
41
+ --color-chart-4: hsl(var(--chart-4));
42
+ --color-chart-5: hsl(var(--chart-5));
36
43
  }
37
44
 
38
45
  /* CSS custom properties for theme */
@@ -66,6 +73,12 @@
66
73
  --ring: 222.2 84% 4.9%;
67
74
 
68
75
  --radius: 0.5rem;
76
+
77
+ --chart-1: 12 76% 61%;
78
+ --chart-2: 173 58% 39%;
79
+ --chart-3: 197 37% 24%;
80
+ --chart-4: 43 74% 66%;
81
+ --chart-5: 27 87% 67%;
69
82
  }
70
83
 
71
84
  .dark {
@@ -96,6 +109,12 @@
96
109
  --border: 217.2 32.6% 17.5%;
97
110
  --input: 217.2 32.6% 17.5%;
98
111
  --ring: 212.7 26.8% 83.9%;
112
+
113
+ --chart-1: 220 70% 50%;
114
+ --chart-2: 160 60% 45%;
115
+ --chart-3: 30 80% 55%;
116
+ --chart-4: 280 65% 60%;
117
+ --chart-5: 340 75% 55%;
99
118
  }
100
119
 
101
120
  * {
package/src/index.ts CHANGED
@@ -20,6 +20,7 @@ export { registerPlaceholders } from './renderers/placeholders';
20
20
 
21
21
  // Export raw Shadcn UI components
22
22
  export * from './ui';
23
+ export * from './custom';
23
24
 
24
25
  // Export an init function to ensure components are registered
25
26
  // This is a workaround for bundlers that might tree-shake side-effect imports
@@ -47,6 +47,7 @@ ComponentRegistry.register('button-group',
47
47
  );
48
48
  },
49
49
  {
50
+ namespace: 'ui',
50
51
  label: 'Button Group',
51
52
  inputs: [
52
53
  {
@@ -13,6 +13,16 @@ import { forwardRef } from 'react';
13
13
 
14
14
  const DivRenderer = forwardRef<HTMLDivElement, { schema: DivSchema; 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 "div" component is deprecated. Please use Shadcn components instead:\n' +
20
+ ' - For containers: use "card", "flex", or semantic layout components\n' +
21
+ ' - For simple wrappers: use layout components like "container", "stack", or "grid"\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 DivRenderer = forwardRef<HTMLDivElement, { schema: DivSchema; className?:
38
48
  ComponentRegistry.register('div',
39
49
  DivRenderer,
40
50
  {
41
- label: 'Container',
51
+ namespace: 'ui',
52
+ label: 'Container (Deprecated)',
42
53
  inputs: [
43
54
  { name: 'className', type: 'string', label: 'CSS Class' }
44
55
  ],
@@ -34,6 +34,7 @@ ComponentRegistry.register('html',
34
34
  );
35
35
  },
36
36
  {
37
+ namespace: 'ui',
37
38
  label: 'HTML Content',
38
39
  inputs: [
39
40
  { name: 'html', type: 'string', label: 'HTML', description: 'Raw HTML content' }
@@ -75,6 +75,7 @@ IconRenderer.displayName = 'IconRenderer';
75
75
  ComponentRegistry.register('icon',
76
76
  IconRenderer,
77
77
  {
78
+ namespace: 'ui',
78
79
  label: 'Icon',
79
80
  icon: 'smile',
80
81
  category: 'basic',