pxengine 0.1.2 → 0.1.4

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.
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@pxengine/ui",
3
3
  "version": "1.0.0",
4
- "lastUpdated": "2026-01-28T06:18:24.958Z",
4
+ "lastUpdated": "2026-01-28T09:16:14.091Z",
5
5
  "components": {
6
6
  "Accordion": {
7
7
  "name": "Accordion",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "pxengine",
3
- "version": "0.1.2",
3
+ "version": "0.1.4",
4
4
  "type": "module",
5
5
  "description": "Shadcn-based UI component library for agent-driven interfaces",
6
6
  "main": "./dist/index.cjs",
@@ -12,7 +12,7 @@
12
12
  "src"
13
13
  ],
14
14
  "scripts": {
15
- "build": "tsup src/index.ts --format cjs,esm --dts --clean && npm run generate-metadata",
15
+ "build": "tsup && npm run generate-metadata",
16
16
  "generate-metadata": "tsx scripts/generate-metadata.ts",
17
17
  "dev": "tsup src/index.ts --format cjs,esm --watch --dts",
18
18
  "lint": "eslint src --ext .ts,.tsx",
@@ -1,272 +1,94 @@
1
1
  import React from "react";
2
- import { UIComponent, UISchema, UIAtom, UIMolecule } from "../types/schema";
2
+ import { UIComponent, UISchema } from "../types/schema";
3
3
  import * as Atoms from "../atoms";
4
- import * as Molecules from "../molecules/index"; // Explicit index to help resolution
5
-
6
- // NOTE: This renderer will be used by the frontend to interpret JSON schemas
7
- // generated by the AI agent via the MCP server.
4
+ import * as Molecules from "../molecules/index";
8
5
 
6
+ /**
7
+ * PXEngineRenderer
8
+ *
9
+ * Handles both the full schema { version, root } and individual components.
10
+ * Dynamically resolves components from the Atoms/Molecules registry.
11
+ */
9
12
  interface PXEngineRendererProps {
10
13
  schema: UISchema | UIComponent;
11
14
  onAction?: (action: string, payload?: any) => void;
12
15
  }
13
16
 
14
- /**
15
- * PXEngineRenderer
16
- *
17
- * The core engine of the @pxengine-ui library.
18
- * Recursively renders Atoms and Molecules based on the provided JSON schema.
19
- */
20
17
  export const PXEngineRenderer: React.FC<PXEngineRendererProps> = ({
21
18
  schema,
22
19
  onAction,
23
20
  }) => {
24
- // Determine if it's a full schema or just a component
25
- const root = "root" in schema ? schema.root : schema;
21
+ if (!schema) return null;
26
22
 
27
- /**
28
- * Render Atomic components (UI Primitives)
29
- */
30
- const renderAtom = (
31
- atom: UIAtom,
32
- renderComponent: (c: UIComponent) => React.ReactNode,
33
- ): React.ReactNode => {
34
- const { type, id } = atom;
23
+ // Extract root if it's a full UISchema
24
+ const root = (schema as any).root || (schema as UIComponent);
35
25
 
36
- switch (type) {
37
- case "layout":
38
- return (
39
- <Atoms.LayoutAtom
40
- key={id}
41
- {...(atom as any)}
42
- renderComponent={renderComponent}
43
- />
44
- );
45
- case "card":
46
- return (
47
- <Atoms.CardAtom
48
- key={id}
49
- {...(atom as any)}
50
- renderComponent={renderComponent}
51
- />
52
- );
53
- case "text":
54
- return <Atoms.TextAtom key={id} {...(atom as any)} />;
55
- case "button":
56
- return (
57
- <Atoms.ButtonAtom key={id} {...(atom as any)} onAction={onAction} />
58
- );
59
- case "input":
60
- return <Atoms.InputAtom key={id} {...(atom as any)} />;
61
- case "badge":
62
- return <Atoms.BadgeAtom key={id} {...(atom as any)} />;
63
- case "avatar":
64
- return <Atoms.AvatarAtom key={id} {...(atom as any)} />;
65
- case "progress":
66
- return <Atoms.ProgressAtom key={id} {...(atom as any)} />;
67
- case "skeleton":
68
- return <Atoms.SkeletonAtom key={id} {...(atom as any)} />;
69
- case "alert":
70
- return <Atoms.AlertAtom key={id} {...(atom as any)} />;
71
- case "separator":
72
- return <Atoms.SeparatorAtom key={id} {...(atom as any)} />;
73
- case "table":
74
- return <Atoms.TableAtom key={id} {...(atom as any)} />;
75
- case "tabs":
76
- return (
77
- <Atoms.TabsAtom
78
- key={id}
79
- {...(atom as any)}
80
- renderComponent={renderComponent}
81
- />
82
- );
83
- case "accordion":
84
- return (
85
- <Atoms.AccordionAtom
86
- key={id}
87
- {...(atom as any)}
88
- renderComponent={renderComponent}
89
- />
90
- );
91
- case "scroll-area":
92
- return (
93
- <Atoms.ScrollAreaAtom
94
- key={id}
95
- {...(atom as any)}
96
- renderComponent={renderComponent}
97
- />
98
- );
99
- case "carousel":
100
- return (
101
- <Atoms.CarouselAtom
102
- key={id}
103
- {...(atom as any)}
104
- renderComponent={renderComponent}
105
- />
106
- );
107
- case "aspect-ratio":
108
- return (
109
- <Atoms.AspectRatioAtom
110
- key={id}
111
- {...(atom as any)}
112
- renderComponent={renderComponent}
113
- />
114
- );
115
- case "collapsible":
116
- return (
117
- <Atoms.CollapsibleAtom
118
- key={id}
119
- {...(atom as any)}
120
- renderComponent={renderComponent}
121
- />
122
- );
123
- case "tooltip":
124
- return (
125
- <Atoms.TooltipAtom
126
- key={id}
127
- {...(atom as any)}
128
- renderComponent={renderComponent}
129
- />
130
- );
131
- case "popover":
132
- return (
133
- <Atoms.PopoverAtom
134
- key={id}
135
- {...(atom as any)}
136
- renderComponent={renderComponent}
137
- />
138
- );
139
- case "dialog":
140
- return (
141
- <Atoms.DialogAtom
142
- key={id}
143
- {...(atom as any)}
144
- renderComponent={renderComponent}
145
- />
146
- );
147
- case "sheet":
148
- return (
149
- <Atoms.SheetAtom
150
- key={id}
151
- {...(atom as any)}
152
- renderComponent={renderComponent}
153
- />
154
- );
155
- case "alert-dialog":
156
- return (
157
- <Atoms.AlertDialogAtom
158
- key={id}
159
- {...(atom as any)}
160
- onAction={onAction}
161
- renderComponent={renderComponent}
162
- />
163
- );
164
- case "breadcrumb":
165
- return <Atoms.BreadcrumbAtom key={id} {...(atom as any)} />;
166
- case "spinner":
167
- return <Atoms.SpinnerAtom key={id} {...(atom as any)} />;
168
- case "calendar":
169
- return <Atoms.CalendarAtom key={id} {...(atom as any)} />;
170
- case "pagination":
171
- return <Atoms.PaginationAtom key={id} {...(atom as any)} />;
172
- case "command":
173
- return <Atoms.CommandAtom key={id} {...(atom as any)} />;
174
- default:
175
- return null;
26
+ const renderRecursive = (
27
+ component: UIComponent | string | any,
28
+ ): React.ReactNode => {
29
+ // 1. Handle text nodes (string or number)
30
+ if (typeof component === "string" || typeof component === "number") {
31
+ return component;
176
32
  }
177
- };
178
33
 
179
- /**
180
- * Render Molecule components (Domain-specific / Complex)
181
- */
182
- const renderMolecule = (molecule: UIMolecule): React.ReactNode => {
183
- const { type, id } = molecule;
34
+ if (!component) return null;
184
35
 
185
- switch (type) {
186
- case "campaign-seed":
187
- return (
188
- <Molecules.CampaignSeedCard
189
- key={id}
190
- {...(molecule as any)}
191
- onProceed={() =>
192
- onAction?.((molecule as any).proceedAction || "proceed")
193
- }
194
- />
195
- );
196
- case "search-spec":
197
- return (
198
- <Molecules.SearchSpecCard
199
- key={id}
200
- {...(molecule as any)}
201
- onProceed={() =>
202
- onAction?.((molecule as any).proceedAction || "proceed")
203
- }
204
- />
205
- );
206
- case "mcq":
207
- return (
208
- <Molecules.MCQCard
209
- key={id}
210
- {...(molecule as any)}
211
- onProceed={() =>
212
- onAction?.((molecule as any).proceedAction || "proceed")
213
- }
214
- />
215
- );
216
- case "action-button":
217
- return (
218
- <Molecules.ActionButton
219
- key={id}
220
- {...(molecule as any)}
221
- onProceed={() => onAction?.((molecule as any).action || "proceed")}
222
- />
223
- );
224
- default:
225
- return null;
226
- }
227
- };
36
+ const { type, name, props = {}, children = [], id } = component;
37
+
38
+ // Determine the component name to search for
39
+ const componentName = name || type;
40
+ if (!componentName) return null;
228
41
 
229
- const renderComponent = (component: UIComponent): React.ReactNode => {
230
- const { type } = component;
42
+ // Normalize name to PascalCase and check for "Atom" suffix
43
+ const normalizedName =
44
+ componentName.charAt(0).toUpperCase() + componentName.slice(1);
45
+ const atomName = normalizedName.endsWith("Atom")
46
+ ? normalizedName
47
+ : `${normalizedName}Atom`;
231
48
 
232
- // Route based on defined Atom types
233
- const isAtom = [
234
- "layout",
235
- "card",
236
- "text",
237
- "button",
238
- "input",
239
- "badge",
240
- "avatar",
241
- "progress",
242
- "skeleton",
243
- "alert",
244
- "separator",
245
- "table",
246
- "tabs",
247
- "accordion",
248
- "scroll-area",
249
- "carousel",
250
- "aspect-ratio",
251
- "collapsible",
252
- "tooltip",
253
- "popover",
254
- "dialog",
255
- "sheet",
256
- "alert-dialog",
257
- "breadcrumb",
258
- "spinner",
259
- "calendar",
260
- "pagination",
261
- "command",
262
- ].includes(type);
49
+ // 2. Resolve Component from library registry
50
+ const TargetComponent =
51
+ (Atoms as any)[atomName] ||
52
+ (Atoms as any)[normalizedName] ||
53
+ (Atoms as any)[componentName] ||
54
+ (Molecules as any)[normalizedName] ||
55
+ (Molecules as any)[componentName];
263
56
 
264
- if (isAtom) {
265
- return renderAtom(component as UIAtom, renderComponent);
57
+ if (!TargetComponent) {
58
+ console.warn(`[PXEngineRenderer] Component not found: ${componentName}`);
59
+ return (
60
+ <div
61
+ key={id}
62
+ className="p-2 border border-dashed border-red-500/50 text-red-500 text-[10px] rounded"
63
+ >
64
+ Unknown: {componentName}
65
+ </div>
66
+ );
266
67
  }
267
68
 
268
- return renderMolecule(component as UIMolecule);
69
+ // 3. Render Component
70
+ // We pass 'renderComponent' for components that handle their own child rendering (like Layout/Card)
71
+ // We also pass children as props for standard React children behavior
72
+ return (
73
+ <TargetComponent
74
+ key={id || Math.random().toString(36).substr(2, 9)}
75
+ {...props}
76
+ onAction={onAction}
77
+ renderComponent={renderRecursive}
78
+ children={Array.isArray(children) ? children : undefined}
79
+ >
80
+ {Array.isArray(children)
81
+ ? children.map((child, idx) => (
82
+ <React.Fragment key={idx}>
83
+ {renderRecursive(child)}
84
+ </React.Fragment>
85
+ ))
86
+ : typeof children === "string"
87
+ ? children
88
+ : null}
89
+ </TargetComponent>
90
+ );
269
91
  };
270
92
 
271
- return <>{renderComponent(root)}</>;
93
+ return <div className="px-engine-root">{renderRecursive(root)}</div>;
272
94
  };