@object-ui/components 0.3.1 → 2.0.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 (326) hide show
  1. package/.turbo/turbo-build.log +34 -0
  2. package/CHANGELOG.md +13 -0
  3. package/README.md +13 -0
  4. package/dist/index.css +1 -1
  5. package/dist/index.js +36430 -25529
  6. package/dist/index.umd.cjs +53 -32
  7. package/dist/src/SchemaRenderer.d.ts +3 -0
  8. package/dist/src/custom/action-param-dialog.d.ts +21 -0
  9. package/dist/src/{ui → custom}/button-group.d.ts +1 -1
  10. package/dist/src/custom/field.d.ts +19 -0
  11. package/dist/src/custom/index.d.ts +14 -0
  12. package/dist/src/custom/input-group.d.ts +14 -0
  13. package/dist/src/{ui → custom}/item.d.ts +1 -1
  14. package/dist/src/custom/native-select.d.ts +12 -0
  15. package/dist/src/custom/navigation-overlay.d.ts +50 -0
  16. package/dist/src/custom/sort-builder.d.ts +22 -0
  17. package/dist/src/index.d.ts +2 -0
  18. package/dist/src/renderers/action/action-button.d.ts +11 -0
  19. package/dist/src/renderers/action/action-group.d.ts +25 -0
  20. package/dist/src/renderers/action/action-icon.d.ts +10 -0
  21. package/dist/src/renderers/action/action-menu.d.ts +19 -0
  22. package/dist/src/renderers/action/index.d.ts +0 -0
  23. package/dist/src/renderers/action/resolve-icon.d.ts +6 -0
  24. package/dist/src/renderers/data-display/table.d.ts +1 -1
  25. package/dist/src/renderers/layout/page.d.ts +1 -1
  26. package/dist/src/renderers/placeholders.d.ts +1 -1
  27. package/dist/src/ui/accordion.d.ts +4 -4
  28. package/dist/src/ui/alert-dialog.d.ts +17 -11
  29. package/dist/src/ui/alert.d.ts +4 -5
  30. package/dist/src/ui/aspect-ratio.d.ts +1 -1
  31. package/dist/src/ui/avatar.d.ts +3 -3
  32. package/dist/src/ui/badge.d.ts +3 -3
  33. package/dist/src/ui/breadcrumb.d.ts +16 -8
  34. package/dist/src/ui/calendar.d.ts +7 -7
  35. package/dist/src/ui/card.d.ts +7 -8
  36. package/dist/src/ui/carousel.d.ts +5 -6
  37. package/dist/src/ui/chart.d.ts +62 -0
  38. package/dist/src/ui/checkbox.d.ts +1 -1
  39. package/dist/src/ui/collapsible.d.ts +3 -3
  40. package/dist/src/ui/command.d.ts +78 -16
  41. package/dist/src/ui/context-menu.d.ts +14 -12
  42. package/dist/src/ui/dialog.d.ts +17 -13
  43. package/dist/src/ui/drawer.d.ts +19 -10
  44. package/dist/src/ui/dropdown-menu.d.ts +20 -18
  45. package/dist/src/ui/form.d.ts +6 -7
  46. package/dist/src/ui/hover-card.d.ts +3 -3
  47. package/dist/src/ui/index.d.ts +2 -8
  48. package/dist/src/ui/input-otp.d.ts +30 -7
  49. package/dist/src/ui/label.d.ts +2 -1
  50. package/dist/src/ui/menubar.d.ts +19 -17
  51. package/dist/src/ui/navigation-menu.d.ts +9 -11
  52. package/dist/src/ui/pagination.d.ts +25 -10
  53. package/dist/src/ui/popover.d.ts +4 -5
  54. package/dist/src/ui/progress.d.ts +1 -1
  55. package/dist/src/ui/radio-group.d.ts +2 -2
  56. package/dist/src/ui/resizable.d.ts +5 -8
  57. package/dist/src/ui/scroll-area.d.ts +2 -2
  58. package/dist/src/ui/select.d.ts +11 -13
  59. package/dist/src/ui/sheet.d.ts +23 -11
  60. package/dist/src/ui/sidebar.d.ts +27 -29
  61. package/dist/src/ui/skeleton.d.ts +1 -1
  62. package/dist/src/ui/slider.d.ts +1 -1
  63. package/dist/src/ui/sonner.d.ts +2 -1
  64. package/dist/src/ui/switch.d.ts +2 -2
  65. package/dist/src/ui/tabs.d.ts +1 -1
  66. package/dist/src/ui/textarea.d.ts +1 -1
  67. package/dist/src/ui/toast.d.ts +22 -0
  68. package/dist/src/ui/toggle-group.d.ts +8 -3
  69. package/dist/src/ui/toggle.d.ts +4 -1
  70. package/dist/src/ui/tooltip.d.ts +4 -4
  71. package/dist/src/ui/typography.d.ts +21 -0
  72. package/package.json +20 -9
  73. package/shadcn-components.json +52 -47
  74. package/src/SchemaRenderer.tsx +28 -0
  75. package/src/__tests__/PageRendererRegions.test.tsx +668 -0
  76. package/src/__tests__/Registry.test.ts +21 -0
  77. package/src/__tests__/basic-renderers.test.tsx +1 -1
  78. package/src/__tests__/complex-disclosure-renderers.test.tsx +3 -2
  79. package/src/__tests__/compliance.test.tsx +72 -0
  80. package/src/__tests__/feedback-overlay-renderers.test.tsx +1 -1
  81. package/src/__tests__/form-renderers.test.tsx +1 -1
  82. package/src/__tests__/layout-data-renderers.test.tsx +1 -1
  83. package/src/__tests__/navigation-overlay.test.tsx +273 -0
  84. package/src/__tests__/view-compliance.test.tsx +153 -0
  85. package/src/custom/action-param-dialog.tsx +264 -0
  86. package/src/{ui → custom}/button-group.tsx +1 -1
  87. package/src/{ui → custom}/combobox.tsx +3 -3
  88. package/src/{ui → custom}/date-picker.tsx +3 -3
  89. package/src/custom/field.tsx +81 -0
  90. package/src/{ui → custom}/filter-builder.tsx +3 -3
  91. package/src/custom/index.ts +14 -0
  92. package/src/custom/input-group.tsx +53 -0
  93. package/src/{ui → custom}/item.tsx +1 -1
  94. package/src/custom/native-select.tsx +33 -0
  95. package/src/custom/navigation-overlay.tsx +296 -0
  96. package/src/custom/sort-builder.tsx +129 -0
  97. package/src/index.css +20 -1
  98. package/src/index.ts +2 -0
  99. package/src/renderers/action/action-button.tsx +147 -0
  100. package/src/renderers/action/action-group.tsx +270 -0
  101. package/src/renderers/action/action-icon.tsx +150 -0
  102. package/src/renderers/action/action-menu.tsx +203 -0
  103. package/src/renderers/action/index.ts +18 -0
  104. package/src/renderers/action/resolve-icon.ts +35 -0
  105. package/src/renderers/basic/button-group.tsx +1 -0
  106. package/src/renderers/basic/div.tsx +12 -1
  107. package/src/renderers/basic/html.tsx +1 -0
  108. package/src/renderers/basic/icon.tsx +1 -0
  109. package/src/renderers/basic/image.tsx +1 -0
  110. package/src/renderers/basic/navigation-menu.tsx +1 -0
  111. package/src/renderers/basic/pagination.tsx +31 -4
  112. package/src/renderers/basic/separator.tsx +1 -0
  113. package/src/renderers/basic/span.tsx +12 -1
  114. package/src/renderers/basic/text.tsx +4 -2
  115. package/src/renderers/complex/__tests__/data-table-batch-editing.test.tsx +275 -0
  116. package/src/renderers/complex/__tests__/data-table-cell-renderer.test.tsx +120 -0
  117. package/src/renderers/complex/__tests__/data-table-editing.test.tsx +221 -0
  118. package/src/renderers/complex/carousel.tsx +1 -0
  119. package/src/renderers/complex/data-table.tsx +355 -95
  120. package/src/renderers/complex/filter-builder.tsx +2 -1
  121. package/src/renderers/complex/resizable.tsx +2 -1
  122. package/src/renderers/complex/scroll-area.tsx +25 -7
  123. package/src/renderers/complex/table.tsx +1 -0
  124. package/src/renderers/data-display/alert.tsx +1 -0
  125. package/src/renderers/data-display/avatar.tsx +1 -0
  126. package/src/renderers/data-display/badge.tsx +1 -0
  127. package/src/renderers/data-display/breadcrumb.tsx +1 -0
  128. package/src/renderers/data-display/kbd.tsx +1 -0
  129. package/src/renderers/data-display/list.tsx +21 -49
  130. package/src/renderers/data-display/statistic.tsx +21 -5
  131. package/src/renderers/data-display/table.tsx +21 -11
  132. package/src/renderers/data-display/tree-view.tsx +7 -1
  133. package/src/renderers/disclosure/accordion.tsx +1 -0
  134. package/src/renderers/disclosure/collapsible.tsx +1 -0
  135. package/src/renderers/disclosure/toggle-group.tsx +2 -0
  136. package/src/renderers/feedback/empty.tsx +1 -0
  137. package/src/renderers/feedback/loading.tsx +2 -1
  138. package/src/renderers/feedback/progress.tsx +1 -0
  139. package/src/renderers/feedback/skeleton.tsx +1 -0
  140. package/src/renderers/feedback/sonner.tsx +1 -0
  141. package/src/renderers/feedback/spinner.tsx +1 -0
  142. package/src/renderers/feedback/toast.tsx +1 -0
  143. package/src/renderers/feedback/toaster.tsx +1 -0
  144. package/src/renderers/form/button.tsx +35 -1
  145. package/src/renderers/form/calendar.tsx +1 -0
  146. package/src/renderers/form/checkbox.tsx +38 -16
  147. package/src/renderers/form/combobox.tsx +2 -1
  148. package/src/renderers/form/command.tsx +1 -0
  149. package/src/renderers/form/date-picker.tsx +1 -0
  150. package/src/renderers/form/file-upload.tsx +1 -0
  151. package/src/renderers/form/form.tsx +115 -19
  152. package/src/renderers/form/input-otp.tsx +1 -0
  153. package/src/renderers/form/input.tsx +3 -0
  154. package/src/renderers/form/label.tsx +1 -0
  155. package/src/renderers/form/radio-group.tsx +1 -0
  156. package/src/renderers/form/select.tsx +35 -15
  157. package/src/renderers/form/slider.tsx +1 -0
  158. package/src/renderers/form/switch.tsx +1 -0
  159. package/src/renderers/form/textarea.tsx +50 -27
  160. package/src/renderers/form/toggle.tsx +3 -45
  161. package/src/renderers/index.ts +1 -0
  162. package/src/renderers/layout/aspect-ratio.tsx +2 -1
  163. package/src/renderers/layout/card.tsx +10 -2
  164. package/src/renderers/layout/container.tsx +1 -0
  165. package/src/renderers/layout/flex.tsx +1 -0
  166. package/src/renderers/layout/grid.tsx +23 -8
  167. package/src/renderers/layout/page.tsx +433 -57
  168. package/src/renderers/layout/semantic.tsx +1 -0
  169. package/src/renderers/layout/stack.tsx +2 -1
  170. package/src/renderers/layout/tabs.tsx +43 -17
  171. package/src/renderers/navigation/header-bar.tsx +1 -0
  172. package/src/renderers/navigation/sidebar.tsx +11 -0
  173. package/src/renderers/overlay/alert-dialog.tsx +1 -0
  174. package/src/renderers/overlay/context-menu.tsx +1 -0
  175. package/src/renderers/overlay/dialog.tsx +1 -0
  176. package/src/renderers/overlay/drawer.tsx +1 -0
  177. package/src/renderers/overlay/dropdown-menu.tsx +1 -0
  178. package/src/renderers/overlay/hover-card.tsx +1 -0
  179. package/src/renderers/overlay/menubar.tsx +1 -0
  180. package/src/renderers/overlay/popover.tsx +1 -0
  181. package/src/renderers/overlay/sheet.tsx +1 -0
  182. package/src/renderers/overlay/tooltip.tsx +1 -0
  183. package/src/renderers/placeholders.tsx +4 -4
  184. package/src/stories/CRMApp.stories.tsx +706 -0
  185. package/src/stories/Guide.mdx +55 -0
  186. package/src/stories/Introduction.mdx +61 -0
  187. package/src/stories/MockedData.stories.tsx +121 -0
  188. package/src/stories/assets/accessibility.png +0 -0
  189. package/src/stories/assets/accessibility.svg +1 -0
  190. package/src/stories/assets/addon-library.png +0 -0
  191. package/src/stories/assets/assets.png +0 -0
  192. package/src/stories/assets/avif-test-image.avif +0 -0
  193. package/src/stories/assets/context.png +0 -0
  194. package/src/stories/assets/discord.svg +1 -0
  195. package/src/stories/assets/docs.png +0 -0
  196. package/src/stories/assets/figma-plugin.png +0 -0
  197. package/src/stories/assets/github.svg +1 -0
  198. package/src/stories/assets/share.png +0 -0
  199. package/src/stories/assets/styling.png +0 -0
  200. package/src/stories/assets/testing.png +0 -0
  201. package/src/stories/assets/theming.png +0 -0
  202. package/src/stories/assets/tutorials.svg +1 -0
  203. package/src/stories/assets/youtube.svg +1 -0
  204. package/src/stories/button.css +30 -0
  205. package/src/stories/header.css +32 -0
  206. package/src/stories/page.css +68 -0
  207. package/src/stories-json/accordion.stories.tsx +43 -0
  208. package/src/stories-json/aggrid.stories.tsx +103 -0
  209. package/src/stories-json/alert.stories.tsx +39 -0
  210. package/src/stories-json/aspect-ratio.stories.tsx +34 -0
  211. package/src/stories-json/avatar.stories.tsx +38 -0
  212. package/src/stories-json/badge.stories.tsx +53 -0
  213. package/src/stories-json/breadcrumb.stories.tsx +30 -0
  214. package/src/stories-json/button-group.stories.tsx +43 -0
  215. package/src/stories-json/button.stories.tsx +73 -0
  216. package/src/stories-json/calendar.stories.tsx +85 -0
  217. package/src/stories-json/card.stories.tsx +48 -0
  218. package/src/stories-json/carousel.stories.tsx +33 -0
  219. package/src/stories-json/charts.stories.tsx +195 -0
  220. package/src/stories-json/chatbot.stories.tsx +248 -0
  221. package/src/stories-json/code-editor.stories.tsx +92 -0
  222. package/src/stories-json/collapsible.stories.tsx +40 -0
  223. package/src/stories-json/controls.stories.tsx +36 -0
  224. package/src/stories-json/crm-live-data.stories.tsx +154 -0
  225. package/src/stories-json/dashboard.stories.tsx +318 -0
  226. package/src/stories-json/data-table.stories.tsx +136 -0
  227. package/src/stories-json/data_display_extras.stories.tsx +102 -0
  228. package/src/stories-json/date-picker.stories.tsx +28 -0
  229. package/src/stories-json/detail-view.stories.tsx +258 -0
  230. package/src/stories-json/dialog.stories.tsx +43 -0
  231. package/src/stories-json/feedback_extras.stories.tsx +40 -0
  232. package/src/stories-json/feedback_others.stories.tsx +46 -0
  233. package/src/stories-json/form-variants.stories.tsx +210 -0
  234. package/src/stories-json/form_advanced.stories.tsx +117 -0
  235. package/src/stories-json/form_extras.stories.tsx +123 -0
  236. package/src/stories-json/grid.stories.tsx +56 -0
  237. package/src/stories-json/icon.stories.tsx +36 -0
  238. package/src/stories-json/input.stories.tsx +52 -0
  239. package/src/stories-json/kanban.stories.tsx +295 -0
  240. package/src/stories-json/layout_extended.stories.tsx +76 -0
  241. package/src/stories-json/layout_flex.stories.tsx +107 -0
  242. package/src/stories-json/list-view.stories.tsx +97 -0
  243. package/src/stories-json/markdown.stories.tsx +129 -0
  244. package/src/stories-json/menus.stories.tsx +63 -0
  245. package/src/stories-json/metric-card.stories.tsx +143 -0
  246. package/src/stories-json/navigation-menu.stories.tsx +37 -0
  247. package/src/stories-json/object-aggrid-advanced.stories.tsx +389 -0
  248. package/src/stories-json/object-aggrid.stories.tsx +252 -0
  249. package/src/stories-json/object-form.stories.tsx +130 -0
  250. package/src/stories-json/object-gantt.stories.tsx +114 -0
  251. package/src/stories-json/object-grid.stories.tsx +315 -0
  252. package/src/stories-json/object-map.stories.tsx +116 -0
  253. package/src/stories-json/object-view.stories.tsx +118 -0
  254. package/src/stories-json/overlay_extras.stories.tsx +113 -0
  255. package/src/stories-json/overlay_others.stories.tsx +76 -0
  256. package/src/stories-json/page.stories.tsx +55 -0
  257. package/src/stories-json/reports.stories.tsx +163 -0
  258. package/src/stories-json/resizable.stories.tsx +44 -0
  259. package/src/stories-json/select.stories.tsx +34 -0
  260. package/src/stories-json/separator.stories.tsx +41 -0
  261. package/src/stories-json/sidebar.stories.tsx +147 -0
  262. package/src/stories-json/statistic.stories.tsx +44 -0
  263. package/src/stories-json/tabs.stories.tsx +51 -0
  264. package/src/stories-json/timeline.stories.tsx +188 -0
  265. package/src/stories-json/typography.stories.tsx +45 -0
  266. package/src/ui/accordion.tsx +47 -53
  267. package/src/ui/alert-dialog.tsx +103 -117
  268. package/src/ui/alert.tsx +35 -36
  269. package/src/ui/aspect-ratio.tsx +1 -5
  270. package/src/ui/avatar.tsx +41 -42
  271. package/src/ui/badge.tsx +6 -15
  272. package/src/ui/breadcrumb.tsx +81 -75
  273. package/src/ui/button.tsx +10 -11
  274. package/src/ui/calendar.tsx +178 -51
  275. package/src/ui/card.tsx +51 -110
  276. package/src/ui/carousel.tsx +136 -113
  277. package/src/ui/chart.tsx +367 -0
  278. package/src/ui/checkbox.tsx +20 -22
  279. package/src/ui/collapsible.tsx +5 -25
  280. package/src/ui/command.tsx +106 -135
  281. package/src/ui/context-menu.tsx +69 -116
  282. package/src/ui/dialog.tsx +94 -113
  283. package/src/ui/drawer.tsx +82 -99
  284. package/src/ui/dropdown-menu.tsx +134 -188
  285. package/src/ui/form.tsx +51 -40
  286. package/src/ui/hover-card.tsx +18 -33
  287. package/src/ui/index.ts +2 -8
  288. package/src/ui/input-otp.tsx +42 -52
  289. package/src/ui/input.tsx +13 -15
  290. package/src/ui/label.tsx +17 -15
  291. package/src/ui/menubar.tsx +188 -206
  292. package/src/ui/navigation-menu.tsx +96 -136
  293. package/src/ui/pagination.tsx +86 -96
  294. package/src/ui/popover.tsx +24 -41
  295. package/src/ui/progress.tsx +21 -22
  296. package/src/ui/radio-group.tsx +19 -20
  297. package/src/ui/resizable.tsx +32 -42
  298. package/src/ui/scroll-area.tsx +38 -48
  299. package/src/ui/select.tsx +129 -157
  300. package/src/ui/separator.tsx +2 -2
  301. package/src/ui/sheet.tsx +110 -107
  302. package/src/ui/sidebar.tsx +442 -408
  303. package/src/ui/skeleton.tsx +6 -11
  304. package/src/ui/slider.tsx +19 -54
  305. package/src/ui/sonner.tsx +19 -1
  306. package/src/ui/switch.tsx +19 -21
  307. package/src/ui/tabs.tsx +6 -37
  308. package/src/ui/textarea.tsx +8 -4
  309. package/src/ui/toast.tsx +137 -0
  310. package/src/ui/toggle-group.tsx +28 -37
  311. package/src/ui/toggle.tsx +19 -19
  312. package/src/ui/tooltip.tsx +21 -52
  313. package/src/ui/typography.tsx +85 -0
  314. package/tsconfig.json +1 -1
  315. package/vite.config.ts +9 -1
  316. package/vitest.config.ts +5 -0
  317. package/ISSUES_FOUND.md +0 -128
  318. /package/dist/src/{ui → custom}/combobox.d.ts +0 -0
  319. /package/dist/src/{ui → custom}/date-picker.d.ts +0 -0
  320. /package/dist/src/{ui → custom}/empty.d.ts +0 -0
  321. /package/dist/src/{ui → custom}/filter-builder.d.ts +0 -0
  322. /package/dist/src/{ui → custom}/kbd.d.ts +0 -0
  323. /package/dist/src/{ui → custom}/spinner.d.ts +0 -0
  324. /package/src/{ui → custom}/empty.tsx +0 -0
  325. /package/src/{ui → custom}/kbd.tsx +0 -0
  326. /package/src/{ui → custom}/spinner.tsx +0 -0
