pxengine 0.1.3 → 0.1.5
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.
- package/dist/index.cjs +9057 -2405
- package/dist/index.d.cts +105 -10
- package/dist/index.d.ts +105 -10
- package/dist/index.js +9062 -2407
- package/dist/registry.json +1388 -4364
- package/package.json +4 -4
- package/src/atoms/CardAtom.tsx +7 -7
- package/src/atoms/FormInputAtom.tsx +97 -0
- package/src/atoms/FormSelectAtom.tsx +106 -0
- package/src/atoms/FormTextareaAtom.tsx +89 -0
- package/src/atoms/LayoutAtom.tsx +5 -3
- package/src/atoms/index.ts +4 -0
- package/src/components/ui/index.ts +54 -0
- package/src/render/PXEngineRenderer.tsx +265 -242
- package/src/types/atoms.ts +8 -1
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "pxengine",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.5",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "Shadcn-based UI component library for agent-driven interfaces",
|
|
6
6
|
"main": "./dist/index.cjs",
|
|
@@ -32,12 +32,12 @@
|
|
|
32
32
|
"peerDependencies": {
|
|
33
33
|
"react": "^18.0.0",
|
|
34
34
|
"react-dom": "^18.0.0",
|
|
35
|
-
"tailwindcss": "^3.4.0"
|
|
35
|
+
"tailwindcss": "^3.4.0",
|
|
36
|
+
"@types/react": "^19.0.2",
|
|
37
|
+
"@types/react-dom": "^19.0.2"
|
|
36
38
|
},
|
|
37
39
|
"devDependencies": {
|
|
38
40
|
"@types/node": "^20.19.30",
|
|
39
|
-
"@types/react": "^19.0.2",
|
|
40
|
-
"@types/react-dom": "^19.0.2",
|
|
41
41
|
"autoprefixer": "^10.4.23",
|
|
42
42
|
"eslint": "^8.0.0",
|
|
43
43
|
"postcss": "^8.5.6",
|
package/src/atoms/CardAtom.tsx
CHANGED
|
@@ -11,7 +11,7 @@ import { CardAtomType, UIComponent } from "../types/schema";
|
|
|
11
11
|
import { cn } from "@/lib/utils";
|
|
12
12
|
|
|
13
13
|
interface Props extends CardAtomType {
|
|
14
|
-
renderComponent: (component: UIComponent) => React.ReactNode;
|
|
14
|
+
renderComponent: (component: UIComponent, index?: number) => React.ReactNode;
|
|
15
15
|
}
|
|
16
16
|
|
|
17
17
|
/**
|
|
@@ -44,17 +44,17 @@ export const CardAtom: React.FC<Props> = ({
|
|
|
44
44
|
</CardHeader>
|
|
45
45
|
)}
|
|
46
46
|
<CardContent className="space-y-4">
|
|
47
|
-
{children.map((child) => (
|
|
48
|
-
<React.Fragment key={child.id}>
|
|
49
|
-
{renderComponent(child)}
|
|
47
|
+
{children.map((child, index) => (
|
|
48
|
+
<React.Fragment key={child.id || `card-content-${index}`}>
|
|
49
|
+
{renderComponent(child, index)}
|
|
50
50
|
</React.Fragment>
|
|
51
51
|
))}
|
|
52
52
|
</CardContent>
|
|
53
53
|
{footer && footer.length > 0 && (
|
|
54
54
|
<CardFooter className="bg-gray-50/50 border-t border-gray-100 flex flex-wrap gap-2 pt-6">
|
|
55
|
-
{footer.map((footerChild) => (
|
|
56
|
-
<React.Fragment key={footerChild.id}>
|
|
57
|
-
{renderComponent(footerChild)}
|
|
55
|
+
{footer.map((footerChild, index) => (
|
|
56
|
+
<React.Fragment key={footerChild.id || `card-footer-${index}`}>
|
|
57
|
+
{renderComponent(footerChild, index)}
|
|
58
58
|
</React.Fragment>
|
|
59
59
|
))}
|
|
60
60
|
</CardFooter>
|
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
import React from "react";
|
|
2
|
+
import {
|
|
3
|
+
Form,
|
|
4
|
+
FormField,
|
|
5
|
+
FormItem,
|
|
6
|
+
FormLabel,
|
|
7
|
+
FormControl,
|
|
8
|
+
FormDescription,
|
|
9
|
+
FormMessage,
|
|
10
|
+
} from "@/components/ui/form";
|
|
11
|
+
import { Input } from "@/components/ui/input";
|
|
12
|
+
import { useForm } from "react-hook-form";
|
|
13
|
+
import { cn } from "@/lib/utils";
|
|
14
|
+
|
|
15
|
+
export interface FormInputAtomType {
|
|
16
|
+
type: "FormInput";
|
|
17
|
+
name: string;
|
|
18
|
+
label?: string;
|
|
19
|
+
placeholder?: string;
|
|
20
|
+
description?: string;
|
|
21
|
+
defaultValue?: string;
|
|
22
|
+
required?: boolean;
|
|
23
|
+
inputType?:
|
|
24
|
+
| "text"
|
|
25
|
+
| "email"
|
|
26
|
+
| "password"
|
|
27
|
+
| "number"
|
|
28
|
+
| "tel"
|
|
29
|
+
| "url"
|
|
30
|
+
| "date"
|
|
31
|
+
| "time";
|
|
32
|
+
className?: string;
|
|
33
|
+
id?: string;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
interface FormInputAtomProps extends Omit<FormInputAtomType, "type"> {
|
|
37
|
+
renderComponent?: any;
|
|
38
|
+
children?: any;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
/**
|
|
42
|
+
* FormInputAtom
|
|
43
|
+
*
|
|
44
|
+
* Self-contained form input component that properly wraps FormField, FormItem, FormLabel, and FormControl.
|
|
45
|
+
* This component provides the necessary React Context for form components to work correctly.
|
|
46
|
+
*
|
|
47
|
+
* Features:
|
|
48
|
+
* - Handles all form context requirements internally
|
|
49
|
+
* - Supports various input types (text, email, password, etc.)
|
|
50
|
+
* - Includes validation support through react-hook-form
|
|
51
|
+
* - Schema-safe for dynamic rendering via PXEngineRenderer
|
|
52
|
+
*/
|
|
53
|
+
export const FormInputAtom: React.FC<FormInputAtomProps> = ({
|
|
54
|
+
name,
|
|
55
|
+
label,
|
|
56
|
+
placeholder,
|
|
57
|
+
description,
|
|
58
|
+
defaultValue = "",
|
|
59
|
+
required = false,
|
|
60
|
+
inputType = "text",
|
|
61
|
+
className,
|
|
62
|
+
id,
|
|
63
|
+
}) => {
|
|
64
|
+
// Create a local form context for this field
|
|
65
|
+
const form = useForm({
|
|
66
|
+
defaultValues: {
|
|
67
|
+
[name]: defaultValue,
|
|
68
|
+
},
|
|
69
|
+
});
|
|
70
|
+
|
|
71
|
+
return (
|
|
72
|
+
<Form {...form}>
|
|
73
|
+
<FormField
|
|
74
|
+
control={form.control}
|
|
75
|
+
name={name}
|
|
76
|
+
rules={{
|
|
77
|
+
required: required ? `${label || name} is required` : undefined,
|
|
78
|
+
}}
|
|
79
|
+
render={({ field }) => (
|
|
80
|
+
<FormItem className={cn("w-full", className)}>
|
|
81
|
+
{label && <FormLabel>{label}</FormLabel>}
|
|
82
|
+
<FormControl>
|
|
83
|
+
<Input
|
|
84
|
+
type={inputType}
|
|
85
|
+
placeholder={placeholder}
|
|
86
|
+
id={id || `form-input-${name}`}
|
|
87
|
+
{...field}
|
|
88
|
+
/>
|
|
89
|
+
</FormControl>
|
|
90
|
+
{description && <FormDescription>{description}</FormDescription>}
|
|
91
|
+
<FormMessage />
|
|
92
|
+
</FormItem>
|
|
93
|
+
)}
|
|
94
|
+
/>
|
|
95
|
+
</Form>
|
|
96
|
+
);
|
|
97
|
+
};
|
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
import React from "react";
|
|
2
|
+
import {
|
|
3
|
+
Form,
|
|
4
|
+
FormField,
|
|
5
|
+
FormItem,
|
|
6
|
+
FormLabel,
|
|
7
|
+
FormControl,
|
|
8
|
+
FormDescription,
|
|
9
|
+
FormMessage,
|
|
10
|
+
} from "@/components/ui/form";
|
|
11
|
+
import {
|
|
12
|
+
Select,
|
|
13
|
+
SelectContent,
|
|
14
|
+
SelectItem,
|
|
15
|
+
SelectTrigger,
|
|
16
|
+
SelectValue,
|
|
17
|
+
} from "@/components/ui/select";
|
|
18
|
+
import { useForm } from "react-hook-form";
|
|
19
|
+
import { cn } from "@/lib/utils";
|
|
20
|
+
|
|
21
|
+
export interface SelectOption {
|
|
22
|
+
value: string;
|
|
23
|
+
label: string;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
export interface FormSelectAtomType {
|
|
27
|
+
type: "FormSelect";
|
|
28
|
+
name: string;
|
|
29
|
+
label?: string;
|
|
30
|
+
placeholder?: string;
|
|
31
|
+
description?: string;
|
|
32
|
+
defaultValue?: string;
|
|
33
|
+
required?: boolean;
|
|
34
|
+
options: SelectOption[];
|
|
35
|
+
className?: string;
|
|
36
|
+
id?: string;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
interface FormSelectAtomProps extends Omit<FormSelectAtomType, "type"> {
|
|
40
|
+
renderComponent?: any;
|
|
41
|
+
children?: any;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
/**
|
|
45
|
+
* FormSelectAtom
|
|
46
|
+
*
|
|
47
|
+
* Self-contained form select component that properly wraps FormField, FormItem, FormLabel, FormControl, and Select.
|
|
48
|
+
* This component provides the necessary React Context for both form and select components to work correctly.
|
|
49
|
+
*
|
|
50
|
+
* Features:
|
|
51
|
+
* - Handles all form and select context requirements internally
|
|
52
|
+
* - Supports dynamic options list
|
|
53
|
+
* - Includes validation support through react-hook-form
|
|
54
|
+
* - Schema-safe for dynamic rendering via PXEngineRenderer
|
|
55
|
+
*/
|
|
56
|
+
export const FormSelectAtom: React.FC<FormSelectAtomProps> = ({
|
|
57
|
+
name,
|
|
58
|
+
label,
|
|
59
|
+
placeholder = "Select an option",
|
|
60
|
+
description,
|
|
61
|
+
defaultValue = "",
|
|
62
|
+
required = false,
|
|
63
|
+
options = [],
|
|
64
|
+
className,
|
|
65
|
+
id,
|
|
66
|
+
}) => {
|
|
67
|
+
// Create a local form context for this field
|
|
68
|
+
const form = useForm({
|
|
69
|
+
defaultValues: {
|
|
70
|
+
[name]: defaultValue,
|
|
71
|
+
},
|
|
72
|
+
});
|
|
73
|
+
|
|
74
|
+
return (
|
|
75
|
+
<Form {...form}>
|
|
76
|
+
<FormField
|
|
77
|
+
control={form.control}
|
|
78
|
+
name={name}
|
|
79
|
+
rules={{
|
|
80
|
+
required: required ? `${label || name} is required` : undefined,
|
|
81
|
+
}}
|
|
82
|
+
render={({ field }) => (
|
|
83
|
+
<FormItem className={cn("w-full", className)}>
|
|
84
|
+
{label && <FormLabel>{label}</FormLabel>}
|
|
85
|
+
<Select onValueChange={field.onChange} defaultValue={field.value}>
|
|
86
|
+
<FormControl>
|
|
87
|
+
<SelectTrigger id={id || `form-select-${name}`}>
|
|
88
|
+
<SelectValue placeholder={placeholder} />
|
|
89
|
+
</SelectTrigger>
|
|
90
|
+
</FormControl>
|
|
91
|
+
<SelectContent>
|
|
92
|
+
{options.map((option) => (
|
|
93
|
+
<SelectItem key={option.value} value={option.value}>
|
|
94
|
+
{option.label}
|
|
95
|
+
</SelectItem>
|
|
96
|
+
))}
|
|
97
|
+
</SelectContent>
|
|
98
|
+
</Select>
|
|
99
|
+
{description && <FormDescription>{description}</FormDescription>}
|
|
100
|
+
<FormMessage />
|
|
101
|
+
</FormItem>
|
|
102
|
+
)}
|
|
103
|
+
/>
|
|
104
|
+
</Form>
|
|
105
|
+
);
|
|
106
|
+
};
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
import React from "react";
|
|
2
|
+
import {
|
|
3
|
+
Form,
|
|
4
|
+
FormField,
|
|
5
|
+
FormItem,
|
|
6
|
+
FormLabel,
|
|
7
|
+
FormControl,
|
|
8
|
+
FormDescription,
|
|
9
|
+
FormMessage,
|
|
10
|
+
} from "@/components/ui/form";
|
|
11
|
+
import { Textarea } from "@/components/ui/textarea";
|
|
12
|
+
import { useForm } from "react-hook-form";
|
|
13
|
+
import { cn } from "@/lib/utils";
|
|
14
|
+
|
|
15
|
+
export interface FormTextareaAtomType {
|
|
16
|
+
type: "FormTextarea";
|
|
17
|
+
name: string;
|
|
18
|
+
label?: string;
|
|
19
|
+
placeholder?: string;
|
|
20
|
+
description?: string;
|
|
21
|
+
defaultValue?: string;
|
|
22
|
+
required?: boolean;
|
|
23
|
+
rows?: number;
|
|
24
|
+
className?: string;
|
|
25
|
+
id?: string;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
interface FormTextareaAtomProps extends Omit<FormTextareaAtomType, "type"> {
|
|
29
|
+
renderComponent?: any;
|
|
30
|
+
children?: any;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
/**
|
|
34
|
+
* FormTextareaAtom
|
|
35
|
+
*
|
|
36
|
+
* Self-contained form textarea component that properly wraps FormField, FormItem, FormLabel, and FormControl.
|
|
37
|
+
* This component provides the necessary React Context for form components to work correctly.
|
|
38
|
+
*
|
|
39
|
+
* Features:
|
|
40
|
+
* - Handles all form context requirements internally
|
|
41
|
+
* - Supports configurable rows
|
|
42
|
+
* - Includes validation support through react-hook-form
|
|
43
|
+
* - Schema-safe for dynamic rendering via PXEngineRenderer
|
|
44
|
+
*/
|
|
45
|
+
export const FormTextareaAtom: React.FC<FormTextareaAtomProps> = ({
|
|
46
|
+
name,
|
|
47
|
+
label,
|
|
48
|
+
placeholder,
|
|
49
|
+
description,
|
|
50
|
+
defaultValue = "",
|
|
51
|
+
required = false,
|
|
52
|
+
rows = 3,
|
|
53
|
+
className,
|
|
54
|
+
id,
|
|
55
|
+
}) => {
|
|
56
|
+
// Create a local form context for this field
|
|
57
|
+
const form = useForm({
|
|
58
|
+
defaultValues: {
|
|
59
|
+
[name]: defaultValue,
|
|
60
|
+
},
|
|
61
|
+
});
|
|
62
|
+
|
|
63
|
+
return (
|
|
64
|
+
<Form {...form}>
|
|
65
|
+
<FormField
|
|
66
|
+
control={form.control}
|
|
67
|
+
name={name}
|
|
68
|
+
rules={{
|
|
69
|
+
required: required ? `${label || name} is required` : undefined,
|
|
70
|
+
}}
|
|
71
|
+
render={({ field }) => (
|
|
72
|
+
<FormItem className={cn("w-full", className)}>
|
|
73
|
+
{label && <FormLabel>{label}</FormLabel>}
|
|
74
|
+
<FormControl>
|
|
75
|
+
<Textarea
|
|
76
|
+
placeholder={placeholder}
|
|
77
|
+
rows={rows}
|
|
78
|
+
id={id || `form-textarea-${name}`}
|
|
79
|
+
{...field}
|
|
80
|
+
/>
|
|
81
|
+
</FormControl>
|
|
82
|
+
{description && <FormDescription>{description}</FormDescription>}
|
|
83
|
+
<FormMessage />
|
|
84
|
+
</FormItem>
|
|
85
|
+
)}
|
|
86
|
+
/>
|
|
87
|
+
</Form>
|
|
88
|
+
);
|
|
89
|
+
};
|
package/src/atoms/LayoutAtom.tsx
CHANGED
|
@@ -3,7 +3,7 @@ import { LayoutAtomType, UIComponent } from "../types/schema";
|
|
|
3
3
|
import { cn } from "@/lib/utils";
|
|
4
4
|
|
|
5
5
|
interface Props extends LayoutAtomType {
|
|
6
|
-
renderComponent: (component: UIComponent) => React.ReactNode;
|
|
6
|
+
renderComponent: (component: UIComponent, index?: number) => React.ReactNode;
|
|
7
7
|
}
|
|
8
8
|
|
|
9
9
|
/**
|
|
@@ -35,8 +35,10 @@ export const LayoutAtom: React.FC<Props> = ({
|
|
|
35
35
|
|
|
36
36
|
return (
|
|
37
37
|
<div className={classes}>
|
|
38
|
-
{children.map((child) => (
|
|
39
|
-
<React.Fragment key={child.id
|
|
38
|
+
{children.map((child, index) => (
|
|
39
|
+
<React.Fragment key={child.id || `layout-item-${index}`}>
|
|
40
|
+
{renderComponent(child, index)}
|
|
41
|
+
</React.Fragment>
|
|
40
42
|
))}
|
|
41
43
|
</div>
|
|
42
44
|
);
|
package/src/atoms/index.ts
CHANGED
|
@@ -26,3 +26,7 @@ export * from "./SpinnerAtom";
|
|
|
26
26
|
export * from "./CalendarAtom";
|
|
27
27
|
export * from "./PaginationAtom";
|
|
28
28
|
export * from "./CommandAtom";
|
|
29
|
+
// Form Atoms - self-contained with context wrappers
|
|
30
|
+
export * from "./FormInputAtom";
|
|
31
|
+
export * from "./FormSelectAtom";
|
|
32
|
+
export * from "./FormTextareaAtom";
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
// Auto-generated index file for UI components
|
|
2
|
+
export * from "./accordion";
|
|
3
|
+
export * from "./alert-dialog";
|
|
4
|
+
export * from "./alert";
|
|
5
|
+
export * from "./aspect-ratio";
|
|
6
|
+
export * from "./avatar";
|
|
7
|
+
export * from "./badge";
|
|
8
|
+
export * from "./breadcrumb";
|
|
9
|
+
export * from "./button-group";
|
|
10
|
+
export * from "./button";
|
|
11
|
+
export * from "./calendar";
|
|
12
|
+
export * from "./card";
|
|
13
|
+
export * from "./carousel";
|
|
14
|
+
export * from "./chart";
|
|
15
|
+
export * from "./checkbox";
|
|
16
|
+
export * from "./collapsible";
|
|
17
|
+
export * from "./command";
|
|
18
|
+
export * from "./context-menu";
|
|
19
|
+
export * from "./dialog";
|
|
20
|
+
export * from "./drawer";
|
|
21
|
+
export * from "./dropdown-menu";
|
|
22
|
+
export * from "./empty";
|
|
23
|
+
export * from "./field";
|
|
24
|
+
export * from "./form";
|
|
25
|
+
export * from "./hover-card";
|
|
26
|
+
export * from "./input-group";
|
|
27
|
+
export * from "./input-otp";
|
|
28
|
+
export * from "./input";
|
|
29
|
+
export * from "./item";
|
|
30
|
+
export * from "./kbd";
|
|
31
|
+
export * from "./label";
|
|
32
|
+
export * from "./menubar";
|
|
33
|
+
export * from "./navigation-menu";
|
|
34
|
+
export * from "./pagination";
|
|
35
|
+
export * from "./popover";
|
|
36
|
+
export * from "./progress";
|
|
37
|
+
export * from "./radio-group";
|
|
38
|
+
export * from "./resizable";
|
|
39
|
+
export * from "./scroll-area";
|
|
40
|
+
export * from "./select";
|
|
41
|
+
export * from "./separator";
|
|
42
|
+
export * from "./sheet";
|
|
43
|
+
export * from "./sidebar";
|
|
44
|
+
export * from "./skeleton";
|
|
45
|
+
export * from "./slider";
|
|
46
|
+
export * from "./sonner";
|
|
47
|
+
export * from "./spinner";
|
|
48
|
+
export * from "./switch";
|
|
49
|
+
export * from "./table";
|
|
50
|
+
export * from "./tabs";
|
|
51
|
+
export * from "./textarea";
|
|
52
|
+
export * from "./toggle-group";
|
|
53
|
+
export * from "./toggle";
|
|
54
|
+
export * from "./tooltip";
|