@@ -0,0 +1,264 @@
1
+ /**
2
+ * ObjectUI — Action Param Dialog
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
+ * Renders a dialog to collect ActionParam values before action execution.
9
+ * Used by the ActionRunner when an action defines params to collect.
10
+ */
11
+
12
+ import React, { useState, useCallback } from 'react';
13
+ import type { ActionParamDef } from '@object-ui/core';
14
+ import {
15
+ Dialog,
16
+ DialogContent,
17
+ DialogDescription,
18
+ DialogFooter,
19
+ DialogHeader,
20
+ DialogTitle,
21
+ } from '../ui/dialog';
22
+ import { Button } from '../ui/button';
23
+ import { Input } from '../ui/input';
24
+ import { Label } from '../ui/label';
25
+ import { Textarea } from '../ui/textarea';
26
+ import { Checkbox } from '../ui/checkbox';
27
+ import {
28
+ Select,
29
+ SelectContent,
30
+ SelectItem,
31
+ SelectTrigger,
32
+ SelectValue,
33
+ } from '../ui/select';
34
+
35
+ export interface ActionParamDialogProps {
36
+ /** The param definitions to render */
37
+ params: ActionParamDef[];
38
+ /** Whether the dialog is open */
39
+ open: boolean;
40
+ /** Called when the user submits the form */
41
+ onSubmit: (values: Record<string, any>) => void;
42
+ /** Called when the user cancels */
43
+ onCancel: () => void;
44
+ /** Dialog title */
45
+ title?: string;
46
+ /** Dialog description */
47
+ description?: string;
48
+ }
49
+
50
+ /**
51
+ * ActionParamDialog renders a dialog with form fields for each ActionParam.
52
+ * It collects user input and returns the values on submit.
53
+ */
54
+ export const ActionParamDialog: React.FC<ActionParamDialogProps> = ({
55
+ params,
56
+ open,
57
+ onSubmit,
58
+ onCancel,
59
+ title = 'Action Parameters',
60
+ description = 'Please provide the required parameters.',
61
+ }) => {
62
+ // Initialize values from defaultValues
63
+ const [values, setValues] = useState<Record<string, any>>(() => {
64
+ const initial: Record<string, any> = {};
65
+ params.forEach((p) => {
66
+ if (p.defaultValue !== undefined) {
67
+ initial[p.name] = p.defaultValue;
68
+ } else {
69
+ initial[p.name] = p.type === 'boolean' ? false : '';
70
+ }
71
+ });
72
+ return initial;
73
+ });
74
+
75
+ const [errors, setErrors] = useState<Record<string, string>>({});
76
+
77
+ const handleChange = useCallback((name: string, value: any) => {
78
+ setValues((prev) => ({ ...prev, [name]: value }));
79
+ // Clear error on change
80
+ setErrors((prev) => {
81
+ const next = { ...prev };
82
+ delete next[name];
83
+ return next;
84
+ });
85
+ }, []);
86
+
87
+ const handleSubmit = useCallback(() => {
88
+ // Validate required fields
89
+ const newErrors: Record<string, string> = {};
90
+ params.forEach((p) => {
91
+ if (p.required) {
92
+ const val = values[p.name];
93
+ if (val === undefined || val === null || val === '') {
94
+ newErrors[p.name] = `${p.label} is required`;
95
+ }
96
+ }
97
+ });
98
+
99
+ if (Object.keys(newErrors).length > 0) {
100
+ setErrors(newErrors);
101
+ return;
102
+ }
103
+
104
+ onSubmit(values);
105
+ }, [params, values, onSubmit]);
106
+
107
+ const renderField = (param: ActionParamDef) => {
108
+ const value = values[param.name];
109
+ const error = errors[param.name];
110
+
111
+ switch (param.type) {
112
+ case 'textarea':
113
+ return (
114
+ <div key={param.name} className="space-y-2">
115
+ <Label htmlFor={param.name}>
116
+ {param.label}
117
+ {param.required && <span className="text-destructive ml-1">*</span>}
118
+ </Label>
119
+ <Textarea
120
+ id={param.name}
121
+ value={value || ''}
122
+ onChange={(e) => handleChange(param.name, e.target.value)}
123
+ placeholder={param.placeholder}
124
+ />
125
+ {param.helpText && (
126
+ <p className="text-sm text-muted-foreground">{param.helpText}</p>
127
+ )}
128
+ {error && <p className="text-sm text-destructive">{error}</p>}
129
+ </div>
130
+ );
131
+
132
+ case 'number':
133
+ return (
134
+ <div key={param.name} className="space-y-2">
135
+ <Label htmlFor={param.name}>
136
+ {param.label}
137
+ {param.required && <span className="text-destructive ml-1">*</span>}
138
+ </Label>
139
+ <Input
140
+ id={param.name}
141
+ type="number"
142
+ value={value ?? ''}
143
+ onChange={(e) => handleChange(param.name, Number.isNaN(e.target.valueAsNumber) ? '' : e.target.valueAsNumber)}
144
+ placeholder={param.placeholder}
145
+ />
146
+ {param.helpText && (
147
+ <p className="text-sm text-muted-foreground">{param.helpText}</p>
148
+ )}
149
+ {error && <p className="text-sm text-destructive">{error}</p>}
150
+ </div>
151
+ );
152
+
153
+ case 'boolean':
154
+ return (
155
+ <div key={param.name} className="flex items-center space-x-2">
156
+ <Checkbox
157
+ id={param.name}
158
+ checked={!!value}
159
+ onCheckedChange={(checked) => handleChange(param.name, !!checked)}
160
+ />
161
+ <Label htmlFor={param.name}>{param.label}</Label>
162
+ {param.helpText && (
163
+ <p className="text-sm text-muted-foreground ml-2">{param.helpText}</p>
164
+ )}
165
+ </div>
166
+ );
167
+
168
+ case 'select':
169
+ return (
170
+ <div key={param.name} className="space-y-2">
171
+ <Label htmlFor={param.name}>
172
+ {param.label}
173
+ {param.required && <span className="text-destructive ml-1">*</span>}
174
+ </Label>
175
+ <Select
176
+ value={value || ''}
177
+ onValueChange={(val) => handleChange(param.name, val)}
178
+ >
179
+ <SelectTrigger>
180
+ <SelectValue placeholder={param.placeholder || 'Select...'} />
181
+ </SelectTrigger>
182
+ <SelectContent>
183
+ {param.options?.map((opt) => (
184
+ <SelectItem key={opt.value} value={opt.value}>
185
+ {opt.label}
186
+ </SelectItem>
187
+ ))}
188
+ </SelectContent>
189
+ </Select>
190
+ {param.helpText && (
191
+ <p className="text-sm text-muted-foreground">{param.helpText}</p>
192
+ )}
193
+ {error && <p className="text-sm text-destructive">{error}</p>}
194
+ </div>
195
+ );
196
+
197
+ case 'date':
198
+ return (
199
+ <div key={param.name} className="space-y-2">
200
+ <Label htmlFor={param.name}>
201
+ {param.label}
202
+ {param.required && <span className="text-destructive ml-1">*</span>}
203
+ </Label>
204
+ <Input
205
+ id={param.name}
206
+ type="date"
207
+ value={value || ''}
208
+ onChange={(e) => handleChange(param.name, e.target.value)}
209
+ />
210
+ {param.helpText && (
211
+ <p className="text-sm text-muted-foreground">{param.helpText}</p>
212
+ )}
213
+ {error && <p className="text-sm text-destructive">{error}</p>}
214
+ </div>
215
+ );
216
+
217
+ // text and all other types default to text input
218
+ default:
219
+ return (
220
+ <div key={param.name} className="space-y-2">
221
+ <Label htmlFor={param.name}>
222
+ {param.label}
223
+ {param.required && <span className="text-destructive ml-1">*</span>}
224
+ </Label>
225
+ <Input
226
+ id={param.name}
227
+ type="text"
228
+ value={value || ''}
229
+ onChange={(e) => handleChange(param.name, e.target.value)}
230
+ placeholder={param.placeholder}
231
+ />
232
+ {param.helpText && (
233
+ <p className="text-sm text-muted-foreground">{param.helpText}</p>
234
+ )}
235
+ {error && <p className="text-sm text-destructive">{error}</p>}
236
+ </div>
237
+ );
238
+ }
239
+ };
240
+
241
+ return (
242
+ <Dialog open={open} onOpenChange={(isOpen) => { if (!isOpen) onCancel(); }}>
243
+ <DialogContent className="sm:max-w-[425px]">
244
+ <DialogHeader>
245
+ <DialogTitle>{title}</DialogTitle>
246
+ <DialogDescription>{description}</DialogDescription>
247
+ </DialogHeader>
248
+ <div className="space-y-4 py-4">
249
+ {params.map(renderField)}
250
+ </div>
251
+ <DialogFooter>
252
+ <Button variant="outline" onClick={onCancel}>
253
+ Cancel
254
+ </Button>
255
+ <Button onClick={handleSubmit}>
256
+ Continue
257
+ </Button>
258
+ </DialogFooter>
259
+ </DialogContent>
260
+ </Dialog>
261
+ );
262
+ };
263
+
264
+ ActionParamDialog.displayName = 'ActionParamDialog';
@@ -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,14 @@
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 './navigation-overlay';
12
+ export * from './spinner';
13
+ export * from './sort-builder';
14
+ export * from './action-param-dialog';
@@ -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 }